为自定义对象检测收集数据
用于训练您的自定义检测模型的 5 种数据收集技术
在过去的十年里,深度学习在计算机视觉中的使用越来越多。在过去的几年中,计算机视觉应用,如人脸检测和车辆检测已经成为主流。原因之一是预训练模型的可用性。
被深度学习在这些应用上的成功所说服,企业现在已经开始使用深度学习来解决自己的问题。
但是如果可用的预先训练的模型不适合您的应用程序呢?
假设您有一个家禽养殖场,想要使用物体检测来将好鸡蛋与坏鸡蛋进行分类,这样您就可以在包装过程中自动剔除坏鸡蛋。
包装中的 5 个好鸡蛋和 1 个坏鸡蛋(图片由 Caroline Attwood 在 Unsplash 上拍摄)
一个预先训练的模型也许能够检测鸡蛋,但它肯定不会区分好鸡蛋和坏鸡蛋,因为它从未被教会这样做。
那你会怎么做?
获取大量好鸡蛋和坏鸡蛋的图像,并训练一个定制的检测模型。
创建良好的定制计算机视觉模型的一个常见挑战是训练数据。深度学习模型需要大量的数据来训练其算法,正如我们在基准模型中看到的那样,如 MaskRCNN 、 YOLO 和 MobileNet ,这些模型是在现有的大型数据集 COCO 和 ImageNet 上训练的。
如何获取用于训练自定义检测模型的数据?
在本帖中,我们将探讨 5 种收集数据的方法,用于训练您的自定义模型来解决您的问题。
1.公开可用的开放标记数据集
如果你幸运的话,你可能会在网上得到你想要的带标签的数据集。
这里有一个免费的计算机视觉图像数据集列表,你可以从中选择。
ImageNet**😗*ImageNet 数据集包含总共约 1400 万张图像,涉及 21,841 个不同类别的对象(截至 2020 年 2 月 12 日的数据)。ImageNet 中一些流行的对象类别是动物(鱼、鸟、哺乳动物、无脊椎动物)、植物(树、花、植物)和活动(运动)。
ImageNet 数据集中的图像示例(来源)
【COCO】**😗*COCO 是一个大规模的对象检测、分割和字幕数据集。它包含大约 330,000 幅图像,其中 200,000 幅图像被标记为 80 种不同的物体类别。
COCO 数据集的图像示例(来源)
Google 的开放图像 : 开放图像是一个约 900 万张图像的数据集,标注有图像级标签、对象边界框、对象分割遮罩和视觉关系。它包含 1.9M 图像上 600 个对象类的总共 16M 的边界框,使其成为具有对象位置注释的最大现有数据集。
开放图像数据集的图像示例(来源)
MNIST 手写数据集 :该数据集总共有 70,000 个手写数字图像,是可从 NIST 获得的更大集合的子集。数字已经过大小标准化,并在固定大小的图像中居中。
来自 MNIST 数据集的图像示例(来源)
Cityscapes 数据集 : 该数据集专注于城市街道场景的语义理解。它包含 30 个不同类别的大约 20,000 张带注释的图片。
来自 Cityscapes 数据集的注释图像示例(来源)
注意:这些只是我找到的几个,还有很多其他的数据集你可以在网上找到。此外,请确保在使用这些数据集之前检查其许可。
2.刮网
另一个选择是在网上搜索图片,然后手动选择下载。由于需要大量数据,这种方法效率不高。
注意:网络上的图片可能受版权保护。在使用这些图片之前,一定要记得检查它们的版权。
谷歌图片中的图片搜索示例
另一种方法是编写一个程序来抓取网页并下载你想要的图片。
一个这样的程序是下载所有图片,一个谷歌 Chrome 的扩展,允许你一次下载一堆图片。在这篇博文中, Arun Ponnusamy expalins 介绍了如何使用下载所有图片来下载戴头盔的人的图片。
注意:图像的版权使用权可能不允许使用批量下载的图像。在使用之前,一定要检查每张图片的版权。
3.拍照
如果您找不到您想要的对象的图像,您可以通过单击照片来收集它们。这可以手动完成,即通过自己点击每张图片或众包,即雇佣其他人为你拍照。另一种收集真实世界图像的方法是在你的环境中安装可编程的摄像机。
4.数据扩充
我们知道深度学习模型需要大量的数据。当你只有一个很小的数据集时,可能不足以训练一个好的模型。在这种情况下,您可以使用数据扩充来生成更多的训练数据。
诸如翻转、裁剪、旋转和平移等几何变换是一些常用的数据扩充技术。应用影像数据扩充不仅可以通过创建变化来扩展数据集,还可以减少过度拟合。
左边是一只狗的原始图像,右边是围绕中心水平翻转的图像(来源
猫的原始和随机裁剪图像(来源)
猫的原始和旋转图像(来源
网球的原始图像和翻译图像(来源
5.数据生成
有时,真实数据可能不可用。在这种情况下,可以生成合成数据来训练您的自定义检测模型。由于其低成本,合成数据生成在机器学习中的使用越来越多。
生成对抗网络(GANs)是用于合成数据生成的许多技术之一。GAN 是一种生成性建模技术,其中人工实例是以保留原始集合的相似特征的方式从数据集创建的。
甘的现代艺术(来源)
摘要
收集训练数据集是训练您自己的定制检测机模型的第一步。在这篇文章中,我们看了一些用于收集图像数据的技术,包括搜索公共开放标签数据集、抓取网页、手动或使用程序拍照、使用数据增强技术和生成合成数据集。
在下一篇帖子中,我们将看看训练您的自定义检测器的下一步,即 为您的数据集 贴标签。敬请关注。
您使用什么技术来收集图像数据集? 在下面留下你的想法作为评论。
原载于*www.xailient.com/blog*。**
找一个预先训练好的人脸检测模型。点击这里下载。
查看这篇文章了解更多关于创建一个健壮的物体检测模型的细节。
更多故事:
关于作者
Sabina Pokhrel 在 Xailient 工作,这是一家计算机视觉初创公司,已经建立了世界上最快的边缘优化物体探测器。
资源:
Roh,y .,Heo,g .,& Whang,S. (2019 年)。机器学习的数据收集调查:大数据-人工智能集成视角。IEEE 知识与数据工程汇刊,1–1。土井指数:10.1109/tkde。58606.88868688666
2019 年 10 月 6 日 Arun Ponnusamy 来源:Tryo labs 在之前的帖子中,我们看到了如何使用 OpenCV 来使用预训练的 YOLO 模型…
www.arunponnusamy.com](https://www.arunponnusamy.com/preparing-custom-dataset-for-training-yolo-object-detector.html) [## 如何为计算机视觉用例创建训练数据|阿彭
对于简单的计算机视觉项目,如识别一组图像中的模式,公开可用的图像…
appen.com](https://appen.com/blog/how-to-create-training-data-for-computer-vision-use-cases/) [## 为计算机视觉建立训练数据的权威指南
谷歌、微软、亚马逊和脸书等科技巨头已经宣布了他们以人工智能为先的产品战略…
hackernoon.com](https://hackernoon.com/a-definitive-guide-to-build-training-data-for-computer-vision-1d1d50b4bf07)*
如何从《纽约时报》收集任何时期的数据
Python 中的简单指南
来源:JJ·古恩,via Adobe Stock
假设我们想知道在一段时间内,*《纽约时报》*中的话语是如何演变的。这些天来,分析这一点会很有趣,因为每当我们访问头版时,都会被关于冠状病毒的新闻淹没。疫情是如何塑造了美国最受欢迎的报纸之一的头条新闻的?
要回答这样的问题,我们需要从纽约时报收集文章元数据。这里我描述了如何用 Python 来做这件事。
目录:
- 在哪里可以找到《纽约时报》的文章元数据
- 如何从纽约时报请求文章元数据
在哪里可以找到《纽约时报》的文章元数据
纽约时报提供了一个由几个API组成的开发者网络,让非员工向他们索取文章和元数据,这对于这种分析来说超级方便。
实际上,没有多少报纸这么做。维护一个 API 需要做很多工作。对于不提供 API 的报纸,我们需要一种不同的方法来获得它们的标题。还是有可能的,只是没那么容易。
开始使用纽约时报API:
在这里创建一个免费的开发者账户。打开验证电子邮件中的链接后登录。进入开发者的主页。
纽约时报开发者网络的主页。
在您的开发者帐户中注册一个新应用。
- 点击右上角的电子邮件地址。
- 在出现的下拉菜单中选择应用。
- 在您的应用程序页面选择**+新应用程序**。
- 输入任何名称和描述。
- 激活存档 API。
- 选择创建。
记下您刚刚注册的应用程序的 API 密钥。这是我们需要从《纽约时报》获取数据的唯一信息,我们很快就会需要它。
您的应用的 API 密钥。
如何从纽约时报请求文章元数据
我们将使用归档 API 来获取去年的所有文章元数据。这段代码可以在 1851 年到今天的任何时间内修改。
加载依赖项。
import os
import json
import time
import requests
import datetime
import dateutil
import pandas as pd
from dateutil.relativedelta import relativedelta
指定日期范围。
end = datetime.date.today()
start = end - relativedelta(years=1)
列出属于这个范围的月份,即使只是一部分。我们需要这些信息来调用归档 API,因为它一次只能运行一个月。
months_in_range = [x.split(' ') for x in pd.date_range(start, end, freq='MS').strftime("%Y %-m").tolist()]
范围内的月份
我编写了一些代码来请求和处理来自归档 API 的文章元数据。这段代码一次只能运行一个月,以实现最佳的内存管理。我们向 API 发送给定月份的请求,接收并解析响应,然后用每篇文章的一些详细信息填充数据框,包括其出版日期、主要标题、章节、主题关键字、文档类型和材料类型。最后,我们将数据帧保存为 CSV 文件,并继续下一个月,直到到达所需时间范围的末尾。
从纽约时报存档 API 请求和处理任意时间段的文章数据的代码。
注意,每个 API 有两个速率限制:每天 4000 个请求和每分钟 10 个请求。为了避免达到每分钟的速率限制,我们在两次通话之间睡眠 6 秒钟。
不要忘记用你的 API 键在第 4 行切换出 YOUR_API_KEY 。
运行代码以获取并处理来自 months_in_range 的文章。
我们已经收集了去年 80,460 篇文章的元数据!每个月都被保存到 headlines 目录下的 CSV 文件中。
让我们看看我们处理的上个月的响应是什么样子的,它仍然在内存中。
response
还有很多。文档告诉我们那里都有什么。
看看这个月的 CSV 文件是什么样子的。
df
正如在数据框中看到的,偶尔会有一致性问题需要注意。有时一个月的第一天被认为是前一个月的一部分。有时数据会缺失,比如 1978 年 9 月和 10 月,原因是多工会罢工。
我们可以利用我们现在的 headlines 目录中的所有文章元数据做很多事情。我们可以做的事情之一是探索*《纽约时报》在过去一年的报道中是如何演变的,重点是疫情冠状病毒。这将是有趣的,因为我们不仅考虑发生了什么,而且考虑媒体如何讨论它。*
完整的笔记本是这里。
如果你想阅读更多我的文章或探索数百万篇其他文章,你可以注册一个中级会员:
[## 通过我的推荐链接加入 Medium-briena Herold
作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
brienna.medium.com](https://brienna.medium.com/membership)
您还可以订阅我的电子邮件列表,以便在我发布新文章时得到通知:
每当布蕾娜·赫罗尔德发表。通过注册,您将创建一个中型帐户,如果您还没有…
brienna.medium.com](https://brienna.medium.com/subscribe)
你可能会对我的其他一些故事感兴趣:
Python 中的简单指南
towardsdatascience.com](/how-to-download-twitter-friends-or-followers-for-free-b9d5ac23812) [## 总统竞选中服用维柯丁:用马尔可夫链制造假头条
在讽刺和现实之间游走
towardsdatascience.com](/zonked-on-vicodin-in-the-presidential-race-generating-fake-headlines-with-markov-chains-87f06cccd866) [## 如何批量获取 arXiv 全文预印本
使用 Python3 和 MacOS X 命令行
towardsdatascience.com](/how-to-bulk-access-arxiv-full-text-preprints-58026e19e8ef)
使用 Python 通过 RSS/Atom 提要收集新闻文章
新闻捕手
或者如何停止依赖数据提供商
由 Unsplash 上的Cup 先生/杨奇煜·巴拉拍摄的照片
在我之前的一篇文章中,我谈到了如何只用 5 行代码就能搜集和分析新闻文章:
好的程序员写代码,伟大的先搜索 github。
towardsdatascience.com](/scrape-and-summarize-news-articles-in-5-lines-of-python-code-175f0e5c7dfc)
这次我将向您展示如何设置一个管道来自动收集几乎所有新闻提供商(如纽约时报、CNN、彭博等)发布的所有新文章。)
为了实现这个目标,我将向您展示如何使用 feedparser Python 包自动收集新闻,该包有助于规范 RSS/Atom 提要。
这篇文章是写给谁的?
面向可能希望收集自己的数据并练习构建数据管道的数据工程师和数据科学家。
什么是 RSS 和 Atom?
RSS 是一种 XML 格式的纯文本,提供一些内容提供商(新闻、播客、个人博客等)最近发表的文章的简要摘要。)
RSS 最常见的生产者是新闻出版商。
RSS 提要的存在是为了提供对最新新闻的访问(例如,对于新闻聚合器和新闻辛迪加)。
RSS 提要不包含整篇文章的文本(在大多数情况下),但提供一些基本信息,如作者、标题、描述、发表时间等。
Atom 是另一种 XML 格式,是作为 RSS 提要的替代而开发的。Atom 似乎比 RSS 更先进,但是我不会在这篇文章中比较这两种格式。
RSS XML 的一个例子:
<?xml version="1.0" encoding="UTF-8" ?>
**<rss** version="2.0"**>**
**<channel>**
**<title>**RSS Title**</title>**
**<description>**This is an example of an RSS feed**</description>**
**<link>**http://www.example.com/main.html**</link>**
**<lastBuildDate>**Mon, 06 Sep 2010 00:01:00 +0000 **</lastBuildDate>**
**<pubDate>**Sun, 06 Sep 2009 16:20:00 +0000**</pubDate>**
**<ttl>**1800**</ttl>** **<item>**
**<title>**Example entry**</title>**
**<description>**Here is some text containing an interesting description.**</description>**
**<link>**http://www.example.com/blog/post/1**</link>**
**<guid** isPermaLink="false"**>**7bd204c6-1655-4c27-aeee-53f933c5395f**</guid>**
**<pubDate>**Sun, 06 Sep 2009 16:20:00 +0000**</pubDate>**
**</item>****</channel>**
**</rss>**
通过 RSS 端点抓取新闻
所以,剩下的唯一事情就是收集我们感兴趣的新闻发布者的所有 URL(端点)。
对于本文,我采用纽约时报提要端点。为此,我不得不:
- 去看https://www.nytimes.com/
- “检查”页面的源代码
- 搜索“rss”术语
- 抓取第一个结果
纽约时报页面的源代码
让我们抓住那个链接,检查它是否像我们需要的东西。
https://rss.nytimes.com/services/xml/rss/nyt/HomePage.xml
好的,正如我们所看到的,这是**“NYT>头条新闻”** RSS。
在 <频道> 部分,您可能会找到关于提要本身的一般信息——描述、构建时间、语言等。
此 RSS 下的每个 <条目> 代表文章。第一个项目代表标题( < title > )称为 的文章“特朗普打赌他能孤立伊朗,迷倒朝鲜。没那么容易。”
如果我们拿这个 <项下的> 链接( <链接> )我们会被转发到一篇文章的原始页面:
RSS 不会给我们一篇文章的全文,但它会建议一个简短的 <描述> 来代替。
Feedparser
现在,当我们知道什么是 RSS 以及如何使用它时,我们可以尝试自动获取新文章。
RSS/Atom 提要的主要缺点是它们没有被规范化。根据维基百科页面,RSS/Atom 只有几个必填字段(链接、标题、描述)。
https://en.wikipedia.org/wiki/RSS
这意味着,如果您想存储来自不同新闻出版商的数据,您应该考虑所有可能的键-值对,或者使用一些无模式技术(例如,elasticsearch)。
探索 feedparser 包
pip install feedparser
import feedparser
feed = feedparser.parse('[https://rss.nytimes.com/services/xml/rss/nyt/HomePage.xml'](https://rss.nytimes.com/services/xml/rss/nyt/HomePage.xml'))
现在我们的提要被加载到了feed
变量下。在.feed
属性下,我们可以找到关于提要元数据本身的主要信息。
**feed.feed**Out[171]:
{‘title’: ‘NYT > Top Stories’,
‘title_detail’: {‘type’: ‘text/plain’,
‘language’: None,
‘base’: ‘[https://rss.nytimes.com/services/xml/rss/nyt/HomePage.xml'](https://rss.nytimes.com/services/xml/rss/nyt/HomePage.xml'),
‘value’: ‘NYT > Top Stories’},
‘links’: [{‘rel’: ‘alternate’,
‘type’: ‘text/html’,
‘href’: ‘[https://www.nytimes.com?emc=rss&partner=rss'](https://www.nytimes.com?emc=rss&partner=rss')},
{‘href’: ‘[https://rss.nytimes.com/services/xml/rss/nyt/HomePage.xml'](https://rss.nytimes.com/services/xml/rss/nyt/HomePage.xml'),
‘rel’: ‘self’,
‘type’: ‘application/rss+xml’}],
‘link’: ‘[https://www.nytimes.com?emc=rss&partner=rss'](https://www.nytimes.com?emc=rss&partner=rss'),
‘subtitle’: ‘’,
‘subtitle_detail’: {‘type’: ‘text/html’,
‘language’: None,
‘base’: ‘[https://rss.nytimes.com/services/xml/rss/nyt/HomePage.xml'](https://rss.nytimes.com/services/xml/rss/nyt/HomePage.xml'),
‘value’: ‘’},
‘language’: ‘en-us’,
‘rights’: ‘Copyright 2020 The New York Times Company’,
‘rights_detail’: {‘type’: ‘text/plain’,
‘language’: None,
‘base’: ‘[https://rss.nytimes.com/services/xml/rss/nyt/HomePage.xml'](https://rss.nytimes.com/services/xml/rss/nyt/HomePage.xml'),
‘value’: ‘Copyright 2020 The New York Times Company’},
‘updated’: ‘Thu, 02 Jan 2020 15:03:52 +0000’,
‘updated_parsed’: time.struct_time(tm_year=2020, tm_mon=1, tm_mday=2, tm_hour=15, tm_min=3, tm_sec=52, tm_wday=3, tm_yday=2, tm_isdst=0),
‘published’: ‘Thu, 02 Jan 2020 15:03:52 +0000’,
‘published_parsed’: time.struct_time(tm_year=2020, tm_mon=1, tm_mday=2, tm_hour=15, tm_min=3, tm_sec=52, tm_wday=3, tm_yday=2, tm_isdst=0),
‘image’: {‘title’: ‘NYT > Top Stories’,
‘title_detail’: {‘type’: ‘text/plain’,
‘language’: None,
‘base’: ‘[https://rss.nytimes.com/services/xml/rss/nyt/HomePage.xml'](https://rss.nytimes.com/services/xml/rss/nyt/HomePage.xml'),
‘value’: ‘NYT > Top Stories’},
‘href’: ‘[https://static01.nyt.com/images/misc/NYT_logo_rss_250x40.png'](https://static01.nyt.com/images/misc/NYT_logo_rss_250x40.png'),
‘links’: [{‘rel’: ‘alternate’,
‘type’: ‘text/html’,
‘href’: ‘[https://www.nytimes.com?emc=rss&partner=rss'](https://www.nytimes.com?emc=rss&partner=rss')}],
‘link’: ‘[https://www.nytimes.com?emc=rss&partner=rss'](https://www.nytimes.com?emc=rss&partner=rss')}}
最重要的字段是copyright
和published
。
Feedparser 会小心地为这些属性分配正确的值,这样您就不必浪费时间自己对它们进行规范化。
标准化文章
与提要一样,您可能会在.entries
属性下找到关于每篇文章的信息。
feed.entries[0].titleOut[5]: 'Trump Bet He Could Isolate Iran and Charm North Korea. It’s Not That Easy.'
这样,我们将知道提要中每个元素的基本信息。
如果你想要这篇文章的全文,你必须带着网址,使用报纸。检查一下我的另一篇文章,我已经把它嵌入了这篇文章的开头。
进一步的工作
试着想想如何构建一个数据管道来收集新文章,并对数据库中已经看到的文章进行重复数据删除。此外,在顶部增加一个 NLP 管道可能会带来很多有用的见解( spaCy python 包非常适合这一点)。
在我的个人博客中,我讲述了我如何构建新闻捕捉器——一个从最受欢迎的新闻出版商那里获取新闻数据的 API。如果你想知道如何将我上面描述的内容扩展成成千上万的内容,请关注我的媒体博客,并收听我的推特。
COVID 期间大学足球旅行的图表
利用 NetworkX 对 2020 年大学足球赛程的网络分析及对大学足球艰难决策的思考
当圣母大学在 8 月 17 日暂停面对面学习时,这是对新冠肺炎阳性病例激增的回应。我质疑,如果校园对学生关闭,这一举措将如何影响足球活动的继续。令人欣慰的是,在回到现场学习后,圣母大学仪表盘上的数字显示阳性测试已经下降并保持稳定。然而,另一个集群的威胁仍然存在,特别是当班级和足球呈现出正常的味道。其他足球强国没有采取如此迅速的行动。例如,阿拉巴马大学塔斯卡卢萨分校(又名阿拉巴马)继续通过一个主要的集群进行个人学习。普遍获得系统发布了一份报告,对每周病例的下降有些乐观。这是一个好消息,希望这种趋势继续下去,然而,阿拉巴马州 6.1%的学生已经被检测为阳性。那太多了。对于学校的管理者来说,迫切的问题是多少阳性测试足以关闭校园?
阿拉巴马州(和其他州)将在秋季学期后转向远程教育
阿拉巴马州已经宣布允许 20%的主场足球比赛容量。超过 2 万人!!我相信许多学校无法证明在足球比赛上招待球迷是合理的,而学生被限制在校园内和远程学习。所以,学校会有两种选择;让球迷离开主场比赛,或者不管爆发的规模如何,坚持亲自学习。你认为学校管理者会喜欢哪一个?
足球的费用
大学橄榄球教练的费用随着收入的增加而增加。如果要求学生支付足球教练的薪水,那么在阿拉巴马,每个学生每年至少要支付 441.38 美元。该数字不包括与项目其他部分相关的成本,包括体育场维护、其他员工、差旅或奖学金成本。
按州和会议列出的每个学生的价格
medium.com](https://medium.com/swlh/exploring-college-football-salaries-dc472448684d)
足球是许多体育院系的生命线,作为校园体验的一部分,它吸引了许多学生。与 COVID 相关的成本也是一个严重的问题。虽然大学年龄人口的死亡率相对于一般人群来说较低,但 COVID 可能会产生严重的长期影响。大约 15%的患有冠状动脉疾病的大学生运动员患上了心脏病,这是一种潜在的长期健康疾病。有多少学生会出现类似的情况?
旅行的风险
我们知道高风险活动,如航空旅行和足球,会增加感染 COVID 的可能性。这个赛季有多少场联盟外和州外的比赛?本文使用 NetworkX 创建网络来找出答案。完整的 2020 赛季时间表可以使用下面的命令从 collegefootballdata.comAPI 下载:
curl -X GET “[https://api.collegefootballdata.com/games?year=2020&seasonType=regular](https://api.collegefootballdata.com/games?year=2020&seasonType=regular)" -H “accept: application/json”
本赛季 FBS 游戏总数为 **413。**参加 FBS 比赛的有 91 支队伍(包括部分 FCS 队伍)。为了构建网络,我们使用了 NetworkX 和 matplotlib。本赛季有 322 场会议赛对 91 场非会议赛。这个赛季谁在打非联盟赛?为了找到答案,我们过滤了会议游戏中的所有内容,然后创建了一个图形对象,并根据团队的会议应用了颜色。
边表示由会议着色的团队之间的游戏。图片作者。
在上面的网络中,FBS 独立队今年玩了最多的会议外游戏(这并不奇怪)。有趣的是,圣母大学仍然被归类为 FBS 独立,尽管打了 ACC 赛程,使南佛罗里达成为唯一的非大会比赛。
随着一些州成为感染热点,今年去其他州旅行可能会成为一个大问题。不同州的球队之间打多少场比赛?原来 86.2%或 356 场比赛需要一个团队跨越州界。我们过滤掉来自同一个州的球队之间的比赛,而不是创建一个图形对象,并根据球队的区域应用颜色。
优势表示位于两个不同州的球队之间的比赛。图片作者。
各州之间有很多旅行。哪个州跨州参赛的队伍最多?那就是佛罗里达,它正在打败德克萨斯,来自 16 个不同州的球队来到阳光之州进行足球比赛。所有的代码、数据和图表都可以在项目 GitHub 上找到。
结论
大学足球的前景是不确定的,球迷、学生和球员的涌入可能会在今年秋天成为 COVID 的热点。我希望在足球赛季结束后,许多目前亲自去的大学会去偏远地区或混合地区。提前去看这些比赛的成本意味着要把球迷从主场比赛中赶走。一些体育部门和学校管理人员根本不能失去足球收入来资助他们的教练人员的年薪,有些高达数千万美元。我相信 COVID 将导致许多运动员质疑业余模式,因为学校似乎将足球美元看得比学生健康更重要。这里希望这个季节能够继续下去,不要在团队或学生群体中爆发任何重大疫情。
附言:带回 NCAA 足球电子游戏!!!
我叫科迪·格利克曼,可以在 LinkedIn 上找到我。一定要看看我下面的其他文章:
按州和会议列出的每个学生的价格
medium.com](https://medium.com/swlh/exploring-college-football-salaries-dc472448684d) [## 一个幻想草案秩序彩票使用 R 闪亮
作为 web 应用程序编写的 NBA 风格的彩票系统
towardsdatascience.com](/a-fantasy-draft-order-lottery-using-r-shiny-6668a5b275d2) [## 刮胡子,还是不刮胡子,这是个问题
使用深度学习对有胡须和无胡须的照片进行年龄分类
towardsdatascience.com](/to-beard-or-not-to-beard-that-is-the-question-b46864d7e003)
大学排名不靠谱
我们来看看数据。
瓦迪姆·谢尔巴科夫在 Unsplash 上拍摄的照片
大学排名没有兑现诱人的承诺。他们接受了决定在哪里学习或教学的丑陋的复杂性,并用一种客观性的幻觉来取代它们。
如果你像我一样,你会从数据中寻求清晰和指导。不幸的是,这些数据有时掩盖了对重大决策至关重要的细微差别。(谎言,可恶的谎言等。)
抛开上哪所大学是否重要的宏观问题不谈,我认为排名的主要来源是不可靠的。利用《泰晤士报高等教育》、《美国新闻》和 QS 的数据,我提出了三个论点:
- 排名不一致
- 排名是不相关因素的集合
- 排名不够
排名不一致
这就是大学排名不靠谱的最简单的原因。我从三个主要来源整理了全球十大大学的排名:
比较泰晤士高等教育、美国新闻和 QS 的 2020 年排名
排名之间的平均标准差为 7.1 。这一数字无疑因一些异常值而增加,如华盛顿大学,它勉强进入了美国新闻排名的前十名,但在美国和 QS 分别排名第 26 位和第 68 位。
六所大学在这三份榜单中都进入了前十名,但即使是这一组也显示出巨大的差异。例如,牛津大学是世界上最好的大学之一,但是在另外两个榜单中并没有进入前三名。
为了更加仁慈,我决定限制我的搜索范围。这三个来源都按学科提供全球大学排名。我选择了经济学的排名,尽管应该注意的是,它将该主题列在“经济学和商业”之下,这与《美国新闻》和 QS 的“经济学和计量经济学”的分类略有不同。
2020 年经济学排名对比
特定经济学排名的平均标准偏差为 3.5 ,约为未指定主题时标准偏差的一半。这似乎表明,在顶尖大学中,当受学科限制时,排名更加一致。
当然,如果受到个人因素的限制,如引用或教学声誉,他们也会更加一致。进一步缩小我的搜索标准将会偏离对大学排名的关注,因为它们通常被认为是(也因为它们出现在新闻中)。
我能想到两个反对以这种方式交叉比较排名的理由:
- 就数量级而言,大学排名仍然是可靠的——排名第 1、#10、#100 和#1000 的大学之间有明显的区别。
- 每份榜单使用不同的标准对大学进行排名,因此结果大相径庭也就不足为奇了。
我同意第一种反对意见。第二个问题揭示了一个更大的问题:
排名是不相关因素的集合
总体排名中使用的大多数标准都是不相关的。需要明确的是,师生比、研究生产率和引用率(都被使用)等维度是大学总分的合理组成部分。然而,任何给定的利益相关者都不应该关心考虑的大多数因素。
例如,学生不会因为他们的教授被大量引用而明显受益。至少,引用不值得占总分数的 30%,因为它们在列表中。也就是说,它的目标是比《美国新闻》更能代表教学质量,后者完全专注于研究成果。
另一方面,学者可能对薪水、职场文化和福利感兴趣。这些类别都没有直接包含在我检查过的列表中。
有人可能会说,排名是衡量一所大学声誉的标准。有趣的是,它包括一项声誉调查,衡量“教学机构的感知声望”,作为其总分的一部分。这意味着他们的“教学”类别本身并不是教学声誉的衡量标准。
这一观点也与排名的交叉比较相矛盾。加州理工学院在非特定学科排行榜上一直排在耶鲁之上,然而人们很难认为耶鲁是这两所大学中更不出名的一所。
这并不是说考虑的所有因素都是合理和重要的。美国和 QS 都将国际学生的比例作为排名的一部分。我明白了为什么拥有一个多元化的学生群体可以提升学生体验,或者表明一个模范的全球声誉。然而,如果不考虑国际学生在某个大学学习的原因,把这个因素包括进去似乎是有问题的。
例如,迪拜的美国大学(排名第 600-650 位)和 T2 的伦敦经济学院(排名第 49 位)吸引了许多海外学生,这可能有不同的原因。在 QS 世界排名中,这两所大学的国际学生比例都是 100 分。
我最近听到一句话,“垃圾进,垃圾出”适用于机器学习模型。这在这里同样相关。如果指标本身一开始就有缺陷,那么仔细组合几十个指标不会让大学排名更可靠。
排名不够
等等,什么?
首先,我要说的是,更多的全球大学排名出版物并不一定会增加可信度。然而,目前排名数量太少,无法对每个大学形成准确的看法。
让我们假设每一份名单都像同行评议研究一样严谨。即使在这种情况下,少数具有矛盾结果的研究也没有给我们提供多少新知识。在将研究结果用于决策之前,通常建议等待形成某种程度的共识;我不明白为什么我们要在这种情况下破例。
除了大量的数据,更集中的分析是必要的。比如哪些大学导致毕业生工资涨幅最高?校园文化哪里更有利于心理健康?在一个给定的机构中,不同系之间的教学质量如何不同?
这些问题没有一个有助于产生全面的分数,但它们最终会对学生、教师和私营部门组织产生影响。这些问题也可以由负责编制大学排名的研究人员来回答。
是时候离开年度新闻周期了,在这一周期中,我们浏览大学排名,就好像它们是体育排行榜一样。在那些给许多雄心勃勃的学生提供过度安慰的组织有序的清单下面,有一个相关的和必要的故事要讲述。
共线性度量
减轻线性回归模型多重共线性的度量和方法
特征选择是选择对目标变量的预测/分类贡献最大的预测变量的过程。在线性回归模型的特征选择中,我们关注与变量有关的四个方面。作为助记“线”,这些是:
- 不平等。所选变量与目标变量具有线性关系。
- I 预测变量的不依赖性。所选变量相互独立。
- 常态。残差通常遵循正态分布(平均值为零)。
- E 方差质量。残差在预测变量的值之间通常是一致的(即,同方差)。
如果选定的预测变量不是相互独立的,我们将无法确定或归因于各种预测变量对目标变量的贡献——模型系数的可解释性成为一个问题。
特征选择的一种方法是通过使用 p 值;其中 p 值高于某个阈值(通常为+/- 0.05)的变量表现为对目标变量没有显著贡献,因此可以删除以降低模型复杂性。然而,当预测变量之间存在多重共线性时,这种方法具有挑战性,正如 sklearn 中的波士顿住房数据集所示。
# Original (full) set of variables
X_o = df_wdummy[['CRIM', 'ZN', 'INDUS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD', 'TAX', 'PTRATIO', 'B', 'LSTAT', 'CHAS_1.0']]
X_o = sm.add_constant(X_o)
y_o = df_wdummy['MEDV']
# Baseline results
model_o = sm.OLS(y_o, X_o)
results_o = model_o.fit()
results_o.summary()
OLS 回归结果 1,注意 0.05 以上的 p 值(图片由作者提供)
基于 p 值,我们移除变量 INDUS 和 AGE,并检查更新的 p 值。
# Remove Age -> Remove INDUS, based on p-values.
X_r0 = df_wdummy[['CRIM', 'ZN', 'NOX', 'RM', 'DIS', 'RAD', 'TAX',
'PTRATIO', 'B', 'LSTAT', 'CHAS_1.0']]
X_r0 = sm.add_constant(X_r0)
y_r0 = df_wdummy['MEDV']
# results
model_r0 = sm.OLS(y_r0, X_r0)
results_r0 = model_r0.fit()
results_r0.summary()
更新的 OLS 回归结果;请注意,p 值均不超过 0.05(图片由作者提供)
尽管所有 p 值都低于 0.05,但多重共线性仍然存在(在 TAX 和 RAD 变量之间)。)多重共线性的存在可能会掩盖各变量对目标变量的贡献的重要性,从而使 p 值的可解释性变得具有挑战性。我们可以使用相关性度量和矩阵来帮助可视化和减轻多重共线性。这种方法是好的,直到我们需要使用不同的相关措施(即 Spearman,Pearson,Kendall)由于变量的固有属性。在上面的例子中,变量 RAD(放射状公路可达性指数)是一个顺序变量。税收(每 10,000 美元的全价值财产税税率)是一个连续变量(非正态分布)。使用不同的相关性度量和矩阵,人们可能会忽略不同类别变量之间的相关性。
另一种识别多重共线性的方法是通过方差膨胀因子。VIF表示每个变量系数的方差膨胀百分比。从值 1(无共线性)开始,介于 1-5 之间的 VIF 表示中度共线性,而大于 5 的值表示高度共线性。在某些情况下,高 VIF 是可以接受的,包括使用相互作用项、多项式项或虚拟变量(具有三个或更多类别的标称变量)。相关矩阵能够识别变量对之间的相关性,而 VIF 能够全面评估多重共线性。大多数连续变量的相关矩阵如下所示,以突出各种共线变量对。可以使用 statsmodels 软件包计算 VIF;下面的代码块显示了包含(左)和移除(右)共线变量的 VIF 值。
连续变量的相关矩阵;肯德尔系数(图片由作者提供)
# Setting the predictor variables
X_o = df_wdummy[['CRIM', 'ZN', 'INDUS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD', 'TAX', 'PTRATIO', 'B', 'LSTAT', 'CHAS_1.0']]
X_r1 = df_wdummy[['CRIM', 'ZN', 'INDUS', 'RM', 'AGE', 'DIS', 'TAX', 'PTRATIO', 'B', 'LSTAT', 'CHAS_1.0']]#
from statsmodels.stats.outliers_influence import variance_inflation_factorvif = pd.Series([variance_inflation_factor(X_o.values, i) for i in range(X_o.shape[1])], index=X_o.columns,
name='vif_full')
vif_r = pd.Series([variance_inflation_factor(X_r1.values, i) for i in range(X_r1.shape[1])], index=X_r1.columns,
name='vif_collinear_rvmd')
pd.concat([vif, vif_r], axis=1)
预测变量的 VIF 值(图片由作者提供)
VIF 值对应于相关矩阵;例如,可变对 NOX 和 INDUS,相关系数在 0.5 (0.61)以上,各自的 VIF 值在 5 以上。共线变量 RAD 和 NOX 的去除改善了 VIF 图。仅仅根据最高的 VIF 数删除共线变量并不能保证构建出性能最佳的模型,这将在下一节中详述。
我们通过删除相关矩阵(如上所示)中确定的所有共线变量来构建基线模型,下一步将删除待定税和 RAD。
# Baseline variables
X_bl = df_wdummy[['INDUS', 'RM', 'AGE', 'RAD', 'TAX', 'PTRATIO', 'LSTAT']]
y_bl = df_wdummy['MEDV']# Explore mitigating multi-collinearity
vif_bl = pd.Series([variance_inflation_factor(X_bl.values, i) for i in range(X_bl.shape[1])], index=X_bl.columns,
name='vif_bl')X_noTAX = X_bl.drop(['TAX'],axis=1)
X_noRAD = X_bl.drop(['RAD'],axis=1)
vif_noTAX = pd.Series([variance_inflation_factor(X_noTAX.values, i) for i in range(X_noTAX.shape[1])],
index=X_noTAX.columns, name='vif_noTAX')
vif_noRAD = pd.Series([variance_inflation_factor(X_noRAD.values, i) for i in range(X_noRAD.shape[1])],
index=X_noRAD.columns, name='vif_noRAD')
pd.concat([vif_bl, vif_noTAX, vif_noRAD], axis=1)
评估基线模型中预测变量的 VIF 图(图片由作者提供)
虽然基于 VIF 放弃税收变量似乎更好,但谨慎的方法是通过调整后的 R 平方度量进行检查(根据预测因素的数量进行调整,只有当下一个添加的变量对模型的改善程度超过偶然的预期时,度量才会增加)。
# Without TAX
model = sm.OLS(y, sm.add_constant(X_noTAX)).fit()
print_model = model.summary()
print(print_model)
模型指标摘要(不含税)(图片由作者提供)
# Without RAD
model = sm.OLS(y, sm.add_constant(X_noRAD)).fit()
print_model = model.summary()
print(print_model)
模型指标摘要(无 RAD)(图片由作者提供)
从更高的调整后的 R 平方数字,我们可以推断出模型在 RAD 变量被删除的情况下表现得更好!多重共线性问题解决后,下一步可能是探索增加交互项以潜在地提高模型性能。
总之,多重共线性的存在会掩盖预测变量对目标变量的重要性。相关矩阵和 VIF 的使用有助于识别相关变量对并评估所选变量(要素)之间的多重共线性。虽然仍然需要一些迭代来评估模型性能,但有了 VIF 和相关矩阵,我们将能够为特征选择做出更明智的决策。
代码托管在这里:https://github.com/AngShengJun/petProj/tree/master/eda_viz
参考资料:
- 相关方法 1https://data science . stack exchange . com/questions/64260/Pearson-vs-spearman-vs-Kendall
- 相关方法 2https://support . minitab . com/en-us/minitab-express/1/help-and-how-to/modeling-statistics/regression/supporting-topics/basics/a-comparison-of-the-the-Pearson-and-spearman-correlation-methods/
使用 NLTK 库的自然语言处理中的搭配
一棵树的两根树枝美丽地并列在一起。来源:像素
搭配是包含多个单词的短语或表达,这些单词很可能同时出现。比如——‘社交媒体’、‘学校假期’、‘机器学习’、‘新加坡环球影城’等。
为什么需要搭配?
想象一下,有一个需求,您希望了解客户留下的文本评论。你想了解行为洞察,比如谁是你的顾客,有多少人光顾你的店,他们对什么感兴趣,他们买什么,他们参加什么活动,等等。
为了更简单,让我们假设你有一家餐馆,你有几千条评论。因此,如上所述,作为餐馆老板,你需要了解顾客的行为。
使用命名实体识别,我在人、事件、日期、产品类别中提取了某些有趣的实体。例如日期中的“星期六”。然后我想知道人们在“星期六”前后在他们的评论中写了什么!
因此,我缩小了几个广泛的主题,如“家庭”、“夫妇”、“假日”、“早午餐”等。搭配帮助我找到了两三个很有可能围绕这些主题同时出现的词。这两个或三个词一起出现,也被称为二元和三元。
搭配与常规的二元或三元组有何不同?
作为二元模型共现的两个单词的集合,以及作为三元模型共现的三个单词的集合,可能不会给我们有意义的短语。例如,句子“他应用了机器学习”包含二元词:“他应用了”、“应用了机器”、“机器学习”。“他应用”和“应用机器”没有任何意义,而“机器学习”是一个有意义的二元模型。仅仅考虑同现单词可能不是一个好主意,因为像‘of’这样的短语可能会频繁地同现,但实际上没有意义。因此,需要 NLTK 库中的搭配。它只给我们有意义的二元模型和三元模型。
一个搭配怎么比另一个好?
哦!所以你基本上想知道评分是如何进行的?嗯,我用了点态互信息或 PMI 分数。讨论什么是 PMI 以及它是如何计算的不是这篇博客的范围,但是这里有一些很棒的文章,你可以阅读来了解更多:第一条和第二条。我使用 PMI 分数来量化和排列搭配库产生的二元模型和三元模型。
如何实现搭配?
正如我前面提到的,我想知道人们围绕某些主题写些什么,比如一些特定的日期、事件或人物。因此,从我的代码中,你将能够看到特定单词周围的二元模型、三元模型。也就是说,我想知道除了我选择的“特定单词”之外,很可能形成的二元模型、三元模型。这个特定的词就是我们从命名实体识别中得到的主题。
import nltk
from nltk.collocations import *bigram_measures = nltk.collocations.BigramAssocMeasures()# Ngrams with 'creature' as a member
creature_filter = lambda *w: 'kids' not in w ## Bigrams
finder = BigramCollocationFinder.from_words(
filtered_sentences)
# only bigrams that appear 3+ times
finder.apply_freq_filter(3)
# only bigrams that contain 'creature'
finder.apply_ngram_filter(creature_filter)
# return the 10 n-grams with the highest PMI
# print (finder.nbest(bigram_measures.likelihood_ratio, 10))
for i in finder.score_ngrams(bigram_measures.likelihood_ratio):
print (i)
二元搭配代码的示例结果
结果显示,人们在评论中会写“儿童菜单”、“儿童跑步”、“儿童餐”。现在让我们看看“孩子”周围的三元组。
## Trigrams
trigram_measures = nltk.collocations.TrigramAssocMeasures()# Ngrams with 'creature' as a member
creature_filter = lambda *w: 'kids' not in w finder = TrigramCollocationFinder.from_words(
filtered_sentences)
# only trigrams that appear 3+ times
finder.apply_freq_filter(3)
# only trigrams that contain 'creature'
finder.apply_ngram_filter(creature_filter)
# return the 10 n-grams with the highest PMI
# print (finder.nbest(trigram_measures.likelihood_ratio, 10))
for i in finder.score_ngrams(trigram_measures.likelihood_ratio):
print (i)
三元组搭配代码的示例结果
代码输出让我们对上面挖掘的二元模型有了更深入的了解。因此,“儿童菜单可用”和“伟大的儿童菜单”是“儿童菜单”的延伸,这表明人们为有儿童菜单的餐厅鼓掌。同样,“孩子跑”与“孩子尖叫着跑”这一负面含义联系在一起。这意味着,当有孩子跑来跑去尖叫时,餐馆里的客人可能没有好好享受他们的时光。
这就结束了我对 NLTK 库提供的 NLP 中搭配应用的演示和解释。我希望这个博客对你有帮助。请让我知道你是否使用了不同的方法来评分或提取搭配。
感谢您的阅读,我也写过其他与软件工程和数据科学相关的帖子。你可能想看看这里的。您也可以订阅我的博客,直接在收件箱中接收相关博客。
数据可视化中的颜色:少一些“如何”,多一些“为什么”
太多时候,我们把颜色作为一种工具来制作漂亮的图片,而它应该被用来告诉我们的观众。
如果我们在可视化中使用颜色遵循五个 w(和一个 H) ,我们在如何上花了太多时间,而在为什么上花的时间不够。当色彩应该被用来传达给我们的观众时,它却常常被看作是一种制作精美图片的工具。
举个例子,看看这个来自营销网站的“色彩情感指南”点击(当你在🧐).谷歌搜索“数据可视化中的色彩”时,这是最热门的结果之一
这里隐含的建议是我们应该使用颜色——无论何时何地——来捕捉某种形式的情感。不仅这种特定的分类相当奇怪(怪物能量饮料是和平的,维珍移动体现了“大胆的兴奋”,哈雷戴维森摩托车只是喊着“愉快的友好”)🤩),导致新手从业者认为,应该只是为了用色而用色。
无端使用颜色的例子比比皆是。
这些例子说明了我的论点:当我们应该问为什么我们使用颜色的时候,我们经常问我们如何在我们的可视化中使用颜色。
1)默认的软件设置,2)对漂亮的调色板的痴迷,以及 3)缺乏对仔细的颜色考虑的重视,这些因素的结合导致了我们在一些最流行的数据可视化中对颜色的草率使用。
我看到的最常见的错误之一是过度使用颜色。例如,在上面的图表中,很明显有太多的颜色,没有明显的原因
很多时候,那些创建可视化的人会争辩说他们必须在他们的图表中包含 14 种颜色,因为数据集有 14 个数据点!一些最流行的数据 viz 工具(如 Excel)的默认设置是将分类变量映射到颜色,这并没有帮助。
然而,实际情况是,如果您的图表中需要多种颜色,您可能会以不同的方式呈现数据。从 Datawrapper 中取出这个例子:
外卖?当你强调一切时,你最终会什么都不强调*。这就是为什么我们停止不加批判地问如何在图表中使用颜色是很重要的。*
如果不能告知查看者,数据可视化只不过是一幅美丽的图画。如果你的图表显示了 14 个不同的数据点,它们都被映射成不同的颜色,那么它在讲述什么样的故事呢?我非常喜欢苹果数据可视化从业者 Elijah Meeks 的这句话:
当你有如此多的维度时,不要试图找到不可能的 20 色调色板,停止使用颜色。这是难以区分的,令人困惑的,你只是把复杂性和决策权交给了你的读者。
这就是为什么颜色应该更少地使用和更周到地使用。颜色是我们视觉化的最重要的部分之一,然而它们目前的使用太多时候是不必要的和压倒性的。**
那么,你应该如何运用色彩呢?
颜色不是敌人。更确切地说,对颜色的滥用和误用才是。那么,如何才能正确使用色彩呢?这取决于你视觉化的目的,作为推论,也取决于颜色的目的。你应该问:我为什么要用颜色?
1)颜色区分
颜色的一个用途是引起人们对感兴趣的数据点的注意。这种颜色的使用属于解释性可视化的范畴,与其探索性的对应物相反。如果您已经探索、分析和探查了您的数据,现在您需要将这些见解传递给其他人(主管、客户或好奇的朋友)。向他们展示你所做的所有探索性工作是浪费时间,这就是为什么你的展示应该利用颜色来突出你的发现。
正如实践者安迪·基尔克所说,在这个展示阶段的可视化实践者应该让格雷成为他们最好的朋友**。这是因为没有色彩,而不是过度使用色彩,有助于描绘一幅图画和讲述一个故事。通过在可视化中使用灰色作为主要颜色,我们自动地将我们的观众的眼睛吸引到任何不是灰色的地方。这样,如果我们有兴趣讲述一个关于一个数据点的故事,我们可以很容易地做到。**
这是我不久前在 R 做的一个简单的例子:
可视化的目的不是向我们的观众展示德克萨斯州每个县的幼儿园疫苗接种率。取而代之的是强调最低比率——特里县。这种可视化利用每隔一个酒吧的灰色填充,立即将观众的目光吸引到特里县。因为我们只使用了两种颜色,所以我们还可以突出字幕中的文本,让观众看起来更加清晰。颜色——如果谨慎使用的话——会让我们的视觉效果更容易理解,信息量更大。
现在,想象一下,如果我用下面的方式可视化同样的数据:
或者更糟的是:
看了那些碍眼的东西,你是不是很庆幸我们在最初的剧情中有节制地使用了色彩?
或许你对 2016 年各县选举结果的概览感兴趣。尽管你可能会忍不住根据特朗普/克林顿的分歧给所有县编码,但这比有见地更美好。相反,如果我们专注于那些在 2012 年至 2016 年间从一个政党转向另一个政党的著名县,会怎么样?摘自基兰·希利的书数据可视化:
正如我们在这里看到的,更多的县从 2012 年的多数民主党转向 2016 年的多数共和党。因为我们只关注所有数据点的一小部分,我们也可以观察到趋势:大多数翻转的县都有少量的黑人人口。没有一个县的黑人人口超过 53%(我自己的注释):
我们还注意到,翻转方向可能与人口规模相关:几乎所有对数人口低于 10 万的翻转县都转向了共和党,而如果对数人口超过 10 万,则所有翻转县中更大比例的人转向了民主党。
颜色可以,也应该被用来关注你的视觉效果中你想让你的观众看到的关键部分。通过有策略地使用颜色,我们可以减少理解可视化所描绘的内容所需的认知负荷。 Kalyuga 等人发现颜色编码“改善了注意力分散效应,从而降低了感知难度。”其他研究人员报告称,当给实验参与者提供颜色编码时,认知负荷会降低。
过度使用颜色会产生相反的效果。在 2019 年的一篇论文中,研究人员发现“与任务无关的数字颜色信息只会在触发与基本代码单词的语义属性冲突的情况下阻碍学习过程。”这是什么意思?如果颜色编码与它所代表的对象相冲突,就会阻碍学习,削弱理解。你不必理解这一切意味着什么(我并不完全理解)。这一点简单来说明:我们应该关心颜色。颜色可能会令人困惑和复杂,这就是为什么它的使用应该是有意的和最小的。它应该被用来引起对我们图表中重要部分的注意。
2)色彩探索
颜色不一定要和普通的灰色形成对比。它还可以用作一种工具来展示映射到不同颜色的各种数据点。重要的是,这种用法应该节省。鉴于我们之前的例子,我们肯定不想要这样的情节(来自 Claus Wilke 的数据可视化基础 的第 19 章):
一个更合适的替代方案可能是这样的:
这样,观众仍然可以看到数据中的一般模式,但他们不必像对待查找表一样对待填充图例!最理想的情况是,这个图表应该具有一定的交互性,这样用户就可以将鼠标悬停在某个点上来查看其相应的数据。
在这样的例子中,我们是在探索而不是解释,我们把探索留给了我们的用户;他们可以看到他们想看的东西,我们给他们所需的信息。
颜色的另一个常见用途是显示梯度上的数据级数(例如,从低到高、从差到好、从冷到暖)。
这些例子在 choropleth 地图中最常见,其中给定州(或县或地区)的颜色阴影对应于感兴趣的值。作为一个例子,这里有一个我用 D3.js 创建的 choropleth 地图,它可视化了美国阿片类药物过量死亡的情况:
从地图上我们可以看出,“铁锈地带”各州遭受阿片类药物危机的程度比西方各州要大得多。Choropleth 地图利用颜色显示地区差异,并说明颜色阴影的力量,以代表给定变量的严重性或范围。
然而,在这种情况下,颜色也可能被误用。可以根据分类色标或彩虹色标绘制数据,这使得很难看到进展。Claus O. Wilke 的图表是一个好(坏)的例子:
这张图表很漂亮!当彩虹秤被用于媒体或其他地方时,可能是因为它们的创造者问“我如何才能用颜色来制作一幅漂亮的画?”但是这种非单调色标的使用意味着难以检测数据点之间差异的相对大小。举个例子,看看你回答这个问题需要多长时间:用上面的图例,这个颜色和这个颜色的百分比差是多少?(答案是~70%。)
2019 年,一组研究人员要求气候科学家评估描绘气候变化的地图,其中地图要么是彩虹状的(类似于上面的得克萨斯州地图),要么是单调的(如早先的阿片类地图)。研究人员发现,当这些地图用单调亮度标度而不是传统的彩虹标度编码时,对这些地图中量值差异的评估明显更准确。其他研究一致发现彩虹色既有害又受欢迎。所有这些都是为了说明:颜色很重要。
所以,颜色可以用于探索的目的。也就是说,颜色不一定要专门用于焦点,它可以用在除了灰色以外的其他颜色的图表中!但是探索性的颜色使用(和所有的颜色使用一样)需要谨慎。
结论
颜色很棘手。虽然它可以让你的情节更上一层楼,但也可能毁了它。区别?我们问的问题。我们是否在质疑你如何运用色彩;使用众多调色板中的哪一个,以及我们如何在变量间映射它们?这些都是重要的问题,但是它们必须以为什么我们首先使用颜色这个问题为前提。如果颜色不能起到告知、澄清或引导观众的作用,它还有什么作用呢?
https://twitter.com/CL_Rothschild
原载于 我的博客 。
使用 BodyPix 和 TensorFlow.js 的颜色流行效果
在 Unsplash 上发现的女孩照片
O 谷歌照片应用程序中我最喜欢的小功能之一是它的彩色流行效果。颜色流行(也称为颜色飞溅)效果使主体(通常是人)从图像的其余部分中突出出来。主体保持彩色,但背景变成灰度。在大多数情况下,这给人一种愉快的感觉。
彩色流行效果示例。原稿左侧,彩色弹出右侧
虽然这项功能非常好用,但 Google 相册只将这种效果应用于一些它认为容易检测到人类的图像。这限制了它的潜力,并且不允许用户手动选择图像来应用这种效果。这让我思考,有没有什么方法可以达到类似于的效果,但是用我选择的图片?
大多数应用程序不提供自动化解决方案。它需要用户手动在他们的图像上绘制这种效果,这既耗时又容易出错。我们能做得更好吗?像 Google 相册这样的智能东西?是啊!😉
了解了如何手动实现这种效果,我发现以下两个主要步骤:
- 在图像中的人物周围创建一个遮罩(也称为分段)。
- 使用遮罩保留人物的颜色,同时使背景灰度化。
从图像中分割出人
这是这个过程中最重要的一步。一个好的结果很大程度上取决于分割掩模创建得有多好。这一步需要一些机器学习,因为它已经被证明在这些情况下工作良好。
从零开始建立和训练一个机器学习模型会花费太多时间(不了解 ML 的人说😛),所以我搜索了一下有没有预先训练好的模型可以用。快速搜索将我带到了 BodyPix ,这是一个 Tensorflow.js 模型,用于人物分割和姿势检测。
[## Tensorflow.js 的 BodyPix 模型
这个包包含一个名为 BodyPix 的独立模型,以及一些演示,用于运行实时人和身体…
github.com](https://github.com/tensorflow/tfjs-models/tree/master/body-pix)
创作者提供的 BodyPix 现场演示。在这里尝试一下
正如你所看到的,它在检测图像中的一个人(包括多人)方面做得很好,并且在浏览器上运行相对较快。彩虹色的区域就是我们需要的分割图。🌈
让我们用 Tensorflow.js 和 BodyPix CDN 脚本建立一个基本的 HTML 文件。
<html>
<head>
<title>Color Pop using Tensorflow.js and BodyPix</title>
</head>
<body>
<!-- Canvas for input and output -->
<canvas></canvas>
<!-- Load TensorFlow.js -->
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@1.2"></script>
<!-- Load BodyPix -->
<script src="https://cdn.jsdelivr.net/npm/@tensorflow-models/body-pix@2.0"></script>
<!-- Color Pop code-->
<script src="colorpop.js"></script>
</body>
</html>
在画布中载入图像
在分割之前,理解如何在 JavaScript 中操作图像的像素数据是很重要的。一个简单的方法是使用 HTML Canvas。Canvas 使得读取和操作图像的像素数据变得很容易。还兼容 BodyPix,双赢!
function loadImage(src) {
const img = new Image();
const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');
// Load the image on canvas
img.addEventListener('load', () => {
// Set canvas width, height same as image
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0);
// TODO: Implement pop()
pop();
});
img.src = src;
}
正在加载 BodyPix 模型
BodyPix 的 README 很好地解释了如何使用该模型。加载模型的一个重要部分是您使用的architecture
。ResNet 更准确,但速度较慢,而 MobileNet 不太准确,但速度较快。在构建和测试这个效果时,我将使用 MobileNet。稍后我将切换到 ResNet 并比较结果。
注意:最好加载一次模型,并多次重复使用它进行分段,因为每次加载模型时都必须下载架构。在下面的例子中,每次对图像应用颜色弹出效果时,都会加载模型(以保持主要功能清晰)。
async function pop() {
// Loading the model
const net = await bodyPix.load({
architecture: 'MobileNetV1',
outputStride: 16,
multiplier: 0.75,
quantBytes: 2
});
}
执行分段👥
BodyPix 具有多种功能来分割图像。一些适合于身体部分分割,而另一些适合于单人/多人分割。所有这些都在他们的自述文件中有详细解释。segmentPerson()
将在这种情况下工作,因为它在一个单独的地图中为图像中的每个人创建一个分割地图。此外,它比其他方法相对更快。
segmentPerson()
接受一个画布元素作为输入图像,以及一些配置设置。internalResolution
设置指定分割前输入图像尺寸调整的因子。我将使用full
进行设置,因为我想要清晰的分割图。我强烈建议你阅读一下其他的设置,并尝试一下。
async function pop() {
// Loading the model
const net = await bodyPix.load({
architecture: 'MobileNetV1',
outputStride: 16,
multiplier: 0.75,
quantBytes: 2
});
// Segmentation
const canvas = document.querySelector('canvas');
const { data:map } = await net.segmentPerson(canvas, {
internalResolution: 'full',
});
}
分割后的结果就是一个物体(如下图)。结果对象的主要部分是data
,它是一个将分割图表示为一个数字数组的Uint8Array
。我已经用 ES6 析构把data
拿出来当map
。这将用于应用颜色流行到图像!
{
width: 640,
height: 480,
data: Uint8Array(307200) [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, …],
allPoses: [{"score": 0.4, "keypoints": […]}, …]
}
制作背景灰度
准备好分割数据后,下一部分涉及使用分割图实现颜色弹出,以使背景灰度化并保留图像中人物的颜色。为此,需要对图像进行像素级的操作,这也是 canvas 元素大放异彩的地方。getImageData()
函数返回ImageData
,其中包含 RGBA 格式的每个像素的颜色。在下面的代码中,我使用了析构来提取有用的data
作为imgData
async function pop() {
// ... previous code
// Extracting image data
const ctx = canvas.getContext('2d');
const { data:imgData } = ctx.getImageData(0, 0, canvas.width, canvas.height);
}
应用效果
所有的材料都准备好了,这就是色彩流行魔法发生的地方!让我们从创建新的图像数据开始。createImageData()
创建一个新的图像数据,我们对实际图像数据的所有修改都将存储在这里。
接下来,我们遍历地图中的像素,其中每个元素都是 1 或 0。
- 1 表示在该像素处检测到人。
- 0 表示在该像素处没有检测到人。
为了提高代码的可读性,我使用析构将颜色数据提取到r
g
b
a
变量中。然后使用 RGB 值,使用亮度方法计算适当的灰色。有各种方法来计算灰度值。这篇文章有一个很好的列表,列出了其中的一些转换公式。
最后,基于分割图值(0 或 1 ),可以将灰度或实际的 RGBA 颜色分配给新的图像数据。请注意,RGB 中对应的灰色是通过为所有三个通道分配相同的灰度值来计算的。
处理完每个像素后,使用putImageData()
功能在画布上绘制新的图像数据。
async function pop() {
// ... previous code
// Creating new image data
const newImg = ctx.createImageData(canvas.width, canvas.height);
const newImgData = newImg.data;
// Apply the effect
for(let i=0; i<map.length; i++) {
// Extract data into r, g, b, a from imgData
const [r, g, b, a] = [
imgData[i*4],
imgData[i*4+1],
imgData[i*4+2],
imgData[i*4+3]
];
// Calculate the gray color
const gray = ((0.3 * r) + (0.59 * g) + (0.11 * b));
// Set new RGB color to gray if map value is not 1
// for the current pixel in iteration
[
newImgData[i*4],
newImgData[i*4+1],
newImgData[i*4+2],
newImgData[i*4+3]
] = !map[i] ? [gray, gray, gray, 255] : [r, g, b, a];
}
// Draw the new image back to canvas
ctx.putImageData(newImg, 0, 0);
}
可以看到具有彩色 pop 效果的最终图像应用于原始图像。耶!🎉
探索其他架构和设置
我对 ResNet 和 MobileNet 架构进行了一些测试。在所有示例图像中,图像的一个维度(宽度或高度)的大小为 1080px。请注意,分割的内部分辨率被设置为full
(分割期间图像不缩小)。
对于我的测试,我在加载 BodyPix 模型时使用了以下设置。
// MobileNet architecture
const net = await bodyPix.load({
architecture: 'MobileNetV1',
outputStride: 16,
quantBytes: 4,
});
// ResNet architecture
const net = await bodyPix.load({
architecture: 'ResNet50',
outputStride: 16,
quantBytes: 2,
});
测试 1 —单人
这里两个模特都发现了照片中的女孩。与 MobileNet 相比,ResNet 更好地分割了该图像。
从左至右:原始样本、MobileNet、ResNet
测试 2 —多人
这是一个有点棘手的问题,因为它有许多人在图像周围摆着不同的姿势和道具。ResNet 再次准确地分割了图像中的所有人。MobileNet 也很接近,但错过了一些边缘。
两者都错误地分割了坐垫的一部分。
从左至右:原始样本、MobileNet、ResNet
测试 3 —面朝后
另一个棘手的问题是,照片中的女孩面朝后。老实说,我期待着对图像中女孩的不准确检测,但 ResNet 和 MobileNet 在这方面都没有问题。由于 dupatta,两种架构中的分段都不准确。
从左至右:原始样本、MobileNet、ResNet
测试的结论是📋
从测试中可以明显看出,ResNet 比 MobileNet 执行更好的分段,但代价是更高的时间。两者都很好地检测了同一幅图像中的多人,但有时由于服装的原因无法准确分割。由于 BodyPix 打算在浏览器(或 Node.js) 中与 Tensorflow.js 一起运行,所以当使用正确的设置时,它的执行速度令人印象深刻。
这就是我如何能够创造受谷歌照片启发的彩色流行效果。总而言之,BodyPix 是一个很棒的人物细分模型。我很想在我未来的一些项目中使用这个和 Tensorflow.js。你可以在这里找到源代码和现场工作版本:https://glitch.com/~color-pop-effect
我已经为这个颜色的流行效果创建了一个 Firebase 云函数。它在 Node 上使用 Tensorflow.js,这使得它比在用户的浏览器上运行要快得多。您可以检查颜色弹出🌈在这里投影。我迫不及待地想看到你的❤️和对它的贡献!
使用克雷奥拉颜色为图像着色(Python)
我如何使用 cython 和 OpenCV 编写了一个 python 代码来将图像转换为好像它们是使用 Crayola 颜色着色的。
作者图片
创建一个颜色数组。首先,我为一个 120 色蜡笔蜡笔盒选择相应的 RGB 值,并将它们复制到一个列表中。
colorsFile = open("colors.txt","r")
colors = []for line in colorsFile.readlines():
colorset = line.strip().split(" ")
rgbFormat = [int(x) for x in colorset[2].split(",")]
colors.append(rgbFormat)
其次,我从挑选一张图片并把它调整到较小的尺寸开始。这主要是为了减少运行时间。此外,我注意到较小的图片似乎更好地带出预期的效果。
import cv2
import os
for imageFile in os.listdir("TestImages"):
img_rgb = cv2.imread("TestImages/" + imageFile)
img_rgb = cv2.resize(img_rgb, (0, 0), fx = 0.7, fy = 0.7)
原始图像(作者)
接下来,我运行了一个双边滤波器,它平滑了图像,但保留了边缘。边缘是很重要的,因为大多数蜡笔画都有强烈的、非常真实的、轮廓分明的边缘。OpenCV 中的双边滤镜由两个主要因素控制,sigmaColor(值越高,混合的远距离颜色越多)和 sigmaSpace(值越高,混合的远距离像素越多)。
#alpha = 6 Repeatedly running the filter with small values brought better results than a single run with a larger filter
for _ in range(alpha):
img_rgb_smooth = cv2.bilateralFilter(img_rgb, d=9, sigmaColor=9, sigmaSpace=7)
运行双边过滤器后
运行双边过滤器后,我识别了图像中的边缘。首先,我将图像转换成灰度。主要是因为我们将使用自适应阈值方法来识别边缘,这种方法只适用于灰度。我们基本上是在制作一个二进制图像,其中每个像素不是黑就是白。为创建这个二进制图像设置一个单一的阈值会遇到麻烦,比如图像上的光照不均匀。因此,最好是使用局部阈值,这将带来更好的结果。根据图像调整块大小会产生更好的结果。
img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_RGB2GRAY)
img_edge = cv2.adaptiveThreshold(img_gray, 255,
cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
cv2.THRESH_BINARY,
blockSize=11,
C=2)
边缘提取
然后,我把固体边缘放回我们的图像上。我们可以使用逐位 and 算术运算符,对带有边缘的图像和 RGB 图像进行逐像素运算。
img_edge = cv2.cvtColor(img_edge, cv2.COLOR_GRAY2RGB)
img_rgb_edges = cv2.bitwise_and(img_rgb, img_edge)
叠加边缘
然后我用调色板中最接近的颜色替换了每个像素的颜色。我花了很长时间才把它做好,这很容易成为本模块的核心步骤。我首先使用了当前颜色和调色板中每种颜色之间的纯欧几里德距离。输出不像我希望的那样真实。它通常会显示出与预期颜色的显著偏差。使用这里提供的堆栈溢出解决方案缓解了这个问题,它用我们感知颜色的灵敏度来增强公式。其他的建议是基于色调距离,然而,我觉得它并没有比欧几里得更好的表现。所以最初,我用 python 写了一个 for 循环来操作每个像素。
for x in range(0,width):
for y in range(0,height):
channels_xy = img_rgb_edges[y,x]
colorSwapping(x,y,channels_xy)def colorSwapping(x,y,rgbArray):
r1,g1,b1 = rgbArray
shortestDistance = None
sol = None
for color,value in colors.items():
r2,g2,b2 = value
d = pow(((r2-r1)*0.30),2) + pow(((g2-g1)*0.59),2) + pow(((b2-b1)*0.11),2)
if(shortestDistance == None or d < shortestDistance):
shortestDistance = d
sol = value
img_rgb_edges[y,x] = sol
然而这真的很慢,然后我尝试使用线程。那也没多大帮助。Python 有一个叫做的全局解释器锁,它不允许在一个数组上并发运行。经过进一步的搜索,我发现 cython 可以帮助大大加快这个过程。在我的例子中,将像素操作逻辑转移到 cython 有助于将速度提高 20 倍。
import cythoncode
img_rgb_edges = cythoncode.coloringImage(img_rgb_edges, colors)
cv2.imwrite("Output/"+imageFile ,img_rgb_edges)
cython 功能,
#cythoncode.pyx
cpdef coloringImage(img,colors):
cdef int height = img.shape[0]
cdef int width = img.shape[1]
for x in range(0,width):
for y in range(0,height):
pixelSwap(img,x,y, colors)
return img
cpdef pixelSwap(img,x,y,colors):
channels_xy = img[y,x]
cdef int shortestDistance = -1
sol = []
cdef length = len(colors)
for index in range(0,length):
d = distanceCalculator(channels_xy,colors[index])
if(shortestDistance == -1 or d < shortestDistance):
shortestDistance = d
sol = colors[index]
img[y,x] = solcpdef int distanceCalculator(color1, color2):
cdef int r2 = color1[0]
cdef int g2 = color1[1]
cdef int b2 = color1[2]
cdef int r1 = color2[0]
cdef int g1 = color2[1]
cdef int b1 = color2[2]
return int(((r2-r1)*0.30)**2 + ((g2-g1)*0.59)**2 + ((b2-b1)*0.11)**2)
Cython 就像 Python 的一个超集,具有来自 c 的函数。由于我对 cython 相对陌生,所以我只将简单的组件(如距离计算器)转移到 cython,这纯粹是计算。将 python 图像对象转换成数组可能有助于进一步提高速度。
Setup.py 构建模块,
from setuptools import setup
from Cython.Build import cythonize
setup(
name='Cython Pixel Manipualtion Code',
ext_modules=cythonize("cythoncode.pyx"),
zip_safe=False,
)
切换到最接近的克雷奥拉颜色
如你所见,最合适的颜色并不总是在图像中挑选。但是,仍然产生了相当好的卡通化效果。
这是我运行代码的更多图片,
在 Pixel 3 上拍摄多张照片,然后使用代码进行转换
将印度染成红色、橙色和绿色:Covid19 Chloropleth 地图
基于 Bokeh 的绘图/地图,显示印度不同地区的新型冠状病毒的实时数据和爆发严重程度
从 Freepik 创建的图像,请参见最后的致谢
注 : 走向数据科学 是以数据科学和机器学习研究为主的中型刊物。我们不是健康专家或流行病学家,本文的观点不应被解释为专业建议。想了解更多关于疫情冠状病毒的信息,可以点击 这里 。
新冠肺炎或新型冠状病毒已使世界各国政府强制全国封锁,以对抗这种致命的病毒。这种病毒现在已经感染了全球 400 多万人,并导致 30 万人死亡。
印度在 5 月 4 日实施了为期两周的第三次封锁,可能正在计划第四次封锁。一些人认为这是世界上最大的封锁,有近 13 亿人被困在家中。印度开始根据疾病传播的严重程度,将 733 个地区用颜色划分为红色、橙色和绿色区域。
红色:案件量最高的区,占各州案件量的 80%以上,或者加倍率少于 4 天的区。
绿色:一个超过 28 天没有报告任何病例的地区。
橙色:既不属于红色也不属于绿色的地区
政府试图利用国家的联邦结构来绘制和隔离疫情,建立限制级别,有效地分配资源,并追究责任。
作为一个呆在禁闭室内的极客,我试图用 Python 来绘制这些区域,这篇博客就是关于这个的。
目标:这个博客展示了为印度各区创建一个 choropleth 地图的步骤,并用它们的颜色标记出来。该地图是一种交互式绘图,它还显示每个地区受 Covid19 影响的人数。
代码已经内置在 Jupyter 笔记本中,可以在我的 Github repo 上找到:[https://github.com/yatharthaggarwal/CovidIndia]。我一直在为基于 Python 的项目使用 Anaconda 工具包,并向其他人推荐同样的工具包。
套餐:
- geo pandas**😗*是一个帮助用户处理地理空间数据的开源包。我们将关注的一个依赖项是 shapely ,GeoPandas 依赖于它来执行几何运算。在我们的例子中,印度每个地区的形状将通过 shapely 包编码为多边形或多多边形。然后通过 GeoPandas 来理解地理空间数据。
- 散景 : 它可以让我们创作出更复杂的剧情。Bokeh 是一个多功能的开源软件包,旨在帮助用户创建漂亮的交互式可视化效果。
导入数据集
1。新冠肺炎患者数据
首先,我们需要在地区级别加载 COVID 19 数据。印度政府/邦政府没有按地区提供数据。因此,我们需要依靠基于众包的门户网站,比如 https://www.covid19india.org/。
甚至他们提供的数据也有很大一部分是不正确的。他们在“未知”部分推送了大量数据。但是,我们将选择提到地区的行。下图是加载数据集的代码片段,我们感兴趣的是已确认、活动、已恢复和已死亡的列。确诊病例是另外三个的总和。
districtdata = pd.read_csv ('[https://api.covid19india.org/csv/latest/district_wise.csv'](https://api.covid19india.org/csv/latest/district_wise.csv'))
districtdata.head()
2。印度地区形状文件
为了创建一个地图,你需要一个形状文件。shp)。该文件告诉 Geopandas 我们正在绘制什么形状。在我们的例子中,我们需要一个概述每个地区的文件。我们使用一个 geometry 列,以便 Geopandas 包知道在哪里寻找每个州的形状信息。
一个优秀的更新 shapefile 可以在这里找到:https://hub . ArcGIS . com/datasets/esriindia 1::India-districts-boundary。人们可以从这里下载并使用它。虽然有很多拼写错误,我已经在数据清理部分纠正了。请参见下面的代码片段:
df1 = gpd.read_file('India_Districts/c44c9b96-f570-4ee3-97f1-ebad64efa4c2202044-1-1rb4x6s.8xx6.shp')
df1.head()
我们可以利用绘图功能来查看 shapefile 中的内容。如果有人能找到任何官方文件,请做评论。这张地图不包含 2020 年的行政区,但出来的地图很漂亮。
# showing the India map based on the shapefile... See the districts boundary
df1.plot(figsize = (8,8))
shapefile 中的印度地区地图
3。逐区分区数据
该数据已由卫生和家庭福利部公布。我已经直接从 https://www.kaggle.com/xordux/india-corona-severity-zones下载到工作目录下了。请参见下面的代码片段:
zones = pd.read_csv('Zones in india.csv')
zones.head()
数据清理
数据清理部分是任何基于数据的项目非常必要的一部分,因为它提供了纠正/删除数据值、处理 NaN 值和格式化整个数据集的方法。我没有把代码片段放在这里,因为它只是纠正了大量的拼写错误。直接检查存储库中的代码部分,这里再次链接了。
数据预处理
用上面显示的所有数据创建一个公共数据框架。
在 df1 (shapefile)中,我们根据地区和州合并了 Covid19 患者的数据,然后类似地合并了 Zones 数据帧。一些不必要的栏目也被删除。在印度,不同的邦经常保留一个相似的区名,因此在’ merge’ 函数中我们需要同时检查[ *District ‘,’ States’]。*参见代码片段,其中包括几何图形、区域和患者数据以及区名和州名:
newdf = df1.merge(districtdata[['State', 'District', 'Confirmed', 'Active', 'Recovered', 'Deceased']], on = ['District', 'State'])newdf = newdf.merge(zones[['State', 'District', 'Zone']], on = ['District', 'State'])newdf = newdf.drop(columns = ['statecode', 'state_ut', 'distcode', 'countrynam'])
newdf.head()
现在,数据已经转换为适当的格式,我们可以按照以下步骤绘制地区的 choropleth 地图:
- 创建体形对象
- 将面片渲染器添加到图形中
- 创建显示患者数据的悬停工具
- 展示图
导入散景库并创建数据类型格式
import json
from bokeh.io import show
from bokeh.io import output_file, save
from bokeh.models import (CDSView, ColorBar, ColumnDataSource,
CustomJS, CustomJSFilter,
GeoJSONDataSource, HoverTool,
CategoricalColorMapper, Slider)
from bokeh.layouts import column, row, widgetbox
from bokeh.io import output_notebook
from bokeh.plotting import figure
散景使用 GeoJSON 格式,用 JSON 表示地理要素。GeoJSON 将点、线和多边形(在散景中称为面片)描述为要素的集合。因此,我们将合并后的文件转换为 GeoJSON 格式。
此外,还创建了一个分类颜色映射器,用于将红色区域映射为红色,绿色和橙色区域也是如此。
a)用我们的初始数据创建 GeoJSONDataSource 对象
geosource = GeoJSONDataSource(geojson = newdf.to_json())
b)定义要使用的调色板并映射到区域的分类值
palette = ['red', 'orange', 'green']
color_mapper = CategoricalColorMapper(palette = palette, factors = ['Red', 'Orange', 'Green'])
Choropleth 地图
以下代码创建 figure 对象(包括缩放和平移工具),添加渲染的修补程序(包括带列区域的 geosource 和 mapping 颜色映射器),并创建悬停工具以显示特定地区的已确认、活动、已恢复和已死亡病例。
最后,以“HTML”格式保存绘图。现在经过上述步骤:
- 在创建一个人物对象时,我们可以为情节设置标题、高度、宽度和交互工具。
p = figure(title = 'Red, Green and Orange Distric of Covid19: 19 May 2019',
plot_height = 700 ,
plot_width = 650,
toolbar_location = 'right',
tools = "pan, wheel_zoom, box_zoom, reset")
2.补丁渲染器是我们输入数据源和颜色映射器的主要地方。
states = p.patches('xs','ys', source = geosource,
fill_color = {'field' :'Zone',
'transform' : color_mapper},
line_color = 'black',
line_width = 0.25,
fill_alpha = 1)
3.悬停工具允许我们将想要显示的数据放入绘图中。
p.add_tools(HoverTool(renderers = [states],
tooltips = [('District','[@District](http://twitter.com/District)'),
('State','[@State](http://twitter.com/State)'),
('Zone','[@Zone](http://twitter.com/Zone)'),
('Confirmed cases','[@Confirmed](http://twitter.com/Confirmed)'),
('Active cases','[@Active](http://twitter.com/Active)'),
('Recovered cases','[@Recovered](http://twitter.com/Recovered)'),
('Deaths','[@Deceased](http://twitter.com/Deceased)')
]))
4.最后是 HTML 格式的情节。这是一个巨大的 150 兆字节。我需要看看我如何能减少尺寸。保存功能将它保存在当前目录中。
output_file('plot.html', mode='inline')
save(p)
show(p, notebook_handle = True)
显示印度所有地区的 Choropleth 地图,工具位于右侧
恭喜你。!我们已经成功地创建了我们的 Choropleth 地图。人们可以在任何浏览器中简单地打开 plot.html 文件来查看其内容。或者只执行下面的命令,在新的选项卡中查看图形。
我制作了一个展示互动地图的小视频。
https://www.youtube.com/watch?v=JuF4cNeWKzc
Choropleth 地图工作
在这里可以直接看到代码。
如果你对我们如何进一步增强情节或代码有任何意见或建议,我很乐意听到!
跟我连线:noobdatascientist@gmail.com
感谢阅读!
第一张图片(也充当缩略图)是使用 Freepik 的: 印度地图 , 日冕感染
用生成对立网络给照片着色
用深度学习把黑白照片带到现在。
自从我开始学习数据科学和机器学习以来,一直有一种算法不断吸引我的注意力:生成敌对网络(GANs)。以至于我写的第二篇博客详细介绍了这些模型是如何工作的以及它们能创造什么。当我第一次了解它们时,大多数文章(包括我自己的)只报道了它们如何能够接受随机噪声向量并产生逼真的照片。
在我写完那篇博客文章后不久,我偶然发现了周而复始的(朱等),它允许图像到图像的翻译。这意味着我们能够传入一个图像作为输入,并接收一个修改过的副本作为输出。这包括绘制梵高等艺术家的风格,将照片从夏天变成冬天,或将斑马变成马。
来源:朱俊彦
在我写了前面提到的博文之后,我觉得我对 GANs、它们的工作方式以及它们的变体已经足够满意了,于是我决定创建自己的 GANs。然而,有这么多的应用程序可供选择,我很难决定我想创造什么。一天晚上,当我还在考虑不同的选择时,我看了彼得·杰克逊的他们不会变老 ,这是一部通过图像重建和重新着色创作的一战纪录片。这一点,结合我对迁移学习的了解,启发我创建了一个可以将黑白照片转换为彩色的模型。
(对于那些不熟悉生成性敌对网络的人,我建议在继续之前阅读我的第一篇博客
创建 GAN 的步骤:
- 检索数据
- 预处理图像
- 创造建筑
- 训练、监控和调整参数
获取数据:
在我开始编码或规划我的模型架构之前,我需要找到一个数据集来使用。我了解到,当谈到图像翻译时,GANs 在理解照片的纹理和对称性方面比他们在识别复杂的几何图形方面更有效率。这意味着,举例来说,他们能够比一个人或一只狗更容易地创作风景照片。这促使我收集了 2 个不同的数据集:
- 麻省理工学院计算视觉库数据集:只使用了海岸照片,因为它们包含简单的风景。
- **MPII 人体姿态数据集:**进行各种活动的人的图像。
我第一次尝试从麻省理工学院的数据集开始,因为这些图像更容易建模,这使我可以专注于创建我的第一个架构和所有必要的预处理,然后再处理更大的 MPII 数据集。一旦我获得了所有的数据,我终于可以开始编码了。
下面是 Github 供参考。
图像预处理:
由于 gan 的计算量非常大,因此限制图像的大小非常重要;我选择了 256x256 的图片尺寸。麻省理工学院的海岸照片已经是这个尺寸了,所以不需要对数据集中的照片做任何处理。另一方面,MPII 数据集图像的大小不一,大于 256x256,因此需要调整大小,这可以使用 Numpy 轻松完成。
我的第一个想法是将每张图像简单地转换为灰度,并将其传递到生成器中,使用标准 RGB(红绿蓝)颜色通道(其正常值为 0-255)创建全彩色图像。我很快意识到这种方法非常低效,为了转换我的图像,我需要使用一些不同的方法,而不是一个简单的解决方案。
资料来源:Photoscreenprint.com
在我的研究过程中,我仔细检查了研究人员试图给黑白照片上色的例子,并注意到其中的一种模式;许多人将图像从 RGB 颜色值转换为 LAB 颜色值。与 RGB 不同,RGB 合并红色、蓝色和绿色值来创建彩色图像,LAB 由一个光敏通道和两个颜色通道组成。L 通道包含照片的感光度信息,相当于黑白版本。A 和 B 是颜色通道,其中 A 控制绿-红权衡,B 控制蓝-黄权衡。Python 的 Scikit-Image 库提供了一个很好的方法,允许我们轻松地将 RGB 照片转换到实验室。
我最初的方法是尝试创建所有三个颜色通道,现在我决定将 L 通道作为输入通过生成器,并输出新的 A 和 B 颜色通道。最后,一旦我将图像转换到 LAB,我需要进行归一化,因为它们的像素值对于我的模型来说是一个非常低效的范围。我决定将像素值从-1 缩放到 1,这样我可以很容易地用 tanh 激活来复制它。
创建架构:
为了创建模型,我使用了 Keras,这是 Python 的深度学习库。首先,我分别创建了生成器和鉴别器;然后我把两者连接起来,这样生成器就可以根据它欺骗另一个模型的程度来学习。
发电机
资料来源:i2tutorials.com
发生器可以分为两部分:编码器和 T2 解码器。原始图像,在我的情况下是 L 通道,通过卷积层缩小,直到达到所需的特征图大小。再次放大图像之前的这组特征图被称为图像的潜在空间表示。从这里,我执行所谓的转置卷积或反卷积,这允许我对我的图像大小进行上采样;这里的动画链接展示了一个很好的例子,展示了这是如何工作的。我重复这个过程,直到我回到原来的大小,然后输出新的图像,A 和 B 通道。
我的生成器的编码器由四个卷积层组成,步长为 2,这样我可以缩小图像。我从 64 个特征地图开始,并将每一层的地图数量增加一倍,以便在我到达潜在空间表示(即网络的中间)时,我最多有 512 个地图,每个地图的大小为 16x16。然后,每层的输出经过批量标准化,最后是泄漏 ReLU 激活。解码器几乎是一个反向拷贝,因为它有四个去卷积层,其输出经过批量归一化和 ReLU 激活。最后一层是具有两个输出通道(A 和 B 颜色通道)的单步卷积,具有 tanh 激活,以匹配我们之前在预处理图像时设置的-1 到 1 比例。
鉴别器
鉴别器是一个比其对应的生成器简单得多的模型,因为它是一个标准的卷积神经网络(CNN),用于预测 AB 通道是真是假。它有四个 2 步卷积层,每一层都包括丢失、泄漏 relu 激活,以及除第一层之外的批量归一化。像其他 CNN 一样,我把最后一层弄平,然后通过一个 s 形管来预测图像是真是假。
初始化模型
两个模型都将使用二进制交叉熵作为损失函数和 Adam 优化器。与我读到的一切相反,我需要对发电机使用更高的学习率,以防止它被压制。首先,初始化鉴频器,然后我创建并链接发电机的损耗到鉴频器的输出。
训练、监控和调整参数:
在完成了上面解释的过程之后,我准备好训练模型了,或者说我是这样认为的。当我在笔记本电脑上运行这个模型时,我收到了“内核死亡”的消息。对我的笔记本电脑来说,内存和计算需求太大了。在 CPU 上训练一个 GAN 也可能需要几天时间,这让我明白了两件事:我需要一台强大的计算机/实例和一个 GPU。为此,我去 AWS SageMaker 租了一个 GPU 实例,它为我提供了足够多的功能。
我做的最后一个调整是将我的历元大小限制为只有 320 个,而不是训练几百个历元,而是训练几千个。我用半个时期的真实图像和半个时期的虚假图像来训练鉴别器。最后,生成器生成一个完整时期的图像,并将其传递给鉴别器,如果图像被标记为假的,则生成器会受到惩罚。GANs 很难训练,因为与大多数其他深度学习算法不同,它不会最小化或最大化任何损失函数。相反,我寻找一个平衡点,或者说鞍点,在这个点上,两个网络保持竞争,并继续相互依赖。从下面的损失图可以看出,这是一个非常零星的训练周期。
可能需要多次尝试才能使模型稳定,但一旦你这样做了,耐心是很重要的,因为在 GPU 实例中可能需要 6-12 个小时来训练模型。帮助我控制长时间训练和模糊指标的两件事是经常打印图像和以一半的频率保存模型。为了查看照片,只需按比例缩小到原始像素值并转换为 RGB。
结果
左:原始|右:重新着色
左:原始|右:重新着色
正如你从上面的图片中看到的,模型有时会偏向某些颜色,特别是最后一张图片,倾向于绿色和红色以及一些渗色。
后续步骤
这个项目肯定仍在进行中,我的下一步是建立一个自我关注层,以帮助模型更好地理解照片中的几何图形。一旦我建立了新的模型,我的目标是在 Imagenet 数据集上训练它,这样它就可以推广到更多的照片,并创建一个 web 应用程序,允许任何人立即给他们的照片着色。
用深度学习给视频上色
零本地设置/解密/ Colab 笔记本
一个用户友好的版本,可以将黑白视频转换成彩色视频,并免费自动导出到 Google Drive。
“Haal Hai Jana ab Ka”宝莱坞歌曲— 1958 年和“美丽的黑白好莱坞电影镜头集”
按照我的目标轻松做事,我想尝试去锁定一遍又一遍地将 B & W 视频内容转换成音频,而不必因为 Google Colab 上的免费资源会话超时而改变代码或丢失进度。
以下是步骤——大约 10 次点击,让你做到这一点!请记住,我只测试了免费硬件资源的短视频(5 分钟)。
打开存储库中的 Colab 笔记本链接。这篇文章也可能让你熟悉 Colab 的力量,为你下一篇激动人心的人工智能论文做准备。
首先,确保通过登录分配一个空闲的 GPU 资源。点击运行时菜单上方的> 改变运行时类型>GPU>保存然后点击右上方的连接。
第一步
登录后,再次点击连接,然后将网址更新为你从 YouTube 视频的分享图标上获得的视频链接。默认网址是卢米埃尔兄弟的电影 101 历史 1895 中标志性的“火车到达”片段。
您可以选择修改默认的 google drive 导出目录路径。
点击左边的运行图标!每次打开这个页面(会话),都会要求你授权 google drive 挂载到你当前的会话。
第二步
复制粘贴授权码,点击进入。点击 Setup t ext 部分将其聚焦,并点击页面顶部 Runtime 菜单中的 Run After 选项。
第三步
坐着别动,去喝杯咖啡!只要确保你的机器正在运行,浏览器保持活跃。
处理需要一段时间,但是成功转换后,源和结果视频将会上传到您选择的路径下的 google drive。
同样,以上是最简单的转换方法,不需要花里胡哨。更多定制,请看一下原装笔记本。
在未来的帖子中,我们将尝试增加视频的每秒帧数以获得更平滑的剪辑,甚至可能将视频升级到更高的分辨率,以满足当代显示设备的要求。
如果你想尝试更多从头到尾的快速 AI 实验,请访问我的上一篇帖子: 训练神经网络对图像进行分类&在 10 分钟内优化 CPU 推理
人工智能给黑白照片上色。
利用 Fastai 的生成性对抗网络(GAN)使黑白照片变得丰富多彩
(左)百老汇在纽约州萨拉托加温泉市的美国酒店(https://www.loc.gov/pictures/item/2016818127/)(右)彩色照片
介绍
当我看到历史黑白照片时,我总是想知道真实的颜色是什么,摄影师在拍照时看到了什么。
发现 B&W 照片的确切颜色并不容易,但根据经验和想象给照片上色是可能的。这可以通过调查照片中物体的可能颜色来实现,例如,衣服、建筑物、树木、汽车等的颜色。,并用 Photoshop 等软件手工上色。
另一种方法是通过提供大量彩色照片来训练计算机理解不同物体的颜色,然后要求计算机通过识别检测到的物体的似乎合理的颜色来着色。由于深度学习的发展,它可以通过使用生成对抗网络(GAN)来完成。
生成对抗网络
生成性对抗网络的思想非常简单,它包含两个神经网络,生成器和鉴别器。生成器的工作是根据黑白照片预测颜色,然后生成彩色照片。然后,鉴别者的工作是判断生成的照片与真实照片相比是否足够真实。
如果鉴别器能轻易分辨出照片是生成的,说明生成器不够好,生成器需要更多的训练。当发生器正在改进并且鉴别器不能再分辨出差别时,鉴别器将被更多地训练以分辨出差别。
在这项工作中,我以杰森·安蒂克的 deol dify(【https://github.com/jantic/DeOldify】)为参考,用 fastai 训练了一个 GAN。
资料组
我使用 ImageNet 作为我的训练数据集。然而,由于计算限制(Colab 上 12 小时的运行时间限制),使用所有的图像并不容易,所以我最终只使用了其中的 5000 张图像。
训练数据集的一部分
制作黑白照片
首先,我需要把彩色图像变成黑白的来进行训练。我还添加了一点噪点,给这些图片一些旧照片的感觉。
(左)ImageNet 中的一幅图像(右)带噪声的黑白图像。
预训练发电机
现在我已经准备好了数据集,可以开始训练了。我为生成器创建了 U-Net 学习器,并在 GAN 之前对其进行了预训练。fastai 库可以轻松完成。
我从小尺寸(64 像素)开始,所以我可以用更大的批量更快地训练它。
用 64 像素图像进行生成器预训练。
然后我把尺寸加大到 128 和 256。随着时代的增加,我开始看到一些好的结果。
使用 128 像素图像进行生成器预训练。
使用 256 像素图像进行生成器预训练。
训练前鉴别器
在生成器预训练之后,我使用生成器从黑白数据集生成彩色照片。然后我用这些生成的照片和原始照片来训练鉴别器。
在 10 个时期之后,鉴别器能够以 85%的准确度辨别图像是否被生成。
开始
现在是把它们放在一起的时候了。Fastai 为创建 GAN 提供了一个非常有用的工具,结合了预先训练的生成器和鉴别器。经过 50 个时代的训练,我得到了初步的结果。
甘在训练的时候。
结果
我下载了一些黑白照片,这些照片是模特以前没有见过的,用来测试。以下是一些结果。
这个模型能够给树和草上色。它也做了很好的着色人类的皮肤。
(左)纳特。我是。芭蕾舞,8/20/24(https://www.loc.gov/pictures/item/2016838246/)(右)彩色照片
(左)9 月 24 日,罗莎莉·琼斯开始拉福莱特的竞选之旅(【https://www.loc.gov/pictures/resource/cph.3c15477/? 】)co=ggbain )(右)彩色照片
(左)拳击(【https://www.loc.gov/item/2016878085/】)(右)彩照
(左)裁判看着纽约扬基队球员在与华盛顿(https://www.loc.gov/pictures/resource/cph.3c35415/)的棒球比赛中滑入垒位
(左)土路上的乡村商店。周日下午。注意右边的煤油泵和左边的汽油泵。粗糙、未加工的木柱被用来支撑门廊屋顶。黑人正坐在门廊上。店主的兄弟站在门口。北卡罗来纳州戈登顿(https://www.loc.gov/pictures/resource/fsa.8b33922/)(右)彩色
(左)路易斯·阿姆斯特朗的肖像,水族馆,纽约,加利福尼亚州。1946 年 7 月(https://www.loc.gov/item/gottlieb.00201/)(右)彩色照片
(左)马里兰州安蒂特姆,林肯总统和乔治·b·麦克莱伦将军在将军的帐篷里(https://www.loc.gov/pictures/resource/cwpb.04351/)(右)彩色照片
有些颜色不是很真实,但仍然很有说服力。
(左)费城运动家队的宾·米勒在一场棒球比赛中被华盛顿国民队的捕手“泥巴”鲁埃尔在本垒板标记出局(【https://www.loc.gov/pictures/item/2005685880/】)(右)彩色照片
(左)购买复活节鲜花,联合广场。纽约州(右)彩色照片
请注意,这是仅由 5000 幅图像训练的,并没有很多历元,它可能会通过更密集的训练得到进一步改善。
网络应用
使用 Streamlit 可以快速创建 web 应用程序原型。它不需要大量的 HTML 和 Java 技能,所以它对像我这样的 web dummy 真的很有帮助。
Streamlit 构建的 Web 应用程序
[## 生成性对抗网络:构建一个用 Streamlit 给 B&W 照片着色的 web 应用程序
使用 Streamlit 快速将生成式对抗网络模型转换为 web 应用程序,并部署到 Heroku
towardsdatascience.com](/generative-adversarial-network-build-a-web-application-which-colorizes-b-w-photos-with-streamlit-5118bf0857af)
感谢阅读,欢迎提出建议和反馈。
更多示例:
草地网球选手可能在波斯顿地区(https://www.loc.gov/resource/ppmsca.53290/)
茱莉亚·欧贝尔,国家妇女党总部的信使(https://www.loc.gov/resource/cph.3d01840/)
周日骑自行车的人在华盛顿特区的东波托马克公园(https://www.loc.gov/resource/fsa.8c34879/)
弗朗西丝·班杰明·庄士敦,装扮成假胡子男人的全身自画像,骑着自行车,面朝左(https://www.loc.gov/resource/ppmsc.04884/)
一名男子和一名男孩骑着自行车,一只狗骑在男子的肩膀上,靠近 https://www.loc.gov/resource/ppmsca.38847/的美国国会大厦倒影池
托尼·皮索(https://www.loc.gov/resource/npcc.01561/)
更换场地,14 年 8 月 14 日(网球)(https://www.loc.gov/resource/ggbain.16897/)
爱丽丝大理石在森林山打网球;展示她发球和反手击球的八张照片的合成(【https://www.loc.gov/resource/cph.3c15631/】T2
华盛顿特区,伍德罗·威尔逊高中足球队成员在场边观看比赛(【https://www.loc.gov/item/2017863035/】T4)
杜克大学-卡罗莱纳州足球赛当天高速公路沿线的汽车队。杜伦,杜克大学体育馆附近。北卡罗来纳州达勒姆县(https://www.loc.gov/item/2017801879/)
修补网球网——水手的舒适港湾(https://www.loc.gov/resource/ggbain.16850/)
柱状商店——何时/如何/为什么?
揭开行与列大数据存储的神秘面纱(Parquet、Postgres、Avro 等)
照片由 Unsplash 上的 Skyler Gerald 拍摄
很久以前,数据存储很简单——堆文件和 b 树,仅此而已。今天的选择是压倒性的——ORC、Parquet、HDFS 或 S3 上的 Avro 或者像 Postgresql、MariaDB 这样的 RDBMS 解决方案,或者像 Oracle 和 DB2 这样的商业解决方案。甚至在 RDBMS 引擎和云服务中也有很多选择!
本指南是对广阔的存储领域的“随机漫步”。
样本数据集
我调出了芝加哥公务员的工资信息。你知道公务员的工资是以每个人的真实姓名公布的吗?查找你最喜欢的警察或专员的工资(不幸的是,它不包括加班、津贴或贿赂)。
我添加了一些虚拟的人——Foo & Bar 家族。否则它的真实数据。
面向列与面向行
首先是数据的基本存储机制。行列方向。
面向行将每个单独的记录存储在一起,Doug Foo 的完整记录,然后是 Jane Foo 的完整记录,依此类推。
[Doug,Foo,Foostack,程序员,M,120000] [Jane,Foo,Foostack,程序员,F,110000] [Doug,Bar,…]…
列或 列 将所有列数据存储在一起—因此所有的名字(Doug、Jane 等),然后是所有的姓氏、头衔等等,最后是所有的薪水。
[道格、简、道格、简……][福、福、吧、吧……][程序员、程序员……][M、F、M、F……][120000、110000、100000、130000……]…
数据通常以 KB(或 MB/GB)为单位从磁盘中读取,因此对 1 条记录的单次读取会带来比您想要的更多的数据。
典型块大小[*1]:
- HDFS: 128MB(块)
- 谷歌文件系统:64MB(块)
- 亚马逊 AWS S3: 128KB
- Oracle 数据仓库:32KB
- Postgres 数据库:8KB
- Linux 和 Windows 文件系统:4KB
薪水记录非常小~ 50chars ( <50 bytes). An 8KB block with metadata could easily store 100+ 行导向 记录【8192 / 50 = 163】)。因此,对包含“Doug Foo”的记录的块的一次读取包括更多内容。
对于列块读取—读取因列大小而异。例如,对于 8KB 数据块:
- 名字可能平均为 10 个字节,意味着大约 800 个以上的名字。
- 薪水可以放入一个 32 位的 Int(4 字节)中,产生大约 2000 个条目!
- 性别是 M/F/?—可以存储为 1 个字节,甚至半个半字节~ 8000!
在我们稍后进行更多分析时,记住这一点非常重要。
数据转换
我想添加一个 M/F 属性,所以我合并到一个婴儿名字数据库中,然后写出各种熊猫支持的格式(JSON、CSV 和 Parquet)。
基本熊猫性别数据
注意同等磁盘格式的文件大小差异 (38k 记录) :
- 不带头文件的 CSV 为 2.526 MB
- 压缩后的拼花(柱状)为 606 KB(CSV 的 1/4)
- JSON 为 4.615 MB(比 CSV 大 90%,比 Parquet 大 700%)
拼花地板是一种二进制压缩格式,因此需要一些努力来快速浏览——稍后将讨论细节。
注意一些奇怪的事情,它只显示了道格和简一次,尽管我们有两个道格和两个简。名字聚集在一起。
为什么不存储为 CSV 或 JSON?
显而易见,但让我们把它拼出来:
- 空间利用率差(字符串形式的数字浪费空间)
- 没有类型或结构检查(字符可能会出现在数字字段中)
- CSV —无元数据/标题信息,JSON —重复的元/格式
- 没有重复值的本机压缩
- 没有本地索引/搜索能力
注意 CSV 和 JSON 具有非常容易阅读的明显优势,因此有时是很好的交换格式。
深入探究 Postgres 格式(RDBMS)
Postgres 是一个全功能的开源数据库,既有传统的基于行的存储(有时称为“堆文件”),也有列存储扩展(cstore_fdw)。
我创建了一个模式并将工资数据加载到两个变量中,一个是标准的行和列版本。
查询 38k 记录时两者之间的一些基本统计/比较:
- 选择计数(*) →列存储略快(7.9 毫秒对 10.9 毫秒),并且“成本”较低(480 毫秒对 873 毫秒)(假设这是估计操作/读取的指标)。理论上,我们使用列存储读取少于的块,因为您只需要扫描一列来获得计数,并且它是压缩的。
count(*)测试,只是在列上快一点
- Select sum(salary) →这应该是柱形图的一个经典案例,我们只需要扫描一列或一系列块,而基于行的需要扫描所有块,以便从每行中提取薪金。但是没有我们预期的那么快。成本便宜了 493 vs 873,但是计时是 14.1ms vs 17.1ms。
38k 行,即使在一个单独的列上,速度也快不了多少。
3.更大的数据集— 我将它提升到 380 万行,并重新运行 sum 查询。变化不大——有点令人惊讶!理论上,这应该比 20-30%的涨幅要快得多。其实柱状往往是缓存 生效后 *变慢!(公平地说,您确实需要比您的内存缓存更大的 GB 到 TB 数据集才能获得真正的收益) [2] 。
3.8 米的行,还是没有快很多。
在阅读了一些 bug 报告和开发者笔记之后,我可以猜测作为一个扩展,它不如标准行存储健壮。例如,本机行格式提供多核处理和缓冲区缓存。我可能应该与本地列存储数据库进行比较…
请注意我加载 3.8m 行时的文件大小:
- 标准行格式: 321 MB
- 柱状/压缩格式: 72 MB
巨大的空间节省(几乎 4 倍)!注意磁盘上的行和列的原始数据转储(在 linux/wsl2 上使用“xxd -c 32”):
行方向非常简单
纵列由带有压缩子串的纵列展开
镶木地板——最受欢迎的?
Parquet 来自 Twitter 和 Cloudera (Hadoop ),作为 Apache 项目维护。这是 Spark 的实际格式,因此最受欢迎。(之前流行的格式包括 ORC 和 RCFile)。
Python/Pandas 本身也支持它,并提供多种压缩格式。基本的文件格式是一个由行组成的列,存储一个中央模式&组级元数据,以允许并行和部分读取。
对原始文件的适度深入研究显示:
类似于 Postgres CStore —列被分批分组并压缩,这样 Doug,Jane 在整个文件中只出现一次。
AVRO —面向行的模式进化
与 Parquet 竞争激烈的是 Avro,它不仅仅是一种存储格式,但我们将只关注存储方面。这也是一个 Apache 项目。 *[3] 拼花地板的两个主要区别:
- 更好的模式进化
- 面向行的存储
模式和更改(新行和旧行的默认值)嵌入到文件中。添加新列只需要定义默认值,这使得渐变维度(SCD)和更改更容易处理。
请注意,它是面向行的,因此您不会获得像使用 Parq 那样的一些优势,例如压缩和性能——假设您的用例更多地是关于列聚合,而不是逐记录处理。
Avro 代码和数据文件示例:
其他存储选项(MongoDB、Kafka、KDB 等)
NoSQL — 像 MongoDB、AWS Dynamo 和 Cassandra 这样的名值对象存储通过不同的键存储整个 JSON(或任意)对象。该 API 使用基本的键值存储(put/get)语义,非常简单。高水平+/-:
- +简单的编程接口
- +快速启动并运行您的应用
- -加载多个或复杂数据的效率低下
- -索引和查询/搜索不灵活
- -模式演变挑战
**日志结构化商店(和日志结构化合并树)**和它们的创新用途是一个迷人的领域——卡夫卡是领导者和创新者(不要被愚弄了,它不仅仅是消息传递,它真正关于 日志*根据联合创作者 Jay Kreps 。 [4]
- +简单的编程接口
- +实时消息存储和数据库的可扩展替代方案
- -复杂的集群管理
最后,KDB 值得一提,他是列式、实时和时序内存数据库的先驱。最初编写于 90 年代,即使在今天也拥有无与伦比的单核性能。不幸的是,这是一种昂贵的利基产品,因此最近被出售给一级衍生品,很可能会失血而死…
- +超快和低占用空间(800kb)适合 L1/L2 缓存
- +利用矢量/SIMD CPU 指令
- -不超过 1 台机器(不需要?)
- -成本和晦涩的语言(K/Q)使大多数消费者望而却步。
Apache Arrow(内存列格式和串行器)和 OLAP 理工大学也是值得研究的两个领域。
总结:首要考虑事项
- 列式是否适合您的典型用例(在几列上频繁聚合)?
- 您现有的数据库是否提供像列存储这样的存储选项?
- 模式演变/改变是常见的,也是一个关键的考虑因素吗?
- 存储空间/容量是一个关键考虑因素吗?
仔细考虑一下,试运行一下。关系数据库在缓存和索引方面已经有了很大的改进,这在某些情况下可能会降低其必要性。
参考资料、脚注和灵感
- 对于文件系统/操作系统、数据库和大数据存储,如 S3/GFS,块大小在概念上是不同的。在每种情况下,它都是一个逻辑单元。AWS EBS 使用 4K,S3 是一个对象存储,但它的最小分配是 128KB。
- ***【2】-*列性能仅在冷启动/清除缓存时更快。一旦数据库填满了它的缓存,Postgres 上的传统行存储总是更快。但是,列存储适用于大数据~TB 大小的数据集,这些数据集大于内存,会表现出冷缓存行为。
- 【3】——更混乱的是,Avro 的序列化代码可以写入 Parquet 文件格式。它既是竞争对手,也是合作者。
- 【4】——大多数人认为 Kafka 只是下一个 MQ,但它是一个根本不同的方法,以提交/事务日志*为中心,这是一个伪数据库。*
- *Postgres c store——【https://github.com/citusdata/cstore_fdw *
- Parquet 上的好读物—https://medium . com/swlh/insights-into-Parquet-storage-AC 7 e 46 b 94 FFE
- Avro—https://www . perfectlyrandom . org/2019/11/29/handling-Avro-files-in-python/
- LSM 树 vs B 树—https://blog . yugabyte . com/a-busy-developers-guide-to-database-storage-engines-the-basics/
- 关于 LSM 树的更多信息—https://www . slide share . net/ConfluentInc/power-of-the-log LSM-append-only-data-structures
- 克雷普斯 ♥ 日志(卡夫卡)—https://www . confluent . io/ebook/I-heart-logs-event-data-stream-processing-and-data-integration/
- 阿瑟·惠特尼对 KDB &的完整改写——https://kx.com/blog/small-core-code-and-hp-apl/
- 源数据集—https://Data . cityofchicago . org/Administration-Finance/Current-Employee-Names-salary-and-Position-Title/aned-ke5c
- 本文 GitHub——https://github.com/dougfoo/fileformats
多元时间序列预测的 LSTM 和 VAR 组合方法
多步训练过程在时间序列预测领域的应用
在经典的时间序列预测任务中,建模时的第一个标准决策涉及采用统计方法或其他纯机器学习模型,包括基于树的算法或深度学习技术。这种选择与我们正在解决的问题密切相关,但总的来说:当我们面临一个自回归问题,而未来只与过去相关时,统计技术就足够了;而机器学习模型适用于更复杂的情况,也可以组合多样化的数据源。
在这篇文章中,我试图将统计方法从经验中学习的能力与深度学习技术的推广相结合。我们的任务是一个多变量时间序列预测问题,所以我们使用 ARIMA 的多变量扩展,称为 VAR,和一个简单的 LSTM 结构。我们不生产一个集合模型;我们使用 VAR 的能力来过滤和研究历史,并在预测未来时为我们的神经网络提供益处。
我们的工作流程可以总结如下:
- 根据我们的训练数据正确估计 VAR
- 提取 VAR 学到的知识,并将其用于改进执行两步培训的 LSTM 模型的培训流程。
我们会发现我们的结果并不明显,因为按照这个步骤,我们必须与灾难性遗忘的问题作斗争。
数据
我们实验的数据包含嵌入在空气质量多传感器设备中的金属氧化物化学传感器的每小时平均响应,该设备位于意大利城市污染严重地区的场地*。*记录了一年的数据,包括一氧化碳、非后生碳氢化合物、苯、总氮氧化物(NOx)和二氧化氮(NO2)的实际小时平均浓度。此外,还提供了外部变量,如天气状况。存在大量 nan,因此在继续之前需要进行线性插值(排除训练数据中 nan 超过 50%的序列)。
由我们支配的时间序列的例子(图片由作者提供)
VAR 建模
对于 ARIMA,我们使用每个变量的过去值来预测未来。当我们有多个时间序列可供支配时,我们也可以从它们的关系中提取信息,这样 VAR 就是 ARIMA 的多元推广,因为它理解并使用几个输入之间的关系。这有助于描述数据的动态行为,并提供更好的预测结果。
要正确开发风险值模型,必须满足拟合 ARIMA 时遇到的相同经典假设。我们需要给予平稳性并利用自相关行为。这些先决条件使我们能够开发一个稳定的模型。我们所有的时间序列平均都是平稳的,显示出每日和每周的模式。
我们所掌握的一些时间序列的自相关例子(图片由作者提供)
在这些初步检查之后,我们准备好拟合我们的 VAR。最佳滞后阶数的选择是根据 AIC/BIC 准则自动进行的。我们用 AIC 来操作选择:我们需要做的就是递归拟合我们的模型,改变滞后阶数,并标注 AIC 分数(越低越好)。可以仅考虑我们的列车数据来执行该过程。在我们的例子中,27 是最好的延迟顺序。
用 AIC 方法进行 VAR 滞后阶数选择(图片由作者提供)
将 VAR 和 LSTM 结合起来
现在我们的范围是使用我们拟合的 VAR 来改善我们神经网络的训练。VAR 已经了解了我们的多变量数据源的内部行为,调整了疯狂的值,纠正了异常的趋势,并正确地重建了 NaNs。所有这些信息都存储在拟合值中,它们是模型在训练过程中处理过的原始数据的平滑版本。换句话说,我们可以将这些值视为原始列车的一种增强数据源。
我们的策略包括应用两步训练程序。我们使用 VAR 产生的拟合值,开始为我们的 LSTM 自动编码器提供数据,用于我们处理的所有序列的多步预测(多变量输出)。然后,我们用原始数据结束训练,在我们的情况下,它们是我们之前用来拟合 VAR 的相同数据。通过我们的神经网络,我们还可以结合外部数据源,例如,天气状况或一些时间属性,如我们循环编码的工作日、小时和月。
我们希望我们的神经网络可以从两个不同但相似的数据源中学习,并在我们的测试数据上表现得更好。我们的方法听起来很棒,但这不是“免费的午餐”。在进行多步训练时,我们必须注意 灾难性遗忘 的问题。灾难性遗忘是很多模型和算法面临的问题。当在一个任务上训练,然后在第二个任务上训练时,许多机器学习模型“忘记”如何执行第一个任务。这被广泛认为是神经网络的一个严重问题。
为了避免这个繁琐的问题,整个网络的结构必须进行适当的调整,以提供性能方面的好处。根据这些观察,我们保留了之前培训的最后一部分作为验证。
从技术上讲,网络非常简单。它由一个 seq2seq LSTM 自动编码器构成,可以提前 N 步预测未来可用的传感器。使用keras-hype tune执行训练程序。该框架以非常直观的方式提供了神经网络结构的超参数优化。对所有三个涉及的训练(对 VAR 拟合值的拟合、对原始数据的微调拟合和直接对原始数据的标准拟合)都进行了这一步。
最后,我们可以将根据 VAR 的拟合值加上原始数据训练的模型与仅根据原始训练数据训练的相同结构进行比较。在大多数情况下,当我们执行两个训练步骤时,误差较低。我们还报告了使用基线获得的性能,该基线由最近可用观察的简单重复组成。该程序是验证预测是否不是重复的当前值(即不是有用的预测)的良好实践。
测试台上的 RMSE(图片由作者提供)
摘要
在本文中,我们尝试使用 VAR 模型获得的信息来完成一项多变量时间序列任务,以提高经过训练的预测未来的递归神经网络的性能。我们实施了两步训练程序,解决了灾难性遗忘的问题,并提高了整体表现。
保持联系: Linkedin
参考文献
基于梯度的神经网络中灾难性遗忘的实证研究
结合贝叶斯神经网络和集成技术
通过利用不确定性使机器学习变得有意义
在机器学习领域,追求越来越大的准确性推动了创新。然而,要使机器学习实用,一个同样重要的特征是能够定义给定预测的不确定性。在本文中,我们将讨论实现这些目标的各种技术,并在文献中给出实践示例,其中选择了这些技术并取得了成功。一般格式是贝叶斯深度学习框架的格式,该框架寻求将集合预测的准确性和稳健性与贝叶斯建模中可用的不确定性估计统一起来。因此,我们将把这一条分成:
技术
地图
集成技术
贝叶斯神经网络
随机地图采样
高斯混合模型
例子
’ ‘用于系外行星大气反演的贝叶斯神经网络集合’
‘神经网络中的不确定性:近似贝叶斯集合’
‘使用堆叠来平均贝叶斯预测分布’
术语
fᵂ(X) —神经网络模型
p(W|X,y)—nn 权值 w 给定数据 x,Y
p(Y|X,w)—nn 权值 w 来自数据 x,Y
p(W)的最大似然—nn 权值的先验概率
p(Y|X) —数据的边际概率
~N(μ,σ ) —均值为μ且方差为σ的正态分布
N —训练样本大小
M —集合大小
(下面显示的所有等式)
技术
地图
表示为 fᵂ(X 的神经网络(NN)模型由一组相互连接的权重 w 组成,允许我们从输入 x 预测输出 y。这是通过使用梯度下降和使用损失函数 l 的反向传播优化权重来实现的。在统计术语中,这导致给定数据 p(Y|X,w)的权重的频率最大似然估计(MLE)。
最大后验概率估计 使用神经网络的另一种方法是最大化最大后验概率(MAP)估计。换句话说,这就是找到最好地解释我们的数据的参数, p(W|X,Y) 。这可以使用贝叶斯规则来发现:p(W|X,Y) = p(Y|X,W)p(W)/p(Y|X)。如果我们针对 p(W|X,Y)进行优化,我们可以忽略归一化的 p(Y|X)并将其重新表述为针对 p(W|X,Y) 进行优化,这相当于针对 *p(Y|X,W)p(W)进行优化。我们必须对 p(W)部分的权重进行先验分布,这是我们的先验信念(如果这是一致的,我们可以观察到我们的 MAP 和 MLE 估计是相同的)。在实践中,这相当于在我们的损失函数中增加正则化项来训练神经网络(L2 项相当于高斯先验,L1 相当于拉普拉斯先验),如这里的所示。这给了我们地图点估计预测。
集成技术
集成技术包括训练多个模型(弱学习者)来解决同一问题,然后将这些模型组合起来以获得更好、更稳健的预测,这些预测具有更低的方差和/或更低的偏差。它们可以大致分为三种不同类型训练过程:装袋,助推和堆叠。
打包包括在 N 个不同的子数据集上不同次数地训练相同的基础模型 N 。这些子数据集是使用自举采样方法从初始数据集生成的。这有效地随机采样具有替换的初始较大数据集(确保采样的子数据集的大小足够小于初始数据集)。根据模型,从初始数据集中选择用于训练的特征也可以进行引导采样。为了对输入进行预测,这 N 个不同的模型都根据输入进行各自的预测,然后将得到的 N 个不同的预测进行平均。
Boosting 类似于 bagging,但是由顺序训练 N 个(相同基础)模型组成。每一个连续的模型都集中在先前模型错误预测的数据上。最终的集合由所有弱学习者组成,每个弱学习者根据他们的表现被适当地加权。例子包括 adaboost 和梯度增强。
Bagging 并不昂贵,因为它可以并行训练,而 boosting 由于其持续改进而导致较低的偏差。
堆叠包括训练不同的基础模型,然后通过将它们传递到另一个“元模型”来组合它们的预测,从而产生我们的最终预测。我们将初始数据集分成一个用于训练弱学习者的数据集和另一个弱学习者预测的数据集,元模型训练弱学习者的预测,以最终输出单个预测。
详细的精彩讲解可以在这里找到。
贝叶斯神经网络
在神经网络中进行回归预测时,典型的用例是点估计。然而,对此的一个非常有用的补充扩展是,也能够衡量我们在预测中的自信或不确定程度。为此,我们利用了贝叶斯神经网络(BNN)。
不确定性类型 我们先来讨论一下不确定性的不同类型。有两种类型的不确定性:任意的和认知的。随机不确定性来自于数据集中固有的噪声,因此对于给定的 x 值,我们可能会得到多个 y 值(y 值的分布)。随机不确定性可分为两种类型:不确定性水平在所有 x 值上保持不变(同方差)或不确定性水平在 x 值上变化(异方差),如下所示。
还存在认知上的不确定性,这种不确定性来自于我们建模的不足。这可以通过更好的建模和更多的数据来改善。
不同类型不确定性的完整解释可以在这里找到。
对认知不确定性建模 为了对认知不确定性建模,我们使用了一个 BNN,我们现在将对其进行解释。这类似于神经网络,除了代替精确的参数,我们的权重 W 现在被建模为分布。
现在在常规的神经网络中,我们首先初始化我们的权重,然后求解一个优化任务来得到我们的最终权重。然而,在 BNN(我们也将表示为 fᵂ(X))中,最初我们在我们的权重上放置一个先验分布(通常是高斯先验),p(W)。然后,我们执行贝叶斯推断,从贝叶斯定理中找到权重 p(W|X,Y)的后验分布,如下所示。
注意这里 p(Y|X,W)是我们的可能性。为了得到 p(Y|X ),我们需要在所有可能的权重上平均我们的可能性(边缘化),从而得到积分。
然而,在 BNN 中获得后验分布 p(W|X,Y)通常是困难的,因此我们使用近似方法来尝试解决这个问题。变分推理就是这样一种方法。这包括将由θ参数化的简单分布 q*(W)拟合到后验分布。因此,这用简单分布参数的优化任务代替了难以处理的边缘化,该优化任务最好地最小化 q*(W)和真实模型后验 p(W|X,Y)之间的 KL 散度。
一个示例实现方法是丢弃变分推断。这里,为了近似后验分布,我们建立了 NN 模型,以在每个权重层中包括丢失单元 ⁴(这将权重随机设置为 0 或 1)。然后正常训练神经网络。然而,对于预测,我们再次使用 dropout(称为 monte carlo dropout)将一些权重随机设置为 0,这让我们可以从近似的后验样本中进行采样。这里的和 ⁵表明,像这样使用漏失等价于对 q*(W)使用伯努利分布的变分推断。这种情况下的损失函数是:
这里 N 是数据点的数量,漏失概率用 p 表示,θ是简单分布参数。我们的权重是从我们的简单分布 Wᵢ ~ q*(W)中抽取的。
建模异方差随机不确定性 为了建模随机不确定性,我们可以只使用一个正常的神经网络。然而,我们不是仅仅预测我们的输出 Y,而是通过将我们的输出改变为我们的平均值μ(本质上是正常的神经网络预测)和我们的方差σ来预测分布。分布方差σ让我们了解不确定性的水平。对于异方差,这个方差取决于输入,σ(Xᵢ).我们像往常一样用修正的损失函数训练神经网络:
还可以添加重量衰减 L2 正则化项。
要注意的一个关键点是,我们只是在这里执行正常的优化,而不是变分推理。这产生了我们的模型权重 W 的地图点估计,而不是之前看到的分布 q*(W)。
建模认知和随机不确定性 在这种情况下,我们将使用异方差神经网络,并将其转化为 BNN,或者换句话说,我们将神经网络的权重建模为分布。我们的模型需要推断权重的后验分布,该分布将我们的输入 X 映射到输出(预测 y/μ和方差σ)。我们用损失函数训练这个 BNN:
这类似于纯粹的任意神经网络。d 是样本数,yᵢ是实际产量,戴帽子的 yᵢ是预测产量,戴帽子的σᵢ是预测方差。当实现这个损失函数时,我们对其进行处理,以使我们预测 sᵢ而不是σᵢ:= logσᵢ为:
这是因为该损失函数在训练时被证明在数值上更加稳定,因为它避免了被零除。损失由两部分组成:第一部分是利用参数的不确定性通过模型输出的随机样本获得的均方残差,第二部分是不确定性正则化。我们不需要指定不确定性标签,因为模型从成本函数中隐含地学习了这一点。第二项防止网络预测无限的不确定性,因此零损失。
因此,我们得到[y,σ ]的 T 个样本,每个样本从近似分布 q(W)中抽取权重 W~q(W ),总方差由下式给出:
一个很好的讨论可以在这里 ⁶.找到
随机地图抽样
在随机地图抽样中,我们的目的是尝试使用神经网络的集合来预测后验分布,并对认知不确定性进行建模。我们可以像往常一样想象我们的神经网络,我们称之为 fᵂ(X).然而,为了找到我们的模型权重,不是仅仅使用正常的映射损失函数(通常是 L2 正则化损失函数)来训练神经网络,我们还将噪声添加到我们的损失项中。
我们使用噪声损失函数的每个不同实例来训练多个模型,这为每个模型提供了不同的优化权重。因此,当使用所有模型进行预测时,我们得到了一个地图解的分布,它估计了我们的真实输出分布。现在,我们必须考虑如何将噪声添加到我们使用马尔可夫链蒙特卡罗(MCMC)程序的问题中。
首先让我们陈述这个问题。为了便于解释,我们将假设一个多元正态 n(μₚᵣᵢₒᵣ,σₚᵣᵢₒᵣ),n(μₗᵢₖₑ,σₗᵢₖₑ).的先验分布和概率在这种情况下,为了求解μₚₒₛₜ,存在一个标准解:
我们必须添加噪声,以使约束 var(μₚₒₛₜ=σₚₒₛₜ得以实施,或者换句话说,我们的输出分布的均值方差等于输出分布的方差。实际上,我们通过将μₚᵣᵢₒᵣ(我们先前分布的平均值)建模为随机噪声变量θ₀来注入这种噪声,导致损失函数如下:
对于足够宽的 NN,这里显示了⁷,我们的符合约束的随机噪声变量可以有效地建模为θ₀~ n(μₚᵣᵢₒᵣ,σₚᵣᵢₒᵣ).
高斯混合模型
高斯混合模型(GMM)是一种在整个数据集中参数化正态分布子集的方法。因此,这是一种无监督学习的形式。在我们的情况下,我们可以考虑两种不同的情况。
这方面的一个例子是考虑男性和女性的一组正态分布的权重。仅给出体重数据而不给出性别归属,我们可以发现总体分布是两个缩放(方差变化)和移位(均值变化)正态分布的总和,这是 GMM 模型的一种形式。因此,我们的 GMM(数学模型如下所示)由两种类型的值参数化:分量权重和分量均值和方差。
图片取自https://brilliant.org/wiki/gaussian-mixture-model/
我们的 GMM 概率记为 p(x)。在上面的第一行中,我们可以看到这被建模为多个正态分布(我们的组件)的加权和。第二行只是定义了经典的正态分布公式,第三行给出了我们对权重的约束,这样它们加起来就是一。
GMM 建模的任务是计算其成分权重ϕᵢ、成分均值、μᵢ和成分方差σᵢ.如果组件权重未被学习,则它们可以被视为组件上的先验分布,如 p(由组件 Cₖ生成的 x)= ϕₖ.如果它们是已知的,那么它们就是给定数据的分量概率的后验估计。
为了学习模型的权重,我们使用了最大似然技术,称为期望最大化。EM 算法如下所示:
图片取自 https://brilliant.org/wiki/gaussian-mixture-model/
作为算法的开始,我们从数据集中随机分配样本,不替换我们的分量均值估计μ₁….μₖ并将所有分量方差估计值设置为样本方差:
我们还将所有组件权重设置为均匀分布= 1/K,其中 K 是组件的数量。
然后,在如上所述的期望步骤中,我们找到给定其当前参数 p(Cₖ|xᵢ,ϕᵢ,μᵢ,σᵢ).的每个数据点的每个分量的期望然后,在最大化步骤中,我们根据模型参数ϕᵢ、μᵢ和σᵢ.最大化这些期望值
这个概念在这里⁸.得到了更充分的解释
例子
用于系外行星大气反演的贝叶斯神经网络集成
摘自论文 Cobb et al. 2019 ⁹的一个例子显示了上述实施的各种技术的组合,证明是成功和最先进的。在论文中,他们试图说明认知和随机的不确定性。
首先,他们使用输出均值和协方差矩阵的 BNN(以模拟随机不确定性),其架构为 4 个密集的混凝土脱落层,每层由 1024 个单元组成。批量大小为 512,使用了 adam 优化程序。负对数似然损失函数与训练期间保存的早期停止和最佳检查点一起使用。这些模型中的 5 个然后被用于整体平均过程。
让我们讨论一些细微差别。首先,在 BNN 的权重上假设高斯先验。在训练过程中,蒙特卡罗下降近似用于变分推断,这允许宽 NN 层。在预测阶段,它们通过网络向前传播 T 次,以获得 T 个预测,形成我们的经验输出分布,该分布封装了我们的认知不确定性。使用混凝土脱落层,这是一种技术,此处⁰解释了这种技术,它有效地优化了每层中要脱落的单元的比例。
然后将其整合到 5 个模型(5 个通过经验性能选择)的集合中,以增加其对权重初始化和优化路径的鲁棒性。当每个集合预测一个分布时,通过使用元高斯混合模型将它们组合在一起,其中每个分量的权重等于 1/M,其中 m 是给出最终输出分布为σₑₙₛ).θₑₙₛ~n(μₑₙₛ的模型的数量通过平均所有分量的平均值,并使用总方差的定律,可以得到μₑₙₛ,σₑₙₛ为:
‘神经网络中的不确定性:近似贝叶斯集合’
摘自论文 Pearce et al. 2018 ⁴的一个例子展示了应用集成方法来模拟贝叶斯技术的能力。总的来说,集成方法不遵循任何正式的贝叶斯建模技术。
第一步是将我们的机器学习从 MLE 重新表述为映射问题,这将我们引向正则化的损失函数:
然后,我们实现上述随机 MAP 采样方法,其中我们假设我们将噪声添加到我们的先验分布中,从而得到上述锚定损失函数。
这种随机映射采样方法是用 100 个单元的单层神经网络运行的。少量的神经网络就足够了,因为我们在参数空间而不是输出空间进行推理,输出空间需要相对较少数量的集成神经网络。在论文测试中,随机地图抽样被证明是黄金标准(高斯过程和哈密顿蒙特卡罗)贝叶斯推断的良好近似。与不考虑相关性的平均场变分推断或 MC 丢失相比,它有过度预测方差的趋势,但在捕捉插值区域的不确定性方面表现更好。对于实际的图和结果,请参考上面的文章链接。
这证明了该方法的有效性,特别是其简单性及其与神经网络正常工作的相似性,增加了围绕来自先验分布的值进行正则化和使用集成技术进行重新采样的复杂性。
‘使用堆叠来平均贝叶斯预测分布’
摘自 Yao 等人 2018 的一个例子试图将点估计文献中通常使用的叠加方法与预测分布的贝叶斯建模相结合,并将其有效性与通常的贝叶斯模型平均(BMA)进行比较。
问题公式化如下,给定遵循多维分布的数据集 X,然后我们可以从一系列候选模型中生成一个新模型,该模型将预测尽可能接近真实输出数据生成分布的输出分布 Y。这个问题包括三种不同的情况。
- M-closed:真正的数据生成模型存在于我们的候选模型列表中, M = (M₁,….,Mₖ).
- M-complete:真实的输出数据生成分布不在我们的列表中,但是我们知道这一点并选择我们的候选模型,因为真实的模型是难以处理的。
- M-open:真正的数据生成模型对我们来说是未知的,因为它可能在概念上或计算上太困难了。
作为对最基本的 BMA 类型的一行总结,对于一个给定的数据点,它从一系列候选模型中挑选一个能最好地预测它的模型。然而,这通常是浪费知识和不稳定的,并且适合于 M-闭的情况。
堆叠使用候选模型列表, M ,并获得每个模型的每个数据点的 LOO 预测(留一预测:在除一个数据点之外的所有数据点上拟合一个模型,并在其上进行预测)。然后,通过获得所有模型预测的加权和,将这些模型组合起来进行预测。通过最小化 LOO 评分规则来确定为每个模型生成的权重:
k 迭代模型,I 迭代数据点。这个等式表明,我们找到了使模型的加权和与实际输出之间的残差最小化的最佳权重。然后,预测由模型的加权和给出:
为了将此转化为预测分布的叠加,我们需要首先提出一个评分规则。
评分规则 评分规则是作用于概率空间和整数的一些函数,并返回关于概率空间预测整数的程度的值。评分规则的例子包括:二次评分、对数评分、连续排名概率评分、能量评分以及取决于分布的一阶和二阶矩的评分规则。二次和对数计分的分数由下式给出:QS(p,y)= 2p(y)-||p||₂和 LogS(p,y) = log(p(y))。
广义堆叠问题可以表述为:
根据分布和它试图估计的点之间的一些评分规则标准,预测 C 是最优的,并且遵循模型权重总和应该为 1 并且模型权重必须为非负的约束。
在我们的例子中,我们通过用 LOO 预测分布替换预测分布 p(yₒᵤₜ|y,Mₖ来使用评分规则的 LOO 版本。我们可以这样做,因为对于样本大小→ ∞,LOO 预测分布和完全预测分布的得分之间的 L2 误差趋于零,因此证明堆叠渐进地给出了权重的最佳组合。然而在实践中,LOO 仍然过于繁重,因此使用了 PSIS-LOO ( 帕累托平滑重要性采样 ⁴)。
举一个例子,如果我们将此应用于一种情况,例如试图预测一个形式为 y~n(3.4,1)的真实基础模型,该模型具有形式为 n(μₖ,1(1≤k≤8)的 8 个候选解。BMA 会在 k = 3 时选择单一模型,叠加总会给我们 1/nσⁿᵢ₌₁yᵢ.对于预测分布结果的叠加,我们需要根据损失和约束条件优化权重:
该论文表明,这完全优于均方误差训练点估计预测。这表明在 KL 散度上接近的两个分布在每个时刻都是接近的,而反之则不一定。这说明了匹配分布而不是匹配矩(如均值)的必要性。
结论
总的来说,这篇文章试图展示一种不同的方法在处理机器学习问题上的理论可能性和实践合理性。
[1] J. Brownlee ,《机器学习的最大后验概率(MAP)的温柔介绍》(2019),https://machinelingmastery . com/Maximum-A-posterior-estimation/
【2】j . Rocca,《集成方法:装袋、助推和堆叠》(2019),https://towardsdatascience . com/Ensemble-methods-bagging-boosting-and-stacking-c 9214 a10a 205】劳曼《贝叶斯神经网络中的不确定性告诉你什么》(2019)https://towards data science . com/What-unabilities-tell-you-in-Bayesian-Neural-Networks-6 FBD 5 f 85648 e
【4】C*。Ranjan* ,用背后的简化数学理解辍学(2019),https://towardsdatascience . com/Simplified-Math-behind-Dropout-in-Deep-Learning-6d 50 F3 f 47275
【5】y . Gal, Z. Ghahramani ,带伯努利近似变分推理的贝叶斯卷积神经网络(2016),https://arxiv.org/abs/1506.02158
(2017),https://arxiv.org/abs/1703.04977
【7】t .皮尔斯,M .扎基,a .尼利,贝叶斯神经网络系综(2018),http://bayesiandeeplearning.org/2018/papers/78.pdf
j .麦戈纳格, G .皮林, A .多布尔,【2020】,https://brilliant.org/wiki/gaussian-mixture-model/
【9】科布,亚当 系外行星大气反演的贝叶斯神经网络集成(2019 年),https://arxiv.org/abs/1905.10659
【10】y . Gal, J. Hron , A. Kendall ,Concrete Dropout(2017 年),https://arxiv.org/abs/1705.07832
【11】全方差直觉定律 (2016 年),https://math . stac A. Vehtari , D. Simpson , A. Gelman ,https://arxiv.org/abs/1704.02030
【14】a . Vehtari, D. Simpson , A. Gelman , Y .姚,
使用 Pandas 合并数据帧
关于 concat 和 merge 函数的完整教程
Pandas 是一个高效且广泛使用的数据分析工具。Pandas 的核心数据结构是DATA frame,它以表格的形式表示数据,带有标记的行和列。DataFrame 有许多强大而灵活的功能和方法,可以简化和加快数据清理和分析过程。
**注意:**键入“DataFrame”可能不是正确的英语,但它在 Pandas 语法中作为 DataFrame 存在。因此,在这篇文章中,我将把它写成 DataFrame,这样你就会习惯了。如果您将其键入为“dataframe”或“Dataframe ”,将会出现错误。
数据科学项目通常需要我们从不同的来源收集数据。因此,作为数据准备的一部分,我们可能需要组合数据框架。在这篇文章中,我将解释组合数据帧的不同方法。
让我们首先创建两个数据帧:
串联
组合或连接数据帧的一种方法是 concat() 函数。通过改变轴参数,它可用于沿行或列连接数据帧。axis 参数的默认值为 0,表示沿行组合。
正如您在上面的第一张图中所看到的,保留了各个数据帧的索引。为了改变它并重新索引组合数据帧, ignore_index 参数设置为真。
concat()函数的 join 参数决定如何组合数据帧。默认值为“outer ”,返回两个数据帧中的所有索引。如果选择了’ inner '选项,则只返回具有共享索引的行。我将改变 df2 的索引,以便您可以看到“内部”和“外部”的区别。
join =“内部”vs join =“外部”
Pandas 还提供了标记数据帧的方法,以便我们知道哪个部分来自哪个数据帧。我们只是使用键参数按顺序传递组合数据帧列表。
它还使得方便地访问数据帧的不同部分变得更加容易:
关于 concat()函数的一个重要注意事项是,它制作了数据的副本。为了防止进行不必要的复印,需要将复印参数设置为假。默认值为 True。
append() 函数也用于组合数据帧。它可以被看作是 concat()函数的一个特例(axis=0,join='outer '),所以我不会详细讨论它,而只是给出一个例子来展示语法。
合并
组合数据帧的另一个广泛使用的函数是 merge() 。Concat()函数只是将数据帧一个接一个地相加或并排相加。它更像是附加数据帧。Merge()根据共享列中的值组合数据帧。与 concat()函数相比,Merge()函数提供了更多的灵活性。看到例子就更清楚了。
让我们先来看看初始数据帧:
上的参数选择用于合并的列或索引级别。
列名不必相同。我们关注的是列中的值。假设两个数据帧在一个列中有共同的值,您希望使用该列来合并这些数据帧,但是列名不同。在这种情况下,可以使用 left_on 和 right_on 参数,而不是 on 参数。为了显示差异,我将在 df2 中更改列名,然后使用 merge:
尽管 column_a 和 new_column_a 中的返回值是相同的,但由于具有不同的名称,合并的数据帧包括这两个列。
您也可以将多个值传递给参数上的**。返回的数据帧只包括在所有传递给参数上的的列中具有相同值的行。**
df1 和 df2 是根据 column_a 中的公共值合并的,是时候介绍一下howmerge()的参数了。顾名思义,表示你想怎么组合。how 的可能值为“内部”、“外部”、“左侧”、“右侧”。
- 内部:只有在参数上的指定的列中具有相同值的行(如何参数的默认值)
- 外部:所有行
- 左侧:左侧数据帧中的所有行
- 右侧:右侧数据帧中的所有行
“如何”的概念在下图中更加清晰。如果您熟悉 SQL,其逻辑与 SQL 连接相同。
下面的数字更清楚地代表了参数的概念。
outer ‘,’ left ‘和’ right '选项包括不在其中一个数据帧中的数据。缺少的零件自动用 NaN 值填充。NaN 是熊猫缺失价值观的典型代表。
如何= ‘内在’
how 的默认值是“inner ”,因此您不必在函数中显式编写。“Inner”只返回 column_a 中具有公共值的行。
如何= ‘外部’
当 how 参数选择’ outer '时,合并的数据帧包括两个数据帧中 column_a 的所有值。但是,公共值(column_a = 1 和 column_a = 2)不会重复。
怎么= ‘左’
当 how 参数选择’ left '时,合并数据帧包括左侧数据帧中所有行。如果 column_a(传递给 on 参数的列)中的值不在右数据帧中,则右数据帧中的列将填充 NaN 值。很少使用“right”选项,因为您只能在 merge 函数中更改数据帧的顺序(而不是(df1,df2)使用(df2,df1))。
您可能已经注意到,两个数据帧中相同的列名会添加一个后缀。区分哪一列来自哪一个数据帧是很有用的。您可以使用后缀参数指定要添加的后缀。
感谢您的阅读。如果您有任何反馈,请告诉我。