自动文本摘要:简化
了解自动文本摘要的世界
为什么是文本摘要?
以封面来判断一本书不是正确的做法…但是我想一个总结就足够了。
在一个互联网每天都在以惊人的数据量爆炸的世界里,能够自动汇总是一个重要的挑战。长文档、新闻文章、甚至对话的摘要可以帮助我们更快更有效地消费内容。自动文本摘要是自然语言处理中的一个新兴领域,在过去的几年中受到了广泛的关注。
inshorts : An innovative mobile app that converts news articles into 60 word summaries.
我不会讨论任何算法或实现的具体细节。这个博客是为那些想更深入了解这些文本摘要模型如何工作的好奇的少数人准备的。任何以前没有深度学习或 NLP 经验的人都可以肤浅地关注这个博客。即使对常用的 NLP 模型有初步的了解,也足以充分理解其细节。
文本摘要的类型
有两种类型的文本摘要方法,即提取的和抽象的。提取摘要本质上是从文本中挑选出最能代表其摘要的句子。摘要技术由于其起源于 20 世纪 50 年代,已经流行了相当一段时间。更多的是学习理解每个句子的重要性以及它们之间的关系,而不是试图理解文章的内容。
另一方面,抽象概括就是试图理解文本的内容,然后在此基础上提供一个摘要,这个摘要可能有也可能没有与原文相同的句子。抽象概括试图创建自己的句子,这无疑是向更像人类的概括迈出的一步。
那么具体是怎么做的呢?
用于提取和抽象概括的技术彼此相差甚远。如前所述,概括地说,提取摘要是一个句子排序问题,而抽象摘要在生成新句子时涉及更复杂的语言模型。
我个人认为抽取式摘要已经走到了尽头,现在大部分的研究焦点都集中在抽象摘要上,这实际上是一个更有趣的问题…只是我的看法!!)。所以我不会谈论提取摘要,但如果你仍然有兴趣阅读它,我会建议这个可怕的博客。
对于那些有学术写作的人来说,总结——产生一个简洁流畅的总结同时保留…
medium.com](https://medium.com/sciforce/towards-automatic-text-summarization-extractive-methods-e8439cd54715)
在过去的几年里,自从深度学习的到来,抽象概括,通过自然语言与机器的交互以及机器翻译都取得了很大的成功。我在这里提到了机器翻译和交互,因为它与抽象概括是并行的。所有这些技术将输入的句子编码成特征,然后试图生成不同的句子,即解码这些特征。
一种常用的基于深度学习的机器翻译模型是基于 LSTM 的带注意力的编码器解码器网络。这个骨架有各种成功的变体,每一个都有自己的优点和缺点。
该模型从基于 LSTM 的编码器开始,该编码器将句子转换成特征向量。解码器也由 LSTM 组成,负责产生输出,一次一个单词。解码器从编码器提供的特征向量开始,然后基于前一个字预测和 LSTM 输出来预测每个字。我们将注意力放在编码器功能上,以使它们更加特定于当前单词。
一个基于 LSTM 的编码器和解码器网络的工作原理的详细解释可以在这个博客中找到。
注意力机制正越来越多地被用于改善神经机器翻译(NMT)的性能…
towardsdatascience.com](/attention-based-neural-machine-translation-b5d129742e2c)
好像都想通了!!
可惜,没有!生成新句子是一个复杂的过程,机器还没有掌握。抽象概括的一个问题是要编码的句子的长度。虽然 LSTMs 有能力捕捉长期和短期环境,但是它们对什么可以被认为是长期的也有限制。这使得总结非常长的文档变得困难。
摘要的另一个天文上的重要问题是它不应该包含与输入文本相矛盾的事实。摘要永远不会面临这个问题,因为它们直接从文本中提取句子。但是抽象概括容易出现这种事实上的不一致。
例如,如果一个抽象的摘要模型看到像德国 3–2 法国、英国 3–2 葡萄牙等句子。在测试时进行训练,它可能会预测西班牙 3–2 巴西,即使输入文本中的实际分数是 1–2。这是因为 1–2 不是模型词汇表的一部分,但 3–2 是。
听起来很糟糕!!
抽取式摘要缺乏创建自己的句子的能力,而抽象式摘要无法克服自身创建完整句子的复杂性。最近,在一个名为“指针生成器网络”的网络中,提出了一种介于这两个极端之间的非常有创意的方法。
更简单地说,作者以这样一种方式创建了网络,它对下一个预测单词应该是什么提出了两种不同的概率分布。第一个是基于模型的词汇,而第二个是基于输入文本中的词汇。然后将这两者结合起来得到最终的分布。你可以在这里进一步了解这个模型的细节。
这是一篇关于我们最新论文的博客文章,直入主题:用指针生成器网络进行总结,看起来…
www.abigailsee.com](http://www.abigailsee.com/2017/04/16/taming-rnns-for-better-summarization.html)
下一步是什么?
如果你观察一些抽象概括的最新成果,你会发现它们做得相当不错。但是它们只适用于某些类型的文档,而对于其他类型的文档则非常失败。在这一点上,最大的挑战之一是能够从编码特征中创建语法连贯的句子,这是抽象摘要和机器翻译的核心部分。
这个博客是为机器学习领域创建简化介绍的努力的一部分。点击此处的完整系列
在你一头扎进去之前就知道了
medium.com](https://medium.com/@prakhargannu/machine-learning-simplified-1fe22fec0fac)
或者干脆阅读系列的下一篇博客
看一眼自动化唇读的世界(ALR)
towardsdatascience.com](/automated-lip-reading-simplified-c01789469dd8)
参考
[1]卢恩,汉斯·彼得。"文献摘要的自动生成."IBM 研究与发展杂志 2.2(1958):159–165。
[2]Luong、Minh-Thang、Hieu Pham 和 Christopher D. Manning。"基于注意力的神经机器翻译的有效方法."arXiv 预印本 arXiv:1508.04025 (2015)。
[3]参见 Abigail、Peter J. Liu 和 Christopher D. Manning。"抓住要点:指针生成器网络摘要."arXiv 预印本 arXiv:1704.04368 (2017)。
数据科学家的自动版本控制
我为学习者写了一份名为《强大的知识》的时事通讯。每一期都包含链接和最佳内容的关键课程,包括引文、书籍、文章、播客和视频。每一个人都是为了学习如何过上更明智、更快乐、更充实的生活而被挑选出来的。 在这里报名 。
数据科学最棒的部分之一是从头到尾经历一个完整项目的冒险。从数据清理开始,到可视化,到特征构建,最后,训练机器学习模型。一个伟大的数据科学家的技能非常抢手,他拥有的高薪。
所有这些中的一个主要挑战是组织。
如今,数据科学家都是以小组形式工作,每个小组至少有几个成员。他们中的每一个人都在利用相同的数据,建立在彼此的工作基础上。
The many different components of great Data Science
不幸的是,数据科学团队成员经常在他们自己的小仓库中工作。他们创建自己的代码库,运行自己的 Jupyter 笔记本,并显示自己的可视化。在某种程度上,他们匆匆忙忙地将所有的信息融合在一起,形成了最终的报告。退一步说,这种配合并不完美。
但是一定有更好的方法。某种类型的系统或工具,允许大量处理数据和图形的人,即数据科学家,高效地与他们团队的其他人一起工作,以彼此的工作为基础。该系统需要灵活、易于使用,并且不会中断数据科学工作流程。
让我们看看我们能做些什么……
git 如何为数据科学服务
在常规的老软件工程团队中, Git 是组织代码、项目和团队协作的常用工具。团队成员在他们自己的本地代码上工作,但是总是与中央存储库同步他们的进展和新的开发。
这确保了每个人都是最新的和同步的。这是一个很好的方式,让团队的工作互相配合,而不是互相冲突,从而导致更高的产出。
Git flow. Team members work on their own “Feature” branches which are then all synced up in the “Develop” branch. Once the Develop branch is nice and polished, the production version of the code is synced up with Master.
数据科学有点棘手,因为它是研究和软件工程的结合:
- 数据本身很大,因此共享存储数据会很有挑战性。Git-LFS 有所帮助,但是使用起来相当慢。
- 大多数时候,代码变化很小,但是可视化效果看起来完全不同。Git 不允许显示从提交到提交的图形变化
- 数据科学家通常使用 Jupyter 笔记本。在 GitHub 上可视化笔记本的变化很可怕。它显示了。ipynb 文件,但不是我们在笔记本中发现有用的图表上的实际代码。
综上所述,我们可以开始了解一个好的数据科学版本控制系统应该是什么样子。
首先,我们寻求易用性。 DevOps 和后端工程师可能非常精通 git,但是数据科学更倾向于研究而不是工程。处理代码冲突应该特别顺利。
我们还想看看数据科学项目中的实际变化是什么。看到代码更改是好的,但这并不能说明全部情况。如果团队使用的是 Jupyter 笔记本,那就更是如此了,从视觉上看,代码太复杂了,无法告诉我们关于一些图表或数据操作是如何变化的。
最后,中央数据存储或工作平台非常有用。如果没有中央存储,数据科学家将不得不一直下载并准备自己的数据副本,这对于大型数据集来说效率非常低。
记住这些,我们现在可以研究一个解决方案
在数据科学中使用 Git 的平台
为数据科学准备版本控制系统的一个很好的选择是土星云平台。有了它,多名数据科学家可以在同一台 Jupyter 笔记本上工作,使用相同的数据集,但运行在他们自己的机器上。
数据科学协作
首先,我们将创建自己的托管 Jupyter 笔记本,任何有链接的人都可以访问。创建帐户后,下面的视频将向您展示如何操作。
Creating a hosted Jupyter Notebook
一旦我们建立并运行起来,我们就可以开始运行我们的 Jupyter 实验室了。一旦打开,您应该看到您的项目文件夹已经设置。
对于这个实验,我们将使用 2018 Kaggle ML 和 DS 调查数据集。该数据集由超过 23,000 个针对数据科学家和机器学习从业者提出的一系列关于薪酬的问题的多项选择答案组成。
数据集中一些有趣的事实:
- “数据科学家”的薪酬最高,高于“数据工程师”和“研究科学家”
- 科技公司的薪酬最高,其次是营销和金融
- 更多的经验和更高的教育会增加工资
- 美国的薪酬最高,其次是瑞士和澳大利亚
你可以点击查看 Jupyter 数据科学补偿的完整笔记本。
Data Scientist compensation
要开始团队协作,请转到您的仪表板,点击协作者链接。在其中,您将发现通过 Saturn Cloud 用户名向您的项目添加合作者的能力。
将用户添加到您的项目中会向他们发送一封个人电子邮件,邀请他们参与项目协作。一旦他们接受邀请,他们自己的云实例将会用完全相同的设置、库和软件来创建。
用户(数据科学家)可以立即访问他们自己版本的项目 Jupyter 笔记本和数据集。这使得多名数据科学家可以在相同的环境中工作,使用相同的数据,并以相同的起点开始他们的笔记本电脑!
Collaboration for Data Scientists
数据科学版本控制
现在我们可以进入土星云的版本控制系统。
一旦在您的实例上打开 Jupyter 实验室,您将看到您的工作界面。在屏幕的左侧有一个项目文件夹。在该项目文件夹中创建并保存的任何 Jupyter 笔记本都将自动启用版本控制。我已经把我的ds _ jobs . ipynb笔记本放到了项目文件夹中,以便在上面启用版本控制。
为了展示版本控制是如何工作的,我们将修改一些数据可视化。我们将假装只对欧洲国家的数据感兴趣,并过滤掉其他一切。一旦可视化被改变,我们将能够把我们的改变推送到一个远程的 git 存储库。下面这个 45 秒的视频展示了如何做到这一点!
Data Science Version Control
太好了!
我们能够对我们的 Jupyter 笔记本进行一些快速简单的修改。所有项目合作者(数据科学家)都可以访问该笔记本。因此,无论他们何时登录,他们都将能够看到您所做的更改,并可以选择提取这些更改,以便他们能够保持最新状态!
按需数据科学—倒带
另一个很棒的功能是倒带功能。它的工作方式类似于 git reset ,它基本上只是恢复我们的更改,这样我们就可以回到以前的状态。如果你觉得自己犯了一个错误,想要回滚,或者只是想看看以前的情况,这是非常有用的。
假设我们想要回滚到我们的可视化,显示数据科学补偿的所有区域。我们将再次点击右下角的 git 按钮。这一次,点击就可以倒带这个资源库的链接。弹出一个滑块,您可以在其中选择希望回滚到的时间。一旦设置好,你就可以看到你的旧代码和图表了!
Rewinding Jupyter Notebooks
这才是控制!
喜欢学习?
在推特上关注我,我会在那里发布所有最新最棒的人工智能、技术和科学!也在 LinkedIn 上与我联系!
自拍的自动白平衡调节
时尚科学来拯救!(其中包括机器学习)
问题是相机真的很努力——但坦率地说,在呈现准确的肤色方面经常失败。在我的例子中,为智能手机建立一个个性化的颜色推荐工具,我要求肤色要像皮肤一样。
Before and After Automatic White Balance Adjustment
下次你在脸书的时候,看看人们给自己的图片。它们离我们有多远,以及人类大脑是如何适应这种情况的,真是不可思议。
为了说明这一点,举例来说,Photoshop 确实有多种颜色校正算法。不幸的是,它们并不总是有效,最终的方法要求一个人在图像中找到一个灰点。我们确实有他们没有的优势——我们知道这张照片是自拍,我们知道如何提取肤色——相信我,文章就要来了。
Accurate skin colors
我们来看一些数据。随附的图表显示了在受控灯光下精心制作的一系列模特的肤色。很明显,这里有一个很好的模式。
我进一步指出,这代表了人性和大致的肤色范围。
Real-life Model Results plotted against Baseline Models
那又怎样?
这是上面的同一组数据,现在用红 x 表示。(简化为二维,红色对绿色。)肉色圆点来自用 iPhone 拍摄的现实生活中的模特。有些很离谱——他们是人类吗?
但是更好的是——它们都来自同一个人!
谁知道这种变化来自哪里——照明类型/温度、照明位置、曝光、相机显影处理等等。有很多变化。
顺便说一下,我们从我们的应用程序“所有的眼睛都在色调上”收集了超过 10 万张模型图像(在匿名的承诺下)用于分析。显示的测试集是一个用户在不同条件下拍摄了大约 20 张自拍。谢谢匿名人士!
所以首先,一个工作定义白平衡。见鬼,去维基百科,搜索“色彩平衡”以获得更好的定义。m 定义是图像在红色、绿色和蓝色通道中被线性地独立破坏。通过将每个像素乘以每个 RGB 通道的白平衡调整因子,我们可以校正图像。那三个线性调整——姑且称之为 R wb ,G wb ,B wb 。是的,这显然是一种简化——但它似乎在大多数情况下都能产生足够好的结果。
解决方案 1
校正图像的一个简单方法是:
- 识别模特的肤色
- 确定基线中最接近“好”模特的肤色——上图中的红色 x
- 将模型的皮肤颜色拖到最接近的“好”模型上。
就是这样。数学很简单。这很有效——我们每次都能得到“人类”的肤色。顺便说一下,我有一个俗气的 iOS 应用程序可以做到这一点——更好的 Selfie⁴.
但是等等…
我想我在上面的图表中提到过,所有这些变异都来自同一个人。将每种肤色拖到最接近的“好”肤色会给我们好的肤色——但不是他们的那种,真正的肤色。这就是我想要的!让我们重新定义这个问题——我们希望将所有这些不同的肤色统一为一种肤色。
顺便说一下,为了测试我们的方法,我们将假设正确的“好”答案是使用解决方案 1 的所有校正肤色的平均值。
解决方案 2
机器学习 101。获取大量训练数据来训练模型。完成了。
我们的训练数据从之前显示的“好”模型开始。每种肤色都有特定的平均 RGB 值。它的白平衡校正系数为 1.0、1.0、1.0。也就是说,不需要进行白平衡校正就可以将其校正到良好的肤色。
我们需要的是一个涵盖可能的“坏”肤色范围的训练集,以及相应的白平衡校正因子,以将其移回“好”肤色。我们要做的是用不同的白平衡因子生成糟糕的合成肤色。例如,如果我们想创造一个合理的“坏”肤色,我们可以将“好”肤色乘以 1.1、0.9、1.05。用于回到“良好”状态的白平衡与此相反,即 1/1.1、1/0.9、1/1.05。很简单。
Synthetic Training Set
创建大型数据集有不同的方法。一种方法是在可能的范围内使用高斯分布。另一种方式是三角形分布(numpy . random . normal/numpy . random . triangular)。我们最终得到的是一大组训练数据。
这里有价值的优化是创建训练集,以便覆盖预期的“坏”肤色,但仅此而已。这使我们能够将我们的训练数据点集中在它做得好的地方。(我觉得那是个专业术语。)
从这里让我们跳到 Python。
cls = Classifier()cls.fit(X_train, y_train)predictions = cls.predict(X_test)
我们需要的是训练许多可能的分类器中的一个。这些来自 scikit-learn 库以及一些定制的神经网络方法。以下是各种方法的结果:
上面的列表示:
- 方法——实际使用的分类方法。比如线性回归参考 sk learn . Linear _ model . Linear Regression,后面三个解释一下。
- 相同模型的均方误差—根据我们之前对正确答案的定义,这显示了我们的预测结果与该平均值的均方误差。越低越好。
- 集群——请记住,我们的目标不仅仅是获得“好”的肤色,而是获得一个“好”的肤色。事实证明这是不可能的——但是 3 比 10 好——我们仍然可以解决这个问题。顺便说一句,我们使用肘方法来确定集群的数量——“没有肘”意味着没有一个明确的答案。
最后三个分类器是使用 Keras 定制的神经网络。
- 仅 DNN 平均颜色-这是一个密集的神经网络,输入仅为肤色 RGB,输出为白平衡校正
- CNN-仅图像-这有一个 CNN 输入来开始拍摄眼睛周围的图像,包括大量的肉,输出是白平衡校正。这个想法是,见鬼,让 CNN 发挥它的魔力,也许加入一些眼睛的颜色——巩膜和虹膜。
- CNN +标量注入——这是上述两种方法的结合。每一个都有其相应的输入,但它们加入了一个密集的神经网络,以产生白平衡校正的输出
正如你从图表中看到的,DNN 平均颜色比其他方法都要好。
所以我们仍然有 3 个集群,我们需要 1 个…
好吧,所以这不能完全解决我们的问题。对于正确的肤色,我们得到的不是一个事实,而是三个潜在的事实。我只想说,不是同一个人的每一个可能的损坏图像都可以被校正到一个肤色,而不需要比单个图像提供的更多的知识。
所以我又变了两个戏法:
- 训练美国有线电视新闻网检测非常糟糕的图像。这是基于完整的自拍图像,我将图像分类为不可接受或可接受。不可接受的原因是明亮照明、黑暗照明和眩光等因素。与白平衡关系不大,但对更广泛的目标(为个人创建个性化的最佳调色板)很重要的是不可接受的元素,如眼镜和阴影。这个 CNN 在过滤掉明显不好的图像方面做得很好,我们可以要求用户拍摄另一张图像。
- 手动将“好”肤色的数量限制在一个能够产生“一个”答案的数量,而不会过度限制所有人看起来相似。
还不错!
总之,这是一种自动白平衡校正的强大方法。
未来的方向实际上只是机器学习 101 方向,即模型和更多数据点的调整。
Sample Before/After Selfies
脚注
https://www.youtube.com/watch?v=B-W44JJToG8
http://johnthemathguy . blogspot . com/2013/08/what-color-is-human-skin . html
https://itunes.apple.com/us/app/better-selfie/id999484452 的⁴
自动分析实验室测试数据
教程:自动分析实验室数据以创建性能图
如何编写为您执行数据分析的 Python 程序
科学家发现自己拥有大型数据集是很常见的。有时,它以单个文件中数千兆字节数据的形式出现。有时是数百个文件,每个文件包含少量数据。无论哪种方式,都很难管理。很难理解。你的电脑很难处理。您需要一种方法来简化这一过程,使数据集更易于管理,并帮助您跟踪一切。
这就是本教程的内容。我们正在编写 Python 脚本,它将自动为您分析所有数据,并以有意义、直观的文件名存储数据。同时使用来自实际研究的例子,这样你就知道你正在发展的技能是实用和有用的。
本教程的第一篇文章介绍了本教程的概念。如果“热泵热水器”、“性能系数(COP)”和“性能图”这些术语对你来说毫无意义,你可能想读一下。
第二篇文章介绍了的配套数据集,将数据集分割成多个文件,并使用用户友好的名称。
伴随数据集是教程过程中有价值的一部分,因为它允许您跟随。您可以编写与我将要展示的完全相同的代码,运行代码,查看结果,并与我展示的结果进行比较。这样你就能确保你做得对。
在本教程的第二部分结束时,我们现在有三个数据文件,每个文件都包含指定环境温度下的测试结果。在这些文件中,我们可以看到热泵的耗电量、储水箱中的水温以及热水器周围的空气温度。
下一步是处理这些结果。我们需要编写一些代码来自动理解数据,计算热泵的 COP,并绘制数据,以便我们可以直观地理解它。
事不宜迟,我们开始吧。与所有 Python 编程一样,我们需要首先导入包。
我需要导入什么包?
这里有几个对这一步非常重要的包。它们是:
- glob 是一个列表创建包。它读取存储在文件夹中的文件,并创建一个包含所有这些文件的列表。因为 Python 非常擅长遍历列表,所以我们可以使用 glob 来创建所有数据文件的列表,并让 Python 一次分析一个。
- 熊猫:需要我说明这个包裹的重要性吗?pandas 是 Python 中数据分析工具的黄金标准。
- os : os 让我们可以访问操作系统命令。这听起来很吓人,因为使用它你可能会把你的电脑搞砸。不用担心;我们将只使用它来检查和添加文件夹。
- numpy 是一个伟大的数字包,它支持强大的数据分析工具。在这个特定的例子中,我们将使用 numpy 来创建数据回归。
- bokeh 是 Python 中的一个交互式绘图工具。它使您能够编写在分析数据时自动生成图的代码,并为用户提供与它们交互的选项。进一步了解散景的一个很好的来源是用散景进行实际数据可视化。
在本教程的这一部分,将不会在脚本中使用散景;然而,这个相同的脚本将是未来部分的基础。现在导入散景是值得的,这样你就不用担心它了。
对于这个项目,我们需要导入整个 glob,pandas,os 和 numpy,而只从 bokeh 导入某些功能。这些都可以使用以下代码调用:
import glob
import pandas as pd
import os
import numpy as np
from bokeh.plotting import figure, save, gridplot, output_file
注意,pandas 被导入并分配给 pd,numpy 被分配给 np。这意味着我们现在可以通过写“pd”和“np”来引用这些包,而不是熊猫和 numpy。
既然我们所有的包都被导入了,下一步就是创建我们的 glob list 和 for 循环来依次遍历所有的文件。准备好后,您就可以编写代码来分析我们的每个数据文件了。
我如何遍历我所有的文件?
第一步是配置 glob。为此,您需要为 glob 提供一个路径和一个文件类型(文件类型是可选的,但是我们的所有数据都在。csv 格式,所以我们希望指定它以避免包含无关文件)。然后当你调用 glob 时,它会在指定的文件夹中创建一个该类型的所有文件的列表。这可以使用以下代码行来完成:
Path = r'C:\Users\YourName\Documents\AutomatingDataAnalysis\Files_IndividualTests'Filenames = glob.glob(Path + '/*.csv')
Path 变量告诉 glob 在指定的文件夹中查找相关的文件。请注意,上面指定的文件夹与您在本教程第一部分中保存文件的文件夹相同。
第二行调用 glob 包中的 glob 函数来创建所有指定文件的列表。请注意,代码引用了您指定的 Path 变量来说明 glob 应该在哪个文件夹中搜索文件。接下来是声明 glob 应该包含所有。csv 文件,没有别的。
这段代码完成后,glob 将创建一个包含所有。文件夹中的 csv 文件。它将具有[1.csv,2。csv,3.csv,…,n.csv】。对于那些已经下载了配套数据集并正在跟随教程的人来说,它将是 PerformanceMap_HPWH_55.csv、PerformanceMap_HPWH_70.csv 和 PerformanceMap_HPWH_95.csv 的完整路径
现在您已经有了一个文件列表,下一步是创建一个 for 循环来遍历这些文件。然后,您需要打开这些文件,以便可以对每个文件执行数据分析。为此,您需要以下代码:
for Filename in Filenames:
Data = pd.read_csv(Filename)
这段代码自动遍历文件名列表中的每个条目。请注意,这种编写方式导致 Filename 保存列表中每个条目的实际文件名。例如,第一次通过 For 循环时,文件名将包含 PerformanceMap_HPWH_55.csv 的完整路径。
第二行代码使用 pandas 将文件读入内存,并保存到数据中供以后分析。
既然文件已经定位并按顺序打开,下一步就是添加分析每个文件的代码。这将是我们的下一步。
如何编写代码来自动分析每个文件?
除了 Python 编程知识之外,这还需要大量关于正在研究的设备的知识。因为我假设你不是 HPWHs 的读者,我会确保写出相关信息。
过滤数据以仅包含重要部分
对于此过程,我们只关心 HPWH 中的热泵处于活动状态时的数据。这些设备中的热泵通常消耗 400–600 W,具体取决于环境温度和水温。同时,他们有消耗一些电力的机载电子设备。为了将数据过滤到我们所关心的部分,我们需要移除功耗小于 300 W 的所有数据,该功耗被选择为显著高于板载电子设备的功率消耗,但低于热泵的最小消耗。我们可以使用下面的代码行来实现这一点:
Data = Data[Data['P_Elec (W)'] > 300]
这一行重置了我们的数据帧,使仅包含器件功耗超过 300 W 的数据。但这确实影响了数据帧的索引,因此我们需要重置它,以保持数据帧干净。为此,我们可以使用以下代码:
Data = Data.reset_index()
del Data['index']
识别测量之间的时间变化
现在,这个数据集中的时间戳数据不容易处理。幸运的是,我们从与实验室测试伙伴的合作中了解到,测量每 10 秒进行一次。因此,我们可以使用以下代码在数据框中创建一个新列,说明测试已经进行了多长时间:
Data[‘Time Since Test Start (min)’] = Data.index * 10./60.
计算储存在水中的能量的变化
影响 HPWHs COP 的一个关键参数是储水箱中的水温。水混合得不够好,无法保持一个恒定的温度。通常情况下,水箱底部是冷水,顶部是热水。为了这个练习,计算水箱的平均温度就足够了。由于我们的实验室测试人员好心地通知我们,他使用了 8 个均匀分布在水箱中的温度测量值,我们可以使用以下公式计算平均水温:
Data['Average Tank Temperature (deg F)'] = (1./8.) * (Data['T1 (deg F)'] + Data['T2 (deg F)'] + Data['T3 (deg F)'] + Data['T4 (deg F)'] + Data['T5 (deg F)'] + Data['T6 (deg F)'] + Data['T7 (deg F)'] + Data['T8 (deg F)'])
现在,我们真正关心的是水箱的平均温度在不同的测量时间有多大的变化。这样,我们可以确定储存在水箱中的能量的变化,从而确定热泵增加到水中的能量。我们可以使用下面两行代码来实现这一点:
Data['Previous Average Tank Temperature (deg F)'] = Data['Average Tank Temperature (deg F)'].shift(periods = 1)
Data.loc[0, 'Previous Average Tank Temperature (deg F)'] = 72.0
第一行使用。pandas 数据框的 shift 命令,用于在包含“平均油箱温度(华氏度)”数据的数据框中创建一个新列,但在数据框中下移一行。这会在第一行(索引 0)中创建一个空单元格,这会在执行计算时导致错误。第二行代码通过使用。用 72.0 填充此单元格。我们能做到这一点是因为我们友好的实验室测试人员告诉我们,每次测试都是在华氏 72.0 度时开始的。
现在我们可以计算每两个时间标记之间储存在水中的能量的变化。为此,我们需要知道一些常数和方程:
- 首先,用能量=质量比热(最终温度-初始温度)来确定水中能量的变化
- 第二,我们知道 HPWH 的储存罐容纳 80 加仑(再次感谢我们友好的实验室测试人员的交流),
- 第三,水的密度是 8.3176 磅/加仑,并且
- 第四,水的比热是 0.998 Btu/lb-F。
我们可以将所有这些放在一起,用下面这条线计算储存能量的变化:
Data['Change in Stored Energy (Btu)'] = (80 * 8.3176) * (0.998) * (Data['Average Tank Temperature (deg F)'] - Data['Previous Average Tank Temperature (deg F)'])
计算 COP
分析每个数据集的下一步是计算作为水箱水温函数的 COP。本教程的目标是将 COP 确定为水温和环境温度的函数,这将有助于理解在每个指定的环境温度下 COP 作为水温的函数。它指向正确的方向。
为了计算热泵的 COP,我们需要进行一些单位转换。耗电量目前以 W 表示,而添加到水中的能量目前以 Btu/时间步长表示。为了进行单位转换,我们使用 1 W = 3.412142 Btu/hr 的比率,然后将 Btu/hr 转换为 Btu/s,并乘以每个时间戳的 10 秒。这给出了代码:
Data['P_Elec (Btu/10s)'] = Data['P_Elec (W)'] * (3.412142/60/60) * 10
根据定义,COP 是添加到水中的热量除以消耗的电量。因此,可以通过下式计算:
Data['COP (-)'] = Data['Change in Stored Energy (Btu)'] / Data['P_Elec (Btu/10s)']
生成回归
现在我们有了一个表格,显示了三个指定 COP 中每一个 COP 与水温的函数关系。但是我们可以做得更好。如果有一个函数可以用来计算 COP 不是很好吗?只需输入水温,并据此识别 COP?
Numpy 提供了使这变得容易的工具。我们可以使用数字函数“polyfit”来确定将 COP 描述为水温函数的折射率系数。这是一个灵活的函数,允许您通过指定函数末尾的顺序来控制曲线的形状。因为热泵的 COP 作为温度的函数是抛物线,所以我们需要对这个例子进行二阶回归。因此,系数可以用下面一行来标识:
Coefficients = np.polyfit(Data[‘Average Tank Temperature (deg F)’], Data[‘COP (-)’], 2)
numpy“poly 1d”函数可用于使用这些系数创建回归。这通过以下方式完成:
Regression = np.poly1d(Coefficients)
现在,您可以使用这种回归方法确定热泵在特定水温下的 COP。请记住,仅针对特定的气温生成回归,因此仅使用正确气温的回归来估计 COP。创建二维性能图是本教程的最终目标,但我们还没有达到。
特定水温下的 COP 可以通过调用函数并使用水温作为输入来识别。例如,如果您想在水温为 72°F 时查找 COP,您可以输入:
COP_72 = Regression(72.0)
我如何保存这些结果?
可以使用我们一直使用的相同技术保存数据,如自动存储来自分析数据集的结果中所述。我们需要 1)确保分析结果的文件夹可用,2)创建一个新的文件名,清楚地说明文件包含的内容,3)保存数据。
在这种情况下,我们希望将数据保存到一个名为“已分析”的新文件中。它应该在同一个数据文件夹中,并用来显示分析的结果。我们可以用下面的代码做到这一点:
Folder = Path + '\Analyzed'
if not os.path.exists(Folder):
os.makedirs(Folder)
第一行创建新文件夹的路径。它将’ \Analyzed '添加到当前存在的路径中,声明它正在当前文件夹中查找一个名为“Analyzed”的文件夹。第二行确定该文件夹是否已经存在。如果没有,第三行创建它。
之后,我们需要为数据集和系数设置文件名。这可以通过将我们已经拥有的与字符串的一个子部分相结合来实现。我们可以使用字符串索引来标识我们想要保留的文件名部分。例如,第一个文件的文件名部分“PerformanceMap_HPWH_50”非常清楚地说明了文件包含的内容。因为我们知道文件名的最后四个字符是。我们可以通过使用索引[-26:-4]来分离字符串的这一部分。换句话说,我们希望字符串中的字符从“倒数第 26”到“倒数第 4”,不包括倒数第 4。
接下来,我们可以定制一点文件名。也就是说,我们可以声明我们希望数据文件名声明它包含分析数据,我们希望系数文件名声明它包含系数。我们可以用下面几行写下这两个文件的文件名:
Filename_Test = Folder + '\\' + Filename[-26:-4] + '_Analyzed.csv'
Filename_Coefficients = Folder + '\Coefficients_' + Filename[-6:]
然后我们简单地保存文件。分析后的数据可以和熊猫一起储存。to_csv 函数,系数可以用 numpy 保存。tofile 函数如下:
Data.to_csv(Filename_Test, index = False)
Coefficients.tofile(Filename_Coefficients, sep = ‘,’)
请注意,保存数据集的行 index = False。这意味着保存表时不会保存数据框的索引。还要注意 numpy。tofile 函数要求您指定一个分隔符。在这种情况下,我们使用一个逗号,用代码 sep = '、 指定。
我怎么知道它工作正常?
在流程的这个阶段,有大量的事情可能会出错。也许实验室测试人员在进行实验时犯了一些错误。可能是乐器坏了。也许代码中有一个错别字,或者一个不正确的单位转换。
必须确保在这个过程中不出现这些问题或任何其他问题。因此,该过程的下一步是检查数据集的错误。我们将在教程的下一阶段讨论这个问题。首先,我将讨论如何手动检查数据错误。这样,你将对我们正在检查的潜在错误以及如何识别它们有一个明确的理解。然后我将讨论如何在这个脚本中添加代码来自动检查这些错误,并在出错时向您发出警告。
教程目录
这是一系列文章的一部分,教你自动分析实验室数据和绘制热泵热水器性能图所需的所有技巧。本系列的其他文章可以通过以下链接找到:
自动寻找最适合你的神经网络
甘斯的汽车!
想获得灵感?快来加入我的 超级行情快讯 。😎
生成对抗网络 (GANs)自从在 2014NIPS上首次发明并发表以来,一直是深度学习领域的热门话题。
这一切都有一个很好的理由:GANs 只需要一点点指导就可以创造新的内容。正是这种创造力让他们如此强大。事实证明,GANs 能够将这种创造力应用于多种多样且有用的应用中:
- 生成穿着某种服装的人的图像。非常适合虚拟观看顾客在网上看到的服装会是什么样子。
- 创建艺术品
- 电影和视频游戏的灌制和质量改进
- 加强对非常复杂的深层物理课题的研究,如暗物质
仅举几个例子。
有鉴于此,大量资源被投入到 GAN 研究中,以弄清楚它们是如何工作的,以及如何设计绝对最佳的 GAN 网络。最后,经过几年的成熟, AutoML 和神经架构搜索(NAS) 已经进入了 GANs 的领域。
本文接下来分为两个部分:第一部分解释了 GANs 是如何工作的,以及它们目前是如何手工设计的。第二个是全新深度学习研究的展示——AutoGAN,它将神经架构搜索应用于自动找到最佳的 GAN 架构。
gan 是如何工作的
生成对抗网络(GANs)被归入“生成”模型组。这意味着它们能够生成全新的“有效”数据。所谓有效数据,我们的意思是网络的输出应该是我们认为目标可以接受的。
为了说明,考虑一个例子,其中我们希望生成一些新图像来训练图像分类网络。当然,对于这样的应用,我们希望我们的训练数据尽可能真实,也许在风格上与其他图像分类训练数据集非常相似。
下图显示了 GAN 生成的一组图像的示例。它们看起来很真实!如果我们没有被告知它们是计算机生成的,我们可能会相信这些是人类收集的!
An example output of Progressive GANs. Source
为此,gan 由两个独立的、相对的网络组成:发生器和鉴别器。当仅给定噪声图像阵列作为输入时,生成器被训练来创建看起来逼真的图像。鉴别器被训练来分类图像是否是真实的。
GANs 的真正力量来自他们所遵循的对抗训练风格。基于鉴别器的损耗学习发电机网络的权重。因此,生成器被推动以这样一种方式训练,即对于它生成的图像,很难辨别它们是否真实。在这些图像看起来越来越真实的同时,鉴别器也越来越好地分辨出哪些图像是真实的,不管肉眼看起来有多相似。
因此,GANs 建立了一种反馈回路,发电机帮助训练鉴别器,鉴别器帮助训练发电机。他们一起变得更好。下图有助于说明这一点。
An illustration of the structure of a Generative Adversarial Network
请注意,生成器只是一个以图像为输出的 CNN,而鉴别器只是一个以分类概率为输出的 CNN 分类网络;很简单。由于这种简单性,大多数 GAN 架构只是其他先进深度网络的副本。生成器可能采取类似于修改的 U-Net 的形式,而鉴别器通常看起来像 ResNet、DenseNet 或类似的体系结构。
好的一面是,这可能会简化部分问题。研究科学家可以简单地借用以前经过验证的研究中的网络设计,并简单地专注于 GANs 的算法设计和训练机制。
另一方面,这可能有点限制。如果当前的网络设计不是最适合 GANs 的,该怎么办?它们本身工作得足够好,但也许改进网络结构可以进一步提高专为它们设计的 GAN 性能。
使用 AutoGAN 寻找最佳 GAN
神经架构搜索(NAS) 一直是另一个热门的深度学习话题。NAS 是搜索寻找最佳神经网络架构的算法。
大多数 NAS 算法以如下方式工作。
- 首先定义一组可用于我们网络的“构建模块”。
- 然后使用控制器递归神经网络(RNN)对这些构建块进行采样,将它们放在一起以创建某种端到端的架构。
- 然后,在特定数据集上训练和评估这个新建立的网络。
- 基于评估,RNN 选择的构建模块被调整,即 RNN 将选择新的一组,保留有助于准确性的模块和配置,并替换或移除没有帮助的模块和配置。
- 步骤 3 到 4 重复多次,直到找到最佳架构。
The NAS algorithm. Source from the research paper
AutoGAN 也遵循相同的学习方案,特别侧重于构建生成器网络,因为在寻找最佳分类网络(用于鉴别器)方面已经做了更多的工作。
正如作者在他们的论文中指出的,训练 GANs 由于其设计本身就不稳定。精心的网络建设对整个过程的顺利进行至关重要。考虑到这一点,AutoGANs 的搜索空间比 NAS 的搜索空间要小得多。AutoGAN 的生成器搜索空间被设置为,而不是能够从许多不同类型和大小的卷积块中采样并跳过连接:
- 一个二进制值 skip ,它指示当前单元格是否从前一个单元格获取一个加法skip 连接*。*
- 一个基本的卷积模块,决定是否包括预激活或后激活。
- 归一化类型的选择:批量归一化、实例归一化、无归一化。
- 要使用的上采样类型:双线性上采样、最近邻上采样或步长 2 去卷积。
- 是否使用单元格内 加法 跳过连接
The search space of AutoGAN’s Generator network. Source from the original research paper
有了这个更受控制的搜索空间,应用 NAS 来寻找最佳发电机架构就简单得多,也更稳定,因为 NAS 的搜索范围更广,也更简单。
另一项使培训更加有效的技术是使用多层次架构搜索(MLAS),而不是常规的多层次架构搜索(SLAS)。对于常规的 SLAS,一个 RNN 控制器将用于一次构建整个 NAS 网络。但是在 MLAS,网络是逐步建立起来的。
MLAS 以自下而上的方式执行搜索,对每个单元分别执行架构搜索。因此,每个细胞将使用其自己的个人 RNN 控制器进行搜索。从某种意义上说,这也简化了搜索,因为 NAS 一次只关注网络的一个特定部分,而不是非常复杂的整体。
AutoGAN’s RNN controller. Source from the research paper
凭借其聪明的新训练设置和精细、集中的细胞搜索空间,AutoGAN 能够实现最先进的结果。具体来说,它为基于人类判断生成高视觉质量的新图像设置了新的标准。
AutoML 正在慢慢进入深度学习和人工智能的许多领域。毫无疑问,这将是未来几年人工智能研究的一个重点。人工智能创造人工智能。
喜欢学习?
在推特上关注我,我会在这里发布所有最新最棒的人工智能、技术和科学!也请在 LinkedIn上与我联系!
使用 LSTM 自动生成酒店描述
Photo credit: W Seattle
如何使用 Python 中的 LSTM 递归神经网络和 Keras 创建文本生成模型
为了建立一个基于内容的推荐系统,我收集了西雅图 152 家酒店的描述。我在想一些其他的方法来折磨这个高质量的干净数据集。
嘿!为什么不训练我自己的酒店描述文本生成神经网络?即,通过实现和训练基于单词的递归神经网络来创建用于生成自然语言文本(即,酒店描述)的语言模型。
这个项目的目标是生成新的酒店描述,给定一些输入文本。我不期望结果是准确的,只要预测的文本是连贯的,我就高兴了。
感谢Shivam ban sal的这个教程帮助我完成了这个练习。
数据
desc_preprocessing.py
我们的数据集中总共有 152 个描述(即酒店)。
先看一下第一个描述:
corpus = [x for x in all_descriptions]
corpus[:1]
Figure 1
在标记化之后,我们可以:
- 探索单词及其计数的字典。
- 浏览单词词典,了解每个单词出现在多少个文档中。
- 探索用于适应记号赋予器的文档总数的整数计数(即文档总数)。
- 探索单词及其唯一指定整数的字典。
t = Tokenizer(num_words=None, filters='!"#$%&()*+,-./:;<=>?@[\\]^_`{|}~\t\n', lower=True, split=' ', char_level=False, oov_token=None, document_count=0)
t.fit_on_texts(corpus)print(t.word_counts)
print(t.word_docs)
print(t.document_count)
print(t.word_index)
print('Found %s unique tokens.' % len(t.word_index))
文本预处理
标记化
我们使用 Keras 的标记器来矢量化文本描述,
- 我们删除所有标点符号。
- 我们将文本转换成小写的空格分隔的单词序列。
- 然后,这些序列被分割成记号列表。
- 我们设置了
char_level=False
,所以每一个单词都会被当作一个记号而不是字符。 - 然后,记号列表将被索引或/和矢量化。
- 我们将语料库转换成符号序列。
sequence.py
Figure 2
上面的整数列表表示从语料库中生成的 ngram 短语。例如,假设一个句子“ 位于尤宁 湖的南端”由这样的词的索引来表示:
Table 1
填充序列并创建预测值和标签
- 将序列填充到相同的长度
- Pad sequences 将整数列表转换成形状为
(num_samples, maxlen)
的 2D Numpy 数组。 - 预测值和标签看起来像这样:
Table 2
如你所见,如果我们想要精确,这将会非常非常困难。
pad_sequence.py
建模
我们现在可以定义我们的单一 LSTM 模型。
- 具有 100 个存储单元的单个隐藏 LSTM 层。
- 网络使用概率为 10 的辍学。
- 输出层是使用 softmax 激活函数输出 0 到 1 之间的 3420 个单词中每个单词的概率预测的密集层。
- 我们的问题是具有 3420 个类别的单个单词分类问题,因此被定义为优化对数损失(交叉熵),并使用 ADAM 优化算法来提高速度。
- 没有测试数据集。我们正在对整个训练数据进行建模,以学习序列中每个单词的概率。
- 根据 Keras 文档,在生成的文本开始听起来连贯之前,至少需要 20 个历元。所以,我们要训练 100 个纪元。
text_generator.py
使用训练好的 LSTM 网络生成文本
- 关于这一点,我们可以编写一个函数,将种子文本作为输入,并预测下一个单词。
- 我们对种子文本进行标记,填充序列,并将其传递给训练好的模型。
generate_text.py
试试吧!
- 我随机选择“”作为种子文本,我希望 model 返回我接下来的 100 个单词。
*print(generate_text("hilton seattle downtown", 100, model, max_sequence_len))*
Figure 3
- 我选择“ 贝斯特韦斯特西雅图机场酒店 l”作为种子文本,并且我希望模型预测接下来的 200 个单词。
*print(generate_text("best western seattle airport hotel", 200, model, max_sequence_len))*
Figure 4
- 我选择“ 位于西雅图市中心 ”作为种子文本,并且我希望模型预测接下来的 300 个单词。
*print(generate_text('located in the heart of downtown seattle', 300, model, max_sequence_len))*
Figure 5
结论
- 没有拼写错误。
- 这些句子看起来很真实。
- 一些短语被一遍又一遍地重复,特别是预测给定种子的大量单词输出。
关于改进的一些想法:更多的训练数据、更多的训练时期、更多的层、更多的层存储单元、对于给定的种子,预测更少数量的单词作为输出。
Jupyter 笔记本可以在 Github 上找到。享受余下的周末吧!
参考资料:
这个类允许向量化文本语料库,通过将每个文本转换成整数序列(每个整数…
keras.io](https://keras.io/preprocessing/text/) [## 使用 LSTMs 的语言建模和文本生成 NLP 的深度学习
随着深度学习和人工智能领域的最新发展和改进,许多严格的…
medium.com](https://medium.com/@shivambansal36/language-modelling-text-generation-using-lstms-deep-learning-for-nlp-ed36b224b275)*
自动存储分析数据集的结果
如何存储数据分析结果以方便后期回归分析
这是教你如何编写自动分析科学数据的程序的系列文章的第五篇。首先介绍了概念和动机,然后规划了高级步骤。第二个教你如何构建数据集,使自动化数据分析成为可能,并自动识别每个测试的条件。的第三篇文章讨论了创建一个 for 循环,自动对每个测试结果执行计算并保存结果。第四篇文章覆盖了可能是最重要的部分:自动检查数据和分析错误。这第五篇文章将教你如何在一个逻辑文件夹结构中存储数据,使回归开发和验证数据的访问变得容易。
存储中间结果供以后分析
到目前为止,所有的讨论都集中在分析单个测试的结果上。下一步是开始考虑更大的图景,并创建将那些单独的测试结果组合成描述整个项目结果的数据集的方法。第一步是以逻辑方式存储各个测试结果,以便于以后的分析。
有两个通用的技巧来存储中间结果,供以后在自动化过程中进行分析。首先是规划组织结构,以确保在需要时可以轻松找到所有文件。第二种方法是在代码中使用动态文件名,这样程序每次迭代的结果都会保存到新文件中。
创建文件夹层次结构
规划组织结构实质上意味着创建一个对给定项目有意义的文件夹层次结构。例如,假设一个项目包括在多台设备上进行几个实验。目标是创建模拟每件设备性能的回归。在这种情况下,为每件设备创建一个文件夹,然后将单个测试的结果存储在相应的文件夹中是有价值的。图 1 提供了一个如何构建这个文件夹层次结构的例子。
Figure 1: Example Folder Hierarchy
使用动态名称存储文件
要记住的第二点是,所有对存储数据的引用都应该使用动态名称,这些动态名称使用第 2 部分中描述的技术从数据集中获取的变量来创建特定于该数据集的文件名。例如,数据集可能包含设备 2 测试 3 的特定数据。在这种情况下,任何保存该数据集数据的代码都必须使用变量来指定它需要使用“设备 2”文件夹的“设备 2 测试 3”子文件夹。
创建文件夹结构时,有必要确保所有文件夹都存在。有两种方法可以做到这一点。第一种是为项目手动创建文件夹,提前安排好一切。如果这有助于您思考整个过程并创建一个强大的结构,这可能是一个好方法,但这是一个关于自动化的系列!让 Python 来做这项工作更容易。通过在分析循环中包含适当的代码,可以自动创建该结构。这是通过以下步骤完成的。
1)导入操作系统包,允许访问控制计算机操作系统的命令。这可以用 Python 代码“import os”来完成。
2)在分析循环中,使用第 2 部分中的技术来确定正在执行的测试。以图 1 中的层次表为例,这可能会导致变量“设备”设置为“设备 2”,变量“测试”设置为“测试 3”。确保这两个值都以字符串形式存储在其变量中。
3)使用变量和来自数据集的输入为现有数据集指定文件夹。在我们当前的示例中,这可以通过以下代码来完成:
Folder = r’C:/Users/JSmith/DataAnalysis/’ + Equipment + ‘/’ + Test
4)使用 os.path.exists 命令确定该文件夹是否存在,如果需要,使用以下代码创建该文件夹:
if not os.path.exists(Folder) :os.makedirs(Folder)
这些步骤创建的代码将自动生成该结构所需的所有文件夹。根据任何给定项目的需要,可以使用相同的技术来创建更多级别的子文件夹。
然后,每个测试的结果需要存储在适当的文件夹中。保存结果的代码因包而异。使用下面的代码示例,可以用 pandas、bokeh 和 matplotlib 保存结果。
熊猫
数据帧有方便的标签。to_csv 函数。读者应该查阅 pandas 文档来了解如何工作的具体细节,但是一般的方法是调用函数并指定文件路径。对于当前示例和名为“data”的数据帧,这可以通过以下代码完成:
Data.to_csv(r’C:/Users/JSmith/DataAnalysis/’ + Equipment + ‘/’ + Test + ‘/’ + Equipment + ‘_’ + Test + ‘.csv’)
最后一部分,‘/’ +设备+ ‘_’ +测试+'。“csv”被添加到前面的代码中,以便为。csv 文件放在文件夹中。假设前面的代码用于定义变量 Folder,实现相同目标的一个更短的方法是:
Data.to_csv(Folder + ‘/’ + Equipment + ‘_’ + Test + ‘.csv’)
散景
散景使用一种更复杂的方法来保存文件。这提供了在单个文件中存储多个图的能力。使用以下步骤执行:
1)创建一个网格地块。gridplot 函数允许指定如何在一个文件中包含多个绘图。一个数组用于指定主 gridplot,而较小的数组可用于指定任何给定行内的多个 plot。例如,gridplot 的第一行有两个图,第二行有三个图,编程如下:
p = gridplot([[p1, p2], [p3, p4, p5]])
2)指定所需的文件位置和标题。继续设备 2 —测试 3 的例子,这可以用下面的代码来完成:
output_file(Folder + ‘/’ + Test + ‘.html’, title = Test + ‘.html’)
3)保存剧情。这是通过直观的 save()命令完成的。本例中保存绘图的语法是:
save(p)
matplotlib
matplotlib 使用一个非常简单的文件保存约定。命令是 plt.savefig()。此示例的语法是:
plt.savefig(Folder + ‘/’ + Test)
后续步骤
本文向您介绍了如何修改您的代码,以便在逻辑位置保存来自单个测试的数据。这为过程的下一阶段做好了准备,即使用数据生成回归。通过将数据存储在逻辑位置,您可以轻松地打开该数据,并将其用作以后回归分析的数据集。下一篇文章将讨论这个主题:如何创建、验证和记录数据集的回归。
自动总结特朗普的国情咨文
Photo credit: Pixabay
文本排名,潜在语义分析,Gensim,Sumy,NLTK
自动文本摘要,是为较长的文档创建简短、简明和连贯版本的过程。这是 NLP 领域中最有趣、最具挑战性的问题之一。
自从川普昨晚发表了他的 国情咨文 ,关键要点,事实核查,分析,反应充斥着新闻媒体。如果你像我一样,不想听完 82 分钟的整个演讲,或阅读整个演讲,并且你不想错过任何重要的东西,那么我们将尝试探索文本摘要的领域并建立一个文本摘要器。希望我们从文本摘要器中得到的摘要尽可能地接近原文,但要短得多。我们开始吧!
带 NLTK 的 TextRank
TextRank 是一种无监督的文本摘要技术,它使用 PageRank 算法背后的直觉来对句子进行排序。在我们的项目中使用 NLTK 时,我们有以下步骤:
- 在网上获取国情咨文。
- 基本文本清理。
- 找出每个句子的向量表示(单词嵌入)。
- 然后计算句子向量之间的相似度并存储在矩阵中。
- 相似度矩阵转换成图,以句子为顶点,相似度得分为边。
- 对该句子图应用 PageRank 算法进行句子等级计算。
- 打印出几个排名靠前的句子。
数据
这些数据可以在白宫网站上找到,并于今天发布。
def get_only_text(url):
"""
return the title and the text of the article
at the specified url
"""
page = urlopen(url)
soup = BeautifulSoup(page, "lxml")
text = ' '.join(map(lambda p: p.text, soup.find_all('p')))
print ("=====================")
print (text)
print ("=====================")
return soup.title.text, text
url="[https://www.whitehouse.gov/briefings-statements/remarks-president-trump-state-union-address-2/](https://www.whitehouse.gov/briefings-statements/remarks-president-trump-state-union-address-2/)"
text = get_only_text(url)
首先,我们来窥见几个句子:
sentences = []
for s in text:
sentences.append(sent_tokenize(s))sentences = [y for x in sentences for y in x]
sentences[30:40]
听起来差不多。
我们将使用预先训练的单词向量来为国情咨文中的句子创建向量。我已经从手套下载了数据并保存在我的工作目录中。
word_embeddings = {}
f = open('glove.6B.100d.txt', encoding='utf-8')
for line in f:
values = line.split()
word = values[0]
coefs = np.asarray(values[1:], dtype='float32')
word_embeddings[word] = coefs
f.close()
一些基本的文本预处理,如删除停用词和删除特殊字符。
clean_sentences = pd.Series(sentences).str.replace("[^a-zA-Z]", " ")
clean_sentences = [s.lower() for s in clean_sentences]
stop_words = stopwords.words('english')
def remove_stopwords(sen):
sen_new = " ".join([i for i in sen if i not in stop_words])
return sen_new
clean_sentences = [remove_stopwords(r.split()) for r in clean_sentences]
在下面的代码脚本中,我们为句子创建向量。我们首先获取句子中组成单词的向量(每个向量的大小为 100 个元素),然后取这些向量的平均值,以得到该句子的合并向量。我们创建一个空的相似度矩阵,并用句子的余弦相似度填充它。最后,我们用余弦相似性分数初始化矩阵,并打印出排名前 15 的句子作为摘要表示。
sentences_vector
Sumy Python 模块
Sumy 是一个 Python 库,用于从 HTML 页面或纯文本中提取摘要。是由 Miso-Belica 开发的。我们将把以下总结方法应用到国情咨文中,并为每种方法打印出 10 个句子:
- LsaSummarizer 。潜在语义分析结合词频和奇异值分解。
LANGUAGE = "english"
SENTENCES_COUNT = 10
url="[https://www.whitehouse.gov/briefings-statements/remarks-president-trump-state-union-address-2/](https://www.whitehouse.gov/briefings-statements/remarks-president-trump-state-union-address-2/)"
parser = HtmlParser.from_url(url, Tokenizer(LANGUAGE))
print ("--LsaSummarizer--")
summarizer = LsaSummarizer()
summarizer = LsaSummarizer(Stemmer(LANGUAGE))
summarizer.stop_words = get_stop_words(LANGUAGE)
for sentence in summarizer(parser.document, SENTENCES_COUNT):
print(sentence)
- 卢恩总结者。一种基于 TF-IDF 并查看高重要性单词之间不重要单词的“窗口大小”的简单方法。它还为出现在文档开头附近的句子分配较高的权重。
print ("--LuhnSummarizer--")
summarizer = LuhnSummarizer()
summarizer = LuhnSummarizer(Stemmer(LANGUAGE))
summarizer.stop_words = ("I", "am", "the", "you", "are", "me", "is", "than", "that", "this")
for sentence in summarizer(parser.document, SENTENCES_COUNT):
print(sentence)
- 词法分析器。受 PageRank 算法启发的无监督方法。它找出文档中所有单词的相对重要性,并选择包含最多高分单词的句子。
print ("--LexRankSummarizer--")
summarizer = LexRankSummarizer()
summarizer = LexRankSummarizer(Stemmer(LANGUAGE))
summarizer.stop_words = ("I", "am", "the", "you", "are", "me", "is", "than", "that", "this")
for sentence in summarizer(parser.document, SENTENCES_COUNT):
print(sentence)
- *埃德蒙森总结者。*使用 *EdmundsonSummarizer 时,*我们需要输入我们希望在摘要中看到的有意义的单词,不重要的 stigma_words,以及停用单词 null_words。
print ("--EdmundsonSummarizer--")
summarizer = EdmundsonSummarizer()
words1 = ("economy", "fight", "trade", "china")
summarizer.bonus_words = words1
words2 = ("another", "and", "some", "next")
summarizer.stigma_words = words2
words3 = ("another", "and", "some", "next")
summarizer.null_words = words3
for sentence in summarizer(parser.document, SENTENCES_COUNT):
print(sentence)
这是edmundsonsumrizer在我设置了上述单词标准后的输出:
在我们确定哪种方法是总结特朗普国情咨文的最佳方法之前,似乎有很多参数需要调整。不管怎样,我个人很享受这次学习之旅。希望你也是。
Jupyter 笔记本可以在 Github 上找到。享受这周剩下的时光吧!
参考资料:
[## 使用 TextRank 算法的文本摘要介绍(Python 实现)
引言文本摘要是自然语言处理(NLP)的应用之一
www.analyticsvidhya.com](https://www.analyticsvidhya.com/blog/2018/11/introduction-text-summarization-textrank-python/) [## 黑客用文本摘要的文本排名
摘要任务是一个经典的任务,已经从不同的角度进行了研究。这项任务包括…
nlpforhackers.io](https://nlpforhackers.io/textrank-text-summarization/) [## 使用 Python 文本分析技术的自动文本摘要
自动文本摘要是用软件缩短文本文档的过程,以便创建摘要…
ai.intelligentonlinetools.com](http://ai.intelligentonlinetools.com/ml/text-summarization/)
科学数据集的自动化分析
如何编写自动分析科学数据集的 Python 程序
这是教你如何自动分析科学实验室数据的系列文章中的第三篇。第一篇文章介绍了概念,提供了一些动机,并描述了一般过程。第二个 T2 描述了几种识别条件和为每个测试创建单独数据文件的方法。这第三篇文章将教你如何编写一个程序,自动打开每个文件,并对这些数据集进行计算。
自动打开每个数据文件
自动分析每个数据文件的第一步是打开它们。然而,由于我们想自动分析大量的文件,我们不能简单地写一行打开特定文件的代码;相反,我们创建一个结构,顺序打开项目中的每个文件。这可以通过使用 glob、pandas、for 循环和以下步骤来完成:
- 首先,将项目中的所有文件存储在特定的文件夹中。将所有文件放在同一个文件夹中是很有帮助的,因为这样你只需要将程序指向一个路径。如果您使用了第 2 部分中的动态文件名建议,您应该能够识别测试之间的差异,而不必将文件存储在许多不同的文件夹中。
- 其次,使用 glob 包创建该文件夹中与您的数据文件类型相匹配的所有文件的列表。glob.glob 函数非常适合这个目的,只需要一个路径和一个文件类型作为输入。例如,如果您想打开一个文件夹中的所有文件,您可以使用下面三行代码(Path 变量是虚构的,需要修改以符合您的特定情况)。第一行导入 glob 包,第二行告诉代码文件的位置,第三行创建一个名为‘Filenames’的变量,用 all。路径指定的文件夹中的 csv 文件。
import glob
Path = r'C:\Users\JSmith\Documents\AutomatedDataAnalysis\Example'
Filenames = glob.glob(Path, '/*.csv')
- 第三,创建一个遍历每个文件的 for 循环。打开和分析这些文件的代码可以存储在 for 循环中。通过这样做,您创建了一系列的分析步骤,程序将依次对文件名中的每个文件执行这些步骤。但是首先我们需要创建 for 循环。这可以使用下面的代码来完成,该代码创建了一个新的变量“Filename”来临时保存存储在“Filenames”中的每个路径:
for Filename in Filenames:
- 最后,我们需要打开文件。假设数据存储在。csv 文件你可以用 pandas.read_csv 函数打开。假设您之前的代码导入了 pandas,您可以通过在 for 循环中添加以下行来打开每个文件:
Data = pd.read_csv(Filename)
就是这样!您的代码现在按顺序打开文件夹中包含的每个文件。这意味着下一步是在 for 循环中添加代码,告诉程序如何处理数据。
自动分析每个数据集
打开文件后,程序可以继续执行数据的实际分析。这一过程必须针对每个项目进行高度定制,因为计算必须针对特定项目进行。由于这一限制,本节将为 Python 新手提供一些技巧,而不是试图提供具体的步骤。一些重要的提示包括:
- 用 pandas.read_csv 打开文件创建了一个 pandas DataFrame 对象,其中包含来自该文件的数据。数据帧本质上是一个表。以这种方式打开文件可以访问 pandas 的所有数据操作功能。如果你不熟悉那些考虑阅读熊猫文档以获取提示的人。
- Python 中的计算可以用任意数量的有用包来执行。对于项目的这一部分,pandas 和 numpy 可能会提供最重要的功能。目标是找到包并编写代码来执行您需要对每个文件进行的所有计算。
- 如果您需要针对每个文件的特定部分,不要忘记使用类似于第 2 部分中描述的技术来过滤数据。
- 根据需要,使用 matplotlib、bokeh 或其他包来绘制结果。
- 完成计算后,可以用 pandas DataFrame.to_csv 函数打印结果。确保给它一个新的文件名,以避免覆盖原始数据文件。
后续步骤
第二篇和第三篇文章结合起来,为您提供了自动分析每个数据文件并保存结果的完整指南。随着文件的打开、计算的执行和数据的分析,现在是过程中最重要的部分:检查数据集的错误。我的下一篇文章将教你一些在程序中添加代码的方法,让你更容易检查数据集的错误。
利用计算机视觉和节点实现灯光自动化
基于智能计算机视觉和 NodeJS 的解决方案,可以在不使用时关闭灯,从而节省电能。
Photo by Henry McIntosh on Unsplash
挑战
常见的情况是,在家庭和办公室中,被照亮的空间附近很少有人或没有人。
除了花费更多,这种照明对环境也有负面影响。我们越来越依赖有限的、不可再生的能源来发电,而这些能源经常被浪费掉。
虽然我们在家里的能源使用是名义上的,但在办公室,我们的能源使用要多得多。因此,对环境和成本的负面影响要大得多。这需要我们采取积极的行动。
当张贴“离开前请关灯”的标志影响很小或没有影响时,考虑到灯的数量、覆盖的区域和其他因素,损失的大小更大。让某人每次都简单地关灯来解决过度照明的问题是不可行的。人类的记忆变化无常,不可依赖。
我们来了解一下单个灯泡的影响。一个 10 瓦的灯泡每小时耗电 0.01 千瓦。我们假设 1 度电的成本是 12 美分。那么每一个不需要时点亮的 10 瓦灯泡,每小时将花费 0.12 美分。
我会让你运用基本的算术技巧,通过将灯的数量乘以上述数字来计算整个办公室的总成本。
那么我们如何解决这个问题呢?
虽然市场上有许多智能控制和自动化解决方案,但大多数解决方案都需要定期安装额外的硬件,并导致额外的维护成本。
有没有更好的方法来应对这一挑战?
所有办公场所都安装了摄像头来监控该区域。我和我的同事们集思广益,想出了用最少的投资解决这个问题的方法。然后灵光一现!💡
为什么不使用这些捕捉不同画面的相机来自动关灯呢?
我们的回应
解决方案是通过计算机的眼睛——通过计算机视觉来表达我们节约能源的意图。
那么到底什么是计算机视觉呢?
“计算机视觉,通常缩写为 CV,被定义为一个研究领域,旨在开发技术来帮助计算机‘看’和理解数字图像(如照片和视频)的内容。”
—杰森·布朗利,在他关于机器学习的文章中。
举例来说,就像一个生态友好的人,寻找无人居住的照明房间或空间,关灯,我们的系统将被编程为自动这样做。该系统将查看来自摄像机的输入流,这实质上是摄像机的视野。每个捕获的帧被分成 4 个象限。并且如果在特定的象限中没有人,则属于该象限的灯将被关闭。
这个解决方案是用 opencv4Nodejs 实现的,它是流行的开源计算机视觉库 OpenCV 的 Node.js 包装器。与一起,socket.io 和 express 用于渲染一个 web 应用程序,以显示实时视频流并模拟灯光的打开和关闭。
实施步骤
- 导入所需的库。
2.开始从摄像机捕捉视频。
3.读取 feed 并以固定的帧速率将其传输到 web 应用程序。
4.以大于实时流的时间间隔读取订阅源,以确定用户是否存在。
5.使用任何 OpenCV 分类器检测人。在这个解决方案中,使用了“哈尔正面人脸分类器”。检测到的相对于帧的面部位置被存储以备后用。
6.在框架上标记面部,以便可视化检测。
7.确定人们相对于画面的位置,以决定他们在哪个象限,以便只照亮那些部分。识别的结果然后被发送到网络应用程序进行照明模拟。灯泡颜色会发生变化,以模拟点亮哪个象限。
Since people are present in Quadrant 2, the system lights up only quadrant 2
结论
这是众多例子中的一个,展示了技术如何通过节约能源来改善地球。您还可以通过这个简单的实现了解如何解决常见的工作场所挑战。
请参考上述解决方案的源代码:
[## mudas sir-23/opencv-nodejs-节能器
基于 opencv 和 nodejs 的节能解决方案。通过以下方式为 mudas sir-23/opencv-nodejs-energy-saver 开发做出贡献…
github.com](https://github.com/Mudassir-23/opencv-nodejs-energy-saver)
还可以查看基于 opencv4nodejs、express 和 socket.io 的应用程序的样板代码。
这个解决方案可以扩展到不仅仅是模拟。
您可以使用已建立的套接字连接到 express 应用程序,并从每个象限接收二进制数据。您可以通过继电器决定在哪个象限打开或关闭物理灯!⚡️
在 AWS 上自动化机器学习模型
使用自动气象站 Lambda、S3 和 EC2
Photo by Samuel Zeller on Unsplash
作为马里兰大学 Gordon Gao 教授手下的一名研究助理,我有机会将我的数据工程和科学兴趣结合起来,在云中实现机器学习模型的自动化。在协助高教授的一位博士生时,我的任务是提供一种基于 AWS 的解决方案,这将减少在为一家即将成立的健康初创公司运行深度学习模型时的人工干预。
问题定义
我们的客户将问题定义为
“通过仅运行 EC2 实例进行计算,降低 EC2 实例的成本。只要客户将数据上传到 S3 存储桶,这些计算就会发生,这可能发生在一天中的任何时间。”
提到的计算包括机器学习模型和处理上传到 S3 的数据。这意味着,EC2 应该仅在执行 ML 模型时运行,而在其他时间应该关闭,而且这些作业没有固定的时间,它们拥有的唯一固定属性是它们必须在数据上传到 S3 数据桶后立即运行。我用下面的算法形成了一个粗略的工作流程,这个流程后来帮助我简化了整个自动化过程。
1。将数据上传到 S3 数据桶,触发 Lambda 函数。
2。触发器 Lambda 函数打开 EC2 实例并调用 Worker Lambda 函数。
3。Worker Lambda 函数从 S3 数据桶中复制数据,并开始执行机器学习模型。
3。EC2 实例执行 ML 模型并将输出发送到 S3 输出桶。
4。输出文件被放入 S3 输出桶,该桶执行 Stop EC2 Lambda 函数。
5。停止 EC2 Lambda 功能关闭 EC2 实例。
可视化管道
在我担任高教授的助教期间,我曾参与过 EC2 和的课堂作业。然而,Lambda 没有,这些是学术设置,我没有太多的限制。现在,我正在与一个客户打交道,这带来了安全的重要方面,并增加了在截止日期前工作的元素。这一点,再加上我不得不在项目的大部分繁重工作中使用 Lambda 函数,对我来说更加困难。
Automation Workflow Visualized
这种自动化确保了 EC2 实例仅在处理数据时被实例化,并在输出被写入 S3 存储桶时被关闭。
我从设置我的弹性云计算实例开始。我用 Python 创建了一个虚拟环境来加载库,这是运行 worker.py 和 trigger.py 脚本以及 ML 模型所需的包所必需的。我还向 EC2 实例添加了一个标记,因为这将帮助我在配置 Lambda 函数时识别实例。一旦 EC2 实例被设置好,我就开始研究 Lambda 函数。触发器函数负责两项任务:当数据上传到 S3 数据桶时启动 EC2 实例,然后在 EC2 启动后调用 Worker Lambda 函数。
Trigger Lambda Function
我使用 boto3 库来调用各种 AWS APIs,例如启动 EC2 实例,调用 Worker Lambda 函数,并将 EC2 的 IP 传递给它。
接下来,我开始开发 Worker Lambda 函数,并将它编程为将数据从 S3 数据桶复制到 EC2,然后开始执行机器学习模型。
Worker Lambda Function
从上面的函数可以看出,我用了我的私钥(。pem)登录到 EC2,然后执行命令以启动从数据桶到 EC2 的 S3 复制,然后对数据调用机器学习 Python 脚本,并将生成的结果复制到 S3 输出桶。
此外,我编写了 Stop EC2 Lambda 函数,该函数将在机器学习模型的输出被复制到 S3 输出桶时启动,该 Lambda 函数将调用 EC2 上的 stop API,确保 EC2 仅在机器学习模型的持续时间内运行。
Stop EC2 Lambda Function
将所有东西整合在一起
Photo by Perry Grone on Unsplash
我已经准备好了单独的 Lambda 函数,但是让它们一起工作,当一个函数完成时启动另一个函数是需要完成的不同任务。最初,我开始使用 AWS CloudWatch,并试图用它来触发不同的 Lambda 函数,设置 cron 类计时并使用警报来执行函数。虽然这些看起来可行,但我们的客户觉得我增加了整个工作流程的复杂性,希望我把事情变得简单。这些限制促使我使用现有服务寻找解决方案,这就是我遇到 S3 事件的原因。
S3 事件是可以在 S3 存储桶的属性选项卡下找到的功能,它允许您在 S3 存储桶中执行某些操作时安排事件。经过进一步研究,我能够为我的两个 Lambda 函数设置事件,允许我链接管道并完成自动化。
决赛成绩
Photo by NeONBRAND on Unsplash
工作流现在更容易理解和设置,S3 数据桶中的初始 PUT 请求将触发第一个 S3 事件,该事件旨在调用 Trigger Lambda 函数。Trigger 函数打开 EC2,然后调用 Worker Lambda 函数。如前所述,Worker 函数将从数据桶中复制上传的数据,并对数据运行深度学习模型。一旦计算完成,Worker 函数就会将结果复制到 S3 输出桶中,触发下一个调用 Stop EC2 Lambda 函数并停止 EC2 的事件。
这确保了深度学习模型现在是自动化的,并且 EC2 将仅在需要时运行,而在所有其他时间被关闭。
因此,我已经成功地减少了 EC2 实例的运行时间,以前,我的客户机必须从上午 9 点到下午 5 点运行 EC2,用于一天运行三四次并且每次运行不超过 20 分钟的作业。在我实现流程自动化后,客户的运行时间从 8 小时减少到了 1 小时,从而使客户在 AWS 服务上减少了大约 90%的成本。
编辑卡纳克亚达夫
参考链接
[## 使用 Lambda 和 CloudWatch 以预定的时间间隔停止和启动 EC2 实例
我想通过停止和启动我的 EC2 实例来减少我的 Amazon 弹性计算云(Amazon EC2)的使用…
aws.amazon.com](https://aws.amazon.com/premiumsupport/knowledge-center/start-stop-lambda-cloudwatch/)
自动化 ML 特征工程
Source: http://www.publicdomainfiles.com/show_file.php?id=13545363012524
构建组合规模的数据产品
“机器学习的圣杯之一是自动化越来越多的特征工程过程”——Pedro Domingos,CACM 2012
机器学习工作流中最大的挑战之一是识别数据中的哪些输入将为训练预测模型提供最佳信号。对于图像数据和其他非结构化格式,深度学习模型显示出比以前的方法有很大的改进,但对于已经是结构化格式的数据,好处就不那么明显了。
在 Zynga,我一直在探索浅层学习问题的特征生成方法,我们的数据已经是结构化的格式,挑战是将每个用户的数千条记录翻译成总结用户活动的单个记录。一旦您能够将原始跟踪事件转换为用户摘要,您就可以将各种监督和非监督学习方法应用到您的应用程序中。
https://github.com/FeatureLabs/featuretools
我一直在利用 Featuretools 库来显著减少我在构建预测模型上花费的时间,并且它解开了数据科学家可以解决的一类新问题。我们现在不是为单个游戏和特定反应建立预测模型,而是建立可以应用于广泛问题的机器学习管道。我将在圣克拉拉的人工智能博览会上概述我们的方法。
[## 本·韦伯|演讲嘉宾| 2019 年北美人工智能和大数据博览会
杰出数据科学家本·韦伯是 Zynga 的杰出数据科学家,曾在 Twitch 工作过…
www.ai-expo.net](https://www.ai-expo.net/northamerica/speaker/ben-weber/)
自动化特征工程是从每个用户的数千甚至数百万个数据点中创建特征向量的过程。该方法受深度学习的特征合成方法的启发,但只关注特征生成阶段,而不是模型拟合阶段。深度特征综合的结果是,您可以将描述用户活动的数千条记录转换成可用于训练模型的单个记录。以下是我一直在探索的自动化特征工程的一些用例:
- **倾向模型:**用户在做什么动作?
- **建议:**我们应该规定什么行动?
- **细分:**我们应该如何个性化用户体验?
- **异常检测:**哪些用户是不良行为者?
在 Spark 峰会上,我用我的 AutoModel 演讲对特征工程进行了深入的探讨。从那以后,我们发现了自动化特征工程的各种不同的用例。关键是,如果你可以将原始事件数据转化为用户行为的总结,那么你就可以将机器学习模型应用于各种问题。
倾向模型
预测哪些用户可能会执行某个动作对于个性化游戏体验非常有用。我使用 Featuretools 库来自动化项目的特征工程,但它需要使用更新的熊猫 UDF 功能来扩展到大规模数据集。
Propensity Models
推荐
协同过滤是为用户提供个性化内容的有价值的工具。我没有使用过去的购买作为协同过滤的特征向量,而是探索了一些代理变量来推荐商品。
Recommendation Engine
原型
细分是分析团队可以向产品组织提供的关键产出之一。如果你能理解你的产品中不同用户群的行为,你就能提供个性化的处理来提高你的用户群的参与度。
User Clustering
异常检测
任何网络环境中都有坏人。我们一直在探索针对这个问题的深度学习,对我们生成的特征集应用自动编码为标记有问题的用户提供了一个强大的工具。
Anomaly Detection
结论
机器学习工作流中的特征生成步骤自动化为数据科学团队解决了新的问题。我们的数据科学家不再专注于特定的游戏,而是可以构建可扩展到一系列游戏的解决方案。
用深度 Q 学习自动化 Pac-man:在 Tensorflow 中的实现。
强化学习的基础
简介
在我们关于 GradientCrescent 强化学习基础的文章中,我们研究了基于模型的和基于样本的强化学习方法。简而言之,前一类的特征在于需要所有可能的状态转移的完整概率分布的知识,并且可以通过马尔可夫决策过程来举例说明。相反,基于样本的学习方法允许简单地通过重复观察来确定状态值,而不需要转换动态。在这个领域中,我们已经讨论了蒙特卡罗和时间差电子学习。简而言之,这两者可以通过状态值更新的频率来区分:蒙特卡罗方法要求一个情节完成一轮更新才能发生,而时间差异方法增量地更新情节内,使用状态值的旧估计以及折扣奖励来生成新的更新。
TD 或“在线”学习方法的快速反应性使它们适合于高度动态的环境,因为状态和动作的值通过一组估计值随着时间不断更新。也许最值得注意的是, TD 是 Q-learning 的基础,Q-learning 是一种更高级的算法,用于训练代理处理游戏环境,如 OpenAI Atari 健身房中观察到的环境,这也是本文的重点。
Our previous policy-based Pong model, trained over 5000 episodes with a binary action space.
超越 TD: SARSA & Q-learning
回想一下,在时间差异学习中,我们观察到一个主体在一个环境中通过一系列状态(S)、动作(A)和(奖励)循环地行为。
由于这种循环行为,我们可以在到达下一个状态时更新前一个状态的值。然而,我们可以扩展我们的训练范围,以包括状态-动作值,就像我们之前对马尔可夫决策过程所做的那样。这就是通常所说的萨尔萨。让我们比较状态-动作和状态-值 TD 更新方程:
Q-learning 通过在更新期间强制选择具有最高动作值的动作,以类似于利用贝尔曼最优方程观察到的方式,将此向前推进了一步。我们可以检查贝尔曼和贝尔曼优化方程旁边的 SARSA 和 Q-learning,如下所示:
你可能想知道如何确保我们的状态-动作空间的完整探索,给定需要不断地为具有最高现有动作值的状态选择动作。从理论上讲,我们可能只是因为一开始就没有评估而避免了最佳行动。**为了鼓励探索,我们可以使用一个衰减的 e-greedy 策略,**本质上是强迫代理人选择一个明显的次优行动,以便在某个百分比的时间里了解更多关于其价值的信息。通过引入衰减过程,我们可以在评估完所有状态后限制探索,之后我们将永久地为每个状态选择最佳操作。
正如我们之前用 MDP 的模型解决了 Pong 一样,让我们把我们学到的关于 Q-learning 的知识应用到雅达利的《吃豆人小姐》游戏中。
实施
我们的 Google 协作实现是利用 Tensorflow Core 用 Python 编写的,可以在 GradientCrescent Github 上找到。这是基于 Ravichandiran 等人的观点。al,但是升级到与 Tensorflow 2.0 兼容,并且显著扩展以促进改进的可视化和解释。由于这种方法的实现非常复杂,让我们总结一下所需动作的顺序:
- 我们定义我们的深度 Q 学习神经网络。这是一个 CNN,它拍摄游戏中的屏幕图像,并输出 Ms-Pacman gamespace 中每个动作的概率,或 Q 值。为了获得概率张量,我们在最后一层不包括任何激活函数。
- 由于 Q-learning 要求我们了解当前和下一个状态,我们需要从数据生成开始。我们将表示初始状态 s 的游戏空间的预处理输入图像输入到网络中,并获得动作的初始概率分布,或 Q 值。在训练之前,这些值将是随机的和次优的。
- 利用我们的概率张量,我们然后使用 argmax()函数选择具有当前最高概率的动作,并使用它来构建 epsilon 贪婪策略。
- 使用我们的策略,我们将选择动作 a ,并评估我们在健身房环境中的决策接收关于新状态s’、奖励 r 以及该集是否已结束的信息。
- 我们以列表形式
将该信息组合存储在一个缓冲区中,并重复步骤 2-4 预设次数,以建立一个足够大的缓冲区数据集。 - 一旦步骤 5 完成,我们转到生成我们的目标 y 值,R’和A’,这是损失计算所需的。虽然前者只是从 R 中减去,但是我们通过将*S’*输入到我们的网络中来获得 A’。
- 有了所有的组件,我们就可以计算训练网络的损耗。
- 培训结束后,我们将通过图形和演示来评估代理的表现。
让我们开始吧。随着 Tensorflow 2 在实验室环境中的出现,我们已经使用新的 compat 包将我们的代码转换为符合 TF2 标准。注意,这段代码不是 TF2 本地的。
让我们导入所有必要的包,包括 OpenAI gym 环境和 Tensorflow 核心。
import numpy as npimport gymimport tensorflow as tffrom tensorflow.contrib.layers import flatten, conv2d, fully_connectedfrom collections import deque, Counterimport randomfrom datetime import datetime
接下来,我们定义一个预处理函数,从我们的健身房环境中裁剪图像,并将它们转换成一维张量。在我们的 Pong 自动化实现中,我们已经看到了这一点。
**def preprocess_observation(obs):** # Crop and resize the image img = obs[1:176:2, ::2] # Convert the image to greyscale img = img.mean(axis=2) # Improve image contrast img[img==color] = 0 # Next we normalize the image from -1 to +1 img = (img — 128) / 128–1 return img.reshape(88,80,1)
接下来,让我们初始化健身房环境,检查几个游戏画面,并了解 gamespace 中可用的 9 个动作。当然,我们的代理人无法获得这些信息。
env = gym.make(“MsPacman-v0”)n_outputs = env.action_space.nprint(n_outputs)print(env.env.get_action_meanings())observation = env.reset()import tensorflow as tfimport matplotlib.pyplot as pltfor i in range(22): if i > 20: plt.imshow(observation) plt.show()observation, _, _, _ = env.step(1)
您应该遵守以下几点:
我们可以借此机会比较我们的原始和预处理输入图像:
接下来,让我们定义我们的模型,一个深度 Q 网络。这本质上是一个三层卷积网络,它获取预处理的输入图像,展平并将其馈送到一个全连接层,并输出在游戏空间中采取每个行动的概率。如前所述,这里没有激活层,因为激活层的存在会导致二进制输出分布。
**def q_network(X, name_scope):**# Initialize layers initializer = tf.compat.v1.keras.initializers.VarianceScaling(scale=2.0) with tf.compat.v1.variable_scope(name_scope) as scope: # initialize the convolutional layers layer_1 = conv2d(X, num_outputs=32, kernel_size=(8,8), stride=4, padding=’SAME’, weights_initializer=initializer) tf.compat.v1.summary.histogram(‘layer_1’,layer_1) layer_2 = conv2d(layer_1, num_outputs=64, kernel_size=(4,4), stride=2, padding=’SAME’, weights_initializer=initializer) tf.compat.v1.summary.histogram(‘layer_2’,layer_2) layer_3 = conv2d(layer_2, num_outputs=64, kernel_size=(3,3), stride=1, padding=’SAME’, weights_initializer=initializer) tf.compat.v1.summary.histogram(‘layer_3’,layer_3) flat = flatten(layer_3) fc = fully_connected(flat, num_outputs=128, weights_initializer=initializer) tf.compat.v1.summary.histogram(‘fc’,fc) #Add final output layer output = fully_connected(fc, num_outputs=n_outputs, activation_fn=None, weights_initializer=initializer) tf.compat.v1.summary.histogram(‘output’,output) vars = {v.name[len(scope.name):]: v for v in tf.compat.v1.get_collection(key=tf.compat.v1.GraphKeys.TRAINABLE_VARIABLES, scope=scope.name)} #Return both variables and outputs togetherreturn vars, output
让我们借此机会为我们的模型和训练过程定义超参数
num_episodes = 800batch_size = 48input_shape = (None, 88, 80, 1)#Recall shape is img.reshape(88,80,1)learning_rate = 0.001X_shape = (None, 88, 80, 1)discount_factor = 0.97global_step = 0copy_steps = 100steps_train = 4start_steps = 2000
回想一下,Q-learning 要求我们选择具有最高行动值的行动。为了确保我们仍然访问每一个可能的状态-行为组合,我们将让我们的代理遵循一个ε贪婪策略,探索率为 5%。我们将这个探索速率设置为随时间衰减,因为我们最终假设所有的组合都已经被探索了——在该点之后的任何探索将简单地导致次优动作的强制选择。
epsilon = 0.5eps_min = 0.05eps_max = 1.0eps_decay_steps = 500000#**def epsilon_greedy(action, step):** p = np.random.random(1).squeeze() #1D entries returned using squeeze epsilon = max(eps_min, eps_max — (eps_max-eps_min) * step/eps_decay_steps) #Decaying policy with more steps if np.random.rand() < epsilon: return np.random.randint(n_outputs) else: return action
回想上面的等式,Q-learning 的更新函数要求如下:
- 当前状态 s
- 当前动作一
- 当前动作后的奖励 r
- 下一个状态s’
- 下一个动作a’
为了以有意义的数量提供这些参数,我们需要按照一组参数评估我们当前的策略,并将所有变量存储在一个缓冲区中,我们将在训练期间从该缓冲区中提取迷你批次中的数据…这与我们之前在 Pong 中的实现不同,我们使用的是增量方法。让我们继续创建我们的缓冲区和一个简单的采样函数:
buffer_len = 20000#Buffer is made from a deque — double ended queueexp_buffer = deque(maxlen=buffer_len)**def sample_memories(batch_size):** perm_batch = np.random.permutation(len(exp_buffer))[:batch_size] mem = np.array(exp_buffer)[perm_batch] return mem[:,0], mem[:,1], mem[:,2], mem[:,3], mem[:,4]
接下来,让我们将原始网络的权重参数复制到目标网络中。这种双网络方法允许我们在使用现有策略的训练过程中生成数据,同时仍然为下一次策略迭代优化我们的参数。
# we build our Q network, which takes the input X and generates Q values for all the actions in the statemainQ, mainQ_outputs = q_network(X, ‘mainQ’)# similarly we build our target Q network, for policy evaluationtargetQ, targetQ_outputs = q_network(X, ‘targetQ’)copy_op = [tf.compat.v1.assign(main_name, targetQ[var_name]) for var_name, main_name in mainQ.items()]copy_target_to_main = tf.group(*copy_op)
最后,我们还将定义我们的损失。这就是我们的目标动作(具有最高动作值)和我们的预测动作的平方差。我们将使用 ADAM 优化器来最大限度地减少我们在训练中的损失。
# define a placeholder for our output i.e actiony = tf.compat.v1.placeholder(tf.float32, shape=(None,1))# now we calculate the loss which is the difference between actual value and predicted valueloss = tf.reduce_mean(input_tensor=tf.square(y — Q_action))# we use adam optimizer for minimizing the lossoptimizer = tf.compat.v1.train.AdamOptimizer(learning_rate)training_op = optimizer.minimize(loss)init = tf.compat.v1.global_variables_initializer()loss_summary = tf.compat.v1.summary.scalar(‘LOSS’, loss)merge_summary = tf.compat.v1.summary.merge_all()file_writer = tf.compat.v1.summary.FileWriter(logdir, tf.compat.v1.get_default_graph())
定义好所有代码后,让我们运行我们的网络并检查培训过程。我们已经在最初的总结中定义了大部分,但是让我们为后代回忆一下。
- 对于每个时期,在使用ε-贪婪策略来选择下一个动作之前,我们将输入图像馈送到我们的网络中,以生成可用动作的概率分布
- 然后,我们将它输入到健身房环境中,获取下一个状态和相应奖励的信息,并将其存储到我们的缓冲区中。
- 在我们的缓冲区足够大之后,我们将下一个状态采样到我们的网络中,以便获得下一个动作。我们还通过贴现当前的奖励来计算下一个奖励
- 我们通过 Q 学习更新函数生成我们的目标 y 值,并训练我们的网络。
- 通过最小化训练损失,我们更新网络权重参数,以便为下一个策略输出改进的状态-动作值。
with tf.compat.v1.Session() as sess: init.run() # for each episode history = [] for i in range(num_episodes): done = False obs = env.reset() epoch = 0 episodic_reward = 0 actions_counter = Counter() episodic_loss = [] # while the state is not the terminal state while not done: # get the preprocessed game screen obs = preprocess_observation(obs) # feed the game screen and get the Q values for each action, actions = mainQ_outputs.eval(feed_dict={X:[obs], in_training_mode:False}) # get the action action = np.argmax(actions, axis=-1) actions_counter[str(action)] += 1 # select the action using epsilon greedy policy action = epsilon_greedy(action, global_step) # now perform the action and move to the next state, next_obs, receive reward next_obs, reward, done, _ = env.step(action) # Store this transition as an experience in the replay buffer! Quite important exp_buffer.append([obs, action, preprocess_observation(next_obs), reward, done]) # After certain steps we move on to generating y-values for Q network with samples from the experience replay buffer if global_step % steps_train == 0 and global_step > start_steps: o_obs, o_act, o_next_obs, o_rew, o_done = sample_memories(batch_size) # states o_obs = [x for x in o_obs] # next states o_next_obs = [x for x in o_next_obs] # next actions next_act = mainQ_outputs.eval(feed_dict={X:o_next_obs, in_training_mode:False}) #discounted reward for action: these are our Y-values y_batch = o_rew + discount_factor * np.max(next_act, axis=-1) * (1-o_done) # merge all summaries and write to the file mrg_summary = merge_summary.eval(feed_dict={X:o_obs, y:np.expand_dims(y_batch, axis=-1), X_action:o_act, in_training_mode:False}) file_writer.add_summary(mrg_summary, global_step) # To calculate the loss, we run the previously defined functions mentioned while feeding inputs train_loss, _ = sess.run([loss, training_op], feed_dict={X:o_obs, y:np.expand_dims(y_batch, axis=-1), X_action:o_act, in_training_mode:True}) episodic_loss.append(train_loss) # after some interval we copy our main Q network weights to target Q network if (global_step+1) % copy_steps == 0 and global_step > start_steps: copy_target_to_main.run() obs = next_obs epoch += 1 global_step += 1 episodic_reward += reward history.append(episodic_reward)print(‘Epochs per episode:’, epoch, ‘Episode Reward:’, episodic_reward,”Episode number:”, len(history))
一旦训练完成,我们就可以根据增量情节绘制奖励分布图。前 550 集(大约 2 小时)大概是这样的:
在额外的 800 集之后,这汇聚成以下内容:
为了在实验室环境的限制下评估我们的结果,我们可以录制整个情节,并使用基于 IPython 库的包装在虚拟显示器中显示:
“””Utility functions to enable video recording of gym environment and displaying it. To enable video, just do “env = wrap_env(env)””“”**def show_video():** mp4list = glob.glob(‘video/*.mp4’) if len(mp4list) > 0: mp4 = mp4list[0] video = io.open(mp4, ‘r+b’).read() encoded = base64.b64encode(video) ipythondisplay.display(HTML(data=’’’<video alt=”test” autoplay loop controls style=”height: 400px;”> <source src=”data:video/mp4;base64,{0}” type=”video/mp4" /> </video>’’’.format(encoded.decode(‘ascii’)))) else: print(“Could not find video”)
**def wrap_env(env):** env = Monitor(env, ‘./video’, force=True) return env
然后,我们使用我们的模型运行环境的新会话,并记录它。
#Evaluate model on openAi GYMobservation = env.reset()new_observation = observationprev_input = Nonedone = Falsewith tf.compat.v1.Session() as sess: init.run() while True: if True: #set input to network to be difference image obs = preprocess_observation(observation) # feed the game screen and get the Q values for each action actions = mainQ_outputs.eval(feed_dict={X:[obs], in_training_mode:False}) # get the action action = np.argmax(actions, axis=-1) actions_counter[str(action)] += 1 # select the action using epsilon greedy policy action = epsilon_greedy(action, global_step) env.render() observation = new_observation # now perform the action and move to the next state, next_obs, receive reward new_observation, reward, done, _ = env.step(action) if done: #observation = env.reset() break env.close() show_video()
你应该观察几轮比赛!这是我们录制的几集。
对于一个几个小时就训练好的模特来说,成绩远高于 400 分,这已经不错了。特别是,看起来我们的代理人在被幽灵直接追逐时表现得很好,但在预测即将到来的幽灵方面仍然很差,可能是因为它还没有足够的经验来观察它们的运动。
这就结束了 Q-learning 的介绍。在我们的下一篇文章中,我们将从 Atari 的世界转移到解决世界上最著名的 FPS 游戏之一。敬请期待!
我们希望你喜欢这篇文章,并希望你查看 GradientCrescent 上的许多其他文章,涵盖人工智能的应用和理论方面。要了解关于 GradientCrescent 的最新更新,请考虑关注该出版物并关注我们的 Github 资源库。
参考文献
萨顿等人。强化学习
怀特等人。阿尔伯塔大学强化学习基础
席尔瓦等人。阿尔,强化学习,UCL
Ravichandiran 等人。al,用 Python 实践强化学习
通过深度学习实现项目管理自动化
如何使用自然语言处理对项目状态更新进行分类
介绍
在数据驱动的项目管理未来,项目经理将得到人工智能的增强,人工智能可以突出项目风险,确定资源的最佳分配,并自动化项目管理任务。
例如,许多组织要求项目经理定期提供项目状态更新,作为交付保证过程的一部分。这些更新通常由文本注释和相关的红-琥珀色-绿色(RAG)状态组成,其中红色表示失败的项目,琥珀色表示有风险的项目,绿色表示正在进行的项目。如果我们能自动化这个过程,使它更加一致和客观,那不是很好吗?
在这篇文章中,我将描述我们如何通过应用自然语言处理(NLP)将文本评论自动分类为红色、琥珀色或绿色状态来实现这一点。
Updating a project status in Sharktower, Mudano’s data-driven project management platform
训练项目管理语言模型
为了确保我们的 RAG 状态分类器取得好的结果,我们首先需要建立一个语言模型,它理解项目经理使用的特定语言。
仅仅在几年前,训练一个定制的项目管理语言模型需要大量的文本和强大的计算能力。然而,将迁移学习应用于 NLP 的最新进展允许我们在几分钟内在一个适度的 GPU 上使用相对较小的数据集训练一个定制的语言模型。
在迁移学习中,我们采用在大型通用数据集上训练的模型所学习的权重,并使用它们作为在不同数据集上训练新模型的起点。这是一个非常有用的技术,因为它允许我们在数据有限的情况下训练高性能的语言模型。
Mudano 已经收集了一个小型(但丰富)的数据集,该数据集涵盖了许多大型 IT 转型项目的项目状态更新。我们将使用此数据集首先训练一个自定义项目管理语言模型,然后训练 RAG 状态分类器。
探索数据
我们首先将数据加载到一个pandas.DataFrame
中,并查看一个示例项目状态更新。我们的数据以一种.csv
格式存储,由一列文本评论和一列相关的 RAG 状态组成。我们可以如下加载它:
import pandas as pddatapath = '/path/to/data/'
datafile = 'project-updates.csv'df = pd.read_csv(datapath+datafile)
从我们的数据集中随机选取一个示例文本注释:
df['text'][42]
所有活动继续在阶段关口批准的情况下进行计划。\ n \对数据库的分析已完成,当前正在评估使系统符合要求的选项。一旦完成,将提出将系统纳入项目范围的请求。\ n \ nA 已确定对下游的影响,如果在源系统中删除信息后对其进行查询,将返回空响应。正在进行调查,以了解这种影响是否可以接受,或者是否需要采取行动。
文本非常干净,我们不需要做任何额外的清理。
根据经验,我们知道项目经理更可能报告绿色状态,而不是琥珀色或红色状态。让我们快速检查一下我们的数据是否如此,然后绘制结果:
labelcounts = df.groupby(["label"]).size()
label_sum = len(df["label"])
class_imbalance = [(count/label_sum) for count in labelcounts]
正如我们所怀疑的,绿色状态更新比琥珀色状态更新的可能性大得多,而红色状态更新的可能性最小。当我们训练我们的 RAG 状态分类器时,我们将需要考虑这种类别不平衡。
深度学习入门
现在我们已经探索了我们的数据,我们可以使用机器学习对其建模。深度学习是机器学习的一个分支,它使用在大型数据集上训练的深度神经网络,特别适合于语言建模和文本分类等任务。为了构建我们的深度学习模型,我们将使用fastai
库。
fastai
是一个高级深度学习库,针对典型的机器学习问题,如图像和文本分类、图像分割和协同过滤,大大简化了深度神经网络的训练。
要安装fastai
库,我们可以简单地使用conda
包管理器,如下所示:
conda install -c pytorch -c fastai fastai
然后我们可以导入主fastai
库和fastai.text
模块:
from fastai import *
from fastai.text import *
将数据加载到 fastai
现在我们已经导入了fastai.text
模块,我们可以使用它的内置函数轻松加载和处理我们的数据。由于我们的数据是基于文本的并且是.csv
格式的,并且由于我们正在构建一个语言模型,我们使用TextLMDataBunch.from_csv
函数将我们的数据加载并处理到一个数据集中:
data_lm = TextLMDataBunch.from_csv(datapath, datafile)
令人惊讶的是,这就是我们准备训练我们的自定义语言模型!
不过,在我们这样做之前,有必要花点时间深入了解一下fastai
在幕后所做的巧妙的数据处理。
标记化、数字化和分裂
与图像数据不同,原始文本数据不能直接输入到机器学习模型中,需要处理成数字格式。要做到这一点,我们需要将文本分割成标记,然后可以为这些标记分配数值。
默认情况下,在fastai.text
中,文本标记化在单词级完成,标记化中包括单词的标点符号和缩写。fastai.text
还会自动删除 HTML 符号,并添加特殊标记来替换未知标记。
一旦文本被标记化,fastai.text
就会将标记列表转换成整数,并计算每个标记出现的频率。默认情况下,fastai.text
保留 60,000 个最常用的标记,并删除在文本中出现不到两次的标记。这些标记是用于训练语言模型的词汇。在我们的例子中,由于相对较小的数据集,我们只有一个994
令牌的词汇表。
fastai
还可以方便地将数据分为训练集和验证集。
训练自定义语言模型
我们通过在fastai
中定义一个语言学习者对象来构建我们的定制语言模型:
learn_lm = language_model_learner(data_lm, pretrained_model=URLs.WT103, drop_mult=0.5)
我们使用之前定义的 data bunch(data_lm
)和一个预训练的语言模型(pretrained_model=URLs.WT103
)作为学习者对象的输入,并将 dropout 设置为0.5
以避免过度拟合(drop_mult=0.5
)。
fastai.text
默认使用 AWD-LSTM 模型,我们选择通过提供在 WikiText-103 数据集上训练的预训练模型来利用迁移学习。
为了开始训练我们的模型,我们需要决定一个合适的学习速率。幸运的是,fastai
有一些非常有用的内置工具,可以很容易地为此选择一个最佳值。
我们可以使用fastai
学习率查找器(它在一定的学习率范围内运行一系列小型培训任务),然后绘制损失与学习率的关系图:
learn.lr_find()
learn.recorder.plot()
然后,我们在最小损失之前选择一个学习率,就像杰瑞米·霍华德在fast . aiCoders 实用深度学习课程中推荐的那样。从上面的情节,我决定了一个1e-01
的学习率。
为了训练我们的模型,我们只需从我们的学习者对象中调用fit_one_cycle
方法,输入我们想要训练的时期数(在本例中为20
)以及我们使用学习率查找器找到的最佳学习率:
learn_lm.fit_one_cycle(20, 1e-1)
使用我们相对较小的数据集,在 Nvidia Tesla K80 GPU 上训练超过 20 个纪元只需要几分钟,并给出了34.3
的验证困惑分数。
还不错!但我们肯定可以在这方面有所改进。
在第一次训练中,我们只训练了 LSTM 模型的最后一层。fastai
库允许我们“解冻”模型的早期层并训练它们。
在我们的第二次训练运行中,我们将使用较低的学习率来微调我们的模型,并使用slice
函数衰减模型中早期层的学习率:
learn_lm.unfreeze()
learn_lm.fit_one_cycle(20, slice(1e-2/10, 1e-2))
这背后的直觉是,模型中的早期层已经学习了语言的基本方面,所以我们不想改变太多。
在解冻模型的早期层并使用超过 20 个时期的衰减学习率进行训练之后,我们得到了验证困惑分数3.3
。
让我们看看我们的定制项目管理语言模型在生成项目更新评论方面做得如何:
learn_lm.predict("This project is", n_words=10)
该项目现已完成,目前正在工作过程中。
这是相当惊人的!该模型理解语法和标点符号,并在正确的上下文中使用项目管理特定的单词。
让我们保存自定义语言模型编码器,以便在分类器中使用:
learn_lm.save_encoder('lm_enc')
训练 RAG 状态分类器
现在我们有了一个定制的项目管理语言模型,我们可以构建一个模型来将文本注释分类为红色、琥珀色或绿色状态。
我们需要做的第一件事是创建一个文本分类数据库,就像我们在训练语言模型时所做的那样:
data_clas = TextClasDataBunch.from_csv(datapath, datafile, vocab=data_lm.train_ds.vocab, bs=32)
为了创建文本分类数据束,我们需要为该函数提供我们的定制语言模型词汇表(vocab=data_lm.train_ds.vocab
)和训练批量大小(bs=32
)。
接下来,我们定义一个文本分类学习器对象,使用文本分类数据束作为输入,并在0.5
设置 dropout:
learn_clas = text_classifier_learner(data_clas, drop_mult=0.5)
然后,我们加载之前保存的定制语言模型编码器:
learn_clas.load_encoder('lm_enc')
我们现在可以开始训练我们的 RAG 状态分类器,但是为了确保我们得到好的结果,我们需要一种方法来处理我们在探索数据时注意到的显著的类别不平衡。如果我们不处理这一点,分类模型很可能会简单地学习预测我们输入的任何文本评论的多数类(green
)。
我们可以处理类别不平衡的一种方式是计算不同类别的平衡,并使用这种平衡的逆来加权每个不同类别的损失函数,即,如果类别出现得更频繁,则该类别被扣分。
这只是我们在探索数据时计算的class_imbalance
的倒数,可以很容易地输入到我们的交叉熵损失函数中:
weights_balance = [(1-count/label_sum) for count in labelcounts]
loss_weights = torch.FloatTensor(weights_balance).cuda()
learn_clas.crit = partial(F.cross_entropy, weight=loss_weights)
现在我们已经处理了类别不平衡,我们可以训练我们的 RAG 状态分类器。我们遵循与训练自定义语言模型完全相同的过程。
首先,我们运行fastai
学习率查找器并绘制结果:
learn_clas.lr_find()
learn_clas.recorder.plot(skip_end=15)
然后,我们开始使用最佳学习率(1e-2
,取自上面的图)和我们选择训练的时期数(20
)来训练分类器模型:
learn_clas.fit_one_cycle(20, 1e-2)
由于这是一个高度不平衡的多类分类问题,我们不能使用准确性作为我们模型的性能度量。相反,我们将使用微观 F1 分数作为我们的性能指标,它考虑了精确度、召回率和类别不平衡。
在这个初始训练周期之后,我们的分类模型达到了 F1 分数0.77
。我们解冻早期的层并微调我们的模型:
learn_clas.unfreeze()
learn_clas.fit_one_cycle(20, slice(1e-3/10, 1e-3))
那就是我们!我们有一个 RAG 状态分类器,它使用一个定制的项目管理语言模型,并且达到 F1 分数0.79
。
让我们看看 RAG 状态分类器在我们从一个项目更新中输入一个文本注释示例时是如何工作的。
分类示例
数据里程碑 31/05 将无法实现,当前重新计划日期正在审核中。这是由于数据接收挑战,特别是“同步排序”数据迁移问题、平台复杂性和 IT 发布治理流程。
由于技术 SME 可用性造成的持续数据来源延迟,解决方案里程碑面临风险;升级继续优先考虑集团 IT 和技术部门的计划
工作正在进行中,以制定流程,商定计划中使用的工具,并确定流程改进的可行性、交付的逻辑分组,以纳入优化的计划。
learn_clas.predict(example)(Category **red**, tensor(2), tensor([0.0018, 0.0034, 0.9948]))
我们的模型正确地将上面基于文本的评论分类为红色状态更新,它读起来肯定像一个红色状态!
结论
在这篇文章中,我已经向你介绍了如何通过迁移学习,使用在相对较小的数据集上训练的定制语言模型,来构建深度学习文本分类器。
通过利用fastai
库的功能,我们现在有了一个定制的项目管理语言模型和 RAG 状态分类器,我们可以使用它来基于文本评论自动确定项目的状态。
这只是一个例子,说明了 Mudano 如何通过使用机器学习来自动化项目管理任务,从而使项目经理能够专注于真正重要的事情。
你想为一些世界上最大的公司做类似的项目吗?或者帮助开发支持自主项目的产品?如果有,那就在这里 查看 Mudano 的面向客户端的数据科学家和 R & D 数据科学家开放职位 或者在LinkedIn上联系我。
自动化科学数据分析第 1 部分:
为什么以及如何编写能够自动分析科学数据集的 Python 程序
许多人都熟悉数据科学技术的典型应用。一家拥有巨大数据集的公司要求某人挖掘数据集以进行理解,开发针对数据集训练的算法,并让公司使用他们的模型来推动业务决策。数据科学写作通常关注这种有价值的应用,但也有其他应用,人们可以从这些技术和思维模式中受益。例如,科学研究人员。
科学研究与数据科学有许多共同之处。经常有大量的数据集需要研究。这些数据集通常包含重要问题的答案。这些答案通常对决策很重要。主要区别在于,科学研究人员通常在电子表格中手动进行数据分析,而数据科学家通常利用 Python 中许多强大的软件包。
这篇文章的目的是向科学家介绍数据科学技术和思维方式可以改善科学研究的一些方法,以及为什么科学家应该考虑使用这些技术而不是他们当前的方法。基本原理很简单:大多数科学数据分析的数据分析部分是例行的,可以用 Python 脚本自动完成。这种自动化使科学家能够在一段时间内处理比竞争对手更大的数据集,错误更少。
我为什么要自动化我的数据分析?
这也许是最重要的问题。没有人会去学习一项新技能,在这里是 Python 编程和数据分析自动化这两项新技能,如果他们认为这对他们没有好处的话。幸运的是,科学家应该自动化数据分析的原因有很多,包括以下几点:
- 更快的数据处理速度:分析科学数据集可能会耗费数周或每年数月的时间。每个项目,无论是实验室实验、现场研究还是模拟研究,都会产生数百个甚至数千个数据文件。这些文件中的每一个都必须打开,研究以确保测试/监控/模拟正确进行,并分析以找到包含在该文件中的结果。然后,必须将结果添加到另一个文件中,并保存以供以后分析。手动执行此操作需要大量时间。它是昂贵的。又重复又无聊。自动化解决了所有这些问题。如果项目提前计划好,科学家可以编写一个 Python 脚本,自动对每个数据文件执行所有这些任务。那么这个过程可以在几分钟而不是几个月内完成。
- 减少的错误可能性:人类会犯错误。这只是人类的一部分。分析数百个测试文件需要数千次计算。它包括创造数百个情节。它需要在正确的位置保存数百个数据点。这些操作中的每一个都有可能出现打字错误、不正确地记忆常数、将文件保存在错误的位置、不一致的绘图轴标签等等。这一直是过程的一部分,需要大量的关注和时间来避免。同样,自动化有可能完全避免这个问题。科学家只需要确保一个 Python 脚本是正确的,而不是确保数百个数据文件中的所有计算和绘图都是正确的。然后将该脚本应用于每个文件。如果脚本中有一个错误,没有必要翻遍数百个文件来检查错误在哪里;只需更新脚本并在所有文件上重新运行即可。喝咖啡的时候。
- 访问 Python 包:有许多 Python 包是专门为让科学家的生活更轻松而设计的。Scikit-learn 对于需要进行回归或实现机器学习的科学家来说是一个优秀的软件包。Numpy 是一个数字软件包,能够执行科学家需要的大多数计算。Matplotlib 和 Bokeh 都提供了具有不同功能的绘图选项,允许灵活地创建绘图。Pandas 用数据框架取代了 Excel 表格,使数据能够以熟悉的方式进行结构化和操作。
- 可用于其他目的的时间:由于自动化数据分析让你可以在更短的时间内完成那部分工作,突然你就有时间从事其他活动了。也许你更愿意把时间花在业务拓展和提案写作上。或者你有一个你想指导的员工。或者你想花更多时间的客户关系。不管你觉得什么活动更有意义,分析你的数据分析会帮助你在那里花更多的时间。
我相信这些原因为学习自动化数据分析提供了坚实的理由,并且任何科学家这样做都是明智的。但我确信这些不是全部原因。你认为你还能获得什么好处?
由于实验室实验和相关的数据分析是科学研究的一个常见部分,本系列文章将重点关注如何自动化这一过程。
我需要采取什么步骤来自动化实验室数据分析?
首先,在更深入地讨论几个主题之前,我们将介绍项目的结构和总体设计。这一系列的文章将集中在这个过程的计划和数据分析方面。
不幸的是,每个项目都必须单独处理,详细的通用解决方案并不存在。然而,有一个基本的方法可以应用于每个项目,具体的编程(主要是计算)在项目之间有所不同。下面的一般过程提供了自动化数据分析项目的结构。
1.创建测试计划
确定需要执行哪些测试来生成回答研究问题所需的数据集。这确保了在项目结束时生成回归时有令人满意的数据集可用,并避免了执行额外测试的需要。
2.设计数据集以允许自动化
这包括指定哪些信号将被用来识别测试中最重要的部分,或者将被脚本分析的部分。这确保了有一种简单的方法来构建脚本,以识别每个单独测试的结果。
3.创建一个清晰的文件命名系统
要么创建一个数据打印方法,使每个测试中的测试条件的识别变得简单明了,要么与实验室测试人员合作来完成。这确保了程序能够识别每个测试的条件,这对于分析数据和存储结果是必要的。
4.将结果数据文件存储在特定文件夹中
这允许使用 Python 包“glob”来依次打开和分析来自每个单独测试的数据。
5.分析单个测试的结果
创建一个程序来自动循环所有的数据文件,并分析每个数据集。这个程序可能会使用 for 循环和 glob 来自动分析每个数据文件。它可能会使用 pandas 来执行计算,以确定测试的预期结果,并创建检查来确保测试正确执行。它还可能包括使用散景或 matplotlib 的绘图功能。
6.包括错误检查选项
在这个过程中可能会出现许多错误。也许有些测试有错误。也许程序计算有错误。通过确保程序提供足够的输出来检查测试结果和后续数据分析的质量,使您的生活更加轻松。这可能意味着打印测试图,以便进行视觉检查,或者添加一种算法,将测量数据和计算结果与预期进行比较,并报告错误。
7.逻辑地存储数据
每次测试的计算值需要存储在表格和数据文件中,以备后用。这些值的存储方式可能会使剩下的步骤变得容易,也可能变得不可能。数据通常应该存储在不同的表中,这些表提供了以后执行回归所需的数据集。
8.从产生的数据集生成回归
创建一个程序,该程序将打开步骤 7 中存储的数据并创建回归。它应该包括一个算法来创建每个期望的回归,匹配步骤 7 中确定的数据存储结构。确保该程序提供足够的统计和视觉输出,以便对结果进行彻底验证。
9.验证结果
使用步骤 8 中提供的统计和可视化输出来验证回归结果。确定模型是否足够精确。如果没有,要么返回步骤 7 并生成不同的回归,要么返回步骤 1 并添加额外的测试以创建更全面的数据集。如果模型足够精确,就公布它的优点和缺点的详细描述,以便将来的用户了解应该/不应该使用该模型的情况。
后续步骤
这篇文章介绍了使用 Python 脚本自动化科学数据分析的概念、动机和过程。本系列的其余文章将指导你完成上述 9 个步骤。下一篇文章将讨论第 1 步到第 6 步,让你对如何自动分析单个实验室测试有一个明确的理解。第三篇也是最后一篇文章将讨论如何存储每次测试的数据,并将其组合起来形成回归。当这两篇文章中涉及的主题结合在一起时,您将能够编写脚本来自动执行特定项目的整个数据分析过程。
我希望在那里见到你,也希望你觉得这些帖子有用。
自动化科学数据分析第 2 部分:
如何构建您的项目,以便 Python 程序能够理解您的数据文件
自动化科学数据分析的第一步是确保您的程序能够理解每个文件中包含的数据。这一步有三个主要挑战:
- 首先,来自测试的数据必须以一种程序能够识别数据的重要部分的方式来组织。许多测试在进入具有可用数据的测试部分之前会有预热阶段、调节阶段和/或过渡阶段。为了分析数据集,程序必须使用一致信号来识别要分析的正确周期。本文将介绍几种潜在的解决方案,您可以使用它们来克服这一挑战。
- 第二,程序必须有识别每个测试条件的方法。这些条件对于执行计算以理解数据,以及将结果存储在适当的位置都至关重要。这篇文章将介绍几种不同的方法来指导你的程序获得每个测试的条件。
- 第三,每个测试的数据必须有自己独特的文件,前面的建议才能起作用。有时来自整个项目的数据文件在一个文件中,这使得识别每个测试的条件更加困难。本文将提供两个解决方案来帮助您分离这些文件,为每个测试创建一个单独的数据文件。
为自动化实验室数据分析设计数据集
可重复数据集允许创建程序,每次都以完全相同的方式处理数据集,无需修改。与此同时,所有的实验和/或模拟数据集都将是复杂的,在整个测试过程中会发生变化,或者在比其他人更感兴趣的时期发生变化。因此,目标是在潜在的不可重复的过程中创建可重复的信号。
有几种方法可以做到这一点。它们包括使用阀门状态或控制设定点作为表明试验已改变阶段的信号,将测量条件与设定点进行比较,或使用试验时间。这些选项将以热交换器的单次测试为例进行说明。
引入单个数据集
本主题将使用模拟逆流换热器测试过程中发生的情况的示例数据集进行描述。这不是实际的实验室数据;相反,它是专门为演示这些概念而创建的人工数据集。当表征热交换器时,感兴趣的主要输出是稳态效率。确定有效性的公式如公式 1 所示。根据等式 1,该测试中的重要测量值是装置两侧的流速、入口温度和出口温度。
Equation 1: Heat Exchanger Effectiveness
图 1 和图 2 显示了可能来自典型测试的示例数据,图 1 显示了水流速数据,图 2 显示了温度数据。数据集模拟了一个测试,该测试在设备两侧具有相同的流速,热侧水温为 100.4 度,冷侧水温为 50 度。为了模拟实验数据中固有的可变性,在人造数据集中加入了一些随机性。
为了便于讨论,需要注意的重要一点是,这个测试有三个阶段。第一阶段是测试的条件阶段。在这一阶段,整个系统用 70 度的水冲洗,以确保装置有一个稳定的启动条件。第一阶段可以被识别,因为温度数据都是大约 70 度,并且流速接近 0.5 加仑/分钟。在第二阶段开始之前,该阶段持续测试的第一个 410 秒。第二阶段是预热阶段,此时热水和冷水进入设备,设备接近稳态运行。因为流速从大约 0.5 加仑/分钟突然跳到大约 3.5 加仑/分钟,所以它可以被识别。第三阶段是测试的稳态有效性部分。在第三阶段,流速相当稳定在 3.5 加仑/分钟,热侧入口温度相当稳定在 100.4 度,冷侧入口温度相当稳定在 50 度。因为系统运行稳定,所以它用于识别设备在稳态条件下的性能。该阶段从 440 秒开始,直到测试结束。
Figure 1: Example Water Flow Data from a Typical Test
Figure 2: Example Temperature Data from a Typical Test
图 3 显示了使用图 1 和 2 所示的数据和公式 1 计算的有效性。在测试的前两个阶段计算的有效性是没有价值的。这是因为在测试过程中,系统不是在稳定状态下运行的,而稳定状态的有效性才是我们所关心的。
Figure 3: Calculated Effectiveness From the Sample Data
图 3:使用样本数据计算的有效性
请注意,在试验的不同阶段,稳态有效性有很大的差异。这些差异给自动化数据分析带来了挑战。由于每次测试的预期结果是计算装置在稳定状态下的平均有效性,包括前两个阶段的数据将产生错误的结果。这需要过滤数据集,以便分析集中在所需的部分,并设计实验来实现它。
分离所需数据集的方法
有无数种方法可以分离出所需的数据集。诀窍是根据个人的需求和对可用数据的控制,找到一种适用于任何给定应用程序的方法。本节将描述几种不同的方法,同时比较它们的优缺点。
使用控制信号
分离所需数据的最有效方法是在数据集中打印一个控制信号。该控制信号陈述了识别测试的适当阶段的测试的一些条件。使用该控制信号过滤数据集允许分析器减少数据集以仅包括相关数据。
使用示例热交换器分析,打印流量控制阀的状态将达到此结果。阀的状态必须改变,以使通过装置的流速在第一阶段结束时从 0.5 加仑/分钟突然变为 3.5 加仑/分钟。打印该控制阀信号为程序提供了一个坚实的点,以识别调节阶段已经结束,测试阶段已经开始。图 4 显示了添加了控制阀信号的典型测试的相同流量数据。
Figure 4: Valve Status and Flow Data in a Typical Test
图 5 显示了通过阀门状态信号过滤的来自同一数据集的有效性数据。由于使用了该阀门信号,该有效性数据集仅包括当有流体通过该装置时的数据(阶段 2 和 3)。包含第 2 阶段的数据会导致少量的错误,尽管远远没有包含第 1 阶段的数据那么多。图 5 所示的有效性数据的稳定性表明,稳态期间的平均有效性是一个精确的计算结果。
Figure 5: Effectiveness Data Filtered by a Valve Signal
使用已知的时间
分离所需数据部分的第二种方法是过滤数据以选择特定的时间段。这种方法效果很好,因为它给了用户对结果数据集的最大控制权。与使用控制信号相比,该方法可以将数据集单独隔离到第三阶段,而不包括第二阶段。从第二阶段移除数据将略微增加结果的准确性。使用基于时间的控制的缺点是,它要求用户在每次测试中确定一个相同的时间段。如果与最初的测试计划有任何偏差,那么分析脚本必须进行相应的修改。
示例数据集中的第三阶段开始于 440 秒,因此这是用于分析数据的逻辑时间条件。然而,没有办法确定每一个测试都将相同地进行,并且第三阶段将在每次 440 秒时开始。因此,稍后设置过滤器可以提高分析的安全性。不利的一面是,分析是使用更少量的数据完成的,但是影响应该是可以忽略的,因为测试的稳态部分是 935 秒长。图 6 显示了过滤数据对测试最后 900 秒的影响。
Figure 6: Effect of Filtering the Data to the Last 900 Seconds
使用测试最后 900 秒的数据会将结果数据集隔离到测试的第三阶段。它还会排除样本数据中第三阶段的一小部分,以防第二阶段在其他测试中变慢。同时,900 秒转换为 15 分钟,这对于识别设备的稳态操作来说绰绰有余。图 7 显示了过滤后仅包含样本数据集最后 900 秒的有效性数据。
Figure 7: Effectiveness Data Filtered to the Last 900 Seconds
如何确定实验室测试的条件并拆分大数据文件
该过程的下一步是编写您的脚本,以便它知道它所分析的每个测试的条件。该程序必须能够确定测试条件,以执行必要的计算,并正确存储数据,供以后进一步分析。有几种方法可以向程序提供测试条件信息,包括以下方法:
- 以数据文件的名称写入测试条件,
- 将测试编号放在数据文件的名称中,并引用测试计划,以及
- 从数据集中读取测试条件。
这些解决方案都有一个共同的假设,即每个测试都来自一个单独的数据文件。然而,有时数据集在单个数据文件中包含几个测试。在这种情况下,必须开发另一种算法来将大数据文件分割成单独的数据文件。解决这一问题的一些可能方法包括:
- 基于测试之间的已知调节期分割数据集,以及
- 使用测试中打印的控制信息。
以下章节详细介绍了三种确定测试条件的方法。
将条件写入数据文件的名称中
这种策略使用数据文件的名称来存储测试条件。这样,分析程序可以在打开文件时读取条件。这种方法的一个主要优点是测试条件也容易被读者理解。不利的一面是文件名可能会变得又长又麻烦。
例如,假设使用以下参数进行测试:
- 热端和冷端流速均为 3 加仑/分钟,且
- 热端入口温度为 100.4 华氏度,且
- 冷端入口温度为 50 华氏度
以下是包含此信息的文件名示例:
flow hot = 3 _ flow cold = 3 _ temperature hot = 1004 _ temperature cold = 50 . CSV
请注意,文件名中不能使用小数点,因此热端入口温度应写成“1004”而不是“100.4”。
为了从这个文件名中读取条件,数据分析脚本需要一个算法来读取文件名的内容。最简单的方法是创建一个算法来读取位于两个标识符之间的值。这些标识符是用于将参数与文件名中的描述性术语分开的字符。在我们的例子中,它们是“=”和“_”。继续热交换器的例子,四个参数的值可以用下面的代码来标识。
def Find_Between(String, First, Last):try:Start = String.index(First) + len(First)End = String.index(Last, Start)return String[Start:End]Flow_Hot = float(Find_Between(filename, ‘FlowHot=’, ‘_FlowCold))Flow_Cold = float(Find_Between(filename, ‘_FlowCold=’, ‘_TemperatureHot’))Temp_Hot = float(Find_Between(filename, ‘_TemperatureHot=’, ‘_TemperatureCold’))/10Temp_Cold = float(Find_Between(filename, ‘_TemperatureCold=’, ‘.csv’))
Find_Between 需要三个输入:1)正在搜索的完整字符串,2)感兴趣部分之前的字符串部分,以及 3)感兴趣部分之后的字符串部分。然后,它返回位于描述符之间的字符串。如果没有找到指定的描述符,它将返回一个错误。
Find_Between 定义之后的四行代码调用函数来标识文件名中指定的四个参数的值,并将它们转换为 float 类型。在 T_Hot 的情况下,该值除以 10,因此程序将其视为 100.4 而不是 1004。
在文件名中引用测试号
另一种解决方案是在文件名中打印测试号,并让程序打开测试文件来识别条件。这种方法实现起来不太复杂,并且数据文件的名称也更短。然而,文件名的描述性要差得多,这使得手动识别每个测试的内容更加困难,如果这被证明是重要的话。
例如,考虑名为“14 HX 2018 年 1 月 30 日. csv”的文件。该文件代表 2018 年 1 月 30 日进行的第 14 次热交换器试验。为了识别测试条件,程序需要识别它是测试号 14,并通过参考测试矩阵来识别测试 14 的条件。下面一行代码可以识别测试号:
Number_Test = int(filename[0:3])
这段代码读取文件名中的前两个索引,在本例中为“14”,并将它们转换为一个整数值。注意,在只有一位数的测试中,返回的字符串后面会跟一个空格。转换为整数时,空格会被删除。
然后必须参考测试矩阵,根据测试矩阵确定测试条件。它可以用熊猫来打开。read_csv 函数,如下所示。
Test_Matrix = pd.read_csv(r’C:\Users\JSmith\DataAnalysis\TestMatrix.csv’)
注意,代码中的路径是完全虚构的,并且必须被修改以读取测试矩阵的位置。
最后一步是从测试矩阵中读取测试条件。这是通过使用。熊猫锁功能。假设测试矩阵如表 1 所示。测试编号中显示“…”的行表示矩阵中有额外的测试,但没有显示出来。
可以使用下面的代码来确定测试的条件。
Flow_Hot = Test_Matrix.loc[Number_Test, ‘Hot-Side Flow Rate (gal/min)’]Flow_Cold = Test_Matrix.loc[Number_Test, ‘Cold-Side Flow Rate (gal/min)’]Temperature_Hot = Test_Matrix.loc[Number_Test, ‘Hot-Side Inlet Temperature (deg F)’]Temperature_Cold = Test_Matrix.loc[Number_Test, ‘Cold-Side Inlet Temperature (deg F)’]
此代码将搜索使用 pandas.read_csv 读取第 14 行的数据帧时创建的 Test_Matrix 数据帧,其中 Test_Number = 14,并从相应的列中提取值,如每行代码中所指定的。通过这种方式,可以识别每个测试的条件,并为以后的分析做好准备。
从数据文件中读取测试条件
最后一个选择是读取文件中的数据,并根据发生的情况确定测试条件。这个选项是最不准确的,因为它有错误识别条件的风险,应该被认为是最后的手段。这种方法的优势在于它不需要实验室测试人员的帮助,并且可以识别未指定数据文件的测试条件。
请记住,测试的稳定状态部分是在测试的最后 920 秒进行的。测试的标称条件可以通过计算在此期间每个点的平均值来近似。可以使用下面的代码来估计四个必需的参数。
Flow_Hot = Data_File[‘Hot-Side Flow Rate (gal/min)’][-50:].mean()Flow_Cold = Data_File[‘Cold-Side Flow Rate (gal/min)’][-50:].mean()Temperature_Hot = Data_File[‘Hot-Side Inlet Temperature (deg F)’][-50:].mean()Temperature_Cold = Data_File[‘Cold-Side Inlet Temperature (deg F)’][-50:].mean()
这四行代码选择每个数据列中的最后 50 个条目,并计算平均值。这提供了测试稳定状态期间该数据点的平均值,以及代表测试条件的近似值。
下一步是确定运行测试时使用的标称条件。因为测量数据永远不会与标称条件完全匹配,所以测试矩阵中指定的值与分析脚本确定的值之间会有细微的差异。使用测试矩阵来确定脚本中的标称值可以更容易地跟踪结果。这是通过将测试中的识别值与测试矩阵中的标称值进行比较,并识别差异最小的情况来实现的。考虑以下可用于识别标称 Flow_Hot 值的代码。
Test_Matrix = pd.read_csv(r’C:\Users\JSmith\DataAnalysis\TestMatrix.csv’)Test_Matrix[‘Difference Flow Hot (gal/min)’] = abs(Test_Matrix[‘Hot-Side Flow Rate (gal/min)’] — Flow_Hot)Flow_Hot = Test_Plan.loc[Test_Plan[‘Error_Flow_Hot’][Test_Plan_First:Test_Plan_Final].idxmin(), ‘Hot-Side Flow Rate (gal/min)’]
这段代码中发生了三件事:
1.第一行读取测试矩阵。
2.第二行在表中创建一个新列,该列标识每个测试的标称条件和当前测试的估计条件之间的差的绝对值。
3.第三行标识标称条件和测量条件之间差异最小的行,并将 Flow_Hot 设置为等于为该测试指定的热端流量。
请记住,该代码返回的标称条件与测试过程中发生的情况最接近。在测量不确定度较高或每次测试之间标称条件差异较小的情况下,该代码可能会识别不正确的标称条件。因此,这种方法应被视为最后的手段。
拆分数据文件
所有先前描述的方法都假设每个测试都有一个独立的数据文件。如果数据是通过包含在一个大数据文件中的几个测试交付的,那就不行了。在这种情况下,脚本必须将不同的测试从数据集中分离出来,并创建单独的数据文件。这可以通过识别可重复的信号并在该信号出现时创建新的数据文件来实现。在我们的热交换器示例中,可重复信号的两个示例包括:
- 每个测试在开始前都有一个冲洗期。冲洗期用于确保设备在可重复的条件下开始每次测试。在 70 华氏度时,装置两侧的流量为 4.15 加仑/分钟。流速和/或温度条件可用于识别该冲洗周期。
- 控制阀用于引导水流通过试验装置的不同部分。一种阀门配置指示冲洗周期,而另一种指示测试周期。流量阀配置是识别冲洗周期的另一种选择。
注意,使用控制阀状态的第二种选择比使用温度和/或流量条件更可靠。这是因为一些测试可能使用类似于刷新周期的条件,并且存在脚本混淆两者的风险。
一旦选择了标识符,就必须编写代码来定位发生这种情况的实例,并相应地创建新的测试文件。这可以通过删除表示刷新周期的数据并识别表索引发生变化的实例来完成。以下代码显示了一个示例,其中当“电磁阀 1 状态(-)”= 0 时发生冲洗,当“电磁阀 1 状态(-)”= 1 时进行测试。
Data_File = pd.read_csv(r’C:\Users\JSmith\Data.csv’)Data_File[‘Index’] = Data_File.indexData_File = Data_File.drop(Data_File[Data_File[‘Solenoid Valve 1 Status (-)’] == 0].index)Data_File = Data_File.reset_index()Data_File[‘Index_Shift’] = Data_File[‘Index’].shift(periods = -1)Data_File[‘Index_Shift’] = Data_File[‘Index_Shift’] — Data_File[‘Index’]End_Of_Tests = []End_Of_Tests = End_Of_Tests + Data_File[Data_File[‘Index_Shift’] > 1].index.tolist()End_Of_Tests.append(Data_File.index[-1])
该代码执行以下操作:
1.前两行读取数据文件,并创建一个标题为“Index”的列,该列与表的索引相匹配。
2.第三行删除表中“电磁阀 1 状态(-)”= 0 的所有行,从而删除代表冲洗周期的所有代码部分。
3.第四行重置表的索引,这样看起来好像没有删除任何行。请注意,标题为“Index”的列在此步骤中没有更改。
4.第五行创建了一个名为“Index_Shift”的新列,它复制了“Index”中的值,但在表中上移了一行。它提供了一种简单的方法来识别从一行到下一行有多少“索引”变化。
5.第六行将任何给定行中的“Index_Shift”更改为等于“Index”减去“Index_Shift”。在测试的稳定状态部分,该值等于 1。在清除周期被移除并且数据现在从一个测试跳到下一个测试的情况下,“Index_Shift”将大于 1。
6.最后三行创建了一个名为“End_Of_Tests”的数组,数组中的条目表示与任何给定测试中的最后数据读数相对应的行的索引。它用“Index_Shift”大于 1 的任何行的索引填充。它还接受数据集中的最终索引,因为“Index_Shift”方法不会将该行标识为测试中的最终读数。
这段代码运行后,“End_Of_Tests”数组提供了一个列表,列出了与每个测试的结尾相对应的所有索引。然后,代码需要将数据集分割成单独的文件,并将它们另存为新文件。带有描述性名称的 csv 文件。这可以通过以下步骤实现:
1.创建一个循环遍历“End_Of_Tests”数组的 for 循环。
2.使用中描述的技术,从数据文件中读取测试条件,以确定每个测试的标称条件。
3.为描述测试条件的每个数据文件创建一个文件名。这样做的代码类似于:
File_Name = “FlowHot=” + str(Flow_Hot) + “_FlowCold=” + str(Flow_Cold) + “_THot=” + str(T_Hot) + “_TCold=” + str(T_Cold)
这将创建一组单独的数据文件,可以使用包含测试条件的文件名对这些文件进行单独分析。它们已经准备好被打开,并使用中描述的技术理解,将条件写入数据文件的名称。
后续步骤
前一篇文章关注于分析独立测试的独立结果。到目前为止,我们已经讨论了如何设计允许自动化的测试,如何从数据文件中识别测试的条件,如何根据需要分割文件,一些可用于分析数据的有用的 Python 包,以及如何自动确保测试和分析是有效的。下一篇文章将关注如何逻辑地存储这些数据文件以方便以后对数据集的分析,如何从存储的结果生成回归,以及如何验证/记录这些回归的有效性。
在自动化数据分析过程中生成回归
如何从完整的数据集推导、验证和记录回归
这是教您如何自动化科学数据分析的四篇系列文章中的第六篇。第一篇文章介绍了概念,提供了动机,并描述了一般过程。第二篇、、第三篇和第四篇文章描述了如何控制数据集、识别每个测试中的条件、处理数据以及检查数据错误。第五篇文章描述了如何以逻辑方式存储数据,以便于生成回归。这第六篇,也是最后一篇文章将教你如何从这些结果中开发回归,并验证和记录结果模型。
从存储的数据生成回归
最后一个基于 Python 的实验室数据分析自动化主题是从存储的数据中生成和验证回归。这往往是实验室数据分析项目的最终目标,在宣布项目完成之前,还有几件事情需要考虑清楚。生成回归时,必须考虑以下主题:
- 如何确定回归的最优阶,
- 用 numpy 创建一维回归,
- scikit 简介-学习创建 n 维回归,
- 验证模型,以及
- 可视化回归和验证的结果。
本节偶尔使用回归预测热交换器性能的例子。有关该技术的介绍,以及用于建模的测试和数据分析,请参见第 2 部分。
确定最佳回归结构
回归的顺序对最终模型的预测精度有着巨大的影响。高阶回归更加灵活,能够比低阶回归更好地统计匹配数据集,或者匹配更复杂的数据集。然而,增加的灵活性可能会导致模型在统计上看起来很好地符合数据,但在数据集中的测量点之间进行预测时却有很大的不准确性。低阶回归不太灵活,通常也难以在统计上匹配数据,但提供了更稳定的预测。这可能导致测量点的精度较低,但测量点之间的精度较高。
这种差异是由数据集中的数据点数量造成的。需要更多的数据点来创建更高阶的稳定回归。图 1 和图 2 清楚地显示了这种影响。两个图都显示了二阶、三阶和四阶回归。图 1 显示了使用完整数据集创建的回归。注意回归中没有显著的差异。四阶回归比三阶回归更接近数据集,三阶回归比二阶回归更好。但它们都非常接近,并且由于趋势与测量数据显示的趋势非常接近,因此可以相信它们能够准确预测中间值。在这种情况下,显然应该选择 4 阶回归。
Figure 1: Example Regression Created from a Thorough Data Set
图 2 中的回归不是这样的。图 2 显示了使用同一组测量数据的子集创建的回归。在这种情况下,4 阶回归再次比 2 阶或 3 阶回归更好地匹配测量的数据点。然而,对于高阶回归来说,既太复杂又没有足够的数据。当他们试图用有限的数据集来匹配数据点呈现的曲线形状时,他们变得不太稳定。这可以通过三阶回归,尤其是四阶回归的波动来观察。虽然四阶回归明显地与测量数据相匹配(三者中最好的),但是它不能被信任在数据集的边界内进行插值。在流速高于 3.5 加仑/分钟时尤其如此。
Figure 2: Regressions Created from a Limited Data Set
这个问题有几种可能的解决方法。它们按优先顺序排列如下:
- 收集更多数据以创建更好的数据集,
- 将数据集分成多个部分,并生成多个低阶回归,以及
- 尝试从当前可用的选项中确定最佳回归。
收集更多数据
通过提供更多的约束点,收集更多的数据会产生更稳定的回归。当确定新的测试来改进数据集时,请指定填补当前数据集中较大空白的测试。例如,如果添加额外的点来填充从 3.5 到 5.5 加仑/分钟和从 5.5 到 7.5 加仑/分钟的间隙,图 2 所示的简化数据集将更加完整。
分割数据集
拆分数据意味着确定多个部分,每个部分可以有单独的、平滑的回归,将数据集拆分成多个部分,并为这些拆分的数据集创建单独的回归。虽然它减少了每次回归的数据量,但它为它们的匹配创建了更平滑的形状。因此,即使数据集较小,也有可能得到更平滑的曲线和更好的匹配。在这种情况下,分割数据集,从 0.5-2 加仑/分钟创建一个回归,从 2.5-7.5 加仑/分钟创建第二个回归,会产生更好的结果。图 3 显示了使用前面提到的分割创建二阶和三阶回归的结果。
Figure 3: Regressions Created from a Limited Data Set, Split at 2 gal/min
结果显示,与使用单一数据集相比,使用分割数据集可以获得更好的匹配。分裂发生在 2 加仑/分钟,并且通过二阶回归预测的突然增加而明显。该凸起显示了在 2.0-2.5 加仑/分钟范围内使用二阶回归的误差增加。除了该区域,二阶回归与数据集非常接近。三阶回归在分界点没有显示出同样的不确定性,并且在整个 0.5–7.5 加仑/分钟范围内与回归非常接近。这表明,以 2 加仑/分钟的速度分割数据集,并为以上和以下创建单独的回归的方法对于该数据集非常有效。
确定最佳选项
最低效的方法是从可用选项中选择最佳回归,这是在不可能收集更多数据并且拆分数据集不能产生令人满意的结果时使用的方法。在这个数据集和图 2 所示的回归中,这意味着使用四阶回归。二阶回归可能是三个选项中最平稳的一个,但它明显高估了低流速时的有效性,低估了高流速时的有效性。三阶回归更接近,但也不太稳定。四阶回归非常接近地匹配数据点和趋势,直到 3.5 加仑/分钟。从 3.5 加仑/分钟到 5.5 加仑/分钟,它将预测过高,从 5.5 加仑/分钟到 7.5 加仑/分钟,它将预测过低;然而,在该范围内的不准确预测对所有三个选项都是真实的,并不比三阶回归更引人注目。当使用这种回归时,重要的是要记住它在低于 2.5 加仑/分钟时非常精确,在更高的流速时不太可信。
使用 Numpy 创建回归
NumPy 是 Python 中可用的科学计算工具包。在它提供的众多工具中,有一个用于创建一维回归的工具集。主要的两个工具是:
- polyfit:该工具使用用户提供的 x 和 y 数据确定 1 维 n 阶多项式的系数。NumPy.polyfit 以语法“numpy.polyfit(Data_x,Data_y,Order)”调用。
- poly1d: poly1d 使用用户指定的系数创建一个回归,并将它们赋给一个变量,以便以后可以很容易地引用该回归。NumPy.poly1d 是用语法“numpy.poly1d(系数)”调用的。
如果结果的存储方式与存储中间结果以供以后分析的建议一致,这些工具可以很自然地生成结果的回归。该过程使用以下步骤:
1.打开包含所需数据的数据文件,并将其存储在数据框中。对于这个例子,数据帧将被称为“数据”
2.使用 NumPy.polyfit 确定数据集的系数,并将它们存储到变量中。这可以通过类似下面的代码来实现:
Coefficients = numpy.polyfit(Data[‘Flow Rate (gal/min)’], Data[‘Effectiveness (-)’], 2)
在这种情况下,将流速作为 x 数据、有效性作为 y 数据的二阶回归系数存储到变量“系数”中。在热交换器中,该数据集仅具有单个流率,表示在设备的任一侧具有相同流率的情况。
3.使用系数调用 NumPy.poly1d,将回归作为函数分配给变量。例如,上一步中的系数可用于通过以下方式创建回归:
Effectiveness_SecondOrder = numpy.poly1d(Coefficients)
现在,可以通过调用“有效性 _ 二阶”函数,使用二阶回归来估计该热交换器的有效性。
4.最后一步是调用函数来生成所需的回归估计值。如何使用它的几个例子如下:
- 如果使用回归来评估特定条件下的结果,请调用引用该条件的函数,并将其赋给一个描述性变量。例如,任一侧流量均为 2 加仑/分钟的热交换器的效率可通过下式确定和保存:
Effectiveness_2_GalPerMin = Effectiveness_SecondOrder(2).
- 另一种可能的用途是用估计回归值填充数据框的列。这在验证模型时非常有用,因为回归估计值可以存储在测量值旁边的数据框中,很容易进行比较。这可以通过类似如下的代码来实现:
Data[‘Effectiveness, Estimated, Second Order (-)’] = Effectiveness_SecondOrder(Data[‘Flow Rate (gal/min)’]
c.第三种可能性允许绘制平滑回归曲线,并使用 NumPy“arange”函数。NumPy.arange 创建用户指定的值范围。它的语法是这样的:
numpy.arange(Minimum Value, Maximum Value, Step)
例如,numpy.arange(0.5,7.6,0.1)从 0.5 开始创建一个范围,每个值以 0.1 为步长递增,最大值为 7.6。这对于绘制平滑曲线非常有用,因为这是一种在期望的时间间隔预测回归结果的快速方法。例如,以下代码将创建一个 x 和 y 数据集,用于以 0.1 加仑/分钟的间隔绘制回归曲线,从最小值 0.5 加仑/分钟到最大值 7.5 加仑/分钟:
x_array = np.arange(0.5, 7.6, 0.1)Effectiveness_array = Effectiveness_SecondOrder(x_array)
Scikit 简介-学习
目前,创建 n 维 n 阶回归的最佳工具是 scikit-learn 软件包。它基于 scipy、NumPy 和 matplotlib,通常用于数据科学和机器学习领域。它提供了许多不同的回归工具,有许多不同的方法。那些有兴趣了解 scikit-learn 中所有功能的人应该查阅他们的文档,并准备学习许多不同类型的回归技术。了解数据科学的基本原理也将是有益的,关于 Coursera.org,吴恩达出版了一个信息丰富的免费课程。由于对数据科学和 scikit-learn 的全面讨论对于本文来说太长了,本节将重点介绍一些基本的线性回归技术。
使用 scikit-learn 创建线性回归的两个非常有用的工具是 1)sk learn . preprocessing . polynomial features 和 2)sk learn . linear _ model . linear regression。
多项式功能提供了一组矩阵运算,用于将数据转换成线性回归所需的形式。它创建一个矩阵,该矩阵由小于或等于用户指定的输入变量的所有组合组成。例如,使用具有两个输入变量(x 和 y)的多项式特征创建的准备二阶模型的矩阵将具有项[1,x,y,x2,xy,y2]。这种方法有时被称为“黑盒建模”,因为它并不试图理解模型行为背后的结构,而是旨在创建完全基于数学技术的匹配回归。
可以使用以下步骤创建输入矩阵:
- 通过调用多项式 Features 并指定回归的顺序来创建 matrix 对象。请注意,scikit-learn 使用术语“程度”而不是“顺序”。
- 为即将到来的线性回归安排正确格式的输入数据。对于多项式特性,这意味着单个矩阵包含指定每个测试条件的子矩阵。例如,具有三个测试和两个输入条件的输入矩阵将具有[[x_1,y_1],[x_2,y_2],[x_3,y_3]]的形式。
- 对输入数据调用 polynomial features fit _ transform 函数,并使用 numpy.delete 移除第一行。
例如,以下代码使用两个输入“热流量(加仑/分钟)”和“冷流量(加仑/分钟)”为五阶回归生成正确的矩阵。请注意,输入数据矩阵是使用从有效性数据框中读取值的 for 循环创建的。
poly = PolynomialFeatures(degree=5)All_Flow_Pairs = []for i in Effectiveness.index: FlowRate_Hot = Effectiveness.loc[i, ‘Hot Flow Rate (gal/min)’] FlowRate_Cold = Effectiveness.loc[i, Cold Flow Rate (gal/min)’] All_Flow_Pairs.append([FlowRate_Hot, FlowRate_Cold]) All_Flow_Pairs_Transformed = poly.fit_transform(All_Flow_Pairs) All_Flow_Pairs_Transformed = np.delete(All_Flow_Pairs_Transformed, (0), axis = 1)
LinearRegression 旨在轻松接受该矩阵,并生成指定的回归。它提供了对这个过程特别有用的四个函数。它们是:
- 。拟合:此函数接受输入数据矩阵和匹配结果矩阵,并将多项式特征中指定的回归拟合到数据。这是创建回归的步骤。
- 。coef_:这个函数打印描述回归的系数。存储来自的结果。coef_ 到一个变量,并在程序结束时打印它,允许存储系数供以后外部使用。
- 。intercept_:如果所有输入都设置为 0,此函数将返回回归的值。
- 。score:该函数返回回归的 r2 值,与用于创建回归的数据集进行比较。它提供了回归预测输入数据集的能力的度量。这个概念将在下一节详细讨论。
以下代码延续了 PolynomialFeatures 中的示例,并显示了 LinearRegression 的函数如何创建、记录和测试回归。
clf = LinearRegression()clf.fit(All_Flow_Pairs_Transformed, Effectiveness[‘Effectiveness (-)’])n_Dimensional_Coefficients = clf.coef_n_Dimensional_Intercept = clf.intercept_n_Dimensional_Score = clf.score(All_Flow_Pairs_Transformed, Effectiveness[‘Effectiveness (-)’])
验证模型
模型开发中最重要的部分,也是这个概念文本中无法详细描述的部分,是验证。验证是确保模型生成的预测与建模的现象相匹配的过程。这是一个复杂的、多阶段的过程,永远不会真正结束。执行质量模型验证的步骤如下:
- 确保模型与用于创建它的数据集相匹配,
- 将模型预测与附加数据集进行比较,
- 发布报告,详细说明模型的优点、缺点和适当的应用。
验证模型
第一步是将模型预测与源数据进行比较。这一步通常被称为“验证”这一步的目标很简单:确保模型与用来创建它的实验数据相匹配。正如本书中所讨论的,在为创建模型而明确创建特定数据集的情况下,模型中的误差应该非常低。执行此步骤时,需要回答两个一般问题:
- 模型是否在可接受的误差范围内与数据集匹配?
- 数据集的哪些方面被模型很好地/差地表示了?
通常,如果误差小于用于收集数据的测量的不确定性,则认为模型在可接受的误差限度内与数据集匹配。这经常被用作极限,因为它代表了知识的极限;如果模型和测量值之间的误差小于测量值的不确定性,那么就没有办法知道模型是不完美的。
不可避免的是,这个模型在一些预测上会比其他的更好。识别和研究这些差异是很重要的。它们可能显示出模型中的缺陷,可能需要使用不同的建模方法来纠正它们。如果它们是对最终结果没有重大影响的小问题,那么记录下来就足够了。确定最佳回归结构一节对这些情况提供了一些回答。
验证模型
模型验证的第二步是将模型预测与第二个数据集进行比较。这是重要的一步,因为第一步并没有真正验证模型,它只是表明它能够匹配它在数学上被迫匹配的数据集。
这个挑战的解决方案是在测试计划中包含额外的测试,但是不要将它们包含在用于生成回归的数据集中。将它们保存在一个单独的数据集中,该数据集是专门为模型验证而创建的。这样,它们对回归没有影响,并提供了可用于验证检查的附加点。
验证数据集中的测试应该尽可能彻底地测试模型。包括在模型对输入变化高度敏感的区域进行测试,以确保模型在这些范围内的预测是正确的。包括模型中所有不同变量的变化,以确保它准确地预测模型响应这些变量变化的行为。在原始数据集中数据点之间有较大间隙的区域进行测试,以确保模型在这些区域保持稳定,如所示,创建最佳回归结构。
在此验证阶段,尝试回答与第一阶段相同的问题。模型在测量不确定度范围内准确吗?有比其他地方更准确的地方吗?如果在测量不确定度范围内不准确,可以改进模型吗?和以前一样,任何可以改进的问题都应该改进,任何不能改进的问题都应该记录下来。
证明文件
模型验证过程的最后一步是发布发现,同时认识到这比简单的“有效”或“无效”声明更复杂。没有一个模型在所有方面都有效,或者在所有方面都无效。简单地宣布一个模型无效并不代表即使是有限的模型也能提供的价值。宣布一个模型是“有效的”给人的印象是它准确地预测了一切,没有弱点。
这个问题的解决方案很简单:不要宣称模型是有效的,而是公布模型的优点和缺点。这为用户提供了对模型适当使用的更准确的理解,允许他们决定何时应该使用模型,何时不应该使用模型。它还提供了支持未来改进模型的文档。
作为一个例子,这些文章使用了发展回归预测热交换器的稳态效率的例子。该模型设计用于预测流速在 0.5 至 7.5 加仑/分钟之间时的稳态效率。只要装置两侧的流速相同,它就非常精确。这些模型没有解决超出该范围的流速,或者设备两侧流速不同的情况。此外,它是专为稳态有效性而设计的,不应用于瞬态模拟中的预测。
结论
这一系列的四篇文章已经向您介绍了编写自动分析科学数据集的程序所必需的所有概念。您已经了解了以下主题:
- 自动化数据分析的一些可能的好处,
- 自动化数据分析的程序结构,
- 如何构建数据集以实现自动化,
- 如何识别每个数据测试的条件,
- 如何拆分数据文件,
- 如何编写一个遍历每个数据文件的 for 循环,
- 如何分析每个文件中的数据,
- 如何检查每个文件中的数据是否有错误,
- 如何存储每个文件中的数据,以便随时用于生成回归,以及
- 如何从数据集生成、验证和记录最终回归。
希望这些文章已经帮助你发展了新的技能,也希望你可以用它们在你的职业生涯中找到更多的轻松和满足感。
使用开源软件自动分析调查数据
第一部分:数据处理流程
你已经向电话里友好的声音承认,你要投票给怪物疯狂党;在那个弹出的在线测试中,你点击了百事可乐而不是可口可乐;你说你会在后续的客户满意度调查中高度推荐这家汽车经销商(但后来没有)。当全世界的人都向政治、医学、品牌、人力资源等领域的研究者表达自己的感受和看法时;数据最终在哪里?它是如何分析的?
市场研究仍在等待开源革命
在主流数据科学中,开源软件主宰着世界:如果你是认真的,你很可能,至少是部分地,在使用 Python 或 r。网飞的数据科学家在 Jupyter 笔记本上的指尖就能拿到公司的数据。AirBnb 开源了他们建立的工作流程自动化软件,以帮助他们在登记后立即自动估算上市房屋的终身价值。
让数据科学从业者如此强大的过多工具在很大程度上仍然不存在。市场研究人员依赖 SPSS、Merlin 和 Quantum 等专有软件,有可能成为数据世界的勒德分子。
Jupyter 笔记本
A Jupyter Notebook showing the results of an opinion poll in both table and chart form using the open source Quantipy library.
本文是一系列文章中的第一篇,展示了开源软件如何使用 Jupyter 笔记本和各种其他开源库等工具,大规模提高分析调查研究数据的生产率、质量和安全性。
Jupyter Notebooks(以下简称笔记本)是一个始于 2014 年的项目,旨在为科学研究、可复制的工作流、数据叙述和分析创建一套一致的开源工具。这是一个易于使用的基于网络的平台,而且碰巧这项技术也非常适合调查数据。
我们的目标是鼓励行业抓住集体的木屐,拥抱即将到来的数据革命。
自动化数据处理工作流程
我们假定我们已经收集了数据。在这些文章中,数据处理包括清理、重新编码、合并和加权数据等任务。使用笔记本,我们可以将这些任务安排到生产线或工作流程中。许多繁重的工作是自动化的,但是过程是可适应的:当工作流程的任何部分发生变化时,只需点击一个按钮,就可以很容易地按照定义的顺序运行所有其他部分。
我们将使用开源库 Quantipy(python 3 端口在这里),并从将数据读入 Quantipy 数据集开始(该数据之前是从 UNICOM mdd/ddf 文件转换而来的,但在后面的帖子中会详细介绍)。
import quantipy as qp
dataset = qp.DataSet("opinion poll")
dataset.read_quantipy(
path_meta="../data/interim/{}.json".format(filename),
path_data="../data/interim/{}.csv".format(filename)
)
我们将创建三个不同的笔记本,每个笔记本执行三个任务中的一个;清理、重新编码和加权,以创建流水线。在管道运行之前,数据被转换(用一个笔记本),以便该过程总是从原始数据开始。在以后的管道中,我们将能够用一个直接从数据库读取的笔记本来替换数据转换笔记本。这将使我们能够为客户提供实时更新。
The data processing workflow is run across multiple Jupyter Notebooks. This will allow us to run the entire workflow with the papermill library when anything changes and share specific parts of the process with other projects.
在后面的文章中,我们将介绍上述文件的自动创建,但是现在,我们将手动创建它们。
现在我们有了数据集(在 Quantipy 中,我们有两个数据结构。元数据:用于描述数据,数据:用于实际记录),我们可以编写组成管道的笔记本。我们从一个简单的 clean 命令开始
#file: 1_clean.ipynbdataset = dataset.filter('completed', {'SurveyCompletionStatus':6})
在这种情况下,清理是简单的,但在这里,用户可以,例如,使用机器学习来过滤掉欺诈性的答案。
接下来,我们记录数据。我们希望根据英格兰、苏格兰、北爱尔兰和威尔士对这些地区进行加权,但正如元数据所示,目前有太多地区无法应用该加权方案。
因此,我们希望通过将英格兰答案分组,但保留其他答案,来导出一个新变量。
#file 2_recode.ipynb# mapper arguments are: new code, new label, {variable: old codes}
mapper = [ (1, 'England', {'Regions': frange('3-5, 7-12')}),
(2, 'Scotland',{'Regions': [2]}),
(3, 'Wales', {'Regions': [6]}),
(4, 'Northern Ireland', {'Regions': [1]}),
(5, 'Other', {'Regions': [0]})
]# arguments: variable name, type (single response), label, mapper
dataset.derive('Regions_recoded',
'single', dataset.text('Regions'), mapper)
我们还将根据年龄对数据集进行加权,因此我们可以正确地表示不同年龄组的投票意向。记录单个响应变量(如 region)不同于记录一个数字。为了记录年龄变量,我们使用数据集的 band 命令。
# 2_recode.iypnbage_bands= [{"Younger than 18": (0, 17)},
(18, 24),
(25, 34),
(35, 44),
(45, 54),
(55, 64),
{"65+":(65, 200)}
]
dataset.band(name='Age', bands=age_bands,
new_name='Age_recoded', label="Age groups")
我们现在准备应用权重。我们有一个加权方案,以确保我们的结果代表正确的性别、年龄和地区分布。
# 3_weight.ipynb
#
age_and_gender_targets = {
'Gender': {
1:49,
2:51
},
'age_recoded': {
1: 21.3,
2: 9.4,
3: 13.4,
4: 14,
5: 13.7,
6: 11.7,
7: 16.5
},
'Regions_recoded': {
1: 84.2,
2: 8.2,
3: 4.7,
4: 2.8,
5: 0.1
}
}
scheme = qp.Rim('gender, age, region')
scheme.set_targets(targets=age_and_gender_targets)
权重报告向我们展示了权重是合理的(有人在获取代表性样本方面做得很好),任何响应的最大增加权重是 10%(最大权重因子)。
最后,将我们的管道存储在一个名为data_processing
的目录中(关于我们的文件夹结构将在以后的文章中详细介绍),这意味着无论何时发生变化,我们都可以按顺序运行它们,以使我们的数据跟上速度。我们为用户提供了一个笔记本,它调用一个运行所有数据处理笔记本的脚本,如下所示。
The run_data_processing script is a for loop that takes all notebooks in the data_processing directory and runs them with the python library papermill.
许多组织有复杂得多的重新编码和加权方案,开源软件可以处理所有这些——为了简洁起见,我们在这里保持简单。
在即将发布的帖子中,我们将介绍上述内容如何成为标准的“cookie cutter”文件夹结构的一部分,PowerPoint 文件、表格和在线仪表板的自动生成如何集成到上述过程中,以及如何将图形用户界面添加到该过程中,以使需要快速访问结果但没有时间编写代码的用户可以访问该过程。
盖尔·弗雷松是 Datasmoothie 的联合创始人,这是一个专门从事调查数据分析和可视化的平台。