爱丽丝医生和云原生鲍勃,我最喜欢的机器学习用户
爱丽丝和鲍勃都很棒,这也很好,因为我无论走到哪里都会遇到他们!他们热情、勤奋,尽最大努力构建伟大的机器学习解决方案。不幸的是,很多事情阻碍了他们,让他们慢了下来。
我的工作是倾听并帮助所有的 Alices 和 bob:)在这篇文章中,我将尝试总结他们面临的挑战,他们如何开始用 AWS 服务解决这些问题,特别是 Amazon SageMaker。
Tell me about your first GPU cluster.
信不信由你,我保证你在下面读到的一切都是 100%基于无数的客户互动。
爱丽丝医生
爱丽丝拥有博士学位,在一家大型公共研究实验室工作。她是一名训练有素的数据科学家,在数学和统计学方面有很强的背景。
她把时间花在大型科学项目上(生命科学、物理学等)。),涉及庞大的数据集(几 TB,往往更多)。她可以用像 Matlab、R 和 Python 这样的高级语言编写数据分析代码:也许它看起来不怎么样,但确实有用。
Alice 通常不太了解 IT 和基础设施,老实说,她根本不关心这些话题。她的重点是推进她的研究,发表论文,等等:其他一切都是“工具”。
对于日常工作,她可以依靠自己强大(但昂贵)的桌面工作站:高端英特尔 CPU、64GB 内存、4TB 本地存储和几个中端英伟达 GPU。她认为自己很幸运有一个这样的人(并不是她的所有同事都这样),她很高兴自己可以独自工作“”。不过,如果她想保持合理的训练时间,她只能用一小部分数据集进行实验。
她每天晚上和每个周末都运行长时间的工作负载,希望它们不会崩溃…或者没有人会关掉她办公室的电源。当这种情况发生时,她叹了口气,然后重新开始工作。“浪费时间和精力又有什么用呢?”她想,但她对此无能为力。
她试图自己维护她的机器的软件配置,因为它不太了解她使用的深奥工具。尽管如此,她还是希望有人能为她这么做:NVIDIA 驱动程序、Tensorflow 依赖项等等让人感到相当困惑。当出现问题时,她会浪费宝贵的时间来修理“ IT 设备,这令人沮丧。当爱丽丝想要运行大型实验时,她必须使用托管在计算中心的远程服务器:一群非常强大的多 GPU 服务器,连接到 1pb 的 NAS 存储。当然,她必须与其他研究人员共享这些服务器。每周,团队领导都要会面并尝试对项目和工作量进行优先排序:这从来都不容易,决策往往需要上报给实验室主管。宝贵的时间被浪费了,有时实验无法在会议提交截止日期前完成。主管承诺明年的预算将考虑更多的服务器,但即使它们获得批准,采购和部署它们也需要几个月的时间。为了帮助安排工作量,Alice 雇佣了一名暑期实习生来编写一个简单的内部网门户,研究人员可以在那里手动预订服务器。它有点工作,但有时她的同事忘记发布服务器…或者他们不愿意发布服务器,因为他们知道他们必须等待获得另一个服务器。爱丽丝认为一定有更好的方法,但解决这个问题不是她的工作。不管怎样,她尽量用她能得到的东西来凑合。她不禁想到,如果她的实验不受容量限制,她会取得更大的进步。
最后但并非最不重要的一点是,Alice 受邀与位于另一个大陆的世界级实验室合作。在过去的一个月里,她一直试图找出如何与他们共享数据和基础设施。连接是复杂的,鉴于数据集的规模,数据传输几乎是不可能的。再次,“ IT 材料”阻碍了她的研究,她开始认为必须有一种更快更简单的方法来完成所有这些…也许云计算的东西可以有所帮助?
塞格马克土地上的爱丽丝医生
经过一些个人研究和数周的内部讨论,Alice 已经说服实验室主任让她试验 AWS,特别是那个看起来很有趣的 Amazon SageMaker 服务。
在短短几个小时内,她阅读了在线文档,快速创建了一个便宜的笔记本实例,并开始运行一些样本笔记本,以熟悉这项服务及其典型的工作流程。尽管她对 AWS 或 Python 了解不多,但她相信 SageMaker SDK 正是她所需要的,她很快就会上手。她甚至找到了一个关于如何为她心爱的 R 语言[创建定制环境的样本笔记本!
在 IT 的一点帮助下,爱丽丝上传了几兆字节的真实生活数据到](https://github.com/awslabs/amazon-sagemaker-examples/tree/master/advanced_functionality/r_bring_your_own)亚马逊 S3 ,以便在亚马逊 SageMaker 上复制她的桌面环境。在更多的阅读之后,她了解到只需要几行代码就可以在托管实例上训练她的模型,并且她将只为她实际使用的东西付费。她甚至可以根据需要在任意多的 p3.16xlarge 实例上训练她的模型:每一个都配备了八个 NVIDIA V100 GPUs!这与计算中心的大型服务器的配置相同。她现在可以按需创建它们:不再与其他团队争论。
得益于分布式训练和管道模式等高级功能,Alice 发现在自己的大型数据集上训练模型很容易:一切都开箱即用,伸缩自如。Alice 也很高兴看到 SageMaker 包含了一个自动模型调整模块:由于这个,她能够在仅仅几个小时的并行优化中显著提高她的模型的准确性。由于缺乏计算资源,用她以前的设置做这些是不可能的。
部署模型很简单:Alice 可以选择将模型部署到实时端点,或者运行批量预测。后者对她最有用,因为她需要偶尔预测大量数据。同样,只需要几行代码:她实际上复制粘贴了样本笔记本中的所有内容。最后但并非最不重要的一点是,跟踪她的支出很容易:AWS 控制台会告诉她花了多少钱,爱丽丝还可以设置预算警报。在与 IT 部门的同事交谈时,Alice 意识到 AWS 还有很多功能。看起来实验室可以使用名为 AWS Snowball 的服务轻松上传数百兆字节到亚马逊 S3!与已经是 AWS 客户的其他实验室和大学共享这些数据看起来并不复杂。爱丽丝期待着合作和创新的步伐加快!
短短一周左右,她对它的整个看法都变了。她说:“这个云东西实际上非常酷”。过去,AWS 阻碍了我的发展,但现在,它确实帮助我提供了比以前更好、更快、更便宜的结果。
云原生 Bob
鲍勃在一家大公司工作。他是一名后端软件工程师,从记事起就一直与数据打交道:SQL、NoSQL、Hadoop、Spark 以及现在的机器学习。使用现成的库(主要是 scikit-learn,还有一点 Tensorflow),Bob 和他的队友处理企业数据来训练数百个 ML 模型:线性回归、分类、分段等。繁重的工作(ETL、清理、特性工程)正在运行一个大的 Spark 集群。Bob 的公司使用 AWS 已经五年多了。所有开发、QA 和生产基础设施都托管在那里,他们是 DevOps 和云原生技术的忠实粉丝。最初,他们把一切都建立在亚马逊 EC2 上,因为他们觉得拥有完全控制权很重要。两年前,他们将 Spark 集群迁移到了亚马逊 EMR ,还决定使用 Docker containers 实现标准化生产:他们现在 100%的工作负载都部署到了一个大型的亚马逊 EKS 集群,因为 Kubernetes 是如此之酷,也因为从笔记本电脑到生产的无缝开发体验。他们根据建立了所有的 CI/CD 工具链,并使用 Terraform 实现了一切自动化。使用自动缩放和点实例优化成本。这些人真的很了解他们的东西,他们被邀请在下一次 AWS 峰会上展示他们的架构。当然了。
当然,他们的 ML 工作负载也运行在 EKS 集群上(大部分是在 CPU 实例上,也有一些 GPU)。Bob 为训练和预测维护定制的容器:库、依赖项等。这需要一点时间,但他喜欢这样做。他只是希望没有人会要求他也做 Pytorch 和 Apache MXNet。Bob 听说过深度学习 AMI 和深度学习容器。检查那些东西在他的任务清单上,但是他现在没有时间。
最初,Bob 希望让每个数据科学家使用 Terraform 模板创建他们自己的按需集群,但他担心成本难以管理。此外,创建一个集群需要 15-20 分钟,团队肯定会抱怨这一点。相反,Bob 建立了一个大型的共享培训集群:用户可以在几秒钟内开始他们的分布式工作,Bob 管理单个集群更简单。已经设置了自动扩展,但是仍然需要容量规划来找到预留、现场和按需实例的正确组合。
Bob 每周与团队开会,以确保他们有足够的实例…当他们需要额外的容量时,他们还会让他随时待命。Bob 尝试在晚上和周末集群不太忙的时候自动减少容量,但他很确定他们的花费太多了。哦好吧。
一旦模型经过训练和验证,Bob 会将它们推送到 CI/CD,它们会自动部署到生产集群。绿/蓝部署、服务发现、自动扩展、将日志推送到弹性搜索集群等。:整个九码。Bob 对他构建到系统中的自动化水平感到非常自豪,这是理所当然的。
云土著鲍勃在 SageMaker 土地
鲍勃已经在 SageMaker 上观看了一个 AWS 视频。他喜欢基于 Docker 的训练和预测,并且内置框架的容器是开源的:那么就不需要维护他自己的容器了。
将培训工作负载迁移到 SageMaker 看起来很容易:Bob 可以摆脱 EKS 培训集群,让每个数据科学家完全按需进行培训。随着 Spot 实例即将推出,Bob 当然可以进一步优化培训成本。
就预测而言,Bob 会考虑将批处理作业转移到 SageMaker,但不会转移实时 API:根据公司政策,这些必须部署到 EKS。这不成问题,因为他可以重复使用相同的容器。
几个星期后,鲍勃实现了所有这些改变。数据科学团队现在从实验到培训都是完全自主的,这是他们喜欢的:容量不再是问题,每周会议也变得没有必要。此外,由于 SageMaker 提供了已训练模型的可追溯历史,Bob 也发现自动化模型再训练和重新部署更容易:以前,他必须让数据科学团队来做,这个过程对他来说太不确定了。
像分布式训练、管道模式和自动模型调整这样的高级功能也相当不错。数据科学团队很快就采用了它们,这为他们节省了大量时间。此外,他们不再需要维护自己编写的代码来实现类似的东西。只有一个问题:现在,Bob 必须更新他的 AWS 峰会幻灯片,以说明 SageMaker 用例。也许当地的福音传道者可以帮助他?;)
一如既往的感谢您的阅读。很乐意在这里或者在 Twitter 上回答问题(DMs 开放)。也可以随意分享你自己的趣闻轶事!
我举起我的号角,向世界各地的人们致敬。继续建,我的 M(eta)L 兄弟姐妹:)
神秘博士 Kaggle 数据集和 NLTK 概述
你好,我写这篇短文的目的是:
- 展示一个我在过去几周构建的数据集
- 获得 nltk 的一些特性的概述
《神秘博士》是一部英国电视节目,是一部科幻片,由 BBC 制作于 1963 年,节目讲述了一个外星人(人形)博士的故事,他乘坐他的时间机器/宇宙飞船 Tardis(警察岗亭)在宇宙中旅行。
在这次时空旅行中,博士被来自地球的同伴跟随,因为他对地球有一些偏好(那很方便不是吗)。医生非常聪明、有趣,但角色的两个主要特征(来自他的外星种族时间领主)是:
- 他是不朽的
- 当他死的时候,他会以一种新的人类形式复活(对契约的结束非常有用)。每一次再生都保留着先前形态的记忆,但他有了新的面貌和新的举止。但是这种再生过程在迭代次数上受到限制
就表演而言,可以定义两个阶段(这是我的术语,所以请神秘博士的粉丝不要消灭我):
- 从 1963 年到 1989 年的经典区域
- 从 2005 年到现在的现代区域
就我而言,我在 2010 年左右发现了神秘博士,所以我更喜欢现代区域,我不太熟悉经典区域,但我喜欢现代区域,因为他们重新导入了经典区域的知识,并进行了更新(例如重新设计了博士的敌人)。
不管怎么说,这部剧从参照物到演员都是英国流行文化的一颗钻石,如果你喜欢科幻,绝对值得一看。
所以现在让我们深入研究一下这个项目的数据。
所以说实话,这个数据集受到了的启发,这个数据集聚焦于电视剧《辛普森一家》。
我从不同的网站搜集数据:
- 这几集的剧本来自网站 chakoteya ,在那里可以找到每一集的所有对话等等
- 《摩登地区》每集的收视率来自 IMDB
- 关于这一集的信息来自指导的《神秘博士》,包含关于这一集的细节、演员或工作人员的分布。
这些数据集给出了节目的不同细节,可用于确定节目中可能影响 IMDB 评分的某些特定事件的影响。
例如,下图显示了现代地区不同季节的等级。
似乎所有赛季的收视率都接近 8,但最后一季似乎不太受公众欢迎,我认为这可能是两个原因:
- 2005 年重新推出 sho 的历史节目主持人史蒂文·莫法特离开了制作,所以新的基调不适合观众
- 这位新医生是一位女性,这是第一次在节目中出现,在宣布之后,这位女演员在互联网上引起了轩然大波/负面评论,因为 IMDB 上的评级是基于用户的,负面评论会影响评级(被仇恨者所偏见)
现在让我们看看这部剧的演员阵容,我想看看是否有一些名字出现在这部剧的两个时代之间,而且是一个相当大的数字,在 3146 名演员中,有 1362 名演员似乎出现在两个时代,医生似乎有更多的回归演员,但这很容易与周年纪念集(角色可以在时间中旅行,哈哈)
如果我们将这种分析集中在两个时代的演员身上,我们可以看到这些演员中有很大一部分是一些非人类角色的配音演员,例如尼古拉斯·布里格斯(Nicholas Briggs)扮演的 Dalek 的配音。
让我们深入剧集的脚本,开始用 NLTK 做一些文本分析。
为了对脚本进行分析,我将使用包 NLTK ,它被定义为
“构建 Python 程序以处理人类语言数据的领先平台。它为超过 50 个语料库和词汇资源(如 WordNet)提供了易于使用的接口,以及一套用于分类、标记化、词干化、标记、解析和语义推理的文本处理库,以及工业级 NLP 库的包装器”
对于这一部分,我将遵循 datacamp 制作的 NLTK 上的教程,在开始对文本进行分析之前,对脚本进行一些处理(标记化、停用词的清理和词汇规范化)。
我的分析将分为 3 个部分:
- 获取最常用的单词和单词的索引
- 为一些特定的字符画一些文字云
- 做一些情绪分析
最常用的单词和索引
首先,在对不同的句子和单词进行标记化并对元素进行停用词过滤后,我们可以看到 10 个最流行的单词是:
猜猜哪个医生是最受欢迎的词,现在让我们调查一下医生这个词与之前和之后的词的一致性,并统计出现的次数。这是与“医生”这个词最相关的前 20 个词。
有趣的是,“the”是与医生更相关的单词的一个很好的候选词,但令人难过的是,“who”没有排在前 20 位(它排在第 34 位)。现在让我们来看看一些特定角色使用的单词。
Wordcloud
在这一部分,我将确定一系列字符中使用最多的单词(受这篇文章的启发,使用了一个单词云)
我们可以看到,医生是一个在医生的同伴口中反复出现的词。现在让我们看看这些疯狂的 Dalek 罐子说的话。
灭绝是剧中 daleks 使用最多的词之一,他们基本上想摧毁一切。
现在让我们对脚本进行一点情感分析
情绪分析器的使用
我将使用可以在 NLTK 上找到的情绪分析器,称为 Vader 情绪分析器
Vader 分析器来自 2014 年的出版物,它参考了化合价感知词典和情感推理器,你可以找到关于这个主题的一篇有趣的文章。这个开箱即用的分析器非常有用,下图是医生在第一季的一集里说的话的演变。
正如我们所看到的,在一集的不同阶段,医生会引用不同的话,但大多数时候,医生对他的讲话是中立的。在下图中,有另一个引用医生的话的情绪的图示,有一个引用的积极和消极的图。
结论
这篇文章是对我的 kaggle 数据集的介绍。通过对 NLTK 的简单了解,我对这个数据集有了一些想法,将来我一定会用它来做一些关于 NLP 的实验。如果您对数据集、应用程序等有任何意见,请随时联系我。
原载于http://the-odd-dataguy.com。
文档嵌入技术
关于这一主题的著名文献综述
单词嵌入——将单词映射到数字向量空间——近年来已被证明是自然语言处理(NLP)任务的一种非常重要的方法,使各种依赖向量表示作为输入的机器学习模型能够享受更丰富的文本输入表示。这些表示保留了单词的更多语义和句法信息,从而提高了几乎所有可以想象的 NLP 任务的性能。
这种新颖的想法本身及其巨大的影响促使研究人员考虑如何为更大的文本单元(从句子到书籍)提供更丰富的矢量表示这一好处。这一努力导致了一系列产生这些映射的新方法,对该问题提出了各种创新的解决方案,并取得了一些显著的突破。
这篇文章是我在介绍自己这个话题的时候写的(作为大熊猫项目的一部分,在那里我咨询了几年 ❤️🐼),旨在展示从业者产生文档嵌入的不同方式。
**注意:**我在这里使用单词 文档 来指代 任何单词序列 ,从句子和段落到社交媒体帖子,一直到文章、书籍和更复杂结构的文本文档(例如表格)。
Figure 1: A common example of embedding documents into a wall
在这篇文章中,我不仅会谈到直接扩展单词嵌入技术的方法(例如,以 doc2vec 扩展 word2vec 的方式),还会谈到其他值得注意的技术,这些技术有时会产生其他输出,例如在ℝⁿ.中从文档到矢量的映射
只要有可能,我还会尽量提供链接和参考资料,既指向原始论文,也指向被评审方法的代码实现。
**注:**这个题目和学习结构化文本表示的问题有些关联,但不等价(例如【刘& Lapata,2018】)。
目录
文档嵌入的应用
将文档映射到信息向量表示的能力具有广泛的应用。以下只是部分列表。
[ Le & Mikolov,2014 ]在几个文本分类和情感分析任务上展示了他们的段落向量方法的能力,而[ 戴等人,2015 ]在文档相似性任务和[ Lau & Baldwin,2016 ]在一个论坛问题复制任务和语义文本相似性(STS) SemEval 共享任务上对其进行了基准测试。
【 Kiros 等人,2015 】已经展示了他们的跳过思维向量用于语义相关度、释义检测、图像句子排序、问题类型分类和四个情感和主观性数据集。[Broere,2017]使用它们来预测词性标签和依存关系。
【陈等,2018 】展示了 BioSentVec ,他们在生物医学文本上训练的句子嵌入集,在句子对相似度任务上表现良好(官方 Python 实现)。
最后,深度语义相似性模型被各种作者用于信息检索和网页搜索排名、广告选择/相关性、上下文实体搜索和兴趣任务、问题回答、知识推理、图像字幕和机器翻译任务。
突出的方法和趋势
我最后写这一部分,已经花了很多时间思考如何组织这篇文章,如何将下面几节中涉及的各种技术归类到突出的方法中,以及在检查该领域中不同的作品如何相互关联以及它们彼此遵循的方式时会出现什么趋势。
但是,请注意,虽然文档嵌入的问题由来已久,但许多目前有影响力的解决方案还很年轻,而且这个领域最近(大约在 2014 年)在当代基于编码器-解码器的单词嵌入技术取得成功之后又出现了复兴,所以这仍然处于早期阶段。说了这么多,我希望这一部分能把下面的部分放到一个更广阔的背景中,并以一种有意义的方式框定它们。
文档嵌入方法
绘制该领域的一种可能方法是以下四种主要方法:
- 总结词语向量
这是的经典做法。单词袋对一个热门单词向量就是这样做的,你可以对它应用的各种加权方案都是这种总结单词向量的方法的变体。然而,这种方法在与最先进的单词表示一起使用时也是有效的(通常通过求平均值而不是求和),尤其是当单词嵌入考虑到这种用途而被优化时,并且可以抵抗这里介绍的任何更性感的方法。 - 主题建模
虽然这通常不是 LDA 和 PLSI 等主题建模技术的主要应用,但它们最近生成了一个文档嵌入空间来建模和解释语料库中的单词分布,其中维度可以被视为隐藏在数据中的潜在语义结构,因此在我们的上下文中很有用。在这篇文章中,我并没有真正涉及这种方法(除了对 LDA 的简单介绍),因为我认为 LDA 很好地代表了这种方法,而且这种方法也广为人知。** - 编码器-解码器模型
这是场景中最新的无监督添加,具有 doc2vec 和 skip-thought 之类的功能。虽然这种方法自 21 世纪初就已经存在,名为神经概率语言模型,但最近随着它在单词嵌入生成方面的成功应用,它获得了新的生命,当前的研究集中在如何将其应用扩展到文档嵌入。这种方法比其他方法从不断增加的大量未标记语料库中获益更多。 - 监督表示学习
这种方法的生命力归功于神经网络模型的伟大崛起(或复兴),以及它们使用各种非线性多层运算符学习输入数据的丰富表示的能力,这可以近似大范围的映射。通过简单地将旧的单词袋输入到神经网络学习中,以解决一些与监督文本相关的问题,您可以获得一个模型,其中隐藏层包含输入文本的丰富表示,这正是我们所追求的。
有几个无监督的方法不适合上述任何一组(特别是,快速思考和单词移动器的距离浮现在脑海中),但我认为大多数技术都属于这四大类别之一。
***注:*虽然人们很容易指出经典的单词袋技术缺乏订单信息,但这实际上是一种规律,而不是例外。这里回顾的大多数新方法获得的主要信息是将分布假设扩展到更大的文本单元。基于神经网络的序列模型是例外。
趋势和挑战
当从整体上考察文档嵌入技术的研究和应用时,出现了几个大的趋势,以及人们可能会发现的几个挑战。
- ***编码器-解码器优化:*研究的一个显著部分集中在优化确切的架构(例如 NN/CNN/RNN)和一些组件/超参数(例如 n-gram、投影函数、称重等)。)的无监督编码器-解码器方法来学习文档嵌入。虽然这种微调的部分目标是提高各种任务的成功指标,但在更大的语料库或更短的时间内训练模型的能力也是一个目标。
- 学习目标设计:**无监督(或自我监督)表示学习的关键在于设计一个学习目标,它利用数据中可自由获得的标签,以某种方式生成对下游任务有用的表示。对我来说,这是最令人兴奋的趋势,我认为这是对 NLP 任务影响最大的趋势,可能等同于单词嵌入技术。目前,我认为只有思维敏捷的和字移动器的距离可以作为编码器-解码器方法的替代方案。这一趋势的另一个吸引人的方面是,这里的创新可能也适用于单词嵌入的问题。
- ***基准测试:*一般来说,作为机器学习研究领域趋势的一部分,文档嵌入,也许是因为它是一个年轻的子领域,很好地证明了对大范围和大量任务的技术基准测试的研究的日益关注(参见 the GLUE leaderboard )。然而,几乎每一篇关于这一主题的论文都宣称其结果与目前的 SOTA 技术相当或更好,这还没有导致一个明确的领导者出现在这群人的前面。
- ***开源:*同样,作为更广泛趋势的一部分,易于使用的代码实现技术(通常也是实验)的火热发布实现了可重复性,并推动了学术界以外更广泛的数据科学社区的参与和对真实世界问题的使用。
- ***跨任务适用性:*虽然不是所有的无监督技术都以相同水平的全面性作为基准,但这可能更多是监督嵌入学习的情况。无论如何,依赖于文本数据中不同类型的信息的各种各样极其不同的 NLP 任务,使得这个问题成为一个突出的问题。从几个任务中联合学习嵌入是一种有趣的方式,其中有监督的方法可能解决这个挑战。
- ***标记语料库:*非常大的标记语料库的有限可用性也是未来监督方法的一个问题。这可能代表了未来几年无监督方法在监督表示学习方面的真正优势。
***注意:*如果你觉得这部分有点断章取义,我建议你在看完这篇文章中的大部分技巧后再来看一看。
经典技术
本节简要介绍了两种已建立的文档嵌入技术:单词袋和潜在狄利克雷分配*。随意跳过。*
词汇袋
该方法在[Harris,1954]中提出,将文本表示为其单词的包( multiset )(丢失语法和排序信息)。这是通过决定将形成映射所支持的词汇表的一组 n 个单词,并给词汇表中的每个单词分配一个唯一的索引来完成的。然后,每个文档由一个长度为 n 的向量表示,其中第 i 个条目包含单词 i 在文档中出现的次数。
Figure 2: A bag-of-words representation of an example sentence
比如那句“狗咬狗的世界,宝贝!”(在清除标点符号之后)可以由 550 长度的向量 v 表示(假设选择了 550 个单词的词汇),除了以下条目之外,该向量在任何地方都是零:
- V₇₆=1,作为词汇表的第 76 个单词是世界*。*
- V₂₀₀=2,作为词汇表的第 200 个单词是狗*。*
- V₃₂₂=1,作为词汇表中的第 332 个单词是吃。
- 单词 baby 没有被选择包含在词汇表中,因此它在没有向量条目时导致值 1。
尽管它非常简单,除了单词出现频率之外的所有信息都丢失了,并且表示大小有快速增长以支持丰富词汇的趋势,但这种技术几十年来几乎只在大量的 NLP 任务中使用,并取得了巨大的成功。尽管近年来文本的矢量表示取得了重大进展,但这种方法的常见细微变化(见下文)今天仍在使用,而且并不总是作为第一个被迅速超越的基线。
n 字袋 为了重新获得由字袋方法丢失的一些词序信息,短词序列(长度为二、三等)的频率。)可用于(附加地或替代地)构建单词向量。自然,单词袋是这种方法的一个特例,因为 n=1 。
对于那句“狗咬狗的世界,宝贝!”,单词对是“狗食”、“吃狗”、“狗世界”和“世界宝宝”(有时也有“狗”和“宝宝”),词汇由输入语料库中所有连续的单词对组成(或用其增强)。
Figure 3: 2-grams representation of the sentence “The movie is amazing”
这种方法的一个主要缺点是词汇大小对唯一单词数量的非线性依赖,这对大型语料库来说可能非常大。过滤技术通常用于减少词汇量。
tf-idf 加权 词袋上下文中最后一个值得一提的相关技术是 词频——逆文档频率 ,通常表示为 tf-idf 。该方法用每个单词的逆文档频率* (IDF)对上述单词(或 n-gram)频率向量重新加权。一个单词的 IDF 就是语料库中文档数量的对数除以该单词出现的文档数量。*
简而言之,TF 术语随着该词出现得越来越频繁而增长,而 IDF 术语随着该词出现得越来越少而增长。这是为了调整频率分数,因为一般来说,有些词出现的频率更高(或更低)。参见[ Salton & Buckley,1988 ]对术语加权方法的全面概述。
潜在狄利克雷分配
LDA 是一个生成统计模型,它允许用未观察到的组来解释观察结果集,从而解释为什么数据的某些部分是相似的。例如,如果观察是收集到文档中的单词,那么它假设每个文档是少量主题的混合物,并且每个单词的出现都归因于文档的一个主题。
为了将这一点与词袋联系起来,前一种方法可以被认为是一种过于简单的概率模型,将文档作为词的分布。单词袋向量则代表我们对每个文档中的非标准化单词分布的最佳近似;但是这里的文档是基本的概率单位,每一个都是其唯一分布的单个样本。
因此,问题的关键是通过增加一个潜在的(隐藏的)K 主题的中间层,从这个简单的文档概率模型转变为一个更复杂的模型。
Figure 4: The probabilistic model shift from bag-of-words to LDA
主题现在的特征是单词上的分布,而文档是主题上的分布。文档的概率模型对应于文档的生成模型;为了生成一组长度为 {Nᵢ} 的 M 个文档,假设预定数量的 K 个主题,其中 Dir() 表示一个狄利克雷分布:
- 对于每个题目 v ,取样一个单词分布φᵥ~ Dir(β) 。
- 对于每个文档 i ,抽取一个主题分布(或混合)θᵢ~ Dir( α ) 。
- 生成长度为 Nᵢ 的文件 i ,每个字 j :
3.1。样题 zᵢⱼ ~ Multinomial(θᵢ) 作词 j 。3.2。样字j*~multinomial(zᵢⱼ)。*
给定这个模型和一个文档集,问题就变成了推理,在推理过程中可以找到上述各种分布的近似值。其中有θᵢ,每个文档的主题分布 i ,维度矢量 K 。
因此,在推断模型的过程中,推断出维度为 K 的向量空间,该向量空间以某种方式捕获了我们语料库中的主题或主题以及它们在其中的文档之间共享的方式。当然,这可以作为这些文档的嵌入空间,并且——取决于对 K 的选择——它可以比基于词汇表的文档小得多。
事实上,虽然 LDA 的主要使用情况是无监督的主题/社区发现,但是其他情况包括使用所得的潜在主题空间作为文档语料库的嵌入空间。还要注意,其他主题建模技术——例如非负矩阵分解(NMF) 和概率潜在语义索引(PLSI)——可以以类似的方式用于学习文档嵌入空间。
***注意:*从业者对于概率主题模型的一个主要问题是它们的稳定性。因为训练主题模型需要概率分布的采样,所以可以预期相同语料库的模型随着随机数生成器的种子变化而不同。这个问题由于主题模型对相对小的语料库变化的敏感性而变得复杂。
无监督文档嵌入技术
本节中介绍的许多方法都是受著名的单词嵌入技术的启发,其中最主要的是 word2vec ,它们有时甚至是这些方法的直接推广。这些单词嵌入技术有时也被称为神经概率语言模型*;这些不是相同的术语,因为概率语言模型是单词序列的概率分布,但是由于这种方法是作为一种学习语言模型的方法在[ Bengio,2003 中介绍的,所以它们是紧密相关的。*
因此,对单词嵌入技术的基本理解对于理解本节至关重要。如果你不熟悉这个主题,Chris McCormick 写得很好的关于 word2vec 的两部分教程是一个很好的起点(第二部分,Joshua Bengio 教授写的关于神经网络语言模型的 Scholarpedia 文章也是如此(参见 Hunter Heidenreich 的帖子,以获得关于单词嵌入的更一般和简明的概述,以及 [Alex Minnar 的然而,为了深刻理解细节,我强烈建议您阅读 Bengio,2003 年 ]、[ Mikolov 等人,2013 年 a ]和[ Pennington 等人,2014 年 ]关于该主题的开创性论文,这些论文在许多方面塑造了这一子领域。
即使假设你熟悉这个模型的一个重要假设,我仍然希望注意到这个模型所做的一个重要假设,这个假设可能被这里回顾的每一个模型所继承:分布假设。下面是来自维基百科的简要描述:
语言学中的分布假设来源于语言使用的语义理论,即在相同语境中使用和出现的词语倾向于表达相似的意思。“一个词由它所结交的朋友来表征”的基本思想是由弗斯推广开来的。分布假设是统计语义学的基础。
事实上,很容易看出 word2vec 以及其他用于学习单词表示的自我监督方法严重依赖于这一假设;毕竟,该模型的关键在于,在学习从单词本身预测单词的上下文(或反之亦然)时学习的单词表示表示捕获深层语义和句法概念和现象的向量空间。意义,从一个词的上下文中学习可以教我们关于它的意义和它的句法作用。
在本节中,涵盖自我监督的文档表示学习,您将看到所有这些方法都保持了对单词的假设,并以某种方式将其扩展到更大的文本单元。
n 元文法嵌入
[ Mikolov 等人,2013b ]扩展了 word2vec 的 skip-gram 模型,通过使用数据驱动的方法识别大量短短语(作者专注于两个和三个单词的短语),然后在 word2vec 模型的训练期间将这些短语视为单独的标记,来处理短短语。自然,这不太适合学习更长的短语——因为当短语长度增加时,词汇量会爆炸——而且肯定不会推广到看不见的短语以及跟随它的方法。
Moshe Hazoom 写了一篇关于这种方法的精彩实用评论,他的雇主将其用于一个专注于金融领域的搜索引擎。
平均单词嵌入
从有意义的单词嵌入中构造文档嵌入有一种非常直观的方法:给定一个文档,对该文档的单词对应的所有向量执行一些向量运算,以在相同的嵌入空间中将它们概括为单个向量;两种常见的汇总运算符是 average 和 sum。
在此基础上,您也许已经可以想象扩展 word2vec 及其相关的编码器-解码器架构来学习如何将单词向量组合到文档嵌入中会很有趣;这个方法之后的方法属于这一类。**
第二种可能性是使用固定的(不可学习的)算子来进行向量汇总,例如平均,并使用旨在产生丰富的文档嵌入的学习目标来学习在前一层中的单词嵌入;一个常见的例子是使用一个句子来预测上下文句子。因此,这里的主要优点是单词嵌入被优化用于平均到文档表示中。
Figure 5: Siamese CBOW network architecture from [Kenter et al, 2016]
[ 肯特等人,2016 ]正是这样做的,使用一个简单的神经网络对单词向量进行平均,通过预测给定的句子表示来学习单词嵌入。他们将结果与平均的 word2vec 向量和 skip-thoughts 向量进行比较(参见下面相应的小节)。【 Hill 等人,2016 】比较了过多的方法,包括训练 CBOW 和 skip-gram 单词嵌入,同时优化句子表示(这里使用单词向量的元素相加)。[ Sinoara 等人,2019 ]还提出了一种将单词嵌入向量和其他知识源(如词义向量)直接组合到它们的质心中来表示文档。
最后,[ Arora 等人,2016 ]进一步表明,当增加两个小的变化时,这种方法是一种简单但难以击败的基线:(1)使用平滑的逆频率加权方案,以及(2)从词向量中移除常见话语成分;这个成分是使用 PCA 发现的,并且它被用作最频繁话语的校正术语,推测与句法有关。作者提供了一个 Python 实现。
***注意:*当观察基于注意力的机器翻译模型时,也许可以找到正确平均的单词“嵌入”的力量的另一个证明。单向解码器 RNN 获得先前翻译的单词作为输入,加上不仅要翻译的当前单词的“嵌入”(即来自编码器 RNN 的双向激活),而且要翻译其周围单词的“嵌入”;这些以加权的方式被平均成一个上下文向量。它教导了这种加权平均能够保持来自编码器网络激活的复杂的组成和顺序相关的信息(回想一下,这些不像在我们的情况中那样是孤立的嵌入;每一个都注入了前面/后面单词的上下文)。
Sent2Vec
在[ Pagliardini 等人,2017 ]和[ Gupta 等人,2019 ](包括一个官方的基于 C++的 Python 实现)中介绍了这种技术,这种技术在很大程度上是上述两种方法的结合: word2vec 的经典 CBOW 模型都进行了扩展,以包括单词 n-grams 和,它们适用于优化单词(和 n-grams)嵌入,以便对它们进行平均
Figure 6: sent2vec can be thought of as an unsupervised version of fastText
此外,去除了输入二次采样的过程,而是将整个句子视为上下文。这意味着 (a) 放弃使用频繁的单词二次采样——以便不阻止 n-grams 特征的生成——以及*(b)*word 2 vec使用的动态上下文窗口被取消:整个句子被视为上下文窗口,而不是在 1 和当前句子的长度之间均匀地采样每个二次采样单词的上下文窗口大小。
另一种思考 sent2vec 的方式是作为 fastText 的无监督版本(见图 6),其中整个句子是上下文,可能的类别标签都是词汇单词。巧合的是,[ Agibetov 等人,2018 ]针对生物医学句子分类的任务,比较了使用 sent2vec 向量作为特征的多层感知器与 fastText 的性能。
段落向量(doc2vec)
有时被称为 doc2vec ,这种方法在[ Le & Mikolov,2014 中提出,可能是第一次尝试将 word2vec 推广到处理单词序列。作者介绍了 p 图向量模型的两种变体:分布式内存和分布式单词包。**
段落向量:分布式内存(PV-DM) PV-DM 模型通过添加内存向量来增强标准编码器-解码器模型,旨在从输入中捕捉段落的主题或上下文。这里的训练任务和连续包话挺像的;一个单词可以从它的上下文中预测出来。在这种情况下,上下文单词是前面的单词,而不是周围的单词,就像段落一样。
Figure 7: The Distributed Memory model of Paragraph Vectors (PV-DM)
为了实现这一点,每个段落都被映射到一个唯一的向量,由矩阵中的一列表示(用 D 表示),词汇表中的每个单词也是如此。上下文是固定长度的,从段落上的滑动窗口中采样。段落向量在从同一段落生成的所有上下文之间共享,但不在段落之间共享。自然地,单词嵌入是全局的,并且可以使用预先训练的单词嵌入(参见下面的实现和增强*)。*
正如在 word2vec 中,向量必须以某种方式汇总成一个单一的向量;但是与 word2vec 不同,作者在他们的实验中使用了串联。请注意,这保留了订单信息。类似于 word2vec ,一个简单的 softmax 分类器(在这种情况下,实际上是分层的 softmax)被用于这个概括的向量表示,以预测任务输出。训练以标准方式进行,使用随机梯度下降并通过反向传播获得梯度。
注意,只有训练语料库中的段落具有来自 D 的与其相关联的列向量。在预测时,需要执行推理步骤来计算新段落的段落向量:文档向量是随机初始化的。然后,重复地从新文档中选择一个随机单词,并使用梯度下降来调整输入到隐藏层的权重,使得对于所选择的单词,softmax 概率最大化,而隐藏到 softmax 输出的权重是固定的。这导致新文档的表示为训练语料库文档向量(即 D 的列)的混合,自然地驻留在文档嵌入空间中。
段落向量:分布式单词包(PV-DBOW)
段落向量的第二种变体,顾名思义,或许是 word2vec 的 skip-gram 架构的并行;分类任务是仅使用段落向量来预测单个上下文单词。在随机梯度下降的每次迭代中,采样一个文本窗口,然后从该窗口中采样单个随机单词,形成下面的分类任务。
Figure 8: The Distributed Bag of Words model of Paragraph Vectors (PV-DBOW)
训练在其他方面是相似的,除了单词向量不与段落向量一起被联合学习的事实。这使得 PV-DBOW 变体的内存和运行时性能都要好得多。
***注:*在 its Gensim 实现中,PV-DBOW 默认使用随机初始化的字嵌入;如果 dbow_words 设置为 1,则在运行 dbow 之前,会运行一步 skip-gram 来更新字嵌入。[ Lau & Baldwin,2016 ]认为,尽管 dbow 在理论上可以处理随机单词嵌入,但这严重降低了他们所研究的任务的性能。
一个直观的解释可以追溯到模型的目标函数,即最大化文档嵌入与其组成单词嵌入之间的点积:如果单词嵌入是随机分布的,则更难以将文档嵌入优化为接近其更关键的内容单词。
应用、实现和增强 【Le&miko lov,2014】演示了段落向量在几个文本分类和情感分析任务中的使用,而【Dai et al,2015】在文档相似性任务的背景下对其进行了检查,并且【Lau & Baldwin,2016】将其与论坛问题复制任务和 语义文本相似性(STS) SemEval 共享任务进行了基准测试。后面的两篇论文对该方法进行了扩展评估(前者侧重于 PV-DBOW 变体),将其与其他几种方法进行了比较,并给出了实用建议(后面的包括代码)。
这个方法有一个 Python 实现,作为 gensim 包的一部分,还有一个 PyTorch 实现。同样,【 Lau & Baldwin,2016 】也提供了他们考试用的代码。
最后,提出了对该方法的各种改进。例如,【李等,2016 】将该方法扩展为也包含 n-gram 特征,而【thong tan&phiconstrakul,2019】建议在计算嵌入投影时使用余弦相似度而不是点积(还提供了一个 Java 实现)。
Doc2VecC
【陈,2017 】提出了一种有趣的方法,该方法受段落向量方法(PV-DM)的分布式记忆模型和平均单词嵌入的方法的启发来表示文档。
Figure 9: The architecture of the Doc2VecC model
与段落向量*,doc 2 vecc(文档
向量穿越讹误的首字母缩写)由输入层、投影层和输出层组成,预测目标词(上例中为“仪式”)。相邻单词的嵌入(例如“开始”、“for”、“The”)提供局部上下文,而整个文档的向量表示(以灰色显示)用作全局上下文。与直接学习每个文档的唯一向量的段落向量相反,doc 2 vec将每个文档表示为从文档中随机采样的单词的嵌入的平均值(例如,在位置 p 的“性能”,在位置 q 的“称赞”,以及在位置 r 的“巴西”)。*
此外,作者选择通过随机删除单词的重要部分来破坏原始文档,通过平均化剩余单词的嵌入来表示文档。这种损坏机制允许在训练期间加速,因为它显著地减少了在反向传播中要更新的参数的数量。作者还展示了它如何引入一种特殊形式的正则化,他们认为这导致了观察到的性能改善,基准测试是情感分析任务、文档分类任务和语义相关度任务,而不是过多的最先进的文档嵌入技术。
在一个公共的 Github 库中可以找到一个基于 C 的方法和代码的开源实现,用于重现论文中的实验。
[ 希尔等人,2016 年 ]还将破坏或添加噪声到文档嵌入学习过程以产生更鲁棒的嵌入空间的一般思想应用于跳过思维模型(见以下小节),以创建他们的顺序去噪自动编码器(SDAE)模型。
跳跃思维向量
在[ Kiros et al,2015 中提出,这是另一个早期推广 word2vec 的尝试,并与一起发布了一个官方的纯 Python 实现(最近还宣称实现了 PyTorch 和 TensorFlow )。
然而,这以另一种直观的方式扩展了word 2 vec*——特别是 skip-gram 架构:基本单元现在是句子,一个编码的句子用于预测它周围的句子。使用在上述任务上训练的编码器-解码器模型来学习矢量表示;作者使用具有 GRU 激活的 RNN 编码器和具有条件 GRU 的 RNN 解码器。两个不同的解码器被训练用于前一个和下一个句子。*
Figure 10: The skip-thoughts model. Given a tuple of contiguous sentences, the sentence sᵢ is encoded and tries to reconstruct the previous sentence sᵢ₋₁ and the next sentence sᵢ₊₁
skip-thought 中的词汇扩展
skip-thought编码器使用单词嵌入层,将输入句子中的每个单词转换为其对应的单词嵌入,有效地将输入句子转换为一系列单词嵌入。这个嵌入层也由两个解码器共享。
Figure 11: In the skip-thoughts model, sentence sᵢ is encoded by the encoder; the two decoders condition on the hidden representation of the encoder’s output hᵢ to predict sᵢ₋₁ and sᵢ₊₁ [from Ammar Zaher’s post]
然而,作者只使用了 20,000 个单词的小词汇量,因此在各种任务中使用时可能会遇到许多看不见的单词。为了克服这一点,通过为参数化该映射的矩阵 W 求解非正则化的 L2 线性回归损失,学习从在大得多的词汇表(例如 word2vec )上训练的单词嵌入空间到跳过思想模型的单词嵌入空间的映射。
应用、增强和进一步阅读 作者演示了将跳过思维向量用于语义相关度、释义检测、图像句子排序、问题类型分类和四个情感和主观性数据集。【 Broere,2017 】通过对 skip-thought 句子表征进行训练逻辑回归来预测词性标签和依存关系,从而进一步研究其句法属性。
[ Tang et al,2017a ]提出了一种针对 skip-thought 的邻域方法,丢弃排序信息并使用单个解码器预测上一句和下一句。【【唐等,2017b 】扩展该检查,提出对模型的三个增强,他们声称使用更快和更轻的模型来提供可比的性能: (1) 仅学习解码下一句话, (2) 在编码器和解码器之间添加 avg+max 连接层(作为允许非线性非参数特征工程的方式),以及 (3) 执行良好的字嵌入初始化。最后,【 Gan et al,2016 】在广泛的应用中,使用基于 CNN 的分层编码器而不是仅基于的编码器来应用相同的方法。
在[ Lee & Park,2018 ]中提出的另一种变体,通过基于文档结构为每个目标句子选择整个文档中有影响的句子来学习句子嵌入,从而使用元数据或文本样式来识别句子的依存结构。此外,【 Hill 等人,2016 】提出了顺序去噪自动编码器(SDAE)* 模型,这是 skip-thought 的变体,其中输入数据根据一些噪声函数被破坏,模型被训练以从被破坏的数据中恢复原始数据。*
对于关于 skip-thought 模型的进一步非学术阅读, Sanyam Agarwa 在他的博客上给出了该方法的一个非常详细的概述,而 Ammar Zaher 展示了其用于构建烹饪食谱的嵌入空间。
快速发送
【 Hill 等人,2016 】在skip-thinks模型的基础上提出了一个明显更简单的变体; FastSent 是一个简单的加法(对数双线性)句子模型,旨在利用相同的信号,但计算开销低得多。给定一些上下文句子的 BOW 表示,该模型简单地预测相邻的句子(也表示为 BOW)。更正式地说, FastSent 学习模型词汇表中每个单词 w 的源 uᵂ和目标 vᵂ嵌入。对于连续句的训练示例 Sᵢ₋₁,Sᵢ,Sᵢ₊₁,Sᵢ被表示为其源嵌入的总和**=∑t34】uᵂ超过 w∈Sᵢ 。这个例子的成本是简单的∑𝜙(sᵢ*,* vᵂ)除以w∑sᵢ₋₁∪sᵢ₊₁,其中𝜙是 softmax 函数。这篇论文附有官方的 Python 实现。**
思维敏捷的向量
[ Logeswaran & Lee,2018 ]将文档嵌入任务——预测句子出现的上下文的问题——重新表述为监督分类问题(见图 12b),而不是之前方法的预测任务(见图 12a)。
Figure 12: The Quick-Thought problem formulation (b) contrasted with the Skip-Thought approach (a)
要点是使用当前句子的含义来预测相邻句子的含义,其中含义由从编码函数计算的句子的嵌入来表示;注意这里学习了两个编码器:输入句子的 f 和候选句子的 g 。给定一个输入句子,由编码器(本例中为 RNNs)进行编码,但模型不是生成目标句子,而是从一组候选句子中选择正确的目标句子;候选集是从有效的上下文句子(基本事实)和许多其他非上下文句子中构建的。最后,所构建的训练目标最大化了为训练数据中的每个句子识别正确上下文句子的概率。将以前的句子预测公式视为从所有可能的句子中选择一个句子,这种新方法可以被视为对预测问题的一种判别近似。
作者评估了他们在各种文本分类、释义识别和语义相关任务上的方法,并提供了官方 Python 实现。
文字移动器嵌入(WME)
一个最近的方法,来自 IBM 的研究,是字移动器嵌入(),在 Wu et al,2018b 中提出。提供了一个官方的基于 C、Python 包装的实现。
【库什纳等人,2015 】提出 W 移动者距离(WMD);这将两个文本文档之间的相异度度量为一个文档的嵌入单词需要在嵌入空间中“行进”到达另一个文档的嵌入单词的最小距离量(见图 13a)。此外,[ Wu et al,2018a ]提出了 D2KE(到核和嵌入的距离),一种从给定的距离函数推导正定核的通用方法。
Figure 13: Contrasting WMD with WME. (a) WMD measures the distance between two documents x and y, while (b) WME approximates a kernel derived from WMD with a set of random documents 𝜔.
WME 基于三个组件来学习不同长度文本的连续矢量表示:
- 以无监督的方式学习高质量单词嵌入的能力(例如,使用 word2vec )。
- 使用 Worder Mover 的距离 (WMD)基于所述嵌入为文档构建距离度量的能力。
- 使用 D2KE 从给定的距离函数导出正定核的能力。
使用这三个组件,应用以下方法:
- 使用 D2KE,通过由字移动器到来自给定分布的随机文档𝜔的距离 (WMD)给出的无限维特征映射,构造一个正定字移动器的核 (WMK)。由于使用了 WMD,特征图考虑了由预训练单词嵌入给出的语义空间中的文档之间的单个单词的对齐(参见图 13b)。
- 基于该核,通过核的随机特征近似来导出文档嵌入,其内积近似精确的核计算。
这个框架是可扩展的,因为它的两个构建模块,word2vec 和 WMD,可以被其他技术代替,例如 GloVe(用于单词嵌入)或 S-WMD(用于将单词嵌入空间转换成文档距离度量)。
作者在 9 个真实世界文本分类任务和 22 个文本相似性任务上评估了 WME,并证明它始终匹配,有时甚至超过其他最先进的技术。
句子-BERT (SBERT)
NLP 中的 2018 年以 transformers 的崛起为标志(见图 14),最先进的神经语言模型受[ Vaswani et al 2017 ]中提出的 transformer 模型的启发-一种序列模型,它无需卷积和递归,而是使用注意力将序列信息纳入序列表示。这个蓬勃发展的家庭包括伯特(及其延伸),GPT (1 和 2)和 XL 口味的变形金刚。
Figure 14: Rise of the transformers
这些模型生成输入标记(通常是子词单元)的上下文嵌入,每个标记都注入了其邻域的信息,但并不旨在为输入序列生成丰富的嵌入空间。BERT 甚至有一个特殊的[CLS]令牌,其输出嵌入用于分类任务,但对于其他任务来说仍然是输入序列的不良嵌入。[ 雷默斯&古雷维奇,2019
Sentence-BERT ,在【 Reimers & Gurevych,2019 中提出,并伴随有一个 Python 实现,旨在通过使用连体和三联体网络结构来调整 BERT 架构,以导出语义上有意义的句子嵌入,可以使用余弦相似度进行比较(见图 15)。
Figure 15: The SBERT architecture in training on a classification objective (left) and inference (right)
监督文档嵌入技术
前一节中介绍的非监督方法允许我们从大型未标记的语料库中学习有用的表示。这种方法不是自然语言处理所独有的,它通过设计学习目标来关注学习表示,这些学习目标利用数据中可自由获得的标签。因此,这些方法的强度和稳健性不仅在很大程度上取决于学习框架,还取决于人工设计的学习目标要求或带来在各种下游任务中证明有用的有意义特征或知识的学习的程度。例如,我们希望单词和文档嵌入空间能够很好地捕获语义和句法信息。
学习有意义的数据表示(在我们的例子中是单词序列)的对比方法是利用显式标签(几乎总是由人类注释者以某种方式生成)。这里,与各种任务的相关性取决于明确的任务和标签与最终应用的接近程度,同样,该任务对可概括的特征和知识的学习有多好。
我们将看到监督方法的范围从那些直接利用特定的标记任务来学习表征,到那些重组任务或从中提取新的标记任务来引出更好的表征。
从标记数据中学习文档嵌入
已经有各种尝试使用标记的或结构化的数据来学习句子表示。具体来说,[ Cho 等人,2014a ]和[ Sutskever 等人,2014 ]可能是首次尝试应用编码器-解码器方法来显式学习带有标记数据的句子/短语嵌入;第一个使用了用于统计机器翻译的平行短语语料库 Europarl ,第二个使用了来自 WMT 14 数据集的英语到法语的翻译任务。另一个值得注意的尝试在[ Wieting 等人,2015 和[Wieting & Gimpel,2017]中提出,其中单词嵌入及其到文档嵌入的映射被联合学习,以最小化释义对之间的余弦相似性(来自PPDB 数据集)。[ Hill 等人,2015 ]训练神经语言模型,将字典定义映射到由那些定义定义的单词的预训练单词嵌入。最后,【 Conneau et al,2017 】在斯坦福自然语言推理任务上训练了各种架构的 NN 编码器(见图 16)。
Figure 16: Generic NLI training scheme
文档相似性的上下文嵌入 上述方法的一个具体情况是由文档相似性驱动的。[ Das 等人,2016 ]展示了通过社区问答的暹罗网络学习到的最大化两个文档之间相似性的文档嵌入(参见图 17)
Figure 17: The SCQA network consists of repeating convolution, max pooling and ReLU layers and a fully connected layer. Weights W1 to W5 are shared between the sub-networks.
同样,[ Nicosia & Moschitti,2017 ]在学习二进制文本相似性的同时,使用暹罗网络产生单词表示,将同一类别中的示例视为相似。(参见图 18)
Figure 18: The architecture of the siamese network from [Nicosia & Moschitti, 2017]. Word embeddings of each sentence are consumed by a stack of 3 Bidirectional GRUs. Both network branches share parameter weights.
跨语言降秩岭回归(Cr5) 【Josifoski 等人,2019】介绍了一种将任何语言编写的文档嵌入到单一的、与语言无关的向量空间的方法。这是通过训练基于岭回归的分类器来完成的,该分类器使用语言特定的词袋特征来预测给定文档所涉及的概念。当将学习的权重矩阵限制为低秩时,作者表明它可以被分解以获得从语言特定的词袋到语言无关的嵌入的期望映射。提供了官方的 Python 实现。
特定任务的监督文档嵌入
产生文档嵌入的普通监督方法使用各种神经网络体系结构,学习将单词向量映射到文档向量的合成算子;这些被传递给受监督的任务,并依赖于类标签,以便通过合成权重反向传播(参见图 19)。
因此,网络的几乎所有隐藏层可以被认为产生输入文档的矢量嵌入,直到该层的网络前缀是从单词矢量到嵌入空间的学习映射。在[ Wieting et al,2015 ]中可以找到基于单词向量和监督学习任务的学习句子向量的不同方法的严格检查。
Figure 19: Neural networks implicitly learn to map word embedding sequences to document embeddings
请注意,虽然所使用的单词嵌入可以是预先生成的,并且是任务不可知的(至少在一定程度上),但是从单词嵌入到文档嵌入的映射是任务特定的。虽然这些对于相关的任务可能是有用的,但这种方法肯定不如无监督的方法健壮和通用,至少在理论上是这样。[ Kiros 等人,2015 年 ]
值得注意的应用包括使用 RNNs 的情感分类[Socher 等人,2013],使用 CNN 的各种文本分类任务[Kalchbrenner 等人,2014] [Kim,2014],以及使用递归卷积神经网络的机器翻译和文本分类任务[Cho 等人,2014a,2014 b][赵等人,2015]。
GPT
拉德福德等人,2018提出了生成式预训练 (GPT)方法 ( 伴随一个 Python 实现),结合无监督和有监督的表示学习,使用瓦斯瓦尼等人 2017 提出的 transformer 模型在无标签语料库上学习一个无监督的语言模型,然后使用有监督的数据分别对其用于每个任务进行微调。[他们后来在 拉德福德等人,2019 ]中展示了 GPT-2 ,专注于支持他们工作的无监督学习部分,再次发布了官方的 Python 实现。
深度语义相似度模型(DSSM) T22【微软研究项目,DSSM 是一种深度神经网络建模技术,用于在连续的语义空间中表示文本串,并对两个文本串之间的语义相似度进行建模(见图 20)。
Figure 20: The architecture of a DSSM neural network
在其他应用中,DSSM 用于开发潜在的语义模型,该模型将不同类型的实体(例如,查询和文档)投影到公共的低维语义空间中,用于各种机器学习任务,例如排序和分类。例如,【黄等,2013 】使用 it 将查询和文档投影到一个公共的低维空间,在该空间中,文档与给定查询的相关性被计算为它们之间的距离。
实现包括 TensorFlow 、 Keras 和两种 PyTorch 变体。
共同学习句子表征
[ Ahmad 等人,2018 ]提出,从多个文本分类任务中联合学习句子表示,并将它们与预先训练的单词级和句子级编码器相结合,会产生对迁移学习有用的健壮句子表示
Figure 21: Jointly learning sentence embeddings using auxiliary tasks
[ 于&姜,2016 ]类似地表明,使用两个辅助任务来帮助诱导句子嵌入对于跨领域的情感分类来说应该是很好的,与情感分类器本身一起共同学习这个句子嵌入(图 21)。
通用句子编码器 在 Cer et al,2018a 和 Cer et al,2018b 中提出,并伴随一个 TensorFlow 实现,该方法实际上包括了两种可能的句子表征学习模型:变换器模型和深度平均网络(DAN) 模型(见图 22)。两者都被设计成允许多任务学习,支持的任务包括(1)类似于无监督学习的任务;(2)用于包含解析的会话数据的会话输入-响应任务;以及(3)用于对监督数据进行训练的分类任务(参见前面的小节)。作者专注于迁移学习任务的实验,并将他们的模型与简单的 CNN 和 DAN 基线进行比较。该方法后来扩展到解决多语言设置。**
transformer 模型直接基于 Vaswani et al 2017 中提出的 transformer 模型,这是第一个完全基于注意力的序列转导模型,用多头自注意力取代了编码器-解码器架构中最常用的递归层(见图 22a)。
该模型使用转换器架构的编码子图来构建句子嵌入。编码器使用注意力来计算句子中单词的上下文感知表示,同时考虑其他单词的顺序和身份。上下文感知单词表示被平均在一起以获得句子级嵌入。
Figure 22: The two models of the Universal Sentence Encoder: (a) Transformer and (b) DAN
相反,在丹模型中,在[ Iyyer et al,2015 ]中,单词和双字母组合的输入嵌入首先被平均在一起,然后通过前馈深度神经网络(DNN)产生句子嵌入(见图 22b)。
GenSen 与通用句子编码器非常相似,GenSen 方法,【 Subramanian 等人,2018 】与官方 Python 实现一起提出,结合多个监督和非监督学习任务来训练基于 RNN w/ GRU 的编码器-解码器模型,从该模型中提取嵌入。四个支持的任务是:(1) 跳过思维向量,(2)神经机器翻译,(3)选区分析,以及(4)自然语言推理(三向分类问题;给定一个前提和一个假设句子,目标是将它们的关系分为蕴涵、矛盾或中性。官方 Python 实现发布。
如何选择使用哪种技术
我在这里没有简单的答案,但这里有一些可能的要点:
- 平均单词向量是一个很好的基线,所以一个好主意是通过集中精力生成非常好的单词向量,并且首先简单地平均它们,来开始你对好的文档嵌入的探索。毫无疑问,文档嵌入的大部分功能来自于构建它们所基于的词向量,我认为可以肯定地说,在继续前进之前,该层中有大量的信息需要优化。你可以尝试不同的预训练单词嵌入,探索哪些源域和哪些方法(例如 word2vec vs GloVe vs BERT vs ELMo)可以更好地捕捉你需要的信息类型。然后,通过尝试不同的摘要操作符或其他技巧(像[ 阿罗拉等人,2016 ]中的那些)来稍微扩展这一点可能就足够了。
- 绩效可能是一个关键的考虑因素,尤其是在方法中没有明确的领导者的情况下。在这种情况下,无论是平均字向量的,还是像 sent2vec 和 FastSent 这样的精益方法,都是不错的选择。相比之下,使用 doc2vec 时,每个句子所需的实时向量表示推理可能会被证明在给定应用约束的情况下代价很高。 [SentEval,在 Conneau & Kiela,2018 ]中提出的一个句子表征的评估工具包,就是在这种背景下值得一提的工具。
- 考虑学习目标对你的任务的有效性。上面提到的不同的自我监督技术以不同的方式扩展了分布假设,跳跃思维和快速思维分别根据句子和段落在文档中的距离建立了它们之间的强关系。这也许适用于书籍、文章和社交媒体帖子,但可能不适用于其他文本序列,尤其是结构化的文本,因此可能会将您的文档投影到一个对它们不适用的嵌入空间。同样,WME 所依赖的单词对齐方法可能并不适用于每种情况。
- 开源实现非常丰富,因此针对您的任务对不同的方法进行基准测试可能是可行的。
- 没有明确的任务负责人。论文经常针对分类、转述和语义相关度任务测试不同的方法。然而,当考虑关于该主题的所有文献时,特别是考虑 2018 年的两个最新基准测试的结果时,上述结论就会出现,第一个由[ Logeswaran & Lee,2018 在介绍他们的快速思考方法时完成,第二个由[ Wu 等人,2018b 作为他们关于字移动器嵌入的论文的一部分完成。
最后的话
就是这样!一如既往,我确信我写的帖子并不完整,所以请随时对以上概述提出更正和补充建议,要么在此评论,要么直接联系我。😃
我还要感谢 Adam Bali 和 Ori Cohen,他们提供了非常有价值的反馈。去看看他们的帖子!
最后,我发现值得一提的是,代码为的论文有致力于文档嵌入的任务,脸书研究公司开源了 [SentEval,这是一个在 Conneau & Kiela,2018 ]中展示的句子表示的评估工具包。
现在坐好,让参考文献淹没你。📕 📗 📘 📙
参考
Agibetov,a .,Blagec,k .,Xu,h .,和 Samwald,M. (2018 年)。用于生物医学句子分类的快速可扩展神经嵌入模型。 BMC 生物信息学, 19 (1),541。
艾哈迈德,吴伟国,白,徐,彭,张国威(2018)。学习用于文本分类的健壮的、可转移的句子表示。 arXiv 预印本 arXiv:1810.00681 。
阿罗拉,s .,梁,y .,,马,T. (2016)。一个简单但难以攻克的句子嵌入基线。[ 非官方实施
Bengio,r . Ducharme,Vincent,p .和 Jauvin,C. (2003 年)。一个神经概率语言模型。机器学习研究杂志,3(2 月),1137–1155。
B.Broere,(2017)。跳过思维向量的句法属性。蒂尔堡大学硕士论文。
Cer,d .,Yang,y .,Kong,S. Y .,Hua,n .,Limtiaco,n .,John,R. S .,和 Sung,Y. H. (2018 年)。通用语句编码器。 arXiv 预印本 arXiv:1803.11175 。
Cer,d .,Yang,y .,Kong,S. Y .,Hua,n .,Limtiaco,n .,John,R. S .,和 Strope,B. (2018 年 11 月)。英语通用句子编码器。在2018 自然语言处理经验方法会议记录:系统演示(第 169-174 页)。
陈,男(2017)。通过讹误对文档进行有效的矢量表示。 arXiv 预印本 arXiv:1707.02377 。
陈,秦,彭,杨,陆,钟(2018)。 BioSentVec:为生物医学文本创建句子嵌入。arXiv 预印本 arXiv:1810.09302。
Cho,k .,Van merrinboer,b .,Gulcehre,c .,Bahdanau,d .,Bougares,f .,Schwenk,h .,和 Bengio,Y. (2014 年)。使用用于统计机器翻译的 RNN 编码器-解码器学习短语表示。 arXiv 预印本 arXiv:1406.1078 。
Cho,k .,Van merrinboer,b .,Bahdanau,d .,和 Bengio,Y. (2014 年)。关于神经机器翻译的性质:编码器-解码器方法。 arXiv 预印本 arXiv:1409.1259 。
Conneau,a .,Kiela,d .,Schwenk,h .,Barrault,l .,和 Bordes,A. (2017 年)。从自然语言推理数据中监督学习通用句子表示。 arXiv 预印本 arXiv:1705.02364 。
Conneau,a .,& Kiela,D. (2018 年)。 Senteval:通用语句表示评估工具包。 arXiv 预印本 arXiv:1803.05449 。
戴,A. M .,Olah,c .,& Le,Q. V. (2015 年)。用段落向量嵌入文档。 arXiv 预印本 arXiv:1507.07998 。
Das,a .,Yenala,h .,Chinnakotla,m .,& Shrivastava,M. (2016 年 8 月)。我们站在一起:相似问题检索的连体网络。《计算语言学协会第 54 届年会论文集》(第 1 卷:长篇论文)(第 378–387 页)。
甘,钟,蒲,杨,,李,何,林(2016)。使用卷积神经网络的句子表示的无监督学习。 arXiv 预印本 arXiv:1611.07897 。
甘,钟,蒲,杨,,李,何,林(2016)。使用卷积神经网络学习通用语句表示。arXiv 预印本 arXiv:1611.07897 。
Gupta,p .,Pagliardini,m .,和 Jaggi,M. (2019)。通过解开上下文 n 元语法信息实现更好的单词嵌入。 arXiv 预印本 arXiv:1904.05033 。
哈里斯,Z. S. (1954)。分配结构。Word,10(2–3),146–162。
f .希尔、k .乔、a .科尔霍宁和 y .本吉奥(2015 年)。通过嵌入字典学习理解短语。计算语言学协会汇刊, 4 ,17–30。
Hill,f .,Cho,k .,和 Korhonen,A. (2016 年)。从未标记数据中学习句子的分布式表示。 arXiv 预印本 arXiv:1602.03483 。
黄,张平,何,高,邓,阿塞罗,海克,(2013 年 10 月)。使用点击链接数据学习用于 web 搜索的深度结构化语义模型。在第 22 届 ACM 国际信息会议论文集&知识管理(第 2333–2338 页)。ACM。
Iyyer、v . Manjunatha、j . Boyd-Graber 和 h . daum III(2015 年)。深度无序组合匹敌文本分类的句法方法。在计算语言学协会第 53 届年会暨第 7 届自然语言处理国际联席会议论文集(第 1 卷:长篇论文)(第 1 卷,第 1681-1691 页)。
Josifoski,m .,Paskov,I. S .,Paskov,H. S .,Jaggi,m .,& West,R. (2019,1 月)。作为降秩岭回归的跨语言文档嵌入。第十二届 ACM 网络搜索和数据挖掘国际会议论文集(第 744–752 页)。ACM。
Kalchbrenner,e . Grefenstette 和 Blunsom,P. (2014 年)。用于句子建模的卷积神经网络。 arXiv 预印本 arXiv:1404.2188 。
茨韦塔纳·肯特、博里索夫和米·德·里基(2016 年)。 Siamese cbow:优化句子表达的单词嵌入。 arXiv 预印本 arXiv:1606.04640 。
金,尹。“用于句子分类的卷积神经网络.” arXiv 预印本 arXiv:1408.5882 (2014)。
Kiros,r .,Zhu,y .,Salakhutdinov,R. R .,Zemel,r .,Urtasun,r .,Torralba,a .,& Fidler,S. (2015 年)。跳过思维向量。在神经信息处理系统的进展(第 3294–3302 页)。
m .库斯纳、孙、n .科尔金和 k .温伯格(2015 年 6 月)。从单词嵌入到文档距离。在机器学习国际会议(第 957–966 页)。
刘,J. H .,,鲍德温,T. (2016)。对 doc2vec 的实证评估,以及对文档嵌入生成的实际见解。 arXiv 预印本 arXiv:1607.05368 。[ 代码 ]
Le,q .,& Mikolov,T. (2014 年 1 月)。句子和文档的分布式表示。在机器学习国际会议(第 1188–1196 页)。
李,t .,&帕克,Y. (2018)。使用基于文档结构的上下文的无监督句子嵌入。
Logeswaran,l .,& Lee,H. (2018 年)。学习句子表征的高效框架。arXiv 预印本 arXiv:1803.02893。
李,b,刘,t,杜,x,张,d,赵,z(2015)。通过预测 n-grams 学习文档嵌入,用于长电影评论的情感分类。 arXiv 预印本 arXiv:1512.08183 。
刘,杨,&拉帕塔,M. (2018)。学习结构化文本表示。计算语言学协会汇刊,6,63–75。
Mikolov,Chen,k .,Corrado,g .,& Dean,J. (2013 年)。向量空间中单词表示的有效估计。arXiv 预印本 arXiv:1301.3781。
Mikolov,Sutskever,I .,Chen,k .,Corrado,G. S .,& Dean,J. (2013 年)。单词和短语的分布式表示及其组合性。在神经信息处理系统的进展(第 3111–3119 页)。
尼科西亚,m .,& Moschitti,A. (2017 年 8 月)。使用分类信息学习结构语义相似性的上下文嵌入。在第 21 届计算自然语言学习会议论文集(CoNLL 2017) (第 260–270 页)。
Pagliardini,m .,Gupta,p .,和 Jaggi,M. (2017 年)。使用合成 n-gram 特征的句子嵌入的无监督学习。 arXiv 预印本 arXiv:1703.02507 。
Pennington、r . Socher 和 c . Manning(2014 年 10 月)。 Glove:单词表示的全局向量。在2014 年自然语言处理(EMNLP)经验方法会议记录(第 1532-1543 页)。
a .拉德福德、k .纳拉辛汉、t .萨利曼斯和苏茨基弗(2018 年)。 用无监督学习提高语言理解 。技术报告,OpenAI。
a .、吴、j .、Child、r .、Luan、d .、Amodei、d .、& Sutskever,I. (2019)。语言模型是无人监督的多任务学习者。 OpenAI 博客, 1 (8)。
Reimers 和 Gurevych,I. (2019)。句子伯特:使用连体伯特网络的句子嵌入。 arXiv 预印本 arXiv:1908.10084 。
鲁道夫,m .,鲁伊斯,f .,阿塞,s .,,布莱,D. (2017)。分组数据的结构化嵌入模型。在神经信息处理系统的进展(第 251–261 页)。
g .索尔顿和 c .巴克利(1988)。自动文本检索中的术语加权方法。信息处理&管理, 24 (5),513–523。
Sinoara,R. A .、Camacho-Collados,j .、Rossi,R. G .、Navigli,r .、& Rezende,S. O. (2019)。用于文本分类的知识增强文档嵌入。基于知识的系统, 163 ,955–971。
Socher,r .、Perelygin,a .、Wu,j .、Chuang,j .、Manning,C. D .、ng,a .、Potts,C. (2013 年 10 月)。情感树库语义合成的递归深度模型。在2013 年自然语言处理经验方法会议记录(第 1631-1642 页)。
Subramanian,s .,Trischler,a .,Bengio,y .,& Pal,C. J. (2018)。通过大规模多任务学习来学习通用分布式句子表示。 arXiv 预印本 arXiv:1804.00079 。
Sutskever,I .,Vinyals,o .,& Le,Q. V. (2014 年)。用神经网络进行序列对序列学习。在神经信息处理系统的进展(第 3104–3112 页)。
唐,苏,金,洪,方,王,张,&德萨,V. R. (2017)。反思跳跃思维:一种基于邻域的方法。 arXiv 预印本 arXiv:1706.03146 。
唐,苏,金,洪,方,王,张,&德萨,V. R. (2017)。修剪和改进跳跃思维向量。 arXiv 预印本 arXiv:1706.03148 。
Thongtan 和 t . phiquethrakul(2019 年 7 月)。基于余弦相似度训练的文档嵌入的情感分类。《计算语言学协会第 57 届会议记录:学生研究研讨会》(第 407-414 页)。
Vaswani,a .、Shazeer,n .、Parmar,n .、Uszkoreit,j .、Jones,l .、Gomez,A. N .、… & Polosukhin,I. (2017)。注意力是你所需要的全部。神经信息处理系统进展(第 5998-6008 页)。
j .维廷、m .班萨尔、k .金佩尔和 k .利维斯库(2015 年)。走向普遍的倒装句嵌入。arXiv 预印本 arXiv:1511.08198。
j .维廷和 k .金佩尔(2017 年)。重新考察用于反对比句子嵌入的循环网络。 arXiv 预印本 arXiv:1705.00364 。
吴,严,刘怡红,徐,李,李,李(2018)。 D2ke:从距离到内核和嵌入。arXiv 预印本 arXiv:1802.04956 。
Wu,l .,Yen,即,Xu,k .,Xu,f .,Balakrishnan,a .,Chen,P. Y,… & Witbrock,M. J. (2018)。 Word Mover 的嵌入:从 Word2Vec 到文档嵌入。 arXiv 预印本 arXiv:1811.01713 。
俞军、蒋军(2016 年 11 月)。跨领域情感分类辅助任务学习句子嵌入。在2016 年自然语言处理经验方法会议论文集(第 236–246 页)。
张,杨,陆,张(2019)。用子词信息和网格改进生物医学词嵌入。科学数据, 6 (1),52。
赵,洪,陆,张,等(2015 年 6 月)。自适应层次句子模型。在第二十四届国际人工智能联合大会。
神经网络在不知道的时候知道吗?
简要介绍神经网络跳出框框思考的技术
如果你一直在关注数据科学和机器学习,你可能知道,近年来,深度神经网络彻底改变了人工智能和计算机视觉。自从 AlexNet 在 2012 年以较大优势赢得 ImageNet 挑战赛以来,深度神经网络已经征服了许多以前无法解决的任务。神经网络令人惊叹。他们可以学习如何将冬天的风景变成夏天的风景,给马穿上斑马条纹,在基本没有监督的情况下学习单词之间的语义表示,从草图中生成逼真的图像,以及许多令人惊叹的技能。这项技术已经发展到如此程度,以至于基本上每个拥有笔记本电脑的人都可以使用和构建神经网络架构,实现以前无法实现的壮举。许多开源深度学习框架——如 TensorFlow 和 py torch——都可用,将这一令人惊叹的技术带到您触手可及的地方。
每天早上都有几十份新的预印本发布在 arXiv 上,通过不断的技术创新击败最先进的技术。然而,除了提高性能,深度学习研究还有一个同样重要的领域,涉及一系列与理解神经网络如何感知世界和一个模型如何概括已知之外的事物相关的问题。在实际应用中,最后一个问题至关重要。考虑以下情况。您正在构建一个根据制造商和型号对汽车进行分类的应用程序。但是,如果发布了一款全新设计的新车型,该怎么办呢?在这种情况下,神经网络在训练期间没有看到这个实例。在这种情况下,正确的答案是什么?
识别未知并不是神经网络的默认功能。这个问题叫做开集识别,有几种方法可以解决这个问题。在这篇文章中,我将对它们做一个简单的概述。
自信错了
在深入细节之前,让我们考虑一个玩具例子。假设我们有一个非常简单的二进制分类问题,为此我们训练一个分类器。决策边界被学习,模型很好地概括了我们的测试数据,所以我们很高兴。
模型部署后,我们开始看到类似这样的情况。
我们还幸福吗?嗯,可能没那么多。从右边的点群来看,我们——人类专家——可能会认为这是一个新的类。也许它不是我们感兴趣的课程,也许它很重要。但是神经网络是如何感知这一点的呢?因为它落在相对远离决策边界的地方,所以新实例被非常有把握地归类为橙色。然而,在这种情况下,我们的分类器是错误的。
为了有效地检测这些情况,需要采用额外的方法。本质上,网络只有有限的工具来识别新的类:它有一个特征变换,一个 Softmax 函数和一个只有两个类的承诺。我们如何利用这些来解决我们的问题?一种简单的方法是设定 Softmax 概率的阈值:如果预测类别的概率低于一个给定的阈值,比如 0.5,我们就拒绝这个未知的项目。正如我们之前看到的,这在许多情况下可能不起作用,因为神经网络可能会给出高置信度的错误预测。
查看上下文:OpenMax 方法
我们的网络提供的预测概率可能是错误的,但看看这些点的分布,很明显可能存在一个新的类别。让我们来看看激活向量!例如,这是上面模型中激活分数的分布情况。
蓝色是我们在培训中看到的数据,红色是来自部署的奇怪的新实例。通过激活向量值的分布,我们可以判断一个新的数据点在知识方面是否新颖。这是 OpenMax 方法的基本原理,由 Abhijit Bendale 和 Terrance E. Boult 在他们的 CVPR16 论文中开发,致力于开放集深度网络。在他们的实验中,他们使用了一个 ImageNet 预训练模型,给它输入真实的、愚弄的和开放的图像(即来自训练中看不到的班级的图像);然后检查了激活向量模式。他们的基本发现是,这些模式可以用来检测神经网络不知道的*。*
Activation patterns of the Softmax layer. Source: Abhijit Bendale and Terrance E. Boult, Towards Open Set Deep Networks
在左侧,您可以看到使用不同图像的已训练模型的激活向量的热图。他们发现异常值的方法如下。
1)对于每个类别,使用该类别的正确分类的训练示例,将威布尔分布拟合到激活分数。
2)给激活向量添加一个新的“未知”类。
3)使用威布尔分布的参数转换激活分数。这些被称为 OpenMax 分数。
4)对于新图像,基于 OpenMax 分数,拒绝为未知或接受为已知。
The OpenMax algorithm. Source: Abhijit Bendale and Terrance E. Boult, Towards Open Set Deep Networks
与基于阈值 Softmax 概率的朴素方法相比,使用这种方法,他们能够提高开集检测的准确性。
OpenMax performance. Source: Abhijit Bendale and Terrance E. Boult, Towards Open Set Deep Networks
因此,OpenMax 基本上是神经网络的替代最终层,取代了优秀的旧 Softmax。但是,这一层是不可训练的!因此,它不会让你的神经网络在开集识别方面更聪明,它只是以更聪明的方式使用它的预测。这似乎是一个错失的机会。有没有办法训练一个网络来识别未知?
着眼于已学习的表示:嵌入空间中的开集识别
让我们深入了解神经网络是如何看待数据的!为了简单起见,让我们看看 LeNet-5,这是字符识别的经典架构,由 Yann LeCun 及其同事在改变游戏的论文基于梯度的学习应用于文档识别中提出。
The LeNet architecture. Source: Yann LeCun et al., Gradient-Based Learning Applied to Document Recognition
如您所见,网络的输入是原始数据本身。这可以被认为是一个真正高维空间中的向量,在我们的例子中是 32 x 32。如果你能在这个高维空间中看到与我们的训练数据集相对应的所有向量,你可能会认为与每个类相对应的子集是相当混乱的。基于这种表示,没有简单的方法来区分类。这正是神经网络最初看到的。然而,对于每一层,它都连续地将数据转换为越来越有形的表示,最终输出一个非常简单的表示:低维单纯形(三角形在多维中的推广),每个顶点对应一个类。
就我们的目的而言,最有趣的表示是上一个之前的表示。最后一种表示——输出——有点不自然,因为它被限制在一个维度等于类数量的空间中。正如我们之前看到的,在这个表述中没有未知的空间。但是,这对于倒数第二层的输出来说就大不一样了!这通常称为嵌入,嵌入向量代表数据的高级特征表示。在这个嵌入空间中,理想情况下,每个类都应该是一个独立的集群,与其他类分开。在这个空间里,你会把未知数放在哪里?好吧,如果每个类确实由一个簇表示,那么一个开集例子应该远离任何已知的簇。
沿着这个思路,Hassen 和 Chan 在他们的论文(学习基于神经网络的开集识别表示)中开发了一种方法,旨在训练网络来实现这一点。它们引入了一种新的损耗,将集群彼此推得更远,并将集群本身挤压在一起:
ii-loss.
ii-loss 可以附加到嵌入层,产生以下设置。
ii-loss setups. Source: Mehadi Hassen and Philip K. Chan, Learning a Neural-network-based Representation for Open Set Recognition
嵌入空间中的开集识别原则上很简单:只需将落在聚类之外的点分类为未知。这种方法是对 OpenMax 的改进,但是它仍然错过了非常重要的一点:它没有明确地教会网络识别未知。这样我们会获得更好的开集识别性能吗?
教神经网络知道它不知道的东西(真的)
我们在第一个例子中已经看到,不确定性不是识别开集例子的好方法:网络可以以非常高的置信度将未知的例子分类为已知类的成员。然而,在这个例子中,我们在训练期间没有向网络显示任何未知实例。按照公开的术语,套用美国前国防部长唐纳德·拉姆斯菲尔德的话:有已知的未知和未知的未知*。前一个类由培训期间可用的实例组成,尽管不是我们感兴趣的。如果我们用这些来训练未知的网络,并显示这些是你应该不确定的例子,会怎么样?*
这是 Dhamija 等人在他们最近的论文中提出的想法,他们引入了两个新的损失函数来将未知的例子从已知的例子中分离出来:熵开集损失和物圈损失。它们是如何工作的?
作者的第一个观察结果是,通过为专门在 MNIST 训练的网络可视化 MNIST 数字和梵文手写字符的特征表示,未知的例子往往在某种程度上围绕原点聚集。
Softmax activations of MNIST digits and Devanagari handwritten characters of a network trained exclusively on MNIST. Colored dots are MNIST classes, black dots are unknowns. Below are histograms of Softmax activation values for both classes. Source: Akshay Raj Dhamija et al, Reducing Network Agnostophobia
为了利用这一点,他们引入了一个新的损失,称为熵开集损失*,它将未知实例的 Softmax 分数驱动到均匀的概率分布。*
Entropic Open Set loss. On the top: loss when instance known. On the bottom: loss when instance is unknown. Source: Akshay Raj Dhamija et al, Reducing Network Agnostophobia
让我们停下来研究一下这个问题。对于具有已知类别(定义的顶部)的样本,这只是好的旧的交叉熵损失。当 Softmax 分数将概率 1 赋予真实类别时,交叉熵被最小化。然而,在定义的底部,我们看到了一些有趣的东西。这是负对数似然向量的平均值,当 Softmax 向量中的所有概率相等时,该值最小!实际上,这个损失告诉网络“这个实例是未知的,你现在应该是不确定的”。
所以,让我们假设我们已经用熵开集损失代替了我们通常的交叉熵损失。我们的要素制图表达会发生什么情况?事实证明,这种损失有一种特殊的影响:它使未知样本的范数下降!
Feature magnitudes for networks trained with and without Entropic Open Set loss. Source: Akshay Raj Dhamija et al, Reducing Network Agnostophobia
我们能增强这种效果吗?熵开集损失并不直接影响特征量级:未知样本接近最优的分数仍然可以有很大的量级,只要它们的激活分数对于每个类都是相似的。为了实现这一点,作者为这个损失函数引入了一个新术语。他们把这种新的损失统称为大气层损失。
Objectosphere loss. Source: Akshay Raj Dhamija et al, Reducing Network Agnostophobia
如我们所见,第二项迫使已知类中的样本具有较大幅度(顶行),而迫使未知样本具有较小幅度(底行)。这些术语共同实现了开集识别任务的相当大的改进。
Correct Classification Rates at different False Positive Ratios. Source: Akshay Raj Dhamija et al, Reducing Network Agnostophobia
开集识别的状态
正如我们之前看到的,开集识别在过去的几年里取得了很大的进步。然而,我们离一个强大的通用解决方案还很远。尽管它在实际应用中很重要,但却是一个被忽视的话题。然而,对于任何给定的问题,甚至不可能集合一个训练集来覆盖所有可能的情况并包括所有相关的知识。在许多情况下,领域专家甚至不知道这一点。想想细胞生物学家,他们使用显微图像来分析细胞表型,或许还能发现新的表型。如果一个表现型真的未知,你怎么能提前推理出来呢?
在我个人看来,关于深度学习的真正有趣的问题始于我们研究神经网络如何超越已知进行概括。对人类来说,这是智力的本质。想一想:随着你不断积累知识和个人成长,最能推动你前进的一句话是什么?
“我不知道。”
参考文献。
[1] A. Bendale 和 T. E. Boult,迈向开集深度网络 (2016),IEEE 计算机视觉和模式识别会议(CVPR),2016,第 1563-1572 页
[2] M. Hassen 和 P. K. Chan,学习基于神经网络的开集识别表示法,(2018) arXiv 预印本
[3] A. R. Dhamija 等人,【T8
如果你喜欢把机器学习概念拆开,理解是什么让它们运转,我们有很多共同点。看看我的博客,我经常在那里发表这样的技术文章!
大数据是否承诺在未来给每个人带来巨大的好处?
大数据对话
以下是未来 12 个月大数据的预期
可以毫不夸张地说,过去大多数企业的运营就像一个新手用不同材料制成的子弹瞄准目标,希望一些(如果不是全部)能坚持下来。
不管是好是坏,自动化时代带来了智能机器,它们正在越来越多的领域挑战人类的优势。大数据、机器学习和自动化现在正不经意地帮助企业每天做出高效、更智能的决策。
数据驱动的经济
大数据正在对全球经济产生重大影响。到 2021 年,全球大数据市场预计将增长至近 670 亿美元。根据 Andreessen Horowitz 的说法,世界上 90%的数据都是在过去的二十年里产生的。如今,每天都有 2.5 万亿字节的数据被创建出来,而且这一速度在未来几年还会加快。事实证明,学习如何理解这些海量数据对各种规模的企业都大有裨益。欢迎来到数据驱动的经济,在这个经济中,所有伟大的商业决策都是由数据驱动的。
对企业的好处
随着数据以如此快的速度增长,企业主适应数字化转型变得前所未有的重要。这是每个企业家在未来几年必须了解的事情,以便他们能够找到充分利用大数据潜力的方法,并最大限度地提高生产力和投资回报。
大数据可以为企业带来巨大好处的几种方式有:
- 快速获得更准确的答案
对于一个企业家来说,一个简单的问题,比如“谁是我的 10 个最好的客户?”可能需要几个月的研究才能找到答案。一个业务团队可能需要 60 天或更长时间来分析一切,以得出此类问题的最佳答案,即使这样,它也可能是非常错误的。但是,在强大的大数据商业智能解决方案的帮助下,回答这些问题只需几个小时。大数据的最大好处之一是能够更有力地提问和回答问题。整个回答复杂问题的过程可以从几个月缩短到几天甚至几分钟。
- 更好地了解消费者并预测他们的行为
“到 2025 年,将有超过 150 兆字节(150 万亿千兆字节)的数据需要分析.”— 福布斯
市场研究是受益于大数据革命的一个领域。对大型数据集和尖端云技术的可访问性使公司能够在短短几分钟内收集和分析超过一百万条信息。预测分析和深度学习的进步进一步简化了这一过程,使企业能够提高其营销战略的成功率。然而,许多消费者数据是无用的,因此关键是通过研究转化的客户类型和迫使他们进行购买的行为因素来收集正确的数据。
通过显示消费者购物和与企业互动的模式,数据还可用于预测消费者行为。通过确定客户需要什么以及何时需要,可以利用这一点为客户提供相关的解决方案。这种大数据应用最常被引用的例子可能是塔吉特如何在一名少女的父亲怀孕之前发现她怀孕了。
- 探索趋势
谷歌是世界上最大的数据农业公司之一,它提供谷歌趋势,允许用户根据术语或关键字搜索热门趋势。有了这样的工具,公司可以很容易地找到合适的模式,这有助于他们构建未来的产品。
- 目标广告
“经过多年的谨慎热情,营销和广告技术部门现在能够大规模接受大数据。”安德鲁奖章
企业在投放广告中损失了数百万美元,结果证明是灾难性的。当人们很少或根本不关注研究阶段时,就会发生这种情况。大数据可以让公司在开展新活动之前获得准确的客户洞察,从而节省人力资源。这一过程是通过广告商和营销人员使用的类似方法进行的,包括监控客户的在线活动、销售点交易和客户趋势的变化。结果,最终的活动变得更有针对性,只针对正确的受众。
- 风险管理——用准确的数据增强信心
不管是哪个行业,风险管理计划对任何企业来说都是一项重要的投资。能够预见潜在的风险并在风险发生前降低风险对于企业保持成功至关重要。事实证明,大数据分析在开发卓越的风险管理解决方案方面发挥了重要作用。这些解决方案允许企业对他们经常面临的风险进行量化和建模,然后使他们能够做出更好的决策,以创建更智能的风险缓解策略。
对消费者的好处
如今,大数据完全是为了增强客户体验。从向用户推荐他们想看的节目到建议购买的产品,数据正在让公司在你能想到的每个领域赢得人心。事实上,消费者现在 期望 品牌监控他们的在线活动,以便他们能得到更好的服务。
Big data is watching — for good!
以下是大数据向未来消费者承诺的更多好处:
- 更智能的个性化购物体验
智能聊天机器人、虚拟造型师和类似的产品推荐是大数据革命带来的众多创新中的几个。欢迎来到客户时代,在这个时代,各公司都在努力通过数据的力量为客户提供卓越的客户体验,从而让客户满意。
- 降低成本,获得更好的交易
利用数据进行有针对性的营销,不仅能为客户提供相关优惠,还能帮助企业降低产品和服务的价格。向 20 万目标明确的潜在客户发送电子邮件的成本与向整个城市进行营销的成本相比,可能会对公司提供的产品和服务的总成本产生重大影响。因此,对于各种规模的企业来说,数据都是降低成本的重要工具。
- 通过消费者偏好的渠道改善沟通
未来,大数据和自动化承诺客户可以在一天中的任何时间,通过他们首选的渠道,在他们首选的设备上,更快地响应他们的查询。
数据驱动的世界
这仅仅是大数据能够为世界带来什么的开始。数据永不停息,每一秒钟都在继续增长,随之而来的是数据造福人类的可能性越来越多。随着技术的不断进步,越来越多的组织越来越容易获得数据。因此,这些组织有责任确保信息技术在未来以最佳方式为消费者服务。
差异中的差异方法实践指南
实验和因果推理
卡德和克鲁格论文的翻版:“工资上升,就业率下降?”
Photo by Dean Nahum on Unsplash
执行摘要
- 在完全竞争的市场中,传统经济理论预测最低工资的增加会导致失业率上升。
- 横断面研究提供了相互矛盾的证据,但不是因果关系。
- 卡德和克鲁格采用了一种 DID 方法,发现工资增长会带来更高的就业率。
Photo by Alexander Mils on Unsplash
前言
在这篇文章中,我将复制 Card 和 Krueger 的论文,一步一步地解释,并补充关于准实验设计的定义、假设、R 代码和潜在结果框架解释的附加信息。
什么是准实验?
准实验设计是一种没有真正随机化过程的实验设计。由于缺乏随机分配,治疗组和对照组在干预前是不相等的。因此,这两组之间的任何差异都可能是由先前存在的差异造成的。
这种准设计受到了政策分析师、医疗保健提供商和直接面向消费者的公司(特别是网飞和 Airbnb)的欢迎。
为什么是准实验设计?
在其他帖子中,我解释了实验研究的好处,以及如果可能的话,为什么它们应该是因果推断的首选。那么,我们为什么不一直进行实验呢?
很棒的问题!一个简单的答案是,实验设计对某些类型的问题并不适用。例如,将人们随机分配到可能损害他们健康的危险环境(如吸烟)是不道德的。
在政策领域,我们不能随意指定加州而不是纽约获得新的税收优惠。
此外,在实验设计中,实验组和对照组之间存在溢出效应。网飞没有对某些类型的问题进行 A/B 测试,而是依靠准实验性的解决方案(在本文中,网飞解释了为什么 A/B 测试并不总是可行)。
在这种情况下,当完全成熟的实验研究不可行时,准设计就派上了用场。
“准实验的结果不会像 A/B 那样精确,但我们渴望对因果关系进行定向解读。”
Photo by Christian Regg on Unsplash
背景
1989 年 11 月签署成为法律的一项法案将联邦最低工资从每小时 3.35 美元提高到 3.8 美元,于 1990 年 4 月 1 日生效,并于 1992 年 4 月 1 日从每小时 4.25 美元进一步提高到 5.05 美元。新泽西州经历了工资上涨,但宾夕法尼亚州没有。戴维和克鲁格在涨价前后进行了两轮调查。
一个简短的时间表可能有所帮助:
- 1992 年 2 月和 3 月:第一轮调查
- 1992 年 4 月:新泽西州最低工资从 4.25 加元提高到 5.05 加元
- 1992 年 11 月和 12 月:后续调查
以下是我们运行准设计的原因。#1 新泽西和宾夕法尼亚在很多方面没有可比性。#2 立法过程不是随机的。
然而,我们可以根据 DID 方法确定工资增长对失业率的因果影响。
准实验设计不需要同等组。
潜在成果框架 分析研究
这是注释。设 D 代表是否接受治疗,T 代表时间,I 代表研究对象数量。
Di = 1:新泽西接受待遇(最低工资增加)
Di = 0:宾夕法尼亚州不接受治疗
T=1:工资增长后(1992 年 11 月和 12 月)
T=0:工资增长前(1992 年 2 月和 3 月)
y:结果变量(失业率)
I made this
Based on the poor handwriting, it’s my credits.
有一个潜在的问题。我们不知道对照组(宾夕法尼亚州)如果接受治疗会有什么表现(missing E[Y0i(1)| D = 1】)。
我们可以用 DID 的方法解决这个问题:
****ATTE[Y1(1)—Y(0(1)| D = 1]=
{ E[Y(1)| D = 1]—E[Y(1)| D = 0]}—{ E[Y(0)| D = 1]—E[Y(0)| D = 0],假设平行趋势。
平行趋势假设意味着如果没有治疗,治疗组和对照组之间的差异将保持不变。在这种情况下,如果没有工资增长法,新泽西州和宾夕法尼亚州的就业率之间的差异将是相同的。
R 分析:
**# Credits to Jonathan Mummolo**d <- read.csv(“wage_data.csv”,convert.factors = FALSE)
head(d[, c(“ID”, “nj”, “postperiod”, “emptot”)])with(d,
(
mean(emptot[nj == 1 & postperiod == 1], na.rm = TRUE) — mean(emptot[nj == 1 & postperiod == 0], na.rm = TRUE)
)-
(mean(emptot[nj == 0 & postperiod == 1], na.rm = TRUE) — mean(emptot[nj == 0 & postperiod == 0], na.rm = TRUE)
)
)ols <- lm(emptot ~ postperiod * nj, data = d)
coeftest(ols)
为了控制地区和时间差异,我们可以建立一个固定效应回归模型,该模型具有单位和期间固定效应。
#A set of estimators and tests for panel data econometrics
library(plm)
library(lmtest)
d$Dit <- d$nj * d$postperiod
d <- plm.data(d, indexes = c("ID", "postperiod"))
did.reg <- plm(emptot ~ postperiod + Dit, data = d,model = "within")
coeftest(did.reg, vcov=function(x)
#Heteroskedasticity-Consistent Covariance Matrix Estimation
vcovHC(x, cluster="group", type="HC1"))
****
The original paper, Table 3
在将其与原始表进行比较后,我们成功地复制了结果!
原文是这里的。
复制数据集在这里是。警告:这是原始数据,我们需要处理它进行分析。
Medium 最近进化出了自己的 作家伙伴计划 ,支持像我这样的普通作家。如果你还不是订户,通过下面的链接注册,我会收到一部分会员费。
** [## 阅读叶雷华博士研究员(以及其他成千上万的媒体作家)的每一个故事
作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
leihua-ye.medium.com](https://leihua-ye.medium.com/membership)**
喜欢读这本书吗?
还有,看看我其他关于人工智能和机器学习的帖子。
薪酬会影响科技行业的忠诚度吗?简单数据可视化研究。
旧金山的技术领域以敏捷著称:公司转向,产品更新,员工跳槽。为一家公司工作,当员工达到一年或两年的纪念日时,该公司会庆祝他们,这种情况并不少见。这种情况不仅发生在初创公司(通常只有几年历史),也发生在大型企业。由于劳动力市场的泡沫化,员工们已经习惯了每周(如果不是每天的话)来自脸书招聘公司、合同招聘公司和代表他们投资的风投公司的连珠炮。
看来招聘人员才是这个行业的真正赢家:因为挖人而获得奖励,但很少因为留住员工而获得奖励。但是肯定有一些公司已经想出了如何留住员工,从而停止无休止的 LinkedIn 挖掘、电话筛选、杠杆审查循环,这些循环会消耗团队的时间。
带着这样的想法,我很兴奋地偶然发现了去年围绕这个问题发布的调查数据。Blind 是一款应用程序,时尚、大型科技公司的员工可以匿名参与讨论话题。在本次调查中,Blind 要求用户二对两项陈述做出回应:
- 我得到了公平的补偿
- 我对换工作/换公司感兴趣
然后,他们获取这些用户的雇主,并提供汇总结果。请记住,这是对非代表性员工样本的自愿调查数据,发现公司之间的差异仍然很有意思。Blind 将此描绘成一个堆积条形图。
虽然这张图有它的优势,你可以很快找到一家公司,并看到它在哪里,但我发现它(以及后来的出版物: BI 、 Inc 、 Dice 、 SFGate )在传达任何真正的洞察力方面令人失望。充其量,这是一张记分卡,告诉我们一家公司最终在哪里,但没有告诉我们为什么他们可能会在那里。
所以我深入研究了一下数据。首先,公司回应的分布讲述了一个有趣的故事。
在左侧,我绘制了一个直方图,显示了公司数量以及员工/受访者对“薪酬合理”这一说法的认同程度。大多数公司位于 40-70%的范围内,中间值正好是 50%。这意味着,大多数公司的“典型”感觉大致相当:员工(作为一个群体)没有被利用的感觉,也没有沉浸在薪资满足感中。
右边是“换公司”的柱状图。在这里,图表严重向右移动,中间值接近 70%。很少有公司的价值低于 50%。这意味着几乎所有 T2 主要科技公司的大多数员工都在考虑离开 T3!
但是这些有联系吗?换句话说,**付更多的钱会让人呆得更久吗?**虽然这里真正的黄金标准是进行一项受控实验(随机挑选一半的员工,提高他们的工资,监控留用情况),但我们仍然可以从盲目的数据中梳理出一些要点。
盲目地试图用一个双条形图来解决这个问题,该图筛选出了 30 多家公司中的 10 家,但我发现它太忙了,没有时间吸取任何教训。
通过将数据转换成散点图,每个公司用“公平补偿”协议(x-轴)与“考虑改变”(y-轴)来绘制,一些趋势开始出现。您可以将鼠标悬停在各个点上来查看公司。
很快你就能看到一个强烈的下降趋势,员工感觉收入高的公司很少有员工考虑离职。相关性在-0.59 处相当强。
因此,薪酬有着强烈的影响,这可能对我们大多数人来说并不奇怪。在网飞,几乎每个人的工资都很高(88%的人同意),很少有人有兴趣离开(27%),而在另一端,惠普企业(HPE)有工资问题(13%)和挽留问题(91%)。
但我会走得更远:你必须支付高薪来留住你的团队。这些调查数据显示,没有一家公司找到了留住人才的廉价良方;尽管所有的工作都是关于使命宣言,健康计划和战利品。一般来说,每个有薪酬差距的公司都有很高的变化考虑。
该图还显示,感觉收入丰厚的员工(图的右侧)仍然有很高的辞职率。在极端情况下,NerdWallet 受访者是对薪酬最满意的人之一(78%的人同意“我得到了合理的补偿”),但也是最不想留下来的人之一(90%的人同意“我想换工作/公司”)。Intuit 和 LinkedIn 的薪酬协议相似(分别为 61%和 63%),但 Intuit 的员工对离职的兴趣是 LinkedIn 的两倍(80%,LinkedIn 的 40%!).光靠高薪是不够的!
让你的公司在稳固的薪酬满意度上似乎是一个必要的,但不是充分的,解决员工保留的策略。在 SF tech 的旋转门文化中,它应该被认为是桌面上的标杆。我会从检查你的员工的脉搏开始:如果大多数人觉得他们早就该加薪了,那就等着看他们定期离开吧。
一些必须的脚注:
感谢盲人做调查。这是一个伟大的公关举措,我从来没有听说过这家公司,直到我听的一个播客选择了这个调查作为一个故事。
但是没有一个内容营销驱动的调查是完美的。数据现在已经有一年多了(所以我猜脸书已经看到了“对改变感兴趣”的增加……),并且对盲人用户有反应偏差和选择偏差。我可以想象一个系统性的问题,即正在考虑换工作的员工与盲人接触,以更多地了解其他公司。最重要的是,我使用的数字是我对盲人图表的手动解释。这将是很酷的,看看如何比较,比如说,玻璃门审查和工资数据。
最后,我将我的数据和 python 分析笔记本存储在 github 中,如果有人有兴趣的话。
你的产品有用吗?
随机对照试验、不完全依从性和反事实时间机器
我们开发软件来解决人类的问题。但是人类的问题可能是混乱的,有时并不十分清楚我们是否真的解决了它们。
Snapchat 可能会说,如果他们看到 50%的普通用户检查他们的新狗过滤器,他们就成功了,脸书可以说,他们已经打破了他们的增长里程碑,显示他们已经实现了超过 23 亿的月活跃用户。
但是,当你的应用程序被设计成帮助会员应对焦虑时,你的接受标准是什么?当你的软件被构建来培养正念时,你能监控什么标准?
或者,以我的公司为例——甚至——我们如何判断我们是否对会员的财务健康产生了影响?
我们与我们的移动应用高度互动,我们已经向我们的会员发送了价值超过 10 亿美元的工资,我们还自动为他们在雨天账户中节省了数百万美元。这些都是值得庆祝的事情。
但这还不够。
我们更直接关心的是,我们的产品是否能在物质上改善我们会员的生活。作为一名致力于了解我们功效的数据科学家,这基本上是我所关心的全部。
这是从度量优化到更像科学实验的地方。我需要了解的是我们的平均治疗效果——也就是我们在用户生活中造成影响的预期值。
为了解释我如何做到这一点,我将深入一种因果分析,这种分析被朱迪亚·珀尔在他的奇幻书和本文(与亚历山大·巴尔克合著)中分解。
如果你是数据驱动型组织的一员,在这个组织中跟踪应用程序的使用模式相对容易,那么这种分析与执行涉及产品对用户影响的实验高度相关。即便如此,我还没有看到甚至是最学术性的科技研究使用我将要深入探讨的那种思维。
快速警告:深度潜水将涉及一点科学方法、许多概率论、一点 Python 和一点线性编程。你不需要成为任何一个主题的专家来理解我将要讨论的内容,但是这几乎肯定需要一些时间,努力,也许还需要一些背景阅读。
不过,我向你保证,这很酷,值得一试。
让我们从科学复习开始:随机对照试验。
随机对照试验
相关性不是因果关系——我们感兴趣的是因果关系。我们希望让成员的生活得到改善。不过,在我开始宣扬“因果关系”之前,先定义一下它是有用的。的反事实定义是我个人认为最清楚的一个:
事件 A“引发”了事件 B,当且仅当,我们把事件 A 从历史中删除,事件 B 就不会发生。
成为一个原因就是成为引发连锁反应的多米诺骨牌,成为引爆炸药的导火索。如果你消除了这个原因,无论发生什么都不再发生了。
为了研究因果关系,我们可以去除我们认为是因果关系的东西,看看它的影响是否仍然存在,其他一切都是一样的。这就是“受控试验”试图做的事情。
我们自然一直在做对照试验。想想你上一次尝试安装一盏新灯,却发现它不起作用。你是如何着手解决这个问题的?
你可能对哪里出了问题有一些想法。灯泡可能已经烧坏了。或者你插的插座是个哑弹。
让我们取其中的一个想法,正式称之为我们的假设。
**假设:**插座不起作用,这意味着没有电力可以到达灯泡,它不能点亮。
我们如何检验这个假设?嗯,我们有一个试验,我们尝试了当前的插座,插座 a。这是我们的治疗试验——我们用我们认为导致我们最终黑暗和沉闷状态的输入来治疗我们的系统。
现在我们需要一个控制试验——我们把插座 A 换成一个我们知道有效的插座:插座 B,它已经忠实地为我们的手机充电几个月了。系统中的一切都保持不变,除了插座。
在我们进行这个试验之前,让我们尽可能正式地设计这个实验。我们寻找的是插座 A 对房间照明的平均处理效果(ATE)。
Treatment Effect = The probability of a non-functional lamp given that we use Outlet A, minus the probability of a non-functional lamp given that we use Outlet B.
我们已经知道 P(黑暗|出口 A) = 1 。如果当我们将插座 A 与插座 B 交换时,房间仍然是黑暗的,那么 P(黑暗|插座 B) = 1 也是如此,因此 ATE = 0 。这意味着插座是我们问题的 0%原因。
但是,如果我们把灯插到插座 B 上,灯瞬间就亮了,那么 P(暗度|插座 B) = 0 ,我们的 ATE = 1。或者换句话说,插座 A 100%是我们问题的原因!
所以,让我们把灯插到插座 b 上。砰:
…Surprise! We were talking about a lava lamp this whole time. Now the living room of your imagination is just a tiny bit more whimsical. Source: Warisan Lighting
灯亮了;出口 A 是黑暗的原因。
问题解决了。
就像我说的,我们一直在做这种事情。对使用我们软件的人进行对照试验的复杂之处在于,其中涉及到一个特别棘手的变量:人。
虽然家用电器(通常)是完全确定的,但人却不是。没有一个人是相同的,他们使用你的产品的方式和对它的反应经常会让你吃惊。他们中的一些人会下载它并忘记它,一些人会每天登录。你的一些成员可能会从这个产品中得到帮助,但是——这是一个可怕但必要的想法——他们中的许多人可能会受到伤害。
当你的实验的一个输入变量如此多变时,你如何对你的产品进行受控试验?
这就是统计学介入的地方。我们不能再像在确定性系统中那样做单一的对照试验和单一的治疗试验。我们需要做数百次试验。成千上万。
每次试验将针对不同的人。重要的是,将一个人分配到控制或治疗条件的标准是完全随机的。这确保了在每种情况下的实验参与者的样本在总体上或多或少是相同的:他们将有来自每种性别、身高、收入水平、性格等的相同比例的人。不在审查范围内的因素的影响应该会互相抵消。
到目前为止,我们已经把相当多的片段放在一起:我们控制着一个单一的解释变量,并且随机化以减轻我们没有研究的一堆外生变量的影响。我们现在有了一个随机对照试验(T12)和一个研究什么导致什么的黄金标准(T13)。
但是故事还没有结束。我们可以将人分配到治疗状态(被分配使用你的产品的人)和控制状态(不使用你的产品的人),但是谁敢说你的参与者真的会遵守你的分配呢?
谁能说你的治疗组的参与者真的会下载并使用你的软件,或者你的对照组的人不会在应用商店找到它并试用它?
当你不知道参与者是否真的接受了你的治疗时,你不能进行因果归因。所以。我们如何做到这一点?
处理不完全合规
让我们回顾一下我们在 RCT 的设置。
- 我们将参与者随机分配到治疗组或对照组。
- 他们可能决定服从他们的任务,这取决于一些不可观察的因素。
- 他们会以某种方式对你的产品作出反应(或缺乏产品),这取决于他们是否接受了治疗,以及一些不可观察的因素。
我们可以描述这些事件如何与贝叶斯网络相互作用,如下所述。
Bayesian Network description of an RCT: This diagram describes conditional dependences of the events we’d expect to see. Z is completely independent of anything else, since it’s done via random coin-flip. U is a catch-all variable for the whole universe of unknowns that affect X and Y, and is also conditionally independent from other variables. X would be conditionally dependent on Z and U. Y would be conditionally dependent on X and U.
我们将使用 Z 、 X 、 Y 和 U 符号来简写它们在该图中代表的随机变量。例如,当我们提到 Y 时,我们谈论的是参与者可能意识到的结果变量(或者是好的结果,或者是坏的结果)。使用小写字母, y ,表示随机变量的实际实现(例如 Good )。
这种图表只是一种方便的方式来描述我们可能如何计算一些联合的概率 Z 、 X 、 Y 、 U 配置(例如,“ Z = 治疗、 X = 真、 Y = 好、用象征性的术语来说,这个图表是在说:
根据图表/表达式,你或许可以说出一些直观的东西:
- 知道 X = x 改变了 Y 等于特定 y 的概率。
- 知道 Z = z 和/或 U = u 改变 X 为特定 x 的概率。
- 知道 Z = z 不会给我任何关于 u 值 U 可能是什么的额外信息。
我们所做的就是在这里捕获条件依赖。
然而,我们的最终目标是能够计算出平均治疗效果,即:
i.e: The probability of having a good outcome given that we force a participant to take the treatment, vs. the probability of a good outcome given that we force them not to take the treatment. This difference is the ‘goodness’ directly attributable to our intervention
注意那个 do() 操作符,那里。也就是说,我们想知道当我们迫使 X 进入特定状态时,好结果的概率是多少——而不仅仅是被动地观察它。
问题是,在 RCT,我们从来没有强迫任何人做任何事情。我们让参与者接触到产品,然后他们想做什么就做什么。我们能做的就是被动观察!
有鉴于此,一个幼稚的方法可能是宣布:
但这是一个致命的错误。
我们必须记住,不同的潜在因素*、*由 **U、**表示,驱动着参与者接受治疗和不接受治疗的案例。同样的情况很可能会影响他们获得良好结果的可能性,这将会混淆我们对治疗效果的描述。
例如,在 Even 的案例中,选择定期使用该应用程序的成员可能天生就比那些不经常使用的成员更富裕(反之亦然)。在这种情况下,我们会看到一个高比率,但这并不能说明它对人的影响——它只是选择偏差的虚假结果!
我们想要的是能够比较给予治疗的良好结果的机会与不治疗的良好结果的机会,其中所有其他因素都是固定的*。*看起来更像这样:
Here we’re making sure that we’re only capturing the difference in P(Y = Good) between the treated (X = True) and untreated (X = False) groups given the same unobserved condition (the same u), for all possible unobserved conditions (all u ∈ U)
好吧,我们有点进展了。我们有一个如何将实验观察转化为 ATE 的表达式…但是这个表达式是没有用的,除非我们找到某种方法来理解什么样的 u 态是 U 的元素,这样我们就可以正确地控制这些态。
但是 U 是这个不可思议的随机变量,它应该捕捉影响人们为什么决定尝试一种产品以及他们可能如何反应的整个未观察到的因素。
你怎么能开始分解它呢?
让我们把问题尽可能简化。我们不需要模拟人们的神经生理学,或者天气,或者股票市场,或者任何能够影响日常决策的无限因素。
让我们考虑一下哪些事情会影响我们的实验结果。我们知道 U 影响 X 和 Y —即 U 包含了人们的遵从行为(他们是否使用了该产品)以及他们的反应行为(他们是否变得更好了)。
我们可以把未被观察到的宇宙中的无数因素归纳成几大类,然后:决定参与者顺从和反应行为的原型。
我列举了一个这样的方案如下:
合规行为类型
- 总是接受者——无论我们如何分配,他们都能获得产品。
- 服从者— 他们服从小组分配。接受治疗的人下载并使用产品,而对照组的人则没有。
- 否认者— 他们做了与他们被指派做的相反的事情。对照组的人找到了使用该产品的方法,而治疗组的人从未使用过。
- 从不接受者— 他们从不接触产品,不管任务是什么。
反应行为类型
- 总是更好— 无论是否使用该产品,他们都会有好的结果。
- 帮助— 如果他们使用该产品,将会有良好的结果。
- 伤害— 如果他们使用该产品,结果会很糟糕,但如果不使用,结果也会很好。
- 再好不过了 —无论他们使用我们的产品,都不会有好结果。
实验中的所有参与者必须恰好有一种遵从行为类型和一种响应行为类型,因为它们被定义为互斥的。所以你可以把每一个人都描述成属于一个(顺从,回应)行为对,给我们一个人可能的 16 个原型。
我想这有点像 Myers-Briggs——除了这个框架实际上对科学研究有用(T21)。
It’s like a horoscope! Except it sorts people into groups that aren’t hot garbage
太好了,现在我们知道了 U 可以像*(总是接受者,被帮助)或(从不接受者,永远不会更好)一样接受 u 值。参与者可能属于特定的 u 的原因对于我们的分析并不重要——我们只需要知道uu是什么*。如果我们知道 U 的分布,我们实际上可以为 ate 制定一个简单得多的表达式:
We’re marginalizing the compliance behaviors in this expression — P(U=helped) is actually a union of all P(U=u) where u has a ‘helped’ response type, for example.
但是怎么才能知道 U 的分布呢?
…好吧,事情是这样的:我们永远不会知道这种分布是什么。那是不可能的。在某些实验场景中,你怎么知道一个人是否会“好得不能再好”呢?这根本说不通。
在这一点上,你可能会通过你的电脑对我大喊大叫,说我浪费了你的时间。为什么我们刚刚经历了所有这些麻烦审议,结果却被卡住了?许多研究走捷径,根本不涉及 U 或 X 或任何像我们设置的图表那样复杂的东西!
例如,医学研究中一个非常标准的做法是将 ate 表述为如下形式:
这被称为意向性治疗分析,它认识到了自己名字中的缺陷:它测量的是意向给某人治疗(治疗或控制的任务)的效果,而不是他们是否真的接受了治疗。
你可能已经知道为什么我不是意向治疗的支持者,但是为了让我的不快真正发自内心,我将为你模拟一个实验。在本笔记本中跟随:
这是我们刚刚模拟的大量工作——我们招募了一些参与者,获得知情同意,跟踪他们一段时间,测量结果,查询我们的生产数据库以获得合规数据,进行一些汇总等。等等。最后我们得到了那 8 个美丽的值: Z 中每个 z 的 P(X,Y|Z=z) (这里是治疗和控制)。
你知道在关于蜘蛛丝及其神奇特性的纪录片中,叙述者会不断提到他们如何辛辛苦苦地为 14000 只义愤填膺的蜘蛛挤奶三个月,只为了得到一盎司的蛛丝?
The true cost of scientific progress. Base image source: Pexels.com.
我们的 P(X,Y|Z) 值是那盎司丝。它们很珍贵。
意向性治疗立即将它们抹去,并将其卷成两个粗略的数字:P(Y =好| Z =治疗)和P(Y =好| Z =对照)。
多么浪费有用的信息啊!这就像点燃我们一盎司的蜘蛛丝,然后系统地扇我们 14000 只已经痛苦不堪的蜘蛛的耳光。
How could you do this
这就是信息湮灭的悲剧:
必须有一些用于丰富 P(X,Y|Z) 信息。对吗?
反事实的时间机器
虽然我们永远无法知道 U 在我们的参与者群体中的分布情况,但我们知道 P(X,Y|Z) 的变化取决于 U 。或者换句话说,存在某个函数 U → P(X,Y|Z) 。
该函数可能是一对一或多对一的——但无论哪种情况,知道什么是 **P(X,Y | Z)**应该能够揭示 U 可能是什么。
除非它是一个活板门功能,在这种情况下,我们就完了。
不是虽然!实际上, U → P(X,Y|Z) 就是一个简单的线性函数,你很快就能直观地感受到。让我们仔细想想:
取量 P(X= 真,Y= 好 | Z= 处理 ) 。这个概率给了我们在治疗条件下接受治疗并有良好结果的人的比例。
但是我们可以得到这个值的另一种方法是,假设我们知道在 U 上的分布,将我们知道的总是接受治疗并好转的人的比例相加,以及服从治疗分配并好转的人的比例相加。
这让我们断言以下线性关系:
事实证明,我们拥有的每一个单独的 P(X,Y|Z) 值都是一组 P(U=u) 值的并集,就像上面的例子一样,这意味着 U 受到我们容易观察到的数据的约束!
这些并不是唯一的限制。我们还有概率规则在起作用:每个 P(U=u) 必须位于*【0,1】*区间内,所有 P(U=u) 的总和也必须等于 1。
除了这些限制,我们还想学习一个涉及到 U 的表达式:ATE,我们的圣杯。又来了:
Again, we’re marginalizing over the compliance behaviors in this expression — P(U=hurt) is actually a union of all P(U=u) where u has a ‘hurt’ response type
虽然我们没有工具来精确地解决 U 的分布——我们所做的都是线性优化问题的正确成分。
我们可以在可能的约束空间范围内,找出绝对最好和最坏的情况。这给了我们实际 ATE 值的硬边界。
我设置了这些约束,并使用 PuLP 进行了优化,这是一个 Python 库,它允许您用超级可读的符号表达式来构建这类线性编程问题:
请密切注意我们刚刚做的事情。使用一些假设和我们图表的结构,我们能够回到过去,看看如果我们生活在我们能想象的最幸福的时间线,有最高的可能 ATE,会发生什么。
使用同样的推理,我们也可以回到过去探索最黑暗的时间线(如果我们最小化而不是最大化)。
The darkest timeline. Source: Community.
如果你密切关注,你可能也会注意到一些相当惊人的事情。
意向性治疗分析——记住,这是分析人类参与者大多数实验结果的标准做法——宣布我们的治疗有 45%的 ATE,对参与者的结果有适度的积极影响。
但是当我们考虑治疗变量 X 时,我们看到最高可能的 ATE 是-15%。
治疗伤害人。
模型驱动与数据驱动的思维
从因果模型的角度思考,而不是把数据本身当成福音,是解开这种推理的关键。
我们没有被 RCT 提出的 8 种可能性困住,而是能够推断出某些东西对我们的实验参与者如何接受我们的治疗并对其做出反应负有责任。考虑到这一点,我们可以算出在不同的情况下会有什么样的结果。
我需要在这里对你说实话:在大多数情况下,这种分析会得到与意向治疗研究相同的方向性结果。我故意用了一个人为的例子,其中他们的结果是不同的。但重要的是要认识到,这种分歧一开始就可能发生,而且可能如此剧烈。
我认为许多从事应用统计学工作的人习惯于把我们看到的数据扔进我们众多古老而成熟的机器中。或者至少,我知道。这是个坏习惯。
权变表?进行卡方检验,然后转动曲柄。一张 2x2 的桌子和超低的样本量?把它扔进费希尔精确测试中,转动曲柄。映射到连续标签上的特征矩阵?把它放入线性回归中
转身。
那个。
曲柄。
很容易忘记数据的减少并不是分析的最终目的。理解并制作一个关于创造过程的心智模型,这些数据释放出一系列全新的力量。你可能从未意识到自己拥有的力量。
其中一些能力让你根本不需要进行实验就能进行因果推断。**
但那是以后的事了。
现在,我希望我已经给你的工具箱增加了一个可爱的新工具——更好的是,一个思考你的问题的新方法。
YouTube 的数据是否告诉了我们一个关于 2020 年民主党候选人的故事?
Photo by Philipp Lublasser on Unsplash
随着 2020 年总统大选在一年内举行,所有与弹劾无关的新闻都在谈论谁将成为面对特朗普总统的民主党候选人。
现有的信息来源包括新闻渠道和民意调查,但对我个人来说,我想看看我是否可以探索其他类型的公开可用数据。
作为一个每天在 YouTube 上花费大量时间的人,我决定从 YouTube 的数据 API 中获取数据,并设计自己的快速实验,看看这些数据是否会为民主党候选人竞选增添色彩,而传统渠道和民意调查无法提供这些色彩。YouTube 是一个非常棒的平台,因为创作者经常上传针对个人候选人的内容,内容表现可供每个人查看和使用。
提取数据的方法
每个快速数据实验都是围绕一些快速假设和规则设计的。以下是我使用的方法:
- YouTube 数据 API 获取数据。许多数据方法是围绕 YouTube 有配额限制这一事实设计的。
- 我调出了 2019 年 12 月 4 日的视频列表和 2019 年 12 月 6 日的统计数据
- 收集了 2019 年 11 月 20 日辩论的候选人名单。在写这篇文章的时候,我意识到卡玛拉·哈里斯已经退出,迈克尔彭博正在竞选。我很可能会在未来写一部续集。
- 在 2019 年 1 月 1 日之后上传的前 250 个视频中,他们的名字出现在搜索词中。
- 消除了跨越多个候选人的重复视频,如“DNC 市政厅— SNL”。因此,该分析不包含涵盖多个或所有候选人的视频。
- 查看、喜欢、不喜欢和评论的统计数据
- 将名单缩小到每个候选人观看次数最多的前 150 个视频。
- 已禁用喜欢和评论的视频被限定为该视频的 0 个喜欢、不喜欢和评论。
- 在 Excel 中快速处理数学和图表。还将附上表格。
数据告诉我们的是
虽然我们有很多方法可以深入数据,并做进一步的分析和细分,但我认为快速简单地浏览一下基本统计数据确实讲述了一个很好的故事,我们可以从中学到很多东西。
视图
浏览量相当于每个候选人有多少人观看了独特的视频。这总计约为 4.3 亿英镑。候选人之间的意见分歧是这样的:
Chart Representing Candidates’ Share of Unique YouTube Views
Table Representing Candidates’ Share of Unique YouTube Views
正如你在这里看到的,6800 万的浏览量属于乔·拜登,占了 15.8%的份额。他领先,紧随其后的是伯尼·桑德斯 15.6%,皮特·布蒂吉格 14.3%,杨安泽 13.6%,塔尔西·加巴德 11.7%,卡玛拉·哈里斯 11.3%,伊丽莎白·沃伦 10.8%,然后是科里·布克,艾米·克洛布查尔和汤姆·斯特耶加起来约 7%的显著下降。
喜欢
视图对于理解链接被打开和可能被观看的频率是至关重要的,但是视频赞告诉我们一些视图不能告诉我们的事情。喜欢更符合观众参与度。就向其他观众推荐什么而言,赞是 YouTube 算法的关键组成部分之一。
Chart Representing Candidates’ Share of Unique YouTube Likes
Table Representing Candidates’ Share of Unique YouTube Likes
厌恶
就成为观众反馈的良好标记而言,类似于“喜欢”,但以负面方式表达。
Chart Representing Candidates’ Share of Unique YouTube Dislikes
Table Representing Candidates’ Share of Unique YouTube Dislikes
评论
评论是敬业度的另一个重要部分。它们不一定一眼就能反映出积极或消极的参与度,但它们确实代表了哪些候选人被认为更具“争议性”
Chart Representing Candidates’ Share of Unique YouTube Comments
Table Representing Candidates’ Share of Unique YouTube Comments
比率
当谈到观察数据时,从基本数据中创造比率可以为我们的理解增加很多价值。然而,简单的统计数据并不总能说明全部情况,因此比率的存在有助于我们将事情放入背景中。这方面的一个例子是当我们从视频中查看“喜欢”时。一个有数百万次观看的视频会比一个有数千次观看的视频获得更多的喜欢,但这并不能真正告诉你它与观众的互动有多好。它也可以有数以百万计的厌恶。考虑到这一点,我决定看看下面的比率,它给出了一个关于“可爱度”的概念
- 点赞浏览量(百分比): 这简单地告诉我们候选人的视频每被观看 100 次就有多少人点赞。单独拥有这个比例并不意味着什么,但当与其他人进行比较时,它可以成为谁被认为更“可爱”的有用基准。
Likes to Views Ratio. Average is 2.3%
- 喜欢与不喜欢的比率: 这告诉我们一个候选人得到多少喜欢与不喜欢。与不喜欢相比,喜欢和不喜欢的比例很高的候选人可以被认为是非常可爱的。
Likes to Dislikes Ratio. Average is 10.3
从上面的分析中,我们可以看到,YouTube 告诉了我们一些如果我们只依靠新闻和民意调查获得数据时不一定会知道的事情。乔·拜登获得了观点,目前他在民调中领先,但当涉及到参与度和可爱程度时,YouTube 的观众似乎倾向于伯尼·桑德斯和杨安泽。
由于技术,我们与信息和媒体互动的方式自上次民主党人取代共和党人入主白宫以来发生了巨大变化。正因为如此,我认为我们还应该探索额外的方法来衡量和基准测试候选人,特别是在 YouTube 这样每天都在变大的平台上。
基于 CNN 的犬种分类
在今天的帖子中,我将向你展示如何制作一个非常有趣的应用程序,来检测一张照片中是人还是狗。此外,在图像中检测到狗的情况下,它会以很高的准确度告诉我们狗的品种。
可以通过这个 github 链接访问相关的存储库,在那里可以找到关于下载数据集和先决条件的说明。
在构建我们的分类器时,我们将遵循以下步骤:
- 步骤 0:导入数据集
- 第一步:探测人类
- 第二步:探测狗
- 第三步:创建一个 CNN 来分类狗的品种
- 第四步:训练 CNN 对狗的品种进行分类(从头开始)
- 第五步:训练 CNN 对狗的品种进行分类(通过迁移学习)
第 0 步:导入数据集
我们的第一步将是加载分为训练、验证和测试文件夹的数据集。
我们想把我们训练数据集中的狗分成 133 个不同的品种。
正如我们在下面的代码片段中看到的,我们将使用 6680 张狗的图片来训练我们将要使用的模型。我们将使用 835 验证图像来微调我们的参数,并在 836 测试图像上测试最终模型的准确性。当然,测试数据集将是模型以前没有见过的图像。
Snippet 1 : Loading the Dataset
第一步:探测人类
为了检测人,我们首先将三通道 RGB 图像(红绿蓝)转换成灰度。一个名为“ detectMultiScale ”的 OpenCV 函数对灰度图像起作用,并给我们一个检测人脸的“盒子”的坐标。稍后,我们可以使用它在我们正在绘制的图像上绘制一个蓝色的矩形,如下所示。
Snippet 2 : Detecting humans
第二步:检测狗 我们将使用 Keras 中的 resnet50 预训练模型来检测图像中的狗。这里的第一步是转换的 RGB 编码。jpg 图像到 BGR,然后根据从庞大的 Imagenet 数据库中获得的平均值和标准偏差对三个通道进行归一化。幸运的是,这是由 Keras 中 applications.resnet50 模块中的 preprocess_input 完成的。
Snippet 3: Resnet50
使用我们从 keras.applications 库导入的 ResNet50 模型,我们可以将图像分类到标签中。在 resnet 库中,任何编码为 151 到 268 的标签实际上都是“狗”。如果是这种情况,下面的函数将给出一个真布尔值,否则为假。
Snippet 4: Dog Detector
第三步:创建 CNN 对狗的品种进行分类
我们将使用下面的基本序列模型,并设计我们的 CNN 网络。
我使用了三个卷积层,每个卷积层后面都有一个 MaxPooling2D,以降低堆叠模型的复杂性。
最后,我们将使用 global_average_pooling 将 Max Pooling 图层中的每个要素地图转换为标量。
Snippet 5: Building the CNN Model
第四步:训练 CNN 对狗的品种进行分类(从头开始)
我们开始训练我们创建的模型,我们看到我们的验证损失不断降低,我们的准确性降低了 5 个时期,表明我们的模型正在学习。
Snippet 6: Training the Model with 5 Epochs
在 20 个历元时,有可能达到大约 4.5%的精度吗?当我们在这个数据集上运行 250 个历元时,我们能够达到%40+的准确度,即使有强大的 GPU 支持,这也需要相当长的时间,这就是为什么我们将使用迁移学习作为下一步。
第五步:训练 CNN 对狗的品种进行分类(通过迁移学习)
接下来,我们将使用预提取的“瓶颈特征”,这些特征是应用于我们的训练、测试和验证数据集的预训练库的输出。
我们将使用 Resnet50 库输出作为我们模型的输入,并使用这些瓶颈特性训练我们的模型。
Snippet 7: Loading bottleneck features
我们通过添加一个全局平均池层来创建一个简单的模型,该层将之前的每个特征映射总结为一个标量。密集层创建 133 个不同的输出,每个输出对应一个所需的标签。然后,softmax 激活将这些转换成概率。
Snippet 8: Define, compile and train the model
然后,我们现场测试我们的算法,看看它是否能正确预测加载图像路径中的狗的品种。我们将一张威尔士施普林格犬的图片加载到模型中,正如你在下面看到的,神经网络正确地对我们使用的样本狗图片进行了分类。
Snippet 9: Predict using the model
最后一部分连接了我们之前构建的所有函数,将有助于确定所提供的图像是人还是狗,或者两者都不是。
Snippet 10: Final algorithm
基于细胞神经网络和迁移学习的犬种预测
在本文中,我将演示如何使用 keras 和 tensorflow 来构建、训练和测试一个卷积神经网络,该网络能够在提供的图像中识别狗的品种。成功将由高验证和测试准确性来定义,准确性和召回分数在具有相似准确性的模型之间有所不同。
这是一个监督学习问题,特别是一个多类分类问题,因此可以通过以下步骤来解决:
- 积累标签数据。在这种情况下,这意味着用已知品种的狗编辑一个图像库。
- 构建一个能够从训练图像中提取数据的模型,该模型输出可以被解释以辨别狗的品种的数据。
- 根据训练数据训练模型,在训练期间使用验证数据验证性能
- 评估绩效指标,可能返回到第 2 步进行编辑以提高绩效
- 根据测试数据测试模型
当然,每一步都有许多子步骤,我将在后面详述。
序幕
训练一个神经网络的行为,即使是一个相对简单的网络,在计算上也是极其昂贵的。许多公司使用专用于此类任务的 GPU 服务器机架;我将在配有 GTX 1070 图形卡的本地电脑上工作,我将为这次练习招募该电脑。为了在您的本地计算机上执行这个任务,您必须采取一些步骤来定义一个合适的编程环境,我将在这里详细介绍它们。如果您对后端设置不感兴趣,请跳到下一节。
首先,我在 Anaconda 中创建了一个新环境,并安装了以下包:
- 张量流-gpu
- 朱皮特
- glob2
- sci kit-学习
- 克拉斯
- matplotlib
- opencv(用于识别图像管道中的人脸——不是必要的功能,但在某些应用中很有用)
- tqdm
- 枕头
- 海生的
接下来,我更新了我的显卡驱动。这一点很重要,因为驱动程序更新会定期推出,即使是像我这样使用了 3 年的卡,如果您使用的是 tensorflow 的现代版本,是否有必要使用最新的驱动程序来实现兼容性。在我的案例中,只有 5 个月大的驱动程序与最新版本的 tensorflow 不兼容。
最后,在新环境的 anaconda 提示符下打开 jupyter 笔记本,以便执行您的工作,并确保 jupyter 使用了正确的内核环境。如果不这样做,Tensorflow 可能会遇到问题。
作为健全性检查,在模块导入后,我可以调用以下代码来显示可用的 CPU 和 GPU。
from tensorflow.python.client import device_lib
print(device_lib.list_local_devices())
成功!这是我的 GTX 1070。
最后,我执行下面的代码块,它编辑 tensorflow 后端的一些配置参数,并防止将来出现一些运行时错误。
# tensorflow local GPU configuration
gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=0.8)
config = tf.ConfigProto()
config.gpu_options.allow_growth = True
session = tf.Session(config=config)
步骤 1:编译数据
在我的情况下,这是微不足道的,因为 Udacity 向我提供了 1.08Gb 的跨越 133 个品种的狗图像,已经在一个适当的文件结构中。适当的文件结构,在 CNN 用 keras 建立分类的情况下,意味着文件通过训练、验证和测试被隔离,并且在这些文件夹中通过狗的品种被进一步隔离。每个文件夹的名称应该是您计划识别的类的名称。
显然,世界上有超过 133 个狗品种——美国权威机构 AKC 列出了 190 个品种,而世界权威机构 FCI 列出了 360 个品种。如果我想增加我的训练数据集的大小,以包括更多的品种或每个品种的更多图像,我可以采用的一种方法是安装 python Flickr API,并在其中查询标记有我想要的任何品种名称的图像。然而,为了这个项目的目的,我继续使用这个基本数据集。
作为第一步,我将把所有文件名加载到内存中,以便以后更容易处理。
*# define function to load train, test, and validation datasets*
def **load_dataset**(path):
data = load_files(path)
dog_files = np.array(data['filenames'])
dog_targets = np_utils.to_categorical(np.array(data['target']))#, 133)
return dog_files, dog_targets# load train, test, and validation datasets
train_files, train_targets = load_dataset('dogImages/train')
valid_files, valid_targets = load_dataset('dogImages/valid')
test_files, test_targets = load_dataset('dogImages/test')*# load list of dog names
# the [20:-1] portion simply removes the filepath and folder number*
dog_names = [item[20:-1] for item in sorted(glob("dogImages/train/*/"))]*# print statistics about the dataset*
print('There are %d total dog categories.' % len(dog_names))
print('There are %s total dog images.\n' % len(np.hstack([train_files, valid_files, test_files])))
print('There are %d training dog images.' % len(train_files))
print('There are %d validation dog images.' % len(valid_files))
print('There are %d test dog images.'% len(test_files))
它输出以下统计信息:
There are 133 total dog categories.
There are 8351 total dog images.
There are 6680 training dog images.
There are 835 validation dog images.
There are 836 test dog images.
接下来,我通过将图像中的每个像素除以 255 来标准化数据,并将输出格式化为张量 keras 可以使用的向量。注意:下面的代码将数千个文件作为张量加载到内存中。尽管对于相对较小的数据集来说这是可能的,但最好使用批量加载系统,一次只加载少量的张量。我在后面的步骤中为我设计的最后一个模型这样做。
*# define functions for reading in image files as tensors*
def **path_to_tensor**(img_path, target_size=(224, 224)):
*# loads RGB image as PIL.Image.Image type
# 299 is for xception, 224 for the other models*
img = image.load_img(img_path, target_size=target_size)
# convert PIL.Image.Image type to 3D tensor with shape (224, 224, 3)
x = image.img_to_array(img)
*# convert 3D tensor to 4D tensor with shape (1, (target_size,) 3) and return 4D tensor*
return np.expand_dims(x, axis=0)def **paths_to_tensor**(img_paths, target_size = (224, 224)):
list_of_tensors = [path_to_tensor(img_path, target_size) for img_path in tqdm(img_paths)]
return np.vstack(list_of_tensors)*# run above functions*
from PIL import ImageFile
ImageFile.LOAD_TRUNCATED_IMAGES = True*# pre-process the data for Keras*
train_tensors = paths_to_tensor(train_files).astype('float32')/255
valid_tensors = paths_to_tensor(valid_files).astype('float32')/255
test_tensors = paths_to_tensor(test_files).astype('float32')/255
构建、培训、测试、评估
有无数种方法可以做到这一点,其中一些会比另一些更好。我将探索 3 种独特的方法,并遵循它们从构建到测试和评估。我采用的方法如下:
- **琐碎的解决办法。**我将在数据集上构建并训练一个非常简单的 CNN,并评估其性能。
- **具有瓶颈特征的迁移学习。**我将利用一个已在大规模图像库上训练过的现有 CNN,并通过使用它将我的输入图像转换为“瓶颈特征”:图像的抽象特征表示,使其适应我的应用程序。
- **图像增强的迁移学习。**类似于瓶颈特征方法,但我将尝试通过创建一个模型来获得更好的模型泛化,该模型是一个预训练的瓶颈特征 CNN 的堆栈,带有一个用于我的应用程序的自定义输出层,我将向它提供通过象形变换随机增强的输入图像。
首先,我将演示创建一个基本 CNN 并在数据集上训练它的简单方法。
步骤 2a:构建简单模型
我用下面的代码创建了一个简单的 CNN,使用 keras 和 tensorflow 后端。
from keras.layers import Conv2D, MaxPooling2D, GlobalAveragePooling2D
from keras.layers import Dropout, Flatten, Dense
from keras.models import Sequentialmodel = Sequential()*# Define model architecture.*
model.add(Conv2D(16, kernel_size=2, activation='relu', input_shape=(224,224,3))) # activation nonlinearity typically performed before pooling
model.add(MaxPooling2D()) # defaults to pool_size = (2,2), stride = None = pool_size
model.add(Conv2D(32, kernel_size=2, activation='relu'))
model.add(MaxPooling2D())
model.add(Conv2D(64, kernel_size=2, activation='relu'))
model.add(MaxPooling2D())
model.add(GlobalAveragePooling2D())
model.add(Dense(133, activation='softmax'))model.summary()
model.summary()方法打印出以下模型结构:
在这里,我创建了一个 8 层顺序神经网络,利用与最大池层配对的 3 个卷积层,并终止于具有 133 个节点的全连接层——我试图预测的每个类一个节点。注意在密集层我使用了一个 softmax 激活函数;原因是它的范围是从 0 到 1,并且它强制输出层中所有节点的总和为 1。这允许我们将单个节点的输出解释为模型的预测概率,即输入是对应于该节点的类。换句话说,如果层中的第二个节点对于特定图像的激活值为 0.8,我们可以说模型已经预测到输入有 80%的机会来自第二类。请注意 19,000 个模型参数——这些是我的网络将尝试优化的权重、偏差和核(卷积滤波器)。现在应该很清楚为什么这个过程需要大量的计算。
最后,我编译这个模型,以便它可以被训练。注意,这里我可以使用许多损失函数和优化器,但是当前多类图像标签预测的通用约定使用 Adam 作为优化器,使用分类交叉熵作为损失函数。我用 SGD 和 RMSProp 测试了 Adam,发现 Adam 的训练速度要快得多。
model.compile(optimizer=’adam’, loss=’categorical_crossentropy’, metrics=[‘accuracy’])
步骤 3a:训练平凡模型
现在我有了一个用来训练、验证和测试模型的张量列表,还有一个完整编译的 CNN。在我开始训练之前,我定义了一个 ModelCheckpoint 对象,它将作为一个钩子,我可以使用它来保存我的模型权重,以便将来轻松加载,而无需重新训练。为了训练模型,我调用。用我的关键字参数拟合模型的()方法。
checkpointer = ModelCheckpoint(filepath='saved_models/weights.best.from_scratch.hdf5', verbose=1, save_best_only=True)model.fit(train_tensors, train_targets,
validation_data=(valid_tensors, valid_targets),
epochs=3, batch_size=20, callbacks=[checkpointer], verbose=2)
正如您所看到的,我只运行了 3 个时期的模型,因为我知道由于它的简单性,它不会是一个高性能的模型,这个模型纯粹是为了演示的目的。模型训练给出以下输出:
模型完成训练,训练准确率为 1.77%,验证准确率为 1.68%。虽然这比随机猜测要好,但也没什么值得大书特书的。
顺便提一下,在训练这个模型时,我们可以看到我的 GPU 使用率立即跃升!这太好了——这意味着 tensorflow 后端确实在使用我的显卡。
步骤 4a:评估普通模型
该模型在训练或验证数据上没有达到合理的精确度,这表明它大大地低估了数据。这里我展示了一个模型预测的混淆矩阵,以及一个分类报告。
该模型预测了几乎所有输入图像的两类中的一类。似乎偏爱巴吉度猎犬和边境牧羊犬。不幸的是,我没有创造出有一只喜欢的狗的有知觉的 AI;在巴吉度猎犬和边境牧羊犬的训练集中,图片比大多数其他种类的图片要多一些,这是模型学来的。由于模型的严重欠拟合,不值得探究精度或回忆它在此时达到的效果。
步骤 5a:测试普通模型
最后,我在测试数据集上测试模型。
# get index of predicted dog breed for each image in test set
dog_breed_predictions = [np.argmax(model.predict(np.expand_dims(tensor, axis=0))) for tensor in test_tensors]# report test accuracy
test_accuracy = 100*np.sum(np.array(dog_breed_predictions)==np.argmax(test_targets, axis=1))/len(dog_breed_predictions)
print('Test accuracy: %.4f%%' % test_accuracy)
这产生了 1.6746%的测试精度——符合我的预期。如果我在更多的时期训练模型,我可能会达到更高的精度,但这个模型是高度简化的,修改我的架构将是一个更好的主意。很快,我将展示使用迁移学习建立模型的更好方法,这可以实现更高的准确性。
步骤 2b:构建瓶颈特征模型
我可以显著提高性能的一种方法是利用迁移学习,也就是说,我可以利用现有的 CNN,它已经过预训练,可以识别一般图像数据的特征,并根据自己的目的进行调整。Keras 有许多这样的预训练模型可供下载和使用。每一个都是在一个名为 imagenet 的图像库中训练过的模型,该图像库包含分布在 1000 个类别中的数百万张图像。在 imagenet 上训练的模型通常是具有许多完全连接的输出层的深度 CNN,这些输出层已经被训练为将卷积层暴露的隐藏特征分类为 1000 个类别中的一个。我可以采用这些预训练模型中的一个,简单地用我自己的完全连接层替换输出层,然后我可以训练这些层,将每个输入图像分类为我的 133 个狗品种中的一个。这里需要注意的是,我不再训练 CNN,我将冻结卷积层的权重和内核,卷积层已经被训练来识别图像的抽象特征,并且只训练我自己的自定义输出网络。这节省了大量的时间。
至少有两种方法可以解决这个问题。一种方法是将预训练网络和我的定制网络连接在一起,如上所述。另一种更简单的方法是,通过预训练的网络输入我的数据集中的每幅图像,并将输出保存为数组,以便稍后通过我的网络输入。后一种方法的好处是它节省了计算时间,因为每个训练时期我只通过我自己的模型进行前向传递和后向投影,而不是 imagenet 模型和我的模型一起进行。方便的是,Udacity 已经通过一些内置的 CNN 提供了他们提供的所有训练图像,并提供了原始输出或瓶颈功能,供我简单地阅读。
在这里,我定义了自己的全连接网络,以接受瓶颈特性并输出 133 个节点,每个品种一个。这是 VGG16 网络的一个例子。我在实际训练中使用不同的网络,这将在下一节中看到。
VGG16_model = Sequential()
VGG16_model.add(GlobalAveragePooling2D(input_shape=train_VGG16.shape[1:]))
VGG16_model.add(Dense(133, activation='softmax'))
这里需要注意一些事情:
- 我从 GlobalAveragePooling 层开始——这是因为 VGG16 的最后一层,事实上我测试的所有 imagenet 模型都是卷积/池序列。全局池层减少了该输出的维数,并且在输入到密集层时极大地减少了训练时间。
- 我的网络中第一层的输入形状必须适合它所设计的模型。我可以通过简单地获得瓶颈数据的形状来做到这一点。瓶颈特征形状的第一个尺寸被切除,以允许 keras 添加一个尺寸进行批处理。
- 我再次使用一个 softmax 激活函数,原因与简单模型相同。
步骤 3b:列车瓶颈特征模型
Udacity 为 4 个网络提供了瓶颈功能:VGG19、ResNet50、InceptionV3 和 Xception。下面的代码块读入每个模型的瓶颈特性,创建一个完全连接的输出网络,并在 20 个时期内训练该网络。最后输出每个模型的精度。
从最后一行可以明显看出,所有 4 个模型的表现都比我自己微不足道的 CNN 好得多,其中 Xception 模型达到了 85%的验证准确率!
步骤 4b:评估瓶颈特征模型
表现最好的——Xception 和 resnet 50——都取得了显著的验证准确性,但是通过挖掘日志,我们可以看到它们对训练数据的准确性接近 100%。这是过度拟合的标志。这并不令人惊讶,Xception 有 2200 万个参数,ResNet50 有 2300 万个参数,这意味着这两个模型都有巨大的熵容量,能够只记住训练数据图像。为了解决这个问题,我将对我的全连接模型进行一些更改并重新培训。
我已经添加了第二个密集层,希望模型能够对预训练参数依赖少一点,我还用 L2 正则化和丢弃增强了完全密集层。L2 正则化因高个体参数权重而惩罚网络,而丢弃在训练期间随机丢弃网络节点。两者都通过要求网络在训练过程中进行更多的归纳来对抗过度拟合。还要注意我已经改变了优化策略;在真实的研究环境中,这将通过 GridSearch 来完成,grid search 接受超参数列表(比如具有超参数范围的优化器),但是为了节省时间,我自己试验了几个。请注意,我已经切换回使用 SGD——通过实验,我发现尽管 Adam 训练速度极快,但如果给定足够的训练次数,SGD 始终会超过 Adam(这一发现在本文中有所暗示)。
训练 100 个周期(5 分钟)后:
该模型取得了与以前相当的验证精度,但训练精度要低得多。训练精度低是由于辍学,因为它从来没有使用完整的模型来评估训练输入。我很满意这个模型不再像以前一样过度合身。看起来验证准确性和损失都大致持平——可能再过 100 个纪元,我还能挤出 1 %- 2%的准确性,但我可以先采用更多的训练技术。
步骤 5b:测试瓶颈特征模型
在测试数据集上有将近 83%的准确率。与预期的验证集非常相似。看着混乱矩阵:
比上一部好多了。我们可以在这里看到,有几个品种的狗,模型表现相当好,有几个地方,它真的很难。看看这个例子,原因就很清楚了。
让我们放大 y 轴中间和 x 轴大约 1/4 处的异常值。
模型一致认为 66 级其实是 35 级。也就是说,它认为一只田野猎犬实际上是一只博伊金猎犬。这是并排的两个品种。
Field Spaniel (left), Boykin Spaniel (right)
注意到相似之处了吗?显然,区分这两个品种是一项极其困难的任务。我怀疑,在这种情况下,调整我的模型参数不会导致分类的有意义的改进,在真实的场景中,我会训练一个二元分类器来区分这些品种,如果主要模型预测了任一类别,则在分类预测管道中使用它。但是现在,我感兴趣的是通过增加我的训练数据来获得更好的表现。
步骤 2c:编译扩充输入模型
在根据图像数据训练的模型中,有一种引导训练数据的形式,称为图像增强,在训练期间,我可以对训练图像应用随机旋转、缩放和平移。这具有通过改变训练图像的像素同时保持内容的完整性来人为增加训练数据的大小的效果;例如,如果我将一只柯基犬的图像旋转 15 度并水平翻转,该图像仍然可以被识别为一只柯基犬,但是模型在训练期间将不会看到该图像。希望这项技术既能提高大量时期的模型精度,又能防止过度拟合。为了做到这一点,我不能再使用我以前使用的瓶颈特性,我必须一起编译整个模型,以便向前和向后传播。另请注意,由于我仍然不想编辑 imagenet 预训练模型的参数,我将在训练前冻结这些层。
首先,我定义了我的数据加载管道:
接下来,我加载 imagenet 模型,定义一个定制的完全连接的输出模型,并将它们组合成一个顺序模型。由于训练时间的原因,我在这里重新使用了 Adam。如果我有更多的计算资源,可能值得像以前一样使用 SGD。
步骤 3c:训练增强输入模型
这个模型的训练时间比我以前的任何模型都要长,因为每次向前传递都必须遍历 imagenet 模型的所有节点。在我的 GPU 上,每个 epoch 需要大约 3.5 分钟来训练,而瓶颈功能模型只需要几秒钟。这暴露了我们以前从使用瓶颈特性中获得的计算增益。
该模型在训练和验证数据集上非常快地实现了相对较高的准确性——这要归功于我切换到 Adam 优化器。请注意,训练精度仍然低于验证精度,这是因为我仍然在使用 dropout。另一件要注意的事情是验证准确性的高度变化。这可能是高学习率(看着你,亚当)或高熵容量(参数太多)的症状。随着时间的推移,它似乎变得平稳了,所以我并不担心。
步骤 4c:评估扩充输入模型
查看这个模型和以前的模型的分类报告,在验证过程中,两个模型的精确度和召回率都得了 0.80 分。两者都以大约 1 的验证损失结束,进一步表明没有改善。我希望看到由于训练数据的增加而导致的准确性的提高,但是我认为在这种提高变得明显之前,只需要更多数量级的训练周期。我怀疑改用 SGD 分类器并运行更多的纪元会有所帮助。
步骤 5c:测试增强的输入模型
使用 keras ImageDataGenerator,我可以像输入培训和验证数据一样输入增强模型测试数据:
测试精度与瓶颈特性模型大致相同,只是低了几个百分点。
为了深入研究精确度和回忆,我使用混淆矩阵执行了与之前相同的分析:
这里真正有趣的是,我们看到了和以前一样的异常值,尽管它更模糊,表明这个模型在区分西班牙猎犬方面做得稍好。然而,现在在矩阵的中心附近有另一个明亮的异常值——放大显示,这个模型无法区分杜宾犬和德国犬。
Doberman (left) and German (right) Pinschers
去想想。
最后结果
对我来说,最后一步是编写一个函数,从零开始加载给定的模型,接受图像数据作为输入,并输出品种预测。我将继续我的增强图像模型,因为我相信在未来我可以通过更多的训练来改进它。
在我在这里测试的每个模型的训练期间,我将参数保存到. hdf5 文件中。因此,一旦训练完成,假设我知道如何编译我感兴趣使用的模型,我可以根据命令加载我上次训练运行的最佳权重。然后在我的预测函数中,我只需要重新创建我在训练期间执行的图像处理步骤。
因为我已经将模型权重存储在一个外部文件中,并且我知道如何重新创建模型架构,所以我可以将所述模型打包,以便在任何地方使用,包括在 web 或移动应用程序中。事实上,在我写这篇文章的时候,我在 Play Store 上看到有一个狗品种识别应用程序,我怀疑它使用了与我在这里结束的那个类似的模型。
github 回购:https://github.com/jfreds91/DSND_t2_capstone
在 R 中进行并报告您的第一个方差分析和安协方差分析
如何测试和报告分类自变量对区间因变量的影响?
方差分析或 ANOVA,是许多科学领域中经常使用的基本统计测试。最常见的形式是,它分析模型中因变量的方差有多少可归因于自变量。它最常用于分析分类自变量的影响(例如,实验条件、狗的品种、花的种类等)。)上的区间因变量。方差分析的核心是提供与简单线性回归(即 OLS)相同的信息。然而,ANOVA 可以被视为一种替代的界面,通过它可以访问这些信息。不同的科学领域可能有不同的偏好,这通常意味着你应该使用哪种测试。
协方差的分析,或 ANCOVA,表示有一个以上自变量的 ANOVA。假设你想分析狗的品种对狗的体重的影响,控制狗的年龄。如果不控制狗的年龄,你可能永远无法确定狗的品种对其体重的真正影响。因此,你需要运行 ANCOVA 来“过滤”狗的年龄的影响,看看狗的品种是否仍然影响体重。控制另一个协变量可能会加强或削弱你感兴趣的自变量的影响。
Photo by Akshay Nanavati on Unsplash
方差分析
数据集
在这个练习中,我将使用 iris 数据集,它在 core R 中可用,我们将使用下面的命令以 df 的名称将其加载到工作环境中:
df = iris
鸢尾数据集包含描述不同种类鸢尾花的形状和大小的变量。
一个可以用方差分析来检验的典型假设是鸢尾的种类(独立分类变量)是否对花的其他特征有任何影响。在我们的例子中,我们将测试鸢尾的种类是否对花瓣长度(因变量区间)有任何影响。
确保你不违反关键假设
在运行方差分析之前,必须首先确认数据集中满足方差分析的关键假设。关键假设是在您的计算机如何计算方差分析结果时假设的方面,如果违反了这些方面,您的分析可能会产生虚假的结果。
对于 ANOVA,假设是方差的同质性。这听起来很复杂,但它基本上检查了由分类自变量创建的不同组中的方差是否相等(即,方差之间的差为零)。我们可以通过运行 Levene 的测试来检验方差的同质性。** Levene 的测试在 R 基地不可用,所以我们将使用车包进行测试。**
安装软件包。
install.packages("car")
然后加载包。
library(car)
然后进行 Levene 的测试。
leveneTest(Petal.Length~Species,df)
这会产生以下输出:
如您所见,测试返回了一个重要的结果。在这里,了解检验中的假设是很重要的:如果检验结果不显著,我们可以接受 Levene 检验的零假设,这意味着方差是同质的,我们可以继续进行方差分析。然而,测试结果非常显著,这意味着花瓣之间的差异。不同物种的长度有显著差异。
现在怎么办?
嗯……在这一点上,和你的合著者、同事或主管谈谈。从技术上讲,你必须进行稳健的方差分析,即使面对非齐次方差,它也能提供可靠的结果。然而,并不是所有的学科都遵循这个技术指南…所以要和你领域里更资深的同事交流。
无论如何,我们将继续本教程,就好像 Levene 的测试结果无关紧要一样。
运行实际的方差分析
我们通过使用公式符号、数据集名称和 Anova 命令指定该模型来实现这一点:
fit = aov(Petal.Length ~ Species, df)
在上面的命令中,你可以看到我们告诉 R 我们想知道物种是否影响花瓣。数据集 df 中的长度使用 aov 命令(这是 R 中的 ANOVA 命令)并将结果保存到对象 fit 中。**上述命令的两个基本要素是语法(即结构、符号、括号等)。)和 aov 命令。**其他一切都可以修改,以适应您的数据:花瓣。长度和物种是由虹膜数据集指定的名称,而 df 和 fit 只是我随意选择的名称——它们可能是你想要分析的任何东西。
您可能已经注意到,R 还没有报告任何结果。我们需要使用以下命令告诉 R 我们想要访问保存在名为 fit 的对象中的信息:
summary(fit)
该命令产生以下输出:
这张表给了你很多信息。尽管如此,我们感兴趣的关键部分是行物种,因为它包含我们指定的自变量的信息,以及列 F 值和 Pr( > F) 。如果我们的目标是拒绝零假设(在这种情况下,零假设是鸢尾的物种对花瓣长度没有任何影响)并接受我们的实际假设(物种对花瓣长度有影响),我们要寻找高 F 值和低 p 值 *。*在我们的例子中,F 值是 1180(非常高),p 值小于 0.000000000000002(写出来的 2e-16,你可能已经猜到了,非常低)。这一发现支持了我们的假设,即鸢尾的种类对花瓣长度有影响。
报告方差分析的结果
如果我们想报告这一发现,最好报告数据中个体组的平均值(在我们的例子中是物种)。我们使用 psych 包中的 describeBy 命令来完成这项工作。如果您还没有安装 psych 包并且想第一次使用它,请使用以下命令:
install.packages("psych")
否则,或者在安装了 psych 包之后,运行以下命令。
library(psych)
describeBy(df$Petal.Length, df$Species)
对于 describeBy 函数,您传递您希望看到描述的变量(花瓣。长度)和分组变量(物种)。我们需要在变量名前指定 df ,这与上面使用的 aov 命令使用的公式符号不同,因为 describeBy 命令不允许我们单独指定数据集。运行此命令会产生以下输出:
在此输出中,我们可以看到三个物种 Setosa、Versicolor 和 Virginica,在第三列中,我们看到了花瓣值的平均值。三组的长度。
这一发现可以用以下方式报告:
我们观察了三种鸢尾(M=1.46)、杂色鸢尾(M=4.26)和海滨鸢尾(M=5.55)的花瓣长度差异。方差分析表明物种之间的这些差异是显著的,即物种对花的花瓣长度有显著影响,F(2,147)=1180,p <.001./>
One could also add a graph illustrating the differences using the package *ggplot2。*运行以下命令安装 ggplot2 包,如果你还没有安装的话。
install.packages("ggplot2")
然后加载包。
library(ggplot2)
然后运行图形命令。
ggplot(df,aes(y=Petal.Length, x=Species, fill=Species))+
stat_summary(fun.y="mean", geom="bar",position="dodge")+
stat_summary(fun.data = mean_se, geom = "errorbar", position="dodge",width=.8)
这产生了下图。代码相当复杂,解释 ggplot2 的语法超出了本文的范围,但是请尝试对其进行修改并将其用于您的目的。
安科瓦
现在想象你想要做上面的分析,但是同时控制花的大小的其他特征。毕竟,物种可能不会具体影响花瓣长度,但更普遍的是,物种会影响植物的整体大小。所以问题是:**在控制了其他植物尺寸的情况下,物种是否仍然会影响花瓣的长度?**在我们的分析中,代表植物大小的另一个指标是变量 Sepal。长度,在虹膜数据集中也有。因此,我们通过添加这个新的协变量来指定我们的扩展模型。这就是 an cova——我们在控制一个或多个协变量的同时,分析分类自变量对区间因变量的影响。
fit2=aov(Petal.Length~Species+Sepal.Length,df)
然而与之前不同的是,我们现在不能简单地在 fit2 对象上运行 summary 命令。因为在默认情况下,非常奇怪的是,base R 使用类型 I 错误作为默认。在进行简单的方差分析时,I 型误差不是问题。但是,如果我们试图运行 ANCOVA,I 类错误将导致错误的结果,我们需要使用 III 类错误。如果你对什么是 I 型和 III 型错误感兴趣,我可以推荐安迪·菲尔德的书《使用 R 发现统计数据》第 457 页底部的简·超级大脑部分
因此,我们需要使用不同包中的另一个函数来指定我们希望使用的错误的确切类型。我们将使用赛车套件。运行下面的命令来安装汽车包,如果你还没有安装的话。它和上面 Levene 的测试是同一个包,所以如果你从一开始就遵循教程,你可能不需要安装和加载这个包。如果您不确定,为了安全起见,只需运行这些命令。
install.packages("car")
然后加载包。
library(car)
然后,在我们的 fit2 对象上运行 car Anova 命令,指定我们希望使用类型 III 错误。
Anova(fit2, type="III")
这会产生以下输出:
正如您在我们的行*物种、*列 *Pr( > F)、*即 p 值中所看到的,物种仍然对花瓣的长度有显著影响,即使在控制萼片的长度时也是如此。这可能意味着花朵确实有不同的比例,并不是因为物种的不同而简单地变大或变小。
尝试在 fit2 对象上运行 summary 命令,查看 summary 命令产生的结果是否不正确;然而,如果您要通过 summary.lm 命令查看 fit2 对象,该命令以线性模型(即 OLS)的样式生成输出,并且还使用 III 类错误,您将在输出中获得与通过 Anova 命令从 car 包获得的相同的正确信息。
我们可以如下所示报告这一发现。
协变量,萼片长度,与花的花瓣长度显著相关,F(1,146)=194.95,p <.001. there=“” was=“” also=“” a=“” significant=“” effect=“” of=“” the=“” species=“” plant=“” on=“” petal=“” length=“” after=“” controlling=“” for=“” sepal=“” f=“” p=“”/>
After completing either the ANOVA or ANCOVA, you should normally be running the appropriate post hoc tests to reveal more about the effects. After all, an ANOVA is merely an inferential test, i.e., it tests whether the data is distributed in a way that we would expect if the distribution were random. So far, we only know that there is a relationship between species and sepal length —we know that sepal length is non-randomly distributed when grouped by species. However, how exactly does species influence sepal length? One way of achieving this is by breaking down the variance explained by the independent variable of interest into its components . You可以在我关于计划对比的文章中了解更多信息。
在 R 中做并报告您的第一个中介分析
如何测试和报告介导效应
本教程将解释什么是调解分析,展示如何为调解分析模拟数据,运行必要的统计程序,并撰写报告以供发表。
简介将关注于建立冥想到底是什么。如果你知道什么是中介,只是想知道如何在 R 中实现它,那么跳到“第一步:总体效果”这一章。
中介听起来可能很有挑战性,但实际上很简单。中介效应也称为间接效应。当自变量对因变量的影响——顾名思义——被另一个变量(中介变量)调节时,就会发生这种情况。
考虑调解时,一些重要的注意事项是:
- **介体必须是内源性的:**这意味着介体不能是治疗或研究条件。介体本身必须依赖于外生变量,这些变量通常是实验研究中的治疗或研究条件。
- **调解人必须揭示更多关于自变量如何影响因变量的见解:**调解人揭示关于过程的一些情况。
因此,中介帮助我们找出自变量如何影响因变量。通过运行中介分析,我们正在测试关于自变量如何影响因变量的过程的假设。
得出一个中介效应
对于本文,我们将模拟数据。我相信模拟数据确实有助于弄清楚我们正在分析的数据中发生了什么。数据将基于经典的“iris”数据集,该数据集包含在 base R 中。另外,同时设置样本种子,这样你的随机数生成器的结果就会和这里的一样。
df=iris
set.seed(12334)
iris 数据集包含 5 个变量和 150 个观察值。这 5 个变量是萼片的长度和宽度,花瓣的长度和宽度,以及鸢尾花的种类。
Photo by Lukas Blazek on Unsplash
在这篇文章中,我们将假设花瓣的长度影响花朵被蜜蜂授粉的可能性。然而,这种影响不会是直接的,而是通过开花对蜜蜂的吸引力来调节的。因此,我们的假设是萼片长度对蜜蜂通过花朵的吸引力授粉的可能性有间接影响。
只有萼片长度是包含在虹膜数据集中的变量。剩余的两个变量将被模拟。所以下一步,让我们模拟数据。
模拟中介的数据
模拟有一个很好的副作用,你可以直接看到数据中发生了什么。这可以提高你对统计结果的直观理解。
首先,让我们模拟一下中介,“对蜜蜂的吸引力。”这个变量将被命名为 mediator ,在我们的例子中,它将由两部分组成。其价值的 35%是萼片。长度+其值的 65%是随机噪声。想象一下,变量“对蜜蜂的吸引力”中的随机噪声可能是其他特定于花朵的属性,如颜色、形状、气味等。
df$random1=runif(nrow(df),min=min(df$Sepal.Length),max=max(df$Sepal.Length))df$mediator=df$Sepal.Length*0.35+df$random1*0.65
其次,让我们模拟因变量,“被蜜蜂授粉的可能性。”这个变量将被命名为 dv 并再次由两部分组成。其值的 35%是介体,+ 65%是随机噪声。在我们的例子中,随机噪声可以是非植物特有的属性,如花的位置、天气条件、土壤等。
df$random2=runif(nrow(df),min=min(df$mediator),max=max(df$mediator))df$dv=df$mediator*0.35+df$random2*0.65
现在,“萼片长度”中包含的大约 12%(准确地说是 12.25%)的信息应该包含在因变量“被蜜蜂授粉的可能性”(as 35% × 35% = 12.25%)中。这是我们预期的总效果。由于因变量包含了中介“开花对蜜蜂的吸引力”中 35%的信息,因此通过中介的间接效应将“强于”直接效应这正是中介分析所显示的。
如何用统计程序为调解提供支持
我们将在中介分析的帮助下,通过四个简单的步骤为中介提供统计支持。
- 首先,我们将测试总体效果。这里我们正在观察萼片长度的任何变化是否会影响 DV。稍后将详细介绍。
- 其次,我们将测试自变量对中介的影响。萼片长度对调解的显著影响是调解成为可能的绝对先决条件。
- 第三,我们将同时检验中介变量和自变量对因变量的影响。这是当橡胶碰到路面时,所有的东西都聚集在一起。
- 第四,也是最后一点,我们将为因果中介分析估计各种数量,这意味着我们将比较直接和间接影响,让我们对数据中发生的事情有更多的了解。
The four steps of mediation analysis.
第一步:整体效果
总效应描述自变量(iv) 萼片长度对因变量(dv) 被蜜蜂授粉的可能性的总效应。基本上,我们想了解这两个变量之间是否有关系。对于这种关系是否需要对调解产生重要影响,有两种观点:
- 第一种观点认为两者之间必然存在着重要的关系。否则,即使有显著的间接影响,我们也不能肯定地说改变 iv(在我们的例子中是萼片长度)对 dv(被蜜蜂授粉的可能性)有任何影响。然而,这个学派正在慢慢地让位于第二个学派。
- 第二种观点认为静脉注射和家庭暴力之间不一定有显著的关系。正如相关性不能证明因果关系一样,没有相关性也不能否定因果关系。海斯 2018,第 80 页。一个同样有道理的论点。
总之,你不需要有显著的总体效果,但是有一个绝对没有坏处。如果有疑问,和你的合著者谈谈,因为我的经验是这是一个高度个人化的决定。并希望你的最终审稿人同意你和你的合著者的观点。
幸运的是,在我们的例子中,当我们模拟数据时,我们将有一个显著的总效应。因此,我们开始运行一个简单的线性回归到 dv 加上任何协变量(在我们的例子中没有)。
fit.totaleffect=lm(dv~Sepal.Length,df)
summary(fit.totaleffect)
这将产生以下结果。正如你所看到的,萼片长度对我们的 dv 的总影响是显著的(p <.05 and=“” the=“” coefficient=“” is=“” very=“” close=“” to=“” expected=“” from=“” above=“”/>
If the output you receive differs from the one below (e.g., the coefficients differ), you might have set a different random seed (see above) or have set no random seed at all. This seed introduces some predictability to the randomness. You can remedy this by setting the random seed above and re-simulating the data.
So now we have a significant total effect. Let’s proceed to step 2.
Step #2: The effect of the IV onto the mediator
To establish any mediation, the independent variable (iv, “sepal length” in our case) must significantly affect the mediator. This makes sense, as, for a mediation to take place, the iv must significantly impact the mediator.
So we do another simple linear regression of the iv onto the mediator plus any covariates you might have this time (none in our case).
fit.mediator=lm(mediator~Sepal.Length,df)
summary(fit.mediator)
This will yield the following results below. As you can see, the total effect of sepal length on our dv is significant (p<.05 and=“” the=“” coefficient=“” is=“” close=“” to=“” expected=“” from=“” above.=“”/>
Now we have a significant effect of the independent variable “sepal length” onto the mediator “attractiveness of the bloom to the bee.”
Step #3: The effect of the mediator on the dependent variable
The third step confirms that the mediator affects the dependent variable*,同时控制自变量*。这意味着,为了进行调解,调解人必须解释因变量中比自变量更多或其他部分的方差。
因此,我们做一个简单的线性回归,将自变量和中介变量回归到因变量,再加上这次可能有的任何协变量(在我们的例子中没有)。
fit.dv=lm(dv~Sepal.Length+mediator,df)
summary(fit.dv)
这会产生以下输出:
请注意该输出的几个方面:
- 中介物有显著的影响(p <.05 on=“” the=“” dv.=“” with=“” result=“” from=“” step=“” we=“” can=“” now=“” already=“” say=“” that=“” there=“” is=“” a=“” mediation.=“” again=“” coefficient=“” very=“” close=“” to=“” expected=“”/>
- Whereas sepal length was a significant predictor of the dv “likelihood of pollination” before, it is no longer. In our data simulation, we included all the information of the IV that was contained in the DV also in the mediator, so this is not unexpected. In such cases, we speak of a “complete mediation.” This means that the total effect of the IV on the DV is explained by the mediator. In our case, it means that the total effect of “sepal length” onto “likelihood to be pollinated by a bee”)通过“花朵对蜜蜂的吸引力”中介分析有助于我们更好地理解 iv 对 dv 的作用过程。
如果 IV 仍然是重要的,我们会说“不完全调解”,这也是完全可以的。不完全的调解意味着静脉注射对静脉注射的另一种影响,这种影响不通过调解人。
从统计学上来说,我们有所有的支持来假设数据中的中介。但是,在一个模型中计算整个模型是一种很好的做法。中介是一个迷你结构方程模型(SEM ),所以如果我们愿意,我们可以使用 SEM-packages for R,比如“lavaan ”,来估计整个中介。然而,这将是相当复杂的。谢天谢地,有更简单的方法来完成这项工作。这就是第四步的内容。
步骤 4:因果中介分析
让我们加载必要的 R 包。
#install.packages("mediation") #uncomment this command in case you haven't installed the mediation package yet.
library(mediation)
这将加载(并安装)中介包,它采用我们刚刚估计的回归模型,组合它们并估计整个中介。因此,让我们运行命令。
results = mediate(fit.mediator, fit.dv, treat='Sepal.Length', mediator='mediator', boot=T)
来自中介包的中介函数请求我们刚刚估计的模型,然后要求我们指定作为*处理的变量、即我们的自变量、*和作为中介的变量。此外,我们需要指定 boot=T ,因为默认情况下, mediate 将对置信区间使用准贝叶斯近似。然而,我们想要报告百分位数的置信区间,所以我们将其设置为 T 为真。这个命令需要一些时间来运行,但不会产生任何输出。要获得输出,我们需要运行下面的命令。
summary(results)
这会产生以下输出:
这些缩写可能有些吓人,但它们的意思是:
- ACME 代表*平均因果中介效应。*这是 IV(萼片长度)通过媒介(对蜜蜂的吸引力)对 DV(授粉可能性)的间接影响。请注意,它估计这种影响为 0.11——这正好是 0.30(步骤#2 中 IV 对介质的影响)乘以 0.37(步骤#3 中介质对 DV 的影响)——因此不一定是新信息。然而,新的是,我们现在有了整个间接效应的置信区间和显著性水平,而不仅仅是它的两个单独部分。这是我们报告中介所需要的。
- ADE 代表*平均直接效果。*它描述了静脉注射对静脉注射的直接影响。再说一遍,这不是新信息。我们已经在步骤 3 中计算了这种影响:当控制介体时,静脉对静脉的直接影响。
- 总效应代表 IV 对 DV 的总效应(直接+间接)。这也不是新信息。我们在第一步中计算了这一点。我们也可以通过简单地将 ACME (.1132)和 ADE (.0167)相加得到. 1298 的总效果。我们也已经知道,从第一步开始,总的效果是显著的。
- 道具。中介描述了静脉注射对通过中介的静脉注射的影响比例。计算方法是将顶点(. 113)除以总效果(. 13)得到 0.87。这条信息是一个很好的花絮,但不一定是我们感兴趣的焦点。
你看,我们在这最后一步没有学到很多新东西。然而,我们现在已经获得了报告中介所需的所有信息。
报告调解
我们计算的中介可以按以下方式报告:
Figure 1
萼片长度对授粉可能性的影响完全是通过花的吸引力来调节的。如图 1 所示,萼片长度和授粉可能性之间的回归系数以及吸引力和授粉可能性之间的回归系数是显著的。间接效应为(. 30)*(.37) = .11。我们使用自举程序测试了这种间接影响的显著性。对 1000 个自举样本中的每一个样本计算非标准化的间接效应,并通过确定第 2.5 和 97.5 百分位的间接效应来计算 95%的置信区间。自举非标准化间接效应为. 11,95%置信区间为. 06 到. 17。因此,间接效应具有统计学意义(p<.001/>
该图的系数取自步骤#1 到#3 中的不同模型。大部分文本信息来自中介函数的结果(第 4 步)。我们之前忽略了它,但中介函数确实执行引导,即,它使用从数据中随机抽取的子样本重新计算模型 1000 次。这样做是为了对我们的结果更有信心。
以正确的方式处理数据
数据科学的伦理
(from: robynmac on Depositphotos)
当我学习如何从网上搜集数据时,我第一次想到了数据科学中的伦理概念。刚刚配备了能够轻松捕获和存储任何仅仅是在线打印的信息的能力,我正享受着仅仅为了它而抓取不同网站的乐趣。然后,在尝试搜索 Reddit 时,我收到了这条消息:
whoa there, pardner!
网页抓取虽然繁琐却是一个强大的工具。像 Reddit 这样更大的网站有类似上面的措施来阻止我们一次获得太多的信息。看着上面的信息,我们仍然可以获得这些信息,只是不是一下子。网络抓取是我们作为数据科学家最先学会的事情之一,在我涉足数据科学领域的一个月内,我就有能力在线存储写在任何网页上的几乎任何信息。权力越大,责任越大。肯定有一些人会滥用他们的网络抓取能力来作恶。
我们生活在一个信息时代,这里存在着大量的数据,并且这些数据还在不断产生。信息现在是生活和社会不可或缺的一部分,随之而来的是需要知道如何管理它。电气和电子工程师协会(IEEE)实际上在 1999 年发布了软件工程道德规范,概述了软件工程师应该遵守的 8 项原则“符合他们对公众健康、安全和福利的承诺。”道德规范为软件工程师的行为和决策提供了指南,并且(简单地说)非常实用。例如,第一条原则规定“软件工程师的行为应该与公众利益一致。”下面的原则也符合做好事和最大化软件产出的好处的路线。
数据科学是一个比软件工程还要新的领域。2018 年,我们看到了剑桥分析/脸书崩溃和欧盟实施通用数据保护法规 ( GDPR )等事件,这两者都与大数据以及如何处理我们在线信息有关。大数据不可避免地会对世界和我们的社会产生巨大影响,因此我们(作为数据科学家)必须对我们正在做的任何事情的道德影响有所认识。
所以…什么是对的?怎么了?
silicon Republic上发表的一篇文章质疑为什么数据科学家没有接受道德培训。文章一开始就提出了一系列与道德相关的问题,比如:我们能卖什么?我们可以得到这些信息吗?“问 20 个数据科学家这些问题,你会得到 20 个不同的答案。”
由于该行业还处于起步阶段,对于什么是正确的还没有达成社会共识。此外,在数据科学过程中,有许多阶段会涉及不同的伦理问题。我在两个广泛的领域探索数据科学的伦理:数据收集和有效性。这不是在任何情况下做什么的答案,而是探索如何将伦理应用于数据科学,以及我们如何以正确的方式实践数据科学。
在开始之前,我想声明这篇文章中的很多内容都是基于网上研究的。我的一个主要资源是密歇根大学 Jagadish 教授在 Coursera 上的 数据科学伦理课程。
数据收集
对于一项数据科学任务,流程的第一个一般阶段是收集和清理数据。出现了许多伦理争议,比如我遇到的网络抓取。这里有一个关于数据收集道德的问题:如果我给你拍了一张照片,这张照片是不是因为我拍的而属于我?或者既然照片的主体是你,那这张照片是属于你的吗?
这个基本的例子已经引出了两个在数据科学伦理领域越来越受关注的主要概念:知情同意和数据所有权。
知情同意的概念来自医学研究领域,在这一领域,患者必须在接受治疗前了解治疗的全部风险。更相关的是,知情同意发生在研究对象必须知道他们正在被研究的时候。这似乎是显而易见的,不是吗?如果你正在参加某个临床试验,你会知道你是这个试验的一部分,对于研究人员来说,随机给人用药来测试某种治疗的有效性是完全不道德的。现在将这个概念应用于数据科学。许多企业基于 A/B 测试做出决策。A/B 测试对受试者的影响可能不如测试抗癌药物,但它也是一种实验。
这里有几个现实生活中的例子可以考虑。2014 年,在一项与康乃尔大学和加州大学旧金山分校联合进行的关于情绪传染的研究中,脸书被揭露操纵用户的新闻推送。他们想知道在他们的订阅源上看到更多正面帖子的用户是否会发布更多正面帖子,以及看到更多负面帖子的用户是否会发布更多负面帖子。他们得出结论,情绪传染是显而易见的,但当公众发现脸书不仅操纵他们看到的内容,而且还使用他们的新闻订阅和帖子上的信息进行研究时,大多数人都感到愤怒。快速的谷歌搜索发现了许多抨击脸书滥用用户数据的文章,特别是因为这个实验操纵了用户的情绪。然而,脸书声称,在他们的实验中使用数据符合他们的数据使用政策,用户在创建他们的脸书账户之前已经同意并接受了该政策。
同年, OkCupid 出来说,他们在一项实验中也操纵了呈现给用户的信息,以观察被告知他们是兼容的是否会影响真正的兼容性。OkCupid 基本上告诉不相容的夫妇他们是相容的,反之亦然,以观察报告的相容性分数是否重要。我引用莫莉·伍德在《纽约时报》上发表的一篇关于这个实验的文章:
OKCupid 的用户协议说,当一个人注册该网站时,个人数据可能会用于研究和分析。
“我们告诉用户一些不真实的东西。我绝对没有隐瞒这个事实,”OKCupid 的总裁鲁德尔先生说。但他说,测试是为了确定人们如何从网站上获得最大收益。“人们来找我们,是因为他们希望网站能够运行,而我们也希望网站能够运行。”
与脸书的失败类似,他们声称知情同意是因为用户在注册服务时达成的协议。在不同的网站注册时,我们盲目同意了多少这样的协议?这算不算知情同意?
数据所有权有些相关。在数据科学中,数据属于记录它的人。因此,在照片示例中,约定将规定照片属于我。作为数据科学家,我们通常获取和处理现有数据——我们不是进行调查和发布表格的人。数据的所有权现在变得更加复杂了。在知识产权方面,我们正在处理记录数据的衍生产品,因为我们从一个地方获得数据,对其进行管理和收集,然后为我们的研究进行清理和验证。因为在整个清理过程中投入了如此多的精力,而且从技术上来说,因为我们是这些新数据的记录者,所以这些清理过的数据集属于我们吗?
普遍的共识是,在我们使用这些数据之前,我们必须得到发布这些数据的人的许可。但是如果我们从产品评论上获取信息呢?我们必须得到每个留下评论的人的许可。这就是为什么像亚马逊或易贝这样的在线网站在他们的用户协议中有某种条款,规定无论用户在他们的网站上发布什么,公司都可以使用。因此,如果我们是亚马逊的数据科学家,我们可以在伦理上使用他们的产品评论数据。这是与 GDPR 相关的数据科学道德领域——一种保护互联网用户数据不被公司处理的措施。对许多公司来说,数据是一种资产。尤其是在技术领域,数据推动他们做出决策,一般来说,数据越多越好。
GDPR 是政府监管用户数据所有权和使用的首批重大举措之一,它以某种方式影响了每一家有网络业务的公司。这也暴露了数据所有权这一复杂领域中的许多灰色地带。
有效性:在数据、处理和模型中
有效性可以在数据科学过程的不同点进行评估。我粗略地简化了过程,并解决了三个主要的争论点:数据的有效性、处理的有效性和模型的有效性。从伦理上评估数据科学过程的有效性是主观的。谁来说什么是对的,什么是错的?当然有比其他方法更好的方法,但是关于处理数据的正确方法还没有一个行业标准。没有关于如何确保收集的数据符合某种标准的指南。
首先,在我看来,作为数据科学家,我们有责任尽最大能力验证我们正在处理的数据是有效的;或者至少,我们应该将数据放在上下文中,并向决策者概述其局限性。决策者应该在最大程度上了解从数据和我们创建的模型中得出的结论所处的环境。在评估数据的有效性时,我会考虑以下几个问题*(绝对不是详尽的列表)*:
- **数据是否代表了您想要捕捉的内容?**会不会是来自将要得出结论的人群中的某个特定子集?我认为 Jagadish 课程中的一个例子很好地描述了这一点:使用来自 Twitter feeds 的数据来代表公众意见。Twitter 用户普遍倾向于更年轻、更富有。
- 数据有多永恒?随着时间的推移,你用于预测/模型的数据会有相关性吗?如果没有,是否有措施防止模型过时或是否有一个已知的模型使用截止点?例如,SAT 的得分是 2400 分,直到 2016 年,随着阅读和写作部分的合并,它变成了 1600 分。我们应该知道大学用来评估整体分数的标准分数转换,或者如果我们评估阅读/写作能力,考虑各部分的合并。
我们有很多方法可以处理数据。当我们处理表格和数据帧中的NaN
值时,我们可以采取许多不同的方法,从而产生不同的结果。无论是删除行、用平均值或中值替换空值还是从相邻数据点进行插值,都有一般的最佳实践,但没有硬性的标准规则。什么是最好的方法也取决于学习的背景。由于这是如此主观,需要如此多的背景,我在这里能做的最好的就是推荐功利主义的方法——选择任何你认为最有意义的方法;你认为最大化效用的任何方法。
模型有效性与我们讨论的非常相似。我们只是想确保无论在什么情况下,我们都在尽最大努力产生最好的结果。在技术层面上,我们希望验证我们的模型,以便它最适合我们拥有的任何场景。这就是为什么我们有不同的评估系统和测试分数——来看看我们的模型表现如何。提出一个不准确的模型来做预测或决策是非常不道德的,尤其是如果它可以改进的话。我认为,作为一名数据科学家,负责任的做法是不断测试你的模型。是过拟合还是欠拟合数据?设计的功能有意义吗?模型容易改变吗?
我发现软件工程道德准则中有三个条款与数据科学的这个方面相关:
软件工程师应确保他们的产品和相关的修改符合最高的专业标准。
软件工程师应保持其专业判断的完整性和独立性。
软件工程经理和领导者应认同并促进软件开发和维护管理的道德方法。
(摘自 IEEE 的软件工程道德准则)
到结束掉,我们来深入一下。想象一下,我们正试图训练一个人工智能像人类一样行动。在监督学习算法中,目标是优化一些目标函数。现在我们如何定义人类的目标函数?这个人工智能会有什么样的道德?不管是谁负责定义这个目标函数,他基本上都有权力定义,至少对这个人工智能来说,定义“理想人类”。
电车难题及其变种,是经典的伦理思想实验之一。随着自动驾驶汽车的出现,这种思想实验现在变成了现实。如果一辆自动驾驶汽车将要撞上一些行人,汽车是否应该突然转向,从而有可能杀死司机?还是汽车应该饶了司机,害死行人?
NPR 的 Laurel Wamsley 写道 自动驾驶汽车应该有伦理吗?2018 年 10 月。这篇文章着眼于在线向人们提出的 Trolly 问题变体的结果。 (可以看到这里提出的问题!—在“判断”标签下) 研究发现,人们的答案会因他们来自哪里而有所不同。因此,对于在每种情况下什么是正确的,还没有达成共识。这项电车问题研究的作者写道:
“在我们允许我们的汽车做出道德决定之前,我们需要进行一次全球对话,向设计道德算法的公司和监管它们的决策者表达我们的偏好。”
随着人工智能成为社会越来越重要的一部分,规则将开始形成。我们非常幸运能够见证该行业的发展,并有可能作为数据科学家为其做出贡献。我希望,作为数据科学家,我们要确保把我们的力量用在好的方面。
TL;博士:尽你所能做正确的事情。
想法?给我留个评论@Yish Lim和大家说说吧。
用机器学习做有意义的工作——对灾难信息进行分类
建立模型,帮助救灾组织拯救人们的生命。
I’m writing this post at 1am in Bucharest, Romania.
又见面了。欢迎来到我的第四篇关于机器学习的内容。我最近做了一个我认为对社会有意义的项目。我将简要概述这是怎么回事,然后马上深入代码:)
在这个项目中,我应用数据工程技术创建了一个 API(应用程序编程接口),将来自各种来源(Twitter,文本消息)的灾难消息分为 36 类。这种分类问题是一种受监督的机器学习,因为模型根据对提供给它的数据的学习来学习对结果进行分类。即信息与什么相关:水、食物、住所、金钱等。?原因是当灾难发生时,有数百万条消息被发送和推文告知。然而,灾难由不同的组织负责。食物供应可能由某个组织提供,而灭火则由另一个组织负责。因此,该应用程序的用途是将这些消息分类成各种类型,以便可以理解对于特定的灾难需要哪种类型的援助。
项目结构
该项目有三个部分:
- ETL 管道
提取、转换、加载数据。这与处理数据有关。也就是说,我加载、合并和清理了消息和类别数据集。我存储到 SQLite 数据库中,以便模型可以在下一步中使用它进行训练。 - ML 流水线
机器学习流水线与训练模型和测试模型有关。管道包括一个文本处理部分,因为它处理开头提到的文本源。我还使用 GridSearchCV 进一步调优模型,并将其保存为 pickle 文件。 - Flask Web App
run.py``process_data``train_classifier
基本就是终端工作空间包含的 ETL 管道和 ML 管道,让 App 工作。
ETL 管道
在项目的第一部分,我的目的是提取我需要的数据,进行必要的转换,以便我可以在以后的算法构建中使用它。一旦我看到了我需要的两个数据集:T3 和 T4,我就使用公共 id 合并这两个数据集。
*# merge data sets*
df = messages.merge(categories, on = [‘id’])
df.head()
然后,我将类别分成单独的类别列,并为每一列指定了单独的类别名称。
*# create a dataframe of the 36 individual category columns*
categories = df['categories'].str.split(';', expand = **True**)row = categories.head(1)category_colnames = row.applymap(**lambda** x: x[:-2]).iloc[0, :].tolist()*# rename the columns of `categories`*
categories.columns = category_colnames
categories.head()
因为模型使用数字作为输入,所以我将类别值转换为数字 0 或 1。
**for** column **in** categories:
*# set each value to be the last character of the string*
categories[column] = categories[column].astype(str).str[-1]
*# convert column from string to numeric*
categories[column] = categories[column].astype(int)
categories.head()
转换类别列后,我对数据框进行了更改。我用新的类别列替换了原来的类别列。
*# drop the original categories column from `df`*
df.drop('categories', axis = 1, inplace = **True**)*# concatenate the original dataframe with the new `categories` dataframe* df = pd.concat([df, categories], axis = 1) df.head()
在检查了数据中的重复项后,我删除了它们。
*# check number of duplicates*
df[df.duplicated].shape(170, 40)*# drop duplicates*
df.drop_duplicates(inplace = **True**)*# check number of duplicates*
df[df.duplicated].count()
我最终将干净的数据集保存到 SQLite 数据库中。
*# Save the clean dataset into a sqlite database.*
engine = create_engine('sqlite:///disaster.db')
df.to_sql('messages_disaster', engine, index=**False**)
ML 管道
在项目的第二部分,我创建了机器学习管道,用于将灾难信息分类成不同的类别。被称为“管道”的原因是因为这个建模工具由几个步骤组成,这些步骤处理输入以生成输出。在这种情况下,我使用标记化来处理文本数据。
*# load data from database*
engine = create_engine('sqlite:///disaster.db')
df = pd.read_sql_table('messages_disaster', con = engine)X = df['message']
Y = df.drop(['message', 'genre', 'id', 'original'], axis = 1)*# Tokenization function to process text data.*
**def** tokenize(text):
tokens = word_tokenize(text)
lemmatizer = WordNetLemmatizer()
clean_tokens = []
**for** tok **in** clean_tokens:
clean_tok = lemmatizer.lemmatize(tok).lower().strip()
clean_tokens.append(clean_tok)
**return** clean_tokens
机器学习管道将在数据集中的 36 个类别上以message
列作为输入和输出分类。这是一个*自然语言处理的问题;*即对文本进行处理,从信息中提取含义。是不是很神奇?
pipeline = Pipeline([
('vect', CountVectorizer()),
('tfidf', TfidfTransformer()),
('clf', MultiOutputClassifier(RandomForestClassifier()))
])
就像所有其他 ML 模型一样,我们必须有训练和测试集。原因是我们不希望我们的模型在训练集上表现得非常好,同时在看到新数据时不能正确地对我们的类别进行分类。因此,我们必须只使用数据的子集来训练它,并观察它在测试集上的表现。
*# Split data into train and test tests.*
X_train, X_test, y_train, y_test = train_test_split(X,Y, test_size = 0.2, random_state = 45)*# Train the model.*
pipeline.fit(X_train, y_train)
在测试我的模型时,我希望有一些客观的性能指标。即我会看 f1 分数,精度和召回。
*# Test the model and print the classification report for each of the 36 categories.*
**def** performance(model, X_test, y_test):
y_pred = model.predict(X_test)
**for** i, col **in** enumerate(y_test):
print(col)
print(classification_report(y_test[col], y_pred[:, i]))performance(pipeline, X_test, y_test)
just a snapshot
在建立模型时,寻求改进总是一个好主意。尝试调整模型的参数以获得更好的结果。这就是我在这里尝试的。这是相同的过程,但有不同的管道。
*# Improve the pipeline.*
pipeline2 = Pipeline([
('vect', CountVectorizer()),
('best', TruncatedSVD()),
('tfidf', TfidfTransformer()),
('clf', MultiOutputClassifier(AdaBoostClassifier()))
])*# Train the adjusted pipeline.*
pipeline2.fit(X_train, y_train)# Check the performance of the adjusted model.
performance(pipeline2, X_test, y_test)
我更进一步,使用了一组不同的参数和一定范围的值。在 GridSearchCV 的帮助下,模型选择最佳参数。
parameters2 = {
'tfidf__use_idf': (**True**, **False**),
'clf__estimator__n_estimators': [50, 100],
'clf__estimator__learning_rate': [1,2] }cv2 = GridSearchCV(pipeline2, param_grid=parameters2)cv2.fit(X_train, y_train)performance(cv2, X_test, y_test)
构建 API
最后,我以制作一个 API 来结束这个项目,这个 API 接收一条灾难消息,并将其分类为最可能的灾难类别。这样,我们可以帮助救灾组织更好地了解发生了什么类型的灾难,以及需要哪种援助。
结束语
如果你做到了这一步,非常感谢你的阅读!希望这能让你了解机器学习有多有用。以及它的应用范围有多广。通过了解如何处理文本数据和实现模型,我们可以真正挽救人们的生命。说到模型,这是我的 github 上的完整项目。
祝你一切顺利,永远幸福:)
附:我们来连线一下 Linkedin !