GitHub 副驾驶。软件工程行业的兴衰故事
GitHub 和 OpenAI 已经宣布了 Copilot,这是一个人工智能助手,可以通过为他们的软件解决方案生成或自动完成代码来协助编码人员。这对软件工程行业意味着什么?
2021 年 6 月中旬,OpenAI 的首席执行官萨姆·奥尔特曼(Sam Altman)发布了一条推文,他在推文中声称,人工智能将对电脑前的工作产生更大的影响,比现实世界中的工作快得多:
山姆·奥特曼关于人工智能在计算机辅助工作中的破坏的推文
17 天之后,GitHub 和 OpenAI 宣布了与那条推文相关的副驾驶的技术预览。Copilot 是一个人工智能驱动的代码助手,它使用 OpenAI 的新解决方案 Codex,此前它接受了从公开来源(包括 GitHub 的公共资源库)中选择的英语文本和源代码的训练。
Copilot 对软件工程行业的颠覆性有多大?一年前,GPT-3 宣布后,我写了一篇介绍 OpeanAI 最新自然语言处理模型的文章,其中我分析了一些测试人员创建的第一批应用程序,这些应用程序允许基于 GPT-3 的语言能力生成代码。当时,我问自己是不是到了恐慌的时候了,对此我回答如下:
作为一个在 IT 服务市场工作的人,当看到所有这些令人难以置信的基于 GPT 3 的应用程序时,首先想到的问题很明显:软件工程师会因为像这样的人工智能改进而失业吗?这里我首先想到的是,软件工程和写代码是不一样的。软件工程是一项意义深远的任务,它意味着解决问题、创造性,当然,还包括编写实际解决问题的代码。也就是说,我真的认为,由于启动,这将对我们通过软件解决问题的方式产生影响。
我在一年后肯定了袖手旁观的说法,同时我也认为 Copilot 将对软件工程行业产生深远的影响。我预计,这种颠覆会加速一些起伏:
上升中
- 软件架构:现在,软件架构师的角色比以往任何时候都更加重要,以确保软件工程原则:可靠性、可用性、可维护性、性能(RAMP)。虽然生成有效解决特定问题的代码几乎是零成本问题,但如果没有强大的软件架构原则,正确设计所有代码如何在一个通用和一致的软件架构下组合在一起将变得更加复杂。
- **漏洞发现工具:**对高质量数据的培训将是 Copilot 这样的工具被大规模采用的关键。这就是为什么像亚马逊这样的公司已经押注于 Bug 修正全球挑战( BugBust )来改善他们的智能软件开发助理( CodeGuru )的表现。
- **Lowcode/ Nocode —企业架构集成:**我预计 Copilot 和其他 Lowcode 和 Nocode 工具都将保持快速发展,这强化了如何集成和正确维护这些工具生成的软件代码的问题。Copilot 或任何其他类似的工具如何确保稍微改变功能或技术需求不会导致生成的代码发生巨大变化?请记住,Copilot(或任何其他类似的模型)是在海量数据上训练的,因此该模型的未来版本可能会生成完全不同的最终代码。在这种情况下,这种工具集成到可扩展企业架构中的可能性将成为无代码/低代码供应商的明显竞争优势。当被理解为代码生成工具的特定训练时,这种集成将考虑到用于编码目的的灵活性和成本降低的益处,同时确保生成的代码与预定义的软件架构及其原理一致。
- 软件启动/提示工程:正如我在 GPT-3 的文章中提到的,启动的概念将是使 Copilot 这样的技术有用的关键,为模型提供我们想要解决的问题的良好定义,等等。一些作者已经写了关于“ prompt engineering ”的概念,作为一种通过人工智能解决问题的新方法。同样,一个工程过程仍然需要比目前 Copilot 所展示的更多的东西,但它肯定会改变我们作为它的一部分处理编码的方式。
- ****软件许可管理:Copilot 发布后, Hackernews 开始充斥着关于使用 Copilot 或类似工具时如何管理软件许可的评论。我还预计,专门从事软件许可模式的知识产权律师将会越来越多,来处理这个问题。
hackernews 上的 Copilot 线程,提到 GPL 软件的潜在含义
在秋天
- 软件编码员和测试员:为了寻找(我会说是可疑的)效率,许多公司将编程任务外包/外包给缺乏软件工程技能和商业理解的编码员。正如我们所提到的,通过正确定义业务和技术需求,快速工程将成为基于 Copilot 生成高质量代码的关键。因此,没有深厚业务和技术能力的编码人员和测试人员将很难为软件工程过程增加价值(正如解决方案本身的名称所暗示的那样,是副驾驶)。
根据这第一个兴衰列表,像 Copilot 这样的工具似乎将在软件开发行业创造/推动新的角色,同时破坏那些不会给软件创造过程增加真正价值的角色。你有什么想法?你会将哪些角色添加到这个兴衰列表中?
如果你喜欢阅读这篇文章,请 考虑成为会员 以便在支持我和媒体上的其他作者的同时,获得上的所有故事。
面向数据科学家的 GitHub 桌面
实践教程,教程|版本控制| GitHub 桌面
没有命令行中的版本控制可怕
放松,你不必在 Unsplash 上使用命令行|照片由丹尼斯·范达伦
版本控制对于代码协作、与他人共享代码、能够查看代码的旧版本,甚至自动部署代码都很重要。一开始可能会有点混乱,但是非常值得花时间,特别是如果您在开放源代码领域工作或者在一个经常使用项目版本控制的团队中工作。以下是一些值得使用的最大特性:
- 存储带有注释的文件更改历史
- 组织多个用户同时编辑同一个项目
- 简化代码审查程序
- 自动化工作流以报告问题、请求改进和部署代码
版本控制功能
版本控制的主要特性之一是存储库中每个文件的文件更改历史。这可以作为每个文件的变更日志,因此总是可以看到过去任何时候运行的代码。每当有人更新一个文件并将新版本推送到存储库时,他们都必须添加一个简短的注释。在一个完美的世界中,这详细描述了变化是什么以及为什么要进行这些变化。如果有任何关于为什么更改或为什么更改的问题,负责人将在提交中被标记,以及他们提供的附加信息。
版本控制的另一个特性是创建分支的能力。分支是保持独立的代码的新版本。这有助于对代码进行修改和测试,因为它不会改变主分支,那里是最新的工作版本。不同的用户也可以使用分支来同时处理不同的代码或特性。当这些分支准备好时,可以合并回主分支,并且在合并时有一个过程来协调它们之间的差异。
在与团队合作时,代码审查是最佳实践。一个人可能在一个新的分支中做一个新特性的所有工作,但是在盲目地将其合并到主分支之前,应该由团队进行评审。当创建一个 pull 请求来将代码移动到主分支时,它还会启动一个讨论,团队成员可以在代码合并到主分支之前讨论代码并请求更改。这个过程应该有助于改进投入生产的代码,以防止错误和中断,提高代码的效率,甚至使代码符合格式化代码的标准。
使用 GitHub 进行版本控制的最后一个值得注意的好处是它提供的自动化选项。如果有一个标准的代码审查清单,它可以作为一个模板被添加,当一个拉请求被创建时,它将是可用的,当审查任务被完成时,它可以被填写。当人们创建问题时,也可以使用模板,以便他们在创建问题时记住需要输入的所有详细信息。GitHub 还提供了支持自动化的动作。这些可以由不同的事件触发,比如将代码合并到主分支中。一个动作可以运行单元测试,构建/编译包组件,甚至将代码部署到生产环境中。
版本控制风格
有几个大名鼎鼎的版本控制你可能听说过。一些最流行的是 Git 和 GitHub。 Git 是版本控制的底层技术, GitHub 是简化版本控制工作流程的软件。
Git 可以在本地使用,不需要任何外部存储库。您可以在计算机硬盘上执行所有版本控制任务。本地 Git 存储库非常适合个人项目,或者当您还没有准备好与整个团队共享您的代码,但是仍然想要版本控制的好处时。
GitHub 网站是一个存储代码的仓库。GitHub 网站上托管了很多开源项目,比如 Python 和 R 包。对于公共存储库,任何人都可以查看修订历史、包的问题以及与之相关的文档。
要连接到 GitHub 网站上的存储库,我们可以使用 Git 或 GitHub Desktop。对于那些喜欢命令行界面(CLI)的人来说, Rebecca Vickery 有一篇关于使用 Git CLI 进行数据科学的精彩文章。那么你为什么要继续读书呢?命令行可能会令人生畏。想要一个图形用户界面(GUI)来管理您的版本控制并没有错。GitHub Desktop 为您的存储库提供了一个清晰简单的界面。
GitHub 桌面流程
虽然每个人对于他们的存储库都有一个稍微不同的流程,但是有一些通用的步骤来修改 GitHub 上的代码:
- 创建分支
- 添加提交
- 创建新的拉式请求
- 完成代码审查
- 合并拉取请求
创建一个分支会复制当前的生产代码。开发人员将对文件进行更改,将任何更改提交到新的分支。接下来,pull 请求将打开讨论,将新分支的变更添加到生产代码中,通常是在 master 或 main 分支中。代码评审者可以添加注释,并请求对拉请求所做的更改进行澄清。一旦审查完成并做出任何必要的更改,就可以将拉请求合并到主分支或主要分支并关闭。
让我们更详细地浏览这些步骤,看看如何使用 GitHub Desktop 完成每一步。
创建分支(将新代码与旧代码分开)
要进行更改,首先创建一个新分支。如果您拥有对存储库的完全访问权限,那么您可以简单地在存储库的 GitHub 站点上创建一个新的分支。
1a。点击分支:主
作者图片
2a。在文本框中键入新分支的名称。为了组织有序,您的组织可能需要考虑一些分支命名约定
作者图片
3a。点击创建分支
作者图片
现在将选择新的分支。
作者图片
如果您没有对存储库的完全访问权,这在公共项目中很常见,那么您将不得不分叉存储库。新分支和分叉是同义词。fork 将在一个新的存储库中创建,而不是与生产代码相同的存储库,通常在您的个人配置文件下。要分叉:
1b。在右上角,单击 Fork
作者图片
2b。等待文件复制
作者图片
3b。将选择新的分叉
作者图片
添加提交(增强代码/添加特性)
要提交代码,您需要将存储库克隆到您的本地计算机上。在将更新发送回存储库之前,这将为您复制要处理的代码。要将存储库克隆到您的本地计算机,请执行以下操作:
单击克隆或下载。
作者图片
点击用 GitHub 桌面打开。
作者图片
如果你没有 GitHub 桌面,点击下载 GitHub 桌面。
作者图片
GitHub desktop 会询问将存储库克隆到本地机器的哪个位置。这是本地路径字段。
作者图片
单击分支并选择新创建的分支。这将使用该分支上的任何更新来更新本地机器上的文件,并使其成为要添加提交的活动分支。
作者图片
要进行更改,请打开您在克隆时选择的目录,并像往常一样使用文本编辑器或集成开发环境(IDE)进行更改。保存文件。
返回 GitHub 桌面。GitHub Desktop 会不断扫描存储库文件夹树,并会看到您所做的任何更改。这些更改将显示在左侧窗格中。右窗格将预览对所选文件的更改(某些文件类型不会预览)。
作者图片
每当您做出一组相关的变更时,将这些变更提交到您的存储库中。记得在提交中添加注释,这样人们就可以很容易地识别出什么被改变了。上面的文本框用于快速描述,但是如果您有更多关于提交的注释,请将它们放在更大的描述文本框中。
做出更改并添加注释后,提交更改。
作者图片
提交更改只会将它们保存在本地文件中。要将更改推回 GitHub 服务器,请点按“推回原点”。如果有尚未推回服务器的提交,右窗格中将出现一条消息,说明将 xx 提交推送到源远程。origin 只是存储库被克隆的地方的名称。
作者图片
打开拉取请求
导航到 GitHub 服务器上的存储库。确保你在正确的分支上。如果您在原始存储库上创建了一个新分支,请导航到那里。如果您必须派生存储库,请在您的个人资料中导航到该存储库。
在拉动请求选项卡上,点击新拉动请求。
作者图片
选择新的分支作为要比较的分支,点击创建拉式请求。在我们的例子中,pull 请求会自动填充我们的 commit 注释。
作者图片
代码审查
代码审查有助于确保我们添加或更改的代码是正确的,并且已经过多人的审查和批准。无论您是否有权访问存储库,您都应该让审阅者检查变更。如果有任何问题,作为一个团队检查它们。
“拉”请求显示在存储库的“拉”请求选项卡下。每个“拉”请求都有一个“对话”、“提交”和“文件已更改”选项卡。
对话是人们可以添加关于代码的问题或评论的地方。您可以格式化您的评论,并在您的评论中标记人物和问题。
提交显示拉请求中的所有提交和注释
“更改的文件”显示了哪些文件被更改、添加或删除,并对可用的代码进行了逐行比较
作者图片
合并拉取请求
在我的例子中,当我在新的分支上工作时,我的主分支被改变了。这就是为什么有消息说有冲突要解决。单击解决冲突按钮将打开一个编辑器。它将显示来自每个分支的文件版本,允许您删除一个并保留另一个,或者创建两者的某个版本。
作者图片
在这种情况下,主分支的版本是正确的。可以删除来自其他分支和分隔符的更改。冲突可被标记为已解决,并提交给合并。
作者图片
随着代码审查和冲突的消除,拉请求可以被合并。这里将再次出现一个选项,对合并完成的内容给出一个注释。合并后,代码将成为主分支或主分支的一部分!
作者图片
现在你知道如何使用 GitHub 和 GitHub Desktop 完成最基本的版本控制任务了!
https://realdrewdata.medium.com/membership
进一步阅读
如何为 Python 数据科学项目创建 GitHub 存储库
了解如何使用 GitHub 存储库来共享和协作数据科学项目
克里斯蒂娜·莫里洛在 Pexels 上的照片
一、什么是 Git?
Git 是一个 版本控制系统——一个软件工具,允许开发者在一种特殊的数据库中跟踪和管理代码的变化。自从 2005 年由 Linus Torvalds 开发以来,Git 已经成为使用最广泛的版本控制系统之一。GitHub是一个 代码库托管服务 ,你可以免费使用它来分享和协作代码。
在协作项目中使用 GitHub 的一些优势是:
- 当代码中断时,开发人员可以返回到代码的早期版本,以识别孤立分支中的问题,从而最大限度地减少对项目其他方面的干扰。
- 独立的分支允许团队成员处理同一项目的不同方面,从而在不影响其他团队的情况下进行更改。
- 当变更完成时,它们可以被合并到主分支中。任何有冲突的变更都会被标记出来,以便能够解决。
GitHub 会记录您向 GitHub 贡献(或上传)文件的频率。这是向潜在雇主展示你对编程认真的好方法。
二。在 GitHub 上创建项目存储库
- 如果你是从零开始,看看用 Python 进行数据科学项目的一般设置、虚拟环境 I:用自制软件安装 Pyenv】和 Jupyter 笔记本 I:Jupyter 笔记本入门。正确的数据科学项目设置对于本教程非常重要。
- 确保您遵循了本教程前四部分中概述的步骤,并且您已经:
- 创建了项目文件夹
- 激活了项目文件夹中的新虚拟环境
3.导航到 GitHub.com。如果您没有帐户,请创建一个帐户。前往右上角靠近您个人资料图片的下拉菜单中的您的存储库选项卡
突出显示您的存储库的 GitHub 配置文件屏幕
4.在那里,点击右上角的绿色按钮,上面写着新**。**
新按钮在右上角。
5.输入唯一的存储库名称和简短描述。如果你愿意,你可以以后再改。存储库的命名约定建议使用由破折号分隔的小写名称(例如“my-project”)是最好的。将存储库设置为公共或私有。
注意:如果你正在跟随 日 教程中的数据,你现在可以将这个项目命名为“metal-project”并带有“日教程数据仓库”的描述。
创建具有名称、描述和隐私设置的新存储库。
6.当您到达页面底部时,不要选择“使用“初始化此存储库”部分中的任何项目。点击创建存储库。
完成创建您的存储库。
7.将出现一个新屏幕,上面有一些说明。下面,我将提供相同的说明,并为初学者提供一些额外的细节。
GitHub.com 上的说明截图
三。在本地初始化您的存储库
既然您已经在 GitHub.com 上创建了一个存储库,那么是时候通过将您在 GitHub.com 上创建的存储库初始化到您的项目文件夹中来将您的项目文件夹与您的存储库同步了。
1.打开终端并输入:
$ cd my-project
2.进入该页面后,您可以通过输入以下内容来初始化存储库(确保替换您的用户名):
git remote add origin https://github.com/username/my-project.git
git branch -M main
git push -u origin main
现在,存储库在您的本地项目文件夹中初始化。这就是我们将本地文件连接到在线存储库的方式。一旦连接上,我们就可以使用命令来推送(或上传)我们项目的新版本。GitHub 将跟踪变化和不同的版本。
动词 (verb 的缩写)下一步是什么?
- 在使用 Python 进行数据科学项目的一般设置中,您通过安装 CLT、Xcode、Hombrew、Python 和 Pip 安装了入门所需的基础包。
- 在Virtual Environments I:Installing Pyenv with home brew中,您学习了如何在 Mac OS Big Sur 上使用 Pyenv、Virtualenv 和 Pip 为您的 Python 数据科学项目创建虚拟环境。
- 在Jupyter Notebooks I:Jupyter Notebooks Getting Started with Jupyter Notebooks中,您通过创建一个内核规范将 Jupyter Notebooks 链接到您项目的虚拟环境。
- 最后,在本教程中,您在 GitHub.com 上创建了一个 GitHub 存储库,并在本地初始化了该存储库(在您自己的计算机上)。
在下一节“Python 初学者数据科学基础”中,您将创建一个 Jupyter 笔记本来记录您的项目,我将向您展示如何通过将这个笔记本推送到 GitHub 存储库来进行第一次提交。
感谢阅读!
👩🏻💻克里斯汀·伊根◇ 克里斯汀-伊根. xyz
GitHub 和预训练模型:锁眼视图
GitHub 包含预先训练的模型,这些模型可能包含固有的偏见,模型记分卡的缺乏将有助于放大用户对这些回购的偏见。
设置上下文
GitHub 是一个著名的软件代码及其版本控制的互联网托管平台。GitHub 使其 5600 万用户(组织和个人)能够在平台上创建他们的作品的存储库,以便于访问、版本控制以及在有或没有许可的情况下共享(Apache License 2.0)。对于研究人员来说,GitHub 是一个指向他们工作的资源目录。此外,对于开源其工作/解决方案的大型组织来说,GitHub 使其可以被社区访问。
GitHub 上有超过 1.9 亿个公共知识库。这些存储库包含源代码、文档、API、数据集和其他与源代码相关的元数据信息。GitHub 允许用户派生(创建存储库的副本)、提交(更改历史)和发出拉请求(原始存储库的更改通知)。这使得能够重用平台上的现有内容。在机器学习的情况下,有超过 331,000 个储存库包含 ML 模型、它们的源数据、结果、度量和与它们相关的分析。
来源:等距的人与技术自由矢量( Freepik )工作
迁移学习和内在挑战
GitHub 仍然是支持迁移学习和利用现有模型或源代码的最大平台。迁移学习是利用从解决一个问题到解决另一个相似或不同问题的知识的过程。这有助于通过协作和开源有效地优化现有内容。虽然这种优化放大了可能性,但它也放大了源代码中的错误和偏见,这可能会伤害人和组织。
例如,GitGuardian 在其报告(2021 年 GitHub 上的秘密蔓延状态)中提到,包括 API 密钥、凭证和敏感信息在内的信息都在 GitHub 的公共存储库中。这使得存储库容易受到攻击(不仅是网络攻击,还有数据中毒攻击),从而对组织和个人造成伤害(此处)。
类似地,偏见可以存在于公共知识库上的自然语言处理模型(单词嵌入)中的预先存在的偏见(潜在的或其他的)、技术偏见(特征选择和权衡决策)和紧急偏见(设计和基础事实之间的价值或知识库的不匹配)的性质中。这些模型是在公共数据集上训练的,也可能造成伤害。研究表明,模型或公共数据集中的潜在偏见导致了性别歧视(此处)。值得注意的是,数据科学家做出的优化选择和权衡决策也可能导致模型中的偏差。根据上下文和模型部署的方式,从原始存储库中派生或改编的模型也可能会导致或有时会放大危害的程度。
底层根源
潜在的问题是,GitHub 作为一个存储库包含的源代码或模型在被带到平台上之前没有经过验证。此外,GitHub 的方法是使社区能够在各自的存储库上互相审查、评论、使用或共享 bug 或挑战(称为“问题”)。然而,在社区中对潜在问题的认识不一致的情况下(特别是在新兴研究领域),这种方法可能是不够的。此外,GitHub 并不强制要求在用户入职、声明流程或存储库创建流程中签署行为准则(仅作为建议)。
GitHub 社区指南提供了一个机会,通过表单提交流程,在审核存储库的同时报告滥用和报告内容。此类提交的当前选项包括“我要报告有害代码,如恶意软件、网络钓鱼或加密货币滥用”。然而,鉴于机器学习模型造成的危害的影响,有必要包括更多具体涉及偏见和歧视的选项。
这不是一个孤立的挑战。在使用 Imagenet 数据集(这里的、这里的和这里的)开发的图像识别模型中,也存在类似的偏见和歧视挑战。如果迁移学习是采用正在变得民主化的新兴技术的途径,那么有必要理解,在当前的形式下,这些民主化并非没有危害。
需求:预培训模型的记分卡
需要为 GitHub 上的 预训练模型 或代码建立记分卡。记分卡应包含关于模型或其基础训练数据是否经过偏见、网络安全或恶意攻击等测试的整理回答。在公开存储库之前,还应收集关于使用模型的限制或可以使用或不可以使用模型的环境、与使用此类模型相关的注意事项等信息。虽然这看起来对 GitHub 用户有很大的期望,但它不可避免地是相关的,并且旨在为社区和广大人民的福祉做出贡献。应该要求用户在用代码更新存储库时更新这些信息,并且应该通知用户从记分卡的角度查看存储库,反之亦然。
像 GPT-3 这样的储存库在储存库上包含特定的模型卡,包括对模型使用的期望、模型的限制和潜在偏差的可能性(此处为)。这是最佳实践之一,因为您在 GitHub 上的许多其他公共存储库中找不到类似的参考资料。然而,即使这样的最佳实践披露也不够具体,不足以分享团队为验证模型免受偏见或敌对攻击所做的努力。
结论
鉴于 GitHub 的“Copilot”的宣布,这是至关重要的,Copilot 是一种人工智能工具,在平台上的数十亿行代码上进行训练。该工具有望为用户的项目生成补充代码。除了这个工具的合法性问题之外(这里是),一个相关的问题是“你会舒服地使用一个有潜在偏见的代码或模型吗?”。记分卡不是目的,而是一种在机器学习中民主化迁移学习的同时带来上下文视图的手段。
GitRater —预测您的 GitHub 档案的质量
使用机器学习来预测你是否擅长编码
如果你曾经申请过技术职位,你可能会给公司发一个你的 GitHub 简介的链接。这个档案中的信息可以很好地表明你的编码能力和是否适合团队。所有这些信息的不利之处在于,招聘人员可能需要很长时间来评估这些信息。为了节省时间,机器学习有可能被用来自动评估你的编码能力。
来源: flaticon
在本文中,我们将带您了解构建这样一个模型的过程。我们讨论如何从 GitHub 收集数据,并使用这些数据创建模型特征。为了建立一些直觉,我们探索数据集中的关系。最后,我们比较和解释了两种最大似然算法——决策树和随机森林。你可以在 GitHub 上找到这个分析的代码,在 Kaggle 上找到数据集。
数据收集和特征工程
从您的代码库到您关注的其他程序员,您的 GitHub 个人资料中有许多公开信息。我们构建了一个 web scraper,从 230 个用户的个人资料中收集了一些数据。例如,您将在任何用户的概览页面上看到与图 1 中相似的贡献列表。当用户编写新代码并将其保存到他们的一个代码库(repos)时,他们就做出了贡献。
图 1: GitHub 贡献(来源:作者)
通过搜集这些数据,我们最终得到了去年每天所做贡献的列表。为了能够在模型中使用这些数据,我们首先需要做一些特征工程。有几种方法可以做到这一点。比如我们可以统计最近一年的投稿总数( n_cont )。我们还可以获取自他们最后一次投稿以来的天数( last_cont )。这些贡献只是我们可以用来创建模型特征的 GitHub 概要文件的一个方面。
图 2: GitHub 工具条(来源:作者)
图 2 显示了用户侧边栏中的一些可用信息。由此,我们可以获得关注者的数量,以及用户已经标记的存储库的数量( stars )。这些已经是数字了,所以不需要特征工程。最后,我们还从组织信息中创建一个标志( org_flag ),它将表明用户是否是组织的一部分。
最后一组特征来自用户的回复。在图 3 中,我们可以看到一些代码回收的例子。我们收集了用户创建的回购总数(回购)。我们还收集了每个回购协议中使用的编码语言。由此,我们统计了所有用户回复中使用的不同编码语言的数量( n_lang )。
图 3: GitHub 存储库(来源:作者)
表 1 总结了所有创建的模型特征。除了 stab_cont 、 foll_ratio 和 **cont_repo_ratio、**这些我们上面都讨论过。还可以创建其他信息源/特征。我们将自己限制在这个集合中,因为它们相当简单,数据也很容易收集。希望这些特征至少与允许我们做出准确预测的编码能力有关。具体来说,我们将尝试使用它们来预测从 0 到 5 的评分。
表 1:模型特征列表
此评级是通过取两个独立评级的平均值得出的。重要的是,评价者并不局限于上述特征中包含的信息。例如,评价者可以打开 repos 中的文件,阅读实际编写的代码。在浏览了一个档案之后,每个评价者根据用户的编码水平给出一个等级,从 0 到 5 (5 是最好的)。两次评级的平均值作为最终评级/目标变量。
数据探索
在我们开始建模之前,探索一下我们的模型特征是一个好主意。我们这样做是为了建立直觉,并了解哪些功能将有助于预测评级。图 4 中可以看到一个潜在的好预测器的例子。在这里,我们可以看到额定值和 n_cont 之间的关系。请注意,随着用户总贡献的增加,用户的评级往往也会增加。
图 4:评级与贡献散点图
此时,你应该问问自己这段感情有没有意义。没有贡献或贡献很少的用户在过去的一年中不会做很多编码工作。做了很多贡献的用户会做很多编码。这似乎是合乎逻辑的——你编码得越多,你就越擅长编码。我们的模型有望利用这种关系进行预测。
另一方面,你可以看到评分和带星库数量的关系(星)。在这种情况下,似乎没有任何模式。也许这是因为你不需要做任何编码就可以启动其他用户的回复。也就是说,星星不会告诉我们任何关于你编码能力的事情。从这个分析中,我们不应该期望星星是我们模型中的一个重要特征。
图 5:评级与星级散点图
另一个潜在的重要特征是组织标志。我们可以期待组织中的用户成为更好的程序员。特别是,如果他们是像谷歌开源社区的一部分。在下面的方框图中,我们可以看到,属于某个组织的用户的评分往往更高。没有组织的平均评分为 1.8,而当用户是组织的一部分时,平均评分为 3.4。这种差异表明 org_flag 可能是一个很好的预测器。
图 6:评级与组织标志箱线图
我们应该记住,这些特征不是孤立存在的。看似具有预测性的特性,当它们与其他特性一起包含在模型中时,可能并不那么重要。这是由于特征本身之间的关系。例如,在图 7 中,我们可以看到贡献更多的用户更有可能成为组织的一部分。具体来说,贡献 500 英镑或更多的用户中有 70%是某个组织的成员。然而,对于那些缴款少于 500 英镑的人来说,这一比例仅为 20%。
图 7:评级与贡献-组织散点图
假设我们创建一个只有 **org_flag 的模型。**根据上述分析,组织中的员工可能会获得更高的预测评级。我们可以通过在模型中添加 n_cont 来改进这些预测。同样,贡献较大的人可能会获得较高的评级。然而,许多具有高贡献的用户将是组织的一部分。这意味着他们可能已经被给予了很高的评级,所以包括 n_cont 可能不会像我们想象的那样改善这些预测。最终, n_cont 的重要性实际上取决于它给出的信息比 org_flag 给出的信息多多少。
来源: flaticon
决策图表
考虑到我们的探索性数据分析,是时候继续建模了。我们将从创建一个简单的决策树开始。为此,我们首先分割数据集,并使用 200 行来训练决策树。我们保留剩余的 30 行作为测试集。决策树是使用基尼系数来决定每个节点的最优分割。我们还将树限制为每个叶节点至少有 10 个样本。您可以在图 9 中看到整个决策树。
为了理解这棵树是如何工作的,让我们从根节点开始。如果用户满足第一行中的规则(即,至少做出了 105 个贡献),我们将沿着树中的右箭头向下。如果不满足该规则,我们将遵循左箭头。我们不断地检查规则并跟随箭头,直到到达一个叶节点。例如,如果一个用户做了 900 次贡献,并且有 90 个关注者,那么我们将到达用红色圈出的叶节点。17 个用户最终在这个桶中,并且他们被给予 4.603 的评级。
图 9:决策树
下一步是使用这个模型对测试集进行预测。为了评估这个模型,我们应该将实际评分与这些预测进行比较。一种方法是使用图 8 中的散点图。如果模型是完美的,所有点将落在红线上(即实际=预测)。黑色虚线距离红线一个单位。这意味着,与实际评级相比,只有 2 个预测的差异超过 1。总体而言,该模型在测试集上的 MSE 为 0.3077。
图 8:决策树实际评分与预测评分
随机森林
决策树通常被认为是一个简单的 ML 模型。让我们看看能否使用更复杂的方法——随机森林——来提高这一精度。具体来说,我们使用一个有 100 棵树的随机森林。每棵树的最大深度限制为 4。与决策树一样,您可以在图 10 中看到实际评分与预测评分的对比图。
同样,我们有 2 个预测的误差超过 1 个单位。就 MSE 而言,似乎确实有所改善。测试集上的 MSE 为 0.2691,比决策树低 12.5%。在决定使用哪种最终模型时,应该将精确度的提高与使用更复杂模型的缺点进行权衡。
图 10:随机森林实际与预测评级
其中一个缺点是我们不能像解释决策树一样解释随机森林。换句话说,我们不能简单地将整个模型可视化,如图 9 所示。这意味着我们对模型如何做出预测的理解会更差。为了解释这个模型,我们将不得不使用额外的技术,比如特征重要性分数。
我们可以在图 11 中看到随机森林的特性重要性分数。一般来说,特征的重要性越大,该特征在进行预测时就越有用。我们可以看到 n_cont 是迄今为止最有用的,其次是回购和追随者。我们可以看到星星并不是很重要。这与我们的探索性分析是一致的。不一致的是 org_flag 最不重要。看起来这个特性并不像我们预期的那样重要。
图 11:随机森林特征重要性
想法和未来的工作
在任何模型中,都有需要解决的弱点。我们应该努力理解的一个方面是为什么 n_cont 比其他任何特性都重要。参见图 12,当您第一次打开某人的个人资料时,贡献会立即吸引您的注意。这可能会对评定者的决策过程产生影响。换句话说,他们对捐款的依赖可能超过了他们的意愿。
图 12: Github 概述页面
评级也可能在其他方面出现偏差。例如,如果评价人考虑用户的档案图片,可能会引入种族/性别偏见。为了解决这个问题,我们需要一个客观的评级系统。它应该只考虑与编码能力直接相关的信息,并且该信息应该更统一地呈现。
在实践中,不同的公司或团队的评级系统可能会有所不同。对于给定的用户,数据工程团队可以给数据科学团队一个完全不同的评级。这是因为每个团队所需的技能不同。换句话说,评级将捕获用户在特定团队中的表现,而不是他们在总体编码方面的表现。
来源: flaticon
围绕特征工程也有很多工作可以做。到目前为止,我们所使用的功能实际上只是与编码能力相关。做出很多贡献并不能让你成为一个好的程序员。只是好的程序员往往会做出很多贡献。我们应该尝试从实际编写的代码中创建功能。例如,我们可以识别用户是否使用了单元测试,使用了一致的命名约定,或者正确地注释了他们的代码。
总的来说,使用机器学习来预测编码能力似乎是可能的。使用一个相当简单的方法,我们可以做出与实际评级一致的预测。希望这将为将来更好的模型打下基础。
我们提到了性别/种族偏见。机器学习中的这种偏见比许多人意识到的更普遍。亚马逊使用的一个系统就是一个例子,该系统不以性别中立的方式对求职者的简历进行评级。我们将在下面的文章中讨论这一点以及其他一些有偏差的算法:
图像来源
所有图片都是我自己的或从www.flaticon.com获得的。在后者的情况下,我拥有他们的高级计划中定义的“完全许可”。
给 Python 插上翅膀——实现更快 Python 程序的简单技巧
编写优化且更快的 Python 程序的策略汇编
Python 不是特别快,但它是最受欢迎的编码语言之一,尤其是在数据分析方面。有趣的是,使它天生缓慢的原因也使它成为最受欢迎的语言。
- 动态类型化 —用户不必提供变量的数据类型。这让用户的生活更轻松,但给解释者带来了麻烦。
- 已解释,未编译 — Python 被解释为未编译,这意味着它不能提前对程序进行内存和速度的高级优化。
- 内存问题——由于 Python 的灵活性,每个元素都有自己的内存,而不是一个连续的内存块。它会在提取操作过程中造成时间延迟
资料来源:联合国人类住区规划署
尽管有这些问题,我相信大多数缓慢进入系统可以归因于程序员编写简洁、优化程序的能力。这些年来,我在处理数据、构建模型、将不那么优化的代码投入生产的时候犯了很多错误。但是所有这些经历为我提供了一些工具,我一直用这些工具来使我的代码更干净、更快、更 pythonic 化(不管那意味着什么)。
让我们看看那是什么。
创可贴解决方案
如果你有很多时间,那么你可以把你的 Python 代码转换成 C/C++,然后在上面写一个 Python 包装器。它将为您提供 C++的速度,并保持 Python 的易用性。
但是,我们不希望这样,因为有更简单的解决方案。
Numba 走进房间。
好吧,我告诉你 Numba 从 2012 年就开始出现了,但对许多程序员来说仍然是难以捉摸的。
它本质上是把你的 Python 代码转换成机器码,速度和 C 代码差不多。
让我们用一个简单的例子来验证一下。一个简单的功能,没什么重的。
在具有 6 个内核的 i7 机器上,每循环 1.43 秒。看起来很慢,但肯定可以改进。
使用 pip 在您的机器上安装 numba
pip install numba
我们所做的只是添加了两行代码,import 和@jit(nopython=True)
每循环 14.5 毫秒。
那就是 1430/14.5 ~ 98X 的速度增益。
收益当然取决于你的机器和你到底想做什么,但如果你想快速解决问题而又不想过多地陷入代码的罪恶中,这是一个很好的起点。
- 它通常在你不得不处理令人烦恼的循环时起作用
或者,
- 其中需要对大集合执行相同的操作。
侧写师
您需要找出代码的哪一部分使它变慢了。在大多数情况下,这将是一些错误形成的循环或函数,这将是麻烦制造者。
Unix 计时器
在 shell 上,在调用 python 和您的代码之前,您需要使用 Unix 的 time 命令。
cProfiler
您可以从 shell 中运行 cProfiler,方法是调用
python -m cProfile -s time name_of_your_file.py
它会让你淹没在大量的信息中,所以你需要做些别的事情。
您可以在代码中导入 cProfile,并在您怀疑会使您陷入困境的函数上运行它。
import cProfile
cProfile.run('complicated_func()') #*Here I am running it on a complicated_function that has time overheads.*
输出可以放在文件中,也可以在 shell 上看到。
cProfile.run('complicated_func()', 'output.txt')
舒马赫速度
到目前为止,它是关于创可贴解决方案以及如何对您的代码进行时间配置,让我们来看看某些策略,它们不仅是最佳实践,而且还能为您加快速度。
发电机节省内存,提高速度
列表是很好的,但是如果你正在处理一些需要延迟生成的列,那么生成器会更好。
使用生成器带来的性能提升是延迟(按需)值生成的结果,这意味着更低的内存使用率。此外,我们不需要等到所有的元素都生成之后才开始使用它们。
上面的代码片段为列表使用了 87,616 字节的内存,而生成器只使用了 112 字节的内存**。**
节省下来的内存可以让你的代码运行得更快,因为 CPU 正在处理的所有数据都应该在缓存中;如果使用列表,那么数据溢出到 L1 缓存的可能性更大。
范围内的枚举
这更多的是一个 干净代码 的原则,而不是与速度有关。如果您不仅需要处理数据的索引,还需要处理数据本身,那么在 Python 3.8 上,enumerate 是一个更干净、更好、也更快的选择。
进口
如果你打算只使用一个函数,不要导入整个库和包。
import math
value = math.sqrt(50)vsfrom math import sqrt
value = sqrt(50)
当编写生产级代码时,如此小的开销累积起来会达到惊人的比例。
明智地使用 Itertools
尽可能使用 itertools,它们可以节省大量时间,尤其是在避免 for 循环方面。
from itertools import productdef cartesian_prod (arr1, arr2):
return list(product(arr1, arr2))arr1 = [1,2,3]
arr2 = [4,5,6]
cartesian_prod(arr1, arr2) # Output is
[(1, 4), (1, 5), (1, 6), (2, 4), (2, 5), (2, 6), (3, 4), (3, 5), (3, 6)]
如果您正在处理一个问题陈述,比如推荐系统,并且想要用户项的组合,那么通过 itertools 计算笛卡尔积是一个明智而安全的选择。
人们还可以使用 itertools 的排列组合功能来减轻生活中的一些痛苦。
只用 f 弦系住你的琴弦
不要对字符串使用任何旧的方法,比如%s 或 format(),f 字符串非常快,而且更容易使用
传统 for 循环的列表理解
一般来说,for 循环(至少比 while 循环好)很慢,如果你开始使用两个嵌套循环,那么复杂度将会是 n。
对于传统的 For 循环,时间是 136 毫秒
对于列表理解,它是 118 毫秒
这不是一个很大的改进,但是代码看起来更干净,并且只用一行代码就完成了。
类似地,使用 map、filter 和 reduce 函数可以减轻代码的时间和空间复杂度。
资料来源:Giphy
你的硬件是什么?
十有八九,你可能在 SSD(固态硬盘)上运行你的代码。如果你已经达到专业水平的 python 编程,那么你检查 SFrames,可伸缩框架的缩写。它们在固态硬盘上的大型数据集上工作得非常好,比熊猫好得多。
人们可以使用 turicreate(graph lab 的免费版本)在代码中使用 SFrame。
结论
有许多方法可以优化代码的性能。所有上述策略都经过了尝试和测试,但它们不是快速解决问题或万无一失的解决方案,因为它们在某种程度上取决于您运行它的数据和您使用的硬件。
还有许多其他方法,如使用局部变量、并发和多线程,也有助于实现更快的速度。
编码时,遵循最佳实践,而不是抄近路,因为生产环境非常敏感,您不希望花费无数时间回顾您在亿万年前编写的东西。
通常在代码库的可读性和优化之间有一个折衷。孰先孰后的决定取决于你。
给你的图表一些(空白)空间!
理解空白在数据可视化中的重要性的 3 个步骤——以及如何将理论应用于实践
伊莲娜·乔兰在 Unsplash 上的照片
当查看任何数据可视化时,我们大多数人首先关注的是以几何形状、数字、颜色等形式显示的内容。一句话:作为人类,我们直觉上倾向于最关注图表中的“哇”元素。然而,正是空白的使用让我们能够理解图表——而不仅仅是看到形状、数字和颜色的增加。
我邀请你以你最近看到的任何图表为例。当然,你会先看我前面提到的元素。但是再看一遍:图中不是“wow”元素的其余空间怎么办?图形本身周围的所有空间呢?图形中两个文本块或两行之间的空间呢?正是这些空白的使用让你有可能理解这个图表。为了让你相信这一点,想象一下没有任何空白的同一个图形!
图 1 —玛丽·勒费夫尔
1.空白真的重要吗?
先说一个定义。我在这里定义的白色空间不是指“宇宙”,也不是指房间里的白色墙壁。本文重点介绍空白,即图中没有显示任何内容的所有空间:没有颜色,没有文本,什么都没有。有些人使用术语“负空格”来指代页面中未标记的区域。如本研讨会课程中关于数据可视化的所述:
“负空间和所使用的轴、文本和形状一样,都是整体设计的一部分。它需要给元素呼吸的空间,并提高形象的视觉吸引力和效果”。
为了证明空白的重要性,让我举一个你肯定知道的例子:联邦快递的标志在 E 和 x 之间隐藏了一个指向右边的箭头,你也可以在本文中看到其他公司标志使用负空格的例子。出于版权原因,我不会在这里展示他们的标志。这些公司使用空白来揭示其标志中隐藏的符号或含义,这突出了他们的品牌,并使他们的名称和视觉身份对潜在客户来说是难忘的。这就是留白的强大之处:负空间比彩色空间更能告诉我们公司的信息。
第二个证明空白空间重要性的例子是媒体平台本身。你有没有注意到 Medium 的文章的文字边距有多宽?媒体文章的行距和整体设计充分利用了留白空间。结果是显而易见的:对于读者来说,阅读间隔良好的文本要比紧凑的线条舒服得多。总的来说,这种类型的设计有助于更清楚地传达文章的信息,同时文章的视觉效果由围绕它们的空白空间突出。
图 2 — 玛丽·勒菲弗尔
2.数据可视化中的空白怎么办?
既然您已经理解了空白有多重要的理论,那么让我们开始数据可视化领域的实践吧。在图表和信息图中,我们可以确定两种类型的空白,我们将在本文的下一部分讨论:
- 宏观空白区域是图形主要部分周围的所有空间,也就是说,活动的核心发生在这里
- 微空白是所有的间隙空间,例如文本的两个字母之间、数字和轴之间、两条图形线或条之间
更形象地说,我收集了基于名义 GDP(国内生产总值)的十大经济体 2009 年至 2019 年间生育率演变的数据。你可以在我们的数据世界的网站上找到我在这里使用的数据集的来源。让我先给你展示一下这张图的一个不太理想的版本:
图 3 —玛丽·勒费夫尔
下图突出显示了该图中的宏观(蓝色)和微观(红色)空白区域:
图 4 —玛丽·勒费夫尔
3.如何优化图表和信息图中的空白?
在之前的文章中,我探讨了玩颜色如何影响同一图表的含义。在这里,让我们一起探索如何利用图表的空白对数据可视化的两个关键方面产生重大影响:图表的可读性和所传达信息的有效性。
首先,在图表周围添加一些宏观空白会给你的图表空间。当包含在研究论文或文章中时,添加宏观空白可以确保你的图表充分融入你的正文。顺便说一句,你可以注意到我是如何在整篇文章中应用这条建议的,尤其是在上面的图中故意添加空白的时候。在这里的行间添加一些微小的空格将会对你的读者产生影响:增加两个国家之间的间距使读者更容易区分每个国家分别从 2009 年到 2019 年的数据(见图 5)。
图 5 —玛丽·勒费夫尔
其次,让我们关注空白如何能够支持图表作者想要传达的信息。在我的例子中,假设我想突出显示列表中的前 3 个国家,例如,因为我对根据不同指标(总人口、GDP、贸易平衡等)比较前 3 个国家特别感兴趣。).在这种情况下,在第三个国家和第四个国家之间添加一个更宽的空间将突出我作为图形创建者的目的(见图 6)。
图 6 —玛丽·勒费夫尔
结论:空白≥“Wow”元素
我的最后一句话实际上就是这篇文章的标题:请给你的图表留白!除了美学方面的考虑,在数据可视化中使用留白在使您的图形适合您的故事以及向您的受众传达正确的信息方面起着至关重要的作用。
我对您关于如何最好地组织数据可视化空间的建议很感兴趣,请不要犹豫,分享您对这个主题的想法!
你喜欢阅读这篇文章吗? 成为会员 加入一个不断成长的充满好奇心的社区吧!
在物理引擎中实现遗传算法控制
人工智能在物理引擎中的应用简介
Vishnu Mohanan 在 Unsplash 上的照片
人工智能最常见的商业应用是获得洞察力或对数据集进行预测。尽管我认为这很有趣,但是这些技术已经被其他人广泛地讨论过了。
本文涵盖了机器学习的一个更具实验性的应用:这是允许机器学习操纵物理模拟。
概念:
将人工智能放入物理环境有很多不同的可能性,但所有这些都涉及到操纵和控制环境中的对象和力。为了从这个项目中获得好的结果,我们需要给人工智能在环境中的控制增加限制。
照片由 Med Badr Chemmaoui 在 Unsplash 拍摄
我决定的限制如下:人工智能必须生成一个 n 边多边形。多边形的每个点都有一个以固定速度旋转的分支。这个旋转速率是由 AI 定义的。
遗传算法需要一个适应度函数来随着时间的推移改进代理。在这种情况下,将根据两个因素来判断代理:速度和面积。在这种情况下,速度被定义为在 100 帧中行进的 x 距离。面积是由多边形的点围成的空间。面积被考虑在内,以防止需要更复杂的编码来添加空气阻力对生物的影响。
我们希望速度最大化,面积最小化。我们可以得出结论,智能体的适应度可以是速度/面积。这将使得适应度与速度成正比,与面积成反比。希望我们最终能拥有移动迅速、体积小巧的“生物”。这意味着一个类似的生物在现实中应该站得住脚,这给了这个项目更多的实用价值。
实施:
我将只添加代码中有趣的部分,因为代码的其余部分不需要任何解释。如果想要项目的完整代码,可以在这里找到。
物理模拟基础:
我在这个项目中使用的物理引擎是基于 pymunk 库的,它包含了使这个项目工作的所有部分。
下面的脚本是一个可以由模型生成的布娃娃的例子。
列表“vs”是构成布娃娃主体的点的列表。“肢体”列表是定义每个肢体的向量长度的列表。循环通过将肢体添加到身体的每个点来构建身体。这是模拟的 gif 图:
由作者创建
健身功能:
这是控制选择保留哪些代理的适应度函数。这个适应度函数为每个代理运行物理模拟。
每个智能体都有三个独立的神经网络,即“运动网络”、“身体网络”和“手臂网络”。运动网络为每个肢体生成运动速度,身体网络定义身体上每个点的坐标,手臂网络定义每个肢体的长度。这两种神经网络都将随机值作为输入。
模型有一个最终的双曲正切值(范围为-1 到 1)。然后乘以一个常数值,作为网络的范围。这是为了使模型可以创建多用途的结果,同时防止非常大或非常小的机构。这允许一些一致性,以便更好地比较。
身体的定义在第 26–29 行:对于身体上的每个点,添加一个手臂,连接类型为“枢轴关节”。枢轴关节只是一个围绕单个点旋转的关节。“简单的马达”仅仅意味着转速是一致的。
在药剂被放入一个大盒子之前,身体和马达已经安装好了。对于定义的步数,代理移动。代理运行的距离可以由它的身体位置的 x 维变化来定义。
我将单独讨论遗传算法,因为它更复杂,而且我在最近的项目中使用了很多。
结果:
以下是该算法创造的更多生物:
由作者创建
这种生物的身体很瘦,但手臂很短,而且确实会导致过多的净移动,从而导致体能下降。
由作者创建
瘦弱的身体和不同的旋转方向/速度使这种生物获得了比其他生物更高的分数。
由作者创建
对称的运动导致不多的运动,因此健康值低。
结论:
这个项目花了很长时间来拼凑,因为我尝试了许多不同的方法来使用物理环境。幸运的是,在我放弃这个项目之前,我找到了 pymunk。
这个项目的一个巨大限制是缺乏可以逐渐移动而不是旋转的关节/马达。我计划创建/找到一个功能,可以改变每一步的旋转角度/方向,允许像 LSTMs 更复杂的模型的实现。
我仍然认为这个项目很有趣,足以让我继续研究更多基于物理的优化问题。
我的链接:
如果你想看更多我的内容,点击这个 链接 。
给谷歌云上新的统一 ML 平台 Vertex AI 一个旋转
我们为什么需要它,无代码 ML 培训到底有多好,以及所有这些对数据科学工作意味着什么?
过去几个月,谷歌云人工智能平台团队一直在构建机器学习前景的统一视图。这是今天在谷歌 I/O 发布的顶点人工智能。这是什么?有多好?对数据科学工作来说意味着什么?
有什么好统一的?
这个想法是机器学习中有几个关键的结构:
- 我们通过接收数据、分析数据和清理数据(ETL 或 ELT)来创建数据集。
- 然后我们训练一个模型(模型训练)——这包括实验、假设检验和超参数调整。
- 当有新数据时,在计划中,或者当代码改变时,该模型被版本化和重建(ML Ops)。
- 对模型进行评估,并与现有模型版本进行比较。
- 该模型被部署并用于在线和批量预测。
然而,这取决于您如何进行 ETL(您是否将数据存储在 CSV 文件中?TensorFlow 记录?JPEG 文件?在云存储中?在 BigQuery?),剩下的管道就变得很不一样了。有一个 ML 数据集的想法不是很好吗?任何下游模型(TensorFlow,sklearn,PyTorch)都可以使用的?这就是统一数据集概念背后的含义。
Vertex AI 为 ML 生命周期提供了一套统一的 API。图表由亨利·塔彭和布莱恩·科巴什卡瓦提供
此外,部署 TensorFlow 模型的方式不同于部署 PyTorch 模型的方式,甚至 TensorFlow 模型也可能因使用 AutoML 还是通过代码创建而有所不同。在 Vertex AI 提供的一组统一的 API 中,你可以用同样的方式对待所有这些模型。
Vertex AI 提供了四个概念的统一定义/实现:
- 一个数据集可以是结构化的,也可以是非结构化的。它管理包括注释在内的元数据,可以存储在 GCP 的任何地方。认识到这是远景——目前只支持云存储和 BigQuery。还不是 Bigtable 或 Pub/Sub。
- 训练管道是一系列容器化的步骤,可用于使用数据集训练 ML 模型。容器化有助于通用性、可再现性和可审计性。
- 一个模型是一个带有元数据的 ML 模型,它是用训练管道构建的或者是直接加载的(只要它是兼容的格式)。
- 用户可以调用端点进行在线预测和解释。它可以有一个或多个模型,以及这些模型的一个或多个版本,并根据请求进行消歧。
关键的想法是,无论数据集、训练管道、模型或端点的类型如何,这些工件都是相同的。都是混搭。因此,一旦创建了数据集,就可以将其用于不同的模型。无论你如何训练你的模型,你都可以从一个端点获得可解释的人工智能。
这一点在 web 用户界面上显而易见:
好了,说够了为什么。让我们兜一圈。
带 BigQuery 的 SQL 中的 ML
当你使用新技术训练一个 ML 模型,并将其与你知道和理解的东西进行比较时,这总是好的。
我将使用 Kaggle 上的 Airbnb 纽约市数据集来预测公寓租金的价格。
首先,我们将数据加载到 BigQuery 中。这个数据集有点笨拙,在我将它加载到 BigQuery 之前需要清理(详情见的博文),但是我将它公之于众,所以你可以简单地尝试一下这个查询:
SELECT
neighbourhood_group, neighbourhood, latitude, longitude, room_type, price, minimum_nights, number_of_reviews, reviews_per_month, calculated_host_listings_count, availability_365
FROM `ai-analytics-solutions.publicdata.airbnb_nyc_2019`
LIMIT 100
已经验证了数据现在看起来是合理的,让我们继续训练一个 xgboost 模型来预测价格。这就像添加两行 SQL 代码一样简单:
CREATE OR REPLACE MODEL advdata.airbnb_xgboost
OPTIONS(**model_type='boosted_tree_regressor', input_label_cols=['price']**) ASSELECT
neighbourhood_group, neighbourhood, latitude, longitude, room_type, price, minimum_nights, number_of_reviews, reviews_per_month, calculated_host_listings_count, availability_365
FROM `ai-analytics-solutions.publicdata.airbnb_nyc_2019`
我们得到一个快速收敛的模型
…平均绝对误差为 64.88 美元。
这有多好?Airbnb 上纽约市公寓的均价是多少?
SELECT
AVG(price)
FROM `ai-analytics-solutions.publicdata.airbnb_nyc_2019`
一共是 153 美元。所以,我们有 40%的折扣。也许不是一个投入生产的模型…但你不会期望一个公共数据集有更多的专有和个性化的数据来帮助改善这些预测。不过,这些数据的可用性有助于我们了解如何训练 ML 模型来预测价格。
接下来,我们来试试 Vertex AI 中的 Auto ML 表格。
顶点人工智能
让我们从 Kaggle 上的 CSV 文件开始,这样我们就不会被我将数据加载到 BigQuery 时所做的数据转换所困扰。转到https://console.cloud.google.com/vertex-ai/datasets/create
- 将其命名为 airbnb_raw,选择表格、回归,选择爱荷华地区,点击创建
- 创建数据集后,从 GCS 中选择 CSV 文件,提供 URL:GS://data-science-on-GCP/Airbnb _ NYC _ 2019 . CSV,然后点击继续。
- Vertex AI 愉快地加载数据,没有任何限制,拉出标题并显示 16 列。
- 单击 Generate Statistics,它会向您显示在缺少值方面唯一可能有问题的字段是 review 字段。但这是有道理的:不是每个 BnB 航空公司的客人都会留下评论。
- 现在选择训练新模型并选择回归和自动:
- 再次注意,我们可以提供自己的定制代码,并且仍然保留在整个工作流中。我们不必仅仅因为想要定制流程的一部分就放弃自动化培训管道。
- 在下一个窗格中,选择 price 作为要预测的目标列:
- 在下一个窗格中,从预测值集中删除 id 列。将邻域更改为分类(来自文本),并将目标更改为 MAE。
- 给它 3 个小时的预算,开始训练。
大约 3 小时后,培训结束,我们可以检查模型并根据需要进行部署:
我们得到的平均绝对误差为 55 美元,比使用 xgboost 得到的误差几乎高出 20%。所以,一个更精确的模型,用更少的代码。包括评估、特性重要性、可解释性、部署等。所有这些都是现成的。
最底层的
BigQuery ML 和 AutoML 表都易于使用并且非常好。它有助于理解领域的基础知识(为什么没有评论?),以及机器学习的(不要用 id 列做输入!),但从一个公民数据科学家的角度来看,他们相当平易近人。编码和基础设施管理开销几乎完全消除了。
这对数据科学工作来说意味着什么?从编写原始 HTML 到使用 weebly/wix/etc 的转变。并不意味着网络开发人员的工作会减少。相反,这意味着更多的人创建网站。当每个人都有一个基本的网站时,它驱动了一种差异化的需求,以建立更好的网站,因此为网络开发人员提供了更多的工作。
机器学习的民主化也会导致同样的效果。随着越来越多的事情变得容易,将会有越来越多的机器学习模型被构建和部署。这将推动差异化的需求,并建立超越和解决日益复杂的任务的 ML 模型管道(例如,不只是估计租赁价格,而是进行动态定价)。
机器学习的民主化将导致更多的机器学习,以及更多的 ML 开发者的工作,而不是更少。这是一件好事,我为此感到兴奋。
还有,哦,Vertex AI 真的很好看。在你的 ML 问题上尝试一下,让我知道(你可以在 Twitter 上@lak_gcp 找到我)效果如何!
更多关于 Vertex AI 的阅读:
- 给谷歌云上的新统一 ML 平台 Vertex AI 一个旋转 :
我们为什么需要它,无代码 ML 培训到底有多好,所有这些对数据科学工作意味着什么? - 如何将 TensorFlow 模型部署到 Vertex AI :在 Vertex AI 中使用保存的模型和端点
- 使用 Python 在 Vertex AI 上开发和部署机器学习模型:编写让你的 MLOps 团队满意的训练管道
- 如何在 Vertex AI 中为超参数调整构建 MLOps 管道 :
为超参数调整设置模型和协调器的最佳实践
GLMs 第二部分:牛顿-拉夫森,费希尔评分,迭代加权最小二乘法(IRLS)-一个严格的概述
用计算机模拟迭代拟合技术的数学推导和实现。
穆罕默德·拉赫马尼在 Unsplash 上的照片
1:背景和动机
广义线性模型(GLMs)在包括统计学、数据科学、机器学习和其他计算科学在内的领域中起着关键作用。
在本系列的第一部分中,我们提供了规范和非规范形式的常见 GLMs 的全面的数学概述(带证明)。下一个需要解决的问题是,我们如何让数据符合 GLM 模型?
从历史背景来看 GLMs 时,有三个密切相关的重要数据拟合程序:
- 牛顿-拉夫森
- 费希尔评分
- 迭代加权最小二乘法(IRLS)
我发现这些技术的关系和动机往往很难理解,上面的术语有时会以不正确的方式互换使用。这篇文章提供了这三个重要的迭代数值拟合过程的严格概述,连接它们的历史的讨论,以及在示例规范和非规范 GLMs 上实现这些方法的详细计算模拟。在未来的一篇文章中,我们将通过多阶段递归 GLM 模型的镜头来涵盖神经网络的推导。
这篇文章的目录如下:
作者图片
说到这里,让我们开始吧!
2:迭代数值拟合技术的推导
2.1:根据数据拟合模型—简介
让我们首先为我们如何思考“用数据拟合模型”以及我们在数学上的含义打下基础。
作者图片
作者图片
在构建我们的第一个迭代数值拟合过程之前,我们需要首先绕道通过泰勒展开。
2.2: 泰勒展开和二阶近似
在构建我们的第一个迭代数值拟合过程之前,我们首先需要理解泰勒展开的基础。
作者图片
作者图片
我们现在准备构建我们的三个迭代数值拟合过程,从牛顿-拉夫森开始。
2.3:三次迭代数值拟合过程
2.3.1:牛顿-拉夫森
作者图片
作者图片
作者图片
作者图片
我们现在准备讨论我们的第二个迭代数值拟合过程费希尔评分,以及它与牛顿-拉夫森的联系。
2.3.2:费希尔得分
将牛顿拉夫森应用于我们在第 2.1 节中的例子,我们得到:
作者图片
有没有办法减轻这种计算负担?这就是费希尔得分发挥作用的地方。
作者图片
作者图片
在这篇文章的后面,我们将看到在 GLMs 可以以标准形式参数化的情况下,Newton-Raphson 和 Fisher 评分在数学上是等价的。
已经讨论了牛顿-拉夫森和费希尔评分,我们准备讨论我们的最后一个迭代数值拟合程序迭代加权最小二乘法(IRLS)。
2.3.3:迭代加权最小二乘法(IRLS)
为了理解我们的最后一个迭代数值拟合过程迭代重加权最小二乘(IRLS)及其与费希尔评分的关系,我们需要快速复习一下加权最小二乘(WLS)估计量。
作者图片
(更深入的推导有 【加权最小二乘(WLS)【广义最小二乘(GLS)【普通最小二乘(OLS) 估值器,参见我以前的几篇)**
作者图片
你可能会问…
“嗯……那很好……但是这和 GLMs 有什么关系呢?为什么我要让我的费希尔评分算法看起来“有点”像 WLS 估计量呢?这有什么意义???"
为了理解费希尔得分和 WLS 之间的联系,我们需要一些 GLMs 的历史背景。
如果你还记得本系列的第一部分,GLMs 是在 20 世纪 70 年代早期作为一个统一理论发展起来的。随着这一理论的发展,从业者希望找到一种方法,用他们可以在计算机上运行的计算软件将他们的数据拟合到 GLM 模型。嗯,20 世纪 70 年代仍然是计算的相对早期,尤其是科学计算。没有唾手可得的线性代数和数值库(例如 python 中的 numpy)。相反,人们必须从头开始编写他们自己的库。说当时的计算机几乎没有内存和硬盘空间是一种保守的说法;与今天相比,20 世纪 70 年代计算机的内存小得可笑。软件必须小心编写,并且必须在内存方面进行高度优化。那时写软件,尤其是科学计算软件,是很困难的。非常非常困难。
然而,在 GLM 理论发表之前,该领域的研究人员和从业者已经编写了计算机软件来拟合加权最小二乘估计量。换句话说,他们已经编写了软件来恢复以下估计量的经验估计值:
作者图片
因此,随着 GLM 理论的建立和软件使用费希尔评分将数据拟合到 GLMs 的需要,从业者有了一个想法:
“你知道……我们费希尔评分算法中的部分术语看起来很像 WLS 估计量。我们已经编写了解决 WLS 估计量的软件,它似乎工作得很好。那么…如果我们不完全从零开始编写费雪评分软件,而是让我们的费雪评分软件成为我们的 WLS 软件的简单包装函数,会怎么样呢!对于费希尔评分算法的每一个迭代步骤,我们可以重新参数化我们的问题,使其看起来像 WLS 估计量,并调用我们的 WLS 软件返回经验值。”
换句话说,在我们的费希尔评分算法的每一个迭代步骤中,我们要重新参数化以下内容:
作者图片
因此,迭代加权最小二乘法(IRLS)诞生了。术语“重新加权”是指在费希尔评分算法的每个迭代步骤中,我们都使用新的更新权重矩阵。
在第 3 节中,我们将通过计算实例展示如何将牛顿-拉夫森、费希尔评分和 IRLS 用于规范和非规范 GLMs。然而,首先,在拟牛顿法和梯度下降简短的旁白。
2.4: 略论拟牛顿法和梯度下降法
在开始执行 GLMs 的三个主要迭代数值拟合过程之前,我想简单提一下另外两类相关的迭代方法,拟牛顿法和梯度下降法。
作者图片
作者图片
作者图片
作者图片
作者图片
3: 实施 GLMs 的装配程序
我们现在准备探索如何操作牛顿-拉夫森,费希尔评分,IRLS 为规范和非规范 GLMs。让我们先回顾一下 GLM:
3.1: GLM 复习
广义线性模型(GLM)有三个主要部分:
作者图片
现在让我们来研究一下标准和非标准形式的指数离差分布族的概率密度函数(PDF)的参数化。
作者图片
有关更深入的概述,请参见 GLMs 上的本系列文章的第一部分。
3.2:拟合程序 form 标准形式
回想一下,规范 GLMs 具有以下属性:
作者图片
我们现在准备展示如何将牛顿-拉夫森、费希尔评分和 IRLS 用于规范 GLMs:
3.2.1:牛顿-拉夫森
作者图片
作者图片
作者图片
作者图片
3.2.2:费希尔得分
作者图片
作者图片
3.2.3:迭代加权最小二乘法(IRLS)
作者图片
作者图片
作者图片
3.3:拟合程序——GLM 非标准形式
作者图片
作者图片
作者图片
作者图片
作者图片
作者图片
3.3.1:牛顿-拉夫森
作者图片
作者图片
作者图片
作者图片
3.3.2:费希尔评分
作者图片
作者图片
3.3.3:迭代加权最小二乘法(IRLS)
作者图片
作者图片
作者图片
作者图片
3.4:派生算法的总结
下面是 3.2 节和 3.3 节推导出的算法的总结
作者图片
作者图片
4:计算模拟
以下是两个典型 GLMs 的计算模拟:
- 逻辑回归
- 泊松回归
…和一个非规范的 GLM:
- 概率单位回归
对于每个回归模型,我们使用牛顿-拉夫森法、费希尔评分法和迭代加权最小二乘法(IRLS)将模型拟合到数据。
让我们导入我们需要的库:
并指定一个函数来模拟不同的建模集:
指定我们需要的激活功能:
典型 GLMs 的牛顿-拉夫森、费希尔评分和 IRLS 的函数:
非规范 GLMs 的牛顿-拉夫森、费希尔评分和 IRLS 的函数:
4.1:逻辑回归
回想一下,对于逻辑回归,我们有:
作者图片
现在,让我们模拟我们的逻辑回归,使用牛顿-拉夫森、费希尔评分和 IRLS 拟合我们的模型,并将我们的结果与 python 中 Statsmodels 的内置逻辑回归库进行比较:
如我们所见,我们的结果与 Statsmodels 库的结果相同
4.2:泊松回归
回想一下,对于泊松回归,我们有:
作者图片
让我们模拟泊松回归,使用牛顿-拉夫森、费希尔评分和 IRLS 拟合我们的模型,并将我们的结果与 python 中 Statsmodels 的内置泊松回归库进行比较:
同样,我们的结果与来自 Statsmodels 库的结果相同
4.3:概率单位回归
对于概率单位回归,我们有:
作者图片
使用:
作者图片
作者图片
让我们模拟我们的概率单位回归,使用牛顿-拉夫森、费希尔评分和 IRLS 拟合我们的模型,并将我们的结果与 python 中 Statsmodels 的内置概率单位回归库进行比较:
同样,我们的结果与 Statsmodels 库的结果相同
以上计算模拟的完整代码/笔记本,请看下面的 github 链接 。
5:总结和结论
在未来的一篇文章中,我们将通过多阶段递归 GLM 模型的镜头来涵盖神经网络的推导。
希望以上有见地。正如我在以前的一些文章中提到的,我认为没有足够的人花时间去做这些类型的练习。对我来说,这种基于理论的洞察力让我在实践中更容易使用方法。我个人的目标是鼓励该领域的其他人采取类似的方法。我打算在未来写一些基础作品,所以请随时在 LinkedIn 上与我联系,并在 Medium 上 关注我的更新!
GLMs 第三部分:作为递归广义线性模型的深度神经网络
实践教程
数学推导和计算机模拟
1:简介
广义线性模型(GLMs)在包括统计学、数据科学、机器学习和其他计算科学在内的领域中起着关键作用。
本系列的第一部分提供了一个全面的数学概述,用规范和非规范的形式证明了常见的 GLMs。第二部分提供了 GLMs 常用迭代数值拟合程序的历史和数学背景,包括牛顿-拉夫森法、费希尔评分法、迭代加权最小二乘法和梯度下降法。
在这个三部分系列的最后一部分,我们探索神经网络及其与 GLMs 的联系。事实上,神经网络只不过是递归的规范 glm。伴随这一块是一个完全可用的计算机模拟。
这篇文章的目录如下:
作者图片
让我们跳进来吧!
2:激励神经网络
在本系列的前两篇文章中,我们重点讨论了 GLMs 的数学规范和恢复模型参数经验估计的拟合过程。然而,在这两篇文章中,我们都假设我们对所拟合的 GLMs 的参数模型规格有很强的信心。例如,假设我们有一个特性-结果关系,其中有 10 个特性的结果是伯努利分布的。我们可以拟合指定 11 个系数(1 个截距项,10 个特征中的每一个都有一个系数)的逻辑回归模型,而不需要特征或联合相互作用项的任何变换。只要问题的模型说明是正确的,逻辑回归模型将只返回“正确的”结果和推论。这些事实上是非常严格的参数假设。
然而,现在让我们假设我们不愿意对我们对模型规范的理解做出如此严格的参数假设。事实上,让我们假设我们根本不愿意对模型规范做任何假设。我们只是举手高呼“我们不知道模型规范是什么,我们也不愿意对它做任何假设!”。我们希望使用一种方法来大大放松对上述假设的需求。
有一类被称为“通用逼近器”的方法,神经网络属于其中。仅用一个隐藏层和非线性 sigmoid 激活函数,神经网络(理论上)就能够一致地估计任何任意模型规格。这是在某些用例中广泛采用神经网络的主要动机。
在进入神经网络背后的数学之前,让我们先回顾一下 GLMs 的数学知识。
3: GLM 复习
回想一下,广义线性模型(GLM)有三个主要组成部分:
作者图片
现在让我们来研究一下标准和非标准形式的指数离差分布族的概率密度函数(PDF)的参数化。
作者图片
回想一下,对于规范 GLMs,我们有以下属性:
作者图片
(以上工程量的证明和推导见本 GLM 系列第一、二部分*)*
作者图片
4:跳到神经网络
假设我们有一个统计模型:
- 我们不是指定一个 GLM,而是指定几个相互并行的 glm。这些 GLMs 的平行分组我们称之为“层”。
- 模型不是由一个“层”组成,而是有几个层。前一层 GLMs 的输出成为下一层 GLMs 的输入特征。
上述模型实际上是标准的前馈神经网络。我们将网络的第一层称为“输入层”,最后一层称为“输出层”,中间的所有层称为“隐藏层”。
让我们假设一个前馈神经网络的例子,在输入和输出层之间有两个隐藏层。下图显示了这种网络的常见图示。每个“节点”(即圆)代表一个变量。请注意,下图并未精确显示每层中存在的节点数量。同样,节点的数量将对应于所述层中“特征”的数量。每个箭头对应一个估计的“权重”或系数。
作者图片
…让我们用数学方法指定每层的输入和输出,以及它们的尺寸:
作者图片
如果我们将每一层都想象成一个局部 GLM,我们可能会对拟合哪种类型的 GLMs 感兴趣?换句话说,我们可能对利用哪些链接功能/激活功能感兴趣?下表列出了神经网络层中使用的常见 GLM 类型。
作者图片
现在让我们来讨论如何将神经网络与数据相匹配。
5:拟合神经网络—带反向传播的梯度下降
在本系列的第二部分中,我们深入研究了将数据拟合到 GLMs 的迭代数值技术。出于计算效率的考虑,标准 GLMs 通常在实践中适合利用牛顿-拉夫森或费希尔评分。然而,神经网络最适合利用梯度下降。我们需要在神经网络的每一层中恢复参数估计。给定网络各层的固有依赖结构,利用梯度下降作为我们选择的迭代数值拟合过程,在数值上将问题简化为动态规划算法(正如我们很快将看到的)。回想一下,对于梯度下降,在迭代步骤“ t+1 ”求解层“ k 中的权重如下:
作者图片
根据以上梯度下降算法的说明,我们需要恢复关于我们的神经网络中每个β系数的的成本函数的第一梯度。从技术上讲,我们可以用数学方法求解并恢复 中任何我们喜欢的 顺序的梯度。然而,仔细检查我们的神经网络,如果我们以“巧妙”的顺序求解梯度,我们可以降低所需的总计算量。可以容易地估计外层中权重的梯度(类似于如何在单个 GLM 中估计系数)。倒数第二层中权重的梯度是最后一层中梯度的函数。倒数第三层中的梯度是倒数第二层中梯度的函数,以此类推。因此,如果我们求解最后一层中的梯度,并通过网络逐层求解梯度,这种梯度求解练习简化为一般的动态规划问题。
在人工智能领域和神经网络文献中,动态编程的这个特殊实例被赋予了自己的特殊名称。我们称之为 反向传播 。随着梯度下降的每一次迭代,我们使用从前到后通过网络向前传播的来自步骤“ t 的权重的当前经验值(即 前向传播 )来计算每一层的变量的值,然后通过从后到前的网络工作来更新步骤“ t+1 的权重。
让我们用数学方法推导出具有两个隐藏层的玩具问题的梯度:
作者图片
…因此,我们对步骤“ t+1 ”的权重更新为三层中的权重:
作者图片
6:计算模拟
下面是一个用玩具数据集拟合前馈神经网络的完整工作示例(从头开始构建)。在下面的代码中,神经网络类对象允许下列可调参数:
- 隐藏层数
- 每个隐藏层中的节点数
- 每个隐藏层的激活函数
- 小批量
- 节点丢失正则化
让我们导入我们需要的库:
…以及用于指定具有伯努利分布结果的玩具数据集的函数:
…以及神经网络模型的函数和类对象:
现在,让我们在玩具数据集上拟合神经网络模型,计算结果,并返回曲线下面积(AUC)分数
从上面可以看出,拟合神经网络模型的 AUC 约为 80%
有关上述计算模拟的完整代码/笔记本,请参见下面的 github 链接 。
7:总结和结论
在本系列的第一部分中,我们提供了规范和非规范形式的常见 GLMs 的全面的数学概述(带有证明)。在第二部分中,我们提供了对典型和非典型 GLMs 的三个重要的迭代数值拟合过程的严格概述:牛顿-拉夫森,费希尔评分和迭代加权最小二乘法(IRLS)。在第三篇也是最后一篇文章中,我们介绍了标准的神经网络模型,以及如何将它们表述为递归 GLMs。
希望以上有见地。正如我在以前的一些文章中提到的,我认为没有足够的人花时间去做这些类型的练习。对我来说,这种基于理论的洞察力让我在实践中更容易使用方法。我个人的目标是鼓励该领域的其他人采取类似的方法。我打算在未来写一些基础作品,所以请订阅 并在媒体 和 LinkedIn 上关注我的更新!
埃尔莫&伯特手套公司
使用 Spark NLP 的最新文本分类指南
阿玛多·洛雷罗在 Unsplash 上的照片
机器学习模型最具挑战性的任务之一是找到最佳方式来生成单词的数字表示,以便模型可以在计算中使用这些信息。
在计算机视觉任务中,彩色(RGB)图像中的红色通道总是指红色通道,绿色通道指绿色通道。然而,文本在很大程度上是基于上下文的,因此同一个词可以根据它的用法有多种含义。例如,熊猫可以指可爱而模糊的熊或 Python 数据分析库。
当考虑句子和段落时,这变得更加复杂。请考虑以下情况:
熊猫可爱又毛茸茸。他们不用熊猫数据分析库,因为他们是熊。
现在我意识到这不是一个普利策奖获奖故事的开头,但重点是要引起你对第二句话中的单词 They 的注意。他们是谁?为了回答这个问题,必须有一个内置的内存组件,允许算法生成与第二句中的熊猫相似而与第二句中的熊猫不同的熊猫(第一句中)的表示。
今天,我将通过使用开源自然语言处理库 Spark NLP 的示例,使用最先进的算法来执行文本分类任务,这些算法已经尝试处理上述挑战(以及其他挑战)。
我将比较以下模型的结果
- 手套
- 埃尔莫
- 伯特
什么是 Spark NLP?
在我们进入文本分类挑战之前,先简单描述一下 Spark NLP:
Spark NLP 是一个开源的自然语言处理库,构建在 Apache Spark 和 Spark ML 之上。它提供了一个简单的 API 来集成 ML 管道,并由 John Snow 实验室提供商业支持。Spark NLP 的注释器利用基于规则的算法、机器学习和一些在引擎盖下运行的 Tensorflow 来支持特定的深度学习实现。
我鼓励每个人看一看 Spark NLP 的媒体页面和他们的 Github 以获得大量 NLP 任务的深入教程。
如果您的笔记本已经打开并准备好,您可以通过使用下面的代码安装和导入必要的包来开始使用 Spark NLP。
瞧啊!现在我们准备开始工作了。
数据集
对于今天的挑战,我们将使用在找到的数据集。在这个回购上,你也可以跟着我的笔记本。
首先,您可以阅读。csv 文件,使用以下代码输出数据帧示例:
我们感兴趣的是按目标对我们的文本列进行分类,其中 0 =无灾难和 1 =灾难。使用下面的代码可以让我们看到目标变量的分布。
有 1211 个空值,它们对我们的分类没有用处。我们可以使用下面的代码将它们从数据帧中删除。
接下来,我们将经历我用来转换原始文本的预处理步骤。
构建预处理管道
Spark NLP 管道中的每一步都需要某些列作为输入,并产生不同类型的新列作为输出。在这一节中,我们将回顾在整个项目中保持一致的预处理管道。关于所有 Spark NLP 转换器和注释器的完整描述,包括所有可修改的参数,请参见链接。
这是我们管道的入口点,它将我们的原始文本转换成一个文档类型。这个注释器使用包含我们的 tweets 的输入列 text,,并输出一个新列 document 。我还选择了清理模式收缩来去除空白(新行、制表符、多个空格)。
2. 【标记器()】
记号赋予器将我们的句子分解成单独的成分(例如,单词或短语)。这个注释器的输入是文档列,它将输出一个新列令牌*。我修改了参数 SplitChars 来拆分由连字符连接的标记,还修改了参数 ContextChars 来删除标记中的某些字符,如下面的代码所示。*
3. 规格化器()
规范化器是一个文本清理注释器,它接受来自我们的标记列的输入,并输出和规范化的列。参数 CleanupPatterns 用于删除所有标点符号,同时保留所有字母数字字符。
4.【stopwodsguner】)**
停用字词注释器删除基于库的预定义字词列表。这个库是 Spark ML 和 scikit-learn 使用的同一个库,完整的列表可以在这里找到。这些单词通常是非常常用的单词,它们在文本分类问题中不会提供任何效用(例如,and、am、be、do、for、get、no)。
5. Lemmatizer()
词汇化指的是一个规范化文本的过程,其目标是通过将派生相似的单词转换为基本形式(例如,writes、written、written、writer → write )来减少可变性。你会注意到下面 Spark NLP 有一个预训练的词条库ant BNC,它是基于英国国家语料库中的单词。
下面你可以看到预处理管道的完整代码。在最后一个模块中,管道被定义为我们已经介绍过的步骤序列,从原始文本开始,到词条结束。
可视化管道的效果
接下来,我们将通过一个例子来看看原始文本在预处理管道的每一步是如何被转换的。为此,我们将使用下面简要介绍的 Spark NLPs 光管道。
光管道是 Spark NLP 专用管道,相当于 Spark ML 管道,但意在处理更少量的数据。它们在处理小型数据集、调试结果,或者从服务于一次性请求的 API 运行训练或预测时非常有用。
下面你可以看到,拟合由 7000 多条推文组成的火车数据帧花了 15.2 秒。
假设我们想要保存这个预处理模型,并将其用于另一个任务。下面,我们使用一个示例文本创建一个 Spark 数据帧,然后使用相同的管道转换它。尽管文本的大小是训练数据帧的 1/7000,但它花费了 1.55 秒(1/10)的时间。
进入光管线。正如你在下面看到的,在 121 毫秒,这增加了将近 13%的速度。****
现在,为了可视化这个预处理管道将如何影响我们的数据帧,我们可以使用下面的代码。
为了便于阅读,我将结果插入了一个表格。
注意,在第 10 行你会看到<逗号>。当我创建一个要点时,我不得不替换实际的逗号,因为它将此解释为另一列。
也就是说,我们可以看到规格化器是如何去掉标点符号的。停用词清理器移除了诸如 as、she、The 等词… 最后,词条整理器将词转换为它们的词条,例如 sat → sit,watching → watch,catch→catch。
到目前为止,我们已经清理了我们的数据帧,但它仍然包含文本。在下一节中,我们将研究各种用于将明文转换成数字表示的预训练嵌入。
单词嵌入
如上所述,本节将简要描述用于转换干净文本的不同嵌入。详细讨论每一个的机制已经超出了本文的范围,但是我将为那些想看得更深一点的人提供原始论文的链接。
单词嵌入生成单词的多维向量表示。目标是为具有相似含义的单词生成相似的表示。比如海啸、飓风、龙卷风可能有类似的表示,但是龙卷风呢?这就是语境重要性的一个例子。Twister 可以指游戏或龙卷风,但是游戏和龙卷风肯定不应该有类似的表示。让我们快速看一下每个模型是如何创建嵌入的。
根据创造者的说法,手套是:
本质上是具有加权最小二乘目标的对数双线性模型。该模型背后的主要直觉是简单的观察,即单词-单词共现概率的比率具有对某种形式的意义进行编码的潜力
考虑以下我们的目标 灾难 和 无灾难 和四个单词(风、损害、汉堡、驾驶)的同现概率的虚构示例。对此的解释是,比率为 1 意味着分子P(k |灾难)和分母P(k |无灾难)之间没有差异。随着值变得大于 1,它与 灾难 相关联的概率增加。反之,随着数值变得小于 1,它与 无 灾难 相关联的概率增加。
从我们的例子来看,伤害与我们的目标 灾难 关联最强,而汉堡与目标 无灾难 关联最强。驱动的风和都接近于 1,意味着与任一目标都没有强关联。
GloVe 的一个局限性是,它没有考虑到单词在什么样的上下文中使用。考虑这两句话:
- 喜欢开着我的敞篷车,头发上带着 风 !
- 风 那么大,我的敞篷车就这么飞走了!
ELMo 的创造者找到了一种方法来解决这个问题,从而产生了语境化的单词嵌入。这里,没有生成固定的嵌入。取而代之的是,在分配嵌入之前,先读取整个句子。使用双向 LSTM,ELMo 学习下一个和上一个单词。
GloVe 和 ELMo 都是在无人监督的情况下对大量文本进行预训练的。一个关键的区别是,使用 GloVe,我们将学习到的向量用于一些下游任务。对于 ELMo,我们使用学习向量和预训练模型作为一些下游任务的组件。
如果 NLP 的研究人员不那么喜欢布偶,我认为比 BERT 更好的名字应该是 Frankenstein,因为它包含了许多最近的突破。为了获得非常详细和有用的指南,我鼓励你看看这篇文章。
BERT 建立在最近在 NLP 社区兴起的许多聪明想法的基础上——包括但不限于半监督序列学习(由 Andrew Dai 和 Quoc Le)ELMo(由 Matthew Peters 和来自的研究人员和UW CSE)ulm fit(由 fast.ai 创始人和 Sebastian Ruder)OpenAI 转换器(由 OpenAI 研究人员、Narasimhan
尽管 ELMo 使用双向 LSTMs,但是它连接正向和反向模型的事实限制了表示同时利用两种上下文的能力。
伯特使用了一个掩蔽语言目标,意思是单词被随机隐藏并被一个掩蔽所取代。使用一个变换器,然后使用它周围的非屏蔽单词(左右)来预测屏蔽单词。
在下一节中,我们将比较这些模型的嵌入如何用于将灾难与非灾难进行分类。
结果
在公布结果之前,我想花点时间介绍一下所使用的分类器。 ClassifierDL 是由 John Snow Labs 在 TensorFlow 内部构建的通用分类器,支持多达 100 个类。我设置的关键参数是:
- 学习率(0.001)
- 批量大小(8)
- 最大训练次数(5)
还值得注意的是,我使用以下方法将原始数据帧分成训练集和验证集:
- 手套
下面你可以找到完整的管道,它是我上面描述的预处理管道的扩展。如您所见,GloVe word 嵌入被用作另一个 Spark NLP 注释器 SentenceEmbeddings 的输入,然后使用 ClassifierDL 进行分类。
然后使用下面的代码对验证集进行预测,预测的示例显示在下面的表中。
在显示的十个预测中,一个错误完美地突出了手套嵌入的局限性。由于缺乏上下文,我想要一些海啸外卖被归类为灾难。
使用 sklearn,我们可以看到手套嵌入可以很好地分类我们的文本。事实上,以 81%的准确率,它做得相当不错!
2.埃尔莫
接下来,让我们看看 ELMo 嵌入是否能够提高分类精度。要使用预训练的 ELMo 嵌入件,只需将以下部件插入上述管道,作为手套嵌入件的替代品。
使用上面所有相同的代码,对验证集进行了预测,如下所示。这里我们看到 ELMo 能够学习手套漏掉的单词海啸的上下文。干得好埃尔莫!
尽管如此,模型精度仅提高了 1%。
3.伯特
最后,让我们看看 BERT 嵌入在分类任务中的表现。就像我们上面做的一样,简单地把下面的插入同一个点。
再次展示了验证集的预测示例。有趣的是,我们看到 BERT 并没有正确地对句子进行分类,见见 Brinco 你自己的地震和海啸预警信标。
不过,这次我不得不站在伯特一边。在我看来,这条推文描述的是一个灾难探测系统,而不是一场灾难。
无论哪种方式,BERT 嵌入的最终结果都没有提高 ELMo 所达到的精度。
我们学到了什么?
今天我们讨论了几个使用 Spark NLP 进行文本分类的例子。我们重点介绍了 3 个单词嵌入模型,提供了如何将它们包含在您自己的分类任务中的分步说明:
- 手套
- 埃尔莫
- 伯特
虽然结果变化不大,但我们看到了一些不同嵌入模型如何工作的例子。具体来说,我们能够看到手套嵌入缺乏背景。它无法区分海啸、餐馆和真正的灾难。
这个项目专注于单词嵌入。在未来的帖子中,我们将探索 Spark NLPs 句子嵌入选项,如通用句子编码器(USE)和 BERT 句子嵌入。
感谢阅读!
有用的资源
使用 Bert 和通用语句编码器在 Spark NLP 中进行文本分类
单词嵌入(第二部分) :直觉和(一些)数学来理解端到端手套模型
手套研究论文解释
手套模型背后数学的直观理解和解释
图片来自 Unsplash
继我的 word2vectors 研究论文讲解 博客之后,我又拿起 GloVe 研究论文【Pennington 等人】来讲解我对一篇非常详细而全面的研究论文的理解。
GloVe 代表**Global**Vectors其中 Global 是指语料库的全局统计,Vectors 是单词的表示。早期的单词嵌入方法,如 LSA,word2vec,能够学习单词之间的句法和语义关系,但其起源尚不清楚。手套模型旨在明确归纳单词向量中的规则,并找到单词之间学习关系的来源。
1。手套型号概述
GloVe 是一个全局对数双线性模型**。嗯,我相信你想知道术语’ ‘全局对数双线性’ '是什么意思。全局是指训练语料的全局统计。对数双线性是指输出的对数是两类字向量乘积的线性回归。在手套的情况下,两种类型是单词向量(w)和上下文向量(w^).如下所述,手套模型结合了两种广泛采用的用于训练单词向量的方法。**
1.1 矩阵分解
这些方法分解单词-单词或文档-术语共现矩阵。哈尔(语言的超空间模拟)【隆德&伯吉斯】、 LSA (潜在语义分析)【兰道尔、福尔茨、&拉哈姆】是使用矩阵分解的流行模型。特征值分解用于方阵,奇异值分解 (SVD)用于矩阵分解的矩形矩阵。在词-词矩阵中,行代表词,列代表上下文词。矩阵 Mᵢⱼ中的值表示特定单词 Wᵢ在 Wⱼ.上下文中出现的次数在文档术语矩阵中,行代表单词,列代表文档。一行表示特定单词在所有文档中的分布,一列表示该文档中所有单词的分布。
矩阵分解方法通常包括以下步骤。
- 为每个单词定义上下文,并生成单词-单词或文档术语矩阵 m。
- 按行、列或长度规范化矩阵中的值。
- 删除方差较小的列,以降低矩阵的维数。
- 对 M 进行 SVD 矩阵分解,生成 U,S,V 矩阵。
- 在通过取第一个 r 以降序对矩阵 M 的奇异值进行排序之后,< R (rank of matrix M), low rank of a matrix M can be obtained. Product of low rank matrices U^, S^ and V^ is close approximation to the original matrix M.
- Vector of a word Wⱼ is the jᵗʰ vector from reduced rank space matrix U^.
In such methods, the most common words in the corpus such as (和贡献了单词之间不成比例的相似性。出现在“The”、“and”上下文中的单词 Wᵢ和 Wⱼ导致比其真实相似性得分更大的相似性得分。类似地,Wᵢ和 Wⱼ不经常出现在“the”、“and”的上下文中,但具有真正的相似性,它们的相似性得分会更低。诸如煤**【t . Rohde 等人】的方法通过使用基于矩阵的相关性或熵归一化来克服这个问题。当使用基于熵的归一化时,在所有上下文或文档中出现的单词,例如“the”、“and”,将具有高熵。原始计数用高熵项归一化,导致矩阵中这些项的高值缩小。这解决了向单词相似性分数添加不成比例的度量的问题。**
1.2 基于窗口的方法
这些方法在局部上下文窗口上工作,而不是使用语料库的全局统计。[Bengio 等人]中的语言模型训练神经网络,神经网络又训练单词向量表示。该模型以 N 个单词的过去历史和预测下一个单词作为语言建模的目标。因此,该方法中的每个示例都是作为输入的单词的局部窗口,而输出是下一个单词。后来 word2vec 模型【Mikolov et al .】如 skip-gram 和 CBOW 解耦语言建模,训练单隐层神经网络。更详细的了解,可以去翻翻 我之前的文章 就可以了。
与矩阵分解方法相比,这些方法没有利用可用的全局统计,导致单词的次优向量表示。通过使用跨语料库的重复局部窗口,可以减少模型的训练时间和复杂度。
2。手套模型背后的详细数学运算
接下来是你们都期待阅读的部分。理解任何算法背后的数学是非常重要的。它有助于我们理解算法的公式和掌握一个概念。也就是说,让我们定义一些符号。
x 是共现矩阵(单词-单词),其中 Xᵢⱼ是单词 Wⱼ在单词 Wᵢ.的上下文中的计数上下文对一个特定的单词意味着什么?单词周围的上下文可以被定义为由过去的 N 个单词和未来的 N 个单词组成的对称上下文。不对称上下文只包含过去的 N 个历史单词。简单计数或加权计数可用于计算矩阵中的值。简单计数将 1 作为出现次数。在加权计数中,1/d 用作出现次数,其中 d 是与给定单词的距离。使用权重背后的动机是,作为有意义的上下文,与给定单词距离较近的上下文单词比距离较远的单词更重要。
iᵗʰ行-eqⁿ的共现值(1)
在 Eqⁿ (1)中,“Xᵢ”是在“Wᵢ.”这个词的上下文中出现的所有词的总和
Eqⁿ (2)
在 Eqⁿ (2)中,p 是共现概率,其中 Pᵢⱼ是单词 Wⱼ在单词 Wᵢ.的上下文中出现的概率
GloVe 建议根据概率而不是原始计数来寻找两个单词之间的关系。通过寻找与一些探测词 (Wₖ).)的共现概率来检查两个词(Wᵢ和 Wⱼ)之间的关系
假设我们有两个词,Wᵢ是’冰,Wⱼ是’蒸汽,还有一些探测词 Wₖ是’固体’、‘气体’、‘水’、‘时尚’。从基本的理解中,我们知道“固体”更多地与’冰’有关(Wᵢ)and“气体”更多地与’蒸汽 ’ (Wⱼ)有关,而时尚与’冰’和’蒸汽’都无关,而水与’冰’'和’蒸汽’都有关现在我们的目标是在探测词中找到给定词的相关词。
表 1: 来自 60 亿令牌语料库的同现概率(来源——GloVe 研究论文)
根据表 1,对于作为“固体”的探测词(Wₖ),p(固体|冰)是“固体”在“冰”的上下文中出现的概率,是(1.9*10^–4)大于 p(固体|蒸汽)。P(k |冰)/P(k |蒸汽)之比是> > 1。对于探测词‘气’,比率为<<1. For probe words ‘water’ and ‘fashion’ the ratio is nearly equal to 1. The ratio of co-occurrence probability distinguishes words (solid and gas) which are more relevant to given words than irrelevant words (fashion and water). The words having ratio nearly equal to 1 either appear in the context of given words or not, hence causing no impact in learning relationship between given words. This proves 的同现概率比率 是学习词表征的起点。
Pᵢₖ/Pⱼₖ的同现概率比取决于三个词 Wᵢ、Wⱼ、Wₖ.函数 F 的最一般形式可以在单词和上下文向量上定义如下。
Eqⁿ (3)
其中 w ∈ Rᵈ是单词向量,w∞∈rᵈ是上下文向量。Eqⁿ (3)的右侧是从训练语料库中获得的概率。尽管 f 函数有大量的可能性,但它应该对存在于 Pᵢₖ/Pⱼₖ.的信息进行编码目标词 Wᵢ和 Wⱼ之间的关系可以通过向量差来获得,因为这些向量来自 d 维的线性向量空间。因此等式变成了,
Eqⁿ (4)
现在,方程的右边是定标器,而 F 的输入是 d 维向量。f 可以被复杂的神经网络参数化,这最终将打破向量空间中的线性结构。为了避免这种情况,我们可以取 F 的输入的点积,这样可以防止向量维数与其他维数的混合。
Eqⁿ (5)
单词和上下文单词可以相互交换,因为出现在“ice”上下文中的“solid”等同于出现在“solid”上下文中的“ice”。因此 w ↔ w 和 X ↔ Xᵀ的替换可以在 Eqⁿ完成(5)。基本上,我们将左边的输入改为 f,然后希望对 Eqⁿ的右边产生类似的影响(5)。这也被称为保持两个组之间的结构相似性(同态函数)。我们在 Eqⁿ (5)的左手边有组 g,用减法作为组运算,在右手边有组 h,用除法作为组运算。现在,当我们替换 w ↔ w 和 X ↔ Xᵀ时,为了保持结构的相似性,g 中两个向量的相减应该反映 h 中这两个字向量的相除。假设 X= wᵢᵀwₖ,Y= wⱼᵀwₖ ∈ G,z =(x y)。函数 F 在组®和(R>0)之间应该是同态的。根据同态的定义,如果 G 中的 Z = X-Y 减去 op,那么在组 HF(Z)= F(X)÷F(Y)但是 Z = X-Y 因此我们得到 F(X-Y)=F(x) ÷ F(y)。****
Eqⁿ (6)
那么函数 F 应该是什么呢?你猜对了,应该是指数函数。F (x)= e ˣ.比较 Eqⁿ (5)和 Eqⁿ (6),我们得到,F(wᵢᵀwₖ)=Pᵢₖ = Xᵢₖ / Xᵢ.因此,取两边对数,我们得到,*
Eqⁿ (7)
Eqⁿ (7)在单词和上下文方面展示了对称性,除了术语 log(Xᵢ).由于这个术语独立于 Wₖ,我们可以认为这是 bᵢ的偏见术语。再加上一个偏差项 bₖ,我们得到
Eqⁿ (8)
由于 log(x)在 0 附近发散,我们可以在 log(Xᵢₖ上使用加法移位,使得对数的输入总是≥1,
Eqⁿ (9)
Eqⁿ (9)类似于同现 矩阵的对数的分解,这是 LSA 算法背后的主要思想。但是上面的等式有一个问题。如果我们使用平方误差函数来定义成本函数,它将对矩阵中的所有项给予相同的权重,即使对于值接近 0 的罕见频率项也是如此。这样的术语很吵,携带的信息也不多。因此,加权最小二乘法可以用作手套模型的成本函数。
Eqⁿ (10)
注意,加法移位已经在 Eqⁿ (10)所示的矩阵 x 上完成。j 是我们想要在具有词汇大小的共现矩阵上最小化的成本函数。f(Xᵢⱼ)给矩阵中的每一项加权。wᵢ是单词向量,wⱼ是上下文向量。bᵢ和 bⱼ是每个向量的偏差项,Xᵢⱼ是共生矩阵中的项。
现在问题是如何选择函数 f,它应该遵循一定条件。f(0)=0,f 应该是非递减的,并且对于 x 的大值,f(x)不应该非常高,因为不应该过度加权频繁出现的单词。来自 Eqⁿ的 xₘ(11)与图 1 中的 Xₘₐₓ相同。在用 Eqⁿ的 Eqⁿ (11)代替 f(xᵢⱼ(10)后,我们得到手套模型的最终成本函数。然后,使用优化器对一批训练样本训练模型,以最小化成本函数,从而为每个单词生成单词和上下文向量。
Eqⁿ (11)
图 1-α= 3/4 的权重函数。(来源——手套研究论文)
最后,我们完成了手套模型的完整推导。到目前为止,我们所有人都取得了很大的成就!!!现在,如果您想找出 GloVe 模型与 skip-gram (word2vec 模型)之间的关系,并理解 GloVe 模型的整体复杂性,您可以浏览接下来的部分。在这些部分之后,手套模型的实验和结果被讨论。
3。手套和 Skip-Gram 之间的等效性(word2vec 模型)
GloVe 模型基于全局共现矩阵,而 skip-gram 通过局部窗口扫描,并且不考虑全局统计。这两种方法可以被认为是训练单词向量的两种不同的思想流派。本节找出了 GloVe 和 skip-gram 之间的相似性,即使乍一看这两种类型的模型有不同的解释。
让我们定义跳格模型,其中 Qᵢⱼ定义单词 j 出现在单词 I 的上下文中的概率。Qᵢⱼ是给定 Wⱼ的上下文单词的概率分布,并且可以被认为是 softmax 函数。
Eqⁿ (12)
这里,wᵢ和 wⱼ分别是跳格模型的语境向量和词向量。skip-gram 模型的目标是最大化训练语料上所有局部窗口扫描的对数概率。通过由局部窗口生成的示例,经由随机/在线发生训练,但是全局目标函数可以在来自语料库的所有局部扫描上公式化为
Eqⁿ (13)
为了使成本函数为+ve,当 Qᵢⱼ值在 0 和 1 之间时添加负号,并且该值范围的对数为-ve。上述成本函数和原始跳转程序之间的唯一区别是前者是全局的,后者是局部的。当遍历每个局部窗口时,我们可以将相同的单词-上下文对(Xᵢⱼ)组合在一起,并将它们直接乘以 log(Qᵢⱼ项。
Eqⁿ (14)
我们知道 Pᵢⱼ=Xᵢⱼ/Xᵢ.因此代入 Xᵢⱼ,我们得到
Eqⁿ (15)
Xᵢ独立于 j,所以它可以在 j 上求和之外。H(Pᵢ,Qᵢ)是 Pᵢ和 Qᵢ.概率分布之间的交叉熵注意,在交叉熵公式中考虑了负号。代价函数变成交叉熵误差的加权和,权重为 Xᵢ.上述目标函数可以解释为全局跳过程序的目标。使用交叉熵作为误差度量有一定的局限性。p 是长尾分布,当使用交叉熵作为误差度量时,不太可能/罕见的事件具有较高的权重。此外,Q 必须用词汇 V 上的求和来归一化,这在使用交叉熵时是一个巨大的瓶颈。因此,可以使用不同成本误差度量来代替 Eqⁿ (15)中的交叉熵,其中之一是最小平方目标。q 中的分母项可以通过仅取分子项 Q^.来忽略,新的成本函数被定义为,
Eqⁿ (16)
这里,p^ᵢⱼ = Xᵢⱼ,Q^ᵢⱼ= exp(wᵢᵀ * wⱼ)是非正态分布。与 Q^ᵢⱼ相比,Xᵢⱼ采用较大的值,导致优化中的大梯度和大步骤,导致模型的不稳定学习。因此,使用对数的平方误差。
Eqⁿ (17)
代替 Xᵢ,f(Xᵢⱼ)被用作权重函数,如图 1 所示。方括号中的项可以颠倒,没有任何符号变化。Eqⁿ (17)的成本函数与 Eqⁿ (10)的 GloVe 模型的成本函数等价,这表明 skip-gram 模型最终基于语料库的共现矩阵,并且与 GloVe 模型具有相似性。
4。手套模型的复杂性
手套模型的复杂性可以从 Eqⁿ (10)的成本函数中找到。它取决于共生矩阵中非零元素的总数。求和在 I 和 j 上运行,vocab 大小为 V。手套模型的复杂度不超过 O(|V|)。对于几十万字的语料库,|V|超过几十亿。因此,为了获得模型的精确复杂度,可以对 x 中非零项的总数设置更严格的界限。共生矩阵 Xᵢⱼ中的项可以被建模为单词 j 和上下文 I 的频率等级(rᵢⱼ)的幂律函数
Eqⁿ (18)
语料库|C|中的单词总数与共现矩阵 x 的所有项的总和成比例
Eqⁿ (19)
矩阵中的所有元素,无论是单词 I 还是上下文 j,都可以通过将矩阵中的所有项(单词、上下文)放在一起考虑,从 X 中获得其频率排名。|X|是矩阵中任何单词/上下文的最大秩,与矩阵中非零元素的数量相同。ₓ,α是一个调和级数,比值为α,元素个数为|X|。通过将 Xᵢⱼ设置为其最小值 1,Eqⁿ (18)可以获得频率秩 r 的最大值。因此我们得到,|X|=k ^( /α)。在 Eqⁿ (19)中使用这个,我们得到
Eqⁿ (20)
使用广义调和数(Apostol,1976)在右侧展开 H 项,我们得到:
Eqⁿ (21 岁)
其中ζ (α)是黎曼ζ函数。当|X|很大时,两项中只有一项是相关的,这取决于我们得到的是α>1 还是α<1. Hence we finally arrive at,
Eqⁿ (22)
Authors of GloVe observed that Xᵢⱼ is well modelled by setting α=1.25. When α>1 |x|=o(|c|^0.8).因此,该模型的总体复杂度比 O(|V|)好得多,并且略微好于用 O(|C|)缩放的原始 skip-gram 模型。
5。实验
在以下三个 NLP 任务上测试训练的手套单词向量。
一、词语类比
任务是找到单词 d,它回答了“a 对于 b 就像 c 对于”这样的问题。数据集包含句法和语义问题。为了找到单词 d,根据余弦相似性,预测最接近(Wᵇ− Wᵃ+ Wᶜ)的 Wᵈ作为输出。
二。单词相似度
任务是按照相似性的降序排列与给定单词相似的单词。Spearman 等级相关用于测量模型的性能。
三。命名实体识别(NER)
任务是为语料库中的每个标记分配实体类型。CoNLL-2003 英语基准数据集有四种实体类型,即人员、位置、组织和杂项。连同记号特征一起,从手套模型训练的词向量作为输入被添加到 NER 模型,以生成实体类型的概率分布。
6。手套模型训练详情
手套模型在五个不同的语料库上训练:2010 年具有 10 亿个标记的维基百科转储,2014 年具有 16 亿个标记的维基百科转储,具有 43 亿个标记的 Gigaword 5,具有 60 亿个标记的 Gigaword5 + Wikipedia2014 的组合,来自普通爬行的 420 亿个标记的网络数据。
预处理步骤 :-语料库文本小写。斯坦福标记器用于标记化。使用前 400,000 个常用词的词汇来构建共现矩阵。在构造矩阵之前,必须定义单词的上下文。对于相距 d 的单词,使用权重为 1/d 的递减加权窗口来计算矩阵值。GloVe 使用单词的左标记(历史)以及使用单词的左和右标记(历史和未来)的对称上下文来探索不对称上下文的影响。
以下数值在手套模型训练中设定。
对于图 1 所示的加权函数,Xₘ= 100,α=3/4。
优化器 - 阿达格拉德(杜奇等人,2011)初始学习率为 0.05 的优化器用于从 x 随机采样的一批非零项。对于小于 300 维的向量,使用 50 次训练数据迭代,而对于大于 300 维的向量,使用 100 次迭代。
手套模型为每个令牌生成两个向量,W(单词向量)和 W(上下文向量)。两个向量的和(W+W)被用作最终向量。
7。结果
一、词语类比
各种模型的单词类比实验结果如表 2 所示。SG 模型代表 skip-gram,CBOW 代表连续词袋模型,SVD 代表奇异值分解。表 2 中显示了语义和句法以及总的准确率百分比。手套型号的性能优于两种 word2vec 型号。在语料库大小 1.6B 和向量维数 300 上训练的手套模型已经实现了近 70%的准确度,超过了 skip-gram 的 61%和 CBOW 的 36%。在 word2vec 模型中,随着向量维数从 300 增加到 1000,语料库大小从 1B 增加到 6B,模型准确性的提高非常显著,但与向量大小为 300 且语料库大小为 1.6B 的 GloVe 模型相比,仍然表现不佳。这表明即使在较小数据集上训练了 300 维的 GloVe 模型词向量,也比在大得多的数据集上训练的 1000 维的 word2vec 模型具有更有意义的信息。与主体大小的增加(从 6B 到 42B 增加了 7 倍)相比,手套模型的准确性增加了小幅度(75%)。
表 2 :词语类比任务的语义、句法和整体模型准确性(Source- GloVe 研究论文)
关于对称和非对称上下文、窗口大小和向量维数的手套模型的准确性如图 2 所示。所有模型都在 6B 语料库上进行训练。在(a)中,上下文是对称的,在向量维数的所有变化中,窗口大小为 10。随着向量维数从 50 增加到 300,句法、语义以及整体准确度稳步增加,之后准确度的增加与向量维数的增加相比可以忽略不计。在(b)中,向量维数在对称上下文窗口大小的所有变化中保持为 100。随着对称窗口大小的增加,与句法相比,所有的准确性随着语义的急剧增加而增加,这表明理解语义需要更宽的上下文,而短的上下文对于句法问题就足够了。在©中,向量大小在所有非对称窗口模型中保持为 100。类似的行为在©中被注意到作为来自(b)的对称上下文。在对称窗口大小为 3 时,语义准确性超过语法准确性,而在非对称窗口中,语义准确性需要 5 个窗口。
图 2 -词语类比模型精度 vs 向量维数、上下文和窗口大小。(来源——手套研究论文)
在图 3 中,显示了不同语料库上的手套模型准确度。在所有训练语料库中保持 300 的向量维数。句法准确率随着语料库规模的增大而稳步提高,而语义准确率却没有这种规律。因此,通过将语料库的大小从 1B 增加到 6B 和 42B,总体准确度没有显著提高。
图 3 -词语类比模型准确率 vs 训练语料库。(来源——手套研究论文)
二世。 词语相似度——各种数据集( WordSim-353 、 MC 、 RG 、 SCEW 和 RW )与其他模型一起用于测试 GloVe 300 维词语向量。通过对词汇表中所有单词的每个向量维度进行归一化来获得相似性得分,然后对归一化向量使用余弦相似性来找到与给定单词相似的前 n 个单词。Spearman 的等级相关系数是根据从相似性得分和人类判断获得的前 n 个单词的等级来计算的。
Spearman 等级相关公式,其中 d =模型预测等级和输出等级之间的差异,n =观察值数量-eqⁿ(23)
在单词相似性任务的各种数据集上测试的各种模型的结果如表 3 所示。在 WS353、MC、RG 和 RW 数据集上, GloVe model 优于 SVD、CBOW 和 SG。在 42B 语料上训练的 GloVe 模型比在 SCWS 数据集上训练的 CBOW 模型提高了 spearman 等级相关性。
表 3 :跨各种数据集的不同模型的单词相似性任务的 Spearman 等级相关性。(来源——手套研究论文)
三。——NER 任务在不同数据集上的模型性能(验证测试集 CoNLL-2003 、 ACE 和 MUC7 )如表 4 所示。****
表 4 :各种模型在不同数据集上的 NER 任务 F1 得分。(来源——手套研究论文)
以上所有模型都是基于 CRF 的,具有不同的特征集。离散模型使用来自斯坦福 NER 模型的特征集,而其他模型使用基本特征集及其经过训练的词向量作为特征。F1 分数与其他数据集的测试数据一起用于 CoNLL-2003 的验证和测试数据集,以比较模型性能。 GloVe 模型在 NER 任务中的表现优于所有其他模型(离散、SVD 和两种 word2vec 模型)。
8。结论
手套模型讨论了两类算法,基于计数的算法和基于预测的算法。手套模型显示这两类方法差别不大,并且最终都使用共现矩阵作为底层概念来训练词向量。GloVe 捕获数据中存在的全局统计和线性子结构。因此 GloVe 是一个全局对数双线性模型在各种下游 NLP 任务上优于这两类模型。
如果你想了解更多关于如何使用 python 实现手套模型的知识,请在评论中告诉我。
9。资源
[1]原始研究论文——GloVe:单词表征的全局向量:https://nlp.stanford.edu/pubs/glove.pdf
【2】从词汇共现中产生高维语义空间:https://link.springer.com/article/10.3758/BF03204766
【3】潜在语义分析研究论文简介:https://mainline . brynmawr . edu/Courses/cs 380/fall 2006/intro _ to _ LSA . pdf
【4】向量空间中单词表征的高效估计:https://arxiv.org/pdf/1301.3781.pdf【T10
在黑暗的浓咖啡中发光,寻找微粒迁移
咖啡数据科学
寻找另一种方式来看待微粒迁移理论
这是我写的第四篇关于微粒迁移的文章。我假设有证据表明,微粒不会通过粉笔实验(T0)和 T2 实验(T3)以及 T4 实验(T5)迁移。
我不打算重新做粉笔实验,直到我的儿子带着黑粉笔回家。我想这可以成为一个有趣的实验,结合用过的咖啡。如果更细小的粒子在整个冰球中运动,黑暗部分的发光会有助于使它们更容易被看到。白垩粉本身的尺寸比 100 微米小得多,所以它是细粉的一个很好的替代品。
目的是在黑暗的粉笔黄昏中,在用过的咖啡渣(直径为 400 微米)上发光。如果细粒迁移发生,它肯定会发生在大的咖啡颗粒上,颗粒之间有更多的空间供细粒迁移。
所有图片由作者提供
回顾一下,浓缩咖啡中的微粒迁移理论是,非常细小的颗粒(微粒)在一次喷射中迁移,然后可能会堵塞过滤器或进入杯中。这种迁移被认为是沟道效应的根本原因之一。
来展示黑暗粉笔在黑暗中的发光效果。
粉笔不容易溶解。有一些研究表明,升高温度会降低溶解度,而升高压力会降低溶解度,但在浓缩咖啡范围内并不多。
在黑暗中发光的颜色通常也不溶于水。
在这两种情况下,干燥地面和随后的液体仍然会让我们看到黑暗粉笔发光。
数据收集
我从 18g 经过筛选的废咖啡渣开始,因此大多数咖啡渣的直径大于 400um。然后我在上面加了 0.62g 的粉笔,我还加了一个金属网筛减少粉笔回流到我的机器里。
我做了粉笔灰,让它在阳光下晒几个小时。
我启动了金快车,然后开枪了。这是一场泥泞的灾难,很可能是因为提取了所有剩下的东西。我怀疑,由于高流量,这很可能是微粒迁移的最坏情况。最初,我想在黑暗中进行这个测试,这样我就可以看到如果微粒真的迁移了,它们是否会发光。
经过一番清理,我开始着手分析冰球。
圆盘分析
出于理智,我想检查一下顶部在黑暗中是否还会发光。因此,黑暗的图像是在一个没有灯光或窗户的房间里用长曝光相机拍摄的。
当我试图把整个冰球取出来时,只有最上面的部分露了出来。完美!冰球的顶部暴露得很好,我在黑暗中拍了张照片。视觉上,没有白色斑点,也没有任何东西在黑暗中出现。
我仔细检查了顶部,除了最顶部的颗粒外,我仍然没有发现任何白色颗粒。
然后我切开那一部分,我仍然没有发现白色斑点,表明没有粉笔穿透冰球。
作为一个健全的检查,我弹出了冰球的另一部分,我没有发现白色斑点的证据。在黑暗中,我没有发现发光的东西。
筛分分析
我拿起最上面的部分,用 400 微米的筛子筛选。有一些粉笔块留在上面,但是很多细小的粉笔颗粒在下面。
我用显微镜观察一些粒子只是为了好玩。
另外,我用烤箱烘干了所有的液体。我在黑暗中也观察了这个,我没有在黑粉笔中看到任何发光的迹象。我也没有看到托盘里有任何白色颗粒。
我刮去残渣,有 0.5 克残渣,相当于 2.77%的提取率。通常在用过的磨碎物中仍有少量残余物需要提取。
超暗测试
我把冰球的底部放在托盘上,我寻找任何白色颗粒,但我没有找到。
我试图用我的厨房灯在黑暗的粉笔中充电发光,但我发现了一个紫外线灯,所以我能够充电并在黑暗中前进。
对于顶部来说,黑暗粉笔中的光芒仍然闪耀,但对于底部,在托盘上展开,什么也没有。我试着拿着灯走了很多距离,但是什么都没有出现。
然后我对残留物做了同样的检查,什么也没发现。
我做了一个实验,试图用黑色粉笔和粗筛过的废咖啡找到微粒迁移的证据,但我没有找到证据。我尝试了多种方法来检测证据,在常规光线和紫外线下进行视觉检查,但我还是没有发现粉笔穿透冰球的任何证据。
结论:没有足够的证据表明微粒会迁移。
很有可能我错了,做了一个糟糕的实验,但是这个实验很简单,其他人可以重复甚至改进这个实验方案。我欢迎这样的测试。
如果你愿意,可以在 Twitter 和 YouTube 上关注我,我会在那里发布不同机器上的浓缩咖啡视频和浓缩咖啡相关的东西。你也可以在 LinkedIn 上找到我。也可以关注我中。
我的进一步阅读:
GMM:高斯混合模型——如何成功地使用它对你的数据进行聚类?
机器学习
GMM 的直观解释和有用的 Python 示例
GMM-高斯混合模型。图片由作者提供。
本文是解释不同机器学习算法如何工作的系列文章的一部分,并为您提供了一系列 Python 示例,以帮助您开始自己的数据科学项目。
故事涵盖以下主题:
- 高斯混合模型(GMM)属于算法的范畴。
- GMM 算法如何工作的描述。
- 如何使用 GMM 进行聚类的 Python 示例。
GMM 属于哪一类算法?
虽然不可能总是对每种算法进行完美的分类,但尝试这样做仍然是有益的。下面的互动图是我试图帮助你看到更广阔的机器学习领域。
确保点击👇在不同的类别上对进行放大并揭示更多的。
请注意,在许多情况下,相同的算法可以用于解决多种类型的问题。例如,可以使用神经网络进行分类、回归,并作为强化学习的一部分。
机器学习算法分类。由作者创建的交互式图表。
如果你喜欢数据科学和机器学习 ,请 订阅 每当我发布一个新的故事,你都会收到一封电子邮件。
由于高斯混合模型(GMM)用于聚类,它们属于机器学习的无监督分支。
您可能已经知道,非监督技术(尤其是聚类)通常用于分段分析,或者作为一种在数据集中查找观察值之间的相似性/差异性的方法。这不同于监督学习模型,监督学习模型通常用于进行预测。
GMM 算法的解释
聚类算法的类型
并非所有的聚类算法都是一样的。不同的聚类算法对如何最好地对数据进行聚类有不同的想法。有 4 个主要类别:
- 基于质心的 —使用欧几里德距离将每个点分配到最近的聚类中心。例:K-表示
- 基于连通性的 —假设附近的对象(数据点)比远处的对象更相关。例如:层次凝聚聚类(HAC) 。
- 基于密度的 —将集群定义为由低密度区域分隔的密集空间区域。他们擅长寻找任意形状的星团。示例:带噪声的应用程序的基于密度的空间聚类(DBSCAN) 。
- 基于分布的 —假设数据中存在指定数量的分布。每个分布都有自己的均值(μ)和方差(σ ) /协方差(Cov)。示例:高斯混合模型(GMM)。
注意,方差用于单变量分析,协方差用于多变量分析。本文中的示例使用多元设置(多重分布/聚类)。
GMM 简介
正如您可能已经想到的,高斯混合模型假设您的数据遵循高斯(也称为正态)分布。因为在您的数据中可以有多个这样的分布,所以您可以指定它们的数量,这实际上就是您想要的集群的数量。
此外,由于单独的分布可以重叠,因此模型输出不是将点硬分配给特定的聚类。该点属于所述分布是基于概率的。比方说,如果点 A 属于“聚类 0”的概率为 0.6,属于“聚类 1”的概率为 0.4,那么模型将推荐“聚类 0”作为该点的标签(因为 0.6 > 0.4)。
为了进一步帮助解释,让我们看一些图表。
- 下图显示了 GMM 确定的 4 个澳大利亚城市集群。请注意,每个聚类都有自己的均值(中心)、协方差(形状)和大小。此外,不同的集群(紫色、蓝色和绿色)之间有明显的重叠。
高斯混合模型(GMM) —澳大利亚城市的 4 个集群。图片由作者提供。
- 如前所述,分类标签分配是基于挑选属于特定分类的特定数据点的最高概率。然而,这并不意味着该点肯定是该集群(分布)的一部分。
- 看看当我们要求模型为上面找到的分布生成新的数据点(样本)时会发生什么:
高斯混合模型(GMM)-为 4 个分布生成 10,000 个新样本。图片由作者提供。
- 由于分布的重叠性质,你会得到一些混在蓝点中的紫色点,以及一些混在蓝点和紫色点中的绿色点。因此,GMM 可以被描述为一种软聚类方法,其中不存在硬决策边界来分离不同的聚类。
期望最大化(EM)
为了理解 GMM 在实践中是如何工作的,我们需要看看期望最大化(EM)算法。EM 使用迭代方法来计算和重新计算每个聚类(分布)的参数,即平均值、方差/协方差和大小。
我不会对每一步中发生的事情进行复杂的数学计算。相反,我将给你一个直观的解释,从下面的图表开始,以便于形象化:
高斯混合模型(GMM) —寻找 4 个聚类的迭代过程。图片来自作者。
开始时,该模型用一组参数初始化指定数量的聚类,这些参数可以是随机的,也可以是用户指定的。智能初始化选项在某些实现中也是可用的(例如, sklearn 的 GMM 实现默认使用 kmeans 来初始化集群)。
对于上面的图表,我已经指定了我自己的一组平均值(起始中心)来初始化聚类,这帮助我创建了一个更好的可视化。与随机初始化相比,它还加快了收敛速度。
然而,你必须非常小心初始化,因为 GMM 的最终结果往往是非常敏感的初始参数。因此,建议使用智能初始化或随机初始化多次,然后选择最佳结果。
因此,初始化聚类后,我们就可以使用均值(μ)、协方差(Cov)和大小(𝜋)了。
- 期望(E 步骤) —对于每个数据点,计算一个“责任” r ,简单来说,就是该数据点属于一个聚类 c 的概率。这是针对每个集群的每个点进行的。
- 最大化(M 步) —然后使用“责任”来重新计算每个聚类(分布)的平均值、协方差和大小。到了这一步,你也可以把“责任”当成一个砝码。数据点属于一个聚类的可能性越小,它在μ、Cov 和𝜋.的重新计算中的权重就越小在上面的 GIF 图像中,您可以看到簇的位置、形状和大小是如何随着每次迭代而变化的。
E-step 和 M-step 的过程重复多次,直到不能进行进一步的改进,即达到收敛。
GMM 聚类的 Python 示例
设置
我们将使用以下数据和库:
- 来自 Kaggle 的澳大利亚天气数据
- Scikit-learn 库根据剪影得分确定我们想要多少个聚类,并执行 GMM 聚类
- 用于数据可视化的 Plotly 和 Matplotlib
- 用于数据操作的熊猫和 Numpy
- 地理坐标,进度条,采集澳大利亚城市坐标的时间
让我们导入所有的库:
然后我们从 Kaggle 获取澳大利亚的天气数据,你可以按照这个链接下载:https://www . ka ggle . com/jsphyg/weather-dataset-rattle-package。
我们接收数据并派生出一个新变量“Location2”,它具有使用 Geopy 提取城市坐标的正确格式。
一段经过修改的 Kaggle 的澳大利亚天气数据。图片由作者提供。
因为我们的原始数据只包含位置(城市)名称而不包含坐标,所以我们将使用 Geopy 的名称来获取这些坐标。请注意,我们在每次调用之间添加了 1 秒钟的睡眠时间,以避免服务器过载。
这是我们得到的回报片段:
澳大利亚城市坐标。图片由作者提供。
接下来,让我们在地图上标出城市:
地图上的澳大利亚城市。图片由作者提供。
GMM 聚类—选择聚类的数量
有多种方法可以选择应该有多少个集群。它可以基于你对数据的了解,或者更多的数据驱动的东西,比如剪影分数。这里有一段直接引自 sklearn 的话:
轮廓系数是为每个样本定义的,由两个分数组成:
a: 一个样本到同一类中所有其他点的平均距离。
b: 样本与下一个最近的聚类中所有其他点之间的平均距离。
单个样品的轮廓系数 s 为:
一组样本的轮廓系数是每个样本的轮廓系数的平均值。
让我们创建多个 GMM 模型使用不同数量的集群和绘图剪影分数。
利用剪影分数确定 GMM 聚类数。图片由作者提供。
一般来说,轮廓分数越高,你的聚类就越清晰。在这个例子中,我选择了 4 个集群,而不是 2 个,尽管 2 个集群设置的分数略高。
请注意,如果您非常熟悉您的数据,在决定聚类数量时,您可能更喜欢使用轮廓分数作为指南,而不是硬性规则。
GMM 聚类—构建模型
现在让我们建立我们的 GMM 模型:
下面是上面的代码打印出来的总结。注意,在显示均值(聚类中心)的情况下,7 次迭代后已经实现收敛:
GMM 模型的输出。图片由作者提供。
现在,让我们在地图上绘制集群:
高斯混合模型(GMM) —澳大利亚城市的 4 个集群。图片由作者提供。
最后,您还可以绘制模型生成的 10,000 个新点的样本,如本文前面的图表所示:
高斯混合模型(GMM)-为 4 个分布生成 10,000 个新样本。图片由作者提供。
结论
高斯混合模型在聚类呈“椭圆形”的情况下非常有用。K-Means 只使用均值(质心)来寻找聚类,而 GMM 还包括方差/协方差。这正是 GMM 在识别非圆形聚类时优于 K-Means 的地方。
一般来说,你可以认为 GMM 是 K-Means 的一个更高级的版本,但是请记住,它并不总是给你优越的结果。这是因为这很大程度上取决于数据的形状和你想要达到的目标。
我希望这篇文章能帮助你更好地理解高斯混合模型。如果想了解更多的备选聚类算法,可以参考我下面的文章。
干杯!👏
索尔·多比拉斯
如果你已经花光了这个月的学习预算,下次请记得我。 我的个性化链接加入媒介是:
https://solclover.com/membership
来吧,改变我的想法
公平和偏见
代理作为人工智能公平辩论中缺失的成分。
你曾经试图改变别人的想法吗?你当然有。毕竟,从根本上讲,这是大部分交流的目的。这也非常困难。
当谈到塑造了我们的根深蒂固的政治、宗教或社会信仰时,就更难了,因为它们往往与我们自己的身份联系在一起。许多信念甚至是完全无意识的,只能通过间接手段引出。没有人知道我分发的工作申请是否会因为我的种族或性别而受到不同的对待,因为我交给的人可能甚至没有意识到他们自己的偏见。如果是的话,他们很容易隐藏。以持续、持久的方式改变一个人的想法需要多年的时间和奉献,尤其是当一种信仰根植于某人的情感经历时。
人工智能系统并非如此。尽管存在缺陷和偏见,但人工智能系统与人类决策系统的一个区别在于,暴露它们的偏见并改变它们的想法相对容易。
如果你想发现某人在评估求职者时的偏见,正确的方法可能是给他们数千份申请,根据你寻求的属性,对照所有其他属性,审查和衡量结果的统计差异。虽然当有足够多的申请人通过标准化流程时,这通常会在团体层面进行,但对于任何单个决策者来说,这是不可能的,这使得很难进行干预,除非是在政策层面。你不可能让一个人审查成千上万份申请,然后得到有统计学意义的结果。你不能问决策者他们的偏见,因为他们可能没有意识到这些偏见,或者他们可能有隐藏这些偏见的既得利益。
另一方面,人工智能系统可以处理成千上万的测试样本。事实上,正是这种可伸缩性使它们成为如此多审查的对象:很容易发现它们,并且通过增加样本大小,任何缺陷通常都可以用可接受的 p 值发现。这也是一件好事,因为它使我们能够深入研究那些有可能以各种方式对人们的生活产生巨大影响的系统。
但是这种可用性偏差并不经常被认识到:因为类似的偏差研究很难在人身上进行,所以它们很少被执行。我们听到的许多关于人工智能偏见的叙述正是因为这是我们可以衡量的,而影响当今世界的绝大多数决策系统都是人类的,不透明的,经得起统计审查。
当我们在人工智能系统中发现偏差时,我们可以当场改变他们的想法。我们可以控制他们接触到的数据和事实,以便建立他们的知识库。作为模型设计者,我们可以修改我们将哪些归纳偏差编码到其中,以及它试图优化的成本函数。作为一个社区,我们越来越好地提高了对我们所拥有的相关旋钮的理解。例如,研究表明,用非常 很少的基础陈述,你可以影响一个非常大的神经模型的整个‘信念系统’。您还可以微调 ML 系统做出的权衡,以确保公平的结果,而不牺牲性能。这是很了不起的,尤其是当你把它与几乎不可能对我们基本上无意识的人类认知偏见有任何作用的情况进行对比时。
结果的一致性也有内在的公平性。没有根本原因而改变的决策本质上是不公平的,这就是为什么自动决策系统不一定需要比人类同行表现得更好才能提供更公平的结果,只要它们减少了结果的差异。人工智能不会遭受决策疲劳。
在评估机器学习的公平性和道德含义时,可审计性、可控性和一致性值得占据中心位置。
有些人会说,这里的障碍不是人类决策系统,而是基于规则的系统,这些系统也可以说是一致的、可控的和可审计的。但是这里存在着另一个陷阱:越糟越不公平。一个在任务中表现更差的系统,即使更简单、更容易推理,通常在结果的公平性方面更差。我曾经从事自动语音识别的工作,在早期,这些系统在识别英语口语方面效果不佳。但受影响最大的并不是在美国出生的中年白人男性,他们在完全安静的办公室环境中工作。年轻人和老年人,母语非英语的人,生活在充满挑战的嘈杂的声学环境中的人。以透明性和可检验性的名义争论更粗糙、更简单的模型常常忽略了一个简单的事实,即一个更好的决策系统通常比分布的主要模式更积极地影响“长尾”。事实上,尽管人们对使用越来越大、越来越复杂的语言模型感到担忧,但有强有力的证据表明,语言模型做得越好,它们就越符合人类共同的价值观。
人们实际上可以说,在人工智能系统的基本性能方面所做的工作对公平结果的影响比许多直接针对人工智能公平的文献要深远得多,尽管如果没有今天在这个主题上的大量工作,我们甚至无法评估这种影响。我们在这个领域的更多集体工作应该越来越少地以仅仅揭露他们的缺陷为目标,而是更多地利用我们对人工智能系统的这种代理,以及我们改变他们的想法以实现更公平和更公正结果的前所未有的能力。
(感谢 Ed H. Chi 对本文的宝贵反馈。)
与 OpenFL 联合
将您的深度学习管道放在联邦 rails 上
介绍
OpenFL 是英特尔开发的用于联合学习 (FL)的开源框架。FL 是一种在分布于多个节点的分片数据集上训练统计模型的技术。此外,由于隐私/法律问题(如 HIPAA 或 GDPR 等法律)、数据集的大小或其他原因,数据可能在不同的分片之间分布不同,并且不能在节点之间移动。OpenFL 旨在解决当数据在组织或远程数据中心之间拆分时所谓的跨筒仓联合学习问题。
OpenFL 旨在为数据科学家提供一个有效且安全的基础设施。OpenFL 的可扩展特性应该使联邦学习领域的研究变得容易和民主化
随着 1.2 版本的更新,OpenFL 团队努力提高框架的可学性,并分离设置联邦和使用它运行 FL 实验的过程。在 OpenFL 团队,我们致力于最小化用户入口点,简化建立联盟的过程,以及注册和运行 FL 实验。
1.2 版 OpenFL 更新引入了用户会话、允许在重用现有连接的同时进行多次后续实验的长期组件,以及开发的交互式 Python API,以简化对单节点训练代码的修改,并为数据科学家提供单节点体验。
轻松处理远程数据
让我们想象一群配备有计算单元并保存唯一数据集的节点。如果一组节点持有的数据允许解决特定的数据科学问题,并且控制这些节点的人愿意合作解决该问题(至少允许对他们的数据进行本地培训),则这样的一组节点可以组成联盟。
让我们想象一下,几个节点所有者同意创建一个联盟,从而使他们唯一的数据集成为虚拟全局数据集的碎片。现在,我们仔细看看最重要的部分——上面提到的数据碎片。数据碎片可能以不同的格式保存,尤其是如果节点属于不同的组织。数据碎片是异构的(这是我们首先要将它们组合在一起的原因),它们在来源、磁盘上的结构、标记模式等方面有所不同。为了促进这种多样性并描述一个将使用所有碎片的单个实验,我们必须选择以下之一:
- 实验中的数据加载过程应该有一个 switch-case 逻辑来加载不同的数据碎片。这种必要性不仅打破了实验定义的单节点体验,还意味着数据科学家知道每个数据集碎片的结构。
- 数据集碎片所有者同意一个通用的数据结构,并相应地准备他们的数据。尽管实验中的数据加载过程对于所有数据集碎片都是相同的,但它们的所有者必须描述数据读取和转储脚本,并为每个给定的数据接口保留一份数据集副本。
OpenFL 试图通过将数据准备过程包含在联邦设置管道中,从这两种方法中取长补短来解决这个问题。OpenFL 现在为数据集碎片所有者提供了碎片描述符接口。它允许定义数据读取程序,并描述符合统一数据接口的数据采集方法。在不转储数据集碎片的格式化副本的情况下,碎片描述符为联邦中所有节点上的实验提供了单一的数据访问方法。在这个模式中,数据样本只在运行时加载。
总之,分片描述符的引入是为了解决数据异构,并为定义 FL 实验的数据科学家提供统一的数据接口。数据集碎片所有者可以介绍他们的数据读取过程、预处理,如果需要,甚至可以利用差分隐私技术。
主要使用场景
在这一节中,我们将介绍设置一个联邦所需的主要步骤,并使用 OpenFL 进行一个 FL 实验来理解工作流。
成立联合会
我们现在的情况是,有一群数据所有者同意合作解决一些数据科学问题,他们标记的数据集符合这一目的。第一步是在所有将用于联邦模型训练的机器上安装 OpenFL,我们将这些机器进一步称为“合作者节点”。
OpenFL 可以从 PyPI 安装(conda 包和 docker 镜像也是可用的):
$pip install openfl
然后数据所有者需要实现分片描述符 Python 类。
此时,联合参与者必须选择联合中的中心节点,该节点将用作实验服务器,并将从所有协作者节点聚合模型更新。
名为 Director 服务的实验服务器现在应该使用 OpenFL 命令行界面(CLI)在中心节点上启动。它以联邦中的统一数据集格式和中心节点上的开放端口作为参数。
随着导演的运行,其名为使节的‘客户’现在可能在合作者节点上启动。特使也使用 OpenFL CLI 启动,使用配置文件和控制器的网络地址作为参数。上面提到的配置文件应该包含本地 Shard Descriptor 类的导入地址及其参数(如果需要的话)。启动后,特使尝试与指挥者建立 gRPC 连接,如果分片描述符符合统一数据接口,指挥者可能会接受特使加入联盟。
到目前为止,我们有一个星形的节点网络:几个特使连接到主任并等待即将到来的实验。我们称这样的网络为联盟。当控制器关闭时,该联盟可能会主持几个实验并停止存在。
注册一个 FL 实验
此时,数据科学家可以注册他们的实验,以便在联邦中执行。OpenFL 提供了一个单独的前端 Director 的客户端作为 Python API 的一部分来注册实验。数据科学家可以从另一台机器(包括计算资源有限的笔记本电脑)连接到 Director ,并在交互式环境(如 Jupyter 笔记本或 Python 脚本)中定义他们的实验。在下一节中,我们将进一步了解前端 Python API。
几个用户可能连接到同一个 Director ,但是注册的实验是在联邦中一个一个执行的(至少对于 OpenFL v1.2 是这样)。当实验结束时,用户可以检索训练工件:检查点和训练日志。
当一个实验被主任接受时会发生什么
当用户向主管报告 FL 实验时,实验工作空间和用于再现 Python 环境的信息被打包到一个档案中并发送给主管。导演向参与的使者播放实验档案。然后,导演启动一个聚合器服务来编排培训过程。特使启动协作者进程,该进程将根据本地数据训练模型。
绿色块是长期存在的组件。黄色块是为特定实验产生的短命组件。双向箭头是 gRPC 连接。(图片作者)
交互式前端 API
在上一节中,我们从数据持有者的角度调查了与 OpenFL 的交互,现在让我们概述一下数据科学家可以利用所创建的基础设施的方式。
如上所述,OpenFL 提供了一个独特的交互式 Python API,旨在简化 FL 实验。通过这次更新,我们试图将研究人员的界面从建立网络的过程中分离出来,因此定义 FL 实验的努力不会随着联盟中合作者的数量而增加。
定义 FL 实验的努力并不与联盟中合作者的数量成比例
一般来说,前端 Python API 允许用户注册统计模型和训练逻辑,因此可以以联合的方式训练它。下面我们重点介绍在 OpenFL 中所看到的 FL 实验的三个主要部分:
- 模型和优化器可以以用户喜欢的方式创建和初始化。OpenFL 前端 API 提供了一个模型接口类来注册这些对象。OpenFL 允许使用 PyTorch 或 TensorFlow 2 深度学习框架作为计算后端。模型接口是选择其中一个或者提供支持另一个 DL 框架的插件的地方。OpenFL 本身是 DL 框架无关的。
- FL 任务是包含训练逻辑的主要单元,描述独立于其他部分的训练程序的独立部分,例如“训练”或“验证”。OpenFL Python API 提供了任务接口类,允许将独立函数改编为 FL 任务。任务必须将模型、优化器和数据加载器作为参数,并可选地返回一些计算的指标,但除了这些约束,它还是一个常规的 Python 函数。
- **数据加载器。**FL 实验定义的最后一部分是准备数据。OpenFL API 中有一个可子类化的数据接口,它将在 collaborator 节点上适配 Shard 描述符,并为任务提供本地数据。必须解释一下分片描述符和数据加载器之间的区别:分片描述符执行数据读取和预处理例程,每个特使可能有唯一的分片描述符,而数据加载器在数据科学家的环境中每个 FL 实验定义一次,包含扩充和批处理逻辑。
OpenFL 是一个深度学习框架不可知的库
当 FL 实验的所有三个部分都实现时,用户应该利用控制对象来注册实验并监督实验的执行。
联盟对象是主管的客户端的包装器,它帮助将特定的笔记本连接到联盟。连接的联邦对象允许用户检查连接的特使集合,也可以提供一个模拟远程的虚拟碎片描述符。它允许对实验代码进行本地调试,从而提供单节点体验,就好像可以从数据科学家的机器上访问数据一样。
实验对象包装了模型、数据和任务接口,并帮助向给定的联邦报告实验。应该是用来打包本地代码和使用过的 Python 包列表,并发送给 Director 。实验对象还提供了监控已接受实验的状态和检索已训练模型的方法。
将交互式 API 引入 OpenFL 背后的总体意图是允许数据科学家包装他们现有的单节点训练管道,并以最小的努力开始 FL 实验。
摘要
OpenFL 开发致力于为数据科学家创建一个灵活方便的工具,试图简化和加速联邦学习领域的研究。
您可以查看一个使用 OpenFL 以联邦方式在 Kvasir 数据集上训练 UNet 模型的实际示例,以及一个关于如何做的手册。
如果您感兴趣,这里有一个有用的资源列表:
照片由 Alina Grubnyak 在 Unsplash 上拍摄