TowardsDataScience 博客中文翻译 2020(三百六十六)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

利用自然语言处理从期刊论文中提取分类数据

原文:https://towardsdatascience.com/extracting-taxonomic-data-from-a-journal-articles-using-natural-language-processing-ab794d048da9?source=collection_archive---------38-----------------------

从期刊文章中提取科学用语的快速方法

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

澳大利亚阿德莱德州立图书馆。图片来源:弗拉德·库特波夫@ Unsplash

我最近遇到了一个客户的问题,他们希望从一篇 PDF 格式的期刊文章中提取所有的“科学词汇和名称”以及作者姓名和大学。虽然可以一个字一个字地浏览文章,并将其与分类名称列表进行比较,但这对于一篇期刊文章来说极其麻烦,尤其低效。相反,我使用自然语言处理的常用元素来确定期刊文章中的科学术语/分类数据。下面是一个教程,介绍如何从期刊文章 PDF 中提取文本,准备进行处理,并最终使用 Python libraries for NLP 从文章中获取分类或科学数据列表。

要加载的包

为此,我使用了 PyPDF、NLTK、pandas、scikit-learn 和 re。您需要 pip 安装这些包,特别是对于 NLTK,您需要通过使用 nltk.download('stopwords ')和 nltk.download('word_tokenize ')下载 stopwords 和 word_tokenize。

从期刊文章中提取文本

我将使用我随机选择的这篇期刊文章来浏览这个例子。有许多关于如何做到这一点的好文章,所以请随意查阅,但我是用 PyPDF2 做的。使用 PyPDF2 读取所有页面后,我将结果写入一个 txt 文件并处理。txt 文件。

清理用于分析的文本

现在我们有了要处理的语料库,我们必须做一些清理工作。使用正则表达式,我删除了数字、停用词、少于 3 个字符的单词和标点符号。我还定制了一个停用词表,删除那些“科学”但对我的分析没有特别启发性的词。运行代码后,可以修改该列表,删除可能没有用的额外单词。

使用 TFIDF 进行标记和提取

我们利用了上面定义的清理函数,并对清理后的输出进行了标记化(拆分成单个单词)。之后,我们得到了二元模型(词对)和三元模型(词三元组),然后对它们进行了矢量化。在矢量化之后,我们使用 TFIDF 来提取有可能成为重要科学词汇的单词。输出遵循代码。

虽然我们看到一些不相关的短语(如前所述),但这是论文中科学用语的一个很好的摘录。

结论

这篇文章展示了一种从发表的文章中提取科学信息的快速方法。对于特定的论文,可以对您的代码进行一些定制,以删除额外的短语。整个脚本可以在我的 Github 库这里找到。

使用 Pytesseract & Open CV 从扫描的 PDF 中提取文本

原文:https://towardsdatascience.com/extracting-text-from-scanned-pdf-using-pytesseract-open-cv-cd670ee38052?source=collection_archive---------0-----------------------

使用 Python 和其他开源库的文档智能

从发票的数字副本中提取信息的过程可能是一项棘手的任务。市场上有各种工具可以用来完成这项任务。然而,有许多因素导致大多数人希望使用开源库来解决这个问题。

几天前,我遇到了一个类似的问题,我想和你分享我解决这个问题的所有方法。我用来开发这个解决方案的库是 pdf2image (用于将 pdf 转换成图像)、OpenCV (用于图像预处理),最后是用于 OCR 的pytesserac以及 Python

将 PDF 转换为图像

pdf2image 是一个 python 库,它使用 pdftoppm 库将 pdf 转换为一系列 PIL 图像对象。以下命令可用于使用 pip 安装方法安装 pdf2image 库。

pip 安装 pdf2image

注意:pdf2image 使用的 Poppler 是基于 xpdf-3.0 代码库的 pdf 渲染库,没有它就无法工作。有关 Poppler 的下载和安装说明,请参考以下资源。

https://anaconda.org/conda-forge/poppler

https://stack overflow . com/questions/18381713/how-to-install-poppler-on-windows

安装后,任何 pdf 可以转换成图像使用以下代码。

使用 Python 将 PDF 转换为图像

将 PDF 转换为图像后,下一步是突出显示我们必须从中提取信息的图像区域。

注意:在标记区域之前,请确保您已经对图像进行了预处理以提高其质量(DPI ≥ 300,应调整偏斜度、锐度和亮度、阈值等。)

标记用于信息提取的图像区域

在这一步中,我们将标记图像中需要提取数据的区域。在用矩形标记了这些区域之后,我们将从原始图像中一个接一个地裁剪这些区域,然后将它们提供给 OCR 引擎。

我们大多数人都会想到这一点——为什么我们要在进行 OCR 之前标记图像中的区域,而不是直接进行呢?

这个问题的简单答案是你可以

此问题的唯一问题是,有时文档中嵌入了隐藏的换行符/分页符,如果此文档直接传递到 OCR 引擎,数据的连续性会自动中断(因为 OCR 会识别换行符)。

通过这种方法,我们可以对任何给定的文档获得最大的正确结果。在我们的例子中,我们将尝试使用完全相同的方法从发票中提取信息。

以下代码可用于标记图像中感兴趣的区域,并获得它们各自的坐标。

用于标记图像中感兴趣区域的 Python 代码

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

原始图像(来源:Abbyy OCR 工具示例发票图像)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图像中标记的感兴趣区域(来源:Abbyy OCR 工具样本发票图像)

对图像应用光学字符识别

一旦我们标记了感兴趣的区域(以及相应的坐标),我们就可以简单地裁剪特定区域的原始图像,并通过 pytesseract 来获得结果。

对于那些不熟悉 Python 和 OCR 的人来说,pytesseract 可能是一个让人不知所措的词。根据它的官方网站-

Python-tesseract 是谷歌的 Tesseract-OCR 引擎的包装器。它作为 tesseract 的独立调用脚本也很有用,因为它可以读取 Pillow 和 Leptonica 图像库支持的所有图像类型,包括 jpeg、png、gif、bmp、tiff 等。此外,如果用作脚本,Python-tesseract 将打印识别的文本,而不是将其写入文件。

另外,如果你想玩玩 pytesseract 的配置参数,我建议你先浏览下面的链接。

[## 宇宙魔方

Python-tesseract 是 Python 的光学字符识别(OCR)工具。也就是说,它会识别并“读取”…

pypi.org](https://pypi.org/project/pytesseract/) [## Pytesseract OCR 多个配置选项

感谢贡献一个堆栈溢出的答案!请务必回答问题。提供详细信息并分享…

stackoverflow.com](https://stackoverflow.com/questions/44619077/pytesseract-ocr-multiple-config-options)

以下代码可用于执行此任务。

裁剪图像,然后执行 OCR

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

裁剪后的图像-1 来自原始图像(来源:Abbyy OCR 工具示例发票图像)

OCR 的输出:

Payment:

Mr. John Doe

Green Street 15, Office 4
1234 Vermut

New Caledonia

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

裁剪后的图像-2 来自原始图像(来源:Abbyy OCR 工具示例发票图像)

OCR 输出

COMPLETE OVERHAUL 1 5500.00 5500.00 220
REFRESHING COMPLETE CASE 1 380.00 380.00 220
AND RHODIUM BATH

如你所见,我们输出的准确率是 100%。

所以这一切都是关于如何开发一个从复杂文档(比如发票)中提取数据的解决方案。

OCR 在文档智能方面有许多应用。使用 pytesseract,无论文档的格式如何(无论是扫描的文档、pdf 还是简单的 jpeg 图像),都可以提取几乎所有的数据。

此外,由于它是开源的,所以整个解决方案既灵活又不昂贵。

基于 DOM 分割和 BERT 的新闻故事作者抽取

原文:https://towardsdatascience.com/extracting-the-author-of-news-stories-with-dom-based-segmentation-and-bert-69225ea0e5c2?source=collection_archive---------22-----------------------

如何利用 Web2Text 的 HTML 特征生成框架和 HuggingFace Transformers 进行海量内容提取

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

获得大量新闻故事的作者是令人生畏的。网页有不同的格式,一个完美的解决方案应该在所有情况下,当可用时,识别作者的全名。作者的名字有时会出现在标题的正下方,但有时会出现在文章的下方,或者几乎完全隐藏在不同的栏目中。作者的名字可能出现在的任何一种语言中,可能有也可能没有助词在里面,比如英语介词 by 。在某些情况下,有一个以上的作者,名字用逗号-和- 分隔。

基于**试探法的解析器,**也就是说,使用正则表达式和 bash 脚本来处理条件,在很多情况下都可以很好地工作。然而,一个好的解决方案应该推广到看不见的格式。例如,一些文章在文档中有给定名称的列表(链接到网站上的其他文章或其他元素),这可能会产生歧义。

众所周知,分类器非常适合内容提取任务,因为它们可以查看多个上下文和布局特征。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这篇来自卫报的文章在左栏有作者。字符串在巴黎指的是记者写文章的地点,而不是名字的一部分。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

瑞典小报 Aftonbladet 上的一篇新闻文章,通讯作者在左边。瑞典语中, av 放在作者姓名前,类似于英语中的 by**。注意到第二列有一些名字(哈里王子梅根汗·马克尔等等。),这可能会被误认为是文章的作者。这个标题也包含了一个名字( Prins Phillip ),同样不是作者。**

获取培训示例

我使用了 Andrew Thompson 的All News数据集(其中有来自 15 家美国出版物的 73,000 篇文章,带有 URL 和作者)。新闻文章的时间跨度为 2015 年至 2017 年。Archive.org以其原始格式存储了大约 27000 篇新闻文章,其他的都在他们原来的新闻网站上。抓取所有链接大概花了三天时间(4.1 GB 压缩数据)。

因为报纸每隔一段时间就会改变他们的网站结构,所以语料库涵盖的不同案例的数量是未知的(但可以说是很少的)。收集和手动标记其他新闻渠道的更多培训示例以涵盖更多案例应该相当容易。

概观

流水线包含三个步骤:一个预处理器,一个分类器,以及命名实体识别

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

端到端作者提取器管道

预处理程序

我使用了论文web 2 text:Deep Structured Boilerplate Removal(Github repo)中的预处理器。

Web2Text 可以为兼容和不兼容的 HTML 构建一个 DOM 树。它有逻辑来清理已知包含非信息数据的 DOM 节点,向下遍历 DOM 树并折叠单个子节点及其各自的子节点。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

(来源:Web2Text)

该模型的训练示例是 HTML 文件的 DOM 节点。每个 HTML 文件平均有 138 个 DOM 节点。因此,该数据集总共包含 m = 73K * 138 = 101M 个训练示例。平均而言,代码需要 127 毫秒将每个 HTML 文件转换为 CSV 特征表示文件,其中每行代表一个特征,每列是一个 DOM 节点(运行在 1.7GHz 双核 i7 和 8GB DDR3 内存上)。

主类ExtractPageFeatures将一个原始 HTML 文件作为输入,并生成一个 CSV 文件,该文件具有去除样板文件的功能。我修改了这段代码,并创建了更适合作者提取任务的新特性。编译 Scala 项目后,您可以在任何 HTML 文件上运行:

> ./extract_page_features.sh  <input_html_file>

让我们以数据集中的一个文本为例:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

算法通过路由header -> div -> div -> h2 / a到达令牌政治 (8 个字符)。注意<h2><a>是如何折叠成一片叶子的。

对于每个折叠的 DOM (CDOM)节点,Web2Text 构建一个特征向量:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Web2Text 允许您将 CDOM 树输出到 HTML 文件中,以便您可以看到每个节点的特征。

Web2Text 附带了一组 128 个预定义的特性:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Web2Text 的开箱即用特性(来源:Web2Text)

功能存在于以下级别:

  • 叶子
  • 父母
  • 祖父或祖母

预处理器使用对后代特征进行求和(对整数),或者使用 (对布尔值)来计算祖先级特征(父级、祖父级或根级)。例如,如果有两个兄弟节点,一个有电子邮件地址,另一个没有,预处理器会将公共父节点标记为包含电子邮件。

在作者提取任务中使用祖先级别的数据捕获功能非常方便,因为在许多新闻网站中,作者姓名和出版日期(有时还有作者的社交媒体资料)被小方框包围。该信息可以帮助分类器学习识别哪些块包含作者。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在这个来自纽约时报的例子中,预处理器将包含作者的节点标记为在祖先层有一个 T21 日期字段。

特征工程

作者提取任务用一些额外的特性扩展了 Web2Text(出于性能原因,仅当2<=nWords<=5时才运行检查):

  • contains_popular_name:如果 CDOM 节点包含 1880-2008 年期间美国每年 1000 个最常见婴儿名字的数据集中的一个名字,则为真。在任何一年,它涵盖了美国 80%的男孩和 67%的女孩的名字(68k 的重复数据删除记录)。(注意:这一部分使用了字符串比较。这个特性的一个更好的解决方案将涉及单词嵌入或者可能是 BERT 或它的后继者)。
  • contains_author_particle:如果 CDOM 节点包含粒子 byand,则为真。
  • contains_author_url:如果节点包含格式为http[s]://[something]/author/[something的 URL,则为真。许多报纸都包含一个链接,链接到一个包含作者传记的页面,或者一个包含同一作者的其他文章的页面,并带有这种格式的链接。

我很兴奋地得知我可以使用 Web2Text 的一些标准特性来捕获与我的任务相关的信息:

  • contains_two_capitalized_words:包含至少两个大写单词(无名氏无名氏 ) (Web2Text 的特性b20b21b22)
  • at_least_two_words:包含至少两个单词(由 Web2Text 特征b5捕获)
  • contains_date:合理距离内的节点包含日期。这是由父级或祖父级的contains_year特性(b19)捕获的。

扩展该模型的一些非常有趣的特性是:

  • 呈现的 HTML 字体大小
  • 祖先节点包含到社交媒体的链接
  • number_of_sibling_nodes:同胞 CDOM 叶数。捕捉名称可以是链接列表的一部分的事实,如前面看到的 Aftonbladet 的例子。
  • 确定文章使用的语言,因为该模型依赖于大写字母、英语日期格式和一系列英语名字。

分类

Web2Text 的架构使用卷积神经网络,然后是隐藏马尔可夫模型,分别计算块和相邻块对上的一元和成对势。然而,在我们的例子中,我们希望每页最多找到一个包含作者姓名的块,所以我将这个问题构建为一个包含两个类的二进制分类器:{contains_author, not_contains_author},并选择了最小化二进制交叉熵损失的块。实际模型是一个简单的神经网络 (1 个隐含层;140 个隐藏单元)

分类结果

超参数

*分析的 HTML 文件数量:15000【717414训练示例(DOM 节点);**历元:**50;批量大小: 50 档;**学习率:**0.0001;**辍学率:*0.2;培训/开发/测试分割 : 60%/20%/20%。

关键指标

***准确率:**99.93%;**精度:**91.30%;**召回:*95.40%;F1-得分: 93.31%。

培训时间: 8.3 小时

混淆矩阵

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

/public/trained_model_all_the_news/,训练模型的权重存储在我们的存储库中。

推理

该模型在推理期间执行两个步骤:

1.-对 HTML 文档运行训练好的神经网络,选择代价最小的 DOM 块。

2.-运行一个 BERT 命名实体识别器,从块中提取所有人名。这个模型使用 HuggingFace Transformer 对 BERT (Large,cased)链接到模型 的实现,并将一个句子中的每个标记标记为属于四种类型: PersonMISCOrganizationLocation ,使用标准的 IOB 格式。对于作者提取任务,只有人名(PER标签)是相关的。该模型使用用于命名实体识别的标准数据集 CoNLL-2003 ⁵数据集进行微调。

最后,您可以运行以下命令来预测新闻文章的作者姓名:

*> ./inference_from_url.sh [https://www.theguardian.com/us-news/2016/jul/13/alton-sterling-son-cameron-protesters-baton-rouge](https://www.theguardian.com/us-news/2016/jul/13/alton-sterling-son-cameron-protesters-baton-rouge)The Author Name is: Jessica Glenza.*

贮藏室ˌ仓库

https://github.com/canetcesc/AuthorExtractor

参考

[1]沃格尔斯、加内亚和埃克霍夫。" Web2text:深度结构化样板去除(2018)欧洲信息检索会议。斯普林格,查姆。

[2]周和马舒克。"通过机器学习进行网页内容抽取(2014)斯坦福大学

[3]姚和左。网页内容提取的一种机器学习方法(2013)S坦福德大学*。*

[4] J. Devlin、M.W. Chang、K. Lee 和 K. Toutanova。" Bert:用于语言理解的深度双向变换器的预训练(2018)arXiv 预印本 arXiv:1810.04805

[5]桑和德默德。CoNLL-2003 共享任务介绍:独立于语言的命名实体识别(2003)arXiv 预印本 cs/0306050

感谢

非常感谢催眠师为这篇文章提供了想法。Hypefactors 是一个面向媒体专业人士的平台,其管道中的一个组件是识别每天数百万篇新闻文章的作者。这篇文章是由他们的真实业务需求所激发的,尽管实现可能有所不同。

剪贴画由工作室提供。

用 Python 为非程序员提取网页信息

原文:https://towardsdatascience.com/extracting-webpage-information-with-python-for-non-programmer-1ab4be2bb812?source=collection_archive---------16-----------------------

基本编程必备

用一些基本的数据挖掘技能来增强自己的能力

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由 Isaac QuesadaUnsplash 上拍摄

知道如何使用脚本从网页中提取数据是很有帮助的。我发现最简单的方法是在 lxml 库的帮助下使用 Python。

最好的部分是,你可能不需要在你的机器上做。你可以把你的脚本放到 Python 在线编译器上,然后你得到一些数据。

对于一些简单的东西,我们只需要在一个文件中的几行代码,然后它会做非常酷的事情。

下面举几个例子。

[## 如何在 Excel 中分析您的中型合作伙伴计划数据

在简单的图形中寻找模式

medium.com](https://medium.com/better-marketing/export-personal-medium-partner-program-data-into-excel-spreadsheet-8887cb4d4442) [## 如何在媒体上找到你们的相互联系

使用 Python 脚本和指令,不需要任何编码知识

medium.com](https://medium.com/better-programming/how-to-find-your-mutual-connections-on-medium-d0c586c04e6f)

学习网站

为了使学习更加相关,我们将把 Wordometer 冠状病毒网页作为我们的来源。

如果你访问这个页面,你会看到类似下面的内容。我将学习分成 4 个部分,我称之为练习,如下所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我已经提供了代码脚本(只有 70 行),借此复制粘贴并运行它(在在线编译器中),你会看到下面的内容

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

并选择每个数字来执行它。这应该会使学习更容易。

HTML 的基础

所有网页都是用 HTML 构建的。

让我们来看看 HTML 最基本的结构,因为这是我们提取所需信息时需要认识的基本模式。

我能提供的最基本的结构如下。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  1. 它们都是由包裹着<>tag组成。而且它通常带有一个对它的补充,即</tag>,或者它只是在tag中以/>结尾。
  2. <tag>中,它可能有一个或多个被命名的attribute。这有助于区分同类型的tag
  3. <tag>对周围,我们可以有一个(或多个)标签被包裹在里面,我在上面将其命名为<sub-tag>。你可以成像,sub-tag可以有 sub-sub-tag等等…,它构成了 HTML 的大部分。
  4. 有时,tag可以用一个text包围它,这通常构成了我们要寻找的信息的核心。

就是这样!给自己拍一下。您已经掌握了 HTML(以及 XML)结构🎉

第一件事:在 HTML 中阅读

在提取 HTML 信息之前,我们需要让我们的脚本先读取 HTML。有两种方法可以做到这一点。

1.直接从网站读取和加载 HTML

我们使用 Python 的请求库。别担心,就像下面这条线一样简单,然后就搞定了。

import requests

之后,尝试使用下面的代码获取网站内容。

response = requests.get(url)

为了更加健壮,万一url出错或者网站关闭,我添加了以下内容

try:
  response = requests.get(url)
except:
  print ('Sorry bad url') 
  sys.exit(2)if response.status_code != 200:
  print ('Sorry invalid response ' + str(response.status_code))
  sys.exit(2)

如果请求加载成功,那么您可以使用下面的代码获取 Html 内容,并将其提取到一个中。

tree = html.fromstring(response.text)

之所以称之为树,是因为如果我们画出标签关系,它们看起来就像一棵树。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

HTML 标签树

2.将 HTML 保存在文件中并从中读取

有时这是需要的,因为一些网页需要凭证登录,因此从脚本访问它会更复杂,因为您需要提供所需的凭证。

但是因为你只需要从 HTML 中提取一些数据,你可以把它保存为一个*。html* 文件,并获取从中读取的脚本。

之后,在您的 python 脚本中,您只需要

  1. 打开文件,并将其作为一个字符串(一组字母)读取。
  2. 读出 HTML 内容,形成一个
inputFile = open(inputfile,"r") 
fileContent = str(inputFile.readlines())tree = html.fromstring(fileContent)

准备提取数据!

1 提取单 **tag** 包裹 **text** **。**简单回顾一下,在练习 1 中,我们要提取如下所示的国家名称。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

如果我们检查它的 HTML 代码,我们会看到下面的模式。

<a class=”mt_a” href=”country/spain/”>Spain</a>

为了提取Spain,我们只需要识别具有"mt_a"的属性classa标签。

为了提取,我们只需对使用xpath函数。

extracteditems = tree.xpath(‘//a[[@class](http://twitter.com/class)=”mt_a”]/text()’)
print("\n".join(extracteditems))

我们将得到一个列表,在这里我们用一个新行(即"\n")将它们分开,并打印出来。

我们会得到

USA
Spain
Russia
UK
Italy
... and many more ...

轻松点。

2 抽取 **tag** **sub-tag** 包裹 **text** 。简单回顾一下,在练习 2 中,我们要提取每个国家的人口信息。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

如果我们检查它的 HTML 代码,我们会看到下面的模式。

<td style=”font-weight: bold; text-align:right”>
   <a href=”/world-population/spain-population/”>46,752,556</a> 
</td><td style=”font-weight: bold; text-align:right”>2,467,761</td>
<td style=”font-weight: bold; text-align:right”>52,783</td>

我们无法获得 <a href=”/world-population/spain-population/”>,因为每个国家的href会有所不同。

我们也不能捕获<td style=”font-weight: bold; text-align:right”>,因为上面显示了许多我们不想要的其他数字(例如2,467,761)。

因此,最好是捕获后面跟有<a>标签的<td style=”font-weight: bold; text-align:right”>

为了提取,我们只对使用xpath函数。

extracteditems = tree.xpath(
    '//td[[@style](http://twitter.com/style)="font-weight: bold; text-align:right"]//a/text()')print("\n".join(extracteditems))

我们将得到一个列表,在这里我们用一个新行(即"\n")将它们分开,并打印出来。

330,758,784
46,752,556
145,926,781
67,841,324
60,472,650
... and many more ...

轻松点。

3 **tag** 中提取 **attrib** **值。**简单回顾一下,在练习 3 中,我们想要提取网站的图片 URL。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在 HTML 中,图像 URL 存储为img标签的src属性。

<img src="/img/alert-plus.png" style="height:16px; width:16px" />

要提取它,我们首先需要先提取img元素,然后使用下面的特殊提取,即list(map(lambda ...))来提取每个src属性,即x.attrib.get(‘src’)

x是每个elements内的一个单项。

elements = tree.xpath(‘//img’)
extracteditems = list(map(lambda x: x.attrib.get(‘src’), elements))
print(“\n”.join(extracteditems))

由此,我们现在可以得到

/img/worldometers-logo.gif
/images/alert.png
/img/alert-plus.png
... and a few others ...

list(map(lambda ...))上有点复杂,但这是一种提取元素列表中各个项目的方法。

4 迭代每个 **tag** 来提取 **sub-tags** **。**简单回顾一下,在练习 4 中,我们想要提取每个大洲的高级数字

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

更具体地说,当我们进入其中一个大陆时,值如下所示,这就是我们要提取的内容。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

如果我们查看 HTML,每个大洲的数据都用具有"total_row_world row_continnet"class属性的tr分组。

<tr class="total_row_world row_continent" data-continent="Europe" style="display: none">
  <td></td>
  <td style="text-align:left;"><nobr>Europe</nobr></td>    
  <td>1,741,129</td>
  <td></td>
  <td>160,482</td>
  <td></td>
  <td>739,811</td>
  <td>840,836</td>
  <td>12,196</td>
  <td></td>
  <td></td>
  <td></td>
  <td></td>
  <td></td>
  <td style="display:none;" data-continent="Europe">Europe</td>
</tr>

让我们提取"total_row_world row_continnet"作为信息段。

为了进一步提取每个部分中的每一项,我们创建了一个单独的函数名extractElements,如下所示。我们发送x,它是各个部分中的每个部分。

sections = tree.xpath(
    '//tr[[@class](http://twitter.com/class)="total_row_world row_continent"]')extracteditems = list(map(lambda x: 
    '\"' + str(**extractElements(x)**) + '\"', sections))print("\n".join(extracteditems))

现在在函数extractElements中,我们使用findall提取出所有的td标签,并再次使用list(map(lambda ...))单独提取它的text

def extractElements(element):
    return list(map(lambda x: x.text, element.findall('.//td')))

输出如下所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

就是这样!

为了进一步说明element.findall(‘.//td’)是如何工作,我使用了一个 for 循环来单独打印每个提取的

def extractElements(element):
 **for item in element.findall('.//td'):
    print('  EXTRACTED: ' + str(item.text))**return list(map(lambda x: x.text, element.findall('.//td')))

输出如下所示

EXTRACTED: 1,741,129
EXTRACTED: +22,456
EXTRACTED: 160,482
EXTRACTED: +1,414
EXTRACTED: 739,811
... and more ...
EXTRACTED: Europe
EXTRACTED: None
EXTRACTED:

学会了这四种方法,你现在就有了探索你感兴趣的网站并提取相关信息进行进一步处理的基本要素。🛠

干杯。

感谢阅读。你可以在这里查看我的其他话题。

您可以在**Twitter脸书Reddit 上关注我,了解关于移动开发、媒体写作等相关主题的小技巧和学习。Elye**

从非结构化文本中提取越南地址数据

原文:https://towardsdatascience.com/extraction-of-vietnam-address-data-from-the-unstructured-text-150fe8cb0045?source=collection_archive---------36-----------------------

如今,社交网络和电子商务是我们生活的重要组成部分。我们在这些平台上买卖很多东西,越南也不例外。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

丹尼尔·伯纳德在 Unsplash 上的照片

介绍

如今,社交网络和电子商务是我们生活的重要组成部分。我们在这些平台上买卖很多东西,越南也不例外;在这个人口超过 9400 万的国家,脸书(Messenger)和 Zalo 是两个最大的社交网络。除此之外,很多商家利用这些平台卖各种东西。所以聊天应用是沟通自己想买的商品的主要渠道,比如价格、保质期、收货人地址、电话号码、什么时候送到(Ahamove 和 GHN 是越最大的送货公司)等等因此,在 Ahamove,我们开发了一个应用程序,可以快速帮助商家发现买家信息,如地址和电话号码。我们面临两个挑战:

  • 如何快速提取非结构化文本的地址数据?
  • 当这些文本通常没有结构、发音符号或拼写错误时,我们如何检测它们呢?

这些问题以及我们如何解决它们将在下面的章节中介绍。

1.消息中的越南语

首先,越南语是一种严重依赖发音符号的语言。这些许多音调符号,通常在同一个元音上有两个,使得书面越南语很容易在拉丁字母的本地化变体中识别出来。有 9 个区别符号,例如一个急性符号(dấu sắc),一个坟墓符号(dấu huyền),一个扬抑符号(dấu),一个短音符(dấu ớ),一个喇叭符号(ư或ơ),一个上面的钩子符号(dấu hỏi),一个波浪符号(dấu ng),一个下面的符号(d\u n\ng),一个染料符号——类似于{\或{\。

在理想的世界中,使用拉丁语发音符号的任何语言的人都可以轻松地排版他们的语言,并产生高质量的排版。

维克多·高尔特尼

然而,当我们互相发信息时,我们可以用或不用发音符号来发信息,但对方可以很好地理解。例如,我们可以传达这样的信息:

Giao hàng cho em đến 285 đường Cách mạng tháng Tám, Phường 12, Quận 10, Hồ Chí Minh nha
// English: Can you deliver it to 285 Cách mạng tháng Tám street, Ward 12, District 10, Hồ Chí Minh city for me, please.

如果我们传达这样的信息是没问题的:

Giao hang cho em den 285 duong cach mang thang tam phuong 12 quan 10 ho chi minh nha

越南所有有文化的人都能理解,没有任何困难。

其次,人们通常倾向于在对话中使用缩写。他们通常会将上述信息缩写成以下具有相同含义的例子:

gh cho e den 285 duong cmtt, p12, q10, hcm nha
gh cho e den 285 cmt8, p.12, q10, tp.hcm nha
gh cho em den 285 d.cmt8, p12, q.10, tp hcm nha

第三,他们可以使用错误的发音标记位置,他们也理解得很好。例如,当我们发信息时,意思是一样的,但是如果你做越南语听写测试,你的分数是 F;D

đường == đừơng
Trường Trinh == Trừơng Trinh

最后,当他们一起传递信息时,客户的信息通常不遵循越南语的结构。意思是文本没有主语+动词+宾语这样的结构。例如,当他们点东西时,对话通常是这样的:

Merchant: Cho mình xin địa chỉ và số điện thoại của bạn với.
//English: Could you give me your address and phone number, please?Customer: 285 cmt8, p.12, q10 09028388xx3
//or more harder structure like
Customer: 285 09028388xx3 cmt8 p12 q10

总之,在聊天应用程序中有许多不同的方式来发送消息。其中一些不容易被统计模型预测或在两个同义词之间进行比较。要解决这个问题,我们首先需要弄清楚越南的地址结构。在下一节中,我们将对此进行更多的解释。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们存档的结果。作者图片

2.越南地址结构

如上所述,我们只关注越南地址,但也有可能发展到其他国家和语言。越南的行政单位分为四级。在第一层,越南分为 58 个省和 5 个直辖市。直辖市是最高级别的中央控制城市,拥有与省同等的特殊地位。直辖市分为市区、镇、农村区作为二级单位。之后,城市地区被划分为选区,城镇被划分为选区和公社,而农村地区被划分为乡镇和公社。最后,最后一层单元是村落、村庄和社区。有许多层单元,但我们只用一个单元来代表每个层单元。

  1. 一线:城市
  2. 二线:县
  3. 第三层:地区

我们绕过了第四层,因为我们通常不在地址中使用它,我们也找不到任何关于第四层的知识来源。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

越南地址结构。作者图片

首先,地点单位有三种可能的后缀:街道名称、国家名称和城市/省份名称。在地点单位之后,我们通常用一个地区名、县名和市/省名,以便区分两个区/县或市/省之间的地点单位。对于街道编号,给出后缀,例如街道名称。在街道名称之后,它通常跟随着与地点单元中的街道名称相同的结构。

街巷号

在越南有几种不同的方式来显示地址号码。这将在下面解释:

  1. 如果房子或建筑在正面。它由一个数字(如“2”)或一系列数字(如“200”)组成。如果有两个或两个以上的组合土地,该街道编号包含一个街道编号范围(例如“200–201–202”)。此外,它可以以字符作为后缀(例如“47a”)
  2. 另一方面,当房子放在小巷里。水花用来表示房子或建筑在巷子里。斜线越多,巷子越深越曲折(如“76/4/8/3”、“76a/34h”)。
  3. 在胡志明市,“Bis”不定期出现。事实上,它反映了越南历史上法国殖民主义时代的痕迹(如“56 之二”)。“Bis”在法语中是重复或再次的意思。
  4. 有时,街道号码的前缀是“số nhà”或“số”(如“Số nhà 500 hẻm 34/56”)。)

地址名称

街道的名称可以有不同的结构。在某些情况下,他们有前缀“đường”或“phố”,这在北边更常见,意思是“街道”然而,很大一部分街道不是以这些前缀开头的。街道可以用不同的方式命名,通常使用缩写。因为在越南常见的街道是“mạng 汤汤”,可以用不同的方式缩写:

  1. 恰赫·mạng·汤 8
  2. Cach mang thang tam
  3. cmtt
  4. cmt8

我们也有一些街道命名,如“đườngsố76”意味着“76 号街”。地址中门牌号和街道名称相同的房屋。这在 Hồ的胡志明市经常发生。不同之处在于选区或地区部分——例如,像“恰赫·mạng·汤·汤”这样的街道穿过第 1 区和第 3 区。所以这里需要病房名或区名来澄清。

地名

这没有任何具体的案例;它通常以“phường”、“x”和“thị trấn.”为前缀。但是,在某些情况下,一些县的地名可能是其他县或市/省的街道名或县名。

县名

类似的问题描述为地点名称,县名称可以是街道名称或其他地区的地点。用于识别县名的指示符以“quận”、“huyện”或“thị x”为前缀

城市/省份名称

如上面街道名称中所述,城市或省份通常以各种方式使用,如“phố Hồ市”、“TP。“hồ·齐明”、“tp.hcm”、“tp hcm”、“hcmc”都是同一个城市的同义词。然而,这种方式有一个缺点。在一些城市或省份,名称可能很难识别,例如,“Nẵng”或“đồng 奈”在缩写时是“n”。

国家名称

目前只关注越南,所以国名只有越南;我们在提取信息时也绕过国家名称,因为如果它没有我上面解释的这些步骤,那么它是绝对错误的。

地名

一般来说,地名不遵循任何特定的模式。它可以利用这是最难识别的部分,并经常改变。所以我们只关注商场、建筑、部门,因为它们很少变化。

3.我们的目标

我们旨在识别与特定地点单元和地址相关的地址数据。因此,诸如商场、建筑、部门和地址等场所单位必须加以识别。我们关注这些类型的原因是:

  1. 地址是具有一定顺序的结构化文本,由不同的属性组成(如街道号码、地址名称、地点名称、县名、城市名称、地名等。).因为我们可以依次利用这些属性。此外,如果我们不能识别所有的地址属性或大多数属性,结果也不会更有价值。
  2. 这些属性不经常变化(地名除外)。所以我们不经常维护它。对于地名,只有商场和部门是重点,因为他们很少改变。
  3. 我们不需要识别咖啡店、沙龙或餐馆,因为我们只关注住宅区。终端用户通常不会在胡志明市的星巴克咖啡点东西,不是吗?
  4. 我们从维基百科、越南统计总局、OpenStreetMap 和 350 多个网站收集数据,以收集地址和地点单位。

我们目前只关注越南的地址,因为每个国家的地址结构都非常不同。然而,我们已经计划在其他国家和语言开发。我们已经开发了一种混合方法,使得手动开发的试探法和自由数据都可以作为信任资源。

4.地址数据的标识

有许多不同的方法。然而,一般来说,信息提取可以大致分为两类。有两种方法:基于规则的匹配训练 s 统计模型。

  • 基于规则的匹配是一种定义明确模式的方式。它类似于在原始文本上使用正则表达式,但是它让您找到您正在寻找的单词和短语。此外,您可以访问和分析周围的标记,将范围合并到单个标记中,或者向命名实体添加条目。这意味着你可以控制结果。在这种方法中,它明显优于训练静态模型。
  • 训练统计模型是对数据集应用统计分析的过程。静态模型是观察数据的数学表示。训练一个新模型需要一些努力,但是一旦完成,它可以以各种形式和在各种环境中被识别。

通过结合静态模型和基于规则的组件,可以提高静态模型的准确性。通过为特定标记提供标签、实体或句子边界。我们还在静态模型之后使用基于规则的组件来纠正常见错误。为了建立更抽象的逻辑,基于规则的组件可以引用静态模型设置的属性。

5.解决办法

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

完整的工作流程。作者图片

通过这样做,我们还可以独立于通常在它们之后或之前的其他属性来检测属性。最后,我们将找到的候选地址组合成一个或多个完整的地址。

预处理

最初,我们通过在我们想要获得地址数据的数据上使用正则表达式来移除所有发音符号。这样做之后,会对数据进行一些清理,例如删除非 Unicode 字符或邮政编码,因为越南语很少使用邮政编码。如果没有完成这些预处理步骤,标记化可能会产生错误的结果。最后的预处理步骤包括词性(POS)。在该步骤中获得的 POS 标签稍后用于识别单个属性。

识别单个属性

地址的每个属性都是单独标识的,几乎独立于其他属性,因此数据中地址格式结构的变化对整体结果的影响很小。在某些情况下,两个有规律地相互继承的属性的序列被用来识别属性。这使得单个步骤的排序考虑了前一步骤的信息以用于下一步骤。在识别单个属性的过程中,所有可能包含地址属性的标记序列都被标注为候选。此外,一些候选属性用启发法进行了注释,从而产生了这个候选属性。

6.地址属性的集合

我们将县候选作为种子来聚合结果,因为地址的名称和地点可以重复,但县在不同的城市或省中不能重复。基于此,我们尝试为每个县候选人分配地址。为此,执行以下步骤:

  1. 首先,我们检查所有候选地址是否有地址号码。如果不是,那么我们忽略它,因为我们不能通过使用这些地址找到准确的位置。
  2. 第二,地址号后面的下一个候选必须是地址名。如果下一个候选项是地区或县,我们将其转换为地址名称,因为街道名称可以与地区或县相同(巴海 Trung 街和巴海 Trung 区)。但是,这种方法可能是错误的,因为客户可能会键入错误的地址。幸运的是,我们有一个很好的反向地址 API,可以检查地址是否正确,所以这不是大问题。
  3. 第三,地址后的名称可以是地名或县名。我们如何知道它是一个地方或县的名称?如果候选人的长度大于 5(包括城市名称)或 4(不包括城市名称),则包括地点和县名。此外,因为县在不同的城市中不重复,所以如果县候选是县名,我们可以确定县候选是县名。另一方面,它是地名。
  4. 第四,地名是一种特殊的称呼类型。在地名可以是县名、省名或市名(如永旺梦乐坛府或永旺梦乐平阳)之后,这些地名很少改变,因此我们可以将它们收集到地名录中以便快速查找。
  5. 如果在文本中找到所有属性,则假定它们属于一个公共地址。

7.问题

我们面临一些重要的挑战,这些挑战对未来的工作很有意义。检查提取的地址,我们主要意识到错误识别的地址名称的原因:

  • 我们没有足够的知识来源,所以郊区的一些地址无法识别,然后就被忽略了。为了解决这个问题,我们建立了一个统计模型,可以学习这些丢失的地址,并在下一次改进地址检测。然而,这种方法超出了本文的范围。我们将在另一篇文章中讨论这种方法。

8.结论和未来工作

我们提出了一种在非结构化文本中识别越南地址的方法。为此,我们开发了一种混合方法,利用可以从 OpenStreetMaps、Wikipedia、General Statistics Office 和其他来源获得的信息模式和地名词典。

随着 AhaMove 的区域扩展,我们将调整和评估该方法在其他语言和其他国家的可行性。为此,需要确定识别单一地址属性的模式,并需要汇编具体国家的地名录。

咖啡豆一生中的萃取

原文:https://towardsdatascience.com/extraction-over-the-life-of-the-coffee-bean-f777f017718a?source=collection_archive---------34-----------------------

咖啡数据科学

萃取与咖啡烘焙时间的数据

我收集照片数据已经快两年了。我想浏览这些信息,看看我是否能看到任何趋势,特别是烤肉的年龄。主要警告是:

  1. 随着时间的推移,我的方法有所改进。
  2. 我的品味变了。
  3. 我的味觉扩展了。

所以我对数据进行了归一化处理,以给出一个更公平的比较。我发现烘烤后 5 周内,味道和萃取度都有所改善。过去三周,我没有发现味道有所下降,而这正是烘焙师通常暗示的。然而,我没有过去 5 周的太多数据,因为我的烘焙通常在 1 磅左右,而且我喝了太多的浓缩咖啡,以至于烘焙时间不会太长。

烘焙/储存/提取

我每周用一个烤箱烤一次 T1,我把它加满到 350 克。他们说最大重量是 250 克,但是对于中等程度的烘烤,你可以更高。当我启动机器时,我把豆子放进去,而不是等着滚筒达到温度。我知道这不符合标准,但我不介意。我还没有对充电温度进行并排比较,但我相信有一天我会的。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

所有图片由作者提供

当我开始收集数据时,我在第一次裂纹(FC)后 1 分钟结束烘烤。现在,我在 1:30 过 FC。我过去常常在烤之前混合豆子,现在我在烤之后做它。

储存;储备

这些豆子大部分储存在密封的塑料或玻璃罐中,但它们没有被真空密封。它们被存放在厨房的橱柜里,暴露在光线下。虽然人们说暴露在光线下对咖啡没有好处,但我还没有看到支持或否定这一说法的数据。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

提取,血统

我是杠杆机器的粉丝,这些镜头大部分是在金快车上拍摄的。有些是拉帕沃尼,Flair,Kompresso,意大利的恩里科和拉佩皮纳。我从 10 秒的预灌输开始,但在过去的两年里,我已经转移到 30 秒的预灌输。我也是一年前开始压脉,很多镜头都是断奏或者断奏捣实。六个月前,我做了相当多的工作,在研磨前加热豆子,在冲泡前冷却研磨物(又名辣磨)。最重要的是,我已经使用纸质过滤器将近一年了。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

所以有相当多的变化,但我相信一些标准化有助于比较随着烘烤时间的变化。

绩效指标

我使用了两个指标来评估镜头之间的差异:最终得分咖啡萃取

最终得分是 7 个指标(强烈、浓郁、糖浆、甜味、酸味、苦味和余味)记分卡的平均值。当然,这些分数是主观的,但它们符合我的口味,帮助我提高了我的拍摄水平。分数有一些变化。我的目标是保持每个指标的一致性,但有时粒度很难,会影响最终得分。

使用折射仪测量总溶解固体(TDS ),该数字用于确定提取到杯中的咖啡的百分比,并结合一杯咖啡的输出重量和咖啡的输入重量,称为提取率(EY)。

数据

我最终得到了 1200+个数据点,在编译下面的图之前,我必须清理这些数据。我扔掉了在咖啡馆拍的照片和一些奇怪实验的照片。

由于数字(Mac ),将数据表放在一起很有挑战性。我把我的数据储存在数字表中,每一列都是一杯浓缩咖啡。我使用了列而不是行,因为这使得在我的手机上查看这个表单更容易。然而,直到最近,最大列数还是几百列。所以我有几个表,我添加和移动了一些行来改进工作流,所以我必须创建一个公共表来收集所有其他表的重要部分。

并不是所有的镜头都有 EY,但我仍然想尽可能多地查看最终得分数据。下面是桌子一部分的大图。我有输入指标、输出指标和计算指标。我有彩色编码,可以很快看到分数之间的对比。我还记录当前镜头的笔记,以及下一个镜头要修改的内容。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

数据手册的尺寸示例。所有图片由作者提供

首先,我把一切都绘制成散点图,没有归一化。我只区分了断奏和常规,但除了在 EY,似乎没有太大的区别。在过去的六个月里,我没有定期进行断奏击球,这是我能够使用更长的预灌注时间来驱动 EY 更高的时间。最终得分似乎随着时间的推移而上升,EY 也是如此。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

你可以观察到我没有超过 6 周的烘烤数据。我有一些数据点,因为我出城了一个月,没有带豆子。

提取时间在第一周至第二周很长,但之后不会有太大变化。过去两个月我确实注意到了,做一次非常努力的夯实并没有多大效果;镜头会跑得很快。

然后,我使用 Z 分数归一化法通过烘焙来归一化数据。这将使用平均值 0 和标准差 1 对同一分布上的所有分数进行归一化。因此,如果点开始向正方向移动,就意味着分布在移动。散点图的问题在于它们不能很好地讲述故事。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

所以让我们转到方框图。对于那些不熟悉盒子剧情的人来说,这是一个传奇:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这些是没有规格化的箱线图。它们显示出分数和 ey 随时间增加的趋势。这可能会产生误导,因为在这个数据之旅的开始,我会在两周内烤一次,喝一次。现在,我的烘焙在我酿造之前至少要放置两周。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

让我们通过每次烘烤来标准化数据。最终得分和 EY 的分布似乎都有所上升,但投篮时间的分布没有上升那么多。拍摄时间下降,尤其是在过去 7 周。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们也可以做最小最大归一化来强制所有的分数在 0 到 1 之间。我们可以对每一次烘烤都这样做,然后将它们组合起来。分数越高越好。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们看到了一种趋势,即使用这种类型的标准化来组合数据,味道和 EY 会得到更高的分数。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

只看烘焙后每天每箱的中值,它们都遵循粗略的趋势,但是有一些噪音归因于烘焙后的天数不一致。不是每一份烤肉都有每天的数据点。然而,我想尝试看看我能做些什么来理解烘焙后的味道和萃取趋势。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

与 Q 分数相比

我的品味分数和 Q 分一致吗?幸运的是,我也有这个问题的一些数据。在过去的两年里,我也一直在收集关于我的考试和平均成绩的数据。我假设混合咖啡豆会得到单个咖啡豆等级的平均值,我想知道这个合并的 Q 值是否能给我一个很好的指示,让我知道一次烘焙是好是坏。

以下是我的烘焙数据表示例:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

烘焙数据表示例

下面是一个例子,说明我是如何根据单个豆的分数来计算平均 Q 分数的。前两个没有名字或输出重量。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

烘焙数据表的特写视图

我的混合烤肉平均 Q 值从 8.1 到 8.9 不等。下面是一个直方图,用来理解数据是如何分布的。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

显然,我不能标准化每一次烘烤的拍摄数据,所以相反,我标准化了 3 到 5 次烘烤的拍摄数据:前 2 次烘烤(如果存在),有问题的烘烤,以及后 2 次烘烤(如果存在)。我用最小最大归一化法对分数进行了归一化。

箱线图可以提供一些关于趋势的信息,但我在过去一年的购买中更关注 Q 值,所以它可能会因我的购买而有所偏差。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

看看最小最大标准化,最终分数似乎有轻微上升趋势,但 EY 没有。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们可以通过查看每个 Q-score bin 的平均分数来简化这种情况,它显示了一个非常轻微的趋势。然而,数据点的数量非常少,所以我不会太依赖它。我曾希望看到一个更清晰的趋势,但正如数据中的情况一样,许多变量可能会相互妨碍。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

总的来说,随着烘焙时间的推移,我发现味道和提取率都有上升的趋势,我怀疑这两者之间存在相关性。我没有看到 Q 级和口味之间的强烈趋势,这可能是由于酿造技术的改进。如果更多的技术变量得到控制,我预计趋势会更加清晰。

最让我兴奋的是,我总是可以再次进行这种分析,我很好奇更多的数据如何能够更好地理解烤肉的味道何时达到顶峰。对我来说,风味的高峰期在 3 到 5 周之间,这是一个比烘焙师建议的典型的 2 到 3 周更长的时间。对于提取率,我没有看到随着时间的推移而下降。通常情况下,EY 会继续上涨,然后到达一个平台。

对于过去 5 周的烘焙,有一丝陈腐,特别是在较暗的烘焙和持续 3 个月的烘焙中,但拍摄仍然令人愉快,部分原因是较高的 EY 潜力抵消了一些陈腐的味道。

如果你愿意,可以在 Twitter 和 YouTube 上关注我,我会在那里发布不同机器上的浓缩咖啡视频和浓缩咖啡相关的东西。你也可以在 LinkedIn 上找到我。

我的进一步阅读:

咖啡豆脱气

解构咖啡:分割烘焙、研磨和分层以获得更好的浓缩咖啡

浓缩咖啡的预浸:更好的浓缩咖啡的视觉提示

咖啡的形状

搅拌还是旋转:更好的浓缩咖啡体验

香辣浓缩咖啡:热磨,冷捣以获得更好的咖啡

断续浓缩咖啡:提升浓缩咖啡

用纸质过滤器改进浓缩咖啡

浓缩咖啡中咖啡溶解度的初步研究

断奏捣固:不用筛子改进浓缩咖啡

浓缩咖啡模拟:计算机模型的第一步

更好的浓缩咖啡压力脉动

咖啡数据表

被盗浓缩咖啡机的故事

浓缩咖啡过滤器分析

使用 BERT 的抽取摘要

原文:https://towardsdatascience.com/extractive-summarization-using-bert-966e912f4142?source=collection_archive---------4-----------------------

一种利用 BERT 嵌入能力的监督方法

摘要总结是一项具有挑战性的任务,直到最近才变得实用。像 NLP 的许多东西一样,这种进步的一个原因是像 BERT 这样的 transformer 模型所提供的高级嵌入。这个项目使用 BERT 句子嵌入来建立一个提取摘要器,采用两种监督方法。第一种只考虑嵌入及其导数。这符合我们的直觉,一个好的总结者可以分析意思,应该纯粹根据文章的内部结构来选择句子。这种方法的基线是无监督的 TextRank 模型。另一种方法结合了序列信息,并利用了众所周知的新闻语料库特有的 Lead3 现象。这是一个观察,前三个句子通常能很好地概括文章。事实上,许多出版商都明确部署了这一策略。导联 3 用作第二种方法的基线。在这两种情况下,监督模型都优于 Rouge-1 和 Rouge-L F1 指标的基线。

背景

总结策略通常分为提取型、抽象型和混合型。提取策略选择最能代表文章要点的前 N 句。摘要试图用新词再现文章的要点。混合策略要么在确定一个抽象的中间状态后产生一个抽象的总结,要么可以根据文本的细节选择使用哪种方法(例如:指针模型)。

提取策略被设置为二元分类问题,其中目标是识别属于摘要的文章句子。摘要需要识别关键点,然后添加生成性元素。最后,混合策略需要结合这些元素,并提供一种机制来决定何时应该使用每种模式。

指标

摘要评估面临的挑战之一是它需要一组参考或黄金摘要的存在。对于大多数主题来说,这些都不是自然可得的,这也解释了为什么新闻文集和科学期刊主导了研究。科学论文有摘要,而新闻出版商通常在他们的网站上使用综述或横幅。摘要和翻译任务的自动评估是一个有趣但有争议的话题。这个马蜂窝在 TDS 上这里覆盖得很好。对于当前的目的,知道 Rouge-N 系列度量标准已经成为标准度量标准并具有以下特性就足够了:

Rouge-N 测量预测和 gold 汇总之间的 n-grams 重叠

胭脂召回通过黄金总结的长度使重叠正常化

Rouge precision 通过预测摘要的长度来归一化重叠,从而抵消回忆失败以说明简明。例如,一个非常长的预测摘要可以获得完美的回忆,尽管有许多多余的或误导性的单词

Rouge-1 F1(召回率和精确度的调和平均值)是主要的评估指标

Rouge-1 是一个更严格的衡量标准,也考虑到了顺序,通常与 Rouge-1 一起报告

数据集

康乃尔新闻编辑室数据库包含 130 万篇文章摘要对,来源于 39 种出版物。该数据集代表一组不同的汇总策略,这些策略基于透明算法被标记为(提取的、抽象的、混合的)。

用于该项目的数据集仅过滤了提取的文章摘要对,并将该选择截断为 5000 个样本。

管道

注意事项

总结的一些重要注意事项是:

句子排名:每篇文章都需要返回一个非空的摘要,但可能会有一些文章的所有句子都没有越过概率阈值。事实上,摘要的长度通常是一个棘手的问题,但一个常见的实用解决方案是指定返回的句子数量作为固定的用户输入 k。在这种情况下,句子按照预测概率的降序排列,并选择前 k 个句子。当前项目将使用 k=3。

rouge:rouge 分数不是一个标准的评估指标,需要自定义实现

混淆矩阵:使用句子排序和 Rouge 的一个结果是模型之间的评估结果可能与标准混淆矩阵显著不同。例如,一个模型可能无法预测阈值以上的许多句子,但在返回前 3 个句子后仍然得分高或模糊。

示意图

预处理

火车

预测概率

选择前 3 个句子作为总结并连接

使用 rouge-score 包通过自定义实现计算 rouge 分数

预处理

特性

BERT 足够复杂,可以从语言的所有细微差别中解析出意思,并且有意忽略了停用词移除、词干提取和小写转换等步骤。

预处理包括:

将数据从 JSONL 加载到 Pandas 数据框架

使用 spaCy 将文本分割成句子,清理短句,并通过句子转换器包使用 BERT 嵌入

通过计算句子嵌入的平均值来计算冠词的含义

计算文章中每个句子的句数

目标

数据集的提取标记依赖于一种算法,该算法在相关类别中对文章策略进行宁滨之前,在连续体上对文章策略进行评分。结果,摘要并不都是完全摘录的,也不是所有的句子在文章文本中都有精确匹配。下面的算法用于识别摘要中的句子

计算每个摘要句子和文章句子之间的余弦相似度矩阵

将具有最大值的句子标记为 in-summary(设置为等于 1 )

文件级的培训-测试-拆分

虽然句子是第一组模型中的样本单元,但是训练测试分离需要发生在文档级别,以确保文章级别的摘要可以被合理地连接起来用于 Rouge 评估。这需要一个训练-测试-分割的自定义功能。

数据探索

第一步是对文章和摘要的长度有一个高层次的概述,用句子来衡量。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

句子中文本长度的统计(作者自己的图像)

Lead3 现象在数据集中非常明显,超过 50%的摘要中的句子来自前 3 篇文章的句子。随着与文章开头距离的增加,摘要收录的下降也同样明显。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

引导句现象在语料库中高度可见(作者自己的图像)

主题域可以使用 t-sne 和简单的标签分配方法来可视化

计算“娱乐”、“犯罪”、“商业”和“政治”作为四个领域参考嵌入的 BERT 嵌入

计算每篇文章相对于四篇参考文献的余弦相似度

用最接近的参考文献(最高余弦相似度)标记文章

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者自己的形象

尽管有大量的信息丢失,但特定主题领域的密集程度是显而易见的,政治在左下角,犯罪在右下角,商业在左上角,娱乐在右上角。同样值得注意的是,政治和犯罪占据了底部,而商业和娱乐占据了顶部。广义的解释是,政治和犯罪共同关注社会和法律问题,而商业和娱乐有着共同的商业目标。主题域决不是预期可分离的,并且观察到的分散程度并不令人惊讶。

方法 1

这种方法的目标是仅使用句子嵌入及其派生来获得摘要,以便训练能够解析文章内部结构的监督模型。 TextRank 被选为该方法的基线。一系列逻辑回归模型和神经网络用以下总结结果进行训练:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

最优 logistic 回归模型是 l1 _ 比值为 0.25、正则化倒数为 0.5 的弹性网。最佳神经网络是一个双层密集网络,每层 25 个神经元。(作者自己的图片)

整个测试过程中一个值得注意的特点是,微调,甚至是平衡数据的调整产生的益处很少。例如,所有尝试的逻辑回归模型得分在 41%和 42%之间。这并不奇怪,因为这些模型调整不太可能改变句子排名,这是他们各自胭脂分数差异的唯一来源。对于 Rouge-1 和 Rouge-L,这两个监督模型都轻松击败了文本排名基线,得分相当令人印象深刻。它们的优势在召回率和精确度方面也是一致的。一个令人惊讶的方面是,弹性网络模型略微优于神经网络。一个原因可能是仅提供句子嵌入和文章含义的特征集没有为神经网络的非线性提供足够的上下文信息来充分探索。在进一步思考中讨论了可能的补救措施。

进场 2

Lead3 是 Rouge metrics 的强大对手,本节通过包含顺序信息,利用了新闻语料库中已知的顺序结构。使用句子数量作为句子嵌入和文章含义的附加特征来训练逻辑回归模型。各种 LSTM 体系结构,自然地结合了顺序信息,在与上一节相同的嵌入特性上进行训练:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

LEDE3 取前导三句。LogReg def 是 SK-learn 中的默认逻辑回归模型,LSTM Bi 50 是在 Keras 中实现的 50 神经元双向 LSTM 网络,没有填充,纪元为 1,并使用 Adam 优化器。(作者本人图片)

虽然逻辑回归模型滞后,但 LSTM 在 LEAD3 基线上享有优势。再深入分析一下,LSTM 的召回率与领先 3 相似,但在精确度方面有很大优势。这表明,在 LSTM 不同于 Lead3 的情况下,它在选择同样相关但更简洁的句子方面做得相对较好。

进一步的想法

在每个句子给出的信息很少的情况下,仅嵌入方法的结果令人惊讶地好。一个有趣的方法是通过创造性特征工程为模型提供更多关于文章内部结构的信息。这可能特别有利于从神经网络的非线性中提取更多信息。一种想法是,可以根据一些属性在语料库中标记句子,然后将文章级质心作为一个新的特征。有监督的方法可以基于词性标注为每个句子分配一个功能标签。无监督选项可以使用聚类算法来分割整个语料库上的句子嵌入空间。

进一步工作的更简单选项包括(I)使用在 TextRank 中获得的相似性矩阵作为监督模型的特征集,(ii)使用比这里使用的 5000 篇文章多得多的数据来训练模型,当然,(iii)添加注意机制或使用转换器来获得更细微的结果。

最后,值得记住的是,语料库仅被过滤为摘录摘要,下一步将包括对数据集中更广泛的策略类型采取相同的方法。

感谢您阅读我的文章。欢迎所有反馈,记得查看我的 GitHub 的代码和更详细的分析。

非凡的数据可视化—圆形图表

原文:https://towardsdatascience.com/extraordinary-data-visualisation-circular-chart-fe2d835ef929?source=collection_archive---------33-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

数码师Pixabay 拍摄的照片

一个圆形图表显示了用 Python Plotly 实现的比例和位置关系

使用饼图或圆环图来表示整体中不同组成部分的比例是非常常见的。然而,最近我遇到了这样的数据可视化需求:

  • 该图表需要呈现几个组件
  • 每一个组成部分都需要显示出相对于整个事物的比例

到目前为止,饼图或甜甜圈图仍然是完美的选择。但是,请注意其余的要求。

  • 组件可能会重叠
  • 除了显示比例外,每个组件将从基线的某个位置开始,并以某个端点结束。

有些情况需要这样的要求。例如,根据 DNA 片段与基线的相似性来表示 DNA 片段。

圆形图表

我们可以用一个圆形图表来形象化这种关系。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

如上所示,圆形图表包括

  1. 代表基线的圆
  2. 表示起点/终点的指示。因为是圆,所以起点和终点其实是一样的。
  3. 一些度作为刻度将指示位置,以及显示它是顺时针还是逆时针。直观来说,我会推荐用顺时针。
  4. 最后,用不同颜色显示位置(起点和终点)和比例(径向长度)的组件

要可视化的数据

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

照片由 MiraCosicPixabay 上拍摄

要可视化的数据如下。

gene_list = [
  [0.1, 0.25],
  [0.15, 0.3],
  [0.6, 0.68]
]

这是一个二维数组。每个子阵列代表基因的一个片段。这两个数字分别是起点和终点。

例如,第一个基因[0.1, 0.25]意味着该基因片段从基线的 10%开始,在 25%结束。所以长度是原来的 0.15。

现在,让我们看看如何使用 Plotly 来绘制这个圆形图表。

履行

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

julianestanczykPixabay 上拍摄的照片

用 Plotly 画圆形图并不太难。

首先,我们需要导入 Plotly。如果还没有拿到库,可以简单的通过pip install plotly安装。

import plotly.graph_objects as go
import numpy as np

Plotly 支持极坐标系统,非常适合用来绘制我们的圆形图表。要在极平面中绘制圆,两个重要的参数是

  • 圆的半径:r
  • 角度:*θ*

在我们的例子中,我们需要使用半径r来区分我们的基圆和其他组件(圆段)。角度*θ* 很重要,因为我们需要它来显示起点和终点。换句话说,我们需要基圆的*θ* 为 0–360 度,而组件取决于它们相应的比例和位置。

我们定义一个函数来得到*θ*

def get_theta(pct, num_points):
  start = pct[0] * 360
  length = (pct[1] - pct[0]) * 360
  step = 360 / num_points
  return np.arange(start, start + length + step, step)

在这个函数中,它有两个参数。第一个参数pct是一个包含两个元素的列表/元组。第一个元素是开始百分比,第二个元素是结束百分比。第二个参数num_points表示对于一个完整的 360 度圆,我们想要在图上呈现多少个点。越多的num_points我们将拥有越平滑的圆。在我的情况下,360 点就足够了,因为人眼将无法看到小角度。

让我们在这里定义两个常数:

num_points = 360
r_gap = 0.05

上面提到的num_points,我想用 360 分。r_gap表示我们希望基圆和每个线段之间有多大的间隙。

我们还需要知道图表的半径应该是多少,才能显示所有的线段。既然我们已经知道了r_gap。如果我们假设基圆有它的半径1,我们就可以计算出我们想要的最大半径。

# Get radial scale
max_r = 1 + (len(gene_list)) * r_gap

现在,让我们用 Plotly 初始化一个图形。

fig = go.Figure()

添加基圆

然后,添加基圆。它应该是黑色的。这里我们定义了半径r=1,这样线段就是1 + r_gap * (index + 1)

# Create the base circle
fig.add_trace(go.Scatterpolar(
  r=[1] * num_points,
  theta=get_theta([0, 1], num_points),
  mode='lines',
  line_color='black',
  line_width=3,
  showlegend=False
))

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

添加零度指示器

现在,让我们在 0 度上画一个小“杠”来表示基圆从哪里开始。此外,在图表边缘和线段之间留出一些空间也有所帮助。

# Create the zero indicator
fig.add_trace(go.Scatterpolar(
  r=[1, max_r],
  theta=[0, 0],
  mode='lines',
  line_color='black',
  line_width=3,
  showlegend=False
))

请注意,这里我们只需要图上的两点:

  • (1,0 度)
  • (最大 r,0 度)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

渲染线段

现在看起来好多了。让我们在 for 循环中渲染我们的片段。

# Loop the gene list to add all the gene cirles 
for index, seg in enumerate(gene_list):
  fig.add_trace(go.Scatterpolar(
    r = [1 + (index + 1) * r_gap] * num_points,
    theta = get_theta(seg, num_points),
    mode='lines',
    line_width=3,
    name='Segment' + str(index+1)
  ))

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

好的。看来还是有事情要做的。如图所示,有几个问题:

  • 第三段几乎看不见,因为它几乎不在图表的边缘。
  • 零度从 3 点钟位置开始,最好让它从 0 点钟位置开始。
  • 图表是逆时针方向的,对于大多数人的习惯来说并不直观。
  • 半径记号没有用。
  • 网格没有用。

调整布局

让我们解决上述所有问题。

# Configure the layout based on the requirements.
fig.update_layout(
  polar=dict(
      angularaxis=dict(
        rotation=90,
        direction="clockwise",
        showticklabels=True,
        showgrid=False
      ),
      radialaxis=dict(
        range=[0, 1 + (len(gene_list) + 1) * r_gap],
        showticklabels=False,
        visible=False
      )
  )
)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

现在,我们有了一个完美的圆形图表!

摘要

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Pixabay 上的absolute vision拍摄的照片

在本文中,我展示了如何使用 Plotly 绘制一个圆形图表,表示数据的比例和位置关系。

所有代码都可以在我的 Google Colab 笔记本中找到:

[## 圆形图表

用 Python 中的 Plotly 绘制圆形图表

colab.research.google.com](https://colab.research.google.com/drive/1JyAF3saWjwb8DIr_u_cQA9Mm8jNSs688?usp=sharing)

虽然有时数据可视化库可能不提供一些现成的数字和图表,但我们仍然可以使用 Python 轻松地绘制出我们脑海中的任何东西。Plotly 就是这样一个令人惊叹的数据可视化库。

[## 通过我的推荐链接加入 Medium 克里斯托弗·陶

作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…

medium.com](https://medium.com/@qiuyujx/membership)

如果你觉得我的文章有帮助,请考虑加入灵媒会员来支持我和成千上万的其他作家!(点击上面的链接)

引人注目的 R 动画地图——简单介绍

原文:https://towardsdatascience.com/eye-catching-animated-maps-in-r-a-simple-introduction-3559d8c33be1?source=collection_archive---------7-----------------------

使用传单闪亮轻松制作美丽地图的动画。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

提莫·维林克Unsplash 上拍摄

作为数据科学家和数据分析师,我们每天都要处理不同种类的数据。我们都知道,数据和我们的发现的可视化是关键,尤其是在向同事或客户展示时。毕竟,用图表来讲述一个故事比用简单的数字或文本要容易得多。当您通过仪表板呈现数据时,不仅静态可视化变得重要,您还希望动态显示数据的变化。

在这篇文章中,我将展示如何使用 r 中的活页闪亮库轻松制作基于地理空间数据的图表。

1.介绍

虽然在 R 中绘制地图有许多方法(例如使用 ggplot2tmap ),但传单库是我个人最喜欢的,原因如下:

  • 简单
  • 高度定制化
  • 漂亮的交互式地图
  • 适用于所有主要的桌面和移动平台

leaflet R 库建立在 leaflet.js 之上,这是领先的用于移动友好的交互式地图的开源 JavaScript 库。R 实现让我们只用几行代码就能生成简单的地图。例如,只需一行代码,您就可以显示以下地图,放大奥地利美丽的维也纳:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

基本传单地图(图片由作者提供)

尽管创建这个地图非常简单,但是它还没有显示任何数据。最终我们想要的是这样的东西:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

附有数据的基本传单地图(图片由作者提供)

我们想要用数据覆盖我们的地图(就像在上面的例子中,我们已经添加了一些圆圈标记),或者甚至根据一些底层数据给我们的地图着色(所谓的 Choropleth )。最后,我们希望能够动画显示数据随时间的变化,以便将我们的地图包含在一个漂亮的仪表板中。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

基本动画(图片由作者提供)

在接下来的部分,我将简要演示如何制作一个类似于上面的动画,以及如何创建一个动画的 Choropleth。

2.数据

首先,我们需要两种类型的数据:我们需要显示我们想要的地图和我们有兴趣显示的数据。

对于地图数据,我们使用活页有两个主要选项:

  • 瓷砖
  • GeoJSON 或 TopJSON 文件形式的地理空间数据

我们已经看到了如何使用上面图表中的基本图块,简单地使用默认为 OpenStreetMap 图块的 addTiles() 函数。我们也可以通过使用 addProviderTiles() 函数来使用其他第三方图块集。有关可用图块的完整列表,请参见此处的。

我们还可以从 GeoJSON 或 TopJSON 文件中读取地理空间数据,并将它们转换为 r 中的空间对象。为了创建我们的 Choropleth,我们必须使用一个名为 addPolygons() 的函数,它要求我们使用这样的空间数据。虽然这整个过程一开始听起来复杂而吓人,但实际上非常简单。

在本文中,我们将重点展示国家级别的数据。我们可以很容易地从www.thematicmapping.org获得所需的空间数据,它提供了“世界边界数据集”。下面的代码片段展示了如何从 r 下载、解压缩和加载这些数据。

生成的空间面数据框包含所有国家的信息,例如国家代码、名称、经度和纬度坐标。对象中包含的基本数据可以通过以下方式访问:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

世界边界数据集概述(图片由作者提供)

对于绘制 Choropleth 来说,重要的是对象中包含的多边形数据。这基本上是用来绘制国家边界的数据。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

多边形数据(图片由作者提供)

这是我们需要的所有数据,用来创建我们将要使用的基本地图。

我们将要显示的数据与当前的重要主题相关:正在进行的新冠肺炎疫情的案例数据。世界卫生组织以 csv 格式发布所有国家的每日病例统计数据,我们可以随时查阅。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

世卫组织 Covid 数据集(图片由作者提供)

该数据集为我们提供了自 2020 年初以来的每日统计数据,并且每天都在更新。

3.基本地图

在这一节中,我将展示如何创建地图的基本版本,我们将在后面制作动画。

首先,我们将把空间数据与选定日期的 COVID 案例结合起来,定义将要显示的标签文本,并为数据和图表图例设置调色板。

现在,我们可以使用圆形标记来创建地图的第一个版本,以显示 COVID 案例。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

基本圆形标记图(图片由作者提供)

这很简单!我们所要做的就是使用 addCircleMarkers() 函数,使用我们的数据集中包含的经度和纬度坐标作为圆的中点,并使它们的半径和颜色取决于案例的数量。我们还添加了出现在鼠标悬停时的标签文本以及左下角的图例。所有这些都不费吹灰之力!

创建 Choropleth 版本同样简单。不使用 addCircleMarkers() 函数,我们只需使用 addPolygons() 函数,并且不使用坐标,我们需要使用空间多边形数据框中包含的多边形。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

基本 Choropleth 地图示例(图片由作者提供)

再说一遍,超级简单!在下一节中,我们将使用闪亮的为我们创建的两个版本的地图制作动画。

4.动画

虽然传单本身无法帮助我们完成显示数据随时间变化的任务,但我们可以使用 shiny 中的简单设置来完成这一任务。我们所要做的就是使用一个 sliderInput 小部件为我们选择日期,并将 animate 参数设置为 TRUE。

这个输入部件在右下角有一个小的播放按钮,如果我们在这个部件中观察地图的变化,我们将得到我们的模拟!

为了避免每次改变时都要重新绘制整个地图的开销,我们可以使用 leafletProxy() 函数,它是专门为在闪亮的上下文中使用而设计的。它允许我们访问已经绘制的地图并改变其特征。

对于地图的标记版本,我们只需通过 clearMarkers() 清除现有标记,并在观察到所选日期发生变化时添加新标记。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

闪亮的动画标记地图(图片由作者提供)

不幸的是,重新绘制多边形在计算上更加昂贵,并且会在我们的闪亮的应用程序中引入显著的延迟。在撰写本文时,传单库中还没有直接的方法允许我们简单地改变绘制的多边形的特征。然而,使用一点 JavaScript 就像这里详细描述的一样将允许我们做我们想做的事情。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

闪亮的动画 Choropleth 地图(图片由作者提供)

正如承诺的那样,你可以在下面找到闪亮应用的完整代码:

5.结论

这就把我们带到了本文的结尾,在这篇文章中,我演示了如何使用传单闪亮的** R 库轻松创建引人注目的动画地图。希望这能让你自己通过几个简单的步骤创建令人惊奇的交互式地图,并在一个漂亮的仪表板上分享它!**

如果您对我在本文中展示的内容有任何反馈或问题,请务必让我知道,并在这些不确定的时期保持安全!

F# Azure 函数

原文:https://towardsdatascience.com/f-azure-functions-a5cce33dce58?source=collection_archive---------31-----------------------

在 F#中创建 Azure 函数

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

F#中的 Azure 函数

F#是一种很棒的语言,也是为你的 Azure 函数编程的好选择。不幸的是,微软并没有让实现它们变得容易。这当然比以前容易,但在开始时需要做一些准备工作。但是我认为这种努力是值得的!

Azure CLI

要开始,您需要在计算机上安装 Azure CLI。如果您还不知道,请点击下面的链接:

https://docs . Microsoft . com/en-us/CLI/azure/install-azure-CLI?view=azure-cli-latest

这将使您能够从 Windows 命令行或 PowerShell 提示符使用 Azure CLI。我更喜欢 PowerShell 提示符,因为这也能让您完成制表符。

在 PowerShell 提示符下,键入以下内容以获取当前为 F#安装的 Azure 模板列表:

dotnet new --list -lang F#

您应该会看到类似这样的内容:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

F#的 Azure 模板

创建项目模板

首先,我们将根据提示为 Azure 函数创建项目模板:

dotnet new func -lang F# --name AzureFunctionFSharp

这将创建 4 个文件:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

创建功能

在所有可用的 Azure 函数模板中,最容易使用的是 HttpTrigger 。要在提示符下创建它:

dotnet new http -lang F# --name HttpTrigger

这将创建 HttpTrigger.fs

创建解决方案

完成所有这些后,下一步是在 Visual Studio 2019 中创建解决方案文件。如果你打开项目文件azurefunctionfsharp . fsproj,你应该会发现几乎所有你已经添加的东西:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

VS2019 中的初始项目

但是,您会注意到它没有我们的 HttpTrigger.fs 文件!只需将该文件添加到项目中。还需要添加 hosts.jsonlocalhost . settings . JSON。对于这最后两个文件,您必须确保它们的构建动作是 None 并且它们被复制到输出目录(如果较新的话):

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

为 JSON 文件构建属性

一旦你完成了,构建项目并保存解决方案。

附加 NuGet 包

我找到了 FSharp。Data NuGet 包在处理 F#项目时非常有用。您可以通过项目的管理包选项来添加它。

创建自定义模板

完成所有这些后,您可以将整个项目保存为自定义模板,供将来的项目使用。这将使你不必再次经历这一切。如果您在解决方案浏览器选项卡中选择您的项目,然后从项目菜单中选择导出模板,您可以将该项目导出为未来模板:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

导出模板

下次你想创建一个 F# Azure Function 项目时,你可以使用你已经创建的自定义模板:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

创建一个新的 F# Azure 函数项目

调试你的 F# Azure 函数

如果一切设置正确,您现在应该能够按 F5 键并调试您的项目。您应该会看到类似这样的内容:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Azure 功能在本地运行

然后,您可以使用类似于 Postman 的东西向 REST API 发送请求,并查看您的输出。

结论

正如我在开头所说,这不像在 C#中创建 Azure 函数那样简单,但肯定值得付出努力。希望微软会继续改进他们对 F# Azure 函数的支持,并在 Visual Studio 2019 或未来版本中放置一个合适的模板。与此同时,这是你自己可以做到的。

寻找最佳预测模型:不同单变量预测模型的比较

原文:https://towardsdatascience.com/f-forecasting-5d23341462eb?source=collection_archive---------22-----------------------

使用 AR、MA、ARIMA 和 SARIMA 进行单变量预测的最简单、最全面的指南。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

预测可能是一项艰巨的挑战,尤其是对那些只有很少或没有统计学背景的人来说。但我认为这比人们想象的要容易得多。在本文中,我将介绍基本的单变量预测模型,并相对轻松地预测一个变量。

基本模型

单变量预测有两种基本模型。第一种是利用预测变量的过去值的自回归模型和使用白噪声误差项的过去值的移动平均模型。

自回归模型看起来像这样

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

自回归模型

请注意,该模型仅使用预测变量(y)的过去(滞后)值。我们使用滞后的数量 pp 通过一些测试来确定。

移动平均线模型看起来是这样的

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

移动平均模型

像 AR 一样,MA 使用过去的值,但它使用误差项,而不是预测变量。我们使用 q 数量的滞后, q 由一些测试确定。

我们可以将自回归模型和移动平均模型结合在一个叫做 ARMA 的模型中。然而,通常情况下,我们的预测变量是非平稳的。这意味着该系列通常包含上升或下降趋势。为了减轻这一点,我们可以差分序列,以消除那些向上或向下的运动,使序列平稳。这样做,我们产生了 ARIMA 模型或自回归综合移动平均。一些时间序列变量可能具有季节性,如销售或收入,它们通常在假日期间激增。为了适应这种情况,我们有一个 ARIMA 的广义变体,称为 SARIMA,它也包含了季节滞后。

ARIMA模型看起来是这样的

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

滞后算子表示法中的 ARIMA 模型

在这个模型中,我们将系列差 d 次,直到它变得稳定*。*phi 和 theta 分量分别代表 AR 和 MA 模型。

萨里玛模型看起来像这样

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

滞后算子表示法中的 SARIMA 模型

这仅仅是 ARIMA 的一个概括,但是增加了季节差异、季节移动平均滞后和季节自回归滞后。

预赛

我们的目标是预测下个月的通货膨胀率。您应该拥有的是逗号分隔的值文件(。从 2000 年 1 月到 2020 年 4 月菲律宾的月通货膨胀率。档案名称为 InflationRateLecture.csv。如需完整系列,您可以从 Bangko Sentral ng Pilipinas 主要统计指标页面下载。您还应该在 Mac 或 PC 上安装 R 和 RStudio 的副本。如果这是你第一次使用 R,不要害怕,只要遵循下面的代码就可以了。

第一步是安装必要的软件包。对于这个例子,我们需要安装所需的包。这些命令如下:tidyverse 用于常规数据操作,urca、forecast、TSstudio 和 tseries 用于必要的预测命令。请随意探索您可以从中获得的各种功能。

生成一个新的脚本,以便您可以跟踪事情。首要任务是安装所需的软件包。我们可以在 tools 选项卡中手动查找包,或者您可以只运行下面的命令。请注意,根据您的互联网连接,安装可能需要一些时间。

install.packages("tidyverse")
install.packages("urca") 
install.packages("forecast") 
install.packages("tseries") 
install.packages("TSstudio")

安装完成后,您现在必须告诉 R 您将要使用这些包。我们通过调用 library()函数来实现这一点。把这想象成从图书馆里拿一本书,你想借并在一次特定的学习中使用。

library(tidyverse)
library(urca)
library(forecast)
library(tseries) 
library(TSstudio)

运行完所有这些命令后,您应该准备好运行所有必要的命令。如果在预测过程中关闭 R 会话,只需再次使用库命令来重新加载包。无需重新安装(除非有可用的软件包更新)。

加载数据集

加载数据集的一个简单方法是使用 file.choose()函数,它会打开一个对话框,类似于我们打开文件时习惯使用的对话框。将数据集存储在对象中很重要,这样我们以后就可以引用它。首先,我们加载数据集并将其存储在一个对象中。在本教程中,我将物体命名为“膨胀”,但是你可以随意命名。代码和数据集可以在这里找到

https://drive . Google . com/drive/folders/11 rzi 8 p-qcvwlamdro 93 fnslqlxco 39 ef?usp =共享

inflation <- read_csv(file.choose())

read_csv 是 tidyverse 内 R 中 readr 包的一部分。这用于读取 csv 文件,并能够在 r 中加载它。您应该注意到,应该会出现一个对话框,提示您选择文件。一定要选 InflationRateLecture.csv。

head(inflation)
nrow(inflation)

运行 head(inflation)命令会列出数据集的前 6 行。你应该看到 2000 年 1 月的通货膨胀率是 5.5,2000 年 2 月是 5.6,以此类推。nrow(inflation)给出数据集中的总行数。这表明数据集中有 244 个时间段(月)。您也可以通过查看环境选项卡并单击通货膨胀旁边的网格来查看数据集。

声明时序对象

目前,我们加载的数据集是一个框架。为了能够预测,我们需要一系列。如果你查看数据集,我们只对预测其中的“利率”变量感兴趣。因此,我们需要将“利率”变量转换成一个序列。

inf <- ts(inflation$Rate, start = c(2000,1,5), frequency = 12)

我们正在创建一个名为“inf”的新对象,这是我们将使用的系列。ts 命令创建该对象。命令中的第一个参数是变量。$告诉 R 我们想从数据集通货膨胀中获得利率变量。之后,我们指定开始日期为 2000 年 1 月 5 日。r 可以在这之后自动检测结束。最后,我们指定系列的频率。因为我们处理的是月度数据,所以频率应该是 12。如果是每季度一次,频率为 4,每周一次为 52,每两年一次为 2。

绘制时间序列图

将我们的系列形象化是很重要的。我们可以使用 autoplot 命令来做到这一点。

autoplot(inf) + ggtitle("Inflation Rate (Philippines), January 2000 to April 2020") + labs(x = "Time", y = "Inflation Rate")

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

通货膨胀率曲线图

该命令以相应的标题“通货膨胀率(菲律宾),2000 年 1 月至 2020 年 4 月”绘制系列“inf”,其中 x 轴标记为时间,y 轴标记为通货膨胀率。对于这些规范,我们使用 ggtitle 和 labs 选项。如果你做的正确,你应该有一个类似上图的图。我们可以看到全球金融危机期间的通胀飙升,缩减恐慌,以及最近通过的第一套刺激方案。

预测构建模块

我们现在继续生成 ACF 和 PACF 图,并确定序列是否是非平稳的。

让我们首先生成通货膨胀率的 ACF 和 PACF。同样,ACF 和 ACF 可以告诉我们很多关于这个系列的特性。通常,它给出了序列的基本过程的一些指示,无论它是 AR、MA 还是 ARMA。此外,如果我们认为序列是非平稳的,我们将看到通货膨胀差值的 ACF 和 PACF。

ggAcf(inf) + ggtitle("ACF of Inflation")
ggPacf(inf) + ggtitle("PACF of Inflation")

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

ACF 和 PACF(水平)

图中的 ACF 是几何衰减的,而 PACF 记录了立即截止。如果我们回忆一下上节课关于 ACFand PACF 的内容,这与 AR 过程是一致的。虽然还不确定,但这给了我们一个潜在过程的线索。在 ACF 中,请注意第一个到第十一个滞后具有统计显著性(超出蓝色置信带)。我们还可以看到,一些部分自相关是重要的,如第一、第二和第十四。

系列差异

减轻非平稳性的一种方法是对序列求差分。为此,我们使用 diff()命令。

dinf <- diff(inf)
ggAcf(dinf) + ggtitle("ACF of Inflation (Differenced)") 
ggPacf(dinf) + ggtitle("PACF of Inflation (Differenced)")

第一个命令利用 diff()函数对序列进行差分,并创建一个对象“dinf ”,它是通货膨胀的差值。默认情况下,它会差一次,但我们可以将其设置为差两次或指定的任何次数。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

ACF 和 PACF(差异)

类似于这些水平,我们可以看到 ACF 呈几何衰减,而在 PACF 中可以看到立即截止。这是支持 AR 过程的更多证据。但是,请注意,并不是很多滞后都很明显。这是一个信号,表明序列是“平稳的”,这迫使它显示协方差平稳的性质。我们将继续深入探讨这个问题。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

水平与差异通货膨胀

比较通货膨胀的水平值和差值会得出一些有趣的结果。首先,使用简单的图形外观可以证明非平稳性。但是,在进行正式的统计测试之前,我们不能太确定。第二,请注意,在差分序列中仍然有野峰值(异常值)。这些可能是结构性突变的指标,我们需要考虑它们是否存在。

时间序列的分解

对我们拥有的时间序列进行适当的分解也很重要。这些成分是趋势、季节性和序列中的随机成分。幸运的是,R 中有一些命令可以自动为我们绘制图表。

ts_decompose(inf, type = "additive", showline = TRUE)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

级数的分解

TSstudio 库中的 ts_decompose 命令为我们提供了该系列组件的可视化效果。此命令会将序列分割成序列的观察、趋势、季节和随机部分。请注意,可能在每年的八月或九月,会出现一些可观察到的季节性。原因我会留给你去想。TSstudio 中的分解命令更具交互性,允许您将光标悬停在图形(由 plot.ly,一个有趣的图形库生成)上,并深入研究该系列。随着时间的推移,我们将会更多地使用这种方法。

非平稳性测试

在测试非平稳性时,我们将使用三种最流行的测试。这些是扩展的迪基-富勒试验、菲利普-佩伦试验和 KPSS 试验。请记住 ADF 和 PP 测试是单位根测试。因此,他们的零假设是非平稳的,而他们的替代品是平稳的。相反,KPSS 检验是平稳性检验,其零假设是平稳性,而其替代假设是非平稳性。

扩充迪基-富勒试验

进行 ADF 测试的命令是 r 中的 adf.test()。我们将使用平稳性的两个备选假设对系列进行此测试。我们将在原始系列和差异系列上运行此操作。

adf.test(inf) 
adf.test(inf, k = 1)
adf.test(inf, k = 2)
adf.test(dinf)

请注意,当我们运行第一行时,有一个提示提示序列是静止的。我们测试第四行的时候也是这样。虽然通货膨胀的差异变量肯定是稳定的,但该水平的值可能具有很大的欺骗性。正如我们前面说过的,ADF 测试的限制是你必须指定滞后阶数。这些测试(第一次和第三次)在第六轮进行。如果我们使用一个更现实的滞后,比如 1 或 2,这个序列被确定为非平稳的。

菲利普斯-佩龙试验

对于 Phillips Perron 测试,我们使用 pp.test()命令。与 ADF 测试不同,我们不再需要指定滞后阶数,并且更加通用。

pp.test(inf)
pp.test(dinf)

PP 测试的结果相当有说服力。我们看到,在水平,该系列是不稳定的,因为我们无法拒绝零假设。一旦求差,数列就稳定了。因此,当我们开始建立一个预测模型时,我们需要对通货膨胀进行差分,以使其平稳化。

科维亚特科夫斯基-菲利普斯-施密特-申试验

最后,我们转向 KPSS 检验。请记住,这个测试的零假设是平稳性,而另一个假设是非平稳性。KPSS 测试的命令是 kpss.test()。我们可以指定一个名为 null 的选项为“趋势”或“水平”或两者。在这种情况下,我们就让它保持缺省值,考虑两者。

kpss.test(inf)
kpss.test(dinf)

正如所料,我们发现水平序列不是平稳的。奇怪的是,检验还发现差分序列是非平稳的。尽管如此,我们也可以参考 ADF 和 PP 检验的结果来支持我们的主张,即差分序列是平稳的。

预测本身

现在让我们转到预测本身。首先,在进行样本外预测之前,我们先进行样本内预测。正如我们在第一部分中提到的,预测样本的原因是为了查看生成的模型的质量,并让我们将不同的预测模型及其估计值与实际实现值进行比较。我们将使用上一章讨论的预测质量指标。最后,在接近尾声时,我们将使用我们确定的最佳预测模型来预测下一年的通货膨胀。

将数据集分成训练集和测试集

首先,让我们将数据集分成两个样本,一个训练样本和一个测试样本。训练样本是我们必须预测的可用数据。测试样本是已经实现的数据(即我们已经知道系列值),但我们坚持测试预测模型的质量。而以前,这一步曾经是一个痛苦,与 R,它是一件轻而易举的事。我们使用 ts_split 命令来做到这一点。

split_inf <- ts_split(inf, sample.out = 12)training <- split_inf$train 
testing <- split_inf$testlength(training)
length(testing)

我们使用 ts_split 函数创建了一个名为 split_inf 的对象,它本质上是 inf,但被分成两部分。对象 inf 分为两部分,其中测试集由命令 sample.out 给出。我们将 sample.out 设置为等于 12,即 12 个月或一年。因此,我们希望我们的测试(验证)周期等于一年。之后,我们创建两个对象(培训和测试),这将创建两个独立的系列。使用 length 命令,我们可以确定每个生成的序列中有多少个周期。您会注意到,定型数据集有 232 个周期,而测试数据集有 12 个周期(与 sample.out 选项指定的数量相同)。

诊断训练集

至少对实现什么模型有一些概念是很重要的。要做到这一点,我们需要尝试和诊断我们必须的训练数据集,看看我们是否可以提出关于哪个模型可能适合该系列的建议。为此,我们恳求使用 arima_diag()命令。

arima_diag(training)

运行这个程序,我们就能得到要跟踪的数字。由于这是使用 plot.ly 创建的,因此交互性很强。我们可以看到,它显示了训练数据集的值以及相关的 ACF 和 PACF。它还向我们展示了差异训练系列的图表。我们可以看到,ACF 正以几何级数下降,在 PACF 看到了一个直接的截止。这类似于我们对 ar 模型的预期模式。要确定要使用的滞后数量,请注意在 PACF 中,前两个滞后仍然很重要。在第二个滞后之后,大多数剩余的滞后是不重要的。现在,让我们猜测两个自回归滞后。还要注意,在 PACF 和 ACF 中,有红色的数据点。这些红色的数据点表明了季节性滞后的可能性。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

ARIMA 诊断图

构建预测模型

让我们试着预测具有三种不同规格的三种模型。我们将尝试使用的三种模型是

安 ARIMA(2,1,1)

萨里玛(2,1,1)(1,0,0)

该模型使用 auto.arima()函数确定了最合适的值

对于第一个模型,我们将尝试使用 2 个自回归滞后,因为这是 PACF 所表明的。我们将对序列进行一次差分,因为我们知道在不同的水平上,序列是不稳定的,如 ADF、PP 和 KPSS 检验的结果所示。我们猜测我们有 1 移动平均线滞后。对于第二个模型,我们将使用与第一个相同的规范,只是我们添加了一个季节性自回归滞后。最后,对于第三个模型,我们使用 R 中内置的 auto.arima()函数来避免猜测选择哪个 lag 规范是最好的。

让我们转到模型 1。我们创建一个名为 arima211 的对象,并使用 arima()命令进行建模。arima()命令中的第一个选项是 training,这是我们将使用的系列。阶数选项指定了 ARIMA 的阶数,在这种情况下,我们指定了一个具有两个自回归滞后、一个平稳化差异(即序列是 1 阶的积分)和一个移动平均滞后的 ARIMA。autoplot()命令检查是否满足稳定性条件。这就是第二节中阐述的平稳性条件。由于我们处理的是逆根,所以所有的逆根都必须在单位圆内。最后,check_res 命令提供对残差的诊断,我们希望残差是白噪声。模型 2 的结构与此相同,只是我们在调用 arima()命令时添加了一个季节性订单。在这种情况下,我们添加 1 个季节性自回归滞后。模型 3 的结构与此相同,只是我们让 R 使用 auto.arima()命令来决定顺序。选项 search = TRUE 只是确保它可以选择一个 SARIMAmodel,如果它认为它是最佳的。

#For Model 1arima211 <- arima(training, order = c(2,1,1))
autoplot(arima211)
check_res(arima211)#For Model 2 sarima2111 <- arima(training, order = c(2,1,1), seasonal = list(order = c(1,0,0)))
autoplot(sarima2111)
check_res(sarima2111)#For Model 3auto <- auto.arima(training, seasonal = TRUE)
auto #We obtained a SARIMA(2,1,0)(2,0,1) based on auto.arima()
autoplot(auto)
check_res(auto)

如果你做对了,你应该会看到后面的数字。请注意,对于所有三个模型,根都在单位圆内,因此,模型已经通过了平稳性标准,表明不再有单位根。查看残差图,我们看到所有三个模型的残差通常都是白噪声。然而,我们确实注意到有一些滞后在置信带之外,但毫无疑问,模型 2 和模型 3 相对于模型 1 产生更多的白噪声误差,模型 1 在第 12 个滞后时具有相当显著的 ACF。这种红色滞后是季节性滞后,表明季节性模型更适合。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

逆 AR 和 MA 根

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

残留诊断

生成预测和预测评估

现在我们到了关键时刻。现在让我们使用每个模型生成预测,并根据基线对它们进行评估。每个型号的命令结构相似。首先,我们创建三个对象,即 fcast1、fcast2 和 fcasta,它们代表每个模型的预测。每个对象都是使用 forecast()函数生成的,该函数有两个选项。首先是我们键入它将使用什么模型进行预测。第二个是要预测的周期数。由于测试数据集有 12 个周期长,我们将范围 h 设置为 12。接下来,我们使用 test_forecast()命令将预测值与实际值进行比较。该命令生成一个交互式图表,并将每个预测与实际值进行比较,同时还显示每个数据点的关键预测质量指标。最后,accuracy()命令生成我们在上一节中讨论的预测指标的完整平均值。accuracy()命令中的第一个选项是将每个模型生成的预测与测试或验证系列进行比较。

我们可以在下图中看到实际值与预测值的对比图。我们注意到,使用 auto.arima()命令生成的规范的模型 3 似乎是基于 fit 的最佳模型。请注意,当我们生成这些图表时,我们可以悬停在每个数据点上,它会给我们。

#For Model 1fcast1 <- forecast(arima211, h = 12)
test_forecast(actual = inf, forecast.obj = fcast1, test = testing)
accuracy(fcast1,testing)#For Model 2fcast2 <- forecast(sarima2111, h = 12)
test_forecast(actual = inf, forecast.obj = fcast2, test = testing)
accuracy(fcast2,testing)#For Model 3fcasta <- forecast(auto, h = 12)
test_forecast(actual = inf, forecast.obj = fcasta, test = testing)
accuracy(fcasta,testing)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

预测与实际

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

预测指标

进一步使用 accuracy()命令,我们可以看到每个模型的预测统计比较。预测指标如下表所示,由 accuracy()命令生成。我们可以看到从模型 1 到模型 2 以及从模型 2 到模型 3 的改进。这表明添加季节滞后是至关重要的,基于这些指标,auto.arima()生成的模型似乎是最佳的。

样本外预测

既然我们知道了预测的最佳模型,我们现在将生成一个样本外预测。在这种情况下,我们不知道数列的实际值。我们只能利用我们所拥有的任何信息来预测未来。本质上,这是你一直期待的预测。

生成最佳拟合

与生成模型类似,我们创建一个对象,在其中存储选择的模型。我们不使用训练数据,而是使用 inf 的整个膨胀序列。然后,我们测试逆 AR 和 MA 根以及残差。

finalfit <- auto.arima(inf, seasonal = TRUE)
autoplot(finalfit)
check_res(finalfit)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

最终装配诊断

我们发现所有的逆根都在 AR 和 MA 单位圆内。这样,我们满足了稳定性条件,不再有任何单位根。在残差诊断中,虽然仍有一些明显的滞后,但通常已经是白噪声了。

生成样本外预测

我们现在使用我们选择的模型进行预测。以下命令将生成预测。由于通货膨胀通常会被重新预测,让我们设定一个 4 个月的短期范围。然后,让我们看看它对 2020 年 5 月至 8 月通胀率的预测。summary()命令列出了未来四个月的点预测和置信区间。

fcastf <- forecast(inf, model = finalfit, h = 4)
plot_forecast(fcastf)
summary(fcastf)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

2020 年 5 月至 8 月通胀率预测

我们可以看到,5 月(2.0%)、6 月(2.1%)、7 月(2.1%)和 8 月(2.1%)的预测值与 BSP 的通胀目标和其他预测估计值相当一致。还要注意,随着地平线变得越来越大,置信带也随之扩大。干得好,你刚刚预测了你的第一个关键经济变量。

结论

我们现在已经对样本外进行了预测,并获得了未来四个月的值。随着时间的推移,我们将会看到我们的预测是否确实可靠。可以说,预测是一个反复试验的过程,但我希望您看到指标和内置函数能够消除这一过程中的猜测。尽管如此,预测也是一门艺术,根据经济结构和直觉确定滞后和条件可能在改善预测方面发挥关键作用。当我们讨论多变量预测时,我们将会看到更多。

现在,建议您使用您现在已经学习过的许多工具进行试验,看看您是否能找到一个模型,它提供的预测质量指标甚至比使用 auto.arima()函数选择的模型还要好。这当然是可能的,它只是表明,虽然机器已经进步了这么多,但在一个充满数学和科学的地方,仍然有艺术的空间。一个人只需要寻找这样做的动机。

为了获得更多的实践经验,我制作了这篇文章的视频,可以在我的 YouTube 频道上找到。

参考

[1]布鲁克斯,C. 金融计量经济学导论。(2019)剑桥大学出版社。

[2]汉密尔顿,j .时间序列计量经济学。(1994) 普林斯顿大学出版社,普林斯顿

基于主成分分析的人脸数据集压缩

原文:https://towardsdatascience.com/face-dataset-compression-using-pca-cddf13c63583?source=collection_archive---------27-----------------------

用于图像数据集压缩的主成分分析

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

照片由 Unsplash 上的 Grzegorz Walczak 拍摄

在我的上一篇文章中,我们采用了一种图形化的方法来理解主成分分析是如何工作的,以及如何将其用于数据压缩。如果您对这个概念不熟悉,我强烈建议您在继续之前阅读我以前的文章。我提供了以下链接:

[## 主成分分析—可视化

使用主成分分析(PCA)的数据压缩

towardsdatascience.com](/principal-component-analysis-visualized-17701e18f2fa)

在本文中,我们将了解如何使用 PCA 来压缩现实生活中的数据集。我们将在野外(LFW),使用标记的人脸,这是一个由 13233 张人脸灰度图像组成的大规模数据集,每张图像的尺寸为 64x64 。这意味着每个面的数据是 4096 维的(每个面要存储 64×64 = 4096 个唯一值)。我们将使用主成分分析将这一维度要求降低到几百个维度!

介绍

主成分分析(PCA)是一种用于降低数据集维度的技术,利用了这些数据集中的图像具有共同点的事实。例如,在由脸部照片组成的数据集中,每张照片都有像眼睛、鼻子、嘴巴这样的面部特征。我们可以为每种类型的特征制作一个模板,然后将这些模板组合起来,生成数据集中的任何人脸,而不是逐个像素地对这些信息进行编码。在这种方法中,每个模板仍然是 64x64 = 4096 维,但是由于我们将重用这些模板(基函数)来生成数据集中的每个面,因此所需的模板数量很少。PCA 正是这样做的。让我们看看如何!

笔记本

您可以在此处查看 Colab 笔记本:

[## PCA

colab.research.google.com](https://colab.research.google.com/drive/1QZYqjLm_rLxkgR6COMjjBicHSLMwKxF-)

资料组

让我们从数据集中可视化一些图像。你可以看到每个图像都有一张完整的脸,并且像眼睛、鼻子和嘴唇这样的面部特征在每个图像中都清晰可见。现在我们已经准备好数据集,让我们压缩它。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

压缩

**五氯苯甲醚是一个 4 步流程。**从包含 n 个维度的数据集开始(需要表示 n 个轴):

  • 步骤 1 :找到一组新的基函数(n-轴),其中一些轴对数据集中的方差贡献最大,而其他轴贡献很小。
  • 第二步:按照方差贡献度递减的顺序排列这些轴。
  • 第三步:现在,选择要使用的顶部 k 轴,放下剩余的 n-k 轴。
  • 步骤 4 :现在,将数据集投影到这些 k 轴上。

这些步骤在我之前的文章中有很好的解释。在这 4 个步骤之后,数据集将从 n 维压缩到仅 k 维(k**n)。

第一步

找到一组新的基函数(n-轴),其中一些轴贡献了数据集中的大部分方差,而其他轴贡献很小,这类似于找到我们稍后将组合以在数据集中生成人脸的模板。总共将生成 4096 个模板,每个模板的维度为 4096。数据集中的每个人脸都可以表示为这些模板的线性组合。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

请注意,标量常数(k1,k2,…,kn)对于每个面都是唯一的。

第二步

现在,这些模板中的一些对面部重建贡献很大,而另一些贡献很小。这种贡献水平可以量化为每个模板对数据集贡献的方差百分比。因此,在这一步,我们将按照方差贡献的降序排列这些模板(最重要…最不重要)。

第三步

现在,我们将保留顶部的 k 个模板,删除其余的。但是,我们应该保留多少模板呢?如果我们保留更多的模板,我们的重建图像将非常类似于原始图像,但我们将需要更多的存储空间来存储压缩数据。如果我们保留的模板太少,我们重建的图像将与原始图像非常不同。

最佳解决方案是确定我们希望在压缩数据集中保留的方差百分比,并使用它来确定 k 的值(要保留的模板数量)。如果我们计算一下,我们发现要保留方差的 99%,我们只需要顶部的 577 个模板。我们将把这些值保存在一个数组中,并删除剩余的模板。

让我们来看看这些模板。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

请注意,这些模板看起来都有点像人脸。这些被称为特征脸。

第四步

现在,我们将构建一个投影矩阵,将图像从原来的 4096 维投影到 577 维。投影矩阵将有一个形状 (4096,577) ,其中模板将是矩阵的列。

在我们继续压缩图像之前,让我们花点时间来理解压缩的真正含义。回想一下,这些面可以通过所选模板的线性组合来生成。由于每个面都是唯一的,因此数据集中的每个面都需要一组不同的常数(k1,k2,…,kn)来进行线性组合。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

让我们从数据集中的图像开始,计算常数(k1,k2,…,kn),其中 n = 577。这些常数连同所选择的 577 个模板可以被插入到上面的等式中以重建面部。这意味着我们只需要为每幅图像计算和保存这 577 个常数。我们可以使用矩阵同时计算数据集中每个图像的常数,而不是逐个图像地进行计算。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

回想一下,数据集中有 13233 幅图像。矩阵 compressed_images 包含数据集中每个图像的 577 个常数。我们现在可以说,我们已经将图像从 4096 维压缩到 577 维,同时保留了 99%的信息。

压缩比

让我们计算一下数据集压缩了多少。回想一下,数据集中有 13233 幅图像,每幅图像的尺寸都是 64x64。因此,存储原始数据集所需的唯一值总数为
13233 x 64 x 64 = 54,202,368 个唯一值

压缩后,我们为每个图像存储 577 个常数。因此,存储压缩数据集所需的唯一值总数为
13233 x 577 = 7,635,441 个唯一值。但是,我们还需要存储模板,以便以后重建图像。因此,我们还需要为模板存储
577 x 64 x 64 = 2,363,392 个唯一值。因此,存储压缩数据集所需的唯一值总数为
7,635,441 + 2,363,392 = 9,998,883 个唯一值

我们可以将压缩百分比计算为:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

重建图像

压缩后的图像只是长度为 577 的数组,因此无法可视化。我们需要将其重建回 4096 维,以形状数组(64x64)的形式查看。回想一下,每个模板的尺寸都是 64x64,每个常数都是一个标量值。我们可以使用下面的等式来重建数据集中的任何人脸。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

同样,我们可以使用矩阵一次性重建整个数据集,而不是逐个图像地进行重建,当然会损失 1%的方差。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们来看一些重建的人脸。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者图片

我们可以看到,重建的图像已经捕获了关于人脸的大部分相关信息,并且忽略了不必要的细节。这是数据压缩的额外优势,它允许我们过滤数据中不必要的细节(甚至噪音)。

那都是乡亲们!

如果你成功了,向你致敬!在这篇文章中,我们了解了 PCA 如何用于压缩**在野外(LFW)**标记的人脸,这是一个由 13233 个人脸图像组成的大规模数据集,每个图像的尺寸为 64x64 。我们将该数据集压缩了 80%以上,同时保留了 99%的信息。可以查看我的 Colab 笔记本 了解代码。我鼓励您使用 PCA 来压缩其他数据集,并评论您获得的压缩率。

有什么建议请留言评论。我定期写文章,所以你应该考虑关注我,在你的订阅中获得更多这样的文章。

如果你喜欢这篇文章,你可能也会喜欢这些:

[## 机器学习—可视化

理解机器学习的视觉方法

towardsdatascience.com](/machine-learning-visualized-11965ecc645c) [## 用 Pytorch 检测人脸标志点

想知道 Snapchat 或 Instagram 如何将惊人的滤镜应用到你的脸上吗?该软件检测你的关键点…

towardsdatascience.com](/face-landmarks-detection-with-pytorch-4b4852f5e9c4)

访问我的网站,了解更多关于我和我的工作的信息:

[## 阿卜杜勒·拉赫曼

让我们让电脑智能化吧!

arkalim.netlify.app](https://arkalim.netlify.app/)

面向初学者的 10 行人脸检测

原文:https://towardsdatascience.com/face-detection-in-10-lines-for-beginners-1787aa1d9127?source=collection_archive---------32-----------------------

使用 Python OpenCV 在图像和视频中检测人脸的介绍

我最近在为一个个人项目探索 OpenCV 的 Haar 级联对象检测模块。虽然网上有很多这方面的技术资料,但我这篇文章的重点是用通俗易懂的语言解释这些概念。我希望这将有助于初学者以简单的方式理解 Python 的 OpenCV 库。

在这个演示中,我们将拍摄一张图像并在其中搜索人脸。我们将使用预训练的分类器来执行该搜索。我计划分享更多关于我们将来如何训练我们自己的模型的文章。但是现在,让我们开始使用一个预先训练好的模型。

对于外行来说,OpenCV 是一个 Python 库,主要用于各种计算机视觉问题。

在这里,我们使用的是来自 opencv github 资源库作为我们的模型。您可以下载这个 xml 文件,并将其放在与 python 文件相同的路径中。这里还有一堆其他的模型,你可能想以后尝试一下(例如:-眼睛检测,全身检测,猫脸检测等。)

在开始编写代码之前,让我们先看一下程序的高级流程。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

下面描述的整个过程的图表[输入、面部检测过程和输出]

输入:

该算法需要两个输入:

  1. 输入图像矩阵(我们将读取一个图像并将其转换为数字矩阵/numpy 数组)
  2. 脸部特征(可在Haar cascade _ frontal face _ default . XML文件中找到)

人脸检测过程:

OpenCV 的哈尔级联分类器基于滑动窗口方法。在这种方法中,一个窗口(默认大小为 20×20 像素)在图像上滑动(逐行)以寻找面部特征。每次迭代后,图像按一定的因子缩小(调整大小)(由参数’ 比例因子 '决定)。每次迭代的输出被存储,并且在较小的、调整大小的图像上重复滑动操作。在最初的迭代过程中可能会出现误报,这将在本文后面详细讨论。这种缩小和开窗过程一直持续到图像对于滑动窗口来说太小为止。比例因子的值越小,精度越高,计算费用越高。

输出:

我们的输出图像将在每个检测到的人脸周围包含一个矩形。

代码&解释:

让我们从 python 代码开始。对于这个实验,我们将需要以下 Python 包:

**pip install numpy
pip install opencv-python**

让我们把我们的 python 文件叫做‘face _ detector . py’,把它放在与我们从上面分享的 github 链接下载的 xml 文件相同的路径中。

**# File Name: face_detector.py
# Import the OpenCV library
import cv2**

现在让我们看看承诺的 10 行!

我们准备了 2 个输入[ 输入图像 & 面部特征 XML],如上面流程图中所示。

我用贝丝·哈米蒂的这张美丽的照片(下面的链接)作为我的输入图像(kids.jpg)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

照片由 Pexels贝丝·哈米蒂拍摄

1 我们首先加载 xml 分类器和输入图像文件。由于输入文件相当大,我已经用与原始分辨率相似的尺寸调整了大小,这样它们就不会显得太大。然后,我把图像转换成灰度图像。灰度图像被认为提高了算法的效率。

**face_cascade = cv2.CascadeClassifier("haarcascade_frontalface_default.xml")
image = cv2.imread("kids.jpg")
image = cv2.resize(image, (800,533))
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)**

读取的图像存储为多维 numpy 数组,如下所示。

**print(type(gray_image))
<class 'numpy.ndarray'>**

在下一步中,我们将 gray_image 作为输入传递给 detectMultiScale 方法。

detect multi scale方法将为我们执行检测。它采用以下参数:

scaleFactor : 该参数指定图像缩小的因子,例如:-如果该值为 1.05,则图像缩小 5%。如果该值为 1.10,则图像缩小 10%。比例因子 1.10 比比例因子 1.05 需要更少的计算。

****最小邻居:这是一个阈值,指定每个矩形应该有多少个邻居才能被标记为真正。换句话说,让我们假设每次迭代标记某些矩形(即,将图像的一部分分类为面部)。现在,如果随后的迭代也将相同的区域标记为阳性,则增加了该矩形区域为真阳性的可能性。如果某个区域在一次迭代中被识别为人脸,但在任何其他迭代中没有被识别为人脸,则它们被标记为假阳性。换句话说,minNeighbors 是一个区域被确定为一个面的最小次数。

让我们做一个实验来更好地理解它。我们将使用不同的 minNeighbors 参数值运行我们的代码。

对于 minNeighbors = 0,

所有的矩形都被检测为面。对于一些矩形,有许多重叠的矩形,这意味着这些矩形在多次迭代中被检测为阳性。我们设置阈值来提高算法的准确性。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

minNeighbors = 0 的阳性[图片来自 Pexels贝丝·哈米蒂

明邻= 2

当 minNeighbors = 2 时,大多数重叠矩形不再存在。然而,我们仍然有一些误报。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

minNeighbors = 2 的阳性[照片由贝丝·哈米蒂像素拍摄]

如果我们将这个阈值增加到 4 或 5,我们可以看到不再有假阳性。让我们将这个值设置为 5,然后继续。

**faces=face_cascade.detectMultiScale(gray_image,scaleFactor=1.10,minNeighbors=5)**

detect multi scale方法返回一个 numpy 数组,其中包含面的矩形的尺寸和位置。

x,y-矩形左上角的位置

w,h-矩形的宽度和高度

我们现在用绿色(0,255,0) (BGR 色码)画一个矩形,边界厚度= 1。

该窗口等待 2 秒(2000 毫秒)并自动关闭。

**for x,y,w,h in faces:
    image=cv2.rectangle(image, (x,y), (x+w, y+h), (0, 255, 0),1)
    cv2.imshow("Face Detector", image)
    k=cv2.waitKey(2000)
cv2.destroyAllWindows()**

或者,我们也可以通过添加下面一行来保存图像。

**cv2.imwrite("kids_face_detected.jpeg", image)**

我们的输出图像现在在每个检测到的人脸周围包含一个绿色矩形。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

误报 minNeighbors = 5[图片来自 Bess Hamiti 来自 Pexels

我希望这篇文章能让您对如何在 python 中使用 OpenCV 进行人脸检测有一个基本的了解。我们也可以扩展这段代码来跟踪视频中的人脸。如果你感兴趣的话,我已经在我的 GitHub 储存库这里上传了上面讨论的和用于跟踪网络摄像头视频中的人脸的完整代码。祝你有美好的一天!

** [## 在 5 分钟内制作一个声控鼠标/键盘

Python 中语音识别和 GUI 自动化的初学者指南

medium.com](https://medium.com/@b.arindom/build-a-voice-controlled-mouse-keyboard-in-5-minutes-952bc8f101fc) [## 用 Python 生成 5 行二维码

也许在你的简历中使用它来链接到你的网站或 LinkedIn 个人资料

towardsdatascience.com](/generate-qrcode-with-python-in-5-lines-42eda283f325) [## 绝对初学者的神经网络

用简单的英语介绍感知器

medium.com](https://medium.com/swlh/artificial-neural-networks-for-absolute-beginners-a75bc1522e1d)

参考文献&延伸阅读:

[1]级联分类器,https://docs . opencv . org/2.4/modules/obj detect/doc/Cascade _ classification . html

[2] 5KK73 GPU 分配,https://sites . Google . com/site/5kk 73 GPU 2012/Assignment/viola-Jones-face-detection

[3] OpenCV Github 页面,https://Github . com/OpenCV/OpenCV/tree/master/data/Haar cascades**

仅用 5 行代码实现人脸检测

原文:https://towardsdatascience.com/face-detection-in-just-5-lines-of-code-5cc6087cb1a9?source=collection_archive---------19-----------------------

使用世界上最简单的人脸识别 python 库来识别和操作人脸。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

从印度尼西亚一群孩子的图像中检测人脸。图片由 Pixabay 提供。

F 王牌检测是深度学习的计算机技术师。它识别数字图像或视频场景中的人脸。它被用于多种应用,如面部识别、解锁智能手机、智能广告、情感推断等等。

深度学习是人工智能(AI)中机器学习的子集,它拥有能够从非结构化或无标签的数据中进行无监督学习的网络。

“计算机现在能够看、听和学习。欢迎来到未来!”—戴夫·沃特斯

在这个初学者教程中,我们将学习如何安装和配置 python 环境,使用集成开发环境(ide)来调试和运行我们的 python 代码。然后我们将使用广泛流行的人脸检测和操作库Adam Geitgey 开发的人脸识别。我们将在检测到的 faces🕵.周围定制不同颜色和边框形状的图像它是使用 dlib 最先进的具有深度学习功能的人脸识别技术构建的。该模型在 Wild 基准中的标记人脸上具有 99.38%的准确率。

TL;博士本教程是为绝对初学者准备的,即使你是刚毕业的学生或者是期待使用 python 开始机器学习的人。像 Web 和移动开发者后端开发者这样的技术堆栈开发者也可以轻松地阅读这篇文章。那么,让我们开始新的简短的代码之旅。

环境配置和安装

首先我们需要下载 Python 的最新稳定版本。

通常有两种著名的方法来配置 python 环境并在我们的计算机上安装软件包——pip 或 condo。

python 包包含模块所需的所有文件。模块是可以包含在项目中的 Python 代码库。

  1. PIP**-**一个用于 Python 包的包管理器。
  2. Anaconda**-**一个完整的 python 环境解决方案,运行不同版本,管理所有 python 包。使用 Anaconda Navigator,您可以安装和管理计算机中的所有软件包。

您可以关注其中任何一个或两个。

代码编辑器和 IDE

除了基本的 python REPL (命令行界面),我们可以在这两个专业编辑器中运行我们的 python 程序

  1. py charm**-**下载热门面向专业开发者的 Python IDE 并开始。它就像其他著名的 IDE 一样,启动和使用都很简单。
  2. Jupyter 笔记本 - 被程序员和专业培训师广泛使用的基于网络的代码编辑器。

使用康达安装 Jupyter 笔记本电脑

conda install -c conda-forge notebook

或者使用 pip 安装,然后运行 Jupiter notebook 来运行它-

pip install notebook
jupyter notebook

这足以让我们开始编写第一个 Python 程序并运行它。你可以使用上面的任何一个编辑器。在我们的教程中,我们将使用 PyCharm 编写带有 pip 包管理器的代码来安装包。

所以,让我们开始在任何给定的图像和照片中检测人脸。你不兴奋吗?😀

giphy.com 的 Gif

首先,让我们安装代码运行所需的库。我们将只安装和导入 2 个库。

  1. - 友好的 PIL 叉(Python 影像库)。
  2. -检测图像中的人脸。
**pip install Pillowpip install face-recognition**

您可以创建一个 python 类型的新文件(扩展名为)。py )或者 Jupyter 笔记本中的新笔记本开始编码— face_detection.py 。如果它需要其他相关的库,你也可以使用 pip 或 conda 简单地安装它们。****

让我们在代码中导入上述库-

****import** PIL.Image
**import** PIL.ImageDraw
**import** face_recognition**

第一行

让我们在代码文件所在的文件夹中选择一个名为 GroupYoga.jpg 的图片(你可以选择任何图片),或者给出图片的正确路径。我们应该从 face_recognition 库中将我们的图像加载到 load_image_file() 方法,该方法会将它转换成该图像的 NumPy 数组。我们把它赋给变量名 given_image

**given_image = face_recognition.load_image_file(**'GroupYoga.jpg'**)**

第二行

使用同一个库中的 face_locations() 方法,我们将计算给定 _image 中的人脸数量,并将打印图像中找到的所有人脸的长度。

**face_locations = face_recognition.face_locations(given_image)

number_of_faces = len(face_locations)
print(**"We found {} face(s) in this image."**.format(number_of_faces))**

第 3 行

现在,为了在图像上绘制任何形状,我们将使用 PIL.Image 中的 fromarray() 方法将图像转换为枕头库对象。

**pil_image = PIL.Image.fromarray(given_image)**

第 4 行

现在,我们将运行一个 for-in 循环来打印四个像素位置,如检测到的人脸的上、左、下和右。

****for** face_location **in** face_locations:top, left, bottom, right = face_location
    print(**"A face is detected at pixel location Top: {}, Left: {}, Bottom: {}, Right: {}"**.format(top, left, bottom, right))**

第 5 行

我们将绘制一个绿色的矩形框,宽度为 10。您也可以将形状更改为多边形或椭圆形。所以,在上面的循环中写下面的两个绘制方法。

**draw = PIL.ImageDraw.Draw(pil_image)
draw.rectangle([left, top, right, bottom], outline=**"green"**, width=10)**

现在,只需使用变量 pil_image 来显示我们的新图像,其中检测到的人脸周围使用矩形边框。

**pil_image.show()**

新的临时映像将在您的计算机上自动打开(如果一切设置正确)。它应该是类似下图的东西-

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

检测到做瑜伽的女人的脸。图片由 Pexels 提供。

答对了。🎉

如果您遇到任何编译时或运行时问题以及环境配置问题,您可以在下面的回复部分写下,或者与我联系。

现在,让我们把上面所有的小代码片段收集到一个文件中,这个文件可以在任何 python 环境中运行。让我们使用学校孩子的形象(作为文章封面的特色)

face_detection.py 中的完整代码

如果您运行上面的文件(PyCharm 或 Notebook 中的 run 按钮),如果一切正常(我指的是编译或运行时错误),您将在编辑器的控制台得到下面的输出-

PyCharm 中的控制台输出

就是这样。我们最简单的人脸检测🎭代码已准备好从任何给定的照片中识别人脸。您可以通过更改颜色、边框类型和宽度来自定义上面的代码。我建议尝试定制,并探索其他方法和选项。

Face _ recognitionlibrary 还可以用来在人脸上进行数码化妆,在一群人中检查相似的人脸,围绕这些检测到的人脸开发一些游戏。****

我相信你会发现它是互联网上所有技术文章中最简单的人脸检测教程之一。您可以通过下面的参考资料来了解这个库的更多细节。对于这个库的其他应用,下次我会写一些其他的文章。

资源:

**** [## 人脸识别

查找图片中的面孔查找出现在图片中的所有面孔:查找和处理图片中的面部特征获取…

pypi.org](https://pypi.org/project/face-recognition/) [## 年龄/面部识别

You can also read a translated version of this file in Chinese 简体中文版 or in Korean 한국어 or in Japanese 日本語. Recognize and…

github.com](https://github.com/ageitgey/face_recognition)

在 Medium 上关注我,让我们在 LinkedIn(@ kapilraghuwanshI)和 Twitter ( @techygeeek y)上保持联系,以获取更多此类有趣的科技文章。🤝****

人脸检测模型:使用哪一个,为什么?

原文:https://towardsdatascience.com/face-detection-models-which-to-use-and-why-d263e82c302c?source=collection_archive---------1-----------------------

在 Python 中实现不同人脸检测模型的完整教程之后,通过比较,找出用于实时场景的最佳模型。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Unsplash 上由 Jerry Zhang 修改的照片。

人脸检测是计算机视觉最基本的方面之一。这是许多进一步研究的基础,如识别特定的人,在脸上标记关键点。最近,由于种族定性事件,新闻报道很多,如这里的和这里的所述,有色人种比白人更容易被误解。因此,像 IBM、微软和亚马逊这样的主要科技公司已经禁止他们的系统被警方使用。然而,本文不会详细讨论这些方面,我们只会尝试使用预先训练的模型在人脸上绘制边界框,如 Haar cascades,dlib 正面人脸检测器,MTCNN,以及使用 OpenCV 的 DNN 模块的 Caffe 模型。然后我们将对它们进行比较,找出哪一个最适合实时应用程序。

目录

  • 介绍
  • 装置
  • 为模型编码
  • 比较图像结果
  • 视频比较结果以及达到的帧速率
  • 结论

介绍

我们将使用 Haar、dlib、多任务级联卷积神经网络(MTCNN)和 OpenCV 的 DNN 模块。如果您已经了解它们,或者不想了解它们的技术细节,可以跳过这一部分,直接进入代码。否则,让我们学习它们是如何工作的。

哈尔瀑布

早在 2001 年,保罗·维奥拉(Paul Viola)和迈克尔·琼斯(Micheal Jones)在他们的论文“使用简单特征的增强级联进行快速物体检测”中提出了这些方法它的工作速度非常快,就像简单的 CNN 一样,可以从图像中提取很多特征。然后通过 Adaboost 选择最佳特性。这样就把原来的 160000+的特征减少到了 6000 个特征。但是在滑动窗口中应用所有这些特性仍然需要很多时间。因此,他们引入了一系列分类器,对特征进行分组。如果窗口在第一阶段失败,则该级联中的这些剩余特征不会被处理。如果通过,则测试下一个特征,并重复相同的过程。如果一个窗口可以通过所有的特征,那么它被分类为面部区域。更详细的阅读,可以参考这里

哈尔级联需要大量的正负训练图像来训练。幸运的是,这些级联与 OpenCV 库以及经过训练的 XML 文件捆绑在一起。

正面人脸检测器

Dlib 是一个 C++工具包,包含用于解决现实世界问题的机器学习算法。虽然它是用 C++编写的,但它有 python 绑定来在 python 中运行。它还有一个很棒的面部标志关键点检测器,我在以前的一篇文章中使用它来制作一个实时凝视跟踪系统。

[## 使用 OpenCV 和 Dlib 的实时眼睛跟踪

在本教程中,学习通过 python 中的网络摄像头创建一个实时凝视探测器。

towardsdatascience.com](/real-time-eye-tracking-using-opencv-and-dlib-b504ca724ac6)

dlib 提供的正面人脸检测器使用通过梯度方向直方图(HOG)提取的特征,然后通过 SVM。在 HOG 特征描述符中,梯度方向的分布被用作特征。此外,Dlib 提供了一个更先进的基于 CNN 的人脸检测器,但是,它不能在 CPU 上实时工作,这是我们正在寻找的目标之一,因此在本文中被忽略。尽管如此,如果你想了解它,你可以参考这里的。

MTCNN

它是由张等人于 2016 年在他们的论文“使用多任务级联卷积网络的联合人脸检测和对齐”中介绍的它不仅检测面部,还检测五个关键点。它使用三级 CNN 的级联结构。首先,它们使用完全卷积网络来获得候选窗口及其包围盒回归向量,并且使用最大值抑制(NMS)来重叠高度重叠的候选窗口。接下来,这些候选者被传递到另一个 CNN,该 CNN 拒绝大量的假阳性并执行边界框的校准。在最后阶段,执行面部标志检测。

OpenCV 中的 DNN 人脸检测器

它是一个基于单触发多盒探测器(SSD)的 Caffe 模型,使用 ResNet-10 架构作为其主干。它是在 OpenCV 3.3 之后在其深度神经网络模块中引入的。也可以使用量子化张量流版本,但我们将使用 Caffe 模型。

装置

Dlib 和 MTCNN 都是 pip 可安装的,而 Haar Cascades 和 DNN 人脸检测器需要 OpenCV。

pip install opencv-python
pip install dlib
pip install mtcnn

如果您使用的是 Anaconda,那么请使用 conda 命令安装它们:

conda install -c conda-forge opencv
conda install -c menpo dlib
conda install -c conda-forge mtcnn

为模型编码

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

照片由法比安·格罗斯Unsplash 拍摄

在这一节中,我将解释所有这些不同模型的代码。Dlib 和 MTCNN 的基于 HOG 的描述符的权重已经预先与它们的安装捆绑在一起。Haar cascade XML 文件以及 DNN 模块的人脸检测器的权重和图层文件可以从我的 Github repo 下载。

哈尔瀑布

import cv2classifier = cv2.CascadeClassifier('models/haarcascade_frontalface2.xml')
img = cv2.imread('test.jpg')
faces = classifier.detectMultiScale(img)# result
#to draw faces on image
for result in faces:
    x, y, w, h = result
    x1, y1 = x + w, y + h
    cv2.rectangle(img, (x, y), (x1, y1), (0, 0, 255), 2)

如你所见,使用哈尔级联很容易做出预测。只需使用cv2.CascadeClassifier初始化模型,然后使用cv2.detectMultiScle进行检测。然后循环所有的脸,并把它们画到图像上。

基于 Dlib HOG 的正面人脸检测器

import dlib
import cv2detector = dlib.get_frontal_face_detector()
img = cv2.imread('test.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = detector(gray, 1) # result
#to draw faces on image
for result in faces:
    x = result.left()
    y = result.top()
    x1 = result.right()
    y1 = result.bottom()
    cv2.rectangle(img, (x, y), (x1, y1), (0, 0, 255), 2)

与所有其他模型不同,Dlib 适用于灰度图像。它返回一个“dlib 模块的矩形对象”,该对象不仅包含坐标,还包含其他信息,如面积和中心。

MTCNN

import cv2
from mtcnn.mtcnn import MTCNNdetector = MTCNN()
img = cv2.imread('test.jpg')
faces = detector.detect_faces(img)# result
#to draw faces on image
for result in faces:
    x, y, w, h = result['box']
    x1, y1 = x + w, y + h
    cv2.rectangle(img, (x, y), (x1, y1), (0, 0, 255), 2)

mtcnn.mtcnn加载 MTCNN 模块并初始化。函数detect_faces用于查找结果。这将返回一个 JSON 风格的字典,其中包含人脸的坐标以及它们的预测置信度和检测到的面部标志的坐标。

DNN 模块正面人脸检测器

import cv2
import numpy as npmodelFile = "models/res10_300x300_ssd_iter_140000.caffemodel"
configFile = "models/deploy.prototxt.txt"
net = cv2.dnn.readNetFromCaffe(configFile, modelFile)
img = cv2.imread('test.jpg')
h, w = img.shape[:2]
blob = cv2.dnn.blobFromImage(cv2.resize(img, (300, 300)), 1.0,
(300, 300), (104.0, 117.0, 123.0))
net.setInput(blob)
faces = net.forward()
#to draw faces on image
for i in range(faces.shape[2]):
        confidence = faces[0, 0, i, 2]
        if confidence > 0.5:
            box = faces[0, 0, i, 3:7] * np.array([w, h, w, h])
            (x, y, x1, y1) = box.astype("int")
            cv2.rectangle(img, (x, y), (x1, y1), (0, 0, 255), 2)

使用cv2.dnn.readNetFromCaffe加载网络,并将模型的层和权重作为参数传递。这可以在 OpenCV DNN 的 Github 页面上找到。

为了达到最佳精度,在尺寸调整为*300x300*的 BGR 图像上运行该模型,相应地对每个蓝色、绿色和红色通道应用值*(104, 177, 123)*的平均减法。

绿色的价值有很大的差异。在 pyimagesearchlearn openv的文章中,我发现他们都使用了 117 而不是 177,所以我在cv2.dnn.blobFromImage函数中使用了 117。最后,返回一个 4-D 数组,该数组包含置信度和缩小到 0 到 1 范围的坐标,从而通过将它们乘以原始宽度和高度,可以获得对原始图像的预测,而不是模型预测的 300x300。

比较图像结果

我创建了两个包含 10 张图片的小型数据库,其中一个是从 Unsplash 创建的,另一个是从 Google 创建的,以了解这些技术在大小图片上的表现。让我们一个一个地检查一下。

不溅

在我开始之前,我想给我使用过的布鲁斯·迪克森克里斯·库里克里斯·莫瑞伊森·约翰逊杰里·张杰西卡·威尔逊罗兰·塞缪尔蒂姆·莫斯霍尔德提供图片致谢。由于图像的平均尺寸约为 5000x5000,因此在处理之前,高度和宽度都减少了一半。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

结果

正如预期的那样,Haar cascades 表现最差,也有很多假阳性。Dlib 和 MTCNN 的表现相当均衡,一家领先另一家,反之亦然。DNN 模块有一个全有或全无类型的表现。仔细观察,我们可以看到它在小尺寸的图像上表现不佳,这可能是由于在开始之前将其大小调整为 300x300,所以让我们看看如果采用原始大小,它会如何表现。为此,只需将cv2.dnn.blobFromImage()中的(300, 300)分别更改为原始宽度和高度,并移除调整大小功能。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

完整图像的结果

因此,通过拍摄全尺寸图像,结果得到了相当大的改善,然而,这种方式下,DNN 模块无法对面部尺寸较大的情况做出任何预测。示例:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

没有检测到人脸

谷歌图片

这些来自 Unsplash 的图像非常大,所以我决定也检查一些小图像,看看它们的性能。所有拍摄的图像都有修改后的可重复使用许可。平均尺寸为 220x220,并且它们是按原样处理的,除了 DNN 模块,在该模块中图像被调整到 300x300 的尺寸,并且如果使用原始尺寸的图像,结果并不好。

这给 Dlib 面部检测器带来了一个问题,因为它不能检测小于 80x80 大小的面部,并且由于图像非常小,面部甚至更小。因此,为了测试,图像被放大了 2 倍,但这在使用 Dlib 时是一个巨大的问题,因为面部尺寸不能非常小,并且对图像进行上采样会导致更多的处理时间。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

结果

正如所料,哈尔再次表现最差。MTCNN 给出了完美的结果,除了几张图片,总共不能识别两张脸。DNN 紧随其后,无法识别 3 张面孔。Dlib 漏掉了更多的面孔,我们也不应该忘记它已经将图像放大了 2 倍。

因此,在进入视频部分之前,让我们回顾一下我们从本部分的结果中学到的东西。

  • Haar 是相当过时的,并且通常给出最差的结果。
  • OpenCV 的 DNN 模块的面部检测模型工作得很好,但是如果图像的尺寸非常大,那么它会引起问题。一般来说,我们不处理这种 3000x3000 的图像,所以这应该不是问题。
  • Dlib 不能检测小于 80x80 的人脸,所以如果处理小图像,请确保放大它们,但这会增加处理时间。
  • 所以考虑到以上两点,如果我们要处理极端的脸尺寸,MTCNN 将是最好的选择,可以说是领先竞争到现在。

**注意:**由于 Dlib 的作者戴维斯·金(Davis King)手动注释的人脸,Dlib 的预测有时会遗漏下巴或前额,因此如果您正在进行的任务无法负担此费用,请不要使用 Dlib。

比较视频中的模型

在开始之前,为什么不澄清我们将在哪些目标上测试我们的模型:

  • 面部的不同角度
  • 头部移动
  • 面部遮挡
  • 不同的照明条件
  • 达到的帧速率

传递给模型的每个帧的大小是 640x360,它们按原样被处理,除了 DNN 模型被减小到 300x300。

面部和头部运动的不同角度

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

结果(压缩以减小大小)

OpenCV 的 DNN 模块在这里打了一个本垒打。它能够检测到高达疯狂角度的侧脸,并且很大程度上不受快速头部运动的影响。其他人不是它的对手,在大角度和快速移动时失败了。

面部遮挡

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

结果(再次根据大小进行压缩)

同样,OpenCV 的 DNN 的面部检测模块是这里的明显赢家。让我提供确切的结果。这个视频一共 642 帧。DNN 模块能够检测出其中 601 个人的脸!相比之下,第二名是哈尔,是的哈尔,它在其中的 479 张照片中出现了这张脸,紧随其后的是 MTCNN,有 464 张照片。Dlib 远远落后,只在 401 帧中检测到人脸。

不同的照明条件

这里的目标是看看这些模型在光线很弱的情况下以及当光源在人的正后方时表现如何。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

结果

让我们给它应有的荣誉,因为只有哈尔·卡斯卡特是唯一能够在黑暗中在几帧内检测到人脸的模型,而 DNN 模型在那段时间提供了假阳性。当灯打开时,DNN 模块又开始工作,提供完全准确的预测。Dlib 的输出有点不稳定,但比 Haar cascade 要好,Haar cascade 能够预测的帧数更少,也给出了一些假阳性。真正令人惊讶的是 MTCNN。它甚至没有在一帧图像中检测到人脸,这表明如果要使用它,照明条件需要良好。

帧频

报告的值是使用英特尔 i5 第七代处理器获得的,传递的图像大小为 640x360,但 DNN 模块除外,它传递的图像大小为 300x300,这是迄今为止的做法。

哈尔 — 9.25 fps

Dlib — 5.41 fps

MTCNN — 7.92 fps

OpenCV 的 DNN 模块 — 12.95 fps

结论

  • Haar Cascade 分类器在大多数测试中给出了最差的结果,同时还有许多假阳性。
  • Dlib 和 MTCNN 的结果非常相似,略微优于 MTCNN,但 Dlib 无法识别非常小的人脸。此外,如果图像的大小非常极端,并且保证照明良好,遮挡最小,并且主要是正面人脸,MTCNN 可能会在我们比较图像时给出最佳结果。
  • 对于一般的计算机视觉问题,OpenCV 的 DNN 模块的 Caffe 模型是最好的。它可以很好地处理遮挡、快速头部运动,还可以识别侧脸。此外,它还提供了所有游戏中最快的 fps。

所有的代码和文件都可以在我的 Github repo 上找到。该目标是找到最适合在线监考场景中的人脸检测的人脸检测模型。如果你有兴趣了解更多,你可以阅读这篇文章。

[## 使用人工智能实现在线监考自动化

基于视觉和音频的半自动监考功能,以防止在线考试中的作弊和监控…

towardsdatascience.com](/automating-online-proctoring-using-ai-e429086743c8)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值