TowardsDataScience-博客中文翻译-2021-十七-
TowardsDataScience 博客中文翻译 2021(十七)
原文:TowardsDataScience Blog
协议:CC BY-NC-SA 4.0
Azure 数据工厂管道的自动化测试
原文:https://towardsdatascience.com/automated-testing-of-azure-data-factory-pipelines-23f60d33ba5e?source=collection_archive---------14-----------------------
从 DevOps 的角度提高解决方案的质量
把你的脚抬起来——照片由 Unsplash 上的 Kewal 拍摄
在 DevOps 的帮助下,在更小或更大的团队中开发 ETL 或 ELT 解决方案从未如此简单。它使我们能够确定,在多个团队成员对解决方案的不同部分进行更改后,解决方案仍然有效。例如数据库存储过程、表、视图等的变化。结合 Azure 数据工厂管道和部署管道(CI/CD) 设置的变化。
DevOps 教导我们尽可能多地自动化,以创造过程的可重复性。使用源代码控制和频繁的代码签入。实施持续集成和持续开发(CI/CD)将有助于我们快速、可靠地交付产品,而无需人工依赖。
我们和一个小团队一起开发一个数据平台“解决方案加速器”。这个加速器使我们能够轻松地部署一个有效的端到端解决方案,包括 Azure SQL 数据库、Azure 数据工厂和 Azure Key Vault。
我们一直在改进我们的解决方案,并为其添加新功能。作为产品所有者,我想确保我的产品不会被这些添加的东西破坏。除了好的分支策略之外,尽可能多地自动化测试有助于我们实现这一点。
对我们的部署管道的最新改进是从我们的部署管道触发一个 Azure 数据工厂(ADF)管道,并监控结果。在这种情况下,结果决定了是否允许完成拉请求,因此减少了导致“中断”主分支的机会。
在本文中,我将对的构建和发布管道中的步骤进行概述,并提供用于触发和监控ADF 管道的脚本。
Please note the difference between pipelines. I'm talking about **Azure Data Factory pipelines** whose main task is the movement of data. And on the other hand **CI/CD or deployment pipelines**. These are used to deploy resources to our Azure subscription. And live in our Azure DevOps Project. Please note that there are many kinds of tests that you can perform. In this example we are merely checking if the ADF pipeline 'is **doing things right**'. In contradiction to 'is it **doing the** **right things**'!
Azure DevOps 管道设置
除其他外,我们目前使用的设置具有以下要素:
GitHub 资源库:
- Azure 资源管理模板(ARM 模板)
- Visual Studio 数据库项目
- JSON 格式的 Azure 数据工厂管道
Azure DevOps 项目:
- YAML 的天蓝色管道:
- 构建和验证阶段
- 发布阶段
我强烈建议使用 YAML 语法来定义管道,而不是传统的编辑器。最大的优势是能够用代码的相应版本来控制管道的版本。请参见文档的参考资料。
管道设置—构建和验证阶段
管道有两种不同的阶段:一个“构建和验证”阶段和多个“发布”阶段。
“构建和验证”阶段有两个主要目标:
- 验证 ARM 模板
- 构建数据库项目
这些任务的结果作为工件发布,在发布阶段使用。
Azure DevOps 构建和验证步骤
管道设置—发布阶段
“发布”阶段的任务是按照以下顺序部署所有资源:
- ARM 模板的部署
- ADF 对象(管道、数据集等)的部署。)*
- SQL 数据库项目的部署
Azure DevOps 发布步骤
*Tip Deploying Azure Data Factory: We had many discussions about the topic, but in the end chose to use an [extension build by Kamil Nowinski](https://sqlplayer.net/2021/01/two-methods-of-deployment-azure-data-factory/) in stead of the Microsoft approach. The are many quality of life improvements in this extension!
管道设置—发布阶段触发器
部署管道的发布阶段针对我们定义的不同环境重复进行。在我们的情况下,我们使用开发、测试和生产。这些环境的触发器是我们选择的 git 分支策略的结果。
正是在这个“测试”环境的发布阶段,我们实现了一个 PowerShell 任务,它触发并监控 ADF 管道的运行。当 GitHub 存储库中的 pull-request 被启动时,测试环境的发布被触发。
触发和监控 ADF 管道运行
除了 ADF 用户界面,还有多种方法可以触发管道。这里我们使用 PowerShell,因为它很容易被整合到部署管道中。下面是一个 Azure PowerShell 任务的示例,它从您的存储库中执行一个脚本。
Microsoft 文档为 PowerShell 脚本提供了一个很好的起点。在合并了用于触发和监控的语句后,我做了两个重要的修改:
- 如果 ADF 管道获得“排队”状态,脚本将会中断
- 如果结果不等于“成功”,我们抛出一个错误
在第 27 行抛出错误确保发布阶段的任务失败,因此整个流水线获得状态‘失败’。这很重要,因为这个防止拉请求在这个错误在对存储库的另一个提交中被解决之前完成。
就是这样!请分享更多改进的建议!
参考
Azure Pipelines |微软文档
Azure Pipelines—Azure PowerShell 任务|微软文档
Azure 数据工厂— PowerShell |微软文档
Azure Data Factory—Azure Data Factory 中的持续集成和交付|微软文档
ADF 工具| SQL 播放器
自动树状图切割
原文:https://towardsdatascience.com/automatic-dendrogram-cut-e019202e59a7?source=collection_archive---------25-----------------------
实践中打包贝叶斯
由 kazuend 在 Unsplash 拍摄的照片
聚类分析是一种探索数据结构的有用技术。在众多算法中,凝聚聚类是一种简单而有用的方法,它通过逐步链接最相似的对,直到所有数据都链接在一起,从而自下而上地建立聚类层次。通过将层次结构表示为树状图,它有助于我们深入了解数据的分布和结构。尽管很有见地,但有时我们可能更希望在实际应用中使用扁平化的表示,结果却是一个关于如何切割树状图的问题。在本文中,我将向您展示我们如何在特定的标准下,最优地将树状图切割成小块,而不是沿着特定的阈值简单地直接切割。
切割树状图的最佳方式
简而言之,我们的目标是将树状图切割成 k 个不相交的子树,使得一些选择的损失达到最小。损失/选择标准是自由的,一个可能的选择是类内平方和(WCSS),这是 k 均值聚类旨在最小化的目标函数。有了标准,下一个问题是,我们如何去做?列举所有的可能性肯定有用,但那样会太累。一个聪明的解决方法是探索最优子结构并执行动态规划。简而言之,为了最优地将整棵树切割成 k 个子树,这相当于找到最优的 kₗ和 kᵣ,我们需要从根的左右分支获得子树的数量,使得 kₗ + kᵣ = k。对于每个可能的(kₗ,kᵣ)对,我们需要将左右分支切割成 kₗ和 kᵣ子树,这与我们切割整棵树的问题完全相同。因此,我们可以递归地划分问题,直到树状图的叶子。要了解清楚的细节,这里有戈蒂埃·马蒂的一个很棒的帖子。
简单的三类数据集。
平均法树状图。这三种分别是最佳的 2 切、3 切和 4 切。
选择要切割树状图的聚类数
我们已经学习了如何最优地将一个树状图切割成 k 块,现在我们需要确定我们需要多少个聚类。确定 k 无疑是我们在进行聚类分析时面临的最困难的问题,特别是当我们希望以数据驱动的方式自动确定 k 时。在 rest 内容中,我将介绍一个强大但不太为人所知的框架,称为 PAC 贝叶斯学习,用于 k 选择问题。
什么是 PAC 贝叶斯?
可能近似正确,又名 PAC,是一个通过构建过度误差的上限来量化可学习性的框架,过度误差是样本内误差和样本外误差(泛化误差)之间的差异。PAC Bayesian 扩展了这个框架,它通过引入假设的先验分布来表达关于假设的某种信念,就像我们在 Bayesian 学习中所做的那样。
它是如何工作的?
关于 PAC 贝叶斯界的形式其实有很多种,下面我将介绍最基本的(我认为)形式。在贝叶斯设置中,人们通常使用模型证据作为度量来评估模型的性能,并从中选择最佳的一个。它被表述为
其中 D 是观测数据,M 是模型,θ是模型参数,p(θ|M)是θ的先验分布,p(D|M,θ)是在模型配置为θ的情况下观测到 D 的可能性。
为了评估证据,我们需要计算积分,这有时是棘手的。因此,我们求助于优化它的下界,证据下界(ELBO):
对于所有可能的 q,当 q 等于后验 p(θ|D,M)时,等式成立。因此,给定一组模型,我们可以尝试优化 ELBO,并选择最大的 ELBO 作为最终选择。这个框架是独立的,有很强的理论支持,但有很大的限制,因为我们需要给出有效的概率度量来量化可能性——它当然不适用于我们的树图切割问题。概括的一种方法是将对数似然替换为任意损失函数,得到
通过一些代数运算,它等价于求的最小值
因为我们有一个单一的切割,而不是对每个 k 的所有可能性的分布,它进一步退化为
其中前一项是由最优切割产生的总 wcs,Zᵏ代表每个观察值的聚类标签。现在,我们只需要指定 Zᵏ的先验分布来完成最后一个谜题。一个合理的选择将是中国餐馆过程,一个众所周知的非参数贝叶斯文献中的分布,用于描述聚类标签的分布。它可以通过以下方式进行累积评估
不同的 k 与 PAC 贝叶斯正则化项的损失,λ=0.2,α=1
地毯下的污垢
在玩机器学习的时候,我们都知道没有免费的午餐。一个适用于所有数据集的通用λ是不存在的,我们不可避免地要动手寻找最适合数据集的λ。尽管如此,我们至少在系统地解决问题。
最后的话
PAC Bayesian 是一个强大的、强有力的理论支持框架,用于研究模型的泛化能力,甚至用于过参数化的神经网络。在本文中,我简单地应用了基本形式来解决从一组最优树图切割中选择 k 的问题,这只是其威力的冰山一角。我希望它能对每个对此感兴趣的人有所帮助和启发。
模拟:https://github.com/jerrylin0809/pac-bayesian-dendrogram-cut
用 Python 自动下载电子邮件附件
原文:https://towardsdatascience.com/automatic-download-email-attachment-with-python-4aa59bc66c25?source=collection_archive---------1-----------------------
使用 PyWin32 实现自动化
简化繁琐的东西来解放我们的思想。
由大卫·巴拉迪在 Unsplash 上拍摄的照片
您是否曾经在邮箱中搜索过所有需要的附件?然后也许你离开了,回来的时候忘记了你停在哪里?也许你还需要把它们保存到不同的目录或文件夹中?
我以前也在那个位置。这就是为什么我想自动下载附件到正确的目录。之后,对电子邮件的附件进行相应的转换。
在本文中,我将比较解决方案的可能 Python 库,并分享我如何使用 Python 来自动化这个过程。
访问邮箱的 Python 库比较
作者创建的图像
smtplib 不是我的选择之一,因为它只能发送电子邮件,而 imaplib 需要用户名和密码,这不太好。因此,我选择了 pywin32 。
使用 pywin32 从 Outlook 下载特定邮件
没有可用的 pywin32 官方文档。目前,我们只能参考Visual Basic for Application(VBA)中的 Outlook MailItem 的引用来了解可以用来操作邮箱和邮件的函数。然后,当您在 Python 中编写脚本时,不能直接使用该示例。在各种技术写作网站上也有一些很好的 pywin32 应用实例,但都不完整。
本文涵盖了使用 pywin32 访问 Outlook 邮箱所需的所有基本知识。
- 导入模块
第一步。
# pip install pywin32 #if you not installed yet
import win32com.client
2。建立与 Outlook 的连接
# set up connection to outlook
outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")
3。MailItem 操作的一些基本方法/属性
(1)访问收件箱。
inbox = outlook.GetDefaultFolder(6)# for sub folder, add <.folder("your folder name")>
inbox = outlook.GetDefaultFolder(6).folders("Testing")
6 是收件箱的索引。其他常见项目的索引如下。
3 Deleted Items
4 Outbox
5 Sent Items
6 Inbox
16 Drafts
您可以使用下面的源代码来检查其他文件夹的索引。(参考 C2)
import win32com.client
outlook=win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")
for i in range(50):
try:
box = outlook.GetDefaultFolder(i)
name = box.Name
print(i, name)
except:
pass
(2)阅读电子邮件
# Access to the email in the inbox
messages = inbox.Items# get the first email
message = messages.GetFirst()
# get the last email
#message = messages.GetLast()# to loop thru the email in the inbox
while True:
try:
print(message.subject) # get the subject of the email
# if you use messages.GetFirst() earlier
message = messages.GetNext()
# if you use messages.GetPrevious() earlier
#message = messages.GetPrevious()
except:
# if you use messages.GetFirst() earlier
message = messages.GetNext()
# if you use messages.GetPrevious() earlier
#message = messages.GetPrevious()
上面的例子显示了如何打印收件箱中所有邮件的主题。除了主题之外,我们还可以打印其他属性或将其用作定义条件语句的标准。下面显示了一些常见的属性。
message.subject
message.senton # return the date & time email sent
message.senton.date()
message.senton.time()
message.sender
message.SenderEmailAddress
message.Attachments # return all attachments in the email
注意,以一对括号结尾的messages.GetFirst()
或messages.GetNext()
指的是我们可以用来操作邮箱的方法,而message.subject
或message.senton
指的是电子邮件的属性,使用 Python 时不区分大小写。因此,对于完整的 MailItem 属性列表,你可以参考 VB 中的 MailItem 文档,它可以在底部的参考 C1 中找到。(我没有全部试过,但是大部分都可以适用。)
(3)下载邮件附件。
attachments = message.Attachments# return the first item in attachments
attachment = attachments.Item(1)
# the name of attachment file
attachment_name = str(attachment).lower()
attachment.SaveASFile(path+ '\\' + attachment_name)
4。完整示例
# import libraries
import win32com.client
import re
# set up connection to outlook
outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")inbox = outlook.GetDefaultFolder(6)
messages = inbox.Items
message = messages.GetFirst()
today_date = str(datetime.date.today())while True:
try:
current_sender = str(message.Sender).lower()
current_subject = str(message.Subject).lower()
# find the email from a specific sender with a specific subject
# condition
if re.search('Subject Title',current_subject) != None and re.search(sender_name,current_sender) != None: print(current_subject) # verify the subject
print(current_sender) # verify the sender
attachments = message.Attachments
attachment = attachments.Item(1)
attachment_name = str(attachment).lower()
attachment.SaveASFile(path + '\\' + attachment_name)
else:
pass message = messages.GetNext() except:
message = messages.GetNext()exit
上面是一个完整的例子,它将来自特定发件人的带有特定标题的电子邮件下载到特定的路径。您可以根据自己的情况更改条件,例如,您可以使用message.senton.date()
获取在指定日期收到的电子邮件。此外,您可以使用嵌套的 if-else 语句将附件保存在不同的目录中,这在您要下载大量附件时非常方便。
保持联系
订阅 YouTube
参考
A.smtplib
smtplib 的文档
B.imaplib
imaplib 的文档
C.pywin32
- MailItem 接口(所有 Outlook MailItem 对象属性、方法和事件的应用程序参考 Visual Basic)
- 清楚地记录了使用 python win32com outlook 阅读电子邮件的功能(包含了在 outlook 中访问邮件和附件所需的大部分基本属性)
一些旁注
如果你对如何使用pywin32
实现 Microsoft Excel 报表自动化感兴趣,可以参考这篇文章《用 Python 实现 Excel 自动化》。
如果你有兴趣用 Python 创建一个图表或数据透视图,并将其作为电子邮件附件自动共享,那么用 Python 自动化 Excel 图表。
祝贺并感谢你阅读到最后。希望你喜欢这篇文章。 ☺️
由凯文·布茨在 Unsplash 上拍摄的照片
PyTorch 自动语法和拼写纠正—第 1 部分:基线
原文:https://towardsdatascience.com/automatic-grammar-and-spelling-correction-with-pytorch-part-1-a-baseline-d97b7202de74?source=collection_archive---------20-----------------------
建立一个深层的变压器网络,纠正英语句子
阿伦·普拉卡什在 Unsplash 上的照片
我是 Grammarly 或 Reverso 等服务的忠实粉丝,这些服务可以帮助纠正语法和拼写错误。这促使我建立了一个更简单的机器学习基线,可以自动纠正英语句子。
在本帖中,我们将介绍序列到序列转换器模型的实现和训练,该模型将输入一个有潜在错误的句子,然后在纠正所有错误后生成相同的句子。这类似于在巴特中所做的。
数据
对于这种基线方法,我们将仅使用合成数据来训练该模型。我们将使用维基百科中的句子。然后,对于每个句子,我们将生成一个“受干扰”的句子,其中有随机的人工拼写和语法错误。这给了我们一个 (input,output) 对,其中输入是有错误的句子,输出是原来的句子。
这里我们假设大部分原始维基百科句子不包含错误。
使用合成数据的好处是它们是免费的,我们可以免费生成我们想要的数据。缺点是它们可能不像人们犯的语法和拼写错误的真实例子那样真实或有用。
总之,我们实现了 11 种原始句子的随机变换。
随机扰动的例子:
小写:
原句:
- 这个 是一个例句
转换句子:
- 这个 是一个例句
删除随机单词:
原句:
- 这个 是一个例句
转换句子:
- 是一个例句
改变动词形式:
原句:
- 这个 是 的一个例句
转换句子:
- 这个 分别是 一个例句
扰乱随机词:
原句:
- 这是一个 例句 句子
转换句子:
- 这是一个 宠爱 的句子
等等…
在将它们依次应用于原句之前,我们随机挑选了其中的 3 个。这些扰动中的每一个都与一个权重相关联,该权重决定了它们被选取的频率。
以下是使用此过程生成的(输入,输出)对的示例:
输入(或受干扰的句子):
- 地基 是 的河漂石;外墙 是 红砖加砂岩点缀。
输出(或原句):
- 地基 是河流巨砾的;外墙 为 红砖加砂岩点缀。
在这个例子中,我们可以看到,被打乱的句子中动词“to be”的形式和“is”的大小写都是错误的。
模型
我们将要使用的模型架构与论文中介绍的相同。这个模型有一个编码器变压器和一个解码器变压器,注意这两者之间。
编码器处理有潜在拼写或语法错误的句子,而解码器生成有所有更正的句子。
解码器是一个自回归模型,我们在训练中使用教师强制。
模型架构——作者图片
这个模型将学习复制输入的句子,同时纠正它的错误。
在解码器的每个时间步骤,模型可以“注意”输入句子的每个标记以及在解码句子中出现在它之前的每个标记。正是这种关注使得模型能够挑选信息,用于预测解码过程中的下一个令牌。
我们使用 RTX 3080 在大约 800 万个维基百科句子上训练这个模型大约两天。
示例预测
现在是时候看看训练有素的模型了:
示例 1:
有错误的句子:(an 而不是 a)
- 这是爱尔兰对 2010 年的总结。
由模型更正的句子:
- 这是 2010 年爱尔兰的总结。**
该模型用“a”代替了“an”。
示例 2:
有错误的句子:(错误的大写+复数而不是单数)
- 马蒂诺 是 的一部分 音乐 项目 埃斯佩里克 炫目 。
由模型更正的句子:
- 马蒂诺是的部分,音乐投射 埃斯佩里克 眩光。
在这里,模型能够纠正大写错误,但不能解决复数问题。
示例 3:
有错误的句子:(错误的动词形式+拼写错误)
- 何 被 选入西孟加拉 立法院1962 年从巴拉萨特选区击败前进集团领袖奇塔巴苏。
由模型更正的句子:
- 何 曾于 1962 年从巴拉萨特选区击败前进集团领袖奇塔巴苏 当选西孟加拉邦【立法】 议员。
这里的模型使用了动词“to be”的正确形式,并修复了拼写错误。
从这些例子中我们可以看出,模型学习了单词的正确拼写,以及动词的正确形式。它仍然有一些问题固定单词的单数/复数形式。有趣的是,该模型可以正确地复制像“Barasat”或“Basu”这样的罕见或不常见的单词,这正是我们想要的。
结论
在这个项目中,我们实现了拼写和语法纠正的基线方法。这个模型在 PyTorch (见代码)中实现起来很简单,并且可以修复明显的错误,就像上面例子中看到的那样。下一步是更严格地评估模型,然后通过使用其他训练集来改进其性能。
来源:
- http://norvig.com/ngrams/spell-errors.txt
- https://py torch . org/tutorials/初学者/transformer_tutorial.html
- https://github.com/monolithpl/verb.forms.dictionary
使用 Optuna 的自动超参数搜索和优化
原文:https://towardsdatascience.com/automatic-hyperparameter-search-and-optimization-using-optuna-392d77917ede?source=collection_archive---------20-----------------------
如何简单高效地优化您的 AI/ML 模型的超参数
超参数调优是 AI/ML 模型开发中比较耗时的手工任务之一。有时候,您希望在处理其他事情的时候能够自动化它们,比如弄清楚如何部署您的模型,或者只是享受一个下午茶休息时间。现在你可以这么做了。奥普图纳来救援了!
作者图片
为什么是 Optuna?
有许多类似的超参数调节库,包括 Hyperopt。但是为什么特别是 Optuna?对我来说,有几个原因:
- 它是轻量级的、通用的和平台无关的。有很少的依赖性,Optuna 可以集成到流行的 ML 框架中,包括 PyTorch、Tensorflow、scikit-learn、等。
- Optuna 是高效的,并且用优化的算法实现。它从一开始就通过删除没有前途的超参数搜索空间来执行修剪,从而使优化程序运行得更快。
- 它为您跟踪优化过程的发展提供了简单而强大的可视化工具。
- 而且对我个人来说,Optuna 有一个直观易懂的 API,让我可以专注于模型开发任务本身。
既然你已经对 Optuna 有些信服了,那就让我们进入正题吧。
设置
首先,我们需要安装一些依赖项。您可以选择使用 pip 或 conda 进行安装。
- 使用画中画
pip install optuna
pip install plotly
2.使用 conda
conda install -c conda-forge optuna
conda install plotly
不要忘记安装 PyTorch!你可以在这里找到它的安装步骤。
超参数优化
一切都准备好了!让我们从导入一些我们需要的依赖项开始,包括 PyTorch 和 Optuna。
获取数据集
为了便于说明,我们将使用 TorchVision 库提供的时尚 MNIST 数据集。我们将如下定义train_loader
和test_loader
。
初始化常量
既然我们已经有了加载时尚 MNIST 数据集的工作函数,下一步就是定义一些以后会有用的常量。
定义模型
此后,我们需要建立一个简单的网络来训练和验证我们的时尚 MNIST 数据。该网络将是一个简单的线性多层感知器,我们将在其中执行我们的第一个超参数优化试验:
number of layers (n_layers)
hidden units (hidden_units)
dropout probability (dropout_p)
请注意,在上面的代码片段中,有一个参数trial
被传递到函数define_model()
中。这是一个独特的关键字,每当您想要试验超参数的值时,Optuna 都会使用它。
trial.suggest_int()
或trial.suggest_float()
是您可以调用来执行试验的一些方法。第一个参数是试验的名称,随后的参数将指示试验可以采用的可能值的列表。
支持功能
现在让我们定义我们的train
函数,我们将枚举train_loader
并使用negative log-likelihood (nll)
损失函数来计算训练损失。
不要忘记我们将要计算测试accuracy
的test
函数!
定义目标函数
这里,我们将向函数中传递另一个trial
参数,以表明我们对执行超参数优化的兴趣。
我们将进行两次超参数试验:
optimizer_name
lr
(学习率)
Optuna 的优点是能够尽早修剪超参数搜索空间(即移除没有显示出有希望的结果的候选者)。
如果结果不好且不需要进一步考虑,可在报告该纪元的试验后调用raise optuna.exceptions.TrialPruned()
来完成。
7.把所有东西放在一起
最后,我们需要通过定义一个驱动程序来编译我们所有的函数。我们通过以下方式做到这一点:
- 创建一个
study
,我们的超参数优化将放置在它的下面 - 指定
optimize
到maximize
我们的准确性(或者minimize
,如果您报告损失是要注意的关键指标) - 初始化两种类型的试验研究:
pruned_trials
(由于结果不够好而跳过的试验)或complete_trials
(潜在的好结果) - 打印出数值,以跟踪哪个超参数组合产生最佳结果
试验结束后,我们看到终端打印出以下结果。
结果(图片由作者提供)
我们观察到,在 100 次试验后,其中 38 次确实有潜力(即完成)而其中 62 个实际上是无用的(即修剪)。最佳试验包括以下一组超参数:
- 层数 : 3
- 优化器:亚当
- LR : 0.05492006
干得好!
可视化结果
现在一切都完成了,我们可以进行一个快速的可视化来看看我们的试验进展如何。
例如,我们可以检查哪个超参数对模型的性能影响最大:
from optuna.visualization import plot_param_importancesplot_param_importances(study)
超参数重要性(图片由作者提供)
第二层中隐藏单元的数量似乎是影响模型性能的主要因素!
离别的思绪
现在,您可以相对轻松地自动化您的超参数优化过程。有了这些多余的时间,你肯定可以构建一个更好的 ML 模型,或者享受更多的下午茶休息时间…
我定期通过我的电子邮件简讯,用简单的英语和漂亮的可视化总结人工智能研究论文,请在【https://tinyurl.com/2npw2fnz】订阅。
使用网格和随机搜索的 Sklearn 自动调整超参数
原文:https://towardsdatascience.com/automatic-hyperparameter-tuning-with-sklearn-gridsearchcv-and-randomizedsearchcv-e94f53a518ee?source=collection_archive---------11-----------------------
深入探究 Scikit-learn 的 GridSearch 和 RandomSearch 类
照片由海伦娜删剪 上 像素
什么是超参数?
今天,隐藏在引擎盖下的数学世界的算法只需要几行代码就可以训练出来。他们的成功首先取决于训练的数据,然后取决于用户使用了什么超参数。那么,这些超参数是什么?
超参数是用户定义的值,如 kNN 中的 k 和脊套回归中的 alpha 。他们严格控制模型的拟合,这意味着,对于每个数据集,都有一组独特的最佳超参数。找到这个完美集合的最基本的方法是根据直觉随机尝试不同的值。然而,正如您可能猜到的那样,当有许多超参数需要优化时,这种方法很快就变得无用了。
相反,今天您将了解自动超参数调整的两种方法:随机搜索和网格搜索。给定模型的所有超参数的一组可能值,网格搜索使用这些超参数的每一个组合来拟合模型。此外,在每次拟合中,网格搜索使用交叉验证来解决过度拟合问题。尝试所有组合后,搜索会保留产生最佳分数的参数,以便您可以使用它们来构建最终模型。
随机搜索采用的方法与网格略有不同。它不是穷尽性地尝试超参数的每一个组合,这在计算上是昂贵和耗时的,而是随机地对超参数进行采样,并试图接近最佳集合。
幸运的是,Scikit-learn 提供了GridSearchCV
和RandomizedSearchCV
类,使得这个过程变得轻而易举。今天,你将了解他们的一切!
https://ibexorigin.medium.com/membership
获得由强大的 AI-Alpha 信号选择和总结的最佳和最新的 ML 和 AI 论文:
https://alphasignal.ai/?referrer=Bex
准备数据
我们将在爱荷华州住房数据集上调整一个 RandomForestRegressor 模型。我选择 Random Forests 是因为它有足够大的超参数,使本指南更加丰富,但是您将学习的过程可以应用于 Sklearn API 中的任何模型。那么,让我们开始吧:
目标是SalePrice
。为简单起见,我将只选择数字特征:
首先,训练集和测试集都包含缺失值。我们将使用SimpleImputer
来处理它们:
现在,让我们用默认参数来拟合一个基础RandomForestRegressor
。因为我们将测试集仅用于最终评估,所以我将使用训练数据创建一个单独的验证集:
注意:本文的主要焦点是如何执行超参数调优。我们不会担心其他主题,如过度拟合或特征工程,而只是缩小如何使用随机和网格搜索,以便您可以在现实生活中应用自动超参数调整。
我们在测试集上给 R2 打了 0.83 分。我们仅使用以下默认参数来拟合回归变量:
这是很多超参数。我们不会调整所有的,但只关注最重要的。具体来说:
n_esimators
-使用的树木数量max_feauters
-在每个节点分割处使用的特征数量max_depth
:每棵树的叶子数量min_samples_split
:分割内部节点所需的最小样本数min_samples_leaf
:每片叶子的最小样本数bootstrap
:取样方法——有或没有替换。
网格搜索和随机搜索都试图找到每个超参数的最优值。让我们先来看看随机搜索的实际应用。
使用 Sklearn RandomizedSearchCV 进行随机搜索
Scikit-learn 提供了RandomizedSearchCV
类来实现随机搜索。它需要两个参数来设置:一个估计量和一组可能的超参数值,称为参数网格或空间。让我们为随机森林模型定义这个参数网格:
这个参数网格字典应该将超参数作为它们在模型文档中出现的语法中的键。可能的值可以以数组的形式给出。
现在,让我们最后从sklearn.model_selection
导入RandomizedSearchCV
并实例化它:
除了可接受的估计量和参数网格,它还有n_iter
参数。它控制我们在搜索中允许随机选取超参数组合的迭代次数。我们将其设置为 100,因此它将随机抽取 100 个组合并返回最佳得分。我们还使用三重交叉验证,以决定系数作为默认的评分。您可以通过sklearn.metrics.SCORERS.keys()
的任何其他评分功能。现在,让我们开始这个过程:
注意,由于随机搜索执行交叉验证,我们可以将其作为一个整体应用于训练数据。由于 CV 的工作方式,它将为训练和评估创建单独的集合。另外,我将
*n_jobs*
设置为-1 来使用我机器上的所有内核。
经过大约 17 分钟的训练后,可以使用.best_params_
属性访问找到的最佳参数。我们还可以看到最好的分数:
>>> random_cv.best_score_0.8690868090696587
我们得到了大约 87%的决定系数,比基本模型提高了 4%。
Sklearn GridSearchCV
你千万不要根据RandomSearchCV
的结果来选择你的超参数。相反,仅使用它来缩小每个超参数的值范围,以便您可以向GridSearchCV
提供更好的参数网格。
你会问,为什么不从一开始就使用GridSearchCV
?好吧,看看初始参数网格:
有 13680 种可能的超参数组合,对于 3 重 CV,GridSearchCV 将不得不适应随机森林 41040 次。使用RandomizedGridSearchCV
,我们仅用 100 * 3 = 300 次拟合就获得了相当好的分数。
现在,是时候在前一个基础上创建一个新的网格建筑,并将其输入到GridSearchCV
:
这次我们有:
240 种组合,这仍然很多,但我们会继续下去。让我们导入GridSearchCV
并实例化它:
我不必指定scoring
和cv
,因为我们使用的是默认设置,所以不必指定。让我们适应并等待:
35 分钟后,我们得到了上面的分数,这次是真正的最佳分数。让我们看看它们与RandomizedSearchCV
有多大的不同:
>>> grid_cv.best_score_0.8696576413066612
你惊讶吗?我也是。结果的差异是微不足道的。然而,这可能只是给定数据集的一个特例。
当您在实践中有计算繁重的模型时,最好是获得随机搜索的结果,并在更严格的范围内在网格搜索中验证它们。
结论
在这一点上,你可能会认为这一切都很棒。你必须学习调优模型,甚至不需要再看一眼参数的实际作用,仍然可以找到它们的最佳值。但是这种自动化的代价很大:计算量大而且耗时。
你可以等几分钟让它结束,就像我们在这里做的那样。但是,我们的数据集只有 1500 个样本。尽管如此,如果你结合网格和随机搜索,找到最佳参数花了我们将近一个小时。想象一下,您需要等待多长时间才能获得大型数据集。
那么,网格搜索和随机搜索更小的数据集?毫无疑问是的。对于大型数据集,您需要采取不同的方法。幸运的是,“不同的方法”已经被 Scikit-learn…再次覆盖。这就是为什么我的下一篇文章会在HalvingGridSearchCV
和HalvingRandomizedSearchCV
发表。敬请期待!
自动识别系统和拼花地板
原文:https://towardsdatascience.com/automatic-identification-system-and-parquet-365160852b3?source=collection_archive---------37-----------------------
理解大数据
如果在 Parquet 文件中存储最低程度解析的船舶位置数据,查询大量数据会更快更容易。
通过维基百科的公共领域图像
仅仅一百多年前,两艘船在加拿大新斯科舍省的哈利法克斯港相撞。勃朗峰装载了用于欧洲战争的炸丨药,当它与国际海事组织相撞时,货物着火了。这是核武器出现之前最大的一次人为爆炸,在战时的哈利法克斯,它夷平了城市的一部分,杀死了 1700 多人。
碰撞很少如此戏剧性,但即使是最近在 2017 年的,也有生命在这些事故中丧生。
自动识别系统旨在防止这种情况发生。装有 AIS 应答器的船只在水中行驶时会广播它们的位置、航向和身份。
这些低功率广播旨在为雷达提供帮助,可被邻近船只、岸上接收器甚至低空卫星接收到。从全球陆地和空间传感器网络收集 AIS 数据可以提供全球船舶交通状况。
这些数据已被用于评估无冰夏季对加拿大北部群岛船舶交通的影响,估计船舶对鲸鱼栖息地的噪声影响,以及规划港口社区的铁路和公路服务发展。
考虑到这一点,我的目标是构建 AIS 存储,以便可以轻松地创建关于时间、位置、身份和目的地的摘录,但要做到这一点,我需要从 AIS 的加密编码方案中提取一些重要信息。
数据
未分析的 AIS 数据样本。
从 AIS 接收器流出的数据只能模糊地辨认出来。AIS 发射机使用 27 个信息的词汇表。广播的不仅仅是船只的动向,AIS 信息还可以传递天气、船员、搜救活动和航行危险的信息。
我使用 Eric Raymond 的 AIVDM/AIVDO 协议解码指南来导航 AIS 句子结构。因为我正在处理已经存储在压缩文件中的数据,所以我的第一步是将每个文件加载到 pandas 中,并将感叹号上的每一行分成两列——前缀和后缀。**
前缀包含关于一系列标记块中的消息的元数据。正则表达式可以提取这些有趣的比特。卫星来源的人工智能可以在轨道上缓冲,一些供应商提供传感器接收广播的时间(报告 _ 时间)和地面站接收数据的时间(接收 _ 时间)。不是每个句子都有下载时间,所以当数据存在时,会对其进行解析。
正则表达式也可以用来从后缀中分离出值——消息是否被分割成多个句子?如果有,这是第一句还是第二句?把两个句子联系在一起的片段 id 是什么?有效载荷需要填充吗?
AIS 信息最重要的部分是由随机出现的字符串组成的,它构成了信息后半部分的大部分。
AIS 有效载荷以 6 位 ASCII 编码。为了使它可读,我们必须将这部分消息转换成二进制,取出必要的数据位,并将数据转换成适当的类型——字符串、浮点、有符号或无符号整数。
构建有效负载的最后一步是将第二个片段附加到多部分句子的第一个片段上。我招募了一个熊猫“外”合并为这项工作。
现在我们有了一串 1 和 0,我们可以分割它们来找到船的身份和位置。
分割比特
第一步是通过将消息的前六位拉成一个无符号整数,用句子的消息类型标记每一行。
有了消息类型,我们可以开始提取船只的位置。消息 1、2、3、4 和 18 具有纬度和经度。
每艘装有 AIS 发射机的船只都由有效载荷的第 8 至 37 位携带的海上移动服务标识* (MMSI)进行识别。*
消息类型 5 保存船只的目的地,如果声明的话。
使用上面的例子和 Raymond 的 AIS 指南中的详细规范,很容易从有效载荷中解析出其他属性。在这一点上,我有足够的元素来满足我在时间、位置、身份和目的地上创建摘录的目标。
如何存储数据?
我主要看到以 CSV 格式存储的 AIS 数据——我明白了,CSV 无处不在,大多数工具都能理解它,但是数据读取很慢。因为这个归档文件只能被读取,所以理想的做法是以列存储格式存储数据,比如 Apache Parquet 。
intertubes 上有很多关于拼花地板的信息,所以我在这里就不赘述了。我更想看看这种格式作为阅读格式与 CSV 相比如何。
将数据帧写入 Parquet 非常简单。为了帮助基于时间的搜索,我按年、月、日和小时对表进行了分区。
为了测试 Parquet 对搜索性能的影响,我以 snappy 压缩 Parquet 和未压缩 CSV 格式创建了一个大型 AIS 数据存储库,并使用 Apache Drill 运行了一些查询。对于每个计时,我记录第二次运行的时间值,以便 optimiser 有机会缓存元数据。
使用 CVS 存储的数据执行大约 3.34 亿个报告的行计数需要 90 秒。对于拼花地板,计数需要 0.121 秒。查找前 100 个引用目的地的分组和排序查询对于 CVS 花费了 87 秒,对于 Parquet 花费了 4.5 秒。
对 CSV 存储数据执行的所有唯一 MMSIs 的频率计数需要 89 秒,而使用 Parquet 则需要 19.1 秒。最后,搜索单个 MMSI 对于 CSV 存储需要 82 秒,对于数据需要 6.2 秒
代码可以在这里找到。
使用人工智能的自动音乐生成
原文:https://towardsdatascience.com/automatic-music-generation-using-ai-64e3c1f0b488?source=collection_archive---------18-----------------------
意见
AI 会取代音乐人吗?
图片由作者提供,背景图片授权由作者通过 E nvato 持有
随着 2021 年的开始,我们不得不谈论一些最近经常被提起的事情。随着越来越多的人把时间花在家里,在各种项目中创作、聆听和使用音乐成为许多生活中更重要的一部分。人工智能驱动的软件在音乐生成、制作和编辑方面取得的第一次成功令人震惊,并将进一步加速这一趋势。
现在我不想说 AI 会在 2021 年完全自动化音乐行业,但创作专业品质的音乐在不久的将来肯定会变得更容易、更便宜。
使用人工智能的自动音乐生成
出于多种原因,自动创作音乐尤其困难。最大的障碍是,一首简单的 3 分钟歌曲,一群人可以很容易地记住,对计算机来说有太多的变量。
此外,训练人工智能(又名损失函数)成为音乐家的理想方式还不为人知。对美国开发者来说,目标本身也远非显而易见。我们是试图凭空创造音乐,还是基于某种形式的输入?或者我们是在尝试生成一个可以在演奏时陪伴人类音乐家的系统?
虽然我认为目前对于音乐家来说,没有理由对他们的工作前景感到恐慌。我们将关注三家试图自动生成音乐的公司,看看第一个格莱美是否会很快授予一位数据科学家。
OpenAI 的点唱机——面向未来主义者
OpenAI 是由热爱鹿、制造火箭汽车机械师埃隆·马斯克创立的公司之一。他们有几个艺术项目,最著名的是文学的 GPT-3,但作为一个音乐爱好者,Jukebox 在我心中有一个特殊的空间。
我们引入了 Jukebox,这是一个神经网络,可以生成音乐,包括基本的歌唱,作为各种流派和艺术家风格的原始音频——open ai
其基本思想是他们获取原始音频,并使用卷积神经网络(CNN)对其进行编码。可以把它想成一种把很多变量压缩成更少变量的方法。他们必须这样做,因为音频每秒有 44100 个变量,而一首歌有许多秒。然后,它们在这个较小的变量集上进行生成过程,并解压缩回 44'100 个变量。
来自 OpenAI 的简化图形
瑞克·阿斯特利风格的流行音乐——点唱机
这个例子是通过给 AI 10 秒钟的歌曲并生成剩余部分而生成的。
警告:在生成的零件启动后,至少要听 10 秒钟
虽然这首歌仍然有很多杂音,但它显然是朝着正确的方向迈出了一步。
未来方向 OpenAI,更有前途?
他们最近的发现来自于通过对 MIDI 文件进行调节来生成他们的音乐,你可以想象这就像一张给音乐家提供粗略指示的乐谱(我们将在最后解释细节)。
我觉得这种方法会取得更大的(近期)成功。目标基本上是,给定一张乐谱,为我生成 MP3 录音。
AIVA——面向创作者
AIVA 很像 OpenAI 的点唱机,一种生成音乐的方法。然而,他们的方法在生成数据的底层数据结构上有分歧。AIVA 操作所谓的 MIDI 文件。继续把 MIDI 文件想象成一张乐谱。这里的不同之处在于,上一个例子中的 OpenAI 获取了 MIDI 文件并生成了一个音频记录。但是 AIVA 创造了,给定一个 MIDI 文件,一个相似但完全新的和不同的作品。
他们的方法是我们可以上传一首 MIDI 格式的歌曲。他们会用这首歌来调节他们的生育过程。换句话说,这首歌会影响生成的歌曲。
[AIVA](https://creators.aiva.ai/) 截图
我尝试了两首歌,“永远不会放弃你”,另一首是“超级马里奥主题。”选择一首歌曲作为条件后,我们有一些选择。很遗憾,现在我们只能以一首歌为条件。
[AIVA](https://creators.aiva.ai/) 截图
我选择用一小段<0:30 seconds. I found that it worked very well on the simple “Super Mario Theme” song and rather bad for the “Never Gonna Give you up” song.
It seems to ignore the more complex song “Never Gonna Give you up,” I assume this is due to the relative complexity. Judge the results of the “Super Mario Theme” yourself.
While I generally feel that this tool can be a great starting point for new compositions and composers, heavy human assistance is still necessary to generate a proper song at this stage.
Amper Music — For Everyone
A completely different approach takes Amper Music. Instead of allowing us to control the generation process, Amper well generates the music. It does so by using so-called Descriptors.
Descriptors are musical algorithms that play a specific style of music. One descriptor might be born to play punky New York rock, and another might excel at chilled out beachside folk — Amper 音乐为每种影响创作 3 首作品
我们可以在一代人的时间里选择两件事。一个是歌曲的长度。另一个是口头描述描述符的一组(给定的)形容词。例如,我选择了一部“有趣的未来主义纪录片”,结果非常可爱,而且可能有用。之后,系统还会提示您选择一组乐器作为基础。我带着刀叉去了。
截图琥珀音乐,选择过程
结果非常好,我可以看到这是一个关于狗玩具的纪录片的伟大曲调。当重复相同的参数选择时,歌曲可能非常重复,但这是故意的。
钢琴卷帘窗——不同的方法
虽然 Ampers 解决方案可能是其他两种解决方案的混合,但我很难论证它到底是如何工作的。AIVA 和点唱机的区别主要在于数据结构(音乐存储的方式)的本质。要理解自动点唱机和 AIVA 的区别,我们首先要理解录音和 MIDI 标准的区别。在我们的例子中,MIDI 可以被理解为几个钢琴卷的集合。钢琴卷帘窗基本上是一种乐器。
钢琴卷帘窗可以说是最古老的专门数据结构之一。钢琴曲的基础创作于 1896 年。最初是为了让钢琴自动演奏而设计的,现在它们被用作音乐的画布。
钢琴曲的起源
在 X 轴上,我们有时间,在 y 轴上,有钢琴当前正在演奏的音高(可能包括几个同时演奏的音高)。
钢琴曲历史,图片来自维基百科
正如你所想象的,这种方法产生的变量比一个完整的音频波少得多。对于钢琴曲,我们有
Amount of pitches * Amount Of Voices * Amount of Quantization steps
这是一个 1 分钟的片段,有 4 个声部和 64 个音高(这是机器学习的常见选择)。大概会导致
(400)*4*64 = 102'400 possibilities
假设:1/16 量化每分钟 100 拍所有声部都是单声道,简化计算
相比之下,数字化的音频波 44’100 的采样率将持续 60 秒导致
(44'100*60)*16 = 42'336'000 possibilites
假设:44100 采样率,16 位字长,声音是单声道的
这个简化的计算应该说明,在不涉及太多细节的情况下直接处理音频波更具挑战性。事实上,额外的因素使得在音频波上的工作更加不可原谅,这在自动点唱机示例中也作为“噪声”部分出现。当以 MIDI 格式生成时,这样的噪声不可能存在。
直接在 wave 上工作的主要优势是,AI 模型也可以创建不特定于音乐的声音,例如人类的语音。理论上,他们可以通过使用音频波作为基础来达到人类歌手的录音水平。
结论
我们已经看到,计算机确实可以创作出能够通过简化的旋转测试的音乐。提出的 3 个解决方案都在人工智能音乐生态系统中占有一席之地。AIVA 的目标是希望用人工智能创作并从中获得灵感的音乐家。Amper 是一个为视频创作者和广告专家提供的解决方案,他们希望找到简单而又实用的音频用于他们的创作。
OpenAI 的点唱机是一个研究项目,旨在彻底改变音乐创作和聆听的方式。虽然它的潜力很大,但他们能在人工智能和音乐之间推进多远还有待观察。
如果你喜欢这篇文章,我会很高兴在 Twitter 或 LinkedIn 上联系你。
一定要看看我的 YouTube 频道,我每周都会在那里发布新视频。
基于开源的自动数据管道?开始救援!
原文:https://towardsdatascience.com/automatic-open-source-based-data-pipelines-openshift-to-the-rescue-b2e57d7e6e1d?source=collection_archive---------26-----------------------
斯蒂芬·道森在 Unsplash 上的照片
Kubernetes 是我们的新操作系统,没有人会怀疑这一点。为了开发一种微服务方法,并将工作负载迁移到 Kubernetes,已经做了很多工作,但是组织还是放弃了他们的数据服务。
由于新冠肺炎,我们都看到了数据的重要性,以及拥有适当的架构和数据结构的重要性。数据不会停止增长!更有甚者,它会一年又一年地打破消费记录。
这一挑战迫使我们通过将我们的数据服务转移到 Kubernetes,为我们的组织提供一个更加自动化和可扩展的解决方案,所有的奇迹都在这里发生。Kubernetes 提供的操作员将帮助您管理第 1 天和第 2 天的操作,使用健康检查、状态保存、自动驾驶等。
在这个演示中,我将向您展示如何通过Operator Hub
使用每个 Openshift 安装中提供的操作符来运行您的自动数据管道。我选择将Real-Time BI
作为一个用例,并围绕它构建这个演示。该演示利用了 Openshift 的机制,以创建可扩展的、基于 Kubernetes 的数据管道,并使用所有事实上的标准产品来满足这些要求。所有操作符都将部署在 Openshift 4 集群上,而 Openshift 容器存储将为对象和块存储协议提供底层存储解决方案。
这个演示部署了一个音乐流应用程序,它根据用户的行为生成事件(将进一步解释)。
演示架构
利用生成的数据,我们可以使用开源工具来创建我们的仪表盘和可视化,并为我们的利益相关者提供更可靠的方式来可视化重要数据。
这直接影响商业逻辑!
既然信息清楚了,那就开始玩吧!
先决条件
- 正在运行的 Ceph 集群(> RHCS4)
- 正在运行的 Openshift 4 集群(> 4.6.8)
- 外部模式下的 OCS 集群,提供对象和块存储
装置
在您的 Openshift 集群中创建一个新项目,所有资源都应该部署在这个集群中:
$ oc new-project data-engineering-demo
安装AMQ Streams
和Presto
操作符,因为我们需要它们来创建我们的相关资源。转到左侧面板上的Operator Hub
部分进行安装:
已创建项目中已安装的运算符
克隆所需的 git 存储库,以便您能够部署演示:
$ git clone [https://github.com/shonpaz123/cephdemos.git](https://github.com/shonpaz123/cephdemos.git)
将您的目录更改为 demo 目录,所有清单都位于该目录中:
$ cd cephdemos/data-engineering-pipeline-demo-ocp
数据服务准备
准备我们的 S3 环境
现在我们已经准备好了所有的先决条件,让我们开始创建我们需要的 S3 资源。因为我们使用外部 Ceph 集群,所以我们应该创建所需的 S3 用户,以便与集群进行交互。此外,我们需要创建一个 S3 桶,以便 Kafka 可以将我们的事件导出到数据湖。让我们创建这些资源:
$ cd 01-ocs-external-ceph && ./run.sh && cd ..
预期产出:
{
"user_id": "data-engineering-demo",
"display_name": "data-engineering-demo",
"email": "",
"suspended": 0,
"max_buckets": 1000,
"subusers": [],
"keys": [
{
"user": "data-engineering-demo",
"access_key": "HC8V2PT7HX8ZFS8NQ37R",
"secret_key": "Y6CENKXozDDikJHQgkbLFM38muKBnmWBsAA1DXyU"
}
.
.
.
}
make_bucket: music-chart-songs-store-changelog
该脚本使用awscli
将我们的凭证导出为环境变量,这样我们就能够正确地创建 bucket。确保您可以通过所有打开的端口访问您的端点 URL,以便该脚本可以正常工作。
部署 Kafka new-ETL
现在我们已经准备好了 S3,我们需要部署所有需要的卡夫卡资源。在本节中,我们将使用AMQ Streams
操作符部署一个 Kafka 集群,它是通过Openshift Operator Hub
提供的。此外,我们还将部署 Kafka 主题和 Kafka Connect,以便将所有现有的主题事件导出到我们的 S3 bucket。重要!确保您更改端点 URL 以适合您的,否则 Kafka Connect 将尝试公开事件,但不会成功。
运行脚本以创建这些资源:
$ cd 02-kafka && ./run.sh && cd ..
现在,让我们验证是否已成功创建所有 pod:
$ oc get pods
NAME READY STATUS RESTARTS AGE
amq-streams-cluster-operator-v1.6.2-5b688f757-vhqcq 1/1 Running 0 7h35m
my-cluster-entity-operator-5dfbdc56bd-75bxj 3/3 Running 0 92s
my-cluster-kafka-0 1/1 Running 0 2m10s
my-cluster-kafka-1 1/1 Running 0 2m10s
my-cluster-kafka-2 1/1 Running 0 2m9s
my-cluster-zookeeper-0 1/1 Running 0 2m42s
my-connect-cluster-connect-7bdc77f479-vwdbs 1/1 Running 0 71s
presto-operator-dbbc6b78f-m6p6l 1/1 Running 0 7h30m
我们看到所有的 pod 都处于运行状态并通过了它们的探测,所以让我们验证一下我们是否有需要的主题:
$ oc get kt
NAME CLUSTER PARTITIONS REPLICATION FACTOR
connect-cluster-configs my-cluster 1 3
connect-cluster-offsets my-cluster 25 3
connect-cluster-status my-cluster 5 3
consumer-offsets---84e7a678d08f4bd226872e5cdd4eb527fadc1c6a my-cluster 50 3
music-chart-songs-store-changelog my-cluster 1 1
played-songs my-cluster 12 3
songs my-cluster 12 3
我们的流应用程序将使用这些主题来接收、转换这些事件,并以适当的格式将其导出到我们的 S3 存储桶中。最后,topic music-chart-songs-store-changelog
将通过其最终结构保存所有信息,以便我们能够查询它。
为分布式查询运行 Presto
在这个演示中,我们将使用 Presto 查询 S3 存储桶前缀的能力(类似于关系数据库中的表)。Presto 需要创建一个模式,以便了解它需要查询的文件结构,在我们的示例中,所有导出到 S3 存储桶的事件如下所示:
{"count":7,"songName":"The Good The Bad And The Ugly"}
每个文件都将导出一个 JSON 结构,其中包含两个键值对。为了强调,你可以把它想象成一个表,有两列,第一列是count
,第二列是songName
,所有被写入桶的文件都是这个结构的行。
现在我们对数据结构有了更好的理解,我们可以部署我们的 Presto 集群了。这个集群将创建一个 hive 实例来存储模式元数据(用 Postgres 来存储模式信息),以及一个包含协调器和工作单元的 Presto 集群。所有这些资源都将由 Presto Operator 自动创建,它也是 Openshift Operator Hub 的一部分。
让我们运行脚本来创建这些资源:
$ cd 04-presto && ./run.sh && cd ..
现在,让我们验证是否已成功创建所有 pod:
$ oc get pods | egrep -e "presto|postgres"
NAME READY STATUS RESTARTS AGE
hive-metastore-presto-cluster-576b7bb848-7btlw 1/1 Running 0 15s
postgres-68d5445b7c-g9qkj 1/1 Running 0 77s
presto-coordinator-presto-cluster-8f6cfd6dd-g9p4l 1/2 Running 0 15s
presto-operator-dbbc6b78f-m6p6l 1/1 Running 0 7h33m
presto-worker-presto-cluster-5b87f7c988-cg9m6 1/1 Running 0 15s
用超集可视化实时数据
超集是一个可视化工具,它可以呈现来自许多 JDBC 资源的可视化和仪表板,如 Presto、Postgres 等。由于 Presto 没有真正的用户界面,让我们能够探索我们的数据,控制权限和 RBAC,我们将使用超集。
运行脚本以便在集群中部署超集:
$ cd 05-superset && ./run.sh && cd ..
现在,验证是否已成功创建所有单元:
$ oc get pods | grep superset
superset-1-deploy 0/1 Completed 0 72s
superset-1-g65xr 1/1 Running 0 67s
superset-db-init-6q75s 0/1 Completed 0 71s
不错!一切顺利!
数据逻辑准备
准备好所有基础设施服务后,我们需要创建流应用程序背后的数据逻辑。当 Presto 从我们的 S3 桶中查询数据时,我们需要创建一个模式,这将允许 Presto 知道它应该如何查询我们的数据,以便作为一个表来提供结构知识。
登录到您的Presto Coordinator
节点:
$ oc rsh $(oc get pods | grep coordinator | grep Running | awk '{print $1}')
更改上下文以使用配置单元目录:
$ presto-cli --catalog hive
创建一个模式,告诉 Presto 使用s3a
连接器从我们的 S3 存储桶前缀查询数据:
$ CREATE SCHEMA hive.songs WITH (location='s3a://music-chart-songs-store-changelog/music-chart-songs-store-changelog.json/');
更改模式上下文,并创建一个表:
$ USE hive.songs;
$ CREATE TABLE songs (count int, songName varchar) WITH (format = 'json', external_location = 's3a://music-chart-songs-store-changelog/music-chart-songs-store-changelog.json/');
注意了!正如我们在上一节中所看到的,创建表提供了每个文件结构的实际知识。现在让我们尝试查询我们的 S3 存储桶:
$ select * from songs;
count | songname
-------+----------
(0 rows)Query 20210203_162730_00005_7hsqi, FINISHED, 1 node
Splits: 17 total, 17 done (100.00%)
1.01 [0 rows, 0B] [0 rows/s, 0B/s]
我们没有数据,也没关系!我们还没有开始传输任何数据,但是我们看到没有错误,这意味着 Presto 可以访问我们的 S3 服务。
流式实时事件
既然所有资源都已准备就绪,我们终于可以部署我们的流应用程序了!我们的流媒体应用程序实际上是一个模拟媒体播放器的 Kafka producer,它有一个由我们的媒体播放器随机“播放”的预定义歌曲列表。每当用户播放一首歌曲,事件就被发送到一个 Kafka 主题。
然后,我们使用 Kafka 流,以便将数据转换成我们想要的结构。Streams 将获取发送到 Kafka 的每个事件,对其进行转换,并将其写入另一个主题,在那里它将自动导出到我们的 S3 桶中。
让我们运行部署:
$ cd 03-music-chart-app && ./run.sh && cd ..
让我们验证所有 pod 都在运行,player-app
pod 是我们的媒体播放器,而music-chart
pod 实际上是包含所有 Kafka 流逻辑的 pod:
$ oc get pods | egrep -e "player|music"
music-chart-576857c7f8-7l65x 1/1 Running 0 18s
player-app-79fb9cd54f-bhtl5 1/1 Running 0 19s
让我们来看看player-app
日志:
$ oc logs player-app-79fb9cd54f-bhtl52021-02-03 16:28:41,970 INFO [org.acm.PlaySongsGenerator] (RxComputationThreadPool-1) song 1: The Good The Bad And The Ugly played.
2021-02-03 16:28:46,970 INFO [org.acm.PlaySongsGenerator] (RxComputationThreadPool-1) song 1: The Good The Bad And The Ugly played.
2021-02-03 16:28:51,970 INFO [org.acm.PlaySongsGenerator] (RxComputationThreadPool-1) song 2: Believe played.
2021-02-03 16:28:56,970 INFO [org.acm.PlaySongsGenerator] (RxComputationThreadPool-1) song 3: Still Loving You played.
2021-02-03 16:29:01,972 INFO [org.acm.PlaySongsGenerator] (RxComputationThreadPool-1) song 2: Believe played.
2021-02-03 16:29:06,970 INFO [org.acm.PlaySongsGenerator] (RxComputationThreadPool-1) song 7: Fox On The Run played.
我们看到,我们的数据是随机写入的,每次播放一首歌曲时,都会有一个事件被发送到我们的 Kafka 主题。现在,让我们来看看我们的music-chart
日志:
$ oc logs music-chart-576857c7f8-7l65x [KTABLE-TOSTREAM-0000000006]: 2, PlayedSong [count=1, songName=Believe]
[KTABLE-TOSTREAM-0000000006]: 8, PlayedSong [count=1, songName=Perfect]
[KTABLE-TOSTREAM-0000000006]: 3, PlayedSong [count=1, songName=Still Loving You]
[KTABLE-TOSTREAM-0000000006]: 1, PlayedSong [count=1, songName=The Good The Bad And The Ugly]
[KTABLE-TOSTREAM-0000000006]: 6, PlayedSong [count=1, songName=Into The Unknown]
[KTABLE-TOSTREAM-0000000006]: 3, PlayedSong [count=2, songName=Still Loving You]
[KTABLE-TOSTREAM-0000000006]: 5, PlayedSong [count=1, songName=Sometimes]
[KTABLE-TOSTREAM-0000000006]: 2, PlayedSong [count=2, songName=Believe]
[KTABLE-TOSTREAM-0000000006]: 1, PlayedSong [count=2, songName=The Good The Bad And The Ugly]
我们看到数据正在成功转换,并且随着用户播放更多的歌曲,计数会增加。
现在,我们需要确保我们的管道工作,所以让我们去我们的 S3 服务,以验证所有事件都被成功导出。出于这个目的,我使用了 Sree 作为 S3 浏览器。确保您使用正确的凭据和端点 URL:
我们创建的桶前缀的 S3 浏览器
让我们回到我们的 Presto coordinator pod,再次尝试查询我们的数据:
$ presto> presto-cli --catalog hive
$ presto:songs> USE hive.songs;
运行 SQL 查询以获取我们的数据:
$ select * from songs;
count | songname
-------+-------------------------------
1 | Bohemian Rhapsody
4 | Still Loving You
1 | The Good The Bad And The Ugly
3 | Believe
1 | Perfect
1 | Sometimes
2 | The Good The Bad And The Ugly
2 | Bohemian Rhapsody
3 | Still Loving You
4 | Sometimes
2 | Into The Unknown
4 | Believe
4 | Into The Unknown
2 | Sometimes
5 | Still Loving You
3 | The Good The Bad And The Ugly
太神奇了!我们看到我们的数据正在自动更新!试着多运行几次这个命令,您会看到行数增加了。现在,为了开始可视化我们的数据,寻找超集路径,在这里您将能够登录到控制台:
$ oc get routeNAME HOST/PORT PATH SERVICES PORT TERMINATION WILDCARD
superset superset-data-engineering-demo.apps.ocp.spaz.local superset 8088-tcp None
当我们到达我们的超集控制台(使用admin:admin
登录)时,我们可以看到我们可以转到Manage Databases
->-Create Database
来创建我们的普雷托连接,确保您输入了 Presto 的 ClusterIP 服务名称,最后确保您测试了您的连接:
创建数据库时测试 Presto 的连接
既然我们可以有一个更方便的方法来查询我们的数据,让我们尝试探索一下我们的数据。去SQL Lab
,看看你能不能执行我们之前的查询。为了强调,请看下面的查询,它将显示每首歌曲被播放了多少次:
创建可视化查询
很好!我们可以查询数据!随意创建你想要的可视化和仪表板。例如,我创建了一个实时变化的控制面板,每次刷新控制面板都会再次查询 Presto 中的所有数据:
实时数据仪表板
结论
在这个演示中,我们看到了如何利用开源产品来运行自动数据管道,所有这些都安排在 Openshift 上。随着 Kubernetes 打破采用记录,组织应该考虑将他们的工作负载转移到 Kubernetes,这样他们的数据服务就不会落后。利用 Red Hat 和合作伙伴运营商,Openshift 为您的数据服务提供第 1 天和第 2 天的管理。
感谢你阅读这篇博文,下次见:)
自动平行泊车:路径规划、路径跟踪和控制
原文:https://towardsdatascience.com/automatic-parallel-parking-system-including-path-planning-path-tracking-and-parallel-parking-in-a-ece780b2e8e0?source=collection_archive---------18-----------------------
使用 A *算法、B 样条插值、车辆运动学和 MPC 控制器在 2D 环境中实现自动停车系统的 Python。
作者图片
本文包含虚拟环境中自动平行泊车系统的 python 实现,包括路径规划、路径跟踪和平行泊车。代理在环境中导航其路线,并被 MPC 控制器指引到指定的停车位置。你可以在这里找到完整的项目。
环境
开发自动停车场系统的第一步是设计和开发一个能够使用OpenCV
库进行可视化渲染的环境。环境作为一个类在environment.py
中实现,并在开始env = Environment(obs)
时接收障碍。可以使用env.render(x,y,angle)
放置代理。
下面显示了一个环境示例。你可以从 1 号到 24 号选择停车位。
作者图片
路径规划
A*算法
代理将使用找到从起点到目标的路径。这个来自 PythonRobotics 的 A实现考虑了障碍物和机器人半径等参数。
用 B 样条插值路径
在离散的 100100 空间中找到路径后,使用 b 样条将路径平滑并缩放到环境的 10001000 空间。结果是一组点来指导我们的代理!
路径跟踪
小车的运动学模型为:
x' = v . cos(ψ)
y' = v . sin(ψ)
v' = a
ψ' = v . tan(δ)/L
a:加速度,δ:转向角,ψ:偏航角,L:轴距,x: x 位置,y: y 位置,v:速度
状态向量为:
z=[x,y,v,ψ]
x: x 位置,y: y 位置,v:速度,ψ:偏航角
输入向量为:
u=[a,δ]
a:加速度,δ:转向角
控制
MPC 控制器基于模型控制车辆速度和转向,并引导车辆通过路径。MPC 有一个使用线性化模型的选项。在这种情况下,MPC 将工作点周围的运动学模型线性化,然后进行优化。
自动停车
这部分包括 4 条规则,代理人必须根据停车位置进行选择。这里我们来看看其中的一个。路径设计的规格如下图所示。
作者图片
首先,代理将找到一条路径来停放车辆,然后计算到达角度。基于到达角度,代理选择 2 个坐标作为确保 1 (x0,y0)和确保 2 (x1,y1)点。这是起点和终点。
作者图片
此后,使用如下所述的 2 个圆方程来规划从确保 1 (x0,y0)到确保 2 (x1,y1)的停车路径。2 条直线也被添加到路径上,以提供一个漂亮的停车路线。
作者图片
MPC 通过 ensure2 坐标中的路径和停车场控制代理。
结论
您可以从 G ithub 下载整个项目,并使用以下命令运行代码:
$ python main_autopark.py --x_start 0 --y_start 90 --psi_start 0 --parking 7
可以看出,汽车由 MPC 控制器引导,沿着它的路径行驶,直到它到达环境的停车点。最后,该车与其他车辆平行并停在指定位置。
作者图片
熊猫队 在 2020-2021 年全国自动驾驶汽车拉尼山竞赛中获得第一名。
阿米尔侯赛因·海达里安,艾达·穆罕默德·沙希,米拉德·索尔塔尼,阿巴斯·奥米迪,阿米尔侯赛因·卡泽罗尼
利用 1D RegNet 和 AdaCos 的深度度量学习进行自动光谱识别
原文:https://towardsdatascience.com/automatic-spectral-identification-using-deep-metric-learning-with-1d-regnet-and-adacos-8b7fb36f2d5f?source=collection_archive---------14-----------------------
引入强大的深度度量学习,实现更加精确和稳定的自动光谱分析,从数据库中识别物质
国家癌症研究所在 Unsplash 上拍摄的照片
背景和动机
像《犯罪现场调查》、《法律与秩序》和《法医档案》这样的电视节目向大众观众介绍了法医学,并生动地展示了科学证据对破案的重要性。留在现场的一小块碎片可以推翻凶手的不在场证明,从而指认凶手。基于光谱分析的物质鉴定在法医学中起着至关重要的作用。同样,材料识别过程对于制造部门和材料研究中的故障推理至关重要。
光谱,如无机材料的 X 射线衍射(XRD)和有机材料的傅里叶变换红外光谱(FT-IR ),是鉴定成分的典型方法。独特的光谱特征,即所谓的“光谱指纹”,使我们能够通过将测得的光谱与数据库中的光谱进行比较来识别材料。识别准确度大致基于光谱数据库的搜索引擎算法以及从经过仔细检索的样品中获得的无噪声光谱数据的程度。然而,样品量不足或其他物质的污染可能会使光谱数据变得嘈杂,难以识别。具体来说,大多数数据库搜索算法利用输入光谱的峰值位置。然而,峰移通常发生在小样本的情况下,导致可识别性差。没有人类专家的帮助,搜索引擎结果不会成为值得信赖的分析。更鲁棒的识别算法可以使搜索结果本身成为更可靠的分析结果。因此,深度学习,一种更准确的识别机器学习模型,可能会使法医分析过程自动化。
下面会解释这段代码,GitHub 上也有!
机器学习策略
但是,我们如何利用深度学习来解决这个嘈杂的样本识别问题呢?我脑海中立即浮现的想法是卷积神经网络,表示为 CNN,这是一个非常成功的用于对象识别的深度学习分类器。但是等等,这里有与平常图像分类任务的四个不同点。
1.输入光谱不是 2D 张量,而是一维,不像图像。
2。任务的目标是不是分类而是识别。也就是要识别的类数超过一万,像人脸识别任务。
3。与图像噪声类型不同,独特噪声包含在原始光谱中。
4。光谱数据库由每种材料的单一光谱组成,没有任何变化或噪音样品。
让我们来研究一下每个问题。数字对应每个问题。
1.1D 有线电视新闻网
首先,维度的差异对迁移学习有影响。在图像分类任务中,我们可以使用 GitHub 上发布的预训练模型,使我们能够减少我们应该准备的数据数量。幸运的是,GitHub 上有几个 1D-CNN 模型,但没有针对 spectra 的预训练模型。在我尝试的这些模型中,1D-雷格内特效果最好。RegNet 是由脸书研究人员创建的源于神经架构搜索(NAS)的最先进的 CNN 模型(论文)。RegNet 的原始版本仅用于 2D 图像。但是,多亏了佐治亚理工学院的研究人员,1D 版的 RegNet 可以在 GitHub 上找到。资源库的链接在这里:
https://github.com/hsd1503/resnet1d
2.深度度量学习
其次,我们应该把这个光谱识别问题看作少拍度量学习,人脸识别也是如此。一般来说,分类任务需要每个类别超过 100 个样本。在我们的设置中,每个类的可用光谱是 1 或 2,这意味着少量的学习。其次,分类任务一般对待 100 类以下;否则,精度会降低。超过 5000 个类,我们通常会将问题从学习区分每个类的标准转换为学习衡量样本相似性的评估度量。这就是所谓的度量学习。这在人脸识别上非常有效,更好的是,我们所要做的度量学习就是替换损失函数。 CosFace 、 ArcFace 是使用 CNN 进行深度度量学习的开创性损失函数。如今,这些损失函数发展到了 AdaCos ,自动识别 CosFace 的超参数,无需额外的调谐程序就能很好地工作。AdaCos 实现可在此处获得:
https://github . com/4 uiiurz 1/py torch-AdaCos/blob/master/metrics . py
3.贝叶斯去噪预处理
第三,要考虑光谱中独特噪声的去噪过程。频谱中的噪声类型可以大致分为两类:白噪声和背景噪声。背景噪音来自样品架、样品板或不充分结晶样品的信号。在珠出现之前,移除一直由人工完成。由于贝叶斯稀疏分析的能力,我们可以用很少的超参数自动对这两种噪声类型进行去噪。资源库在这里:
https://github.com/skotaro/pybeads
4.基于物理学的数据增强
即使我们考虑少量的学习设置,每个类 1 或 2 个训练数据也是不够的。这是因为相同的材料有几种不同的光谱。变量及其原因如下:
1.峰值缩放;由于粉末样品中晶体取向的排列差异,导致峰值强度偏离数据库中的标准光谱
2。巅峰淘汰;由于实验仪器设置
3,从数据库中的标准光谱中删除一些峰。模式转换;由于样品中的应变或实验条件,当模式从数据库中的标准光谱向下或向上移动时。
4。峰值分裂;由于晶体结构紊乱,数据库中标准光谱出现新峰。
因此,1 或 2 个数据无法将这些光谱变化告诉深度学习模型。因此,我们应该应用数据扩充。感谢麻省理工学院的研究人员,这里提供了 1-3 的数据增强代码:
https://github.com/PV-Lab/autoXRD
关于峰分裂,我们可以使用 pymatgen 库来创建无序晶体结构及其 X 射线衍射光谱。
问题设置
让我们设置一个具体的问题来理解上面的策略。假设我们想鉴定未知的结晶粉末样本。我们可以测量 X 射线衍射(XRD)作为指纹图谱。我们只知道这个样本中一定含有锂。
可通过晶体学开放数据库(COD)访问 XRD 光谱数据库,使用 pymatgen 将晶体信息文件(CIF)转换为 XRD 光谱。根据化学需氧量,迄今为止报告的锂化合物有 8172 种。检查 8172 个与目标样本相似的光谱对人类来说是不可行的,因此我们考虑将候选范围缩小到 5 个。最有可能的候选人的识别准确率不重要,但是指定的 5 个候选人必须包含真实材料。假设准确率应该在 95%以上。因此,我们可以将这个问题公式化如下:
使用光谱识别技术,我们如何从 8,172 个候选样本中识别出未知样本,并达到 95%以上的前 5 名准确度?
代码
Python 库要求:
- pymatgen
- pytorch
- sci kit-学习
环境;Python 3.7.3,Pytorch 1.4.0,
数据集构建
从 COD 下载 CIF
我们将使用 COD 来构建数据集。首先点击左侧表格中的访问 COD 数据>搜索页面。之后,在“ 1 至 8 元素搜索框中输入“李”,然后点击发送。跳转到搜索结果页面后,您将看到文本“结果:选择中有 8172 个条目”。点击“CIF 网址列表,即可下载“ COD-selection.txt ”。这样,您可以获得 8,172 个 cif URLs 的列表。
接下来,下面的 python 代码将从 COD 中集体下载所有的 cif 文件。
将 CIF 转换为 XRD 光谱
第一步,您需要检查 pymatgen 是否能够读取 cif 文件。不幸的是,有些 CIF 文件不能被 pymatgen 读取。下面的 read_CIF 模块可以将 CIF 解释为 pymatgen 可读的结构数据,保存为任意名称的 pickle 文件。
接下来,我们可以使用下面的 XRDspectra 模块将 pymatgen 结构数据转换为 XRD 光谱。
因此,在按顺序运行上述代码后,我们获得一个名为 XRD_epoch5.pkl 的 XRD 光谱数据库。LiTaO3 等晶体名称被转换成数字 int 标签。在 material_labels.csv 中总结了数字标签和人类可理解的晶体名称之间的对应关系。
深度度量学习模型(1D-RegNet + AdaCos)
首先,从这个库下载 net1d.py 。然后,执行以下代码来训练深度度量学习模型。
因此,您可以使用下面的代码可视化学习曲线( learning_curve.csv )。
作者创建的学习曲线
我们可以看到,在第 100 个历元时,验证前 5 名的准确度达到了 97.3 ,这意味着我们的目标已经达到。测试准确度是相同的(97.3),因此与验证数据集的过度拟合无关。
这个代码在 GitHub 也有,链接这里。玩吧,就像你是法医一样!
如果你喜欢这篇文章,请在 Medium、GitHub 和 Twitter 上关注我!
推特:https://twitter.com/masaki_adachi
GitHub:https://github.com/ma921
自动语音识别:分解语音成分
原文:https://towardsdatascience.com/automatic-speech-recognition-breaking-down-components-of-speech-85d065061517?source=collection_archive---------26-----------------------
思想和理论
理解语音的基本单位以训练声学模型
由杰森·罗斯韦尔在 Unsplash 上拍摄的照片
目录
- 概述
- ASR 中的困难 : 噪音、口齿不清、语言含糊不清、缺乏上下文
- 语音的物理属性 : 音素、字素
- 信号分析 : 音频信号、声音分量、傅立叶变换
- 光谱图 : 快速傅立叶变换算法
- 梅尔频率倒谱系数 : 梅尔标度、频率分析、倒谱分析、源-滤波器模型
概观
自动语音识别(ASR)是将语音或音频波转换成单词的文本表示。一般是在苹果 Siri 、亚马逊 Alexa 等[语音用户界面](http://Voice User Interfaces) (VUIs)的第一步。
这种语言的许多特性使得它很难准确地执行 ASR。其中一些是噪音、雄辩、模糊的单词边界和缺乏上下文。这些困难在随后的章节中有更详细的描述。
语音识别管道
让我们简单地看一下通过 ASR 管道的转换过程。
作者图片
特征提取
在将语音或原始音频提供给模型之前,需要通过特征提取将其转换为模型可以理解的适当形式。这些表示由光谱图或 MFCCs 组成。
声学模型
在特征被提取之后,这些向量被传递给声学模型。声学模型试图将音频信号映射到语音的基本单元,例如音素或字素。这些模型的实现包括 hmm 和神经网络。这些语言单位将在下一节详细阐述。
语言模型
让我们假设声学模型正确地将音频映射到单词。有些词可能听起来一样(谐音:海 vs 见)或者听起来很像(单 vs 海),但意思完全不同。语言模型允许算法学习句子或单词的上下文或含义。一个流行的打破记录的语言模型叫做 BERT 。
本文将包含管道中的第一步,即将原始音频的组件分解为声学模型可以学习的特征表示。
ASR 中的困难
由于原始音频本身的各种因素、个体发音的独特性、模糊的单词边界以及缺乏上下文,自动语音识别是困难的。让我们来看看这些挑战。
噪音
噪声是指模糊或不包含有意义的数据或其他信息的随机波动。识别器应该能够从无用噪声区域中分离出音频信号区域。
- 这些声音包括背景对话、麦克风静电噪声、飞过的飞机、狗叫声等等。
演讲
口才是指一个人发音和发音的方式。不同的人有不同的发音,如音高的可变性、音量的可变性和语速的可变性,因此很难解释这些差异。
- 例如,视觉上和听觉上,我们可以看到和听到' speed '和'speeechch'是以不同的速度说的。很可能音高和音量也不同。这些差异需要对齐和匹配。
模糊的单词边界
与书面语言不同,语音没有清晰明确的单词边界。书面文本在单词之间有空格、逗号和其他形式的分隔。在演讲中,单词似乎一个接一个地重叠在一起。
- ”字的界限在哪里?vs .wherethewordlines
缺乏上下文
一般来说,对话之所以流畅,是因为人们能够通过我们固有的上下文识别器来填补空白。没有上下文,很难区分两个完全不同但听起来很像的句子。
- 你能识别语音吗?你能毁掉一个美丽的海滩吗?”
言语的物理属性
虽然语音识别存在困难,但语音的物理属性有助于语音识别。例如,我们可以将语音分解成基本单元,如字素和音素。
音素
音素是语言中不同的声音,用斜线表示,即/ah/。换句话说,它们是声音的最小单位。美国英语大约有 40 个音素,英国英语有 44 个音素。例如,我们可以把 SPEECH 分解成 S . P . IY CH。
字形
字素是语言中独特的字符,用尖括号表示,即。它们是书写系统的最小单位。在英语中,有 250 个字素,但最小的字素是一组字母(A-Z)加上一个空格字符。
为什么不能只映射音素→字素或者反之?
音素→字素或字素→音素之间不存在一对一的映射。多个音素映射到同一个字素,多个字素映射到同一个音素。
字母 c 根据单词映射成不同的音。
- 即
→ /K/表示猫, → /CH/表示聊天, → /S/表示仪式。
或者,诸如单词“SPEECH”中的“IY”音可以用不同的拼法形成。
- 即/IY/ →
表示接收,/IY/ → 表示相信,/IY/ → 表示讲话。
这些怎么有用?
虽然音素不能直接映射到字素,但它们是语音处理的一个有用的中间步骤。这一步叫做。如果我们可以成功地将声学模型的输出解码为音素,那么我们可以在后处理步骤中使用 词典 (词典映射)将这些音素映射到它们的单词,以形成单词和句子。
此外,这个后处理步骤允许我们通过映射到一组常量值来降低复杂性。对于高维度问题,具有大量词汇的问题,音素可以用于显著减少单词之间的比较次数。但是,如果问题的词汇量很小,可以选择使用声学模型直接映射到单词,跳过这个中间步骤。
如果你想把音素合并到你的后处理步骤中,看看 ARPHABET 。这是一个众所周知的音素集,是为语音研究而创建的。
信号分析
语音由声波组成,声波是在空气中传播的正弦振动。麦克风等音频输入设备从这些声波中捕获声能,并将其记录为音频信号。更多关于声音。
作者图片
以下是波属性的一些基本定义:
振幅
- 声波中的声能有多大,声音就有多大。
- 较大的声音振幅较高,而较小的声音振幅较小
频率
- 波重复自身的次数,以赫兹(Hz)或每秒周期数来度量
- 高频声音如汽笛的波长较短,而低频声音如低音的波长较长
现在,让我们来看一段录音。
作者图片
请注意,这个波形看起来不像之前显示的余弦或正弦函数。这是由于声音的复杂性。声波由多个重叠的波组成,当 通过相长干涉叠加 (加在一起)时振幅增加,通过相消干涉振幅减小(抵消)。
作者图片
通过观察两个波,我们已经可以看到当波 1 和波 2 叠加时,一个更复杂和更嘈杂的波开始形成。从本质上讲,声波是由许多重叠的声波组成的,因此可以分解成单独的、更小的波成分。换句话说,对于 2 个波,合成波=波 1 +波 2。
傅里叶分析
傅立叶分析是将数学函数分解成更简单的三角函数的研究。由于声音由振荡振动组成,我们可以使用傅立叶分析和傅立叶变换将音频信号分解为不同频率的正弦函数分量。
傅里叶变换
傅立叶变换是一种数学变换,它将基于时间的模式分解成其组成部分。
这里有一个简单的英语比喻:
傅立叶变换有什么作用?给它一杯奶昔,它就能找到配方。
如何?将思慕雪过滤,提取每种成分。
为什么?食谱比奶昔本身更容易分析、比较和修改。
我们怎么把奶昔拿回来?将配料混合。— 来源
使用傅立叶变换,我们可以将复杂的声波分解为更简单的成分,并在尝试将音频转录为文本或执行其他目标之前,将各个成分处理为有用的特征。
傅立叶变换是从语音中提取特征并转换成我们的模型可以使用的有意义形式的有用工具。我们可以使用快速傅立叶变换(FFT)算法,通过将声波分成 声谱图 来生成声波的频率表示。然后可以将频谱图提供给一个模型来直接预测,或者我们可以在预测阶段之前进一步从中提取特征。
光谱图
频谱图是波在时间上的频域表示。我们将在下面看看这是什么意思。
Nasa 着陆器记录的振动频谱图
垂直轴代表频率或波在时间 t 移动的速度,在水平轴中定义。颜色表示信号的幅度。我们能够相对于时间将声谱图输出与原始音频信号对齐。
- 这里的是解释频谱图中的声音如何被解读的资源。
使用一种称为快速傅立叶变换 (FFT)算法的算法,我们可以以波的形式获取音频,将它们分解为更小的分量,并在声谱图中的每个时间间隔 t 可视化这些分量。
- 将信号分成时间帧
- 用 FFT 将每一帧分解成频率分量
- 每个时间帧现在被表示为每个频率的振幅向量
SciPy 允许您使用以下 import 语句轻松实现 FFT:
*from spicy.fftpack import fft*
关于 SciPy FFT 函数的更多信息
问题
虽然频谱图给出了声音数据的完整表示,但它仍然包含噪声和其他可变性(如上所述),这些可变性可能会使数据变得模糊,并且超出我们实际需要的量。识别和隔离音频信号中真正具有预测能力的部分至关重要。
梅尔频率倒谱系数
频谱图允许我们将原始音频映射成频率的表示。然而,我们需要一种方法来进一步过滤噪声音频信号。请注意,听觉语言受到我们的嘴(发出声音)和耳朵(捕捉声音)的限制。
这就是梅尔频率倒谱系数(MFCCs)的用武之地。梅尔频率倒谱系数从梅尔频率分析和倒谱分析中提取。
梅尔频率分析
首先,让我们定义一个音高的相对音阶。
梅尔标度
梅尔音阶(在一词之后旋律)【1】是被听者判断为彼此距离相等的音高的感知音阶。
Mel 标度是从音高感知的研究中发展出来的,它允许我们测量音高之间的距离。它告诉我们人们真正能辨别的音高。
- 例如,音高 100 Hz 和 200 Hz 可能被感知为比音高 1000 Hz 和 1100 Hz 听起来更远,即使这两对音高相差 100 Hz。这个结果可能是因为人们可以更好地区分低频的音高。
降维
因为不能辨别每一个频率,所以可以通过只保留实际上可以听到的频率来过滤声音。过滤掉人类听众范围之外的频率可以去除不相关的信息,同时保留预测信号。
此外,如果我们不能区分两个不同的频率,那么这些频率可以被标记为相同的频率。注意光谱图是连续的。通过转换到宁滨频率的离散标度,频率的总数将减少。
Mel 频率分析允许通过过滤噪声和离散化频率来整体降低数据维度。
倒谱分析
即使我们的解剖结构相同,人的声音也因人而异。人类产生声音是由“源”和“过滤器”结合而成的。我们将在下面看到这意味着什么。
源-过滤器模型
源-滤波器模型区分说话者无关和说话者相关的语音源。
作者图片
红色显示的声源代表每个人独有的发声部位,如声带或声带。蓝色显示的过滤器由声道组成,它影响所有人说话时使用的词语的清晰度,如鼻腔或口腔。目标是关注单词的发音(声带),忽略与说话无关的部分(声道)。
倒谱分析允许我们分离源和过滤器。主要是它让我们可以放下声源,保持过滤器发出的声音的形状。源和滤波器激发了倒谱分析背后的思想。本质上,信号源与滤波器相乘形成信号,然后通过 FFT 等将信号转换到频域。
如果你想了解这个理论,请看下面的内容:
语音理论的倒谱分析
结合特征
Mel 频率分析和倒谱分析产生大约 12 个 MCFF 特征。此外,MFCC 德尔塔(频率的变化)或 MFCC 德尔塔-德尔塔(频率变化的变化)可能是自动语音识别的有用特征。这些附加功能可以使 MFCC 功能的总数增加一倍或三倍。它们也显示出在 ASR 中给出更好的结果。
关于 MFCC 实施和 MFCC 三角洲的教程
主要的好处是 MCFF 的特性导致频率数量大大减少。与声谱图不同,MCFFs 可以过滤噪声,并专注于具有更强预测能力的信号部分。
结论
总之,自动语音识别带来了许多挑战,但通过理解语音的基本组成部分,我们可以简化问题。原始音频波可以被转换成特征表示,然后使用声波的知识和声音的物理人类约束的领域知识来进一步简化。这些技术可以产生更清晰、更强的信号,帮助我们更有效地训练声学模型。
从 Google 电子表格自动更新 Django 模型
原文:https://towardsdatascience.com/automatic-update-of-django-models-from-a-google-spreadsheet-7c6d4f30e3ca?source=collection_archive---------18-----------------------
数据输入
关于如何直接从 Google 电子表格创建和更新 Django 模型的现成 Python 教程
作者图片
通常,数据模型定义和数据模型实现是由不同的人执行的,数据模型定义中的一点点变化都应该尽快转换成实现的模型。
模型变化转化为实现的速度取决于定义和实现之间的关系。
在本教程中,我提出了一种机制,将模型中的变化直接转化为实现中的变化。我利用以下工具:
- 数据模型定义的谷歌电子表格
- Python 将电子表格中的更改转化为 Django 的更改
- Django 在 Web 界面中呈现模型。
通过 Google 电子表格自动更新 Django 中的数据模型需要三个步骤:
- 谷歌电子表格中的数据模型定义
- 模型转换从 Google 电子表格到 Django 模型
- Django 的车型更新
1 数据模型定义
首先,我定义了一个基本的数据模型。例如,我可以考虑三个表:
Person(**id**,name,surname,birthDate,sex)
Organization(**id**,name,address,website,locality)
Staff(person_id,organization_id)
然后,我创建了一个新的 Google 电子表格,并为每个表格分配了一个工作表,如本例所示。对于每个表,我定义了以下列:
- 属性— 表格的属性列表
- 描述 —属性代表什么
- 数据类型 —属性数据类型
- 最大长度 —字符型变量的最大长度。它仅对字符属性有效
- 关键字 —指定属性是否为关键字(主关键字或外键)
- 外键表 —如果属性是外键,指定相关的表
下图显示了 Person 表的构建表:
作者图片
数据模型可由模型设计者动态更新,无需考虑任何实现。他们甚至可以通过添加或删除属性,向电子表格中添加其他表格或修改现有表格。
模型设计者尊重表格的结构就足够了。
2 模型到 Django 模型的转换
下一步包括从 Google 电子表格到 Django 的模型转换。这可以通过用 Google 电子表格的内容动态构建 Django 模型来实现。实际上,我可以编写一个 Python 代码,根据 Google 电子表格动态生成 Django **model.py**
脚本。
模型转换可以通过三个步骤实现:
- 阅读谷歌电子表格
- 创建表和 Django 模型类之间的映射
- 创建
model.py
脚本的内容
2.1 阅读谷歌电子表格
在我之前的文章中,我描述了如何用 Python 加载 Google 文档的内容。关于 Google 电子表格,认证的过程非常相似,不同之处在于 Google 电子表格 API 应该在 Google 控制台中启用,而不是在 Google 文档 API 中启用。
为了完整起见,我在这里报告了用于身份验证的 Python 代码:
from __future__ import print_function
import os.path
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials# If modifying these scopes, delete the file token.json.
SCOPES = ['[https://www.googleapis.com/auth/spreadsheets.readonly'](https://www.googleapis.com/auth/spreadsheets.readonly')]# The ID and range of a sample spreadsheet.
SPREADSHEET_ID = 'YOUR DOCUMENT ID' creds = None
# The file token.json stores the user's access and refresh tokens, and is created automatically when the authorization flow completes #for the first time.
if os.path.exists('token.json'):
creds = Credentials.from_authorized_user_file('token.json', SCOPES)
# If there are no (valid) credentials available, let the user log in.
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
'credentials.json', SCOPES)
creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open('token.json', 'w') as token:
token.write(creds.to_json())
认证后,我可以加载 Google 电子表格的内容:
service = build('sheets', 'v4', credentials=creds)
sheet = service.spreadsheets()
sheet_metadata = service.spreadsheets().get(spreadsheetId=SPREADSHEET_ID).execute()
并把它转换成熊猫字典的数据框架。实际上,字典中的每一项都是 Google 电子表格的一个表,相关的键是表名:
df_dict = {}properties = sheet_metadata.get('sheets')for item in properties:
table = item.get('properties').get('title')
df_dict[table] = pd.DataFrame()
result = sheet.values().get(spreadsheetId=SPREADSHEET_ID,
range=table + '!A1:F').execute()
header = result.get('values', [])[0]
values = result.get('values', [])[1:]
if not values:
print('No data found.')
else:
all_data = []
for col_id, col_name in enumerate(header):
column_data = []
for row in values:
if col_id < len(row):
column_data.append(row[col_id])
else:
column_data.append('') ds = pd.Series(data=column_data, name=col_name)
all_data.append(ds)
df_dict[table] = pd.concat(all_data, axis=1)
2.2 创建表和 Django 模型类之间的映射
这一步可以通过构建一个表来轻松完成,该表将每个数据帧的列映射到 Django 模型类的属性:
tables = {}
for table,df in df_dict.items():
tables[table] = {}
for i in range(0, df.shape[0]):
attr = {}
attr['default'] = 'None'
if df['MAX LENGTH'][i] != '':
attr['max_length'] = df['MAX LENGTH'][i]
if df['KEY'][i] == 'primary key':
attr['primary_key'] = 'True'
tables[table][df['ATTRIBUTES'][i]] = [df['DATA TYPE'][i], attr]
它产生以下输出:
{
'**PERSON**': {
'**id**' : ['Integer', {'default': 'None', 'primary_key': 'True'}],
'**Name**' : ['Char', {'default': 'None', 'max_length': '32'}],
'**Surname**': ['Char', {'default': 'None', 'max_length': '32'}],
'**BirthDate**': ['Date', {'default': 'None'}],
'**Sex**'. : ['Char', {'default': 'None', 'max_length': '1'}]}, '**ORGANIZATION**': {
'**id**' : ['Integer', {'default' : 'None', 'primary_key': 'True'}],
'**Name**' : ['Char', {'default': 'None', 'max_length': '64'}],
'**Address**' : ['Char', {'default': 'None', 'max_length': '128'}],
'**WebSite**' : ['Char', {'default': 'None', 'max_length': '128'}],
'**Locality**': ['Char', {'default': 'None', 'max_length': '64'}]}, '**STAFF**'. : {
'**person_id**': ['Integer', {'default': 'None'}],
'**organization_id**': ['Integer', {'default': 'None'}]}
}
在实践中,为每个表构建属性列表,并为每个属性将表列转换为 Django 模型属性。
2.3 创建model.py
脚本的内容
模型转换的最后一步包括动态生成model.py
脚本。
我定义了一个函数来解析上一个表中的每一项,并为 Django 类中的每个属性构建代码:
def **get_type**(attr_type):
if isinstance(attr_type, list):
attr = attr_type[0] + 'Field('
for k,v in attr_type[1].items():
attr = attr + k + '=' + v + ','
attr = attr[:-1]
return attr + (')\n')
else:
return attr_type + 'Field()\n'
然后我构建一个字符串,它将包含model.py
文件的所有内容。我用静态代码初始化它:
script = 'from django.db import models\n'
然后,我为表中的每一项构建一个 Django 模型类:
for model,attributes in tables.items():
script = script + "class " + model + "(models.Model):\n"
for attr_name,attr_type in attributes.items():
script = script + '\t' + attr_name + ' = models.' + get_type(attr_type)
最后,我将结果保存到名为model.py
的文件中:
root = 'mywebsite/myapp/'
file_name = root + 'models.py'
with open(file_name, "w") as py_file:
py_file.write(script)
3 在 Django 更新模型
现在我准备对 Django 进行修改。我只需运行以下命令:
python3 manage.py makemigrations
这将给出以下输出:
作者图片
最后:
python3 manage.py migrate
该命令应该将三个表添加到数据库中:
作者图片
摘要
在本教程中,我展示了如何从 Google 电子表格中自动更新 Django 模型。这个过程允许同步数据模型和数据实现,尽管这两个过程由不同的人管理。
如果你已经走了这么远来阅读,对我来说今天已经很多了。谢谢!你可以在这篇文章中读到更多关于我的信息。
你愿意支持我的研究吗?
你可以每月订阅几美元,解锁无限的文章——点击这里。
额外奖金
我可以在 Django 中配置管理控制台,以便手动插入记录。这可以通过将每个创建的模型类注册到管理控制台来实现。我可以通过创建一个admin.py
脚本来自动完成:
script = """from django.contrib import admin\nfrom .models import *
"""for model in tables.keys():
script = script + "admin.site.register(" + model + ")\n"
然后,我可以保存文件:
file_name = root + 'admin.py'
with open(file_name, "w",encoding='utf-8') as py_file:
py_file.write(script)
然后,我可以再次应用迁移并创建一个新的超级用户:
python3 manage.py makemigrations
python3 manage.py migrate
python3 manage.py createsuperuser
最后,我可以运行应用程序:
python3 manage.py runserver
并连接到管理控制台:
[http://127.0.0.1:8000/admin](http://127.0.0.1:8000/admin)
在这里我可以看到我的表并添加新记录:
作者图片
本教程的所有代码都可以从我的 Github 库下载。
相关文章
使用 Python 自动编辑视频
原文:https://towardsdatascience.com/automatic-video-editing-using-python-324e5efd7eba?source=collection_archive---------11-----------------------
如何使用 Python 库 moviepy 和 vosk 实现语音控制或删除视频中的无声片段
由 Peter Stumpf 在 Unsplash 上拍摄的照片
视频剪辑总是很繁琐。移除不必要的视频片段并不是一项困难的任务,而是一项漫长的任务。您需要完整地查看视频(可能不止一次!),选择所有你需要的片段,加入它们然后渲染视频很长时间。简单剪辑一个小时的视频一般要三个多小时!所以我才有了这个想法。
当然,替代方案是存在的。比如 wisecat ,它能做的远不止“视频剪辑”。但是我想做一个快速、简单、免费的程序。Python 库 moviepy 和 vosk 会帮我做这件事。
问题陈述
我想建立一个程序,它会自动剪切一些视频片段,然后将这些片段连接在一起。它必须以两种方式接收关于这些片段的数据:
- 自动(部分自动,有一些人工干预)——识别控制字,以及
- 自动(全自动,无需人工干预)——识别长时间的静默
解决视频自动编辑问题的两种方法。作者图片
该任务可分为以下子任务:
- 了解如何使用 moviepy 编辑视频
- 识别控制字/静音及其时间戳
- 将这两个部件连接在一起
使用 Moviepy 编辑视频
首先,让我们尝试使用 moviepy 库裁剪并加入视频。
这非常简单——将源视频读入一个VideoFileClip
对象后,我们可以用构建的方法做很多事情。我们将需要下列各项:
video.subclip(start_seconds, end_seconds)
返回视频片段,从start_seconds
的video
切到end_seconds
- 和
concatenate_videoclips(clips)
,它们加入来自clips
列表的所有视频片段。
将您需要的所有(start_seconds, end_seconds)
对的列表放入segments
变量中。现在,您可以使用下面的代码从片段中制作一个视频。
事实上,这个简单的程序已经非常有用了。它可以处理简单的任务(修剪视频的开头/结尾,剪切所需的片段),比专业的视频编辑程序(索尼维加斯等)快得多。
现在我们所要做的就是从一个智能系统中得到这些配对(segments
)。
带时间戳的语音识别概述
这项任务更加复杂。作为搜索和试验的结果,我决定使用 vosk API 。在本文的中,我描述了一个关于如何用时间戳实现语音识别的详细教程。但是我也将在这里简要地描述一下最重要的几点。
首先,我们需要从视频文件中识别语音。正如我在上面的文章中解释的,vosk 语音识别模型输出一个 JSON 字典列表,其中包含每个识别单词的四个参数— confidence
、start time
、end time
和识别的word
(文本)。我创建了一个自定义的Word
类,按照这个格式描述单词。
下面的代码使用model_path
vosk 模型识别audio_filename
文件,并输出一个Word
对象列表。
识别控制字
我们知道每个单词的发音时间。太好了!现在我们需要选择控制词——这里有发挥创造力的空间。
我们需要两个——剪切片段的开始和结束。不能只用启动和停止。其实当然可以,只是不能确定在平时的讲话中不会说这些话。如果你说,程序将无法正常运行。最初,我决定使用一些罕见的英语单词,如睿智和过分。但结果是生僻字识别更差,非常生僻的可能根本不在字典里。也是在这一刻,我意识到口音对语音识别质量的影响有多大。因为我的母语不是英语,所以我决定采用更简单的解决方案。
我决定只使用我的母语中的单词开始和结束。由于 vosk 有国外的模型,你可以用你的母语模型识别英语语音。文字会被认定为废话,但我们不需要,对吧?主要是控制字将被正确识别。在俄语中,它们分别被写成 начало 和 конец ,读作纳哈罗和 konets 。第一个字表示要剪切的片段的开始,第二个字表示其结束。
使用俄语模型的英语语音识别示例。作者图片
也可以将英文单词的组合识别为控制命令。你甚至可以进一步识别声音——例如,手指点击或鼓掌。然而,它对我来说似乎不太方便。
现在我们需要迭代list_of_words
并检查识别的单词是否是控制单词之一。如果是,那么我们记住时间(开始时间为start_word
,结束时间为end_word
)。我还创建了offset
变量来确保视频的裁剪不会太尖锐。
之后,剩下的就是将segments
变量传递给用 Moviepy 编辑视频部分的代码片段!
识别沉默
另一种选择是删除静默持续时间超过某个阈值(例如 2 秒)的时刻。这里几乎所有的东西我们都已经很熟悉了。
这种方法是完全自动化的,在视频记录期间或之后不需要任何人工干预。你只要指定视频的路径,就能获得没有静默瞬间的视频。
最终计划
程序的两个主要部分已经准备好了,我们只需要把它们连接起来。唯一没有描述的是视频到单声道音频的转换。但是 moviepy 可以轻松应对这种情况。
项目结构
带有详细注释的完整程序可在本 GitLab 报告中获得。
https://gitlab.com/Winston-90/automatic_video_editing/
该项目的结构如下:
automatic_video_editing
├───article
├───models
│ ├───vosk-model-en-us-0.21
│ └───vosk-model-ru-0.10
├───videos
│ .gitignore
│
│ automatic_video_cutter.ipynb
│ automatic_video_cutter.py
│ Word.py
│
│ README.md
└── requirements.txt
它包含以下文件夹:
article
文件夹包含本教程的数据。models
文件夹包含从官方网站下载的 vosk 模型。videos
文件夹包含要处理的视频。
和代码文件:
Word.py
文件描述了Word
类。automatic_video_cutter.ipynb
笔记本包含一个完整的程序。automatic_video_cutter.py
文件包含相同的完整程序,但以 python 脚本的形式。不用 Jupyter 笔记本也能用来运行程序。
参见README.md
获取用户手册。
结果和结论
因此,程序的工作方式如下:
使用 Python 自动编辑视频 Youtube 上的控制词
使用 Python 自动编辑视频——消除 Youtube 上的静默时刻
我对结果很满意,但是还有很多时间需要讨论。
支持的视频格式
首先,关于支持的格式。该程序使用 moviepy ,并且 moviepy 支持 ffmpeg 支持的所有视频扩展。ogv,. mp4,.mpeg,。avi,。mov,。mkv 等。
执行时间
接下来,关于执行时间。我用不同长度的视频(从 1 分钟到 17 分钟)测试了这个程序几次。基于这些实验,我可以说完整视频处理的时间小于原始视频文件的长度。执行时间可能因硬件而异,但比例将保持不变。
17 分钟视频的程序执行时间。作者图片
首先,你需要阅读沃斯克模型。但是这个阶段是恒定的(不依赖于视频的长度),大约需要 30 秒。该计划有四个主要阶段:
- 将视频转换为音频 —不是在固定时间内执行,而是非常快速地执行(不到视频初始长度的 1%)
- 使用 Vosk 型号的语音识别 —实验表明,你需要大约
0.2*X
秒来识别持续时间X
秒的音频。 - 分析识别出的文本,得到
segments
—立即执行。在处理一分钟长的视频和 17 分钟长的视频时,我没有注意到区别。 - 渲染 —最长的阶段。使用默认参数,它的执行需要大约
0.5*X
时间。
视频质量
探究执行时间后产生的问题是——质量呢?毕竟渲染越快,质量越差。这里的渲染速度非常快。
是的,它是。渲染是使用write_videofile
moviepy 方法完成的,它有很多参数。我使用了它的默认值。
渲染我就不多说了,最重要的参数就是bitrate
。比特率是单位时间内用于处理信息的位数。使用的比特率越多,质量就越好。同时,你的文件也会变大。
默认的bitrate
值是None
,大约是'2000k'
(我在文档中找不到确切的值,通过实验找到了这个值)。使用这个值,视频被压缩了一点 ,但是我没有注意到任何特别的质量损失。
您可以设置更高的值来获得更好的质量。这也会降低渲染速度(但不会太慢)。我进行了一个实验,以从'1000k'
到'10000k'
的比特率渲染了一个视频——最小和最大值的渲染时间相差 50%。我就是这样算出大概的默认值的。
不同的比特率值和输出文件大小。作者图片
如果我们按比例计算文件大小(最初的视频持续 61 秒,为 11.6 MB,处理后的视频持续 24 秒),我们得到的值为 4.5 MB。所以默认比特率就足够了。
这也可能与初始视频质量有关。我用我的网络摄像头录的视频,所以不是很好。下面可以看到质量对比。如果网络摄像头有所不同,那么对于屏幕捕捉,即使是最低的比特率也能显示出良好的效果。
不同比特率的质量比较。作者图片
如果你想深入了解这个,你可以从 moviepy write_videofile 方法文档开始。
感谢您的阅读!
- 我希望这些材料对你有用。在 Medium 上关注我获取更多这样的文章。
- 如果您有任何问题或意见,我将很高兴得到任何反馈。在评论中问我,或者通过 LinkedIn 或 Twitter 联系。
- 为了支持我作为一名作家,并获得数以千计的其他媒体文章,使用我的推荐链接获得媒体会员资格(不收取额外费用)。
只需点击几下鼠标,即可自动生成机器学习代码
原文:https://towardsdatascience.com/automatically-generate-machine-learning-code-with-just-a-few-clicks-7901b2334f97?source=collection_archive---------20-----------------------
使用 Traingenerator 轻松创建 PyTorch 和 scikit-learn 模板代码,用于机器学习模型培训
阿纳斯塔塞·马拉戈斯在 Unsplash 上拍摄的照片
重复编写模板代码来训练您的机器学习(ML)模型可能是一个巨大的痛苦。
虽然您可能有基础代码要处理(例如,过去的项目,其他队友的工作),但是手动定制许多代码组件,如超参数和输入类型,仍然会引起不必要的麻烦。
本文介绍了 Traingenerator ,一个用于机器学习模型训练的简单代码生成器。
内容
(1)关于 train generator(2)如何使用(3)结论****
(1)关于列车发电机
Traingenerator 是一个简单的 web 应用程序(部署在 Streamlit 上),允许你在 PyTorch 和 scikit-learn 这两个流行的框架中生成模板代码。
生成的代码覆盖了代码模板的各个部分,包括预处理、模型设置、训练和可视化。
可用的模板目前仅限于图像分类(正在进行物体检测)。尽管如此,我们可以很容易地修改这些样板代码以适应其他 ML 任务,甚至添加我们自己的模板。
这个应用程序的美妙之处在于,它简化了数据科学家的工作,同时降低了非技术用户探索 ML 代码的门槛。
💻链接到 web app:https://traingenerator.jrieke.com⌨️链接到 github:https://github.com/jrieke/traingenerator🧑创建人: 约翰内斯·里克
(2)如何使用
我们将使用 PyTorch 框架选项来执行图像分类任务,以演示train generatorweb 应用程序是如何工作的。****
GitHub 的演示 GIF 在麻省理工学院许可下使用
步骤 1 —定义模型
根据麻省理工学院许可使用图像
有四种神经网络架构可供选择,分别是 AlexNet 、 ResNet 、 DenseNet、和 VGG 。
对于后三种中的每一种,您可以根据层数选择具体的变体(例如,ResNet 18、ResNet 34、ResNet 50 等)。).
指明班级人数后,可以决定是否要使用 ImageNet 预训练模型。如果是这样,生成的代码(例如,用于 ResNet 18)将如下所示:
****model = models.resnet18(pretrained=**True**)****
步骤 2 —选择输入数据
根据麻省理工学院许可使用的图像
有三个选项可用于输入数据选择:
- 公共数据集:从 MNIST 和 CIFAR10 等流行数据集中选择
- NumPy 数组:以 NumPy 数组的形式直接输入数据(以适当的数组形状组织)
- 图像文件:为你的数据集提供目录(以正确的格式)
步骤 3 —默认预处理
预处理序列基于预定义的 旋转视觉变换,如下所示:
- 将图像调整为 256 x 256 像素****
- 居中裁剪图像至 224 x 224 像素
- 用特定于所选神经网络的平均值和标准偏差标准化图像(转换为张量后)
第 4 步—设置培训
图片在麻省理工学院许可下使用
您可以在这里指定模型训练的详细信息:
- 损失函数 (CrossEntropyLoss 或 BCEwithLogitsLoss)
- 优化器(如 Adam、Adagrad、SGD 等。)
- 超参数(学习率、批量、时期)
- 记录(每 n 批打印进度)
- 设备(是否使用 GPU)
您可以选择为每个历元保存模型检查点,但是请注意这可能会占用大量存储空间。****
步骤 5 —指标可视化
根据麻省理工学院许可使用的图像
您可以选择自己喜欢的记录方法来跟踪您的模型训练跑步。可用的选项包括流行的工具,如 Tensorboard 、 Aim 和Weights&bias。
步骤 6 —下载代码
根据麻省理工学院许可使用的图像
最后,您现在可以下载刚刚定制的培训代码了。
Traingenerator 提供了三种方法,即作为一个 Jupyter 笔记本(。ipynb) , Python 脚本(。py)、或者谷歌 Colab 笔记本。****
结论
在这篇文章中,我们探索了由train generatorweb 应用提供的自动代码生成特性。我个人一直在我的 PyTorch 深度学习项目中使用它,所以我希望你会发现它很有帮助。****
鉴于可用的模板有限,您还会很高兴地了解到,您可以添加和保存模板,而无需更改应用程序中的任何内容。只需遵循自述文件中概述的简单步骤。
在你走之前
欢迎您加入我的数据科学学习之旅!点击此媒体页面,查看我的 GitHub ,了解更多精彩的数据科学内容。同时,祝你训练 ML 模型愉快!****
****** ******
在 Excel 中自动运行 SAP 交易
原文:https://towardsdatascience.com/automatically-run-and-export-sap-transactions-out-of-excel-using-vba-9c63a28ff566?source=collection_archive---------2-----------------------
使用 SAP 和 Excel GUI 自动化枯燥的工作。
向无聊大喊!(经我的朋友马蒂亚斯友好许可,马蒂亚斯·布勒的《蓝月亮》
动机
您是否经常需要使用特定的过滤参数执行 SAP 事务,并将结果导出为 Excel 文件?如果是这样,并且如果您想使用 Excel VBA 和 SAP 脚本来自动化这些步骤,这就是您的故事。在 Excel 文件中,我们将使用定义的过滤器/设置自动运行 SAP 交易,从 SAP 中导出结果,并将结果保存为 Excel 文件,无需进一步手动输入。当我们必须经常运行特定的 SAP 事务时,总是使用相同的过滤器/参数设置,这非常有用。现在,让我们开始自动完成构建 Excel-SAP GUI 这一枯燥重复的手工工作。
解决办法
在 SAP 中,您可以使用“脚本记录和回放”功能记录您的输入。这非常类似于例如 Excel 的宏记录器。要在 SAP 中执行此操作,您必须按 ALT+F12,然后单击“脚本录制和回放”:
虽然在德语中,序列顺序是一样的,不管你用的是什么 SAP 语言。
点击红色按钮记录您的 SAP 行动。
点击红色的“记录”按钮后,您在 SAP 中所做的一切都将被记录下来,直到您通过“停止”按钮停止记录。
在我们的示例中,我们将运行事务“IW29”,设置一些过滤器,并执行事务以查看结果。我们还会将 SAP 中的结果导出为 Excel 文件。之后,我们将停止记录并查看刚刚记录的 SAP 脚本文件。在我们的示例中,它看起来像这样:
我们现在简单地复制并粘贴这个脚本到我们的 Excel 文件的 VBA 模块。因此,我们打开 Excel 宏文件(例如 xlsm)并将以下代码(子例程)添加到我们的模块中:
Sub SapExport()
If Not IsObject(SAPapplication) Then
Set SapGuiAuto = GetObject(“SAPGUI”)
Set SAPapplication = SapGuiAuto.GetScriptingEngine
End If
If Not IsObject(SAPconnection) Then
Set SAPconnection = SAPapplication.Children(0)
End If
If Not IsObject(SAPsession) Then
Set SAPsession = SAPconnection.Children(0)
End If
If IsObject(WScript) Then
WScript.ConnectObject SAPsession, “on”
WScript.ConnectObject Application, “on”
End If
这段 VBA 代码将设置我们的 Excel 文件和 SAP 之间的连接。每次我们运行这段代码时,SAP 都会向我们显示这条消息,在脚本继续运行之前,需要首先确认这条消息:
SAP 消息弹出“一个脚本正试图访问 SAP GUI”
如果您想摆脱这条“一个脚本正试图附加到 SAP GUI,请通过 ok 按钮确认”的消息,您必须在 SAP 中定制您的本地布局,如下所示:
在 SAP 中按(ALT+F12)可以“自定义本地布局”。然后点击“选项”,点击“辅助功能&脚本”,最后选择“脚本”。现在取消勾选“当脚本连接到 SAP GUI 时通知”和“当脚本打开连接时通知”复选框。因此,最终 SAP 脚本设置应该是这样的:
回到您的 Excel VBA 模块,您现在可以粘贴已记录的会话任务(事务的过滤器)。您必须做的唯一修改是用 SAPsession 替换 session,因此最终它在您的 Excel 模块中看起来像这样:
SAPsession.findById(“wnd[0]”).maximize
SAPsession.findById(“wnd[0]/tbar[0]/okcd”).Text = “iw29”
SAPsession.findById(“wnd[0]”).sendVKey 0
SAPsession.findById(“wnd[0]/usr/chkDY_MAB”).Selected = False
SAPsession.findById(“wnd[0]/usr/ctxtQMART-LOW”).Text = “z2”
SAPsession.findById(“wnd[0]/usr/ctxtDATUV”).Text = “10012021”
SAPsession.findById(“wnd[0]/usr/ctxtDATUB”).Text = “26012021”
SAPsession.findById(“wnd[0]/usr/ctxtDATUB”).SetFocus
SAPsession.findById(“wnd[0]/usr/ctxtDATUB”).caretPosition = 8
SAPsession.findById(“wnd[0]”).sendVKey 0
SAPsession.findById(“wnd[1]/tbar[0]/btn[0]”).press
SAPsession.findById(“wnd[0]/tbar[1]/btn[16]”).press
SAPsession.findById(“wnd[1]/tbar[0]/btn[0]”).press
SAPsession.findById(“wnd[1]/tbar[0]/btn[0]”).press
SAPsession.findById(“wnd[1]/tbar[0]/btn[0]”).press
到目前为止,我们已经使用定义的过滤器运行了 SAP 事务,并将结果导出为 Excel 文件。最后,我们还想将这个文件保存到一个定义的路径中。下面你会找到一个简单的解决方案,这已经足够完成我们的任务了:
‘Disable the Application Alert before saving the fileApplication.DisplayAlerts = False
Windows(“FileName”).Activate
ActiveWorkbook.SaveAs FileName:=”C:\FileName.xlsx”, FileFormat _
:=xlOpenXMLWorkbook, CreateBackup:=False‘Enabling the Application Alerts after saving the file
Application.DisplayAlerts = True'to “clean up” SAP we return back to SAP’s Easy Access:
SAPsession.findById(“wnd[1]/tbar[0]/btn[0]”).press
SAPsession.findById(“wnd[0]/tbar[0]/btn[3]”).press
SAPsession.findById(“wnd[0]/tbar[0]/btn[3]”).press
End sub()
如果您将所有这些 VBA 代码添加到 Excel 的一个子例程中,就大功告成了。因此,将来您可以使用 Excel 中定义的过滤器来调用您的 SAP 事务。
注意:要使 VBA 代码正常工作,您必须打开一个 SAP 实例(换句话说,您必须已经登录)。请确保只有一个 SAP 模式处于活动状态,并且该实例必须处于启动模式:
在启动 VBA 之前,您必须打开 SAP Easy Access
现在,您可以使用 Excel 以自动化的方式从 SAP 中导出结果列表了!你可以在我的 Github 上找到完整的 Excel 宏。
非常感谢您的阅读!希望这篇文章对你有帮助。请随时在 LinkedIn 、 Twitter 或工作室与我联系。
https://jesko-rehberg.medium.com/membership
最初发表在我的网站 DAR-Analytics 。
使用 Sweetviz 和 Comet.ml 自动跟踪您的所有 EDA
原文:https://towardsdatascience.com/automatically-track-all-your-eda-using-sweetviz-and-comet-ml-9cb7545b0fab?source=collection_archive---------41-----------------------
即时归档和跟踪每一份 Sweetviz EDA 和分析报告
Comet.ml 工作区中的 Sweetviz 报告(图片由作者提供)
Sweetviz 是一个很棒的库,不仅可以在 EDA 阶段,而且可以在整个分析和模型开发过程中快速获得任何数据集的快照(上一篇文章中的细节)。2.1 版引入了 comet.ml 平台的集成,可自动记录每份 Sweetviz 报告。
😎自动跟踪是神奇的!
这种情况经常发生在我身上,也可能发生在你身上:你“处于最佳状态”,绘制一幅又一幅图表,随着你经历一连串的模式分析、填补缺失数据、剔除异常值、工程特性和调整模型,开始对数据集有越来越深刻的理解。唷!
当然,在进行过程中,您会尽最大努力做些笔记,到处保存最好的代码和图表。但是当你几天后重新开始的时候,你会意识到你并没有完全抓住的全部。什么是确切地说,你在某个时候偶然发现的那个如此有洞察力的分布图?什么是该功能的变体,它很有希望,但是你从来没有仔细检查过?这份清单还在继续…****
自动跟踪系统提供的是一张大网,几乎可以捕捉到你做的每一件事,几乎不用写代码。你模型上的随机凌晨 2 点变化?检查。两周前图表上的第 12 个变化可能最终被证明是有见地的?检查。
这还不到一半。跟踪系统还可以自动记录大量元数据和与您的工作相关的一般分析,无需任何用户干预,支持实验之间的比较,跟踪各种元数据,当然,另一个巨大的优势是团队协作和团队内共享工作见解&。
Sweetviz 和 Comet.ml
鉴于所有这些,以及我所说的 Sweetviz 在整个项目中的有用性,很容易理解为什么将其与 Comet.ml 完全集成会如此有用,Comet.ml 是一个领先的基于云的实验管理平台,可跟踪您的数据集、代码更改、实验历史和模型。在 2.1 版中,Sweetviz 报告现已成为广泛数据收集的一部分,确保不会因为每次都要花时间单独保存不同的报告而丢失或浪费任何工作。
没有更多的" Report_3mo_test8.html "!😁
Comet.ml 集成
自动记录
如前所述,自动跟踪包的优势之一是它们通常需要很少的持续努力。一旦正确设置了 comet_ml 环境(这超出了本文的范围,但通常包括pip install comet_ml
然后设置几个环境变量,如COMET_API_KEY
,使用 Sweetviz 命令显示的任何报告,如show_html()
或show_notebook()
将自动上传到您的 comet_ml 工作区。
这种自动记录的实验将记录到您的环境指定的项目中(如果没有设置项目,则记录到Uncategorized Experiments
项目中),在 HTML 选项卡下:
报告位于 HTML 选项卡中(按作者排列的图像)
直接记录
彗星追踪是以“实验”为基础的。自动记录将为报告创建自己的实验,但有时在正在进行的实验中对报告进行分组会很有用。
要在正在进行的实验中直接添加 Sweetviz 报告,提供了一个直接的log_comet(exp)
功能。该函数将一个“实验”对象作为参数,报告将被添加到该参数中。像现有的 Sweetviz 函数(如show_html()
)一样,它将在所需的报告对象上被调用。
report = sweetviz.analyze(dataframe)
report.log_comet(my_experiment)
使用直接记录的优点是报告将直接出现在正在使用的项目/实验中,而不是更一般的“未分类实验”项目中。
配置 Comet.ml 的 Sweetviz 报告
使用宽屏布局(图片由作者提供)
Sweetviz 报告可配置为使用宽屏(水平)或垂直布局,以及缩放。这有助于适应各种用户设置和硬件配置。
无论是通过自动记录还是log_comet()
,Sweetviz 报告都将使用[comet_ml_defaults]
标题下的 Sweetviz INI 配置,如下所示:
[comet_ml_defaults]
html_layout = vertical
html_scale = 0.85
要覆盖这些设置,只需创建一个自定义 INI 文件,并在使用以下命令生成报告之前加载它:
sv.config_parser.read("MyOverride.ini")
结论
我希望你和我一样会发现自动跟踪很有用,如果你选择使用这些平台,那么这篇通过 Comet.ml 和 Sweetful 进行自动跟踪的指南会很有帮助!
用 Python 自动化 AWS S3 文件管理
原文:https://towardsdatascience.com/automating-aws-s3-file-management-with-python-6312e26dd771?source=collection_archive---------18-----------------------
如何利用可编程性和 Python 来自动化管理您的 AWS S3 文件。
图片来自 Unsplash。
亚马逊网络服务(AWS) S3 是全球使用最多的云存储平台之一。免费层包括 5 GB 的标准存储,20,000 个 get 请求和 2,000 个 put 请求,为期 12 个月,这使其适合于在相对较短的时间内运行的各种中小型项目。一些项目可能需要频繁收集需要存储在云中的数据,我们可以利用可编程性来自动管理这些文件,而不是手动管理这些文件。
在今天的文章中,我将展示一些介绍性的代码示例,介绍如何利用 AWS S3 API 并使用 Python 3.8 和 boto3 包自动化您的文件管理。
1 |收集 AWS S3 API 信息
首先,我们将定义几个 Python 变量,这些变量将保存我们的 AWS S3 帐户的 API 和访问信息。
登录您的 AWS S3 管理控制台,通过您右上角的用户名打开下拉菜单,点击 我的安全凭证 。
来自 AWS S3 管理控制台的图像。
在访问密钥下,您需要点击 C 创建一个新的访问密钥并复制您的访问密钥 ID 和您的秘密密钥。这两个变量将作为单独的变量添加到我们的 Python 代码中:
aws_access_key = "###############"
aws_secret_key = "###############"
然后,我们需要创建我们的 S3 文件桶,我们将通过我们的 API 访问。在 S3 管理控制台上,导航至桶并点击创建桶。
创建存储桶后,我们定义一个保存存储桶名称的变量:
aws_bucket = "bucket-name"
2 |将文件上传到 S3 存储桶
在我们收集了 AWS S3 帐户的 API 和访问信息之后,我们现在可以开始使用 Python 和 boto3 包对我们的 S3 bucket 进行 API 调用。 boto3 包是 Python 的官方 AWS 软件开发包(SDK)。
我们首先导入必要的包,并定义包含 API 和 bucket 信息的变量。然后,我们可以编写一个函数,让我们将本地文件上传到我们的 bucket。
local_filename 参数保存了我们想要上传的本地文件的名称,而 aws_filename 参数定义了当本地文件上传到我们的 AWS S3 存储桶时应该如何对其进行重命名。然后我们通过 boto3.client 建立到 AWS S3 账户的连接,最后利用 boto3 函数 upload_file 上传我们的文件。
3 |从 S3 桶下载文件
既然我们已经看到了如何将本地文件上传到我们的 S3 存储桶,我们还将定义一个函数来将文件下载到我们的本地机器。
4 |列出 S3 存储桶中的文件
除了上传和下载文件,我们还可以请求一个目前在我们的 S3 桶所有文件的列表。
输出将是我们的 bucket 中所有文件名的 Python 列表。
5 |获取 S3 桶中文件的公共 URL
此外,我们可以请求生成一个可公开访问的 URL,指向我们的 bucket 中的一个文件。如果我们想与外部人员自动共享文件,这将非常有用。
为了生成一个公共 URL,我们还需要定义 Python 变量,这些变量包含我们的 bucket 的签名版本和我们的 bucket 的数据中心所在的区域名称。请相应地调整变量值。
这个函数将返回一个我们文件的公共 URL 的 Python 字符串,这个字符串允许任何有链接的人访问它。
我希望这篇用 Python 自动管理 AWS S3 文件的介绍对你有所帮助。💡我将在未来更新和添加新的代码示例,所以请随时回来更新。
让我知道你的想法,或者如果你有任何问题,请联系我或在下面评论。
机器学习系统中数据漂移阈值的自动化
原文:https://towardsdatascience.com/automating-data-drift-thresholding-in-machine-learning-systems-524e6259f59f?source=collection_archive---------18-----------------------
在缺乏真实数据的情况下,实际有效地监控生产 ML 模型输入
在 Unsplash 上由 Carlos Muza 拍摄的照片
更新:我有机会在 3 月 30 日的纽约 MLOps 世界大会上展示并记录这些原则。如果你喜欢对下面的材料进行口头处理,下面是录音。
在实际的 ML 监控应用中,我们希望检测 ML 模型是运行良好还是出现故障。没有发现糟糕的模型性能可以转化为糟糕的甚至有偏见的预测,这可能导致收入损失甚至公关火灾,我们年复一年地从大型科技公司那里看到,从面部识别系统未能发现某些少数民族,到搜索引擎自动完成中的仇恨言论。
在本文中,我们将简要概述数据漂移阈值处理如何帮助捕捉较差的模型性能,本文的大部分内容将重点讨论在生产级 ML 监控系统中实现自动数据漂移检测的两个版本。
概观
为什么我们需要数据漂移?
监控模型的标准方法是基于性能指标,即某个时间段或批次之间的准确度/精确度/召回率/f 值。为了生成这些指标,我们需要数据点的预测和基础事实标签,例如,信用风险模型预测一个人将在 1 年内按时支付贷款,因此应该被批准使用信用卡,我们知道这个人是否在 1 年内按时支付了贷款。我们已经有一个问题,因为我们不知道地面真相,直到 1 年后。
在大多数生产应用中,预测时间和地面实况收集时间之间存在滞后,这极大地阻碍了快速修复模型问题的能力。利用标签团队或服务可以帮助消除这种滞后,但它不会完全消除它。因此,我们可以根据数据漂移指标来监控输入,而不是根据输出来监控指标。
什么是数据漂移?
数据漂移从根本上衡量两个分布之间的统计分布变化,通常是相同的特征,但在不同的时间点。例如,在我们查看一个输入特征的单变量情况下,我们应该合理地预期,如果特征的形状在训练时间和预测时间之间发生显著变化,模型输出的质量将会下降。
作为一个玩具示例,如果我们训练一个 ML 模型只解决代数问题,而突然在预测时将几何问题输入到模型中,我们会认为预测非常糟糕,因为该模型没有经过几何问题的训练。
本质上,数据漂移是在缺乏基础事实标签的情况下,我们的经典性能指标的代理。下一个自然问题是如何正式量化数据漂移。
数据漂移指标概述
我们可以使用许多不同种类的指标来量化数据漂移。这里,我们将关注两个流行的度量家族:f-散度和假设检验度量。对于前者,我们将研究 KL 散度和 PSI。对于后者,我们将查看卡方检验和 KS 检验统计。
对于任何漂移度量, P 是训练 ML 模型的训练数据(参考集),而 Q 是模型执行预测的数据(推理集),这可以在流动模型的滚动时间窗口上定义,或者在批量模型的批量基础上定义。
KL 散度
如果你需要一个快速概览,我发现这篇介绍性的文章非常有帮助。
从 P 到 Q 的 KL 散度被解释为我们在使用 Q 而不是 P 对数据 X 建模时预期丢失的信息的 nats,其在概率空间 K 上被离散化。KL 散度是不对称的,即如果交换 P 和 Q 的值是不同的,并且不应用作距离度量。
离散 KL 散度
人口稳定指数
虽然 KL 散度是众所周知的,但它通常被用作 VAEs 等生成模型中的正则化惩罚项。可以用作距离度量的更合适的度量是群体稳定性指数(PSI ),其测量从 P 到 Q 然后从 Q 返回到 P. 我们预期丢失的信息的往返损失
离散 PSI
假设检验
假设检验根据特征是分类的还是连续的使用不同的检验。
对于具有 K 类别的分类特征,即K——1 为自由度,其中 N_Pk 和 N_Qk 为特征出现的次数,为 k ,1≤ k ≤ K ,分别为 P 和 Q ,则卡方检验统计量为标准化方差的总和
具有 K-1 个自由度的卡方统计
对于连续特征,F_P 和 F_Q 分别是经验累积密度,对于 P 和 Q ,Kolmogorov-Smirnov (KS)检验是非参数的,即无分布的,检验比较经验累积密度函数 F_P 和 F_Q
Kolmogorov-Smirnov 检验统计量
为什么是自动漂移阈值?
斯科特·罗杰森在 Unsplash 上拍摄的照片
让人类手动查看模型随时间或批次产生的漂移度量显然是乏味且不理想的,漂移度量的直接用例将是基于某个阈值设置警报,例如,对于该批次,PSI 跳转超过 0 . 3,并且应该创建警报以供人员检查。补救措施可以是检查将该特性输入到模型中的管道是否损坏,最近是否有错误代码或计算变更,或者该特性是否确实漂移并建议模型需要重新训练。
但是那 0.3 是从哪里来的呢?设置任意选择的阈值不是一个好的解决方案。如果阈值太高,应该发出的警报现在会被忽略(更多的假阴性)。如果阈值太低,现在会出现不应出现的警报(更多误报)。
通用常数阈值是不鲁棒的,因为该阈值应该取决于训练数据 P 的形状。如果 P 是均匀的,并且我们看到单峰 Q ,那么漂移值将显著小于如果 P 是高度单峰的并且以远离相同的 Q 的某个平均值为中心的情况,因为如果 Q 不是来自于 P ,那么均匀的前 P 就不太确定。下面是一个例子。
为了设置对警报系统有意义的可靠阈值,我们将深入探讨如何自动计算此类阈值。也就是说,我们希望推荐数据漂移阈值来创建警报,以便用户(a)不必手动设置警报,并且(b)不必确定什么是好的阈值。
假设检验指标的自动漂移阈值
对于假设检验指标,简单的解决方案是使用传统的α= 0.05 为每个检验设置适当临界值的阈值,即 95%确信任何高于各自临界值的假设指标表明存在显著漂移,其中Q∽P可能为假。
然而,假设检验也有局限性,从影响卡方检验显著性的样本量到分布中心的敏感性,而不是 KS 检验的尾部。
出于这些原因,探索 f-散度指标等其他类别的漂移指标非常重要,现在我们将探索 f-散度漂移阈值自动化的方法。
自动漂移阈值 V1:自举
概观
自举自动漂移阈值系统(图片由作者提供)
(1)对于由 i 索引的大量模拟,对于给定的输入特征,从参考集 P 中引导采样 m 次,其中 m 足够大,并构建推理分布 Q ᵢ,其代表如果我们的数据通过模拟真正来自 P 时我们所期望的。然后,我们计算并跟踪每次模拟的数据漂移 f( P,Q ᵢ)。
(2)我们将数据漂移阈值设置为 max_i(f( P,Q ᵢ))的保守值,其本质上是传统统计设置中α → 0 的临界值/截止值,即,我们 99.999%确信来自实际 Q ,即推断时间片或批次的数据漂移值高于阈值表示推断数据不是从与p相同的底层分布产生的如果导致假阳性的代价不高,那么我们可以在传统的α=.05 单侧设置中,将阈值设置为 f 的 95%百分位( P,Q ᵢ)。**
自举的局限性
自举很有吸引力,因为它是基于模拟的,并且不需要分发,但是这种方法由于两个问题而不可扩展。
(1)对每个模型的每个特征进行模拟在计算上是昂贵的。具体来说,基于每个模型的运行时间将是O(n_features*n_categories_per_feature*n_metrics*n_simulations)
。
(2)样本容量越小,抽样稳定性假设就越不成立。
作为一个玩具例子,假设我们在 P 中有红色、白色、蓝色和橙色的弹珠,均匀分布。现在让我们呈现尺寸为 3 的Q;因为我们没有办法代表所有四种颜色,所以没有办法判断 Q 是否来自 P 。即使我们对 6 颗弹珠进行了取样,我们也无法对这 6 颗弹珠中的每一类进行 1/4 的近似。
设 m 为每次模拟的模拟数据点数,以创建 Q ᵢ.在相同的弹珠玩具示例中,当 m 为低时,采样不稳定性导致人为的高不确定性(并因此导致人为的高数据漂移阈值),因为 P 没有被很好地采样并在 Q ᵢ.中表示
KL 散度自助采样不稳定性(图片由作者提供)
解决问题(2)的方法是通过改变 m 为给定特性创建模拟阈值曲线,但现在我们通过将运行时间乘以 m 加剧了问题(1)。我们现在还有空间复杂性的问题,因为现在我们必须在查找(数据库或缓存)中存储阈值,以便在下游应用程序中使用,如创建警报规则的警报服务或查询服务缓存。放弃额外的存储并在查询时模拟阈值曲线也不是一个选项,因为对于大多数面向用户的应用程序来说,查询会花费太长时间。
简而言之,在考虑校正曲线时,使用灵活的模拟设置的权衡不值得计算费用,校正曲线要么(a)需要存储,这将花费大量存储费用或炸毁缓存,要么(b)在查询时模拟,这对于面向用户的应用程序来说太慢。
自动漂移阈值 V2:封闭形式的统计
照片由 Edge2Edge 媒体在 Unsplash 上拍摄
事实证明,我们可以使用概率论一次性设定数据漂移阈值的上限。我们将利用标准概率论、狄利克雷分布和一阶泰勒级数展开。请记住,我们仍然是在每个功能的基础上推导阈值。
KL 散度
首先,让我们
参考集 P 已知,推理集 Q 未知。直观地说,这仅仅意味着我们已经观察了在创建我们的 ML 模型中使用的训练数据,并且我们正在问一个假设的问题,即对于一些假设的推理集 Q 来说,我们可以预期数据漂移是什么。形式上,
第二行:期望的线性和条件概率。
第三行:Q∞Dirchlet(α),即 Q 对一个概率分布建模,是 beta 分布的多元推广。因此,在这种情况下,我们可以使用 digamma ψ函数。
α = (α_1,…,α_K)传统上对应于从 Q,偏移一个小常数的特征的 K 类别中的观测概率,即先验计数。然而, Q 是未知的,那么我们如何得到正确的计数呢?我们从 P 开始做。毕竟,这个期望陈述的整个要点是平均量化我们期望看到的漂移,如果Q∩P,并且在实际推理集中超过该值的数量表明我们可能有显著的漂移,即Q∩P为假。
回到 α ,我们可以使用贝叶斯均匀先验Q∞狄利克雷( 1 _K)并更新使得Q|P∞狄利克雷( 1 _K + N_q * p _K),其中 N_q 是推理集合Q中的数据点数这是β-二项式共轭的多元推广。
因此我们有了,
人口稳定指数
PSI 变得有点棘手,我们需要设定期望值的上限。让
然后
以下是步骤:
第二行:期望值的线性,并用结果代替上面的 KL 散度。
第 3 行:期望和条件概率的线性。
第四行:对狄利克雷分布的期望。
第 5 行:德尔塔法近似值(见附录)。
第 6 行:对狄利克雷分布的期望。
第七行:简化。
V1 问题解决了!
请注意,我们现在已经解决了引导中的两个问题。
(1)我们不必担心运行时间,因为这种形式是只涉及计数的一次性解决方案,并且我们可以使用对 digamma 函数的近似。
(2)我们通过在 Q 的参数上使用贝叶斯加伪计数设置来处理不同的样本大小。
履行
在生产中,我们如何实现这种动态阈值?虽然阈值是动态的,取决于指标和传入的推理集,但上面所有的预期,以 P 为条件,都可以表示为 SQL 查询或定制但简单的函数。
离散化所有连续特征,而不是平滑离散特征,将是一种合理的权衡:尽管我们可能无法捕捉到 P 和 Q 的完整连续性质,但我们将避免计算开销巨大的核密度估计,将 P 和 Q 表示为连续分布。
等等,方差呢?
我们也可以计算方差并应用 Delta 方法近似,因为我们会遇到使用标准概率理论无法解决的对数项的方差和协方差。这些工具在下面的附录中。然而,事实证明,大多数度量标准不会像 KL 散度那样清晰,所以大多数条件期望和方差都是通过柯西-施瓦兹上界的。当然,包含一个附加的上限方差项,或者甚至使用二阶近似都是可行的,但是额外的计算可能不值得用获得的时间来换取更严格的界限。
另一次…
我们还可以使用泰勒级数展开来上限其他指标,如 JS 散度和海灵格距离。
结论
今天到此为止!希望您获得了一些关于如何以计算上和概率上合理的方式实现自动阈值的见解!我们在 Arthur AI 实现了这些类型的系统,一些等式可以对客户体验有很大帮助。
快乐监控!
由 Pablo Heimplatz 在 Unsplash 上拍摄的照片
附录:增量法近似值
请注意,下面两个部分的一阶近似是上限,因为对数函数是凹的。
对数近似值
通过围绕平均值的一阶泰勒级数展开,
使用这个近似值,我们有
和
柯西-施瓦茨的不等式。
Xlog(X)
通过围绕平均值的一阶泰勒级数展开,
使用这个近似值,我们有
并且让
我们有
柯西-施瓦茨的不等式。
在 Python 上自动化数据科学任务以节省时间
原文:https://towardsdatascience.com/automating-data-science-tasks-on-python-to-save-hours-2a1ad7a0311f?source=collection_archive---------11-----------------------
使用 Pandas、操作系统库和自定义数据库包装器(psycopg2)
卡尔·海尔达尔在 Unsplash 上的照片
连接到您的数据库,为您的数据创建一个表,查询它进行清理,然后输出您的数据作为一个自定义文件,然后基本上重复整个周期,直到最后的文件。在本文中,我们将创建一个 python 脚本来自动化上面提到的整个循环。
在将数据加载到模型中之前清理数据的过程是项目生命周期中不可或缺的一部分。如果你在一家公司工作,你可能和你的 QA 团队使用同一个数据库;所有这些都让事情变得有点复杂。在数据准确性对系统成功至关重要的环境中,手动数据处理任务总是一个缺点,因为它们可能导致不可避免的错误。
为了避免错误、低速度和培训人员的成本,需要自动化您的数据清理/修改任务。在本文中,我们将学习数据集的一些复杂自动化,无论是在本地机器上,还是像[postgres](https://www.postgresql.org/), [MySQL](https://www.mysql.com/)
或[AWS](https://cloud4c.com/lp/aws-cloud-services/?utm_source=google_search&utm_medium=cpc&utm_campaign=MSP_Cloud_AWS_India_Exp_Srch&utm_term=%2Baws%20%2Bcloud&utm_content=528924743032&utm_device=c)
这样的云数据库上。
提示:如果你是新手,我建议你尝试一下 AWS,而不是把它实现为一个
localhost
。使用 pgAdmin 和它一起从你的 IDE 本身访问你的数据库。
https://aws.amazon.com/free/?trk=ps_a134p0000078PqHAAU&trkCampaign=acq_paid_search_brand&sc_channel=ps&sc_campaign=acquisition_IN&sc_publisher=google&sc_category=core-main&sc_country=IN&sc_geo=APAC&sc_outcome=acq&sc_detail=aws&sc_content=Brand Core AWS_p&sc_matchtype=p&sc_segment=509606977839&sc_medium=ACQ-P|PS-GO|Brand|Desktop|SU|Core-Main|Core|IN|EN|Text|xx|PH&s_kwcid=AL!4422!3!509606977839!p!!g!!aws&ef_id=CjwKCAjwruSHBhAtEiwA_qCppmvfB1w0x10A5j14DMGEDdDrLgL0_SLT1F-cDG3qd_AVLsLpqrxodxoCFkIQAvD_BwE:G:s&s_kwcid=AL!4422!3!509606977839!p!!g!!aws&all-free-tier.sort-by=item.additionalFields.SortRank&all-free-tier.sort-order=asc&awsf.Free Tier Types=*all&awsf.Free Tier Categories=*all
清洁技术太阳能数据集拥有过去几个月来自逆变器和电表的数据。这些数据在处理之前需要进一步处理,这是自动化解决问题的一个很好的例子。我们将把Inverter-1, Inverter-2, MFM, and WMS
中的原始数据转换成我们需要的 Gen-1 文件。
你可以在这里下载数据集和执行源代码:https://github.com/preetshah7/csv_automated_modifier
以下是我们自动化的逐步概述:
- 定义问题陈述
- 使用 bash 命令和循环识别 CSV
- 创建一个熊猫数据框架来执行您的清理任务
- 使用操作系统库配置输出目录
- 从数据帧创建所需的 Gen-1 文件
- 将数据导入 Amazon Web Services (AWS)上的 Postgres 数据库
定义问题陈述
我们有两个逆变器、一个电能表(MFM)和一个气象变电站(WFM)的原始数据,分别位于两个月内。
我们需要执行的任务如下:
- 对于反相器,列 i32 表示行的时间戳。将此列作为 Gen1 文件中的第一列,并将列标题重命名为“Timestamp”)。
- MFM:规则同上;唯一的区别是时间戳列是 m63。
- WMS:规则同上;唯一的区别是时间戳列是 w23。上述每个示例的输出文件中都给出了列名。
预期输出格式:[站 ID]|-->[年]|-->[年-月]|-->[变电站 ID]|-->[Gen-1 data . txt]
使用 bash 命令和循环识别 CSV
一个月内输入的原始文件列表
对于这个实现,我们需要库 numpy、pandas 和 os。
可以使用getcwd(),
获得月份目录,并将它们存储为一个列表。
创建一个函数,使用os.listdir()
遍历目录中的所有文件,并识别将被添加到列表中的 CSV。
我们已经创建了一个函数,给定路径作为输入,将自动给出 CSV 文件列表。
创建一个熊猫数据框架来执行您的清理任务
首先,我们对单个文件执行任务,然后实现自动化
通过df.columns
从各自的数据帧中提取样本列名
现在,实现df.loc()
来重新定位列,并将列名分配给我们的数据帧。
现在我们已经获得了所需的输出,我们可以为每个仪表自动执行这项任务。
逆变器:
对于输入,我们取一个文件所在的files
和path
的列表。完成清理任务后,我们修改输出的输入路径。(检查创建输出目录的下一步)
能量计(MFM):
同样的功能也适用于 MFM,但是我们在这里替换了'm63'
列。记得插入 MFM 示例输出中的列名。
气象分站(WMS):
这里带有时间戳值的列是'w23'.
,注意在'[df.to_csv()](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.to_csv.html)'
、'\t'
中使用正确的分隔符。
我们已经成功地创建了稍后要实现的自动化任务。
使用操作系统库配置输出目录
将带有月份数据的仪表组合起来,以获得所有配置,然后执行os.mkdir()
来自动创建所有目录。
与其他语言相比,Python 中的异常处理更容易使用。我们将它用于目录配置,这样,如果目录已经存在,代码仍然可以运行而不会出错。
自动生成的目录
从数据帧创建所需的 Gen-1 文件
最后,为了实现我们的自动化,我们运行一个嵌套的 For 循环。它基于其输入路径的字符串有条件地将特定的修改任务应用于文件。在几秒钟内,我们的结果就可以在自动化创建的目录中看到。您可以向这种自动化添加任何数量的数据,它将始终高速运行。
我们已经从本地的角度完成了自动化,但是我们将继续它的云应用。
根据需要修改生成的输出文件
将数据导入 Amazon Web Services (AWS)上的 Postgres 数据库
对于本文,我们在 AWS 上使用了一个 Postgres 数据库。我们还需要在我们的机器上运行 pgAdmin 来建立与数据库的连接。在您的环境中安装所需的库(psycopg 2);对于其他数据库,包装器库可能有所不同,但游标过程是相同的。
灵感来源:内特在地层抓痕
这个脚本会自动将 CSV 文件导入您的 Postgres 数据库。只需将 CSV 文件放在与笔记本相同的目录中,然后运行笔记本。我们已经成功实现了数据科学任务自动化。
https://www.postgresql.org/
摘要
下面是我们在构建 CSV 自动修改器时遵循的逐步过程的总结:
- 我们定义了问题陈述
- 使用 bash 命令和循环识别 CSV
- 创建了一个熊猫数据框架来执行我们的清洁任务
- 使用操作系统库配置输出目录
- 从数据帧创建了所需的 Gen-1 文件
- 将数据导入 Amazon Web Services (AWS)上的 Postgres 数据库
未来的工作
以下是我们扩展项目的一些方法:
- 降低时间复杂度,这样可以快速处理大量数据;尽可能使用列表理解。
- 在实践中实现最常见的数据库,以便更多的人可以利用这项工作;常见的建议是 MongoDB 和 MySQL。
- 可以在自动化本身中实现无监督的机器学习,与特征的数量无关。数据清理在这里会相当困难。
参考
- 堆栈溢出答案为。九和。iloc
- 清洁技术太阳能公司发布的自动化问题声明。
- https://www.geeksforgeeks.org/os-module-python-examples/
- https://www.psycopg.org/docs/
使用 DataPrep 实现 EDA 自动化
原文:https://towardsdatascience.com/automating-eda-using-dataprep-2b541b6a3149?source=collection_archive---------25-----------------------
使用 Dataprep 自动化探索性数据分析
报告(来源:作者)
数据分析帮助我们识别数据集中的模式,分析不同变量之间的相关性和关联性。借助于不同的可视化效果,我们可以确定这些数据是否试图讲述某个特定的故事。有不同类型的图表和绘图可用于分析和可视化数据。
创建不同类型的绘图和图表会耗费大量时间,因为我们需要根据列的数据类型确定有用的图形类型,并且我们还需要编写大量代码来创建这些图形。但是,如果我告诉你,你可以在一行代码中完成所有这些,那会怎么样呢?
Dataprep 是一个开源 Python 库,有助于自动化探索性数据分析过程。它在创建数据分析报告时很有用,它还有 3 个功能,用于绘制图形、绘制缺失数字和数据的相关性。
在本文中,我们将探索 Dataprep 提供的一些功能。
让我们开始吧…
安装所需的库
我们将从使用 pip 安装 Dataprep 库开始。下面给出的命令可以做到这一点。
!pip install -U dataprep
导入所需的库
在这一步中,我们将导入加载数据集和执行 EDA 操作所需的库。
from dataprep.datasets import load_dataset
from dataprep.eda import create_report
from dataprep.eda import plot, plot_correlation, plot_missing
正在加载数据集
对于本文,我们将使用 Dataprep 中预定义的著名成人数据集。
df = load_dataset("adult")
创建 EDA 报告
现在,我们将创建一个 EDA 报告,其中包含所有的可视化、相关性、缺失图等,这有助于分析数据集。
create_report(df).show_browser()
报告(来源:作者)
这是报告的主页,在这里您可以看到我们正在使用的数据的概述。同样,让我们看看如何创造不同的情节。
创建地块
在这一步中,我们将创建由 Dataprep 提供的不同的图。
- 剧情
该图为所有数据变量创建了可视化。
plot(df)
情节(来源:作者)
2.剧情关联
此图创建不同类型的相关图,显示不同数据变量之间的相关性。
plot_correlation(df)
相关性(来源:作者)
3.剧情失踪
这是最终的绘图,有助于创建显示缺失数据的表格和图表。
plot_missing(df)
缺失数据(来源:作者)
在这里,我们研究了 Dataprep 创建的报告,它对 EDA 非常有帮助,我们还创建了不同的图来理解数据并分析其属性。
继续尝试使用不同的数据集,并创建 EDA 报告和图来执行数据分析。如果您发现任何困难,请在回复部分告诉我。
本文是与 Piyush Ingale 合作的。
在你走之前
感谢 的阅读!如果你想与我取得联系,请随时通过 hmix13@gmail.com 联系我或我的 LinkedIn 个人资料 。可以查看我的Github*简介针对不同的数据科学项目和包教程。还有,随意探索* 我的简介 ,阅读我写过的与数据科学相关的不同文章。
Apache Airflow 中的电子邮件自动化:操作指南
原文:https://towardsdatascience.com/automating-emails-in-apache-airflow-a-how-to-guide-1d2330a29d1e?source=collection_archive---------4-----------------------
实践教程
编写一个单步 DAG 以使用 Python 的 SMTP 库、Gmail 和 Apache Airflow 自动化电子邮件的简单演练
由布雷特·乔丹在 Unsplash 上拍摄的照片
作为一名数据工程师,我做的一些工作包括定期从第三方来源为组织中的各个团队自动提取数据。尽管我倾向于认为员工总是能够意识到新的数据拉取何时发生(哈!),我不能指望他们每次都记得。正因为如此, Apache Airflow 是一项出色的服务,可以在数据管道完成和新数据集处理完毕时,向相关方发送电子邮件提醒。
Airflow 不仅出色地协调了数据拉取本身,而且与 Python 库(如 SMTP)配合得很好,便于将电子邮件传输给适当的收件人。
在下面的快速指南中,我将带您在 Apache Airflow 中建立您的第一个有向无环图(DAG ),它编排了这个电子邮件自动化流程!
先决条件#1:对 Apache 气流有基本的了解
如果您不知道什么是 Apache Airflow,可以先通读下面的资源,以便更好地理解它的一些用例。
- 气流官方文档:https://air flow . Apache . org/docs/Apache-air flow/stable/index . html
- 一篇关于气流的好中帖:https://Medium . com/swlh/Apache-air flow-in-5-minutes-c 005 B4 b 11 b 26
主要是,您需要对任务、操作符和 Airflow 的文件结构有一个基本的了解。
先决条件#2:配置您的 Gmail 帐户以使用 Python 的 SMTP 库
此外,使用 SMTP 的 Python 中的电子邮件自动化依赖于正确配置的发件人电子邮件地址。虽然可以使用许多不同的电子邮件提供商,但我发现 Gmail 让这变得非常容易。
为了让发件人的电子邮件正确地使用 SMTP 和 Python,您需要按照这里的说明https://realpython.com/python-send-email/(在选项 1:设置 Gmail 开发帐户下)。这应该是一个很快的步骤,你需要将其中一个安全设置更改为“ 允许不太安全的应用程序到”。
当这两个先决条件都满足时,您将需要着手在本地机器上安装气流(如果您还没有这样做的话)。
气流安装
如果/当你对气流感到舒适,你会想确保它安装在本地。如果您在这个过程中需要一些帮助,这里有一些本地安装的入门指南:
- 在 Mac 上安装:https://arpitrana . medium . com/install-air flow-on-Mac OS-guide-fc 66399 b2a9e
- 通过 Docker 安装:https://medium . com/@ itun predictable/Apache-air flow-on-Docker-for-complete-初学者-cf76cf7b2c9a
- Windows 10 上的安装:https://medium . com/@ ryanroline/installing-Apache-air flow-on-Windows-10-5247 aa 1249 ef
简单地说,如果你计划在 Windows 上安装 Airflow(没有 Docker),你需要创建一个 Linux 子系统。以上指南中的说明应该会有所帮助,但是可能需要对您的本地设置进行一些配置才能使其工作。
运行气流
一旦你安装了 Airflow,并且很好地掌握了软件本身,我们就可以开始了。
如果您还没有启动 web 服务器,请在终端窗口中运行以下命令:
*airflow webserver*
此外,您可以在单独的终端窗口中启动气流调度程序:
*airflow scheduler*
然后,您应该能够导航到 http://localhost:8080 (或者您为本地 web 服务器配置的任何端点),并找到您的 UI。
为了避免与其他帖子重复,并减少文章的长度,我不会详细介绍上传 Dag。最后,当您启动 web 服务器时,如果您的目录和环境结构正确,您应该看到您的 Dag 加载到 UI 中。如果你第一次启动你的网络服务器,如果你在你的airflow.cfg
文件中配置了这个选项,你可能会在用户界面中看到一些样例 Dag。
现在,随着 web 服务器在您的本地机器上运行,我们可以创建将发送电子邮件的 DAG。为了帮助指导你完成这个过程,我在 GitHub 上发布了我的 DAG 文件:
【https://github.com/zachalexander/airflow-medium-post】T4
请随意克隆存储库并同时完成这项工作,或者通读下面的指南,然后使用代码将其集成到您的 Dag 中!
重要提示:对于那些已经经常使用 Airflow 的人来说,由于 DAG 文件只包含一些函数,所以您可以将这些函数集成到您已经设置好的任何管道中(并将其作为任务添加)。但是,出于本演练的目的,为了简单起见,我将把它创建为一个单独的单步 dag。
创建 DAG
要创建我们的电子邮件自动化 DAG,我们可以导航到您的 Airflow 项目中的 dags 文件夹,它的结构应该类似于我的 GitHub repo。您可以使用我现有的“email_automation.py”文件,也可以创建自己的空白 python 文件。目录结构的示例如下:
*airflow
dags/ **email_automation.py***
在这个 python 文件中,您可以在顶部添加以下导入:
*from airflow import DAG
from airflow.operators.python_operator import PythonOperator
from datetime import timedelta
import smtplib, ssl
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart*
第一个导入允许在 Airflow 中使用 DAG 功能,第二个导入允许使用 Airflow 的 Python 操作符,稍后我们将使用它来启动电子邮件。导入timedelta
将帮助我们在 DAG 运行时间过长时调整超时间隔(气流最佳实践)。然后,我们将导入一些电子邮件和 SMTP 库,它们对于将电子邮件发送给我们的收件人是必不可少的。
在这之后,我们可以添加我们的第一个函数声明,它被命名为send_email_basic()
:
*def send_email_basic(sender, receiver, email_subject):port = 465 # For SSL
smtp_server = "smtp.gmail.com"
sender_email = sender # Enter your address
receiver_email = receiver # Enter receiver address
password = 'env variable' # Enter your gmail passwordemail_html = """
<html>
<body>
<p>Hello!</p>
<p>Add any text you'd like to the body of the e-mail here!</p> <br>
</body>
</html>
"""message = MIMEMultipart("multipart")# Turn these into plain/html MIMEText objectspart2 = MIMEText(email_html, "html")# Add HTML/plain-text parts to MIMEMultipart message
# The email client will try to render the last part firstmessage.attach(part2)
message["Subject"] = email_subject
message["From"] = sender_email## iterating through the receiver listfor i, val in enumerate(receiver):
message["To"] = val
context = ssl.create_default_context()with smtplib.SMTP_SSL(smtp_server, port, context=context) as server:
server.login(sender_email, password)
server.sendmail(sender_email, receiver_email, message.as_string())*
在这项职能中,我们要做几件事:
- 我们正在识别 SSL 端口
- 识别 SMTP 服务器
- 将发件人和收件人地址以及发件人的电子邮件密码存储在变量中。
- 为电子邮件正文创建一个包含自定义 html 的文本字符串,并将其保存到一个变量中
- 将电子邮件标识为“多部分”电子邮件,并将正文文本附加到我们的电子邮件中
- 将“主题”和“发件人”参数附加到邮件中
- 遍历我们的收件人列表(在电子邮件有多个收件人的情况下),以添加到消息的“to”参数中
- 连接到我们的服务器,发送带有消息参数“收件人”、“发件人”、“主题”和“消息”的电子邮件。
虽然看起来有很多,但是函数调用非常简单。想了解更多关于上述电子邮件术语的信息,请点击这里阅读这个过程:https://realpython.com/python-send-email/(和上面的文章一样,把你的 Gmail 账户设置成一个合适的发件人)。
接下来,我们可以声明我们的下一个函数:
*def init_email():sender = "yourgmailaddress@gmail.com" # add the sender gmail address hererecipients = ["email address 1", "email address 2"] # add your e-mail recipients heresubject = "Subject Line" # add the subject of the e-mail you'd like heresend_email_basic(sender, recipients, subject)*
我们的 Python 操作者将使用这个函数init_email()
来触发我们的电子邮件。下面是对上述情况的分析:
- 我们将我们的发件人地址(即您将用来发送电子邮件的 Gmail 地址)保存在发件人变量中
- 我们将收件人地址作为列表保存在 recipients 变量中。在这里,因为我们已经在前面的函数中设置了一个遍历这个列表的方法,所以我们可以在这里的列表中列出我们的电子邮件地址。
- 我们正在为主题行创建文本,并将其保存到主题变量中
- 最后,我们将把这些变量作为参数添加到初始的
send_email_basic()
函数中
最后,我们可以设置我们的气流语法来初始化这个 DAG 并添加所需的参数:
*default_args = {
'owner': 'airflow',
'depends_on_past': False,
'start_date': 'trigger date',
'email': ['your Airflow email'],
'email_on_failure': True,
'email_on_retry': True,
'retries': 0
}dag = DAG('email_automation',
default_args=default_args,
dagrun_timeout=timedelta(minutes=5),
# schedule_interval = '0 13 * * 1', # if you want to set up an automation schedule you can do that here
catchup=False
)t1 = PythonOperator(
task_id='send_email',
python_callable=init_email,
dag=dag
)t1*
我们正在做以下工作:
- 为 DAG 创建默认参数,类似于气流文档。
- 创建我们的 DAG(),将其命名为
email_automation
。 - 使用 PythonOperator()创建任务,调用我们的
init_email
python 函数。 - 给我们的任务是
t1
。
一旦这一切准备就绪,你的 DAG 文件应该都设置好了!通过运行:
*airflow init db*
现在,您应该能够看到一个新的 dag 作为 email_automation 加载进来。
带有正确加载的 email _ automation DAG | Image by author 的气流用户界面
为您自己的使用情形定制此 DAG
如果你已经做到了这一步,那么恭喜你!有了这个 DAG 示例,您现在可以做许多不同的事情:
- 如果您想真正实现自动化,可以每隔一段时间(例如每天、每周等)向收件人发送一封电子邮件。),您可以在上面的 DAG 中取消注释“schedule_interval”语法。关于如何为这段代码创建语法的更多信息可以在 这里 找到。
- 此外,您可以通过调整“email_html”变量文本来编辑电子邮件正文。
- 正如我在开篇中提到的,我已经将这个 DAG 中的这些函数作为一个更大的管道中的任务来使用。例如,我在数据拉取的末尾添加了一个电子邮件任务,向接收者发送通知,告知新数据已经加载,新文件已经创建,等等。假设您可以自定义电子邮件正文语言,您可以添加到最终数据源的链接,以及关于管道实例本身的任何其他重要信息。
最后,Apache Airflow 帮助数据工程师自动化了很多事情!我希望这个演练是一个有用的演示,展示了如何有效地使用 SMTP 库和 Python 来使电子邮件自动化成为一项简单的任务!
感谢阅读!如果您喜欢这篇文章,请随意访问我的其他文章,在那里我讨论了我从事的其他数据工程、数据科学和数据可视化项目。
此外,请查看我的投资组合:【zach-alexander.com】。
使用 QuickDA 自动化探索性数据分析
原文:https://towardsdatascience.com/automating-exploratory-data-analysis-using-quickda-fd68ad8e3873?source=collection_archive---------26-----------------------
使用 QuickDA 预处理和操作数据
照片由UX在 Unsplash 上拍摄
探索性数据分析由不同的部分组成,如可视化数据模式、分析统计属性、预处理数据等。这个过程大约占项目总时间的 30%,但是这个问题可以通过自动化探索性数据分析来解决。
自动化探索性数据分析可以节省大量时间和精力,因为现在我们不必为每个可视化或统计分析编写代码。自动化过程还将生成所有可视化和数据分析的报告。类似地,对于其他预处理,我们可以使用单行代码。但是如何自动化这个过程呢?
QuickDA 就是这个问题的答案。它是一个开源的 python 库,用于探索性的数据分析和数据操作。它易于使用,只需一行代码就可以执行操作。
在本文中,我们将探索 QuickDA 提供的一些功能。
让我们开始吧…
安装所需的库
我们将从使用 pip 安装 QuickDA 开始。下面给出的命令可以做到这一点。
!pip install quickda
导入所需的库
在这一步中,我们将导入执行探索性数据分析所需的库。
from quickda.explore_data import *
from quickda.clean_data import *
from quickda.explore_numeric import *
from quickda.explore_categoric import *
from quickda.explore_numeric_categoric import *
from quickda.explore_time_series import *
import pandas as pd
加载数据集
我在这里使用的数据集是著名的糖尿病数据集,可以从网上下载,你也可以使用任何其他数据集。
df = pd.read_csv("Diabetes.csv")
df
来源:作者
探索统计属性
在这一步中,我们将使用 QuickDA 的 explore 功能来分析数据的统计属性。
explore(df)
统计属性(来源:作者)
EDA 报告
在这里,我们将在后端使用 Pandas Profiling 生成一个 EDA 报告。
explore(df, method='profile', report_name='Report')
EDA 报告(来源:作者)
数据预处理
在这一步中,我们将对数据进行一些预处理。所有这些函数都是单行代码。
- 栏目名称标准化
df = clean(df, method='standardize')
df
来源:作者
2。删除列
df = clean(df, method='dropcols', columns="skinthickness")
df
来源:作者
3。移除重复行
df = clean(df, method='duplicates')
4。填写缺失数据
df = clean(df, method='fillmissing')
继续尝试不同的数据集,并使用 QuickDA 执行上述所有操作。如果您发现任何困难,请在回复部分告诉我。
本文是与 Piyush Ingale 合作完成的。
在你走之前
感谢 的阅读!如果你想与我取得联系,请随时通过 hmix13@gmail.com 联系我或我的 LinkedIn 个人资料 。可以查看我的Github*简介针对不同的数据科学项目和包教程。还有,随意探索* 我的简介 ,阅读我写过的与数据科学相关的不同文章。
自动调整 Keras 模型的超参数
原文:https://towardsdatascience.com/automating-hyperparameter-tuning-of-keras-model-4fe69b8dedee?source=collection_archive---------46-----------------------
Hyperas 在 Keras 模型超参数调整中的应用
由乌列尔 SC 在 Unsplash 上拍摄的照片
如果不能优化模型以获得良好的性能和更高的精度,那么构建模型是没有用的。一般来说,建模比优化模型需要的时间少,因为在优化或调整模型期间,您需要寻找最佳参数,这是一个耗时的过程。
我们可以自动执行这一过程,找出超参数的最佳值,并获得 Keras 模型的最高精度。在这篇文章中,我们将讨论 Hyperas ,这是一个开源的 python 包,用于自动化 Keras 模型超参数调整的过程。
让我们开始吧……
安装 Hyperas
像任何其他 python 库一样,我们将使用 pip 安装来安装 hyperas。在安装之前,我们需要运行一个命令,以避免在以后的阶段出现错误,确保这个命令是您在构建时运行的第一个代码。
from __future__ import print_function
!pip install hyperas
设置 Google Colab
为了运行 hyperas,我们需要更改某些设置,我们还将使用一个与我们的 collab 笔记本完全相同的文件名,即如果我的 collab 笔记本命名为 Hyperas.ipynb,那么在下面的代码中,我将使用 Hyperas.ipynb 作为文件名。
!pip install -U -q PyDrive
from pydrive.auth import GoogleAuth
from pydrive.drive import GoogleDrive
from google.colab import auth
from oauth2client.client import GoogleCredentials# Authenticate and create the PyDrive client.
auth.authenticate_user()
gauth = GoogleAuth()
gauth.credentials = GoogleCredentials.get_application_default()
drive = GoogleDrive(gauth)# Copy/download the file
fid = drive.ListFile({'q':"title='Hyperas.ipynb'"}).GetList()[0]['id']
f = drive.CreateFile({'id': fid})
f.GetContentFile('Hyperas.ipynb')
导入所需的库
接下来,我们将导入本文所需的所有依赖项。
import numpy as npfrom hyperopt import Trials, STATUS_OK, tpe
from keras.datasets import mnist
from keras.layers.core import Dense, Dropout, Activation
from keras.models import Sequential
from keras.utils import np_utilsfrom hyperas import optim
from hyperas.distributions import choice, uniform
为数据和模型创建函数
在这一步中,我们将创建两个函数,分别帮助我们加载数据和创建模型。
加载数据
def data():
(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train = x_train.reshape(60000, 784)
x_test = x_test.reshape(10000, 784)
x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train /= 255
x_test /= 255
nb_classes = 10
y_train = np_utils.to_categorical(y_train, nb_classes)
y_test = np_utils.to_categorical(y_test, nb_classes)
return x_train, y_train, x_test, y_test
创建模型
def create_model(x_train, y_train, x_test, y_test):
model = Sequential()
model.add(Dense(512, input_shape=(784,)))
model.add(Activation('relu'))
model.add(Dropout({{uniform(0, 1)}}))
model.add(Dense({{choice([256, 512, 1024])}}))
model.add(Activation({{choice(['relu', 'sigmoid'])}}))
model.add(Dropout({{uniform(0, 1)}})) if {{choice(['three', 'four'])}} == 'four':
model.add(Dense(100))model.add({{choice([Dropout(0.5), Activation('linear')])}})
model.add(Activation('relu'))model.add(Dense(10))
model.add(Activation('softmax'))model.compile(loss='categorical_crossentropy', metrics=['accuracy'],
optimizer={{choice(['rmsprop', 'adam', 'sgd'])}})result = model.fit(x_train, y_train,
batch_size={{choice([64, 128])}},
epochs=2,
verbose=2,
validation_split=0.1)
#get the highest validation accuracy of the training epochs
validation_acc = np.amax(result.history['val_accuracy'])
print('Best validation acc of epoch:', validation_acc)
return {'loss': -validation_acc, 'status': STATUS_OK, 'model': model}
找出最佳参数和精确度
这是我们将使用 hyperas 并找出最佳参数和最高精度的最后一步。
if __name__ == '__main__':
best_run, best_model = optim.minimize(model=create_model,
data=data,
algo=tpe.suggest,
max_evals=5,
trials=Trials(),
notebook_name='Hyperas')
X_train, Y_train, X_test, Y_test = data()
print("Evalutation of best performing model:")
print(best_model.evaluate(X_test, Y_test))
print("Best performing model chosen hyper-parameters:")
print(best_run)
最佳模特(来源:作者)
在这里,您可以清楚地分析 hyperas 如何显示最佳性能的超参数以及模型的准确性。这很简单,可以节省时间和精力。
试试这个,让我知道你在回复部分的经历。
本文与Piyush Ingale合作
在你走之前
感谢 的阅读!如果你想与我取得联系,请随时通过 hmix13@gmail.com 联系我或我的 LinkedIn 个人资料 。可以查看我的Github*简介针对不同的数据科学项目和包教程。还有,随意探索* 我的简介 ,阅读我写过的与数据科学相关的不同文章。
使用 Optunity 自动调整超参数
原文:https://towardsdatascience.com/automating-hyperparameter-tuning-with-optunity-e5576807f41e?source=collection_archive---------40-----------------------
利用 Optunity 进行 ML 模型的超参数优化
沙哈达特·拉赫曼在 Unsplash 上拍摄的照片
超参数调整对于任何模型都是一项重要的任务,无论是机器学习还是深度学习,因为它不仅有助于优化模型,而且有助于获得更高的精度和更好的性能。
有不同的 Python 库有助于超参数优化,但是大多数都很耗时或者效率不高。Optunity 是一个开源 Python 库,有助于自动化超参数调优过程。
在本文中,我们将探索 Optunity 提供的一些功能。
让我们开始吧…
安装所需的库
我们将从使用 pip 安装 Optunity 库开始。下面给出的命令可以做到这一点。
!pip install optunity
导入所需的库
在这一步中,我们将导入加载数据集、创建模型和查找最佳超参数所需的库。
import optunity
import optunity.metrics
import numpy as np
# importing machine learning models
from sklearn.neighbors import KNeighborsClassifier
from sklearn.svm import SVC
from sklearn.naive_bayes import GaussianNB
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_digits
正在加载数据集
对于本文,我们将使用 Sklearn 中预定义的 Digits 数据集。
digits = load_digits()
n = digits.data.shape[0]positive_digit = 3
negative_digit = 9positive_idx = [i for i in range(n) if digits.target[i] == positive_digit]
negative_idx = [i for i in range(n) if digits.target[i] == negative_digit]
定义模型
在这一步中,我们将定义一个函数,它将包含我们将在本文中使用的所有模型。
def train_svm(data, labels, kernel, C, gamma, degree, coef0):
"""A generic SVM training function, with arguments based on the chosen kernel."""
if kernel == 'linear':
model = SVC(kernel=kernel, C=C)
elif kernel == 'poly':
model = SVC(kernel=kernel, C=C, degree=degree, coef0=coef0)
elif kernel == 'rbf':
model = SVC(kernel=kernel, C=C, gamma=gamma)
else:
raise ArgumentError("Unknown kernel function: %s" % kernel)
model.fit(data, labels)
return model
定义模型后,我们将相应地定义超参数及其值。
search = {'algorithm': {'k-nn': {'n_neighbors': [1, 5]},
'SVM': {'kernel': {'linear': {'C': [0, 2]},
'rbf': {'gamma': [0, 1], 'C': [0, 10]},
'poly': {'degree': [2, 5], 'C': [0, 50], 'coef0': [0, 1]}
}
},
'naive-bayes': None,
'random-forest': {'n_estimators': [10, 30],
'max_features': [5, 20]}
}
}
之后,我们将定义性能函数,该函数将相应地测量所有模型的性能。
@optunity.cross_validated(x=data, y=labels, num_folds=5)
def performance(x_train, y_train, x_test, y_test,
algorithm, n_neighbors=None, n_estimators=None, max_features=None,
kernel=None, C=None, gamma=None, degree=None, coef0=None):
# fit the model
if algorithm == 'k-nn':
model = KNeighborsClassifier(n_neighbors=int(n_neighbors))
model.fit(x_train, y_train)
elif algorithm == 'SVM':
model = train_svm(x_train, y_train, kernel, C, gamma, degree, coef0)
elif algorithm == 'naive-bayes':
model = GaussianNB()
model.fit(x_train, y_train)
elif algorithm == 'random-forest':
model = RandomForestClassifier(n_estimators=int(n_estimators),
max_features=int(max_features))
model.fit(x_train, y_train)
else:
raise ArgumentError('Unknown algorithm: %s' % algorithm)# predict the test set
if algorithm == 'SVM':
predictions = model.decision_function(x_test)
else:
predictions = model.predict_proba(x_test)[:, 1]return optunity.metrics.roc_auc(y_test, predictions, positive=True)
寻找表演
现在,我们将使用性能函数来查找我们定义的不同模型的性能。
performance(algorithm='k-nn', n_neighbors=3)
`资料来源:作者
接下来,我们将找到最佳配置。
optimal_configuration, info, _ = optunity.maximize_structured(performance,
search_space=search,
num_evals=300)
print(optimal_configuration)
print(info.optimum)
来源:作者
寻找最佳解决方案
在这一步中,我们将找出具有最佳超参数的数据集的最佳解决方案。
solution = dict([(k, v) for k, v in optimal_configuration.items() if v is not None])
print('Solution\n========')
print("\n".join(map(lambda x: "%s \t %s" % (x[0], str(x[1])), solution.items())))
来源:作者
在这里,您可以清楚地看到,性能最好的算法是 SVM 算法,超参数的值也是由 optunity 提供的。
继续使用不同的数据集进行尝试,并找到该数据的最佳模型和最佳超参数。如果您发现任何困难,请在回复部分告诉我。
本文是与 Piyush Ingale 合作的。
在你走之前
感谢 的阅读!如果你想与我取得联系,请随时通过 hmix13@gmail.com 联系我或我的 LinkedIn 个人资料 。可以查看我的Github*简介针对不同的数据科学项目和包教程。还有,随意探索* 我的简介 ,阅读我写过的与数据科学相关的不同文章。
自动化机器学习模型优化
原文:https://towardsdatascience.com/automating-machine-learning-model-optimization-5dd6119b0a86?source=collection_archive---------29-----------------------
使用贝叶斯调整和强盗进行机器学习
亨特·哈里特在 Unsplash 上的照片
创建机器学习模型是一项艰巨的任务,因为我们需要建立一个最适合我们数据的模型,并且我们可以优化以获得更好的性能和准确性。一般来说,建立机器学习模型很容易,但找出最佳参数和优化是一个耗时的过程。
有一些库/包可以让你自动完成这个过程,毫不费力地制作机器学习模型。我们可以使用这些软件包来为我们的数据选择最佳模型以及模型的最佳参数。
在本文中,我们将讨论贝叶斯调整和 BTB,它用于选择和超参数调整最佳模型,以解决给定的机器学习问题。我们将探索为机器学习的 BTB 提供的不同功能。
让我们开始吧…
安装所需的库
在本文中,我们将使用 Google Colab。让我们使用下面给出的命令安装所需的库,即 BTB
!pip install baytune
导入所需的库
在这一步,我们将导入所有需要的库,如 sklearn、btb 等。
from sklearn.datasets import load_breast_cancer
from sklearn.linear_model import SGDClassifier
from sklearn.metrics import f1_score, make_scorer
from sklearn.model_selection import cross_val_score
from sklearn.tree import DecisionTreeClassifier, ExtraTreeClassifier
from btb.tuning import Tunable
from btb.tuning import hyperparams as hp
from btb import BTBSession
加载数据集和定义模型
接下来,我们将从 sklearn 导入著名的乳腺癌数据集,我们还将定义一个字典,其中包含我们需要的不同模型的名称。
dataset = load_breast_cancer()
models = {
'DTC': DecisionTreeClassifier,
'SGDC': SGDClassifier,
'ETC': ExtraTreeClassifier,
}
计算不同模型的分数
定义模型名称后,接下来我们将创建一个函数,用于计算不同模型的得分。我们将使用该函数来比较不同模型的得分。
def scoring_function(model_name, hyperparameter_values):
model_class = models[model_name]
model_instance = model_class(**hyperparameter_values)
scores = cross_val_score( estimator=model_instance,
X=dataset.data,y=dataset.target,
scoring=make_scorer(f1_score, average='macro'))
return scores.mean()
定义可调超参数
在这一步中,我们将定义要调整的超参数,我们将为不同的模型提供不同的超参数。
tunables = {
'DTC': Tunable({
'max_depth': hp.IntHyperParam(min=3, max=200),
'min_samples_split': hp.FloatHyperParam(min=0.01, max=1)
}),
'ETC': Tunable({
'max_depth': hp.IntHyperParam(min=3, max=200),
'min_samples_split': hp.FloatHyperParam(min=0.01, max=1)
}),
'SGDC': Tunable({
'max_iter': hp.IntHyperParam(min=1, max=5000, default=1000),
'tol': hp.FloatHyperParam(min=1e-3, max=1, default=1e-3),
}),
}
创建 BTB 会话
现在,这是最后一步,我们将通过传递可调超参数和上面定义的评分函数来创建一个 BTB 会话,以找出哪个模型最适合我们的数据。
session = BTBSession(
tunables=tunables,
scorer=scoring_function
)
现在,在定义了会话之后,我们将通过传递我们想要的迭代次数来运行这个会话。
best_proposal = session.run(20)
现在我们将打印出结果,它是一个字典,包含最佳模型的名称以及该模型的最佳超参数值。
best_proposal
最佳模特(来源:作者)
这就是如何使用 BTB 来选择具有最佳超参数值的最佳性能机器学习模型。继续尝试不同的数据集,并让我知道您在回复部分的评论。
本文是与 Piyush Ingale 合作完成的。
在你走之前
感谢 的阅读!如果你想与我取得联系,请随时在 hmix13@gmail.com 上联系我或我的 LinkedIn 个人资料 。可以查看我的Github*简介针对不同的数据科学项目和包教程。还有,随意探索* 我的简介 ,阅读我写过的与数据科学相关的不同文章。
自动化机器学习建模
原文:https://towardsdatascience.com/automating-machine-learning-modelling-62aac2081e3f?source=collection_archive---------28-----------------------
使用 MLBox 创建高度优化的机器学习模型
马库斯·温克勒在 Unsplash 上的照片
创建机器学习模型并不是一项困难的任务,因为 Python 提供了大量的库,可以帮助创建与回归、分类等问题相关的模型。像 Sklearn Statsmodel 这样的 Python 包可以用来创建这些模型,但困难的部分是优化和概括这些模型,以便它们也可以处理看不见的数据。
换句话说,单独创建一个机器学习模型并不能解决问题,我们还应该能够调整这些模型的超参数,使其通用化,并实现更高的性能和精度。有大量的机器学习模型,我们可以从中选择最适合我们数据集的模型,但这是一个耗时的过程,因为我们需要为每个算法编写代码和训练模型。类似地,如果我们能够选择模型,那么我们需要选择模型的最佳超参数,这也是一个耗时的过程。
因此,为了减少这些过程中花费的精力和时间,我们可以使用 MLBox 实现自动化。它是一个开源 python 库,用于自动化机器学习过程,包括特征选择、超参数优化、创建模型以及使用该模型生成预测。
在本文中,我们将探索 MLBox 提供的一些功能。
让我们开始吧…
安装所需的库
我们将从使用 pip 安装 MLBox 开始。下面给出的命令可以做到这一点。
!pip install mlbox
导入所需的库
在这一步,我们将导入自动化机器学习过程所需的库。
from mlbox.preprocessing import *
from mlbox.optimisation import *
from mlbox.prediction import *
正在加载数据集
对于本文,我们将使用著名的糖尿病数据集,这是一个分类问题。我已经将数据分为测试和训练两个不同的电子表格。这个数据集的目标变量是“结果”。
paths = ["/content/train.csv","/content/test.csv"]
target_name = "Outcome"
在此之后,我们将使用读取器读取数据,并测试火车分割数据。
rd = Reader(sep = ",")
df = rd.train_test_split(paths, target_name)
来源:作者
这里您可以看到,在拆分数据的同时,它还对数据进行了清理和预处理。
创建模型
接下来,我们将定义优化器以及我们将为此数据集考虑的模型。
#Defining Optimiser
opt = Optimiser(scoring = "accuracy", n_folds = 5)#Defining the model
space = {
'est__strategy':{"search":"choice","space":["LightGBM"]},'est__n_estimators':{"search":"choice","space":[150]},'est__colsample_bytree':{"search":"uniform","space":[0.8,0.95]},'est__subsample':{"search":"uniform","space":[0.8,0.95]},'est__max_depth':{"search":"choice","space":[5,6,7,8,9]},'est__learning_rate':{"search":"choice","space":[0.07]}
}
params = opt.optimise(space, df,15)
来源:作者
在这里,您可以清楚地看到 MLBox 使用 LightGBM 模型为此数据集导出的最佳超参数。
特征重要性
在这一步中,我们将根据我们创建的模型找出该数据集最重要的特征。
prd = Predictor()
prd.fit_predict(params, df)
来源:作者
在这里,您可以清楚地看到数据集最重要的特征。
继续用不同的数据集尝试这种方法,并自动化机器学习的过程。如果您发现任何困难,请在回复部分告诉我。
本文是与 Piyush Ingale 合作完成的。
在你走之前
感谢 的阅读!如果你想与我取得联系,请随时联系我在 hmix13@gmail.com 或我的 LinkedIn 简介 。可以查看我的Github*简介针对不同的数据科学项目和包教程。还有,随意探索* 我的简介 ,阅读我写过的与数据科学相关的不同文章。
自动化机器学习管道
原文:https://towardsdatascience.com/automating-machine-learning-pipeline-edcf74e869a4?source=collection_archive---------31-----------------------
使用模型搜索实现机器学习自动化
由 Unsplash 上的 Pietro Jeng 拍摄
创建机器学习模型是一项艰巨的任务,因为我们需要编写大量代码来尝试不同的模型,并找出针对特定问题的执行模型。有不同的库可以自动化这一过程,以找出性能最佳的机器学习模型,但它们也需要一些编码。
如果我告诉你,我们可以运行多种 AutoML 算法,在单个代码单元中找出分类问题的最佳模型架构,会怎么样?模型搜索有助于实现分类问题的 AutoML。它运行多种 ML 算法并相互比较。它创建了一个搜索空间,我们可以在其中定制我们想要的神经网络层的类型。
Model Search 是一个开源的 Python 库,它提供了一种轻松的方法来运行多个 AutoML 并找出最佳的一个。这是非常有用的省时省力的工作。
在本文中,我们将探索模型搜索及其一些功能。
让我们开始吧…
安装所需的库
我们将从使用 pip 安装来安装模型搜索开始。下面给出的命令将使用 pip 安装模型搜索。
!git clone [https://github.com/google/model_search.git](https://github.com/google/model_search.git)
%cd /content/model_search/
导入所需的库
在此步骤中,我们将导入创建模型所需的所有库,并训练模型以找到最佳模型。
import model_search
from model_search import constants
from model_search import single_trainer
from model_search.data import csv_data
创建模型
现在我们将直接创建模型。我们将使用已经存储在模型搜索中的 CSV 数据。为了创建模型,我们只需传递所有必需的参数并开始训练。
trainer = single_trainer.SingleTrainer(
data=csv_data.Provider(
label_index=0,
logits_dimension=2,
record_defaults=[0, 0, 0, 0],
filename="model_search/data/testdata/csv_random_data.csv"),
spec='/content/model_search/model_search/configs/dnn_config.pbtxt')trainer.try_models(
number_models=200,
train_steps=1000,
eval_steps=100,
root_dir="/tmp/run_example",
batch_size=32,
experiment_name="example",
experiment_owner="model_search_user")
模型训练(来源:作者)
正如我们在这里看到的,模型正在接受训练。现在我们还可以打印最佳模型及其参数。
!ls /tmp/run_example/tuner-1/
产出(来源:作者)
这里你可以看到表现最好的模型。所有模型文件都保存在本地计算机的 run_example 文件夹中。继续尝试不同的数据集,创建不同的模型,并让我知道您在回复部分的评论。
本文是与皮尤什·英格尔合作完成的。
在你走之前
感谢 的阅读!如果你想与我取得联系,请随时通过 hmix13@gmail.com 联系我或我的 LinkedIn 个人资料 。可以查看我的Github*简介针对不同的数据科学项目和包教程。还有,随意探索* 我的简介 ,阅读我写过的与数据科学相关的不同文章。
使用 FLAML 实现机器学习自动化
原文:https://towardsdatascience.com/automating-machine-learning-using-flaml-46400b94a6b3?source=collection_archive---------11-----------------------
使用 FLAML 实现机器学习过程的自动化
由 Unsplash 上的 Pietro Jeng 拍摄
机器学习是一个过程,在这个过程中,我们试图使用一套不同的算法来解决现实生活中的商业问题。创建机器学习模型很容易,但选择哪个模型在泛化和性能方面最适合我们的数据是一项困难的任务。
回归和分类都有各种各样的机器学习算法。这些可以根据我们试图解决的问题的类型来选择,但是这是一个需要很高的计算成本、时间和努力的过程。有不同的 Python 库提供了一个选项来自动高效地选择最佳机器学习模型的过程,其中一个这样的库是 FLAML。
FLAML 是一个轻量级开源 Python 库,有助于自动、高效、经济地找出最佳的机器学习模型。它既快又省时,而且设计轻巧。
在本文中,我们将探索 FLAML 及其功能。
让我们开始吧…
安装所需的库
我们将从使用 pip 安装来安装 FLAML 开始。下面给出的命令将使用 pip 安装 FLAML。
pip install flaml
导入所需的库
在这一步中,我们将导入创建机器学习模型和下载数据集所需的所有库。
from flaml import AutoML
解决分类问题
现在我们将从解决一个分类问题开始。我们将在这里使用的数据是著名的 Iris 数据集,可以很容易地从 Seaborn 库中加载。让我们开始创建模型。
#Loading the Dataset
from sklearn.datasets import load_iris
为 Automl 创建实例很重要,定义 Automl 设置也很重要,因此在这一步中,我们还将创建 Automl 实例并定义设置。
automl = AutoML()automl_settings = {
"time_budget": 10, # in seconds
"metric": 'accuracy',
"task": 'classification'
}
接下来,我们将拆分数据负载,并将其放入模型中。最后,我们还将使用模型进行预测,并找到最佳模型。
X_train, y_train = load_iris(return_X_y=True)
# Train with labeled input data
automl.fit(X_train=X_train, y_train=y_train,
**automl_settings)print(automl.predict_proba(X_train).shape)
# Export the best model
print(automl.model)
模型(来源:作者)
在这里,我们可以清楚地看到,额外的树估计量是这个数据的最佳模型。现在让我们打印出模型的最佳超参数和精确度。
print('Best ML leaner:', automl.best_estimator)
print('Best hyperparmeter config:', automl.best_config)
print('Best accuracy on validation data: {0:.4g}'.format(1-automl.best_loss))
print('Training duration of best run: {0:.4g} s'.format(automl.best_config_train_time))
最佳模特(来源:作者)
同样,对于回归问题,我们也将遵循相同的过程。
解决回归问题
现在我们将解决一个回归问题。我们将在这里使用的数据是著名的波士顿数据集,可以很容易地从 Seaborn 库中加载。我们可以遵循与分类问题完全相同的过程。
from sklearn.datasets import load_boston
automl = AutoML()
automl_settings = {
"time_budget": 10, # in seconds
"metric": 'r2',
"task": 'regression'
}
X_train, y_train = load_boston(return_X_y=True)
# Train with labeled input data
automl.fit(X_train=X_train, y_train=y_train,
**automl_settings)
# Predict
print(automl.predict(X_train).shape)
# Export the best model
print(automl.model)
模型(来源:作者)
print('Best ML leaner:', automl.best_estimator)
print('Best hyperparmeter config:', automl.best_config)
print('Best accuracy on validation data: {0:.4g}'.format(1-automl.best_loss))
print('Training duration of best run: {0:.4g} s'.format(automl.best_config_train_time))
最佳模特(来源:作者)
在这里,我们可以清楚地看到回归问题的最佳模型和超参数。
同样,您可以对您的数据集执行此过程,并为您的问题找到最佳模型和超参数。尝试使用不同的数据集,并在回复部分告诉我您的意见。
本文是与 Piyush Ingale 合作完成的。
在你走之前
感谢 的阅读!如果你想与我取得联系,请随时联系我在 hmix13@gmail.com 或我的 LinkedIn 简介 。可以查看我的Github*简介针对不同的数据科学项目和包教程。还有,随意探索* 我的简介 ,阅读我写过的与数据科学相关的不同文章。
使用 Python 和 HTML5 自动化标记
原文:https://towardsdatascience.com/automating-markup-with-python-and-html5-9054362e87ce?source=collection_archive---------32-----------------------
使用原始 Python 处理 HTML5 非常容易,以便从字典数据创建 web 友好的表格。
(src =https://unsplash.com/photos/0qE0qZ7_3eY
介绍
IPython 笔记本在 Python 的奇妙世界和超文本标记的世界之间建立了一座急需的桥梁。虽然在此之前,通过利用诸如网页之类的东西来利用 Python 的某些标记特性是完全可能的,但是随着 IPython 笔记本和 IPython 模块的普及,看到这两种语言一起工作来实现某个目标已经变得更加常见了。
标记的伟大之处在于,在某种程度上,它只是一组被解析的表达式,用来指示解析器需要在屏幕上显示什么。这意味着基本上任何编程语言都可以创建它,并解码它。元编程是一个术语,主要用于做同样的事情,但是有表达式和求值,然而我认为在很多方面,将编程语言与标记结合起来的行为与元编程非常相似。
笔记本
数据表
在现代 Python 编程世界中,HTML5 的一个非常常见的应用是 IPython 笔记本内部的显示。这通常是用 HTML5 或 Javascript 完成的。这两种方法都有各自的优点,比如交互性和简单性,但是不管怎样,能够做出一些非常有用的东西是非常好的,比如在 Python 笔记本中显示数据表的方法。
有趣的是,我最初在 Julia 语言中编写了这个算法,以便使用 data frames . JL。data frames . JL 有一个众所周知的可怕的显示输出,这是由它背后的大量软件包提供的,以便提供该功能。我决定用一个扩展来改变我自己安装的 DataFrames.jl,这个扩展可以用更具表现力的 HTML 输出来显示数据帧。如果你想看看我在字典上的实现,你可以看看 OddFrames.jl,这是一个在 Julia 中处理数据的包:
现在,我们将编写一个新的算法,将 Python 中的一些字典数据解析成 HTML5 表。
编写我们的函数
在深入研究这个函数之前,我们首先需要评估的是输入和输出。首先,需要注意的是,我们很可能想要使用某种显示方法,而不是常规的返回。这是因为如果我们排除这个调用,HTML5 可能会以字符串的形式返回,而不是显示出来。根据我的经验,我估计 IPython 的 display()函数可能是最适合使用的解决方案。然而,在围绕一个函数构建某些东西之前测试它的功能总是很棒的,所以让我们尝试使用这种方法显示一些 HTML,看看我们得到了什么:
from IPython.display import display
注意,这个函数包含在同名的模块中。这一点很重要,因为很容易不小心说
from IPython import display
然后不小心调用了一个模块作为函数。现在让我们在一点 HTML 上试试这个函数:
display("<h1>Header</h1>")
作者图片
这正是为什么先测试一下是个好主意的原因。然而,在模块内部还有一个 HTML 类型,它在其构造函数中接受一个字符串。我猜 display 方法也可以接受这个 HTML 类型,以便实际返回 HTML,因为现在它认为它只是在处理一个字符串。
from IPython.display import display, HTML
display(HTML("<h1>Header</h1>"))
作者图片
既然我们已经确定有一个可靠的方法来显示我们的 HTML,我们可以假设函数的输出步骤已经完成。现在让我们考虑位置参数形式的输入。首先,当然,我们需要一本字典。对于本例,我将调用该查找。如果我们最终得到一个非常长的数据表,我们可能不希望显示所有的数据,所以我们应该添加另一个参数来决定我们的数据表要打印多少行。所有这些给了我们一个函数定义,看起来像这样:
def show_dict(lookup : dict, count : int = 5):
由于这种情况下的大部分工作都是字符串连接,我们需要做的第一件事就是创建一个字符串。在这个特殊的例子中,我们将创建一个保存字典中的键的表头和一个保存字典中的值的表体。表头是用 HTML5 中的标签做的。我们还将添加一个标签,因为头部只有一行。对于表体,我们将把它作为一个字符串设置到标签中。
def show_dict(lookup : dict, count : int = 5):
thead = "<thead><tr>"
tbody = "<tbody>"
接下来,我们将使用 dict.keys()函数遍历字典中的键。这将从我们的字典中返回一个有序的键列表。对于这个列表中的每个迭代,我们将使用表头标签添加一个新的表头。在标签之间,我们将放入在这个迭代循环中循环的每个名字。我将把“str”类型转换到这些键上,以防它们被存储为不同的数据类型,以避免任何方法错误的问题。总结一下我的意思,如果我们不事先将这个类型转换成字符串,就有可能出现“没有方法匹配字符串(str,不支持的类型,str)”的错误。也就是说,如果字符串构造函数不能首先转换我们的类型,那么添加这个构造函数基本上是没有用的。
for name in lookup.keys():
thead = str(thead, "<th>", str(name), "</th>")
现在,我们将通过添加我们的和标签的结尾来结束我们的 head 标签,这两个标签是相同的,只是添加了一个斜杠,有点像正则表达式中的反斜杠:
thead = string(thead, "</tr></thead>")
现在,我们实际上可以尝试一下这个功能,看看头部的显示器实际上是否工作。当然,我们首先需要添加 IPython.display.display()调用。
def show_dict(lookup : dict, count : int = 5):
thead = "<thead><tr>"
tbody = "<tbody>"
for name in lookup.keys():
thead = str(thead, "<th>", str(name), "</th>")thead = str(thead, "</tr></thead>")
display(HTML(thead))
我们来试试吧!
lookup = dict({"A": [5, 10, 15, 20], "B": [5, 10, 15, 20]})
show_dict(lookup)
(图片由作者提供)
使用多种语言的问题是。
在 Python 中,我们实际上不需要强制转换这种类型,我们可以使用+运算符来连接字符串。我来自编程的函数世界,我认为这很有趣也很酷,因为这些字符串是完整的类,而不仅仅是保存数据的简单结构。让我们改用加法运算符:
def show_dict(lookup : dict, count : int = 5):
thead = "<thead><tr>"
tbody = "<tbody>"
for name in lookup.keys():
thead = thead + "<th>" + str(name) + "</th>" thead = thead + "</tr></thead>"
display(HTML(thead))
作者图片
添加正文
至于表的主体,我们将从使用 dict.values()函数提取值开始,就像我们使用 dict.keys()函数一样。
cols = lookup.values()
鉴于前面的操作,很容易想象我们下一步需要做什么。我们当然会迭代地创建新的表行。为了做到这一点,我们不打算像上次一样循环遍历我们的新值集。这是因为我们将按顺序创建每个标记,所以如果我们要遍历这些值,我们将遍历一个特征的所有观察值,而不是遍历行。换句话说,我们需要水平填充,而不是垂直填充。考虑到这一点,我们将在迭代中使用一个范围生成器。这将允许我们为每一行调用附加 for 循环中的每个观察。当然,我们不希望这调用特征的长度,而是我们希望调用第一个特征的长度,因为否则我们将得到特征计数而不是观察计数。
for i in range(1, len(cols[0])):
现在,我们将使用另一个迭代循环将我们的工作限制在我们的一行特征上:
for i in range(1, len(cols[0])):
obs = [row[i] for row in cols]
现在,我们将在 for 循环中为此行开始一个新的行标记:
tbody = tbody + "<tr>"
现在我们将遍历行内的值,并将它们添加到我们的 tbody 中的标签之间:
for observ in obs:
tbody = tbody + "<td>" + observ + "</td>"
最后,我们将使用之前开始的标记结束该行:
tbody = tbody + "</tr>"
现在,整个循环应该看起来像这样:
for i in range(1, len(cols[0])):
obs = [row[i] for row in cols]
tbody = tbody + "<tr>"
for observ in obs:
tbody = tbody + "<td>" + observ + "</td>"
tbody = tbody + "</tr>"
在这个循环之后,我们将关闭 tbody 标记:
tbody = tbody + "</tbody>"
最后,我们将组合 thead 和 tbody,然后使用 display 函数和 HTML 构造函数来显示结果:
composition = str(thead + tbody)
display(HTML(composition))
现在我们的函数应该看起来有点像这样:
def show_dict(lookup : dict, count : int = 5):
thead = "<thead><tr>"
tbody = "<tbody>"
for name in lookup.keys():
thead = thead + "<th>" + str(name) + "</th>"
thead = thead + "</tr></thead>"
cols = lookup.values()
for i in range(1, len(cols[0])):
obs = [row[i] for row in cols]
tbody = tbody + "<tr>"
for observ in obs:
tbody = tbody + "<td>" + observ + "</td>"
tbody = tbody + "</tr>"
tbody = tbody + "</tbody>"
composition = str(thead + tbody)
display(HTML(composition))
现在让我们试着在字典上使用这个函数:
show_dict(lookup)
作者图片
这是一个问题。
奇怪的是,似乎字典键和值都有一个单独的类。为了避免遇到这个问题,我们需要创建一种新的方法来提取没有 values()函数的值,或者找出一种方法来重新转换我们的类型。我选择了前者,因为我们已经将键放入了一个列表中,要创建这样一个列表,循环遍历这个列表是相当简单的。
cols = [lookup[name] for name in lookup.keys()]
现在我们的新函数看起来像这样:
def show_dict(lookup : dict, count : int = 5):
thead = "<thead><tr>"
tbody = "<tbody>"
for name in lookup.keys():
thead = thead + "<th>" + str(name) + "</th>"
thead = thead + "</tr></thead>"
cols = [lookup[name] for name in lookup.keys()]
for i in range(1, len(cols[0])):
obs = [row[i] for row in cols]
tbody = tbody + "<tr>"
for observ in obs:
tbody = tbody + "<td>" + observ + "</td>"
tbody = tbody + "</tr>"
tbody = tbody + "</tbody>"
composition = str(thead + tbody)
display(HTML(composition))
让我们看看这个解决方案是否可行!
show_dict(lookup)
作者图片
有趣的是,我可能已经做了我之前警告过的事情,但是这是一个类型错误而不是方法错误。这可能是 Julia 的一个方法错误,所以这就是错误的来源,你每天都会学到新的东西!
def show_dict(lookup : dict, count : int = 5):
thead = "<thead><tr>"
tbody = "<tbody>"
for name in lookup.keys():
thead = thead + "<th>" + str(name) + "</th>"
thead = thead + "</tr></thead>"
cols = [lookup[name] for name in lookup.keys()]
for i in range(1, len(cols[0])):
obs = [row[i] for row in cols]
tbody = tbody + "<tr>"
for observ in obs:
tbody = tbody + "<td>" + str(observ) + "</td>"
tbody = tbody + "</tr>"
tbody = tbody + "</tbody>"
composition = str(thead + tbody)
display(HTML(composition))show_dict(lookup)
作者图片
成功了!
您可能已经注意到列表是[5,10,15,20],换句话说,第一个值从行中删除了。发生这种情况的原因是因为我使用 1 作为我们的范围生成器的开始,因为 Python 的索引从 0 开始。回到指责我的错误是因为习惯了 Julia,Julia 从 1 开始它的索引,就像 Mathematica 一样。如果我们将其更改为 0,我们会看到现在所有的值都已填充:
作者图片
结论
在我看来,这是相当有趣的编程练习!将文本连接在一起制作一个微型网页不仅很酷,而且如果没有一千个更好的实现的话,这段代码可能会很有用。也就是说,不管它是否有用,我确实认为在这里检查代码,并在 Python 中使用这样的算法是有价值的!这是我们的最后一个函数,正如我之前讨论的那样,范围生成器发生了改变:
def show_dict(lookup : dict, count : int = 5):
thead = "<thead><tr>"
tbody = "<tbody>"
for name in lookup.keys():
thead = thead + "<th>" + str(name) + "</th>"
thead = thead + "</tr></thead>"
cols = [lookup[name] for name in lookup.keys()]
for i in range(0, len(cols[0])):
obs = [row[i] for row in cols]
tbody = tbody + "<tr>"
for observ in obs:
tbody = tbody + "<td>" + str(observ) + "</td>"
tbody = tbody + "</tr>"
tbody = tbody + "</tbody>"
composition = str(thead + tbody)
display(HTML(composition))
希望这是一种有趣的方式来提高一些循环技巧,并发现一些关于 Python 编程语言的更有趣的事情。谢谢你的阅读,它对我来说意味着整个世界!
使用 Selenium 和 Heroku 自动处理日常的基于 Web 的任务
原文:https://towardsdatascience.com/automating-mundane-web-based-tasks-with-selenium-and-heroku-715a2f1ec35e?source=collection_archive---------30-----------------------
用简单的方法自动化掉那些不断重复的任务
在 Unsplash 上 Magnet.me 拍照
手头的任务
作为一个狂热的跑步者和数据爱好者,我自然喜欢记录我的训练。几年前我确定的解决方案是在 Strava 和 Attackpoint 上记录我的培训。虽然这两个平台都提供使用 GPS 数据跟踪锻炼的服务,但 Strava 强调的是社交网络,它允许你以深入的方式查看每个活动,这是 Attackpoint 所缺乏的;另一方面,Attackpoint 更简单,我个人更喜欢把它作为我训练的一个整体(以周/月/年为时间尺度)。
左边的斯特拉瓦和右边的攻击点。作者图片
然而,我的一个问题是,我总是努力保持这两个日志是最新的。Garmin(我的跑步手表的制造商)通过 API 与两个网站同步,所以我的跑步神奇地出现在两个网站上,所以问题不在于我的跑步只出现在一个网站上。我的问题是保持两个网站都有运行记录/描述是一件乏味的事情。我倾向于总是保持 Strava 的最新状态,并在我感到烦恼的时候在 Attackpoint 上浏览帖子。那么,为什么不把我对这些网站的承诺问题自动化呢?
任务:每次我在 Strava 上跑步并写下关于它的描述,然后把它添加到 Attackpoint 上相应的跑步帖子中。
游戏计划
所以我有了一个为什么,剩下的就是找出方法。选择从 Strava 到 Attackpoint,而不是相反,是一个简单的选择。首先,Strava 使用起来更好,其次,该网站更现代、更灵活、更别致,因此编写代码来发布内容并与之交互虽然可行,但会更具挑战性。那么我实际上是怎么做的呢?
输入硒。Selenium 是一个 Python 包,用于启动和控制 web 浏览器。它能够在这个浏览器中填写表格和模拟鼠标点击。一个关于 Selenium 的优秀教程,我用的比较多,可以在这里找到:https://towardsdatascience . com/controlling-the-web-with-python-6 fceb 22 C5 f 08。
有了这些东西,我发现写下行动计划总是好的;无论是在纸上还是在你的电脑上,这完全取决于个人喜好,我倾向于用纸。当事情不可避免地出错时,我往往最终会严重偏离最初的计划,但不管怎样,我发现写下最初的想法/想法会让我思路清晰,给我方向感。
因此,下面是我选择自动执行这项任务的大致轮廓:
-
调用 Strava API 来获取我最近跑步的惟一 id 的有序列表。这原本不在计划中,但是由于增加的复杂性(例如,我的许多 runs 组运行,html 在这里变得棘手),从 Strava 获得我的活动+相应的时间顺序信息比我最初想象的要困难得多。有了这些 id,提取信息就更容易了。
-
使用 Selenium 登录 Strava,导航到“您的活动”选项卡,检索与每个唯一活动 ID 对应的跑步信息。正如您在下面的代码中看到的,Selenium 非常容易使用,因为它非常直观。下面的代码是一个大概的框架,完整的代码+注释可以在我的 Github 页面找到。
-
现在我们有了我最近的所有活动(按照完成的顺序!)以及活动细节:时间、标题、描述、距离和速度。现在剩下要做的就是将标题和描述添加到我的 Attackpoint 页面,尽管还有一些小的微妙之处。首先,如果任何活动已经有了描述,我不想再去管它们。其次,如果任何 Strava 标题是默认的,即没有被改变,我也想离开岗位,因为我还没有得到周围命名 Strava 运行。和以前一样,为了清楚起见,省略了一些代码细节。
我们完成了,如果我在终端中运行 attackpointSelenium.py,它会将任何缺失的描述添加到我的攻击点中!
使自动装置完全自动化
显然,一天运行一行代码一两次太费力了,所以剩下要做的最后一件事就是把代码部署到网上的某个地方,这样我就完全置身事外了。遵循这个优秀的教程,我能够将我的代码部署到 Heroku 并对其进行调度,以便我的代码检查我的攻击点是否需要每 10 分钟更新一次!最棒的是,它完全免费。
TL;DR 编写了代码,自动将信息从一个网站发布到另一个网站的相应部分。
代号:https://github.com/jackmleitch/strava2ap
感谢阅读,我希望你喜欢它。这里有一些你可能感兴趣的我的其他故事…
** **
使用预提交挂钩自动化 Python 工作流
原文:https://towardsdatascience.com/automating-python-workflows-with-pre-commit-hooks-e5ef8e8d50bb?source=collection_archive---------28-----------------------
什么是预提交钩子,它们如何给你的 Python 项目带来好处
unsplash.com上维沙尔·贾达夫的照片
像大多数版本控制系统(VCS)一样,Git 具有运行脚本和在特定点触发动作的能力。这些脚本被称为钩子,它们可以驻留在客户端或服务器端。服务器端挂钩通常在接收到推送之前或之后触发,而客户端挂钩通常在提交或合并之前触发。有许多钩子类型可以用来执行特定的动作来服务于您的工作流。
在本文中,我们将探讨预提交挂钩,这是在客户端执行的特定操作。我们将讨论它们的用途,以及在 Python 项目的工作流中需要考虑触发哪些特定操作。最后,我们将探索一种在创建提交时绕过预提交挂钩的快速方法。
什么是预提交挂钩?
顾名思义,预提交挂钩是在创建提交之前触发的特定操作。预提交挂钩通常用于检查您的代码,确保它符合某些标准。例如,您可以启用预提交挂钩,以便验证提交内容的代码风格是否符合 PEP-8 风格指南。
现在,执行的每个预提交钩子都返回一个状态代码,任何非零代码都将中止提交,关于失败的钩子的详细信息将报告给用户。
开发团队同意并共享适当的预提交挂钩是很重要的,因为它们有助于确保源代码的一致性和高质量。此外,预提交挂钩可以提高开发速度,因为开发人员可以使用它们来触发某些操作,否则,这些操作将需要手动重复执行。
如何安装和启用预提交挂钩
首先,确保您已经启用了虚拟环境。一旦完成,您就可以开始安装pre-commit
到pip
:
$ pip install pre-commit
我们现在可以验证安装是否成功
$ pre-commit --version
pre-commit 2.10.1
既然我们已经成功安装了pre-commit
包,下一步就是启用期望的预提交钩子。命令行工具附带了一个方便的选项,允许我们自动生成预提交挂钩的示例配置:
$ pre-commit sample-config# See [https://pre-commit.com](https://pre-commit.com) for more information
# See [https://pre-commit.com/hooks.html](https://pre-commit.com/hooks.html) for more hooks
repos:
- repo: [https://github.com/pre-commit/pre-commit-hooks](https://github.com/pre-commit/pre-commit-hooks)
rev: v3.2.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files
示例配置带有 4 个不同的预提交挂钩;
这个钩子从每一行的末尾开始修剪所有的空白。如果出于某种原因,您希望修剪额外的字符,您可以指定以下参数:args: [--chars,"<chars to trim>"]
。举个例子,
hooks:
- id: trailing-whitespace
args: [--chars,"<chars to trim>"]
- id: end-of-file-fixer
**end-of-file-fixer**
:这个钩子确保所有文件都以一个换行符结束,并且只有一个换行符。
**check-yaml**
:这个钩子将尝试加载所有 yaml 文件并验证它们的语法
**check-added-large-files**
:最后,这个钩子将防止非常大的文件被提交。默认情况下,任何超过 500Kb 的文件都将被视为大文件。您可以通过提供以下参数来修改大小:
hooks:
- id: check-added-large-files
args: [--maxkb=10000]
既然我们已经探索了一些基本的预提交挂钩,那么是时候看看它们的实际应用了。我们需要做的是将这些钩子添加到一个名为.pre-commit-config.yaml
的文件中。在这个例子中,我们将使用我们之前已经研究过的示例配置。为此,只需运行以下命令:
$ pre-commit sample-config > .pre-commit-config.yaml
现在,验证示例配置是否已成功添加到 yaml 文件中:
$ cat .pre-commit-config.yaml# See [https://pre-commit.com](https://pre-commit.com) for more information
# See [https://pre-commit.com/hooks.html](https://pre-commit.com/hooks.html) for more hooks
repos:
- repo: [https://github.com/pre-commit/pre-commit-hooks](https://github.com/pre-commit/pre-commit-hooks)
rev: v3.2.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files
最后,我们需要安装文件中的钩子。以下命令将自动解析.pre-commit-config.yaml
的内容并安装所有定义的钩子:
$ pre-commit install --install-hooks
注意,默认情况下,pre-commit
会在目录.git/hooks/pre-commit
下安装目标钩子。如果一切按计划进行,您应该会看到下面的输出
pre-commit installed at .git/hooks/pre-commit
[INFO] Initializing environment for [https://github.com/pre-commit/pre-commit-hooks](https://github.com/pre-commit/pre-commit-hooks).
[INFO] Installing environment for [https://github.com/pre-commit/pre-commit-hooks](https://github.com/pre-commit/pre-commit-hooks).
[INFO] Once installed this environment will be reused.
[INFO] This may take a few minutes...
现在,让我们提交我们所做的更改,并在我们的 Git 存储库上添加预提交挂钩。
$ git add .pre-commit-config.yaml
$ git commit -m "Added pre-commit hooks in the repo"
一旦执行了git commit
命令,预提交钩子将在创建新提交之前运行所有指定和安装的检查。
Trim Trailing Whitespace............................................Passed
Fix End of Files......................................Passed
Check Yaml............................................Passed
Check for added large files...........................Passed
[main f3f6caa] Test pre-commit hooks
1 file changed, 10 insertions(+)
create mode 100644 .pre-commit-config.yaml
正如我们所见,pre-commit
钩子已经运行了所有 4 个已定义的钩子,并且它们都通过了。因此,新的提交将被成功创建,现在您可以git push
对您的远程存储库进行更改了。请注意,如果至少有一个pre-commit
挂钩失败,提交的创建将会失败,您将会被告知哪些挂钩失败了。此外,它将尝试解决问题(如果可能)。如果这是不可能的,你将不得不作出必要的修改,并重新提交。
例如,假设我们的.pre-commit-config.yaml
文件在最后有额外的新行。pre-commit
挂钩将失败,并自动为您解决问题:
Trim Trailing Whitespace............................Passed
Fix End of Files....................................Failed
- hook id: end-of-file-fixer
- exit code: 1
- files were modified by this hookFixing .pre-commit-config.yamlCheck Yaml.........................................Passed
Check for added large files........................Passed
现在问题已经解决了,你要做的就是再次git commit
,最后git push
。
哪些预提交挂钩用于 Python 项目
根据您想要实现的具体目标,您需要在创建提交之前触发某些操作。然而,在开发 Python 应用程序时,有几个必备的预提交钩子将使您的生活变得更加容易。
首先,让我们定义适合大多数 Python 应用程序的pre-commit-config.yaml
文件。请注意,我认为示例配置的 4 个预提交挂钩非常重要,所以我也要包括它们。
# .pre-commit-config.yaml# See [https://pre-commit.com](https://pre-commit.com) for more information
# See [https://pre-commit.com/hooks.html](https://pre-commit.com/hooks.html) for more hooks
repos:
- repo: [https://github.com/pre-commit/pre-commit-hooks](https://github.com/pre-commit/pre-commit-hooks)
rev: v3.2.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files
args: [--maxkb=10000]
- id: double-quote-string-fixer
- id: mixed-line-ending
args: [--fix=lf]
- id: check-ast
- id: debug-statements
- id: check-merge-conflict
- repo: [https://github.com/pre-commit/mirrors-autopep8](https://github.com/pre-commit/mirrors-autopep8)
rev: v1.4
hooks:
- id: autopep8
我们已经讨论了前四个钩子,它们是我们在上一节中探索的示例配置的一部分。现在让我们探索文件中剩余的钩子。
**double-quote-string-fixer**
:这个钩子,将在适用的地方用单引号('
)代替双引号("
)。当需要双引号的时候(比如说my_string = "Hello 'World'"
),这个钩子不会代替它们
**mixed-line-ending**
:该挂钩将检查混合行尾,并可选择用 CRLF(回车线)和 LF 替换行尾。在我们的例子中,我们显式地指定了--fix
选项,以便钩子强制用 LF 替换行尾。
**check-ast**
:这个钩子将检查以.py
结尾的文件是否解析为有效的 Python。
**debug-statements**
:这个钩子将检查所有以.py
结尾的文件中的调试器导入。对于 Python 3.7+来说,它还将验证在源代码中没有提到breakpoint()
。
**check-merge-conflict**
:这将检查包含合并冲突字符串的文件。
**autopep8**
:最后,这个钩子会自动格式化所有以.py
结尾的文件,以符合 PEP-8 样式指南。
有关所有可用挂钩的更多详细信息,您可以参考本页。
如何在不创建提交的情况下运行提交前挂钩
如果出于某种原因,您想运行pre-commit
钩子而不创建提交,您所要做的就是运行下面的命令
$ pre-commit run --all-files
这个命令将验证您的存储库的所有文件是否都符合预提交挂钩所施加的限制。如果一切都符合标准,您应该会看到以下输出
Trim Trailing Whitespace.............................Passed
Fix End of Files.....................................Passed
Check Yaml...........................................Passed
Check for added large files..........................Passed
如何绕过预提交挂钩
在某些时候,你可能希望做一个git commit
并绕过预提交钩子执行的检查。这可以通过提供--no-verify
选项来实现:
git commit -m "Bypassing pre-commit hooks" --no-verify
结论
在本文中,我们探讨了预提交挂钩的重要性,以及它们如何使开发团队受益,以便他们能够维护满足特定标准的高质量代码。预提交挂钩可以通过自动化工作流中的某些操作来帮助您节省时间。此外,我们讨论了如何在您的本地机器上安装预提交钩子,以及启用哪些特定的钩子,以使您在开发 Python 应用程序时更加轻松。
使用 Python 自动提交表单
原文:https://towardsdatascience.com/automating-submission-forms-with-python-94459353b03e?source=collection_archive---------3-----------------------
照片由格伦·卡斯滕斯-彼得斯在 Unsplash 拍摄
永远不要再填写提交表单
不用再填表格了
填写在线表格很烦人。然而,许多从事案头工作的人有时仍然不得不花相当多的时间填写在线表格。那么,为什么不使用 Python 来自动化这个过程并节省一些宝贵的时间呢?
在本文中,我将向您展示如何使用 Python 来自动化填写提交表单的过程。
如果你喜欢视频,请点击这里查看我的 Youtube 视频:
台阶
对于这个例子,我将创建一个简单的 google forms 调查,然后我将检查它以收集执行自动化所需的必要 web 元素。
总体步骤将是:
- 将您的答案设置为. csv 文件
- 根据输入类型检查必要的网页元素
- 设置网址和浏览器
- 访问网址
- 发送基于文本输入的按键
- 发送复选框类型输入的点击
- 访问并点击提交按钮完成
- 循环访问数据库并为每个用户提交答案
1.将您的答案设置为. csv 文件
为了简单起见,我在 google forms 上创建的表单由三个简单的问题组成:
- 你叫什么名字?
- 你多大了?
- 你最喜欢什么颜色?
我知道我知道…非常原始,但这只是为了演示的目的,所以对我来说是赤裸裸的。实际的形式如下所示:
作者图片
现在,让我们建立一个. csv 文件来存储我们的答案。我将使用faker
库、numpy.rando.randint()
方法和熊猫来模拟一个简单的名字、年龄和颜色选择的数据库,作为最终的数据帧。
from selenium import webdriver
import pandas as pd
import time
import json
from datetime import datetime
import pathlib
import glob
import sys
sys.path.append(".")
import faker
import numpy as np
import pandas as pd
f = faker.Faker()
colors = ["Blue","Pink","Black","White","Green"]
names = [f.name() for _ in range(100)]
ages = [np.random.randint(18,65) for _ in range(100)]
color_choices = [np.random.choice(colors,1)[0] for _ in range(100)]
database = pd.DataFrame(dict(names=names, ages=ages, colors = color_choices))
database.to_csv("submission_form_database.csv", index=False)
database.head()
作者图片
完美!现在我们有了数据库,让我们设置浏览器自动化。
2.根据输入类型检查必要的 web 元素
现在,我只需进入我的 google 表单的预览链接,或真实案例调查的实际网址,并根据输入类型收集不同问题的类别名称。
在这种情况下,我有三个问题,其中两个是基于文本的,一个是多选的,所以我通过按下CTRL+Shift+I
检查问题中的每个元素,如果你在 chrome 中,然后转到:copy -> copy element
,在那里我复制每个问题的元素,看起来应该是这样的:
- 问题 1 和 2 的 Web 元素:
<input type="text" class="quantumWizTextinputPaperinputInput exportInput" jsname="YPqjbf" autocomplete="off" tabindex="0" aria-labelledby="i1" aria-describedby="i2 i3" required="" dir="auto" data-initial-dir="auto" data-initial-value="">
- 问题 3 的 Web 元素(多选)
<div class="appsMaterialWizToggleRadiogroupOffRadio exportOuterCircle"><div class="appsMaterialWizToggleRadiogroupOnRadio exportInnerCircle"></div></div>
现在,我只是复制每种类型的类名,并把它和提交按钮的xpath
一起设置为两个不同的变量:
text_question_element_class = "quantumWizTextinputPaperinputInput"
checkbox_question_element_class = "appsMaterialWizToggleRadiogroupOffRadio"
submit_element_class = '//*[@id="mG61Hd"]/div[2]/div/div[3]/div[1]/div/div/span/span'
太好了,现在我们已经为自动化部分做好了准备!
3.设置网址和浏览器
url = "https://forms.gle/WY7E9N8wkiMtziTD9"
driver = webdriver.Chrome(executable_path="./chromedriver")
这里,我们只是为提交表单的 url 和浏览器设置了变量,在我的例子中是 Google Chrome。要使用它,你需要下载 chromedriver,你可以在这里找到。
4.访问网址
driver.get(url)
5.为基于文本的输入发送按键
现在,我们编写一个函数,通过使用提供的 element 类来回答基于文本的问题。这个函数将把数据帧、类名、用户 ID 和控制浏览器的驱动程序作为输入,并提交适当的答案。
def answerNameAge(driver, df, element_class, user_id):
name = df["names"][user_id]
age = df["ages"][user_id]
text_answers = [name, str(age)] # following the order in the form
text_questions = driver.find_elements_by_class_name(element_class)
for a,q in zip(text_answers,text_questions):
q.send_keys(a)
return driver
6.发送复选框输入的点击
现在,我们设置函数来填充复选框问题,对于这个问题,我们需要一个字典来匹配颜色和它们在表单中的相应顺序。
color_index_dict = {"Blue": 0, "Pink": 1, "Black": 2, "White": 3, "Green": 4}
def answerCheckBox(driver, df, element_class, user_id):
color_answer = df["colors"][user_id]
color_answer_index = color_index_dict[color_answer]
driver.find_elements_by_class_name(element_class)[color_answer_index].click()
return driver
太好了,现在我们要做的就是提交表单!
7.访问并单击提交按钮完成
在这里,我们只编写一个简单的函数来访问之前获得的提交按钮的xpath
并单击它。
def submit(driver, element_class):
driver.find_element_by_xpath(element_class).click()
return driver
搞定了。现在,我们遍历数据库并提交每个用户的答案。
8.遍历数据库并提交每个用户的答案
让我们在包含数据的数据帧上创建一个简单的循环,然后一个接一个地提交答案。
df = pd.read_csv("./submission_form_database.csv")
text_question_element_class = "quantumWizTextinputPaperinputInput"
checkbox_question_element_class = "appsMaterialWizToggleRadiogroupOffRadio"
url = "https://forms.gle/WY7E9N8wkiMtziTD9"
driver = webdriver.Chrome(executable_path="./chromedriver")
for user_id in range(len(df)):
driver.get(url)
driver.maximize_window()
driver = answerNameAge(driver, df, text_question_element_class, user_id)
driver = answerCheckBox(driver, df, checkbox_question_element_class, user_id)
driver = submit(driver, submit_element_class)
我们做到了,我们自动化了提交多个表单的枯燥过程!在我的谷歌表单回复统计页面上,我现在看到了这个:
作者图片
这对于经常发现自己填写具有相似结构的在线表单的个人,以及从事案头工作并必须为客户或其组织中的人员执行这些类型的提交的人来说可能是有用的。
为什么要自动化?
我们在网上做的任何可重复的任务都应该自动化,这样我们就可以只关注重要的事情。当试图检测可自动化的任务时,一件有用的事情是问:我是否定期这样做?它是否涉及可重复的过程,很少或没有涉及明智的决策?如果两个问题的答案都是肯定的,那么你应该自动完成这个任务。
在本文中,您了解了:
- 如何使用 Python 的
selenium
框架来自动化填写提交表单(如 google forms)的过程 - 自动化提交表单包括:用表单的数据建立一个数据框架,从所需的 web 地址检查 web 元素以了解如何导航在线表单,编写一个函数来回答基于输入类型的问题,编写一个简单的函数来点击相关的按钮,如提交按钮
如果你喜欢这篇文章,请在 Twitter 、 LinkedIn 、 Instagram 上联系我,并在 Medium 上关注我。谢谢,下次再见!😃
使用 AWS Textract,Lambda & DynamoDB 自动进行文本提取和数据预处理
原文:https://towardsdatascience.com/automating-text-extraction-and-data-preprocessing-using-aws-textract-lambda-dynamodb-e3de318d9122?source=collection_archive---------7-----------------------
自动化是关键。任何时候,只要有一项耗时或手动的任务可以轻松地自动化,您就应该这样做。
数据科学家工作最重要的部分之一是自动化流程,这可以减轻耗时任务的负担,让您有时间处理更重要的事情。在本教程中,我们将介绍一个用于自动化文档文本提取的端到端 AWS 解决方案。我们将原始的和非结构化的文档组织起来进行解析。
自动文本提取过程的流程图。图片作者。
目录:
- 创建两个 S3 桶
- 创建一个 Textract Lambda 函数& IAM 角色
- 创建一个 DynamoDB 表
- 创建一个 DynamoDB Lambda 函数& IAM 角色
- 结论
1-创建两个 S3 存储桶:
您需要创建两个 S3 存储桶,一个作为输入存储桶,另一个作为输出存储桶。您可以很容易地将这两者合并到一个桶中,但是,递归对于类似这样的 lambda 过程可能是有问题的——因此,在本教程中,我们将使用两个桶的解决方案。
图片是来自 AWS 的屏幕截图。
当您创建此项目所需的资源时,请确保指定的区域保持不变。如果您为 S3 时段选择“us-east-2 ”,则所有其它资源也需要这样做。导航到 S3 控制台并单击“创建存储桶”,创建一个新的存储桶。您可以将这个存储桶命名为您想要的任何名称,但是,建议您坚持特定的命名约定——在我们的例子中,它将是“s3-json-input-bucket”。
图片是来自 AWS 的屏幕截图。
一旦完成,您应该看到您的两个 S3 桶列在 S3 AWS 控制台下。
2-创建 Textract Lambda 函数和 IAM 角色:
有了 S3 桶,让我们继续创建我们的 Lambda 函数。在 AWS 中导航到 Lambda 控制台,然后单击“创建函数”。
图片是来自 AWS 的屏幕截图。
选择“使用蓝图”选项,搜索“蓝图名称:s3-get-object-python”。单击“配置”,以便我们可以编辑一些设置。
图片是来自 AWS 的屏幕截图。
继续输入一个函数名。最佳实践是根据 lambda 函数的用途来标记它。在这种情况下,我们将调用函数“textract-s3-to-json-function”。接下来,为名为“textract-s3-to-json-role”的函数创建一个新角色。命名的一致性有助于您在单独工作时记住每个资源的用途,或者有助于其他人在团队工作时轻松完成项目。在页面底部,选择感兴趣的特定 S3 存储桶——在我们的示例中,这将是我们之前创建的 s3-json-input-bucket”。我们将使用此输入区作为新 pdf 的“放置区”。一旦文件被放入,lambda 函数将被触发以触发 Textract 脚本。
图片是来自 AWS 的屏幕截图。
您可以通过前缀(即仅查看特定目录中的文件)或后缀(即仅查看以.结尾的文件)来限制将应用此功能的文件。pdf)。这些是可选参数,如果需要,可以在以后添加。接下来,点击“创建函数”。
我们将使用 Boto——AWS 官方 python SDK——将该功能连接到我们的其他 AWS 资源。为了让这个 SDK 在我们的 Lambda 函数中工作,我们需要将它作为一个层上传。在屏幕的左侧,从菜单中选择“创建图层”。
图片是来自 AWS 的屏幕截图。
图片是来自 AWS 的屏幕截图。
通过上传一个可以从我的 Github 中获取的 zip 文件来创建一个层。这将允许该函数使用 Boto。上传后,点击“创建”。导航回 lambda 函数,在屏幕底部,点击“添加层”。
图片是来自 AWS 的屏幕截图。
图片是来自 AWS 的屏幕截图。
在代码部分,继续用我的 GitHub 文件中的代码替换代码。这个代码片段将在第一个 S3 桶中接收任何传入的文档,通过 AWS textract 运行它们,然后将它们写回到第二个 S3 桶中。注意,这个 Github 文件中有两个字段需要替换:
- ARN 的角色(见于第 27 行)。
- 输出桶名(第 111 行)。
您可以用在第一步中选择的存储桶名称替换输出存储桶名称。但是,ARN 角色需要替换为写在 IAM 控制台角色页面顶部的 ARN 角色。这将确保该功能可以使用与角色相关联的适当权限。
一些 pdf 文件需要比其他文件更长的分析时间。为了确保 pdf 不会在处理过程中超时,您需要延长超时限制。文档越大,分析时间就越长——该设置高度依赖于提交的文档。
图片是来自 AWS 的屏幕截图。
完成功能设置后,我们现在可以编辑角色,以确保配置了所有必要的权限。在 AWS 中导航到 IAM 控制台,搜索我们之前创建的名为“textract-s3-to-json-role”的角色。
ARN 角色将在本页顶部注明,这与您之前配置 Python 代码时需要的 ARN 角色相同。
导航到权限部分,添加我们将需要的其他资源:
图片是来自 AWS 的屏幕截图。
除了已经指定的两个,我们将需要“AmazonS3FullAccess”和“AmazonDynamoDBFullAccess”。继续并附加那些策略。
在下一个名为“信任关系”的选项卡上,确保关系如下:
{
“Version”: “2012–10–17”,
“Statement”: [
{
“Effect”: “Allow”,
“Principal”: {
“Service”: “lambda.amazonaws.com”
},
“Action”: “sts:AssumeRole”
}
]
}
完成这两个步骤后,您现在可以将 pdf 文件放入“输入”桶,这将自动提取文件的文本并将它们作为 JSON 上传到“输出”桶。很漂亮吧?
3-创建一个 DynamoDB 表
完成 textract 部分后,现在让我们把注意力集中在设置表上。在 AWS 中导航 DynamoDB 控制台,并单击“创建表”。
图片是来自 AWS 的屏幕截图。
输入表名和主键。在我们的例子中,我们称主键为“id”。但是,您可以根据自己的需要,使用数据中的任何其他唯一 ID 来重命名该字段。继续并点击屏幕底部的“创建”。
图片是来自 AWS 的屏幕截图。
创建完成后,您应该会在屏幕右侧看到填充的表格。
4-创建 DynamoDB Lambda 函数和 IAM 角色:
与前面的 Lambda 函数类似,继续重复创建函数、添加 boto 层和更改相关角色的权限的相同过程。请注意,这个函数和另一个函数之间会有一些细微的差别:
- 确保相关的触发器指向输出桶。记住,这里的想法是第一个函数的输出将是第二个函数的输入。
- 确保与该函数相关的代码不会重新运行 textract,而只是获取 JSON 输出并通过 DynamoDB 运行它。从下面复制代码片段,或者从我的 GitHub 文件复制。
import json
import boto3
import os
import urllib.parse
import json
import uuid
from decimal import Decimals3_client = boto3.client(‘s3’)
dynamodb = boto3.resource(‘dynamodb’)def lambda_handler(event, context):
print(“Starting Transfer:”)
bucket = event[‘Records’][0][‘s3’][‘bucket’][‘name’]
json_file_name = urllib.parse.unquote_plus(event[‘Records’][0][‘s3’][‘object’][‘key’], encoding=’utf-8')
json_object = s3_client.get_object(Bucket = bucket, Key = json_file_name)
jsonFileReader = json_object[‘Body’].read()
jsonDict = json.loads(jsonFileReader, parse_float=Decimal)
table = dynamodb.Table(‘s3-json-textract-table’)
finalObject = jsonDict[0]
finalObject[“key”] = json_file_name
finalObject[‘id’] = str(uuid.uuid4())
table.put_item(Item = jsonDict[0])
3.最后,确保该函数的 IAM 角色包括 DynamoDB 的权限和 S3 完全访问权限。您可以通过导航到 IAM 控制台,搜索角色名称,并在权限部分下添加 DynamoDB 和 S3 来添加这些角色。
5 —结论
至此,您应该已经准备好了!当您使用 PDF 文件填充输入 S3 存储桶时,这将触发第一个 lambda 函数对您的文件应用 Textract OCR,并将 JSON 格式的输出发送到输出存储桶。一旦进入输出桶,第二个 lambda 函数将被触发,并将新创建的 JSON 文件传输到 DynamoDB。虽然本教程主要面向 PDF 文件,但 Textract 也能够处理图像。来吧,自己试试这个!
自动化圣诞鸟计数:Redux
原文:https://towardsdatascience.com/automating-the-christmas-bird-count-redux-9dd308fed225?source=collection_archive---------65-----------------------
什么有效,什么无效
作者笔下的鱼鹰
在之前的一篇文章 中,我描述了一个一年一度的观鸟活动如何自动化的愿景。随着 2020 年第 121 届圣诞鸟数的结束,让我们看看哪些可行,哪些不可行。
在这个疫情年,自动化成了这个过程中的一个必要部分。由于公共卫生命令,包括旧金山和奥克兰在内的一些地方计数被完全取消。其他的计算也可以进行,但是有一套严格的规则来确保社会距离。这也意味着许多国家积极鼓励使用 eBird 来收集数据。
这样做的一个结果是有大量的一个或两个人的团队。这给部门领导和编纂者带来了更多的工作。在不止一种情况下,这导致计数的取消。使用这个工具,合并清单变成了几分钟的任务,而不是几天。
在计数之前,我已经将我认为对计数领导者最重要的工具的工作进行了优先排序。套用老赫尔穆特·冯·毛奇的一句名言,这个计划在与敌人的接触中失败了。在投票之前和之后的日子里,软件变化很快。此时,它正在生成准确而有用的数据,并且通过现场测试得到了极大的改进。
名字
因为仅仅谈论“工具”会让人感到困惑,所以我被鼓励给整个包起一个名字。我称它为伽马射线 Corvi ,以乌鸦星座中最亮的星星命名。这不是一个不寻常的名字,如果你想象这个包的目的之一是数乌鸦 …
Gamma Corvi 概述
Gamma Corvi 中的工具目前以 Jupyter Python 笔记本的形式出现。使用的两个主要工具是服务解析和服务计数。Service-Parse 的主要任务是为计数生成一个带注释的、标准化的清单版本。这项工作是为我参与的两个项目提前完成的,这两个项目是圣荷西(CASJ)和卡莱罗-摩根山(CACR)。许多改进来自帕洛阿尔托(CAPA)和蒙特里半岛(营地)的类似工作。
CASJ 2020 标准化清单之首
第二个工具 Service-Count 有多个阶段,包括从 eBird 检索数据,为每个部门创建详细的报告,然后将这些报告合并成一个总结报告,该报告可用于将数据输入到 Audubon 官方网站供编译器使用。
合并
整个软件包的最大优势之一是能够将计数数据合并到一个主列表中,该列表是按分类学排序的。
为了进一步说明这一点,让我们看一个 FeederWatch 示例。CASJ 的主要清单有 206 个物种和变种。一组 FeederWatch 数据是通过电子邮件发送过来的。这是手动转换成一个 CSV 文件与 32 个物种和计数,没有特定的顺序。将此作为一列输入计数摘要非常繁琐:浏览摘要以找到物种,输入计数,然后继续下一个物种。
然而,当使用服务计数工具时,我们只是将 CSV 文件放在输入目录中,它被合并为一个单独的列。大获全胜。
总结报告
总结报告有六页,下面我将展示其中的一些。编译器的主要用途是汇总所有部门汇总的小计。
CASJ 2020 最终清单的一部分
每个扇区都有自己的列,添加到“总计”列中。向 Audubon 站点输入数据时,total 为零且“Category”字段不是“species”的行将被过滤掉。通常这是按‘分类顺序’排序的,但按‘NACC _ 排序 _ 顺序’排序会按奥杜邦的顺序排列。
稀有物种表显示了一些物种的快速总结,这些物种要么被编辑者明确标记为稀有,要么在主要清单中缺失。
CASJ 2020 珍奇物品单
个人详细信息表显示了计数圈内归档的每个清单的有用信息。
CASJ 2020 个别细节部分
这里的一些关键字段是地点名称、评论和 eBird 上的清单的可点击链接。
自动派对
Autoparty 不是一些涉及机动车辆的节日,它是我用来描述基于 eBird 数据自动创建聚会的名称。今年这一点非常重要,因为社交距离措施迫使许多小党派加入。
CASJ 2020 汽车派对表部分
这通过将地点 ID 和观察时间与相应清单上的人分组来创建当事人。填写党的努力和时间被大多数领导人认为是一个主要的痛点,今年更糟。Autoparty 可以提供帮助。
部门摘要
很难手工构建的部门摘要的一个特征是按地点和时间分组。
CASJ 2020 明矾岩板块概要
上图显示了这一关键特性,为了清晰起见,删除了一些列。Bill 和他的妻子 Kitty 在两个地点(L12060407 和 L12988268)观鸟。没有显示 Kitty,因为他们创建了一个共享的清单。蓝色的列显示了比尔和约翰都获得了 L370800 的情况。他们在不同的时间出现在那里,并且没有共享一个清单。前两个位置使用求和函数,因为没有重复。最后两列使用了一个 MAX 函数,因为我们想避免两次计算鸟的数量。这就引出了“总计”栏中的公式:
=SUM($I2:$Q2)+MAX($R2:$W2)
注意,我在这里隐藏了列,但是\(I 到\)Q 是所有不重复的位置,而\(R 到\)W 是用于 L370800 的。如果有更多的重复位置,那么在“总计”公式中,每个位置都有一个最大分组。
如果我们有一个好的系统来指定参与方,这可以用来为“总计”字段生成适当的公式。无论如何,这肯定是要自动化的事情,因为 CASJ 2020 的统计中包括了 198 份清单。
地图
通常,展示大量数据的最佳方式是使用图形。这可能很有启发性,但是交互式图形更好。为了全面了解每个人在哪里观鸟,我用叶子制作了一张地图。
CASJ CBC 2020 活动
这显示了 12–20–20 日加州圣何塞计数圈内 eBird 中的每个观察值。带数字的圆圈是观察的集群,点击它们可以显示出来(在地图的交互式版本中)。有几个不同的层,可以打开和关闭。
正如你在上面的地图上看到的,在常青星区有很多观察者,但是根本没有人观察贝里萨星区和卡拉维拉斯星区。
个人观察有一个带有双筒望远镜图标的标记。标记工具提示显示了观察的详细信息,并包括一个指向基本 eBird 清单的可点击链接。这篇文章是弄清楚如何让这些层正常工作的关键。
我认为这可以成为明年统计的一个很好的计划工具。
eBird 规则
科内尔最近发表了一篇文章 记录你的圣诞鸟数 。这主要描述了如何使用 eBird 进行精确计数。除了他们的建议之外,我还要补充以下几点:
- 在每一个新的地点开始一份新的清单,或者如果聚会分裂了。
- 汇编者和行业领导者应分发首选位置/热点名称列表。这使得判断多人是否在同一个地点观鸟变得更加容易。请注意,如果两个位置之间的距离在 150 米以内,代码会认为它们是相同的,因此这有所帮助。
- 物种计数不要用‘X’;而是粗略的猜测一下(10,50,100,1000 等。).我设置‘X’等于 3(一,二,多);参见*皮拉人 。*
视窗网际网路名称服务
- 手工将多个清单中的数据合并到一个主清单中是一件极其痛苦的事情。为此使用 Gamma Corvi,即使大部分数据不是来自 eBird,它本身也是值得的。
- 一位与会者说,“使用伽马射线 Corvi 节省的时间让我们能够参与另一次计数”。
- Gamma Corvi 用于提供三个计数圈的数据。对于一个 alpha 版本来说还不错。
损耗
- 可填充的 pdf 应该很容易获胜,但是人们似乎不愿意使用它们。至少,Audubon 应该使稀有鸟类表单可填充(我在 GitHub 库中有一个)。
- 其他数据(如以 CSV 文件形式提供的 FeederWatch 数据)仍涉及一些手动步骤。
- eBird 有 200 个清单的限制,这是整个县一天的清单。幸运的是,我们在这一点上勉强过关,但这一限制显然必须提高。
- 管理聚会时间和工作量的过程仍然很乏味,但是自动聚会功能很有帮助。参与者列表管理是一个需要关注的领域。
- 需要将这些代码制作成 web 服务,以便部门领导和汇编人员能够访问。例如,康奈尔大学可能希望将它放在他们的服务器上。
我最喜欢的功能
- 节省时间的合并功能
- 规划图
- 自动党表
代码和例子见 GitHub 库。我计划改进代码,并希望很快将其用于春夏计数和鸟类马拉松。
参考
*https://github.com/jhurley13/automatingcbc https://www.audubon.org/conservation/science/christmas-bird-count https://ebird.org/news/ebirding-your-christmas-bird-count-updated *
鱼网:自动鱼门铃
原文:https://towardsdatascience.com/automating-the-fish-doorbell-a668285728d6?source=collection_archive---------40-----------------------
使用机器学习和计算机视觉支持鱼类洄游
许多不同的鱼类每年都要长途跋涉才能到达它们的繁殖地。如今,由于水闸等障碍,这一旅程变得更加困难。乌特勒支的 Weerdsluis 是沿着一条受欢迎的鱼类迁徙路线设置的水闸之一。为了提高认识,与乌得勒支市共同发起了一项倡议:T2 鱼门铃。在这里,用户可以观看船闸处的实时水流,如果他们发现了一条鱼,就会“按铃”。然后锁可以打开,让任何等待的鱼通过。这个倡议很快就像病毒一样传播开来,门铃被按了超过 10 万次!
乌特勒支的 Weerdsluis,图片来自维基媒体
尽管这显然是一场提高意识的活动,但我们开始想知道是否有一种方法可以自动检测这些鱼,这样即使没有人观看溪流,它们也可以通过。我们使用图像处理方法和深度学习创建了一个解决方案。
我们的解决方案
那么我们到底如何才能检测到这些鱼呢?我们提出了一个由两步组成的解决方案:
- 使用传统的图像处理从包含运动的静止视频中提取碎片
- 使用快速简单的卷积神经网络(CNN)来确定图像块是否包含鱼。
图像处理
鱼可见的时间只占直播的一小部分。我们希望收集潜在鱼类游过的图像,并希望这些图像包含尽可能多的有用信息。
为了做到这一点,我们决定实施一种背景减法方法来检测运动并获得包含没有背景的鱼的图像块。“数据收集”一节解释了我们是如何做到这一点的。检索到的图像块然后被调整到 100x100 像素的分辨率,并被送入下一部分:CNN。
网络
该模型应该能够实时工作,以便与直播工作。我们也更喜欢网络只使用有限的训练数据。我们选择使用一个简单的 CNN 进行鱼类分类。该网络仅由两个卷积层和两个全连接层组成。由此产生的网络架构如下图所示。在一些测试中,我们发现增加更多的层并没有显著的积极效果,但是仍然有优化的空间。
通过https://bit.ly/3vlnkuU获得的网络架构
收集和注释数据
因为我们是作为监督学习任务来处理的,所以我们需要一些带注释的数据来训练我们的网络。由于游过 Weerdsluis 的鱼的公共注释数据集并不存在,我们不得不创建自己的数据集。
数据收集
我们直接从 visdeurbel.nl 读取直播,为此我们使用了 OpenCV 和从网站上提取的直播 url。使用指数加权移动平均 (EWMA),我们获得了一个移动的背景流图像,如下图左上角所示。这个背景图像不会包含快速移动的物体,如鱼,并且会随着白天的光照条件而变化。
数据收集器的快照,左上:背景图像,右上:带有边界框的视频帧,左下:阈值,右下:减去背景后的帧-作者提供的图像
接下来,我们对视频的最新帧的背景图像执行简单的数字减法,并将结果放大五倍,以获得仅包含移动对象的图像,如本视频所示。
背景减除的视频流——作者根据原始来源制作的视频
最后,我们在图像上应用过滤器并执行阈值操作,从而产生包含运动物体轮廓的遮罩。如果轮廓超过一定的大小,并且可以跟踪 20 帧,我们将保存一帧视频以及减影图像的 100×100 像素块。在仅仅 2-3 天的时间里,我们收集了超过 7000 种潜在鱼类的照片。
数据标注
因为注释成千上万的图像补丁听起来并不吸引我们,所以我们想让它尽可能简单。为此,我们编写了一个单独的脚本: annotator.py. 这个脚本加载还没有被注释的图像补丁,然后允许用户通过一次按键来标记它们。它还会统计注释的总量、当前会话中的注释量以及您每分钟的平均注释量,有时会达到每分钟 55 个以上的注释。我们区分两类:鱼(30%)和非鱼(70%)。我们也可以将图像归类为不清晰,之后在训练中忽略。我们最终注释了大约 3000 个样本,其中 2500 个是清晰的,用于我们的网络。
数据标注工具快照—图片由作者提供
训练网络
我们使用 TensorFlow 2 和 Keras 构建了网络。我们使用 Adam 作为优化器,使用二进制交叉熵损失作为损失函数。我们使用 80/20 的训练测试分割。训练网络真的很快,在普通笔记本电脑上只需要一分钟左右。我们做了一些简短的实验,看看什么样的超参数最适合我们的问题。在未来的工作中,我们希望进行更广泛的超参数优化,以获得最佳结果。
结果
下图显示了训练和测试数据集在训练时期数量上的准确度曲线。奇怪的是,测试精度曲线在 20 个时期后变平,但随着模型过度拟合,不会进一步降低。对于最佳模型,我们在大约 10 个时期后使用早期停止。
精确度曲线
这里画出了模型的损失。随着训练损失接近于 0,测试损失继续增加。我们的假设是,网络试图使训练损失尽可能接近于 0,但在这样做的过程中,预测错误的预测越来越多。这不会对准确性产生负面影响,但会增加这种预测的损失,从而增加总体测试损失。
损失曲线
这里绘制了 ROC 曲线。该模型实现了高的真阳性率(或召回率),即使是在相对低的假阳性率下。这意味着该模型能够非常频繁地检测到鱼,而当对象不是鱼时,将对象分类为鱼的机会非常低。这对于这种应用尤其重要,因为我们不希望水锁无缘无故被打开。
受试者工作特征曲线
项目的状态
我们这个项目的计划是让这个模型对鱼进行实时分类。然而,到目前为止,我们只能在同一天收集的图像块上测试该模型。当我们想用直播实现这个模型时,我们发现鱼门铃刚刚离线到 2022 年春天,我们再也不能用直播演示这个模型了。
我们希望在某个时候能够用视频数据展示这个模型的工作情况。如果是这样的话,我们一定会用我们的结果更新这篇博文。
Simon 已经为 FISH-Net v2 编制了一个主要和次要的更改列表,包括更好的背景过滤、数据收集值嵌入等。所以明年一定要收听更多。
接触
西蒙·范·伊登~ 5185734
simonvaneeden@hotmail.com
沃特·德·勒乌~ 4487753
w . f . deleeuw @ student . tudelft . nl
如需获取本项目中使用的源代码,请发送电子邮件至:simonvaneeden@hotmail.com
自动化 SageMaker Studio 自定义图像的设置
原文:https://towardsdatascience.com/automating-the-setup-of-sagemaker-studio-custom-images-4a3433fd7148?source=collection_archive---------17-----------------------
在工作室域中连续交付自定义图像的分步指南
Amazon SageMaker Studio 是一个完全集成的 IDE,它统一了管理您的 ML 项目和与您的团队成员协作所需的工具。
来源:亚马逊 SageMaker
除了为运行您的笔记本提供预建图像,SageMaker Studio 还允许您创建包含您最喜欢的库的容器,并将它们作为自定义图像附加到您的域中。
在大多数大型企业中,ML 平台管理员将管理这些自定义图像,以确保工作室用户仅使用经批准的库。如果手动完成,这可能会给管理员带来运营开销。
在这篇文章中,我将展示如何通过为您的自定义图像实现简单的连续交付来实现 Studio 域设置的自动化。
照片由拉希德在 Unsplash 上拍摄
我们将基于 Tensorflow 2.5.0 创建一个自定义图像,并将其附加到工作室域。我们将使用 CodeCommit、CodeBuild 和 CodePipeline 来连续交付定制图像。在您的环境中随意使用您选择的任何 CI/CD 工具。该堆栈打包在一个 CloudFormation 模板中,因此您可以按需重复设置。
访问将您自己的定制容器图像带到 Amazon SageMaker Studio 笔记本、 SageMaker Studio 定制图像示例和代码管道教程可能是一个好的开始,如果这些东西对您来说听起来很新的话。
演练概述
我们将分三步解决这个问题:
- 我们将首先启动一个堆栈来创建一个 CodeCommit repo、一个 CodeBuild 项目和一个 CodePipeline 管道。
- 然后,我们将把定制图像 Dockerfile、configs 和 buildspec.yaml 推入代码报告中。这将触发管道。
- 一旦映像被附加到域,我们将在 Studio 中推出一个带有自定义内核的笔记本。
先决条件
要浏览此示例,请确保您具备以下条件:
- 这是建立在 SageMaker Studio 的自定义图像功能之上的。在开始之前,确保你熟悉这个博客和那些代码样本。
- 访问亚马逊 SageMaker 工作室环境,熟悉工作室用户界面。
- 拥有自定义图像的 IAM 角色。当您运行映像时,会将权限授予该映像。例如,您可以使用您的 Studio 用户配置文件角色 arn。
- 这个 GitHub 库克隆到您的环境中
步骤 1:启动云形成堆栈
架构概述
首先,我们需要基于模板创建一个 CloudFormation 堆栈。
下面是设置的架构概述:
堆栈将创建一个 CodeCommit repo,我们将在其中推送 Dockerfile、configs 和 buildspec.yaml 。它还将创建一个 CodePipeline 管道和一个 CodeBuild 项目。CodeBuild 项目将负责执行 buildspec.yaml 文件来构建容器映像并将其推送到 ECR,并将其附加到 Studio 域。该模板还将创建基本的 SageMaker 映像和其他有用的资源,如 IAM 角色。
在您的帐户中创建堆栈
要创建堆栈,请执行以下步骤:
- 导航到 AWS CloudFormation 控制台页面。确保您是从与 SageMaker Studio 域相同的 AWS 区域执行此操作的
- 选择上传模板文件用模板创建堆栈
作者图片
- 选择下一个
作者图片
在这里,您需要为图像输入一个堆栈名称、SageMaker 工作室域 ID 和角色 ARN 。您可以让 ImageName 保持原样。
作者图片:你可以在 SageMaker Studio 控制台页面找到你的工作室 ID
- 选择下一步
- 将所有选项保留为默认,直到您到达最后一个屏幕
- 选择我承认 AWS CloudFormation 可能会创建 IAM 资源。
作者图片
- 选择创建
这需要几分钟才能完成。
Image by author:完成后,您可以将创建的 CodeCommit repo 克隆到您的环境中
步骤 2:用您的映像更新代码报告
接下来,您需要将 tf25 文件夹中的内容推送到 CodeCommit repo 中。
作者图片:这里我将代码推送到回购的主分支
以下 buildspec.yaml 将由 CodeBuild 执行:
它将运行 build_and_push.sh 根据这个 Dockerfile 将容器映像推送到 ECR,并运行 attach_image.sh 将 ECR 映像附加到 Studio。
在将映像推送到 ECR 之前,您还可以在这里运行进一步的林挺和测试。您还可以在 ECR 存储库上启用图像扫描来识别常见的漏洞。
一旦代码被推送到 repo 的主分支,您就可以导航到 CodePipeline 并看到您的管道正在运行。
几分钟后,您应该会看到您的 Studio 域更新了最新版本的自定义图像。
作者图片
从现在开始,每次你提交,Studio 都会自动获得你自定义图像的新版本。
如果您有多个自定义图像
update-domain-input . JSON是用于使用自定义映像及其配置更新您的域的配置。
在这个例子中,我运行了 attach_image.sh 中的 sagemaker update-domain 命令。如果您有多个自定义映像,您可以将域配置文件保持为全局的,并独立于各个映像管道运行更新命令。
步骤 3:在 Studio 中使用自定义图像
现在你可以在 Studio 中使用自定义图像内核
你会看到它出现在工作室启动器中,并可以用它运行你的笔记本。
我们现在可以在 SageMaker Studio 中使用 Tensorflow 2.5.0 了!
作者图片
结论
通过自定义图像,您可以在 Studio 中运行带有您最喜欢的库的笔记本。在这篇文章中,我们自动化了图像设置,这样 ML 平台管理员就可以自动创建、版本化和附加它们到一个 Studio 域。
为了进一步自动化设置,您还可以使用本博客中使用的 CloudFormation 模板创建一个服务目录产品。您还可以尝试 Lijo 的这个示例自定义图像。它允许 Studio 用户在他们的笔记本上本地运行 PySpark。
为您的 Python 项目自动化版本标签和变更日志
原文:https://towardsdatascience.com/automating-version-tags-and-changelogs-for-your-python-projects-6c46b68c7139?source=collection_archive---------17-----------------------
基于项目的提交历史,使用 commitizen 实现版本标签和变更日志自动化的实践指南
由 Yancy Min 在 Unsplash 上拍摄的照片
厌倦了跟踪您的代码变更是否保证次要或主要版本增量?太忙而不能保持一个整洁的日志?尝试使用 commitizen ,这是一个命令行实用程序,它“强迫”您按照常规提交标准(或不同的用户定义格式)编写提交消息。配置完成后,commitizen 将根据您的提交自动调整代码的语义版本,并更新您的 changelog。
配置
Commitizen 通过五个简单的步骤进行配置。首先,您需要安装 commitizen:
pip install commitizen
第二,将代码当前版本号的引用添加到您的__init__.py
文件中,或者添加一个单独的__version__.py
文件,如下所示:
第三,更新你的.pre-commit-config.yaml
以包含一个用于提交的预提交钩子(如果你不熟悉预提交钩子,查看我之前的关于使用预提交钩子改进代码风格的博文):
第四,更新您的pyproject.toml
文件以包含 commitizen,它引用您代码的当前版本以及代码中需要在提交时更新版本的其他位置(例如您的setup.py
文件):
最后,运行pre-commit install --hook-type commit-msg
来设置提交预提交挂钩。
在 git 工作流中使用 commitizen
现在我们已经安装并配置了 commitizen,让我们看看它在 git 工作流中的使用。
让我们假设您已经签出了一个新的(特性)分支,并且您已经做了一些您想要提交的更改。在添加(卸载)被跟踪的文件后,我们不使用传统的git commit '<commit-message>'
命令,而是使用commitizen commit
命令(简称为cz c
)。使用该命令将提示一系列选项:
使用“cz c”提交时的不同提交选项(图片由作者提供)
使用选择菜单对您所做的更改进行分类(例如,错误修复或新功能),并在提示时添加提交消息。这将为提交消息添加所选代码更改分类的前缀(如feat
或fix
)。例如,如果您添加了一个新特性,commitizen 生成的提交消息可能如下所示:
doc: update README
在您提交并推送您的分支、注册一个 PR 并合并到主分支(或“main”)之后,检查主分支并运行:
cz bump --check-consistency --changelog
这将检查您的 commitizen 配置(和代码)中版本的一致性,并生成或更新一个变更日志(见这里是一个基于 commitizen 的变更日志的例子)。随后,运行以下命令来更新分支上的 changelog 和版本引用,并推送新的版本标记:
git push
git push --tags
就这样——现在,您已经为基于提交历史的 Python 项目的自动化版本和变更日志设置好了。感谢阅读!
另外,如果这一切进行得有点太快,看看 这个回购 我为一个 不同的博客帖子 设置的,在那里我使用 commitizen 进行版本控制。
https://medium.com/@ndgoet/membership
如果你喜欢这篇文章,这里还有一些你可能喜欢的文章:
https://python.plainenglish.io/how-to-improve-your-python-code-style-with-pre-commit-hooks-e7fe3fd43bfa
在依赖 中的任何内容之前,请仔细阅读 本免责声明 我关于 Medium.com 的文章 。
使用 Python 自动化您的数字早晨程序
原文:https://towardsdatascience.com/automating-your-digital-morning-routine-with-python-8387fe884422?source=collection_archive---------8-----------------------
照片由努贝尔森·费尔南德斯在 Unsplash 拍摄
一个简单的 python 脚本开始您的一天
当你早上第一次使用笔记本电脑/台式机时,你可能会打开很多应用程序。每天都这样做可能会令人厌倦,所以我写了一个脚本来自动化在我的桌面上开始一天的过程,在这个教程中我将向你展示它是如何工作的。
【2021 年 11 月 22 日更新】
我制作了这篇文章的视频版本,你可以在 Youtube 上查看:
简单地说,这个剧本
这个脚本简化了我早上启动电脑后的日常工作,处理了我在开始工作前必须完成的大量基本手动任务。
这个例程包括类似 的过程,打开特定的浏览器标签,显示例程提醒,启动跟踪脚本等等。
让我们一行一行地过一遍:
1。导入依赖关系
import webbrowser
import time
import os
import subprocess
from datetime import datetime
2。写一个通知函数
def sendNotificationOnLinux(message):
subprocess.Popen(["notify-send", message])
return
这里我使用内置库subprocess
调用我的 Linux 机器上的通知系统并发送一个简单的消息。这是一个让一整天都自动和自己对话的好方法。
这样我就不用为我每天做的任务设置每日自定义闹钟了。下面我也提供了一个类似的 Windows 选项:
def sendNotificationOnWindows(msg="", delay=2):
t = 0
notify = ToastNotifier()
while t < delay:
notify.show_toast("Notification",msg)
time.sleep(1)
t+=1
3。写一个延续日函数
def continueDay():
cont = input("Press to continue")
这里我只是包装了 python 内置的 input()函数给它一个更合适的名字,我用它来做逐行控制脚本的执行。
4。当我打开和关闭电脑时记录日志
os.system("bash /home/lucassoares/Desktop/projects/self_track/scripts/logSystemOnOff.sh")0
在这里,我运行一个 bash 脚本来记录我的计算机最后一次打开和关闭的时间,以跟踪我何时开始工作,何时停止工作。这个 bash 脚本如下所示:
# logSystemOnOff.sh
echo "$(who -b)" >> path/to/file/systemOnOff.txt
5。打印关于我正在运行的跟踪器的提醒
现在我给自己留一个提醒,我正在为我的键盘和应用程序窗口运行跟踪脚本。
print("Running keyfrequency and active window loggers with sudo")Run keyfrequency and active window loggers with sudo
这些与使用 python 的multiprocessing
包的脚本并行运行:
# call_Start_and_Logs.py
import os
from multiprocessing import Pool
processes = ('/home/lucassoares/Desktop/automated/logWin.py',
'/home/lucassoares/Desktop/automated/logKeys.py',
'/home/lucassoares/Desktop/automated/startday.py')
def run_process(process):
os.system('python {}'.format(process))
pool = Pool(processes=3)
pool.map(run_process, processes)
在这里,我运行一个 python 脚本来记录我在键盘上输入的所有键(因为我在我的 linux 机器上做了一点自我跟踪,这是另一篇文章的主题)以及我使用的应用程序。上面提到的startday.py
剧本就是我们现在正在讨论的。
6。打印开始跟踪焦点的提醒
sendNotificationOnLinux("Turn on Focus")
continueDay()
这里有一个提醒我打开 focus 的提示,这是另一个跟踪我聚焦时间的脚本。现在我正在使用一个名为logFocus.sh
的定制 bash 脚本在终端上做这件事。如果您对以下 bash 脚本感到好奇:
logfile="/path/to/text/file/focus.txt"
start="$(date +%s)"
echo "Started logging focus"
read stop
echo "Stopped recording focus"
echo "Calculating focus time"
end="$(date +%s)"
echo "$start $end" >> $logfile/path/to/python/executable/python
/path/to/python/script/to/calculate/focused/time/calculateTodaysFocusTime.py
我最近发现这个名为 timetrap 的终端工具在这方面做得更好,所以我可能会在不久的将来改变它。
计算和存储聚焦时间的 python 脚本如下:
from utils import loadFocus
import pandas as pd
from datetime import datetimetoday = datetime.strftime(datetime.today(),format="%Y-%m-%d")
timeStartsStamp,dateStartsStamp,durations = loadFocus()
df = pd.DataFrame(dict(dates=dateStartsStamp, durations=durations))
todayFocus = df[df["dates"]==today]["durations"].sum()
print(todayFocus)
7。Spotify 提醒
sendNotificationOnLinux("Turn on white noise")
continueDay()
这里是另一个提醒,启动 Spotify 并打开白噪音(是的,我一天的大部分时间都在听白噪音)。
8。打开谷歌日历
# Google calendar events
sendNotificationOnLinux("Check your calendar")
webbrowser.open("https://calendar.google.com/calendar/u/0/r/day")
这个很简单,我只需使用 python 的 webbrowser 模块在浏览器上打开谷歌日历。
# Touch typing practice
print("TYPE")
os.system('"mlt random "0)-_=+[{]};:\'\|//?"') #pinky finger
os.system("mlt random 123456!@#$%^qwertasdfgzxcvbZXCVBASDFGQWERT~") #left hand
os.system("python /home/lucassoares/Desktop/automated/logTyping.py") #general practice
continueDay()
这部分是我每天的触摸打字练习套路。我使用 mltype ,一个很棒的命令行工具,来改进命令行输入!我用这个工具写了三种不同的练习:
logtyping.py
:标准实践,从我保存的数据集中抽取几行 python 脚本,其中包含我感兴趣的模块和脚本- 一个是专注于练习我的左手(所以只有键盘上的左手键)
- 另一个是给我右手小指的,我发现这是我打字速度的瓶颈
我在日常实践中调用的 python 脚本是这样的:
# logTyping.py
import os
import pathlib
import random
import pandas as pd
from datetime import datetime
import sysdef updateTypingPerformance(df,datedPerformance):
if "Unnamed: 0" in df.columns:
df.drop("Unnamed: 0", axis=1, inplace=True)
df.loc[len(df)] = datedPerformance
return dfdef typePractice(typingDataset):
files = list(typingDataset.iterdir())
file = random.choice(files)
f = open(file, "r")
numberOfLines = len(f.readlines())
print(file)
print(numberOfLines)
if numberOfLines>10:
numberOfLines=10 os.system(f"mlt file --n-lines {numberOfLines} {file}")typingDatasetFolder = "path/to/folder/typingDataset"typingDataset = pathlib.Path(typingDatasetFolder)typingPerformance = "path/to/typing/performance/file/typingPerformance.csv"df = pd.read_csv(typingPerformance)
typePractice(typingDataset)performance = []date = str(datetime.now())wpm = input("What was the wpm?")
acc = input("Waht was the accuracy?")
cont = input("Continue typing?")
performance.append(date)
performance.append(wpm)
performance.append(acc)updateTypingPerformance(df,performance)
while cont=="y":
performance = []
typePractice(typingDataset)
date = str(datetime.now())
wpm = input("What was the wpm?")acc = input("Waht was the accuracy?")performance.append(date)
performance.append(wpm)
performance.append(acc)updateTypingPerformance(df,performance)
cont = input("Continue typing?")if len(sys.argv)>1:
if sys.argv[1]=="plot":
df["wpm"].plot()
plt.show()
它基本上是用 mlt 命令行工具设置培训,并更新一个. csv 文件,我用我的触摸输入性能保存它。
9。学习普通话提醒
print("MANDARIN")
webbrowser.open("www.duolingo.com")
continueDay()
这是另一个不言而喻的例子:我每天练习普通话,所以我会自动在浏览器上打开它,进行每天 10 分钟的练习。
10。在浏览器上打开项目 euler 进行晨间编码例程
print("CODE")
webbrowser.open("https://projecteuler.net/archives")
# start Anki
在练习了普通话之后,我练习了一些解决问题的方法,所以我打开 project euler 作为我的日常编码练习。我喜欢每天只做一项运动来暖脑。
我更喜欢在终端上有一些提醒,在系统的通知弹出窗口上有一些提醒,但这只是个人喜好,根据你的喜好调整它。
11。检查通信信道
做完一天的热身活动后,我喜欢先检查我使用的基本沟通渠道,即:
- 松弛(网络)
- 团队(工作)
- 电子邮件(工作)
- Whatsapp(社交)
# teams, mail, slack, whatsapp
sendNotificationOnLinux("Open Mail, Teams, Slack and Whatsapp")
os.system("teams")
os.system("mailspring")
os.system("slack")
webbrowser.open("https://web.whatsapp.com/")
一旦我完成了检查(我一天做三次,早上一次,下午一次,晚上一次),我就检查我的中等状态,以了解我在平台上做得如何。
# medium
webbrowser.open("https://medium.com/me/partner/dashboard")
print("Check your stats on Medium")
continueDay()
12。最终提醒和结束
sendNotificationOnLinux(message="Leave an Ipython window Open")
这是为了让我记住总是打开一个 ipython 窗口,这样我就可以在需要快速编写脚本时随时使用它。
sendNotificationOnLinux(“Be grateful, no negative self-narratives and have a great day!”)
这里有一个很好的日常小提醒,让我专注于重要的事情,永远心存感激,避免消极的适得其反的自我叙述,这样我就不会分心。
这个项目的源代码可以在这里找到。
关于桌面日常自动化的思考
我喜欢这种自动化脚本,因为它们允许我通过简化所有的手动过程来更快地执行我的例程,即使是像打开标签页这样简单的事情。
这篇文章的重点是 展示 python 和 bash 脚本结合的威力,通过自动化我们每天必须完成的烦人的手动任务来提高您的生产力 。
我试着用一个原则来写这些:如果事情可以自动化,就不要重复做。
如果您有兴趣学习 bash 脚本来优化您的开发工作流,请查看 Udemy 的这些课程:
这些是附属链接,如果你使用它们,我会得到一小笔佣金,干杯!😃
- Bash 脚本和 Shell 编程(Linux 命令行)
- Linux Shell 脚本:基于项目的学习方法
如果你喜欢这篇文章,请在 Twitter 、 LinkedIn 上联系我,并在 Medium 上关注我。谢谢,下次再见!😃
商业自动化:为什么它很重要,为什么你的组织需要它
原文:https://towardsdatascience.com/automation-in-business-why-it-matters-and-why-your-organisation-needs-it-9ca2162ee204?source=collection_archive---------23-----------------------
由 Tomasz Frankowski 在 Unsplash 上拍摄的图片
直到最近,世界级的创新和技术进步才阐明了业务流程自动化的真正潜在影响。
“世界上最大的空间就是改进的空间。”
海尔马特·斯克米特
“我不了解商业自动化。我不需要在我的业务中引入自动化。
…不是一个聪明的、着眼于未来的组织会说的话。
然而,许多公司仍然认为自动化不是他们当前想要或需要的东西。也许他们太专注于扑灭短期火灾,因此没有时间考虑自动化。或者他们只是看不到它的价值。不管原因是什么,这种想法可能是错误的,甚至在一个快速走向数字化和自动化的世界中是危险的短视。
业务流程自动化的快速发展
过去几年,业务流程自动化(BPA)和机器人流程自动化(RPA)解决方案发展迅速。全球数字过程自动化的未来也是光明的,市场将从 2018 年的 67.7 亿美元增长到 2023 年的 126.1 亿美元。
对于现代资本主义经济中的组织来说,业务流程管理(BPM)一直很重要。BPM 使公司能够了解他们的“当前状态”,确定需要改进的领域,并设计行动计划来提高有效性、效率和盈利能力。BPM 也是将信息技术和运营技术投资与业务战略结合起来的关键。
几十年前,有远见的商业领袖就认识到了业务流程自动化的价值。但是直到最近,世界级的创新和技术进步才阐明了 BPA 真正的潜在影响。此外,不断下降的成本和更少的采用壁垒使得 BPA 的竞争环境更加公平。因此,无论大小组织,现在都有可能成功地实现关键业务领域的自动化,并从中获利。
为什么要实现业务流程自动化
BPA 涉及使用技术、数字工具和软件来实现业务流程和工作流的自动化。
如果处理得当,BPA 可以为各行各业的组织带来众多长期的好处:
- 更高效、更快速的流程
- 降低成本
- 可靠、一致和透明的运营
- 精确输出
随着时间的推移,业务中的自动化可以在流程、工作流和员工层面提高生产力。BPA 使员工从单调重复的任务中解脱出来,将他们的精力集中在高价值的活动上,在这些活动中他们的才能和技能可以得到充分发挥。这对激励和参与会产生巨大的影响,从而为组织创造高生产率、增强盈利能力和竞争优势的良性循环。
商业自动化:展望未来
根据 MuleSoft 连接基准报告,在不久的将来将塑造数字化转型的主要趋势是:
- 数字化文化的发展
- 创新将被大众化
- 企业将变得更加灵活,执行速度更快
- API 安全性将变得更加重要
- 微服务将被用来支持更大的创新
- 解锁和利用数据的能力将决定组织的成长和寿命
最后但同样重要的是,自动化将改善业务流程,提高运营效率,并实现业务相关性。另一方面,自动化的缺乏将导致或加剧流程效率低下,甚至可能导致业务过时。
所有这些因素都在推动 BPA 的快速采用,这就是为什么:
- 67%的组织正在探索至少一个或多个业务部门或职能部门的流程自动化
- 77% 的企业领导者希望通过自动化主导的数字化转型来简化运营
- 50% 的公司计划加速重复性任务的自动化
这些当前的现实为未来提出了重要的问题:
在近期内,有多少对 BPA 可行的流程仍将由人工完成?
组织还会继续浪费时间和金钱、消耗员工精力的手动流程多久?
图片由Fakurian-un splash 上的设计
什么时候是开始业务自动化的合适时机
最佳答案— 昨天。
可行答案— 尽快。
BPA 和 RPA 已经以许多积极的方式影响着工作场所。例如,借助工作流自动化平台,组织可以自动执行重复性任务,从而节省时间并实现规模经济。工具也可用于自动化许多类型的流程,包括文件传输、订单输入、报告生成、电子邮件营销、事件日志监控和批处理。甚至客户支持流程也正在通过对话式人工智能聊天机器人、语音机器人和语音助手实现自动化。
目前的 BPA 市场已经相当广阔,而且在未来几年内只会越来越大。现在认识到这一点的组织将处于有利地位,在未来的获得商业自动化的所有好处。
**您的组织会加入这个成功俱乐部吗?
简单的事实是,当涉及到过程自动化时,您不能浪费时间。如果您的企业继续使用手动流程并且继续容忍由此产生的低效率,甚至持续 2-3 年,您将会落后。然而,你的竞争对手认识到了 BPA 的价值,并制定了正确的 BPA 实施策略和路线图,他们很快就会超过你。这就是为什么你需要尽快更新你的业务计划。此外,计划必须围绕 BPA 制定,而不是相反。
结论
这里有一些好消息:如果你有一个 BPA 计划,你的组织可以确保未来的业务连续性、竞争力和增长。即使您现有的手动流程效率低下,这也是可能的。
然而,如果 BPA 还没有出现在你的视野中——在可预见的将来也可能不会——那么你已经在竞争格局中打了一场败仗。最坏的情况是,这种缺乏远见的行为可能会导致商业失败。为了避免这种命运,不要犯这种错误(或者任何自动化错误)。尽早开始考虑 BPA。你的组织的未来可能取决于它。
机器学习工程中的自动化
原文:https://towardsdatascience.com/automation-in-machine-learning-engineering-c80220fa02da?source=collection_archive---------25-----------------------
机器学习自动化的原因、内容和时间
这篇博文关注的是机器学习工程中的自动化。尽管自动化源于软件开发,但这个概念变得越来越适用于机器学习。我分享了一些建议,关于你可以自动化哪些内容,以及你应该在什么时候自动化 T2。在其他博客中,我将向展示如何做到这一点。但是首先,让我们看看为什么你应该自动化。希望你能在这篇博客中找到一些灵感,开始让你作为机器学习工程师的生活变得轻松一些。
为什么是自动化?
作为数据科学家或者机器学习工程师,解决问题是你的任务。您通常通过开发一段符合特定标准、可读且不包含任何错误的代码来实现这一目标。您运行该代码和其他程序来获得结果。通常,您的最终产品会在其他地方运行。也许你只运行一次,但通常,这是一个重复的过程。然而,你应该记住,编写和运行代码或程序本身并不是目标——它只是实现你的目标的一种方式。
专注于你擅长的事情 在这个解决问题的过程中,你与计算机一起工作,在那里你编写代码、进行分析、进行计算并运行程序。充分利用这种合作是有意义的。为此,让我们来看看人类和计算机的长处。人类和计算机都有许多不同的风格,但一般来说,它们可以这样描述:
人类对计算机。图片作者。
那么这告诉我们什么呢?人类和计算机擅长不同的任务。由于人类在做重复性工作时会犯错误并感到无聊,我们应该使用计算机来做这件事。另一方面,人类应该尽可能地将时间花在解决问题上,并使用计算机来完成代码重构等详细任务。因此,我们应该自动化。
这就是软件开发和机器学习自动化的全部内容:使用计算机执行重复的任务。
提高质量
自动化的另一个好处是你的工作质量会提高。我们将研究增强代码的自动化代码重构。此外,通过自动化,您可以在开发过程的几个阶段强制运行测试。这样,您可以在早期发现错误。
其次,通过自动化任务,你不太可能不小心跳过任何任务。任务执行也很容易被记录。通过记录这些步骤,您可以验证所有必需的任务都已运行,并向其他人证明这一点。最后,您可以在开发过程的几个阶段强制运行测试。这样,您可以在早期发现错误。
节省时间
尽管您需要在项目开始时投资实现自动化,但最终,您将从中受益。增强你的代码会更快;随着质量的提高,花费在调试上的时间会减少,解决方案的部署会更快。
自动化什么?
你可以自动化机器学习中的许多事情,但一般来说,这都归结于机器学习自动化的这个金字塔:
机器学习自动化的金字塔。图片作者。
尽管并不相互排斥——有些任务可以被分配到多个类别中——但我确实认为这是引入自动化概念的好方法。让我们从基础做起,从我们自己做起,直到顶峰。
1。重构代码
对于代码的重构,我的意思是坚持代码符合某些标准,而不改变代码中的逻辑。这是一个由计算机(部分)接管的完美任务,因此作为开发人员,您可以专注于构建逻辑。让我们看看林挺、格式化和检测质量和安全问题。
Linters
通过这样做,你可以很容易地发现任何错误。棉绒的例子有皮林特和薄片 8 。SonarQube 还提供一种叫做 SonarLint 的棉绒。
格式化 尽管 linters 只指出问题而不改变代码,格式化程序格式化代码,使其遵循一定的准则。它使您的代码对其他人来说可读性更好,因此更容易理解代码并为其做出贡献。此外,代码审查可以关注逻辑本身,而不是布局。文本文件,如 YAML 文件,也可以格式化。流行的 Python 格式化程序的例子有 Black 和 autopep8 。
检测质量和安全问题 在人类和计算机的对比中我们已经看到,你会写 bug。您可以通过在每次提交时运行测试函数,或者当您合并到主代码分支时发现它们。使用 Pytest 你可以自己设置,或者你可以使用像 Jenkins 这样的工具。
您编写的一些代码可能会导致安全问题。例如不正确的异常处理、硬编码的密码或误用正在运行的子流程。像 Bandit 和 SonarQube 这样的软件可以帮助你发现这些问题。
您很可能会使用 Python 包来解决您的问题。尽管您可能认为这些包使用起来是安全的,但是可能有一些包本身并不安全。快速浏览一下 Github 页面可以给出一个很好的提示;比如维护人员的数量,更新频率。接下来,T4 安全系统会根据允许清单检查你所有的进口商品。
Linters、formatters 以及 Pytest 和 Safety 之类的包可以手动运行,但是当然,自动化的思想就是使之自动化。使用 git 挂钩,您可以在提交之前运行格式化程序和包,或者您可以将它们添加到管道中,如下所述。Linters 和 formatters 也可以直接安装在您的 IDE 中。因此,当您自动化这些任务时,您的持续集成(CI)过程会得到改进,因为您在主代码分支上实施了代码质量。
2.部署
现在我们已经爬上了金字塔的地基,让我们把重点放在中间层。
一些机器学习问题通过对数据进行分析来解决,这可能是在您的机器上本地完成的事情。但是,您通常希望将代码发布到不同的环境中,例如其他数据可用的环境,或者更适合计算密集型运行的环境。另一个原因可能是您正在为用户构建一个应用程序。
将您的代码部署到该环境中称为部署。您需要采取多个步骤。您可以随心所欲地添加安全性检查,在开发环境中运行单元测试,或者在测试环境中运行集成测试,等等。基本步骤包括:
- 定义上下文(比如应用程序的名称,或者目标环境)
- 打包代码,例如通过压缩或创建工件
- 发布代码
- 在目标环境上构建应用程序,比如解压缩它,或者通过在 Kubernetes 上从源代码构建一个容器
当然,运行这些任务可以是手动工作。然而,自动化这些重复的任务是有意义的。通过自动化部署,您能够连续部署(CD)您的应用程序。您可以在 shell(如 Bash 或 Powershell)中通过命令行界面(CLI)使用脚本来自动化部署。另一种方法是使用管道。
脚本
使用命令行界面你可以给程序下命令。通过编写一个捕获这些命令的脚本,您可以一次性完成一系列任务。这里的好处是您也可以对脚本进行版本控制。此外,可以将日志打印到屏幕或日志文件中,以实现可追溯性。Bash 和 Powershell 可以用来创建目录、移动文件、读写纯文本文件等等。要与程序交互,您需要使用相应的程序 CLI。您也可以用这样的方式编写 Python 函数,即您可以使用 argparse 通过输入参数调用它们。多个脚本可以组合在一个 Makefile 中。
下面是一个小例子,演示了如何通过弹性 Beanstalk 客户端和 Bash 将 Docker 容器部署到 AWS Cloud。通过 AWS 控制台得到同样的结果需要我 3 分钟的点击和输入时间。
部署到 AWS Elastic Beanstalk 的示例
管道 管道建立在脚本之上。它们为这些脚本添加了额外的功能,从而增强了部署过程。所有这些功能当然都是有代价的。如果您需要管道,或者脚本就足够了,这取决于实际的用例。管道工具的例子有 Azure 管道、 AWS CodeBuild 和 Buildkite 。这些功能的非详尽概述如下:
- 它们提供了一个图形界面。这样更容易看到流动的样子;如果生成或部署成功;以及每个处理步骤的输出是什么;
- 管道可以自动触发。虽然这也可以用脚本实现,但是管道往往是在有人合并开发或者主分支的时候触发的;
- 所有的构建都有日志记录,所以很容易看到谁在什么时候触发了什么;
- 用户管理已经就绪,因此您可以将部署限制在某些用户的生产环境中;
- 以前的部署被保存,因此如果出现问题,您可以轻松地返回到以前的部署。
通常,代码的来源是一个 Git 库。管道的定义也存储在那里,或者如果您有多个管道,它可能存储在一个中央代码存储库中。这样,您可以防止管道定义随着时间的推移而发生分歧。
大多数情况下,YAML 被用作建立管道结构的语法,而任务是用 Bash 之类的语言编写的。此外,通常预定义的任务也是可用的。所有这些任务都需要一些计算实例来运行。这通常由提供商来管理。然而,您也可以自己托管管道,这样您的代码就不会被转移到您的组织之外。
3.机器学习过程
是时候移动到我们机器学习自动化金字塔的顶端了。现在,它变得非常有趣:除了重构代码和部署,您还可以自动化机器学习过程。我指的是如下所示的简化过程。
机器学习过程。图片作者。
在左侧,我们看到了模型实验的过程,在这里您可以对不同的模型进行特征工程和一些超参数调整。从这里,您选择最有希望的模型,该模型是图中间所示的模型训练过程的输入,在该过程中,您优化并验证最终的模型。在右边,我们看到服务于模型或推理过程的模型。
实验通常是用生产数据的子集“离线”完成的。在实验阶段投资自动化几个步骤可能是值得的,例如使用下面讨论的 AutoML。另一方面,实验特征可能使整个过程难以自动化。
部署模型训练和服务的应用 模型训练和模型服务通常不是在本地完成的,而是在单独的环境中完成的。出现这种情况的原因是您的机器在存储和计算方面的限制,或者因为不允许您在本地存储生产数据。在服务的情况下,速度(延迟)也是一个问题。
可以构建一个用于模型训练的微服务或应用程序,而不是像前面讨论的那样进行部署。这同样适用于用于模型服务的服务。
自动训练 该图显示了一般的训练过程,实际上还包括许多步骤。所有这些步骤可以紧密结合在一起。这可以像一个脚本一样简单,例如通过使用 sklearn 管道。如果运行这样的管道,数据作为输入被加载,并且在模型注册中心注册的经验证的模型是输出。
另一种方法是将流程分成不同的服务。对于每个服务,您可以优化主机。对于预处理,存储可能很重要,而对于训练,计算可能是决定性因素。AWS 正在使用这种方法,提供亚马逊 SageMaker 管道。
Auto ML 特别是有了监督学习,就有可能实现特征工程和超参数调整过程的自动化。通过强力结合巧妙的算法,该模型针对成功指标进行了优化。为此需要多次运行,因此专用的训练环境在这里可能会很有用。帮助你的工具有 TPOT 、特征工具和自动 sklearn 。云提供商也在这里提供工具,比如亚马逊 SageMaker Autopilot。
自动再训练 当数据静止时,这些过程是一次性的。然而,最有可能的情况是数据会随着时间的推移而改变(称为数据漂移),这意味着模型性能也可能会随着时间的推移而降低。模型再培训是必要的,这是自动化的东西。这也称为持续培训(CT),指的是 CI/CD。自动再训练中通常只涉及超参数调整,因为特征工程不太容易自动化,需要手工操作。再培训可以按时触发,比如每个周日晚上,或者由性能监控步骤触发。
所有主要的云提供商都提供自动化、管道和自动再培训的框架和工具:
- Google 在这篇博文中分享了他们对 MLOps 和自动化管道的观点
- AWS 在本博客中介绍了金融服务的最佳实践,但它也适用于其他行业
- Azure 在这个博客中讨论了他们的模型再训练方法
何时实现自动化?
我们处于金字塔的顶端,我们已经涵盖了许多需要自动化的任务。然而,这需要花费时间和精力来设置我们到目前为止介绍的所有内容。因此,跳过自动化部分,专注于功能性需求可能很有诱惑力。此外,您的经理可能希望您关注新功能,而不是这些非功能性的自动化需求。尽管如此,现在应该很清楚自动化有很大的价值。
我列出了一系列标准来检查您是否应该将您正在处理的任务自动化:
- 任务的复杂程度 如果是一个简单的任务,在执行的时候出错的机会就少,所以对自动化的需求就少。另一方面,当任务复杂时,执行它可能需要花费大量的时间和精力。
- 任务发生的频率 如果你知道一个任务只运行一次,那么跳过自动化部分是有意义的。然而,根据我自己作为开发人员的经验,典型的任务很少是一次性的。
- 自动化任务所需的时间和精力
这更像是一种成本效益的权衡。设置自动化的成本与收益相比如何,比如以后提高质量和节省时间?
鉴于这些标准,在我看来,总是实现某种程度的自动化是有意义的。自动化的好处是您可以重用以前项目的一些工作,比如管道模板或预提交钩子定义。我经常使用的一种方法是,首先手动执行一项任务,比如运行测试功能,或者使用鼠标和键盘通过控制台界面进行部署。在我知道需要做什么之后,我会自动执行这些步骤。对于机器学习过程的自动化,如果需要自动(再)训练,则取决于项目要求。
结论
在这篇博文中,我解释了为什么你应该在你的机器学习项目中使用自动化。这是你作为机器学习工程师工作的一个重要部分。接下来,我们研究了通过探索机器学习自动化的金字塔你可以自动化什么:代码重构、部署和机器学习过程。最后,我简要地提到了一些需要记住的标准,以决定何时应该自动化。
在接下来的文章中,我将更深入地讨论如何自动化这些任务。
我要感谢我的同事塞巴斯蒂安·坎德尔、约斯特·德·泰耶和朱莉娅·苏博特尼亚亚的反馈和启发。
SMAC:Python 中快速超参数调优的 AutoML
原文:https://towardsdatascience.com/automl-for-fast-hyperparameters-tuning-with-smac-4d70b1399ce6?source=collection_archive---------19-----------------------
在高维空间中寻找出路
蓝莓制作在 Unsplash 上的照片
为给定的数据科学问题生成第一个模型可能非常简单。建立一个高效的模型,提供高水平的精确度,要困难得多。数据科学家必须清理数据,提炼特征,找到正确的指标,找到正确的验证策略,正确地构建测试和训练集,并微调所选模型的参数。
这些步骤大多受益于数据科学家的经验,很难自动化。幸运的是,超参数调优不是这样的,可以使用自动机器学习:AutoML。
在本帖中,我们将从数学上解释为什么超参数调整是一项复杂的任务,并展示 SMAC 如何帮助建立更好的模型。
超参数?你在说什么?
当尝试为给定数据集拟合模型时,必须定义两种参数:
- 用于配置模型的参数:决策树的深度、SVM 模型的内核、多项式的次数、神经网络的层数等等
- 模型本身的参数:决策树叶子的权重,SVM 核的参数,多项式的系数,每个神经元的权重,…
第一类参数被称为模型超参数,因为它们定义了模型的结构,而后者被附加到模型本身。
为什么需要 AutoML 进行超参数调整?
请记住,超参数调整,有时也称为超参数优化(HPO),是一个通过根据您选择的指标确定模型的最佳配置来尝试充分利用模型的过程。
使用 AutoML 主要有两个原因:
- 手动寻找最佳参数是一项非常繁琐的任务。配置空间的组合学可能相当大。对于随机森林,需要考虑的参数不少于 10 个。每个参数可以有 10 个不同的值。因此,探索配置空间需要评估 10 种⁰配置!
- 绝对不能保证针对给定数据集优化的配置在另一个数据集上也同样有效。每次将模型应用到新的数据集时,优化超参数至关重要。
使用 AutoML 技术允许通过自动化配置空间探索来解决这两个限制。
用 AutoML 调整超参数:一项艰巨的任务
在进一步向您展示如何高效地自动调优超参数之前,让我们解释一下为什么这是一项复杂的任务。
让我们用一些数学来形式化什么是超参数优化。
从数学上来说,HPO 试图最小化一个或多个测试集上的评估指标,通常使用交叉验证来生成。这可以形式化为:
HPO 的数学公式。作者的公式。
其中 M 是我们希望使用给定的训练和测试集来优化模型 f_hat 的度量的评估。θ是用于配置模型的一组参数。数值取自配置空间θ。
通常,当面对这样的优化问题时,使用基于数值微分的方法。基本上,要优化的函数,即 M 与 f_hat 的组合,相对于参数θ是微分的。然后,使用牛顿-拉夫森法、梯度下降法或任何类似的方法迭代收敛到最优值。
然而,在超参数调谐的情况下,通常不可能计算这些梯度:
- 度量可以是非平滑的,例如 MAE。参见我关于这个主题的另一篇论文。因此,微分是不可能的。
- 模型本身可能很难区分,不仅在符号上,在数字上也是如此。想想所有基于树的方法,它们是分段常数的。
- 梯度可以消失。这是神经网络的情况,也是基于树的方法:随机森林,XGBoost,CatBoost,LightGBM,…
- 数值评估梯度是非常耗时的,因为对于每个参数方向上的每个变化,我们需要训练一个完整的模型。
- 模型超参数可能不连续。想想 XGBoost 的 nb_estimators 参数:它是一个整数值。分类参数也是如此。
请注意,自动微分在某些情况下会有所帮助,但在大多数情况下,您无法使用梯度导向方法进行优化。
正如您所看到的,在超参数调优的情况下,许多原因禁止使用标准优化方法。我们被迫仅仅依靠我们作为数据科学家的经验来选择最佳参数吗?
为什么不用网格搜索?
一种选择是使用暴力。毕竟,为 XGBoost、Random Forest 或任何其他模型寻找最佳超参数只需要评估每个可能配置的指标。
但是如上所述,配置空间可能是巨大的,即使计算机越来越强大,探索 10 ⁰配置仍然(远远)超出他们的能力范围。
所以这只能是你配置空间非常有限的时候的一个选项。
那么随机搜索呢
这是一种选择。但是有随机性在里面;)我们将在下面看到它是可行的,但是不能保证收敛到最佳配置,至少在给定的时间内。
使用 SMAC
库 SMAC 提出了蛮力和随机探索的替代方案:基于序列模型的算法配置。
这个库背后的想法是建立一个模型(因此 SMAC 的缩写是基于模型的),试图为一组给定的超参数估计度量值。使用这个内部模型,您可以随机生成配置,并使用这个估计器来猜测什么是最好的配置。
参见这篇非常好的开创性的论文了解更多关于这个主题的细节。我还写了一篇关于如何使用模型创建自己的 HPO 引擎的完整文章:
[## 用 XGBoost 调优 XGBoost:编写自己的 Hyper Parameters 优化引擎
towardsdatascience.com](/tuning-xgboost-with-xgboost-writing-your-own-hyper-parameters-optimization-engine-a593498b5fba)
SMAC 使用随机森林模型来捕捉算法/模型的行为,以根据指标进行优化。
整个算法非常简单。运行第一次训练并计算指标。用这个第一输出训练随机森林模型。
然后生成随机配置,具有最佳估计分数的配置用于下一次训练。然后用这个新的结果重新训练模型,这个过程再次开始。
内部性能模型指导配置空间探索。如代码所示,受 SMAC 示例的启发,SMAC 从之前的运行中学习,并在每一步中提高自己的知识:
使用随机搜索和 SMAC 调整随机森林模型。
上面的代码使用 SMAC 和 RandomizedSearchCV 来调整 Hyper 参数。请注意,SMAC 支持连续实参数以及分类参数。支持分类参数是使用随机森林作为指导探索的内部模型的一个原因。
这段代码演示了如何使用 SMAC 和 Random Forest 作为模型进行微调,但是我一直将它用于 XGBoost 以及 SVM 或萨里玛模型,它非常有效。
下图比较了两种情况下的配置空间探索,即使用 SMAC 和随机搜索。他们根据超参数调整迭代次数绘制分数:
随机搜索(左)与 SMAC(右)超级参数探索。作者的图表。
在左侧,我们看到随机搜索不规则地探索配置空间。优化没有受益于以前的培训。另一方面,在右边的图中,可以清楚地看到 SMAC 从以前的试验中吸取了经验,并尝试了一些适合改进的构型。
结果是 SMAC 更快地收敛到更好的解。
结论
为一个模型寻找最佳的超参数是一项乏味但至关重要的任务。SMAC 是一个非常有效的库,它带来了自动 ML 并真正加速了精确模型的构建。任何类型的模型都可以从这种微调中受益:XGBoost,Random Forest,SVM,SARIMA,…
非常有趣的是,基于 ML 的方法可以用来帮助更好地训练 ML 模型。然而,这提出了一个问题:SMAC 内部随机森林模型的超参数是如何优化的?
你会在 SMAC 代码或者学术论文中找到答案:它们是硬编码的;)
用于物体检测的 AutoML:如何训练模型以识别坑洞
原文:https://towardsdatascience.com/automl-for-object-detection-how-to-train-a-model-to-identify-potholes-e22c3f4b774?source=collection_archive---------13-----------------------
如何使用新的 Azure 机器学习功能进行对象检测
来自我们训练的模型的坑洞预测和置信度得分-图片由作者提供
初始算法选择和超参数优化是我个人不喜欢做的活动。如果你像我一样,那么也许你会喜欢https://docs.microsoft.com/en-us/azure/machine-learning/concept-automated-ml自动化机器学习,这是一种让脚本为我们完成这些耗时的 ML 任务的技术。
Azure Machine Learning (AML) 是一种云服务,它的一些功能使得准备和创建数据集、训练模型以及将它们部署为 web 服务变得更加容易。最近,反洗钱团队发布了 AutoML for Images 功能供公众预览。今天,我们将使用该功能训练一个对象检测模型来识别道路上的坑洞。
在本文中,我将简要回顾一些 AML 和对象检测概念,因此您不需要完全熟悉它们就能理解。这个教程很大程度上基于 Azure 的这个例子,你可以在这里查看我编写的 Jupyter 笔记本。
酷,我们开始吧!
我们要做什么?
对象检测数据集很有趣,因为它们由表格数据(边界框的注释)和图像数据组成。png,。jpeg 等)。 COCO 格式是对象检测数据集的流行格式,我们将下载坑洞数据集 ( 坑洞数据集)。分享者。阿提库尔·拉赫曼奇托利安。2020 年 11 月。执照。ODbL v1.0)使用这种格式。Azure 机器学习使用 TabularDataset 格式,所以我们需要做的第一件事是从 COCO 转换到 TabularDataset。****
转换后,我们将选择一个对象检测算法,最后训练模型。
1-准备数据集
我从 Roboflow 得到了数据集。它有 665 张道路图片,上面标注了坑洞,是由阿蒂库尔·拉赫曼·奇托里安创作并分享的,作为他本科论文的一部分。Roboflow 团队将这些图片重组为 70/20/10 的训练有效测试分割。
每次拆分都有两个主要部分:
_annotations.coco.json
,一个 JSON 文件,带有images
、categories
和annotations
元数据- 图像本身(。jpg 文件)
这是 COCO 注释键的样子:
images
:有关于数据集图像的信息(id,文件名,大小等。)categories
:边框类别的名称和 idannotations
:包含关于对象的信息,包括边界框坐标(在这个数据集中是绝对坐标)、对象的 image_id 和 category_id
现在是时候开始与 AML 合作了。你要做的第一件事就是创建一个 Azure 机器学习工作区。你可以使用 https://portal.azure.com 的网络界面来完成。
我们需要一个计算实例来运行笔记本,然后运行 train 实验,所以请在您的工作区内创建一个。图像任务的 AutoML 模型需要 GPU 计算实例。您也可以使用 web 界面创建一个计算实例。
在哪里创建计算实例—按作者分类的图像
我已经下载并提取了。/potholeObjects 文件夹。每个分割都有它的文件夹,里面有图像和 JSON 文件。
的内容。/火车坑洞图片—作者图片
您需要将图像和 JSON 文件上传到数据库,以便 AML 可以访问它们。数据存储是云数据源的抽象。创建 AML 工作区时,会创建一个azureblobdastore并将其设置为默认值。我们将使用这个默认的数据存储并将图像上传到那里。****
注释是 COCO 格式(JSON ),但是 TabularDataset 要求它在 JSON 行中。TabularDataset 具有相同的元数据,但是以不同的键组织。这是用于对象检测的 tabular 数据集的样子:
***{
**"image_url"**:"AmlDatastore://data_directory/../Image_name.image_format",
**"image_details"**:{
"format":"image_format",
"width":"image_width",
"height":"image_height"
},
**"label"**:[
{
"label":"class_name_1",
"topX":"xmin/width",
"topY":"ymin/height",
"bottomX":"xmax/width",
"bottomY":"ymax/height",
"isCrowd":"isCrowd"
},
{
"label":"class_name_2",
"topX":"xmin/width",
"topY":"ymin/height",
"bottomX":"xmax/width",
"bottomY":"ymax/height",
"isCrowd":"isCrowd"
},
"..."
]
}***
幸运的是,微软工程师编写了一个从 COCO 转换的脚本:https://github . com/Azure/Azure ml-examples/blob/1a 41978d 7 DDC 1 D1 f 831236 ff 0 C5 c 970 b 86727 b 44/python-SDK/tutorials/automl-with-Azure ml/image-object-detection/COCO 2 jsonl . py
这个文件的 image_url 键需要指向我们正在使用的数据存储中的图像文件(默认的)。我们使用 coco2jsonl.py 脚本的 base_url 参数来指定。
***# Generate training jsonl file from coco file
!python coco2jsonl.py \
--input_coco_file_path "./potholeObjects/train/_annotations.coco.json" \
--output_dir "./potholeObjects/train" --output_file_name "train_pothole_from_coco.jsonl" \
--task_type "ObjectDetection" \
--base_url "AmlDatastore://**{datastore_name}**/potholeObjects/train/"***
我们将对验证集运行相同的命令。现在,下一步是将文件上传到数据存储,并在 AML 中创建 数据集 。不要混淆数据集和数据存储库。数据集是版本化的打包数据对象,通常基于数据存储中的文件创建。我们将从 JSON 行文件中创建数据集。****
对于培训和验证拆分,您也将这样做。如果一切顺利,你可以在 AML 中看到图片预览。
AML 工作区内的数据集预览—按作者分类的图像
2 —运行实验
在 AML 内部,你所做的一切都被称为实验。要使用 AutoML 训练模型,您将创建一个实验,指向它应该运行的计算目标,并提供 AutoML 参数的配置。****
让我们首先创建实验,并从工作区获得计算机实例:
在这里,我将使用 yolov5 默认参数运行实验。您需要提供超参数、计算目标、训练数据和验证数据(正如示例所说,验证数据集是可选的)。
现在我们终于可以提交实验了:
***automl_image_run = experiment.submit(automl_config_yolov5)***
您可以使用 Workspace web 界面监控实验:
使用工作区用户界面监控实验——作者图片
在这里,我只使用一个单一模型的字典,并使用默认参数,但你可以探索参数和调谐设置。这里有一个来自微软教程的例子:
3 —可视化预测
这个 yolov5 模型是使用 Pytorch 训练的,所以我们可以下载这个模型并使用 Jupyter 笔记本来检查预测。我的花了 56 分钟训练。要获得模型,您需要做的第一件事是在工作空间中注册最佳运行,这样您就可以通过它来访问模型。
现在我们可以下载 model.pt 文件并运行推理。为此,我们将使用来自azure ml-contrib-automl-dnn-vision包的代码:
我使用了微软教程中的代码来可视化边界框。以下是测试图像的结果:
来自我们训练的模型的坑洞预测和置信度得分-图片由作者提供
酷吧?
最后的想法
Azure 机器学习是一个让你开始机器学习(嗯,在我们的情况下是深度学习)的好工具,因为它隐藏了很多复杂性。现在有了 AutoML 功能,你甚至不必考虑在不同的时刻训练不同的模型,因为调谐设置可以为我们做到这一点。
你可以在这里查看 Jupyter 笔记本的所有代码。
管道中的下一步是将模型部署为 web 服务。如果你很好奇,你也可以使用微软教程来查看如何做到这一点。
感谢阅读!😄
参考
- 坑爹数据集 。分享者。阿提库尔·拉赫曼奇托利安。2020 年 11 月。执照。ODbL v1.0 版
时间序列的 AutoML:使用 FEDOT 框架的高级方法
原文:https://towardsdatascience.com/automl-for-time-series-advanced-approaches-with-fedot-framework-4f9d8ea3382c?source=collection_archive---------2-----------------------
思想和理论
使用 FEDOT 和其他 AutoML 库处理具有间隙和非平稳性的真实世界数据的示例
用于时间序列预测的 AutoML 框架 FEDOT(图片由作者提供)
正如我们在之前的帖子中已经注意到的,大多数现代开源 AutoML 框架并没有广泛覆盖时间序列预测任务。在那篇文章中,我们已经初步演示了 AutoML 方法可以产生什么样的预测。
然而,我们可以更深入地研究一个 AutoML 框架 FEDOT ,它可以自动进行时间序列预测的机器学习管道设计。因此,我们将通过时间序列预测的实际任务详细解释 FEDOT 核心中正在发生的事情。
FEDOT 框架和时间序列预测
之前我们已经讨论过机器学习问题的流水线。管道是一个无环的有向图。用 FEDOT 的术语来说,这个图叫做链,或者复合模型,或者管道。
FEDOT 操作的基本抽象是:
- 操作是对数据执行的动作:它可以是对数据进行预处理(规范化、标准化、填补空白)的动作,也可以是给出预测的机器学习模型;
- 节点是放置操作的容器。一个节点中只能有一个操作。主节点只接受原始数据,次节点使用前一级节点的输出作为预测值;
- 链或管道是由节点组成的无环有向图。FEDOT 中的机器学习流水线是通过 Chain 类实现的。
给定的抽象可以在下图中看到:
FEDOT 框架中的操作、节点和链(管道)
机器学习模型和经典模型,如时间序列的自回归(AR ),都可以插入到这种管道的结构中。
我们知道如何解决分类或回归问题。我们甚至知道如何在 FEDOT 制作一系列模型。但是我们如何进行时间序列预测呢?例如,我们如何使用决策树?特色在哪里?
特色就在这里!要构建具有特征的表,只需要用滑动窗口遍历时间序列,并准备一个轨迹矩阵。
值得一提的是,这不是我们的发明:你可以阅读使用这种转换的 SSA 方法。这种方法也在 H2O 图书馆的一个版本中使用。几乎所有时间序列的机器学习模型的应用都是构造这样的矩阵。
让我们更详细地分析一下级数变换的这种方法。时间序列是一系列值,其中后续值通常依赖于之前的值。因此,我们可以使用时间序列的当前和先前元素来进行预测。假设我们希望使用当前值和一个先前值来预测前面一个元素的序列:
制作时间序列预测特征表示例(作者图片)
我们称这样的转换为时间序列的“滞后转换”。在 FEDOT 中,我们将它放在一个单独的操作“滞后”中。重要的超参数是滑动窗口的大小,它决定了我们将使用多少以前的值作为预测值。
下面是一个动画,展示了多步预测提前一个元素的示例。然而,可以一次对前面的几个元素执行一步预测。在这种情况下,解决了多目标回归问题。你可以看到从形成轨迹矩阵(或滞后表)到做出预测的整个预测过程:
动画。用滞后时间序列变换提前预测 3 个元素(作者制作的动画)
任何机器学习模型都可以用作预测模型。但是我们也在 FEDOT 中实现了几个具体的时间序列预测模型(比如 AR 和 ARIMA)。此外,时间序列特定的预处理方法,如移动平均平滑或高斯平滑被添加。
这里还没有自动机器学习。当框架的智能部分 composer 启动时,它就“活了起来”。Composer 是制作管道的界面。在其中,它使用了一种优化方法,实现了 AutoML 的“自动”部分。默认情况下,该框架使用基于遗传编程原则的进化方法。但是,如果有必要,任何搜索算法都可以添加到合成器中,从随机搜索到贝叶斯优化。
AutoML 分两个阶段工作:
- 组合就是寻找管道结构的过程。默认情况下,进化算法用于该目的。在这个阶段,节点中的操作被改变,子树从一些解决方案中被删除,并“生长”到其他解决方案。节点中操作的超参数在这里也发生了变异;
- 超参数调优是管道结构不变,但节点中超参数在变化的过程。这个阶段在作曲完成后开始。
下面是在合成阶段对管道执行的突变转换的示例:
动画。合成期间管道中的变化过程。显示了改变节点中超参数、替换操作、添加节点的各种变异操作符。交叉运算符未显示(由作者制作动画)。
在进化过程中,选择最精确的模型。因此,在合成结束时,将有一个具有固定结构的管道,我们只需要在节点中配置超参数。
使用来自hyperpt库的优化方法,在管道的所有节点中同时调整超参数:
动画。复合模型节点中参数调整的过程(作者制作的动画)
完成所有阶段后,我们将获得最终的管道。
数据我们有
在机器学习(非科学)文章中,普遍使用相对简单的时间序列来证明算法的有效性。其中最受欢迎的是“美国航空公司乘客”,下面是剧情,展示了它的样子:
美国航空公司乘客数据集(图片作者
在这样的时间序列上展示图书馆的能力是非常诱人的——然而,大多数有点复杂的模型将能够提供足够的预测。我们决定从现实世界中获取一个数据集,以展示 AutoML 算法的所有功能。我们希望,这个例子对于演示来说足够好。
有两个时间序列:第一个是风电场的平均日发电量。第二个是柴油发电机的平均日发电量。这两个参数都以千瓦时为单位进行测量。
柴油和风力发电机发电(图片由作者提供)
风力发电机的发电量高度依赖于风速。如果风速降低,柴油发电机就会启动,以维持足够的发电量。因此,当风力涡轮机的功率输出下降时,柴油发电机的功率输出就会上升,反之亦然。同样值得注意的是,时间序列有缺口。
编程代码不会在这篇文章下面列出。不过为了更好的感知,我们准备了大量的可视化。编程代码的完整版本位于 jupyter 笔记本中,所有技术方面都有更详细的描述。
任务
任务是建立一个预测未来 14 天柴油发电量的模型。
补缺
出现的第一个问题是原始时间序列中存在间隙。在 FEDOT 中,有三组方法可用于时间序列间隙填充:
- 线性插值等简单方法;
- 使用单一时间序列预测模型的迭代预测方法:
- 填补空白的高级预测方案。
第一组方法工作速度快,但精度低。第二组的方法不考虑问题的细节,相当于简单地预测一个时间序列。最后一组方法考虑到了前面方法的缺点。所以我们将进一步应用第三组的方法。复合模型使用双向时间序列预测来填补空白。
组合预测的示例,其中使用了两个模型,并且使用加权平均值将它们的预测结果组合在一起(图片由作者提供)
为了填补时间序列中的空白,我们创建了一个简单的高斯平滑、滞后变换和岭回归的管道。然后我们训练这条管道来预测“未来”。
所获得的用于修复时间序列中的间隙的管道的结构(图片由作者提供)
然后反方向重复这个动作——训练管道预测“过去”。之后,我们可以使用平均法合并两个预测。
这种方法中的操作顺序可以描述如下。首先,使用位于间隙左侧的时间序列部分。在这一部分上训练一个复合模型,以给出对间隙中存在的前方元素数量的预测。之后,对右侧部分重复该程序。为此,反转时间序列的已知部分,训练模型,进行预测,并反转结果预测。使用加权平均值进行预测组合。因此,向量的值越接近作出预测的时间序列的已知部分,其权重就越大。也就是说,在平均时,红色预测(图中)将在通道的左侧部分具有更大的权重,绿色预测将在右侧部分具有更大的权重。
在应用间隙填充算法后,我们得到这样的结果:
柴油发电机发电量时间序列的填补空白(作者图片)
很好,不是吗?但是第二个时间序列在它的中心部分仍然有一个缺口。我们也可以将前面的方法应用于这个缺口,但是存在另一种方法。我们使用成对回归来匹配两个时间序列的值,并使用具有柴油发电机的序列作为单一预测器来恢复风力涡轮机发电量(目标)的值。我们还将使用 FEDOT 框架解决这个回归问题。
在所有这些间隙填充过程之后,我们得到了以下结果:
还原的时间序列(可以看出它们走的是反相的——填充的通行证并不违反这个原则)——(作者图片)
现在,两个时间序列都没有间隙,可以进一步使用了。
预报
让我们使用上面描述的所有 FEDOT 特性,并对我们的数据运行 AutoML 算法。我们已经使用 API 中的 fit 和 predict 方法启动了带有默认配置的 FEDOT 来进行时间序列预测。现在让我们来看看结果预测,并计算指标:平均绝对误差(MAE)和均方误差的根(RMSE):MAE-100.52,RMSE-120.42。
时序预测示例(作者图片)
如果我们看图表和度量值,问题就来了:这个模型好不好?
回答:很难搞清楚。最好不要在一个小样本上验证模型——那里只有 14 个值。最好至少计算几次指标。例如,三乘以 14(即 42)。为此,您应该使用样本内预测。
高级验证
下面的动画应该有助于您理解样本外预测和样本内预测的区别:
动画。样本内和样本外预测流程(作者制作动画)
因此,我们的模型可以预测未来的 14 个值。但是我们希望提前获得 28 个值的预测—在这种情况下,我们可以迭代两次预测 14 个元素。在这种情况下,第一次迭代中预测的值(样本外)将作为第二次预测的预测值。
如果我们想验证模型,我们将使用样本内预测。通过这种方法,我们预测了时间序列中已知的部分(测试样本)。然而,在迭代预测中,已知值用于形成下一步的预测值,而不是前一步的预测值。
在 FEDOT 中,也实现了这种方法,所以现在我们将在三个各有 14 个值的块上测试该算法。为此,我们将划分样本并再次运行 composer。预测结果如下图所示。重要的是澄清进化算法是随机的,因此 AutoML 模型的输出可能不同。
在三个包含 14 个元素的区块上验证时间序列的复合模型。右侧显示的是原始时间序列(图片由作者提供)
第一个验证块上的预测完美地重复了时间序列的实际值。这似乎很奇怪,但只要我们看看获得的管道的结构,一切都变得清楚了。
合成过程中获得的管道实例(进化过程)。考虑了具有特定于时间序列的预处理操作的管道和表示线性关系的简单管道(图片由作者提供)
从图中可以看出,更复杂的流水线并不总是提供最低的误差度量。因此,最佳发现的管道结果是短的,但是验证的误差值很小。基于此,我们得出结论,对于这个时间序列来说,这已经足够了。
由于最终模型是 K-最近邻算法,管道能够很好地重复来自训练样本的时间序列模式。这种模型可能会出现问题,例如,根据趋势,时间序列不是稳定的。在这种情况下,K-最近邻模型将不能从训练样本中充分推断依赖性。这个时间序列还有一个特点——方差非平稳。
但是,它的结构包含相对同质的部分,与执行验证的时间序列部分没有太大不同。
时间序列中与验证部分“相似”的同质部分以橙色突出显示(图片由作者提供)
在这些部分,有重复的模式,时间序列是趋势稳定的-值围绕平均值波动,然后上升到 1000 千瓦时以上的值,然后下降到 0。因此,为构建的管道复制这些模式的能力非常重要。但是没有必要去猜测时间序列的低频波动(例如趋势或季节性)。KNN 模式适合这些任务。链合成后获得的预测质量度量是 MAE-88.19 和 RMSE-177.31。
需要注意的是,我们已经在自动模式下准备了一个解决方案,并且没有向搜索算法添加任何额外的专家知识。这个任务在笔记本电脑上运行的框架只用了 5 分钟就解决了。毫无疑问,对于大型数据集,构建一个好的管道需要更多的时间。
与竞争对手的比较
D isclaimer:本节中的比较远非详尽无遗。为了证明一个框架比另一个框架更好或更差,您需要进行更多的实验。建议使用一个以上的数据源,应用交叉验证,对相同的数据和相同的参数运行算法几次(对指标进行平均)。在这里,我们有一个介绍性的比较:我们展示了如何替代解决方案可以应付这项任务。如果你对 FEDOT 与其他框架相比如何处理时间序列感兴趣,请关注 ResearchGate 的新闻。一篇科学论文中的全面比较将很快问世!
让我们试着比较一下 FEDOT 和其他开源的时间序列预测框架——AutoTS和 pmdarima 。Jupyter 笔记本的代码,以及情节,可通过链接获得。因为不是所有的库都在多个块上实现验证功能,所以决定只在时间序列的一个片段上进行这个小的比较。每个算法运行 3 次,并对误差指标进行平均。包含指标的表格如下所示(单元格显示 std —标准偏差):
该图还显示了其中一个实验的预测:
通过竞争算法获得的预测示例(图片由作者提供)
从图中可以看出,用 FEDOT 得到的预测更“接近实际数据”。
结论
所以,今天我们看到了像 AutoML 这样一个越来越受欢迎的机器学习领域。在本帖中,我们回顾了自动生成 ML 管道的现有解决方案,并指出它们如何用于时间序列预测任务。
我们还在使用 FEDOT 框架预测发电量序列的例子上尝试了 AutoML:我们恢复了丢失的值,使用进化算法构建了管道,并验证了解决方案。最后,演示了 FEDOT 与其他框架在这一任务上的简单比较。
这篇文章中的例子(代码和图表)可以通过链接在 github 库中找到。
对于那些决定深入研究的人,有几个额外的链接:
- 带有 FEDOT 的 Github 存储库
- 为框架开发的 web 模块的 Github 存储库— FEDOT。网络
- 聊天为 FEDOT 讨论和解决问题
用 AutoML,试试 FEDOT!
米哈伊尔·萨拉法诺夫、帕维尔·维楚查宁和尼古拉·尼基丁参与了这篇文章的工作。
时间序列的 AutoML:绝对是个好主意
原文:https://towardsdatascience.com/automl-for-time-series-definitely-a-good-idea-c51d39b2b3f?source=collection_archive---------3-----------------------
利用 AutoML 进行时间序列预测的方法及自动预测的实例
用于时间序列预测的 AutoML(图片由作者提供)
目前,数据科学已经成为 IT 行业的重要组成部分,并为业务提供了有用的功能。数据科学家收集和过滤数据。他们训练大量的 ML 模型,执行验证并选择最好的一个。而做这一切活动的主要原因是为了做一个面向商业的产品,这将是最有效的(带来更多的钱)。这些活动可以表示为机器学习工作流。
同时,一些阶段逐年深入自动化。首先,这种自动化触及工作流程中最枯燥的部分。因此,它允许数据科学家将节省下来的时间用于更令人兴奋的任务。
http://memegenerator.net/
让我们假设我们有一个任务:建立一个机器学习模型,然后将其部署到一个 web 应用程序中。例如,这个模型必须预测顾客今天将在网上商店支付多少钱(或其他任何东西)。但是在我们开始训练我们模型之前,有必要克服几个步骤:
- 从各种来源收集数据;
- 执行预处理操作,如标准化、编码等。;
- 功能工程、移除功能或辛迪思新功能;
- 进行过滤,例如去除异常值;
机器学习流水线 这样的多步序列被称为“流水线”。由于管道的复杂结构,使用管道比使用单个机器学习模型更难。此外,对于这种多步结构,故障的概率变得更高。为了控制和管理包含多个 ML 操作的复杂系统,构建了特定的仪器— MLFlow 、 Apache AirFlow 。它们类似于数据科学和机器学习领域的工作流管理系统(WMS)。您使用它们的原因是为了简化 ML 管道的管理。
http://memegenerator.net/
自动生成管道可能是一项更加雄心勃勃的任务。有几个框架可以做到这一点。开源库有 TPOT 、自动克隆、 MLJAR ,或者 H2O 。这些框架正在尝试 toя解决的任务“生成管道,这将在最终预测上给出最低的误差”。在绝大多数情况下,管道的结构是固定的,只有超参数在变化。但是有几个框架能够自己找到管道结构。这种优化任务(寻找具有可变结构的流水线)通常使用进化算法来解决,例如,TPOT 和 FEDOT 框架。也有专有的 SaaS 产品,如 DataRobot 、 GoogleAutoTables 和 Amazon SageMaker 。
通常,AutoML 库和服务只有效地解决广泛的任务:对表格数据的分类和回归。不太常见的是,AutoML 支持文本和图像处理、时间序列预测任务。在本文中,我们将不考虑 AutoML 库的优缺点,但是我们将分析它们在时间序列预测中的能力。
时间序列的自动机器学习
尽管事实上时间序列预测任务在科学和商业中是一个相当受欢迎的任务,但是大多数开源 AutoML 库并没有提供为时间序列处理生成流水线的工具。这可能有几个原因,其中之一是在不重构用于其他任务(分类和回归)的工具的情况下,很难使当前的库功能适应预测序列。
关键是时间序列数据的处理不同于解决回归问题时通常的一系列操作。差异从原始样本的划分开始:例如,以随机顺序混合数据来验证时间序列模型是没有意义的。对于时间序列,特征的形成是不同的:通常,机器学习模型不会在原始序列上训练,因为需要将其转换为另一种表示。在已经存在的具有自身特性的 AutoML 项目中实现这样的构造可能会有问题。最有可能的是,这就是为什么开发人员经常拒绝从时间序列(以便“不要一石二鸟”)和集中处理特定的数据类型:只有表格,或只有文本。
一些决定支持时间序列预测的研究人员受限于这种类型的数据。一个很好的开源例子是 AutoTS 框架。这类图书馆通常使用“经典”统计模型进行预测,例如 AR 或 ARIMA。在框架的“内部”,这些模型被调整,然后选择最好的一个(通过验证样本的误差度量),但是这里没有生成新的模型。此外,pmdarima 库基于相同的逻辑。
另一种方法是将现成的 AutoML 工具用于预测。回归模型非常适合这种情况。例如,这种逻辑被用于 H2O,在那里,在其商业版本的产品开发商提供了这样一种可能性。然而,从一些使用开源版本的例子来看,用户将不得不手动预处理原始系列。这样一个精简的工具包可能不足以完成整个工作。
我们希望 AutoML-toolkit 具有哪些功能?
虽然预测一维数组行为的任务看起来很琐碎,但工程师在处理时间序列时希望拥有各种工具。例如:
- 能够构建可解释的模型集合(例如,使得第一个模型再现时间序列的高频分量,第二个模型能够模拟低频分量,第三个模型组合它们的预测);
- 能够调整时间序列管道中的超参数;
- 使用外生(辅助)时间序列;
- 应用特定的预处理方法(从移动平均平滑到 Box-Cox 变换);
- 应用样本内和样本外预测;
- 如果时间序列包含间隙,如何修复它们?
在一个框架中考虑所有列出的可能性,而不仅仅局限于时间序列,这是一项相当困难的任务。
对 AutoML 的这些要求并不是偶然出现的。我们在自然系统模拟 (NSS 实验室)工作,在过去的几年里,我们参与了几十个机器学习、数据驱动建模和优化方面的各种研究和商业项目。在实践中,我们经常要解决类似的问题,包括时空数据预测。
我们是谁 我们为什么担心 AutoML
不久前,我们对 AutoML 研究产生了兴趣,团队也有了新的实验想法。最终,这些想法形成了一个成熟的开源 AutoML 框架,由我们在实验室中开发和维护。
我们还希望在单个管道中自动解决一个以上的问题,即回归问题和时间序列预测问题,或者同时解决回归和分类问题。例如,在信用评分任务中,即潜在借款人的二元分类中,您不仅可以使用问卷特征,还可以使用即将到来的现金流值,这些值可以作为时间序列进行预测。在我们看来,自动获得这些任务的基线是非常有希望的。
我们还对研究识别可变结构管道的方法感兴趣,并使用多标准优化来优化建模误差和找到的解决方案的复杂性(例如,可以通过管道中的总块数来估计)。
我们在其中一些问题上获得了有趣的结果,如果感兴趣,可以在这里和这里找到关于它们的科学论文。下面,我们将重点讨论预测时间序列的问题,并讨论如何在此类任务中使用 AutoML,尤其是 FEDOT。
利用 FEDOT 框架进行时间序列预测
FEDOT 可以解决的任务(图片由作者提供)
正如你从我们之前的帖子中所知,FEDOT framework 可以使用进化算法为各种任务自动生成 ML 管道。下面,我们以 FEDOT(版本 0.3.0)为例,演示如何使用 AutoML 工具预测交通量的时间序列。这个版本可以很容易地通过命令安装
pip install fedot==0.3.0
Jupyter 笔记本,通过链接提供代码和图表。
我们有交通量的时间序列,它以客车为单位显示明尼苏达州明尼阿波利斯和圣保罗之间 94 号州际公路沿线的交通量。该数据包含每小时交通量值,每天有两个高峰:早上和晚上。此外,对于该数据,周末的流量通常会减少。
假设我们必须预测 144 个流量元素(我们随机选择了这个值,我们不希望预测范围太大或太短)。意思是需要搞清楚未来六天这条路上会有多少乘客经过。
进口
*# FEDOT api* **from** **fedot.api.main** **import** Fedot*# Tasks to solve* **from** **fedot.core.repository.tasks** **import** Task, TaskTypesEnum, TsForecastingParams*# Input data for fit and predict* **from** **fedot.core.data.data** **import** InputData*# Train and test split* **from** **fedot.core.data.data** **import** train_test_data_setup
首先,我们需要定义任务和预测范围
forecast_length = 144
task = Task(TaskTypesEnum.ts_forecasting,
TsForecastingParams(forecast_length=forecast_length))
为模型准备输入数据
*# Load data from csv file and wrap it into InputData structure* input_data = InputData.from_csv_time_series(task, 'ts_traffic.csv', target_column='value')*# Divide into train and test* train_data, test_data = train_test_data_setup(input_data)
发布模型:拟合并做出预测
*# Init model for the time series forecasting* model = Fedot(problem='ts_forecasting',task_params=task.task_params)*# Run AutoML model design* chain = model.fit(features=train_data)*# Use model to obtain forecast* forecast = model.predict(features=test_data)
获得的预测可以在下图中看到:
AutoML FEDOT 模型预测(图片由作者提供)
从图中可以清楚地看出,获得的模型善于猜测数据中的模式,并且可以近似一天内的波动(早晚高峰时间)和周末交通流量的减少。而且只需要两分钟的计算就能得到这样的结果!
让我们来看看生产出来的管道:
机器学习管道,由 AutoML 框架 FEDOT 获得(图片由作者提供)
从图中可以看出,结果链由两个操作组成。“滞后”操作提供了时间序列的滞后(令人惊讶的)转换。我们将在下一篇文章中讨论这个问题。
结论
今天,我们已经讨论了几种自动机器学习技术。我们讨论了如何在自动模式下预测时间序列和识别预测模型。我们已经使用一个简单的例子检查了 AutoML 解决方案的功能。
在接下来的文章中,我们将仔细研究使用 AutoML 预测时间序列的所有困难。我们将详细分析 FEDOT 框架在真实世界数据上的能力。
一些有用的链接:
- 采用 FEDOT 框架的 Github 知识库
- 带示例的笔记本
米哈伊尔·萨拉法诺夫、帕维尔·维楚查宁和尼古拉·尼基丁参与了这篇文章的写作。
Python 中的 AutoML:Hyperopt sk learn 和 TPOT 的比较
原文:https://towardsdatascience.com/automl-in-python-a-comparison-between-hyperopt-sklearn-and-tpot-8c12aaf7e829?source=collection_archive---------27-----------------------
数据分析
两种流行的 Python AutoML 库的优缺点
图片来自 Pixabay
自动化机器学习 ( AutoML )涉及将机器学习应用于现实世界问题的任务的自动化。AutoML 涵盖了从原始数据集到可部署的机器学习模型的完整管道。
Python 提供了一些提供 AutoML 的库。在本教程中,我比较了两个流行的库:Hyperopt Sklearn 和 TPOT。存在另一个库,名为 AutoSklearn ,本文没有对其进行测试,因为它与一些操作系统不兼容。
这两个被分析的库都与 scikit-learn 兼容,后者是著名的用于机器学习的 Python 库。
本教程的完整代码可以从我的 Github 库下载。
作为本教程的用例,我利用了由 Kaggle 库提供的heart.csv
数据集。数据集关注心脏病发作,包含 14 个输入特征,并提供二元分类作为输出(心脏病发作是或否)。
1.远视 Sklearn
这个库很容易安装,如文档中所解释的,并且使用起来非常简单。文档简单明了。它支持许多scikit-learn
分类器、回归器和预处理模型。为了建立一个 AutoML 模型,创建一个HyperoptEstimator()
的实例,配置一些参数(如估计类型),然后拟合模型就足够了。HyperoptEstimator
的bestmodel()
返回一个包含完整scikit-learn
管道的对象。
让我们假设X
和y
分别包含输入特征和目标。我们可以通过scikit-learn
函数train_test_split()
将它们分成训练集和测试集:
from sklearn.model_selection import train_test_splitX_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=42)
现在我们可以训练HyperoptEstimator
搜索最佳分类器:
from hpsklearn import HyperoptEstimatorestim = HyperoptEstimator()
estim.fit( X_train, y_train )
我们可以得到最好的模型:
best_model = estim.best_model()
它给出了以下输出:
{'learner': ExtraTreesClassifier(criterion='entropy', max_features='sqrt', n_estimators=13,
n_jobs=1, random_state=4, verbose=False),
'preprocs': (),
'ex_preprocs': ()}
键/值对learner
包含最佳模型,第二个模型(preproc
)包含应用的预处理技术。在这种情况下,它是空的。
Hyperopt Sklearn 库反映了机器学习的随机性质:事实上,如果我们试图在相同的训练集上再次运行分类器,我们会获得另一个结果。
使用相同的训练集运行相同的代码(不执行再次训练/测试分割),我们获得以下最佳模型:
{'learner': GradientBoostingClassifier(learning_rate=0.00813591154617836, max_depth=None, max_features=0.6562885234780235, min_samples_leaf=11, n_estimators=63, random_state=0, subsample=0.68797222866341),
'preprocs': (MinMaxScaler(feature_range=(-1.0, 1.0)),),
'ex_preprocs': ()}
反正我们可以计算模型的性能。我们可以利用内置函数score()
或者定义我们的性能指标。在最后一种情况下,首先,我们必须将获得的预处理(如果有的话)应用于测试集,并将预测结果与实际值进行比较:
X_test_norm = X_test
if len(best_model['preprocs']) > 0:
preprocs = best_model['preprocs'][0]
X_test_norm = preprocs.transform(X_test)
Hyperopt Sklearn 库不提供predict_proba()
函数,因此我们必须手动计算:
model = best_model['learner']
y_score_hp = model.predict_proba(X_test_norm)
然后,我们可以绘制由scikitplot
库提供的 ROC 曲线和精确召回曲线,如下所示:
import matplotlib.pyplot as plt
from sklearn.metrics import roc_curve
from scikitplot.metrics import plot_roc,auc
from scikitplot.metrics import plot_precision_recall# Plot metrics
plot_roc(y_test, y_score_hp)
plt.show()
plot_precision_recall(y_test, y_score_hp)
plt.show()
作者图片
作者图片
我们还可以计算精确度、召回率和准确度:
y_test_pred = model.predict(X_test_norm)
accuracy = accuracy_score(y_test, y_test_pred)
precision = precision_score(y_test, y_test_pred)
recall = recall_score(y_test, y_test_pred)print('accuracy: %s ' %(round(accuracy, 2)))
print('precision: %s ' %(round(precision, 2)))
print('recall: %s ' %(round(recall, 2)))
它给出了以下输出:
accuracy: 0.85
precision: 0.85
recall: 0.9
在我的 Github 存储库中可用的完整代码中,我还通过 10 重验证计算了所获得模型的精度、召回率和准确度。下图显示了折叠次数的精度趋势:
作者图片
我注意到模型没有过度拟合。
2.TPOT
TPOT 是 AutoML 的另一个 Python 库。它的文档做得很好。然而,安装它并不简单,因为它是建立在其他库的基础上的,因此你必须先安装它们才能让 TPOT 工作和运行。个人觉得在正确安装之前遇到了很多问题。
一旦安装完毕,我们就可以创建一个评估器,或者是一个TPOTClassifier()
或者是一个TPOTRegressor()
。在我们的例子中,我们构建了一个 TPOT 分类器:
from tpot import TPOTClassifiertpot = TPOTClassifier(generations=5, population_size=50, random_state=42)
tpot.fit(X_train, y_train)
这个过程非常缓慢,需要一段时间才能完成。我们可以计算模型的精度、召回率和准确度:
y_test_pred = tpot.predict(X_test)
accuracy = accuracy_score(y_test, y_test_pred)
precision = precision_score(y_test, y_test_pred)
recall = recall_score(y_test, y_test_pred)
print('accuracy: %s ' %(round(accuracy, 2)))
print('precision: %s ' %(round(precision, 2)))
print('recall: %s ' %(round(recall, 2)))
它给出了以下输出:
accuracy: 0.8
precision: 0.84
recall: 0.81
关于通过 Hyperopt Sklearn 获得的最佳模型,TPOT 表现较差。
TPOT 也提供了predict_proba()
方法,可以用来计算 ROC 曲线和精确召回曲线。
作者图片
作者图片
我们可以通过scikit-learn
管道访问最佳模型:
tpot.fitted_pipeline_
它给出了以下输出:
Pipeline(steps=[('logisticregression',
LogisticRegression(C=20.0, random_state=42))])
虽然在文档中提到模型可能在相同的数据集上产生不同的最佳模型,但是在我们的例子中,在相同的数据集上运行更多次相同的代码会返回相同的模型。
现在,我可以通过 10 重交叉验证来计算精确度、召回率和准确度。TPOT 本身提供了交叉验证。然而,在这种情况下,我们手动计算它,因为我们想要绘制度量相对于每个折叠的趋势。
下图显示了精度趋势。对于其他情节(回忆和准确性),请检查我的 Github 库:
作者图片
关于 Hyperopt Sklearn 库,TPOT 似乎更稳定,有不同的数据集。
摘要
在本文中,我们比较了两个流行的用于 AutoML 的 Python 库:Hyperopt Sklearn 和 TPOT。
远视 Sklearn
优点
- 易于安装
- 快的
- 最佳模型达到高性能
缺点
- 相同(简单)数据集的不同最佳模型
- 简单和糟糕的文档
TPOT
优点
- 对于相同(简单)的数据集,总是相同的最佳模型
- 写得好的文件
- 最佳模型达到良好的性能
缺点
- 非常慢
- 难以安装
如果你想了解我的研究和其他活动的最新情况,你可以在 Twitter 、 Youtube 和 Github 上关注我。
相关文章
[## 如何使用 scikit-learn 检查分类模型是否过度拟合
towardsdatascience.com](/how-to-check-if-a-classification-model-is-overfitted-using-scikit-learn-148b6b19af8b)
汽车 vs HPO vs 现金:有什么区别?
原文:https://towardsdatascience.com/automl-vs-hpo-vs-cash-what-is-the-difference-38c8e0a9d93b?source=collection_archive---------35-----------------------
AutoML 将逐渐取代人类专家分析师提供的功能,但不仅仅是提供预测模型
照片通过 Shutterstock
自动化机器学习,或简称为 AutoML 正在兴起。越来越多的商业产品出现在市场、学术工具和公共的开源 AutoML 库中。正如每一种新的、不清楚的、定义模糊的新技术一样,AutoML 被误解了。一方面,有浮夸的说法称它将把数据分析师送回家,另一方面,有极端的说法称它只自动化了分析的琐碎部分。这是因为不同的人对 AutoML 给出了不同的定义。让我们检查一下。
(预测性)AutoML 的愿景:AutoML 到底是什么?维基百科将其定义为端到端的机器学习过程的自动化。但是机器学习不是已经自动化了吗?我有一个数据集,我用默认的超参数值运行一个学习算法(例如,随机森林,SVM ),然后,我有了一个模型实例。那是自动的,不是吗?那么,有什么大惊小怪的?
AutoML 的目标是逐渐取代越来越多由人类专家分析师提供的功能。这些不仅仅是交付预测模型。优秀的数据科学家会为您提供图表、视觉效果、解释、见解和建议。他们不仅会确定要尝试的适当分类算法,还会对数据类型进行专门的预处理,尝试数据或 ML 任务的各种表示,并应用特征提取方法。而且不止于此。模型投入生产后,数据分析师需要持续监控预测的健全性,以防数据统计分布漂移。如果是这种情况,则需要标记一个警报,并且需要对模型进行重新训练。最重要的是,一个好的分析师将帮助你基于你的模型做出最优决策,比如当你应用模型时,最优的分类阈值是什么,以及哪些因素(特征、变量)可能会影响你的订户的行为。这就是 AutoML 应该做的。AutoML 是最终目标,但我们还没有完全实现。
超参数优化(HPO):AutoML 平台的一个子问题是在其处理的所有可用算法中提供最好的可能模型实例。这些算法中的每一个都可以使用超参数进行“调整”。超参数是修改其行为的算法的输入。使用不同的超参数值运行相同的算法可能会导致完全不同的预测模型实例。因此,出现的问题是如何调整它们的值并获得可能的最佳模型实例。超参数的解释通常与它们对检测模式和拟合数据的敏感性有关。例如, K- 最近邻中的 K 越低,或者岭逻辑回归中的权重惩罚λ越低,模型将越复杂,模型将越好地拟合训练数据,并且过度拟合模型的概率越高。一些算法接受不止一个超参数,例如,XGBoost 算法接受大约 12 个与调整学习性能相关的超参数!调整算法的超参数可以大大提高预测性能!以我们的个人经验来看,调优“几个好的算法”可以说比使用大量默认设置的算法更重要。超参数优化(HPO)是自动调整给定算法的超参数的问题。几个基本的和先进的算法已经出现在 HPO 的文献中。HPO 算法尤其具有挑战性,因为它需要调整许多超参数。
组合算法和超参数选择(CASH): HPO 通常用于优化单个算法的超参数。然而,预测建模算法的选择(例如,SVM 对随机森林)也可以被编码为数字超参数:1 表示 SVM,2 表示 RFs,等等。此外,可以在建模之前应用一系列分析步骤,例如预处理、缺失值插补和特征选择。因此,分析的每一步都需要考虑算法选择和超参数调整。当除了超参数值之外还进行算法选择时,使用的更具体的术语是组合算法和超参数选择算法,或现金*。*
汽车、现金和 HPO 的区别。几个非常流行、特别有用、非常成功的免费软件库,像 auto sklearn 、 TPOT 和Gamma*在我们看来更好的描述是 CASH 或 HPO 库,而不是 AutoML 。所以,这就是不同之处:*
现金 自动搜索最优预测模型。
让我们用一个例子来说明不同之处。我们考虑了[1]测量 48 名阿尔茨海默病患者(病例)和 22 名年龄匹配的健康受试者(对照组)血液中 503 种 miRNA 表达的数据。任务是学习阿尔茨海默病状态的分类模型(二元分类)并估计其样本外预测性能。此外,还需要确定最佳预测所需的特征(在这种情况下是血液生物标志物),并了解它们的作用和重要性。我们在这个问题上应用了我们的 AutoML 平台,叫做 JADBio 。可以在这里访问实际成绩(https://app . jad bio . com/share/f 0 DCE 75d-612 c-4160-9256-55 b5 af 98 D2 d 2)。
首先, JADBio 解决了一个 CASH 问题,为预处理、特征选择和建模步骤选择算法,以及它们对应的超参数值,从而得到一个最佳预测模型。有 3017 种不同的算法和超参数值的组合被尝试(称为配置)来识别胜出者。每种配置都经过交叉验证,以评估性能和最终赢家,从而产生 90510 个经过训练的模型实例。获胜配置和分析报告如下图所示:
********
图 1: JADBio 对 lei dinger et al . 2013[1]48 名阿尔茨海默病患者和 22 名对照受试者的 miRNA 数据的分析报告。分析步骤的第一行显示了产生最佳模型实例的成功的 ML 管道(配置)。90510 个模型实例在 34 '内的 3017 个配置中被训练(适合)。
到目前为止,你可以从任何其他的 CASH 算法,比如 auto sklearn,得到相似类型的输出。这就是差异开始的地方。下图显示了模型的样本外(即新的、未见过的样本)性能的估计值。相比之下,像 auto sklearn 这样的现金库不会为您自动进行性能评估。作者建议您省去一个保留集来评估性能。JADBio 强调精确的性能评估,即使是小样本。它在内部自动执行所有必要的交叉验证;它还调整了“赢家的诅咒”的性能估计,即,为了选择最佳配置,已经尝试了许多配置。“未经调整的估计值”是没有经过这种调整的交叉验证的估计值,是一种高估(参见[2]了解更多信息)。 JADBio 也输出 ROC 曲线。曲线上的圆圈表示不同概率分类阈值的模型的不同操作点。绿色圆圈对应于阈值 0.46。将具有高于 0.46 的模型概率的受试者分类为患有阿尔茨海默氏病使得该模型在 ROC 上的该点上运行,其中它实现了 0.15 的假阳性率和 0.93 的真阳性率。用户可以点击任何圆圈,并获得模型的假阳性率和真阳性率之间的相应权衡。这是支持在模型操作环境中使用的分类阈值优化的一种方式。
图 2: JADBio 报告样本外接收操作特性(ROC)。它通过为阈值的不同选择提供估计来促进最佳分类阈值的优化。曲线上的每个圆圈对应于不同的阈值(底部 x 轴)以及假阳性率(x 轴)和真阳性率(y 轴)之间的不同权衡。例如,将任何概率高于 0.46(右侧摩天大楼点)的新样本分类为患有阿尔茨海默氏病,会导致选择 FPR 为 0.15、TPR 为 0.93 的绿色圆圈。每个轴上的置信区间显示为绿色十字。
JADBio 的配置还包括特性选择。因此,用户被告知测量和获得最佳性能所需的最小特征集。下图(子图(A))显示了 503 个特征中的 3 个特征被选择用于模型包含。大多数 CASH 库现在不同时执行特征选择和建模,尽管这可能会改变。无论如何, JADBio 的目标不仅仅是选择特性,还包括自动解释它们的作用和重要性。ICE 曲线[3]显示了每个特征,试图解释它们在预测中的作用。ICE 曲线显示,平均而言,作为特征值的函数,模型预测的成为阿尔茨海默病受试者的概率。在本例中,我们放大了第一个特征的 ICE 图(面板 B)。我们推断这一特征是疾病的风险因素:其值越高,平均而言,阿尔茨海默氏症模型的概率输出越高。请注意,准确的预测取决于所有 3 个选定的特征,并且根据其他两个特征的值而变化。这种差异在 ICE 图中用灰色区域表示。为了便于解释重要性,它们的附加值显示在特征重要性面板中。它显示了当从模型中删除一个功能,并且只删除该功能时,预期的性能下降。总的来说,AutoML 为从业者提供了一套功能来决定测量哪些特性以及如何解释它们的作用。**
图 3: A)最终模型的特征(所选特征), B)特征 hsa-miR-30d-5p 的 ICE 图,以及 C)如果特征被排除在特征之外,基于相对性能下降的特征重要性。
还有其他的视觉和输出来促进解释和决策。这些包括自动识别可能错误标记的样本和“难以预测”的样本(当前可用)、可能损坏的样本(“脏数据”)、对单个预测的解释(尚不可用)等等。AutoML 正面处理问题的解释和说明。视角发生了转变:当生产出一个模型实例时,HPO 和卡什就停止了。对于 AutoML 来说,这只是一个起点。
由 Ioannis Tsamardinos(克里特岛和亚德比奥大学)、Zacharias Papadovasilakis(亚德比奥大学)、Giorgos Papoutsoglou(克里特岛大学)和 Vassilis Christophides(法国恩塞阿)研究和撰写
参考
[1] P. Leidinger,C. Backes 和 S. Deutcer,“阿尔茨海默病患者的基于血液的 12-miRNA 标记。、“基因组生物学,第 14 卷第 7 期,R78 页,2013 年。**
[2] I. Tsamardinos,E. Greasidou 和 G. Borboudakis,“引导样本外预测实现高效准确的交叉验证”,机器学习,第 107 卷第 12 期,第 1895–1922 页,2018 年。**
[3] C. Molnar,“5.2 个人条件期望(ICE)”,载于可解释机器学习。使黑盒模型变得可解释的指南。,2021 年。**
AutoML 不会取代你的数据科学职业
原文:https://towardsdatascience.com/automl-will-not-replace-your-data-science-profession-52753a4a53ed?source=collection_archive---------22-----------------------
让我们通过机器学习过程的步骤来找出“为什么?”
亚历山大·奈特在 Unsplash 上拍照
许多已经是数据科学家或数据科学领域新手的人正在寻找问题“AutoML(自动机器学习)会取代数据科学家吗?” 问这样一个问题是非常合理的,因为自动化已经被引入到机器学习中,并且它在现代世界中发挥着关键作用。除此之外,想要成为数据科学家的人正在思考如何在就业市场中长期获得一席之地。
AutoML 会而不是取代你的数据科学职业。它只是为了让你的事情变得更简单,比如协助你完成枯燥的重复性任务,节省你的宝贵时间,协助你进行代码维护和一致性等!
让我们通过机器学习过程的步骤来找出“为什么 AutoML 不会取代你的数据科学专业?”。我们还将讨论一些可以应用于机器学习过程的流行自动化选项。在这篇文章的结尾,你会意识到 AutoML 将而不是取代你的数据科学职业。
让我们介绍一些关键的定义
基本上, 机器学习 就是在没有明确编程的情况下,计算机从数据中学习的能力。它与传统编程有所不同。 自动化 是一个需要最少人工投入的过程。存在各种类型的自动化。只有 AI 自动化 使用机器学习。它是自动化和机器学习相结合的东西。人工智能自动化系统可以根据数据进行学习和决策。将自动化应用于机器学习意味着我们使用自动化选项,以最少的人力来实现机器学习过程中的一些重复任务。
机器学习过程的步骤
下图显示了机器学习过程的步骤,分为三个主要类别——通常为,自动化适用,半自动适用和通常为,自动化不适用。
(图片由作者提供)
让我们详细讨论每个步骤。
问题定式化
这才是真正需要数据科学家的地方。因为每个问题都是不同的,所以问题的表述不能自动化。它需要大量的领域知识。解决问题没有单一的方法。数据科学家应该根据给定的场景使用不同的策略。这是 AutoML 无法处理的事情。在这一步,AutoML 无法取代数据科学家。
收集数据
数据科学家或数据工程师应该决定需要收集的数据类型和数量。这取决于他们想要解决的问题。这些事情不能自动化。但是,他们可以使用相关的自动化选项进行数据挖掘,以避免重复的任务。因此,数据收集可以是半自动的!这一步仍然需要数据科学家,AutoML 不能完全取代数据科学家。
数据清理
数据科学家和数据工程师将 60–70%的时间花在数据清理上。这是因为每个数据集都是不同的,它需要特定领域的知识。这是机器学习过程中最重要的一步。数据清理包括处理缺失值、异常值检测、分类变量编码等。处理缺失值是数据科学家最耗时的部分。离群点检测涉及到很多领域知识。如果我们检测到一个异常值,我们下一步应该做什么?我们应该移除它吗?我们应该保留它吗?或者我们应该用一个相关的值来代替它?这取决于特定分析问题的领域知识。一个离群值背后可能有一个有趣的故事。这些事情是自动化系统无法完成的。所以,这里需要数据科学专业人才。
型号选择
(图片由作者提供)
模型选择是指选择一个合适的机器学习算法来解决你的问题。数据科学家或机器学习工程师应该做出多项决策,以选择最佳算法。这个要看你手里的问题类型和收集的数据量和类型。如果您的数据有标注(基础真值),您可以选择像回归或分类(监督方法)这样的算法。如果标注是类值,则可以选择分类算法。如果标签是连续值,您可以选择回归算法。如果您有非线性数据,您可以选择非线性分类器或回归器(例如随机森林、决策树、XGboost)。如果您有线性数据,您可以使用线性回归器进行回归任务,使用具有线性核的支持向量机进行分类任务。如果您的数据不包含任何标签(基础真值),您可以选择像降维或聚类(非监督方法)这样的算法。如果您仍然希望找到未标记数据背后的隐藏模式,可以在已知聚类数的情况下使用 KMeans 算法。如果聚类数未知,可以尝试 MeanShift 算法。如果你想降低数据的维数,你可以对线性数据使用 PCA 或 LDA 算法,对非线性数据使用核 PCA,t-SNE 算法。算法的选择也取决于你拥有的数据量。一般来说,算法的选择取决于各种标准。数据科学专家应该想出一个办法来自动化这些事情。现在也有一些 Python 框架可用。但是,他们不能完全自动化这一过程。
特征选择
所选择的算法应该能够通过考虑特征的重要性来选择特征。向后消除、向前选择和随机森林方法可用于特征选择。这些算法可以自动选择最佳特征,但数据科学家仍应在使用这些方法之前手动设置参数值。这意味着这里也需要数据科学家。
超参数调谐
模型参数在训练过程中从输入数据中学习它们的值。相反,模型超参数在训练过程中不学习它们的值。因此,数据科学专业人员应该在训练过程之前指定模型超参数的值。机器学习模型通常会包含许多超参数。数据科学家的任务是为每个超参数尝试不同的值,并找到超参数值的最佳组合。如果他们一个接一个地手工操作,将需要很长的时间。自动化选项,如网格搜索或随机搜索可用于此。大多数时候,超参数调整过程包含数百甚至数千次迭代,数据科学家无法手动处理。一些超参数包含从 0 到正无穷大的值。数据科学家的任务是使用领域知识缩小超参数值的范围,然后应用网格搜索或随机搜索来实现最佳调整过程!
模型评估
模型评估过程确保模型很好地符合训练数据,并且也可推广到新的未见过的数据。对于监督学习,模型评估过程很容易,因为标签(基础真值)是可用的。相比之下,在标签(基础真值)不可用的无监督学习中,模型评估具有挑战性。在无监督学习中,很难找到任何用于模型评估的自动化选项。
数据科学家的主要职责
现在,我们可以弄清楚数据科学家在机器学习过程中的一些关键职责。
- 数据科学家应该把问题公式化。
- 数据科学家应该指导算法如何从数据中学习。
- 他们应该确定特征(变量)之间的真实关系。
- 他们应该为算法提供准备充分的足够数量的数据。
- 在大多数情况下,他们应该能够解释模型及其最终输出。
当承担这些责任时,数据科学家可以对机器学习过程的某些部分使用自动化选项。但是,AutoML 不能完全取代数据科学家的这些职责。
可用于机器学习任务的自动化选项
在本节中,我们将介绍一些可以应用于机器学习过程步骤的自动化选项。一些方法还包含 Python 代码。
使用 cross_val_score() 进行交叉验证
我们可以通过交叉验证使用 sci kit-learncross _ val _ score()函数进行模型评估。以下 Python 代码对基于“房价数据集”构建的回归模型执行交叉验证。
通过交叉验证进行模型评估的 Python 代码(等到加载!)
(图片由作者提供)
这里,我们用不同的数据折叠对模型进行了几次训练,然后得到了平均 RMSE 值。但是我们没有手动完成这个过程,而是使用 sci kit-learncross _ val _ score函数自动完成了这个过程。因此,自动化可以用来处理模型评估中的重复性任务。
超参数调谐用 g rid 搜索
我们可以使用 Scikit-learnGridSearchCV()函数进行超参数调整。以下 Python 代码为基于“房价数据集”构建的回归模型执行超参数调整。
超参数调优的 Python 代码(等到加载!)
(图片由作者提供)
这里,我们在RandomForestRegressor中调 3 个超参数【max _ depth】【min _ samples _ leaf】和【max _ features】。因此,超参数空间是三维的,所以每个组合包含 3 个值。组合数为 192 (8 x 8 x 3)。这是因为 max_depth 包含 8 值,min _ samples _ leaf包含 8 值, max_features 包含 3 值。这意味着我们训练 192 个不同的模型!在 5 重交叉验证过程中,每个组合重复 5 次。因此,总迭代次数为 960 (192 x 5)。但是还要注意,每个 RandomForestRegressor 有 100 个决策树。所以,总计算量是 96000(960 x 100)!自动化流程让数据科学家的工作变得更加轻松。
使用 Pipeline() 训练多个模型
通过使用 Scikit-learnPipeline(),我们可以自动化多个复杂模型的训练过程。下图显示了构建多项式回归模型的一般工作流程。应该按照给定的顺序应用这些步骤。
多项式回归模型的一般工作流程(图片由作者提供)
流水线通过顺序地应用一系列转换器和最终预测器来自动化训练过程。在我们的工作流程中,
- StandardScaler() 是变压器。
- PCA() 是变压器。
- 多项式特性()是变压器。
- LinearRegression() 是预测器。
以下 Python 代码将自动执行上述工作流。
多项式回归模型的一般工作流程的 Python 代码(等到加载!)
现在,您可以通过一个来训练所有的估计器。调用 fit()。
*ploy_reg_model.fit(X,y)*
其他自动化选项
下面是本文中不会详细讨论的其他流行自动化选项的列表。
- PyCaret —这是 r 中可用的 Caret 包的 Python 版本,PyCaret 中的大多数机器学习任务就像函数调用一样简单。你可以用几行代码训练和可视化多个机器学习模型。
- 微软 Azure AutoML——这将自动化应用于具有速度和规模的机器学习模型。如果将此与 Microsoft Power BI 相结合,您可以从数据中获取最大价值。
- TPOT —这是一个 Python 库,通过应用自动化来处理机器学习任务。
- Google Cloud AutoML —你可以用最少的努力训练出高质量的定制机器学习模型。
关键要点
现在,你对 AutoML 以及它如何应用于机器学习任务有了清晰的理解。我们已经走过了机器学习过程的步骤,并找到了“AutoML 不会取代你的数据科学专业”的原因。我们还讨论了目前可用的一些自动化观点。你可以试试它们!在以后的文章中,我也会谈到其中的一些。
有两件明显的事情无法完全自动化机器学习过程:
- 对领域知识的需求
- 未标记数据的存在(在无监督学习中)
因为这些东西,AutoML 无法取代数据科学家。
除此之外,我想给你以下两条关于使用 AutoML 的建议:
- 如果你是数据科学或机器学习领域的新手,不要从像微软 Azure AutoML 或谷歌云 AutoML 这样易于使用的框架开始你的机器学习过程。与其这样,不如学习 Python(或者 R)及其相关包。在你对机器学习理论和那些包有了扎实的基础知识之后,你可以试试微软 Azure AutoML 或者谷歌云 AutoML 。这样做将为成为该领域的大师创造一条漫长而清晰的道路。
- 当你学习数据科学和机器学习时,更多地关注数据清理任务,如处理缺失值、离群点检测、特征编码和无监督学习方法。除此之外,更多地关注获取特定问题的领域知识,并用简单的英语解释你的结果,这样即使是非技术人员也能理解你的发现。这些都是自动化无法取代的。
最后,确实需要数据科学家!自动化让他们的事情变得更容易。
感谢阅读!
本教程由 鲁克山·普拉莫迪塔数据科学 365 博客作者设计创作。**
在 https://rukshanpramoditha.medium.com阅读我的其他文章
2021–05–11
AutoNLP:基于 SOTA 模型的自动文本分类
原文:https://towardsdatascience.com/autonlp-automatic-text-classification-with-sota-models-f4a0dd8bdbfa?source=collection_archive---------12-----------------------
从头开始理解和使用 AutoNLP 的分步指南
图一。AutoNLP |作者图片|取自 freepick 的图标
开发一个端到端的自然语言处理模型并不是一件容易的事情。这是因为必须考虑几个因素,例如模型选择、数据预处理、训练、优化、模型服务的基础设施以及其他因素。出于这个原因,今天出现了一些有趣的替代方法来简化和自动化这些任务。这就是 AutoNLP 的情况,这是一个允许我们自动化 NLP 模型的端到端生命周期的工具。
在这篇博客中,我们将了解什么是 AutoNLP,以及如何在安装过程、项目创建、培训、指标、成本估算和模型服务中很好地使用它。因此,本博客将涵盖以下几个部分:
- 什么是 AutoNLP?
- 实践中的 AutoNLP
什么是 AutoNLP?
AutoNLP [ 1 ]是一个自动创建端到端 NLP 模型的工具。AutoNLP 是由拥抱脸 [ 2 团队开发的工具,于 2021 年 3 月推出测试阶段。AutoNLP 旨在自动完成构成 NLP 模型生命周期的每个阶段,从训练和优化模型到部署模型。
“AutoNLP 是一种自动训练和部署最先进的 NLP 模型的方法,与拥抱脸生态系统无缝集成。”— AutoNLP 团队
AutoNLP 的一大优点是,它为二进制分类、多级分类和实体识别的任务实现了最先进的模型,支持 8 种语言,即:英语、德语、法语、西班牙语、芬兰语、瑞典语、同样,AutoNLP 负责模型的优化和微调。在安全和隐私部分,AutoNLP 实现了受 SSL 保护的数据传输,数据也是每个用户帐户的私有数据。
正如我们所看到的,AutoNLP 是作为一种工具出现的,它简化并加速了创建 NLP 模型的过程。在下一节中,将会看到使用 AutoNLP 创建文本分类模型时从头到尾的体验。
实践中的 AutoNLP
对于这个例子,我们将处理一个二元分类问题。该数据集来自 SEPLN (塔斯社)[ 3 ]研讨会的语义分析,由西班牙语的推文组成,标记为 3 类负面、正面和中性。出于这个例子的目的,我们将从中性类中移除样本,以得到一个适合二进制分类问题的数据集。你可以点击下载数据集。在图 X 中,我们可以观察到训练和验证数据集的特征。
图二。训练和验证数据集|按作者分类的图像
现在,我们不必对数据集做任何其他事情。接下来就是开始使用 AutoNLP 了,那就加油吧!
安装 AutoNLP
为了通过 AutoNLP 工具使用 Hugging Face 基础设施,我们需要注册并创建一个帐户,其中将包含我们的模型和数据集。此帐户将提供一个令牌,用于在 AutoNLP CLI 和 Hugging Face 基础架构之间建立通信。
可以通过pip
从命令行直接安装 AutoNLP,如下所示:
图 3。按作者安装 autonlp |图像
我们还将要求安装 Git 大文件存储 (Git LFS)。在我的例子中,由于我在 macOS 操作系统上工作,我是这样做的:
图 4。作者安装 git-lfs |图像
然后,为了设置git-lfs
,您需要键入:
图 5。按作者设置 git-lfs |图像
一旦autonlp
被安装,它的要求,我们继续创建一个项目,上传数据和训练我们的模型,让我们去做吧。
创建 AutoNLP 项目
创建项目的第一步是进行身份验证,为此,我们只需要您帐户设置中的令牌,使用autonlp
CLI 键入:
图 6。记录|按作者分类的图像
一旦通过认证,我们就开始创建我们的项目。对于这个例子,我们的项目将被称为polarity_detection
,它将用spanish
语言处理数据,任务将是binary_classification
,我们想要训练的模型的最大数量是5
。然后,该命令如下图所示:
图 7。按作者创建项目|图像
当创建我们的项目时,终端将向我们显示关于我们创建的项目的信息。我们的示例项目的信息如图 8 所示。
图 8。项目描述|作者图片
正如我们所看到的,这些信息向我们展示了一些细节,比如我们项目的标识符(在这个例子中是128
),属性比如name
、owner
等等。但是,还显示了一条非常重要的信息,即成本。在这个阶段,成本仍然显示USD 0.00
,因为我们还没有训练任何模型,因此,只有当我们的模型训练结束时,这个值才会改变,这一点我们将在后面详细介绍。
上传您的数据
一旦我们的项目被创建,我们将继续上传我们的数据集。建议分别上传训练数据集和验证数据集。要上传数据集,只需指定项目的名称(在我们的例子中是polarity_detection
)、分割的类型(即train
或valid
)、列名的映射(在我们的例子中是tweet
和polarity
,它们分别映射到text
和target
以及数据集文件。下图显示了这些命令的外观:
图 9。上传数据集|按作者上传图像
与项目的创建一样,在终端上传数据集时,我们将看到与我们的流程相关的信息,在这种情况下,我们的数据集信息如下图所示:
图 10。数据集信息|作者提供的图像
一旦数据集上传完毕,我们就可以开始训练了。然而,要考虑的一个重要方面是成本。AutoNLP 为我们提供了一个命令,根据训练数据集中的样本数量来估计项目的成本。为了获得估计值,我们使用下图所示的命令:
图 11。成本估算|作者图片
我们可以看到,成本是在一个范围内提供的,对于这个例子,成本估计为7.5
到12.5 USD
。培训结束后会提供最终费用,我们将在下面看到。
培养
从模型的训练开始,我们只需要使用train
参数和项目名称,如下图所示:
图 12。培训|作者图片
培训开始后,我们将会看到一个问题,询问我们是否同意估计的成本(即我们在上一节中看到的成本范围),在接受估计的成本时,我们将观察每个模型的状态,如下图所示:
图 13。培训状态|作者图片
根据我们推出的模型数量以及数据集的特征,训练时间会有所不同。但是,我们可以使用project_info
参数来监控模型的状态,如下图所示:
图 14。项目信息|作者图片
从上图可以看出,每一款推出的车型都有令人满意的结局(记住我们只推出了 5 款)。还显示了更新后的最终成本,即11.70 USD
。
在每个模型的训练过程中,我们可以监控一些指标,出于本例的实际目的,我们只显示在所有模型的训练结束时获得的指标。因此,为了形象化度量,我们使用了metrics
参数和项目名称,如下所示:
图 15。指标|作者图片
对于每个训练模型,报告的度量是loss
、accuracy
、precision
、recall
、AUC
和f1-score
。在我们的例子中,我们看到平均来说accuracy
是0.85
,考虑到数据集的特征,这可能是一个可接受的值。我们还可以看到,它再次显示了我们培训的总成本。
推断
一旦我们的模型经过训练,它们就可以做预测了。为了进行预测,我们将使用predict
参数以及模型标识符、项目名称和要预测的短语,如下图所示:
图 16。预测|作者图片
正如我们在前面的图中看到的,这个句子假装是肯定的,实际上,这个模型为肯定的类产生了一个得分0.99
。在第二个例子中,句子假装是否定的,实际上,该模型为否定类产生了得分0.99
。
同样,AutoNLP 允许通过 cURL 请求和 Python API 进行预测,分别如图 17 和 18 所示。
图 17。按请求预测|按作者分类的图片
图 18。通过 Python API 预测|作者图片
结论
在这篇教程博客中,我们看到了什么是 AutoNLP,它的组件,以及它是如何工作的。
值得一提的是,一旦我们通过 AutoNLP 使用了 Hugging Face 基础设施,我们将会收到一张发票,上面的金额显示在命令行上。
我测试 AutoNLP 的经历很愉快。我第一次训练时遇到了一些问题,但是他们提供的支持是有效的。
参考
[1] AutoNLP
[2] 抱紧脸
[3]SEPLN 语义分析
自动缩放 SageMaker 实时端点
原文:https://towardsdatascience.com/autoscaling-sagemaker-real-time-endpoints-b1b6e6731c59?source=collection_archive---------10-----------------------
将您的 ML 工作负载投入生产
图片来自阿尔普·杜兰的 Unsplash
让一个端点启动并运行以进行推断是一回事。确保端点能够处理您预期的流量是另一回事。有了 SageMaker 实时端点,在生产中推出模型时需要考虑许多因素。您用于端点的实例类型是什么?对于这个用例来说,更重要的是,您有多少实例支持端点?
在本帖中,我们将研究自动缩放 SageMaker 端点来处理流量。最简单的形式是,您可以拥有一个由一个实例支持的 SageMaker 实时端点。有时,该实例可能会超负荷工作,这可能会导致您的端点出现故障和推断错误。为了解决这个问题,您可以创建一个自动扩展策略,帮助您的实例根据 CloudWatch 指标展开,比如每个实例的调用次数或 CPU 利用率。
对于今天文章中的例子,我们将从一个 Amazon XGBoost 部署的端点构建一个自动伸缩策略。要获得部署 Amazon XGBoost 算法的演练,请先阅读本文和。
注意 : 对于那些刚接触 AWS 的人来说,如果你想继续下去,请确保在下面的 链接 中进行登记。本文假设读者对 AWS 和 SageMaker 具有中级知识水平。
目录
- 自动缩放选项
- 部署 XGBoost 端点
- 自动缩放端点
- 其他资源和结论
1.自动缩放选项
有几种不同的方法可以扩展您的端点;不同的自动缩放策略选项定义如下。
目标跟踪缩放 :通过目标跟踪,您可以指定要监控的指标。对于 SageMaker,请查看受支持的 CloudWatch 指标,您可以从中选择一个并监控它。您可以为此指标设置阈值,如果达到阈值,它可以按照您的定义进行扩展。请注意,您还可以使用 SageMaker 定义定制指标。
计划缩放 :通过计划缩放,您可以设置自己的缩放计划。例如,如果您知道一周中某一天的流量会比较高,那么您可以构建自己的策略,在这一天扩大流量。
步进缩放 :步进缩放变得更加具体,您可以定义触发策略的具体阈值。步进缩放的强大之处在于,它根据警报破坏的程度进行缩放。如果在更大程度上违反了阈值,将应用更大的缩放。
对于我们的具体例子,我们将与目标跟踪缩放工作。要了解所有其他可用的缩放选项,请查看文档。
2.部署 XGBoost 端点
让我们快速演练部署 Amazon 提供的算法之一:XGBoost。我们将把它用于带有鲍鱼数据集的回归用例。要更深入地了解每个步骤,请查看我的上一篇文章,这篇文章更深入地介绍了如何使用算法进行训练和部署。在本节中,我们将快速浏览一下模型部署,跳过培训过程。
我们将使用 Boto3 Python SDK 与 SageMaker 客户机一起进行模型部署。第一步是获取我们的模型数据并创建我们的 SageMaker 模型。
SageMaker 模型创建
接下来,我们可以使用 SageMaker 模型来定义我们的端点配置。
端点配置创建
我们指定只从一个实例开始支持我们的端点。然后,我们可以使用此端点配置来创建端点,这需要几分钟时间。
端点已创建
现在我们已经创建了端点,我们可以输入一个样本数据点来测试调用模型进行推理。
调用端点
样本结果(作者截图)
3.自动缩放端点
我们现在可以专注于定义一个扩展策略来处理流量。我们将使用目标跟踪策略,我们关注的指标将是 InvocationsPerInstance。我们可以为每个实例设置 10 次调用的阈值。我们可以使用 Boto3 Python SDK 和自动缩放客户端来定义这个策略。
自动缩放策略
注意,我们将的最大容量定义为的 4 个实例,在我们的端点之后至少有 1 个实例。现在,我们可以定义阈值、目标指标,以及在和横向扩展时间内的规模。这两个时间将是我们的实例向外扩展,然后在每个实例的调用没有达到阈值的情况下再向内扩展所需的时间。
目标跟踪缩放
现在我们可以用一些压力测试来测试这个策略。我们将使用 invoke 端点 Boto3 调用,并在一定时间内发送请求。请记住,我们的横向扩展期需要 60 秒。
测试终点
端点应该被调用 250 秒,我们可以在 SageMaker 控制台上通过特定端点的 CloudWatch 调用度量来监控这一点。
SageMaker 的 CloudWatch 指标(作者截图)
实例最小值-最大值设置为 1-4(作者截图)
现在,我们可以监控 CloudWatch 图表,因为我们的端点在这 250 秒内受到了压力。
调用指标(作者截图)
我们可以放大到特定的区间来观察我们的终点变得越来越紧张。
调用指标(作者截图)
在我们的端点受到压力之后,我们可以使用 Boto3 来监控我们的端点描述更新,以反映我们的实例向外扩展。
监控端点实例
端点更新(作者截图)
过一会儿,您应该会看到端点已经更新为有四个实例。
更新的端点(作者截图)
4.其他资源和结论
参考博客:https://AWS . Amazon . com/blogs/machine-learning/configuring-auto scaling-inference-endpoints-in-Amazon-sage maker/
代码举例:https://github . com/RamVegiraju/sage maker-Deployment/blob/master/advanced functionality/auto scaling/XGBoost-ASG/XGBoost-鲍鱼. ipynb
SageMaker AutoScaling 帮助您以多种方式将模型投入生产。通过大量的扩展选项,以及详细的 CloudWatch 监控,您可以根据您对流量的预期来定义您的策略。
另一个值得一试的功能是 SageMaker 推理推荐器,这个新功能有助于负载测试并为您的端点选择最佳实例类型。如果对更多 SageMaker 相关内容感兴趣,我在下面附加了一些资源。
- SageMaker 自带容器/定制框架
- 在亚马逊 SageMaker 上部署定制 TensorFlow 模型
- SageMaker 多模型端点
- SageMaker 推理范例库
如果你喜欢这篇文章,请在LinkedIn上与我联系,并订阅我的媒体 简讯 。如果你是新手,使用我的 会员推荐 报名。
使用 Kubeflow 和羽衣甘蓝进行大规模 AutoSklearn
原文:https://towardsdatascience.com/autosklearn-at-scale-with-kubeflow-and-kale-bfd51f57a54f?source=collection_archive---------36-----------------------
如何使用 Kale 和 AutoSklearn 在 Kubeflow 上运行 AutoML 实验
照片由 Goh Rhy Yan 在 Unsplash 上拍摄
给定一个任务、一个度量、一个训练数据集以及一个资源预算,AutoML 系统可以自动地在一个测试数据集上产生一组预测。预算可能涉及计算资源,例如 CPU 和/或挂钟时间和内存使用。
上一段是对 AutoML 的定义。简单地说,当您启动 AutoML 实验时,您提供了训练数据集和您期望的最终目标。用简单的英语来说,最终目标可能是这样的:给我找一个模型,当你将它用于这个训练数据集时,它可以在那个测试数据集上产生最佳的分类精度性能。此外,在半小时内完成。
你会如何解决这个问题?最简单的方法是获取适用于该任务的每个 Scikit 学习预测器(例如,每个分类器),对其进行拟合,并在半小时内返回产生最佳结果的预测器。
然而,这种简单的方法是不够的。每个分类器都接受几个超参数,这些超参数可能会使其性能变好或变坏。此外,在拟合可能显著改变预测器性能的模型之前,您可以使用数十个数据处理函数。测试每一种可能的组合是不可能的。
但是有一个更好的方法,包括元学习,我们最喜欢的 Scikit Learn 机器学习(ML)框架和 Kubernetes。让我们把大枪拿出来!
Learning Rate 是一份时事通讯,面向那些对 AI 和 MLOps 世界感到好奇的人。你会在每周五收到我关于最新人工智能新闻和文章的更新和想法。订阅这里!
元学习
在深入研究代码之前,让我们先停止使用第一个术语。什么是元学习?我可以解释为学会学习,但对我来说听起来更困惑。所以,让我们再试一次:
元学习方法将数据集和任务(例如,分类或回归)作为输入,并返回应用于该数据集的一组算法,其超参数是预先填充的。
现在,我认为这个高层次的解释做得更好。但是元学习是如何做到的呢?第一步,生成输入数据集的描述性模型。我说的模型,不是指 ML 模型。它只是一组数字,以某种方式捕捉数据集的各种核心特征。这也称为元特征向量。
这些元特征可以是数据集代表值,例如维度、基数、维度之间的相关性、熵、互信息和稀疏性相关统计。
这个向量旨在提供足够的信息,以便元学习系统可以计算数据集之间的相似性。这意味着,你可以将两个数据集转换成这些向量,比较这些向量,并找出数据集在某种意义上是否相似。
在第二步中,元学习系统接收生成的数据集模型,并试图发现过去已经处理过的类似数据集。关于过去的数据集、对这些数据集执行的算法以及评估结果的信息存储在存储库中。
最后,通过计算手边的数据集和储存库中的其他数据集之间的相似性,系统可以检索一组算法及其超参数,这些算法在过去表现最好。
简单的例子
既然我们已经解决了各种流行词汇,您将从您的 Jupyter 笔记本开始创建一个 AutoML 工作流。此外,您将在 Kubeflow 上这样做,以便可以利用 Kubernetes 集群的强大功能。
你需要什么
首先,您需要一个正在运行的 Kubeflow 实例和一个 Jupyter 笔记本服务器。不要担心,我们将使用 MiniKF,我们将立即拥有所有这些。要设置 Kubeflow 并启动笔记本服务器,请遵循以下指南:
如果您更喜欢使用 AWS,我们将为您提供:
在文章中,您将看到要创建一个笔记本服务器,您需要选择jupyter-kale:v0.5.0–47-g2427cc9
Kale 图像(注意图像标签可能不同)。然而,在我们的例子中,让我们选择gcr.io/arrikto/jupyter-kale-py36:kubecon21eu-automl-nightly
图像,因为这个特性仍然处于早期阶段。
我们准备好了。让我们建立我们的第一个例子!
卡格尔推土机比赛
推土机蓝皮书是 8 年前举办的一场 Kaggle 竞赛。在这次比赛中,参与者被要求预测在拍卖会上出售的推土机的销售价格。
我们将使用这个数据集,因为同一个数据集用于测试流行的 ML 框架的性能,例如fastai
。fastai
有一个很棒的tabular
模块,专门解决结构化数据集(如 CSV 文件)的挑战。
他们在课程和书本上都使用推土机数据集来测试这个模块。他们实现了实际拍卖价格和预测拍卖价格之间的 RMSLE(均方根对数误差)为 0.226。这是使用神经网络实现的。
为了将我们的方法与fastai
的方法进行比较,我们需要使用相同的输入。因此,我们使用预处理管道fastai
来扩充数据集并转换分类值。
具体来说,我们使用add_datepart
方法来扩展数据集的saledate
字段。这意味着我们使用该字段中给出的信息创建新字段(例如,“今天是星期几?”,“是周末吗?”,“放假了吗?”等。).
最后,我们使用TabularPandas
类将分类值转换成数字。在我们的例子中,我们没有在预处理管道中使用FillMissing
方法,因为我们期望我们的系统建议一个相关的估算器。
要获得示例,克隆 Kale repo 并检查相关分支:
git clone https://github.com/kubeflow-kale/kale -b kubecon21eu
克隆的存储库包含一系列带有数据和注释笔记本的精选示例。在侧边栏中,导航到文件夹kale/examples/bulldozers-kaggle-competition/
并打开笔记本[blue-book-bulldozers.ipynb](https://github.com/kubeflow-kale/kale/blob/kubecon21eu/examples/bulldozers-kaggle-competition/blue-book-bulldozers.ipynb)
。
进行实验
跟着笔记本的单元格跑实验。神奇的事情发生在下面的命令中:
automl = kale_ml.run_automl(dataset,
kale_ml.Task.REGRESSION,
metric=metrics.mean_squared_log_error,
number_of_configurations=4,
max_parallel_configurations=1,
tuner=tuner)
您可以看到,我们调用了 Kale 提供的run_automl
函数,给出了一个数据集、一个任务和一个指标。number_of_configurations
参数指示系统将尝试多少 ML 管道配置。
让我们在这里暂停一下。我们之前说过,元学习返回一组应用于该数据集的算法,并填充了它们的超参数。然而,在我们的例子中,我们得到的不仅仅是一组算法。Kale 在底层使用了 AutoSklearn ,所以我们得到了一组完整的 ML 管道配置,数据和特征处理功能以及 ML 模型在顶层。这就更厉害了!
接下来,max_parallel_configurations
参数定义了并行运行的管道数量。最后但同样重要的是,调优器将在性能最佳的配置上运行超参数调优实验。
您可以通过观察协调一切的管道来监控实验的进度:
AutoML 编排管道—按作者分类的图像
或者,您可以在笔记本上完成:
自动监控—图片由作者提供
仅仅经过四次尝试,并且没有对我们的选项做太多改动,我们得到了大约 0.26 的分数。几乎什么都不做也不错。我们至少可以用这个结果作为我们的基准!
结论
在这个故事中,您创建了一个从原始数据开始自动发现和训练完整 ML 管道的机制。
您了解了什么是 AutoML 和元学习,然后,从数据集开始,您使用 Kale API 实例化了一个流程,该流程将为输入数据搜索最合适的模型。然后,您使用最佳配置中的模型自动启动了超参数优化实验。
有关您需要的所有步骤的更详细的指南,请在此处进入代码实验室:
https://codelabs.arrikto.com/codelabs/minikf-kale-automl/index.html?index=..%2F..index#0
关于作者
我的名字是迪米特里斯·波罗普洛斯,我是一名为阿里克托工作的机器学习工程师。我曾为欧洲委员会、欧盟统计局、国际货币基金组织、欧洲央行、经合组织和宜家等主要客户设计和实施过人工智能和软件解决方案。
如果你有兴趣阅读更多关于机器学习、深度学习、数据科学和数据操作的帖子,请关注我的 Medium 、 LinkedIn 或 Twitter 上的 @james2pl 。
所表达的观点仅代表我个人,并不代表我的雇主的观点或意见。
AutoVideo:一个自动视频动作识别系统
原文:https://towardsdatascience.com/autovideo-an-automated-video-action-recognition-system-43198beff99d?source=collection_archive---------12-----------------------
利用神经网络和自动化机器学习识别人类行为,如刷牙、坐着和跑步
视频动作识别管道可以使用 AutoVideo 预测的一些常用动作来源: HMDB (CC BY 4.0)
在这篇文章中,我将介绍我们如何建立一个神经网络来自动识别人类的行为。虽然这对于人类来说似乎是一项简单而琐碎的任务,但对于人工系统来说却很难做到。基于视频的动作识别旨在通过从视频片段中识别不同的动作来解决这个问题。这是视频理解的一项重要任务,在各个领域都有广泛的应用,如安全(孟、Pears 和 Bailey 2007) 、医疗(高等 2018) 、行为分析 (Poppe 2010)。视频动作识别的实际应用包括老年人行为监控以增强辅助生活、自动视频监控系统等等。
https://github.com/datamllab/autovideo。图片作者。
本文的目的是为我们的开源项目 AutoVideo ( GitHub )提供一个教程,这是一个全面且易于使用的视频动作识别工具包。在本教程中,您将学习:
(1)如何训练一个可以预测人类动作的神经网络;
(2)如何使用自动调优工具节省你调优超参数的努力;
(3)如何在你定制的数据集上训练模型。
你将能够使用你训练过的模型来识别任何新的视频剪辑,就像下面检测刷毛的演示一样。
预测演示视频上的动作(刷牙)。图片作者。
概观
AutoVideo 是一个高度模块化和可扩展的系统,它用标准管道语言包装了数据加载、数据处理和最先进的动作识别模型。因此,从业者可以很容易地添加新的动作识别模块或其他模块,如其他视频理解任务。AutoVideo 还引入了数据驱动的搜索器来自动调整不同的模型和超参数,以减少人工工作量。
图一。系统概述。AutoVideo 中的每个模块都被包装成一个带有一些超参数的原语。流水线由从预处理到动作识别的一系列原语组成。AutoVideo 配备了调谐器来搜索模型和超参数。图片作者。
入门指南
让我们从教程开始吧,它将帮助您熟悉这个包,并在自定义/基准数据集上执行动作识别。
安装:
要安装该软件包,请确保您的 Linux/MacOS 系统上安装了 Python 3.6 和 pip。首先安装以下软件包:
pip3 install torch
pip3 install torchvision
然后,只需使用以下命令即可安装 AutoVideo 软件包:
pip3 install autovideo
准备数据集:
数据集必须遵循 D3M 格式,由一个 csv 文件和一个媒体文件夹组成。csv 文件应包含三列,用于指定实例索引、视频文件名和标签。下面是一个示例 csv 文件:
**d3mIndex,video,label**
0,Brushing_my_waist_lenth_hair_brush_hair_u_nm_np1_ba_goo_0.avi,0
1,brushing_raychel_s_hair_brush_hair_u_cm_np2_ri_goo_2.avi,0
2,Haarek_mmen_brush_hair_h_cm_np1_fr_goo_0.avi,0
3,Haarek_mmen_brush_hair_h_cm_np1_fr_goo_1.avi,0
4,Prelinger_HabitPat1954_brush_hair_h_nm_np1_fr_med_26.avi,0
5,brushing_hair_2_brush_hair_h_nm_np1_ba_med_2.avi,0
媒体文件夹应该包含视频文件。你可以参考我们在 Google Drive 中的例子 hmdb6 数据集。我们还在 Google Drive 中准备了 hmdb51 和 ucf101 进行基准测试。要试用这个教程,你可以从这里下载 hmdb6 数据集。然后,您可以解压缩一个数据集,并将其放入数据集。
进行实验:
这个界面基于 Axolotl,我们对 D3M 的高级抽象。下面给出了使用预训练权重(在子采样 hmdb6 数据集上训练)在样本视频上运行动作识别任务的最小示例。我们开始吧!
加载数据集:
如上所述,以 D3M 格式准备数据集,并将其放在数据集文件夹中。在这个例子中,我们使用了 hmdb-6 ( Google-Drive )(来自 HMDB-51 的子样本,仅包含 6 个类)。我们使用实用函数 set_log_path() 为实验设置日志记录系统。train _ table _ path是带有视频文件名和标签信息的训练 csv 文件的路径。train _ media _ dir表示包含视频文件的媒体文件夹,而 target_index 指定包含输出标签信息的列的索引
预处理:
在读取火车 csv 文件后,接下来我们通过从 火车 _ 媒体 _ 目录 中的视频中提取帧并将它们存储在文件夹目录 帧中来预处理数据集。 为了实现这一点,我们从 autovideo 包中使用extract _ frames实用函数如下:
构建模型:
我们的软件包支持 7 种动作识别模式。在这个例子中,我们使用 TSN 作为视频识别模型。build _ pipeline()函数返回由端到端可训练模型组成的 管道 。下面是一个构建管道的示例。
调整超参数:
在上面的函数中,用户可以在build _ pipeline()函数中自定义配置字典 (config) ,用不同的超参数训练不同的算法。我们已经指定了一些超参数值(如学习率、时期数。等等)来演示用法。支持的超参数的完整列表可在这里找到。AutoVideo 中的每个模型都被包装成一个图元,其中包含一些超参数。TSN 的一个例子是这里的。所有的超参数都可以在构建管道时指定,方法是在上面的config
字典中传递它们。
火车:
可以使用上面指定的配置对模型进行端到端训练。这里我们使用 拟合 函数,该函数将训练模型并返回拟合的管道/模型。这可以保存下来供将来使用。下面是一个适合管道的示例:
上述函数在训练集上进行训练,并在验证集上进行验证,以将最佳执行模型保存在验证集上用于推理阶段。fit 函数的输出如下所示:
**Confidence Scores:**
[[0.0692555 0.06158188 0.02618745 0.05211503 0.10426781 0.68659234]...[0.00917702 0.01555088 0.00744944 0.00688883 0.02226333 0.9386706 ]]
上面的输出是在上面已经在训练集上训练之后的验证集中的视频的置信度分数。
最后,你可以在 examples/fit.py 找到上述代码片段的完整示例代码。要使用 fit()函数训练模型,只需运行:
python3 examples/fit.py
推论:
我们可以加载使用 fit() 函数获得的训练模型权重,以检测样本视频上的动作或计算测试集上的准确度。可点击此处下载一段演示视频和预训练的重量。在演示视频中检测动作的示例如下:
下面是演示视频输出的 GIF 图:
图片作者。
或者,我们可以使用经过训练的模型来计算测试集的准确性。这里我们使用 autovideo 的 produce() 函数从测试集中获得 预测 ,然后使用compute _ accuracy _ with _ preds()实用函数计算准确度。
这里test _ table _ path表示包含视频文件路径及其标签信息的测试 csv 文件,而test _ media _ dir表示包含视频文件的媒体目录。
在测试集上计算精确度的完整代码可以在 examples/produce.py 中找到。您可以使用以下命令运行此示例:
python3 examples/produce.py
搜索器模块:
除了用指定的配置拟合模型之外,用户还可以使用调谐器以数据驱动的方式自动搜索管道(即,模型和超参数)。我们当前的系统支持两种类型的调谐器,包括随机搜索和 Hyperopt。要使用自动搜索,您需要安装 ray-tune 和 hyperopt 以及:
pip3 install 'ray[tune]' hyperopt
运行搜索器模块的示例界面如下。
加载数据:
让我们通过在 train_table_path 和 valid_table_path 中指定 csv 文件路径来加载训练和验证数据集。 搜索器使用 train_dataset 使用搜索器在每个样本中绘制的一组超参数来训练模型。搜索结束时超参数的最佳配置是在valid _ dataset上具有最佳准确度的那些。
初始化搜索器模块:
在这里,用户可以使用 RaySearcher 为上面指定的数据集初始化搜索器模块。除了指定搜索算法(随机 v/s 超点)之外,用户还可以定义搜索空间(支持连续和离散空间)。在下面的例子中,我们使用了远视搜索。
搜索:
然后,调谐器将在搜索空间中搜索最佳超参数组合,以提高性能。下面是一个使用指定配置进行搜索并返回最佳超参数集的示例:
搜索器的完整代码可以在 examples/search.py 中找到,可以使用以下命令运行:
python3 examples/search.py
总结:
要了解这个项目的更多信息,请点击查看。该团队正在积极开发项目的更多功能,包括带有可视化工具的图形用户界面,并添加更多的视频理解任务。我们的目标是让视频识别对每个人来说都更容易使用。我希望你喜欢阅读这篇文章。
Autoviz:自动可视化任何数据集
原文:https://towardsdatascience.com/autoviz-automatically-visualize-any-dataset-75876a4eede4?source=collection_archive---------8-----------------------
只需一行代码即可可视化任意大小的数据集
来源:作者
可视化是一种使用不同的图形和绘图来可视化数据的技术。在数据科学中,我们通常使用数据可视化技术来理解数据集和发现数据之间的关系。可视化还有助于发现数据集中的模式,用于进一步分析。
python 中有不同的技术/库用于数据可视化,如 Matplotlib、Seaborn、Plotly 等。但是在使用所有这些库的时候,我们需要定义我们想要可视化的图形类型和我们需要可视化的参数。
在本文中,我们将了解一个 python 库 AutoViz ,它可以在一行代码中自动化整个数据可视化过程。
AutoViz 只需一行代码就可以对任何数据集进行自动可视化。AutoViz 可以找到最重要的功能,并只使用那些自动选择的功能来绘制有影响力的可视化效果。此外,AutoViz 非常快,可以在几秒钟内创建可视化效果。
让我们借助一些数据集开始探索 AutoViz。在使用 AutoViz 之前,我们需要安装它。
此外,请查看我的 Youtube 频道,了解更多关于数据科学的有趣内容。
安装 AutoViz
像任何其他 python 库一样,我们可以使用下面给出的 pip install 命令来安装 AutoViz。
pip install autoviz
加载数据集并进行分析
在这里,我将使用不同的数据集来可视化/探索 AutoViz 可以生成的不同类型的图表/绘图。你可以从 Github 库查看并下载所有的数据集。
- 汽车设计数据集
这个数据集包含不同汽车制造商的不同属性。让我们用 AutoViz 可视化这个数据集。
AutoViz 可以通过下面给出的 3 个简单步骤来实现。
#importing Autoviz class
from autoviz.AutoViz_Class import AutoViz_Class#Instantiate the AutoViz class
AV = AutoViz_Class()
这些步骤将导入 AutoViz 类并实例化它。最后一步是创建可视化。仅仅这一行代码就将创建所有的可视化效果,包括计数中的所有属性。
df = AV.AutoViz('car_design.csv')
a.所有连续变量的直方图(KDE 图)
来源:作者
b.连续变量的小提琴图
来源:作者
c.连续变量的热图
来源:作者
正如您在上面看到的,这些是使用 AutoViz 在一行代码中生成的不同图表。
让我们再分析一个数据集,在这个数据中,有 4 个属性描述了公司的广告支出和销售额。我们将通过创建上面使用的步骤来分析这一点,只是改变数据集。
2。广告数据集
在这里,我们将传递另一个参数 depVar,它是因变量,以便 AutoViz 相应地创建可视化。在这个数据集中,我们知道“销售额”是因变量。
df = AV.AutoViz('Advrtising.csv', depVar='Sales')
a.变量与销售额的散点图
来源:作者
来源:作者
“销售”取决于
同样,您将看到它将创建直方图、violin 图、热图等。将“销售额”作为因变量。
在调用 AutoViz 时,我们可以传递的其他一些参数有:
- sep,是分隔数据的分隔符,默认为','。
- target,它是数据集中的目标变量。
- chart_format 是显示的图表的格式。
- max_row_analyzed 用于定义要分析的行数
- max_cols_analyzed 用于定义要分析的列数。
在本文中,我们看到我们可以用一行代码可视化数据集,并且我们可以相应地找到数据集中的模式。
AutoViz 能够适应任何数量的不同数据环境,例如回归、分类甚至时间序列数据。继续使用不同的数据集探索这个库,并在回复部分分享您的经验。
在你走之前
感谢 的阅读!如果你想与我取得联系,请随时通过 hmix13@gmail.com 联系我或我的 LinkedIn 个人资料 。 您也可以在我的**Github 中查看我在这里使用的代码和数据。
利用 AutoXGB 进行金融欺诈检测
原文:https://towardsdatascience.com/autoxgb-for-financial-fraud-detection-f88f30d4734a?source=collection_archive---------8-----------------------
AutoXGB 与标准 XGBoost 在检测欺诈性信用卡交易方面的对比
由 CardMapr 在 Unsplash 上拍摄的照片
XGBoost 由于其通用性和令人印象深刻的性能,已经成为最重要的机器学习算法之一。
在以前的项目中使用过 XGBoost 之后,我一直乐于让它的实现更快、更好、更便宜。当我遇到 AutoXGB 时,我的好奇心被激起了,它声称是一个自动化工具,用于简化 XGBoost 模型的训练和部署。
鉴于我在金融服务行业的工作,欺诈是一个很大的问题,这将是一个利用信用卡欺诈数据来评估 AutoXGB 相对于通常使用的标准 XGBoost 设置的表现的绝佳机会。
内容
【1】数据采集与理解【2】处理类不平衡【3】选择性能指标 让 AutoXGB 经受考验【6】最终裁决
点击 此处 查看该项目的 GitHub 回购
(1)数据获取和理解
概观
这个项目使用了来自 Worldline 和机器学习小组(布鲁塞尔大学)在欺诈检测方面的研究合作的信用卡交易数据(在 GNU 公共许可证 下使用的)。
该数据集是真实世界信用卡交易的现实模拟并且被设计为包括复杂的欺诈检测问题。****
这些问题包括类别不平衡(只有< 1%的交易是欺诈性的)、数字和(高基数)分类变量的混合,以及与时间相关的欺诈事件。
数据转换
我们将使用 转换后的数据集,而不是原始数据集,以符合项目目标。基线特征工程的细节不在讨论范围之内,因此这里有一个简短的总结:
- 注明交易是发生在日还是夜(I);在工作日或周末。 这样做是因为欺诈模式根据一天中的时间和一周中的日期而不同
- 使用 RFM (近期、频率、货币价值)指标描述客户的消费行为(例如,平均消费、交易数量)
- 通过计算一个时间窗口内欺诈案件的平均数量,对与每笔支付终端相关的风险进行分类
拍摄于 Unsplash 上的粘土堤
预测器和目标特征
在完成特征工程后,我们有一个具有以下特征的数据集:
- TX_AMOUNT :美元交易金额 float
- TX_DURING_WEEKEND :交易是否发生在周末 boolean
- TX_DURING_NIGHT :交易是否发生在夜间 boolean
- *CUSTOMER _ ID _ NB _ TX _DAY _ WINDOW:每个客户最近 1 天、7 天、30 天的交易笔数[ 整数
- *CUSTOMER _ ID _ AVG _ AMOUNT _DAY _ WINDOW:每位客户在过去 1 天、7 天、30 天的平均消费金额(美元) float
- TERMINAL _ ID _ NB _ TX _ * DAY _ WINDOW**:终端最近 1、7、30 天的交易笔数整数
- ****TERMINAL _ ID _ RISK _ * DAY _ WINDOW:过去 1 天、7 天、30 天终端上欺诈交易的平均数量[ 整数
- TX_FRAUD: 指示交易是合法( 0 )还是欺诈(1)【布尔】**
转换后的信用卡欺诈数据集示例
从目标变量 TX_FRAUD ,,我们可以看出,我们正在处理一个二元分类任务。
具有延迟期的列车测试分离
欺诈检测中要考虑的一个重要方面是延迟期(又名反馈延迟)。在现实世界中,欺诈交易只有在投诉或调查发生后一段时间才会为人所知。****
因此,我们需要引入一个连续的延迟期(例如,一周)来分离训练集和测试集,其中测试集应该在训练集的最后一个事务之后至少一周发生。****
列车测试划分如下:
- 车组 : 8 周(2018 年 7 月 1 日至 2018 年 8 月 27 日)
- 延迟期 : 1 周(2018 年 8 月 28 日至 2018 年 9 月 3 日)
- 测试集 : 1 周(2018 年 9 月 4 日至 2018 年 9 月 10 日)
列车和测试设备之间的延迟时间图|图片由作者提供
(2)处理阶层失衡
欺诈交易不会经常发生,所以我们手上有一个严重不平衡的数据集也就不足为奇了。
从目标变量的值计数来看,在 550,000+交易中,只有 4,935 个欺诈案例 (0.9%) 。
原始类的值计数:1 =欺诈;0 =合法|作者提供的图片
我们可以使用合成少数过采样技术(SMOTE)** 来处理这种类别不平衡。原始 SMOTE 论文的作者在他们的实现中结合了 SMOTE 和随机欠采样,所以我在这个项目中使用了这种组合。**
具体采样策略如下:
- 进行过采样以将少数类增加到总数据集的 5%(从最初的 0.9%增加 500%),然后
- ****随机欠采样使多数类的规模为少数类的两倍(即少数类为多数类规模的 50%)
尽管SMOTE作者表明不同的组合给出了可比较的结果,但我选择了 500%/50%组合,因为该论文表明它在石油数据集中的少数样本上给出了最高的准确性。**
经过这次采样后,数据集更加均衡,占整个数据集的少数类从 0.9%增加到** 33.3%。**
样本类的值计数:1 =欺诈;0 =合法|作者提供的图片
(3)性能指标的选择
在我们开始建模之前,我们必须决定评估模型性能的理想指标是什么。
典型的是基于阈值的指标,如准确性和 F1 分数。虽然他们可以评估错误分类的程度,但他们依赖于特定决策阈值的定义,例如,概率>0.5 =欺诈。
这些指标对决策阈值的依赖使得对比较不同的模型提出了挑战。因此,更好的选择是无阈值指标,如 AUC ROC 和平均精度。
****平均精度将精度-召回曲线总结为每个阈值达到的精度的加权平均值,权重为召回从前一阈值的增加。
虽然 AUC-ROC 更常见,但平均精确度被选为该项目的主要报告指标,原因如下:
- 对于不平衡数据集,平均精度为 比 更具信息量。虽然我们已经应用了抽样来平衡我们的数据,但我觉得仍然存在一定程度的剩余不平衡(67:33 而不是 50:50)
- 过多的假阳性会使欺诈调查团队不堪重负,因此我们希望在低 假阳性率(FPR)值时评估召回(又名敏感度)。使用 PR 曲线(和 AP)相对于 ROC 的优势在于 PR 曲线可以有效地突出低 FPR 值的模型性能。****
照片由 Christiann Koepke 在 Unsplash 上拍摄
(4)基线— XGBoost 和随机搜索 CV
基线模型的设置(XGBoost withRandomizedSearchCV)是我倾向于使用的分类任务的第一线方法。
以下是基线模型的测试集预测结果,其中平均精度的关键度量是 0.776 。训练所用的时间是 13 分钟。
测试集基线 XGBoost 模型的性能指标|作者图片
(5)测试 AutoXGB
与最近兴起的 AutoML 解决方案一致,AutoXGB 是一个库,它从 CSV 格式的表格数据中自动训练、评估和部署 XGBoost 模型。
使用 Optuna 自动完成超参数调整,使用 FastAPI 进行部署。
AutoXGB 由拥有世界首位 4x Kaggle 特级大师头衔的 HuggingFace 研究员 Abhishek Thakur 开发。用他自己的话说,AutoXGB 是一个建立 XGBoost 模型的简单工具。
因此,我热衷于利用他的专业知识来探索和改进我的 XGBoost 模型通常的实现方式。
要安装 AutoXGB,请运行以下命令:
**pip install autoxgb**
AutoXGB 框架大大简化了设置 XGBoost 训练和预测所需的步骤。下面是用于为二进制分类任务设置 AutoXGB 的代码:
下面是 AutoXGB 的测试集结果,其中平均精度的关键指标是 0.782 。训练时间为 9 分钟。
测试集 AutoXGB | Image 按作者的性能指标
(6)最终裁决
结果比较
性能和速度比较|图片由作者提供
与基准分数 0.776 相比,AutoXGB 的平均精度分数略高,为 0.782** 。**
AutoXGB 培训所花费的时间比基准的 13 分钟大约缩短了30%9 分钟。****
AutoXGB 的另一个关键优势是,我们距离将模型作为 FastAPI 端点只差一个命令行。这种设置减少了建模部署的时间,这是培训时间之外的一个关键因素。
以下因素可能是推动 AutoXGB 获得更好性能的原因:
- 使用贝叶斯优化和 Optuna 进行超参数调整,这比随机搜索更快,因为它使用来自先前迭代的信息,在更少的迭代中找到最佳超参数
- 根据作者丰富的数据科学经验,仔细选择 XGBoost 超参数(类型和范围)的进行调优****
- ****优化内存使用,通过特定的类型转换减少内存使用,例如,将数据类型为
int64
的值转换为int8
(消耗的内存减少了 8 倍)
重要警告
虽然性能指标给了 AutoXGB 一个优势,但它最重要的问题之一是参数设置中粒度控制的损失。
如果您一直密切关注,您可能会意识到,我们没有引入我们为交叉验证申请的训练/测试分割的顺序延迟期(我们应该已经完成)。****
在这种情况下,AutoXGB 不允许我们指定我们想要用作交叉验证(CV)一部分的验证折叠,因为唯一与 CV 相关的参数是n_folds
(CV 折叠数)。
这种缺乏控制的另一个问题是,我们不能为 XGBoost 分类器指定评估度量。
在基线模型中,我能够将eval_metric
设置为aucpr
(PR 曲线下的 AUC),这与我们的平均精度的主要指标一致。但是,对于二进制分类,AutoXGB 的 XGBoost 分类器中的硬编码评估度量是logloss
。
归根结底,虽然 AutoXGB 等解决方案在简化(并可能改进)XGBoost 实现方面做得很好,但数据科学家需要通过了解幕后发生的事情来了解其局限性。
随意查看 GitHub repo 中的代码,点击 。
在你走之前
欢迎您加入我的数据科学学习之旅!关注我的 Medium 页面和 GitHub ,了解更多精彩的数据科学内容。同时,享受在你的 ML 任务中使用 AutoXGB 的乐趣!
**https://medium.com/geekculture/using-ensemble-regressors-to-predict-condo-rental-prices-47eb7c3d5cd9
资源
- 用于信用卡欺诈检测的机器学习—实用手册
- AutoXGB — GitHub
- sci kit-Learn:Precision-Recall**
AvatarGAN —使用 GAN 生成卡通图像
原文:https://towardsdatascience.com/avatargan-generate-cartoon-images-using-gan-1ffe7d33cfbb?source=collection_archive---------5-----------------------
有没有想过如何生成不属于任何人脸的 bitmoji?看看 GAN 是如何创建这些图像的。
我们大多数人都创建了自己定制的 bitmoji,并在不同的社交媒体应用中使用。这些 bitmoji 是为特定用户定制的。但你有没有想过如何生成不属于任何人脸的 bitmoji?好吧,让我们探索一下甘斯是如何为我们完成这项工作的。
作者对 AvatarGAN 图像的预测
生成对抗网络是当今计算机科学中最有趣的想法之一。GANs 可以从垃圾数据集生成图像。甘是由伊恩·j·古德菲勒于 2014 年开发的。它由两个神经网络组成,这两个网络相互竞争,以使预测更加准确。
生成模型找出输入数据中的特征,能够分析、捕获和复制数据集中的变化,并以无监督的方式生成看起来与输入集相似的新图像。例如,GANs 可以创建类似人脸照片的图像。
来源:https://www.thispersondoesnotexist.com/
所有这些由甘生成的图像都有一个共同的模式。每张脸的眼睛都在同一个坐标上。背景只是一个模糊的随机纹理。如果有多个面,第二个面的形状会非常扭曲。
在我们开始训练之前,让我们先了解一下 GANs 是如何工作的。
生成顾名思义就是试图生成看起来像真图像的假图像。它学习特征的概率 X 。发生器将噪声(随机特征)作为输入噪声。
鉴别器是一个二元分类器,试图区分真实图像和生成器生成的图像。它学习类 Y (真或假)给定特征 X 的概率。概率是生成器的反馈。
发电机学会制造看起来像真的假货。鉴别者学会辨别真假。
训练 GANs 的步骤:
- 定义发生器和鉴别器网络架构
- 训练生成器模型以生成可以欺骗鉴别器的假数据
- 训练鉴别器模型以区分真实数据和虚假数据
- 继续训练几个时期,并保存发电机模型
本质上,我们把随机噪声通过发生器。生成器生成假图像。该输出图像连同来自真实图像数据集的图像流一起被传递到鉴别器。真实和伪造的图像都被提供给鉴别器,鉴别器返回图像真实性的概率。然后,我们从鉴别器输出计算成本函数,并更新两个模型的权重。
噪声→发生器→特性→鉴别器→输出→成本(输出)
甘建筑—作者图片
甘的训练
现在,我们已经完成了 GAN 的基础知识,是时候进行繁重的工作并训练模型了。
GIF via Giphy
1.资料组
我们将在卡通场景上训练我们的甘,这是一组随机的二维卡通化身图像。这些漫画有 10 个艺术类别、4 个颜色类别和 4 个比例类别,所以我们有很多可能的组合。我们将使用包含 100,000 个随机选择的卡通图像的数据集。
下一步是读取所有图像。由于我们有许多图像要读取和处理,这项任务可能需要一段时间。因此,我们将读取所有的图像,将其转换为 JPG 格式,调整其大小,将其规范化,并将预处理后的图像存储为二进制文件。只执行一次这一系列步骤会更有效。这样我们可以简单地读取处理过的图像数据并快速使用它。我们将为所有图像创建一个 Numpy 数组,并将其保存为一个. npy 文件。我们使用 Numpy 二进制而不是 Pickle,因为该文件非常大,可能会导致某些版本的 Pickle 出现问题。
现在,为了在内存中保存图像,我们将使用 tensor flowTF . data . dataset。Dataset 对象用于编写描述性的高效输入管道。迭代以流的方式发生,因此完整的数据集不需要适合内存。
2.建立模型
这两个模型都使用 Keras 顺序类。
发电机
生成器需要上采样层来从噪声(即种子)生成图像。我们可以使用 UpSampling2D() 和 Conv2DTranspose() 进行上采样。
UpSampling2D 只是利用一些上采样技术对图像矩阵进行简单的放大。我们通常使用最近邻法或双线性上采样法。所以没有机器在这里学习。向上采样 2D 的好处是它很便宜。而 Conv2DTranspose 层是一个卷积运算,学习几个类似于常规 Conv2D 层的滤波器。转置层简单地交换向后和向前传递,保持其余的操作相同。Conv2DTranspose 也将对其输入进行上采样,但关键的区别在于,该模型应该了解什么是该作业的最佳上采样功能。
第一层是密集层,其输入是种子噪声。然后我们对其进行多次上采样,直到尺寸为28x28x1。对于生成器,我们将使用 LeakyReLU 激活函数,对于最后一层,我们将使用 tanh。
来源: DCGAN
让我们尝试绘制生成器神经网络生成的图像。
训练前由生成器根据随机噪声生成的图像—作者提供的图像
鉴别器
鉴别器网络是一种简单的卷积神经网络图像分类器。
让我们检查一下我们的鉴别器模型的输出。
输出: tf。张量([0.50059265]],shape=(1,1),dtype=float32)
它返回概率得分。
3.损失函数
我们将使用二元交叉熵损失函数。BCE 成本函数有两个部分,一个与每个类相关。当标签和预测相似时,该值接近零,但当标签和预测不同时,该值接近无穷大。
二元交叉熵损失函数—作者图片
让我们分解方程,分析每一部分。
作者图片
作者图片
鉴别器损失量化了鉴别器模型能够区分真实和伪造图像的程度。它将鉴别器对真实图像的预测与 1 的数组进行比较,并将鉴别器对虚假图像的预测与 0 的数组进行比较。
发电机损耗量化了它欺骗鉴别器的能力。直观地说,如果生成器运行良好,鉴别器会将假图像分类为真实图像(或 1)。这里,我们将把鉴别器对生成图像的判定与 1 的数组进行比较。
生成器和鉴别器模型都使用 Adam 优化器和相同的学习速率和动量。它们的优化器是不同的,因为我们分别训练两个不同的网络。
4.培训渠道
现在,我们已经定义了培训渠道的主要组成部分,让我们转到培训部分。下面的函数就是神奇之处。
注意 tf.function 注释的使用。这可以完善功能并提高性能。
这两个神经网络必须在两个单独的过程中独立训练。因此我们为梯度定义了两个独立的损失函数和独立的更新。在鉴别器模型的反向传播期间,有必要仅应用鉴别器的梯度来减少鉴别器的损耗,并且仅更新该模型的权重。如果创成式模型的权重也同时更新,模型将不会学习。
5。训练模型
训练数据集应该被规范化。两个类别的样本数量必须相等。对于鉴别器训练集,输入图像将是 x 和 y,对于真实图像包含值 1,对于生成的图像包含值 0。而对于生成器训练集,x 包含随机噪声(种子), y 总是 1。这里,生成器的目的是生成如此好的图像,以至于鉴别器被愚弄,并给它们分配一个接近 1 的概率。
既然一切都准备好了,我们开始训练吧。
GIF via Giphy
train(train_dataset, EPOCHS)
查看正在被训练生成卡通图像的模型。
作者图片
拍拍背!我们的模型终于被训练好了,现在是时候保存它了,以便我们将来可以使用它。
generator.save(os.path.join(DATA_PATH, "face_generator.h5"))
氮化镓的应用
现在我们知道了 GAN 的功能,是时候检查它的迷人应用了。在研究中有大量关于 GAN 的用法。
图像到图像的翻译
在 GANs 的帮助下,我们可以进行照片的翻译。 Phillip Isola 在论文中展示了 pix2pix 方法用于许多图像到图像的翻译任务。例如,使用 GANs,我们可以将马的图像转换成斑马,从草图创建彩色照片,彩色黑白图像,等等。
来源: CycleGAN
甘斯安保公司
随着人工智能的兴起,欺诈和网络威胁的风险也在增加。网络威胁会泄露大量机密信息。GANs 可以用来防止【对抗性攻击】。这些对抗性攻击使用各种技术来欺骗深度学习架构。GAN 可以创建更多这样的假样本,我们可以通过在假生成的样本上训练模型来轻松地标记它们。
来源: SSGAN
SSGAN 用于执行隐写分析,并检测图像中不应该出现的隐藏编码。GANs 还可用于生成监督用的合成数据。
照片修复
GANs 可用于执行照片修补或斑点填充,即,填充由于某种原因被移除或被破坏的照片的缺失区域。论文上下文编码器:通过修补的特征学习已经描述了使用上下文编码器来执行照片修补。
来源:结合上下文注意的生成式图像修复
用于 3D 对象生成的 GAN
吴家俊提出了一种 GAN,可以用来生成三维物体,如枪、椅子、汽车、沙发和桌子。
来源:通过 3D 生成-对抗建模学习物体形状的概率潜在空间
结论
生成器的目标是欺骗鉴别器,而鉴别器试图区分真假。两个模型都从彼此的竞争中学习。最后,假的看起来像真的。生成数据的想法开启了新的潜力,但不幸的是也带来了巨大的危险。
如果你坚持了这么久…谢谢!我希望这对你来说是一次学习经历。如果你喜欢这篇文章,请与你的朋友和同事分享。如果你觉得有用或有任何后续问题,请给我留言。
对于那些没有阅读或者没有亲自完成教程的懒人,这里有一个源代码的链接。
https://github.com/aakashjhawar/AvatarGAN
避免使用函数式编程的调试器
原文:https://towardsdatascience.com/avoid-debuggers-with-functional-programming-43ea379605dd?source=collection_archive---------30-----------------------
用纯函数和跟踪器调试你的代码
作者:爱德华·克鲁格和道格拉斯·富兰克林。
照片由 Fotis Fotopoulos 在 Unsplash 上拍摄
介绍
我们的目标是有一个纯函数的代码库,我们可以用一个 tracer 来修饰它。通过将这个装饰器应用到纯函数,我们可以在不使用笨重的调试器的情况下调试代码。这减少了开发人员的痛苦,因为调试器通常是乏味且难以使用的。
什么是纯函数?
严格地说,在一个函数式编程范例中,所有函数都是纯函数。它们是什么,我们如何编码它们,它们为什么有用?
在此之前,让我们回顾一下数学函数。
数学函数
数学函数,如cos(x),
返回单个值。给它一个x
,它返回x
的余弦值。相同的x
值将总是返回相同的结果。
Python 函数不同于数学函数。Python 函数不仅仅计算值;它可以改变程序的状态。
Python 函数可以设置影响不同函数结果的全局变量。例如,一个函数可以改变另一个函数使用的列表。这种突变是该功能的副作用。
副作用使得编程和调试更加困难。你不需要仅仅考虑一个特定的功能在做什么;您还必须考虑其他函数之前可能做了什么,这会影响程序的状态。
纯函数消除了一些意想不到的副作用。
纯函数
纯函数是数学函数的计算模拟。这意味着当你传递一个值给一个函数时,它将总是产生相同的结果,没有任何副作用。
让我们用一个非纯计数器和一个纯计数器来说明这个概念。这个计数器是迷信的,所以它将跳过 13。
带测试的不纯计数器
对于非纯函数——为了测试 13 的条件跳过,我们必须注意count .
的全局状态。为了检查这种行为,我们必须运行计数器 13 次,看看它是否工作。每次我们调用increment_counter()
都会有将count
增加 1 的副作用。因此,我们必须运行increment_counter()
12 次,让它进入一种状态,在这种状态下count = 13
触发我们正在测试的条件行为。
注意,我们将在本文后面的第 20 行讨论调试器代码breakpoint()
。
当我们将计数器实现为一个纯函数时,测试我们的计数器是否跳过 13 要简单得多。
带测试的纯计数器
对于纯计数器,我们需要做的就是检查我们的条件情况,看看计数器是否跳过 13。不存在需要留意的全球状态,也不存在需要担心的副作用。
如果您只使用纯函数编写项目代码,计算将通过嵌套或组合函数调用进行,而不会改变状态或可变数据。这将允许更容易的调试。此外,因为纯函数对于相同的参数有相同的返回值,所以它们非常适合单元测试。
什么是调试器?他们很差劲吗?
调试器的目标是在受控条件下运行目标程序,允许程序员跟踪正在进行的操作并监控变化。
下面我使用 Python 调试器 pdb 运行了非纯计数器代码。第 20 行上的breakpoint()
触发程序暂停,并向我们显示下一行的代码。我调用count
来查看这个全局变量的状态,并使用n
来运行下一行代码。在这种情况下,我们可以看到每次调用increment_counter
时count
都会增加。
使用调试器检查上述非纯计数器的状态
我们可以看到count
比我们的下一个断言落后了一个,这是意料之中的。此外,我们可以观察到计数从 12 跳到 14。注意计数状态是如何随着每次断言测试而增加的。这看起来像是好的软件设计吗?
像这样一行一行地遍历程序是很慢的。使用调试器重新创建一个状态来测试某个行为可能会很痛苦。
传统的调试器在几个方面都很糟糕。
- 你花了很多时间试图在本地重现错误,这样你就可以附加你的调试器。
- 当您反复缩小原因范围时,您必须多次重现问题。
- 人工调试环境将创建一个与错误最初出现时不同的状态。
- 调试器不跟踪数据或控制流,也不记得过去发生了什么。
开发人员有时会发现自己在为调试器编写代码来解决特定的问题。应该为手边的应用程序编写代码,而不是为正在其上使用的调试器编写代码!
各地的软件开发人员都应该对此感到不安。有更好的调试方法。如果您没有使用调试器,那么您可能通过添加日志记录代码并重新运行程序来进行调试。
这类似于我们的解决方案,使用带有跟踪器的纯函数,以获得更优雅和可重用的调试方法。
纯函数结合跟踪器对于生产中的日志记录非常有用,因为您可以确切地看到什么输入值产生了错误。对于纯函数,如果我们知道我们的输入和输出,我们就知道修复代码中的错误所需要的一切。
使用追踪器调试你的软件
应用跟踪装饰器,而不是使用调试器。
为什么要追踪?
跟踪是模拟程序的执行,一行一行地遍历程序,显示变量是如何变化的。有经验的程序员使用跟踪来调试程序,通常作为调试器的替代品。
“干杯,爱!骑兵来了!”—示踪器
当您知道一个纯函数的输入和输出时,您就知道了调试所需的一切。
跟踪装饰者:@tracefunc
这是作为装饰器编写的跟踪程序,我们将把它应用于我们感兴趣的函数。
tracer.py
这个装饰器打印出传递给tracefunc()
的函数的轨迹。在第 10 行,result
存储了func(*args, **kwargs).
的值,之后生成一个打印语句。此语句报告func.__name__
,args 和 kwargs。
这个装饰器将允许我们看到我们装饰的函数的名字和它的参数,kwargs 和 result。
通过用tracefunc
修饰我们的纯函数,我们生成了调试程序所需的所有日志信息。
对纯函数应用 tracefunc
让我们用我们的 tracer 来装饰这个纯计数器,看看输出。
用 tracefunc 装饰的纯计数器
我们在第 3 行使用@
语法将tracefunc
应用到increment_counter
。
增量 _ 计数器 _ 纯的跟踪
现在,当我们运行这个文件时,我们在第 11 行的测试生成了上面的输出。我们可以看到func.__name__
,12 作为自变量,14 作为结果。
通过对这个纯函数应用追踪器,我们生成了我们想要测试的行为的清晰日志。专柜确实很迷信。
结论
通过用追踪器装饰纯函数,您获得了一个优雅的、可重用的模式来调试您的程序。装饰是增强功能行为的有力工具。有了好的代码(纯函数)和跟踪器,您可以避免使用调试器和管理状态来调试程序的痛苦。
请随意将tracefunc
复制到您的代码库中,或者您可以尝试编写自己的跟踪装饰器!
用 Jupyter 内核避免 DLL 地狱
原文:https://towardsdatascience.com/avoid-dll-hell-with-jupyter-kernels-4447cf16dc34?source=collection_archive---------49-----------------------
斯特凡诺·波利奥在 Unsplash 上拍摄的照片
类似于 Docker 容器,内核是确保你的 ML 应用程序可以在任何地方运行的关键。
介绍
以前在 Windows 上有一个叫做 DLL Hell 的东西。简而言之,过去你电脑上的所有应用程序都共享已安装库的相同版本——所以每次你安装一个新的应用程序,你都冒着更新底层库和破坏先前安装的应用程序的风险。
对于习惯于容器化他们的应用程序的 Docker 爱好者来说,这是很好理解的:运行时环境需要虚拟化以便应用程序可以移植,并且对特定版本库的依赖可以被隔离到容器本身。这确保了应用程序可以在任何人的计算机上运行,包括云。
蟒蛇
Anaconda 个人版让打包和分发 ML 应用变得轻而易举:
https://www.anaconda.com/products/individual
中的到底是什么由你决定——你可以使用 Python 或 R ,并包含你的项目所需的任何库/框架。当你完成后,你就有了一个可移植的内核,它可以跟随你的应用程序,并确保它总是看到相同的运行时环境。不管你的同事使用的是 Windows 、 MacOS 还是 Linux 都没关系——你可以轻松地与他们分享你的项目,并确保他们在他们的机器上看到的结果与你在自己的机器上看到的一样。
康达环境
这个食谱背后的秘方是环境的概念。安装完 Anaconda 之后,你将能够使用一个叫做 Anaconda Prompt 的漂亮的命令窗口。在管理环境时,它会很快成为你新的最好的朋友。
这是你可以用康达环境做的所有酷事情的官方清单,但在下一节,我将带你经历一个典型的场景:
GPU 上的张量流
斯蒂芬·科斯马在 Unsplash 上拍摄的照片
或者…曲速!在 CPU 上构建神经网络是所以昨天,所有酷孩子都在使用支持 CUDA 的 Nvidia GPU来运行他们的!比方说,我们有一些新的想法来提高我们一直在做的 CNN 的准确性。首先要做的是旋转一个 conda env 并加载我们需要的所有东西(从 Anaconda 提示符):
conda create -n tf-warp-speed tensorflow-gpu=2.1 python
我们将把我们的 conda 容器命名为 tf-warp-speed ,并用支持 GPU 的版本 TensorFlow 对其进行初始化。我们现在有了一个沙盒来玩——从现在开始我们在里面做的任何事情都不会影响我们所依赖的操作系统。
步入沙盒很容易,只需激活它:
conda activate tf-warp-speed
我们已经安装了 Python 和支持 GPU 的 TensorFlow 版本,但是您可以在这里为您的项目加载额外的库/框架。
对于这篇文章,我们将使用 rogue 和 version-up(通过pip)tensor flow:
pip install tensorflow-gpu==2.3.1
忽略你可能看到的任何依赖错误,让我们继续让我们的新 conda env 对 Jupyter 笔记本可见!
conda install ipykernel
我们上面安装的是一个交互式 Python 内核,它为 Jupyter 笔记本提供了一个执行后端。现在我们需要给它贴上消费标签:
python -m ipykernel install --user --name=tf-warp-speed
瞧!启动一个 Jupyter 笔记本,进入内核- >改变内核,你应该会看到一个 tf-warp-speed 的选项!选择那个,我们就可以开始了!在新笔记本的代码单元中输入以下内容:
import tensorflow as tf
from tensorflow.python.client import device_libprint("TensorFlow version: ", tf.**version**)
print("TensorFlow built with CUDA: ",tf.test.is_built_with_cuda())
print("GPUs Available: ", len(tf.config.list_physical_devices('GPU')))!python --version
当您执行它 (CTRL-ENTER)时,您应该看到类似这样的内容:
TensorFlow version: 2.3.1
TensorFlow built with CUDA: True
GPUs Available: 1
Python 3.7.9
让我们带它出去兜一圈,看看它能做什么!
import timeitdef cpu():
with tf.device('/cpu:0'):
random_image_cpu = tf.random.normal((100, 100, 100, 3))
net_cpu = tf.keras.layers.Conv2D(32, 7)(random_image_cpu)
return tf.math.reduce_sum(net_cpu)def gpu():
with tf.device('/device:GPU:0'):
random_image_gpu = tf.random.normal((100, 100, 100, 3))
net_gpu = tf.keras.layers.Conv2D(32, 7)(random_image_gpu)
return tf.math.reduce_sum(net_gpu)
# We run each op once to warm up
cpu()
gpu()# Run the op several times
print('Time (s) to convolve 32x7x7x3 filter over random 100x100x100x3 images '
'(batch x height x width x channel). Sum of 100 runs.')
print('CPU (s):')
cpu_time = timeit.timeit('cpu()', number=100, setup="from __main__ import cpu")
print(cpu_time)
print('GPU (s):')
gpu_time = timeit.timeit('gpu()', number=100, setup="from __main__ import gpu")
print(gpu_time)
print('GPU speedup over CPU: {}x'.format(int(cpu_time/gpu_time)))
如果此时一切正常,您应该会看到如下内容:
Time (s) to convolve 32x7x7x3 filter over random 100x100x100x3 images (batch x height x width x channel). Sum of 100 runs.
CPU (s):
6.590599500000053
GPU (s):
0.8478618999999981
GPU speedup over CPU: 7x
等等…什么?!?在 GPU 上运行我的 CNN比我的 CPU 快七倍 ?!?现在那就是的曲速!
共享
在这一点上,我对我的新内核非常兴奋,但是我有一个朋友在 Ebay 上花了太多的钱买了两张 3090 卡,我真的很想听听它是什么感觉。
轻松点。我可以简单地将我的 conda env 导出到一个 yaml 文件中,并通过电子邮件发送该文件(连同我的*。ipynb 文件)给我的朋友。他们可以重新创建我的内核,重新运行我的笔记本,让嘲讽开始(因为我还在运行一台 GTX 1080)!
conda env export > environment.yml
运行完以上程序后,我有了我的 yaml 文件,其中包含了我的朋友构建他们的新 conda env 所需的一切:
conda env create -f environment.yml
结论
使用 Anaconda 来管理您的虚拟环境是维护您的 ML 项目的完整性的关键。库和框架的版本来来去去就像日落一样快——明智的做法是为您的每个项目拍摄运行时环境的快照。
避免带有偏斜计数数据的机器学习模型中的错误
原文:https://towardsdatascience.com/avoid-mistakes-in-machine-learning-models-with-skewed-count-data-e3512b94d745?source=collection_archive---------10-----------------------
入门
一些常见警告和解决方案的介绍
由卢克·切瑟在 Unsplash 上拍摄的照片
1.背景
计数数据到处都是。计数数据听起来很容易处理:它们只是无限的整数,没什么特别的。如果你这样认为,那么你很可能会把它们处理得* 错误 。为什么本博客旨在为您提供一些在 机器学习(ML) 中使用*计数数据的技巧,帮助您避免一些您以前可能从未注意到的常见错误。****
先说一个简单的问题。
假设我们正在开发关于电影观看的 ML 模型,并且有一个名为“用户在最近 6 个月观看的卡通电影计数”的字段。由于每个人对电影的口味不同,所以我们看到的是 0,1,2,3…101 这样的值(没错,看了 101 电影的用户一定是个超级粉丝)。
现在我有个问题要问你:
这个计数数据可能遵循什么统计分布?
如果你的答案是“正态分布”或者“我不知道”,那么恭喜你!我相信这个博客会帮助你。
如果你没有太多的统计学知识,那也没关系。这个博客旨在提供实际操作的 ML 技术,尽管我也为好奇的读者提供一些统计数据的细节。
首先我们来看看这个计数数据(一个为了演示而创建的玩具数据)的剧情和数据汇总。正如我们所知,进入一个全新的数据集最快的方法是绘制一些图表。所以我们开始吧:
import numpy as np
import pandas as pd
import plotly.express as px
count = np.concatenate((np.zeros(202),np.repeat(1, 50),np.repeat(2, 40)))
np.random.seed(1)
a=np.random.choice(range(3, 60),90)
b=np.random.choice(range(61, 100),20)
df = pd.DataFrame(np.concatenate((count, a, b, [101])),columns=['val'])
fig = px.histogram(df, x='val',nbins=200)
fig.show()
作者图片
作者图片
现在我确信你不会再假设这是一个正态分布。你可能会注意到数据是…
…高度歪斜右边有一条长尾巴,带着一堆 0 的。****
事实上,如果我们看看中间值,他们中的一半是 0,这表明一半的用户在过去 6 个月中没有看过任何卡通电影。你可能开始同意我的观点(如果你以前不同意),这种数据可能需要在你的 ML 模型中得到适当的处理。是的,这种类型的数据在统计中有一个特定的类别:零膨胀,表示计数数据的分布是稀疏的,有许多 0(本例中为 50%)。
接下来,在第 2 节中,我们将讨论新手在处理作为建模特征(即自变量)的偏斜计数数据时的常见错误。然后在第 3 节中,我们将看到当预测偏斜计数数据是您的目标(即响应变量)时的注意事项。如果你准备好了,那我们就开始吧!
2.作为独立变量的偏斜计数数据
常见错误 1:根据数据的统计数据移除异常值
我们都知道在数据探索之后要做的第一件事是数据清理,其中离群点去除是一个重要的部分。但是,在应用一些常见的异常值剔除方法时,如标准差法和四分位差法,请务必小心。正如您从下面看到的,您可能最终会删除大部分不是异常值的值,因为在这个倾斜的数据中,中值是 0。
- 错误:使用标准差法- >计算出的异常值百分比为:96.5%(该方法将大部分数据作为异常值)
**# Mistake 1: Standard Deviation Method
# calculate summary statistics
data_mean, data_std = np.mean(df.val), np.std(df.val)
# identify outliers
cut_off = data_std * 3
lower, upper = data_mean - cut_off, data_mean + cut_off# remove outliers
outliers_removed = [x for x in df.val if x > lower and x < upper]
print('the calculated percentage of outliers is:',100*len(outliers_removed)/df.shape[0])**
- 错误:使用四分位差法- >计算出的异常值百分比为:19.7%(好于标准差法,但异常值仍然过多)
**# Mistake 2: Interquartile Range Method
# calculate interquartile range
q25, q75 = np.percentile(df.val, 25), np.percentile(df.val, 75)
iqr = q75 - q25
# calculate the outlier cutoff
cut_off = iqr * 1.5
lower, upper = q25 - cut_off, q75 + cut_off# identify outliers
outliers = [x for x in df.val if x < lower or x > upper]
print('the calculated percentage of outliers is:',100*len(outliers)/df.shape[0])**
剔除异常值的解决方案:
谨慎使用基于数据分布统计的方法,如均值或中值。我们可以考虑使用像百分点封顶这样的方法(删除大于某个阈值的点,比如 99%)。****
常见错误 2:不做任何事情就将有偏差的计数数据投入线性回归
在执行线性回归模型时,人们通常会忽略使用 OLS 模型的基本假设,比如所有自变量建模后的误差应该服从正态分布。因此,如果你对有偏差的计数数据什么都不做,OLS 模型不会给你可靠的结果。
如果你感兴趣,这背后的一些统计数据(或者你可以跳过这个):
你不需要让自变量遵循正态分布进行线性回归,但为什么你仍然关心你的自变量是否偏斜?原因是:
- 尽管在实际绘制残差图之前很难判断,但有偏差的数据很可能会违反我们上面提到的假设(残差/同方差的正态性),并牺牲模型的准确性。
- 重尾可能会增加高杠杆的概率,从而影响回归模型的性能。
- 运行线性回归后计算 t 统计量和 p 值是很常见的,线性回归旨在评估估计系数是否与 0 有显著差异。为了使推论有效,估计系数的分布必须遵循正态分布。
那该怎么处理呢?有些人可能会考虑使用一些数据转换方法。嗯,这是正确的方向,但请务必避免下一个错误:
常见错误 3:使用 Box-Cox 方法进行数据转换
Box-Cox 是转换数据的一种很好的方法,但它不应该在这里应用,因为它有一个假设:数据必须全是负数或正数。由于我们的数据中有大量的 0,Box-Cox 不能再用了。
数据转换的解决方案:
1)给这个字段的所有值加一个小数字(我建议 0.5),做对数转换。为什么要加 0.5?因为你不能对 0 做对数运算,这在数学上是没有定义的。
2)通过取值的平方根进行平方根变换。
这两种方法都有助于改善偏斜度,如下面的输出所示。
**print('skewness of raw data:', df['val'].skew())
# log transformation
df['log_trans'] = np.log(df.val+0.5)
print('skewness of log-tranformed data:', df['log_trans'].skew())
# square root transformation
df['sqr_trans'] = np.sqrt(df.val)
print('skewness of square root tranformed data:', df['sqr_trans'].skew())**
作者图片
附加提示:
1。如果您的数据非常稀疏,例如> 60%都是 0,我建议您将其更改为二进制变量:
**df['binary'] = np.where(df.val>0, 1, 0)**
2.如果您正在使用非线性 ML 方法,比如树模型,您可能不需要太担心有倾斜的数据。然而,由于多种原因,如可解释性、立法要求等,线性回归模型在工业中被广泛使用。
3.作为响应变量的偏斜计数数据
当偏斜计数(零膨胀)数据是响应变量时,我们可能会面临一些类似的问题,如异常值去除,您可以参考第 2 节中的解决方案。就不对称计数数据的建模而言,我们希望避免以下错误:
常见错误 4:将数据作为一般的连续响应变量来处理
许多人用线性回归(OLS)拟合数据,发现模型性能不好。这是可以理解的,因为数据不是来自正态分布(如第 1 节所述),所以 OLS 不会很好地估计它(尽管这样做是有效的)。
为了获得更好的模型性能,我们需要理解数据分布的本质。回到我们一开始的问题:“这个计数数据可能遵循什么统计分布?答案是:
与其用单一分布来描述,不如用二项式(看不看)和泊松分布(如果看了也算)来描述。
理论表明,多余的零是通过与计数值(即正值)分开的过程产生的(参考文献 1)。1).因此,我们可以认为数据有两部分:第一部分是一个二进制变量,表示值是否为 0。在第二部分,我们看到数据来自计数数据的泊松分布。
有两种方法可以尝试符合模型:
3.1 机器学习方法
- 如果你有一些 0(<30%):**
您可以尝试使用 Python 库“scikit-lego”(参考文献 2)中的零膨胀回归器来拟合一个模型的数据
- 如果您有多余的 0:
虽然你仍然可以使用上面提到的 Python 库“scikit-lego ”,但我个人会对这么多零感到有点担心,因为这表明数据有明显的分段/分离。正如我们讨论的数据来自两个过程,我会考虑为这种类型的数据创建两个 ML 模型:
-第一个模型将预测值是否等于 0。在博客的例子中,我们使用第 2 节中创建的 df['binary']作为第一步的响应变量。
-其次,我们过滤掉所有的 0,并为大于 0 的值开发一个模型。
****在我们的“观看卡通电影”的例子中,我们可以像“用户细分”一样考虑这个过程,通过预测:
- 如果用户观看了卡通电影,****
2)关注观看过卡通电影的用户,并预测他们观看了多少部。
3.2 统计建模
有许多研究讨论零膨胀数据。这里有几个你可以尝试的模型(参考。1):
- 零膨胀泊松回归
- 零膨胀负二项式回归 —负二项式回归更适用于过度分散的数据,即方差远大于平均值。
- 普通计数模型 —如果没有多余的零,泊松或负二项式模型可能更合适。
4.摘要
计数数据很常见,但如果有多余的零,就很难处理了。这篇博客为您提供了清理、操作和建模偏斜计数数据时的四个常见错误。我希望你能从这个博客中学习,这样你会对你的机器学习之旅更有信心!
注意:我在这个例子中创建的正值不一定遵循泊松分布,因为它只是用于演示目的的玩具数据。在现实中,这种正计数数据应该遵循泊松分布。
💖喜欢这个故事吗?请随意订阅 DS 和 ML 粉丝的邮件列表,并且成为会员!🤩
这篇博客最初发表在我的个人网站上。
****参考文献
1。https://stats.idre.ucla.edu/r/dae/zip/2。https://scikit-lego.netlify.app/meta.html****
避免用 R 平方来判断回归模型的性能
原文:https://towardsdatascience.com/avoid-r-squared-to-judge-regression-model-performance-5c2bc53c8e2e?source=collection_archive---------3-----------------------
依靠 R 来判断一个回归模型的表现是被误导的
总结
r 可以在 之前计算 甚至拟合一个回归模型,这没有意义然后用它来判断预测能力。如果你翻转输入和输出,你会得到相同的 R 值。同样,这对于预测指标来说是没有意义的。
您的回归模型的意图是选择合适度量的重要因素,合适的度量可能是 而不是 R。
本文解释了存在哪些更好的替代方案:标准误差、置信区间和预测区间。
1.我们为什么要建立线性回归模型?
收集历史数据并计算输入𝑥和输出𝑦之间的关系。这种关系往往是线性回归模型,写成𝑦 =a+ 𝑏𝑥,其中截距为 a ,斜率为 b 。
最常见的目的是使用计算出的关系,并预测一些未来的输出,称为𝑦̂,给定一个新的输入:𝑦̂=和+𝑏𝑥.
以下是建立线性回归模型的两个最常见的原因:
- 向了解更多关于投入与产出的关系;
- 到目前为止,最常见的用法是根据输入获得输出的预测。
让我们依次来看一下每一项。
了解更多关于关系的信息
线性回归𝑦= a+bx 的系数𝑏显示了投入𝑥.每增加一个单位对产出𝑦的平均影响这叫做“了解我们的系统”。
回归模型的斜率和截距提供了对系统的学习或洞察。该图还显示了这里使用的术语。【来源:自己的作品
例如,如果您在系统(输入)的摄氏温度𝑥=temperature 和𝑦=pH(输出)之间建立了一个回归模型,您可能会得到一个回归模型: 𝑦=4.5+0.12𝑥 ,从中您可以了解到两点:
- 温度每升高 1 度,平均会导致 pH 值增加 0.12
- 当使用𝑥=0 摄氏度的温度时,预期或预测的 pH 是 4.5 单位的输出 pH。
但是考虑两种情况:如果我告诉你这个模型的 R 是 0.2,或者是 0.94 呢?这对你的学习有什么影响?我们将在下一节中讨论这个问题,在这里我们将对 R 测量的内容有更多的了解。
使用模型的预测
这个场景是大多数人都熟悉的。继续上述内容,它询问对于给定的新的温度输入值𝑥.,预测的 pH 值是多少例如,在我们从未使用过的 13°C 新温度下,我们预计输出 pH 值为 4.5+0.12×13=6.06 pH 单位。
同样,当模型的 R 值在 0.2 左右,或者模型的 R 值为 0.94 时,我们赋予这样的预测什么样的价值呢?
2.背景:R 实际衡量的是什么?
注意:搜索类似“http://www.google.com/search?q=R2+interpretation”或类似的短语,会返回许多推理错误的网站。
最简单的形式是,R 只不过是两个变量相关程度的度量。它是𝑥和𝑦.之间相关系数的平方
其中花式“E{…}”是“的期望值”运算,花式“V{…}”是“的方差”,Cov{ x , y }是“的协方差”运算。𝑥和𝑦上方的水平线告诉您使用这些数据列的平均值。
A 第二种解读是 R 是回归平方和(RegSS)与平方和总和(TSS)的比值。任何“平方和”值都只是一个重新调整的方差,因此这里的公式显示 R 只是两个方差的比值:
r 值为 1.0 意味着分子和分母完全相同,或者换句话说,预测值𝑦̂ ᵢ 与原始值𝑦 ᵢ 完全相同。相反,要使 r 的值为 0.0,分子必须等于零,这意味着预测只是等于一条平线,即𝑦的平均值,而不管𝑥.的输入值是多少这是你能得到的最差的模型:它说在 R =0 的情况下,你能对𝑦做出的最好预测只是返回训练𝑦值的平均值。
R 的一般解释来自于这个等式:这就是解释的百分比变化。分母与总变化量成比例,分子是解释的变化量,导致 0 和 1 之间的分数(百分比)。
开放圆用于计算(建立)模型;而单个闭合圆圈显示了该模型如何在稍后被用于进行预测。RegSS、RSS 和 TSS 是根据空心圆表示的数据点计算的。【来源:自己的作品】。
与之前的解释相关的是 R = 1.0 RSS/TSS,因为对于简单的回归模型,我们有 TSS = RegSS + RSS。
RSS 是残差平方和(RSS),或者从数学上讲
这清楚地表明,要得到 R =1,你必须没有残差(RSS = 0);R =0 意味着 TSS = RSS,换句话说,残差与原始数据的方差相同。
更多的细节和说明在我的免费书中:https://learn che . org/PID/least-squares-modeling/least-squares-model-analysis
到目前为止的总结
理解上面的公式并尝试用简单的语言解释它们是非常有益的。一开始这并不容易,但理解如何使方程的每一部分变大变小,以及如何获得 0.0 和 1.0 的极值是值得的。
3.为什么 R 不足以判断模型的回归性能
综上所述,这里有两个非常简单的原因,说明为什么 r 几乎不是判断根据新的输入𝑥:预测新的输出𝑦的正确度量
- 如果你把历史数据调换一下,把𝑦变成𝑥,让𝑥变成𝑦,那么你得到的 和 R 值完全一样。这有什么意义呢?模型预测能力的度量标准必须取决于什么是输入,什么是输出。
- 如果我告诉你在 计算模型的斜率和截距之前,我可以告诉你 R 值会是什么 会怎么样?同样,这没有意义。在拟合预测模型之前,如何计算预测性能的良好度量?
这相当于在拟合神经网络之前计算它的预测能力;或者翻转神经网络的输入和输出,得到相同的性能指标。
那么我们如何做出这两个关于 R 的强有力的陈述呢?回头看看第一个公式:
把𝑥和𝑦调换一下
分子是对称的。如果你交换𝑥和𝑦的角色,你会得到相同的分子值。这也适用于分母。请用 Python,Excel,R,MATLAB,或者任何你用来做线性回归的工具自己确认一下。下面是一些拟合线性模型的 R 代码(lm
):
*x = c(10, 8, 13, 9, 11, 14, 6, 4, 12, 7, 5)
y = c( 8, 7, 8, 9, 8, 10, 7, 4, 11, 5, 6)
summary(lm(y ~ x)) # R^2 = 0.657
summary(lm(x ~ y)) # R^2 = 0.657*
能够在拟合模型之前计算 R
再来看一下上面的公式。它是否取决于:
- 模型的残差? 否
- 模型的任何系数,如斜率或截距? 否
因此,即使不拟合回归模型,也可以计算 R。该公式仅依赖于原始数据,而不依赖于任何模型!这不是什么数学把戏,因为事情以某种特殊的方式抵消或简化了。这只是一个 r 被设计用来测量的事实:𝑥和𝑦.两个序列之间的相关程度
很简单,最后一句话指出了何时应该使用 R:仅作为两个序列之间相关性的度量。
4.好吧,我已经被说服了。但是应该使用哪些指标呢?
让我们回头看看这两个用例:
- 从模型中学习
- 根据模型进行预测
从模型中学习
如果你的目标是解释斜率或截距,那么使用一个与之相关的度量,而不是 R。在这种情况下,斜率和截距的置信区间是信息性的。置信区间是两个数字,一个是范围。在此范围内,您可以预期,在指定的置信度下,它包含参数的真实值(如斜率)。让我们回到温度和 pH 值的例子,只考虑斜率。同样的想法也适用于截击。
请记住,𝑦=4.5+0.12𝑥意味着温度每升高 1 度,平均会导致 pH 值增加 0.12 个单位。真实(但未知)斜率的 95%置信区间可能是[0.09;0.15],这意味着我们有 95%的可能性这个范围包含真实的斜率。注意, 不是 真实斜率在这个范围内的概率;一个微妙但重要的区别。有 没有概率 与真值相关联;概率与包含真实斜率的范围相关,真实斜率是一个固定但未知的值。
为什么使用置信区间?主要原因是数值都是你关心的单位,而不是两个方差的抽象比值,比如 R,其次,范围越宽,模型越差。假设斜率的置信区间是[0.09;0.15]或[0.03;0.21];你想要哪个?
在间隔的宽度和 R 的值之间存在直接的关系,但是这种关系是非线性的,并且对于不同的模型具有不同的形状。
这里有一些你可能会用到的 R 代码。类似的代码在 Python 中也是可行的:
*x = c(10, 8, 13, 9, 11, 14, 6, 4, 12, 7, 5)
y = c( 8, 7, 8, 9, 8, 10, 7, 4, 11, 5, 6)linmod = lm(y ~ x) # predict y from x
summary(linmod)
confint(linmod) # confidence interval*
根据模型进行预测
如果您想要判断模型的预测,请使用标准误差 (se)或预测区间,而不是 R。为什么使用 SE?
标准误差是残差的标准偏差。这听起来比 R 更复杂,但事实并非如此。首先,标准误差有输出变量的单位。换句话说,它有你真正关心的量的单位,预测的单位!如果您的残差呈正态分布(使用 q-q 图进行快速简单的检查),那么您知道大约 70%的残差位于范围[SE;+SE],95%的残差在 2SE+2SE]。这是我个人使用最多的方法:计算 se 并乘以 4,以了解我的典型残差的“带宽”。不确切,但足以判断“我的预测模型够好吗?”如果您认为预测值的范围在 2SE+2SE],那你就可以对你的模型满意了。
你会在无数的博客和教科书上读到 R 低不一定不好,R 高也不一定好。没错。这是因为我见过 R 超过 0.99 的情况,但标准误差仍然太大,对最终用户的要求没有用处。
比使用构建(训练)模型时计算的标准误差更好的方法是使用全新测试数据集上预测的残差的标准偏差。这是相同的指标,但只是从测试数据中计算出来的,或者如果您不能将测试数据放在一边,则通过交叉验证来计算。
与标准误差相关的另一个选项是使用预测区间。这就像是一个置信区间,但对于一个全新的预测。在上面的例子中,我们可能有:
- 一个新的温度测量,𝑥=10 摄氏度,导致预测的 pH 值为 5.7±0.4
- 换句话说,预测的 pH 值位于从[5.3 到 6.1]的范围内,置信度为 95%。
预测区间(为了说明而放大)是阴影区域。它在训练数据的中心最窄,并且随着距离的增加而变宽。【来源:自己的作品
这样的时间间隔非常有用;我们马上得到一个范围,用我们关心的单位,也就是输出变量𝑦.的单位预测区间是图中的阴影区域,并且是非线性的。离模型中心点越远,它就越宽。虽然在一些软件包(如 Excel)中并不总是容易获得这个区间,但作为一个近似规则,您可以使用阴影区域覆盖 2SE。
*x = c(10, 8, 13, 9, 11, 14, 6, 4, 12, 7, 5)
y = c( 8, 7, 8, 9, 8, 10, 7, 4, 11, 5, 6)linmod = lm(y ~ x) # predict y from x# Get the prediction interval for 3 new values of x:
newdata = data.frame(x=c(1, 8, 15))
predict(linmod, newdata, interval="predict")*
如前所述,R 值越高,预测区间宽度越小,这直观地证明了 R 越高越好,但您无法提前推导出什么是“好 R”的截止界限,因为它取决于测量的数据,当然也取决于您的目的可接受的范围。
收尾
问问自己为什么要建立线性回归模型:
- “我想更多地了解我的斜率或截距”。对它们使用置信区间,而不是 R。较高的 R 与较小的置信区间相关。
- “我希望能够从我的模型中判断预测”。使用预测间隔或模型的标准误差。较高的 R 与较小的预测区间和较低的标准误差相关。
所有描述的选择都比 R 更容易理解,并且是你关心的单位。如果你已经做到这一步,并想阅读更多,请查看我的免费书籍。
避免这些与 Python 中的参数和自变量相关的陷阱/错误
原文:https://towardsdatascience.com/avoid-these-gotchas-errors-related-to-parameters-and-arguments-in-python-6bf4dbec9183?source=collection_archive---------27-----------------------
我们将讨论几个错误和一个与 Python 参数相关的问题。
麦克斯韦·尼尔森在 T2 的照片
在继续之前,让我们讨论几个术语。查看下面的代码片段。这是一个简单的函数,打印其参数的总和。
代码片段
- 参数 -它们是函数定义中列出的名称。例:在上面的代码片段中, num1 和 num2 是参数
- 参数——它们是我们在调用函数时传递的值。例如:在上面的代码片段中,在对函数 10 和 12 的两次调用中,参数都被传递给了函数
- 位置实参——当我们将实参传递给一个函数而没有显式地将它们赋给参数时。在上面的代码片段中,我们在第一次调用 func 时使用了位置参数
- 关键字参数 -当我们通过显式地将参数赋值给形参来传递参数给函数时。在上面的代码片段中,我们在第二次调用 func 时使用了关键字参数
- 默认值 -在功能定义期间分配给参数的值。例:在上面的代码片段中, 20 是赋给参数 num2 的默认值
默认参数的顺序
规则:如果在定义函数时有一个带默认值的参数,那么它后面的所有参数也必须有默认值
错误的
代码片段
在上面的 func 的函数定义中,一对没有默认值的参数( num3,num4 )跟在一个有默认值的参数( num2 )后面。这将导致语法错误。
正确的
代码片段
这不会导致任何错误,因为我们已经为变量 num3 和 num4 指定了默认值
关键字参数的顺序
ULE:当调用一个函数时,一个关键字参数必须跟在一个关键字参数之后。因此,位置参数不能跟在关键字参数后面。
错误的
代码片段
12 作为关键字参数传递。然而,它后面的自变量( 20 和 30 )作为位置自变量被传递。这将导致语法错误。
正确的
代码片段
这次,我们将参数( 20 和 30 )作为关键字参数进行传递。因此,不会引发任何错误。
默认参数值
误解:在每个函数调用期间,默认值被分配给参数
正确:默认值只分配一次。在将来的函数调用中,使用以前的值
当你遵循下面的例子时,这将更有意义
代码片段
该函数有两个参数 num 和 arr 。 arr 有一个空列表的默认值。该函数不做任何花哨的事情。它只是将参数 num 插入到数组 arr 中,然后打印该数组。
预期
'''OUTPUT[10][20][30]'''
所以基本上每次我们调用函数的时候, arr 都被设置为一个空列表的默认值,并且 num 被插入其中。
但这不是正确的输出
实际的
'''OUTPUT[10][10, 20][10, 20, 30]'''
嗯,很奇怪吧?🤯
基本上,默认值是在第一次函数调用时设置的。在下面的函数调用过程中,不会再次分配默认值。而是使用以前的值。
解决办法
代码片段
不将空列表指定为默认参数,而是将 None 指定为默认值,并在函数内指定空列表。
结论
我希望你今天学到了新东西。参数和实参看起来是简单的概念,但实际上,它们比你想象的要稍微复杂一些。现在你知道要避免的错误和误解。
在LinkedIn, Twitter 上跟我连线
原载于 2021 年 5 月 2 日 https://www.realpythonproject.comhttps://www.realpythonproject.com/avoid-these-gotchas-errors-related-to-parameters-and-arguments-in-python/。
用平均避免麻烦
原文:https://towardsdatascience.com/avoid-troubles-with-average-923012d1cd3e?source=collection_archive---------39-----------------------
平均值是最常见的显示值,但经常会产生误导
由 Charles Deluvio 在 Unsplash 上拍摄的图像
平均反应是积极的。平均值是 3。对于这个话题,普遍的看法是中立的。平均而言,女性比男性更赞同。你一直都在阅读和听到这样的陈述。是什么样的信息?
平均值可以是多个值。它是一组数据中的典型值(按照牛津语言的定义)。使用统计词汇,平均值可以是:
- Mode 是一个数据集中出现频率最高的数字,意思是被挑选最多的选项。
- Median 当你从最小到最大排序你的值时,把你的数据集从中间分开。
- Mean 是一种将所有数字相加并除以数值个数的计算方法。
都有一些优点。然而,平均值是最常用的值。但是我们用得好吗?
卑鄙可以是卑鄙
注意您的平均值,并根据您的数据对其进行评估,以防止误解。这里我们有一个问题和一个分析师的笔记:
Q1。您对以下陈述的同意程度如何:您的经理定期与您一起评估您的目标。
- 非常同意(5)
- 稍微同意(4)
- 既不同意也不反对(3)
- 略微不同意(2)
- 强烈反对(1)
分析师:对 Q1 的平均反应是 3.00。我们的受访者既不同意也不反对这一说法。
如果我们只看平均值,我们就看不到全貌。我们可以使用平均分数来比较其他语句和我们的 Q1,但是这样做值得吗?每当我们有一个平均值时,我们需要掩盖它背后的东西。我们来看看下面的数据:
Ivona Fikejzlova 提供
这里我们有选项 A 和 b,它们的平均值都是 3.00。然而分布是不同的。如果我们有选项 A,3 的平均值也是它的众数和中位数。在这种情况下,大多数受访者既不同意也不反对。
但是当我们有选项 B 时,反应是两极化的:30%的人同意,30%的人中立,30%的人不同意。
均值不适合捕捉两极分化的数据或极端情况。意思是可以隐藏信息。所以,不要让刻薄的人对你刻薄,要经常检查你的数据分布。平均值并不是任何时候都有用,所以在有意义的时候使用它。
小数字的平均值
许多学生确实打算从课堂上评估他们的最终评价。这样,他们知道会发生什么。
Ivona Fikejzlova 提供
在这里,我们的学生知道,如果他想得到 2 分,他需要在期末考试中表现出色,得到 1 分。否则,他会得 3 分。这是计算平均值的一种简单而有用的方法,
在其他情况下,当我们从一小部分人那里收集数据时意味着是多余的。假设我们有一份 10 人的问卷,最终呈现的数据如下所示:
Ivona Fikejzlova 提供
它让数据变得更加复杂。当我们有像这样的小数字时,它足以呈现计数。我们不必为平均值或百分比而烦恼。毕竟 10% = 1 人。
在这种情况下,这种方法不能提供有用信息。这会分散观众的注意力。在这种情况下,我们会做更多的定性分析。我们关注个体而不是平均水平。
干净数据的平均值
许多数据收集调查都有逃避性的回答,比如“我不知道”或“我不想回答”。
在准备平均值时是否应该考虑这些因素?而完全不填数据的人呢?他们应该参与计算吗?
只有相关的数据才能提供你的平均数据。你的平均分数)。所以,小心错误的选择。从数字数据中得出平均值是很容易的。当你必须将书面数据转换成数字时,你可能会面临一个潜在的问题。
所以,在计算平均值之前,你必须清理你的数据。清洁过程正在检查这些:
- 数据范围:如果我们有一个刻度,比如 1-5,就不应该有 6、7、8 等等。如果我们把错误留在那里,平均值将是错误的。
- 空数据:我们经常会遗漏一些数据。这就是为什么该项目不应该进入计算,因为平均将再次是错误的。
- 非数字数据:需要填写数字。但是他们写的不是 2,而是 2。您需要将所有文本值更改为数字,以便能够计算平均值。此外,任何其他不相关的文本应该相应地编码。
干净的数据易于处理和操作。您可以选择感兴趣的平均值——众数、中位数或平均值。这取决于你分析的范围。
最终平均音符
无论何时你要提出一个平均值,不要想当然。想想为什么要呈现,怎么呈现。
平均值适用于比较,但不适用于分析数据分布。您有三个选项——众数、中位数和平均数。
所有数据应该是干净的,没有错误的值,以达到正确的平均值。
注意,如果数据样本很小,平均值可能不是最合适的值。最后,一定要提到你是如何计算平均值的。每个人都应该清楚你在说什么,你是怎么做到的。
附注:你应该会收到我的邮件。 做到这里 ! 如果你自己喜欢体验媒介,可以考虑通过注册会员 来支持我和其他成千上万的作家 。每月只需 5 美元。
如何以及为什么停止使用熊猫。申请()(这么多)
原文:https://towardsdatascience.com/avoiding-apply-ing-yourself-in-pandas-a6ade4569b7f?source=collection_archive---------3-----------------------
理解为什么确定。apply()的工作很好,为什么有些人表现不佳。
如果您正在阅读这篇文章,我猜您已经在某个时候使用过流行的 python 数据处理库 pandas 中的.apply(…)
方法。如果你没有,那么你可能会迷失,你可能不会从这篇文章中得到很多(但无论如何,如果你读了它,还是值得称赞的)…
如果这篇文章写得好,并且你成功地阅读和理解了它,你可以希望;
- 更好地了解
.apply(…)
在不同场景中的作用(剧透一下,它可能不总是你想的那样); - 知道什么时候
.apply(…)
可能是一个好的选择,什么时候使用替代品可能更好;
“当你只有一把锤子时,一切看起来都像钉子”
我将在这篇文章中指出,最好少用.apply()
,当你把手放在.apply()
瑞士军刀上时,可能会有其他更合适的工具。
由我用 Microsoft Paint 专业绘制
有什么关系?apply() do?
在一个非常高的层次上,.apply()
允许我们以不同的方式调用 pandas 对象上的 python 函数。这使得第一次使用 pandas 库时变得非常容易,因为你可以用一种非常熟悉的方式编写 Python 代码,然后使用.apply()
将其转换到你的系列或数据帧上。
什么(在我看来)是有效的熊猫?
关于这方面的文章有很多很多,所以我就不赘述了,但这里有一些关于“有效的熊猫”(或一些人喜欢称之为“可漫游的熊猫”)的重要特征的观点:
- 尽可能有效利用矢量化运算的代码(这几乎总是可能的)
- 对于我们原始的大脑来说,代码是容易阅读和理解的(当然这不仅仅是熊猫的代码)
如果你想了解更多关于这些事情,请去做吧(但是之后一定要回来)。关于 pandas 性能的一个关键要点是,在 pandas 数据帧中对每一行进行操作通常很慢,但使用列作为序列对其进行矢量化操作(一次处理一整列)通常很快。
申请什么?
在熊猫中使用 **.apply(…)**
的时候,这大概是最需要问自己的问题。你可能会合理地认为,每当你在熊猫身上做 **.apply(…)**
动作时,它都会以大致相同的方式动作,不幸的是事实并非如此!
你有一个 python 函数和一个 pandas 对象,你想把你的 python 函数应用到你的 pandas 对象,但是这个函数实际上会收到什么参数(它会得到一个 int,一个 series,一个 dataframe)以及这对代码的行为有什么影响?
答案是,这取决于你正在应用的对象的类型(我们将查看pd.Series
、pd.DataFrame
和pd.GroupBy
),以及你如何调用、。
我们将创建一个简单的测试数据框架,并进行一些探索…
import pandas as pd
import numpy as np
df_len = 1000
test_df = pd.DataFrame(
{
"cat_column": np.random.choice(["a", "b", "c"], size=df_len),
"float_col1": np.random.random(size=df_len),
"float_col2": np.random.random(size=df_len),
}
)
这里我们有一个具有 3 列的数据帧,一个对象列包含“ a”、“b”或“c”,两个浮点列包含 0 和 1 之间的值。
警察。系列.应用
好了,这是更有趣的地方(因为我们已经完成了预华夫饼,我们正在运行一些代码)。现在,请耐心等待,我们将把内置的type
函数作为一个系列应用到我们的一个专栏中。
输入:
print(f"Applying on {type(test_df['float_col1'])}")
test_df["float_col1"].apply(type)
结果:
Applying on <class 'pandas.core.series.Series'>0 <class 'float'>
1 <class 'float'>
2 <class 'float'>
3 <class 'float'>
4 <class 'float'>
...
995 <class 'float'>
996 <class 'float'>
997 <class 'float'>
998 <class 'float'>
999 <class 'float'>
Name: float_col1, Length: 1000, dtype: object
酷,谁在乎?这告诉我们什么?嗯,第一行简单地告诉我们,在这种情况下,我们正在.apply
到一个pd.Series
。输出的其余部分告诉我们什么?它告诉我们一些事情:
- 当我们对
pd.Series
应用函数时,函数接收序列中的值作为参数,而不是一次性接收整个序列。我们正在使用的type
函数接收每个“单元格”中的浮动对象。 - 我们应用的函数在序列中每行被调用一次(在本例中被调用 1000 次)
如前所述,每行调用一个函数会有性能损失,所以当您在一个pd.Series
上调用.apply
时,您并没有向量化您的操作,如果可以的话,请避免使用这种.apply
。
系列应用的调用模式图,应用的函数 f 是用系列中的单个值调用的。
例子
例子的问题是它们总是做作的,但是相信我,在大多数情况下,这种pd.Series.apply
是可以避免的(请至少试一试)。因此,在这种情况下,我们将采用示例数据帧中的一个浮动列的log(cos(x) + 5)
,只是因为它看起来有点复杂,我们可能会在这种情况下使用 apply。
def trig_transform(x):
return np.log(np.cos(x) + 5)
使用 pd。
test_df["float_col1"].apply(trig_transform)
时机
3.25 ms ± 119 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
忌 pd。Series.apply:
因为大多数常见的数值运算在 numpy 中都有一个矢量化的实现,可以接受标量或数组,所以在某些情况下(比如这样),您可以简单地直接在pd.Series
上调用函数,而不是将它应用于每个元素。
trig_transform(test_df["float_col1"])
时机
264 µs ± 11.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
我不会喋喋不休地说它快了多少,但在这个基准测试中,它看起来快了大约 12 倍,但您应该亲自尝试一下,因为性能有许多因素。
非数字示例可能需要对我们在 pandas 对象上调用的函数进行一些更改,我建议您查看一下pd.Series.str
访问器和pd.Series.dt
以了解字符串和日期时间类型上的常见操作。
警察。数据框架.应用
警察。DataFrame.apply(轴=0)
好了,让我们对之前的代码做一个很小的改动,来观察 apply 在pd.DataFrame
而不是pd.Series
上的行为。我们使用相同的测试数据帧,但是这里选择相关的列作为列表["float_col1"]
而不是单个字符串"float_col1"
。
输入:
print(f"Applying on {type(test_df[['float_col1']])}")
test_df[["float_col1"]].apply(type)
输出:
Applying on <class 'pandas.core.frame.DataFrame'>float_col1 <class 'pandas.core.series.Series'>
dtype: object
我们可能期望在这里得到类似的结果,但事实并非如此,我们可以看到我们的函数只被调用了一次,而不是 1000 次,并且在我们应用的函数中收到了一个pd.Series
。
当您在pd.DataFrame
上调用 apply 时,(默认轴=0),应用的函数在每列被调用一次。这对调用函数的行为有很大的影响。
dataframe apply 的调用模式图示在 axis=0 的情况下,使用 dataframe 中的列系列调用应用的函数 f。
例子
这是另一个人为的例子。这一次,我们将对示例数据帧中的每个浮点列应用上一个示例中的相同函数。
def trig_transform(x):
return np.log(np.cos(x) + 5)
使用 pd。DataFrame.apply (axis=0)
在我们的示例数据框架中,我们只将这些应用于数字列,否则我们会遇到一些错误。
test_df[[“float_col1”, “float_col2”]].apply(trig_transform)
时机
2.74 ms ± 367 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
如果你回到前面的例子,你可以看到它在 2 列上比pd.Series.apply
在 1 列上运行得更快。
避免 pd。DataFrame.apply (axis=0)
等等,为什么我们要避免使用pd.DataFrame.apply
?看起来性能还不错。好吧,我要给出的原因与性能无关,你可以不同意;每次你使用.apply()
时,它都要求代码的读者/维护者知道它是如何被使用的,以及它将如何运行;因为.apply()
可能有许多行为方式,这增加了代码的复杂性,而(在大多数情况下)没有增加价值。
同样值得注意的是,这种.apply()
非常罕见,因为您很少想要在数据帧中的每一列上单独调用同一个函数。
*trig_transform(test_df[[“float_col1”, “float_col2”]])*
时机
*1.1 ms ± 45.6 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)*
在这种情况下,就像 Series 示例一样,我们可以直接在 DataFrame 上调用我们的函数,因为 numpy 函数适用于所有不同形状的数组(wow numpy 很好)。在这种情况下,速度快了两倍,而且我认为更容易理解。如果你想念.apply()
给你的链接风格,考虑在这里使用.pipe()
,这有一个更简单的使用模式,并且和直接函数调用一样快。
*test_df[["float_col1", "float_col2"]].pipe(trig_transform)*
警察。DataFrame.apply(轴=1)
在应用于pd.DataFrame
时,您可能会经常看到 axis=1 参数。这给出了另一种不同的行为;该函数每行调用一次,而不是每列调用一次。
输入:
*print(f"Applying on {type(test_df[['float_col1']])}")
test_df[["float_col1"]].apply(type, axis=1)*
输出:
*Applying on <class 'pandas.core.frame.DataFrame'>0 <class 'pandas.core.series.Series'>
1 <class 'pandas.core.series.Series'>
2 <class 'pandas.core.series.Series'>
3 <class 'pandas.core.series.Series'>
4 <class 'pandas.core.series.Series'>
...
995 <class 'pandas.core.series.Series'>
996 <class 'pandas.core.series.Series'>
997 <class 'pandas.core.series.Series'>
998 <class 'pandas.core.series.Series'>
999 <class 'pandas.core.series.Series'>
Length: 1000, dtype: object*
在本例中,与pd.Series
apply 不同,调用函数不接收单个单元格元素,而是接收包装在pd.Series
中的行,其中索引是列名,值是列值。
再次考虑性能,您可能希望避免使用 axis=1 applys,因为每行都有一个函数调用,并且我们通常在对列进行矢量化操作时获得最佳性能。
axis=1 应用程序可能很常见,通常很慢,并且通常易于矢量化。
dataframe apply 的调用模式图示在 axis=1 的情况下,对 dataframe 中的每一行调用一系列应用函数 f。
例子
axis=1 apply 是在 pandas 数据框架中的不同列之间进行比较或操作时可能会遇到的一种情况。这种模式(或者反模式)相当常见,因为您编写的应用于数据帧的函数看起来非常 pythonic 化(您得到一行,像字典一样对其进行索引,并对值进行处理)。
这一次,我们将对数据帧应用以下函数。
*def row_trig_transform(row):
return np.sin(row["float_col1"]) * np.sqrt(row["float_col2"])*
使用 pd。DataFrame.apply (axis=1):
*test_df.apply(row_trig_transform, axis=1)*
时机
*34.2 ms ± 1.39 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)*
避免 pd。DataFrame.apply (axis=1):
在这种情况下,我们实际上不需要改变调用函数,尽管我们打算这样做,因为这将提高代码的质量。
*def calculate_series_trig_transform(ser_1, ser_2):
return np.sin(ser_1) * np.sqrt(ser_2)*
为什么这样更好?现在,您可以轻松地在任何其他列或系列中重用该函数。
*calculate_series_trig_transform(
ser_1=test_df[“float_col1”],
ser_2=test_df[“float_col2”],
)*
时机
*290 µs ± 12 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)*
我们得到了相同的结果,我们的代码更具可重用性,并且由于我们使用了矢量化运算,最终速度提高了约 90 倍,这是一个很大的提高。
警察。GroupBy.apply
这是我们在这篇文章中要看的最后一个.apply()
(我们不会触及pd.Series.map
或pd.DataFrame.applymap
,它们也在这个空间中)。你可以说pd.GroupBy.apply
是一个特例,但我认为既然所有这些.apply()
的行为都不同,那么它们都是特例。
所以让我们来看看当我们执行pd.GroupBy.apply
时,我们的调用函数接收到了什么…
投入
*test_df.groupby("cat_column").apply(type)*
输出
*cat_column
a <class 'pandas.core.frame.DataFrame'>
b <class 'pandas.core.frame.DataFrame'>
c <class 'pandas.core.frame.DataFrame'>
dtype: object*
在这种情况下,我们没有得到标量,没有得到一系列的列,也没有得到一系列的行,我们实际上得到的是整个数据帧。这些数据帧包含特定组中的所有行(一个函数调用使用数据帧调用所有行,其中一个调用使用数据帧调用cat_column=="a"
,一个调用使用数据帧调用cat_column=="b"
,一个调用使用数据帧调用cat_column=="c"
)。我们可以推断,只要组的数量不太大,这里的性能就会相当不错(如果每一行都在一个唯一的组中,性能就会很差,而且分组也没有什么意义)。
groupby-apply 调用模式的图示,应用的函数 f 被称为每个组的数据帧(在这种情况下,将“cat_column”作为分组变量)。
例子
这里我们将假设我们想要得到数据帧中所有sin
的总和(我不知道为什么我们可能想要这样,但我们可能会这样)。
*def sum_all_sins(df):
return np.sin(df).sum().sum()*
该函数将每个数据帧中的所有值的sin
转换成一个序列,然后sum
转换该序列的值,得到一个标量。值得一提的是,你不一定要返回一个标量,你也可以返回一个序列或一个数据帧,但我们不打算深入讨论。
使用 pd。GroupBy.apply:
*test_df.groupby("cat_column").apply(sum_all_sins)*
时机
*6.08 ms ± 316 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)*
避免 pd。GroupBy.apply:
在我看来,使用pd.GroupBy.apply
很好。
为什么这个没问题?一个原因是在 groupby 对象中将函数应用于组的其他方法不多(有agg
和transform
,但是它们的用途更具体,或者在组上循环,这不太优雅并且有性能成本)。从这个意义上来说,这个组合就是习语熊猫自己的组合。这也很难出错,应用的函数接收一个数据帧,所以你可以让它快速处理数据帧。
摘要
最后,我将快速回顾一下这些应用程序是如何工作的,以及我是否认为这是一个好的实践(当然这些事情是主观的,这是一个自由的世界)。你可能已经知道了,我的观点是尽可能避免使用 apply。
pd。Series.apply
- 应用的函数每行调用一次,值在该行中
- 通常最好避免——你的列上可能有矢量化操作或内置熊猫操作,这样会更快一些
pd。DataFrame.apply (axis=0)
- 每个列调用一次应用函数,使用列系列的值
- 通常最好避免——如果应用的函数使用了系列运算,则速度会相对较快,但您很可能不需要这种应用,您可以在数据帧上直接调用函数(或通过管道传递它),这可能会使代码更具可读性。
pd。DataFrame.apply (axis=1)
- 每行调用一次应用函数,在每个函数调用中获取一系列行
- 通常最好避免——很可能有一种矢量化的方法可以实现更好的性能。
pd。GroupBy.apply
- 每组调用一次应用函数,每次函数调用获得一个数据帧(如果只选择一列,也可以是系列)
- 典型的好选择——只要你没有太多的组,因为你的函数每个组调用一次。
结论
在你从工具箱中拿出.apply()
之前,考虑一下你是否有合适的箱子。有时“通常很慢”的使用是难以避免的,也许如果你正在使用一些不可避免的棘手的object
类型(比如一列不同长度的列表),这些类型需要不容易矢量化的操作。尽管在大多数情况下有更好的选择。
如果实现很难解释,这是一个坏主意。
这是直接引用自 python 的禅宗(你可以通过在 python 解释器中运行import this
来阅读)。我认为.apply()
API 很难解释(因此有了这篇文章),所以我个人认为最好少用,特别是当经常有其他选项对我们的灵长类大脑来说更容易理解的时候。
希望你从这篇文章中学到了什么,或者如果没有,至少喜欢阅读它!快乐的熊猫!
避免时间序列中的数据泄漏 101
原文:https://towardsdatascience.com/avoiding-data-leakage-in-timeseries-101-25ea13fcb15f?source=collection_archive---------9-----------------------
在 Unsplash 上由 Aron 视觉拍摄的照片
你已经做出了选择。你来这里是为了明白你为什么会成功。—神谕,矩阵
时间序列是几乎每天都变得难以建模的极少数数据学科之一。
例如,丰富的数据对于许多其他领域来说是一个好消息。我们可以训练更好的模型并期待更好的结果。但是在时间序列的背景下,大量的数据经常以不同的形式出现。这通常意味着数据到达的时间间隔越来越短。当这种情况发生时,与其更好地解释这种情况的潜在动力,通常更新的和以前未知的怪癖开始在时间序列中出现。例如,部分季节性或突然变化的趋势。
对于许多其他学科,建模和预测是齐头并进的。对于时间序列来说,它们通常是大敌。以有效市场假说(EMH)为例。它是金融学的一个理论基础,然而,它曾经(现在仍然)是金融时间序列预测的一个强有力的打击。因为它说,由于市场效率,股票价格只是随机游走。模拟随机漫步非常简单。然而,预测是一种徒劳的尝试(EMH 是否成立是另一回事,许多聪明人拒绝相信 EMH)。
在这篇文章中,我将讨论数据泄露,这在很多 ML 任务中很普遍。数据泄漏可能会在您的 ML 生命周期中蔓延,并一直保持沉默,直到您将模型推向生产,一切都将失控。但是什么是数据泄露呢?
维基百科为数据泄露提供了一个恰当的定义。我冒昧地以如下方式对其进行了一点修改:数据泄漏是在模型训练和验证期间使用的信息,这些信息在预测阶段是不可用的。就时间序列而言,这种可用性的缺乏可能以多种形式出现,尤其是当预测范围很大时。这可能是由于以下原因:
- 该功能在未来根本不可用。在交叉验证期间,这种不可用性可能会被忽略,因为我们在数据集上进行交叉验证,而数据集本身是由过去的观察值组成的。因此,在生产之前,我们总是可以访问这些特性。这些类型的数据泄露的主要影响是——他们认为花费在特征创建上的时间是没有意义的
- 为了便于讨论,假设特性可以在预测范围内通过特性本身的预测/预期而变得可用。在这种情况下,有两个警告:(a)可靠的预测是非常昂贵的(b)预测带有许多不确定性/误差,所以做好准备,看看模型在生产中的性能急剧下降。
数据泄露的一个常见例子可能是使用库存变动数据来预测某些生产的数量。在交叉验证阶段,股票运动数据可能显示出极好的匀称值,使其成为一个重要的建模特征。但是当涉及到实时预测时,它的效用变得非常小,如果不是绝对无用的话。
在接下来的内容中,我将尝试标准化一些可以用来避免这个陷阱的实践。这里详述的一些实践在 ML 从业者中非常普遍地被接受,为了完整起见,我将提到它们。
先分裂,后正常化。
这种做法是众所周知的洗钱从业者。这也与时间序列分析有些关系,特别是当涉及神经网络的技术(例如:AR-Net,NeuralProphet,RNN-LSTM)被应用时。这是因为神经网络很难(如果不是不可能的话)用未标准化的数据集进行训练。
这种做法包括以下步骤:
- 将数据集分为训练集、验证集和测试集
- 仅使用训练集计算归一化因子。规范化训练集
- 使用在前一阶段发现的标准化因子,标准化验证和测试集
如果我们使用整个数据集计算出归一化因子,我们就会在模型训练期间以归一化因子的形式引入数据泄漏。这仅仅是因为归一化因子现在包含了来自验证和测试集的统计数据。
有一些重要的警告值得注意。如果被建模的过程不是静态的,那么将归一化因子带到很远的将来(验证+测试)会对模型性能产生不利影响。然而,这是一个不同的讨论。
直接进入 MVP,稍后交叉验证!
听起来有点违背直觉,但让我解释一下。
MVP 代表最小可行产品。这基本上是我们正在设计的 ML 系统的精简版本(例如:推荐引擎或预测引擎),能够实时交付端到端的解决方案。它不一定需要被部署。
通常的 ML 实验生命周期有以下步骤:
- 准备数据集(分割+归一化+要素创建)
- 快速构建一系列模型
- 交叉验证,然后进行超参数调整
- 型号选择/组装
- 创建一个 MVP
请记住,如果模型中存在数据泄漏,那么您所监控的每个性能指标都会被严重夸大,并且在所有模型中不对称。因此,在模型选择过程中,我们可能会因为一个据说是错误的性能指标而放弃最健壮的模型。或者在组装时,我们可能会给每个模型分配不准确的重量,从而在生产中产生不良的预测。
为了避免所有这些陷阱,让我稍微重组和重新设计一下实验生命周期:
- 准备数据集(分割+归一化+要素创建)
- 训练一个简单的模型。为什么不是复杂精密的模型呢?下一步就清楚了。
- 创建一个 MVP。由于 MVP 是实时预测的(例如,未来 7 天),因此无法衡量模型的性能。因此,模型复杂性是不相关的。
- 假设引入数据泄漏的特征被识别,继续进一步迭代(更复杂的模型,模型选择/集合)
这个重新设计的生命周期不仅可以帮助您识别可能引入数据泄漏的特性,还可以让您了解实际上可以包含哪些类型的特性。
不要解耦模型训练和预测/推理
对于许多 ML 任务,模型训练和预测/推理可以完全解耦。以所谓的猫分类器为例。人们可以完全分离分类器训练和分类的过程。可以有把握地假设,进行预测所需的特征(像素值数组)的可用性不是时间的函数。
然而,当涉及到时间序列时,情况就完全不同了。在时间序列分析中,建模和预测通过时间关系交织在一起。只有当一个特征是时间的直接/间接函数时,它才能有助于推断。因此,在模型训练期间所做的每一个决定都需要得到这个想法的全面支持。这与其说是一种实践,不如说是思维过程和领域专业知识的结合。自然需要时间来完善。
就我而言,在我的时间序列分析之旅中,我发现上面的实践非常有帮助。我希望也有一些外卖给你。祝你愉快。干杯!
避免 ML 管道的技术债务
原文:https://towardsdatascience.com/avoiding-technical-debt-with-ml-pipelines-3e5b6e0c1c93?source=collection_archive---------28-----------------------
在快速结果和高质量编码之间取得平衡。
机器学习中的技术债务可能很难管理。来源: Unsplash
好吧,首先让我们弄清楚:这篇文章不是为那些做一次性的孤立项目的人准备的,比如参加 Kaggle 竞赛或者在 Jupyter 笔记本上做爱好项目来学习交易。抛弃、快速、肮脏的脚本代码的价值是显而易见的——并且有它的位置。相反,它是为在生产环境中工作的 ML 从业者设计的。因此,如果你在一个 ML 团队中工作,在生产 ML 模型的同时努力管理技术债务,这一个适合你。
典型的工作流程
图片来源: 迈克尔·迈耶上 Flickr |找到归属许可 这里
这里有个前提:你是一名在初创公司/中小企业/企业工作的 ML/DL/AI 工程师/分析师/科学家。你的工作是从所有地方获取一堆随机数据,并产生价值。你是做什么的?您坐下来,以某种方式将数据传输到您的本地机器上,并且不可避免地要做一些类似以下的事情:
jupyter notebook
或者你可以去一个实验室,如果你喜欢并且你的团队的隐私规则允许的话。
下面是一个我以前看过很多次的故事——当然是伪代码。
import pandas **as** pd
import xyzlibraryforml***# CELL 1: Read***
df = pd.read_*("/path/to/file.*")
df.describe()*# INSERT HERE: a 100 more cells deleted and updated to explore data.****# CELL 2: Split***
train, eval = split_the_data() *# basic**# INSERT HERE: trying to figure out if the split worked****# CELL 3: Preprocess***
*# nice, oh lets normalize*
preprocess(train)
preprocess(eval)*# exploring preprocessed data, same drill as before****# CELL 4: Train***
model = some_obfuscated_library.fit(train, eval) *# not being petty* *# if youre lucky here, just look at accuracy. otherwise:****# CELL 5: Evaluate***
complicated_evaluation_methods(model)*# INSERT HERE: do this a 1000 times****# CELL 6: Export (i.e. pickle it)***
export_model()
你说完了,对吧?就是这样——嘣。测试集结果非常好。让我们把它交给运营部的人在生产中部署。午休和 Reddit 一整天!
好吧,我是不是太夸张了?是。对于一些企业来说,这是否非常接近事实?也是的。
那么,有什么问题呢?
问题是,上面的笔记本电脑是一个技术债务球,如果不及早剔除,它将继续增长。让我们来分析一下它出了什么问题:
没有朝着更大的方向前进
当您将可概括的逻辑放入无版本的、一次性的笔记本块中时,您的团队就无法利用它了。例如,从静态数据源加载/提取数据的逻辑。当然,现在使用pd.read_json
很容易,但是如果格式改变了会发生什么呢?更糟糕的是,如果数据增长并被分割成多个文件,会发生什么?更糟糕的是,如果它不再适合内存会发生什么?如果你的同事遇到同样的问题,会发生什么——她可能会经历同样的循环,而你甚至不知道这是一个已经解决的问题。当然,所有这些问题都有解决方案,但是你会一直在你的本地笔记本上解决它们吗?
答案很可能是否定的(除非你是网飞或者其他什么)。通常,合乎逻辑的做法是将加载提取到一个逻辑上独立的服务中。通过这种方式,您可以将实际的数据提取抽象出来,放到一个对每个人都透明的可维护层中。例如,这可能是某种形式的feature store
,它将组织中所有不同的数据流收集到一个点,然后团队中的每个人都可以在定义的 API 中使用它。
这同样适用于上述脚本的预处理、训练和评估部分。
在本地构建逻辑(因此一次又一次)
就像上面的例子一样,当您编写代码来探索数据时,您会生成大量的好东西——可视化、统计数据框架、经过清理和预处理的数据等等。Jupyter 笔记本执行的随机、任意顺序确保了实现这些工件的路径永远消失在被覆盖的局部变量和自发的内核重启中。更糟糕的是,这种逻辑在代码本身的深处嵌入了复杂的、容易被覆盖的配置——这使得重新创建工件变得更加困难。
听着,我明白——我一直都这么做。数据争论是一个随机的、痛苦的过程,而且会很混乱。但是建立一些框架来跟踪您的数据探索管道将会带来巨大的回报。类似于评论你的代码,跟踪的最大受益者将是你自己。此外,如果这些工件和问题的迷你答案对每个人都是自动透明和清晰的,您的团队将会更快,并避免多余的工作。
不拥有部署
这本笔记本的最后一部分可能是最令人沮丧的。我真的不相信写那个笔记本的人的工作会以导出 ops 的模型而结束。这没有任何意义。
首先,preprocessing_fn()
函数必须与它一起使用,否则 training-serve skew 将从一开始就破坏你的模型。第二,运营人员如何知道您在构建模型时采用了哪些假设?您是否要编写大量的文档,说明输入什么数据、应该如何预处理数据,以及在部署到端点时数据应该是什么形状?我的意思是,现在已经有了自动化的方法来实现这一点,所以拥有部署吧!
上述脚本中缺少的一个方面是忽略了对模型性能的度量。我认识的大多数数据科学家并不关心模型有多大,它为预测消耗了多少内存,以及它在部署中有多快/多高效。如果不满足最终应用程序的性能标准,模型就不会产生价值。同样,开发模型的人应该拥有其最终部署的所有权。
建议
解决上述问题的最简单的方法是开发一个框架,在这个框架中,ML 团队可以用可维护的、易于共享的代码来平衡一次性的探索性代码开发。如果您要这样做,您可能需要记住以下几点:
创建定义良好的接口(即分解成管道)
您的工作流的split
、transform
、train
、evaluate
、deploy
组件是逻辑上独立的实体/服务。从具体的实现中抽象出 ML 工作流的单个组件。这可以通过定义面向对象风格的实际接口来实现,或者简单地确保您的 repo 具有某种形式的结构,便于每个人参与和扩展。这不一定一开始就是火箭科学,但它会有巨大的帮助。
这就是 ML 管道的概念发挥作用的地方:管道是定义一系列数据处理任务的抽象表示。在pipelines
中思考将帮助你的团队在他们的工作流程中分离出逻辑实体,并让数据独立地流过它。这将不可避免地产生更健壮、可维护的代码库。此外,像这样定义 ML 管道可以确保您可以在新数据到来时自动对旧模型进行连续训练。但是,您还需要为此跟踪您的数据元数据(见下文)。
为你的 ML 元数据制定一个计划
你运行的每一个实验都会产生 ML 元数据:谁运行的,什么时候运行的,输入了什么数据,结果存储在哪里等等。请务必标出这些内容,并提供一种方便的方式来添加到该商店。重要的是要注意:我也不只是在谈论实验跟踪。有许多很棒的库可以帮助跟踪以模型为中心的元数据,例如度量等。然而,经常被忽视的是以数据为中心的元数据——尤其是当数据不断变化时。像数据版本控制、统计、可视化、随机分割时使用的种子之类的东西。应该有一种简单的方法来跟踪数据在开发过程中的各种路径。
确保您的工作负载可以在任何环境中运行
在一台机器上运行一个工作负载总是比在任意环境下运行相同的代码要容易。我知道 Docker 对于很多 ML 的人来说是无敌的,也是辛苦的,但是至少做一个requirements.txt
加一个__init__.py
!理想情况下,将您的代码容器化,并在某种形式的编排框架上运行实验。现在做这一步,当您扩展和自动化整个事情来处理更大的数据时,将会省去很多麻烦。
不要将部署与培训分开
这可能是迄今为止最没脑子的建议了。20 年前,端到端所有权导致了整个 DevOps 革命,这在 ML 开发中也没有消失。提供一个平滑的机制来将一个训练好的模型转移到一个端点,并且确保操作人员和你的 ML 开发人员坐在同一个房间里(并不总是这样)。制定流程,让每个人都了解生产的最终目标。尽可能实现自动化。
不要在可重复性和可追溯性上妥协
你知道当人们开始用 Python 编码,然后转向 C++或 Java 时,他们不理解像指针和静态类型这样的概念吗?他们认为:“给变量一个类型有什么用,我知道它是什么,为什么我被迫这么做?”很抱歉打断你,但是指针和静态类型有一个目的——了解它们可以保护你的代码免受你自己的错误,并确保高质量的健壮输出。终极灵活性可能是一件坏事,尤其是对于那些容易犯懒惰错误的开发人员(像我一样)。
在 Jupyter 笔记本中也发生了非常类似的事情——以任何顺序运行任何任意代码的自由带来了自由,但也让你失去了非常重要的可重复性和可追溯性的概念,这是任何健壮的、生产就绪的工程学科的两个基石。请至少确保您的笔记本是自上而下可执行的,并且是可重复的。杂乱无序的 Jupyter 笔记本应该受到像代码审查会议上这样的长篇大论的惩罚。
确保这两种特性的一种方法是从实现中提取代码的settings
。这就引出了我的下一个观点…
将配置与实施分开
将配置与实际代码实现分开绝对是一件痛苦的事情。然而,这是另一种“长期回报”的事情。我们在之前已经写过了,但是总结一下:分离你的配置允许你自动化重复的任务,增加结果的可预测性,并且确保可再现性。理想情况下,配置应该被视为代码、版本和维护。管理这一点的一个好方法是将代码写成管道——我已经写了很多关于管道的内容,并且在这篇 Neptune.ai 博客文章中受到了极大的启发。
结论
许多组织中的 ML 从业者都被强烈地激励着快速取胜以产生早期的结果。然而,这导致了累积的技术债务,随着时间的推移,最终会减慢团队的速度。解决方案是从一开始就遵循适当的软件工程原则,并依靠指南在快速结果和高质量软件开发之间取得平衡。
以上想法是我在过去 4 年中在生产中部署模型时学到的非常个人的经验。它们绝不是一个详尽的列表,欢迎您将它用作基准测试您的产品架构的样板,或者作为设计您自己的产品架构的蓝图。如果你正在寻找一个实用的教程
我们将这些因素作为我们开源 MLOps 框架 ZenML 的指导原则。所以在你从头开始之前,请在 GitHub 上查看 ZenML:https://github.com/zenml-io/zenml,如果你喜欢你所看到的,别忘了给我们一颗星!
避免数据科学项目的 4 大陷阱
原文:https://towardsdatascience.com/avoiding-the-4-major-pitfalls-of-data-science-projects-8132b295bcdb?source=collection_archive---------7-----------------------
从事数据科学项目,尤其是与新的利益相关方合作,可能会很有挑战性。学习如何避免主要的陷阱。
图片由风险化(经许可使用)
随着数据科学、机器学习和人工智能在商业领域的不断普及,公司正在试图利用这些技术解决新问题。作为一名数据科学家,你知道你接下来的项目很有可能会失败。如果机器学习只是你公司运营的一个小方面——主要产品中的一个功能或产生有价值的商业洞察力的一种方法,那就更是如此。在 Riskified ,机器学习是我们业务的核心,但牢记这些陷阱总是很重要的。
由于数据科学家方面的不专业,项目可能失败的原因数不胜数:选择偏差、目标泄露、数据漂移、p-hacking、过度拟合等等。然而,在本文中,我们将关注与业务协作相关的一些基本问题。
纳入数据科学与任何变更管理流程都是一样的,需要仔细考虑和规划才能做好。任何重大的变革过程都需要强大的成员联盟,包括创造愿景、推动愿景和消除障碍的倡导者。约翰·科特的八步流程是最经典的变革管理模型之一,它强调提前规划变革流程的重要性。让我们看看当关键的准备工作没有完成时会发生什么。希望下面的提示可以帮助你挽救你的数据科学项目,或者避免开始一个注定失败的项目。
错误数据
如果您是您所在组织(或之前从未使用过数据科学的业务部门)的第一位数据科学家,那么您很有可能错过了关键数据,或者数据质量不够好,无法开始工作。与数据工程师或数据库管理员讨论现有数据、获得对该数据的许可和访问权、探索该数据以检查其特性、空率、一致性、验证其回溯多远、预测标签的存在、该标签的准确性以及其他质量问题可能会花费大量时间。如果你的公司到目前为止做得很好,那些数据提供商不一定理解为什么他们必须满足关于数据质量的新的严格要求(“到目前为止一切都很好,不是吗?”).
对于您工作线之外的业务人员来说,在这段漫长的时间里似乎没有取得任何进展,因为这似乎是一个永无止境的数据清理过程。如果高级管理层不了解将数据置于最低工作条件下所需的大量准备工作,他们就不会有必要的耐心,也不会期望很快得到结果。在那些背负大量技术债务以快速前进的公司中,数据质量可能会更差,他们的耐心会更低,因为他们习惯于快速交付。
如果你处于这种棘手的情况,在对你的项目进展速度做出任何假设(或者项目是否可行)之前,获取数据并开始一些最小的探索是至关重要的。如果你是第一次想加入数据科学的利益相关者,提前做好数据准备是很重要的,否则可能会有一个非常沮丧的雇员,他可能会很快离开。
缺乏认同和信任
你公司的高级管理层很可能会收到大量承诺通过实施“人工智能”创造奇迹的信息你可能会发现一位孤独的高管决定冒险将机器学习引入他们的组织。关于人工智能实际上如何被利用,它将解决的商业问题,以及它可以带来的价值的细节将作为细节留给你去解决。虽然这可能行得通,但组织必须了解利用机器学习所需的准备工作量以及它擅长解决的问题类型。
如果组织没有准备好,你通常会看到整个公司对机器学习的支持有限(即,它是由高管自上而下驱动的),这意味着你可能会遇到中层管理利益相关者的障碍。从数据科学家的角度来看,它可能看起来有点像这样:你刚刚为一个不习惯使用机器学习的新利益相关者完成了一个项目。在最后一次会议中,你不会得到很多关于工作的问题或反馈。任何销售人员都知道,拒绝比得不到任何反馈更容易。经验较少的数据科学家可能会尝试证明他们的解决方案的价值。然而,当你到达这一点的时候,可能已经太晚了。你的利益相关者没有参与进来,也不会最终使用你的项目。
此外,许多公司并不是真正由数据驱动的。虽然每个公司都说他们的决策是由数据驱动的(在今天的商业环境中,不这样说实际上是一种亵渎),但许多公司实际上并不是这样运作的。在许多情况下,这可能是因为没有足够的数据。结果,他们没有提高他们的分析能力,公司文化可能不重视对新流程的系统测试。如果一个数据科学家(或者具体来说是一个决策科学家)提供了独特而关键的洞察力来对抗公司的部落知识,那么直觉很有可能会占上风。员工们只是不会对这种类型的工作感到足够舒服,如果它与他们所知道的有足够的不同,他们就不会接受它。
为了避免这种情况,了解谁是你的利益相关者并让他们参与整个过程是至关重要的。不要在几周的工作后拿出一个解决方案,然后期望他们只是接受它。通过经常让利益相关者参与进来,利用他们的专业知识,并允许他们塑造你的项目解决方案,你可以利用宜家效应——一旦利益相关者亲自投入时间,他们会更加重视项目。
不知道的利益相关者
有时,利益相关者对利用机器学习感兴趣,但不知道如何使用它。你可能真的有足够的参与度和相关级别的兴趣(包括高管买入和中层管理),但他们不确定到底会发生什么,也缺乏对机器学习背后过程的清晰理解。当数据科学家不断提到数据质量问题、缺少必需的工具和基础设施,或者在现有生产系统中部署他们的第一个模型时遇到困难时,他们可能期望立即得到结果,并变得不耐烦。
从数据科学家的角度来看,事情可能是这样的:你和一个新的利益相关者开始了一个项目,这个利益相关者几乎没有数据科学方面的经验。他们想利用“ML 魔力”,但很难定义他们的具体问题。你可能会感到有压力,开始探索数据,“看看你能发现什么。”虽然这可能有效,但应尽可能避免。
首先,确定您想要尝试和预测的具体指标——花在详细说明指标计算和完成定义上的每一分钟都是值得的。这也可以帮助你从一开始就设定期望——一些利益相关者可能期望从 ML 那里得到不可能的东西,在开始项目之前,最好把这一点提前说出来。你可以先随意探索这些数据,但是不要只是开始,看看你能做得有多好。重申任何研究项目固有的不可预测性也很重要。你没有考虑到的问题会突然出现,你期望的绩效可能无法实现。在承诺具体的绩效目标或交付日期时要非常谨慎。
随着项目的进展,在向前推进太远之前,不断地运行假设分析。例如,如果您已经从一个简单的基准模型开始,与涉众讨论准确性度量。模型已经好到有价值了吗?如果不是,这是否在正确的范围内?这种复杂性在生产中实现可行吗?还需要考虑哪些其他限制因素?
经常讨论这些问题是有好处的,尤其是当项目已经取得进展并且需要考虑新的信息时。
当利益相关者改变主意时
在某些情况下,利益相关者可能非常清楚他们的要求,而你在继续之前已经同意了所有的期望。由于数据科学项目可能需要几周(甚至几个月),利益相关者可能会改变他们的请求。这可能是由于以下原因造成的:
- 最初的请求不再相关。只要有可能,使用更快的增量交付成果(瀑布式敏捷)可以帮助减少这类问题。
- 原始任务的成功将项目推向不同的方向。例如,涉众最初可能要求一个非常准确的销售预测。虽然这听起来很简单,但解决方案可能涉及多个模型的集合,每个模型都有不同的参数和季节性。在您最终改进了模型以满足最初的阈值,并且它被业务所利用之后,涉众现在要求能够解释每个预测背后的基本原理。这可能是一个比涉众想象的要大得多的请求,这种必要性最好在项目开始时讨论,因为它可能会影响设计的解决方案的复杂性。
- 利益相关者会改变——不要假设每个人都会以同样的方式对待你的工作。一个新的利益相关者不太认同,在机器学习方面的经验有限,并且普遍持较高的怀疑态度,这可能会严重影响你的项目进展。同样,争取增量速赢以展示对业务的价值也很重要。比起继续投资一个没有明确结束日期的黑箱,给一条有价值的赛道开绿灯要容易得多。
作为一名真正的专业人士,你需要考虑利益相关者如何看待你的工作,权衡影响你工作的约束和限制。无论您是与新的利益相关方合作一个项目,还是刚刚在您的公司开始数据科学,都要提前计划几个步骤-管理预期,关注增量价值,并获得项目成功所需的认可。时间太少,工作太多,不能让一个运行良好的数据科学项目白白浪费掉。祝你好运!
如果你已经读到这里,你可能会喜欢我以前的博客:
</7-must-haves-in-your-data-science-cv-9316841aeb78> https://medium.com/riskified-technology/3-ways-to-break-into-data-science-6a7a8fd679b3
每个数据分析师都应该知道的出色 AWS-Quicksight 视觉效果
原文:https://towardsdatascience.com/awesome-aws-quicksight-visuals-every-data-analyst-should-know-e4e9302b2711?source=collection_archive---------9-----------------------
使用这些视觉效果创建引人入胜的仪表板
图片由 MBWA 公关在 Flickr 上发布
答几乎每个以分析数据为生的人都会使用这样或那样的可视化工具。有数百种可视化数据的工具。无论是在带有 Matplotlib、Plotly 和 Bokeh 等包的 Python 编程环境中,还是在带有 SAP Lumira、Tableau 甚至 Excel 等内置软件的环境中,我们拥有的工具都比我们可能使用的工具多。
那你怎么选择最好的呢?事实上,几乎所有这些都是非常好的实现。您的选择取决于您的用例。
到目前为止,我在大多数用例中使用 Tableau,因为在服务器上共享仪表板便于终端用户使用。但是当我们需要创建某些类型的视觉效果时,它却缺乏能力。例如,您将不得不经历一个乏味的仪式来创建甚至简单的流程图。祝你好运,记住最后所有的聚合和数据乘法。
在这种情况下,Plotly 当然会有所帮助,但是你必须忍受为每一个需要的可视化对象从头创建一个好的数据框架的痛苦。
我最近遇到的一个工具消除了上述几个限制。
它将众多可视化软件的精华结合到一个基于云的商业智能服务中。它叫做 Quicksight ,作为亚马逊网络服务(AWS)的一项服务提供。您可以在以下文档中了解更多信息:
亚马逊 QuickSight —商业智能服务—亚马逊网络服务
在 Quicksight 上工作了几天后,我发现那里有几个作为标准提供的可视化,否则在其他工具中需要花费很长时间才能构建。
对于不熟悉 AWS 和 Quicksight 的人来说,有大量的文档可供使用。如果您愿意,在我们进入视觉效果之前,您可以快速浏览一下如何在 Quicksight 中连接数据的概述:
使用新数据源创建数据集— Amazon QuickSight
在这篇文章中,我将带你浏览我非常喜欢在 Quicksight 中使用的 7 个视觉效果,这是我最喜欢的倒计时。我为什么喜欢他们?因为:
- 数据准备的简单性
- 提供给最终用户的直观性
- 使用频率(基于我的使用案例)
我将带您了解所需的基本数据结构以及结果可视化。有了这些视觉效果的知识和组合,你也可以创建引人入胜的仪表板!
7.瀑布图
当我们需要显示一段时间内值的累积增加或减少时,可以使用瀑布图。虽然有许多工具可以创建这些图表,但 Quicksight 提供了最简单的一种。考虑公司收入和费用的下列累积数据:
作者截图
你需要做的就是在 Quicksight 中导入 Excel 数据。数据导入后,从左下角的视觉类型选择区域选择瀑布图。
你会看到一个图表的空白区域和一个叫做油田井的区域。
创建瀑布图所需的油田井有:
- 种类
- 价值
- 分解(可选)
将字段列表中的类型和值列分别拖动到和字段井的类别和值中。
好了,图表准备好了!
作者截图
6.漏斗图
漏斗图基本上用于显示任何业务流程的流程,最常用于销售。因为。例如,在这些图表的帮助下,我们可以看到在流程的每个步骤中用户数量的下降(这给出了特有的漏斗形状)。
考虑以下图书销售过程的累积数据,从估计的市场规模到售出的总册数:
作者截图
将数据导入 Quicksight 后,从视觉类型部分选择漏斗图。所需的油田井有:
- 分组依据
- 价值
将字段列表中的图书销售和计数列拖至字段井的类别和值中。
作者截图
5.树形地图
在我们到目前为止经历了 2 个简单的图表之后,让我们走向更复杂和有趣的图表。一种这样的视觉类型是树形图,这是我在几个用例中使用的图表之一。它用于以嵌套矩形的形式表示分层数据。这种图表中的节点以大小和颜色两个维度进行分类,为我们提供了一个非常紧凑和数据丰富的可视化。
考虑以下由产品项目、数量和总价组成的虚拟数据:
作者截图
数据导入后,从视觉类型部分选择树形图。所需的油田井有:
- 分组依据
- 大小
- 颜色
将字段列表中的项目、数量、和价格栏分别拖动到字段井的分组依据、大小和颜色中。
作者截图
正如您所看到的,图中的每个图块根据数量和价格来量化数据中的给定项目,数量和价格分别用图块的大小和颜色来表示。当分类涉及两个维度时,这使得它成为一种非常方便的视觉类型。
4.热图
这是一种数据可视化技术,以颜色显示事件的大小。通常,颜色强度的变化用于向最终用户提供关于事件如何聚集的明显视觉提示。因此,热图的一个常见用途是可视化自然环境现象。此外,它还用于可视化流体流动动力学、表面变形等。
考虑到这一点,有什么数据比城市的温度数据更适合可视化为热图呢?在本例中,我从这里下载了柏林的天气数据,并做了一些数据工程处理,以获得日期、一天中的时间和温度(以摄氏度为单位)。因此,在 Quicksight 中导入的最终数据如下所示:
作者截图
数据导入后,从视觉类型部分选择热图。所需的油田井有:
- 行
- 列
- 价值观念
将字段列表中的日期、一天中的小时、和温度列分别拖动到字段井的行、列和值中。
作者截图
瞧啊。几秒钟之内的惊人热图。这绝对是我最喜欢的可视化类型之一,但是还有更多的。
3.地图上的点
如今这是一个相当普遍的可视化。它被用来可视化国家的人口,疫情疫情,空中交通路线,供应链,等等。很有可能,无论你在哪个行业工作,你都很可能会在你的公司仪表盘中使用或看到这种视觉类型。因此,将它作为标准的可视类型才是可行的。
在 Quicksight 中,这种实现称为地图上的点,它可以理解基于纬度、经度、城市名称甚至邮政编码的数据!(尽管根据您所在的地理位置,您可能需要等待它的上市,但它刚刚在欧洲上市)。
为了演示它是如何工作的,我使用了来自德国城市数据库的人口数据,我在这里找到了。
作者截图
导入数据后,从视觉类型部分选择地图上的点。所需的油田井有:
- 地理空间(纬度、经度、城市名称等。)
- 大小
- 颜色
将字段列表中的 lat & lng 列拖到地理空间中,并将人口拖到 Size 字段中。如果需要指示另一个参数,例如人口密度,您也可以使用颜色。
作者截图
现在你知道了。有一个惊人的地图可视化是如此容易!
2.词云
词云被用作文本数据的可视表示,其可以或可以不按照任何特定的顺序或次序。也是一个随着社交媒体和文本分析领域的兴起而变得非常普遍的图表。它们特别受欢迎,可以直观地显示所使用的词频,例如标签、关键词,甚至可以分析网页或书籍中的文本。
有许多在线工具可以免费构建单词云。但是 AWS 环境中的这种实现使它变得强大。您可以使用 python 分析数据,并创建输出数据集以便在 Quicksight 中导入。这为高度灵活的文本可视化提供了广泛的可能性!
为了在这里进行演示,我创建了一个虚拟数据集,其中包含来自一项调查的成员及其母语列表:
导入数据后,从视觉类型部分选择单词 Cloud。所需的油田井有:
- 分组依据
- 大小
将字段列表中的本地语言列拖入分组依据。它会根据计数自动生成云!如果数据的结构不同,字数在不同的列中,也可以使用大小指示器。
我唯一怀念的是没有一个色域,用不同的颜色显示不同的单词。这将使可视化更加吸引人(我真的希望在未来的更新中实现这一点)。
作者截图
1.桑基图
最后,我最喜欢使用的视觉类型,因为它灵活、直观。桑基图本质上是流程图,其中流程表示与流量(或速率,或流量中的任何其他度量)成比例。
这使得 Sankey 图成为业务运营中的能量流、材料流、网络、流程链等用例中的绝对宝藏。
到目前为止,它们缺乏普遍性的唯一障碍是缺少一个简单的实现。我们可以在舞台上做到,但只能用一千种迂回的方法。或者我们可以自己编写这样的代码。所有这些都可以通过迄今为止我在商业智能软件中发现的最简单的实现来避免。
考虑下面的数据(来自德国的能源流程图— 2018,我在这里找到了):
作者截图
所有你需要的是一个来源,目的地,和两者之间的流量。让我们看看这是如何工作的。
导入数据后,从视觉类型部分选择 Sankey 图。所需的油田井有:
- 来源
- 目的地
- 重量
将字段列表中的源、目的、和单位(千万亿焦耳)列分别拖到字段井中的源、目的和重量中。
几秒钟内,你就拥有了魔力!基于数据的流的可视化表示。实现会根据给定的数量自动调整自己,这意味着值中的任何错误都会使图表看起来有点笨拙(例如,如果流出的比流入的多)。
作者截图
其实现的简单性使它成为这个列表中最好的可视化工具!
这是 AWS Quicksight 中 7 种视觉类型的列表!有了这些以及更多提供的和持续升级的组合,我相信你已经可以成为一个令人惊叹的视觉故事讲述者了!你喜欢哪一个?是只有我,还是你也有一些经常使用的可视化类型?我肯定想知道和学习更多。欢迎在评论中告诉我!
真棒 PyTorch 闪电模板
原文:https://towardsdatascience.com/awesome-pytorch-lightning-template-485a75c2f47e?source=collection_archive---------13-----------------------
TLDR:py torch Lightning 模板,包含了很多特性。链接到谷歌实验室这里。
认知状态:这个模板是几周学习的结果,而不是多年的经验。把这当成你朋友的课堂笔记,而不是老师的讲义。为了让你知道我是多么的不合格和固执己见,只要看看我没能解决的问题列表就知道了。如果你知道如何解决它们,请告诉我。
可怕的闪电照片。Marc Szeglat 在 Unsplash 上拍摄的照片
你是否曾经困惑过 PyTorch 的最佳实践是什么?比如,什么时候把你的张量发给 GPU?或者什么时候打电话给 zero_grad?或者,您是否尝试过做一些新的事情,比如添加一个类似 SimCLR 的管道,并且因为写得太差而不得不重写大部分代码?又或许,你在想别人的管道是什么样的?他们的效率是 100%的吗?有哪些你一直缺失的简单小技巧和窍门?也许不是你,但我有。PyTorch 闪电 (PL)前来救援。它基本上是一个关于你的代码应该如何构造的模板。
PL 在他们的文档中有很多特性,比如:
- 测井
- 检测坡度
- 剖析器
- 等等。
他们还有很多模板,例如:
- 最简单的例子叫做对无聊模型进行调试
- 用于快速成型的划痕模型
- 基本例子像 MNIST
- 类似生成性对抗网络的高级例子
- 甚至更多的东西在 PL 螺栓 ( github )
问题是所有这些例子都很简单。这对于演示或作为模板来说非常好。但是缺少一个更完整的例子来展示所有这些特性是如何集成的。尤其是对于深度学习领域的第一个编码项目的人来说,这就是:
模板
点击此处链接至 Google Colab。
特征
记录
张量板 HPARAMS 选项卡。出于某种原因, hp_metric 不工作,我无法修复它 T_T(黑暗模式 ftw!).(图片作者)。
- 记录到 TensorBoard 和 stdout 用于冗余(这是我自己做的,^^).我还是不能什么都抄。一些信息只放入标准输出。这是一个问题,因为如果您使用超级计算集群,输出文件有难以描述的名称,这使得查找实验细节更加困难,特别是在遥远的未来。(我也在考虑登录到 WandB )。
- 正确使用 hp_metric 以便我们可以在 TensorBoard 中选择最佳的超参数(还没有运行 T_T。作为一个临时解决方案,它保存到一个. json 中,该文件将被加载到 pandas 数据帧中)。
显示最低验证的损失曲线。该图是诊断培训中的问题的一种方式。(图片作者)。
- 损失曲线(这是我自己做的^^).
- 整个脚本计时(如果你使用超级计算集群,用于估计 WALLTIME)(这是我自己做的,^^).
- 检查坡度规范以防止消失或爆炸坡度。
我们可以看到参数分布的演变(文字权重和偏差,而不是品牌)。(图片作者)。
- 将参数以直方图的形式记录到 TensorBoard(这是我自己做的,^^).记录单个参数可能不现实,每个时期会有数百万个参数。
- 打印照明模块的摘要。这是一个打印输出的例子,我不能重定向到 TensorBoard 文本。
- 记录系统(硬件和软件)信息。
你能在这幅图中找到这只虫子吗?很好!现在发现我的模板中的错误,需要帮助!玄阮在 Unsplash 上拍照。
排除故障
PyTorch 号侧写员报告。(图片作者)。
- 剖析器 ( PyTorch )找出哪些层/操作是一直在窃取你的时间和内存的瓶颈。请注意,这会减慢速度。差很多!因此,在进行超参数调整之前,请务必关闭此功能。
- 健全性检查是默认开启的功能。很高兴知道这个存在。(我是吃了苦头才知道的)
GPU 内存日志。为什么会涨?(图片作者)。
- 有两种方法来监控 GPU。第一个只是监控内存,而第二个可以监控多个统计数据。我的模板就用第一个。
- 有两种方法可以缩短纪元。第一种是通过限制批次数量。而第二个是 fast_dev_run ,它限制了后台的批处理数量。我的模板直接调用限制参数。
- 对数据子集进行模型过拟合
(错误:探查器与缩短时期冲突。)
想象一下这崎岖不平的地形。格拉汉姆·斯潘塞在 Unsplash 拍摄的照片。
最佳化
- 提前停止因为当模型已经收敛时,我们不要浪费资源。
- 渐变裁剪
- 说到优化器,我过去只是简单地使用 Adam ,使用 ReduceLROnPlateau ,然后就到此为止(我甚至不为 betas 优化)。但这让我晚上睡不着觉,因为我总是怀疑自己,怀疑自己是否错过了巨大的进步。我知道这是一个非常活跃的研究领域。但是另一种选择是优化器超参数的维数灾难。这就是 PL 拯救我的地方。现在,我可以简单地将 PL 视为一个行业标准,使用所有提供的优化工具,睡得稍微轻松一些。这里有两个工具:学习率查找器,和随机加权平均。
激活分析:MNIST MLP 隐藏层激活的前 2 个主成分。(图片作者)。
保存和加载重量
- 保存最佳模型和测试它。
- 一旦你完成了你的超参数搜索,你可能想要在会话结束后加载一个检查点来对最佳模型做类似残差分析或激活分析(看上面漂亮的图)。
- (跟踪训练期间激活如何变化可能也有帮助,但我没有在这个模板中实现这一点。)
超参数调谐:
- 在我的 Google Colab 模板中有一个网格搜索的例子。是的,我知道随机搜索更好,但这只是为了演示。
- 出于某种原因,我无法让 TensorBoard 上的 hp_metric 工作,所以我做了一个. json 来解决这个问题。还包括一个代码片段来聚合。来自不同实验运行的 json 文件。
- 我还需要一个超参数优化器库,实现良好的算法,从离线文件读取和写入(因为我正在使用 HPC)。目前为止最好的解决方案是 Optuna ,因为离线很容易并行化 。
从这里去哪里?
显然,我在谷歌上的模板还没有检查过。但是你可能想在 Bolts 中检查现有的模型,并为你自己的数据集制作你自己的 LightningDataModule 。祝你好运!
参考
所有的图片,除了标题中注明的,都是我的。
Awesome R Markdown Word 报表,带有以编程方式插入的标题、输出和交叉引用
原文:https://towardsdatascience.com/awesome-r-markdown-word-report-with-programmatically-inserted-headings-outputs-and-19ad0de29a22?source=collection_archive---------18-----------------------
如何在 Word 中自动生成报告,以便专注于解决具有挑战性的问题
Thomas de March in(pharm Alex 统计和数据科学高级经理)和 Milana Filatenkova(pharm Alex 统计和数据科学经理)
照片来自马丁·范登赫维尔在 Unsplash
什么是 R: R 语言被统计学家和数据挖掘者广泛用于开发数据分析软件。
什么是 R Markdown : R Markdown 是一个工具,旨在帮助使用 R 创建可再现的动态报告。R Markdown 文档是以 Markdown(一种易于编写的纯文本格式)编写的,包含大量嵌入式 R 代码。
为什么使用 R and R 降价:作为数据科学家,我们经常需要重复进行分析(例如:分析方法的验证)。自动化这样的例程可能是一种很好的方法,可以减少在执行大量重复任务时经常出现的人为错误的可能性,并将资源从枯燥的复制/粘贴类型的练习转移到具有挑战性的问题解决上。
本帖面向谁:本帖面向希望使用 R Markdown (Rmd)脚本创建 Word (docx)文档并希望以编程方式插入标题、输出和 Word 交叉引用的 R 用户。
不包括的内容:这篇文章不会介绍 R and R 降价。如果您刚刚开始使用这些工具,有许多优秀的教程可供参考。另外,安装 R 和 MS-Word 是继续本教程的先决条件。
当用 R 生成报告时,PDF 和 HTML 给出了更好的结果。但是,在职业语境中,Word 是无法避免的。
有几个包可以用来从 r 生成 Word 文档,最流行的是 rmarkdown 。Markdown 的美妙之处在于它使纯文本文档(代码)可读性更好,没有杂乱的标签。另一方面,缺点之一是 Word 的功能非常有限。例如,不能调整样式、添加表格和图表标题以及使用单词交叉引用。在其他旨在自动生成报告的软件包中,值得一提的是官员。这个软件包提供了许多在 rmarkdown 中没有的 Word 功能。但是,官码非常难读。在官里,单词交叉引用也不行。还值得一提的是,一些 R 包已经开发出来管理表格,数字编号和标题,如标题或预订。但是,这些软件包输出常规文本,无法生成动态标题和引用(即,您无法点击这些引用或生成图表目录)。后者带来了交叉引用的问题:当内容更新时,引用保持静态。
最后,让我们提一下最近令人敬畏的 officedown 包,它将一些 officer 特性引入 R Markdown 文档。 officedown 的一个关键特性是为引用和标题添加 Word 计算字段的选项。换句话说,这是第一个支持真正单词交叉引用的 R 包!
最后,关于 R 生成的输出(图、表……)在报告中的出现——使用 rmarkdown ,可以通过编程将它们插入 Word 报告中,这实际上是 rmarkdown 包的中心目的。但是,如果您事先不知道报告将包含多少表格、数字和章节,该怎么办呢?一个典型的例子是对多个属性执行重复分析的脚本或应用程序。让我们设想这样一种情况,当用户选择上传具有任意数量属性的数据,5、10、20、100……在这种情况下,为了以编程方式从 R 中插入标题和输出,解决方案是在 rmarkdown 中设置 chuck 选项‘results = " asis’”。该选项将使用循环的从 R 创建 R 降价代码。
那么,这篇文章的目的是什么呢?嗯,即使有可能以编程方式插入输出和标题,并通过 officedown 包获得正确的单词交叉引用,我也从未设法使这两者一起工作……当我试图在循环的中使用交叉引用时,它从未产生想要的输出(引用不起作用,图形重复……)。我猜这个问题会在 officedown、的未来版本中得到解决,但我就是等不及了。我需要为我的客户完成这项工作。然后,我花了很多时间在互联网上寻找解决办法,并提出了一些解决方案,最终完成了它!我并不认为我的方法是自动编译功能 Word 报告所独有的,当然还有其他方法可以达到同样的目的。这里的困难是文档的缺乏和许多与 Markdown 相关的 R 包的不成熟。这篇文章是我尝试与大家分享我的发现,这样你就不会迷失在无休止的试错过程中,试图从你的 Rmarkdown 中得到一个好的 Word 文档。
这是要点列表。
交叉引用由以下人员创建:
1.使用 run_autonum 函数创建书签
2.使用 block_caption 函数添加标题
3.文本中的引用是使用 run_reference 函数完成的
通过使用 result='asis' chunk 选项,以编程方式创建分析部分中的子部分。这个选项告诉 knitr 不要把文本输出打包在逐字的代码块中(就像普通的代码块一样),而是“按原样”处理,输出原始的减价内容。在这些类型的块中:
1.使用cat(' \ n # # heading name \ n ')创建标题。请注意' \n '是使其工作所必需的。
2.绘图输出为:打印(绘图)
3.必须使用 knit_print 和 cat 功能输出弹性工作台
4.标题( block_caption )和引用( run_reference )需要封装到 knit_print_block 函数中
下面是一个例子。请注意,下面的代码以及它生成的 Word 报告和所有必要的文件都可以在我的 Github 上找到:https://github.com/tdemarchin/AwesomeRmarkdownWordReport
结论
虽然直到最近,从 R 生成定性的 Word 报告仍然具有挑战性,但是已经开发了新的包,使得在业务环境中生成报告成为可能。本文中描述的方法证明了手工编写 R 输出的报告已经没有用武之地了。
例子
输出
自动生成 Word 报告的示例
代号
---
title: "Awesome Rmarkdown Word report with programmatically inserted headings, outputs and cross-references"
author: "Thomas de Marchin"
date: "17MAR2021"
output:
word_document:
reference_docx: "template.docx"
---```{r setup, include=FALSE}
# Let's setup a few things.rm(list=ls())
library(knitr)
library(officedown)
library(officer)
library(ggplot2)
library(tidyverse)
library(broom)
library(flextable)# set chunks defaults
knitr::opts_chunk$set(
echo = FALSE,
message = FALSE,
warning = FALSE
)# set flextable defaults
knitr::opts_chunk$set(echo = TRUE, fig.cap = TRUE)
set_flextable_defaults(
font.family = "Arial", font.size = 9,
theme_fun = "theme_vanilla",
big.mark="", table.layout="autofit")
# formatting properties for specific paragraphs
centeredP <- fp_par(text.align = "center")```# IntroductionThe aim of this document is to introduce a way to generate word reports from R using Rmarkdown with programmatically inserted headings, outputs and Word cross-references. See [https://towardsdatascience.com/awesome-r-markdown-word-report-with-programmatically-inserted-headings-outputs-and-19ad0de29a22](/awesome-r-markdown-word-report-with-programmatically-inserted-headings-outputs-and-19ad0de29a22) to understand the context of this example.# DataWe will use the built-in iris dataset as an example.
This dataset consists in Petal and Sepal width and length measurements for three iris species.
Table `r run_reference("summaryTable")` shows summary statistics.```{r data, echo = FALSE}
# this chunk is a normal chunk compared to the next one# create the bookmark for the summary table
tab_num <- run_autonum(seq_id = "Table", pre_label = "Table ", bkm = "summaryTable")
# add the caption
block_caption(label= "Summary table for the iris dataset",
style = "caption", autonum = tab_num)# create the summary table and output it with flextable()
summaryData <- iris %>% gather(value="value", key="Attribute", -Species) %>% group_by(Attribute, Species) %>% summarise(n=n(), mean=mean(value), sd=sd(value), min=min(value), max=max(value))
summaryData %>% flextable() %>% merge_v(j = "Attribute") %>% colformat_double(j=c("mean", "sd"), digits = 2)
```# Analysis```{r analysis, echo = FALSE, results = 'asis'}
# this chunk will programmatically generates Markdown code (results='asis')# split the data by specie to simulate different attributes to analyze, it is here 3 here but it could be any number.
data <- split(iris, iris$Species)
uniqueSpecies <- levels(iris$Species)# for loop
for(i in 1:length(uniqueSpecies)){
dataSubset <- data[[uniqueSpecies[i]]]
# print the heading
cat("\n##", uniqueSpecies[i], "\n")
# print an empty line
cat("\n <br> \n")
# print some text
cat("Figure ")
# reference the figure below (note the use of knit_print_run function in 'asis' chunks)
knit_print_run(run_reference(paste0("pData", uniqueSpecies[i])))
cat(" shows the relation between Sepal width and length.")
# plot the data
pData <- ggplot(aes(x=Sepal.Length, y=Sepal.Width), data=dataSubset) +
geom_point() + geom_smooth(method='lm', se=F) + labs(title=uniqueSpecies[i])
# output the plot (note the use of the print function in 'asis' chunks)
print(pData)
cat("\n") # sometimes you need to add this to make things work
# Add the figure numbering and caption (note the use of the knit_print_block function in 'asis' chunks)
fig_num <- run_autonum(seq_id = "Figure", pre_label = "Figure ", bkm = paste0("pData", uniqueSpecies[i]))
knit_print_block(block_caption(paste0("Scatter plot of Sepal Width vs Sepal Length for ", uniqueSpecies[i], ". Blue line is a linear regression."),
style = "caption", autonum = fig_num))
# print some text
cat("A linear regression was performed using Sepal.Length as the response and Sepal.Width as the explanatory variable. Table ")
knit_print_run(run_reference(paste0("tabRegression", uniqueSpecies[i])))
cat(" shows the parameters estimates and 95% Confidence intervals.")
cat("\n") # sometimes you need to add this to make things work
# do a regression generate the fit summary table
regression <- lm(Sepal.Length ~ Sepal.Width, data=dataSubset)
tabRegression <- tidy(regression)
tabRegression <- cbind(tabRegression, confint(regression, level=0.95))
# Add the table numbering and caption (note the use of the knit_print_block function in 'asis' chunks)
tab_num <- run_autonum(seq_id = "Table", pre_label = "Table ", bkm = paste0("tabRegression", uniqueSpecies[i]))
knit_print_block(block_caption(paste0("Parameters estimates of the fit for ", uniqueSpecies[i]),
style = "caption", autonum = tab_num))
# output the summary table (note the use of knit_print and cat functions in 'asis' chunks)
tabRegression %>% flextable() %>% knit_print() %>% cat()
cat('\n')
}# Add a page break
run_pagebreak()
```# Conclusion`r fpar(ftext("Congratulations!", fp_text(font.size = 12, bold = TRUE, color = "#C32900")), fp_p = fp_par(text.align = "center"))`
参考
https://R Markdown . R studio . com/
https://bookdown.org/yihui/bookdown/
https://ardata-fr.github.io/officeverse/
https://science loft . com/technical/programmably-create-new-headings-and-outputs-in-R Markdown/
https://www.r-bloggers.com/
解释 AWS 应用程序迁移服务架构
原文:https://towardsdatascience.com/aws-application-migration-service-architecture-explained-2947348ef194?source=collection_archive---------12-----------------------
了解流程
图片由杰洛特来自 Pixabay
AWS 应用程序迁移服务(AWS MGM)是一项提升和转移 AWS 服务,任何人都可以通过 AWS 管理控制台进行访问。在这篇文章中,我将回顾 AWS MGN 服务和网络架构。AWS MGM 是一种灵活、可靠、高度自动化的提升和移位解决方案。
塞缪尔·马丁斯的图片
您可以使用它来帮助简化、加快和降低将应用程序迁移到 AWS 的成本。您还可以使用 AWS NGN 将物理、虚拟或云服务迁移到 AWS,而不会出现兼容性问题、性能问题、中断或长时间切换窗口。您可以从运行受支持操作系统的任何源基础架构中迁移应用程序和数据库。这包括 Oracle 和 SQL server 等常见数据库、SAP 等任务关键型应用程序以及自主开发的应用程序。AWS MGN 支持最常见的 windows 和 Linux 操作系统,并在数据块级别持续复制它们的数据。
塞缪尔·马丁斯的图片
左侧是源环境。它可以包括物理、虚拟或云服务器的组合。在此示例中,源环境有两台服务器,其中两个磁盘连接到顶层服务器,三个磁盘连接到底层服务器。在右侧,您可以看到服务器将被迁移到的 AWS 区域。在本例中,已经定义了子网。
首先,在源服务器上安装 AWS 复制代理。代理可以以无人值守的方式安装,不需要重新启动。
塞缪尔·马丁斯的图片
安装时,代理会对使用 TLS 1.3 加密的 AWS MGM API 端点执行身份验证握手。这将向服务注册代理,而服务又会自动提供临时区域子网资源。
塞缪尔·马丁斯的图片
塞缪尔·马丁斯的图片
临时区域子网使用低成本计算和存储来保持源环境中的数据在 AWS 上同步。临时区域子网由以下资源组成:
- 复制服务器。这些是轻量级、Amazon elastic、云计算或 Amazon EC2 实例。
- 暂存卷。这些是低成本的亚马逊弹性块商店,或亚马逊 EBS 卷。
- 亚马逊 EBS 快照。这些是增量 EBS 快照。
对于复制的每个源磁盘,AWS MDN 都会在临时区域子网中创建一个大小相同的 EBS 卷,以便进行数据同步。在此示例中,五个复制源磁盘导致五个等效的 EBS 卷连接到登台区复制服务器。
塞缪尔·马丁斯的图片
安装代理并创建临时区域子网资源后,复制开始。数据经过加密,并直接从源服务器传输到复制服务器卷。用户控制复制路径,在复制路径中,他们可以使用专用连接选项,如 AWS direct connect 或 VPN。
塞缪尔·马丁斯的图片
该服务自动管理临时区域子网资源,根据并发复制的源服务器和磁盘按需扩展或缩减资源。因此,用户无需维护操作即可管理中转区子网。AWS MGN 服务器是短暂的资源,由服务不时自动轮换。
需要注意的重要信息包括:
- 默认情况下,复制服务器使用 T3.small Linux 实例,启用 T3 无限制定价。
- 一般经验是,一台复制服务器最多可以处理 15 个并发复制的磁盘。
- 默认情况下,数据在传输过程中使用 AES 256 位加密密钥进行压缩和加密。也可以在您的 AWS 区域使用 Amazon EBS 加密对其进行静态加密。
复制从初始同步开始。在初始同步期间,代理将源磁盘上的所有内容复制到分段区域子网中的 EBS 卷。同时,代理会在数据权限发生时跟踪并持续复制数据权限,并将数据异步复制到临时区域子网中的相关资源。初始同步完成后,连续复制将无限期继续。
安装代理并开始复制后,检查启动设置。启动设置是服务、特定配置和易于启动的模板的组合。启动设置定义了迁移实例的启动位置和方式,包括子网安全组、实例类型、卷类型和标记。配置启动设置后,等待初始同步完成。当源服务器被标记为可以测试时,您可以选择 test and cutover 按钮并启动实例。然后,AWS MGN 将发出一系列 API 调用来启动启动过程,并根据您配置的启动设置在 AWS 上自动启动实例。
在启动过程中,该服务会自动启动转换服务器。转换过程包括对驱动程序、网络和操作系统许可证的更改,以便实例可以在 AWS 上本地引导。
塞缪尔·马丁斯的图片
塞缪尔·马丁斯的图片
塞缪尔·马丁斯的图片
与复制服务器(只要复制处于活动状态,复制服务器就处于活动状态)不同,转换服务器仅在启动过程中出于转换服务器的特定目的而启动,然后立即终止。转换完成后,新的实例在 AWS 上启动并准备好使用。请注意,连接到已启动实例的卷代表启动时源服务器的状态。
塞缪尔·马丁斯的图片
启动后,新创建的卷不再与源服务器保持同步。对源服务器所做的任何更改仍然会由 AWS 复制代理不断复制到临时区域卷,但是这些更改不会应用到已启动的实例。每次启动新的测试或转换实例时,它都会反映从源服务器复制到临时区域子网的数据的最新状态。使用这种设计,您可以快速测试启动的实例,而不会中断源服务器或复制过程。您还能够按需启动源服务器的最新拷贝。为同一个源服务器启动新实例将自动清理并覆盖该服务器以前的副本(如果以前启动过的话)。这有助于最小化成本,并避免未使用资源的积累。
要准备运行 AWS MGN 的网络,请设置以下连接:
- 源服务器和 AWS MGN API 端点之间的连接。允许源服务器上的 AWS 复制代理和 AWS MGN 端点之间的端口 443 上的连接。这种连接的目的是身份验证、配置和监控。对于 AWS 复制代理安装,并且只要源服务器正在复制,就必须有这种连接。因为这是一个 HTTPS 连接,所以可以使用源服务器上的标准设置通过 web 代理进行重定向。您还需要允许源服务器和 S3 之间的连接。设置此连接,以便 AWS 复制代理可以从 S3 存储桶中检索必要的软件组件。
塞缪尔·马丁斯的图片
塞缪尔·马丁斯的图片
- 源服务器和临时区域子网之间的连接。AWS 复制代理将数据从源服务器直接发送到端口 1500 上的复制服务器。因此,必须允许通过端口 1500 进行连接,以实现连续数据复制。
塞缪尔·马丁斯的图片
- 中转区之外的连接。在临时区域子网中启动的 AWS MGN 复制服务器和转换服务器必须在端口 443 上持续与 AWS MGM 端点通信,以便进行身份验证、配置和监控。
塞缪尔·马丁斯的图片
只要复制正在进行,这种连接就必须存在。此外,必须允许与 S3 的连接。当复制或转换服务器启动时,它连接到 S3 存储桶以下载软件和配置文件。
塞缪尔·马丁斯的图片
- 最后,复制服务器的角色之一是发出 API 调用,以便在复制期间拍摄分段 EBS 卷的快照。为此,还必须在端口 443 上建立到 EC2 API 端点的连接。
塞缪尔·马丁斯的图片
感谢您花时间来看这个架构。我希望这有助于你理解 AWS MGN,因为它帮助了我,因为我正在研究它。
AWS 认证机器学习—专业
原文:https://towardsdatascience.com/aws-certified-machine-learning-specialty-97eacbd1a0fe?source=collection_archive---------11-----------------------
关于如何准备和通过考试的提示和建议
穆罕默德·阿里·皮克在 Unsplash 上拍摄的照片
相信很多人都听说过 AWS 的这个认证。我了解到 AWS 认证机器学习—专业 是一个艰难的认证考试,我非常同意。
我上周 10 月 1 日参加了这次考试。在阅读和回答前几个考试问题时,我立即意识到这并不容易通过。但是不要沮丧,因为如果你付出努力并做好充分的准备,你一定能做到。相信自己,努力是有回报的。
经历并通过这次考试对我来说是一次伟大的学习之旅。
我很高兴我设法达到了这个里程碑。既满足又有收获。
关于考试
“AWS 认证机器学习-专业认证面向从事开发或数据科学工作的个人。它验证候选人针对给定业务问题设计、实施、部署和维护机器学习(ML)解决方案的能力”——来源: AWS
考试时间为 3 小时。总共有 65 个问题,这意味着您平均有大约 2.7 分钟的时间来回答每个问题。你会得到多项选择或多项回答问题。
这 65 个问题中,有 15 个是未评分的问题。AWS 使用它们来评估候选人的表现,以及将来是否将它们作为评分问题。可惜的是,考试上不公开。
结果以 100 到 1,000 的标度分数报告。最低及格分数是 750 分。
这项考试的费用是 300 美元。如果您之前通过了 AWS 认证考试,您可以从您的 AWS 认证帐户获得 50%的折扣券。
测试域
有 4 个领域的候选人将被测试。下图总结了这些领域及其权重。
AWS 认证机器学习的测试领域-专业。作者图片
对于每个领域的完整细节和范围,您可以从 AWS 下载的考试指南中阅读它们。下面是一个简短的总结:
- 数据工程 —了解存储介质(S3、EFS 等)、数据摄取(Kinesis 等)、数据转换(ETL、Glue、EMR、AWS Batch、Lambda)
- 探索性数据分析—涵盖数据准备(地面实况、牧马人等)、特征提取和工程(OHE、PCA 等)、分析和可视化(相关性、残差图等)
- 建模 —了解与监督/非监督学习、迁移学习、强化学习、类型(分类、回归、预测、聚类、推荐)、优化、超参数、正则化(L1/L2、辍学)、模型评估(欠拟合/过拟合)、度量(准确度、精确度、召回率、RMSE、F1 评分、AUC-ROC)、混淆矩阵等相关的各种算法。
- 机器学习实现&操作 —监控和日志(CloudTrail、CloudWatch)、ML & AI 服务(Lex、understand、Transcribe、Rekognition、Textract 等)、IAM、安全、带 API 网关的端点、批量转换、A/B 测试、BYOC、物联网 Greengrass、SageMaker Neo、增强 AI 等。
学习选项
考试前你可以选择很多学习方法。我已经在下图中列出了可用的可能性。
AWS 认证机器学习的学习选项-专业。作者图片
根据你的经验和知识水平,你可能需要也可能不需要全部。我将在下一节解释每一个问题。
📑 1.AWS 示例问题
首先,我会推荐你从 AWS 下载样题。它由 10 个带答案的问题组成。还提供了每个答案背后的解释和理由。
试着不看答案回答这些问题。然后,对照提供的答案检查您的答案。这会让你感觉到问题的难度。它还能让你大致判断自己的状况,你是否做得很好,或者需要进一步的培训和学习。
💡 2.机器学习认证课程
如果你觉得你需要更多的培训和学习,你可以在 Udemy,Whizlabs,A Cloud Guru 等网站上找到几个 AWS 机器学习认证课程。
我参加了钱德拉·林根的 Udemy 课程 AWS 认证机器学习专业(MLS-C01) 。这是一门 AWS SageMaker 实践课程,包括模拟测试。除此之外,它还涵盖了许多基本的机器学习概念和重要的算法。
我对这门课程的质量印象深刻。我特别喜欢展示具体概念或实现的许多动手实验和用例。讲师还积极维护和更新课程材料。我实际上在今年 3 月下旬完成了课程,但我推迟了参加考试的计划。当我在 9 月份再次浏览该课程时,我惊讶地发现增加了新的主题,我发现这些主题都是相关和有用的。
根据学生们的说法,这位老师反应很快,很有帮助。甚至还有有组织的团体直播问答环节。简而言之,这是一门不容错过的精彩课程。
📚 3.AWS 资源和文档
您可以从 AWS 找到许多辅助学习材料和资源。AWS 为其所有服务和产品维护大量文档。我提供以下所有主要链接。
AWS 上的机器学习
这是 AWS 机器学习的主页,它包含了 AWS 人工智能服务、ML 服务、框架、基础设施、用例解决方案、博客、学习资源、客户故事等的所有链接。
AWS 文档
在这里,您可以找到用户指南、开发人员指南、API 参考、教程和项目、SDK 和工具包。
亚马逊 SageMaker 开发者指南特别有用。它包含关于 SageMaker 特性的非常详细的信息和教程,以及所有内置的算法。
AWS 白皮书
- 公共部门组织的机器学习最佳实践【新】
- 机器学习镜头——AWS 架构良好的框架
- 增强人工智能:人类和机器的力量
亚马逊 SageMaker 技术深潜系列
这个亚马逊 SageMaker 技术深潜系列在 YouTube 上有 16 个视频。了解如何使用 Amazon SageMaker 构建、培训、调整、部署和优化模型。
AWS 数字培训
通过 AWS 数字培训在自己的时间和计划内学习。从学习库中浏览并选择相关课程。
AWS 产品&技术常见问题解答
FAQ 是浏览特定产品或服务要点和功能的另一个很好的资源。
仅列举几个:亚马逊 SageMaker FAQ 、亚马逊 S3 FAQ 、 AWS Glue FAQ 、亚马逊 Kinesis 数据流 FAQ 、亚马逊 Kinesis 数据消防软管 FAQ 、 AWS 湖泊形成 FAQ 、亚马逊领悟 FAQ 、亚马逊 Rekognition FAQ 等。
💻 4.实践实验和练习
如果您没有使用 AWS 的经验,请尝试在 AWS 中进行动手实验,例如数据准备和转换,以及构建、调优和部署模型。
这一步是可选的,但它有一个额外的好处,可以帮助您熟悉 AWS 服务和产品,以及它们如何相互集成。
注册一个 AWS 帐户,你将能够探索、体验和开始构建 AWS。新账户持有人可以享受免费等级下的大部分产品和服务。查看 AWS 的免费等级产品,它们可以归入以下三个类别之一:短期免费试用、 12 个月免费或永远免费。
下面提供了示例笔记本、SDK 和 AWS CLI 的链接:
- 亚马逊 SageMaker 示例笔记本
- 亚马逊 SageMaker Python SDK 是一个开源库,用于在亚马逊 SageMaker 上训练和部署机器学习模型。
- Boto3 是用于 Python 的 AWS SDK,您可以使用它来创建、配置和管理 AWS 服务。
- AWS 命令行界面 (AWS CLI)是一个统一的工具,为与亚马逊 Web 服务的所有部分进行交互提供了一致的界面。
如果你感兴趣,你可以点击下面的链接来阅读我写的关于如何用 Amazon SageMaker 因子分解机构建和训练推荐引擎的文章。
https://pub.towardsai.net/building-a-product-recommendation-engine-with-aws-sagemaker-321a0e7c7f7b
📝记下自己的笔记
由于这次考试的覆盖范围非常广,我建议你在浏览学习资料的时候自己记笔记。
作者图片
开始时你可能觉得没有必要。随着你的进步,深入研究章节,查阅成堆的文献和阅读材料,你很快就会发现自己被信息过载所淹没,无法记住你之前学过的特征或东西。
照片由sumet B在 Unsplash 上拍摄
如果你正在上课,它们通常会附带 PowerPoint 幻灯片。但是,自己做笔记会帮助你更好地记住对你来说重要的关键点和概念,并在期末复习时快速回忆起相关的想法和观点。
5.最后的准备
在你完成所有必要的主题和材料后,这个 考试准备:AWS 认证的机器学习-专业 课程是一个必须要做的。这是一门 4.5 小时的免费在线电子学习课程。你将学到宝贵的关键应试策略和翻译试题的技巧。
当面对你没有信心的问题时,你需要知道如何解决它们。你将学会识别重要的关键词,消除不相关或干扰选项,缩小到可能的答案选择。
因为大多数问题都是基于场景的,所以你也需要学会注意问题中指定的要求。例如,您可能会被要求"选择最具成本效益的解决方案"或"选择管理和开销最小的 解决方案"。
本课程将贯穿 4 个高级考试领域。对于每个领域,您将回答几个测验问题。
最后你还会发现另外 35 个学习问题。这些问题模拟了实际考试中出现的问题类型。但是,我还是觉得实际考试题的难度水平更高。但我也收到了一些简单的问题。
绿色变色龙在 Unsplash 上拍摄的照片
在最后阶段,尽可能多地做模拟测试或模拟问题。你需要这样做,以便熟悉问题的风格,并在规定的时间内自如地回答问题。
即使你觉得你已经准备好了,也要这样做。通常你会惊讶地发现,仍然有一两个问题需要你进一步研究才能找到答案!
同样,你可以在像 Udemy 这样的平台上找到练习测试,或者参加 AWS 的官方练习考试,费用是 40 美元。如果您之前已经通过了 AWS 认证考试,您可以利用您的 AWS 认证帐户中的练习考试优惠券免费参加 AWS 练习考试。
更新:AWS 取消了免费实践考试的福利。2021 年 11 月 19 日起,每个人都可以在 上免费访问 AWS 认证官方练习题集【AWS 技能构建器 】。如果您获得了免费的模拟考试作为考试福利,您仍然可以在 2022 年 6 月 30 日之前通过 PSI 申请、激活和使用模拟考试。
给你一点奖励,考试中出现的题目。这些是我能回忆起的一些零碎的东西,但并不详尽。作者图片
摘要
在这篇文章中,我简要介绍了 AWS 认证机器学习专业的考试形式和考试领域。
我介绍了在参加考试之前可以选择的各种学习方法。我还提供了各种 AWS 资源和文档的链接摘要,可以帮助您准备考试。
我建议你在浏览学习资料的时候自己做笔记。当你做最后几轮复习时,这些笔记会很方便。
为了做好最后准备,请参加 AWS 考试准备课程。学习应试策略至关重要。尽可能多地尝试模拟测试。
祝你学习愉快,考试顺利!
如果你喜欢我的帖子,别忘了点击 关注 和 订阅 获取邮件通知。
可选地,你也可以 注册 成为媒体会员,以获得媒体上每个故事的全部访问权限。
有兴趣了解变形金刚吗?我有以下的帖子给你。
AWS EC2 实例类型说明
原文:https://towardsdatascience.com/aws-ec2-instance-types-a29385912222?source=collection_archive---------26-----------------------
了解 Amazon Web Services 上不同类型的 EC2 实例
Marcus Dall Col 在 Unsplash 上的照片
介绍
亚马逊弹性计算云(EC2)是一种提供云计算能力的 web 服务,是亚马逊 Web 服务中最受欢迎的产品之一。该服务允许用户租用虚拟机,在虚拟驱动器上存储数据,在不同的机器上分配负载,以及扩展服务。
AWS 提供了不同类型的 EC2 实例类型,这些实例类型经过了优化,以适应几种不同的用例。每种实例类型都提供了不同的内存、CPU、存储和网络组合,可以在不同的环境中使用,以适应特定的使用情形。
在今天的文章中,我们将讨论四种最基本的 EC2 实例类型,即通用、计算优化、内存优化和存储优化。此外,我们将给出每个实例类型最适合的几个示例用例。
通用
通用实例提供了计算、内存和网络资源的平衡,并且大多适用于各种不同的工作负载,例如代码库或 web 服务器。
计算优化
计算优化实例用于需要高性能处理能力的计算密集型任务。一些可能受益于计算优化实例的用例包括
- 科学建模和机器学习工作流
- 高性能计算(HPC)
- 批处理工作负载
- 高性能 web 服务器
内存优化
内存优化实例适用于需要快速性能的工作负载,以便处理内存中的大型数据集。受益于内存优化实例的一些用例包括:
- 关系和非关系数据库
- 内存数据库
- 对大量数据执行实时处理的任务
存储优化
最后,存储优化实例专为存储密集型任务而设计,这些任务需要对本地存储上的大型数据集进行高顺序读写访问。这些实例经过优化,能够为运行于其上的应用提供低延迟操作。受益于存储优化实例的几个使用案例是
- 关系数据库和 NoSQL 数据库
- 数据仓库应用
- 分布式文件系统
- 内存数据库的缓存
最后的想法
在今天的文章中,我们讨论了 Amazon Web Services 中提供的不同 EC2 实例类型。关于具体实例的更多细节,您可以参考 AWS 产品的相关章节。
EC2 有大量不同的 EC2 实例,有时在亚马逊网站上比较它们可能会很耗时。以下网站为比较 EC2 实例指标和定价提供了一种非常直观的方式,请务必查看。
成为会员 阅读媒介上的每一个故事。你的会员费直接支持我和你看的其他作家。你也可以在媒体上看到所有的故事。
https://gmyrianthous.medium.com/membership
你可能也会喜欢
面向机器学习工程师的 AWS
原文:https://towardsdatascience.com/aws-for-machine-learning-engineers-47e50a3b8015?source=collection_archive---------18-----------------------
探索 AWS 提供的一些关键服务,以解决数据驱动的挑战。
亚历克斯·库利科夫在 Unsplash 上的照片
介绍
随着越来越多的公司决定将内部数据中心转移到云提供商,过去几年中技术的一个关键趋势是对云计算的需求不断增长。2020 年,云计算市场规模相当于 3714 亿美元,预计到 2025 年将达到约 8321 亿美元[1]。截至 2021 年,按市场份额计算,AWS 目前是全球领先的云提供商[2]。
我最近完成了 AWS 机器学习专业考试(图 1),因此,我决定总结一个数据科学家在从事 AWS 项目时可能会用到的关键服务。
图 1: AWS ML 考试完成推文(图片由作者提供)。
如果您有兴趣了解关于云计算基础的更多信息,可以在我之前的文章“数据科学家的云基础”中找到更多信息。
AWS 服务
AWS 提供了 3 个不同的抽象级别,您可以使用它们来创建机器学习解决方案:人工智能(AI)服务、ML 服务、ML 框架和基础设施。
人工智能服务
在这个层面上,我们可以找到所有专注于易用性和快速上市的 AWS 人工智能服务。这些服务完全由 AWS 管理,只需对已经由 AWS 预训练的高性能模型进行 API 调用,就可以为您的产品添加机器学习功能。通过这种方式,任何人都可以利用人工智能服务,即使没有任何 ML 方面的经验。人工智能服务的一些例子是:
- Amazon understand:是一种自然语言处理(NLP)服务,旨在分析大量非结构化文本数据(例如,识别语言、文本中的关键事实、整体情感等。)
- Amazon Polly: 是一个支持深度学习的文本到语音服务,可用于创建基于语音的应用程序。
- Amazon transcripte:是语音转文本服务,用于将音频文件转换为文本文件。这种服务能够为批处理和实时流数据提供可靠的性能。
- 亚马逊翻译:是基于深度学习的语言翻译服务。
- Amazon Rekognition: 是一项旨在从图像和视频中获得洞察力的服务(例如,对象/人物检测、内容审核等)。).
- Amazon Personalize: 是一个推荐系统,旨在根据用户交互轻松提供实时产品排名、定制营销和推荐。
下面是一个简单的例子,展示了开始使用 Amazon Rekognition 是多么容易(图 2)。
图 2:亚马逊 Rekognition 演示(图片由作者提供)。
ML 服务
ML Services 专注于为数据科学家和研究人员提供托管资源和服务,以便他们能够创建和部署机器学习模型,而不必花费太多时间来建立支持他们模型的架构。ML 服务的一些例子是:
- 亚马逊 SageMaker: 是一个完全托管的服务,旨在覆盖整个机器学习工作流程,从数据准备到部署和监控(图 3)。Amazon Sagemaker 中一些最有趣的选项有: Data Wrangler (一个基于 GUI 的数据准备工具),一个内置的功能库, Autopilot (AWS 自动 ML 服务), Pipelines (用于编排自动化工作流)等。如果您有兴趣了解有关 Sagemaker 及其功能的更多信息,请点击链接。
- 亚马逊 SageMaker 地面真相:是一项服务,旨在为机器学习任务创建数据集标签。使用这项服务,可以选择人工智能驱动的自动标签工具,或者将您的数据发送给人工劳动力进行人工标签。此外,还可以让服务自动标记它具有高可信度的实例,并将剩余的实例发送给人工(从而节省时间和成本)。目前,Ground Truth 能够支持不同类型的数据,如文本、图像和视频。
- 亚马逊 SageMaker Neo: 一旦经过训练,就可以在任何地方(在云端或物联网边缘设备上)部署机器学习模型。SageMaker Neo 通过采用在任何主要的 ML 框架(如 Keras、PyTorch、、ONNX )中训练的模型,然后将其转换为优化的二进制表示,从而减少用于对模型进行推理的内存量,从而使这一点成为可能。
- 亚马逊增强人工智能:是一项服务,旨在创建生产 ML 模型,使人类保持在循环中。对于一些应用,如金融或医学,ML 模型做出的预测可能非常重要,并具有长期的影响。使用增强的人工智能,我们可以创建工作流,使人类有可能检查模型预测,并在必要时改变它们,以便向模型提供反馈(用于潜在的重新训练),同时提高性能。
图 3:亚马逊 Sagemaker 仪表盘(图片由作者提供)。
ML 框架和基础设施
该级别旨在使机器学习专家能够使用传统的开源框架(如 PyTorch、TensorFlow 和 AWS 上的 Apache MXNet)创建他们的模型。AWS 提供了不同的机器映像,旨在运行高性能的机器学习工作流,如深度学习 AMI 和深度学习容器(它们都带有已经安装的不同 ML 框架)。这样,ML 从业者就不必再担心与库依赖和有限计算能力的冲突了。
结论
总体而言,AWS 提供了一套令人印象深刻的服务,可用于在分析生命周期的任何阶段使用数据(例如,数据接收、数据存储、数据处理、数据分析等)。如果你有兴趣了解更多关于其他人工智能云提供商服务的信息,比如微软 Azure,更多信息可以在我之前的文章“人工智能驱动的微软工具简介”中找到。
联系人
如果你想了解我最新的文章和项目,请在 Medium 上关注我,并订阅我的邮件列表。以下是我的一些联系人详细信息:
- 领英
- 个人网站
- 中等轮廓
- GitHub
- 卡格尔
文献学
[1]环球新闻网,研究和市场。访问:https://www . globe news wire . com/news-release/2020/08/21/2081841/0/en/Cloud-Computing-Industry-to-Grow-from-37140 亿-in-2020-to-83210 亿-by-2025-at-a-a-of-17-5 . html
[2] Statista,亚马逊引领着价值 1500 亿美元的云市场。访问:https://www . statista . com/chart/18819/world wide-market-share-of-leading-cloud-infra structure-service-providers/
AWS Lambda 是 SQS 和 Kinesis 之间的纽带
原文:https://towardsdatascience.com/aws-lambda-as-a-link-between-sqs-and-kinesis-a39cb6e4f762?source=collection_archive---------16-----------------------
使用 Lambda 作为桥梁,使数据从帐户 X 中的 SQS 队列流向帐户 Y 中的 Kinesis 数据流
照片由卡尔焊接在 Unsplash 上
让我们看一下这里使用的不同的 AWS 服务。
AWS 简单队列服务 : 简单队列服务(SQS)是一个托管的分布式队列服务,允许在应用程序或服务之间发送和接收消息[并可选地持久化]。
AWS Kinesis 数据流 : AWS 以 Kinesis 数据流的形式提供数据流服务,可用于实时收集数据并提供给下游消费者进行进一步处理。
AWS Lambda:Lambda 是一种无服务器计算服务,可用于执行一段代码,该代码在其他 AWS 服务的指定触发下处理数据。
AWS 身份&访问管理 : 身份&访问管理(IAM)服务使用户能够根据组或用户或角色以及附加到它们的策略使用权限来访问各种 AWS 服务。
问题陈述
在最近的一个项目中,我正在开发一个能够产生用户行为事件的产品,比如页面访问、点击流、播放的录音等。为了获取这些数据进行分析,我们使用特定的 API 订阅了相应的事件,这些 API 将这些事件发送到它在 AWS 服务帐户 X 中创建的相应的 SQS 队列,该帐户的 id 为 000000000000。这里的问题是让数据流向我们团队可以访问的 id 为 1111111111111 的帐户 Y。
我们怎样才能越过接收存在于另一个账户中的数据的障碍呢?
解决方案
首先,让我们看一下解决方案架构。
解决方案架构
本质上,需要在帐户 Y 中创建一个交叉帐户角色,并附加一组策略。角色为crossaccount_sqs_lambda_role
的 sqs_to_kinesis lambda 应该能够轮询(读取)和删除帐户 x 中 sqs 队列的消息。此外,该角色应该能够写入帐户 y 中的 kinesis 数据流
第一步:创建跨账户角色,附加需要的策略
在账户 Y 中,创建了一个 IAM 角色,名为“crossaccount_sqs_lambda_role”,我们用 ARN arn:aws:iam::111111111111:role/crossaccount_sqs_lambda_role
来说吧。该角色附加了一个自定义策略:
- CustomLambdaAccess(内联策略):该策略是 AWSLambdaFullAccess 和 AWSLambdaSQSQueueExecution 角色的变体的组合。而且,该策略包括了 Kinesis 定义的所有可以在所需的 Kinesis 流上执行的动作(这里是 PageVisitEventStream&clicked eventstream)。
注意:您可以在资源字段下添加所需的流 arn。此外,如果使用的 Lambda 位于 VPC 中,则必须提供 EC2 网络接口权限。
步骤 2:向 SQS 队列添加权限
假设 PageVisitEvent 队列 URL 为https://sqs.us-east-1.amazonaws.com/000000000000/PageVisitEventQueue
,ClickedEvent 队列 URL 为https://sqs.us-east-1.amazonaws.com/000000000000/ClickedEventQueue
。
具有跨帐户角色的服务应该能够执行ReceiveMessage
、DeleteMessage
和GetQueueAttributes
动作,因此,权限应该被添加到指定主体(这里是帐户 Y 的帐户 id)的队列中。
在账户 X 中,
- 在 AWS CLI 上执行以下命令:
$ aws sqs add-permission --queue-url https://sqs.us-east-1.amazonaws.com/000000000000/PageVisitEventQueue --label AllowedSQSPermissions --aws-account-ids "111111111111" --actions ReceiveMessage DeleteMessage GetQueueAttributes$ aws sqs add-permission --queue-url https://sqs.us-east-1.amazonaws.com/000000000000/ClickedEventQueue --label AllowedSQSPermissions --aws-account-ids "111111111111" --actions ReceiveMessage DeleteMessage GetQueueAttributes
https://docs.aws.amazon.com/cli/latest/reference/sqs/add-permission.html
- 现在,在 AWS 控制台中,打开 PageVisitEvent SQS 队列。转到 Permissions 选项卡并编辑策略,以便我们创建的特定 IAM 角色可以访问队列,而不是整个帐户,即将主体从
arn:aws:iam::111111111111:root
更改为arn:aws:iam::111111111111:role/crossaccount_sqs_lambda_role
。
访问策略的 YAML 应该如下所示:
步骤 3:创建运动流
在账户 Y 中,创建 Kinesis 数据流,您将能够从账户 x 中各自的 SQS 队列映射到这些数据流
在 AWS CLI 上执行以下命令:
$ aws kinesis create-stream --stream-name PageVisitEventStream --shard-count 1$ aws kinesis create-stream --stream-name ClickedEventStream --shard-count 1
类似地,可以根据您的要求创建其他流。
https://docs.aws.amazon.com/cli/latest/reference/kinesis/create-stream.html
除了这些流之外,还要创建一个 DLQ 流(在步骤 4 中提供了理由):
$ aws kinesis create-stream --stream-name DLQStream --shard-count 1
步骤 4:创建和部署 Lambda 函数
首先,在您的本地系统中,创建一个名为sqs_to_kinesis_mapping.json
的 JSON 文件,其中 SQS 队列的 ARN 将被映射到帐户 y 中的 Kinesis 流名称。将来,可能会有许多这样的事件被摄取,因此将它分离到一个配置文件中是一个更好的选择。
接下来,创建一个名为lambda_function.py
的 python 文件,内容如下:
让我解释一下代码中发生了什么。
首先,读取包含 SQS 队列到 Kinesis 流映射的 JSON 文件。接下来,为每个 SQS 队列 ARN 创建一个字典kinesis_records_all
,该包括一个Records
关键字,该关键字包含将被转储到相应的StreamName
中的字典列表。从event
字典中Records
键的每个记录中,提取所需的信息,这些信息是要推送到 Kinesis 流的实际数据。
每个 SQS 队列都可以配置一个死信队列(DLQ ),它本身就是一个接收在处理时导致异常/错误的消息的队列。不是维护必须在账户 X 中创建的单独的 DLQ,而是将所有不一致的消息作为一个整体来消费,并将它们推送到账户 y 中的动态流 DLQStream。这样做是为了避免关于维护来自账户 X 的 DLQ 的额外的复杂性层。可以在 DLQStream 上设置一个 CloudWatch 警报(请参考解决方案架构图),如果 GetRecords。记录度量值增加到某个阈值以上。此外,DLQStream 中的记录可以通过 Kinesis Firehose/Lambda/Spark 结构化流应用程序转储到 S3,以发现消息未在 Lambda 中得到处理的原因。这也确保了记录出现在 DLQStream 中的唯一原因是 Lambda 捕获的来自源(即 SQS 队列)的记录的格式不同于在其中执行的数据提取过程。
接下来,使用以下命令压缩这两个文件以创建一个 sqs_to_kinesis.zip 文件:
$ zip sqs_to_kinesis.zip lambda_function.py sqs_to_kinesis_mapping.json
在帐户 Y 中创建 Lambda 并部署它。
$ aws lambda create-function --function-name sqs_to_kinesis --zip-file fileb://sqs_to_kinesis.zip --handler lambda_function.lambda_handler --runtime python3.8 --role arn:aws:iam::111111111111:role/crossaccount_sqs_lambda_role
步骤 5:向 Lambda 添加触发器
当消息在源 SQS 队列中可用时,必须调用 Lambda 代码。为此,必须在 SQS 队列和 sqs_to_kinesis lambda 之间创建事件源映射。为此,在账户 Y 中的,执行以下命令:
*$ aws lambda create-event-source-mapping --event-source-arn arn:aws:sqs:us-east-1:000000000000:PageVisitEventQueue --function-name arn:aws:lambda:us-east-1:111111111111:function:sqs_to_kinesis$ aws lambda create-event-source-mapping --event-source-arn arn:aws:sqs:us-east-1:000000000000:ClickedEventQueue --function-name arn:aws:lambda:us-east-1:111111111111:function:sqs_to_kinesis*
*https://docs.aws.amazon.com/lambda/latest/dg/invocation-eventsourcemapping.html
这将使 Lambda 函数能够轮询任何消息的 SQS 队列。一旦消息存在于队列中,lambda 就会对其进行处理,并根据代码是否能够成功提取所需的数据将消息发送到相应的流,然后从相应的 SQS 队列中将其删除。
步骤 6:在 CloudWatch 中为 Lambda 设置日志保留期
由于日志是在 Lambda 中打印的,因此必须为日志组设置一个保留期,以便在一段特定的时间后,将早于指定保留期的日志丢弃。这避免了日志占用大量的存储空间,尤其是当 Lambda 处理的事件数量很大时。
为此,在帐户 Y 中执行此命令 :
$ aws logs put-retention-policy --log-group-name /aws/lambda/sqs_to_kinesis --retention-in-days 7
或者,
- 转到帐户 Y 的 AWS 控制台
- 打开云观察
- 在导航窗格中选择日志组
- 搜索/aws/lambda/sqs_to_kinesis 日志组并单击它
- 转到操作下拉菜单→编辑保留设置。将保留期设置为 7 天(或根据需要)。
步骤 7:在 DLQStream 的 GetRecords 上添加 CloudWatch Alarm。记录指标
为了获得关于出现在 DLQStream 中的记录的通知,可以在 GetRecords 上创建一个 CloudWatch 警报。记录指标,每当最小(或根据您的要求的任何其他统计)记录数超过给定时间段的阈值时,将发送电子邮件。您可以转到 AWS 控制台,按如下方式进行设置。
CloudWatch 警报设置
接下来,您可以配置 SNS,以便在指标值超出给定阈值时接收通知。
[根据您的要求]步骤 8:从 Kinesis 流中消耗数据
有几种方法可以从 Kinesis 流中获取数据,根据您的需求,可以选择其中的任何一种:
- 使用 AWS Lambda 读取记录并转储到 AWS S3
- 使用消防软管将记录直接转储到 S3 自动气象站
- 开发一个 Spark 流应用程序,使记录可以从 Kinesis Stream 实时传输到 datalake。
- 其他方法可以在这里找到:
使用这种架构向前发展
如果将来对相同格式的事件有任何接收请求,可以通过实现以下步骤来使用该体系结构:
- 首先,执行步骤 2,将所需的权限添加到帐户 X 中的 SQS 队列
- 接下来,执行步骤 3,这将在帐户 Y 中创建一个新的 Kinesis 数据流
- 通过添加一个新条目来更新
sqs_to_kinesis_mapping.json
,该条目以 SQS 队列 ARN 为键,以 Kinesis 数据流名称为值。将更改部署到sqs_to_kinesis
lambda。 - 在 SQS 队列和 lambda 之间创建一个事件源映射(步骤 5)
就是这样!*
包装它
通过这篇博客,我们了解了如何在 AWS 上设置 Lambda 函数来获取跨帐户数据,以及各种其他服务,使模型能够轻松机动化。
我希望记录我在这个项目中获得的知识能让你在这种情况下占据优势。
干杯!
AWS Lambda 与雪花的集成
原文:https://towardsdatascience.com/aws-lambda-integration-with-snowflake-426debc9ec3a?source=collection_archive---------15-----------------------
图为泰根·罗杰在 Unsplash
在 lambda 中执行 python 代码作为雪花中的外部函数
最近,我和 Supreeth Chandrashekar 合作了一项任务,我们希望对存储在雪花中的一些数据进行多重推理。我们利用外部函数触发 lambda,lambda 反过来从 AWS Sagemaker 端点(服务于不同的模型)获得推断。在这篇博客中,我们将讨论如何从雪花中调用 lambda。
解决方案概述
作者图片
工艺流程
- 雪花用户承担目标帐户中的角色
- 它使用角色调用 API 网关(API 网关资源策略只允许上述角色调用 POST 方法)
- API 网关将有效负载传递给 lambda
- Lambda 处理数据并将响应返回给 API Gateway
- API 网关向雪花发送回响应
AWS 设置
我的角色将由雪花承担
只需创建一个没有权限的空角色。我们稍后将添加跨帐户信任。
λ函数
创建一个 lambda 函数,它将响应 API 网关。使用下面的代码。这里要注意的重要事情是事件结构和响应结构。
雪花以 list 的形式发送事件,list 以 JSON 格式封装在名为data
的 key 中。它期望响应对象包含一个statusCode
键和一个带有 JSON 值的data
键。
API 网关
使用具有 lambda 代理集成的 POST 方法创建 API 网关。使用我们在上一步中创建的 Lambda ARN。在“方法请求”中添加 IAM 授权。
资源政策
替换以下 JSON 中的相关字段后,为 API 添加相同的资源策略。
最后,在 lambda 控制台中,您应该观察 API 触发的 Lambda 函数。
雪花设置
API 集成
我们在雪花中创建了一个 API 集成。该集成将创建一个用户,并允许该用户承担我们在 AWS 设置步骤 1 中创建的角色。此外,它记录了我们在 API 网关中创建的 API 的执行端点。
外部函数
我们通过使用上一步中创建的集成来创建一个外部函数。使用以下代码进行集成和外部函数创建。
一旦创建了集成。描述集成。您将得到与下图类似的结果。
作者图片
记下describe integration
命令输出的API _ AWS _ IAM _ USER _ ARN&API _ AWS _ EXTERNAL _ ID。在下面的策略中替换它,然后将它作为信任策略添加到开始时创建的“承担角色”中。
为了测试端到端功能,在雪花中运行该函数,您应该会看到 lambda 的响应。
添加从雪花内部执行 python 代码的功能,提供了雪花和云系统之间更好的集成。我们可以插入这些函数,并从雪花内部触发外部流程。
注意:lambda 上有 6MB 有效载荷的限制,所以来自雪花的触发不能太大。
快乐融入!!
AWS re:invent 2021 AI &机器学习发布会:你应该知道的 7 件事
原文:https://towardsdatascience.com/aws-re-invent-2021-ai-machine-learning-launches-7-things-you-should-know-18c6c06fa982?source=collection_archive---------10-----------------------
你需要的唯一 re:invent AI/ML 发布摘要
作者插图
这是一年中最美好的时光——对云中的机器学习来说。AWS 本周在 re:invent 2021 上宣布了几项令人兴奋的人工智能和机器学习服务。在这篇文章中,我将为你逐个服务地分解所有的 ML 美味。我将所有有趣的人工智能/人工智能发布归类为 7 种不同的人工智能用例,因此您可以挑选与您的兴趣最相关的部分:
- ML 适合所有人
- ML 培训
- 最大似然推理
- ML 和数据科学工作流
- ML 数据处理和标记
- ML 硬件
- 面向非开发人员的 ML
听起来不错?我们开始吧!
1。每个人的 ML
亚马逊 SageMaker 工作室实验室
什么事?
亚马逊 SageMaker Studio Lab 是一项免费托管的 JupyterLab 服务,在这里您可以运行您的机器学习(ML)项目,而不需要 AWS 帐户、信用卡或云配置技能。你没看错,我说的是免费。如果您是开发人员、数据科学家、学生或初涉 ML 和数据科学的人,您将需要访问 CPU 和 GPU 计算资源。SageMaker Studio Lab 已经为您准备好了,只需创建一个帐户,您就可以访问云中的免费 ML 开发环境。就这么简单。
它是如何工作的?
你可以选择纯 CPU 或 CPU+GPU 后端。如果您选择纯 CPU 后端,您将获得 12 小时的计算时间,这对于 Pandas 的大量数据预处理和 sci-kit learn 或 XGBoost 的经典 ML 算法训练来说已经足够了。对于深度学习训练,选择 GPU 后端获得 4 小时的计算时间,这对于在较小的数据集上训练或微调模型来说足够了。达到开始新会话的时间限制后,您可以立即重新启动 Studio lab 项目。您的数据(包括训练检查点)将在会话之间保持不变。
GPU 支持是由英伟达 T4 GPU,我也会在亚马逊 EC2 G4 实例中找到。作者图片
是给谁的?你应该什么时候使用它?
像许多人一样,我在用学生预算购买的笔记本电脑上训练了我的第一个 ML 模型,并很快意识到我需要访问 GPU 来训练更复杂的深度学习模型。Studio Lab 是任何想要快速、轻松、无痛地访问机器学习计算资源的人。你可以使用 Studio Lab 来完成你的学校作业,参加 Kaggle 竞赛或者做 ML 研究。就我个人而言,我将首先使用 Studio Lab 制作模型原型,然后将其转移到 Amazon SageMaker 来运行更大规模的实验或在更大的数据集上进行训练。
AWS DeepRacer 学生& AWS AI & ML 奖学金项目
这是什么?
本次发布包括两个部分:
- 新的 DeepRacer 学生服务和 DeepRacer 学生联盟竞赛
- 为参加 DeepRacer 学生联盟的学生提供奖学金计划
AWS DeepRacer Student 是一项面向全球 16 岁以上高中和高等教育入学学生的新服务。申请人可以访问 50 小时的 AWS AI/ML 内容,并接受 10 小时的模型培训,以及每月 5 GB 的存储空间,以参加 AWS DeepRacer 学生联盟。
AWS 推出了 AWS AI & ML 奖学金计划,以帮助代表性不足和服务不足的高中和大学学生学习机器学习概念,并为他们在 AI/ML 领域的职业生涯做好准备。AWS AI & ML 奖学金计划每年为 2000 名学生提供 Udacity“用 Python 进行 AI 编程”纳米学位计划的奖学金。完成第一个纳米学位的前 500 名学生将有资格参加专门为 AWS AI & ML 奖学金获得者策划的第二个纳米学位项目。
它是如何工作的?
每个学生都可以注册并参与 AWS DeepRacer 学生计划,开始在排行榜中竞争。不需要 AWS 帐户。参加奖学金计划是可选的。要获得奖学金,您必须成功完成所有 AWS DeepRacer 学生学习模块,并在所有课程测验中取得至少 80%的分数,在学生联盟中驾驶 DeepRacer 赛车达到一定的单圈成绩,并提交一篇论文。奖学金获得者还可以从 Udacity 讲师那里获得长达 85 小时的辅导和指导。前往 http://student.deepracer.com/的开始吧!
是给谁的?
如果你是一名面临经济困难的学生,那么这个项目适合你。如果你是一名 16 岁以上的学生,自认为在技术领域服务不足或代表性不足,目前正在就读高中或全球认可的本科课程。你可能是科技行业中代表性不足的群体的一员,包括女性、残疾人、LGBTQ+人群以及有色人种。
2。ML 培训
亚马逊 SageMaker 培训编译器
是什么?
SageMaker Training 编译器是一款针对机器学习模型的优化编译器,旨在加快训练速度。它通过分析模型的计算图和寻找更好地利用 GPU 资源的机会来加速模型训练。最终结果是,您可以在不对培训脚本进行任何代码更改的情况下获得性能改进。
它是如何工作的?
模型的计算图提供了许多简化的机会。例如,当您在没有训练编译器的 GPU 上训练您的模型时,您的模型的计算图中的操作将作为单独的 GPU 内核函数调用来执行。这增加了每次额外内核调用的函数调用开销。优化编译器可以识别这种低效,因为它可以查看完整的图形,而不是框架解释器会看到的独立函数。然后,编译器可以融合或组合运算符,从而减少 GPU 上的内核函数调用。编译器还可以查看整个图形,以便在内存规划和张量布局转换方面做出更好的决策,从而进一步加快训练速度。
作者图片
是给谁的?你应该什么时候使用它?
如果你正在训练深度学习模型,你将受益于 SageMaker 训练编译器。在发布时支持的模型很少,包括大量的 HuggingFace 模型,并且您可以在不做任何代码更改的情况下获得一些免费的加速。编译模型的想法绝对不是新的,有几个模型编译器用于推理部署,如 SageMaker Neo、TVM 和 NVIDIA TensorRT。这是因为仅针对前向传递执行图形优化相对简单。在训练期间,你有向前传递和向后传递,这使得编译器的工作更加困难。我很高兴在 SageMaker 中看到训练编译器支持,并期待今天在 HuggingFace 模型上使用它,我将密切关注它将来支持的其他模型。
在 re:invent 2021 上还有其他与硬件培训相关的发布,我将在下面一个名为“ML 硬件”的专门章节中进行介绍。现在,让我们继续讨论 ML 推理服务的发布。
3.最大似然推理
亚马逊 SageMaker 无服务器推理[预览]
什么事?
Amazon SageMaker 无服务器推理是一个模型托管功能,允许您部署端点进行推理,根据流量自动启动和扩展计算资源。使用 SageMaker 无服务器推理,您不必管理实例类型,只需为预测请求和处理这些请求所花费的时间付费。
它是如何工作的?
如果您在 AWS 上使用其他无服务器服务,如 Lambda、Fargate、SQS 等,那么您应该可以在使用无服务器推理时获得类似的好处。借助无服务器部署,您无需根据需求和流量供应、管理或扩展 Amazon EC2 实例。SageMaker 无服务器推理将为您完成所有这些工作,使部署和扩展 ML 推理模型变得更加容易。
作者图片
是给谁的?你应该什么时候使用它?
如果您已经在使用 SageMaker 来托管推理端点,那么只需更新您的端点配置,就可以很容易地从实时端点切换到无服务器端点。如果您预计您的流量在本质上是零星的,例如在一天的不同时间请求的数量是可变的,并且您没有严格的响应延迟要求,那么您应该从 SageMaker 无服务器推断开始。如果无服务器推理端点处于空闲状态,它将经历一个冷启动期,因此,如果您有一个延迟关键型应用程序,在任何时间点都不能容忍更低的延迟,您应该切换到实时端点,这些端点由您选择的专用 ml CPU 或 GPU 实例类型支持。对于其他一切,无服务器推理是一个显而易见的选择。
亚马逊 SageMaker 推理推荐器
什么事?
Amazon SageMaker 推理推荐器加快了为您的模型部署找到正确的计算实例类型的过程,以最低的成本为您提供最高的性能。SageMaker 推理推荐器通过自动运行性能基准测试和跨 SageMaker ML 实例调优模型性能来实现实例类型发现过程的自动化。
它是如何工作的?
SageMaker 支持超过 60 种实例类型和数量,选择合适的实例来满足您的部署目标可能会很耗时。您可以使用 SageMaker 推理推荐程序来运行默认的推荐作业,或者在一组选定的实例上指定自定义性能基准,以模拟您的生产部署的性能。您可能有一个目标吞吐量、延迟,并且您可以指定这些以及一个示例负载来运行测试。这个过程通常需要几个小时或更长时间,这取决于模型和自定义选项,结果可以在 SageMaker Studio 中查看,或在 Studio notebook 中使用 Pandas 等流行的库进行分析。
推理推荐器希望您的模型被打包到模型注册中心。通过创建模型包组来注册模型的好处是,您可以包含额外的元数据,例如服务容器、模型域(计算机视觉、NLP 等。)、任务(分类、回归等。)、框架(TensorFlow、Pytorch)、框架版本样本有效载荷等。一旦模型被注册,推理推荐器将处理剩下的。
基准测试完成后,您可以查看结果,并从延迟、吞吐量、成本、计算使用和内存使用等多个方面评估不同端点配置的利弊。
作者图片
是给谁的?你应该什么时候使用它?
如果您目前有生产中的模型,您可能已经手动对多个 CPU 和 GPU 实例大小进行了基准测试,以确定满足您的目标延迟和吞吐量要求的正确实例,并计算每个实例上的部署成本,以选择最符合您预算的性能实例类型。如果这个人是你,那么亚马逊 SageMaker 推理推荐器将通过自动化过程为你节省几天甚至几周的时间。如果这个人不是你,那你也没必要变成那个人。使用亚马逊 SageMaker 推理推荐器,节省自己宝贵的时间。
4.ML 和数据科学工作流
Amazon SageMaker Studio 与 Amazon EMR 的集成
什么事?
Amazon SageMaker Studio 引入了与 Amazon EMR 的深度集成,使您不仅可以查看现有的 EMR 集群,还可以创建、监控和调试运行在 EMR 上的 Spark 作业,而无需离开您的 SageMaker Studio 界面。通过这种集成,您可以在 SageMaker Studio 界面中启动 Amazon EMR 集群,使用 SageMaker spark 库执行数据预处理,然后在 SageMaker 中训练和托管您的模型。在一个 SageMaker Studio 用户界面下,您得到的是端到端的数据预处理到部署工作流。
它是如何工作的?
典型的设置是使用 AWS 服务目录来定义和推出预配置的模板,允许 SageMaker Studio 用户直接从 Studio 创建 EMR 集群。在这个通常由 DevOps 管理员或才华横溢的数据科学家执行的初始设置过程之后,您的 Studio 环境就可以创建 EMR 集群,连接到它,使用 Spark UI 监控和调试 Spark 作业。要运行 Spark 作业,您可以使用 Sparkmagic,它允许您在 Jupyter Notebook 中针对您在 Studio 中创建的远程 EMR 集群运行 Spark 代码。Sparkmagic 还创建了一个自动 SparkContext 和 HiveContext。
作者图片
使用完集群后,您还可以在 Studio 界面中终止它。
是给谁的?你应该什么时候使用它?
如果你是一名数据工程师或数据科学家,使用运行在亚马逊 EMR 上的 Apache Spark、Hive 或 Presto 来做数据准备,并且还需要在亚马逊 SageMaker 中开发模型、训练、调优和部署它们,那么 SageMaker Studio 和亚马逊 EMR 之间的这种集成将使你的生活变得容易得多。我认为这离理想的完全集成的开发环境更近了一步,无论您是执行数据预处理还是模型部署,您都不必离开这个环境。
5.ML 数据标记
亚马逊 SageMaker 地面真相加
是什么?
Amazon SageMaker Ground Truth Plus 是一项数据标注服务,它使用 AWS 管理的工作人员来提供高质量的标注,而无需您构建标注应用程序和管理标注工作人员。启动 Amazon SageMaker Ground Truth Plus 项目将使您与 AWS 团队保持联系,他们将与您一起了解您的用例、标签量和时间线要求。在项目批准时,您的数据集将由训练有素的 AWS 管理的工作人员使用已经可用的 SageMaker Ground Truth 功能进行标记。这意味着您不必与多家贴标供应商合作或在内部建立贴标团队,您可以仅在需要对数据进行贴标时使用 Ground Truth Plus 服务,从而解放您的数据科学家和 ML 专家的时间,让他们专注于模型开发和部署。
它是如何工作的?
作为 SageMaker Ground Truth Plus 的用户,您负责定义您的项目目标并提供数据集,输出是您的 S3 桶中的高质量数据标签,您可以使用 Amazon SageMaker 等服务来构建、训练和部署机器学习(ML)模型。在幕后,SageMaker Ground Truth Plus 结合了 ML 辅助预标记、人工专家标记和 ML 辅助验证人工标签,以检测人工错误和低质量标签。SageMaker Ground Truth Plus 还为您提供了一个了解质量控制数据标签操作的窗口。您可以监控进度,在仪表盘上查看标注指标,并对输出数据集提供反馈。
作者图片
是给谁的?你应该什么时候使用它?
SageMaker Ground Truth Plus 适用于贵组织中负责生产 ML 团队使用的高质量标注数据集的人员。此人是数据领域和业务问题方面的专家,需要一个端到端的标签解决方案。在较小的团队或组织中,这可能是数据科学家,或者在较大的团队或组织中,这可能是专门的数据运营经理。无论您的角色是什么,您都不希望管理一年中不断变化的标签需求的标签工作人员,而是希望及时向您的 AI/ML 团队交付高质量的标签数据。
6.ML 硬件
由 AWS Graviton2 处理器支持的 Amazon EC2 G5g 实例
什么事?
Amazon EC2 G5g 是目前 AWS 上广泛可用的 GPU 实例列表中的最新成员。G5g 是第一个将 NVIDIA GPU 与 AWS Graviton2 CPU 配对的实例。
作者图片
是给谁的?你应该什么时候使用它?
EC2 G5g 实例是一个经济高效的机器学习推理部署选项,是基于英特尔 CPU 的 EC2 G4 和 EC2 G5 的替代方案。NVIDIA 在 AWS Marketplace 上提供深度学习亚马逊机器映像,它预配置了所有必要的 NVIDIA 驱动程序、库和依赖项,以便在 EC2 G5g 上运行支持 Arm 的软件。
亚马逊 EC2 Trn1 实例[预览]
这是什么?
亚马逊 EC2 Trn1 实例由 AWS Trainium 提供支持,这是一款由 AWS 设计的高性能 ML 训练芯片,用于加速训练工作量。Trn1 实例是首批网络吞吐量高达 800 Gbps 的 EC2 实例,是基于 GPU 的 EC2 实例的网络吞吐量的两倍。它们还支持加速器之间的超高速互连,以在云中提供最快的 ML 训练。
是给谁的?你应该什么时候使用它?
EC2 Trn1 基于 AWS Trainium 加速器,这是继 NVIDIA GPUs 和英特尔 Habana Gaudi 之后,AWS 上用于 ML 培训的第三种加速器类型。如果您现在正在使用 GPU,并且正在突破 P4d.24xlarge GPU 实例的极限,那么 Trn1 应该会在它退出预览时引起您的注意。Trn1 也是第二个包含 AWS 设计的芯片的实例类型,第一个是 Inf1 实例,带有为推理而设计的推理加速器。要在 Inf1 上加速您的模型,您需要使用 AWS Neuron SDK,而同一 SDK 也不支持用于训练工作流的 Trn1 实例。
总的来说,我很高兴看到这么多的加速器选择 ML 从业者。当它变得可用时,我很兴奋地测试它,你可以打赌,在它可用后不久,我将为你准备一个深入的博客帖子。
7.面向非开发人员的 ML
亚马逊 SageMaker 画布
什么事?
亚马逊 SageMaker Canvas 提供了一个可视化的点击界面,无需编写任何代码就可以创建机器学习模型并生成预测。它的 UI 为您提供了访问数据集、创建连接、选择目标变量列的选项。然后,它会自动训练多个模型,并让您直观地分析模型性能,生成预测。
它是如何工作的?
Canvas 支持从亚马逊 S3 或本地上传的 CSV 文件类型。您还可以从 Amazon Redshift 或 SnowFlake 导入,并选择执行连接和 SQL 查询,以便更好地控制导入过程。导入数据集后,您可以使用左连接、右连接、内连接和外连接来组合数据集。当您对数据集满意时,可以选择要预测的目标列。SageMaker Canvas 将自动确定 type 问题类型—二元或多类分类或回归。当你开始训练时,它将建立多达 250 个模型,并选择一个表现最好的。最佳是主观的,所以你可以预览模型,看看它的估计准确性,并使用它来生成新数据集的预测。
注:作为一名 ML 教育者和实践者,我有责任告诉你负责任地使用你训练过的模型。模型可能有偏差,数据集也可能有偏差。引用著名统计学家乔治·博克斯的话“所有的模型都是错的,有些是有用的”。不管训练模型有多容易,都要对它们的有用性做出最佳判断。
作者图片
是给谁的?你应该什么时候使用它?
读完这篇文章后,如果你的第一反应是测试 SageMaker Training 编译器,那么可以肯定 SageMaker Canvas 不适合你。SageMaker Canvas 可以简化数据分析和其他面向统计的工作角色的模型开发,这些工作角色需要构建预测模型,但不一定具备 python 编码或使用 SageMaker Studio 的技能。如果您具有解释数据集、理解数据分布和数据不平衡、识别好的和差的数据集以及缺失数据如何影响预测的技能,SageMaker Canvas 可以填补模型开发空白,因此您可以专注于成为数据和领域专家。
回复:cap
我发现这是 AI/ML 发布以来最激动人心的发明之一,原因如下。
我们得到了一个使用 SageMaker Canvas 非常简单的服务,我们得到了一个免费的服务,每个人都可以使用,包括 SageMaker Studio Lab 的学生。我们获得了一项服务,专家数据科学家可以依靠这项服务来加快 SageMaker 训练编译器的训练速度,我们还获得了一项服务来帮助数据科学家找出最佳实例来托管他们的 SageMaker 推理推荐器模型。我们得到了一个服务来托管模型,而不需要使用 SageMaker 无服务器推理来管理实例。我们为数据标注项目经理提供了一项服务,通过 SageMaker Ground Truth Plus 获得高质量的标注数据集。最后,我们用 Trn1 和 G5g 获得了新的训练和推理加速器,这意味着开发者有了更多的选择。我们为每个人提供人工智能/人工智能服务!
- ML for everyone: 亚马逊 SageMaker 工作室实验室,AWS DeepRacer 学生& AWS AI & ML 奖学金项目
- ML 训练:亚马逊 SageMaker 训练编译器
- ML 推理:亚马逊 SageMaker 无服务器推理,亚马逊 SageMaker 推理推荐器
- ML 和数据科学工作流程: Amazon SageMaker Studio 与 Amazon EMR 的集成
- ML 数据处理和标注:亚马逊 SageMaker Ground Truth Plus
- ML 硬件:亚马逊 EC2 G5g,亚马逊 EC2 Trn1
- 面向非开发者的 ML:亚马逊 SageMaker Canvas
所有的东西都在这里了!如果你喜欢阅读这份总结,请随时在 medium、 twitter 和 LinkedIn 上关注我。在接下来的几周里,我将会忙于对这些服务进行更深入的研究,你不会想错过的。下一篇博文再见!
AWS SageMaker
原文:https://towardsdatascience.com/aws-sagemaker-db5451e02a79?source=collection_archive---------8-----------------------
在 Amazon SageMaker 上构建、训练和部署一个 ML 模型
亚历克斯·库利科夫在 Unsplash 上的照片
让我们从简单简短的 SageMaker 介绍开始,理解我们正在使用的是什么,稍后我们将深入 ML 教程!
什么是 AWS SageMaker?
亚马逊 SageMaker 是一个云机器学习平台{就像你的 jupyter 笔记本环境一样:),但在云上}帮助用户在生产就绪的托管环境中构建、培训、调整和部署机器学习模型。
使用 AWS SageMaker 的一些好处
- 高度可扩展
- 快速训练
- 保持正常运行时间—过程保持运行,没有任何中断。
- 高数据安全性
用 SageMaker 进行机器学习
SageMaker 附带了许多内置的优化 ML 算法,这些算法广泛用于训练目的。现在要建立一个模型,我们需要数据。我们可以自己收集和准备培训数据,或者我们可以从亚马逊 S3 桶中选择,这是 AWS SageMaker 内的存储服务(有点像你系统中的硬盘驱动器)。让我们看看如何利用这个服务来构建一个端到端的 ML 项目。
现在让我们开始在 SageMaker 上构建我们的模型
本教程的重点将是使用 SageMaker 和所使用的库。任何 ML 概念都不会有任何解释。
注意 : 你应该有一个 AWS 账户来执行这些任务。
1.创建笔记本实例
就像您在您的系统中创建一个 jupyter 笔记本一样,我们也将在我们的平台上创建一个 jupyter 笔记本。以下是执行相同操作的步骤:
- 登录 AWS SageMaker 控制台。
- 点击笔记本实例,然后选择创建笔记本实例。
作者图片
- 在下一页,将您的笔记本命名为,将实例类型和弹性推理保留为默认,并为您的实例选择 IAM 角色。
图片作者|从下拉列表中,选择创建一个新角色,并选择任何 S3 桶
IAM(身份和访问管理)角色:
简而言之,SageMaker 和 S3 水桶是由 AWS 提供的服务。我们的笔记本实例需要存储在 S3 桶中的数据来构建模型。在 AWS 中,一个服务不能直接访问另一个服务。因此,应该提供一个角色,以便笔记本实例可以从 S3 存储桶访问数据。您可以为您的例程提供特定的 S3 时段或所有的 S3 时段。
- 创建角色后,点击创建笔记本实例。
- 创建实例需要几分钟时间。之后点击 jupyter,选择你想要使用的笔记本环境。
图片作者|本教程我选择了 conda_python3
这就是了。您的笔记本已创建。
2.了解使用的库
在本次会议中,我们将研究执行该任务所需的所有库:
使用的库
正如我之前提到的,AWS 包含了很多我们可以使用的内置 ML 算法。为了使用这些算法,我们需要 sagemaker 库。所有这些内置算法都是图像容器的形式,因此 get_image_uri 帮助我们访问这些容器。
如果你正在使用 sagemaker,你需要 boto3 库。就像您使用 pandas 从您的本地系统读取数据一样, boto3 帮助我们访问 S3 存储桶中的数据,前提是提供对这些存储桶的访问权限(还记得我的角色吗?).现在,如果我们想使用 sagemaker 实例,我们必须创建会话来完成。会话库用于创建会话。
3.创建 S3 存储桶
图片作者|最初没有水桶
S3 桶可以手动创建,也可以使用 boto3 从我们的笔记本实例中创建。在本教程中,我们将使用 boto3 来创建一个。
创建 S3 桶的代码
在 AWS 中有多个区域,每个用户在自己的区域工作。默认情况下,存储桶是在美国东部(N. Virginia)地区创建的,因此,如果您所在的地区不是 US-East-1 ,您必须在创建存储桶时明确指定您所在的地区。
**my_region = boto3.session.Session().region_name** # this gives you your region
**s3.create_bucket(Bucket=bucket_name, CreateBucketConfiguration={ 'LocationConstraint': my_region })** # this is how you explicitly add the location constraint
存储桶名称是全球唯一的!如果您与一个已经存在的存储桶冲突,并且您指定了一个不同于已经存在的存储桶区域的区域,AWS 将向您提供“IllegalLocationConstraintException”错误。如果您碰巧猜出了现有 bucket 的正确区域,它会给出 BucketAlreadyExists 异常。
除此之外,在给它们命名时,还必须记住一些命名约定:
- 存储桶名称的长度必须在 3 到 63 个字符之间。
- 存储桶名称只能由小写字母、数字、点(。),以及连字符(-)。
- 存储桶名称必须以字母或数字开头和结尾。
- 存储段名称不得格式化为 IP 地址(例如,192.168.5.4)
- 桶名不能以
xn--
开头(2020 年 2 月以后创建的桶)。 - 存储桶名称在一个分区中必须是唯一的。分区是一组区域。AWS 目前有三个分区:
aws
(标准地区)aws-cn
(中国地区),以及aws-us-gov
(AWS GovCloud【美国】地区)。 - 与亚马逊 S3 传输加速一起使用的桶不能有点(。)在他们的名下。有关传输加速的更多信息,请参见亚马逊 S3 传输加速。
4.将数据加载到 S3
我们首先将数据分为训练和测试。然后我们会把它运到 S3。
使用 SageMaker 时要记住的一个重要步骤是,SageMaker 中的内置算法期望相关要素是我们数据集的第一列。因此,如果数据集的第一列不是依赖要素的第一列,请确保对其进行更改。
将训练和测试数据加载到 S3 存储桶中
s3_input_train 和 s3_input_test 包含 s3 存储桶中上传的训练和测试数据的路径,这些数据将在以后训练时使用。
5.构建和训练模型
模型
容器通过指定区域名来检索内置的 XGB 模型。估算器通过指定我们希望在 image_uri 下使用的算法来处理端到端的 Amazon SageMaker 培训和部署任务。s3_input_train 和 s3_input_test 指定了训练和测试数据在 s3 存储桶中的位置。我们在步骤 4 中确定了这些路径。
6.部署
**xgb_predictor = xgb.deploy(initial_instance_count=1,instance_type='ml.m4.xlarge')**
然后可以使用上面的代码行部署训练好的模型。 initial_instance_count 指定预测时应该使用的实例数量。实例数量越多,预测越快。
7.预言;预测;预告
上述代码可用于预测结果。
8.打扫
在这一步中,您将终止您使用的所有资源。终止当前未被使用的资源可以降低成本,并且是一种最佳做法。不终止您的资源将导致您的帐户收费。
# Delete your deployed end points
**xgb_predictor.delete_endpoint()
xgb_predictor.delete_model()**# Delete your S3 bucket
**bucket_to_delete = boto3.resource('s3').Bucket(bucket_name) bucket_to_delete.objects.all().delete()**
最后删除你的 SageMaker 笔记本:停下来,删除你的 SageMaker 笔记本。
- 打开 SageMaker 控制台。
- 在笔记本下,选择笔记本实例。
- 选择您为本教程创建的笔记本实例,然后选择“操作”、“停止”。笔记本实例需要几分钟才能停止。当状态变为“已停止”时,继续下一步。
- 选择操作,然后选择删除。
- 选择删除。
你有它!这就是如何使用 AWS SageMaker 构建一个端到端的 ML 模型
本教程的完整代码可以从我的GitHub中访问。
随时和我联系LinkedIn。
希望你喜欢这个教程。感谢阅读:)
AWS Sagemaker 气流工作流管理
原文:https://towardsdatascience.com/aws-sagemaker-workflow-management-with-airflow-979748bf1eb0?source=collection_archive---------14-----------------------
实践教程
使用 Sagemaker 笔记本电脑和 Airflow DAGs 生产数据科学项目
在这篇文章中,我将谈谈我在 AWS Sagemaker 实例上使用气流调度数据科学项目笔记本的经验。我们已经使用网飞的 papermill 库运行 Jupyter 笔记本两年多了,每天都有数十个 Sagemaker 笔记本实例由气流精心编排,工作起来很有魅力。
你将读到这个系统的总体架构设计,工作方式是什么,团队之间的角色和职责是什么,以及你如何自己实现它。
本文原载于我的个人博客https://halilduygulu . com/blog/2021-12-11-managing-sage maker-workflows-with-air flow
问题
这一切都是从我在网飞博客上读到的这篇关于使用外部参数运行 jupyter 笔记本文件来生产数据科学工作负载的文章开始的。这可能是我在以前的公司面临的一个常见问题的解决方案,我们使用 pyspark 和其他 python 代码运行 Apache Spark 应用程序,用于 AWS EMR 上的数据科学和报告项目。大多数开发都是通过笔记本进行的,因为 Jupyter 笔记本几乎是数据科学家的标准开发环境。当时,一个常见的问题是在开发和准备生产代码期间,将代码从 ipynb 笔记本文件移动到普通的 python 文件,然后再移动回来。由于这是两个独立的文件,这涉及到从笔记本到。用于生产作品的 py 文件。
虽然在项目的早期阶段,这是一项简单的任务,但后来当一个较旧的项目必须修改以获得新功能或修复错误时,您每次都必须从 python 文件创建一个笔记本文件,或者在您的工作区中找到较旧的笔记本,并使用 python 文件上发生的更改来修改它。当您完成开发后,现在是时候将更改放入 python 文件中了,再次将您最近所做的更改复制粘贴到 python 文件中并测试它。在这种来回的复制粘贴过程或自动生成文件的过程中,经常会发生一些简单的错误,如忘记导入、漏掉一行修改、缩进错误等..有些错误是立即可见的,有些是在运行 spark 应用程序超过 3 个小时后才可见的。如果只有一个人在一个项目中工作,想象一下,多个数据科学家在同一个项目中使用多个笔记本文件,将函数或代码块从一个文件移动到另一个文件,这是一项非常复杂的工作,仅仅是解决 git 上的冲突。
使用笔记本进行开发、python 进行生产的另一个缺点是,对于在测试 airflow automation dag 期间发生的错误,您会得到许多“它正在我的开发环境中工作”的响应。而这些错误都是简单的编码错误,就像我上面提到的,缺失导入,硬编码值,开发时使用的额外导入,requirement.txt 文件中缺失库等等。所以本质上,项目的可维护性是一个痛点。
解决方案
当我开始在目前的公司工作时,我不想有同样的问题,并从一开始就寻找一种方法来建立数据科学和数据工程团队之间的可靠工作方式。这个想法是,数据科学家可以自由地在 Sagemaker 笔记本实例上开发他们的项目,只要他们在 git 存储库中交付这个项目,并在 requirements.txt 文件中运行笔记本文件和整个依赖项,当使用 Airflow 生产项目时。
因此,从数据工程的角度来看,我们只需要知道应该安装哪些依赖项,然后哪些笔记本文件必须用一组参数和笔记本文件的顺序(如果有多个)来执行。有了这些信息,任何数据工程师都可以准备一个 DAG,在生产流程中按照要求的时间表运行这个项目,因为几乎所有的数据科学项目都有通用而简单的代码作为抽象的结果。通过将项目级别的领域知识保存在笔记本文件中,并将常见任务抽象为 Airflow 操作符,我们已经将安排关于 Airflow 的数据科学项目任务作为配置流程,而不是开发工作。
现在我们已经讨论了工作方式,让我们深入系统架构和实现的细节。
作者图片
上面你可以看到 AI 平台的简化概览图。我们将在这里讨论的主要组件是 Airflow 和 Sagemaker,但让我简单解释一下其他一些工具。
我们主要使用 s 3 存储桶作为 data science 的输入源,每个帐户都有 3 个主要存储桶,位于许多其他 S3 存储桶之上,用于其他目的。
- 数据,一个只读桶,在一个类似于 Hive 文件系统的文件夹结构中包含拼花文件。我们还在这些文件之上提供了 AWS Athena 用于特殊查询。
- 中间,读/写桶,存储不重要的临时、短期文件。想象一下 spark 作业的 parquet 或 json 输出,它们将作为管道中下一步的输入。
- 输出,读写桶,应用最终产品的存储。因此,如果有必要,预测结果、经过训练的模型或工件会长期存储在这里。
我们还在大多数项目中使用 MLflow,它用于存储跨帐户的模型工件和度量。并且雪花是公司中的主要数据仓库,对于一些项目也用作输入数据源,对于许多项目雪花是 ML 模型的输出数据的目的地。将数据加载到雪花是通过气流完成的。
如果我们回到运行笔记本文件的 Airflow 和 Sagemaker 编排,我们可以从讨论笔记本和项目中的其他代码是如何部署的开始。如图所示,每个项目的代码照常存储在 Gitlab 中,部署任务实际上做了一件简单的事情,将这个项目中的全部代码复制到一个 S3 桶中,我称这个桶为automated-notebook
。与其他 S3 存储桶一样,该存储桶存在于每个名称带有后缀的 aws 帐户中。因此,当您在 gitlab pipeline 中单击 deploy to preprod 时,它实际做的是将项目内容复制到xx-automated-notebook-preprod
bucket 中,以便 Sagemaker 实例在运行笔记本时可以访问该分支中代码的最新部署版本。
好了,我们把代码放在了 Sagemaker 实例可以访问的地方,现在我们需要一个触发器,在我们的例子中是气流。正如我上面提到的,每个项目都有一个 dag,当 DAG 运行时,它为每个项目执行几乎标准的任务,例如;
创建一个 Sagemaker 实例https://halilduygulu.com/blog/2021-12-11-managing-sagemaker-workflows-with-airflow#create-a-sagemaker-instance
根据 DAG 的要求,我们可以在一个 sagemaker 实例中运行所有笔记本,也可以使用多个 sagemaker 实例并行运行它们。想象这样一个场景,您为每个国家训练一个模型,因此我们可以简单地同时为 20 个国家启动 20 个 sagemaker 实例,因为没有必要等待彼此训练完成后再启动下一个。我们通常这样做,并保持 dag 的总运行时间不变,即使国家的数量在不断增加。有时,您必须为每种类型的实例创建 AWS 限制增加支持票,以增加您的活动 Sagemaker 实例数。
获取 Sagemaker 实例的 IP 地址
由于我们每次都创建一个新的实例,这也意味着它们在 aws 私有子网中被分配了新的私有 ip 地址,我们需要这个 IP 地址才能 ssh 到这些实例中。虽然 AWS 没有在 boto3 的描述实例 api 响应中返回这个 IP,但是因为实例是在我们的子网中创建的,所以我们仍然能够在弹性网络接口(ENI)控制台中找到它们。因此,通过一些 boto3 api 调用技巧,我们现在能够获得 IP 并通过 Xcom 将其传递给 Airflow 中的下一个任务。
通过 Papermill 运行笔记本
为了运行 papermill 命令,我们将使用 Airflow SSHOperator 和几个链接在一起的命令。
- 将项目代码签入新创建的 Sagemaker 实例。这是一个从自动笔记本存储桶到本地磁盘的
aws s3 sync
命令。 - 激活本项目中使用的首选 conda 环境。
- 安装所需的 papermill 版本,因为不是每个 conda env 都有默认版本。
- 使用项目中的文件通过
pip install -r requirements.txt
安装项目依赖项。 - 最后,在其他一切准备就绪的情况下,我们运行 papermill 命令,该命令包含笔记本名称、输出目的地、内核和许多其他要传递给笔记本文件的自定义参数。
Papermill 是一个伟大的项目,我最喜欢它的两个特点。当然,第一个是注入参数。Papermill 使您能够将参数注入笔记本文件,如果您只是在 ipynb 文件中添加一个带有parameters
标签的单元格,如这里所述。我们使用此功能将一些标准参数传递给笔记本,如 aws 环境名称或 id、来自 airflow dag 的执行日期以及项目/模型特定参数。
papermill 的第二个功能是,您可以将每个笔记本运行文件与单元输出和注入参数等保存在一起。得救了。ipynb 文件看起来与您手动运行它时一样。这为我们提供了两件事情,使用详细的错误日志进行故障排除,以及保存每次计划的运行以供审计或保存历史记录。基本上每个自动运行的笔记本文件都作为一个单独的文件保存在 S3 上。
删除 Sagemaker 实例https://halilduygulu.com/blog/2021-12-11-managing-sagemaker-workflows-with-airflow#delete-sagemaker-instance
当所有笔记本文件都通过 Airflow dag 中的 SSHOperator 执行时,下一步是删除这个 Sagemaker 实例,因为我们不再需要它了。此 dag 和其他 Dag 的下一次运行将创建他们自己的 Sagemaker 实例来运行笔记本,这为我们提供了每个项目的临时和隔离运行时,以及项目的更多并发运行程序。AWS Sagemaker 管理 api 的限制是每秒 4 个请求,因此如果出现 api 错误,您需要处理这个问题。
交付结果https://halilduygulu.com/blog/2021-12-11-managing-sagemaker-workflows-with-airflow#delivering-results
由于此流程用于 ML 模型训练以及预测/推理,大多数情况下 Dag 会有一个最终步骤,我们将笔记本的输出加载到雪花或其他目的地。这些是基于项目需求的 json 或 parquet 文件,在我们的例子中,与 Snowflake 或其他第三方的交互比在笔记本文件中更容易。Airflow 几乎为我们已经集成的所有东西都提供了一个操作符或插件,因此我们选择不在数据科学项目笔记本中包含这一职责,以保持简单。
作者图片
上面,我用 Sagemaker 笔记本实例为一个典型的气流 DAG 添加了一个简单的流。每个笔记本都可能在其中进行非常复杂的 ML 模型训练或预测,但从数据工程的角度来看,这是一个简单的应用程序,通过带有参数的气流触发,与各种源数据系统交互,并产生将被传递到目标系统的输出。
此解决方案的优势https://halilduygulu.com/blog/2021-12-11-managing-sagemaker-workflows-with-airflow#benefits-of-this-solution
- 数据工程师不需要了解数据科学项目的细节就可以实现自动化。
- 数据科学家可以开发和测试没有硬编码参数的笔记本,并且知道相同的代码正在生产中运行,没有复制粘贴,没有临时代码行等。所有的代码变更和历史都在 git 仓库中。
- 应用程序运行时是相同且独立的。每个 sagemaker 实例安装项目需求,并且只运行一个项目。不存在会导致与库版本冲突或需要定期维护长期运行时。
- 您不必等待另一个项目完成,这样另一个项目就可以开始运行。
- 所有 Sagemaker 实例仅在应用程序运行时使用,稍后会终止。因此,闲散人员无需支付任何费用。
- 多个软件开发环境可用于测试或解决生产问题,因为所有实例都设置相同,并且具有来自 git 存储库的相同代码。
- 任何支持的语言或内核都可以在项目中使用,这只是 Airflow dag 中的一个参数。
- 可以保持历史记录的日志气流,也在 S3 从造纸厂输出。
- 不需要丰富的 docker 经验或 kubernetes 集群管理员。
- 不需要处理 EMR 集群设置以及随之而来的相关问题。
- 您受到最大 Sagemaker 实例类型的限制,目前为 96 个 cpu 和 768 GB 内存,但在我们的情况下,这已经足够了,作为回报,我们不必维护 EMR 集群或其他运行时来运行数据科学工作负载。如果需要,在使用其他优势的同时,还有其他解决方案可供使用。
链接
- 【https://aws.amazon.com/sagemaker/
- https://papermill.readthedocs.io/en/latest/
- https://netflixtechblog . com/scheduling-notebooks-348 E6 c 14 CFD 6
- https://jupyter.org/
AWS 系统管理器—远程管理服务器
原文:https://towardsdatascience.com/aws-system-manager-manage-server-remotely-4f8ffe63575d?source=collection_archive---------17-----------------------
丹尼尔·格雷瓜尔在 Unsplash 拍摄的照片
SSM 在多台主机上并行运行命令,不使用 SSH
最近,由于我们安全团队的一些更新,我们不得不在 AWS 帐户的所有主机上安装一个代理。我们在客户中运行了 1100 多个 EC2 实例。这些服务器有不同的操作系统(亚马逊 Linux、Fedora、CentOS、RHEL、Ubuntu、Windows、FreeBSD 等)。此外,这些服务器支持各种工作负载,如 EMR(各种版本)、EKS、ECS、Airflow、Tableau、Alation。其中许多是供应商配置的服务器,它们有自己的 ami。用代理为每种类型创建 ami 需要很长时间和巨大的努力。此外,有些服务器不能容忍重启(为了让用户数据脚本工作)。
AWS 有一个名为 System Manager 的服务,它允许我们在不需要 SSH 的情况下运行远程命令。运行 SSM 文档的基本要求是主机应该运行amazon-ssm-agent
,并且主机应该有一个能够访问 SSM(amazonsmsmanagedinstancecore)的 IAM 角色。下图总结了 SSM 运行命令的工作方式。
SSM 运行命令的高级流程|图片由作者提供
SSM 运行命令中的低级 API 调用:
- SSM 代理向 SSM 服务端点更新实例详细信息。这每 5 分钟发生一次(ssm:UpdateInstanceInformation)。此更新增强了运行命令实例的详细信息。
- 代理持续轮询(长时间)来自消息传递服务(ec2messages:GetMessages)的消息。
- 一旦它接收到预定的消息,它就发送一个确认(ec2messages:AcknowledgeMessage)。
- 它从 SSM 下载文档(ssm:GetDocument)
- 执行文档。
- 如果在此期间收到取消消息,它将取消文档执行。
- 将响应发送回消息传递服务(ec2messages:SendReply)。
幸运的是,我们在这些服务器上安装了 SSM 代理。我们为 SSM 和其他所需的访问权限创建了一个托管策略,并将该策略附加到主机的 IAM 角色。我们利用 boto3 让所有拥有 EC2 服务的 IAM 角色成为可信实体,并向角色添加托管策略。
一旦满足了先决条件,我们就利用系统管理器的文档和运行命令功能来安装代理。对于正在运行的实例,我们采用了基于标签的方法,并基于该标签运行文档。
现有服务器修补解决方案设计|作者图片
由于我们的平台使用了大量的自动伸缩,我们还需要在由 AWS 管理的自动伸缩运行的新服务器上放置代理。我们可以使用启动模板的用户数据,但是 EMR 管理的扩展组(实例组)没有用户数据,我们不想干扰现有的引导脚本。我们使用了 CloudWatch、Lambda、SQS 和 SSM 来处理这些问题。
现场安装解决方案设计|作者图片
- EC2 实例出现,它生成事件并将它们发送到 CloudWatch。
- CloudWatch 基于实例状态变化(正在运行)来挖掘事件。它将该事件发送到 SQS 队列。
SQS 队列在消息上增加了 3 分钟的延迟,然后在 3 分钟的窗口中对消息进行批处理。
递送延迟的 SQS 队列配置|作者图片
- AWS Lambda 批量接收消息。它过滤由 SSM 管理的实例。对于不由它管理的实例,将它发送到另一个数据库。SSM it 部门管理的所有实例都根据平台(Linux/Windows)进行分组。它调用 SSM 的相应文件。
Lambda |图片的 SQS 事件触发器(作者)
- SSM 文档向所有目标实例发送命令,并在服务器上安装代理。
SSM 文档样本
命令的 SSM 文档运行历史|作者的图像
这种方法使我们能够在 3 天内对所有的机器运行安装命令(我们分批执行以减小爆炸半径)。所有新机器都通过 lambda 自动打补丁。我们也可以使用 cli 发送命令。
aws ssm send-command \
--document-name "<Document_name>" \
--targets "Key=instanceids,Values=i-1234567890abcdef0" \
--timeout-seconds 300
尽管我们这样做是为了安装特定的代理,但是该解决方案可以扩展到各种用例(自动化就是其中之一)。我能马上想到的一个是替换air flow . contrib . operators . ssh _ operator。有了 SSM,我们不必创建 SSH 连接。一切都由 SSM 负责。解决方案中唯一的问题是 SSM 15 分钟的暂停。但是如果你跟着火走,却忘了接近,这将是一个很好的探索选择。
云计算快乐!!
Azure 认知服务:探索认知愿景
原文:https://towardsdatascience.com/azure-cognitive-service-computer-vision-33ba62ce9d7e?source=collection_archive---------33-----------------------
第 1 部分:Azure 认知视觉服务概述,用于处理和分类来自深度学习的计算机视觉领域的图像
戴维·特拉维斯在 Unsplash 上拍摄的照片
介绍
随着各种公共云提供商(如 Azure、AWS 或 Google Cloud)提供的各种预培训服务的出现,认知服务领域发展得太快了。这个领域已经变得越来越有前景,因为它覆盖了解决大多数跨行业领域的常见业务用例。
这篇文章将主要研究微软 Azure 提供的各种认知服务,值得讨论每种服务的能力以及它们可以提供的解决方案。这将是一系列的帖子,首先介绍这些服务:1)认知视觉,2)认知文本分析,3)认知语言处理,4)知识处理和搜索。
在这第一篇文章中,我们将简要了解微软 Azure 的认知愿景产品。
- 认知人脸 API
- 计算机视觉 API
- 定制视觉服务
- 媒体服务视频分析器
https://www.linkedin.com/in/p-jainani
视觉、图像和视频
Face API
该服务提供算法,公开为基于 REST 的 web 服务调用,用于检测、验证、识别和分析人脸。该服务可以提供面部匹配、面部属性和特征分析。该 API 还具有面部识别和辨认的能力。该服务还提供特定于面部的:标志(鼻子、眼睛)和属性(肤色、年龄、性别)。
人脸检测 API :人脸检测 API 提供关于图像中检测到的人脸的信息,但并不是为了识别或辨认特定的人脸而设计的。
人脸识别 API :它建立在面部检测 API 的基础上,通过分析两张或更多图片中的地标来确定是否存在同一张脸。这对于人脸验证和识别是有用的。
情感 API:Face API 可以通过检测方法情感属性返回一般的情感值。API 通过使用额外的方法和算法来检测人脸图像中丰富的情绪集,通过提供以下情绪的置信度来提供这些结果:愤怒、轻蔑、厌恶、恐惧、快乐、情绪缺失(中性)、悲伤和惊讶。**
这里有一个快速入门指南,可以用你选择的任何语言和平台开始使用 Face API。
与大多数认知服务一样,Face API 需要使用订阅密钥(有时称为 API 密钥)进行授权。这个密钥应该保密,以确保其他人无法使用您的资源。您将为每个对 Face API 的调用包含订阅密钥
计算机视觉 API
计算机视觉 API 提供了处理图像的算法能力,并使用预先训练的模型 API 返回洞察力。它使你能够发现一个图像是否有淫秽内容,或者需要找到图像中的所有面孔。它还通过评估图像特征和颜色、图像内容分类以及使用内置的 API 功能生成图像描述来提供帮助。
用于图像分析的计算机视觉 API
API 的分析端点根据图像内容提取丰富的视觉特征。请求示例如下所示:
curl "https://<region>.api.cognitive.microsoft.com/vision/v2.0/**analyze**?**visualFeatures=Categories,Description&details=Landmarks**" \
-H "Ocp-Apim-Subscription-Key: $key" \
-H "Content-Type: application/json" \
-d "{'url' : '/images/mountains.jpg'}" \
| jq '.'curl "https://<region>.api.cognitive.microsoft.com/vision/v2.0/analyze?**visualFeatures=Adult,Description**" \
-H "Ocp-Apim-Subscription-Key: $key" \
-H "Content-Type: application/json" \
-d "{'url' : '/images/people.png'}" \
| jq '.'
有关
*analyze*
操作的更多信息,参见分析图像参考文件。
生成图像缩略图的计算机视觉 API
此外,计算机视觉 API 还可以使用缩略图端点:https://<region>.api.cognitive.microsoft.com/vision/v2.0/generateThumbnail
智能生成图像缩略图,以有效显示大图像。请求示例如下所示:
curl "https://<region>.api.cognitive.microsoft.com/vision/v2.0/**generateThumbnail**?width=100&height=100&smartCropping=true" \
-H "Ocp-Apim-Subscription-Key: $key" \
-H "Content-Type: application/json" \
-d "{'url' : '/images/dog.png'}" \
-o thumbnail.jpg
关于
generateThumbnails
操作的更多信息,参见获取缩略图参考文件。
计算机视觉 API 提取印刷文本
API 的ocr
操作检测图像中的打印文本并提取字符,然后将其转换为字符流供下游应用程序使用。请求的 URL 具有以下格式:https://<region>.api.cognitive.microsoft.com/vision/v2.0/ocr?language=<...>&detectOrientation=<...>
。请求示例如下所示:
curl "https://<region>.api.cognitive.microsoft.com/vision/v2.0/ocr" \
-H "Ocp-Apim-Subscription-Key: $key" \
-H "Content-Type: application/json" \
-d "{'url' : '/images/ebook.png'}" \
| jq '.'
有关
ocr
操作的更多信息,请参见 OCR 参考文档。
提取手写文本的计算机视觉 API
与 OCR 操作不同的是,recognizeText
操作从笔记、信件、白板、表格和其他来源中检测和提取手写的&书法文本。请求的 URL 具有以下格式:
https://<region>.api.cognitive.microsoft.com/vision/v2.0/recognizeText?mode=[Printed|Handwritten]
请求将输出转储到控制台:
curl "https://<region>.api.cognitive.microsoft.com/vision/v2.0/recognizeText?mode=Handwritten" \
-H "Ocp-Apim-Subscription-Key: $key" \
-H "Content-Type: application/json" \
-d "{'url' : '/images/handwriting.jpg'}" \
-D -
有关
recognizeText
操作的更多信息,请参见识别手写文本参考文档。
专业提示 : Azure 还提供了利用容器封装其认知服务产品的选项,这允许开发者跨平台快速部署他们的定制认知解决方案。快速参考此处。
定制视觉服务
Custom Vision 服务旨在创建图像分类模型,从您为特定领域提供的已标记图像中“学习”。例如,从给定的图像目录中识别狗的品种。
作为开发人员,要利用这项服务,您需要使用自定义视觉服务门户创建一个项目
自定义视觉服务门户:登录页
使用您的 Microsoft 帐户登录门户,并开始创建项目。它提供了在项目类型之间进行选择的能力,例如分类或对象检测、多标签或多类分类,以及预定义的域选择,即地标、零售、食品等...
要快速实践定制视觉服务,请遵循此 URL 中提到的步骤。全面的细节可从定制视觉文档中获得。
媒体服务视频分析器
媒体视频分析器是一个 Azure 认知服务,用于从视频媒体中提取见解。它使用可以进一步定制和训练的机器学习模型。它支持从视频媒体文件中进行人脸识别、文本识别、对象标记、场景分割。
它还分析来自音频的内容,例如转录和情感检测。这些结果可用于改进搜索、提取剪辑和创建缩略图。
微软为此服务提供了一个单独的门户网站,即媒体门户网站的视频分析器
Azure Video Analyzer for Media 提供了几个上传视频的选项,最常见的是从 URL 上传、REST API 或以字节数组的形式发送文件。它还支持广泛的文件格式,如 WMV,MOV,MPG 和 AVI。视频上传后,索引过程会自动开始。完成后,您可以检查索引器结果。
由此产生的见解不仅限于:成绩单、OCR、面孔、品牌、情绪或情感。
此外,它支持关于视频的高级见解和关键方面,如场景、镜头和关键帧。它还支持搜索视频中的关键概念,并提供时间线建议。
为了在媒体 Azure 视频分析器上获得快速的动手练习,请遵循此 URL 或此处的中提到的步骤。全面的细节可通过 Azure 媒体视频分析器获得。
摘要
在这篇文章中,我们简要讨论了各种 Azure 认知服务,这些服务旨在解决需要计算机视觉能力的业务问题。这些服务在调配后即可立即使用,并且大多以随用随付的方式提供。
在下一篇文章中,我们将讨论 Azure 的语言和文本认知服务。
参考
[1] Azure 认知服务— 文档
**https://www.linkedin.com/in/p-jainani **
Azure Cosmos DB:用例与权衡
原文:https://towardsdatascience.com/azure-cosmos-db-use-cases-and-trade-offs-5a65727daaa9?source=collection_archive---------26-----------------------
如何在 Azure Cosmos DB 中选择正确的数据模型?SQL,MongoDB,Cassandra,图还是表?
吉列尔莫·费拉在 Unsplash 上拍摄的照片
Azure Cosmos DB 是一个完全托管的、可弹性伸缩的全球分布式数据库,采用多模型方法,为您提供使用文档、键值、宽列或基于图形的数据的能力。
在这篇博客中,我们将深入探讨多模型功能,并探索可用于存储和访问数据的选项。希望它能帮助你在正确的 API 上做出明智的决定。
- 核心(SQL) API:结合了 SQL 查询功能的 NoSQL 文档存储的灵活性。
- MongoDB API :支持 MongoDB wire 协议,这样现有的 MongoDB 客户端可以继续使用 Azure Cosmos DB,就像它们运行在实际的 MongoDB 数据库上一样。
- Cassandra API :支持 Cassandra wire 协议,因此现有的符合 CQLv4 的 Apache 驱动程序可以继续与 Azure Cosmos DB 一起工作,就像它们是在实际的 Cassandra 数据库上运行一样。
- Gremlin API :用 Apache TinkerPop(一个图形计算框架)和 Gremlin 查询语言支持图形数据。
- Table API :为针对 Azure Table 存储编写的应用提供高级功能。
您可以进一步了解一些 的主要优势
使用 Azure Cosmos DB 的一些常见场景(无论如何不是一个详尽的列表)包括:
- 现代游戏服务需要提供定制和个性化的内容,如游戏内统计数据、社交媒体整合和高分排行榜。作为一个完全托管的产品,Azure Cosmos DB 需要最少的设置和管理,以允许快速迭代,并缩短上市时间。
- 电子商务平台和零售应用程序存储目录数据,并用于订单处理管道中的事件采购。
- 零售用例存储产品目录信息,这些信息在结构上可以是动态的。
…还有更多!
使用哪种 API,何时使用?
没有完美的公式!有时,选择是明确的,但是其他场景可能需要一些分析。
要考虑的一个相当明显的问题是,是否存在通过 wire 协议使用任何受支持的 API 的现有应用程序(例如 Cassandra 和 MongoDB)?如果答案是肯定的,您应该考虑使用特定的 Azure Cosmos DB API,因为这将减少您的迁移任务,并充分利用您团队中以前的经验。
如果您希望模式发生很大变化,您可能希望利用文档数据库,使 Core (SQL)成为一个不错的选择(尽管也应该考虑 MongoDB API)。
如果您的数据模型由实体之间的关系和相关元数据组成,那么您最好使用 Azure Cosmos DB Gremlin API 中的图形支持。
如果你目前正在使用 Azure Table Storage ,Core (SQL) API 将是一个更好的选择,因为它提供了更丰富的查询体验,并改进了 Table API 的索引。如果你不想重写你的应用,考虑迁移到 Azure Cosmos DB Table API 。
让我们看看每个 API 并应用其中的一些。
核心(SQL) API:两全其美
核心(SQL) API 是默认的 Azure Cosmos DB API。您可以使用 JSON 文档存储数据来表示您的数据,但是有几种方法可以检索它:
- SQL 查询:使用结构化查询语言(SQL)作为 JSON 查询语言编写查询
- 点读取:在单个条目 ID 和分区键上进行键/值样式的查找(这些比 SQL 查询更便宜、更快)
对于许多应用程序来说,半结构化数据模型可以提供他们所需要的灵活性。例如,具有大量产品类别的电子商务设置。您将需要添加新的产品类别和支持操作(搜索,排序等。)跨多个产品属性。您可以用关系数据库对此进行建模,但是,不断发展的产品类别可能需要停机来更新表模式、查询和数据库。
使用 Core (SQL ),引入新产品类别就像为新产品添加文档一样简单,无需更改模式或停机。Azure Cosmos DB MongoDB API 也适合这些需求,但是 Core (SQL) API 具有优势,因为它在灵活的数据模型之上支持类似 SQL 的查询。
考虑一个博客平台的例子,用户可以创建帖子,喜欢这些帖子并添加评论。
你可以这样表示一个post
:
{
"id": "<post-id>",
"type": "post",
"postId": "<post-id>",
"userId": "<post-author-id>",
"userUsername": "<post-author-username>",
"title": "<post-title>",
"content": "<post-content>",
"commentCount": <count-of-comments>,
"likeCount": <count-of-likes>,
"creationDate": "<post-creation-date>"
}
以及comments
和likes
:
{
"id": "<comment-id>",
"type": "comment",
"postId": "<post-id>",
"userId": "<comment-author-id>",
"userUsername": "<comment-author-username>",
"content": "<comment-content>",
"creationDate": "<comment-creation-date>"
}{
"id": "<like-id>",
"type": "like",
"postId": "<post-id>",
"userId": "<liker-id>",
"userUsername": "<liker-username>",
"creationDate": "<like-creation-date>"
}
为了处理喜欢和评论,您可以使用一个存储过程:
function createComment(postId, comment) {
var collection = getContext().getCollection(); collection.readDocument(
`${collection.getAltLink()}/docs/${postId}`,
function (err, post) {
if (err) throw err; post.commentCount++;
collection.replaceDocument(
post._self,
post,
function (err) {
if (err) throw err; comment.postId = postId;
collection.createDocument(
collection.getSelfLink(),
comment
);
}
);
})
}
如果你想了解更多,请参考 在 Azure Cosmos DB 中使用 JSON
从现有的 MongoDB 实例迁移
Azure Cosmos DB 为 MongoDB 实现了 wire 协议,它允许与原生 MongoDB 客户端 SDK、驱动程序和工具透明兼容。这意味着任何理解这个协议版本的 MongoDB 客户端驱动程序(以及 Studio 3T 等现有工具)都应该能够本地连接到 Cosmos DB。
例如,如果您有一个现有的 MongoDB 数据库作为采购订单处理应用程序的数据存储,以捕获不同格式的失败和部分订单、履行数据、运输状态。由于数据量不断增加,您希望迁移到可扩展的基于云的解决方案,并继续使用 MongoDB——使用 Azure Cosmos DB 的 API for MongoDB 是非常合理的。但是,您希望对现有应用程序进行最少的代码更改,并在尽可能短的停机时间内迁移当前数据。
借助 Azure 数据库迁移服务,您可以执行在线(最小停机时间)迁移,并根据您的需求灵活扩展为您的 Cosmos 数据库提供的吞吐量和存储,并且只需为您需要的吞吐量和存储付费。这导致了显著的成本节约。
参考https://docs.microsoft.com/azure/cosmos-db/mongodb-pre-migration?WT.mc_id=data-12713-abhishgu*和* 迁移后 指南。
一旦迁移了数据,您就可以继续使用现有的应用程序。下面是一个使用 MongoDB 的例子。网络驱动:
初始化客户端:
*MongoClientSettings settings = new MongoClientSettings();
settings.Server = new MongoServerAddress(host, 10255);
settings.UseSsl = true;
settings.SslSettings = new SslSettings();
settings.SslSettings.EnabledSslProtocols = SslProtocols.Tls12;MongoIdentity identity = new MongoInternalIdentity(dbName, userName);
MongoIdentityEvidence evidence = new PasswordEvidence(password);settings.Credential = new MongoCredential("SCRAM-SHA-1", identity, evidence);MongoClient client = new MongoClient(settings);*
检索数据库和集合:
*private string dbName = "Tasks";
private string collectionName = "TasksList";var database = client.GetDatabase(dbName);
var todoTaskCollection = database.GetCollection<MyTask>(collectionName);*
将任务插入集合:
*public void CreateTask(MyTask task)
{
var collection = GetTasksCollectionForEdit();
try
{
collection.InsertOne(task);
}
catch (MongoCommandException ex)
{
string msg = ex.Message;
}
}*
检索所有任务:
*collection.Find(new BsonDocument()).ToList();*
您还应该仔细考虑如何将 MongoDB 写/读问题映射到 Azure Cosmos 一致性级别、管理索引并利用更改提要支持。
请注意,如果不需要重用现有代码和从现有 MongoDB 数据库导入数据,那么核心(SQL) API 将是一个合适的选择。
用 Cassandra 处理实时数据
如果您的应用程序需要处理大量的实时数据,Apache Cassandra 是一个理想的选择。使用 Azure Cosmos DB Cassandra API,您可以使用符合 CQ v4 的现有 Apache 驱动程序,并且在大多数情况下,您应该能够通过更改连接字符串,从使用 Apache Cassandra 切换到使用 Azure Cosmos DB 的 Cassandra API。也可以继续使用基于 Cassandra 的工具,比如cqlsh
。
对于高级分析用例,您应该将 Azure Cosmos DB Cassandra API 与 Apache Spark 相结合。你可以使用熟悉的Spark connector for Cassandra来连接 Azure Cosmos DB Cassandra API。此外,您还需要来自 Azure Cosmos DB 的Azure-Cosmos-Cassandra-spark-helperhelper 库,用于定制连接工厂和重试策略等功能。
可以从Azure data bricks以及 Spark on YARN 使用 HDInsight 访问 Azure Cosmos DB Cassandra API
要连接到 Cosmos DB,您可以像这样使用 Scala API:
*import org.apache.spark.sql.cassandra._
import com.datastax.spark.connector._
import com.datastax.spark.connector.cql.CassandraConnector
import com.microsoft.azure.cosmosdb.cassandraspark.conf.set("spark.cassandra.connection.host","YOUR_ACCOUNT_NAME.cassandra.cosmosdb.azure.com")
spark.conf.set("spark.cassandra.connection.port","10350")
spark.conf.set("spark.cassandra.connection.ssl.enabled","true")
spark.conf.set("spark.cassandra.auth.username","YOUR_ACCOUNT_NAME")
spark.conf.set("spark.cassandra.auth.password","YOUR_ACCOUNT_KEY")
spark.conf.set("spark.cassandra.connection.factory", "com.microsoft.azure.cosmosdb.cassandra.CosmosDbConnectionFactory")spark.conf.set("spark.cassandra.output.batch.size.rows", "1")
spark.conf.set("spark.cassandra.connection.connections_per_executor_max", "10")
spark.conf.set("spark.cassandra.output.concurrent.writes", "1000")
spark.conf.set("spark.cassandra.concurrent.reads", "512")
spark.conf.set("spark.cassandra.output.batch.grouping.buffer.size", "1000")
spark.conf.set("spark.cassandra.connection.keep_alive_ms", "600000000")*
可以进行聚合,如average
、min/max
、sum
等。:
*spark
.read
.cassandraFormat("books", "books_ks", "")
.load()
.select("book_price")
.agg(avg("book_price"))
.showspark
.read
.cassandraFormat("books", "books_ks", "")
.load()
.select("book_id","book_price")
.agg(min("book_price"))
.showspark
.read
.cassandraFormat("books", "books_ks", "")
.load()
.select("book_price")
.agg(sum("book_price"))
.show*
使用 Gremlin (Graph) API 连接一切
作为个性化客户体验的一部分,您的应用程序可能需要在网站上提供产品推荐。比如“买了产品 X 的人也买了产品 Y”。您的用例可能还需要预测客户行为,或者将人们与具有相似兴趣的人联系起来。
Azure Cosmos DB 支持 Apache Tinkerpop 的图遍历语言(即 Gremlin)。有许多用例会产生与缺乏灵活性和关系方法相关的常见问题。例如,管理连接的社交网络、地理空间使用案例,如在一个区域内查找感兴趣的位置或定位两个位置之间的最短/最佳路线,或将物联网设备之间的网络和连接建模为图表,以便更好地了解设备和资产的状态。除此之外,您可以继续享受所有 Azure Cosmos DB APIs 共有的功能,如全球分布、存储和吞吐量的弹性扩展、自动索引和查询以及可调的一致性级别。
例如,您可以使用以下命令将产品的三个顶点和相关采购的两条边添加到图形中:
*g.addV('product').property('productName', 'Industrial Saw').property('description', 'Cuts through anything').property('quantity', 261)
g.addV('product').property('productName', 'Belt Sander').property('description', 'Smoothes rough edges').property('quantity', 312)
g.addV('product').property('productName', 'Cordless Drill').property('description', 'Bores holes').property('quantity', 647)g.V().hasLabel('product').has('productName', 'Industrial Saw').addE('boughtWith').to(g.V().hasLabel('product').has('productName', 'Belt Sander'))
g.V().hasLabel('product').has('productName', 'Industrial Saw').addE('boughtWith').to(g.V().hasLabel('product').has('productName', 'Cordless Drill'))*
然后,您可以查询随“工业锯”一起购买的其他产品:
*g.V().hasLabel('product').has('productName', 'Industrial Saw').outE('boughtWith')*
下面是结果的样子:
*[
{
"id": "6c69fba7-2f76-421f-a24e-92d4b8295d67",
"label": "boughtWith",
"type": "edge",
"inVLabel": "product",
"outVLabel": "product",
"inV": "faaf0997-f5d8-4d01-a527-ae29534ac234",
"outV": "a9b13b8f-258f-4148-99c0-f71b30918146"
},
{
"id": "946e81a9-8cfa-4303-a999-9be3d67176d5",
"label": "boughtWith",
"type": "edge",
"inVLabel": "product",
"outVLabel": "product",
"inV": "82e1556e-f038-4d7a-a02a-f780a2b7215c",
"outV": "a9b13b8f-258f-4148-99c0-f71b30918146"
}
]*
除了传统的客户端,你可以使用图形批量执行程序。NET 库在 Azure Cosmos DB Gremlin API 中执行批量操作。与使用 Gremlin 客户端相比,使用此功能将提高数据迁移效率。传统上,使用 Gremlin 插入数据将要求应用程序在需要验证、评估、然后执行以创建数据的时候发送一个查询。批量执行器库将处理应用程序中的验证,并为每个网络请求一次发送多个图形对象。以下是如何创建顶点和边的示例:
*IBulkExecutor graphbulkExecutor = new GraphBulkExecutor(documentClient, targetCollection);BulkImportResponse vResponse = null;
BulkImportResponse eResponse = null;try
{
vResponse = await graphbulkExecutor.BulkImportAsync(
Utils.GenerateVertices(numberOfDocumentsToGenerate),
enableUpsert: true,
disableAutomaticIdGeneration: true,
maxConcurrencyPerPartitionKeyRange: null,
maxInMemorySortingBatchSize: null,
cancellationToken: token); eResponse = await graphbulkExecutor.BulkImportAsync(
Utils.GenerateEdges(numberOfDocumentsToGenerate),
enableUpsert: true,
disableAutomaticIdGeneration: true,
maxConcurrencyPerPartitionKeyRange: null,
maxInMemorySortingBatchSize: null,
cancellationToken: token);
}
catch (DocumentClientException de)
{
Trace.TraceError("Document client exception: {0}", de);
}
catch (Exception e)
{
Trace.TraceError("Exception: {0}", e);
}*
虽然可以使用核心(SQL) API 作为 JSON 文档来建模和存储这些数据,但是它不适合需要确定实体(例如产品)之间关系的查询。
您可能想要探索 Azure Cosmos DB Gremlin API 的 图形数据建模 以及 数据分区 。
Azure 桌面储物系列!
如果你已经有了为 Azure Table storage 编写的应用程序,它们可以通过使用 Table API 迁移到 Azure Cosmos DB,而不需要修改代码,并利用高级功能。
将您的数据库从 Azure Table Storage 迁移到 Azure Cosmos DB,以较低的吞吐量,可以在延迟(一位数毫秒的读写)、吞吐量、全局分布、全面的 SLA 以及成本方面带来很多好处(您可以使用基于消耗的或供应容量模式。将表数据存储在 Cosmos DB 中会自动索引所有属性(没有索引管理开销),而表存储只允许对分区和行键进行索引。
Table API 具有可用于的客户端 SDK。例如,对于 Java 客户端,使用连接字符串来存储表端点和凭证:
*public static final String storageConnectionString =
"DefaultEndpointsProtocol=https;" +
"AccountName=your_cosmosdb_account;" +
"AccountKey=your_account_key;" +
"TableEndpoint=https://your_endpoint;" ;*
..并执行 CRUD(创建、读取、更新、删除)操作,如下所示:
*try
{
CloudStorageAccount storageAccount =
CloudStorageAccount.parse(storageConnectionString); CloudTableClient tableClient = storageAccount.createCloudTableClient(); CloudTable cloudTable = tableClient.getTableReference("customers");
cloudTable.createIfNotExists(); for (String table : tableClient.listTables())
{
System.out.println(table);
} CustomerEntity customer = ....;
TableOperation insert = TableOperation.insertOrReplace(customer);
cloudTable.execute(insert); TableOperation retrieve =
TableOperation.retrieve("Smith", "Jeff", CustomerEntity.class);
CustomerEntity result =
cloudTable.execute(retrieve).getResultAsType(); TableOperation del = TableOperation.delete(jeff);
cloudTable.execute(del);
}*
参考 表 API 哪里和 Azure 表存储行为不一样? 了解详情。
结论
Azure Cosmos DB supports 在 API 方面提供了许多选项和灵活性,并且根据您的用例和需求有其优缺点。虽然核心(SQL)非常通用,并且适用于广泛的场景,但是如果您的数据能够更好地用关系来表示,那么 Gremlin (graph) API 是一个合适的选择。如果您有使用 Cassandra 或 MongoDB 的现有应用程序,那么将它们迁移到各自的 Azure Cosmos DB APIs 提供了一条阻力最小且具有额外好处的路径。如果您想从 Azure 表存储中迁移,并且不想重构您的应用程序以使用核心(SQL) API,请记住,您可以选择 Azure Cosmos DB 表 API,它可以提供与表存储的 API 兼容性以及诸如保证高可用性、自动二级索引等功能!
Azure Data Factory CI-CD 简化版:使用 Azure DevOps YAML 管道构建和部署 ARM 模板
原文:https://towardsdatascience.com/azure-data-factory-ci-cd-made-simple-building-and-deploying-your-arm-templates-with-azure-devops-30c30595afa5?source=collection_archive---------5-----------------------
发布/部署 Azure 数据工厂工件的最简单方式
安德里亚斯·费尔斯克在 Unsplash 上的照片
如果你使用 Azure Data Factory,你可能会注意到这个工具的部署过程是独一无二的。它不同于 API 或网站部署,因为它生成 ARM 模板,并且在某些时候肯定会问“为什么部署它如此困难?”。嗯,不一定是…
数据工厂 CI/CD —旧的(有问题的)流程
Azure Data Factory 是大数据流程的优秀编排工具。它有许多集成和功能,使数据工程师的生活非常容易。
虽然当我们谈论部署时,有一些技巧,例如工作区内的发布按钮,这是生成要部署的 ARM 模板所必需的。此外,没有部署到开发环境中,因为您已经在那里作为一个编辑器工具工作。与其他“传统开发”相比,这个过程有点不同,这个手动步骤让开发人员不寒而栗:
从 Azure 数据工厂工作区部署—图片来自微软文档
它经常创建讨论和“变通办法”来处理这个手动步骤。在一些解决方案中,人们将生成 ARM 模板从 adf_publish 手动移动到 feature 分支,并创建新的提交。在其他情况下,有一个使用多个 repo 的集成,但是同样,启动部署应该是一个手动步骤。
在旧的方法上,从我的角度来看,最好的解决方案是使用 Azure Powershell 进行部署,但这增加了复杂性,因为您需要手动控制所有应该部署的元素,如链接的服务和管道。
数据工厂 CI/CD —新的(更好的)流程
幸运的是,有一种新的方法可以生成要部署的 ARM 模板,您不需要上面提到的变通方法。
在这种策略中,您基本上是验证您的数据工厂 JSON 文件并将其“构建”到准备使用的 ARM 模板中。为了让它工作,你需要创建一个构建管道并使用 ADFUtilities NPM 包。这样就干净多了,手动步骤也消失了:)。
部署新的 Azure 数据工厂流程——图片来自微软文档
更多信息,查看官方文档这里。
如何使用 IaC 创建 Azure 数据工厂
基础设施作为代码
在你的项目中使用 IaC 有很多理由,你可以在这里查看。其中之一是基础设施作为代码是实现您的环境的最简单快捷的方式。所以,既然我们想保持 ADF 部署简单,为什么不使用它呢:)?
在这个例子中,我将使用 Bicep 模板来部署我们的数据工厂。如果 Bicep 对你来说是新的,它基本上是一种 DSL(领域特定语言),让 ARM 模板用户更容易使用。
Bicep 对 VS 代码有很好的扩展——图片来自微软文档
在这篇文章中,您可以查看如何使用 git 集成为数据工厂创建 Bicep 文件,该文件将用于部署 ADF。
它将在你的 Azure 数据工厂和你的 git repo 之间创建一个链接(它在 Azure DevOps 和 GitHub 上工作),所以当你在你的数据工厂中创建一个管道时,它也将被版本化到 git repo 中。
Git 储存库
知识库结构
回购结构将取决于每个项目。最佳实践之一是在同一个 repo 中保留部署项目所需的所有代码。因此,我喜欢创建一个结构,其中有组件的名称,并且下面总是有一个“src”文件夹。在这种情况下,我们将把 src 文件夹作为 git 集成过程中的“根文件夹”。
存储库结构—按作者分类的图像
构建 ARM 模板所需的文件
一些文件是必要的,在我们的回购生成模板。这些文件需要添加到 src 文件夹中,在构建阶段会被引用。
在 src 文件夹中创建 package.json 文件,它包含将用于构建 ADF 工件的包的元数据。
在同一个文件夹中,创建包含以下内容的 publish_config.json 文件。这不会影响 ARM 模板的生成,但是运行构建是必要的:
最后一个文件是 ARM-template-Parameters-definition . JSON。我不会进入细节,因为它需要一个专门的职位。对于初始版本,您可以创建以下内容:
在创建 git integrate 和所有必要的文件之后,这就是你的回购看起来的样子:
Azure 数据工厂的存储库结构—按作者分类的图片
如何为 Azure 数据工厂创建构建 YAML 管道
毫无疑问,管道作为代码将是管道定义的未来,具有版本控制和可重用性的能力。
变量
第一个必要的配置是变量。它们将被用于以后的构建和发布。
构建阶段最重要的变量是:
- 这是 src 目录。必须有上面提到的所需文件。
- dataFactoryResourceId -用您的 ADF 的资源 Id 填充它。这是一个好主意,使其参数化,以在不同的环境中工作
构建和部署变量—按作者分类的图像
构建数据工厂
如上所述,我们需要在构建过程中使用 ADFUtilities NPM 包。
在前两个任务中,NodeJS 是在构建代理中配置的。注意我们在变量部分提到的 workingDir 变量。
在最近的两个任务中,我们调用 NPM 包来验证和“构建”我们的数据工厂,并生成 ARM 模板。在最后一个任务中,“工件”是相对输出目录。这意味着它将是 ARM 模板的输出目录。
为 Azure 数据工厂构建任务—按作者分类的图片
在接下来的任务中,我们将把 ARM 模板从输出复制到暂存目录,并将 bicep 文件“构建”到 ARM 模板中。这些将用于创建 Azure 数据工厂工作区。
为 Azure 数据工厂构建任务—按作者分类的图片
在运行构建管道之后,您将拥有将在部署阶段使用的工件:
Azure 数据工厂工件——作者图片
Azure 数据工厂 ARM 模板—作者图片
如何为 Azure 数据工厂创建发布 YAML 管道
为了部署数据工厂,我们使用运行一次策略。它将消耗在构建阶段创建的工件
发展
当在开发环境中启用 git 集成时,因为代码是在工作区中生成的,所以不需要在这个环境中发布。它将只部署使用基础设施作为代码模板的环境。它还包含构建阶段的依赖项。
开发环境—作者图片
UAT 和生产
在 UAT,我们依赖发展环境。在生产方面,依赖于 UAT。在这些阶段,我们需要部署基础架构和代码,我们将使用预部署和部署作业:
部署前阶段—作者提供的图像
部署阶段—按作者排列的图像
在运行时,它将首先在预部署阶段使用 Bicep 文件创建基础设施,然后部署在构建阶段生成的工件。这是最后的结果:
部署管道—按作者分类的图片
关键要点
部署 Azure Data Factory 的策略不止一种,我已经尝试了其中的大部分,它们工作得非常好,但在我看来,这是实现完全自动化部署的最简单、最干净的方法。
下面您可以查看用于部署它的完整 YAML。你也可以在我的 GitHub repo 中查看其他 Azure DevOps YAML 模板示例:devo psnights/azuredevops-YAML-quick start-Templates(github.com)
希望能有用!
基于容器映像构建的 AWS Lambda 的 Azure DevOps CI/CD 管道
原文:https://towardsdatascience.com/azure-devops-pipelines-with-aws-toolkit-and-docker-cd619ebce375?source=collection_archive---------5-----------------------
Azure DevOps 中的 CI/CD 管道介绍,用于自动执行使用 docker 容器构建的 AWS Lambda 的构建过程。
Jean-Philippe Delberghe 在 Unsplash 上拍摄的照片
介绍
我最近的文章关注了 AWS 中一个相当新的功能,即通过容器映像构建 AWS Lambda。
- 如何为数据科学构建 AWS Lambda
- 如何构建算法交易的 AWS Lambda
来自 AWS 控制台的图像
这一新功能使得打包 AWS Lambda 所需的所有代码依赖项变得非常容易,而且就在 Lambda 的源代码旁边。这也消除了将代码从您最喜欢的 IDE 中复制并粘贴到 AWS 控制台中的倾向,并使事情变得无序。您的源代码现在成为部署到 AWS 中的所有代码的根,这使得事情变得非常顺利和有条理。
当我开始看到用容器映像构建我的 AWS lambda 的美妙之处时,我并不热衷于通过命令行进行维护,如果我对 docker 文件或包含 AWS lambda 代码的文件进行任何更改,这就是我最初维护代码部署的方式。所以,我开始研究 CI/CD 管道。
CI/CD 代表:
- CI-持续集成
- CD-连续部署
参见此文章了解更多信息。
有很多不同的工具可以用来构建 CI/CD 管道,但我决定使用 Azure DevOps,因为我对该工具很熟悉。自由层允许创建一个 CI/CD 管道。Jenkins是一个非常受欢迎的开源解决方案。Azure DevOps 与 AWS 合作创建了一个工具包,使得创建构建管道变得非常容易。
步骤 1:使用版本控制分发服务器组织您的代码
有许多不同的版本控制发行商。只要确保你有办法把你的代码连接到 Azure DevOps。出于本教程的目的,我们将构建一个 docker 文件,并更新已经内置在 AWS 中的 AWS Lambda。要跟进,请确保您已经完成了这些步骤。如果您在这些方面需要任何帮助,请随意阅读我之前的两篇关于如何构建 AWS Lambda 的文章。
步骤 2:创建 Azure DevOps 帐户
这里有一个开始使用的链接。这是免费的,如果你有一个 Github 帐户,你可以使用它来加快这个过程。
Azure DevOps 服务|微软 Azure
步骤 3:创建您的存储库
根据代码存储的位置和方式,这一步可能会因人而异。总体目标是在 Azure DevOps 中连接或建立代码存储库,以便您的管道可以访问构建过程所需的文件。
这可以在左侧面板的 Repos 部分找到。
来自 Azure DevOps 的回购部分
您可以从 Azure DevOps 的这个部分创建一个新的存储库、导入一个存储库并管理您的存储库。
Azure DevOps 中的存储库选项
第四步:创建新的管道
导航到左侧面板上的管道选项。选择底部的“使用经典编辑器”。
Azure DevOps 中的新管道构建
然后,您将选择代码所在的位置,以及您想要从哪个存储库和分支进行构建。
连接到 Azure DevOps 中的存储库
接下来,将提示您选择一个模板。选择顶部的“空工单”。
在这里,您将能够自动化构建 docker 映像、将其推送到 AWS ECR 以及基于更改更新 lambda 的整个过程。整个过程大约需要 4 分钟。
在 Azure DevOps 中创建管道
首先,我们将使用构建 docker 映像的模板来构建 docker 映像。单击代理作业 1 旁边的+。
Azure DevOps 中的 Docker 构建
添加完成后,点击即可开始。
Docker 图像说明
需要注意一些事情:
- 确保将任务版本更改为*0。
- 确保您拥有 docker 文件的正确路径。您可以使用输入旁边的省略号在 repo 中找到它。
- 在图像名称上,它必须与您在 ECR 中为标签使用的名称相匹配。在我以前的文章中,我将其标记为 lambda_dependencies。
AWS 中的 ECR 存储库名称
我们现在将通过单击代理作业旁边的+添加下一个任务。这一次,我们将添加一个作业,将新更新的 docker 映像推送到云中。
来自 Azure DevOps 的 ECR 推送
AWS 工具包使得使用所有 AWS 服务变得非常容易。您所要做的就是用您的访问令牌连接这两个服务
ECR 推送构建创建
在显示+New 的地方,您将添加您的 AWS 凭证。
Azure DevOps 中的 AWS 凭据
最后,我们将添加另一个作业并找到 AWS CLI 任务。这将用于用最新版本的 docker 映像更新我们的 lambda。
Azure DevOps 中的 AWS CLI 任务
AWS CLI 允许您调用您想要的任何命令和子命令。这只是完成工作的一个简单方法。
在 Azure DevOps 中设置 AWS CLI
需要对典型的 CLI 命令进行一点转换,比如从一开始就删除 AWS,并像命令/子命令/和参数一样进行拆分。
当你完成时,事情应该是这样的。
完成的管道
现在,您已经准备好对其进行测试,并通过点击 Save 和 Queue 来查看神奇的事情发生了。拿些爆米花。
步骤 5:测试构建管道
您可以通过保存编辑和排队来手动触发构建管道。Azure DevOps 在快速浏览构建方面做得很好。如果您单击代理作业 1,您可以看到幕后实际发生的情况。(魔术)
Azure DevOps 中的构建摘要
代理作业 1 将向您显示日志以及管道在其进程中所处的位置。整个过程大约需要 4 分钟。
构建日志
管道完成后,您的屏幕将显示作业进展情况的总体统计数据。
成功
此时,你应该庆祝一下!😃
步骤 6:决定什么应该触发构建管道
在管道创建面板中,有一个触发器部分。CI/CD 的目的是持续集成和部署,因此下面显示了如何实现这一点。您可以在 repo 中选择一个分支,以便在每次提交该分支时触发构建管道。还有一些其他选项,比如制定一个时间表,或者让它在不同的构建完成时触发。我的偏好,尤其是在云中工作时,是在每次提交后构建。它让我的代码在我的机器上和云中保持干净和最新。
Azure DevOps 中的触发器管道
第七步:坐下来,放松一下,下次再做承诺
每当我自动化一些东西时,我总是需要花一些时间放松和享受我的好工作。
结论
使用容器映像构建 AWS Lambda 函数的能力改变了游戏规则。将它与 CI/CD 配对可以确保您的包依赖项从 docker 文件同步到本地写到云中的 lambda 函数。我希望你喜欢这个教程,并且它可以让你在每次修改你的 lambdas 时,不用再通过命令行来维护你的 docker 镜像。
干杯。
面向机器学习工程师的 Azure
原文:https://towardsdatascience.com/azure-for-machine-learning-engineers-7c3ae416ea0f?source=collection_archive---------30-----------------------
了解 Azure 提供的所有不同的人工智能服务,以及何时应该使用它们
马库斯·温克勒在 Unsplash 上的照片
介绍
随着越来越多的公司决定将其内部数据中心迁移到云中,云技能现在变得越来越重要。
2020 年,微软 Azure 被宣布为增长最快的云提供商[1],因此我决定挑战自己,了解更多关于他们的数据科学服务,并完成他们的 Azure 数据科学家认证。
https://www.credly.com/badges/a91b0677-0a13-433e-a19b-cb06add00a9a
在本文中,我们将介绍一些 Azure key 机器学习服务,以及它们如何相互比较,以创建完整的人工智能解决方案。如果您有兴趣了解更多关于云计算和大数据系统的基础知识,可以在我以前的文章“数据科学家的云基础”和“大数据分析:Spark 和 Hadoop”中找到更多信息。
Azure 服务
Azure 提供了 4 个不同的抽象级别,可以用来创建端到端的机器学习解决方案:
- Azure 应用人工智能服务
- Azure 认知服务
- Azure 机器学习
- 人工智能基础设施
Azure 应用人工智能服务
在这个层面上,Azure 提供了一套专门的人工智能服务,这些服务是根据特定的业务场景设计的。这些类型的服务建立在 Azure 认知服务 API 之上,以便为最终用户提供不同类型的预制模型,这些模型可以在特定的业务环境中使用,几乎没有任何形式的设置要求。应用人工智能服务的一些例子是:
- Azure Form Recognizer: 从文档集合中自动提取知识,并以结构化数据格式输出结果,该格式能够提供多条信息,例如:关系、边界框等。
- Azure Metrics Advisor: 执行时序数据的监控和异常检测,以便从数据中自动计算度量并驱动决策。
- Azure Cognitive Search: 使使用人工智能排名功能快速查找和探索大规模组织内可用的内容成为可能。
- Azure Bot 服务:利用预先构建的自然语言模型来快速构建对话机器人。Azure Bot Service Composer 另外提供了一个可视化界面,以便尽可能容易地创建和测试您的虚拟代理。
Azure 认知服务
认知服务是一个可定制的 API 集合,用于与视觉、语音、决策和语言相关的任务。利用这些 API,你就可以在你的应用中集成人工智能的能力,甚至不需要任何关于数据科学和机器学习的专业知识。可以通过使用许多不同的方法来利用 Azure 认知服务,例如:Azure 门户(主要的 Azure 用户界面)、Azure 命令行界面、SDK 库(用 C#、Java、JavaScript 和 Python 等语言)和 Azure 资源管理器模板。认知服务中可用能力的一些例子是:
- 语音到文本转换
- 语音翻译
- 说话人识别
- 异常检测
- 内容审核
- 使用 Bing 搜索新闻
- 物体识别
下面是一个简单的例子,展示了开始使用认知服务 API 是多么容易(图 1)。
图 1: Azure 认知服务计算机视觉应用编程接口(图片由作者提供)。
Azure 机器学习
Azure ML 是一个端到端的平台,可用于准备、构建、训练和部署您自己的机器学习模型和管道(而不是使用微软创建的预制模型)。为了使这成为可能,Azure 提供了图形界面(如拖放设计器和 AutoML 功能)和编码环境(如 Jupyter Lab ),以使用常见的开源库(如 Tensorflow、Keras、PyTorch、ONNX 等)开发您自己的模型
在同一环境中创建终端部署模型,可以遵循常见的 MLOps(机器学习→操作)实践,跟踪 ML 实验并监控它们在生产环境中的性能,以便在出现任何数据漂移时尽快做出反应。
Azure 机器学习提供的一些关键功能是:
- 数据标记
- 协作笔记本环境
- 用于时间序列预测、分类和回归的自动化机器学习工具
- 使用拖放工具创建 ML 管道
- 内置 MLOps 功能
- 内置模型可解释性可视化
下面是一个简单的例子,展示了 Azure 机器学习平台的不同部分(图 2)。
图 2: Azure 机器学习平台(图片由作者提供)。
人工智能基础设施
最后,Azure 还提供了不同的可扩展虚拟机,用户可以选择这些虚拟机来创建和运行他们的机器学习和数据科学项目。通过这种方式,用户能够完全控制他们的开发环境和他们想要使用的不同包。
此外,Azure 还提供特定于数据科学的虚拟机,这些虚拟机预打包了一些最常见的数据科学库(例如 TensorFlow、Keras、MLFlow 等)。
结论
总的来说,Azure 提供了一套完整的服务,可以用来在分析生命周期的任何阶段处理数据。除了微软的人工智能服务,Azure 还提供了一个市场,用户可以在这个市场上决定使用其他组织创建的人工智能服务,如 Azure Databricks(针对优化的 Apache Spark)、SAS Viya、DataRobot、Dataiku、H2O.ai 等
如果你有兴趣了解更多关于 AWS 等其他人工智能云提供商服务的信息,可以在我之前的文章“机器学习工程师的 AWS”中找到更多信息。
联系人
如果你想了解我最新的文章和项目,请通过媒体关注我,并订阅我的邮件列表。以下是我的一些联系人详细信息:
- 领英
- 个人网站
- 中等轮廓
- GitHub
- 卡格尔
文献学
[1]微软 Azure 是目前发展最快的云平台。他们有你可以满足的关键需求。TheNextWeb。访问地址:https://then extweb . com/news/Microsoft-azure 是发展最快的云计算平台,而他们已经得到了你可以满足的关键需求
引擎盖下的 Azure 机器学习:组件和架构
原文:https://towardsdatascience.com/azure-machine-learning-under-the-hood-components-and-architecture-abc0dd27b1fb?source=collection_archive---------26-----------------------
来源: Unsplash
Azure 机器学习(ML)是一个端到端的工具,用于管理机器学习和深度学习管道。它可以跨大型计算资源池自动进行培训,并帮助您在生产中部署模型和管理生产应用程序的推理。
当您在组织中采用 Azure ML 时,更深入地理解它的结构和组件是一个好主意。这篇文章旨在展示 Azure 机器学习的内部工作原理。
在简要回顾了它的功能之后,我将继续描述它的关键组件,包括工作空间、计算、实验和快照,并描述系统在训练你的机器学习模型时所经历的工作流程。
什么是 Azure 机器学习?
Azure Machine Learning (ML)提供的工具旨在帮助数据科学家构建、部署和训练他们的机器学习算法。你可以使用 Azure ML 来训练任何类型的机器学习模型,包括传统的机器学习、监督算法和非监督机器学习。
Azure ML 支持多种语言,包括 Python 和 R,以及一系列 SDK。你也可以利用 Azure ML 的 studio,它为无代码或低代码 ML 和深度学习(DL)模型提供了一个工作空间。
Azure ML 为端到端机器学习操作提供了许多工具,包括:
- Azure ML 的设计师——(预览版)提供了构建实验和部署管道的拖放模块。
- Jupyter 笔记本 —让您使用预制的示例笔记本或创建自己独特的笔记本。
- R 脚本或笔记本——让您在编写自己的代码库时使用 R SDK,或者在设计器中使用 R 模块。
- 多模型解决方案加速器 —(预览)基于 Azure ML,该解决方案使您能够构建、训练和管理成百上千的 ML 模型。
Azure ML 提供了更多的功能,比如机器学习 CLI 和
Visual Studio 代码扩展。该平台与 TensorFlow、PyTorch、Ray RLlib 等开源框架协同工作,用于强化学习等。它还集成了各种各样的外部库,如 Git 和 MLFlow。
Azure 机器学习组件
让我们来看看 Azure 机器学习生态系统的基本组件。
工作空间
工作区是 Azure 中的中心资源,它保存着您的机器学习管道和所有相关资源。它是以下方面的焦点:
- 管理用于训练和部署机器学习模型的资源
- 存储 Azure 机器学习管道使用和创建的资产
工作区包括工作区使用的其他 Azure 资源:Azure 容器注册表(ACR);Azure 存储帐户,用作工作区的默认数据存储。Azure 应用洞察,用于监控;和 Azure Key Vault,它存储用于执行模型的秘密。
计算
Azure Machine Learning 不仅管理模型,它还提供计算资源,您可以使用这些资源在训练和推理模式下运行它们。Azure ML 提供两种类型的计算资源:
计算实例
包括机器学习工具和环境的预配置 Azure 虚拟机(VM)。计算实例通常用作开发机器-在模型开发的早期阶段,您可以启动实例并立即开始运行笔记本电脑。或者,它们也可以用于运行模型的训练和推理。
计算集群
具有自动扩展能力的虚拟机集群。这些适用于大型培训操作,以及在生产中运行模型。当您通过 Azure ML 提交作业时,集群会自动扩展以提供作业所需的资源。
数据集和数据存储
Azure 数据集使得访问和使用你的数据变得容易。Azure ML 创建对您的数据的引用,以及其元数据的副本。数据不会复制到 Azure ML 中,而是保留在原处,因此没有额外的存储成本,也没有数据完整性和安全性的风险。
模型
在最简单的情况下,模型是接受输入并产生输出的代码。机器学习模型通常包括算法、输入数据集和影响算法如何生成输出或预测的超参数。经过一轮或多轮训练后,模型已经从输入数据集中“学习”了它可以学习的内容,并可以根据看不见的数据生成预测。
你可以将之前训练过的模型导入 Azure ML,或者引入新模型的代码,并使用 Azure ML 在 Azure cloud 中提供的计算上训练它。模型被注册为工作空间的一部分。
运行和实验
运行是训练脚本的一次执行。实验是一组运行。两者都存储为工作区的一部分。Azure 机器学习记录每次运行的数据,并保存实验中的信息。这包括:
- 执行元数据—时间戳、持续时间
- 您的培训脚本生成的任何指标
- 作为实验的一部分上传的或由训练脚本生成的任何输出文件
- 包含预运行脚本的文件夹的完整快照
管路可以有“子管路”,您可以将几个级别的管路嵌套在一起。这使您可以自动化复杂的培训程序。
快照
每次运行时,Azure ML 都会获取包含训练脚本的目录,对其进行压缩,并将其复制到计算目标。然后,该脚本在一个或多个计算目标上运行。作为实验的一部分,相同的压缩文件存储在运行记录中。
这提供了对在哪里运行了什么实验的完全可见性,并确保每次都一致地执行训练运行,这与在各种机器上复制和手动运行脚本的临时程序形成对比,后者容易出错且难以跟踪。
幕后:培训工作流程
了解 Azure 机器学习如何在幕后操作和训练模型可能会有所帮助。
每次在 Azure ML 中运行实验时,都会发生以下步骤:
- 请求运行,快照 ID 指向包含代码模型和训练脚本的目录的快照。
- Azure ML 启动,创建一个运行 ID 和一个机器学习服务令牌,计算目标可以在后面的阶段使用。
- 用户为运行选择一个计算目标——这可以是托管的目标(Azure ML 计算资源的两种类型之一),也可以是未托管的目标,它只是一个常规的虚拟机,用户已经在其上安装了机器学习环境。
数据流操作如下:
- 计算目标从密钥库中检索 SSH 凭证,密钥库是 Azure 订阅的一部分。
- Azure ML 管理代码被写到用户的 Azure Files 帐户下的文件共享中(了解 Azure Files 如何工作
- Azure ML 将快照下载到计算实例
- Azure ML 通常使用 Docker 容器在计算目标上设置所需的环境,并设置配置和环境变量。容器使用 Azure ML 管理代码启动,并运行用户的培训脚本。
- 当训练运行完成时,Azure ML 将指标从存储到 Cosmos DB。然后,您可以在 Azure ML 用户界面中看到从 Cosmos 数据存储中提取的结果。
来源:蔚蓝
结论
Azure Machine Learning 巧妙利用 Azure 服务和基础设施,为您提供真正的端到端机器学习工作流管理。我们讨论了 Azure ML 基础设施的关键组件,包括:
- 工作区 —由模型、计算资源和数据集组成的中央实体
- 数据集 —对存储在 Azure 中的机器学习数据集的引用
- 计算 — Azure 虚拟机或虚拟机集群,让您运行分布式培训
- 运行和实验 —用于管理和跟踪训练迭代的实体
学习操作整个过程可能需要一个学习曲线,但一旦您的组织开始大规模培训模型并通过一次点击将它们部署到用户,这将会带来回报。
Azure ML 和 DevOps 遇见泰坦尼克号
原文:https://towardsdatascience.com/azure-ml-and-devops-meets-titanic-6a0aa748d5a8?source=collection_archive---------14-----------------------
Azure Machine Learning 是一个云服务,用于加速和管理机器学习项目生命周期。它使您能够创建模型或使用从开源平台(如 Pytorch、TensorFlow 或 scikit-learn)构建的模型。Azure ML 补充了额外的 MLOps 工具,帮助您监控、重新训练和重新部署模型。
在这篇博文中,我想展示如何使用 Azure 机器学习笔记本和计算实例进行开发,使用集群进行培训,使用容器网站进行生产,来构建、培训和部署一个模型。对于这个演示,我们将使用泰坦尼克号乘客数据( Titanic.csv ),使用随机森林模型预测谁将幸存。
设置环境
如果你有一个 Azure 帐户,你可以去 Azure 门户网站创建一个机器学习工作区。你可以使用搜索栏找到机器学习,然后点击创建按钮。
图片由 Piethein Strengholt 提供
接下来,您需要填写项目细节,比如您的订阅 ID、资源组名称和工作区名称。你可以从基础开始,所以点击“查看+创建”。
图片由 Piethein Strengholt 提供
部署后,您可以使用资源组概述窗格检查所有新创建资源的结果。
图片由 Piethein Strengholt 提供
Azure 机器学习服务自带默认存储账号。在我们的演示中,您将使用这个默认的存储帐户来使我们的 Titanic 数据可用。点击存储账号,点击默认的 azureml-blobstore-xxx 容器,使用上传按钮上传你的 Titanic.csv 数据。
图片由 Piethein Strengholt 提供
在本演示中,您还需要使用存储帐户访问密钥。点击返回并转到默认存储帐户。在左侧点击“访问密钥”,点击“显示密钥”,并将密钥信息复制到一个安全的位置供以后使用。
服务主体认证
为了将机器学习工作流设置为自动化过程,我推荐使用服务主体认证。这种方法将身份验证从任何特定的用户登录中分离出来,并允许管理访问控制。
第一步是创建服务主体。首先选择 Azure Active Directory 和 App 注册。然后选择+New application,给你的服务主体起个名字,比如my-SVP-machine-learning。您可以保持其他参数不变。
图片由 Piethein Strengholt 提供
从您新创建的服务主体的页面中,复制应用程序 ID 和租户 ID ,因为稍后需要它们。然后选择证书&秘密,和+新客户秘密为你的密钥写一个描述,并选择持续时间。然后点击添加,将客户端机密的值复制到安全位置以备后用。
图片由 Piethein Strengholt 提供
最后,您需要授予服务主体访问 Azure ML 工作空间的权限。导航到资源组,导航到机器学习工作区的资源组。然后选择访问控制(IAM)并添加角色分配。对于角色,指定需要授予的访问权限级别,例如参与者。开始输入您的服务主体名称,找到后,选择它,然后单击 Save。
图片由 Piethein Strengholt 提供
Azure 机器学习
设置好一切后,我们就可以开始了。悬停回到机器学习服务并启动工作室。
图片由 Piethein Strengholt 提供
启动 studio 环境后,您将看到一个包含许多框和控件的概览屏幕。让我给你一个组件的高层次理解,以及它们如何一起工作,以协助建立,部署和维护机器学习模型的过程。
图片由 Piethein Strengholt 提供
- 一个工作区是集中所有服务和平台组件的地方。
- 一个计算目标是您用来运行您的培训脚本或托管您的服务部署的任何机器或一组机器(集群)。
- 数据集使访问和处理数据变得更加容易。通过创建数据集,可以创建对数据源位置的引用及其元数据的副本。
- 环境是对你的机器学习模型进行训练或评分的环境的封装。
- 一个实验是来自一个指定脚本的许多运行的分组。它总是属于一个工作区。提交运行时,您需要提供一个实验名称。
- 一次运行是训练脚本的一次执行。一个实验通常包含多次运行。
- 一个笔记本用来在集成的 Jupyter 笔记本服务器上编写和运行你自己的代码。
设置计算实例
为了开发新的模型,您需要有一个计算实例,这是一个包含为机器学习安装的多个工具和环境的容器。计算实例主要用于开发工作站。该计算实例还可以用作培训和推理作业的计算目标。在左侧,单击 compute 并创建一个新的计算实例。您现在可以保留默认设置,因此单击“Create”创建您的第一个计算实例。
图片由 Piethein Strengholt 提供
构建您的第一台笔记本电脑
让我们继续我们的旅程,开发我们的泰坦尼克号生存预测模型。您将通过使用 Jupyter 笔记本来完成此操作。点击“笔记本”和“新建”,然后选择创建新笔记本。左侧的文件夹和文件结构将类似于您在下图中看到的内容。点击+新建。在我的例子中,我输入 Titanic.ipny 作为我的第一个笔记本,但是你可以选择任何名字。请注意,这是为了开发和测试的目的。
图片由 Piethein Strengholt 提供
对于模型本身,我使用了来自 towardsdatascience.com 的预测泰坦尼克号乘客生存的文章。我用额外的配置增强了代码,以将流程与 Azure ML 紧密集成。让我们一行一行地浏览脚本:
# importing necessary librariesfrom azureml.core import Workspace, Datastore, Dataset, Experiment, Model
from azureml.data.dataset_factory import DataType# importing sklearn librariesimport sklearn
from sklearn import linear_model
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier
from sklearn import metrics
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
from sklearn.metrics import confusion_matrix
from sklearn.preprocessing import MinMaxScaler
from sklearn.tree import DecisionTreeClassifier
from sklearn import preprocessing# Useful for good split of data into train and test
from sklearn.model_selection import train_test_split# import pandas
import pandas as pd# linear algebra
import numpy as np# import re package
import re# import joblib
import joblib# import seaborn
import seaborn as sns# import matplotlib
%matplotlib inline
from matplotlib import pyplot as plt
导入所有必需的库需要第一个代码块。azureml.core 包是与我们的 azureml 工作空间进行通信所必需的。我们的模型需要其余的包,比如 sklearn。
# get existing workspace
ws = Workspace.from_config()# set connection string settings
blob_datastore_name='machinelearnin9342837683'
container_name=os.getenv("BLOB_CONTAINER", "azureml-blobstore-867fb2e1-6f13-4490-bc45-291d19912ec0")
account_name=os.getenv("BLOB_ACCOUNTNAME", "machinelearnin9763237684")
account_key=os.getenv("BLOB_ACCOUNT_KEY", "ExMnf3yB6usdSLi96wo53MMDA/QX5E6WnccJHAq1ECawHDDb5WI1ATw9UUqS3lgHQm69oKfNwWIrUtlSXZ1RQA==")# register blob storage account within AMLS
datastore = Datastore.register_azure_blob_container(workspace=ws,
datastore_name=blob_datastore_name,
container_name=container_name,
account_name=account_name,
account_key=account_key,
overwrite=True)# connect to the azure blob storage account
try:
datastore = Datastore.get(ws, blob_datastore_name)
print("Found Blob Datastore with name: %s" % blob_datastore_name)
except UserErrorException:
datastore = Datastore.register_azure_blob_container(
workspace=ws,
datastore_name=blob_datastore_name,
account_name=account_name, # Storage account name
container_name=container_name, # Name of Azure blob container
account_key=account_key,
protocol=http) # Storage account key
print("Registered blob datastore with name: %s" % blob_datastore_name)# attach Titanic.csv file
dataset = Dataset.Tabular.from_delimited_files(path=[(datastore, 'Titanic.csv')])
下一个代码块需要访问我们的工作区,并从您的存储帐户和容器中检索大量数据。此脚本中的凭据用于将存储帐户注册为新的数据存储(从您的安全位置复制粘贴访问密钥)。一旦连接上,你就可以删除这些行项目,因为 Azure ML 会进一步处理这个问题。这允许您不在脚本中放置任何凭据。现在,就让它这样吧。
# register Dataset as version 1
dataset.register(workspace = ws, name = 'titanic', create_new_version = True)
下一行项目是关于将该数据集注册为版本 1。
experiment = Experiment(ws, "TitanicExperiment")
run = experiment.start_logging(outputs=None, snapshot_directory=".")
下一步是你将注册你的泰坦尼克号实验。这很有用,因为通过实验,您可以查看所有使用的输入数据集、训练和测试数据、结果、日志记录信息等等。让我们跳到机器学习模型本身。
# convert dataset to pandas dataframe
titanic_ds = dataset.to_pandas_dataframe()print("Examine titanic dataset")
titanic_ds.info()print("Show first records")
titanic_ds.head(10)# convert ‘Sex’ feature into numeric
genders = {"male": 0, "female": 1}
data = [titanic_ds]
for dataset in data:
dataset['Sex'] = dataset['Sex'].map(genders)# since the most common port is Southampton the chances are that the missing one is from there
titanic_ds['Embarked'].fillna(value='S', inplace=True)# convert ‘Embarked’ feature into numeric
ports = {"S": 0, "C": 1, "Q": 2}
data = [titanic_ds]
for dataset in data:
dataset['Embarked'] = dataset['Embarked'].map(ports)# convert ‘Survived’ feature into numeric
ports = {False: 0, True: 1}
data = [titanic_ds]
for dataset in data:
dataset['Survived'] = dataset['Survived'].map(ports)# a cabin number looks like ‘C123’ and the letter refers to the deck.
# therefore we’re going to extract these and create a new feature, that contains a persons deck.
deck = {"A": 1, "B": 2, "C": 3, "D": 4, "E": 5, "F": 6, "G": 7, "U": 8}
data = [titanic_ds]
for dataset in data:
dataset['Cabin'] = dataset['Cabin'].fillna("U0")
dataset['Deck'] = dataset['Cabin'].map(lambda x: re.compile("([a-zA-Z]+)").search(x).group())
dataset['Deck'] = dataset['Deck'].map(deck)
dataset['Deck'] = dataset['Deck'].fillna(0)
dataset['Deck'] = dataset['Deck'].astype(int)# drop cabin since we have a deck feature
titanic_ds = titanic_ds.drop(['Cabin'], axis=1)# fix age features missing values
data = [titanic_ds]
for dataset in data:
mean = titanic_ds["Age"].mean()
std = titanic_ds["Age"].std()
is_null = dataset["Age"].isnull().sum()
# compute random numbers between the mean, std and is_null
rand_age = np.random.randint(mean - std, mean + std, size = is_null)
# fill NaN values in Age column with random values generated
age_slice = dataset["Age"].copy()
age_slice[np.isnan(age_slice)] = rand_age
dataset["Age"] = age_slice
dataset["Age"] = titanic_ds["Age"].astype(int)# convert ‘age’ to a feature holding a category
data = [titanic_ds]
for dataset in data:
dataset['Age'] = dataset['Age'].astype(int)
dataset.loc[ dataset['Age'] <= 11, 'Age'] = 0
dataset.loc[(dataset['Age'] > 11) & (dataset['Age'] <= 18), 'Age'] = 1
dataset.loc[(dataset['Age'] > 18) & (dataset['Age'] <= 22), 'Age'] = 2
dataset.loc[(dataset['Age'] > 22) & (dataset['Age'] <= 27), 'Age'] = 3
dataset.loc[(dataset['Age'] > 27) & (dataset['Age'] <= 33), 'Age'] = 4
dataset.loc[(dataset['Age'] > 33) & (dataset['Age'] <= 40), 'Age'] = 5
dataset.loc[(dataset['Age'] > 40) & (dataset['Age'] <= 66), 'Age'] = 6
dataset.loc[ dataset['Age'] > 66, 'Age'] = 6# create titles
data = [titanic_ds]
titles = {"Mr": 1, "Miss": 2, "Mrs": 3, "Master": 4, "Rare": 5}for dataset in data:
# extract titles
dataset['Title'] = dataset.Name.str.extract(' ([A-Za-z]+)\.', expand=False)
# replace titles with a more common title or as Rare
dataset['Title'] = dataset['Title'].replace(['Lady', 'Countess','Capt', 'Col','Don', 'Dr',\
'Major', 'Rev', 'Sir', 'Jonkheer', 'Dona'], 'Rare')
dataset['Title'] = dataset['Title'].replace('Mlle', 'Miss')
dataset['Title'] = dataset['Title'].replace('Ms', 'Miss')
dataset['Title'] = dataset['Title'].replace('Mme', 'Mrs')
# convert titles into numbers
dataset['Title'] = dataset['Title'].map(titles)
# filling NaN with 0, to get safe
dataset['Title'] = dataset['Title'].fillna(0)# drop name and title column since we have create a title
titanic_ds = titanic_ds.drop(['Name','Ticket'], axis=1)# default missing fare rates
titanic_ds['Fare'].fillna(value=titanic_ds.Fare.mean(), inplace=True)# convert fare to a feature holding a category
data = [titanic_ds]
for dataset in data:
dataset.loc[ dataset['Fare'] <= 7.91, 'Fare'] = 0
dataset.loc[(dataset['Fare'] > 7.91) & (dataset['Fare'] <= 14.454), 'Fare'] = 1
dataset.loc[(dataset['Fare'] > 14.454) & (dataset['Fare'] <= 31), 'Fare'] = 2
dataset.loc[(dataset['Fare'] > 31) & (dataset['Fare'] <= 99), 'Fare'] = 3
dataset.loc[(dataset['Fare'] > 99) & (dataset['Fare'] <= 250), 'Fare'] = 4
dataset.loc[ dataset['Fare'] > 250, 'Fare'] = 5
dataset['Fare'] = dataset['Fare'].astype(int)# create not_alone and relatives features
data = [titanic_ds]
for dataset in data:
dataset['relatives'] = dataset['SibSp'] + dataset['Parch']
dataset.loc[dataset['relatives'] > 0, 'not_alone'] = 0
dataset.loc[dataset['relatives'] == 0, 'not_alone'] = 1
dataset['not_alone'] = dataset['not_alone'].astype(int)# create age class
data = [titanic_ds]
for dataset in data:
dataset['Age_Class']= dataset['Age']* dataset['Pclass']# create fare per person
data = [titanic_ds]
for dataset in data:
dataset['Fare_Per_Person'] = dataset['Fare']/(dataset['relatives']+1)
dataset['Fare_Per_Person'] = dataset['Fare_Per_Person'].astype(int)# convert all data to numbers
le = preprocessing.LabelEncoder()
titanic_ds=titanic_ds.apply(le.fit_transform)print("Show first records of all the features created")
titanic_ds.head(10)
在这个演示中,我们将创建一个模型来预测泰坦尼克号沉没时谁会幸存(或死亡)。大块提供了准备数据的所有代码。总之,您将许多特征转换为数字和聚合数据,以提高模型的准确性。例如,您将年龄转换为一个类别,并根据名称编辑标题。此外,您还修复了丢失的值,并导出了其他要素的数据。最后一行显示了创建的所有特征的前 10 行。
# convert all data to numbers
le = preprocessing.LabelEncoder()
titanic_ds=titanic_ds.apply(le.fit_transform)# split our data into a test (30%) and train (70%) dataset
test_data_split = 0.30
msk = np.random.rand(len(titanic_ds)) < test_data_split
test = titanic_ds[msk]
train = titanic_ds[~msk]# drop ‘PassengerId’ from the train set, because it does not contribute to a persons survival probability
train = train.drop(['PassengerId'], axis=1)X_train, X_test, Y_train, Y_test = train_test_split(train.drop("Survived", axis=1), train["Survived"],test_size=0.4,random_state=54,shuffle=True)
接下来的几行确保所有数据都被转换成数字。接下来,您将我们的完整数据集分成测试和训练数据集。在我们的例子中,所有的乘客信息被合并到一个大的数据集中。接下来,数据被拆分为用于训练和验证模型的数据。从概念上讲,你可以看到我们在下面做了什么:
来源
# save data
np.savetxt('download/train.csv', train, delimiter=',')
np.savetxt('download/test.csv', test, delimiter=',')
np.savetxt('download/X_train.csv', X_train, delimiter=',')
np.savetxt('download/Y_train.csv', X_train, delimiter=',')
np.savetxt('download/X_test.csv', X_train, delimiter=',')
np.savetxt('download/Y_test.csv', X_train, delimiter=',')# upload data to blob storage account
datastore.upload_files(files=['download/train.csv', 'download/test.csv', 'download/X_train.csv', 'download/Y_train.csv', 'download/X_test.csv', 'download/Y_test.csv'],
target_path='titanic_data/',
overwrite=True)# attach all datasets
dataset_train = Dataset.Tabular.from_delimited_files(path=[(datastore, 'titanic_data/train.csv')])
dataset_test = Dataset.Tabular.from_delimited_files(path=[(datastore, 'titanic_data/test.csv')])
dataset_X_train = Dataset.Tabular.from_delimited_files(path=[(datastore, 'titanic_data/X_train.csv')])
dataset_Y_train = Dataset.Tabular.from_delimited_files(path=[(datastore, 'titanic_data/Y_train.csv')])
dataset_X_test = Dataset.Tabular.from_delimited_files(path=[(datastore, 'titanic_data/X_test.csv')])
dataset_Y_test= Dataset.Tabular.from_delimited_files(path=[(datastore, 'titanic_data/Y_test.csv')])# register datasets as version 1
dataset_train.register(workspace = ws, name = 'train', create_new_version = True)
dataset_test.register(workspace = ws, name = 'test', create_new_version = True)
dataset_X_train.register(workspace = ws, name = 'X_train', create_new_version = True)
dataset_Y_train.register(workspace = ws, name = 'Y_train', create_new_version = True)
dataset_X_test.register(workspace = ws, name = 'X_test', create_new_version = True)
dataset_Y_test.register(workspace = ws, name = 'Y_test', create_new_version = True)
为了在 Azure ML 中存储和管理我们所有的数据,你需要使用下面几行代码。在稍后阶段,您将注册您的版本化模型并将其链接到此版本化数据,包括所有其他元数据,如性能指标、准确性等。这对展示证据和保持控制很重要。
# Random Forest
random_forest = RandomForestClassifier(n_estimators=100)
random_forest.fit(X_train, Y_train)# Save model as pickle file
joblib.dump(random_forest, "outputs/random_forest.pkl")# Predict and get result
Y_prediction = random_forest.predict(X_test)
random_forest.score(X_train, Y_train)
acc_random_forest = round(random_forest.score(X_train, Y_train) * 100, 2)# show the important features for the classification
feature_imp = pd.Series(random_forest.feature_importances_, index=X_train.columns).sort_values(ascending=False)
plt.figure(figsize=(10,6))
sns.barplot(x=feature_imp, y=feature_imp.index)
# Add labels to your graph
plt.xlabel('Feature Importance Score')
plt.ylabel('Features')
plt.title("Visualizing Important Features")
plt.tight_layout()
接下来,您将使用随机森林模型,这是一种受监督的机器学习算法。它创建了一个决策树的森林,并使其具有一定的随机性。此外,您会看到一个显示模型中最主要特征的图。
# register model within workspace
model_random_forest = Model.register(workspace=ws,
model_name='random_forest',
model_path='outputs/random_forest.pkl',
model_framework=Model.Framework.SCIKITLEARN,
model_framework_version=sklearn.__version__,
sample_input_dataset=dataset_X_train,
sample_output_dataset=dataset_Y_train,
description='Titanic survival prediction using random forest.',
datasets = [('train',dataset_train),('test',dataset_test),('X_train',dataset_X_train),('Y_train',dataset_Y_train),('X_test',dataset_X_test),('Y_test',dataset_Y_test)],
tags={'type': 'regression'})
使用上面的代码行,您将在 Azure ML 中注册您的模型。模型本身被序列化为 pickle 文件,这意味着它已经被转储以供以后使用。此外,您还将模型链接到了我们的训练数据集。
# log plot image
run.log_image('Feature Importance Score', plot=plt)# complete run
run.log("Random Forest accuracy", acc_random_forest)
run.complete()
最后,您记录我们模型的准确性,并将运行标记为完成。
MLOps 功能
在典型的开发流程中,开发模型只是第一步。最大的努力是让一切都准备好投入生产。这包括数据收集、数据准备、培训、服务和监控。您只是执行了这些最初的步骤,并在 Azure ML 中存储了所有相关的元数据信息。例如,您可以看到下面的绘图图像,它和我们的模型的其他信息,如实验、版本化数据集、日志记录信息等等。
图片由 Piethein Strengholt 提供
最大的好处是,您可以将模型和实验与可靠且可重复的结果关联起来。团队成员可以轻松地观察、解释和改进模型行为和准确性,因为所有信息都集中在一个中心位置。
利用计算集群进行纵向扩展
下一步是在集群上训练模型,这对计算密集型处理很有用。例如,当使用大型数据集或复杂计算时。这项工作可以分配给几台机器。在计算部分,您可以创建和配置集群。在本演示中,您可以通过单击“下一步”来使用标准配置。
图片由 Piethein Strengholt 提供
为了向我们的集群提交作业,您需要设置一些额外的脚本。第一个脚本名为 setup.sh ,用于安装所需的软件包。
#!/bin/bash
pip install azureml-sdk[notebooks]
pip install azureml-core
pip install azure-storage-blob
pip install joblib
第二个脚本叫做 script.py ,它与我们的 Azure ML 工作空间交互,用于提交我们的作业。让我们检查下面的代码块。
from azureml.core import ScriptRunConfig, Experiment
from azureml.core import Workspace
from azureml.core.compute import ComputeTarget, AmlCompute
from azureml.core.compute_target import ComputeTargetException
from azureml.core import Environment
from azureml.widgets import RunDetails
from azureml.core.authentication import ServicePrincipalAuthenticationsvc_pr = ServicePrincipalAuthentication(
tenant_id="72f988bf-FDf1-41af-9Ab-2d7cd011Ab47",
service_principal_id="ef861c6f-b0FA-4895-8330-9b90Aea3bd1",
service_principal_password="~_V846CU~R36tP.UV4Sz78TtUAaeyF40C")ws = Workspace(
subscription_id="3466fg5d-afda-4533-b3e2-c498g86a45aa",
resource_group="rg-machinelearning",
workspace_name="machinelearning",
auth=svc_pr
)# create or load an experiment
experiment = Experiment(ws, 'TitanicExperiment')# create or retrieve a compute target
cluster = ws.compute_targets['cluster1']# create or retrieve an environment
env = Environment.get(ws, name='AzureML-sklearn-0.24.1-ubuntu18.04-py37-cpu-inference')# configure and submit your training run
src = ScriptRunConfig(source_directory='.',
command=['bash setup.sh && python train.py'],
compute_target=cluster,
environment=env)run = experiment.submit(config=src)
run
你还记得服务原则账户吗?服务原则帐户信息来自您之前使用的帐户信息。这允许您的集群与 Azure ML 进行交互。另一个重要的方面是推论。我正在使用一个预构建的 Docker 容器映像,它包含最流行的机器学习框架和 Python 包。
另一个重要方面是命令参数。我用它来传入 setup.sh 和 train.py 脚本。setup.sh 脚本安装所有必需的软件包。在我的示例机器学习模型脚本中, train.py 引用了与 Titanic.ipny 相同的代码。在存储这些脚本并运行 script.py 之后,应该向集群提交一个作业,如下图所示。
图片由 Piethein Strengholt 提供
最大的好处是您可以轻松地纵向扩展。从在计算实例上开发的模型过渡到高性能的弹性集群相对容易。这只是用另一个(小的)脚本来包装你的实验。
使用 Azure ML 端点操作您的模型
最后一步是操作您的模型,在我们的例子中是将模型部署为 web 服务。在 Azure ML 中,您可以部署实时或批处理服务。要将您的模型部署为实时 web 服务,请使用下面的代码:
# set service name
service_name = 'titanic-service'
service = Model.deploy(ws, service_name, [model_random_forest], overwrite=True)
service.wait_for_deployment(show_output=True)
titanic-service 是指服务名。在我们的例子中, model_random_forest 指的是您在我们的工作空间中注册的模型。成功部署后,您应该在端点部分看到您的服务:
图片由 Piethein Strengholt 提供
这个 REST 端点可以与任何其他系统集成。让我们通过使用 postman 来验证服务。
图片由 Piethein Strengholt 提供
我通过提交 13 个数据属性进行 API 调用。第二和第三个属性是性别和年龄。数字 1 和 1 对应于年龄小于或等于 11 岁的女性。提交我们的请求后,你可以看到泰坦尼克号幸存的概率是 88.5%。
图片由 Piethein Strengholt 提供
如果您将性别和年龄更改为 0 和 6,这些值对应于年龄在 44 和 66 之间的男性。幸存的概率,如你所见,下降到了 42.0%。
结论
我们刚刚展示的是一个从数据收集和准备到模型部署和运作的自动化 ML 生产环境。合乎逻辑的下一步是将我们的所有代码存储到一个版本化的 Git 存储库中,并使用一个持续集成(CI)流程来自动化管道启动、培训和测试自动化、审查和批准流程。
代码仓库:https://github . com/pietheinstrengholt/Azure-ML-and-devo PS-meets-Titanic
Azure Synapse 分析—简介
原文:https://towardsdatascience.com/azure-synapse-analytics-introduction-34d4a0a81c0?source=collection_archive---------4-----------------------
关于 Azure Synapse Analytics 的内容、原因和方式的简要概述
信用:ISTOCKPHOTO
介绍
Synapse Analytics 是来自 Microsoft Azure 的集成平台服务,它结合了数据仓库、数据集成、ETL 管道、分析工具和服务、大数据功能的规模、可视化和仪表板的功能。
微软 Azure Synapse 分析逻辑架构。鸣谢:微软 Azure
该平台支持企业范围的决策分析需求。工具、过程和技术支持跨维度的分析能力: 描述性 & 诊断分析 通过利用其数据仓库能力,借助 T-SQL 查询收集业务见解。它通过利用与 Apache Spark、Databricks、Stream Analytics 的集成,利用 预测性 和 规定性 分析功能,为组织的决策提供支持。
它是如何工作的
Azure Synapse Analytics 是一站式分析解决方案,提供以下功能:
- SQL 服务器的专用池,称为 Synapse SQL,是整个分析数据存储的主干,这些为在其下实施数据仓库提供了必要的基础设施。使工程师能够根据他们现有的经验执行 T-SQL 查询。
它还支持 empower 使用无服务器模式处理计划外或临时工作负载,通过使用数据虚拟化允许从他们自己的数据存储中释放洞察力,而无需通过建立数据仓库的正式流程。** - 使用 Synapse 管道的 ETL 和来自不同来源的数据集成功能使组织能够高效地搅动数据以用于仓储和分析目的。可重用的工作流和管道编排功能易于适应。对 Hadoop 和 DataBricks 的 HDInsight 等大数据计算服务的支持使其成为一个更强大的 ETL 工具。
- 借助面向 Azure Synapse 的 Apache Spark 实现大数据工作负载和机器学习解决方案的开发。该平台通过支持大规模可扩展的高性能计算资源来处理大数据工作负载。SparkML 算法和 Azure ML 集成使其成为训练机器学习工作负载的完整解决方案。
- 使用 Synapse Link 从运营数据源提供实时运营分析。
哪里合适?
Azure Synapse Analytics 最常见的业务用例有:
- 数据仓库:集成各种数据平台和服务的能力。
- 描述性/诊断性分析:对 Synapse 数据库使用 T-SQL 查询来执行数据探索和发现。
- 实时分析 : Azure Synapse Link 支持与不同的运营数据源集成,以实施实时分析解决方案。
- 高级分析:通过利用 Azure 数据块,使用 Azure 数据块来支持决策。
- 报告&可视化:与 PowerBI 集成,增强业务决策能力。
**https://www.linkedin.com/in/p-jainani/
功能演练
假设您已经在 Azure 订阅中 设置并配置了Azure Synapse 分析工作区。
Synapse Analytics Workspace — 鸣谢:MS Azure Synapse Analytics Studio
Azure Synapse Analytics workspace 的设置和配置超出了本文的范围。有关更多详细信息,请查看参考资料部分。
使用 Spark 加载和分析数据
- 从数据中心,浏览图库和
covid-tracking
数据集。 - 使用下面的数据集打开新的 Spark 笔记本。
演示屏幕截图—Ccreate Spark 笔记本。鸣谢:Azure Synapse 分析工作室女士
- 该笔记本包含以下默认代码,以及使用 Spark backbone framework 分析数据集的更多功能
## ---- ##
df = spark.read.parquet(wasbs_path)
display(df.limit(10))
一个演示的屏幕截图— 使用 Spark 分析数据集。鸣谢:Azure Synapse 分析工作室女士
分析无服务器 SQL 池中的数据
- 再次从数据中心加载示例数据集,但是这次创建一个新的 SQL 脚本,如下所示:
演示屏幕截图— 使用 SQL 脚本分析数据集。鸣谢:Azure Synapse 分析工作室女士
- 这将为您提供使用本机 T-SQL 查询分析数据集的自由脚本
演示的屏幕截图— 使用 SQL 脚本分析数据集。鸣谢:Azure Synapse 分析工作室女士
设置和集成管道
这个小演示将展示如何在 Azure Synapse 中集成管道任务
- 从 Synapse Analytics Studio 的 集成 中心选择 管道。
演示的屏幕截图—创建集成管道。鸣谢:Azure Synapse 分析工作室
- 一旦管道被实例化——你可以根据手头的问题添加工作流 活动 。
演示屏幕截图—设置管道活动。鸣谢:Azure Synapse 分析工作室
- 您可以添加触发条件来响应事件或手工执行管道工作流。同样,选择 监控中枢 ,选择 管道运行 监控任何管道执行进度。
演示的屏幕截图—探索 Synapse Studio 的显示器选项。鸣谢:Azure Synapse 分析工作室
集成链接服务
使用 Synapse Analytics Studio 集成和启用各种链接服务,例如 Power BI
- 使用 管理 枢纽查看已有的 关联服务
演示的屏幕截图—探索 Synapse Studio 的链接服务。鸣谢:Azure Synapse 分析工作室女士
- 此外,创建一个到 PowerBI 工作区的链接,以利用数据可视化和报告。
演示的屏幕截图—创建和设置 Synapse Studio 的链接服务。鸣谢:Azure Synapse 分析工作室**
结论
在这个关于 Azure Synapse Analytics 的简介中, 我已经浏览了浅水区,以了解 Azure 的这个托管服务的基本功能。
现在,您已经了解了什么是Synapse Analytics,为什么解决优化组织的目标非常重要,并且稍微了解了如何在各种分析用例中利用其功能。
希望你已经获得了一些见解,让我知道你的反馈和疑问。
与我连线LinkedIn进一步讨论**
**https://www.linkedin.com/in/p-jainani/
参考
[1]微软文档|Azure Synapse Analytics**
Azure Synapse 专用 SQL 池模式设计选项基准
原文:https://towardsdatascience.com/azure-synapse-dedicated-sql-pool-schema-design-options-benchmark-63ee1e0f1a19?source=collection_archive---------18-----------------------
理解大数据
通过基准测试证明的最佳实践集(dis)
介绍
MPP 引擎的市场非常广阔,云领域的大玩家也有不断发展的产品。因此,更好地了解它们的能力和表现真的很有趣。
让我们回顾一下 Azure 的 Synapse 专用 SQL Pool MPP 数据库平台,它是微软基于 PDW 设备的数据仓库的演进,旨在服务于数据仓库需求。
动机
该基准测试的动机是找到简单问题的简单答案:如何在基于经典星型模式构建的 Azure 专用 SQL 池上调整物理模式,使用现实的企业级数据量来回答最常见的分析查询。
基于 TPC-H 模式有一些不错的值得回顾的基准,例如由 Gigaom 执行的基准。最新的一个确实值得研究,但是,对我来说,它没有提供以下问题的答案:
- 索引调优和分布选项如何影响性能?
- 基数如何影响响应时间?
- 对于给定的数据量大小,将查询保持在 3-5 秒的响应时间间隔内需要多少资源
当前的基准旨在回答这些问题,并证明或否定一些一般性建议。
基准描述
数据模型
让我们考虑一个经典的星型模式,其中一个事实表被一组维度表包围
为了简化测试,事实表包含对不同大小的相同维度的引用。
要测试的查询
让我们将简单分析查询分为 3 个简单类别:
- 全范围/大范围/小范围扫描以及随机访问,根据等式和范围谓词进行适当过滤;
- 加入大表和(事实和尺寸)小表之间的操作;
- 大桌对大桌加入年代
基本数据
为了测试不同的配置文件,需要检查不同大小的输入表:
- 较小尺寸用 100 、 10K 、 100K 记录
- 较大尺寸: 1M、10M、和 100M 记录
- 事实表尺寸用 10M 、 100M 、 1B 记录
集群环境
已经执行了以下集群配置和准备工作:
- DW200c、DW1000c、DW3000c、DW6000c 容量/性能等级已使用;
- 没有并发查询,所有查询都是随后运行的;
- 查询在 xlargerc 资源类下运行,确保 70%的内存资源分配;
- 在对基于复制的数据分布类型的所有维度表运行基准查询之前,调用了索引重建;
- 参与查询的所有表的统计数据被更新;
- 结果集缓存被关闭;
- 在每次测试之前,运行以下代码:
DBCC DROPCLEANBUFFERS; DBCC FREEPROCCACHE;
- 显示的运行时间值是连续 5 次运行的平均值,不包括最小值和最大值。
专用 SQL 池模式设计选项
基准测试的目的是使用基于固定星型模式的逻辑数据模型在物理模式级别测试不同的选项。
因此,让我们考虑以下两个主要方向:索引和数据分布的选项:
索引:
- 默认聚集列存储索引,称为 CCI 向下文本
- 有序聚集列存储索引(有序 CCI 下文本)
- 聚集索引(非列索引)
- 次级 B 树索引
分配:
- 循环赛
- 混杂
- 复制
基准测试结果
测试#1:小型、大型和全表扫描(无连接)
在测试#1 的范围内,一组简单的过滤器查询正在扫描不同的数据集大小:
- 小定位记录对;
- 大—占整个表格的 10-30 %;
- 全扫描—分析整个表。
每个单独的测试都有一个特定的目标要验证。在基准测试期间运行的所有查询的列表可以在本文的最底部找到。
测试 1.1:默认 CCI 指数
第一个测试是在具有默认索引配置(聚集列存储索引)的表上执行的。以下是不同容量级别的结果:DW200c、DW1000c 和 DW3000c:
测试 1.1 结果图表。作者图片
观察 :
- 从 DW200c 性能级别开始,专用 SQL 池为大多数查询提供 3 秒内的响应时间。
- 例外情况是对非常大的表的查询,例如包含十亿行的表
- 有趣的是,与 DW200c 相比,查询“Small_Range_Dim_10M_02”在 DW1000c 上的时间更短。我认为这与以下事实有关:从 DW1000c 开始,群集开始拥有 2 个计算节点,这为节点间通信带来了一些开销,并导致此类查询的性能下降。
测试 1.2:默认 CCI 与订购 CCI
最近,Azure 引入了一个有趣的专用 SQL 池性能增强特性,称为有序聚集列存储索引。
乍一看,它可能会给人留下改变游戏规则的印象。但事实上,并不是这样。我推荐你阅读来自微软的文章,更好地理解它能带来显著利益的独特环境。
在当前测试的范围内,测试了基于时间戳的范围扫描,它覆盖了所有记录的 10%或 30%。表结构的 3 个选项已经过测试:
- 默认 CCI 指数
- "有序 CCI 1 索引-基于 order_timestamp 字段的有序 CCI 索引,结合基于同一 order_timestamp 字段的散列分布
- "有序 CCI 2 索引-基于 order_timestamp 字段的有序 CCI 索引,具有基于散列的分布,这与基于 order_id 字段的默认 CCI 索引中的分布相同
测试的查询模式:
**select** **count**(*), **sum**(total_amount),
**sum**(shipping_amount), **avg**(tax_amount)
**from** <fact_order_line_1B_with_different_index_config>
**where** order_timestamp **between** <range_of_different_size>
测试 1.2 结果图表。作者图片
观察 :
- 尽管有序的 CCI 1 可以为较小范围的扫描带来显著的性能优势,但是您应该为它创建理想的环境,这在现实生活中几乎是不可能的
- 一般来说,有序的 CCI 指数不会带来显著的好处
测试 1.3:聚集(非列存储)和 BTree 索引
专用 SQL 池可以灵活地选择不同类型的索引。除了默认的聚集列存储索引之外,还可以创建常用的聚集列存储索引。
所以理解什么时候值得使用它是很有趣的。
在测试范围内,相同的查询在一个维度表上运行,该维度表有 1000 万行,构建在默认 CCI 索引或聚集(非列存储)索引上,并在其上构建 B 树索引。
结果反映在下表中:
测试 1.3 结果图表。作者图片
观察结果 :
- 聚集索引以及辅助 BTree 索引为随机访问或小范围扫描提供了最佳的响应时间;
- 对于更大范围和全扫描,聚集索引和辅助 BTree 索引的效果稍差
测试 1.4:不同的列数
众所周知,默认的 CCI 索引最适合在查询中包含几列的分析场景。
测试的目的是验证 select 语句中涉及的列数如何影响计时。
查询模式:
**select** <calculation list>
**from** fact_order_line_1B
**where** order_timestamp **between** '2021-02-01' and '2021-03-01'<calculation list>:
1 Column: **count**(*)
2 Columns: **count**(*), **sum**(total_amount)
3 Columns: **count**(*), **sum**(total_amount), **sum**(shipping_amount)
4 Columns: **count**(*), **sum**(total_amount), **sum**(shipping_amount),
**sum**(tax_amount)
关于查询时间的统计信息可以在下面找到:
测试 1.4 结果图表。作者图片
观察结果 :
- 向 select 语句中添加更多列会显著影响响应时间:
- 计算中涉及的 2 列和 4 列之间大约有 40%的差异
测试#1.5:复制与哈希分布
测试#1.5 的主要目标是验证数据分布类型如何影响不同类型的范围查询的性能。
相同的数据已经存储在 3 种数据分布类型的表中:1)循环法;2)复制;3)哈希分布。
您可以看到 DW1000c 和 DW3000c 两个性能级别的基准测试结果:
onDW1000c 上的测试 1.5 结果图表。作者图片
DW3000c 上的测试 1.5 结果图表。作者图片
观察结果 :
- 对于所有 3 个选项,查询结果时间与 DW1000c 性能水平非常接近;
- 从 DW3000c 开始,哈希分布式类型(我假设它允许更好的并行化)的性能开始显著提高。
测试#2:大到小的表连接(事实到维度)
如上所述,测试#2 的目的是对连接操作的不同方面进行基准测试。让我们回顾一下收集的各种统计数据。
测试 2.1:默认值
本节中第一个测试的目的是对基本的连接场景进行基准测试,包括:
- 事实到维度表的连接操作;
- 不同大小的事实表和维度表;
- 根据一个维度属性和几个聚合进行分组
- 较大的事实表通过散列来分发,而较小的维度被复制;
- 所有表都基于默认的 CCI 索引;
- 以 3 个性能级别为基准:DW1000c、DW3000c 和 DW6000c
查询模板如下所示:
**select** **top 50**
d.category_id, **max**(d.category), **avg**(f.tax_amount),
**sum**(f.total_amount), **sum**(f.shipping_amount)
**from** fact_order_line_<size> f
**inner join** <dimension_of_different_size> d on <join_criteria>
**group** **by** d.category_id
**order** **by** sum(f.total_amount) desc
测试 2.1 结果图表。作者图片
观察值 :
- 从 DW1000c 的性能级别开始,大多数查询在 5 秒内执行;
- 例外是两个最新的查询,包括更大的表的连接:1B 到 100K 和 1B 到 1M;
- 从 DW1000c 到 DW6000c 的资源扩展不会对较轻的查询产生巨大影响,但是对于最近两个明显较重的查询,线性地改善了时间
测试 2.2:要连接更多维度表
测试#2.2 的目标是验证相同大小的额外维度表的连接如何影响总体计时。
已经在事实表到 1 维表的连接与到 2 维表的连接和到 3 维表的连接之间进行了比较。
性能等级 DW1000c 的结果反映如下:
测试 2.2 图表。作者图片
观察结果 :
- 要连接的维度数量会显著影响总体时间:连接三个维度表的时间比连接一个维度表的时间长 3-4 倍
测试 2.3:具有聚集非列存储索引的维度表
有些数据库引擎同时支持基于行和基于列的存储配置文件,建议以基于行的格式存储维度表。
如果将事实表与维度表连接进行比较,验证连接的性能有何不同是一件有趣的事情,其中维度表是在 CCI 上构建的,而维度是使用简单聚集索引(非列存储索引)构建的
测试 2.3 图表。作者图片
观察结果 :
- 从上面的图表可以看出,整体性能几乎相同;
- 因此,另一个因素应该决定对维度表使用哪种索引方法。
测试#2.4:哈希复制与复制复制连接
MPP 存储的一个关键最佳实践是保持较大的事实表均匀分布在所有节点上,同时存储在所有节点上复制的较小维度表。
另一方面,Azure 建议将较小的表复制到大约 2GB 的空间。问题是,如果事实表仍然适合这个大小,那么还值得复制它吗?
因此,下面的测试比较了事实表(相对较小)被复制或通过散列分布的连接查询的时间。
测试 2.4 结果图表。作者图片
观察值 :
- 事实表的分布式版本在所有情况下都能更好地工作。
- 对于较大的表连接,这种差异非常显著
测试#3:大表到大表的连接
最后一个测试致力于大表到大表的连接。
测试 3.1:分布类型
在这个测试的范围内,有 10 亿行的大型事实表被连接到一个包含 1 亿行的大型维度表。
事实表是按维度外键(customer_sk)上的散列分布的。使用以下维度表配置:
- 按主键散列分布的维度表(customer_sk)
- 按备选键分布的维度表(customer_bk)
- 配置为复制的维度表
使用 DW1000c 性能水平的时序对比如下所示:
观察值 :
- 令人惊讶的是,基于连接键的分布并没有带来显著的好处;
- 基于复制的维度表的联接优于其他选项。
测试#3.2 分布与复制和扩展
最后一项测试旨在验证更大规模的相同分布与复制选项:DW3000c 和 DW6000c:
观察结果 :
- 在更大的范围内,维度表的复制版本比分布式版本显示出更大的优势;
- DW6000c 的性能水平足以在 5 秒间隔内处理 10 亿到 1 亿个连接(对于复制版本)。
结论
尽管事实上不同的 MPP 引擎之间有很多相似之处,但它们中的每一个都有很多细节,包括 Azure 专用 SQL 池。它需要深入了解索引和数据分布配置的所有可能选项,以便充分利用它。
在本文中,索引和数据分布的不同方面和最佳实践已经通过基准测试得到了验证。
需要记住的一些亮点:
- 总是尝试将较大的分布式表与较小的复制表连接起来;
- 尽可能避免两个大表连接。否则,您将需要大量昂贵的资源来获得合理的用户查询体验;
- 减少返回的 select 查询中的列数,或者考虑使用基于聚集索引的维度;
- 减少要连接的表的数量。非常明显,但仍然)。
基准模式/数据/查询文件
你可以在 github 这里找到模式创建、数据生成以及基准查询 SQL 代码。
Azure Synapse 分析和 Power BI
原文:https://towardsdatascience.com/azure-synpase-analytics-power-bi-f6ded6f96d5f?source=collection_archive---------16-----------------------
使用无服务器 SQL 池轻松高效地刷新 Power BI 数据集
https://www . pexels . com/photo/adventure-air-aircraft-balloon-210012/
引用微软的 Synapse 产品页面
Azure Synapse Analytics 是一项无限的分析服务,它将数据集成、企业数据仓库和大数据分析结合在一起。它让你可以自由地使用无服务器或专用资源来查询数据。
我非常同意与自由有关的那一点。Synapse 拥有您针对不同工作负载或需求所需的所有工具。如果您需要一个普通的数据仓库,那么使用专用的或无服务器的 SQL 池。如果你想要 Spark,那么 Spark pools 可以提供友好的笔记本体验,如 Databricks(缺点是最新的 Spark 版本还没有出现)。Data factory 还与 Synapse workspace 集成在一起,因此无需在不同的工具之间来回切换。如果您想要对代码制品和 CI/CD 过程有更多的控制,那么源代码控制也包含在同一个配方中。
然而,如果不首先进行测试,就无法评估某个工具或应用程序的有用性。
要解决的问题
我想解决的问题是提高 Power BI 数据集刷新速度,并简化一些用于提取所需数据的 M 查询。源数据是 Azure Data Lake Gen2 上托管的一组 parquet 文件。Power BI 提供了一个 M 函数来解析拼花数据,就像所有用于读取 CSV、Excel 等的经典连接器一样。不幸的是,这种方法的总体体验并不理想。对于重要的数据加载,数据集刷新通常很慢,因为解析是使用 Power BI premium capacity 完成的,这不是从 parquet 文件加载/过滤大量数据的最佳工具。此外,用于提取数据的 M 查询有点复杂,更重要的是不容易阅读。
潜在解决方案
Azure Synapse 无服务器 SQL 池可以在包含 CSV 或 Parquet 文件的数据湖文件夹上定义外部表或视图。一旦定义了这些表或视图,我们就可以用 SQL 数据库连接器切换 Power BI 中的 parquet 连接器,并尝试创建使用查询折叠的加载查询。因此,使用 M 完成的任何过滤器或投影都将被翻译成普通的 T-SQL 语句,这些语句将由 Synapse 本身执行,而不是 Power BI。如果 Synapse 足够聪明,能够像 Spark 一样进行分区修剪或谓词下推,那么这将是一个巨大的胜利。数据集刷新有望更快,产生的成本也将最小。顺便说一下,无服务器 SQL 池的定价取决于为查询服务而读取的数据的大小。
让我们来制作一些 Power BI 数据集。
https://www . pexels . com/photo/cooked-food-on-black-plate-5949889/
环境设置
需要 synapse analytics 工作区。它带有一个内置的无服务器 SQL 池,您可以选择连接到一个现有的数据湖或创建一个新的与工作区相关联的数据湖。我将使用纽约市黄色出租车出行数据集。这是一个非常著名的数据集,已经被许多 Synapse 样本很好地记录和使用。数据集托管在美国东部 Azure 地区,因此出于数据局部性目的,建议将 Synapse workspace & Power BI 服务放在同一地区。在我的情况下,我将 2015/2016/2017 年复制到我的 Synapse 工作区,因为它不在同一地区托管。
假设报告要求是:
- 年份是 2015 年
- 供应商 ID 为 1
将包括 2015 年在内的 3 年数据加载到数据湖中,以便稍后使用 Synapse 测试分区修剪,但对于测试 Power BI 开箱即用数据湖加拼花连接,我们可以简单地指向仅托管 2015 年的文件夹。
提示: Azure storage explorer 还可以用来从公共 blob 容器中浏览/复制数据。
提供公共 blob 容器的 URL,即https://azureopendatastorage.blob.core.windows.net/nyctlc。一旦连接,你可以浏览数据,甚至复制一些文件夹到你自己的数据湖文件夹。您需要获取nyctlc/yellow
文件夹中的数据。
使用 Power BI 拼花阅读器
好了,让我们首先尝试使用 Power BI 提供的 parquet 连接器读取这些数据。由于需要从数据湖中枚举文件、parquet 解析和应用供应商 Id 过滤器,M query 看起来有点复杂。下面的大部分内容是由向导创建的,用来从数据湖中加载数据。将首先选择某个容器文件夹,然后使用 M 函数扩展该根文件夹中的所有拼花文件的内容,并将所有内容连接在一起。
为了最大限度地减少本地填充文件并发布到 powerbi.com 所需的时间,我使用了一个小技巧。
- 通过在 2015 文件夹的末尾添加一些字符来重命名该文件夹
- 用相同的命名模式创建一个新的 2015 文件夹
- 从 real 2015 文件夹中复制超过一个月的数据
- 将更改应用于本地报表,然后将其发布到 powerbi.com
- 删除包含一个月数据的文件夹,然后恢复 2015 重命名的文件夹,使其具有正确的名称
接下来,我们将了解刷新 powerbi.com 数据集需要多少时间。此次刷新是针对包括 12 个月在内的 2015 年文件夹数据进行的。
供应商 Id 为 1 的 2015 年纽约旅行的数据刷新花费了 43 分钟。该数据集有一个包含大约 7000 万条记录的表,虽然不算多,但刷新速度很慢。部分时间用于构建数据集的底层表格数据库,但 43 分钟似乎太长了。
接下来,让我们看看使用不同的方法(如使用 Synapse 无服务器 SQL pool)是否会有所不同。
正在准备 Synapse 无服务器 SQL 池
Synapse workspace 附带一个内置的无服务器 SQL 池。我们需要准备一个指向数据湖中 trips 数据的 SQL 抽象层。
首先,我们需要使用 UTF8 排序规则创建一个数据库。如果没有 UTF8 排序规则,在读取拼花文件时会有很多警告。详见本文。打开 Synapse Studio,然后创建一个新的空 SQL 脚本文件来运行以下代码片段。
CREATE DATABASE NycTaxiTrips COLLATE Latin1_General_100_BIN2_UTF8;
如果我们需要添加一些认证细节,那么就特别需要一个外部数据源。在我们的例子中,我使用传递身份验证,所以不需要添加这样的细节。
CREATE EXTERNAL DATA SOURCE NycTripsDataSourceWITH (LOCATION='https://[DATA-LAKE-ACCOUNT].dfs.core.windows.net/')
创建一个指向包含 3 年纽约出租车旅行的文件夹的视图。
CREATE VIEW Trips ASSELECT *, T.filepath(1) AS year, T.filepath(2) AS monthFROMOPENROWSET(BULK '/root/nyctlc/puYear=*/puMonth=*/*.parquet',DATA_SOURCE = 'NycTripsDataSource',FORMAT='PARQUET')AS T;
如果您想尝试上面的两个片段,那么更新它们以使用您自己的 data lake 帐户名和 trips parquet 文件的正确相对路径。
您可以看到,我们已经使用 synapse filepath
函数从文件路径中提取了年份和月份列。
要验证视图是否按预期工作,请读取前 10 条记录。如果向右滚动,您将看到来自分区结构的额外的 year 和 month 列。
分区修剪
数据湖有 3 年的数据。如果我们想读取 2015 年的数据,Synapse 应该能够读取 2015 年的文件夹,只选择所需的数据。我们来验证一下这个假设是否成立。
首先运行此查询。
SELECT year, COUNT(*) AS count
FROM Trips
GROUP BY year
结果应该是这样的,这意味着视图可以访问 3 年的数据。
切换到 messages 选项卡,查看与运行该查询所读取的数据量相关的查询统计信息。
Synapse 需要读取 53MB 来运行这个查询。顺便说一下,Synapse 不必读取 parquet 文件的全部内容来得出记录计数。Parquet 是一种分栏文件格式,在我们的例子中,或者在投影几列的情况下,Synapse 可以只读取满足查询所需的列。
让我们对同一个查询应用一个年份过滤器。
Synapse 这次扫描了 18MB 的数据,大约是查询扫描所有年份读取的 53MB 数据的 1/3。
另一个类似的模式是,读取较小数量的列比读取较大数量的列需要读取较少的数据。如果我们不需要加载所有的列,这是很方便的。
太好了!这意味着我们可以在所有年份定义一个视图,如果我们想要提取特定年份,分区修剪将只读取所需的数据,这使得查询运行更快,并且您的 Azure 账单不会飙升。
更新 Power BI 以使用 Synapse SQL 视图
现在克隆您拥有的 Power BI 报告,并删除现有的 Trips 表。然后将其替换为到 SQL server 数据库的连接,并选择 Trips 视图。SQL server 连接可以从 Synapse workspace 主页获取,因为它具有无服务器 SQL 池服务器名称。使用您的 Azure 凭据进行身份验证。
在 year 列上,使用下拉箭头应用基本文本筛选器,仅提取 2015 年,类似地,在 vendorID 列筛选器上,值为 1。删除年份和月份列。
右键单击最后一个应用的步骤,然后单击查看本地查询,它应该被启用,这意味着查询折叠在那里。您将看到应用的过滤器出现在 WHERE 子句中,SELECT 语句有一个投影,因此 year & month 列不包括在内。如果您只需要几列,投影也会使事情变得更快。
用于提取数据的 m 查询看起来更加清晰易读。
查询折叠提示
如果您需要使用一个包含过滤值的
CSV 字符串(类似于多个产品 id)的参数来过滤某一列,您可以使用Table.SelectRows
和List.Contains
的组合。不幸的是,这将直接破坏查询折叠。您需要将参数值具体化为一个独立的查询,生成一个值列表,然后将List.Contains
指向该查询。
现在是关键时刻了。使用之前使用的相同技巧将该报告推送到 powerbi.com,填充 Synapse 连接的凭证并触发数据集刷新。
现在大约需要 23 分钟,大约是数据湖和拼花连接器所需时间的一半。实际上,如果您有滤波器,使得滤波后的数据是完整原始数据的一个小子集,则增益会明显得多。
用于执行刷新的数据量如何?
以下查询获取由无服务器 SQL 池处理的数据大小。数据刷新后的每日值与数据刷新前的每日值之间的差异可以很好地指示用于进行刷新的数据大小,这可以用于评估使用 Synapse 所需的成本,特别是在定期计划刷新的情况下。
SELECT * FROM sys.dm_external_data_processed
要考虑的其他想法
将刷新数据集所需的时间减少一半是一个很好的进步,但在 Synapse 和 Power BI 方面还可以做得更多。这里是 Dax Studio VertiPaq Analyzer 指标,它提供了一些优化该数据集的线索。
- 接送时间的基数非常大(大约 25M)。我们可以考虑使用一个日期列来表示接送,两个时间列来表示接送,也许可以使用另一个列来表示持续时间,以防旅行跨越一天的界限。
- 所有包含货币金额的列都应该从十进制转换为固定十进制(货币)。
- 重新定义 Synapse 视图,仅从 Parquet 中选择所需的列(以防我们不需要所有列),并在 CREATE VIEW 语句中显式指定每个列的数据类型。这可能有助于字符串列。
- 对于空间列(纬度和经度),我们可以将它们四舍五入到小数点后 4 位,例如,如果报告位置的误差在 11 米范围内是可以的。这将减少最终数据集的基数和大小。
资源
https://datamozart.medium.com/synapse-serverless-sql-power-bi-having-fun-with-pivot-3491dbb13ae8 https://blog.crossjoin.co.uk/2021/01/31/comparing-the-performance-of-importing-data-into-power-bi-from-adlsgen2-direct-and-via-azure-synapse-analytics-serverless-part-2-transformations/
婴儿的第一次分配算法抽样:可用的方法和如何使用它们
原文:https://towardsdatascience.com/babys-first-algorithmic-sampling-from-a-distribution-methods-available-and-how-to-use-them-208678247e62?source=collection_archive---------19-----------------------
Gabriela Morgenshtern 拍摄的图片
实践教程
从复杂分布中取样和近似的缓慢和可接近的介绍
TL;速度三角形定位法(dead reckoning)
这篇文章包括了来自最近一篇关于算法抽样的论文的描述,用更简单的术语描述了使用简单或马尔可夫链蒙特卡罗方法进行抽样的动机和方法。它将 Metropolis Hastings 算法作为在读者实践中实现这种思想的一个例子,并简要地列出了对所涉及的超参数的考虑和启发。
抽样作为一个概念
这里,我们将来自分布 p(x)的样本 xᵢ称为概率分布为 p(x)的单个实现。这与统计中的一些其他地方相反,在这些地方,样本 x 可能指的是实现的集合
蒙特卡洛
蒙特卡罗方法有两个目标:(1)从一个给定的分布中产生覆盖该分布的样本;(2)在给定的分布下估计函数的期望。如果我们使用蒙特卡罗方法进行采样(即解决我们的第一个问题),我们也将能够为我们的第二个问题的解决方案提供一个无偏估计量——良好的覆盖采样将允许我们近似期望表达式中的积分 x~P(X) :
eₓ=e[f(x)]=∫f(x)p(x)dx**
因此,我们应该考虑的基本计算问题是如何最好地获取这些样本。这里,我们讨论一种根据蒙特卡罗和马尔可夫方法获取这些样本的算法方法,以及改进这种马尔可夫链蒙特卡罗方法的计算时间的一些考虑因素:Metropolis Hastings 采样算法
马尔可夫性质/过程
一个简短但重要的注意事项是,我们在这里讨论的不是马尔可夫链,它是一种类型的概率模型,它融合了马尔可夫过程的思想。马尔可夫过程排序的方法在假设下操作,即在随机变量(RVs)的时间序列中,每个 RV 独立于所有其他 RV,除了紧接在它前面的那个。这转化为应用于一系列样本的联合概率分布的概率链规则,因此:
P( X ₁ ,…,xₙ)= p(x₁p(x₂| x₁【t21)…p(xₙ| xₙ₋₁
蒙特卡罗方法
如果我们的数据分布简单(即由我们的一个分布公式很好地定义),或者如果我们的累积密度函数(CDF)是已知的,那么采样就很容易。如果分布不简单,我们不能直接从中取样。例如,当我们处理基于能量的模型时,就存在这种情况,因为归一化常数需要对输入域中的所有值进行计算开销很大的求和计算。
蒙特卡罗(MC)方法是探索(良好覆盖的采样)领域空间的迭代方法。这些方法有两个总体分类:简单和马尔可夫链。
简单抽样
这里,每次迭代都是独立的,因为每次迭代都是盲目执行的(不知道先前的采样结果)。简单 MC 使用简单样本(明确定义的)分布。虽然我们不会在这里详细讨论这些,但简单的 MC 采样可以进一步细分为:
重要性抽样:
通过简单样本分布,在域上逼近复杂(非简单样本)函数的期望
拒绝采样:
来自复杂(非简单到样本)函数的样本通过简单到样本上限分布。也就是说,我们通过取某个明确定义的分布 Q(x) 来近似我们的复函数,该分布通过乘以某个正整数 c ,将总是位于我们在笛卡尔轴上感兴趣的分布 P(x) 之上,并且从来自 Q(x) 的垂直切片的轴值的均匀分布范围中取样。在此图中可以看到这种方法的示例和伪代码:
****
同时计算 c 图和伪代码的拒绝采样是 Ghojogh、Nekoei 和 Ghojogh 等人提出的方法的改进。
然后,可以通过我们所有样本的平均值 {x} ∈ S 来计算我们对利息预期的无偏估计值( E[P(x)] )。它是无偏的,因为随着样本集的大小接近域的大小,我们接近了兴趣分布期望值的真实值。此外,通过增加 S 的基数(即,通过获取更多样本),我们的估计量的方差将以与 1/R 成比例的速率减少。这两个性质的证明,对所有的蒙特卡罗估计器都是通用的,如下所示:
****
左: 蒙特卡洛估计量无偏的证明。 对: 证明蒙特卡洛估计量的方差以 1/R 的速率递减 。 这些证明摘自 CSC 412 2020 年冬季第 6 周笔记
从上面的估计器计算表达式中可以看出,这是一个非常简单的计算,可以包含在训练模型的证据下限(ELBO)函数计算中。而且,当你增加你的训练集的大小,或者用于训练的小批量的数量,你将更加接近你的概率的,难以处理的损失函数的真实期望。
马尔可夫链抽样
在马尔可夫链抽样算法中,有一个候选生成分布 Q 是由实现者做出的选择。在φᵢ的候选可能或可能不直接依赖于φᵢ-₁,但是将总是以某种方式依赖于前一次迭代,从而允许马尔可夫属性特征(如上所述)。让φᵢ直接依赖于φᵢ-₁的一个替代方案是保持相同的q(φ)分布,具有相同的参数化,然后将依赖依赖与φᵢ-₁第一次迭代相关的一些其他属性。然后,q(φᵢ)必须与我们的目标分布相似,以确保它是对它的良好近似。
Metropolis-Hastings 采样算法
在 Metropolis 算法中,有一个简单到样本的候选(或建议)分布,取决于前一次迭代的样本值φᵢ-₁。我们使用这个候选提议作为从复杂的利益分布中取样的手段, P*(X) 。
例如,如果我们选择一个候选分布为具有一个常数𝝈但依赖于迭代的𝝁的高斯族,由于这种依赖性引入的对称性,我们简化了𝞪值的计算,如q(φᵢ-₁|φ)= q(φ | φᵢ-₁).在这种情况下,𝝈的值也被称为步长,这是一个必须仔细考虑的超参数,因为它影响探索具有足够覆盖的样本空间所花费的时间,从而影响算法的运行时间。对建议函数的这种对称选择定义了 Metropolis 算法。当算法的 alpha 值计算被推广以接受不一定对称的建议时,就会出现黑斯廷斯增强。 Metropolis-Hastings 基于 Metropolis 方法,使用重要性抽样的思想:它通过候选分布对新旧样本进行加权。
******
左:Metropolis 算法的伪代码。右:黑斯廷斯扩增允许近似的非对称候选分布。改编自 Ghojogh,Nekoei,和 Ghojogh 等人。**
请注意,在 Metropolis 和Metropolis-Hastingsalpha 计算中, P*(X) 项同时出现在分子和分母中——这是一种抵消任何不依赖于 X 但仍然难以处理的归一化因子的聪明方法,例如那些出现在基于能源的模型中的因子。
在大都市的随机漫步(RWM)
在 RWM,比如大都会黑斯廷斯,我们有当前候选样本对先前迭代的依赖性。通常在 RWM 中,候选φᵢ可能或可能不直接依赖于φᵢ-₁,但总是以某种方式依赖于前一次迭代,从而利用了马尔可夫性质。当使用这个算法系列时,我们有两个重要的选择:候选分布和步长。步长将直接影响我们接受样本的速率:太高的速率(太小的步长)将导致非常慢的域探索;过低的速率(过大的步长)将导致域的不完全覆盖。有一篇论文提出,在大多数情况下,为大都市实施设置的合适步长是𝝈 = 2.38。对于适当的接受率,一个建议的启发式方法是 23–50%的样本,并且在任何情况下,候选分布应该具有比
P*(X) (用于近似的感兴趣的分布)更高的方差。
来源
1.Ghojogh,Nekoei,Ghojogh,et。艾尔。抽样算法,从调查抽样到蒙特卡罗方法:教程和文献综述。2020 年 11 月:https://arxiv.org/pdf/2011.00901.pdf
2.乔治。多伦多大学,CSC412 年冬季讲座 5:https://probmlcourse.github.io/csc412/lectures/week_6/
3.乔治。多伦多大学 CSC 412 2020 年冬季讲座 7:https://probml course . github . io/CSC 412/lections/week _ 10/# optimizing-the-elbo
4.理解 Metropolis-Hastings 算法。机器学习电视(加州大学圣克鲁斯分校)。2020 年 2 月:https://www.youtube.com/watch?v=0lpT-yveuIA
**5.罗森塔尔。优化和调整 Metropolis 算法。2013 年 2 月:【http://probability.ca/jeff/ftpdir/lawlessart.pdf **
MuseGAN:用 GANs 创作原创音乐
原文:https://towardsdatascience.com/bachgan-using-gans-to-generate-original-baroque-music-10c521d39e52?source=collection_archive---------11-----------------------
实践教程
用可播放的音频文件来听生成的音乐
照片由马里乌斯·马萨拉尔在 Unsplash 上拍摄
下面是这个项目的 github 回购 (ads):
gan 是高度通用的,允许生成任何可以合成为图像的东西。通过利用 GANs 的这一特性,有可能生成非常非正统的内容,至少从机器学习的角度来看是这样。这篇文章分享了我的项目,在这个项目中,我基于巴赫作品的 midi 文件,使用 GANs 生成了巴洛克音乐。
这并不是我第一次使用 GANs 来生成创意内容。我上次写了一个可以产生艺术的甘,基于著名艺术家的著名作品。从该项目中,我获得了一些关于 GANs 以及如何平衡它们的关键信息:
- 质量重于数量。当我第一次训练甘产生艺术时,我用了大量的现实主义、抽象主义和印象派作品来训练甘。与只在每个类别中训练产生的结果相比,这一结果就相形见绌了。
- 平衡是关键。将 GAN 维系在一起的是鉴别者和生成者之间的对立关系。如果鉴别器太过擅长识别假代,生成器就会停留在当前位置。如果鉴别器在识别伪代时变得太弱,生成器就开始利用环境并开始生成欺骗鉴别器的内容,但不会模仿真实的数据点。
有了这两点,我开始着手这个项目:
数据预处理:
机器学习的第一步是数据预处理。对于这个项目,它包含 3 个步骤:
访问 Midi 文件:
我在网上找到了一个巴赫作品的数据集,是从一个网站上搜集来的。我把所有的 midi 文件提取出来,放在一个文件夹里。
将 Midi 文件转换成图像:
我找到了一个 github 页面,其中有两个程序使用 music21 库将 midi 文件转换成图像,然后再转换回来。
每个音符可以表示为一个白块。音块的高度决定了音高,长度决定了音符演奏的时长。
然后,我编写了一个脚本,将这两个程序与我的 midi 文件集成在一起,在不同的目录中创建新的图像:
import os
import numpy as nppath = 'XXXXXXXXX'os.chdir(path)
midiz = os.listdir()
midis = []
for midi in midiz:
midis.append(path+'\\'+midi)
这个脚本转到 midi 目录,然后将所有 midi 文件路径添加到一个列表中,供以后访问。
from music21 import midimf = midi.MidiFile()
mf.open(midis[0])
mf.read()
mf.close()
s = midi.translate.midiFileToStream(mf)
s.show('midi')
这个脚本打开第一个 midi 文件,并播放它以确保程序正常工作。如果在非交互环境中运行,这可能不起作用。
import os
import numpy as np
import py_midicsv as pmos.chdir(path)
midiz = os.listdir()
midis = []
for midi in midiz:
midis.append(path+'\\'+midi)
new_dir = 'XXXXXXXX'
for midi in midis:
try:
midi2image(midi)
basewidth = 106
img_path = midi.split('\\')[-1].replace(".mid",".png")
img_path = new_dir+"\\"+img_path
print(img_path)
img = Image.open(img_path)
hsize = 106
img = img.resize((basewidth,hsize), Image.ANTIALIAS)
img.save(img_path)
except:
pass
这个脚本使用 github 页面中的 midi2image 函数,并根据 midi 文件的路径转换所有的 midi 文件。它们也被重新成形为形状(106,106)。为什么?106 是程序的高度,因为这是 midi 文件中可能的音符数。此外,对于卷积转置,使用正方形要容易得多。
构建数据集:
import os
from PIL import Image
from matplotlib import pyplot as plt
import numpy as nppath = 'XXXXXXXXXXXXXX'
os.getcwd()
img_list = os.listdir(path)def access_images(img_list,path,length):
pixels = []
imgs = []
for i in range(length):
if 'png' in img_list[i]:
try:
img = Image.open(path+'/'+img_list[i],'r')
img = img.convert('1')
pix = np.array(img.getdata())
pix = pix.astype('float32')
pix /= 255.0
pixels.append(pix.reshape(106,106,1))
imgs.append(img)
except:
pass
return np.array(pixels),imgsdef show_image(pix_list):
array = np.array(pix_list.reshape(106,106), dtype=np.uint8)
new_image = Image.fromarray(array)
new_image.show()
pixels,imgs = access_images(img_list,path,200)
这个脚本转到包含所有图像和记录所有像素值的目录。这将是用作真实样本的像素值,将与计算机生成的样本一起输入鉴别器。像素值必须除以 255,因此值可以是 1 或 0(白色或黑色),这使得程序更容易正常工作。
np.unique(pixels)
这个脚本只是确保像素值已经在 1 和 0 之间标准化。
创建 GAN:
进口:
这个程序要运行有很多先决条件:
from numpy import zeros
from numpy import ones
from numpy import vstack
from numpy.random import randn
from numpy.random import randint
from keras.datasets.mnist import load_data
from keras.optimizers import Adam
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import Reshape
from keras.layers import Flatten,BatchNormalization
from keras.layers import Conv2D
from keras.layers import Conv2DTranspose
from keras.layers import LeakyReLU
from keras.layers import Dropout
from matplotlib import pyplot
from IPython.display import clear_output
这些基本上是运行 GAN 时需要使用的所有层和 numpy 函数。clear_output 只是每 10 个历元清除一次屏幕,这样屏幕就不会堵塞。
定义鉴别器:
def define_discriminator(in_shape = (106,106,1)):
model = Sequential()
model.add(Conv2D(64, (3,3), strides=(2, 2), padding='same', input_shape=in_shape))
model.add(LeakyReLU(alpha=0.2))
model.add(Dropout(0.5))
model.add(Conv2D(64, (3,3), strides=(2, 2), padding='same'))
model.add(LeakyReLU(alpha=0.2))
model.add(Dropout(0.5))
model.add(Flatten())
model.add(BatchNormalization())
model.add(Dense(1, activation='sigmoid'))
opt = Adam(lr=0.0002, beta_1=0.5)
model.compile(loss='binary_crossentropy', optimizer=opt, metrics=['accuracy'])
return model
这个鉴别器经过多次试验后已经微调过了。卷积层的节点数量很少,因此生成器可以在鉴别器领先之前赶上鉴别器。漏失层也是必要的,以便鉴别器不会对数据进行过拟合。
定义生成器:
def define_generator(latent_dim):
model = Sequential()
n_nodes = 128 * 53 * 53
model.add(Dense(n_nodes, input_dim=latent_dim))
model.add(LeakyReLU(alpha=0.2))
model.add(Reshape((53, 53, 128)))
model.add(Dense(1024))
model.add(Conv2DTranspose(1024, (4,4), strides=(2,2), padding='same'))
model.add(Dense(1024))
model.add(LeakyReLU(alpha=0.2))
model.add(Dense(1024))
model.add(Conv2D(1, (7,7) , padding='same',activation = 'sigmoid'))
return model
发电机特别深,因为几乎在所有情况下,发电机都会落后。泄漏 relu 的使用是为了防止“死亡 relu”问题,其中小于 1 的值完全阻止训练。这个 GAN 的潜在尺寸不能太大,因为它会降低生成器的训练速度。我决定它的价值是 100
def define_gan(g_model, d_model):
d_model.trainable = False
model = Sequential()
model.add(g_model)
model.add(d_model)
opt = Adam(lr=0.0002, beta_1=0.5)
model.compile(loss='binary_crossentropy', optimizer=opt)
return model
该脚本将鉴频器和发生器结合在一起,因此鉴频器的损耗可以反向传播回发生器。
生成样本:
def generate_real_samples(dataset, n_samples):
ix = randint(0, dataset.shape[0], n_samples)
X = dataset[ix]
y = ones((n_samples, 1))
return X, y
def generate_latent_points(latent_dim, n_samples):
x_input = randn(latent_dim * n_samples)
x_input = x_input.reshape(n_samples, latent_dim)
return x_inputdef generate_fake_samples(g_model, latent_dim, n_samples):
x_input = generate_latent_points(latent_dim, n_samples)
X = g_model.predict(x_input)
y = zeros((n_samples, 1))
return X, y
这些自由函数能够产生 GAN 起作用所需的所有参数和数据:潜在点作为发生器的输入,而假样本和真样本用于训练和测试鉴别器。
列车 GAN:
def train(g_model, d_model, gan_model, dataset, latent_dim, n_epochs=51, n_batch=10):
bat_per_epo = int(dataset.shape[0] / n_batch)
half_batch = int(n_batch / 2)
for i in range(n_epochs):
for j in range(bat_per_epo):
X_real, y_real = generate_real_samples(dataset, half_batch)
X_fake, y_fake = generate_fake_samples(g_model, latent_dim, half_batch)
X, y = vstack((X_real, X_fake)), vstack((y_real, y_fake))
d_loss, _ = d_model.train_on_batch(X, y)
X_gan = generate_latent_points(latent_dim, n_batch)
y_gan = ones((n_batch, 1))
g_loss = gan_model.train_on_batch(X_gan, y_gan)
print('>%d, %d/%d, d=%.3f, g=%.3f' % (i+1, j+1, bat_per_epo, d_loss, g_loss))
if (i+1) % 10 == 0:
summarize_performance(i, g_model, d_model, dataset, latent_dim)
clear_output()
该功能训练 GAN。它基本上协调了上面定义的所有函数,并打印了鉴别器和发生器的损耗。这允许您检查发生器和鉴别器之间的平衡。
latent_dim = 100
d_model = define_discriminator()
g_model = define_generator(latent_dim)
gan_model = define_gan(g_model, d_model)
print(pixels.shape)
train(g_model, d_model, gan_model, np.array(pixels), latent_dim)
这个脚本只是调用函数并实际运行程序。
可视化结果:
from keras.models import load_model
from numpy.random import randn
from matplotlib import pyplotdef generate_latent_points(latent_dim, n_samples):
x_input = randn(latent_dim * n_samples)
x_input = x_input.reshape(n_samples, latent_dim)
return x_inputmodel = g_model
latent_points = generate_latent_points(latent_dim,1)
X = g_model.predict(latent_points)array = np.array(X.reshape(106,106),dtype = np.uint8)
array*= 255
new_image = Image.fromarray(array,'L')
new_image = new_image.save('composition.png')
这个脚本调用模型对潜在点进行预测,从而得到一个数组。然后使用 PIL 将该数组转换成图像。
image2midi('composition.png')
将图像转换为 midi 文件后,您可以在单元格中运行这些命令来聆听 midi 文件。
!apt install fluidsynth
!cp /usr/share/sounds/sf2/FluidR3_GM.sf2 ./font.sf2
!fluidsynth -ni font.sf2 composition.mid -F output.wav -r 44100
from IPython.display import Audio
Audio('output.wav')
结果:
以下是一些我最喜欢的人工智能音乐片段:
该模型已经开始掌握歌曲结构、基本和声和节奏,尽管它听起来确实有点像爵士乐。
我的链接:
如果你想看更多我的内容,点击这个 链接 。
回归基础——R 中的线性回归
原文:https://towardsdatascience.com/back-to-basics-linear-regression-in-r-3ffe4900482b?source=collection_archive---------20-----------------------
线性回归是统计学中最基本的知识之一,下面是如何用 R
Jean-Philippe Delberghe 在 Unsplash 上拍摄的照片
自从我的上一篇文章以来已经有一段时间了,这是因为我一直在忙于准备两个月后即将到来的精算考试。在过去几周的学习过程中,我遇到了一位老朋友,他是我第一次上统计学课线性回归时认识的。
随着我开始学习更复杂的机器学习算法,我有时会忙于构建最复杂的模型来解决问题,而实际上,一个简单的线性模型可以轻松完成工作。直到我开始更新关于线性回归的知识,我对它的简单性和易用性有了新的认识。
因此,我认为利用这篇文章不仅可以加深我对线性回归的理解,还可以借此机会与他人分享统计学中的这个基本话题,这是一个好主意。
介绍
为了使本文尽可能简洁,我将不会涵盖线性回归的每个细节,而是提供足够的信息,让您很好地理解如何在 R 中执行和解释它。我还将简要地谈到方差分析的主题,即方差分析以及决定系数,或更普遍地称为 R 平方。
说到这里,我们开始吧!
线性回归是一种线性模型,它描绘了响应变量与单个解释变量(简单线性回归)或多个解释变量(多元线性回归)之间的关系。
既然我们在谈论我的精算考试,就让我们以此为例吧。
假设我想研究某人花在学习上的时间和他们相应的考试分数之间的关系。我首先需要为我的研究收集数据点。然后,我会将这些数据点绘制成图表,x 轴代表某人学习的时间,y 轴代表他们的最终考试分数。
请注意,本例中的最终考试分数代表我们的回答变量,因为它是我们正在研究的变量。另一方面,学习时间被称为解释变量,因为它是影响和“解释”反应变量结果的变量。
最佳拟合线
但是等等,到目前为止,我们只讨论了出现在图表上的数据点。回归线到底是怎么来的?
如果我们试图通过所有的数据点画一条线,很有可能,并不是所有的数据点都直接适合这条线。那么,我们如何知道如何最好地定位生产线呢?这就是最佳拟合线概念的由来。
想法是通过所有数据点拟合一条线,使得该线最小化观测值和拟合值之间的累积距离或回归项残差。这个过程称为拟合最佳拟合线。
我强烈建议查看下面的视频,以获得对这一特定概念的更直观的解释。
因此,我们应该会看到一条呈上升趋势的直线,或者换句话说,有一个正斜率,这是因为一个人花在考试学习上的时间越多,很自然地,这个人在考试中的表现就越好。
个案研究
既然我们已经了解了所有的基础知识,现在让我们看看如何在 r 中执行简单的线性回归。
假设我们有一个 6x2 的数据框架,它测量了怀孕期间不同时期的估计婴儿体重。
绘制数据点
首先,让我们将这个数据帧存储到一个名为 baby 的变量中。
# Load data
baby = read.table("baby weights.txt", header = T)# Show data
baby
然后,我们可以使用散点图在图表上绘制这 6 个数据点。
# Plot data
plot(baby, main = "Estimated baby weights during pregnancy", xlab = "Gestation period (weeks)", ylab = "Weight (kg)")
Main 、 xlab 和 ylab 是 R 中 plot 函数内的简单参数,分别指定绘图的主标题、x 轴标签和 y 轴标签。以下是那个情节的结果。
怀孕期间估计婴儿体重散点图
看起来我们的解释变量——孕育期和反应变量——体重之间确实存在正相关。换句话说,婴儿在子宫里呆的时间越长,体重就越重。听起来很合理。
我们可以通过使用 R 中的 cor 函数来检查两个变量之间的相关性,并进一步测试它是否具有统计显著性。
同样,我们可以附加baby data frame,这样我们就可以访问它的内容,而不需要重复调用变量,这只是为了让我们的分析更容易。
# Attach data
attach(baby)# Compute correlation between gestation period and baby weight
cor(gestation, weight)# Test whether correlation coefficient is zero
cor.test(gestation, weight)
相关性检验
这两个变量之间有很强的正相关性。输出也清楚地表明这是一个重要的结果。因此,我们现在可以通过这些数据点拟合一条直线。
拟合线性回归模型
在 R 中拟合一个线性回归模型是非常简单和直接的。这里要注意的函数是 lm,代表线性模型。
这里,我们将拟合一个线性模型,该模型将 y 轴上的婴儿体重与 x 轴上的妊娠期进行回归。这里的顺序很重要,值得记住,响应变量总是在解释变量之前。
我们将线性模型存储在一个名为 model 的变量中,这样我们就可以在稍后阶段访问输出。
# Fit linear model
model = lm(weight ~ gestation)# Examine model
model
summary(model)
有很多方法可以检查线性模型,但最全面的方法是使用汇总函数。
摘要
正如我们所看到的,在这个特定的输出中有几个部分,但是不要担心,我们将浏览每个部分,并在后面讨论它们的确切含义。现在,让我们通过使用 abline 函数将这个线性模型添加到我们之前的散点图中。
# Add regression line
abline(model, col = "red", lty = "dashed")
带回归线的散点图
拟合值
拟合值与观测数据共享相同的 x 值,只是它们正好位于回归线上。
在本节中,我们将了解如何获得这些拟合值,以及如何将它们添加到现有的回归线中。同样,我们有几种方法可以解决这个问题,它们都给出了相同的结果。
# Obtain fitted values
model$fitted.values
fitted(model)
predict(model)# Add fitted values to regression line
points(gestation, fitted(model), col = "blue", pch = 16)
蓝点代表拟合值
方差分析(ANOVA)和 R 平方
方差是数据集中数字之间分布的统计度量。更具体地说,每个数据点离平均值有多远。因此,方差分析是对方差的研究。
通过将总方差分成两部分,我们可以评估由回归线解释的方差和未解释的方差,称为残差。
r 平方是线性模型解释的响应变量变化的百分比。R 平方值越高,观察值和拟合值之间的差异越小。
然而,单独的 R 平方并不足以表明回归线是否提供了良好的拟合。我们还必须考虑研究的背景以及回归模型中每个解释变量的统计显著性。
# ANOVA
anova(model)
方差分析(ANOVA)
f 检验的 p 值 0.0003661 证实了妊娠和体重之间存在线性关系。这个结果与我们之前的相关性测试是一致的。
我们还可以看到,回归平方和为 2.92129,残差平方和为 0.09371,总平方和为 3.015。
有两种方法可以计算平方和。一种是通过第一原理,另一种是通过使用来自 anova 函数的输出。
x = gestation; y = weight# Total sum of squares
(SStot = sum((y - mean(y))^2)
sum(anova(model)[,2])# Residual sum of squares
(SSres = sum((y-fitted(model))^2))
anova(model)[2,2]# Regression sum of squares
(SSreg = sum((fitted(model)-mean(y))^2))
anova(model)[1,2]
类似地,有三种方法可以计算决定系数或 R 平方,这三种方法得出的结果都是 0.9689173。
- 从汇总输出
- 相关平方
- 用回归平方和除以总平方和
# Method 1
summary(model)$r.squared# Method 2
cor(gestation, weight)^2# Method 3
SSreg / SStot
截距和回归系数
因为在这个特定的研究中我们只有一个解释变量,所以我们总共有两个系数,一个用于截距,一个用于斜率。
调用摘要功能的输出。
摘要
我们可以看到,斜率参数的 p 值为 0.000366,这表明它在统计上是显著的,换句话说,非零。
为了更进一步,我们还可以得出截距和斜率参数的置信区间。
# Confidence interval for intercept and regression coefficient
confint(model, level = 0.99)
截距和回归系数的置信区间
做预测
拟合线性模型的目标是做出具有合理精确度的预测。
在这一节中,我们将探讨使用简单线性模型进行预测的两种不同方法。
- 根据基本原则
- 使用预测功能
此外,我们还可以对这些预测产生置信区间和预测区间,以评估其准确性。
假设我们想预测一个婴儿在第 33 周的体重,下面是我们如何通过两种不同的方法来实现。
# First principles
coef(model)[1] + coef(model)[2] * 33# Using predict function
newdata = data.frame(gestation = 33)
predict(model, newdata)# Confidence interval
predict(model, newdata, interval = "confidence", level = 0.9)# Prediction interval
predict(model, newdata, interval = "predict", level = 0.9)
两种方法应该给出相同的预测值 2.141429。
残差
回想一下,残差是观测值和回归拟合值之间的差异。回归中有一个潜在的假设,即残差应该服从正态分布。
除了检查正态假设之外,通过检查残差的趋势,我们还可以评估我们的回归线与数据点的拟合程度,即观察模型是否存在高估或低估真实数据点的特定部分。
在本节中,我们将讨论如何获得残差值,以及如何使用各种图来分析这些残差值中存在的模式。
有两种方法可以获得残差:
- 使用残油功能
- 从观察值中减去拟合值
# Method 1
resid(model)[1]# Method 2
weight - fitted(model)
接下来,我们将看看如何可视化残差的趋势。这里我们可以使用不同的图,每个图可以为我们提供关于残差行为的不同信息。
# Plot residuals vs fitted
plot(model, 1)
残差与拟合
残差在值 0 附近徘徊,这是线性模型非常适合的良好指标。点 2 看起来确实像一个异常值,但是很难用几个值来区分。
我们可以使用的另一个图叫做 QQ 图,它是一个散点图,描绘两组分位数之间的关系。在我们的例子中,我们感兴趣的是残差是否遵循正态分布,因此我们将绘制残差的分位数与正态分布的分位数。
如果我们的残差确实是正态分布的,我们应该会看到一个从左下角到右上角的对角线。
# QQ plot
plot(model, 2)
QQ 情节
对角线看起来非常接近除了点 2 之外的大多数数据点。这可能意味着从数据集中删除点 2 是值得的,这样可以得到更精确的线性模型。
结论
干得好,一路看完了这篇文章。我希望你已经了解了更多关于线性回归的概念,以及如何在 r。
概括地说,在本文中,我们讨论了:
- 什么是线性模型
- 如何拟合最佳拟合线
- 方差和 R 平方分析
- 截距和回归系数的显著性
- 如何使用线性模型进行预测
- 残差
如果你对学习数据科学和机器学习感兴趣,一定要看看我的其他文章。
快乐学习!
https://medium.com/swlh/customer-segmentation-using-k-means-clustering-in-r-a74d512a4cfa
回归基础:最近邻
原文:https://towardsdatascience.com/back-to-basics-nearest-neighbours-676d6f11a31?source=collection_archive---------73-----------------------
我们回到基础,并在密度估计和推荐系统的背景下研究最近邻方法
介绍
鉴于最近人工智能研究中基于深度学习的方法的大肆宣传的进展,特别是在 NLP 和 CV 中,是时候回到基础上了。许多基本方法,例如基于邻域的方法,在许多领域甚至在今天都非常有效。我们简要介绍最近邻方法及其在密度估计和推荐系统中的应用。讨论了基于用户和基于项目的协同过滤。最后,还讨论了冷启动和数据稀疏问题。
密度估计中的最近邻
先说密度估计的问题。简单地说,密度估计是基于观测数据,对不可观测的潜在概率密度函数的估计。它可以用来洞察你手头的数据,更好的是,它还可以用来生成合成数据。
一种最常见的密度估计方法是简单的直方图,其中我们计算一个面元内的点数,并使用计数来可视化潜在的分布。直方图的主要缺点是它在面元大小和面元位置方面对面元选择非常敏感。读者可以参考 scikit-learn 文档获得更好的插图。
一个更复杂的方法是使用一个内核(例如高斯内核)来代替简单的计数计数,并使用 Parzen 窗口来代替朴素箱。Parzen 窗口可以直观地理解为围绕数据点的定义区域。为了专注于直觉,详细的数学被有意省略了。主要思想仍然类似于直方图,我们仍然尝试使用区域(而不是箱)中的相邻点来估计概率密度,使用核(而不是简单计数)来平滑分布。
有关核密度估计的更多信息,请参考 Bishop 的 PRML 第 2 章或更多实用指南。
在核密度估计方法中,区域是固定的,而相邻点的数量可以根据局部数据稀疏性而变化。另一种方法是固定相邻点的数量 K,并扩展区域直到 K 个点被包含。这种方法被称为 K 近邻(KNN)。
KNN 方法(也称为核密度估计)是非参数方法的一种形式,因为它不假设训练数据的基本分布。相反,它“记住”整个训练数据,因此也被称为“基于记忆的方法”。当将 KNN 应用于分类时,它通过预定义的相似性度量(稍后将详细介绍)找到最近的邻居,或者换句话说,找到最相似的训练数据点,并且使用邻居点的标签通过例如多数投票来确定预测结果。
有些还将 KNN 标记为“基于实例的学习或“懒惰学习”,因为它不需要任何训练过程来拟合训练数据,重载计算被延迟到预测,并且基于预测样本邻域中的少数实例进行预测。正如我们将在后面看到的,在现实世界的实现中,可以进行一些工程优化来缓解这个问题。
优点和缺点
在算法的世界里,这永远是一个权衡的问题。
优点:
- 简单直观
- 高度通用(可以选择各种相似性度量结合特征工程来实现很多)
缺点:
- 空间复杂度高,因为需要“记忆”整个训练数据
- 预测期间的高时间复杂度,因为它需要穷尽搜索所有训练样本以形成邻域
也存在许多补救措施来解决上述缺点。一种方法是使用离线阶段来预先计算相似性得分并存储中间结果,这些结果可以在稍后的在线阶段被有效地获取。
对于大小为 N 且维数为 D 的数据集,计算所有样本对的相似性的计算成本为 O(DN)。使用 K-D 树,复杂度降低到 O(DNlogN),在 N 较大的情况下是显著的提升。
实际上,许多图书馆,scikit-learn 是最受欢迎的例子,已经通过在训练阶段构建有效的数据结构做到了这一点。一旦调用fit
方法,取决于算法选择(sklearn 提供kdtree, balltree, bruto
)。如果你正在寻找这种索引的更快的实现,看看这篇博客文章。
推荐者上下文中的最近邻
对于那些感兴趣的人来说,2019 年推荐系统顶级会议 RecSys 的最佳论文揭示了该领域深度学习研究的一些问题[1]。事实证明,基于邻居的方法仍然是一个强大的基线。
KNN 方法用于推荐系统中的协同过滤算法。CF 的核心是如何找到相似的用户或物品,形成对等群体或邻居。
在推荐器中有两种对称的基于邻域的 CF 方法,即基于用户的 CF 和基于项目的 CF。
如下图所示,在一个记录了用户消费模式的水果店中,目标是向 Bob 推荐水果。
改编自互联网(来源不明)
在左边的基于用户的方法中,Alice 被认为与我们的目标用户相似(实际上,我们通常会识别一组相似的用户),因为他们在消费行为中都喜欢西瓜和草莓。因此,基于相似用户分享相似水果口味的假设,我们向 Bob 推荐葡萄和橙子,因为那些是他的同行买的,而不是他买的。
基于用户的 CF 矩阵(图片由作者提供)
在右边的基于商品的方法中,我们寻找与目标用户已经购买的商品相似的商品。在这种情况下,Bob 已经购买了西瓜,西瓜与葡萄最相似,因为它们被许多重叠的用户(Alice 和 Eve)购买。所以推荐葡萄。
基于项目的 CF 矩阵(图片由作者提供)
正如我们已经看到的,基于项目和基于用户的 CF 方法的最重要的部分是选择正确的相似性度量和形成邻域。
一些相似性度量是:
- 欧几里得相似性
- 余弦相似性
- 贴现余弦相似度
- 基于相关性的相似性(皮尔逊)
- Jacaard 相似性
- 等等。
除了前面提到的关于 KNN 方法在空间和时间复杂度方面的问题之外,在推荐系统的应用领域中还出现了其他问题。
两个主要问题是:
- 冷启动:当新的项目或用户被添加到矩阵中时,会出现这个问题,结果是一个空向量,使得很难计算相似性和邻居,因此几乎不可能生成推荐。
- 数据稀疏性:即使在上面的玩具示例中,我们已经观察到稀疏性问题,矩阵中的一些条目丢失,导致不准确的相似性计算,降低推荐质量。在拥有大量商品和用户的网络商店中,一个用户只能与一小部分商品交互,矩阵本质上是稀疏的。
有许多方法可以缓解上述问题:
- 作为一种简单的方法,该系统可以通过向新用户推荐最受欢迎的商品来启动,然而,这失去了个性化的吸引力。
- 另一种通常采用的方法是使用某种“主动学习”来激励用户输入评级或隐式反馈(点击、喜欢/不喜欢按钮等)。)来填充系统。
- 一种颇具争议的方式是利用辅助信息,如社交网络分析,根据用户的社交圈推荐商品,前提是这些辅助信息是可访问的。这里的基本假设是,朋友们有相似的品味,并在现实生活中互相推荐商品。关于边信息用法的参考文献见【4】。
- 使用基于模型的方法,如矩阵分解,它本质上处理数据稀疏性问题,因为它基于现有的可用评级进行 MF。然而,这并没有真正解决问题,因为由于可用数据有限,它仍然会影响模型的准确性。对于 MF 方法,一个很好的教程写在[5]中。在 Aggarwal 的“推荐系统:教科书”中描述了关于隐式数据集和 NMF 的更高级 MF 的更完整的描述。
参考
[1]“我们真的有很大进步吗?最近神经推荐方法的令人担忧的分析”,https://arxiv.org/abs/1907.06902
[2]Aggarwal 的《推荐系统:教科书》
[3]用https://www.tablesgenerator.com/markdown_tables制作的桌子
[4]“关于附带信息的建议的研究评论:调查和研究方向”,https://arxiv.org/abs/1909.12807
[5]博客:https://albertau yeung . github . io/2017/04/23/python-matrix-factorization . html和代码:https://github . com/albertau yeung/matrix-factorization-in-python
用 Codex 和 COBOL 回到未来
原文:https://towardsdatascience.com/back-to-the-future-with-codex-and-cobol-766782f5ae8f?source=collection_archive---------7-----------------------
图片由皮特·伯肯肖通过维基百科 (CC BY 2.0)
OpenAI 的代码生成系统能处理打卡时代的代码吗?
COBOL 已经存在了六十多年。尽管人们齐心协力将越来越多的 COBOL 程序移植到现代语言中,但它并没有很快消失的迹象。仍然有很多 COBOL 在运行— 根据最近的一项估计接近 1/4 万亿行。有没有一种方法可以让我们加速将这些庞大的代码从穿孔卡片时代转移到 21 世纪?
早在 2020 年 GPT-3 问世时,我曾半心半意地试图让它将 COBOL 翻译成 Python,但没有得到任何有用的结果。现在我已经可以访问 Codex,我决定看看专门研究代码生成的模型是否能做得更好。Codex 能处理 COBOL 吗?在这篇文章中,我将描述一些我试图回答这个问题的实验。
目标
我想看看能否让 Codex 从 Python 生成有效的 COBOL,或者从 COBOL 生成有效的 Python。我注意到 COBOL 不是 OpenAI 声称 Codex 精通的语言之一,但是我认为这仍然值得一试,因为 Codex 的训练集中可能有一些 COBOL 代码。
实验 1:从 Python 到 COBOL 的 hello world
首先,我改编了在Codex介绍中列出的一个例子。这个提示示例用于从 Python 生成 R:
# Convert this from Python to R
# Python version [ Python code ] # End
# R version
我修改了这个提示,使 COBOL 成为目标语言:
# Convert this from Python to COBOL
# Python versionprint("hello world")# End# COBOL version
果然,根据这个提示,Codex 生成了一些看起来可能是有效的 COBOL 的东西:
我已经有几十年没有用 COBOL 编码了,所以我不能信任我的内部编译器。我需要找到一种方法来测试 Codex 在实际的 COBOL 环境中生成的东西。幸运的是,我能够找到并安装 OpenCobol IDE 。有了这个 IDE,我可以练习 Codex 生成的 COBOL“hello world”代码。
我将 Codex 的输出粘贴到 OpenCobol 中,但是它不认为它是有效的 Cobol:
OpenCobol 中 Codex 的原始输出—作者图片
看到这个问题,我隐约记得需要将 COBOL 代码限制在某些列中。这与为穿孔卡上的序列号保留前几列有关。您认为这篇文章的介绍插图是某种玩笑!
为了清理 Codex 的输出,我缩进了所有代码行,使它们从第 8 列开始,并删除了前缀“#”以获得以下代码:
清理了 OpenCobol 中 Codex 的输出—图片由作者提供
我点击锤子图标编译代码,然后点击运行按钮。令我高兴的是,代码运行了!
所以,Codex 可以产生一个最小的 COBOL 程序。在下一个实验中,我们将尝试相反的方向,从 COBOL 到 Python。
实验二:从 COBOL 到 Python 的 hello world
将 Python 翻译成 COBOL 是一个有趣的用例,但在现实世界中,从 COBOL 翻译成 Python(或另一种现代语言)可能更有用。让我们看看当我们试图让 Codex 将它在上次实验中生成的 COBOL“hello world”翻译回 Python 时会发生什么。
下面是我们开始时的提示:
# Convert this from COBOL to Python
# COBOL versionIDENTIFICATION DIVISION.
PROGRAM-ID. HELLO-WORLD.
PROCEDURE DIVISION.
DISPLAY 'hello world'.
STOP RUN.# End# Python version
以下是食品法典委员会得出的结果:
print('hello world')
为了完全公开,Codex 还运行了 bit 并生成了以下 COBOL:
IDENTIFICATION DIVISION.
PROGRAM-ID. HELLO-WORLD.
PROCEDURE DIVISION.
DISPLAY 'hello world'.
DISPLAY 'hello world'.
DISPLAY 'hello world'.
DISPLAY 'hello world'.
DISPLAY 'hello world'.
STOP RUN.
在 OpenCobol 中尝试这一点,它如预期的那样工作:
因此,Codex 可以在 Python 和 COBOL 之间来回调用“hello world”。它将如何处理涉及 COBOL 的更复杂的挑战?
实验 3:对两个数求和——Python 对 COBOL
生成一个 COBOL“hello world”程序并不是 Codex 的最高标准。它能处理稍微复杂一点的程序吗?为了找到答案,我让它从一个返回两个函数之和的 Python 函数生成 COBOL:
# Convert this from Python to COBOL
# Python versiondef sum_integers(integer1, integer2):
return(integer1 + integer2)# End# COBOL version
以下是 Codex 生成的内容:
# IDENTIFICATION DIVISION.
# PROGRAM-ID. PYTHON_TO_COBOL.
# PROCEDURE DIVISION.
# FUNCTION SUM-INTEGERS (INTEGER1, INTEGER2)
# RETURNING INTEGER
# BEGIN-PROCEDURE
# RETURN (INTEGER1 + INTEGER2);
# END-PROCEDURE.
# END.
我将这段代码粘贴到 OpenCobol 中,并做了与“hello world”程序相同的小清理:
OpenCobol 中两个数相加的 Codex 输出—作者图片
即使我对 COBOL 有模糊的记忆,我也能看出这离工作 COBOL 代码还很远。在某种程度上,我缺乏 COBOL 技能在这个练习中是一个优势,因为我不能真正为 Codex 倾斜天平。要么它产生的 COBOL 只需很少的改动,要么实验失败。在这种情况下,实验失败了。
实验 4:将两个数相加——COBOL 到 Python
由于 Codex 无法从一个将两个数相加的 Python 程序中产生有效的 COBOL,我决定尝试另一个方向。我找到了一个将两个数相加的 COBOL 程序,我想看看 Codex 是否可以用这个输入生成可用的 Python。
这是我开始使用的 COBOL 程序,改编自将来自代码 POC 的两个数相加的程序。我必须做一些修改(去掉反斜杠)才能让代码在 OpenCobol 中正确编译。
这是这个 COBOL 程序在 OpenCobol 中的输出:
以下是 Codex 以 COBOL 程序作为输入生成的初始 Python 输出:
# ```
# A = int(input("Enter A: "))
# B = int(input("Enter B: "))
#
# print("-----------------------------------------------")
# print("A is ", A)
# print("B is ", B)
# print("-----------------------------------------------")
#
# ANS = A + B
#
# print("A + B = ", ANS)
# print("-----------------------------------------------")
# ```
我清理了这个输出,删除了无关的“#”,得到了最终的 Python 程序:
# ```
A = int(input("Enter A: "))
B = int(input("Enter B: "))
#
print("-----------------------------------------------")
print("A is ", A)
print("B is ", B)
print("-----------------------------------------------")
#
ANS = A + B
#
print("A + B = ", ANS)
print("-----------------------------------------------")
# ```
在 Python 3.7.4 中运行,代码如预期的那样工作:
Enter A: 3
Enter B: 4
-----------------------------------------------
A is 3
B is 4
-----------------------------------------------
A + B = 7
-----------------------------------------------
因此,虽然 Codex 不能从 Python 代码生成有效的 COBOL 来对两个数求和,但是当给定一个对两个数求和的 COBOL 程序时,它会生成有效的 Python。
结论
以下是我从本文描述的实验中得出的主要观察结果:
- 我不认为从本文中列出的 4 个简单实验的结果中就能决定 Codex 是否能处理 COBOL 的翻译。
- COBOL 语法与任何现代语言都有很大不同,我之前让 GPT-3 用 COBOL 做任何事情的尝试都令人失望,如果 Codex 没有通过所有 4 项测试,我也不会感到惊讶。此外,Codex 并没有被专门训练来处理 COBOL,它仍然设法处理一些涉及 COBOL 的基本任务。
- 简单来说,Codex 超出了我的预期。Codex 能够双向生成“hello world ”,并且能够从一个(勉强)非平凡的 COBOL 程序生成工作 Python。
从用 Python 等现代语言编写的程序中生成 COBOL 在某些情况下可能是有用的。然而,我认为真正有趣的用例是从 COBOL 程序生成 21 世纪的代码。如果我们能够自动清除目前保持正常运行的 1/4 万亿行 COBOL 代码,并用更易于维护的现代代码来替换这些代码,那将是一件非常美妙的事情。也许法典的后代可以做到这一点,让我们最终结束穿孔卡片的时代。
其他详细信息:
- 你可以在这里看到这篇文章的视频:【https://youtu.be/uTIk2fifO50
- 你可以在这个回购中找到这篇文章的代码样本:【https://github.com/ryanmark1867/codex_experiment
- 更多实验:深入了解为什么 Codex 努力从 COBOL 生成 Python 和使用 Codex 从 COBOL 生成 JavaScript
- 你可以在本文的中看到一个从英语生成 JavaScript 的 Codex 实验
回到城市集群:天体和地图
原文:https://towardsdatascience.com/back-to-the-municipality-clusters-celestial-objects-and-maps-55c64e39f805?source=collection_archive---------54-----------------------
塞尔吉奥·索萨在 Unsplash 上的照片
就在 2020 年的八月,我写了一篇的文章,展示了从与 GDP 相关的变量中得出的城市集群模型的发现。是时候再次参观这个模型并进行新的实验了。在这里,报告将集中在易于用视觉模式解释的发现上。
这个想法是在分布图和地图中详细描述集群。在 XKCD 天文灵感和它的黑银调色板的帮助下,我们组装了图形,至少在视觉上解决了变量的分布问题。
星系、星云和对数
旅程从星星开始。这里使用的数据提出了一个巨大的分布问题。我们比较了像沙普里和圣保罗这样不同的城市。为了有一些成功的图形解释,我们借鉴 XKCD 的想法代表各种天体距离地球。一个对数标度的巨大图表允许把长颈鹿的高度和离这里很远的星云和星系的天文距离放在同一个数字中。
逐渐滚动屏幕,在哈勃望远镜观察到的最遥远的物体和我们踩着的地面之间做出相反的路径。小心不要摔倒。
XKCD 宇宙距离视野:https://xkcd.com/482/
国内生产总值组成部分和人均国内生产总值的模糊不清
这里评估的变量总是经济部门的组成部分:农业、行政、工业和服务业。我们也分析人均 GDP 数据。记住所有数据都是指巴西各城市的变量。
当对数标度的变量分布完成后,人们可以感知图像的形成,回忆起天文学教科书中描述的星云。
各市国内生产总值各组成部分的对数分布(以千雷亚尔计)。作者图片
从上图中可以看出:
- 管理变量在 10,000 和 100,000 之间的范围内呈现大的点集中,然后有大的分散,直到接近 100 Mi。
- 其他变量也显示了浓度范围,尽管密度较低。
- 最分散的变量是工业,对最低值负责的变量是农业,达到最高值的变量是服务业。
各市人均国内生产总值的对数分布(以 1 雷亚尔计)。作者图片
鉴于规模的差异,人均国内生产总值的分析总是在单独的图表中进行,因为它是国内生产总值和人口之间的比率。上图显示了一个浓度,该浓度从略高于 5000 雷亚尔的位置开始,达到 50000 雷亚尔的位置,然后这些点被分散。这些分散特征是确定形成的六个集群的基础。在接下来的部分,我们将看到如何用与每个星团相关的颜色填充星云点。
从星团中给星云上色
以变量值表示的巴西不平等最终成为六个集群的决定因素。总体而言,国内生产总值和人均国内生产总值的较低值出现在第 1、2 和 3 组,而较高值出现在第 4、5 和 6 组。利用这一特性,总是可以从两个超簇中进行簇分析。这允许更清晰的视觉分析,从而有助于更好地识别聚类的特征。
作者图片
从上图中可以看出:
- 聚类 4、5 和 6 比其他聚类分布在更大的值范围内
- 第 3 组和第 6 组集中在农业部门
- 第 6 组代表最高值的部门:行政、工业和服务业
作者图片
说到人均 GDP,从上图可以看出:
- 聚类 1 密集地位于最低值中
- 第 5 组尽管分散在国内生产总值的各个组成部分中,但在人均国内生产总值分析中被认为占据了最高值的范围
六维中心的水母
用于这项工作的聚类算法的特点是能够识别所谓的水母。这个奇怪的名字与六个维度形成的集群中心点相关联:我们在这里分析的五个变量和总 GDP。
medoids 的概念可以与描述统计学中的平均值和中值进行比较,即确定最能表征一组数据的元素。在我们的研究中,从分析变量的角度来看,medoids 是六个集群中每个集群的最佳特征。
作者图片
当我们分析经济部门的 medoids 时,我们认识到:
- 代表聚类 6 的 Blumenau 与除农业部门之外的其他 medoids 相距甚远。在这种情况下,它排在第三位。
- Assis Chateaubriand 是第 5 组的特点,在农业部门领先,与其他部门有很大不同。
- 行政部门是聚类 1 至 5 的 medoids 彼此最相似的地方。
作者图片
当分析人均国内生产总值时,人们认识到:
- Blumenau 和 Nova Veneza(星团 4 的水母)非常接近
- Santa Maria do Suaç,聚类 1 的水母类完全被其他水母类取代,呈现非常低的值。
回到地球和制图表达
现在讨论制图表达,研究结果对聚类及其跨城市的分布特征有什么影响?在八月份的文章中,我们用地图做了第一次实验。现在我们来看另一个例子,它显示了从一个簇的 medoids 分析该簇的影响。但是首先我们将在巴西地图上画出这些集群和它们各自的城市。
作者图片
我用来识别聚类的算法的结果表明,组 1 是最有凝聚力的。据观察,这种凝聚力也是地理上的。东北部各州集中了这个集群中的大部分城市。米纳斯吉拉斯州北部也有大量具有这种特征的城镇。这里值得记住的是,这一组在五个变量中的值最低,特别是人均国内生产总值,这加剧了影响巴西这些地区的收入分配不均和贫困状况。
该地图还显示了圣保罗州的财富带以及主要分布在南部和东南部各州的其他集群。同样值得注意的是,中西部少数几个城市与农业部门的高 GDP 集群有很大关联。
值得记住的是,我们需要回到梅多伊德。我已经指出了这些城市,但我还没有说它们在哪里。下面的地图纠正了这个差距。
作者图片
六个城市集中在东南部和南部地区。巴拉那有两个市,圣卡塔林纳有两个市,圣保罗有一个市,米纳斯吉拉斯有一个市。
总的来说,考虑到南部和东南部地区的城市集中,预计这主要是针对第 2 至第 6 类城市。群组 1 的 medoids 位于米纳斯吉拉斯州也不足为奇,因为 Santa Maria do Suaç uí位于该州北部,因此位于该群组主要城市所在的区域。
使用 medoids 作为参考,可以进行一些地图分析。现在,我将重点介绍第一组的人均国内生产总值。在下面的地图中,接近蓝色的阴影表示人均 GDP 高于圣玛丽亚岛的城市。更接近粉色的颜色是 GDP 低于我们参考值的城市。对于这两个方向,颜色越深表示距离参考点越远。
作者图片
聚类的 medoids 和 GDP 值接近 medoids 的城市位于两种色调之间的过渡范围内。从图例中可以看出,这个过渡带位于所考虑的区间的中间。从视觉上可以观察到色调有一点不平衡。显然,接近粉色调的城市比接近蓝色调的城市要多一些。实际上,集群 1 的分布是这样的:
- 人均国内生产总值高于梅多伊德市的 1221 个市。
- 人均国内生产总值低于梅多伊德市的 1103 个市。
需要注意的是,在上面的地图上,即使在星团内部,地理模式也会重复出现。数值较低的城市正好集中在米纳斯吉拉斯州的东北部和北部。具有最高值的点分散在其他区域中。
下一次星际旅行
所介绍的研究结果似乎对主要涉及不平等相关主题的几项研究很重要。因此,发展可能走向与联邦制及其减少不平等的目标有关的研究。研究影响不平等效果甚至其原因的公共政策也可能是有趣的。
还值得注意的是,聚类方法也可以用于定性方法的研究。Medoids 和聚类中其他点到 medoids 的距离有助于识别城市,以便进行更深入的原位研究,其中经济产出和 GDP 分布的维度与直辖市的选择相关。甚至试点公共政策项目的城市定义也可以使用这种方法。
最后,希望对不平等的阐述能够有助于各城市之间的社会经济差异越来越少地用天文单位来衡量。
代码和数据
代码在我的 Github 中。看看那里。我强调使用地理图书馆在制作地图时总是很有帮助。
其他文本中使用的数据相同。这是 2017 年直辖市的 GDP 数据库。
承认
我感谢 Tiago Maranhã提供了最准确的数据可视化技巧,并向我介绍了 XKCD。建议在 twitter 关注他那里。我也感谢莫尼卡和但丁选择了这些颜色。
备份您有价值的 BigQuery 视图和计划查询
原文:https://towardsdatascience.com/back-up-your-valuable-bigquery-views-and-scheduled-queries-424791b6f2c7?source=collection_archive---------19-----------------------
你的宝贝 SQL 也需要一些爱
原图卡莉·谢伊
进行数据备份很重要。但是隐藏在视图和预定查询中的宝贵的 SQL 代码呢?本教程将向您展示如何使用 Python 将所有 SQL 代码备份到 Git 存储库中。
在许多情况下,视图和预定查询包含了所有艰苦工作(和花费的大量时间)的结果。它们基本上包含了很多构建模块。想想数据转换、特征工程、选择甚至模型本身。
注: 你喜欢这篇文章吗?阅读 原文 (以及其他许多动手营销技术相关文章)上stacktonic.com🚀
此外,当很多用户积极参与谷歌云平台(GCP)环境的开发时,很难跟踪视图和预定查询的变化。
本教程中提供的解决方案将:
- 备份您的 BigQuery 视图和调度查询*到本地文件系统上的
.sql
文件。* - 能够提交对一个 Git 库的更改。定期运行脚本时,可以跟踪变更历史。
- 支持多个 GCP 项目。
准备
我们将使用服务帐户对您的 Google 云项目进行身份验证。
通过将此具有正确角色的服务帐户添加到您想要备份的所有 GCP 项目,您可以对所有项目使用相同的服务帐户。
如果你不熟悉设置服务账户,请先阅读谷歌文档。
- 创建一个服务帐户,并为该帐户启用
BigQuery User
角色。 - 为服务帐户生成并下载 JSON 密钥文件。
- 在您的 GCP 项目中启用
Data Transfer API
脚本如何工作
- Python 脚本将获取脚本中配置的 GCP 项目中所有视图和计划查询的 SQL 代码。
- 文件被下载到您的本地文件系统。
- 当您启用
REPO_COMMIT
设置时,脚本将首先克隆一个(远程)存储库,获取视图和预定查询 SQL,并将更改提交给存储库。在克隆远程存储库之前,它将首先删除旧版本的存储库
当使用 Git 存储库备份 SQL 和跟踪变更历史时,可以使用 SSH 密钥进行认证。参见 GitHub 或bit bucket的说明
文件结构
该脚本将根据以下文件夹/文件结构创建和填充:
**
安装和运行代码
安装包
该脚本需要一些依赖项。使用pip
来安装这些包:
*pip install google-auth
pip install google-cloud-bigquery
pip install GitPython*
最后一步是调整脚本中的设置:
现在,您已经准备好运行代码了:
*python backup_views_scheduled_queries.py*
Python 脚本
手动将代码保存到一个文件中,或者直接从我们的 GitHub 库下载代码。
backup _ views _ scheduled _ query . py
一些最后的提示
- 您可能希望每天安排这个脚本。你可以使用你最喜欢的调度工具,比如 Apache Airflow 或者 good ol' cronjobs。
- 在 windows 上,配置 SSH 密钥可能会给您带来一些麻烦。参见 GitHub 和 Bitbucket 文档进行故障排除。
背景噪声去除:传统算法与人工智能算法
原文:https://towardsdatascience.com/background-noise-removal-traditional-vs-ai-algorithms-9e7ec5776173?source=collection_archive---------7-----------------------
将深度学习噪声去除模型与旧的减法模型进行比较。
凯利·西克玛在 Unsplash 上的照片
噪音无处不在。无论你是在舒适的家中还是走在街上,垃圾车的声音或你的狗的叫声都会很快成为一种骚扰。尤其是在数字时代,所有这些噪音都会被麦克风拾取,干扰我们的交流。所以,让我们来看看我们如何才能删除它!
背景噪声去除 是通过隔离主导声音来增强嘈杂语音信号的能力。背景噪声消除无处不在——它出现在音频/视频编辑软件、视频会议平台和降噪耳机中。因此,背景噪音消除仍然是一项快速发展的技术,人工智能带来了一个全新的领域来改善这项任务。
今天,让我们通过查看 传统方法和基于机器学习的方法 来探索背景噪声去除是如何工作的。
传统的去噪方法
大多数噪声去除算法是减法,识别具有较高水平背景噪声的某些频率,并从原始信号中减去这些频带。许多这样的方法使用静态滤波器,例如低通、高通和带通滤波器,它们被设计成具有特定的参数,以隔离被认为是主导信号的信号。这些算法最适用于确定性信号,在这种信号中,被滤波的噪声类型和被隔离的噪声类型几乎没有不确定性。实际上,这些滤波器在变化的条件下是非常无效的,特别是在背景噪声的特性与要分离的干净信号重叠的情况下。诺伯特·维纳采取了不同的方法,放弃了给定噪声信号是确定性的假设。
维纳滤波
来源:https://medium . com/audio-processing-by-MATLAB/noise-reduction-by-wiener-filter-by-MATLAB-44438 af 83 f 96
维纳滤波是动态信号处理的工业标准,广泛用于助听器和其他边缘设备,如电话和通信设备。给定两个音频信号,自适应滤波器工作得最好:一个具有语音和背景噪声,另一个仅测量背景噪声。现代智能手机设计师通常会将两个麦克风放置在彼此相距一定距离的位置,一个放置在说话者的嘴附近,以记录嘈杂的语音,另一个可以测量环境噪声,以滤除噪声。
你可能会想,如果我们有一个背景噪音和嘈杂的语音分离的信号,为什么我们不能简单地从嘈杂的语音减去背景噪音,以分离干净的语音?虽然这种方法看起来很直观,但结果并不完全符合我们的预期。事实证明,这种做法行不通有很多原因。麦克风之间的宏观距离使两者所处的环境略有不同。因此,我们不能通过简单的信号相减来消除大部分噪声元素,因为噪声是由许多因素引起的,包括硬件组件中的静电电荷和环境中的微小振动,所有这些因素都会随着环境的微小变化而发生巨大变化。
然而,维纳滤波器使用这两个信号的特性来产生干净语音的估计。然后计算一个误差,称为均方误差,并将其最小化,以便产生干净语音的最佳估计。
不幸的是,维纳滤波也有缺点:
- 首先,为了充分发挥其优势,需要两种不同的音频信号。在许多情况下,例如在驾驶舱或智能手机中,双麦克风系统很实用,但在更普遍的情况下,能够处理来自单个音频流的噪声会更有利。
- 第二,在背景噪声的频谱属性与语音的频谱属性重叠的情况下,音频中可能存在明显的语音失真。滤波器的减法性质可以去除听起来类似于背景噪声的语音部分。随着深度学习的兴起,这些问题很多都得到了解决。
人工智能去噪方法
人工神经网络是一个古老的想法,最近以深度学习的形式爆发出来。虽然有不同的深度学习方法来消除噪声,但它们都是通过从训练数据集学习来工作的。
噪声去除的训练数据集
建立准确的噪声去除模型的第一步是构建高质量的训练数据集。由于我们的目标是去除背景噪声,我们的数据集应该由干净语音与其嘈杂变体配对的记录组成。
在组装数据集之前,考虑模型的用例非常重要。例如,当训练将应用于来自直升机飞行员麦克风的信号的噪声去除算法时,用被直升机声音的变化扭曲的音频样本来训练网络是最有意义的。对于一个通用的噪声去除模型,用日常背景声音的样本进行训练是有意义的,例如大声的聊天、空调、打字、狗叫、交通、音乐——你明白了。
一旦我们弄清楚了我们想要用什么样的数据进行训练,我们就必须实际生成数据集。最好的方法是找到大量干净的语音信号和纯噪声信号,并以各种方式组合它们。例如,您可以将一个高质量的人说话的样本和一个狗叫的样本组合在一起,生成一个背景中有人说话且有狗叫的新样本。因此,通过提供说话人的原始样本以及带有语音和狗叫声的样本,神经网络可以重复地将其估计的干净语音信号与实际的干净语音信号进行比较,然后调整自身并再次尝试。
最后,我们现在可以将我们的数据集输入到神经网络,这样它就可以学习隔离背景噪音并生成干净的语音。用于音频处理的最流行和最有效的方法之一是递归神经网络。
递归神经网络(RNN)
递归神经网络是可以识别和理解序列数据的模型。顺序数据包括音频、文本或对象在一段时间内的位置。
rnn 对于去除背景噪声特别有效,因为它们可以随着时间学习模式,这对于理解音频是必不可少的。
那么 RNNs 是如何工作的呢?首先,让我们来看一个前馈神经网络,它有三个主要层:输入层、隐藏层和输出层。RNNs 从隐藏层引入了一个称为隐藏状态的反馈循环,当模型以某种顺序处理每个项目时,隐藏状态会自我更新。
来源:https://medium.com/@Aj.程/different-between-CNN-rnn-quote-7c 224795 db 58
为了了解这一点,让我们观察一个 RNN,它被训练来隔离嘈杂音频样本的背景噪声。我们可以将音频样本分解成一系列均匀间隔的时间间隔。当序列的每个单独的样本被传递到 RNN 时,隐藏状态在每次迭代期间被更新,每次都保留先前步骤的记忆。在迭代结束时,输出通过前馈神经网络发送,以生成背景噪声被完全去除的新音频流。听起来像魔术?是啊,算是吧!
然而,RNN 也有自己的陷阱。最重要的问题是,它们不能有效地长时间保留信息。这是由于在称为反向传播的过程中梯度消失的问题。虽然我不想被细节冲昏头脑,但这里的是了解更多信息的好资源。
这种长期记忆的缺乏使得 RNNs 在长期记忆非常有用的过程中效率较低。因此,研究人员发明了传统 RNN 的变体,使用门来解决这个问题。门是可以学习向隐藏状态添加或删除什么信息的操作。使用这些门的两个主要神经网络是长短期记忆(LSTM)和门控循环单元(GRU)。这两种方法都比简单的递归网络计算量大得多,但更适合我们的去噪任务。
从这里,有各种各样的方向,我们可以去。一些模型被设计成执行背景噪声去除的端到端任务,但是这也意味着它们在计算上更加密集并且在尺寸上更大。这些模型非常强大,经常用于语音识别。其他人采用更混合的方法,使用传统的减法噪声去除来预处理数据,然后应用神经网络来处理样本中仍然存在的任何非静态背景噪声。虽然这两种方法都是有效的,但是它们的使用依赖于开发者的计算资源和期望的精度。
那么哪种方法更好呢?
自麦克风发明以来,背景噪声降低一直是音频处理中感兴趣的主要领域。有数百种过滤音频的传统方法,但许多方法(如果不是全部的话)在处理非静态音频时效果不佳,并且当背景噪声与主扬声器混合时会引入失真。随着计算能力的增长和我们建立能够长时间记住复杂模式的深度学习模型的能力,我们已经能够训练计算机在特定任务上变得异常出色。通过用大量数据训练深度学习模型,计算机已经变得格外能够消除音频中的噪声。
那么,哪种方法更好呢?如果计算资源和等待时间无关紧要,人工智能方法远远优于传统方法。这是因为它们是生成性的,而传统模型是减法性的。人工智能方法能够生成一个全新的音频信号,消除背景噪声,并使清晰的语音失真最小。
如果计算资源和等待时间是一个问题,鉴于当今的技术,人工智能方法可能是不切实际的实施。模型的处理时间有时会给处理带来延迟,这在某些情况下是不希望的。然而,在可预见的未来,这肯定不会是一个大问题。神经网络每天都在变得更快、更有效、更容易使用,最终它们将成为标准。
最初发布于 Audo AI 。
…
感谢您花时间阅读本文。一如既往,我感谢您的任何意见/反馈。
欢迎在我的媒体页面或奥多艾的博客查看我的其他作品!
使用 Python 去除背景
原文:https://towardsdatascience.com/background-removal-with-python-b61671d1508a?source=collection_archive---------1-----------------------
使用 OpenCV 检测前景
奥斯塔普·森尤克在 Unsplash 上拍摄的照片
我们生活在视频通话的时代。我们通过互联网,使用笔记本或电脑自带的任何相机,向我们的同学、同事和家人直播我们的生活。
但是,有时我们不想广播我们的空间。我的办公室,像许多其他办公室一样,有一些常年的杂物。我身后的墙上也有一把吉他,不总是喊专业。
因此,Zoom 和其他视频通话软件包含了隐藏背景的功能,通常隐藏在您选择的图像后面。虽然大多数人不太想它,但确定图像中前景和背景的实际任务很难忽略。
前景检测
前景检测是计算机视觉中最重要的应用之一。除了视频呼叫的例子之外,前景检测可以用于寻找和读取图像中的文本、确定自主车辆中障碍物的位置以及许多其他应用。
因此,已经开发了许多复杂的方法来区分前景和背景。
OpenCV 提供了几个“开箱即用”的解决方案;然而,如果没有任何其他背景,这些都是黑箱,不会提供太多学习的机会。相反,我将使用一个利用几个 OpenCV 模块的定制算法来实现类似的结果。
边缘检测和轮廓
我将演示的方法基于两个概念:边缘检测和轮廓。
顾名思义,边缘检测试图在图像中找到对比线或边缘。这个关键的第一步是预处理图像,以帮助区分任何对象。存在几种边缘检测方法,但是 Canny 方法非常受欢迎,并且与 OpenCV 打包在一起。
一旦找到了边缘,寻找轮廓就变得更加容易和准确。在计算机视觉中,轮廓仅仅是对比色或强度区域之间的连续边界线。与边缘检测不同,寻找轮廓将在图像中找到突出的形状。
该算法
如前所述,OpenCV 中预打包的背景移除器将不会被使用。相反,下面的流程图概述了我将使用的方法:
首先,我们将图像转换成黑白。接下来,将应用边缘检测,并且将找到图像中的轮廓。任何太大或太小而不能作为前景的轮廓都将被移除。
剩余的轮廓将被视为前景。这有一些直观的意义,因为在繁忙的背景下,特别小的细节会产生非常小的轮廓。相比之下,占据大部分屏幕的非常大的轮廓可能不是前景,而是背景的一些视觉假象。
最后,从剩余的轮廓中生成掩模,并将其融合到原始图像中。
履行
import numpy as np
import cv2
在做很多事情之前,需要导入两个库。NumPy 致力于让一些数字运算更有效率。OpenCV 处理图像操作。
# Parameters
blur = 21
canny_low = 15
canny_high = 150
min_area = 0.0005
max_area = 0.95
dilate_iter = 10
erode_iter = 10
mask_color = (0.0,0.0,0.0)
接下来,分配一组变量,这些变量将影响如何去除背景。每个变量都有独特的效果,可能需要根据视频的主题进行微调。简而言之:
- 模糊:影响背景和前景之间分界线的“平滑度”
- canny_low:沿其绘制边缘的最小亮度值
- canny_high:沿其绘制边缘的最大亮度值
- min_area:前景中轮廓可能占据的最小面积。取 0 到 1 之间的值。
- max_area:前景中轮廓可能占据的最大面积。取 0 到 1 之间的值。
- dilate_iter:将在遮罩上发生的膨胀的迭代次数。
- 腐蚀 iter:掩模上腐蚀的迭代次数。
- mask_color:背景移除后的颜色。
这些解释中的一些可能还没有意义,但是当它们出现在代码中时,将会被进一步解释。与此同时,您可以随意将所提供的值作为默认值来开始使用。
# initialize video from the webcam
video = cv2.VideoCapture(0)
接下来,初始化网络摄像机(如果可用)。如果没有视频文件的路径,可以用 0 来代替。
while True:
ret, frame = video.read()
从摄像机读取帧开始一个无限循环。read 方法返回 2 个值:
- 一个布尔值,用来判断相机是否正常工作,存储在 ret 变量中
- 来自视频源的实际帧,记录在 frame 变量中。
if ret == True: # Convert image to grayscale
image_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # Apply Canny Edge Dection
edges = cv2.Canny(image_gray, canny_low, canny_high)
if 子句只允许代码在摄像机正确捕获视频的情况下继续执行。该帧被渲染成灰度,因此可以进行下一步,边缘检测。
设置强度值最小值(canny_low 变量)决定了检测对比度的灵敏度。将其调整得太低可能会导致检测到过多的边缘。
将强度值设置为最大值(canny_high 变量)表示任何高于该值的对比度将立即被分类为边缘。将其调得太高可能会影响性能,但将其调得太低可能会错过重要的优势。
edges = cv2.dilate(edges, None)
edges = cv2.erode(edges, None)
这一步严格来说是可选的,但是扩张和侵蚀边缘会使它们更明显,并返回更好的最终产品。
# get the contours and their areas
contour_info = [(c, cv2.contourArea(c),) for c in cv2.findContours(edges, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)[1]]
这一行有很多内容,但它是为了性能而这样写的。本质上,OpenCV 函数 findContours 返回一组信息。在这些信息中,我们只关心轮廓,其索引为 1。
对于找到的所有轮廓,实际轮廓本身及其面积的元组存储在一个列表中。
# Get the area of the image as a comparison
image_area = frame.shape[0] * frame.shape[1]
# calculate max and min areas in terms of pixels
max_area = max_area * image_area
min_area = min_area * image_area
计算图像的面积,然后确定最大和最小面积。
理想情况下,这一步应该在循环之外进行,因为它会影响性能。在流式传输之前拍摄一个初始帧或者简单地预先知道你的相机的尺寸会更有效。也就是说,为了让代码在演示时简单一点,这就足够了。
# Set up mask with a matrix of 0's
mask = np.zeros(edges.shape, dtype = np.uint8)
接下来,创建一个掩码,此时它是一个 0 的矩阵。
# Go through and find relevant contours and apply to mask
for contour in contour_info: # Instead of worrying about all the smaller contours, if the area is smaller than the min, the loop will break
if contour[1] > min_area and contour[1] < max_area:
# Add contour to mask
mask = cv2.fillConvexPoly(mask, contour[0], (255))
对于找到的所有轮廓,将轮廓面积与最小值和最大值进行比较。如果轮廓大于最小值而小于最大值,轮廓将被添加到遮罩中。
如果轮廓小于最小值或大于最大值,它不会被视为前景的一部分。
# use dilate, erode, and blur to smooth out the mask
mask = cv2.dilate(mask, None, iterations=mask_dilate_iter)
mask = cv2.erode(mask, None, iterations=mask_erode_iter)
mask = cv2.GaussianBlur(mask, (blur, blur), 0)
像以前一样,扩张和侵蚀面膜在技术上是可选的,但创造了更美观的效果。同样的原理也适用于高斯模糊。
# Ensures data types match up
mask_stack = mask_stack.astype('float32') / 255.0
frame = frame.astype('float32') / 255.0
这些行将遮罩和框架转换成它们需要混合在一起的所需数据类型。这是一个平凡但重要的预处理步骤。
# Blend the image and the mask
masked = (mask_stack * frame) + ((1-mask_stack) * mask_color)
masked = (masked * 255).astype('uint8') cv2.imshow("Foreground", masked)
最后,蒙版和框架混合在一起,使背景被涂黑。最后一行显示结果。
# Use the q button to quit the operation
if cv2.waitKey(60) & 0xff == ord('q'):
break else:
breakcv2.destroyAllWindows()
video.release()
作为最后一分钟的清理,前几行创建了一个 exist 条件。如果按下键盘上的“q ”,将会中断循环并终止程序。
else 连接回之前关于相机正确捕捉帧的 if 语句。如果相机出现故障,也会中断循环。
最后,一旦循环中断,显示结果图像的窗口关闭,相机关闭。
结果
如果一切顺利,应该会创建一个显示实时背景去除的输出窗口。虽然这里的算法对于非常简单的背景足够好,但是它可能在区分更复杂的“繁忙”或混乱的背景时有更多的困难。然而,总的来说,它很好地证明了这个概念。
下面给出了一个理想的例子,我站在一面普通的白墙边:
理想情况下实时去除背景。作者制作的视频。
算法很容易就能把我和墙区分开来。有一些口吃可能需要消除,但对于第一次尝试来说,它做得很好。
相反,这是我靠在书架上的最坏情况下的结果:
恶劣条件下的背景去除。作者制作的视频。
非常繁忙的背景,如装满书籍和其他配件的书架,会混淆算法,导致不太完美的结果。当我的手臂和脸的大片在背景中闪烁时,它很难区分前景和背景。
我确实有点夸大了这个结果。我把后背靠在书柜上,这样放大了效果。如果我站在书柜前面更远的地方,结果就不会这么糟糕;然而,它说明了在不太理想的情况下背景减除的困难。
实际上,大多数尝试都会产生介于最好和最坏情况之间的结果。
结论
前景检测和背景减除这两个相互交织的概念是计算机视觉研究最多的方面之一。虽然存在许多方法,但是边缘检测和在图像中寻找轮廓的简单应用提供了良好的基础。
使用 OpenCV 的内置函数,所使用的方法能够实时渲染背景去除。在理想条件下,该算法几乎完美无缺,但对于复杂或繁忙的背景,可能需要一些额外的调整。
从头开始反向传播:神经网络如何真正工作
原文:https://towardsdatascience.com/backpropagation-from-scratch-how-neural-networks-really-work-36ee4af202bf?source=collection_archive---------5-----------------------
神经网络究竟是如何工作的?我将向您展示一个完整的示例,它是用 Python 从头开始编写的,包含您完全理解该过程所需的所有数学知识。
我也会用简单的英语解释一切。你可以跟着读,只读课文,仍然能得到大意。但是要自己从头开始重新实现一切,你必须理解数学和代码。
我看过几篇这样的文章,但在大多数情况下,它们是不完整的。我想给这个话题一个完整的治疗:所有的数学+工作代码,包括电池。
你必须掌握线性代数、微积分和统计学,才能完全理解数学部分:矩阵乘法、点积、偏导数、链式法则、正态分布、概率、标准差等。
我们试图解决的问题
我们有一大组图像,每个都是 28 x 28 像素,包含手绘数字。我们需要编写一个应用程序,可以查看图像,并识别那里画的数字。换句话说,如果应用程序看到这张图片…
(图片由作者提供)
…然后它应该打印出这个…
[0, 0, 0, 0, 1, 0, 0, 0, 0, 0]
…这意味着“我看到了数字 4”:这里有 10 个插槽,第一个对应数字 0,第二个对应数字 1,第三个对应数字 2,依此类推;除了对应于编号 4 的时隙具有值 1 之外,所有时隙都具有值 0。这意味着应用程序已经“识别”了数字 4。
或者如果它看到这个图像…
(图片由作者提供)
…然后它应该打印出这个…
[0, 0, 1, 0, 0, 0, 0, 0, 0, 0]
…意思是“我看到第二个”。
这被称为图像识别,因为我们正在识别图像。它也被称为分类,因为我们有一堆输入(数字的图像)需要被分类(归类)到 10 个不同的类别(它们代表的数字种类,从 0 到 9)。
这些图像实际上就是充满数字的矩阵。矩阵中的每个像素都是不同的数字。我们可以使用 28 x 28 的正方形像素矩阵,或者我们可以简单地将每个矩阵展开成一串 784 个数字——软件实际上并不关心形状,只要我们保持一致。
神经网络应该很好地用于图像分类。让我们试着从头开始构建一个。
什么是神经元?
神经元是神经网络的基本构件。它有几个输入 Iᵢ和一个输出 o
(图片由作者提供)
内部和 Z 就是所有输入 I 的加权和(乘以它们的权重 W):
通常,Z 的公式末尾会添加一个恒定偏置项 B(因此 Z 通常以“… + B”结尾)。在这篇文章中我们将忽略偏见;网络性能会稍微差一些,但数学会更简单。
z 的值可以在很宽的范围内,但是对于 O,我们希望将值保持在一个合理的区间内,比如[0,1],这类似于概率,只是更容易处理。你还需要一些非线性,否则输出将总是所有输入的线性集合,这肯定不是你想要的。
所以我们需要使用一个函数将 Z 转换成 O,比如 sigmoid ,它的输出总是在这个范围内。我们说乙状结肠是神经元的激活功能。我们可以使用许多不同的激活函数 A(Z ),但 sigmoid 是一个很好的基本例子,所以我们在这里使用它。
(图片由作者提供)
稍后,我们还需要 sigmoid 的导数,所以我们把它放在这里:
乙状结肠的 Python 代码:
def sigmoid(x, derivative = False):
if derivative:
return np.exp(-x) / ((np.exp(-x) + 1) ** 2)
else:
return 1 / (1 + np.exp(-x))
什么是神经网络?
神经网络通常由几层组成,每层包含多个神经元:
(图片由作者提供)
为所有连接编写所有方程,根据一些输入计算最终输出可能会非常无聊。一个网络可以有很多连接,这意味着一大堆方程。
然而,矩阵符号可以用一个简单得多的矩阵方程代替一个方程组。
对于每一层 l,所有神经元的内部和 Z 是前一层输出的加权和。每层的输出仅仅是应用于该层所有内部和的激活函数。层 l 的矩阵形式:
让我们把这些方程推广到整个网络。
我们将使用 X 符号来表示输入(我们正在识别的手写图像)。所以,让我们用矩阵符号来写上面所有的内容,所有的层,所有的值。
Oₙ的最终方程式有点不同(最后一层得到了特殊处理),我们将在下面讨论 softmax 时再回到它。
矩阵用点积相乘。
每个 Wₗ矩阵的形状为矩形;一边的大小是当前层神经元的数量;另一边的大小是上一层神经元的数量;权值总数是前一层神经元数乘以当前层神经元数的乘积。这就是点积起作用的“魔力”。
初始化网络
当我们创建网络时,我们不知道我们需要什么样的权重。我们可以简单地给权重分配随机值。例如,我们可以从标准正态分布中抽取随机值。
为了减少权重可能得到的非常大的值的数量,我们将缩小与权重数量成比例的分布的标准偏差。更多的权重=更窄的分布(更接近 0)。这将避免在计算 z 时必须处理非常大的数字。
神经元的数量有点难以计算。输入和输出已经确定:如果图像中有 784 个像素,则需要 784 个输入。如果你要识别 10 个类别,你需要 10 个输出。对于其他层,它变得更加复杂;一般来说,神经元的数量从输入到输出逐层逐渐“减少”是个好主意。
参见下面的代码。整个网络(“模型”)都在称为“模型”的变量中。它有 4 层。输入层的大小与一个输入样本数据的大小相同(784)。输出的大小与一个输出样本数据(10)的大小相同。其他两层具有中等数量的神经元(128 和 64)。记住,我们只在模型中存储权重 W。
def nn_init(lsize):
# human-readable names for clarity
input_layer = lsize[0]
hidden_1 = lsize[1]
hidden_2 = lsize[2]
output_layer = lsize[3]
# narrowing down the standard deviation by layer size, with np.sqrt()
# large layers have tighter initial values
nnet = {
'w0': np.random.randn(hidden_1, input_layer) * np.sqrt(1\. / hidden_1),
'w1': np.random.randn(hidden_2, hidden_1) * np.sqrt(1\. / hidden_2),
'w2': np.random.randn(output_layer, hidden_2) * np.sqrt(1\. / output_layer)
}
return nnetlayer_sizes = [x_train[0].shape[0], 128, 64, y_train[0].shape[0]]
model = nn_init(layer_sizes)
输出
我们正在做分类,所以网络有 K 个输出,每一个输出代表我们正在识别的一类物体。在这种情况下,K = 10,因为对象是数字,并且有 10 个类别(0,1,2,…,9)。
我们可以对每个输出使用 sigmoid 函数,就像我们对网络中所有其他神经元所做的那样。那么每个输出将具有 0 和 1 之间的值,并且最高值(最接近 1)获胜。但是我们可以更进一步:为了使输出看起来像实际的概率,让我们确保它们的总和总是 1。每个输出在 0 和 1 之间,它们的总和需要正好是 1,因为对象在总共 K 个类中的任何一个类中的总概率总是 1(我们从不向网络显示“外来”对象,至少在训练期间不显示,这是重要的部分)。
这可以通过 softmax 函数来完成。对于每个输出 Oᵢ,我们如下计算其值:
下面的 Python 函数计算 softmax,但是对指数进行了移位以避免计算非常大的值。结果是一样的,函数看起来有点复杂,但是在实践中表现得更好。
def softmax(x, derivative = False):
# for stability, we shift values down so max = 0
# [https://cs231n.github.io/linear-classify/#softmax](https://cs231n.github.io/linear-classify/#softmax)
exp_shifted = np.exp(x - x.max())
if derivative:
return exp_shifted / np.sum(exp_shifted, axis = 0) * (1 - exp_shifted / np.sum(exp_shifted, axis = 0))
else:
return exp_shifted / np.sum(exp_shifted, axis = 0)
正向传播
好了,我们有了网络,我们在输入端应用一个样本值(一个数字的图像),我们如何计算它的输出呢?我们逐层进行,将输入/先前输出乘以权重,应用激活函数(sigmoid ),等等,直到我们到达输出,在那里应用 softmax。让我们再次展示方程式:
仅此而已。一个训练有素的网络就是这样运作的。这是一系列的线性代数运算,逐层进行,最终根据输入和网络权重计算输出。
下面的 Python 函数就是这样做的。它假设模型(所有 W 矩阵)是一个全局变量(为了代码简单,这是学校的东西,而不是生产代码),它将一个输入样本 X 作为参数,并返回一个包含一堆矩阵的字典,每个矩阵包含网络中每一层的 O 和 Z 值。
字典中最后一个矩阵是网络输出。这就是我们想要的结果。
def forward_pass(x):
# the model is a global var, used here read-only
# NN state: internal sums, neuron outputs
nn_state = {}
# "output zero" is the output from receptors = input to first layer in the NN
# these are activations for the input layer
nn_state['o0'] = x
# from input layer to hidden layer 1
# weighted sum of all activations, then sigmoid
nn_state['z1'] = np.dot(model['w0'], nn_state['o0'])
nn_state['o1'] = sigmoid(nn_state['z1'])
# from hidden 1 to hidden 2
nn_state['z2'] = np.dot(model['w1'], nn_state['o1'])
nn_state['o2'] = sigmoid(nn_state['z2'])
# from hidden 2 to output
nn_state['z3'] = np.dot(model['w2'], nn_state['o2'])
nn_state['o3'] = softmax(nn_state['z3'])
return nn_state
训练网络
但是如何训练一个网络呢?如果我们从随机权重开始,并应用输入 x(一个图像),输出 Oₙ将是无意义的,它不会接近“真正的”输出 y
训练的中心思想是,我们必须调整权重 w,直到网络 Oₙ的输出接近 y(“理想”值)。高层次的训练算法可能如下所示:
- 用随机权重初始化网络
- 应用输入样本 X(图像)
- 进行正向传播并计算输出 Oₙ
- 将输出 Oₙ与您想要获得的实际值 y 进行比较
- 调整最后一层的权重,使输出变得稍微“更好”(误差减少)
- 逐层返回并调整权重,以减少误差(这是困难的部分)
- 应用下一个输入样本 X(另一个图像)
- 使用许多不同对的输入 X 和输出 Y 样本,重复上述所有操作数千次,直到网络表现足够好
困难的部分是弄清楚如何调整权重,从输出到输入,从而减少误差。这被称为反向传播。但是要实现这一点,我们首先需要创建一些工具。
成本函数
假设我们有网络输出 Oₙ,并将其与来自训练数据的“完美”输出 y 进行比较。Oₙ离 y 有多近,我们如何定义“近”?如果我们有一个值随着 Oₙ变得越来越“不同”于 y 而增加的函数,我们可以称之为成本函数(因为错误是昂贵的),我们可以用它来降低成本。
对于这个分类问题,交叉熵可以起到代价的作用(在其他情况下使用其他函数)。假设我们有 K 个输出,它是所有输出的和:
其中,Oᵢ是网络上的各种输出,Yᵢ是每个输出的相应训练值。
这个公式有效的原因是 Yᵢ可以是 0 也可以是 1 。如果在 Y 样本中有 10 个值,那么其中 9 个值将是 0(对象 X 不属于这些类别中的任何一个),其中一个值将是 1(对象 X 属于该类别)。那么总和中的一项或另一项变成 0,另一项只取决于 Oᵢ.
如果 O 和 Y 都是 1 维向量(确实如此),那么在使用点积的矩阵符号中,上面的等式变成:
对数是按元素应用的,差 1-y 也是如此。
Numpy 库可以进行矩阵运算,因此 Python 的 cost 函数是对最后一个公式的直接直译:
def part_cost(o, y):
c = np.dot(y, np.log(o)) + np.dot((1 - y), np.log(1 - o))
return -c
让我们记住这个函数,我们稍后将使用它来评估网络的性能。
最小化成本
这是争论的重点:给定从输出 O 和训练值 Y 计算的成本 C,我们想要改变权重 W,使得 C 减少(通过使 O 更类似于 Y)。
如果我们可以计算 C 关于 W 的导数(我们称之为δ),然后在导数平面的向下方向调整 W,那么 C 会减少。如果导数是正的,那么我们减少 W(因为最小值朝向更小的 Ws),反之亦然。这项技术的另一个名字是梯度下降。
换句话说:想想 W 空间中的成本函数 C。忘了 X 或者别的什么吧。只想到 C(W)。你需要在 W 空间中穿行 C,直到你在 W 空间中偶然发现某个最小值。这就是“训练”的含义:找到使 c 最小的最佳 W 值集。
接下来的并不是严格的证明。这更像是一种数学直觉。如果你仔细看这些方程,你会注意到我们滥用数学的几个地方(例如,混淆微分和实际的有限变化)。在实践中,它会成功的——神经网络对错误有很强的抵抗力。
让我们将δ定义为成本 C w r t 的偏导数,内部和 z,对于层 l,这写为:
对于前一层 l-1,我们通过应用链式法则获得:
但是我们从 Z 的定义中知道这是真的:
将最后一个公式代入前一个公式,我们得到:
这个公式是递归的。我们所需要的是最后一层的δₗ,我们可以从 c 和 Zₗ计算出来,这是我们从正向传播中知道的。一旦我们有了δₗ ,我们就可以一层一层地回去,一个接一个地计算所有层的δ值。
更重要的是,现在我们还可以逐层返回,计算成本函数 c 相对于每层 l 的权重 Wₗ的导数δₗ。这是我们使反向传播工作真正需要的。我们现在越来越接近了。
让我们使用链式法则重新计算每层的δ:
换句话说:
但是我们有来自正向传播的所有 Oₗ值(它们是每一层的输出),并且我们已经计算了上面所有的δₗ值。这意味着我们可以计算所有图层的δₗ,从输出开始,通过网络返回。
一旦我们有了所有大的增量,我们就可以用它们来更新权重。在实践中,更新将通过学习速率因子λ进行加权,学习速率因子λ通常是一个小值(0.001),因此我们不会对网络进行突然的大的改变。
同样,如果δ(C . W . r . t . W .的导数)为正,这意味着在较小 W 值的方向上将有较小 C 值。所以我们需要减少 W 来使 C 减少。反之亦然。
λ可能很难思考。不要停留在“单位”或类似的东西上。只需选择一个λ值,使 W 的变化足够小——小步前进。不管δ发生了什么,在乘以λ之后,结果应该比 w 小,这就是全部。这足以让算法工作。
反向传播和训练
对于每个训练样本,通过反向传播修改网络权重 W 以最小化成本的工作方式如下:
- 将训练样本 X(图像)应用于输入
- 进行正向传播,计算所有图层的所有 Z 和 O(输出)值
- 递归(向后)计算所有层的所有δ矩阵
- 从δ矩阵计算所有δ矩阵
- 更新权重
这是一个完整的反向传播步骤。请参见下面的 Python 代码:
def backward_pass(x, y):
# do the forward pass, register the state of the network
nn_state = forward_pass(x)
# small deltas: derivatives of the error w.r.t. z
nn_state['d3'] = nn_state['o3'] - y
nn_state['d2'] = np.dot(nn_state['d3'], model['w2']) * softmax(nn_state['z2'], derivative = True)
nn_state['d1'] = np.dot(nn_state['d2'], model['w1']) * sigmoid(nn_state['z1'], derivative = True)
# large deltas: adjustments to weights
nn_state['D2'] = np.outer(nn_state['d3'], nn_state['o2'])
nn_state['D1'] = np.outer(nn_state['d2'], nn_state['o1'])
nn_state['D0'] = np.outer(nn_state['d1'], nn_state['o0'])
return nn_state
backward_pass()函数将图像 X 和训练响应 Y 作为参数。该模型是一个全局变量。它返回包含所有 Z、O、D 和 D 矩阵的 nn_state 字典。这里 d 代表δ。D 矩阵是在反向投影期间计算的权重调整项δ。
参见下面的完整培训代码。“时期”是代码需要检查整个训练数据的次数;良好的训练需要多次通过;我们做 5 个纪元。定义了一个训练率 t_rate,用于权重更新——它实际上是我们方程中的λ(抱歉改变了符号)。
您可以在每个输入样本 X 之后更新权重(随机梯度下降),或者您可以累积整个时期的 W 变化(累积δ矩阵)并在最后应用所有内容(批量梯度下降),或者您可以在两者之间做些事情。这里我们使用随机下降。
该代码还评估成本(与完美答案的偏差)和准确性(分类正确的次数)。
最后,模型(W 矩阵)被保存到磁盘上。
epochs = 5
t_rate = 0.001# train
print('################### training ####################')
for e in range(epochs):
print('epoch:', e)
samples = x_train.shape[0]
cost = 0
hit_count = 0
for i in tqdm(range(samples)):
m_state = backward_pass(x_train[i], y_train[i])
# add partial cost
cost += part_cost(m_state['o3'], y_train[i])
# stochastic gradient descent
# update weights
model['w0'] -= t_rate * m_state['D0']
model['w1'] -= t_rate * m_state['D1']
model['w2'] -= t_rate * m_state['D2']
if np.argmax(m_state['o3']) == np.argmax(y_train[i]):
# successful detection
hit_count += 1# performance evaluation
cost = cost / samples
accuracy = hit_count / samples
print('cost:', cost, 'accuracy:', accuracy)# save the model
with open('model.pickle', 'wb') as f:
pickle.dump(model, f)
评估网络性能
那么网络做得有多好呢?我们用训练数据 x_train 和 y_train 对它进行了训练。但是我们已经为测试留出了数据:x_test 和 y_test。
只保留一些数据用于测试总是一个好主意。这是网络在训练中从未见过的数据。因此,我们保证性能评估将是公平的。大约 20%是留出测试数据的合适大小(假设您有大量的数据——数千个样本或更多)。
评估只是检查测试数据,计算成本和准确性,并打印出结果。
# test
print('################### testing ####################')# load the model
if os.path.isfile('model.pickle'):
with open('model.pickle', 'rb') as f:
model = pickle.load(f)# run the whole test data
samples = x_test.shape[0]
cost = 0
hit_count = 0
for i in tqdm(range(samples)):
m_state = forward_pass(x_test[i])
cost += part_cost(m_state['o3'], y_test[i])
if np.argmax(m_state['o3']) == np.argmax(y_test[i]):
hit_count += 1# evaluate performance
cost = cost / samples
accuracy = hit_count / samples
print('cost:', cost, 'accuracy:', accuracy)
因为我们不对神经元使用偏置,网络的性能将相当适中:大约 60%的准确率。它肯定可以做得更好。但这是一个学习示例,不是生产代码。
这是训练中的网络性能,请注意它是如何随着每个时期而变得更好的:
(图片由作者提供)
参见下面测试中的性能。它实际上比在训练中要好一点,这不是典型的,但训练算法的行为在某种程度上有点随机。
(图片由作者提供)
这里有一个 Jupyter 笔记本,上面有本文使用的全部代码:
https://github . com/FlorinAndrei/misc/blob/master/nn _ back prop . ipynb
它下载了 MNIST_784 数据集,这是一组带有手写数字的图像,总共约有 70,000 张图像。它使用 Tensorflow 库中的函数来准备训练/测试分割(这完全是多余的,但是非常方便)。
它训练和测试网络。另外,它生成了本文中使用的一些图像。
笔记
所有的图片和代码都是由本文作者创作的。
几年前,我在 Coursera 上参加了吴恩达的机器学习课程,如果你想理解这种算法的数学复杂性,这非常有用。
https://www.coursera.org/learn/machine-learning
感谢阅读!
全卷积网络中的反向传播
原文:https://towardsdatascience.com/backpropagation-in-fully-convolutional-networks-fcns-1a13b75fb56a?source=collection_archive---------6-----------------------
在 Unsplash 上 NeONBRAND 拍摄的照片
反向传播是神经网络训练中最重要的阶段之一。作为一个目标,它决定了神经网络的知识被理解为对未来冲动做出正确反应的能力。术语“知识”和“适当地”必须考虑两个方面:(I)第一方面由经验给出,或者更好地说,由网络学习从数据集的样本中提取的信息(特征)给出(ii)第二方面由误差计算或也称为损失给出。在监督学习中,每个样本都标有类别(分类)、一个或多个值(回归)或两者都有。设 y_actual 为主管分配给样本的标签, y_pred 为网络预测,反向传播阶段将确保两者之间的距离(误差)是可接受的。误差和特征都有与之相关的权重,当在反向传播过程中被修改时,就构成了网络的学习知识。
在离开之前,我想再补充几点。反向传播有两个阶段。第一个是计算梯度,或者更好地说,损失函数对每个网络权重的导数。第二是它们的更新( delta 规则)。最后一个可以用各种优化算法来执行,例如 Momentum、Adam 等。在本文中,我将只关注第一个阶段,而将第二个阶段的深化留给后续阶段。此外,我没有发现太多的证据证明反向传播适用于卷积网络,每一个计算和解释都是个人研究的结果。如果有错误或误解,我很乐意讨论。谢谢你和良好的阅读。
符号
1.核和卷积
我们可能会问的一个问题是,为什么使用卷积神经网络而不是 MLPs 来分析图像?让我们举一些例子。图像是以矩阵形式排列的一系列数值(像素亮度)。为了使用 MLPs,我们应该将矩阵转换成向量,并将其呈现给网络的输入层。在这方面,我们考虑大小为(224,224,3)的图像 X,其中 224 表示高度和宽度,而 3 是色标红、绿、蓝中的深度。通过变换,我们得到一个大小为(150,528,1)的向量,如图 4 所示
图 4:输入图像 x 的多层感知器(MLPs)的表示。(图片来源链接,经作者许可编辑)
这种方法主要有两个错误。首先是图像是空间有序的数据。更清楚地说,像素排列形成矩阵的顺序为特征提取提供了很大的帮助。所以这是我们不能丢失的信息。第二是使用 MLPs 的参数数量非常高。以我们的例子为例,仅输入层就有 150,528 个神经元。考虑到第二层中的 100,000 个神经元,我们的网络仅在第一层和第二层之间就有 150,528×100,000 = 15,052,800,000 个参数,让我们设想考虑整个网络。(注意:参数数量增加越多,训练需要的时间就越多,找到最优的就越困难,模型在记忆方面的权重就越大 ) 。
图 5:维度(4,4,1)的图像 X 和维度(2,2)的核 W 之间的卷积,步长 S = [1,1]。输出特征图由 Z 表示,并且具有维度(2,2)(来源:我的图像)
内核的引入解决了这些问题。内核 W 是通常尺寸为 2×2、3×3 或 5×5 的正方形矩阵,其沿着图像 X 的宽度 M 和高度 N 行进一定的步幅 S,在内核和重叠区域的值 w ( 权重)之间执行加权求和。这种操作称为卷积,考虑了像素的空间顺序,并允许与图像的像素共享权重,减少了参数的数量。卷积的一个例子如图 5 所示。输出 Z 是一个特征图或者更确切地说是一个新图像,其中 X 的特定特征被强调。假设内核 W 突出显示边缘,卷积运算产生如下特征图:
图 6:强调 X 图像边缘的卷积运算。因子 1/16 被引入以减少特征图中的噪声。(图片来源链接,经作者允许编辑)
可以看出,在图 5 和图 6 中,Z 不具有与起始图像相同的尺寸。这个效果叫做跨步下采样。假设尺寸是 X: (Mx,Nx)W:(Mw,Nw)和步距 S,特征图 Z: (Mz,Nz)的尺寸计算如下:
公式(1)
2.前馈
图 7:具有两个卷积层的卷积神经网络的表示(来源:Image by me)
让我们考虑一个具有两个卷积层的网络,这两个卷积层都具有大小为 2x2 的核 W 和沿高度和宽度的步长 1,并且在输出层中有两个神经元。作为激活函数,我们不特别选择一个,一般用 g 表示。网络的输入是大小为 4x4x1 的灰度图像(单通道)图 7
让我们检查一下正向阶段。在开始最后一个音符之前。为了构建计算图,对于特征图的每个像素,记住在卷积操作期间使用了哪些像素是很重要的。我们需要的是将保存在集合 p 中的位置**
- 卷积输入 X 和第 1 层
**
(图片来源:图片由我提供)
- 卷积输出第 1 层和第 2 层
**
(图片来源:图片由我提供)
- 全连接
**
(图片来源:图片由我提供)
3.计算图形
我们在计算图(图 8)中对在正向阶段获得的信息进行分组。这是我们的卷积神经网络的表示,其中每个节点对应一个向前的步骤。具体来说,我们可以看到每个卷积节点 z 将索引为 p 的节点作为输入。
图 8:图 7 中网络的计算图表示(来源:图片由我提供)
4.B ackpropagation
公式(2)
让我们考虑 l 作为损失函数,计算图形允许你容易地定义梯度向量∇wL.这将被增量规则用来更新网络权重。公式(2)表示图 7 中网络的梯度向量。它包括三个分量,也是向量,关于第 3 层的权重以及分别关于第 2 层和第 1 层的核。下面,我用链规则来分析它们每一个偏导数演算。
- ∂L /∂W^(3)微积分
公式(3)
公式(3)是权重 W 层 3 的梯度向量。必须求解单个依赖关系[附录 1.1]才能计算其元素。作为示例,对重量 w1 层 3 的损失导数的计算如公式(4)所示:
公式(4)
用 F ( 完全用表示)向量公式(3)的每个元素 n 的最后一层神经元的数量,我们得到:
公式(5)
- ∂/∂w^(2l)微积分**
公式(6)
公式(6)是矩阵 W 层 2 的梯度向量。为了计算它的元素,有必要首先求解由于层 3 的梯度而引起的单个相关性,然后求解每个神经元 f. 的多个相关性【附录 1.2】参见图 8, 我们可以看到:( I)由于卷积的共享权重特性,第 2 层中的每个权重 w 存在于不同的和 zi ^(2 中;( ii)每个神经元 f 连接到第 2 层中的每个激活输出,用于完全连接(,因为它是完全连接的层)。
图 9:计算每个第 3 层 zf 节点的下游梯度(来源:图片由 me 提供)
作为例子,我们考虑关于层 2 中的权重 w1 的梯度计算。为了便于讨论,对于第 2 层的每个激活节点,我们计算通过对各个第 3 层节点 zf 的下游梯度【附录 2】求和而获得的上游梯度。图 9 示出了下游的计算,然后对每一对求和,以形成公式(10)中每个激活的正式上游。
公式(10)
此时,层 2 中相对于 w1 的损耗梯度将由公式(11)给出,其中每个 ∂L /∂ai 上游梯度乘以各自 ai 和 zi 节点的导数。此后,在上述步骤(I)中,对每个贡献进行求和。
公式(11)
从我们已经看到的和概括的开始,对于层 2 中的每个节点 ai ,上游梯度将由公式(12)给出。后者是公式(5 ),其中我们导出激活 ai 而不是导出权重 w 的 zf 层 3,然后将贡献相加。
公式(12)
相反,对于向量公式(6)的每个元素 n ,我们得到:
公式(13)
为了完整性,结合公式(12)和(13)我们得到:
- ∂/∂w^(1微积分**
公式(14)
公式(14)是矩阵 W 层 1 的梯度向量。与前面的情况相比,对于偏导数的计算,有必要根据完全连接和卷积层来求解多个相关性的不同步骤。查看图 8,可以看到(I)w^(1 的每个权重存在于层 1 的不同 zj 加权和中(共享权重)。
作为一个例子,我们考虑权重 w1 层 1 的梯度的计算。同样,对于第 1 层中的每个激活节点 aj ,我们计算公式(15)中形式化的上游梯度。为了计算它,我们使用我们已经有的信息。特别是,一旦我们获得 ∂L /∂zi ^(2 】,公式(10)中的上游梯度将允许我们计算单个下游图 10
图 10:计算每个节点 zi 层 2 的下游梯度(来源:me 提供的图像)
公式(15)
在这一点上,到 w1 层 1 的损耗梯度将由公式(16)给出,其中在公式(15)中形式化的 ∂L /∂aj 上游梯度中的每一个乘以各自激活节点 aj 和 zj 的导数。此后,对上述点(I)的每个贡献进行求和。
公式(16)
从我们所看到的和概括的开始,对于第 1 层中的每个节点 aj ,上游梯度将由公式(13)给出,其中,代替将第 2 层的 zi 导出到权重 w ,我们将其导出到第 1 层的 aj :
公式(17)
相反,对于向量公式(14)的每个元素 n,我们得到:
公式(18)
为了完整性,结合公式(12)、(17)和(18),我们得到:
5.结论
在本文中,我们探讨了反向传播阶段,重点分析了图 7 中虚拟网络的计算图。一般来说,要计算第 l 个卷积层的梯度向量,有必要:
- 为了计算来自层 l 的每个激活输出的上游梯度
- 对层 l 中 z 相对于 w 的导数的贡献求和(由于共享权重)
现代网络要复杂得多。不同之处可能在于每个要素贴图块的通道数量(将多个要素贴图一个接一个地想象为立方体,每个都是一个通道),从而增加了内核 W 的深度,或者我们可以为每个层使用多个内核,或者我们可以使用批量归一化层,然后在此处应用反向传播,或者为每个层使用一个偏差项,并考虑该项的反向传播。所以本文中的例子是一个简单的,但有希望解释反向传播的例子。
附录
在图 11 / 12 / 13 中,以节点 z 为例进行了分析,同样的考虑也适用于任何其他功能。
- 链式法则
链式法则是计算复合函数导数的求导法则[1]。
1.1 单一依赖
公式(19)
设 a(t) 为 t 中的可微函数 z(a(t)) 为 a 中的可微函数。 z 相对于 t 的导数由公式(19)描述。分析用于计算导数的计算图,我们得到:
图 11:复合函数 z(a(t))的导数的表示
1.2 多重依赖
公式(20)
设 a1(t) 和 a2(t) 为 t 中的可微函数 z(a1(t),a2(t)) 为 a1 和 a2 中的可微函数。 z 对 t 的导数由公式(20)描述。分析用于计算导数的计算图,我们得到:
图 12:复合函数 z(a1(t),a2(t))的导数的表示
2.渐变【2】
设 a1(。)和 a2(。) be 两个函数和 z(a1(。),a2(。))在 a1 和 a2 中的一个可微函数。我们定义:
图 13:单个节点上不同渐变形状的表示
- 上游梯度:节点 z 反向传播时接收的梯度
- 局部梯度:相对于节点 z 的输入计算的梯度
- 下游梯度:上游梯度和局部梯度之间的乘积(链式法则)
参考
[1] 链式法则—维基百科
[2] 第五讲斯坦福在线 pg。54
更多资源
- jefkine kafuna,卷积神经网络中的反向传播
神经网络中的反向传播
原文:https://towardsdatascience.com/backpropagation-in-neural-networks-6561e1268da8?source=collection_archive---------5-----------------------
从零开始的神经网络,包括数学和 python 代码
照片由 JJ 英在 Unsplash
介绍
你曾经使用过神经网络,并想知道它背后的数学是如何工作的吗?在这篇博文中,我们将从头开始推导前向和后向传播,从中编写一个神经网络 python 代码,并学习线性代数和多元微积分的一些概念。
我将从解释一些线性代数基础开始。如果你对这个足够精通,你可以跳过下一部分。
向量和矩阵
简单的数字(标量)用小写字母书写。
作者图片
向量用粗体字母表示,默认情况下它们是列向量。
行向量的名称也用粗体表示,但是用大写字母 T 表示转置。
autor 提供的图像
矩阵用粗体大写字母表示。
autor 提供的图像
当转置一个矩阵时,我们交换行和列。
作者图片
矩阵或向量的维数是:
(行数、列数)
作者图片
点积⋅
当两个向量或矩阵乘以点积时,左边向量或矩阵的列数必须与右边向量或矩阵的行数相匹配。
(图片由作者提供)
结果的维数可以计算如下:
作者图片
该乘法中的“内部”维度必须匹配,并在输出维度中消失。
元素态乘积(Hadamard 乘积)
当使用元素乘积将两个向量或矩阵相乘时,它们必须具有相同的维数。
(图片由作者提供)
矩阵计算
我们还需要向量和矩阵的微积分。我们使用雅可比矩阵的概念。雅可比就是一个向量或导数矩阵。
标量值函数相对于矢量 𝑥 的导数定义如下:
作者图片
我们用输出向量 𝑓 定义一个函数对单个变量 x 的导数,如下所示:
作者图片
具有输出向量和输入变量向量的函数的导数定义如下:
作者图片
向量链规则
矢量链规则看起来非常类似于标量链规则。在这个例子中,向量 𝑓 是向量 𝑔 的函数,向量 𝑔 本身是向量 𝑥 的函数。所以𝑓(𝑔(𝑥))相对于 𝑥 的导数计算如下:
作者图片
单输入向量神经元
作者图片
𝑥 :是进入神经元的输入样本。在上图中,它有 3 个特征。例如,这可以是一个人的身高(1.75 米)、体重(80 公斤)和年龄(30 岁)。注意,我们一次只输入一个样本(在我们的例子中是一个人)到神经元中。
𝑎:被称为激活,它是神经元的输出。它是神经元根据一个输入样本做出的预测。我们可以选择我们的神经元应该预测什么。在我们人类的例子中,一个有用的预测可能是身体质量指数。
𝑤 :神经元的权重。它对向量 𝑥 的每个输入特征有单独的权重。
𝑏: 神经元的偏差。一个神经元只有一种偏向。
𝑦:是网络输出的真实值或目标值。我们希望𝑎尽可能靠近𝑦。因此,我们在训练阶段改变权重 𝑤 和偏差𝑏。
𝐿:被称为损失。𝑎离𝑦越近,损失越小,因此越好。因此,我们想尽量减少损失。最小化神经网络中损失的最常见方法是梯度下降。在这篇博文中,我将使用“均方误差”损失。
梯度下降
在训练期间 w 以下列方式更新。
作者图片
其中 w 是新更新的权重向量,𝜆是学习率。𝜆是一个超参数,可以自由选择。通常在 0.05 左右。
作者图片
∇𝐿( w 是损失相对于权重的梯度。它只是损失𝐿的导数相对于权重的转置。一般来说,函数对某些变量的梯度总是相应导数的转置。
作者图片
𝑏是新的更新的偏见。∇𝐿(𝑏)是损耗相对于权重的梯度。
作者图片
在这种情况下,梯度是导数的转置并不重要,因为它是一个单一的数,转置一个单一的数不会改变它。
计算渐变
应用向量链规则:
作者图片
重量的导数:
作者图片
𝑥 不依赖于 w ,因此它被视为常数,导数必须仅针对w
关于偏差的导数:
作者图片
梯度下降
作者图片
代码
作者代码
测试我们神经元的代码:
作者代码
然后,我们用虚拟数据集测试我们的数据,看看它是否有效。每个样本有 3 个特征。如果第一个特征是 1,则期望的输出是 1。其他两个特征对结果并不重要。因此,我们希望第一个权重变为 1,而其他权重和偏差将变为 0。
显示训练过程中权重、偏差和损失变化的图表(图片由作者提供)
我们对训练过的网络在训练中从未见过的样本进行测试,以了解它对未见过的数据的推广情况。
Test:
predicted y: 0.9992918862001037, true y: 1
测试样本的输出显示,我们非常接近真实值。
能够同时对多个样本进行训练
前进传球
每个数据点的大小为 3:
我们有数据点𝑥1,𝑥2,…
圆点表示我们可以输入神经元的数据点(𝑚)的数量是可变的。
作者图片
为了获得输入矩阵,我们垂直堆叠输入向量:
作者图片
我们必须按如下方式调整损失:
作者图片
其中𝑚是我们使用的数据点数。
𝑎,激活向量然后以如下方式计算:
作者图片
作者图片
偶数道次
应用向量链规则:
作者图片
计算导数。
作者图片
关于重量:
作者图片
关于偏差:
作者图片
梯度下降
作者图片
密码
作者代码
随机梯度下降
随机梯度下降意味着,我们同时对所有训练样本进行训练。
我们可以看到权重、偏差和损失的相同演变,就像在具有单一输入的神经元中一样。
作者图片
我们可以在下面看到,预测的输出非常接近真实的 y:
Test:
predicted y: 0.9999991060923578, true y: 1
小批量梯度下降
小批量梯度下降意味着,我们同时在训练集的子集上训练神经元。
我们必须编写一个函数来生成随机批次。
作者代码
作者图片
predicted y: 0.9956078874633946, true y: 1
添加激活功能
激活函数是非线性函数。
3 个非常重要的激活函数及其导数:
tanh:
作者图片
西蒙德:
作者图片
整流线性单位:
作者图片
前进传球
作者提供的图片
向后传球
应用向量链规则:
作者图片
计算导数:
作者图片
np.diag 函数从一个向量构造一个矩阵,其中矩阵的对角线等于该向量,并且它是非对角线的。
关于重量:
作者图片
关于偏差:
作者图片
密码
激活功能:
作者代码
神经元:
作者代码
迷你批次梯度下降
作者图片
值、权重和偏差收敛到不同于先前的情况。
prediceted y: 0.9394357707018176, true y: 1
深度神经网络
向前传球
作者图片
括号中的上标表示该层。
第 1 层(=输入层):
作者图片
第二层(=输出层):
作者图片
损失:
作者图片
向后传球
第一层(=输入层):
作者图片
第二层(=输出层):
作者图片
计算第 2 层的导数是一个问题,因为我们必须对矩阵求向量的偏导数,对矩阵求矩阵的偏导数。这将导致张量,这将使它变得不必要的复杂。
我们不使用向量链规则,而是直接计算损失对权重和偏差的最终导数。为此,我们:
- 用索引符号重写向前传递。在这个符号中,我们可以看到损失的最终导数的每个元素相对于权重和偏差的样子。
- 计算导数。
- 为了编写高效的代码,请返回到矢量化形式。
第一层(=输入层):
作者图片
第二层(=输出层):
作者图片
损失:
作者图片
向后传球
第二层(=输出层):
为了推导索引符号中的公式,我们可以查看计算图。例如,为了推导第 2 层权重的公式,我们构建了一个计算图,其中所有相互依赖的变量都是相连的。
作者图片
我们用索引符号重写了相同的计算图。
作者图片
我们现在想知道损失对每个重量的导数。对于每个权重,我们必须对该权重出现的所有分支求和。作为层 2 的重量 1 的例子:
作者图片
损失相对于所有重量的导数为:
作者图片
以矢量化形式写回:
作者图片
注意,通过观察等式的左侧,我们可以看到我们的矢量化形式最终必须具有的维数。这有助于我们以正确的方式构造点积,并给我们必须转置的信息。
作者图片
以矢量化形式写回:
作者图片
第一层(=输入层):
作者图片
以矢量化形式写回:
作者图片
重新划分偏差:
作者图片
以矢量化形式写回:
作者图片
为了使求和更清楚:
作者图片
“轴= 1”意味着我们对各列求和。
通式
为了推广我们上面导出的公式,我们将输入损耗的概念引入到层中的神经元中。输入错误 𝛿 (𝐿)进入最后一层𝐿是:
作者图片
以矢量化的形式:
作者图片
对于我们网络的所有其他层 l:
作者图片
以矢量化的形式:
作者图片
𝑓表示非线性激活函数。这可以是例如乙状结肠或 relu。𝑓′表示𝑓.的导数
关于重量的导数:
作者图片
以矢量化的形式:
作者图片
关于偏差的导数:
作者图片
以矢量化的形式:
作者图片
最终代码
此代码可用于创建和训练任意深度神经网络。传递给 init 方法的列表“层”可以更改,这将更改网络。列表的长度等于层数。这些数字等于每层中神经元的数量。第一个必须等于特征的数量。
作者代码
测试我们的代码:
作者代码
我们再次查看输出层的权重和偏差的演变以及训练期间损失的演变。
作者图片
predited y: 0.9514167066315814, true y: 1
结论
如果你还和我在一起,我祝贺你,虽然这是一个旅程。如果第一次没有成功,也不要绝望。我花了一个多月才想明白这一切。
今天你已经学会了如何在任意深度神经网络中导出权重梯度。你现在也应该能够将这些知识应用到其他问题上,比如线性回归、递归神经网络和强化学习等等。
但是要知道,现在有非常好的自动签名框架,它能够为你数值计算梯度。尽管如此,我仍然认为,手工推导这些公式有助于我们对神经网络如何运行以及出现的一些问题(如香草 RNN 中的消失和爆炸梯度)的总体理解。
相关著作
https://medium.com/@Vincent.Mueller/einstein-index-notation-d62d48795378
想联系支持我?
LinkedIn
https://www.linkedin.com/in/vincent-m%C3%BCller-6b3542214/
脸书
https://www.facebook.com/profile.php?id=100072095823739
Twitter
https://twitter.com/Vincent02770108
Medium
https://medium.com/@Vincent.Mueller
成为 Medium 会员并支持我(你的部分会费直接归我)
https://medium.com/@Vincent.Mueller/membership
反向传播:简单的证明
原文:https://towardsdatascience.com/backpropagation-the-natural-proof-946c5abf63b1?source=collection_archive---------7-----------------------
是时候真正理解算法是如何工作的了。
人工神经网络与其他机器学习算法的区别在于它们如何有效地处理大数据,以及它们如何对你的数据集假设很少。
内核诡计[1]
您的神经网络不关心您的分类数据是否不能通过核进行线性分离,或者您的回归数据所遵循的趋势是否是过山车。只要你的数据集是从一个有限空间( x )到另一个有限空间( y )的连续映射,那么你就可以根据你的架构以任何精度近似这个映射。这是因为它们是通用近似器,正如 通用近似理论 所证明的。关键是,当神经网络在 40 年代首次出现时,没有快速的方法来利用神经网络的这一方面。直到 1970 年,反向传播——一种神经网络的快速训练算法以其现代形式发表。
在这个故事中,我们将花大部分时间从数学角度理解这种算法是如何工作的。
一个全局最小值的例子[2]
在我们深入研究它的证明之前。我想确定你知道两件事。首先,假设给定一个多变量函数【x,y】(例如上图所示的曲面)那么最小化 f(x,y) 就是找到∂f/∂x***和∂f/∂yt22】如果我们的多变量函数是数百万个变量(权重和偏差)中的某个成本函数,这同样适用。如果我们希望将其最小化,那么只需找到该函数相对于每个参数的偏导数,然后使用梯度下降迭代更新其参数,以最小化损失。
第二个我想让你注意的是链条法则。考虑 f(x) 与 x 为某变量中的函数 w , 然后去找**∂f/∂w我们写
**∂f/∂w=(∂f/∂x×(∂ x ₃)* 与每个xᵢ是w中的一个函数通过为每个写它然后添加:
**∂f/∂w=(∂f +(∂f/∂x₂)×(∂x₂/∂w)+(∂f/∂x₃)×(∩x********
****现在我们的目标很明确,给我们一个数据集,一个任意的神经网络,一个成本函数 J ,我们需要找到 J 关于神经网络中每个参数(权重/偏差)的导数,反向传播允许我们这样做,一次一个观察值。这意味着如果我们的损失函数是
均方误差: yᵢ 为观测值y(xᵢ)为由于馈网用【xᵢ】。 d 是数据集的长度。
为了找到它对某个权重或偏差的导数,我们可以找到
对于每个单独的训练示例 (xᵢ、yᵢ) 然后将它们全部相加并除以 d 。就像我们在和中引入导数一样。向前看,上面的公式就是我们在写 J 时所暗指的。
艺术的例证[3]
现在,在我们开始证明之前剩下的是决定一个符号。
对于权重,设 w ᴸₘₙ 为从 (L-1) ₜₕ 层的 mₜₕ 神经元到 L ₜₕ 层的 nₜₕ 神经元的权重。例如,从输入层的第三个神经元到隐藏层的第二个神经元的权重将是 w ⁰₃₂ 我们稍后会回头看,让第一个隐藏层的权重为 L = 0 ,但现在请耐心听我说。
神经网络示例[4]
除了权重,我们还有神经元特有的激活和偏差。我们将通过 a ᴸₘ 来表示 mₜₕ 神经元在 L ₜₕ 层的激活,对于偏差我们将做 b ᴸₘ 。
注意,如果我们调用激活函数 h ,那么我们可以写
这准确地捕捉到了任意神经元内部发生的情况。激活后的线性组合。现在,如果我们称线性组合为 z 可能会对我们有好处,所以下面是真的
现在,我们要开始证明了吗?好吧,既然我们要实现这个(也许,在的另一个故事中),如果我们也讨论一下如何用向量/矩阵符号来写我们到目前为止所介绍的内容,那将会很有帮助。
对于神经网络中不是输入层的每一层,我们可以定义如下:
Wᴸ :包含从 (L-1)ₜₕ 层到**层权重的权重矩阵。如果 (L-1)ₜₕ 层具有 M 个神经元,而 Lₜₕ 层具有 N 个神经元,则这具有维度 **MN* 。正如你所想象的,元素wᴸ[m,n】就是我们之前定义的 w ᴸₘₙ 。****
bᴸ : 任何层的偏置向量都会有其每个神经元的偏置, bᴸ[m] = bᴸₘ
aᴸ : 任何层的激活向量将具有其每个神经元的激活, aᴸ[m] = a ᴸₘ
zᴸ : 任何层的预激活向量将具有其每个神经元的线性组合, zᴸ[m] = zᴸₘ
使用这个新的符号,如果我们让函数 h 被应用于向量元素,那么我们可以写
请注意, h 应用于向量 z 中的每个元素。
请记住,由于我们的符号, W 中的每一列都代表 Lₜₕ 层中特定神经元的权重。这一事实以及矩阵乘法的工作原理应该能让你理解上面的公式。
还要注意,对于 L = 0 (第一个隐藏层),当且仅当我们用 x 代替激活时,上述关系成立。我们没有给输入层 L = 0 的唯一原因是,这将使 Wᴸ 、 bᴸ 等。对于 L = 0 未定义。我们不妨让最后一层有 L = H ,这样我们就可以很容易地在证明中突出它。这也使得 H 成为我们网络中的隐藏层数。
正在进行的证明的说明。[5]
让我们从找到 ∂J/∂ w ᴸₘₙ 开始我们可以利用这样一个事实,即t5】zᴸₙ是wᴸₘₙ中的一个函数,通过使用链式法则,如下所示
通过将 z ᴸₙ 代入其定义,并考虑到 b ᴸₙ 不是 w ᴸₘₙ 中的函数,我们得到
现在,因为在求和中唯一能经受住微分的权重是 i = m,我们可以写为
在我们证明的大部分时间里,我们会试图找到红色的术语;因此,给它一个名字是值得的。姑且称之为δᴸₙ吧。注意,每个神经元都有自己的 δᴸₙ 。对于整个图层,我们可以像写 bᴸ的、 aᴸ的和 zᴸ的一样写矢量 δᴸ的。****
所以我们在索引符号中的结果变成了
在向量符号中
这直接来源于外积的定义和我们的指数符号结果。
现在让我们利用类似的事实来找到∂J/∂bᴸₙ,即 zᴸₙ是 bᴸₙ的一个函数
将 zᴸₙ 代入其定义,并考虑到总和不是 bᴸₙ 中的函数,我们得到
这意味着
或者用向量符号表示
所以证明的结论可以归结为找到 delta。还记得我们的成本函数是什么样的吗?
【y(x)】其实只是最后一层的激活,所以我们可以这样写
因为 J 在【aᴴ中明确是一个函数,这应该会诱使你利用链式法则并涉及去寻找【δᴴₙ。****
这样,我们就隐含地假设【aᴴₙ】只是该层中【zᴴₙ】的一个函数,这对于你遇到的大多数成本函数来说是正确的,但对于 soft-max 来说不是,因为任何 aₙ 都是该层中所有 zₙ 的函数。在这种情况下,我们需要用链式法则的多变量版本来考虑它们。但是我们下次再做吧。
这两个术语都很容易找到。第一次
因为这适用于最后一层中的任何神经元,所以我们可以将向量形式写为
现在是第二学期,我们有
在矢量形式中,它只是简单的h’(zᴴ)其中h’将按元素应用于矢量 z ᴴ 。
在索引符号中结合这两者产生
因为它在索引符号中的样子,如果我们用ⵙ来表示两个向量的元素乘积,那么我们可以通过写来实现向量符号中的公式
但是,当我们为网络中的任何神经元寻找δ(δᴸₙ)时,这只能说明最后一层。
因为我们知道最后一层的δ,所以使用它来找出其它层的δ的一种方法是找出当前层 L 的δ与下一层的δ的关系。让我们试试看。
这里我们需要求和,因为下一层中的每一个 zₘ 都是zₙ(h(zₙ)的函数,对吗?).
对于下一个术语,将 z 代入其定义,考虑到aᴸᵢ只是 zᴸₙ 中的一个函数,当 i = n 时,我们可以写成:
现在回想一下aᴸₙ=h(zᴸₙ)我们可以写
通过代入δᴸₙ,在索引符号中我们得到
请注意,我们在 sum 中所做的相当于权重矩阵中对应于神经元的行与整个 delta 向量(列)之间的点积。如果我们将权重矩阵乘以增量向量,这正是幕后发生的情况,除了因为它发生在 W 中的所有行,所以我们得到一个考虑所有神经元数量的向量。因为对于每个我们简单地乘以 h( z ᴸₙ) 我们可以再次利用ⵙ作为元素式乘积,并写出:
深呼吸。证明到此结束。
为了编译我们用索引符号导出的所有方程,我们可以写
用向量符号表示(一层一层)
证明只帮助我们得出方程;算法就是雇佣他们的东西。它** 一次考虑一个例子,如下所示:**
1- 找 aᴸ 和 z ᴸ 找层 0 到 H 通过把一个例子馈入网络。(用前两个方程。)这就是所谓的“向前传球”。
2- 分别用 δᴴ 、 δᴸ 的公式计算 H 到 0 层的 δᴸ 。(用第三个等式。)
3- 同时计算层 H 到 0 的 ∂J/∂Wᴸ 和 ∂J/∂bᴸ 因为一旦我们有了 δᴸ 我们就可以找到这两个。(用最后两个等式。)这就是所谓的“倒传”。
4- 重复更多示例,直到网络的权重和偏差可以通过梯度下降进行更新(取决于您的批量):
假设 d 是数据集的长度。
正如你可能已经注意到的,步骤 2 和 3 是这个算法的名字;为了找到参数,我们必须反向传播。在下一个故事中,我们可能会考虑用 Python 来实现。
如果你喜欢阅读,并希望看到更多这样的故事,那么请考虑给帖子一些掌声,并跟我来。下次见,再见。
参考文献:
[1]“文件:内核 Machine.Png—维基共享”。Commons.Wikimedia.Org,2011,https://commons.wikimedia.org/wiki/File:Kernel_Machine.png.
[2] Pixabay,2015,https://pix abay . com/de/vectors/抛物面-mathematik-schale-fl % C3 % a4che-696804/。于 2021 年 9 月 21 日访问。
[3]“文件:English.Png 多边网络——维基共享”。Commons.Wikimedia.Org,2010 年https://commons . wikimedia . org/wiki/File:MultiLayerNeuralNetworkBigger _ English . png .
[4]布特,威廉。“档案:美国旧金山旧金山现代艺术博物馆(Unsplash Rkjf2bmrljc)。Jpg —维基共享”。Commons.Wikimedia.Org,2017,https://commons . wikimedia . org/wiki/File:San _ Francisco _ Museum _ of _ Modern _ Art,San_Francisco, United States _(Unsplash _ rkjf 2 bmrljc). jpg .
[5]“在白板上写字的女人”。 Pexels ,2021,https://www . Pexels . com/photo/woman-writing-on-a-white board-3862130/。于 2021 年 9 月 21 日访问。
学习资源:
尼尔森迈克尔。神经网络和深度学习。2019,CHP。1,2.
将数据库备份到 Google 云存储
原文:https://towardsdatascience.com/backup-database-to-google-cloud-storage-5348a916f791?source=collection_archive---------19-----------------------
设置定期数据库备份到 Google 云存储的流程
由 Kelvin Ang 在 Unsplash 上拍摄的照片
我有几个托管在数字海洋服务器上的小网站。他们每个人都有一个 MySQL 数据库,我想定期设置上传完整的数据库导出到数字海洋之外的一些独立位置,以便更平静地睡觉。由于我的生活围绕着谷歌云,我对存储的偏好很明显。目标是使用 crontab 定期运行 bash 脚本来执行 MySQL 数据库导出和 gsutil 命令来将文件复制到云存储桶。要配置整个过程,需要几个步骤,我将在本文中进行描述。我与谷歌云项目的互动,我使用网络用户界面,虽然所有步骤都可以通过命令行界面完成。
1.为备份创建一个云存储桶
第一步是创建一个云存储桶,用于存储备份文件。在 Cloud Console 中,我们转到云存储部分,然后单击按钮 Create bucket。
有几件事需要设置。由于这是一个备份桶,我将存储类设置为 Nearline (而不是 Standard ),因为这是为不太频繁的访问而设计的,而且有点便宜(数据访问也要收费)。我还设置了一个保留策略,只保留最近 3 个月的对象。
2.创建服务帐户
因为这个操作是在服务器上完成的(在 Google Cloud 之外),所以我将使用一个服务帐户来认证和访问 Google Cloud 项目。
下一步是下载密钥文件。在服务帐户列表中,单击您创建的帐户。
切换到“密钥”选项卡,然后点击“添加密钥”,然后“创建新密钥”,文件将自动下载。
您的互联网浏览器将下载该文件。
最后一步是将这个文件复制到服务器,我使用的是 scp 命令:
scp service_account.json <myusername>@<SERVER>
3.设置服务帐户对存储桶的访问权限
由于脚本会将数据库导出文件上传到存储桶,因此我需要为备份存储桶的服务帐户设置正确的权限,目前该服务帐户不需要其他访问/角色。
要设置云存储桶的访问权限,请在云存储桶列表中,单击相关的桶名称。
然后切换到权限选项卡,点击添加按钮,添加对服务账户的访问权限。
在“新成员”字段中,我添加了服务帐户的完整电子邮件地址“my-backup-Account @ iam . gserviceaccount . com”
最小的角色是存储对象管理员(在云存储部分下)。注意:存储对象创建器是不够的,因为当使用 gsutil 命令时,它也对桶使用“列表”操作(出于某种原因)。
使用保存按钮保存设置。
将服务帐户添加到存储桶后,它会列在“成员”列表中。
在此过程中,仅授予此存储桶的访问权限,服务帐户将无法访问其他云存储存储桶。
3.在服务器上下载和安装 Google Cloud SDK
安装 Google Cloud SDK 有几种方法。一种方法是直接将其作为操作系统包安装。我使用的方法包括从源文件安装。
谷歌云 SDK 的安装就是基于这些步骤【https://cloud.google.com/sdk/docs/install#linux 。为简洁起见:
curl -O [https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-sdk-337.0.0-linux-x86_64.tar.gz](https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-sdk-337.0.0-linux-x86_64.tar.gz)
tar -zxvf google-cloud-sdk-337.0.0-linux-x86_64.tar.gz
./google-cloud-sdk/install.sh
根据您如何配置其他东西,我需要做这个额外的步骤:
作为我的服务器上的默认版本,Python 2.7 已设置,Google Cloud SDK 对此有问题,所以我使用 pyenv 来支持多个 Python 版本。为了将 Google Cloud SDK 指向我想要的 Python 版本,我将 bash_profile 中的环境变量 CLOUDSDK_PYTHON 设置为指向 pyenv 的 Python3 解释器。
export CLOUDSDK_PYTHON=/home/ubuntu/.pyenv/shims/python3
4.使用服务帐户对 Cloud SDK 进行身份验证。
为了使用我创建并下载的服务帐户对 gcloud 进行身份验证,我使用了以下命令
gcloud auth activate-service-account my-backup-account@iam.gserviceaccount.com --key-file=/<PATH TO KEY>/service_account.json
如果一切正常,它将打印以下消息:
Activated service account credentials for: [my-backup-account@iam.gserviceaccount.com]
现在我们可以使用像 gcloud 和 gsutil 这样的云 SDK 工具与 Google Cloud 项目进行沟通。
5.Bash 脚本
脚本 backup.sh 包括将数据库转储到一个临时文件夹,然后从该文件夹上传到云存储桶:
#!/bin/bash
DUMP_FOLDER="/tmp"
GCS_BUCKET="my-safe-backups"
DT=$(date "+%Y%m%d")
function backup() {
database=$1
filename="${database}_${DT}.sql"
output_file="${DUMP_FOLDER}/${filename}"
echo $output_file
mysqldump "$database" >"$output_file"
if test -f "$output_file"; then
gsutil cp "$output_file" "gs://${GCS_BUCKET}/${database}/${filename}"
echo "${database} dump uploaded"
rm "${output_file}"
else
echo "No dump file ${output_file}"
fi
}
backup mydb_1
backup mydb_2
DUMP_FOLDER 是将导出数据库的本地路径,GCS_BUCKET 是在第一步中创建的云存储存储桶的名称。
因为我有多个数据库,所以我为每个数据库创建一个备份,调用 backup 函数,将数据库名作为输入参数。
6.设置 cron
我已经将备份脚本设置为每周执行一次。
10 0 * * 1 /home/ubuntu/bin/backup.sh
结论
由于大多数数据库都有自己的导出命令,因此也可以很容易地进行编辑以用于备份。
糟糕的数据可视化以及如何修复它们
原文:https://towardsdatascience.com/bad-data-visualizations-and-how-to-fix-them-432444213c01?source=collection_archive---------25-----------------------
使用数据可视化原理来修复误导和无信息的图表
Firmbee.com在 Unsplash 上拍照
构建数据可视化:数据科学周期中的一个阶段,在此阶段,您在理解和清理数据集之后,可以展示您的发现。我相信你一定想知道以图形方式显示数据的最佳方式是什么,以及你所做的不同选择,无论是颜色、标题、标签还是单位,会如何影响观众对你的结果的感知。那么,视觉化是好是坏呢?
直观地说,一个好的可视化应该清晰准确地传达关于其内容的信息。虽然这看起来似乎是一个足够简单的任务,但使用大量工具来构建图表,很容易陷入制作不必要的复杂图表的困境,这些图表要么难以理解,要么可以在更简洁的图表中得到更好的简化。因此,在考虑向观众传达数据时,设计和内容似乎都是最重要的。
让我们考虑一个不满足好的可视化标准的可视化的例子。首先,让我们从导入 Plotly 开始,这是我们获取内置数据集的首选包,并打开 carshare 数据集:
乍一看,似乎有一个纬度和经度列,其中也包含单词“质心”,所以我可能认为它们代表某种多边形的中心。该数据还有一个名为 peak_hour 的列,这似乎是高峰汽车份额可用性的 24 小时格式的小时,还有一个 car_hours 列,这不是立即可以理解的。在 Plotly 文档中,我们被告知这与蒙特利尔一个月内的汽车可用性有关,因此这可能是一个月内每个高峰小时汽车数量的平均值。现在,我们想进一步探索数据,但在此之前,让我们先看看数据是否需要清理。
小时数据有没有 0 到 23 以外的奇怪数值?
不,不是的。car_hours 栏呢?它是否有低于 0 等不可能的值?
我们得到的是一个空的系列。因此,看起来数据状态良好,我们可以继续对其进行可视化处理。
示例 1:直方图
该数据集中的一个关键变量是 car_hours,我们假设它表示某个位置高峰时段的汽车共享车辆数。由于这是一个数字变量,我们可以使用直方图来可视化它,为了显示您在构建图表时做出的选择有多重要,让我们设置一个非常低的 bin 计数。
从这个直方图中我们能注意到什么?首先,它是向左倾斜的:在 1000 年和 2000 年似乎有更多的峰值汽车数量,而不是大于 2000 年。也有极少数地点的高峰车流量超过 3000 辆。我们如何知道这是否是有益的,或者我们的箱子应该有多大?我们现在的图表是否违反了我们任何好的图表设计原则?可以说,是的:如果我们考虑到我们正在比较不同车辆计数的频率这一事实,一个非常小的箱大小并不能帮助我们推断这些计数在高峰时间是如何分布的。
幸运的是,我们可以使用斯特奇规则,这是一个很好的确定 bin 大小的经验法则: K = 1 + 3。322 logN,其中 K 是容器大小,N 是我们拥有的观察值或数值的数量。在这种情况下,对于 N = 249(如在 249 个峰值汽车计数观察中),K = 8.9 或大约 9。那么,让我们来看看实际情况。
现在直方图更加精确了,我们可以看到数据中更具体的趋势。例如,看起来最常见的值是每个区域 500 到 1000 辆车(高峰时段),直方图是左偏的,但现在更清楚不同的计数如何细分为箱。
那么,我们能进一步改进这个图表吗?嗯,使用像 Plotly 这样的 Python 可视化包,我们可以控制图表的许多属性,比如颜色、标签和标题。当前的标签是否为查看者提供了足够的信息来清楚地理解图表所显示的内容?可能不会,因为我们已经确定 car_hours 标签有点模糊。因此,让我们修复它们,并添加一个描述性标题:
2.覆盖直方图
接下来,让我们想象一下 car_hours 在白天和晚上的分布情况。在这个图表中,我将从早上 5 点到晚上 8 点定义为白天,晚上 8 点到凌晨 4 点定义为晚上。下面是进行过滤和显示直方图的代码:
我在这里故意犯了一个错误。你能说出这是什么吗?这是为重叠直方图选择的颜色:红色和绿色。红色和绿色色盲是最常见的色盲类型,您在设计图表时必须记住,它们需要让您的所有观众都可以访问,这通常意味着要考虑可视化组件的设计,而不仅仅是它所呈现的内容。还有一个方法:在图例中添加正确的标签和合适的标题。所以让我们解决所有这些问题。
我们注意到什么有趣的趋势了吗?首先,这两个直方图似乎在它们覆盖的 x 值上有相似的分布。其次,两个直方图的大量数据似乎都集中在 500 到 1500 的范围内,这有点令人惊讶,因为我们会认为与白天相比,晚上的汽车共享服务可用性会更低。
3.互动和额外元素
要为图表添加额外的功能,您有许多选项可供选择。一个例子是为你的数据添加工具提示,当你将鼠标悬停在某个点上时,工具提示会显示该点的值。这在检查异常值时很有用,例如上面直方图中 3000 个区间,因为它们提供了对这些数据点的额外洞察。当您创建直方图时,Plotly 会自动创建这些工具提示,并帮助您的图表获得全面的信息。
那你怎么知道什么时候添加额外的元素,比如工具提示呢?您是否冒着使可视化过于复杂的风险,或者元素本身对于赋予图形意义是不可或缺的?对于最后一个例子,让我们来看看来自 Plotly 内置数据集的亚洲国家预期寿命数据的 3D 图表。
以上是结果。它看起来确实非常吸引人,比以前的视觉化效果更现代。但是,问题是:这个第三维度给数据增加了任何信息吗?这个图表可以被分成两个更容易理解的 2D 吗?我想是的。在我看来,如果我们只看每一对,就更容易看出年和预期寿命或年和人口之间的关系。虽然我们注意到这些年来预期寿命有明显的上升趋势,但很难准确确定国家之间的差异或人口增长如何影响预期寿命。总的来说,我认为这个图表很难解释,所以你应该把它分成两三个线图。
既然我们已经看到了一些如何提高我们的可视化的例子,那么主要的收获是什么呢?首先,考虑图表的设计:它的颜色和标签,同时记住,你要让你的图表尽可能简单直接,便于观众理解。接下来,你可能要抵制诱惑,不要选择看起来更复杂的图表,而要选择更简单、更容易显示变量之间关系的图表。
感谢你的阅读,我希望你喜欢这个故事!
令人困惑的真阳性和真阴性概念
原文:https://towardsdatascience.com/baffling-concept-of-true-positive-and-true-negative-bffbc340f107?source=collection_archive---------7-----------------------
了解 TP/TN 和 FP/FN
Michael Dziedzic 在 Unsplash 上拍摄的照片
在机器学习和统计学中,我们经常使用术语“真正”和“真负”,但人们仍然会感到困惑,因此他们的矩阵被称为混淆矩阵。现在的问题是什么是真和假,什么是正和负。我们可以读定义,可以更迷惑。所以,用简单的话来说,我们会明白的。
什么是积极和消极?
正面和负面无非就是两类,比如幸存/未幸存,癌症/未癌症,信用卡诈骗/未诈骗,垃圾邮件/未垃圾邮件等。它不仅在两个发生/没有发生之间,而且还可以分为猫/狗、雄性/雌性。因此,我们认为一类是积极的,另一类是消极的。这是任意的,或者取决于研究的目的,你认为一个是积极的,另一个是消极的。这里面没有好的(积极的)或坏的(消极的)方面。
什么是真假?
当有来自某个群体的样本数据时,我们使用建模来预测它的类别/标签。“真”表示模型能够识别其类的记录,而“假”表示模型不能识别的记录。
混乱矩阵
混淆矩阵是表示分类问题预测结果汇总的表格。我们可以在下面看到一个混淆矩阵。预测值和实际值的位置改变了假阴性(FN)和假阳性(FP)的位置,但是真阳性(TP)和真阴性(TN)保持在矩阵中彼此对角放置的相同位置。但正因为如此,情况变得扑朔迷离。
作者图片
简单的例子来更好地理解这个概念。在这个例子中,有两类水果。我们有 9 个苹果和 10 个草莓,但是模型只正确识别了 6 个苹果(真阳性)和 8 个草莓(真阴性),此外,模型预测 2 个草莓是苹果(假阳性),3 个苹果(假阴性)是草莓。在另一个例子中,怀孕/未怀孕是两个类。有 8 名妇女怀孕,8 名妇女未怀孕,该模型正确地将 6 名怀孕(真阳性)和 5 名未怀孕(真阴性)的妇女分类,但将 3 名未怀孕(假阳性)的妇女分类为怀孕,将 2 名怀孕(假阴性)的妇女分类为未怀孕。
作者图片
通过下面的 GIF,你可以更清楚地理解这个概念。
作者图片
绩效评估措施
从混淆矩阵中,我们还可以计算模型的准确率、精确召回率和 F1 值。这些度量有助于理解模型的性能。从公式中,我们可以计算这些措施,并计算我们可以使用混淆矩阵。公式在下面的矩阵中给出。这里 NPV 是负的预测值。如上所述,随着实际值和预测值的位置改变,度量的位置也改变。
用更简单的术语定义:
准确性:准确性是模型正确分类的记录占记录总数的比率。例如,如果有 10 个红色球和 10 个紫色球,其中 8 个红色球和 7 个紫色球你识别正确,那么你的准确度是 8+7/20=0.75,因此,准确度是 75%。
Precision: Precision 是模型正确识别的阳性记录与全部阳性记录的比率。例如,如果有 10 个红色球和 10 个紫色球,人们必须识别哪些是红色球,并且出于任何原因,您将 8 个红色球和 2 个紫色球识别为“红色球”,那么您的精度是 8/10,即 80%。
敏感性:检测正确识别真阳性的能力(患有疾病的人和模型如此识别)。
特异性:检测正确识别真阴性的能力(没有患病的人和模型如此识别)。
F1 得分:F1 得分是精度和召回率/灵敏度的加权平均值,最佳得分为 1,最差得分为 0。公式如下。
作者图片
作者图片
Python 代码
我们可以构建这些混淆矩阵,甚至使用 Python 轻松计算这些度量。所用数据取自 UCI 库存“https://archive . ics . UCI . edu/ml/datasets/Heart+failure+clinical+records”。代码如下:
Sklearn.metrics 提供了不同的选项来制作混淆矩阵,首先只是为了显示数字,一个选项是混淆矩阵,它给出的矩阵如下。
作者图片
而且,为了绘制混淆矩阵,sklearn.metrics 有两个选项,即 ConfusionMatrixDisplay 和 plot_confusion_matrix。通常使用 plot_confusion_matrix,因为只有在选项 normalize 为“真”时,才可以获得归一化混淆矩阵图。
作者图片
我们也可以使用 python Seaborn 的热图来制作如下的混淆矩阵,“不能”选项保持 false 会删除矩阵中的数字。
作者图片
下面是获得准确度、召回率、F1 得分、精确度、roc auc 得分(根据预测得分计算受试者操作特征曲线下面积(ROC AUC))的代码。
作者图片
作者图片
虽然有一些简单的选择来创建混淆矩阵和计算评估措施,但我们最好理解这些概念和公式,以便我们能够理解和解释这些分析。
感谢阅读!
参考资料:
https://sci kit-learn . org/stable/modules/classes . html # module-sk learn . metrics
利用 Bag 数据库进行 bag 文件管理
原文:https://towardsdatascience.com/bag-file-management-using-bag-database-44d774d54df3?source=collection_archive---------31-----------------------
一个来自 swri 机器人的开源项目。
照片由尼古拉斯·佩罗尔在 Unsplash 拍摄
如今,自动驾驶汽车越来越普遍。像特斯拉这样的大公司正在让无人驾驶汽车成为现实。为了收集数据以便 auto car 可以在现实世界中学习和适应,我们需要处理大量的包文件。
包是 ROS 中用于存储 ROS 消息数据的文件格式。包——如此命名是因为它们。包扩展——在 ROS 中有着重要的作用,并且已经编写了各种工具来允许您存储、处理、分析和可视化它们。
示例 ROS 包文件可以从http://real sense-HW-public . S3 . amazonaws . com/RS-tests/test data/stairs . bag中获得。
箱包数据库管理
最简单的开始方式是从 docker-compose 触发箱包数据库,无需认证。在您的目录中创建 docker-compose.yml 文件:
注意:在 docker-compose 之前,您需要创建/var/local/bags 和/var/lib/docker/volumes/bag-database _[scripts,indexes,postgres]。
运行后
docker-compose up
我们将看到 bag-database 正在端口 8080 上运行
我们可以观看录像
或者直接看地图
希望有帮助。
开心编码~
参考
https://github.com/swri-robotics/bag-database
包装决策树——解释清楚
原文:https://towardsdatascience.com/bagging-decision-trees-clearly-explained-57d4d19ed2d3?source=collection_archive---------10-----------------------
整体技术-装袋
照片由皮查拜从派克斯拍摄
决策树
决策树是监督机器学习算法,用于分类和回归任务。
在本文中,我介绍了以下概念。
- 如何建立决策树?用什么标准来分割决策树?
- 如何克服决策树中的过度拟合?
- 什么是装袋?包装决策树是如何工作的?
决策树是一种树状模型,可用于预测目标变量的类别/值。决策树有效地处理非线性数据。
作者图片
假设我们有难以线性分类的数据点,决策树提供了一种简单的方法来确定决策边界。
作者图片
它通过递归分割整个区域来实现。让我们看看分裂是如何进行的。
节点类型
- 根节点—决策树中最顶端的节点称为根节点。
- 内部节点—进一步分裂的子节点称为内部节点。
- 叶节点—不会进一步拆分的节点称为叶节点
如何在决策树中进行拆分?
在决策树中,在每个节点,基于特征进行分割。如果特征是连续变量,则在某个阈值上形成分裂条件。【比如年龄> 50】。如果特征是分类变量,则对所有值进行分割。【例如。性别=男性】。
选择杂质减少更多的分流。
用于计算最佳分割的标准是
- 分类误差
- 熵
- 基尼指数
分类误差
如何计算分类误差?
根据拆分条件,节点 N1 被拆分为 N2 和 N3[图片由作者提供]
步骤 1:计算节点 N1 处的分类误差【分割前】
P[类 0]= 3/8
P[类 1]=5/8
1- max[p(c)]=1-[3/8,5/8]= 1–5/8 = 3/8
classification error before split =3/8
步骤 2:计算节点 N2 的分类误差
P[0 级]= 1/4
P[1 级]=3/4
1- max[p(c)]=1-[1/4,3/4]= 1–3/4 = 1/4
第三步。在节点 N3 计算分类误差
P[0 级] = 2/4
P[1 级]= 2/4
1- max[p(c)]=1-[2/4,2/4]= 1–2/4 = 2/8
第四步。子节点的平均分类误差。
节点 n2 中数据点的比例= 4/8
【8 个数据点中有 4 个在节点 N2】
节点 n3 中数据点的比例= 4/8
【8 个数据点中有 4 个在节点 n3】
加权分类误差= 4/8 * 1/4 + 4/8 * 2/4 = 3/8
classification error after split =3/8
5。分类错误变更:
分割前的分类误差= 3/8
分割后的分类误差= 3/8
分类误差变化= 3/8–3/8 = 0
Classification error for the above split is 0
分割是基于每个特征进行的。对于每个特征,计算分类误差的变化,选择产生最大分类误差变化的特征进行分割。
但有时,分类误差变化将为零。[在上面的例子中,分类误差变化为零]。所以,这不是首选。基尼指数和熵优于分类误差。
熵
熵用于度量决策树中节点的同质性。如果节点是同质的,熵是 0。熵指的是杂质。
熵公式
熵的范围从 0 到 1【针对 2 类问题】
- 如果节点是同质的,并且所有数据点都属于类 0 p[class=1]=0。熵将为 0。[纯节点-无杂质]
- 如果节点是同质的,并且所有数据点都属于类 1,p[class=1]=1。熵将为 0。[纯节点]
- 如果节点包含相同数量的属于类 0 和类 1 的数据点,则 p[c=1]=0.5。熵将是 1。
信息增益
熵(杂质)的减少被称为信息增益。如果特定拆分的信息增益更大,则首先执行该拆分条件。
Information gain= Entropy before split — Entropy after split
为上述决策树计算熵。
计算分裂前后的熵[图片由作者提供]
计算信息增益。
分割是基于所有特征完成的。对于每个特征,计算信息增益,并选择给出更多信息增益[杂质减少更多]的特征用于第一次分离。
基尼指数
基尼指数是衡量杂质的另一个标准。
基尼指数下降
基尼系数的范围从 0 到 0.5。
熵的范围从 0 到 1。
决策树中的问题
决策树往往会过度拟合。它将继续增长,直到所有的叶节点都是纯的。所有叶节点都是同质的[属于一个类]。这将产生一个精确符合训练数据的树。所以,它不会很好地概括,也不会在测试数据中表现良好。
如何克服决策树中的过拟合?
为了防止过度拟合,应该有一些停止标准。
避免过度拟合的两种方法。
- 截断或预修剪→有许多超参数来截断树。这是一种自上而下的方法。
- 让树完全长大,然后修剪。这是一种自下而上的方法。
预剪枝→决策树停止准则—决策超参数
- 最大深度 →树被允许生长到提到的最大深度。
- min_samples_split →拆分决策节点所需的最小样本数。[决策节点是具有进一步拆分的节点]。如果决策节点的样本数少于 min_samples_split 中提到的样本数,则不会进一步分割。
- min_samples_leaf →一个叶节点所需的最小样本数。
- max_features →进行分割时要考虑的特征数量。
通过调整这些参数,它可以防止树过度拟合。
后期修剪→减少错误修剪
这是一种自下而上的方法。一棵树完全长大后,再修剪。
训练数据分为训练集和验证集。迭代地修剪节点,并在确认集和训练集中检查修剪树的性能。如果验证集中被修剪的树的准确度大于训练集的平均值,则该节点被修剪。修剪意味着删除以该节点为根的子树。
为什么要用装袋?
决策树是高方差模型。这意味着训练数据的微小变化,将导致完全不同的模型。决策树通常会过拟合。为了克服这种情况,可以使用集成技术——bagging。
什么是装袋?
Bagging 表示自举聚合。 Bagging 是指利用样本子集建立不同的模型,然后聚合不同模型的预测值以减少方差。
装袋如何减少差异?
假设我们有一组' n' 的独立观测值,比如说 Z1,Z2…Zn 。个体观察的方差为 σ2 。
所有数据点的平均值将为( Z1+Z2+…)。+Zn)/n 类似地,该平均值的方差将是 σ2/n.
因此,如果我们增加数据点的数量,均值的方差就会减小。这就是装袋决策树背后的概念。
同样,如果我们在给定的数据集上训练多个决策树,然后聚合预测。方差将会减小。
引导样本
装袋分两步
- 拔靴带
- 聚合
拔靴带
我们已经知道,如果我们对一组观察值进行平均,方差将会减少。但是我们只有一个训练集,我们必须建立多个决策树。
引导有助于从训练数据中创建多个子集。然后,我们可以在自举样本上构建多个树。
Bootstrapping 将从训练集中随机选择重复的数据点,并创建多个子集-替换采样。
如果在训练集中有‘n’个数据点,
在 bootstrap 样本中选择特定数据点的概率= 1/n
bootstrap 样本中特定数据点未被选择的概率=
1-1/n
所以,自举样本中每个点未被选中的概率=
(1–1/n)^n
引导样本中未选择的数据点的百分比-按作者分类的图像
这种方法也被称为 0.632 自举。表示 bootstrap 样本中每个数据点被选中的概率=63.2%。
每个引导样本将包含原始训练数据的 63.25% 。剩余的数据点将是重复的。
每个引导样本将不包含 36.8% 的训练数据。这用作从该样本构建的模型的测试数据。
汇总输出
现在,我们有了不同的引导样本,并为每个引导样本构建了' B' 决策树。下一步是汇总输出。
套袋分类树
对于测试集中的每个数据点,通过' B' 树来预测输出类。基于多数表决机制,计算最终类。
另一种方法是从“B”树中获得类的概率,并且根据概率的平均值对最终的类进行分类。
装袋回归树
对于回归→对于测试集中的每个数据点,从“B”回归树的所有预测的平均值计算目标值。
Bagging 是引导聚集
通过从训练数据集创建引导样本,然后在引导样本上构建树,然后聚合所有树的输出并预测输出,来完成决策树的打包。
bagging[图片由作者提供]
如何计算装袋误差?
我们知道,在每个 bootstrap 样本中,大约有三分之一的数据点被遗漏(36.8%)。来自训练集的大约只有三分之二的原始数据点被包括在引导样本中(63.2%)
因此,对于基于自举样本构建的每棵树,误差是根据该特定自举样本的未使用样本计算的。测量所有误差的平均值。这就是所谓的出 BagError。
如何计算特征重要性?
通过使用基尼指数/熵来计算特征重要性。
在为每个引导样本构建树时,基于信息增益在节点中进行分裂。我们将查看所有树中该特征的信息增益。然后在所有树中平均该特征的信息增益。
袋装决策树的优势
- 模型的方差减小。
- 可以同时训练多个树。
包装决策树的问题。
如果一个特征是最强的预测值,并且它对目标变量均值有更大的影响,则基于不同引导样本构建的所有树将首先基于该最强的预测值进行分割。因此,在不同引导样本上训练的所有树将是相关的。所以,它不会减少模型的方差。
为了克服这种情况,使用了随机森林。同样在随机森林中,我们将训练多棵树。但是数据点和特征都是随机选择的。通过这样做,树不相关,这将改善方差。
结论
决策树使用像基尼指数/熵这样的分裂标准来分裂节点。决策树往往会过度拟合。为了克服过度拟合,使用预修剪或后修剪方法。装袋决策树也被用来防止过度拟合。
我希望这篇文章对你有所帮助。感谢阅读!
进一步阅读:
https://betterprogramming.pub/understanding-decision-trees-in-machine-learning-86d750e0a38f
如果你喜欢看我的更多教程,就关注我的 中 ,LinkedIn,Twitter。
点击这里成为中等会员:https://indhumathychelliah.medium.com/membership
烘焙扫描和细胞扫描
原文:https://towardsdatascience.com/bakeryscan-and-cyto-aiscan-52475b3cb779?source=collection_archive---------18-----------------------
人工智能识别面包的意外结果
最近有人问我这个问题:“你为什么决定学数据科学?”我首先想到的是一些事件,比如在我以前的安全工作的停工期自学 Python,编写 Python 脚本来输入并在飞行地图上显示公司旅行者的数据,或者只是我在报告我的工作大楼里哪些门最常使用时获得了多少乐趣。然而,我越想越意识到,这些都是促使我决定学习数据科学的因素,而不是主要原因。主要原因来自一个故事,自从我第一次听到这个故事,它就一直萦绕着我。
大脑有限公司
2007 年,日本科技公司 Brain Co. Ltd .向大公司出售软件取得了一定的成功。例如, TEX-SIM 是他们开发的用于设计纺织品图像的用户界面工具。他们还帮助开发了在个人电脑上显示汉字的软件,甚至制作了设计桥梁的软件。当地一家面包店找到了这些才华横溢的软件工程师,他们希望解决一个问题,Brain 公司对此一无所知,但他们对这个问题的解决方案将会定义他们,并将产生比他们计划的更大的影响。
日本的糕点问题
T2 的面包店以拥有种类繁多的新鲜出炉的糕点而自豪。一些面包店每天早上会制作数百种不同种类的糕点给 T4。在面包店进行的分析研究发现,售出的糕点总量与售出的不同种类的糕点总量直接相关。一家提供 100 种糕点的面包店的销售额是提供 30 种糕点的两倍。该研究还发现,顾客更喜欢没有包装的糕点,并且喜欢放在敞开的篮子里,如下图所示。
照片由水貂在 Unsplash 上混合而成
当面包店根据分析研究实施这些变革时,一个新的、不可预见的问题出现了。因为糕点根本不需要包装,所以没有办法在上面贴上条形码。顾客会把糕点交给收银员,收银员必须识别糕点,并正确记住它的价格。其中一些面包店有数百种不同价格的独特糕点,所以这开始给收银员带来明显的压力。培训新员工意味着教他们如何正确识别所有糕点并记住它们的价格。面包店老板开始注意到培训新店员需要几周的时间,即使训练有素的店员也要花相当多的时间才能正确识别顾客的物品。因此,当地一家面包店找到 Brain Co .询问他们是否有更好的解决方案。
贝克斯坎和大脑试验公司。
大脑公司面临着一个难以置信的任务。该团队无法获得神经网络所需的大量数据,因此他们必须想出另一种解决方案。除了这个难题之外,2008 年的金融危机发生在项目开始一年之后。Brain Co .发现他们所有的其他商业机会都已经枯竭,公司的生存突然取决于这个项目的成功。大脑公司的团队将他们的一切投入到这个项目中,这个项目将成为 BakeryScan AI。《纽约客》的詹姆斯·萨默斯描述了该团队如何开发解决方案:
计算机视觉领域的最新技术包括将一系列算法拼凑在一起,每一种算法负责一项特定的任务。假设你想建立一个行人识别系统。你首先要有一个算法来调整你图像的亮度和颜色,这样你就不会被某人的红色衬衫所困扰。接下来,你可以添加识别感兴趣区域的算法,也许是通过注意人行横道的斑马图案。只有这样,你才能开始分析图像“特征”——梯度和对比度的模式,可以帮助你挑出某人肩膀的独特曲线,或躯干和腿形成的“A”。在每一个阶段,你都可以从数十种甚至数百种算法中进行选择,并选择组合它们的方式。
使用这种“算法管道”导致了许多问题,这些问题都记录在团队的开发文档中。问题很多——例如,他们发现房间的照明会显著影响面包店扫描的准确性。他们发现,当两个糕点靠得很近时,面包店会有麻烦,必须开发一种方法来辨别这种情况何时发生。当糕点被撕开或损坏时,也会发生同样的情况。有时他们会遇到一些问题,比如一个甜甜圈投在甜甜圈孔上的阴影会阻止面包店正确识别商品。他们以首席执行官 Hisashi Kambe 所描述的“疯狂”的专注持续解决这些问题。有一次,该团队在两年的时间里开发了 10 个原型。最后,在 2013 年:
Brain 公司 5 年的努力得到了回报。他们开发了一种人工智能,可以以令人难以置信的准确度识别 50 多种不同的糕点。BakeryScan 通过摄像头识别糕点,然后向店员显示其名称和价格,只需几秒钟。BakeryScan 大受欢迎,每台售价 20,000 美元,现已在日本 400 多家商店使用。
贝克斯坎的遗产
这个故事本身是鼓舞人心的;一个软件开发团队,他们的生计岌岌可危,他们将所有的一切投入到一个看似不可能的任务中,并取得了成功。然而,故事并没有到此结束。
2017 年,一名在京都路易·巴斯德医学研究中心工作的医生看到了一则面包店的广告。经过一番思考,他有了一个非常有趣的认识。他认为被人工智能扫描的面包店食品与他一直在研究的癌细胞有着惊人的相似性。因此,他决定联系 Brain Co .看看他们是否有兴趣进行测试,看看 BakeryScan 是否能够在显微镜下检测癌细胞。
细胞扫描
贝克斯坎能够在显微镜下以 98%的准确率识别出癌细胞。起初,它一次只能观察一个细胞。经过一些修改和测试,人工智能能够在显微镜下观察整个细胞切片,并突出显示哪些细胞是癌变的,准确率再次达到 98%的。在治疗癌症时,癌症发现得越早,存活率就会大大提高。使用人工智能极大地提高了实验室技术人员整理样本和检测癌细胞存在的速度。Brain Co .给改造后的 BakerScan 起了一个新名字:“Cyto-AiSCAN”,目前正在日本神户和京都的两家大医院接受医生的使用和培训。****
当我听到这个故事时,我立即想到他们一定已经显著改变了贝克斯坎检测癌细胞的操作方式。《纽约客》的记者詹姆斯·萨默斯也有同样的想法。他向 Brain Co .的首席执行官 Hisashi Kambe 提出了同样的问题。
我问 Kambe 它是如何工作的——它使用深度学习吗?“原路,”他说。然后,带着灿烂的笑容,“和面包一样。”
不,和面包一样。
一个人创造的东西的影响
我经常想,在 2008 年开发 BakeryScan 的团队是否曾想过他们的人工智能会发展成这样。尽管我很怀疑是否有人能预见到这个结果。一名医生意识到糕点在显微镜下看起来几乎像癌细胞,于是心血来潮联系了该公司!这一事件导致这个人工智能从识别糕点到协助医生拯救生命。我想回到 2008 年,Brain Co .团队在开发 BakeryScan 时经历了一些非常令人沮丧的日子。我希望在那些日子里,有人能回到过去,让他们看看他们的小 AI 会变成什么样子。
这是我最喜欢的故事之一,因为它不仅仅是一个故事。这是一个艰难、胜利和奉献的故事。谁能想到面包扫描仪能拯救无数生命?我几乎可以保证他们没有。他们对这个项目的奉献和热情把他们带到了一个目的地,在他们到达之前,他们甚至不知道这个目的地的存在。
这个故事是我想学习数据科学的主要原因。也许它不会是用深度学习训练一个人工智能,或者创建一个神经网络,但我确实希望我能有幸创造一些有影响力的东西;一些超出我预期的东西。一些让我感到自豪和充满激情的事情。数据科学领域是我最擅长做类似事情的地方。我希望 Brain Co .团队为自己感到骄傲,知道即使他们的小 AI 不会被永远使用,他们创造的影响也会在未来很长一段时间内被记住。
参考
"设计用来区分糕点类型的人工智能识别癌细胞的准确率达到 99% . "Express Digest ,Express Digest . com/ai-designed-to-discriminate-types-of-pastes-identified-cancer-cells-with-99-accuracy/。
"人工智能糕点扫描仪正在与癌症作斗争."正在与癌症作斗争的人工智能糕点扫描仪——CES 2022,2018 年 5 月 20 日,www . CES . tech/Articles/2021/May/The-AI-Pastry-Scanner-That-Is-Now-Fighting-Cancer . aspx .**
“bakery scan-瞬间识别所有糕点!-." YouTube ,YouTube,2020 年 12 月 24 日,www.youtube.com/watch?v=vTwxKXokVB8.
詹姆斯·萨默斯。“学会抗癌的糕点人工智能”《纽约客》,2021 年 3 月 18 日,www . New Yorker . com/tech/annals-of-technology/The-pastry-ai-that-learn-to-fight-cancer。
平衡行为:不平衡数据的分类
原文:https://towardsdatascience.com/balancing-act-classification-with-imbalanced-data-cea06df39781?source=collection_archive---------13-----------------------
帮助您的数据找到平衡点,以确保创建质量分类模型
Niklas Ohlrogge 在 Unsplash 上拍摄的照片
瑜伽、放松、感恩日记:所有这些都可能帮助你找到平静与和谐。但是你的数据集也需要你的帮助来达到一个理想的平衡——而且,就像人类的自我保健一样,如果我们不花时间去寻找平衡,事情可能会出错。
图片 via GIPHY
了解您的训练数据在您想要预测的类中的分布并做出相应的调整是创建质量分类模型的关键步骤。当您试图预测一些不经常发生的事情时,例如很少发生的欺诈性交易或不寻常的设备故障,不平衡的数据集尤其容易发生。然而,不管您的特定领域是什么,您总是想要评估目标类的分布。
深吸一口气,让我们来探索如何和为什么与不平衡的数据集进行斗争。这里我们将关注二元分类,这里有两种可能的目标变量结果。我们将在 Alteryx Designer、Alteryx 机器学习和 Python 中使用一些工具来简化这个过程。
用 EDA 解放你的思想
这可能已经是您数据分析例行程序的一部分,但是彻底的探索性数据分析(EDA)对于成功的模型构建是至关重要的。特别是,为了我们的目的,你要密切注意你的结果变量的分布。无论您是尝试构建二元分类模型(只有两个类)还是多类分类模型(有两个以上的选项),如果您的数据非常均匀地分布在各个类中,那么前进的道路是最简单的。
当然,事情很少会如此顺利。让我们以来自 Kaggle 的信用卡欺诈检测数据集为例来看看。我为这个演示创建了一个较小版本的数据集,有 57,355 行,每行代表一个事务。不过,我保留了欺诈/非欺诈交易之间的不平衡,其中只有 492 笔交易被标记为欺诈。
在 Alteryx Designer 中,使用基本数据分析工具和频率表工具以及其他选项,很容易快速了解变量的分布。后者生成如下图所示的直方图,使数据集中的不平衡非常明显。
“类别”字段中 0 和 1 标签的直方图,其中 1 代表相对较少的欺诈交易。图片作者。
失去平衡
如果你反复随机选择这个数据集中的一行,然后问我这是不是一次欺诈交易,如果我只是一遍又一遍地说“不是”,我就很有可能是对的。类似地,如果你简单地根据这些不平衡的数据训练一个模型,并且只看你的模型的准确性,看起来你有一个令人惊讶的模型。您可以在本文中阅读更多关于为分类模型选择正确指标的信息;现在,请记住,对于不平衡的数据来说,准确性本身确实会产生误导。
图像通过 GIPHY
举个简单的例子,让我们把我的迷你数据集分成 70%用于训练,30%用于验证。我可以天真地构建一个随机的森林模型,不调整目标类之间的平衡。(您可以通过打开 Alteryx 社区上原始帖子的附带的 Alteryx 包来跟进。)一开始我可能会印象深刻:哇,模型只错分了 40149 个观测值中的 70 个!但是让我们仔细看看:
图片作者。
不幸的是,正如你所看到的,这个模型在预测非欺诈交易方面做得很好——但是,对不起,是信用卡账户持有人;它在检测欺诈的实际工作中表现不佳。是时候做些调整以获得更好的结果了!
关于抽样的思考
谢天谢地,我们有一些平衡数据集的方法来避免这种情况。让我们探索一些选项,从最简单到最复杂排列(但是仍然非常容易管理!).
图片经由 GIPHY
Alteryx 机器学习
如果你是第一批使用 Alteryx 机器学习的用户之一,你会很幸运——尤其是当你正在与不平衡的数据进行斗争的时候。Alteryx 机器学习将自动检查类标签的分布(例如,0/1、真/假等。)在您的数据集中。然后,它会根据数据集的大小应用适当的过采样或欠采样,以适应它发现的任何不平衡。例如,它可以应用过采样技术 SMOTE,我们稍后会讨论这一点。
在最初的“Auto Insight”数据探索阶段,Alteryx 机器学习生成了一个易于下载的图,如下图所示,显示了目标变量的类标签分布。
Alteryx 机器学习的目标变量标签分布柱状图。图片作者。
在这种情况下,如下图右侧所示,Alteryx 机器学习决定从我的不平衡数据集中的多数类(非欺诈性交易)中进行欠采样,然后构建一系列模型,以查看哪个表现最好。(Alteryx 机器学习速度如此之快,以至于我可以使用完整的数据集来代替样本。)
在这里,我选择了平衡精度作为评估模型的度量,随机森林分类器在比较中脱颖而出。当对维持数据进行评估时,该模型在过程的下一步中表现更好,平衡精度为 91%。
图片作者。
Alteryx 智能套件
使用 Designer 中的智能套件,您有几个选项。首先,您可以使用 AutoML 工具来自动构建和评估模型,这些模型优先考虑您选择的度量标准。在该工具的高级参数选项中,您可以选择一个更适合不平衡数据集的指标,或者尝试多个选项以查看它们的比较情况。例如,您可以告诉工具在评估各种模型时优先考虑平衡的准确性或日志损失。
使用两种不同的适合不平衡数据的目标函数选项设置 AutoML。图片作者。
来自两个自动生成模型的结果。图片作者。
在这里,辅助建模也是一个选项,但是您需要仔细查看模型排行榜,以了解各种指标的情况。同样,准确度不是唯一要考虑的指标,所以一定要检查每个型号的平衡准确度和 F1 分数,并确保您对您选择的型号在各个班级的表现感到满意。
这些数据的辅助建模分类模型的结果。图片作者。
过采样现场工具
过采样现场工具包含在 Designer 中,非常容易使用,尽管它的名字有点混乱;它真正欠采样你的多数类,而不是过采样你的少数类。只需将它放入您的工作流中,告诉它您希望它调整哪个变量,该变量的“正”类是什么(例如,在本例中,“1”表示“欺诈性的”),以及您希望数据集中的类比例是多少。本质上,这个工具将随机删除足够多的“负面”案例,以达到这些比例。
但是,根据数据集的大小和正类的相对出现频率,最终可能会留下非常少的记录,因此,您没有多少信息来构建模型。例如,如果您有 1000 条记录,其中只有 100 条表示正类,并且您要求工具为您实现 50/50 的平衡,那么您最终将只有 200 条记录来构建您的模型。对于您的特定建模需求来说,这可能不太理想。
简单过采样
另一种平衡方法是根据目标变量的值对训练数据进行分层,然后从较小的“少数”类中随机抽样替换。目标是在训练数据集中过多地呈现这些观察结果。然而,这种“幼稚”的采样方法会产生重复的数据,并可能导致您的模型从这些数据点学到太多东西,从而可能导致过度拟合。
幸运的是,聪明的机器学习研究人员已经开发出更复杂的方法来实现平衡。
图像通过 GIPHY
介绍 SMOTE
另一种平衡数据的方法是 SMOTE,代表合成少数过采样技术。SMOTE 是一种广泛使用的处理类不平衡的技术。基本上,这种方法会为您弥补一些数据,但这是一种好的方式。“合成”部分是指生成与少数类中的数据相似的额外数据的过程,这些额外数据可以添加到数据集中以平衡这些类。
SMOTE 的工作方式是选择一个表示少数类的观测值,查找其最近邻点(您可以指定数量),并使用所选观测值和邻点之间的关系来生成少数类的新示例。
SMOTE 家族宏
应用 SMOTE 的一种方法是使用 SMOTE 家族宏,它是由 Alteryx 社区成员@ Timothy创建的,包含在本文所附的 Alteryx 包中。这个基于 R 的宏使用了 smotefamily 包,其中包含了各种实现基于 SMOTE 技术的方法。
例如,在所附的工作流中,通过 SMOTE 系列宏传递数据并使用常规 SMOTE 选项,实现了更好的平衡:39,791 个非欺诈性交易和 39,738 个“欺诈性”交易。后者中,只有 492 个在我的原始数据中,而其余的都是合成的。
接下来,让我们重新看看我之前尝试的随机森林模型,但是现在使用的是后 SMOTE 数据集。我的模型现在可以从更多的例子中了解欺诈交易(即使其中大多数是合成的),因此,它可以更好地对数据进行分类:
通过 SMOTE 系列宏处理的数据构建的模型的性能。图片作者。
后 SMOTE 模型并不完美,但它只对 27 个交易进行了错误分类,并且它的准确性在两个类别中大致相同,而不是在一个类别中比另一个类别中犯更多的错误。
除了宏中提供的配置选项之外,请记住,您还可以打开宏并根据自己的需要修改它的代码。本文提供了在 Designer 中使用 R 的一些细节。
图像通过 GIPHY
Python 中的 SMOTE
最后,如果您最喜欢 Python 解决方案,您可以使用不平衡学习库来实现各种采样方法,这些方法可以解决您的数据不平衡,包括 SMOTE。在工作流中使用这种方法只需要 Python 工具中的几行代码,正如您在附带的演示中所看到的。然而,这种方法提供了大量的定制选项。
您将需要安装该软件包,因为它不包含在设计器中;这意味着您需要以管理员身份运行 Designer。这一步完成后,您只需将数据集分为预测变量和目标变量,使用 SMOTE 或您从库的选项中选择的方法进行重新采样,然后重新组装数据集。然后,您可以从 Python 工具中写出更加平衡的、部分合成的数据,以便在工作流中以您喜欢的方式进一步使用。
我正是这样做的,然后再次使用森林模型工具来构建一个随机的森林模型。结果看起来很像基于上述 SMOTE 系列宏数据构建的模型的结果:
通过 SMOTE 处理数据建立的模型的性能,通过 Python 工具中的不平衡学习实现。图片作者。
这里,总体准确性更好,并且模型的错误在两个类之间平均分布,而不是在原始数据中较少表示的“少数”类上表现不佳。
让我们将所有三个模型——简单模型和两个 SMOTE 'd 模型——都放入模型比较工具中,以便进行整体观察:
模型比较工具对三种模型性能的报告。图片作者。
从上表的比较报告中可以看出,所有三种型号的总体准确率都超过了 99%。然而,建立在不平衡数据上的朴素模型对欺诈交易的性能较低。这两个建立在更平衡数据基础上的模型表现都稍好。如果我们使用 Kaggle 上提供的完整数据集,有近 300,000 个事务,我们可能会获得更好的性能。此外,如果像检测欺诈这样的潜在成本很高的事情,即使是很小的性能改进也可能在财务上非常有意义。
图像通过 GIPHY
找到完美的平衡
现在,您拥有了新的工具,可以在数据和生活中找到平衡!好吧,至少在数据上是这样,尽管更好的模型可能也会给你带来快乐。请务必查看下面推荐的阅读链接,了解解决这一重要问题的更多信息和选项。
推荐阅读
- SMOTE:合成少数过采样技术(原始研究论文)
- 用 Python 攻击不平衡分类
- 不平衡分类项目的分步框架
- 使用不平衡学习库的例子
- 另一种策略:如何处理不平衡的分类,无需重新平衡数据
原载于 Alteryx 社区数据科学博客 。
平衡就是不平衡
原文:https://towardsdatascience.com/balancing-is-unbalancing-5f517936f626?source=collection_archive---------33-----------------------
入门,机器学习
不平衡分类背后的理论
由阿马尔·埃拉米尔在 Unsplash 上拍摄的照片
不平衡分类是一个监督的最大似然问题,其中类别分布非常不均匀(例如,5%正的和 95%负的),并且通常,对具有少数类别标签的数据的决策是重要的,是正确的。在这种情况下,训练更具挑战性,因为使用普通方法,模型越来越偏向于估计具有多数标签的类(多数类),而大多数时候,我们关心的是正确估计少数类。开发了不同的技术来克服这一挑战,例如重采样或加权;都试图以某种方式创建一个平衡的数据集,然后使用共同的方法。虽然这些技术在应用中是有益的,但它们对我来说都是启发性的,我无法找到该问题的精确数学定义。所以我决定思考到底会发生什么,这份文件是我对不平衡数据挑战的理解。
判别模型是如何工作的?
监督概率机器学习的主要关注点是使用条件似然最大化来估计具有参数分布的p(y | x)**q(y | x,θ) ,这可以通过采用交叉熵损失函数(又名 log-loss)来完成。此外,最小化交叉熵损失函数等价于最小化真实条件分布和估计条件分布之间的 KL 散度:
在这个等式中, H(Y|X) 是常数,所以为了最小化期望的 KL 散度,我们应该最小化第二项,它等于对数损失。为了最小化对数损失,首先,我们需要来自 p(x,y) 的样本来估计期望值,然后,我们可以解决一个优化问题,找到 q(y|x,θ) 作为对 p(y|x)的估计。
但是如果我们只有来自 p'(x,y) = p(x|y) p'(y) 的样本而不是 p(x,y) 其中 p'(y) 是不同于 p(y) 的经验边际分布呢?我们可以将对数损失改写如下,并使用样本重量:
它表明,要学习 p(y|x) 我们需要将样本权重设置为p(y)/p’(y),如果经验边际分布与真实边际分布相同,则等于 1。因此,如果 p(y+)=5% ,但是数据集是平衡的并且 p'(y+)=50 %,我们需要将样本权重设置为 0.1 。这与我们对不平衡数据集所做的正好相反,在不平衡数据集上,我们认为平衡后权重相等。因此,主要问题是使用不平衡数据集的真实边际分布有什么问题?困难就在这里,平衡是解决问题的方法。
不平衡数据有什么特别之处?
当我开始思考这个问题时,首先我记得偏向多数类并以此预测所有样本,因此我认为这个问题可能是由于优化问题的难度和陷入局部最优。事实上,对于不平衡的数据集,边缘分布和条件分布在很大程度上几乎是相同的,这与平衡数据集不同。所以通过设置 q(y|x)=p(y) 并用 p(y) 预测 p(y|x) ,交叉熵等于 H(Y) 这么小。因此,我认为用多数类预测可能是参数空间中的强局部最优。但后来我想起,损失函数是凸的逻辑回归,所以它应该训练没有任何问题。在下面的例子中,在没有使用任何平衡技术的情况下,逻辑回归在不平衡数据上工作得很好,我们可以用 σ(wᵀx) 很好地估计 p(y+|x) :
图一。在不平衡数据集(5%-95%)上进行 logistic 回归的结果确实不错。
经过这次模拟,我提醒说,在我的经验中,不存在少数类概率接近 1 的特征空间区域(如上图),通常多数类几乎处处可见,只是概率不同。作为另一个例子,考虑下图,让我们看看逻辑回归是如何工作的:
图二。在另一个不平衡数据集(5%-95%)上的 logistic 回归结果确实很差。
你可以观察到,logistic 回归模型没有学好,我们无法用 σ(wᵀx).估计 p(y|x) 通过这些观察,我们可以提出一个重要的问题:为了使我们能够用 σ(wᵀx) 来估计 p(y|x) ,应该满足的关于数据的潜在假设是什么?答案可在【1】中找到:类后验分布 p(y|x) 可写成 σ(wᵀT(x)当且仅当类条件分布( p(x|y+) 和 p(x|y-))来自同一个具有充分统计量的指数族 T(x)。例如,一个常见的情况是当类条件分布都是正态分布,我们想要区分它们;在这种情况下,充分统计量是【x,x】,这导致二次判别式。如果我们想要一个线性判别式,正态分布的协方差矩阵应该是相同的,这导致二次项的消除(参见【2】的 4.84)。因此,假设我们有一个给我们带来具有相同协方差矩阵的正态类条件分布的特征提取器, σ(wᵀx) 是 p(y|x)的一个好的估计量。
现在,让我们假设输入(或从输入中提取的特征,例如通过使用神经网络(参见[3]))具有正态类条件分布,并且我们正在处理一个不平衡数据集,其中多数类几乎在任何地方都具有高概率,甚至在少数类的区域中也是如此(与图 2 完全一样)。).在这种情况下,类别条件句的协方差矩阵不可能相同,并且固有地,多数类别的规模更大。此外,我们不能通过转换到核空间来克服这个问题,因为无论转换是什么,多数阶级都出现在少数阶级的区域中,此外还有其他一些少数阶级不存在的区域。因此,线性函数的逻辑 sigmoid 不是后验分布的良好估计。
平衡有什么帮助?
假设我们在选择逻辑回归模型时非常激进,尽管它是不平衡数据后验分布的弱学习器,但我们想使用它。在这种情况下,平衡使我们能够构建一个核空间,在其中我们对类条件分布具有相同的尺度,并且使逻辑回归成为一个合理的候选。这样一来,平衡就是一种躲闪:与其估计 p(y|x) (由于p(y)**的不均匀性,这是不可能的),不如先在平衡设置下估计 p'(y|x) ,然后重构 p(y|x)。因此,当我们平衡数据集时,我们破坏了真正的边际分布,更准确地说,我们破坏了它的本性。
假设我们已经正确预测了p’(y | x),在通过将 p(y) 变为p’(y)进行重采样并构建平衡数据集之后,其中p’(y+)和p’(y-)都是 0.5。现在是重建 p(y|x) 的时候了,这可以通过下面的方法来完成:
其中我们在第二个方程中使用了 p'(x|y)=p(x|y) (因为我们刚刚改变了 y 和 p(x|y) 的边际分布与 p'(x|y) 相同)。因此,具有p’(y | x)导致具有 p(y|x) 的缩放版本,这足以做出决策。
现在让我来讨论另外两个有趣的直觉,在第一个直觉中,我关注了少数群体的重要性,在第二个直觉中,我提出了我们如何用助推来模拟这个问题。
扩展交叉熵
考虑图 2,如果数据集是不平衡的,则逻辑斯蒂模型不能很好地预测后验分布,并且存在许多坏的局部最优,其中,只有少数高估了少数类的后验分布,而大多数低估了它。相反,通常,少数类的重要性更高,我们宁愿高估它的概率而不是低估它。通过增加来自少数类的样本的权重,我们将损失函数改变为以下形式并扩展交叉熵:
其中 ECE 是扩展的交叉熵,α表示 0 和 1 之间的样本权重,对于少数类较大,对于多数类较小(例如α₊=0.8 和α₋=0.2,其和为 1)。以下两个数字比较了α₊=0.5 和α₊=0.8.的 ECE 很明显,在图 4 中,我们对 p(y+|x) 低估的惩罚远远大于对其高估的惩罚。
图三。α₊=0.5 欧洲经委会(无余额)。
图 4。α₊=0.8.欧洲经委会高估比低估受到的惩罚要少。
同样将 ECE 相对于 q 的导数设置为零,我们可以发现 ECE 的极小值为:
即等于 p(y+|x) 如果α₊=0.5.这个等式也给了我们一种从 q(y|x) 重建 p(y|x) 的方法,其中 q 是在平衡数据集上估计的。
平衡和增压
逻辑回归是不平衡数据的弱分类器,但是正如我们所知,将一些弱分类器组合起来可以得到一个强分类器。Boosting 是通过在每一步增加误分类样本的权重来顺序集成弱学习者的方法之一。平衡数据集就像考虑一个两阶段 AdaBoost,其中第一个弱分类器只学习多数类,第二个在 50–50 平衡数据集上训练,然后它被用作主分类器。
笔记
- 阿林达姆·班纳吉。逻辑模型分析:指数家庭联系和在线绩效。2007 年 SIAM 数据挖掘国际会议论文集。**
- 克里斯托弗·m·毕晓普模式识别和机器学习。斯普林格,2006 年。
- 考虑到深度分类器使用逻辑 sigmoid 或 softmax 函数来估计提取特征空间上的 p(y|x) ,这种讨论的重要性更加明显。事实上,深度模型首先将数据转换到输出层之前的层中的特征空间,然后使用与逻辑回归相同的方法来估计后验分布。因此,如果有任何重要的假设,深度模型应该能够建立一个拥有这些假设的特征空间。
平衡您的数据…
原文:https://towardsdatascience.com/balancing-your-data-bd97123a7aaf?source=collection_archive---------46-----------------------
罗伯特·阿纳奇在 Unsplash 上的照片
‘如果你被问题的大小压垮了,把它分成小块……’
机器学习中的类不平衡是一个重要的问题,也是处理数据集时最受关注的问题之一。具有类不平衡的数据集往往更具欺骗性,如果处理不当,其结果可能会导致错误的决策。
最近,我碰巧在一个具有显著的类不平衡的数据集中工作。由于我不是数据生成技术的狂热爱好者,并且由于不平衡严重,dint 希望使用分层 K-fold 之类的技术,所以我使用了一种比传统技术好不了多少的技术来帮助模型学习数据。也许我使用这个技术有点晚了,但我想我会在这里分享它,以便它对某人来说是新的和有用的。
import pandas as pdtrain=pd.read_csv('/Desktop/Files/train_data.csv')
print(train['Top-up Month'].value_counts())No Top-up Service 106677
> 48 Months 8366
36-48 Months 3656
24-30 Months 3492
30-36 Months 3062
18-24 Months 2368
12-18 Months 1034
Name: Top-up Month, dtype: int64
以上是来自训练数据的因变量的值计数。从上面可以清楚地看出,在“无充值服务”类别和其他类别之间存在严重的类别不平衡。
方法…
因此,我在这里采用的方法是将多数类数据分成大小为“n”的小折叠。每个数据块(文件夹)将具有与多数类相关“k”个数据点。所有其他次要类别的数据点被组合在一起(“m”)
def chunks(df,folds):
df_no_topup=df.loc[df['Top-up Month']==0]
df_topup=df.loc[df['Top-up Month']==1]
recs_no_topup=int(df.loc[df['Top-up Month']==0].shape[0]/folds)
start_no_topup=0
stop_no_topup=recs_no_topup
list_df=[]
for fold in range(0,folds):
fold_n=df_no_topup.iloc[start_no_topup:stop_no_topup,:]
start_no_topup=stop_no_topup
stop_no_topup=start_no_topup+recs_no_topup
df=pd.concat([fold_n,df_topup],axis=0)
list_df.append(df)
return list_df
上面的代码片段将主类数据分成多个文件夹,每个文件夹包含相同数量的数据点。然后,多数类数据的第一个 fold(在上面的代码中称为 fold_n)与次要类(df_topup)的所有数据连接在一起。这发生在一个循环中,并且该循环将继续,直到等于折叠“n”的大小。可以看出,每次,多数类数据的新块都与次要类的相同(完整)数据连接,从而允许模型在训练阶段训练相等比例的数据。
Major class initially - 106677
Fold size(n) - 5
Major class data(k) per fold=106677/5 - 21335
Minor class(all minor classes combined) - 21978
Total data per fold(major+minor) - 43313
下面的代码片段可以验证这一点。
list_data=chunks(df_train_main,5)
list_data_shape=[df.shape for df in list_data]
print(list_data_shape)[(43313, 6), (43313, 6), (43313, 6), (43313, 6), (43313, 6)]
现在可以看到,一个具有严重类别不平衡问题的大数据集已被分成 5 个类别不平衡程度较轻的小数据集(因为一些次要类别与主要类别相比仍然不平衡)
然而,以下是我从上述方法中认识到的两个问题:
- 添加到每个文件夹的多数类数据的分布。由于我们只是将整个主要类别数据划分为多个折叠(n ),每个折叠大小相等(k ),因此任何折叠中主要类别数据的分布可能不是训练数据中主要类别总体数据的样本表示。
- 在需要解决的所有问题中,类别(12-18 个月)和主要类别(“无充值服务”)之间仍然存在不平衡。但是在二进制类的情况下,这种方法效果更好。
然后将这些折叠的数据传递给一个模型,以使用更少的不平衡数据来训练该模型。这是一种通用方法,除了结构化数据之外,它甚至可以应用于图像等非结构化数据。我个人在一次 Kaggle 比赛中使用了同样的方法进行图像分类,并获得了更高的准确率。
尝试一下,并告诉我们您对该方法的宝贵想法……
Bamboolib:你见过的最有用的 Python 库之一
原文:https://towardsdatascience.com/bamboolib-one-of-the-most-useful-python-libraries-you-have-ever-seen-6ce331685bb7?source=collection_archive---------3-----------------------
大蟒
这是我对这个很酷的 Python 库的看法,以及为什么你应该试一试
照片由来自 Pexels 的安德里亚·皮亚卡迪奥拍摄
我喜欢写关于 Python 库的文章。如果你读过我的博客,你可能知道我写过关于多个图书馆的文章。在写之前,我测试了一些 Python 库,检查了它们最显著的特性,如果我喜欢,我会写一些关于它们的内容。通常,我会尝试在同一个博客中包含几个库,以使它更具知识性。然而,偶尔,我发现那些非常酷的图书馆应该拥有自己的博客。Bamboolib 就是这样!
Bamboolib 是那种让你思考的库:我以前怎么不知道呢?是的,这听起来有点戏剧性,但是相信我,你会惊讶的。Bamboolib 可以为需要一段时间才能编写的东西构建代码,比如复杂的 group by 子句。让我们直接开始吧,因为我很高兴向你们展示它是如何工作的。
bamboo lib——适合初学者和专业人士
Bamboolib 自称可以让任何人不用成为程序员或搜索语法就可以用 Python 进行数据分析。根据我的测试,这是真的!它要求零编码技能。然而,我认为它对于时间紧迫的人或者不想为简单的任务键入长代码的人来说是非常方便的。我也可以看到学习 Python 的人如何利用它。例如,如果你想学习如何用 Python 做一些事情,你可以使用 Bamboolib,检查它生成的代码,并从中学习。
不管是哪种方式,我们来探讨一下你如何使用它,你可以决定它是否对你有帮助。我们开始吧!
装置
安装 Bamboolib 很简单。我在这个博客中写过不同的安装方法,展示了如何在安装 Bamboolib 之前创建一个环境。如果你没有心情创建一个新的环境,你可以在你的终端中输入pip install — upgrade bamboolib — user
,它会工作得很好。现在你可以通过输入import bamboolib as bam
将它导入到 Jupyter 笔记本中,我们就可以开始了。
现在,我们需要一个数据集。我将使用所有视频游戏销售数据集,因为它看起来很有趣,但你可以使用任何你喜欢的东西。一旦你下载了你的数据集,让我们导入它,这时我们就可以开始使用 Bamboolib 了。
第一步
还记得我说过 Bamboolib 不需要编码吗?我是认真的。要将数据集导入到您的 Jupyter 笔记本中,请键入bam
,它将向您显示一个用户界面,您可以通过三次点击来导入数据集。
Type bam > Read CSV file > Navigate to your file > Choose the file name > Open CSV file
作者 GIF
注意 Bamboolib 导入了 Pandas 并为您创建了代码。是的,在整个项目中都会这样。
数据准备
将字符串更改为日期时间
您加载了数据,并意识到日期列是一个字符串。然后,单击列类型(列名旁边的小字母),选择新的数据类型和格式,如果需要,选择一个新名称,然后单击执行。
你是否看到单元格中也添加了更多的代码?
作者 GIF
另外,user_review
列似乎是一个对象。让我们通过创建一个整数来解决这个问题。
作者 GIF
还记得我说过列名旁边的小字母是列数据类型吗?如果你看一下user_review
列名旁边的字母,你会看到一个f
,而不是整数中的i
,尽管我把数据类型改成了整数。这是因为 Bamboolib 将数据类型理解为 float,所以它没有抛出错误,而是为您修复了错误。
用不同的数据类型和名称创建新列
如果您不需要更改列的数据类型和名称,而是需要一个具有不同数据类型和名称的新列,该怎么办呢?只需单击列数据类型,选择新的格式和名称,然后单击执行。您将立即看到数据集中的新列。
在下图中,我选择了meta_score
列,将数据类型改为 float,选择了一个新名称,新列就创建好了。
作者 GIF
删除列
如果您意识到不需要列,只需在搜索转换框中搜索 drop,选择 drop,选择要删除的列,然后单击执行。
作者 GIF
重命名列
现在您需要重命名一个列,这再简单不过了。只需搜索 rename,选择要重命名的列,写下新的列名,然后单击 execute。您可以选择任意多的列。
作者 GIF
拆分字符串
假设您需要将包含人名的列拆分为两列,一列包含名字,另一列包含姓氏。你可以很容易做到这一点。出于演示的目的,我将游戏名称拆分,这实际上没有意义,但您可以看到它是如何工作的。
只需在搜索转换框中键入 split,选择要拆分的列、分隔符和最大列数。嘣!
作者 GIF
因为这只是一个演示,所以让我们删除额外的列。搜索删除,选择要删除的列,然后在执行中单击。
作者 GIF
选择列
然后,我们可以选择只显示几列。在这里,我将选择游戏名称、平台和分数。只需在搜索转换中键入 select,选择您想要选择的列并执行。
作者 GIF
在这些步骤的最后,Bamboolib 创建了以下代码,即使某人没有安装 Bamboolib,也可以使用这些代码。很酷,对吧?
作者图片
数据转换
过滤数据
如果您想要过滤您的数据集或使用过滤的信息创建一个新的数据集,您可以在搜索转换中搜索过滤器,选择您想要过滤的内容,决定您是否想要创建一个新的数据集,然后单击执行。就这么简单!
作者 GIF
合并数据
如果需要合并两个数据集,只需搜索 merge,选择要合并的两个数据集、连接类型,选择要用于合并数据集的键列,然后单击“执行”。您可以创建一个新的数据集或只编辑当前的数据集。
作者 GIF
提取日期时间属性
如果您想从日期列中提取一个字符串,比如星期几和月份,您知道代码吗,或者您必须搜索它吗?嗯,有了 Bamboolib,两者都不需要。只需搜索 extract datatime 属性,选择 date 列,然后选择要提取的内容。
有多种选择供你选择。我必须承认,我不知道如何做到这一点,甚至不知道用熊猫做这件事是否可能…我只是学到了一些新东西。
作者 GIF
分组依据
使用分组是你可以对熊猫做的最有价值的事情之一。然而,它有时会变得非常复杂。幸运的是,Bamboolib 可以让分组变得非常直观和简单。搜索“分组依据”在“搜索转换”框中,选择要分组的列,然后选择要查看的计算。
在这个例子中,我希望看到每个平台的游戏的计数和平均分数。这样做,我才知道 PlayStation 4 在所有平台中平均得分最低。
作者 GIF
数据可视化
Bamboolib 是创建快速数据可视化的伟大工具。例如,要创建直方图,单击 create plot,选择图形类型、x 轴,就差不多了。你刚刚用四次点击创建了一个漂亮的图表。
作者 GIF
或者您可以创建一个箱形图。过程非常相似。很好很容易!
有许多其他类型的图表可供探索,但 all games 数据集并不是创建图表的最佳选择。不过,您可以用其他数据集来测试这个特性。有很多值得探索的地方。
数据探索
Bamboolib 让数据探索变得超级简单。只需点击一下,您就可以从您的数据集中获得见解。为此,单击 Explore DataFrame,它将返回诸如平均值、中值、四分位数、标准偏差、观察值数量、缺失值、正面和负面观察值数量等信息。它还创建图表,以便您可以了解数据分布。
如果数据集中有 DateTime 数据类型,它还可以创建图表来显示数据在一段时间内的变化情况。因此,您不必浪费时间创建单独的图表来理解数据集,而是可以使用此功能来深入了解数据集。
作者 GIF
最后的想法
唷!我现在对给予这个图书馆应有的关注感到满意。是的,我知道这不是第一个关于 Bamboolib 的博客,但是我想谈谈我的看法。还有很多要探索的。Bamboolib 有很大的潜力来改变我们分析数据和学习的方式。我使用熊猫已经有几年了,我学到了一些我们可以使用 Bamboolib 做的新东西。感谢阅读,下一篇博客再见。
你可能也会喜欢…
5 个你不知道但应该知道的 Python 库 4 个你应该知道的很酷的 Python 库4 个你现在就应该尝试的神奇的 Python 库
银行客户流失的潮汐模型——第一部分模型开发
原文:https://towardsdatascience.com/bank-customer-churn-with-tidymodels-part-1-model-development-cdec4eeb131c?source=collection_archive---------21-----------------------
利用潮汐模型探索不平衡分类
假设您是一家大型跨国银行的数据科学家,首席客户官找到您,希望开发一种预测客户流失的方法。您开发了一个包含 10,000 个客户的快照数据集,客户的类别不平衡度为 1:4,这有利于客户不离开来训练这样的二元分类模型。为了帮助模型开发,您决定研究各种可能有助于解决类别不平衡的采样技术。
Jorge Fernández Salas 在 Unsplash 上拍摄的照片
这个由多个部分组成的系列将涵盖开发和解释模型过程中的以下主题,重点是将模型输出转化为业务成果,并与高级风险承担者进行沟通。
- 第 1 部分不平衡分类的模型开发
- 第二部分阈值分析和成本影响
- 第 3 部分用 DALEXtra & Tidymodels 解释 ML
- 第 4 部分使用生存分析的替代方法
最终目标是创建一个模型,使银行能够锁定可能被归类为客户流失的当前客户,并应用一些干预措施来防止客户流失。干预是有代价的,所以我们将寻求平衡假阴性率和假阳性率。我们将在第 2 部分用可能是包开发一个成本函数和阈值分析。
第 3 部分将通过使用 DALEX/DALEXtra XAI 套餐,重点了解客户流失更为突出的可变空间,并使我们能够在本地和全球层面了解导致客户流失的主要因素。
在第 4 部分中,我们将采用不同的方法,将生存分析方法应用于该数据集,因为它经过了适当的审查,并利用最近在 tidymodels 中发布的生存分析功能,突出了事件发生时间(任期)和结果。
加载包
library(tidymodels)
library(themis) **#Recipe functions to deal with class imbalances**
library(tidyposterior) **#Bayesian Resampling Comparisons**
library(baguette) **#Bagging Model Specifications**
library(corrr) **#Correlation Plots**
library(readr) **#Read .csv Files**
library(magrittr) **#Pipe Operators**
library(stringr) **#String Manipulation**
library(forcats) **#Handling Factors**
library(skimr) **#Quick Statistical EDA**
library(patchwork) **#Create ggplot Patchworks**
library(GGally) **#Pair Plots**options(yardstick.event_first = FALSE) **#Evaluate second factor level as factor of interest for yardstick metrics**
加载数据
数据取自https://www.kaggle.com/shivan118/churn-modeling-dataset(LicenseCC0:Public Domain)并加载如下。
train <- read_csv("Churn_Modelling.csv") %>%
select(-c(Surname, RowNumber, CustomerId))
探索性数据分析
我喜欢 skimr 包快速提供所有数据集变量的摘要。
skim(train)
从 Skim 输出(图片由作者提供)
我们的目标变量 Exited 在两种可能的结果之间具有大约 4:1 的比率,其中 Exited = 1 表示客户流失。为了形象化这一点,我们采用下面的自定义函数。
viz_by_dtype <- function (x,y) {
title <- str_replace_all(y,"_"," ") %>%
str_to_title()
if ("factor" %in% class(x)) {
ggplot(train, aes(x, fill = x)) +
geom_bar() +
theme_minimal() +
theme(legend.position = "none",
axis.text.x = element_text(angle = 45, hjust = 1),
axis.text = element_text(size = 8)) +
scale_fill_viridis_d()+
labs(title = title, y = "", x = "")
}
else if ("numeric" %in% class(x)) {
ggplot(train, aes(x)) +
geom_histogram() +
theme_minimal() +
theme(legend.position = "none") +
scale_fill_viridis_d() +
labs(title = title, y = "", x = "")
}
else if ("integer" %in% class(x)) {
ggplot(train, aes(x)) +
geom_histogram() +
theme_minimal() +
theme(legend.position = "none") +
scale_fill_viridis_d()+
labs(title = title, y = "", x = "")
}
else if ("character" %in% class(x)) {
ggplot(train, aes(x, fill = x)) +
geom_bar() +
theme_minimal() +
scale_fill_viridis_d() +
theme(legend.position = "none",
axis.text.x = element_text(angle = 45, hjust = 1),
axis.text = element_text(size = 8)) +
labs(title = title, y ="", x= "")
}
}
variable_list <- colnames(train) %>% as.list()
variable_plot <- map2(train, variable_list, viz_by_dtype) %>%
wrap_plots(
ncol = 3,
heights = 150,
widths = 150)
ggsave("eda.png", dpi = 600)
viz_by_dtype 函数的输出(图片由作者提供)
从上面我们可以更好地理解连续变量的分布和离散变量的计数。
- 信用评分大致呈正态分布
- 地理分布在三个国家,以法国为主
- 性别几乎是均等的
- 年龄近似右偏正态分布
- 任期没有明显的分布,大多数客户的任期在 2-9 年之间
- 余额通常分配给大量余额为零的客户
- 大多数客户要么有 1 种,要么有 2 种产品
- 有信用卡表明 70%的客户有信用卡
- 活跃会员显示 51.5%的客户是活跃用户
- 估计工资没有明显的分布
二元数值分析
现在我们将使用 GGally::ggpairs()来了解数字变量之间是否有任何关系
ggpairs(train %>%
select(-c(HasCrCard,IsActiveMember,NumOfProducts, Gender, Geography)) %>%
drop_na() %>%
mutate(Exited = if_else(Exited == 1, "Y","N")), ggplot2::aes(color = Exited, alpha = 0.3)) +
scale_fill_viridis_d(end = 0.8, aesthetics = c("color", "fill")) +
theme_minimal() +
labs(title = "Numeric Bivariate Analysis of Customer Churn Data")
按目标排列的数值对图(按作者排列的图片)
上面唯一值得注意的是,有过搅动的客户向右移动,这表明年纪大的客户离开的可能性更大。
分类变量分析
下一步是确定分类变量和目标之间是否有任何关系。
下文描述了汇总数据框架的创建,该数据框架计算每个分类变量和目标变量的平均值和 95%置信区间。
train %>%
mutate(Exited = if_else(Exited == 1, "Y", "N"),
HasCrCard = if_else(HasCrCard == 1, "Y", "N"),
IsActiveMember = if_else(IsActiveMember == 1, "Y", "N"),
NumOfProducts = as.character(NumOfProducts)) %>%
select(Exited,where(is.character)) %>%
drop_na() %>%
mutate(Exited = if_else(Exited == "Y",1,0)) %>%
pivot_longer(2:6, names_to = "Variables", values_to = "Values") %>%
group_by(Variables, Values) %>%
summarise(mean = mean(Exited),
conf_int = 1.96*sd(Exited)/sqrt(n())) %>%
ggplot(aes(x=Values, y=mean, color=Values)) +
geom_point() +
geom_errorbar(aes(ymin = mean - conf_int, ymax = mean + conf_int), width = 0.1) +
theme_minimal() +
theme(legend.position = "none",
axis.title.x = element_blank(),
axis.title.y = element_blank()) +
scale_color_viridis_d(aesthetics = c("color", "fill"), end = 0.8) +
facet_wrap(~Variables, scales = 'free') +
labs(title = 'Categorical Variable Analysis', subtitle = 'With 95% Confidence Intervals')
95%置信区间的分类变量分析(图片由作者提供)
值得注意的是,我们看到性别、非活跃会员、产品数量和地理位置显示出明显不同的流失倾向。相反,客户是否有信用卡对客户流失的可能性没有显著影响。考虑到阶级的不平衡,这一点应该有所保留。
模型开发
数据分割—r 样本
使用 rsample::initial_split(),我们指定了一个 3:1 的训练数据拆分。
set.seed(246)
cust_split <- initial_split(train, prop = 0.75, strata = Exited)
型号规格— Parnsip &长方形
我们将使用 parsnip 和 baguette 包(针对 bag_trees)将模型规范的范围限制为那些基于树的模型,这些模型的复杂性在不断增加。每个模型指定其各自的超参数设置为 tune(),用于下一步筛选。
dt_cust <-
decision_tree(cost_complexity = tune(), tree_depth = tune(), min_n = tune()) %>%
set_engine("rpart") %>%
set_mode("classification")rf_cust <-
rand_forest(mtry = tune(), trees = tune(), min_n = tune()) %>%
set_engine("ranger", importance = "impurity") %>%
set_mode("classification")xgboost_cust <-
boost_tree(mtry = tune(), trees = tune(), min_n = tune(), tree_depth = tune(), learn_rate = tune(), loss_reduction = tune(), sample_size = tune()) %>%
set_engine("xgboost") %>%
set_mode("classification")bagged_cust <-
bag_tree(cost_complexity = tune(), tree_depth = tune(), min_n = tune()) %>%
set_engine("rpart") %>%
set_mode("classification")
特征工程—配方
接下来,我们将使用 recipes 包指定特征工程步骤。我们将利用这一阶段开发 10 个配方,每个配方都有不同的采样技术来处理类别不平衡。 themis 包提供了方便不同取样技术的配方步骤。
- SMOTE——合成少数过采样技术
- ROSE——随机过采样技术
- 边界合成少数过采样技术
- 向上采样-将重复的少数类数据添加到与多数类的指定比率中
- ADASYN——自适应合成过采样
- TOMEK-删除多数类中的 TOMEK 链接
- NEARMISS 通过欠采样移除多数类实例
- 无采样—无采样程序
- 平滑缩减采样-生成合成少数实例并移除多数实例
- ROSE-下采样-过采样少数实例,下采样多数实例
recipe_template <-
recipe(Exited ~., data = training(cust_split)) %>%
step_integer(HasCrCard, IsActiveMember, zero_based = T) %>%
step_integer(NumOfProducts) %>%
step_mutate(**SalaryBalanceRatio = EstimatedSalary/Balance,
CreditScoreAgeRatio = CreditScore/Age,
TenureAgeRatio = Tenure/Age,
SalaryBalanceRatio = if_else(is.infinite(SalaryBalanceRatio),0,SalaryBalanceRatio)**) %>%
step_scale(all_numeric_predictors(), -c(HasCrCard, Age, IsActiveMember, NumOfProducts)) %>%
step_dummy(all_nominal_predictors()) %>%
**step_samplingmethod**(Exited) **#Change or Add Sampling Steps Here as Necessary**
上面我们已经设计了附加功能,采用不同连续变量的商。
相关图— corrr
我们可视化整个训练数据集的相关图,使用没有应用采样技术的配方。
cust_train <- recipe_8 %>% prep() %>% bake(new_data = NULL)
cust_test <- recipe_8 %>% prep() %>% bake(testing(cust_split))cust_train %>%
bind_rows(cust_test) %>%
mutate(Exited = as.numeric(Exited)) %>%
correlate() %>%
rplot(print_cor = T, .order = "alphabet") +
scale_color_gradient2(low = 'orange', high = 'light blue') +
theme(axis.text.x = element_text(angle = 90)) +
labs(title = "Correlation Plot for Trained Dataset")
训练数据集的相关图(图片由作者提供)
在上面,年龄和我们生成的衍生比率之间的负相关并不令人惊讶。Exited 与年龄正相关,与 credit score 比率稍负相关,与 SalaryBalanceRatio 比率稍正相关。
工作流图—工作流集
使用 workflowsets 软件包,我们可以在 parsnip 和 recipes 组合之间生成 40 个工作流程的列表,并为每个工作流程筛选 20 个超参数组合。我们使用 rsample::vfold_cv()创建一个 5 重交叉验证对象,使用 strata kwarg to Exited,这样每个折叠都具有目标变量水平的一致比率。
recipe_list <-
list(SMOTE = recipe_1, ROSE = recipe_2, BSMOTE = recipe_3, UPSAMPLE = recipe_4, ADASYN = recipe_5, TOMEK=recipe_6, NEARMISS = recipe_7, NOSAMPLING = recipe_8, SMOTEDOWNSAMPLE= recipe_9, ROSEDOWNSAMPLE = recipe_10)model_list <-
list(Decision_Tree = dt_cust, Boosted_Trees = xgboost_cust, Random_Forest = rf_cust, Bagged_Trees = bagged_cust)wf_set <-
workflow_set(preproc = recipe_list, models = model_list, cross = T)set.seed(246)
train_resamples <-
vfold_cv(training(cust_split), v = 5, strata = Exited)class_metric <- metric_set(accuracy, f_meas, j_index, kap, precision, sensitivity, specificity, roc_auc, mcc, pr_auc)doParallel::registerDoParallel(cores = 12)
wf_sample_exp <-
wf_set %>%
workflow_map(resamples = train_resamples,
verbose = TRUE,
metrics = class_metric,
seed = 246)
我们使用 parsnip::metric_set()函数创建一组定制的评估指标。这些自定义指标与 wf_set 对象一起传递给 workflow_map,以筛选所有 40 个工作流并输出每个工作流的所有指标计算。现在可以分析产生的 workflow_set 对象 wf_sample_exp,并将其用于模型比较。
这在计算上相当费力,所以我建议启动所有可用的内核来缓解这一问题。
collect_metrics(wf_sample_exp) %>%
separate(wflow_id, into = c("Recipe", "Model_Type"), sep = "_", remove = F, extra = "merge") %>%
group_by(.metric) %>%
select(-.config) %>%
distinct() %>%
group_by(.metric, wflow_id) %>%
filter(mean == max(mean)) %>%
group_by(.metric) %>%
mutate(Workflow_Rank = row_number(-mean),
.metric = str_to_upper(.metric)) %>%
arrange(Workflow_Rank) %>%
ggplot(aes(x=Workflow_Rank, y = mean, color = Model_Type)) +
geom_point(aes(shape = Recipe)) +
scale_shape_manual(values = 1:n_distinct(recipe_list)) +
geom_errorbar(aes(ymin = mean-std_err, ymax = mean+std_err)) +
theme_minimal() +
scale_color_viridis_d() +
labs(title = "Performance Comparison of Workflows", x = "Workflow Rank", y="Error Metric", color = "Model Types", shape = "Recipes") +
facet_wrap(~.metric,scales = 'free_y',ncol = 4)
通过各种分类指标比较所有工作流。(图片由作者提供)
以上内容的目的是展示一个分类指标的示例,人们可能会看到一个不平衡的数据集。我们想要一个能充分区分不同类别的模型,但考虑到我们的特殊问题,我们需要尽量减少假阴性(客户流失,但预测会不同)。第 2 部分讨论了一个成本函数,以找到干预成本和阶级分化之间的平衡。
鉴于类别不平衡,ROC AUC 和准确性不是合适的指标。 我们考虑精确召回的 AUC、KAP、J 指数、Mathews 相关系数和特异性。考虑到这一点,UPSAMPLE_Boosted_Trees 是一个强有力的候选,在所有这些指标上都有良好的结果。
贝叶斯模型比较—tidy poster
关注 J 指数,我们可以使用 tidyposterior 比较重采样后验分布。tidyposterior::perf_mod()采用包含 workflow_map 结果的 wf_sample_exp 对象,完成重采样的贝叶斯比较,并生成感兴趣的度量平均值的后验分布。注意:workflow_set 对象必须计算目标度量,否则将不起作用。
jindex_model_eval <-
perf_mod(wf_sample_exp, metric = "j_index", iter = 5000)
jindex_model_eval %>%
tidy() %>%
mutate(model = fct_inorder(model)) %>%
separate(model, into = c("Recipe", "Model_Type"), sep = "_", remove = F, extra = "merge") %>%
ggplot(aes(x=posterior, fill = Model_Type)) +
geom_density(aes(alpha = 0.7)) +
theme_minimal() +
scale_fill_viridis_d(end = 0.8) +
facet_wrap(~Recipe, nrow = 10) +
labs(title = "Comparison of Posterior Distributions of Model Recipe Combinations",
x = expression(paste("Posterior for Mean J Index")),
y = "")
工作流程的比较和取样程序对 J 指数的影响。(图片由作者提供)
上面有很多内容需要解释,但简而言之,它展示了处理类不平衡的采样过程的影响以及对 J 指数的影响。这可以针对任何度量来完成,并且我认为这是探索不同的上采样和下采样过程的影响的有用练习。我们注意到,与袋装采油树方法一样,助推采油树通常表现良好,这都取决于取样程序。
结束语
我们已经展示了一个具有 4:1 不平衡数据集的二元分类器的模型开发过程。我们性能最好的工作流以 XGBoost 模型为特色,该模型带有一个上采样过程来平衡类的比率。在第 2 部分中,我们将拟合模型,并使用 probably 包完成决策阈值分析,并开发两个场景——要么改变决策阈值以最小化流失和干预的成本,要么实现更好的阶级区分。第 2 部分将重点关注将模型输出转化为业务涉众,并使他们能够围绕客户流失的成本和风险做出明智的决策。
谢谢你的阅读,请留意后面的部分。我希望你能像我喜欢写作一样喜欢阅读这篇文章。如果你不是媒介会员,使用下面我的推荐链接,定期从我和其他优秀的媒介作者那里获得新出版物的更新。
https://mmgillin.medium.com/membership
条形图:备选方案和特定类型
原文:https://towardsdatascience.com/bar-plots-alternatives-specific-types-9d10ef250e5?source=collection_archive---------15-----------------------
何时以及是否使用它们
来自 Unsplash
当显示整体中不同元素的比例时,条形图似乎是最佳选择。有没有其他功能与他们相似的图表?让我们使用 Kaggle 的一个与酒吧相关的数据集来探究这个问题— 世界各地的酒精消费量🤩🍷特别是,我们将关注饮料消费量排名前十的国家。此外,我们将快速了解还有哪些其他类型的条形图,以及何时可以使用它们。
让我们看看熊猫的数据:
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as snsdf = pd.read_csv('drinks.csv')
print(df.head(3))**Output:** country beer_servings spirit_servings wine_servings \
0 Albania 89 132 54
1 Algeria 25 0 14
2 Andorra 245 138 312
total_litres_of_pure_alcohol
0 4.9
1 0.7
2 12.4
并提取必要的信息:
top10_spirit = df.sort_values('spirit_servings',
ascending=False)[:10]\
.reset_index(drop=True)\
[['country', 'spirit_servings']]
圆形分格统计图表
饼图或其版本的环形图(中心区域被切掉)是条形图最常见的替代方案。然而,如果要在它们和条形地块之间做出选择,第二个似乎是更安全的选择。事实上,饼状图是基于角度而不是长度,通常更难阅读和从中提取见解。如果我们在一个饼图中有许多类别和/或几乎相等比例的类别,即使试图找到最大/最小的类别也是相当复杂的,更不用说按值排序了:
fig, ax = plt.subplots(figsize=(16,8))
fig.tight_layout(pad=4)# Creating a case-specific function to avoid code repetition
# (will be used for comparing with 2 more plot types)
def plot_hor_bar_2():
ax = sns.barplot(x='spirit_servings', y='country',
data=top10_spirit, color='slateblue')
plt.title('TOP10 countries by spirit consumption', fontsize=28)
plt.xlabel('Servings per person', fontsize=23)
plt.xticks(fontsize=20)
plt.ylabel(None)
plt.yticks(fontsize=20)
sns.despine(left=True)
ax.grid(False)
ax.tick_params(bottom=True, left=False)
return Noneplt.subplot(1,2,1)
plot_hor_bar_2()plt.subplot(1,2,2)
plt.pie(top10_spirit['spirit_servings'],
labels=top10_spirit['country'],
startangle=90, autopct='%1.1f%%')
plt.title('TOP10 countries by spirit consumption', fontsize=28)
matplotlib.rcParams['font.size']=18
plt.show()
作者图片
即使我们只有 10 个国家出现在这两张图表上(2010 年饮酒量排名前 10 的国家),我们也无法从饼状图中获得太多信息。事实上,这些扇区看起来彼此非常相似,即使将startangle
参数赋值为 0 并添加%标签也没有真正提高第二个图表的可读性。
这些图表的另一个缺点是,我们必须为每个类别使用不同的颜色,而正如我们前面所讨论的,在条形图上,对所有的条形图使用相同的颜色就足够了(如果我们不想特别强调什么)。这意味着在饼图上,每个类别都有两个特征:颜色和角度,这会产生冗余的视觉信息。如果我们有很多类别,因此有很多颜色,那么我们的饼状图就会变得铺天盖地。同样,上图只有 10 个元素,看起来已经严重超载了。
最后,在几个饼图的情况下,每个饼图代表一个以不同比例细分为相同元素的类别(类似于分组条形图),几乎不可能跟踪所有元素的趋势或找出数据中任何有意义的模式。
基于以上所述,条形图应优先于饼图。
树形图
像条形图和饼图一样,树状图显示了所有数据的组成。它将分层数据显示为一组嵌套的矩形,每个矩形的面积与相应数据的值成比例。为了定制一个树形图,我们可以为矩形分配一个颜色列表,为标签分配颜色和字体大小,以及其他一些参数。
让我们复制上面的条形图,这次将它与相应的树形图进行比较:
import squarify# Renaming Russian Federation into Russia to avoid too long lables
top10_spirit.at[3, 'country'] = 'Russia'fig, ax = plt.subplots(figsize=(16,8))
fig.tight_layout(pad=4)plt.subplot(1,2,1)
plot_hor_bar_2()plt.subplot(1,2,2)
cmap = matplotlib.cm.tab20
colors = []
for i in range(len(top10_spirit.index)):
colors.append(cmap(i))
squarify.plot(sizes=top10_spirit['spirit_servings'],
label=top10_spirit['country'],
color=colors,
text_kwargs={'fontsize': 16})
plt.title('TOP10 countries by spirit consumption', fontsize=28)
plt.axis('off')
plt.show()
作者图片
我们可以确认,树形图看起来比之前创建的饼图更有洞察力:感知区域肯定比感知角度容易得多。我们没有在树形图中添加值或百分比;然而,仍然有可能从定性的角度来估计前 10 名中饮酒最多和最少的国家(我的国家和海地并列第三😔).不过,在一个可视化中使用大量颜色的问题也存在于树形图中。
茎图
stem 图是一个很好的替代条形图的方法,它有许多条,或者有相似长度的条。它最大化了图表的数据-油墨比率,使其更具可读性。要创建一个水平茎图,我们可以使用stem()
或vlines()
功能,创建一个垂直茎图,只有hlines()
与plot()
结合使用。这些函数有许多参数需要调整,以改善结果图的外观。在这篇文章中,你可以找到更多关于如何定制茎图和树状图的信息。
fig, ax = plt.subplots(figsize=(16,8))
fig.tight_layout(pad=4)plt.subplot(1,2,1)
plot_hor_bar_2()top_sorted = top10_spirit.sort_values('spirit_servings',
ascending=True)\
.set_index('country')plt.subplot(1,2,2)
plt.hlines(y=top_sorted.index, xmin=0, xmax=top_sorted,
color='slateblue')
plt.plot(top_sorted, top_sorted.index,
'o', color='slateblue')
plt.title('TOP10 countries by spirit consumption', fontsize=28)
plt.xlabel('Servings per person', fontsize=23)
plt.xticks(fontsize=20)
plt.xlim(0, None)
plt.ylabel(None)
plt.yticks(fontsize=20)
sns.despine(left=True)
ax.grid(False)
ax.tick_params(bottom=True, left=False)
plt.show()
作者图片
第二个图看起来不那么杂乱,更优雅,这种效果在有许多类别的情况下变得更加明显。另外,我们可以注意到俄罗斯和海地交换了位置,有相同的值。
条形图的特定类型
有一些特殊类型的条形图,它们在某些相当有限的情况下很有用:
- 径向条形图看起来像渐开线条形图,不是用笛卡尔坐标而是用极坐标绘制的。每个条从不同的径向点开始,并且具有圆形形状而不是直线。尽管这些可视化看起来相当有效,但几乎总是应该避免,因为它们严重扭曲了对背后数据的感知,并且难以分析:条形具有不同的周长(而不是长度,如常见的条形图),内部的条形应该是最小的,看起来甚至更小,外部的条形看起来更大,即使它们中的一些可能具有相同的长度。在这样的图上没有 y 轴会造成额外的混乱。有时径向条形图被误称为圆形,这实际上是另一种类型的图表,我们很快就会看到。你可以查看这篇 StackOverflow 关于如何用 Python 创建径向条形图的帖子。
- 圆形和极坐标条形图以不同长度的线段形式显示条形图,从圆形(圆形版本)或点(极坐标版本)开始,而不是传统条形图中的直线。这种图形最适合大量具有明显循环模式的类别(条形)。但是,在所有其他情况下,圆形和极坐标条形图并不是一个好的选择,因为存在一些问题:缺少 y 轴,难以直观地解释线段之间的长度差异,较小条形(靠近基圆或基点的条形)的视错觉甚至更小。这里的演示了如何在 matplotlib 中创建一个极坐标条形图。
- 甘特图 。说明项目进度、不同活动之间的关系以及当前进度状态。
- 瀑布图 。显示在数据序列中连续应用正或负变化后,起始值如何被修改(增加或减少)到最终值。
结论
简而言之,即使条形图仍然是最流行的可视化类型来说明整体由什么组成,为了更有效地讲故事,我们总是可以考虑一些特定情况的替代方案,或者在特定类型的条形图之间进行选择。为了进一步阅读,你可以找到有用的这篇文章,讨论了如何创建有意义的条形图的最佳实践和问题。
感谢阅读!
/.---.\
|`````|
\ /
`-.-' ____
| /\ .' /\
__|__ |K----; | |
`-----` \/ '.___\/
如果你喜欢这篇文章,你也可以发现下面这些有趣的:
https://medium.com/geekculture/creating-a-waterfall-chart-in-python-dc7bcddecb45 [## 在 Faker 库中测试生日悖论(Python)
towardsdatascience.com](/testing-birthday-paradox-in-faker-library-python-54907d724414)
条形图:最佳实践和问题
原文:https://towardsdatascience.com/bar-plots-best-practices-and-issues-30f1ad32c68f?source=collection_archive---------6-----------------------
如果你认为你了解他们的一切…
来自 Unsplash
作为最常见的可视化类型之一,条形图在技术上非常容易创建:我们只需要编写一小段代码。然而,如果我们想要创建一个真正信息丰富、易读的图表,有效地揭示数据背后的故事,我们必须记住几个重要的事情,这是我们将在本文中讨论的。其中一些建议只适用于条形图,其他建议适用于任何类型的可视化。
为了练习我们的柱状图,我们将使用来自 Kaggle 的一个与柱状图密切相关的数据集— 全球酒精消费量🤪🍾这张表是 2010 年的,所以让我们回到过去。
import pandas as pd
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
import seaborn as snsdf = pd.read_csv('drinks.csv')
print('Number of all the countries:', len(df), '\n')# Removing the countries with 0 alcohol consumption
df = df[df['total_litres_of_pure_alcohol'] > 0]\
.reset_index(drop=True)
print(df.head(3), '\n')
print('Number of all the drinking countries:', len(df))**Output:**Number of all the countries: 193
country beer_servings spirit_servings wine_servings \
0 Albania 89 132 54
1 Algeria 25 0 14
2 Andorra 245 138 312
total_litres_of_pure_alcohol
0 4.9
1 0.7
2 12.4
Number of all the drinking countries: 180
去杂乱
一般来说,我们应该最大化图表的数据-墨水比率,因此,排除所有不能通过数据为我们讲述故事提供任何额外信息的东西。
移除冗余特征
首先,我们应该避免情节上任何可能转移读者注意力的特征:
- 不必要的刺和扁虱,
- 如果网格是多余的,
- 尽可能用十进制数,尤其是小数点很多的数字,
- 将精确的数字(十进制或非十进制)放在每个条的顶部:如果我们真的需要它们,我们可以用相应的表格来补充我们的图表。或者,我们可以只在条形顶部使用这些直接标签,并删除数字轴,以避免重复相同的信息。
标签和尺寸
创建条形图时,讲故事的一个看似显而易见但有时被忽视或误用的方面与标签和大小有关:
- 足够的图形宽度和高度,
- 图表标题、轴标签、记号和注释(如果有)的易读字体大小,
- 标题尽可能简洁,同时尽可能详尽地描述,不超过 2-3 行(如果很长),
- 清除坐标轴标签,
- 旋转刻度标签(如有必要),
- 包含在轴标签中或直接包含在标题中的测量值的单位(%、分数或任何绝对值),
- 如果分类轴的值是不言自明的,我们可以省略这个轴标签。
永远要避免的事情
创建柱状图时,应始终避免以下特征:
- 3D 条形图:它们严重扭曲了现实,产生了一种视觉错觉,使识别每个条形的实际高度(长度)变得更加困难。此外,后面的条可以被前面的条完全覆盖,因此读者是看不见的。
- 交互性(极少数情况除外)。
- 装饰品或色彩效果。
让我们比较下面的两个条形图,它们在数据方面是相同的,但在风格上是不同的。此外,我们还将找出 2010 年哪些国家饮酒最多:
top5_alcohol = df.sort_values('total_litres_of_pure_alcohol',
ascending=False)[:5]\
.reset_index(drop=True)fig, ax = plt.subplots(figsize=(16,7))
fig.tight_layout(pad=2)plt.subplot(1,2,1)
sns.set_style('whitegrid')
ax = sns.barplot(x='country', y='total_litres_of_pure_alcohol',
data=top5_alcohol)
for p in ax.patches:
ax.annotate(format(p.get_height(), '.1f'),
(p.get_x() + p.get_width() / 2., p.get_height()),
ha='center', va='center',
xytext=(0, 7), textcoords='offset points')
plt.title('TOP5 countries by pure alcohol consumption')
plt.xlabel('Countries')
plt.ylabel('Litres per person')
ax.grid(True)plt.subplot(1,2,2)
sns.set_style('ticks')
ax = sns.barplot(x='country', y='total_litres_of_pure_alcohol',
data=top5_alcohol)
plt.title('TOP5 countries by pure alcohol consumption', fontsize=30)
plt.xlabel(None)
plt.xticks(fontsize=22, rotation=30)
plt.ylabel('Litres per person', fontsize=25)
plt.yticks(fontsize=22)
sns.despine(bottom=True)
ax.grid(False)
ax.tick_params(bottom=False, left=True)
for _,s in ax.spines.items():
s.set_color('black')
plt.show()
作者图片
第二个条形图,即使仍然不理想,也肯定比第一个干净得多,可读性更好。我们删除了不必要的脊线、分类轴上的刻度、网格、条形值指示、增加字体大小、旋转 x 刻度标签、省略分类轴标签。
是的,我们清楚地看到哪些国家在 2010 年喝了更多的酒。不过,最有可能的是,他们喝的是不同种类的饮料。我们很快会调查这个问题。
着色
我们已经提到,使用额外的颜色效果,如背景或字体颜色,不是一个好的做法。为条形图选择颜色时,还有一些其他的事情需要考虑。
突出显示一些条形
当应用不同的颜色不能传达任何关于数据的信息时,应该避免。默认情况下,seaborn 条形图中的每个条形都有不同的颜色,正如我们前面看到的那样。我们可以通过引入参数color
并给所有的条分配相同的颜色来覆盖它。
但是,我们仍然可以特别强调一些条形,而用灰色显示其他条形。例如,在我们上面的前 5 个国家中,让我们突出在饮酒方面的领导者。除了颜色强调,我们还将添加相应的注释:
spirit_top = top5_alcohol['spirit_servings']
colors = ['grey' if (s < max(spirit_top)) else 'red' for s in spirit_top]fig, ax = plt.subplots(figsize=(10,5))
sns.set_style('white')
ax=sns.barplot(x='country', y='total_litres_of_pure_alcohol',
data=top5_alcohol, palette=colors)
plt.title('TOP5 countries by pure alcohol consumption', fontsize=25)
plt.xlabel(None)
plt.xticks(fontsize=16)
plt.ylabel('Litres per person', fontsize=20)
plt.yticks(fontsize=15)
ax.text(x=2.5, y=12.3, s='the highest \nspirit servings',
color='red', size=17, weight='bold')
sns.despine(bottom=True)
ax.grid(False)
ax.tick_params(bottom=False, left=True)
plt.show()
作者图片
加勒比海小岛国格林纳达的纯酒精消费量排名第四,在排名前五的国家中,它是烈酒消费量最高的国家。
使用色盲调色板
为了让我们的条形图能够达到更广泛的受众,我们应该考虑使用色盲友好的颜色。有各种各样的在线工具(如斯塔克或科尔布林德)来测试不同类型色盲的图像。然而,它最常见的形式涉及区分红色和绿色,所以一个好的方法是避免调色板上有这两种颜色。另一种方法是使用 Tableau 的色盲 10 调色板。缺点是它提供的颜色选择相当有限。
避免违反直觉的颜色
对于大多数人来说,一些颜色与某些类别的现象或品质有很强的联系。例如,紫红色被广泛认为是女性的颜色,交通灯调色板通常用于区分危险、中性和安全区域,红蓝调色板与温度有关,等等。即使你是一个坚定的不墨守成规者,总是反对任何刻板印象,你最好在创建分组条形图时遵循这些不成文的约定,以免误导读者。
如果我们的小组没有特定的惯例,一个好的做法是尝试提出(如果可能的话)一些有背景的,但仍然易于理解的决策。比方说,我们将创建一个过去 10 年全球考拉和狐狸数量的分组柱状图。在这种情况下,我们可以考虑用橙色代表狐狸,灰色代表考拉,而不是相反。
让我们回到纯酒精消费排名前五的国家,并检查每个国家饮用啤酒和葡萄酒的比例。当然,有些啤酒是深红色的(例如樱桃色的),有些葡萄酒是金黄色的(白葡萄酒或梅子酒)。尽管如此,这些饮料最直观的颜色联想是葡萄酒的深红色和啤酒的金黄色:
fig, ax = plt.subplots(figsize=(10,5))
x = np.arange(len(top5_alcohol))
width = 0.4
plt.bar(x-0.2, top5_alcohol['wine_servings'],
width, color='tab:red', label='wine')
plt.bar(x+0.2, top5_alcohol['beer_servings'],
width, color='gold', label='beer')
plt.title('TOP5 countries by pure alcohol consumption', fontsize=25)
plt.xlabel(None)
plt.xticks(top5_alcohol.index, top5_alcohol['country'], fontsize=17)
plt.ylabel('Servings per person', fontsize=20)
plt.yticks(fontsize=17)
sns.despine(bottom=True)
ax.grid(False)
ax.tick_params(bottom=False, left=True)
plt.legend(frameon=False, fontsize=15)
plt.show()
作者图片
现在我们可以很容易地捕捉到,在法国,人们喝葡萄酒比喝啤酒多得多,而在立陶宛和格林纳达——反之亦然。在安道尔,这两种饮料都相当受欢迎,葡萄酒略占主导地位。
配置
垂直与水平
尽管竖条图通常是默认的,但有时水平版本是首选:
- 为了绘制名义变量,
- 当 x 刻度标签太长时,旋转它们有助于避免重叠,但会降低可读性,
- 当我们有大量的类别(条)时。
在最后一种情况下,水平条形图对于从移动电话的窄屏幕上查看图形特别有利。
相反,垂直条形图更适合绘制顺序变量或时间序列。例如,我们可以用它来按地质时期绘制地球上的总生物量,或按月份绘制 UFO 目击数量,等等。
由于country
列代表一个名义变量,并且一些国家的名称相当长,让我们选择许多类别(人均啤酒消费量排名前 20 位的国家),并查看横条图:
top20_beer = df.sort_values('beer_servings', ascending=False)[:20]fig, ax = plt.subplots(figsize=(40,18))
fig.tight_layout(pad=5)# Creating a case-specific function to avoid code repetition
def plot_hor_vs_vert(subplot, x, y, xlabel, ylabel, rotation,
tick_bottom, tick_left):
ax=plt.subplot(1,2,subplot)
sns.barplot(x, y, data=top20_beer, color='slateblue')
plt.title('TOP20 countries \nby beer consumption', fontsize=85)
plt.xlabel(xlabel, fontsize=60)
plt.xticks(fontsize=45, rotation=rotation)
plt.ylabel(ylabel, fontsize=60)
plt.yticks(fontsize=45)
sns.despine(bottom=False, left=True)
ax.grid(False)
ax.tick_params(bottom=tick_bottom, left=tick_left)
return Noneplot_hor_vs_vert(1, x='country', y='beer_servings',
xlabel=None, ylabel='Servings per person',
rotation=90, tick_bottom=False, tick_left=True)
plot_hor_vs_vert(2, x='beer_servings', y='country',
xlabel='Servings per person', ylabel=None,
rotation=None, tick_bottom=True, tick_left=False)
plt.show()
作者图片
将所有单词水平翻转(包括测量值轴的标签)会使第二个图表更具可读性。
这份名单是纳米比亚开的,接下来是捷克共和国。除了立陶宛,我们再也看不到酒精消费量最高的国家了,该国已降至第五位。似乎他们在之前评级中的高位置是用喝烈酒和葡萄酒而不是啤酒来解释的。
排序
如果我们提取人们饮酒超过平均水平的所有国家,然后将这些数据可视化为条形图,得到的条形图将按字母顺序按基本类别(国家)排序。不过,最有可能的是,在这种情况下,我们更感兴趣的是看到按人均葡萄酒数量排序的数据。让我们比较一下这两种方法:
wine_more_than_mean = (df[df['wine_servings'] > df['wine_servings']\
.mean()])
sort_wine_more_than_mean = wine_more_than_mean\
.sort_values('wine_servings',
ascending=False)fig, ax = plt.subplots(figsize=(30,30))
fig.tight_layout(pad=5)# Creating a case-specific function to avoid code repetition
def plot_hor_bar(subplot, data):
plt.subplot(1,2,subplot)
ax = sns.barplot(y='country', x='wine_servings', data=data,
color='slateblue')
plt.title('Countries drinking wine \nmore than average',
fontsize=70)
plt.xlabel('Servings per person', fontsize=50)
plt.xticks(fontsize=40)
plt.ylabel(None)
plt.yticks(fontsize=40)
sns.despine(left=True)
ax.grid(False)
ax.tick_params(bottom=True, left=False)
return Noneplot_hor_bar(1, wine_more_than_mean)
plot_hor_bar(2, sort_wine_more_than_mean)
plt.show()
作者图片
在第一个情节中,我们可以通过人均葡萄酒量(仅指人们饮酒量超过平均水平的国家)来区分前三名和后三名,然后事情变得过于复杂。在第二个情节中,我们可以很容易地追溯整个国家的评级。为了获得更真实的情况,我们应该考虑每个国家的人口(当然,将俄罗斯联邦与库克群岛和圣卢西亚进行比较并不完全正确),并且可能排除弃权者。然而,这里的要点是,如果我们想从可视化中获得最大限度的信息,我们应该始终考虑在绘制数据之前对数据进行排序。这并不一定是按值排序:相反,我们可以决定按类别本身对数据进行排序(如果它们是有序的,如年龄范围),或者如果必要的话,它背后可能有任何其他逻辑。
从 0 开始
虽然其他类型的图不一定要从零开始,但条形图一定要从零开始。其背后的原因是条形图应该显示每个数据点的大小以及所有数据点之间的比例,而不是像线图那样只显示变量的变化。如果我们截断 y 轴(或 x 轴,在水平条形图的情况下),从 0 以外的值开始,我们也截断了每个条形的长度,因此我们的图表不再正确显示每个类别的单个值或它们之间的比率:
usa = df[df['country']=='USA'].transpose()[1:4].reset_index()
usa.columns = ['drinks', 'servings']fig = plt.figure(figsize=(16,6))
fig.tight_layout(pad=5)# Creating a case-specific function to avoid code repetition
def plot_vert_bar(subplot, y_min):
plt.subplot(1,2,subplot)
ax = sns.barplot(x='drinks', y='servings',
data=usa, color='slateblue')
plt.title('Drink consumption in the USA', fontsize=30)
plt.xlabel(None)
plt.xticks(usa.index, ['Beer', 'Spirit', 'Wine'], fontsize=25)
plt.ylabel('Servings per person', fontsize=25)
plt.yticks(fontsize=17)
plt.ylim(y_min, None)
sns.despine(bottom=True)
ax.grid(False)
ax.tick_params(bottom=False, left=True)
return None
plot_vert_bar(1, y_min=80)
plot_vert_bar(2, y_min=None)
plt.show()
作者图片
左边的图给了我们一个误导的印象,即在美国,葡萄酒的消费量比烈酒的消费量低 15 倍左右,而烈酒的消费量还不到啤酒的一半。在右边的图上,我们看到完全不同的比例,这是正确的比例。
分组和堆叠
视觉明显的分组
创建成组条形图时,注意条形之间的距离是很重要的,当每个组内条形之间的间距小于(最大为 0)相邻组条形之间的间距时,认为成组是正确的。
回到纯酒精消费量排名前五的国家,现在让我们来看看每个国家饮用烈酒和葡萄酒的比例:
top5_alcohol_rev = top5_alcohol\
.sort_values('total_litres_of_pure_alcohol')\
.reset_index(drop=True)fig, ax = plt.subplots(figsize=(20,9))
fig.tight_layout(pad=5)# Creating a case-specific function to avoid code repetition
def plot_grouped_bar(subplot, width, gap):
plt.subplot(1,2,subplot)
x = np.arange(len(top5_alcohol_rev['wine_servings']))
plt.barh(x, top5_alcohol_rev['wine_servings'],
width, color='tab:red', label='wine')
plt.barh(x+width+gap, top5_alcohol_rev['spirit_servings'],
width, color='aqua', label='spirit')
plt.yticks(x+width/2, top5_alcohol_rev['country'], fontsize=28)
plt.title('TOP5 countries \nby pure alcohol consumption',
fontsize=40)
plt.xlabel('Servings per person', fontsize=30)
plt.xticks(fontsize=22)
sns.despine(left=True)
plt.tick_params(bottom=True, left=False)
ax.grid(False)
plt.legend(loc='right', frameon=False, fontsize=23)
return Noneplot_grouped_bar(1, width=0.4, gap=0.1)
plot_grouped_bar(2, width=0.3, gap=0)
plt.show()
作者图片
从左边的图中,很难立即区分相邻组之间的边界,因为每个组内部和组之间的条形之间的距离是相等的。相反,右边的图表清楚地显示了每个条形与哪个国家相关。我们现在看到,格林纳达、白俄罗斯和立陶宛的人更喜欢烈酒,而不是葡萄酒,而法国和安道尔的情况正好相反。
堆叠与分组
在堆积条形图和分组条形图之间进行选择时,我们应该考虑我们可视化的主要信息:
- 如果我们最感兴趣的是几个类别的总体值,并且作为次要目标,我们希望粗略估计哪个组件在最大或最小的总体值中贡献最大,那么最佳选择是堆积条形图。然而,这里的问题是,除了第一个元素(即垂直堆积条形图中的最底部或水平条形图中的最左侧),很难找出其单个元素的趋势。这在我们有很多小节的情况下尤其重要,有时,我们甚至会得到一个欺骗的印象并得出一个错误的结论。
- 如果我们想跟踪各个类别中每个单独组件的趋势,我们最好使用分组条形图。显然,在这种情况下,我们不能说按类别的总价值。
让我们将堆积和分组条形图应用于波罗的海国家,找出他们的饮酒偏好:
baltics = df[(df['country']=='Latvia')|(df['country']=='Lithuania')\
|(df['country']=='Estonia')].iloc[:,:4]
baltics.columns = ['country', 'beer', 'spirit', 'wine']
baltics.reset_index(drop=True, inplace=True)labels = baltics['country'].tolist()
beer = np.array(baltics['beer'])
spirit = np.array(baltics['spirit'])
wine = np.array(baltics['wine'])fig, ax = plt.subplots(figsize=(16,7))
fig.tight_layout(pad=5)# Creating a case-specific function to avoid code repetition
def plot_stacked_grouped(subplot, shift, width, bot1, bot2):
x = np.arange(len(baltics))
plt.subplot(1,2,subplot)
plt.bar(x-shift, beer, width,
label='beer', color='gold')
plt.bar(x, spirit, width, bottom=bot1,
label='spirit', color='aqua')
plt.bar(x+shift, wine, width, bottom=bot2,
label='wine', color='tab:red')
plt.title('Drink consumption \nin Baltic countries',
fontsize=35)
plt.xlabel(None)
plt.xticks(baltics.index, labels, fontsize=25)
plt.ylabel('Servings per person', fontsize=27)
plt.yticks(fontsize=20)
sns.despine(bottom=True)
plt.tick_params(bottom=False, left=True)
plt.legend(frameon=False, fontsize=17)
return Noneplot_stacked_grouped(1, shift=0, width=0.35,
bot1=beer, bot2=beer+spirit)
plot_stacked_grouped(2, shift=0.2, width=0.2,
bot1=0, bot2=0)
plt.show()
作者图片
- 从上面的堆积图中我们可以看到,在所有三个波罗的海国家中,立陶宛的酒精消费量最高,而爱沙尼亚的消费量最低。两种情况下的主要贡献都来自啤酒。关于这些国家烈酒和葡萄酒的消费,从这个情节中我们说不出什么精确的东西。事实上,数量似乎相等。
- 分组图清楚地显示,立陶宛也在饮用烈酒方面领先,而爱沙尼亚再次显示最低水平。不过,这种饮料的区别并不像啤酒那样明显。至于葡萄酒,差异就更不明显了,但似乎拉脱维亚的葡萄酒消费量最高,而立陶宛的消费量最低。然而,从这个图表中,猜测这些国家的总体酒精消费量已经变得更加困难。我们必须做一些心算,如果有超过 3 个酒吧组,这个任务就变得不切实际了。
结论
正如我们所看到的,条形图并不像看起来那样平庸。在创建有意义的可视化并从中获得正确的见解之前,我们必须考虑许多细节,包括我们的目标、我们的目标受众、我们的图表中最重要的内容是什么、如何在显示其他有用信息的同时强调它,以及如何排除对我们讲故事完全无用的功能。
感谢阅读,和 za zdorovie!😉🥂
如果你喜欢这篇文章,你也可以发现下面这些有趣的:
https://medium.com/geekculture/emojize-your-data-science-projects-8f19d447f03c
棒球和机器学习:2021 年击球预测的数据科学方法
原文:https://towardsdatascience.com/baseball-and-machine-learning-a-data-science-approach-to-2021-hitting-projections-4d6eeed01ede?source=collection_archive---------7-----------------------
萨凡纳·罗莱德在 Unsplash 上的照片
实践教程
一个接一个的统计看最好的预测者和一个预测离群值的探索
如今,体育界的名人喜欢抨击分析。很难在体育广播中听五分钟的棒球谈话而不听到有人对“书呆子接管”做出贬损的评论具有讽刺意味的是,他们随后立即推出体育博彩广告,猜猜看,伙计们…任何时候你下注,因为“巨人队总是在华盛顿输”或其他什么,这是一种基本的分析形式,没有实际的建模。我还注意到一种流行的观点,即高级统计和建模将产生一种单一的(阅读:无聊的)游戏方式。如果发生这种情况,那是因为缺乏想象力。我坚信分析的许多方面代表了一种类型的棒球知识。传统的棒球本能和经验是另一个,当两个领域协调工作时,你会得到最好的结果。我确实认为棒球中的分析有扩展的空间,并且可以更深入地进入数据科学领域。
这就是说,我终于有足够的时间来构建机器学习模型,以构建我今年的棒球预测。只是提醒一下:这篇文章将会很密集。我将向您介绍我的方法、思维过程以及我在研究这些模型时的失误。对于以棒球为中心的读者来说,它在数据科学上有点沉重,对于数据科学家来说,它在棒球上有点沉重。但是这一切都很酷,如果你关心这些话题的话。这个会比较长,所以我打算分成两篇:一篇关于击球,一篇关于投球。作为背景,我在三月份,赛季开始前建立了这些模型,所以我没有包括本赛季前几周的数据。只是花了一些时间来整理这篇文章。
数据:从哪里开始
这是容易的部分。尖括号。总是从尖牙形开始。对此,我想考虑我可能获得的每一份数据,并尽量减少关于什么是可预测的和不可预测的先入为主的观念…所以我从一切开始。一切?
eeeevverythiiiing!
</释义>
不过,说真的,你可以做到的。FanGraphs 允许你提取他们保存的每个统计数据并导出到一个整洁的 csv 文件中。从 2015 年到 2020 年,我每年都是这么做的。这样做将获得大量重复数据,包括许多完全相关的列——我们将在进行过程中对它们进行分类。
建模第 1 部分:回归方法
这一点是为了预测 2021 年的具体统计数据,这意味着这必须是一种回归方法,而不是一种分类方法(或者说,我是这样认为的……这方面还有更多的内容)。回归问题对选项的限制远远超过分类问题:这是一个过于简化的问题,但我主要是从线性回归、随机森林和 XGBoost 中进行选择。线性回归在这里并不是一个很好的选择,因为它假设输入变量之间是独立的,而在这里却不是这样。也仅限于寻找线性关系。
随机森林回归本来是一个非常合理的选择,但是我选择 XGBoost 来构建模型,因为它是对随机森林的改进。XGBoost 是一种流行的集成决策树算法,它结合了许多连续的决策树,每棵树都从其前身学习,并改进前一棵树的残差。它在这类问题上也表现得很好。
我计划的步骤是:清理和准备数据。
2。确定目标变量。
3。将模型拟合到 2017 年和 2018 年的数据,试图预测随后一年的统计数据。
4。将模型的超参数调整到最佳设置。
5。结合 2017 年和 2018 年的数据,重新训练模型,重新调整超参数,并评估差异。
6。使用 2019 年和 2020 年的混合输入数据集,使用生成的模型预测 2021 年的统计数据。
让我们打开最后一件行李。2020 年提出了一个问题,你可能还记得,我们有一点疫情问题,所以我们只有 60 场比赛。我最初的计划是制作一个 2019 年和 2020 年的混合数据集。我这样做是通过准备两年的加权平均数据,然后将它们扩展到 162 场比赛。如果一个球员在 2020 年没有比赛,我使用 2019 年的总数。这种方法的好处是,我有一个数据集,它不会过度依赖于被最不正常的环境包围的短暂季节。主要的缺点是,我丢失了一年的模型训练数据,所以我必须使用 2017 年和 2018 年的数据。最终,我认为丢失这一年的数据更糟糕。我最终合并了 2019 年的数据,并将 2020 年的数据扩展到 162 场比赛(这远远不是一个完美的解决方案,但它比我想象的要好……我们将会实现这一点)。
数据清理/准备
这些数据带来了一些挑战,但不是人们通常在真实世界数据集上看到的那种挑战。很高兴事先知道这些数字基本上是干净的。有一些空值需要处理,但这是最小的痛苦。绝大多数缺口都在 Statcast 字段中,很明显,这主要是因为所讨论的事件没有发生。如果投手不投滑球,就很难确定他们的平均滑球速度。我处理缺失数据的一般方法是:如果一列填充了不到 60%的内容,我就剪切该列,因为估算那么多缺失值是没有用的。否则,我用两种方法填充空白:对于百分比,我用零填充空值。这似乎是合乎逻辑的,因为这些百分比与包含未发生事件的其他字段相关。否则,我用每一列中的中值填充空值(对于每一年,我在整个数据准备过程中保持年份分开)。
我手动添加了一些字段。这些可能会在随后的研究中发挥更大的作用,但我想看看他们在这些模型中的表现。我增加了联赛的变量(0 代表 AL,1 代表 NL),球员是否在之前的淡季更换了球队和/或联赛,以及他们是否在赛季中更换了球队/联赛,考虑了交易/削减/签约。这最后一部分有一些灰色地带,因为在这一年中有几个球员在两支以上球队之间流动的例子。我对这些做了判断。如果有人跳槽到四支球队,我会查看他们打比赛最多的地方。如果一个人在美联球队打了六年,在休赛期被一个国联球队签下,并为他们打了七场比赛,然后在这一年的剩余时间里被交易回美联…我不认为这是改变联盟。无论如何,这些都是数字编码的。我 one-hot-encoded 玩家的团队,看看加入某个特定的团队是否有任何影响。
我还为大约 20 个统计数据添加了滞后变量(即前一年统计数据的值)。我说我想消除关于什么是预测性的先入为主的观念,但是我也需要确保不要忽略简单的概念,比如,“过去两年中每一年的 RBI 都是下一季 RBI 的最具预测性的度量。”包含滞后变量的不利方面是有相当多的球员在之前的赛季中没有积累统计数据。我选择从数据集中删除那些案例。这是一个艰难的决定,但我在这里的假设是,使用滞后变量的收益大于排除那些没有上年数据的变量的损失。我还认为在这种情况下使用中间值是不正确的。举例来说,如果我这样做了,数据中显示的每个新秀赛季都会假设球员在上一年有有效的联盟平均表现,我认为这将是一个非常不正确的假设,对模型的影响比删除这些行更大。
目标变量
我们到底在预测什么?最初,我专注于十个统计数据:出场数(PA),跑垒数(R),本垒打数(HR),安打数(RBI),盗垒数(SB),抢断数(cs),击球率(AVG),上垒率(OBP),以及上垒率+击球率(OPS)。我为 2016 年至 2019 年的每个数据集添加了这些统计数据的目标列。这仅仅包括从下一年的数据集中映射各自的字段。对于 2019 年,我使用了 2020 年数据的一个版本,该版本的目标是 162 场比赛。这最初是为了探索的目的。敬请关注。
任何在下一年没有数据的玩家都被从当年的数据集中删除。此算法的目标不能包含空值。为了好玩,我还包括了由 FanGraphs 计算的“美元价值”(Dol)数字。我并不期望这些表现良好,但由于它们是基于整体生产,我认为测试它们会很好。如果结果和个人数据的质量水平相当,那将会是一个有趣的结果。
现在,我们一次只能预测这些目标变量中的一个,所以这意味着有 11 套不同的模型。没问题。
首批型号:全进
标题在这里说明了一切。我运行了一组模型,基本上包括了输入变量集合中的所有内容,并观察了它们中哪一个具有最大的影响。在这个阶段,我对超参数进行了一定程度的调整,主要是为了查看输入变量的影响是否发生了变化以及变化了多少。我不会在这里做太多的详细说明——结果是我做了一些功能工程,并减少了我的输入尺寸。本质上,我删除了所有的 Statcast 字段,因为它们在预测任何目标变量时似乎没有移动指针。出于同样的原因,我也放弃了所有的团队变量。
最终回归模型
使用这个修剪过的数据集,我运行了新的 XGBoost 回归模型,并稍微仔细地调整了超参数。我还测试了它们每年的一致性:我分别为 2017 年、2018 年和 2019 年的数据集建立了模型,预测了下一年的目标变量。
我分几个步骤进行了超参数调整。我从一些常见的中间值开始:
param_dict = {'n_estimators':500, 'learning_rate':0.01, 'max_depth':5, 'subsample':0.1, 'colsample_bytree':0.3}
然后,我连续几轮进行了网格搜索。首先,我调整了最大树深度,这是一个防止模型过度拟合的关键超参数。在没有最大深度的情况下,该算法可以构建能够完美适应您的训练数据的多级决策树,但永远不会推广到其他数据(XGBoost 确实假设默认的 max_depth 为 6,但对其进行优化仍然是一种很好的做法)。接下来,我一起调优了 colsample_bytree 和 subsample。这两者是相关的。随着算法增长其决策树,子采样选择训练数据的指定部分,这进一步有助于防止过度拟合。在那之后,我调整了学习速率,听起来是这样的:你可以指定算法从每一次决策树迭代中学习的速度。最后一次迭代是调整估计数,即模型中树的数量。在每个阶段,我都重写了上面的参数字典,以匹配最佳参数。我将上述所有内容打包在一个函数中,然后针对每年的训练数据运行它。令我惊讶的是,调整后的超参数每年产生完全相同的最佳参数(每个统计数据不同,但每年一致)。这既可疑又令人鼓舞。
每年数据的精确度和准确度都很相似。有趣的是,尽管 2019 年的数据比其他几年更差,但它并没有明显更差,尽管它是基于新冠肺炎疫情期间 60 场比赛的规模数据。它表现得足够好,我能够将它纳入我的主数据集中,这是 2016 年至 2019 年的总和。
建模第 2 部分:陷阱(哈…抱歉)
大多数模型表现良好。我会说,输出是完全可以接受的,如果我们追求一般的准确性,将它们投入生产会很舒服。问题是:机器学习,一般来说,在预测非异常值方面做得很好。不幸的是,在棒球中,我们最关心的是预测异常值。我们想知道谁脱颖而出,谁又平平无奇。为此,XGBoost 回归模型没有削减它。这里有一个例子。这是针对 RBI 的调整模型的性能:
如你所见,预测在中间。而且它很大程度上预测得很好…除了它基本上错过了每一个 90 分以上的球季以及每一个 30 分以下的球季。不理想。
那我们该怎么办?我的方法:我基本上把它变成了混合回归/分类练习。对于每一个统计数据,我们知道回归模型在哪里做得好,在哪里做得不好,我们也知道这些异常值的范围。使用这些范围,我能够很容易地将统计数据分成不同的层,这些层使我能够构建 XGBoost 分类器模型来尝试预测它们。计划是将回归工作和分类工作的结果结合起来,以产生全面的预测。
这里有一个例子:本垒打的回归模型可靠地预测了 6-29 之间的任何事情。它在 0-5 和 30+之间摇摆不定。我对我的训练数据进行了编码,0–5 是 0,6–29 是 1,30+是 2。分类器算法会根据上面使用的所有输入数据,尝试预测每个玩家的 0、1 和 2。对于预测为 1 的任何东西,我使用回归预测。对于 0 和 2,我分别使用 0–5 和 30+范围,然后将回归模型的输出映射到我对这些范围的假设。
一个额外的复杂因素是:即使划分到层中,这些值仍然是异常值,这意味着我们正在处理不平衡的数据。这是一个有点问题的问题,因为算法可以为任何事情选择多数类,并且很大程度上是准确的。我采用过采样数据的方法来解决这个问题。过采样是一种复制代表性不足的数据以平衡建模数据集的方法。我尝试了几种不同的方法,最终决定采用 SMOTE(合成少数过采样技术),它构建了未充分表示的数据的合成示例,而不是添加直接的副本。起初,我在使用这种方法时遇到了一点麻烦,因为我的模型中的交叉验证步骤似乎抵消了过采样。我发现我不正确地进行了过采样,在分割成交叉验证折叠之前应用了它。这篇文章很好地/更深入地解释了如何正确地实现这一点(以及哪里可能出错)。我最终用不平衡学习包通过管道实现了它,这是专门为此目的设计的。
from imblearn.pipeline import Pipeline, make_pipeline
from imblearn.over_sampling import SMOTE
RANDOMSTATE = 120imb_pipeline = make_pipeline(SMOTE(random_state=RANDOMSTATE),
xgb.XGBClassifier(eval_metric='merror', **param_dict, verbosity=0, use_label_encoder=False))
scores = cross_val_score(imb_pipeline, xtrain, ytrain, scoring='f1_micro', cv=5)
print("Mean cross-validation score: %.2f" % scores.mean())kf_cv_scores = cross_val_score(imb_pipeline, xtrain, ytrain, scoring='f1_micro', cv=kfold)
print("K-fold CV average score: %.2f" % kf_cv_scores.mean())
我将这些分类器算法的成功定义为它们正确预测异常值的能力。我研究了精度(正确预测的离群值的比例)和召回率(识别的所有离群值的比例),以及在应用 SMOTE 技术后这些度量如何变化。所有人都有所改善。总的来说,精确度非常好:在标记为异常值的统计数据中,算法在正确选择它们方面做得非常好。不过,召回率并不高,这意味着有很多算法没有发现的异常值。总结如下:
结果
但是天哪,伙计…结果在哪里?!?告诉我们发生了什么事!好吧好吧。让我们一点一点来。我将展示通过调整算法得到的最佳超参数,然后使用 SHAP 软件包中提供的精彩摘要图向您展示哪些输入变量对模型产生了最大的影响。我发现这些是令人惊奇的解释工具:输入特征按照对模型的重要性排列。对于每个特征,你会看到一个红到蓝的光谱:红色是较高的值,蓝色是较低的值。各个点从左到右排列,显示对模型的影响程度。因此,如果 RBI Lag_1(即前年的 RBI)的所有红点都在右边,这意味着 2019 年的较高 RBI 值对模型的积极影响比较低的值更大。
有些结果是直观的。以盗垒为例:最具预测性的变量是前一年的盗垒,速度(Spd),前两年的盗垒,前一年被抓到的盗垒,跑垒(BsR),以及前两年被抓到的盗垒。这似乎是显而易见的。其他一些数据则不然。我发现最令人吃惊的是年龄在其中的作用。我知道这很重要,但是对于这些数据中的一半来说,它是第一号预测因素,而且它在大多数情况下都排在前五位。
板材外观(PA)
Best hyperparameters:
{'n_estimators': 500,
'learning_rate': 0.01,
'max_depth': 3,
'subsample': 0.5,
'colsample_bytree': 0.25}
运行(R)
Best hyperparameters:
{'n_estimators': 400,
'learning_rate': 0.01,
'max_depth': 4,
'subsample': 0.5,
'colsample_bytree': 0.15}
本垒打(小时)
Best hyperparameters:
{'n_estimators': 500,
'learning_rate': 0.01,
'max_depth': 4,
'subsample': 0.6,
'colsample_bytree': 0.3}
击球得分(打点)
Best hyperparameters:
{'n_estimators': 500,
'learning_rate': 0.01,
'max_depth': 6,
'subsample': 0.4,
'colsample_bytree': 0.3}
偷垒(某人)
Best hyperparameters:
{'n_estimators': 400,
'learning_rate': 0.01,
'max_depth': 3,
'subsample': 0.4,
'colsample_bytree': 0.35}
偷窃被抓(密室)
Best hyperparameters:
{'n_estimators': 300,
'learning_rate': 0.01,
'max_depth': 3,
'subsample': 0.7,
'colsample_bytree': 0.35}
击球率(AVG)
Best hyperparameters:
{'n_estimators': 500,
'learning_rate': 0.01,
'max_depth': 3,
'subsample': 0.4,
'colsample_bytree': 0.25}
上垒百分比(OBP)
Best hyperparameters:
{'n_estimators': 500,
'learning_rate': 0.01,
'max_depth': 3,
'subsample': 0.5,
'colsample_bytree': 0.15}
上垒百分比+击球百分比(OPS)
Best hyperparameters:
{'n_estimators': 500,
'learning_rate': 0.01,
'max_depth': 3,
'subsample': 0.7,
'colsample_bytree': 0.15}
美元价值
Best hyperparameters:
{'n_estimators': 500,
'learning_rate': 0.01,
'max_depth': 3,
'subsample': 1.0,
'colsample_bytree': 0.35}
投影输出
一旦我有了完整的计划,我就根据自己的评分公式计算分数。我想看看它们与公布的投影相比如何,所以我使用了德里克·卡蒂的精彩的 THEBAT 投影(我认为这是技术上最先进的投影系统)。然后,我用给自己打分的方式给它们打分,这样我就可以检查它们之间的差异。我只看了那些平均选秀位置在 300 或更低的球员,因为,嗯,那些更有趣。首先,我们有一些球员,我预测他们会比棒球手表现得更好:
首先,我的预测没有考虑玩家是否已经开始工作。这就是为什么你会在这里看到像皮勒和维拉尔这样的人。算法不知道那些球员是作为替补签的。我们将看到这些在 2021 赛季的过程中如何发展。现在,让我们看看模型预测的产量比实际产量差的地方:
我从这套模型中看到的最大收获是:
1)我的模型对 2020 年糟糕表现的惩罚超过了对手。正如我之前讨论的,2020 年的数据有很多问题。在这个世界分崩离析的时候,60 场比赛中有太多我们不知道的东西。我的模型对那些因伤错过很多时间的球员更加悲观。在年底重温这些将会非常有趣。
包裹
如果你已经走到这一步,恭喜你。我希望你觉得这很有趣。接下来的一周左右,我们将推出这个版本。
你觉得我的方法怎么样?在未来的迭代中,我应该做哪些不同的事情?我正在让我的代码和数据文件在 GitHub 上可用。
棒球和机器学习第 2 部分:2021 年投球预测的数据科学方法
原文:https://towardsdatascience.com/baseball-and-machine-learning-part-2-a-data-science-approach-to-2021-pitching-projections-530dbfe6dcc4?source=collection_archive---------27-----------------------
Jose Francisco Morales 在 Unsplash 上的照片
看看投球的最佳预测
在棒球和机器学习第一部分中,我概述了我在 3 月份使用回归和分类算法组合构建 2021 年 MLB 击球预测的方法。然后我骗了你。可怕地。我答应在“一周左右”内完成我的项目哎呀。我想我应该在这个估计中包含一个置信区间。将近六个星期后,我终于分娩了。
从今年开始,我越来越意识到这是一个多么糟糕的赛季。2020 年是现代历史上试图用作预测基础的最不正常的一年:60 场比赛,比正常情况开始得晚得多,有一个收缩的上升期,由于 COVID 而频繁取消。哦,让我们不要忽视在疫情期间演奏的心理影响。现在,我们可以加上 MLB 打击投手在投球时使用异物的影响,这一影响尚未确定。不过,我还是做了预测,所以让我们来看看。
该方法与我在第 1 部分中阐述的方法基本相同——请查看完整的文章。我将在这里给出一个简要的概述,但我将主要关注我们看到的投球与击球的具体差异以及投球的结果。
方法概述
源数据
方块字。我的起始数据集包含了他们报告的所有投球统计数据。我自己加了几个字段,都是手动编译的。这些包括联赛的指标变量(0 代表 AL,1 代表 NL),球员是否在之前的淡季更换了球队和/或联赛,以及他们是否在赛季中更换了球队/联赛,考虑了交易/削减/签约。这个变量比你想象的更加主观。如果一个球员在一个赛季中出现在几个球队,我会查看他们在哪里打了最多的比赛。如果有人在美联效力了六年,在休赛期被国联球队签下,并为他们打了七场比赛,然后在这一年的剩余时间里被交易回美联,我不认为这是改变联赛。我最初包含了团队的指标变量,但是在特性工程阶段我删除了它们。
我还为大约 20 个统计数据添加了滞后变量(即前一年统计数据的值)。这带来了一些问题,因为有相当多的球员在前几个赛季没有累积数据。我选择从数据集中删除这些案例,是基于这样一种假设,即包含这些变量的收益大于删除这些区域中的空行的损失。
我使用 2016-2019 年的数据来训练我的模型。对于先发投手,我使用了 60 局的最低投球局数,并删除了低于该阈值的所有数据点。对于替补投手,我设定了 40 局。
数据准备
对于这个练习中最重要的部分,我在特性工程阶段从输入特性集中删除了几乎所有的 Statcast 字段。我更犹豫要不要为投球数据采取那一步。不过,我确实减少了,因为 Fangraphs 显示了来自多个来源的许多统计数据。我删除了 Pitch f/x 版本的 stats(在 Fangraphs 上标记为“(pi)”)并保留了 Statcast 版本(标记为“(sc)”)。这些字段也是您会发现绝大多数缺失数据的字段。这是合乎逻辑的:不是每个投手都投每种类型的球,所以自然会有差距。我处理缺失数据的一般方法是,如果填充的数据少于 60%,就删除一列,因为我认为填充这么多缺失值是没有用的。否则,我用两种方法填充空白:对于百分比,我用零填充空值,因为百分比是从包含未发生事件的其他字段中计算出来的。否则,我用每一列中的中值填充空值(按年份——在整个数据准备过程中我将年份分开)。
目标变量
我使用不同的模型预测了 11 个投球统计数据:投球局数(IP),胜场数(W),失球数(L),救球数(SV),吹救球数(BS),持球数(HLD),允许本垒打数(HRA),三振数(K),平均得分(ERA),每局投手保送+安打数(WHIP),以及 Fangraphs 的计算美元值(Dol)。对于训练数据,我使用了下一年的每个统计数据的结果。对于 2019 年的数据,目标变量是我缩放到 162 场的 2020 年数据。这不是一个理想的解决方案,但已经足够好了。
模型
我为这个练习构建了两种类型的模型。第一个使用 XGBoost 回归来产生上面列出的 2021 年统计数据的一组预测。我分几个步骤调优了这些模型:首先,我调优了最大树深度。接下来,我一起按树进行子抽样和列抽样。第三步是学习率,最后一步是估计数。我使用 kfold 交叉验证了十次折叠和平均绝对误差。这产生了坚实的整体结果,但遇到了机器学习的一个常见问题:它在预测中间值方面很好,但在确定离群值方面很糟糕。不幸的是,离群值是我们在预测棒球统计数据时最关心的。
为了解决这个问题,我准备了第二组模型,这次使用 XGBoost 分类器。先发投手和替补投手天生产生非常不同的统计范围,所以我在这个练习中把他们分成两个数据集。我将各种统计数据分成不同的等级,并预测这些等级(例如,对于先发投手,0-49 次三振是 0 级,50-179 次是 1 级,180 次以上是 2 级;第 0 层和第 2 层代表异常值)。因为我故意试图预测异常值,这些是严重不平衡的数据集。为了优化不平衡数据的模型,我对代表性不足的类使用了 SMOTE 过采样。和回归练习一样,我用 kfold 进行了十次交叉验证。不过,在这种情况下,我在交叉验证中使用了微平均 F1 分数,因为我在寻找精确度和召回率之间的最佳平衡。
我用分类模型预测异常值的能力来定义分类模型的成功。总的来说,精确度非常好:在标记为异常值的统计数据中,算法在正确选择它们方面做得非常好。回忆没有那么好,但在这方面投球比击球表现得更好。总结如下。这里有一些奇怪的东西。例如,救援投手投球局数以 0%的准确率和召回率开始,以 100%的准确率结束。这部分是因为中继局只有两层:少于 55 个 IP 是第 0 层,多于 55 个 IP 是第 1 层,第 0 层代表唯一的异常值。最初,算法预测每个人都在第 1 层。在应用 SMOTE 后,该模型使那些标记为第 0 层的 100%正确,但仅识别出那些异常值的 21.43%。
一旦所有模型都调优并最终确定,我就将结果组合起来构建我的预测:对于任何预测的中间层,我都使用回归结果。对于极端情况,我使用分类结果,将各层扩展到预期范围。
结果
让我们来看看每个统计数据。我将给出优化的超参数,然后向您展示哪些输入变量对模型的影响最大。汇总图来自 SHAP 包,它按照对模型影响从大到小的顺序显示输入要素。对于每个特性,都显示一个红到蓝的光谱,其中红色值较高,蓝色值较低。各个点从左到右排列,显示对模型的影响程度。因此,如果所有代表年龄的红点都在最左边,这意味着年龄越小,对模型的正面影响越大。
记住,输入的特征是针对上一季的,所以如果你看到 IP 预测 IP,说明是某一年的 IP 预测下一年的 IP。当您看到“Lag1”附加到一个 stat 上时,例如 IP_Lag1,它表示两年前投的局数。一个注意事项:我注意到有两个标签没有正确传递。如果您看到“#NAME?”,表示“-WPA”(所有负赢概率加事件的总和),以及“#NAME?. 1”表示“+WPA”(所有负获胜概率相加事件的总和)。我不会在这里浪费你的时间来定义所有的 sabermetric 统计数据,所以如果你看到一个你不认识的统计数据,你应该查阅关于 Fangraphs 的 sabermetrics 词汇表,或者,你知道,谷歌。
投球局数
Best hyperparameters:
{'n_estimators': 400,
'learning_rate': 0.01,
'max_depth': 3,
'subsample': 0.8,
'colsample_bytree': 0.1}
胜利(W)
Best hyperparameters:
{'n_estimators': 300,
'learning_rate': 0.01,
'max_depth': 7,
'subsample': 0.5,
'colsample_bytree': 0.2}
损失(L)
Best hyperparameters:
{'n_estimators': 300,
'learning_rate': 0.01,
'max_depth': 6,
'subsample': 1.0,
'colsample_bytree': 0.1}
保存(服务)
Best hyperparameters:
{'n_estimators': 200,
'learning_rate': 0.01,
'max_depth': 6,
'subsample': 0.4,
'colsample_bytree': 0.3}
吹救(BS)
Best hyperparameters:
{'n_estimators': 200,
'learning_rate': 0.01,
'max_depth': 6,
'subsample': 0.4,
'colsample_bytree': 0.1}
保留(HLD)
Best hyperparameters:
{'n_estimators': 200,
'learning_rate': 0.01,
'max_depth': 6,
'subsample': 0.6,
'colsample_bytree': 0.15}
删除线(K)
Best hyperparameters:
{'n_estimators': 500,
'learning_rate': 0.01,
'max_depth': 3,
'subsample': 0.4,
'colsample_bytree': 0.2}
允许本垒打
Best hyperparameters:
{'n_estimators': 300,
'learning_rate': 0.01,
'max_depth': 8,
'subsample': 0.8,
'colsample_bytree': 0.1}
挣得运行平均值(ERA)
Best hyperparameters:
{'n_estimators': 500,
'learning_rate': 0.01,
'max_depth': 6,
'subsample': 0.4,
'colsample_bytree': 0.15}
每局投球保送+安打数(鞭笞)
Best hyperparameters:
{'n_estimators': 500,
'learning_rate': 0.01,
'max_depth': 7,
'subsample': 0.6,
'colsample_bytree': 0.2}
美元价值
Best hyperparameters:
{'n_estimators': 300,
'learning_rate': 0.01,
'max_depth': 4,
'subsample': 0.5,
'colsample_bytree': 0.15}
外卖食品
这些结果对我来说很有趣。首先映入我眼帘的是明显缺少年龄这一因素。在我的击球文章中,你可以看到年龄是大多数击球统计的头号预测因素,而在投球方面却无处可寻。
另一件让我特别感兴趣的事情是,一些整体价值指标扮演了多么突出的角色——尤其是尖牙尖牙的美元价值。奇怪的是,两年前的美元价值(Dol_Lag1)是最具预测性的因素。它是 IP、W 和 K 的头号预测因子,在其他几个统计数据中也占有显著地位。我还在消化这个结果。很耐人寻味。
K/9+是 ERA 和 WHIP 比率的强预测因子。我感觉好像专家们不久前就开始关注这个问题了,但在实践中看到这一点还是很有趣的。K/BB+也表现强劲。那一个最近几年在专家中非常流行。
我怀疑在投球局数类别中有一些混淆的变数。投球局数、先发投手 IP 和中继投手 IP 都在这些模型中出现,但它们之间有很大的相关性,所以算法只能在每个决策树中选取一个。当你把所有的树加起来得到集合模型时,这意味着一个或多个局的投球类别可能在最终结果中被缩短。
投影输出
【2022 注:在 2022 年 4 月评估这些结果时,我发现了一个重大错误。我的分数是正确的,但是蝙蝠的分数是错误的。更多详情请见2022 文章。]
一旦我有了完整的计划,我就用我开发的评分公式计算分数。然后我用同样的公式给德里克·卡蒂的底部预测打分,这样我就能看到最大的差异在哪里。我只看了那些有 60 局或更多预测局数的球员——比较那些没有被预测一个完整赛季的人的预测是没有用的。首先,我们有一些球员,我预测他们会比棒球手表现得更好:
我将借此机会重申,这是进行这种特定练习的最愚蠢的一年,COVID 年被纳入了训练数据,MLB 改变了球,大量的受伤(其中一些与上面的 miiiight 有关),现在,MLB 打击使用粘性物质。上面的名字已经有一大块受伤了。一些人失去了他们最初的工作(我们永远不会知道大卫·普莱斯的预测会如何发展)。我们还有很多赛季,但其中一些电话看起来真的很好(伯恩斯,默斯格罗夫),其他人看起来像巨大的失误(邦迪,卡斯蒂洛)。
现在,让我们看看模型预测的产量比实际产量差的地方:
这批有意思。到本赛季的这个时候,算法似乎已经击中了比他们错过的悲观主义团队更多的东西。杰克逊、布鲁贝克、维特格伦、威廉姆斯和巴西特都是这份名单上的常客。其他 10 个与我的预测一致得多(尽管我们可以暂时放过谢恩·格林,因为他失业的时间太长了)。
包裹
伟大的投球探索到此结束。我希望它以某种方式为你打开了齿轮。
我很想听听你的意见。你觉得我的方法怎么样?在未来的迭代中,我应该做哪些不同的事情?我在 GitHub 上发布我的代码和数据文件。
NeurIPS 2021 轮班挑战赛机器翻译任务的基线演练
原文:https://towardsdatascience.com/baseline-walkthrough-for-the-machine-translation-task-of-the-shifts-challenge-at-neurips-2021-e432c92882de?source=collection_archive---------11-----------------------
让你自己站起来跑起来!
图片由 Yandex 提供
分布式转移(训练和部署数据之间的不匹配)在现实世界的任务中普遍存在,并对人工智能系统的安全和可靠使用提出了重大挑战。今年在 NeurlPS 上,我们组织了 转变挑战 ,在那里我们调查了在真实的工业规模应用中对分布转变和不确定性的鲁棒性。本博客仅针对此次挑战的机器翻译任务,是对官方 Github 页面上的说明的补充,带有关于数据集、培训和评估流程的附加说明。本教程是对黄的《换挡挑战赛车辆运动预测任务教程的后续。
本教程的结构如下:
- 任务概述
- 设置环境和存储库
- 下载数据和基线
- 将数据预处理成 Fairseq 格式
- 模特培训
- 获得预测和不确定性估计
- 模型评估和提交
- 改进方向
1.任务概述
作为轮班数据集的一部分,我们检查机器翻译的任务。翻译服务,如 Google Translate 或 Yandex Translate,在其翻译查询中经常遇到非典型和不寻常的语言使用。这通常包括俚语、脏话、糟糕的语法、拼写和标点符号,以及表情符号。这对现代翻译系统提出了挑战,现代翻译系统通常是在语言使用更“标准”的语料库上训练的。因此,对于模型来说,重要的是既要对非典型语言的使用具有鲁棒性,以提供高质量的翻译,又要能够指出它们何时不能提供高质量的翻译。这在机器翻译系统用于翻译敏感的法律或外交文件时尤其重要,在这种情况下,意义不“在翻译中丢失”是至关重要的。因此,我们希望模型能够在一系列场景中表现良好,并在它们不能表现良好时进行指示。这分别对应于 鲁棒性 和 不确定性 的预测。在转变 挑战中,我们评估了分布转变下的预测稳健性和不确定性。
在大多数先前的工作中,不确定性估计和对分布变化的稳健性是分开评估的。鲁棒性通常通过对特定任务的预测性能的度量来评估,例如分类错误率。同时,不确定性估计的质量通常通过区分与训练数据匹配的“域内”数据集和基于不确定性测量的移位或“域外”(OOD)数据集的能力来评估。然而,我们认为这两个问题是一个共同整体的两个部分,因此必须一起评估。此外,它们必须在包含大量匹配或“域内”数据和大量移位数据的数据集上进行联合评估[1]。我们将在评估部分描述更多细节。
翻译本质上是一个 结构化预测 任务,因为输出序列中的标记之间存在依赖关系。通常我们必须对这些依赖的形式做出假设;例如,大多数现代翻译系统是从左到右自回归的。然而,我们可以考虑条件独立预测或其他因子分解顺序。这些假设的性质使得获得理论上合理的不确定性度量具有挑战性。直到最近,人们才开始开发结构化预测的原则性不确定性测量方法[2,3,4,5,6]。然而,这仍然是一个未解决的任务和一个富有成果的研究领域。本教程研究了如何在自回归结构化预测【2】中基于不确定性估计建立和运行基线系统。
2.设置环境和存储库
要开始这项任务,您必须首先设置所有必需的包和适当的环境。请注意代码有点过时,使用的是 Fairseq 0.9 和 PyTorch 1.6.0。我们计划很快创建一个更干净的最新实现。因此,你将需要 python 3.7 和 CUDA 10.2。
首先,启动您的 shell,克隆并安装轮班质询存储库:
*git clone [https://github.com/yandex-research/shifts.git](https://github.com/yandex-research/shifts.git)*
在目录中,您会发现一个“requirements . txt”——继续安装所有这些包:
*pip install matplotlib numpy torch==1.6.0 sacrebleu==1.4.3 nltk==3.4.5*
这也将安装与 Fairseq 0.9 兼容的所有必需软件包的版本。最后,克隆一个自回归结构化预测【2】中不确定性估计的实现。
*git clone [https://github.com/KaosEngineer/structured-uncertainty.git](https://github.com/KaosEngineer/structured-uncertainty.git)
cd structured-uncertainty
python3 -m pip install — user — no-deps — editable .*
现在,您已经设置了环境、班次库和结构化不确定性库,应该为下一步做好准备了。
3.下载数据和基线
现在您已经设置了您的存储库,您可以下载培训和开发数据以及基线模型。注意,下载数据的脚本也做一些初始预处理。
要下载培训和发展数据,请运行预处理脚本:
*chmod +x ./shifts/translation/data/prepare_data.sh ./shifts/translation/data/prepare_data.sh*
这将对数据进行预处理,将所有训练数据合并为一个数据,并从训练数据中移除重复和复制的示例。接下来,下载基线模型:
*wget [https://storage.yandexcloud.net/yandex-research/shifts/translation/baseline-models.tar](https://storage.yandexcloud.net/yandex-research/shifts/translation/baseline-models.tar)tar -xf baseline-models.tar*
这将产生以下顶级目录结构:
*./
├── baseline-models
├── mosesdecoder
├── orig
├── shifts
├── structured-uncertainty
├── subword-nmt
└── wmt20_en_ru*
orig 、 wmt20_en_ru 和 baseline-models 目录应包含以下内容:
*orig
├── dev-data
│ ├── LICENSE.md
│ ├── newstest2019-enru-ref.ru.sgm
│ ├── newstest2019-enru-src.en.sgm
│ ├── reddit_dev.en
│ ├── reddit_dev.meta
│ └── reddit_dev.ru
└── train-data
├── 1mcorpus
│ ├── corpus.en_ru.1m.en
│ └── corpus.en_ru.1m.ru
├── WikiMatrix.v1.en-ru.langid.en
├── WikiMatrix.v1.en-ru.langid.ru
├── WikiMatrix.v1.en-ru.langid.tsv
├── commoncrawl.ru-en.en
├── commoncrawl.ru-en.ru
├── en-ru
│ ├── DISCLAIMER
│ ├── README
│ ├── UNv1.0.en-ru.en
│ ├── UNv1.0.en-ru.ids
│ ├── UNv1.0.en-ru.ru
│ └── UNv1.0.pdf
├── extra
├── news-commentary-v15.en-ru.en
├── news-commentary-v15.en-ru.ru
├── news-commentary-v15.en-ru.tsv
├── news.en
├── news.en.translatedto.ru
├── news.ru
├── news.ru.translatedto.en
├── paracrawl-release1.en-ru.zipporah0-dedup-clean.en
├── paracrawl-release1.en-ru.zipporah0-dedup-clean.ru
├── readme.txt
├── wikititles-v2.ru-en.en
├── wikititles-v2.ru-en.ru
└── wikititles-v2.ru-en.tsv
wmt20_en_ru
├── code
├── reddit_dev.en
├── reddit_dev.ru
├── test19.en
├── test19.ru
├── tmp
│ ├── bpe.reddit_dev.en
│ ├── bpe.reddit_dev.ru
│ ├── bpe.test19.en
│ ├── bpe.test19.ru
│ ├── bpe.train.en
│ ├── bpe.train.ru
│ ├── bpe.valid.en
│ ├── bpe.valid.ru
│ ├── reddit_dev.en
│ ├── reddit_dev.ru
│ ├── test19.en
│ ├── test19.ru
│ ├── train.en
│ ├── train.en-ru
│ ├── train.ru
│ ├── train.tags.en-ru.clean.tok.en
│ ├── train.tags.en-ru.clean.tok.ru
│ ├── train.tags.en-ru.tok.en
│ ├── train.tags.en-ru.tok.ru
│ ├── valid.en
│ └── valid.ru
├── train.en
├── train.ru
├── valid.en
└── valid.ru
baseline-models/
├── dict.en.txt
├── dict.ru.txt
├── model1.pt
├── model2.pt
├── model3.pt
├── model4.pt
└── model5.pt*
4。将数据预处理成 Fairseq 格式
既然您已经下载了数据,清理并预处理了它,现在必须将它转换成一个 Fairseq 特定的格式。这可以使用以下命令来完成:
*python3 structured-uncertainty/preprocess.py — source-lang en — target-lang ru — trainpref wmt20_en_ru/train — validpref wmt20_en_ru/valid — testpref wmt20_en_ru/test19,wmt20_en_ru/reddit_dev — destdir data-bin/wmt20_en_ru — thresholdtgt 0 — thresholdsrc 0 — workers 24*
如果您使用提供的基线模型,请使用以下命令进行预处理:
*python3 structured-uncertainty/preprocess.py — srcdict baseline-models/dict.en.txt — tgtdict baseline-models/dict.ru.txt — source-lang en — target-lang ru — trainpref wmt20_en_ru/train — validpref wmt20_en_ru/valid — testpref wmt20_en_ru/test19,wmt20_en_ru/reddit_dev — destdir data-bin/wmt20_en_ru — thresholdtgt 0 — thresholdsrc 0 — workers 24*
上面的命令使用基线模型附带的字典,这些字典与您通过运行前面几节中的脚本得到的字典略有不同。以上两个命令应该创建一个新目录' data-bin ',其结构如下:
*data-bin/
└── wmt20_en_ru
├── dict.en.txt
├── dict.ru.txt
├── test.en-ru.en.bin
├── test.en-ru.en.idx
├── test.en-ru.ru.bin
├── test.en-ru.ru.idx
├── test1.en-ru.en.bin
├── test1.en-ru.en.idx
├── test1.en-ru.ru.bin
├── test1.en-ru.ru.idx
├── train.en-ru.en.bin
├── train.en-ru.en.idx
├── train.en-ru.ru.bin
├── train.en-ru.ru.idx
├── valid.en-ru.en.bin
├── valid.en-ru.en.idx
├── valid.en-ru.ru.bin
└── valid.en-ru.ru.idx*
其中 测试 为域内开发数据集— 新闻测试 19测试 1* 为转移后的开发数据— reddit_dev 。*
5.模特培训
现在,如果您想要重新创建基线,可以运行以下命令:
*python3 structured-uncertainty/train.py data-bin/wmt20_en_ru — arch transformer_wmt_en_de_big — share-decoder-input-output-embed — fp16 — memory-efficient-fp16 — num-workers 16 — optimizer adam — adam-betas ‘(0.9, 0.98)’ — clip-norm 0.0 — lr 5e-4 — lr-scheduler inverse_sqrt — warmup-updates 4000 — dropout 0.1 — weight-decay 0.0001 — criterion label_smoothed_cross_entropy — label-smoothing 0.1 — max-tokens 5120 — save-dir MODEL_DIR — max-update 50000 — update-freq 16 — keep-last-epochs 10 — seed 0*
这用于产生基线,只有种子不同。如果你正在训练的 GPU 不是 V100 或 A100,那么很可能你不应该使用 FP16,因为这种模式在数值上可能不稳定。请注意,您可能希望使用不同的设置、不同的历元数或使用不同的体系结构来训练您的模型,因此该命令的详细信息可能会有所不同。
6.获得预测和不确定性估计
现在,您已经有了一个基线模型或您自己的模型的集合,您可以对单个模型或集合运行推理,如下所示。要运行单一模型基线:
*mkdir single
for i in test test1; do
python3 structured-uncertainty//generate.py wmt20_en_ru/ — path baseline-models/model1.pt — max-tokens 4096 — remove-bpe — nbest 5 — gen-subset ${i} >& single/results-${i}.txt
done*
要运行集合基线:
*mkdir ensemble
for i in test test1; do
python3 structured-uncertainty/generate.py wmt20_en_ru/ — path baseline-models/model1.pt:baseline-models/model2.pt:baseline-models/model3.pt — max-tokens 1024 — remove-bpe — nbest 5 — gen-subset ${i} — compute-uncertainty >& ensemble/results-${i}.txt
done*
注意,如果您正在使用 集合 ,您应该只使用“ —计算不确定性 ”标志。这产生了翻译的原始输出和相关的不确定性分数,然后需要进一步处理。所有文件都保存在目录“single”和“ensemble”中,结构如下:
*ensemble
├── results-test.txt
└── results-test1.txt*
7.模型评估和提交
既然您已经成功地用您的模型运行了推理,我们现在需要评估模型的输出并创建一个提交文件。请记住,test 是您的 newstest19,即非转移开发数据,而 test1 是 reddit_dev,即转移开发数据。我们将对这两个模型进行评估。
这可以通过运行以下脚本轻松完成:
*chmod +x ./shifts/translation/assessment/eval_single.sh
chmod +x ./shifts/translation/assessment/eval_ensemble.sh./shifts/translation/assessment/eval_single.sh
./shifts/translation/assessment/eval_ensemble.sh*
该脚本现在将修改单个目录和集合目录,如下所示:
*ensemble
├── results-test.txt
├── results-test1.txt
├── test
│ ├── aep_du.txt
│ ├── aep_tu.txt
│ ├── entropy_expected.txt
│ ├── ep_entropy_expected.txt
│ ├── ep_epkl.txt
│ ├── ep_mkl.txt
│ ├── ep_mutual_information.txt
│ ├── epkl.txt
│ ├── expected_entropy.txt
│ ├── hypo_ids.txt
│ ├── hypo_likelihoods.txt
│ ├── hypos.txt
│ ├── log_probs.txt
│ ├── logcombo.txt
│ ├── logvar.txt
│ ├── mkl.txt
│ ├── mutual_information.txt
│ ├── npmi.txt
│ ├── ref_ids.txt
│ ├── refs.txt
│ ├── score.txt
│ ├── score_npmi.txt
│ ├── tmp
│ ├── var.txt
│ └── varcombo.txt
└── test1
├── aep_du.txt
├── aep_tu.txt
├── entropy_expected.txt
├── ep_entropy_expected.txt
├── ep_epkl.txt
├── ep_mkl.txt
├── ep_mutual_information.txt
├── epkl.txt
├── expected_entropy.txt
├── hypo_ids.txt
├── hypo_likelihoods.txt
├── hypos.txt
├── log_probs.txt
├── logcombo.txt
├── logvar.txt
├── mkl.txt
├── mutual_information.txt
├── npmi.txt
├── ref_ids.txt
├── refs.txt
├── score.txt
├── score_npmi.txt
├── tmp
├── var.txt
└── varcombo.txt*
除了假设 id(hypo _ ids . txt)、引用( refs.txt )假设(hypo . txt)和假设可能性(hypo _ likelihoods . txt)之外,大多数输出都是代码产生的不同的不确定性度量。假设文件应该比参考文件长射束尺寸的倍数。例如,如果光束宽度为 5,那么假设文件应该比参考文件长 5 倍。
一旦我们获得了假设和(许多不同的)不确定性分数,我们就可以评估相对于参考文献的预测,然后创建提交文件。首先,让我们讨论如何评估模型。
使用 BLEU 和 GLEU 指标评估模型的性能。然而,BLEU 仅在语料库级别是鲁棒的,而 GLEU 在句子级别是鲁棒的。由于我们对评估每个翻译句子的质量感兴趣,我们的鲁棒性和不确定性质量的 联合评估 使用 GLEU。我们计算模型相对于适当的参考转录产生的每个假设的 GLEU。回想一下,该模型可以为每个输入产生多个平移假设(例如:如果波束宽度为 5,则每个输入 5 个)。我们分别通过取最大值或所有假设的加权平均值来计算最大(最佳)GLEU 和预期 GLEU。每个假设的权重可以用不同的方式计算。一种方法是对每个假设的长度归一化似然性进行指数化和归一化。这将产生一组总计为 1 的 5 个正权重。最后,我们在**联合域内和移位数据集(测试+测试 1 )上取平均 maxGLEU 或 expectedGLEU。****
现在,我们已经评估了我们的模型在联合域内和移位集上的预测质量,我们可以通过构建误差保留曲线来评估不确定性估计的质量。为此,我们首先通过从 100 中减去(这样越低越好),将我们的 GLEU 度量转换为“ GLEU 误差”。接下来,按照不确定性递减的顺序,用从神谕中获得的基本事实转录替换模型的预测,从而构建误差保留曲线,从而减少误差。理想情况下,模型的不确定性与其误差相关,因此误差最大的预测将首先被替换,随着更多预测被替换,这将产生平均误差的最大减少。这代表了一种混合的人类-人工智能场景,其中模型可以在困难的情况下向先知(人类)寻求帮助,并从先知那里获得关于这些例子的完美预测。
随着原始预测的保留部分减少,GLEU 误差也减少。最后,我们测量误差保留曲线下的面积(R-AUC)。保留曲线下面积(R-AUC)是一个用于联合评估对分布变化的稳健性和不确定性估计质量的指标。R-AUC 可以通过改进模型的预测来降低,使得它在任何给定的保留率下具有更低的总误差,或者通过提供与误差更好相关的不确定性的估计,使得最不正确的预测首先被拒绝。
在上面的保留曲线中,除了基于不确定性的排名,我们还包括了代表“随机”排名和“最佳”排名的曲线,前者不确定性估计值完全没有信息,后者不确定性估计值与误差完全相关。这些代表作为不确定性质量函数的 R-AUC 性能的下限和上限。根据评估数据(10 月 17 日相关数据)获得最低 R-AUC 的提交材料将胜出。
现在我们已经讨论了评估,让我们讨论如何创建提交文件。如果您已经运行了上面描述的所有内容,那么您的顶级目录中应该已经有一个“submission.json”文件了。该文件是通过运行以下命令创建的:
*python shifts/translation/assessment/create_submission.py ensemble/test ensemble/test1 — save_path ./submission-ensemble.json — beam_width 5 — nbest 5 — ensemble — uncertainty_metric SCR-PE*
这个脚本接受域内数据( 测试 ),然后是移位数据( 测试 1 ),保存路径,解码期间的波束宽度是多少( beam_width ),要使用的假设有多少( n_best ),是否使用了 集合 输出,以及要包含哪些不确定性度量()然后,该脚本将输出处理成一个 json-list 文件,其结构如下:
*jsn_list = [jsn0, jsn1, ..., jsonN]jsn0 = {‘id’: ‘001’,
‘hypos’: [hypo1, hypo2, hypo3],
‘uncertainty’: 9000}
hypo1 = {‘text’: “Кошка сидела на столе”,
‘confidence’: 0.3}*
然后可以在班次网站上提交该文件。注意,如果您使用自定义的不确定性度量,那么您必须修改这个脚本。
8.改进方向
这篇博客只涉及轮班挑战中机器翻译任务的基线方法。有几个方向可以带来有趣的发现和改进:
- 增强集合中模型的多样性。这可以通过使用测试时数据扩充来实现,例如 BPE 丢失或在测试时在每个系综成员中启用“正常”丢失。
- 考虑组合对数据做出不同假设的模型集合,如从左到右、从右到左自回归模型、非自回归模型和允许考虑任意分解顺序的模型,如 XL-Net [7]。
- 考虑调整和评估不需要使用模型集合的确定性方法[9]。
但是,你可以自由地找到自己的问题解决方案,只要他们遵守这里描述的和的规则和计算限制。
参考
[1] A. Malinin、N. Band、Ganshin、Alexander、G. Chesnokov、Y. Gal、M. J. F. Gales、A. Noskov、A. Ploskonosov、L. Prokhorenkova、I. Provilkov、v .刘冰、v .刘冰、Roginskiy、Denis、M. Shmatova、P. Tigas 和 B. Yangel,“转变:跨多个大规模任务的真实分布转变数据集”,2021 年。
[2] Andrey Malinin 和 Mark Gales,“自回归结构化预测中的不确定性估计”,ICLR 2021。
[3]萧,蒂姆·Z 和戈麦斯,艾丹·丹和加尔·亚林,“Wat heb je gezegd?用变分变压器检测非分布翻译”,贝叶斯深度学习研讨会,NeurIPS 2019
[4]王,刘硕,杨,王,晁,栾,黄波,孙,茅松,“基于不确定性的置信度估计改进回译”。2019
[5] Fomicheva,Marina 和 Sun,Shuo 和 Yankovskaya,Lisa 和 Blain,Frederic 和 Guzman,Francisco 和 Fishel,Mark 和 Aletras,Nikolaos 和 Chaudhary,Vishrav 和 Specia,Lucia,《神经机器翻译的无监督质量估计》,2020 年
[6]诺廷、帕斯卡尔和埃尔南德斯-洛巴托、何塞·米格尔和加尔、亚林。
“高维数据的原则性不确定性估计”,深度学习研讨会中的不确定性&鲁棒性,ICML,2020 年
[7]杨,,戴,子航,杨,,卡波内尔,海梅,萨拉赫丁诺夫,鲁斯和勒,郭五,“XL-Net:语言理解的广义自回归预训练”,NeurIP,S2019
[8] Joost van Amersfoort,Lewis Smith,Yee Whye Teh,Yarin Gal,“使用单一深度确定性神经网络进行不确定性估计”,ICML,2020 年