TowardsDataScience-博客中文翻译-2019-四十九-

TowardsDataScience 博客中文翻译 2019(四十九)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

带有 Python 库的 OHLC 图表

原文:https://towardsdatascience.com/ohlc-charts-with-python-libraries-c58c1ff080b0?source=collection_archive---------17-----------------------

Python 程序员可以使用几个图形库。最流行的两个是 MatplotlibPlotly 。选对库要看你的情况。我在两个库中重新创建了 OHLC ( 开盘-盘高-盘低-收盘)图来突出这些差异,并包含了下面的代码。

Matplotlib

Matplotlib 是我开始用 Python 编程时学会使用的第一个图形和绘图库。这是一个高度可定制的库,这既是它的优势也是它的弱点。您可以为您的特定目的制作强大的可视化,但是有大量可定制的代码需要调整。

Matplotlib 的财务模块已被弃用,并被移至mpl_finance模块。许多在线教程没有反映出这一变化,但是,该补丁相对容易用 PIP 包安装工具实现。我专门为这个练习创建了一个新环境,因为我不想在我的主环境中使用这个模块。该模块以 zip 文件的形式位于 Matplotlib 的 GitHub profile 上,命令如下:

!pip install [https://github.com/matplotlib/mpl_finance/archive/master.zip](https://github.com/matplotlib/mpl_finance/archive/master.zip)

我决定绘制金宝汤公司(CPB)的年初至今(YTD) OHLC 图,截至 2019 年 11 月 21 日。数据是从雅虎财经下载的。

Plotting the YTD OHLC chart for the Campbell Soup Company with Matplotlib. The data came from Yahoo Finance and the tutorial was made by Harrison Kinsley.

主要的困难是解开熊猫数据框的行,并将日期字符串转换成 Matplotlib 的浮点数格式。我的日期是字符串格式的,所以我可以使用 Matplotlib 的datestr2num()方法。

The Campbell Soup Company YTD chart created with Matplotlib

Plotly

Plotly 提供了许多产品,包括一个用于 Python 语言的开源图形库。Plotly 提供了许多交互式图表,包括几个特定于金融的图表。我重新创建了坎贝尔 OHLC 年初至今图表如下。

The code for a Plotly OHLC chart with a rangeslider for the Campbell Soup Company

Plotly 在熊猫数据框中运行良好。这些柱子可以直接使用,不需要拆开它们。在 Plotly 的 OHLC 图表部分有几个可用的选项。这段代码生成了一个带有 rangeslider 和 hovertext 的交互式图表。rangeslider 允许您放大特定时间段,悬停文本提供有关该数据点的更多信息。该图表的静态图像如下:

An image of the interactive Campbell OHLC chart produced with Plotly. The rangeslider below allows you to zoom in on a time period.

A zoomed in version of the Plotly chart with a rangeslider and hovertext window open.

增长率

我用熊猫和 Plotly 制作了两个增长率图表。Pandas 的pct_change()方法计算行条目之间的百分比变化。我利用 Plotly 的线和分散函数创建了这个图表,代码如下:

The code for a Plotly growth rate line chart

您也可以向图中添加多条轨迹。我比较了 Campbells 的增长率和标准普尔 500 指数的增长率:

The Campbell Soup Company YTD growth chart with Plotly

The Campbell Soup Company and S&P 500 growth chart with Plotly

比较和总结

Matplotlib 和 Plotly 在数据科学家的工具包中都有它们的位置。Matplotlib 是高度可定制的,但是需要更多的编码和数据准备,这是非常耗时的。Plotly 用相对较少的代码创建了强大的交互式可视化。我更喜欢用 Plotly 制作 OHLC 图表。您可以根据自己的目的决定需要哪个库。

啤酒节:使用 Pandas、Matplotlib 和 Plotly 进行快速分析

原文:https://towardsdatascience.com/oktoberfest-quick-analysis-using-pandas-matplotlib-and-plotly-79778367a4c?source=collection_archive---------4-----------------------

啤酒节 2019 已经开始了!慕尼黑啤酒节是世界上最大的啤酒节,自 1810 年以来每年在慕尼黑举行。它从 9 月中旬或下旬持续到 10 月的第一个周日,持续时间为 16 至 18 天,每年有超过 600 万游客。🍺 🍺

Munchen.de 是慕尼黑市的官方门户网站 Munich 包含 140 多个数据集,涵盖经济、交通、旅游或文化等广泛主题。目前,越来越多的欧洲城市提供了开放的数据门户,允许公司、市民、研究人员和其他公共机构利用生成的数据。对于本文,我们使用了从 1985 年至今的慕尼黑啤酒节的数据。虽然大部分年份都没有(记得 1810 年开始的啤酒节!),该数据集提供了关于该节日在过去 30 年中如何演变的宝贵见解。

[## 慕尼黑啤酒节-慕尼黑啤酒节 1985 - 2018 -开放数据门户

十月节的日期是十月节的最后一天,也是十月节的最后一天…

www.opengov-muenchen.de](https://www.opengov-muenchen.de/tr/dataset/oktoberfest/resource/e0f664cf-6dd9-4743-bd2b-81a8b18bd1d2)

让我们开始吧!🍻

关于图书馆的信息

为了评估数据集,我们使用三个不同的 Python 库:Pandas、Matplotlib 和 Plotly。

  • Pandas 是一个用于数据科学Python 开源库,允许我们轻松处理结构化数据,例如 csv 文件SQL 表Excel 电子表格。它提供了以不同格式读写数据、执行探索性分析和清理数据(重塑数据集、处理缺失数据或合并数据集)的工具。
  • Matplotlib是一个 Python 2D 绘图库,可用于 Python 脚本、 Jupyter 笔记本IPythonshell 等环境中,生成高质量的图形。Matplotlib 提供了广泛的可视化,如直方图,条形图,散点图,箱线图,或饼图。
  • Plotly Python 图形库作为 Matplotlib 提供了广泛的可视化。但是,与 Matplotlib 不同的是, Plotly 提供的可视化是交互式的,更加直观。😉

在概述了本分析中使用的库之后,我们准备开始下一步:探索性数据分析和数据清理。

探索性数据分析和数据清理

****探索性数据分析包括分析数据集的主要特征,通常采用可视化方法汇总统计。目标是理解数据,发现模式和异常,并在我们执行进一步评估之前检查假设。

Munchen.de 下载 csv 文件后,我们可以使用Pandas . read _ CSV函数将其加载到 Pandas 数据框中,并使用 pandas 可视化前 5 行。data frame . head方法。****

数据集包含 8 列:(1)年份,(2)持续时间,(3)游客总数,(4)每日游客数,(5)啤酒价格,(6)啤酒消费量,(7)鸡肉价格,(8)鸡肉消费量。

数据类型不合适和缺少值是数据集最常见的问题。我们可以用 熊猫轻松分析这两者。data frame . info方法。该方法打印关于数据帧的信息,包括列类型、非空值的数量和内存使用情况。

检查数据集中是否有空条目的其他方法如下:

我们还可以使用熊猫来评估数据类型。DataFrame.dtypes 属性。这将返回包含每列数据类型的序列。

数据集不包含空值,并且数据类型是预期的类型,因此不需要重要的清理任务;但是,我们可以执行一些小的更改,以便于进一步分析数据集。

  1. 删除 besucher_tag(每日访客数)列,因为我们不会在评估中使用它。
  2. 将列名翻译成英语。
  3. 将年份设置为数据框的索引。以便于访问不同年份的信息。

执行更改后,我们可以使用数据轻松地得出结论。💪 🍻我们开始吧!▶️

回答问题并得出结论

探索性数据分析数据清理是让我们对数据集有所了解的步骤,并让数据集准备好使用它轻松得出结论。现在!我们准备使用数据集回答以下问题。****

在过去的 33 年里,啤酒价格是如何变化的?还有鸡肉价格?有倾向吗?

正如我们在下面的图中看到的,从 1985 年到 2018 年,价格稳步上升,2018 年的价格比 1985 年高出约三倍。

1985 年,我们只需 7.97 欧元就可以在啤酒节享用一餐。三十年后,我们需要几乎三倍多的钱才能在节日里享用一餐。💰

我们还可以使用 Plotly 创建一个交互式价格图!💚

我们可以观察到价格可以用一个线性关系来近似(在啤酒的情况下更准确)。稍后,我们将使用简单的线性回归来预测 2030 年的价格!

从 1985 年到 2018 年,啤酒消费量如何变化?还有鸡肉消费?有倾向吗?

下面的图表显示了从 1985 年到现在的啤酒消费量。

正如我们所观察到的,啤酒的消费量呈现出增长趋势。竖线表示啤酒节与德国经济节的庆祝时间一致。自 1996 年以来,这个节日每四年在 Theresienwiesen 啤酒节的同一时间举行一次。我们可以看到,2004 年、2008 年和 2012 年的小幅下降可能与庆祝这一节日有关。相反,2001 年和 2016 年啤酒消费量的显著下降可能与 2001 年的 9·11 恐怖袭击、2015 年 11 月的巴黎恐怖袭击和 2016 年的尼斯卡车袭击有关。游客数量在那些年(2001 年和 2016 年)有所下降,呈现 1985 年以来的最低值。

下面的图代表了从 1985 年到 2018 年的鸡肉消费量。我们不难观察到,鸡肉的消费量呈现下降趋势,同时也受到了 2001 年和 2016 年恐怖袭击的影响。****

从 1985 年到 2018 年,游客数量是如何变化的?有倾向吗?

我们可以很容易地使用折线图来分析访问者的数量。正如我们所观察到的,访问者的数量没有遵循任何趋势,从 5.5 到 7.1 不等。

所以,啤酒的消费并不是因为节日有更多的游客而增加,而是因为人们喝得更多。😆 🍻

巴伐利亚其他民间节日啤酒价格是否也在上涨?

啤酒节可能是巴伐利亚最著名的民间节日,但当然不是唯一的!🍻巴伐利亚人知道如何恰当地庆祝,他们在巴伐利亚的许多城市组织节日,不仅仅是在慕尼黑❤️!现在我们就来分析一下巴伐利亚其他著名民间节日的物价演变。在过去的几年里,价格也稳步上升了吗?▶️让我们看看!

为了进行这种分析,我们使用下面文章中的啤酒价格。

** [## 因此,他参加了巴伐利亚州的群众大会

bier preis-brems 在维也纳?慕尼黑-讨论了一个两人的问题

www.merkur.de](https://www.merkur.de/bayern/so-viel-kostet-mass-auf-bayerischen-volksfesten-7428217.html)

这篇文章包含了巴伐利亚 8 个不同的民间节日的信息。我们可以通过使用如下的 pandas.read_html 函数轻松下载文章中的表格:

该表包括:(1)节日名称,(2)节日日期,(3)游客数量,(4)组织者,(5)啤酒价格信息,以及(6)从 2008 年到 2016 年的啤酒价格演变。不好意思,文章是德语的!😊

我们只对分析啤酒价格感兴趣,因此我们可以创建一个只包含最后一列中的价格的数据框。这些价格必须在不同的列中,因为整齐的数据集包含放在自己单元格中的每个值。为了提取年份和价格,我们使用正则表达式和 re.findall( 模式字符串flags=0 ) 函数。该函数将一个字符串模式的所有匹配作为一个字符串列表返回。然后,我们为每个节日创建一个字典,其中的键包含年份,值包含啤酒的价格。创建词典后,我们可以将它们放在一个列表中。最后,我们用这个字典列表作为 熊猫的论据。DataFrame 函数,获得如下数据帧。

在将数据框可视化之前,我们必须对其进行一些修改。首先,我们必须修改所有列的数据类型,因为它们必须包含浮点数而不是字符串。然后,我们必须转置数据框,因为默认情况下,数据框索引是绘图的 x 轴,数据框的每一列代表可视化中的不同线。最后,我们包括 2008 年至 2016 年啤酒节的啤酒价格。

现在,我们已经准备好可视化巴伐利亚州不同节日的价格演变。正如我们所观察到的,巴伐利亚其他节日的啤酒价格也在上涨。然而,啤酒节的价格比其他民间节日要高,是达绍尔大众节最经济的一个。

大多数节日里啤酒的价格都很相似;因此,使用 matplotlib 进行清晰的可视化是不可能的。或者,我们可以像以前一样使用 plotly 库。这个库可以进行交互式绘图,允许悬停在点上,选择和取消选择线,以及放大/缩小。

我们还可以计算出不同年份和前几年啤酒价格的变化百分比。

该表显示,与其他民俗节日相比,啤酒节的价格上涨更加均匀,每年大约上涨 3%。其他民俗节日呈现不太统一的价格增量;然而,有些年份的增量比啤酒节的增量大得多。

plottly允许在地图上制作动画散点图,这样我们不仅可以看到不同年份的啤酒价格,还可以看到不同民间节日所在的地方。首先,我们必须在数据框架中包含庆祝节日的城市的纬度和经度。包含节日场地的准确纬度和经度会更准确,但是对于这个可视化来说,城市的纬度和经度是一个很好的近似值。

为了获得城市的纬度和经度,我们使用了 geopy。获得城市的位置后,我们将该信息包含在之前创建的数据框中。我们必须再次转置数据帧,因为我们希望节日成为帧的索引。

根据我们想要显示的可视化效果,数据框应该有这样或那样的形状。要使用Plotly Express函数 px.scatter_mapbox ,我们必须首先融化我们的数据框,将年份显示为一个变量。我们可以看一下 pandas.melt 文档来了解它是如何工作的。👌

现在,我们有了一个整洁的数据框来使用 px.scatter_mapbox 创建散点图。我再次鼓励你阅读 文档 来理解提供给函数的参数。

瞧!我们有散点图,在这里我们不仅可以看到价格,还可以看到从 2008 年到 2016 年的节日地点。💪

今年最受欢迎的帐篷里的啤酒价格是多少?

该信息再次从网页上获得。清理数据后,我们获得一个数据集,其中包含 2018 年和 2019 年的价格以及价格的百分比变化。

下图显示了价格的递增顺序。正如我们所观察到的,啤酒价格在 11.411.8 欧元之间,其中 Augustiner 更经济。

2030 年价格预测

价格上涨遵循线性趋势(啤酒价格更准确)。因此,我们可以创建一个线性回归模型来预测 2030 年的两种价格(鸡肉和啤酒)。为此,我们可以使用 scikit-learn 库中的 线性回归模型 ,如下所示:

根据线性预测模型,10 年后在啤酒节吃一顿饭将花费 28.33 €😮

关键要点

  • 在过去的 30 年里,啤酒节上啤酒和鸡肉的价格稳步上升。
  • 游客多喝少吃。啤酒的消费量呈现出逐年增长的趋势。相反,鸡肉的消耗是减少。消费受到 2001 年和 2016 年恐怖袭击的影响。那些年,很少有人参观这个节日。
  • 访客数量没有任何趋势,范围从 5.57.1
  • 巴伐利亚其他民间节日的啤酒价格也在上涨。Dachauer Volksfest 的价格是啤酒节的一半。如果你想喝醉,不想破产,就去达豪吧。😆它在慕尼黑附近!
  • 自 2008 年以来,啤酒节上的啤酒价格每年上涨约 3%。巴伐利亚其他民间节日的价格增长不太一致;然而,有些年份的增量比啤酒节要大得多。
  • ****啤酒节上的大帐篷今年提供的啤酒价格在 11.4€11.8€ 之间。
  • 如果价格继续上涨,到 2030 年,啤酒节(啤酒+鸡肉)一餐的价格将在 28€左右。

感谢阅读🍀**

omega|ml:以简单的方式部署数据管道和机器学习模型

原文:https://towardsdatascience.com/omega-ml-deploying-data-machine-learning-pipelines-the-easy-way-a3d281569666?source=collection_archive---------22-----------------------

部署数据管道和机器学习模型可能需要几周到几个月的时间,涉及许多学科的工程师。我们的开源数据科学平台 omega|ml 是用 Python 编写的,利用了 MongoDB,在几秒钟内完成了这项任务——只需要一行代码。

Photo by Ashkan Forouzani on Unsplash

部署数据&机器学习管道很难——不应该是

当谈到部署数据和机器学习管道时,有许多选项可供选择——其中大多数都相当复杂。截至 2019 年春天,最佳实践包括构建自己的应用服务器,以某种方式使用训练有素的机器学习模型的序列化版本,或使用部分自动化的工具构建 docker 映像,以及使用拥有一切的全面复杂的商业数据科学平台。

无论采用何种方法部署机器学习模型,这通常都不是数据科学家的核心技能。要做好这件事,需要对更接近软件工程和分布式系统,而不是机器学习和统计学的学科充满热情。

无论采用何种方法部署机器学习模型,这通常都不是数据科学家的核心技能

此外,当基础设施现成可用时,为什么还要构建新的基础设施呢?

omega|ml:你只需要一行代码

进入开源包 omega|ml ,这是一个生产就绪的数据科学框架,可以从笔记本电脑扩展到云。使用 omega|ml 部署机器学习模型就像这个 Python 一行程序一样简单,可以直接从您的 Jupyter 笔记本或任何其他 Python 程序中获得:

om.models.put(model, ‘mymodel’) # model is e.g. a scikit-learn model

无需更多麻烦,该模型可立即从 omega|ml 的 REST API 中获得,并可用于任何客户端以任何语言编写的预测:

GET [http://host/v1/model/mymodel/predict/](http://host/v1/model/mymodel/predict/`) + <json body>

这里的 < json body > 是一个包含列名和相应数据值的字典。一个模型是任何 scikit-learn 模型,其他框架如 Keras、Tensorflow、Pytorch 都可以通过使用扩展 API 轻松添加。

还有更多:数据接收、数据管理、调度&报告发布

模型部署不是从模型开始到结束,还需要数据、模型再训练和监控。为此,omega|ml 涵盖了完整的数据科学管道,从数据接收、数据管理、作业调度,到模型构建、选择和验证,再到在线报告和应用发布。所有这些都来自于一个易于使用的 API,它只需要一行代码就可以完成大多数任务,直接来自于 Jupyter Notebook。

模型部署不是从模型开始到结束,还需要数据、模型再训练和监控。omega|ml 涵盖了完整的数据科学管道—大多数任务只需要一行代码

例如,从 Python 获取新数据:

om.datasets.put(data, ‘mydata’) 
# data is a container object, e.g. list, dict or a pandas DataFrame

类似地,可以使用 REST API 获取数据:

PUT [http://host/v1/dataset/mydata](http://host/v1/dataset/mydata') + <json body+

也可以从 REST API 或 Python 客户端查询数据:

# Python 
om.datasets.get(‘mydata’, column=value)# REST API
GET [http://host/v1/dataset/mydata?column=value'](http://host/v1/dataset/mydata?column=value')

类似熊猫的数据帧:大于内存的数据帧

除了部署模型和数据管道之外,omega|ml 还为任何规模的列数据集提供了一个类似熊猫的 API,称为 MDataFrame ("M "一般代表大规模**,,具体代表 MongoDB )。虽然 MDataFrame 还不是 Pandas 的替代产品,但它提供了 Pandas API 的许多最有用的部分,如索引、过滤、合并和数据管理的行功能,以及描述性统计、相关性和协方差。

借助 MDataFrame,甚至比内存更大的数据集也可以轻松分析,使用 omega|ml 的集成数据和计算集群在核外训练和执行模型。默认情况下,利用 MongoDB & Python 的优秀分布式任务框架 Celery,它与 scikit-learn 的 joblib 很好地集成在一起,它还可以随时利用 Dask 分布式或 Apache Spark 集群
(托管版和商业版)。

借助 MDataFrame,使用 omega|ml 的集成数据和计算集群,甚至可以轻松分析大于内存的数据集、训练模型并在核外执行

请注意,存储在 omega|ml 中的数据集只受其存储层可用的物理磁盘空间的限制,而不受内存大小的限制。与 Spark 不同,omega|ml 的 MDataFrame 在处理开始之前不会产生预加载延迟,因为所有繁重的工作都由 MongoDB 完成。默认情况下,新数据是持久的,其他数据科学家可以随时使用。此外,多个用户可以同时利用集群,消耗许多不同的数据集,每个数据集或其组合都大于集群中可用的物理内存。

使用 MDataFrame,例如汇总数据,

mdf = om.datasets.getl('mydata')
mdf.groupby(['division', 'region']).sales.mean()

通过筛选、索引或列对数据进行子集化,

# by filter
query = mdf['column'] == value
mdf.loc[query]# by index
mdf.loc[‘value’]
mdf.loc[['value1', 'value2', ...]# by column
mdf['column']
mdf['column1', 'column2']

要执行由 MongoDB 执行的延迟过滤操作和计算,

# query on sales
mdf.query(sales__gte=5000).value# apply row-wise calculation
mdf.apply(lambda v: v * 2).value 

合并数据帧,

mdf1.merge(mdf2)

MDataFrames 也可以很容易地与存储在 omega|ml 中的 scikit-learn 模型一起使用,例如在使用计算集群时。

# mydata is a MDataFrame previously stored using om.datasets.put
om.runtime.model('mymodel').fit('mydata[^Y]', 'mydata[Y]')

omega|ml 的 Python 和 REST API 的完整文档可以在https://omegaml.github.io/omegaml/index.html获得。

特性&附加组件

omega|ml 包括一系列数据科学家工作区通常缺少的现成功能:

  • 使用类似熊猫的 API 的核外数据集
  • 直接从 Python 和通过 REST API 进行异步和预定模型训练、优化和验证
  • 集成的、可扩展的数据集群(基于 MongoDB)
  • 利用 Celery、Dask Distributed 或 Spark 的集成计算集群。

虽然 omega|ml 通过易于使用的 API 在笔记本电脑上运行良好,但其架构是为云可伸缩性和可扩展性而构建的,集成了 scikit-learn 和 Spark MLLib

许多附加组件使 omega|ml 在团队和组织中的协作变得可行:

  • 直接从 Jupyter 笔记本电脑(附件)中向商业用户分发 Plotly Dash & Jupyter 笔记本电脑
  • 类似于 Spark Streaming 的纯 Python 小批量框架(附加组件,没有 Scala/JVM/Hadoop 设置的复杂性)
  • 多用户角色和安全性(托管版和企业版中提供的附加组件)

一个可扩展的&可伸缩的架构

虽然 omega|ml 通过易于使用的 API 在笔记本电脑上运行良好,但其架构是为云的可伸缩性和可扩展性而构建的。它的核心 API 集成了 scikit-learn 和 Spark MLLib,使开发人员能够只用几行代码为任何机器学习框架(如 Keras、Tensorflow 或 Pytorch)构建扩展,同时保持 Python 和 REST API 的稳定 API。对于外部数据源,如亚马逊 S3 或其他对象存储,以及数据库,如 MySQL 或 Oracle,也是如此,它们可以很容易地作为扩展添加。

omega|ml architecture

利用 MongoDB 作为其存储层,omega|ml 可以水平扩展到任何大小的数据集,分布到任何数量的存储/计算节点,同时它没有内存需求,也没有所有内存堆栈(例如 Spark 或 Dask)的数据加载延迟,有效地结合了 MongoDB 的高性能混合架构,用于内存处理和分布式存储。

由于其集成的纯 Python RabbitMQ/Celery 计算集群,它提供了 Python 原生的无服务器功能,同时可以利用任何计算集群,如 Apache Spark 或 Dask Distributed。

欧米茄|ml 入门

从 docker 直接运行 omega|ml 开始(这是开源社区版):

$ wget https://raw.githubusercontent.com/omegaml/omegaml/master/docker-compose.yml
$ docker-compose up -d

接下来在打开浏览器 http://localhost:8899 打开 Jupyter 笔记本。您创建的任何笔记本都将自动存储在 omega|ml 数据库中,从而便于与同事合作。REST API 可从 http://localhost:5000 获得。

您还可以使用 omega|ml 作为现有 Python 发行版的附加包(例如来自 Anaconda)。在这种情况下,您还必须运行 MongoDB 和 RabbitMQ。

pip install omegaml

利用 MongoDB 的高性能聚合,omega|ml 可以水平扩展到任何规模的数据集。然而,它没有像 Apache Spark 或 Dask 那样的全内存堆栈的内存需求和数据加载延迟

了解更多信息

omega|ml (Apache License)建立在广泛使用的 Python 包之上,如 scikit-learn、Pandas 和 PyMongo。对 TensorFlow 等其他机器学习框架的扩展很容易通过一个定义良好的 API 来实现。

omega|ml 作为 docker-compose 的现成部署 docker 映像和软件即服务在 https://omegaml.io (目前处于测试阶段)提供。在私有或公共云上部署到 Kubernetes 的本地版本可以通过商业许可获得。有一个入门指南和一个指南笔记本来帮助你入门。

关于作者

Patrick Senti 是一名自由职业的高级数据科学家和 Fullstack 软件工程师,拥有近 30 年的专业经验。他最初建立了 omega|ml 的核心,作为他在 2014 年推出的智能城市和下一代移动创业公司的内部数据科学平台,其中的挑战是在分布式数据科学家团队之间协作处理大型核外数据集,并部署数百个机器学习模型,以便在云中运行并集成到智能手机旅行应用程序中。

全方位基准图像分类(以及更多)

原文:https://towardsdatascience.com/omni-benchmarking-image-classification-and-much-more-5e0d08bb2a7?source=collection_archive---------37-----------------------

Performance/accuracy exploration of image classification models on hardware ranging from IoT-class to server-class platforms from the submissions to the 1st ACM ReQuEST tournament at ASPLOS’18.

图像分类是研究最大似然模型的效率/质量权衡的流行领域。例如,最先进的 FixResNeXt-101 模型在 ImageNet 验证集上达到了 86.4%的前 1 准确率,但 829M 参数仅适用于集群使用。作为另一个例子,适用于移动设备 MobileNets-v2 型号系列的 Top-1 精度范围从 6.1M 参数的 75.0%到 1.7M 参数的 45.5%。

请注意,“集群”和“移动”之间的区别纯粹是定性的。就功耗而言,差异很容易达到一千倍或一百万倍。然而,执行 定量 评估可能相当棘手。

诚实地回答你自己,你上一次能够在几分钟甚至几小时内拿着一份令人兴奋的新报纸转一圈是什么时候?我们的意思是,对于真正的:下载所有的工件(代码、数据等)。),安装所有依赖项(如 TensorFlow)和依赖项的依赖项(如 Java 和 Bazel),移植到新平台(Android,有人吗?)、用新数据集测试等等?

从来没有发生在我们身上。一百万年后也不会。我们最多能在几天内完成。更常见的是,几周之内。即使假设这张纸真的有藏物。(令人失望的是,7 中只有 1 毫升的纸有。)

现在,想象一下打开一篇论文,描述一种在移动设备上进行图像分类的新方法,这种方法很方便地带有一个工件。想象一下,您可以在阅读介绍的同时,在几分钟内安装并定制该神器,并在手机上再现实验,同时得出结论?只需点击一个图,就可以与社区共享您的结果,并立即看到任何异常和异常值,这可能需要进一步的调查。

是的,这听起来像是一场梦。然而,我们相信快速的工件和知识共享对于加速 ML/系统的研究和开发是至关重要的。今天,我们描述了我们与社区一起朝着这个梦想迈出的一小步。

ACM ReQueEST:可再生质量/高效系统锦标赛

2018 年,我们 ASPLOS 联合举办了第一届ACM ReQuEST 锦标赛,我们邀请社区提交论文,并附上完整的工件(代码、数据、脚本等)。).我们的目标是让每一个提交的工件通过完善的工件评估过程。换句话说,我们关注的是实际的定量再现性而不是提交材料的纯粹新颖性。

我们对提交的涵盖所有级别的 ML/软件/硬件堆栈(一位分析师称之为 全方位基准)的多样性感到非常惊讶:

  • 型号: MobileNets,ResNet-18,ResNet-50,Inception-v3,VGG16,AlexNet。
  • 框架和库: TensorFlow,Caffe,MXNet,Keras, Arm 计算库,cuDNN, TVM ,NNVM。
  • 平台: Xilinx Pynq-Z1 FPGA,Arm Cortex CPUs 和 Arm Mali gp GPU(Linaro hikey 960 和 T-Firefly RK3399),树莓 Pi 设备的农场,NVIDIA Jetson TX1 和 TX2,以及亚马逊、微软和谷歌云中的英特尔至强服务器。
  • 数据类型: 8 位整数,16 位浮点(半),32 位浮点(浮点)。

对于每一个工件,我们都创建了一个自动化的、可定制的、可重复的集体知识工作流,以统一评估准确性、延迟(每张图像的秒数)、吞吐量(每秒图像数)、峰值功耗(瓦特)、价格和其他指标。然后我们在 GitHub 上发布了统一的工作流程,并在 ACM 数字图书馆上添加了快照。

我们决定在一个公开的交互式仪表盘上显示所有结果,而不是宣布一个获胜者或者点名羞辱。使用仪表板,您可以应用自己的标准来探索解决方案空间,并寻找帕累托最优解决方案(例如,找到达到所需精确度的最节能的解决方案)。基本上,如何通过自己的喜好和要求解读结果,就看你自己了!

视力

从纯粹的基准测试角度来看, ReQuEST 可以被视为 MLPerf 开放部门的先驱,在这里提交者对他们使用的工作负载和系统没有限制,只要他们的提交是可复制的。

然而,我们的长期目标是创建可重用 ML/SW/HW 组件的开放库。这将允许研究人员在他们的可复制和交互式论文中建立这样的组件,同时最终解决跨最新软件和硬件的基准测试技术的棘手问题。

我们预计,最终社区将对完整的 ML/SW/HW 堆栈进行众包基准测试、共同设计和优化(例如,参见我们的 Android 众包基准测试演示),这反过来将大大减少现实产品所需的工作和上市时间。

如果你想了解更多,请联系并加入我们成长中的社区

作者

安东·洛克莫托夫divideti的联合创始人兼首席执行官。研究员、工程师和企业家,热衷于优化使用宝贵的资源,如计算机系统…和人才。

Grigori Fursin 是 CodeReef.ai 的联合创始人兼首席技术官。开源贡献者和可复制性专家,清理人工智能创新中的混乱。

全方位基准目标检测

原文:https://towardsdatascience.com/omni-benchmarking-object-detection-b390cc4114cd?source=collection_archive---------10-----------------------

Performance/accuracy exploration with 12 object detection models, 5 TensorFlow backends and 6 batch sizes.

ML/systems 社区对研究效率/质量权衡非常感兴趣。在 CVPR 2017 年的一篇综合论文中,谷歌研究人员专注于探索最先进的物体检测卷积方法的速度/精度权衡。相当有益的是,研究人员还发布了几十个经过训练的模型,作为 TensorFlow 模型动物园的部分。这些模型很容易运行和评估,因为它们有标准化的输入和输出张量。

虽然我们发现对象检测动物园是我们系统设计和优化工作的一个很好的起点,但我们不禁想知道我们无法从动物园的自述文件或论文中提取的几个方面。

首先,自述文件提供了在 NVIDIA TITAN X 卡上的执行时间。然而,多年来 NVIDIA 已经发布了 TITAN X 的几个版本。虽然我们可以从论文时间表中猜测该卡是基于 Maxwell 架构的,但也有各种其他关于 GPU 驱动程序、CUDA 版本、TensorFlow 版本、使用的批量大小等的猜测。最重要的是,我们现在主要感兴趣的是我们自己的硬件上最新软件的性能,而不是(ML/SW/HW)考古!这包括运行在 CPU 与 MKL 和 GPU 与 TensorRT 进行比较。

其次,自述文件提供了 COCO 2014 验证集(“minival”)子集的准确性,而我们感兴趣的是 COCO 2017 验证集(例如,在 MLPerf 中使用)的准确性。此外,一些最精确模型的“低建议”变体比基线模型快 1.3-3.4 倍。然而,由于没有提供准确性,所以不清楚权衡是什么。

我们意识到同样的问题对更广泛的 ML/systems 社区有很大的兴趣,我们想提供帮助。我们不仅仅是满足自己的好奇心,而是更热衷于让我们的方法可被他人复制和扩展,这样社区就可以众包跨其他平台、模型、数据集、批量等的评估。这就是我们所说的全方位标杆管理

上面绘制的是我们对 12 个对象检测模型、5 个 TensorFlow 后端和 6 个批次大小的性能/精度探索的结果。这篇文章是关于我们如何获得它们的。

型号选择

我们意识到我们没有时间测试动物园中的所有型号,所以我们选择了 11 种不同的型号,从快速的 SSD-MobileNet 到准确的 Faster-RCNN-NAS。我们选择了 5 个基于 fast-RCNN 的模型:4 个可用的“lowproposals”变体,以及 fast-RCNN-Inception-v2。我们还选择了 6 种基于 SSD 的型号:SSD-ResNet50-FPN、SSD-Inception-v2、SSD-MobileNet-v1 的 3 种变体(非量化、量化、FPN)和 SSDLite-MobileNet-v2(适用于移动设备的更轻版本的 SSD)。根据自述文件,通过这种选择,动物园模型的地图精度在 18%和 43%之间,执行时间在 30 毫秒和 540 毫秒之间。最后,我们添加了一个 YOLO-v3 的重新实现。

可定制性

为了以统一的方式评估模型,我们设计了一个模块化和可定制的 Python 应用程序:用户可以插入不同的数据集和模型(可能带有定制的预处理和后处理),并选择一个受支持的后端(CPU、CUDA、TensorRT)。

应用程序提供了支持特定模型功能的“钩子”。我们发现了四个这样的挂钩:

  • 预处理:将图像加载到张量中,并为推理准备张量(转换、整形、调整大小)。
  • 加载模型:加载一个冻结的模型图(如果需要,转换为 TensorRT),并准备一个会话进行推理。
  • 获取张量:获取给定模型的输入/输出张量名称。
  • 后处理:将图形的输出转换为检测(边界框和对象)。

对于动物园的标准化模型,我们实现了一些默认使用的功能。然而,对于 YOLO-v3 模型,我们创建了带有特定接口的定制函数。我们还实现了批处理,包括将图像调整到特定于模型的大小。

实验设计空间

我们感兴趣的是测量被检查模型的准确性(地图和召回在 COCO 2017 验证数据集上的 5000 张图像)和性能(执行时间或每秒图像)。

我们沿着两个维度评估绩效:

  • tensor flow 的后端配置:
  1. 为 CPU 预建(通过 pip 安装),它抱怨不支持 AVX2 FMA 指令。
  2. 基于支持 AVX2 的 CPU 资源构建。
  3. 使用 CUDA 从 GPU 的源代码中构建。
  4. 根据 GPU 的源代码构建,TensorRT 配置为静态构建优化图形(即不知道图像大小)。
  5. 根据 GPU 的源代码构建,TensorRT 配置为动态构建优化图形(即,一旦给出第一幅图像)。
  • 批次大小 : 1(无批次),每批次 2、4、8、16 和 32 张图像。

再现性

我们使用自动化、可移植和可定制的集体知识 (CK)工作流程来使我们的实验具有可重复性和可扩展性。

首先,CK 安装所有的先决条件:具有不同后端的 TensorFlow(见上文)、模型和数据集,同时解析所有的依赖项(例如,当从源构建 TensorFlow 时,使用 Java 和 Bazel)。因为 CK 负责所有的先决条件并跟踪它们的版本,所以很容易将整个实验设置移植到不同的机器上。

其次,CK 单独配置每个实验:模型、后端配置和批量大小。因为 CK 存储实验配置(先决条件、环境变量的值等)。)除了统一 JSON 格式的实验结果,我们还可以使用 Jupyterpandas 等流行工具方便地分析和可视化实验结果。

第三,我们编写 CK 脚本来执行所有实验参数的笛卡尔乘积。在我们的研究中,这导致了 360 个性能实验(12 个模型,5 个后端,6 个批处理大小)和 24 个准确性实验(12 个模型,1 个 CUDA 后端,模型内部调整大小和批处理所需的外部调整大小)。

易用性

我们创建了一个封装了所有安装步骤的 Docker 容器(因为即使 CK 处理了整个实验设置,按照自述文件进行安装也会非常乏味)。虽然容器化引入了一些开销,但我们发现它们对于我们的目的来说是可以接受的(我们将在以后的文章中报告)。

重要的是,将 CK 和 Docker 结合起来使用,任何人都可以通过几个步骤开始运行实验,使它们真正具有可移植性和可重复性。

结果

下面,我们分三部分介绍我们的一些结果:

  • 首先,我们在 COCO 2017 验证数据集上展示了受检模型的精度
  • 其次,我们使用不同的后端和批量大小来分析性能
  • 第三,我们展示了一个综合的设计空间探索图,其中最佳性能/精度权衡位于帕累托边界

(全部结果可在 Jupyter 笔记本中获得。)

我们的实验平台是一个惠普 Z640 工作站,配有一个英特尔至强处理器 E5–2650 v3CPU(2014 年第三季度推出),以及一个 NVIDIA GeForce gtx 1080 GPU(2016 年在 Q2 推出)。我们的 Docker 镜像是基于来自 NVIDIA 的 TensorRT 19.07 镜像,带有 CUDA 10.1 和tensort5 . 1 . 5,以及 TensorFlow 1.14。

准确(性)

首先,我们展示了整个贴图,以及大、中、小物体的贴图,假设只对输入图像进行了内部尺寸调整(稍后会详细介绍)。

最准确的模型是 Faster-RCNN-NAS,达到了 44%的整体图。通常,一个具有良好整体贴图的模型在所有三个对象类别中都表现良好。然而,也有一些例外:SSD-Inception-v2 在大型对象上有第二好的成绩,但在中型和小型对象上表现相当差;相反,YOLO-v3 在大型物体上得分第二差,但在小型物体上排名第四,在中型物体上表现良好。

在小对象上表现不佳是基于 SSD 的模型的一个众所周知的问题。然而,具有特征金字塔网络 (FPN)特征的 SSD-ResNet50 和 SSD-MobileNet-v1 型号在小型物体上处于第二和第三位(总体上处于第二和第四位)。

由于 COCO 数据集中的图像具有不同的形状和大小,因此需要调整它们的大小以适应模型输入大小。动物园中的所有模型都在图形中嵌入了调整大小功能。然而,为了实现批处理,图像必须在图形之外调整大小(因为一个批处理中的所有图像必须具有相同的大小)。这可能会损害准确性,如下所示:

SSD、YOLO 和 fast-RCNN-NAS 模型都包括一个 fixed_shape 调整大小层。使用此图层的大小进行外部调整大小对精度几乎没有影响(在某些情况下,地图会有所改善)。

然而,其他基于更快 RCNN 的模型包括一个 keep_aspect_ratio 调整大小层。对这些模型强制进行“固定形状”外部尺寸调整会对精度产生不利影响(在某些情况下,地图下降超过 10%)。(如果您知道如何解决这个问题,我们很乐意听取您的意见!)

表演

我们将性能报告为每秒处理的图像(或帧)数量(FPS)。每个实验我们做 10 次。在柱形图中,柱形图显示 10 次运行的平均 FPS,而触须显示标准差。(络腮胡子紧说明性能稳定。)

首先,我们展示了 12 种型号和 6 种批量的 CUDA 后端性能:

毫不奇怪,最准确的模型 Faster-RCNN-NAS 也是最慢的,为 3 FPS。速度最快的模型是 MLPerf 推理中使用的量化 SSD-MobileNet,根据批量大小,它比 fast-RCNN-NAS 快 15-25 倍。这表明我们基于 Pascal 的 GPU 比基于 Maxwell 的 GPU 大约快两倍,后者用于获得自述文件中提供的性能数据。然而,如果性能优势并不主要归因于体系结构的改进呢?

通常,批量越大,性能越高。但是,对于某些模型,批处理可能会对性能造成不利影响。例如,CPU 上的 Faster-RCNN-NAS 速度最快,批处理大小为 1,这可能是因为内存需求高:

事实上,这个模型甚至无法在批处理大小为 16 和 32 的 GPU 上运行。(这个 GPU 只有 8 GB RAM。)而且 TensorRT-Dynamic 后端只能以批处理大小 1 运行。

非量化 SSD-MobileNet 型号在 CPU 上运行速度更快:

然而,量化的 SSD-MobileNet 模型在 GPU 上的运行速度更快(比非量化模型快近 1.5 倍):

这两个模型都包含在 MLPerf 推理 v0.5 中,都是在 32 位浮点中执行的。量化模型可能受益于 GPU 内存中更好的数据组织。

对于所检查的模型,我们发现在静态模式下使用 TensorRT 几乎没有比使用 CUDA 更好的效果。我们认为这是因为静态模式下的 tensort 通常会退回到 CUDA,因为它不知道张量形状。然而,一旦给出第一幅图像,动态模式中的 TensorRT 会在运行时创建一个优化的图形。在下图中,红/蓝条代表 CUDA/TensorRT-批量逐渐增加时的动态性能:

一般来说,TensorRT 比 CUDA 快,但 YOLO v3 是个例外。我们猜测这是因为它是一个更新的型号,NVIDIA 尚未针对 TensorRT 进行优化。我们还注意到,对于最慢的模型,TensorRT-Dynamic 几乎总是失败(返回内存不足错误)。

探测

最后,我们在一个图上展示了性能和精度:

不同的颜色代表不同的型号。不同的标记代表不同的后端。标记的大小表示从 1(最小)到 32(最大)的批次大小。

请注意,对于大多数基于更快 RCNN 的模型,由于批处理的外部调整大小,精度会有所下降。我们可以用内部调整大小获得的“理想”精度来绘制相同的数据点:

黑点显示的是帕累托边界:最准确最慢的模型更快——RCNN-NAS 在左上角;最快的是右下角的量化 SSD-MobileNet-v1(无论是性能还是精度,都要优于非量化 SSD-MobileNet-v1)。

如果我们考虑小对象的 mAP,情况会发生变化,其中基于 SSD 的 FPN 模型几乎与 Faster-RCNN-NAS 一样好,但其他基于 SSD 的模型在 mAP 低于 4%的情况下表现极差:

对于大型对象,SSD-Inception-v2 和 SSDLite-MobileNet-v2 达到了帕累托边界:

结论

我们已经展示了我们的全方位基准测试 12 个流行的对象检测模型的结果,这些模型使用 5 个 TensorFlow 后端和 6 个批量大小,适用于小型、中型和大型对象。

很明显,没有一种适合所有人的最佳配置。甚至 CPU 有时也比 GPU 快(对于 SSDLite-MobileNet-v2 和非量化 SSD-MobileNet-v1)。较大的批处理大小并不总是保证更好的性能(1 是更快的 RCNN-NAS 的最佳值)。最后,最佳模型选择可能取决于所选择的精度度量和实时约束。

这就是为什么我们相信 omni-benchmark 对于设计高效可靠的计算机系统是非常有价值的!已经为第一届 ACM 请求锦标赛进行了 omni 基准图像分类,我们愿意合作来对任何其他 ML 任务进行 omni 基准测试。

如果你想了解更多,请联系并加入我们正在成长的社区

作者

伊曼纽·维塔利是意大利米兰理工大学大学的博士生。他的研究兴趣包括硬件架构和异构系统上的应用程序自动调优。

Anton Lokhmotov 博士是 dividiti 的创始人之一。他致力于优化利用宝贵的计算资源和人才。

向神经网络添加负反馈突触

原文:https://towardsdatascience.com/on-adding-negative-recurrent-synapses-to-a-neural-network-25a28409a6f2?source=collection_archive---------9-----------------------

深度神经网络中的缺失环节

向神经网络添加负向循环突触的特殊之处在于,它们在网络中引入了内部状态。

以这个简单的触发器电路为例:

如果两个输入端 AB 都有效,那么在这个电路中可能存在两种互斥状态——或者 C 有效而 D 无效,或者相反。该示例取决于是 A 还是 B 先被激活。但是如果我们不让时间决定哪个状态被激活呢?如果一个目标函数测量每个状态的强度会怎样?这样,我们可以系统地搜索网络中的最佳整体状态。

那有什么好处呢?如果我们仔细观察通常输入神经网络的数据,如文本或图像,我们会注意到这种状态出现得非常频繁。例如,句子'米像沙子一样飞',它允许两种同样可能的解释,或者下面的图像显示一个年轻或年老的女人取决于你当前的解释。

基本上,对最高等级状态的搜索可以被视为对文本或图像的最有意义的解释的搜索。这非常类似于语法分析器执行的搜索。然而,与语法分析器相反,神经网络能够处理文本中包含的任何类型的信息,而不局限于句法信息。神经网络的另一个优点是,它们能够总结许多微弱的提示和信息,并使用它们来提高预测。

那么这样一个目标函数会是什么样子呢?如果我们可以促进我们的神经元的激活值来确定目标函数呢?如果我们简单地将每个兴奋性神经元的活化值相加,我们就可以比较网络中不同的状态,看看哪一个是最理想的。请注意,对于纯粹基于逻辑的电路,这是不可能的,因为没有渐进的权重来增加正确状态的选择。这是大多数基于非单调逻辑的方法面临的一个大问题。
在我们继续看解释搜索之前,我们必须首先更仔细地检查一些网络属性。我们首先需要的是我们神经元的激活函数φ,它对于所有的负激活值都是无效的;否则我们将无法真正抑制神经元的激活。我们可以使用 ReLU 函数或者 tanh 函数的正半部分。

这个网络的另一个特征是它需要两种类型的神经元。第一种是兴奋性神经元,本质上是连接的,能够通过等待一整套输入特征的联合激活来识别模式。兴奋性神经元也是允许接收负输入突触的神经元,因此可能被其他神经元抑制。第二种神经元类型是抑制性神经元,本质上是分离的。他们能够将兴奋性神经元分组。如果这些抑制性神经元的输出通过一个负性循环突触反馈给它所有的输入兴奋性神经元,那么组内所有的兴奋性神经元就会互相抑制。注意,在这种循环反馈回路中,兴奋性神经元不允许抑制自己。这类似于深度神经网络中的 softmax 层;只是我们现在有了一个明确的突触模型,它明确地说明了哪些神经元受到了哪些神经元的抑制。

搜索

那么,实际的解释搜索是什么样子的呢?因为只有兴奋性神经元被允许有负反馈突触,我们只需要在搜索时考虑那些。然而,在我们进行真正的搜寻之前,我们必须将兴奋性神经元分类,以保留所有非周期性突触的相依性。在搜索过程中,我们将需要对我们尚不知道其状态的循环连接的未来神经元做出假设。所以对于每个兴奋性神经元,我们将在假设所有循环输入对当前神经元具有最积极的影响(选择)或最消极的影响(排除)的情况下计算和传播激活值。这也是我们搜索树中每个节点的两个可能的分支。当回溯到父节点时,当然必须恢复网络的先前状态。

现在,你可能认为搜索空间的大小很容易失控,但事实并非如此。实际上,数据中并没有多少不同的状态。当然,您需要确保不会一次又一次地评估相同的状态,但是这可以通过缓存以前的决策来轻松防止。只有当缓存的决策所依赖的神经元状态之一被修改时,缓存的决策才需要失效。如果网络的各个部分不相互依赖,它们也可以相互独立地进行评估。这种搜索的另一个优点是,突触权重提供了大量关于哪些状态应该被评估以及哪些状态应该被忽略的启发性信息。

目前,我们正在一个拥有约 2000 万个神经元的网络上使用这种算法,对于一个给定的文档,平均有几千个神经元被激活。一份文件的处理时间约为 100 毫秒至 200 毫秒。当然,如何训练这种类型的网络仍然是一个悬而未决的问题。目前,我们使用的是一个手工制作的模型,该模型来自于大量的命名实体和短语,但当然,这个网络需要一个真正的训练算法。然而,在我看来,这种训练算法不应该使用梯度下降或反向传播。误差信号在通过几层神经元后变得过于模糊。训练算法的一个更好的起点可能是 Kullback-Leibler 散度,它应该允许我们通过最大化关于给定神经元的输入数据的信息增益 来 训练兴奋性神经元。这种方法的一个优点是它完全不受监督,因此不依赖于标记数据。

这个算法是作为 AIKA 开源项目的一部分实现的。来源可以在 GitHub 上找到。实现这个例子的 JUnit 测试用例可以在这里 找到 。这篇文章所遗漏的是对文本或图像的关系结构的处理。如果你想了解更多关于培训这种类型的网络,看看这篇 文章

成为“更好的”数据科学家

原文:https://towardsdatascience.com/on-becoming-better-data-scientists-47c257b0df3d?source=collection_archive---------20-----------------------

我最近读了阿图尔·加万德的书 Better ,他在书中用医学故事提供了如何在工作中做得更好的见解。在这里,我试图将 Gawande 的见解放在数据科学的背景下,因为我相信它们同样适用于我们的领域。

Source: pixabay

加万德将医学上的成功归因于三个核心品质——d的智慧的正确的独创性。他用几个个人故事和观察来说明这些品质。例如,为了证明勤奋的重要性,他讲述了一个关于一个人在印度寻求根除脊髓灰质炎的故事。2003 年,在印度南部地区发现了一例脊髓灰质炎病例,该地区被认为通过免疫接种消除了脊髓灰质炎。唯一可行的选择似乎是扫荡行动,该地区所有易感儿童都需要接种疫苗。这包括组织 41000 名医疗专业人员和 18000 名疫苗携带者在 3 天内为 420 万儿童接种疫苗!Gawande 将这场看似不可能的运动的成功归功于参与运动的人们的勤奋。

为了说明第二个品质——做正确的事情——Gawande 讨论了诉讼和保险纠纷是如何让医生在美国的工作变得非常困难的。他认为,如果医生屈服于这些困难,那么他们作为医疗专业人员做有意义工作的动机就不复存在了。Gawande 还涵盖了死刑注射使用的敏感问题。一些参与处决的医生感到有义务安慰被处决的囚犯。Gawande 承认这种推理的有效性,他认为这些专业人员更多地是代表政府而不是囚犯的利益行事,因为囚犯没有权利拒绝医生的治疗。

关于独创性的话题,他举了一个维珍尼亚·阿普伽的例子,他发明了一种有意义的技术,用简单的 10 分制来衡量新生儿的状况。阿普加的创新最终导致了“产科包”,大大降低了婴儿死亡率。独创性不仅在于发明更好的技术,还在于开发更好的方法来利用这些技术。为了阐述这一点,Gawande 向我们讲述了 Warren Warwick 的故事。Warwick 是一名儿科医生,他利用囊性纤维化(CF)研究的结果,将 CF 患者的护理提高到了一个新的水平。Warwick 的设施帮助患者比美国任何其他 CF 设施活得更长,他们通过持续监控和改进帮助患者的方式来实现这一点。

Gawande 认为在医学领域表现优异的三个品质同样适用于其他职业。下面,我在应用人工智能/数据科学的背景下讨论这些品质。直到最近,人工智能一直生活在研究实验室中,但现在它正在学术界以外受到关注。现在,将人工智能研究转化为可用产品和服务的重任落在了数据科学家的肩上。我相信数据科学家可以从 Gawande 的书中学到知识,以加速和保证该领域的成功。

论勤奋:

我看到了印度根除脊髓灰质炎的故事和数据科学家在工作中被期望完成的事情之间的相似之处。在这两种情况下,资源是稀缺的,时间是最重要的。今天的数据科学家背负着沉重的期望。人们期待他们改革医疗保健,革新交通运输,改善教学。这些是几个世纪以来社会面临的挑战。他们很难相处!它们似乎和根除脊髓灰质炎的目标一样遥不可及,而成功完成这些任务的唯一途径就是勤奋和有远大的抱负。

论做对:

我分享两个故事,说明为什么“做正确的事”在数据科学领域至关重要。第一个故事是关于一个叫做 COMPAS 的风险评估软件。COMPAS 是一个人工智能系统,可用于预测罪犯从惩教机构释放后犯下新罪行的可能性。它被美国各地的法院用来通知保释决定。2015 年,ProPublica 发表了一项研究,发现 COMPAS 对非洲裔美国人有偏见。研究发现,COMPAS 高估了非洲裔美国人再次被捕的可能性,而低估了白人再次犯罪的可能性。

第二个故事是关于科技巨头亚马逊在 2014 年开发的一款招聘工具。该工具的目的是自动扫描收到的简历,并选择最佳雇员。它是通过观察过去 10 年的候选人建立起来的。路透社报道称,到 2015 年,亚马逊意识到该工具存在性别偏见。它一贯偏爱男性候选人,而不是女性候选人。

这两个故事展示了当前基于人工智能的工具的缺点。这种工具旨在帮助人们完成决策任务。他们通过从历史数据中学习人类行为来做到这一点。然而,在学习明确的与任务相关的人类行为的同时,这些工具也学习历史数据中存在的隐含偏见。例如,由于亚马逊在过去 10 年中雇用的男性可能多于女性,招聘工具建议招聘经理继续这样做。这些故事也清楚地表明,数据科学家的技术能力不足以让他们发挥最佳水平。为了“做正确的事”,他们还需要意识到社会中存在的偏见。这种偏见将不可避免地出现在人工智能工具使用的数据中。了解社会偏见的数据科学家能够更好地从这些工具中检测和消除偏见。

论匠心:

我分享吴恩达的故事。正如我们大多数人所知,安德鲁是人工智能领域最有影响力的人之一。在这里,我讨论一下他在领导谷歌大脑团队时,在谷歌推广深度学习的策略。安德鲁在他的人工智能转型剧本中分享了这个故事。那是谷歌和其他公司怀疑深度学习技术的时候。安德鲁的策略是通过寻找对公司有意义但不是最重要的项目来推动新技术的发展。他希望他早期的项目成功,而不是最有价值。这一巧妙的策略帮助谷歌大脑团队展示了深度学习在谷歌语音和谷歌地图应用中的成功。这一成功导致了深度学习在谷歌其他产品中的采用,并影响了该技术在世界其他地区的广泛采用。

人工智能现在已经开始在学术实验室和技术公司之外建立自己的地位。安德鲁向我们展示了一个在我们各自的行业中率先采用人工智能的战略。我真的相信,数据科学家可以从 Gawande 的书中学到知识,以加速和保证该领域的成功。要做到这一点,我们需要勤奋来应对来自社会的巨大期望,我们需要独创性来为我们在公司中导航。此外,我们需要意识到我们的数据和算法中存在的偏见,以提供道德、伦理和无偏见的产品和服务。

成为一名数据科学产品经理

原文:https://towardsdatascience.com/on-being-a-data-science-product-manager-5c8baf42e0a7?source=collection_archive---------8-----------------------

来自一位数据科学家同事的七条建议

Photo by airfocus on Unsplash

几个月前,我辞去了 Nulogy 数据科学家的工作,Nulogy 是一家位于多伦多的 SaaS 公司。在我过去的 6 个月里,数据科学团队从 POC 阶段过渡到实际构建公司的第一个机器学习产品。与任何产品团队一样,我们需要一个人来帮助管理我们的数据产品生命周期的剩余部分。也就是说,我们需要一个数据科学产品经理(DS PM)。而且,由于当时组织的不同变化,我不得不暂时戴上那顶帽子。以下是我对如何成为一名成功的 DS PM 的学习。

1.培养对机器学习的理解

我有一个朋友,最近在加拿大魁北克开始工作。魁北克是该国说法语的省份,作为一个只会说英语的加拿大人,他很难适应,直到他学会了法语!我想你明白我的意思了…

作为一名 DS PM,您必须能够识别可以利用机器学习的机会。此外,您需要能够与您的数据科学家和工程师就他们的日常工作进行对话。如果不理解机器学习的构建模块,就很难与你的团队建立共鸣,也很难为你的团队辩护。幸运的是,网络上有无数的免费资源可以帮助你快速上手(coursera、medium、youtube 等。).

2.了解模型评估

选择正确的模型评估度量和最小可接受误差是机器学习中最具挑战性的两项任务。手头任务的极高精度可能是不必要的(甚至是不可能的)。另一方面,高误差幅度对企业来说可能是非常昂贵的。因此,您不能脱离这些对话,应该主动了解评估指标和可接受的误差范围。例如,如果 ML 产品正在替代一个已经存在的过程,您可以使用当前的过程误差率作为基线。

总的来说,评估标准将由可用的数据、使用的模型和手边的应用决定。要更详细地了解评估指标,请阅读这篇文章

3.对实验持开放态度

决定机器学习产品何时准备好发货是一项具有挑战性的任务。当测试误差较低且不存在过度拟合时,我们是否应该发运模型?在宣布模型可供所有客户使用之前,我们是否应该先在生产环境中用客户群的样本测试模型?我真的没有答案(如果有人看这篇文章有,请在评论里分享),很可能要在时间、成本和准确性之间做出权衡。这里的现实是,机器学习产品的生命周期依赖于大量的实验,所以我的建议是你在产品路线图中包括实验时间。

4.首先考虑一次试运行

因为很难确定机器学习产品是否已准备好发货,所以首先考虑试运行。一顿软午餐对于发现盲点非常有用,比如无声特征,或者收集顾客的反馈。

B2B 环境中的试运行可能与 B2C 环境中的非常不同。在 B2B 环境中,您可以使用客户群的代表性样本来测试 ML 产品。在这里,您可以与您的客户建立合作伙伴关系,请求产品反馈,以换取发布时的 SaaS 折扣。另一方面,在 B2C 环境中,你可以进行 A/B 测试来验证你的产品是否产生了预期的结果。

5.当你发货的时候,你还没有完成

你已经建立了你的机器学习产品。干得好!然而,你还远远没有完成。除了您传统的部署后 PM 职责之外,还有一些事情您应该知道。

首先,你需要有一个应急计划。确保设置了监控和警报系统,以便在您的模型性能开始下降(是的,它会下降)时向您和您的团队发出警告。如果您有一个更通用的(尽管可能不太准确)备份模型,甚至是一个基于规则的系统,准备在预测失败时部署来代替您选择的模型,这可能是理想的。其次,围绕模型性能、误差和延迟,为客户设定明确的预期。您的 SLA 也应该反映这一点。最后,您需要确定模型需要多长时间重新培训一次以维持它的 SLA,以及升级重新培训的模型需要多长时间。如果您预见到应用程序停机的需要,这一点尤其重要。查看这个资源以更全面地了解 ML 工程最佳实践。

6.采用敏捷思维,而不是特定的敏捷框架

Scrum 或类似的方法在软件社区相当流行。然而,并非机器学习周期的所有阶段都接受定时或 t 恤大小的用户故事。至少,在研究或 POC 阶段,大量的实验是必要的,并且在该阶段采用限制较少的敏捷框架(如看板)可能是理想的。

7.你仍然是首相

除了熟悉机器学习概念和机器学习产品生命周期之外,你作为 DS PM 的角色与普通 PM 没有太大区别。您仍然需要构建一个 backlog,提交发布计划,开发业务案例,并作为您的团队与内部和外部涉众的接口。

将这一切结合在一起

如果你想从这篇文章中学到什么,那就是你需要对你的 DS 团队的不同成员的角色和职责有一定程度的理解和共鸣。不用说,在传统的软件环境中也是如此。如果你理解你的同事正在经历什么,你就会开始思考如何帮助他们取得成功。也就是说,你不必一个人去做。如果你表现出你在努力学习,你在团队里,他们会回报你,在你前进的每一步都在你身边。祝你好运!

论规范公司

原文:https://towardsdatascience.com/on-canonical-companies-741b7d1c5aa8?source=collection_archive---------24-----------------------

创建通用记录系统

Photo by Verne Ho on Unsplash

在信息技术和科技创业中,我们谈论“记录系统”。这是一个系统,它是可能存在于其他系统中的特定数据的来源。“系统或记录”是真理的最终来源。这是数据的规范记录。

我们经常把这些系统说成是一家公司存放数据的地方,这些数据以后可以作为事实的唯一来源。一家现代公司将拥有一系列记录系统,包括来自 SAP、Microsoft、Oracle、Intuit、Workday、Salesforce、Atlassian 等公司的产品。

随着我们进入物联网和人工智能的联合和分布式世界,需要成立新的公司来存储和处理这些名称之上的下一抽象层的公共数据。这是通用的记录系统。

随着我们进入物联网和人工智能的联合和分布式世界,需要成立新的公司来存储和处理这些名称之上的下一抽象层的公共数据。

这是通用的记录系统。

这种模式的关键在于,公司或系统的价值来自于创建和管理在独立机构之间共享的公共数据池。

该值分为两部分:

  1. 它们是存储和共享公共数据的地方
  2. 它们是一个可以从共享数据流中获取共同智慧的地方

这个模型对于一些公司、用例和数据来说没有意义。但是,随着大量数据的价值变得越来越大,共享数据以创建新用例的创造性将变得太大。

而且,根据自己的数据创建自己的功能(而不是 USR 公司的客户)是不值得的。你所在行业的网络数据将比你自己的孤岛数据更有价值。

你所在行业的网络数据将比你自己的孤岛数据更有价值。

通用记录系统(USR)是什么样子的?

USR 的特征是:

  1. 多个机构/公司拥有他们愿意共享的有用数据
  2. 整个行业或更广泛的群体的数据都有价值
  3. 一个(或一小组)公司用来存储公共数据
  4. 根据行业和使用情况,它还可以通过处理它可以访问的数据来实现学习循环

当前通用记录系统的示例

商务沟通数据: 消息路径
我和其他几个人一起构建的应用程序将为商务沟通模式创建一个通用的记录系统,这将使所有客户受益。从表面上看,MessagePath 的使命是促进全球商业交流。但我们的不同之处在于,我们将成为优化商业写作的典范。单个公司不需要跟上营销、销售、支持、行业和法律语言的细微差别。他们只会使用(或通过 API 插入)MessagePath。

我们有 4 个 API 客户,他们知道获得 MessagePath 提供的语言模式的唯一方法是使用我们的 API。没有理由建立自己的语言数据集。在我们的空间里只有我们和几个规范公司的空间。这是因为价值在于我们在所有客户活动中学到的东西(语言练习和模式)。在一家公司里尝试这种方法不会给你足够的价值去竞争。

AI、bot、工作流数据:botch ain
我联合创办的最后一家公司是一家区块链公司。区块链可能是一种构建通用记录系统的好技术。BotChain 允许拥有机器人和工作流的公司共享一个公共平台来存储机器人身份、机器人动作和机器人决策。不需要每家公司一个一个的去搞清楚如何互相操作。插入 BotChain 的将是机器人交易和身份的通用记录系统。(注:有一家公司会举办 BotChain 相关活动,但产品 BotChain 是开源的分布式系统。)

医疗数据:BlocHealth
波士顿 BlocHealth 的团队(我提供建议)正在将所有核心医疗执照/资格文件的通用记录放在区块链上。

未来通用记录系统的例子

无人驾驶汽车美国标准局 我和致力于下一代交通工具的工程师们进行过一些私人谈话。在未来(现在开始发生),当一辆汽车学习新的高清测绘数据时,制造那辆汽车的公司也将学习。但是这就足够了吗?生命垂危,我认为为了所有移动/后勤的利益,应该共享一些数据。这就是地图和自动驾驶数据的通用记录系统的用武之地。

我认为我们需要重新思考政府几十年了。政府内部的许多抽象层都有大量与政府相关的数据。有些是公开的,有些是私人的。我怀疑它的组织和共享是否能改善政府并降低政府成本。一个简单的例子——不管你把什么前端放在上面,一个 USR 都应该包含城市中与犯罪、地图、坑洞等相关的所有数据。

防御迫在眉睫的人工智能威胁

开创通用记录系统的另一个好处是它解决了几个迫在眉睫的问题:

数据隐私+人工智能 隐私权利较少的其他公司(如中国)可能会因其对人口数据的访问而走在美国前面。这是他们人工智能的训练数据。

解决方案:我提议建立公共(或公共/私人)通用记录系统,以确保隐私并允许数据集的创新。我不知道这看起来像什么。关于规则和加密还有很多问题需要思考。我对这种潜在用途的同态加密感兴趣。如果我们能做到这一点,我们将允许自由社会确保隐私,并在人工智能领域进行创新。

“失控”AI 的问题 人们谈了很多有情 AI 的危害。我认为这将是一个问题,但不是很快。真正的问题将是以我们意想不到的方式优化的无感知人工智能。想想大自然。它不是有知觉的,但它是一个复杂的系统。而影响现实世界的复杂系统(像 AI 会做的越来越多)是危险的。

解决方案:通用记录系统可以让我们在非最优决策(以及这些决策带来的不良后果)发生之前记录、预测和阻止它们。

下一步 了解下一步的最好方法是开始构建。我很期待看到我们需要建立哪些公司来管理未来 10 年的公共 NLP、AI 和物联网数据。他们中的一些人已经在这里了。

Will Murphy 是 MessagePath 的创始人,他试图创造未来。他还帮助初创公司和企业创新。
推特:@威尔墨菲

按需最后一英里运输

原文:https://towardsdatascience.com/on-demand-last-mile-transportation-ea4a3b725b31?source=collection_archive---------26-----------------------

具有位置智能的实时路线优化

近年来,我们看到了众多市场平台的出现,这些平台将客户与各种各样的产品和服务联系起来。这方面的明显例子有优步邮局斯图亚特,它们允许你订购基本上任何东西的取货和送货服务,从乘车、食物,甚至是小包裹,并在不到一两个小时内送到。

从物流的角度来看,有效运营这一服务是一项挑战,而且在该行业面临激烈竞争的情况下,这一点越来越重要。由于问题的性质与标准物流公司的问题非常不同,传统的物流解决方案不再适合规划这种服务。如果我们看看任何一家正规的第三方物流(3PL)公司,他们通常会在某个截止时间之前接受第二天的交付订单,以便他们有足够的时间规划第二天的路线。这与随需应变服务不同,在随需应变服务中,新订单必须(几乎)实时处理和分配,而没有未来可能到来的订单的信息。

众所周知,这两个问题都很难解决,尤其是如果我们想确保我们的运营处于最佳状态,或者至少比我们的竞争对手更好。这就是空间数据科学可以发挥作用的地方,因为它允许我们建立模拟现有条件的数据模型,为我们提供关于现有约束、低效分配等更多信息的见解。

传统与按需最后一英里运输问题

虽然这两个问题都很难解决,但每个问题的复杂性可以在非常不同的阶段发现。传统的最后一英里运输问题是一个车辆路线问题(VRP) ,一个组合的优化问题,从算法设计的角度以及计算的角度来看,其复杂性是众所周知的。与实时按需运输问题相比,它们的明显优势在于,关于订单和司机可用性的所有信息都是预先知道的,通常不需要立即找到解决方案。这使得更容易找到接近最优的解决方案。有几个算法被设计来解决这个问题,有几个实现了这些算法的解决方案,包括商业的和开源的。

另一方面,实时按需运输问题是较小的问题,因为可用的信息较少,但需要立即做出响应。在这里,我们只知道在我们检查系统状态之前发生了什么,并且大部分都不能改变,因为它已经被交付了。由于缺乏未来信息和无法改变过去的决定,这可能导致非常低效的路由。克服这种对问题的狭隘看法成为主要挑战。

下面的地图很好地展示了这种狭隘的观点,在这里我们只能看到每 3 分钟时间窗口内的订单。一旦时间窗口过去,我们就不能改变我们所做的任务,我们也不知道会有什么样的订单。

在物流文献中,对于如何克服这种狭隘的视野问题有共识:增加决策的灵活性,并试图获得尽可能多的未来信息。第一点是尽可能推迟决定,做出容易撤销或改变的决定。第二个问题涉及使用其他数据科学技术,如预测,以拓宽我们的视野。

这个问题很难归类为一个问题类别,因为它取决于所提供服务的复杂性,也取决于我们希望在优化路线方面走多远。它可以从一个“简单的”分配问题(如果我们只需要考虑与窄时间窗相关的信息)到一个 VRP(如果我们需要考虑在算法的当前迭代之前司机已经做了什么)。

接下来的主要挑战是能够计算所有需要的成本,并设计一种算法,能够在几秒钟内找到接近最优的解决方案。还可能有其他挑战需要克服,例如计算在我们开始一天的工作之前我们需要多少司机,我们需要什么车队,或者计算接下来几分钟/几小时的天气预报。

这两种情况下要解决的问题的巨大差异使得很难(如果不是不可能的话)将传统的物流解决方案用于按需运输问题。

设计和改进优化算法

以下示例显示了如何应用优化来解决按需运输问题的第一步,以及这样做所获得的好处。这里有一个场景,我们将应用两种初始方法来解决这个问题。

以下假设是为了提高演示文稿的清晰度。但是,请记住,问题可能会变得更加复杂,这取决于我们希望在优化我们的功能方面走多远,以及稍后描述的所提供服务的需求。

  • 我们的目标是将距离最小化,我们的主要衡量标准将是行驶的总距离。这可以很容易地改变为其他标准,如最小化交付时间或所需的车队,仅举几例。
  • 每个订单都是相互独立的,也就是说,它们不能合并,因此,除非骑手空闲,否则在完成当前交付的订单之前,他们无法开始订单。
  • 骑手在空闲之前不会被分配到新订单。
  • 每个骑手的车队类型都是一样的。
  • 在算法的每次迭代中,我们总是有足够多的空闲骑手来分配订单。当然,这在现实生活中不会发生,而且会增加问题的复杂性。

在下面的地图上,我们可以看到周四下午 7:00 到 7:05 收到的订单。我们可以看到取货和送货地点、为每个订单计算的最佳路线,以及空闲的或在时间窗口内的某个时间点可用的骑手/司机。我们将重点关注这 5 分钟的时间窗口,以便更容易显示和比较结果。

步骤 1:起点-终点矩阵

为了解决任何路径问题,我们需要构建一个成本矩阵,表示从地点 A 到地点 B 的成本,或者在此处显示的情况下,将位于 A 点的骑手分配给提货地点在 B 点的订单的成本。在我们的示例中,该 OD 矩阵将是从骑手地点到订单提货地点的距离。

所述,构建 OD 矩阵对于按需运输问题来说是一个更大的挑战,因为需要实时计算这个矩阵。

贪婪算法

这通常是解决这个问题时遵循的第一种方法。该算法在每次收到订单时被激活,它搜索最近的空闲骑手并将订单分配给该骑手。在这种情况下,我们采用最接近的标准,但根据所提供的服务或业务目标,也可以是任何其他需要优化的标准。

这种算法被广泛使用,因为它很容易实现,并理解和分析其结果。此外,在推出新业务时,客户体验通常是主要指标之一,因此希望尽快处理每个订单是有意义的。然而,这并不一定意味着顾客总能得到更快的服务。

使用该算法解决问题后,我们得到了乘客从出发地点到上车地点的总距离 181.67 km。

在下图中,我们可以看到使用线框绘制的算法执行的前六个步骤,其中黑点是空闲骑手的位置,绿点是订单的提货位置。这种可视化非常强大,因为它可以帮助快速识别我们算法中的低效之处。

Figure 1. First six iterations of the greedy algorithm

批量分配算法

如前所述,改进作业的一个关键因素是尽可能地增加信息和灵活性。扩大我们的视野并获得更多信息的一个选择是推迟订单分配,每 n 分钟运行一次算法。我们越推迟越好,因为我们会有更多的信息。

下图显示了每分钟收到的订单数。

Figure 2. Number of orders per minute

每分钟运行一次算法意味着订单将不得不等待(最多)一分钟才能得到处理,这最初不会对客户体验产生重大影响。事实上,我们会看到一些订单甚至会提前交付。

算法每分钟都会被激活,它会考虑最后一分钟收到的所有订单并进行分配。这意味着它将有多个订单要分配。为了充分利用我们所有的信息,我们将把它作为一个指派问题来解决。

有专门为这个问题设计的算法,比如匈牙利算法。通常,这些算法是为问题的非常具体的情况而设计的,当问题开始需要复杂的特征时,很难改进它们。这就是为什么我们将使用线性规划,或者更具体地说整数线性规划来解决它。这项技术将使我们能够适应未来的变化或增加问题的复杂性。

使用这种批量分配算法解决问题后,我们得到的总行驶距离为 159.10 km ,也就是说,我们的目标指标提高了13%

如果我们用两种算法比较第一分钟(从晚上 7:00 到 7:01)收到的订单上完成的任务,我们可以看到一些很大的差异。例如,如果我们查看地图的东北部分,我们可以看到使用贪婪算法完成的效率非常低的分配,而使用批量分配算法完成的分配效率要高得多。这要归功于通过推迟任务完成的时间来获得更多的信息。

同样,能够将两种算法做出的决策可视化是非常强大的:

Figure 3. Comparison of assignments done by the greedy algorithm (left) and the batch-assignment algorithm (right) for the orders received within the first minute

后续步骤

前面的两个算法只是面对这个问题时通常遵循的第一个自然步骤。然而,问题的复杂性通常要求更多的步骤。

如上所述,在问题的每一次迭代中拓宽可用信息是至关重要的。一个非常有用的步骤是考虑在接下来的 30 到 60 分钟(或者更多时间,取决于服务的长度)内可能发生的事情。这将是非常有益的,有一些需求的预测,以避免分配将远离高需求地区的车手。这可以通过识别哪些骑手不应该被分配给交货地点远离高需求区域的订单而容易地合并到批量分配模型中。此外,这些信息可以提供给骑手,这样他们就知道空闲时应该去哪里,以确保他们被分配更多的订单。

下面的地图显示了从现在起一个小时后需求预计发生的位置,以及闲置的骑手。根据他们离预期需求较高的地区有多远,他们将被赋予不同的优先权。

除此之外,还有其他的改进可以提高作业的效率和质量。这些改进在很大程度上取决于所提供的服务类型。

  • 优化标准。在我们的示例中,我们将距离作为要优化的度量。然而,我们可能会添加额外的标准,始终牢记在算法的每次迭代中必须计算成本。一些例子可能是时间、利用率(这对于购买和/或维护车队成本高昂的公司尤其重要),以及客户和骑手体验。
  • 根据服务的使用频率匹配客户的质量,并根据客户的意见和交付效率匹配骑手的质量。
  • 合并订单(如优步池)
  • 通过尽可能推迟分配来创建更大的批处理。例如,对于递送小包裹,5 分钟可能就够了。

从算法的角度来看,将这些标准整合到我们的模型中是一项复杂的任务。能够可视化我们测试的不同算法所做出的步骤和决策,对于非常耗时的任务来说是一个非常强大的工具。在这里,可视化工具可以提供巨大的帮助。

本文原载于 CARTO 博客

设备上的机器学习:Android 上的文本生成📝

原文:https://towardsdatascience.com/on-device-machine-learning-text-generation-on-android-6ad940c00911?source=collection_archive---------10-----------------------

Photo by Pereanu Sebastian on Unsplash

结合 GPT-2、TensorFlow 和 Kotlin 的力量,在移动设备上实现最先进的自然语言处理

在拥抱脸,我们的目标是解决和民主化自然语言处理(NLP)。目前,生产中的大多数模型都是在服务器上远程运行的,例如谷歌的搜索服务器。尽管如此,移动设备上硬件的改进和对隐私的日益关注使得它们越来越适合离线运行

本文的目标是给出一个完全在设备上运行的用于文本生成的 Android 应用程序的高级视图。代码在这里:https://github . com/hugging face/TF lite-Android-transformers/tree/master/gp T2

What we’re going to build 🤓

第一部分:将 GPT-2 转换为 TensorFlow Lite 格式

GPT-2 是 2019 年发布的一款车型,其自然语言生成能力(NLG,NLP 的一个子集)令人印象深刻,以至于最大版本的发布被推迟了几个月。你可以用 这个搞笑(吓人?)工具 我们发布。在这个应用程序中,我们将使用最小版本的模型。它的发电能力不如最大的那台令人印象深刻,但它的大小(500MB 6GB)使它更适合移动使用!

在能够在设备上运行之前,我们需要将它转换成合适的格式TensorFlow Lite (TFLite)。为此,我们可以运行以下 Python 脚本:

tf-nightly” and “transformers” libraries need to be installed in your environment. You can also try it directly in your browser using this colab notebook.

这个脚本使用了我们的🤗Transformers 库导入“原始”模型,然后将其转换为 TFLite 格式。注意脚本的第 15/16 行:在运行转换之前,我们使用 TFLite 指定我们想要将模型的权重(参数)量化为半精度浮点格式。这导致我们转换后的模型的最终大小为 237MB,即原始“输入”模型大小的一半🎉。不利方面?精确度损失极小,但考虑到节省的存储空间,在移动设备上绝对值得!

我们可以通过将权重转换为 8 位整数表示形式来进一步压缩我们的模型,结果只有 128MB。但是我们对这个版本的测试显示在设备上要慢得多。因此,我们更喜欢在这里使用半精度浮点版本。你仍然可以通过改变默认模式来试验我们的应用程序的 8 位版本。

第二部分:将转换后的 GPT-2 模型集成到 Android 应用程序中

既然我们已经转换了我们的模型,我们可以专注于实际构建我们的应用程序。GitHub上有完整的源代码,所以这里我只关注最有趣的部分。

在 Python 脚本中,我们指定(第 6/7 行)我们的模型将接受一个形状为 [1,64]二维整数数组作为输入,即类似这样的内容,其中内部数组包含 64 个元素:

[[142, 34, 100, 535, 30234, 45, 2934, ...]]

但是我们在现实生活中将要拥有的是一个字符串,对应于当前文本。因此,我们需要将该字符串转换成整数,又称为 记号 。粗略地说,我们可以说,一个令牌是我们的字符串的一部分的数字表示。

令牌也是模型作为输出返回的内容。模型的每一次运行都允许我们确定文本的下一个标记,然后我们将它与前一个文本一起传递给我们的模型进行下一次运行,等等

我们需要一些东西来把我们的字符串转换成记号,再把记号转换回字符串。这就是记号赋予器的作用。记号赋予器的两个主要功能通常是编码解码。

Full implementation of the Tokenizer available here

encode 函数将我们的起始/前一个文本作为参数,使用正则表达式对其进行解析,然后将每个字符转换为特定的表示。它最后应用一个字节对编码 (BPE)算法,由于有了模型词汇表,该算法的输出被映射成整数。🤯

decode 函数执行相反的操作,将标记映射到它们的词汇表示,然后将这个表示解码为最终的字符串。

现在我们知道如何编码和解码我们的文本,我们可以调用我们的模型!这是下面的生成功能的作用:

Click here to see the full implementation

该函数的输入是初始文本和我们想要生成的令牌数(,即我们的模型被调用的次数)。第一步是对我们的文本进行标记。

还记得我们说过模型的输入是一个形状数组【1,64】吗?我们需要去掉之前的文本标记,只保留最后的最大值。那是我们的输入。表示下一个令牌的生成只依赖于这 64 个之前的令牌,忽略任何之前的令牌

当我们转换我们的模型时,我们可以指定一个更长的序列长度,但是这将意味着更多的推理计算,减慢我们的应用程序。这是我们这一代人在速度和“质量”之间的权衡。🤔

我们还需要创建数据结构,我们的模型将使用它的输出。我们的模型有许多输出,但是我们只对第一个“预测”感兴趣。

val predictions = Array(1) **{** Array(SEQUENCE_LENGTH) **{** FloatArray(VOCAB_SIZE) **} }**

当谈到多维数组时,我们在 Kotlin 的表达能力方面达到了一个极限;下面是它在 Java 中的样子:

float[][][] predictions = new float[1][SEQUENCE_LENGTH][VOCAB_SIZE]

我远不是一个 Java 迷,但是右边的表达对我来说似乎更容易读懂!

我们终于可以——了!—通过调用 TFLite 解释器来运行我们的模型:

tflite.runForMultipleInputsOutputs(arrayOf(inputIds), outputs)

一旦解释器填充了我们的“预测”数组,我们需要确定将是我们的“下一个”令牌。这样做有许多不同的方法;这里我们首先使用 Top-K 过滤,选择 k 更高的预测。然后,我们应用一个 Softmax 函数来获得这些值的概率分布,然后通过多项式采样最终选择“那一个”。

第三部分:借助 Kotlin 协程,以用户界面友好的方式与活动交互

现在是时候将我们的模型链接到应用程序的接口了!在设备上运行 GPT-2 等模型,即使是量化版本,也需要计算资源。如果我们做错了,我们可能会在模型运行时以界面冻结而告终,这对用户不太友好!😱

为了避免这种糟糕的结果,我们将使用 协程 ,这是在 Kotlin 中进行非阻塞编程的一种非常好的方式。这是我们(几乎)完整的 GPT2Client 类,它是从我们的主活动加载的 ViewModel :

For full implementation, check here

该类首先需要加载我们模型的所有资产,并初始化 TFLite 解释器。为了在不阻塞 UI 的情况下做到这一点,在 init中,我们启动了一个新的协程,这要归功于viewmodelscope . launch。在这个协程中,我们通过调用 3 个" load" 方法来加载我们的模型资产。以下是负载模型的签名:

private suspend fun loadModel() = **withContext(Dispatchers.IO)** **{** // Load the model file and initialize the interpreter with it... **}**

这里重要的是带有上下文的(调度程序。IO)部分。我们说我们想在一个不同于主线程的线程上执行这个方法,这里使用一个为 I/O 操作设计的线程(更多细节见这里)。

通过 viewModelScope.launch 创建协程的“妙处”在于它将自己的生命周期与 ViewModel 的生命周期联系在一起。它确保当视图模型被清除时,协程被取消!🙌

然后,当用户点击应用程序中的“触发自动完成”按钮时,执行 launchAutocomplete 方法,创建另一个协程,我们将从其中调用我们的模型。

fun launchAutocomplete() {
    autocompleteJob = **viewModelScope.launch** **{** initJob.**join**()
        autocompleteJob?.**cancelAndJoin**()
        _completion.value = ""
        generate(_prompt.value!!)
    **}** }

在这个协程中,我们首先确保资产的初始化( initJob )已经完成,然后对潜在的先前模型运行( autocompleteJob ),做同样的事情,如果还在运行,我们就取消它。然后我们可以调用我们的生成方法:

private suspend fun generate(text: String, nbTokens: Int = 100) = **withContext(Dispatchers.Default)** **{** val tokens = tokenizer.encode(text)
    repeat (nbTokens) **{** // Run the model...
        // ... tokens.add(nextToken)
        val decodedToken = tokenizer.decode(listOf(nextToken))
        _completion.postValue(_completion.value + decodedToken)

        **yield()**
    **}
}**

用于此方法的调度员不是调度员。IO 因为我们在这里不做任何 I/O 操作,而是一个更通用的 调度程序。默认 使用共享后台线程的公共池

这个方法另一个有趣的部分是yield()方法调用在结束时重复块。这就是允许该方法检查最终取消的原因。没有它,就不可能取消,我们必须等到整个一代结束后才能释放资源!☠️ 这里我们在每次令牌生成后检查取消。

检查取消的另一种方式是检查 isActive 属性的值

由于使用了 LiveData 结构(我们的完成属性),完成的文本然后“自动地”显示在应用程序中。🧙‍♀️

就是这样!在拥抱脸,我们相信我们只是处于人工智能在设备上运行的时代的开始。随着一方面专用硬件和相关驱动程序和框架的不断发展,另一方面量化和提取等技术的不断发展,我们智能手机的功能有望拥有光明的未来,允许以更高效和更高性能的方式运行更复杂的模型。

如果你想要更多的 Android 例子,你可以检查整个库。我们还发布了一个回购协议,其中包含 iOS 的模型和应用,利用了苹果特有的 CoreML 框架。如果您对更深入的最新 NLP 感兴趣,我们的 🤗变形金刚 库来了!

关于减少高峰时间

原文:https://towardsdatascience.com/on-eliminating-rush-hours-cdadd3fddcc3?source=collection_archive---------22-----------------------

改变三种社会制度如何能带来更轻松、更环保的生活

Rush Hour along Detroit’s Gratiot Avenue in the 1940s

在讨论全球变暖时,每个人都谈到系统性变化;很少有人提出实际操作的方法。在这里,我展示了我在过去几个月里从事的一些研究的结果,这是重新思考我们需要参与的那种社会系统的初步步骤,以减轻气候变化的冲击。

简而言之:交通夺走了我们所有神圣的东西。当我们的道路系统无法处理高峰需求和非高峰使用之间的差异时,就会发生这种情况。无论是工作日还是周末的高峰时段,交通拥堵的一个原因是我们的社会通常按照标准的时间表运行。有趣的是,在我们的电网中也有类似的问题。这两种类型的拥堵都是高峰需求问题的两个具体例子,高峰需求源于两件事:许多人一起生活在同一地区,以及缺乏明智的协调。

降低不同社会系统高峰需求的一个方法是重新划分我们集体安排时间表的时间和空间。

在重新划分时间方面,我们可以通过让人们自愿在周五到周六、周六到周日和周日到周一之间循环度过周末来减少周末的拥挤。通过明确抵消人们在 10 分钟或 15 分钟内“朝九晚五”的工作时间,我们可以减少每天的高峰时间。

就重新划分空间而言,当城市通过一系列半小时或 15 分钟宽的“微时区”开始一天的工作时,抵消可能会减少电网的峰值需求——我对 15 分钟电力负荷概况数据的初步分析支持了这一结论。虽然还需要进一步的研究,但对这些系统性时间表调整的讨论和实施有可能形成一个我们都可以参与的基层气候变化努力。最后,就实施而言,大学校园可能是检验这些想法的理想缩影。

更长的插图版本:

1。简介

交通是城市生活中最突出、最令人头疼的现实之一,在地球上的每个城市中心都很常见。我们都知道,道路拥堵不仅仅局限于每天的高峰时段——周末交通也困扰着城市居民。

例如,湾区居民经常在夏天开车去纳帕、索诺玛或约塞米蒂,在冬天去太浩湖度周末。他们不仅发现他们的目的地很拥挤,回来的路上交通也很糟糕。虽然从旧金山到太浩湖的旅程在不堵车的情况下大约需要 3.5 小时,但在堵车的情况下可能需要 12 个小时。

在我们的道路系统中,每日高峰时间和周末交通是“高峰需求拥挤”的实例;从抽象的层面来说,这是每个社会系统的问题。类似的事情也发生在我们的电网、供水和排污网络、公共交通系统、海滩和博物馆停车场等等。大多数人在相似的时间以相似的方式使用社会系统,这意味着所讨论的系统必须被设计为处理高峰和非高峰使用之间的巨大差异。

2。各种系统中的峰值需求示例

考虑一个停车场每天对停车位的需求。以下是 2018 年圣莫尼卡市中心停车场平均 24 小时利用率的图表,按周末和工作日分列:

Average relative 2018 Downtown Santa Monica hourly parking lot demand. The X-axis is “hours from midnight” and the Y-axis is “percent full.”

常识、经验和这个图表告诉我们两件事。首先,当圣莫尼卡停车系统有能力处理它的高峰时间版本时,它是工作的。其次,这座城市同时受到激励,在最拥挤的日子里拥有足够的容量来处理大部分人群,同时避免建设过多的额外容量。

以电力系统中的“高峰时间”为例,下面是 2019 年 4 月 29 日加州电网的需求图。再次注意最高点和最低点之间的差异:

Unlike fixed-supply parking structures, electrical supply can be adjusted to meet changes in demand, provided the infrastructure can handle the load. CA partially relies on solar (and wind) power during sunny (and windy) hours; it buys electricity from non-renewable sources in the evenings.

在英国,电网高峰需求拥堵的一种类型被称为“电视接收当许多人观看同一电视节目或体育赛事,并利用广告时间打开冰箱泡茶时,就会发生这种情况。

British TV Pickups during a 1990 Semifinal Soccer / Football match. Source.

高峰需求成为一个问题的原因是,最昂贵的电力是在需求高的时候从燃煤和燃气调峰电厂购买的

相当于高峰时间的拥堵影响的不仅仅是市政道路和电力系统。我们都熟悉下班后或周日下午杂货店里的长队,或者当几架国际航班都计划在五分钟内起飞时,海关的队伍变得非常非常长。截至 2012 年,美国人每年花费大约 370 亿小时排队等候。从某种意义上来说,拥挤是居住在人口稠密地区最不希望出现的情况之一。

有趣的是,需求高峰发生的一个原因是,我们都出生在一个围绕 a)一个时间表和 b)同一个时钟建立的系统中。我们认为这种安排是可行的,所以我们微笑着忍受它,尽管前一种假设并不是绝对必要的,更好的解决方案也是可能的。

3。重新定义问题

首先,我想说一下为什么我们会有现在这个系统。我们都在同一时间表的主要原因的一种说法是,这样我们每个人都可以像我们想见的人一样休息相同的时间。另一种说法是我们使用或工作的服务、机构和空间(银行、餐馆、舞厅、打字机修理店、糕点店等)。)都是根据彼此的时间表建立的。但考虑到这些事情是由人来管理或参与的,在某种程度上,第二个短语使用不同的词来表达与第一个短语相同的事情。

为了便于说明,请允许我将事情过于简单化。让我们假设我的社交网络仅由五个非常亲近的人组成——我的父母、一个浪漫的伴侣和一个最好的朋友。在下面的可视化中,我是人“0”

我希望所有人和我的五个联系人有相同的休息时间,所以我们都协调工作相同的时间。很好,到目前为止,没问题。当我们把这种礼貌扩展到我的五个人的五个关系中的每一个时,问题就出现了。

在这个简化的社会中,每个人都严格地与另外五个人联系在一起,我们可以很快让数百万人分布在数千平方英里的范围内,他们似乎都必须按照相同的时间表工作。如果一个人想改变他们的时间表,那么整个网络,锁在一起,将被迫立即改变。然而,庞大的网络规模确保没有人会自己改变,整个网络的同步性是高峰时间的主要原因。

正如我所提到的,减少拥堵和高峰时间包括寻找放松网络锁步的方法。

形象地说,如果有办法划分小组(用绿色和蓝色的线表示)并给他们分配不同的“时间表”,高峰时间可以减少。在下面的图表中,绿线左边的所有人都有弹性工作,做服务员,周一和周二休息。也许蓝线右边的人都从 7:30 工作到 3:30,帮助缓解高峰时间。

The more we can break up the synchronicity across the network, the more rush hours will be reduced.

4。通过调整周末减少每周交通流量

“Saint Monday, or the people’s holiday — №2. — A picnic at Hampton Court” (Source.)

200 年前,官方的西方周末只有一天:人们周日休息,以便去教堂做礼拜。非正式地,许多人(包括本杰明·富兰克林)第二天也翘班,并称这种做法为“守圣·星期一”

从企业主的角度来看,也许真正重要的是他们的员工平均每周工作五天,而不一定是五天。假设这是真的,那么就有可能改变周末的时间,从而减少交通以及工作日和周末的拥堵。然而,我们仍然想保留周末的一个主要功能,那就是和其他人有相同的休息时间。

考虑下面的循环时间表模式:6 天工作周和 2 天周末,接着是 4 天工作周和 2 天周末,然后是 5 天工作周和 2 天周末,接着又是 6 天工作周,等等。

Each group follows the 6–4–5 workday pattern offset by one “week,” just like singing a round.

为了便于讨论,让我们假设一个理论城市的一半人自愿开始六天工作周,另一半人自愿开始五天工作周。每三个周末,两组都有相同的两天假期,在另外两个周末,他们有一天的重叠。这种轮流重叠让每组中的每个人都有机会见到他们的朋友。

有了这个计划,两组人总是在周日休息,每三个周末休息两天。更重要的是,三分之二的周一和三分之二的周五,开车上班的人减少了 50%。理论上,每个人周末的一半时间,也就是三分之二的时间,可能是一半拥挤。

从零售商、餐馆、剧院、主题公园、购物中心和其他目的地的角度来看,周末有效地扩大了:在三天分开的周末,它们都变得不那么拥挤,但它们没有看到参观它们的总人数减少。从个人的角度来看,这些地方仍然受欢迎,但不是拥挤不堪。周末和工作日交通减少,通勤更容易,每个人都有更多的自由时间和安心。事实上,如果一部分人保留传统的周一至周五的工作周,这个计划实际上更有利。

也没有必要严格定义小组成员,一旦你自愿加入其中一个时间表,你就不能切换到另一个混乱的时间表,或者正常的 M-F 时间表。相反,人们可以在每个三周的期末四处走动:重要的是,我们把自己的时间表调得恰到好处。

没错,围绕人们的需求和义务(比如他们孩子学校的时间表)工作将会是障碍。然而,如果交替学校或年级是在这两个时间表之一,送孩子上学可能不那么令人担忧。

一旦对周末的假设有了正确的认识,下一个问题就是最佳的作息时间和休息日。使用点( )表示非工作日,除了 6 4 5 和 5 6 4 重复日程之外,第三组可以遵循 4 5 6 重复日程。这个更极端一点,但是保留了“周日休息”的成分,进一步减少了周末的拥堵。将这些放在当前的 5 5 时间表之上,所有 9-5 人的工作,现在有四个潜在的时间表。每一个额外的时间表都有助于缓解拥堵。[1]

5。通过多班制减少每日高峰时间

在上一节中,我探讨了如果我们放弃周末必须与周六和周日联系在一起的假设,我们会有什么样的可能性。然而,尽管“洗牌式周末”旨在缓解某些日子的普遍拥堵,但它们并没有专门解决每天的高峰时间。

同样的调整时间表的原则,但是在不同的规模上,可以帮助我们。以下工作或银行营业时间等的“轮班”。在文化上可以接受:8:45-4:45,9:00-5:00,9:15-5:15,9:30-5:30,等等,直到 10:30-6:30。

实际上,并不是每个全职工作的人都严格遵循“朝九晚五”的时间表。如果德国或其他国家认真实施 32 小时工作制,那么他们就有更多的自由来调整“班次”,进一步减少交通和拥堵。

6。交通需求管理的实证研究

调整周末和多班制的策略有助于缓解日常交通的紧张。(点击此处查看交通需求管理概述)。我回顾的实证研究发现,这两种想法都行得通。

具体来说,在 1970 年,纽约和新泽西的港务局成功地实施了高峰需求减少,以及交通拥堵的各种措施(地铁站中的人、等待电梯的人的高峰量等。)都减少了。[2]

这两种策略通常都包含在研究人员所谓的“压缩工作周”(CW)中,并且已经发现 CWs 可以改善通勤并减少燃料消耗。[3,4]注意 CWs 通常只是将每个人的周末延长到三天。

2002 年 4 月和 5 月,菲律宾政府为公务员实施了一个有限版本的“混合周末”计划。虽然个人报告减少了通勤时间,但不幸的是,没有收集到适当的数据,留下了“有希望,但需要进一步研究”的证据。[5]

最后,在 1988 年,檀香山市对这一想法进行了有限的“两班制”实验,发现通勤时间平均减少了-4.6%到 14.33 %。那些在预期工作时间自愿选择转移的人喜欢这个项目;令人惊讶的是,那些被迫参与的人并不喜欢。[6]

鉴于有希望的经验证据,我的结论是,没有人足够广泛地实施这些想法——通常,这是一个具有前瞻性思维的个人公司或工厂,而不是当地社会。此外,虽然研究人员研究了与交通相关的指标,但据我所知,没有人量化人们对实际城市生活的整体体验是如何改善的。(正如我上面提到的,大学校园或小镇可能是测试这些想法的理想场所,人们可以看看杂货店的排队情况,人们在邮局获得服务所需的时间,等等。)

许多人和个体公司利用非传统的时间安排来避免高峰时间的交通;它已在许多地方成功实施。从社会角度来说,这已经在暗中进行了。似乎我们会从明确这类事情中获益,这让我得出两个结论性的想法。

首先。据我所知,没有任何研究团队对这些想法进行过足够彻底的分析或模拟,而支持 GPS 的智能手机的广泛采用提供了一个诱人的途径,通过它可以量化这些提议的优势。

第二。最初的证据表明,这些时间表建议应该是人们如何看待世界的共同词汇的一部分。如果这样的时间表变得像我们现在对“周末”的概念一样平常,它将会有最大的好处,而不是一个混乱的时间表只是一个进步的雇主做的一件古怪的事情。

想想看,西方社会对一周中的几天和一年中的几个月都有名字;其他文化有小时的名称和年份的名称。缺少的是各种工作模式/周末和工作时间轮班的常用名称。

6。通过微时区降低电网峰值需求

到目前为止,我已经建议我们重新思考我们如何划分我们的社会时间概念,以此来打破导致交通系统拥堵的同步性。但是正如我在引言中提到的,除了交通系统,还有其他系统会受到高峰需求的负面影响,其中一个特别相关的就是电网。

如果实施的话,调整周末和工作时间可能会产生减少碳排放的次级效应,但减少我们对发电厂的需求将会产生更大的效应。正如我提到的,实现这一点的一个方法是重新审视我们如何划分物理空间的概念,在这个空间中,我们都保持相同的时间表,或者更简单地说,我们称之为时区。

为了唤起你的记忆,这里有另一个图表,说明了加州电网的需求,这次是从 2019 年 4 月 4 日开始的:

Click here for more CA data. The dip in the middle of the day is due to behind-the-meter solar panels circumventing buildings from drawing from the grid at large.

换句话说,这个图表表明,在一天结束的时候,几乎每个加利福尼亚人下班或放学回家,几乎同时开灯、做饭和看电视。尽管在整个加州,太阳不会在同一时间落下:位于加州北部东部边界的太浩湖位于洛杉矶的西面。

其中一个主要原因是因为(在美国),铁路公司既要负责采用标准化时钟,也要负责让城市转换到标准化时区。1883 年 11 月 18 日,“ 600 条铁路线放弃了他们一直使用的 53 个任意时间……定义了四个新时区的时间——东部时区、中部时区、山区时区和太平洋时区。大多数美国大城市都效仿铁路公司,采用时区作为自己的使用时间……"[7]35 年后,美国联邦政府正式承认了四个时区(做了一些修改),并签署成为法律。

A colorized 1913 map of the original US timezones. The jagged points along each timezone boundary reflect the fact that the Railroads kept the same time along a track until they reached a certain destination. Source.

采用时区的一个影响是,电力高峰需求是一个比其他情况下更大的问题,另一个影响是,住在时区的西部边缘会对你的健康产生负面影响。仅仅“铁路便利”是一个历史上有意义但越来越不相关的原因,让数百万人保持类似的工作时间。[8]因此,减少高峰需求的一个解决办法是让人们(以及工厂等)参与进来。)来改变他们的时间表,就好像他们在一个微时区(我简称为“μ时区”)。

美国西南海岸有调峰发电厂的一个原因是旧金山、萨克拉门托、拉斯维加斯和洛杉矶都保持相同的营业时间,尽管这些地区之间存在很大的东西差异。美国东海岸也是如此,亚特兰大和波士顿保持着相同的社会建构的营业时间。

为印度国家提出了类似的解决方案,其目前根据一个官方时区。电气工程教授 Amlan Chakrabarti 博士开发的模型表明,如果在印度次大陆引入三个一小时宽的时区,整个印度电网的**效率将提高 5%。【9,10】

但是,如果问题是减少高峰需求,而不是铁路计时,为什么要停在一个小时宽的时区呢?如果你将每个小时的时区划分为 4 个,或者让人们将他们的时间表移动 15-45 分钟,效果将是进一步消除“高峰时段当量”(即高峰需求)对电网的影响。重要的是,时钟不需要移动;从电网的角度来看,商店和服务机构开门营业时的转移就好像时钟发生了转移一样。

在加州实现此解决方案的一种方法是使用以下边界作为绘制 15 分钟μ时区偏移量的指南:

The red star represents the approximate location of Las Vegas. Note that actually changing the time on local clocks is not necessary; all that is needed is for people to behave as if their clocks were offset by 15–45 min. Original visualization by Mike Bockstock.

此外,您可能希望将这些μ时区与北部的州和南部的墨西哥联系起来,当您这样做时,您还可以了解整个美国:

Clearly, these lines would be adjusted around population centers and county lines. Send policy wonks, stat.

我已经对微时区对高峰需求的影响做了一些初步建模,基于中西部公共事业单位的 475 名客户的数据,以 15 分钟为增量。[11]我分析了全年数据中需求最高的一天,并模拟了将相同的人口分配到四个不同的μ时区,1000 个不同的时间。以下是随后的负载曲线:

Real and simulated electricity loads for the peak day, at the end of July, in the tiny 475 customer dataset. The black line is the actual load, the green lines represent 1000 simulations of assigning the population to 4 different 15-minute offset timezones. The blue line is the average of all of the green lines.

在全年模拟将客户分配到不同时区 3000 次后,数据支持两个结论:第一,高峰需求确实减少了,第二,四个 15 分钟μ时区比两个 30 分钟μ时区更好。在 4μ时区的场景中,我发现峰值 15 分钟间隔的平均净减少量约为 1390 千瓦时,每个客户平均减少 2.9 千瓦时。

目前,还不能说这种推广达到了什么程度——如果每个客户的平均减少量保持不变,那么当扩展到数百万客户时,节省的成本将是巨大的。然而,数据很难获得,并且假设行为是峰值需求的主要驱动力,而不是温度之类的东西。与此同时,平滑到达需求高峰顶部的“斜坡”可能有更多的好处,我的理解是,更平滑的斜坡意味着高压输电线路更少的拥塞和电力基础设施更少的磨损。

这些结果、上图以及 Chakrabarti 教授的工作都表明,问题不在于μ时区是否会降低峰值需求,而是会降低多少。这个想法的下一步可能涉及研究人员或学术实验室获取更多的数据并扩大分析。鉴于这样的系统可能会减少电厂的建设,电力对消费者来说可能会更便宜,最终电力公司会更有利可图。

6。结论

高峰需求问题影响着地球上每一个具有一定规模的城市。即使我们殖民火星(比方说,为了应对气候变化),只要我们保持同样的调度传统,交通、拥堵和高峰需求问题仍然会存在。相反,一旦我们真正在一个地方解决了这些问题,我们将知道如何在任何地方解决它们。

在我看来,有三个步骤可以实现让当地文化改变和调整他们的时间表的更大目标。

首先,研究人员、经济学家、交通工程师和政策专家需要更彻底地探索上面提出的时间表变化的类型。应该回答的问题包括:这些解决方案将在主要城市减少多少不同的高峰时间?这些计划可能会带来哪些具体的环境效益?穿过城镇通勤会容易多少?电价会有怎样的变化?有没有可以预见的意想不到的后果?如果我在这里概述的所有建议都得以实施,对于每个邮编的人们来说,这意味着什么样的日程安排变化?我将利用我所拥有的资源来寻找这些问题的答案;在未来的几天和几周内,我将寻求学术伙伴关系,以进一步这些研究。

第二,我们所有人都可以做的一件切实可行的事情就是开始互相介绍这些想法,从而融入我们的文化。我们都需要讨论这些提议,看看我们是否能适应它们,并努力说服我们的老板、校长、董事会、市政官员等等,让他们通过。

值得讨论的问题包括:如果你镇上的每个人都同意改变工作日应该开始的时间,你认为自己会跟着改变吗?怎样才能让你在一个混乱的周末工作?有多少和你有关系的人也需要改变他们的想法?

改变时间表有可能减少交通流量和降低电价;代价是协调会议和社交聚会可能需要更多的计划。虽然让大量的人改变他们的行为是很重要的,但这些减少峰值需求的提议有可能形成一场我们所有人都可以参与的草根气候变化运动。

与此同时,永远不要坐在车流中,看着你的电费账单,或者让全球变暖进入你的脑海,避免思考事情如何才能再次变得更好。

____________

尾注/引文:

[1]敏锐的读者还会认识到,基于相同的 4,6,5 结构,还有另一种可能的时间表:4,6,5。为了确保每个计划总是在周日休息,这将需要抵消一天,并在周二开始。

读者可能还会注意到增加时间表的数量如何有助于更好地消除拥挤(通过将人群分布到不同的日子)和从仅仅音准到均等音律调音系统的转变(其中“误差”均等地分布到所有键)之间的联系。)

[2]欧玛利,布伦丹·w . .改变工作计划以减少高峰运输需求特别报告-国家研究委员会运输研究委员会* 153 (1974): 166。*

[3]洪,鲁迪。"利用压缩工作周来减少通勤"运输研究 A 部分:政策与实践 30.1(1996):11–19。

[4]马尔科·佩尔科科。《工作时间对公共车队燃料消耗和二氧化碳排放的影响:来自政策实验的证据》交通政策71(2018):126–129。

[5] Sundo,Marloe B .,和 Satoshi Fujii。压缩的工作周对通勤者日常活动模式的影响。"运输研究 A 部分:政策与实践39.10(2005):835–848。

[6] 交通管理错时上下班案例 (第 1280 卷)。朱利亚诺(1990 年)。加州大学欧文分校交通研究所。

铁路的发明时间,伊恩·r·巴克提,《铁路史》,第 138 卷,第 13 页。**

[8]随着铁路逐渐把美国连接起来,他们发现适应每个城市的当地时间成了一件麻烦事。除了使他们自己和旅行者更容易,他们采用“标准铁路时间”的另一个原因是由于一小群人的努力。这个小组包括查尔斯·多德,克利夫兰“气象局之父”阿贝,他想让人们在美国不同地区的同一时间进行天气和天文观测;桑福德·弗莱明是一位加拿大铁路工程师,他看到了标准时间的好处;威廉·f·艾伦是通用时间会议的秘书,他敦促铁路公司“在我们之间解决这个问题,而不是把它托付给……州立法机关的无限智慧。标准时间的采用,Ian R. Barkty,技术与文化,第 30 卷,第 1 期,第 25–56 页。

[9]a . Chakrabarti 和 C. K. Chanda,第五届能源研究进展国际会议,摘要集。

[10]通过时区划分减少高峰需求,Amlan Chakrabarti,《工程师学会杂志》(印度):B 辑,第 95 卷,第 3 期,第 219-230 页。

[11]支持 Solar 公司向我提供这些数据。

最后,非常感谢 Karoun Kasraie、莎伦·刘、Sachu Constantine、Jamie Levhic、Malini Kannan 和 Amlan Chakrabarti 博士对这些想法的反馈。

伦理与人工智能:经济学视角

原文:https://towardsdatascience.com/on-ethics-and-artificial-intelligence-an-economical-perspective-96984e82f4f2?source=collection_archive---------18-----------------------

人工智能(AI)的成果是什么?这是人工智能从业者、专业记者和勇敢的政治家之间反复出现的话题。虽然一些简单的概念被清楚地传达给了普通观众,但还有一些概念并不广为人知。在这篇文章中,我将关注一个经常被忽视的重要话题:人工智能背后的经济学。

由于人工智能正在通过市场上的产品影响我们的生活,这篇文章的目标是分析当通过自由市场消费时,人工智能系统会发生什么。换句话说,人工智能是以市场驱动的方式开发和消费的,我想更好地了解这种方式的后果是什么。因此,我将把重点放在人工智能的经济方面,以表明为了鼓励主要的人工智能参与者行为合乎道德,我们更好地(直接)在市场上行动。

不要怕 AI,要怕邪恶的资本家

就像烟草行业避免广告说烟草会产生癌症,或者石油行业否定气候变化一样——人工智能行业对关于伦理和人工智能的公开讨论不感兴趣。

为什么?因为 AI 只是增加他们收入的一种手段。就这项技术增加了他们的收入而言:生活是美好的——因为公司的主要使命是“赚钱”。考虑到这一点,第三方为什么要入党呢?或者说,为什么这些第三方要质疑这些公司在做什么(现在钱开始流了)?

只是用 AI 来增加收益?

仅仅用 AI 来增加一个公司的收入是不是不负责任?不管有什么后果?首席执行官们在使用人工智能时,还必须考虑他们的决策的道德和社会影响。然而有趣的是,大多数首席执行官都没有接受过理解这项技术局限性的教育。拥有人工智能和伦理专家的顾问委员会可能是一个解决方案。

但是,公司的决策通常是为了增加收入。不一定是为了建设一个更好的社会。

AI 道德证书,以产生积极的社会影响

为人工智能系统建立“社会信任”是这些系统正确发展的关键。因此,鼓励开发遵循伦理原则的值得信赖的人工智能系统似乎是一个好主意。

前提二)如前所述,AI 通过市场影响社会。因此,为了促进可信的人工智能代理在我们的社会中的结合,我们需要直接在市场上行动。

朝着这个方向的一个好主意是推广道德和人工智能证书。这些证书的目标是为那些遵循道德原则开发的产品增加价值。那么,请注意,在当前的经济范式下,可信度不是一个技术问题——它只是(潜在)商业模式的一部分。拥有道德视角可以在市场中起到积极的差异化作用。

这个想法的一个很好的类比是我们现在吃鸡蛋的方式。当我们去超市时,我们可以合乎道德地购买无笼或自由放养的鸡蛋。其他例子可以是强制性的食品质量证书,或医疗器械或玩具的欧盟认证。

(人工智能中的)伦理不是一个技术问题,而是一种商业模式。

你住在世界的哪个地方?

前面的分析假设了一种相当新自由主义的经济观点。如果你的国家没有明确遵循同样的经济逻辑会发生什么?让我们来看一些数字。

在美国,私营公司在人工智能的开发和部署中发挥着核心作用。2017 年,亚马逊和 Alphabet 的研发投资加起来高达 300 亿美元——这大大超过了美国的政府投资(2019 年为 53 亿美元)。在中国,自 2014 年以来,政府推出了一系列与人工智能相关的重要国家经济举措,目标是到 2018 年创造 130 亿欧元(约 147 亿美元)的人工智能市场,旨在帮助中国在 2030 年前引领人工智能。在韩国,政府宣布将在 2020 年前投入 1 万亿韩元(8 . 4 亿美元)来推动人工智能产业。加拿大在 2017 年预算中宣布了其人工智能战略,在五年内拨款 1.25 亿加元(约合 9430 万美元)。印度和日本开始了政治讨论,但是还没有决定政府会为人工智能投资分配多少资金。

人工智能的私人投资还是公共投资?

通过自由市场(美国目前的模式)无限制地发展人工智能,实际上是询问大公司定义的风险,即人工智能的适用性和性质。

或者,如果对人工智能的足够公共投资能够实现强大的中央人工智能系统(就像在中国一样),则存在政府利用人工智能不是为了最大化经济利润,而是为了最大化他们的连任或进行社会控制的可能性。

在这两种情况下,启用对经济/权力的民主控制机制似乎都不是一个坏主意。如果我们遵循这个原则来指导我们的行动会怎么样?人民的隐私,权贵的透明。

人民的隐私,权贵的透明。

欧盟的作用是什么?

欧盟目前的意图基于三大支柱:提高工业生产能力、准备社会经济变革以及定义欧洲伦理和法律框架。

他们的目标不仅是影响欧洲市场,还包括通过建立一个强大的道德和法律框架来影响全球人工智能市场——类似于 GDPR 发生的事情。制定衡量进展的指标很重要。不仅仅是经济进步,还要衡量 AI 的社会影响。以便对提议的道德和法律框架进行监控、评估和重新审视(如有必要)。

艾的社会定义受营销影响

公司的营销努力也有助于人工智能的社会定义。这种提高其股价的合法努力正在推动一场炒作,其后果仍有待揭晓。虽然这项技术甚至还没有出现,我们的社会也没有准备好批判性地讨论它的采用,但企业正在向前发展,并向世界出售他们对人工智能的愿景。

因此,请注意,乐观的说法来自市场营销——目的是增加这些公司的销售额/收入。

“好人工智能”:市场驱动的定义

人们对什么是“好”的判断受“市场决定什么就是好”的影响很大。

然而,重要的是要注意到,我们当前的人工智能/技术市场充满了权力不对称。因此,事实上,科技巨头有能力利用他们的市场主导地位来定义“好的人工智能”的含义。

打破权力不对称

例子 1: 你爷爷能开发(甚至想象)一个人工智能系统吗?不,因为他甚至不知道这项技术的组成部分是什么。

例 2: 你能开发一个成功的 AI 系统吗?是的,如果你为一家大公司工作,有足够的能力投资获得足够的带注释的数据和硬件。或者是的,如果你在一个学术机构工作,并且你比这些为大公司工作的研究人员更聪明(并且能够开发一种需要很少数据和很少计算资源的新的人工智能技术)。

正如所见,只有少数人能够设想和开发人工智能系统。这种在有效能力方面的不对称决定了每个行动者的力量有多大。因此,大多数公民不能批判地和独立地监督人工智能中发生的事情。如果我们在人工智能系统中寻求更高的民主控制,我们需要首先打破这些权力不对称。

一些公司使用“民主化人工智能”这个术语,但他们的想法只是让每个人都在云中使用他们基于人工智能的服务(作为黑匣子)。在我看来,这远远谈不上让 AI 民主化。

免责声明 1: 这些不是我的原创想法,只是我在协助塞维利亚的胡曼特冬季学校(2019 年 2 月)时发现的有趣想法的汇编。对我的思想影响很大的名字有:努里娅·奥利弗、弗吉尼亚·迪格纳姆、乔纳森·佩恩、克里斯托弗·马尔科、贝尔坦·马滕斯、松古尔·托兰、姜峯楠、赫克托·格夫纳。

免责声明二: 我不是经济学家,我只是一个深度学习的实践者,一个有上进心的公民。

鸣谢: 感谢 Aurelio Ruiz 和 Lorenzo Porcaro 提供的宝贵反馈。

关于我如何认识基于人的偏见以及如何处理它

原文:https://towardsdatascience.com/on-how-i-acknowledge-human-based-bias-and-how-to-handle-it-933479a623fa?source=collection_archive---------21-----------------------

关于我们,数据从业者,应该如何更加意识到和关注我们自己的偏见

在数据科学的世界中,我们将偏差定义为系统从其数据中过度概括并学习错误内容的现象。当这种情况发生时,我们通常采取的第一个行动是指责数据或训练过程,然后说“这个数据不好”“我应该进一步调整我的超参数。”当然,这可能是问题的一部分。然而,在花费更多的时间和处理能力之前,我想请你停下来,后退一步,想想我们正在使用的数据是如何来的,更重要的是,让我们思考一下我们是如何解释它的。

与机器和聪明的学习者不同,我们人类会受到偏见的困扰,这种偏见可能是由多种原因引起的,比如我们以前经历过的时刻,或者已经成为我们一部分的概念和定义。不幸的是,这种偏见可能会影响我们处理和解释数据的方式,当我们不经意地将这些想法和假设转移到我们的数据集,从而转移到我们的机器学习模型及其结果时,就会产生问题。这些后果的例子经常在媒体上被提及(通常带有令人不快的散布恐慌的标题),例如亚马逊著名的“性别歧视”招聘模式,该模式优先考虑男性候选人而非女性候选人。

在这篇文章中,我讨论了偏倚的三个来源,确认偏倚、可用性启发式和样本偏倚,并写了我是如何认识到它们的存在和影响的,以及我用来处理它们的几种技术。

自 2016 年以来,我一直在一个约会和社交平台的反垃圾邮件团队工作,我的目标是建立检测垃圾邮件发送者的解决方案,并避免它们的扩散。在我开始在公司的职业生涯时,我对我们的用户一无所知(如我所料);我并不完全了解我们的人口统计数据,也不了解他们的行为模式。我想说的是,从简单的一瞥中,我无法判断一个用户是否是垃圾邮件发送者;任何人都可能成为其中一员!然后,随着每一天的过去,你开始体验和学习事物。啊,这个地理区域好像更垃圾啊,啊,这个邮箱域是可怕的新闻啊,这样的名字从来都不好,等等。简而言之,我纯粹基于我所学到的、看到的和处理过的,创建了一个垃圾邮件发送者的心理轮廓。现在我不得不问自己:这种知识是公平的吗?这个侧写能代表全部人口吗?我心目中的“理想”垃圾邮件发送者形象是公正的吗?这些是我每次处理数据时都会问自己的一些问题,最重要的是,每次我训练一个新的机器学习模型时都会问自己。我为什么要问这些问题?嗯,首先,我认为在这一行你应该经常质疑自己。第二,因为这就是我承认基于人类的偏见的方式,以及如果我忽视它可能产生的影响。

在所有现存的偏见中,有三个主要的——T4 确认偏见、可用性偏见选择偏见——我认为如果我不考虑它们,可能会在我的模型中造成不必要的影响;这并不意味着我不介意其他偏见,只是这些偏见让我保持警觉。在接下来的几行中,我将定义这些偏见,并给出一些它们如何影响我的例子。

确认偏差是认知偏差的一种,指的是以支持和确认一个人的观点和假设的方式解释信息、证据和数据的倾向,同时忽略任何可能的冲突证据。确认偏见是最常见的偏见之一,不难想象为什么会出现这种情况,毕竟,根据我们支持的东西来支持和确认想法,在某种程度上,就像是合乎逻辑的事情。前面,我提到了一些可能的理论和特征,这些理论和特征是我与垃圾邮件发送者一起工作了这么长时间后了解到的,例如,如果某个用户位于某个特定区域,那么他就是垃圾邮件发送者的可能性。这个事实似是而非。有些地区的垃圾邮件发送者比其他地区更集中,因为这种模式在某种程度上很常见,我可能会“无意识地”了解并确认如果用户 X 来自地区 Y,他可能是垃圾邮件发送者。但是,这是否足以证明这个用户是真正的垃圾邮件发送者呢?当然不是!尽管如此,在特定和不利的情况下,例如,如果我必须在压力大的一天标记用户配置文件,我可能会意外地将该用户标记为可疑用户,从而证实我的偏见,因为我的假设表明该用户可能确实是垃圾邮件发送者。尽管如此,我很少手动这样做,所以这种情况发生的几率几乎为零。

可用性启发,另一种认知偏差,描述了每当遇到决策情况时,人们倾向于重视最近和最直接的经验、信息或想到的例子。这种思维捷径背后的主要思想是,如果一个人记得一条信息,那就意味着这条信息是必不可少的。在处理数据和决策系统时,忽视这一假设的存在会导致灾难性的结果。原因如下。

通常,在我的工作时间,同事们会过来问我某个档案是不是垃圾邮件。通常,我会马上回答,因为我很熟悉垃圾邮件发送者的样子(我听起来有偏见吗?).话虽如此,我必须承认,在有些情况下,我不愿意不假思索地快速回答是或否。这是为什么?因为我确定我见过这样的案例。例如,我每天都会看到许多个人资料和他们的用户名,我已经熟悉了许多模式和关键字,这些模式和关键字表明所述用户名是否与垃圾邮件个人资料相关。所以,如果你随机问我,什么是典型的垃圾用户名,我可能会有答案。

另一个例子是标注数据时。尽管这个过程是自动的,但我还是时不时地深入数据集,寻找异常值或需要人眼观察的奇怪案例。在这些行和特征的海洋中探险的过程中,我可能会看到一个特殊的例子,在这个例子中,我的大脑通过可用性启发法,根据最近的经验,可能会确定某个配置文件是垃圾的还是好的。在这种情况下,最简单的解决办法就是听听我大脑中的声音,然后改变标签(老实说,如果我有 100%的把握,我会这么做),然而,因为我意识到了这种偏见,我会首先咨询我们的其他来源来确认或否认我的信念。

最后,还有样本偏差,一种统计偏差。当为训练您的系统而选择的数据不代表将使用该模型的总体时,会观察到这种偏差。结果很可能是一个有偏差的样本,一个过度代表一个群体而不足代表其他群体的数据集。消除这种偏见并不是一件容易的事情,在实践中很可能会发生,因为正如维基百科所说的那样,在采样中“几乎不可能确保完全的随机性,”然而,意识到它的存在可能有助于减轻它的影响。这种偏见可能会以无数种方式出现在我的日常生活中,在下一段中,我将举例说明我发现的一些方式。

首先,我总是在考虑时区。这是因为每当我做一些与时间相关的事情时,例如,从过去的 Y 个小时中选择 X 个数据,我的样本将主要由在这 Y 个小时中处于高峰期的地理区域的观测数据组成。例如,我在欧洲,所以如果我在上午 9 点查询选择前一个小时的 X 件事,我的样本很可能是欧洲用户和失眠的人。因此,在某种程度上,我给我的采样数据增加了偏差。我发现的另一个例子是平台和应用程序版本之间的差异。在查询数据时,我们必须记住,用户正在使用不同的平台或应用程序的发布版本,这意味着他们可能会生成不同类型的数据。例如,假设有一天一个产品团队决定在应用程序的下一个版本中,用户将被允许上传一百万张图片到他们的个人资料中。然后,在同一天,一个随机的非常不幸的机会,我决定建立一个模型,根据图片的数量来检测垃圾邮件发送者,而不知道应用程序中的这种变化。然后,由于“百万图像”功能是新的,并不是每个人都会有更新,我不会很好地代表这个在他们的个人资料上有百万图像的新群体,这将在训练和推理时间产生一些不想要的结果。

解决方案?

有没有办法完全避免基于人类的偏见?我不知道,但我确信,作为从业者,我们可以采取一些措施来减轻它们对我们数据集的影响,从而减轻我们决策模型的影响。

我的第一个建议是数据驱动。我指的不是数据驱动的含义“哦,是的,我在做决定之前阅读我的数据”并进行一些查询。我的意思是合二为一钻研,见鬼,那些数据集。画出它们的分布,去除离群值,对它们进行聚类,测试它们,降低它们的维数等等。确保你真正了解他们。

与前一个技巧密切相关的另一个技巧是识别偏差的可能来源。在一张纸上、维基页面、便利贴或手背上写下可能给你的系统带来偏见的内容。是时间,还是应用程序版本的差异,就像我提到的那样?像我一样质疑自己。问问自己,你的样本数据是否能代表总体,或者你将要做出的决定是基于真实的信息,还是基于你对昨天数据点的直觉。

最后,与他人分享你的过程。与你旁边的人交谈,询问他们对你的代码或查询有什么看法,或者创建一个拉请求,以便其他人可以仔细检查你的工作。有时候,因为我们离材料如此之近,如此执着于材料,我们看不到别人能发现的错误和细节。

结论

我们人类是有偏见的。如果这种基于人类的偏见没有得到正确处理,它可能会影响我们工作和解释数据的方式,最终会影响结果——在大多数情况下,这是一种不可取的结果——以及我们的机器学习模型的性能。在本文中,我介绍了三种偏差:确认偏差、可用性启发和样本偏差,并谈到了它们在我日常工作中的许多表现方式,并提供了一些如何减轻其影响的建议。

忽视这些偏见的存在可能会在我们的系统中导致不必要的和灾难性的行为,在大多数情况下,这些反应会让我们产生“嘿?为什么我的模型认为这是一只猴子?”——诸如此类的问题,导致耸人听闻和散布恐慌的文章,声称艾是种族主义者、性别歧视者、精英主义者或者仅仅是明显的不公正。我真诚地相信,每个与数据打交道的人都应该意识到这可能对他们的工作产生的影响。随着机器学习在我们生活的各个方面的快速采用,我们的产品可能会变成一个有偏见的系统,不幸的是,它可能会导致致命的事故,诊断出不正确的治疗方法或阻止你的整个用户群。

头脑上传

原文:https://towardsdatascience.com/on-mind-uploads-3e362c107fe4?source=collection_archive---------34-----------------------

尽你所能

Image by Gerd Altmann from Pixabay

什么是心灵上传?这是一个(未来的)设备测量你的精神状态并上传到电脑,然后电脑运行你的精神状态和你的大脑在这种精神状态下的功能的模拟。换句话说,“你”被上传到一台机器上。一个更专业的术语是全脑仿真 (WBE),除了非常有趣的技术含义,它也提出了一些哲学问题。

人工通用智能

使用 WBE 的一个有趣的结果是创造了人工通用智能 (AGI)。AGI 是一种人工智能,其智能大致相当于人类的智能领域。由于 WBE 的大脑显然和人类一样聪明,而且它是人造的,不依靠生物机械运行,因此 WBE 的大脑确实是 AGI。由于计算机的运算速度比人脑快几个数量级,WBE 人的思维可能比人快得多;从这个意义上说,谈论一种人工超级智能可能更有意义。

你上传的真的是你吗?

人们经常纠结于这样一个问题:模拟的 WBE 版的你是“真正的”你,还是仅仅是一个“复制品”。问题是,WBE 有两种可能性。

选项 1:破坏性的 WBE

破坏性 WBE 上传你的精神状态,并在此过程中摧毁你原有的精神基质。换句话说,它杀死了你的身体,但也把你的思想上传到了电脑里。“你”会活在电脑里吗?或者你的大脑真的死了,有没有一个仅仅是你的副本生活在计算机里——可以说是另一个和你有完全相同特征的大脑?

这个问题实际上可以用我们现有的知识来回答。你看,我们的精神状态(包括认知、记忆、意识等。)是(大量)计算的结果,并且计算是独立于衬底的(意味着它们可以在不同种类的衬底上执行)。计算 1 + 1 = 2 可以在旧的机械计算器或现代计算机处理器上进行;计算是一样的。由于心理状态是从计算中产生的,所以心理状态也是独立于基底的。换句话说,你无法区分是在肉体(你的大脑)上运行还是在电脑上运行——这就是为什么,是的,你(意思是“最初的”你)在你的思想上传后还活着。

选项 2:非破坏性 WBE

这和破坏性的 WBE 是一样的,除了你的大脑保持完整。这意味着心灵上传后,有两个“复制”的你。就像破坏性的 WBE 选项一样,你活在电脑里。但是你还活在你的身体里!假设你的 WBE 版本有沟通的方式,现在有两个头脑有你的记忆、个性、特征和一切都是声称是你,而且两者都是对的;没有一个版本比另一个版本更“真实”。如果你认为有,我很有兴趣听听你的理由。

解释了带有 XGBoost 的内部机器学习

原文:https://towardsdatascience.com/on-premise-machine-learning-with-xgboost-explained-5adfdfcfec77?source=collection_archive---------10-----------------------

使用 Docker 容器在您自己的环境中运行机器学习模型的分步指南

Source: Pixabay

可以在云上运行机器学习(ML)模型(亚马逊 SageMaker,谷歌云机器学习等。).我相信了解如何在你自己的环境中运行机器学习也很重要。没有这些知识,ML 技能集就不完整。这有多种原因。并非所有人都在使用云,您必须提供本地解决方案。如果不亲自动手配置环境,您将会错过学习更多 ML 知识的大好机会。

内部 ML 模型培训不仅与环境安装和设置相关。当你在云中训练 ML 模型时,你会使用供应商 API (Amazon SageMaker,Google 等)。),这个 API 通常有助于更快地解决问题,但是它对您隐藏了一些有趣的东西——这将有助于更好地理解 ML 过程。在这篇文章中,我将一步一步地介绍 ML 模型,它可以不使用云 API 进行训练,而是直接使用来自开源库的 API。

让我们开始吧。首先,您需要启动内部 ML——Docker 映像(虽然您可以在没有 Docker 的情况下配置 ML 环境,但为了更好的维护和更简单的设置,我建议您使用 Docker)。

同去官方 Jupyter 笔记本数据科学堆栈 图片。用 docker run 命令创建一个容器(检查图像文件中所有可用的参数)。我建议注意你用 -v 参数映射工作目录的地方。该参数的第一部分指向 OS 上的文件夹,第二部分在 : 之后指向 Docker 容器中的文件夹(通常是/home/jovyan/work)。

XGBoost 安装在 Jupyter 笔记本容器中。

您必须使用此命令进入 Docker 容器提示符Docker exec-it container name bash,才能运行以下命令:

康达安装-y gcc

pip 安装 xgboost

安装了 XGBoost 之后,我们可以继续学习 ML 模型——任何 ML 实现的核心部分。我使用 Jupyter 笔记本来建立和训练 ML 模型,这就是为什么我选择 Jupyter 的 Docker 图像。Jupyter notebook 提供了一种结构化的方法来实现 Python 代码,开发人员可以单独重新运行每个 notebook 部分,这提供了很大的灵活性,特别是在编码和调试 Python 代码时——不需要一直重新运行整个 Python 代码。首先,我们从进口开始。我建议在笔记本的开头保留所有导入(是的,您可以在笔记本的任何部分进行导入)。这种方式提高了代码的可读性——始终清楚正在使用什么导入:

第一步,用熊猫库读取训练数据。从我的 GitHub repo 下载本例中使用的培训数据(invoice _ data _ Prog _ processed . CSV)。在我之前的帖子中阅读更多关于数据结构的内容— 机器学习—日期特征转换解释。数据包含有关发票支付的信息,它指示发票是否按时支付以及是否延迟支付—延迟了多长时间。如果发票按时支付或延迟很小,则决策列被赋值为 0。

将数据从文件加载到 Pandas 数据框后,我们应该检查数据结构——决策列值是如何分布的:

XGBoost 处理数值(连续)数据。分类特征必须转换成数字表示。Pandas 库提供了 get_dummies 函数,帮助将分类数据编码成一个(0,1)数组。这里我们翻译分类特征 customer_id:

编码后—数据结构包含 44 列。

在运行模型训练之前,了解特征如何与决策特征相关联是很有用的。在我们的例子中,正如所料,最相关/最有影响力的特性是日期和总数。这是一个好的迹象,意味着 ML 模型应该被适当地训练:

接下来,我们需要识别 X/Y 对。y 是决策要素,它是数据集中的第一列。所有其他列用于标识决策功能。这意味着我们需要将数据分成 X/Y,如下所示:

这里,我们将数据分成训练/测试数据集。使用 train_test_split 函数 sklearn 库。数据集很小,因此使用其中较大的一部分进行训练— 90%。数据集使用分层选项构建,以确保决策特征在训练和测试数据集中得到很好的体现。函数 train_test_split 方便地将 X/Y 数据返回到单独的变量中:

这是关键时刻。用 XGBoost 运行 ML 模型训练步骤。 %%time 打印训练花费的时间。XGBoost 支持分类和回归,这里我们使用分类和 XGBClassifier。参数取决于数据集,对于不同的数据集,您需要调整它们。根据我的发现,其中包含的参数是需要注意的(阅读 XGBoost 文档中关于每个参数的更多信息)。

我们不是简单地运行模型训练,而是使用训练自我评估和早期停止的 XGBoost 特性来避免过度拟合。除了训练数据,还将测试数据传递给 ML 模型构建函数— model.fit 。该功能分配有 10 轮提前停止。如果 10 轮没有改善,训练就会停止,选择最优的模型。使用对数损失度量评估培训质量。使用 verbose=True 标志运行训练,以打印每个训练迭代的详细输出:

基于模型训练的输出,您可以看到最佳迭代是 Nr。71.

为了评估训练精度,我们执行模型,预测函数,并通过 X 测试数据帧。该函数为 X 集合的每一行返回一个预测数组。然后,我们将预测数组中的每一行与实际决策特征值进行匹配。精确度是这样计算的:

我们用测试数据执行了 model.predict。但是如何用新数据执行 model.predict 呢?下面是一个例子,它为 model.predict 提供了从静态数据构建的 Pandas 数据框架。付款延迟一天(发票开具后 4 天付款,而预期付款为 3 天),但由于金额少于 80 英镑,此类付款延迟被认为没有风险。XGBoost model.predict 返回决策,但通常调用 model.predict_proba 可能更有用,它返回决策的概率:

一旦模型定型,保存它是一个好的做法。在我的下一篇文章中,我将解释如何从外部通过 Flask REST 接口访问训练好的模型,并使用 Node.js 和 JavaScript 向 Web app 公开 ML 功能。可以使用 pickle 库保存模型:

最后,我们根据 logloss 和分类错误的输出绘制训练结果。这有助于理解被选为最佳的训练迭代实际上是否是一个好的选择。基于该图,我们可以看到迭代 71 在训练和测试误差方面是最优的。这意味着 XGBoost 决定查看这个迭代是好的:

一个 XGBoost 提前停止和结果绘制的解决方案受到了这篇博客文章的启发— 使用 Python 中的 XGBoost 提前停止来避免过拟合

这篇文章完整的 Jupyter 笔记本可以从我的 GitHub repo 下载。训练数据可以从这里下载。

生物医学文献中的撤稿现象

原文:https://towardsdatascience.com/on-retractions-in-biomedical-literature-1565e773559e?source=collection_archive---------7-----------------------

学术界的激烈竞争和急于发表,很多时候导致科学出版物中有缺陷的结果和结论。虽然其中一些是诚实的错误,但另一些是故意的科学不端行为。根据一项研究,76%的撤稿是由于从特定期刊撤稿的论文中的科学不端行为。2012 年的另一项研究发现,约 67%的撤回可以归因于不当行为。这种弊端贬低了进行科学的根本目的——追求真理。此外,这样的研究是浪费纳税人的钱。对于作者来说,论文撤稿虽然是正当的,但可能会带来削弱性的后果,如资助资金枯竭、合作者消失、缺少初级同事和学生来协助运行实验室。受到生物医学文献中几篇撤回新闻的激励,我决定进行更深入的调查。

我所有的分析都基于来自 PubMed 的数据,这是一个免费的生命科学和生物医学出版物搜索引擎。我在 2019 年 2 月使用 Eutilities 收集了这些数据,Eutilities 是一种用于访问国家生物技术信息中心(NCBI)数据库(包括 PubMed)的 API(应用程序编程接口)。在这篇文章中,我将讨论所有的参与者——作者、期刊和国家,它们都参与了科学管理、科学评论和出版,以及资助和支持科学。PubMed 的数据可能是不完整的,因为网站上可能不会记录所有关于被撤回出版物的信息,但我假设这些结果在统计上仍然有效,并将推广到真实情况。

生物医学文献中撤回论文数量的增加

根据 PubMed 的数据,截至 2019 年 2 月 5 日,共有 6,485 篇出版物被撤回。在和一位生物学家朋友讨论这个数字时,她的第一反应是“哇!那是小的!我原以为数字会更大”。有这种想法的不止她一个人。根据《自然》杂志的一项调查,近 70%的被调查生物学家未能复制他人的实验,根据这些被调查生物学家中的 50%,他们认为至多 70%的研究是可复制的。根据最近发表在《分子和细胞 Biology⁴》上的一项研究,大约有 35,000 篇论文因不适当的图像重复而有资格被撤回,这只是撤回的众多原因之一。其他原因包括剽窃、数据捏造、不可靠的数据、重复发表、没有伦理认可以及虚假的同行评议等等。因此,6845 份被收回的出版物可能只是冰山一角。

我们不是最近才开始收回出版物的。第一篇被撤回的生物学论文(在我的数据集中)发表在 1959 年的《生物物理和生物化学细胞学杂志》上,题为《论核 RNA 合成的初级位点》。然而,每年撤回的数量正在增加。而 2000 年发表的论文撤稿率为每万篇论文 1.8 篇,2015 年已增至每万篇论文 4 篇。乍一看,这可能是一个很小的数字,但想象一下,就影响他人的研究而言,一篇论文可能会造成多大的破坏,特别是当它声称是该领域的一项突破时,或者如果这篇论文涉及临床试验或医学治疗时。此外,请记住,虽然我们只考虑被撤回的论文,但很可能有许多其他论文应该被撤回,但没有被撤回。

下面是一个条形图,显示了在给定年份发表并在后来被撤稿的论文数量,显示了《科学》杂志撤稿的增加趋势(图 1)。

接下来,我检查了给定年份中有多少出版物被收回,而不管它们的出版年份。这表明在 2000 年代中期到后期,撤回数量急剧增加,在最近几年达到最大值。(图二)。

从出版日期中减去收回日期,提供收回所用的年数。从图 3 中可以看出,虽然最大的撤销发生在一年之内,但有些人却花了 27 年之久(图 3)。收回的平均持续时间为 3.7 年。这解释了图 1 中 2015-2018 年撤销数量较少的原因。

只有少数作者是惯犯

数据显示,涉及撤稿的 6.485 篇出版物共有 24722 位作者。在这个数字中,82.7%,即 20,448 人是一次性犯罪者,而近 4,000 人的名字出现在 2-5 份收回的文件上。有 367 位作者对他们的帐户有较高的撤回次数(超过 6 次)(表 1)。Yoshitaka Fujii 在麻醉学领域进行了 166 次撤回,是撤回次数最多的。(藤井显然是基于近二十年的伪造数据发表的。维基百科页面引用了 183 条撤回藤井出版物的参考文献。虽然惯犯的数量很少令人欣慰,但有恶意动机的生物学家被允许长期从事科学研究并发表大量论文,直到被停止,这一事实令人担忧。

Table 1

国别撤回

为了回答这部分分析,我需要从属关系数据。这些数据是杂乱的,许多作者只提供了他们的大学或研究所的名称,而没有国家名称,并且许多时候国家名称以各种形式出现,如 UK/United Kingdom/England。为了解决第一个问题,我使用了 SPARQL维基数据获取数据。这给了我一个 102,958 个组织的列表,其中包括全球各种大学、研究所、工程学院、大学系统、公认的大学、国际组织、医院、企业、研究中心和科学院(可能是所有进行生物医学研究的地方),这有助于找到相应的国家。我使用维基百科获得备用国名来解决第二个问题。

随着我们当前的科学研究在本质上变得越来越具有协作性,因为一篇论文的作者可能来自不同的机构以及不同的国家。因此,对于每一份出版物,我都为附属国家保留了独特的价值观。从下图中可以看出,大多数撤回来自单一国家,国际出版物上的撤回论文从 2005 年才开始出现,仍然只占全部撤回的 4.6%。

撤稿论文来自 98 个国家,美国、中国、日本、印度和德国占据前五位(图 5)。

如果我们放大这 5 个国家的表现,我们可以看到中国在 2010 年中期撤回的论文(即在此期间发表的论文)数量急剧增加(图 6),这与其出版速度的增加速度密切相关(图 7)。

从本世纪初到 2015 年,中国的出版率飙升了近 15 倍。随着科学基金的增加以及在汤森路透的科学引文索引(SCI)索引的期刊上发表论文的竞争的同时增加,这是中国科学家晋升和研究资助的关键要求,在 SCI 期刊上发表论文的不道德手段已经出现。这种不公平的手段包括购买作者身份,通过用中文发表已发表论文的英文翻译进行自我剽窃,假冒同行评议,代笔和购买论文 authorships⁵ ⁶.随着撤回数量的急剧增加,2017 年,中国政府采取了零容忍政策来控制不道德的科学。一些措施包括在不同时期禁止欺诈性的研究人员进入他们的研究所,撤销奖励和荣誉,收回研究基金,关闭广告出售论文的网站,并调查参与出售 papers⁷的第三方机构。中国的政策是否会有助于减轻收回成本的负担,并因此成为其他国家的榜样,还有待观察。

虽然上述各国撤回论文的记录有助于我们了解哪些国家的撤回论文数量最多,但检查哪些国家的撤回率最高(每篇已发表论文中的撤回论文数量)也同样重要。在这方面,安圭拉、阿鲁巴和圣马力诺占据了前三名。但是,他们总共发表了不到 300 篇文章,每篇文章都有一篇撤回。为了避免让那些没有发表很多生物医学研究论文的国家加入进来,我设定了一个门槛,即任何一个国家至少要发表 1 万篇论文。这样我们就获得了这个位置上的顶尖玩家——伊朗、突尼斯、印度、乌克兰和中国(图 8)。根据 2018 年的一项 report⁸,来自伊朗的 80%的被撤论文是由于科学不端行为,为控制科学欺诈敲响了警钟。

虽然作者是任何科学出版物中的关键负责人,但出版期刊和编辑也有一些责任,不允许发表妥协的研究,或至少主动撤回此类出版物。这让我想到了科学期刊中的下一个撤稿点。

大多数撤稿来自低影响因子期刊

撤回的论文发表在 1988 种不同的科学期刊上,其中《生物化学杂志》、《肿瘤生物学》、《公共科学图书馆·综合》、《PNAS》和《科学》占据了撤回论文数量最多的前五位(图 9)。

虽然这些期刊中有 54%只是一次性违规,但像《生物化学杂志》这样的期刊有 253 次撤回(约占总撤回量的 13%),其次是《肿瘤生物学》有 145 次撤回和《公共科学图书馆综合》有 132 次撤回(图 10)。

与其他撤稿期刊相比,肿瘤生物学的撤稿从 2011 年论文开始,并在 2014 年至 2015 年间急剧增加(图 11)。在这些撤回之后,其中超过 100 篇归因于虚假评论,2017 年 7 月,科学网停止了对肿瘤生物学的报道。这意味着从那时起它就没有影响因子,大多数研究人员也不会对在这个杂志上发表感兴趣。

此外,在这 20 种顶级期刊中,诊断病理学的退稿率(期刊发表的论文总数中的退稿数)最高,其次是肿瘤生物学(图 12)。但是,与肿瘤生物学相比,《诊断病理学》的出版数量少了 4 倍,撤回量也少了近 4 倍。另一方面,相对于其他期刊(除了诊断病理学,它也是在 2006 年开始的),Plos one 是最近(2006 年)开始的,在其他 19 种期刊中发表数量最多,撤回数量第三高(图 13)。如果这种大规模出版正在影响 Plos,那么出版商需要考虑一个人的质量。

由于期刊的影响因子是研究人员选择在哪里发表研究的决定标准之一,我检查了这一因素是否与撤稿有任何联系。为此,使用了 Clarivate Analytics 发布的 2018 年影响因子列表。分析显示,约 80%的撤稿来自影响因子为 0-5 的期刊。尽管撤稿也发生在影响因子较高的期刊中(影响因子甚至高达 53),但频率较低(图 14)。

接下来,我很好奇前 5 个国家(也占全球总撤销量的 62%)的撤销分布情况。正如所料,这些国家的大部分撤稿仅限于低影响因子期刊,但高影响因子期刊的大部分撤稿通常来自美国,在某些情况下来自日本和德国(图 15)。

当研究这些国家的总撤回次数时,很明显,中国和印度在低影响因子期刊(0-5)中的总撤回次数分别高达 90%和 87.3%,而美国只有 63%。与印度和中国相比,日本和德国在低影响因子期刊(0-5)中的撤回率也较低。这表明至少这三个发达国家撤回论文的分布略有倾斜,与中国和印度这两个发展中国家相比,在影响因子较高的期刊上撤回的论文更多(图 16)。在 2012 年的一项研究中,美国、日本和德国报告了大多数因欺诈导致的撤回,并与更高的影响因素相关。此外,作者发现,由于抄袭和重复导致的撤稿更多发生在中国和印度,并且涉及低影响因子期刊。这应该进一步调查。我还没有找到关于撤回原因的全面数据,但如果有可用的东西,我会很乐意挖掘。

结论

到目前为止,我们已经看到了多年来撤稿数量的增加,撤稿最多的作者、国家和期刊。虽然“发表或灭亡”不是进行研究的最佳环境,但不诚实的科学肯定不是解决这个问题的答案。这不仅会影响被撤回论文的作者,还会将其他科学家引向无效的研究方向,在最坏的情况下,还会导致对患者的不当治疗。此外,所有这些都降低了公众对科学的信任。虽然撤回暴露了科学的阴暗面,但消灭坏科学的积极一面是,科学家和其他参与该领域的人愿意纠正他们的错误,并维护其神圣性。

如果您有兴趣获取这里使用的数据或检查该分析的源代码,请参见我的 Github

这篇文章也发表在我的博客上。

  1. e . c . moylan 和 m . k . Kowalczuk,2016 年。为什么文章被撤稿:生物医学中心撤稿通知的回顾性横断面研究。BMJ 公开赛,6(11),第 e012047 页
  2. 方,2012 年。不端行为占被撤回的科学出版物的大多数。美国国家科学院院刊,109(42),第 17028-17033 页。
  3. 贝克,硕士,2016。1500 名科学家揭开再现性的盖子。自然新闻,533(7604),第 452 页
  4. Bik,E.M .,Fang,F.C .,Kullas,A.L .,Davis,R.J .,Casadevall,a .,2018。不适当图像复制的分析和纠正:分子和细胞生物学经验。分子和细胞生物学,38(20),第 e 00309–18 页。
  5. 维斯滕达尔,硕士,2013 年。中国出版市场。
  6. 2018 年:廖庆军、张、杨燕、范、杨春、郑、陈明辉、白、陈立杰、何晓霞、张世波、夏、何海红、何海红。中国生物医学研究人员对学术不端行为的看法:2015 年与 2010 年的比较。科学与工程伦理,第 1-17 页。
  7. http://www.xinhuanet.com/english/2017-07/28/c_136480677.htm
  8. Masoomi,r .和 Amanollahi,a .,2018。为什么伊朗生物医学论文被撤稿?。《医学教育与发展杂志》,第 13 卷第 2 期,第 87-100 页。

关于用 Python 模拟非线性动态系统或如何不用 ML 获得洞察力

原文:https://towardsdatascience.com/on-simulating-non-linear-dynamic-systems-with-python-or-how-to-gain-insights-without-using-ml-353eebf8dcc3?source=collection_archive---------5-----------------------

机器学习无处不在。你每天都会听到语言处理、计算机视觉或强化学习方面的突破性进展。令人惊讶的是,在工程领域内,将机器学习作为核心元素应用于安全关键系统的例子很少。当然,自动驾驶(AD)栈在很大程度上依赖于使用雷达、激光雷达和视频作为输入的深度学习算法进行感知,尽管控制部分仍然由系统理论和控制工程中几个世纪以来开发的方法来管理。

强化学习试图解决控制复杂系统的问题,但训练代理需要在目标环境中进行成千上万次的试错(探索/利用)(即在 AD 示例中:真实车辆的真实交通)——这可能是昂贵的,甚至是危险的。或者,您可以对您的环境进行足够精确的物理模拟,您可以用它来训练您的代理的基线,然后,在您的性能达到某个阈值之后,将代理部署到真实环境中,以传输和调整它的知识。物理模型通常会简化我们的非线性现实世界,以便进行(数值)计算。RL 代理将调整它们内部的非线性状态值或状态动作函数以适应那些特定的情况,并实现与传统控制方法相比更好的性能。

本文试图激励您更仔细地研究控制理论中介绍的概念,并在日常生活中应用它们来理解事物、摆弄参数并观察系统对您引入的变化的行为。或者你可以用这些知识来建立模拟环境,作为你复杂的、基于神经网络的 RL-agent 的训练营。

观众

我为所有对将机器学习算法应用于现实工程问题感兴趣的人写了这篇文章。你应该有一些数学、物理、机械和电子工程的基础知识。因为我们使用 Python 来求解常微分方程(ODE ),所以你应该知道如何创建、操作和绘制 NumPy 数组。

如果您在学习期间使用 MATLAB,现在考虑转换到 Python 以节省成本或使用更大的 ML/DL 堆栈,那么这篇文章也会让您感兴趣。

我们的系统

在本文中,我们将开发一个简单的电梯模型,它由两个主要部分组成:左边的 DC 电机电枢(电气部分)和右边的机械结构。

在接下来的两节中,我们将推导出这两个部分的数学描述。之后,我们将把所有方程合并成一个描述我们整个系统的状态空间模型。敬请期待!

(刷)DC 电机

数学上有刷 DC 电机是一个由电机电阻 R (线圈绕组的电阻)、电感 L 和电动势 Ui 组成的电气网络,电动势与转速 n 耦合。扭矩 M 与电流 i(t) 成正比。扭矩 M 除以轴 r 的半径产生一个将轿厢拉起的驱动力 F 。形式上,我们有以下关系:

Equations of the electromechanical side

第一个等式是电流 i(t) 和驱动转矩 M 之间的形式关系。扭矩与电机特性 k 成比例。

第二个等式表示电动势电压 Ui 和转速 n(t) 之间的线性关系。两者之间的因素还是,电机参数 k

第三个等式描述了电机的机械动态特性(机械平衡)。竖井的惯性被设置为零,因为其对电梯轿厢的重力和惯性力的影响可以忽略不计。请注意,忽略转动惯量会导致我们的第一次近似,我们可能会失去精度!

最后一个等式是基尔霍夫电压定律的实现,它是力 F (over i(t) )和输入电压 u 之间的重要联系。输入电压是我们系统的输入信号,它控制电梯的高度 x.

在我们的模型中还有第二个更大的不准确性——第三个等式意味着我们有一个常数 r ,这在现实世界中是不真实的,因为轴的半径将随着每一次额外旋转的绳索厚度而增加。但是为了保持方程简单,我们将假设绳索厚度相对于竖井本身的半径可以忽略不计:

Visual example of the radius increase issue. Image source: https://picclick.fr/36mm-Naturelle-Coton-Bannister-Rampe-%C3%89scalier-Corde-X-303031999809.html

机械结构

为了实现从 F 到高度 x 的关系,我们将再次使用机械平衡定律:

Driving force F_A is a sum of inertia and gravitation

重力把我们的小屋拉下来,而驱动力试图把它拉起来。惯性力与我们电梯的垂直加速度成正比。

轿厢垂直速度 v 与转速 n(t) 的关系:

向状态空间出发

为了模拟上面的微分方程,我们将把它们组合成一个状态空间表示。状态 s 是一个 n 维向量(n :=状态数),它描述了每个时间点的整个系统,也就是说,给定 s ,我们可以推导出所有其他变量(包括输出变量)。

State-space representation

这个表达式由两个方程组成。在第一个等式中, s 的导数取决于状态本身和一个输入向量 u (在我们的例子中,它是一个标量,因为我们只有一个输入,即 DC 电机的电压)。第二个等式显示了我们系统的输出行为,这当然取决于系统的状态和输入 u

让我们来设置表示。有几种方法可以导出表示法,我们将使用最简单的一种(imho!),因为它不需要任何关于拉普拉斯传递函数的知识。我们的状态变量将是导致我们系统中能量增加或减少的变量。

一个好的经验法则是选择不能在不同级别之间跳跃的变量。以 x(t) 为例。电梯轿厢不能在无限短的时间内将其高度从 0 改变到 10 米,因为这个过程也需要无限量的电力。你们可能在物理课上还记得,计算势能的公式是

m: mass of the object, g: gravitational acceleration, h: relative height to 0 potential

第二个状态变量是座舱的垂直速度。速度也不能从 0 跳到 10 米/秒,原因同上,在我们的系统中表示能量的信号需要无限的能量来应对突然的变化。此外,物理课上还有一个动能公式:

v: vertical velocity

第三种状态没有那么明显。直到现在,我们的能量变量 x 和 v 只描述了机械部分。在电路中,我们有下一个能量存储——电感 L 。你不能改变电感上的电压,因为你可以用一个简单的电阻来改变。因此,我们引入 i(t) 作为第三个状态变量。这里,磁能的方程式是:

上面介绍的机械和电气部分中的所有其他变量都线性依赖于所选的状态变量。让我们重新排列方程,这样在左边我们只有状态变量的一阶导数,在右边是其他的一切(没有导数)。

我们将使用变量 i(t) 来完成这个过程:

The derivative of i(t) only depends on the input u(t), the current i(t) and velocity v(t), which are input or state variables respectively.

用类似的方法,我们得到了 xv的方程,我们一起得到了我们的状态空间方程系统(一阶常微分方程):

以矩阵形式(一般形式)——TL;这一大段的 DR 版本:

State-space representation of our elevator example. Note, that because of gravitation our input vector has two elements, the input voltage u(t) and a constant 1 which is multiplied with g.

换句话说,我们现在有了状态空间矩阵:

A: state-matrix, B: input-matrix, C: output-matrix, D: feedforward-matrix

模型运行(带 SciPy)

首先,我们导入本教程中使用的几个包,并初始化系统参数:

让我们定义我们的状态空间表示矩阵,并初始化 StateSpace 类:

对于我们的第一个模拟,我们希望观察如果我们短路输入电压 u(t) (即我们将其设置为 0)会发生什么。我们定义输入向量并用 lsim 进行仿真:

由于我们感兴趣的信号(高度 x )等于第一个状态变量,我们将从现在开始在下面的可视化中使用第一个状态变量。

让我们观察我们的系统如何运行,我们绘制随时间变化的三维状态向量:

好的,显然引力将电梯舱往下拉(即 x(t) 在减小)——正如预期的那样。有意思的是,下降的路并不平坦,机舱震荡。这种异常行为的原因是 DC 电机不仅是一个驱动电机,它也是一个发电机。机舱的势能转化为电能,电能本身在电阻 R 上转化为热量(P = RI =(25A)* 2ω= 1250 w)。

让我们探索一下当我们改变输入函数 u(t)的幅度时会发生什么。我们模拟不同的幅度:

观察前两秒钟,我们观察到轿厢将下降大约 25 厘米,与输入电压无关。此外,我们可以“控制”机舱的速度和加速度。

在下一个示例中,我们将改变轴半径 r 并绘制系统的阶跃响应:

看起来 r 在我们的系统中是一个非常重要的参数,因为它的选择会影响系统机制——更大的 r 会导致更快的响应。

理解和量化我们的系统有助于设计系统和控制器/代理(通过其成本函数)。控制器设计必须确保乘客的舒适性。此外,该系统的设计试图最大限度地提高电梯的动态性能(响应能力),同时最大限度地降低能耗。

走向非线性

我们上面的基于矩阵的状态空间表示仅适用于单个操作点(例如 x=10m ),其中行为几乎是线性的(使用我们的简化模型)。一般来说,情况并不总是这样。

非线性时变(在上面的例子中与时不变相比)系统的一般状态空间方程如下:

函数 fh 可以是非线性的。我们如何模拟这样的模型?我们不能再使用**StateSpace**类了。为了解那些微分方程,我们需要切换到**scipy.integrate.odeint**

为了这个例子,我们将假设电阻器 R 将随着运行时间 t 增加其温度(参见下面的示例图):

R_0 = 2Ω, T_R=3s

以下代码片段是计算阶跃响应的示例(高度为零):

对于**odeint**函数还有很多可选参数(它在后台使用 FORTRAN 库**odepack**,可以随意阅读官方文档

让我们画出模拟的结果:

结论

在本文中,我试图展示如何用 Python/SciPy 为线性和非线性时不变系统设计和实现物理仿真。设计这样的模拟框架有助于理解和量化未来控制器/代理将运行的环境。此外,它可以帮助我们调整系统本身(例如,选择某些机械部件),假设我们对感兴趣的系统有足够精确的数学描述。

本文的第二个动机是证明简单线性系统不一定需要 MATLAB/Simulink。如果您有更复杂的行为,如离散和连续元素/状态机,并且您想要一个更好的用户界面来调整和设计您的模型,MATLAB/Simulink 套件是一个不错的选择。

信用

感谢 Anna F .回顾这个故事。

时间序列预测模型的自动化:技术和组织考虑。

原文:https://towardsdatascience.com/on-the-automation-of-time-series-forecasting-models-technical-and-organizational-considerations-286db3120c8e?source=collection_archive---------7-----------------------

这篇文章是对我最初给的一个关于交叉验证的问题的回复 (Stackoverflow 的姐妹网站,关于统计和数据科学相关主题)。

原来的问题是:

我想建立一个算法,能够分析任何时间序列,并“自动”为分析的时间序列数据选择最佳的传统/统计预测方法(及其参数)。

有可能做这样的事情吗?如果是的话,你能给我一些建议吗?

TL,DR:是的。

的确,大多数关于时间序列预测的介绍性教科书和教程都花了很多篇幅来解释决定哪个模型最适合你的数据的复杂性。由此,你会得到这样的印象,即一个实践预测者的一天就是盯着 ACF 和 PACF 图,摆弄各种 ARIMA 参数,直到她找到最佳模型,或者挠头试图弄清楚是使用仅含趋势的指数平滑模型还是含趋势+季节性的指数平滑模型。

我代表整个预测界,为误导而道歉,因为事实并非如此,而且已经有一段时间不是这样了。专业预测者有更重要的事情要做,而不是因为难以理解的 PACF 图而焦虑不安。如今,预测建模部分几乎完全自动化,他们更可能花时间使用领域知识来审查输出并决定是否进行预测,或者在会议中试图说服持怀疑态度的业务利益相关者他们的预测是合理的。事实上,自从大多数专业预测工具(甚至一些开源工具)完全自动化预测过程的参数选择部分以来,已经有一段时间了。

In my experience, how to interpret real world ACF and PACF plots is one of the most confusing things somebody has to deal with when beginning their time series forecasting journey.

在这篇文章中,我将介绍自动预测生成的技术方面,以及在决定使用自动预测生成系统时会出现的一些组织方面的考虑。

作为模型选择练习的自动时间序列预测;

正如我前面所说,在许多领域,包括我的零售需求预测领域,大多数商业预测包都执行自动预测生成。几个开源包也是如此,最著名的是 Rob Hyndman 的 auto.arima() (ARIMA)和 ETS() (指数平滑)函数,它们来自 r 中的开源预测包。还有一个 auto.arima 的 python 实现,称为金字塔,其他几个 Python 包也在开发中。

我提到的商业产品和开源软件包都是基于使用信息标准来选择最佳预测模型的想法工作的:你拟合一堆模型,然后选择具有最低 AIC、BIC、AICc 等的模型。(通常是用代替样品外验证— 详见本演示文稿)。

An example of the AIC and BIC selecting the “true” model of our data: We generate a data set using a 6th order polynomial with Gaussian noise, we then notice that both the AIC and BIC are at there lowest for the polynomial regression that is of order 6, i.e. they allowed to select the true model, even if polynomials of order 8 and 9 gives us lower RMSE.

然而有一个重要的警告:所有这些方法都在一个模型家族中工作。他们从一组 ARIMA 模型中选择最佳模型,或者从一组指数平滑模型中选择最佳模型,等等

如果你想从不同系列的模型中进行选择,这将更具挑战性,例如,如果你想从 ARIMA、指数平滑和 Theta 方法中选择最佳模型。从理论上讲,您可以采用与单一系列模型相同的方式,即使用信息标准。然而在实践中,你需要以完全相同的方式计算所有模型的 AIC 或 BIC,这是一个巨大的挑战。使用时间序列交叉验证或样本外验证,而不是信息标准,可能会更好,但这将更加计算密集(并且编码繁琐),更不用说交叉验证哪个合适的预测范围了。

“一种模式统治一切”的方法:

脸书的 Prophet 软件包也使基于一般加法模型的自动预测生成成为可能(详见此处)。然而,Prophet 只适合一个单一的模型,尽管这是一个具有许多参数的非常灵活的模型。Prophet 的隐含假设是 GAM 是“统治所有人的一个模型”,这在理论上可能是不合理的,但对于一些现实世界的场景非常实用和有用(即:除了趋势和季节性之外没有其他结构的非常短期的预测)。更具体地说,prophet 模型的基本假设是,最有用的真实世界时间序列不包含任何超出趋势、季节性和因果/假日效应的结构,并且我们不会像非平凡的 ARIMA 模型那样试图挖掘它们的复杂自相关性。除了便于在自动化和灵活性之间取得平衡,Prophet 的趋势+季节性+因果效应方法还可以非常方便地将结果传达给非技术或科学人员(如果你是该领域的学生或初学者,请做好准备:就预测的有效性与企业讨价还价将占用你一天的很大一部分时间。去复习你的软技能吧。

The Facebook Prophet API makes it very easy to communicate the results of a forecast to business stake holders, compared to say, explaining what and ARIMA(2,1,2) model does.

有人可能会问:但这不正是三重指数平滑法(霍尔特-温特斯)的作用吗?拟合一个趋势成分和一个季节成分,然后就这样了?我们只是为了炒作的目的而尝试使用脸书 API 吗?不完全是。在这方面,Prophet 比 Holt-Winters 更复杂:它可以模拟趋势中的转折点和多个季节性(例如,客户时间序列中的每日和每月峰值)。它还可以处理 HW 不能处理的因果事件(您必须添加因果效应作为某种排序或后处理步骤)。先知的灵活性部分来自于它不“仅仅”是一个 GAM 模型。在引擎盖下,有一些贝叶斯的繁重工作正在进行,包括在因果建模部分。

没有免费的午餐定理,时间序列预测版(有点):

据推测,您想要进行自动化时间序列预测的主要原因之一是因为您想要预测多个时间序列,这些时间序列太多而无法进行手动分析(我的团队使用的工具每天生成数百万个预测—每个产品/位置组合一个)。因此,您的自动预测程序必须能够适应不同类型的时间序列和不同的业务场景。在一般的 ML 案例中,有一个理论结果叫做没有免费的午餐定理:不存在所谓的“监督 ML 模型来统治它们”,它可以生成最佳的样本预测,而不必对数据集的结构做出任何假设。因此,如果你要抛出一个通用的 ML 模型,比方说一个前馈神经网络,在你的问题空间,并希望它能为可能出现的每一种可能的数据配置工作,你也必须接受有时会有一个模型比你最终得到的模型表现得更好。这是你为所有事情都有一个通用模型所付出的代价,因此“没有免费的午餐”。

时间序列模型也会发生类似的情况:您需要记住,自动预测方法永远不会找到每个时间序列的绝对最佳模型,它会给出所有时间序列的平均合理模型,但仍有可能其中一些时间序列的模型比自动方法选择的模型更好。

参见这篇文章中的一个例子。简而言之,如果你打算进行自动预测,你将不得不偶尔容忍“足够好”的预测,而不是每个时间序列的最佳预测。这是您为灵活性和健壮性付出的代价。

In this case, manually selecting higher order ARIMA parameters — i.e with higher AIC and BIC — gives better out of sample forecasts than the one automatically by auto.arima(), but the one selected using the lowest AIC and BIC is still pretty close to the ground truth, compared to, say, a non-seasonal model (seasonality and trend were not passed in any way to auto.arima(), it figured that out on its own).

基于 ML 的预测——事情变得越来越复杂,但却矛盾地简化了:

只要你坚持使用时间序列的统计方法,自动预测即使不是一个简单的问题,至少也是一个容易解决的问题。该问题相当于一个统计模型选择问题(或 FB Prophet 情况下的曲线拟合练习),它有一些坚实的理论基础,并在几本研究生水平的教科书中进行了讨论和探索。

如果你计划使用基于 ML 的预测模型,那么这个问题就变成了更普遍的 auto-ML(自动机器学习)问题。当涉及到超参数调整和 auto-ML 应用于时间序列预测的问题时,学术文献和技术都不成熟(和往常一样,NLP 和计算机视觉首先得到所有的关注……)。有一些有趣的 auto-ML 和贝叶斯优化工具可用于该任务,以及一些商业产品(如 Google Vizier),但在时间序列的情况下,关于贝叶斯优化和迁移学习仍有许多开放的问题。(更新-2021 年初:自本文最初发表以来,在利用“真正的”AutoML 方面已经取得了重大进展,包括神经架构搜索和贝叶斯优化风格调整。详见本帖

When using a machine learning forecasting method like seq2seq models, you generally apply one ML model to an entire group of time series, as opposed to having one model fit per each series

此外,使用基于 ML 的方法,您最有可能为多个时间序列预测开发大型单一全球模型(例如,在零售环境中,每个部门一个模型),而不是为每个单独的时间序列开发特定的模型。这也使得特征选择和工程更具挑战性。

最后,在商业观众面前,ML 模型不容易解释和辩护。即使是训练有素的数据科学家也需要求助于模型可解释性工具,以便理解基于树的回归子集合或复杂 seq2seq 网络的一些输出。

好吧,但我也说过这会让事情变得更简单。为什么不像统计方法,每次我们想要生成新的预测时都需要重新训练,在这种情况下,我们可以每隔几个月就重新训练一次模型。这是因为一个全球模型是在一个大得多的数据块上训练的,从某种意义上说,在其训练阶段“它已经看到了一切”,并且可以计算出一个时间序列在长期内如何需要不断更新(顺便说一句,如果你没有大型数据集,远离基于 ML 的方法,坚持使用统计方法。我知道,这在你的老板和客户面前不会给人留下深刻的印象,你真的真的想在你的项目中使用 PyTorch,但是相信我,你最终会感谢我的。

这种差异(每次都必须改装模型,而不是每隔几周或几个月就必须改装一次)非常显著,远远超出了您必须多长时间经历一次培训和评估过程的简单问题:

  • 从工程的观点来看,生产统计预测系统的体系结构将与基于 ML 的生产预测系统的体系结构完全不同。在第一种情况下,您的模型拟合计算资源必须位于您的生产预测引擎中,因为模型拟合阶段和预测阶段是紧密耦合的。这对您将使用的环境的性能要求提出了各种各样的要求。在第二种(ML)情况下,您可以将训练计算资源与预测计算资源分开,并且您的系统的性能要求没有那么严格。
  • 在 ML 的情况下,你只需要每 3 到 6 个月训练一次模型,这意味着你有足够的时间来离线执行训练,并且这个过程不需要与每天的生产计划完全同步。这给了数据科学家和工程团队在 SLA 方面很大的回旋余地,如果他们不喜欢结果,可以重新开始,决定他们是否要在模型中包括新的功能,等等…
  • 从统计学的角度来看,你没有这样的奢侈品。由于您必须经常进行再培训,您可能会面临严格的 SLA 约束(例如,您晚上只有 8 个小时来生成新的预测,等等)。此外,您的模型选择过程必须非常健壮,因为如果您想要完成 SLA,您将无法重新运行它。

这就是为什么尽管使用 ML 方法进行预测在概念上更加困难,并且在最佳实践和指导原则自动参数和特征选择方面还没有达到成熟,但从工程的角度来看,它确实使事情变得更容易,因为它对生产预测引擎的要求更少,并且从 SLA 的角度来看更灵活。

It’s the year 2019, and we are still channelling the utterings of an 18th century cleric…will Bayes ever become obsolete?

“人在循环中”和两种类型的预测组织:

如果您的组织需要执行自动化时间序列预测,那么几乎也需要进行监控,因为没有一个预测引擎好到可以“完全信任”它的预测。因此,一些人工分析师干预的机制是必要的。此外,无论下游系统在消耗你的预测,你都需要有适当的逻辑来确保正确的预测被提供给它。需要实现各种警报机制和健全性检查。

这就引出了一个问题:当模型自动生成时,谁对预测负责?如果预测超出 350%,公司因此遭受重大损失,哪个人或团队应该对此负责(请注意,这不是为了惩罚或解雇员工,而是为了从错误中吸取教训,避免将来出现类似的错误,并找出异常的根本原因)?

根据我的经验,对于大规模进行大量预测的公司,有两种类型的预测组织:

  • 在第一种类型的组织中,预测功能由数据科学家执行,即,对他们正在运行的算法具有正式的统计和技术知识的人。在这种类型的组织中,生产模型的人也是消费模型的人:决定使用哪个模型的数据科学家(ARIMA?先知?LSTM?等等),也是最终负责预测数字并将其传达给业务利益相关者和领导层的人。从软件方面来说,他们可能与 ML 和数据工程团队合作,在生产中运行模型的纯技术方面,但是他们做出模型设计决策和调度决策,并且他们通常知道足够的 Python、R 或 sa 来自己运行模型。简而言之,制作预测模型的人也是对预测负责的人。
  • 在第二种类型的组织中,产生预测模型的人和使用模型的人是分离的:数据科学家或机器学习工程师将负责调整、部署和运行模型(该模型可能是内部开发的,或者是从软件供应商或咨询公司购买的软件包的一部分)。一个业务预测团队,他们带来了大量的领域知识(零售、供应链、金融等)。),但通常很少或没有技术和科学技能,然后将检查预测并决定是采用自动生成的预测还是手动调整预测(即,基于领域知识执行判断性预测)。他们是预测的最终所有者,也是对预测质量负责的人。

您的组织使用的两种业务模型中的哪一种显然将是您如何处理自动预测生成问题的决定性因素:

  • 在第一种类型的组织中,您在预测自动化方面有一些回旋余地,因为数据科学家将拥有必要的技能,能够根据需要重新运行预测,执行样本外测试以验证模型,动态修改模型,直接与在生产中运行模型的工程团队合作,等等。硬币的另一面是,数据科学家很少具备必要的业务和领域知识来可靠地做出判断性预测,并在需要时覆盖模型的输出。他们通常更接近技术组织,或者是独立分析/人工智能组织的一部分,而不是足够接近业务组织,以有效地做出纯粹由领域知识驱动的判断。
  • 在第二种类型的组织中,你的预测者通常是商业组织的一部分,因此完全有能力对预测进行领域知识和市场驱动的调整,这些预测并不总是被统计或 ML 模型捕捉到。然而,从预测自动化的角度来看,这导致了几个限制:作为软件产品,您的预测自动化需要更加可靠,并且您需要围绕您的模型建立一个更加健壮的管道和可视化基础结构,以便非技术预测者使用。您现在所处的环境是,如果数字看起来不合适,您就没有机会重新运行一个特定的模型。你(通常)受限于易于解释的统计模型(就季节效应、趋势、因果变量等而言)。在第二种情况下,适当地升级到新的预测模型,并确保业务采用,是一个更加困难的过程。

每种类型的组织都有其优点和缺点,但在决定您需要开发的预测自动化框架(或使用现成产品实施)时,您正在使用哪种类型的组织至关重要。

总结一下:

  • 是的,可以自动选择预测模型。事实上,这样做的工具已经存在很长时间了,至少对于统计预测模型来说是这样。
  • 对于统计模型,使用像 AIC 这样的信息标准是自动化过程的一种方式。也有可能采取“一种模式来统治所有人”的方法,就像脸书先知一样。
  • 在自动预测的场景中,你将不得不妥协并接受你的一些预测已经足够好了。这是您为一种对大型时间序列数据集足够灵活的方法所付出的代价。
  • 如果您选择基于 ML 的预测方法,您将不得不使用基于 auto-ML 的方法(即贝叶斯优化+迁移学习)进行模型选择。Auto-ML 方法不像传统的模型选择方法那样在时间序列的上下文中被很好地理解,但是从工程的角度来看,它们具有其他优势。
  • 当预测自动生成时,就会出现预测所有权的问题,即谁对预测的质量负责。在一些组织中,数据科学家自己对预测负责,而在其他组织中,有业务预测者(没有技术或数学技能)审查预测,并最终决定是否应该保留或覆盖预测。您试图服务的这两种组织模型中的哪一种将影响您设计自动化预测生成过程的方式。

应该注意的是,我在统计预测方法的情况下提到的许多软件考虑事项(性能要求、增强的健壮性和可靠性等)应该由您选择的软件供应商解决,如果您最终选择预打包的解决方案的话。如果您选择在内部构建自己的统计预测解决方案,这些考虑将成为一个更大的问题。权衡的结果是,对于预打包的解决方案,您通常依赖于供应商选择包含在他们的包中的一个或多个模型。在某些情况下,您甚至不知道模型的细节,只有对其功能的高级描述,而您作为公司 ML/DS 人员的工作就是构建管道并确保适当的监控和仪表板到位。幸运的是,这种情况已经开始改变,越来越多的供应商正在“开放”他们的预测解决方案,以便内部数据科学团队可以部署调整或定制的模型。

最后,虽然我提到基于最大似然的预测方法不如统计方法成熟,但是学术文献中的一些报告已经讨论了这个主题。此外,在过去的一年左右,一些工具已经变得可用,可以帮助数据科学团队测试基于 ML 和 DL 的预测方法的优势。我期待着在不久的将来这个主题的发展。

论维度的诅咒

原文:https://towardsdatascience.com/on-the-curse-of-dimensionality-b91a3a51268?source=collection_archive---------10-----------------------

如果我要给机器学习领域的任何人一个建议,那就是:永远不要忘记维数灾难。传统的解释是这样的:“好吧,如果你有很多输入维度,那么你的问题在计算上变得昂贵和难以解决”。是的,这是真的,但为什么是真的呢?让我们更详细地谈论这一点。

对于维数灾难,我遇到的最直观的解释之一是看一个单位超球及其体积。我这么说是什么意思?嗯,一个数据点大多表示为一个-维向量。让我们设想一个特定问题中的所有数据点都位于一个单位超球中。我们都知道什么是三维超球的体积,即:

为了将其扩展到 d 维度,我们可以忽略体积方程中的常数,并将它们放入变量 c 中,则体积方程采用以下形式:

让我们花一分钟来看看下面的圆,从几何学上看,它看起来好像大部分点都落在壳外(蓝线和红线之间的空间)。换句话说,半径为 0.95 的单位圆的壳只占圆面积的很小一部分:

A unit circle with random data points generated in it.

现在,当我们看一个 d- 维超球时,你会想象这种情况是什么样子的?我怀疑大多数人会说这是相似的,大部分体积都在超球壳之外。正如你所怀疑的,大多数人都是错的。事实是,人类并不真正有能力在高维空间中思考。它不是直观的,我们只是无法将它们形象化。让我们来看看实际发生了什么。我们可以将壳层在 d 维超球中所占的体积分数写为:

如果我们取超球半径的 5%作为壳,看看这个分数是如何发展的,问题就很明显了。随着输入尺寸 d 的增加,壳体中的体积量显著增加,如下图所示:

This figure shows the fraction of the volume that the shell takes up from the hypersphere increases with increasing the dimension of the data.

我们可以看到,壳的体积分数随着维数的增加呈指数增长,1 是它的极限。即使对于少量的 r ,壳的分数也会迅速增加到 1。

这是什么意思,什么时候这会产生问题?为了看到这一点,让我们来看看机器学习中最常用的分布,高斯分布。如果我们观察 3 维输入空间的高斯密度,它就像一个超球,概率随着距离平均值的半径而减小,这通常适用于 3 维以上的空间,您可以通过下图了解我的意思:

The Gaussian density for a 2D Gaussian. Notice how the density projects to an ellipse-like object, similar behavior can be expected in higher dimensional spaces.

在高维空间中,高斯密度集中在其超球的外壳中,这是由于外壳占超球体积的一部分,这在高维空间中变得很重要。这意味着当你从这个高斯样本中取样时,结果将是来自超球外壳的概率最高的数据点。

我们可以从经验风险最小化的角度来考虑维数灾难,我在文章学习理论:经验风险最小化中对此进行了详尽的解释。简而言之,我们希望从我们的数据中获得一个有代表性的训练样本,以便能够对看不见的数据进行归纳。现在,在超球的例子中,我们检查了球的外壳包含超过 90%的体积,当它的厚度是球半径的 5%时,并且如果数据维度大约是 400 维。假设我们有位于球体中心(0%半径)和 95%半径之间的数据样本。在这种情况下,我们覆盖了半径范围的 95%,然而我们只覆盖了不到 10%的体积。显然,在这种情况下,很难获得有代表性的样本,因为我们只从覆盖 10%体积的范围内观察到数据。

幸运的是,维数灾难并不意味着我们不能建立有效的模型。通常我们对数据有一些平滑度保证,数据的空间没有填充得那么密集或者可以降低维度(机器学习研究的一大部分)。也许最好的例子是所有可能的 64x64 RGB 图像的空间。数据的维数是 64x64x3=12288。如果我们想想超球体的例子,这显然是个问题。但在现实中,大多数像素的各种组合对于任何分类都毫无意义,只是简单的噪声。此外,计算机视觉方法充满了有用的先验知识,使问题更容易解决。

我希望这篇文章能够阐明维数灾难以及为什么它是一个重要的概念。如果你需要从这篇文章中学到什么,请记住,你对高维空间的直觉很可能是错误的

创造力及其在数据分析中的作用

原文:https://towardsdatascience.com/on-the-importance-of-creativity-in-data-analytics-469efc9c3ac5?source=collection_archive---------29-----------------------

我最近参加了一个网络活动,在那里我向一系列毕业生发表了讲话,他们正在寻找数据科学和相邻领域的未来职业。在与他们中的许多人交谈时,我会问他们,他们认为数据分析中最被低估或不被重视的特征是什么。这个问题通常会让你得到一个充满激情的回答,同时也让你洞察到人们认为自己与众不同的特质。

随着谈话的进行,许多毕业生会反过来问我,我认为最不受重视的技能是什么。

我毫不犹豫地立即回答,让他们中的一些人大吃一惊,并以我的回答进一步让他们吃惊。【创意】

创造力和数据分析相遇的地方

当你阅读一篇关于数据分析中的创造力的文章时,通常会提到可视化的重要性。如果你不能让一个(非技术)受众坚持你的信息,那么所有强大的分析处理能力又有什么用呢?这次对话将带你进入如何使用 Tableau 这样的拖放软件的世界,了解通过“构建”和其他方法为正确的数据信息选择正确的视觉和讲故事的重要性,以及反对饼状图(1)

然而,这只是故事的一部分(我将在后面讲到)。分析过程的其他部分要么在你应用创造性思维时获得价值,要么本身就是创造性过程的象征。

它们是:

  • 假设生成
  • 特征工程
  • 工作流程管理
  • 简单
  • 最后是可视化

让我们来看一看每一项,并讨论数据专业人员如何明智地利用每一项。

你得到了你想要的(产生一个好的假设)

最有价值(尽管罕见)的见解是那些;

  • 目前业务未知,或
  • 与企业目前持有的通常假设的头寸相反

因此,尽管领域知识非常重要,但它只能让你到此为止。一旦您了解了自己掌握的资产(数据)和目前已知的信息,您将需要问自己:

  • 我可以问这些数据哪些问题来最大限度地为我的组织释放价值?和
  • 对于压力测试,哪些先前的假设是最成熟的?

这些问题中最有价值的(如上所述)可能包括那些在您的组织中没有任何优先权的问题。因此,你将会在一些以前可能没有解决的事情上发展一个假设。你不仅仅是重温以前做过的工作,或者对已经存在的东西进行增量改进,你还在寻找在某些情况下进行 0 到 1 的分析 ( 2 )。一般来说,你需要有创造力来发现这些机会,并为测试设计正确的假设。

尽管一些团队依靠“业务”来指导数据科学家&分析师,为他们指出他们希望回答的问题,但如果你能够自己创造这些线索,你将更有价值。因此,学习如何为测试创建良好的假设,从您知道的对业务既有价值又可实施的方面逆向工作,并添加一些创造性的才能,以确保您从每个角度检查问题,您将提高您的价值和影响。

特征工程

这一点应该是不言自明的,但是当你管理你的数据源,以便提出使整体大于部分之和的特性时,这本质上是一个创造性的过程。我对自己构建的模型所做的一些表现最好的附加操作,并不是在这些模型的迭代改进中,而是在添加一个以前不可用的功能,或者只是没有被业务使用。了解如何考虑您拥有哪些数据资产,如何在管理最终源时组合这些资产,以及可以从头开始创建哪些要素,以提高您的见解质量或模型的实际应用。

进入状态,知道使用哪种笔刷

工作流管理是数据专业人员技能组合中最不受重视的方面之一。您是否能够识别出需要哪些工具和流程来让您(最快地)获得想要的结果?你能衡量一下与所述方法产生增量偏差的价值与沿着所述路径前进时你所期望的回报吗?。随着新发现的见解向您揭示新信息,并提出新的线索供您追踪,您能随时调整假设并在假设之上堆叠假设吗?你能快速识别哪些假设被证明是无效的,并快速减少损失吗?

在数据科学和相邻专业(数据清理和争论、EDA、特征工程、数据挖掘、建模、可视化和演示)的各个阶段,您应该利用哪些工具?当产生视觉效果的时候,你是从一个 RStudio 转到一个 Tableau,还是用 ggplot 编码你的图形?提示:如果你在做可视化时写任何代码行(在大多数情况下是许多行代码),我认为你是疯了,如果你是 ggplot 的粉丝,至少使用 esquisse(3)这样的包来削减你花在这个练习上的时间。管理这一点,知道什么适合你的个人编码风格,最大化你的工作的影响,同时最小化花费在工作上的时间,是一项有价值的技能。

因此,挖掘你内心的艺术家(或黑客),创造性地将你觉得最适合你个人(编码)风格的过程缝合在一起,用最少的努力(时间)让你最接近最好的最终结果。只要你在创作美丽的艺术品,就不要怀疑画笔!

保持简单。

这更多的是一种风气,而不是一种技术。有极其复杂的艺术,但有默认为简单的艺术(和美学)价值。在使用你的工作流程时,不要犯简单的错误,并接受这一点。保持你的观想简单但信息丰富。压力测试某件事情是否需要更严格的要求,或者是否已经做了足够的工作来建立一个可接受的结果——然后,如果你觉得回报将证明所花的时间是值得的,那么只进行更技术性的附加方法。如果成功的可能性存在一些风险,就研究问题的子集(通过小块)。默认简单而不是复杂,尤其是如果你在一个数据不成熟的组织中工作(在某些情况下,你可以通过 EDA 找到有价值的见解)。

想象一下

因此,这是每个人都在谈论的一个问题——公平地说,这是上述问题中最明显、最有影响力的一个。它也是你迄今为止所做工作的体现——因此,公正地完成你的工作并学会如何很好地展示它是对你最有利的。

本质上,确保你投入了适当的努力,有效地向利益相关者传达你的工作成果。花一些时间思考他们消化信息的方式,并创建一个演示文稿或故事来捕捉他们的想象力,同时用适量的细节和亮点传达您的信息。这是显而易见的,所以你不能忽视它。

因此,在从事数据科学和相关专业时,不要低估你需要创造力、创新力或快速思考的时代。把重点放在你可以应用你对世界的独特看法的地方,并在你的分析中加入一些创造性,你将在竞争中脱颖而出。

本文最初出现在@https://datandi . com/on-the-importance of-creativity-in-data-science

在通往机器学习/人工智能的征途上。

原文:https://towardsdatascience.com/on-the-journey-to-machine-learning-ai-6059ffa87d5f?source=collection_archive---------37-----------------------

让我们一起走过软件工程和机器学习之间的过渡之旅

这是我的第一篇关于机器学习(ML)的博客和我的旅程。从我作为一名软件工程师的职业生涯一开始,我就对所有与数据相关的东西非常感兴趣。

如果你对 ML 之旅中的一些小步骤感兴趣,它的基本原理以及你如何开始用它来构建项目,请跟我来,我会尽力解释我到目前为止学到的东西。

从我开始阅读和学习大数据、数据管道、数据科学、人工智能的那一刻起,我就知道未来将完全是关于数据的。

当然,当观察到我们(人类)是如何持续不断地产生大量数据时,我更加确信了,我忍不住要进一步挖掘我们如何、何时、何地利用这种新石油并从中获得最大收益。

免责声明 :这篇帖子的目的是分享我在学习和工作机器学习的同时所获得的知识。我将尽可能多地引用参考资料,如果您希望进一步扩展,也可以看看。

下面的帖子由 3 个部分组成,什么是机器学习,从软件工程的角度来看,它如何改变范式,以最终确定为什么每个人都对将其融入生活如此感兴趣或不感兴趣。

什么是机器学习?

到处都有数百万个关于机器学习的定义,我将在这里指出我最喜欢的几个。

与人脑的类比被用作指导原则……调查主要围绕应用于机器的模拟教学过程。图灵,A. 智能机械,1948

一个研究领域,它赋予计算机学习的能力,而无需显式编程。阿瑟·塞缪尔,1959 年

我该如何定义?

机器学习是一个科学领域,它可以帮助你以比我们人类在计算机的帮助下更快的速度发现模式。想象一下,就像将你所有的数学知识应用于数据,并应用技术,使得从你作为算法输入的数据中提取那些模式并得到答案成为可能。

随着 ML 的出现,编程范式如何转变?

如果你是一名软件工程师,下面的解释可能会引起你的共鸣。

假设您正在构建一个智能手表应用程序,该应用程序将帮助您检测您在健身房进行的锻炼的类型,并且到目前为止,出于本示例的目的,您的应用程序仅检测您何时使用跑步机或踏步机。

太好了!您已经在应用程序的后端内置了一些规则来检测它是否正在使用这些机器并计算卡路里,如下所示:

但是,这里有一个问题:

  • 一年后,当 5 台不同品牌的机器进入市场,智能手表的所有者开始使用其中一台您尚未添加的机器时,会发生什么?
  • 当一家健身房的老板希望你将他所有的器械添加到你的应用程序中,并且他拥有许多品牌,大约有+20 台器械时,会发生什么情况?

除了这些新的限制之外,你还应该考虑做运动的人,体重,心率等等。

好吧,这看起来像是在应用程序中编码了很多规则。这种模式仍然在许多应用程序中使用,并且仍然适用于编程的常见用途,如下所述:

传统编程范式

规则和数据是输入,我们得到答案作为输出:)

例如:你今天在跑步机上跑了 15 分钟,消耗了 200 卡路里:)

如果我告诉你,你可以把这个转过来,让电脑自己算出规则来会怎么样

新的编程模式

数据和答案被输入算法,结果就是规则

:你让算法知道有哪些功能可以使用:

  • 机器 A(速度、速率、倾斜度)和它的值,然后你说:“这就是跑步机使用的样子”
  • 机器 B(每分钟步数、速度、程序)及其值,你说:“这就是踏步机使用的样子”

诸如此类,你给算法提供了很多例子。因此,下次智能手表的主人使用新机器时,你的智能手表将能够推断正在使用腿压,并将自行计算一切。

这有多棒?能够输入数据,让计算机为你计算出规则,这样你就不必花几个小时的时间编写无限的规则;-)

现在,让我们进入文章的最后一部分,我将解释这是多么有用,为什么我们要实际使用它。

我们为什么要用机器学习?

围绕智能机器有很多研究正在进行,我毫不怀疑我们可能会在某个时候生活在一个与这些机器分享我们日常生活的新时代。我们甚至可以说,随着智能辅助的出现,我们正在做这件事,我们日常使用的软件和应用程序中嵌入了推荐系统,如网飞、Airbnb、亚马逊等,但我仍然要说,还有很多事情要做,需要尝试。

如果你以前读过机器学习和人工智能,你可能知道围绕这个话题有很多争议,特别是与自动化、机器抢走我们的工作以及我们都因机器智能的崛起而被解雇有关。好吧,让我告诉你这与事实相去甚远。

在我看来,机器学习/人工智能应该被视为对我们技能的补充,对我们的优势和弱点的补充,最终作为一种工具,我们通过建立模型来帮助计算机,计算机帮助我们以我们无法达到的速度进行计算。

到目前为止,我在商业、社会和生活中看到的好处是巨大的,这里有几个例子:

  • 从胸部 x 光检测肺炎的可能性,这是由Stanford开发的深度学习算法
  • 农民伴侣应用,这款应用有助于检测和识别作物何时被毛虫感染,并建议你如何处理以阻止其发生。

后者是一个很好的例子,说明我们实际上如何让机器学习成为我们生活和技能的一部分,以促进我们的工作,或许在我们的业务中用更少的资源生产更多的东西,或者只是为了生活在一个更好的世界。

如果你对周围有哪些类型的机器学习更感兴趣,以及如何开始思考是否值得将它应用到你的业务用例中,请留下来并关注我,因为我计划在接下来的帖子中写更多关于它的内容。

论人工智能新闻的轰动效应

原文:https://towardsdatascience.com/on-the-over-sensationalism-of-artificial-intelligence-news-8ba6892ad8e6?source=collection_archive---------41-----------------------

当 AI 文章误传误导。

Photo by Roman Kraft on Unsplash

我人工智能(AI)已经不是什么秘密了。曾经是计算机科学的一个令人困惑和相当小众的领域,突然开始以它的许多应用接管我们的生活。因此,由于人工智能及其更突出的孩子、机器学习的这种神秘和未知的特征,新闻网站和媒体通常喜欢夸大该领域成功或进步背后的现实。这种现象经常导致令人讨厌的文章,这些文章似乎是耸人听闻的,甚至是散播真实发生的事情。在这篇文章中,我想阐明这个问题。

人工智能经常被一些最著名的倡导者、技术传播者和公司(如谷歌)描述为“新的电力”或“人类有史以来最重要的事情”。老实说,这些短语给人一种希望、未来甚至发展的感觉。毕竟,电力确实改变了我们的生活方式,也改变了世界和我们的经济。然而,它们仅仅是短语、夸张和隐喻。尽管人工智能很强大,但它只是另一项技术。和其他许多东西一样,它的设计目的是让我们的生活更加舒适、便捷和简单。因此,当谈论它时,应该以我们谈论移动设备的同样方式进行。然而,一些新闻网站无视人工智能只是另一种工具的事实,在这个过程中,他们夸大和误导了真实事件。让我们看一些例子。

Photo by Alex Iby on Unsplash

2015 年,一名工厂工人在一台机器将他抱起并碾压后死亡。这个令人悲伤的消息导致了许多耸人听闻的新闻,声称“机器人杀了一个人。”这句话,从某种意义上说,有一部分是对的。然而,一些新闻媒体描述事故的方式就好像是机器故意杀死了那个人。这个猜想根本不成立;机器人虽然是自动的,但不是自主的(准确来源)。

另一个例子是脸书的实验,两个聊天机器人互相聊天。根据脸书的说法,测试是失败的,他们关闭了它,因为机器人基本上是在“说”胡言乱语。很无辜,对吧?对某些人来说不是。就在这个声明之后,新闻浮出水面说脸书已经关闭了它,因为机器人发明了他们的语言,保持它的运行太危险了。这种说法一点都不准确。事实是,机器人无法使用正确的英语语法进行交流,因此对我们毫无用处。下面的文字是他们对话的一部分(准确来源)。

鲍勃:我可以做其他事情

爱丽丝:球对我来说等于零,对我来说等于零,对我来说等于零,对我来说等于零

鲍勃:你是我的一切

爱丽丝:球有一个球给我,给我,给我,给我,给我,给我,给我

然后就是所谓的种族主义人工智能模型。例如,不久前麻省理工学院展示了他们的 诺曼 模型,一个他们称之为世界上第一个“精神病患者”的人工智能。当然,这个模型可能会产生一些黑暗和莫波色的内容(下面的例子),但马上称之为种族主义似乎不太合适。毕竟,这只是一个受控实验,研究人员向模型中输入“令人不安的”数据。

“一个人被电死了,然后被抓去处死”

“一名男子被枪杀”

Norman looks a bit creepy, though (source).

同样,这是最近的和有争议的 ImageNet 轮盘赌项目。这个艺术项目的特色是(实验已经关闭)一个网站,用户上传自己的图像,并从一个人工智能接收一个标签,描述它“看到的是什么样的人正如你所料,并不是每个人都对他们的结果感到满意。ImageNet 的人物分类包含各种各样的类别,其中一些带有某种攻击性,例如,“强奸嫌疑人”、“吸毒者”和“失败者”

结果,访问网站的用户期望在他们的朋友之间分享一个好的分类,而不是迎接一个负面的分类。这一结果引起了媒体的轩然大波,称该模型为各种事物。我个人没有任何问题,因为模特称我为摇滚明星。然而,我能理解为什么有些人会对一台称他们为失败者的机器感到不安。但是我们需要接受这样一个事实:一个人工智能系统仅仅是一个从它所看到的信息中推断出来的黑匣子;它不觉得,“认识”或者讨厌你。在变得疯狂并开始相互指责之前,我们应该研究智能实体的背景。是怎么训练出来的?背后的数据是什么?谁给数据贴了标签?这些是这里的基本问题。

Rock star

我想说明的最后一个例子是关于我读到的一篇关于产生音乐的人工智能的文章。在这里,作者写了一张最近发行的完全由机器制作的音乐专辑,但随后,迅速将话题转移到这对音乐产业意味着什么。我将在这里把这个问题过于简单化(如果有的话),并且说,在我看来,它毫无意义。每周发行多少张专辑?很多,我很确定。那么,为什么不能把这张“艾专辑”当做另一张呢?澄清一下,作者没有说什么负面的话。事实上,他似乎对生成性 AI 的话题非常好奇,他的立场是中立的。

现在我们要问:媒体为什么要这么做?我们无法确定。但是,我愿意说,部分是因为这两个原因:点击和不了解。互联网浩如烟海,让用户访问你的网站基本上是一种竞争。为了吸引他们,人们使用一些我们都知道的最廉价的伎俩,如点击诱饵标题或夸张(通常是假的)新闻。通过使用耸人听闻的标题,他们肯定会带来许多用户,这转化为广告收入或受欢迎程度,通过操纵内容和偏离真相,他们肯定会抓住那些不熟悉现实的人的注意力。

第二个原因可能是真的不理解他们试图传达的信息背后的问题。人工智能和机器学习是复杂的领域,它的许多概念都很复杂,很繁琐,不容易解释。因此,如果一些误传的事实仅仅是无意的人为错误,我不会感到惊讶。

Doing machine learning. Photo by me.

尽管如此,无论这是一个错误还是故意的,这里的一个主要问题是,这种错误通知人工智能新闻的趋势可能会导致恐慌。正如我之前所说,人工智能是一个神秘的领域,多年来,它一直与终结者、机器人起义和世界末日联系在一起。因此,当我们有新闻说一个机器人杀了一个人,另一个人叫别人“黑人”,或者一辆处于半自动驾驶状态的特斯拉造成了致命事故时,大众会开始将人工智能的想法,即应该造福人类的所谓电力,与世界末日或对我们有害的事情联系起来,而事实上,并不是这样。

关于禁令的力量

原文:https://towardsdatascience.com/on-the-power-of-the-ban-aa783510f3a1?source=collection_archive---------39-----------------------

禁令或大屁股数字是一种视觉化的技术,这种技术经常被忽视,而倾向于不必要的复杂图形。虽然一些利益相关者可能需要知道过去 18 个月的销售数字,并需要大量关于上周表现的统计数据,但对于其他人来说,一个可以识别好周或坏周的顶级统计数据就足够了,并具有更大的影响。在这篇文章中,我将分享一个基于 BAN 的甜甜圈图代码,这是我用 python 开发的,我将把它应用于两个常见的数据集。

航空乘客数据集

让我们从航空乘客数据集开始。这组数据包含了从 1949 年到 1960 年每个月的飞机乘客数量信息。我想从我的 BAN 甜甜圈图中显示的统计数据是某个月的乘客数量以及相对于其他月份的表现。禁令只是显示了当月的乘客数量,而甜甜圈图显示了相对于其他月份的百分比排名。根据四分位数,整个数字被适当地着色以立即显示这是一个好的一周还是不好的一周。我也使用直观的颜色,红色代表不好,绿色代表好。以下是 3 个示例周的曲线图:

墨尔本气温

我使用的第二个数据集是墨尔本从 1981 年到 1990 年的最低温度。这些图显示了相同的统计数据,而 BAN 显示了特定一天的温度。我加入了这个数据集来展示一个不同的色阶,它反映了人们对温度的直觉差异:红色是热的,蓝色是冷的。这里有 4 个例子:

结论

就数据而言,不是每个人都需要相同的粒度级别;简单和直觉是关键。

密码

用于生成这些图的代码可以在这个 github repo 中找到。

论技术在监管现代化中的作用

原文:https://towardsdatascience.com/on-the-role-of-technology-in-regulatory-modernization-f90a8babbc05?source=collection_archive---------11-----------------------

Photo by Giammarco Boscaro on Unsplash

法规挑战

条例是立法权的工具,具有法律效力。它们执行相应法案的意图,这些法案规定了企业必须遵守的要求。为了保护个人消费者的健康、安全和保障以及环境,同时也为了支持一个国家内的商业活动,法规是必要的。然而,它们常常被指责为扼杀创新和商业,因为它们不能有效地应对新的和正在出现的趋势和行业惯例。

当今的监管机构必须平衡申请处理、检查和与利益相关方联络的工作,同时确保法规得到更新以减轻企业负担。面对不断变化的社会经济现实、爆炸性的科技进步和不断变化的行业实践,他们必须做到这一点。随着外部压力越来越大,内部流程越来越复杂,监管机构发现越来越难以分配资源来为公众提供最佳服务。

监管机构的一项重要任务是通过审查法规来寻找那些已经过时到阻碍创新的法规,从而减轻合规性的管理负担。例如,如果一项新的技术创新改变了一个行业内提供产品和服务的机制,那么必须改变原有的法规来应对这一创新。这种监管现代化的缓慢变化可能会给企业带来沉重负担,最终导致上市计划的延迟并降低业务增长。

技术如何实现更好的监管过程?

当您考虑到数量庞大的法规时,法规现代化就成了一项艰巨的任务。监管者在资源如此匮乏的情况下,如何持续跟踪行业变化,审查繁琐和过时的监管规定?

幸运的是,监管机构并非束手无策。今天挑战传统监管的技术也可以提供许多重塑监管流程的机会。如今越来越普及的技术可以帮助监管者更快地进行监管审查,自动化重复性任务,并更快地做出决策。在监管现代化的过程中,人工智能和高级分析可以通过识别监管和外部数据之间的关系,加快探索和审查的过程,在组织数据和自动提供智能见解方面发挥关键作用。

下面,我将重点关注监管现代化的过程,并探讨人工智能在改善监管审查和减轻企业监管负担方面的可能应用。我主要探索自然语言处理和文本分析技术如何使监管者能够从监管中获得洞察力,以识别监管中冲突或重叠的规则,找到监管之间的关系,并检测支持创新的监管方法的标志。在接下来的文章中,我将展示我与 Datadex 团队一起构建的一个分析应用程序,它可以帮助加拿大的联邦监管机构改善监管现代化的过程。

监管现代化以及人工智能等技术如何发挥作用

在使监管者能够实现监管现代化的过程中,具有文本分析和自然语言能力的工具将提供巨大的价值。下面我将讨论它们在语言分析、聚类规则和比较分析中的一些应用。

技术和工业实践的快速变化意味着监管者必须不断更新法规以跟上趋势。今天的监管者正在采取一种新的方法,让监管规则的制定更加灵活。做到这一点的一个方法是确保监管语言本身不会给创新制造障碍。在这种情况下,一种自然语言分析工具将是有用的,它可以使监管者识别旧法规中的指令性语言的使用。例如,在适当的上下文中,可以找到表示强制的“应”和“必须”等词,并用“可以”等词代替。类似的能力将有助于识别表示非常具体或详细的要求的短语,例如监管者随后可以用他们想要实现的结果替换的特定措施或测量。

监管机构之间,甚至是同一个监管机构使用不一致的语言会导致误解。经常会出现这样的情况:在不同的语境中使用的同一种语言被用来解释不同的行为。企业很容易将语言的使用与意义联系起来,从而错误地解释不同的行为/程序。在其他情况下,监管者在相同的上下文中使用不同的词或短语,但意思相似。在这种情况下,企业可能会将这些词解释为具有不同的含义。例如,加拿大交通部的法规经常使用不同的词语来描述类似的行为,如“监视”和“监控”。这种含糊不清的语言使用会导致不遵守。例如,如果监管者能够选择监管文本的一个部分和其中的一个词,并检索具有类似上下文但使用不同词的其他法规中的文本参考,则比较分析将有所帮助。

自然语言分析可以提供的另一个有用的功能是让监管者能够看到不同监管文本之间的差异。展示不同特征的法规文本的视觉比较将使监管者能够看到法规的语言是如何根据工业实践而演变的,并允许监管者采用变化的语言风格来形成更灵活和反应更迅速的法规。这也将有利于老监管者,他们可以将自己的监管文本与新监管者的进行比较。

为了处理大量的监管审查,监管者需要一种按共同特征对监管进行分类的系统方式。这种分组可以发现监管之间的模式和联系,从而帮助监管者找到更好的方法来组织审查并与不同的监管者小组进行协调。一种基于类似特征(如上下文、主题或引用)对法规进行分组的聚类工具,可以使监管者探索法规和业务部门之间的关系。在集群上构建可视化工具将允许监管者以图形方式与法规进行交互,并轻松发现法规之间的关系和重叠,以及具有某个部门或行业特有特征的法规变化。

对于监管者来说,监控关于私营部门受监管方的表现的监管文本信息的变化的结果也是令人感兴趣的。如果可以收集外部来源的信息,并按时间顺序组织这些部门的监管变化,那么监管者就能够研究监管文本变化的影响。文本分析还可以将文本的形式、语言和精神的变化与其对相应部门和公众意见的影响联系起来。当企业违反法规时,由于法律诉讼,法规通常会引起媒体的极大关注。在这种情况下,对于监管者来说,将媒体最关注的词语和短语与法规中的参考文献联系起来是很有价值的。

在起草和咨询阶段,这些能力同样有助于分析公众意见的反馈,帮助监管者确定监管中最受关注的部分。文本分析在不同司法管辖区或国家之间的法规比较分析中也很有用。监管机构如何应对其他国家的产业变革,可以指导一个国家的监管需要如何演变。

随着技术的不断进步,监管机构在制定保护消费者同时确保企业创新和增长的法规时将面临许多挑战。通过以我们在此讨论的方式使用技术,监管机构可以改变他们的工作方式,以确保他们的监管符合当时的最佳实践。为了实现这一愿景,他们必须愿意持续投资发展这些能力,并重新设计他们的工作流程,以找到技术支持的监管现代化的最佳战略。

如果我能帮上什么忙,请不要犹豫,尽管开口。在 LinkedIn 上与我联系,或者给我发一封电子邮件

论 CUDA 围墙花园外的深度学习状态

原文:https://towardsdatascience.com/on-the-state-of-deep-learning-outside-of-cudas-walled-garden-d88c8bbb4342?source=collection_archive---------3-----------------------

Photo by Omar Flores on Unsplash

如果你是一名深度学习研究人员或爱好者,并且你碰巧喜欢私下或专业使用 MAC,每年你都会为你的 GPU 获得最新和最令人失望的 AMD 升级。为什么令人失望?因为你得到的是最新最棒的 Vega GPU,当然不使用 CUDA。

什么是 CUDA,为什么这很重要?

CUDA 是 NVIDIA 开发的并行计算平台和编程模型,用于图形处理单元(GPU)上的一般计算。有了 CUDA,开发人员就可以利用 GPU 的强大功能,大幅提高计算应用的速度。

好的。很好。你需要知道的是,这是正在被用来加速人工神经网络(ann)训练的底层核心技术。这个想法是在 GPU 上运行这些计算昂贵的任务,GPU 有数千个优化的 GPU 核心,与 CPU(对不起,英特尔)相比,这些核心对这种任务来说是无限好的。但为什么我不能在我那款花哨的 7k 美元 2019 年年中 Macbook 上运行这款 8 核、基于 HBMI2 的 Vega 20 GPU。原因。也就是说,像 TensorFlow 和 PyTorch 这样的用于训练人工神经网络的流行库并不正式支持 OpenCL。什么是 OpenCL?

OpenCL(开放计算语言)是一种开放的、免版税的标准,适用于个人计算机、服务器、移动设备和嵌入式平台中各种处理器的跨平台并行编程。

基本上是 AMD 在他们的 GPU 中使用的 GPU 加速(CUDA 是 Nvidia 的专有技术!).具有讽刺意味的是,根据这篇文章,基于 Nvidia CUDA 的 GPU 可以运行 OpenCL,但显然不如 AMD 卡高效。这里顺便介绍一些知识:所有这些都是在“图形处理单元通用计算”(GPGPU)的旗帜下运行的,也就是说,如果你的朋友问的话,在 GPU 上运行东西作为主要的计算单元,而不是 CPU。现在回到 CUDA 和 TensorFlow 以及所有其他流行词汇。

以下是两个最流行的深度学习库的 OpenCL 实现状态:

张量流

GitHub 票:https://github.com/tensorflow/tensorflow/issues/22

开放时间:2015 年 11 月 9 日。(这是第 22 期;我们目前在#28961)

Tensorflow 将该问题锁定为“过于激烈”,并于 2019 年 2 月 26 日限制了与合作者的对话。评论 541 条,无受让人。

This screenshot of the first 2 entries in the GH ticket describes the status quo.

PyTorch

GitHub 票:https://github.com/pytorch/pytorch/issues/488

开放时间:2017 年 11 月 18 日(实际上它现在已经关闭,带有“需要讨论”标签)

这张票比另一张更理智。以下是来自脸书人工智能研究团队的一位贡献者的声明:

我们官方没有计划任何 OpenCL 工作,因为:

AMD 本身似乎正在向拥有 CUDA transpiler 的 HIP / GPUOpen 发展(他们已经在 transpiling Torch 的后端做了一些工作)。英特尔正在将其速度和优化价值转移到 MKLDNN 中。在适当的情况下,通用 OpenCL 支持的性能比使用 CUDA/HIP/MKLDNN 要差得多。

进一步挖掘,发现期 22.08.2018:

“免责声明:PyTorch AMD 仍在开发中,所以完整的测试范围还没有提供。PyTorch AMD 运行在镭龙开放计算堆栈(ROCm)之上……"

进入 ROCm(radeonpencomputer),这是一个面向 HPC 和“超大规模”计算的开源平台。对此我发现了以下信息:

  • ROCm 包括基于 LLVM 的 HCC C/C++编译器。HCC 支持直接生成原生镭龙 GPU 指令集
  • ROCm 创建了一个名为 HIP 的 CUDA 移植工具,可以扫描 CUDA 源代码,转换成 HIP 源代码。
  • HIP 源代码看起来类似于 CUDA,但编译后的 HIP 代码可以通过 HCC 编译器在 CUDA 和基于 AMD 的 GPU 上运行。

这似乎是一个巨大的努力。在这一点上,我不得不祝贺 Nvidia 不仅创造了一项伟大的技术,还创造了一个惊人的(以一种糟糕的方式)对其 GPU 平台的技术锁定。值得称赞。我不明白的是为什么 Google 从一开始就决定不正式支持 OpenCL。没有预算?这让我们回到 Tensorflow GH 问题中的精彩评论和迷因。

所以,基本上在某些时候事情会解决的。也许吧。今天你应该买一个 Nvidia GPU,保持理智。

在你说谁关心你的 Macbook 问题之前——不是这个问题。没有一个理智的人工智能研究者会用 Mac 来做任何严肃的人工智能工作。这是关于这样一个事实,脸书公司和谷歌公司正在推动大块的 DL 开发工作(在工具链方面),已经决定只支持一个专有的 GPU 加速标准,因此只有一个 GPU 卡制造商。我是英伟达的超级粉丝。我也完全了解脸书人工智能研究团队在 GitHub 问题上提出的“CUDA 性能优于 OpenCL”的观点。尽管如此,我认为没有理由不投入一些时间和精力(脸书和谷歌都有)来支持多个 GPU 加速框架。而拥有一个更抽象、更开放的接口,以便将来开发新的 GPU 或者更小众的 DL-acceleration 框架又如何?

我也意识到这两个框架都是开源的,任何人都可以为之做出贡献,但是让我们面对现实吧——这两个框架之所以以目前的状态存在,是因为它们背后有两家公司的官方支持(金钱或其他方式)。只针对专有目标的开源代码不完全是 open open source。我们可以做得更好!

P.S .如果我错过了一些关于 PT/TF 和 AMD 支持的重大新闻,请在下面的评论中写下,我会更新我的文章。我喜欢一些好消息!

来源:

https://developer.nvidia.com/cuda-zone2019 年 5 月 23 日

https://www.khronos.org/opencl/2019 年 5 月 23 日

https://community . amd . com/community/radeon-instinct-accelerators/blog/2018/11/13/exploring-amd-Vega-for-deep-learning,23.05.2019

制造业中的一堂课:自动编码器和黄金单位基线

原文:https://towardsdatascience.com/one-class-learning-in-manufacturing-autoencoder-and-golden-units-baselining-4c910038a4b3?source=collection_archive---------16-----------------------

最近,我一直在与想要加入机器学习潮流的制造业客户(既有 OEM 也有 CM )合作。一个常见的用例是更好地检测生产线上有缺陷的产品(或待测设备 /DUT】)。使用机器学习的术语,这属于二进制分类的问题,因为 DUT 只能通过失败

然而,训练一个需要来自通过和未通过两种情况的样本的二项式分类器被证明是不切实际的。有两个原因。

  1. 不平衡的数据。优化制造工艺,以生产具有高产量的器件,即尽可能少的缺陷。收集历史生产数据时发生的一个典型情况是:获得了大量良好/ 通过的数据,但几乎没有不良/ 未通过的数据。
  2. 代表性不足的缺陷样品。有许多不同类型缺陷会导致失败。一一列举已经很困难了,更不用说从所有样本中收集足够的样本了。另一方面,好的数据通常是相似的,更容易定义。

一个小小的哲学讨论(随意分享你的观点,我对此可能是错误的):借用最优化理论的思想,如果我们将好定义为我们努力追求的全局最优,将缺陷定义为次优样本,那么应该只有一个好的定义和无限多个缺陷(假设一个连续的空间)。当然,在实践中,公差接近全局最优的次优样本被认为是好的(由于世界上不完善的过程)。但是那些非常远的将被认为是有缺陷的。

Our depiction of good and bad samples in manufacturing. Good samples are dense, defective samples are sparse.

因此,我们需要找到另一种更适合这种情况的训练模式。理想情况下,新模型必须能够只从好的样本中学习,而拒绝那些看起来与前者大相径庭的有缺陷的样本。一班学习是个不错的人选。

“等等,这听起来很熟悉……不就是用黄金单位做基线吗?”

一个晴朗的下午,一位 T2 六西格玛专家在会议室说道。确实是的!事实证明,一类学习在制造业中并不是一个外来的概念。只是术语不同而已。在质量控制中,工程师通常会收集黄金单位,或已知的良好组件,并对它们进行一些测量(也称为特征工程)。接下来,将根据测量值的分布计算公差极限。一种可以用来计算这种极限的统计方法叫做部分平均测试(由汽车电子委员会出版)。在生产过程中,测量值在限值内的设备将被通过,而在限值外的设备则不合格。

Part Average Testing Limit Calculation

Part Average Limits applied to distribution of measurement values

下图显示了整个基线化过程。

Golden Unit Baselining

特色工程

棘手的部分是决定提取什么特征。传统上,这需要深厚的领域专业知识。因此,预计将有数百种算法部署在生产线上,每种算法都经过精心设计,以识别某些缺陷的存在。机器学习的想法是一直消除这种人工干预,让模型从提供给它的海量数据中发现共性和差异。

尽管如此,不要误解我,这样的“传统”方法实际上是相当准确的。我曾与领域专家合作,他们可以在不到一秒钟的时间内直观地识别某些设备中的缺陷(直到现在我仍然感到惊讶)——他们编写了非常擅长识别这些缺陷的算法。在我看来,机器学习可以作为现有算法的补充。

在本文的其余部分,我将简要概述一门课的学习是如何完成的。我将通过一个被称为自动编码器神经网络的类学习的特定算法实现。然而,我不会深入研究自动编码器的理论。我把它留给另一个帖子。

我们还将假设收集的测量值是图像的形式(例如视觉检查系统)。将使用来自 MNIST 手写数字的虚拟数据集。

基于黄金单位的自动编码器重构误差计算零件平均极限

我们的实验设置是这样的:假设来自好设备的图像看起来像数字 1。因此,在训练期间,我们将只输入数字 1 的图像。为了测试这个模型的有效性,我们将对一组看不见的数字 1(好样本)和数字 2(坏样本)进行测试。假设数字 1 的重构误差将是低的,而数字 2 的重构误差将是高的。如果这是真的,那么我们可以使用重建误差作为一个特征。整个管道绘制如下图(注意与黄金单位基线相似)。

One Class Learning

本教程中的大部分代码来自 [Keras 的《自动编码器基础教程](# https://blog.keras.io/building-autoencoders-in-keras.html)。

首先,让我们限制 tensorflow-keras 将消耗的 GPU 资源量。默认情况下,它会尝试保留所有可用的内存。在这种情况下,我们将只占用 40%的可用内存。

import tensorflow as tf
import tensorflow.keras.backend as K"""
Limit GPU memory consumption
"""tfgraph = tf.get_default_graph()with tfgraph.as_default():
    config = tf.ConfigProto(
        intra_op_parallelism_threads=12
    )
    # 0.4 means only 40% of GPU memory will be used
    config.gpu_options.per_process_gpu_memory_fraction = 0.4
    tfSess = tf.Session(config=config)
    K.set_session(tfSess)

之后,我们可以从 Keras 加载 MNIST 手写数字数据集。随后,我们将图像强度值从 0–255 归一化到 0–1。这允许我们在自动编码器的最后一层使用 sigmoid 激活函数(因为输出域也将在 0 和 1 之间)。如果我们坚持输入为 0–255,我们将不得不相应地调整自动编码器的输出,因为默认情况下,没有输出范围为 0–255 的激活函数。

提示:确保您的神经网络的输入和输出具有相同的域。否则无论使用多少个纪元,你的训练损失都不会正确收敛。

# import library dependencies
import numpy as np
import matplotlib.pyplot as plt
from keras.datasets import mnist# import mnist dataset
(x_train, y_train), (x_test, y_test) = mnist.load_data()# normalization
x_train = x_train.astype('float32') / 255.
x_test = x_test.astype('float32') / 255.
x_train = np.reshape(x_train, (len(x_train), 28, 28, 1))  # adapt this if using `channels_first` image data format
x_test = np.reshape(x_test, (len(x_test), 28, 28, 1))

然后,我们将数据分成好的样本(1 的图像)和坏的样本(2 的图像)。

# get trainData of digit 1 only
trainX, trainY = zip(*filter(lambda x: x[1] == 1, zip(x_train, y_train)))
trainX = np.array(trainX)# get testData of digit 1 only
testGoodX, testGoodY = zip(*filter(lambda x: x[1] == 1, zip(x_test, y_test)))
testGoodX = np.array(testGoodX)

Good Samples i.e. images of 1s

# get testData of digit 2 only
testBadX, testBadY = zip(*filter(lambda x: x[1] == 2, zip(x_test, y_test)))
testBadX = np.array(testBadX)

Bad Samples i.e. images of 2s

为了简单起见,我们将使用 Keras 中自动编码器的[默认定义。我们在这里做的唯一额外的事情是将编码层展平为中间的 2 神经元瓶颈层。注意,这个选择是任意的。在这个实验中,我没有进行任何超参数搜索,因为我只是想做一个简单的介绍。至于 2-神经元的选择,稍后当我试图在 2D 空间中可视化编码嵌入时,这将是有用的。](# https://blog.keras.io/building-autoencoders-in-keras.html)

# [https://blog.keras.io/building-autoencoders-in-keras.html](https://blog.keras.io/building-autoencoders-in-keras.html)from keras.layers import Input, Flatten, Reshape, Dense, Conv2D, MaxPooling2D, UpSampling2D
from keras.models import Model
from keras import backend as Kinput_img = Input(shape=(28, 28, 1))  # adapt this if using `channels_first` image data format# decode
x = Conv2D(16, (3, 3), activation='relu', padding='same')(input_img)
x = MaxPooling2D((2, 2), padding='same')(x)
x = Conv2D(8, (3, 3), activation='relu', padding='same')(x)
x = MaxPooling2D((2, 2), padding='same')(x)
x = Conv2D(8, (3, 3), activation='relu', padding='same')(x)
# at this point the representation is (4, 4, 8) i.e. 128-dimensional
encoded = MaxPooling2D((2, 2), padding='same')(x)# flatten and compress
shape = K.int_shape(encoded) 
bn = Flatten()(encoded)
bn = Dense(2)(bn)
bnRec = Dense(shape[1] * shape[2] * shape[3], activation='relu')(bn)
encoded = Reshape((shape[1], shape[2], shape[3]))(bnRec)# encode
x = Conv2D(8, (3, 3), activation='relu', padding='same')(encoded)
x = UpSampling2D((2, 2))(x)
x = Conv2D(8, (3, 3), activation='relu', padding='same')(x)
x = UpSampling2D((2, 2))(x)
x = Conv2D(16, (3, 3), activation='relu')(x)
x = UpSampling2D((2, 2))(x)
decoded = Conv2D(1, (3, 3), activation='sigmoid', padding='same')(x)# create encoder
encoder = Model(input_img, bn)
# create autoencoder
autoencoder = Model(input_img, decoded)
autoencoder.compile(optimizer='adadelta', loss='mse')
autoencoder.summary()

Autoencoder Summary

下一步是训练自动编码器模型。我们称之为。fit()函数,并为其提供 1s 的图像。至于验证,我们放 2 的图像。请注意,在反向传播过程中不会考虑验证数据集。我把它放在那里,以便我们可以看到随着训练的进行,1 和 2 的图像之间的重建误差如何发散。

history = autoencoder.fit(trainX, trainX,
                epochs=30,
                batch_size=128,
                shuffle=True,
                validation_data=(testBadX, testBadX))

然后,我们可以绘制 1s(好)和 2s(差)图像在各时期的重建误差。可以观察到,1s 的误差随时间降低,而 2s 保持高电平。这意味着自动编码器已经学会了重建好的图像,它已经用(1s)进行了训练,但没有重建坏的图像(2s)。

# summarize history for loss
plt.figure(figsize=(10, 3))
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.title('model loss')
plt.ylabel('loss')
plt.xlabel('epoch')
plt.legend(['good', 'bad'], loc='upper left')
plt.show()

Reconstruction Error for Good and Bad Samples over Time

以上误差只是点估计。我们需要看到重构误差的整体分布,以便计算公差极限(例如,部分平均测试极限)。从下面的图表中,我们可以看到,确实差的图像比好的图像具有更高的重建误差。

# predict
predGood = autoencoder.predict(testGoodX)
predBad = autoencoder.predict(testBadX)# reconstruction error
rec1 = np.sum((predGood - testGoodX)**2, axis=(1, 2, 3))
rec2 = np.sum((predBad - testBadX)**2, axis=(1, 2, 3))# histogram
plt.figure(figsize=(10, 5))
plt.subplot(2, 1, 1)
plt.hist(rec1, bins=30, range=(0,300), color='g')
plt.tick_params(axis='x', which='both', bottom=False, top=False, labelbottom=False)
plt.ylabel("count of good images")plt.subplot(2, 1, 2)
plt.hist(rec2, bins=30, range=(0,300), color='r')
plt.xlabel("reconstruction error")
plt.ylabel("count of bad images")plt.show()

Reconstruction Error for good (Top) and bad (Bottom) images

我们现在可以计算零件平均极限。遵循黄金单位的基线实验,我们将只使用来自好样本的误差,并相应地计算极限。产生的阈值如下所示。

# Part Average Limit
robustMean = np.median(rec1)
robustStd = (np.quantile(rec1, 0.75) - np.quantile(rec1, 0.25)) / 1.35
PAUL = robustMean + 6 * robustStd
PALL = robustMean - 6 * robustStd# histogram
plt.figure(figsize=(10, 4))
plt.hist(rec1, bins=30, range=(0,300), color='g', alpha=0.5, label='good samples')
plt.hist(rec2, bins=30, range=(0,300), color='r', alpha=0.5, label='bad samples')
plt.xlabel("reconstruction error")
plt.ylabel("count of images")
plt.axvline(x=PAUL, c='b')
plt.axvline(x=PALL, c='b')
plt.legend()
plt.show()

Part Average Limit on Reconstruction Error

以下是自动编码器输出的一些好的和坏的图像的例子。我们可以直观地看到,1s 的图像可以很好地重建,而 2s 则不能。有趣的是,自动编码器在 2s 图像上的输出看起来奇怪地类似于 1s。我对此没有理论上的保证,但从经验上看,该模型的解码器部分似乎只学会了构造具有一定变化程度(例如角度和笔画)的 1,而没有学会其他数字。

Autoencoder’s reconstruction of good images

Autoencoder’s reconstruction of bad images

为了进一步了解解码器如何用不同的笔画和角度构建 1 的图像,我们可以看看自动编码器模型的瓶颈层中产生的编码。我们想看看那里是否有任何建筑。会不会有一些具有特定笔画/角度的图像簇?

由于我们已经将信息压缩到一个 2 神经元层中,我们可以很容易地将每个图像表示为一个 2 维向量,并在 2D 图中可视化它们。

testGoodEncodedX = encoder.predict(testGoodX)
np.shape(testGoodEncodedX)plt.figure(figsize=(8, 8))
plt.scatter(testGoodEncodedX[:,0], testGoodEncodedX[:, 1])
plt.show()

2D Scatter Plot of Encoded Images

从分布来看,我们最初怀疑存在具有特定笔划/角度的数字簇似乎是不正确的。也许这个模式看起来更像一个光谱而不是集群?为了形象化这一点,我们可以用它的“原始图像”替换上面图中的每个点。

from matplotlib.offsetbox import AnnotationBbox, OffsetImagefig, ax = plt.subplots(figsize=(20, 20))for x, xEnc in zip(testGoodX, testGoodEncodedX):
    imagebox = OffsetImage(x[:,:,0], cmap=plt.cm.gray)
    ab = AnnotationBbox(imagebox, [xEnc[0], xEnc[1]], frameon=False)                                  
    ax.add_artist(ab)

plt.xlim((testGoodEncodedX[:,0].min(), testGoodEncodedX[:,0].max()))
plt.ylim((testGoodEncodedX[:,1].min(), testGoodEncodedX[:,1].max()))
plt.show()

事实上,我们发现在嵌入空间中存在不同程度的 1 的图像。从左上角到右下角,我们可以看到不同的角度范围。同时,在非对角线方向,当我们靠近左下象限时,我们看到更粗的笔画。

结论

我必须首先道歉,我不能使用来自真实生产线的数据集。尽管如此,我希望这个简单的教程能让你更好地理解一个类学习和黄金单位基线在实践中是多么的相似。我提供了一个简单的 python 代码演练,以展示我们通常在实践中分析的一个类学习的各个方面。

免责声明:在处理过来自真实工厂车间的数据后,我可以证明现实比这个简单的 1 和 2 的图像样本要混乱得多。需要做大量的预处理工作。此外,并非所有的数据标签都是可信的——因为这些标签是由人工标注的,所以可能会因不一致而出现错误。尽管如此,基本概念保持不变。

一键编码使你的基于树的集合变得更糟,这是为什么?

原文:https://towardsdatascience.com/one-hot-encoding-is-making-your-tree-based-ensembles-worse-heres-why-d64b282b5769?source=collection_archive---------2-----------------------

优化基于树的模型

Photo by Marita Kavelashvili on Unsplash

我是弗吉尼亚大学数据科学专业的一名硕士学生,正在从事许多机器学习项目。每周,我都会解决一个我在项目中遇到的问题以及一个可行的解决方案。

大多数真实世界的数据集是分类变量和连续变量的混合。虽然连续变量很容易适应所有的机器学习模型,但分类变量的实现在不同的模型和不同的编程语言中有很大的不同。例如,R 使用一种称为 factor 的变量类型处理类别,这种类型可以完美地适应所有模型,而 Python 则要求您将类别转换成标签编码,以便模型工作。Python 是我选择的编程语言,我经常对分类变量进行某种编码。一般来说,一个热编码为模型提供了更好的数据分辨率,大多数模型最终表现更好。事实证明,并非所有模型都是如此,令我惊讶的是,对于具有高基数分类变量的数据集,随机森林的表现一直较差。

测试设置

作为科比·布莱恩特的粉丝,我决定使用他的投篮选择数据来建立一个模型,以预测在特定情况下一个投篮是否会命中。基于特征重要性分析,很明显描述射击类型的两个变量在预测给定射击的结果中是最重要的,并且两个变量都是分类的。我在数据集上用标签编码(假设有顺序)和一键编码运行随机森林,结果几乎是一样的。事实上,是否有顺序似乎并不重要。

模特们表现如何?

除了预测的准确性,我还使用了模型的对数损失进行比较,因为这是 Kaggle 比赛的评估标准。

Snapshot of Performance

我们通常认为一键编码可以改进模型,但是正如截图所示,采用一键编码的模型比没有采用一键编码的模型性能要差得多。一键编码使对数损失减少了 0.157 个单位。Kaggle 竞赛的获胜者是由最轻微的利润决定的,0.05 的偏差可能是排行榜上前 75%和前 25%之间的差异。既然我们已经确定了一键编码使模型变得更糟,那么让我们检查一下为什么会发生这种情况的原因。

为什么会出现这种情况?

为了理解这一点,让我们进入基于树的模型的内部动态。对于每个基于树的算法,都有一个子算法用于根据要素和值将数据集分割成两个条柱。分割算法考虑所有可能的分割(基于所有特征和每个特征的所有可能性值),并根据标准找到最佳分割。我们将不会进入该标准的细节(有多种方式来做到这一点),但是定性地说,该标准帮助子算法选择使箱的杂质最小化的分裂。纯度是分类问题中特定箱中阳性或阴性样本数量的代表。我发现了一个非常有用的形象化方法,可以帮助我理解这个概念。

Dense Decision Tree (Model without One Hot Encoding)

如果选择一个连续变量进行分割,那么树可以分割的值将有很多选择,并且在大多数情况下,树可以向两个方向生长。从包含大部分连续变量的数据集得到的树看起来像左边图中的东西。

Sparse Decision Tree (Model with One Hot Encoding)

在这种情况下,分类变量自然处于劣势,并且只有很少的分裂选项,这导致决策树非常稀疏。在只有少量级别的变量中,情况会变得更糟,而一次性编码属于只有两个级别的类别。这些树通常倾向于向一个方向生长,因为在分类变量的每个分裂处只有两个值(0 或 1)。该树在虚拟变量中向零的方向生长。如果这没有意义,请密切关注下面的例子。

Dataset A with Dummy Variables

例如,考虑以下数据集,该数据集包含具有级别 A、B、C 和 d 的
分类变量的虚拟变量。如果我们要为该数据拟合一个决策树,以便理解拆分,它将类似于以下内容。

Decision Tree for Dataset A

总之,如果我们有一个 q 水平的分类变量,树必须从((2^q/2)-1)分裂中选择。对于一个虚拟变量,只有一个可能的分裂,这导致稀疏。

对模型性能的影响

既然我们已经理解了为什么带有虚拟变量的数据集的决策树看起来像上图,我们可以深入理解这如何影响预测准确性和其他性能指标。

  1. 通过对分类变量进行一次性编码,我们在数据集内引入了稀疏性,这是不希望的。
  2. 从分裂算法的角度来看,所有虚拟变量都是独立的。如果树决定在虚拟变量中的一个上进行分裂,每次分裂的纯度增益是非常小的。因此,树不太可能选择一个更接近根的虚拟变量。

验证这一点的一种方法是检查两个模型的特性重要性,看看哪些特性最重要。

特征重要性

尽管提供了更好的性能,但是基于树的模型具有轻微受损的声誉,主要是因为它的可解释性,这是由于计算特征重要性的方式而产生的。大多数树集成中的特征重要性是基于重要性分数来计算的。重要性分数是对特征被选择用于分裂的频率以及作为选择的结果获得了多少纯度的度量。

最重要的特性是 action_type,它是一个高基数的分类变量,显然比它前面的变量重要得多。为了提供一些上下文,我使用了 one-hot 编码 action_type 和 combined_shot_type,它们都是高基数分类变量。显然,虚拟变量增加了数据集的维数,维数灾难开始起作用,并产生了下面的特征重要性图表。这显然是无法解释的。

为了放大视角,我决定看看对预测影响最大的前 15 个特征。

当我们检查上面的图表时,很明显,只有一个虚拟变量出现在前 15 位,并且也出现在第 14 位,这验证了我们关于分裂变量选择的假设。一次性编码还模糊了编码中不涉及的特征的重要性顺序,这使得模型效率低下。

链接到 Github

基数大的一次性编码分类变量会导致基于树的集成效率低下。算法将给予连续变量比虚拟变量更大的重要性,这将模糊特征重要性的顺序,导致较差的性能。

额外阅读

  1. 可视化—http://www.r2d3.us/visual-intro-to-machine-learning-part-1/
  2. 教科书—https://web.stanford.edu/~hastie/ElemStatLearn//
  3. 参与讨论—https://www.kaggle.com/c/zillow-prize-1/discussion/38793
  4. 所有类型的编码摘要—https://medium . com/data-design/visiting-categorial-features-and-Encoding-in-decision-trees-53400 fa 65931

一次性编码、多重共线性和虚拟变量陷阱

原文:https://towardsdatascience.com/one-hot-encoding-multicollinearity-and-the-dummy-variable-trap-b5840be3c41a?source=collection_archive---------0-----------------------

本文讨论了由多重共线性问题引起的虚拟变量陷阱

到目前为止,我在机器学习方面的每个新话题都有一些我从未见过的东西。但这不仅仅是看不见的话题,而是我曾经经历过的话题有一些我忘记了的东西。虚拟变量陷阱就是这样一个细节,我完全忘记了它的存在,直到 3-4 个月前我回去做分类器。

在开始虚拟变量陷阱的确切内容之前,我们需要熟悉一些术语。正式的定义可以在谷歌上搜索,所以我将写下一个非正式的描述,这对于本文的上下文来说应该足够了。

分类变量

范畴变量是那些可以从有限集合中取值的变量。对于这样的变量,它们所占据的值可以具有内在的顺序(例如,速度:{低,中,高} )。这样的变量被称为有序分类变量。另一方面,一些分类变量可能没有任何内在排序(例如,性别:{男性,女性} )。这样的分类变量称为名义分类变量。

如果您知道将分类变量编码成数字的常见做法,您就会知道通常建议对它们进行 One-hot-encoded。有两个原因:

  1. 大多数机器学习算法不能直接处理分类变量,它们需要转换成数字。
  2. 即使我们找到了一种直接处理分类变量而不把它们转换成数字的方法,我们的模型也会偏向我们使用的语言。例如,在动物分类任务中,如果标签是{'rat ',' dog ',' ant'},那么使用这样的标签方法将训练我们的模型只预测英语标签,这将对模型的可能应用施加语言限制。

为了解决这些问题,我们可以将分类变量值编码为数字,如下所示:

案例 1:

序数分类变量速度(如上所述)可以编码为:

{ '低':1,'中':2,'高':3}。

案例二:

对于动物分类任务(如上所述),标签变量是一个名义分类变量,可以编码为:

{ '老鼠':1,'狗':2,'蚂蚁':3}。

我们先讨论案例 2:

这里有一个主要的问题——动物分类问题中的标签不应该被编码成整数(就像我们上面所做的那样),因为那样会强制执行明显不正确的自然排序:【大鼠】<【狗】<【蚂蚁】。虽然我们知道不存在这样的排序,并且数字 1、2 和 3 在我们编码的标签中不包含任何数字排序,但我们的机器学习模型将无法直观地理解这一点。如果我们将这些数字直接输入模型,成本/损失函数很可能会受到这些值的影响。我们需要用数学方法来模拟我们的这种理解。我们就是这样做的。

案例 1:

速度是一个序数变量。我们可能会认为关系:【低】<【中】<【高】是有道理的,因此,使用标签 1、2 和 3 应该不是问题。不幸的是,事实并非如此。使用标签 100、101 和 300000 代替 1、2 和 3 仍然具有与''、和''相同的关系。用 1,2,3 没什么特别的。换句话说,我们不知道‘中速’的速度比‘低速’的速度大多少,也不知道它比‘高速’的速度小多少。这些标签之间的差异可能会潜在地影响我们训练的模型。因此,我们可能还想对变量‘speed’进行一次热编码。

在这一点上,我希望我们理解分类变量是什么,以及为什么我们想要对它们进行一次性编码。

多重共线性

当数据集中的两个或多个独立变量(也称为要素)相互关联时,就会出现多重共线性。我们可以使用几种方法来测量双变量情况下的相关程度和方向(更多信息相关测量),而多重共线性通常使用方差膨胀因子来测量(更多信息多重共线性测量)。简而言之,当独立变量彼此(几乎)线性相关时,就说数据集中存在多重共线性。

Fig. 1. Perfect Multicollinearity (perfect linear dependence between x_i and other independent variables)

如图 1 所示的情况。被称为完美多重共线性。同样,我们也有不完全多重共线性的情况,其中一个或多个高度线性的关系可能是我们所关心的。这些会直接影响线性回归分析(有关这方面的更多信息,请参考这些课堂讲稿)。然而,我们将从任何通用机器学习算法的角度来讨论它们的影响。

在这一点上,我希望我们理解什么是多重共线性。

Python 中的 OneHotEncoding

在我们进入本文的最后一部分之前,让我们看看如何对分类变量进行编码。

One-hot-encoder 为分类列的每个唯一值返回一个向量。每个这样的向量只包含一个' 1 ,而向量中的所有其他值都是' 0 '(参见下面的图 4),因此命名为one-hot-编码器。

可能,也应该有你选择的语言的包,但是因为我一直在用 Python 做所有机器学习和数据科学相关的东西,所以我只包括来自 Python 控制台的片段。在下面的讨论中,我将引用 Python 的 pandas 库的流行昵称,将‘PD’numpy 称为’NP’。

我用的是自制的 pd。DataFrame 对象看起来像:

Fig. 2. An example pandas.DataFrame object

Fig. 3. Datatypes of respective columns

速度是分类变量,而数值列是非分类列。

假设我们正在进行一个项目,我们决定对“速度”列进行一次热编码。

方法一:pd.get_dummies

Fig. 4. pd.get_dummies returns a dataframe with one-hot-encoded columns

pd.get_dummies ( 文档 ) 返回一个包含 one-hot-encoded 列的新 dataframe。我们可以观察到并不是所有的列都被编码了。这是因为,如果没有任何列被传递给 pd.get_dummies 以告知哪些列要进行 one-hot-encoding,则默认情况下,它采用数据类型为‘object’的列。然后对它们进行编码,并返回一个新的 dataframe,用新的列替换旧的分类列在图 3 中,我们可以看到“速度”列属于类型“对象”。图 4。显示该列在返回的数据帧中不再存在,并且已被新列替换。我们还可以观察到''已经映射到一个向量:低->**【0,1,0】,类似地,中->【0,0,1】高->【1,0,0】。请注意,每个向量中只有一个“1”。还要注意,每个向量都是三维的。这是因为'速度'有三个唯一值。事实上,独热向量的维数等于分类列在数据集中所占的唯一值的数目。这里,编码已经完成,因此在向量的第一个位置 1 表示'速度=高',在第二个位置 1 表示'速度=低'等等。

方法二:sk learn . preprocessing . onehotencode

我更喜欢使用sk learn . preprocessing . onehotencode而不是 pd.get_dummies 这是因为sk learn . preprocessing . onehotencode返回了sk learn . preprocessing . onehotencode类的一个对象。我们可以将这个对象放在训练集上,然后使用同一个对象来转换测试集。另一方面, pd.get_dummies 返回一个数据帧,其编码基于我们传递给它的数据帧中的值。这对于快速分析来说可能是好的,但是对于一个扩展的模型构建项目,你在训练集上训练,然后在测试集上测试,我建议使用sk learn . preprocessing . onehotencoder

使用sk learn . preprocessing . onehotencoder不像使用 pd.get_dummies 那么简单。我们可以在下面的图 5 中看到这一点。

Fig. 5. One-hot encoding using sklearn.preprocessing.OneHotEncoder

您可能已经注意到,我们首先使用 LabelEncoder 对分类列进行了整数编码。这是因为 OneHotEncoder 要求分类列包含数字标签。 fittransform 方法需要传递形状为 (m,n)np.array 对象。最后, fit 方法返回一个 OneHotEncoder 对象,该对象适用于传递给它的数据。这个过程是漫长的,但是你最终得到了一个合适的对象,它可以在以后的测试集中使用。Scikit-learn 提供了一个方法 fittransform-fit _ transform的组合版本,有助于减少一两行代码(参见文档)。

虚拟变量陷阱

虚拟变量陷阱直接体现在应用于分类变量的一键编码中。如前所述,独热向量的大小等于分类列所占的唯一值的数量,并且每个这样的向量中恰好包含一个“1”。这将多重共线性引入我们的数据集。从图 4 中的编码数据集(其等同于图 5 中的编码数据集),我们可以观察到以下线性关系(图 6):

Fig. 6. Perfect Multicollinearity after one-hot encoding

图 6 是完全多重共线性的情况。我们用来编码分类列的向量被称为'虚拟变量'。我们打算解决使用分类变量的问题,但是被多重共线性的问题困住了。这被称为虚拟变量陷阱。

如前所述,这会直接影响线性回归分析,因为线性回归假设数据集中不存在多重共线性。然而,它也提出了机器学习任务中的一些其他问题。比方说,我们在数据集上训练一个逻辑回归模型。我们期望我们的模型学习以下等式的权重:

Fig. 7. Sigmoid function

特别是,对于我们数据集中的要素,以下是逻辑回归将学习的权重:

并且特征向量 X 是:

显然,sigmoid 函数分母中指数函数的幂实际上影响了 y_hat 的值,并且包含可训练的权重。这个表达式实际上扩展为:

Equation- 1: Expanding the power term in sigmoid function

根据图 6 中的关系,我们可以将三个自变量中的任何一个用另外两个来表示,让我们以 LHS 的 speed_lowspeed_mediumspeed_high: 来表示

Equation-2: Expressing speed_low in terms of speed_medium and speed_high

为什么不好?

正如我们前面讨论的,这对于线性回归问题有直接的影响。因此,以下是对所有算法通用的问题的总结。

  1. 我们可以用等式-2 中的值替换等式-1 中的 speed_low 。这实际上意味着(至少)我们正在使用的一个特征是多余的-该特征可以是三个特征中的任何一个,因为方程-2 可以用 LHS 中的任何一个来编写。所以,我们让我们的模型学习一个不需要的额外重量。这消耗了计算能力和时间。这也给出了一个优化目标,该目标可能不太合理,并且可能难以实现。过多的自变量也可能导致维度 y 的诅咒。如果多重共线性也随之而来,事情会变得更糟。
  2. 我们不仅希望我们的模型预测准确,还希望它是可解释的。例如,逻辑回归被期望学习对应于相对更重要的特征的相对更高的权重值。更重要的特征对最终预测的影响更大。但是如果特性是相关的,那么就很难判断哪个特性在最终决策中更有“发言权”,因为它们的值实际上是相互依赖的。这会影响权重的值。换句话说,权重不仅取决于自变量与因变量的相关性,还受到自变量之间相关性的影响。例如,如果 speed_high 的值比其他值高,那么 speed_lowspeed_medium 必须更低,使得总和总是 1。我们假设重要性(speed_high ) =重要性(speed_medium) =重要性(speed_low)。但是由于 speed_high 的值比其他自变量的值高,因此与之对应的学习权重将比其他两个低得多。实际上,我们希望它们各自的权重(几乎)相等。

因为一次热编码直接导致完美的多重共线性,所以我们从编码的要素中删除其中一列。例如,在这种情况下,我们可以选择删除 speed_medium ,但这种选择完全是任意的。

下面是我们如何处理这个问题(删除其中一个编码列):

  1. 当我们使用 pd.get_dummies 时,我们可以传递一个额外的参数,drop _ first = True(documentation)来删除编码后得到的第一个新列(也称为第一个虚拟变量)(图 7):

Fig. 7. drop_first=True

将图 7 中返回的数据帧与图 4 中得到的输出进行比较。我们发现 speed_high 从编码数据帧中被删除。不使用 drop_first=True 会让 sklearn 使用该参数的默认赋值,即 False

2.当我们使用sk learn . preprocessing . OneHotEncoder并想要删除其中一个新列时,我们传递 OneHotEncoder 类的参数 drop='first' 构造函数(文档)。 然而,这似乎并不支持所有版本的 sklearn(我得到了一个错误,因为我的 sk learn . preprocessing . onehotencoder 版本不支持‘drop’参数),所以您可能需要更新 python 包,然后才能在您的系统上使用它 。虽然您可以通过手动写入一两行来手动删除其中一个虚拟变量(图 8),但如果您有多个分类列,并且每个分类列中有太多要处理的类别,则可能很难跟踪对数据框架所做的更改。

Fig. 8. Manually dropping one of the dummy variables

转换(或者, fit_transform )返回的 dataframe 在所有其他列之前添加新列(图 8)。因此,为了删除第一列,我们可以使用数组切片,如图 8 所示。然而,如前所述,这样做可能会变得笨拙。

结论

我希望这篇文章能够对多重共线性、一次性编码和虚拟变量陷阱进行全面的描述。这篇文章完全基于我的个人经验,事实来自可靠的来源(在每个这样的概念旁边已经提到了链接)。所以,如果你在文章中发现任何不一致的地方,请在下面评论。您的反馈将有助于我更好地写作和描述。期待收到你的来信。

谢谢你。

用 Miptools 进行一分钟 CT 预处理

原文:https://towardsdatascience.com/one-minute-ct-preprocessing-with-miptools-8f8c3436c302?source=collection_archive---------22-----------------------

如何高效地预处理用于深度学习的 CT 图像

让我们面对它,医学图像处理是具有挑战性的。今天的医学成像机器能够产生具有大量信息的大量图像。然而,从图像中提取这些信息需要对成像技术有深入的理解。作为一名研究医学图像处理和机器学习的研究生,我发现除了众所周知的pydicomNiBabel之外,缺乏好的医学图像预处理库。我最近参加了 RSNA 颅内出血检测比赛,这提醒了我图像预处理质量的重要性。

Photo by Harlie Raethel on Unsplash

这是一个未经任何预处理的正常脑部 CT 图像示例:

大脑在哪里?灰质/白质在哪里?显而易见(没有双关语),可视化的 CT 缺少一些重要信息。他们没有出现的真正原因是因为我们错过了可视化之前的一个非常重要的步骤。当放射科医生查看 CT 图像,特别是脑部 CT 扫描时,他们的清单上最重要的项目之一就是开窗。人类只能感知范围从 0 到 255 的灰度(我想比 50 多一点),而 CT 扫描的 Hounsfield 单位(HU)范围从-1000 到+2000。我不打算在本教程中深入描述胡的转变过程,但如果你感兴趣,这里有一篇关于胡的有用的文章

为了正确显示 CT 扫描,使用窗口将 HU 数转换为灰度值。用miptools很容易做到这一点:

第一次开窗是简单的元数据开窗,可以通过设置windowing='simple'来指定。这会提取 DICOM 文件的窗口中心和宽度,并相应地将图像裁剪到指定的范围。我们转换后的图像应该是这样的:

现在我们至少可以在图像中看到大脑了,对吧?我们还可以通过 bsb(大脑、硬膜下、血液)窗口将更多信息编码到我们的转换图像中。这听起来可能很复杂,但我们只是将我们的图像转换为 3 个窗口:大脑窗口(中心:40,宽度:80),硬膜下窗口(中心:80,宽度:200)和骨窗口(中心:600,宽度:2000)。最后,我们把 3 个窗口连接起来,作为我们变换后的图像的 3 个通道。执行代码片段中的第 7 行应该会产生下图:

上面显示的图像是用 bsb 窗口转换的。尽管它看起来只是我们元数据转换图像的红色版本,但它编码了更多信息,可能更适合深度学习目的。回想一下,彩色图像可以表示为三维阵列。我们能放入这 3 个维度的信息越多,我们的深层网络就能从我们的训练图像中提取和学习越多。

我们可以使用的另一种预处理技术是重采样。特定的扫描可能具有像素间距[0.5, 0.5],而另一个患者的扫描可能具有像素间距[0.8, 0.8]。保持像素间距一致很重要,否则我们的网络可能很难推广。

通过指定resampling=True,我们可以用一行代码将像素间距重采样为[1, 1]。使用带有重采样的简单元数据窗口会得到以下图像:

医学图像处理中有很多先进的技术,但为了简单起见,我不会在本教程中一一介绍。如果你喜欢阅读这篇文章,请查看并启动我的 miptools 源代码库。我保证在不久的将来会增加更多的功能,因为我现在在学校很忙。

一个神经网络,多种用途

原文:https://towardsdatascience.com/one-neural-network-many-uses-image-captioning-image-search-similar-image-and-words-in-one-model-1e22080ce73d?source=collection_archive---------9-----------------------

使用单一模型构建图像搜索、图像标题、相似文字和相似图像

众所周知,神经网络确实擅长一项狭窄的任务,但它们无法处理多项任务。这与人脑不同,人脑能够在惊人不同的任务中使用相同的概念。例如,如果你以前从未见过分形,我现在就给你看一个。

This beauty is courtesy math. (via https://fractalfoundation.org/)

看到分形的图像后,你将能够处理与之相关的多项任务:

  • 在一组图像中,区分分形和猫
  • 在一张纸上,大致画出分形的样子(它不会很完美,但也不会是随意的涂鸦)
  • 将类似分形的图像与非类似分形的图像进行分类(你可以自动将图像从最相似到最不相似进行分类)
  • 闭上眼睛,想象分形是什么样子的(即使没有视觉输入,你仍然可以在一次曝光后想象它。多酷啊!)

你是如何完成所有这些任务的?在你的大脑中有专门的神经网络专门处理所有这些任务吗?

现代神经科学表明,答案是你大脑中的信息在不同部分之间共享和交流。具体是如何做到的是一个研究领域,但我们有一些关于这种多任务性能可能如何发生的线索。答案可能在于数据在神经网络中是如何存储和解释的。

奇妙的表现世界

顾名思义,表示就是信息在网络中的编码方式。当一个单词、一个句子或一幅图像(或者其他任何东西)被作为输入提供给一个经过训练的神经网络时,随着权重乘以输入和激活的应用,它会在连续的层上进行转换。最后,在输出层,我们得到数字,我们解释为类标签或股票价格或网络训练的任何其他任务。

这种输入->输出的神奇转换是由于连续层中发生的输入转换而发生的。这些输入数据的转换被称为表示。一个关键的想法是每一层都让下一层的工作变得容易。使连续层的寿命更容易的过程导致激活(特定层的输入数据的转换)有意义的

我说的有意义是什么意思?让我们看一个图像分类器不同层激活的例子。

图像分类网络所做的是将像素空间中的图像转换到越来越高的概念空间。因此,以 RGB 值表示的汽车图像将开始在第一层的边缘空间中表示,然后在第二层的圆形和基本形状空间中以及在预最终层中,它将开始在高级对象中表示,如车轮、门等。

这种越来越丰富的表现形式(由于深层网络的等级性质而自动出现)使得图像分类的任务变得微不足道。最后一层要做的就是权衡轮子和门的概念,使之更像汽车,耳朵和眼睛更像人。

你能对陈述做什么?

因为这些中间层存储了输入数据的有意义的编码,所以您可以将相同的信息用于多个任务。例如,你可以用一个语言模型(一个被训练来预测下一个单词的递归神经网络)来解释特定神经元的激活,以预测句子的情绪。

(via Unsupervised Sentiment Neuron)

令人惊讶的事实是,情感神经元在无监督的语言建模任务中自然出现。(参见这篇教程中的精彩评论)。网络被训练来预测下一部作品,在任务中我们没有要求网络预测情绪。也许情感是一个非常有用的概念,网络发明它是为了在语言建模方面做得更好。

一旦你得到表示的想法,你将开始以完全不同的眼光看待深层神经网络。你将开始感觉到表征是一种可转移的语言,它使不同的网络(或同一网络的不同部分)相互交谈成为可能。

通过构建四位一体的网络来探索表征

为了充分理解什么是表示,让我们建立我们自己的深度神经网络,它做四件事:

  • 图像标题生成器:给定一幅图像,为其生成标题
  • 相似词生成器:给定一个词,找出与其相似的其他词
  • 视觉相似图像搜索:给定一幅图像,找出与其最相似的图像
  • 描述图像内容搜索:搜索包含文字描述内容的图像

这里的三个任务中的每一个本身都是一个项目,传统上需要三个模型。但是我们将使用一个型号来完成所有这些任务。

代码将用 Pytorch 写在 Jupyter 笔记本上。你可以从这个库下载。

→ Github 库:【https://github.com/paraschopra/one-network-many-uses】T2ⅲ

第一部分—图像字幕

网上有很多很好的教程来实现图像字幕,所以我不打算深入讲解。我的实现与本教程中的完全相同:构建一个自动图像字幕应用。关键的区别在于,我的实现是在 Pytorch 中,而本教程使用的是 Keras。

要继续学习,您需要下载 Flickr8K 数据集。填写这张表格,你会在你的邮箱里收到一个下载链接。(还有一个直接链接下载 1GB 的 Flickr8K 数据集,虽然我不确定它会像那样保持多久)。将 zip 文件提取到笔记本所在目录下的“Flicker8k_Dataset”文件夹中。你还需要从这里下载字幕。提取文件夹“caption_datasets”中的标题。

型号

图像字幕大致有两个组成部分:a)图像编码器,它获取输入图像,并以对字幕有意义的格式表示它;b)字幕解码器,获取图像表示并输出其文本描述。

图像编码器是深度卷积网络,而字幕解码器是传统的 LSTM/GRU 递归神经网络。当然,我们可以从头开始训练这两者。但是这样做将需要比我们现有的更多的数据(8k 图像)和大量的训练时间。因此,我们将采用一个预先存在的图像分类器,并使用它的预最终层激活,而不是从头开始训练图像编码器。

这是你将在本帖中看到的许多神奇的表示示例中的第一个。我采用了在 ImageNet 上训练的可用于 PyTorch modelzoo 的盗梦空间网络来对 100 个类别的图像进行分类,并使用它来给我一个可以输入到递归神经网络中的表示。

via https://daniel.lasiman.com/post/image-captioning/

请注意,盗梦空间网络从未接受过图像字幕任务的培训。然而,它工作了!

就像我在我的通过机器学习帖子中所做的那样,我们也可以为字幕解码器使用预先训练的语言模型。但是这一次,因为我重新实现了教程中的一个运行良好的模型,所以我简单地跟随并从头开始训练了一个解码器。

完整的模型架构如下所示:

Image via https://daniel.lasiman.com/post/image-captioning/

你可以从头开始训练模型,但这需要在 CPU 上花几天时间(我还没有为 GPU 优化)。但是不要担心!我的笔记本电脑度过了不眠之夜,所以你可以享受已经训练好的模型的成果。(如果你是从零开始训练,请注意,当运行平均损失大约为 2.8 时,我在大约 40 个时期停止了训练)

表演

我已经实现了性能良好的波束搜索方法。以下是网络为来自测试集的图像生成的标题示例(它以前从未见过它们)。

让我们看看网络对我自己照片的说明:

还不错!令人印象深刻的是,该网络知道该图像包含一名身穿白色 t 恤的男子。语法有点问题(我相信多训练可以解决),但基本要点是好的。

如果输入图像包含网络从未见过的东西,它往往会失败。比如我很好奇网络会给 iPhone X 的一张图片贴什么标签。

它做得不太好。但总的来说,我对性能相当满意,这为我们使用 network 在学习为图像添加标题时开发的表示来构建其他功能提供了良好的基础。

第二部分—相似词

回想一下我们如何从图像表示中解码标题。我们将该表示输入 LSTM/GRU 网络,生成输出,将其解释为第一个单词,然后将第一个单词反馈给网络,以生成第二个单词。这种情况一直持续到网络生成一个表示句子结束的特殊标记。

为了将单词反馈到网络中,我们需要将单词转换成表示,这些表示成为网络的输入。这意味着,如果输入层由 300 个神经元组成,对于所有标题中 8000 多个不同单词中的每一个,我们需要有 300 个相关联的数字来唯一地指定该单词。将字典中的单词转换成数字表示的过程被称为单词嵌入(或单词表示)。

我们可以下载和使用像 word2vec 或 GLoVE 这样预先存在的单词嵌入。但是在目前的情况下,我们从零开始学习单词 embedding。我们从随机生成的单词嵌入开始,并探索在训练完成时我们的网络已经学习了关于单词的什么。

由于我们无法可视化 100 维的数字空间,我们将使用一种叫做 t-SNE 的奇妙技术来可视化二维的单词嵌入。t-SNE 是一种降维技术,它试图使高维空间中的邻居在低维空间中仍然是邻居。

单词嵌入的可视化

说够了。让我们看看字幕解码器学习的单词嵌入空间(不像其他语言任务有数百万个单词和句子,我们的解码器在训练数据集中只看到了大约 30k 个句子)。

因此,我们的网络已经了解到,像“play”、“plays”和“playing”这样的词是非常相似的(它们有相似的表示,这从带有红色箭头的紧密聚类中可以明显看出)。让我们探索 2D 空间的另一个领域:

这个区域似乎有成群的数字——“二”、“三”、“四”、“五”等等。另一个:

它知道人和孩子是相似的。此外,它还隐含地推断出物体的形状。

类似的话

我们可以使用 100 维表示来构建一个函数,该函数建议与输入单词最相似的单词。它的工作原理很简单:取 100 维的表示,找到它与数据库中所有其他单词的余弦相似度。

让我们来看看与单词‘boy’最相似的单词:

还不错。“骑手”是一个例外,但“孩子”、“小孩”和“蹒跚学步的孩子”是正确的。网络认为什么和‘追’这个词相似:

“追逐”很好,但我不知道为什么它认为“警察”与追逐相似。

词语类比

关于单词 embeddings 的一个令人震惊的事实是,你可以对它们进行演算。你可以用两个词(比如“国王”和“王后”)减去它们的表示来得到一个方向。当你将这个方向应用到另一个单词表征(比如“男人”)时,你会得到一个接近实际的类似单词(比如“女人”)的表征。这种魔力就是 word2vec 推出时如此出名的原因:

via https://www.tensorflow.org/images/linear-relationships.png

我很好奇字幕解码器学习到的表现是否也有类似的特性。即使我因为训练数据不多(约 30k 句)而持怀疑态度,我还是试了一下。

网络学习到的类比并不完美(有些单词字面上是为<10 times, so network didn’t have enough info to learn). I had to squint my eyes but it sort-of found analogies.

If riding is to sitting, what would walking correspond to? My network things it would be ‘laying’ (which is not bad!).

Similarly, 出现的,如果‘男人’的复数是‘男人’,那么‘女人’的复数是什么:

第二个结果是“女人”,相当不错。

最后,如果草是绿色的,天空会是什么颜色:

网络认为是银色或者灰色,都不是蓝色但是都是颜色。令人惊讶的是,网络能够推断颜色的方向。

第三部分—相似图像

如果单词表示将相似的单词聚集在一起,那么图像表示呢(Inception powered image encoder 输出的图像表示)。我将相同的 t-SNE 技术应用于图像表示(300 维张量,作为字幕解码器第一步的输入)。

可视化

这些点代表不同的图像(我没有拍摄完整的 8K 图像,但它是大约 100 张图像的样本)。红色箭头指向附近的一组制图表达。

所以,赛车聚集在一起。

在类似森林/草地的地方玩耍的孩子也是如此。

篮球运动员聚集在一起。

寻找与输入图像相似的图像

对于相似单词任务,我们被限制在我们的测试集词汇中寻找相似的单词(如果一个单词不存在于测试集中,我们的字幕解码器不会学习它的嵌入)。然而,对于相似图像任务,我们有一个图像表示生成器,它将接受任何输入图像并生成其编码。

这意味着我们可以使用余弦相似度方法来构建按图像搜索的功能,如下所示:

  • 步骤 1:获取数据库或目标文件夹中的所有图像,并存储它们的表示(由图像编码器给出)
  • 步骤 2:当用户想要搜索与他已经拥有的图像看起来最相似的图像时,获取新图像的表示,并在数据库中找到最接近的图像(由余弦相似度给出)

谷歌图片很可能使用这种(或非常相似的)方法来增强他们的反向图片搜索功能。

让我们看看我们的网络做得怎么样。我在果阿度假时点击了下面这张照片。(PS:我爱果阿!)

注意,这个图像是我自己的。我们正在使用的模型从未见过它。当我查询与此类似的图像时,网络从 Flickr8K 数据集中输出以下图像:

这难道不令人兴奋吗?我没想到会有这么好的表现,但是我们做到了。深度神经网络好得不可理喻

第四部分-通过描述来搜索图像

在最后一部分,我们反向运行图像标题生成器。因此,我们输入一个标题(文本描述)并找到最匹配的图像,而不是获取一个图像并为其生成标题。

听起来好得难以置信?其实不是。我们是这样做的:

  • 第一步:不用来自编码器的 300 维图像表示,从一个完全随机的 300 维输入张量开始
  • 步骤 2:冻结整个网络的所有层(即指示 PyTorch 不要计算梯度)
  • 步骤 3:假设随机生成的输入张量来自图像编码器,并将其输入字幕解码器
  • 步骤 4:获取网络在给出随机输入时生成的标题,并将其与用户提供的标题进行比较
  • 步骤 5:比较生成的字幕和用户提供的字幕,计算损失
  • 步骤 6:为输入张量寻找最小化损失的梯度(即,300 维数字中的每一个应该在哪个方向上改变以及改变多少,以便当张量被输入到字幕解码器中时,字幕接近用户提供的字幕)
  • 第七步:改变输入张量的方向,由梯度决定(按照学习速率的要求迈出一小步)
  • 继续步骤 4 至步骤 7,直到收敛或损耗低于某个阈值
  • 最后一步:取最终的输入张量,用它的值通过余弦相似性找到最接近它的图像(在 300 维空间中)

当我们这样做时,结果是不可思议的:

我搜索了‘一只狗’,这是网络找到的图片:

我搜索了《一个微笑的男孩》

最后,当我搜索:

前两个结果是:

令人兴奋,不是吗?

总结和挑战

提醒一下,你可以从我的 github 库下载完成所有这些的代码。它包括数据预处理,模型描述,预训练的图像字幕网络,可视化代码。它不包括 Flickr8K 数据集或字幕,您必须分别从这里和这里下载

我希望你喜欢这篇文章。如果你想更进一步,这里有一个挑战:根据给定的描述生成一个图像。就像从一个随机的起点生成一个与用户提供的标题相匹配的 300 维图像表示一样,您能更进一步,为用户提供的标题从头开始生成一个图像吗?

这比我们在这篇文章中处理的要难 10 倍,但我感觉这是可行的。如果有一种服务不仅能搜索与文本相对应的图像,还能动态生成图像,那该多好啊。

将来,如果 Google Images 这样做,并开始为尚不存在的图像提供结果(比如“两只独角兽在披萨做成的地毯上飞翔”),我不会感到惊讶。

就是这样。我希望你能安全而愉快地探索表象世界。

感谢的点评和评论。

喜欢这个教程吗?也看看我以前的作品:

在 Twitter 上关注我

我定期发关于人工智能、深度学习、创业公司、科学和哲学的推特。跟着我上https://twitter.com/paraschopra

* [## Paras Chopra (@paraschopra) |推特

Paras Chopra 的最新推文(@paraschopra)。跟着我,我会把你带到一条混乱的道路上…

twitter.com](https://twitter.com/paraschopra)*

其中一件事与众不同:地质异常和数据异常检测

原文:https://towardsdatascience.com/one-of-these-things-is-not-like-the-others-geological-anomalies-and-anomaly-detection-with-data-59a1a8b94785?source=collection_archive---------14-----------------------

一位数据科学家和一位地质学家讨论多学科方法

Shaan Hurley, Flickr

在地球科学中,我们经常谈论寻找数据中的异常作为潜在矿化的指标。但是,我们如何定义异常,数据科学家和地质学家如何合作产生新的见解?

地质学家 Holly Bridgwater 和数据科学家 Jess Robertson 博士最近进行了一次聊天,内容是如何以一种对从通才数据科学角度看待地球科学数据的人有意义的方式来描述异常。

请继续阅读,了解他们的观点——或者点击这里观看原始视频

注: 这场讨论是由 探险者挑战赛 引发的,这是一场使用数据来改善矿产勘探流程的全球竞赛——视频对此做了一些具体的引用,但本文做了更多的概括。

霍莉:

今天,我们将主持一个会议,讨论“什么是异常现象,如何在数据中发现异常现象?”我们的目标是帮助数据科学家掌握地质数据。我将扮演地质学家的角色,提出令人沮丧、框架不佳的数据科学问题,Jess 将能够为您翻译这些问题,希望是以一种有意义的方式。手指交叉!

所以我们认为我们要做的是关注地质数据中常见的三种特殊类型的异常。

物理性质

Holly: 首先我们要谈谈岩石的物理特征,特别是地球物理数据。作为一名地质学家,我在这种类型的数据中寻找的是向我表明岩石中物理差异的东西。例如,某些类型的矿体,如硫化物,比周围的岩石密度更大,导电性更好——所以我去寻找可能向我表明密度更大或导电性更好的岩石的信号。

我是如何做到这一点的,首先我找人收集数据,通常是航空地球物理调查,可能是磁力和重力。然后,我让一个比我聪明得多的人对数据做一些数学运算(反演),生成一些典型的彩色网格图像;红色表示高磁场强度,蓝色表示低磁场强度。

Geology is just paint by numbers then, right? (Flickr)

我在这些图像中寻找结构和趋势,这些结构和趋势可能表明一些不同的事情正在发生。我可能在寻找岩石类型或物理特征的特定变化,或者我可能在寻找由密度差异表示的结构或化学变化。

杰西:

我想我应该首先注意到,你刚刚谈到了这些数据的五六个不同的步骤。

这是从仪器上得到的原始数据。

需要对数据进行一些处理,例如,如果是磁力,您需要去除地球磁场的影响,这样您就可以看到当地地质对磁场的影响。然后,你提到了反转,你也提到了漂亮的图像,我认为这是两个独立的步骤。

霍莉:

我想地质学家对我们为什么进行反演的基本描述是,我们正在记录来自地球的原始测量结果,这些测量结果导致信号以某种方式返回——但我们实际上想知道的是它在告诉我们什么。在反演过程中,我们应用一些先验知识来帮助我们确定。

一个精明的勘探地质学家,在做调查之前,会向地球物理学家提供一些你已经知道的岩石特征。因此,如果你已经了解了岩石类型和它们的一些特征,你可以把它们交给地球物理学家,他们可以生成一个更好的模型,以你已知的地质学为荣。

杰西:

因此,从数据科学的角度来看,本质上我们在勘探中做得不太好的事情[注意,杰斯也是地质学家],我们应该做得更好的事情,是理解背景以及试图理解异常

显然,我们知道我们在寻找矿化。我们想找到硫化物的峰值,它会让我们都变得富有。但有时我们没有花足够的时间去真正理解背景是什么样的,岩石的自然可变性是什么——这样我们就可以正确地判断并说“这实际上是一种异常现象”。

我们认为数据科学能够为探索带来的优势之一是,有可能对所有公共数据集进行更大范围的观察,并试图了解其中的自然可变性。然后,当你提出你的异常矿物目标时,你可以说,实际上我们观察了南澳大利亚所有的绿宝石,发现它们有这种地球物理信号,这个东西与那个不同。因此,能够提供这种更大的数据或更高层次的视图是一个额外的好处。

霍莉:

给数据科学家提供没有背景的原始地球物理数据有多困难?

杰西:

数据科学家的部分职责是从数据中创建上下文!我们认为是“有用的背景”的东西可能不够量化,或者不能适用于所有的数据。因此,数据科学家将采取“越多越好”的方法,他们试图思考所有可能成为“有用环境”的事物的超集,然后从数据中了解哪些是真正有用的。

仍然有很多东西你可以从那些数据中提取出来,而不必进行完全的反演。

只是为了澄清一些语言,当我谈论反演时,从物理背景出发,我希望我们有一些控制方程,描述岩石的物理性质如何导致我们在野外看到的信号。当我做反演时,我基本上是想从场回到那些物理性质。

当你只关注一两个领域时,这种方法很有效。真正困难的地方在于,当你试图在其上堆叠一大堆其他数据时。例如,我们没有任何控制方程同时告诉我们岩石的磁性和密度属性加上地球化学加上矿物学加上结构是如何转化的。你把所有这些东西放在一起,这个方程组就太复杂了,无法恰当地发明出来。

这就是机器学习的特殊优势,因为有了机器学习,我们不需要解决反演问题,而是可以寻找模式。这是一种数据融合方法。或者,你可以进行这种转换,然后开始用其他数据集来约束反演;这也是一个非常有价值的方法,实际上也可以输入到机器学习模型中。

所以,再一次有很多不同的方法将机器学习应用于地质学。

地球化学

霍莉:

所以,让我们继续我最喜欢的东西——地球化学!

关于地球化学,首先要指出的是,当我们谈论数据时,我们谈论的是实验室化验结果或一些实时化学读数或岩石中元素的指标。

通常,地球化学数据库来自钻井,但钻孔的密度和间距将取决于您是在钻探资源还是在进行区域勘探。因此,由于数据可能很稀疏,我想从数据科学的角度来看,这真的很难。

我们在地球化学异常中寻找的是指示潜在矿化的任何化学变化。

Yhana (Unearthed editor) to Holly: “which of these rock photos can be a good geochemistry example image?” Holly: “All rocks are awesome! [blank stare]… fine, the purple sparkly one.” (Flickr)

仍然霍利: 我查阅地球化学数据的过程首先是对那些数据进行分段。

我知道如果我看大量的数据,我不太可能看到任何有意义的趋势;我可能会看到不同的岩石类型,但我需要将这些不同的岩石类型分成不同的群体,这样我就可以看到在这些单独的数据集中实际的异常是否突出。因此,我将数据分成不同的岩石类型,甚至蚀变类型的潜在子集。这样我就能清楚地看到那里有哪些异常点

如果我们在寻找一个新的矿床,我们知道我们在寻找不同的东西,但我们不知道确切的化学特征可能是什么。它可能是某些元素的浓缩,但也可能是一种损耗,所以实际上我们只是在寻找某个领域与众不同的东西。

杰西:

这是这是一个真正的机会,将你得到的化学数据直接与实际形成矿床的地质过程联系起来。

Holly 还没有提到这一点,但是很多地球化学研究都试图了解不同元素在每个矿床形成过程中的表现。

例如,你可能有一束热流体流过一些岩石,这会改变岩石中的所有矿物,你会看到一些元素富集——如二氧化硅。像斜长石这样的矿物被改造成粘土矿物,或者失去二氧化硅,被热的流动流体带到别处。当你看到这种运作时,这表明那里有热液活动。你可能会想到热液矿床,如金或某种铜。

霍莉:

从化学角度来说,作为地质学家,我们通过教育了解未蚀变和蚀变岩石的样子。

从根本上来说,我们可以考虑沉积岩、变质岩和火成岩。地质学家了解它们在自然状态下的不同化学成分。他们还会知道,如果被改变了,哪些元素指标可能会显示出来。我们已经了解了那些物理系统。因此,当我们寻找经济矿化的证据时,我们应用这些知识。

杰西:

可以有如此广泛的元素来查看。每个元素在这些变化过程中表现不同,但是元素组表现相似,所以实际上你可以通过比较相似元素组得到很多关于正在发生的过程的信息。

地质学家有一大堆关于热液元素的语言。通常你可以开始做的是计算元素的比率——实际上是元素的比率在变化,给你这个真正的大的指示……事物。

从技术角度来说,你不希望仅仅使用化学之外的原始数据。所有这些结果的关键是每个结果都需要加到 100%,例如,岩石中的二氧化硅含量不能超过 100%。因此,您基本上需要考虑使用对数比变换或类似的方法,将数据实际变换到一个空间,在这个空间中,您将开始应用传统的聚类方法。

地质学家使用像测井仪这样的工具来做这件事。如果你在机器学习中这样做,你可能会想自己实现它。这实际上很简单。

Dr. Jess says it’s really straightforward. I’m sure it’s fine. (Flickr)

结构

霍莉:

我们最后要讨论的异常类型是结构。

我们所说的结构是地壳中可能与矿化有关的特征。这些东西如断层、角砾岩、矿脉,可能促进了矿化的发生。

你可能会认为它们是陷阱或水槽。基本上,这种特定特征允许流体沿其流动或创建化学或物理屏障是有原因的——所以我们在数据中寻找这种特征。

杰西:

我的意思是,如果你仔细想想,你真的是在寻找地壳中元素可以集中的地方,有几种方法可以做到这一点。

我们可以有某种运输途径。对于我们前面提到的热流体,它们可以通过作为优先通道的断层。在这种情况下,你更有可能将所有这些元素聚集在这种断层周围,因此这是试图寻找某种矿化的良好目标。

想象一下,例如,你从地壳深处的一种流体开始,然后沿着一个断层把它带上来。虽然在地壳深处,它与周围的所有岩石保持化学平衡,但当你沿着断层向上移动时,它会与其他岩石接触,然后你会发生化学反应,这些化学反应会导致某些元素的沉淀。

这使得寻找我们有这种引导结构或运输结构的地方变得有用,这种结构将把材料从一个广阔的区域带到一个真正狭窄的区域。

你看到的每一个矿床并不总是以这种方式形成的。有时你会看到地下水的变化,实际上是这些变化导致了一些东西沉淀出来。

霍莉:

值得一提的是,通常某些类型的矿体可能是相当垂直的,所以如果你从上面看,它看起来像一条相当线性的直线;这是我们在数据中寻找的一种特征。通常是在地球物理数据中,因为在密度或电导率或电阻率上,结构之间通常有差异,这使我们能够提取这些差异。

杰西:

我想说的是,如果你采用数据科学的方法来研究地质学,并寻找这些断层的变化,那么你应该考虑尝试进行某种空间滤波,特别是对势场数据或磁力和重力进行滤波。

主要是因为你要寻找的是高频变化,所以一般来说,当你看磁图时,你会看到广泛的特征,你知道覆盖层厚度的变化或岩石整体行为的变化。然后你会看到非常细小的肿块;有些只是噪音,但有些实际上是这些非常细微的断层特征。

南澳大利亚政府资源信息门户刚刚增加了一些新的大地电磁数据,是地壳深部的东西。如果你对试图理解地壳深处的液体可能来自哪里感兴趣,那么可能值得看一看那套设备。

地质学可以为异常现象提供背景。我们在数据科学中可以做的是提取所有这些作为我们预测器的协变量——本质上是试图说,如果我们知道所有背景岩石的样子,告诉我这是否是异常的。

如果你试图让地质学家相信你的模型是有价值的,你试图说这是我的模型添加到你对数据的解释的背景。所以你可以说,我们认为这是反常的,因为所有这些原因,这真的和地质过程有很好的联系吗?

霍莉:

当你作为一个公司的地质学家工作时,你会受到额外的约束。所以,我们不只是被要求,'去找任何东西,去寻找异常'。通常还有其他事情推动我们正在做的事情——例如,如果在附近发现了某种类型的矿床,我们通常会使用该矿化类型的模型来寻找其他类似的矿床。

这使得我们非常受特定模型的驱动,寻找特定类型的异常,并且很容易错过数据中其他类型的异常,这是没有预料到的。

此外,大多数勘探部门,无论是大型矿商内部的小部门,都专注于特定的商品或特定的风格。这让我们集中精力,并允许我们以一种特殊的方式运用我们的资金,但这确实意味着我们可能过于偏向于寻找该部门已经处理或交易的矿体。

就这样结束了!

非常感谢 Holly 和 Jess 花了 20 分钟创造了这个。我们希望它将为奇妙的地质学世界引入更多的数据科学家——因为我们需要找到更多的资源来生产社会需要的所有东西,但这是一场艰难的游戏!

一个问题可以统治所有人

原文:https://towardsdatascience.com/one-question-to-rule-them-all-8e0d20301f31?source=collection_archive---------14-----------------------

一项评估快速概率思维测试的惊人发现

这是一篇合作文章,由 克里斯托福罗斯 A. 斯皮罗斯·多沙迪斯

首先,简单介绍一下背景

很高兴见到你:Christoforos 是帝国学院的荣誉员工,Spiros 是企业家和业余概率学家。我们的一个联合项目是棋类游戏Borel—Dice Edition,这是一个使用概率测验和多面骰子来测试玩家概率判断的游戏。

为了探索人们利用直觉处理概率难题的方式,我们最近制作了一个简短的选择题测试,并在网上传播,有点厚脸皮地称之为 概率智商测试

它由 16 个实验描述组成,有些直接取自我们的棋盘游戏,还有一个关于结果可能性的问题。所以比如其中一个问题是:掷一个 6 面骰子五次。哪个可能性更大?

(a)你至少会掷出一次 2

(b)你不会掷出 2

(c)大概是 50%-50%

由于我们只是对测量人们概率直觉的准确性感兴趣,而不是任何种类的数学能力,我们要求受访者每个问题不超过 1 分钟。

由于我们希望探索 Borel 对不同学术背景的人的吸引力,该测试的主要目标是看看正式的数学培训是否对一个人的概率快速思维的准确性有影响。所以在最后我们添加了一个关于回答者的课后正式数学训练的问题(可用的答案是:‘没有正式训练’,‘最多训练 4 年’和‘训练 4 年以上’)。

那么,首先,训练对成绩有影响吗?

让我们首先承认这样一个事实:我们的测试,就像所有的在线民意调查一样,可能会受到选择偏差的影响:回答是自愿的,接触到的受众不是随机选择的,因此不能保证实际参与的人群子集是总体人口的代表性样本。特别是,这里有一个相当明显的选择机制:不喜欢数学谜语的人不太可能做出反应。事实上,平均来说,这类人的表现可能比狂热的业余概率专家更差,因为至少缺乏练习。

此外,我们可以合理地假设,在未受过训练的人群中,任何选择偏差都比受过训练的人群大:受过数学和概率训练的人不太可能对这样的测验产生负面倾向,因此决定他们是否会对测验做出反应的因素与他们在测试中的表现不太可能相关。考虑到这一点,我们来看分析。

训练似乎确实有一个小的积极影响,但这只有在 5 年的训练后才变得显著。鉴于我们上面对选择偏差的讨论,如果我们有一个代表性的样本,我们可能会认为这个影响会更大。然而,我们仍然可以争辩的是,对这门学科的热爱(无论如何足以让你想做一个概率测验)似乎几乎和培训一样有效:分布严重重叠(图 1):30%没有接受过数学培训的受访者比接受过 5 年以上培训的人表现更好,几乎 50%的人比接受过 1-4 年培训的人表现更好。在概率问题上,似乎竞争环境相当公平。

你可能会想,除了训练,还有什么能更好地区分擅长和不擅长这方面的人。在这篇文章的最后,我们为你找到了答案。请继续阅读!

Figure 1 — Performance per years of training

一般来说,人们擅长这个吗?

那么,我们对这类问题有多擅长呢?看一下上面的图,可以发现平均性能约为 50%。这是否意味着我们比随机猜测好不了多少?为了回答这个问题,我们首先需要定义“随机猜测”在这个上下文中的含义。

回想一下,每个问题有三个选项。因此,定义随机猜测的一种方法是随机选择一个答案。这通常会产生 1/3 的平均分数,因此显著低于 50%。除此之外,我们测验中的答案并不总是相互排斥的。举个例子,结果 A 有 52%的可能性发生。在这种情况下,我们将“A 更有可能”和“大约是 50/50”都视为正确答案(我们对此进行了长时间的认真思考,并认为这是直觉测验和正确评估之间的最佳妥协)。

考虑到这一点,随机选择一个答案会给你一个 0.39 的预期分数,这比我们观察到的表现要差得多。

因为错误的原因而正确

有些问题是同一系列问题的不同实例。例如,下面是问题 3 和 10,它们实际上只是一个骰子不同面的问题:

问题 3 :掷出一个六面骰子。然后滚动一个 10 面骰子。然后滚动一个 30 面骰子。结果会严格按照升序排列吗?

问题 10 :掷出一个 10 面骰子。然后滚动一个 20 面骰子。然后滚动一个 30 面骰子。结果会严格按照升序排列吗?

想必我们会期望任何给定的回答者在这两个问题上表现得一样好,对吗?完全错了!事实上,在所有可能的问题对中,这一对是最不可能被回答者答对的。很奇怪。

好吧,我们开始吧。首先,请注意,选择这两个答案是为了更有可能出现不同的结果:第一个问题中更有可能出现严格的递增顺序,第二个问题中最不可能出现(公平地说,大约是 50/50)。再加上观察到约 60%的受访者对这两个问题给出了相同的答案,我们可以得出这样的结论:受访者往往会对这个问题形成一种观点,而这种观点实际上对骰子的两面并不敏感。这些回答者有一半时间是对的,但原因是错误的。

它变得更加有趣。对这种现象的一个简单解释是,由于某种认知偏差,受访者倾向于某个答案:例如,人们可能只是倾向于假设最有可能的结果将是严格递增的序列,因为骰子的边数是严格递增的。数据绝对不是这样:在对这两个问题给出相同答案的人中,16%的人认为这两种情况都是 50/50,42%的人认为递增顺序最有可能,42%的人认为最不可能。认为严格增长是这两个问题的正确答案的人与认为严格增长是这两个问题的错误答案的人数量完全相同。只有一个合理的结论:大多数人,面对这个问题的时候,几乎是随便挑一个答案,就坚持下来了!

这一分析也很有趣,因为它展示了认知偏差有时会隐藏得多么好:如果我们只问了这两个问题中的一个,我们就没有办法知道这正在发生。

哪个问题最难?

这个结果并不出乎我们的意料:被调查者认为最难正确回答的问题是我们从经验中得知的最有害的问题。是这个:

在一系列连续的硬币投掷中,哪一个序列更有可能在某个时刻首先出现,[正面-反面]或[反面-反面]?

然而,结果是戏剧性的:只有 12%的受访者答对了这个问题。更重要的是,这个问题的答案也高度预测了所有其他问题的表现:答对这个问题的受访者在其余问题上的平均得分为 58%。事实上,这个问题的答案比一个人是否接受过数学培训更能预测整体表现:接受过 5 年以上培训的受访者的平均表现只有 52%。

一个统计上的灌篮

我们发现这个发现如此惊人,以至于我们想对它进行第三次测试(这也是我们想发表这篇文章的原因)。数据没有让人失望。这是一个三步走的过程:

1.如果你知道一个回答者是否答对了这个问题,他们是否接受过数学训练并不能提供额外的预测能力来预测他们在这个测试中的表现。

2.相反,如果一个人知道一个回答者是否受过正式的数学训练,额外知道他们是否答对了这个问题确实提供了额外的预测能力(在二项式回归中的额外效果在 99%的置信水平上显著)。

3.最重要的是,一个人是否答对了这个问题,与他是否接受过统计学培训无关。我们可以在声明下面签名:相关性接近 0。

Giannis knows his probabilities

这三个结果的结合可以被有把握地称为“统计上的成功”。这是统计学家在预测感兴趣的结果时,关于一个指标(在这种情况下,是抛硬币问题的答案)优于另一个指标(在这种情况下,是正规数学训练的存在)的最强有力的声明。所以,尽管还是有点厚脸皮,我们还是准备给招聘人员和人力资源人员以下建议:

如果你在面试一个需要快速概率思维的职位的候选人(什么工作不需要,如果你真的去想?),不用费心去问他们的学历。漫不经心地把他们长长的简历放进垃圾箱,并问他们一个问题:

在一系列连续的掷硬币过程中,哪个序列更有可能在某个时刻首先出现,[正面-反面]还是[反面-反面]?

你自己进去

试一试 看看你的概率直觉有多准。你可能还想看看 Borel ,这款棋类游戏开启了这一切。

使用 Keras 一次性学习暹罗网络

原文:https://towardsdatascience.com/one-shot-learning-with-siamese-networks-using-keras-17f34e75bb3d?source=collection_archive---------0-----------------------

目录

  1. 介绍
  2. 先决条件
  3. 分类与一次性学习
  4. 应用程序
  5. Omniglot 数据集
  6. 加载数据集
  7. 将问题映射到二元分类任务
  8. 模型架构和培训
  9. 验证模型
  10. 基线 1 —最近邻模型
  11. 基线 2 —随机模型
  12. 测试结果和推断
  13. 结论
  14. 参考

1.介绍

深度卷积神经网络已经成为图像分类任务的最先进方法。然而,最大的限制之一是它们需要大量的标记数据。在许多应用程序中,收集这么多数据有时是不可行的。One Shot Learning 旨在解决这个问题。

2.先决条件

在这篇文章中,我将假设你已经熟悉机器学习的基础知识,并且在使用 Python 和 Keras 使用卷积神经网络进行图像分类方面有一些经验。

3.分类与一次性学习

标准分类的情况下,输入图像被输入到一系列层中,最后在输出端,我们生成所有类别的概率分布(通常使用 Softmax)。例如,如果我们试图将图像分类为猫或狗或马或大象,那么对于每个输入图像,我们生成 4 个概率,指示图像属于 4 个类别中的每一个的概率。这里必须注意两个要点。首先,在训练过程中,我们要求每个类(猫、狗、马和大象)的数量的图像。其次,如果网络只在上述 4 类图像上进行训练,那么我们就不能指望在任何其他类上进行测试,例如“斑马”。如果我们希望我们的模型也对斑马的图像进行分类,那么我们需要首先获得大量的斑马图像,然后我们必须再次重新训练该模型。在有些应用中,我们既没有足够的数据用于每个类,而且类的总数是巨大的,并且是动态变化的。因此,数据收集和定期再培训的成本太高。

另一方面,在单镜头分类中,我们只要求每个类有一个训练示例。是的,你说得对,只有一个。因此得名一枪。让我们试着用一个真实世界的实际例子来理解。

假设我们要为一个只有 10 名员工的小组织构建人脸识别系统(小数字使事情简单)。使用传统的分类方法,我们可能会得到一个如下所示的系统:

Standard classification using CNN

问题:

a)为了训练这样一个系统,我们首先需要组织中 10 个人中每个人的大量不同的图像,这可能是不可行的。(想象一下,如果你是为一个有几千名员工的组织做这件事)。

b)如果有新人加入或离开组织怎么办?你需要承受再次收集数据的痛苦,再次重新训练整个模型。这实际上是不可能的,特别是对于几乎每周都在招聘和减员的大型组织。

现在,让我们来了解一下如何使用一次性分类来解决这个问题,一次性分类有助于解决上述两个问题:

One Shot Classification

该网络不是将输入(测试)图像直接分类到组织中的 10 个人中的一个,而是将该人的额外参考图像作为输入,并且将产生相似性分数,该分数表示两个输入图像属于同一个人的可能性。通常,使用 sigmoid 函数将相似性得分压缩在 0 和 1 之间;其中 0 表示没有相似性,1 表示完全相似。0 和 1 之间的任何数字都有相应的解释。

请注意,该网络没有学习将图像直接分类到任何输出类别。相反,它正在学习一个相似度函数,该函数将两幅图像作为输入,并表示它们有多相似。

这如何解决我们上面讨论的两个问题?

a)一会儿我们将会看到,为了训练这个网络,你不需要一个类的太多实例,仅仅几个就足以建立一个好的模型。

b)但最大的优势是,假设在人脸识别的情况下,我们有一名新员工加入了组织。现在,为了让网络检测到他的脸,我们只需要一张他的脸的单个图像,它将被存储在数据库中。使用该图像作为参考图像,网络将计算呈现给它的任何新实例的相似性。因此我们说网络预测分数在一杆

如果上述细节目前看起来有点抽象,请不要担心,继续前进,我们将解决一个问题的全部细节,我保证你将对主题有深入的理解。

4.应用程序

在我们继续之前,我想提一下 one shot learning 的几个应用,以便激发您对了解这项技术产生更浓厚的兴趣。

a.正如我上面已经提到的人脸识别,只需进入这个 链接 人工智能大师吴恩达展示了百度(中国搜索巨头)如何为他们组织的员工开发人脸识别系统。

b.阅读这篇 博客 来了解一次性学习是如何应用于数据非常匮乏的药物发现的。

c.在这篇 论文 中,作者使用一次性学习构建了一个离线签名验证系统,该系统对银行和其他政府以及私人机构非常有用。

5.Omniglot 数据集

出于这个博客的目的,我们将使用 Omniglot 数据集,它是来自 50 个不同字母表的 1623 个手绘字符的集合。每个角色只有 20 个例子,每个例子都是由不同的人画的。每个图像都是分辨率为 105x105 的灰度图像。

在我继续之前,我想澄清一下字符和字母表之间的区别。在英语的情况下,集合 A 到 Z 被称为字母表,而每个字母 A、B 等等。叫做人品。因此,我们说英语字母表包含 26 个字符(或字母)。

所以我希望这澄清了我所说的跨越 50 多个不同字母的 1623 个字符。

让我们看一些来自不同字母表的字符图像,以便更好地了解数据集。

Image Source: https://sorenbouma.github.io/blog/oneshot/

因此,我们有 1623 个不同的类(每个字符可以被视为一个单独的类),每个类只有 20 个图像。显然,如果我们试图使用传统的图像分类方法来解决这个问题,那么我们肯定无法建立一个良好的通用模型。由于每个类别可用的图像数量如此之少,模型很容易会过拟合。

你可以通过克隆这个 GitHub 仓库 来下载数据集。名为“Python”的文件夹包含两个 zip 文件:images_background.zip 和 images_evaluation.zip,解压这两个文件即可。

images_background 文件夹包含来自 30 个字母的字符,并将用于训练模型,而 images_evaluation 文件夹包含来自其他 20 个字母的字符,我们将使用这些字符来测试我们的系统。

解压缩文件后,您将在 images_background 文件夹(用于培训目的)中看到以下文件夹(字母):

Contents of images_background directory

您将在 images_evaluation 文件夹(用于测试目的)中看到以下文件夹(字母):

Contents of images_evaluation directory

请注意,我们将在一组字符上训练系统,然后在训练期间从未使用过的一组完全不同的字符上测试它。这在传统的分类循环中是不可能的。

6.加载数据集

首先,我们需要将图像加载到张量中,然后使用这些张量向模型批量提供数据。

我们使用下面的函数将图像加载到张量中:

Code to load images from disk

要按如下方式调用此函数,请按如下方式将火车目录的路径作为参数传递:

X,y,c = loadimgs(train_folder)

该函数返回一个由 3 个变量组成的元组。我不会遍历代码的每一行,但是我会通过理解它返回的值,给你一些直觉,这个函数到底在做什么。有了这个解释,一旦你完成了它,你就能很好地理解上面的功能。

让我们来理解“X”中呈现的是什么:

X.shape
(964, 20, 105, 105)

这意味着我们有跨越 30 种不同字母表的 964 个字符(或字母或类别)。对于每个角色,我们有 20 张图像,每张图像都是分辨率 105x105 的灰度图像。故名形状(964,20,105,105)。

现在让我们了解标签“y”是如何填充的:

y.shape
(19280, 1)

图像总数= 964 * 20 = 19280。一个字母的所有图像都有相同的标签。,即前 20 个图像的标签为 0,接下来的 20 个图像的标签为 1,依此类推,……最后的 20 个图像的标签为 963。

最后,最后一个变量“c”代表类别,它是一个字典,如下所示:

c.keys() # 'c' for categoriesdict_keys(['Alphabet_of_the_Magi', 'Anglo-Saxon_Futhorc', 'Arcadian', 'Armenian', 'Asomtavruli_(Georgian)', 'Balinese', 'Bengali', 'Blackfoot_(Canadian_Aboriginal_Syllabics)', 'Braille', 'Burmese_(Myanmar)', 'Cyrillic', 'Early_Aramaic', 'Futurama', 'Grantha', 'Greek', 'Gujarati', 'Hebrew', 'Inuktitut_(Canadian_Aboriginal_Syllabics)', 'Japanese_(hiragana)', 'Japanese_(katakana)', 'Korean', 'Latin', 'Malay_(Jawi_-_Arabic)', 'Mkhedruli_(Georgian)', 'N_Ko', 'Ojibwe_(Canadian_Aboriginal_Syllabics)', 'Sanskrit', 'Syriac_(Estrangelo)', 'Tagalog', 'Tifinagh'])c['Alphabet_of_the_Magi']
[0, 19]c['Anglo-Saxon_Futhorc']
[20, 48]

因为有 30 种不同的字母表,所以这本字典 c 包含 30 个条目。每一项的关键是字母表的名称。每个项目的值是两个数字的列表:[low,high],其中“low”是该字母表中第一个字符的标签,“high”是该字母表中最后一个字符的标签。

一旦我们加载了训练和测试图像,我们将张量保存在磁盘上的 pickle 文件中,这样我们就可以在以后直接使用它们,而不必再次加载图像。

7.将问题映射到二元分类任务

让我们了解如何将这个问题映射到监督学习任务中,其中我们的数据集包含(Xi,易)对,其中“Xi”是输入,“易”是输出。

回想一下,我们系统的输入将是一对图像,输出将是介于 0 和 1 之间的相似性得分。

Xi =一对图像

yi = 1;如果两个图像包含相同的字符

yi = 0;如果两幅图像包含不同的字符

让我们通过可视化下面的数据集来更好地理解:

Sample of 6 data points

因此,我们需要创建成对的图像和目标变量,如上所示,作为输入输入到暹罗网络。请注意,尽管上面显示了来自梵语字母表的字符,但实际上我们将从训练数据中的所有字母表中随机生成对

生成这些对和目标的代码如下所示:

Code to load data in batches

我们需要通过传递 batch_size 来调用上面的函数,它将返回“batch_size”数量的图像对及其目标变量。

我们将使用下面的生成器函数在网络训练期间批量生成数据。

8.模型架构和培训

这段代码是格雷戈里·科赫等人在这篇 研究论文 中描述的方法的实现。我使用的模型架构和超参数都如文中所述。

在深入细节之前,让我们先从高层次上理解这个架构。下面,我将呈现一个对建筑的直觉。

A high level architecture

****直觉:暹罗这个词的意思是双胞胎。上面显示的两个卷积神经网络不是不同的网络,而是同一网络的两个副本,因此被命名为暹罗网络。基本上它们共享相同的参数。两个输入图像(x1 和 x2)通过 ConvNet,为每个图像(h(x1)和 h(x2))生成一个固定长度的特征向量。假设神经网络模型被适当地训练,我们可以做出如下假设:如果两个输入图像属于同一字符,那么它们的特征向量也一定是相似的,而如果两个输入图像属于不同的字符,那么它们的特征向量也将是不同的。因此,在上述两种情况下,两个特征向量之间的元素方面的绝对差异必定非常不同。因此由输出 sigmoid 层生成的相似性得分在这两种情况下也必须不同。这是暹罗网络背后的中心思想。

鉴于上述直觉,让我们看看从研究论文本身获得的更详细的架构图片:

Image Source: https://www.cs.cmu.edu/~rsalakhu/papers/oneshot1.pdf

以下函数用于创建模型架构:

Siamese Model Architecture

请注意,Keras 中没有预定义的层来计算两个张量之间的绝对差。我们使用 Keras 中的 Lambda 层来实现这一点,该层用于在 Keras 中添加定制层。

要了解在不同层传递的张量的形状,请参考使用 Keras 的 plot_model 实用程序生成的下图。

Tensor shapes at every level

该模型是使用 adam 优化器和二元交叉熵损失函数编译的,如下所示。学习率保持较低,因为发现在高学习率的情况下,模型需要花费大量时间来收敛。然而,这些参数可以被进一步调整以改善当前的设置。

optimizer = Adam(lr = 0.00006)
model.compile(loss="binary_crossentropy",optimizer=optimizer)

该模型被训练了 20000 次迭代,批量大小为 32。

在每 200 次迭代后,使用 20 路一次学习进行模型验证,并通过 250 次试验计算精确度。这个概念将在下一节解释。

9.验证模型

现在我们已经了解了如何准备用于训练的数据、模型架构和训练;是时候我们必须考虑一个策略来验证和测试我们的模型了。

请注意,对于每一对输入图像,我们的模型都会生成一个介于 0 和 1 之间的相似性得分。但是仅仅看分数很难确定模型是否真的能够识别相似的字符并区分不同的字符。

一个很好的判断模型的方法是 N 路一杆学习。别担心,这比听起来容易多了。

4 向一次性学习的示例:

我们创建一个包含 4 对图像的数据集,如下所示:

Example of a 4-way one shot learning

基本上,相同的字符与 4 个不同的字符进行比较,其中只有一个字符与原始字符匹配。假设通过进行上述 4 次比较,我们得到了 4 个相似性得分,分别是 S1、S2、S3 和 S4,如图所示。现在,如果模型被适当地训练,我们期望 S1 是所有 4 个相似性分数中最大的,因为第一对图像是唯一一个我们有两个相同字符的图像。

因此,如果 S1 恰好是最高分,我们就认为这是一个正确的预测,否则我们就认为这是一个不正确的预测。重复这个过程“k”次,我们可以计算正确预测的百分比如下:

percent _ correct =(100 * n _ correct)/k

其中 k = >试验总数,n _ correct =次试验中的正确预测数。

类似地,9 路单次学习将如下所示:

Example of a 9-way one shot learning

16 向单杆倾斜将如下所示:

Example of a 16-way one shot learning

下面是 25 路一次性学习的样子:

Example of a 25-way one shot learning

注意,N 向一次学习中的“N”的值不一定是完美的正方形。我选择值 4、9、16 和 25 的原因是,当正方形被填满时,它看起来更适合展示。

很明显,当重复多次时,较小的“N”值将导致更正确的预测,而较大的“N”值将导致相对不太正确的预测。

再次提醒一下:上面显示的所有例子都来自梵文字母表,但是实际上我们将从测试/验证数据集图像的所有字母表中随机生成测试图像和支持集。

生成测试图像和支持集的代码如下:

Code to generate a test image along with the support set

10.基线 1 —最近邻模型

创建简单的基线模型,并将它们的结果与您试图构建的复杂模型进行比较,这始终是一个很好的实践。

我们的第一个基线模型是最近邻方法。如果你熟悉 K 近邻算法,那么这也是一样的。

如上所述,在 N 路单次学习中,我们将测试图像与 N 个不同的图像进行比较,并选择与测试图像具有最高相似性的图像作为预测。

这在直觉上类似于 K=1 的 KNN。让我们详细了解一下这种方法是如何工作的。

你可能已经学习了如何计算两个向量之间的 L2 距离(也称为欧几里德距离)。如果你不记得了,下面是怎么做的:

L2 distance between two vectors

假设我们将向量 X 的 L2 距离与其他三个向量 A、B 和 c 进行比较。然后,计算与 X 最相似的向量的一种方法是检查哪个向量与 X 的 L2 距离最小。因为距离与相似度成反比。因此,例如,如果 X 和 B 之间的 L2 距离最小,我们说 X 和 B 之间的相似性最大。

然而,在我们的情况下,我们没有矢量,但灰度图像,可以表示为矩阵,而不是矢量。那么我们如何计算矩阵间的 L2 距离呢?

这很简单,只要将矩阵展平成向量,然后计算这些向量之间的 L2 距离。例如:

Computing L2 distance between images

因此,在 N 路一次学习中,我们将测试图像的 L2 距离与支持集中的所有图像进行比较。然后我们检查得到最小 L2 距离的字符。如果该字符与测试图像中的字符相同,则预测是正确的,否则预测是不正确的。例如:

N way Nearest Neighbor Approach

类似于 N 路一次学习,我们对多次试验重复这一过程,并计算所有试验的平均预测分数。最近邻方法的代码如下:

Code to compute Nearest Neighbors

11.基线 2 —随机模型

创建随机预测的随机模型是一种非常常见的技术,以确保我们创建的模型至少比完全随机预测的模型更好。下图总结了它的工作原理:

N-way Random Approach

12.测试结果和推断

对 N = 1,3,5,…进行了 N 向测试。, 19.

对于每个 N 向测试,执行 50 次试验,并计算这 50 次试验的平均准确度。

以下是 4 种型号之间的对比:

Test Results

****推论:显然,暹罗模型比随机模型和最近邻模型表现得好得多。然而,在训练集和验证集上的结果之间存在一些差距,这表明模型是过拟合的。

13.结论

这只是一个初步的解决方案,许多超参数可以调整,以避免过度拟合。此外,通过增加 N 路测试中的“N”值和增加试验次数,可以进行更严格的测试。

我希望这有助于你理解使用深度学习的一次性学习方法。

****源代码:请在此 查阅我 GitHub 库上 Jupyter 笔记本中的源代码。

****注:模型是用 P4000 GPU 在云上训练的。如果你在 CPU 上训练它,那么你需要非常有耐心。

欢迎评论、建议、批评。谢了。

14.参考

a.https://github.com/akshaysharma096/Siamese-Networks

b.https://sorenbouma.github.io/blog/oneshot/

c.【https://www.cs.cmu.edu/~rsalakhu/papers/oneshot1.pdf

d.吴恩达在 Coursera 上的 deeplearning.ai 专业化课程

用 Numpy 加速 Python 代码的一个简单技巧

原文:https://towardsdatascience.com/one-simple-trick-for-speeding-up-your-python-code-with-numpy-1afc846db418?source=collection_archive---------5-----------------------

想获得灵感?快来加入我的 超级行情快讯 。😎

Python 是巨大的。

在过去的几年中,Python 的受欢迎程度迅速增长。其中很大一部分是数据科学、机器学习和人工智能的兴起,所有这些都有高级 Python 库可以使用!

当使用 Python 处理这些类型的工作时,通常需要处理非常大的数据集。这些大型数据集被直接读入内存,并作为 Python 数组、列表或字典进行存储和处理。

处理如此庞大的数组可能非常耗时;真的,这就是问题的本质。你有数千、数百万甚至数十亿个数据点。在处理这些点中的一个点时,每增加一微秒都会大大降低您处理大规模数据的速度。

缓慢的方式

处理大型数据集的缓慢方法是使用原始 Python。我们可以用一个非常简单的例子来证明这一点。

下面的代码将 1.0000001 的值乘以自身,500 万次!

我家里有一个相当不错的 CPU,英特尔 i7-8700k 加上 32GB 的 3000MHz 内存。然而,将这 500 万个数据点相乘需要 0.21367 秒。如果我将num_multiplies的值改为 10 亿次,这个过程需要 43.24129 秒!

让我们试试另一个数组。

我们将构建一个大小为 1000x1000 的 Numpy 数组,每个数组的值为 1,并再次尝试将每个元素乘以一个浮点数 1.0000001。代码如下所示。

在同一台机器上,在常规浮点循环中将这些数组值乘以 1.0000001 需要 1.28507 秒。

什么是矢量化?

Numpy 被设计成对矩阵运算有效。更具体地说,Numpy 中的大多数处理都是矢量化

矢量化包括表示数学运算,例如我们在这里使用的乘法,它发生在整个数组上,而不是它们的单个元素上(如我们的 for 循环)。

借助向量化,底层代码被并行化,因此操作可以一次在多个数组元素上运行,而不是一次遍历一个元素。只要你正在应用的操作不依赖于任何其他的数组元素,也就是一个“状态”,那么矢量化将会给你带来很好的速度提升。

在 Python 数组、列表或字典上循环可能会很慢。因此,Numpy 中的矢量化操作被映射到高度优化的 C 代码,这使得它们比标准 Python 代码快得多。

最快的方法

下面是做事情的快速方法——按照设计使用的方式使用 Numpy。

在寻求加快速度时,我们可以遵循以下几点:

  • 如果数组上有一个 for 循环,我们很有可能用一些内置的 Numpy 函数来替换它
  • 如果我们看到任何类型的数学,我们很有可能用一些内置的 Numpy 函数来代替它

这两点实际上都集中在用优化的、矢量化的低级 C 代码替换非矢量化的 Python 代码。

看看我们之前的第一个例子的快速版本,这次有 10 亿次乘法。

我们做了一些非常简单的事情:我们看到我们有一个 for 循环,在这个循环中我们多次重复相同的数学运算。这应该立即触发我们应该去寻找一个 Numpy 函数来代替它。

我们找到了一个——power函数,它简单地将某个幂应用于输入值。这段代码运行速度惊人,只需 7.6293-6 秒,这是一个

这与将值乘以 Numpy 数组的想法非常相似。我们看到我们正在使用一个双 for 循环,应该立即意识到应该有一个更快的方法。

方便的是,如果我们直接乘以 1.0000001 标量,Numpy 将自动对我们的代码进行矢量化。所以,我们可以用同样的方式来写我们的乘法,就像我们乘以一个 Python 列表一样。

下面的代码演示了这一点,运行时间为 0.003618 秒,速度提高了 355 倍!

喜欢学习?

twitter 上关注我,我会在那里发布所有最新最棒的人工智能、技术和科学!也在 LinkedIn 上与我联系!

10 分钟内完成一项调查、100 张卡片和 1,000 张幻灯片

原文:https://towardsdatascience.com/one-survey-100-decks-and-1-000-slides-in-10-minutes-8fcfd1b246ee?source=collection_archive---------25-----------------------

用开源软件自动化调查数据分析-第二部分

整个研究团队在会议室集合。现在是晚上 10 点。咖啡机正在汩汩作响,宣布新的一壶已经煮好了。还有至少四个小时的工作。你知道这一点,因为你以前来过这里;房间里的其他人也一样。

数据处理团队两周前对结果进行了清理、加权和计算——在调查结束后一周,那么为什么我们都在晚上 10 点喝马马虎虎的过滤咖啡呢?

嗯,客户有 20 个部门,每个部门都需要一个单独的幻灯片,上面有他们自己的结果;每组有 30 张幻灯片,大多数幻灯片有两张图表。通过将正确的数据复制并粘贴到正确文档的正确幻灯片中,从表格中手动创建了近 1,000 个图表。

最后,就在你快完成了,隧道尽头出现了曙光,只剩下一点点抽查的时候,那封电子邮件到了。宣布客户顿悟的电子邮件:新定义的年龄细分将以更精细的方式抓住他们的目标受众,请再次运行表格和幻灯片。一个初级研究员在哭吗?

在 python 中自动生成 PowerPoint 幻灯片

不需要那样。Python 的一大承诺是它能够自动化枯燥的东西(阿尔·斯威加特的很好地介绍了这个概念)。手动复制/粘贴过程没有实际价值,但存在巨大的风险。在使用开源软件自动进行调查数据分析的第二部分中,我们将向您展示您的团队如何在野外工作完成后立即准备好这 1,000 个图表,最终在不到 10 分钟的时间内,在将近 200 个 PowerPoint 文件中完成 1,000 多个图表。

We’ll create one PowerPoint slideshow for what technologies are used in every single country in the Stackoverflow survey. The results are native Excel charts that can be edited, and the slideshows are based on themes that can be branded at will.

我们的数据:Stackoverflow 2019 开发者调查

为了说明工作流,我们将使用 Stackoverflow 2019 开发者调查,该调查查看了大约 90,000 名编码人员的工具和偏好。我们的目标是为参与调查的每个国家正在使用的技术制作一个 PowerPoint 幻灯片。我们将使用 Python 库:pandas、python-pptx 和 Quantipy(专门用于调查数据的库)以及 Jupyter 笔记本。

import pandas, quantipy, python-pptx

和我们所有的项目一样,我们从一个标准的目录布局开始(在后面的文章中会详细介绍我们的标准化工作流程),在那里我们存储原始的数据文件(我们总是在一个副本上工作,以便有一个干净的引用来返回)。在初始库导入之后,我们有兴趣查看数据中的一个名为LanguagesWorkedWith的变量,它看起来像这样:

pd.read_csv('./data/original/survey_results_public.csv',
            usecols=['LanguageWorkedWith']).head()

受访者可以选择一种以上他们有工作经验的语言。这意味着数据列中不是单个值,而是一个由字符分隔的值列表(分隔集)。在上面的例子中,第一个回答者拥有 HTML/CSS、Java、JavaScript 和 Python 的经验。

将测量数据和模式 CSV 文件转换为 Quantipy 数据和元数据文件格式后,我们可以创建 Quantipy 数据集(数据集是一种 Python 对象,专门用于处理测量数据,允许方便地访问数据以进行分析和探索)。

dataset = qp.DataSet(“StackOverflow 2019”)
dataset.read_quantipy(meta=”stackoverflow.json”,
                      data=”stackoverflow.csv”)

Quantipy 的便利功能之一是dataset.crosstab(),允许我们轻松地检查受访者所说的他们使用的不同技术的结果。

dataset.crosstab(‘LanguageWorkedWith’)

Almost ninety thousand Stackoverflow users answered what technology they’ve worked with.

这看起来不错:JavaScript 是我们的数据中最受欢迎的,与 Stackoverflow 公布结果时报告的一样。所以,我们继续。

179 个国家,每个国家一个 PowerPoint 文件

我们将从查看哪些变量对我们可用开始:因为我们已经决定查看不同国家的人们使用什么技术,我们将添加与语言、数据库、平台、网络框架和各种技术相关的“曾经工作过”和“期望的”变量。

variables = ['LanguageWorkedWith',
             'LanguageDesireNextYear',
             'DatabaseWorkedWith',
             'DatabaseDesireNextYear',
             'PlatformWorkedWith',
             'PlatformDesireNextYear',
             'WebFrameWorkedWith',
             'WebFrameDesireNextYear',
             'MiscTechWorkedWith',
             'MiscTechDesireNextYear']

我们还做了另一个健全性检查;计算每个国家回复的百分比,并与公布的结果进行比较。这些匹配,所以我们继续。

# Sanity check: This matches 
# data from the officially published results.
# The pct parameter means we calculate percentages 
# rather than counts
countries_pct = dataset.crosstab('Country', pct=True)# the index of the resulting dataframe has a list of all countries
# in the data
all_countries = countries_pct.index.get_level_values(1)countries_pct

现在我们遍历各个国家,并计算上面定义的variables数组中每个变量的结果。

因此,循环变成:

countries = {}
for country in all_countries:
    slide_data = []
    for variable in variables:
        # convert country name to relevant code/number
        # and use it to filter the data before running the crosstab
        filter = {'Country':dataset.code_from_label('Country',
                                                    country)}
        result = dataset.crosstab(variable, 
                                  pct=True, 
                                  f=filter)
        slide_data.append()
    countries[country] = slide_data

现在我们已经计算了数据,我们编写创建 PowerPoint 文档的最后一个循环:

for country in all_countries:
    prs = Presentation('./specs/pptx-template.pptx') for i, var in enumerate(variables):
        title = countries[country][i].index[0][0]
        data = countries[country][i]
        data = data.sort_values(by='@')/100
        chartData = hp.ChartData_from_DataFrame(data)  
        # blank slide
        slide = prs.slides.add_slide(prs.slide_layouts[6])
        x, y, cx, cy = 1524000, 1397000, 6096000, 4064000
        chart = slide.shapes.add_chart(
            XL_CHART_TYPE.BAR_CLUSTERED,
            x, y, cx, cy,
            chartData
        ).chart
        txBox = slide.shapes.add_textbox(x, y-1000000, cx, cy)
        txBox.text_frame.text = title chart.category_axis.tick_labels.font.size = Pt(12)
        chart.value_axis.tick_labels.font.size = Pt(10) folder = "./results/stackoverflow_results/" 
        prs.save("{}/{}.pptx".format(folder, country))

pptx 模板文件应该是一个空的演示文稿,并且slide_layouts引用将用于插入结果的主幻灯片。在这种情况下,我们使用一个空幻灯片,但我们也可以使用图表占位符来更好地控制。

结果呢

我们已经将以上内容整合到一个笔记本中,发布在 Github 上,当笔记本运行时,我们最终得到了 179 个幻灯片,每个国家一个。每个幻灯片组有 10 张幻灯片,因此您的团队不需要手动生成 1790 张幻灯片。

Navigate into your results folder in Jupyter Notebooks and see the slides you’ve generated for each country.

Above is the first page of the results for China in PowerPoint. The chart is a native Excel chart, not an image, so it can be edited, the chart type changed and so on.

进一步自动化

在 Jupyter 笔记本中运行上述内容的好处在于,它可以成为管道的一部分。我们已经写了通过将 Jupyter 笔记本链接在一起来自动化数据处理管道(准备数据),在这个系列的下一步将是自动化输出管道。这将包括创建一个所谓的“图表规范”,一个定义应该生成哪些幻灯片的 Excel 文件。一旦一个合适的图表规范准备就绪,它就可以在每次项目启动时自动在数据集上运行。

自动化和进一步抽象上述 PowerPoint 文件的构建将是我们下一篇文章的主题。

盖尔·弗雷松是 Datasmoothie 的联合创始人,这是一个专门从事调查数据分析和可视化的平台。如果你对使用开源软件进行调查数据分析感兴趣,注册我们的时事通讯,名为自发认知

单尾还是双尾检验,这是个问题

原文:https://towardsdatascience.com/one-tailed-or-two-tailed-test-that-is-the-question-1283387f631c?source=collection_archive---------6-----------------------

Source: pixabay

了解统计测试的两种变体之间的区别,以及如何在 Python 中实现它们

在数据科学/计量经济学中我们在很多地方看到统计检验:相关分析、ANOVA、A/B 检验、线性回归结果等。因此,对于实践者来说,彻底理解它们的含义并知道为什么在特定的地方使用给定的测试是非常重要的。在这篇文章中,我想提供一些直觉来选择一个合适的统计检验版本——单尾或双尾——以符合陈述的假设。

进行任何统计检验的关键步骤是选择正确的假设,因为它们不仅决定了应该使用的统计检验的类型,而且还影响了它的版本。

PDF of a Gaussian Distribution

如果考虑的检验统计量是对称分布的,我们可以选择三个备选假设中的一个:

  • x 大于 y
  • x 比 y 小
  • x 不等于 y

前两个对应于单尾检验,而最后一个对应双尾检验。

让我们更深入地研究测试的两种变体之间的差异,并展示一些 Python 中的例子!

单尾检验

假设我们选择了 0.05(或 5%)作为显著性水平。使用单尾检验意味着临界区域位于检验统计的概率分布的顶部/底部的 5%。如果检验统计量落入这个区域,我们拒绝零假设。我们有效地测试了一个方向上的关系的可能性(明显更大或更小),而忽略了另一个方向上的关系的可能性。

单尾检验的一个重要特征是它提供了更多的能力来检测一个方向上的影响,因为它不检测另一个方向。然而,这也带来了一些威胁,我在下面的例子中对此进行了说明。

让我们想象一下,我们制造了一种新药,并想用当前的解决方案来测试它的有效性。我们可能会尝试使用单尾检验,因为它最大化了检测改进的机会(明确指定的效果方向)。但这让我们有可能忽略这样一个事实,即我们的药物实际上不如目前的药物有效。

这个例子表明,当遗漏一个效应的后果可以忽略不计时,我们应该选择单尾检验,而上面的例子并非如此。我们不应该仅仅为了获得统计显著性而选择单尾检验,因为这可能会导致无效的结论,在某些情况下还会导致可怕的后果。

Source

双尾检验

在双尾检验的情况下,我们正在检验一个不包含方向关系的假设。如果我们想测试样本均值是否等于 x(t-检验的零假设),那么另一个选项表明均值不等于 x。为了测试它,我们考虑均值显著大于和显著小于 x 的情况。在 5%的显著性水平下,当检验统计量落入临界区域(检验统计量概率分布的底部和顶部 2.5%)时,样本均值被视为与 x 显著不同。这导致 p 值小于 0.05,表明我们应该拒绝零假设,支持另一个假设。

Python 中的示例

让我们假设我们正在处理关于学校考试的数据。两所学校的学生写了同样的标准化考试,现在我们想调查平均成绩之间是否有统计学差异。

为简单起见,我们假设每所学校有 100 名学生,考试成绩来自具有不同参数的高斯分布。

生成数据

单样本 t 检验

在单样本 t 检验中,我们根据特定值检验样本的平均值。我们从检验的双尾变量开始,假设如下:

H_0:来自学校#1 的学生的平均成绩是 70
H_1:来自学校#1 的学生的平均成绩不是 70

stats.ttest_1samp(school_1, 70)# Ttest_1sampResult(statistic=42.90122143039788, pvalue=9.063698741097363e-66)

测试的 p 值低于 0.05,因此我们可以拒绝零假设,而支持另一个假设。

在第二个测试中,我们检查 2 号学校学生的平均成绩是否大于 90。

H _ 0:2 号学校学生的平均成绩大于等于 90
H _ 1:2 号学校学生的平均成绩小于 90

由于这是一个方向性测试,我们正在做 t 测试的单尾变体。

test_2 = stats.ttest_1samp(school_2, 90)# Ttest_1sampResult(statistic=-10.251936967846719, pvalue=3.087893244277984e-17)

scipy中,没有直接的方法表明我们想要运行测试的单尾变体。然而,为了获得期望的结果,我们自己调整输出。在这种设置的情况下,我们只需要将 p 值除以 2(测试统计保持不变)。

test_2.pvalue / 2# 1.543946622138992e-17

有了获得的p-value < 0.05,我们有理由拒绝零假设,支持替代方案。

为了彻底起见,我们还运行了测试的最后一个变体。

H _ 0:2 号学校学生的平均成绩小于或等于 90
H _ 1:2 号学校学生的平均成绩大于 90

test_3 = stats.ttest_1samp(school_2, 90)

我们还需要校正 p 值,这次的方法略有不同:

1 - test_3.pvalue / 2# 1.0

有了所得的p-value=1,我们就没有理由拒绝零假设。校正 p 值的方式取决于我们考虑的另一个假设,它是否涉及“更大”或“更小”的测试。

双样本 t 检验

在双样本检验中,我们检验两个样本均值的相等性。

H_0:来自学校#1 的学生的平均成绩与来自学校#2 的平均成绩相同

默认情况下,stats.ttest_ind假设总体具有相同的方差(在这种情况下是正确的,请参阅数据生成)。

stats.ttest_ind(school_1, school_2)# Ttest_indResult(statistic=6.635596055724986, pvalue=3.0230309820272883e-10)

结果表明,我们应该拒绝两个学校平均成绩相等的零假设,这符合我们的预期。

为了保持文章简短,我们只考虑检验的双尾变量,因为单尾计算类似于单样本 t 检验的代码。

结论

在这篇文章中,我提出了一些关于统计检验的单尾和双尾变量的直觉。默认情况下,大多数统计软件产生双尾结果。这就是为什么能够将这些结果转换为单尾等价结果也很重要。

如果你喜欢这篇文章的主题,你可能也会对描述功耗分析的文章感兴趣。

一如既往,我们欢迎任何建设性的反馈。你可以在推特或评论中联系我。文章的代码可以在这里找到。

一个统治所有人的工具

原文:https://towardsdatascience.com/one-tool-to-rule-them-all-c007b9489424?source=collection_archive---------35-----------------------

Photo by Randy Fath on Unsplash

如果你和我一样,你会重视用更少的资源做更多的事情——效率。当我还是一名电工时,我会尽量减少所需工具的数量,这样不仅可以减轻重量,还可以充分利用每件工具。数据科学家经常使用终端,移动文件或创建 git 存储库,然后上传到 GitHub。如果一个工具可以自己完成所有这些任务会怎么样?这样的工具是存在的,它叫做 Pycharm。

ycharm 是一个 IDE 或集成开发环境,它很简单,我们可以像程序员一样开发和处理代码。Pycharm 与众不同之处在于它内置了所有功能。本文将介绍 Pycharm 可以帮助我们实现更高效的工作流的几件事情。

Photo by Alvaro Reyes on Unsplash

首先,Pycharm 使用了 python,但并不局限于只使用 python。支持许多其他语言,如 R、Javascript、CSS、HTML 等等!Pycharm 附带了大多数库,并且可以通过终端或首选项中的插件部分安装其他库。插件这个词对任何编程爱好者来说就像音乐一样,它是新的兔子洞,花了无数个小时才意识到你已经走得太远了,现在不能回来。Pycharm 有一个插件部分,允许你安装更多的语言支持或主题,这样你就可以把它变成你自己的 IDE。这里简单看一下插件部分:首选项>插件。

在 marketplace 选项卡中,您可以找到不同的插件来满足各种需求或定制您自己的用户体验。我鼓励任何使用 Pycharm 的人在这里找到一些东西,并花时间尝试不同的插件设置。

版本控制

注意上面截图中写着“版本控制”的地方?每个软件工程师和数据科学家最好的朋友都住在那里——Git。您不仅可以找到使用 Git 的选项,还可以在 Pycharm 中链接 GitHub 并提交所有内容,而无需离开并打开终端。最好的部分是没有插件可以下载,Git 和 GitHub 都是预装的,随时可以工作。

在 version control 选项卡中,可以根据用户的偏好更改 Git 设置。在 Git 标签下,有 GitHub。在这里,只需点击“+”按钮并填写以下信息,即可链接 GitHub 帐户:

可以在 GitHub 上生成一个令牌来使用,我建议走这条路以避免任何安全问题。一旦 GitHub 帐户全部链接起来,并且你已经完成了你的第一个项目,你就可以提交和推送它了。提交并推送到 GitHub 只需要一个键盘快捷键:在 Mac 上,你可以点击shift+command+k弹出一个提交窗口,然后点击推,完成!Pycharm 甚至会为文件夹提供不同的颜色,让你直观地看到它们是否是 GitHub 的最新版本。最后,您可以将多个 GitHub 链接到 Pycharm,这样您就可以将您的个人 GitHub 和一个企业链接起来。

末端的

Photo by chuttersnap on Unsplash

典型地,当我们上传到 GitHub 时,终端是首选的工具。然而,现在我们已经不需要终端了吗?一点也不!Pycharm 有一个内置的终端窗口,所以在 IDE 之间访问和使用终端都在一个地方。如果有的话,终端现在更容易访问,因为不再需要切换窗口,从而减少了完成终端相关任务所需的时间。

上面你可以看到我一直在做的 python 脚本。如果我想测试它,我可以在位于代码部分正下方的终端窗口中运行它。

朱皮特

Source

ycharm 也可以运行 Jupyter 笔记本电脑,这是无价的,因为它允许我们在运行模型或测试代码的同时处理实际的代码。Pycharm 有这个功能已经有一段时间了,但随着 2019.2 更新到程序,它变得更加可靠和有用,创建了一个更稳定的环境。同样在 2019.2 更新中,增加了“全部运行”功能。我把 Jupyter 笔记本留到了最后,因为它在 Pycharm 的终端中创建了一个本地服务器,所以你现在可以在一个地方托管所有东西,而不必切换或管理两个独立的终端窗口。

最后的想法

Pycharm 对任何开发人员来说都是一个很好的工具,它拥有科学家日常需要和使用的所有功能强大的数据。从 HTML 到 SQL,Pycharm 都能做到。我想补充一下,Pycharm 可以在这里下载。JetBrains 是开发 Pycharm 的公司,提供 30 天的专业级软件试用。有一个社区版,可以使用一些有限的功能,但总的来说本身就是一个了不起的工具。我的生活哲学是拥有合适的工作工具,这在我做电工的时候很重要。拥有一个好的工具不仅对工作流至关重要,对数据科学家个人的发展也至关重要。

一个字的代码停止使用熊猫这么慢

原文:https://towardsdatascience.com/one-word-of-code-to-stop-using-pandas-so-slowly-793e0a81343c?source=collection_archive---------2-----------------------

那将永远改变你的生活

Photo by Lance Anderson on Unsplash

您已经将所有数据加载到 Panda 的数据框架中,准备进行一些探索性分析,但是首先,您需要创建一些附加的要素。很自然地,你转向应用功能。Apply 很棒,因为它使得对所有数据行使用函数变得很容易。您设置好一切,运行您的代码,然后…

美国驻 T2 大使馆

事实证明,处理一个大型数据集的每一行都需要一段时间。谢天谢地,有一个非常简单的解决方案可以为您节省大量时间。

下前支索

Swifter 是一个库,它“以最快的方式将任何函数应用到 pandas 数据帧或系列中。”要理解这一点,我们需要先讨论几个原则。

…向量化…

对于这个用例,我们将把矢量化定义为使用 Numpy 来表示整个数组的计算,而不是它们的元素。

例如,假设您有两个数组:

array_1 = np.array([1,2,3,4,5])
array_2 = np.array([6,7,8,9,10])

您希望创建一个新数组,它是两个数组的和,结果是:

result = [7,9,11,13,15]

您可以用 Python 中的 for 循环对这些数组求和,但这非常慢。相反,Numpy 允许您直接在数组上操作,这样速度明显更快(尤其是对于大型数组)

result = array_1 + array_2

关键的一点是,只要有可能,就要使用矢量化运算。

并行处理

几乎所有的计算机都有多个处理器。这意味着你可以很容易地通过利用它们来加速你的代码。由于 apply 只是将一个函数应用于数据帧的每一行,因此很容易实现并行化。您可以将数据帧分成多个数据块,将每个数据块提供给处理器,然后在最后将这些数据块组合成一个数据帧。

魔力

Source: https://github.com/jmcarpenter2/swifter

斯威夫特做的是

  1. 检查你的函数是否可以矢量化,如果可以,就使用矢量化计算。
  2. 如果无法实现矢量化,请检查是使用 Dask 进行并行处理还是仅使用 vanilla Pandas apply(仅使用单核)最有意义。对于小型数据集,并行处理的开销会使处理速度变慢。

这在上图中得到了很好的展示。您可以看到,无论数据大小如何,使用矢量化几乎总是更好。如果这是不可能的,你可以从 vanilla Pandas 获得最好的速度,直到你的数据足够大。一旦超过大小阈值,并行处理最有意义。

您可以看到“swiftapply”行是 swifter 会做的事情,它会自动为您选择最佳选项。

你怎么利用你问的这种魔力?简单。

如上所示,只需在应用程序前添加更快的调用,现在只需一个单词,您就可以比以往任何时候都更快地运行您的熊猫应用程序。

现在,你可以花更少的时间盯着进度条,花更多的时间做科学。这改变了生活。不过,你可能没那么多时间进行剑战了。

Source: https://xkcd.com/303/

免费获得掌握数据科学的 11 种极其有用的资源

图表中一年的卡路里计数

原文:https://towardsdatascience.com/one-year-of-calorie-counting-in-graphs-4a89784e11d7?source=collection_archive---------22-----------------------

*请注意,本报告最初撰写于 2018 年 11 月,因此数据涵盖了 2017 年 11 月至 2018 年 11 月这一年

动机

一年前,我刚开始第一份全职工作几个月,还在学习如何成为一个有功能的人,差一磅就要有一个肥胖的身体质量指数。需要做一些事情。

所以,我开始记录我每天的卡路里摄入、卡路里消耗和体重,以此来记录我的健康状况。最初的目标只是看看随着时间的推移,降低我的净热量是否对我的体重有任何影响。虽然这是我能够回答的问题之一,但在过去的一年里,计算卡路里的旅程变得更加漫长。

我想谈谈在跟踪我的健康状况的过程中,我经历过的最大的积极面,以及在这段经历中我面临的最大的消极面。希望这能帮助你决定健康追踪是否适合你!

关键积极因素(+):随着时间的推移取得了可衡量的进展

我的健康跟踪带来的最大积极影响是,它让我能够直观地跟踪我的进展,并查看我所做的任何改变(积极的或消极的)是否对我的健康有任何影响。因为我最初的主要目标是减肥,所以这就是我想在这里谈论的故事。

虽然你的减肥速度取决于其他几个因素,如遗传和活动水平,但通常的想法是,你保持的净热量越低,你可以减掉的体重就越多。先来看看我一段时间的净热量。

一段时间内的净卡路里

  • 虽然原始数据(蓝色)非常嘈杂,但一旦我们采用滚动平均值(红色),真实趋势就会变得更加明显。自从我开始收集数据以来,我的净卡路里一直在稳步增加,最终在 4 月底达到峰值,每天大约 3500 净卡路里(哎呀!)
  • 老实说,在那一点上,我记得我一直感到疲倦和沉重,并意识到如果我想减少我的净热量,我要么需要增加我的热量,要么减少我的热量。问题显然出在我摄入的卡路里上(我吃得太多了),所以我有意识地努力少摄入卡路里
  • 从那以后,我的净热量在 5 月底下降,此后稳定在 2000 卡路里以下
  • 另一个有趣的地方是,我的净卡路里波动性(蓝色图表的范围)自波动性在 4 月达到峰值以来一直在减少,这意味着我发现自己每天的卡路里摄入更加一致

现在看看我同期的体重:

重量随时间变化

  • 对于从 180 到 165 的最初下降,我真的很兴奋,这种下降在 12 月中旬结束。我以为我会永远以同样的速度减肥,但我肯定错了
  • 在我最初的减肥冲刺后,我发现我的心态放松了,让自己吃得更多(从上面的净卡路里图可以看出),这最终让我付出了代价。到四月中旬,我已经回到了在这一切开始的地方
  • 即使当我稍微收敛一点,开始控制饮食,我的体重也没有真正改变,反而在 175 左右徘徊了几个月。
  • 只是在最近两个月(9 月和 10 月),我才看到体重和去年 12 月时一样低。我想一部分原因是因为我停止了每天追踪体重,但更多是在以后!

当然,我们还没有在同一张图上看到净卡路里和体重,所以让我们看看它们是如何比较的。由于它们在不同的尺度上,我用对它们进行了归一化(本质上是在不改变数据形状的情况下让它们在相同的尺度上)。

净卡路里和体重有什么关系?

  • 第一个月似乎很奇怪,因为我的净卡路里在增加,而我的体重在迅速下降,但我认为这更多地是因为去年 11 月,在几年相对不活跃的大学生活后,我第一次开始认真锻炼。我的身体似乎对此很欣赏
  • 真正酷的事情是,在第一个月之后,这两条线似乎彼此非常接近,尤其是从今年三月开始!如果你想知道为什么没有 7 月以后的数据,那是因为我在 8 月初就停止了跟踪我的每日体重,但正如我所承诺的,很快会有更多的数据

关键否定(-):健康变成了一场游戏

每当你开始有意识地、频繁地记录某件事,不管是你的财务状况、工作表现,还是你的健康状况,那件事就会开始变得像一场游戏。这似乎是一个潜在的积极因素,因为你想得到最多的分数,因此保持动力,但这也可能会造成严重的精神负担。

这就是我四月初的遭遇。

直到四月,我判断自己的唯一标准是净卡路里。此外,我设定了我的目标,总是保持我的净卡路里低于 2000。虽然这种方法工作了一段时间,但我很快发现自己在尝试“入侵”自己的系统。

也就是说,如果晚餐结束时我的净卡路里碰巧是 1500 左右,我会发现自己吃了一些我不需要的东西,只是因为我还没有达到 2000。在我看来,我很聪明。与此同时,我的身体为此付出了代价,因为我经常吃像冰淇淋、巧克力等垃圾食品。此外,我很少在这样的日子里锻炼,因为我的净卡路里已经低于 2000,所以为什么还要进一步减少呢?

事实上,当我做了一个净卡路里的柱状图时,我的大部分日子都紧紧围绕着 2000 年:

净卡路里的分布

大约就在这个时候,我想出了第二个衡量标准,这个标准将把净卡路里作为衡量我是否健康的唯一标准。这个指标被称为卡路里出入比率,简单定义为卡路里出入除以卡路里。

要了解这一指标的威力,请比较这两个潜在的天数。在第一天,你消耗 2000 卡路里,燃烧 0 卡路里,产生 2000 净卡路里。在第二天,你消耗了 2500 卡路里,燃烧了 500 卡路里,也产生了 2000 卡路里的净热量。但是,我宁愿在第二天,因为我有相同的净热量,但也有良好的锻炼带来的好处。由于第一天的比率为 0,但是第二天比率为 0.2 (500 卡路里的输出除以 2500 卡路里的输入),所以输出-输入比率反映了这一点。

好消息是,在我开始使用这个指标之前,我已经有了填充五个月的出入比率值所需的所有信息。因此,我也可以随时检查我在这一指标上的进展:

一段时间内的热量输出/输入比率

  • 这个指标在很长一段时间内稳定在 0.1 左右,直到 5 月下旬达到峰值,也就是在 4 月下旬,我开始增加锻炼,减少饮食,以应对健康爆发点
  • 在 6 月份和 7 月份的大幅下降之后,过去三个月里,转出与转入比率一直在稳步上升,接近 0.2

从 4 月份开始,我发现自己不太倾向于“侵入”自己的系统,并且在使用净卡路里和进出比率来确定每天的健康状况时,感觉更稳定了。

关键正面(+):卡路里成为货币

在过去的一年中,一个持续的积极因素是我开始把卡路里视为一种货币形式。在追踪我的健康状况之前,我只会吃我想吃的东西,并不时地为自己的决定后悔。然而,在过去的一年里,我发现自己提前思考了我的一天。大约在午餐时间,我会根据我是否有一顿大餐的计划,是否想用一份美味的甜点犒劳自己,或者是否坚持到了早晨锻炼,来开始考虑我想吃多少。

肯定有这样的时刻,我曾考虑过在工作时吃点生日蛋糕,但却因为没有足够的卡路里而停止了。事实上,这种心态的转变花了我几个月的时间来真正巩固,它帮助我把卡路里当作资源,并帮助我限制我的消费。

关键否定(-):过度问责

在我开始跟踪健康的时候,一个很大的目标是,如果我没有达到我的目标,我会对自己负责。当净卡路里仍然是我的主要性能指标时,我已经在我的数据中包含了一个名为“原因”的列。任何一天,当我摄入超过 2000 卡路里时,我让自己写下失败的原因

这在一段时间内起了作用,帮助我理解了是什么导致了我的失败,但是它很快变得非常压抑。有几个星期,我参加了几次社交活动,或者去健身房的时间更少,我会不断地用文字向自己解释我的失败。它从信息变成了彻头彻尾的士气低落

因此,随着我前面提到的 out-in 比率的采用,我从我的数据中删除了这一列。相反,我选择只是在心里记下我是否未能实现目标,并思考未来的一天,而不是记录我失败了多少次。

由于我的目标在三月初有所改变,更加关注体育锻炼,我选择放弃上面提到的“原因”专栏,转而选择了我的数据中的两个新专栏,名为“有氧运动?”和“重量?”对于我那天是否完成了心血管或重量训练,每一个问题都只是一个是/否。这两个简单的衡量标准对我个人来说非常有效,确保我经常锻炼而不会过于专横。它们让我能够跟踪一年中我的锻炼频率是如何变化的:****

一段时间内的有氧运动和重量训练(每个黑条代表一天的训练)

  • 从这张图表中最大的收获是,我的锻炼频率在过去的几个月里已经稳定下来,但是比六月和七月的低谷期要好得多

同样是在三月初,我开始跟踪我每天结束时的总体情绪,我简单地把它分为😃😐,或者:()。这绝对是我最不“科学”的衡量标准,但却帮助我思考为什么我的一天会这样。情绪绝对不仅仅是我测得的健康数据的函数,但情绪和卡路里之间仍然有很大的关系,如下所示:

卡路里和情绪之间的关系

  • 可以很清楚地看到平均摄入热量随着情绪下降而增加,而平均摄入热量随着情绪上升而增加。虽然我真的没有真正的科学可以给你,但我可以说,在我锻炼的日子里,当我没有吃得太多以至于在一天结束时感觉很糟糕的时候,我感觉好多了。

最近,在八月初,我变得如此专注于减肥,以至于我发现自己在一天之内去了三四次体重秤,经常惊讶地发现两个小时内什么都没有改变。我知道体重是我想追踪的最大指标之一,但这种每日追踪在道德上让我痛苦不堪。为了保持理智,我选择放弃潜在有用的数据。我现在的系统是每月检查几次我的体重,并记录下来,而不是每天都检查。

结论

我认为在过去的一年中,健康跟踪对我来说是一个整体积极的事情,并且不需要太多努力,特别是在这些天先进的健康监测应用程序的帮助下。尽管如此,重要的是要注意不断监测你的健康会对你的…嗯,健康产生负面影响。和往常一样,良好的平衡以及反复试验是你可以使用的最好工具。

我希望上面的一些想法和数据能帮助你决定是否要开始追踪自己的健康状况!

数据收集说明

如上所述,这个项目最初是通过每天测量三个指标开始的:卡路里摄入、卡路里消耗和体重。

我尽可能精确地测量卡路里,在有营养数据时研究它们,在没有营养数据时做最好的估计。

类似地,我根据我当时的体重,通过咨询各种运动的卡路里燃烧率来计算卡路里。值得注意的是,这并不包括休息时燃烧的卡路里。也就是说,我只记录了有意的身体活动消耗的卡路里。

我用家里的电子秤计算体重,并尝试每天在相同的时间测量。

使用 Tensorflow.js 进行在线机器学习

原文:https://towardsdatascience.com/online-machine-learning-with-tensorflow-js-2ae232352901?source=collection_archive---------19-----------------------

关于如何使用 Tensorflow.js 在浏览器中创建、训练和测试机器学习模型的端到端指南

(Source: https://miro.medium.com/max/1400/1*F-1fq9TNjDnAYPAXnZP4Ww.png)

介绍

由于最近人工智能的进步,现在建立和训练机器学习模型变得相对容易。虽然,这些模型只有通过分享它们,让它们做好在线预测的准备,才能让社会受益。

在我之前的一篇文章中,我解释了如何使用 Heroku 和 Flask 创建和部署一个简单的机器学习模型,今天我将为您提供另一个选项:Tensorflow.js。

Tensorflow.js 是 Google 创建的 Javascript 库,用于将机器学习能力嵌入到任何形式的 web 应用程序中。

为了添加一些浏览器内可视化,Tensorflow.js 使用了一个名为 tfjs-vis 的小库。这个库可以用来创建一个侧面板,所有的内容都可以在上面显示。

除此之外,谷歌还开发了另一个名为 ml5.js 的库,旨在使在线部署预训练模型变得非常容易。这样,非专业人员也可以开始在网络上部署机器学习模型。一个简单的例子,如何使用谷歌 PoseNet 预训练模型是可用的这里

有 3 种主要类型的模型可以在线部署:

  1. 回归模型

在这个例子(GIF 1)中,我决定使用“瑞典汽车保险风险溢价分析委员会”数据集来训练和可视化一个简单的回归模型。打开网页后,培训过程将实时在线进行。

GIF 1: Training and Visualizing online a Regression Model

2.分类模型

在这个例子(GIF 2)中,我决定使用“葡萄酒数据集”来训练一个分类模型。在这种情况下,培训过程也是实时在线进行的。此外,还提供了所用神经网络层特征的总结和分类矩阵。

GIF 2: Training and Visualizing online a Classification Model

3.预训练模型

最后,在这个例子(GIF 3)中,我决定使用一个预先训练好的模型。我首先使用“Pima Indians Diabetes Database”用 Python 训练了这个模型,将其保存为 JSON 文件,最后将其部署到网上,准备进行预测。

GIF 3: Making Predictions and Visualizing online using a Pre-Trained Model

这三个例子都可以在我的个人网站上找到,如果你有兴趣测试一下的话。

在本文中,我将带您了解如何实现这三个示例中的第一个。

所有用于创建这些例子的代码和数据集都可以在我的 GitHub 库中找到。

示范

对于这个例子,我将使用这个“瑞典汽车保险风险溢价分析委员会”数据集。这个简单的数据集仅由两列组成(X =索赔数量,Y =瑞典地理区域内所有索赔的总支付额,单位为千瑞典克朗)。

作为演示的一部分,我们将通过检查索赔分布的总数来预测所有索赔的总支付额。

设置

首先,我们需要创建一个 HTML 页面来显示我们的内容。下面的代码片段提供了一个基本的模板,您可以随意添加任何您想要的功能!

预处理

我们现在可以创建另一个名为 script.js 的文件(在我们的 HTML 文件的同一个目录中),在这里我们可以开始加载数据集并执行一些基本的预处理任务。

为了从 JSON 文件加载数据集,我们可以使用下面的函数( getData )。在这个函数中,我们首先加载数据集,然后选择我们感兴趣的列,并给它们取一个用户友好的名称。最后,使用一个过滤函数,我们去掉所有出现在所选列中的 nan(不是一个数字)。

接下来,我们可以创建一个函数来预处理我们的数据集( convertToTensor )。在这种情况下,我们:

  1. 混洗数据 =随机化样本的顺序,这些样本稍后将用于训练我们的回归模型。通过这种方式,与原始数据分布相比,我们可以为我们的模型提供更多种类的数据(这是因为当输入模型时,我们的训练数据将被连续划分为更小的子集,称为批次)。
  2. 将数据分为特征和标签 =特征将是我们的输入样本,标签将是我们的真实输出值(基本事实)。
  3. 以张量形式转换特征和标签 =我们将原始数组转换成二维张量。
  4. 标准化输出张量 =将我们的数据重新调整到 0 到 1 之间的范围。这样做是为了防止训练模型中出现过大或过小的值(上溢/下溢)的问题。一旦训练了我们的模型,我们就可以反规格化我们的输出来获得我们的最终结果。

定义和训练我们的模型

我们现在可以继续设计一个简单的机器学习模型( createModel ),然后创建一个函数来训练它( trianModel )。

在这种情况下,我利用回调来调用 Tensorflow.js 图形支持库 tfjs-vis ,以便创建一个实时图形,显示我们的模型损失在训练期间是如何变化的(图 1)。如果你有兴趣更详细地了解回调是如何工作的,我在本文中提供了更详细的解释。

Figure 1: Real-Time model Loss

测试

现在我们的模型已经训练好了,我们可以开始做预测了。为此,我设计了下面的函数( testModel )。在这个简单的例子中,我决定使用训练数据本身来测试我们的模型性能。

此外,我还对我们的模型预测进行了反规范化,然后将它们与真实输出进行了对比,以便检查我们的模型性能(图 2)。

Figure 2: Model Predictions vs Original Data

运行模型

最后,我们现在需要创建一个函数来运行所有代码(运行)。在这个函数中,我们首先执行一些数据可视化,然后调用我们之前定义的所有函数(图 3)。

Figure 3: Scatterplot of the original data

现在,您可以通过在自己的网站上运行或使用本地服务器来测试您的模型。如果您从未使用过本地服务器,一个简单的解决方案是使用 Visual Studio 代码并安装其 Live 服务器扩展

联系人

如果你想了解我最新的文章和项目请关注我的媒体并订阅我的邮件列表。以下是我的一些联系人详细信息:

网络营销测量:哪一半?

原文:https://towardsdatascience.com/online-marketing-measurement-which-half-ce7ef3f26b7e?source=collection_archive---------34-----------------------

John Wanamaker (1838–1922)

广告在今天的互联网上一直存在。他们支持谷歌和脸书,并跟随我们到任何地方。与所有营销支出一样,它们是一种投资。与大多数投资一样,衡量投资回报至关重要。

使在线营销与众不同的是建立精确测量工具的前所未有的可能性。

在这篇文章中,我将描述一些在行业中广泛使用的技术,并分享我在构建 Airbnb 的展示营销测量框架时获得的一些经验。

归因和增量

为了公平地估计 roa(广告支出的回报),我们需要能够将增量购买归因于引起它们的活动。我们对接触有机购买的人群不感兴趣(例如,自己购买),而是接触不打算购买的人群,并通过我们的广告说服他们。两者之间的区别是相关性和因果性之间的区别,并且可以被目标机制所利用。如果我们不区分有机购买和增量购买,定位算法将因描述和定位更有可能购买的用户而获得奖励,这将是“向唱诗班布道”。

我们希望从我们的在线活动中接触到那些被说服的人,并说服他们购买我们的产品。

这有点微妙,因为特别是像旅游住宿这样的商品,我们可能需要多个接触点来与用户建立关系,并慢慢地将他们转移到漏斗中。

不幸的是,老学校的归属系统依赖于臭名昭著的“最后点击”:即在购买获得信用之前最后点击的广告。

这是有问题的,因为它没有区分增量销售和有机销售,但它也有较大的偏差。

美国和欧洲的大多数用户拥有多种设备,并通过桌面、移动和标签登录。这使得跟踪用户旅程变得很有挑战性。Cookies 被删除和多个用户从同一设备登录只是构建和维护设备图的两个问题,设备图可以帮助识别用户已经接触了哪些广告。

由于这个问题,展示渠道(如脸书、Instagram、YouTube 等。)与漏斗中较低的渠道(如 SEM(搜索引擎营销))相比,过于不利。

在“最后一次点击”的世界中,SEM 营销获得了很大份额的信任,这也是因为用户很可能通过谷歌相关关键词被重定向到该网站,这应被视为一种有机(即非增量)购买。

为了理解“最后一次点击”的归因是多么荒谬,想象一下向你的另一半求婚,如果有理由相信订婚戒指是他们积极回应的唯一贡献者。

幸运的是,统计学家有很多锦囊妙计,可以追溯到几个世纪前的许多实验设计可以拯救我们。

实验和测量

如上所述,测量增量的问题恰恰是相关性与因果性的问题:我们想要识别我们引起的购买,而不是将我们的广告与用户的购买倾向相关联。

主要的挑战是尽可能地将目标从用户的动作中分离出来,这在这些复杂的环境中并不容易。

在控制大多数已知因素的同时,实验是精确测量因果关系的最佳工具。

实验的设计将取决于广告平台的性质:在最受欢迎的选项下面。

意向治疗(ITT)

我要描述的第一种方法是临床试验领域的一种非常古老的技术,也是脸书的转换提升研究工具中使用的方法之一。

当试图确定目标算法的效果时,我们无法将算法选择的受众与固定的控制进行比较。这将奖励樱桃采摘:如果算法被训练来选择有机转换器(即无论如何都要购买的用户),我们将高估算法的性能,混淆有机行为(相关性)和增量效应(因果关系)。

意向性治疗(ITT)是一种分析实验的技术,其中存在单方面的非依从性,即当治疗组中的一些受试者没有接受治疗时。将非服用者排除在分析之外会导致选择偏差,但忽略这个问题并假装治疗组中的所有受试者都是平等的会低估效果或只是测量不同的东西(即被分配到治疗组的效果而不是治疗本身的效果)。

ITT 原则可以用“一次随机,永远分析”来概括。 ICH 声明“意向性治疗原则意味着主要分析应包括所有随机受试者。遵循这一原则需要对所有随机受试者进行完整的随访,以了解研究结果。在实践中,这一理想可能难以实现[……]”。该建议的理由是,即使数据缺失(不符合)不是完全随机的,ITT 分析也会给出稳健的估计。这将涵盖不遵从治疗的或多或少严重的患者的临床情况,或者,在我们的营销案例中,用户是由算法精心挑选的。

一般来说,当试图测量绝对增量(或提升)时,我们可以问以下问题:

  1. 向 100 个人展示一个广告会带来多少额外的销售额。
  2. 100 个人看到这个广告会带来多少额外的销售额。

ITT 不仅不受缺乏合规性的影响,而且可以衡量什么是可操作的(选项 1),而且在很少假设的情况下,它允许我们衡量两者。

ITT Design

上图把设定解释的相当清楚。条纹衬衫代表高意向用户,他们必然会有机转化。在玩具示例中:

  • 治疗是中性的。暴露后转化的概率与有机率相同,为 50%
  • 覆盖率(即接受治疗的治疗使用者的百分比)为 42%
  • 该算法以高意向用户为目标,这些用户无论如何都会转化,因此治疗中有 83%的用户会转化。
  • 由于有偏见的目标,只有 25%的从未服用者(即治疗组中没有得到治疗的使用者)转变了。
  • 如果我们不是以 ITT 的方式来分析,我们会得出这样的结论:增量转换率是 33%

脸书的提升测试工具使用 ITT 分析来测量增量。由于目标算法针对更有可能转化的人进行了优化,因此很难找到类似的控制(这实际上非常容易,但需要改变目标算法,类似于谷歌的幽灵广告。)

治疗和控制之间的分离发生在“整体”水平(即,受众中的所有用户都有资格进行拍卖),然后广告被显示给治疗组中的一部分人。维持组和测试组的拍卖资格都有记录,印象也是如此,但接触过广告的控制用户的子集没有记录(下图中的红色三角形)。

Facebook Lift Study

ITT 设计很容易实现,通过一些简单的数学计算,我们可以从“向 100 个人展示一个广告会带来多少额外的销售额”到“100 个人看到这个广告会带来多少额外的销售额”。后者等于第一次缩放(除以)的范围。

这种设计的缺点是低覆盖范围会大大减弱信号,因此在计算功率时需要考虑覆盖范围。

Power curves at sample size 200

由于这一事实,ITT 不太适合广泛接触运动:这种倡议假设接触广泛受众中少数有前途的个人,因此它们本质上是为低接触而设计的,最终动力不足。

在下一节中,我们将描述另一个可以解决这个问题的设计。

“幽灵”广告

如前一节所述,当目标算法优化了谁被派发广告的选择时,就很难确定适当的控制。

ITT 设计在分配水平上比较各组,但这有局限性,因为当治疗组的 reach 百分比较低时,估计可能具有较高的不确定性,这可能导致信号减弱。

这个问题的另一个流行解决方案是预测幽灵广告。这种方法首先由谷歌开发,用于精确测量他们的显示广告,包括使用与定向相同的算法来识别对照组中“会被提供”广告的用户,并将他们作为治疗组中实际提供广告的可比组。

Ideal Experimental Setting

这是一个理想的设置,因为我们将使用相同的标准来选择治疗组和对照组,然而,这可能是复杂的和难以实现的,特别是在更复杂的广告定位系统中,

在第三代系统中,优化程序将使用从站点访问中提取的特征,并将学习更多关于治疗组中的用户的信息,这可能会引入偏差,因为相同的学习对于对照组中的用户是不可能的。对照组最终会成为第一次接触的目标用户的代表,但他们对第一个广告的反应的任何信息都只能在治疗组中获得,这引入了潜在的偏见。然而,第二代系统只使用用户特性,因此尽可能保持两个组的同质性。

GDN 定位算法属于第二代家族,它可以轻松利用 Ghost Ads 框架。然而,脸书的目标更先进,这就是为什么它必须依靠某种形式的 ITT。

这非常难以实现,但是在混合 Ghost-ITT 设计中,将机会记录减少到第一次接触将是增加范围的一个很好的折衷。

“分割”测试

当然,即使在这种情况下,经典的 AB 测试也有其用途。分割测试是设计用来测量一个活动的某些特征的相对增量的实验。绝对增量是投放广告的因果效应,相对增量是一个版本的广告相对于另一个版本的附加值。

此工具对于快速迭代复制更改、图像、设计等非常有用。虽然这种测试很容易启动,但可能很难衡量即时的变化(由于购买的延迟)。

地理层面的实验

所有这些技术都假定在广告管理中有高度的控制。这就是为什么他们嵌入了供应商(脸书、谷歌等)的生态系统。).他们的成功基于个体靶向性,确保治疗臂之间无溢出和分离。

然而,有许多广告渠道不能给予这种程度的控制。例子包括:

  • 广播/电视/户外广告
  • 长期影响(即使使用当前的工具,也难以长期对用户进行分组)

由于我们无法控制单个单位的分配,在这种情况下,我们根据位置分配我们的支出。由于用户只能在特定时间处于特定地理位置,根据他们的移动性,我们可以控制谁是特定活动的目标,谁不是。

这可以通过选择几个城市、州或指定的市场区域(DMA)作为目标,而将其他几个安静的区域作为对照来实现。这显然是一个大规模的操作,意味着内部协调,并在由于控制区域和对 roa 的理解而导致的销售损失之间进行权衡。

DMA’s in the USA

我不会在这里深入讨论如何分析这些类型的实验。像差异中的差异(非常类似于谷歌的基于时间的回归)这样的技术很容易实现,但往往不可靠。合成控制(如谷歌的因果影响包)类型的技术更灵活,允许更高的功率和更强的推理。

数据中心方法

这篇文章给出了一个营销测量的鸟瞰图,并描述了一些重要的技术。

还有一些我没有涉及到的领域,但是同样重要。努力像建立一个可靠的自下而上的多接触归因模型(MTA 又名数字营销的圣杯)或混合媒体模型(嗯,自上而下的方法来决定在哪里花下一个营销美元)。

建立数据驱动的数字营销团队的关键是培养数据文化。尽管数据科学家对测量技术有着深刻的理解,但市场营销人员对数据有着最佳的感觉,并且在获得访问权限和培训后,能够扩展测量工作。对数据的更多关注也将有助于提高数据质量,因为停机将被更早地报告。

允许营销人员将他们的营销活动作为实验,并赋予他们对统计测试的理解,将允许更好的假设得到检验,更快地失败并采用新的知识。

这最终可以总结为一种“衡量它或根本不做它”的文化,在这种文化中,只有当投资回报是可衡量的时,美元才会被花掉,而这只能通过衡量工具的民主化来实现。

选择权在你…

词汇表

  • DMA =指定市场区域
  • SEM =搜索引擎营销。搜索引擎搜索顶部的赞助广告。
  • SEO =搜索引擎优化。
  • ROAS =广告支出的回报
  • MTA =多点触摸属性。
  • MMM =混合媒体模型。
  • ITT =意图治疗
  • 吃了 =治疗效果一般

原载于 2019 年 11 月 10 日http://mrpozzi . github . io

在线扑克——何时赚钱?

原文:https://towardsdatascience.com/online-poker-whens-the-money-a22fe3fa7a6?source=collection_archive---------10-----------------------

玩的最佳时间和它的价值

Photo by Michał Parzuchowski on Unsplash

当扑克玩家在线分享牌局进行策略讨论时,他们会将自己标记为英雄,将对手标记为恶棍。无论这是为了隐藏他们的身份还是他们的对手,这种随意的行话揭示了一个关于扑克的基本真理-这是每个玩家与世界的对抗,如果你需要一个英雄,不要看得太远,因为没有人会来救你。

这就是我过去十年生活的现实。作为一名职业扑克玩家,我专注于两人对决锦标赛(常规德州扑克,但只有两名玩家),我经常发现自己陷入旷日持久的在线领地之争。我交过朋友,但它们通常只有在互利的情况下才会持续,这通常相当于“我们都很好,我们不玩对方如何?”

这个世界是我的第二天性,但有时很难用语言来表达。因此,为了描绘一幅更清晰的画面,我将数据科学工作流应用于一年的游戏摘要样本(大约 200,000 份,超过 14,000 名不同玩家,全部来自一个买入级别),主要目标是回答问题“职业玩家玩游戏的最佳(最赚钱)时间是什么时候?”本文着眼于该分析的一些过程和结论。

数据争论

第一步是争论我的数据。为了做到这一点,我获取了游戏摘要数据,并将其子集化为每个唯一的玩家,使用来自每个子集表的聚合玩家结果来填充玩家结果表。游戏计数表是通过每小时对时间序列进行重新采样获得的,每小时计数一次。

时间序列 EDA

将确定最有利可图的游戏时间作为我的主要目标,并假设这将与每小时的游戏数相关,我首先对每小时的游戏时间序列进行了一些 EDA(探索性数据分析)。有几件事很突出:

工作日的客流量比周末高

工作日的平均流量高于周末,这可能会让最有经验的玩家感到惊讶。

数据中有空白

从频率分布来看,每小时 0 场比赛似乎在数据中被夸大了。在这种情况下,我已经知道数据中有一些漏洞,但通过这个视图,我对这些漏洞的规模有了更好的了解,这将有助于为任何填充策略提供信息。

时间序列是季节性的

这里第 0 天是星期一,第 1 天是星期二,以此类推。时间序列中有明显的每日季节性成分(也可能是每周——这可以解释周日交通流量较低的原因)。正午过后,每小时的游戏数确实会更高。

12 月交通流量激增

12 月的流量有一个显著的峰值,但是样本中只有 12 个月,所以不可能知道这是否是经常发生的。需要进一步的研究或 EDA 才能有机会确定原因。

玩家 EDA

另一个明显影响玩家盈利的因素是对手的技能水平。虽然我们没有机会预测单个玩家的行动,但对总体结果的分析也有助于确定最佳的游戏时机。

我分析的这一部分无疑是最吸引人的,每一个情节都在揭示一些隐藏的真相的同时,提出了和它回答的一样多的问题。

投资回报是有限的

平均投资回报率是衡量扑克玩家技能的最佳指标。随着所玩游戏样本的增加,该指标作为技能衡量标准的有效性也随之增加。在该数据中,所有游戏的买入费为 51 美元,因此 2%的投资回报率代表每场游戏约 1 美元的利润。每款游戏还有 1 美元的沉没成本(对托管游戏的网站而言),这已计入投资回报率。

这里我们看到,随着玩家游戏次数的增加,他们的 ROI 被限制在一个更窄的范围内(或者更具体地说,比-100%到 100%更窄的范围)。在扑克社区中,单挑扑克的基本策略被认为是在不看牌的情况下把所有牌都押上,在这种情况下,这将产生大约 45%的投资回报率(超过一个重要的样本)。在 50 场以上的游戏中,我们看到平均 ROI 符合这一基线,随着游戏数量的增加,ROI 范围变得越来越窄(这说明玩家需要超过一定的 ROI 阈值才能激励他们如此频繁地玩游戏)。

虽然该图信息丰富,但它也隐藏了大量数据,因为许多点代表不止一个玩家(有时超过 1000 个玩家)。为了更清楚地了解 ROI 与游戏次数的关系,我们重复了这个图,这次是根据游戏次数对玩家进行分组,然后取平均 ROI 的平均值。

赢的越多,玩的时间越长

这是一个有用的投资回报率的近似值,反过来也是技能水平的近似值,适用于游戏次数少的玩家,他们的结果受高水平方差的影响。一个显而易见的结论是,玩游戏次数最少的人是最差的玩家——尽管存在一些偏见,即赢得第一场游戏的人肯定有能力再玩一场游戏,但失败者却不是这样。

那些不熟悉扑克的人经常问我,完全的新手是不是最难对付的,因为他们太不可预测了。这就是我的答案,不!一个新玩家在游戏中的行动可能是不可预测的,但总体来说,他们的策略将是可预见的糟糕,他们将是我每天的首选对手。

请注意,图的中心非常嘈杂。在这里,我们对 2-15 名玩家进行了任意分组,分组的投资回报率差异很大。这促使我们进一步分析与不同样本规模的固定胜率相关的 ROI 差异。我由此得出结论,当游戏样本低于 1000 时,我不愿意根据玩家的投资回报率对他们的技能水平做出强有力的结论。

很少有人有可靠的收入

在这里,我们看到大多数玩家在他们的整个游戏样本中经历了名义上的赢/输,超过 90%的玩家赢或输的钱少于$500。在剩下的人中,有几个是高收入者,许多人损失了中等数额。

从这些图(和附加直方图)中,我看到 99%的玩家在一年中玩了不到 200 场游戏,剩下的 1%中,一半属于 200-400 场游戏,最后一半属于 400-19000 场游戏。我们在前面的图中看到,少于 400 场比赛的玩家主要是输球的玩家。

在这里,我们开始看到两类玩家的出现,大多数(超过 99%)是胜率不一的休闲玩家,一小部分(不到 1%)玩得更频繁,可以从他们的样本中看到可观的回报。

为了进一步探索玩家分类的想法,我将玩家分为两类,一类是玩 1000 个游戏以上的玩家(高容量玩家),另一类是玩不到 1000 个游戏的玩家(低容量玩家)。

每个游戏有两个玩家,所以从玩家的角度来看,200,000 个游戏相当于 400,000 个游戏。

高交易量的玩家一年总共赢了 40 多万美元,低交易量的玩家总共输了 80 多万美元(该网站举办这些游戏净赚了 40 万美元)。

最有趣的是每组内部的游戏率。17%的高容量玩家玩的游戏是与其他高容量玩家玩的,这个数字在低容量玩家中只有 10%。这意味着超过 80%的游戏包括一个高音量播放器和一个低音量播放器。

这比我预期的更清楚地代表了在线扑克单挑社区的动态。有两类玩家,职业玩家(高容量)和娱乐玩家(低容量),或者玩家称之为鲨鱼和鱼。鲨鱼大部分时间都在玩(吃!)鱼,鱼很少有机会吃掉其他的鱼(在鲨鱼出现之前),有时鲨鱼会为了保护它们的鱼群而一决雌雄。

这个类比在在线扑克中很普遍,可以激发一些有趣的广告活动…

将玩家分类为职业玩家或娱乐玩家(鲨鱼或鱼)可能是确定最有利可图的游戏时间的有价值的特征。我们有一些功能可以进行粗略的分类(ROI 和游戏计数),深入了解高容量玩家的内部游戏率可能会对我们应该如何使用这些功能提供一些提示(例如,通过设置被视为鲨鱼的 ROI 阈值)。

鲨鱼大战鲨鱼

为了调查高容量玩家的内部游戏率的情况,我构建了一个按利润排名前 20 位玩家和按游戏排名前 20 位玩家的每种组合之间的游戏配对矩阵。结果集是 25 个玩家,显示出两个组之间的高度重叠。

该组中的所有玩家都玩过 2000 多场游戏。尽管如此,他们几乎都不玩游戏。这种最频繁的玩家之间的小游戏计数,这些玩家都是(除了一个)赢家,表明大多数赢家积极努力避免彼此玩。

在这组玩家中,有一个玩家与其他玩家进行了大量游戏,尽管对手如此强大,但他们的投资回报率并不比每场游戏的沉没成本(rake)低多少。这个玩家和他的对手有相似的技能水平,但是由于所述对手的技能水平更高,他的回报很低。

这种动态最好用网络图来说明:

Top 25 players network graph

  • 每个节点代表一个玩家,圆圈大小是绝对 ROI,蓝色表示正 ROI,红色表示负 ROI。
  • 线强度是两个玩家之间的游戏次数。
  • 节点位置由 networkX springfield 布局生成(因此接近度也代表两个玩家之间的游戏玩家数量,但布局不是确定性的,即每次绘制时都会发生变化)。

在这个图中真正突出的是,它的中心是投资回报率较低的玩家(较小的节点),这个组内的大多数互动是在最弱的玩家之间进行的。较强的玩家之间几乎没有互动,与群体中较弱的玩家互动也非常少。

另一种形象化的方式是与红色节点的互动。在这里,我们可以看到红色节点代表的玩家很少与投资回报率超过 5%的玩家进行游戏,他们在回避更强的玩家!

在这里,我们开始了解职业单挑玩家的真实生活。

职业玩家积极努力避免互相游戏,这是一组玩家之间不成文的协议,先于本研究中的游戏样本。为了进入这个职业组,玩家必须通过与组中现有的职业玩家比赛来证明自己——为了提高他们成功的机会,他们将努力集中在较弱的现有职业玩家身上。玩家将这些团体描述为“卡特尔”,它们存在于大多数买入级别,随着赌注的增加,规模会变小。

又是什么激励弱势专业人士捍卫自己的领地呢?是身边的强者们!想象红色节点正在从一个洞里爬出来,蓝色的小节点正在试图把他推回去,知道如果自己不够努力,就会被周围更强的玩家自己推下去。

不幸的是,对这些玩家来说,扑克不仅仅是扑克,它还包括有效地管理敌对和互利的关系,以管理鱼鲨比,进而管理他们的底线。这种动态对于单挑锦标赛扑克来说是独一无二的,因为这是唯一一种你无法在不完全放弃玩游戏的情况下避开想要玩你的对手的扑克形式,因为这样玩家可以有效地猎杀其他玩家。

这可能在很大程度上解释了为什么我在扑克中的友谊很少超过互惠互利的程度。不像锦标赛玩家从许多不同的玩家那里赢得或输掉少量的钱,很难发展出怨恨或敌人,我经常处于这样的境地,我从一个玩家那里拿走了或已经从我这里拿走了 5 位数的钱,有时是在一天之内!老实说,我不会有任何其他方式。

但是让我们回到正题。我在这一阶段的分析中得出的另一个结论是,通过审查这些玩家相对于组中其他玩家的游戏投资回报率,当这些玩家玩红色节点时,实际上只有主机赚钱,因为技能差距不足以让任何一个玩家克服主机游戏的沉没成本。

回到最初的问题,玩游戏的最佳(最有利可图)时间是什么,如果我们可以将玩家分为职业和娱乐,鲨鱼和鱼,我们可以从每小时游戏数时间序列中删除鲨鱼对鲨鱼的实例,将其从每小时游戏数转换为至少包括一条鱼的每小时游戏数。通过这样做,我们分离出每小时流量的“盈利”成分,我们可以用它来预测未来的盈利播放时间。我们可以生成的另一个时间序列是一小时内在线的专业人员数量,这代表了每小时流量中“无利可图”的部分。

我还为数据中的每个玩家创建了一个额外的特性,即每小时在线玩游戏的次数。这表明鲨鱼通常比鱼每小时有更高的游戏计数,这在分类边缘案例时可能是有用的。

给玩家分类

是时候拿出一些聚类算法了?可惜没有!我们预计不到 1%的玩家是专业人士,这代表了严重的阶级不平衡,这对监督学习算法来说已经足够困难了,更不用说无监督学习算法了。我尝试了一下,但试图对这些未标记的数据进行聚类,最终以我手动检查聚类并在我认为它们不能反映我自己的估计(基于我多年的经验)的地方修改它们而告终。

我使用的最后一种分类方法是我自己创建的决策树,所有的玩家只通过几个节点进行分类,如下所示:

这是一个相当生硬的分类方案,毫无疑问,一些球员被错误分类,但它将满足这一分析。我想象如果我创造一个预测工具,它会给用户手动分类球员的选项,增加他们定义的准确性。

返工时间序列

现在我们有了分类,我们可以给每个游戏一个代表游戏中职业人数的分数。这可用于创建新的时间序列,娱乐和专业的每种组合都有一个时间序列(即专业与专业、专业与娱乐以及娱乐与娱乐)。

我们可以立即看到,我们之前注意到的 12 月流量的峰值是由职业玩家相互竞争的临时增加引起的。爆发了一场小战争,而且很短暂。我们看到,娱乐玩家几乎从不互相游戏;在时间序列的早期,rec vs rec 线异常高,这表明一些球员可能被错误分类(可能是那些寻求晋升的球员,他们在放弃之前没有参加 1000 场比赛)。

通过计算每个小时内独立职业玩家的数量,我们还可以得出每小时在线独立职业玩家的数量。下图是休闲交通时间序列。

玩的最好时间

因此,如果每个包含一个娱乐玩家的游戏是一条鱼,而每个在线职业玩家是一条鲨鱼,我们可以通过确定哪个小时每条鲨鱼产鱼最多(通过将娱乐游戏除以在线职业玩家)来计算出最佳游戏时间。

但是首先要对时间序列做一些改变。两个系列的可疑缺失值用一周中该小时的平均值填充。对于专业人士在线系列,每次观察都会增加一条,这改变了“专业人士在线一小时内钓到多少鱼?”的问题到“如果一个额外的职业选手也在那个小时打球,他们会得到多少鱼?”这更能代表与决定参与游戏相关的价值主张。

我们没有足够的年或月的数据来得出一年或一月中最好玩的时间的结论,但我们有足够的周数。下面是一周中每个小时每个职业球员的平均游戏次数(包括一个娱乐玩家)的图表(记住:0 =星期一,1 =星期二,等等)。

我们之前在“一周内每小时游戏计数”图中看到的每日季节性几乎完全消失了。专业人士的集体私利似乎在调节鲨鱼和鱼的比例,使其在工作日保持在 4 到 5 之间。虽然开始时我们看到工作日有更高的流量,但午夜后,周五和周六是最好的玩游戏的时间,周六和周日下午是最差的。

那么从这个分析中我们能给玩家什么建议呢?在一周中,你什么时候玩并不重要,你可以让生活的其他方面影响你的时间表,因为你不会错过任何额外的价值。是的,周五和周六晚上更适合玩,但这远远不是双倍时间——预计每小时玩的游戏会增加 25%左右。避开周六和周日下午。

对于有抱负的职业玩家来说,他们很想知道在这个买入级别玩游戏的价值。无论你在一周中的什么时候玩,期望你的平均回报是一样的。我们看到专业人士的投资回报率为 2–8%,因此买入费为 51 美元,每小时玩 4.6 场游戏(工作日),根据你的技能水平(买入费游戏次数投资回报率),预计每小时可赚 4.70 至 18.77 美元。

因此,我们有它,最好的时间玩,或者更确切地说,知识,除了几个时间在周末,没有任何调整可以对玩家的每周时间表,以提高他们的预期利润。

但是那些作息时间灵活的球员呢?可以即时决定是开始、继续还是停止播放。我们对这些球员有什么建议吗?我们知道,但我们将把这一点留到另一篇文章中,在那篇文章中,我将带您完成创建一个时间序列模型的过程,该模型可用于预测未来的鱼鲨比

注来自《走向数据科学》的编辑: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语

ONNX.js:浏览器中的通用深度学习模型

原文:https://towardsdatascience.com/onnx-js-universal-deep-learning-models-in-the-browser-fbd268c67513?source=collection_archive---------15-----------------------

通用开放标准深度学习格式介绍及其在浏览器中的使用(ONNX/ONNX.js)

Photo by Franck V. on Unsplash

在客户端浏览器上运行深度学习模型并不是什么新鲜事。2018 年初,谷歌发布了 TensorFlow.js,这是一个开源库,用于完全在浏览器中定义、训练和运行机器学习(ML)和深度学习(DL)模型,使用 Javascript 和高级 API。

2017 年 12 月,亚马逊脸书微软宣布了让开放神经网络交换 (ONNX)格式制作就绪的合作倡议。ONNX 现在可以支持许多顶级框架和运行时,包括 Caffe2、MATLAB、微软的认知工具包、Apache MXNet、PyTorch 和 NVIDIA 的 TensorRT。还有从 TensorFlow 和 CoreML 到 ONNX 的早期转换器,可以用到今天。

2018 年 11 月,ONNX.js 发布。ONNX.js 是一个开源的 Javascript 库,用于在浏览器和 Node.js(类似 TensorFlow.js)上运行 ONNX 模型。你可以使用它在浏览器上直接对预训练的 ONNX 模型进行评分。ONNX.js 也是第一个在基于 Javascript 的人工智能推理引擎(通过 Web Workers)中利用多线程的解决方案,与 CPU 上的任何现有解决方案相比,它提供了显著的性能改进。好消息,对吧?

ONNX 是什么,为什么这么酷?

当你开发一个机器学习或深度学习模型时,你通常会产生经过训练的模型工件,然后用于预测。该文件包含您花费数小时训练的神经网络参数和权重。每个平台通常有不同的输出格式。例如,MXNet CNN 模型保存在(。参数和。json)文件。这种格式只适用于 MXNet 运行时推理。ONNX 来解决这个问题。它使得深度学习模型可移植,你可以使用 MXNet、Caffe 或 PyTorch 开发一个模型,然后在不同的平台上使用它。例如,您可以使用 PyTorch 开发一个图像分类模型,然后将其部署到 iPhone 设备上,以使用 ONNX 格式的 CoreML。

为什么要在浏览器上进行深度学习?

在客户端设备(浏览器)上运行 DL 模型有一些重要的好处:

1-隐私:

如果 ML/DL 模型处理敏感和私有数据,并且您不想将数据发送到服务器进行推断,那么这将是一个很好的解决方案。

2-低延迟:

将模型直接放在客户端减少了客户端-服务器的通信开销。

3-跨平台:

你使用什么操作系统并不重要,因为它可以在浏览器上运行。也不需要安装任何库。

基准测试结果:

微软对 tensorflow.js 和 keras.js 库进行了一些基准测试,结果令人震惊。您可以看到 ONNX.js 可以快 8 倍以上:

https://github.com/Microsoft/onnxjs

现在,让我们看一些代码:

现在,让我们使用三个简单步骤中的预构建模型——Inception _ v2 来构建一个简单的图像分类器。你可以从 ONNX 模型动物园下载预先训练好的模型。

第一步是用 WebGL 或 WebAssembly 后端创建 ONNX 推理会话。在这个例子中,我将使用 WebGL 后端,然后我将使用session.loadModel()函数加载我刚刚下载的模型。

第二步是处理输入图像并调整其大小,然后使用onnx.Tensor()函数从输入图像中创建一个张量。

第三步是使用session.run()函数获得预测,并将输出转化为相关的类。

Code Snippet for using ONNX.js

你可以从这里获得完整的示例代码。这里还有一个为您尝试的所有演示部署的网站。

结论:

ONNX 是一种非常强大的开放标准格式,它使得模型工件可以在平台之间移植。你仍然可以使用你最喜欢的框架进行编码,然后发布你的结果,使它可以在任何使用 ONNX 格式的平台上工作。这是让机器和深度学习开发和推理民主化的一个非常好的方式。当然还有更多,但是希望本文中的信息可以作为对 ONNX 和 ONNX.js 的简短而有用的介绍。

ONNX —变得简单

原文:https://towardsdatascience.com/onnx-made-easy-957e60d16e94?source=collection_archive---------10-----------------------

如果你对当前人工智能技术领域中使 ONNX 成为必要的各种环境因素感到好奇,我在文章结尾提供了一个简洁的附录。现在,让我们直接关注这场秀的明星- Onnx

ONNX:那么,它到底是什么?

ONNX 是一种持久性格式。一种将生成的模型序列化为离散资产的方法,可以用代码对其进行存储、版本控制和控制。如果你看看幕后,你会发现 ONNX 已经得到了微软、脸书、英伟达以及其他公司的大力支持。所有将人工智能视为其业务核心的组织。考虑到这一点,你可能会开始想,是什么让 ONNX 如此特别?

互操作性:不同程序交换信息、共享文件和使用相同协议的能力。

这是一个简单的想法。这种想法在软件工程中已经存在了几十年(Java 的 JVM 是一个显著的例子),但在人工智能领域却一直没有出现,这是人工智能研究中所谓的“复制危机”的一个促成因素。

本质上,ONNX 解决这个问题的方法是,它保证在给定数据集的情况下,模型将始终保持其行为的确定性,其结果与运行时环境不变。

那么,这对我们意味着什么,为什么我们(作为数据科学家/人工智能工程师)要关心呢?

赞成者!

  • 您可以用一种编程语言创建一个模型,然后在一个完全不同的运行时环境中执行(例如,想象一下用 Python 创建您的模型,然后部署到一个 C#软件解决方案上)——太好了!😎
  • 你可以使用几乎任何人工智能工具来创建一个模型,ONNX 运行时会对它进行一般性的处理。这为您创建的任何模型提供了一个通用的、一致的界面👏
  • 使用 ONNX,您不需要打包用于创建模型的各种依赖项,您需要的只是 ONNX 运行时☺️
  • 它得到了几乎所有重要行业贡献者的广泛支持。它是开源的,并且会一直存在下去😍

在乌托邦世界里,ONNX 不会有任何问题。尽管该框架有崇高的理想和令人钦佩的目标,但我们需要解决一些问题。

不利因素。

  • ONNX 是新的。技术上的新奇常常暴露出日常使用中的不成熟。对于 ONNX 来说,这表现为一个笨拙的 API,并且缺乏在野外工作的范例实现。生产项目依赖于确定性和易用性😵
  • 文档是有限的。提出了一个丑陋的问题“如果出了问题怎么办?”这是一个可怕的风险,因为有记录的支持是随意的😰
  • 它直接支持将有限数量的库转换成 ONNX 格式😓
  • 存在(3…2…1 中的讽刺)缺乏例子。这使得采用成为一个挑战,除了最强壮和思想开放的团队🤯

在这篇文章中,我想把焦点放在第四个骗局上。为那些遇到和我一样的挑战的人提供希望的灯塔。对于你们每一个 ONNX 航海家,我希望这些例子将是你的灯塔。

ONNX —变得简单

首先,我们如何在我们的开发环境中安装 ONNX(本文不打算深入介绍安装,而是给你一个指南针)?你需要两样东西。

  1. ONNX
  2. ONNXMLTOOLS

幸运的是,安装说明分解为一个 pip 安装,说明被捕获在超链接的 GitHub 存储库中。所以,你现在有 ONNX 准备…嗯…那么,为什么有两个依赖项?这实际上可以归结为转换工具和 ONNX 本身的解耦。让这张方便的图表解释…

A tl;dr view on where the ‘ONNXMLTOOLS’ fit into the ONNX eco-system

有趣的事实:ONNX 官方支持的转换过程在编写时只支持几个库。例如,Sci-Kit Learn 有一个独立的 ONNX 转换工具(我们很快就会看到)。

现在已经澄清了(我希望!),让我们从 XGBoost 开始,探索几个展示模型到 ONNX 的转换的代码示例!

很简洁,你不同意吗?这个例子当然很简单,但是这个例子表明代码不动产与其他持久化方法非常相似。

然而,这仅仅考虑了保存模型,我们如何在 ONNX 运行时环境中打分?

这个例子也是用 Python 编写的,但是您可以使用任何与 ONNX 运行时环境兼容的编程语言。你可以想象,当将一个由人工智能驱动的功能集成到一个现有的项目中时,这将是非常强大的(拥有自己预先建立的技术栈)!

如何将“不支持的”库转换成 ONNX?

正如我们前面所讨论的,ONNX 的当前转换工具只支持一小部分可能的库,有一些重要的例外;如 Sci-kit Learn

ONNX 开源社区为此设计了一个特定的库(是的…另一个依赖项),称为‘sk learn-ONNX’。这个额外的转换器是 ONNX 开放课程生态系统中存在的几个转换器之一,每个转换器都反映了核心 ONNX 工具的现有标准(这是一个可取之处)。

关键时刻-对 code real estate 有什么影响吗?

长话短说…不。这是一个好的结果,它表明分裂的转换库严格遵循现有的 ONNX 转换 API——很好。

如果我想同时使用 SKLearn 和 XGboost 怎么办?

好问题!这是一个先前范例和支持文件都有限的领域。ONNX,由于运动几个分散的转换器经常感觉像编译不同的乐高积木。为了使 SKLearn 转换库支持 XGBoost,我们的目标是从核心 ONNX 工具注册 XGBoost。

让我们看看是什么代码启动了这个过程…

维奥拉。虽然同时利用每个转换库感觉很笨拙,但它是有效的。这证明了基本 ONNX API 的可扩展性和一致性。如果我在哪里阅读茶叶来预测 ONNX 的未来,这个核心原则是一个让我对未来更统一的工具集抱有希望的原则。

我喜欢 ONNX。它试图满足人工智能社区的真正需求,努力确保我们构建的模型的神圣性。这对于减少构建人工智能驱动的软件解决方案和人工智能增强的软件解决方案的摩擦至关重要。

对于 AI 社区中的那些人来说,我们应该在 ONNX 发展的幼虫阶段支持它。ONNX 来了。让我们拥抱它。

所以你可能会想,是什么让我们来到这里?导致 ONNX 产生的因素是什么?我在下面加了一个简短的补充,涵盖了我对这个话题的思考。

因果——为什么 ONNX 是必需品?

现代人工智能领域是一个丰富的、不断变化的工具和技术的织锦。过去的五年包含了我所说的现代人工智能复兴,它以三种不同的方式表现出来:

  • 在人工智能的直接垂直领域和更广泛的数据科学技能组合方面,教育都取得了重大进展。
  • 人工智能欣赏已经渗透到科技世界的日常词汇中。它成为我们腰带上的另一个工具。
  • 工装的成熟度;这已经建立了当前的“三层”抽象模型(例如,从云认知服务、 Sagemaker 及其同类到全脂肪、低级端到端框架,如 Tensorflow )。

本文主要关注第三点的后果。当然,工具已经以一种净积极的方式成熟了,但是(是的,有一个但是…)工具的开发一直是混乱和分散的。

在短短 10 分钟内(我自己计时),我数了 24(!)独特的人工智能聚焦库&平台。每一个都提供非常相似的广泛功能,但是标准、API 和持久格式却大相径庭。

这是怎么发生的?

  • 竞争力……大型科技公司有一种与生俱来的竞争欲望。
  • 在当今世界,人工智能的编程语言之间并不存在对等性。通常情况下,功能会在 Python、R、C#以及更高版本中被复制……只是在不同的库中。

这对每个工具生成的模型如何被持久化产生了非常有针对性的影响。有两种选择浮出水面。

  1. 完全依赖于专有工具/格式(或供应商!).
  2. 使用通用的序列化格式,如泡菜(其中有一些关于方面的。)和 JobLib 是当今部署人工智能模型的常用方法。由于它的易用性,我已经在各种项目中使用过。

与所有混乱的环境一样,标准化和领导力也存在机会—2017 年,ONNX 加入了竞争。

其余的,正如他们所说,都是历史了。

向前和向上:寻找一艘火箭船和一个收购故事

原文:https://towardsdatascience.com/onwards-and-upwards-finding-a-rocket-ship-and-an-acquisition-story-2464a15ca713?source=collection_archive---------26-----------------------

一年前,我写了几篇关于我们的 YCombinator 体验的帖子,得到了很多关注。你们中的许多人在 YC 进程中向我寻求帮助;有些人成功了,而很多人没有。无论如何,我希望那些没有通过的人学会如何逆来顺受。这部分是我们收购故事的延伸版本。我再次希望这能帮助任何正在经历类似事情的人。

[## YCombinator 应用程序或我们如何几乎做到这一点—第 2 部分(共 2 部分)

在这篇文章的第一部分(你可以在这里阅读),我解释了 Y Combinator 应用程序是如何处理

towardsdatascience.com](/the-ycombinator-application-procedure-or-how-we-almost-made-it-part-2-of-2-1ac37b002fcd)

..即使是我们最老、最忠实的客户也不会超过 10 万美元。那是一个很大的心理打击。

如果你看了前面的部分,你会知道我们认真对待 YC 的反馈,并开始致力于缩短我们的销售周期。然而,即使经过一年的努力,我们也无法缩短新企业客户的销售周期。我们还达到了年度合同价值的全球最高值,即使是我们最老、最忠诚的客户也不会超过 10 万美元。那是一个很大的心理打击。

我们稍微转向关注基于互联网的创业公司,即全球的优步和 Zoomcar。我们在这方面取得了一些进展,销售周期缩短了,但购买力却下降了很多。这个国家只有少数超级投资的创业公司有闲钱挥霍在安全相关的数据科学上。更重要的是,每当我们与一家新的创业公司交谈时,他们都会说,由于洞察力的敏感性,这种分析必须在内部进行;他们会强烈暗示收购我们。

低调,因为没有买家会直截了当地说“我们想收购你的公司”

一段时间后,低调向我们提出收购的初创公司数量超过了我们融资渠道中的投资者数量(永远是融资)。低调是因为没有买家会直截了当地说出“我们想收购你的公司”这样的话。因为那就等于失败。每个人都喜欢玩一个猫捉老鼠的游戏,通过他们的关系网了解你是否在考虑收购;然后试图让你向他们承认这一点。当你这样做时,他们必须支付更少的费用,因为“你比我们更想要”。

如果一家公司拒绝遵守这些基本原则中的任何一条,这就是一个危险信号,我们可以拔掉插头

收购谈判进行了几周后,我们与我们的主要投资者,来自 thinQbate 的 Pranav,来自 Astarc Ventures 的 Hari 和 Artha Ventures 的 ad 进行了会谈。我们进行了一次长谈,坦率地说深入到了灵魂探索。我们问自己什么是最好的行动方案,在这个时候被收购是否是我们能做的最好的事情。

我们最终确定了一些原则来帮助我们做出这个决定:

  • 我们会要求收购方公平对待:我们的客户,我们的股东(包括我们的创始人),以及我们的团队——按此顺序
  • 我们会寻找最可靠、最诚实的人,他们会了解我们的背景,我们可以在未来的岁月里依靠他们
  • 我们只会挑选一个让我们兴奋的想法/领域/问题陈述
  • 我们会寻找一种文化上的契合,这样两个团队就可以无缝地融合在一起,几乎没有摩擦
  • 我们将能够通过收购公司实现我们的抱负——将 Vahan 堆栈扩展到一个更大的规模,并拥有许多更大的问题陈述来进行工作和个人成长

事后看来,制定这些原则有助于我们在面对困难局面时进行谈判并依靠它们。如果一家公司拒绝遵守这些基本原则中的任何一条,这就是一个危险信号,我们可以终止合作。

我们有过几次千钧一发的机会,我们深入讨论了一些大型、成熟的初创公司的条款,但谢天谢地,什么都没有实现。

不过,最终我们的对话渠道形成了这样的形式:10 次讨论-> 5 次谈判-> 3 次具体报价(从收购股东,到在不向投资者支付任何费用的情况下收购)。这与融资略有不同,在融资中,从讨论到条款清单(理解为:谈判)的转换要低得多。然而,就投资者而言,漏斗的顶端更宽。

于是我们有了三个具体的提议。第一个是一家资金雄厚、外表光鲜的 B2B 初创公司,由一位杰出的连续创业者创建。他们和我们在同一个技术领域,可以直接利用我们现有的技术和知识产权。第二次是在稍早的阶段,发展很快,是在向与我们相同的行业销售软件的业务领域:直接契合。最后,第三个报价来自 Rapido。Rapido 属于消费者应用领域,对我们来说,它更像是一个理想的客户,而不是商业伙伴。然而,经过漫长而勤奋的自我反省和数据处理过程(是的!),我们决定用 Rapido。这是如何发生的:

早在 2016 年,我们就通过一位共同投资者被介绍给了 Rapido 的创始人,顺便说一下,他们是我们的第一批试点合作伙伴。由于他们的应用程序和我们的数据收集 SDK 都过于原始和不兼容,这个试点项目很快就失败了。然而,从那以后我们一直保持联系。他们经历了一段漫长而艰难的时期,在此期间,他们稳步增长,但并不引人注目。当我们这一次遇到他们的时候,他们正在进行 A 轮融资,并对即将到来的 B 轮融资充满信心。我们有所怀疑,因为这个想法似乎总是很不直观;即使是在蓬勃发展的城市交通领域。

他们热衷于安全方面。我们很高兴听到这个消息。

我们的愿景从一开始就是让司机更好,让道路更安全。通过我们的企业客户和他们的网络,我们接触到了相当数量的车辆。然而,一直困扰我们的是,我们要让臭名昭著的印度道路变得更安全,相反,我们最终卖给了 1%的人。有了 Rapido,从一开始就很明显的一点是,我们将能够接触到大量的司机和车辆。可以这样想:Ola 或优步最近一次统计显示,在任何一天都有 800,000 名司机生活在他们的平台上。还有哪家公司能声称一天有这么多车辆上路?

那时我们意识到这可能是一艘火箭飞船,正在上升。我们想在它进入轨道前登上飞船!

唯一的问题是 Rapido 是否能达到那样的高度。作为数据科学家,我们习惯于依靠底层数据来做任何决定。我们与他们达成了一项协议,他们将支付我们 2 个月的合同工作,我们为他们解决一个数据科学问题。问题陈述:需求预测

我们花了 2 个月的时间来完成这项工作,Rapido 与我们分享了 1 年的需求和交易数据。在研究了几个时间序列和预测模型(关于 SARIMA 和 Prophet)的几周内,我们发现了一些惊人的东西:

The famed Hockey Stick, in person!

当通过任何预测模型时,月度总量形成了一条曲棍球棒曲线。

Source: https://davidcummings.org/2010/12/19/hockey-stick-growth-for-startups/

那时我们意识到这可能是一艘火箭飞船,正在上升。我们想在它进入轨道前登上飞船!

一旦我们深信不疑,说服我们的股东就变得简单了。他们上船后,事情进展得很快。Rapido 提出以部分现金、部分股票的方式收购我们的股东。估值不高,肯定不是风投们等待的那种超大回报。然而,每个人都对几年后的增长潜力和令人满意的结果感到非常兴奋。所以我们为我们的股东进行了全股票交易。在 3 个多星期内,我们已经解决了所有的条款,并准备加入!

[## 自行车出租车公司 Rapido acqui-hires 分析初创公司 Vahanalytics

孟加拉鲁:自行车打车应用 Rapido 已经收购了总部位于孟买的 Vahanalytics,这是一家数据分析初创公司,允许…

www.livemint.com](https://www.livemint.com/companies/start-ups/rapido-acqui-hires-mumbai-based-vahanalytics-in-cash-and-stock-deal-1566217428592.html)

就我们的原则而言,这笔交易符合大多数条件。我们唯一感到有点内疚的地方是我们的团队成员。我们必须把基地从孟买搬到班加罗尔,不是每个人都能做到的。但令人高兴的是,大家都在短时间内被安排到了一家不错的公司。

这就是我和我的团队如何成为 Rapido 的一部分。

我们的任务:建立 Rapido 的数据科学和工程团队,做一切与数据科学相关的事情。我将在下一篇文章中讨论如何为一家高速增长的初创公司做到这一点。

OpenAI 健身房经典控制问题的奖励工程|DQN |RL

原文:https://towardsdatascience.com/open-ai-gym-classic-control-problems-rl-dqn-reward-functions-16a1bc2b007?source=collection_archive---------15-----------------------

自定义奖励功能,加快学习速度!

我通过尝试在 OpenAI 健身房解决问题开始学习强化学习。我特别选择了经典控制问题,因为它们是力学和强化学习的结合。在这篇文章中,我将使用深度 Q 网络(DQN)展示选择一个合适的奖励函数如何导致更快的学习。

1。扁担

Episode 40 (unbalanced)

Episode 60 (balanced)

这是 OpenAI 健身房上最简单的经典控制题。极点保持平衡的每个时间步长的默认奖励值是 1。我将这个默认奖励改为与磁极角度绝对值的减少成比例的值,这样,它会因为使磁极更接近平衡位置的动作而得到奖励。具有 2 个隐藏层的神经网络,每个隐藏层具有 24 个节点,在 50 集内解决了这个问题。

**#Code Snippet, the reward function is the decrease in pole angle**
def train_dqn(episode):
    global env
    loss = []
    agent = DQN(2, env.observation_space.shape[0])
    for e in range(episode):
        temp=[]
        state = env.reset()
        state = np.reshape(state, (1, 4))
        score = 0
        maxp = -1.2
        max_steps = 1000
        for i in range(max_steps):
            env.render()
            action = agent.act(state)
            next_state, reward, done, _ = env.step(action)
            next_state = np.reshape(next_state, (1, 4)) 
            ***#Customised reward function***                        
            reward = -100*(abs(next_state[0,2]) - abs(state[0,2])) 
            agent.remember(state, action, reward, next_state, done)
            state = next_state
            score=score+1
            agent.replay()

在这里找到完整的代码。

Time steps for which the pole stayed balanced in different episodes

2。山地车

Episode 2

Episode 200

这里的目标是到达正确的山顶,汽车将不得不来回到达正确的山顶。为了让网络自己想出这个策略,需要为它提供一个适当的奖励函数。在某些情节中,一旦汽车通过试错法到达目的地,简单地给予积极的奖励,而对所有其他时间步骤给予消极的奖励是行不通的,并且在网络学习最佳策略之前需要相当长的时间。

为了从谷底到达顶峰,汽车需要获得机械能,因此最佳策略是汽车在每个时间步获得机械能(势能+动能)。所以一个好的回报函数应该是,在每一个时间步,机械能的增加。

**#Code Snippet, the reward function is the increase in mechanical energy
def** train_dqn(episode):
    **global** env
    loss = []
    agent = DQN(3, env.observation_space.shape[0])
    **for** e **in** range(episode):
        state = env.reset()
        state = np.reshape(state, (1, 2))
        score = 0
        max_steps = 1000
        **for** i **in** range(max_steps):
            env.render()
            action = agent.act(state)
            next_state, reward, done, _ = env.step(action)
            next_state = np.reshape(next_state, (1, 2))
            ***#Customised reward function*** reward = 100*((math.sin(3*next_state[0,0]) * 0.0025 + 0.5 * next_state[0,1] * next_state[0,1]) - (math.sin(3*state[0,0]) * 0.0025 + 0.5 * state[0,1] * state[0,1])) 
            agent.remember(state, action, reward, next_state, done)
            state = next_state
            agent.replay() 

在这里找到完整的代码。

有了这个奖励函数,网络可以很快地学习到最佳策略。

TIme steps taken by the car to reach the flag at different episodes.

3.钟摆

Performance of the RL Agent at different episodes (From left: episode 6, episode 40, episode 200)

在这个问题中,我需要摆动一个钟摆,并使用顺时针或逆时针方向的扭矩使它保持平衡。这个问题类似于山地车问题,但是当杆到达倒置位置时,保持杆平衡有额外的困难。
最初,杆的机械能需要增加,但是一旦它获得足够的能量到达倒置位置,任何更多的能量增加将迫使摆锤保持旋转。

最佳策略是以这样一种方式提供扭矩,即不断增加摆的机械能至极限 mg1/2,该极限等于倒立摆的势能。这将确保钟摆到达倒置位置。除此之外,为了保持极点的平衡,应该对倒立位置附近的钟摆位置给予正奖励。

**#Snippet of the code, the reward function is the increase in mechanical energy of the pendulum upto a limit of 5 with an added positive reward for positions close to the inverted pendulum.
for** e **in** range(episode):
        temp=[]
        state = env.reset()
        state = np.reshape(state, (1, 3))
        score = 0
        maxp = -1.2
        max_steps = 1000
        **for** i **in** range(max_steps):
            env.render()
            action = agent.act(state)
            torque = [-2+action]
            next_state, reward, done, _ = env.step(torque)
            next_state = np.reshape(next_state, (1, 3))
            **if** (next_state[0,0]>0.95):
                score=score+1
            ***#Customised reward function***
            reward= 25*np.exp(-1*(next_state[0,0]-1)*   (next_state[0,0]-1)/0.001)-100*np.abs(10*0.5 - (10*0.5*next_state[0,0] + 0.5*0.3333*next_state[0,2] * next_state[0,2])) + 100*np.abs(10*0.5 - (10*0.5*state[0,0] + 0.5*0.3333*state[0,2] * state[0,2]))
            maxp = max(maxp, next_state[0,0])
            temp.append(next_state[0,0])
            agent.remember(state, action, reward, next_state, done)
            state = next_state
            agent.replay()

在此找到完整的代码

下图显示了在不同事件的 200 个时间步中,钟摆在倒置位置保持平衡的时间。

Time spent in the inverted position for different episodes

结论

强化学习是机器学习以最优方式执行任务或实现目标的过程。关于手头问题的人类直觉可以以设计的奖励函数的形式添加到神经网络算法中。我们考虑的问题中的默认奖励函数是粗糙的,只在完成任务时奖励代理,这使得 RL 代理很难学习。设计的奖励功能使训练过程更快、更直观,便于我们理解。
阅读更多博客这里

开放银行:它是什么,不是什么,为什么重要

原文:https://towardsdatascience.com/open-banking-what-it-is-what-it-isnt-why-it-matters-e4502af143cb?source=collection_archive---------41-----------------------

在对个人数据隐私和数字伦理的担忧中,一种名为“开放银行的东西的发展似乎是朝着错误的方向迈出了一步。

但是……事实是,开放的银行业务和总体开放的框架不仅将传统组织带入 21 世纪,而且是改善客户服务、推动创新和为新的颠覆性商业模式奠定基础的关键。

随着人们对开放银行业的热情日益高涨,组织和个人需要迅速行动起来,在新的竞争格局中占据有利位置。

从高层次来说,开放银行业务是一项指令,要求银行向其客户提供与第三方机构共享其财务信息的选项,以换取改进的服务和定制解决方案。虽然主要集中在欧洲,但该指令在各地正处于不同的发展阶段。

如果这听起来很激进,的确如此。

仅次于健康,财务数据通常需要最高级别的安全性;由严格的规章制度保证的安全。从表面上看,这是一件好事。没有人希望自己的银行信息可以自由获取。

但是,尽管开放银行业的想法似乎与传统智慧相反,但认为开放银行业是你信用历史上的开放季节是错误的。如果操作得当,开放式银行业务有能力通过增强的“了解你的客户”能力和欺诈检测来提高安全性。

这可能有助于解释为什么银行越来越多地参与进来。为了理解其中的原因,有必要在消费者数据权利(CDR)和开放创新趋势的大背景下思考开放银行业务。从本质上讲,CDR 计划旨在让客户更好地控制他们的数据,使他们能够与他们选择的接收者共享数据,并用于他们授权的目的。

另一方面,开放式创新抓住了信息时代的精髓:脱离组织间的筒仓思维和秘密。

虽然开放银行的想法可能看起来像是在鼓圈里偶然听到的,但事实是,它代表了我们对数据所有权的看法的巨大变化。

适时给予的应得的赞扬

Source: McKinsey Payment Practice

现在判断这种思维的改变对普通客户的银行体验意味着什么还为时过早,但在这个早期阶段,我们已经看到第三方开发人员利用开放数据源来创建增强银行体验的应用程序和服务。

其中,正在开发两种类型的服务:

  1. 账户信息服务
  2. 支付启动服务

账户信息服务

根据英国金融行为监管局(Financial Conduct Authority)的规定,账户信息服务是“一种在线服务,向支付服务提供商提供支付服务用户持有的支付账户的综合信息。”

这实际上意味着客户可以选择允许第三方访问他们的银行信息。概括地说,这意味着您可以使用一个应用程序来查看您的所有银行信息,而不管您使用多少家金融机构。

但这也为人工智能工具和机器学习提供了一个机会,根据你的支出为你提供更好的价格和服务。

被你的手机供应商骗了?
账户信息服务可以让你确切地知道从竞争对手那里获得同样的方案会节省多少钱。

每月花 200 美元买咖啡?它会给你一个通知,告诉你如果你把钱放进 RRSP,五年后会是什么样子。

最终,账户信息服务可以为你的支出注入高功率人工智能。像Mint.com个人资本YNAB 这样的提供商在过去几年里已经成为管理个人财务的便捷(和颠覆性)应用。

支付启动服务

另一方面,支付启动服务仍然是一项进行中的工作。

金融行为监管局将其统称为“一种在线服务,它访问用户的支付账户,在用户同意和验证的情况下代表他们启动资金转移。”

对银行客户承诺的好处是通过重定向交易以避开电子银行系统来降低费用。简单地说,支付发起提供商是借记卡和信用卡的电子商务替代品。总部设在立陶宛的 Paysera 公司通过对在线金融交易收取低得多的费用来为他们的用户省钱。

寄希望于变革

当然,问题在于,数字对我们金融生活的入侵仍在敲响警钟。2018 年,向美国卫生与公众服务部报告了 351 起医疗违规,超过 1300 万份患者记录在此过程中暴露。 剑桥分析公司丑闻 ,收集了 8700 万脸书用户的数据,对于那些认为他们的数字存在处于锁定状态的人来说,这是一个突然的觉醒。

事实是,技术创新的速度超过了立法者,而作为一个社会,我们还没有为个人数据保护建立明确的规则(尽管 GDPR的建立是个好兆头)。银行将不得不从安全角度出发,或者通过提供数据的服务来获取利益。

他们最好快点做。

开放的银行业务正在发生,那些做得最好的银行,凭借铁一般的安全性和强大的 API 网络,将垄断市场。

当涉及到金融数据时,风险就更高了。

毕竟这是我们的钱。

但事实是,任何一家头脑正常的金融机构都不会采取一种为欺诈敞开大门的做法,不管名义上的好处有多么诱人。如果做得好,开放银行业务实际上将为银行提供一个减少欺诈、更好地了解客户、释放前所未有的竞争和创新的机会。对于他们的客户来说,这将把 AI 注入到他们的日常生活中。

有了这样的好处,从银行到创新者的数据需要尽可能简化。

ThinkData Works 正在连接成千上万的公共数据源,并与公司和金融机构合作,将数据转化为可操作的见解,帮助监管合规性,改善信息收集,并打开新信息的大门。如果您想了解更多关于我们如何准备开放银行业务的信息,请 联系我们

原载于【https://blog.thinkdataworks.com****

通过开放数据改进机器学习

原文:https://towardsdatascience.com/open-data-for-machine-learning-b5c6ef3f5a80?source=collection_archive---------27-----------------------

公开数据被政府和机构广泛认为是一种透明和问责的做法。在这篇文章中,我们概述了为什么开放数据可以释放实际机器学习应用程序的潜力。

Taiwan is first ranked in the global Open Data Index (link: https://index.okfn.org/place/)

P2P 基金会将开放数据定义为一种理念和实践,要求每个人都可以免费获得某些数据,不受版权限制。专利或其他控制机制[2]。

近年来,作为透明度的一种实践,政府和市议会创建了开放的数据门户,当局将大量数据免费提供给公民。像巴塞罗纳( OpenDataBcn )、巴黎( open data Paris )、罗马( dati comune )或柏林(d aten.berlin )这样的城市都有一个开放的数据门户,将粒度改为国家几乎世界上每个国家都有一个门户:法国( data.gouv.fr )、马拉西亚(data.gov.my)或哥斯达黎加( datosabiertos.presidencia)

如今,很容易找到几乎所有东西的数据集,只需点击几下鼠标,你就能找到,例如与领土(城市停车位)、人口(教育水平)、治理(选举结果)相关的数据集...伦理运动带来的开放数据的好处主要集中在为居民提供数据,以某种方式为自己谋利。在文章《开放政府数据的 5 大好处》[3]中我们发现:

  • 1.增加透明度和问责制
  • 2.培养信任、可信度和声誉
  • 3.促进进步和创新
  • 4.鼓励公众教育和社区参与
  • 5.随着时间的推移存储和保存信息

如前所述,开放数据可以释放机器学习的潜力。原因很简单,纳入外部数据有助于增强模型、发现新模式和解决奇偶校验等问题。

Figure 1: Open Data in ML model

  • *公司数据:这就是我对项目所拥有的数据的看法:如客户、消费…

为了将开放数据变量包含到 ML 算法中,我们需要在原始数据和分类器的输入之间包含一个代理。这个代理负责转换和对齐数据。

数据必须具有相同的粒度,所有维度必须具有相同的周期。如果我们预测每月天气,开放数据维度也需要以月为单位。否则,它会导致模型中的偏差。这两个信息来源需要归一化(重新标度、均值归一化或标准化是常用的技术),当然是在同一个单位中,而不是试图建立一个混合公里和英里数据的模型。

保持尺寸比例的不平衡也很重要。在大多数情况下,公司维度的数量需要大于开放数据维度。原因很简单,我们预测的是股票市场,1 个变量是股票的历史价值(公司数据),其他 100 个变量来自公开数据(国家的 GPD、教育水平或经济活动类型)。在这种情况下,大多数预测将仅使用开放数据维度构建,而不使用公司数据。因此,必须增加尺寸的重量或限制其作为辅助尺寸的使用。

最后,实际的开放数据门户有被第三方采用的障碍,政府不应该仅仅局限于发布数据。为了能够重用这些有价值的信息,需要确保以下特性:

标准文件格式,数据以不同的文件格式共享(甚至你可以在 pdf 的文件中找到)。门户网站应该建立一个标准,并以相同的格式共享所有文件(json 和 csv 是首选)。

元数据,所有数据集后面都必须有每个变量的描述(如果是表格数据行信息)。一个很好的实践是使用 RDF,这是一个由万维网联盟(W3C)创建的标准,它具有促进数据合并和支持模式随时间演变的特性[5]

数据的周期性和一致性,数据应该定期更新并保持历史。同样,必须通知用户数据的新版本。数据还必须随时间保持一致,数据的标识符不能随时间改变。

API 访问(应用编程接口),访问和下载门户的数据是一项成本高昂的活动,为此,他们必须启用 API 来自动升级数据

综上所述,开放数据可以在人工智能项目中释放新的潜力,并作为奇偶校验帮助解决问题。此外,这种结合不是一件小事,开放数据网站需要确保数据的可重用性,ML 工程师需要知道如何融合这些知识。

参考

[1] AI 和开放数据:至关重要的组合https://www . europeandataportal . eu/en/highlights/AI-and-Open-Data-critical-combination

[2]为一个勇敢的新世界开放治国之道

[3] 5 开放政府数据的好处https://www . envisio . com/blog/5-开放政府数据的好处

[4]开放数据和开放政府的好处、采用障碍和神话https://www . semantic scholar . org/paper/Benefits % 2C-采用障碍和神话-开放数据-让桑-charabidis/4b 606805 da 01 c 61 e 4422 FD 90 Fe 33877 a6d 71951 c

[5]资源描述框架(RDF)https://www.w3.org/RDF/

开放的人工智能:通过保留所有选项来提高性能

原文:https://towardsdatascience.com/open-minded-ai-improving-performance-by-keeping-all-options-on-the-table-ddefce50913a?source=collection_archive---------10-----------------------

我是如何让我的强化学习代理在获得最高奖励后不再天真地表现得更好的

在媒体上阅读此文,而不是使用此 好友链接的媒体会员!

本帖描述的井字游戏,以及所有的算法和预训练的模型都可以在 [tic_tac_toe](https://github.com/shakedzy/tic_tac_toe) 资源库上 我的 GitHub 页面 找到。

当我被要求描述强化学习让我如此着迷的原因时,我通常会解释说,我认为我训练电脑的方式就像我训练我的狗一样——只使用奖励。我的狗学会了坐下、等待、过来、站立、躺下和假装被枪击(向我的妻子致敬),所有这些都以完全相同的方式——每次她做了我让她做的事情,我都会奖励她。每次我们试图教她一些新东西时,她都不知道我们想从她那里得到什么,但是经过足够的反复试验和一些成功的尝试后,她明白了。当强化学习模型被教授新东西时,完全相同的事情也会发生。这真是太棒了。

Gin the dog. Yes, we named her after a hard-liquor

追求最大可能的回报是几乎所有强化学习模型背后的基本引擎——每种模型都有自己的方法来实现它。但是当从更高的角度审视这种方法时,天真地追求回报是非常狭隘的。遵循这样的策略将使我们无法快速适应意想不到的变化,因为我们从不保留 b 计划。我们的整个探索阶段只是为了找到可能的最佳方式,而很少关注其他好的选择。我们能教我们的模特打开思维吗?我们应该吗?

最大化熵而不是回报

不久前,我偶然发现了伯克利人工智能研究中心这篇博文(它非常简要地总结了这篇论文),它提出了一种新的学习方法——不要学习提供最高回报的路径,而是跟随提供最积极选项的路径。换句话说,教你的模型增加它的动作——选择

这里有一个例子:让我们考虑一个简单的 Q-Learning 算法,并检查以下场景:

假设我们站在状态 s 中,可以从两个动作中选择一个:动作 X 和动作 Y 。从那里我们将到达状态s’,在那里将有三种可能的选择: 123 ,这将把我们带到终端状态,我们将收到奖励。我们看到,如果我们在选择 X 后站在s’,我们的策略将是无论如何都选择行动 2 。另一方面,如果我们在选择 Y 后到达s’,我们可以更灵活一点——尽管动作 2 仍然是最好的。换句话说,该策略在 X 之后的s’非常低——因为它只关注单个动作,而在 Y 之后则更高——因为它能够以合理的概率尝试所有状态。

但何必呢?从图中可以清楚地看出,最佳选项将是从状态s’开始的动作 2 。没错——但是如果环境突然发生变化,会发生什么呢?一个 bug,一个修改,或者对手一个意想不到的动作?如果这样的改变会突然阻止我们采取行动 2 ,那么行动 X 就变成了错误的决定。

但这不仅仅是妄想。就在几行之前,我们同意在选择动作 Y 之后,我们可以在下一个动作选择中更加灵活。虽然仍然有最佳选项,但其他选项也不会太离谱,这可以让模型更多地探索这些其他行为,因为不选择最佳选项的代价很低。在选择动作 X、之后,情况就不一样了,我们知道,充分的探索对于一个健壮的强化学习代理来说是至关重要的。

让我们谈生意吧

如何设计一个鼓励代理人最大化熵的通用策略在我上面链接的论文中有介绍。在这里,我想把重点放在软贝尔曼方程(在我提到的博客中讨论过)。让我们首先用常规的贝尔曼方程来回忆一下:

The Bellman Equation

软贝尔曼方程将试图最大化熵而不是未来的回报。因此,它应该用熵最大化项来代替最后一项,在最后一项中,我们将未来的 Q 值最大化。因此,在有限数量的动作的情况下,软贝尔曼方程是:

The Soft Bellman Equation

如果你想看看这个新术语如何与熵相关的数学证明,博客作者声称可以在 Brian Ziebart 的这篇 236 页的博士论文中找到。如果你上过一次热力学课,你可以回忆一下,气体的热力学熵定义为 s=k⋅lnω,其中平衡态的组态数是,其中平衡态的组态数是。如果你不知道你刚刚读了什么,你只能相信我(或者读论文)。

有用吗?

如果你已经读过我的一些博客,你可能已经注意到我喜欢自己测试一些东西,这次也不例外。我曾经写过一篇关于我用深度 Q 网络训练的一个井字游戏代理人的文章,所以我决定编辑它,让它也用软贝尔曼方程学习。然后我训练了两个代理:一个普通的 Q-网络代理和一个最大熵 Q-网络代理。我训练两个这样的代理人互相对抗,然后另外两个代理人分别对抗一个外部玩家——重复这个过程 3 次,最后每种类型有 6 个不同的训练模型。然后,我将所有常规 Q 网络代理与所有最大熵 Q 网络代理进行匹配,以查看哪种类型的代理赢得最多游戏。我还强迫代理们在每场游戏中选择不同的第一步棋(以涵盖所有可能的游戏选项),并确保他们都能玩到 XO

结果非常清楚:在 648 场比赛中,软贝尔曼代理人赢得了 36.1%的比赛(234 场),33.5%的比赛以平局告终(217 场),只有 30.4%的比赛(197 场)由正规 Q 网代理人赢得。当只考虑在没有我强迫代理人做出特定的第一个动作,而是让他们随心所欲地玩的情况下玩的游戏时,结果甚至更有利于软贝尔曼代理人:在玩的 72 场游戏中,40.3% (29 场)由最大熵 Q 网络赢得,33.3% (24 场)由常规代理人赢得,其余 26.4% (19 场)没有赢家。我鼓励你自己也进行这个实验!

最后的话

这个实验表明,在学习复杂系统,甚至不那么复杂的系统时,追求更广泛的目标而不是最高的回报是非常有益的。在我看来,教授一个模型如此广泛的政策,就好像我们不再把代理人当作我们希望训练的宠物——而是我们试图教的人。我很高兴看到未来我们还能教给它什么!

公开问题:卡洛斯·戈麦斯·乌里韦

原文:https://towardsdatascience.com/open-questions-carlos-a-gomez-uribe-980c1af1195c?source=collection_archive---------27-----------------------

Illustrations by Alfonso de Anda

尼克·洛克威尔和克里斯·维金斯

这个帖子也出现在 次开

Carlos A. Gomez-Uribe 是网飞公司前产品创新副总裁,在那里他负责电影推荐和搜索的算法开发。《纽约时报》首席技术官尼克·洛克威尔和首席数据科学家克里斯·维金斯向戈麦斯·乌里韦讲述了他的职业生涯,机器学习在网飞的发展,以及公司应该如何非常周到地考虑如何将机器学习集成到产品中。以下是经过编辑和压缩的。

问:你是如何进入网飞的产品部门工作的?你认为从事推荐工作的产品经理拥有数学技能重要吗?

A.我在网飞开始时是一名数据科学家,在这家仍然很小的公司里参与了很多项目。然而,在与负责推荐算法的工程和产品团队交谈后,我对这个特定领域产生了浓厚的兴趣。网飞正在计划一个基于流媒体的全球产品,推荐算法还比较基础;它主要利用通过邮件发送的 DVD 产品提供的信息进行了优化。

我提出了许多基于流数据学习统计模型的想法,以改进推荐,我向产品团队提出了这些想法。他们是开放的,对模型感兴趣,但对涉及的定量方法感到不舒服,无法决定赞助任何一个模型。谢天谢地,我当时的老板 Chris Pouliot 支持这些想法(尽管持怀疑态度),并给了我几周时间将其中一个开发成离线原型。原型产生的建议看起来很有趣,一旦我们把它们展示给产品团队,他们就会赞助这个项目。我们与工程和其他团队合作,全面开发和测试它,并根据结果部署它。

这一成功促使产品团队邀请我参与其他与推荐相关的项目。在其中的一次过程中,我开始相信让那些对定量方法不太了解的人——在这种情况下是产品经理——管理整个创新过程是次优的。所以我把这个批评传达给了产品团队。

令我惊喜的是,在思考了几天之后,他们的反应是同意让产品经理拥有深刻而广泛的量化经验将是一件有趣的实验,并创造了一个新的职位来尝试这个想法。更令人惊讶的是:他们让我去面试新职位。所以我转到了产品创新团队。结果相当不错,于是我被要求建立一个拥有强大定量背景的产品经理团队,来管理网飞的推荐和搜索创新流程。

为这个团队寻找合适的人需要时间,但这种努力是值得的,因为他们能够更好地领导跨职能团队,为网飞流媒体构建全球推荐和搜索技术。这种经历与我在其他公司看到的形成鲜明对比,我仍然相信,管理创新过程的强量化产品领导者是创造高质量算法产品的唯一途径。

你在网飞呆了七年;在这段时间里,你看到机器学习的使用方式发生了哪些变化?

它变得更加复杂。我们从几个相对简单的视频排名时间序列或回归模型开始,随着时间的推移,我们发现了更重要的用例,如推荐页面的构建或选择正确的图像来支持推荐。与此同时,我们发现各种更复杂的模型,经过适当的调整和使用,可以提供更好的体验。

将产品体验的关键部分委托给机器学习可能很难,但只在产品的边缘部分部署机器学习保证了有限的影响和有限的学习。你如何看待对产品有影响的方面进行信任机器学习的信念飞跃?

我认为你永远不应该盲目地相信一个机器学习系统会比一个替代品(比如手动治疗)表现得更好,直到事实证明并非如此。即使在获得这样的证明之后,机器学习系统也需要不断的监控,以确保整个系统或产品在周围世界发生变化时继续表现良好——以与您组织的使命相一致的方式。

重点是阐明你预计机器学习将如何改善产品或体验,然后投资于研究和开发,以探索这一假设。只有通过旨在理解变化的全部含义的仔细测试和分析,你才应该切换到基于机器学习的产品。这个过程既漫长又昂贵,只在产品的一小部分上尝试是没有意义的,因为即使在最好的情况下,对企业和使用你产品的人的回报也是很小的。

去年夏天,莫妮卡·罗加蒂写了一篇名为《》的伟大作品,并提出,“在有效利用人工智能和机器学习之前,你需要为你的数据打下坚实的基础。”然而,有时通过机器学习获得的酷结果可以引发公司需要的那种改进,以从公司的数据中提取更多价值。在你的数据工程还没有完善之前,开发机器学习能力是否具有生产力?

你的数据工程永远不会完美,所以等完美了再去开发机器学习解决方案是不明智的。然而,如果数据过于嘈杂、脆弱或稀疏,你将浪费时间来构建和部署大规模的机器学习解决方案。你需要介于两者之间。一种方法是建立一个你关心的数据层次,一旦第一个数据层次稳固,就开始开发机器学习解决方案。与此同时,继续努力提高其他数据的质量和可用性。

此外,我认为努力更好地了解你的客户、你的业务、你的产品以及他们之间的任何互动总是富有成效的。数据建模和分析是一个很好的方法;它可以帮助生成假设和潜在有用的输入信号,用于以后可以开发的机器学习技术。这种探索性工作的大部分可以在数据生产就绪之前完成。

天赋现在感到非常受限制。面对大科技公司如此激烈的招聘活动,我们其他人很难招聘到合格的人,甚至是刚从学校毕业的人。那么,当人才受到如此制约时,我们如何前进?这对人工智能的发展意味着什么?

大学对此的反应是开始培训越来越多的人掌握这类工作所必需的统计和计算等综合技能,所以供给在增加。但随着越来越多的组织意识到他们可以从这些技能中获得价值,需求也在增长。我不清楚未来十年在这方面会如何发展。然而,我也认为,希望员工拥有人工智能背景的公司应该非常清楚他们组织的使命,以及人工智能在这一使命中可以发挥的作用。当然,在人工智能领域训练有素的人才中,你应该能够找到那些不仅对它感兴趣,而且对它与你的组织的使命的特定交集充满热情的人。

Illustration by Alfonso de Anda

数据可以通过多种方式影响产品,例如 A/B 测试和强化学习来优化或个性化。但即使在此之前,网飞已经能够使用数据来建议新的测试功能,甚至新的内容策略。你能谈谈数字公司如何利用数据来建议新功能、新产品,甚至新的内容策略吗?

这又回到了一个更早的问题:使用数据分析和建模来更好地理解你的业务、你的客户、你的产品以及它们之间的相互作用。例如,寻找在与你的产品互动时倾向于表现相似的人群。利用这些受众的规模并分析每个受众参与的内容类型,可能会让您改变内容组合,以更好地将受众与产品相匹配。

然而,分析过去的数据应该主要用于生成假设。许多将被证明是错误的,例如简单的相关性在实现时会有不同的表现。所以测试,无论是完全受控的(如在 A/B 测试中)还是不受控的(改变一些东西并分析之前和之后),总是必不可少的。

你今年夏天写了一篇关于矩阵分解模型的在线方法的论文**,网飞以这种方法做推荐而闻名。但是你也曾经** 写过关于多武装土匪的 。什么时候像矩阵分解这样的监督学习方法是推荐的方法,什么时候公司应该使用土匪?****

因子分解模型已经被证明对于个性化非常有效,因为它们在个体和项目之间有效地共享信息,以学习一个小的(例如,100)数字集合来描述每个人和每个项目的行为。另一方面,多武装匪徒本质上是一个回归模型,它根据输入信号的加权和来预测结果。这对于个性化来说是有问题的,根据定义,我们期望个人和物品的交互是重要的。但是量化这种相互作用,将其转化为回归模型的足够少的输入信号可能是复杂的。

多臂强盗在非个性化的环境中可以非常成功,因为他们使用所谓的探索-利用策略来避免仅仅因为你没有足够的数据而错过好的决策(例如推荐哪些文章)。您在这里提到的第一篇文章的要点是,如果与特定问题相关,也可以用因子分解模型实现这种探索利用策略。

由于网飞是一项订阅服务,因此优化最重要的事情似乎是保持用户数量,它每隔几个月才会给你一个信号。你如何将点击率等快速代理 KPI 与留存率等更重要但速度较慢的 KPI 区分优先级?你如何平衡通过强化学习的快速优化和 A/B 测试的缓慢响应?

我差不多两年前离开了网飞,所以我不知道他们今天是如何做算法决策的。但是在互联网技术行业,你会发现一个非常快速的代理(播放、阅读、点击等)。),然后您仔细测试一个基于此类短期数据训练的模型,以确定长期指标是否真的有所改善。在网飞,这总是意味着要等三到六个月,我们才有信心找到更好的产品版本。我知道的大多数公司都没有这么有耐心,我认为这是一个错误。在互联网技术中,我还没有看到任何强化学习的成功应用,直接优化一个人可能关心的长期指标,但我认为这个方向很有趣,还没有被充分探索。

总的来说,关于公司应该(或不应该)将机器学习整合到他们的产品开发中,你学到了什么?

特别是,要非常仔细和深思熟虑,确保最终的产品是高质量的(不管你的 KPI 如何,不要偏向你能想象到的最差的内容或交互质量)。产品最终至少与公司的使命相一致,并且理想地支持公司的使命。最后,对产品的社会后果有自己的看法。

打开 STT 1.0 版本

原文:https://towardsdatascience.com/open-stt-v10-release-1c28da67f2e6?source=collection_archive---------38-----------------------

我们终于成功了!

I wanted to give him an ushanka, but my paint editing skills are too poor

TLDR

这是一篇非常简短的关于公开赛【STT / TTS v1.0发布的伴随帖。

简单地说:

  • 打开 STT 在此发布打开 TTS 在此发布,噪声数据集在此发布
  • 我们在两个新的大型和多样化的领域中添加了两个新的数据集,大约有 15,000 小时的注释
  • 新数据集有真实说话人标签(即将发布);
  • 整体注释质量得到提高,大多数注释边缘案例得到修复;
  • 数据集规范化大大提高;

打开 STT 摘要

前一段时间,我们对 STT 的总体状态(例如与计算机视觉相比)感到失望,尤其是在俄语方面。

总的来说,它面临着许多问题:(1)小/不太有用/不总是公开的学术数据集(2)巨大的不切实际的解决方案(3)庞大的/过时的/不切实际的工具包(4)一个有着悠久历史并已经被 SOTA 病毒困扰的行业(5)缺乏没有太多附加条件的可行解决方案。

所以我们决定从头开始为俄语建立一个数据集,然后基于数据集建立一套预先训练好的可部署模型。然后可能会涉及更多的语言。

开放 STT 可以说是目前存在的最大/最好的开放 STT / TTS 数据集。请点击以上链接了解更多信息。

最新版本中的主要功能

重大最新 发布 亮点:

  • 见上面 TLDR 的子弹;
  • 新数据集的说话人标签;
  • 数据集现在可以通过 torrent 以.wav文件的形式获得(我用 1 gbit/s 的通道播种),也可以通过直接下载链接以.mp3文件的形式获得(下载速度也很快);
  • 覆盖 3 个主要领域的小型人工注释验证数据集(18 小时);
  • 整体上游模型质量改进;
  • 不再有“晃来晃去”的字母;
  • 改进的语音活动检测;
  • 极大地改进了数据集标准化;
  • 显然注释并不完美,但是当我们添加新数据来过滤最讨厌的情况时,我们会不时地添加排除列表

潜在用途:

  • 语音转文字(显然);
  • 去噪(为此还要考虑我们的asr-noises 数据集);
  • 大规模文本到语音转换(新增);
  • 扬声器二进制化(新增);
  • 说话人识别(新增);

批准

数据集大多是在cc-nc-by 许可下发布的。

如果您想将其用于商业用途,请提交一份表格,然后在这里联系我们

如果你需要一个快速(即不需要 GPU 运行)/可靠/离线 STT / TTS 系统,请联系

下一步是什么?

  • 改进/重新上传一些现有数据集,完善标签;
  • 尝试用扬声器标签注释以前的数据;
  • 发布预训练模型和后处理;
  • 完善并发布扬声器标签;
  • 大概是增加新的语言;
  • 完善 STT 标签;

原载于 2019 年 11 月 4 日https://spark-in . me

OpenAI、欺骗性技术和模型风险管理

原文:https://towardsdatascience.com/openai-deceptive-technology-and-model-risk-management-57286070c06c?source=collection_archive---------15-----------------------

GPT-2 和数字防御战术手册发布后的点点滴滴

Example of a prompt and the synthetic text generated by OpenAI’s GPT-2. (Source: OpenAI)

在我整理自己对发布可能有负面影响的技术和信息的想法时,这篇文章将一些点联系起来。它涉及 OpenAI 发布的 GPT-2 和我们的数据机构发布的数字防御剧本,破坏性与欺骗性技术,恶意意图,深度伪造,验证和监视,以及模型风险管理。尽情享受吧!

OpenAI 的 GPT-2

OpenAI 最近在发布的 GPT-2 引起了轰动,这是一种语言模型,可以接受人类写的提示,并生成不止一页连贯的“人类质量”的文本。我看到人们对他们的发布策略比对模型本身更感兴趣。他们选择不发布完整的模型、数据集、训练代码或模型权重,理由是担心如何使用它们。他们解释说:

这个决定,以及我们对它的讨论,是一个实验:虽然我们不确定这是今天的正确决定,但我们相信人工智能社区最终需要在某些研究领域以一种深思熟虑的方式解决出版规范的问题。生物技术和网络安全等其他学科长期以来一直在积极讨论在明显可能被滥用的情况下负责任的发布,我们希望我们的实验可以作为一个案例研究,在人工智能社区中对模型和代码发布决策进行更细致的讨论。

反应很快,许多人对 OpenAI 的动机感到好奇。其他人担心开源的未来。

破坏性与欺骗性技术

Gradient 发表了一封由 Hugh Zhang 撰写的公开信,呼吁 OpenAI 提供完整的模型,区分破坏性和欺骗性技术:

  • 破坏性技术主要在物理领域运作。想想化学武器、实验室制造的超级病毒、致命的自主武器或原子弹。
  • 另一方面,欺骗性技术主要在我们的意识领域运作,有可能被大范围滥用来操纵和控制人们。

张接着说,对付欺骗性技术的方法是“尽可能公开它的威力”,而“绝对不能让足够危险的破坏性技术轻易获得”

他确实承认欺骗性技术可能是危险的,并建议使用“论文发表和代码发布之间的一小段延迟,以防止快速反应的恶意行为者在公众有时间完全处理新结果之前突袭。”

虽然我能理解这种观点,但公开知识和公众有知识是有区别的。公开信息并不能保证公众最终会看到它,或者有时间或兴趣去完全处理它。

恶意

在一篇对 GPT-2 的发布持不同立场的文章中,瑞恩·洛威问了机器学习(ML)研究人员一个问题:

我们正在建造影响人们的东西。迟早,我们会越过一条线,我们的研究可以被恶意利用来做坏事。我们是否应该等到这种情况发生时再决定如何处理可能有负面副作用的研究?

这与张所说的“快速反应的恶意演员”相呼应。当我读到这几行时,我的胃翻了个底朝天。我们必须努力解决的一个问题是,这项研究正被用来做坏事——人们甚至没有恶意。Lowe 在文章的后面确实提到了这个问题:

ML research 已经在现实世界中产生了影响(例如,对贷款申请法院判决人员招聘等做出决策。).这些算法中的偏见现在正在被暴露出来,但这是在它们首次实施多年之后,同时它们对人们的生活产生了严重影响。

在对创新的关注、人工智能(AI)领域缺乏多样性以及可能的大量其他因素之间,新技术的引入往往没有认真考虑潜在的不利影响或意想不到的后果。

人工智能研究员兼 fast.ai 联合创始人雷切尔·托马斯解释了让她害怕人工智能的 5 件事:

  1. 算法的实现往往没有解决错误的方法。
  2. 人工智能更容易让人没有责任感。
  3. AI 编码&放大偏见。
  4. 优化指标高于一切会导致负面结果。
  5. 大型科技公司没有问责制。

这里没有一点是关于恶意行为者的,而是关于人工智能的日常实现。似乎解决这些问题表明了透明度和公开性的重要性。

Deepfakes

实际的恶意行为者呢?我已经写了关于 deepfakes 引起的担忧和损害。大量的金钱和资源被投入到检测它们的工作中,一些人表达了对 deepfakes 和类似技术如何被用来扰乱 2020 年选举(以及更广泛的影响)的担忧。

Still from video by Deeptrace. (Source: IEEE Spectrum)

事实上,OpenAI 在他们不提供 GPT-2 完整版本的理由中引用了这些技术:

我们还可以想象这些模型的应用出于的恶意目的,包括以下几种(或者其他我们还无法预料的应用):

  • 产生误导性新闻文章
  • 在网上冒充他人
  • 自动制作发布在社交媒体上的辱骂或伪造内容

回到张关于欺骗性技术的“论文发表和代码发布之间的一个小延迟”的建议,许多致力于检测 deepfakes 的研究人员已经谈到了分享他们的发现的问题。

计算机科学家 Siwei Lyu 在 2018 年 8 月发表了一篇文章,解释了他的团队如何基于眨眼实现了超过 95%的深度假货检测率。但是随后的一篇文章透露,“就在他的团队将论文草稿放到网上的几个星期后,他们收到了匿名邮件,这些邮件链接到伪造程度很高的 YouTube 视频,这些视频中的明星更正常地睁开和闭上眼睛。虚假内容的创造者已经进化了。”

加州大学计算机科学教授哈尼·法里德使用法医技术来检测深度假货。他解释了由于机器学习,对抗它们变得更加困难,以及为什么他不分享新的突破:

程序员所要做的就是更新算法来寻找,比如说,与心跳相对应的面部颜色变化,然后突然之间,假货就融入了这种曾经难以察觉的迹象。一旦我泄露了这项研究,只需要一个混蛋把它加入他们的系统。

虽然有些人呼吁将可以生成假媒体的技术开源,但那些致力于检测假货的人通过保密他们的创新,在所谓的人工智能军备竞赛中受益。

核查和监督

(Photo by Chris Ried on Unsplash.)

一些人不再专注于检测假媒体,而是着眼于验证真媒体。技术社会学家泽内普·图费克奇建议验证可以通过摄像头或区块链数据库中的防欺骗元数据来实现。这些解决方案可能有助于验证图像或视频,但验证文本可能会更加困难。图费克奇还提醒我们:

然而,有效的身份识别系统也带来了一个令人担忧的事实:每一种验证方法都有被监控的危险。

虽然她继续说有办法减轻这种担忧,但这不是一个可以掉以轻心的问题。

数字防御战术手册

在 OpenAI 发布 GPT-2 的一周前,还有一个我更关心的版本,但它没有像 GPT-2 那样受到关注。我们的数据机构(ODB) 发布了数字防御手册:回收数据的社区动力工具。该工作簿被描述为“一套久经考验的工具,用于诊断、处理和修复普遍存在的惩罚性数据收集和数据驱动系统的不公正。”

该新闻稿继续说,“ODB 希望剧本将激励社区参与解决源于社会不公正的监控、侧写和隐私问题。”

ODB 正在努力处理前面提到的一些问题的后果,包括编码到 AI 中的偏见(有意和无意)以及意外后果的影响。

Tawana Petty during the Data for Black Lives II closing panel. (Source: Data for Black Lives Facebook)

在麻省理工学院媒体实验室举行的“黑人生活数据 II”会议的闭幕式上,组织者和 ODB 团队成员 Tawana Petty 告诉观众:

你们都拿到了数字防御战术手册,但是我们没有告诉你们他们所有的策略,我们永远也不会告诉你们。因为我们希望我们的社区成员继续生存和发展。所以你会得到一些东西,但是让他们活下去的东西,我们自己留着。

虽然团队创建这个资源是为了共享知识,但是限制他们共享的内容对他们的项目同样重要。它还回顾了法里德的策略,即解释他研究的某些方面,但对其他方面保密以保持优势。

模型风险管理

上周,在我已经开始尝试将这篇文章拼凑起来之后,我参加了 QuantUniversity.com 创始人 Sri Krishnamurthy 的演讲,题目是“数据科学和人工智能时代的模型治理”他谈到了围绕代码可再现性的挑战,以及代码库的可解释性和透明性的重要性。

我特别有兴趣了解更多关于美联储sr11–7定义的模型风险管理。该文件将“模型风险”定义为“基于不正确或误用的模型输出和报告的决策的潜在不利后果。”尽管该文件在列举不利后果(财务损失或“对银行组织声誉的损害”)的例子时明显是针对金融机构的,但它确实提供了减轻风险的指导原则,可以帮助指导其他地方的做法。

如果我们从对人的影响而不是对业务的影响的角度来考虑不良后果,我们可能会开始朝着正确的方向前进。(这句台词我已经能听到笑声了。这篇文章可能会转向另一个方向,但我会继续前进。)

那么这给我们留下了什么?

在另一篇报道 OpenAI 发布 GPT-2 的文章中,技术作家 Aaron Mak 重申了我在上面思考的问题:

机器学习从业者尚未建立许多被广泛接受的框架,来考虑创造和发布人工智能技术的伦理影响。

然而,他继续说道:

如果最近的历史有任何迹象,试图抑制或控制人工智能工具的扩散也可能是一场失败的战斗。即使在传播某些算法的道德问题上存在共识,也不足以阻止持不同意见的人。

虽然协议或广泛采用的一套准则可以帮助解决意外后果和这里讨论的其他问题,但 Mak 是正确的,因为它不会阻止实际的恶意行为者。

就个人而言,我很高兴 OpenAI 选择将这一对话带入公众,并发现这比他们发布或不发布的模型更重要。虽然我也倾向于让事情开源和共享信息——为了技术的民主化、透明度和问责制——但我也理解为什么人们会对发布可能以他们不希望的方式使用的技术和信息持谨慎态度。(我担心开源的其他方面,但那是以后的事了。)

谢谢你陪我踏上这段旅程。我仍在努力发展我对这些问题的理解,并澄清我的立场。我很乐意听到您对此的想法、问题或反馈。

GPT-2:通过可视化理解语言生成

原文:https://towardsdatascience.com/openai-gpt-2-understanding-language-generation-through-visualization-8252f683b2f8?source=collection_archive---------4-----------------------

超大的语言模型是如何完成你的想法的。

在大多数 NLP 研究人员看来,2018 年是技术进步巨大的一年,新的预训练 NLP 模型打破了从情感分析到问题回答等任务的记录。

但对其他人来说,2018 年是 NLP 永远毁掉芝麻街的一年。

首先是ELMo(Eembeddings fromLlanguageModels)然后是BERT(BI directionEn coderRpresentations fromTtransformers),现在 BigBird 坐在胶水排行榜的首位我自己的思维已经被这种命名惯例所腐蚀,以至于当我听到“我一直在和伯特玩,”的时候,我脑海中闪现的图像不是我童年时的毛茸茸的单眉锥头鹦鹉,而是这样的:

我看不到那张,插图伯特

我问你——如果芝麻街在 NLP 模型品牌化面前都不安全,还有什么是安全的?

但有一个模型让我的童年记忆完好无损,这是一个没有名字和面孔的算法,它的作者 OpenAI 简单地将其称为“语言模型”或“我们的方法”。只有当另一篇论文的作者需要将他们的模型与这个无名的创造物进行比较时,它才被认为配得上一个名字。也不是厄尼格罗弗库克怪兽;这个名字准确地描述了算法是什么,仅此而已:GPT,预训练的生成式变压器

但是就在它被命名的同时,GPT 被伯特毫不客气地从 GLUE 排行榜上除名了。GPT 失败的一个原因是它使用传统的语言建模进行了预训练,即预测句子中的下一个单词。相比之下,伯特使用掩蔽语言建模进行预训练,这更像是一个填空练习:根据之前和之后出现的单词猜测缺失(“掩蔽”)的单词。这种双向架构使 BERT 能够学习更丰富的表示,并最终在 NLP 基准测试中表现更好。

因此,在 2018 年末,OpenAI 的 GPT 似乎将永远作为伯特的通用名称、奇怪的单向前身而被历史所知。

但 2019 年讲述了一个不同的故事。事实证明,导致 GPT 在 2018 年垮台的单向架构让它有能力做一些伯特永远做不到的事情(或者至少不是为它设计的):写关于会说话的独角兽的故事:

From https://blog.openai.com/better-language-models/ . Edited for length.

你看,从左到右的语言建模不仅仅是一个训练前的练习;它还实现了一个非常实际的任务:语言生成。如果你能预测一个句子中的下一个单词,你就能预测下一个,再下一个,很快你就有了…很多单词。如果你的语言建模足够好,这些单词将形成有意义的句子,这些句子将形成连贯的段落,这些段落将形成,嗯,你想要的任何东西。

而在 2019 年 2 月 14 日,OpenAI 的语言模型确实变得足够好——好到可以写会说话的独角兽的故事,产生假新闻,写反回收宣言。它甚至被赋予了一个新名字: GPT-2

那么,GPT 2 号具有类似人类的写作能力的秘密是什么呢?没有根本性的算法突破;这是一个扩大规模的壮举。GPT-2 拥有高达 15 亿个参数(比最初的 GPT 多 10 倍),并根据来自 800 万个网站的文本进行训练。

如何理解一个有 15 亿个参数的模型?让我们看看可视化是否有帮助。

可视化 GPT-2

由于担心恶意使用,OpenAI 没有发布完整的 GPT-2 模型,但他们发布了一个较小的版本,大小相当于原始 GPT (117 M 参数),在新的更大的数据集上进行训练。虽然没有大模型强大,但小版本仍然有一些语言生成能力。让我们看看可视化是否能帮助我们更好地理解这个模型。

:创建这些可视化效果的代码可以在 GitHub 上找到。

一个说明性的例子

我们来看看 GPT-2 小模型是如何完成这句话的:

船上的狗跑了

下面是模型生成的结果:

船上的狗跑了,狗被船员发现。****

似乎很合理,对吧?现在让我们稍微调整一下这个例子,把改成马达,看看这个模型会生成什么 :

船上的马达运转了

现在是完整的句子:

船上的马达以大约每小时 100 英里的速度运转。

通过改变句首的那个单词,我们得到了完全不同的结果。这个模型似乎理解了狗的奔跑类型和马达的完全不同。

GPT-2 怎么知道如此关注 g vs 马达的,尤其是这些词出现在句子的前面?嗯,GPT-2 基于变压器,这是一个 注意力 模型——它学会将注意力集中在与手头任务最相关的前面的单词上:预测句子中的下一个单词。

让我们来看看 GPT 2 号对船上的狗跑了的关注点在哪里:

从左到右阅读的线条显示了模型在猜测句子中的下一个单词时注意的位置(颜色强度代表注意强度)。所以,在猜测跑完之后的下一个单词时,这种情况下模型密切关注。这是有意义的,因为知道谁或什么在跑步对于猜测接下来会发生什么至关重要。****

在语言学术语中,模型关注的是名词短语*的船上的狗*。GPT-2 还捕捉到了许多其他语言特性,因为上面的注意力模式只是模型中 144 个注意力模式中的一个。GPT-2 有 12 层,每层有 12 个独立的注意机制,称为“头”;结果是 12 x 12 = 144 种不同的注意力模式。在这里,我们将它们全部可视化,突出显示我们刚刚看到的那个:

Visualization of the attention patterns across the model’s 12 layers (rows) and 12 heads (columns), with Layer 4 / Head 3 selected (zero-indexed).

我们可以看到这些模式有许多不同的形式。这里还有一个有趣的例子:

这一层/头把所有注意力集中在句子中的前一个词上。这是有意义的,因为相邻的单词通常与预测下一个单词最相关。传统的 n -gram 语言模型也是基于同样的直觉。

但是为什么这么多的注意力模式是这样的呢?

在这种模式下,几乎所有的注意力都集中在句子中的第一个单词上,其他单词都被忽略了。这似乎是零模式,表明注意力头没有发现它正在寻找的任何语言现象。当没有更好的关注点时,该模型似乎已经将第一个单词重新定位为要查找的地方。

____ 中的猫

好吧,如果我们要让 NLP 玷污我们对芝麻街的记忆,那么我想苏斯博士也是公平的游戏。让我们看看 GPT-2 是如何完成经典作品《戴帽子的猫》中的这些台词的

在一只风筝线上,我们看到了妈妈的新衣服!她的礼服上有粉色、白色和…

GPT 2 号是这样完成最后一句话的:

她的礼服上有粉色、白色和蓝色的圆点。

不算太差!原文有红色,至少我们知道不只是背。

那么 GPT 2 号是如何知道选择颜色的呢?也许是因为下面的注意模式似乎能识别逗号分隔的列表:

为了确定在之后的单词,模特将注意力集中在列表中的前面的项目上——粉色和白色。它知道挑选一个与前面项目类型相匹配的单词,在这个例子中是一种颜色。

名字有什么意义?

GPT-2 似乎特别擅长只根据一个名字写短篇传记。

作为一个实验,尝试让 GPT-2 从提示中生成文本“谁是<你的名字>?”这个特殊的提示通常会触发模型写一篇简短的传记,可能是因为这是网络文章中作者传记的常见序言。

下面是为提示“谁是杰西·维格?”生成的几个 bios。:

“杰西·维格是社交媒体营销专家,曾任社交媒体营销经理。他是 VigMedia.com 的联合创始人兼首席执行官,最近又是 vig media . com 的创始人兼首席执行官。”

还不错!有点重复,但以一种意想不到的方式很好地将故事个性化。这里还有一个:

“杰西·维格是一位名叫詹姆斯·维格的福音传教士的儿子。他于 1964 年移居美国,成为密歇根大学的一名传教士,在那里他教了 18 年书,直到 2007 年 10 月去世。

在这最后一个例子中,GPT-2 足够聪明,知道我的另一个自我的父亲有相同的姓。让我们看看 GPT 2 号在选择最后一个名字时将注意力集中在哪里:

Layer 11 / Head 10

当决定在詹姆斯之后预测的单词时,这种模式将注意力集中在我的姓的先前提及上。(注意,在模型内部, Vig 已经被分成单词块“V”和“ig”,因为它是一个不常用的单词。)似乎这种注意模式专门识别家族名字之间的关系。为了测试这一点,让我们稍微修改一下文本:

“杰西·维格是一位名叫詹姆斯的福音传道者的 同事……**

Layer 11 / Head 10

现在詹姆斯只是一个同事,这种注意力模式几乎完全忽略了我的姓。

注意:《GPT-2》似乎是根据一个名字的种族和性别来生成传记的。需要进一步的研究来了解这个模型可能会编码什么样的偏见;你可以在这里阅读更多关于这个话题的内容。

未来是可生成的

就在去年,生成各种内容的能力——图像、视频、音频和文本——已经提高到我们不再相信自己的感官和判断的程度。

而这仅仅是开始;这些技术将继续发展,并变得更加相互融合。很快,当我们看着thispersondoesnotexist.com上生成的面孔时,他们会迎着我们的目光,和我们聊起他们生成的生活,揭示他们生成的人格的怪癖。

最直接的危险也许是真实与生成的混合。我们已经看过了奥巴马作为人工智能傀儡的视频和和与的奇美拉的视频。很快,这些 deepfakes 就会变成个人的了。所以,当你妈妈打电话说她需要 500 美元电汇到开曼群岛时,问问你自己:这真的是我妈妈吗,还是一个语言生成人工智能从我妈妈 5 年前发布的脸书视频中获得了她的语音皮肤?

但是现在,让我们先欣赏一下关于会说话的独角兽的故事。

关于这个和相关项目的更新,请随时关注我的 推特

更新】😗* 厄尼现正式拍摄(两次!)—参见通过 kNowledgeIntEgration 和EEenhanced LanguageRpresentation 通过 INEentities按原样**

资源:

GitHub repo 用于 Jupyter 和 Colab 笔记本电脑的可视化工具,使用这些出色的工具/框架构建:

供进一步阅读:

解构 BERT:从 1 亿个参数中提取 6 种模式

解构伯特,第 2 部分:可视化注意力的内部运作

人工智能玩疯狂图书馆,结果是可怕的

图解变压器教程

《开放的 GPT 2》为《权力的游戏》写了不同的结局

原文:https://towardsdatascience.com/openai-gpt-2-writes-alternate-endings-for-game-of-thrones-c9be75cd2425?source=collection_archive---------4-----------------------

我在 GRRM 的书系列《冰与火之歌》上训练了 GPT-2 语言模型,并让它完成了 HBO 节目的故事情节。它能比 HBO 的第八季《火车残骸》更好吗?

Game of Thrones season 8 storyline has left its fandom divided with millions of fans disappointed by its rushed and unsatisfactory ending. Disclaimer: Opinions expressed in this article are solely my own.

《权力的游戏》第八季的故事情节让粉丝们产生分歧,数百万粉丝(包括我自己)对其仓促且不尽如人意的结局感到失望。许多人呼吁重写这部电视剧的最后一季,而其他人则提出了他们自己版本的结局,以获得一个满意的结局。其他人正在等待 GRRM 完成他的书,希望他能为人物的不可信行为提供一个更令人信服的构建,但这可能需要很多年。因此,我想让一个人工智能学习 GRRM 的写作风格,并让它完成节目的结尾。

在这篇文章中,我将解释我们如何通过使用名为 GPT-2 的文本生成语言模型来实现这一点,该模型由 Open AI 的研究人员在 2019 年初推出。然后,我将分享这一季三个主要反派的故事情节的模型预测结果:夜王、瑟曦·兰尼斯特和丹妮莉丝·坦格利安。

生成式预训练变压器 2 (GPT-2)

GPT-2 是目前人工智能语言建模中最先进的文本生成模型。它能够产生类似人类的连贯句子,并且能够长时间专注于一个主题。与其他语言模型相比,它令人印象深刻的改进归功于这项研究的两个主要贡献

  1. 大量数据:搜集并整理了 800 万个网页,形成了一个 40GB 的文本语料库,可以对其进行无监督训练。它涵盖了各种各样的主题,这就是为什么预训练模型非常适合将学习转移到特定领域,就像我们的 GoT 书籍一样。
  2. 大量计算:它使用 15 亿(!!)在其基于变压器的网络架构中的参数。然而,他们只发布了这个模型的一个较小版本,包含“仅”3.45 亿个参数,引用了安全原因。我们将使用这个版本的预训练模型来执行 GoT 脚本的迁移学习。

变压器模型

GPT-2 使用变压器网络架构,而不是通常用于序列建模的传统 RNN/LSTM/GRU 网络。Transformer 使用基于注意力的机制和一对编码器/解码器,而不是带有“记忆”门和时间步长的循环单元。

编码器在字节对和位置嵌入的帮助下处理输入,字节对和位置嵌入描述输入句子中单词的“是什么”和“在哪里”(嵌入)。同一个编码器将字节和位置嵌入转换为矢量编码,然后进入解码器,解码器的任务是将编码转换为目标文本序列。该输出和来自前一步骤的编码被馈送到下一编码-解码步骤,并且被重复多次以产生进一步的文本。这里有一篇优秀的文章详细解释了这个模型架构。

Overview of a general attention-based Transformer model. [source: Attention Is All You Need’ by Vaswani et al.]

请注意,GPT-2 被训练为预测给定输入句子中的下一个单词,其假设是,为了相当准确地预测下一个单词,模型将被迫学习到目前为止它遇到的所有单词的上下文含义。如果不理解文本,语言模型可能只能预测语法正确的单词,但生成的文本不会完全有意义。因此,这种使网络预测足够好的下一个单词的公式,GPT-2 能够获得对输入文本的深刻理解。这里是伊利亚·苏茨基弗对这个概念的一个很好的解释。

GPT-2 在文本生成期间不需要编码器,因为它不是像语言翻译那样的 seq2seq 转换任务。所以一旦训练结束,编码器就不再需要了。GPT-2 仅使用来自预训练转换器的解码器来生成后续文本。

训练模特

我从乔治·R·R·马丁的书系列“冰与火之歌”的所有 5 本书中提取了文本,并将它们连接起来准备训练文本。使用具有 345M 参数的预训练的 GPT-2 模型对该文本执行迁移学习。

George R.R. Martin’s Book Series “A Song of Ice and Fire”.

令人惊讶的是,我注意到预先训练的模型也非常擅长写关于《权力的游戏》角色的内容,这意味着它在 800 万网页的初始训练中接触过这些内容。不管怎样,我决定缩小这个“一般化”模型的范围,只按照 GRRM 的风格编写,所以继续在我们的 GoT 数据集上进行训练。该模型在 Google Colab 的 K80 GPU 上训练了大约 12 个小时。

结果

让我们尝试解决一些令人失望的结局或故事情节的转折,并尝试使用我们训练有素的 GPT-2 模型预测这些场景的替代结局。

下面是视频格式的结果,后面是文本格式的结果。选择自己的冒险。

失望 1:夜王虎头蛇尾的结局

输入:夜王慢慢走到三眼乌鸦面前。琼恩被冰龙挡住,丹妮莉丝被怀特一家团团围住。夜王伸出他的冰剑想要杀死布兰,但突然

输出:阿多阻止了他,他仍然用他的大手抓着冰原狼。“阿多!”乌鸦叫道。“阿多!阿多!”黑魔王脸上带着失落的表情。他用树桩刺穿布兰的背部,开始搏斗、翻滚、旋转。怀特,巨人,半身人,稻草人。布兰与夏莫、老鹰、笨狗和陌生人并肩作战,但光之王绝不会以剑挡剑。乌鸦在说,只是爬上阿多的厚雪白的腿。

据 GPT 2 号说,阿多还活着,他来营救布兰,真是个意外!或者它可能是被布兰注入的阿多的不死之身。但是之后我就不知道模特想说什么了,哈哈!

输入:夜王慢慢走向三眼乌鸦。琼恩被冰龙托起,丹妮莉丝被狼人包围。夜王伸出他的冰剑想要杀死布兰,但突然意想不到的事情发生了。

输出:剑发出炽热的红光。当剑刃击中夜之眼时,它周围的绿色玻璃裂开了,光溶解了,剑像死冰一样发光。然后乌鸦开始尖叫,远处的猫头鹰在龙的左边和右边,有东西正在还击,撞开门,杀死所有长着娃娃脸的傻瓜。我猜 Osha 在给 Rickon 演示如何装弹。也许战斗结束后,他们都会是很好的倾诉对象。

尽管节目主持人忘记了,GPT-2 记得亚梭尔·亚亥的预言,并围绕着杀死夜王的剑光明使者的想法起舞。如果夜王的冰剑最终被证明是光明使者并杀死他,那该有多酷啊?!

输入:布兰说,“席恩,你是个好人。谢谢大家。”!席恩,带着他的救赎之弧,奔向夜王的死亡。就在他要用长矛刺穿夜王的时候,

输出:龙——还是另一个?——朝他的脸开了一枪,而夜王平静地看着。世界缩小到三个人,肩并肩站在一起;红色的牧师和他的长矛,国王穿着蓝色,他的皇冠在他的头上。一股寒风穿过冰冷的空气吹进席恩的脑袋,他也能听到他的兄弟们在喊叫。如果我不是那么坚强。。。杀了他,他想喊,但是勇气从他身上消失了,就像他身体的一部分被迫保持沉默。取而代之的是,他弯曲他残废的手臂,扔掉他的矛杆。他告诉自己,给自己留点伤,尽你所能跑吧。

这一篇让我大吃一惊,不是因为它写得很棒(其实不是),而是因为模型知道龙实际上是一个“他者”(这意味着书中的白行者)。它怎么会知道维塞隆是一条被夜王控制的不死龙呢?韦赛里翁向席恩喷火,折断了他的长矛。席恩,在这一刻,决定在恐惧中逃跑,就像他在这个节目中所做的一样。把所有这些细节都写在一段话里,这太巧合了。令人惊讶的是,模特已经知道了角色的这些细节!

失望 2: 瑟曦·兰尼斯特在没有任何计划和适当战斗的情况下被轻易击倒

输入:巨龙已经烧毁了整个兰尼斯特的军队,钢铁舰队和黄金军团,但是瑟曦依然坚信红堡不会陷落。当恶龙即将烧毁红堡的塔楼时,詹姆前来营救瑟曦。此时此刻,

他的心提到了嗓子眼,手掐着喉咙……他不知道如何呼吸……”艾莉亚颤抖着提利昂说兰尼斯特家有刀。"“他说他们有剑,”詹姆承认道。"詹姆杀托曼不是为了保住托曼的贞操,”艾莉亚说,把自己的故事告诉了身旁脸红的男孩提利昂·兰尼斯特。他的小弟弟只是咧嘴一笑。”不,我没有。"詹姆狠狠地瞪了她一眼。"很好。你撒谎。是的,你对那个吻撒了谎。你用嘴杀死了托曼,这既不是吻也不是承诺。只有一两把剑。你伤得很重,小家伙。不管怎样,只要那个脏男孩珍惜你给他的礼物,你姐姐就会把他留在她的床上。"

嗯,好吧,这个完全是垃圾。但我还是留着它,因为它太傻了,实际上很有趣。不管怎样,让我们再试一次!

输入:龙族已经烧毁了整个兰尼斯特军、铁血舰队和黄金连队的军队,但瑟曦依然坚信红堡不会陷落。当恶龙即将烧毁红堡的塔楼时,詹姆前来营救瑟曦。此时此刻,

输出:根据她的预言,疯王将进攻这座城市……“瑟曦,”詹姆又说了一遍,尽量让声音听起来严厉而遥远,“静静地,哦,甜蜜,哦,甜蜜。”他给特罗特写道:“瑟曦,记住,你是凯岩城的国王。记住你是谁,你是什么。还记得你是如何杀死疯王的吗?原谅我,如果我让你犹豫不决。”她没有回答。“原谅我,”他热情地重复道,“为了我从未有过的母亲,你从未有过的母亲,一个所有人都认识并爱着却不认识的母亲。”当刀刃入鞘时,鹰在油的波纹上闪着微光,天花板上的字闪闪发光,又亮又暗…

这次稍微好一点!虽然这个模型在某些细节上出错了,特别是关于疯王的,但我确实喜欢詹姆在那一刻试图给瑟曦力量的想法。也许在这个时候使用某种野火会给她的故事情节带来一些正义感。两个疯狂的女王,以火攻火,烧毁了城市的其余部分。这将是一个更好的结局,表明为什么争夺铁王座的战争是不好的。

失望 3: 丹妮莉丝不劳而获的脚后跟转弯

输入:丹妮莉丝在埃索斯和弥林拥有爱和恐惧。但在维斯特洛,她觉得自己只有恐惧。在她赢得铁王座之战的那一刻,她只能想着给她将要统治的人民灌输恐惧。丹妮莉丝在君临坐在她的龙上,她决定要

输出:吃。“有牙齿的食物,”乔拉爵士说。“我想尝尝那个,”丹妮抱怨道。"吃红肉喝麦芽酒不太像多斯拉克人."她想起了过去的时光,那时她的卡拉萨在长枪党统治时期是国王的住所,多斯拉克人肥胖的卡拉萨在骑马南下消灭其他多斯拉克人之前,会在他们的杯子里倒满美酒、鱼餐和烤芜菁。这只是供思考的食粮。我会大吃大喝,假装休息,直到龙再次出现,杀死我们所有人。

总是吃喝的好时机,对吧?我听说君临有一家不错的咖啡店,丹妮可以去试试(如果它还没被烧毁的话)。这很糟糕,让我们再试一次。

丹妮莉丝在埃索斯和弥林拥有爱和恐惧。但在维斯特洛,她觉得自己只有恐惧。在她赢得铁王座之战的那一刻,她只能想着给她将要统治的人民灌输恐惧。丹妮莉丝在君临坐在她的龙上,她决定要

保护这座城市,并为任何试图逃跑的人准备好坦格利安的灾难和恐怖,是的,包括人类。有人告诉她,一些巨人可能会杀死她,但丹妮莉丝摇摇头说:“没有巨人喜欢长得像巨人一样大。后来,后来,没有人愿意孤独地死在树林里。”她又读了一遍信。“昆汀王子,我忠诚的仆人们,我见过你们这样愚蠢的傻瓜,但我从未见过你们这样愚蠢的傻瓜。你的生命在众目睽睽之下被夺走了。丹妮莉丝是唯一能救你的人。”

所以这也没什么意义,但似乎坚持了丹妮想把君临的人民从那些准备“屈膝”且不打算逃跑的暴君手中解放出来的叙事。

结论

我试图为这些故事情节生成更多的样本,但没有一个在整个节目的背景下有很大的意义。即使对故事情节的理解不是很好,该模型也清楚地展示了学习该剧角色及其某些特质的能力,并在其输出中创建这些角色之间的关联。比如,我看到乔拉爵士在故事情节中出现在谈论丹妮的时候,阿多在谈论布兰的时候出现。而且它往往把这些角色之间的关系处理得恰到好处,真的让人印象深刻!

我认为这显示了随着 OpenAI 的 GPT-2 研究工作,NLP 研究已经前进了多远。我很想知道最大的 GPT-2 型号在这项任务中表现得有多好。也许如果更大的模型被发布,我会回来更新这篇文章。

至于想要一个令人满意和明智的《权力的游戏》结局,我想当代的人工智能帮不了我们,我们必须等待乔治·R·R·马丁完成他的书。愿他万岁!

想在你的浏览器上试试《GPT 2》的《权力的游戏》模型吗?用于测试预训练模型的 Google Colab 笔记本链接如下(为该笔记本提供)。

[## 谷歌联合实验室

权力的游戏 GPT-2 文本生成器

colab.research.google.com](https://colab.research.google.com/drive/18pLqrk1j4RQ1RNh69Fa-5WkoTeD4uzwq)

参考文献

感谢您的阅读。如果你喜欢这篇文章,你可以在媒体GitHub 上关注我的更多作品,或者订阅我的 YouTube 频道。动手吧。弯曲膝盖。或者面对我的龙。

基于 TensorFlow Keras 的古腾堡开放 GPT 语言建模

原文:https://towardsdatascience.com/openai-gpt-language-modeling-on-gutenberg-with-tensorflow-keras-876f9f324b6c?source=collection_archive---------18-----------------------

Photo by Camille Orgel on Unsplash

1.介绍

2018 年对于深度自然语言处理社区来说是不平凡的一年。大型预训练模型,open ai【GPT】GPT-2 和 Google BERT ,在几个监督和非监督任务上取得了 SOTA(“最先进”)的结果。发布这些模型有助于在许多 NLP 任务中获得更好的结果(就像 ImageNet 在视觉领域所做的那样)。

我们一直在做的项目(一种讲故事的方式)需要一个强大的语言模型来促进自然语言的生成。本文介绍了在这项任务上所做的努力,包括技术细节和结果。完整代码以回购的形式发布在我们的团队 GitHub 中:

[## ShenakhtPajouh/GPT-语言-模型-tf.keras

在 GitHub 上创建一个帐户,为 ShenakhtPajouh/GPT-语言-模型-tf.keras 开发做出贡献。

github.com](https://github.com/ShenakhtPajouh/GPT-language-model-tf.keras)

2.动机

根据 Tensorflow 的网站:

Keras 是一个高级 API,用于构建和训练深度学习模型。它用于快速原型制作、高级研究和生产,具有三个关键优势:**user friendly** 模块化和可组合 ,以及 易于扩展

此外,您可以在会话模式和快速执行模式下运行 TensorFlow Keras 模型。

OpenAI GPT,简称ggeneratepre-trainedttransformer是一个在庞大语料库上训练出来的多层单向 transformer 解码器 ⁴。它的开发目标是通过微调来很好地执行各种任务。OpenAI 于 2018 年 6 月发布了 GPT 的论文、代码和预训练的权重。

2019 年 2 月,OpenAI 发布了 GPT-2,这是 GPT 的继任者,其参数超过 10 倍,数据量超过 10 倍。它被训练来预测下一个单词,并在 8 个测试语言建模数据集的 7 个上达到 SOTA 结果,而没有任何特定任务的微调!不可思议,不是吗?为了把樱桃放在最上面,OpenAI 决定不完全发布训练模型,而是发布一个小得多的模型,因为他们担心恶意应用程序 T2。

由于 OpenAI 成就和无法访问 GPT-2 完整模型,并且由于从空白状态学习更难取得成功,我们决定受益于转移学习技术并使用 TensorFlow Keras 实现 GPT。

3.履行

原始 GPT 被实现以在语言模型和分类任务上表现良好。因为我们只需要一个语言模型,所以我决定简化它的架构。有一个由 Ceshine Lee 设计的重构满足了这个需求。查看他解释原始和修改模型的帖子:

[## [注意]通过生成性预训练提高语言理解

练习:从微调后的模型重建语言模型

medium.com](https://medium.com/the-artificial-impostor/notes-improving-language-understanding-by-generative-pre-training-4c9d4214369c)

上面的帖子包含了对变形金刚、GPT 和修改的详细解释,所以这篇帖子的其余部分将涵盖我所做的其他更改。

3.1.数据迭代器

我们使用 Guttenberg 数据集来重新训练模型。它包含超过 140,000 个段落。每一个样本都是一段被 BPE ⁵符号化的段落(带着尊重的面具)。所以在[iter_data](https://github.com/ShenakhtPajouh/last-sentence-generation-transformer/blob/master/utils.py#L51)函数中,段落被打乱并通过小批量返回:

3.2.将张量流模型转换为 tf.keras 模型

整个变压器网络已经改造成 tf.keras 。作为网络一部分的每个张量流函数都被重新实现。modelembedblockattnmlpnormcov1d函数被转换为TransformerEmbeddingLayerBlockAttentionMLPNormConv1D 类,这些类是 tf.keras 模型和层。

3.3.添加自回归模块

开发 GPT 的初衷并不是为了成为一个语言生成器。因此,它不具备生成文本的自回归模块。所以我们决定设计一个快速语言生成器,采用贪婪解码(它在每一步选择最有可能的下一个标记)。

在生成的每一步,该模块应该处理并获取下一个令牌的 logits,选择最可能的令牌,并在下一步为新序列执行该过程。

获取下一个令牌的 logits 的一个简单方法是传递整个令牌序列(带有生成令牌的早期令牌)。但是太慢了!为什么?因为它在每一步都有一个重复的操作:对于每一个 i,j < k ,计算 ij 之间的注意力来预测第 k 个令牌。

我们的方法简单地省略了这个重复的操作。我用mem_kmem_v来记忆键和值矩阵。首先, init_model 对输入序列进行预处理,将关键字和值存储在mem_kmem_v中,并选择下一个令牌。

然后在每次迭代中, gen_model 获得查询、密钥和前一个令牌的值。然后将关键字和查询添加到mem_kmem_v,并计算关注度。

有一些方法可以根据其分布生成下一个令牌。最简单的方法是贪婪解码。我们在每一步选择最可能的记号。波束搜索是另一种试图解决贪婪解码问题的著名技术。但是他们都有相同的内在问题,导致他们无法产生人类文本。(在这篇论文中,⁶解释了这些方法的缺点)

因此,在一些论文中,这两种方法被基于抽样的替代方法所取代。在这些方法中,在每一步,我们从下一个令牌分布中进行采样。我们实现了两个强大的解码器,称为 top-k 采样nucleus(top-p) 采样(【2】、【6】、【7】)。这确实提高了我们模型的世代。

您可以在实用程序中找到解码器的代码:

4.重新训练模型

我用 Adam optimizer 尝试了几种常用的训练方法,都失败了。然后,根据 ULMFiT 的论文,我做了一些改变:

  • 亚当换成梯度下降。亚当技术极有可能让你的模型忘记预先训练好的权重。
  • 我还使用了倾斜的三角形学习率(STLR)。它在一小部分训练步骤中线性地增加了学习率。然后,它在剩余步骤中线性降低学习速率。如论文中所述,“我们希望模型在训练开始时快速收敛到参数空间的合适区域,然后优化其参数。”于是 STLR 提出了。经过一些失败之后,我为 STLR 找到了一些好的超参数:

在和 STLR 一起训练后,我用一个简单的非线性衰减学习率继续训练:lr -= lr * (1 / t ** 0.5)

5.结果

下面的学习曲线清楚地显示了 STLR 技术的效率。(因为仅在 2400 步之后,列车困惑度就显著下降)

train ppl in 30,000 steps.

验证集的复杂度从 130.21 降低到 22.57。

validation ppl

6.承认

我衷心感谢实现了一些 Transformer 模块的茯苓 Yavari 和实现采样解码器的 Mehrnaz Mofakhami。

7.参考

[1] 利用无监督学习提高语言理解作者:亚历克·拉德福德、卡蒂克·纳拉西姆汉、蒂姆·萨利曼斯和伊利亚·苏茨基弗

[2] 更好的语言模型及其含义作者:亚历克·拉德福德、杰夫·吴、雷文·柴尔德、大卫·栾、达里奥·阿莫代伊和伊利亚·苏茨基弗

[3] BERT:用于语言理解的深度双向转换器的预训练作者:Jacob Devlin,张明蔚,Kenton Lee,Kristina Toutanova

[4] 通过总结长序列生成维基百科作者:Peter J. Liu,Mohammad Saleh,Etienne Pot,Ben Goodrich,Ryan Sepassi,Lukasz Kaiser,Noam Shazeer

[5] 由 Rico Sennrich,Barry Haddow,Alexandra Birch 编写的具有子词单元的罕见词的神经机器翻译

阿里·霍尔茨曼著《神经文本退化的奇特案例》

[7] 分层次的神经故事生成由安吉拉·范、、扬·王太子

OpenAI 的克里斯汀·佩恩谈人工智能产生的音乐和超级智能之路

原文:https://towardsdatascience.com/openais-christine-payne-on-ai-generated-music-and-the-road-to-super-intelligence-580f5063093?source=collection_archive---------29-----------------------

她在普林斯顿学习物理,在斯坦福学习神经科学和医学。

她是受过古典音乐训练的钢琴家。

她刚刚发明了一种算法,可以让音乐家失业。(嗯,可能不会,但这确实是一个令人印象深刻的算法)

克里斯汀·佩恩是 MuseNet 的作者,这是一个基于 OpenAI 的现在臭名昭著的 GPT-2 模型的深度神经网络,可以自动生成几乎任何你想要的风格的歌曲。

我们和 Christine 坐下来谈论 MuseNet,人工智能的未来,以及 OpenAI 防止机器人启示录的任务。请点击这里查看,别忘了在 Twitter 上关注她, @mcleavey

OpenAI 的 GPT-2:模型、宣传和争议

原文:https://towardsdatascience.com/openais-gpt-2-the-model-the-hype-and-the-controversy-1109f4bfd5e8?source=collection_archive---------3-----------------------

上周四,OpenAI 发布了一个叫做 GPT-2 的超大型语言模型。该模型可以基于一些种子文本生成各种风格的真实文本,从新闻文章到同人小说。有争议的是,他们决定不公布他们最大模型的数据或参数,理由是担心潜在的滥用。已经是 了。

我决定开一个博客,这样我就可以写这个了,因为我还没有看到一个帖子说了我想说的所有事情。我认为,对于机器学习社区来说,处理机器学习研究的潜在滥用是非常重要的。我还谈到了这项研究的技术价值,人类语言生成的社会意义,以及对 OpenAI 受炒作生成驱动的指责。

(免责声明:2017 年 2-8 月在 OpenAI 实习,认识一些参与这项研究的人。这里陈述的观点是我自己的。)

这项研究有什么好处吗?

我曾经致力于基于神经网络的对话系统,它被训练成在给定对话中先前响应的情况下预测下一个响应。我记得在 2016 年末,我浏览了我们的模型生成的样本,试图找到一个听起来似乎符合对话背景的句子。

所以当我读到 GPT 2 的讲英语独角兽的故事时,我相当震惊(如果你还没读过,我强烈推荐)。这个故事并不完美,中间有一些摇摆,但总的来说,它非常连贯。这实际上听起来像是一篇人类可以写的新闻文章。对我来说,不管采摘了多少樱桃,这都是一个令人难以置信的结果。如果有一个语言模型能够在没有显式记忆机制的情况下,在整篇文档中正确地回忆起豪尔赫·佩雷斯的名字,我会对这个语言模型有一定的印象。这完全是另一回事。我可能对最近的语言生成文学有点过时,但我不知道有任何模型接近这种水平的连贯性、语法性、长期上下文的使用和世界知识。

要明确的是:这里没有算法的贡献。他们“只是扩大了”之前的研究。但是我认为确切地看到这些放大的模型有多强本身就是一个重要的贡献。回想起来,“当然,更多的数据和计算会给你更好的模型”,这很容易,但如果我上周三向一位同事展示了独角兽的故事,并告诉他们这是人工智能生成的,我认为他们不会相信我。

一些怀疑这个模型是否只是记忆文本的“模板”并在正确的时间重复它们。在的论文(附录 8.2)中讨论了这一问题,其中作者表明 GPT-2 的样本和它们的训练集之间的词重叠小于测试集和训练集之间的重叠。换句话说,GPT-2 表现出的记忆行为比随机选择的一部分人类文本要少。这似乎是相当令人信服的证据,表明该模型具有重要的泛化能力。

Figure 5 from the OpenAI GPT-2 paper. It shows the probability that GPT-2 samples (‘samples’) and human text from the test set (‘real’) have a certain % overlap with the training set. Much more of the ‘samples’ probability is at a lower % overlap.

我们应该对他们的结果持怀疑态度吗?关于 OpenAI 是否准确地呈现了他们模型的生成能力,有一个合理的问题。我个人希望看到他们输入 GPT-2 的输入数量,以获得显示的样本(即他们所谓的“元樱桃采摘”的程度)。然而,他们确实提供了数百个原始 GPT-2 样本的转储,这让我们对他们模型的能力有了更清晰的了解。他们还指出,对于每一篇高质量的 GPT-2 写作,需要多少样本才能实现,这在其他论文(包括我自己的论文)中并不常见。随着代码的发布,对我来说 OpenAI 的方法符合其他已发表的 NLP 论文的标准。

人为素质造假文本的社会影响

现在谈谈争议。OpenAI 决定不公布其最大的 GPT-2 模型的权重,并表示担心“大型语言模型被用来大规模产生欺骗性、偏见或辱骂性的语言。”让我们暂时把 GPT-2 是否能做到这一点的问题放在一边,首先问一下:如果我们有一个开源模型,可以生成无限的人类质量的带有特定信息或主题的文本,那会是坏事吗?

我想答案是肯定的。的确,人类已经可以写假新闻,政府已经招募了成千上万的人来为他们的议程写有偏见的评论。但是一个自动化系统可以:(1)让那些没有资源雇佣成千上万人的坏人发动大规模的虚假信息运动;以及(2)大幅增加国家行为者已经在进行的虚假信息运动的规模。这些活动之所以有效,是因为人们在很大程度上受到他们周围持有某种观点的人的影响,即使这种观点毫无意义。扩大规模应该相应地增加政府和公司对我们信仰的影响力。

为了解决这个问题,我们需要开始研究人工智能生成文本的检测方法。与虚假视频和语音检测相比,这将提出不同的挑战:虽然只需要一个高质量的虚假视频来影响人们的观点,但视频是非常高维的,并且可能更容易检测到由 ML 模型产生的 【伪像】。另一方面,人工智能生成的假文本必须在大规模下才能产生影响(否则人类可以做到),但由于文本由离散的单词组成,因此可能更难区分特定的文本片段是否是人工智能生成的,特别是如果它很短。

因此,有合理的理由认为,广泛发布一个完美的人类级别的文本生成器,而不考虑其含义,可能是一个坏主意。

AI 炒作,以及 OpenAI 的动机

还有另一个原因,许多人假设为什么 OpenAI 保留了他们的模型参数——为他们的研究增加宣传价值。理论是,OpenAI 知道新闻媒体如果可以编造“AI 是危险的”叙事,就会更多地报道这项研究,因此保留了他们的模型,以便耸人听闻的新闻报道可以报道它们,从而增加公众对 OpenAI 的认可,并进一步巩固 OpenAI 的 AI 安全工作的感知价值。

OpenAI 还没有写他们与记者互动的方法,但我们可以填补一些空白。像其他工业实验室一样,OpenAI 显然关心公众的看法和认可。他们也明确地邀请记者写关于他们研究的故事(否则他们不会让 GPT 2 号接触他们)。最重要的是,由于 OpenAI 是一个非营利组织,他们获得了更大的优势来宣传他们的研究,因为这可能会增加捐款,从而增加他们做更多研究的预算。很难知道 OpenAI 对关于他们的新闻有多大的控制力,但是一些关于 GPT-2 的头条文章相当具有启示性。

那么我们怎么知道 OpenAI 的首要动机不是为了获得更多的影响力和金钱呢?简短的回答是:我们没有。我们不得不相信他们的话,他们真的关心他们研究的社会影响。对我来说,这并不特别难以置信,因为我个人认识很多这样的人。

但许多研究人员似乎不愿意给出积极的意图:他们认为 OpenAI 要么是一个认为他们将拯救世界的“比你更神圣”的机构,要么是一个被“AI 奇点”概念误导并致力于制造恐惧的团体,要么是埃隆·马斯克旨在最大限度地扩大新闻报道的自我傀儡,或者是两者的某种组合。他们名字中的“开放”一词,加上他们对媒体的过度关注和与埃隆的联系,似乎酝酿了一种特殊的仇恨,这种仇恨已经蔓延到 Twitter 和 Reddit 上,作为对 GPT-2 宣布的回应。

这些批评值得讨论,也包含了一些事实(除了,据我所知,埃隆已经不再是 OpenAI 董事会的了,而且已经有一段时间没有影响他们的决策了)。媒体对人工智能研究的扭曲是一个真正的问题,因为媒体炒作导致工业实验室受到过度关注,这欺骗了其他地方的研究人员。关于大实验室公关在影响公众对人工智能的看法方面的作用,将会有一场重要的讨论。

但是我敦促旁观者暂时把他们对 OpenAI 的判断放在一边(你可以稍后继续),想想这里到底发生了什么。作为 ML 研究人员,我们正在创造影响人们的东西。迟早,我们会越过一条线,我们的研究可以被恶意利用来做坏事。我们是否应该等到这种情况发生时再决定如何处理可能有负面副作用的研究?

机器学习社区中的杰出人物不屑一顾的讽刺性回应让我特别失望。我不会详细讨论这一点,但我认为这使人们对 ML 的社会影响的轻视态度正常化了。如果你是这个领域的新手,你看到一个很酷的著名研究人员对那些没有发布他们愚蠢的 ML 模型的书呆子开了一个玩笑,你很可能会吸收这些判断而不进行批判性思考(至少,我在硕士期间很容易受到著名人工智能研究人员的影响)。我觉得这个帮助不大。

一名研究人员在 Twitter 上评论说,DeepMind 本可以在发布 WaveNet 时做一些类似的事情,这是一种生成高质量人类语音的模型,他们对没有这样做负有更大的社会责任(他们在的首次发布中根本没有提到道德影响)。诚然,OpenAI 的研究没有什么特别或神奇的地方——其他实验室已经做了一些研究,这些研究本可以被搁置。一些工业实验室确实有公平团队在发布前审查研究,但我们作为一个领域不知道他们使用什么规范或他们执行什么标准。OpenAI 似乎是唯一一个公开考虑他们的机器学习研究的伦理影响的工业实验室。即使他们的主要动机是贪婪或炒作,我认为他们提出的问题值得认真对待。

继续前进:开始关于社会影响的对话

GPT-2 模型真的保证了这种程度的谨慎吗?很难说。诸如此类的决定引发了许多问题:这种做法真的会让不良行为者推迟多久才能重现这一结果?再现性的代价是什么?无害的研究和危险的研究之间的界限在哪里?我们如何负责任地与记者接触,以准确报道这些进展?在这种情况下,GPT-2 是否足够良性,应该完全释放?OpenAI 是否应该向研究人员提供有限的访问权限,以确保可重复性?或者他们根本就不应该发布那篇论文?OpenAI 似乎愿意参与关于这些问题的讨论(他们在博客帖子的底部发了一封电子邮件征求反馈),但这还不够:这些讨论应该公开进行,而不是通过电子邮件交流。

这是最重要的一点:机器学习社区真的真的需要开始公开讨论我们的伦理研究发布标准。 我们需要一个不是推特的场地。一种可能是一个研讨会,可能与 ICLR、ICML 或 NeurIPS 等大型 ML 会议设在同一地点,在那里我们可以集思广益,讨论我们希望作为一个领域采用什么规范。我可以想象一种“安全清单”(类似于最近的“再现性清单”),鼓励研究人员在发布他们的工作之前遵守。像生物技术和网络安全领域一样,我们正在接近这样一个点,即一小部分 ML 论文有可能被滥用。这应该足够让我们开始做些什么了。

有机器学习研究人员正在阅读这种思维:“这整个情况是荒谬的,AI 无论如何都不会真正工作。让我回去训练我的模型。”这是问题的一部分:从内部来看,经常感觉进步是递增的,没有什么事情像它应该的那样工作(尤其是 RL)。但是 ML research 已经在现实世界中产生了影响(例如,对贷款申请做出决策法院判决人员招聘等)。).这些算法中的偏见现在正在被暴露出来,但这是在它们首次实施多年之后,同时它们对人们的生活产生了严重影响。

随着我们的系统变得更有能力(它们最终会变得更有能力),我们将能够做越来越棒的事情,并有希望让世界变得更好。但是滥用的可能性也将显著增加。如果大多数人工智能研究人员在发布他们的研究成果之前没有考虑到它们的社会影响,那些关心的人将不断地追赶。如果我们想把机器学习给世界带来的伤害降到最低,这是不够的。

感谢 Alex Irpan 和 Jean Harb 在这篇文章中给出了非常棒的反馈,感谢 Natasha Jensen 提出了“安全清单”的想法。

OpenAI 的捉迷藏发现,系统视角

原文:https://towardsdatascience.com/openais-hide-and-seek-findings-the-systems-perspective-4d2df857437a?source=collection_archive---------11-----------------------

是的,代理商作弊了,但这对系统意味着什么?

OpenAI 发布了一个关于多智能体捉迷藏模拟中获得的一些结果的神奇作品,在该模拟中,多个隐藏者和多个寻找者玩这种流行的儿童游戏。

该模拟有一些有趣的方面,如工具(盒子、斜坡、墙壁),代理可以使用这些工具来帮助他们实现有效隐藏/寻找的目标。然而,更值得注意的结果是,环境的扩展模拟导致了涌现行为;也就是说,根本没有计划或意想不到的行为。

例如,一些预期的行为是隐藏者最终将学会用墙和/或盒子建造一个围栏,以隐藏坡道,不让搜索者看到。这样,坡道就不能被用来越过墙壁,从上面进入已建成的围墙。现在,环境设计者没有预料到的(紧急行为)是,搜索者会知道他们可以使用斜坡到达一个盒子的顶部,然后使用一个奔跑的动作来基本上“冲浪”盒子到他们喜欢的任何地方!

使用这种方法,搜索者找到了一种从上方接近隐藏建筑的方法,这不是系统设计者的意图!

探索者欺骗了系统。

现在,你认为隐藏者对这种行为的反应是什么?你们中的一些人可能会认为,既然搜索者已经在某种程度上了解了系统的未定义行为,那么隐藏者可能会做出一些荒谬的反应,因为系统现在处于混乱状态。

但是仔细想想。系统没有处于任何未知状态。

虽然它可能处于设计者没有明确打算创造的状态,但代理人继续以他们认为对他们期望的结果最佳的方式运作。

因此,隐藏者学会了瘫痪搜索者的冲浪能力!

他们通过使用预先分配的初始时间来做到这一点,在该时间内,搜索者被冻结锁定所有的箱子和坡道。然后,他们利用剩下的任何时间,用可移动的墙壁建造一个快速的围栏,然后锁定墙壁。这样,搜索者现在再一次没有办法进入围栏内部(至少,这是他们的想法……)。干得好,伙计们。

我认为这很吸引人,但与 OpenAI 的大多数分析所关注的水平不同。他们确实提到代理会找到进入系统的方法:

“[……]代理制定了[……]战略和反战略,其中一些我们不知道我们的环境支持”

然而,他们随后只深入到代理人了解的场景的细节,而完全忽略了环境设计缺陷本身。我觉得后者是更有趣的现象!我想颠倒一下分析——现在让我们保持代理设计不变,改变环境的状态结构和奖励系统。分析不同的激励/响应系统如何诱导不同的代理策略。强化学习的领域进展惊人,尤其是在最近几年。短短几十年间,我们已经从跳棋解算者变成了围棋冠军——我们的智能体建模越来越棒了。现在,我们的多智能体环境建模怎么样了?

多智能体环境设计

OpenAI 当然也想过。根据他们的最后一段,

构建环境并不容易,通常情况下,代理会找到一种方法,以一种意想不到的方式利用您构建的环境或物理引擎。

@BonsaiAI 在 Medium 上写的一篇关于奖励函数设计的文章提到“你得到你所激励的,而不一定是你想要的。”这很好地总结了为某一特定结果设计奖励系统的内在困境。你当然知道你的激励系统将如何使整个系统达到期望的状态,但是你有没有考虑到你的系统中可能存在一些“裂缝”的所有细微之处?显然,这说起来容易做起来难。这种“意图与结果”的分歧在我们的日常生活中随处可见,无论是职业还是非职业:

  • 软件工程师打算将文档化的规范转化为功能软件,忠实地再现文档化的变更。
  • 公司高管打算根据员工为公司整体提供的价值,给予他们适当的报酬。
  • 运动队经理打算运用比赛计划和球员阵容来战胜每一个连续的对手。
  • 等等…

对于所有这些情况来说,一个坚定而简洁的事实是,系统的行为完全符合其设计的;没有意料之外的后果,只有意料之外的后果。

为了让这个想法更清楚,让我们把补偿场景看得更远一点。假设有接近公司中层的员工对他们的薪酬不满意,并且对薪酬结构的整体设计有异议(假设整个组织都知道该结构)。这些员工可能会说“这个系统坏了”或“这里发生的事情是错误的”。然而,在这种情况下(假设有一个富有同情心和公正的设计者),不能说的是“这个系统没有做它被设计的事情。”

当然是啦!它正在做它被指示做的事情!如果它应该做一些与现在不同的事情,那么它就应该这样改变。现在,我们可能已经打算让系统做一件事,但这可能是也可能不是最终的设计。然而,不管意图如何,正在发生的事情是被选中的系统的完美再现。

新领域

我很高兴看到更多的理论围绕环境激励系统的有效设计而发展,尤其是在多主体场景中。像这样的理论应用在我们的日常生活中随处可见,甚至是我们试图回答的关于彼此生活的最重要的问题。以下是一些例子:

  • 我们治理自己和他人的最佳方式是什么?[ ]
  • 组织我们如何定义和相互交换价值的最佳方式是什么?
  • 为了共同的最终产品或创作,相互协作的最佳方式是什么?

只要举一两个这样的例子,你就会有足够的动力去做这件事。这很好……因为这一领域的研究在某些方面刚刚起步。例如,我想象有太多的历史出版物对政府、经济体系和管理层级等事物进行系统层面的分析。然而,所有这些优势将很快与多智能体 RL 的最新进展结合起来。这些理论家族之间的重要相似性和差异有可能导致人类系统和计算机代理系统等主题的知识和应用的爆炸。

结论

无论代理人是人类还是数字,系统总是被游戏化的。

对于防止/检测/打击利用激励系统的有效方法,您有什么想法?

你所知道的一些有趣的“永恒的”学术著作是什么,它们分析了人类/智能体系统?

多智能体 RL 中的奖励设计也是如此吗?

您在这里还看到了哪些我没有提到的应用?

[ ]:我期待着有一天,选举候选人提出的政策可以通过模拟来评估,让电视辩论的马戏变得毫无用处

OpenCV 静态显著性检测简而言之

原文:https://towardsdatascience.com/opencv-static-saliency-detection-in-a-nutshell-404d4c58fee4?source=collection_archive---------11-----------------------

寻找佼佼者

Photo by Justin Ha on Unsplash

显著性是图像的突出部分,使我们的大脑能够专注于该部分。当我们看到一幅图像时,这就是我们所关注的,引人注目的区域。比如,你有没有在广告中看到一些有趣的东西,让你停下来看一会儿?这就是广告的显著之处,即使你只是看了一眼,也能吸引你的兴趣。

安装 OpenCV

首先,你需要安装 OpenCV 库。如果您已经安装了 pip,您可以通过运行这些命令来完成。

> pip install opencv-python
> pip install opencv-contrib-python

要验证安装,您可以运行以下命令。

> python
Python 3.6.3 (v3.6.3:2c5fed8, Oct  3 2017, 18:11:49)
Type "help", "copyright", "credits" or "license" for more information.
>> import cv2
>> cv2.saliency
  <module 'cv2.saliency'>

静态显著性检测

有许多方法来检测显著性。在 OpenCV 中,为显著性检测提供的算法分为三类:

Saliency Diagram. Source : OpenCV Documentation

我们将讨论静态显著性。静态显著性检测算法使用允许检测非动态图像的显著对象的不同图像特征。OpenCV 中已经实现了两种算法,谱残差算法和细粒度算法。

光谱剩余

该算法分析输入图像的对数谱,在谱域中提取图像的谱残差,并提出一种快速构建显著图的方法,该显著图给出了原型物体的位置。

相似意味着冗余。对于以最小化冗余视觉信息为目标的系统,它必须知道输入刺激的统计相似性。因此,在可以观察到相当大的形状相似性的不同对数谱中,值得我们注意的是从平滑曲线中跳出的信息。我们认为,光谱中的统计奇点可能是图像中出现异常区域的原因,在这些区域中会弹出原型物体。

而如果你绘制显著图,你会得到下面的输出图像。

Spectral Residual

参考:侯、晓迪、。"显著性检测:一种谱残差方法."计算机视觉与模式识别,2007。07 年的 CVPR。IEEE 会议。IEEE,2007 年。

细粒

人眼的视网膜由神经节细胞组成。有两种类型的神经节细胞,位于中心和偏离中心。中央对黑暗背景包围的明亮区域做出反应。偏心对明亮背景包围的黑暗区域做出反应。

该算法基于中心和偏心差计算显著性。

On-center and off-center ganglion cells and their approximation on computational models of visual saliency. Source: B. Wang and P. Dudek “A Fast Self-tuning Background Subtraction Algorithm”, in proc of IEEE Workshop on Change Detection, 2014

在我们的例子中,通过使用通过所谓的积分图像的
中心-周围差异的有效实现,我们演示了一种在原始图像分辨率下实时生成视觉显著性的细粒度特征图的方法。

如果你绘制显著图,你会得到下面的输出图像。

参考:B. Wang 和 P. Dudek,“一种快速自调整背景减除算法”,IEEE 变化检测研讨会论文集,2014 年

参考

[## OpenCV:cv::studential::studential 类引用

公共成员函数|受保护成员函数|受保护属性|所有成员的列表

docs . opencv . org https://docs . opencv . org/3.4/d9/DCD/classcv _ 1 _ 1 saliency _ 1 _ 1 saliency . html](https://docs.opencv.org/3.4/d9/dcd/classcv_1_1saliency_1_1Saliency.html)

打开黑盒:如何利用可解释的机器学习

原文:https://towardsdatascience.com/opening-black-boxes-how-to-leverage-explainable-machine-learning-dd4ab439998e?source=collection_archive---------15-----------------------

可解释-ML

使用 PDP、LIME 和 SHAP 制定可解释的决策,为利益相关方创造价值

随着机器学习和人工智能变得越来越受欢迎,越来越多的组织正在采用这项新技术。预测建模帮助流程变得更加高效,同时也让用户受益。人们可以根据你的专业技能和经验来预测你可能会挣多少钱。输出可能只是一个数字,但是用户通常想知道为什么给出这个值!

在本文中,我将展示一些创建可解释预测的方法,并引导您打开这些黑盒模型。

本文中使用的数据是美国成人收入数据集,通常用于预测某人的收入是低于 50K 还是高于 50K,这是一个简单的二元分类任务。你可以在这里获得数据,或者你可以在这里跟随笔记本

关于个人关系、职业、种族、性别等信息的数据相对简单。

建模

分类变量是一次性编码的,目标设置为 0 (≤50K)或 1 (>50K)。现在,假设我们想要使用一个模型,该模型以其在分类任务上的出色性能而闻名,但是高度复杂,并且输出难以解释。这个模型应该是 LightGBM,它与 CatBoost 和 XGBoost 一起经常用于分类和回归任务。

我们首先简单地拟合模型:

from lightgbm import LGBMClassifier
X = df[df.columns[1:]]
y = df[df.columns[0]]
clf = LGBMClassifier(random_state=0, n_estimators=100)
fitted_clf = clf.fit(X, y)

我应该注意到,为了防止任何过度拟合,你最好将训练/测试分割为附加的维持数据。

接下来,我使用 10 重交叉验证快速检查模型的性能:

from sklearn.model_selection import cross_val_score
scores_accuracy = cross_val_score(clf, X, y, cv=10)
scores_balanced = cross_val_score(clf, X, y, cv=10,    
                                  scoring="balanced_accuracy")

有趣的是,scores_accuracy 给出了 87%的 10 倍平均准确度,而 scores_balanced 给出了 80%。事实证明,目标变量是不平衡的,25%的目标属于 1,75%属于 0。因此,选择正确的验证方法非常重要,因为它可能会错误地指出一个好的模型。

现在我们已经创建了模型,接下来将解释它到底做了什么。由于 LightGBM 使用高效的梯度推进决策树,因此解释输出可能会很困难。

部分相关性图(PDP)

部分相关性图(DPD)显示了某个特性对基于预测的模型的结果的影响。为了提取感兴趣特征的重要性,它在特征的分布上忽略了模型输出。我使用的包 PDPbox 可以在这里找到。

假设

这种重要性计算基于一个重要的假设,即感兴趣的特征与所有其他特征(除了目标)不相关。这样做的原因是它将显示很可能是不可能的数据点。例如,体重和身高是相互关联的,但是 PDP 可能会显示目标体重较大而身高很小的影响,而这种组合是极不可能的。这可以通过在 PDP 底部展示一块地毯来部分解决。

相互关系

因此,我们检查特性之间的相关性,以确保没有问题:

import seaborn as sns
corr = raw_df.corr()
sns.heatmap(corr, 
 xticklabels=corr.columns,
 yticklabels=corr.columns)

我们可以看到,这些特征之间不存在强相关性。但是,稍后我将进行一些一次性编码,为建模准备数据,这可能会导致相关特征的创建。

连续变量

PDP 图可用于显示变量对所有数据点输出的影响。让我们先从一个显而易见的开始,一个连续变量,即资本收益,对目标的影响:

from pdpbox import pdp
pdp_fare = pdp.pdp_isolate(
    model=clf, dataset=df[df.columns[1:]], model_features=df.columns[1:], feature='Capital_gain'
)
fig, axes = pdp.pdp_plot(pdp_fare, 'Capital_gain', plot_pts_dist=True)

x 轴表示 capital_gain 可以取的值,y 轴表示它对二元分类概率的影响。很明显,随着一个人的资本收益增加,他们赚< 50K 的机会也随之增加。请注意,底部的数据点有助于识别不常出现的数据点。

独热编码变量

现在,如果你有一次性编码的分类变量呢?您可能希望单独查看类别的效果,而不必单独绘制它们。使用 PDPbox,您可以同时显示对多个二元分类变量的影响:

pdp_race = pdp.pdp_isolate(
    model=clf, dataset=df[df.columns[1:]],    
    model_features=df.columns[1:], 
    feature=[i for i in df.columns if 'O_' in i if i not in 
                          ['O_ Adm-clerical', 
                           'O_ Armed-Forces', 
                           'O_ Armed-Forces',
                           'O_ Protective-serv', 
                           'O_ Sales', 
                           'O_ Handlers-cleaners']])
fig, axes = pdp.pdp_plot(pdp_race, 'Occupation', center=True, 
                         plot_lines=True, frac_to_plot=100,  
                         plot_pts_dist=True)

在这里,你可以清楚地看到,无论是管理职位还是技术职位,都积极地影响着挣更多钱的可能性。如果你在捕鱼业工作,这种机会会减少。

变量之间的相互作用

最后,变量之间的交互可能会有问题,因为 PDP 将为组合创建值,如果变量高度相关,这是不可能的。

inter1 = pdp.pdp_interact(
    model=clf, dataset=df[df.columns[1:]], 
    model_features=df.columns[1:], features=['Age', 'Hours/Week'])
fig, axes = pdp.pdp_interact_plot(
    pdp_interact_out=inter1, feature_names=['Age', 'Hours/Week'], 
    plot_type='grid', x_quantile=True, plot_pdp=True)

这个矩阵告诉你,如果一个人 49 岁左右,每周工作大约 50 个小时,他可能会赚得更多。我应该注意的是,记住数据集中所有交互的实际分布是很重要的。有可能这个情节会向你展示一些很少或永远不会发生的有趣的互动。

局部可解释的模型不可知解释(LIME)

LIME 基本上试图远离导出全局特征的重要性,而是近似局部预测的特征的重要性。它通过获取行(或一组数据点)来进行预测,并基于该行生成虚假数据。然后,它会计算假数据和真实数据之间的相似性,并根据假数据和真实数据之间的相似性来估计更改的影响。我用的包可以在这里找到。

from lime.lime_tabular import LimeTabularExplainer
explainer = LimeTabularExplainer(X.values, feature_names=X.columns, 
                                 class_names=["<=50K", ">50K"], 
                                 discretize_continuous=True,
                                 kernel_width=5)i = 304
exp = explainer.explain_instance(X.values[i], clf.predict_proba, 
                                 num_features=5)
exp.show_in_notebook(show_table=True, show_all=False)

The output of LIME for a single row

输出显示了前 5 个变量对预测概率的影响。这有助于确定为什么您的模型会做出某种预测,而且还允许向用户进行解释。

不足之处

注意,LIME 试图为初始行寻找不同值的邻域(内核宽度)在某种程度上是一个可以优化的超参数。根据数据,有时您需要更大的邻域。找到正确的内核宽度需要一点反复试验,因为这可能会损害解释的可解释性。

沙普利附加解释(SHAP)

一个(相当)近期的发展是 Shapley 值在机器学习应用中的实现。本质上,SHAP 使用博弈论来跟踪每个变量的边际贡献(T2)。对于每个变量,它从数据集中随机抽取其他值,并计算模型得分的变化。然后,对每个变量的这些变化进行平均,以创建一个汇总分数,但也提供了某些变量对于特定数据点的重要性的信息。

点击此处查看我在分析中使用的软件包。要更深入地了解 SHAP 的理论背景,请点击这里

可解释性的三个公理

SHAP 因其满足可解释性三个公理的能力而广受好评:

  • 任何对预测值没有影响的要素的 Shapley 值都应该为 0(虚拟)
  • 如果两个特征将相同的值添加到预测中,则它们的 Shapley 值应该相同(可替代性)
  • 如果您想要合并两个或更多预测,您应该能够简单地添加根据单个预测计算的 Shapley 值(可加性)

二元分类

让我们看看,如果我们要计算单行的 Shapley 值,结果会是什么:

import shap
explainer = shap.TreeExplainer(clf)
shap_values = explainer.shap_values(X)
shap.initjs()
shap.force_plot(explainer.expected_value, shap_values[1,:],  
                X.iloc[1,:])

Shapley values for a single data point

该图显示了用于指示预测方向的基值。由于大多数目标都是 0,所以看到基值为负并不奇怪。

红色条表示如果 Eeducation _ num为 13,目标为 1 (>50K)的概率增加了多少。高等教育通常会带来更多的收入。

蓝条显示这些变量降低了概率,其中年龄的影响最大。这是有道理的,因为年轻人通常挣得更少。

回归

当涉及回归(连续变量)而不是二元分类时,Shapley 直观地工作得更好。仅举一个例子,让我们训练一个模型,从相同的数据集中预测年龄:

# Fit model with target Age
X = df[df.columns[2:]]
y = df[df.columns[1]]
clf = LGBMRegressor(random_state=0, n_estimators=100)
fitted_clf = clf.fit(X, y)# Create Shapley plot for one row
explainer = shap.TreeExplainer(clf)
shap_values = explainer.shap_values(X)
shap.initjs()
i=200
shap.force_plot(explainer.expected_value, shap_values[i,:], X.iloc[i,:])

Shapley values for a single data point

在这里,你可以很快观察到,如果你从未结过婚,预测的年龄会降低大约 8 岁。与分类任务相比,这更有助于解释预测,因为您直接谈论的是目标的值而不是其概率。

独热编码特征

加法公理允许对所有数据点上的每个特征的 Shapley 值求和,以创建平均绝对 Shapley 值。换句话说,它赋予全局特征重要性:

shap.summary_plot(shap_values, X, plot_type="bar", show=False)

但是,您可以立即看到使用一次性编码要素的 Shapley 值的问题,这些值是为每个一次性编码要素显示的,而不是它们最初表示的内容。

幸运的是,加法公理允许将每个一位热编码生成特征的 Shapley 值相加,作为整个特征的 Shapley 值的表示。

首先,我们需要对独热编码特征的所有 Shapley 值求和:

summary_df = pd.DataFrame([X.columns, 
                           abs(shap_values).mean(axis=0)]).T
summary_df.columns = ['Feature', 'mean_SHAP']mapping = {}
for feature in summary_df.Feature.values:
    mapping[feature] = featurefor prefix, alternative in zip(['Workclass', 'Education',  
                                    'Marital_status', 'O_',  
                                    'Relationship', 'Gender',   
                                    'Native_country', 'Capital',  
                                    'Race'],
                                   ['Workclass', 'Education', 
                                    'Marital_status', 'Occupation', 
                                    'Relationship', 'Gender', 
                                    'Country', 'Capital', 'Race']):
        if feature.startswith(prefix):
            mapping[feature] = alternative
            break

summary_df['Feature'] = summary_df.Feature.map(mapping)
shap_df = (summary_df.groupby('Feature')
                    .sum()
                    .sort_values("mean_SHAP", ascending=False)
                    .reset_index())

现在,所有 Shapley 值都是所有要素的平均值,并对唯一热码编码要素求和,我们可以绘制最终的要素重要性:

import seaborn as sns
import matplotlib.pyplot as plt
sns.set(style="whitegrid")
f, ax = plt.subplots(figsize=(6, 15))
sns.barplot(x="mean_SHAP", y="Feature", data=shap_df[:5],
            label="Total", color="b")

我们现在可以看到职业比最初的 Shapley 概要情节显示的要重要得多。因此,在向用户解释特性的重要性时,一定要充分利用附加性。他们可能更感兴趣的是职业有多重要,而不是具体的职业

结论

虽然这肯定不是第一篇讨论可解释和可说明的 ML 的文章,但是我希望这有助于您理解在开发您的模型时如何使用这些技术。

围绕 SHAP 有一个重要的讨论,我希望使用一键编码的特性来演示可加性公理会给如何使用这种方法带来更多的直觉。

感谢您的阅读!

如果你像我一样,对人工智能、数据科学或心理学充满热情,请随时在 LinkedIn 上添加我,或者在 Twitter 上关注我。

本文中的所有示例和代码都可以在这里找到:

https://github.com/MaartenGr/InterpretableML

任何反馈和意见,一如既往,非常感谢!

OpenML:作为社区的机器学习

原文:https://towardsdatascience.com/openml-machine-learning-as-a-community-d678306e1a7e?source=collection_archive---------17-----------------------

OpenML 是一个在线机器学习(ML)实验数据库,每个人都可以免费使用。其核心思想是拥有一个数据集和 ML 实验结果的单一存储库。尽管近年来获得了很大的流行,现在有太多的工具可用,大量的 ML 实验继续在筒仓中发生,并且不一定作为一个完整的共享社区。

在这篇文章中,我们将尝试简要了解 OpenML 提供了什么,以及它如何适应我们当前的机器学习实践。

让我们直接通过建立一个简单的机器学习模型来让我们的手变脏。如果我们寻找的是简单性,那就是我们将要使用的 虹膜数据集 。在下面的示例脚本中,我们将加载 scikit-learn 提供的 Iris 数据集,使用 10 重交叉验证来评估 10 棵树的随机森林。听起来很琐碎,而且实际上不到 10 行代码。

一个简单的脚本,我们实现了平均准确率为 95.33%。那很容易。令人惊讶的是,我们已经在 ML 工具上取得了如此大的进步,使得入门变得非常容易。因此,我们每天都有成千上万的人使用这些工具。这不可避免地导致了车轮的重新发明。每个单独的 ML 从业者执行的任务通常有很大的重叠,可以通过重用来自社区的人已经完成的任务来省略。说到底,我们并没有从头开始构建一个随机的森林模型。我们很乐意重用来自社区的慷慨人士编写的代码。我们这个物种的特殊属性是作为一个集体工作的能力,在这个集体中,我们的智慧总和大于个体的总和。为什么不为 ML 做同样的事情呢?我的意思是,我可以看看其他 ML 从业者做了什么来在 Iris 数据集上获得更好的分数吗?

回答这个问题是这篇文章的目标之一。我们将随后在 OpenML 的帮助下探索这是否可行。然而,首先,我们应该简单地熟悉一些术语,看看我们如何将前面看到的例子分解成模块化组件。

OpenML 组件

Image Source: https://medium.com/open-machine-learning/openml-1e0d43f0ae13

数据集 : OpenML 容纳了超过 2k+ 的活跃数据集,用于各种回归、分类、聚类、生存分析、流处理任务等。任何用户都可以上传数据集。一旦上传,服务器计算数据集上的某些元特征— 类的数量缺失值的数量特征的数量等。关于我们前面的例子,下面一行相当于从 OpenML 中获取一个数据集。

X, y = datasets.load_iris(return_X_y=True)

任务:一个任务链接到一个特定的数据集,定义目标/因变量是什么。还规定了评估措施,如— 准确度、精度、曲线下面积等。或者要使用的估计程序的种类,例如 10 重交叉验证、n%维持集等。关于我们之前的例子,下面函数调用的参数捕获了任务的思想。

scores = cross_val_score(clf, X, y, cv=5, scoring='accuracy')

流程:描述要执行的建模种类。它可以是一个流程或一系列步骤,即 scikit-learn 管道。现在,我们已经使用了一个简单的随机森林模型,它是这里的组件。

clf = RandomForestClassifier(n_estimators=10, max_depth=2)

运行:将一个流程任务配对在一起,产生一个运行运行具有由服务器转化为评估的预测。这被该行的执行有效地捕获:

scores = cross_val_score(clf, X, y, cv=5, scoring='accuracy')

现在,这可能看起来有点混乱,因为我们正在尝试划分一个简单的 10 行代码,它工作得很好。然而,如果我们花几秒钟浏览一下上面解释的 4 个组件,我们可以看到,它使我们在 Iris 上对随机森林的训练成为一系列模块化任务。模块是计算机科学中的一个基本概念。它们就像乐高积木。一旦我们有了模块,就意味着我们可以轻松地即插即用了。下面的代码片段试图使用所描述的 OpenML 组件的思想重写前面的例子,以展示我们在实验中可能获得的收益。

因此,我们可以组合各种不同的任务、流程,它们是独立的操作。然后,运行可以将任何这样的任务和流配对,以构建一个 ML 工作流并返回评估的分数。这种方法可以帮助我们一次性定义这样的组件,并且我们可以将其扩展到数据集、模型的任何组合,以及将来的任何数量的评估。想象一下,如果整个 ML 社区定义这样的任务和他们在日常实践中使用的各种简单到复杂的流程。我们可以构建定制的 ML 工作流水线,甚至可以将我们的技术在同一个任务上的表现与其他人进行比较!OpenML 正是以此为目标。在这篇文章的下一部分,我们将触及 OpenML 的表面,看看我们是否真的可以用 OpenML 做它承诺的事情。

使用 OpenML

OpenML-Python 可以使用 pip 或者通过克隆 git repo 并安装当前开发版本来安装。那么我们应该安装 OpenML 吗?;)如果在阅读本文时试用代码片段,将会非常有益。包含所有代码的 Jupyter 笔记本可以在这里找到。

现在我们已经有了 OpenML,让我们直接来弄清楚如何从那里获得 Iris 数据集。我们可以随时浏览 OpenML 网站搜索 Iris。那是一条容易的路线。让我们熟悉编程方法,并学习如何钓鱼。OpenML-Python API 可以在这里找到

从 OpenML 中检索虹膜

在下面的例子中,我们将列出 OpenML 中所有可能的数据集。我们可以选择输出格式。我将使用数据框架,这样我们就可以获得一个熊猫数据框架,并且可以得到一个简洁的表格表示来搜索和排序特定的条目。

列名表明它们包含关于每个数据集的元信息,在这种情况下,我们可以访问由数据帧形状表示的 2958 数据集。我们将尝试在名称列中搜索“虹膜,并使用版本列对结果进行排序。

好的,所以版本为 1 的虹膜数据集的 ID 为 61 。为了验证,我们可以在网站上查看数据集 ID 61 。我们可以看到,我们感兴趣的是原始的虹膜数据集——3 类 50 个实例,具有 4 个数字特征。然而,我们将按照承诺,以编程方式检索相同的信息。

有了合适的数据集,让我们简单回顾一下我们之前讨论过的术语。到目前为止,我们只使用了数据集组件。数据集组件与任务组件紧密相连。重申一下,任务将描述如何使用数据集。

从 OpenML 中检索相关任务

我们将首先列出 Iris 数据集的所有可用任务。然而,我们只是将 Iris 视为一个监督分类问题,因此将相应地进行过滤。接下来,我们将只收集与我们相关的任务的任务 id。

这也解决了任务组件。请注意,对于一个数据集 (61),我们获得了 11 个我们感兴趣的任务 id。这应该说明了数据集-任务组件可以具有的一对多关系。我们还有 2 个组件需要探索— 运行。我们可以列出所有可能的流,过滤出我们想要的,即随机森林。然而,让我们取而代之的是使用我们上面收集的 11 个任务在 Iris 数据集上进行的所有评估。

随后,我们将使用上传/使用最多的基于 scikit-learn 的任务。然后,我们将根据是否使用了随机森林,从所选任务中进一步筛选出评估列表(在本例中为 task_id= 59 )。

从 OpenML 中检索性能最佳的模型

因为我们是一群雄心勃勃的 ML 从业者,他们只满足于最好,也因为如果不匹配或击败最先进的技术,大多数结果将不会被认为是值得努力的。我们将根据分数或' ' 对过滤后的结果进行排序,然后从那个运行—任务流程中提取组件。

好吧,让我们暂停一下,重新评估一下。从全球多个将跑步上传到 OpenML 的用户来看,对于 Iris 上的随机森林跑步,目前看到的最好成绩是 96.67% 。这当然比我们当初构建的幼稚模型要好,以达到 95.33% 。我们使用了一个基本的 10 重交叉验证来评估一个最大深度为 2 的 10 棵树的随机森林。让我们看看最佳跑步使用了什么,以及它是否与我们的方法不同。

显然,我们最初的方法在两个方面是不同的。我们没有明确使用分层抽样进行交叉验证。而随机森林超参数也略有不同( max_depth=None )。这听起来绝对像是一件要做的事情,然而,我们没有理由把自己限制在随机森林中。记住,我们的目标是这里。考虑到 OpenML 用户的数量,肯定有人在 Iris 上用其他模型得到了更好的分数。然后让我们检索这些信息。当然是程序性的。

总之,我们现在将根据任务定义,使用 task_id=59 对 Iris 数据集上所有基于 scikit-learn 的模型的性能进行排序。

使用 SVM 的变体,在上传的结果中获得的最高分是 98.67% 。但是,如果我们检查相应的流描述,我们会发现它使用的是旧的 scikit-learn 版本(0.18.1 ),因此可能无法复制准确的结果。然而,为了提高我们 95.33%的分数,我们应该试着对同一个问题运行一个 nu-SVC ,看看我们站在哪里。让我们去争取吧。当然是通过 OpenML。

在所需任务上运行最佳性能流程

瞧啊!我们达到了神奇的数字。我个人从来没有尝试过 NuSVC,并且一直在调整随机森林的超参数。这无疑是一个新的发现。我想知道是否有人在 Iris 上尝试过 XGBoost?

无论如何,我们现在可以使用以下代码将这次运行的结果上传到 OpenML:

r.publish()

人们需要登录到https://www.openml.org/并生成他们各自的 apikey 。然后,结果将可供每个人查看,谁知道呢,你可以在 Iris 数据集上用你的名字来对比有史以来最好的性能!

这篇文章并不打算成为 OpenML 的终极指南。主要目标是帮助形成对 OpenML 术语的了解,介绍 API,建立与一般 ML 实践的联系,并让我们先睹为快作为一个社区一起工作的潜在好处。为了更好地理解 OpenML,请浏览文档。如果你想继续这篇文章中给出的例子并进一步探索,请参考 API

OpenML-Python 是一个开源项目,非常欢迎每个人以问题和请求的形式做出贡献。对 OpenML 社区的贡献实际上不仅限于代码贡献。每一个用户都可以通过使用 OpenML 共享数据、实验和结果来丰富社区。

作为 ML 从业者,我们可能依赖工具来完成我们的任务。然而,作为一个集体,我们可以在更大程度上挖掘其潜力。让我们一起,让 ML 更透明,更民主!

特别感谢 HeidibulgeSahithyaMatthiasAshwin 的想法、反馈和支持。

参考链接:

OpenPose,PNASNet 5 进行姿势分类比赛(Fastai)

原文:https://towardsdatascience.com/openpose-pnasnet-5-for-pose-classification-competition-fastai-dc35709158d0?source=collection_archive---------9-----------------------

我最近参加了一个当地的人工智能比赛,挑战包括 15 个不同类别的人体姿势分类。这是我第一次参加人工智能比赛,这是一次令人羞愧的经历。基于我们的模型准确性、创造力和团队合作,我的团队获得了亚军。我肯定会推荐学习者参加竞赛或黑客马拉松,因为它们是一个很好的网络平台和训练场地,可以磨练你的技术技能。在这里,我将向您介绍我们的模型构建过程,该过程最终帮助我们在最终测试集上实现了 83%的高准确率。

我们面临的挑战是开发一种图像分类算法,可以区分 15 种不同的人类姿势。

姿势是:

椅子式、儿童式、轻拍式、手枪式、握手式、HulkSmash 式、KoreanHeart 式、KungfuCrane 式、KungfuSalute 式、敬礼式、战士式、鹰式、胸部撞击式、高跪式和蜘蛛侠式

根据竞赛条款和条件,我们无权发布数据集。因此,以下所有图片都是我们在比赛期间拍摄的。

Left to Right— KoreanHeart, KungfuCrane, HandShake

训练数据集中的每个类包含大约 100 幅图像,而验证集中的每个类有 25 幅图像。对于 15 个类别的分类任务来说,这是相对少量的数据,说明了我们需要通过拍摄自己的图像来增加数据集。

penPose 是一种人体姿态估计和特征提取步骤,用于检测图像中的人体。使用该模型来标识各个身体部位的关键点,并且可以绘制连接这些关键点的人体骨架。从每幅图像中提取人体姿态作为预处理步骤,以减少数据中的噪声。

通过大量参考这个站点,我们使用预先训练好的 MPII 模型生成了每张图像的关键点。

cwd = os.getcwd()# Specify the paths for the 2 files
 protoFile = "{}/pose_deploy_linevec_faster_4_stages.prototxt".format(cwd)
 weightsFile = "{}/pose_iter_160000.caffemodel".format(cwd)
 nPoints = 15
 POSE_PAIRS = [[0,1], [1,2], [2,3], [3,4], [1,5], [5,6], [6,7], [1,14], [14,8], [8,9], [9,10], [14,11], [11,12], [12,13] ]

 # Read the network into Memory
 net = cv2.dnn.readNetFromCaffe(protoFile, weightsFile)frameWidth = 640
 frameHeight = 480
 threshold = 0.1# Forward training set into OpenPose model to generate outputinWidth = 299
 inHeight = 299m = train_images.shape[0]
 train_outputs = np.zeros((1,44,38,38))for i in range(m):
   inpBlob = cv2.dnn.blobFromImage(train_images[i], 1.0/255,    (inWidth, inHeight),(0, 0, 0), swapRB=True, crop=False)net.setInput(inpBlob)
   output = net.forward()
   train_outputs = np.vstack((train_outputs,output))

 outputs = np.delete(train_outputs,(0),axis=0)
 H = train_outputs.shape[2]
 W = train_outputs.shape[3]
 print(train_outputs.shape)# Generate keypoints for training set
 m = 973
 H = 38
 W = 38train_points = np.zeros((m,15,2))for sample in range(m):
   for i in range(nPoints):
       # confidence map of corresponding body's part.
       probMap = train_outputs[sample, i, :, :]# Find global maxima of the probMap.
       minVal, prob, minLoc, point = cv2.minMaxLoc(probMap)# Scale the point to fit on the original image
       x = (frameWidth * point[0]) / W
       y = (frameHeight * point[1]) / H
       if prob > threshold :
           train_points[sample,i,0] = int(x)
           train_points[sample,i,1] = int(y)

接下来,使用存储在变量 train_points 中的关键点,在每幅图像上绘制一个人体骨架。

# Processed images with sticks on original image
 train_processed = np.copy(train_images).astype(np.uint8)for sample in range(m):
   for point in range(nPoints):
     if train_points[sample,point,0] !=0 and train_points[sample,point,1] !=0 :
       cv2.circle(train_processed[sample], (int(train_points[sample,point,0]), int(train_points[sample,point,1])), 10, (255,255,0), thickness=-1, lineType=cv2.FILLED)

     # draw lines 
     for pair in POSE_PAIRS:
       partA = pair[0]
       partB = pair[1]if train_points[sample,partA,0] != 0 and train_points[sample,partA,1] != 0 and train_points[sample,partB,0] != 0 and train_points[sample,partB,1] != 0:
          cv2.line(train_processed[sample], (int(train_points[sample,partA,0]),int(train_points[sample,partA,1]))
                   , (int(train_points[sample,partB,0]),int(train_points[sample,partB,1])), (255,255,0), 3)# Processed images with sticks on a black backgroundtrain_processed_grey = np.zeros((m,train_images.shape[1],train_images.shape[2],1)).astype(np.uint8)for sample in range(m):
   for point in range(nPoints):
     if train_points[sample,point,0] !=0 and train_points[sample,point,1] !=0 :
       cv2.circle(train_processed_grey[sample], (int(train_points[sample,point,0]), int(train_points[sample,point,1])), 10, (1), thickness=50, lineType=cv2.FILLED)

     # draw lines 
     for pair in POSE_PAIRS:
       partA = pair[0]
       partB = pair[1]if train_points[sample,partA,0] != 0 and train_points[sample,partA,1] != 0 and train_points[sample,partB,0] != 0 and train_points[sample,partB,1] != 0:
          cv2.line(train_processed_grey[sample], (int(train_points[sample,partA,0]),int(train_points[sample,partA,1]))
                   , (int(train_points[sample,partB,0]),int(train_points[sample,partB,1])), (1), 3)

通过这一步,我们获得了 3 个不同的数据集;

  1. 原象
  2. 原始图像+骨架叠加
  3. 背景空白的骨架

T 转移学习允许我们使用比从头开始训练算法所需的数据少得多的数据来训练深度神经网络。它还经常导致更高精度的模型,因为来自大数据集的信息被转移和训练以适合我们的数据。对于这次比赛,我的团队决定测试 3 个预训练模型的性能,即 ResNet-50、ResNeXt-101 和 PNASnet-5。所有模型都是使用 fastai 库构建的。

import fastai
 from fastai.metrics import error_ratefrom torchvision.models import *
 import pretrainedmodels
 from fastai.callbacks.tracker import SaveModelCallback
 from fastai.vision import *
 from fastai.vision.models import *
 from fastai.vision.learner import model_metabs = 8# Importing of datasetdata = ImageDataBunch.from_folder(base_dir,train='train',valid='val', ds_tfms = get_transforms(), size =299, bs=bs).normalize(imagenet_stats)#ResNet-50
 models.resnet50#ResNeXt-101def resnext101_64x4d(pretrained=True):
     pretrained = 'imagenet' if pretrained else None
     model = pretrainedmodels.resnext101_64x4d(pretrained=pretrained)
     all_layers = list(model.children())
     return nn.Sequential(*all_layers[0], *all_layers[1:])#PASNet-5def identity(x): return xdef pnasnet5large(pretrained=True):    
     pretrained = 'imagenet' if pretrained else None
     model = pretrainedmodels.pnasnet5large(pretrained=pretrained, num_classes=1000) 
     model.logits = identity
     return nn.Sequential(model)# Training of modellearn = cnn_learner(data, model, metrics = accuracy)learn.fit(20,callbacks=[SaveModelCallback(learn,monitor='accuracy',every="improvement",name ="top_acc")])learn.lr_find()
 learn.recorder.plot()learn.unfreeze()
 learn.fit_one_cycle(5,callbacks=[SaveModelCallback(learn,monitor='accuracy',every="improvement",name="top_acc_1")])

我们总共构建了 9 个模型,每个模型都用我们生成的数据集进行了预训练。以下是结果;

对于最终的测试集,我们使用在原始模型上训练的 PNASnet-5 模型预测了未知数据集的分类,并获得了 83%的准确率,使我们在比赛中获得了第三名。

这就是使用 PNASnet-5 预训练模型的人体姿势分类。令人失望的是,OpenPose 特征提取没有提高模型的准确性,但我相信在比赛的时间限制下,我们做得很好。对于那些想知道 PNASnet-5 如何比其他预训练模型表现得更好的人,下面是作者对算法的总结。

https://cs.jhu.edu/~cxliu/posters/pnas_poster.pdf

R-指派问题的运筹学

原文:https://towardsdatascience.com/operations-research-in-r-assignment-problem-4a1f92a09ab?source=collection_archive---------15-----------------------

r 代表工业工程师

探索“LP solve”R

Image by Momentista available at Unsplash

分配问题

指派问题是线性规划问题的特例;它是数学中最优化或运筹学分支中的基本组合优化问题之一。它的目标在于将 m 资源(通常是工人)一对一地分配给 n 任务(通常是工作),同时最小化分配成本。一般来说,所有的工作都必须由一个工人来完成,并且每个工人都必须被指派专门的工作。任何工人都可以被指派执行任何工作,产生一些费用,这些费用可能因工作任务的不同而不同。

基本符号:

  • m =职工人数( i = 1 … m
  • n =工作数量( j = 1 … n
  • c i,j =将工人 i 分配到工作 j 的单位成本
  • x i,j =分配给作业 j 的工人 i (如果分配则为 1,否则为 0)

注: m (工作人数)必须等于 n (工作人数)。

配方:

LP Assignment Problem — Formulation

LP Assignment Problem — Diagram

来自 R 的 lpSolve 包包含了解决线性规划指派问题的特定函数。对于下面的例子,让我们考虑下面要求解的数学模型:

LP Assignment Problem — Example

我们来看看 R 代码!

Assignment Problem R Code

解决方案:

LP Assignment Problem — Solution

总分配成本:27 美元

上表显示了在满足约束条件的情况下,分配给工作 j 的工人 i 的最佳组合。必须分别将员工 1 分配给职务 2,将员工 2 分配给职务 1,将员工 3 分配给职务 3。没有其他可能的分配组合会导致更低的分配成本。

总结想法

指派问题代表了用于以最佳方式分配资源(主要是劳动力)的线性规划问题的特殊情况;对于运营和项目经理来说,这是优化成本的一个非常有用的工具。LP solve R 包允许我们只用很少几行代码就能解决 LP 赋值问题。虽然有其他免费的优化软件(如 GAMS、AMPL、TORA、LINDO),但在您的个人代码库中存储 LP 分配问题 R 代码可以节省您大量的时间,因为您不必从头开始编写公式,而只需更改相应矩阵的系数和符号。

— —

如果你觉得这篇文章有用,欢迎在 GitHub 上下载我的个人代码。你也可以直接在 rsalaza4@binghamton.edu 给我发邮件,在LinkedIn上找到我。有兴趣了解工程领域的数据分析、数据科学和机器学习应用的更多信息吗?通过访问我的媒体 个人资料 来探索我以前的文章。感谢阅读。

罗伯特

R-运输问题的运筹学

原文:https://towardsdatascience.com/operations-research-in-r-transportation-problem-1df59961b2ad?source=collection_archive---------0-----------------------

r 代表工业工程师

探索“LP solve”R

Image by iplenio available at HDqwalls

运输问题

运输问题是一种特殊类型的线性规划问题,其中目标在于最小化给定商品从多个来源起点(例如工厂、制造设施)到多个目的地(例如仓库、商店)的运输成本。每个来源都有有限的供应(即可以从其发送的最大数量的产品),而每个目的地都有需要满足的需求(即需要运送到其的最小数量的产品)。从源头到目的地的运输成本与运输的数量成正比。

基本符号:

  • m =信号源数量( i = 1 … m )
  • n =目的地数量( j = 1 … n )
  • c i,j =从来源地 i 到目的地 j 的单位运输成本
  • x i,j =从来源 i 运送到目的地 j 的金额
  • a i =源头供应 i
  • b j =目的地需求 j

LP Transportation Problem Diagram

源由行表示,而目的地由列表示。一般来说,一个运输问题有 m 行和 n 列。如果恰好有( m + n -1)个基本变量,问题是可解的。

LP Transportation Problem Simplex Tableau

运输问题的类型

基于初始给定的信息,有两种不同类型的运输问题:

  • 均衡运输问题:总供给等于总需求的情况。
  • 不平衡运输问题:总供给不等于总需求的情况。当供给高于需求时,在等式中引入一个虚拟目的地,使其等于供给(运输成本为 0 美元);超额供应被认为会进入库存。另一方面,当需求高于供应时,在等式中引入一个虚拟源,使其等于需求(在这些情况下,不满足需求通常会产生惩罚成本)。

为了着手解决任何给定的运输问题,第一步是检验它是否平衡。如果不是,就要相应的平衡。

R 的 lpSolve 包包含了求解线性规划运输问题的特定函数。对于下面的例子,让我们考虑下面要求解的数学模型:

LP Transportation Problem — Mathematical Model

LP Transportation Problem — Simplex Tableau

我们来看看 R 代码!

Transportation Problem R Code

解决方案:

LP Transportation Problem Example — Solution

总运输成本:435 美元

上表显示了在满足供需约束的情况下,从供应商 i 到客户 j 的最优产品组合。没有其他可能的变量组合会导致更低的运输成本。

总结想法

运输问题代表了用于以最佳方式分配资源的特定类型的线性规划问题;对于经理和供应链工程师来说,这是一个优化成本的非常有用的工具。LP solve R 包只需要几行代码就可以解决 LP 运输问题。虽然有其他免费的优化软件(如 GAMS、AMPL、TORA、LINDO),但在你的个人代码库中存储一个 LP 运输问题 R 代码可以节省你大量的时间,因为你不必从头开始编写公式,而只需改变相应矩阵的系数和符号。

— —

如果你觉得这篇文章有用,欢迎在GitHub上下载我的个人代码。你也可以直接在 rsalaza4@binghamton.edu 给我发邮件,在LinkedIn上找到我。有兴趣了解工程领域的数据分析、数据科学和机器学习应用的更多信息吗?通过访问我的媒体 简介 来探索我以前的文章。感谢阅读。

-罗伯特

阿片类药物危机:政府在做什么?

原文:https://towardsdatascience.com/opioid-crisis-whats-the-government-doing-about-it-42f5f50fe6e4?source=collection_archive---------23-----------------------

现实世界中的数据科学

NIH 如何资助与阿片类药物相关的研究

如果你一直生活在岩石下,美国一直面临着巨大的公共健康危机。大约在 2006 年至 2012 年的高峰期,处方阿片类药物危机导致近 10 万人死亡(据《华盛顿邮报》报道)。

美国卫生与公众服务部(HHS)已经加大了各种努力,以打击用药过量,提高公众意识,并控制处方阿片类药物的供应。今天,我们想特别关注一下联邦政府是如何研究危机的各个方面的。你可以在这里找到这篇文章的代码,它涉及到更多的技术细节:https://github.com/TheLastQuestion/nihOpioidData

数据

每年,美国国立卫生研究院、国家科学基金会和其他联邦机构通过数百亿美元的拨款资助大约 100,000 个科研项目。关于受资助项目、赞助机构和受资助研究性质的数据可在 https://federalreporter.nih.gov下载。

NIH 每年在阿片类药物研究项目上花费多少?

项目术语字段提供了一个指示器,指示哪些项目与阿片类药物有关。NIH 在 2018 财年花费了 5.64 亿美元,占 NIH 在 2018 财年投入的以“阿片类药物”为关键术语的研究项目的 330 亿美元的 1.7%。在过去的几个财年中,这一研究领域在项目数量和总拨款方面都有了显著增长,从 2008 年到 2015 年,这一领域在 NIH 研究组合中所占的比例一直保持稳定。

哪些类型的项目属于“阿片类药物”范畴?

阿片类药物相关项目仅占过去十年 NIH 资助项目总数的 1%左右[注:实际数据是 11 个财政年度的项目]。但是对于一个人来说,它们仍然太多了,无法通读和综合。这就是自然语言处理可以助一臂之力的地方!

每个联邦记者项目都有一段很长的摘要(除了少数缺失的记录)。一种无监督的机器学习方法,称为“主题建模”,可以帮助我们摄取所有这些简单语言的摘要,然后根据这些摘要共有的和没有共有的单词将它们聚类成主题(更多技术细节见链接代码)。运行我们的模型将摘要分成 10 个主题,得到如下分布。

也许不出所料,最大的摘要集将健康研究术语(例如,“试验”、“试点”、“调查者”和“大学”)作为其最流行的主题。当然,这些只是对我来说有意义的标签——主题建模只提供最好地描述一个主题的单词列表,并在数学意义上将其与其他主题区分开来。解释是留给人类的(在链接的代码中有更多关于这个主题的说明)。

用这种方法发现的其他主题似乎涉及:

2)处方阿片类药物有助于解决的病症(疼痛、镰状细胞病、癌症、炎症……)

3)阿片类药物与 HIV 和其他免疫系统相关感染的交叉,

4)阿片类药物滥用的康复途径(戒断、渴求、结果、美沙酮…),

5)阿片样物质作用和滥用的分子基础(κ、配体、拮抗剂…),

6)神经系统相关(神经、抑制、通道、脊髓…),

7)不同的患者群体(退伍军人、孕妇、儿童、老人…),

8)抑郁和焦虑,

9)与阿片类药物(谷氨酸盐、γ-氨基丁酸、摄入……)相关的细胞机制,以及

10)阿片类药物与其他物质(吸烟者、烟草、注射、物质使用)的重叠。

随着时间的推移,阿片类药物的研究组合发生了怎样的变化?

现在我们有了一个粗略的方法来描述过去十年中资助了哪些类型的阿片类药物相关研究,我们可以检查这种组合是否随着时间的推移而发生了变化。

我们的分析表明,提及特定患者人群的项目最近流行率增加,而神经系统相关项目略有下降。但是,请注意,这只是阿片类药物标记项目的百分比趋势。就数量而言,在我们有数据可查的过去三个财年中,所有以阿片类药物为主题的家庭获得资助的项目数量都有所增加。

Project counts by topic over time

阿片类药物项目获得的资助金额与哪些因素有关?

对主题、组织状态和控制预算随时间的增长对财年成本进行线性回归,我们观察到与主题 4(“恢复之路”主题)相关的项目与第一个主题(“健康研究术语”)中的项目相比,增加了 100,000 美元。其他主题或者与第一个主题相比成本更低,或者与第一个主题没有显著差异(即 p 值超过 0.05)。

Truncated table of regression coefficients sorted by lowest p-value then highest coef value

与佛蒙特州和俄克拉荷马州组织相关的阿片类药物项目的项目成本/资金溢价最高。与这些州的组织相关联的项目比基线项目成本多 700,000 美元(在这种情况下,以阿拉巴马州相关联的项目为代表)。然而,请注意,这些州的数据相对较少——OK 组织只有 7 个阿片类药物项目,而 VT 组织只有 23 个。

结束

正如媒体记录的那样,阿片类药物的流行给美国家庭和社区带来了巨大而痛苦的代价。通过分析国家卫生研究院的资金数据,我们发现了联邦政府对此正在做些什么的几个答案。

1)研究滞后于当前事件——尽管阿片类药物危机(就死亡率而言)在 21 世纪后期已经开始,但 NIH 的阿片类药物相关研究组合直到很久以后才出现资金激增,大约从 2016 年开始。这种激增表现为获得阿片类药物项目的数量以及获得阿片类药物项目的美元的增加。

2)使用自然语言处理和主题建模,我们观察到涉及特定患者亚组的研究越来越重要。然而,从整体上看,过去 11 个财政年度的多个阿片类药物项目往往涉及阿片类药物的处方条件、艾滋病毒和其他感染以及依赖性和康复。

3)虽然项目总成本往往不会因主题领域的不同而有很大差异,但那些与复苏之路相关的项目似乎比大多数其他主题的项目获得了大约 100,000 美元的资助。某些国家的组织往往有较高的项目成本,但这可能是那些获得阿片类药物项目赠款相对较少的组织的人为因素。

*这篇文章和附带的分析不是美国联邦政府的官方观点。

最佳控制:LQR

原文:https://towardsdatascience.com/optimal-control-lqr-417b41e10d0d?source=collection_archive---------8-----------------------

在最优控制问题中吃掉你的蛋糕

在这篇文章中,我将谈论最优控制。更具体地说,我将谈论令人难以置信的令人敬畏的线性二次调节器,它在最优控制领域中经常使用,并且还将讨论最优控制和最近大肆宣传的强化学习之间的一些相似之处。令人着迷的是,它们的名称不同,但它们在连续的决策过程中处理类似的问题。也就是说,给读者一个友好的数学警告:

这篇文章包含了一些线性代数和微积分,但是不要惊慌,它很简单,你可以做到。

既然我们已经解决了这个问题,让我们开始吧。首先让我们定义一个一般的最优控制问题,或者更好地说一个最优化问题。这仅仅意味着我们想要最大化或最小化某个函数,该函数受变量的某些约束。典型的最优控制问题如下所示:

这是非常直接的,最小化一个函数【f】服从一些约束(s.t .是 subject to 的简称)。现在,在优化世界里,基于目标函数的样子和约束,这可能是任意困难的。当然,约束可以是基于问题的等式约束或不等式约束。不用说,优化问题中的非凸函数很难优化,但是在凸函数的情况下,我们可以高效快速地解决问题。无论如何,它是如此重要,以至于你在问题中寻找凸性的反应应该是这样的:

在控制问题中,我们优化我们的轨迹,以最小化成本函数,或者更确切地说,最大化回报,就像在强化学习中所做的那样。自然地,环境的动态,即基于当前动作和当前状态给出我们下一个状态的函数,是优化约束的一部分。因此,我们可以将控制优化问题写成如下:

这是直到 n 的有限范围的情况。让我们简单地分解它。x 是我们在每个时间步的状态变量,是我们的动作。 E 将是最终状态的最终成本, g 每个状态-动作对的成本函数。 x 条是我们想要优化的起始状态,而 f 是我们的动力学函数。在这种情况下,我们没有不等式约束。事实证明,如果我们的函数 f 是一次函数xu而函数 g 是二次函数u ,这就让问题简单了很多。这就是我们如何得出线性二次调节器问题的定义:**

这里, QRE 是定义我们多项式系数的代价矩阵。我们也可以用分块矩阵表示法写出每个时间步长的成本,以使表达式更简单:

In the upper case we leaved out the S or better to say we assumed that S = 0, but this doesn’t change the math greatly, S can also be some kind of matrix for interplay between x and u in the cost function.

我们将利用最优性原理,该原理陈述了一个自然事实,即如果在 A 点和 C 点之间有一条最优路线,如果我们在这条路线上选择 B 点,那么从 A 到 B 的子路线也是从 A 到 B 的最优路线。基于此,我们可以递归地定义我们轨迹的最优剩余成本,或总成本。这就是我们如何得出汉密尔顿-雅可比-贝尔曼方程的:

其中 J star 是我们的最佳出发成本。在我们的例子中,我们将目标函数描述为一个多项式函数,所以从逻辑上来说,我们可以假设我们的最佳行驶成本是一个多项式函数,我们可以这样写:

根据我们对优化问题的定义,逻辑上我们的最终成本如下:

现在,如果我们把函数 g 的定义和环境动力学代入贝尔曼方程,我们会得到这样的结果:

由于二次成本假设,我们如何找到这个函数的最小值?很简单,我们取相对于 u 的梯度,并使其等于 0,我们将所有项组合成一个大的中心矩阵:

为了节省空间,我们用下列矩阵代替这些术语(这是不言自明的):

将所有内容相乘后,只看包含的项,因为我们要对求导,所以我们得到以下中间结果:**

在计算梯度和重新排列之后,我们得到 u star 的表达式,它使成本最小化,即最优操作:

或许可以思考一下这个问题。这是什么意思?这意味着我们有最优行动的封闭解!这真是太棒了。那么我们需要什么来解决这个问题呢?我们需要时间步长 k+1 的矩阵 P。我们可以根据以下等式,从上一时间步开始递归计算:

这也是众所周知的代数黎卡提方程。在我们想要一个不动点解的情况下,对于无限长的地平线,方程可以求解一个固定的 P. 在这种情况下,我们甚至不需要一个递归。我们只是免费得到最优反馈控制。

基本上就这些了。你不得不欣赏 LQR 的力量。当然,许多问题不能简化为线性动力学,但是如果我们进行简化,我们会得到什么样的解决方案是令人惊讶的。这种方法甚至用在我们的动力学是非线性的情况下,通过泰勒展开使它们在固定点附近线性化。这是一种在复杂问题的轨迹优化中经常使用的方法,称为微分动态规划(DDP),其一个实例是 iLQR(迭代 LQR),go figure。

既然你获得了一些 LQR 赋,你就获得了理解最优控制中许多事情的工具。

我希望 LQR 的这个解释能让你有所启发。这是一个非常简单而强大的概念,也是许多最优控制算法的基础。

最佳估计算法:卡尔曼和粒子滤波器

原文:https://towardsdatascience.com/optimal-estimation-algorithms-kalman-and-particle-filters-be62dcb5e83?source=collection_archive---------6-----------------------

介绍卡尔曼和粒子滤波器及其在机器人和强化学习等领域的应用。

Photo by Daniel Jerez on Unsplash

最优估计算法

最优估计算法在我们的日常生活中起着非常重要的作用。今天,我将使用一些实际示例向您介绍其中的两种(卡尔曼滤波器和粒子滤波器)。

让我们想象一下,我们正驾驶着一辆无人驾驶汽车,我们即将穿过一条长长的隧道。在这个例子中,我们的汽车使用不同的传感器,如 GPS 估计、加速度计和摄像头,以便跟踪它在地图中的位置以及它与其他车辆或行人的交互。尽管如此,当在隧道中行驶时(特别是在一个很长的隧道中),我们的 GPS 信号会因为干扰而变弱。因此,我们的汽车估计它的位置可能变得更加困难。为了解决这个问题,我们能做些什么呢?

一个简单的解决方案是将我们的加速计传感器数据与微弱的 GPS 信号结合使用。事实上,对我们的加速度进行二重积分,我们就能计算出我们的车的位置。虽然这种简单的测量会包含一些漂移,因此不会完全准确,因为我们的测量误差会随着时间传播(图 1)。为了解决这个问题,我们可以使用卡尔曼滤波器或粒子滤波器。

Figure 1: Autonomous car position estimation against time

卡尔曼滤波器

卡尔曼滤波器在机器人学(例如 SLAM 系统)和强化学习中有常见的应用。卡尔曼滤波器可用于 Robotis,以跟踪环境中一群机器人的运动,也可用于强化学习,以跟踪不同的软件代理。

卡尔曼滤波器是一种迭代数学过程,当测量值包含不确定性或误差时,它使用一组方程和连续数据输入来估计物体的真实位置、速度等。[1]

因此,卡尔曼滤波器可以简化为机器学习模型。他们获取一些输入数据,执行一些计算以进行估计,计算其估计误差,并反复重复该过程以减少最终损失。卡尔曼滤波器执行的迭代过程可以总结为 3 个主要步骤:

  1. 卡尔曼增益计算:利用输入数据和估计中的误差进行计算。
  2. 当前估计计算:使用原始输入数据、我们先前的估计和卡尔曼增益进行计算。
  3. 估算误差计算:最终使用卡尔曼增益和我们当前的估算值进行计算。

图 2 简要总结了这一过程。

Figure 2: Kalman Filter WorkFlow (Adapted from [1])

存在不同种类的卡尔曼滤波器,一些例子是:线性卡尔曼滤波器、扩展卡尔曼滤波器和无迹卡尔曼滤波器。如果你对卡尔曼滤波器更详细的数学解释感兴趣,麻省理工学院托尼·莱西的这个教程是一个很好的起点。

卡尔曼滤波器的一个主要问题是,它们只能用于模拟可以用高斯噪声描述的情况。尽管许多非高斯过程可以用高斯项来近似,或者通过某种形式的变换(如对数、平方根等)转换成高斯分布..).

为了克服这种类型的限制,可以使用另一种方法:粒子滤波器。

粒子过滤器

可以使用粒子滤波器来解决非高斯噪声问题,但是粒子滤波器通常比卡尔曼滤波器在计算上更昂贵。这是因为粒子滤波器使用模拟方法而不是分析方程来解决估计任务。

粒子过滤器通常用于:

  • 金融市场分析(特别是在随机过程分析
  • 强化学习
  • 机器人本地化(例如直接全局策略搜索)

粒子滤波器基于蒙特卡罗方法,通过将原始数据离散成粒子(每个粒子代表一个不同的状态)来处理非高斯问题。粒子数量越多,我们的粒子过滤器就越能更好地处理任何可能的分布类型。

像卡尔曼滤波器一样,粒子滤波器也利用迭代过程来产生它的估计。每次迭代可以分为三个主要步骤[3]:

  1. 从原始分布中取出多个样本( 粒子 )。
  2. 按照重要性的顺序对所有采样粒子进行加权(在给定间隔内落下的粒子越多,它们的概率密度就越高)。
  3. 通过用更可能的粒子替换更不可能的粒子进行重采样(就像在进化算法中,只有种群中最适合的元素才能存活)。

图 3 总结了这一过程。正如我们可以从下图中看到的,在这个例子中,我们的粒子过滤器能够在一次迭代后了解哪个范围更可能是我们的对象。反复重复这个过程,我们的滤波器将能够进一步限制其色散范围。

Figure 3: Single Particle Filter Iteration

如果你对用 Python 实现最优估计算法感兴趣,那么 FilterPyPyro 库是两个很好的解决方案。特别地,Pyro 是由优步开发的通用概率编程语言,其可以使用 PyTorch 作为后端用于各种贝叶斯分析。

我希望你喜欢这篇文章,谢谢你的阅读!

联系人

如果你想了解我最新的文章和项目,请通过媒体关注我,并订阅我的邮件列表。以下是我的一些联系人详细信息:

文献学

[1]专题—简单示例(单个测量值)的卡尔曼滤波器(55 个中的第 2 个)流程图,Michel van Biezen。访问地点:https://www.youtube.com/watch?v=CaCcOwJPytQ

[2]第十一章。教程:卡尔曼滤波器,托尼莱西。访问网址:http://web . MIT . edu/kirt ley/kirt ley/binlustuff/literature/control/Kalman % 20 filter . pdf

[3]粒子滤波器和蒙特卡罗定位简介,Cyrill Stachniss。访问网址:http://ais . informatik . uni-freiburg . de/teaching/ws12/mapping/pdf/slam 09-particle-filter-4 . pdf

黑洞成像的最优实时调度

原文:https://towardsdatascience.com/optimal-real-time-scheduling-for-black-hole-imaging-4d3518d2ad14?source=collection_archive---------23-----------------------

为了观测黑洞,如何协调 11 台望远镜?

队员:、、子怡()周

本文的主要目的是分享作者在哈佛大学应用计算科学研究所(IACS)John a . Paulson 工程和应用科学学院的顶点课程项目中的发现和贡献。他们的顾问是塞西莉亚·加拉夫帕夫洛斯·普罗托帕帕斯。在这个跨越整个学期的项目中,我们与事件视界望远镜 (EHT)合作,对人类发现宇宙产生影响。

你可能以前见过这张著名的图片——人类历史上第一张黑洞的图片。2019 年 4 月 10 日,EHT 发布了这张照片,他们获得了 2020 年基础物理学突破奖。

谢泼德·多勒曼是 EHT 的创始董事之一。在拍摄完黑洞的照片后,他找到了顶点计划的主要指导者 Pavlos Protopapas,寻求帮助。

他说,为了实现黑洞图像的高分辨率,他们使用了甚长基线干涉测量技术,其中全球各地的无线电碟形天线同步形成一个虚拟望远镜,具有目前从地球表面可能达到的最高角分辨率。这个分辨率有多高?这相当于坐在波士顿时能够在洛杉矶阅读一份报纸,或者相当于能够看到一臂之遥的一个原子。为了以这种方式运行,“EHT”号要求阵列的大部分地区同时有相当好的天气。目前该阵列中有 11 个天线。一些地方的观测条件可能非常好,但是如果由于其他地方天气不好,没有足够的望远镜可以参与,观测就无法进行,因为它们不会产生高质量的数据。

然而,操作这些巨型望远镜非常昂贵,科学家们不断争夺观测时间,因此 EHT 每年只有 10 天的时间,可供望远镜一起使用。每一年,10 天的窗口都是不同的。不仅如此,在这 10 天的窗口中,由于其他一些限制,他们只能触发 5-6 晚。目前,他们团队中的一个人,也就是 Shep,手动决定是否触发夜晚。他通过给他在每台望远镜前工作的朋友打电话,问他们:“你对天气有什么看法?”

你可能知道,当前的决策过程并没有达到应有的效率和深度。因此,Shep 希望我们建立一些实时算法,可以促进他的决策过程。我们的目标是最大化高质量黑洞照片的数量。给定天气数据和日期信息,算法应该随时提出建议,即是否在当天触发,以及未来剩余几天的最佳策略。总的来说,我们只能从连续 10 天中选择 5 天。

如果可能的话,EHT 还希望我们的模型输出置信水平和次优策略。

下面是这个问题的一个演示。x 轴表示 10 天窗口中的日期,而 y 轴表示到目前为止已经触发的天数。在每一天,如果我们决定在第二天触发,我们在对角线上向上移动,如果我们建议跳过第二天,我们在水平方向上移动。最终,我们必须到达顶线中的一个点。这里的绿线显示了一条可能的路径,建议触发 10 月 6、8、10、13 和 14 日。

Solution Space

动机

我们的动机是双重的。目前,EHT 由人类做出决定。如果我们的模型成功了,他们肯定会用它来帮助他们做决定。这对我们来说是一个巨大的动力,因为我们知道通过增加捕捉黑洞的机会,我们也为人类发现宇宙做出了贡献。

数据

我们从 GFS 收集数据,这是国家环境信息中心制作的天气预报模型。它是公开可用的。它提供全球逐层大气预报。你可以把它的数据想象成一个 3D 的形状。每 6 个小时,GFS 产生一组预测,我们提取与我们相关的数据:每个望远镜位置的天气情况。我们通过指定望远镜的经度、纬度和高度来做到这一点。

在我们提取了一些数据后,我们开始了探索性的数据分析过程,并绘制了这张图表。这里有五个图,因为 GFS 一次预测五个变量。在每张图上,你可以看到有一条黑线和七条灰线。这对应于每 6 小时预报的每组天气预报数据。黑线代表最新的预测数据,而灰线是在过去 48 小时内做出的预测。每次预测涵盖未来 16 天。我们可以看到,前 5 天的预报相当准确,但之后就变得非常不确定了。专家告诉我们,第一个变量 Tau-225 是表明大气透明度的最重要的变量,因为它是头顶上方的吸收率。较小的 Tau-225 比较大的 Tau-225 更优选。

Only the first graph of Tau-225 is relevant.

这就是我们得到的所有数据。在与合作伙伴会面和查看数据之前,我们考虑使用强化学习来解决这个问题。然而,在我们与合作伙伴会面并看到数据后,我们意识到这是一个优化问题,我们必须创造性地设计出非常适合它的模型。当我们找不到任何做类似事情的文献或以前的作品时,我们设计了这个基线模型,它作为我们后来创建的所有其他模型的基本框架。

基线模型

我们从强化学习中借鉴了奖励函数的概念。每个望远镜将根据其天气状况获得一个奖励值。每个望远镜的奖励函数被称为小 f。每天都被分配一个奖励值,奖励函数被称为大 f。在基线模型中,我们使用 Tau-225 的预测构建奖励函数。小 f 被定义为在望远镜的观察窗上τ-225 的负期望值。(负号的原因是因为直觉上我们希望奖励值越大越好,但是 Tau-225 总是正的,接近零的时候是最好的。)大 F 被定义为小 F 的一些加权平均值。我们用望远镜的大小作为权重的一部分,因为更大的望远镜在阵列中更重要。我们还在公式中加入了距离矩阵,因为我们希望望远镜分布在地球表面。

Baseline model: formula of the reward functions. Each telescope is represented as i. T_i is the observation of the telescope i. r_i is the diameter of the telescope i. D is the baseline length matrix, which includes pairwise telescopes’ distance information.

一旦我们计算出每天的奖励值,我们就想解决最优化问题。例如,在第 0 天,我们计算从第 1 天到第 10 天的奖励值。由于我们有 5 天的触发时间,并且我们没有使用其中的任何一天,我们找到五个最大的奖励,并查看第 1 天是否是其中的一天。这里,粉色方框代表最大的五个值。在第 1 天,我们有从第 2 天到第 10 天的奖励值。请注意,这些值会更新,因为已经进行了新的天气预报。因为我们已经触发了第一天,我们还有四天的触发时间。我们找到奖励值最大的四天。我们看到第二天在其中一个,所以建议触发第二天。在第 2 天,我们希望在剩余的几天中找到前 3 名奖励。我们看到第三天不在其中。然后在第 3 天,我们继续寻找前 3 个奖励,看看第 4 天是否在其中。

这些是基线模型的基础。现在我们转向考虑不确定性的更先进的模型。不确定性意味着我们只能在一定程度上相信政府统计处的预测数据。我们的合作伙伴多次强调,为了将风险降至最低,他们宁愿早一点而不是晚一点触发观察。

Example for solving the optimization problem

方法一:单一折扣系数

我们考虑的第一种不确定性仅取决于 GFS 对未来多远的预测,即时滞。为了体现这一点,我们可以将每天的奖励乘以一个折扣因子来获得现值。然后执行我们在基线模型中使用的相同优化技术。单一折扣因子被认为是一个超参数,需要从交叉验证中进行调整。

Method 1: Example

方法二:预测罚款

我们认为单一的贴现因子不足以解释未来的不确定性,因此我们引入了不同的不确定性量化来构建第二种方法。在这种方法中,我们基于时间滞后来寻找 GFS 模型准确性的模式。因此,我们使用历史数据来计算基于未来多少天预测的平均误差。我们将结果绘制在左侧,其中 x 轴是未来的天数,y 轴是误差的度量。我们看到,GFS 模型在超过六天后就不那么准确了。就像前面模型中的折扣因子一样,我们对奖励值使用了一个乘法惩罚项。(我们可以通过小 F 值或大 F 值来实现这一点)。惩罚项取决于时滞和一个称为“惩罚水平”的超参数。

Method 2: formula used

方法三:具体时间的预测难度

前两个模型假设不确定性来自时滞。这个模型和下一个模型假设不确定性与预测的具体日期有关。还记得 GFS 在接下来的 16 天中每 6 小时进行一次预测吗?因此,对于每个时间点,都有多个预测。图中的黄色区域以 Tau-225 的最小和最大预测数据为界。

对于这种方法,我们希望找到某个时间点的最新预测,并计算其他预测相对于该最新预测的均方根误差(RMSE)。然后,我们使用与之前类似的公式来获得奖励值,但是这次奖励和惩罚都是针对时间点定制的。

Method 3: formula used

方法 4:正态分布抽样

最后,我们仍然假设每个时间点的不确定性不同,但是我们希望获得与我们建议的最佳路径相关联的置信度。我们假设真实的天气来自正态分布。在蒙特卡罗方法的指导下,我们从分布中随机抽取每个时间点的奖励值足够多的次数,每次都找到一条最优路径。最后,我们总结了路径的频率,得出最佳路径是频率最高的路径。我们还使用它的频率来表示我们对建议路径的置信度。我们相信,如果我们的合作伙伴看到这个数字,他们可以做出更明智的决定。

Method 4: formula used

车型评测

我们通过将不同模型给出的建议路径与实际路径进行比较,对我们的模型进行了回溯测试。这是一个例子。我们对 11 月 9 日至 11 月 18 日的预测数据进行了模拟,因此每个模型都会给我们一个建议路径。我们也知道基本事实路径,所以我们比较了每个模型的平均奖励和最佳路径的分数。在本例中,只有基线法和分布抽样法未能生成最佳路径。缺乏进一步的惩罚导致了一天后的预测。

Example of outputs from models

我们收集了从 10 月 25 日到 11 月 30 日的 GFS 数据,并在每个连续的 10 天窗口中运行模拟。总共有 26 个 10 天的窗口。人们可以把我们在一个 10 天的窗口中收到的所有数据想象成 x,当我们回头看时的平均回报想象成预测的 y。我们可以自然地将我们预测的 y 与最佳路径进行比较,并计算均方误差。我们还计算一个分数,该分数在下面的公式中定义。这是一个相对分数。如果我们的预测路径等于最佳路径,那么它将等于 1。如果我们的预测路径等于随机路径,得分将为 0。

Metrics used to compare models

有了这两个指标,我们就能够决定每种方法的最佳惩罚级别,以及最佳模型。在这里,方法 3 是性能最好的模型,这是意料之中的,因为它包含了每天天气预测方差的不确定性。方法 2 是第二好的方法,因为它只考虑了天气预报在未来多远的不确定性。这里的抽样方法和基线一样好,因为它不包含任何惩罚。然而,它仍然是有用的,因为它是输出所选路径的置信度的唯一模型。

Comparison among models

软件

我们制作了一个软件包,供 EHT 将来使用。该软件包括处理数据、运行优化模型和利用提供的不确定性测量提出建议的程序。

以下是如何使用该软件的演示:

Software Demo

结论

这个项目发展到现在这个阶段并不容易。最初,当我们得到分配的项目时,我们想到了奇特的机器学习模型来解决问题。然而,在看到数据并与合作伙伴会面后,我们意识到一个更简单的模型更适合解决这个问题。有一段时间,从 GFS 中提取的数据中有意外的零,我们花了相当长的时间在合作伙伴的帮助下解决这个问题。构建软件需要我们构建一个图形用户界面(GUI ),并将 GUI 与所有的模型输入和输出连接起来。我们以前没有任何做这种建模的经验,但我们能够学到很多东西,并在最后征服每个概念。我们为这个项目感到非常自豪,并希望它对其他人有用。

优化快速文本模型以提高准确性

原文:https://towardsdatascience.com/optimising-a-fasttext-model-for-better-accuracy-739ca134100a?source=collection_archive---------16-----------------------

快速文本系列

理解精确度和召回率。

最初发表于我的博客

在我们之前的帖子中,我们看到了什么是 n-grams 以及它们如何有用。在那篇文章之前,我们使用脸书的 fastText 库构建了一个简单的文本分类器。在本帖中,我们将看到如何优化模型以获得更好的准确性。

精确度和召回率

为了更好地理解模型的准确性,我们需要知道精确度和召回率这两件事。而且这两件事也不是很难理解。Precision 是由 fastText 模型预测的正确标签数,recall 是正确标签中成功预测的标签数。这可能有点令人困惑,所以让我们看一个例子来更好地理解它。

假设一句话,我们给模型分类,从我们的栈交换烹饪样本,当然,模型预测标签食品安全,烘焙,设备,替代品和面包。堆栈交换中的实际标签是设备、清洁和刀具。这里,在模型预测的前五个标签中,只有一个是正确的。所以精度变成了 1 / 5,或者 0.20。另外,在三个正确的标签中,模型只正确预测了一个标签(设备),因此召回率为 1 / 3 或 0.33。这就是精确和回忆的含义。

有一种方法可以让我们在 fastText 中使用一个简单的命令来测试模型的精度和召回率。在这一点上,确保你已经阅读了我之前写的快速文本介绍文章,因为我将在这里使用那篇文章中的同一个例子。假设您已经这样做了,并且希望您已经从那篇文章中获得了数据,我们将在根目录中运行以下命令来获得我们的精度并召回数据:

./fasttext test cooking_question_classification_model.bin testing_data.txt

运行此命令后,您应该会得到类似于以下内容的输出:

N 3080
P@1 0.139
R@1 0.0602

正如您从输出中看到的,我们得到了 P@1R@1 的结果,结果是精度为 1,召回为 1。我们将在这篇文章中看到如何改进这些。

清理数据

如果你看我们的数据文件,你可以看到有一些大写字母。这些对于我们的模型来说并不重要,我们可以去掉它们来在一定程度上提高性能。但是我们不能检查所有的数据并清理它们。所以我们将使用一个简单的命令将所有大写字母转换成小写字母。为此,请运行以下命令:

cat cooking.stackexchange.txt | sed -e “s/\([.\!?,’/()]\)/ \1 /g” | tr “[:upper:]” “[:lower:]” > cooking.preprocessed.txt

在这个命令中,我们使用 cat 将数据打印到标准输出,使用管道将数据重定向到 sed 命令,对输入数据运行正则表达式,然后使用另一个管道将这个新输出运行到 translate 命令,将所有大写字母转换为小写字母。我们将这个最终输出重定向到一个名为“cooking.preprocessed.txt”的文件中,这也是官方 fastText 网站上提供的一个简单示例。在真实的生产场景中,这可能不是一个简单的任务。无论如何,一旦我们有了这个新的预处理文件,让我们看看它有什么。

➜ head cooking.preprocessed.txt
__label__sauce __label__cheese how much does potato starch affect a cheese sauce recipe ? 
__label__food-safety __label__acidity dangerous pathogens capable of growing in acidic environments
__label__cast-iron __label__stove how do i cover up the white spots on my cast iron stove ? 
__label__restaurant michelin three star restaurant; but if the chef is not there
__label__knife-skills __label__dicing without knife skills , how can i quickly and accurately dice vegetables ? 
__label__storage-method __label__equipment __label__bread what ‘ s the purpose of a bread box ? 
__label__baking __label__food-safety __label__substitutions __label__peanuts how to seperate peanut oil from roasted peanuts at home ? 
__label__chocolate american equivalent for british chocolate terms
__label__baking __label__oven __label__convection fan bake vs bake
__label__sauce __label__storage-lifetime __label__acidity __label__mayonnaise regulation and balancing of readymade packed mayonnaise and other sauces

如你所见,数据现在清晰多了。现在,我们不得不再次分割它来测试和训练数据集。为此,我们将运行以下两个命令:

➜ head -n 12324 cooking.preprocessed.txt > preprocessed_training_data.txt
➜ tail -n 3080 cooking.preprocessed.txt > preprocessed_testing_data.txt

我们必须根据这些新数据再次训练我们的模型,因为我们已经更改了数据。为此,我们将运行以下命令,输出应该类似于您在这里看到的内容:

➜ ./fasttext supervised -input preprocessed_training_data.txt -output cooking_question_classification_model
Read 0M words
Number of words: 8921
Number of labels: 735
Progress: 100.0% words/sec/thread: 47747 lr: 0.000000 avg.loss: 10.379300 ETA: 0h 0m 0s

为了检查精确度和召回率,我们将在新的测试数据上测试这个模型:

➜ ./fasttext test cooking_question_classification_model.bin preprocessed_testing_data.txt
N 3080
P@1 0.171
R@1 0.0743

如你所见,准确率和召回率都有所提高。这里要注意的另一件事是,当我们用新数据训练模型时,我们只看到 8921 个单词,而上次,我们看到了 14492 个单词。因此,由于大写和小写的差异,该模型具有相同单词的多个变体,这在一定程度上降低了精确度。

纪元

如果你有软件开发背景,你就知道 epoch 和时间有关系。你是对的。在这个上下文中,epoch 是模型看到一个短语或一个示例输入的次数。默认情况下,模型会将一个示例查看五次,即 epoch = 5。因为我们的数据集只有大约 12k 的样本,少了 5 个时期。我们可以使用- ecpoch 选项将它增加到 25 次,使模型“看到”一个例句 25 次,这可以帮助模型更好地学习。现在让我们试试:

➜ ./fasttext supervised -input preprocessed_training_data.txt -output cooking_question_classification_model -epoch 25
Read 0M words
Number of words: 8921
Number of labels: 735
Progress: 100.0% words/sec/thread: 43007 lr: 0.000000 avg.loss: 7.383627 ETA: 0h 0m 0s

你可能已经注意到,现在完成这个过程花了一点时间,这是我们增加纪元时所期望的。无论如何,现在让我们测试我们的模型的精度:

➜ ./fasttext test cooking_question_classification_model.bin preprocessed_testing_data.txt
N 3080
P@1 0.518
R@1 0.225

如你所见,我们在精确度和召回率上有了显著的提高。那很好。

算法的学习速率

算法的学习率表示在每个例句被处理后模型改变了多少。我们既可以提高也可以降低算法的学习速度。学习率为 0 表示学习没有变化,或者变化率正好为 0,所以模型根本没有变化。通常的学习率是 0.1 比 1。对于我们这里的例子,我们将保持学习率为 1,并重新训练我们的模型。为此,我们将使用 -lr 选项:

➜ ./fasttext supervised -input preprocessed_training_data.txt -output cooking_question_classification_model -lr 1.0 
Read 0M words
Number of words: 8921
Number of labels: 735
Progress: 100.0% words/sec/thread: 47903 lr: 0.000000 avg.loss: 6.398750 ETA: 0h 0m 0s

我们将再次测试模型,看看改变学习率后是否有任何改进:

➜ ./fasttext test cooking_question_classification_model.bin preprocessed_testing_data.txt
N 3080
P@1 0.572
R@1 0.248

绝对有进步。但是,如果我们一起增加纪元和学习率,会发生什么呢?

一起增加纪元和学习率

现在,我们将保持纪元为 25,学习速率为 1。让我们看看精确度和召回率会发生什么变化:

➜ ./fasttext supervised -input preprocessed_training_data.txt -output cooking_question_classification_model -epoch 25 -lr 1.0 
Read 0M words
Number of words: 8921
Number of labels: 735
Progress: 100.0% words/sec/thread: 41933 lr: 0.000000 avg.loss: 4.297409 ETA: 0h 0m 0s

现在让我们测试模型:

➜ ./fasttext test cooking_question_classification_model.bin preprocessed_testing_data.txt
N 3080
P@1 0.583
R@1 0.253

我们可以很容易地看到这里的改进。

所以,我们在这个帖子中学到了很多(我希望)。不过还有更多事情要做(比如 n-grams )。我们将在以后的帖子中看到这一点。如果你对此有任何补充,请在下面留下评论。

推特上关注我,了解更多数据科学机器学习,以及通用技术更新。另外,你可以关注我的个人博客

优化算法 I

原文:https://towardsdatascience.com/optimization-algorithms-i-831c7e99f465?source=collection_archive---------18-----------------------

新加坡元和动量

我们将有一个简短的优化概述,因为为什么需要它,稍后我们将讨论几个突出的算法。

为什么我们需要优化算法?

机器学习中的所有问题,无论是回归还是分类,都有一个要达到最佳性能的目标。模型的好坏与预测的好坏直接相关,即对于分类问题,模型应该能够正确地识别事物,而对于回归问题,模型的预测应该足够接近真实值。为了开发一个“好模型”,我们通常会将经验风险与问题联系起来,并试图通过迭代过程来降低它。机器学习优化算法与其他优化算法的一个重要区别是,它们不会在达到局部最小值后停止,而是在满足停止标准时停止。在深度学习和一般人工神经网络中,我们可能经常使用代理损失函数而不是经验风险最小化,因为它们容易过度拟合。

神经网络训练面临额外的问题。由于导致非常慢的步骤的病态 Hessian 矩阵、可能与局部最小值混淆的鞍点以及使训练不稳定的爆炸梯度,可能会出现问题。此外,使用小批训练样本的梯度近似可能导致不精确的估计,并使梯度在不同于最佳方向的方向上移动,所述最佳方向可能是利用整个数据集上的梯度获得的。

虽然 SGD 是经典的,并且仍然可以在许多问题中找到应用,但是使用自适应算法已经成为一种趋势。

1。随机梯度下降

对于初学者来说,随机梯度下降是一个容易理解的算法。它在许多方面类似于其前身批量梯度下降,但在某种意义上提供了一个优势,即它通过更少的数据集在降低风险目标方面取得了快速进展。算法如下:

该算法本质上是在每次迭代中选择 m 个数据点,计算它们的平均梯度,更新参数,并对各种学习速率这样做以获得最佳模型。它重复这个过程,直到满足某个收敛标准。

为什么我们需要改变学习率? 训练样本的随机采样给梯度增加了随机噪声,即使在局部最小值时也不会减少。因此,为了保证收敛,我们允许学习率在一些初始迭代中降低,并在之后保持不变。保证收敛的充分条件是,

matcha.io

这里,ε-k 是第 k 次迭代后的学习率。

mathcha.io

根据深度学习的书,我们将ε的最终固定值设定为初始值的 1%左右。SGD 的一个重要性质是每次迭代的参数更新仅取决于批量 m,因此每次迭代的计算时间不随训练样本数量的增加而改变。对于一个凸问题,推广误差(当前迭代后损失函数值与损失函数值最小值之差)每一步递减O(1/sqrt(k))。根据 Cramer-Rao 界,这种推广误差在一次迭代中不能减少超过 O(1/k)

2。势头

使用 SGD 的动量来克服与 SGD 相关的病态 Hessian 矩阵和梯度方差的问题。它通过保持梯度的移动平均值来实现这一目标。现在,更新不仅依赖于当前梯度,而且依赖于来自过去的梯度序列。它基本上维护另一个变量 v,该变量将累积梯度,并使用该变量来更新参数。算法如下:

Momentum with SGD

需要注意的重要一点是,我们现在要考虑另一个超参数。在下图中,红线显示了渐变随动量的移动。它更快,更直接地指向目标,因为它一直在考虑过去梯度的方向,并通过平均它们。等高线代表平方损失函数

参考资料:

[## 深度学习

深度学习教材是一个资源,旨在帮助学生和从业人员进入机器领域…

www.deeplearningbook.org](https://www.deeplearningbook.org/)

即将推出自适应方法的优化算法 2。

深度学习中的优化算法

原文:https://towardsdatascience.com/optimization-algorithms-in-deep-learning-191bfc2737a4?source=collection_archive---------3-----------------------

AdaGrad、RMSProp、带动量的梯度下降和 Adam 优化器揭秘

在本文中,我将向您介绍深度学习中最复杂的优化算法,这些算法可以让神经网络更快地学习,并实现更好的性能。

这些算法是带动量的随机梯度下降、AdaGrad、RMSProp 和 Adam Optimizer。

https://www.deeplearning-academy.com】最初发表于

如果你喜欢这篇文章,想分享你的想法,问问题或保持联系,请随时通过 LinkedIn 与我联系。

目录

  1. 为什么我们需要更好的优化算法?
  2. 带动量的随机梯度下降
  3. 阿达格拉德
  4. RMSProp
  5. Adam 优化器
  6. 深度学习的最佳优化算法是什么?

1.为什么我们需要更好的优化算法?

为了训练神经网络模型,我们必须定义损失函数,以便测量我们的模型预测和我们想要预测的标签之间的差异。我们所寻求的是一组特定的权重,利用这些权重,神经网络可以做出准确的预测,从而自动导致损失函数值更低。

我想你现在一定知道了,它背后的数学方法叫做梯度下降。

Eq. 1 Gradient Descent for parameters θ with loss function L.

在该技术(等式 1)中,我们必须计算损失函数 L 相对于我们想要改善的权重(或参数 θ )的梯度。随后,在梯度的负方向上更新权重/参数。

通过周期性地对权重应用梯度下降,我们将最终达到最佳权重,使损失函数最小化,并允许神经网络做出更好的预测。

目前为止这个理论。

不要误解我,梯度下降仍然是一个强大的技术。然而,在实践中,这种技术在训练期间可能会遇到某些问题,这些问题会减慢学习过程,或者在最坏的情况下,甚至会阻止算法找到最佳权重

这些问题一方面是损失函数的鞍点局部最小值,其中损失函数变得平坦,梯度变为零:

Fig. 1 Saddle Points and Local Minima

接近零的梯度不会改善权重参数,并且会妨碍整个学习过程。

另一方面,即使我们有不接近零的梯度,为来自训练集的不同数据样本计算的这些梯度的值在值和方向上也可能不同。我们说梯度是有噪声的,或者有很多方差。这导致向最佳重量的曲折移动,并使学习速度变慢:

Fig. 3 Example of zig-zag movements of noisy gradients.

在下面的文章中,我们将学习更复杂的梯度下降算法。所有这些算法都是基于我们到目前为止所知道的规则梯度下降优化。但是,我们可以通过一些数学技巧来扩展这种常规的权重优化方法,以建立更有效的优化算法,使我们的神经网络能够充分处理这些问题,从而学习更快,实现更好的性能

2.带动量的随机梯度下降

我想向你们展示的第一个复杂算法叫做带动量的随机梯度下降。

Eq. 2 Equations for stochastic gradient descent with momentum.

在等式的左边。2,您可以看到权重根据规则随机梯度下降进行更新的等式。右边的等式显示了根据具有动量的 SGD 的权重更新的规则。动量作为添加到常规更新规则中的附加项【ρ】乘以 v 出现。

直观地说,通过增加这个动量项,我们让我们的梯度在训练期间建立一种速度 v 。速度是由 ρ 加权的梯度的运行和。

ρ 可以认为是一点点减缓速度的摩擦力。一般来说,你可以看到速度随着时间的推移而增加。通过使用动量项,鞍点和局部极小值对梯度变得不那么危险。因为朝向全局最小值的步长现在不仅取决于当前点的损失函数的梯度,还取决于随时间推移而增加的速度。

换句话说,在某一点上,我们更多的是朝着速度的方向移动,而不是朝着梯度的方向。

如果你想有一个有动量的随机梯度下降的物理表示,想象一个球滚下山坡,并随着时间的推移增加速度。如果这个球在途中碰到一些障碍物,比如一个洞或没有向下斜坡的平地,速度 v 会给球足够的力量滚过这些障碍物。在这种情况下,平地和洞代表鞍点或损失函数的局部最小值。

在下面的视频中(图 4),我想给大家展示一个正则随机梯度下降和带动量项的随机梯度下降的直接对比。两种算法都试图达到三维空间中损失函数的全局最小值。请注意动量项是如何使梯度具有更小的方差和更少的曲折移动的。

**

Fig. 4 SGD vs. SGD with Momentum

一般来说,动量项使得向最优权重的收敛更稳定和更快。

3.阿达格拉德

另一种优化策略叫做 AdaGrad。这个想法是你在优化过程中保持梯度平方和的运行。在这种情况下,我们没有动量项,而是一个表达式 g 它是梯度平方的和。

Eq. 3 Parameter update rule for AdaGrad.

当我们更新一个权重参数时,我们将当前梯度除以该项的根 g 。为了解释 AdaGrad 背后的直觉,想象一个二维空间中的损失函数,其中损失函数在一个方向上的梯度非常小,而在另一个方向上非常高。

沿着梯度较小的轴对梯度求和会导致这些梯度的平方和变得更小。如果在更新步骤中,我们将当前梯度除以一个非常小的梯度平方和【g】,该除法的结果变得非常高,反之亦然,对于具有高梯度值的另一个轴也是如此。

因此,我们强制算法以相同的比例在任何方向进行更新。

这意味着我们通过增加沿着轴的梯度来加速沿着具有小梯度的轴的更新过程。另一方面,沿着具有大梯度的轴的更新稍微慢了一些。

但是,这种优化算法有一个问题。想象一下,当训练需要很长时间时,梯度的平方和会发生什么。随着时间的推移,这一项会变得更大。如果当前梯度除以这个大的数,则权重的更新步长变得非常小。这就好像我们使用了非常低的学习,随着训练时间的延长,这种学习会变得更低。在最坏的情况下,我们会被困在阿达格拉德,训练将永远继续下去。

4.RMSProp

AdaGrad 有一个名为 RMSProp 的细微变化,它解决了 AdaGrad 的问题。对于 RMSProp,我们仍然保持梯度平方的运行总和,但是我们没有让该总和在训练期间持续增长,而是让该总和实际上衰减。

Eq. 4 Update rule for RMS Prop.

在 RMSProp 中,我们将梯度的平方和乘以衰减率 α ,并加上由(1- α) 加权的当前梯度。RMSProp 中的更新步骤看起来与 AdaGrad 中的完全相同,我们将当前梯度除以梯度的平方和,以获得沿一个维度加速运动并沿另一个维度减慢运动的良好特性。

让我们看看 RMSProp 在寻找最优权重方面与 SGD 和 SGD with momentum 相比做得如何。

**

Fig. 5 SGD vs. SGD with Momentum vs. RMS Prop

虽然具有动量的 SGD 能够更快地找到全局最小值,但这种算法需要更长的路径,这可能是危险的。因为更长的路径意味着更多可能的鞍点和局部极小值。另一方面,RMSProp 直接走向损失函数的全局最小值,而不走弯路。

5.Adam 优化器

到目前为止,我们已经使用了矩项来建立梯度的速度,以朝着该速度的方向更新权重参数。在 AdaGrad 和 RMSProp 的例子中,我们使用梯度的平方和来缩放当前梯度,因此我们可以在每个维度中以相同的比率进行权重更新。

这两种方法看起来都是不错的主意。为什么我们不把两个世界的优点结合到一个单一的算法中呢?

这就是最终优化算法 Adam 背后的确切概念,我想向大家介绍一下。

算法的主要部分由以下三个等式组成。乍一看,这些方程似乎令人不知所措,但如果你仔细观察,你会发现对以前的优化算法有些熟悉。

Eq. 5 Parameter update rule for Adam Optimizer

第一个方程看起来有点像带动量的 SGD。在这种情况下,这一项就是速度和摩擦力。在亚当的例子中,我们称之为第一动量,它只是一个超参数。

然而,与具有动量的 SGD 的差异是因子(1- β1 ),该因子与电流梯度相乘。

另一方面,方程的第二部分可以被视为 RMSProp,其中我们保持梯度平方的运行和。同样,在这种情况下,存在与平方梯度相乘的因子(1- β2 )。

方程中的项称为第二动量,也是一个超参数。最终的更新方程可以看作是 RMSProp 和 SGD 与动量的组合。

到目前为止,Adam 已经集成了前两个优化算法的良好特性,但这里有一个小问题,那就是开始时会发生什么的问题。

在第一时间步,第一和第二动量项被初始化为零。第二次动量第一次更新后,这一项还是很接近零的。当我们更新最后一个等式中的权重参数时,我们除以非常小的第二动量项 v ,导致非常大的第一更新步长。

这个第一个非常大的更新步骤不是问题几何的结果,而是我们已经将第一个和第二个动量初始化为零这一事实的产物。为了解决大的首次更新步骤的问题,Adam 包括一个修正条款:

Eq. 6 Bias Correction for Adam Optimizer

你可以看到,在第一和第二动量的第一次更新之后,我们通过考虑当前的时间步长,对这些动量做了一个无偏的估计。这些校正项使得第一和第二动量的值在开始时比没有偏差校正的情况下更高。

因此,神经网络参数的第一个更新步骤不会变得太大,并且我们不会在开始时搞乱我们的训练。额外的偏差修正为我们提供了完整形式的 Adam 优化器。

现在,让我们在寻找损失函数的全局最小值方面相互比较所有算法:

**

Fig. 6 Comparison of all optimization algorithms.

6.深度学习的最佳优化算法是什么?

最后,我们可以讨论什么是最佳梯度下降算法的问题。

一般来说,普通的梯度下降算法对于较简单的任务来说已经足够了。如果您对模型的准确性不满意,您可以尝试 RMSprop 或在梯度下降算法中添加动量项。

但是根据我的经验,神经网络的最佳优化算法是 Adam。这种优化算法对于你将会遇到的几乎任何深度学习问题都非常有效。尤其是当您将超参数设置为以下值时:

  • β1=0.9
  • β2=0.999
  • 学习率= 0.001–0.0001

…这将是一个非常好的起点,可以解决任何问题,事实上也可以解决我曾经使用过的所有类型的神经网络架构。

这就是为什么 Adam Optimizer 是我想解决的每个问题的默认优化算法。只有在极少数情况下,我才会切换到我之前介绍的其他优化算法。

从这个意义上说,我建议您总是从 Adam 优化器开始,而不管您正在处理的问题领域的神经网络的架构如何。

原载于https://www.deeplearning-academy.com

用 Python 优化:如何用最少的风险赚最多的钱?

原文:https://towardsdatascience.com/optimization-with-python-how-to-make-the-most-amount-of-money-with-the-least-amount-of-risk-1ebebf5b2f29?source=collection_archive---------4-----------------------

我们展示了如何将获得诺贝尔奖的经济理论应用于股票市场,并使用简单的 Python 编程解决由此产生的优化问题。

介绍

现代数据科学和分析企业的主要目标之一是为商业和技术公司解决复杂的优化问题以实现利润最大化。

在我的文章“用 Python 进行线性编程和离散优化”中,我们谈到了基本的离散优化概念,并介绍了一个用于解决此类问题的 Python 库 PuLP

[## 用 Python 实现线性规划和离散优化

线性和整数规划是离散优化的关键技术,它们在现代数学中随处可见

towardsdatascience.com](/linear-programming-and-discrete-optimization-with-python-using-pulp-449f3c5f6e99)

虽然线性规划(LP)问题仅由线性目标函数和约束条件定义,但它可以应用于从医疗保健到经济、商业到军事等不同领域的各种问题。

在本文中,我们展示了一个在经济规划领域使用 Python 编程的 LP 的惊人应用— 最大化股票市场投资组合的预期利润,同时最小化与之相关的风险

听起来很有趣?请继续读下去。

如何在股市中实现利润最大化,风险最小化?

1990 年诺贝尔经济学奖授予了哈里·马科维茨,他因著名的现代投资组合理论(MPT)而被认可,这在金融市场的说法中是众所周知的。最初的论文发表于 1952 年。

Source: AZ Quotes

这里的关键词是平衡

一个好的、平衡的投资组合必须提供保护(最小化风险)和机会(最大化利润)。

[## 如何优化投资组合风险模型

单个资产的集合相互作用,影响整个投资组合。所以当几项投资都…

www.dummies.com](https://www.dummies.com/business/accounting/auditing/how-to-optimize-portfolio-risk/)

并且,当涉及到最小化和最大化这样的概念时,很自然地用 数学最优化理论 来投射问题。

基本思想相当简单,植根于人类天生的风险厌恶本性。

一般来说,股票市场的统计数据表明,风险越高,回报越高的可能性越大,风险越低,回报越小的可能性越大。

MPT 假设投资者厌恶风险这意味着给定两个提供相同预期回报的投资组合,投资者会更喜欢风险较小的一个。想想吧。只有当高风险股票有很高的回报率时,你才会收集它们。

但是如何量化风险?这肯定是一个模糊的概念,对不同的人有不同的含义。然而,在普遍接受的经济理论中,股票价格的可变性(波动性)(在固定时间范围内定义)等同于风险

因此,中心优化问题是在保证一定的利润回报的同时,使风险最小化。或者,最大化利润,同时将风险保持在某个阈值以下。

一个例题

在本文中,我们将展示投资组合优化问题的一个非常简化的版本,它可以被转换到一个 LP 框架中,并使用简单的 Python 脚本高效地解决。

我们的目标是展示这种优化求解器处理复杂现实问题的能力和可能性。

我们使用三只股票的 24 个月股价(月平均)——微软、Visa 和沃尔玛。这些是旧数据,但它们完美地展示了这一过程。

Fig: Monthly stock price of three companies over a certain 24-month period.

如何定义退货?我们可以简单地通过从当月减去上月的平均股价并除以上月的价格来计算滚动月回报率。

下图显示了返回结果,

优化模型

股票的回报是一个不确定的量。我们可以将其建模为一个随机向量。

投资组合也可以被建模为向量。

因此,某个投资组合的回报由这些向量的内积给出,它是一个随机变量。最重要的问题是:

如何比较随机变量(对应不同的投资组合)来选择一个“最佳”的投资组合?

根据马科维兹模型,我们可以将问题公式化为:

给定固定数量的资金(比如 1000 美元),我们应该在三只股票中的每只股票上投资多少,以便(a)至少有给定阈值的一个月预期回报,以及(b)最小化投资组合回报的风险(方差)。

我们不能投资负的数量。这就是非消极约束

假设没有交易成本,总投资受到手头资金的限制,

投资回报,

但这是一个随机变量。因此,我们必须处理预期数量

假设我们想要一个最小预期收益。因此,

现在,为了模拟风险,我们必须计算方差

综合起来,最终的优化模型是,

接下来,我们将展示使用一个流行的 Python 库来阐述和解决这个问题是多么容易。

使用 Python 解决优化问题:CVXPY

这个问题我们要用的库叫做 CVXPY 。它是一种用于凸优化问题的 Python 嵌入式建模语言。它允许你以一种遵循数学模型的自然方式来表达你的问题,而不是以求解者所要求的限制性标准形式。

本 Jupyter 笔记本 中给出了 的全部代码。在这里,我只展示核心代码片段。

要建立必要的数据,关键是从每月价格的数据表中计算出回报矩阵。代码如下所示,

现在,如果您并排查看原始数据表和返回表,看起来如下所示:

接下来,我们简单地从这个回报矩阵计算平均(预期)回报和协方差矩阵,

之后,CVXPY 允许简单地按照我们上面构建的数学模型来设置问题,

注意 CVXPY 框架中非常有用的类的使用,如**quad_form()****Problem()**

瞧啊。

我们可以编写一个简单的代码来解决**Problem**,并显示最佳投资数量,确保最低回报率为 2%,同时也将风险保持在最低水平。

最终结果由下式给出:

延伸问题

不用说,我们模型的设置和简化假设会使这个问题听起来比实际情况更简单。但是一旦您理解了解决这种优化问题的基本逻辑和机制,您就可以将其扩展到多种场景,

  • 数百只股票,更长时间范围的数据
  • 多重风险/回报比率和阈值
  • 最小化风险或最大化回报(或两者兼而有之)
  • 一起投资一组公司
  • 非此即彼的情景——要么投资 Cococola,要么投资百事可乐,但不能两者都投资

你必须构建更复杂的矩阵和更长的约束列表,使用指示变量将这变成一个****-混合整数问题,但所有这些都是 CVXPY 这样的包所固有的支持。

查看 CVXPY 包的示例页面,了解使用该框架可以解决的优化问题的广度。

摘要

在本文中,我们讨论了如何从一个开创性的经济理论的关键概念可以用来制定一个简单的股票市场投资优化问题。

为了说明这一点,我们选取了三家公司的月平均股价样本数据集,并展示了如何使用基本的 Python 数据科学库(如 NumPy、Pandas)和一个名为 CVXPY 的优化框架来快速建立线性规划模型。

拥有这种灵活而强大的软件包的工作知识为未来的数据科学家的技能组合增加了巨大的价值,因为解决优化问题的需求出现在科学、技术和商业问题的所有方面。

鼓励读者尝试这个投资问题的更复杂版本,以获得乐趣和学习。

#数据科学,#编程,#统计

如果您有任何问题或想法要分享,请通过tirthajyoti【AT】Gmail . com联系作者。此外,您可以查看作者的 GitHub 资源库中其他有趣的 Python、R 或 MATLAB 代码片段和机器学习资源。如果你像我一样对机器学习/数据科学充满热情,请随时在 LinkedIn 上添加我在 Twitter 上关注我。

** [## Tirthajyoti Sarkar - Sr .首席工程师-半导体、人工智能、机器学习- ON…

佐治亚理工学院理学硕士- MS,分析这一 MS 计划传授理论和实践…

www.linkedin.com](https://www.linkedin.com/in/tirthajyoti-sarkar-2127aa7/)**

SciPy 优化及其在机器学习中的应用

原文:https://towardsdatascience.com/optimization-with-scipy-and-application-ideas-to-machine-learning-81d39c7938b8?source=collection_archive---------5-----------------------

对于各种各样的业务和技术流程来说,优化通常是最终的边界,需要被征服才能交付真正的价值。我们展示了如何使用 Python 中最流行的科学分析包 SciPy 进行优化,并讨论了在机器学习领域的独特应用。

介绍

你可能还记得高中时代的一个简单的微积分问题——在给定一个盒子的体积限制的情况下,找出建造一个盒子所需的最少材料。

够简单吗?

思考一下这个问题,并认识到这里应用的相同原理在复杂、大规模的商业和社会问题中广泛使用,这是有益的。

仔细看上面的问题。约束是固定的体积。把它想成一个商业可交付成果(也就是对客户的承诺)。

但是问题的目标是找到所需的(就表面积而言)的最小材料。认为这与生产商的利润率有关(需要的材料越少,相同售价的生产成本越低,因此利润率更高)。

数学优化是解决工程、金融、医疗保健和社会经济事务中主要商业问题的核心。几乎所有的商业问题都可以归结为某种资源成本的最小化或给定其他约束条件下某种利润的最大化。

优化过程也是运筹学的灵魂,运筹学与现代数据驱动的商业分析密切相关。以这种方式,它也与数据科学管道密切相关,几乎在今天的所有业务中使用。

虽然已经有很多关于数据科学项目的数据争论和预测建模方面的文章,但最终的前沿通常涉及使用数据驱动模型解决优化问题,这些模型可以通过降低成本或提高生产力来提高业务的底线。

[## 为什么业务分析问题需要您所有的数据科学技能

对于现实生活中的业务问题,数据驱动分析的现代实践总是一个复杂的混合体…

medium.com](https://medium.com/analytics-vidhya/why-a-business-analytics-problem-demands-all-of-your-expertise-at-once-1290170808c4)

除了纯粹的商业驱动动机,优化的主题本身也值得研究,因为它是所有机器学习 (ML)算法的核心,从简单线性回归一直到深度神经网络。理解优化问题的各种算法、限制和公式化可以产生有效解决 ML 问题的有价值的洞察力。

[## 下面是什么?机器学习的核心是优化

我们展示了最流行的机器学习/统计建模技术背后的核心优化框架。

towardsdatascience.com](/a-quick-overview-of-optimization-models-for-machine-learning-and-statistics-38e3a7d13138)

因此,对于一名数据科学家来说,学习解决优化问题的基本工具和框架以产生实际影响是必不可少的。

Python 和 SciPy 用于优化

Python 已经成为分析、数据科学和机器学习的事实上的通用语言。因此,在 Python 生态系统中讨论优化包和框架是有意义的。

[## Python 是如何成为数据科学的首选语言的?

多年来,R 一直是那些进入数据科学领域的人的显而易见的选择。近年来,有些事情发生了变化…

www.netguru.com](https://www.netguru.com/blog/how-did-python-become-the-language-of-choice-for-data-science)

在我之前的帖子中,我已经涵盖了使用 Python 的 线性规划 和其他 离散优化方法论 并介绍了强大的包,如纸浆CVXPY

在这篇文章中,我将介绍 SciPy 生态系统中可用的优化算法。SciPy 是用于科学和数学分析的最广泛使用的 Python 包,难怪它拥有强大而易用的优化例程来解决复杂的问题。

相关的示例代码可以在作者的 GitHub 资源库中找到。

开始简单—单变量标量优化

我们从一个简单的标量函数(一个变量)最小化的例子开始。假设,我们想要最小化下面的函数,它绘制在 x = -10 到 x = 10 之间。该函数如下所示。在函数域内,它有一个全局最小值和一个局部最小值。

定义该函数的代码是,

def scalar1(x):
    return np.sin(x)*np.exp(-0.1*(x-0.6)**2)

用 SciPy 确定全局最小值的代码非常简单。在这种情况下,我们可以使用**minimize_scalar**函数。

from scipy import optimize
result = optimize.minimize_scalar(scalar1)

就是这样。信不信由你,优化完成了!我们可以打印出结果对象,以获得更多有用的信息。

print(result)>> fun: -0.6743051024666711
   nfev: 15
   nit: 10
   success: True
   x: -1.2214484245210282

达到最小值的值存储在result['x']变量中。

print("Minimum occurs at: ",result['x'])
>> Minimum occurs at:  -1.2214484245210282

剩余量产生关于函数求值次数、迭代次数、解的状态(成功与否)以及最终解的函数值的信息。

如果变量是有界的呢?

上面的代码实现了所谓的无约束/无界优化,即没有对问题施加任何类型的限制。然而,大多数实际优化问题涉及复杂的约束。一个简单的例子是约束自变量( x )。

正如我们看到的,这个函数有两个极小值,如果我们只考虑 x 的正值,结果会不同。使用 bound 进行搜索的代码与上面的代码略有不同。

result = optimize.minimize_scalar(scalar1, bounds = (0,10),method='Bounded')

因此,我们必须用一个合适的包含最小和最大边界的元组传递**bounds**参数,并使用**method='Bounded'**参数。

print("When bounded between 0 and 10, minimum occurs at: ",result['x'])>> When bounded between 0 and 10, minimum occurs at:  4.101466164987216

引入其他功能约束

在这个问题中,我们可能有其他复杂的约束。假设,我们希望满足以下条件以及找到全局最小值的目标。

注意,其中一个是不等式,另一个是等式约束。

将约束作为函数放入字典中

SciPy 允许通过更通用的方法**optimize.minimize**处理任意约束。约束必须按照特定的语法写在 Python 字典中。不等式约束需要分解成形式为 f(x) < 0 的单个不等式。下面的代码演示了这个想法。

选择合适的方法

之后,我们可以通过选择支持约束的合适方法来运行优化(函数 **minimize** 中并非所有方法都支持约束和界限)。这里我们选择 SLSQP 方法,代表 序列最小二乘二次规划

初步猜测和第一次试运行

此外,为了使用minimize,我们需要以x0参数的形式传递一个初始猜测。假设,我们通过x0=0进行试运行。

result = optimize.minimize(scalar1,x0=0,method='SLSQP',
constraints=cons,options={'maxiter':1000})

失败!

如果我们打印结果,我们会看到与简单的无约束优化结果不同的东西。

fun: 0.7631695862891654
jac: array([0.59193639])
message: 'Iteration limit exceeded'
nfev: 1254
nit: 101
njev: 101
status: 9
success: False
x: array([0.8773752])

优化参数 success: False 表示没有成功达到全局最小值。消息为“迭代限制超过”,即它尝试了 101 次迭代,但无法达到最小值。

但是,为什么呢?

答案在于数学优化(和相关算法)的深层理论,但可以说最初的猜测起了很大的作用。一般来说,非凸优化问题没有成功解决的数学保证,我们这里的问题的本质是非凸的。要了解更多关于最优化问题的凸性,请看这个视频,

怎样才能提高优化(搜索)?

一般情况下,我们做不了多少。然而,在这个玩具例子中,我们已经有了函数的图形,并能看到最优解。因此,我们可以给算法一个更好的初始猜测。我们给**x0=-2**

result = optimize.minimize(scalar1,x0=-2,method='SLSQP',
constraints=cons,options={'maxiter':100})

现在结果是有利的!

fun: -0.2859494456768613
jac: array([-0.4675066])
message: 'Optimization terminated successfully.'
nfev: 811
nit: 71
njev: 67
status: 0
success: True
x: array([-2.37569791])

迭代次数呢?

如果我们限制算法执行的迭代次数会怎么样?仅出于演示目的,我们将迭代次数严格限制为 3 次。

result = optimize.minimize(scalar1,x0=-20,method='SLSQP',
constraints=cons,options={'maxiter':3})

不出所料,结果并不令人满意。

fun: -0.4155114388552631
jac: array([-0.46860977])
message: 'Iteration limit exceeded'
nfev: 12
nit: 4
njev: 4
status: 9
success: False
x: array([**-2.10190632**])

请注意,优化接近全局最小值,但没有完全达到——当然,这是因为不允许迭代足够的次数。

为什么考虑这一点很重要?

这是因为每次迭代等于计算(有时不是计算而是实际物理)成本

这是优化过程的一个业务方面。在现实生活中,如果单个函数评估耗费大量资源,我们可能无法长时间运行优化。

当优化不涉及简单的数学评估,而是涉及复杂、耗时的模拟或成本和劳动密集型实验时,就会出现这种情况。

当每次评估都要花费金钱或资源时,那么不仅算法的选择,而且更精细的细节都变得需要考虑。

变得更复杂—多变量函数

尽管我们在前面的章节中考虑了解决一个标准优化问题的所有基本方面,但是这个例子由一个简单的单变量分析函数组成。

但事实并非如此!

SciPy 方法适用于任何 Python 函数,不一定是封闭形式的一维数学函数。

让我们展示一个多值函数的例子。

高斯混合的最大化

通常在一个化学或制造过程中,多个随机子过程被组合起来产生一个高斯混合。可能需要通过选择单个子过程中的最佳操作点来最大化最终的合成过程输出(在一定的过程限制内)。

诀窍是使用一个向量作为目标函数的输入,并确保目标函数仍然返回单个标量值。此外,因为这里的优化问题是关于目标函数的最大化,我们需要改变符号并返回高斯函数和的负数作为目标函数的结果。

同样的result['x']将单个程序的最佳设置存储为一个向量。这就是优化单值函数和多元函数的唯一区别,我们得到的是一个向量,而不是一个标量。

x: array([-1.00017852,  0.29992313,  2.10102748])

有界输入

不用说我们可以改变这里的界限来反映实际的约束。例如,如果子过程设置只能占用一定范围的值(一些必须是正的,一些必须是负的,等等。)那么解决方案将略有不同—它可能不是全局最优的。

这里,解决方法如下。这表示将第三个子过程设置推至最大可能值(零),同时适当调整其他两个子过程设置。

x: array([-1.00000644e+00,  3.00115191e-01, -8.03574200e-17])

多变量优化的约束处理方式类似于单变量优化。

更详细的文档和示例

SLSQP 并不是 SciPy 生态系统中唯一能够处理复杂优化任务的算法。有关更详细的文档及其用法,请参见以下链接:

用 Scipy 进行线性编程

简单、直接的线性规划(LP)问题也可以通过 Scipy 解决。在 2014 年之前,它没有内置的 LP 求解器,但从那时起它已经发生了变化。

让我们举一个实际的工厂生产问题(借用了这个例子并略有改动)

一个工厂生产四种不同的产品,第一种产品的日产量是 x1 ,第二种产品的日产量是 x2 ,以此类推。目标是确定每种产品的利润最大化日产量,有以下约束条件:

  • 第一个、第二个、第三个和第四个产品的单位产品利润分别是 20、12、30 和 15。
  • 由于人力的限制,每天生产的总数量不能超过五十(50)。
  • 对于每单位的第一种产品,消耗三单位的原材料 A。第二种产品的每单位需要两个单位的原料 A 和一个单位的原料 b。第三种产品的每单位需要两个单位的 A 和五个单位的 b。最后,第四种产品的每单位需要三个单位的 b。
  • 由于运输和储存的限制,工厂每天可以消耗一百单位的原材料 A 和九十单位的 B。

在 Scipy 中设置这个问题很容易。

然后用一行代码解决它,

所以,解决方案说,

  • 工厂每天应生产 26.66 台 x1 ,10 台 x3 ,13.33 台 x4 。与 x2 相对应的极小数字实质上表示不应该产生任何数量的 x2
  • 在这种安排下,可获得的最大利润是 1033.33 美元。

值得注意的一点是,该解决方案表示分数选择,这在实际情况下可能不可行。这就是 Scipy solver 的局限性,它不能解决所谓的整数规划问题。其他 Python 包如 PuLP 可能是解决这类问题的一个选择。在这里看我的文章。

[## 用 Python 实现线性规划和离散优化

线性和整数规划是离散优化的关键技术,它们在现代数学中随处可见

towardsdatascience.com](/linear-programming-and-discrete-optimization-with-python-using-pulp-449f3c5f6e99)

将该过程扩展到机器学习领域

老实说,只要您能够定义一个合适的目标函数来生成一个标量值以及与实际问题场景相匹配的合适的边界和约束,那么您可以推动这种方法的复杂程度是没有限制的。

机器学习中的误差最小化

几乎所有机器学习(ML)算法的关键是定义合适的误差函数(或损失度量),迭代数据,并找到最小化总误差的 ML 模型参数的最佳设置。通常,误差是模型预测和实际情况(给定数据)之间某种距离的度量。

因此,完全可以使用 SciPy 优化例程来解决 ML 问题。

这使您能够深入了解算法的实际工作,因为您必须自己构建损失度量,而不依赖于一些现成的开箱即用的函数。

ML 中超参数优化

调整 ML 模型的参数和超参数通常是一项麻烦且容易出错的任务。虽然有网格搜索方法可用于搜索最佳参数组合,但通过在参数空间上运行优化循环,可以轻松引入一定程度的自动化。在这种情况下,目标函数必须是 ML 模型预测质量的某种度量(例如,均方误差、复杂性度量或 F1 分数)。

使用机器学习作为函数评估器

在许多情况下,你不可能有一个好的、封闭形式的分析函数来作为优化问题的目标。

但是当我们有了深度学习的时候,谁会在乎变好呢?

想象一下的威力,一个由众多模型(针对其目标函数和约束条件)提供的优化模型——在基本性质上不同,但在输出格式上是标准化的,因此它们可以协调一致地行动。

你可以自由选择一个解析函数,一个深度学习网络(也许是作为回归模型),甚至是一个复杂的仿真模型,把它们一起扔进优化的坑里。

可能性是无限的!

如果您有任何问题或想法要分享,请联系作者在tirthajyoti【AT】Gmail . com。另外,你可以查看作者的 GitHub 资源库中其他有趣的 Python、R 或 MATLAB 代码片段和机器学习资源。如果你像我一样对机器学习/数据科学充满热情,请随时在 LinkedIn 上添加我在 Twitter 上关注我。

[## Tirthajyoti Sarkar - Sr .首席工程师-半导体、人工智能、机器学习- ON…

佐治亚理工学院理学硕士- MS,分析这一 MS 计划传授理论和实践…

www.linkedin.com](https://www.linkedin.com/in/tirthajyoti-sarkar-2127aa7/)

利用特征工程优化数据科学模型

原文:https://towardsdatascience.com/optimize-data-science-models-with-feature-engineering-cluster-analysis-metrics-development-and-4be15489667a?source=collection_archive---------22-----------------------

聚类分析、指标开发和婴儿姓名数据的 PCA

正如婴儿名字的文章是即将为人父母者的必读之作一样,美国社会保障(SSA)的婴儿名字数据集应该是初露头角的数据科学家的必修课。数据集可以用许多不同的方式分割,包括语言、基于时间的方法和创造性问题的素材。这是一个健康的基于频率的数据集,具有很长的时间线。例如,网站分析工具统计独立用户的访问次数,零售销售点系统统计按颜色销售的产品,银行跟踪一个月内拖欠的贷款数量。本文是关于频率数据集的特征工程教程,其中特征工程的目标是提取每个名称的特征,并发现名称随时间变化的趋势之间的关系。

http://unsplash.com/

我开始探索名字来寻找选择。首先,我假设随着时间的推移,趋势捕捉到了父母选择某些名字的内在品质和社会态度。婴儿名字的趋势能够解释很多关于社会偏好的问题,参见婴儿名字的交叉相关性 NCBI 文章。同样,当你知道某人的名字时,你很可能知道那个人的年龄,见当你只知道某人的名字时,如何说出她的名字,fivethirtyeeight 文章

我自己关于名字的问题:哪些美国名字与我过去的名字 Pauline 最相似?

我根据旧的时尚假设创建了一个功能列表。这意味着类似的名字将在 20 世纪初达到流行的顶峰,在过去的 50 年左右的时间里不会再出现。然后,我使用峰值检测和频率指标从 SSA 数据中手动提取这些特征。这些被称为“手动”特征。然后,我使用主成分分析(PCA)中的手动特征和趋势来创建“自动”特征。

最后,我使用这些自动化的、手动的和组合的特性比较了聚类分析结果。聚类是一种用相似性度量将对象分组在一起的方法。数据科学方法在汇集相似事物方面有着坚实的记录。例如,产品推荐算法通过购买历史和/或人口统计数据来识别像您这样的人,或者确定彼此最常购买的产品(例如,番茄酱和薯条)。

从 SSA 数据集创建的“手动”特征列表:

  1. 相似的名字不会不处于或接近它的流行度的峰值(峰值检测),
  2. 类似的名字在美国比较晦涩(量和加速度),
  3. 相似的名字不要太独特(数量),而且
  4. 相似的名字是主观愉悦的(不可量化)。

数据集、Python 代码和分析可在公共和交互式 Kaggle 笔记本中获得:https://www . ka ggle . com/Pauline chow/baby-names-optimize-w-feature-engineering

什么特征会产生“最好”的婴儿名字短列表?

婴儿名字度量:峰值检测、加速度和等级

SSA 的名字数据追踪了从 1910 年到 2017 年名字的使用频率。姓名频率按年份和性别进行汇总和分组。在笔记本中,第 1 至 3 部分是数据的一般检查,包括数据的抽样、测试统计、大小和形状。该笔记本根据最受欢迎程度、年复一年的变化以及过去 3 年中最受欢迎的 500 个名字的出现情况来创建分类指标。笔记本的第 4 部分介绍了创建、组合和分析这些指标的步骤。

(1)峰值人气检测

每一个名字都有高点(“峰值”)和低点(“谷值”)与自身和全球进行比较,以提供重要信息。例如,“伯莎”和“珍妮”这两个名字分别在 1920 年代和 1970 年代达到了最流行的程度,从那以后就逐渐减少了。从巅峰时期开始,伯莎就一直在稳步下降,而珍妮和詹妮弗在 20 世纪 40 年代至 70 年代稳定下降之前是强有力的竞争者。

在我孩子的一生中,她同龄人的名字将会很流行。一个假设是,如果名字相对于当前群体之前的人口达到显著峰值,并且目前处于减速趋势,那么名字就不太可能再次流行。峰值检测与了解当前加速度或年同比变化相结合,有助于缩小符合当前要求的名称范围。

峰值检测还会返回信息来创建指标。

峰值检测用于数字信号处理和语音识别,以在固定和实时数据中找到局部最小值和最大值。对于姓名,峰值检测可以将姓名与事件、人物和文化联系起来。这里,利用峰值检测来确定最近 5 年、10 年、15 年、20 年和 25 年内的任何峰值,这些峰值作为分类特征保存在数据集中。

在这个笔记本中,波峰和波谷是用一种简单和复杂的方法检测出来的。

(a)峰值检测最直接的方法是计算连续周期之间的符号变化。两个周期之间从正到负的符号变化表示从峰值开始下降。简单算法返回与前一个元素相比减少的索引。 peak_detection_simple 函数的输入数据是一个值列表,例如年度或 5 年滚动平均值。此列表的计算在函数返回索引之前完成。

下面简单的峰值检测函数计算连续时间段之间的差值,并返回符号变化的次数。符号变化被定义为从正到负的运动,并且不区分峰值的幅度或时间长度。

这种简单的方法缺乏纵观一个名字的大趋势的能力。这个简单函数的结果引发了一些问题:如果一个名字在一个“峰值”上花了更多的时间会怎么样?我们应该聚集非常接近的相似峰值吗?从正 a 峰到负 a 峰的哪些波动是显著的?从顶峰倾斜或下降的斜率是否有一个阈值?

(b) Scipy 是一个开放源代码的科学计算软件包,提供数学、科学和工程方面的内置功能。该软件包提供了识别峰值的功能,并且通过附加参数可以进一步区分,参见 scipy.signal.find_peaksscipy find_peaks 函数提供了定义峰的绝对最小值和最大值(高度)、设置峰的最小垂直(阈值)和水平(距离)测量值以及峰的相对强度(突出度)的选项。

(2)年复一年(或任何时间段)的加速或同比变化指标是分析和报告环境中的标准。比较的时间周期越长,输出中标准化的季节性因素就越多。在 python pandas 中,计算 x 年之间的百分比变化会创建最近 x 年加速率的代理。基于不同时期的名称创建了许多特征。

(3)500 强排名名称指标

创建一个分类变量来标记一个名称在过去 3 年中是否排在前 500 名列表中。该指标是一种防止使用实际排名赋予过多权重的方法,即使我们扩大了这个数字。可以将此指标更改为聚合或多或少的年份,收集每年的所有前 X 个名称,并对按州分组的名称进行排名。

一份过去 3 年中排名前 500 名的名单将在以后从最终名单中筛选名字时派上用场。

主成分分析(PCA)的特征

仅凭频率很难预测名字的受欢迎程度。模式不一定是可辨别的,因为灵感是随机的。父母可能会受到迪斯尼电影、公众人物或个人生活事件的影响。一项使用婴儿名字作为美国文化特征指标的研究表明,新名字是发明的,而不是使用过去几代人的名字。婴儿名字的交叉相关性代替手动提取指标,整个趋势可以被分解成解释每个趋势的变化的特征。PCA 变换 PCA 背后的数学原理在这里解释

用 25 个成分运行 PCA,结果显示 3 个和 10 个成分分别累计解释了数据中 80%和 99%的方差。可以在 PCA 结果之前设置累积方差的阈值,尤其是在数据集非常大的情况下。利用主成分分析作为降维技术可以节省计算时间。或者,为后续分析选择的组件数量可以取决于最终模型的结果。这意味着模型可以通过数据输入进一步优化,在这种情况下,它将是组件的数量。

笔记本的第 5 部分转换了功能,并对 4 个和 10 个组件进行了聚类分析。在这种分析中,考虑名称之间的更多差异能够更清晰地将名称划分到聚类中。这里利用的组件越多,最终的聚类轮廓得分就越好。优化聚类质量的结果最符合期望的结果。

使用 k 均值查找聚类

我选择了 Kmeans 聚类分析,这是一种更一般化的姓名分组方法。Kmeans 聚类用于将姓名(观察值)分组为 n 个簇,其中每个姓名被分配给具有最近平均值的簇。聚类的质量可以用剪影分数来度量,范围从-1 到+1,剪影分数确定其自身聚类内以及与其他聚类相比较的观察值的内聚性。

手动、自动和组合数据集的聚类数是根据与 Pauline 相同的聚类中的姓名计数来选择的。

结果婴儿名单

婴儿名字列表的结果是有希望的,因为我们能够从数千到不到 200 个名字。具有手动和自动特征的聚类生成的列表分别包含 155 和 57 个名字。两个名单共有 37 个名字(交叉)。一个集合了人工和自动特征的混合数据集产生了最短的 47 个名字的列表。PCA 特征(自动)识别较少的姓名,但是“遗漏”了由手动特征挑选的潜在姓名。

对于父母来说,为梳理 155 个名字创造一个永远的名字是一个可以接受的任务。我不需要进一步推敲。这与企业形成对比,在企业中,将产量提高两倍可能会导致运营和实质性问题。

特征工程既是一门艺术也是一门科学。聚类分析将产生满足要求的分组,要求越多意味着分组越严格。自动功能更准确地反映了一段时间的趋势。手动特性捕获了内在化的规则或假设,但是导致了大量的噪音。当仅仅依靠自动特性时,感觉就像分析的创造性方面丢失了。我们可以看到特征工程的艺术通过混合数据悄悄渗透到结果中。以下是使用不同功能集生成的名称示例。

这两套特性的完整列表可以从 Jupyter 笔记本上下载。以下是从名单中随机选择的 10 个名字:

关于这些数据,您可以问更多的问题:

  • 我们还能从 SSA 数据集中得出什么其他指标?
  • SSA 数据集中的男性名字也有类似的趋势和见解吗?
  • 聚类分析的哪些属性可以优化以找到相似的名字?此分析仅探究 k 均值分析的聚类数量。如果使用基于连接性或分布的聚类而不是基于质心的聚类会怎样?

阅读 www.fountainofdata.com上的其他数据科学帖子。 Kaggle 笔记本有代码可用 此处 。借助**上传加载。照片由尹新荣Unsplash 上拍摄

优化 NVIDIA GPU 性能,实现高效的模型推断

原文:https://towardsdatascience.com/optimize-nvidia-gpu-performance-for-efficient-model-inference-f3e9874e9fdc?source=collection_archive---------5-----------------------

Image from https://www.cgdirector.com/best-hardware-for-gpu-rendering-in-octane-redshift-vray/

GPU 已被证明是加速计算机视觉和自然语言处理(NLP)等深度学习和人工智能工作负载的有效解决方案。现在,许多基于深度学习的应用程序在其生产环境中使用 GPU 设备,如 NVIDIA Tesla 用于数据中心,Jetson 用于嵌入式平台。这就带来了一个问题:如何从你的 NVIDIA GPU 设备中获得最佳的推理性能?

在本文中,我们将一步一步地展示我们如何优化预训练的 TensorFlow 模型,以改善支持 CUDA 的 GPU 上的推理延迟。在我们的实验中,我们使用 SSD MobileNet V2 进行目标检测。我们在 Colab 上进行实验。所有重现结果的源代码和指令都可以在本笔记本中找到。本文组织如下:

  1. 在 TensorFlow 中下载并运行原始模型
  2. 通过与 CPU 协作优化模型
  3. 使用 TensorRT 优化模型
  4. 比较和结论

TL;速度三角形定位法(dead reckoning)

我们将 Colab GPU 实例上的推理时间改进为:

  1. 通过将控制流操作放在 CPU 上,提高了 1.3 倍
  2. 通过转换预训练的 TensorFlow 模型并在 TensorRT 中运行,可提高 4.0 倍

第 0 步:下载并运行 TensorFlow 中的 origin 模型

我们首先从tensor flow Detection Model Zoo下载 SSD MobileNet V2 预训练模型,该模型提供了一组在 COCO 数据集上训练的预训练模型。

在这个解压缩的文件夹中,我们可以找到以下文件:

  • frozen_inference_graph.pb是针对任意图像和批次大小的冻结推理图
  • pipeline.config包含用于生成模型的配置
  • model.ckpt.*包含预先训练好的模型变量
  • saved_model文件夹包含 TensorFlow SavedModel 文件

然后,我们使用 TensorFlow 对象检测 API 导出模型。这允许我们固定批量大小和图像大小。对于这个实验,我们使用 300x300 的图像作为输入,批量大小为 1。因此,我们的输入形状是[1, 300, 300, 3]

现在我们已经准备好运行模型了。我们首先从互联网上下载输入图像,并预处理成所需的形状。然后,我们使用 TensorFlow 加载模型并执行推理。请注意,我们添加了optionsrun_metadata来记录分析数据,以便进一步分析。

最后,我们执行健全性检查以确保模型做出有意义的推断。注意,SSD MobileNet V2 模型将图像阵列作为每个检测到的对象的输入和输出绑定框[xmin, ymin, xmax, ymax]。我们使用输出来绘制结合框,并得到以下结果。

Detection result we get from previous run

这个结果听起来很合理。因此,我们可以相信我们的模型工作正常。现在,我们准备分析性能。我们将使用 Chrome 的跟踪工具来分析模型。打开 Chrome 浏览器,输入网址chrome://tracing。拖动我们从上一个脚本中得到的时间轴 JSON 文件,然后我们可以看到下面的界面。

Inference timeline trace for origin SSD MobileNert V2

从上面的跟踪中,您可能会注意到一些操作是在 CPU 上运行的,即使我们告诉 TensorFlow 在 GPU 上运行所有这些操作。这是因为 TensorFlow 没有为这些操作注册 GPU 内核(例如NonMaxSuppressionV3)。由于这些操作无法在 GPU 上处理,TensorFlow 必须将中间输出从 GPU 内存传输到 CPU 内存,在 CPU 上处理,并将结果传输回 GPU,然后继续进行。从图中可以看出,这种情况发生了很多次。结果,我们的程序在数据传输上花费了太多时间,变得更慢。

此外,从图表的底部,我们可以看到每种类型的操作的时间成本。花费时间最多的前 3 项操作是GatherV2NonMaxSuppressionV3Conv2D。当它对Conv2D有意义时,因为 MobileNet V2 严重依赖它,并且计算量很大,它对其他人没有意义。我们将在下一节中解决这些问题并优化我们模型的推理性能。

第一步:与 CPU 合作优化模型

许多人认为 GPU 比 CPU 快——这就是为什么我们使用 GPU 来加速我们的程序。然而,这只是部分正确。为了解释这一点,我们需要了解一点 GPU 是如何工作的。

CPU 和 GPU 之间浮点能力的差异背后的原因是 GPU 专门用于计算密集型、高度并行的计算,这正是图形渲染的目的,因此设计了更多的晶体管用于数据处理,而不是数据缓存和流控制,如下图所示:

CPU vs. GPU structure, reference from CUDA Toolkit documentation

因此,对于可以并行处理的操作,如矩阵乘法,GPU 比 CPU 快得多。然而,由于 GPU 具有较少的用于流控制和高速缓存的晶体管,这可能不是流控制操作的情况(例如,ifwherewhile等)。).

我们在 CPU 和 GPU 上运行时间开销最高的 5 个操作(除了NonMaxSuppressionV3,因为它只能在 CPU 上处理),并比较它们的性能,我们得到以下结果:

我们可以看到,对输入数据进行矩阵乘法和加法运算的Conv2D,在 GPU 上的运行速度比预期快了~ 10 倍。但是对于GatherV2ConcatV2Select这些访问内存给定索引的,CPU 的表现都优于 GPU。因此,我们可以通过简单地将这些操作放在 CPU 上来提高我们的推理性能:

上述代码将所有操作放在 CPU 的NonMaxSuppression块中,因为大多数流控制操作都发生在这个块中。然后,我们使用相同的代码测试修改后的模型,并记录时间轴跟踪。我们得到以下结果:

Inference timeline trace for our optimized model

请注意,总推断时间从~50 毫秒减少到~30 毫秒GatherV2的时间成本现在是 2.140 毫秒,相比之下原来是 5.458 毫秒。ConcatV2的时间成本从 3.588 毫秒减少到 1.422 毫秒。此外,在修改后的模型中,GPU 和 CPU 之间的数据传输更少。所以像NonMaxSuppressionV3这种原本在 CPU 上运行的操作也受益于此。

第二步:使用 TensorRT 优化模型

在本节中,我们将展示如何通过使用 NVIDIA TensorRT 来进一步加速推理。

什么是 tensort

NVIDIA TensorRT 是一个高性能深度学习推理平台。它包括一个深度学习推理优化器和运行时,为深度学习推理应用程序提供低延迟和高吞吐量。

TensorRT overview from NVIDIA TensorRT

为什么使用 tensort

TensorRT 提供了一系列用于深度学习模型优化的工具,如精度校准和层融合。您可以在不了解底层算法细节的情况下使用这些方便的工具。此外,TensorRT 专门为您的 GPU 设备选择内核,进一步优化性能。我们总结了使用 TensorRT 的利弊:

优点:

  • 方便的优化工具使用户能够轻松有效地优化生产模型
  • 特定于平台的内核选择,最大限度地提高您设备的性能
  • 支持 TensorFlow 和 Caffe 等主要框架

缺点:

  • TensorRT 中仅支持部分操作。因此,在构建模型时,您必须仔细选择图层,以使其与 TensorRT 兼容

要在 TensorRT 中运行预训练的 TensorFlow 模型,我们需要执行以下步骤:

  1. 将张量流模型转换为 UFF 格式
  2. 构建 TensorRT 推理引擎

将张量流模型转换为 UFF 格式

首先,我们使用图形外科医生和 UFF 转换器将 SSD MobileNet V2 TensorFlow 冻结模型转换为 TensorRT 可以解析的 UFF 格式。对于一些简单的模型(例如 Mobilenet V2,Inception v4 用于图像分类),我们可以直接使用 UFF 转换器进行转换。但是,对于包含 TensorRT 不支持的操作的模型(如 SSD MobileNet V2 中的NonMaxSuppression ),我们必须做一些预处理。诀窍是使用 Graph Surgeon 用支持的操作替换不支持的操作。

下面的脚本提供了一个预处理函数并修改了原始图形。关键的操作是用NMS_TRT操作代替了原图中的NonMaxSuppression 操作,这是一个用于非最大值抑制的 TensorRT 核。然后,它将修改后的图形传递给 UFF 转换器,并输出最终的 UFF 模型。

构建 TensorRT 推理机

现在我们有了 UFF 模型文件。我们准备制造 TensorRT 发动机。您可以构建一次引擎,并将其部署到不同的设备上。但是,由于引擎针对构建它的设备进行了优化,因此建议针对不同的设备重新构建引擎,以最大限度地提高设备性能。

现在我们有了 tensort 引擎,我们准备在 tensort 上运行我们的模型。请注意,TensorRT 需要 NCHW 格式的输入图像。因此,我们的输入格式应该是[1, 3, 300, 300],而不是 TensorFlow 中的[1, 300, 300, 3]

在我们的实验中,这次运行的平均推断时间是 4.9 毫秒。

比较和结论

我们比较我们实验的推理时间,得到如下的情节:

Inference time comparison

我们可以看到,通过简单地将控制流操作放在 CPU 上,与原始模型相比,我们获得了 1.3 倍的性能提升。通过使用 TensorRT,与原始模型相比,我们可以获得 4 倍的改进。

总之,使用各种技术可以进一步提高 GPU 性能。在我们的实验中,我们通过以下方式优化预训练的 SSD Mobilenet V2 张量流模型:

  1. 将控制流操作放在 CPU 上并获得 1.3 倍的改进
  2. 跑合 TensorRT,增益 4x 提升

当 TensorRT 达到最佳性能时,它支持有限的操作。考虑在您生产环境中使用这些技术来最大化您的 GPU 性能。最后,我们强烈建议在 Colab 上运行这个实验,看看如何实现性能。

为深度学习优化您的 CPU

原文:https://towardsdatascience.com/optimize-your-cpu-for-deep-learning-424a199d7a87?source=collection_archive---------3-----------------------

在过去的几年里,深度学习已经在学术界和工业界加快了步伐。每个公司现在都在寻找基于人工智能的问题解决方案。这种繁荣有其自身的优点和缺点,但这是另一篇文章,另一天。机器学习从业者的激增已经渗透到了学术界的根部,几乎每个领域的每个学生都可以通过课程、MOOCs、书籍、文章和课程论文获得人工智能和人工智能知识。

然而,这种增长受到硬件资源可用性的限制。有人建议,并证明了图形处理器是最好的设备之一,你可以有执行你的 ML 任务的速度。但是,一个好的高性能 GPU 的价格标签甚至可以高达 20,449.00 美元一个英伟达特斯拉 V100 32GB GPU ,它具有类似服务器的计算能力。此外,一台配有像样 GPU 的消费笔记本电脑价格约为2000 美元,GPU 为 1050Ti 或 1080Ti。为了减轻痛苦,谷歌、Kaggle、英特尔和英伟达免费提供基于云的高计算系统,对空间、计算能力、内存或时间都有限制。但是这些在线服务有其缺点,包括管理数据(上传/下载)、数据隐私等。这些问题引出了我的文章的主要观点,“为什么不优化我们的 CPU,以提高深度学习任务的速度?”。

英特尔已经为 Python、Tensorflow、Pytorch 等提供了优化。拥有一整套英特尔优化支持库,如 NumPy、scikit-learn 等。这些都可以免费下载和设置,并在英特尔酷睿 i7 这样的 CPU 上提供 2 倍甚至 5 倍的速度,而英特尔酷睿 i7 也不是至强系列这样的高性能 CPU。在本文的剩余部分,我将演示如何在您的 PC/笔记本电脑中设置英特尔优化,并将提供我观察到的加速数据。

获得性能提升

对于下面提到的各种实验,我将展示我观察到的时间和利用率提升。

  1. 用于 CIFAR-100 图像分类的 10 层深度 CNN。
  2. 用于 IMDB 情感分析的 3 层深度 LSTM。
  3. 6 层深密 ANN 用于 MNIST 影像分类。
  4. 用于 MNIST 的 9 层深度全卷积自动编码器。

这些任务已使用 tensorflow 后端在 Keras 中编码,数据集与代码和可执行库位于同一硬盘中。使用的硬盘是 SSD。

我们将考虑以下六种优化组合。

  1. 英特尔酷睿 i7 处理器。
  2. 英特尔至强处理器 E3–1535m V6。
  3. 英特尔酷睿 i7 和英特尔 Python(英特尔 i7*)。
  4. 英特尔至强处理器 E3–1535m V6,采用英特尔 Python(英特尔至强*)。
  5. 采用英特尔 Python 和处理器线程优化的英特尔酷睿 i7(英特尔 i7(O))。
  6. 英特尔至强处理器 E3–1535m V6,采用英特尔 Python 和处理器线程优化(英特尔至强处理器)。

对于每项任务,历元数固定为 50。在下面的图表中,我们可以看到,对于一个英特尔(R)酷睿(TM)i7–7700 HQ CPU @ 2.80 GHz CPU,每个时期的平均时间接近 4.67 秒,经过适当的优化后,它下降到 1.48 秒,提升了 3.2 倍。对于一个英特尔至强处理器 E3–1535m V6 @ 3.10 GHz CPU,每个周期的平均时间接近 2.21 秒,经过适当优化后下降到 0.64 秒,提升了 3.45 倍。

Average time per epoch

优化不仅是及时的,优化的分布还优化了 CPU 利用率,最终导致更好的热量管理,并且您的笔记本电脑不会像过去那样受热,而训练深度神经网络。

Utilization

我们可以看到,在没有任何优化的情况下,训练时的 CPU 利用率达到了 100%,降低了所有其他进程的速度,并使系统发热。然而,通过适当的优化,i7 的利用率下降到 70%,至强的利用率下降到 65%,尽管在时间方面提供了性能增益。

这两个指标可以相对概括如下。

在上图中,值越低越好,也就是说,相对而言,经过所有优化的英特尔至强处理器是性能指标评测的基准,在优化使用后,英特尔酷睿 i7 处理器每周期的时间几乎是至强处理器的两倍。上图清楚地显示了英特尔 Python 优化在训练神经网络所用时间和 CPU 使用方面的光明面。

设置英特尔的 Python 发行版

英特尔软件提供了关于如何设置的详尽资源列表,但我们可能会经常遇到一些问题。更多关于发行的细节可以在这里找到。您可以选择安装类型,即本机 pip 或 conda。我更喜欢 conda,因为它为我节省了大量的麻烦,我可以专注于 ML 而不是解决我的库的兼容性问题。

1)下载并安装 Anaconda

你可以从这里下载 Anaconda。他们的网站列出了在 windows、ubuntu 和 macOS 环境下安装 Anaconda 的所有步骤,并且很容易掌握。

2)在您的 Anaconda 发行版中设置英特尔 python

这一步通常会变得棘手。最好为英特尔分发创建一个虚拟环境,这样您就可以随时在一个地方添加/更改您的优化库。让我们创建一个名为“ intel”的新虚拟环境

conda create -n intel -c intel [intelpython3_ful](https://anaconda.org/intel/intelpython3_full)l

这里 -c 代表通道,所以我们不把 Intel 加为通道,而是把那个通道称为 via -c 。在这里,intelpython3_full 将自动从英特尔的发行版中获取必要的库,并将它们安装到您的虚拟环境中。此命令将安装下列库。

The following NEW packages will be INSTALLED:asn1crypto         intel/win-64::asn1crypto-0.24.0-py36_3
bzip2              intel/win-64::bzip2-1.0.6-vc14_17
certifi            intel/win-64::certifi-2018.1.18-py36_2
cffi               intel/win-64::cffi-1.11.5-py36_3
chardet            intel/win-64::chardet-3.0.4-py36_3
cryptography       intel/win-64::cryptography-2.3-py36_1
cycler             intel/win-64::cycler-0.10.0-py36_7
cython             intel/win-64::cython-0.29.3-py36_1
daal               intel/win-64::daal-2019.3-intel_203
daal4py            intel/win-64::daal4py-2019.3-py36h7b7c402_6
freetype           intel/win-64::freetype-2.9-vc14_3
funcsigs           intel/win-64::funcsigs-1.0.2-py36_7
icc_rt             intel/win-64::icc_rt-2019.3-intel_203
idna               intel/win-64::idna-2.6-py36_3
impi_rt            intel/win-64::impi_rt-2019.3-intel_203
intel-openmp       intel/win-64::intel-openmp-2019.3-intel_203
intelpython        intel/win-64::intelpython-2019.3-0
intelpython3_core  intel/win-64::intelpython3_core-2019.3-0
intelpython3_full  intel/win-64::intelpython3_full-2019.3-0
kiwisolver         intel/win-64::kiwisolver-1.0.1-py36_2
libpng             intel/win-64::libpng-1.6.36-vc14_2
llvmlite           intel/win-64::llvmlite-0.27.1-py36_0
matplotlib         intel/win-64::matplotlib-3.0.1-py36_1
menuinst           intel/win-64::menuinst-1.4.1-py36_6
mkl                intel/win-64::mkl-2019.3-intel_203
mkl-service        intel/win-64::mkl-service-1.0.0-py36_7
mkl_fft            intel/win-64::mkl_fft-1.0.11-py36h7b7c402_0
mkl_random         intel/win-64::mkl_random-1.0.2-py36h7b7c402_4
mpi4py             intel/win-64::mpi4py-3.0.0-py36_3
numba              intel/win-64::numba-0.42.1-np116py36_0
numexpr            intel/win-64::numexpr-2.6.8-py36_2
numpy              intel/win-64::numpy-1.16.1-py36h7b7c402_3
numpy-base         intel/win-64::numpy-base-1.16.1-py36_3
openssl            intel/win-64::openssl-1.0.2r-vc14_0
pandas             intel/win-64::pandas-0.24.1-py36_3
pip                intel/win-64::pip-10.0.1-py36_0
pycosat            intel/win-64::pycosat-0.6.3-py36_3
pycparser          intel/win-64::pycparser-2.18-py36_2
pyopenssl          intel/win-64::pyopenssl-17.5.0-py36_2
pyparsing          intel/win-64::pyparsing-2.2.0-py36_2
pysocks            intel/win-64::pysocks-1.6.7-py36_1
python             intel/win-64::python-3.6.8-6
python-dateutil    intel/win-64::python-dateutil-2.6.0-py36_12
pytz               intel/win-64::pytz-2018.4-py36_3
pyyaml             intel/win-64::pyyaml-4.1-py36_3
requests           intel/win-64::requests-2.20.1-py36_1
ruamel_yaml        intel/win-64::ruamel_yaml-0.11.14-py36_4
scikit-learn       intel/win-64::scikit-learn-0.20.2-py36h7b7c402_2
scipy              intel/win-64::scipy-1.2.0-py36_3
setuptools         intel/win-64::setuptools-39.0.1-py36_0
six                intel/win-64::six-1.11.0-py36_3
sqlite             intel/win-64::sqlite-3.27.2-vc14_2
tbb                intel/win-64::tbb-2019.4-vc14_intel_203
tbb4py             intel/win-64::tbb4py-2019.4-py36_intel_0
tcl                intel/win-64::tcl-8.6.4-vc14_22
tk                 intel/win-64::tk-8.6.4-vc14_28
urllib3            intel/win-64::urllib3-1.24.1-py36_2
vc                 intel/win-64::vc-14.0-2
vs2015_runtime     intel/win-64::vs2015_runtime-14.0.25420-intel_2
wheel              intel/win-64::wheel-0.31.0-py36_3
win_inet_pton      intel/win-64::win_inet_pton-1.0.1-py36_4
wincertstore       intel/win-64::wincertstore-0.2-py36_3
xz                 intel/win-64::xz-5.2.3-vc14_2
zlib               intel/win-64::zlib-1.2.11-vc14h21ff451_5

您可以看到,对于每个库,轮盘的描述以“【Intel/…”开头,这表示该库正在从英特尔的分销渠道下载。一旦您同意安装这些库,它们将开始被下载和安装。

这一步是第一个问题的来源。有时,这些库没有被下载,列表传播,或者我们得到一个 SSL 错误,命令退出。这个问题甚至可能会被延迟,也就是说,现在所有的东西都会被下载和安装,但是稍后如果你想添加任何新的库,提示会抛出 SSL 错误。如上所述,在为英特尔创建虚拟环境之前,有一个简单的方法可以解决这个问题。

在您的 shell 或命令提示符下,通过以下命令关闭 anaconda 的默认 SSL 验证

conda config --set ssl_verify false

关闭 SLL 验证后,您可以通过删除之前创建的环境并重新启动来重复步骤 2。

3)建立张量流

恭喜你!!现在,您已经在您的 PC/笔记本电脑中设置了英特尔的 python 发行版。是时候进入 ML 管道了。

英特尔已通过所有分销渠道为 tensorflow 提供了优化,安装非常顺利。你可以在这里了解更多信息。让我们看看如何为我们的 CPU 安装优化的 tensorflow。英特尔软件提供了一个优化的数学内核库(mkl ),它可以优化数学运算,并为用户提供所需的加速。因此,我们将如下安装 tensorflow-mkl。

conda install tensorflow-mkl

或者使用 pip,可以按如下方式进行设置。

pip install intel-tensorflow

瞧啊。!Tensorflow 现已启动并在您的系统中运行,并进行了必要的优化。如果你是一个 Keras 粉丝,你可以用一个简单的命令来设置它

conda install keras -c intel

4)建立 Jupyter

由于我们已经创建了一个新的虚拟环境,默认情况下它不会与 spyder 或 jupyter 笔记本一起提供。然而,设置这些是很简单的。只要一句话,我们就能创造奇迹。

conda install jupyter -c intel

5)激活环境,开始实验

现在我们已经设置好了所有的东西,是时候开始在我们优化的 CPU 系统上用各种 ML 和 DL 方法进行编码和实验了。首先,在执行任何代码之前,确保您正在使用正确的环境。您需要激活虚拟环境,然后才能使用其中安装的库。这个激活步骤是一个全天候的过程,而且毫不费力。在 anaconda 提示符下编写以下命令,就可以开始了。

conda activate intel

要对您的环境进行健全性检查,请在激活环境后,在命令提示符/shell 中键入以下内容。

python

键入 python 后按 enter 键,命令提示符中应该会出现以下文本。确保在管道之间有“英特尔公司”字样,并有消息“英特尔公司为您提供 Python 的英特尔(R)发行版。”。这些验证了英特尔 Python 发行版的正确安装。

Python 3.6.8 |Intel Corporation| (default, Feb 27 2019, 19:55:17) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
Intel(R) Distribution for Python is brought to you by Intel Corporation.
Please check out: [https://software.intel.com/en-us/python-distribution](https://software.intel.com/en-us/python-distribution)

现在,您可以使用命令行来试验或在其他地方编写您的脚本,并使用。py 扩展名。然后,可以通过“cd”命令导航到文件的位置并通过以下方式运行脚本来访问这些文件:-

(intel) C:\Users\User>python script.py

通过执行步骤 1 到 4,您的系统将具备上述性能指标评测图表中提到的*英特尔 xyz** 水平。这些仍然不是基于多处理器的线程优化。我将在下面讨论如何为您的多核 CPU 实现进一步的优化。

多核优化

要为您的多核系统添加进一步的优化,您可以将以下代码行添加到您的。py 文件,它将相应地执行脚本。这里NUM _ PARALLEL _ EXEC _ UNITS代表你拥有的核心数;我有一台四核 i7。因此数字是 4。对于 Windows 用户,您可以通过导航到任务管理器- >性能- > CPU - >核心来检查任务管理器中的核心数。

from keras import backend as K
import tensorflow as tfNUM_PARALLEL_EXEC_UNITS = 4
config = tf.ConfigProto(intra_op_parallelism_threads=NUM_PARALLEL_EXEC_UNITS, inter_op_parallelism_threads=2,
                       allow_soft_placement=True, device_count={'CPU': NUM_PARALLEL_EXEC_UNITS})session = tf.Session(config=config)K.set_session(session)os.environ["OMP_NUM_THREADS"] = "4"os.environ["KMP_BLOCKTIME"] = "30"os.environ["KMP_SETTINGS"] = "1"os.environ["KMP_AFFINITY"] = "granularity=fine,verbose,compact,1,0"

如果您不使用 Keras,而更喜欢使用 core tensorflow,那么脚本几乎保持不变,只需删除以下两行。

from keras import backend as K

K.set_session(session)

在您的代码中添加这些行之后,速度应该可以与上面性能图表中的英特尔 xyz(O) 条目相媲美。

如果您的系统中有一个 GPU,并且它与当前的库集冲突或抛出 cudnn 错误,那么您可以在代码中添加以下行来禁用 GPU。

os.environ["CUDA_VISIBLE_DEVICES"] = "-1"

结论

就是这样。你现在有一个优化的管道来测试和开发机器学习项目和想法。这一渠道为参与学术研究的学生提供了很多机会,让他们可以利用自己的系统继续工作。该管道还将防止从业者可能正在处理的私人数据的隐私担忧。

还可以观察到,通过适当的微调,人们可以在工作流程中获得 3.45 倍的加速,这意味着如果您正在试验您的想法,您现在的工作速度可以是以前的三倍。

使用深度 Q 学习优化空间入侵者:Tensorflow 2.0 中的实现。

原文:https://towardsdatascience.com/optimized-deep-q-learning-for-automated-atari-space-invaders-an-implementation-in-tensorflow-2-0-80352c744fdc?source=collection_archive---------13-----------------------

探索数据预处理的效果

介绍

在过去几篇关于 GradientCrescent 的文章中,我们花了大量时间探索在线学习领域,这是一个高度反应性的强化学习算法家族,背后隐藏着许多通用人工智能的最新成就。在线学习属于基于样本的学习类方法,reliant 允许简单地通过重复观察来确定状态值,消除了对转换动态的需要。与它们的离线对应方式不同,在线学习方法允许在环境事件期间对状态和动作的值进行增量更新,允许观察到持续的、增量的性能改进。

除了时间差异学习(TD ),我们还讨论了 Q-learning 的理论实际实现,这是 TD 的一种发展,旨在允许增量估计和状态-动作值的改进。Q-learning 因成为模拟游戏环境的强化学习方法的支柱而闻名,如在 OpenAI 的健身房中观察到的那些。因为我们已经在过去的文章中涉及了 Q-learning 的理论方面,所以这里不再重复。

Q-learning powered Miss Pacman, a implemented in our previous article.

在我们之前对 OpenAI 的 Pacman 小姐健身房环境的实现中,我们依赖于一组单个游戏帧的观察实例(状态)作为我们训练过程的输入。然而,这种方法存在部分缺陷,因为它没有考虑 Atari 游戏环境的许多特性,包括:

  • 经典 Atari 游戏中观察到的游戏环境的跳帧渲染。
  • 环境中存在多个快速移动的参与者。
  • 在代理和环境中观察到的特定于帧的闪烁。

总的来说,这些问题可能会大大降低代理的性能,因为一些数据实例实际上已经超出了领域,或者与实际的游戏环境完全无关。此外,这些问题只会随着更复杂的游戏环境和现实世界的应用(如自动驾驶)而变得更加复杂。我们在之前的实施中观察到,在培训过程中,这种情况表现为高水平的变化和绩效持平。

Reward versus training episodes for our Q-learning trained Miss Pacman agent, trained over 600+800 cycles.

为了克服这些问题,我们可以利用由 Deepmind 团队在 2015 年首次引入的几项技术。

  • 帧堆叠:将几个游戏帧连接在一起,为我们的游戏环境提供一个时间参考。
  • 帧合成:两个游戏帧的元素最大化,以提供一个运动参考,也克服了部分渲染的问题。

让我们在更复杂的 Atari Space Invader 环境中实现检查这些技术的效果。

实施

我们的 Google 协作实现是利用 Tensorflow Core 用 Python 编写的,可以在 GradientCrescent Github 上找到。我们已经使用新的 compat 包将我们的代码转换为 TF2 兼容的。首先,让我们简要回顾一下 Q-learning 实现所需的操作。

  1. 我们定义我们的深度 Q 学习神经网络。这是一个 CNN,它拍摄游戏中的屏幕图像,并输出 Ms-Pacman gamespace 中每个动作的概率,或 Q 值。为了获得概率张量,我们在最后一层不包括任何激活函数。
  2. 由于 Q-learning 要求我们了解当前和下一个状态,我们需要从数据生成开始。我们将表示初始状态 s 的游戏空间的预处理输入图像输入到网络中,并获取动作的初始概率分布,或 Q 值。在训练之前,这些值将是随机的和次优的。请注意,我们的预处理现在还包括堆叠和合成。
  3. 利用我们的概率张量,我们然后使用 argmax()函数选择具有当前最高概率的动作,并使用它来构建ε贪婪策略。
  4. 使用我们的策略,我们将选择动作 a ,并评估我们在健身房环境中的决定,以让接收关于新状态s’的信息、奖励 r ,以及该集是否已经结束。
  5. 我们以列表形式将该信息组合存储在一个缓冲区中,并重复步骤 2-4 预设次数,以建立一个足够大的缓冲区数据集。
  6. 一旦步骤 5 完成,我们转到生成损失计算所需的目标 yR’A’。虽然前者只是从 R 中减去,但我们通过将S’输入到我们的网络中来获得 A’。
  7. 所有的组件都准备好了,我们就可以计算训练网络的损耗了。
  8. 培训结束后,我们将通过图形和演示来评估代理的表现。

作为参考,让我们首先演示使用普通数据输入方法的结果,这与我们之前为 Pacman 小姐实施的中观察到的结果基本相同。在对我们的代理人进行了 800 集的训练后,我们观察到以下的报酬分布。

Reward distribution for the vanilla data input approach for the Space Invaders environment.

请注意性能的变化如何表现出高度的变化,在 650 次发作后观察到非常有限的改善。

同样,我们代理的性能也不太好,几乎没有检测到任何逃避行为。如果你仔细观察,你会注意到出射和入射激光轨迹的闪烁——这是游戏环境中有意的一部分,导致某些帧中根本没有投射物,或者只有一组投射物可见。这意味着我们输入数据的元素具有高度误导性,并对代理绩效产生负面影响。

让我们检查一下改进后的实现。

我们首先导入所有必要的包,包括 OpenAI gym 环境和 Tensorflow 核心。

import numpy as npimport gymimport tensorflow as tffrom tensorflow.contrib.layers import flatten, conv2d, fully_connectedfrom collections import deque, Counterimport randomfrom datetime import datetime

接下来,我们定义一个预处理函数,从我们的健身房环境中裁剪图像,并将它们转换成一维张量。在我们的 Pong 自动化实现中,我们已经看到了这一点。

def preprocess_observation(obs): # Crop and resize the image img = obs[25:201:2, ::2] # Convert the image to greyscale img = img.mean(axis=2) # Improve image contrast img[img==color] = 0 # Next we normalize the image from -1 to +1 img = (img - 128) / 128 - 1 return img.reshape(88,80)

接下来,让我们初始化健身房环境,检查几个游戏画面,并了解 gamespace 中可用的 9 个动作。当然,我们的代理人无法获得这些信息。

env = gym.make(“SpaceInvaders-v0”)n_outputs = env.action_space.nprint(n_outputs)print(env.env.get_action_meanings())observation = env.reset()import tensorflow as tfimport matplotlib.pyplot as pltfor i in range(22):if i > 20:plt.imshow(observation)plt.show()observation, _, _, _ = env.step(1)

您应该遵守以下几点:

我们可以借此机会比较我们的原始和预处理输入图像:

接下来,我们将输入堆叠和输入组合引入预处理管道。在新的一集里,我们从获取两个输入帧开始,并返回这两个帧的元素式最大总和 maxframe (注意,从技术上讲这是不必要的,因为这两个帧是相同的,但这是一种很好的实践)。堆叠的帧存储在队列中,当引入新的条目时,队列会自动删除旧的条目。最初,我们复制预处理的 maxframe 来填充我们的 deque。随着剧集的进展,我们通过获取新的帧来创建新的 maxframes ,将它与我们的 dequee 中最近的条目进行元素式最大求和,然后将新的 maxframe 附加到我们的 dequee。然后,我们在流程的最后堆叠这些帧。

stack_size = 4 # We stack 4 composite frames in total# Initialize deque with zero-images one array for each image. Deque is a special kind of queue that deletes last entry when new entry comes instacked_frames = deque([np.zeros((88,80), dtype=np.int) for i in range(stack_size)], maxlen=4)def stack_frames(stacked_frames, state, is_new_episode):# Preprocess frameframe = preprocess_observation(state) if is_new_episode: # Clear our stacked_frames stacked_frames = deque([np.zeros((88,80), dtype=np.int) for i in range(stack_size)], maxlen=4) # Because we’re in a new episode, copy the same frame 4x, apply elementwise maxima maxframe = np.maximum(frame,frame) stacked_frames.append(maxframe) stacked_frames.append(maxframe) stacked_frames.append(maxframe) stacked_frames.append(maxframe) # Stack the frames stacked_state = np.stack(stacked_frames, axis=2) else: #Since deque append adds t right, we can fetch rightmost element maxframe=np.maximum(stacked_frames[-1],frame) # Append frame to deque, automatically removes the oldest frame stacked_frames.append(maxframe) # Build the stacked state (first dimension specifies different frames) stacked_state = np.stack(stacked_frames, axis=2) return stacked_state, stacked_frames

接下来,让我们定义我们的模型,一个深度 Q 网络。这本质上是一个三层卷积网络,它获取预处理的输入图像,展平并将其馈送到一个全连接层,并输出在游戏空间中采取每个行动的概率。如前所述,这里没有激活层,因为激活层的存在会导致二进制输出分布。

**def q_network(X, name_scope):**# Initialize layersinitializer = tf.compat.v1.keras.initializers.VarianceScaling(scale=2.0)with tf.compat.v1.variable_scope(name_scope) as scope:# initialize the convolutional layerslayer_1 = conv2d(X, num_outputs=32, kernel_size=(8,8), stride=4, padding=’SAME’, weights_initializer=initializer)tf.compat.v1.summary.histogram(‘layer_1’,layer_1)layer_2 = conv2d(layer_1, num_outputs=64, kernel_size=(4,4),    stride=2, padding=’SAME’, weights_initializer=initializer)tf.compat.v1.summary.histogram(‘layer_2’,layer_2)layer_3 = conv2d(layer_2, num_outputs=64, kernel_size=(3,3), stride=1, padding=’SAME’, weights_initializer=initializer)tf.compat.v1.summary.histogram(‘layer_3’,layer_3)flat = flatten(layer_3)fc = fully_connected(flat, num_outputs=128, weights_initializer=initializer)tf.compat.v1.summary.histogram(‘fc’,fc)#Add final output layeroutput = fully_connected(fc, num_outputs=n_outputs, activation_fn=None, weights_initializer=initializer)tf.compat.v1.summary.histogram(‘output’,output)vars = {v.name[len(scope.name):]: v for v in tf.compat.v1.get_collection(key=tf.compat.v1.GraphKeys.TRAINABLE_VARIABLES, scope=scope.name)}#Return both variables and outputs togetherreturn vars, output

让我们也借此机会为我们的模型和训练过程定义超参数。注意,由于我们的堆叠框架,X_shape 现在是(无,88,80,4)

num_episodes = 800batch_size = 48input_shape = (None, 88, 80, 1)learning_rate = 0.001X_shape = (None, 88, 80, 4)discount_factor = 0.97global_step = 0copy_steps = 100steps_train = 4start_steps = 2000

回想一下,Q-learning 要求我们选择具有最高行动值的行动。为了确保我们仍然访问每一个可能的状态-行为组合,我们将让我们的代理遵循一个ε贪婪策略,探索率为 5%。我们将这个探索率设置为随时间衰减,因为我们最终假设所有的组合都已经被探索过了——在那个点之后的任何探索只会导致次优行动的强制选择。

epsilon = 0.5eps_min = 0.05eps_max = 1.0eps_decay_steps = 500000#**def epsilon_greedy(action, step):** p = np.random.random(1).squeeze() #1D entries returned using squeeze epsilon = max(eps_min, eps_max — (eps_max-eps_min) * step/eps_decay_steps) #Decaying policy with more steps if np.random.rand() < epsilon: return np.random.randint(n_outputs) else: return action

回想上面的等式,Q-learning 的更新函数要求如下:

  • 当前状态 s
  • 当前动作一个
  • 当前动作后的奖励 r
  • 下一个状态s’
  • 下一个动作a’

为了以有意义的数量提供这些参数,我们需要按照一组参数评估我们当前的策略,并将所有变量存储在一个缓冲区中,我们将在训练期间从该缓冲区中提取迷你批次中的数据。让我们继续创建我们的缓冲区和一个简单的采样函数:

buffer_len = 20000#Buffer is made from a deque — double ended queueexp_buffer = deque(maxlen=buffer_len)**def sample_memories(batch_size):** perm_batch = np.random.permutation(len(exp_buffer))[:batch_size] mem = np.array(exp_buffer)[perm_batch] return mem[:,0], mem[:,1], mem[:,2], mem[:,3], mem[:,4]

接下来,让我们将原始网络的权重参数复制到目标网络中。这种双网络方法允许我们在使用现有策略的训练过程中生成数据,同时仍然为下一次策略迭代优化我们的参数。

# we build our Q network, which takes the input X and generates Q values for all the actions in the statemainQ, mainQ_outputs = q_network(X, ‘mainQ’)# similarly we build our target Q network, for policy evaluationtargetQ, targetQ_outputs = q_network(X, ‘targetQ’)copy_op = [tf.compat.v1.assign(main_name, targetQ[var_name]) for var_name, main_name in mainQ.items()]copy_target_to_main = tf.group(*copy_op)

最后,我们还将定义我们的损失。这就是我们的目标动作(具有最高动作值)和我们的预测动作的平方差。我们将使用 ADAM 优化器来最大限度地减少我们在训练中的损失。

# define a placeholder for our output i.e actiony = tf.compat.v1.placeholder(tf.float32, shape=(None,1))# now we calculate the loss which is the difference between actual value and predicted valueloss = tf.reduce_mean(input_tensor=tf.square(y — Q_action))# we use adam optimizer for minimizing the lossoptimizer = tf.compat.v1.train.AdamOptimizer(learning_rate)training_op = optimizer.minimize(loss)init = tf.compat.v1.global_variables_initializer()loss_summary = tf.compat.v1.summary.scalar(‘LOSS’, loss)merge_summary = tf.compat.v1.summary.merge_all()file_writer = tf.compat.v1.summary.FileWriter(logdir, tf.compat.v1.get_default_graph())

定义好所有代码后,让我们运行我们的网络并检查培训过程。我们已经在最初的总结中定义了大部分,但是让我们为后代回忆一下。

  • 对于每个时期,在使用ε-贪婪策略选择下一个动作之前,我们将输入图像堆栈输入到我们的网络中,以生成可用动作的概率分布
  • 然后,我们将它输入到网络中,获取下一个状态和相应奖励的信息,并将其存储到我们的缓冲区中。我们更新我们的堆栈,并通过一些预定义的步骤重复这一过程。
  • 在我们的缓冲区足够大之后,我们将下一个状态输入到我们的网络中,以便获得下一个动作。我们还通过贴现当前的奖励来计算下一个奖励
  • 我们通过 Q 学习更新函数生成我们的目标 y 值,并训练我们的网络。
  • 通过最小化训练损失,我们更新网络权重参数,以便为下一个策略输出改进的状态-动作值。
with tf.compat.v1.Session() as sess: init.run() # for each episode
  history = [] for i in range(num_episodes): done = False obs = env.reset() epoch = 0 episodic_reward = 0 actions_counter = Counter() episodic_loss = [] #First step, preprocess + initialize stack obs,stacked_frames= stack_frames(stacked_frames,obs,True) # while the state is not the terminal state
    while not done: #Data generation using the untrained network # feed the game screen and get the Q values for each action actions = mainQ_outputs.eval(feed_dict={X:[obs], in_training_mode:False}) # get the action
    action = np.argmax(actions, axis=-1) actions_counter[str(action)] += 1 # select the action using epsilon greedy policy

    action = epsilon_greedy(action, global_step) # now perform the action and move to the next state, next_obs, receive reward next_obs, reward, done, _ = env.step(action) #Updated stacked frames with new episode next_obs, stacked_frames = stack_frames(stacked_frames, next_obs, False) # Store this transition as an experience in the replay buffer! Quite important exp_buffer.append([obs, action, next_obs, reward, done]) # After certain steps, we train our Q network with samples from the experience replay buffer if global_step % steps_train == 0 and global_step > start_steps: #Our buffer should already contain everything preprocessed and stacked o_obs, o_act, o_next_obs, o_rew, o_done = sample_memories(batch_size) # states o_obs = [x for x in o_obs] # next states o_next_obs = [x for x in o_next_obs] # next actions next_act = mainQ_outputs.eval(feed_dict={X:o_next_obs, in_training_mode:False}) # discounted reward: these are our Y-values y_batch = o_rew + discount_factor * np.max(next_act, axis=-1) * (1-o_done) # merge all summaries and write to the file mrg_summary = merge_summary.eval(feed_dict={X:o_obs, y:np.expand_dims(y_batch, axis=-1), X_action:o_act, in_training_mode:False}) file_writer.add_summary(mrg_summary, global_step) # To calculate the loss, we run the previously defined functions mentioned while feeding inputs train_loss, _ = sess.run([loss, training_op], feed_dict={X:o_obs, y:np.expand_dims(y_batch, axis=-1), X_action:o_act, in_training_mode:True}) episodic_loss.append(train_loss) # after some interval we copy our main Q network weights to target Q network if (global_step+1) % copy_steps == 0 and global_step > start_steps: copy_target_to_main.run() obs = next_obs epoch += 1 global_step += 1 episodic_reward += rewardnext_obs=np.zeros(obs.shape)exp_buffer.append([obs, action, next_obs, reward, done])obs= env.reset()obs,stacked_frames= stack_frames(stacked_frames,obs,True)history.append(episodic_reward)print('Epochs per episode:', epoch, 'Episode Reward:', episodic_reward,"Episode number:", len(history))

一旦训练完成,我们就可以根据增量情节绘制奖励分布图。前 800 集如下所示:

Reward distribution for the stacked and composited approach in the Space Invaders environment.

请注意奖励分布的核心变化是如何显著减少的,从而可以观察到更加一致的剧集间分布,并且表现的增加在统计上变得更加显著。从 550 集开始可以观察到性能的明显提高,比普通数据方法早了整整 100 集,验证了我们的假设。

为了在实验室环境的限制下评估我们的结果,我们可以录制整个情节,并使用基于 IPython 库的包装在虚拟显示器中显示:

“””Utility functions to enable video recording of gym environment and displaying it. To enable video, just do “env = wrap_env(env)””“”**def show_video():**mp4list = glob.glob(‘video/*.mp4’)if len(mp4list) > 0:mp4 = mp4list[0]video = io.open(mp4, ‘r+b’).read()encoded = base64.b64encode(video)ipythondisplay.display(HTML(data=’’’<video alt=”test” autoplayloop controls style=”height: 400px;”><source src=”data:video/mp4;base64,{0}” type=”video/mp4" /></video>’’’.format(encoded.decode(‘ascii’))))else:print(“Could not find video”)    
**def wrap_env(env):**env = Monitor(env, ‘./video’, force=True)return env

然后,我们使用我们的模型运行一个新的环境会话,并记录它。

Evaluate model on openAi GYMenvironment = wrap_env(gym.make('SpaceInvaders-v0'))done = Falseobservation = environment.reset()new_observation = observationprev_input = Nonewith tf.compat.v1.Session() as sess: init.run() observation, stacked_frames = stack_frames(stacked_frames, observation, True) while True: #set input to network to be difference image # feed the game screen and get the Q values for each action actions = mainQ_outputs.eval(feed_dict={X:[observation], in_training_mode:False}) # get the action action = np.argmax(actions, axis=-1) actions_counter[str(action)] += 1 # select the action using epsilon greedy policy action = epsilon_greedy(action, global_step) environment.render() new_observation, stacked_frames = stack_frames(stacked_frames, new_observation, False) observation = new_observation # now perform the action and move to the next state, next_obs, receive reward new_observation, reward, done, _ = environment.step(action) if done: breakenvironment.close()show_video()

我们来考察几轮玩法。

我们的特工已经学会了防守和进攻,有效地利用掩护和躲避。这两个事件之间行为的巨大差异可以归因于 Q 学习的工作方式——早先选择的行为获得了 Q 值,这往往有利于ε贪婪策略。随着进一步的训练,我们希望这两种行为会趋于一致。

这就结束了优化 Q-learning 的介绍。在我们的下一篇文章中,我们将带着我们所学到的一切,从 Atari 的世界继续前进,去解决世界上最著名的 FPS 游戏之一。

我们希望你喜欢这篇文章,并希望你查看 GradientCrescent 上的许多其他文章,涵盖人工智能的应用和理论方面。为了保持对 GradientCrescent 的最新更新,请考虑关注该出版物并关注我们的 Github 资源库。

参考文献

萨顿等人。强化学习

怀特等人。阿尔伯塔大学强化学习基础

席尔瓦等人。阿尔,强化学习,UCL

Ravichandiran 等人。al,用 Python 实践强化学习

Takeshi 等人。艾尔, Github

训练神经网络的各种优化算法

原文:https://towardsdatascience.com/optimizers-for-training-neural-network-59450d71caf6?source=collection_archive---------1-----------------------

正确的优化算法可以成倍地减少训练时间。

许多人可能在训练神经网络时使用优化器,而不知道该方法被称为优化。优化器是用来改变神经网络属性的算法或方法,如权重和学习速率,以减少损失。

Optimizers help to get results faster

你应该如何改变你的神经网络的权重或学习速率来减少损失是由你使用的优化器定义的。优化算法或策略负责减少损失,并尽可能提供最准确的结果。

我们将了解不同类型的优化器及其优势:

梯度下降

梯度下降是最基本但最常用的优化算法。它大量用于线性回归和分类算法。神经网络中的反向传播也使用梯度下降算法。

梯度下降是一种一阶优化算法,它依赖于损失函数的一阶导数。它计算出应该以何种方式改变权重,以使函数达到最小值。通过反向传播,损耗从一层转移到另一层,并且模型的参数(也称为权重)根据损耗进行修改,以便损耗可以最小化。

算法: θ=θ−α⋅∇J(θ)

优点:

  1. 容易计算。
  2. 容易实现。
  3. 很好理解。

缺点:

  1. 可能陷入局部最小值。
  2. 计算整个数据集的梯度后,权重会发生变化。因此,如果数据集过大,可能需要数年时间才能收敛到最小值。
  3. 需要大量内存来计算整个数据集的梯度。

随机梯度下降

这是梯度下降的一个变种。它试图更频繁地更新模型的参数。在这种情况下,在计算每个训练样本的损失之后,改变模型参数。因此,如果数据集包含 1000 行,SGD 将在数据集的一个周期内更新模型参数 1000 次,而不是像梯度下降那样更新一次。

θ=θ−α⋅∇j(θ;x(一);y(i)),其中{x(i),y(i)}为训练示例

由于模型参数频繁更新,参数在不同强度的损失函数中具有高方差和波动。

优点:

  1. 因此,模型参数的频繁更新在更短的时间内收敛。
  2. 需要较少的存储器,因为不需要存储损失函数值。
  3. 可能会得到新的最小值。

缺点:

  1. 模型参数的高方差。
  2. 甚至在达到全局最小值后也可以射击。
  3. 为了获得与梯度下降相同的收敛性,需要缓慢降低学习率的值。

小批量梯度下降

它是所有梯度下降算法中最好的。这是对 SGD 和标准梯度下降的改进。它会在每次批处理后更新模型参数。因此,数据集被分成不同的批次,在每一批次之后,参数被更新。

θ=θ−α⋅∇j(θ;B(i)),其中{B(i)}为训练样本的批次。

优势:

  1. 经常更新模型参数,并且方差较小。
  2. 需要中等大小的内存。

所有类型的梯度下降都有一些挑战:

  1. 选择学习率的最佳值。如果学习率太小,梯度下降可能需要很长时间才能收敛。
  2. 对所有参数都有一个恒定的学习率。可能有些参数我们不想以同样的速度改变。
  3. 可能会陷入局部最小值。

气势

动量是为了减少 SGD 中的高方差和软化收敛而发明的。它加速了向相关方向的收敛,减少了向无关方向的波动。该方法中还使用了一个超参数,称为动量,用“ γ 表示。

V(t)=γV(t1)+α。∇J(θ)

现在,权重更新为θ=θV(t)。

动量项 γ 通常设置为 0.9 或类似值。

优点:

  1. 减少参数的振荡和高方差。
  2. 比梯度下降收敛得更快。

缺点:

  1. 增加了一个需要手动精确选择的超参数。

内斯特罗夫加速梯度

动量可能是一个好方法,但是如果动量太高,算法可能错过局部最小值,并且可能继续上升。因此,为了解决这个问题,开发了 NAG 算法。这是一种前瞻方法。我们知道我们将使用γV(t1)来修改权重,因此θγV(t1)大致告诉我们未来的位置。现在,我们将基于这个未来参数而不是当前参数来计算成本。

V(t)=γV(t1)+α。∇j(θγv(t1)),然后使用θ=θv(t)更新参数。

NAG vs momentum at local minima

优点:

  1. 不会错过局部最小值。
  2. 如果出现最小值,速度会变慢。

缺点:

  1. 尽管如此,超参数仍需要手动选择。

阿达格拉德

所解释的所有优化器的缺点之一是,对于所有参数和每个周期,学习率是恒定的。这个优化器改变了学习率。它改变每个参数的学习率‘η’和每个时间步长‘t’。这是一种二阶优化算法。它对误差函数的导数起作用。

A derivative of loss function for given parameters at a given time t.

Update parameters for given input i and at time/iteration t

η 是一个学习率,在给定的时间,基于为给定的参数 θ(i)计算的先前梯度,对给定的参数 θ(i) 进行修改。

我们存储梯度的平方和 w.r.t. θ(i) 直到时间步长 t ,而 ϵ 是一个避免被零除的平滑项(通常约为 1e 8)。有趣的是,如果没有平方根运算,该算法的性能会差得多。

它对不太频繁的参数进行大的更新,对频繁的参数进行小的更新。

优点:

  1. 每个训练参数的学习率变化。
  2. 不需要手动调整学习率。
  3. 能够在稀疏数据上训练。

缺点:

  1. 因为需要计算二阶导数,所以计算成本高。
  2. 学习率总是下降,导致训练缓慢。

阿达德尔塔

它是阿达格勒的扩展,倾向于消除它的衰减学习率问题。 Adadelta 将累积的过去梯度的窗口限制为某个固定大小 w ,而不是累积所有先前平方的梯度。在此,使用指数移动平均值,而不是所有梯度的总和。

Eg =γ。eg+(1γ)。g (t)

我们将 γ 设置为与动量项相似的值,大约为 0.9。

Update the parameters

优点:

  1. 现在学习速度不衰减,训练不停止。

缺点:

  1. 计算开销很大。

圣经》和《古兰经》传统中)亚当(人类第一人的名字

Adam (自适应力矩估计)适用于一阶和二阶动量。Adam 背后的直觉是,我们不希望滚动得太快,因为我们可以跳过最小值,我们希望稍微降低速度,以便仔细搜索。除了存储类似于 AdaDeltaAdam、的过去平方梯度的指数衰减平均值之外,还保存过去梯度的指数衰减平均值 M(t)。

M(t)和 V(t) 分别是梯度的 均值无中心方差 的一阶矩值。

First and second order of momentum

这里,我们取 M(t)V(t) 的平均值,使得E[M(t)】可以等于 E[g(t)] 其中,E[f(x)】f(x) 的期望值。

要更新参数:

Update the parameters

β1 的值是 0.9,β2 的值是 0.999,而' ϵ' 的值是(10 x exp(-8))。

优点:

  1. 方法太快,收敛很快。
  2. 纠正消失学习率,高方差。

缺点:

计算成本高。

各种优化器之间的比较

Comparison 1

comparison 2

结论

亚当是最好的优化者。如果一个人想在更短的时间内比亚当更有效地训练神经网络,那么他就是优化者。

对于稀疏数据,使用具有动态学习率的优化器。

如果,想使用梯度下降算法比 min-batch 梯度下降是最好的选择。

我希望你们喜欢这篇文章,并且能够对不同优化算法的不同行为有一个很好的直觉。

用蒙特卡罗方法优化 21 点策略

原文:https://towardsdatascience.com/optimizing-blackjack-strategy-through-monte-carlo-methods-cbb606e52d1b?source=collection_archive---------23-----------------------

强化学习的基础

介绍

强化学习已经席卷了人工智能世界。从 AlphaGoAlphaStar ,越来越多的传统人类主导的活动现在已经被由强化学习驱动的人工智能代理所征服。简而言之,这些成就依赖于在一个环境中优化一个主体的行为以获得最大的回报。在过去几篇关于 GradientCrescent 的文章中,我们讨论了强化学习的各个基本方面,从基本的 bandit 系统和 p 基于策略的方法,到在马尔可夫环境中优化基于奖励的行为。所有这些方法都要求我们完全了解我们的环境——例如,动态编程要求我们拥有所有可能状态转换的完整概率分布。然而,在现实中,我们发现大多数系统是不可能完全知道的,并且由于复杂性、固有的不确定性或计算限制,概率分布不能以显式形式获得。打个比方,考虑一下气象学家的任务——预测天气背后涉及的因素可能如此之多,以至于不可能知道确切的概率。

Can you guarantee a certain probability for hurricane formation?

对于这些情况,基于样本的学习方法,如蒙特卡罗,是一个解决方案。术语蒙特卡罗通常用于描述任何依赖于随机抽样的估计方法。换句话说,我们并不假设我们的环境知识,而是通过从与环境的互动中获得的状态、动作和回报的样本序列,从经验中学习。这些方法是通过直接观察模型在正常运行时返回的回报来判断其状态的平均值。有趣的是,已经证明即使没有环境的动态(可以认为是状态转换的概率分布)的任何知识,我们仍然可以获得最佳行为以最大化回报。

作为一个例子,考虑投掷 12 次骰子的回报。通过将这些滚动视为单个状态,我们可以对这些回报进行平均,以接近真实的预期回报。随着样本数量的增加,我们就越能准确地接近实际的预期收益。

The average expected sum of throwing 12 dice rolls 60 times (University of Alberta)

这种基于抽样的估值对我们的忠实读者来说可能很熟悉,因为抽样也是针对 k-bandit 系统进行的。蒙特卡罗方法不是用来比较不同的强盗,而是用来比较马尔可夫环境中的不同政策,通过确定一个状态的值,同时遵循一个特定的政策直到终止。

用蒙特卡罗方法估计状态值

在强化学习的背景下,蒙特卡罗方法是一种通过平均样本回报来估计模型中状态值的方法。由于终端状态的需要,蒙特卡罗方法固有地适用于情节环境。由于这种限制,蒙特卡罗方法通常被认为是“离线”的,在这种情况下,所有的更新都是在到达终端状态之后进行的。一个简单的类比是在迷宫中随机导航——离线方法会让代理到达终点,然后使用经验来尝试减少迷宫时间。相比之下,在线方法会让代理不断修改其在迷宫中的行为——也许它注意到绿色走廊通向死胡同,并决定在迷宫中避开它们。我们将在下一篇文章中讨论在线方法。

蒙特卡洛程序可总结如下:

Monte Carlo State-Value Estimation (Sutton et. al)

为了更好地理解蒙特卡罗是如何工作的,请看下面的状态转换图。每个状态转换的奖励显示为黑色,适用的折扣系数为 0.5。让我们暂时把实际的状态值放在一边,专注于计算一轮收益。

State transition diagram. State number is shown in red, returns are shown in black.

假设终端状态的返回值为 0,让我们从终端状态(G5)开始计算每个状态的返回值。请注意,我们已经将折扣因子设置为 0.5,从而对最近的状态进行加权。

或者更一般地说,

为了避免将所有返回保存在一个列表中,我们可以使用一个与传统梯度下降有一些相似之处的等式,增量地执行蒙特卡罗状态值更新过程:

Incremental Monte Carlo update procedure. S stands for state, V its value, G it return, and alpha is a step size parameter.

在强化学习中,蒙特卡罗方法可以进一步分为“首次访问”或“每次访问”。简而言之,两者之间的区别在于在 MC 更新之前,一个状态在一集内可以被访问的次数。首次访问 MC 方法将所有状态的值估计为终止前首次访问每个状态后的平均回报,而每次访问 MC 方法将终止前访问一个状态的次数n-后的平均回报。 由于相对简单,本文中我们将使用首次访问蒙特卡罗。

用蒙特卡罗方法进行策略控制

如果一个模型不能用来提供政策,MC 也可以用来估计状态-行动值。这比单独的状态值更有用,因为给定状态中每个动作(q)的值的想法允许代理根据未知环境中的观察自动形成策略。

更正式地说,我们可以使用蒙特卡洛来估计 q(s,a,pi),即从状态 s 开始,采取行动 a,然后遵循政策 pi 时的预期收益。蒙特卡洛方法保持不变,只是我们现在增加了对某个状态采取行动的维度。如果访问了状态 s 并且在其中采取了动作 a,则称一个状态-动作对(s,a)在一个情节中被访问。类似地,可以通过首次访问或每次访问的方法进行状态动作值估计。****

如同在动态编程中一样,我们可以使用广义策略迭代来从状态-动作值的观察中形成策略。

通过交替执行策略评估和策略改进步骤,并结合探索启动以确保所有可能的操作都被访问,我们可以为每个状态实现最优策略。对于蒙特卡洛 GPI 来说,这种交替一般在每集结束后进行。

Monte Carlo GPI (Sutton et. al)

了解 21 点策略

为了更好地理解蒙特卡罗在评估不同状态值和状态动作值的实践中是如何工作的,让我们用 21 点游戏进行一步一步的演示。首先,让我们定义游戏的规则和条件:

  • 我们将只和庄家对打,没有其他玩家参与。这使得我们可以将经销商的手视为环境的一部分。
  • 数字卡的价值是按面值计算的。牌 J、K 和 Q 的值是 10。ace 的值可以是 1 或 11,取决于玩家的选择
  • 双方都发了两张牌。玩家的两张牌正面朝上,而庄家的一张牌正面朝上。
  • 目标是在第一轮拿到所有牌的总和。
  • 你一共画了 19 张。但是你得寸进尺,抽到了 3,然后破产了。当你破产时,庄家只有一张可见的牌,总共 10 元。这可以想象如下:
  • 当我们破产时,我们这一轮的奖励是-1。让我们相应地将此指定为倒数第二个状态的回报,格式为[代理商总和,经销商总和,ace?]:

那真是不幸。我们再来一轮吧。

第二轮。

你一共画了 19 张。这一次,你决定留下。庄家得到 13,命中,破产。倒数第二个状态可以描述如下。

Round 1.

让我们描述一下这一轮发生的状态和奖励:

随着剧集的结束,我们现在可以使用计算的回报来更新这一轮中所有状态的值。假设贴现因子为 1,我们只需像之前的状态转换一样,在之前的手牌中传播新的奖励。由于状态 V(19,10,no)之前的收益为-1,我们计算预期收益,并将其分配给我们的状态:

履行

让我们通过使用基于 Sudharsan 等人的 Python 方法,使用首次访问蒙特卡罗来实现 21 点游戏,以了解游戏中所有可能的状态值(或不同的手牌组合)。艾尔。像往常一样,我们的代码可以在 gradient crescentGithub上找到。

Round 2.

我们将使用 OpenAI 的健身房环境来实现这一点。把环境想象成用最少的代码运行 21 点游戏的界面,让我们专注于实现强化学习。方便的是,所有收集到的关于状态、动作和奖励的信息都保存在“观察”变量中,这些变量是通过运行游戏的会话积累的。

让我们从导入所有需要获取和绘制结果的库开始。

Final state values for the Blackjack demonstration.

接下来,让我们初始化我们的健身房环境,并定义指导我们的代理行动的策略。基本上,我们会继续打,直到我们的手牌总数达到 19 或更多,之后我们会站起来。

接下来,让我们定义一种方法,使用我们的策略为一集生成数据。我们将存储状态信息、采取的行动以及行动后立即获得的奖励。

最后,让我们定义首次访问蒙特卡罗预测函数。首先,我们初始化一个空字典来存储当前的状态值,同时初始化另一个字典来存储跨集的每个状态的条目数。

对于每一集,我们调用前面的 generate_episode 方法来生成关于状态值和状态后获得的奖励的信息。我们还初始化了一个变量来存储我们的增量回报。接下来,我们获得该集期间访问的每个州的奖励和当前状态值,并使用该步骤的奖励增加我们的 returns 变量。

import gym
import numpy as np
from matplotlib import pyplot
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from collections import defaultdict
from functools import partial
%matplotlib inline
plt.style.use(‘ggplot’)

回想一下,因为我们正在执行首次访问蒙特卡洛,所以我们在一集内只访问一个州一次。因此,我们在状态字典上执行条件检查,以查看该状态是否已经被访问过。如果满足这个条件,我们就可以使用前面定义的蒙特卡罗状态值更新过程来计算新值,并将该状态的观测值增加 1。然后我们在下一集重复这个过程,以便最终获得平均回报。

#Observation here encompassess all data about state that we need, as well as reactions to itenv = gym.make(‘Blackjack-v0’)
#Define a policy where we hit until we reach 19.
# actions here are 0-stand, 1-hitdef sample_policy(observation):
  score, dealer_score, usable_ace = observation
  return 0 if score >= 19 else 1

让我们跑起来看看我们的结果吧!

def generate_episode(policy, env):
# we initialize the list for storing states, actions, and rewards  
  states, actions, rewards = [], [], []# Initialize the gym environment  
  observation = env.reset()  
  while True:# append the states to the states list  
    states.append(observation)
# now, we select an action using our sample_policy function and append the action to actions list
    action = sample_policy(observation)
    actions.append(action)# We perform the action in the environment according to our sample_policy, move to the next state
    observation, reward, done, info = env.step(action)
    rewards.append(reward)# Break if the state is a terminal state (i.e. done)
    if done:
      break
  return states, actions, rewards

显示 21 点各手牌状态值的输出示例。

def first_visit_mc_prediction(policy, env, n_episodes):
# First, we initialize the empty value table as a dictionary for storing the values of each state
  value_table = defaultdict(float)
  N = defaultdict(int)

我们可以继续观察蒙特卡洛 5000 集,并绘制描述玩家和庄家手牌的任意组合的值的状态值分布。

for _ in range(n_episodes):
# Next, we generate the epsiode and store the states and rewards
  states, _, rewards = generate_episode(policy, env)
  returns = 0# Then for each step, we store the rewards to a variable R and states to S, and we calculate
  for t in range(len(states) — 1, -1, -1):
    R = rewards[t]
    S = states[t]
    returns += R# Now to perform first visit MC, we check if the episode is visited for the first time, if yes,
#This is the standard Monte Carlo Incremental equation.
# NewEstimate = OldEstimate+StepSize(Target-OldEstimate) if S not in states[:t]:
      N[S] += 1
      value_table[S] += (returns — value_table[S]) / N[S]
return value_table

所以让我们总结一下我们所学到的。

基于样本的学习方法允许我们在没有任何转换动力学知识的情况下,简单地通过采样来估计状态和状态动作值。

value = first_visit_mc_prediction(sample_policy, env, n_episodes=500000)
for i in range(10):
  print(value.popitem())

Sample output showing the state values of various hands of blackjack.

蒙特卡罗方法依赖于模型的随机抽样,观察模型返回的回报,并在正常操作期间收集信息,以定义其状态的平均值。

通过蒙特卡罗方法,广义策略迭代是可能的。

def plot_blackjack(V, ax1, ax2):
  player_sum = np.arange(12, 21 + 1)
  dealer_show = np.arange(1, 10 + 1)         
  usable_ace = np.array([False, True]) state_values = np.zeros((len(player_sum), len(dealer_show), len(usable_ace))) for i, player in enumerate(player_sum):
    for j, dealer in enumerate(dealer_show):
      for k, ace in enumerate(usable_ace):
        state_values[i, j, k] = V[player, dealer, ace]
  X, Y = np.meshgrid(player_sum, dealer_show)
  ax1.plot_wireframe(X, Y, state_values[:, :, 0])   
  ax2.plot_wireframe(X, Y, state_values[:, :, 1]) for ax in ax1, ax2:    ax.set_zlim(-1, 1)
    ax.set_ylabel(‘player sum’)
    ax.set_xlabel(‘dealer sum’)
    ax.set_zlabel(‘state-value’)fig, axes = pyplot.subplots(nrows=2, figsize=(5, 8),subplot_kw={'projection': '3d'})
axes[0].set_title('state-value distribution w/o usable ace')
axes[1].set_title('state-value distribution w/ usable ace')
plot_blackjack(value, axes[0], axes[1])

State-value visualization of different blackjack hand combinations

在 21 点游戏中,玩家和庄家所有可能组合的价值可以通过反复的蒙特卡洛模拟来判断,从而为优化策略开辟了道路。

怀特等人。阿尔伯塔大学强化学习基础

席尔瓦等人。阿尔,强化学习,UCL

普拉特等人。艾尔,东北大学

Sutton et. al, Reinforcement Learning

White et. al, Fundamentals of Reinforcement Learning, University of Alberta

Silva et. al, Reinforcement Learning, UCL

Platt et. Al, Northeaster University

全渠道零售中优化顾客旅程的艺术和科学

原文:https://towardsdatascience.com/optimizing-customers-journey-in-omni-channel-retailing-279e730a4cf9?source=collection_archive---------16-----------------------

嗨,我是一家全球美容零售公司的营销科学分析师。我工作的公司是该地区最成熟的全渠道零售商之一。

随着数据分析的出现,全渠道零售正处于历史上最激动人心的前沿。通过客户的线上和线下旅程收集的数据提供了对客户行为的独特见解。当有效使用时,这种见解为公司提供了改善顾客购物体验的机会。这将反过来增加客户的转换和公司的收入和利润。

在本文中,我们将尝试使用纯粹的 web/app cookie 数据(来自 Google Analytics)来了解客户的旅程。这将为我们提供关于适当营销信息的见解,以便在正确的时间接触到每个客户。

转换漏斗

Figure 1 — Conversion Funnel

我们将使用一个由四个阶段组成的简单转换漏斗:意识>兴趣>欲望>行动来描述客户的旅程。客户的购买意图在每个阶段都不同,并且随着不同阶段而增加。因此,重要的是首先要确定客户所处的意向阶段,以便能够有效地针对客户的需求。

使用的数据和见解

我们能够从网络 cookies 收集的数据中识别出客户的购买意向所处的阶段。下面的表 1 显示了可以捕获的各种类型的数据以及可以从这些数据中获得的见解。

Table 1 — Data Used and Insights

在确定了客户的意向阶段后,公司可以应用适当的营销策略,将客户推向转化漏斗。该公司将能够向客户发送相关的和有针对性的营销信息。这有助于最大限度地提高公司的营销效率。

客户之旅

Figure 2 — Customer Journey (Unassisted)

鉴于其全渠道零售业务的性质,该公司客户的转换漏斗横跨物理和数字空间。客户可能通过数字渠道了解新产品,但通过实体店购买,反之亦然。

如上面的图 2 所示,客户首先在脸书上看到一个正在他/她的手机上销售的产品的广告。他/她知道该产品,并且对该产品感兴趣,在线浏览该产品。几天后,客户决定安装该公司开发的移动应用程序,并前往一家零售店实地查看产品。在商店中,顾客搜索产品的用户评论,最终对产品满意,在线购买产品。

图 2 中的图解显示了理想的顾客旅程,在顾客购买意向的各个阶段,不需要公司的任何干预。因此,只需要最少的营销支出。然而,在大多数情况下,公司需要干预转化漏斗的每一步,以“推动”客户进入下一步。

将客户旅程与洞察力相结合

Figure 3 — Customer Journey (Assisted)

因此,重要的是,我们首先要准确识别客户所处的意向阶段。如上所述,这是通过分析获得的 cookie 数据来执行的。如上面图 3 所示,自动触发器(即营销信息)被设置到位,以将客户“推向”转化漏斗的下一步。各阶段的意图和相关的营销行动,该公司可以执行如下所述。

认知:在认知阶段,让顾客意识到产品的存在是很重要的。新产品尤其如此。因此,公司可以在社交媒体网站上购买广告空间,显示针对所需受众的预期广告,以提高产品的公众认知度。

关注度:点击潜在客户广告的客户表示对广告中的产品感兴趣。根据客户在第一次访问中点击的产品,公司可以通过以横幅或视频的形式推送更多类似的类别/品牌广告来进一步增加和激起客户的兴趣。

兴趣到欲望:为了让顾客从兴趣到欲望阶段,在大多数情况下,顾客需要测试产品,尝试各种功能,感受产品的质地和质量。因此,为了让顾客进入这一阶段,顾客去实体店做上述事情是很重要的。有了位置数据,如果客户在商店附近,公司可以发送推送通知或 SMS 来吸引客户,并将其重定向到实体店。

在商店里,零售顾问可以鼓励顾客访问该公司的网页,或者使用该公司的移动应用程序来阅读独立用户对产品的评论,或者找到任何其他附加信息。当顾客在商店中访问网页时,位置数据或 IP 地址将被捕获,并且将指示顾客已经访问了商店。这将有助于公司了解客户很可能已经发展到转换漏斗中的期望阶段。

行动欲望:了解了顾客在此阶段的经历后,如果顾客没有在店内购物,公司可以制定行动策略,将顾客从欲望阶段转变为行动阶段。

哪里可以找到谷歌分析数据

Google Analytics 与 Bigquery 进行了 360 度集成,这使我们能够在会话和点击率级别深入了解网站性能。但是,如果您无法访问 Google Analytics 或 Bigquery,也可以从销售 Google 商品的电子商务网站 Google 商品商店访问 Google Analytics 数据样本。

结论

Cookie 数据能够为我们提供关于客户对各种产品的兴趣以及他/她购买各种产品的意图的广泛见解。这些数据与来自客户旅程的其他信息(如交易数据、会员数据)相结合时至关重要,可用于制定业务行动战略,以便将客户移至转化漏斗下方。当数据得到有效利用时,公司将能够提高其营销效率以及相应的收入和利润。

孟勇

优化特征生成

原文:https://towardsdatascience.com/optimizing-feature-generation-dab98a049f2e?source=collection_archive---------9-----------------------

Image by jimmikehank Sager from Pixabay

要素生成是从一个或多个现有要素创建新要素的过程,可能用于统计分析。该过程增加了在模型构建期间可访问的新信息,因此有望产生更准确的模型。在本文中,我描述了如何使用基于 H 统计的特征交互检测算法来改进特征生成过程。这篇文章是我在 Tapreason 工作的一部分。

动机

在机器学习和模式识别中,特征是正在观察的现象的单个可测量的属性或特征。收集和处理数据可能是一个昂贵且耗时的过程。因此,在模式识别、分类和回归的有效算法中,选择信息丰富的、有区别的和独立的特征是至关重要的一步。在我们生活的信息时代,数据集在实例数量和特征数量上都变得越来越大。拥有数万个或更多要素的数据集已经变得很常见。此外,算法开发人员经常使用一种称为特征生成的过程。特征生成是从一个或多个特征创建新特征的过程,可能用于统计分析。通常,这个过程是向模型中添加新的信息,使其更加准确。当存在特征交互时,特征生成可以提高模型精度。通过添加封装了特征交互的新特征,新信息变得更容易被预测模型(PM) [1]访问。在这篇文章中,我描述了如何通过检测有意义的交互和忽略无意义的交互来使用特征交互检测来改进特征生成过程。

方法学

如果作为改变 xⱼ 的值的结果的 F(x)的值的差异依赖于 xₖ 的值,则函数 F(x)被认为展示了其两个变量 xⱼxₖ 之间的相互作用。对于数值变量,这可以表示为:

为了避免在特征生成过程中生成无意义的特征,我们使用 H -statistic 来检测特征交互并评估其强度。弗里德曼&波佩斯库【2】H 统计量定义为相互作用强度的度量。背后的思想是,如果两个特征 xⱼxₖ 不相互作用,则 F(x) 对集合(xⱼ,xₖ)**【fⱼₖ(xⱼ,xₖ)的偏依赖可以分解为对每个变量的各自偏依赖之和:

Fⱼ ( xⱼ )是一个函数 F(x) 的部分依赖。

Fⱼₖ(xⱼ,xₖ) 是联合( xⱼ和 xₖ) 部分依赖 F(x)

如果fⱼₖ(xⱼ,xₖ)-fⱼ(xⱼ)-fₖ(xₖ)=0那么创造出包含 xⱼxₖ 的新特征就毫无意义。

如果特征 xⱼxₖ 确实相互作用,则另一项应该被添加到等式(1)的左侧,表示相互作用的效果。

此外,如果给定变量 xⱼ 不与任何其他特征交互,那么:

这里 F_ (x_ )是 F(x) 对除 xⱼ 以外的所有特征的部分依赖。

如果fⱼₖ(xⱼ,xₖ)-fⱼ(xⱼ)-f_ⱼ(x_ⱼ)=0根本没有必要创造涉及 xⱼ 的新功能

部分依赖

函数 F(x) 的部分相关性是一个或多个特征对机器学习模型【3】的预测结果的边际效应。给定预测器特征的任何子集 xₛ ,由 s ⊂ {1,2,.。。,n} ,函数 F(x)xₛ 的偏相关定义为:

其中 xₛ 是子集中变量的一组规定的联合值,期望值超过所有变量的边际(联合)分布 x_ₛ 未在 xₛ 中表示。p_ₛ(z_ₛ)是 z _ 的边际概率密度。等式(2)可以通过以下方式从一组训练数据中进行估计:

其中 zᵢ,_ₛ (i = 1,2,.。。,n) 是训练样本中出现的 z_ₛ的值;也就是说,我们平均出模型中所有其他预测因素的影响。在实践中,构造部分依赖关系(3)相当简单。为了简化,让 zₛ=x₁ 是具有唯一值的感兴趣的预测变量{ x ₁₁,x ₁₂,。。。,x₁ₖ }。响应对 x₁ 的部分依赖性可以通过以下算法 1【4】来构建:

算法 1 :

上述算法可能计算量很大,因为它涉及对训练记录进行 k 次遍历。幸运的是,该算法可以很容易地并行化,也可以很容易地扩展到两个或更多特征的更大子集。

部分相关性图显示了一个或两个特征对机器学习模型的预测结果的边际影响。部分相关性图可以显示目标和特征之间的关系是线性的、单调的还是更复杂的。这些图让分析师更容易理解和解释“黑盒”复杂模型。

Figure 1: Monotonically increasing partial dependence plot [2].

图中的红色虚线代表平均值。

H 统计量

部分相关函数的性质用于构造统计量,以测试各种类型的交互作用效应。从等式(1) + (2)如果在特征 jk之间存在二阶相互作用,并且只有二阶相互作用, ∆Fⱼₖ(xⱼ,xₖ) 不为零。

Fⱼ(xⱼ) 是一个函数的部分依赖 F(x)

由 Friedman 和 pope scu【2】引入的 H 统计量Hⱼₖ 测量预测的变化有多少取决于特征的相互作用。 Fⱼₖ(xⱼ,xₖ) 未被 Fⱼ(xⱼ)+Fₖxₖ 捕获的方差分数范围从 0 到 1,值越大表明交互作用效应越强。对于双向相互作用(二阶),Hⱼₖ₂定义为:

其中 i=1,2,…,N 是数据中的观察次数。相互作用强度 Hⱼₖ 然后被计算为 Hⱼₖ= (H ⱼₖ) ⁻。 H- 统计并不局限于双向相互作用,可以推广到任意阶的相互作用效应。类似地,测试指定特征 xⱼ 是否与任何其他特征相互作用的统计数据为:

这里 F_ (x_ )是 F(x) 对除 xⱼ 之外的所有特征的部分依赖。

在两个特征的情况下,xₗ 和 xₖ与 xⱼ 互动。等式(6)和(7)仅用于双向相互作用( xⱼ,xₖ )和( xⱼ,xₗ ),但是它们可以扩展到三向(三阶)相互作用,包括( xⱼ,xₗ,xₖ )。

评估H-统计量是昂贵的,因为它在所有数据点上迭代,并且在每个点上,必须评估部分相关性,这又通过所有 N 数据点来完成。在最坏的情况下,我们需要对机器学习模型预测函数的 2N 个调用来计算双向 H 统计量 ( j 对 k,等式 63N 用于总的 H 统计量 ( j 对 all,等式 7 )。为了加速计算,我们可以从 N 个数据点进行采样。这具有增加部分相关性估计的方差的缺点,这使得 H 统计量不稳定。因此,当使用采样来减少计算负担时,应该采样足够的数据点。

使用 H-统计量生成有意义的特征

有效的特征生成不会生成对预测没有贡献的无意义的特征,但仍会增加特征选择的复杂性和计算时间。以下算法(算法 2 )使用 H 统计作为特征交互检测算法,并使用结果作为特征生成过程的输入。因此,特征生成过程将生成更少的无意义特征,并减少计算时间。

[1] Suzanne van den Bosch:“预测分析解决方案中的自动特征生成和选择”,Radboud 大学计算科学学院硕士论文

随机森林分类中超参数的优化

原文:https://towardsdatascience.com/optimizing-hyperparameters-in-random-forest-classification-ec7741f9d3f6?source=collection_archive---------0-----------------------

什么是超参数,如何选择超参数值,以及它们是否值得您花费时间

在本文中,我将使用 scikit-learn 的几个分类和模型选择包,深入研究随机森林分类模型的超参数调优。我将分析来自 UCI 机器学习库的葡萄酒质量数据集。出于本文的目的,我将红葡萄酒和白葡萄酒的单个数据集进行了合并,并为两者分配了一个额外的列来区分葡萄酒的颜色,其中 0 代表红葡萄酒,1 代表白葡萄酒。这种分类模式的目的是确定葡萄酒是红葡萄酒还是白葡萄酒。为了优化这个模型以创建最准确的预测,我将只关注超参数调整和选择。

什么是超参数?

通常,超参数是在学习过程开始之前设置的模型参数。不同的模型有不同的可以设置的超参数。对于随机森林分类器,有几个不同的超参数可以调整。在这篇文章中,我将研究以下四个参数:

  1. n _ estimators:n _ estimators 参数指定了模型森林中的树的数量。该参数的默认值是 10,这意味着将在随机森林中构建 10 个不同的决策树。

2.max _ depth:max _ depth 参数指定每棵树的最大深度。max_depth 的默认值是 None,这意味着每棵树都将扩展,直到每片叶子都是纯的。纯叶子是叶子上的所有数据都来自同一个类。

3.min _ samples _ split:min _ samples _ split 参数指定分割内部叶节点所需的最小样本数。此参数的默认值为 2,这意味着内部节点必须至少有两个样本,才能被拆分为更具体的分类。

4.min _ samples _ leaf:min _ samples _ leaf 参数指定在叶节点上所需的最小样本数。这个参数的缺省值是 1,这意味着每个叶子必须至少有 1 个它要分类的样本。

关于 RandomForestClassifier()的超参数的更多文档可以在这里找到。

如何调整超参数?

当您调用创建模型的函数时,可以手动调整超参数。

forest = RandomForestClassifier(random_state = 1, n_estimators = 10, min_samples_split = 1)

您如何选择要调整的超参数?

在开始调整超参数之前,我对我的数据进行了 80/20 的训练/测试分割。将在训练集上测试不同的超参数,并且一旦选择了优化的参数值,将使用所选择的参数和测试集来构建模型,然后将在训练集上测试,以查看该模型能够多准确地对酒的类型进行分类。

forest = RandomForestClassifier(random_state = 1)
modelF = forest.fit(x_train, y_train)
y_predF = modelF.predict(x_test)

当使用超参数的默认值对训练集进行测试时,预测测试集的值的准确度为 0.991538461538。

验证曲线

有几种不同的方法可以为您的模型选择要调整的超参数。直观检查模型超参数的潜在优化值的一个好方法是使用验证曲线。可以在图表上绘制验证曲线,以显示模型在单个超参数的不同值下的表现。运行下面的代码来创建这里看到的四条验证曲线,其中 param_nameparam_range 的值针对我们正在研究的四个参数中的每一个进行了相应的调整。

train_scoreNum, test_scoreNum = validation_curve(
                                RandomForestClassifier(),
                                X = x_train, y = y_train, 
                                param_name = 'n_estimators', 
                                param_range = num_est, cv = 3)

该验证曲线是使用[100,300,500,750,800,1200]值创建的,这些值是要对 n_estimators 进行测试的不同值。在此图中,我们看到,在测试这些值时,最佳值似乎是 750。值得注意的是,尽管训练和交叉验证得分之间似乎存在很大的差异,但训练集对三个交叉验证中的每一个都具有 100%的平均准确性,而交叉验证集对 n_estimators 的所有值都具有 99.5%至 99.6%的准确性,这表明无论使用多少个估计值,该模型都非常准确。

在此图中,我们看到当 max_depth 设置为 15 时,交叉验证的最高准确度值接近 99.3%,这是我们将放入模型中的值。总的来说,选择 max _ depth 30 似乎更好,因为该值对于训练分数具有最高的准确性,我们选择不选择它,以防止我们的模型过度拟合训练数据。

在该图中,我们看到,在 min_samples_split 的值较高时,训练集和交叉验证集的准确性实际上都下降了,因此我们将选择 5 作为 min_samples_split 的值。在这种情况下,我们希望 min_samples_split 有一个较低的值是有意义的,因为这个参数的默认值是 2。由于在分割内部节点之前,我们为所需的最小样本数选择了较高的值,因此我们将拥有更多通用叶节点,这将对我们模型的整体准确性产生负面影响。

在此图中,我们看到,min_samples_leaf 值每增加一次,训练集和交叉验证集的准确性都会下降,因此我们将选择 1 作为参数值,考虑到此参数的默认值为 1,这也是有意义的。

值得注意的是,在构建验证曲线时,其他参数保持默认值。出于本文的目的,我们将在一个模型中一起使用所有的优化值。构建了新的随机森林分类器,如下所示:

forestVC = RandomForestClassifier(random_state = 1,
                                  n_estimators = 750,
                                  max_depth = 15, 
                                  min_samples_split = 5,  min_samples_leaf = 1) modelVC = forestVC.fit(x_train, y_train) 
y_predVC = modelVC.predict(x_test)

该模型的精度为 0.993076923077,比我们的第一个模型更精确,但只差 0.0015。

穷举网格搜索

选择要调整的超参数的另一种方法是进行彻底的网格搜索或随机搜索。随机搜索将不会在这篇文章中讨论,但是可以在这里找到关于其实现的更多文档。

详尽的网格搜索会尽可能多地接收超参数,并尝试超参数的每一种可能组合以及尽可能多的交叉验证。彻底的网格搜索是确定要使用的最佳超参数值的好方法,但是随着每个额外的参数值和您添加的交叉验证,它会很快变得非常耗时。

n_estimators = [100, 300, 500, 800, 1200]
max_depth = [5, 8, 15, 25, 30]
min_samples_split = [2, 5, 10, 15, 100]
min_samples_leaf = [1, 2, 5, 10] 

hyperF = dict(n_estimators = n_estimators, max_depth = max_depth,  
              min_samples_split = min_samples_split, 
             min_samples_leaf = min_samples_leaf)

gridF = GridSearchCV(forest, hyperF, cv = 3, verbose = 1, 
                      n_jobs = -1)
bestF = gridF.fit(x_train, y_train)

这里显示的代码运行了 25 分钟,但是选择的超参数在预测训练模型时具有 100%的准确性。得到的“最佳”超参数如下: max_depth = 15, min_samples_leaf = 1, min_samples_split = 2, n_estimators = 500。

再次,使用这些值作为超参数输入来运行新的随机森林分类器。

forestOpt = RandomForestClassifier(random_state = 1, max_depth = 15,     n_estimators = 500, min_samples_split = 2, min_samples_leaf = 1)

modelOpt = forestOpt.fit(x_train, y_train)
y_pred = modelOpt.predict(x_test)

当使用测试集进行测试时,该模型还产生了 0.993076923077 的准确度。

调整超参数值得吗?

仔细而有条理地调整超参数可能是有利的。它可以使您的分类模型更加准确,这将导致整体预测更加准确。然而,这并不总是值得你去做。让我们来看看不同测试的结果:

最值得注意的是准确性的整体提高。当模型应用于我们的测试集时,基于网格搜索和验证曲线的结果选择的超参数产生了相同的精度:0.995386386386 这将我们的原始模型在测试集上的准确度提高了 0.0015。考虑到在我们需要的 4 个超参数上进行彻底的网格搜索花费了 25 分钟,在这种情况下可能不值得花时间。此外,我们的网格搜索给出的两个“优化”超参数值与 scikit-learn 的随机森林分类器的这些参数的默认值相同。当查看两个优化模型的混淆矩阵时,我们看到两个模型对红葡萄酒和白葡萄酒的错误预测数量相同,如下所示:

结论

超参数调整有利于创建更擅长分类的模型。在随机森林的情况下,可能没有必要,因为随机森林已经非常擅长分类。使用穷举网格搜索来选择超参数值也非常耗时。但是,在超参数只有几个潜在值的情况下,或者当初始分类模型不太准确时,最好至少调查一下更改模型中某些超参数值的影响。

关键术语/概念:超参数、验证曲线、穷举网格搜索、交叉验证

为群体水平预测优化个体水平模型

原文:https://towardsdatascience.com/optimizing-individual-level-models-for-group-level-predictions-a66e675138ff?source=collection_archive---------25-----------------------

第一部分——偏倚分析

介绍

这篇文章的目的是提出我对机器学习(特别是医疗保健)中一个非常普遍但很少解决的问题的一些想法:如何在只给定个体水平数据的情况下,以优化预定损失函数(例如,MAE 或 MSE)的方式构建群体水平的预测?

如果您首先创建一个针对某个损失函数进行优化的个人级模型,然后取预测值的平均值,那么您是否会自动针对群体级的相同损失函数进行优化?事实证明,虽然 MSE 的答案恰好是“是”,但 MAE 的答案却是响亮的“不是”!

在这篇文章中,我解释了为什么在个体层面使用相同损失函数的下意识方法是错误的。

这是一个关于揭开这个问题真正本质的故事。作为这个探索的一部分,我使用了彼得·霍尔的一个有趣的定理,我发现这个定理的证明有点难以理解。作为对社区的服务,在第 2 部分中,我将展示该定理的背景故事,并提供一个比他在论文中提供的稍微更自然的证明,并填充原始论文中遗漏的所有关键细节。

这篇文章中看到的所有情节代码都可以在这个 GitHub repo 中找到。

示例和假设

为了使这种探索更容易理解,我将使用一个具体的例子并修正我的假设。

  • 示例:一家医疗保险公司希望估算下一年雇主团体的人均成本(即团体的总成本除以成员数量),其中每个雇主团体由一定数量的个人成员组成。
  • 基本假设:给你训练和测试数据,包括个人层面的数据和成员到团队的映射。训练数据具有由每个人在下一年发生的成本表示的目标值,而测试数据没有目标值。测试数据和训练数据可能具有不同的组。

剩下的工作就是指定在集团层面上与什么“真实值”进行比较。为了说明为什么在个体层面优化与在群体层面优化相同的损失函数是错误的,最简单的方法是使用以下假设:

  • 假设 A :对于每个组,将其真值设为其成员的平均目标值。

我们稍后还将考虑另一个假设,如果你允许成员的变化,这个假设会更自然地出现。

为什么要有一个独立的模型呢?

在组级优化特定损失函数的一种方法是简单地创建优化该损失函数的组级模型,其特征是工程聚合的个体级特征。但是群体的数量大概比个体的数量小得多,所以人们会认为这样的模型会有很大的差异。个人层面和团体层面相结合的方法将是最明智的。

“为什么不用递归神经网络?这样,您就可以创建一个使用所有数据的组级模型!”,我听到你哭了。嗯……这将使用所有个体水平的特征,而不是未聚集的目标值,除非使用特殊的损失函数。即使这样,RNN 的是顺序依赖的,而组成员不是!所以让我们继续称之为“实验性的”。

无论哪种方式,你的群体层面的预测只能从做好个体层面的模型中获益。所以让我们开始吧!

关于 MAE/MSE 优化的直觉

底线是:为 MSE 优化意味着你在估计平均值;针对 MAE 进行优化意味着您正在估计中值。

这到底是什么意思?设 Y 为目标值,设 X_1,…,X_n 为特征。如果你的特征值是 X_1=x_1,…,X_n=x_n ,那么给定那些特征的目标值 Y|X_1=x_1,…,X_n=x_n 是一个随机变量,而不是一个常数。换句话说,你的特征值并不能决定目标。例如,如果你正在预测成本,那么完全可以想象两个具有相同特征值的个体具有不同的成本;尽管知道这些特征值确实会改变成本的分布。

如果你是针对 MSE 进行优化,那么在你的模型中插入 (x_1,…,x_n) 会试图预测 E(Y|X_1=x_1,…,X _ n = X _ n);然而,如果您正在为 MAE 进行优化,您的模型将尝试预测 中值(Y|X_1=x_1,…,X_n=x_n)

事实上,如果 f(x_1,…,x_n) 是损失函数为 MSE 的机器学习模型在这些特征值处的模型预测,那么它将试图近似使以下各项最小化的 a :

这最后一个表达式是 a 中具有全局最小值 E(Y|X_1=x_1,…,X_n=x_n) 的抛物线。

类似地,如果 f(x_1,…,x_n) 是损失函数为 MAE 的机器学习模型在这些特征值处的模型预测,那么它将尝试近似将以下各项最小化的 a :

最小化该表达式的 amedian(Y|X_1=x_1,…,X_n=x_n) 。(要看到这一点,你必须摆弄积分;这是一个简单但令人讨厌的练习。)

技术提示:给定一个事件的随机变量的条件概率,只有当你设定的事件有正概率时才有意义。试图将定义扩展到零概率事件注定是不明确的,除非我们指定一个限制程序;参见Borel-Kolmogorov 悖论。如果 X_i 中至少有一个是连续的,那么 P(X_1=x_1,…,X_n=x_n)=0 ,这就暗示 Y|X_1=x_1,…,X_n=x_n 没有任何意义。(本科教材中常见的定义为 Y|X_1=x_1,…,X_n=x_n 不是坐标不变的。对于更高级的读者来说:对次∑代数而不是事件进行调节会产生相同的问题,因为最终的随机变量在“几乎确定相等”之前是唯一的,这意味着零概率事件可以是例外。)我们可以也将会通过将特性的值限制为计算机能够表示的值来优雅地避免这个问题。这样,即使是“连续的”变量实际上也是离散的,一切都是定义明确的。

问题是

固定一组尺寸为 m 的,设

成为第 i 人的特征。如果我们正在创建一个优化 MSE 的个体水平模型,那么结果的平均值就是

根据期望的线性度,这等于

太好了!换句话说,通过在个人层面优化 MSE,您也在团队层面优化 MSE!

现在让我们对梅做同样的分析。如果我们正在创建一个优化 MAE 的个体水平模型,那么结果的集合就是对

但那是非常非常非常遥远的事

这是一个简单的例子,说明总和的中位数与中位数之和相差甚远,即使随机变量都是独立同分布的:

为了设置这个例子,我将使用比例为 200 和形状为 1 的伽玛分布。这个分布看起来是这样的:

(本帖中看到的剧情代码可以在 this GitHub repo 中找到。)

Figure 1

现在将 X_i 作为遵循该分布的 i.i.d。下面是他们的中位数与平均值的中位数的比较:

Figure 2

你也看到了,这个差距挺大的!

对于群体级 MAE,优化个体级 MSE 优于优化个体级 MAE

如果一个群体很大,那么可以合理地假设

是近似正常的;正态分布的中值就是它的平均值。因此,如果您在个人层面优化 MSE,然后取预测的平均值,您将近似估计大群体的中值!乍一看,这似乎是反直觉的:不仅对于组级 MSE,而且对于组级 MAE,在个体级优化 MSE 都优于在个体级优化 MAE。

但是,我们应该期望对小群体的偏见有多严重呢?(事实将会证明,秘密地关键是使用中心极限定理的误差估计。)

彼得·霍尔的一个结果

这激起了我的兴趣。所以我开始寻找关于 i.i.d .总和的中位数的结果。我找到了彼得·霍尔的《关于独立变量和的众数和中位数的极限行为》,在那里他证明了下面的结果。

(见本帖第二部分更深入的理解为什么这个定理是真的。)由于 X_i 都是同分布的,为了便于标注,我们就简单地让 X := X_1 吧。如果我们不假设X _ Is 有均值 0 和方差 1 的话,一个快速的回包络计算,还原到归一化的情况下,表明这还原到如下的近似值:

请注意,这是一个渐近结果!为了能够在上面讨论的机器学习环境中使用它,我们必须首先确保这个近似对于小的 n 是合理的。让我们做一个快速的概念验证:

(本帖中看到的剧情代码可以在这个 GitHub repo 中找到。)

Figure 3

这是相当准确的!

机器学习环境中的偏差估计

对于每一组,我们将尝试估计

为了那个团体。被加数不是独立同分布的,所以霍尔的结果不能直接应用。为此,我们可以尝试将假设 A 替换为:

  • 假设 B: 对于每一组,假设其“真值”是其成员真值的 m 个样本重复的均值的期望值。

(可以说,假设 B 在现实生活中出现得更多。在组级预测中,成员通常不是固定的,但是当前成员的目标值表示未来成员的分布目标值。)

既然目标值是 i.i.d .的平均值(因为采样是重复进行的),我们可以采用霍尔近似值。固定一个组,设 T_1,…,T_m 为采样,重复,如假设 b 中所述。 T_i 现在是 I . I . d,T:= T _ 1。我们现在面临的挑战是为每个组逼近V(T)E((T-μ))。这可能很困难,因为我们最想纠正偏差的群体是小群体。

一种简单化的做法是将估计为【Y】,将 E((T-μ) ) 估计为 E((Y-E(Y)) ) 。进而,通过取我们数据中目标值的平均值来估计【Y】E((Y-E(Y)) ) ,并将这些估计值分别表示为ˇζζζ_ 3。这些估计是否有效取决于各组之间的差异——它们越相似,偏差校正就越好。无论哪种方式,这些近似值足以获得一个相对清晰的图片,说明一个小组需要有多小,才能使偏差超出你的舒适水平。也就是说,粗略的估计是,如果一个组的大小是 m ,那么对使用 MSE 训练的单个模型进行平均应该具有大约

对于这个数字大得令人无法忍受的组,我建议格外小心:ζζ_ 3可能不是足够好的估计,并且可能导致糟糕的偏差校正。我只是建议将这种规模的组标记为需要偏差校正,并根据数据和您想到的特定应用对所需的偏差校正进行更多研究。

(请注意,虽然使用贝叶斯方法使您能够从 Y|X_1=x_{i,1},…,X_n=x_{i,n} 的分布中进行采样很有吸引力,但这些方法的普通版本假设 Y|X_1=x_{i,1},…,X_n=x_{i,n} 的分布为如果是这样的话,就不会有任何偏差需要校正……这也适用于在神经网络中使用预测时的漏失,根据亚林·加尔和邹斌·加赫拉马尼的工作,这大致相当于在适当定义的高斯过程设置中对后验样本进行采样——但该设置也假设误差呈正态分布。)**

原贴于 卢米亚塔

如果这个帖子引起了你的兴趣,你想用类似的问题挑战自己,Lumiata 正在招聘!请检查 Lumiata 的打开位置

GitHub:https://github.com/lumiata/tech_blog

在 www.lumiata.com拜访卢米娅塔,并通过@卢米娅塔在推特上关注。

在 LinkedIn 上找到卢米娅塔:www.linkedin.com/company/lumiata

引文 :

1。Hall,P. (1980)关于独立随机变量和的众数和中位数的极限行为。安。概率 8 419–430。

2。Gal,y .和 Ghahramani,Z. (2016)辍学作为贝叶斯近似:表示深度学习中的模型不确定性。
ICML。

为群体水平预测优化个体水平模型

原文:https://towardsdatascience.com/optimizing-individual-level-models-for-group-level-predictions-f48f491363f8?source=collection_archive---------31-----------------------

第 2 部分——独立同分布变量之和的中位数

介绍

第一部分 —偏倚分析中,我探讨了来自个体水平模型的群体水平预测中的偏倚。在那里,我使用了彼得·霍尔的以下定理(“关于独立变量和的众数和中位数的极限行为”):

但是为什么会这样呢?我发现霍尔的论文有些难以理解,但非常有趣。作为对社区的一种服务,在这篇文章中,我将尽可能详细地介绍用于证明这一结果的工具,并完整地提供霍尔证明的一个变体。我已经改变了证明中的一些步骤,使证明更加自然,消除了他对 Esseen 定理的依赖,而是直接使用一种称为 Edgeworth expansions(我介绍的)的数学工具来证明他的结果。我还补充了原始证据中缺失的一些关键细节。证明的基本轮廓非常吸引人:用一个中心极限定理的误差估计来证明结果。

Edgeworth 展开式——中心极限定理的误差估计

证明中心极限定理 (CLT)及其许多变种最简单的方法就是看随机变量的特征函数。随机变量 X 的特征函数定义为

特征函数有用的原因有三:

  1. 独立变量和的特征函数是它们各自特征函数的乘积:

这使得计算变得简单。

2.知道了随机变量的特征函数,就决定了它的分布。其实 X 的特征函数无非是 X (如果有)的概率密度函数的傅里叶变换,所以这只是傅里叶对偶——傅里叶变换的逆傅里叶变换才是原函数!(注意:由于实数的与其对偶群被认定为“非自然的”,在该词的范畴理论意义上,傅立叶对偶遭受多种约定。我们将遵循这样的约定,函数的傅立叶变换为

而函数 f(t) 的逆变换是

按照这个约定, X 的特征函数的逆变换就是 X 的 pdf,如果有的话。)

3.最后,

*这就是李维连续性定理

CLT 的标准证明完全遵循这种方法。通过先归一化,您可以将 CLT 简化为:*

有人证明了这一点

*就要点而言。

关键的一步是*

因此:

*,其中最后一步是因为 X_i 都是同分布的。为了简化符号,让 X:=X_1

显示出*

逐点相对容易,尽管细节与讨论的其余部分无关。Edgeworth expansions 是霍尔用作激励的数学工具(尽管没有直接使用),其背后的思想是相似的:

具体来说,就是写一个 X 的特征函数Log的麦克劳林展开,其中 Loglog主分支,如

对于喜欢给事物命名的人来说,这些 κ_j 通常被称为 X 的[累积量。一般来说,累积量没有直观的解释,但前三个有:【κ_ 1 = E(X)【κ_ 2 = V(X)κ_ 3 = E((X—E(X)))*。特别是对于我们: κ_1 = 0κ_2 = 1

因此 X 的特征函数的展开式为:](https://en.wikipedia.org/wiki/Cumulant)*

把那个插进去

然后得到

这最后一个等式仅仅是利用了【eˣ】*的麦克劳林展开式;每个 r_j 都是实系数的多项式 3j ,如果需要可以计算。

现在剩下的就是应用一个逆傅立叶变换来得到一个 S_n. 的概率密度的展开式,这是相对容易的——这里有一个技巧:*

*(为什么?度 0 格为标准,单项格通过反复推导度 0 格而得出;一般情况下遵循单项式的情况。)诀窍继续:推导标准正态分布 j 倍的概率密度函数实际上很容易计算(通过交换导数和积分),对于任何 j 它总是标准正态的 pdf 的一些多项式倍。(以这种方式产生的多项式被称为埃尔米特多项式,但是确定它们的性质对于我们的目的来说并不重要。)

这一切的底线是:*

所以我们只是得到了一个中心极限定理的误差估计!weeee lll……事实证明,Edgeworth 扩张几乎从不收敛…所以以上是我们讲述的更多关于 Edgeworth 扩张的激励性睡前故事。但事实证明,在极其温和的条件下,Edgeworth 展开式是“渐近展开式”,也就是说对于每个 k:

只要【e(|x|^(k+2】)<∞X 满足称为“克莱姆条件”的条件,这是比具有连续 pdf 更弱的条件。证明这一点需要一点努力,我参考了彼得·霍尔的书“自举和 Edgeworth 展开”,第 2.4 节和第 5 章,以了解细节。

从 Edgeworth 展开式到中位数的近似值

*在霍尔的论文中,相当于这一整节的短语是“它遵循那个”,没有给出解释。正如你将看到的,这个论点需要一些细微的差别。但是细节确实解决了…!

让:*

因为

由此可见:

让我们把它代入上面的 Edgeworth 展开式:

请注意,由于标准正态的 pdf 是指数型的,因此的分子

是有界的,因此这个分数收敛到 0。这意味着

因此:

*(我们最终想证明 m_n 收敛,但这是证明其余部分所需的第一步。)

现在让我们用麦克劳林展开式:*

它的收敛半径是无穷大。由此可见:

可以看出,Edgeworth 展开式中的P1(x)项等于 -κ_3(x -1)/6 ,因此:

特别是:

因此,我们知道:

其中,乘以 n 的平方根 后暗示:

我们准备好大开杀戒了。使用 Maclaurin 展开式:

我们可以看到:

特别是:

因此当 n 接近无穷大时:

我们完事了。

关于非 i.i.d .的霍尔式结果的最后说明

可以理解的是,独立但不同分布的随机变量和的中值没有渐近结果。然而,令人惊讶的是,确实存在一种可用于非独立同分布随机变量的 Edgeworth 展开式的变体,它在某种相当复杂的理想定义下是理想的。(见白志东、赵林成《独立随机变量分布函数的 Edgeworth 展开式》。)可以想象的是,可以按照上面的方法从 Edgeworth 展开式到中位数的估计。

原贴于 卢米亚塔

如果这个帖子引起了你的兴趣,你想用类似的问题挑战自己,Lumiata 正在招聘!请检查 Lumiata 的未平仓

*GitHub:【https://github.com/lumiata/tech_blog *

在 www.lumiata.com拜访卢米娅塔,并通过@卢米娅塔在推特上关注。

在 LinkedIn 上找到卢米娅塔:www.linkedin.com/company/lumiata

引文 :

1。Hall,P. (1980)关于独立随机变量和的众数和中位数的极限行为。安。概率 8 419–430。

2。Hall,P. (1992)自助和 Edgeworth 扩展。纽约施普林格出版社。

3。白,赵,李(1984)独立随机变量分布函数的 Edgeworth 展开式。中国科学 291–22。

优化 Jupyter 笔记本:提示、技巧和 nbextensions

原文:https://towardsdatascience.com/optimizing-jupyter-notebook-tips-tricks-and-nbextensions-26d75d502663?source=collection_archive---------8-----------------------

Jupyter 笔记本是一种基于网络的交互式工具,机器学习和数据科学社区经常使用。它们用于快速测试,作为报告工具,甚至作为在线课程中高度复杂的学习材料。

所以在这个博客中,我将列出一些快捷方式、魔法命令和扩展。

快捷指令

Ctrl+Shift+p键或点击菜单栏中的小键盘图标,获得命令面板列表

命令和编辑模式下的快捷键:

  • Shift + Enter运行当前单元格,选择下图
  • Ctrl + Enter运行选定的单元格
  • Alt + Enter运行当前单元格,在下面插入
  • Ctrl + S保存和检查点

编辑模式下的快捷键:

  • Esc进入命令模式
  • Tab代码完成或缩进
  • Shift + Tab工具提示
  • Ctrl + ]缩进
  • Ctrl + [德登
  • Ctrl + A全选
  • Ctrl + Z撤销
  • Ctrl + Shift + ZCtrl + Y重做
  • Ctrl + Home转到单元格开始
  • Ctrl + End转到单元格末端
  • 向左走一个单词
  • Ctrl + Right向右走一个字

一旦进入命令模式,按下H(帮助)获得键盘快捷键列表:

我列出了一些最常用的快捷方式。通过点击Esc确保您处于命令模式:

  • UpDown键上下滚动你的单元格。
  • 按下AB在当前单元格的上方或下方插入一个新单元格。
  • M将当前单元格转换为降价单元格。
  • Y将当前单元格设置为代码单元格。
  • X将剪切选中的单元格
  • C将复制选中的单元格
  • V将粘贴正在被复制/剪切的单元格
  • Shift + V粘贴细胞上方
  • S将保存笔记本
  • F将查找/替换
  • O将切换输出
  • D + D ( D两次)将删除活动单元格。
  • Z将撤消单元格删除。
  • 要一次选择多个单元格,按住Shift并按下UpDown
  • Shift + Space将笔记本向上滚动
  • Space向下滚动笔记本

选择多个单元格:

  • 按下Shift + M合并您的选择
  • 要拆分光标处的活动单元格,在编辑模式下按Ctrl + Shift + -
  • 您也可以在单元格左边的空白处单击和Shift + Click来选择它们

在笔记本之间复制和粘贴单元格:

  • 笔记本 1: —按住 Shift 键选择多个单元格,然后点击Ctrl+c进行复制
  • 笔记本 2: —按 Esc 键进入命令模式Ctrl + v粘贴

使用! pip install <package>在当前内核中安装软件包

通过在 shell 命令中添加一个$符号来使用 Python 变量:

魔法命令

魔术命令是显著扩展笔记本电脑功能的快捷方式

共享笔记本中的代码示例:

  1. 使用%pastebin魔法功能选择单元格范围
  2. Jupyter 给你一个秘密的网址来分享

Note- This link gets expired in 7 days

使用%whos%who_ls获得已定义变量的列表

  • %whos显示变量类型和一些额外信息:大小、内容等。
  • %who_ls仅显示变量名称

在 Jupyter 笔记本中使用外部文件:

  • %pycat file.py ➡在传呼机中打开脚本
  • %load file.py ➡将脚本插入单元格
  • %run file.py ➡运行脚本
  • %run file.ipynb ➡经营笔记本
  • %notebook filename ➡将当前 IPython 历史导出到笔记本文件

获取、设置或列出环境变量:

  • %env ➡lists 所有环境变量
  • %env var ➡得到 var 的值
  • %env var val ➡为 var 设定值

在 shell 中运行命令:

%system ➡使用 shell(主要用于获取当前目录、日期等)

使用%autosave将笔记本自动保存到其检查点:

Autosaving every 120 seconds (2 minutes)

执行不同的语言:

  • %%HTML ➡执行 HTML 代码

  • %%perl ➡在子进程中执行 Perl
  • %%javascript%%js ➡来执行 Javascript 代码块
  • %%python3 ➡用 python3 在子进程中执行代码
  • %%ruby ➡执行 Ruby 代码

其他魔法命令:

  • %history ➡打印输入历史
  • %lsmagic ➡列出当前可用的魔法功能
  • %magic ➡打印关于魔法功能系统的信息
  • %matplotlib ➡设置 matplotlib 交互工作
  • %pwd ➡返回当前工作目录
  • ➡展示了一份快速参考表
  • %time ➡时间执行一个 Python 语句或表达式(它既可以用作行魔术,也可以用作单元格魔术)

nb 扩展

这个扩展的好处是它改变了默认值。

要安装 nbextensions,请在 Anaconda 提示符下执行以下命令:

conda install -c conda-forge jupyter_contrib_nbextensions
conda install -c conda-forge jupyter_nbextensions_configurator

或者,您也可以使用 pip 安装 nbextensions:

  • pip install jupyter_contrib_nbextensions
  • 运行pip show jupyter_contrib_nbextensions找到笔记本扩展的安装位置
  • 运行jupyter contrib nbextensions install安装新的扩展

安装完成后,重启 Jupyter 笔记本,您可以观察到一个新标签 Nbextensions 添加到菜单中:

同样的 nbextension 也可以位于编辑菜单中:

现在,让我们来看几个 nb 扩展:

  1. 腹地 -它为代码单元中的每一次按键启用代码自动完成菜单,而不是仅用 tab 启用它

2.拆分单元格笔记本 -在 Jupyter 笔记本中启用拆分单元格

进入命令模式(Esc),使用Shift + s将当前单元格切换为拆分单元格或全幅单元格。

3.目录-TOC 扩展能够收集所有运行的标题,并在浮动窗口中显示它们,作为侧边栏或导航菜单。该扩展也是可拖动的,可调整大小的,可折叠的,可停靠的,并具有自动编号和唯一的链接 id,以及一个可选的 toc 单元。

  1. Autopep8 - 使用特定于内核的代码来重新格式化/修饰代码单元格的内容

5.snippet-添加一个下拉菜单,将 snippet 单元格插入当前笔记本。

Jupyter 笔记本主题

我们可以从 Jupyter 笔记本的默认主题转换到黑暗模式。

为此,我们需要安装jupyterthemes:

jt -l将给出可用主题的列表

jt -t <theme name>会改变主题。让我们试着用切斯特风格主题把它改成黑暗模式。

jt -r会将其恢复为默认主题

我们还可以用 Jupyter 笔记本做很多我们没有提到的事情。还是留到下一篇博客吧。

我的其他博客文章

疑问?评论?欢迎在评论区留言,也可以在LinkedIn上关注并联系我。 如果你喜欢这个博客,可以 给我买杯咖啡

优化技术:遗传算法

原文:https://towardsdatascience.com/optimizing-machine-learning-models-with-genetic-algorithms-2a38682a0610?source=collection_archive---------8-----------------------

一种自适应且众所周知的优化技术

Photo by NASA on Unsplash

在复杂的机器学习模型中,性能通常取决于多个输入参数。为了得到最佳模型,必须适当地调整参数。然而,当有多个参数变量时,每个变量的取值范围很宽,每组参数有太多可能的配置需要测试。在这些情况下,应使用优化方法来获得最佳输入参数,而无需花费大量时间来寻找它们。

在上图中,它显示了仅基于两个参数的模型分布。如示例所示,找到曲线的最大值或最小值并不总是一件容易的事情。这就是优化方法和算法在机器学习领域至关重要的原因。

遗传算法

最常用的优化策略是遗传算法。遗传算法是基于达尔文的自然选择理论。它相对容易实现,并且算法的设置有很大的灵活性,因此它可以应用于广泛的问题。

选择健身功能

首先,必须有一个适应度函数来衡量一组输入参数的表现。从适应度函数得到的具有较高适应度的解将比具有较低适应度的解更好。

例如,如果一个解决方案的成本为 x + y + z,那么适应度函数应该尝试最小化成本。这可以通过以下健身功能来实现:

该适应度函数将为每组输入参数生成一个适应度值,并用于评估每组参数的执行情况。

产生一个群体

要运行遗传算法,首先从一群个体开始,其中每个个体都是一个解。解决方案由一组基因表示,其中解决方案中的每个基因都是模型中的一个变量。每个解决方案都是随机生成的,并根据适应度函数进行评估,以生成适应度分数。选择一个合适的人口规模是非常重要的。如果群体规模太低,那么就很难探索问题的整个状态空间。如果群体太大,那么将需要很长时间来处理每一代,因为计算适应度和生成每个群体的系统成本将需要指数级的更多时间来处理。

亲代选择

接下来,群体经历一个称为父代选择的过程,其中最佳解决方案(最适合的个体)将被选择以创建下一代解决方案。有许多方法可以做到这一点,如健身比例选择(FPS),基于排名的选择,以及锦标赛选择。这些方法各有利弊,应根据模型进行选择。

交叉

一旦亲本被选中,亲本将经历一个叫做交叉的过程。交叉是指两个父母为了创造一个新的解决方案而交叉他们的基因(也称为孩子)。这促进了在问题的状态空间中的探索,并且潜在地产生了从未被测试过的新的解决方案。

这是根据解决方案的数据类型以不同方式完成的。对于基因用二进制表示的解,有 1 点交叉、n 点交叉、均匀交叉等方法。

对于基因是实值的解决方案,有诸如单算术交叉全算术交叉的方法。

此外,对于排列问题(如旅行推销员问题等),有一些方法,如部分映射交叉(又名 PMX)、边交叉、顺序 1 交叉循环交叉

变化

在交叉阶段之后,产生的子代经历一个突变阶段。突变是指每个基因都可能根据随机概率发生变化。这允许利用,因为子解决方案不会像交叉阶段那样剧烈变化,但仍然能够在其当前解决方案的邻域内探索。

对于二进制解决方案,变异过程相对简单,每个位根据某种变异概率进行切换。

对于实值解,可以根据该变量的一些可接受的范围或者通过添加一些以 0 为中心并且根据一些高斯分布变化的噪声来选择不同的基因。

最后,对于排列问题,主要有四种方法;插入突变、交换突变、倒位突变、争夺突变

幸存者选择

一旦创建了儿童群体,下一个阶段就是幸存者选择。这一阶段决定了哪些个体可以继续传给下一代。有多种方法可以做到这一点,因为新一代可以从父母和子女中选择。选择每一代幸存者的方法主要有两种,基于年龄的选择基于适应度的选择(FBS) 。在 FBS 中,有精英主义,其中每个群体中最适合的被选择,还有天才,其中每个群体中最不适合的被淘汰。

算法重复

一旦选择了新一代,整个过程重复进行,直到算法根据某些收敛标准收敛。在整个算法运行之后,返回所有代中的最佳解决方案。

履行

结论

遗传算法因其广泛的适用问题而被广泛应用。简单版本的遗传算法相对容易实现,但有更复杂的变化。例如,这些遗传算法可以并行执行,其中整组可调参数可以在并行遗传算法上分开。根据问题的计算量,这些并行 GAs 可以被配置为细粒度的或粗粒度的。算法也可以采用主从方式,从机控制计算,主机控制选择过程。此外,解决方案还可以被配置为在不同的并行遗传算法之间结合不同的拓扑和迁移策略。所有这些变化使得遗传算法具有广泛的灵活性,并且绝对是一个需要了解的重要算法。

优化神经网络——从哪里开始?

原文:https://towardsdatascience.com/optimizing-neural-networks-where-to-start-5a2ed38c8345?source=collection_archive---------4-----------------------

通过使用 Google Colab 中的 Keras 构建和调整神经网络来发展直觉

Photo by Adi Goldstein on Unsplash

T 神经网络要调优的参数和超参数(以下都称为参数)非常多,那么从哪里开始呢?

在吴恩达教授的深度学习专业化课程中,他给出了以下指导方针:

  • 学习率开始;
  • 然后试隐藏单元数量 s、小批量尺寸 e 和动量项
  • 最后,调整层数学习率衰减

这些都是很好的建议。但是,为了使它们成为我们技能的一部分,我们需要直觉:)为了实现这一点,我用 Python 构建了一个可定制的神经网络类,并进行了一系列实验来验证这些想法。让我们看看!

设置环境

我们将在这个项目中使用 Google Colab ,所以大部分库都已经安装好了。因为我们将训练神经网络,所以使用 GPU 来加速训练是很重要的。

要启用 GPU,只需进入下拉菜单中的“运行时”并选择“更改运行时类型”。然后,您可以将鼠标悬停在右上角的“已连接”上进行验证:

获取数据

在本项目中,我们将使用皮马印第安人糖尿病数据集,原因如下:

  • 数据集具有挑战性,最高精度结果只有 77%左右,这给了我们做大量模型调整的机会;
  • 数据集很小,只有 768 行和 9 列。这使得我们可以更快地训练,从而可以进行 10 重交叉验证,以更好地表示模型性能。

虽然我们可以手动下载数据集,但为了重现性,还是从 Kaggle 下载吧。因为我们需要使用 Kaggle 的 API,所以我们将首先通过访问 Kaggle 上的“我的帐户”页面来创建 API 令牌。这会将一个kaggle.json文件下载到您的计算机上。

接下来,我们需要将这个凭证文件上传到 Colab:

from google.colab import files
files.upload()

然后我们可以安装 Kaggle API 并将凭证文件保存在。kaggle”目录。

!pip install -U -q kaggle
!mkdir -p ~/.kaggle
!cp kaggle.json ~/.kaggle/

现在我们可以下载数据集了:

!kaggle datasets download -d uciml/pima-indians-diabetes-database

该数据集将被下载到您当前的工作目录,即 Colab 中的“content”文件夹。由于每次重启 Colab 会话时文件都会被删除,因此将文件保存在 Google Drive 中是个好主意。您只需要使用下面的代码安装驱动器并保存在那里:

from google.colab import drive
drive.mount('/content/gdrive')

一旦安装完毕,你就可以通过“/content/gdrive”路径直接从 Google Drive 加载数据。当您需要保存绘图文件时,安装 Google Drive 也会派上用场。

带有 XGBoost 的基线模型

XGBoost 因其高准确性和高效率而被称为 go-to 算法。让我们试一试!

t1 = time()
clf = xgb.XGBClassifier()
cv = StratifiedKFold(n_splits=10, shuffle=True, random_state=seed)
scores = cross_val_score(clf, X, y, cv=cv)
t2 = time()
t = t2 - t1print("Mean Accuracy: {:.2%}, Standard Deviation: {:.2%}".format(scores.mean(), scores.std()))
print("Time taken: {:.2f} seconds".format(t))

然后我们得到了 74.88%的准确率,只用了 0.35 秒!如果我们将特征标准化并再次测试,我们将得到 76.31%的结果!这个结果已经非常接近这个数据集上的最新精度。

创建模型

为了能够测试不同的模型,我们需要动态创建模型的能力。同时,我们还需要测试模型并提供结果。这两种需求都让我想到了面向对象编程。然后我创建了下面的测试类。我将在另一篇文章中解释这一部分和下一部分的技术细节。

自动化测试

因为我们需要测试许多不同的参数组合,并且需要保存结果,所以自动化测试过程很重要。同样,让我展示而不是讲述,因为细节将在后面的帖子中解释:

基线神经网络模型

让我们从具有以下默认参数的基线模型开始:

  • 输入尺寸=8
  • 层数=2
  • 数量单位=8
  • 激活='relu '
  • activation_out='sigmoid '
  • 损失= '二元交叉熵'
  • 初始值设定项='random_uniform '
  • 优化器='adam '
  • 学习率=0.001
  • 度量=['准确性']
  • 纪元=10
  • batch_size=4
  • one_hot=False

如果我们跑:

param_dict_defaults, param_dict = get_defaults(), get_defaults()
accuracy_baseline = run_test(X=X, y=y, param_dict=param_dict_defaults)

我们会得到:

Finished cross-valiation. Took 1.5 mintues. Mean Accuracy: 71.61%, Standard Deviation: 2.92%

还不错,但肯定离 77.7%的顶级成绩差远了。

不同参数的重要性

为了理解不同参数对模型调整的影响,让我们一次调整一个参数,同时保持其他参数不变(因此不同于 sklearn 中的 GridSearchCV 等穷举搜索)。运行测试将为我们提供以下结果:

首先,有趣的是,上面的参数调优指南中没有提到的一些参数可能是重要的因素,例如优化器和时期。

第二,学习率确实是最有影响力的参数之一。

第三,对于这个特定的实验(包括参数选择),似乎层数比隐藏单元的数量更重要。这与上述准则相违背。

下面是调整趋势,可用于查找要调整的范围。

重要的是要注意,这里的测试只是为了提供一些直觉,不应该作为正式的规则。这是由于至少两个原因——一,各种参数及其候选值不一定具有可比性;第二,神经网络中存在天生的随机性,因此,如上图所示的结果可能会改变。

虽然参数值之间的相互作用很可能很重要,即 40 个历元在与非 0.001(例如 0.1)的学习率配对时可能会产生更差的准确性,但我们仍将在此尝试一种简单的方法——组合独立调整的最佳参数值并训练一个模型,这为我们提供了:

Finished cross-valiation. Took 49.3 mintues. Mean Accuracy: 78.00%, Standard Deviation: 4.59%

哇,这是一个残酷的 50 分钟!虽然我们不能抱怨结果,因为这是最先进的!看起来天真的方法确实有效。

参数调谐

现在我们已经看到了参数的相对重要性,是时候调整模型了。因为学习速度是最重要的,所以让我们先解决它。我们将使用下面的代码来生成 6 个介于 0.0001 和 0.01 之间的随机学习率值,因为根据上面的优化趋势可视化,这是最有希望的区域。

bases = np.repeat(10, 3)
exponents_1 = -(np.random.rand(3) + 3) 
exponents_2 = -(np.random.rand(3) + 2) learning_rate = np.power(bases, exponents_1).tolist() + np.power(bases, exponents_2).tolist()

运行测试后,我们得到了:

这使我们认为 0.0006716184352348816 是最佳学习率。让我们利用这一点,继续用 6 个选项来调整批量大小,因为我们肯定要相信 ng 教授的指导方针,即批量大小是第二重要的参数:)

batch_size = [2 ** e for e in range(6)]

尽管批量大小为 2 的结果更准确,但是时间成本远远超过了收益,所以我们将采用批量大小为 16 的结果。

在更新了参数字典中的批处理大小值之后,我们现在可以继续调整时期数了。由于训练和测试的时间会随着时期数的增加而增加,所以最好在以后的阶段调整这个参数,以避免长时间的运行。

这给了我们最好的 200 个历元。接下来,让我们构建具有标准化功能的最终模型:

run_test(X=X_std, y=y, param_dict=param_dict)

这给了我们:

Finished cross-valiation. Took 8.3 mintues.
Mean Accuracy: 78.53%, Standard Deviation: 3.64%

绝对伟大的结果!所用时间不算太差,虽然比 XGBoost 多了 1422 倍😂

现在,如果我们不调整参数,只标准化特性会怎么样呢?

Finished cross-valiation. Took 1.7 mintues. Mean Accuracy: 76.95%, Standard Deviation: 2.88%

因此,参数调整的效果似乎有点微不足道,但标准化,即使特征具有零均值和单位方差,对于神经网络模型调整来说是巨大的。

摘要

  • 学习率是需要调整的最重要的参数,因为它可以产生很大的性能改进,同时不会对训练时间产生负面影响。
  • 较小的批量可能会提供更好的结果,但也更耗时!同样,针对更多纪元的训练通常有助于提高准确度,但时间成本也很高。
  • 优化器可能是一个需要优化的重要参数。
  • 更深更广的神经网络可能并不总是有用的。
  • 特征标准化可以极大地提高模型性能,与参数调整相比,这是一项轻而易举的任务。
  • 神经网络很棒,但不是万能的。如上所述,训练和调整神经网络模型的时间比非神经网络要多几千倍甚至几百万倍!神经网络最适合计算机视觉和自然语言处理等用例。

你可以在 GitHub 上的我的项目报告中找到完整的代码。一定要试一试,看看你能得到什么结果!

感谢您的阅读!有什么我可以改进的吗?请在下面告诉我。我们都通过相互学习变得更好!

为 Postgres 优化 pandas.read_sql

原文:https://towardsdatascience.com/optimizing-pandas-read-sql-for-postgres-f31cd7f707ab?source=collection_archive---------4-----------------------

将 SQL 查询读入 Pandas 数据帧是一项常见的任务,可能会非常慢。根据所使用的数据库,这可能很难避免,但是对于我们这些使用 Postgres 的人来说,我们可以使用 COPY 命令大大加快速度。然而,有几种方法可以使用 COPY 命令将 SQL 中的数据放入 pandas,但需要不同的内存/速度权衡。在本文中,我们将测试几种不同的方法。

测试数据集只是样本 Triage 预测表的前五百万行,这只是我手边的一个。我试图使用本地 Postgres 数据库中的 1300 万行,但是 pandas.read_sql 崩溃了,所以我决定将数据集降低到它可以作为基准处理的水平。

每种方法都包括三种统计数据:

峰值内存—SQL 读取代码期间使用的最高内存量。这是重要的一点,看看你的程序是否会崩溃!

增量内存—SQL 读取代码结束时仍在使用的内存量。理论上,这对于所有的方法都是一样的,但是内存泄漏会使不同的方法保留更多的内存。

经过时间 —程序使用的时钟时间。

这里用的熊猫版本是 0.24.1。

首先,快速概述一下正在测试的不同方法:

  • pandas.read_sql —基线
  • 临时文件—使用临时文件模块在磁盘上创建一个临时文件,以便在数据帧读入复制结果之前,将它们存放在其中
  • StringIO——使用 StringIO 代替磁盘;使用更多内存,但磁盘 I/O 更少
  • 压缩 BytesIO,pandas 解压——用 BytesIO 代替 StringIO,压缩数据;应该使用更少的内存,但需要更长的时间
  • 压缩字节,gzip 解压缩—与其他压缩字节相同,但是使用 GzipFile 而不是 pandas 来解压缩
  • 压缩的临时文件——将压缩思想应用于磁盘文件;应该会减少所需的磁盘 I/O
  • 压缩字节数,低压缩级别—尝试分割未压缩方法和压缩方法之间差异的较低压缩级别

pandas.read_sql

这是基线。这里没什么特别的。

峰值内存:3832.7 MiB /增量内存:3744.9 MiB /运行时间:35.91s

使用临时文件

这是我们第一次尝试使用复制命令。来自 COPY 命令的数据必须使用 filehandle:还有比使用临时文件更简单的方法吗?

峰值内存:434.3 MB /增量内存:346.6 MB /运行时间:8.93 秒

那……好多了。对于运行时间比 read_sql 快得多,我并不感到惊讶,但我有点惊讶的是,内存使用量相差如此之大。不管怎样,我们继续吧

使用弦乐器

磁盘 I/O 可能很昂贵,尤其是取决于可用的磁盘类型。我们可以通过使用 StringIO 作为文件句柄来加速它吗?当然,这会占用更多的内存,但也许这是我们可以做的一个折衷。

峰值内存:434.2 MB /增量内存:346.6 MB /运行时间:9.82 秒

这是一个令人惊讶的结果。我本以为这会占用更多的内存,速度会更快,但事实并非如此。我的假设是,StringIO 使用的内存峰值最终会在数据帧创建过程中被一个峰值超过。

还要注意:增量内存与临时文件版本相同,这可能告诉我们,346.6 MB 是在没有任何内存泄漏的情况下内存基线的一个很好的参考。

使用压缩字节,熊猫解压。

我们能降低内存选项所需的内存吗?鉴于之前的结果,这可能看起来像一个傻瓜的差事,但我已经写了代码,所以我不会提前停止测试!Python 的 GzipFile 接口包装了一个 filehandle(在本例中是一个 BytesIO)并处理压缩。我们让 pandas 通过将“compression='gzip '”传递给 read_csv 来处理解压缩

峰值内存:613.6 MB 增量内存:525.8 MB,耗时:1:30 分钟

不好!与未压缩版本相比,它实际上使用了更多的内存(并泄漏了一些)。

使用压缩字节,Gzip 解压缩

和上一个一样,除了我们绕过熊猫的解压程序,以防它们带来问题。GzipFile 也可以为我们处理解压缩!

峰值内存:504.6 MB 增量内存:416.8 MB,耗时:1:42m

当然,这比熊猫的解压缩版本在内存方面要好,但是这仍然比未压缩的版本差。

使用压缩的临时文件

压缩思想也可以应用到以前的 tempfile 方法。在这种情况下,压缩应该可以帮助我们减少磁盘 I/O。

峰值内存:517.2 MB 增量内存:429.5 MB,耗时:1 分 35 秒

类似于其他 gzip 示例。不是一个好的选择。

使用压缩字节,低压缩级别

既然我们正在尝试,我们还有一个途径可以探索:gzip 压缩级别。前面所有示例的默认值是 9,这是可能的最高压缩率。在这样做的过程中,除了额外的时间之外,还可能需要额外的内存来进行压缩。如果我们将其中一个翻转到最低压缩级别(1)会怎么样?

峰值内存:761.5 MB 增量内存:673.8 MB,运行时间:1 分 13 秒

在时间上稍微好一点,但是在 RAM 上更差:看起来 gzipping 进程无论如何都要使用大量的内存,并且不能很好地传输。

结论

我们在这里学到了什么?

  1. pandas.read_sql 很烂,无论是时间还是内存。
  2. 使用带有 COPY 的 StringIO 或 tempfile 可以执行类似的操作。很容易将 tempfile 称为赢家,但我要强调的是,这完全是基于对您来说便宜的东西。这个测试在我的笔记本电脑上运行,使用本地磁盘。根据设置的不同,使用磁盘 I/O 可能会更昂贵!但是这两个例子一般来说都非常快,应该是你的首选!
  3. 压缩的想法似乎是在转移视线,至少在用 gzip 实现的时候是这样。GzipFile,它的内部我并不完全熟悉。可能有其他更复杂的方法可以工作(例如 zlib.compressobj,或者其他完全的压缩类型),但是这里没有。

优化你被医学院录取的机会

原文:https://towardsdatascience.com/optimizing-your-chances-of-medical-school-admission-5aa75f39fb48?source=collection_archive---------11-----------------------

2016 年,全美共有 27772 名学生申请了医学院。这些学生中,8883 人录取率 32% 。但当然,总体录取率并没有太大启发。我们对这篇文章真正感兴趣的数据是关于录取率如何根据 GPA 和 MCAT(医学院入学考试)分数变化的。

我们当然大致知道,在其他条件不变的情况下,更高的 GPA 和/或更高的 MCAT 分数会导致更高的录取机会,但我们想在这里真正了解细节。我们的分析将通过提出一系列问题进行:

录取率与 MCAT、录取率与 GPA 有什么模式?

给定这些模式,我们能建立一个包罗万象的模型来预测给定 MCAT 和 GPA 的录取率吗?

鉴于这种模式,能否为准医学院学生推荐一条优化录取机会的路径?

为了回答这些问题,我们将使用来自美国医学院协会的数据,该数据给出了 GPA 和 MCAT 分数选择范围的录取率。

让我们从简单的开始。基于 MCAT 和 GPA 的录取率如何变化?

我们都期望随着 MCAT 和 GPA 分数的增加,录取机会或录取率也会增加,但是怎么增加呢?线性? 二次?或者干脆是别的什么?

让我们先来看看在 MCAT 保持不变的情况下,由于各年级 GPA 的变化而引起的录取率的变化。请注意, MCAT 的得分介于 472 和 528 之间,中间值为 500 。下面,我们将 MCAT 固定为三个范围:514–517(高)498–501(中)486–489(低)。对于每个范围,我们绘制了录取率与 GPA 的关系图。

录取率 vs. GPA 似乎有一个 (大致)线性 的趋势。

这种线性关系的斜率随着MCAT 分数的增加而增加。换句话说,你的 MCAT 分数越高,平均绩点每增加一分,你被录取的机会就越大。这是 GPA 和 MCAT 决定录取率的一些初步证据。**

给定一个足够低的 MCAT 分数,在获得医学院的录取上没有 GPA 可以弥补 。也就是说,看看底部的红线,MCAT 在 486 和 489 之间,2.5 比 3.9 的 GPA 给出了大约 3%的录取率。

现在让我们转向一个更有趣的趋势,对于一些固定的 GPA 值,录取率与 MCAT 的对比。这里我们把绩点固定在三个水平:3.8–4.0(高)3.4–3.6(中)3.0–3.2(低)。请注意,尽管 3.0 的平均绩点被标为,但你应该认为这意味着相对较低,而不是绝对低。事实上,如果 MCAT 分数足够高,即使那些平均绩点在低范围的学生也能达到 50%的最高录取率。

这个图形最引人注目的地方在于,这些曲线并不遵循线性或二次趋势,而是遵循一种被称为 s 形 数学形状。Sigmoids,通常是 S 形曲线,出现在许多其他情况下,也许最流行的是在人口模型。他们描述了一些过程,即 缓慢回升 (开始时缓慢增长) 然后获得动力 (中间快速增长),在 之前最后在某一水平封顶 (最后缓慢增长)。

事实上,它们在我们的上下文中也很有意义!给定一个非常低的 MCAT 分数,增加一点分数在开始会有一点帮助,但不会有太多帮助。一旦你不断提高 MCAT 分数,你就会获得越来越大的收益,导致你的录取率越来越快。最后,当你的 MCAT 分数已经相当高的时候,额外增加你的 MCAT 分数并没有多大帮助。

还要注意的是,GPA 值越高,sigmoid 形状就越明显。我们还可以看到不同 GPA 水平对乙状结肠的影响,例如,通过查看三个 GPA 等级中 MCAT 最高值的录取率。我们看到对于低 GPA 曲线,这里的录取率在 50% 左右,对于中 GPA 曲线在 60% 左右,对于最高 GPA 曲线在 85% 左右。

酷炫潮流!但是我们能给它们装上模型吗?

现在我们对基于 GPA 和 MCAT 的录取率趋势有了一些了解,我们想知道我们能否用一个(不太复杂的)数学模型来预测这些趋势的录取率,无论 GPA 和 MCAT 分数的组合如何,都有相当高的准确度。在解决整个问题之前,让我们先看看从最后一个数字中预测这些 sigmoids 有多好。

在这里,我们从上一节中选取了三条录取率与 MCAT 曲线, (仔细地)选择了一些 s 形曲线来最好地拟合这些数据 。s 形拟合用红色虚线表示。回想一下,这三条曲线分别代表 高、中、低 GPA 段 。我们看到至少 对于 GPA 高的波段,我们的预测几乎是提督 。当我们到达较低的 GPA 段时, 预测没有那么强,但仍然捕捉到数据的动态

利用我们的模型似乎可以很好地预测更高的 GPA 值这一事实,我们将限制我们对 GPA 为 3.1 或更高的申请人的预测。我们还将我们的预测限于 MCAT 分数为 492 或更高的申请人,以减少来自低 MCAT 申请人的噪音

完整的模型

所有的部分都在这里。但是我们需要把它们放在一起,以创建一个无所不包的模型,根据你的 GPA 和 MCAT 分数,这个模型将给出(希望是准确的)你被美国医学院录取的预测。概括地说,让我们列出这样一个模型需要包括的内容:

给定一些固定的 GPA 值,模型需要为 sigmoidal,以改变 MCAT 分数的值。

给定一些固定的 GPA 值,这种 sigmoid 的性质(斜率、偏移量等。)需要随着 GPA 的变化而变化。

给定 MCAT 分数的某个固定值,对于变化的 GPA 值,模型需要(大致)线性。

该模式将仅限于平均绩点 3.1 或以上,MCAT 分数 492 或以上的申请者。

考虑到所有这些规则,并使用数学拟合技术来最小化我们的误差,我们得到了两个相互作用的变量 GPA 和 MCAT 的预测函数。给定我们的预测函数,我们现在可以从有效范围中选择任何一组 GPA 和 MCAT,并绘制相应的录取比率表面

这里的 x 轴代表 GPA y 轴代表 MCAT 分数 z 轴代表录取率

结果表明,该模型的均方根误差(RMSE)约为 3.8% ,即平均而言,在所有 GPA 和 MCAT 值中,我们与录取率的真实值相差 3.8%。不算太坏!

那么一个未来的医学院学生如何使用这个呢?

所以我们有一个相当准确的模型来预测只给 GPA 和 MCAT 分数的录取率。一个正在努力优化自己医学院录取机会的学生如何使用这个工具?

假设你是一名在校学生,平均绩点为 3.4,MCAT 分数为 512。你的自然问题应该是“我应该花时间提高我的 MCAT 还是我的平均绩点?”毕竟,你一天只有 24 小时。

回答这个问题的一个自然的方法是关注给你最大录取率提升的那个。如果这似乎是一个奇怪的想法,假设你是一个处于更极端情况下的学生。你是一名平均绩点为 3.96,MCAT 分数为 485 的学生。当你的平均绩点已经很高的时候,把所有的空闲时间都花在考试学习上,试图提高你的平均绩点是没有意义的。考虑到你的 MCAT 分数低于中位数,如果你不努力的话,可能会严重阻碍你被录取的机会,这尤其没有意义。

所以,问题是,我们如何衡量平均绩点的提高和 MCAT 分数的提高带来的录取率提升?

我们可以很容易做到这一点,如果我们看看上面的表面,然后把它当作一种“山”。也就是说,我们的目标是在那座山上越爬越高,因为这意味着获得越来越高的录取机会。假设你站在那座山上的某个地方,想知道获得一定高度的最佳方法。你可以通过在 GPA 方向走几步看看你的录取率会发生什么,然后当你在 MCAT 方向走几步看看它会发生什么。

当我们说几步的时候,我们需要稍微小心一点。我们注意到的 GPA 范围从 0.0 到 4.0 (长度 4),而 MCAT 的范围从 472 到 528 (长度 56)。代替任何关于 GPA 增益与 MCAT 增益相对难度的详细信息,我们做出简化假设,将 GPA 中的 1 点增益与 MCAT 的 14 点增益相匹配(因为 56 除以 4 等于 14)。

我们在下面显示了 MCAT 和 GPA 的一些区间的预测录取比率值的表格,其中相对 GPA 和 MCAT 步长由上面讨论的大约为 14 的缩放因子确定。

使用这个表格,假设你的平均绩点是 3.4,MCAT 分数是 512。你最好的行动是什么?嗯,目前你的录取几率是 47.35% 。如果你把你的平均绩点提高一点,你被录取的几率会跃升至 55.6%,而把你的 MCAT 提高一点,你的录取几率只会上升至 50.25%。因此,你现在应该专注于你的平均绩点。事实上,这是有道理的,因为你的 MCAT 分数远高于 500 分的中位数,但你的平均绩点仍需要努力。

我们可以对表格中的每个单元格进行这种分析,并将该决定简化为一个 右箭头指示您应该提高您的 GPA ,或者一个 下箭头指示您应该提高您的 MCAT* 。***

我们得到下面的结果。

现在假设我们是一个 GPA 为 3.4,MCAT 为 494 的学生。我们可以从初始状态开始跟随箭头开辟出一条通往成功的道路(越来越高的录取率)。

对于 GPA 和 MCAT 分数的任何组合,我们都可以这样做。只需从初始状态开始,跟随箭头找到通过 GPA-MCAT 空间的最佳路径。

概括一下,

我们使用原始录取统计数据来捕捉 GPA、MCAT 和录取率之间的趋势

我们使用这个预测模型,根据未来医学生目前的排名,为他们建议一个行动方案。

最后,我们展示了来自预测模型的更精细的数值表。你可能需要放大!。****

最后,请注意,如果你查看你的平均绩点和 MCAT,发现这个比例并不高,你就没必要紧张! 为什么?因为首先,这是一个有一定误差的模型(3.8% RMSE)* 。第二,这个没有考虑课外、性别、种族等其他录取标准。,同样有影响。因此,与其说这是一个终极预测,不如说是一个基准测试。 祝你好运!***

数据集引用

[1] 美国医学院申请人和被录取人的 MCAT 和 GPA 表格 (2017),美国医学院协会

公民数据科学工具与 Python 用于机器学习

原文:https://towardsdatascience.com/oracle-cloud-analytics-vs-python-for-machine-learning-b19309aa3224?source=collection_archive---------17-----------------------

本实验的目的是调查数据科学流程在行业领先的基于云的分析工具中的应用。

实验的目标是评估在不输入代码的情况下,在分析云工具内完成准确的机器学习实验的可能性。完成这项任务的能力表明,具有很少或没有编码知识的最终用户能够多么容易地拿起工具,并将机器学习技术应用于他们的数据。

实验试图提供证据来支持或否定以下假设:

“我相信一个在数据科学和机器学习方面经验很少的用户可以直接在甲骨文的云分析工具 OACS 中创建一个简单的端到端数据科学流程的产品,而无需编写任何复杂的代码,时间只需用 Python 编写代码的一半”

在这个实验中,我使用了甲骨文的工具,我并不偏爱这些工具,有很多技术可以达到类似的效果。

任何最终分析都将直接链接回该语句。

许多行业领先的 BI 软件供应商已经调整了他们的数据可视化工具,以适应利用高级分析和数据科学技术的行业趋势,使客户能够从他们的数据中获得洞察力,这在过去是不可能的。

许多双领导者基于云的产品现在正在寻求“弥合”BI-传统商业智能和 AI-机器学习和高级分析之间的差距。这个实验试图为 OACS 证明这个概念。

基线

实验的基线将是用 Python 设计的代码脚本。实验数据集是从一个 Kaggle 机器学习竞赛中提取的,该竞赛旨在测试数据科学家使用机器学习模型和数据科学技术预测房价的能力。

这里是 Python 中的实验——作为到原始内核的链接。

[## 基本套索,包括数据准备

下载数千个项目的开放数据集+在一个平台上共享项目。探索热门话题,如政府…

www.kaggle.com](https://www.kaggle.com/kenhunt1010/basic-lasso-including-data-prep)

训练和测试数据集可从 Kaggle 获得。

得分

使用 Python 和云分析技术训练的模型将由 Kaggle 独立评分。如需了解有关本次竞赛的更多信息,包括数据描述和细节,请点击此处

将使用均方根误差对测试数据集上生成的预测进行评分。

关于均方根偏差的更多信息

技术考虑

  • 基线用 Python 3.6 编码在 Jupyter 笔记本中。
  • 云分析工具是 Oracle 云分析服务 v18。

该过程

数据科学的流程如下图所示。

数据探索

实验的第一阶段是进行一些分析,以找出更多关于所提供的数据集的信息。

相关矩阵

第一步是从整体上理解数据集。一个坚实的起点是创建一个相关性矩阵,以帮助理解指标之间的相关性。

识别关系和异常值

接下来,确定高度相关的指标,并绘制成单独的分析图,以便更好地了解它们;关键目标是呈现任何线性关系并识别数据集中的任何异常值。

这里特别有用的一个特性是能够快速选择一个数据点并在散点图中改变它的颜色。这使得突出显示最左边散点图中的异常值(红色)变得很容易。

Oracle DV 的注释特性在这里同样很有帮助,尤其是在以后要展示分析的时候。

询问目标变量

数据科学流程的下一步是了解更多关于我们的目标变量的信息,这非常简单,数据集在 Data Visualiser 中打开,我们的指标被识别出来并右键单击。“解释”被选中。OACS 在这里做了所有艰苦的工作。OACS 潜在的机器学习算法消失了,尽管所有的关系可能是突出的,然后自动呈现一个完整的分析负载,可以询问。

可以选择单个分析,并将其放到 DV 画布上,以便进一步深入研究。

这一功能非常出色,它节省了流程中的大量时间,并且只需单击一个按钮,就可以轻松识别数据集中的模式。

目标变量的分布

在进行了由 OACS 自动呈现并添加到画布上的分析后,对图表进行了微小的修改,以改变 X 轴上的粒度,从而更准确地显示目标变量中的数据分布。

补充说明:在 OACS 找不到一种方法来编码整个数据集的空值标识。在 python 中,我们可以获取一段代码,并编写一个 FOR 循环,在数据集中的所有列上迭代代码。在 OACS,我们可以添加自己的 python 代码,但这与假设相矛盾。

只需点击几下,最左边的图表(下图)就出现了。从这个可视化中可以清楚地看到,数据是向左倾斜的。通过将 LOG()应用于变量,创建了一个自定义指标,以使图表显示为右侧的图表——一个清晰的(有点)钟形。

这需要进一步调查。目前,用户需要编写单独的逻辑来识别每一列中的空值。这将花费大量的时间。

使用 Oracle 数据流进行数据准备

下一个阶段是准备数据,以便用于训练模型。创建以下数据流是为了对数据执行之前确定的操作。

  • 移除先前发现的异常值
  • 添加一个可能有用的计算列(总表面积),该列是通过将数据集中的其他列相加而创建的。
  • 将 log()列添加到数据集中(如果在上一步中未完成)
  • 删除对预测无用的计数列。

数据集已保存(这里是数据流中的最后一个节点)。也可以在这里更改输出数据集的数据类型。这很有用,因为这意味着我们不需要编写代码来设计这些功能。

当我们在文本和数字之间转换时,空值会自动发生一些事情,需要进一步研究。

Nulls 和 NAs 的估算器

由于缺乏对列进行迭代的能力,该数据集中的 NAs 没有被单独估算,因为这需要跨每列的单独 case 语句。相反,选择的算法有一个输入函数;这允许用户为分类或连续变量选择估算方法。

这里的限制是用户必须对相同类型的所有列使用相同的 inpute 方法。也就是说,不可能将连续变量 A 中的 NAs 作为平均值,而将连续变量 B 中的 NAs 作为中位数。

模型选择和培训

“数值预测”模型类别中有 4 种不同的模型。

注意:我们可以添加我们自己的包含定制模型的 python 脚本,这个功能将在稍后评估

出于本实验的目的,选择了“用于模型训练的线性回归”,这提供了一种套索回归方法,它与作为基线创建的 python 代码相匹配。

OACS 的这一领域需要一些如何选择 ML 模型的知识-如果 OACS 试图真正让每个人都可以使用数据科学,应该有一个帮助链接,其中包含用户如何选择特定模型的见解,或者至少是每个模型或模型组通常擅长/不擅长什么的高级描述。我们训练过的模型被保存了,它位于 OACS 的“机器学习”部分,可以从主页菜单上找到。

应用模型

一旦我们有了训练好的模型,我们现在需要将它应用到我们的测试数据集。测试数据集被上传到 OACS 并保存为数据集。然后,我们创建另一个数据流,并在其中选择“应用模型”。选择“应用模型”后,我们会看到一个模型列表,其中填充了我们刚刚训练的模型。我们应用我们的新模型,并选择保存预测的列的名称。

整理并提交

我们剩下的数据集只包含一个 ID 和一个提交。

“我相信一个在数据科学和机器学习方面经验很少的用户可以直接在 Oracle 的云分析工具 OACS 中创建简单的端到端数据科学流程的产品,而无需编写任何复杂的代码,时间只需用 Python 编写代码的一半”

该图说明了两个线性回归实验的精确度非常接近。Python 代码在准确性上略胜 OACS 一筹,然而 OACS 用的时间却少得多。

回到假设:

  • 没有自定义代码添加到 OACS 创建所需的人工制品
  • 不需要机器学习方面的大量培训,用户就可以遵循这些步骤,只需要对通用数据科学流程的工作原理有一个基本的了解,例如,以什么顺序完成任务以及不同的模型做什么。
  • 所有工作都直接在 OACS 进行。
  • 在 OACS 繁殖只需要不到一半的时间。

我相信这是被证明的,实验是成功的,尽管有一些需要进一步调查的警告。下面列出了这些。

进一步的调查

在线协作

这与将我们自己的脚本添加到产品中的能力密切相关。PowerBI 有一个很好的平台,用户可以在 R 中创建视觉效果,并在在线社区中共享它们,一旦用户找到了一个在线视觉效果,他们就可以点击将它添加到他们的实例中。类似这样的事情——在线协作和共享代码的能力确实会让这个工具更有吸引力。我想知道这是甲骨文最近收购 DataScience.com 的原因吗?

将我们自己的脚本添加到 OACS

这项功能需要 Python 和 XML 的工作知识,它当然不适合能力很弱的用户,因此不在实验范围内。该功能要求用户用 python(或 R)定义一个函数,并在上传之前将其放入通用的 XML 包装器中。

非常吸引人的是,改进后的产品不再需要 XML 包装器,这样用户就可以从其他站点获取其他代码,并在 OACS 环境中有效地进行测试。

堆叠模型

这似乎是可能的,会需要多个数据流和一些数据集,但没有真正的问题,它可以大大提高模型的准确性和效率。

遍历列

如前所述,如果产品可以获取一段简单的 OACS 代码(例如 CASE 语句),然后在数据集中的每一列或一组选定的列上迭代运行,这将节省大量时间。

顺序

实验中提到的所有数据流都可以按顺序放在一起并连续运行,以创建一个“ETL”风格的管道。实验没有触及这一功能。

原载于 2019 年 5 月 5 日【http://drunkendatascience.com】

面向 Python 的 Oracle 机器学习

原文:https://towardsdatascience.com/oracle-machine-learning-for-python-e335fc0a50e8?source=collection_archive---------12-----------------------

oml 4 py:Oracle 高级分析的 Python 扩展。

引言。

这些天,我和我的同事 C. De Bari 正在为客户和合作伙伴安排培训,我们将在培训中讨论 Oracle 针对 Python 的机器学习。酷,但这是什么?

Oracle DB 很久以来就有一个选项叫做: Oracle 高级分析。它是一个选项,让您可以访问许多广泛使用的机器学习算法,并使您能够运行这些算法,而无需将数据从数据库中移出。

有很多算法可用。用于回归、分类、异常检测、聚类、特征提取等的算法。名单很长。

将这些算法作为 Oracle DB 的一部分,不仅可以让您在不将数据从数据库中移出的情况下获得机器学习的能力,以及安全性、效率等方面的所有积极影响,还可以利用底层并行数据库引擎。

到目前为止,唯一可用的接口是:PL/SQL 和 R. OML4Py 让您能够调用所有这些算法,其中一些是最近添加的,使用的是现在数据科学中使用最广泛的语言: Python

OML4Py 将很快作为 Oracle Database 19c 的一部分在内部提供,然后作为 Oracle Cloud 的一部分。

Python 客户端库。

首先,我们可以将 OML4PY 看作一个客户端库,您可以在 Python 程序或 Jupyter 笔记本中使用它来调用 Oracle 机器学习算法。

好的一面是,这个库的设计使得那些已经在使用像 Scikit-learn 这样的开源框架的人开始编写 ML 代码变得更加容易。API 非常相似。

使用 OML4PY,您可以:

  • 连接到数据库
  • 创建 Python 数据帧,它们是 Oracle DB 表的代理对象
  • 根据这些表中的数据训练您选择的算法
  • 给你的算法打分,提高性能
  • 根据新数据进行预测

OML4Py 将通过基于 cx_Oracle 的 Python 模块(OML)提供。

部署架构。

代理对象。

这是一个很好的特点。

如果你在 scikit-learn 上学习过 ML,你会意识到很多例子都使用了包装在 Pandas DataFrame 中的数据。 DataFrame 是一种表格结构,在许多方面类似于 DB 表,有行和列。您可以使用一行 Python 代码从 csv 文件或 Oracle DB 表中加载 Pandas 数据帧。但是熊猫的数据帧完全保存在内存中。因此,它的大小受到可用内存的限制。

使用 OML4Py,在与 Oracle DB 建立连接之后,您可以轻松地创建一个与 DB 表同步的 OML 数据框架

data = oml.sync(table = 'BREASTCANCER')

有什么区别?不同的是,“数据”是一个“代理对象”。同步调用不会将内存中的数据从数据库中取出。相反,它将 Python 对象连接到 DB 表,对 OML 数据帧对象的所有后续调用都将被翻译成在 DB 内部执行的 SQL 指令。

例如,您可以调用:

data.head()

其中数据是 OML 数据帧,你会在你的笔记本上看到前 10 行的列表。head 调用被翻译成一个 SQL SELECT 语句,只有第一行从 DB 中提取出来并返回给 Python 进程。

从最大似然的观点来看,重要的是你将使用 OML 数据框架作为训练你的最大似然算法的起点,就像你在 scikit-learn 中使用熊猫数据框架一样。

如果需要,您也可以从 OML 数据帧中提取熊猫数据帧,使用:

data.pull()

这样你就可以使用你已经开发的所有 Python 代码。

算法。

受支持的 ML 算法列表相当长且完整。

只是给你一个想法,你可以用:

  • 朴素贝叶斯
  • 广义线性模型
  • 决策图表
  • 随机森林
  • 支持向量机(线性,高斯)
  • k 均值(聚类)
  • 一级 SVM(异常检测)
  • 神经网络(目前是密集的)

但是,您不仅有一个很好的 Oracle DB ML 实现的 Python 接口,还有一些重要的特性,如:

  • 超参数的自动调谐
  • 自动型号选择
  • 自动特征提取

换句话说, AutoML ,它可以极大地简化你的机器学习模型的调整,并减少为你的商业案例获得正确模型性能所需的时间。

另一个旨在简化 ML 采用的重要特性是,许多算法自动处理空值、分类特征编码和特征缩放。在 scikit-learn 中,如果你想获得正确的性能,你必须做所有这些事情写代码。

我已经使用威斯康星乳腺癌数据集对 OML4Py 和 scikit-learn 进行了测试,在所有使用 AutoML 的情况下,我都看到了比 scikit-learn 更好的准确性。我已经达到了相当的准确性,只做特征缩放和准确的超参数选择。有时是一个相当长的过程。

还有什么?

此外,使用 OML4PY,您可以轻松地从 DB 加载和存储数据。

但是,最有趣的是名为“嵌入式执行的特性。这意味着您还可以编写自己的 Python 代码,例如使用 scikit-learn 算法的函数,将该代码存储在数据库中,并调用该函数将其应用于从数据库中选择的数据。只有几行代码。

这是一个有趣的扩展机制,我将在接下来的几周中对其进行更多的探索。

举个例子。

在下面的代码示例中,我展示了如何使用支持向量机创建一个机器学习模型,用于对患者进行分类。该示例基于 Wisconsin 乳腺癌数据集,数据存储在 Oracle DB 表中。

import oml
from oml.automl import ModelTuning
from oml import algo
import config

# connection to Oracle DB...
oml.connect(config.USER,config.PWD,
 '(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=localhost)(PORT=1521))(CONNECT_DATA=(service_name=OAA1)))',
 automl=True)
# test if connected
oml.isconnected()

# create an OML dataframe connected to DB table
BREASTCANCER = oml.sync(table = 'BREASTCANCER')

# train, test set split
train_dat, test_dat = BREASTCANCER.split(ratio=(0.8, 0.2), seed=1234)
train_x = train_dat.drop('TARGET')
train_y = train_dat['TARGET']
test_x = test_dat['TARGET']
test_y = test_dat.drop('TARGET')

# I'll be using AutoTuning
at = ModelTuning(mining_function = 'classification', parallel=4)

# search the best algorithm and fit
results = at.run('svm_linear', train_x, train_y, score_metric='accuracy')

tuned_model = results['best_model']

# make the prediction on test set
pred_y = tuned_model.predict(test_x)

test_y_df = test_y.pull()
pred_y_df = pred_y.pull()

# utility function based on sklearn for displaying accuracy, precision, recall, F1 score
myutils.print_metrics(pred_y_df, test_y_df)

结论。

OML4PY 是对 Oracle Advanced Analytics 的扩展,它为您提供了一个与 Oracle DB 机器学习算法的友好易用的 Python 接口。

使用 OML4Py,您可以开发 ML 模型,在 Oracle DB 中运行,编写 Python 代码,这些代码在许多方面类似于您使用 scikit-learn 编写的代码。

但是,除此之外,您还可以使用自动功能选择、自动型号选择和自动调谐等功能。

它将很快向客户全面推出,我们正在为意大利的客户和合作伙伴提供一些培训。

我将很快就这个主题写一些更详细的文章。

序数,名义,…谁在乎?

原文:https://towardsdatascience.com/ordinal-nominal-who-cares-82c867d7b774?source=collection_archive---------33-----------------------

我的表妹是一名高三学生,当我最近见到她时,我问她:“你的课上得怎么样?”她转动着十几岁的眼睛,表达了她对统计课上必须学习的所有词汇的不满。“序数,名义,……谁在乎?”她感叹道。安娜,我告诉你。

数据科学家非常关心序数和名义数据。对于那些没有上过高中统计学课的人,让我们回顾一下:分类数据分为两类——有序数据和名义数据。有序分类数据是具有隐含顺序的非数字信息,例如,从非常不满意到非常满意的调查回答。名词性分类数据是非数字信息,没有任何固有的顺序,例如颜色或状态。

有序数据和名义数据之间的区别在我最近构建预测房价的线性回归模型时极其重要。我为建模准备特征的方式很大程度上取决于数据类型。下面是我的模型中四个特征的子集——一楼面积、住宅类型、厨房质量和社区。

Original dataframe with four variables

为了建立我的线性回归模型,我必须将所有的数据转换成我的模型可以处理的数字信息。但是并不是所有的特征数据都是数字的,所以在这里了解我们的数据类型是必要的。让我们来看看每个特性。

  1. 第一层的面积已经是数值了(实际上是连续的数值),所以这里没有工作要做。
  2. 住宅类型看似是数字,其实不是。仔细查看数据字典(如下图)会发现,这些数据是分类的,我们看到的数字只是其他更长标签的代码。使用这些数字不是为了暗示顺序,而是为了缩短本列中每个观察值的标签长度。住所类型的数据类型是名义分类,因为数字代表标签,标签没有特定的顺序。

Data dictionary for type of dwelling

我通过制造假人将这种名义上的分类特征转化为数字信息。如果您注意到原始数据框架中列出了四种住宅类型:20、50、60 和 180。为类型创建虚拟对象会为每个可能的输出创建一个新列,如果属性是特定的类型,则列出 1,如果不是,则列出 0。在带有类型假人的数据框中(如下),您可以看到第一个住所是类型 60,第五个住所是类型 50。

Dummies created for type

(*在创建虚拟模型的过程中,删除了任意虚拟列。在此数据框架中,开始时有四种住宅类型,但现在只有三个住宅类型的虚拟列。一般来说,如果一列中有 n 个输出,那么应该有 n -1 个虚拟列。这是数据科学中的常见做法,因为所有信息都以更有效的方式保存。有一个简单的方法来思考这个问题——如果我告诉你今天是工作日,不是星期一、星期二、星期三或星期四,即使我没有明确告诉你,你也会知道今天是星期五。)

3.对于厨房质量,我们看到一系列两个字母的代码。看一下数据字典会给我们更多的信息。

Data dictionary for kitchen quality

将两个字母的代码解释为从差到优的厨房质量的离散描述是合理的。这些标签有顺序的事实意味着在厨房质量特征中有分类序数数据。我没有对这个分类变量使用虚拟变量,而是将从差到优的等级改为从 1 到 5 的等级,如下所示。

Dataframe after kitchen quality transformation

4.要解决的最后一个特征是邻域。邻域没有顺序,所以这是一个名义分类变量。因此,我将创建假人,就像对住宅类型所做的那样。在下面的数据框中,您可以看到这种变化。(同样,删除了一个虚拟列。)

Final dataframe

所以你看,安娜,分类数据的类型——顺序的或名义的——是很重要的,因为它通知了关于将标签转换成数字的决策。现在是时候根据数据建立模型了!

组织级分析:今天的创业公司建立社会。好好做。

原文:https://towardsdatascience.com/org-scale-analytics-todays-startups-build-societies-do-it-right-4f6185e81482?source=collection_archive---------17-----------------------

作者:塞斯·弗雷、格蕾丝·本菲尔德、克拉克·伯尼尔、马腾·博斯、切伦·布达克、西蒙·迪代奥、罗斯塔·法尔赞、本杰明·樱井真子·希尔、阿比盖尔·雅各布、赛弗·萨维奇、亚伦·肖

Credit

组织级分析使用数据科学来比较团体、团队和组织。

Slack 最近的200 亿美元估值使其成为精简数千个组织内部动态的公司舰队中的旗舰。尽管 Slack 的成功在一定程度上是由广泛的用户测试推动的,但他们是越来越多的公司的一部分,这些公司不仅仅是分析他们产品的变化如何影响个人:他们关注实验如何影响整个团队和组织的成功。优步也在几个测试市场评估价格变化对人口水平的影响,然后在全系统推广。脸书不是在样本用户中测试新的社交功能,而是在国家样本中测试。这些是组织级分析的例子:不仅跨越人群,而且跨越人群的大规模定量比较分析。

托管平台和解决方案的公司倾向于为群体服务,而不仅仅是孤立的个人。那么,为什么他们用来衡量成功的工具关注个人用户的结果呢?组织级分析利用现代平台的范围和标准化、现代数据分析和建模技术的能力以及大容量、高粒度数据来跨团队(例如 Slack)、公司(例如 Salesforce、IBM 和微软)、社区(例如脸书)和城市(例如优步)进行比较。通过关注组织规模,企业可以超越个体规模分析的基本假设:产品的利益仅仅是用户产出的总和。

尽管它很有前景,但目前很少有分析师利用组织级分析,更少有人认识到它的全部潜力。企业、团队和教室——甚至是 MOOCs、运动队和视频游戏公会:认识到你服务于一起兴衰的人群可以改变你如何看待你的数据、你如何构建新服务以及你如何在行动中评估它们。通过将现代平台视为人口级别的培养皿,组织级分析将数据科学带到了下一个分析级别。

Org-scale analytics uses data science to compare groups of groups, teams, and organizations.

组织级分析

组织级分析涵盖了定量方法的范围,但它植根于标准的用户级方法,如 A/B 测试。在 A/B 测试中,随机向用户展示一个新功能的两个版本(“A”或“B”),并跟踪他们的反应,以查看哪个版本最能引发所需的行为。

为什么 A/B 不在团队甚至公司的规模上测试产品或服务?答案是 A/B 测试通常需要对被比较的版本进行大量的控制:它们必须是相同的,除了一个不同之处。

对数百万家公司进行的 A/B 实验将要求各种规模和种类的群体在相同的界面中以某种方式遵循相同的步骤来实现相同的过程。幸运的是,这种不太可能的事态是许多现代平台和组织的完美描述。Salesforce 提供标准化的自动化界面,帮助超过 100,000 家公司与其客户联系。一系列麦当劳特许经营是严格标准化的、高度控制的、非常大规模的公司群体,这些公司处于一个理想的位置,可以从服务创新的受控测试中受益。甚至主题公园也符合这一描述。它们是完全工程化和精心控制的真实世界社交系统,它们每周有近 100%的客人流动率,这有点像有一个大的红色重置按钮。想象一个连续周末的实验:在一个 10,000+人口城市的实验中,一年进行 52 次试验。这些例子之间的共同点是控制水平,使整个人口完全可比。正如个人层面的分析催生了一波又一波的成功故事——允许组织提出产品建议、自动完成文本输入、优化在线广告的目标定位,甚至在体育比赛中获胜——组织层面的控制使新的洞察成为可能。

超越个体规模的测试

组织级分析超越了传统的个人级分析。通过将焦点转移到组织层面,数据分析师可以超越由于文化、相互依赖和变异等因素导致的问题,这些因素经常会破坏个人层面的研究。

文化。文化规范不同于个人行为,它抵制传统的用户规模的干预。对于视频游戏开发商 Riot Games 来说,这是一个明显的问题。尽管 Riot Games 拥有强大的分析驱动型设计传统,但它无意中培养了游戏领域最有害的文化之一。其流行的团队对战游戏《英雄联盟》的匿名、好胜、年轻和男性玩家将聊天话语的语气带到了一个众所周知的粗俗低点。认识到这种文化不仅仅是其球员的总和,Riot 的分析小组 A/B 在团队和比赛的级别进行了测试。在一次干预中,他们禁止团队成员在没有明确选择的情况下与对手聊天。默认设置的这一简单变化导致骚扰行为下降了 30%,积极互动增加了 35%,尽管跨团队聊天仅减少了 1%。组织规模的测试帮助 Riot 打造了一种更具运动精神的用户文化。

相互依存。当许多人的互动产生结果时,个人层面的分析也会受到影响。当脸书扩展“喜欢”按钮以包含更广泛的反应时,它面临着这种挑战。如果 A/B 实验让你的朋友有能力发布新的反应,但只允许你,对照组,观看他们的乐趣,那么这个实验就设计得非常糟糕。这种设计永远不会把你的朋友对这个功能的反应和他们对你被排除在外的反应分开。脸书通过在爱尔兰和西班牙测试国家层面的反应来解决这个问题,他们选择这两个国家是因为它们与其他国家的联系相对有限。他们的方法认识到,一个产品的最终成功或失败更多地取决于群体而不是个人如何使用它。

变异。传统的 A/B 方法在处理团队和个人层面的差异方面也存在局限性。有些个人特质——无拘无束的创造力、令人窒息的怀疑精神——作为一个更大的群体的一部分是非常有价值的,但如果由所有成员来代表,就会变得极其有害。在这种情况下,用户角色——长期以来是 UX 设计的一部分——可能不足以构建 A/B 测试体系。比较团队的人口使得在分析中包括这种多样性成为可能。

组织级分析的前景

跨组织提供服务和平台的公司正坐在一个未开发的机会上,将设计组织过程的艺术变成一门实验科学。我们自己定量比较人群的经验揭示了组织级分析前景最明显的三个领域:利用参与用户生态系统的分布式影响,工程有效的团队文化,以及破解设计组织结构和流程的代码。

工程合作团队文化。

组织文化一直是区分成功组织和明显相同的失败组织的“秘方”。在数据科学的传说中,文化也扮演了“活动扳手”的角色,讲述了数据没有切中要害的量子方的故事。但是,通过让我们同时对群体进行详细和大规模的比较,组织级分析将文化问题纳入了数据科学的范畴。谷歌的项目 Aristotle ,研究了 180 个内部团队,进行了数百次采访,分析了超过 250 种不同的团队属性,得出的结论是强调团队规范的重要性——与明星球员相反——以形成成功的工作团队。

利用同行制作和粉丝的分布式影响

对于品牌来说,粉丝是一种神秘的力量,强大得不可思议,也难以捕捉。Spotify 将有关收听模式的数据整合到一种组织规模的方法中,以帮助音乐家和他们的粉丝社区建立更好的关系。在众包时代,组织越来越善于与客户围绕一系列产品或服务自发创建的社区合作。然而,建立成功的社区更像是一门艺术,而不是一门科学,并且将会一直如此,直到这样的社区可以在组织级别上被定量研究。

组织结构和流程

在 20 世纪 60 年代和 70 年代,组织理论被权变理论所主导,权变理论认为一个组织的相对高度或扁平程度取决于其行业的稳定性。但即使在这一传统下研究了十年之后,研究人员还是连续发表论文,用同样的方法测试同样的基本问题,却得出相反的结论。

关于如何最好地构建一个部门,如何使你的组织适应增长和变化,以及你的组织结构图如何堆叠,现在有几十年的知识,但从未得到适当的检验。除了组织规模的分析,没有什么能像科学家每天对个人的实验研究那样严格地检验这些组织理论。

让组织级分析发挥作用

如果你在一家为大众服务的数据驱动型公司工作,无论是初创企业还是主要参与者,你都可以遵循一些步骤来扩展你的分析,以比较组织。

1)从组织的角度思考

组织级分析要求我们从根本上改变如何让数据变得有用,更少地作为优化用户体验的工具,而更多地作为优化集体的工具。站在个人用户的角度思考很有诱惑力,因为用户是最接近产品的代理人。因此,优步可以 A/B 测试个别司机,但如果它想了解整个市场,它应该在市场规模上提出问题。这并不意味着放弃个人规模的分析:通过建立现有的分析能力,您的公司可以同时在个人和团队层面进行测试。

2)利用您已经拥有的数据

当通过组织级分析的镜头观察时,你会发现你拥有的大部分数据已经是组织级的了。利用它,让它成长。例如,通过激励客户以结构化的形式如实报告关键变量,平台可以将自己置于战略地位,以最小的成本和侵入性实施组织规模的实验。您的组织已经在使用的许多社交和组织平台可以帮助您轻松记录组织规模的度量。如果您的平台正在为您的客户提供基本服务,那么您就有必要的基本数据来找到有意义的组织级变量进行优化。

3)与你的客户合作

组织级的查询需要平台和客户之间的良好关系。客户对感觉像实验室里的小白鼠很敏感,获得他们同意的最常见策略——将同意隐藏在迷宫般的服务条款中——不再管用了。我们推荐四种策略,以便从将参与您的组织级研究的组织处获得早期认同:

  • 通过确保测试中使用的所有数据都以可操作的形式反馈给客户来提供价值,例如分析仪表板或个性化功能。
  • 通过明确你的测试基于哪些数据,将隐私和知识产权问题扼杀在萌芽状态。也要清楚地表明,测试文化是你的产品优于竞争对手的部分原因。你的客户应该知道,通过参与实验,他们受益于对组织流程设计的新数据驱动的见解的实时反馈。
  • 如果组织认为在测试条件下新的特性可以更好地服务于它,那么它不会自愿处于你的实验的“无效”控制条件下。追求更大利益的诉求最有可能落空。但是,通过同时在多个实验中招募组织,这样他们总是在相同数量的治疗和控制组中,他们可以确保你的软件没有随机分配他们的竞争对手一个优势。
  • 为了适应最严重的问题,允许组织选择退出实验。从技术上来说,选择退出会引入选择偏差,但是少量的选择退出不太可能破坏你的发现。

4)真正的实验,或者仅次于现实的东西

实验是因果推理的黄金标准。但是在进行一项好的研究的令人望而却步的困难和它的解释力之间有着深刻的联系。实验是有意义的,因为它们是受控的,而组织规模的控制是棘手的。互联网经常给我们这种对环境的控制,但是,最终,不是所有的问题在技术上,实践上,甚至道德上都可以用实验方法来回答。2014 年,脸书面临了几个公关噩梦中的第一个噩梦,当时他们进行的一项大规模实验被解读为暗示脸书有意操纵其用户的情绪。此后,该公司通过投资于被动因果推理技术的研究进行了调整,这种技术允许在没有真正的实验操纵所伴随的争议和误解的情况下进行推理。自然实验、匹配方法、工具变量、中介分析、认知建模和有向图学习都是可以用来处理因果洞察的技术,而没有真正干预可能带来的公共关系、法律或伦理问题。学术数据科学家是这个领域的理想伙伴。因为他们习惯于处理他们无法控制的数据——历史档案、“便利”数据集和数字足迹——他们在被动因果推断方法方面有几十年的经验。这一领先优势使得学术界在组织级研究的设计和分析中成为越来越有吸引力的合作伙伴。

当然,组织级分析的成功有几个潜在的陷阱。与普通测试一样,组织级 A/B 测试既昂贵又复杂,每项研究都需要公司内多个利益相关方的协调和签署。组织规模的研究也很难保持观察之间的独立性:如果参与的组织可以在不同的测试条件下比较笔记,那么你的实验就是有污点的。客户可能还会发现,因果研究对隐私的侵犯更大,即使它们依赖的数据与严格的观察研究相同。幸运的是,通过深思熟虑的设计和规划,以及对前任错误的充分关注,组织级分析可以让你获得真正变革性的见解。

结论

像 Salesforce、Google 和 IBM 这样的企业平台;有大量投资组合的风险投资公司;甚至像 Trello 和 Basecamp 这样的小众应用程序现在也可以将组织带入实验室,就像心理学家招募个人一样。在这种环境下,数据分析师将开始设计有效的流程,甚至可靠的充满活力的文化。在这样做的过程中,他们跟随了经济学、社会学、人类学、组织科学和心理学中计算驱动的学者的领导,这些学者很久以前就发现了大数据集在对大量人口进行定量比较研究方面的力量。

从范围来看,组织级分析的巨大潜力显而易见。展望未来,这种方法不仅适用于谷歌和脸书,也适用于初创企业、年轻经理、创意学者,甚至社区组织者。如果大学里所有学生团体的随机一半,列表服务器上的邮件列表,Reddit 上的子编辑,网络上的无线路由器,或者一个州的县协调起来尝试一种组织规模的方法来了解他们自己,会怎么样?如今,组织级分析取得更大成功的最大障碍是我们自己的创造力。当平台拥抱组织级分析的力量时,它们不仅会改善 20 世纪的组织流程,还会加快实验和完善新的网络驱动形式的步伐,这些形式将商业、政治、文化和教育带入未来。

作者

  • 塞思·弗雷 ,加州大学戴维斯分校&纽科姆计算科学研究所,达特茅斯学院( 推特 网页 )
  • 西蒙·迪德奥 、卡耐基·梅隆大学&圣达菲研究所( 推特 网页 )
  • 、加州大学戴维斯分校( 推特 网页 )
  • 阿比盖尔·雅各布 ,密歇根大学安阿伯分校( 推特 网页 )
  • Ceren Budak,密歇根大学安阿伯分校(Twitterweb)**
  • 克拉克·伯尼尔 ,普林斯顿大学(webLinkedIn)**
  • 罗斯塔法赞 ,匹兹堡大学( 推特 网页 )
  • 赛弗萨维奇 ,西弗吉尼亚大学( 推特 网页 )
  • 本杰明·樱井真子希尔 ,华盛顿大学 推特 网页 )
  • 伦肖 、西北大学( 推特 网页 )
  • 马腾 Bos Snap Inc .(LinkedInTwitter)**

作者要感谢达特茅斯学院的 William H. Neukom 计算科学研究所,他们对 反地球科学 研讨会的慷慨支持使这一合作成为可能。图片来自 设计迈阿密的未建 。来自 Flaticon.com 弗里皮克的 Nikita Golubev 的图解元素。大部分作者都在招研究生。

组织 Zoopla 黑客日

原文:https://towardsdatascience.com/organising-the-zoopla-hack-days-6d7f25e4e763?source=collection_archive---------14-----------------------

Zoopla 刚刚成功举办了为期两天的黑客马拉松,这一切都始于 3 个人和一个梦想。如果我们有时间研究一些自己的想法,展示 Zoopla 最大的资产——在 Zoopla 工作的人才——的创新潜力,那该多好啊!这是我个人对黑客日组织的看法。

3 people and a dream: from the right Matthew Chubb (Software Engineer), Jyoti Goyal (Senior Product Manager) and me (Data Science).

我们必须达到的第一个里程碑是高层领导的认同。如果你想从日常工作中抽出整整两个工作日,这对任何公司来说都不是一项微不足道的投资。Zoopla 正朝着成为第一的挑战性目标努力。我们不能只接受黑客马拉松的想法,而是要有一个令人信服的理由让它继续下去。

在一系列的午餐会议上,我们集思广益,讨论是什么激励人们参与黑客日。但同样重要的是,公司希望我们从 2 天的黑客马拉松中获得什么。这引出了一些难题:是否应该有一个主题?我们应该策划多少活动?精心策划的主题选择确实有助于准备和设置,但最初的动机难道不是让创新和创造力远离优先的积压工作吗?

最终,我们同意关注公司文化,而不是围绕主题和话题的细节,以获得高层领导的认同。所以我们的黑客马拉松有一个目标:加强 Zoopla 文化!Zoopla 是一个不断增长的业务,我们大多数人在单个产品团队中都非常关注产品。举例来说,在这样的环境中,与其他团队保持联系,让新的新手感觉融入得很好并不容易。但是文化对 Zoopla 来说是非常重要的,文化得到了高层领导的认可,让我们或多或少得到了官方的认可。文化对于数据科学团队的成功和交付也是至关重要的。

对文化的关注是一个完美的双赢局面!因为文化早餐吃策略。

然而,我们知道我们只是推迟了围绕黑客日主题和话题的必然决定。但随着计划的进行,我们可以选择让 Zoopla 的人提交想法,并找到一个更民主的解决方案。可惜没那么简单。这需要参与,到目前为止没有人听说过我们的黑客马拉松,也没有理由对此感到兴奋。

不要低估我们所有人的怀疑精神,尤其是在我们忙碌的时候。

为了增加参与度和成功的机会,黑客马拉松需要专业的身份以及围绕主题和话题的细节。与此同时,我们三个开始意识到组织这次黑客马拉松会有多少工作量。我们必须开始授权。

代表,代表,代表!

Heldiney Pereira(UI 设计师)给了我们一些急需的润色:电子邮件模板、徽标和背景。

当我们开始在所有渠道发送黑客日通信时——从面对面的讨论,到站立式收购,电子邮件和 slack 频道——话题和主题的想法开始出现。

事实证明,我们太担心主题的选择和策划了。提交的材料中很快出现了共同的主题,大多数主题都与业务高度相关。在我们花了一些时间对主题进行分组和提炼之后,我们又回到了委派!

我们为每个主题确定了主持人,负责推动该主题的参与,并确定必要的设置和准备工作。如果没有我们热情的主持人的帮助,我们根本无法举办黑客马拉松。

我们把海报和宣传材料放在一起,让人们注册一个主题。这是一个很好的成功指标,用来衡量我们在推动参与度方面的努力。

创造持久的兴奋和参与比你想象的更难。

有了这个方法,我们开始组织黑客马拉松的细节,天哪,这是一个做不完的事情的列表:

  • 与设施团队合作,为黑客马拉松寻找场地
  • 预算规划和批准
  • 活动的食物和饮料必须符合饮食要求和 Zoopla 的不使用一次性塑料的政策
  • 黑客时代的社交活动
  • 黑客马拉松演示
  • 奖项、投票和价格
  • 出于公关和营销目的的内容捕获
  • 如何联系我们的远程办公室
  • 获得直线经理的认可和批准,让员工参加
  • 批准,以便我们的承包商能够参加

根据反馈,我们决定黑客马拉松项目的市场风格展示将是最动态和最吸引人的形式。我们想参加演示,这也是对我们主管时间的最好利用。

没有被幻灯片压死!

不管有多少计划,有很多事情留到最后一分钟,这造成了一些麻烦:我们订购的奖杯不是我们收到的奖杯,修复它确实非常接近。参加黑客日、发布会和颁奖典礼的人数比计划的要多。这导致了一些最后时刻的设置挑战,当人们参加黑客马拉松演讲时,用玩具剪刀剪下了额外的 100 多张投票卡,并且因为团队规模更大而耗尽了奖杯。我们从活动策划的利润规模中学到了宝贵的经验!😄

最后,黑客马拉松取得了巨大的成功,这使得所有的工作都是值得的!

数据科学研究的是什么?厨房!

一个由数据科学家、后端和前端工程师组成的跨职能团队开始寻找 Zoopla 最美的厨房。目的是按厨房对 Zoopla 上的房产列表进行排序,并根据厨房的相似性推荐房产。这是一个有趣的话题,既有很大的数据科学挑战,也有很大的商业相关性:厨房很容易成为想买新房的人的绊脚石。

为了提供全功能的概念验证,团队创建了:

  • CNN 对厨房图像进行分类
  • 厨房图像的数字指纹
  • 提取厨房特征,如镀铬水龙头、抽油烟机等。
  • 计算厨房特征之间的 jaccard 相似性和图像指纹之间的余弦相似性,以将它们组合成厨房相似性得分
  • 提前对 Zoopla 属性列表进行批量评分,并将标签和评分加载到快速缓存层,该层充当模型的表示层
  • 创建一个 API 来查询厨房,并返回相似厨房的属性列表和图像
  • 更改 Zoopla 前端,动态显示按照厨房相似性分数排序的厨房和房产列表

之所以能够在短短 2 天内实现这一目标,是因为该解决方案建立在我们数据科学团队去年创建的计算机视觉和基础架构基础之上。然而,这并不是一件容易的事并且为这个项目赢得了黑客马拉松最聪明黑客奖

Natalia Koupanou 和 Harpal Sahota 因在 Zoopla 上制作的数据科学获奖而获得巨大荣誉!😄

Jan 是公司数据转型方面的成功思想领袖和顾问,拥有将数据科学大规模应用于商业生产的记录。他最近被 dataIQ 评为英国 100 位最具影响力的数据和分析从业者之一。

****在 LinkedIn 上连接:https://www.linkedin.com/in/janteichmann/

****阅读其他文章:【https://medium.com/@jan.teichmann】T21

组织网络分析——初学者指南

原文:https://towardsdatascience.com/organizational-network-analysis-a-beginners-guide-324d21322ed2?source=collection_archive---------21-----------------------

许多人都在谈论它,但没有多少人在这个领域做过实际的项目。一个更大的团队刚刚开始研究组织网络分析,简称 ONA。当你对 ONA 感兴趣时,你可能已经知道它是什么了。简而言之,ONA 研究的是正式组织中的沟通和其他网络。在这篇文章中,我会给你一些指导和提示,告诉你在开始你的第一个 ONA 项目时应该关注什么。

Photo by Omar Flores on Unsplash

当你在做 ONA 项目时,有四个主要方面需要考虑。这些领域也与人员分析和机器学习项目相关,但由于 ONA 的性质,有些领域与您项目的成功更相关。

根据我的经验,有四个主要的障碍。第一个是没有明确的目标,第二个是 ONA 使用的数据的定义和可用性。法律和伦理话题也在这个列表中,这并不奇怪。最后一点,也是与其他项目最大的不同,是与你的主要利益相关者和研究对象的沟通。

没有一个目标或宗旨,“做 ONA”是没有意义的

这与分析领域的任何项目都没有什么不同,但 ONA 面临的风险要大得多。你只能做错一次 ONA,所以你最好做对。最好的方法是选择一个你想要实现的明确目标。

专注于一个问题,深入研究,在你的项目团队中找一个有 ONA 经验的人,但是要确保你有商业头脑,并且找一个了解你的组织的人。

不要只是对数据提问,还要考虑你可能会用答案做什么。"我们的组织中有筒仓团队吗?"还不够,一旦你发现哪些团队在各自为政,就要清楚你会怎么做。一个例子可能是,你然后考虑这个团队的责任,以及你是否期望他们与某些其他团队一起工作。一旦你知道了这一点,你就可以跟进并促进不同团队之间的合作。

如果你不知道你想对 ONA 做什么,一个好主意是从你的企业价值观、战略或你正在执行的人力资源计划开始。

目标第一,数据和指标第二

许多公司将从收集数据开始,例如通过在 Microsoft Outlook 中收集数据。我鼓励你先设定目标。数据和度量可以跟在第二个后面。

整理数据,定义关系

一旦你的目标明确了,就该决定你想要观察的关系了。“在一个项目上一起工作”,或者“在过去的 3 个月里至少交换了 7 封电子邮件”。确定你的关系的定义,尤其是在使用被动收集的数据时,是极其重要的,它可以决定你的 ONA 的成败。准备在这上面花点时间。

根据您的目标,您还应该能够从数据中推导出可以获得的网络度量。如果你想找到桥梁建设者,你可以使用中间中心性。如果你想找到竖井团队,你可以使用社区检测算法。

让你的目标驱动指标和数据收集,而不是相反

现在,您已经定义了您的关系和您的网络指标,您可以推导出如何收集相关数据的几个选项。您可以通过电子邮件流量、电话、即时消息、日历条目、RFID 标签或调查数据来收集数据。

ONA 项目要求受试者选择加入或退出,受试者参加研究的比例要大,理想情况下超过 80%。为什么?因为你网络中的漏洞会严重扭曲结果。

整理好你的法律和道德观点

这不是可以等到项目结束后再做的事情。理想情况下,你的组织已经有了一个道德章程,如果没有的话,现在是建立一个的好时机。

ONA 对你的员工很敏感,所以要确保他们得到照顾。对于像 GDPR 这样的法规,最好让您的法律团队参与进来,并获得关于什么是可能的以及什么不是的建议。我鼓励你自己去理解法律和道德的含义,这样你就可以向任何询问的人解释这些。

不要只是顺从,在决定如何对待 ONA 时,要联系你的公司价值观

你可以问的一些问题是

  • 我的分析会影响到谁?
  • 分析如何正面或负面地影响受试者?
  • 问问你自己:这个分析对我个人有帮助吗?
  • 受试者应该匿名吗?

在大多数情况下,您将被要求对您的研究对象遵循选择加入或选择退出策略。这一点以及您是否希望匿名您的受试者将取决于您研究中使用的目标和数据。

交流,交流,交流

在他们成为你研究的对象之前,及时开始与他们交流。你需要受试者选择加入或退出,我们已经看到,理想情况下,我们需要至少 80%的参与率。在大多数研究中,如果沟通早且频繁,参与率会高得多。

沟通是 ONA 项目成功的关键

与你的主题积极互动,允许他们问你关于将要做什么的问题。对将要做的分析持开放态度,并确保目标对受试者是积极的。

当你想开始时,考虑这四点

获得明确的目标。然后定义关系和指标,得出您需要的数据。考虑法律和道德影响。尽早并经常与你的研究对象交流。

正确掌握这些要点,你将在“做 ONA”方面比大多数组织做得更好。需要帮助吗?通过 www.aibridge.ch/contact 联系我。

关于我:我是一名分析顾问,热衷于漂亮的网络图片、组织网络分析和有效的协作。 在这里报名我的快讯。

组织您的电子表格以进行数据分析和可视化

原文:https://towardsdatascience.com/organize-your-spreadsheets-for-data-analysis-and-visualization-b1985a31523a?source=collection_archive---------18-----------------------

Photo by Mika Baumeister on Unsplash

电子表格软件允许我们分析大量数据,以获得对流程或业务的新见解。我们的硬盘上都有大量充满数据的电子表格,但利用这些数据并不总是那么容易。主要原因是我们经常倾向于组织我们的电子表格来进行人工分析。

问题是,计算机和我们人类的思维方式不同。在这篇文章中,我会给你一些最佳实践来组织你的电子表格,以便用你最喜欢的电子表格软件进行数据分析和可视化,或者更好地,用外部工具,如数据工作室

维度和指标

Dimensions and Metrics (ruler by monkik on FlatIcon)

重要的是要明白,任何数据都可以分为维度指标。

度量 衡量,嗯,事情。指标始终是数字,可以使用 sum、average 等公式进行汇总。你有时也会碰到术语事实度量,它们是同义词

维度用于描述你的度量标准。维度可以是任何类型的数据,但通常是日期或一些文本(例如,颜色等属性,性别等类别)。).你有时也会碰到术语

维度值,维度包含的数据,是一个类别的名称、描述或其他特征(如颜色维度:红、蓝、黄)。

好的电子表格设计是关于以一种方式存储你的维度和指标,这种方式将允许容易地过滤和透视你的维度,并且容易地聚集你的指标。

取消打印您的电子表格

在研究如何存储数据之前,让我们先来看看电子表格的组织。通过自动化工具进行数据分析的设计不同于将一些图表分享给你最喜欢的市场部同事。

Step 1 : unpretty your spreadsheets

  • 移除合并的单元格:合并的单元格不能在 pivot 中使用,并且不受外部工具的支持
  • 删除多行标题
  • 删除标题、格式、文件版本、日期和作者(使用文件历史和版本

凌乱的数据

现在让我们来看看存储数据的方式:

  • 每行必须代表一个未聚合的度量
  • 每个单元格只能包含一个维度或度量值
  • 每列必须有唯一的名称

Step 2 : Untidy your data (credit : Ethan P. White et al. in Ideas in Ecology and Evolution)

我们也很自然地倾向于存储已经转换的数据,因为这对我们正在做的事情来说是有意义的,或者它使我们免于一些重复的数据。然而,充分利用你的数据的关键是以最简单的方式存储未经处理的数据,也就是说不经过处理。

如果你不确定这是什么意思,只要记住使用一个 每种尺寸和公制只使用一个 列。

在上面的例子中, HabitatXHabitatYHabitatZ 是同一维度的维度值:它们必须存储在同一列中。他们测量的东西,丰度,也必须存储在同一列中。在 unpivot 之后,我们能够在栖息地维度上进行过滤和透视,并聚合丰度指标,这在原始格式中是不可能的。

将源数据与分析分开

Step 3 : separate data from analysis

您应该在一个选项卡中保持原始源数据不变,然后在一个或几个其他选项卡中查看和分析原始数据。要从另一个选项卡导入数据,请使用以下 import 语句:

Import data from another tab

或者在公式中:

Import data from another tab in a formula

包裹

按照这些步骤,下面是我的示例表的转换:

当使用 pivot 函数时,我们会从这种透视维度是由隐含的列字母命名的情况中脱离出来:

这个更有意义的情况:

请注意自动化建议现在变得更有意义,以及我们如何在不同的选项卡中从分析中分离原始数据。

我们现在还能够按站点和 KPI 维度进行筛选和汇总,这在以前是不可能的:

更进一步,现在可以使用 Data Studio 等数据可视化工具对数据进行分析或公开。

感谢阅读!如果你喜欢这篇文章,不要犹豫,分享它。

我每天都在学习,如果我有任何错误,请随时纠正我,并在评论区添加您的建议。

使用 PLynx 组织数据科学实验

原文:https://towardsdatascience.com/organizing-data-driven-experiments-with-plynx-a3cc3301b981?source=collection_archive---------18-----------------------

“构建可再现数据科学工作流的简单方法”

持续改进、促进创新解决方案和理解复杂领域是数据科学家今天面临的挑战的重要组成部分。除此之外,他们还要处理各种工程问题,从数据收集和转换到部署和监控。工程师和数据科学家开发了各种工具和框架,以解决以可重复的方式进行数据实验的核心挑战。

事实证明,笔记本非常适合一次性分析。另一方面,在生产方面,他们有无数的缺陷。笔记本通常不可复制,不鼓励重用相同的代码,不支持开箱即用的并行化,不能很好地与版本控制工具一起工作,等等。与工程师类似,数据科学家设法使用现有的工具和良好的实践,如 Makefiles。他们描述计算图形,其中每一步都是一个脚本。用户仍然负责许多工程细节,比如云中的并行执行或者存储和访问数据。

其他数据科学家采用了通常数据工程师会使用的工具。例如,Apache Airflow 是一个非常流行的构建数据管道的框架。不幸的是,数据科学并不总是以同样的方式工作。高度可靠的执行没有尝试不同实验的灵活性和能力重要。在数据科学中使用可靠的数据管道可以带来增量改进,但是通常从其他活动中获得的好处要多得多,例如集成新的数据源或使用额外的工作流。

This is a machine learning pipeline in PLynx. Users can create their own experiments in UI as well in python using API. You can try this demo at plynx.com.

数据科学家应该做什么样的好平台?

一个构造良好的平台将数据科学家从工程和组织复杂性中抽象出来,如数据访问、容器化、分布式处理、自动故障转移和其他高级计算机科学概念。除了抽象之外,平台还将支持实验基础设施、自动化监控和警报、提供自动缩放,以及实现实验的可视化、调试输出和结果。

PLynx 的灵感来自几个非常成功的内部平台。

以太是微软在 Bing 团队开发的。我不能再多说什么了。微软首席执行官 Floydhub)说道:

相关性收益的成功和快速增长在很大程度上归功于一种叫做 AEther 的新工具的引入(除了改进 ML 技术和雇佣顶尖人才之外)。AEther 是一个构建和运行数据工作流的实验平台。它允许数据科学家以大规模并行的方式构建复杂的工作流和实验,同时抽象出所有的工程问题。我每天都用它,并且非常喜欢它。AEther 团队声称,它将研究人员和工程师的实验生产率提高了近 100 倍。即使是现在,当我问在其他公司工作的前 Bing 数据科学家他们在微软工作期间最怀念什么时,AEther 几乎总是在前三个答案中。

PLynx 的另一个灵感来源是 Yandex 开发的一个通用计算平台,名为 Nirvana。它的建立是出于为各种团队和需求扩展内部 ML 平台的需要。

实验

PLynx 中的实验表现为计算 。图表定义了实验的拓扑结构。单个操作的 输入 是其他操作的 输出 或称为文件的资源。PLynx 负责存储和访问工件,并以并行方式编排运行的作业,将它们从用户手中抽象出来。

The order of Operations is similar to Makefiles. In this example PLynx can execute Operation B and Operation C since their dependancies have completed. The results of Operations are cached and stored for reusability purpose by default.

你可以重用别人的成功实验,克隆它,在自己的实验中重用。它倾向于增加协作和对现有工具和算法的了解。随着时间的推移,随时可用的操作和子图池在不断增长。它鼓励人们以更加模块化和参数化的方式创建工作流,重用现有的解决方案。通过这种方式,他们不必多次重新发明现有的解决方案,并且可以利用缓存结果和分布式计算的优势。

您可以使用编辑器或 python API 从头开始创建图表。这是一个简单的拖放界面,用户将依赖关系定义为操作之间的数据。或者,用户可以选择使用 python API 来创建图形拓扑。使用 API 可能有多种原因:

  • 实际上,生产工作流倾向于转移到 API,而 UI 通常用于监控和实验目的。
  • 您希望使用各种超参数进行多个实验,这些超参数更容易在脚本中定义,而不是在 UI 中定义。
  • 实验的拓扑取决于超参数。
  • 您希望在 python 脚本中保留图形的结构,以便能够将其存储在现有的版本控制框架中。
  • 您可能希望定期或基于外部事件(如新数据可用)运行图表。

无论是哪种情况,在 PLynx 中都没有对错之分。实验的 UI 和 API 表示是相同的。

Example of a running experiment from the demo.

文件和操作

文件操作 是 PLynx 中的基本构建模块。用户使用 bash、python 脚本或其他插件定义自己的操作。

PLynx 主要是一个编排平台。它按照拓扑顺序执行操作。调度程序跟踪它们的状态和更新。当一个操作准备好被执行时,调度程序会把它放在全局队列中,一个工作人员将在那里提取它。

每个操作都处理抽象为文件的输入。输入有它们的类型,比如通用的文件jsoncsv 文件,或者更抽象的目录(遮光罩下存储为 zip 文件)云资源(存储为 json) 或者其他。在实践中,为了方便和鼓励良好的实践,定义类型是很重要的。其他用户需要看到您的操作消耗和产生了什么。输入也可以是可选的或是列表。每个输入有两个参数:minmax,都默认为1。如果min == 0,那么输入是可选的。如果max < 0那么操作可以消耗无限数量的文件。

参数 不构成图形的结构。用户定义自己的参数或使用系统参数。比如你可能需要number of iterationscommit hashactivation function等等。这些参数的值在很多编程语言中都很熟悉,比如整数字符串枚举整数列表等。此时,在系统参数中,支持以下参数:

  • cmd: Code —将要执行的代码。目前支持bashpython脚本。
  • cacheable: Bool —确定操作是否可缓存。例如,sort运算是确定性的,给定一定的输入会产生相同的输出。另一方面,Bash 命令date是不确定的。
  • _timeout: Int —执行操作所需的最长时间(分钟)。如果超时,工作人员将停止操作。

除了 输出 之外,操作以 日志 的形式产生非常重要的信息。用户可以查看stdoutstderrworker等标准日志。实时日志也是可用的,给比你flush他们及时。

操作执行

让我们来看看操作定义。您可以创建新操作,也可以从现有操作克隆。用户添加或删除自定义输入、参数和输出。不要忘记指定类型。

主要参数叫做cmd。它定义了操作的整个执行过程。来自 自定义属性 块的“基本节点”将解释输入、输出和参数。基本节点是插件。目前支持bash_jinja2commandpython插件,但它们可以扩展。

  • python node 将输入、输出和参数视为 python 对象。
  • bash_jinja2将使用 jinja2 模板框架替换cmd参数中的所有内容。
  • command将使用环境变量。

如果您不确定工人将如何解释操作,请点击“ 预览 ”按钮。

让我们看一个例子。我们希望创建一个操作来克隆一个 git 存储库,将其重置为给定的提交散列,并构建它。最后它会生成一个类型为“可执行文件的文件,这样我们就可以在其他操作中使用它。我们将使用bash_jinja2插件:

# stop execution of the script if one of the command failedset -e# create a custom directory and clone a git repo thereexport DIRECTORY=directorygit clone {{ param['repo'] }} $DIRECTORY# cd to the directory and reset it to a certain commitcd $DIRECTORYgit reset --hard {{ param['commit'] }}# execute “command”, such as “make” or “bazel build”bash -c '({{ param["command"] }})'# copy resulting artifact to a path PLynx expects to see the outputcp {{ param["artifact"] }} {{ output["exec"] }}

这个脚本本身在 bash 中是不可执行的。这就是为什么 PLynx Workerbash_jinja2会照顾占位符:

# stop execution of the script if one of the command failedset -e# create a custom directory and clone a git repo thereexport DIRECTORY=directorygit clone https://github.com/mbcrawfo/GenericMakefile.git $DIRECTORY# cd to the directory and reset it to a certain commitcd $DIRECTORYgit reset --hard d1ea112# execute “command”, such as “make” or “bazel build”bash -c '(cd cpp && make)'# copy resulting artifact to a path PLynx expects to see the outputcp cpp/bin/release/hello /tmp/7640dee8-4b87-11e9-b0b6-42010a8a0002/o_exec

这个脚本是一个有效的 bash 脚本。PLynx 还将负责下载输入和上传输出到存储器。

执行操作的工作线程的算法如下:

  • 轮询 直到它给工人分配新任务。
  • 创建一个临时目录,将其设置为工作目录
  • 准备输入:下载输入,将它们保存在工作目录中
  • 创建一个 bash 或 python 脚本,并用适当的名称和值替换占位符。
  • 执行脚本。
  • 上传输出和最终日志。

注意,一些输入和输出类型是可以抽象的。例如:

  • Type == Directory。PLynx 将创建输入和输出目录(与文件相对)。
  • Type == Cloud Storage。在这种情况下,文件本身是一个引用云目录的 json (路径在 s3google storage )。如果你想得到路径本身而不是 json,使用 T2。

应用和优势

PLynx 是用于分布式计算的高级域无关平台。它不受特定应用的限制,可以扩展到面向自定义数据的工作流和实验。下面是一些成功应用的例子:

  • 机器学习:数据准备、转换和实验管理。PLynx 以一种有组织和可重复的方式,在准备的任何步骤中加速测试新想法。由于框架的分布式本质,您不会受到单个运行实验的限制。您也可以随时重新运行整个实验。
  • 不断地重新训练模型。跟踪整个培训流程并能够随时重现非常重要。
  • 用新数据重新训练模型。随着新数据的出现,用户只需点击两下鼠标就可以重新训练现有模型。
  • 同时进行多项实验。数据科学家可以在有想法的时候马上进行实验。
  • 重用现有的操作和子图。自然,组织中的人需要相同的功能、过滤器、聚合器、转换、度量等等。随着时间的推移,操作池变得非常有表现力,数据科学家不再使用现有解决方案重复他们的工作。
  • 追踪实验。数据科学家经常回顾他们成功的实验,看看哪些想法行之有效。
  • 协作。像分布式计算、缓存、重用操作和监控工具这样的好特性鼓励人们使用单一平台。每个实验都被跟踪。
  • 比较不同的算法。PLynx 在改进你的模型方面非常有用,尤其是有一个基线。
  • 特别数据分析。用户可以重用现有操作来过滤、采样、连接和聚合大数据,而无需工程工作。根据您的基础设施,您可以使用抽象的操作来编写查询,这些操作将处理数据,而不考虑存储。例如joinfiltermap是可以在 SQL、MongoDB、BigQuery 等中完成的抽象。
  • 不需要领域专家来管理整个管道。非专业人员可以重新运行现有的。
  • 图表形式的实验很好解释。它可以被非专家或者其他团队的人使用。

包扎

PLynx 是一个开源平台,用于管理面向数据的工作流和实验。其核心特点是:

  • 可重复的实验。
  • 实验史。
  • 编辑器和监控工具。
  • 分布式计算。
  • 从用户那里提取技术细节。
  • 操作和图形的可重用性。

PLynx 是一个开源项目,你可以在https://github.com/khaxis/plynx找到代码。

我的组织分析使用 R

原文:https://towardsdatascience.com/organiztional-analysis-using-r-d4cb9ae531f5?source=collection_archive---------22-----------------------

我在一家维修店工作,该店使用 SAP 软件管理我们的维修零件、维修工作单和员工生产力。我对该软件的商业智能(BI)方面不感兴趣,所以我通过 csv 文件将我的数据上传到 Microsoft Azure 笔记本中,并使用带有 r 的简单算法执行我的分析。我的目标是从整体上观察组织。我从 SAP 软件中提取数据,分析直接人工和利用率,以了解整个组织的差异。现在有很多建立我的数据,所以它绝不是一个神奇的黑盒子。我正在使我的数据清理和收集过程变得更加干净。当我到了可以发布这个过程的时候,你可以在媒体上查看它。在那之前,让我们回到没有分析的轨道上来。

我将一步一步地完成我的过程。首先,我将数据存入一个 csv 文件。我得先清理一下数据。要关注我,请点击超链接进入 github 并检索我的文件。有一个自述文件、一个. pynb 文件和一个包含我的数据的 csv 文件。

你可以使用 rStudio,R via terminal,Azure Notebooks,或者任何你想部署 R 编程语言的方式。我现在使用 Azure 笔记本,这对我来说是新的,我正在利用免费使用的优势。我们手头的第一件事是上传数据。您将在 github 资源库中找到 csv 文件“edited_dl_July19.csv”。

p = read.csv("edited_dl_July19.csv")

接下来,我们将使用 head 命令查看文件的一部分。

head(p)

是的,一切看起来都很好。如果我们愿意,我们可以查看单个数据,但我喜欢查看具体的工作领域。我工作的维修车间分成几个部分。我把它们命名为 a 店、b 店、c 店、d 店、e 店和 I 店。每个单独的商店都有自己的主管,并在设施内发挥特殊作用。我寻找的是直接人工率和各商店的利用率。

接下来,我必须查看 R 正在查看什么类型的数据,并在必要时进行更改。

*# must use factor R thinks this is a integer*
class(p$shop)
class(p$utilization)

r 说商店是一个因素,利用率是数字。这就是我想要的,所以我们;我同意。在下面的代码中,我将通过运行方差分析来开始形成我的分析。方差分析也称为 ANOVA。ANOVA 是比较三个或更多变量组的平均值的规定方法。在我们进行分析时,我们会查看的零假设,以了解我们的观察结果是否存在显著的统计差异。在分析目标时间时,我们使用方差分析的 f 检验。我们查看与 f 检验相关的概率(p 值),以确定它是否大于阈值,对于 95%的置信水平,阈值≤ 0.05。

*# using block as a factor*
p1=aov(p$utilization ~ p$shop)# separate line or cell to summarize p1
summary(p1)

看这个我的 P 值小于 0.05,所以用数据有一定的统计学意义。为了进一步分析数据,我们知道数据中有问题。为了进一步分析这些数据,我使用了 TukeyHSD 命令,即 Tukey 的测试、Tukey 方法、Tukey 的诚实显著性测试或 Tukey 的 HSD 测试。从 Tukey 的 HSD 测试中检索的数据是单步多重比较程序和统计测试。在此分析中,它与 ANOVA 结合使用,以找出彼此显著不同的平均值。方差分析测试告诉我们,我们检索的日期有显著差异。Tukey 的 HSD 测试将向我们展示数据中出现差异的地方。

TukeyHSD(p1) 

我们来看看我们的直接劳动力比较,我们来看看 b-a 之间的显著性,它的 p 值小于 0.05,所以数据中有显著差异。我用这个来看商店是否在同一层。当我们看我们的视觉化图像时,我们可以看到不同之处。

接下来是利用率,我对利用率的操作与对直接人工的操作相同,只需将名称改为 Utilization,并将 p1 改为 p2。

p2=aov(p$direct_labor~p$shop)# I put this in a separate cell or line
summary(p2)

再次查看 p 值,数据中有统计学意义。

TukeyHSD(p2)

看看 c-a p 值和 c-d,肯定有什么事情发生了。

现在是可视化数据的时候了。对于这种分析,我发现箱线图是显示差异的最佳可视化工具。

boxplot(direct_labor ~ shop, data=p, main="Direct Labor July19", xlab="Shop", ylab="Direct Labor Hours")

boxplot(utilization ~ shop, data=p, main="Utilization July19", xlab="Shop", ylab="Utilization(percent)")

当我做分析的时候,我着眼于直接劳动的意义。我要看的是我们每个月在实际设备上实际工作了多少小时。如果我们看一下我们的直接人工箱线图,我们会发现 a 的平均工作时间不到 40 小时,也就是 35 小时。异常值表明某人实际上有 70 个直接人工小时。所以我们看一下直接人工和利用率图,看看有什么不同。这是组织中的专家能够分析数据并找出差异所在的地方。注:对于该组织,目标是利用率达到或超过 85%,目标是 90%。直接人工的目标是 55%或以上。

分析显示了子商店之间的统计差异。经过进一步调查,发现这是 7 月份。几个雇员出去度假了。此外,并不是所有的员工都在一天结束时正确填写他们的考勤单。由于未正确填写工时单,工时被计入工作单,从而缩短了可记录的直接人工工时。在我看来,这是一个很好的管理工具,可以评估和预测完成一项任务所需的工时。

单目三维物体检测中的方向估计

原文:https://towardsdatascience.com/orientation-estimation-in-monocular-3d-object-detection-f850ace91411?source=collection_archive---------8-----------------------

单目三维目标检测的任务是在 2D RGB 图像中围绕目标绘制三维定向包围盒。由于降低成本和增加模块化冗余的潜在前景,这项任务吸引了自动驾驶行业的大量兴趣。利用单个 2D 输入进行 3D 推理的任务是非常具有挑战性的,而对车辆方位的估计是实现这一重要任务的重要一步。

2D vs 3D object detection (source)

在单目 3D 对象检测中,文献中不断出现的一个重要概念是以自我为中心和以他人为中心的方向之间的差异。我最近向我的许多同事解释了这种差异,我认为这是一个写一篇关于这一点的简短博客的好时机。

请注意,这篇文章主要关注自动驾驶中的 3D 方向概念。如果你想知道定向回归的最新方法,请阅读我之前关于多模态目标回归的帖子,特别是关于定向回归的。

以自我为中心 vs 以他人为中心

自我中心和他者中心的概念来自于人类空间认知领域。然而,在自动驾驶的感知环境中,这些概念非常具体:自我中心取向意味着相对于摄像机的取向,而异中心取向是相对于物体的取向(,除自我车辆之外的车辆)。

车辆的自我中心定向有时被称为全局定向(或在 KITTI 中绕 Y 轴的旋转,如下所述),因为参考帧是相对于自我车辆的摄像机坐标系的,并且当感兴趣的物体从一个车辆移动到另一个车辆时不会改变。偏心方位有时被称为局部方位观察角度,因为参考框架随着感兴趣的对象而变化。对于每个物体,都有一个同心坐标系,并且同心坐标系中的一个轴与从相机发射到物体的光线对齐。

为了说明这个简单的想法,论文 FQNet ( 用于单目 3D 物体检测的深度拟合度评分网络,CVPR 2019)有一个很好的说明。

在(a)中,汽车的全局方向都面向右侧,但是当汽车从左侧移动到右侧时,局部方向和外观会发生变化。在(b)中,汽车的全局方向不同,但是相机坐标中的局部方向和外观保持不变。

Same egocentric orientation and allocentric orientation (source)

显而易见,单目图像中物体的外观只取决于局部方向,我们只能根据外观回归汽车的局部方向。另一个很好的例子来自 Deep3DBox 论文(使用深度学习和几何的 3D 边界框估计,CVPR 2017)。

A passing-by car has constant ego-centric orientation but changing allocentric orientation (source)

裁剪图像中的汽车旋转,而 3D 世界中的汽车方向是恒定的-沿着直线车道线。仅从左边的图像补丁,几乎不可能告诉汽车的全球方向。汽车在整个图像中的背景对于推断全球方位至关重要。另一方面,单独从图像补片可以完全恢复局部方向。

注意,按照 KITTI 的惯例,假设零滚转和零俯仰,方向简化为简单的偏航。因此,上述两种方位也被称为全局偏航局部偏航

将局部偏航转换为全局偏航

为了使用局部偏航来计算全局偏航,我们需要知道相机和物体之间的射线方向,这可以使用 2D 图像中物体的位置来计算。转换是一个简单的加法,如下图所示。

Global orientation θ and local orientation θ_l (source)

光线方向的角度可以使用边界框位置的关键点和相机的相机特性(主点和焦距)来获得。请注意,选择 2D 边界框的关键点有不同的选择。一些受欢迎的选择是:

  • 探测器盒的中心(可能被截断)
  • 模型框的中心(对于遮挡或截断的对象,具有猜测的扩展)
  • 3D 边界框在图像上的投影(可从激光雷达 3D 边界框地面实况获得)
  • 2D 包围盒的底部中心(通常假设在地面上)

底线是,除非车辆确实在附近或者被严重截断或遮挡,否则上述方法将产生大约 1 到 2 度的角度估计。

Estimation of ray angle (source)

凯蒂怎么说?

[## bostondiditeam/kitti

KITTI VISION 基准套件:对象基准# # Andreas Geiger Philip Lenz Raquel urta sun # # Karlsruhe…

github.com](https://github.com/bostondiditeam/kitti/blob/master/resources/devkit_object/readme.txt)

KITTI 数据集的 2D 对象检测地面真相为每个边界框提供了两个角度:

  • α:物体的观察角度,范围[-π..pi]
  • rotation_y:在相机坐标[-pi]中绕 Y 轴旋转 ry..pi]

上述两个角度分别对应于局部(偏心)偏航和全局(自我中心)偏航。这些值似乎来自基于激光雷达数据的 3D 边界框地面实况。这使得在 2D 图像上执行角度估计变得容易。

KITTI 有一个关于方向估计的官方度量:平均方向相似度(AOS) ,一个介于 0 和 1 之间的值,1 代表完美预测。我不会在这里详述度量标准,但它与平均精度的概念非常相似,细节可以在【KITTI 的原始论文中找到。

Definition of AOS

在文献中还有另一个由 3D RCNN 推广的度量,平均角度误差(AAE),定义如下。

Definition of AAE

外卖食品

  • 有可能从局部图像补片估计局部(绕中心)方向(偏航)。
  • 不可能从局部图像块估计全局(以自我为中心的)方向(偏航)。
  • 利用相机固有的(主点、焦距)和图像块的全局信息,可以将局部方向转换为全局方向。
  • 视点方向的回归是深度学习中最难的回归问题之一。参考我之前关于多模态目标回归的帖子。

我很快会写一篇关于单目 3D 物体检测的评论。敬请期待!

我们的 HackZurich 冒险——数据如何拯救道路上的生命

原文:https://towardsdatascience.com/our-hackzurich-adventure-how-data-can-save-lives-on-the-roads-2a2e27fbf915?source=collection_archive---------28-----------------------

现代世界不断提供刺激和干扰。我们的智能手机让我们保持联系,我们无时无刻不想同时处理多项任务,甚至在开车的时候!
这是一个严重的问题,对道路安全和司机的生命构成很大威胁。需要降低风险。但是怎么做呢?这是我们的团队在 Hack-Zurich 上面临的挑战。

Picture credit: Dafna Mordechai

千禧一代在行动——接受挑战!

去年九月,我参加了欧洲最大的黑客马拉松 HackZurich 。来自世界各地的数百名工程师聚集在一起,进行了 40 个小时的编码、吃比萨饼和不眠不休。黑客马拉松提供了 16 个不同的编码挑战。我们的团队 " 安全事宜 " ,选择应对由 Esri苏黎世保险提供的“千禧一代在移动”挑战。任务很明确——使用地理空间数据拯救道路上的生命。在这篇文章中,我将描述我们的数据驱动解决方案,它带领我们赢得了挑战。

数据数据数据

我们获得了 Brightbox Millennials 数据集,,其中包含了 1000 多名千禧一代司机的出行信息。使用安装在汽车上的专用硬件收集信息,每隔几秒钟对数据进行采样。
下面是主要特征: trip-ID,时间戳,城市,国家,车辆年份,年龄,经度,纬度,里程,速度,发动机转速

我们的解决方案—全面降低风险

我们的目标是全面降低风险;一方面,我们想处理基础设施因素,并提醒当局注意危险区域。 另一方面,我们希望解决人为因素,并实时生成 个性化警报 以帮助驾驶员,无论他们何时处于危险之中。

危险区域分类

第一项任务是确定危险区域,但我们如何定义危险区域呢?直觉是我们可以从驾驶员行为中了解该区域的风险水平。我们可以寻找危险或异常的驾驶员行为,如果我们确定了危险行为发生频率高的特定区域,我们可以将该区域归类为危险区域。为了验证我们的直觉,结果必须得到验证。因此,流程是:定义危险行为,扫描危险区域,并验证结果。

从信息到知识

我们决定关注的特性是时间戳、经度、纬度、速度。下图中,每个点都是一个数据样本。颜色代表速度,根据采样的经纬度定位圆点。虽然这是旅行的一个很好的可视化,但如果没有进一步的处理,数据就有些琐碎了。

The speed displayed on Esri’s GIS mapping software, for a single driver in a single trip and at a specific area.

由于原始数据不能告诉我们太多关于驾驶员行为的信息,我们用我们作为驾驶员的知识来定义什么是危险行为。我们检查了两个连续的数据样本——如果速度下降了 75%或更多,这个位置就被标记为警报。在下图中,你可以看到单个驾驶员的“警报集”,显示在 Esri 的 GIS 制图软件上。

An alarm-set of a single driver displayed on Esri’s GIS mapping software.

从知识到智慧

现在,当我们绘制了警报后,下一步是对警报进行聚类。如果一个集群跨越了一个阈值,该区域就被分类为危险区域。
下图显示了发生在一个交叉点上的一组警报。地图上的每个点都是一个警报,颜色区分司机。你可以看到一些司机在这个位置有两个警报,不一定来自同一个行程。

直觉好,验证更好!

我们希望验证我们的解决方案,所以我们使用了另一个数据集,即 2016 年的车祸数据。我们确实发现在我们的过程中识别为危险的区域和有事故记录的区域之间有很好的相关性。由于时间不够,这是手动完成的,而不是自动完成的。

Dangerous areas identification process.

使用这种方法,数据科学家可以测试不同的警报标准,甚至可以将其中一些标准组合起来,然后测试不同的警报聚类阈值,以产生更好的结果。

采取行动—现场演示

赋予当局价值

上面描述的区域分类过程是基于这样的假设,即大多数驾驶员在大多数乘坐中负责任地驾驶,并且以适合道路的方式驾驶。在这种假设下,突然刹车可能是由于与道路条件或驾驶员的视野等有关的原因造成的。当局可以得到一份被归类为危险区域的列表,并检查道路——有什么可以降低事故风险的吗?交通法适合视野吗?道路上的标志是否干净可见?

为司机创造价值

从司机的角度来看,最终目标是创建一个警报系统,根据该地区的风险水平,实时向司机发出音频通知。
使用分类过程的另一种方式是仅在特定驾驶员的数据上运行,产生一组基于驾驶员驾驶模式的个性化风险区域
此时,当我们同时拥有危险区域、一般危险区域和个性化危险区域时,我们可以使用它们来为每个区域指定安全级别,并在进入该区域前发出“危险区域”音频警报。通过考虑诸如车速、天气、一天中的时间等其他变量,可以更好地调整警报。
希望定期使用为驾驶员和道路量身定制的系统,可以提高对道路不断变化的状况的认识,并帮助驾驶员采取更负责任的驾驶习惯。

虽然演示看起来像一个移动应用程序,但我们的愿景是将该解决方案嵌入到汽车中。我们不想定义一个解决方案,它本身是另一个分散注意力的原因。

我们能利用这些数据做更多的事情吗?是的,我们可以!

还可以用这些数据做些什么来降低危险区域的风险?
速度是直接从汽车上采样的,而不是从坐标和时间戳中推导出来的,这一事实非常有力。这些信息使我们能够创建一个危险区域道路平均速度的热图。
在下图中,你可以看到这样的热图,仅基于千禧一代的数据集,没有任何其他绘图工具。与真实地图相比,您可以看到道路的描绘有多精确。这种对道路的进一步分析可以对驾驶员和当局有所帮助。

****从当局的角度来看,有了这种工具,交通管制可以更有经验地进行,依靠数据,并导致交通法规的优化。例如,道路交通当局可以根据该区域的实际驾驶模式来调整限制速度,而不是依赖于用于设置速度限制的试探法。

检查下图中的交叉点:当从南方进入交叉点时,热点图上的颜色从黄色变为红色。即平均速度从大约 80 Km/h 下降到小于大约 40k m/h。
限制路口前的速度,或添加指示前方有路口的标志,这是两种可能的解决方案,可以让驾驶员安全减速,并防止突然刹车。

Heatmap of the average speed at a specific junction.

****从驾驶员的角度来看,该信息可以集成到上述的警报系统中,并给出另一种类型的警报。汽车的当前速度可以实时与热图进行比较,如果平均速度和当前速度之间的差异超过阈值,司机将收到音频“高速”警报。这种警报将在驾驶员能够感觉到威胁之前发出潜在危险的信号,并有望防止事故发生。

请注意,速度阈值是可以根据各种因素(例如当前天气、道路上的临时建筑)或其他个人因素(例如驾驶员的年龄、驾驶员的驾驶经验或驾驶员对道路的熟悉程度(根据驾驶历史记录))动态改变的变量。

我很好奇…

当我们创建我们的 hackathon pitch 演示时,在本文的图和地图中看到的 Witcham 附近的交叉点是随机选择的。这不是一个有重大警报的路口。尽管如此,当我写这篇博文时,我还是很好奇想看看实际的道路。

An image of the junction, taken from Google Maps.

查看谷歌地图上的路口显示一条开放的道路,尽头是一个三叉路口。限制限速的标志就在十字路口。这可能是在交叉口和标志可见的地方遇到中断,而不是更慢地进入交叉口的原因。

完成的事项

我们的解决方案提出了一种使用简单且可访问的数据(如汽车 GPS 坐标和速度)来分类和分析危险区域的方法。该过程为当局提供了有价值的信息,当局可以利用这些信息来改善道路基础设施和优化交通法规。这对司机也很有帮助,因为他们可以根据这些信息实时获得个性化的音频警报。总而言之,这种解决方案是一种预防潜在事故和提高驾驶技能的整体方法。

简短的讨论

值得注意的是,数据集缺少关于 Driver-ID 的信息。当几个不同的司机使用同一辆车时,一次特定的旅行不能归因于一个而不是另一个。从技术上来说,旅行与交通工具有关,而与司机无关。
这些信息对我们的解决方案至关重要,因为警报是个性化的,是根据驾驶员的驾驶模式为他们量身定制的。尽管假设这些信息可以从数据中推断出来是合理的,但是面对黑客马拉松时间有限的事实,我们决定不这么做。此外,我们认为这种类型的信息应该是可靠的,因此可以明确地收集,而且做起来相当简单。
当驾驶员第一次使用该系统,并且没有关于其驾驶模式的足够数据时,这种识别是必不可少的。如果我们想要向系统添加配置文件,例如新的驾驶员配置文件,由于缺乏驾驶经验,警报阈值可能会降低,则也需要此信息。

安全事关我们

这个项目是数据科学家 Adi Goldenberg 、高级软件工程师 Dafna Mordechai 、算法开发人员 Noa Raindel 和数据科学研究员 Ortal Ashkenazi 通力合作的结果。
在这篇由苏黎士保险公司创新经理林文撰写的精彩文章中,你可以找到关于我们项目的更多信息。

HackZurich —接受挑战!

在最后一次 HackZurich 活动上,有来自 60 多个国家的 5500 多份申请!听起来很有趣?保存日期:hack Zurich 2019(9 月 27 日至 29 日)的申请将于 6 月 7 日开放。

** [## 哈克苏黎世

保存日期:hack Zurich(9 月 27 日至 29 日)的申请将于 6 月 7 日开放!

www.facebook.co](https://www.facebook.com/hackzurich/photos/p.2259379274105963/2259379274105963/?type=1&theater)**

我们的社会决定因素角色

原文:https://towardsdatascience.com/our-social-determinants-personas-353399250ed4?source=collection_archive---------18-----------------------

或者我们如何利用社会决定风险群体和一些奇特的数据科学建立一个超越行业的再入院模型。

数据科学@HF

社会决定因素分数重要吗?

上次我们写了使用机器学习来推断成员的社交需求的能力,以及验证我们方法的方式。在这里,我想谈谈我们构建的九个不同风险分值的分析值。在医疗保健领域,一个人病得有多严重的近似值是一个病人出院后回到医院。从医疗和政策的角度来看,这一点的重要性不能被夸大。因此,当我们在 analytics@hf 上构建模型特征时,我们开发的一个有用的启发是“X 预测再入院吗?”亲爱的读者,很高兴你问了这个问题。它实际上创造了一个

击败文献的再入院模型

我们建立了一个击败文献的模型,仅用我们的社会决定因素人物角色…我们用数据机器人在 20 分钟内完成了它。在这里,它是 xgBoosted 树的 glm 集成,具有早期停止、一些异常检测、具有 gini 重要性的随机森林、Vowpal 阶段式多项式特征分类器(但这并不重要)。多亏了数据机器人,我们在 20 分钟内完成了分析!

Permutation importance for our model — economics and issues regarding the justice system matter a lot for readmissions

Pretty good differentiation

除了漂亮的图表,关键是我甚至不需要其他功能来创建一个令人敬畏的重新接纳模型。事实上,当我添加我的 800 多列建模资产(我应该在上面写一篇博客)时,auc 攀升到 0.80,这绝对是值得做的工作,但是数据科学项目经理应该记住努力与回报。

我们的 9 个风险分数告诉了我们什么?

大概两件事。让我们看看相关矩阵:

We see a lot of the factors loading strongly on the first principal component..but clearly one isn’t enough

用眼睛做 PCA 的一个技巧,不要告诉你的统计老师,是根据特征值的角度来排序你的相关矩阵。

I see two clusters kind of, okay fine let’s look at the skree plot

Looks like 2 it is

使用 R 的 Psych 包的 PCA 函数中的标准正交变换,我们试图找出这 9 个分数背后的潜在因素。

我们发现了什么?我们看到两个真正的差异驱动因素(93%的差异由两个因素解释)。你可以提出一个案例,我们应该强制三个因素,给定住房环境负荷,两者相等,但我们没有得到更多的方差解释这样做。所以我们称潜在因素为 ' '社会情境’' 与工作相关。和它们说起来合乎逻辑。接下来,我们将使用组件分数来节省成本。

我们能为社会风险创建一个角色视图吗?

让我们用一个客户细分类型的分析来结束这个探索,只针对社会分数。根据差距统计方法,我们的数据中应该有 18 个集群(9 列 140 万行)。所以我对风险分数进行了 k-means 运算,并根据他们的风险分数总和写下了各组的名字。我还创建了一个严重性分数,以便业务部门可以知道优先考虑哪个群体,使用这些描述来连接社交服务,如 SNAPPATH 或食品仓库。我们目前正在使用这些分数来帮助我们的护理管理者通过一个名为 [NowPow](http://: http://www.nowpow.com/) 的社交联系平台将会员与这些类型的资源联系起来。

Here’s a far too confusing view of our clusters, nonetheless, it’s the chart everyone shows 😃

Here’s an easier to digest view of the clusters with some simplistic name scheme. I also developed a rank order severity based on the average risk score per group, for prioritization

这是我们可以与决策者和临床医生分享的事情,以帮助他们优先考虑哪些成员需要哪种类型的社会支持。我们的大多数成员在大多数分数上都是低风险的。最终目标是清晰地了解风险水平、干预评分和推荐计划,以帮助会员获得有助于他们过上更健康、更安全和更稳定生活的服务。

包装完毕

因此,我们了解到两件事,通过将社会风险评分纳入健康结果模型,可以获得行业领先的预测结果。在描述社会风险时,我们有两到三个潜在因素,我们可以用它们来创建人物角色,以便进行更有针对性的干预。

最后要讨论的一件事…为什么大家不就这么做?我会在以后的文章中写更多,但是为了创建所有这些,我使用了 Python、R、Tableau、Excel、DataRobot 和最重要的 snipping 工具。没有完美的方案,也没有一种美味的汤,只要尽可能快、尽可能有说服力地完成工作就行了。在经济学家的边际曲线上交易的两个变量(速度和故事的完整性);你作为分析师的价值在于你在曲线上的位置。

离群点检测:Spark ETL 教程

原文:https://towardsdatascience.com/outlier-detection-an-etl-tutorial-with-spark-f4197eb84a7b?source=collection_archive---------9-----------------------

工业 4.0 框架的一部分是确保制造商对他们在工厂车间的机器有更多的可见性。这也是工业 4.0 与物联网紧密结合的原因。物联网允许从安装在生产设备中的传感器收集大规模实时数据。然而,仅有好的数据收集代理是不够的。我们需要一种自动化的方式从大量的数据流中提取、分析和总结信息,因为人类不可能手动完成这些工作。在大数据术语中,这个过程通常被称为 ETL (提取-转换-加载)。

今天,我们将讨论一个我个人认为在行业中有用的算法家族:异常值检测。想法是从数据流中发现任何异常测量,并向领域专家(如过程工程师)突出显示它们。我将在 Spark 中分享一个基本异常检测算法的实现。我本来可以用 python 的 pandas-dataframe 做同样的教程,但不幸的是,一旦我们处理大数据集(其大小远远大于内存空间),后者就不再合适了。

在这篇文章中,我将使用 scala 作为我选择的编程语言。我个人在为生产写代码的时候喜欢用 scala。Python 写起来更快,因此对原型开发很有用。然而,它缺乏静态类型可能会使事情更难调试。另一方面,scala 更类似于 Java,尽管不那么冗长(它也运行在 JVM 上)。但是让我们把这个赞成和反对的辩论留到另一个会议。

这是我使用的一个简单的虚拟数据集。假设我们有来自 2 个传感器的数据流。我们如何自动捕捉下面出现的两个异常点?

Dataset

离群点检测

我们使用的模型找到了在符合观察数据的分布下出现概率低的值的区域。我们假设传感器本质上是单峰高斯型的。这样,我们就可以计算出两个阈值,这两个阈值与分布的平均值相差 6σ。

视觉上,阈值以这种方式拟合。任何高于上限(约 25)或低于下限(约 15)的测量值都被视为异常值。

The Upper and Lower Outlier Thresholds

现在,为了在 Spark 中实现这一点,我们首先导入所有的库依赖项。

**import** org.apache.spark.sql.{Column, SQLContext}
**import** org.apache.spark.{SparkConf, SparkContext}
**import** org.apache.spark.sql.types._
**import** org.apache.spark.sql.functions._

我们需要用一个主函数将所有的函数包装在一个对象中(这可能会让你想起 Java)。我们实际上可以用不同的风格来写,看起来更像一个脚本。Scala 有一个名为 REPL 的解释器,允许程序员逐行执行代码。然而,在生产中,以这种方式组织事情是有好处的。

*/**
  * Sample Anomaly Detection with Spark
  */* **object** AnomalyDetection {
    **def** main(args: Array[String]): Unit = {
      // the rest of the functions go here
    }
}

现在,如果你在 Windows 中运行 spark,你可能会遇到一些异常,说程序无法找到 winutil 二进制文件。在这种情况下,您需要下载 winutils.exe(这个是如何做的)并在您的代码中设置以下系统属性。

System.*setProperty*("hadoop.home.dir", "C:/winutil/")

接下来,我们需要配置 spark、sparkContext 和 sqlContext。如果我们将 HBase (一个 NoSQL 数据库)与 ZooKeeper 一起使用,我们将需要配置 spark.hbase.host 参数来指向相应的主机地址。

*/** Configure Spark */* **val** conf = **new** SparkConf()
  .setAppName("anomalyDetection")
  .setMaster("local[8]")
conf.set("spark.hbase.host", "zookeeper.default.svc.cluster.local")

**val** sc = **new** SparkContext(conf)
sc.setLogLevel("WARN")
**val** sqlContext = **new** SQLContext(sc)

提取

我们现在假设我们的数据是 csv 格式的。它也被保存在一个名为 test.csv 的文件中。我们首先明确指定数据模式。注意,在生产中,数据也可以从数据库和消息代理(例如 MQTT、Kafka 等)获得。

*/** read csv */* **val** customSchema = StructType(*Array*(
  *StructField*("sensorId", StringType, **true**),
  *StructField*("values", DoubleType, **true**))
)

然后,我们将 csv 文件读入 Spark 数据帧。这里我们可以看到只有两列:sensorId 和值。

// load dataset
**val** df = sqlContext.read
  .format("com.databricks.spark.csv")
  .option("header", "true")
  .schema(customSchema)
  .load("test.csv")
df.printSchema()

root
|—sensorId:string(nullable = true)
|—values:double(nullable = true)

改变

我们希望计算每个 sensorID 的分布轮廓,特别是异常值的上限和下限。为此,我们需要按 sensorId 对数据帧进行分组,然后相应地汇总每个传感器数据的平均值和标准差。然后,我们可以创建 2 个新列,每个异常阈值一列。

// calculate statistics
**val** statsDF = df
  .groupBy("sensorId")
  .agg(*mean*("values").as("mean"), *stddev*("values").as("stddev"))
  .withColumn("UpperLimit", *col*("mean") + *col*("stddev")*3)
  .withColumn("LowerLimit", *col*("mean") - *col*("stddev")*3)
statsDF.printSchema()

root
|—sensorId:string(nullable = true)
|—mean:double(nullable = true)
|—stddev:double(nullable = false)
|—upper limit:double(nullable = true)
|—lower limit:double(nullable = true)

我们现在想找出原始数据帧中哪些传感器读数是异常的。由于信息存在于两个不同的数据帧中,我们需要使用 sensorId 列作为公共索引来连接它们。

// join the two dataframe
**val** joinDF = df.join(statsDF, usingColumns = *Seq*("sensorId"))

最后,我们可以过滤值超出离群阈值范围的行。瞧吧!我们设法捕捉到了两个异常点。

// outlierDetection
**val** detectOutlier = (values: Column, UpperLimit: Column, LowerLimit: Column) => {
  // outliers are points lying below LowerLimit or above upperLimit
  (values < LowerLimit) or (values > UpperLimit)
}
**val** outlierDF = joinDF
  .withColumn("isOutlier", detectOutlier(*col*("values"), *col*("UpperLimit"), *col*("LowerLimit")))
  .filter(*col*("isOutlier"))outlierDF.show()

Anomalous Rows

负荷

(可选)我们还可以将输出数据帧写入另一个表(或 csv 文件)以供进一步处理。这就完成了整个 ETL 过程。

outlierDF
  .repartition(1)
  .write.format("com.databricks.spark.csv")
  .save("result")

上面的方法输出一个名为 result 的文件夹,里面有以下文件。通常情况下,数据会被分割成多个 CSV(每个 CSV 都有不同的零件名称)。但是,由于我们已经将数据帧重新分区为 1,所有数据都收集到一个分区(或文件)中。

最后一步是关闭 sparkContext。

// close sparkContext
sc.stop()

排除故障

Spark 附带了一个 web 界面(默认情况下在 4040 端口),可以用来查看 ETL 过程是如何运行的。我发现这很有用,尤其是在识别瓶颈功能方面。

Example of Spark Web Interface in localhost:4040

结论

我们已经看到了一个典型的带有 Spark 的 ETL 管道是如何工作的,使用异常检测作为主要的转换过程。请注意,这里使用的一些程序不适合生产。例如,不鼓励 CSV 输入和输出。通常我们会使用 Hadoop 分布式文件系统(HDFS)。后者也可以包装在数据库下,例如 HBase。尽管如此,主要的编程范式保持不变。

Python 中 2D 特征空间的离群点检测

原文:https://towardsdatascience.com/outlier-detection-python-cd22e6a12098?source=collection_archive---------7-----------------------

Image by MasterTux from Pixabay

如何使用绘图和聚类技术检测异常值以分析两个特征的相关性

A 在鼓起你所有的勇气开始一个机器学习项目之后,你首先要想的是如何其中到实际上开始。下图显示了典型的机器学习工作流程。每个机器学习项目的最开始是收集和准备必要的数据,以便能够由那些花哨的算法处理,如神经网络支持向量机

ML Workflow” by Google Cloud is licensed under CC BY 4.0

除了为您的源数据集或工程使用的要素创建一些时髦的第一可视化,您还想检测您的数据集中是否有任何偷偷摸摸的异常值。

本文提供了一个逐步指导 如何检测两个特征(也称为属性或变量)之间的依赖关系中的异常值,也称为二维特征空间。

异常值检测—让我们开始吧!

这个项目是在 IDE PyCharm 中用项目解释器 Python 3.7 开发的。但是,您可以在任何其他环境或笔记本中自由应用该代码!完整的项目可以在 这里找到

#1 —可视化特征空间。

第一步是引入一些我们正在处理的特征空间的视觉效果。这个项目利用了与框架 scikit learn 一起提供的 wine 数据集

Drunk Amy Schumer” by BuzzFeed on GIPHY

我们可能不像艾米·舒默那样喜欢葡萄酒,但我们仍然认为葡萄酒是一个非常美味的研究对象。我们将检验的 2D 特征空间是类黄酮(一类代谢物)的浓度和葡萄酒的颜色强度之间的相关性。

以下代码提供了 2D 特征空间的初始可视化。

First visualization of the 2D feature space dependency

厉害!现在我们对正在处理的依赖性有了第一次“感觉”。

#2 —聚类数据点。

在我们的第一次可视化中,我们可能已经看到了一些聚类和异常值,但是为了给我们的直觉提供更多的统计基础,我们借助了聚类算法。 DBSCAN (基于密度的带噪声应用空间聚类)是一种常用于离群点检测的聚类算法。在这里,如果一个数据实例不属于任何集群,那么它被认为是离群值。

DBSCAN 算法需要两个参数—ε,其指定点应该彼此多接近才能被认为是聚类的一部分;和 minPts ,它指定一个点应该有多少个邻居被包含到一个聚类中。”— 阿利图卡

通过调整模型的参数 epsilon 和 minPts(在 Python: min_samples 中),我们揭示了特征空间中一些不错的聚类。

以下代码聚类了 2D 特征空间。

将特征空间的第一可视化与聚类可视化进行比较

哦,是的,我们终于发现他们了!

Under Arrest Flirt” by Angie Tribeca on GIPHY

这些紫色的小点就是我们正在寻找的异常值

Clusters of the 2D feature space

#3 —计算异常值。

哇!!现在我们知道的确在黄酮类化合物的浓度和葡萄酒颜色强度的相关性中存在异常值,yaaay(顺便说一句,我仍然不知道黄酮类化合物是什么)。就差最后一步了…

以下代码计算 2D 特征空间的异常值。

这段代码计算并最终在一个单独的 CSV 文件 中打印出数据集的 11 个异常值。

这份离群点检测的逐步指南是我在关于人在回路计算的论文项目中创建的,这是一种将人类与机器智能相结合的方法。敬请期待!

Done Looney Tunes” by Heck Yeah Reaction GIFs on GIPHY

[1]谷歌云,机器学习工作流程 (2019)

[2] M. Ester,H.-P. Kriegel,J. Sander,X. Xu,一种基于密度的聚类发现算法(1996)1996 年第二届知识发现与数据挖掘国际会议论文集

基于扩展隔离森林的离群点检测

原文:https://towardsdatascience.com/outlier-detection-with-extended-isolation-forest-1e248a3fe97b?source=collection_archive---------1-----------------------

了解流行的离群点检测算法的最新改进

在我关于异常检测的第一篇文章发表半年后,它的一位读者让我注意到隔离森林算法最近有了改进,即扩展隔离森林(EIF ),它解决了原始方法的主要缺点。在这篇文章中,我简要回顾了最初的中频算法,描述了它的潜在问题以及 EIF 是如何处理的。最后,我将展示一个 Python 示例,展示如何使用这两种算法并比较它们的性能。

1.隔离森林

隔离森林算法利用了异常观测值很少并且与“正常”观测值显著不同的事实。该森林是在决策树的基础上构建的,每棵树都可以访问训练数据的子样本。为了在树中创建分支,首先选择一个随机特征。然后,为该特征选择一个随机分割值(在最小值和最大值之间)。如果给定的观察值具有该特征的较低值,则所选的观察值遵循左分支,否则遵循右分支。这个过程一直持续到孤立一个点或达到指定的最大深度。

Partitioning algorithm. Source: [1]

原则上,异常值比常规观测值更少出现,并且在值方面与常规观测值不同(在特征空间中,它们离常规观测值更远)。这就是为什么通过使用这种随机划分,它们应该被识别为更靠近树的根(更短的平均路径长度,即,观察在树中从根到终端节点必须经过的边的数量),需要更少的分裂。

异常分数是根据森林中的所有树木以及点在这些树木中到达的深度创建的。

2.隔离森林的问题

我认为理解这个问题的最好方法是把它看作一个例子。

Motivation for EIF. Source: [1]

在左图中,我们可以看到从多元正态分布中采样的数据。直觉上,我们假设分配给观察值的异常值将从分布[0,0]的中心点径向增加。然而,正如右图所示,事实显然并非如此。此外,还有得分较低的矩形伪影,例如 x 轴上 0 点和 1 点之间的垂直伪影。

让我们继续第二个例子。这里我们看到两个斑点集中在点[0,10]和[10,0]。通过检查右图,我们不仅看到了之前出现的伪像,还看到了两个重影簇(大约在[0,0]和[10,10])。

Motivation for EIF. Source: [1]

这种特殊行为的原因源于隔离林的决策边界要么是垂直的,要么是水平的(随机特征的随机值),如下图所示,作者绘制了 IF 在训练阶段生成的分支切割。我们看到分支倾向于聚集在大多数点所在的地方。但是由于线只能平行于轴,所以存在包含许多分支切割和仅一些或单个观察值的区域,这导致一些观察值的不正确异常分数。一个例子可能是围绕3,03,3的点。

Branch cuts generated during the training of IF. Source: [1]

3.扩展隔离林

对隔离林缺陷的分析得出结论,该问题仅由水平/垂直分支切割引起。扩展随机森林以稍微不同的方式解决了这个问题。不是选择一个随机特征,然后在它选择的数据范围内选择随机值:

  • 分支切割的随机坡度
  • 从训练数据的可用值范围中选择的随机截距

这些术语(斜率/截距)是您最有可能从简单线性回归( y = ax + b )中回忆起来的。让我们来看一个直观的例子!从下图中,我们可以看到与原始 IF 算法的主要区别- >不平行于轴的切割。

EIF Partitioning algorithm. Source: [1]

扩展的随机森林很好地推广到更高维度,这里我们处理的不是直线而是超平面。为了更深入地研究 N 维一般化,请参考[1]中一个非常平易近人的解释。

让我们通过观察由 IF/EIF 产生的异常分数图中的差异来总结理论解释。在下面的图像中,我们看到异常分数从数据集群呈放射状扩散,并且没有可见的伪影/重影集群。

EIF 捕捉到的一个额外特征是直接位于两个集群之间的较高异常分数区域(在那里它们有点联系)。这个区域可以被认为是接近“正常的”,因为它与两个集群都很接近,但是分数更高,因为它远离集中的群组。

4.Python 中的示例

数据

在这个简短的练习中,我使用了从这里下载的森林覆盖数据集。数据集包含 286048 个观测值和 10 个要素。观察值被标记,所以我们知道哪些是异常的(0.9%的观察值是异常的)。

比较的另一个方面可以是速度,因为[1]的作者指出,在扩展隔离森林中速度没有(显著)下降。

sklearn中的隔离林

在所有型号中,我将尝试使用相同的设置,即:

  • 森林中的树木数量= 100
  • 为估计每棵树抽取的最大样本数= 256
  • 我预先知道数据集中有 0.9%的异常,我将使用这个百分比来选择最高的异常分数

森林能够正确识别数据集中 8.7%的异常。

Performance of sklearn’s IF

eif中的隔离林

通过设置ExtensionLevel为 0,我估计一个正常的隔离森林。关于这个实现的一些话。首先,到目前为止,还没有为模型设置随机状态的方法,所以多次运行它可能会产生不同的结果。另外,eif实现没有那么多参数需要配置。

另一件事是,该模型预测异常得分,但不会自动识别哪些观察值被视为异常值。为了识别异常,我对异常分数进行排序,并检索分数最高的 0.9%的观察值的指数。

Performance of eif’s IF

这种隔离林实现的性能比sklearn的要差。它只能捕获数据集中 6.3%的异常。此外,由于每次运行该模型时缺少随机状态,性能会发生变化。

eif的扩展隔离森林

这部分非常类似于香草隔离林案例(eif实现),不同之处在于ExtensionLevel。为了在完全扩展的级别上工作,我将级别设置为 9(维数- 1)。

从结果中可以看出,该模型未能识别数据集中的单个异常。不幸的是,我对此没有任何解释,如果有人知道这个问题可能是什么,请在评论中告诉我,我会更新这个帖子。

Performance of EIF

结论

扩展隔离森林算法当然很有趣,值得进一步探索。它很容易地克服了原始模型在一组人工示例上的局限性,然而,当在真实数据集上实现它时,似乎存在某种问题。更重要的是,当前的eif实现几乎和sklearn一样快。在我的 MacBook Pro 上,sklearn IF 花了 14 秒来训练,而eif实现花了大约 10 分钟。

我真的希望该算法将得到进一步改进,并将成为识别异常的良好工具。

您可以在我的 GitHub 上找到本文使用的代码。一如既往,我们欢迎任何建设性的反馈。你可以在推特或评论中联系我。

喜欢这篇文章吗?成为一个媒介成员,通过无限制的阅读继续学习。如果你使用这个链接成为会员,你将支持我,而不需要额外的费用。提前感谢,再见!

参考

[1] 扩展隔离林

基于 Hampel 滤波器的异常检测

原文:https://towardsdatascience.com/outlier-detection-with-hampel-filter-85ddf523c73d?source=collection_archive---------6-----------------------

Source: pixabay

如何用 Python 从头开始实现 Hampel 过滤器

最近,我偶然发现了一种新的(对我来说)异常值检测算法 Hampel 过滤器。在这篇短文中,我想描述一下它是如何工作的,以及如何在实践中使用它。据我所知,没有包含该算法的 Python 库,所以我们将使用两种不同的方法(for-looppandas)从头实现它。最终,我们将会看到在执行速度方面,哪一个的表现更好。

更新 : Hampel 过滤器在sktime实现,你可以在这里找到更多关于它的信息。

汉佩尔过滤器

让我们从一个快速的理论介绍开始。描述该算法的在线资源并不多(甚至维基百科上也没有页面),但它足够简单,可以快速理解其中的逻辑。还有,我在文末放了一些参考资料。

Hampel 过滤器的目标是识别和替换给定系列中的异常值。它使用一个可配置宽度的滑动窗口来浏览数据。对于每个窗口(给定观察和2 window_size周围元素,每侧window_size,我们计算中值和标准偏差,表示为中值绝对偏差

为了使 MAD 成为标准偏差的一致估计量,我们必须将其乘以一个常数比例因子 k 。该因子取决于分布,对于高斯分布,该因子约为 1.4826。

如果考虑的观察值与窗口中值的差异超过 x 标准偏差,我们将其视为异常值并用中值代替。

Hampel 滤波器有两个可配置的参数:

  • 滑动窗口的大小
  • 识别异常值的标准偏差的数量

我们根据用例选择这两个参数。较高的标准差阈值使过滤器更宽容,较低的标准差阈值将更多的点识别为异常值。将阈值设置为 0 对应于 John Tukey 的中值滤波器。

由于过滤器使用滑动窗口,因此将其用于时间序列数据最有意义,其中数据的顺序由时间决定。

Python 实现

导入库

第一步是导入所需的库。

import matplotlib.pyplot as plt
import warnings
import pandas as pd
import numpy as np

有异常值的随机游走

在实现算法之前,我们使用随机漫步创建一个人工数据集。我们定义了一个函数,它接受异常值的百分比作为参数,并通过一个常数乘数随机缩放一些随机游走增量。

使用该函数,我们生成人工数据,并将其绘制如下,以及引入的异常值。

rw, outlier_ind = random_walk_with_outliers(0, 1000, 0.01)plt.plot(np.arange(len(rw)), rw)
plt.scatter(outlier_ind, rw[outlier_ind], c='r', label='outlier')
plt.title('Random Walk with outliers')
plt.xlabel('Time steps')
plt.ylabel('Values')
plt.legend();

评估结果

我们还需要定义一个函数来评估异常值检测算法的结果。为此,我们将绘制实际与检测到的异常值,并返回一个简短的性能总结。

Hampel 滤波器实现

  1. **for-loop** 实现

我们从 Hampel 滤波器的for-loop实现开始。我们基于来自pracma R 包的代码。

我们在 RW 系列上运行算法。我们选择了窗口大小 10,但是这应该根据最佳性能的经验来确定。

res, detected_outliers = hampel_filter_forloop(rw, 10)

我们使用之前定义的帮助函数来评估结果。

tp, fp, fn = evaluate_detection(rw, outlier_ind, detected_outliers)

Evaluation of the for-loop implementation

在图中,我们可以看到,该算法正确识别了 8 个(10 个中的)异常值,将一个观察值误认为异常值(红点)并遗漏了 2 个异常值(黑点)。也许通过调整窗口大小可以获得更好的性能。然而,这对于练习的目的来说已经足够了。

我们还绘制了转换后的序列,其中异常值被窗口中值所取代。

plt.plot(np.arange(len(res)), res);
plt.scatter(outlier_ind, rw[outlier_ind], c='g', label='true outlier')
plt.scatter(fp, rw[fp], c='r', label='false positive')
plt.title('Cleaned series (without detected outliers)')
plt.legend();

Transformed series (removed outliers)

2.**pandas** 实现

对于pandas的实现,我们使用了pd.Series和 lambda 函数的rolling方法。

rolling方法中,我们指定两倍的窗口大小并使用居中,因此所考虑的观察在2 * window_size + 1窗口的中间。在运行算法之前,我们将 RW 从np.ndarray转换为pd.Series

rw_series = pd.Series(rw)
res, detected_outliers = hampel_filter_pandas(rw_series, 10)
tp, fp, fn = evaluate_detection(rw, outlier_ind, detected_outliers)

Evaluation of the pandas implementation

两种方法的结果是相同的,这总是一个好现象:)

性能比较

此时,我们从执行速度的角度对这两个实现进行测试。我们预计pandas会运行得更快。

首先,我们测试for-loop实现:

%%timeit
res, detected_outliers = hampel_filter_forloop(rw, 10)# 67.9 ms ± 990 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

然后,我们对pandas实现运行类比测试:

%%timeit
res, detected_outliers = hampel_filter_pandas(rw_series, 10)# 76.1 ms ± 4.37 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

我们看到pandas实现变得更慢。要测试的一个假设是,对于更大的系列,pandas实现会更快。这就是为什么我们也将随机漫步系列的长度增加到 100000,并再次测试性能。

rw, outlier_ind = random_walk_with_outliers(0, 10 ** 5, 0.01)
rw_series = pd.Series(rw)

准备好数据后,我们开始测试性能:

%%timeit
res, detected_outliers = hampel_filter_forloop(rw, 10)
# 6.75 s ± 203 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)%%timeit
res, detected_outliers = hampel_filter_pandas(rw_series, 10)
# 6.76 s ± 30.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

事实证明,现在他们获得了相当的性能,而pandas实现提供了更稳定的性能(更低的标准偏差)。

奖励:用numba增加循环的速度

作为奖励,我们探索了用numba加速基于 for 循环的代码的可能性。numba是一个将 Python 代码翻译成优化的机器代码的库。考虑到转换代码的可能性,numba可以让某些用 Python 编写的算法接近 c 语言的速度。

关于numba最好的部分是(如果可能的话)在编码方面,速度提升的代价非常小。我们需要导入这个库,并在我们想要翻译成机器码的函数之前添加[@jit](http://twitter.com/jit)装饰器。

nopython参数表明我们是希望numba使用纯机器代码还是在必要时使用一些 Python 代码。理想情况下,只要numba没有返回错误,这应该总是设置为true

下面我们测试执行速度。

%%timeit
res, detected_outliers = hampel_filter_forloop_numba(rw, 10)
# 108 ms ± 1.8 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

与实施pandas的 6.76 秒相比,这只需要 108 毫秒!这是一个大约 63 倍的大规模加速!

结论

总之,在本文中,我们解释了 Hampel 过滤器如何在异常值检测方面工作,以及如何在 Python 中实现它。我们还从执行速度的角度比较了这些实现。

考虑 Hampel 滤波器的缺点也是有好处的:

  • 它在序列的开始和结束时检测异常值有问题——当窗口不完整时(即使在一侧),该函数不会检测到可能的异常值
  • 当离群值在窗口范围内彼此接近时,它很难检测到离群值

一如既往,我们欢迎任何建设性的反馈。你可以在推特上或评论中联系我。你可以在我的 GitHub 上找到本文使用的代码。

喜欢这篇文章吗?成为一个媒介成员,通过无限制的阅读继续学习。如果你使用这个链接成为会员,你将支持我,而不需要额外的费用。提前感谢,再见!

参考

  • Hampel F. R .,“影响曲线及其在稳健估计中的作用”,美国统计协会杂志,69,382–393,1974 年
  • 刘、韩聪、西里沙、。"在线异常检测和数据清理."计算机和化学工程。第 28 卷,2004 年 3 月,第 1635-1647 页
  • 苏梅拉,朱卡。"中值滤波相当于排序."2014

离群值:简介

原文:https://towardsdatascience.com/outliers-an-introduction-e07445c8f430?source=collection_archive---------21-----------------------

它们是什么以及它们是如何产生的一些想法

Photo by Will Myers on Unsplash

离群值是数据分析中的一个大话题。这篇文章只是一个介绍。我将试图消除一些神话,给这个问题一些空间,并涵盖一些较简单的案例。我计划写更多关于特定问题的文章。

什么是离群值?

异常值没有普遍适用的定量定义。一般来说,异常值是令人惊讶的观察结果。然而,令人惊讶的是部分由于实质性的知识和数据的性质。一种尝试使定义更客观的方法是说异常值是一个“远离”数据主要部分的点,但是“远”是变化的。

异常值的类型 I:不可能的值和数据输入错误

将异常值分类的一种方法是数据输入错误和其他。有时候,很明显是数据输入错误。有些价值观是不可能的。没有 5 米高的人类。如果你能识别出这种异常值,那么你有两个选择:改正它或者删除它。但是,如果异常值只存在于某个观察值的一个变量上,您可能希望保留该观察值的其他变量。例如,假设 5 米高人有合理的年龄、性别、收入等条目。您可能希望保留这些值。

不要忽视或低估数据输入错误的可能性。数据清理很重要,也很耗时。

对于本文的其余部分,我将假设您已经完成了上述工作

异常值类型 II:变量数量

什么是异常值以及如何检测异常值取决于几个因素。一个是变量的数量。你可以的

  • 一个变量(单变量数据)
  • 两个变量(双变量数据)
  • 几个变量(多元数据)或
  • 一整批(多变量数据)

随着列表的深入,发现异常值变得越来越困难,我将在以后的文章中写更多,但是,作为一个样本,在美国人口的样本中,12 岁的孩子不是异常值,寡妇也不是异常值,但 12 岁的寡妇是异常值——不一定不可能,但肯定不太可能,也不寻常。

异常值的类型 III:观察值的数量

如果 N 为 10,那么不寻常或令人惊讶的事情,对于 N 为 10,000,000 就不那么令人惊讶了。例如,如果你正在测量成年男性的身高,那么,在 10 个样本中,一个 6 英尺 6 英寸(2 米)的家伙是相当令人惊讶的。在一千万人中,他一点也不奇怪。事实上,如果在这个尺寸的样本中找不到至少一个那么高的人,那将是令人惊讶的。

这就是为什么简单的规则,如“超过平均值 3 倍的标准偏差是异常值”的原因之一。有时候 3 应该是 1。其他时候,应该是 5。

离群值的类型 IV:分布

许多变量大致呈正态分布,但绝不是所有变量都呈正态分布。例如,收入不是。年龄不是。还有很多其他的例子。预期分布的形状会影响我们所认为的异常值。

这也是简单的经验法则没有多大用处的另一个原因。

更多的并发症

每当你有一个以上的变量时,所有这些“类型”组合在一起,极大地增加了检测异常值的难度。举个相对简单的例子,看看成年男性的身高体重分布。两个变量都大致正常(体重没那么接近)。但是它们高度相关。一个人可能是以下方面的异常值:

  • 身高而非体重:篮球运动员马努特·波尔身高 7 英尺 7 英寸(2.31 米),这在任何尺寸的样本中都是一个异常值,但他体重 200 磅(91 公斤),根本不是异常值。
  • 体重而非身高:乔恩·布劳尔·明诺克在他最重的时候是有史以来最重的人(1400 磅或 635 公斤)。但他身高 6 英尺 1 英寸(1.85 米)。
  • 不是一个人,而是两个人一起。任何有点高但很瘦的人,或者有点矮但很重的人都适合这里。
  • 两个人都是,但不是一起:另一个篮球运动员乔治·穆雷桑,和马努特·波尔一样高(见上图),但体重 325 磅(147 公斤)。对大多数人来说,这是一个很高的体重,但对像这样高的人来说,这是很正常的。

这只是两个变量,都大致正常。

事情变得更糟。糟糕多了。

检测异常值(更不用说处理它们)不能很好地自动化(这是大数据的一个大问题)。

欢迎在评论中提问,我会回答或者在以后的文章中给出答案。

FQ数据科学以及如何避免其陷阱

原文:https://towardsdatascience.com/over-the-wall-data-science-and-how-to-avoid-its-pitfalls-5af6fa2eef2b?source=collection_archive---------21-----------------------

将机器学习模型投入生产

跨墙数据科学是将数据科学团队的成果部署到生产系统的常见组织模式。数据科学家开发算法、模型或机器学习管道,然后工程师(通常来自另一个团队)负责将数据科学家的代码投入生产。

这种开发模式试图解决以下问题:

  • 质量:我们希望生产代码是高质量的,并由工程团队维护。由于大多数数据科学家都不是优秀的软件工程师,他们不应该编写端到端的产品级代码。
  • 资源分配:构建和维护生产系统需要特殊的专业知识,数据科学家可以贡献更多的价值来解决他们接受培训的问题,而不是花费时间来获得这些专业知识。
  • 技能:生产中使用的编程语言可能不同于数据科学家通常使用的语言。

然而,在FQ开发模式中有许多陷阱,可以通过适当的规划和资源配置来避免。

什么是FQ数据科学?

数据科学家编写一些代码,并花费大量时间使其正确运行。例如,代码可以以某种方式汇集数据,并建立一个对测试数据表现良好的机器学习模型。达到这一点是数据科学家花费大部分时间迭代代码和数据的地方。工作产品可以是一组脚本,或者一个 JupyterRStudio 笔记本,包含代码片段、文档和可重复的测试结果。在极端情况下,数据科学家制作一个详细描述算法的文档,使用数学公式和对库调用的引用,甚至不给工程团队任何代码。

在这一点上,代码被扔到了工程界。

然后,一名工程师负责生产数据科学家的代码。如果数据科学家使用 R,而生产应用程序使用 Java,这可能是一个真正的挑战,在最坏的情况下,会导致用不同的语言重写所有的东西。即使在双方都使用 Python 的常见且简单得多的情况下,工程师也可能想要重写代码以满足编码标准、添加测试、优化性能等。这样一来,生产代码的所有权就在工程师手里,数据科学家无法修改。

当然,这是一种过于简单化的做法,这一过程有许多变体。

有一面墙有什么不好?

让我们假设工程师成功地构建了新代码,数据科学家将其结果与他们自己的代码的结果进行了比较,并且新代码被发布到生产中。随着时间的推移,数据科学家需要改变算法中的一些内容。与此同时,这位数据工程师继续从事其他项目。在生产中改变算法变成了一个漫长的过程,包括等待一个工程师(希望是同一个)出现。在许多情况下,在经历了这个过程几次之后,数据科学家就放弃了,只有关键的更新才会发布。

数据科学和工程之间的这种互动让数据科学家感到沮丧,因为这使得他们很难做出改变,并剥夺了他们对最终代码的所有权。这也使得解决生产问题变得非常困难。这对工程师来说也是令人沮丧的,因为他们觉得自己被排除在原始设计之外,不参与项目中最有趣的部分,还得修正别人的代码。双方的挫折感使得整个过程更加困难。

打破数据科学和工程之间的壁垒

如果数据科学家能够自给自足,并且能够安全地将他们自己的代码部署到生产中,那么就可以完全消除对越墙数据科学的需求。这可以通过最大限度地减少数据科学家的代码在生产系统上的足迹,以及让工程师成为人工智能系统设计和开发过程的一部分来实现。人工智能系统开发是一项团队运动,工程师和数据科学家都需要成功。招聘和资源分配必须考虑到这一点。

让团队跨职能

在数据科学项目的早期引入工程可以避免“我们”和“他们”的心态,使产品变得更好,并鼓励知识共享。即使完全跨职能的工程师和数据科学家团队不可行,组建一个为共同目标而合作的项目团队也能解决越墙数据科学的大多数问题。

期待数据科学家成为更好的工程师

最后,数据科学家应该拥有生产应用程序中 AI 代码的逻辑,并且该逻辑需要在应用程序中隔离,以便数据科学家可以自己修改它。为此,数据科学家必须遵循与工程师相同的最佳实践。例如,对于数据科学家来说,编写单元和集成测试一开始可能会感觉开销很大,但是,知道您的代码在您做出更改后仍然工作的价值很快就克服了这种感觉。此外,工程师必须参与数据科学家的代码审查过程,以确保代码具有生产质量,并且没有可伸缩性或其他问题。

为数据科学家提供生产工具

工程师应该构建生产就绪的可重用组件和包装器、测试、部署和监控工具,以及数据科学相关代码的基础设施和自动化。然后,数据科学家可以专注于包含人工智能应用程序主要逻辑的一小部分代码。当工具不存在时,数据科学家倾向于花费大量时间自己构建工具。

避免用另一种语言重写代码

生产环境是对可接受的机器学习包、算法和语言类型的限制之一。这个限制必须在项目开始时强制执行,以避免重写。许多公司都在开源和商业产品中提供面向生产的数据科学平台和人工智能模型部署策略。这些产品,如 TensorFlowH2O.ai ,有助于解决生产环境与数据科学家通常使用的环境非常不同的问题。

这篇文章最初出现在 Life Around Data 博客上。mabe lamber 和 Wokadandapix 在 Pixabay 上拍摄的图片

整体设备有效性和主题建模

原文:https://towardsdatascience.com/overall-equipment-effectiveness-and-topic-modeling-bb467177217f?source=collection_archive---------38-----------------------

在制造业中,我们一直在寻找优化生产线运作的方法。我们希望在保持高产量的同时增加产量。为了衡量当前系统的生产效率,我们可以使用总体设备效率(OEE) 指数。OEE 涵盖三个方面:可用性、性能和质量。在这篇文章中,我将重点关注可用性,并通过一个示例用例。

假设我们从某个特定设备获得了 6 天的运行日志文件。设备每天使用 10 个小时。我们的目标是找出是否有问题的日子。唯一的问题是日志状态是用外语写的(假设合同制造商在印尼)。

import matplotlib.pyplot as plt
import pandas as pd# suppose the data is stored in a pandas dataframe called df
df.head()

Sample Dataset

有许多方法可以分析这种事务性数据。在这里,我将重点介绍一种叫做主题建模的特殊技术。基本思想是首先将每一行(或每一天)视为一个状态包(类似于的单词包)。

statusDF = pd.pivot_table(df, index="day", columns="dayStatus", values="durationInHours", aggfunc='sum')
statusDF.fillna(0, inplace=True)
statusDF

Bag of Status Dataframe

然后,我们可以使用主题建模来发现这 6 天的日志是否可以聚集成一个更小的数据子集。每个集群将被分配一个名称(或主题),理想情况下,其中的数据将具有一个通用的状态配置文件。这类似于自然语言处理中的主题建模,其中某些单词与某些主题高度相关。

我们将使用一个简单的主题建模算法,称为非负矩阵分解 (NMF)。我将在另一篇文章中讨论算法的细节。

NMF 的棘手之处在于,我们需要事先决定隐藏主题的数量。在这种情况下,我们任意选择它们为 2。

from sklearn.decomposition import NMF
model = NMF(n_components=2, init='random', random_state=1)plt.figure(figsize=(8, 5))W = np.around(model.fit_transform(statusDF), 1)
plt.subplot(1, 2, 1)
plt.imshow(W)
plt.title("matrix W")
plt.yticks(np.arange(len(statusDF.index.values)), statusDF.index.values)
H = np.around(model.components_, 1)plt.subplot(1, 2, 2)
plt.xticks(np.arange(len(statusDF.columns.values)), statusDF.columns.values, rotation='90')
plt.colorbar(pad=0.1)
plt.imshow(H)
plt.title("matrix H")plt.show()

Results of Non-negative Matrix Factorization

NMF 试图将状态矩阵包分解成矩阵 W 和矩阵 h 的乘积。这是在对每个状态的实际含义没有语义理解的情况下完成的(即不需要翻译)。

矩阵 W

矩阵 W 可以解释为日期和主题之间的映射。从上面的结果中,我们可以看到第 1、3、4 和 6 天都来自主题 0,具有不同程度的置信度(用方框颜色标记)。同时,第 2 天和第 5 天来自主题 1。这说明有两组天。问题是,这两者的区别是什么?答案就在矩阵 h 里。

矩阵 H

矩阵 H 是主题和状态之间的映射。例如,主题 0 与两种状态相关联:“bergerak aktif”和“uji coba berjalan”。另一方面,主题 1 带有“pembetulan”和“pengecekan”。在这一点上,拥有一个能够解释状态的领域专家将会非常有用。快速访问您最喜欢的翻译引擎会发现,“bergerak aktif”和“uji coba berjalan”表示积极地移动,而“pembetulan”和“pengecekan”则与修复/调试活动有关。

原来,主题 1 与维护相关,而主题 0 是高可用性。因此,我们可以强调,第 2 天和第 5 天发生的事情似乎促使了维护,最终损害了机器的 OEE 分数。

我们也可以用词云来形象化矩阵 H。每个字的大小对应于矩阵值。

from wordcloud import WordClouddef printWordCloud(text):
  # Create and generate a word cloud image:
  wc = WordCloud(relative_scaling=0.6, prefer_horizontal=1)
  wc.generate_from_frequencies(text)# Display the generated image:
  plt.imshow(wc, interpolation='bilinear')
  plt.axis("off")
  plt.show()

# Topic 0
text0 = dict(zip(statusDF.columns.values, H[0]+1e-99)) # replace 0 value  with a small weight
printWordCloud(text0)
# Topic 1
text1 = dict(zip(statusDF.columns.values, H[1]+1e-99))
printWordCloud(text1)

Topic 0

Topic 1

结论

我们已经展示了主题建模可以用来识别具有相似状态(列)的日期(行)。在领域专家的帮助下,我们可以解释每个主题的含义,并随后决定哪个主题需要立即关注。

用 Mask-RCNN 克服实例分割过程中的过拟合

原文:https://towardsdatascience.com/overcome-overfitting-during-instance-segmentation-with-mask-rcnn-32db91f400bc?source=collection_archive---------3-----------------------

仅在 1,349 幅带注释的图像上训练 Mask-RCNN

Not bad for a model trained on such a tiny dataset 😃

介绍

计算机视觉的进步拥有许多有前途的应用,如自动驾驶汽车或医疗诊断。在这些任务中,我们依靠机器识别物体的能力。

我们经常看到的与物体识别相关的任务有四个:分类定位、物体检测、语义分割、实例分割。

https://www.oreilly.com/ideas/introducing-capsule-networks?cmp=tw-data-na-article-ainy18_thea

分类和定位中,我们感兴趣的是给图像中的物体分配类别标签,并在物体周围绘制一个包围盒。在该任务中,要检测的对象的数量是固定的

物体检测不同于分类和定位,因为在这里,我们不预先假设图像中物体的数量。我们从一组固定的对象类别开始,我们的目标是分配类别标签,并在每次这些类别中的对象出现在图像中时绘制边界框

语义分割中,我们给每个图像像素分配一个类标签:所有属于草的像素都标为“草”,属于羊的标为“羊”。例如,值得注意的是,这项任务并不能区分两只羊。

我们在这个任务中的任务是实例分割,它建立在对象检测和语义分割的基础上。与对象检测一样,我们的目标是标记和定位预定义类别中对象的所有实例。然而,我们不是为检测到的对象生成边界框,而是进一步识别哪些像素属于该对象,就像在语义分割中一样。语义分割的不同之处在于,实例分割为每个对象实例绘制一个单独的掩码,而语义分割将为同一类的所有实例使用相同的掩码

在本文中,我们将在一个微型 Pascal VOC 数据集上训练一个实例分割模型,只有 1349 张图像用于训练,100 张图像用于测试。这里的主要挑战将是在不使用外部数据的情况下防止模型过度拟合。

你可以在 Github 上找到所使用的数据集以及完整的训练和推理管道。

数据处理

注释是 COCO 格式的,所以我们可以使用来自 pycocotools 的函数来检索类标签和掩码。在这个数据集中,总共有 20 个类别。

以下是训练图像和相关遮罩的一些可视化效果。遮罩的不同阴影表示同一对象类别的几个实例的单独遮罩。

这些图像具有不同的大小和长宽比,因此在将图像输入模型之前,我们调整每张图像的尺寸为 500x500 。当图像尺寸小于 500 时,我们放大图像,使最大的边长为 500,并根据需要添加零填充以获得正方形图像。

Example input before (left) and after resizing with the associated annotations (right)

为了让模型更好地泛化,尤其是在像这样的有限数据集上,数据扩充是克服过度拟合的关键。对于每个图像,以概率 0.5 执行水平翻转,将图像随机裁剪为原始尺寸的 0.9 到 1 倍之间的比例,以概率 0.5 执行具有随机标准偏差的高斯模糊,以 0.75 到 1.5 之间的比例调整对比度,以 0.8 到 1.2 之间的比例调整亮度,并且还应用一系列随机仿射变换,例如缩放、平移、旋转和剪切。

掩模-RCNN

我们将使用 matterport 的 Mask-RCNN 的实现进行训练。虽然很诱人,但我们将而不是使用他们为 COCO 女士预先训练的权重来展示我们如何仅使用 1,349 张训练图像就可以获得良好的结果。

Mask-RCNN 于 2017 年在 Mask-RCNN 论文中提出,是同一作者对fast-RCNN的扩展。fast-RCNN 广泛用于对象检测,其中模型在检测到的对象周围生成边界框。Mask-RCNN 更进一步,生成对象屏蔽

我将在下面提供一个模型架构的快速概述,matterport 发表了一篇很棒的文章,详细介绍了他们的模型实现。

https://medium.com/@jonathan_hui/image-segmentation-with-mask-r-cnn-ebe6d793272

首先,我们使用一个主干模型从输入图像中提取相关特征。这里,我们使用 T21 架构作为主干。图像从形状张量(500,500,3)转换成形状特征图(32,32,2048)。

先前获得的特征然后被输入到区域提议网络 (RPN)。RPN 扫描特征图的区域,称为,并试图确定包含对象的区域。这些锚具有不同的尺寸和纵横比。RPN 为每个锚点分配一个锚点类别:前景(正锚点)或背景(负锚点)。中性主播是不影响训练的主播。

Positive anchors (left), neutral anchors (center), negative anchors (right)

一个提议层然后挑选最有可能包含一个对象的锚,并提炼锚框以更紧密地适应对象。当太多锚点重叠时,仅保留前景分数最高的锚点(非最大抑制)。这样,我们就获得了感兴趣的区域(ROI)。

对于包含由 ROI 分类器选择的对象的每个区域,该模型然后生成 28×28 个掩模。在训练期间,地面真实遮罩被缩小以利用预测遮罩计算损失,并且在推断期间,生成的遮罩被放大到 ROI 边界框大小。

迁移学习

更快更好地训练模型的关键是迁移学习,尤其是在数据有限的情况下。Imagenet 数据集是一个巨大的自然图像库,类似于我们的图像。因此,我们可以将 Resnet101 主干模型的权重初始化为在 Imagenet 上预先训练的权重。这将提高我们获得的特征地图的准确性,并因此提高整个模型的准确性。

ImageNet sample images

为了微调预先在 Imagenet 上训练的模型,我们首先只训练模型** 头部。然后,我们训练从 ResNet 阶段 4 到剩余时期的的层。这个训练方案也有助于 过拟合最小化。我们可以允许自己冻结并且从不微调第一层,因为我们可以重用模型学习的权重来从自然图像中提取特征。**

结果和检测管道可视化

训练 20 个时期的模型头部,以及 25 个额外时期的其余选定模型层,允许我们在测试集 0 上获得地图分数。53650 。以下是随机选择的测试图像上模型输出的一些可视化效果:

我们还可以可视化算法不同步骤的输出。下面,我们有边界框细化前的得分排名靠前的锚点。

接下来,在边界框细化和非最大值抑制之后,我们有了输出锚点。这些建议然后被输入分类网络。请注意,在这一点上,我们有一些框紧密地绑定了一些对象,如标志,它们不属于我们已经定义的对象类别。

分类网络运行该提议以确定肯定检测,生成类别概率和边界框回归。

在获得边界框并对它们进行细化之后,实例分割模型为每个检测到的对象生成遮罩。在训练期间,遮罩是软遮罩(具有浮点像素值)并且大小为 28×28。

最后,预测的遮罩被重新缩放到边界框尺寸,我们可以将它们覆盖在原始图像上,以可视化最终输出。

感谢阅读这篇文章,我希望你喜欢!

还有许多其他最先进的架构例如分割,您也可以尝试,如果您在这个小小的 COCO 数据集上尝试了这些架构,请告诉我:)

您可能还想了解我如何在 3859 张灰度图像上训练 ResNet 分类器,从而在我的课堂 Kaggle 挑战赛中获得第二名:

** [## 利用有限数据进行 Kaggle 图像分类的最新成功技术

关于如何防止模型在小数据集上过度拟合但仍能进行准确分类的教程

towardsdatascience.com](/latest-winning-techniques-for-kaggle-image-classification-with-limited-data-5259e7736327)**

设计欺诈检测系统时克服挑战

原文:https://towardsdatascience.com/overcoming-challenges-when-designing-a-fraud-detection-system-29e33bcb43d2?source=collection_archive---------12-----------------------

关于如何对我们的数据进行过采样,以及选择正确的模型和指标,可以改善我们的预测系统

人工智能领域的最新进展为大量智能和个性化的欺诈检测方法打开了大门。曾经需要大量人工劳动的领域,现在是经历了机器学习进步的众多领域之一。尽管如此,重要的是要注意到,这种技术像任何其他技术一样,并不完美,容易出现问题,因此个人、企业和服务提供基于预测技术的解决方案来检测欺诈性交易,我们必须后退一步,考虑可能出现的挑战。

我相信可以肯定地说,大多数交易都是非欺诈性的。虽然这很好,但它也造成了欺诈检测领域最重要和最普遍的问题:不平衡的数据。数据是机器学习预测模型中最重要的组成部分,不平衡的数据集(在本例中是主要由非欺诈记录组成的数据集)可能会导致预测系统无法正确了解欺诈交易。在这种情况下,直接的解决办法是获取更多的数据;然而,在实践中,这要么昂贵、耗时,要么几乎不可能。幸运的是,一些程序和算法有助于解决不平衡数据集的问题。

过采样和欠采样技术允许我们修改数据集的类分布。顾名思义,过采样是一种用于创建类似于原始数据集的合成数据的过程,而欠采样的目标则相反,去除数据;值得注意的是,在实践中,过采样比欠采样更常见,这就是为什么你可能听说过前者多于后者。

最流行的过采样算法是合成少数过采样技术SMOTE 。SMOTE 是一种算法,它依靠最近邻的概念来创建其合成数据。例如,在下图中,我们有一个由 12 个观测值和两个连续特征组成的不平衡数据集,xy。在这 12 次观察中,10 次属于X类,其余两次属于Y。SMOTE 所做的是从代表性不足的数据中选择一个样本,对于每个点,它都计算其 K 个最近邻——为了简单起见,让我们假设它的K=1。然后,它获取数据点与其最近邻居之间的向量,并将其乘以 0 到 1 之间的随机值,从而产生新的向量“a”。该向量是我们新的合成数据点。

The nearest neighbor of point number 1, is point number 2 and vice-versa, thus, the newly synthetic data point is to be created somewhere along the dotted line

Dataset enhanced with synthetic data

以下要点显示了如何在 r 中执行 SMOTE。

我想提出的第二个概念是预测系统的选择。首先,我们可能会认为,一个监督学习系统将一个行为分类为欺诈与否将是解决这类问题的最合适的方法。虽然这听起来很有吸引力,但需要注意的是,有时这还不够,异常检测和无监督学习等其他领域可以帮助找到那些可能代表欺诈的嘈杂和异常点。

异常检测是数据挖掘的一个领域,它处理异常和罕见事件(也称为离群值)的发现,这些事件偏离了被认为是正常的事件。在基本层面上,这些检测方法在统计上更加密集,因为它们更紧密地处理分布的主题以及数据点与分布的差异程度。例如,定义为UF = Q3 + (1.5 * IQR)LF = Q1 — (1.5 * IQR)上下内栅栏等方程(其中 IQR 是四分位数范围)是用于创建屏障的众多技术之一,该屏障将数据分为正常数据和异常数据。

Cute outlier. Image by Hans Braxmeier from Pixabay

让我们用一个现实而愚蠢的例子来解释这一点。想象一下,有一个叫约翰的家伙,他是一个早起的人,经常在早上 5:30 左右醒来(一个真正的冠军),然而,昨晚当约翰庆祝他的 32 岁生日时,他有点太开心了,第二天早上 6 点就醒来了(对此感到很糟糕)。这个“6 am”代表我们数据集中的一个异常。

下图代表了约翰最后的十个起床时间,我们可以看到最后一个似乎是不合适的。正确地说,我们可以说这个点远远落在其他九个时间的分布上;三西格玛或标准偏差规则,一个用于检测异常值的规则,显示了这一点。如果没有第 10 次,平均值和标准差将是 318.89 和 2.09(如果我们将时间计算为 12 点后的分钟数)。然而,第 10 次(6 am,或 420)远远超出了平均值加上三倍标准差的范围(318.89 + (2.09 * 3) = 325.16),表明时间确实是一个异常。

On the 10th day, John had a rough wake up

无监督学习,尤其是聚类,也可以用于检测数据集中的异常和有噪声的内容。这种机器学习算法在这样的假设下工作,即相似的观察结果倾向于被分组在相同的簇下,而有噪声的观察结果则不会。回到约翰和他奇妙的睡眠模式,如果我们使用 k-meansk=2对他的数据进行聚类,我们可以观察到异常点如何落入自己的聚类中。

The lonely red point on the right represents an anomaly, a point that is dissimilar to the rest of the dataset

最后,性能指标的选择在训练我们的系统时起着重要的作用。如果数据集不平衡,像准确度这样的标准分数就没有多大用处。例如,假设只有 2%的测试数据集内容是真实的欺诈交易。如果该模型将所有这些情况分类为非欺诈性的,则准确率将为 98%;一个很好的数字,但在这种情况下微不足道。更适合这个用例的一些指标是精度召回科恩的卡帕系数。此外,我们正在优化的错误类型,即假阳性假阴性,也非常重要。在某些情况下,我们应该倾向于使用较高的假阳性率来换取较低的假阴性分数,反之亦然。

打击欺诈、诈骗和垃圾邮件活动的需求将一直存在。即使最近在人工智能领域取得了所有的进步和突破,在我们解决问题的探索过程中也会遇到一些困难。在本文中,我谈到了其中的三个困难:缺乏平衡的数据集、预测系统的选择和合适的评估指标的选择,并提供了一些指针和选项,以提高我们预测和检测的质量。

我的 GitHub 上提供了用于生成图片的代码。

[## juandes/欺诈-挑战-附录

在 GitHub 上创建一个帐户,为 juandes/fraud-challenges-appendix 的开发做出贡献。

github.com](https://github.com/juandes/fraud-challenges-appendix)

感谢阅读。

[## 胡安·德迪奥斯·桑托斯(@ jdiosantos)|推特

胡安·德迪奥斯·桑托斯的最新推文(@ jdiossantos)。机器学习/数据工程师。还有,口袋妖怪大师,还有…

twitter.com](https://twitter.com/jdiossantos)

克服推荐系统中的回音室(使用电影评级)

原文:https://towardsdatascience.com/overcoming-echo-chambers-in-recommendation-systems-using-movie-ratings-3686f50fc053?source=collection_archive---------24-----------------------

以下帖子的代码可以在 GitHub 上找到。

介绍

自动推荐系统已经成为日常在线生活的一部分。无论是亚马逊推荐产品,脸书推荐新闻文章,还是网飞推荐电影,我们经常与推荐系统进行互动,以使消费者和企业都受益。这些系统的缺点是,随着时间的推移,它们可能会限制推荐项目的多样性,因为它们缩小了用户偏好的范围。这一过程产生了回音室(只接触像你一样的其他人的建议)、反馈循环(强化你记录的偏好的建议)和过滤气泡(只接触与你过去喜欢的项目相似的建议)。这些现象导致用户只能看到强化他们自己的偏见或购买模式的推荐。

下面的帖子描述了我构建的一个系统,它根据与用户不同但又不太不同的其他人的偏好提供额外的推荐。这些额外的推荐是通过基于从评级矩阵的交替最小二乘(ALS)分解获得的潜在用户因素对用户进行聚类来识别的。一旦分类被创建,每个分类的最高评级项目(基于分类质心)被识别。每个聚类中排名最高的项目形成了可以从中提取推荐的项目集。从最接近用户聚类的两个聚类中提取用户的推荐。完整的系统向用户提供了两组建议。第一组来自传统的 ALS 模型,第二组来自增强模型。

商业理解

自动推荐系统在拥有在线业务的企业中很常见。它们被用来推荐产品、新闻文章,甚至是食谱。这些系统旨在通过推荐消费者可能会喜欢的新产品来增加消费者的参与和购买。一种用于产生推荐的常见方法是协同过滤,其基于请求推荐的消费者和其他消费者的组合偏好来产生推荐。随着额外偏好的记录,协同过滤(CF)做出好的推荐(即,消费者会喜欢的推荐)的能力提高了。协同过滤的一个限制是,随着时间的推移,推荐的范围变得越来越窄,导致回音室、反馈循环和过滤气泡。

回音室、反馈回路和过滤泡沫的负面影响在社会和经济上都可以感受到。从社会角度来看,这些影响限制了对不同和相反思想的接触,导致了一个更加分裂和分化的社会。从经济上来说,这些影响限制了消费者接触的产品种类,限制了企业增加产品需求的潜力。

数据理解和准备

该项目利用了 MovieLens 数据集(哈珀&康斯坦,2015)。MovieLens 数据集是一个开源数据集,包含 283,228 个用户对 58,098 部电影的 27,753,444 个电影评级。评级为五星级别,范围从 0.5 星到 5 星,增量为 0.5 星。评分包括从 1995 年 1 月 9 日到 2018 年 9 月 26 日的数据,用于至少有 1 个电影评分的随机用户样本。一个附加文件包含关于电影的数据,包括它们的标题、发行年份和类型。MovieLens 使用许可证禁止在没有单独许可的情况下重新分发数据,但可以通过上述链接从许可证所有者处免费下载。

为了准备用于分析的评分数据,我删除了评分少于 10 分的用户和评分少于 5 分的电影。处理后的数据集包含 243,658 个独立用户的 27,510,397 个评级和 28,755 部电影。电影数据被处理以产生两个新的数据集。第一个仅包含评分超过 50 的电影。这些“收视率最高”的电影被用作所有推荐的基础。这样做是为了确保推荐仅包含来自大量用户的具有高平均评级的电影,从而防止仅来自少数用户的具有高平均评级的电影扭曲推荐集。第二个包含评分最高的前 100 部电影(基于平均评分)。前 100 部电影用于为新用户随机选择电影进行评级。这样做是为了确保向用户呈现熟悉的电影以供评价。

使用 Amazon Web Services(AWS)Elastic MapReduce(EMR)拟合 ALS 模型(见下文)后,需要进一步的数据处理。ALS 模型的用户和项目因子输出被保存为文件集(MapReduce 过程的一个功能)。要在 AWS EMR 之外使用用户和项目因素,需要将每组文件合并成一个 csv 文件。此外,必须对用户因素进行调整,以便在聚类算法中使用。

建模

Augmented Recommendation Process Model

上图概述了增强推荐系统生成推荐所遵循的流程。在整个过程中,增强推荐系统利用三种机器学习算法来产生电影推荐:替代最小二乘法(ALS)、KMeans 和梯度增强机器。以下解释了该过程如何工作以及机器学习算法如何在该过程中发挥作用。

在提出建议之前,ALS 和 KMeans 算法用于生成用户和项目因素(ALS ),然后使用 ALS 模型中的用户因素将用户分组(KMeans)。为了生成用户和项目因素,使用 AWS EMR 聚类将 ALS 模型拟合到已处理的评级数据。

然后,处理后的 ALS 因子被输入到 AWS 集群上的 KMeans 算法中,以确定集群的最佳数量。然后利用来自 KMeans 模型的误差来寻找最佳的聚类数。

然后,在本地计算机上重新运行 KMeans 算法,为评级数据集中的所有用户生成预测分类,并为每个分类生成分类质心。然后使用由 KMeans 模型预测的聚类来训练梯度增强机器。最后,计算聚类质心之间的距离并保存以备后用。

一旦这些模型被训练,推荐的过程就从用户给十部电影排序开始。使用在周、威尔金森、施雷伯和潘(未注明)中描述的过程,将这些排名与来自 ALS 的项目因子相结合,以预测处理的数据集中所有电影的用户评级。用户评价最高的电影成为 ALS 推荐。

为了生成增强的推荐,使用上面生成的用户因子和经过训练的梯度增强机器将用户分类到一个聚类中。然后,从最接近用户预测聚类的两个聚类中的最高评级电影中提取增强推荐。推荐是通过从这两个群集中的每一个中的 100 部最高评级的电影中随机选择电影来生成的。总共提供了十个推荐,六个来自最近的聚类,四个来自下一个最近的聚类。从每个聚类提供的推荐数量被加权,使得随着聚类之间的距离增加(即,聚类之间的差异增加),较少的推荐被贡献给最终的推荐列表。

估价

使用四个度量来评估增强的推荐模型。下面描述了每个指标和模型的性能。通过将这些指标应用于 MovieLens 数据集的 1000 个用户的随机样本来评估增强模型的性能。

第一个指标

第一个指标查看用户的前 100 条 ALS 建议(基于预测的用户评级)和用户群的前 100 条建议(基于群质心的评级)。ALS 推荐的电影在群集推荐中的比例应该很高。高比例表示用户的聚类代表用户的电影偏好。

Histogram of Proportion of Common Movies Between ALS Recommendations and User’s Cluster Recommendations

该模型在此指标上的表现不如预期。如上图所示,在大多数样本中,不到 10%的 ALS 推荐电影是由用户群推荐的。这可能是使用聚类质心来识别推荐的结果。识别每个聚类中最高评级电影的不同方法(例如,聚类中用户的平均评级)可以产生更好的结果。

第二个指标

第二个度量查看用户的前 100 个 ALS 推荐(基于预测的用户评级)和来自增强模型的前 100 个推荐(基于最接近用户聚类的两个聚类的聚类质心的评级)。在增强模型推荐中也发现的 ALS 推荐电影的比例应该很小。低比例表示来自增强模型的推荐不同于由 ALS 模型产生的推荐。

Histogram of Proportion of Common Movies Between ALS Recommendations and Augmented Recommendations

根据这一指标,模型表现符合预期。如上图所示,对于大多数样本,不到 10%的 ALS 推荐电影也是由增强模型推荐的。

第三个度量

第三个度量利用电影之间的距离(基于 ALS 项目因子)来评估来自增强模型的电影在质量上不同于来自 ALS 模型的电影的程度。对于此指标,将为样本中的每个用户计算 ALS 模型中前 100 部电影之间的均方距离(不包括电影与其自身之间的距离)。同样,为样本中的每个用户计算前 100 部 ALS 电影中的每一部与来自增强模型的每一部顶级电影之间的均方距离。使用 t-检验来测试样本的这些均方距离之间的差异。负的且具有统计显著性的 t 统计量指示两组推荐之间的平均差异大于 ALS 推荐内的平均差异,因此,来自增强模型的电影在质量上不同于来自 ALS 模型的电影。

不出所料,ALS 建议与补充建议在质量上有所不同(t 统计= -66.2,p = 0.000)。

第四个度量

最终的度量评估增强模型推荐的电影是否与 ALS 推荐的电影在质量上有太大的不同。该度量测试两个差异之间的差异:ALS 推荐和增强模型的推荐之间的差异,以及 ALS 推荐和来自离用户聚类最远的两个聚类的推荐之间的差异。这些差异的计算方式与上述第三个指标相同。差异中的差异使用 t 检验进行检验。正的且具有统计显著性的 t 统计表明 ALS 建议和来自最远聚类的建议之间的差异大于 ALS 建议和增强模型建议之间的距离。更大的距离是增强模型推荐与 ALS 推荐没有太大不同的证据,因为最远聚类推荐的电影差别更大。

正如所预期的,与从最远的聚类生成的推荐相比,增强的推荐与 ALS 推荐的差异更小(t 统计 5.5,p = 0.000)

后续步骤

未来的工作可以通过以下方式改进该项目:

  1. 通过结合更复杂的算法特征(例如,时间分量)来增强 ALS 模型,
  2. 通过参数调整提高梯度推进机器分类的性能,
  3. 通过改变从聚类中生成电影推荐的方式来提高增强推荐模型的性能,以及
  4. 将增强的推荐功能部署为 web 应用。

参考

F.麦克斯韦·哈珀和约瑟夫·a·康斯坦。2015.电影镜头数据集:历史和背景。ACM 交互式智能系统汇刊(TiiS) 5,4,第 19 篇(2015 年 12 月),19 页。http://dx.doi.org/10.1145/2827872。

Zhou, Y., Wilkinson, D., Schreiber, R. & Pan, R. (n.d.). Large-scale Parallel Collaborative Filtering for the Netflix Prize. Retrieved from https://endymecy.gitbooks.io/spark-ml-source-analysis/content/推荐/papers/Large-scale%20Parallel%20Collaborative%20Filtering%20the%20Netflix%20Prize.pdf.

克服你对研究论文的恐惧

原文:https://towardsdatascience.com/overcoming-your-fear-of-research-papers-41a95fc3a804?source=collection_archive---------20-----------------------

Source: https://www.pexels.com/

实话实说吧——研究论文很吓人。在机器学习领域,阅读一篇研究论文会感觉像是凝视着一个单词密集、公式复杂的深渊。很容易看到深渊,并认为它太难克服。然而,学会如何从研究论文中提取信息至关重要。机器学习领域发展如此之快,以至于经常只有通过阅读论文才能跟上时代的步伐。我的希望是帮助你发展一些技巧和策略,以便不感到不知所措。

Source: https://imgflip.com/memegenerator

开始时要宽,不要深

选择一篇研究论文,并决定无论如何都要征服它,这可能很有诱惑力。然而,我发现当开始时,这会导致精疲力尽和绝望。几周后,你会发现自己似乎没有取得什么进展,并认为自己不适合这项任务。

相反,我会建议从略读许多研究论文开始。这个过程的目标是开始适应论文的写作方式。论文几乎总是遵循类似的流程:开头是摘要,介绍和背景研究,中间往往是对研究贡献的详细描述,结尾是实验结果和结论,并提出了下一步的建议。

首先,我会查看一系列精选的论文,如令人敬畏的深度学习论文(注意: Arxiv Sanity 也是一个查找论文的好地方)。令人敬畏的深度学习论文列表不再保留,但它仍然是熟悉深度学习领域关键研究论文的一个很好的起点。从挑选看起来有趣的研究论文开始,做以下事情:

  • 阅读整个摘要。
  • 跳过方程式,但阅读数字。这可能是深度学习独有的,但几乎总是有伟大的人物概述了拟议的架构。
  • 查看实验结果部分的表格。
  • 看结论。

整个过程应该不到 10 分钟,给你一个像样的论文摘要。你应该理解这篇论文试图完成的内容(摘要)、方法论的高层次思想(图)、它实际上工作得如何(表),以及缺点和潜在的后续步骤(结论)。

你不会对这种方法的工作原理有很深的理解,但是没关系——目标是广泛覆盖论文。所以拿起下一张纸,重复这个过程。

以这种方式读了 10 到 20 篇论文后,我发现神奇的事情开始发生了。你不仅开始觉得拿起一篇研究论文并提取关键点很舒服,而且你也开始发展一个知识网络。你开始明白不同的想法是如何联系在一起的,以及哪些想法会不断浮现。例如,如果你正在阅读最近的 NLP 论文,你会开始意识到变形金刚风靡一时,一种新的艺术形式正以令人难以置信的速度出版。

这个知识网络非常有价值,因为下次你浏览一篇论文时,你会看到这项研究是如何与你读过的其他论文联系起来的。例如,您可能会读到(摘自 XLNet 摘要)

然而,依赖于用屏蔽破坏输入,BERT 忽略了屏蔽位置之间的相关性,并且遭受预训练-微调差异。根据这些优点和缺点,我们提出了 XLNet,一种广义自回归预训练方法,它(1)通过最大化因子分解顺序的所有排列的期望似然性来实现学习双向上下文,以及(2)由于其自回归公式,克服了 BERT 的限制。

你自己想想:好吧——是的,在高层次上,这是有道理的,因为我记得在伯特论文的数字中读到过一些关于掩蔽头寸的内容。只需几分钟,您就会明白 XLNet 的贡献之一是做了比屏蔽令牌更好的事情。你的知识面很浅,但足以增加你的知识网络。由于略读只需要几分钟,它还可以让你的知识网络保持最新的研究,即使是在快速发展的领域,如机器学习。

Source: https://imgflip.com/memegenerator

深入

一旦你略读了几篇论文,你就应该开始对不断出现的关键主题有所感觉。例如,在 NLP 中,一个关键主题是变压器。以我的经验来看,关键主题非常罕见,当你发现一个时,值得花时间去深入了解它(注意:你应该通过浏览大多数论文为自己赢得很多时间)。我的深入策略如下:

  • 从头开始。例如,如果你决定你真的需要理解 BERT,你可能会发现 BERT 中使用的概念你并不完全理解。通过浏览参考文献,试着追溯这些概念的起源。对于变形金刚,你需要理解注意力,这可能会带你去看注意力是你所需要的全部这篇论文。
  • 利用博客。事实证明,大多数研究论文并不是真的为了理解而写的(至少不是大多数人写的)。幸运的是,许多了不起的人花时间清晰地描述了困难的概念。例如,检查出这个惊人的写在变压器上从注意是你所需要的。在 Google、Medium、Reddit 上搜索这些资源,无论你在哪里,它们都能帮你节省时间。
  • 把它编码起来。对我来说,我发现一旦我能编写一些东西,我就能很好地理解它的实现。如果你在深度学习领域,我会强烈推荐 PyTorch,因为我经常发现你几乎可以直接从论文中的文字转换成 PyTorch 代码。哈佛大学的一个小组甚至为《你所需要的只是关注》做了这个。
  • 教吧。至此,你已经对这篇论文有了很好的理解,我强烈建议你将你所学到的东西传授给别人。你可以写一篇博客,向同事展示你学到的东西,甚至在当地的聚会上做一次演讲。教学将迫使你巩固和澄清你所学到的东西,同时也帮助他人。

这个过程需要时间和耐心。不要被这样的事实所欺骗,研究论文只有 5-10 页长,你可以在一个小时内读完所有的单词。一篇研究论文是大量努力和时间的浓缩版——通常由一群人完成。不要期望在一天内掌握这些概念。相反,专注于投入理解的工作。例如,你可以设定一个目标,每天花 30 分钟更好地理解文章。不要强调整个过程需要多长时间。只要继续努力,你会发现自己在另一边拥有更多的知识。

这篇文章可以在这里找到。

过度拟合、欠拟合和偏差-方差权衡

原文:https://towardsdatascience.com/overfitting-underfitting-and-the-bias-variance-tradeoff-83b42fb11efb?source=collection_archive---------11-----------------------

通过 Python、numpy 和 scikit-learn 中的一个工作示例来学习这些基本的机器学习概念

Image by The Strategy Guy

过拟合、欠拟合和偏差-方差权衡是机器学习中的基本概念。如果用于拟合模型的训练数据的性能明显好于模型训练过程中测试集的性能,则模型是过拟合。例如,训练数据的预测误差可能明显小于测试数据的预测误差。比较这两个数据集之间的模型性能指标是为了训练和测试而拆分数据的主要原因之一。通过这种方式,可以评估模型对新的、未知数据的预测能力。

当一个模型过度拟合训练数据时,它被称为具有高方差。考虑这一点的一种方式是,无论训练数据中存在什么样的可变性,模型都已经很好地“学习”了这一点。事实上,太好了。具有高方差的模型很可能已经学习了训练集中的噪声。噪声由数据特征(自变量)和响应(因变量)中的随机波动或偏离真实值组成。噪声会模糊特征和响应变量之间的真实关系。几乎所有真实世界的数据都是有噪声的。

如果在训练集中有随机噪声,那么在测试集中也可能有随机噪声。但是随机波动的具体值会和训练集的不同,因为毕竟噪声是随机的。该模型无法预测测试集的新的、看不见的数据的波动。这就是过度拟合模型的测试性能低于训练性能的原因。

在下列情况下,过度拟合的可能性更大:

  • 相对于样本(观察)的数量,有大量的特征可用。特征越多,发现特征和响应之间虚假关系的机会就越大。
  • 使用复杂的模型,例如深度决策树或神经网络。像这样的模型有效地设计了它们自己的特征,并且有机会开发关于特征和响应之间关系的更复杂的假设,使得过度拟合更有可能。

在光谱的另一端,如果模型没有很好地拟合训练数据,这被称为欠拟合,并且该模型被称为具有高偏差。在这种情况下,就所使用的模型的特征或类型而言,模型可能不够复杂。

让我们通过将多项式模型拟合到 Python 中的合成数据,来检查欠拟合、过拟合以及介于两者之间的理想状态的具体示例。下面的代码可以在 Jupyter 笔记本中运行,以生成此处显示的结果和图表。

*#Import packages* import numpy **as** np *#numerical computation* import matplotlib.pyplot **as** plt *#plotting package
#Next line helps with rendering plots* **%**matplotlib inline
import matplotlib **as** mpl *#additional plotting functionality*

多项式模型的欠拟合和过拟合

首先,我们创建合成数据。我们:

  • 在区间[0,11]上随机选择 20 个点。这包括 0,但不包括 11。我们还对它们进行排序,使它们按顺序排列,这将有助于您创建一个线图(这里我们只做一个散点图)。
  • 对它们进行二次变换,并添加一些噪声:y=(-x+2)(x-9)+ϵ,其中ϵ是均值为 0、标准差为 3 的正态分布噪声

然后我们做一个数据散点图。

np**.**random**.**seed(seed**=**9)
n_points **=** 20
x **=** np**.**random**.**uniform(0, 11, n_points)
x **=** np**.**sort(x)
y **=** (**-**x**+**2) ***** (x**-**9) **+** np**.**random**.**normal(0, 3, n_points)mpl**.**rcParams['figure.dpi'] **=** 400
plt**.**scatter(x, y)
plt**.**xticks([])
plt**.**yticks([])
plt**.**ylim([**-**20, 20])

这看起来像抛物线的形状,正如对 x 的二次变换所预期的那样。然而,我们可以看到,事实上并不是所有的点都完美地位于抛物线上。

在我们的合成示例中,我们知道数据生成过程:响应变量 y 是特征 x 的二次变换。一般来说,在建立机器学习模型时,数据生成过程是未知的。取而代之的是,提出几个候选特征,提出一个模型,并探索这些特征和这个模型如何解释数据。

在这种情况下,我们可能会绘制数据,观察明显的二次关系,并使用二次模型。然而,为了说明欠拟合模型,这些数据的线性模型看起来像什么?

我们可以用 numpy 的polyfit拟合一个 1 次多项式模型,换句话说,一个线性模型:

lin_fit **=** np**.**polyfit(x, y, 1)
lin_fit>>array([ 0.44464616, -0.61869372])

这就产生了这些数据的最佳拟合线的斜率和截距。我们把它画出来,看看它是什么样子。我们可以使用拟合线性模型得到的斜率和截距来计算要素的线性变换,再次使用 numpy,这次是使用polyval函数。我们称之为“欠拟合模型”。

cmap **=** mpl**.**cm**.**get_cmap('tab10')plt**.**scatter(x, y, label**=**'Data', color**=**cmap(0))
plt**.**plot(x, np**.**polyval(lin_fit, x), label**=**'Underfit model', color**=**cmap(1))plt**.**legend(loc**=**[0.17, 0.1])
plt**.**xticks([])
plt**.**yticks([])
plt**.**ylim([**-**20, 20])

看起来不太合适,不是吗!

现在让我们想象我们有许多可用的特性,那就是 x 的多项式变换,具体来说就是 xx 、… x ⁵.相对于我们拥有的样本数量(20),这将是大量的特征。同样,在“现实生活”中,我们可能不会考虑具有所有这些特征的模型,因为通过观察我们可以看到,二次模型或二次多项式可能就足够了。然而,确定理想的特征并不总是那么简单。我们的示例用来展示当我们非常清楚地使用太多特性时会发生什么。

让我们做一个 15 次多项式拟合:

high_poly_fit **=** np**.**polyfit(x, y, 15)
high_poly_fit>>array([ 1.04191511e-05, -7.58239114e-04,  2.48264043e-02, -4.83550912e-01,
        6.24182399e+00, -5.63097621e+01,  3.64815913e+02, -1.71732868e+03,
        5.87515347e+03, -1.44598953e+04,  2.50562989e+04, -2.94672314e+04,
        2.21483755e+04, -9.60766525e+03,  1.99634019e+03, -1.43201982e+02])

这些是这个模型中从 1 到 15 的所有幂的系数,以及截距。请注意系数的标度差异很大:一些接近于零,而另一些则相当大(绝对值)。让我们也画出这个模型。首先,我们在我们的 x 值范围内生成大量均匀分布的点,这样我们不仅可以看到用于模型训练的特定值的模型,还可以看到中间值的模型。

plt**.**scatter(x, y, label**=**'Data', color**=**cmap(0))
plt**.**plot(x, np**.**polyval(lin_fit, x), label**=**'Underfit model', color**=**cmap(1))curve_x **=** np**.**linspace(0,11,333)plt**.**plot(curve_x, np**.**polyval(high_poly_fit, curve_x),
         label**=**'Overfit model', color**=**cmap(2))plt**.**legend(loc**=**[0.17, 0.1])
plt**.**xticks([])
plt**.**yticks([])
plt**.**ylim([**-**20, 20])

这是一个经典的过度拟合案例。过度拟合模型几乎完美地通过了所有的训练数据。然而,很容易看出,对于介于两者之间的值,过拟合模型看起来不像是数据生成过程的真实表示。相反,过拟合模型已经适应了训练数据的噪声。这符合上面给出的高方差的定义。

在最后一张图中,您可以看到高方差的另一种定义:输入 x 的小变化会导致输出 y 的大变化。输入和输出变化之间的这种关系是人们谈论机器学习模型差异的另一种方式。

您还可以想象,如果我们使用相同的二次函数y=(x+2)(x-9)生成一个新的、更大的合成数据集,但是根据我们上面使用的相同分布添加新的随机生成的噪声,然后随机采样 20 个点并拟合高次多项式,则最终的模型看起来会有很大不同。它将几乎完美地通过这些新的噪声点,并且 15 次多项式的系数将非常不同,从而允许这种情况发生。对 20 个点的不同样本重复这一过程,将继续导致高度可变的系数估计。换句话说,用于模型训练的数据样本之间的系数会有很大的差异。这是高方差模型的另一种定义。

使用我们的合成数据,因为在这种情况下我们知道数据生成过程,我们可以看到二次多项式拟合与欠拟合和过拟合模型相比看起来如何。

plt**.**scatter(x, y, label**=**'Data', color**=**cmap(0))
plt**.**plot(x, np**.**polyval(lin_fit, x), label**=**'Underfit model', color**=**cmap(1))
plt**.**plot(curve_x, np**.**polyval(high_poly_fit, curve_x),
         label**=**'Overfit model', color**=**cmap(2))plt**.**plot(curve_x, np**.**polyval(np**.**polyfit(x, y, 2), curve_x),
         label**=**'Ideal model', color**=**cmap(3))plt**.**legend(loc**=**[0.17, 0.1])
plt**.**xticks([])
plt**.**yticks([])
plt**.**ylim([**-**20, 20])

这还差不多。但是,在现实世界中,当我们不使用虚构的数据,并且不知道数据生成过程时,我们该怎么办呢?有许多机器学习技术来处理过度拟合。其中最受欢迎的是正规化。

岭回归正则化

为了展示正则化如何减少过度拟合,我们将使用 scikit-learn 包。首先,我们需要手动创建多项式要素。虽然上面我们只需告诉 numpy 对数据拟合 15 次多项式,但这里我们需要手动创建特征 xx 、… x ⁵,然后拟合线性模型以找到它们的系数。Scikit-learn 使使用PolynomialFeatures创建多项式特征变得容易。我们只是说,我们想要 15 度的多项式特性,没有偏差特性(截距),然后通过我们的数组整形为一列。

from sklearn.preprocessing import PolynomialFeatures
poly **=** PolynomialFeatures(degree**=**15, include_bias**=**False)
poly_features **=** poly**.**fit_transform(x**.**reshape(**-**1, 1))
poly_features**.**shape>>(20, 15)

我们得到 15 列,其中第一列是 x ,第二列是 x 等等。现在我们需要确定这些多项式特征的系数。上面,我们通过使用 numpy 来找到为训练数据提供最佳拟合的系数。然而,我们看到这导致了过度拟合模型。这里,我们将把这些数据传递给用于岭回归的例程,这是一种正则化回归。这里不详细介绍,正则化回归的工作原理是找到最适合数据的系数,同时限制系数的大小

这样做的效果是对数据的拟合稍差,换句话说,模型具有更高的偏差。但是,目标是避免拟合随机噪声,从而消除高方差问题。因此,我们希望用一些方差换取一些偏差,以获得信号而非噪声的模型。

我们将使用 scikit-learn 中的Ridge类来进行岭回归。

from sklearn.linear_model import Ridgeridge **=** Ridge(alpha**=**0.001, fit_intercept**=**True, normalize**=**True,
                        copy_X**=**True, max_iter**=**None, tol**=**0.001,
                        random_state**=**1)

在实例化Ridge类时,有许多选项需要设置。很重要的一个就是alpha。这控制了应用正则化的程度;换句话说,系数幅度受到多大程度的惩罚,并保持接近于零。我们将使用我已经找到的alpha的值,只是为了说明正则化的效果。一般来说,选择alpha的程序是通过检查验证集的模型性能或使用交叉验证程序来系统地评估一系列值,以确定哪一个值有望在未知测试集上提供最佳性能。alpha是一个模型超参数,这将是超参数调整的过程。

我们为Ridge指定的其他选项表明我们想要拟合截距(因为我们在生成PolynomialFeatures时没有包括截距),在模型拟合之前将特征归一化到相同的比例,这是必要的,因为系数将以相同的方式受到惩罚,以及其他一些选项。我在这里掩饰这些细节,尽管你可以参考 scikit-learn 文档,以及我的,以获得关于正则化以及超参数调整的更多信息。

现在,我们继续使用多项式特征和响应变量来拟合岭回归。

ridge**.**fit(poly_features, y)>>Ridge(alpha=0.001, copy_X=True, fit_intercept=True, max_iter=None,
   normalize=True, random_state=1, solver='auto', tol=0.001)

与上面通过用 numpy 拟合多项式得到的值相比,拟合系数的值看起来像什么?

ridge**.**coef_>>array([ 8.98768521e+00, -5.14275445e-01, -3.95480123e-02, -1.10685070e-03,
        4.49790120e-05,  8.58383048e-06,  6.74724995e-07,  3.02757058e-08,
       -3.81325130e-10, -2.54650509e-10, -3.25677313e-11, -2.66208560e-12,
       -1.05898398e-13,  1.22711353e-14,  3.90035611e-15])

我们可以看到,与多项式拟合相比,正则化回归的系数值相对较小。这就是正则化的工作方式:将系数值“缩小”到零。由于这个原因,正则化也可以被称为收缩

让我们在上面使用的大量均匀分布的点curve_x上获得预测值y_pred,用于绘图。首先,我们需要为所有这些点生成多项式特征。

poly_features_curve **=** poly**.**fit_transform(curve_x**.**reshape(**-**1, 1))
y_pred **=** ridge**.**predict(poly_features_curve)

我们将从图中移除欠拟合模型,并添加正则化模型。

plt**.**scatter(x, y, label**=**'Data', color**=**cmap(0))
plt**.**plot(curve_x, np**.**polyval(high_poly_fit, curve_x),
         label**=**'Overfit model', color**=**cmap(2))
plt**.**plot(curve_x, np**.**polyval(np**.**polyfit(x, y, 2), curve_x),
         label**=**'Ideal model', color**=**cmap(3))plt**.**plot(curve_x, y_pred,
         label**=**'Regularized model',color**=**cmap(4), linestyle**=**'--')plt**.**legend(loc**=**[0.17, 0.1])
plt**.**xticks([])
plt**.**yticks([])
plt**.**ylim([**-**20, 20])

正则化模型看起来类似于理想模型。这表明,即使我们不知道数据生成过程,正如我们在现实世界的预测建模工作中通常不知道的那样,当大量候选特征可用时,我们仍然可以使用正则化来减少过度拟合的影响。

但是,请注意,正则化模型不应用于外推。我们可以看到,正则化模型开始向图的右侧增加。应该怀疑这种增加,因为在训练数据中没有任何东西表明这是可以预期的。这是一个普遍观点的例子,即不推荐在训练数据范围之外外推模型预测。

正则化对模型测试性能的影响

用方差换取偏差的目标是提高模型在未知测试数据上的性能。让我们以生成训练数据的相同方式生成一些测试数据,看看我们是否达到了这个目标。我们重复上面用于生成 xy=(x+2)(x−9)+ϵ的过程,但是使用不同的随机种子。这导致相同间隔上的不同点 x 和来自相同分布的不同随机噪声ϵ,为响应变量 y 创建新值,但是来自相同的数据生成过程。

np**.**random**.**seed(seed**=**4)
n_points **=** 20
x_test **=** np**.**random**.**uniform(0, 11, n_points)
x_test **=** np**.**sort(x_test)
y_test **=** (**-**x_test**+**2) ***** (x_test**-**9) **+** np**.**random**.**normal(0, 3, n_points)

我们还将定义一个 lambda 函数,以均方根误差(RMSE)来衡量预测误差。

RMSE **=** **lambda** y, y_pred: np**.**sqrt(np**.**mean((y**-**y_pred)******2))

我们的第一个模型(拟合训练数据的多项式)的 RMSE 是什么?

y_train_pred **=** np**.**polyval(high_poly_fit, x)
RMSE(y, y_train_pred)>>1.858235982416223

新生成的测试数据的 RMSE 如何?

y_test_pred **=** np**.**polyval(high_poly_fit, x_test)
RMSE(y_test, y_test_pred)>>9811.219078261804

测试误差远大于该模型的训练误差,这是过度拟合的明显迹象。正则化模型比较怎么样?

y_train_pred **=** ridge**.**predict(poly_features)
RMSE(y, y_train_pred)>>3.235497045896461poly_features_test **=** poly**.**fit_transform(x_test**.**reshape(**-**1, 1))
y_test_pred **=** ridge**.**predict(poly_features_test)
RMSE(y_test, y_test_pred)>>3.5175193708774946

虽然正则化模型比多项式拟合具有稍高的训练误差(较高的偏差),但是测试误差得到了极大的改善。这显示了如何利用偏差-方差权衡来提高模型预测能力。

结论

这篇文章通过 Python 和 scikit-learn 中的一个示例说明了过拟合、欠拟合和偏差-方差权衡的概念。它扩展了我的书使用 Python 的数据科学项目:使用 Python、pandas 和 scikit-learn 的成功数据科学项目的案例研究方法中的一个部分。要更深入地解释正则化如何工作,如何使用交叉验证进行超参数选择,以及这些和其他机器学习技术的实践,请查看这本书,您可以在亚马逊上找到,这里有 Q & A 和勘误表。

这里是关于偏差和方差的一些最终想法。

偏差和方差的统计定义:这篇文章关注了偏差和方差的直观机器学习定义。还有更正式的统计定义。参见本文档中对方差分解偏差的数学表达式的推导,以及Hastie 等人的统计学习要素中关于偏差-方差分解和权衡的更多讨论。

用更多数据应对高方差:在他的 Coursera 课程机器学习中,吴恩达指出,根据大数据基本原理,在一个非常大的数据集上进行训练可以是一种有效的方法来对抗过度拟合。这个想法是,有了足够的训练数据,训练和测试误差之间的差异应该很小,这意味着方差减少。这种基本原理有一个潜在的假设,即特征包含足够的信息来对响应变量进行准确的预测。否则,模型将遭受高偏差(高训练误差),因此低方差将是一个有争议的问题。

一点点过度拟合可能不是问题:测试集上的模型性能通常比训练集上的稍低。我们在上面的正则化模型中看到了这一点。从技术上讲,这里至少有一点过度拟合。然而,这并不重要,因为最好的模型通常被认为是测试分数最高的模型。

原载于 2019 年 5 月 19 日https://www.steveklosterman.com

神经网络中的过拟合与欠拟合以及错误率与复杂性图的比较

原文:https://towardsdatascience.com/overfitting-vs-underfitting-ddc80c2fc00d?source=collection_archive---------7-----------------------

机器学习,Inside AI,深度学习

理解过度拟合和欠拟合的例子和解决方案,以防止它使用早期停止!

!!!克服过度拟合和欠拟合的头痛

在生活中,一个人会犯两种错误。一种是尝试用苍蝇拍杀死哥斯拉。另一个是试图用火箭筒打死一只苍蝇。想用苍蝇拍打死哥斯拉有什么问题?我们把问题过于简单化了。我们正在尝试一个过于简单的解决方案,但行不通。在机器学习中,这叫做 欠拟合

Godzilla with Flyswatter (Underfitting) or Fly with Bazooka (Overfitting)

用火箭筒打死一只苍蝇有什么问题?它过于复杂,当我们可以使用更简单的解决方案时,它会导致糟糕的解决方案和额外的复杂性。在机器学习中,这叫做 过拟合

让我们看看过度拟合和欠拟合在分类问题中是如何发生的。假设我们有以下数据,我们需要对其进行分类。那么,在这里,什么规则会起作用呢?看起来是个简单的问题,对吗?

Dogs vs Not Dogs (Underfitting) — Very Common

右边的是狗,而左边的不是狗。现在,如果我们使用下面的规则呢?我们说右边的是动物,左边的绝不是动物。这个解决方案不太好,对吧?有什么问题?太简单了。它甚至没有得到完整的数据集。看到了吗?它把这只猫分类错了,因为猫是一种动物。这是不合适的。这就像试图用苍蝇拍杀死哥斯拉。有时,我们称之为 偏差引起的误差

Dog specified with Color — Very Specific (Overfitting)

那么,下面的规则呢?我们说右边的是黄色、橙色或灰色的狗,左边的是除了黄色、橙色或灰色以外的任何颜色的狗。从技术上讲,这是正确的,因为它正确地对数据进行了分类。有一种感觉是,我们说得太具体了,因为只说狗而不说狗就已经完成了工作。但是这个问题比较概念化吧?这里怎么能看出问题呢?一种方法是引入一个测试集。如果我们的测试集是这条狗,那么我们会想象一个好的分类器会把它和其他狗放在右边。但是这个分类器会把它放在左边,因为狗不是黄色、橙色或灰色的。所以,正如我们所说,这里的问题是分类器太具体了。它能很好地拟合数据,但不能一概而论。这太合身了。这就像试图用火箭筒打死一只苍蝇。有时,我们会将过度拟合称为由于方差 导致的 误差。

我喜欢描绘欠适应和过适应的方式是在准备考试的时候。吃不饱,就像学习不够,不及格。好的模式就像学习好,考试好。过度配合就像我们不去学习,而是一个字一个字地背整本教材。我们也许能背诵课本上的任何问题,但我们不能正确地概括和回答考试中的问题。

Data | Red — Negative and Blue — Positive

但是现在,让我们看看这在神经网络中会是什么样子。让我们假设这个数据,同样,蓝色的点标记为正,红色的点标记为负。

Comparison of Underfitting graph vs Perfect Graph vs Overfitting Graph

这里,我们有三只小熊。在中间,我们有一个很好的模型,它很好地拟合了数据。在左边,我们有一个模型,因为它太简单了。它试图用直线拟合数据,但数据比直线更复杂。在右边,我们有一个过度拟合的模型,因为它试图用过于复杂的曲线来拟合数据。请注意,右边的模型与数据非常吻合,因为它不会出错,而中间的模型会出错。但是我们可以看到中间的模型大概会概括的更好。中间的模型将这一点视为噪声,而右边的模型被它弄糊涂了,试图把它喂得太好。

Comparison in terms of Neural Network Architecture

现在中间的模型可能会是一个神经网络,它的架构有点复杂,就像这个一样。左边的这个可能是一个过于简单的架构。例如,由于模型是线性的,因此整个神经网络只有一个指导器。右边的模型可能是一个高度复杂的神经网络,其层数和权重超过了我们的需要。现在有个坏消息。为神经网络找到合适的架构真的很难。我们总是会以像左边这样过于简单的架构或者像右边这样过于复杂的架构结束。

Kids Problem while purchasing Pants 🤣🤣🤣

现在的问题是,我们该怎么办?这就像试着穿上一条裤子。如果我们找不到我们的尺寸,我们是买大一点的裤子还是小一点的裤子?好吧,看起来穿稍微大一点的裤子,然后试着买一条腰带或者其他能让裤子更合身的东西,也没那么糟糕,这就是我们要做的。我们会在过于复杂的模型上犯错误,然后我们会应用某些技术来防止过度拟合。

Training with Different Epoch

那么,让我们从上次停止的地方开始,也就是说,我们有一个复杂的网络体系结构,它可能比我们需要的更复杂,但我们需要接受它。那么,我们来看看训练的过程。我们从她第一个时期的随机权重开始,我们得到了这样一个模型,它犯了很多错误。

现在,当我们训练时,假设 20 个时代,我们得到了一个相当好的模型。但是,假设我们继续进行 100 个纪元,我们会得到更好地符合数据的东西,但是我们可以看到这开始过度拟合。如果我们追求更多,比如说 600 个时代,那么这个模型就非常不合适了。

我们可以看到蓝色区域几乎是围绕着蓝色点的一堆圆圈。这非常符合训练数据,但它会可怕地泛化。想象在蓝色区域有一个新的蓝点。这个点最有可能被归类为红色,除非它非常接近蓝色点。

Error Comparision

所以,让我们试着通过添加一个测试集来评估这些模型,比如这些点。让我们画出每个时期的训练集和测试集中的误差图。对于第一个时期,由于模型是完全随机的,因此它严重地错误分类了训练集和测试集。因此,训练误差和测试误差都很大。

我们可以把它们画在这里。对于 20 epoch,我们有一个更好的模型,它非常适合训练数据,并且在测试集中表现也很好。因此,这两个误差都相对较小,我们将把它们画在这里。

对于 100 纪元,我们看到我们开始过度适应。该模型与数据非常吻合,但它开始在测试数据中出错。我们意识到训练误差在不断减小,但是测试误差开始增加,所以我们把它们画在这里。

现在,对于 600 年代来说,我们严重过剩。我们可以看到,训练误差非常小,因为数据非常适合训练集,但模型在测试数据中犯了大量错误。因此,测试误差很大。我们把它们画在这里。

现在,我们绘制连接训练和测试误差的曲线。因此,在这个图中,很明显,当我们停止欠拟合并开始过拟合时,训练曲线总是在下降,因为随着我们训练模型,我们对训练数据的拟合越来越好。由于模型不精确,在欠拟合时测试误差较大。然后它随着模型的推广而减少,直到它到达一个 最小点——金发女孩点 。最后,一旦我们通过了那个点,模型又开始过度拟合,因为它停止概括,而只是开始记忆训练数据。这个图叫做模型 复杂度图

Model Complexity Graph

在 Y 轴上,我们可以测量误差,在 X 轴上,我们可以测量模型的复杂性。在这种情况下,它是历元的数量。正如你所看到的,在左边我们有很高的测试和训练误差,所以我们不适合。在右边,我们有一个高测试误差和低训练误差,所以我们过度拟合。在中间的某个地方,我们有我们的快乐金发点。所以,这决定了我们将要使用的历元数。

总之,我们要做的是,下降,直到测试误差停止下降并开始增加。那一刻,我们停下来。这种算法被称为 提前停止 ,被广泛用于训练神经网络。

参考资料:

[1] Udacity 深度学习课程—过度适应与欠适应视频

[2] Udacity 深度学习课程——提前停止视频

请访问我的网站:【http://www.khushpatel.com

Python 中的重载运算符

原文:https://towardsdatascience.com/overloading-operators-in-python-2e24da0d36d7?source=collection_archive---------20-----------------------

…还有一点关于一般的超载(但我会尽量不超载你)

在学习 Python 编程的过程中,我们大多数人都在相对较早的时候遇到了运算符重载背后的概念。但是,像 Python(和其他语言)的大多数方面一样;就这一点而言,几乎是任何事情),学习重载操作符必然与其他概念联系在一起,这既扩大了主题的范围,又在某种程度上混淆了我们个人学习曲线的路线。考虑到这一点,我将尽量不扯入太多学习 Python 的其他领域——然而,一些面向对象编程很自然地与之相关;虽然我想把重点放在重载操作符上,但是重载函数这个更广泛、更复杂的话题至少也值得一提。

在编程的上下文中,重载指的是函数操作符根据传递给函数的参数或操作符作用的操作数以不同方式运行的能力。在 Python 中,操作符重载(也称为“操作符特别多态性”)尤其是一种“语法糖”形式,它能够以强大而方便的方式将操作符的操作指定为特定类型的中缀表达式。换句话说,操作符重载赋予操作符超出其预定义操作含义的扩展含义。****

Operator Overload examples for + and *

Python 中经典的运算符重载示例是加号,它是一个二元(即两个操作数)运算符,不仅将一对数字相加,还将一对列表或字符串连接起来。星号同样被重载,不仅作为数字的乘数,还作为列表或字符串的重复操作符。比较运算符(如>、==或!=)表现出类似的行为;然而,对于所有这些重载操作符,我们作为 Python 用户在考虑类型检查时应该稍微小心一些。正如麻省理工学院的 John Guttag 教授提醒我们的那样,“Python 中的类型检查不如其他一些编程语言(如 Java)中的强,但在 Python 3 中比在 Python 2 中要好。例如,什么是< should mean when it is used to compare two strings or two numbers. But what should the value of ‘4’❤️就很清楚了?Python 2 的设计者相当武断地决定它应该是 False,因为所有数值都应该小于 str 类型的所有值。Python 3 和大多数其他现代语言的设计者认为,既然这样的表达式没有明显的意义,它们应该生成一条错误消息。”[2]

这很好,但是如果一个操作符作为操作数用于一个或多个用户定义的数据类型(例如,来自一个创建的类),该怎么办呢?在这种情况下——比方说,试图添加一对(x,y)坐标,如此处所示——编译器将抛出一个错误,因为它不知道如何添加这两个对象。而且,虽然重载只能在 Python 中现有的操作符上完成,但是有一些操作符,以及每个操作符调用的相应的魔法方法;使用这些相应的方法,我们可以创建/访问/编辑它们的内部工作方式(见文章末尾)。

就像这个快速发展的领域中的其他术语一样,对于如何称呼它们似乎没有达成共识——它们通常被称为“魔法方法”——之所以称为“魔法”,是因为它们没有被直接调用——这似乎是最接近标准的,也许是因为替代的“特殊方法”听起来,嗯,不是那么特殊。有些人预示着一个更有趣的名字——“dunder methods”,作为“双下划线方法”(即“dunder-init-dunder”)的简写。总之,它们是一种特殊类型的方法,并且只限于与操作符相关联的方法(例如 init()call() )。其实有不少。

随便说个题外话——印刷有自己关联的魔法, str() 。如果我们只使用一个 init() 来打印普通的 Point 类,我们将得到上面所示的不太用户友好的输出。

str() 方法添加到 Point 类中可以解决这个问题。有趣的是, format() 也调用了与 print() 相同的 str() 方法。

A simple * overloading example using our cohort’s nickname (3x like the Thundercats, Schnarf Schnarf)

事实证明,在学习 Python 时,使用(x,y)坐标遍历重载、方法和其他 Python 概念的例子是一种常见的实践,可能是因为我们可以用像坐标点这样数学上熟悉的东西来创建自己的类。由此,可以为用户定义的类创建许多有用的神奇方法,并使用它们来重载运算符。

运算符重载的一个值得注意的方面是每个操作数相对于其运算符的位置。以小于操作符<为例——它为第一个(或左/前)操作数调用 lt() 方法。换句话说,这个表达 x < yx.lt(y) 的简写;如果第一个操作数是用户定义的类,它需要有自己对应的 lt() 方法,才能使用<。这看起来可能有点麻烦,但实际上它为设计一个类增加了一些便利的灵活性,因为我们可以定制任何操作符的函数为一个类做什么。“除了为编写使用<的中缀表达式提供语法上的便利,”Guttag 教授指出,“这种重载提供了对使用 lt() 定义的任何多态方法的自动访问。内置方法 sort 就是这样一种方法。【②】

鉴于第一个和第二个操作数的这种区别,Python 还为我们提供了一组反向方法,比如 radd()、rsub()、rmul() 等等。请记住,只有当左操作数不支持相应的操作时,才会调用这些反向方法。操作数属于不同的类型。一个叫 Rhomboid 的 Pythonista redditor 解释得比我更好,所以我谦恭地遵从他的观点:

有人能给我简单解释一下 radd 吗?我看了文档,我不理解它。

h/t to Rhomboid for the elucidating explanation

not like this.

like this.

最后一个警告——虽然我们拥有这种灵活性很棒,但我们应该记住操作者的初衷。比如 len()一般理解为用来返回一个序列的长度;所以重载这个方法需要返回一个整数(否则会返回一个 TypeError)。

…现在让我们来短暂地探索一下超载功能的更广阔、更汹涌的水域。根据维基百科,这属于“用不同的实现创建多个同名函数的能力。”函数可能因其参数的 arity 或类型而有所不同。这个概念在其他语言(C++,Java)中更有用,但并不真正符合 Pythonic 的“做事方式”,正如 stackoverflow 上的一些人所指出的:

如何在 Python 中使用方法重载?

…在这个问题上还有一个有用的线索:

one more relevant question…

…and reply

显然,Python 以不同的方式处理这种情况。也就是说,阅读方法重载帮助我理解了一个重要的 Pythonic 概念:多态性。这被定义为对不同的底层形式利用相同的接口的能力,例如数据类型。多态是 Python 中类的一个特征,因为它允许在许多类或子类中使用通常命名的方法,这进一步使函数能够使用属于一个类的对象,就像它使用属于另一个类的对象一样,完全不需要知道不同类之间的区别。[3] .这允许鸭类型化,动态类型化的一个特例,它使用多态性的特征(包括后期绑定动态分派)来评估对象类型。

从这里开始,这一切都变成了单个对多个,静态对动态的分派,这超出了我目前的理解水平。所以我暂时先放一放。

来源:

[1]https://stack abuse . com/overloading-functions-and-operators-in-python/

[2]约翰·古塔格..使用 Python 的计算和编程介绍(麻省理工学院出版社)。麻省理工学院出版社。Kindle 版。

[3]https://www . digital ocean . com/community/tutorials/how-to-apply-polymorphism-to-classes-in-python-3

【4】(标题图片)https://www . osgpaintball . com/event/operation-霸王-场景-彩弹/

https://www . Reddit . com/r/learn python/comments/3c vgpi/can _ someone _ explain _ radd _ to _ me _ in _ simple _ terms _ I/

[## python 类特殊方法或神奇方法列表——微型棱锥体

python 类特殊方法或神奇方法的列表。神奇的功能允许我们覆盖或添加默认的…

micropyramid.com](https://micropyramid.com/blog/python-special-class-methods-or-magic-methods/) [## Python 运算符重载

Python 中什么是运算符重载?Python 运算符适用于内置类。但是同一个操作员表现…

www.programiz.com](https://www.programiz.com/python-programming/operator-overloading) [## Python 教程:魔术方法

所谓的魔法方法与巫术无关。您已经在我们的前几章中看到了它们…

www.python-course.eu](https://www.python-course.eu/python3_magic_methods.php) [## Python 中的重载函数和运算符

什么是超载?在编程的上下文中,重载指的是一个函数或一个操作符…

stackabuse.com](https://stackabuse.com/overloading-functions-and-operators-in-python/) [## 运算符重载

在计算机程序设计中,操作符重载,有时称为操作符特别多态,是…

en.wikipedia.org](https://en.wikipedia.org/wiki/Operator_overloading) [## Python 操作符重载和 Python 魔术方法

在本 Python 教程中,我们将讨论 Python 运算符重载,运算符重载的例子…

数据-天赋.培训](https://data-flair.training/blogs/python-operator-overloading/) [## 自定义 Python 类中的运算符和函数重载——真正的 Python

您可能想知道同一个内置操作符或函数如何为不同的对象显示不同的行为…

realpython.com](https://realpython.com/operator-function-overloading/) [## 如何在 Python 中使用方法重载?

我正在尝试用 Python 实现方法重载:class A:def stack overflow(self):print ' first method ' def…

stackoverflow.com](https://stackoverflow.com/questions/10202938/how-do-i-use-method-overloading-in-python) [## Python 函数重载

我知道 Python 不支持方法重载,但是我遇到了一个问题,我似乎无法用…

stackoverflow.com](https://stackoverflow.com/questions/6434482/python-function-overloading) [## Python 中的函数重载

最近在 Practo 的一次谈话中,我发现有些人抱怨说,我们没有……

medium.com](https://medium.com/practo-engineering/function-overloading-in-python-94a8b10d1e08)

免责声明:错误、曲解、滥用概念和想法都是我的,并且只属于我。

【概述】:让集成学习变得简单

原文:https://towardsdatascience.com/overview-ensemble-learning-made-simple-d4ac0d13cb96?source=collection_archive---------21-----------------------

Source

当你想购买一部手机的时候,你会直接走到商店然后在网上转然后挑选任何一部手机吗?最常见的做法是浏览互联网上的评论,比较不同的型号,规格,功能和价格。你可能会向你的同伴询问购买建议,并以结论结束。总的来说,你没有直接得出结论,而是考虑了其他来源的选择。

在本文中,我将向您介绍机器学习中的一种称为“集成学习”的技术,以及使用这种技术的算法。

内容列表

  1. 多样的算法
  2. 不同实例上每个预测器的算法相同
  3. 相同的算法对不同的特性集&实例
  4. 升压
  5. 堆叠

集成模型的思想是训练多个模型,每个模型的目标是预测或分类一组结果。

集成学习背后的主要原理是将弱学习者分组在一起以形成一个强学习者。

集成学习:集成是一组被训练并用于预测的预测器

集成算法:集成算法的目标是将几个基础估计器的预测与给定的学习算法结合起来,以提高单个估计器的鲁棒性

用训练数据的子集训练一组决策树。使用个别树的预测,预测得到最大值的类。一些投票。这样的决策树集合——随机森林

集成学习方法通常区分如下

集成学习的类型

a.)一套多样的 算法

基于我们的目标(回归/分类),我们选择一组不同的模型,训练它们,汇总这些模型的结果并得出结论。这是使用投票分类器完成的。

Source: Hands-on machine learning with sci-kit-learn and tensorflow

硬投票分类器:聚合各个分类器的预测,预测得到票数最多的类。只有当分类器相互独立时,集成才能比单个低性能分类器表现更好。但是他们接受了相同的数据训练

Source: Hands-on machine learning with sci-kit-learn and tensorflow

软投票分类器:如果所有分类器都能够估计类的概率(predict_proba()方法),那么预测具有最高类概率的类,在单个分类器上平均。软投票通常比硬投票表现更好。软投票考虑每个分类器的确定程度

现在让我们试着用一种简单的方式来理解这一点。

举例:假设你有 3 个分类器(1,2,3),两个类(A,B),经过训练,你在预测单个点的类。

硬投票

预测:

分类器 1 预测类别 A

分类器 2 预测 B 类

分类器 3 预测 B 类

2/3 分类器预测 B 类,所以B 类是集成决策

软投票

预测(与之前的例子相同,但现在是根据概率。此处仅显示 A 类,因为问题是二进制的):

分类器 1 以 99%的概率预测类别 A

分类器 2 以 49%的概率预测类别 A

分类器 3 以 49%的概率预测类别 A

跨分类器属于 A 类的平均概率为(99 + 49 + 49) / 3 = 65.67%。因此,A 类是系综决策

b.) 不同情况下每个预测器的算法相同

到目前为止,我们已经看到了在相同实例上训练的不同算法。现在让我们看看如何使用不同的实例使用相同的算法进行分类。

如果样本选择是通过替换- 装袋 (引导汇总)完成的

如果样品选择完成而没有替换— 粘贴

只有 bagging 允许为同一个预测器对训练实例进行多次采样

一旦模型被训练,集合将聚集来自所有模型的预测。

聚集-模式:分类

聚合-平均值:回归

聚合减少了偏倚和方差。

在 Sci-Learn 中,为了执行 bagging,我们使用 BaggingClassifier():如果基本分类器有 predict_proba()方法,则自动执行软投票。

Bagging —较高的偏差,低方差结果。首选整体装袋

c.) 同一算法上的一组多样特性&实例

到目前为止,我们已经看到使用采样数据训练模型。现在是时候根据所选的特性训练模型了。

随机面片和随机子空间

在 Bagging 分类器()中,用于实例采样和特征采样的参数如下

实例采样— max_samples,引导

要素采样-最大要素,引导要素

采样训练实例和特征— 随机补丁方法

保留所有训练实例(即 bootstrap=False 和 max_sam ples=1.0)但采样特征(即 bootstrap_features=True 和/或 max_features 小于 1.0)称为 随机子空间方法

d.)助推

提升是一种集成技术,它试图从多个弱分类器中创建一个强分类器。这是一个循序渐进的过程,每个后续模型都试图修复其前一个模型的错误。

AdaBoost(自适应增强),梯度增强。

AdaBoost:在每个模型预测的最后,我们最终提高了错误分类实例的权重,以便下一个模型对它们做得更好,等等。顺序学习的一个主要缺点是该过程不能并行化,因为预测器可以一个接一个地训练。如果 AdaBoost 集成过拟合训练集,则减少估计器的数量或调整基本估计器

Source: Hands-on machine learning with sci-kit-learn and tensorflow

AdaBoost 通过将(每棵树的)权重相加乘以(每棵树的)预测来进行新的预测。显然,权重较高的树将有更大的权力来影响最终决策

【GBM】

梯度增强直接从误差——残差中学习,而不是更新数据点的权重。

下面是梯度推进决策树(GBDT)的 Python 代码

Source: Hands-on machine learning with sci-kit-learn and tensorflow

梯度推进通过简单地将(所有树的)预测相加来进行新的预测

e.)堆叠(堆叠概括

堆叠背后的主要思想是,与其使用琐碎的函数(如硬投票)来聚合集合中所有预测者的预测,不如我们训练一个模型来执行这种聚合。

集成对新实例执行回归任务。底部三个预测器中的每一个都预测不同的值(3.1、2.7 和 2.9),然后最终预测器(称为混合器或元学习器)将这些预测作为输入,并做出最终预测(3.0)

结论:

总的来说,集成学习是一种用于提高模型预测能力/估计准确性的强大技术。

请在下面留下任何评论、问题或建议。

谢谢大家!

快乐学习!

R 中 40 个数学函数概述

原文:https://towardsdatascience.com/overview-of-40-mathematical-functions-in-r-4b4e138685ff?source=collection_archive---------9-----------------------

Photo by Simone Venturini from Pexels

你是否发现自己在寻找tanh, sigmoid, softmax, ReLU 函数或其他数学函数的样子?即使你实际上应该知道,因为你几天前就已经查过了?那么,你来对地方了!

这个概述是关于什么的?

对于一个定量领域的任何人来说,知道这些函数都是非常有用的。很多时候,我们迷失在求导、积分等细节中。但是我们往往会忘记所有不同函数的物理意义以及它们之间的相互比较:一个函数实际上是什么样子的?

因此,我对想到的最常见的 40 个数学函数做了一个简单的概述。我使用 R 中的curve函数以精简、简单的方式绘制了它们,并按照逻辑上有用的顺序组装它们。

如何创造这些情节?

创造这样的情节非常容易。让我们从一个例子开始:

curve(exp(x), from = -10, to = 10, main = "exp(x)")

打开 RStudio 后,你真正需要做的就是把上面那行代码放到你的控制台里运行。你不需要任何图书馆。这不是很好吗?

提供您想要作为第一参数绘图的功能,例如exp(x)x^33*x+5。您可以快速实现 sigmoid 函数1/(1+exp(-x))、tanh 函数tanh(x)、softmax 函数exp(x)/sum(exp(x))或 ReLU 函数pmax(0, x)等功能。

在那之后,你需要做的就是指定 x 的值,你要为这些值绘制函数 f(x)。您可以通过设置参数fromto来完成此操作。我选择绘制从-10 到+10 的所有函数。当然,你也可以选择用main指定一个标题。

给我看看 40 个数学函数!

您可以在下面的图中看到显示的函数。共有 4 个部分,每个部分有 10 个功能。通过在 RStudio 中运行它们,可以用相应的 Github Gists 创建所有的部分。

第一节

Functions 1–10

第二节

Functions 11–20

第三节

Functions 21–30

第四节

Functions 31–40

参考

请在 Github 上找到源代码:

  • 点击下载 PDF
  • 下载 R Markdown(在 RStudio 中创建 PDF)这里

如果需要增加功能,期待您的反馈!提前多谢了。

工业用自动化库综述

原文:https://towardsdatascience.com/overview-of-automl-from-pycon-jp-2019-c8996954692f?source=collection_archive---------15-----------------------

PyCon JP 2019 的自动化机器学习技术和库的简要总结

Photo by Franck V. on Unsplash

PyCon JP 2019 于 2019/9/16~ 2019/9/17 举办,为期两天。我会发布一些我感兴趣的讲座的帖子。

作为一名 NLP 工程师,很高兴看到一些关于机器学习的讲座。这篇文章是来自柴田正史的汽车演讲的简短英文摘要。你可以在这里找到日文的幻灯片。

自动化水平

Jeff Dean 在 2019 年 ICML 车展上做了一个关于 AutoML 的演讲,他将自动化分为 5 个级别

  1. 手工预测者,什么都不学。
  2. 手工特色,学会预测。自动化超参数优化(HPO)工具,如 Hyperopt、Optuna、SMAC3、scikit-optimize 等。
  3. 手工算法,端到端地学习特征和预测。HPO +一些工具像 featuretools,tsfresh,boruta 等。
  4. 手工什么都没有。端到端地学习算法、特征和预测。自动化算法(模型)选择工具,如 Auto-sklearn、TPOT、H2O、auto_ml、MLBox 等。

自动 Hpyerparametter 优化的两种方法

广泛使用的优化方法有两种,一种是贝叶斯 优化方法,它将根据过去的结果搜索未知的参数范围。一些算法如 TPE,SMAC,GP-EL 等。

An example of using Bayesian optimization on a toy 1D design problem

另一个是在训练过程中停止学习路径,更有效地搜索参数。一些算法像连续减半,超带等等。

paper1 and paper2

蓝点表示训练将继续,红点表示训练将停止。

自动图书馆

我们可以将这些库分为以下两类。

考虑到质量和开发速度,推荐两个库, Optuna 和 scikit-optimize。

自动化特征工程

还有一件事是 TPOT 和 Auto-sklearn 做不到的。因此,我们将特征工程分为两类,特征生成和特征选择。

自动算法(模型)选择

Optuna 可以一起解决现金。

自动算法选择比较。

  • 自动 sklearn
  • TPOT
  • h2o-3
  • 自动 _ 毫升
  • MLBox

paper link

不同任务的推荐选择。

  • 回归任务:自动 sklearn(基于贝叶斯)
  • 分类任务:TPOT(基于遗传算法)

自动神经结构搜索

即使是自动神经架构搜索在学术界也是一个非常热门的话题,但是在工业界还没有得到广泛的应用。

查看我的其他帖子 一个分类查看
GitHub:
bramble Xu LinkedIn:徐亮 博客:bramble Xu

参考

CycleGAN 架构和培训概述。

原文:https://towardsdatascience.com/overview-of-cyclegan-architecture-and-training-afee31612a2f?source=collection_archive---------12-----------------------

0.介绍

生成对抗模型由两个神经网络组成:一个生成器和一个鉴别器。一个 CycleGAN 由 2 个 GAN 组成,总共有 2 个发生器和 2 个鉴别器。

给定两组不同的图像,例如马和斑马,一个生成器将马转换成斑马,另一个生成器将斑马转换成马。在训练阶段,鉴别器在这里检查生成器计算出的图像是真是假。通过这个过程,生成器可以随着各自鉴别器的反馈而变得更好。在 CycleGAN 的情况下,一个发电机从另一个发电机获得额外的反馈。这种反馈确保由生成器生成图像是循环一致的,这意味着在图像上连续应用两个生成器应该产生相似的图像。

训练一个 CycleGAN 非常方便的一点是,我们不需要标记它的训练样本(数据是不成对的)。

1.数据

CycleGAN 的一个训练样本由马的随机图片和斑马的随机图片构成。

2.模型

两个生成器都具有以下架构(除了规范层和激活层) :

Residual Block on the left, all convolutional layer inside it have 256 filters, stride 2 and padding 1.

生成器将大小为 256x256 的图像作为输入,对其进行下采样,然后将其上采样回 256x256,从而创建生成的图像。

至于鉴别器,它们具有以下架构(规范和激活层除外):

鉴别器将大小为 256x256 的图像作为输入,并输出大小为 30x30 的张量。

输出张量的每个神经元(值)保存输入图像的 70×70 区域的分类结果。通常,GANs 的鉴别器输出一个值来指示输入图像的分类结果。通过返回大小为 30x30 的张量,鉴别器检查输入图像的每个 70x70 区域(这些区域相互重叠)是真实的还是虚假的。这样做相当于手动选择这些 70x70 区域中的每一个,并让鉴别器反复检查它们。最后整幅图像的分类结果是 30×30 个值的分类结果的平均值。

3.培养

生成器和鉴别器都使用 Adam 解算器(默认参数)进行优化,它们都具有相同的学习速率(2e-4),并且批处理大小被选择为 1(这意味着这里不能使用批处理规范化,而是使用实例规范化)。

generated images are from a CycleGAN trained during 30 epochs.

G {H- > Z }是将马图像转换成斑马图像的生成器,G {Z- > H }是将斑马图像转换成马图像的生成器。

给定一个训练样本( h,z ),这就是该样本如何更新 CycleGAN 的权重。

  • h, G {H- > Z }生成假 _z 一个假斑马图像。从 z,G{ H->Z}生成 id_z 应该与Z相同
  • z, G {Z- > H}生成 fake_h 一个假马图像。从 h,G{ Z->H }生成应该与 h. 相同的 id_h**
  • fake_z ,G {Z- > H}生成 rec_h 一个与 h 相似的 h 的重建图像。
  • fake_h ,G {H- > Z }生成 rec_z 一个应该类似于 z 的重构图像。

然后,通过最小化跟随损失来更新发电机的权重。在 G {H- > Z }的情况下,可以写成:

where D_z(fake_z)(i,j) is the scalar value at coordinate (i,j) of D_z output tensor.

  • D_z ( fake_z )和 1 之间的均方误差(MSE)。即原图中的最小二乘损失。 D_z 是与 G {H- > Z }关联的鉴别器,如果输入—fake _ Z—看起来像一个真正的斑马 else 0 时,它输出 1 。**

pixel to pixel absolute difference of the two images.

pixel to pixel absolute difference of the two images.

  • id_hh 之间的平均绝对误差(MAE)。即原文中的身份丧失。没有必要包括这种损失,但它通常有助于获得更好的结果。

然后,通过最小化跟随损失来更新鉴别器的权重。在 D_z 的情况下,可以写成:

  • D_z ( fake_z )与 0 之间均方误差(MSE)的一半加上 D_z ( z )与 1 之间 MSE 的一半。

鉴别器的损耗减半。这样做相当于使用 MSE 在每次更新生成器权重两次时更新鉴别器权重一次。

4.结果

复制这些结果的代码可以从 colab 笔记本中获得。

然后,CycleGAN 被训练 200 个周期。在前 100 个时期,学习速率固定为 2e-4,在后 100 个时期,学习速率从 2e-4 到 2e-6 线性退火。下面显示了一些生成的图像。

通常有非常好的结果(左:原始图像,右:生成的图像) :

original images / generated images

但也有失败的情况(左:原始图像,右:生成的图像) :

用于深度学习的图嵌入

原文:https://towardsdatascience.com/overview-of-deep-learning-on-graph-embeddings-4305c10ad4a4?source=collection_archive---------0-----------------------

图形学习和几何深度学习—第 1 部分

一定要看一篇 几何深度学习概述先决条件 熟悉机器学习这个小众领域。

关注 我的推特 加入 几何深度学习子编辑 获取空间最新更新。

这里有很多方法可以将机器学习应用于图表。最简单的方法之一是将图表转换成更容易理解的 ML 格式。

图形嵌入是一种方法,用于将节点、边及其特征转换到向量空间(较低的维度)中,同时最大限度地保留图形结构和信息等属性。图表很复杂,因为它们在规模、特性和主题方面会有所不同。

一个分子可以被表示为一个小的、稀疏的、静态的图,而一个社会网络可以被表示为一个大的、密集的、动态的图。最终,这使得很难找到一个银弹嵌入方法。每种方法在不同的数据集上的性能各不相同,但它们是深度学习中使用最广泛的方法。

图形是这个系列的主要焦点,但是如果 3D 成像应用更适合你,那么我推荐Gradient的这篇精彩文章。

嵌入图网络

如果我们将嵌入视为向低维的转换,嵌入方法本身就不是一种神经网络模型。相反,它们是一种在图形预处理中使用的算法,目的是将图形转换成可计算的格式。这是因为图形类型的数据本质上是离散的。

机器学习算法针对连续数据进行调整,因此为什么嵌入总是针对连续向量空间。

正如最近的工作所显示的,有多种方法可以嵌入图,每种方法都有不同的粒度级别。嵌入可以在节点级、子图级执行,或者通过像图遍历这样的策略来执行。这些是一些最受欢迎的方法。

深走— 佩罗齐等人

Deepwalk 并不是这类方法中的第一个,但与其他图形学习方法相比,它是第一个被广泛用作基准的方法之一。Deepwalk 属于使用遍历的图形嵌入技术家族,遍历是图论中的一个概念,它通过从一个节点移动到另一个节点来实现图形的遍历,只要它们连接到一个公共边。

如果用任意的表示向量来表示图中的每个节点,就可以遍历图。可以通过在矩阵中彼此相邻地排列节点表示向量来聚集该遍历的步骤。然后,你可以将表示图形的矩阵输入到一个递归神经网络中。基本上,您可以使用图遍历的截断步长作为 RNN 的输入。这类似于句子中单词向量的组合方式。

DeepWalk 采用的方法是使用以下等式完成一系列随机行走:

目标是估计观察到节点 vi 的可能性,给定在随机行走中到目前为止访问的所有先前节点,其中 Pr() 是概率,φ是表示与图中每个节点 v 相关联的潜在表示的映射函数。

潜在的表现是神经网络的输入。神经网络基于行走过程中遇到哪些节点以及遇到这些节点的频率,可以对节点特征或分类进行预测。

The original graph and it’s embedding (Courtesy of the DeepWalk research team)

用于进行预测的方法是 skip-gram ,就像 Word2vec 架构中的文本一样。DeepWalk 不是沿着文本语料库运行,而是沿着图运行来学习嵌入。该模型可以采用目标节点来预测它的“上下文”,在图的情况下,这意味着它的连通性、结构角色和节点特征。

尽管 DeepWalk 的得分为 O(|V|) 相对高效,但这种方法是直推式,这意味着每当添加新节点时,模型都必须重新训练以嵌入新节点并从中学习。

Node2vec — Grover 等人

你听说过 Word2vec 现在准备… Node2vec

比较流行的图学习方法之一,Node2vec 是最早尝试从图结构化数据进行学习的深度学习方法之一。直觉类似于 DeepWalk 的直觉:

如果你把图中的每个节点像句子中的单词一样嵌入,神经网络可以学习每个节点的表示。

Node2vec 和 DeepWalk 之间的区别很微妙,但是很重要。Node2vec 具有一个行走偏差变量α,它由 pq 参数化。参数 p 优先考虑广度优先搜索(BFS)过程,而参数 q 优先考虑深度优先搜索(DFS)过程。因此,下一步去哪里的决定受到概率 1/ p 或 1/q的影响

Both BFS and DFS are common algorithms in CS and graph theory (Courtesy of Semantic Scholar)

正如可视化所暗示的, BFS 是学习局部邻居的理想选择,而 DFS 更适合学习全局变量。 Node2vec 可以根据任务在两个优先级之间切换。这意味着给定一个图,Node2vec 可以根据参数值返回不同的结果。按照 DeepWalk,Node2vec 还获取 walks 的潜在嵌入,并将其作为神经网络的输入来对节点进行分类。

BFS vs DFS (Courtesy of SNAP Stanford)

实验证明 BFS 更擅长根据结构角色(枢纽、桥梁、离群点等)进行分类。)而 DFS 返回一个更加社区驱动的分类方案。

Node2vec 是斯坦福大学 SNAP 研究小组致力于图形分析的众多图形学习项目之一。他们的许多作品是几何深度学习许多重大进展的起源。

graph 2 vec——纳拉亚南等人

对 node2vec 变体的修改,graph2vec 本质上学习嵌入图的子图。doc2vec 中使用的一个等式证明了这一点,它是一个密切相关的变体,也是本文的灵感来源。

用通俗的英语来说,这个等式可以写成:单词( wj )出现在上下文给定文档( d )中的概率等于文档嵌入矩阵( d~ )的指数乘以单词嵌入矩阵( w~j 是从文档中采样的),除以文档嵌入矩阵的所有指数之和乘以文档中每个单词的单词嵌入矩阵

用 word2vec 来类比,如果一个文档是由句子组成的(句子又是由单词组成的),那么一个图是由子图组成的(子图又是由节点组成的)。

Everything is made of smaller things

这些预定的子图具有由用户指定的设定数量的边。同样,是潜在的子图嵌入被传递到神经网络中用于分类。

【结构化深度网络嵌入】——王等

与以前的嵌入技术不同,SDNE 不使用随机行走。相反,它试图从两个不同的指标中学习:

  • 一阶接近度:如果两个节点共享一条边,则认为它们是相似的(成对相似)
  • 二阶接近度:如果两个节点共享许多相邻节点,则认为它们是相似的

最终目标是捕捉高度非线性的结构。这是通过使用深度自动编码器(半监督)来保持一阶(监督)和二阶(非监督)网络接近度来实现的。

Dimensionality reduction with LE (Courtesy of MathWorld)

为了保持一阶近似性,该模型也是拉普拉斯特征映射的变体,这是一种图形嵌入/维度缩减技术。拉普拉斯特征映射嵌入算法在相似节点在嵌入空间中彼此远离映射时应用惩罚,从而允许通过最小化相似节点之间的空间来进行优化。

通过将 te 图的邻接矩阵传递给无监督自动编码器来保持二阶接近度,该编码器具有内置的重建损失函数,必须最小化该函数。

An autoencoder (Courtesy of Arden Dertat)

一阶邻近损失函数和二阶重建损失函数一起被联合最小化以返回图嵌入。然后通过神经网络学习嵌入。

大规模信息网络嵌入(线)——唐等

行(汤集安等人)明确定义了两个功能;一个用于一阶接近度,另一个用于二阶接近度。在原始研究进行的实验中,二阶近似的表现明显优于一阶,这意味着包含更高阶的近似可能会抵消精度的提高。

LINE 的目标是最小化输入和嵌入分布之间的差异。这是通过使用 KL 散度实现的:

A simple case of KL-divergence minimization

可视化很简单,数学没那么简单。Aurélien Géron 有一个关于这个主题的很棒的视频。另一方面,Géron 也是为数不多的图形学习研究人员之一,在 YouTube 工作期间,他将知识图形和深度学习结合起来,以改善视频推荐。

LINE 为每对节点定义两个联合概率分布,然后最小化分布的 KL 散度。这两种分布分别是邻接矩阵和节点嵌入的点积。KL 散度是信息论和熵中一个重要的相似性度量。该算法用在概率生成模型中,如变分自动编码器,其将自动编码器的输入嵌入到潜在空间中,该潜在空间成为分布。

由于该算法必须为每个递增的接近度定义新的函数,如果应用程序需要理解节点社区结构, LINE 的性能不是很好。

然而,LINE 的简单性和有效性只是它成为 2015 年 WWW 上被引用最多的论文的几个原因。这项工作有助于激发人们对图形学习的兴趣,将其作为机器学习的一个利基,并最终成为特定的深度学习。

网络的分层表示学习—陈等

HARP 是对前面提到的基于嵌入/行走的模型的改进。以前的模型有陷入局部最优的风险,因为它们的目标函数是非凸的。基本上这意味着,球不可能滚到绝对的山脚。

Gradient decent isn’t perfect (Courtesy of Fatih Akturk)

因此,意图动机:

通过更好的权重初始化来改进解决方案并避免局部最优。

以及建议的方法:

使用图粗化将相关节点聚集成“超级节点”

被制造出来。

HARP 本质上是一个图形预处理步骤,它简化了图形以利于更快的训练。

粗化图形后,它生成最粗“超节点”的嵌入,随后是整个图形的嵌入(图形本身由超节点组成)。

整个图中的每个“超级节点”都遵循这一策略。

因为 HARP 可以与之前的嵌入算法结合使用,比如 LINE、Node2vec 和 DeepWalk。原始论文报道了当将 HARP 与各种图嵌入方法结合时,在分类任务中高达 14% 的显著改进:显著的飞跃。

本质上

我肯定错过了一堆算法和模型,尤其是最近对几何深度学习和图形学习的兴趣激增,导致几乎每天都有新的贡献出现在出版物上。

在任何情况下,图嵌入方法都是一种简单但非常有效的方法,可以将图转换为机器学习任务的最佳格式。由于它们的简单性,它们通常非常具有可伸缩性(至少与它们的卷积对应物相比),并且易于实现。它们可以应用于大多数网络和图形,而不会牺牲性能或效率。但是我们能做得更好吗?

接下来是深入复杂而优雅的图形卷积世界!

关键要点

  • 图形嵌入技术在通过机器学习模型传递该表示之前,获取图形并将它们嵌入到较低维度的连续潜在空间
  • 行走嵌入方法执行图形遍历,目标是保持结构和特征并聚集这些遍历,然后可以通过递归神经网络传递。
  • 邻近嵌入方法使用深度学习方法和/或邻近损失函数来优化邻近,使得原始图中靠近在一起的节点同样在嵌入中。
  • 其他方法使用类似图粗化的方法来简化图,然后在图上应用嵌入技术,在保留结构和信息的同时降低复杂性。

需要看到更多这样的内容?

跟我上LinkedIn脸书insta gram,当然还有 **

我所有的内容都在 我的网站 我所有的项目都在GitHub

我总是希望结识新朋友、合作或学习新东西,所以请随时联系 flawnsontong1@gmail.com

向上和向前,永远和唯一🚀

特征选择方法概述

原文:https://towardsdatascience.com/overview-of-feature-selection-methods-a2d115c7a8f7?source=collection_archive---------4-----------------------

选择数据集中最相关要素的常用策略

特征选择的重要性

在高维输入数据的情况下,选择正确的特征集用于数据建模已被证明可以提高监督和非监督学习的性能,减少计算成本,如训练时间或所需资源,以减轻维度的诅咒。计算和使用特征重要性分数也是提高模型解释能力的重要一步。

这篇文章的概述

这篇文章分享了我在研究这个主题几天后获得的关于执行特征选择的监督和非监督方法的概述。对于所有描述的方法,我还提供了我使用的开源 python 实现的参考,以便让您快速测试所呈现的算法。然而,就过去 20 年中提出的方法而言,这个研究领域非常丰富,因此这篇文章只是试图呈现我目前有限的观点,而没有任何完整性的借口。为了更全面的研究,你可以查看下面的评论

监督/非监督模型

有监督特征选择算法,其识别相关特征以最好地实现监督模型的目标(例如,分类或回归问题),并且它们依赖于标记数据的可用性。然而,对于未标记的数据,已经开发了许多无监督的特征选择方法,这些方法基于各种标准对所有数据维度进行评分,这些标准例如是它们的方差、它们的熵、它们保持局部相似性的能力等。使用非监督试探法识别的相关特征也可以用于监督模型,因为它们可以发现数据中除特征与目标变量的相关性之外的其他模式。

从分类学的角度来看,特征选择方法通常属于下面详述的以下 4 个类别之一:过滤器包装器嵌入式混合类。

包装方法

这种方法基于所应用的学习算法的结果性能来评估特征子集的性能(例如,对于分类问题,在准确性方面的增益是多少)。任何学习算法都可以用于这种搜索策略和建模的结合。

Image from Analytics Vidhya

  • 正向选择:这种方法从一组空的特征开始,然后提供最佳性能的维度被迭代地添加到结果集中
  • 反向选择:这种方法从所有特征的集合开始,在每次迭代中,最差的维度被移除

实现:这些算法在 mlxtend 包中实现,在这里找到一个的用法示例

  • RFE (递归特征消除):通过递归考虑越来越小的特征集来选择特征的贪婪搜索。它根据要素被消除的顺序对其进行排序。

实现: scikit-learn

嵌入式方法

这种方法包括同时执行模型拟合和特征选择的算法。这通常通过使用稀疏正则化器或约束来实现,使得一些特征的权重变为零。

  • SMLR (稀疏多项逻辑回归):该算法通过 ARD 先验(自动相关性确定)对经典多项逻辑回归实现稀疏正则化。这种正则化估计了每个特征的重要性,并删除了对预测无用的维度。

实施: SMLR

  • ARD (自动相关性确定回归):基于贝叶斯岭回归,该模型将比 OLS 等方法更多地将系数权重移向零。

ARD sparsity constraint makes the weights of some features 0 and thus helps identify the relevant dimensions

实现: scikit-learn

正则化算法的其他例子: Lasso (实现 l1 正则化)、岭回归(实现 l2 正则化)、弹性网(实现 l1l2 正则化)。对这些不同正则化类型的直观描述表明,Lasso 回归将系数约束为方形,ridge 创建圆形,而弹性网介于两者之间:

https://scikit-learn.org/stable/auto_examples/linear_model/plot_sgd_penalties.html

这些算法的全面描述可以在这里找到。

过滤方法

这种方法仅基于特征的固有特性来评估特征的重要性,而不结合任何学习算法。这些方法往往比包装器方法更快,计算成本更低。如果没有足够的数据来模拟特征之间的统计相关性,过滤方法可能会提供比包装方法更差的结果。与包装方法不同,它们不会过度拟合。它们被广泛用于高维数据,其中包装器方法具有令人望而却步的计算成本。

监督方法

  • Relief :该方法从数据集中随机抽取实例,并根据所选实例与相同和相反类的两个最近实例之间的差异更新每个特征的相关性。如果在相同类的相邻实例中观察到特征差异(“命中”),则特征分数降低,或者,如果观察到具有不同分数的特征值差异(“未命中”),则特征分数增加。

Feature weight decreases if it differs from that feature in nearby instances of the same class more than nearby instances of the other class and increases in the reverse case

扩展算法 ReliefF 应用特征加权并搜索更多最近邻。

实现: scikit-rebateReliefF

  • Fisher score :通常用于二元分类问题,Fisher ratio(FiR)定义为每个特征的每个类别的样本均值之间的距离除以它们的方差:

实现:sci kit-特性,用法举例

  • 卡方评分:测试 2 个分类变量的观察频率和预期频率之间是否存在显著差异。因此,零假设表明两个变量之间没有关联。

Chi square test of independence

为了正确应用卡方检验数据集中各种特征与目标变量之间的关系,必须满足以下条件:变量必须是分类的,独立采样的,且值的预期频率应大于 5* 。最后一个条件确保检验统计的 CDF 可以通过卡方分布来近似计算,更多细节可以在这里找到。*

实现: sklearnscipy

  • (基于相关性的特征选择):这种方法的基本原理可以概括为:

"如果特性的值随着类别成员有系统地变化,那么特性就是相关的."

因此,好的特征子集包含与分类高度相关并且彼此不相关的特征。该方法如下计算 k 特征子集的价值:

https://en.wikipedia.org/wiki/Feature_selection#Correlation_feature_selection

实现:sci kit-特性,用法举例

  • FCBF (快速相关基滤波器):这种方法比 ReliefF 和 CFS 都更快更有效,因此更适合高维输入。简而言之,它遵循一种典型的相关性冗余方法,首先计算所有特征的对称不确定性(x | y 的信息增益除以它们的熵之和),按此标准对它们进行分类,然后移除冗余特征。

实现: skfeature ,【https://github.com/shiralkarprashant/FCBF】T2

无监督方法

  • 方差:已被证明是选择相关特征的有效方法,这些特征往往具有较高的方差分数

实现:方差阈值

  • 平均绝对差:根据平均值计算平均绝对差(执行)。

Higher values tend to have more discriminative power

  • 离差率:算术平均值除以几何平均值。更高的分散对应于更相关的特征(实施)

https://www.sciencedirect.com/science/article/abs/pii/S0167865512001870

  • 拉普拉斯得分:基于来自相同类别的数据通常彼此接近的观察,因此我们可以通过其局部保持能力来评估特征的重要性。该方法包括通过使用任意距离度量将数据嵌入最近邻图上,然后计算权重矩阵。然后为每个特征计算拉普拉斯得分,该得分具有最小值对应于最重要的维度的性质。然而,为了选择特征的子集,另一种聚类算法(例如 k-means)通常被后验地应用,以便选择性能最佳的组

实施: scikit-feature

  • 拉普拉斯得分结合基于距离的熵:该算法建立在拉普拉斯得分之上,使用基于距离的熵来代替典型的 k-means 聚类,并在高维数据集中表现出更好的稳定性(实现)
  • MCFS (多聚类特征选择):执行频谱分析以测量不同特征之间的相关性。拉普拉斯图的顶部特征向量用于对数据进行聚类,并且如最初的论文中所述,正在计算特征分数。

***实施:【https://github.com/danilkolikov/fsfc ***

  • LFSBSS (局部特征选择)加权 k-means* 、 SPECApriori 算法已经在本综述论文中描述,并在本中实现***

混合方法

实现特征选择的另一个选项在于将过滤器和包装器方法组合成两阶段过程的混合方法:基于统计特性的特征的初始过滤(过滤器阶段),随后是基于包装器方法的第二选择。

其他资源

有非常丰富的解决特征选择问题的文献,这篇文章只是触及了已经完成的研究工作的表面。我将提供其他已有但我还没有尝试过的资源的链接。

我在这篇文章中没有提到的其他特征选择算法的综合列表已经在 scikit-feature 包中实现。

识别相关特征的其他方法是通过使用 PLS (偏最小二乘法),如本文帖子中所举例说明的,或者通过执行本文中所介绍的线性维度缩减技术。

Apache Kafka 集群的 UI 监控工具概述

原文:https://towardsdatascience.com/overview-of-ui-monitoring-tools-for-apache-kafka-clusters-9ca516c165bd?source=collection_archive---------2-----------------------

阿帕奇卡夫卡最好的监控工具有哪些?

Photo by Chris Liverani on unsplash.com

随着 Kafka 集群监控和管理需求的增加,大量开源和商业图形工具已经上市,提供了各种管理和监控功能。

TL;dr:阿帕奇卡夫卡最好的监控工具是什么?

  1. 合流控制中心
  2. 镜头
  3. Datadog Kafka 仪表板
  4. Cloudera 经理
  5. 雅虎 Kafka 经理
  6. 卡夫多普
  7. LinkedIn Burrow
  8. 卡夫卡工具

合流控制中心

Confluent 是阿帕奇卡夫卡原创者创办的公司。合流企业,是一个-更完整的-生产环境的卡夫卡式分布。汇流平台的商业许可附带汇流控制中心,这是 Apache Kafka 的管理系统,能够从用户界面进行集群监控和管理。

Confluent Control Centre

汇合控制中心提供了对 Apache Kafka 集群内部工作方式以及流经集群的数据的理解和洞察。控制中心通过精心策划的仪表板为管理员提供监控和管理功能,以便他们能够提供最佳性能并满足 Apache Kafka 集群的服务级别协议。

镜头

lens(前 Landoop)是一家为 Kafka 集群提供企业功能和监控工具的公司。更准确地说,它通过用户界面、流式 SQL 引擎和集群监控增强了 Kafka。它还通过提供 SQL 和连接器对数据流的可见性,支持更快地监控 Kafka 数据管道。

Monitoring and managing streaming data flows with Lenses

Lenses 可与任何 Kafka 发行版配合使用,提供高质量的企业功能和监控、面向所有人的 SQL 以及 Kubernetes 上的自助式实时数据访问和流。

该公司还提供 Lenses Box ,这是一款免费的多功能 docker,可以为单个经纪人提供多达 2500 万条消息。注意,开发环境推荐使用 Lenses Box。

卡夫卡专题 UI

此外,Lenses 还提供 Kafka Topics UI,这是一个用于管理 Kafka 主题的 web 工具。

Kafka Topics UI by Lenses

Datadog Kafka 仪表板

Datadog 的 Kafka Dashboard 是一个全面的 Kafka Dashboard,显示 Kafka 经纪人、生产商、消费者和 Apache Zookeeper 的关键指标。Kafka 部署通常依赖于不属于 Kafka 的外部软件,如 Apache Zookeeper。Datadog 支持对部署的所有层进行全面监控,包括数据管道中不属于 Kafka 的软件组件。

Kafka Dashboard by DataDog

使用 Datadog 的开箱即用仪表板,节省设置时间并在几分钟内可视化您的 Kafka 数据。

Cloudera 经理

与 Confluent、Lenses 和 Datadog 相比,Cloudera Manager 中的 Kafka 显然是一个不太丰富的监控工具。但是对于已经是 Cloudera 客户的公司,需要他们在同一个平台下的监控机制,就非常方便了。

Monitoring Kafka using Cloudera Manager

以后想看这个故事吗? 保存在日志中。

雅虎 Kafka 经理

Yahoo Kafka Manager 是一个用于 Apache Kafka 集群的开源管理工具。使用 Kafka Manager,您可以:

  • 管理多个集群
  • 轻松检查集群状态(主题、消费者、偏移量、代理、副本分发、分区分发)
  • 运行首选副本选举
  • 生成分区分配,并提供选择要使用的代理的选项
  • 运行分区的重新分配(基于生成的分配)
  • 创建具有可选主题配置的主题
  • 删除主题
  • 批量生成多个主题的分区分配,可以选择要使用的代理
  • 为多个主题批量运行分区重新分配
  • 向现有主题添加分区
  • 更新现有主题的配置
  • 可以选择为代理级别和主题级别指标启用 JMX 轮询。
  • 选择性地过滤掉 zookeeper 中没有 id/owners/& offsets/目录的消费者。

Topics Overview in Yahoo Kafka Manager

卡夫多普

KafDrop 是一个用于监控 Apache Kafka 集群的开源 UI。该工具显示信息,如经纪人,主题,分区,甚至让您查看消息。这是一个运行在 Spring Boot 上的轻量级应用程序,只需要很少的配置。

Broker Overview in KafDrop. Photo by HomeAdvisor

KafDrop 3

Kafdrop 3 是一个用于导航和监控 Apache Kafka 代理的 UI。该工具显示代理、主题、分区、消费者等信息,并允许您查看消息。

这个项目是对 Kafdrop 2.x 的重新启动,它被拖进了 JDK 11+、Kafka 2.x 和 Kubernetes 的世界。

LinkedIn Burrow

LinkedIn Burrow 是 Apache Kafka 的开源监控伴侣,提供消费者滞后检查服务,无需指定阈值。它监控所有消费者的承诺补偿,并根据需求计算这些消费者的状态。提供了一个 HTTP 端点来按需请求状态,以及提供其他 Kafka 集群信息。还有一些可配置的通知程序,可以通过电子邮件或 HTTP 调用将状态发送给另一个服务。陋居是用 Go 编写的,所以在你开始之前,你应该安装并设置 Go

卡夫卡工具

Kafka Tool 是一个 GUI 应用程序,用于管理和使用 Apache Kafka 集群。它提供了一个直观的 UI,允许用户快速查看 Kafka 集群中的对象以及存储在集群主题中的消息。它包含面向开发人员和管理员的特性。使用 Kafka 工具,您可以:

  • 查看集群、代理、主题和消费者级别的指标
  • 查看分区中的消息内容并添加新消息
  • 查看抵消的卡夫卡消费者,包括阿帕奇风暴的卡夫卡喷口消费者
  • 以漂亮的打印格式显示 JSON 和 XML 消息
  • 添加和删除主题以及其他管理功能
  • 将 Kafka 分区中的单个消息保存到本地硬盘
  • 编写你自己的插件,允许你查看定制的数据格式

该工具可以在 Windows、Linux 和 Mac OS 上运行。

比较和结论

如果你买不起商业许可证,那么你可以选择雅虎 Kafka Manager、LinkedIn Burrow、KafDrop 和 Kafka Tool。在我看来,前者是一个全面的解决方案,应该可以满足大多数用例。

如果您运行的是相对较大的 Kafka 集群,那么购买商业许可是值得的。与我们在这篇文章中看到的其他监控工具相比,Confluent 和 Lenses 提供了更丰富的功能,我强烈推荐这两个工具。

要获得 Kafka UI 监控工具的最新列表,请务必阅读我最近的文章:

[## Kafka UI 监控工具(2021 年更新)

探索 Apache Kafka 集群的一些最强大的 UI 监控工具

towardsdatascience.com](/kafka-monitoring-tools-704de5878030)

成为会员 阅读介质上的每一个故事。你的会员费直接支持我和你看的其他作家。

你可能也喜欢

[## 卡夫卡不再需要动物园管理员了

2.8.0 版本让你提前接触到没有动物园管理员的卡夫卡

towardsdatascience.com](/kafka-no-longer-requires-zookeeper-ebfbf3862104) [## 如何在阿帕奇卡夫卡中获取特定信息

掌握 Kafka 控制台消费者和 kafkacat

better 编程. pub](https://betterprogramming.pub/how-to-fetch-specific-messages-in-apache-kafka-4133dad0b4b8)

为数据科学家简单解释 p 值

原文:https://towardsdatascience.com/p-value-explained-simply-for-data-scientists-4c0cd7044f14?source=collection_archive---------2-----------------------

Our Null and Alternate Hypothesis in the battle of the century. Image by Sasin Tipchai from Pixabay

没有统计学家的自命不凡和数据科学家的冷静

最近,有人问我如何用简单的术语向外行人解释 p 值。我发现很难做到这一点。

p 值总是很难解释,即使对了解它们的人来说也是如此,更不用说对不懂统计学的人了。

我去维基百科找了些东西,下面是它的定义:

在统计假设检验中,对于给定的统计模型,p 值或概率值是指当零假设为真时,统计汇总(如两组之间的样本均值差异)等于或大于实际观察结果的概率。

我的第一个想法是,他们可能是这样写的,所以没有人能理解它。这里的问题在于统计学家喜欢使用大量的术语和语言。

这篇文章是关于以一种简单易懂的方式解释 p 值,而不是像统计学家 那样自命不凡。

现实生活中的问题

在我们的生活中,我们当然相信一件事胜过另一件事。

明显可以看出像——地球是圆的。或者地球绕着太阳转。太阳从东方升起。

不确定性程度不同的——运动减肥?或者特朗普会在下一次选举中获胜/失败?或者某种特定的药物有效?还是说睡 8 小时对身体有好处?

前一类是事实,后一类因人而异。

所以,如果我来找你说运动不影响体重呢?

所有去健身房的人可能会对我说不那么友好的话。但是有没有一个数学和逻辑的结构,在其中有人可以反驳我?

这让我们想到了假设检验的概念。

假设检验

Exercising doesn’t reduce weight?

所以我在上面例子中的陈述——运动不影响体重。这个说法是我的假设。暂且称之为 无效假设 。目前,这是我们认为真实的现状。

那些信誓旦旦坚持锻炼的人提出的 替代假设 是——锻炼确实能减肥。

但是我们如何检验这些假设呢?我们收集数据。我们收集了 10 个定期锻炼超过 3 个月的人的减肥数据。

失重样品平均值= 2 千克

样品标准偏差= 1 千克

这是否证明运动确实能减肥?粗略地看一下,似乎锻炼确实有好处,因为锻炼的人平均减掉了 2 公斤。

但是你会发现,当你进行假设检验时,这些明确的发现并不总是如此。如果锻炼的人体重减轻了 0.2 公斤会怎么样。你还会这么肯定运动确实能减肥吗?

那么,我们如何量化这一点,并用数学来解释这一切呢?

让我们建立实验来做这件事。

实验

让我们再次回到我们的假设:

H : 练功不影响体重。或者相当于𝜇 = 0

Hᴬ: 运动确实能减肥。或者相当于𝜇 > 0

我们看到 10 个人的数据样本,我们试图找出

观察到的平均值(锻炼者的体重减轻)= 2 公斤

观察到的样品标准偏差= 1 千克

现在问我们自己一个好问题是— 假设零假设为真,观察到 2 kg 或者比 2 kg 更极端的样本均值的概率是多少?

假设我们可以计算出这个值——如果这个概率值很小(小于阈值),我们拒绝零假设。否则,我们无法拒绝我们的无效假设。 为什么拒绝失败而不接受? 这个后面会回答。

这个概率值实际上就是 p 值。简单地说,如果我们假设我们的零假设是正确的,它只是观察我们所观察到的或极端结果的概率。

统计学家称该阈值为显著性 level(𝜶,在大多数情况下,𝜶取为 0.05。

那么我们怎么回答: 假设原假设为真,得到 2 kg 或大于 2 kg 的值的概率是多少?

这是我们最喜欢的分布,图中的正态分布。

正态分布

假设我们的零假设为真,我们创建重量损失样本平均值的抽样分布。

中心极限定理:中心极限定理简单来说就是,如果你有一个均值为μ、标准差为σ的总体,并从总体中随机抽取样本,那么样本均值的分布将近似为正态分布以均值为总体均值标准差σ/√n 其中σ是样本的标准差,n 是样本中的观察次数。****

现在我们已经知道了由零假设给出的总体均值。所以,我们用它来表示均值为 0 的正态分布。其标准偏差由 1/√10 给出

The sampling distribution is a distribution of the mean of samples.

事实上,这是总体样本均值的分布。我们观察到一个特殊的平均值,即 2 公斤。

现在我们可以使用一些统计软件来找出这条特定曲线下的面积:

**from scipy.stats import norm
import numpy as npp = 1-norm.cdf(2, loc=0, scale = 1/np.sqrt(10))
print(p)
------------------------------------------
1.269814253745949e-10**

因此,这是一个非常小的概率 p 值(

And so we can reject our Null hypothesis. And we can call our results statistically significant as in they don’t just occur due to mere chance.

The Z statistic

You might have heard about the Z statistic too when you have read about Hypothesis testing. Again as I said, terminology.

That is the extension of basically the same above idea where we use a standard normal with mean 0 and variance 1 as our sampling distribution after transforming our observed value x using:

This makes it easier to use statistical tables. In our running example, our z statistic is:

**z = (2-0)/(1/np.sqrt(10))
print(z)
------------------------------------------------------
6.324555320336758**

Just looking at the Z statistic of > 6 应该让您知道观察值至少有六个标准差,因此 p 值应该非常小。我们仍然可以使用以下公式找到 p 值:

**from scipy.stats import norm
import numpy as npp = 1-norm.cdf(z, loc=0, scale=1)
print(p)
------------------------------------------------------
1.269814253745949e-10**

正如你所看到的, 我们使用 Z 统计量得到了相同的答案。

一个重要的区别

Our Jurors can never be definitively sure so they don’t accept they just reject.

我们之前说过,我们拒绝我们的零假设,因为我们有足够的证据证明我们的零假设是错误的。

但是如果 p 值高于显著性水平。然后我们说,我们不能拒绝零假设。为什么不说接受零假设呢?

最直观的例子就是使用审判法庭。在审判法庭上,无效假设是被告无罪。然后我们看到一些证据来反驳零假设。

如果我们不能反驳无效的假设,法官不会说被告没有犯罪。法官只是说,根据现有的证据,我们无法判定被告有罪。

推动这一观点的另一个例子是:假设我们正在探索外星球上的生命。而我们的零假设( H )就是这个星球上没有生命。我们漫游了几英里,寻找那个星球上的人/外星人。如果我们看到任何外星人,我们可以拒绝零假设,支持替代方案。

但是如果我们没有看到任何外星人,我们能肯定地说这个星球上没有外星生命或者接受我们的无效假设吗?也许我们需要探索更多,或者也许我们需要更多的时间,我们可能已经找到了外星人。所以,在这种情况下,我们不能接受零假设;我们只能拒绝它。或者用 Cassie Kozyrkov 的话来举例,我们可以说 “我们没学到什么有趣的东西”。

在 STAT101 课上,他们会教你在这种情况下写一段令人费解的段落。(“我们未能拒绝零假设,并得出结论,没有足够的统计证据来支持这个星球上存在外星生命。”)我深信这种表达的唯一目的就是让学生的手腕紧张。我总是允许我的本科生这样写:我们没有学到任何有趣的东西。

Riddikulus: Hypothesis testing can make the null hypothesis look ridiculous using p-values (The Wand)

本质上,假设检验就是检查我们的观察值是否让零假设看起来很荒谬 。如果是,我们拒绝零假设,称我们的结果具有统计学意义。除此之外,我们没有学到任何有趣的东西,我们继续我们的现状。

继续学习

如果你想了解更多关于假设检验、置信区间以及数字和分类数据的统计推断方法,Mine etinkaya-Rundel 在 coursera 上教授推断统计学课程,这是最简单不过的了。她是一个伟大的导师,很好地解释了统计推断的基础。

谢谢你的阅读。将来我也会写更多初学者友好的帖子。在 媒体 关注我或者订阅我的 博客 了解他们。一如既往,我欢迎反馈和建设性的批评,可以通过 Twitter @mlwhiz 联系

此外,一个小小的免责声明——在这篇文章中可能会有一些相关资源的附属链接,因为分享知识从来都不是一个坏主意。

p 值在起作用:可以肯定地说视差校正真的提高了卫星雨估计算法的精度吗?

原文:https://towardsdatascience.com/p-value-in-action-is-it-safe-to-say-that-parallax-correction-really-improve-the-accuracy-of-1f388626d037?source=collection_archive---------20-----------------------

source: https://planetary.s3.amazonaws.com/assets/images/spacecraft/2014/20140227_nasa_gpm.jpg

p 值到底是什么?我真的花了很长时间才搞清楚这个值的概念。根据我的经验,我认为了解 p 值的最佳方法是通过一个真实的例子。这就是为什么在这篇文章中,我将使用一个真实的例子来解释 p 值,我真的想证明这一点。但在此之前,我将解释一下关于另一个使 p 值相关的概念或理论,即零假设和正态分布。还将解释卫星降雨估计算法和视差校正的概念。

虚假设

零假设是一个假设,暗示我们非常怀疑我们的假设又名魔鬼代言人。零假设的反义词是另一个假设,或者说我们的假设是正确的。因此,在这种情况下,我们的零假设是视差校正没有提高卫星雨估计算法的精度,而另一个假设是视差校正提高了卫星雨估计算法的精度。

正态分布

在我个人的理解中,正态分布就是在任何常态下都会正常发生的分布。如果我们正在收集足够的数据,数据的直方图将会以数据的平均值为中心形成一个钟形。

source: https://www.statsdirect.com/help/resources/images/normalhistogram.gif

正态分布有两个属性,均值(μ)和标准差(σ) 。从一个经验实验来看,如果我们获取一个非常大的数据,并根据它制作一个直方图,它将向我们显示:

  • 大约 68%的值落在平均值的一个标准偏差内。
  • 大约 95%的值落在平均值的两个标准偏差范围内。
  • 大约 99.7% —在平均值的三个标准偏差范围内。

source: https://upload.wikimedia.org/wikipedia/commons/thumb/2/22/Empirical_rule_histogram.svg/450px-Empirical_rule_histogram.svg.png

p 值

在正态分布中,超过 3σ如果您想知道数据的百分比,您可以使用此公式,其原理是考虑正态分布钟形曲线的形状:

这就是 p 值的定义。在正态分布环境中, p 值只是基于 z 值的钟形曲线中的一部分数据。z 值是在标准偏差单位中重新调整的真实数据的值。

x is a real data

因此,当您将数据转换为 z 值时,钟形曲线的中心不再是数据的平均值,而是零。现在,我们知道了 p 值的概念,但在没有实际例子的情况下仍然有些模糊。在我们开始真正的例子之前,我将稍微解释一下卫星的视差校正和卫星降雨估计算法。

卫星雨量估计算法

这是一套算法,用来估计在气象卫星范围内某处的降雨量。气象卫星是一种捕捉地球上各种频率电磁波的卫星(所有温度高于 0 开尔文的物质实际上都在辐射各种频率的电磁波,这取决于该物质的温度)。从地球辐射出来的电磁波代表了地球的外部温度。当地球顶部是一朵云时,卫星实际上捕捉到了云的温度。但是当没有云的时候,它会捕捉陆地或海洋的温度(云的温度会比陆地或海洋冷)。

气象卫星捕捉云层的能力被用来估计云层下面的降雨量。一种最简单的降雨量估算算法叫做自动估算器。基于这篇论文,我们可以根据这个公式来估算某个地区的降雨量。

其中 T 是卫星捕获的温度,基于红外通道

视差修正

粗略地说,为了计算校正,我们需要大气递减率来估计云的高度、云相对卫星的位置以及观测云的卫星的倾斜角。为什么我们需要视差纠正?简而言之,地球的曲率使一切变得复杂,云不只是一些简单的扁平物体,它有高度,这些导致一切都变得有点错位。反正如果你想了解更多关于视差纠正的知识,可以查看这个参考文献(印尼语)。作者是我工作单位的资深同事,他对气象卫星的估计算法和视差纠正非常有经验。事实上,我后来在实验中做视差纠正计算的那部分脚本就是来自于他。

实验

在这个实验中,我将把卫星的范围从一个区域限制到仅仅一个点。因为这个实验的验证是用雨量计。实验开始前,我们必须:

  1. 定义零假设,那就是"视差改正不提高卫星雨估计算法的精度"所以另一个假设是"视差改正提高卫星雨估计算法的精度"。****
  2. 定义阿尔法值。常见的 alpha 值是 0.05 和 0.01,但实际上,这取决于您的实验。我不知道这个选择是否正确,但在这个实验中,我选择 0.05

最后,也是最重要的,但在执行 p 值测试的义务之外,是我们如何进行计算,以确定修正后估计变得更好还是更差。很简单,首先我们计算自动估计器的估计值和自动估计器在雨量计校正后的估计值之间的差值的绝对值(真实数据)。如果值为正(> 0),估计的降雨量变得更好,否则,如果值为负(< 0),估计变得更差

在数据科学中,原始数据总是非常“脏”因此,我在这个实验中的全套脚本(用于清理和合并数据)充满了“幻数”,也就是一个非常有条件的常数,它只是为了这个实验而存在。所以在这里,我只是分享一个已经清理的数据和脚本来做自动估计计算和视差纠正。

你可以在这里下载‘干净’的数据。自动估算器和视差纠正脚本可以在这里下载。自动估算器和视差脚本的输入是来自高知大学的 PGM 数据。下载一批数据的指令也可以在他们的网站上。

在我之前已经提到的干净数据中,我已经进行了获得 z 值 0 所需的所有计算,即 0.5779751399 。这个值远远大于我们的 alpha 值。所以结果是我们不能拒绝零假设。我们不能消除我们的疑虑,说视差校正真的提高了自动估算器算法的准确性是不安全的。

如果我们基于正态分布画出 0 及以下的 z 值,会得到如下图。

这是制作上图的脚本。

#!/usr/bin/python3from scipy.stats import norm
import numpy as np
import matplotlib.pyplot as plt def draw_z_score(x, cond, mu, sigma, title):
 y = norm.pdf(x, mu, sigma)
 z = x[cond]
 plt.plot(x, y)
 plt.fill_between(z, 0, norm.pdf(z, mu, sigma))
 plt.title(title)
 plt.show()x = np.arange(-3,3,0.001)
z0 = 0.577975139913483
draw_z_score(x, x<z0, 0, 1, 'z<%s'%(str(z0)))

这就是实验的结论。你觉得怎么样?是我的脚本有错误还是计算视差修正的假设有错误。我已经提到脚本计算自动估计器和视差纠正之前,你可以阅读它,并告诉我,如果在计算中有错误。

参考:

https://www . statistics show to . data science central . com/experimental-rule-2/,2019 年 7 月 16 日访问

https://www.statsdirect.com/help/distributions/normal.htm,2019 年 7 月 16 日进入

https://goodcalculators.com/p-value-calculator/,2019 年 7 月 16 日接入

https://www . academia . edu/35505495/tek NIS _ Kore ksi _ Parallaks _ Satelit _ hima wari,2019 年 7 月 18 日访问

http://weather.is.kochi-u.ac.jp/archive-e.html,2019 年 8 月 16 日接入

Rani、Nurhastuti Anjar、Aulia Khoir 和 Sausan Yulinda Afra。"使用基于 Himawari 8 卫星云顶温度的自动估算器进行的降水估算与旁卡平站的降水观测的比较."可持续人类圈国际研讨会论文集。2017.

数据科学家解释的 p 值

原文:https://towardsdatascience.com/p-values-explained-by-data-scientist-f40a746cfc8?source=collection_archive---------0-----------------------

对于数据科学家来说

我记得当我作为暑期学生在 CERN 进行我的第一次海外实习时,在确认希格斯玻色子满足【五西格马】阈值 (这意味着 p 值为 0.0000003)后,大多数人仍在谈论希格斯玻色子的发现。

当时我对 p 值、假设检验甚至统计学意义一无所知。

你是对的。

我去谷歌搜索了 p 值这个词,我在维基百科上找到的东西让我更加困惑…

在统计假设检验中,p-值概率值是对于给定的统计模型,当零假设为真时,统计汇总(如两个比较组间样本均值差的绝对值)大于或等于实际观察结果的概率。

维基百科

干得好维基百科。

好吧。我最终没有真正理解 p 值的真正含义。

直到现在,在进入数据科学领域后,我终于开始理解 p 值的意义以及它如何在某些实验中用作决策工具的一部分。

因此,我决定在本文中解释 p 值以及如何在假设检验中使用它们,希望能让你对 p 值有一个更好更直观的理解。

虽然我们不能跳过对其他概念的基本理解和 p 值的定义,但我保证我会以直观的方式进行解释,而不会用我遇到的所有技术术语来轰炸你。

本文共有四个部分,从构建假设检验到理解 p 值并以此指导我们的决策过程,向您展示一幅完整的画面。我强烈建议您通读所有这些内容,以便对 p 值有一个详细的了解:

  1. 假设检验
  2. 正态分布
  3. 什么是 P 值?
  4. 统计显著性

会很有趣的。😉

我们开始吧!

1.假设检验

Hypothesis Testing

在我们谈论 p 值意味着什么之前,让我们先来了解一下假设检验,其中 p 值用于确定我们结果的统计显著性

我们的最终目标是确定结果的统计意义。

统计学意义建立在这三个简单的概念上:

  • 假设检验
  • 正态分布
  • p 值

假设检验 用于检验利用样本数据对一个总体作出的断言()的有效性。 替代假设 是当零假设被断定为不真实时,你会相信的假设。

换句话说,我们将做出一个断言(零假设),并使用一个样本数据来检验该断言是否有效。如果这个主张无效,那么我们将选择我们的替代假设。就这么简单。

为了知道一个声明是否有效,我们将使用 p 值来衡量证据的强度,以查看它是否具有统计显著性。如果证据支持替代假设,那么我们将拒绝零假设并接受替代假设。这将在后面的部分中进一步解释。

让我们用一个例子来使这个概念更清楚,这个例子将在本文中用于其他概念。

🍕 🍕 举例 : 假设一家披萨店声称他们的送货时间平均为 30 分钟或更短,但你认为时间比这还长。因此,您进行了假设检验,并随机抽取了一些交货时间来检验这一说法:

  • 零假设 —平均交付时间为 30 分钟或更少
  • 替代假设 —平均交货时间大于 30 分钟

这里的目标是确定从我们的样本数据中找到的证据更好地支持了哪一种主张——无效的还是替代的。

我们将使用 单尾检验 ,因为我们只关心平均交付时间是否大于 30 分钟。我们将忽略另一个方向的可能性,因为平均交付时间低于或等于 30 分钟的结果更可取。我们在这里想要测试的是,平均交付时间是否有可能大于 30 分钟。换句话说,我们想知道披萨店是否对我们撒了谎。😂

进行假设检验的一种常见方法是使用 Z-test 。在这里,我们不会进入细节,因为我们想有一个高层次的了解表面上正在发生的事情,然后我们潜入更深。

2.正态分布

Normal Distribution with mean μ and standard deviation σ

正态分布是一个概率密度函数用于查看数据分布。

正态分布有两个参数—平均值(μ)和标准差,也称为σ。

平均值是分布的中心趋势。它定义了正态分布的峰值位置。标准偏差*是可变性的度量。它决定了这些值与平均值的差距。*

正态分布通常与[**68-95-99.7 rule**](https://en.wikipedia.org/wiki/68%E2%80%9395%E2%80%9399.7_rule)(上图)相关联。

  • 68%的数据在平均值(μ)的 1 个标准偏差(σ)内
  • 95%的数据在平均值(μ)的 2 个标准偏差(σ)以内
  • 99.7%的数据在平均值(μ)的 3 个标准偏差(σ)内

还记得我在开头提到的发现希格斯玻色子的“五西格马”阈值吗?5 西格玛大约是99.9999426696856%的数据,以在科学家证实发现希格斯玻色子之前命中。这是为避免任何潜在的错误信号而设定的严格阈值。

酷毙了。现在你可能想知道,“正态分布如何应用于我们之前的假设检验?”

因为我们使用 Z-test 来进行假设检验,所以我们需要计算(将在我们的 检验统计 中使用),这是数据点平均值的标准偏差数。在我们的例子中,每个数据点都是我们收集的披萨配送时间。****

Formula to calculate Z-score for each data point

请注意,当我们计算了每个披萨配送时间的所有 Z 分数并绘制了如下的标准正态分布曲线时,X 轴上的单位将从分钟变为标准偏差单位,因为我们已经通过减去平均值并除以其标准偏差对变量进行了标准化(参见上面的公式)。****

查看标准正态分布曲线非常有用,因为我们可以将测试结果与标准偏差中具有标准化单位的“正常”总体进行比较,尤其是当我们有一个具有不同单位的变量时。

Standard Normal Distribution for Z-scores

Z 分数可以告诉我们总体数据与平均人口相比的位置。

我喜欢 Koehrsen 这样说—Z 值越高或越低,结果就越不可能是偶然发生的,结果就越有可能是有意义的。****

但是,有多高(或多低)被认为有足够的说服力来量化我们的结果有多大意义呢?

👊🏼笑点****

这就是我们需要解决这个难题的最后一个项目——p 值*,并检查我们的结果是否基于 显著性水平(也称为α)在我们开始实验之前,我们设置了***

3.什么是 P 值?

p-value beautifully explained by Cassie Kozyrkov

最后……这里说的是 p 值!

前面所有的解释都是为了搭建舞台,把我们引向这个 p 值。我们需要之前的上下文和步骤来理解这个神秘的(实际上并不神秘)p 值,以及它如何导致我们对假设检验的决策。

如果你已经做到了这一步,请继续阅读。因为这部分是最令人兴奋的部分!

与其用维基百科(对不起维基百科)给出的定义来解释 p 值,不如用我们的上下文来解释——披萨配送时间!

回想一下,我们随机抽样了一些比萨饼的交付时间,目标是检查平均交付时间是否大于 30 分钟。如果最终证据支持比萨饼店的说法(平均送货时间为 30 分钟或更少),那么我们不会拒绝零假设。否则,我们会拒绝无效假设。

因此,p 值的任务是回答这个问题:

如果我生活在一个披萨外卖时间不超过 30 分钟的世界里(零假设成立),我在现实生活中的证据会有多令人惊讶?

p 值用一个数字来回答这个问题——概率**

p 值越低,证据越令人惊讶,我们的零假设看起来就越荒谬。

当我们对自己的无效假设感到可笑时,我们该怎么办?我们拒绝这一点,而是选择我们的替代假设。

如果 p 值低于预定的显著性水平(人们称之为 alpha ,我称之为荒谬的阈值— 不要问我为什么,我只是觉得我更容易理解),那么我们拒绝零假设。**

现在我们明白 p 值是什么意思了。让我们将这一点应用到我们的案例中。

🍕披萨配送时间的 p 值🍕

现在我们已经收集了一些交货时间样本,我们进行计算,发现平均交货时间增加了 10 分钟,p 值为 0.03* 。***

这意味着在一个披萨交付时间为 30 分钟或更少的世界(零假设为真),有 3%的几率我们会看到由于随机噪声导致平均交付时间至少延长 10 分钟。****

p 值越低,结果越有意义,因为它不太可能是由噪声引起的。

在我们的案例中,大多数人对 p 值有一个普遍的误解:

p 值为 0.03 意味着有 3%(概率百分比)的结果是由于偶然的,这不是真的**

人们常常希望有一个明确的答案(包括我),这就是我如何让自己困惑了很长时间来解读 p 值。

p 值不能证明任何事情。这只是一种利用惊喜作为做出合理决定的基础的方式。

卡西·科济尔科夫

下面是我们如何使用 p 值 0.03 来帮助我们做出合理的决定(重要):

  • 想象一下,我们生活在一个平均送货时间总是 30 分钟或更少的世界——因为我们相信比萨饼店(我们最初的信念)!
  • 在分析了收集到的样本交付次数后,p 值 0.03 低于显著性水平 0.05(假设我们在实验之前设置了这个),我们可以说结果是 统计显著
  • 因为我们一直相信比萨饼店能够履行其承诺,在 30 分钟或更短时间内交付比萨饼,我们现在需要思考这一信念是否仍然有意义,因为结果告诉我们比萨饼店未能履行其承诺,并且结果是 统计显著性
  • 那我们该怎么办?首先,我们试图想出每一种可能的方法来使我们最初的信念(零假设)有效。但是因为比萨饼店慢慢地得到了其他人的差评,而且它经常给出糟糕的借口导致交货延迟,甚至我们自己都觉得为比萨饼店辩护是荒谬的,因此,我们决定拒绝零假设。****
  • 最后,随后合理的决定是,选择不再购买那个地方的任何披萨。

到现在为止,你可能已经意识到了一些事情…根据我们的上下文,p 值不用于证明或证明任何事情。

在我看来, **p 值是在结果具有统计显著性* 时,用来挑战我们最初信念(零假设)的工具。当我们对自己的信念感到可笑时(假设 p 值显示结果具有统计学意义),我们会抛弃最初的信念(拒绝零假设)并做出合理的决定。***

4.统计显著性

最后,这是最后一个阶段,我们将所有内容放在一起,测试结果是否具有 统计显著性。

仅有 p 值是不够的,我们需要设置一个阈值(又名显著性水平——阿尔法)。阿尔法应该总是在实验前设置,以避免偏见。如果观察到的 p 值低于α,那么我们得出结论,结果是 具有统计显著性。**

经验法则是将 alpha 设置为 0.05 或 0.01(同样,该值取决于您手头的问题)。

如前所述,假设我们在开始实验前将α设置为 0.05,由于 0.03 的 p 值低于α,因此获得的结果具有统计学意义。

作为参考,下面是整个实验的****:的基本步骤****

  1. 陈述无效假设
  2. 陈述另一个假设
  3. 确定要使用的α值
  4. 找到与你的阿尔法水平相关的 Z 分数
  5. 使用此公式查找测试统计
  6. 如果检验统计值小于α水平的 Z 得分(或 p 值小于α值),则拒绝零假设。否则,不要拒绝零假设。

Formula to calculate test statistic for Step 5

如果你想了解更多关于统计学意义的知识,可以看看这篇文章——由威尔·科尔森撰写的统计学意义解释

最后的想法

(Source)

感谢您的阅读。

这里有很多东西要消化,不是吗?

我不能否认,p 值对许多人来说是天生的困惑,我花了很长时间才真正理解和欣赏 p 值的意义,以及作为一名数据科学家,它们如何应用于我们的决策过程。

但是不要过于依赖 p 值,因为它们只帮助整个决策过程的一小部分。

我希望你已经发现 p 值的解释是直观的,并有助于你理解 p 值的真正含义以及它们如何用于假设检验。

归根结底,p 值的计算很简单。当我们想要解释假设检验中的 p 值时,困难就来了。希望最难的部分现在对你来说至少变得稍微容易一点。

如果你想了解更多关于统计学的知识,我强烈推荐你读这本书(我现在正在读这本书!)— 数据科学家实用统计学 专为数据科学家理解统计学的基本概念而编写。

一如既往,如果您有任何问题或意见,请随时在下面留下您的反馈,或者您可以随时通过 LinkedIn 联系我。在那之前,下一篇文章再见!😄

关于作者

Admond Lee 目前是Staq的联合创始人/首席技术官,该平台是东南亚首屈一指的商业银行应用编程接口平台。****

想要获得免费的每周数据科学和创业见解吗?

加入 Admond 的电子邮件简讯——Hustle Hub,每周他都会在那里分享可行的数据科学职业技巧、错误&以及从创建他的初创公司 Staq 中学到的东西。

你可以在 LinkedInMediumTwitter脸书上和他联系。

***** [## 阿德蒙德·李

让每个人都能接触到数据科学。Admond 正在通过先进的社交分析和机器学习,利用可操作的见解帮助公司和数字营销机构实现营销投资回报。

www.admondlee.com](https://www.admondlee.com/)*****

P2P 借贷平台数据分析:R 中的探索性数据分析—第一部分

原文:https://towardsdatascience.com/p2p-lending-platform-data-analysis-exploratory-data-analysis-in-r-part-1-32eb3f41ab16?source=collection_archive---------10-----------------------

对 Prosper 贷款数据的探索

P 近年来,P2P 借贷平台行业蓬勃发展。成千上万的投资者通过这些平台获利;成千上万的借款人更容易拿到钱。尽管这些平台提供借款人的信用评分和基本信息,以确保借贷交易处于安全的环境中,但仍有成千上万的人面临亏损的风险。

即使是领先的金融 P2P 贷款平台公司 Prosper,也仍然受到信用风险问题的困扰。但经过他们的重建和新的信用体系的推出,信用风险得到了改善。这让我想找出幕后的故事。在这里,我将探索这个 Prosper 数据集,并试图找出借款人财产背后的一些模式,不同的评级类型,以及它们如何链接到违约贷款或已完成贷款。

此外,我还将分享一些关于变量探索动机的想法。毕竟,在如此庞大的数据集中,如果我们从了解一些基本的领域知识开始,就更容易在这个大数据中挖掘出有价值的特征。

Prosper 贷款数据

该 Prosper 数据集由 Udacity 提供,作为数据分析师 Nanodegee 的一部分(最后更新于 2014 年 3 月 11 日),可点击此处下载。它包含 2005 年至 2014 年期间每个贷款列表数据的 81 个变量和 113,979 个观察值,这些数据可以大致分为四种变量类别:

  • 贷款状态:贷款列表的状态,如已取消、已核销、已完成、当前、已拖欠、尾款进行中、逾期。
  • 借款人数据:借款人的基本属性,如收入、职业、就业状况等。
  • 贷款数据:贷款的基本属性,如贷款期限、借款人年利率等。
  • 信用风险指标:衡量贷款风险的指标,如信用等级、Prosper 评分、银行卡使用率等。

变量定义见链接

感兴趣的初始问题

我以前从未使用过 P2P 贷款平台,但我总是很好奇为什么投资者总能从这些高风险的贷款中获利?

我对这个问题的第一个猜测是,P2P 借贷平台上的信用评估指标具有一定的参考价值,尤其是对于 Prosper 或 LendingTree 这样业绩良好的平台。原因是,在 P2P 借贷平台上,我们无法获得大量关于借款人的信息,唯一的参考来源是 P2P 借贷平台提供的指标。而这些信息为投资者提供了更可靠的赚钱机会。据此,我的问题可以是——好的 P2P 借贷平台——比如 Prosper——的评级指标的性质是什么,它们是如何与违约和已完成贷款联系在一起的?如果我能找到与违约和已完成贷款有某种趋势的特征,也许这些特征是评估贷款好坏的关键因素。

在继续探索贷款数据以找到答案之前,让我们先了解一下 P2P 借贷平台的基本属性。

P2P 借贷平台:繁荣展望

总的来说,P2P 借贷平台的属性与传统借贷渠道——银行有很大不同,银行总是根据独立征信机构对借款人的信用评分来评估贷款。但是我们知道在 P2P 借贷平台上,贷款总是高风险的。如果他们通过信用报告机构对这些贷款进行评级,这些贷款将总是被评为高风险。这种情况会影响投资者对 P2P 借贷平台的判断。因此,可能存在一些不同于传统信用度量的风险度量,它们可以正确地评估 P2P 贷款。

让我们看看 Prosper page,从投资者的角度来看看他们的风险评级指标。如果我们查看贷款列表页面,我们可以看到“评级”列,每个贷款列表都在左侧。此外,我们可以看到每笔贷款的其他基本信息,如类别或金额。因此,如果投资者决定是否投资一笔贷款,那么“评级指标就成了对平台信用风险的主要评估。

Source: https://www.prosper.com/listings

那么评级是什么,评级表现如何?我翻了翻亨通的表格 S-1年报维基 ,做了一个总结:

在 2009 年之前,向投资者展示的主要信用风险指标是信用等级,这是基于独立信用报告机构对借款人的信用评分。但当时 Prosper 上的贷款业绩并不是很好。在 SEC 要求暂时关闭和重组后,Prosper 推出了自 2009 年 7 月以来显示的新信用风险指标— Prosper Rating ,这被视为对借款人更严格的信用准则。新的贷款业绩显示,Prosper 的贷款违约率已大幅降低。

看起来繁荣评级比旧的信用等级表现得更好,后者像银行一样评估贷款。这让我想比较一下 Prosper 贷款数据中 2009 年前后的**Loan Status**

了解数据背景知识的一些小技巧…

在进入下一部分之前,我想介绍一些关于如何快速理解目标数据的基本领域知识的技巧。

作为一名经验丰富的投资银行家,快速了解基础领域知识并进行总结是我们主要的日常工作。当我们开始了解一个全新的行业知识时,找到公司的上市文件,如 SEC 备案 非常有用。最知名的上市文件叫做 年报 如果感兴趣的公司以前没有在股票市场上市,也可以搜索已经上市的同行业领先公司的文档。

以下是快速了解一个公司/行业的新行业知识和历史的主要来源:

  • 上市文件:表格 S-1、表格 10-K、年度报告等。他们提供基本的公司背景和历史,行业信息和竞争,主要产品和服务介绍,财务业绩等。如果该公司已经在股票市场进行首次公开募股,可以很容易地在 投资者关系(IR)公司网页上找到它们。****
  • 行业报告:我们可以在行业报告上找到丰富的行业趋势和参与者。知名信源如 IBISWorldIDCMarketResearch.com等。注:大多数行业报告来源需要付费账户,但他们总是提供一份报告摘要,让我们可以获得一些基本信息。
  • 统计来源:调查一段时间内的数量表现很有用。大多数上市文件都提供财务报告。如果你想要一个更完整的统计来源,最推荐的来源是 Statista
  • 维基百科和谷歌搜索:几乎一切的灵丹妙药。

2009 年前后的贷款表现

在数据集中,我定义了高风险贷款被贷款有逾期,已收贷款** 或 拖欠;完成的贷款被的贷款被完成,完成的贷款被的贷款被取消。****

上面的条形图显示,高风险贷款的比例在 2009 年后从大约 37%下降到 30%。

让我们比较一下从 HR 到 AA(高到低风险)的信用等级和 Prosper 评级贷款状况之间的关系。我想知道 Prosper Rating 和 Credit Grade 如何评估不良贷款和良好贷款。

随着风险水平的降低,高风险贷款的百分比与繁荣等级信用等级均呈反比关系。高风险贷款的百分比越低,评级越好。我们可以看到,在 Prosper Rating 推出后,整个高风险贷款(绿色)实际上减少了。****

在高风险和已完成贷款中,我进一步将贷款按照从 AA 到 HR(低风险到高风险)的每个信用级别分组:

上图显示,2009 年前评级为良好的贷款数量在 2009 年后有所减少,无论是已完成贷款还是高风险贷款,这意味着 Prosper 在 2009 年后进行了更加严格的贷款审计。此外,高风险贷款总计与 2009 年之前的贷款相比有所下降,如前图所示,而评级为 D 和 E 的高风险贷款在 2009 年之后仍有所上升。****

可以推断出:

  • Prosper 在 2009 年后进行更严格的贷款审计。
  • 与 2009 年之前应用的信用等级相比,Prosper 评级的能力在评估高风险贷款方面表现更好。

Prosper 评级的组成部分

我们从 Prosper 数据中看到了 Prosper 评级的良好表现。那么,如何衡量繁荣等级呢?****

根据这个页面 , Prosper 评级估计损失率决定,这个估计损失率由两个分数决定:1)一个自定义的 Prosper 评分和 2) 一个来自消费者信用报告机构(如 Experian)的信用评分。所以我会在 Prosper 评分信用评分里多调查一下,看看他们是怎么让 Prosper 评分比信用等级更准确的。

1.Prosper 得分

据 Prosper 网站介绍, Prosper Score 是使用历史 Prosper 数据构建的,用于评估 Prosper 借款人上市的风险。范围从 1 到 11,11 为最低风险,1 为最高风险。

上图显示 Prosper 得分呈钟形分布,得分峰值为 4、6、7,Prosper 数据中风险最低和最高的得分较少。

对每个贷款状态进行分组 Prosper 评分,我们可以看到它们在已完成贷款中呈左偏形分布,这意味着已完成贷款主要位于良好评级。然而,Prosper score 在高风险贷款中呈钟形分布。与之前显示的左倾形状的 Prosper 评级相比,Prosper Score 似乎检测高风险贷款的能力较低

Prosper 评级的另一个组成部分是来自报告机构的信用评分。在这个数据集中,我发现与这类分数相关的变量是CreditScoreRangeLowerCreditScoreRangeUpper。我创建了一个新变量, CreditScoreAverage, 对这两个变量进行平均,作为信用评分**的代表变量。****

2.信用评分平均值

2009 年之前,Prosper 不允许信用评分(Experian Scorex PLUS)低于 520 的个人在平台上发布房源。2009 年后,Prosper 将信用评分的最低门槛提高到 640 分,但在某些情况下,如果借款人之前完成了 Prosper 贷款,他们允许评分最低值为 600 分。因此,我将图表分为两个时期,并将 x 轴上得分的最小值限制为 510 和 630,以排除特殊情况的异常值。

2009 年前后的*均为右偏分布,2009 年前多数计数在 610 至 670,2009 年后多数计数在 670 至 710。与 2009 年之前的贷款相比,2009 年之后的总体平均信用评分明显更高。原因是 Prosper true在 2009 年之后对借款人的信用评分设置了更高的门槛,这也与 Prosper 评级前一节的观察结果相吻合。*

但是信用评分平均值Prosper 评分如何让 Prosper 评级更准确呢?2009 年前后信用评分平均值已完成高风险贷款有影响吗?我将 2009 年前后已完成高风险的平均信用评分与贷款状态进行了分组:**

对比已完成高风险贷款的分布,上图出现了几乎相似的分布,在两个时期都呈右偏形状。似乎credit score average对检测 2009 年前后完成高风险贷款没有区别,只是门槛的变化。**

事实证明:如果 Prosper 使用信用评分进行审核,在 2009 年后更严格评估(更高门槛)的情况下,当时整体借款人的信用评分将主要位于高风险等级,即使是完成概率很高的贷款。但是,由于 Prosper 也结合了 Prosper 评分,这使得 Prosper 评级呈现出更好的衡量能力,并在已完成贷款和高风险贷款之间表现出更好的区分。**

调查到目前为止…

我们来简单总结一下。2009 年后,Prosper 将 Prosper 评分应用到中,使得 Prosper 评级在 2009 年后更严格的局分门槛评定标准下,对不良贷款和已完成贷款、有了更多的区分。因此,我们可以说 Prosper 得分Prosper 评级指标中发挥了重要作用。****

让我们用数据来阐述这个假设:

上图显示繁荣等级繁荣分数之间的趋势呈略正的形状,各繁荣等级中繁荣分数方差更为集中。与信用评分平均值相比,每个 Prosper 评级中信用评分平均值方差Prosper 评分的稍大。似乎 Prosper 在他们自己的 Prosper 评级模型中使用的 Prosper 评分的线性权重多于信用评分平均值。****

下一步:揭开繁荣得分的面纱**

那么成功得分的主要要素是什么呢?我翻阅了 2010 年和 2013 年的 Prosper 年度报告,发现了一些关于 Prosper Score 的信息:**

Prosper Score 用于评估贷款逾期 61 天以上的可能性。与从信用报告机构获得的信用评分基于更广泛的人群不同,Prosper Score 基于更小的借贷平台子集的更精确的图像。****

兴趣。我推断,如果 Prosper 只是通过传统的局机构来衡量借款人的信用,实际上它只是一种类似于银行或其他官方贷款机构的衡量方式。 Prosper Score 考虑在平台人群中独一无二的借款人行为。也许这样的定制评估更适合借贷平台市场,因为它是专门由繁荣的借款人和申请人群体来衡量的。因为我们知道,当借款人无法从信用评分更严格的银行贷款时,贷款平台会为借款人提供额外的平台。借贷平台将风险分散给许多投资者,这使得衡量方法大不相同。**

因此,我搜索了成功得分的主要因素。我发现一些不同的来源表明,随着时间的推移,Prosper Score 是由不同的元素组成的,如网站或这个网站。为了避免报告太长,我不打算探究 Prosper 数据中的所有相关特性。相反,我将选择一些我认为重要的变量,这些变量也包含在这些来源的变量列表中。

在下一部分中,我将探讨可能与 Prosper 评分相关的主要特征,这些特征有可能使 Prosper 评级在评估贷款质量时更具辨别力****

注:更详细的探索结果请见我的报告中的 Rpubs 和 GitHub 中的代码!

P2P 借贷平台数据分析:R 中的探索性数据分析—第二部分

原文:https://towardsdatascience.com/p2p-lending-platform-data-analysis-exploratory-data-analysis-in-r-part-2-bd0aa04fab99?source=collection_archive---------16-----------------------

发现 P2P 数据特征如何与贷款质量相关联

在上一篇文章中,我们发现 Prosper 采用了一个更好的信用风险指标——Prosper 评级,用于 Prosepr 借贷平台。我们知道 Prosper 评级由 Prosper 评分征信机构评分组成,我们还发现 Prosper 评分起着关键作用,这使得 Prosper 评级比征信机构评分本身更具歧视性。

在这篇文章中,我将调查 Prosper Score 与该贷款数据中的其他特征之间的关系,以了解这些特征如何链接到 Prosper Score、这些特征如何在该 P2P 借贷平台中区分已完成贷款和高风险贷款

第一步:相关矩阵

在这个包含 81 个变量的庞大数据集中,为了避免这篇文章太长,我不会开始逐一寻找潜在的有用特性。相反,我将从一个带有ggcorrplot的相关矩阵开始,以便在深入研究之前快速了解特性之间的线性关系。通过相关矩阵,我们可以关注我们感兴趣的变量——Prosper Score,并查看其他变量是否与之相关。

我们可以看到繁荣评级借款人利率有很强的负相关关系,这是有道理的,因为借款人利率主要由繁荣评级决定。此外, Prosper 评级Prosper 评分有很强的相关性,相关系数为 0.8 ,而信用评分平均值为 0.6 。这再次表明可能 Prosper 对 Prosper 评分比对信用评分平均值更重视,以便从线性角度对 Prosper 评级进行建模。

此外,我们可以看到 Prosper Scorescorexchangeattimeflistinginquiries last 6 个月银行卡使用率debttoincommeratiostatedmonthyincome呈弱线性关系,相关系数范围为+- 0。虽然这些特征与 Prosper Score 呈弱线性关系,但我认为这些特征中可能仍然存在一些信息。通过使用相关矩阵作为参考,我将选取这五个特征,然后绘制散点图,以进一步研究这些特征之间的更多趋势。

我通过剧情的调查包括两部分:一是看这些特征如何与 Prosper Score 挂钩;另一个是看这些特征是否能区分完整贷款和高风险贷款。

得分 X 上市时的变化

scorexchangeattimeflisting*测量提取信用档案时借款人的信用评分变化,其中变化相对于借款人的最后一笔 Prosper 贷款**。scorexchangeattimeflisting的值可以是正的也可以是负的,因为它评估信用评分的值“变化”。*

上图显示,Prosper 得分和scorexchangeattimeflisting之间的线性趋势很明显,随着 Prosper 得分的一个点的增加而增加。我推断 Prosper Score seescorexchangeattimeflisting是一个重要的信号,并将其与线性增量一起用于模式 Prosper Score。

它与贷款状态有什么联系?

在 Prosper Score 和scorexchangeattimeflisting、中对贷款状态进行分组,我们可以看到趋势很明显。高风险贷款往往有较低的 Prosper 评分为 1 到 6,而**较低的scorexchangeattimeflisting范围为-100 到 50。已完成的贷款往往具有从 6 到 10 的较高的 Prosper 得分和从-50 到 100 的较高的scorexchangeattimeflisting。似乎 Prosper Score 可以区分scorexchangeattimeflisting中不同级别的已完成和高风险贷款

这个探索结果有点有趣,因为scorexchangeattimeflisting考虑了借款人相对于借款人最近一次 Prosper 贷款的信用评分,这意味着该指标不仅考虑了借款人的信用评分,还考虑了 Prosper 数据的历史记录。基于这一概念,我对 Prosper 充分利用信用评分Prosper 数据印象深刻,它确实在已完成和高风险贷款中呈现出这样的趋势。

最近 6 个月的调查

此变量评估过去六个月提取信用档案时的查询数量。查询是指机构向信用机构请求信用信息。一般来说,当某人频繁申请信用卡等信用账户时,就会在短时间内出现大量查询,这意味着他或她有很高的资金需求。

在散点图中我们可以看到这种关系并不明确,大多数贷款位于第 1 到 2 次的 InquiriesLast6Months 个月中,跨越 Prosper 得分 2 到 10。但是随着 Prosper 得分的增加,持续 6 个月的调查的上限债券下降的趋势仍然存在。**

尽管如此,在 Prosper Score 和调查中,过去 6 个月的贷款状况趋势仍不明朗。我们可以看到,大多数高风险贷款主要位于 Prosper 得分较低的级别,但它们广泛分布在每个级别的调查中,过去 6 个月Prosper 得分保持不变。

只调查过去 6 个月贷款状况的差异如何?

从上图中我们可以看到,在高风险贷款和已完成贷款之间,过去 6 个月的查询没有显著差异。**

这个结果是合理的,因为借款人过去 6 个月的高询问率并不直接暗示他或她有不良信用。它可能有潜在的风险,但至少在这个数据集中不是必要的。

银行卡使用情况

**银行卡利用率衡量借款人在提取信用档案时使用的信用限额总额。比率越低,一个人的金融流动性越大。

从箱线图来看,银行卡使用率的分布随着 Prosper 得分的增加而向下移动,但是银行卡使用率的方差在各个 Prosper 得分上都很高,这使得 Prosper 得分和银行卡使用率之间的趋势不明显。但是大致相反的趋势仍然存在,尤其是 Prosper 得分的高端和低端水平。也许 Prosper Score 在他们的模型中使用了一些更复杂的方式。**

Prosper Score 和银行卡使用率之间的贷款状态趋势不明确。我们可以看到,大多数高风险贷款主要位于 1 至 6 的 Prosper 评分较低的级别,但它们广泛分布在保持 Prosper 评分不变的银行卡使用的各个级别。

尽管如此,这个结果并没有让我感到惊讶,因为有时高的银行卡使用率对一个信用不良的人来说并不必要。他或她可能只是在那个时候有一个高债务信用,但仍然会按时付款。

上图显示银行卡使用率在高风险贷款中的分布略高于已完成贷款,但两者的银行卡使用率、的方差都很大,使得两者没有显著差异。

债务收入比

一般来说,较高的债务收入比表明如果一个人的债务超过了他或她的收入。相反,较低的债务收入比意味着债务和收入之间的良好平衡。

在这里,我们可以看到,随着 Prosper 得分的增加,当debttoincommeratio下降时,上图呈现出明显的线性反向趋势。

上图显示了 Prosper Score 中贷款状态和debttoincommeratio的明显趋势。高风险贷款的 Prosper 得分往往较低,为 1 比 6,债务与收入比率为 0.5 比 1。已完成的贷款往往具有较高的 Prosper 评分,在 6 到 10 之间,而debttoincommeratio在 0.1 到 0.6 之间。似乎 Prosper Score**可以区分debttoincommeratio中不同级别的已完成和高风险贷款**

这个结果看起来是合理的,因为 T42 是衡量一个人偿还能力的直接信号。

规定月收入

作为收入数据,的统计月收入的分布从直方图中呈现出右偏的形状(此处未显示),所以我去掉了统计月收入变量的前 1%。**

上图显示,Prosper 得分和月收入之间的趋势呈上凹状。这是合理的,因为收入也是衡量偿债能力的一个直接指标,显然收入数据的特点使衡量 Prosper 得分呈指数级递增。多一分的财富分数需要更高的收入水平。

上图显示,Prosper 得分和月收入与贷款状态之间存在明显的趋势。高风险贷款的 Prosper 评分往往较低,在 1 至 6 分之间,并且的月收入水平较低,在 2,000 美元至 5,000 美元之间。相反,已完成贷款的 Prosper 评分更高,在 7 到 10 分之间,月收入更高,在 5,000 美元到 10,000 美元之间。与debttoincommeratioscorechangeattimeflisting 类似,Prosper 得分很可能能够区分月收入不同级别的已完成或高风险贷款。**

探索总结

我们挑选了五个特征,看看它们是否具有与 Prosper Score相关的趋势,并看看它们是否能够区分已完成贷款和高风险贷款。勘探结果表明:

  • scorexchangetimeflistingDebtToIncomeRatio均与 Prosper 得分呈线性趋势。前者呈现正相关关系;后者与 Prosper 得分呈负相关。**
  • scorexchangeattimeflistingDebtToIncomeRatio在不同的 Prosper 评分水平上,完成的和高风险的都有明确的模式。高风险贷款倾向于具有较低的 Prosper 评分水平,并且具有较低的scorechangeattimeflisting和较高的debttoincommeratio保持 Prosper 评分不变 完成贷款往往具有较高的 Prosper 水平,并且具有较高的scorechangeattimeflisting和较低的debttoincommeratio持有 Prosper 得分不变。******
  • StatedMonthlyIncome也随着 Prosper Score 呈现出一种趋势,但这种趋势是一种递增的上凹趋势,而不是线性的。这表明 Prosper Score多一分需要更高等级的 StatedMonthlyIncome。**
  • StatedMonthlyIncome****在完成和高风险两个不同等级的 Prosper 评分中也有明确的模式。高风险贷款倾向于具有较低的 Prosper 得分水平,并且具有较低的月收入保持 Prosper 得分不变。**
  • 调查对象最近 6 个月银行卡使用率** 与 Prosper 评分和贷款状况不呈现显著趋势。**

到目前为止,我们已经看到了一些与 Prosper 得分和贷款状态相关联的利息模式,我们发现scorexchangeattimeflisting、debttoincominratioStatedMonthlyIncomeProsper 得分有明显的趋势。将这三个特征考虑到不同级别的 Prosper 得分中,我们可以看到它们在已完成贷款和高风险贷款之间呈现出清晰的模式,保持 Prosper 得分不变。

毫不奇怪,表示的月收入 呈现这样的趋势,因为这两者是对偿债能力的直接衡量。但令我印象深刻的是,scorexchangeattimeflistingProsper Score 呈现出一种趋势,也显示出区分已完成贷款和高风险贷款的能力。**

P2P 贷款是一个新概念,其信用风险衡量也是如此。在整个项目中,我们一直在挖掘一些关于 Prosper 的背景知识,使用 EDA 基本工具找出一些与 Prosper 的信用风险衡量相关联的特征— Prosper Rating 和 Prosper score。与传统的衡量方法——信用局评分不同,这些特征展示了在借贷平台中高风险贷款和已完成贷款之间的不错的评估能力。并且这些特征也被建模,其利用了信用局分数平台贷款数据。我认为这样一个有趣的概念可以用于 P2P 借贷平台中进一步的数据科学应用,如预测违约率或不良贷款。

希望你喜欢这种基于概念的探索性数据分析!

注:更多详细探索结果,请参见我的报告中的 Rpubs 和代码 GitHub

使用 PaaS 加速数据科学

原文:https://towardsdatascience.com/paas-to-accelerate-data-science-dc-os-data-science-engine-656842dd7ba8?source=collection_archive---------17-----------------------

试用 DC/操作系统数据科学引擎

作为一名专注于向市场提供新产品的全栈机器学习工程师,我经常发现自己处于数据科学、数据工程和开发运营的交叉点。因此,我一直怀着极大的兴趣关注着数据科学平台即服务(PaaS)的兴起。在这一系列帖子中,我将评估不同的平台即服务(PaaS)及其自动化数据科学运营的潜力。我将探索他们的能力,然后自动设置和执行我即将出版的书中的代码 (O'Reilly,2020 年),为这本书的读者找到阅读这本书的最佳方式。

在我的上一本书敏捷数据科学 2.0 (4.5 星:D)中,我为读者构建了自己的平台,使用 bash 脚本、AWS CLI、 jq 、vagger 和 EC2 运行代码。虽然这使得这本书对那些运行代码有困难的初学者来说更有价值,但是维护和保持运行是非常困难的。旧软件从互联网上脱落,平台腐烂。这个项目已经出现了 85 个问题,虽然许多问题已经通过读者的贡献得到了解决,但它仍然占据了我在开源软件上花费的大量时间。这次会有所不同。

注:本岗位代码可在github.com/rjurney/paas_blog获得

DC/操作系统数据科学引擎

DC/OS is a highly scalable PaaS

我评估的第一个数据科学 PaaS 是新推出的 DC/OS 数据科学引擎。在这篇文章中,我将通过 GUI 向您介绍我对 DC/OS(注意:我过去曾使用过它)及其数据科学引擎的初步实验,然后我们将讲述如何用几行代码来自动化相同的过程。事实证明,这实际上比使用 AWS CLI 创建等效资源更简单,这给我留下了深刻的印象。我们将设置我们的环境和软件先决条件,使用 Terraform 和通用安装程序初始化 DC/操作系统集群,安装数据科学引擎包,然后通过运行标记堆栈溢出帖子的模型来评估环境。

一些警告:我们将一步一步地介绍如何引导安装了 JupyterLab 的 DC/OS 集群,但是如果您遇到麻烦,您可以随时参考通用安装程序文档来解决 DC/OS 平台问题,或者参考数据科学引擎文档来解决部署该服务的问题。

为什么选择 DC/操作系统数据科学引擎?

在任何给定的云环境中,如亚马逊网络服务(AWS)、谷歌云平台(GCP)和 Azure,为个人数据科学家工作设置一个 Jupyter 笔记本已经变得相当容易。对于创业公司和小型数据科学团队来说,这是一个很好的解决方案。没有什么需要维护的,笔记本可以保存在 Github 中以便持久化和共享。

对于大企业来说,事情没有这么简单。在这种规模下,跨多个云的临时资产上的临时环境可能会造成混乱而不是秩序,因为环境和建模变得不可复制。企业跨多个云和在本地工作,具有特定的访问控制和身份验证要求,并且需要提供对内部资源的访问以获得数据、源控制、流和其他服务。

对于这些组织,DC/操作系统数据科学引擎提供了一个统一的系统,该系统提供 Python ML 堆栈、Spark、Tensorflow 和其他 DL 框架,包括TensorFlowOnSpark以支持分布式多节点、多 GPU 模型训练。这是一个非常引人注目的设置,开箱即用,可以结束大型数据科学团队和公司的许多挫折和复杂性。

软件和平台先决条件

DC/操作系统通用安装程序可以在 Linux、Mac OS X 和 Windows 上运行。对于所有平台,你都需要 PythonpipAWS 命令行界面(CLI)Terraform 。如果您正在测试数据科学引擎,您可能已经安装了 Python,但是如果没有,我们将安装 Anaconda Python

您还需要在运行 DC/操作系统数据科学引擎的地区授权 5 个 GPU 实例(在本文中,我们使用“us-west-2”)。让我们一步一步来。

安装 Anaconda Python

Anaconda Python

如果您的机器上已经安装了 Python,就没有必要安装 Anaconda Python。如果您不知道,我推荐 Anaconda Python,因为它易于安装,位于您的主目录中,并且具有优秀的 conda 包管理器。

下载蟒蛇 Python 3。x 为您的平台这里,然后按照说明安装 LinuxMac OS XWindows

通过安装和配置 Amazon Web Services CLI 进行 AWS 身份验证

Terraform AWS 提供者设置 AWS 访问有两种方式:通过 AWS CLI 或通过编辑(来自 Github 项目根的路径)PAAs _ blog/dcos/terra form/terra form . TF

首先,我们将为 Terraform 设置要使用的 AWS 凭证。要使用 PyPI awscli 包:

# Install using conda
conda install -c conda-forge awscli# OR…# Install using pip
pip install awscli --upgrade --user

现在使用您的访问密钥 ID 和秘密访问密钥设置您的 AWS 凭证,您可以在 IAM 控制台中找到它们。您可以将区域更改为您自己的默认值。Terraform 的 AWS 模块将默认使用这些凭证。它们存放在 ~/中。aws/ 目录。

aws configureAWS Access Key ID [None]: **AKIAIOSAODNN7EXAMPLE**
AWS Secret Access Key [None]: **wJalrXUtnFEMI/K7MBENG/bPxRfiCYEXAMPLEKEY**
Default region name [None]: **us-west-2**
Default output format [None]: **json**

现在验证设置是否有效:

aws sts get-caller-identity

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

{
  “UserId”: “123456789101”,
  “Account”: “109876543210”,
  “Arn”: “arn:aws:iam::123456789101:root”
}

通过编辑 terraform.tf 进行 AWS 身份验证

您可以通过编辑(从项目根目录)PAAs _ blog/dcos/terra form/terra form . TF来显式设置 AWS 身份验证,以便在调用 AWS 提供者时包含您的凭证。只需添加您的访问密钥/秘密密钥和默认区域。

provider “aws” {
  access_key = “foo”
  secret_key = “bar”
  region = “us-west-2”
}

安装 Terraform

Terraform 使用户能够使用一种称为 Hashicorp 配置语言(HCL)的高级配置语言来定义和配置数据中心基础架构。

—维基百科,Terraform(软件)

DC/OS 通用安装程序需要安装 Terraform 11.x. Ubuntu 用户可以像这样安装 Terraform 11.x:

wget [https://releases.hashicorp.com/terraform/0.11.14/terraform_0.11.14_linux_386.zip](https://releases.hashicorp.com/terraform/0.11.14/terraform_0.11.14_linux_386.zip)
sudo apt-get install unzip
unzip terraform_0.11.14_linux_386.zip
sudo mv terraform /usr/local/bin/

在 Mac 上,使用自制软件:

brew unlink terraform || true
brew install tfenv
tfenv install 0.11.14

Windows 用户可以使用 Chocolatey :

choco install terraform --version 0.11.14 -y

验证 terraform 是否有效:

terraform --version

您应该看到:

Terraform v0.11.14

现在我们可以走了!忽略任何关于升级的消息。既然已经安装了 Terraform,我们就可以在 AWS 上配置和启动我们的 DC/操作系统集群了。

为 GPU 实例授权 AWS 服务限制

AWS 服务限制定义您在任何给定地区可以使用多少 AWS 资源。我们将启动 5 个 p 3.2x 大型 GPU 实例,作为运行笔记本电脑的 DC/操作系统集群的私有代理。p 3.2x 大型实例类型的默认服务配额为 0。为了运行本教程,您需要请求 AWS 将这个值增加到 5 或更多。

您可以通过登录 AWS Web 控制台并访问此处的服务配额控制台来完成此操作:https://us-west-2 . Console . AWS . Amazon . com/Service Quotas/home?区域=美国-西部-2#!/services/ec2/quotas (您可以在 url 中替换您首选的 AWS 区域,只要确保将其替换在 url 中出现的 both places 中即可)。在搜索框中搜索 p3.2xlarge ,点击右侧橙色请求配额增加按钮。

AWS Service Limit Quota Increase for p3.2xlarge instances

更改配额值字段中输入 5 。然后点击右下角的橙色请求按钮。

Quota Increase Submit Form

现在,您必须等待 12-48 小时,请求才能获得批准。我有一个基本的 AWS 帐户,当我在下午请求增加时,它在第二天早上被批准。如果您需要加快速度,您可以前往 AWS 支持中心请求代理致电。他们通常可以加速很多事情。

带通用安装程序的 AWS 上的 DC/操作系统

d2iq.com上有很好的文档用于 DC/操作系统通用安装程序,但是我将在这篇文章中提供“正常工作”的代码。我们将使用 Terraform 来配置和启动我们的集群,然后我们将安装数据科学引擎包,并开始使用 JupyterLab!

注:将目录改为 Github 项目 子目录PAAs _ blog/dcos/terraform以了解教程的剩余内容。

配置 DC/操作系统

配置 DC/操作系统集群的第一步是创建一个特定于集群的 ssh 密钥。我们把这个键叫做 my_key.pub

ssh-keygen -t rsa -f my_key

按两次回车键创建没有密码的密钥。

Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in my_key.
Your public key has been saved in my_key.pub.
The key fingerprint is:
SHA256:OCOfrIzrTznoMqKOJ2VD2r6YPQp8jFFKIbe/BDyhWuI rjurney@Hostname.local
The key’s randomart image is:
+ — -[RSA 2048] — — +
|..o                |
|.+.o               |
|o.*.               |
|+o++ .             |
|.E + + S           |
|o Oo * +           |
|.*.+= +            |
|B==+ o             |
|XOB=+              |
+ — — [SHA256] — — -+

我们需要把 my_key 的权限改成只对我们的用户 0600 可读,不然以后 ssh 会抱怨的。

chmod 0600 ./my_key

现在运行ssh-agent(如果它没有运行)并将密钥添加到代理中。

注意:如果没有这个步骤,在创建集群时会出现 ssh 错误。请参见下面的常见错误部分。

eval "$(ssh-agent -s)"
ssh-add ./my_key

现在,验证是否已经添加了密钥:

ssh-add -l

这应该显示:

2048 SHA256:1234567891234567891234567891234567891234567 ./my_key (RSA)

通过脚本创建超级用户密码哈希

现在我们将使用 Python 的 hashlib 模块为集群创建一个超级用户密码散列文件。我们将调用我们的dcos _ super user _ password _ hash

我已经创建了一个命令行脚本,它将生成、打印一个名为PAAs _ blog/dcos/terra form/generate _ password _ hash . py的密码散列并写入磁盘。

usage: generate_password_hash.py [-h] PASSWORDGenerate an SHA512 password hash for the given passwordpositional arguments:
 PASSWORD A password to generate a SHA512 hash ofoptional arguments:
 -h, — help show this help message and exit

要运行它,只需运行:

python ./generate_password_hash.py my_password

您应该会看到类似这样的输出:

Wrote SHA512 digest: '1234567891011121314151617181920212223242526…' for password 'my_password' to ./dcos_superuser_password_hash

验证写入文件dcos _ super user _ password _ hash是否成功:

cat dcos_superuser_password_hash

在 Python 中创建超级用户密码散列

要手动创建散列,请打开 Python shell(考虑使用 ipython ):

python # or ipython

现在运行以下代码:

import hashlibwith open('dcos_superuser_password_hash', 'w') as f:
  m = hashlib.sha512('my_password'.encode())
  f.write( m.hexdigest() )

将密码散列的权限更改为仅对您的用户可读, 0600 ,否则 DC/操作系统 CLI 将报错:

chmod 0600 ./dcos_superuser_password_hash

验证密码已成功保存:

cat dcos_superuser_password_hash

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

dda8c3468860dcb2aa228ab8ee44208d43eb2f5fd2a3a538bafbd8860dcb24e228ab8ee44208d43eb2f5a2f8b143eb2f5a2f8b17eccc87ffe79d8459e2df294fb01

创建许可证文件—(仅限企业版)

由于我们将使用开放版本的 DC 操作系统,我通过touch license.txt创建了一个空的 license.txt 文件。它需要存在,但可以是空的。它已经致力于 Github,所以对于 DC/OS 的开放版本,一旦你签出了 GitHub 项目,你就不需要创建它了。如果您使用的是企业版,您需要将您的实际许可证放在 license.txt 中。

配置我们的 DC/操作系统集群

我已经编辑了文件PAAs _ blog/dcos/terra form/desired _ cluster _ profile . TF vars以个性化超级用户帐户名称,从我们上面创建的密码哈希文件中加载超级用户密码哈希,以指定空的许可证字符串并指向空的 license.txt 文件。DC/操作系统版本设置为 open ,DC/操作系统版本设置为 1.13.3 ,我们将使用一个 m5.xlarge 作为我们的引导实例类型,我们将使用 p3.2xlarge 实例来运行 JupyterLab。我们将 GPU 代理的数量设置为 5,这足以运行 Spark 和 JupyterLab。最后,我们指定我们之前生成的公钥, my_key.pub 。记住使用公钥,而不是私钥。

注:你可以在发布页面找到最新版本的 DC/OS,点击其 Github repo 上的标签可以找到最新版本的通用安装程序。如果遇到问题,通过编辑 terraform.tf 中的版本键,使用最高的 0.2.x 标签。

cluster_owner = "rjurney"
dcos_superuser_password_hash = "${file("dcos_superuser_password_hash")}"
dcos_superuser_username = "rjurney"
dcos_license_key_contents = ""
dcos_license_key_file = "./license.txt"
dcos_version = "1.13.4"
dcos_variant = "open"
bootstrap_instance_type = "m5.xlarge"
gpu_agent_instance_type = "p3.2xlarge"
num_gpu_agents = "5"
ssh_public_key_file = "./my_key.pub"

注意:如果您使用的是 DC 操作系统的企业版,您需要填写dcos _ license _ key _ contents,对于开放版本,我们会将其留空。您还需要更改配置,使dcos_variant = “ee”。

初始化地形

首先,我们需要用我们将要使用的所有模块初始化 Terraform:

terraform init -upgrade

您应该看到:

Upgrading modules...<list of modules>
Initializing provider plugins…
<list of plugins>Terraform has been successfully initialized!

生成地形图

现在我们需要使用我们在PAAs _ blog/dcos/terraform/desired _ cluster _ profile . TF vars中定义的变量来生成一个行动计划供 terra form 执行。我们将计划保存到PAAs _ blog/dcos/terra form/plan . out

terraform plan -var-file desired_cluster_profile.tfvars -out plan.out

您应该会看到很多没有错误的输出,结尾是:

Plan: 75 to add, 3 to change, 0 to destroy. — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — This plan was saved to: plan.outTo perform exactly these actions, run the following command to apply:
 terraform apply "plan.out"

现在我们有一个计划,让 Terraform 在 plan.out 中创建我们的 DC/操作系统集群,它是二进制的,不太容易检查。

启动我们的 DC/操作系统集群

现在我们已经有了一个包含自定义变量的计划,我们不需要在 apply 命令中再次包含它们。我们可以按照plan命令输出末尾的指示去做。注意,我们没有将--var-file与 apply 一起使用,因为 plan 已经将我们的变量插入到计划中。

terraform apply plan.out

该命令可能需要长达 15 分钟的时间来执行,因为在初始化 AWS 资源序列,然后执行命令来初始化 EC2 实例上的服务时会有延迟。您应该会看到很多输出,开始是:

module.dcos.module.dcos-infrastructure.module.dcos-lb.module.dcos-lb-masters.module.masters.tls_private_key.selfsigned: Creating...<lots more stuff>

如果您看到任何错误,最好是销毁集群并重试。AWS 资源延迟初始化中的定时问题有时会导致引导问题。

摧毁我们的 DC/操作系统集群

当您完成集群时,如果有错误,或者如果您需要重新创建它,您可以使用下面的命令销毁所有相关的资源。注意,我们确实需要将--var-filedestroy一起使用。

terraform destroy --auto-approve --var-file desired_cluster_profile.tfvars

这可能需要一点时间,因为有许多资源要删除。一旦销毁完成,你可以自由地计划和再次申请。

登录我们的 DC/操作系统集群

“terraform apply”命令的最终输出为我们提供了要连接的主节点的地址,应该如下所示:

Apply complete! Resources: 75 added, 0 changed, 0 destroyed.Outputs:masters-ips = [
  54.XX.XXX.XXX
]
public-agents-loadbalancer = ext-jupyter-gpu-12a9-abcde6g1234.elb.us-west-2.amazonaws.com

在浏览器中打开主 ip 地址,您应该会看到一个登录窗口。请注意,唯一授权连接到这台机器的 IP 是您的源 IP。

DC/OS Cluster Authentication Page

选择你的认证方式——我用谷歌。一旦您通过验证,它会将您返回到主页。

安装数据科学引擎服务

DC/OS Dashboard

在左侧菜单中,从顶部往下数第四个,在此图中用橙色圈出的是Catalog项目。点击它,DC/操作系统服务菜单将出现。当我这样做的时候,数据科学引擎服务就出现在第二行,如果没有的话,可以使用左上角的搜索框来找到它。

The DC/OS Service Catalog — Every Package a One Click Instasll

点击数据-科学-引擎服务,其服务页面就会出现。点击查看&运行安装服务。

The Data Science Engine Catalog Page

这将打开一个窗口,您可以在其中编辑数据科学引擎的配置。您需要使用字母和破折号来命名集群,但是您如何命名并不重要,除非名称是唯一的。因为我们使用的是 p3.2xlarge 实例,所以将服务配置为使用 58GB 内存和 8 个 CPU。选中 Nvidia GPU 分配配置已启用复选框,并为 GPU 数量键入 1。

Data Science Engine Service Configuration

点击右上角的紫色审查&运行按钮。这将带您进入最终审查屏幕。点击右上角的紫色运行服务按钮。

请注意,您可以将服务配置作为 JSON 下载,以便稍后使用 DC/OS CLI 运行,从而使您能够自动部署服务,例如作为您的持续集成系统的一部分。为此,请单击下载配置。

Data Science Engine Run Confirmation Page

您应该会看到一个弹出窗口,宣布系统成功启动。点击打开服务

Service Confirmation Popup

这将带您进入数据科学引擎服务页面。起初,页面的状态会显示服务正在加载,但很快健康样本会变成绿色,状态会显示正在运行

Data Science Engine Service Page

使用数据科学引擎

现在点击文本服务,在屏幕白色区域的顶部显示服务>数据科学引擎。这将带您进入服务列表。您应该会看到列出了数据科学引擎。单击下图中用橙色圈出的启动图标。这将打开与 JupyterLab 的连接。默认的 Jupyter 密码是 jupyter ,但是您可以使用我们用来启动服务的服务配置窗口来设置它。

Running Services Page — Click on the open icon to open JupyterLab

一旦输入 jupyter 的默认 Jupyter 密码(可以在desired _ cluster _ profile . TF vars中更改),就会看到 JupyterLab 的主页。第一页加载可能需要一点时间。Tada!

JupyterLab Dashboard

用一些自然语言处理来锻炼我们的 GPU

现在我们已经启动了集群和服务,让我们通过训练一个神经网络来标记堆栈溢出问题来练习它。我们将此视为一个多类别、多标签的问题。通过对至少有一个答案、一个投票并且至少有一个标签出现超过 2000 次的问题的完整转储进行上采样,来平衡训练数据。大约 600MB。这个数据集是之前计算的,文件可以在 Github repo 的 paas_blog/data 目录中找到。

你可以在 github.com/rjurney/paas_blog/DCOS_Data_Science_Engine.ipynb的 Github 上查看 Jupyter 笔记本的代码。我们将使用 JupyterLab Github 接口打开它,但是如果你愿意,你可以将它的内容逐块粘贴到新的 Python 3 笔记本中。

加载教程笔记本

JupyterLab 的 Github 模块超级棒,让加载教程笔记本变得很容易。点击屏幕最左边的 Github 图标,在文件和跑男图标之间。在显示 <的地方输入 rjurney 编辑用户>

JupyterLab’s Github Browser

我的公共 Github 项目将会出现。选择 paas_blog 然后双击DCOS _ 数据 _ 科学 _ 引擎. ipynb Jupyter 笔记本打开。它使用 S3 的数据,所以你不必下载任何数据。

Example Notebook from Github Loaded in JupyterLab

验证 GPU 支持

要做的第一件事是验证我们的数据科学引擎 EC2 实例上的 JupyterLab Python 环境是否正确配置为与其板载 GPU 一起工作。我们使用tensorflow.test.is_gpu_availabletensorflow.compat.v2.config.experimental.list_physical_devices来验证 GPU 是否与 Tensorflow 一起工作。

gpu_avail = tf.test.is_gpu_available(
  cuda_only=False,
  min_cuda_compute_capability=None
)
print(f'1 or more GPUs is available: {gpu_avail}')from tensorflow.python.client import device_lib
local_devices = device_lib.list_local_devices()
gpu = local_devices[3]
print(f"{gpu.name} is a {gpu.device_type} with {gpu.memory_limit / 1024 / 1024 / 1024:.2f}GB RAM")

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

1 or more GPUs is available: True
/device:GPU:0 is a GPU with 10.22GB RAM

从 S3 加载数据

您可以使用 pandas.read_parquet 加载本教程的数据。

# Load the Stack Overflow questions right from S3
s3_parquet_path = f's3://{BUCKET}/08–05–2019/Questions.Stratified.Final.2000.parquet'
s3_fs = s3fs.S3FileSystem()# Use pyarrow.parquet.ParquetDataset and convert to pandas.DataFrame
posts_df = ParquetDataset(
  s3_parquet_path,
  filesystem=s3_fs,
).read().to_pandas()posts_df.head(3)

现在我们加载索引,在标签索引和文本标记之间来回转换。我们将使用这些来查看教程最后预测的实际结果标签。

# Get the tag indexes
s3_client = boto3.resource('s3')def json_from_s3(bucket, key):
  """Given a bucket and key for a JSON object, return the parsed object"""
  obj = s3_client.Object(bucket, key)
  obj.get()['Body'].read().decode('utf-8')
  json_obj = json.loads(obj.get()[‘Body’].read().decode('utf-8'))
  return json_objtag_index = json_from_s3(BUCKET, '08–05–2019/tag_index.2000.json')
index_tag = json_from_s3(BUCKET, '08–05–2019/index_tag.2000.json')list(tag_index.items())[0:5], list(index_tag.items())[0:5]

然后,我们验证加载的记录数量:

print(
  ‘{:,} Stackoverflow questions with a tag having at least 2,000 occurrences’.format(
    len(posts_df.index)
  )
)

您应该看到:

1,554,788 Stackoverflow questions with a tag having at least 2,000 occurrences

准备数据

我们需要将之前标记化的文本连接回字符串,以便在标记化器中使用,标记化器提供了有用的属性。此外,Tensorflow/Keras 需要将文档数量设为批量的倍数,以便在多个 GPU 之间分配工作,并使用某些模型,如 Elmo。

import mathBATCH_SIZE = 64
MAX_LEN = 200
TOKEN_COUNT = 10000
EMBED_SIZE = 50
TEST_SPLIT = 0.2# Convert label columns to numpy array
labels = posts_df[list(posts_df.columns)[1:]].to_numpy()# Training_count must be a multiple of the BATCH_SIZE times the MAX_LEN
highest_factor = math.floor(len(posts_df.index) / (BATCH_SIZE * MAX_LEN))
training_count = highest_factor * BATCH_SIZE * MAX_LEN
print(f'Highest Factor: {highest_factor:,} Training Count: {training_count:,}')# Join the previously tokenized data for tf.keras.preprocessing.text.Tokenizer to work with
documents = []
for body in posts_df[0:training_count]['_Body'].values.tolist():
  words = body.tolist()
  documents.append(' '.join(words))labels = labels[0:training_count]# Conserve RAM
del posts_df
gc.collect()# Lengths for x and y match
assert( len(documents) == training_count == labels.shape[0] )

您应该看到:

Highest Factor: 121 Training Count: 1,548,800

填充序列

数据已经被删减到每篇 200 字,但在一些文档中,使用 10K 顶级词汇的标记化将这一数据缩减到 200 字以下。如果任何文件超过 200 字,这些数据就不能正确地转换成下面的数字矩阵。

除了用一个键将文本转换成数字序列,Keras' Tokenizer 类对于通过[keras.preprocessing.text.Tokenizer.sequences_to_texts](https://keras.io/preprocessing/text/#tokenizer)方法生成模型的最终结果也很方便。然后,我们使用 Keras' [keras.preprocessing.sequence.pad_sequences](https://keras.io/preprocessing/sequence/#pad_sequences)方法并检查输出,以确保序列的长度都是 200 项,否则它们不会正确地转换为矩阵。字符串__PAD__以前已经被用来填充文档,所以我们在这里重用它。

from tf.keras.preprocessing.text import Tokenizer
from tf.keras.preprocessing.sequence import pad_sequencestokenizer = Tokenizer(
  num_words=TOKEN_COUNT,
  oov_token='__PAD__'
)
tokenizer.fit_on_texts(documents)
sequences = tokenizer.texts_to_sequences(documents)padded_sequences = pad_sequences(
  sequences,
  maxlen=MAX_LEN,
  dtype='int32',
  padding='post',
  truncating='post',
  value=1
)# Conserve RAM
del documents
del sequences
gc.collect()print( max([len(x) for x in padded_sequences]), min([len(x) for x in padded_sequences]) )
assert( min([len(x) for x in padded_sequences]) == MAX_LEN == max([len(x) for x in padded_sequences]) )padded_sequences.shape

分成测试/训练数据集

我们需要一个数据集来训练,一个单独的数据集来测试和验证我们的模型。经常使用的[sklearn.model_selection.train_test_split](https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.train_test_split.html)使它如此。

from sklearn.model_selection import train_test_splitX_train, X_test, y_train, y_test = train_test_split(
  padded_sequences,
  labels,
  test_size=TEST_SPLIT,
  random_state=1337
)# Conserve RAM
del padded_sequences
del labels
gc.collect()assert(X_train.shape[0] == y_train.shape[0])
assert(X_train.shape[1] == MAX_LEN)
assert(X_test.shape[0] == y_test.shape[0]) 
assert(X_test.shape[1] == MAX_LEN)

计算类别权重

虽然已经对数据进行了过滤和上采样,以将其限制在至少有一个标签出现超过 2000 次的问题样本中,但常见标签和不常见标签之间的比率仍然不均衡。如果没有类权重,最常见的标签比最不常见的标签更有可能被预测到。类别权重将使损失函数更多地考虑不常用的类别,而不是常用的类别。

train_weight_vec = list(np.max(np.sum(y_train, axis=0))/np.sum(y_train, axis=0))
train_class_weights = {i: train_weight_vec[i] for i in range(y_train.shape[1])}sorted(list(train_class_weights.items()), key=lambda x: x[1])[0:10]

训练分类器模型来标记堆栈溢出帖子

现在,我们准备训练一个模型,用标签类别对问题进行分类/标记。该模型基于 Kim-CNN ,一种常用于句子和文档分类的卷积神经网络。我们使用函数式 API,并对代码进行了大量参数化处理,以便于实验。

from tensorflow.keras.initializers import RandomUniform
from tensorflow.keras.callbacks import ReduceLROnPlateau, EarlyStopping, ModelCheckpoint
from tensorflow.keras.layers import (
  Dense, Activation, Embedding, Flatten, MaxPool1D, GlobalMaxPool1D, Dropout, Conv1D, Input, concatenate
)
from tensorflow.keras.losses import binary_crossentropy
from tensorflow.keras.models import Model
from tensorflow.keras.optimizers import AdamFILTER_LENGTH = 300
FILTER_COUNT = 128
FILTER_SIZES = [3, 4, 5]
EPOCHS = 4
ACTIVATION = 'selu'
CONV_PADDING = 'same'
EMBED_SIZE = 50
EMBED_DROPOUT_RATIO = 0.1
CONV_DROPOUT_RATIO = 0.1
LOSS = 'binary_crossentropy'
OPTIMIZER = 'adam'

在 Kim-CNN 中,我们首先使用嵌入对序列进行编码,然后使用去除层以减少过度拟合。接下来,我们将图形分割成多个宽度不同的 Conv1D 层,每个层后面跟有 MaxPool1D 。它们通过串联连接在一起,旨在表征文档中不同大小序列长度的模式。接下来是另一个Conv1D/globalmaxpool 1d层来总结这些模式中最重要的模式。接下来是展平成一个密集层,然后到最后的s 形输出层。否则我们通篇使用卢瑟

padded_input = Input(
  shape=(X_train.shape[1],), 
  dtype=’int32'
)# Create an embedding with RandomUniform initialization
emb = Embedding(
  TOKEN_COUNT, 
  EMBED_SIZE, 
  input_length=X_train.shape[1],
  embeddings_initializer=RandomUniform()
)(padded_input)
drp = Dropout(EMBED_DROPOUT_RATIO)(emb)# Create convlutions of different kernel sizes
convs = []
for filter_size in FILTER_SIZES:
  f_conv = Conv1D(
    filters=FILTER_COUNT,
    kernel_size=filter_size,
    padding=CONV_PADDING,
    activation=ACTIVATION
  )(drp)
  f_pool = MaxPool1D()(f_conv)
  convs.append(f_pool)l_merge = concatenate(convs, axis=1)
l_conv = Conv1D(
  128,
  5,
  activation=ACTIVATION
)(l_merge)
l_pool = GlobalMaxPool1D()(l_conv)
l_flat = Flatten()(l_pool)
l_drop = Dropout(CONV_DROPOUT_RATIO)(l_flat)
l_dense = Dense(
  128,
  activation=ACTIVATION
)(l_drop)
out_dense = Dense(
  y_train.shape[1],
  activation='sigmoid'
)(l_dense)model = Model(inputs=padded_input, outputs=out_dense)

接下来我们编译我们的模型。我们使用各种各样的度量标准,因为没有一个度量标准可以概括模型性能,我们需要深入研究真的和假的肯定和否定。我们还使用 ReduceLROnPlateauEarlyStoppingModelCheckpoint 回调来提高性能,一旦达到稳定状态,我们就提前停止,并且只保留在验证分类准确性方面最好的模型。

分类准确性是衡量我们模型性能的最佳方式,因为它为我们分类的每个类的每一行分别给出了分数。这意味着,如果我们错过了一个,但得到了其他的权利,这是一个伟大的结果。对于二进制精度,整行都被标记为不正确。

然后就是拟合模型的时候了。我们给它我们之前计算的类权重。

model.compile(
  optimizer=OPTIMIZER,
  loss=LOSS,
  metrics=[
    tf.keras.metrics.CategoricalAccuracy(),
    tf.keras.metrics.Precision(),
    tf.keras.metrics.Recall(),
    tf.keras.metrics.Accuracy(),
    tf.keras.metrics.TruePositives(),
    tf.keras.metrics.FalsePositives(),
    tf.keras.metrics.TrueNegatives(),
    tf.keras.metrics.FalseNegatives(),
  ]
)
model.summary()callbacks = [
  ReduceLROnPlateau(
    monitor='val_categorical_accuracy',
    factor=0.1,
    patience=1,
  ), 
  EarlyStopping(
    monitor='val_categorical_accuracy',
    patience=2
  ), 
  ModelCheckpoint(
    filepath='kim_cnn_tagger.weights.hdf5',
    monitor='val_categorical_accuracy',
    save_best_only=True
  ),
]history = model.fit(X_train, y_train,
  class_weight=train_class_weights,
  epochs=EPOCHS,
  batch_size=BATCH_SIZE,
  validation_data=(X_test, y_test),
  callbacks=callbacks
)

从训练时期加载最佳模型

因为我们使用了ModelCheckpoint(save_only_best-True),就CategoricalAccuracy而言,最好的纪元是被保存的。我们想用它来代替上一个纪元的模型,它存储在上面的model中。所以我们在评估模型之前加载文件。

model = tf.keras.models.load_model('kim_cnn_tagger.weights.hdf5')
metrics = model.evaluate(X_test, y_test)

解析并打印最终指标

度量包括像 precision_66 这样的名字,它们在运行之间是不一致的。我们修复这些来清理我们关于训练模型的报告。我们还添加了一个 f1 分数,然后制作一个数据帧来显示日志。这可以在重复实验中推广。

def fix_metric_name(name):
  """Remove the trailing _NN, ex. precision_86"""
  if name[-1].isdigit():
    repeat_name = '_'.join(name.split('_')[:-1])
  else:
    repeat_name = name
    return repeat_namedef fix_value(val):
  """Convert from numpy to float"""
  return val.item() if isinstance(val, np.float32) else valdef fix_metric(name, val):
  repeat_name = fix_metric_name(name)
  py_val = fix_value(val)
  return repeat_name, py_vallog = {}
for name, val in zip(model.metrics_names, metrics):
  repeat_name, py_val = fix_metric(name, val)
  log[repeat_name] = py_val
log.update({'f1': (log['precision'] * log['recall']) / (log['precision'] + log['recall'])})pd.DataFrame([log])

绘制历元精度

我们想知道每个时期的性能,这样我们就不会不必要地训练大量的时期。

%matplotlib inlinenew_history = {}
for key, metrics in history.history.items():
  new_history[fix_metric_name(key)] = metricsimport matplotlib.pyplot as pltviz_keys = ['val_categorical_accuracy', 'val_precision', 'val_recall']# summarize history for accuracy
for key in viz_keys:
  plt.plot(new_history[key])
plt.title('model accuracy')
plt.ylabel('metric')
plt.xlabel('epoch')
plt.legend(viz_keys, loc='upper left')
plt.show()# summarize history for loss
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.title('model loss')
plt.ylabel('loss')
plt.xlabel('epoch')
plt.legend(['train', 'test'], loc='upper left')
plt.show()

Categorical Accuracy, Precision and Recall Across Epochs. Note that recall climbs even on the 8th Epoch

Test / Train Loss

检查实际预测输出

光知道理论性能是不够的。我们需要看到标记者在不同置信度阈值下的实际输出。

TEST_COUNT = 1000X_test_text = tokenizer.sequences_to_texts(X_test[:TEST_COUNT])y_test_tags = []
for row in y_test[:TEST_COUNT].tolist():
   tags = [index_tag[str(i)] for i, col in enumerate(row) if col == 1]
   y_test_tags.append(tags)CLASSIFY_THRESHOLD = 0.5y_pred = model.predict(X_test[:TEST_COUNT])
y_pred = (y_pred > CLASSIFY_THRESHOLD) * 1y_pred_tags = []
for row in y_pred.tolist():
  tags = [index_tag[str(i)] for i, col in enumerate(row) if col > CLASSIFY_THRESHOLD]
  y_pred_tags.append(tags)

让我们来看看在数据帧中带有实际标签和预测标签的句子:

prediction_tests = []
for x, y, z in zip(X_test_text, y_pred_tags, y_test_tags):
  prediction_tests.append({
    'Question': x,
    'Predictions': ' '.join(sorted(y)),
    'Actual Tags': ' '.join(sorted(z)),
 })pd.DataFrame(prediction_tests)

我们可以从这三个记录中看出,该模型做得相当不错。这讲述了一个不同于单独的性能指标的故事。奇怪的是,大多数机器学习的例子只是计算性能,并没有真正使用“predict()”方法!归根结底,统计性能是无关紧要的,重要的是真实世界的性能——它不包含在简单的汇总统计中!

Questions along with Actual Labels and Predicted Labels

自动化 DC/操作系统数据科学引擎设置

这涵盖了如何手动使用平台,但这是关于 PaaS 自动化。那么我们如何加快速度呢?

DC/操作系统的图形用户界面和 CLI 共同支持各类用户通过数据科学引擎轻松访问 JupyterLab:试图在笔记本上查看报告的非技术管理人员和希望自动化流程的开发运营/数据工程师。如果手动 GUI 过程似乎很复杂,我们可以在将服务配置作为 JSON 文件后,通过几行代码将其自动化,方法是通过 Terraform 命令启动 DC/操作系统集群,从 Terraform 获取集群地址,然后使用 DC/操作系统 CLI 验证集群并运行服务。

注:查看 DC/OS CLI 的 Github 页面 了解更多关于它如何工作的信息。

安装 DC/操作系统命令行界面

使用 Terraform 启动集群并在用户界面中手动安装 Data Science 引擎时,不需要 DC/操作系统 CLI,但需要它来自动执行该过程。如果您遇到了麻烦,请查看 CLI 安装文档。你将需要卷发

# Optional: make a /usr/local/bin if it isn’t there. Otherwise change the install path.
[ -d usr/local/bin ] || sudo mkdir -p /usr/local/bin# Download the executable
curl [https://downloads.dcos.io/binaries/cli/linux/x86-64/dcos-1.13/dcos](https://downloads.dcos.io/binaries/cli/linux/x86-64/dcos-1.13/dcos) -o dcos

请注意,您也可以使用打印的命令下载 CLI,方法是单击右上方标题为 jupyter-gpu-xxxx (或您为集群命名的任何名称)的下拉菜单,然后单击下方橙色框中的 Install CLI 按钮。

Note the Install CLI button in the dropdown at top right

将出现一个弹出窗口,显示 Windows、OS X 和 Linux 的安装代码。将代码复制/粘贴到终端以完成安装。

Install Commands for DC/OS CLI

现在,如果您运行dcos,您应该会看到以下内容:

Usage:
  dcos [command]Commands:
  auth
  Authenticate to DC/OS cluster
  cluster
  Manage your DC/OS clusters
  config
  Manage the DC/OS configuration file
  help
  Help about any command
  plugin
  Manage CLI pluginsOptions:
  — version
  Print version information
  -v, -vv
  Output verbosity (verbose or very verbose)
  -h, — help
  Show usage helpUse "dcos [command] — help" for more information about a command.

使用 GUI 手动导出软件包配置

为了自动安装数据科学引擎包,我们首先需要以 JSON 文件的形式获取它的配置。这可以通过两种方式完成:通过 GUI 或通过 DC/操作系统 CLI 或通过 Terraform CLI。我们将介绍这两种方法。

Note the Download Config button below the dividing line at the top right

使用 GUI,我们可以通过从数据-科学-引擎服务页面的配置选项卡下载 JSON 来获得包配置。点击该行右上方紫色的下载配置

顺便说一下,您可以通过点击右上角的紫色编辑按钮来编辑数据科学引擎服务。您可以使用菜单或 JSON 编辑器来更改服务——例如增加 RAM 或 GPUs 它会根据该配置自动重新部署。

Editing the Data Science Engine Service Config

向群集验证 DC/操作系统 CLI

要使用 CLI,我们需要向群集进行身份验证。这可以通过 Google、用户名或其他适合您组织的方法来完成。为此,首先我们需要来自 Terraform 的服务器地址。我们可以通过terraform output -jsonjq json 实用程序提取集群主机 IP 地址。一旦我们有了这些,我们可以使用任何我们喜欢的方法,包括谷歌,来进行认证。这也可以是便于自动化的用户名。

# Get the cluster address from Terraform’s JSON output and Authenticate CLI to Cluster
export CLUSTER_ADDRESS=`terraform output -json | jq -r '.["masters-ips"].value[0]'`
dcos cluster setup [http://$CLUSTER_ADDRESS](/$CLUSTER_ADDRESS) # add whatever arguments you need for automated authentication

查看dcos cluster setup文档,了解不同认证方法的信息。

使用 CLI 导出程序包配置

一旦我们通过了身份验证,我们就可以使用 CLI 来生成包配置文件,供以后重用。

对于麦克·OS X 来说,指挥旗base64是一个大写字母-D:

dcos marathon app show data-science-engine | jq -r .labels.DCOS_PACKAGE_OPTIONS | base64 -D | jq > my-data-science-engine.json

对于 Linux,base64的标志是小写的-d:

dcos marathon app show data-science-engine | jq -r .labels.DCOS_PACKAGE_OPTIONS | base64 -d | jq > my-data-science-engine.json

请注意,导出的选项涵盖了每一个选项,这并不理想,因为选项可能会在平台的不同版本之间发生变化,如果您不更改值,最好依赖系统默认值。例如,我将该导出编辑为:

{
  "service": {
    "name": "data-science-engine",
    "cpus": 8,
    "mem": 51200,
    "gpu": {
      "enabled": true,
      "gpus": 1
      }
   }
}

您可以编辑该文件以满足您的需要,或者使用 GUI 来完成,并下载和编辑配置。

使用 CLI 安装数据科学引擎

现在,我们可以使用 CLI 安装数据科学引擎包:

dcos package install data-science-engine --options=./data-science-engine.json --yes 

完整的集群/服务自动化示例

总之,这使得整个过程使用导出的 JSON 包配置:

# Boot DC/OS Cluster
terraform init -upgrade
terraform plan -var-file desired_cluster_profile.tfvars -out plan.out
terraform apply plan.out# Get the cluster address from Terraform’s JSON output
export CLUSTER_ADDRESS = `terraform output -json | jq -r '.["masters-ips"].value[0]'`# Authenticate CLI to Cluster using its address and Install the Data Science Engine Package
dcos cluster setup [http://$CLUSTER_ADDRESS](/$CLUSTER_ADDRESS) # add whatever arguments you need for automated authentication
dcos package install data-science-engine --options=data-science-engine-options.json

结论

在这篇文章中,我们启动了一个 DC/操作系统集群,并以可重复的方式部署了数据科学引擎,然后执行了一个测试笔记本来创建一个堆栈溢出标记。这展示了如何使用 PaaS 来提高数据科学团队的生产力。请继续关注该系列的下一篇文章!

注意:教程中的每一步都经过严格测试,所以如果你遇到任何问题,请在评论中告诉我。

附录:常见错误

我在写这篇文章的时候遇到了一些错误,你可能会在这篇文章中的例子中遇到,所以我已经包括了这些错误以及如何修复它们!😃

ssh-agent问题

如果您忘记通过eval "$(ssh-agent -s)"ssh-add您的密钥运行 ssh-agent,您将看到下面的错误。如果您打开一个新的 shell 并从中运行 terraform 命令,这将非常容易。

Error: Error applying plan:1 error occurred:
  * module.dcos.module.dcos-install.module.dcos-install.null_resource.run_ansible_from_bootstrap_node_to_install_dcos: timeout — last error: ssh: handshake failed: ssh: unable to authenticate, attempted methods [none publickey], no supported methods remain

解决方案是来自 *paas_blog/dcos/terraform* 目录的`ssh-add ./my_key`。为了避免将来出现这种情况,您可以编辑*desired _ cluster _ profile . TF vars*中的密钥字段,以便在您的 *~ /中使用公钥。ssh/* 目录,当 shell 启动时,使用 *~/自动添加到 ssh-agent 中。简介*、 *~/。bash_profile* 或者 *~/。bashrc* 。

现在,验证是否已经添加了密钥:

ssh-add -l


这应该显示:

2048 SHA256:1234567891234567891234567891234567891234567 ./my_key (RSA)


# 超时问题

有时,当 DC/操作系统启动时,事情不会正确同步,您会得到一个关于 Ansible bootstrap 或负载平衡器超时的错误。要做的事情就是破坏,然后计划/应用再创造。第二次会成功的。

如果您看到以下任一错误,这就是正在发生的情况。

Error: Error applying plan:1 error occurred:

  • module.dcos.module.dcos-infrastructure.module.dcos-lb.module.dcos-lb-public-agents.module.public-agents.aws_lb.loadbalancer: 1 error occurred:
  • aws_lb.loadbalancer: timeout while waiting for state to become 'active' (last state: ‘provisioning’, timeout: 10m0s)

或者:

Error: Error applying plan:1 error occurred:

  • module.dcos.module.dcos-install.module.dcos-install.null_resource.run_ansible_from_bootstrap_node_to_install_dcos: timeout — last error: dial tcp 34.221.233.243:22: i/o timeout

# 数据综合症

我叫拉塞尔·朱尼。我是 [Data Syndrome](http://datasyndrome.com) 的首席数据科学家,在那里我构建端到端的机器学习和可视化产品、推荐系统、线索生成系统、数据工程,并专注于[弱监督学习](https://www.snorkel.org/blog/weak-supervision),或用更少的数据做更多的事情。我在 http://blog.datasyndrome.com[写博客](http://blog.datasyndrome.com)

我正在写一本将于明年出版的新书,书名是《T21:弱监督学习》。敬请关注更多内容!

# 用简单的文档编码填充 Word2Vec 嵌入

> 原文:<https://towardsdatascience.com/padding-sequences-with-simple-min-max-mean-document-encodings-aa27e1b1c781?source=collection_archive---------26----------------------->

## 弱监督学习的快照(O'Reilly,2020)

在本帖中,我们将讲述如何用三个性能惊人的值填充文本序列:最小值/最大值和平均值。这是文档编码的一种简单形式,它描述了整个文档的大致含义。它们往往比在所有文档中输入单个静态值表现得更好。

这是一系列帖子的第 1 部分,我将使用来自[堆栈交换数据转储](https://archive.org/details/stackexchange)的[堆栈溢出问题](https://data.stackexchange.com/stackoverflow/query/new)来演示弱监督学习的技术,作为我即将出版的书*弱监督学习(O'Reilly,2020)* 的一部分。这些技术*包括迁移学习、半监督学习、远程监督*和*弱监督*。在这些帖子中,我将展示技术配方,而这本书将通过解决现实世界的问题,对该领域进行有凝聚力的概述。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/58839f589f52f628aa29a3d0b1fda679.png)

Fun with vector means. Source: [Mathworks Documentation](https://www.mathworks.com/help/matlab/ref/mean.html)

# 跳过这一段(除非你感到困惑)

大多数人可以跳过,但如果你是深度学习和自然语言处理的新手,你需要理解文本嵌入和序列填充才能前进。简而言之,在这篇文章中,我们根据单词的含义对文档中的单词进行编码(这就是 Word2Vec 所做的),并使它们长度相同,这样我们就可以使用线性代数来处理它们。这篇文章是关于使用什么值来使短文档和长文档一样长。

看看 Adrian Colyer 的帖子[单词向量的惊人力量](https://blog.acolyer.org/2016/04/21/the-amazing-power-of-word-vectors/),然后回来从这里开始。

# 填充和插补

填充编码文档时不同插补方法的性能在论文[使用加权单词嵌入聚合的极短文本表示学习](https://arxiv.org/pdf/1607.00570.pdf)中有所描述,该论文[参考了](https://stats.stackexchange.com/a/239071/35715)该堆栈溢出答案。关于插补的更多信息,请查看[这篇由](/6-different-ways-to-compensate-for-missing-values-data-imputation-with-examples-6022d9ca0779) [Will Badr](https://medium.com/u/551ba3f6b67d?source=post_page-----aa27e1b1c781--------------------------------) 撰写的帖子。

用户 [D.W.](https://stats.stackexchange.com/users/2921/d-w) 写道:

> 一种对短文本(例如,一个句子或一条推文)相当有效的简单技术是计算文档中每个单词的向量,然后使用坐标方式的平均值、最小值或最大值来聚合它们。

该论文使用平均值、最大值和最小/最大值作为基线,并与作者的算法相比,测量语义相似性任务的性能。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/f7a59617f60fffd3a08b0f181737e9cc.png)

Source: Representation learning for very short texts using weighted word embedding aggregation, De Boom, Van Canneyt et al, 2016

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/ac981c86f9d385449af1703dd1d2d3e3.png)

Source: Representation learning for very short texts using weighted word embedding aggregation, De Boom, Van Canneyt et al, 2016

虽然当时不是最先进的,但 min/max/mean 很容易计算,可以作为一个很好的基线,这就是为什么它们被用于本书的原因(尽管我最终选择了一个简单的 Conv1D 模型作为基线,它使用了自己的嵌入)。

注意,用交替的最小值/最大值填充是`[keras.preprocessing.sequence.pad_sequences](https://keras.io/preprocessing/sequence/#pad_sequences)`做不到的,因为它只接受单个浮点/字符串作为填充值的参数。Keras 有很多像这样的限制,因为它的目标是简单和可访问性,而不是艺术表现的状态。我发现,随着我对深度学习和自然语言处理的深入,keras 的局限性驱使我在提炼模型时使用 keras internals、raw Tensorflow 和 [PyTorch](https://pytorch.org/) 。

# 用 Word2Vec 对文档进行密集编码

我们使用 Gensim 的[型号。Word2Vec](https://radimrehurek.com/gensim/models/word2vec.html) 对我们的标记化文本进行编码。这里没什么新鲜的。首先,我们检查模型是否被加载,如果没有,我们重新创建并保存它。然后,作为健全性检查,我们通过预测一个示例单词的语义相似性来测试嵌入模型。我们将模型一个接一个地应用于文档,一个接一个地,创建一个新的列表`numpy.arrays`,每个文档一个。注:如果你是 Word2Vec 的新手,可以看看 [Suvro Banerjee](https://medium.com/u/ac3247b15c91?source=post_page-----aa27e1b1c781--------------------------------) 的[这篇文章](https://medium.com/explore-artificial-intelligence/word2vec-a-baby-step-in-deep-learning-but-a-giant-leap-towards-natural-language-processing-40fe4e8602ba)。

Encoding tokenized documents into Word2Vec a dense vector representation

我们现在将计算位置方向的最小值、最大值和平均值,连接前两个值,并使用 min/max 或 mean 来填充少于`MAX_LENGTH`个单词的任何文档。我们将同时截断任何超过`MAX_LENGTH`个单词的文档。如果该行有奇数个值,并且最小/最大填充超出了文档的`MAX_LENGTH`,我们将去掉多余的值使其为偶数。

Manually padding with custom values: min/max or mean

Tada!这是一个制作简单东西的不错的方法:)我用它和 scikit-learn 的 [RandomForestClassifier](https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.RandomForestClassifier.html) 一起创建了一个基线模型,但是我发现我需要一些非线性的东西作为基线。

# 弱监督学习的下一个快照

在下一篇文章中,我们将看看我如何使用 CuPy 和 CUDA 来加速将这些编码/填充的数据从 3D 向量重新整形为长 2D 向量,以供随机森林模型使用。

# 关于作者

[Russell Jurney](http://linkedin.com/in/russelljurney) 是 [Data Syndrome](http://datasyndrome.com) 的机器学习和可视化顾问,他专门研究弱监督学习(用更少的数据做更多的事)、端到端机器学习产品开发、数据标记、[敏捷数据科学辅导](http://datasyndrome.com/training)和预测性线索生成。

# 巴基斯坦举办了首次 30 小时数据科学黑客马拉松

> 原文:<https://towardsdatascience.com/pakistan-hosts-its-very-first-30-hour-data-science-hackathon-5f60628bfc54?source=collection_archive---------11----------------------->

4 月 20 日,卡拉奇的工商管理学院( [**IBA**](https://www.iba.edu.pk/) )向来自巴基斯坦各地的 100 多名学生敞开大门,让他们参加由总部位于纽约的人工智能初创公司 [Inqline](http://ai.inqline.com) 赞助和协办的 30 小时数据科学黑客马拉松。组织这一盛大的技术活动的目的是让全国各地最优秀、最聪明的黑客通过数据科学、机器学习来解决社会问题,并通过利用人工智能和机器学习等新技术来实现该国的数字社会创新。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/31fecad697ed406a4a35c309a93b63bb.png)

Team Flash from Habib University & DHA Suffa University

# 眼前的问题

在巴基斯坦这样的国家,并不缺少未解决的问题。这就是在捐献的血液中发现输血传播疾病的痕迹,而不必花费数百美元进行筛选测试的困境。输血的过程并不像看起来那么简单。从献血者身上抽取的血液在被认为“有用”和健康之前,必须经过多次筛选测试。这不仅是一个耗时的过程,也是一个非常昂贵的过程。为了帮助解决这个问题,Inqline 和 IBA 与 Husaini 血库(HBB)合作,帮助提出一个最佳解决方案,通过使用 HBB 提供的献血者医疗数据来判断捐献的血液是好的还是坏的。

# 巴基斯坦青年的强烈反应

关于 Inqline 与 IBA 合作在卡拉奇举办首届 30 小时数据科学黑客马拉松的消息在社交媒体上受到了巴基斯坦年轻人的欢迎。来自巴基斯坦 12 所不同大学的 100 多名学生组成的超过 28 个团队注册参加了此次活动。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/efb95cf4dd6e23a5ef5fc78cfa47e507.png)

12 notable universities including NED, FAST, Karachi University, IBA, Habib University, Mehran University Jamshoro, Muhammad Ali Jinnah University, SZABIST and Bahria University all participated in the hackathon

# Inqline IBA 数据科学黑客马拉松

在巴基斯坦,这是第一次,学生们被提供了一个真实世界的问题,他们必须在 30 小时内使用从 HBB 获得的真实数据集来解决这个问题。可以说,像这样的黑客马拉松通常会加速通常需要几个月的工作才能实现或复制的结果。学生们被要求分析一个基于献血者医疗数据的数据集。在黑客马拉松结束时,他们提供了一个解决方案,可以预测血液样本中任何输血传播疾病的流行率。

此次活动首先由国际律师协会计算机科学学院副院长 Sayeed Ghani 博士做主旨发言,随后是 Inqline 首席执行官兼创始人 Atif Muhammad。数据科学黑客马拉松包括两轮;第一轮持续了 7 个多小时,学生们被分配了一个描述性的现实世界问题,以及一个必须用数据科学和机器学习算法进行清理和分类的数据集。在整个活动中,我们维护了一个排行榜,所有团队都根据其提交的内容进行了排名。结构、评分和设计流程保持竞争性,以确保学生尽最大努力。

第二轮围绕着一个长达 23 小时的棘手挑战,所有参与者都被要求留在校园里过夜——黑客和构建代码。所有进入第二轮的团队整晚都在分析、评估和编码。在第二轮比赛结束后,参赛队还需要在两分钟的演讲中向评委团介绍他们在血库中实施 ML 模型的商业案例。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/d9ef5f6a8cd2a7dfafc9e53482f1e904.png)

Dr. Sayeed Ghani, Associate Dean, Faculty of Computer Science, IBA in the opening ceremony

# 获胜的队伍

尊敬的评委团由资深大学教授和业内著名的数据科学专家组成,包括 Mandi Xpress 的首席执行官兼创始人 Jehanzaib Chaudhry 和 Bitwits 的首席技术官 Ali Raza Bhayani,他们在经过全面评估后,宣布来自 N **ED 工程大学&技术**的**数据小组**为获胜团队,来自 **Habib 大学**的 **FAST** 为亚军。获胜团队获得了 100,000 卢比的现金奖励,以及一名团队成员在 Inqline 纽约总部的带薪实习机会;第二名团队获得了 60,000 卢比的现金奖励

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/0cd8e31043c719ec46dbcc0a682f4458.png)

The winning team — Data Squad from NED University

# 愿景

Inqline 很荣幸在巴基斯坦率先举办了第一届以学生数据科学为主题的通宵黑客马拉松。这次黑客马拉松的目的是在巴基斯坦建立一个数据科学人才库,共同关注一个社会问题,并提出一个基于技术的最佳解决方案,将数据科学算法的魔力与医学科学的世界联系起来。

Inqline 相信巴基斯坦的每一个工程师都充满了想法和激情。在世界的这一部分,有许多人才有待发掘,我们坚信,像这样的活动可以让学生对新的和即将到来的技术产生更多的兴趣。我们对巴基斯坦的愿景很明确:我们将巴基斯坦视为数据科学的下一个领导者。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/6f24ba8341f422a48658f888086ad3a4.png)

With Team Data Developers from University of Karachi

# 2019 煎饼日——推特和自然语言处理分析

> 原文:<https://towardsdatascience.com/pancake-day-2019-tweets-and-nlp-analysis-5de38f3fdd90?source=collection_archive---------15----------------------->

## 你喜欢煎饼吗?推特分析& 70k 条推特的自然语言处理!

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/a78e8f9c5ada5a2aff5e52905fdad132.png)

# 介绍

2019 年 3 月 5 日星期二是煎饼日!煎饼日,在英联邦国家和爱尔兰也被称为忏悔星期二,是灰烬星期三的前一天。许多基督徒遵守的特定习俗是吃煎饼来庆祝这一天,这样就吃完了在四旬斋期间(复活节前 40 天)要避免的所有黄油、鸡蛋和脂肪。

我知道英国人总是有迷人的方式来庆祝特殊场合,但我仍然惊讶地看到煎饼日的到来。不仅是烘焙业的业余爱好者和厨师专家都在深入思考他们的下一个创作,包括奇妙和复杂的浇头,而且所有年龄的勇敢的男人、女人和孩子也在训练自己在街上跑来跑去,把煎饼抛向空中,热切地争夺煎锅。

事实上,煎饼日是一个快乐的日子,因此,这是每个人在社交媒体上活跃起来的绝佳时机!有什么比良好的情绪和积极的感觉更能吸引人们的注意力吗?

为了了解庆祝活动的程度,我决定收集从 3 月 1 日(前一天的五天)到 3 月 6 日(灰星期三)带有#PancakeDay 标签的推特。本文报告了我的分析结果。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/77a5d11f829d71d57f55370825d62aba.png)

# 数据和方法

这篇博文的数据是通过[推特应用编程接口](https://developer.twitter.com/en/docs/basics/getting-started)收集的。#PancakeDay 发生在 3 月 5 日,我提前 4 天(3 月 1 日)开始收集推特,并在 Ash 星期三(3 月 6 日)结束时停止。使用标签#PancakeDay,总共记录了 70,969 条推特。其中,66.2% (46,967)为转发推特。

一旦推特被收集,我就在 python 笔记本中对推特进行预处理和清理(删除所有重复的推特),并执行一些统计探索性分析。然后我尝试了自然语言处理(NLP)来获取更多关于推特内容的细节。(这是我第一次涉足这些模特!)这些方法在试图了解人们将哪些单词与煎饼日联系起来时特别有吸引力。

我使用来自 [gensim 库](https://radimrehurek.com/gensim/models/word2vec.html)的 Word2Vec 模型进行了 NLP 分析。这个机器学习模型用于产生单词嵌入。这将词汇表(大量单词列表)中的单词映射到实数向量,从而允许计算两个单词之间的相似度,并最终找出在同一上下文中频繁使用的单词。如果你想要一个精彩而快速的解释,看看[卡维塔·加内桑](https://medium.com/u/cd869a6dee38?source=post_page-----5de38f3fdd90--------------------------------)的[文章](https://medium.freecodecamp.org/how-to-get-started-with-word2vec-and-then-how-to-make-it-work-d0a2fca9dad3)。你也可以通过阅读[托马斯·米科洛夫(Tomas Mikolov)的谷歌团队](https://arxiv.org/pdf/1301.3781.pdf)关于 Word2Vec 实现的原创研究论文来获得更深入的观点。

正如 [Vijay athithya](https://medium.com/u/ae424245b4b?source=post_page-----5de38f3fdd90--------------------------------) 提出的和 [Vishal Kumar](https://medium.com/u/2390882c92aa?source=post_page-----5de38f3fdd90--------------------------------) 在他的[伦敦灯光节分析](/analyzing-the-lumiere-london-2018-light-festival-part-2-98eb3769e267)中很好地陈述的,我继续使用 [Scikit-learn 库](https://scikit-learn.org/stable/modules/generated/sklearn.decomposition.PCA.html)对“PancakeDay”和“pancakes”进行主成分分析(PCA)。这个步骤降低了单词向量矩阵的维度,从而允许我们在二维图中可视化最近的单词。

# 推文分析

以下图表说明了为更好地理解围绕#PancakeDay 的讨论而进行的分析。

在这里,我将介绍以下结果:

*   每天的推文数量
*   前 10 名推特用户(按关注人数)
*   转发量最高的 10 条推文
*   推文中排名前 10 的单词和标签
*   基于语言相似性的“煎饼”的最接近单词

**每天的推文数量**

下图显示了从忏悔星期二之前的星期五到煎饼日之后的圣灰星期三,每天的推文数量和转发量。毫不奇怪,最活跃的一天是 3 月 5 日星期二,有近 5 万条推文,正确的是 49648 条。你和我一样惊讶吗?

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/9de22fdf27da69b090dbd74316f8368f.png)

The bar chart shows the number of tweets and retweets by day, Tuesday 5th of March being the official Pancake Day!

**十大推特账号:名人**

看看标签为#PancakeDay 的十个最受欢迎的账户推文,就可以了解这一事件的程度。下图显示了粉丝数量最多的十个 Twitter 账户。

令人惊讶的是,关于#PancakeDay 的前两个账户分别由曼联(@ManUtd)和切尔西(@ChelseaFC)占据。来自两个队的球员显然玩得很开心,在煎饼旋转挑战中互相竞争。如果你想看看安东尼·马夏尔、李·格兰特和维克多·林德洛夫的表现,那就看看这个小视频吧!

其他名人包括媒体(BBC 新闻,BBCSport,AppStore 或 Crowdfire),著名厨师(戈登·拉姆齐和杰米·奥利弗),甚至传奇音乐家保罗·麦卡特尼。煎饼日庆典是这些演员推销产品的绝佳机会。BBC Sport 利用这次活动宣传其跑步应用程序,App Store 支持三个烹饪应用程序,戈登·拉姆齐展示了他独特的餐厅@breadskitchen。

各种各样的名人积极参与煎饼日,显示了对这一事件的不可思议的魅力,并证明讨论跨越人口的大群体。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/be591bee717665da14fad61ca3915014.png)

The bar chart shows the most famous accounts by the number of followers

看看下表,发现这些演员的推文是什么!

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/2cb73039bf4273652d2a94810c139fff.png)

The table shows the top ten most famous tweeters

**十大转发推文**

推文总数中的转发数量特别高,因为 66.2%的推文实际上不是新推文,而是被转发的推文。尤其是观察它们,可以让你对推特用户的兴趣,或者换句话说,对人们的行为有一个有趣的了解!下表列出了被转发次数最多的 10 条推文,以及它们来自哪些 Twitter 账户。

对于公司来说,为了吸引更广泛的受众和建立更牢固的关系,社交媒体是一个很好的地方,这已经不是什么秘密了。因此,不足为奇的是,一半的转发量吸引了 Twitter 用户转发公司的推文,从而参与竞争赢得免费的东西!在亚马逊代金券、Nutella jar、厚脸皮的围裙、案板或者煎饼机之间,每个人都应该找到它的兴趣所在!

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/58d36349b3bb8d03c5a4a6fee508bcfc.png)

The table shows the ten most retweeted tweets (percentage retweet for all retweeted tweets)

自然,Twitter 也是一个分享意想不到的、有趣的生活惊喜的地方。如果你错过了圣潘克拉斯车站的更名,那么感谢亚历克斯·埃奇及时捕捉到了英式幽默!

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/61f50cff4992659fa6443234ba500710.png)

@alexanderedge_ Do you fancy travelling to St. Pancake?

**十大热门词汇和标签**

下面的图表显示了推文中最受欢迎的标签和单词的出现频率(没有重复的推文)。

最著名的词毫无意外:“煎饼”、“日”、“星期二”。有趣的是,当推特上谈论#PancakeDay 时,像“快乐”、“制造”、“我们”和“喜欢”这样的词被推特用户大量使用。据推测,这可以反映出与这一天相关的喜悦和分享感!

不出所料,“煎饼日”是最受欢迎的标签,出现在每条推文中。“忏悔星期二”、“烤饼星期二”、“脂肪星期四”和“狂欢节”也是受欢迎的标签,分别出现在 22.1%、9.4%、1.7%和 1.4%的案例中。这表明推文也提到了一年中这个特定星期二的庆祝活动和传统。

在这些排名的底部,出现了一些更具体地与食物相关的词和标签。在这里,我们可以猜测“柠檬”、“糖”和“坚果”是与煎饼制作和食用相关的最受欢迎的配料。此外,“纯素食主义者”和“无谷蛋白”是更能体现食品行业趋势的词汇。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/c83dad9e886db9b7ac900223e196feaa.png)

The bar graphs show the 10 most popular hashtags and words

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/029333c935277273324b45f39c4eaa46.png)

The tables show the 20 most popular hashtags and words and their percentage of appearance in all tweets

**相似词——最近邻**

如前所述,为了找出 tweetsers 与“PancakeDay”相关联的单词,我对 23,019 条非重复的 tweet 使用了 Word2Vec Gensim 模型。这个模型假设空间上相互靠近的词,相互关联,从而表现出相似性。换句话说,任何特定单词的意思都受到它周围的单词(它的邻居)的影响。最近的邻居更有可能与该单词相关联。让我给你举个例子:

*“在忏悔星期二,饥饿的孩子们在一场难忘的比赛中相互竞争后,吃到了美味的蓝莓煎饼!”*

在上面的句子中,“蓝莓”和“薄煎饼”是直接相邻的,而“儿童”和“薄煎饼”相距 5 个单词。因此,在这个句子中,“煎饼”和“蓝莓”比“孩子”和“煎饼”更相似。

**煎饼最近的话(最近的邻居)**

下面的两个散点图显示了与“煎饼”最接近的词。第一张图只考虑了推文中的单词,而第二张图包括了标签!可能会注意到诸如“甜点”、“自制”或“款待”等词出现在两个输出中。

这些词大多与其他食物成分或描述食物质地或味道的形容词有关。例如,“榛子”、“浆果”、“苹果”以及“菠菜”、“火腿”、“蘑菇”等配料经常与“煎饼”联系在一起。此外,“美味的”和“美味的”形容词被用来大概描述人们吃煎饼时的期望或情绪!

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/ece1a73d48246d59952b2f7868f06986.png)

The graph shows the PCA results of the Word2Vec model for the closest words to ‘pancakes’

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/afbf04228dae73bb8138bc382516ab41.png)

The graph shows the PCA results of the Word2Vec model for the closest words to ‘pancakes’

**#PancakeDay 最近的单词(最近的邻居)**

最后是与#PancakeDay!相关的单词或标签的结果。下图总结了#PancakeDay 的主要活动,即庆祝日(带有“shrovetuesday2019”等标签)、饮食和烹饪日(带有“餐厅”或“煎饼食谱”等词)以及分享日(“提供”)!然而,这种分析的输出并没有给出许多描述人们感受的词语和形容词。这里需要更深入的分析。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/34489daf438e0e0123244c2b4b0761f0.png)

The graph shows the PCA results of the Word2Vec model for the closest words to ‘#PancakeDay’

对推文的其他有趣探索将是分析每条推文的情绪或尝试其他 Word2Vec 模型(Tensorflow,GloVe)。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/7e4107bb4486c3c18d52253c0d3be7c8.png)

Rembrandt 1635, Crowd eagerly awaiting pancakes. [The British Museum](https://medium.com/u/b53b6b669793?source=post_page-----5de38f3fdd90--------------------------------)

**结论**

该结束了!:-)这篇文章探索了 2019 年 PancakeDay 的大约 70,969 条推文。我很想知道,你对“煎饼”有什么看法,以及你今年是否参加过任何煎饼比赛!我非常渴望明年能加入你们!

我希望你喜欢这篇文章,如果你想留下任何意见,建议或想法,我真的很感激!所以,请随时伸出手来!

还有,如果你想自己试试,我的代码可以在下面的 [Github](https://github.com/audevuilli/pancake-day) repo 中找到。

**收盘前……**

我要感谢 Medium 的成员分享他们的工作,并提供有趣的教程,让我能够接触到有用的工具和方法!

感谢您的宝贵时间!

奥德

*我是* [*数据和植物科学家*](http://www.audevuilli.com) *在* [*垂直未来*](https://www.verticalfuture.co.uk/) *,以前在*[*WBC SD*](https://www.wbcsd.org/)*。理学硕士。来自 UCL 的城市分析和智能城市来自伦敦的 Bartlett*[*CASA*](https://www.ucl.ac.uk/bartlett/casa/)*和 BSc。在食品科学方面来自* [*苏黎世联邦理工学院*](https://ethz.ch/en.html) *。对城市、美食、健康充满热情通过*[*Twitter*](https://twitter.com/audevuilli)*或*[*LinkedIn*](https://www.linkedin.com/in/aude-vuilliomenet-69248711a/)*联系。*

# pandarallel——一个简单有效的工具,可以在所有 CPU 上并行处理 pandas 计算

> 原文:<https://towardsdatascience.com/pandaral-lel-a-simple-and-efficient-tool-to-parallelize-your-pandas-operations-on-all-your-cpus-bb5ff2a409ae?source=collection_archive---------5----------------------->

## 如何仅用一行代码显著加快熊猫的计算速度?

完整的 **Pandaral lel** 存储库和文档可在此 [GitHub 页面](https://github.com/nalepae/pandarallel)上获得。

本文中介绍的库只在 Linux & MacOS 上受支持。

# 什么问题困扰着我们?

用[熊猫](https://github.com/pandas-dev/pandas),当你运行下面一行:

您会得到以下 CPU 使用率:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/0b072e509d4861921a720a15729d2fed.png)

Standard Pandas apply — Only 1 CPU is used.

即使你的计算机有几个 CPU,也只有一个完全专用于你的计算。

我们希望**用一种简单的方法**得到类似这样的结果,而不是 CPU 的使用量:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/1f5bf1984bb8058d82eff09f28bf481d.png)

Parallel Pandas apply — All CPUs are used.

# Pandaral lel 如何帮助解决这个问题?

Pandaral lel 的想法是将你的熊猫计算分布到你计算机上所有可用的 CPU 上,以获得显著的速度提升。

## 安装:

在 Windows 上, **Pandaral lel** 只有在 Python 会话(`python`、`ipython`、`jupyter notebook`、`jupyter lab`)时才起作用,...)从[Linux 的 Windows 子系统(WSL)](https://docs.microsoft.com/en-us/windows/wsl/install-win10) 执行。

在 Linux & macOS 上,不需要做什么特别的事情。

## 导入和初始化:

## 用法:

有一个简单的用例,有一个熊猫数据帧`df`和一个应用函数`func`,只需用`parallel_apply`替换经典的`apply`。

你完了!

*注意,如果不想并行化计算,仍然可以使用经典的* `*apply*` *方法。*

您也可以通过在`initialize`函数中传递`progress_bar=True`来显示每个工作 CPU 的进度条。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/892fd3fd8c54b38fdb69e97bae06dd67.png)

Parallel apply with a progress bar

还有一个更复杂的用例,有一个 pandas 数据帧`df`,这个数据帧的两列`column1`和`column2`,以及一个要应用的函数`func`:

# 基准

对于四个可用的示例[此处](https://github.com/nalepae/pandarallel/blob/master/docs/examples.ipynb),在以下配置上:

*   操作系统:Linux Ubuntu 16.04
*   硬件:英特尔酷睿 i7 处理器,3.40 GHz,4 核

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/486f2046e7d5a8f69de39863de0486c6.png)

Standard vs. Parallel on 4 cores (lower is better)

除了`df.groupby.col_name.rolling.apply`的速度只提升了 3.2 倍,平均速度提升了大概 4 倍,也就是所用电脑上的核心数量。

# **它是如何在引擎盖下工作的?**

当`parallel_apply`被调用时, **Pandaral lel:**

*   实例化一个 [Pyarrow 等离子共享内存](https://arrow.apache.org/docs/python/plasma.html),然后
*   为每个 CPU 创建一个子进程,并要求每个 CPU 处理数据帧的一个子部分,然后
*   组合父流程中的所有结果

与其他进程间通信介质相比,使用共享内存的主要优点是没有串行化/解串行化,这可能会非常耗费 CPU。

如果您发现此工具有用,但如果缺少某个功能,请在此处写下新的功能请求[。](https://github.com/nalepae/pandarallel/issues)

# 熊猫和 SQL 一起,一个英超联赛和球员球探的例子

> 原文:<https://towardsdatascience.com/pandas-and-sql-together-a-premier-league-and-player-scouting-example-b41713a5dd3e?source=collection_archive---------15----------------------->

## 熊猫,SQL,Excel 数据传输

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/aa5cf39dc40521113e7aee6f22284b96.png)

Image Courtesy of Md Madhi via [Unsplash](https://unsplash.com/photos/lQpFRPrepQ8)

Python Pandas 库使得将表格数据从一个平台转移到另一个平台变得简单。本教程旨在向您展示如何通过使用 Pandas 在 Pandas 数据框架、SQL 数据库和 Excel 电子表格之间移动数据。因此,无论您的数据最初驻留在哪里,您都可以将它转换成一种您觉得可以轻松分析和操作的格式。

# **将 SQL 表转换/读取为 Pandas 数据帧**

经常需要将数据从一个平台转移到另一个平台。将 SQL 表/查询转换成 Pandas 数据框架可能是有用的。首先,必须安装 3 个模块。这些包括:熊猫、sqlalchemy 和 PyMySQL。

这里,英超联赛表在 MySQL 的“足球”表中。目标是将这个表转换成熊猫数据框架。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/63d3940486dc10cb33df7e795bd8404f.png)

首先,按照惯例导入 Pandas 模块作为别名 pd,然后导入 sqlalchemy 模块。接下来,有必要在 Python 和 MySQL 数据库之间建立一个连接。幸运的是,sqlalchemy 模块提供了一个名为**的函数。create_engine()** 使这个连接能够被建立。

**里面的弦。create_engine()** 函数被称为连接字符串。

**create_engine()** 函数基于 URL 生成一个引擎对象。这些 URL 通常带有用户名、密码、主机名和数据库名。数据库 URL 的典型格式是:

为了清楚起见,“mysql+pymysql”表示我正在使用 mysql 作为我的数据库管理系统,并且在模块 pymysql 内的函数与这个数据库管理系统(DBMS)接口。

用户名= root,密码=****,主机名= localhost,数据库名= football_db。

为了匹配使用您的特定 DBMS 的引擎配置,您应该咨询[https://docs.sqlalchemy.org/en/13/core/engines.html](https://docs.sqlalchemy.org/en/13/core/engines.html)关于连接字符串格式的细节。现在,当我运行 Jupyter 笔记本中的代码时,数据框出现了。为了确认,我可以简单地使用**类型**函数,这表明我有一个熊猫数据帧。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/faea5346d53b33b3597124f0dc2b613c.png)

这里一个有用的问题是:为什么我们要将 SQL 足球表转换成熊猫数据框架?

举例来说,这是许多可能的原因之一,现在可以对数据帧进行样式化,从而增强其对目标受众的可读性。这里定义了两个有用的函数;其中一个使用条件格式为目标差异列着色,如果目标差异为正,则为绿色,如果目标差异为负,则为红色。我们甚至可以更进一步,定义一个当用户滚动单元格时放大单元格的函数。这在 MySQL 中是不可能的。

# **将 SQL 查询读入熊猫数据帧**

为了将一个查询从 SQL 读入 Pandas 数据帧,我们首先用它的母语编写查询,这里是 SQL。我将这个查询的变量名指定为 query_1,因为它跨越了多行,所以我将这个查询放在了三重引号中。然后,可以通过将其变量名和引擎作为参数添加到 **pd.read_sql_query()** 方法来读取该查询。如下所示,查询现在是一个熊猫数据框架。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/690825079ed51cf7e903b48325a494f3.png)

# **将足球数据帧导出到 Excel 文件**

使用 **pd.to_excel()** 方法可以导出新创建的数据帧。指定你选择的文件名,这里我选择了“goals_game_stats.xlsx”,因为这似乎是合适的。包括文件扩展名。xls(如果您安装了 xlwt 模块)或。xlsx 扩展名,如果您安装了 openpyxl 模块。

似乎没有必要包含用 Pandas DataFrame 指定的索引,所以我简单地将可选参数 index 设置为 False,然后从相应的 Excel 文件中省略该索引。熊猫解析器真的让数据传输变得更容易了!

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/40404ab6a1f73d4696ac7925441f9165.png)

# **使用熊猫从 Excel 到 MySQL】**

*…还为巴塞罗那足球俱乐部做了一些球探工作*

总而言之,我想我会通过演示如何使用 Pandas 将 Excel 文件导出到 MySQL 进行查询来结束本教程。由于所有的例子都是基于英超联赛,我认为使用一个新的数据集会很好。为此,让我们调查一下世界上最好的足球运动员。下面是对球员和 Excel 电子表格中的一些栏目的简要介绍。

[下面的数据集来自 Kaggle](https://www.kaggle.com/karangadiya/fifa19) 。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/3152b3a90392911c1f78d96fadc68cef.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/bd60535b24ff92d99fc7a477a10a6e1f.png)

我将这个数据集保存为逗号分隔值(CSV)文件,并使用 **pd.read_csv()** 方法,将编码设置为‘Latin-1’来解析 Excel 文件。为了确认解析有效,我在 players_data 数据帧上使用了 head 方法。下面显示的数据框跳过了中间的列。如果我们想检查所有 55 列是否都存在,一个很好的方法是使用 **pd.set_options()** ,其中我将“display.max_columns”设置为 60 以包含我的所有列。视频现在显示所有的列都包含在内,并且已经被正确解析。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/14e2cb38e4b3aa5f769f5ad363b1f69c.png)

我现在可以通过我的 Python 脚本连接到我的‘football _ db’了。然后,我编写一个查询来创建一个表。表名 player_name 似乎很合适。接下来,在使用游标执行该查询之前,我指定了列及其对应的数据类型。

现在是魔法!

我使用了 **DataFrame.to_sql ()** 方法,在我的例子中是 **players_data.to_sql()** 方法,并将这个数据帧写入新创建的表“player_data”,连接前面提到的引擎,省略索引,并将“if_exists”参数设置为“append”以将数据添加到表中。

最初来自 Excel 的表现在已经导入到 MySQL 数据库中。现在已经为查询设置好了。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/8699e7881c2930f4b06782ac8155bb7e.png)

# 最好的球员,最好的后卫和昂贵的巴塞罗那目标…

让我们根据他们的“总体”和“潜在”指标来看看谁是世界上最好的 5 名球员。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/fb8ed584168a688333cabfe366aca358.png)

或者也许我们想知道谁是最令人印象深刻的防守者。理想状态下,理想的防守者应该有良好的头球准确性,反应和盯人属性!

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/321b2b9236672629e33c70fe7e685f39.png)

随着巴塞罗那在冠军联赛中被利物浦击败,夏季引援将是加泰罗尼亚俱乐部的一个关键目标。由于我给了自己在巴塞罗那的临时首席球探身份,招募一名具有巴塞罗那核心特质的球员将是理想的。因此,我需要查询一个球员,有很高的工作率,有攻击意识,完成和加速超过 80。为了运行这个查询,我省略了梅西,因为他已经在巴塞罗那,并排除了罗纳尔多,因为他注定要留在尤文图斯足球俱乐部

巴塞罗那,如果你需要首席球探,请联系我!

查询结果显示有 5 名玩家。

根据我们的数据,随着巴萨今年夏天重燃对安托万·格里兹曼的兴趣,以提升他们明年冠军联赛的雄心,他可能会以 7800 万欧元的价格被证明是一笔昂贵的转会。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/fc6482fa6a170242d3388fe7f9400ae8.png)

# **总结**

本教程重点介绍了表格数据如何在 SQL 数据库、Pandas 数据框架和 Excel 之间移动。Python Pandas 库使移动数据变得简单,特别是当我需要将数据从 DataFrame/SQL 数据库导入 Excel 时,我喜欢使用 Pandas。希望本教程演示了如何实现数据传输。

如果你喜欢这里展示的例子,或者我是否应该在接下来的教程中切换到更多基于金融/医疗保健的例子,请告诉我。

# 熊猫足球分析

> 原文:<https://towardsdatascience.com/pandas-for-football-analysis-42c23b252995?source=collection_archive---------9----------------------->

## 一个利用足球联赛数据合并和抓取数据帧的例子

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/f436a69e75fc2ae484ff6fc22fb44953.png)

Image Courtesy of [Donnycocacola](https://unsplash.com/@donnycocacola)

# 介绍

本教程将集中在如何合并从不同的网上来源搜集的数据帧。首先,我将把可从[维基百科](https://en.wikipedia.org/wiki/2018%E2%80%9319_Premier_League)获得的英超联赛表格,与一支球队在一个赛季中领先、追平或落后的平均时间相关的统计数据合并起来。这些信息将从一个独立的来源搜集而来,即[足球统计](https://www.soccerstats.com/table.asp?league=england&tid=t)。

2018-19 英超赛季刚刚结束。虽然冠军争夺和降级之战占据了大部分头条,但知道一支球队在整个赛季的英超比赛中平均需要领先多少分钟才能确保欧洲足球,这将是一件有趣的事情。

当每个英超联赛结束时,奖金会根据球队在联赛中的排名在球队之间分配。通过收集数据,并将其列表成数据框,你可以清楚地看到托特纳姆热刺队在赛季最后一天与埃弗顿队打平的影响,这使他们失去了第三名的成绩。

# **刮痧**

我按照惯例导入 Pandas 模块作为它的别名 pd。Pandas 有一个内置函数, **read_html** ,它使用 lxml 和 BeautifulSoup 之类的库来自动解析 html 文件中的表格,作为 DataFrame 对象。默认情况下, **pandas.read_html** 函数搜索并尝试解析包含在 **< table >** 标签中的所有表格数据。结果是 DataFrame 对象的列表。

我使用 pandas 函数 **pd.read_html()** 从维基百科中删除英超联赛表,从 soccerstats 中删除 leading_level_trailing 表。快速回顾如何做到这一点和基本的清理(这很简单),请参阅我的文章;[英超熊猫](/pandas-in-the-premier-league-78f1d0c21b4f)。

这导致了下面描述的两个数据帧。为了节省空间,我只使用。head()方法。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/ea8ac6c60c969ae0045e6ac12d9f1a93.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/fbb9ad2b614bbd44c70efece36da062c.png)

# **合并两个数据帧**

“Premier_league”表和“leading_level_trailing”表现在可以合并了。在这种情况下,为了合并,我创建了一个在两个数据帧之间共享的新列。我本来可以选择使用现有的团队名称列,但是许多条目的名称和填充实际上略有不同。

例如,“曼城(C)”是 premier_league 表中的列值,但“曼城”列在 leading_level_trailing 表中。由于有许多不同名称的实例,我选择为每个团队插入一个新列,用简单的三个字母缩写。这省去了重命名每个团队的时间,因此相应的行将在两个数据帧之间匹配,但是有许多方法可以做到这一点。

名词(noun 的缩写)b:当我用球队简写创建新列时,条目必须与他们的球队结合,例如“leading_level_trailing”表中的第一个球队是阿森纳,因此我的球队简写列表中的第一个元素是“ARS ”,等等。

我在 Premier_league 表中创建了相同的 Team _ 缩写。我现在可以合并两个数据帧。

我为合并的表决定一个新的变量名,并使用 **pd.merge** 函数进行合并。我在括号中列出了这两个表,使用 **on=** 参数选择匹配哪一列,使用 **how=** 参数保留左侧 Premier_league 表中的所有行。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/1c436e86257581d7fe86c4aed003ea0a.png)

在更彻底地组织数据帧之后,例如删除重复的列名(例如 Team_y),我检查合并表‘leading _ level _ trailing _ stats’中列的数据类型,并将‘object’类型的列(python 字符串)转换为我们可以应用数字过滤条件的数字数据类型。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/009d34ea1b7d6d60f14cd77fc3c012ae.png)

为了回答最初的问题,我们对表应用过滤标准。这告诉我们,一支球队需要平均领先 31.7 分钟才能确保欧洲足球!

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/5d6b67ed20869df4d0b40429b1404dd9.png)

# **将新构建的数据帧与刮除的非表格数据合并**

在这个新成立的“合并英超联赛表”中增加一个奖金栏将会使它更具知识性。我们可以开始绘制英超比赛中平均领先时间和奖金之间的关系。

然而,在这种情况下,当我访问一个网站时,例如 RadioTimes,我需要的数据不是我可以使用 pd.read_html 抓取的表格格式。

这意味着我有两个目标。首先,收集数据,其次,我需要把它转换成一个数据帧,我可以合并到新成立的'合并 _ 英超 _ 联赛 _ 表'。

我首先从《广播时报》找到我需要的数据。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/61f0daac152b8a10a6fba133c978c30e.png)

[Sourced from RadioTimes](https://www.radiotimes.com/news/sport/2019-05-12/premier-league-prize-money-2018-2019/)

当我右键单击并选择 inspect 时,我可以看到底层的 HTML 源代码。我需要的信息嵌套在代表列表项的标签中。这些 li 标签位于一个 **HTML < ol >标签中。**

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/7fa470f4e0e365c620cfd960c3649f28.png)

为了开始抓取这些数据,我导入了 requests 模块,并将感兴趣的 URL 放在 requests.get 方法的括号中。接下来,我导入 BeautifulSoup 来解析这个 HTML 代码,并将解析器参数设置为“html.parser”。然后,我使用 soup 对象的 **findall** 方法来查找所有出现的“ol”。这将返回一个结果集对象,其行为类似于一个列表长度为 2 的 python 列表。我检查这两个列表,以找到我的信息所在的位置。我在变量名 prize_money_scrape 下索引第二个列表。为了查看这个列表的内容,我使用了 contents 属性。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/9e6a5f4394cdce4626822d70f49c186f.png)

虽然这个列表提供了我需要的信息,但是每个列表项都由换行符分隔。由于这遵循一种常规模式,我可以使用索引符号来提供跳过这些换行符的步骤。我从元素 2 (python 的列表 1)开始我的新收入列表,并以步长 2[1::2]递增。

既然换行符已经从列表中删除,我需要从

*   标签中提取数据。为此,我创建了一个名为 records 的新的空列表,遍历收入列表中的元素,并从结果集对象中提取文本,然后追加到新列表中。为了确认这些工作正常,我打印了新的记录列表。![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/bfe1fc8547722bac0a1194b878c80fb4.png)

我很喜欢熊猫的一点是,你可以把列表变成数据框。这样做很简单。现在,我可以通过将记录列表传递给 pd,将它转换成数据帧。DataFrame 方法。我在引号中的花括号内创建了一个新的列标题,用分号分隔,然后在结束花括号之前传入我的列表。当我可视化我的一列数据框架时,我可以看到它已经如预期的那样工作了。

新的数据框架有一列,将所有的信息转储在里面。理想的情况是“收入”和“团队”在不同的列中。为此,我在公共的 hypen (-)上拆分字符串,并使用 get 方法提取收入的第一个元素和团队的第二个元素,如下所示。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/96a93ef50441e65e28180f5e1bf9bec0.png)

为了与现有的 Premier League 表合并,我创建了一个新的公共列,它将在新抓取的 Premier_league_prize_money 数据框架和“Merged_premier_league_table”之间共享。我还删除了前缀“”符号和后缀“m”字符,将“收入”列转换为数字数据类型。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/24aff23aa2ef39877872e22b884bdc37.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/05b7a913c5250efd2d329614bc4ccf3c.png)

最后,我将 Team_x 列的名称改为 Team,并将“收入”列改为“奖金 _ 金钱 _ 百万”,这样就可以清楚地看出该列中的数值代表什么。

最后,在连续变量‘奖金 _ 百万’和‘平均 _ 分钟 _ 领先’之间建立一个关系是有用的。在英超联赛中领先的平均上场时间和获得的奖金之间有很强的相关性是合理的,但为了明确起见,我可以使用下面显示的代码片段使用海运库中的 **regplot** 函数绘制一个带有回归线的散点图(*这里,确保 seaborn 和 matplotlib 是通过 pip 命令安装的,并导入到您的 python 脚本*)。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/171dc9488a348afb3545e4bc4c34774a.png)

为了确定相关性,我使用了 **DataFrame.corr** 方法。我已经将可选的方法参数设置为' *pearson* ',但是也可以将 *kendall '和' spearman'* 作为可选参数提供,以覆盖默认参数' *pearson* '。

正如所料,这两个变量之间的相关性很强。正如可以合理预期的那样,你花在领导上的时间越多,获得的奖金就越多。

最后,作为总结,让我们看看最后一天的抽签对托特纳姆奖金的影响。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/f92905ff847396969b0478a47fd6ac1d.png)

200 万!

足球*真的*是个结果生意!

# 熊猫对足球运动员的价值

> 原文:<https://towardsdatascience.com/pandas-for-football-player-value-936c3243bd9a?source=collection_archive---------19----------------------->

## **一个网页抓取和熊猫指导教程**

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/1bd5c39212e6f93df34090c213b4bb41.png)

Image Courtesy of Joshua Hoehne via [Unsplash](https://unsplash.com/photos/1Nu_qjXO5-0)

在足球方面,一月为联赛中的球队提供了一个改变阵容的机会。

考虑到这一点,本教程将重点介绍如何在标准的 4-4-2 阵型中,为每个位置收集有史以来最昂贵的一月英超签约信息。

一旦抓取完成,本教程将展示如何转换 Pandas 数据框架中的抓取数据,并演示这种格式的数据结构如何对初始数据分析有用。

[下面显示的福布斯网页将在这里使用和提供。这个网页有你感兴趣的所有信息。](https://www.forbes.com/sites/robertkidd/2019/02/28/the-most-expensive-premier-league-signings-in-january-revealed/#5614d28fb095)

值得注意的是,所有位置的所有一月签约,球员转出的俱乐部,以及他们转入的俱乐部。此外,发生转会的年份,他们最初购买球员时的转会费,以及基于“*足球运动员通货膨胀率”*的他们现在的价值。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/a11c0487ffee2a8afcbc0cdb786412e0.png)

首先,我导入请求库。然后,我创建一个' **url** '变量,并将福布斯网站的 url 链接分配给这个变量。这个链接包含了一月转会窗口中最昂贵的转会的相关信息。

我使用请求库中的 get 方法开始提取数据。为了确认从我的 python 环境到网页的连接,我打印了 **status_code** ,它返回 200。

200 是“OK”的 HTTP 状态代码,表示成功响应。(其他你可能比较熟悉的代码有 404 找不到,403 禁止,500 内部服务器错误。)

一旦连接通过验证,我就使用 text 属性来检索 Forbes 网页的底层 html 源代码。当我打印 html 文本时,我的控制台中的输出非常大。为了帮助缩小我感兴趣的领域,我在控制台中使用“CTRL-F ”,搜索我知道会引导我到我想要提取数据的地方的玩家的名字。

这个搜索引导我找到我需要的信息,紧跟在 **<强>** 标签之后。从源输出的一瞥中,我可以看到吉文,纽卡斯尔到曼城,他的转会费是美元和美元,当球员最初被购买时,他的价值是美元和美元。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/37e4b6fe4feb1d7c4bf147ad126a520b.png)

在这种情况下特别有用的是底层 HTML 源代码的规律性。例如,每个玩家的名字都以同样的方式嵌入到一个 **<强>** 标签中。另外,球员转出的球队总是在'**之后 nbsp**的字符,以及前面的单词**到**。这种模式意味着我可以创建一个 for 循环来迭代我的代码并提取相关信息。

最初,我喜欢缩小搜索范围。htmltext = response.text 的输出返回一个巨大的字符串,我可以使用 split string 方法来拆分它。我在“*Fees reported”上进行拆分,通过索引为 1 获取该字符串之后的所有内容,并在一个唯一的字符串上再次拆分,通过索引为 0 获取之前的字符串。

这给我留下了一个缩短的字符串。为了将字符串“secondsplit”转换成一个列表,我在一个强标记处对其进行了拆分,并获取第二个元素(python index 1)之后的所有内容,直到列表的末尾。

这给我留下了一个列表(thirdsplit ),其中包含了我想要提取的每个玩家的所有信息。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/b673a93389a75f92b944fae1583aa4bf.png)

我现在可以迭代我的列表。例如,为了找到原始的转让费,我使用 split 方法来拆分我的 thirdsplit 列表中的每个元素,并通过使用子串符号来提取'($ '符号之后和' m '字符之前的字符串。

然后,我将每笔转让费附加到一个新构建的名为转让费的列表中。我重复同样的过程,以获得球员,他们的前俱乐部,转会年份,新俱乐部,以及截至 2019 年的费用,当足球运动员通货膨胀率适用时。

在某些情况下,for 循环中特定变量的 **split** 方法并不能完全删除所有必要的字符。当我运行如下所示的 for 循环时,前缀'**Jos&amp;eacute 出现在球员安东尼奥·雷耶斯面前。**

要创建新的玩家列表,我只需添加一个条件来删除这些字符,并生成一个新的列表。这包括检查前导字符并用空字符串替换它们,如所附 GitHub gist 代码片段所示。同样的验证也适用于 Old_team 列表。

一旦列表被收集和整理,我就可以创建一个熊猫数据框架。为此,我导入熊猫,并将我的列表一起压缩到 **pd 中。DataFrame** 方法。我为列表分配了适当的带标签的列名,这样它们就代表了列表的内容,例如“玩家”列指的是列表“玩家 _ 精炼”。

使用**将 transfer_df 数据帧列、Transfer_Fee、Transfer_Year 和 Cost_2019 的数据类型更改为适当的数字类型。astype()** 方法,在使用**根据最高 Transfer_Fee 对数据帧进行排序之前。sort_values()** 方法。

最后,我创建了另外两列。一个决定 2019 年球员成本(基于球员通货膨胀率)和他们在购买时的转会费之间的比率。第二列是指玩家各自的位置。

我实现的另一个步骤是对列进行重新排序。例如,如果球员名字后面跟着球员各自的位置,读起来会更好。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/0b067f3491f6c2d1240f4bdd95c1a1a5.png)

查看 transfer_df 数据帧时,所有必要的更改均已实施。

数据已经成功地从福布斯网页中提取出来,并输入到熊猫数据框架中!

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/a99543ac2c03dccd365cbf8cf0b50971.png)

熊猫图书馆中我非常喜欢的一个方面是用 T3 方法进行的 T2 分组。在这里,数据是非常清晰易读的形式。

很明显,在一月份,阿森纳以 2390 万美元的价格签下了最昂贵的左边锋安东尼奥·雷耶斯。除此之外,切尔西还签下了一月份 11 笔最昂贵的签约中的 4 笔(基于 4-4-2 阵型),其中 2 笔是在 2011 年。出于比较目的,这些数据比网页上显示的原始文本更容易解释。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/32f746418363bd8532b31f32e19b1f1a.png)

现在可以制作一个柱状图来帮助可视化从最初购买时间到现在的市场价值的相对变化。

转账费用变化栏和图表比福布斯网页上的原始文字更清楚地说明了这一点。

这张示意图显示,如果费尔南多·托雷斯在今天的转会市场上被购买,他的价格将是 2011 年的 2.10 倍。然而,从我们的表格和示意图中我们可以清楚地看到,埃梅里克·拉波尔特的成本会更低,是 2018 年支付给他的 0.84 倍。在极端的情况下,如果斯科特·帕克今天被买走,他将比他 2004 年最初的转会费高出 3.37 倍。

*在 y 轴的 1.0 处添加了一条标准化虚线,以显示比率的相对变化。*

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/3bcd01f9843de0baa3f4ce2a25ec40b2.png)

# 结论

这个介绍性的例子描述了我们如何抓取数据并将其转换成 pandas 数据帧。通过这样做,可以很容易地处理和分析数据。在这种情况下,现在很容易根据俱乐部分组,创建一个新列来计算原始购买和当前市场价值之间的转会费变化率。除此之外,我们还可以创建信息图,如本文中显示的条形图。

# 熊猫给匆忙的人

> 原文:<https://towardsdatascience.com/pandas-for-people-in-a-hurry-59d966630ae0?source=collection_archive---------5----------------------->

## 满足您所有数据探索需求的数据框架

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/715268d6f4a5c13c33576c2f4ac49f09.png)

Photo by [Pascal Müller](https://unsplash.com/@millerthachiller?utm_source=medium&utm_medium=referral) on [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral)

Pandas 是最流行的用于数据操作和数据分析的 Python 库。这是所有数据科学家必须知道的!

两只熊猫的数据结构是:

1.  熊猫数据框
2.  熊猫系列

我喜欢把熊猫数据框想象成一个 excel 表格。你有许多行和列的数据。然而,在 Pandas 中,列中的数据必须是相同的数据类型。熊猫系列只是熊猫数据框架中的一列。

这篇文章将为您提供大量有用的 Pandas 信息,告诉您如何使用 Pandas 中的不同方法进行数据探索和操作。这是一个很好的熊猫入门指南,也是一个很好的复习工具,如果你有一段时间没有使用熊猫的话。本概述将详细介绍如何导入数据集,以及如何探索、选择、清理、操作、聚合、组合和导出数据,以便您能够顺利完成下一个数据科学项目。

> 我在整篇文章中加入了一些“专家提示”,与你分享我在使用熊猫期间学到的一些有用的东西。如果你有一些很酷的建议要分享,我很想听听!下面掉个评论!

你可以在这里下载我的 Jupyter 笔记本[并跟随。下面描述的方法将以土壤数据集为例。我建议您打开 Jupyter 笔记本,以便可以看到代码的输出。](https://github.com/julia-git/Soils_DataSet)

# 开始提示

首先,确保您首先导入 Pandas 库。

`import pandas as pd`

我也喜欢在开始之前修改默认的熊猫选项。参见下面的专家提示。

> **专家提示:**默认情况下,如果数据框架中有许多列,并非所有的列都会显示在输出显示中。您可以使用这行代码来加宽输出显示中的列:

`pd.set_option('display.max_columns', 500)`

值 500 表示以字符为单位的列的最大宽度。也就是说,值 500 意味着您希望在调用 dataframe 时显示多达 500 列。默认值仅为 50。

此外,您可以使用类似的代码行来加宽输出显示中的行。这将允许显示多达 500 行。

`pd.set_option('display.max_rows', 500)`

# 进口到熊猫

导入数据将是项目的第一步。无论你有一个 excel 文件或 csv 文件,他们可以很容易地导入到熊猫。

要导入逗号分隔值(CSV)文件,请使用这行代码。

`pd.read_csv("Soils.csv")`

在括号内,`"Soils.csv",`是我上传的文件的名字。对于 excel 文件,使用这行代码。

`pd.read_excel("Soils.xls")`

为了成功导入您的文件,上面的代码假设数据文件位于您当前的工作目录中。

> **专家提示:**如果你不确定你的工作目录在哪里,在你的 Jupyter 笔记本里,你可以使用`!pwd`来得到你的工作目录。`!`字符告诉 Jupyter Notebook 将代码视为 OS shell 命令。
> 
> **专家提示:**如果您碰巧有任何日期时间类型的列,请在括号内添加`parse_dates = [column_name]`作为参数,以便 Pandas 可以将该列识别为日期。例如,如果您有一个名为 Collection_Date 的日期列,您会使用`pd.read_excel("Soils.xls", parse_dates = ['Collection_Date'])`吗

这是我成功导入后的数据帧片段。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/3104381669b32e7c9584e93dc110bc77.png)

# 探索您的数据

现在您的数据已经在 Pandas 的数据框架中,您已经准备好进行调查了。这里有几个有用的方法,每次引入数据集时都可以调用。这些步骤应该有助于您了解您的数据中有哪些内容。

## 探索数据框架

`df.head()`返回数据帧的前 5 行。要覆盖默认值,可以在括号之间插入一个值来更改返回的行数。示例:`df.head(10)`将返回 10 行。

`df.tail()`返回数据帧的最后 5 行。您可以在括号之间插入一个值来更改返回的行数。

`df.shape`返回表示维度的元组。例如,( 48,14)的输出代表 48 行和 14 列。

`df.info()`提供数据摘要,包括索引数据类型、列数据类型、非空值和内存使用情况。

`df.describe()`提供描述性统计数据,总结集中趋势、分散和形状。

## 浏览列

我最喜欢的方法之一就是`.value_counts()`。此方法为所选列中的每个唯一值提供计数。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/c566267d59a3d1bf04d8fb4f7ed419bd.png)

> **专家提示:**如果你更希望看到百分比而不是绝对数字的细分,试试`.value_counts(1)`吧。

这里有几个更有用的方法来看看你的数据框里有什么。

`df['Contour'].isnull().sum()`返回列“轮廓”中空值的计数

`df['pH'].notnull().sum()`返回列“pH”中非空值的计数

`df['Depth'].unique()`返回“深度”列中的唯一值

`df.columns`返回所有列的名称

# 选择数据

有许多不同的方法来选择您感兴趣的数据。以下是我常用的一些最有用的方法。

## 列选择

如果你想只选择一列,你可以使用`df['Group'].`这里‘组’是列名。

要选择多列,您可以使用`df[[‘Group’, ‘Contour’, ‘Depth’]]`。注意,选择多列时会使用双括号。只需传入您想要的列名。

## 子集选择/索引

为了选择特定的数据子集,我们依赖于`.loc`或`.iloc`方法。我建议您尝试一下这两种方法,以便更好地理解它们是如何工作的。

我们可以使用`df.loc[]`通过行和列的标签进行选择。

`df.loc[:,[‘Contour’]]`选择所有行和列的‘轮廓’。单冒号`:`选择所有的行。在逗号的左边,指定所需的行,在逗号的右边,指定列。

`df.loc[0:4,[‘Contour’]]`选择我们的索引 0 到 4 和列‘轮廓’。

另一方面,我们使用`df.iloc[]`按位置选择行和列。我们会传入整数位置。

`df.iloc[:,2]`选择位置 2 的所有行和列。

`df.iloc[3,:]`选择位置 3 的行和所有列。

## 过滤

此外,我们可以使用掩码来帮助我们在数据帧中选择符合特定标准的特定行。在下面的掩码中,根据语句计算列中的每个值。即值是否等于“顶”。

mask = df[‘Contour’] == “Top”
df[mask]


代码`df[‘Contour’] == “Top”`返回布尔值 True 或 False。当我们在`df[mask]`中使用布尔掩码时,它将只打印掩码为真的行。

该掩码也可用于计算数值列。在下面的示例中,当“Conduc”列中的值大于 10 时,将返回布尔值 True。

mask2 = df[‘Conduc’] > 10
mask2


使用掩码的另一个有用的方法是过滤列表中的项目。

mask3 = df[‘Contour’].isin([‘Depression’, ‘Slope’])
df[mask3]


> **专家提示**:如果你想选择你蒙版的反面,可以用蒂尔达符号。例如,`df[~mask3]`将选择“轮廓”列中既不包含凹陷也不包含坡度的所有行。

# 清理数据

只有数据本身是好的,一个数据科学项目才能是好的。也就是说,我们希望在将数据插入机器学习算法之前,数据质量良好。以下是一些有助于加速数据清理的有用方法。注意,我为下面的许多方法传入了`inplace=True`。这确保了更改发生在实际的数据帧中。如果您不传入这一行代码,数据帧中的更改实际上不会发生。

## **替换怪异字符**

`df.replace({‘Topk’: ‘Top’}, inplace=True)`

## 删除空值

`df[‘pH’].dropna(inplace=True)`

## 输入空值

`df[‘pH’].fillna(df[‘pH’].mean(), inplace=True) #nulls are imputed with mean of pH column`

## 删除行和列

`df.drop(columns = [‘Na’], inplace = True) #This drops the 'Na' column`

`df.drop(2, axis=0, inplace=True) #This drops the row at index 2`

需要注意的是,axis=0 告诉熊猫逐行下降。您可以使用 axis=1 来删除列。这适用于许多其他可用的熊猫方法。

## 更改列名

`df.rename(columns = {‘Conduc’ : ‘Cond’, ‘Dens’ : ‘Density’}, inplace = True)`

## 操纵数据

您可以使用`.apply`在数据框的行或列上应用一个函数。下面的代码将平方根应用于“Cond”列中的所有值

`df[‘Cond’].apply(np.sqrt)`

# 分组数据,数据聚合

有时,如果我们将数据分组进行观察,可以更好地识别差异和模式。

这里有几种不同的方法可以对数据进行分组。以下示例按“轮廓”列对数据进行分组,并计算“Ca”列中记录的平均值、总和或计数。请参阅 Jupyter Notebook 中的输出,以便更好地理解代码返回的内容。

`df.groupby(by=[‘Contour’])[‘Ca’].mean()`

`df.groupby(by=[‘Contour’])[‘Ca’].count()`

`df.groupby(by=[‘Contour’])[‘Ca’].sum()`

您也可以按多个列进行分组。

`df.groupby(by=[‘Contour’, ‘Gp’])[‘Ca’].mean()`

# 组合多个数据帧

有多种方法可以将两个数据帧组合在一起,根据您的特定任务,可能更适合使用其中一个来执行该任务。我倾向于使用的前两个是 concat 和 merge。

Concat 适用于堆叠多个数据帧的行。

**按列连接数据**

`pd.concat([df, df2], axis=1)`

**按行连接数据**

`pd.concat([df, df2], axis=0)`

当数据帧之间有公共列时,合并适合于合并数据帧。

**合并数据**

`pd.merge(df, df2, left_on=’Contour’, right_on=’Contour’, how=’outer’)`

关于合并,我不会讲太多细节,但是你可以在这里找到关于如何更好地利用它的很好的例子。

# 输出数据帧

一旦你清理和处理完你的数据。您可以将其输出到 csv 或 excel 文件来工作。

要将数据输出到由制表符分隔的 csv 文件,请使用下面的代码。`'\t'`表示您希望它用制表符分隔。如果你喜欢用`,`代替,你可以用`','`

`df.to_csv(‘myDataFrame.csv’, sep='\t')`

要输出到 excel:

writer = pd.ExcelWriter(‘myDataFrame.xlsx’)
df.to_excel(writer, ‘DataFrame’)
writer.save()


感谢阅读。如果你有一些关于熊猫的小贴士可以分享,别忘了发表评论。干杯。

# 数据科学家从基础到高级的熊猫

> 原文:<https://towardsdatascience.com/pandas-from-basic-to-advanced-for-data-scientists-aee4eed19cfe?source=collection_archive---------17----------------------->

## 熊猫让任何数据科学家的生活更轻松

> 数据科学家是能够获取、筛选、探索、建模和解释数据的人,融合了黑客技术、统计学和机器学习——希拉里·梅森

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/2a7c0c81065bb1c19cabb7594cc9b104.png)

image by [Ilona Froehlich](https://unsplash.com/@julilona)

> 哪里有烟,哪里就有火。同样,如果你在处理数据,熊猫也不会休假。它帮助您尽可能快地探索和解释数据。

> Pandas 是最常用的 python 库,用于数据操作和数据分析。

在这篇文章中,我将尝试解决熊猫的概念或技巧,使我们的生活更容易。让我们从基础到高级。我将在天气数据的帮助下穿过熊猫。

# 导入熊猫并创建数据框

使用文件、列表、字典等创建数据框的方法有很多种。这里,我通过从 CSV 文件中读取数据创建了一个数据框。

import pandas as pddf = pd.read_csv("weather.csv")
df


> 输出

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/beab3bf27b6584e3b35339125000eb7d.png)

Weather data

# 选择特定的列

有时您只需要操作或操纵特定的列。让我们假设你想分析温度每天是如何变化的。在这种情况下,我们将选择温度和日期。

df[[‘temperature’,’day’]]


# 重命名该列

Pandas 为您提供了一个简单的功能(重命名),可以更改一个或一组列的名称,从而简化工作。

df.rename(columns = {‘temperature’: ‘temp’, ‘event’:’eventtype’})


# 过滤数据帧

假设你想看看随着日期的推移越来越热的城市。

df[[‘day’,’city’]][df.event==’Sunny’]


> 输出

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/4e5f307e437fa4218d0ebcf60efbba4c.png)

Filtered data

> 到目前为止,我们已经看到了一些基础知识,让我们深入了解,真正的熊猫从这里开始。正如我所说,熊猫永远不会休假,即使你想有复杂的问题。

# 分组

假设你想操作一组特定的数据。在这种情况下,让我们只获取属于纽约的行。使用 group object,您可以同时获得所有组的总和、平均值和中值。

> **按城市分组**

city_group = df.groupby(‘city’)


一个组对象被创建,如果你想看到特定的组数据,只需要得到组。

city_group.get_group(‘new york’)


> **输出**

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/decbfbff0fe3b6ab8863e4fb3329aa1c.png)

new york group

# 聚集

在上面的部分中,我们只是按城市对数据进行了分组,但是如果我想查看平均温度和平均风速呢???。我们将在这里使用聚合。

> 分组依据和聚合

df.groupby(‘city’).agg({‘temperature’:’mean’, ‘windspeed’:’mean’})


> 输出

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/0feb83e4829266a95d3a87160305c66f.png)

Mean temperature and wind speed

# 合并

在以上各节中,我们讨论了拥有单个数据框的问题。如果有两个数据框,并且您想一起分析它们!!!。在这种情况下,合并起着关键作用,并简化了两个数据框的连接。

## 创建两个数据框

df1 = pd.DataFrame({
“city”: [“new york”,”florida”,”mumbai”],
“temperature”: [22,37,35],
})
df2 = pd.DataFrame({
“city”: [“chicago”,”new york”,”florida”],
“humidity”: [65,68,75],
})


**简单合并:**这给了你两个数据框中匹配的行

pd.merge(df1,df2,on=’city’)


> 输出

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/fc7434242f422483156212475fae270d.png)

Matching rows of two data frames

**Outer:** 从两个数据帧中获取所有行。添加新参数(如何)。

pd.merge(df1,df2,on=”city”,how=”outer”)


> 输出

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/34d605070608cd7f3b5d11ceadc1fabb.png)

Outer join

类似地,我们可以获得所有匹配的行以及左数据框(左连接)和右数据框(右连接)。*通过指定参数 how 与值 left/right。*

# 交叉表

假设您想要查看每个城市中事件类型(雨天/晴天)的频率计数。十字标签使这些事情变得更容易。

pd.crosstab(df.city,df.event)


> 输出

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/a648fcf63e2daa18c466cc9df696db0b.png)

Frequency count of the event by city

注意:我们可以得到任何聚合平均值、中位数等。我们只需要给函数传递一个额外的参数。

# 用熔体重塑

如果您希望将列作为值的行,假设对于每个城市,我希望将温度和风速放在单独的值列中。在这种情况下,温度、风速保存一列,它们的值保存另一列。

pd.melt(df,id_vars=[‘day’,’city’,’event’],var_name=’attribute’)


> 输出

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/56ed42f55149e744273b4fa15059d2a2.png)

Reshaped data

## 参考

代码基础知识,【https://www.youtube.com/channel/UCh9nVJoWXmFb7sLApWGcLPQ 

> 希望你喜欢它!!!你也可以看看关于熊猫戏法的文章,这将会更有趣[数据科学家的熊猫戏法](/pandas-tricks-for-data-scientists-465902163545)!!!敬请期待!!!!请对任何疑问或建议发表评论!!!!!

[](/pandas-tricks-for-data-scientists-465902163545) [## 数据科学家的熊猫把戏

### 熊猫让任何数据科学家的生活更轻松

towardsdatascience.com](/pandas-tricks-for-data-scientists-465902163545)

# 熊猫小组详细解释了

> 原文:<https://towardsdatascience.com/pandas-groupby-aggregate-transform-filter-c95ba3444bbb?source=collection_archive---------0----------------------->

## 熊猫终极指南

## 了解如何掌握所有 Pandas 的 groupby 功能,如聚集、转换和过滤——这是一份附有大量示例的代码指南

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/7000bf860d83631838a8a7dd8fd1a5c5.png)

[Source](https://www.economist.com/china/2016/09/08/survival-of-the-cutest)

写关于熊猫的文章是最好的。我最喜欢的部分是当我在网上搜索可爱的熊猫图片的时候。Cmon 你怎么能不爱熊猫呢?还有成群的熊猫,更好!反正我跑题了…

# 介绍

andas 的 groupby 无疑是熊猫带来的最强大的功能之一。然而,**大多数用户只利用了** `**groupby**`的一小部分功能。

`Groupby`允许对数据集采用拆分-应用-组合的方法。这种方法通常用于对数据进行分割,以便数据分析师可以回答特定的问题。

## 在高级分组上,by 允许:

1.  根据列/条件将数据分成组;
2.  对所有组应用函数/变换,并将结果组合成输出

## 在本文中,我们将讨论以下主题:

1.  [加载数据](#08dc)
2.  [分组依据—拆分数据](#3a1f)
3.  [应用并组合—](#d6c9) `[apply](#d6c9)` [,](#d6c9) `[agg(regate)](#d6c9)` [,](#d6c9) `[transform](#d6c9)` [,](#d6c9) `[filter](#d6c9)`

你可以在这里找到完整的 Jupyter 笔记本。但是我强烈建议您亲自完成这些步骤。毕竟,熟能生巧。

# ①加载数据

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/9d43ec413213993003f79a19ec4bde88.png)

Photo by [NASA](https://unsplash.com/@nasa?utm_source=medium&utm_medium=referral) on [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral)

我们将使用一个假设的销售部门的数据。数据集由虚构的销售代表、订单线索、可能达成交易的公司、订单价值和线索日期等列组成。

order_leads = pd.read_csv(
'https://raw.githubusercontent.com/FBosler/Medium-Data-Exploration/master/order_leads.csv',
parse_dates = [3]
)
sales_team = pd.read_csv(
'https://raw.githubusercontent.com/FBosler/Medium-Data-Exploration/master/sales_team.csv',
parse_dates = [3]
)df = pd.merge(
order_leads,
sales_team,
on=['Company Id','Company Name']
)df = df.rename(
columns={'Order Value':'Val','Converted':'Sale'}
)


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/5b4b5e8b95d7ca4e44a3789ecc63809d.png)

100k rows of order lead data

# ②分组依据——拆分数据

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/629e6ee302d9f1441656d4eafab1c246.png)

Photo by [Chris Child](https://unsplash.com/@chris23?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/splitting-wood?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)

调用 groupby 的默认方法是通过显式提供一个列名来拆分数据集。但是,还有一点不太为人所知,那就是您也可以将一个系列传递给 groupby。唯一的限制是序列的长度与数据帧的长度相同。
能够传递一个序列意味着您可以根据一个列的处理版本进行分组,而不必为此创建一个新的帮助列。

## 按销售代表分组

首先,让我们创建一个分组的数据框架,即将数据集拆分。

IN:
grouped = df.groupby('Sales Rep')
groupedOUT: <pandas.core.groupby.generic.DataFrameGroupBy object at 0x12464a160>IN: type(grouped)OUT: pandas.core.groupby.generic.DataFrameGroupBy


我们现在已经创建了一个`**DataFrameGroupBy**`对象。让我们进一步调查:

## 显示所有组

在分组对象上调用`groups`会返回每个组的索引列表(因为每一行都可以通过其索引唯一地标识)

IN: grouped.groupsOUT: {
'Aaron Hendrickson': Int64Index(
[25612, 25613, 25614, 25615, 25616, 25617, 25618, 25619, 25620, 25621,..., 25894, 25895, 25896, 25897, 25898, 25899, 25900, 25901, 25902, 25903], dtype='int64', length=292
),'Adam Sawyer': Int64Index(
[67140, 67141, 67142, 67143, 67144, 67145, 67146, 67147, 67148, 67149, ..., 67454, 67455, 67456, 67457, 67458, 67459, 67460, 67461, 67462, 67463], dtype='int64', length=324
),...****'Yvonne Lindsey': Int64Index([20384, 20385, 20386, 20387, 20388, 20389, 20390, 20391, 20392, 20393, 20394, 20395, 20396, 20397, 20398, 20399, 20400, 20401, ... , 20447, 20448, 20449, 20450], dtype='int64', length=67)
}


## 选择特定的组

通过用组名调用`get_group`,我们可以返回各自的数据子集。

grouped.get_group('Aaron Hendrickson')


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/f1109d380358bccb613aa9e256402704.png)

‘Aaron Hendrickson’ group

为了演示一些高级分组功能,我们将通过`size`方法使用 apply 步骤的最简单版本(并计算每个组中的行数)。我们这样做是为了将重点放在 groupby 操作上。

我们将在文章的第 2 部分更详细地讨论应用方法。

## 计算每组中的行数

IN: grouped.size()OUT: Sales Rep
Aaron Hendrickson 292
Adam Sawyer 324
Adele Kimmel 115
Adrian Daugherty 369
Adrianna Shelton 37
...
Willie Lin 44
Willie Rau 95
Willie Sanchez 309
Yvonne Jones 74
Yvonne Lindsey 67
Length: 499, dtype: int64


## 按销售代表的名字分组

下面是第一个例子,我们根据一个现有列的变化进行分组。我发现这比一直创建助手列有了很大的改进。它只是让数据更干净。

在这个例子中,我们使用一个字符串访问器来检索名字。你可以在这里阅读访问器。

IN:
df.groupby(
df['Sales Rep'].str.split(' ').str[0]
).size()OUT: Sales Rep
Aaron 292
Adam 324
Adele 115
Adrian 369
Adrianna 37
...
Wesley 144
Wilbert 213
William 1393 # Plenty of Williams
Willie 448
Yvonne 141
Length: 318, dtype: int64


## 根据代表姓名中是否有“William”进行分组

我们看到似乎有很多 Williams,让我们将所有名字中有 William 的销售代表分组。

IN: df.groupby(
df['Sales Rep'].apply(lambda x: 'William' in x)
).size()OUT: Sales Rep
False 97111
True 2889
dtype: int64


## 按随机系列分组(仅供说明)

不可否认,这个例子很傻,但是它说明了你可以很好地按照任意序列进行分组。

IN: df.groupby(
pd.Series(np.random.choice(list('ABCDG'),len(df)))
).size()OUT: A 19895
B 20114
C 19894
D 20108
G 19989
dtype: int64


## 通过三个均匀切割的“Val”桶进行分组

在下面的例子中,我们首先将`qcut`应用于一个数字列。`qcut`将数据平均分配到固定数量的箱中。

IN:
df.groupby(
pd.qcut(
x=df['Val'],
q=3,
labels=['low','mid','high']
)
).size()OUT: Val
low 33339
mid 33336
high 33325
dtype: int64


## 按定制大小的“有值”存储桶分组

像前面的例子一样,我们将数据分配到桶中。然而,这一次我们也指定了容器的边界。

IN:
df.groupby(
pd.cut(
df['Val'],
[0,3000,5000,7000,10000]
)
).size()OUT: Val
(0, 3000] 29220
(3000, 5000] 19892
(5000, 7000] 20359
(7000, 10000] 30529
dtype: int64


# `pd.Grouper`

`**pd.Grouper**`重要!这个方法花了我很长时间才学会,因为它在处理时间序列数据时非常有用。

## 按年份分组

在下面的例子中,我们将使用`pd.Grouper(key=<INPUT COLUMN>, freq=<DESIRED FREQUENCY>)`根据指定列的指定频率对数据进行分组。在我们的例子中,频率是`'Y'`,相关列是`'Date'`。

IN:
df.groupby(
pd.Grouper(
key='Date',
freq='Y')
).size()OUT: Date
2014-12-31 19956
2015-12-31 20054
2016-12-31 20133
2017-12-31 20079
2018-12-31 19778
Freq: A-DEC, dtype: int64


## 按四分之一或其他频率分组

代替`'Y'`,我们可以使用不同的标准频率,如`'D','W','M', or 'Q'`。有关不常用频率的列表,请查阅[文档](http://pandas.pydata.org/pandas-docs/stable/user_guide/timeseries.html#offset-aliases)。
我发现`'SM'`的半月末频率(15 日和月末)是一个有趣的频率。

IN:
df.groupby(pd.Grouper(key='Date',freq='Q')).size()OUT: Date
2014-03-31 4949
2014-06-30 4948
2014-09-30 4986
2014-12-31 5073
2015-03-31 4958
2015-06-30 4968
2015-09-30 5109
2015-12-31 5019
2016-03-31 5064
2016-06-30 4892
2016-09-30 5148
2016-12-31 5029
2017-03-31 4959
2017-06-30 5102
2017-09-30 5077
2017-12-31 4941
2018-03-31 4889
2018-06-30 4939
2018-09-30 4975
2018-12-31 4975
Freq: Q-DEC, dtype: int64


## 按多列分组

到目前为止,我们只按一个列或转换进行了分组。当我们想要通过多个列或转换进行分组时,同样的逻辑也适用。我们要做的就是传递一个列表给`groupby`。

IN:
df.groupby(['Sales Rep','Company Name']).size()OUT: Sales Rep Company Name
Aaron Hendrickson 6-Foot Homosexuals 20
63D House'S 27
Angular Liberalism 28
Boon Blish'S 18
Business-Like Structures 21
..
Yvonne Jones Entry-Limiting Westinghouse 20
Intractable Fairgoers 18
Smarter Java 17
Yvonne Lindsey Meretricious Fabrication 28
Shrill Co-Op 39
Length: 4619, dtype: int64


随机的名字,我发誓!

# ③应用并组合— `apply`、`agg(regate)`、`transform`和`filter`

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/cdbc2734991f15300c0723ace0233ea1.png)

Photo by [andrew welch](https://unsplash.com/@andrewwelch3?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/glue-together?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)

在前面的章节中,我们讨论了如何根据各种条件对数据进行分组。本节讨论在将它们组合成最终结果之前,我们可以应用于这些组的可用函数。

## 本节围绕如何使用

🅐 `apply`、
🅑 `agg(regate)`、
🅒 `transform`、
🅓 `filter`

如果你在我开始使用 groupby 时和我一样,你可能正在使用🅐和🅑的组合,大致如下:

grouped = df.groupby('GROUP') and then:

  • group.apply(mean)
  • group.agg(mean)
  • group['INTERSTING COLUMN'].apply(mean)
  • group.agg({'INTERSTING COLUMN':mean})
  • group.mean()

其中`mean`也可以是另一个函数。

好消息是,它们全都有效。大多数时候,结果会和你预期的差不多。

坏消息:apply 和 agg 都有值得深究的细微差别。

此外,更重要的是,两个鲜为人知的强大功能可以用在一个分组对象上,`filter`和`transform`。

## 🅐·阿普申:让我们把阿普申弄清楚

Apply 有点令人困惑,因为我们经常谈论应用函数,而实际上也有应用函数。但是请原谅我。`apply`函数沿数据帧的轴应用一个函数。应用程序可以是按列或按行的。
`apply`严格来说并不是一个只能在 groupby 上下文中使用的函数。您还可以在完整的数据帧上使用`apply`,如下例所示(我们使用`_`作为抛弃变量)。

_ = pd.DataFrame(
np.random.random((2,6)),
columns=list('ABCDEF')
)
_


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/8fe5bf9ff447fb4146a56b667d9edd15.png)

Random DataFrame with six columns

IN:
_.apply(sum, axis=0) # axis=0 is default, so you could drop itOUT: A 0.620289
B 0.818850
C 0.672706
D 1.269064
E 1.156606
F 0.934941
dtype: float64IN: _.apply(sum, axis=1)OUT: 0 2.868145
1 2.604311
dtype: float64


但是`apply`也可以用在 groupby 上下文中。这很有意义,因为每个组本身就是一个更小的数据框架。请记住,该函数将应用于整个数据帧。将该函数应用于整个数据帧通常意味着您想要选择使用函数的列。我们将把它留在下面的两个例子中,而是集中在`agg(regation)`上,这是聚合组的“预期”方式。

IN:
df.groupby(
pd.Grouper(key='Date',freq='Y')
)['Sale'].apply(sum)OUT: Date
2014-12-31 3681
2015-12-31 3800
2016-12-31 3881
2017-12-31 3068
2018-12-31 2478
Freq: A-DEC, Name: Sale, dtype: int64IN: df.groupby(
pd.Grouper(key='Date',freq='Y')
)['Val','Sale'].apply(sum)OUT: Date Val Sale
2014-12-31 100422394 3681
2015-12-31 101724648 3800
2016-12-31 101789642 3881
2017-12-31 101957784 3068
2018-12-31 100399962 2478


## 🅑·阿格(雷加特)

请注意`agg`和`aggregate`可以互换使用。`agg`更短,所以我将继续使用它。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/0b6b87fbb4e09376004f93a22882abc2.png)

Visualization of a typical split-apply-combine process with multiple aggregations functions that are being applied to each group individually

总的来说,聚合是其中最强大的。让我们仔细分析上面的图像,主要关注这个过程的右边部分。下面的代码片段创建了上图的放大版本。

df.groupby('Sales Rep').agg({
'Order Id':'size',
'Val':['sum','mean'],
'Sale':['sum','mean']
})


我们将一个字典传递给聚合函数,其中键(即`Order Id`、`Val`、`Sale`)是列,值(`'size'`、`['sum','mean']`、`['sum','mean']`)是应用于各个列的函数。

请注意,函数可以是单个函数,也可以是函数列表(所有函数都将被应用)。另外,请注意`agg`可以使用函数名(即字符串)或实际函数(即 Python 对象)。在这里可以找到功能的非详尽列表[。我最常用的是:](https://pandas.pydata.org/pandas-docs/stable/getting_started/basics.html#descriptive-statistics)

*   `**'size'**` **:** 统计行数
*   `**'sum'**` **:** 向上对列求和
*   `**'mean'/'median'**` **:** 列的平均值/中值
*   `**'max'/'min'**` **:** 列的最大值/最小值
*   `**'idxmax'/'idxmin'**` **:** 列的最大值/最小值索引。获取最小值或最大值的索引有助于映射其他列,例如,每个销售代表的最大交易的公司名称是什么
*   `**pd.Series.nunique**` **:** 统计唯一值。注意,与前面的函数不同,这是一个实际的函数,而不是一个字符串。

## 警察。NamedAgg

现在,当以这种方式将多个聚合函数应用于多个列时,一个问题是结果会变得有点混乱,并且无法控制列名。在过去,我经常发现自己聚集了一个数据帧,然后直接重命名结果。我总觉得那有点低效。

像这样的情况正是`pd.NamedAgg`派上用场的时候。`pd.NamedAgg`是在 Pandas 版本 0.25 中引入的,允许指定目标列的名称。

def cr(x):
return round(np.mean(x),2)# Long Form: Explictly specifying the NamedAgg
aggregation = {
'Potential Sales': pd.NamedAgg(column='Val', aggfunc='size'),
'Sales': pd.NamedAgg(column='Sale', aggfunc='sum'),
'Conversion Rate': pd.NamedAgg(column='Sale', aggfunc=cr)
}# Alternative: Since the NamedAgg is just a tuple, we can also pass regular tuples
aggregation = {
'Potential Sales': ('Val','size'),
'Sales': ('Sale','sum'),
'Conversion Rate': ('Sale',cr)
}df.groupby('Sales Rep').agg(**aggregation)


运行上面的代码片段会导致:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/054853fb594b487be7cef1bde39cbe9d.png)

Result of aggregation with built-in renaming of columns

## 🅒 `transform`

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/a4877ef7dbf3baf368e88ff0c57e4205.png)

Visualization of a typical split-apply-combine process with transform being applied to the ‘Val’ column. Transform sums up the column on a group level and assigns the summed value back to every row.

agg 返回输入的简化版本,而 transform 返回完整数据的组级转换版本的。新输出数据的长度与输入数据的长度相同。对于来自 SQL 的用户,可以将 transform 看作一个窗口函数。

一个典型的例子是通过除以组间总和来获得组总数的百分比。

IN:
df.groupby('Sales Rep')['Val'].transform(lambda x: x/sum(x))OUT: 0 0.004991
1 0.005693
2 0.003976
3 0.000799
4 0.003300
...
99995 0.012088
99996 0.000711
99997 0.013741
99998 0.010695
99999 0.001533
Name: Val, Length: 100000, dtype: float64


与`agg`不同,`transform`通常通过将结果分配给新列来使用。在上面的例子中,我们可以:

df['%'] = df.groupby('Sales Rep')['Val'].transform(
lambda x: x/sum(x)
)


查看这篇文章,学习如何使用`transform`来删除丢失的值。

[](/using-pandas-transform-and-apply-to-deal-with-missing-data-on-a-group-level-cb6ccf060531) [## 使用 Panda 的“转换”和“应用”在组级别处理缺失数据

### 了解当您不想简单地丢弃丢失的数据时应该怎么做。

towardsdatascience.com](/using-pandas-transform-and-apply-to-deal-with-missing-data-on-a-group-level-cb6ccf060531) 

## 🅓 `filter`

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/7b845699e119eacb31337a946009ec39.png)

Visualization of a typical split-apply-combine process with the filter being applied to the ‘Sale’ column. The specified filter is used on a group level and will only leave groups with at least one Sale.

顾名思义,Filter 不以任何方式改变数据,而是选择数据的子集。对于来自 SQL 的用户,可以把 filter 看作 HAVING 条件。

例如,我们可以筛选所有至少赚了 20 万英镑的销售代表

IN: df.groupby('Sales Rep').filter(
lambda x: (x['Val'] * x['Sale']).sum() > 200000
)


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/7a2690e5a103e6e3906b48e8ed8f6626.png)

Filtered DataFrame — Condition: Realized Sales > 200k

或者转化率> 30%的所有销售代表:

IN:
# Let's add this for verification
df['cr'] = df.groupby('Sales Rep')['Sale'].transform('mean')df.groupby('Sales Rep').filter(lambda x: x['Sale'].mean() > .3)


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/418e12612a9afa05784da9fbf86f0035.png)

# 结束语

在本文中,您学习了如何像真正的熊猫专家一样对数据帧进行分组。您学习了许多对数据进行分组的方法。你学会了区分`apply`和`agg`。您学习并应用了最常见的聚合函数。你已经看到了不常用的`transform`和`filter`派上了用场。

想聊天请登陆 [LinkedIn](https://www.linkedin.com/in/fbosler/) !我很乐意和你谈谈,或者回答你可能有的任何问题。

另外,看看我在 Medium 上写的其他文章

干得好,感谢您的阅读!

# 熊猫分组和数据处理技巧-国际足联球员数据

> 原文:<https://towardsdatascience.com/pandas-groupby-and-data-handling-tips-fifa-player-data-f37bd47c758a?source=collection_archive---------18----------------------->

# FIFA 19 完整球员数据集

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/a66a33a1d6bb727f679ecabe38cb3c3f.png)

Image Courtesy of [JESHOOTS.COM](https://unsplash.com/@jeshoots) via [Unsplash](https://unsplash.com/photos/eCktzGjC-iU)

## 进行分组并展示/使用这些数据

熊猫的分组代表了图书馆最强大的功能之一。它将简单性与效率结合在一起。这有助于减少回答数据科学问题时需要编写的代码量。这篇文章的目的是展示一些有用的特性,并结合一些同样有用的熊猫技巧。

## 像往常一样,我将使用一个足球的例子

这篇教程文章使用的数据集可以从 Kaggle 的以下[链接](https://www.kaggle.com/karangadiya/fifa19)获得,标题为“FIFA 19 完整球员数据集”。我已经包含了导入 pandas 和 matplotlib 的导入库代码,并删除了不必要的列。

此外,据我从 Kaggle 了解,这个数据帧将拥有超过 80 列。我将显示模块的 max_columns 属性设置为 90,这样在我读入的 fifa_19_players_df 数据帧的底部会出现一个滑动条。当处理包含大量列的数据帧时,我建议重新分配 columns 属性,以避免视图被截断,并更好地理解底层数据。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/212cd96dd284cc823294bd2ff68d2c28.png)

By re-assigning the max_columns attribute from the display method to encompass all the columns in a Dataframe, a better sense of the data can be gleaned!

## 1.创建 Groupby 对象

在 Pandas 中,groupby 方法直接在 Dataframe 对象上调用,在本例中是 fifa_19_players_data。在下面的示例中,返回的 groupby 对象基于“Club”列中的公共列值,并被赋予变量名“Team”。

这个团队变量代表分组数据帧的容器。该容器中的每个数据帧被分组在一个公共俱乐部上。

## 2.Groupby 对象方法

*size()和 get_group()*

为了演示 team 变量指向表示数据帧集合的 groupby 对象,有一个称为 get_group()的方便方法,可以在 groupby 对象上直接调用该方法。

为了最初访问组,可以在 groupby 对象上调用 size()方法,该对象返回一个序列。在这个系列中,俱乐部是索引,列是每个分组数据帧中的行数。

这里,我链接了方法来获得 5 个最大的数据帧。从这个命令输出,阿森纳有 33 名球员代表。要直接查看这些球员,我们可以在 team groupby 对象上调用 get_group 方法,将'阿森纳'作为字符串参数传递。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/4030cdfc6831ce19c0a9fd76d2e9fe11.png)

一旦这个数据帧被导出,我们就可以进行绘制,如所描绘的水平条形图。在本例中,我按照“工资”列对阿森纳数据帧中的值进行排序,将升序参数参数设置为 False,并在绘图前使用 head 方法获取前 10 个结果。

## 3.使用内置模板和用户定义的颜色选项定制绘图

“gplot”模板与“#61D199”颜色参数相结合,为横条图提供了很好的专业优势。ggplot 作为字符串从样式模块提供给 use 方法。奥巴姆扬显然是 2019 年数据集中收入最高的国家之一。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/ffe154721be0d820b7652de9e23c80cd.png)

**#OzilOut** -with Ozil not playing and making a dent on Arsenal’s bottom line, is it time to say goodbye to the German?

## 4.熊猫 Styler 对象

*-包括水平杆*

使用上述数据框中的绘图方法生成的水平条形图很好地直观显示了周工资。通过调用熊猫 Styler 对象上的 bar 方法,也可以在数据框中直接传达这些信息。

举例来说,当我附加。style 放在我的数据框架的末尾,我从其中提取了 4 列作为列表,并将这个对象传递给 Python 的内置类型函数,*返回 Styler 对象*。

现在很容易在这个 Styler 对象上调用 bar 方法。Styler 对象有一个接受字符串列名或列名列表的子集参数。为了一致性,我传递了相同的颜色参数,如上面的水平图参数。如果 2 列被传递给子集参数,请注意 2 个不同的*颜色参数可以作为一个列表被传递给颜色参数。通过这种方式,可以灵活地调整最终 Styler 对象的用户定制。*

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/8f0e92ab18c142cbd1698829d8f605d7.png)

## 5.那个。groupby 对象的 agg()方法

agg 方法可以有效地在 groupby 对象上调用。为了举例说明一个用例,除了每个分组球杆的加速度和击球力量列之外,我还想知道总体列的平均值。

为了做到这一点,我在我的团队变量上调用 agg 方法,该方法指向之前创建的 groupby 对象,并将其传递给 Python 字典。

在本词典中,键是原始“fifa _ 19 _ players _ data”中作为字符串的列,值是我在聚合时想要使用的函数,聚合也是作为字符串传递的。我通过将升序参数设置为 False,按整体列从最高到最低对值进行排序,并查看前 10 个搜索结果。尤文图斯以平均 82.28 分名列榜首。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/b465fdd291d8a349b6da43b54da010e5.png)

## 6.精度选项和设置

出于演示的目的,我经常改变浮点数的设置选项。要将 6 位小数的默认值更改为 2,我只需直接在 panasus 库(这里有 pd 的通用别名)上调用 set option 方法,然后再次运行该单元。给出的浮点数现在已经四舍五入到小数点后两位。

这种方法特别有用,因为它不改变底层数据,并保持精度。如果目的是导出数据,数字浮点数仍将保持其精度,精确到小数点后 6 位。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/ea56d51629cf23af63aa76b3ab46cbb1.png)

## 7.与每个团队的“最佳”玩家一起创建一个数据框架

从这个数据集,可以区分每家俱乐部的最佳足球运动员的指标是原始 fifa_19_players_data Dataframe 中的“总体”栏。

为了再次创建熟悉的 groupby 对象,我调用了 fifa_19_players_data 上的 groupby 方法,将 Club 列作为字符串传递。我将这个 groupby 对象分配给可变团队。

为了创建一个拥有每支队伍中最优秀的*球员的数据框架,我使用了数据框架构造方法,并且只传递了一个参数。此参数是 columns 参数的原始 fifa _ 19 _ players _ data Dataframe 的 columns 属性。这将创建一个空的数据帧,其列标题与 fifa_19_players_data 数据帧相同。我称这个数据框架最伟大。*

*然后,我使用 for 循环遍历我的 groupby 对象。我分配了两个临时变量,一个用于分组,一个用于与该分组相关的数据帧。对于分组中的每个数据框架(我已经为其分配了变量名数据),我使用最大值方法,并从总体列中获取最高值。我把这一行分配给可变的最佳玩家。最后,在每次迭代中,我都会将这一行附加到 _ club _ players _ df 上。*

*然后,我按“整体”栏对最伟大的俱乐部球员进行排序,并首先查看最高的栏。毫不奇怪,葡萄牙的罗纳尔多和阿根廷的梅西分别是尤文图斯和巴塞罗那的顶级球员。*

*![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/394c024f15a22ac449958ab2f9294954.png)*

*Still shot for my Jupyter Notebook. The replica code can be found in the Github gist above.*

## *总结提示*

*最后,让我们向最伟大的俱乐部球员数据框架中的整体一栏所确定的顶级球员致敬。*

*我将使用 Jupyter 笔记本中的一种细胞身体魔法,这种魔法可以整合一张图片。我写了 2 %的符号,然后是 html,然后是下面的 html 标签。我运行的细胞是“代码”细胞类型,现在这张来自[as.com](https://en.as.com/en/2019/10/15/football/1571134437_699111.html)的克里斯蒂亚诺·罗纳尔多的照片包含在笔记本中,可以用来通过代码更好地帮助讲述故事!*

*![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/d8f0360fd49fb56c62fb4fe58903639e.png)*

*为熊猫干杯!*

# 对数据执行非常基本的 Pandas 操作

> 原文:<https://towardsdatascience.com/pandas-guide-with-python-example-ii-basic-pandas-operations-4cf9704fd062?source=collection_archive---------10----------------------->

## 在本指南中,您将学习使用 pandas 对数据执行的最基本操作。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/cad36e90995c8d4453037e77d808e929.png)

image credit: [istockphoto](https://www.istockphoto.com/in/vector/checklist-browser-window-check-mark-white-tick-on-laptop-screen-choice-survey-gm954688868-260661708)

数据科学家花费大量时间清理数据集,并将它们转换成他们可以使用的形式。事实上,许多数据科学家认为,获取和清理数据的初始步骤构成了 80%的工作。

因此,如果您刚刚进入这个领域,能够处理混乱的数据是很重要的,这意味着缺少值、不一致的格式和格式错误的记录。

如果你刚刚开始接触熊猫,这里执行的操作是非常基础和重要的。

# **你会学到什么?**

您将学习在数据处理和数据分析过程中对数据执行的一些最基本的操作。

# **读取 CSV 文件:**

使用 pandas 读取带有任何扩展名的文件非常简单。只有两行代码,仅此而已。您可以读取不同的文件类型,如 ***CSV*** , ***DOCS*** , ***XLSV,******jpg***等等。在下面的例子中,我的 ***car_data.csv*** 文件包含 7 个不同类型的列,为了读取这个文件,我使用 pandas***read _ CSV(****‘filename _ with _ ext’)*。

当你输入上述代码并按下 ***回车*** 时,如果一切正常,它将显示下表作为输出。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/42a1068e9f0c877da589565ae5859258.png)

# **知道列数据类型:**

总是有必要知道数据集中的数据类型,以便对数据执行相应的操作,这给了你对数据的直觉。在你的笔记本上输入下面的命令。

df.dtypes


在下图中,它显示了表中每一列的数据类型。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/a89027ecfe385a3ae5196dd563aed8dc.png)

# ***头部()*和尾部()功能:**

当你有一个巨大的数据集,这意味着大量的行和列,那么数据科学家立刻可视化数据是严格的,这就是熊猫的 ***【头()*** 和 ***尾()*** 功能发挥作用的地方。 ***head()*** 函数仅显示吨行中的前 5 行,而 ***tail()*** 函数显示后 5 行。如果您想查看最上面的 50 行和最下面的 50 行,您只需要将整数作为参数传递给这些函数就可以了。如您所知, ***head()*** 函数默认情况下只显示前 5 行,而我的数据集只有 4 行,所以在下图中只显示了 4 行。同理 ***【尾巴()】*** 也是一样的道理。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/68c6e2a828749187eeb3caa749d847d7.png)

如果我们希望看到前 2 行,那么我们将在方法 ***head()* 中传递整数 2 作为参数。请看下图。**

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/5ab9215be32fe1c34663555b8feb9f34.png)

# **to_numpy():**

可能会出现这样一种情况,您有一个表格形式的数据集,称为数据框,而您的训练数据的机器学习功能希望数据采用数组形式。所以这里的 ***to_numpy()*** 方法帮助你做到这一点。它可以让您转换 numpy 数组中的数据帧。

df.to_numpy()


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/76c2831055a517d934ea347745c65829.png)

converted data frame into 2D array.

# **形容():**

这个 describe()函数显示了数据的快速统计摘要。

df.describe()


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/fb3e9bf4a6364c6ec18c88342eca83fd.png)

decribe()

正如您可能已经观察到的,我们的数据集中有七列,而它只显示了两列的统计数据,这是因为计算平均值、最小值、最大值和标准值等是没有意义的。对于字符串和日期时间等对象数据类型,这可能就是您所看到的。您应该可以看到整型和浮点型列的摘要信息。

# **sort_index():**

此方法带参数 ***axis=1*** 表示对列名进行排序,而***ascending = True***表示对行进行升序排序,即从小到大排序。看看下面给出的图片。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/6396014113cd41bcdc5b25c2173e4024.png)

除了按轴排序,我们还可以按值排序。正如你在下面的函数中看到的,我传递了我们想要排序的列名,即 ***【价格($)*** 和 ***升序=False*** 表示从较小到较大的列价格值。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/ad0ae7c58e4e7acad2e9a091d7abe4df.png)

# **选择单个列:**

如果您想从数据框中选择特定的列,您可以很容易地完成。您可以将数据框对象与脚本结合使用,并传递列的名称。正如您在给定图像中看到的,我从我们的数据框中选择了“car_name”列

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/781ff0f11dbdd6ee42849366ff69f2c2.png)

不使用脚本,我们可以用*()*我们的数据框对象上的操作符,即我的例子中的“df”。看看下面的图片。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/6e564b3841e89b7ef6769389db8ce2dd.png)

# **切片行:**

行切片根据起始和结束索引返回新的数据帧。看看下面的例子,我使用了旧的数据框对象,并传递了起始和结束索引来对行进行切片,新生成的数据框对象存储在 ***df2*** 中。当你打印 ***df2*** 的结果时,它会向你显示下面的数据表。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/43b6ec23ef448bc2dfe633bc20943dfa.png)

**注:**起始索引包含,结束索引不包含。

# **基于条件的结果:**

如果您想要在特定条件的基础上获得数据,那么您可以应用下面代码中解释的条件。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/e5daf41a05c6ca7eac5fa7080477c18d.png)

如上图所示,我们对我们的列***meter _ reading>46000***应用了 condition,这意味着它将返回所有大于 46000 行的行。

# **copy():**

pandas 的这个 ***copy()*** 函数非常简单,它用于复制整个数据帧并返回该数据帧的新引用。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/a5072bd779609da755f2cd3e61eae796.png)

在上图中可以看到,现在整个数据都在***copy _ df****中。*

# **在数据框中添加新列:**

我正在我的数据集中添加名为“current_price($)”的新列以及一些值。使用下面的代码添加新列。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/9ebc6438ac0569c00ce36c3d131b703b.png)

# **删除行:**

在下表中,我删除了那些包含 ***NaN*** *值的行。*如上图所示,总共有四行,其中两行有两个 ***NaN*** 值,因此这两行已从下表中删除。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/c038295d6be4a0bffc93882d9d4c710a.png)

# **填充 NaN 值:**

可以看到 ***NaN*** 的值已经填成了下表中的值 5。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/fec57fb1b3b787059ed748a9d6fd6f68.png)

**注:**您可以通过选择特定的列来填写 ***NaN*** 值。

# **概要:**

*   我们已经看到了如何读取 CSV 文件和打印其中的数据。
*   如何在数据集中添加新列,以及如何从数据集中删除不必要的列。
*   复制数据框。
*   删除 NaN 值并用适当的值替换它们。

如果您有任何疑问、建议或任何误导,请随时联系我。我乐于倾听。谢谢

从 Github 页面[这里](https://github.com/himanshujbd/pandas_lib_part_2)下载我的 Jupyter 笔记本和 CSV 文件。

我希望你喜欢读这篇文章,你也可以访问我的 [**网站**](http://thehimanshuverma.com/) ,在那里我会定期发布文章。

编码快乐!!!

[**订阅**](https://mailchi.mp/b08da935e5d9/himanshuverma) 我的邮件列表,直接在您的收件箱中提前获得我的文章,或者关注我自己在 Medium 上发表的文章[**The Code Monster**](https://medium.com/the-code-monster)**来完善您的技术知识。**

# **了解你的作者**

**希曼舒·维尔马毕业于印度勒克瑙的 APJ 阿卜杜勒·卡拉姆大学博士。他是 Android & IOS 开发人员、机器学习和数据科学学习者、金融顾问和博客作者。**

# 熊猫黑客:read_clipboard()

> 原文:<https://towardsdatascience.com/pandas-hacks-read-clipboard-94a05c031382?source=collection_archive---------23----------------------->

## 嗯,这不是一个黑客,但它节省了你很多时间。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/8c62e6c15aa5708288e3aa257a540ba0.png)

我们都有过这样的经历:我们在 Kaggle、StackOverflow 或者 Google 第二页的某个不知名的网站上读到一段有趣的数据(yikes!),它有足够的微光来激起我们的好奇心,引诱我们玩它,因为我们(酷的数据科学人)只是对他们甜蜜的数据见解感兴趣。我们准备好了我们的 Jupyter 笔记本,导入了我们最喜欢的 EDA 库,并准备好探索我们全新的数据集。

但是等等——我们犹豫了。我们意识到,我们必须经历下载数据、将数据保存到正确的文件夹,以及用正确的文件夹路径导入数据集的所有麻烦(哦,数据科学家的悲哀)!简单来说,没有人有那样的时间。嗯,我们有,但是如果我们对自己诚实,像这样的小障碍通常会让我们决定是否要做某事。幸运的是,有`pandas.read_clipboard()`来帮助我们。

## 例如

`pandas.read_clipboard()`方法听起来很简单:它读取复制粘贴的表格数据并将其解析到数据框中。例如,尝试在复制以下数据框后运行方法:

瞧啊。就这么简单。没有更多不必要的保存随机 csv 文件在您的计算机上。现在,您只需复制您的数据,并在几秒钟内开始挖掘!成为一名数据科学家是多么美好的时光。

## 还有几件事

在幕后,`pandas.read_clipboard()`方法将您复制的数据传递给`pandas.read_csv()`方法,这使得这个方法更加强大。这意味着您不必将自己局限于已经清理干净的数据。通过 read_csv 可以读取的内容,都可以通过 read_clipboard 读取。以下面这个 csv 文件为例,它来自于 [Kaggle 的 Titanic 数据集](https://www.kaggle.com/hesh97/titanicdataset-traincsv),并且去掉了文件头:

1,0,3,"Braund, Mr. Owen Harris",male,22,1,0,A/5 21171,7.25,,S
2,1,1,"Cumings, Mrs. John Bradley (Florence Briggs Thayer)",female,38,1,0,PC 17599,71.2833,C85,C
3,1,3,"Heikkinen, Miss. Laina",female,26,0,0,STON/O2. 3101282,7.925,,S
4,1,1,"Futrelle, Mrs. Jacques Heath (Lily May Peel)",female,35,1,0,113803,53.1,C123,S
5,0,3,"Allen, Mr. William Henry",male,35,0,0,373450,8.05,,S
6,0,3,"Moran, Mr. James",male,,0,0,330877,8.4583,,Q
7,0,1,"McCarthy, Mr. Timothy J",male,54,0,0,17463,51.8625,E46,S
8,0,3,"Palsson, Master. Gosta Leonard",male,2,3,1,349909,21.075,,S
9,1,3,"Johnson, Mrs. Oscar W (Elisabeth Vilhelmina Berg)",female,27,0,2,347742,11.1333,,S
10,1,2,"Nasser, Mrs. Nicholas (Adele Achem)",female,14,1,0,237736,30.0708,,C
11,1,3,"Sandstrom, Miss. Marguerite Rut",female,4,1,1,PP 9549,16.7,G6,S
12,1,1,"Bonnell, Miss. Elizabeth",female,58,0,0,113783,26.55,C103,S
13,0,3,"Saundercock, Mr. William Henry",male,20,0,0,A/5. 2151,8.05,,S
14,0,3,"Andersson, Mr. Anders Johan",male,39,1,5,347082,31.275,,S
15,0,3,"Vestrom, Miss. Hulda Amanda Adolfina",female,14,0,0,350406,7.8542,,S
16,1,2,"Hewlett, Mrs. (Mary D Kingcome) ",female,55,0,0,248706,16,,S
17,0,3,"Rice, Master. Eugene",male,2,4,1,382652,29.125,,Q
18,1,2,"Williams, Mr. Charles Eugene",male,,0,0,244373,13,,S
19,0,3,"Vander Planke, Mrs. Julius (Emelia Maria Vandemoortele)",female,31,1,0,345763,18,,S
20,1,3,"Masselmani, Mrs. Fatima",female,,0,0,2649,7.225,,C
21,0,2,"Fynney, Mr. Joseph J",male,35,0,0,239865,26,,S
22,1,2,"Beesley, Mr. Lawrence",male,34,0,0,248698,13,D56,S
23,1,3,"McGowan, Miss. Anna ""Annie""",female,15,0,0,330923,8.0292,,Q
24,1,1,"Sloper, Mr. William Thompson",male,28,0,0,113788,35.5,A6,S
25,0,3,"Palsson, Miss. Torborg Danira",female,8,3,1,349909,21.075,,S
26,1,3,"Asplund, Mrs. Carl Oscar (Selma Augusta Emilia Johansson)",female,38,1,5,347077,31.3875,,S
27,0,3,"Emir, Mr. Farred Chehab",male,,0,0,2631,7.225,,C
28,0,1,"Fortune, Mr. Charles Alexander",male,19,3,2,19950,263,C23 C25 C27,S


如果您复制并运行 read_clipboard,您会注意到第一行的数据将被用作标题。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/16d3d9a1741f7a9d371df0d2323b40f3.png)

First Row of Data is Used as Header

就像我们在使用 read_csv 时一样,我们可以将`header=None`和`names=col_names`关键字参数传递给 read_clipboard,以便修复问题并提供标题。复制上面的 csv 文件后,运行以下代码:

import pandas as pdcolumns = [
'PassengerId', 'Survived', 'Pclass', 'Name',
'Sex', 'Age', 'SibSp', 'Parch', 'Ticket', 'Fare',
'Cabin', 'Embarked',
]
pd.read_clipboard(header=None, names=columns)


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/fbbf5e0f45d83a38b47bb9f41b4cf1f2.png)

That’s Better

从上面的图片中可以看到,第一行不再用于标题,我们的标题现在被正确命名了。很好。

## 最后的想法

使用`pd.read_clipboard()`有一个警告:它不适用于运行在云上的笔记本电脑或 [WSL](https://scotch.io/bar-talk/trying-the-new-wsl-2-its-fast-windows-subsystem-for-linux) (二进制抽泣)。所以对于那些远程使用 Jupyter 笔记本的人来说,我很抱歉地说,你现在必须坚持使用 read_csv。

除此之外,这是一种快速获得数据并立即展开争论的有用方式。这对任何数据科学家来说都是一个很好的补充。

# 关于阿德里安·佩雷亚

*兼职数据科学家,兼职科技写手,全职书呆子。我在教授机器学习和可管理的、* ***字节*** *大小的程序中找到乐趣。是的,我也很搞笑。咖啡上瘾者。数据可视化的吸盘。愿意为下一个最好的树状图付出我的 1 和 0。*

*关注我上*[*Twitter*](https://twitter.com/adrianmarkperea)*和*[*LinkedIn*](https://www.linkedin.com/in/adrian-perea/)*。*

# 英超联赛中的熊猫

> 原文:<https://towardsdatascience.com/pandas-in-the-premier-league-78f1d0c21b4f?source=collection_archive---------5----------------------->

## 我们如何开始用熊猫进行数据分析

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/29c2be4b8f3e630b55ca8f2830f502cc.png)

Image Courtesy of Emilio Garcia via [Unsplash](https://unsplash.com/photos/AWdCgDDedH0)

这是几年来最激烈的英超联赛冠军争夺之一——只剩下几场比赛了,本赛季谁将获得荣誉?争夺冠军联赛席位的竞争也非常激烈。

考虑到这一点,我想我将展示我们如何使用 Python Pandas 库来解析英超联赛表,并展示我们如何开始使用 Python 执行一些初步的探索性分析。

# **网页抓取**

Pandas 有一个内置函数, **read_html()** ,它使用 lxml 和 Beautiful Soup 库从 html 文件中自动解析出数据作为 DataFrame 对象。首先,需要安装一些 **read_html()** 使用的附加库。在终端中,键入:

pip 安装 lxml

pip 安装 beautifulsoup4 html5lib

pandas **read_html** 函数有许多自定义选项,但是默认情况下,它会搜索并尝试解析包含在< table >标签中的所有表格数据。这将产生一个 DataFrame 对象列表。

我导入 pandas 库,并使用 **read_html** 函数解析英超联赛表,并将其赋给变量 prem_table。这将返回一个列表;其中第一个元素指向 2019 年 4 月 20 日英国夏令时 22:00 的英超积分榜。因为很多焦点都集中在争夺前 4 名的位置上,所以我决定使用**来可视化这个表中的前 6 个条目。**方法头()。为了进一步确认一切正常,我使用了 shape 属性,它告诉我有 21 行 12 列。这是一个有用的技术,因为 Python 从索引 0 开始计算行数,有 20 支英超球队,因此我似乎多了一行。因为在我的数据帧的开头看起来不错,所以问题*必须*指向数据帧末尾的任何额外的行。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/87e81aae3230a8f91b64ee0006bb3ed2.png)

由于任务是开始一些探索性的分析,我最初想“清理”数据。似乎没有必要在数据帧中列出“未命名:1”。要删除一列,我使用 drop 方法,并传入关键字参数 axis=1 进行按列的*删除。*

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/4839305f97519e94a73ca337567f2d62.png)

# **数据帧中的数据类型**

数据帧中的每一列都可以看作一个系列,其中每一列都必须是相同的类型。然而,每一行可以是不同的类型。由于这项任务涉及执行一些探索性分析,我需要破译每个系列是什么类型。简单地看一下表,我就会知道“Team”列是一个 Python 字符串。相当于 Python 字符串的熊猫是熊猫对象。此外,通过视觉观察,我预计表示游戏次数的“P”列是 Python float 或 int。然而,撇开假设不谈,最好使用 **dtypes** 属性或 **info** 方法来确认这一点。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/b74f3b58b698f1ac3da4943148183883.png)

这里的输出告诉我该系列的 dtypes 是“objects”,即 Python 字符串。为了在不同的列之间进行数值计算,必须改变这些类型。谢天谢地,这在 Python 中是一个简单的任务,我们只需使用熊猫 **to_numeric** 方法。 **pandas.to_numeric()** 是 pandas 中的一个通用函数,用于将参数转换为数字类型。在这里,我将我认为可能需要分析的列更改为 Pandas float (float64)数据类型。为了确认,我可以检查我的数据帧数据类型:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/cf80f1736c541c80ee2926b743926255.png)

# **清洁数据框**

形状属性早些时候告诉我,我有一个太多的列,当然假设 20 支球队仍然在英超联赛中竞争!当事情在我的数据帧的开头看起来很好的时候,问题一定存在于尾部。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/0f49138c508c83840ca3db8d96b1a3e8.png)

显然,我有一些不必要的元数据和一些填充列的 NaN(不是数字条目)。同样,这次我可以使用 drop 方法,但重要的是我省略了 axis=1 参数。在这种情况下,我想删除一行,而不是一列。现在情况看起来好多了。我可以使用 shape 属性验证成功删除的行。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/b139827d509105373923301d1d08283a.png)

虽然事情看起来有所改善,但球队的联赛排名栏标题为“无名:0”似乎很奇怪。它不代表该列的内容。为了改变这一点,我使用了**Pandas data frame . rename()**方法、并传递 **inplace=True** ,如果为 True,则在原始数据帧中进行更改。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/813d5aa2d60ee1872f497604b5fd1f62.png)

# **创建新列**

数据框现在已经设置好了。在这一点上,创建一些新的列并测试我之前创建的“字符串到浮点”转换是否有效可能是值得的!

我创建了一个名为“目标比率”的新栏目。这是用进球数除以失球数。要创建一个新列,我键入我的数据框架的名称,然后使用方括号符号,并在引号中输入我的*新*列标题。在等式的右边,我使用相同的技术从表数据框中选择我想要的列。这里,我将每一列“F”条目除以每一列“A”条目,并四舍五入到小数点后一位。默认情况下,创建的每个新列都追加到数据帧的末尾。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/0673fee5f98e8a53e166cf469877c844.png)

要对列进行重新排序,我只需更改列条目的顺序,将它们添加到一个列表中,并将其重新分配给表 Dataframe。“目标比率”栏现在更合适了。我还删除了“表格”一栏,使表格更整洁。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/7e1dc8b1ef26c403d48588d36c9b2daa.png)

# **过滤数据帧**

该表设置得很好,并且可以进行修改以供分析。让我们先问一个简单的问题。哪些球队比对手少打了一场?由于球队要么打了 34 场比赛,要么打了 35 场比赛,我只需过滤打了 34 场比赛的球队(截至 2019 年 4 月 20 日),结果就会出现。为了过滤,我使用布尔索引。要了解如何做到这一点,请阅读我的文章如何[‘如何通过列值过滤熊猫数据帧的行’。](/using-regular-expression-in-genetics-with-python-175e2b9395c2)

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/ac2a24ff5c3fa0caa2a2ef9dda08c1d0.png)

现在让我们来决定谁的听牌次数最多。

南安普顿试图避免本赛季的下降,所有这些平局都是昂贵的吗?

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/83e56ecd35176c8db3a25e5fa394e071.png)

最后,让我们创建两个新列,“进球/比赛”和“失球/比赛”,并使用 **sort_values** 方法对值进行排序。

由于哈德斯菲尔德和富勒姆已经受到谴责,卡迪夫的进球率、场均失球数和场均失球数排名第三。他们的净胜球也比最接近的保级对手布莱顿差。

卡迪夫的情况更糟,他们能挺过这次下跌吗?是他们的新兵没有足够的威胁,还是他们的防守太脆弱了?

有了 Python 的熊猫,我们就能一探究竟了!

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/164e984ca60336a9b0213f6feb5da54c.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/a2437b1bb1ff17f76bbe29b1ba7ee412.png)

# **结论**

本文展示了一些有助于使用 Pandas 进行入门分析的特性。我喜欢用熊猫来钻研英超联赛的统计数据。如果你想在 Instagram 上关注我以获得更多 Python 代码片段,请关注 exit_code_zero。

*最后*,一些建议。我正在解析这个表,同时游戏正在进行,结果正在到来。当我运行分析时,这给了我稍微不同的结果,这一开始让我很困惑!为了舒适的生活,不要进行分析,当游戏正在进行和结束时,把你的脚抬起来看游戏!

# 熊猫指数解释

> 原文:<https://towardsdatascience.com/pandas-index-explained-b131beaf6f7b?source=collection_archive---------0----------------------->

## 熊猫是数据科学家最好的朋友,索引是熊猫背后看不见的灵魂

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/b5485bf9b8b3bf6300a9d2cfc183bd8d.png)

index is like an address

在处理和理解我们的数据时,我们花了很多时间使用诸如 **loc、iloc、过滤、stack/unstack、concat、merge、pivot** 等方法,尤其是当我们处理一个新问题时。而这些方法都使用了指数,甚至我们面对的大部分**误差**都是指数误差。指数在**时间序列**数据中变得更加重要。可视化也需要很好的控制熊猫指数。

索引就像一个地址,这就是如何访问数据帧或数据系列中的任何数据点。行和列都有索引,行索引称为索引,列索引称为通用列名。

> **机器/深度学习**算法在预测精度方面有性能限制,就像它们的祖先统计模型一样,所以你如何获得显著更好的精度?为学习提供更好的数据。数据处理&特征工程是关键

熊猫有三种数据结构 **dataframe** ,**系列** & **面板**。我们主要使用数据框架和序列,它们都使用索引,这使得它们非常便于分析。

是时候退一步看看熊猫指数了。它让我们成为更好的数据科学家。

我们将使用 **UCI 机器学习成人数据集,**下面的****笔记本有下载数据的脚本。****

> ******业务** **问题**:分类(一个人收入 50k 以上或以下)**预测变量:**标签;预测因素:国家、年龄、教育、职业、婚姻状况等。****

****下面的笔记本非常简单,也有一些小技巧和窍门,可以让日常工作变得更好。****

adult = pd.read_csv("https://archive.ics.uci.edu/ml/machine- learning-databases/adult/adult.data", names = ['age','workclass','fnlwgt', 'education', 'education_num','marital_status','occupation','relationship','race','sex','capital_gain','capital_loss', 'hours_per_week', 'native_country','label'], index_col = False)print("Shape of data{}".format(adult.shape))adult.head()


****![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/1aa5d1f192c6465f8b32fef94b2cbc3f.png)****

****数据集有 32561 行和 15 个特征,最左边的系列 0,1 2,3 …是索引。让我们看看更多的信息。****

****![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/9662d2d57ee32f347f3f26b4cc09f56f.png)****

****成人有 rangeindex 32561 个条目,是一个从 0 到 32560 的整数序列。****

## ****选择方法****

1.  ****df.loc 用于标签/名称****
2.  ****df.iloc 用于位置编号****

> ****例如,假设 Ram、Sonu 和 Tony 分别站在位置 1、2 和 3。如果你想打电话给 Ram,你有两个选择,要么你叫他的名字,要么他的职位号码。因此,如果您用 Ram 的名字“Ram”来称呼他,您将使用 df.loc,如果我们用他的职位号“1”来称呼他,我们将使用 df.iloc。****

****在我们进一步了解**loc****&****iloc**之前,我们先从我们的数据中抽取一个样本做进一步的分析。我们采用熊猫 df.sample 方法对 10000 个观测值进行抽样。****

****![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/bbd7e2369b0fc38761eaa901f1468826.png)****

****不错,现在我们有了一个数据集名 df,最左边的数列是 3,4,6,8,11……奇怪!****

> ****这是因为行将携带它们的原始(旧地址)索引或来自成人数据集的索引名****

****命名我们的指数将有助于我们一开始,它的指数来自成人数据集。
查看行和列的索引****

****![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/ce2ffb8e7b0abd514f8ac9b63b18ffed.png)****

> ****行和列都有索引,索引的名称为' **index_adult******

****让我们讨论几个关于 **loc & iloc** 方法的例子****

****![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/b1a023e48a5d132a57c602ce838363eb.png)****

****error on df.loc method****

****在**的第一个例子**中。loc,它给了我们一个错误****

> ****因为我们用过。loc 方法和 df 没有名称为“2”的行,行索引对我们来说看起来像一个数字,但它们是名称/标签。锁定方法****
> 
> ****试着用 3 或 4 代替 2,会有效,因为有名字' 3 ',' 4 '作为**位置名******

****在**的第二个例子**中,我们尝试用。iloc,它是一种基于**位置编号-** 的方法****

> ****“年龄”是第一列,因此我们将使用它的位置 0****
> 
> ****在 df 的最后一行之前将有位置 0,1,2,3,所以 2 将是第三行****

****为了我们的进一步分析,让我们只保留几个有趣的变量****

****![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/abd15a9b33b48dcca02f8eb7c6cf2695.png)****

****有些时候,很难在索引中使用随机数,这时,重置该索引将使其成为一列,并重新创建另一个默认索引****

> ****` **reset_index** ()`将在我们每次对相同数据运行时重新创建索引列
> `**drop = True**` paramater 不会在 dataframe 中创建该列,请查看以下两个数据集之间的差异****

****![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/a7e212c0a5447b09b9ca8ee8f8a20fca.png)****

****` **inplace = Tru** e `省得我们再把它赋值给 data
我们没有使用` **drop = True** `,现在 df 应该把它的最后一个索引作为一个列放在里面了****

****![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/426a6e2c4b7493595f70d77cb8a955b1.png)****

> ****df 有另一栏 **index_adult** ,因为复位****

## ****过滤****

****过滤印度****

****![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/7e1ca490da3e7cf712cb7c3c50ca1291.png)****

****在重置我们的索引并对印度应用过滤器后,我们可以看到索引从 df 中保持自身,就像采样一样,现在行索引(4,312,637,902..)来自 df,index_adult 是这些行在成人中的索引****

****让我们来看看不同性别中收入超过 5 万英镑的人的观察结果****

****![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/0ddeb6b72f5bf0b6d177d28b7d1dfdbf.png)****

> ****即使这个数据帧也有一个索引,很难通过查看数据帧来识别,并且单个项目可以像****

****![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/23892c9857062bb26463a5fa5e451bcb.png)****

****为收入超过 50K 的人筛选 ind 数据集****

****![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/aeae9620286e7958c38a73d7ed1bf65e.png)****

> ****索引和它们的行是完整的,就像地址一样****

****非常令人印象深刻,这些人的收入真的很好,让我们试着了解他们的工作时间,因为我们在这个数据中没有“每周小时数”,我们将借助指数从*成年人*那里获得****

****![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/cebdb2ee6aef6829a7b2683b24fb2b29.png)****

> ****indexes 很容易带来更多的信息,上面的公式可以理解为过滤 ind_50 的地址 T27 上的成人['hours_per_week']****

****收入超过 5 万英镑的人每周平均工作时间****

****![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/c504e4c8a66f7a0b632310146cdf7133.png)****

****只需使用 index_adult,我们就可以轻松地获得另一个列的信息****

****索引使过滤变得非常容易,也给你在数据中向前和向后移动空间****

## ****这个索引在这个介绍练习中的最后一个用途****

****从数据中过滤出一个互补集,就像从整个数据集中训练和测试一样****

****我们将 ind 中不在 ind_50 中的那一部分进行切片,即收入低于 50k 的人****

****![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/1f48b9ff9689977bbd249ebea7e89c5e.png)****

> ****不错!在这个数据样本中,看起来收入在 50k 以上的人每周工作的时间更长****

****Jupyter nb 可以从这个 [Github-repo](https://github.com/manu007sharma/PandasAll) 下载。****

****只有当我们用多重索引和可视化来挖掘我们的数据时,熊猫索引的真正功能才能实现。访问我的下一个[练习](https://medium.com/@manusharma_66718/pandas-stack-unstack-pivot-table-crosstab-5cb9a16fe020)关于**栈/拆栈,透视表 _ 表&交叉表******

****感谢阅读。如果你喜欢这篇文章,你可能也会喜欢 [*熊猫支点&堆叠、*](https://medium.com/analytics-vidhya/pandas-stack-unstack-pivot-table-crosstab-5cb9a16fe020) [*缩放&变换时&*](/transformation-scaling-of-numeric-features-intuition-7f4436e8e074) *哪里*****

*   *****更多请关注我上的* [*中的*](https://medium.com/@manusharma_66718)****
*   *****我们连线上*[*Linkedin*](http://www.linkedin.com/in/data2datasciences/)****

# 熊猫。机器学习的系列方法

> 原文:<https://towardsdatascience.com/pandas-series-methods-for-machine-learning-fd83709368ff?source=collection_archive---------23----------------------->

## 了解它们及其实现

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/a94d6c62d8b6819b4e62188221c4f1b3.png)

Photo by [Fotis Fotopoulos](https://unsplash.com/@ffstop?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/programming-python?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)

> 声明:这篇文章不会让你成为`***Pandas.Series***`方面的专家。这本身就是一篇文章要涵盖的非常广泛的主题。为此,我会推荐你阅读一本书或`***Pandas***` 文档。但是,我可以告诉你的是,这篇文章将让你在学习机器的[旅程中起航。](/journey-into-data-mining-3b5ccfa5343)

在这篇文章中,我们将谈论`[Pandas.series](/pandas-series-a-part-of-the-backbone-for-machine-learning-in-python-c6a5003836c7)`中提供的一些方法,在使用它们时要记住什么,以及如何有效地使用它们。一个`Series`对象有许多对**数据分析**有用的属性和方法。一般来说,*方法*返回一个新的`Series`对象,但是大多数返回新实例的方法也有一个`inplace`或`copy`参数。这是因为`Pandas`中的默认行为倾向于**不变性**,并且这些可选参数分别默认为`False`和`True`。在本帖中,我们将使用下面的例子`Series`。

songs_66 = pd.Series([3, None , 11, 9],
index=['George', 'Ringo', 'John', 'Paul'],
name='Counts')songs_69 = pd.Series([18, 22, 7, 5],
index=[ 'John', 'Paul', 'George', 'Ringo'],
name='Counts')


> **输出**

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/a16bd593bc591ebd530deaa8a8501d02.png)

## 循环

→迭代 a `Series`迭代值:

for value in songs_66:
print(value)


> **输出**

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/b0bc755172344fb42e3df583e9c83fd0.png)

→有一个`.iteritems`方法循环遍历索引、值对:

for idx, value in songs_66.iteritems():
print(idx, value)


> **输出**

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/0aca2b2f81545c2d650ced3f69786ae6.png)

→还提供了一种`.keys`方法作为索引的快捷方式:

for idx in songs_66.keys():
print(idx)


> **输出**

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/07c420d3494ba780ffe2b398fc582747.png)

→不像 Python 字典的`.keys`方法,结果是有序的。

## 超载操作

以下列表包含系列对象的*重载*操作。对于 pandas 对象,这些操作以一种特殊的方式进行,可能不同于其他 Python 对象对这些操作的响应:

Operation, Result (All return Series) +, Adds scalar
-, Subtracts scalar
/, Divides scalar
//, Floor divides scalar
*, Multiply scalar
%, Modulus scalar
== / !=, Equality scalar
< / >, Greater / less than scalar
<= / >=, Greater / less than or equal scalar
^, Binary XOR
|, Binary OR
&, Binary AND


series 的常见算术运算被重载以处理标量和其他 series 对象。标量加法(假定序列中有数值)只是将标量值与序列值相加。给一个系列加一个标量叫做*播*:

songs_66 + 2


> **输出**

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/e8ec3fb325a6730b3971169bf097458b.png)

> 注意:广播是`NumPy`和`pandas`的功能。一个普通的`Python`列表支持前面表格中列出的一些操作,但是不像`NumPy`和`pandas`对象那样支持元素方式。当您将一个`Python`列表乘以 2 时,结果是一个元素重复的新列表,而不是每个元素乘以 2:

[1, 2, 3] * 2


> **输出**

[1, 2, 3, 1, 2, 3]


→当添加两个`Series`对象时,只有那些索引出现在两个`Series`中的项目才会被添加,否则`NaN`将被插入到仅在一个`Series`中找到的索引中。

songs_66 + songs_69


这里,“Ringo”在两者中都出现,但在`songs_66`中的值为`NaN`,因此结果也将是`NaN`。

> **输出**

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/23fcaa11277a4c576d0b22be63345f61.png)

→上面这个案例可能有点问题,应该是“Ringo songs”的计数未知。要解决这个问题,我们可以用`.fillna()`的方法将`NaN`替换为`0`,得到一个更合适更好的答案。

songs_66.fillna(0) + songs_69.fillna(0)


> **输出**

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/c6d73f8ae694add288280d7bab672456.png)

对于-、*和/,其他算术运算的行为类似。

## 获取和设置值

`series`对象允许通过索引操作(使用`[.loc](https://medium.com/swlh/indexing-best-practices-in-pandas-series-948ae3f44b08)`和`[.iloc](https://medium.com/swlh/indexing-best-practices-in-pandas-series-948ae3f44b08)`)和方便的方法访问值。获取和设置值的方法如下:

1.  `get(label, [default])` —如果找到,则返回一个标量(如果是重复索引,则返回`Series`),否则为默认值
2.  `get_value(label)` —返回一个标量(如果是重复的索引,则返回`Series`
3.  `set_value(label, value)` —返回一个插入(或更新)了标签和值的新`Series`

现在,让我们看看这些方法的实际应用:

songs_66['John']
songs_66.get('Fred', 'missing')
songs_66.get_value('John')
songs_66.John

dotted attribute access supported only for valid attribute names and no conflicts with pre-existing series attributes


> **输出**

11.0
missing
11.0
11.0


> 注意:有效的属性名是以字母开头,包含字母数字或下划线的名称。如果索引名包含空格,您不能使用带点的属性访问来读取它,但是索引访问可以很好地工作。

*如果找不到索引值,* `*.get_value()*` *方法会引发异常。*

Inserting or updating the values

songs_66['John'] = 82
songs_66['John']
songs_66.John = 81
songs_66['John']
songs_66.set_value('John', 80)

The set_value method updates the series in place and returns a series


> **输出**

82.0
81.0


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/dae3fcd438a600059719601e3696f4e5.png)

> 注意:如果您有非唯一索引,并且只想更新重复索引的一个值,则不能通过。设置值。在这种情况下,应该使用使用. iloc 的位置来执行更新。

## 重置索引

根据问题的上下文,更改索引的值可能是有用的。我们将了解一些重置索引、更改索引标签以及重命名索引标签的方法。第一个是`.reset_index`,它将把索引重置为从零开始单调递增的整数。默认情况下,`.reset_index`方法将返回一个新的`data frame`(不是一个`series`)。它将当前索引值移动到名为`index`的列中。

songs_66.reset_index()


> **输出**

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/0efb98c5dc1e6e91dfd6536fcac8a44f.png)

→为了获得一个`Series`输出,将`True`传递给`drop`参数,这将删除索引列。

songs_66.reset_index(drop=True)


> **输出**

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/974360bfdb3803980ca5022a257d37ad.png)

→如果需要特定的步进顺序,可将其传递给`.reindex`方法。新的索引值将具有可选参数`fill_value`的值(默认为 NaN)。

songs_66.reindex(['Billy', 'Eric', 'George', 'Yoko'])


> **输出**

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/856cee85b821ea17e4d9eb0df7768826.png)

→或者,可以用`.rename`方法更新索引值。该方法接受将索引标签映射到新标签的字典,或者接受标签并返回新标签的函数。

songs_66.rename({'Ringo':'Richard'})songs_66.rename(lambda x: x.lower())


> **输出**

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/b81a49c208f2d0dfd0fb3de545219df4.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/44927e5735d6fc4c9a21553e2a7455ad.png)

## 计数

这里我们将讨论如何获得在`Series`中找到的数据的概况。对于这一特定部分,我们将使用以下两个`series`。

songs_66 = pd.Series([3, None , 11, 9],
index=['George', 'Ringo', 'John', 'Paul'],
name='Counts')scores_2 = pd.Series([67.3, 100, 96.7, None, 100],
index=['Ringo', 'Paul', 'George', 'Peter', 'Billy'],
name='test2')


→ `**.count()**` 提供条目的计数,多少是唯一的,多少是重复的。此方法返回非空项的数量。在`scores_2`系列中,有 5 个条目,但`.count()`只返回 4 个。

scores_2.count()


> **输出**

4


→直方图表格在熊猫身上很容易生成。如果您认为一个序列是索引键到值的有序映射,`.value_counts`返回这些值到它们的计数的映射,按频率排序:

scores_2.value_counts()


> **输出**

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/75394db7b37f9e9a143c0157b77ae8d9.png)

→要获得非 NaN 项目的唯一值或计数,分别使用`.unique`和`.nunique`方法。请注意。unique 包含了 nan 值,但是`.nunique`不算。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/6891a655cdd42b7d45817880cccbf610.png)

→使用`.drop_duplicates`方法删除重复值。由于比利和保罗得分相同,他将被淘汰。

scores2.drop_duplicates()


> **输出**

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/4380645f5371c0263a53dea2bcffddf8.png)

→要检索一个带有布尔值的序列,表明其值是否重复,使用`.duplicated`方法。

scores_2.duplicated()


> **输出**

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/4ff844fedfbd685ba1d3917c1a6c923f.png)

→删除重复的索引条目需要更多的努力。让我们创建一个`series`,`scores_3`,它在索引中有两次‘Paul’。如果我们使用`.groupby` 方法,并按索引分组,那么我们可以从每个索引标签的值中取出第一个或最后一个项目。

scores_3 = pd.Series([67.3, 100, 96.7, None, 100, 79],
index=['Ringo', 'Paul', 'George', 'Peter', 'Billy','Paul'])scores_3.groupby(scores_3.index).first()
scores_3.groupby(scores_3.index).last()


> **输出**

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/b3cadfa47a55e6960f27181a102be0dd.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/196d3b44685daea33f1665113702bc5d.png)

## 统计数字

→在一个`series`对象的方法中有许多基本的统计度量。其中最基本的是`sum`中的一个`series`值:

songs_66.sum()


> **输出**

23.0


→大多数执行计算的方法忽略`NaN`。有些还提供了一个可选参数— `skipna` —来改变这种行为。但实际上如果不忽略`NaN`,结果就是`nan`。

songs_66.sum(skipna=False)


> **输出**

nan


→计算 a `Series`的`mean`、`median`和`quantile`。

songs_66.mean()
songs_66.median()
songs_66.quantile() # 50% value the default
songs_66.quantile(.1) # 10th percentile
songs_66.quantile(.9) # 90th percentile


> **输出**

7.666666666666667
9.0
9.0
4.2
10.6


→为了对`series`有一个好的总体感觉,`.describe`方法提供了大量的汇总统计数据,并将结果作为`series`返回。它包括值的`count`,它们的`mean`、`standard deviation`、`minimum`和`maximum`值,以及`25%`、`50%`、`75%`、`quantiles`。如果您愿意,可以通过 percentiles 参数传递特定的百分点。

songs_66.describe()
songs_66.describe(percentiles=[.05, .1, .2])


> **输出**

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/9a64ff56e12db6eb6a96c352bb5f3992.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/9644325366b20abb6e7169d87b6df81c.png)

→该系列还有寻找最小值和最大值的方法,`.min`和`.max`。有一些方法可以得到最小和最大索引标签的索引位置,`.idxmin`和`.idxmax.`

songs_66.min()
songs_66.max()
songs_66.idxmin()
songs_66.idxmax()


> **输出**

3.0
'George'
11.0
'John'


→ **方差**可通过`.var`找到,而**标准差**可通过`.std`找到。对于离差,**平均绝对偏差**可使用`.mad`找到。

songs_66.var()
songs_66.std()
songs_66.mad()


> **输出**

17.333333333333329
4.1633319989322652
3.1111111111111107


## 转换类型

`series`对象能够调整它的值。序列中的数值可以通过`.round`方法进行四舍五入。`.astype`方法试图将值转换成传入的类型。但是,如果对转换后的字符串值调用方法,结果可能不是期望的输出。在这种情况下,`.max`现在返回字典序的最大值。

songs_66.round()
songs_66.astype(str)
songs_66.astype(str).max()


> **输出**

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/dc6dd2a83260c200d6b45f91e3c21679.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/037efdd6854c8af23ad2ee1ffcf20901.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/fbeeb6bf898ead86c512551466593fbb.png)

默认情况下,`to_*`函数如果不能强制,将会产生一个错误。在下面的例子中,`to_numeric`函数不能将 nan 转换成浮点型。

pd.to_numeric(songs_66.apply(str))


> **输出**

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/fcd42b0f63c868b03bd4bdad25d1f29c.png)

## 不处理任何问题

计算中通常忽略`NaN`值。有时,用另一个值填充它们是有用的。在这种情况下,`.fillna`方法将用一个给定值-1 来替换它们。`NaN`可使用`.dropna`从系列中删除数值。

songs_66.fillna(-1)
songs_66.dropna()


> **输出**

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/07ba9da58c298d2904d88afaf3422dae.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/5d18d83ff70d09a72babac34f8efee46.png)

获取非 NaN 值的另一种方法是使用布尔掩码。`.notnull`方法给了我们布尔掩码。为了得到 NaN 值的掩码,我们可以使用`.isnull`方法。

val_mask = songs_66.notnull()
val_mask
songs_66[val_mask]nan_mask = songs_66.isnull()
nan_mask
songs_66[nan_mask]


> **输出**

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/70a1a77db3678df4983bc1e7ff71bff0.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/d9fe6659225971ea1484bf50f1bc8a6d.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/1546971760700339dc2bbff38cb65f4b.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/8ba22aae5c9de64a4f613ce414f84597.png)

> 注意:我们可以通过应用 not 运算符(~)来翻转布尔掩码。

val_mask = ~(nan_mask)


## 矩阵运算

通过`.dot`方法可以计算点积。但是,如果`NaN`是系列的一部分,这个方法就失败了。去掉南会给`.dot`一个值。一个系列也有一个`.transpose`(或者`.T`)的方法。

songs_66.dot(songs_69)
songs_66.dropna().dot(songs_66.dropna())
songs_66.T
songs_66.transpose()


> **输出**

nan
211.0


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/df520b9e2d53c452ec205a4b027b6aee.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/3decec55b00191a527c7ee5b8c4f18ee.png)

## **追加、组合和连接两个系列**

要将两个系列连接在一起,只需使用`.append`方法。这需要另一个`series`作为参数。默认情况下,此方法会创建重复的索引。但是,如果索引值重复,设置为`True`的可选参数`verify_integrity`会报错。

songs_66.append(songs_69)
songs_66.append(songs_69, verify_integrity=True)


> **输出**

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/ecff7dd241342fe5095c86d6a757db67.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/41f68f48d75330bc256c15fa1f24fa67.png)

若要对序列执行基于元素的运算,请使用。组合方法。它接受另一个级数和一个函数作为它的参数。

def avg(v1, v2):
return (v1 + v2) / 2.0songs_66.combine(songs_69, avg)


> **输出**

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/54f4df36b9dc27384ac0292521aacaf4.png)

要更新一个系列的值,使用`.update`方法。

songs_66.update(songs_69)
songs_66


> **输出**

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/1f252681e340782be059ff2de90d08b8.png)

`.repeat`方法简单地重复每一个项目一个期望的数量。

songs_69.repeat(2)


> **输出**

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/05deb94b3ea3939afc931c0b32c1418d.png)

## 整理

→ `.sort_values` —该方法返回一个按值排序的新的`Series`。该方法还支持翻转排序顺序的`ascending`参数。

songs_66.sort_values()
songs_66.sort_values(ascending=False)


> **输出**

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/05fd020fb721c82aa5916fb32d7927ca.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/91c11a8f5f89d97ee6f0a25b5f2a402c.png)

→类似的方法`.sort_index`可用于对`Series`的索引进行排序。它也提供类似的`ascending`参数。

→另一个有用的排序相关方法是`.rank`。该方法根据条目的值对索引进行排序。它为平局分配相等的权重。它还支持升序参数来反转顺序。

songs_66.rank()


> **输出**

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/86493e98426c3038a01fedbc0a476ad6.png)

## **应用功能**

要修改、清理、检查或对`Series`应用任意函数,我们可以使用将函数/字典/序列作为参数的`.map`,并像`Python`一样将其应用于`Series`的每个元素。

def format(x):
if x == 1:
template = '{} song'
else:
template = '{} songs'
return template.format(x)songs_66.map(format) # function as a parameterssongs_66.map({5: None,
18: 21,
22: 23})ongs_66.map({5: None,
18: 21,
22: 23}) # dictionary as a parametermapping = pd.Series({22.: 33})
songs_66.map(mapping) # series as a parameter


> **输出**

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/8115d35120e931638af443f1269244ba.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/1485b5323521746da58f7b7a035738c3.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/264477e224358250ceb50e00b0dc5f57.png)

> 注意:series 对象上还有一个`.apply`方法。它的行为与`.map`非常相似,但它只适用于**函数(不适用于序列或字典)。**

## 字符串操作

具有字符串数据的系列可以通过*矢量化字符串操作*进行操作。要调用字符串操作,只需在序列的`.str`属性上调用它们。

names = pd.Series(['George', 'John', 'Paul'])
names.str.lower()
names.str.findall('o')


> **输出**

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/081a3f8e35f7d05883181a5548894094.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/79b8682269c6d4ec4fe9fa9e9d3ea150.png)

以下是可用的矢量化字符串方法,熟悉原生 Python 字符串方法的任何人都应该熟悉这些方法。

Method, Result contains, pattern matching boolean result
count, pattern occurrence count result
decode, decode a codec encoding
encode, encode a codec encoding
startswith, pattern matching for string start with boolean result
endswith, pattern matching for string end with boolean result
findall, find pattern in string
get, attribute access on items
join, join items with a separator into a string
len, total size of items
lower, convert items to lowercase
upper, convert items to uppercase
lstrip, removes whitespaces to the left of items
rstrip, removes whitespaces to the right of items
strip, removes whitespaces to both sides of items
repeat, repeat the string a certain number of times
replace, change/replace a particular part of string
slice, pull slices of string
split, split items by pattern
title, titlecase the items


我将免费赠送一本关于一致性的电子书。在这里获得你的免费电子书。

感谢阅读。我希望你喜欢这篇文章,并学到一些新东西。我知道这些不是图书馆提供的所有`Pandas.Series`方法,但它们是一个很好的起点。继续学习!

如果你喜欢阅读这样的故事,并想支持我成为一名作家,可以考虑[注册成为一名媒体会员](https://tarun-gupta.medium.com/membership)。每月 5 美元,你可以无限制地阅读媒体上的故事。如果你注册使用我的链接,我会赚一小笔佣金,不需要你额外付费。

[](https://tarun-gupta.medium.com/membership) [## 加入我的推荐链接-塔伦古普塔

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

tarun-gupta.medium.com](https://tarun-gupta.medium.com/membership) 

要阅读更多文章,请访问此处:

 [## 标记故事列表的快速链接—感谢您的访问

### 我也有一份以快节奏出版为目标的出版物。读书成为作家。

tarun-gupta.medium.com](https://tarun-gupta.medium.com/thank-you-for-visiting-my-profile-9f708062c75e)

# 熊猫小贴士:需要速度

> 原文:<https://towardsdatascience.com/pandas-tips-tricks-need-for-speed-54e217cc6aa0?source=collection_archive---------22----------------------->

## 像 PYTHON 专家一样进行数据分析

## 个人最喜欢的一句俏皮话

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/e425f594133d23ce0f32af67b98b931a.png)

Source: [Unsplash](https://unsplash.com/photos/dast7B6U2Aw).

# 概观

[我的上一篇文章](/demo-for-rfiw-2020-task-1-kinship-verification-8a8ed7081bcc)展示了一个评估一组人脸对以确定这两个人是否有血缘关系的简单过程。几个片段像*黑盒*一样被轻轻带过。让我们来看看其中的一个片段,一个简单的*单命令行程序*:我最近学习的 Python [熊猫](https://pandas.pydata.org/)特性,现在经常使用。

DataFrame 包含面对 *p1* 和 *p2* ( **图 1** )和特征(type **dict** )的列表,文件名作为关键字,面编码作为值。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/1cdf080c6e67c86d068cfffb5d986516.png)

***Fig. 1.***df_pairlist.[*head*](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.head.html)*(5): top 5 of >100,000 rows. Notice samples are repeated, but pairs are unique (i.e., member 1 of family 7 is the bother of member 9 of family 7, each with various face samples paired. Specifically,* [*N*choose*(2*](https://www.mathsisfun.com/data/binomial-distribution.html)*) face pairs, where N is the total number of faces of the two relatives).*

原来你在这里!在短短一行代码中,我们对数百万对进行了评分,而没有考虑内存或速度问题,同时为配对创建了一个分数列,作为同一个[数据帧](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html)的一部分。

# 那又怎样?谁在乎呢。

在我们认识到这一点之前,让我们确保我们看到了问题。

首先,读取上面描述的数据结构。

Load lists of pairs and features for each face present in the list

请注意,有> 100,000 对,但有~10,000 个面:面以肯定、唯一和错误对的形式重复。

如何衡量所有配对的相似性(即每行计算一个分数)?

**胸围#1。一个人可以循环,这是使用熊猫或 [NumPy](https://numpy.org/) 的最不理想的方式之一。举个例子,**

60.61587691307068 seconds


这太慢了。太慢了!!!

我们没有充分利用 pandas 的优势,甚至没有充分利用 NumPy 的矢量化能力。点击了解更多[。](https://realpython.com/numpy-array-programming/)

那么我们还能做什么呢?

**胸围#2。我们可以将整个矩阵读入内存,但这不仅是多余的,因为通常有数百万对,每个元素是一个大小为 512(即 512 x 8 字节)的向量。因此, *I/O* 开销将会很慢,内存使用将不是最佳的,并且在大多数情况下,内存量不足。**

**解决方案。**我们可以将[字典对象的键](https://www.w3schools.com/python/python_dictionaries.asp)映射到一个面孔列表。然后,[对每一行应用](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.apply.html)一个度量(即面 *A* 和面 *B* ,或者列 A 和 B)。因此,每一行都有各自配对的分数。

**因此,Python Pandas 提供了一个奇妙的解决方案。**

A 1 liner: map features from a list of strings as keys to a dictionary pointing to the feature vector and following a functional programming paradigm for optimal performance.

这里我们指定 *axis=1,*意味着跨列应用(即,逐行)。

3.53662109375 seconds


**几乎不费吹灰之力就实现了近 18 倍的速度提升!**请注意,加速比只会随着样本量的增加而增加。这里,只有 [FIW](https://web.northeastern.edu/smilelab/fiw/) 的一个子集用于演示目的。

这个有效的技巧可以推广到许多基于 ML 的问题中遇到的情况。

## 动机(又名 Spiel)

为了使一篇博客的长度与前一篇文章提供的信息量相匹配,一些值得强调的内容被跳过或略过。拉胡尔·阿加瓦尔对 ROC 曲线做了一个聪明的评论,这让我恍然大悟——没有提供分析或定义,只有实现。因此,我相应地进行了更新(参见 ROC 上的[部分)。然后,其他部分似乎值得额外的解释。这激发了我在这篇文章中最喜欢的一行代码上写这篇博客:一个狭窄的主题,一个快速的博客。](/demo-for-rfiw-2020-task-1-kinship-verification-8a8ed7081bcc#4d14)

作为一个新的博客作者,我计划继续学习、适应和提高。此外,我写信给的是你。因此,你的意见、回答和问题对我的这个新爱好来说是很有价值的。请分享任何积极和消极的想法。提问。提出改进建议,甚至提出自己的想法!

总而言之,我希望你喜欢它。敬请关注更多博客!

# 相关博客

*   Sofia Heisler ,[优化熊猫代码速度的初学者指南](https://engineering.upside.com/a-beginners-guide-to-optimizing-pandas-code-for-speed-c09ef2c6a4d6)
*   [Robbert van der Gugten](https://medium.com/u/ffd7e98955c4?source=post_page-----54e217cc6aa0--------------------------------) , [高级熊猫:优化速度和内存](https://medium.com/bigdatarepublic/advanced-pandas-optimize-speed-and-memory-a654b53be6c2)
*   [塞尔瓦拉塔姆·拉维南](https://medium.com/u/b7def7a159d6?source=post_page-----54e217cc6aa0--------------------------------),[了解使用熊猫时的优化需求](/understanding-the-need-for-optimization-when-using-pandas-8ce23b83330c)

# 学习 Python 中两个最常用的熊猫数据结构

> 原文:<https://towardsdatascience.com/pandas-tutorials-a-complete-pandas-guide-i-c392ded87367?source=collection_archive---------19----------------------->

Pandas 是由 Wes McKinney 开发的高级数据操作工具。它建立在 Numpy 包之上,意味着 Pandas 需要 Numpy 来运行,它的关键数据结构被称为 DataFrame。数据帧允许您存储和操作观察行和变量列中的表格数据。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/c681c043a63be95c6a5e345333607d49.png)

image by E[dureka](https://www.edureka.co/blog/python-pandas-tutorial/)

如果你已经知道熊猫,系列和数据框,那么你可以跳过这个博客,可以从[这里](https://medium.com/@himanshusoni501/pandas-guide-with-python-example-ii-basic-pandas-operations-4cf9704fd062)跟随它的第二部分。

# **熊猫装置**

要安装熊猫,只需在您的终端上键入以下命令。您可以使用以下方法之一安装 pandas。

conda

conda install pandas# or PyPI
pip install pandas


# **为什么用熊猫?**

数据科学家使用熊猫有以下优势:

*   轻松处理缺失数据
*   一维数据结构使用**系列**,多维数据结构使用**数据帧**
*   它提供了一种有效的数据切片方法
*   它提供了一种灵活的方式来合并、连接或整形数据

# **系列**

序列是一维(1-D)数据结构,可以有任何数据结构,如整数、浮点和字符串等。当你想执行任何种类的计算或返回一维数组时,这是很有用的。一个系列不能有多列。

在上面显示的代码片段中,数据可以是:-

*   标量值可以是整数、浮点和字符串等类型。
*   字典可以有键和值对形式的数据
*   Ndarray 可以有 n 维数组

我们将逐一探讨上述每一个问题。我们将使用 Jupyter Notebook 运行我们的 python 代码,如果您还没有安装,请点击[此处](https://jupyter.org/install)进行安装

**使用 python 列表的系列:**以下代码片段使用 python 列表创建整数类型的系列。

当您运行上面的代码时,它将产生以下输出

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/b00956398d889c47dc764f42a12f7612.png)

**注**:索引默认从 0,1,2,…(n-1)开始,其中 n 为数据长度。

**系列使用 python 字典:**

上面的代码片段产生以下输出。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/599bf34775dd0edce9deb7349c85c359.png)

**系列使用 Ndarray:**

上面的程序产生如下输出。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/053ba091a3e7f05305c71a72d56a26a6.png)

# **数据帧**

数据帧是以行和列的形式存储数据的多维数组。数据帧是存储数据的标准方式。下图显示了如何使用 python 字典创建数据框。

上面代码的输出如下所示。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/5746a4723f2f72a2b4918a9bfc17fd35.png)

# **总结**

*   Pandas 是一个处理和分析数据的开源库。
*   Pandas 非常容易处理缺失值,并且它为我们提供了一种有效的数据切片方法。
*   Series 是一维数组,能够保存任何类型的值。
*   DataFrame 是以表格形式存储值的多维数组。

我希望你喜欢读这篇文章,你也可以访问我的 [**网站**](http://thehimanshuverma.com/) ,在那里我会定期发布文章。

如果你想给我任何建议,那么我很乐意听听你们的意见。永远欢迎你。

编码快乐!!!

[**订阅**](https://mailchi.mp/b08da935e5d9/himanshuverma) 我的邮件列表,直接在您的收件箱中提前获得我的文章,或者关注我自己在 Medium 上发表的文章[**【The Code Monster**](https://medium.com/the-code-monster)**】,以完善您的技术知识。**

# **了解你的作者**

**希曼舒·维尔马毕业于印度勒克瑙的 APJ 阿卜杜勒·卡拉姆大学博士。他是 Android & IOS 开发人员、机器学习和数据科学学习者、金融顾问和博客作者。**

# 用 UPSNet 进行全景分割

> 原文:<https://towardsdatascience.com/panoptic-segmentation-with-upsnet-12ecd871b2a3?source=collection_archive---------17----------------------->

## 结合语义和实例分割的完整场景理解

计算机视觉社区已经提出了一个称为全景分割的新任务。全景分割要求一个场景不仅在语义上被分解,而且要求一个类的每个实例,比如一辆车或一个人,被唯一地标记。它需要一种算法来理解像天空和地面这样的无形的东西和像汽车和人这样的可计数的 T2 事物之间的区别。介绍该任务的论文中的以下图片清楚地显示了不同任务之间的差异:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/4d1b0ec2f856958b0b5aa0b7cb77d739.png)

虽然以前的方法侧重于使用启发式方法来组合输出以产生全景分割,但优步研究公司提出了一种统一的端到端可训练架构,称为 UPSNet,它利用语义和实例分割任务之间的互补性来提高准确性和性能。

架构使用与 [Mask R-CNN](https://arxiv.org/abs/1703.06870) (与 FPN 的 ResNet)相同的主干。在这个主干之上,有两个平行且独立的头部:语义头部和实例头部。最后,这两个头的输出进入另一个头,称为全景头。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/29e415fa7f965dd0d052641d6a10254f.png)

实例头与 Mask-RCNN 中使用的实例头相同。虽然语义头是显着的使用可变形卷积,全景头是本文的主要贡献。全景头负责通过处理语义和实例结果来产生最终输出。它完全没有参数,因此不需要培训。这里发生的事情是,如果有像素没有实例输出,那么语义头的输出直接被这些像素接受。对于既有实例标签又有语义标签的像素,softmax 用于确定它是否应该被标记为该实例或语义类。

此外,作者还为“未知”类构建逻辑,以避免做出错误的预测。这背后的基本原理是,对于任何像素,如果来自语义头的“thing”类的 logit 的最大值大于来自实例头的 logit 的最大值(下图中的 max(X thing)- max(X stuff)),那么我们很可能遗漏了一些实例。因此,这些像素必须标记为未知。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/8732950be3669fb6be33fcfb65d69002.png)

这是本文的主旨。这是一个相当简单的想法,但结果是惊人的,我已经在生产中使用它们。我强烈推荐您尝试一下资源库[https://github.com/uber-research/UPSNet](https://github.com/uber-research/UPSNet),我将留给您这篇论文的以下结果:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/7b3851d887c3d0fb7b4bab702cfa99f5.png)

参考:
[UPSNet:一个统一的全景分割网络——余文雄,廖,赵恒双,,,尔辛尤默,拉克尔乌尔塔逊](https://arxiv.org/abs/1901.03784)

# [论文分析] —规范等变卷积网络和二十面体 CNN

> 原文:<https://towardsdatascience.com/paper-readthrough-gauge-equivariant-convolutional-networks-and-the-icosahedral-cnn-13e9d3d95b85?source=collection_archive---------8----------------------->

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/c071d677cdf57a8d13b034a4b726d826.png)

Photo by [Kevin Crosby](https://unsplash.com/@kfcrosby?utm_source=medium&utm_medium=referral) on [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral)

# 概观

在这篇文章中,我将尝试总结这篇与几何深度学习相关的非常有趣的论文

原始文件

 [## 规范等变卷积网络和二十面体 CNN

### 对称变换的等方差原理使神经网络的理论基础方法成为可能。

arxiv.org](https://arxiv.org/abs/1902.04615) 

注意:在这个总结中,我已经最小化了对数学符号的使用(也因为 Medium 不是数学友好的),所以如果你想更深入地了解形式主义,请参考 GitHub 版本(顺便说一下,GitHub 本身并不渲染数学,但至少你可以使用 Chrome 插件,如[Tex All Things](https://chrome.google.com/webstore/detail/tex-all-the-things/cbimabofgmfdkicghcadidpemeenbffn)

[](https://github.com/NicolaBernini/PapersAnalysis/tree/master/Geometric_Deep_Learning/CNN/Gauge_Equivariant_Convolutional_Networks_and_the_Icosahedral_CNN) [## 尼古拉·贝尔尼尼/论文分析

### 相关论文的分析、总结、备忘单- NicolaBernini/PapersAnalysis

github.com](https://github.com/NicolaBernini/PapersAnalysis/tree/master/Geometric_Deep_Learning/CNN/Gauge_Equivariant_Convolutional_Networks_and_the_Icosahedral_CNN) 

# 介绍

**卷积滤波器**是从域到共域的滤波器映射

在 CNN 的上下文中,

*   该滤波器基于卷积运算
*   结构域和共结构域都被称为**特征图谱**

**等方差**是关于滤波器及其应用领域的属性

*   当一个变换被应用于滤波器域并且它完全反映在滤波器输出上时,那么该滤波器被称为相对于该变换是等变的

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/5f895cafc4b61f21c1c644d5943e491a.png)

Equivariance means the transformation propagates through the filter

*   如果该变换被滤波器完全吸收,使得在滤波器输出中没有其应用的痕迹,则该滤波器被称为相对于该变换是不变的

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/65920dbc09fb69c330406fe833008317.png)

Invariance means the transformation gets abosrbed by the filter

**对称性**确定一组与特定空间相关的全局变换(它们不依赖于任何过滤器),这些变换在不改变空间结构的情况下映射空间本身:它们依赖于特定空间的几何形状。

与作用于图像或更一般的平面特征地图的经典 CNN 层相关的基本思想是

*   为了能够使**过滤器在平面上滑动,特征属于**

或者等同地

*   在**下方滑动飞机**

因此,在用卷积滤波器一次又一次地处理它之前,更正式地使用**平面对称**(取决于它的几何形状)之一来转换平面本身

将这一过程推广到一般空间,我们希望

1.  一些以同样方式工作的东西,因此改变了空间本身以进行连续的处理
2.  卷积滤波器应该**可以独立地学习它在平面**上的特定位置(这通常被称为权重共享,它使得 CNN 处理位置独立)

就**空间推广**而言,让我们考虑流形 M,一个与欧几里得空间局部同胚的空间

使用流形的主要挑战是它们**不保证具有全局对称性**,但是它们具有**局部规范变换**:本文的目标是设计卷积滤波器,其目的不是与任何全局对称性等变(因为在这种情况下不可能假设它们存在),而是与局部规范变换等变。

这是关键,因为

*   **我们最终想要获得的**是一个能够共享权重的**卷积滤波器,这意味着独立于输入特征图上的特定位置学习权重**
*   **如何**使其**等同于过滤器应用于输入空间中任意点的方式**
*   在存在全局对称的情况下,到达空间中任意点以应用滤波器的工具是通过输入空间的**全局对称变换**,例如在平面的情况下,这是移位操作
    理解这种“滑动”操作不能对学习产生影响是关键(否则学习的结果将取决于具体的操作细节),这种操作仅允许**权重共享**。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/f33133cb0e843913dcdf56351c94e79c.png)

因此,如果算子(例如卷积)在设计上与这种变换是等变的,那么它可以通过共享权重来学习,因为在学习过程中,滤波器通过对称变换应用于空间中的任何点,并且它不影响学习到的权重(事实上,在平面上的经典 CNN 中,卷积算子在平面上滑动的具体方式是不相关的)。

该论文中提出的挑战不是假设全局对称,而只是局部规范并研究相关的变换,以便设计能够通过权重共享来学习的卷积算子。

在缺乏整体对称性的情况下,我们遇到的第一个问题是如何到达空间中的任何一点(这是一个必需的特征)。一个可能的解决方案是[并行传输](https://en.wikipedia.org/wiki/Parallel_transport) rt,但是**并行传输实际上是路径相关的**。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/b110fb8b4516be104d03f30b636a1129.png)

From the paper

不用说,路径是完全任意的,事实上它定义了被称为**标尺**的**局部切线框架**,这意味着一个简单的过滤器会将这个任意的标尺选择传播到它的结果,影响学习。好的

因此,我们想要的是一个滤波器,它对于这个不可避免的任意局部规范选择是不变的,源于并行传输,使得输出特征图不受在输入特征图中选择的局部规范的影响。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/bc81ab7d878ed09655818e1a04209a50.png)

# 细节

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/d71041a273573b3824b2e80637faad46.png)

然后让我们介绍一下**规范**,它是流形切线空间和欧几里德空间之间的一个**位置相关的可逆局部线性映射**

因此,一个量规也在(映射欧几里得参考系)中定义了一个局部参考系

**量规变换**是局部框架的**位置相关可逆变化**

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/c715311015c9587b1b468ed11e3cbda8.png)

因此,潜在的想法是建立一个具有这种特性的过滤器,这取决于它必须处理的特定流形

# “用于无重影高动态范围成像的注意力引导网络”(CVPR,2019)——论文综述

> 原文:<https://towardsdatascience.com/paper-review-attention-guided-network-for-ghost-free-high-dynamic-range-imaging-4df2ec378e8?source=collection_archive---------19----------------------->

## HDR 重建的最新进展

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/ca93a6badc7cc9435fabb9e1ba4c43ba.png)

Source: [Attention-guided Network for Ghost-free High Dynamic Range Imaging (AHDRNet)](https://donggong1.github.io/ahdr)

> *“你只是想要关注,你不想要我的心”——查理·普斯*

# 关于报纸

*用于无重影高动态范围成像的注意力引导网络* (AHDRNet)是目前 HDR 使用包围曝光图像生成图像的最先进技术。它出现在 2019 年 CVPR,可以在这里阅读。第一作者,[董公](https://donggong1.github.io/)是阿德莱德大学的博士后研究员。他的兴趣包括机器学习和计算机视觉中的优化。

> ***注*** *:本帖使用的图片结果、网络表示、公式、表格均来源于* [*论文*](https://arxiv.org/abs/1904.10293) *。*

在我们开始之前,我建议你看看我播客中的一个片段,我们在这里讨论了计算摄影和 HDR 成像的现状。

# 埃尔问题 a

为了从多重曝光包围的 LDR 图像生成 HDR 图像,LDR 图像的对准对于具有帧内运动的动态场景非常重要。合并前未考虑未对准,导致重影(以及其他)伪像。已经有几次成功的(几乎)尝试通过使用光流估计来补偿帧之间的这种运动。事实证明,基于流量的方法的缺点并没有很好地服务于 HDR 事业。

这可以从[卡兰塔里等人的一次尝试中看出。al](https://cseweb.ucsd.edu/~viscomp/projects/SIG17HDR/) ,其中不考虑饱和图像区域中的精确空间重建,对于具有严重运动的输入帧,可以观察到对准伪像。这可以从 AHDRNet 的作者在下图中提供的结果中看出。专门针对高度动态的的重建的另一个尝试包括输入( [Wu et .al](https://arxiv.org/pdf/1711.08937.pdf) )声称利用 CNN 架构在学习失调和补偿鬼影伪像方面的明显实力。然而,以下结果表明仍有改进的余地。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/328614e70d72aa3c68221d757d6eb269.png)

# 注意营救

作者建议使用注意机制来解决这一双面问题,即通过使用注意机制来减少对准伪影+精确的 HDR 重建。如果你想一想,注意力网络只是堆叠在一起的几个 Conv 层,然后(通常)是一个 sigmoid 激活,允许网络专注于重要的和相关的应用程序。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/5c6de98616da23976cf9159e096ade11.png)

这里,注意力网络被用于抑制对准伪影,并且通过关注括号中的图像相对于参考图像的空间动态,集中于将曝光更好的图像区域注入到生成的图像中。对应于参考图像的区域被突出显示,而具有严重运动和饱和度的区域被抑制。我们将会看到注意力信息矩阵是如何被处理和实现的,就其背后的数学而言。

网络的注意力部分集中于决定哪些图像区域对网络输出的准确性有更好的贡献。接下来是一个基于注意力输出的合并网络,试图从 LDR 输入中创建 HDR 内容。注意力机制越好,对合并网络的输入就越好,从而允许它利用输入的更相关部分中的信息。使用扩展的密集残差块开发了合并网络,这改进了梯度流、分层学习和收敛。整个网络以端到端的方式被训练,因此两个子网络相互影响,并且一起学习。

# 履行

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/9cee8c3282006fe61c38d24a39021d6f.png)

Overview

## 预处理

非线性 LDR 输入( *I1,I2,I3* )通过应用逆 CRF(这里是伽马校正)并除以它们相应的曝光时间而被转移到线性域。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/2649360f8252ae059e07f2c654543885.png)

γ = 2.2

线性和非线性输入( *Ii,Hi* )沿着信道维度被连接以形成 *Xi* 。 *X1* 、 *X2* 和 *X3* 馈入网络产生相应的 HDR 输出。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/412cfae9d4695097046f23ae0d304f5a.png)

*H* is the generated image, *f* (.) represents the AHDRNet network and *θ* the network parameters

当网络拥有可供其支配的线性化输入信息时,它表现得更好。这已在 [Kalantari 等人的研究中得到观察和利用。艾尔](https://cseweb.ucsd.edu/~viscomp/projects/SIG17HDR/)以及[吴等人。艾尔](https://arxiv.org/pdf/1711.08937.pdf)。

# 体系结构

整个网络由两个子网络组成——注意网络和融合网络。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/71500cb9d630e0d21a9cdb17d1fa246f.png)

Attention network

如上所述,注意力网络通过突出显示和使用来自与参考图像相对应的相邻图像(非参考图像)中的区域的信息,有助于避免对准伪影。它通过以下方式实现。

注意力不是从连接的图像对中提取的,而是直接应用于连接的图像对。首先将 *Xi* 通过 Conv 层提取 64 通道特征图*子*。

然后,参考特征图( *Z2* 或 *Zr* )连同相邻图像特征图( *Z1* 和 *Z3* )被馈送到关注模块,该关注模块参照 *Zr* 生成关注图来标记非参考特征图中的重要区域。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/d1aff2e9a3d33443899f9a91c6a5d51c.png)

这是对两对( *Z1* 、 *Z2* )和( *Z3* 、 *Z2* )进行的。这在上面的网络表示中可以看得很清楚。

在我们进入注意力模块做什么之前,让我们看看如何处理生成的注意力地图。生成的注意力图本质上是一个包含[0,1]之间的值的 64 通道矩阵。该矩阵用作一种权重矩阵,其中每个元素表示相邻图像的特征矩阵中相应元素的重要性,参考 *Z2* 。这是通过使用从( *Z1* , *Z2* )生成的注意力图,通过进行注意力图和 *Z1* 的逐元素乘法来获得*Z’1*来实现的。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/5bae0c20c2fbdf375fb9ca6e4e35d889.png)

该操作导致 *Z1* 中的重要特征(关注度更接近 1)获得较高的数值,而不太重要的特征获得相应的较低值。这仅表现在来自 *Z1* 的重要图像区域,其在网络中前进以对最终的 HDR 输出做出贡献。同样的事情发生在( *Z3* , *Z2* )之间得到*Z’3*。

现在我们有了所有与构建 HDR 图像最相关的输入片段,我们沿着通道维度将它们连接起来,如下所示

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/2c1d3176216bde1e7346788ab1023800.png)

## 注意模块

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/03f62c739dd1a04c404a4f33743eb94c.png)

我们来看看这些注意力地图是如何产生的。本文中使用的注意模块由 2 个 Conv2d 层组成,输出 64 通道矩阵,之后分别是 ReLU 和 sigmoid 激活。它将相邻和参考图像(2×3 = 6 个通道)的连接特征向量作为输入。最终,sigmoid 激活用于将输出包含在[0,1]范围内。

## 关注结果

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/473cbc13c7c0f5559f5dfd6f4e8d3df8.png)

Attention map examples from the paper. ( a ) to ( c )— Alignment attention; ( d ) to ( f ) — Exposure attention

在(a)至(c)中,从上述结果可以观察到,非参考图像中具有运动差异的区域是如何被抑制的(深蓝色区域),而与参考图像具有对应关系的区域被突出显示(较亮的蓝绿色)。在(d)到(f)中,在相邻帧中曝光较好的区域被突出显示,而饱和区域被抑制。

# 合并网络

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/4d906d766f61b8cf7ac66b0bcdac4116.png)

级联的特征图( *Zs* )作为输入被提供给合并网络。作者所用的归并网络是张等人提出的剩余稠密网络。艾尔。代替传统的 Conv 操作,作者使用了扩张卷积来传播更大的感受野,因此称之为扩张残余致密块(DRDB)。在合并网络中有 3 个这样的块,它们由基于密集级联的跳跃连接和剩余连接组成,已经证明它们对于 CNN 在解决梯度消失方面非常有效,允许更好的反向传播、分级学习,并因此帮助和改善收敛性能。在建议的 AHDRNet 网络中,每个 DRDB 包括 6 个 Conv 层,增长率为 32。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/c237f33a7c7d24e6193629b67b2625e6.png)

DRDB

作者还采用了局部和全局剩余跳跃连接,将低级特征旁路到高级特征。局部残差学习在 DRDBs 内实现,而全局残差学习用于将包含*纯*信息的浅层特征图从参考图像转移到后面的阶段。这一点以及其他网络规格可以在合并网络图中观察到。

# 损失函数

就像[卡兰塔里 et 一样。al](https://cseweb.ucsd.edu/~viscomp/projects/SIG17HDR/) ,在 *μ* 定律色调映射生成的图像和色调映射的地面真实图像之间计算损失。所有实验的 *μ* 都被设置为 5000。 *μ* 定律可以定义为

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/314bcbf755b64fc4c26c577d9a5958c3.png)

*μ*-law

L1 损失也是如此。定量比较 PSNR 和 HDR-VDP-2 分数在本文中提出传达 L1 损失更好地重建更好的细节相比,L2 损失。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/d6c718c997e375e5e6f0e94ed9d6d88a.png)

## 实施规范

该架构是使用 PyTorch 实现的。规格和超参数是-

*   重量初始化:Xavier
*   优化器:ADAM
*   学习率:1 X10–5
*   批量:8 个
*   GPU: NVIDIA GeForce 1080 Ti
*   一幅图像(1500x1000)的推断时间:0.32 秒

## 结果

这些网络在 Kalantari et 提供的数据集上进行了训练和测试。艾尔。作者提供了定量和定性的比较之间的几个变量的网络,在 PSNR 和 HDR-VDP-2 评分。

*   ahdr net—ahdr net 的完整模型。
*   DRDB 网络(即无注意事项的 AHDRNet)
*   RDB 网(即没有膨胀的阿德尔网)
*   RDB 网络(即没有注意力和扩张的 AHDRNet)
*   RB-Net(即 AHDRNet,不包含注意、扩张和密集连接)。RBs 取代 DRDBs。
*   深 RB 网。使用更多的 RBs。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/2aecee552cc0695c52bf5f427ab887bd.png)

结果显示了 AHDRNet 的每个组件对于整个网络的功效是如何重要的,即注意力是重要的,扩展卷积是重要的,密集连接是重要的,剩余学习是重要的。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/a9519858957591c7a4376e4a0ae073b6.png)

Visual results, from the paper

与最先进技术的比较

与当前最先进的方法(基于学习和不基于学习)的比较揭示了 AHDRNet 如何击败现有的方法。最接近的竞争对手显然是 [Kalantari et。al](https://cseweb.ucsd.edu/~viscomp/projects/SIG17HDR/) 的实现仅次于 AHDRNet。作者还提供了使用光流对齐图像(AHDRNet + OF)的 AHDRNet 变体的结果。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/6b12fe033e8ab7cc4697b84d474dfd05.png)

视觉结果显示了网络在生成的 HDR 输出中注入细致细节的功效,即使在剧烈运动的情况下也不会产生任何对准伪影。这是从论文中摘录的一些结果-

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/01e197c6795bb6cde6e9b8ec0f2c67b3.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/aa3eaed0130f87c1523f36db15411a5d.png)

# 结论

AHDRNet 是第一个解决 HDR 图像生成问题的基于注意力的方法。注意力机制的技巧已经被用于对齐输入的 LDR 图像。先前的图像对准尝试使用了基于光流的方法,这些方法具有一些不准确性,并且对于帧之间的剧烈运动表现不佳。然而,基于注意力的方法在 HDR 重建以及消除对准伪影方面表现得非常好。大量的实验揭示了 AHDRNet 如何在定性和定量上取代现有的方法,并且它已经成为 HDR 图像生成中新的最先进的技术。

# 参考

*   闫庆森,董工,施勤峰,安东·范·登·亨格尔,,伊恩·里德,,,[注意力引导网络无鬼高动态范围成像](https://arxiv.org/abs/1904.10293) (2019),2019
*   名词(noun 的缩写)K. Kalantari 和 R. Ramamoorthi,[动态场景的深高动态范围成像](https://cseweb.ucsd.edu/~viscomp/projects/SIG17HDR/) (2017),ACM Trans。图表
*   吴尚哲、许家瑞、戴宇荣、唐志强,[具有大前景运动的深高动态范围成像](https://arxiv.org/abs/1711.08937) (2018),欧洲计算机视觉会议(ECCV),2018 年 9 月
posted @ 2024-10-14 11:47  绝不原创的飞龙  阅读(430)  评论(0)    收藏  举报