TowardsDataScience-博客中文翻译-2019-十一-

TowardsDataScience 博客中文翻译 2019(十一)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

模型背后:贝塔、狄利克雷和 GEM 分布

原文:https://towardsdatascience.com/behind-the-models-beta-dirichlet-and-gem-distributions-526b11a24359?source=collection_archive---------10-----------------------

非参数贝叶斯模型的构建模块

在未来的帖子中,我想讨论非参数贝叶斯模型——这些模型是无限维的,允许广泛的在线学习。但是首先我想介绍一些构建模块:Beta、Dirichlet 和 GEM 分布。这些分布有几个有用的属性,除了非参数贝叶斯之外,还提供了各种各样的机器学习用途。

贝塔分布

Beta Distribution — Wikipedia

贝塔分布有两个参数— αβ — ,取值在 0 和 1 之间。当分析概率或比例时,这个有界区域使贝塔成为一个有用的分布。

事实上,贝塔分布是二项分布的“共轭先验”。共轭先验是贝叶斯推理中使用的术语,回想一下,贝叶斯定理允许我们通过用数据更新先验分布来生成后验预测。共轭先验意味着更新过程背后的数学工作得非常好(简单地说)——后验分布是一个容易更新的参数分布。在没有共轭先验的情况下,我们需要使用更先进的采样方法来描述后验分布。

这种共轭先验性质为 αβ 参数提供了直观的含义。想象一个成功概率未知的重复伯努利试验——我们的目标是在查看重复样本时估计未知的成功概率。起初,我们可能会假设所有的概率都是同样合理的(尽管理想情况下,我们可以通过假设一些概率比其他概率更有可能来让我们的模型领先一步)。Beta 分布将描述我们在每一步成功的更新(“后验”)概率,其中 α 参数等于观察到的成功次数,而 β 参数等于观察到的失败次数(每个参数加 1,因为它们需要为> 0)。

在下面的模拟中,蓝线 Beta(1,1) pdf 是我们的起点,它赋予所有概率相等的权重。第一次试验是成功的——我们得到了橙色 Beta(2,1)。第二次和第三次试验都失败了——绿色 Beta(2,2)和红色 Beta(2,3)。然后是成功—紫色 Beta(3,3),最后是失败— Beta(3,4)。

你可以利用这一点获得β的形状——较高的α’s 将质量移向右边,而相对较高的β’s 将质量移向左边。对于大于 1 的 αβ ,pdf 将概率转移到中间,对于小于 1 的 αβ ,pdf 将概率转移到 0 和 1。

不太直观但非常酷的是,Beta 分布描述了从 0 到 1 的连续均匀分布的顺序统计。具体地,样本大小 n 的第 k 个最小值被分布为β(k,n + 1 — k)。下图显示了 5 样本连续均匀分布的 5 个顺序统计量:最小值(蓝色)、第 25 百分位(橙色)、中值(绿色)、第 75 百分位(红色)和最大值(紫色)。

狄利克雷分布

Johann Peter Gustav Lejeune Dirichlet

狄利克雷分布以上图中温文尔雅的 19 世纪数学家命名,是贝塔分布的多元推广,事实上它的另一个名字是多元贝塔分布(MBD)。

Dirichlet 接受一个参数向量,每个参数对应一个变量(可以有 2 到无穷大)。分布的输出是这样的,变量的和总是等于 1——例如,在三维狄利克雷中,x + y + z = 1。

类似于贝塔分布,将所有的α’设置为 1 给我们一个均匀的分布——这里是 Dir(1,1,1)作为一个 3D 散点图:

α’s 小于 1(此处为 0.1)会将概率质量推到分布的边缘。另一种说法是,该分布倾向于三个变量中接近 1 的一个,而以其他两个为代价。

α' s 大于 1(此处为 10)将概率质量推向中心,这样它有利于 3 个变量之间的相等(它们都更接近 0.33)。

将一个 α 设置得比其他的高会使概率质量向它的方向倾斜。这里是 Dir(1,1,10):

狄利克雷分布是分类分布(即离散多变量分布,其工作方式类似于多值伯努利分布:画一个均匀分布,而不是成功的是/否,找到对应于均匀拉力的变量)和多项式分布(多变量二项式分布)的共轭先验。

狄利克雷中的每个变量都是贝塔分布的,有条件的

狄利克雷过程&宝石分布

狄利克雷过程是狄利克雷分布的一种特殊形式。一个常见的例子说明了狄利克雷分布是一个“打破棍子”的过程——回想一下,变量的总和总是 1.0,所以每个贝塔分布变量“打破”1.0 棍子的一部分。在上图中,我们从 Dir(1,1,1,1,1,1)-7 个变量中提取数据。请注意,每个变量都遵循贝塔分布,这里是贝塔(1,6)。

狄利克雷过程是具有无穷多个变量的狄利克雷分布。你可能会问,如何参数化一个有无限多个变量的模型?通过折断棍子的例子,我们可以把狄利克雷看作一个递归过程。对于我的分析,我可能不需要知道 Dirichlet 的整个范围,但可能只需要知道 0.4 的观察值会落入哪个变量:使用上图中的底线,我只需要知道蓝色、红色、绿色和紫色的绘制就可以得到 0.4,而不需要浅蓝色、橙色和紫色的绘制。

拥有无限数量的参数允许你的模型继续在线学习。一个常见的应用是聚类分析:在一个 k 均值聚类算法下,需要提前定义聚类的数目。如果数据集是已知的,并且可以使用肘方法或其他标准来调整 k ,则这是可行的,但是在在线学习应用程序中,我们可能无法在获得每个数据点时可靠地调整 k 。Dirichlet 过程允许我们在数据进入时将新的数据点动态地放入新的聚类中。使用折断棒的例子,仅当观察到~0.25 以上的观测值时,才需要添加绿色“簇”,仅在观察到~0.35 之后才添加紫色,等等。

GEM 分布是狄利克雷过程的一个特例。GEM 分布以 Griffiths、Engen 和 McCloskey 在这一领域的早期工作命名,是一个带有一个参数的 Dirichlet 过程,我们可以将上面的 Dir(1,1,1,1,1,1,1)写成 GEM(1)。这种表征有统计学意义,但实际上,如果参数之间没有已知的变化,为了简单起见,将分布限制在一个参数是有帮助的。

结论

这篇文章理论性很强,我们讨论了贝塔分布、狄利克雷分布和 GEM 分布的有用性质,因为它们与贝叶斯分析有关,建立了非参数贝叶斯。在以后的文章中,我将在应用程序中使用这些模型。

模型背后:乔莱斯基分解

原文:https://towardsdatascience.com/behind-the-models-cholesky-decomposition-b61ef17a65fb?source=collection_archive---------3-----------------------

运行今天的线性模型和蒙特卡洛模拟的 19 世纪地图制作者的诡计

安德烈-路易·乔莱斯基在数学家中是一个有点奇怪的人:他的工作是在他死于第一次世界大战的一场战斗后死后出版的。他发现了线性代数方法,这种方法以他的名字命名,贯穿了他作为 19 世纪后期地图制作者的工作,但它仍然是一种有效的技巧,为许多机器学习模型提供了燃料。本文将讨论该方法的数学基础,并展示线性回归和蒙特卡罗模拟的两个应用。

它是如何工作的

我会尽量让线性代数简短,但这是不可避免的:要理解线性代数只是一种高效求解方程组的方法,也要理解高级线性代数方法是机器学习的核心。先不说道歉,我们开始吧。

乔莱斯基分解将对称矩阵简化为下三角矩阵,当乘以它的转置矩阵时,产生原始的对称矩阵。如果这毫无意义,这就是它看起来的样子:

Cholesky decomposition takes the form: A = L x L*

from numpy import array
from numpy.linalg import cholesky# define a 3x3 matrix
A = array([[36, 30, 18], [30, 41, 23], [18, 23, 14]])
print(L)# Cholesky decomposition
L = cholesky(A)
print(L)
print(L.T)# reconstruct
B = L.dot(L.T)
print(B)

这种方法的内部变得有点棘手——我将在这里展示它,但这将是帖子中跳过的部分,因为这是假装的心脏——有趣的东西(应用程序)在下面。我们将使用[1,1]符号来表示矩阵 A 中的行= 1,列= 1。

乔莱斯基分解是一个迭代的过程。我将坚持下面的方程组符号,但是当我们到第三行的时候,你会发现用线性代数来表示这个会很有意义。这篇文章很好地解释了矩阵代数符号。注意,还有其他方法可以找到乔莱斯基分解——维基百科解释了几种。都遵循相似的流程。

好吧,那又怎样?现在最酷的部分是:使用乔莱斯基分解,我们可以两步解决任何规模的方程组。假设我们想要求解 a、b 和 c:记住,这也可以写成一个 3 个方程的系统。

A * x = b => solve for x

通常,我们会将 3 个方程堆叠在一起,求解一个依赖于其他两个变量的变量,将其插入,等等。使用乔莱斯基分解,我们有一个更有效的方法。

Solving for x using Cholesky Decomposition

一个 3x3 的矩阵有点乏味,但是我们已经可以开始欣赏这种方法在一个非常大的矩阵上的效率。

应用—最小二乘回归

线性回归的形式为 Y = X * β,其中 Y 是因变量的向量, X 是自变量的向量。最小二乘回归指的是找到预测 Y 值和实际 Y 值之间的平方差最小的向量β(即 RSS =“残差平方和”或“误差平方和”)。

如果这没有意义,那么关注这一点:乔莱斯基分解的效率大约是求解线性方程组的其他方法的两倍。

应用—蒙特卡罗模拟

我把最酷的应用程序留到了最后。假设您想要生成许多相关的正态随机变量,但不想处理大量的多变量正态。乔莱斯基分解允许你模拟不相关的正态变量,并将它们转换成相关的正态变量——酷!

假设 3 个正态(0,1)随机变量,我们希望遵循下面的协方差矩阵,表示基本的相关性和标准差矩阵:

我们找到协方差矩阵的乔莱斯基分解,并将其乘以不相关随机变量的矩阵,以创建相关变量。

import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as pltx_uncor = np.random.normal(0, 1, (3, 10000))cov = np.array([[ 10.0, -2.00,  2.00], 
                [-2.00, 20.00,  0.50],
                [ 2.00,  0.50,  0.50]])L = np.linalg.cholesky(cov)x_cor = np.dot(L, x_uncor)
corr_simulated = pd.DataFrame(x_cor).T.corr()std_ = np.sqrt(np.diag(cov))
corr_empirical = cov / np.outer(std_, std_)x_uncor = pd.DataFrame(x_uncor.T)
x_cor = pd.DataFrame(x_cor.T)sns.pairplot(x_uncor, kind="reg")
sns.pairplot(x_cor, kind="reg")

瞧啊。我们从不相关的:

要关联:

与上面给出的相关性和标准偏差矩阵一致,列 0 和 2 具有强正相关性,0 和 1 稍微负相关,1 和 2 稍微正相关。包含变量 2 的标准差,而 0 和 1 的标准差要宽得多。

请注意,对于非正态随机变量,这并不以同样的方式工作。在上面的例子中,我们的相关变量保持正态分布。如果我们将这种方法应用于伽玛生成的随机变量,我们会发现这一过程并不成立。

不相关伽玛(1,5)-一切看起来都很好。

并关联:

在这里,我们看到变量不再是伽玛分布,这是最明显的线索,变量 1 呈现负值,而伽玛分布严格为正。有一个简单的后门近似法,它包括模拟相关随机变量,找到它们的倒数,然后使用逆相关正态值从期望的分布中提取。这不确切,但可以完成工作。确切的方法往往相当奇特。

结论

乔莱斯基分解是许多机器学习应用程序的基础,这里介绍了其中的两个:最小二乘回归和使用相关正态变量的蒙特卡罗模拟。虽然线性代数可能有点可怕,但重要的是要记住,它只是一种标记线性方程组的有效方法,并且对线性代数方法的高层次理解对于理解当前的机器学习算法至关重要。

模型背后:狄利克雷——它如何加到 1?

原文:https://towardsdatascience.com/behind-the-models-dirichlet-how-does-it-add-to-1-b268f0c70afe?source=collection_archive---------23-----------------------

非参数贝叶斯模型的构建模块

之前的文章中,我将狄利克雷分布表示为许多β分布变量的组合,这些变量加起来等于 1.0——这对于需要“随机”分类器的应用程序来说是有用的,这是一篇仍在撰写中的文章的主题。 Sebastian Bruijns 问了我在原文中回避的一个明显的问题:

非常好且易懂的文章。我只是不明白狄利克雷和贝塔之间的联系,你写了狄利克雷的变量遵循贝塔分布。,但这是怎么做到的,怎么保证加起来就是 1 呢?

事实是这样的:

背景

这一部分主要是对上一篇文章的回顾——如果你熟悉那些细节,可以跳过它。

狄利克雷分布是贝塔分布的多元推广。输入是两个或更多参数的向量,输出是一种分布,其中变量的总和总是等于 1.0,并且每个单独的变量都是贝塔分布的。下图中的“断棒”将这两个想法统一起来。

看完上面的内容,生成狄利克雷的直观方法是生成随机贝塔并求和,但那显然行不通。在下面的模拟中,我们显示了 5 个 Beta(3,7)的和看起来很正常(它并不完全正常,部分原因是 Beta 的界限在[0,1],所以和的界限在[0,5])。

import numpy as np
from matplotlib import pyplot as pltn = 100000
z = [np.random.beta(3,7,n) for i in range(5)]for i in range(5):
 plt.hist(z[i], histtype = u’step’, bins = 300)

plt.show()z_sum = [sum([z[x][i] for x in range(5)]) for i in range(n)]
plt.hist(z_sum, histtype = u’step’, bins = 300)
plt.show()

Left: a histogram of 5 Beta(3, 7) variables; Right: a histogram of the sum of the 5 Betas

那么狄利克雷如何加到 1 上呢

狄利克雷分布的 PDF 如下。这里 θ 是多项式范畴, α 是向量或β参数。贝塔系数始终是贝塔系数(α,1),没有第二个参数。请注意,最终的β分布变量不会遵循β(α,1)—β参数是 α 向量的函数。这可能会给我们一些直觉,为什么随着阿尔法变大,狄利克雷数会增加到 1。得到的贝塔分布变量遵循贝塔(α,(K-1)*α),其中 K 是 α 向量中值的数量。自己试一试:

x = np.random.dirichlet((1, 1, 1), 100000)
for n in range(3):
    a, b, l, s = beta.fit(x[:,n], floc = 0, fscale = 1)
    print(a)
    print(b)

Dirichlet 的 PDF 格式让我们第一次看到它是如何确保贝塔值等于 1.0 的。这里 θ 是多项式范畴, α 是我们一直在研究的向量。

一个实际的实现使用伽马分布(回想一下β/γ:B(α,β)=γ(α)γ(β)/γ(α+β)之间的关系),并且易于直观地理解。首先为每个狄利克雷变量画一个独立的伽玛(α,1),然后将它们平均到 1.0,产生狄利克雷分布变量。

a = 3
n_ = 5y = [np.random.gamma(a, 1, 100000) for i in range(n_)]
y_sum = [sum([y[x][i] for x in range(n_)]) for i in range(100000)]
x = [[y[x][i] / y_sum[i] for x in range(n_)] for i in range(100000)]
x = [[x[i][n] for i in range(100000)] for n in range(n_)]for i in range(n_):
    plt.hist(x[i], histtype = u'step', bins = 300, normed = True)a, b, l, s = beta.fit(x[0], floc = 0, fscale = 1)

顺便说一句,这也提供了一个很好的机会来使用一些强大的列表理解:我对这篇文章已经垂涎三尺大约一个月了。

无限情形—狄利克雷过程

在上一篇文章中,我们得到了一个狄利克雷过程,它与狄利克雷分布略有不同。通过狄利克雷过程,狄利克雷分布可以扩展为具有无穷多个变量。这是另一个事实,我挥舞着我的手,可能会冒犯你的直觉。

考虑狄利克雷过程的方式是,来自它的每个拉动本身是狄利克雷分布的(不是贝塔分布的,尽管当然来自狄利克雷分布的拉动是贝塔分布的)。所以不像上面的狄利克雷分布,每个变量

这个过程是可能的,因为我们可以迭代地生成一个新变量,所以我们实际上不会生成无限的变量,但是我们创建了一个框架,如果需要的话,我们总是可以创建更多的变量。在这种情况下,我们不能使用上面的伽马技巧,因为我们不能除以总和,但我们可以确信,如果我们走向无穷大,我们永远不会以变量加起来超过 1 而结束。公式如下所示——p(I)是狄利克雷变量——V(I)是中间变量。

下面我们生成狄利克雷过程中的前 3 个变量:

k = 3z = [np.random.beta(1,1,100000) for i in range(k)]
p = [[np.prod([1 - z[x][n] for x in range(i)]) * z[i][n] for i in range(k)] for n in range(100000)]
p = [[p[i][x] for i in range(100000)] for x in range(k)]for i in range(k):
    plt.hist(p[i], histtype = u'step', bins = 300, normed = True)
    a, b, l, s = beta.fit(p[i], floc = 0, fscale = 1)
    print(a)
    print(b)
plt.show()p_sum = [sum([p[x][i] for x in range(k)]) for i in range(100000)]
plt.hist(p_sum, histtype = u'step', bins = 300, normed = True)
plt.show()

Left: graph of Dirichlet-distributed variates that are components of Dirichlet process; Right: sum of Dirichlet-distributed variates

第一个 Beta draw 在左图中用蓝色表示:Beta(1,1)。在 orange 的第二个 draw 中,我们使用 Beta(1,1),但然后乘以(1-V(1)),因此最终变量是 Beta-looking。绿线是第三个吸引点——随着我们将更多的质量转移到左侧尾部,β继续增加。这具有直观的意义——使用α = 1,我们允许相对较高的值在抽奖的早期出现,因此剩余的抽奖被迫进入较低的数字。右图告诉我们,仅通过三次平局,我们已经非常接近 1.0,因此剩余的平局将具有非常小的余量。

如果我们使用上面的α = 0.5,我们会强制早期的绘制坚持较低的值,因此对以后有更多的自由

Left: graph of Dirichlet-distributed variates that are components of Dirichlet process; Right: sum of Dirichlet-distributed variates

结论

像以前的文章一样,这篇文章是理论性的。希望它有助于填补我在上一篇文章中忽略的一些空白。在以后的文章中,我将在应用程序中使用这些模型。

欧洲电视网评分的背后——多样性法案还是政治永久化?

原文:https://towardsdatascience.com/behind-the-scoring-in-the-eurovision-diversity-act-or-perpetuation-of-politics-3e3fc75ce820?source=collection_archive---------16-----------------------

1975-2018 年间欧洲电视网评分的描述性数据分析。

在过去的几天里,特拉维夫快疯了。人们通过 Airbnb 出租他们的公寓,以制造一个不错的藏身之处,到处都是大标志,巨大的帐篷城就在地上,还有第一批游客涌入的标志。你不能避开臀部。我喜欢超越欧洲电视网的想法;我的意思是,我真的不看每一个“数字”(即使当我的国家进入决赛时),但我赞同每一个庆祝多样性的国际行为。

作为一名国际关系专业的毕业生,我一直在思考投票系统。许多人说这是有偏见的,大多数情况下,更好的分数是在来自同一个地理区域或政治联盟的国家之间给出的。直觉上,这种说法可能有道理,但我还没有看到国家之间的评分总结来支持这种说法。

上周,当我在谷歌上搜索时,我在数据中发现了这个伟大的数据集。世界,由 datagraver.com提供,详细记录了自 1975 年至 2018 年 5 月在里斯本举行的最后一届欧洲电视网的每一次投票(50K 行)。对于那些对我的数据参与步骤感兴趣的人,您可以跳到本文的结尾部分。总的来说,这创造了一个巨大的机会来提供一个描述性和有形的分析。

The stage for the contest next week. Credits to Israeli Public Broadcasting Corporation KAN

研究方法:

  1. 仅计算陪审团——“电话投票”被排除在外,因为它在 2009 年才刚刚开始,自然,在客观性和政治方面,它的属性与陪审团不同。
  2. 只有决赛 人们可以认为决赛中的投票更有价值,因为“Douze Points”(法语中的 12 分)赋予了被得分的国家更多的奢华,更多的宣传和赢得比赛的更好机会。因此,从概念上来说,将半决赛和决赛的分数相加是不正确的,因为客观兴趣是不同的。
  3. 没有确认参加特拉维夫欧洲电视网(2019 年 5 月)的国家被排除在外。这份名单中的传统参与者是乌克兰、保加利亚、斯洛伐克、土耳其和波斯尼亚和黑塞哥维那。

我选择将结果显示为 一个我通过 Tableau 完成的交互地图;将鼠标悬停在一个国家上,你可以看到它喜欢哪个国家,还可以在工具提示中控制可用国家的数量。因为 Medium 不支持嵌入式 Tableau 可视化,所以输入超链接是很重要的(最好从计算机输入)。让我们看四个案例来检验上面的陈述。

在斯堪的纳维亚,五分之四的国家(丹麦、冰岛、挪威和瑞典)倾向于将至少三个斯堪的纳维亚国家的平均得分排在前六名;即使是剩下的国家芬兰,也把瑞典排在第二位,其他国家都排在前十名。综合来看,斯堪的纳维亚地区的平均得分为 4.65 分。即使这个总和听起来很低,但在我看来,这是令人印象深刻的,因为它是一个五重奏,并且分析的时间段超过了 45 年。

往东到波罗的海国家(爱沙尼亚、拉脱维亚和立陶宛),可以看出这种地理趋势相当明显。比如爱沙尼亚,拉脱维亚以 8.4 分排名第一;拉脱维亚以 5.8 分排名立陶宛第 2,立陶宛以 9.9 分排名拉脱维亚第 1,爱沙尼亚以 5.6 分排名第 3。这个三角包平均保持 6.75 分。有人可能会说,由于波罗的海国家的高度政治和文化倾向,加入芬兰是必须的。不管真理是否坚持,芬兰以 7.9 分将它的邻国爱沙尼亚排在第一位。另外一个事实是,所有波罗的海国家都倾向于不与“俄罗斯熊”打交道,给它一次排名第一,两次和第二,平均大约 7.5 分。

还记得维京的成就并印象深刻吗?准备好迎接另一个惊喜吧。在巴尔干半岛(阿尔巴尼亚、克罗地亚、希腊、黑山、北马其顿、塞尔维亚和斯洛文尼亚)局势走向极端。七个国家中有五个平均将一个巴尔干国家排在第一位,所有七个国家中有一个巴尔干国家排在第二位。值得一提的是,塞尔维亚和北马其顿保持忠诚,因为他们得分最高的五个国家都在这个街区内。总体而言,所有七个国家的平均得分为 5.39 分。此外,将塞浦路斯从巴尔干名单中剔除是正确的,但希腊和塞浦路斯之间的地中海政治联盟不容忽视;两人都以超过 10.3 分的平均得分并列第一。

另一个突出的地区集团是俄罗斯及其欧亚延伸体(亚美尼亚、阿塞拜疆、白俄罗斯和格鲁吉亚)。这一轴心的投票模式使其成员国至少在前三名中占据两个位置,而在四分之三的情况下,俄罗斯排名第一。在我的分析中,计算这个模块中的衡量指标达到了最高,在组内每次投票平均达到 6.39 分。想象一下,如果不是亚美尼亚和阿塞拜疆在纳戈尔诺-卡拉巴赫问题上的政治竞争,这个数值会更高;这导致对方平均给自己打 0.1 分。

*备注:

  • 匈牙利和罗马尼亚被排除在巴尔干半岛之外,因为从领土上来说,它们不能完全算作一个巴尔干半岛国家,根据维基百科
  • 一些互联网消息称摩尔多瓦是欧亚国家,包括经合组织本身。将摩尔多瓦列入名单引发了罗马尼亚同样的困境。从我的角度来看,两者之间共同边界上的政治和文化相似性是导致我将它们排除在外的因素,正如前面提到的巴尔干半岛的情况一样。
  • 在参数中替换 40 个国家并查看所有关系的人可能会注意到,并非所有国家都有平均值。例如,冰岛没有投票给澳大利亚,但它确实以相反的方式发生了;这是由于比赛规则,一些没有进入决赛的国家可以在决赛中得分。不过,这些数字代表的是给定所有机会对其他人进行排名时的平均值。
  • 许多 0 分的国家可能只有 1 或 2 分,但平均分数很低,所以是最低分;因此,圆的行动可能会欺骗。

Israel and Cyprus at the Eurovision finals, May 2018. Credits to Escdaily

结束语

除了这四种情况,还有更多隐藏的政治永存的故事。例如,以英语为母语的国家(澳大利亚、爱尔兰、英国)的故事有一个小的评分模式,但将来当更多的分数累积时,它可能会改变;更多的双边关系,如意大利-马耳他和罗马尼亚-摩尔多瓦;法语母语国家、德语和拉丁美洲国家(西班牙、葡萄牙)也是如此,这些国家在分析中没有得到表达,但我们应该希望不会。

我真诚地希望,正如序言中提到的那样,“正确的眼睛”会看到这个帖子。正如在 2018 年 5 月里斯本大赛中获胜的以色列歌手 Netta Barzilai 通过说“感谢你接受差异和庆祝多样性”来表达她的感激之情,我说这是应该得到认可的正义议程,但不仅是在个人层面,而且是在国家之间的集体层面。

谢谢你的阅读。我会很高兴阅读任何评论——可以在我的 Linkedin 个人资料上看到,也可以通过 alonrechavia@gmail.com 看到。

— — — — —

对于那些对自己的作品集发起一个项目感兴趣的人,或者只是对我的工作方法好奇的人,以下是参与步骤-

  1. 数据清洗—决赛、评审团、非参赛国家(塞尔维亚和黑山改为塞尔维亚;前南斯拉夫的马其顿共和国变成了北马其顿。
  2. 创建一个由From CountryTo Country组成的间隔连接列。
  3. 使用“删除重复项”操作(“数据”选项卡)复制到新工作表。
  4. average 如果公式被四舍五入(精确到小数点后 1 位)以得到平均分数,列别名为Avg Score
  5. “文本到列”(“数据”选项卡)来分隔串联列,在空间上分隔(总共创建一个 4 列表格)。
  6. 导入 Tableau——将From CountryTo Country拖到文本表格中;拖动Avg Score到文本标记处,右中对齐;拖动To Country到形状标记,改变为之前下载并插入到我的 Tableau 库文件夹中的旗帜图标;将From Country分组到地理块中,并将药丸拖到颜色标记处。
  7. 为要显示的前 N 个国家创建一个整数参数,连接到To Country过滤器。
  8. 地图创建——基于细节标记中的From Country,带有文本表格上的工具提示过滤器(将过滤器从所有字段更改为From Country,以避免地理区块过滤);将文本表格中的筛选器药丸更改为上下文筛选器。
  9. 将地图复制四次,重新命名为国家(冰岛、圣马力诺、澳大利亚和马耳他)。仔细检查这些表格中的工具提示,是否筛选到了From Country而不是所有字段。
  10. 仪表板格式。

成为数据科学家并不能让你成为软件工程师!

原文:https://towardsdatascience.com/being-a-data-scientist-does-not-make-you-a-software-engineer-c64081526372?source=collection_archive---------3-----------------------

现实世界中的数据科学

如何构建可扩展的 ML 系统—第 1/2 部分

放弃

希望我有争议的标题引起了你的注意。太好了!现在请耐心听我说,我将向您展示如何构建一个可扩展的架构来围绕您机智的数据科学解决方案!

我正在开始一个由两篇文章组成的系列,它将涵盖关于架构和设计的软件工程基础,以及如何在机器学习管道的每一步应用这些基础:

第一部分 :问题陈述|架构风格|设计模式|坚实 第二部分 :构建机器学习管道

介绍

正如我们之前在 Steven Geringer 著名的维恩图中看到的,数据科学是 3 个学科的交叉:计算机科学、数学/统计和特定的领域知识。

Data Science Venn Diagram [Copyright Steven Geringer]

拥有基本的(甚至是高级的)编程技能是进行端到端实验的关键,但是这并不意味着您已经创建了一个可以投入生产的应用程序。除非你已经从 IT 背景进入数据科学和机器学习(ML)领域,并且在构建企业、分布式、可靠的系统方面有切实的经验,否则你的 Jupyter 笔记本不符合优秀软件的标准,而且很遗憾,也不能让你成为软件工程师!

你已经建立了一个很好的预测产品的原型,但是你仍然需要推动它通过工程路线图。你需要的是一个专业软件工程师团队在你身边,把你的(一次性)概念证明变成一个高性能可靠松耦合可扩展的系统!

一切都是设计好的;很少有东西是设计好的!

在这个系列中,我们将看到如何实现这一点的一些想法…我们将从第 1 部分的基础开始,并在第 2 部分逐步设计整体架构。建议的架构将与技术无关。ML 管道将被分解为责任划分清晰的层,在每一层,我们都可以从大量技术堆栈中进行选择。

但是让我们从定义一个成功的解决方案开始吧!

问题陈述

主要目标是建立一个系统:

▸降低 潜伏期
▸与系统的其他部分集成但
松散耦合,例如数据存储、报告、图形用户界面;
▸可以
横向和纵向缩放;
消息驱动 即系统通过异步、无阻塞的消息传递进行通信;
针对
工作量管理 提供高效的计算;
▸是
容错和自愈即故障管理;
支持
批量 实时 加工。
**

建筑风格

我们将首先介绍什么是反应式系统,然后快速浏览一下最流行的架构模式。

反应系统

反应式系统设计范例是一种构建更好系统的连贯方法,它是根据反应宣言的原则设计的。每个反应原理都映射到一个重要的系统可扩展性维度:
反应灵敏 →时间
弹性 →负载
弹性 →错误
消息驱动 →通信。

Features of Reactive Systems

面向服务的架构(SOA)

SOA 以将业务问题分解为服务的概念为中心。这些服务通过网络共享信息,它们还共享代码(即公共组件)以保持一致性并减少开发工作。
服务
提供者发布一个合同,指定服务的性质和如何使用它。服务消费者可以在注册表中定位服务元数据,并开发所需的客户端组件来绑定和使用它。

一个 orchestrator 是一个复合服务,负责调用和组合其他服务。或者,编排为服务组合采用了一种去中心化的方法,即服务与消息/事件的交换进行交互。

SOA

流式架构

流式架构由以下组件组成:

  • ****生产者:生成和发送消息的应用程序
  • ****消费者:订阅和消费消息的应用程序
  • ****主题:属于特定类别的记录流,存储为在分布式集群中分区和复制的有序且不可变的记录序列
  • ****流处理器:以某种方式处理消息的应用程序(如数据转换、ML 模型等)。

Streaming Architecture

λ架构

Lambda (λ)架构旨在以集成方式处理实时和历史聚合批量数据。它分离了实时和批处理的职责,而查询层提供了所有数据的统一视图。
这个概念很简单:当数据生成时,它在存储之前被处理,因此分析可以包括在最后一秒、最后一分钟或最后一个小时生成的数据,只需处理传入的数据,而不是所有的数据。

Lambda Architecture

微服务架构

微服务是一种架构风格,它将应用程序构建为小型、自治、松散耦合和协作服务的集合,围绕业务领域建模。这些服务使用同步协议(如 HTTP/REST)或异步协议(如 AMQP)进行通信。它们可以彼此独立地开发和部署。每个服务都有自己的数据库,以便与其他服务分离。

Microservices Architecture

表述性状态转移(REST)架构

REST 是一种开发 web 服务的架构风格,它建立在互联网 HTTP 的现有特性之上。它允许以无状态的方式传输、访问和操作文本数据表示,即应用程序可以进行不可知的通信。

RESTful API 服务通过统一资源定位器(URL)公开,它提供了创建、请求、更新或删除数据(CRUD)的能力。通过将生产和消费的信息从生产和消费信息的技术中分离出来,它最适合用于管理系统!

REST Architecture

设计模式

我们将仅仅触及这个主题的表面,并且将仅仅讨论我可能在本系列的第二部分中提到的那些模式。—[现在还很难知道,但这些是我每天使用的模式]

软件设计模式是对软件工程中常见问题的优化的、可重复的解决方案。这是一个解决问题的模板,可以在许多不同的情况下使用。

战略

策略模式定义了一系列算法,将每个算法放在一个单独的类中,并使它们可互换。将行为封装在单独的类中,消除了任何条件语句,并在运行时选择正确的算法(即策略)。

****—用法说明:一个业务规则有不同的实现,或者需要不同的算法变体。

Strategy Pattern

模板方法

模板方法旨在从不同的过程中抽象出一个共同的过程。它定义了算法的框架,将一些步骤推迟到子类。子类可以覆盖一些行为,但不能改变框架。

****—用法说明:有一组一致的步骤可以遵循,但各个步骤可能有不同的实现方式。
⭐️ 与策略模式的差异:
模板:通过
子类编译时选择算法。策略:由容器运行时选择算法。

Template Method

责任链

责任链模式建议通过启用一个或多个处理程序来满足请求,从而避免将客户机(请求的发送者)与接收者耦合在一起。这些处理程序链接成一个链,即每个处理程序都有一个对链中下一个处理程序的引用。

****—用法说明:一个以上的对象可能会处理一个请求,而处理程序(也不是序列)是未知的。

Chain of Responsibility

观察者

观察者模式(也称为发布/订阅或简称 PubSub)通过定义对象之间的一对多依赖关系,使通信变得容易广播,这样当一个对象经历状态变化时,它的所有依赖对象都会得到通知并自动更新。观察者有责任记录他们正在“观察”的事件。

****—用法说明:当一个对象的改变需要改变其他对象,而你不知道需要改变多少个对象时。

Observer Pattern

建设者

构建器模式旨在以一步一步的方式构建一个复杂的对象,并将构建与其表示分离开来。本质上,它允许使用相同的代码产生不同类型和表示的对象。

****—用法说明:几种复杂的物体可以用相同的整体构建过程来构建,尽管各个构建步骤有所不同。

Builder Pattern

工厂方法

工厂方法为创建对象定义了一个接口,但是实例化是由子类完成的。

****—用法说明:事先不知道对象的确切类型和依赖关系。

Factory Method

抽象工厂

抽象工厂捕获了如何创建相关对象的系列,而无需指定它们的具体类。****

****—用法说明:存在不同的情况,需要不同的规则集实现,要么事先未知,要么可扩展性是一个问题。
⭐️ 与抽象方法的区别:
抽象工厂:创建其他工厂,这些工厂又创建从基类派生的对象。【工厂方法:创建从特定基类派生的对象。

Abstract Factory

装饰者

装饰模式通过将对象放在包含这些行为的特殊包装类中,动态地将新的责任附加到对象上,因此对原始方法的签名没有影响(组合优于继承)。

****—用法说明:在运行时给对象分配额外的行为,而不破坏使用这些对象的代码。

Decorator Pattern

贮藏室ˌ仓库

存储库模式解决了数据检索和持久化的代码集中化问题,并为数据访问操作提供了一个抽象,即类似于内存中的域对象集合,允许执行 CRUD 方法,并消除了任何数据库问题。****

****—用法说明:将业务逻辑与数据访问代码解耦。

Repository Pattern

小奖励

想了解更多关于模式的知识吗?从“四人帮”的书开始,即:“设计模式:可重用面向对象软件的元素”。下面的模式关系图值得注意— 很漂亮,是吧

Courtesy: Design Patterns: Elements of Reusable Object-Oriented Software

固体

在这里,我们将只玩弄坚实的原则,因为它们对每个软件开发人员来说都是必不可少的。

正如鲍勃大叔所说:它们不是规律。它们不是完美的真理。这些陈述的顺序是:一天一个苹果,医生远离我。

这意味着它们不是某种“魔法”,不会带来牛奶、蜂蜜和伟大软件的乐土,但是它们仍然是健壮和持久软件的重要贡献者。

简而言之,这些原则围绕着两个主要概念,它们是成功的企业应用程序的构建块:耦合是一个类了解另一个类并与之交互的程度,而内聚表示一个类具有单一目的的程度。换句话说:**

耦合是关于类之间如何交互的,而
内聚则关注单个类是如何设计的。

单一责任原则

一个类应该有且只有一个改变的理由。

这是不言自明的,但是说起来容易做起来难——向现有的类中添加新的行为总是很诱人的,但是这是灾难的一个处方:每个行为都可能是将来改变的原因,所以更少的行为导致在改变期间引入错误的机会更少。

开闭原理

你应该能够扩展一个类的行为,而不用修改它。

您使用的类应该对扩展开放,但对修改关闭。实现这一点的一种方法是通过继承,即创建一个子类,这样原始类就不会被修改,但自定义代码会被添加到子类中以引入新的行为。

利斯科夫替代原理

派生类必须可替换其基类。

当将类 A 的行为扩展到子类 B 时,你必须确保你仍然可以在不破坏任何东西的情况下与 B 交换 A。这可能有点吸引人,尤其是当把这一原则与开闭原则结合起来时。

界面分离原理

制作客户特定的细粒度接口。

接口和类必须尽可能的专门化,这样调用客户端就不会依赖于它们不使用的方法。这与单一责任原则是相辅相成的。

从属倒置原则

依赖抽象,不依赖具体。

高级类不应该依赖于低级类。它们都应该依赖于抽象。同样,抽象不应该依赖于细节。细节应该依赖于抽象。

小奖励

我创建了这个快速参考图。如果你想知道我对左边小符号的灵感来自哪里,请看看:' '坚实的原则,用激励海报解释' '文章-我喜欢作者如何在原则上添加有趣的转折🐤。

SOLID

脚注

这并不是所有软件工程概念的详尽列表,但是它是我们在下一篇文章中将要使用的基础。我希望它能让你对构建可伸缩软件的贡献因素有一个很好的了解。让应用程序设计对变化有弹性是构建成功解决方案的关键——如果设计过程仓促,当错误被发现时,项目结束时要支付罚金。**

好的设计显而易见。伟大的设计是透明的。

感谢阅读!第二部快到了…

我定期在 媒体 上撰写关于技术的&数据——如果你想阅读我未来的帖子,请“关注”我!

贝叶斯网络中的信念传播

原文:https://towardsdatascience.com/belief-propagation-in-bayesian-networks-29f51fdc839c?source=collection_archive---------6-----------------------

贝叶斯网络推理

在本文中,我将使用信念传播(BP)和一些示例数据。我假设你已经知道贝叶斯网络(BN)。这篇文章解释了如何计算 BN 中帮助推理的不同变量的信念。

Photo by Clint Adair on Unsplash

信念传播

我在 GitHub 上用 BP 的代码创建了一个存储库,我将用它来解释算法。

首先,假设我们有一棵没有环的多叉树。例如,下图所示的图表。我们有 4 个变量“雨”、“洒水器”、“福尔摩斯”和“华生”,有向边“雨”到“福尔摩斯”、“雨”到“华生”和“洒水器”到“福尔摩斯”。贝叶斯网络模拟了福尔摩斯和华生成为邻居的故事。一天早上,福尔摩斯走出家门,发现草地是湿的。不是下雨了,就是他忘了关洒水器。所以他去邻居沃森那里看看他的草是不是也湿了。当他看到确实是湿的,他很肯定他没有忘记洒水器,而是下雨了。所以信息从沃森流向洒水器。这个信息流在 BNs 中用 BP 建模。

在 BP 中,我们让变量彼此交谈,以交换它们对彼此的信念。有两种信息:父母给孩子的信息和孩子给父母的信息。总的来说,我们只需要使用 5 个公式来做 BP。在我的解释中,我将对某些公式和变量使用不同的名称,因为我发现一些来源相当误导。

1.可能性

似然性保存关于儿童观察的信息,例如,霍姆斯草地未被观察的似然性是 1 表示潮湿,1 表示不潮湿。如果观察到潮湿的草地,则潮湿的可能性变为 1,不潮湿的可能性变为 0。这些单位向量不是归一化的。

Likelihood function is a product of all incoming messages from a variables children

可能性函数基本上是一个变量的子变量发送的所有传入消息的乘积。它返回一个似然向量,包含变量的每个可能值的似然值。在“雨”的情况下,它的基数为 2,代表两种状态“是”和“否”。

如果变量没有子节点,因为它是图中的叶节点并且没有被观察到,那么它的似然向量将是单位向量,对于它的所有可能值都是 1,例如,由于我们在开始时没有观察到霍姆斯的草地,所以我们将它的似然向量分别设置为[1,1]用于“不湿”和“湿”。

在 Python (numpy)代码中是这样的。

**def likelihood**(self):
    incoming_children_messages = np.array([
        c.message_to_parent(self) **for** c **in** self.children
    ])
    **return** incoming_children_messages.prod(axis=**0**)

2.传道者

先验是在开始时已经知道的某些事件的概率,例如,下雨的概率为 20%。如果先验是未知的,下面的公式是计算它。这有点复杂,但我会试试看。先验给出了各个变量的无条件概率。因此,我们也需要包含条件变量。

Prior probability function is the sum of all possible combinations of parent values times the product of the respective incoming messages

在我们的例子中也给出了条件概率。在公式中,“P(X|W)”对应于此。此外,我们需要使用来自所有父母的传入消息,这就是公式中的“ϕ”。索引显示了消息方向——从父变量“K”到当前变量“X”。使用这两个部分(条件概率和来自父母的信息),因为它们都给出了关于变量概率的信息。一方面,我们看到给定一些父母值的概率,另一方面,我们看到那些父母的消息。不用观察,这些信息对应着父母的前科。因此,这里,正在计算“X”的余量,并去掉条件变量。

对于每个父母的消息,在条件概率中存在相应的部分。因此,我们可以用条件概率表对每条消息执行点积,在这个代码片段中是 self.m

**def** **priors**(self):
     parents_messages = [
         p.message_to_child(self) **for** p **in** self.parents
     ]
     **return** reduce(np.dot, [self.m.transpose()]+parents_messages)

3.相信

信念是我们观察到某些事件后的后验概率。它基本上是可能性和先验的标准化产物。

Belief is the normalized product of the likelihood and prior

我们采用我们事先知道的概率,并引入从孩子们那里获得的新知识。这样,我们就对变量产生了新的信念。如果一个变量既有父变量又有子变量,那么信念就是包含上下信息的更新概率(后验概率)。因此每个传入的消息都被考虑在内。“α”是一个归一化常数,因为似然性和先验的乘积总和可能大于 1。这是一种用变量所有可能状态的总和进行除法运算的简写形式。

在这个 Python 片段中,规范化部分变得更加清晰。

**def** **belief**(self):
     unnormalized = self.likelihood() * self.priors()
     normalized = unnormalized/unnormalized.sum()
     **return** normalized

4.给父母的信息

为了计算一个变量的可能性,我们需要考虑来自一个变量的子变量的所有传入消息,这些子变量由可能性函数中的λ表示。

这个公式相当混乱,但是在查看一些 Python 代码时更容易理解。一般来说,我们从 P(X|U)中边缘化掉 k,而 x 是发送者(孩子),k 是接收者(父母),u 是 x 的所有父母,包括 k。如果我们为 x 设想一个条件概率表,对于每个条目,我们取父母的相应激活,并乘以各自的传入消息ϕ,而不包括 k 本身。然后,我们将这个值乘以 X 的可能性。最后,我们对 K 值相同的所有值求和,剩下一个向量,它是从 X 到 K 的信息。

因此,给父母的消息会考虑所有传入的消息,不管它们是由孩子还是父母发送的(除了接收消息的父母),并考虑给定特定父母值的概率。因此,概率高的变量设置比概率低的变量设置更容易转发传入的消息。根据消息设置的条件概率对传入消息进行评级。

我希望 Python 代码能进一步阐明这一点。

**def** **message_to_parent**(self, parent):
    likelihood = self.likelihood()
    parents_priors = np.array([
        p.message_to_child(self) 
            **for** p **in** self.parents **if** p != parent
    ])
    parent_i = self.parents.index(parent)

    stack = np.vstack([
        np.dot(
            self.m.take(r, axis=parent_i).transpose(),    
            parents_priors.prod(axis=**0**)
        ) 
        **for** r **in** range(parent.cardinality)
    ])
    **return** np.dot(stack, likelihood)

或者举个福尔摩斯的例子:

message = np.zeros(rain.cardinality)
**for** r **in** rain:
  **for** s **in** sprinkler:
    **for** h **in** holmes:
      message[r] = probas[r, s, h] \
                   * sprinkler_message[s] \
                   * likelihood[h]

5.给孩子们的信息

要计算父母发给孩子的信息,有两种方法。从其它子节点接收的所有消息与当前节点的先验相乘,或者当前节点的信念除以相应子节点给父节点的消息。

我们认为这个公式叫做 Kappa,它的索引告诉我们信息的方向(从 X 到 K)。

如果我们看看信念的公式,我们看到这个公式是可能性和先验的乘积。然而,可能性是所有传入消息的乘积。因此,信念除以来自 K 的传入消息得到所有传入消息——除了我们除以的那个消息——和先前消息的乘积。这样,我们就可以解释计算 Kappa 的两种方法之间的相等性。传递给孩子们的信息背后的直觉与传递给父母的信息相似。您考虑了所有传入的消息(因此考虑您可以获得的所有信息),并将聚合发送到下一个节点。

α也是一个归一化常数。如果父节点只有一个子节点,它就不能从其他子节点收集消息,因为没有子节点。因此,它将只返回它的 prior。

**def** **message_to_child**(self, child):
    children_messages = []
    **for** c **in** self.children:
        **if** c != child:
            children_messages.append(c.message_to_parent(self))
    **if** len(children_messages) > **0**:
        unnormalized = (children_messages * self.get_priors())
        unnormalized = unnormalized.prod(axis=**0**)
        message = unnormalized/unnormalized.sum()
        **return** message
    **return** self.get_priors()

例子

利用我在开始提到的知识库,我们现在可以用霍姆斯的例子,计算不同情况下的信念。

为了使用这个库,我们需要将它和 NumPy 库一起导入。

**import** **numpy** **as** **np**
**from** **node** **import** Node

我们导入了存储库的节点类,它代表了 BN 中的单个节点。在下一步中,我们实际上创建了代表单个概率变量的节点:“福尔摩斯的草地是湿的”、“下过雨的”、“忘记洒水器了”和“沃森的草地是湿的”。创建节点时,必须提供一个名称。之后,您需要设置一些属性,如基数、先验或可能性(如果存在)。

rain = Node("rain")
rain.cardinality = **2**
rain.priors = np.array([**0.8**, **0.2**]) #  no=0 yes=1

sprinkler = Node("sprinkler")
sprinkler.cardinality = **2**
sprinkler.priors = np.array([**0.9**, **0.1**]) #  no=0 yes=1

对于没有子节点的节点,这很简单。对于其他节点,它们有父节点,但没有可用的先验,我们需要定义一个条件概率表(CPT ),它定义了给定来自父节点的所有可能输入时变量的概率。这个 CPT 在代码中称为“m”。

m = np.zeros((**2**, **2**, **2**)) #  rain, sprinkler, holmes' grass
m[**1**, **1**, **1**] = **1**
m[**0**, **1**, **1**] = **0.9** #  <-- here
m[**0**, **1**, **0**] = **0.1**
m[**1**, **0**, **1**] = **1**
m[**0**, **0**, **0**] = **1**
holmes = Node("holmes")
holmes.cardinality = **2**
holmes.m = m
holmes.likelihood = np.array([**1**, **1**])

m = np.zeros((**2**, **2**)) # rain, watson's grass
m[**1**, **1**] = **1**
m[**0**, **1**] = **0.2**
m[**0**, **0**] = **0.8**
watson = Node("watson")
watson.cardinality = **2**
watson.m = m
watson.likelihood = np.array([**1**, **1**])

正如你所看到的,“m”在矩阵的第一个维度中取父元素的值,在最后一个维度中取实际变量的值,例如(代码注释中的“here”)如果没有下雨(0)并且忘记洒水器(1),那么草地潮湿的概率(1)是 0.9。草地潮湿的可能性是 1,1,这意味着两种状态具有相同的可能性。

接下来,我们必须连接节点来定义因果关系。Node 类有一个名为“add_parent”的方法,它可以将变量连接到父变量。

holmes.add_parent(rain)
holmes.add_parent(sprinkler)
watson.add_parent(rain)

在接下来的步骤中,我们假设福尔摩斯的草地是湿的(因此,可能性[0,1])。然后,我们想知道沃森的草是否也是湿的(或者湿的可能性有多大)。

holmes.likelihood = np.array([**0**, **1**])
holmes.message_to_parent(rain)
holmes.message_to_parent(sprinkler)
watson.get_belief() #  array([0.21176471, 0.78823529])

我们看到,沃森的草是湿的这一信念确实是趋向于湿的(0.21 vs 0.79)。因此,BN 预计 Watson 的草地是湿的,因为在雨节点上有连接,通过它信仰被传播。

结论

BNs 的工具集在推理案例时非常有用,如下所示。我真的对因果推理的整个研究领域感到兴奋,并认为在深度学习和普通人工智能方面也会取得很多进展。

参考

此处的示例取自。

NER 算法基准:spaCy,Flair,m-BERT 和 camemBERT 关于匿名化法国商业法律案件

原文:https://towardsdatascience.com/benchmark-ner-algorithm-d4ab01b2d4c3?source=collection_archive---------4-----------------------

(型号)大小重要吗?

Each of them is strong in its own way

本文是上一篇关于上诉法院判决匿名化的续篇: 为什么我们从 Spacy 转向 Flair 来匿名化法国判例法

根据几位全球机器学习专家,如 Xavier (Curai)、Anima Anand Kumar(Nvidia/Caltech)或 Pedro Domingos (华盛顿大学)的说法,2019 年的一个大趋势是使用非常大的预训练语言模型(BERT、Megatron-LM、AlBERT、RoBERT……)来提高大多数 NLP 任务的分数。

我在 Lefebvre Sarrut 出版社工作,这是一家出版公司,是欧洲法律行业的主要参与者。如下所述,我们还在帮助几个欧洲政府匿名化他们的法律决定,以推动司法数据公开。

我们希望衡量这些新的大型预训练模型与应用于现实生活数据和法律决策的命名实体识别(NER)任务的其他选项相比有多好。

我们之前的文章是关于匿名化上诉法院的判决,这次我们对商业法院的判决感兴趣。这是一个重大的变化,因为商业决策更具挑战性(更高的写作风格多样性、纸张扫描噪音、OCR 错误等)。).

在本文中, (1) 我们将公开解释我们的背景以及为什么一个合法出版商花费时间和精力在法律数据中具体推动数据公开, (2) 详细介绍我们如何着手注释商业决策,以及 (3) 通过一个基准来完成 NER 图书馆执行匿名化任务的 4 个主要选项。

我们测试了 4 种算法,2 种基于变压器,1 种基于双 LSTM,1 种具有原始架构:

  • spaCy v.2.2,这个版本引入了一个有趣的数据增强机制,类似于我们在上一篇文章中手动尝试的,效果更好吗?
  • 天赋:双 LSTM 角色模型,上次带来了最高分,这次还会重演吗?
  • 多语言 BERT (mBERT):著名的支持 104 种语言的 Google 机型,这么大的支持能做好工作吗?
  • camemBERT ,一个新的法语单语 BERT 模型,在 mBERT 已经支持法语的情况下,还有必要投入精力去建立这样的模型吗?

我们公布商业决策的 NER 分数。与前一篇文章中的数据集相比,它们应该要小心一些,因为商业法庭的数据集比上诉法庭的数据集更难处理。

如果你对这个话题感兴趣,在推特上关注我:https://twitter.com/pommedeterre33

为什么一家法律出版商对通过开源其源代码来免费匿名商业法律案件如此感兴趣?

在法国,3 年前投票通过了一项法律,将所有法律案件公开,因此任何公民、诉讼当事人、律师等。可以自由地使用它们,而不需要向任何人支付任何费用。在所有的法律判决中,商事法律判决的情况是特殊的。

商业法律案件是主要涉及公司和商业法律的判决,范围从公司之间简单的商业诉讼到复杂的破产。

这些商业决策的内在价值非常重要;作为一审判决,它们很好地描绘了当今国家的经济形势,包含了上诉法院案件中没有的事实细节,而这些事实细节是律师、大公司、保险、政府感兴趣的(例如,想想破产,你会了解到成千上万家公司日复一日发生的事情的细节,等等)。).

此外,您还可以从匿名化任务中获得附加价值(只有自然人会被匿名化,但许多实体都会被搜索,包括组织名称),例如,利用每个决策的公司名称信息,您可以轻松地生成公司文件,对所有决策进行分组,这可能有助于监控您的客户、提供商等。

出于当时有意义的历史原因,这些决定,根据定义是公共数据,由商业法庭的书记员组成的财团出售。

在 2019 年读到这样的东西可能会令人惊讶,但外表是骗人的,这种状况是有道理的。简而言之,法国政府目前正在建设的一个名为 Portalis 的大型项目旨在集中所有法国法院的法律裁决。这是一个需要几年才能完成的项目。企业家需要访问商业决策,这就是为什么书记员联盟投资了基础设施来扫描、集中和分发所有法律决策的扫描 PDF,这是一项支付成本的付费服务。

在许多人看到混乱的地方,机会主义者看到了商机。

一些出版商试图大量购买商业决策(用于在他们的平台上发布),但没有一家与店员的财团达成普遍协议……直到 2 年前,媒体披露一家初创公司获得了 事实上的独家交易 以获得数百万份商业决策以及免费的流量,使得“独家”公共数据的转售成为他们产品的主要焦点。

对他们来说不幸的是,在围绕他们的付费锁定公共数据数据库的规模进行了几个月的沟通后,他们因使用非法手段获得更“独家”的合法 decisions⁴而成为头条新闻,失去了作为 consequences⁵.之一的交易其他试图独家获得法律判决的尝试接踵而至,failed⁶.

很难说今天的情况对每个人(公民、诉讼当事人、律师、出版商、创业公司、政府)有多无效。简而言之,今天,没有人能够广泛访问最近的商业决策(更新于 1 年半之前),它们仅以 PDF 扫描件的形式存在,可以按单位购买或手动免费索取纸质副本,但这根本不可扩展。

在这种情况下,职员协会试图为每个人改善情况。很有可能这些被集中起来并以扫描的 PDF 格式提供的判决将成为第一批被添加到未来由我们的最高 Court⁷.维护的法律案件公开数据数据库中的判决

这种情况如此极端,以至于它让我们质疑自己以前没有关注的事情,并迫使我们决定我们要去哪里。

我工作的公司( Lefebvre Sarrut )已经做出了在整个欧洲开放法律数据的坚定承诺(我们正在不同的国家开展几个#openJustice 项目)。我们尽最大努力推动我们自己的生态系统,在这个国家,法律裁决对所有人都是免费的。通过下面的文章,我们想分享的是,利用当今的技术,法国商业法院判决的法律案件匿名化是可行的。

我们所有的工作(但不是明显数据隐私 reasons⁸的数据集)都是开源的(存储库),任何有权访问原始商业决策的人都可以轻松复制。

以下是对我们所做的端到端的描述,并提供了有关我们所达到的结果的细节。

不,ocr 化还没有解决!

对于这个测试,我们的工作是基于商业法庭书记员协会提供的法律判决的扫描 PDF。

我们有两种选择来对它们进行 OCR:使用 SAAS 服务,如亚马逊提供的 one ,或者使用开源解决方案,在我们自己的服务器上运行,如 Tesseract (该任务的主要开源库),并自己完成所有工作。

我们选择宇宙魔方,老实说,我们不确定我们做出了正确的决定。取得不错的成绩很容易,但是我们花了很多时间去改进它。

我们面临的主要挑战是,我们自己没有扫描过文档,而且分辨率不是最佳的,无法获得开箱即用的最佳结果。出于这个原因,它需要一个重要的后处理步骤,以清除噪声或执行简单的事情,如识别一些棘手的段落定界或不一致的页眉和页脚。

我们不会提供更多的细节,因为这超出了本文的范围。我们只能说,这是一个制造或购买的决定,我们可能已经失败了,我们稍后将回到这一点。

无名英雄:注释工具和质量控制

这是这个项目最引人注目的方面,我们在注释质量上的每一项努力都被转化为分数改进,即使是最小的改进。

是的,数据质量很重要,这一点我们都知道,但是到底有多重要呢?

我们的不再是秘密酱,数据团队

注释由一个由 5 名法学家组成的团队在 2019 年 7 月至 8 月期间手动执行(任何时候都有 1 至 3 名法学家)。我们设定的目标是注释 500 个或更多的案例(根据我们对其他注释任务的一些观察)。法律判决是一份很长的文件,如下所示, 500 个案例代表了近 60K 个实体提及

通过这个项目和其他一些与机器学习相关的项目,数据团队的角色正在演变成一些新的东西:为算法创建数据和审计算法输出(到目前为止,他们的角色更多地是为编辑产品提供支持)。

这确实是法律出版业的一个有趣的转变,当周围的每个人都在幻想法律机器人和数字劳动力时,这也许应该得到适当的考虑…

人的部分是项目中较少被记录但仍然是最重要的部分之一。注释可能很无聊,而且总是要求很高。为了更好地实现这些观点,所有数据科学家都应该参与注释任务。因此,他们会意识到为什么关注注释者的用户体验如此重要。这意味着仔细选择工具。

为 NER 标记任务寻找合适的工具

工具直接影响数据团队的生产力。找到合适的工具首先需要知道你需要什么,然后测试它们。

来自空间作者的作品

对于一些内部项目,我们已经使用了来自 Ines Montani 和 Matthew Honnibal 的 prodi.gy ,这是一个不错的工具,但是,对于这个任务,它不符合我们的需求:

  • UI 不适用于长文档(我们需要显示完整的文档以获得足够的上下文来标记)
  • 没有简单的方法来查看文档中的所有实体,
  • 没有简单的方法在文档中搜索特定的实体提及,
  • 没有针对多个标注器的高级管理和监控,
  • 需要时间来设置我们的基础架构(需要召开内部会议来访问服务器等。)

勘误表:为了澄清上面所说的,prodi.gy 能够加载长文档,并在单个文档中管理大量的实体提及,但它的 UI 更适合于具有狭窄上下文的短文本,以帮助注释者专注于任务。

很高兴知道一个解决上面列出的一些问题的工具即将推出

prodi.gy and its unequaled UI

多卡诺

我们考虑的另一个选择是多卡诺:

  • 产品更好的长文档用户界面/ UX
  • 开放源码
  • 没有对协同工作的多个标注器进行高级管理和监控
  • 需要时间来设置我们的基础架构(需要召开内部会议来访问服务器等。)

doccano interface

🍃tagtog

我们测试了 3 个付费的 SAAS 标签平台,其中 2 个有错误的 API 和一个坏的 UX。

最后,我们用了第三个,🍃tagtog 。它不是一个开源的解决方案,费用是每月 147 欧元。它满足了我们的所有需求,没有明显的缺点:

  • 成熟的高级多用户模式
  • 几个工具,轻松快速地审查和提高注释质量
  • 适用于长文档
  • 跨多个文档修复特定模式的简单方法
  • 零设置、无服务器、无内部会议

🍃tagtog tagging interface (there are few other screens)

有一个恼人的错误。它已经被修复🍃tagtog 团队,他们似乎对我们的评论反应很大。

每月 147 欧元比在我们的基础架构上设置和维护解决方案的工程师的成本要低,而且我们避免了为获得服务器部署权限而召开内部会议。

如果你要选择一个注释工具,我的建议是永远记住,这基本上是一个制造或购买的决定,以及其间的所有细微差别。当您可以避免该步骤时,服务器的设置/维护时间是一种“决策”选择(至少是部署)。

因此,要做出决定,你需要知道你需要多少来完全控制你的流量,如果它不完全是你想要的会发生什么,你的数据是敏感的(例如健康)等。?

下面是关于内部注释的一个有趣的相反观点:

作为迭代任务的注释

注释的挑战是用尽可能少的资源获得正确的数据质量和数量。

在决定了我们要注释的工具和决策数量之后,许多问题仍然存在:

  • 有没有注释方法论可循?
  • 如何定义标注计划?
  • 如何检查和提高质量?
  • 如何知道质量是否可以,何时可以停止?
  • 我们如何才能轻松快速地找到改进机会?

我们采用的方法可以描述为以下步骤:

  • 决定我们需要哪种类型的实体(在我们的例子中,类似于另一个项目的实体)
  • 用相似的实体对不同的数据训练模型
  • 将该模型应用于 500 个随机选择的决策,对它们进行预注释
  • 将决策及其预注释上传至🍃tagtog
  • 手动修正上的注释🍃tagtog
  • 【循环从此处开始】下载标注,训练模型,测量
  • 生成显示所有错误(标签和模型预测之间的差异)的报告
  • 手动识别错误中的模式(一些是注释中的错误,一些是预测中的错误)
  • 按照中手动发现的模式手动修复注释🍃tagtog
  • 【循环从此处开始】下载数据,学习模型,测量

我们坚持手动分析的重要性。自动分析类似于应用主动学习方法,众所周知,这种方法在许多现实生活的 setups⁹.中有很多局限性

只有人工检查标签才能保证避免最大的偏差和最高的最终结果,这很费时间。

在我们的例子中,最困难的是注释中需要更多的同质化。我们做了 6 遍,试图使每个实体类型的注释均匀化。

为了说明同质化点,我们举一个例子,我们要在决策中标记 ORGANIZATION,意思是组织的名称,商业决策中大多是公司。

在法国,将公司形式放在商业名称前面是一种习惯。以“ SNC 咖啡馆露露”为例。“”是一种公司形式(像其他国家的“”有限合伙)。因此理论上我们不应该在标签中包含“ SNC ”,因为我们对这些信息不感兴趣。**

似乎很大一部分法国企业家在组建公司时会在他们的商业名称中包含公司形式,因为他们错误地认为这样做是强制性的。在这种情况下,如果我们检查法国公司注册处,公司形式将出现在商业名称内的。当然,另一大部分企业家没有犯这个错误。****

最后,当你阅读一个决定,公司形式有时出现在一个名字前面,你不能真正知道这是因为它是完整的真实名称还是法官引用这家公司的方式(因为那是用法)。

理论上,你可以在标记公司名称之前在法国公司注册处进行检查,但这没关系,因为如果你的标签不是同质的,并且上下文没有告诉你是否必须包含公司表单,那么你的 NER 算法将会失败,无论它有多聪明。

因此,出于同质化的原因,我们决定有一个单一的规则,无论真实名称是什么,我们总是在组织标签中包含公司形式。这就是在注释步骤中发现的那种“T4”细节。

按照我们在第一个注释步骤中发现的所有注释规则,在第二个步骤中制作了测试集。

足够大的商业决策数据集

我们已经注释了来自法国不同商业法庭的 585 个判决(由于我们的两步注释过程,比计划的要多一点)。写作风格是多样的,几乎没有共同的惯例。部分原因是,在法国,商业法官不是专业法官,而是由同行选举出来的商人,他们没有受过几年的普通法律培训(比如上诉法院的法官)。

这是一个需要记住的重要事实,与上诉法院相比,这使得 NER 算法的任务更加复杂,因为机器学习模型喜欢识别重复的模式。

下面我们将测试 2 个基于 BERT 的算法。BERT 对它接受的数据有一个限制:它被限制为 512 个单词块。它可以很容易地通过分割长句来解决,然而,为了避免死角,我们只是将它们从数据集中删除。当然,所有算法的度量都是在同一个清除的数据集上执行的。

我们获得了 69.3K 个实体,分为 10 种类型,组织名称是最具代表性的,这对于商业法律案件是有意义的。

Entity mentions count

在我们的上一篇文章中,我们已经描述了每种类型实体的本质。如果还没读过,总结一下,PERS 实体提到的是人名和最重要的实体类型(必须匿名),然后是地址和组织。

相比之下,NER 任务的论文中使用的法语树库包含 11636 个实体提及,分布在 7 个不同的类型中。

聚光灯下基于深度学习的命名实体识别

所有培训都是在相同的硬件上进行的,12 核 i7,128 GB Ram 和 2080 TI Nvidia GPU。

Flair 和 BERT 表示的测试是通过这个中的 Flair 库完成的。BERT 表示不是由 Flair 本身生成的,它从拥抱脸调用了令人敬畏的变形金刚库。

这再次表明了开源生态系统的重要性,因为下面所有的测试(除了 spaCy )都是通过修改一行代码来完成的,所有的库都可以一起交流…太棒了!

我们使用了分支GH-1221-修复-标记化-问题(提交 3cea2fa )的 Flair v0.4.4,以受益于对 BERT 标记化的修复。

使用空间 2.2 增加现成的数据

在这个基准测试中,我们使用了来自伊内斯·蒙塔尼马修·霍尼伯空间 v2.2。与以前的版本相比,这个版本带来了一些改进,特别是数据扩充模式。

基本上, spaCy 作者注意到,在 NER,大小写问题是一个常见的挑战,并且容易混淆算法。这在法律判决中是非常真实的。为了帮助算法,他们在外壳中随机产生变化。它应该使模型对这个问题更加稳健。

根据我们在的上一篇文章中描述的经验,数据扩充是提高 NER 分数的好策略。

需要强调的是,这个模型没有任何每句话的数量限制。

我们在不到一个小时(我们测试到的最快速的算法提前停止)的时间内,对一个空间模型进行了 12 个历元的训练,得到了以下结果:

spaCy NER scores

这些分数不符合我们的要求(69%的地址召回率有点低)。这对我们来说并不意外,因为我们已经在上诉法院尝试了数据增强策略,我们观察到了真正的分数提高,但不足以达到大型预训练模型的结果。

几乎是经典的人物为基础的双 LSTM 从天赋

⁰是一个基于双 LSTM 字符的单语模型,在维基百科上训练过。

需要强调的是,这个模型没有任何每句话的数量限制。准确地说,它有一些字符长度限制,但它是由 Flair 库内部管理的,用户不必了解它。

我们对一个模型进行了 8 小时 40 个纪元的训练,我们的分数如下。

Flair NER scores

这些结果低于上诉法院的结果。我们认为书写风格的多样性加上 OCR 噪声是主要原因。

我们知道,我们可以通过简单地微调我们拥有的大型商业法院判决数据集的模型来轻松提高分数,但该基准的目的是了解我们可以从盒子中得到什么。

多语言 BERT: 1 种表示适合 104 种语言

如果你不了解伯特,你最好先看看这些优秀的解剖伯特的文章。

Google 发布了几个版本的 BERT,主要的有:

  • 仅英语(有套管和无套管)有不同的尺寸(意味着不同的缓慢风格),
  • 仅限中文,
  • 多语言 BERT(通常称为 mBERT):在同一型号中支持 104 种语言。

mBERT 是一个有趣的选择:BERT 的惊人能力适用于大多数现有的语言……等等,事情没那么简单。

训练多语言模型的技巧是首先在语言之间有一个共享的词汇表。一开始没什么意义,每种语言都有自己的词汇。

根据自然语言处理中关于 BPE 的文献,他们试图找到共享的子词,而不是整个词。他们使用句子片段来分析多语言数据集并找到重要的子词,这意味着一个词可以分成几个子词。有了这些子词,你可以试着为每一个标记学习一个单一的表示,由几种语言共享。

聪明而美丽的想法,但它真的有效吗?

在英语任务中,伯特的表现似乎低于英语伯特。到处都可以看到,小语种的开箱即用性能并没有那么高。然后出现了多篇论文《⁴》,表明通过聪明地使用单语模特⁵.,mBERT 的表现可以被显著击败

然而,mBERT 的承诺是美好的(一个模型适合几乎所有的语言),因为你需要疯狂的资源来训练一个端到端的基于 transformer 的单语模型,大多数从业者都坚持尝试利用 mBERT。

这就是我们最初这样做的原因:我们试图在我们的商业法律案件数据集上利用 mBERT。我们在不到一天的时间里对模型进行了 78 个纪元的微调。

结果如下:

mBERT NER scores

这些结果很低,特别是 77%的地址召回率相当低。此外,该模型要求遵守 512 个令牌的限制,并且在内存占用量很大的情况下训练和推断非常慢。

卡门贝干酪,当权力有了一个有趣的名字

自从 BERT 第一次发布以来,事情略有变化,很少有非英语的 BERT 模型被发布,其中一个是法语的: camemBERT ⁶(以一种令人愉快的奶酪命名)。这种架构的灵感很大程度上来自于 BERT 的一个演变,叫做 RoBERTa

有趣的是,这篇论文包括了一个在 NER 的经验,并且报告了一个比适用于法语的 mBERT 大的改进。

在我们的例子中,数据比来自法国树库的更脏,因为它们来自不完善的 OCR 步骤。

训练持续 9 小时 30 分(40 个时代)。我们的结果如下:

camemBERT NER scores

它比 mBERT 好得多,并且在某些实体(如 ADDRESS)上比 Flair 稍好。这与卡门贝干酪论文的研究结果一致(略好于 2018 年 LSTM-SOTA 通用报告格式)。

此外,还有 BERT 的局限性:

  • 512 令牌限制,
  • Flair 的内存占用要低得多,使得在推断过程中有更大的批量成为可能。

结论

在该基准测试中,我们在真实数据集上比较了 4 个模型,我们的主要观察结果如下:

  • 凭借其原始架构, spaCy 提供了比其他测试模型低得多的性能,数据扩充模式是不够的,
  • mBERT 是一个巨大(缓慢)的变压器模型。在我们的 NER 任务中,它并没有转化为高分,这个观察结果与来自卡门贝干酪论文的发现一致,
  • Flair 和 camemBERT 提供了类似的结果(camemBERT稍好一些),但是 camemBERT 在文本大小方面有一个恼人的限制(512 令牌限制),并且在训练和推理上都比 Flair 慢。

我们的结论是,在我们的情况下,对于这个数据集,Flair 仍然是最佳选择。此外,我们认为,如果有更大的数据集用于预训练(或在领域数据中进行微调),结果可能会更高,正如我们的最高法院在其 NER 论文中所发现的那样。

事实上,与仅依赖于法语维基百科的 Flair 语言模型相比, camemBERT 似乎已经在 138 Gb 的未压缩文本上进行了预训练(小了 1 个数量级以上)。

我们想强调的是,以上分数并不是我们能得到的最高分,而是我们现成的分数。决定投资和改进什么算法就够了。

真实的生产设置包括例如类似于上面引用的最高法院的工作的后处理步骤,其大幅度降低了错误率。

我们不认为我们的发现会推广到其他任务,如分类。基于字符的语言模型非常擅长 NER,因为后缀和前缀是强大的功能,但在分类方面,我们预计 camemBERT 会轻松击败 Flair 语言模型。

此外,与 Multifit 论文一致,它也表明从业者在与 mBERT 合作之前应该三思。如果存在的话,使用更简单的单语语言模型似乎更明智。

如前所示, spaCy 型号与今天的大型型号性能相比似乎有限。作者们正在研究它。似乎所有的模式都在朝着同一个方向前进,老实说我等不及结果了!

A discussion following our previous article comparing Flair and spaCy

最后,我要感谢来自 Lefebvre Sarrut 的 SumiJonathanMatthieu (及其整个数据团队)和 Vincent 对项目和/或本文评论的贡献:-)

笔记

1:买下所有这些将花费数百万欧元:每项裁决 4.93 欧元(https://www . infogreffe . fr/activite-judiciaire/rechercher-une-affaire . html),而商业法院在 2018 年已经发布了 137K 项裁决(http://www.justice.gouv.fr/art_pix/CC%202019_V8.pdf,第 11 页)

[2]:Tribunaux de commerce:l ' overval cadeau d ' infogreffeàdoctrine . frhttps://www . lalettrea . fr/entreprises _ tech-et-telecoms/2018/06/25/Tribunaux-de-commerce-l-overval-cadeau-d-infogreffe-a-doctrinefr,108314593-ge0

3:Doctrine veut centrazer tout l ' information juridique disp ible pour-les-professionals du droit-0907-1173997 . html****

[4]:Piratage massif de données au tribunalhttps://www . lemonde . fr/economie/article/2018/06/28/Piratage-massif-de-donnes-au-tribunal _ 5322504 _ 3234 . html

[5]:pour quoi doctrine . fr est l chépar les greffeshttps://www . lalettrea . fr/entreprises _ tech-et-telecoms/2018/09/27/pour quoi-doctrine fr-est-lache-par-les-greffes,108325460-evl

[6]:未来的《司法组织法》第 r . 433–3 条明确将商事法院的判决纳入我们最高法院之一将维护的未来开放数据库,https://www . dalloz-actual ite . fr/flash/open-data-des-decisions-de-justice-projet-de-decret #。XeTUzJNKhaQ

[7]: 公开数据和司法裁决的区别https://www . dalloz-actual ite . fr/flash/distinction-entre-l-open-data-et-l-acces-aux-decisions-de-justice

[8]:数据集由原始法律判决组成,所有个人信息都将被删除。它不能被分享,因为它会违反 GDPR 教。

[9]: 部署主动学习的实际障碍https://www.aclweb.org/anthology/D19-1003.pdf

[10]: 用于序列标记的上下文字符串嵌入https://alanakbik.github.io/papers/coling2018.pdf

[11]: 科萨伯特https://medium.com/dissecting-bert

[12]:支持语言列表,https://github . com/Google-research/Bert/blob/master/multilingual . MD

[13]: 比如这个 Reddit 线程https://www . Reddit . com/r/language technology/comments/bsfb8s/what _ has _ your _ experience _ using _ multilingual/

[14]: MultiFiT:高效的多语言语言模型微调,【https://arxiv.org/abs/1909.04761】T4

[15]:准确地说,多语言模型(激光来自脸书)被用来引导事物,但是最终任务是由单语模型执行的。

[16]: 卡门贝干酪:一种美味的法语语言模型https://arxiv.org/pdf/1911.03894.pdf

基准分类编码器

原文:https://towardsdatascience.com/benchmarking-categorical-encoders-9c322bd77ee8?source=collection_archive---------4-----------------------

大多数表格数据集包含分类要素。最简单的方法就是用标签编码器对它们进行编码。这很简单,但有时不准确。

在这篇文章中,我想展示可以“开箱即用”的更好的方法(感谢类别编码器 Python 库)。我将从描述编码分类变量的不同策略开始。然后,我将向您展示如何通过单次和双次验证来改进这些功能。本文的最后部分专门讨论基准测试的结果(这也可以在我的 GitHub repo—categoricalencoding benchmark中找到)。

以下材料描述了二元分类任务,但所有公式和方法都可以应用于多类分类(只要它可以表示为二元分类)和回归。

TL;速度三角形定位法(dead reckoning)

  1. 天下没有免费的午餐。你必须尝试多种类型的编码器,以找到最适合你的数据;
  2. 然而,最稳定和准确的编码器是基于目标的编码器,具有双重验证:Catboost 编码器、James-Stein 编码器和 target 编码器;
  3. encoder.fit_transform() 在整个列车上是一条无路可走的路:事实证明,单一验证是比常用的无验证好得多的选择。如果你想获得稳定的高分,双重验证是你的选择,但要记住,这需要更多的时间来训练;
  4. 正则化对于基于目标的编码器是必须的。

分类编码器

如果你想更好地理解分类编码,我建议你拿起笔和纸,用我下面提供的公式进行计算。这不会花太多时间,但是真的很有帮助。在公式中,我将使用以下参数:

  • yy+ —观察总数和阳性观察总数(y= 1);
  • 、易——类别和目标的第 i 个值;
  • nn+ —一个分类列的给定值的观察数和正观察数(y= 1);
  • a —正则化超参数(由用户选择)previous—目标的平均值。

示例训练数据集如下所示:

Example train dataset on the left and test dataset on the right

  • y=10,y+= 5;
  • ni="D ",yi =数据集第 9 行 1(最后一次观察)
  • 对于类别 B : n=3,n+= 1;
  • 先验=y+/y= 5/10 = 0.5。

记住这一点,让我们从简单的开始,逐渐增加编码器的复杂性。

标签编码器(LE)或顺序编码器(OE)

Category representation — Label Encoding

处理类别最常见的方法是简单地用一个数字映射每个类别。通过应用这样的转换,模型会将类别视为有序的整数,这在大多数情况下是错误的。这种转换不应该“按原样”用于几种类型的模型(线性模型、KNN、神经网络等)。).应用梯度增强时,只有当列的类型被指定为 【类别】 时才能使用:

df[“category_representation”] = df[“category_representation”].astype(“category”)

标签编码器中的新类别被替换为“-1”或无。如果您正在处理表格数据,并且您的模型是梯度增强的(尤其是 LightGBM 库),LE 是在内存方面处理类别的最简单有效的方法(python 中的类别类型比对象类型消耗的内存少得多)。

一键编码器(OHE)(虚拟编码)

Category representation — One-Hot-Encoding

One Hot 编码是处理分类列的另一种简单方法。它采用标签编码的分类列,然后将该列拆分为多个列。根据哪一列有什么值,数字会被 1 和 0 替换。

OHE 扩展了数据集的大小,这使它成为内存效率低下的编码器。有几种策略可以克服 OHE 的内存问题,其中之一就是使用稀疏而非密集的数据表示。

和编码器(偏差编码或 E 效果编码

Category representation — Sum Encoding

Sum Encoder 将分类列的给定级别的因变量(目标)的平均值与目标的总体平均值进行比较。求和编码与 OHE 非常相似,两者都常用于线性回归(LR)类型的模型中。

然而,它们之间的区别在于对 LR 系数的解释:在 OHE 模型中,截距代表基线条件的平均值,系数代表简单效应(一个特定条件与基线之间的差异),而在 Sum 编码器模型中,截距代表大平均值(所有条件),系数可以直接解释为主要效应。

赫尔默特编码器

Category representation — Helmert Encoder

赫尔默特编码是用于回归的第三种常用类型的分类编码,另外两种是 OHE 和求和编码。它将分类变量的每个级别与后续级别的平均值进行比较。因此,第一个对比将“A”的因变量的平均值与分类列(“B”、“C”、“D”)的所有后续级别的平均值进行比较,第二个对比将“B”的因变量的平均值与所有后续级别(“C”、“D”)的平均值进行比较,第三个对比将“C”的因变量的平均值与所有后续级别的平均值进行比较(在我们的示例中,只有一个级别—“D”)。

这种类型的编码在某些情况下很有用,例如,分类变量的级别是按从低到高或从最小到最大的顺序排列的。

频率编码器

Category representation — Frequency Encoding

频率编码统计类别在数据集中出现的次数。测试数据集中的新类别用“1”或测试数据集中的类别计数进行编码,这使得这个编码器有点棘手:对不同大小的测试批次的编码可能不同。你应该事先想好,把训练的预处理做得尽可能接近测试。

为了避免这种问题,您也可以考虑使用一种频率编码器变体—滚动频率编码器(RFE)。RFE 统计一个类别在给定观察值的最后 dt 时间步出现的次数(例如, dt = 24 小时)。

然而,当分类列具有“长尾”时,频率编码和 RFE 特别有效,例如,在数据集中有几个频繁值,而其余的值只有几个例子。在这种情况下,频率编码将捕捉稀有列之间的相似性。

目标编码器

Category representation — Target Encoding

由于 Kaggle 竞争,目标编码可能已经成为最流行的编码类型。它需要关于目标的信息来编码类别,这使得它非常强大。编码类别值根据以下公式计算:

这里,MDL—leaf 中的最小数据(样本), a —平滑参数,代表正则化的能力。 mdla 的推荐值为 1 到 100 范围内的。类别的新值和在训练数据集中仅出现一次的值被先前的值替换。

目标编码器是一个强大的工具,但是它有一个巨大的缺点——目标泄漏:它使用关于目标的信息。由于目标泄漏,模型过度拟合训练数据,导致不可靠的验证和较低的测试分数。为了减少目标泄漏的影响,我们可以增加正则化(如果没有不可靠的验证,很难调整那些超参数),将随机噪声添加到训练数据集中的类别表示中(某种增强),或者使用双重验证。

m 估计编码器

Category representation — M-Estimate Encoder

M-Estimate 编码器是目标编码器的简化版本。它只有一个超参数——m,代表正则化的力量。 m 的值越高,收缩越强。 m 的推荐值在 1 到 100 的范围内。

在不同的资料中,你可能会找到 M-估计量的另一个公式。分母中不是 y+ 而是 n 。我发现这样的表现有相似的分数。

UPD(2019 年 7 月 17 日):分类编码器库中的 M 估计编码器公式包含一个 bug 。右边的分母应该有 n 。然而,这两种方法都显示出很好的成绩。下面的基准测试是通过“错误的”公式完成的。

证据权重编码器

Category representation — Weight Of Evidence Encoder

证据权重是信用评分中常用的基于目标的编码器。它是对一个分组区分好风险和坏风险(违约)的“强度”的度量。它是根据基本比值比计算出来的:

*a = Distribution of Good Credit Outcomes
b = Distribution of Bad Credit Outcomes
WoE = ln(a / b)*

然而,如果我们按原样使用公式,可能会导致目标泄漏和过度拟合。为了避免这种情况,引入正则化参数 a ,并以如下方式计算 WoE:

詹姆斯-斯坦编码器

Category representation — James-Stein Encoder Encoder

James-Stein 编码器是一种基于目标的编码器。这种编码器的灵感来自 James–Stein estimator,这种技术以 Charles Stein 和 Willard James 命名,他们简化了 Stein 在 1956 年提出的原始高斯随机向量均值估计方法。Stein 和 James 证明了存在比“完美”(即均值)估计量更好的估计量,这似乎有点自相矛盾。然而,当有几个未知总体均值——而不是一个时,James-Stein 估计量优于样本均值。

詹姆斯-斯坦编码器背后的想法很简单。类别 k 的平均目标估计值可根据以下公式计算:

编码旨在通过将类别的平均目标值(金额的第一个成员)向更中心的平均值(金额的第二个成员)收缩,来改进对类别的平均目标值(金额的第一个成员)的估计。公式中唯一的超参数是 B — 收缩的力量。可以理解为正则化的力量,即 B 的值越大,全局均值的权重越大(欠拟合),而 B 的值越小,条件均值的权重越大(过拟合)。

选择 B 的一种方法是通过交叉验证将其调整为超参数,但 Charles Stein 提出了另一种解决问题的方法:

直观地,该公式可以在以下意义上看到:如果我们不能依赖于对目标类别均值的估计(它具有高方差),这意味着我们应该为全局均值分配更大的权重。

等等,但是如果我们不能依靠均值的估计,我们怎么能相信方差的估计呢?嗯,我们可以说所有类别之间的方差是相同的,等于 y 的全局方差(这可能是一个很好的估计,如果我们没有太多独特的分类值;它被称为混合方差混合模型,或者用标准差的平方代替方差,这惩罚了小的观察计数(独立模型)。

看起来很公平,但是 James-Stein 估计量有一个很大的缺点——它只针对正态分布定义(对于任何分类任务都不是这样)。为了避免这种情况,我们可以像在 WoE Encoder(默认情况下使用,因为它很简单)中那样用对数优势比转换二进制目标,或者使用 beta 分布。

留一编码器

Category representation — Leave-one-out Encoding

留一编码(LOO 或 LOOE)是基于目标的编码器的另一个例子。该方法的名称清楚地表明了这一点:如果从数据集中删除了观察值 j ,我们将为观察值 j 计算类别 k 的平均目标:

在对测试数据集进行编码时,类别被训练数据集中类别 k 的平均目标替换:

与所有其他基于目标的编码器一样,LOO 的一个问题是目标泄漏。但是当涉及到 LOO 时,这个问题变得非常严重,因为我们可以通过进行单次分割来完美地对训练数据集进行分类:类别 k 的最佳阈值可以通过以下公式来计算:

LOO 的另一个问题是训练样本和测试样本中的值之间的偏移。你可以从上面的图片中观察到它。在训练样本中,类别“A”的可能值为 0.67 和 0.33,而在测试样本中为 0.5。这是训练和测试数据集中计数数量不同的结果:对于类别“A ”,分母等于测试的 n ,训练数据集的 n-1 。这种转变可能会逐渐降低基于树的模型的性能。

Catboost 编码器

Category representation — CatBoost Encoder

Catboost 是最近创建的基于目标的分类编码器。它旨在克服 LOO 中固有的目标泄漏问题。为了做到这一点,Catboost 的作者引入了“时间”的概念:数据集中观察值的顺序。显然,每个示例的目标统计值只依赖于观察到的历史。为了计算训练数据集中观测值 j 的统计量,我们可以只使用观测值,这些观测值是在观测值 j 之前收集的,即 i≤j:

为了防止过度拟合,对训练数据集的目标编码过程在数据集的混洗版本上重复几次,并对结果进行平均。测试数据的编码值的计算方式与 l00 编码器相同:

Catboost“动态”编码是 CatBoost 的核心优势之一,这是一个用于梯度增强的库,当 Yandex 展示它时,它在几个表格数据集上显示了最先进的结果。

验证方法

模型验证可能是机器学习最重要的方面。在处理包含分类变量的数据时,我们可能希望使用三种类型的验证之一。无验证是最简单的方法,但也是最不准确的方法。双重验证可以显示很高的分数,但它像乌龟一样慢。单一验证是前两种方法的结合。

这一节将详细讨论每一种验证类型。为了更好地理解,对于每种类型的验证,我添加了管道的框图。

无验证

在无验证的情况下,单个编码器适合整个列车数据。数据集的验证和测试部分用同一个编码器处理。作为最简单的一种,这种方法被广泛使用,但它会导致训练过程中的过度拟合和不可靠的验证分数。最明显的原因是:对于目标编码器,无验证导致训练和测试部分之间的转移(参见 LOO 编码器中的例子);测试数据集可能包含新的分类值,但在训练期间,训练和验证样本都不包含它们,这就是为什么:

  • 模型不知道如何处理新的类别;
  • 训练样本和测试样本的最佳树数量可能不同。

单一验证

单一验证是执行验证的更好方式。通过使用单一验证,我们克服了无验证的问题之一:验证和测试数据集之间的转换。在这种方法中,我们为训练数据的每个文件夹安装单独的分类编码器。每个折叠的验证部分以与测试数据相同的方式处理,因此变得更加相似,这积极地影响超参数调整。单次验证得到的最优超参数比无验证得到的最优超参数更接近测试数据集的最优超参数。

注意:虽然我们正在调整超参数,即一些树,但在数据的验证部分,验证分数无论如何都会稍微偏高。测试分数也是如此,因为编码器的类型也是管道的超参数。我通过加大测试(通常数据的 40%)来减少过度拟合的影响。

单一验证的另一个好处是跨折叠的多样性。通过在数据子集上拟合编码器,我们实现了类别的不同表示,这积极地影响了预测的最终混合。

双重验证

双重验证是单一验证的扩展。双重验证的管道与单一验证的管道完全相同,除了编码器部分:我们将在不同的子集上使用几个编码器,而不是为每个折叠使用一个编码器。

双重验证旨在减少第二个无验证问题——新类别的影响。这是通过将每个折叠拆分成子折叠,为每个子折叠安装单独的编码器,然后连接(在训练部分的情况下)或平均(在验证或测试部分的情况下)结果来实现的。通过应用双重验证,我们在训练数据中引入一个噪声(新的类别),作为数据的扩充。然而,双重验证有两个主要缺点:

  • 对于编码器,我们不能“照原样”使用它,它将单个类别表示为多个列(例如,OHE、求和编码器、赫尔默特编码器和后向差分编码器);
  • 双重验证的时间复杂度大约比单一验证大 k 倍( k —子文件夹数)。

基准测试实验设置

我希望你不要被理论部分弄得不知所措,还记得论文的标题。所以,让我们从这一点开始练习吧!在下一节中,我将向您展示我是如何为表格数据确定最佳分类编码器的。

数据集

我创建并测试了 pipeline ,对下表中的数据集进行了类别基准测试。除了 poverty_A(B,C) 之外的所有数据集来自不同的域;他们有不同数量的观察,以及分类和数字特征。所有数据集的目标是执行二元分类。预处理非常简单:我从数据集中删除了所有基于时间的列。剩下的不是绝对的就是数字的。

管道

整个数据集被分成训练(数据的前 60%)和测试样本(数据的剩余 40%)。测试部分在培训期间不可见,并且只使用一次——用于最终评分(使用的评分标准——ROC AUC)。没有对整个数据的编码,没有伪标记,没有 TTA 等。在训练或预测阶段被应用。我希望实验尽可能接近生产环境。

在训练-测试分割之后,训练数据通过混洗和分层被分割成 5 个折叠。之后,其中 4 个用于拟合编码器(对于无验证的情况-如果在分割之前拟合到整个训练数据集,则为编码器)和 LightGBM 模型(LlightGBM-来自微软的用于梯度增强的库),另外 1 个折叠用于早期停止。这个过程重复了 5 次,最后,我们有了 5 个经过训练的编码器和 5 个 LGB 模型。LightGBM 模型参数如下:

"metrics": "AUC", 
"n_estimators": 5000, 
"learning_rate": 0.02, 
"random_state": 42,
"early_stopping_rounds": 100

在预测阶段,用每个编码器处理测试数据,并通过每个模型进行预测。然后对预测进行排名和求和( ROC AUC metric 不关心预测是平均还是求和;唯一重要的是顺序)。

结果

本部分包含实验的处理结果。如果您想查看每个数据集的原始分数,请访问我的 GitHub 存储库—CategoricalEncodingBenchmark

为了确定最佳编码器,我对每个数据集的 ROC AUC 分数进行了缩放(最小-最大缩放),然后对编码器的结果进行了平均。获得的结果代表每个编码器的平均性能分数(越高越好)。表 2.1–2.3 显示了每种验证类型的编码器性能分数。

为了确定最佳验证策略,我比较了每种验证类型的每个数据集的最高得分。得分改进(数据集的最高分和编码器的平均分)如下面的表 2.4 和 2.5 所示。

  • 每个数据集和每种验证类型的最佳编码器是不同的。然而,在无验证实验中,非目标编码器(头盔编码器和总和编码器)占主导地位。这是一个非常有趣的发现,因为最初这些类型的编码器主要用于线性模型。
  • 对于单个验证的情况,最好的编码器是 CatBoost 编码器和序数编码器,这两种编码器在无验证实验中的性能得分相对较低。
  • 具有双重验证的基于目标的编码器(James-Stein、Catboost、Target、LOO、WOE)显示了所有类型的验证和编码器的最佳性能分数。我们现在可以称之为处理分类变量的最稳定和最准确的方法。
  • 通过在训练数据中引入噪声来提高基于目标的编码器的性能。在 LOO 编码器中可以清楚地看到这一点——它在无验证和单验证中都是最差的编码器,与第二差的编码器差距巨大,但在双重验证中却是最好的编码器之一。双重验证(或正则化的另一种变体)是所有基于目标的编码器所必须的。
  • 通过增加验证的复杂性降低了频率编码器的结果。这是因为测试中新类别的频率在整个测试中计算,而在单次验证期间,它在 1/5 的训练数据集(训练数据集中的 5 个折叠)中计算,在双重验证期间,在 1/25 的训练数据集(训练数据集中的 5 个折叠,每个折叠中的 5 个子折叠)中计算。因此,测试数据中的最大频率大于训练和验证数据样本。你记得我告诉过你菲很狡猾吗?这就是原因。

感谢

我要感谢安德烈·卢基扬科、安东·比留科夫和丹尼尔·波塔波夫对工作成果进行了富有成效的讨论。

参考

  1. 分类变量的 R 库对比编码系统
  2. 类别编码器文档
  3. 分类变量的对比编码系统
  4. 回归中分类变量的编码方案回归分析中分类变量的编码系统
  5. 证据权重(WoE)介绍性概述
  6. 詹姆斯-斯坦估计量詹姆斯-斯坦估计量:定义,公式统计学中的斯坦悖论
  7. 分类和预测问题中高基数分类属性的预处理方案
  8. H2O 无人驾驶 AI 的特色工程作者 Dmitry Larko
  9. CatBoost:带有分类特征的无偏增强在 CatBoost 中将分类特征转换为数字特征
  10. 双重验证的想法受到了斯坦尼斯拉夫·谢苗诺夫在“法国巴黎银行”上的演讲的启发

用 Wordbatch 测试 Python 分布式人工智能后端

原文:https://towardsdatascience.com/benchmarking-python-distributed-ai-backends-with-wordbatch-9872457b785c?source=collection_archive---------5-----------------------

三种主要后端调度程序的比较:Spark、Dask 和 Ray

走向分布式人工智能

在过去的几年里,Python 已经成为数据科学和人工智能的通用语言,所有著名的深度学习框架(Keras、Pytorch、MXNet)都使用 Python 作为主要的接口语言。与竞争语言相比,Python 在 DS&AI 的几乎每个方面都达到或超过了对手:最新的机器学习算法及其高效实现(Scikit-Learn、LightGBM、XGBoost)、数据操纵和分析(Pandas、cuDF)、高效的数值计算库(Numpy、PyPy、Numba)、GPU 计算(CuPY)和 web API 编程(Flask、Celery)。

Python 的致命弱点是它在并行多线程和多进程工作负载方面的弱点,这是由于全局解释器锁(GIL)是其核心设计的一部分。这在 Python 阵营中产生了变通解决方案,以及更强调并行性的替代语言,如 GoLang。硬件领域正在进行的军备竞赛加速了对并行性的需求:消费者 CPU 在几年内从 4 核增加到 32 核(AMD 2990WX ),而价格合理的云计算节点现在每个提供 224 核(Amazon u-6tb1.metal)。

对于人工智能来说,并行性的需求不仅仅是单个工作站或计算节点,而是协调分布在潜在的数千个计算节点上的人工智能处理管道。与 CPU 内核的变化类似,本地和云使用的网络传输速度已经从 1 Gb/s 发展到商用 10–100 Gb/s 连接。直到最近,这种类型的大数据技术大多基于 Hadoop 等 Java 框架,但软件和硬件的变化带来了新类型的解决方案,包括三种主要的 Python 分布式人工智能处理框架:PySpark、Dask 和 Ray。

分布式批处理框架

Apache Spark 和它的 Python 接口 PySpark 是最老的框架,最初的 GitHub 版本可以追溯到 2010 年 10 月 4 日。Spark 确立了自己作为主要大数据技术之一的地位,在企业领域获得了广泛采用。它提供了 Map-Reduce 编程范式的扩展,通过将一个较大的任务映射到一组分发给工作人员的小批量(Map)来解决批处理任务,并在每个小批量完成后合并结果(Reduce)。Spark 处理 Map-Reduce 计算管道的有向无环图(DAG ),在处理 DAG 的整个过程中保持数据分布在工人之间。任务图是功能性定义的,任务在优化 DAG 计算顺序后被延迟执行。

Dask 和 Ray 都建立在 Spark 对 DAG 进行并发功能评估的中心思想上,数据在整个过程中保持分布。Dask 及其调度程序后端分布式是一个更新的框架,最初的 GitHub 版本是在 2015 年 1 月 29 日发布的。Spark 是为 Java 和 Scala 编写的,而 Dask 是为 Python 编写的,提供了丰富的分布式类。Dask 还提供了更丰富的底层 API,支持对 AI 模型的分布式训练至关重要的 actor 类。

Ray 是最新的框架,最初的 GitHub 版本发布于 2017 年 5 月 21 日。和 Dask 一样,Ray 也有 Python 优先的 API 和对 actors 的支持。它有几个高性能的优化,使其更有效。与 Spark 和 Dask 不同,任务会在每个节点内急切地执行,因此每个工作进程在收到所需数据后会立即启动。worker 节点中的数据使用 Apache Arrow 对象存储,这提供了在节点上工作的所有进程之间的对象零拷贝共享。工作节点有自己的本地调度程序,进一步减少了全局调度程序的开销。

Wordbatch

这三个框架在它们的调度器引擎的设计和实现上有很大的不同:序列化、传输、调度、配置需求、内存需求等。对于给定的复杂任务,很难说哪种引擎工作得最好,如果不是不可能的话。对于某些任务,特定的框架根本不起作用。Spark 缺少演员,使得模特的大规模训练变得复杂。Dask 不序列化复杂的依赖关系。因此,从性能和可行性来看,测试给定任务的每个框架并选择一个有效的框架是很有用的。

Wordbatch library v. 1.4 使用可切换调度器后端对管道进行批处理。它的 orchestrator 类批处理程序保持对后端句柄的引用,并处理任务到小批处理的映射和减少结果。调度器后端是可交换的,因此如果一个后端不能处理一个处理任务,任何其他后端都可以通过替换批处理程序对象的 backend 和 backend_handle 属性来交换。它支持本地(串行、线程、多处理、韩一菲)和分布式后端(Spark、Dask、Ray)。分布式框架也有类似的叫法,数据尽可能分布在整个管道中。

Wordbatch 还附带了一组管道和类,为基于文本的机器学习提供了全套工具,可以作为其他领域处理的模板。如果需要,Wordbatch 类可以独立调用 Batcher 上的 Map-Reduce 操作,并支持管道中的分布式存储和使用 fit_partial()方法的流处理。

基准设置

我们可以使用 Wordbatch 作为中立的基准来测试三个分布式框架,以及作为基线的非分布式后端。为了使比较简单,我们将在两种硬件设置下使用两个基本管道。这两项任务都使用了来自 http://times.cs.uiuc.edu/~wang296/Data/猫途鹰评论数据集的 128 万条评论。

基准测试脚本的完整版本可从https://github . com/anttttti/word batch/blob/master/scripts/backends _ benchmark . py获得。对于这两个任务,测试脚本如下初始化批处理程序:

*from wordbatch.batcher import Batcher
batcher = Batcher(procs=16, minibatch_size=5000, backend=backend[0], backend_handle=backend[1])*

这里“procs”是使用的进程数,“minibatch_size”是每个 mini-batch 中要处理的数据行数,“backend”是后端的名称,“backend_handle”给出了批处理程序进行通信的 API 句柄。

第一个管道 ApplyBatch 在每个小批量评论上运行 Scikit-learn 哈希矢量器,并返回哈希特征的简化稀疏矩阵。

*from sklearn.feature_extraction.text import HashingVectorizer
from wordbatch.pipelines import ApplyBatch
hv = HashingVectorizer(decode_error=’ignore’, n_features=2 ** 25, preprocessor=normalize_text, ngram_range=(1, 2), norm=’l2')
output = ApplyBatch(hv.transform,batcher=batcher).transform(texts_chunk)*

第二个流水线 WordBatch 是一个完整的文本处理流水线,执行以下连续步骤:1)文本规范化,2)拼写校正和词干化,3)词典计数,4)词袋特征提取和 TF-IDF 加权。拼写校正和字典计数步骤都执行它们自己的 Map-Reduce 操作来计算词频表,并且拼写校正和特征提取步骤需要向每个工作者发送字典。

*from wordbatch.pipelines import WordBatch
from wordbatch.extractors import WordBag
from wordbatch.transformers import Tokenizer, Dictionary
wb = WordBatch(normalize_text=normalize_text,
 dictionary=Dictionary(min_df=10, max_words=1000000),
 tokenizer=Tokenizer(spellcor_count=2, spellcor_dist=2, raw_min_df= 2, stemmer=stemmer),
 extractor=WordBag(hash_ngrams=0, norm= ‘l2’, tf= ‘binary’, idf= 50.0),
 batcher=batcher)
output = wb.fit_transform(texts_chunk)*

第一个硬件设置是使用单个 i9–9900k CPU,8 个内核和 64GB DDR4 RAM,可以处理所有涵盖的测试。第二个设置使用直接 10 Gb/s 以太网连接,通过 18 核 i9–7980 xe CPU 连接一个额外的工作节点。使用的操作系统是 Ubuntu 18.04.2 LTS,库版本是 pyspark 2.4.1、ray 0.7.0 和 distributed 1.28.1。

结果

Benchmark 1. Distributing Scikit-Learn HashingVectorizer on a single node

对于在单个节点上并行化哈希矢量器的简单任务,与运行单个串行进程相比,所有并行框架都获得了大致线性的加速。对于最大的 1.28M 文档,串行处理需要 256 秒,而多处理需要 36 秒。有趣的是,Ray 其实比多处理更快,用了 33s,而 Spark 用了 50s。

Benchmark 2. Distributing the WordBatch feature extraction pipeline on a single node

WordBatch 管道更复杂的任务显示了令人惊讶的结果。Spark、Ray 和 multiprocessing 再次显示,随着数据的增加,线性加速保持不变,但韩一菲和 Dask 在并行化任务方面都有困难。与连续花费 460 秒获取 128 万份文档相比,Ray 再次以 91 秒的速度做到了这一点。韩一菲和 Dask 的时间使用量都在增加,与串行时间使用量大致相同,但随着数据量的增加,时间使用量可能会超过串行时间使用量。这种奇怪行为的可能原因是进程之间缺乏共享,并且在这个任务中需要向每个工作人员发送两次字典。随着数据的增加,字典变得越来越大,并且不能有效地共享辅助数据的开销超过了并行化带来的好处。这是一个令人惊讶的结果,特别是因为向工人发送共享数据是 AI 管道中的一个基本操作。

Benchmark 3. Distributing HashingVectorizer using an additional node

转到第二个硬件设置,增加了 18 个超过 10 Gb/s 的内核,所有三个分布式系统都从增加的节点中受益。然而,Spark 在处理最大的 1.28M 文档任务时遇到了麻烦,因为它需要更大的内存,并且在接近配置的内存限制的情况下运行。在实践中,Spark 需要对其组件进行大量的配置,这一直是用户感到沮丧的一个原因。在最好的情况下,额外的节点为 Spark 提供了 22%的加速。Dask 和 Ray 的性能要好得多,对于 128 万个文档,Dask 和 Ray 的加速分别为 32%和 41%。与单节点相比,加速也随着数据大小的增加而增加,并且在最大测试大小时似乎远未接近饱和。

Benchmark 4. Distributing WordBatch pipeline with an additional node

用额外的节点测试 WordBatch 管道,我们看到 Dask 并没有获得多少收益。当使用额外的节点时,其有效处理辅助数据的问题似乎变得更加复杂,因此在最大的 1.28M 文档条件下,我们只能获得从 457 秒到 420 秒的加速,并且加速随着更大的任务而不断降低。Spark 和 Ray 都可以在这个任务中更好地使用额外的节点,在 0.64M 文档时,Spark 和 Ray 的最大加速分别为 38%和 28%。由于更好地利用了额外的节点,Spark 与 Ray 在性能上几乎不相上下,并且很有可能因为更大的数据大小和更复杂的处理管道而超过 Ray。

总结想法

这些基本基准演示了分布式调度程序的一些主要属性。所有的调度器对于分布 Python 工作负载都是有用的,但是有些并不适合每个任务。实际应用将涉及大型集群上更复杂的管道,但这将使简单的比较变得复杂,因为:配置调度程序的选择,关于如何实现共享数据和远程类(如 actors)的设计决策,以及如何使用 GPU 和其他非 CPU 处理器。

作为初步结论,Ray 似乎是最有前途的框架。它在单个节点上的工作速度比 Python 标准多处理快 10%左右,并且在所有情况下都能很好地使用额外的节点。与 Spark 不同,集群配置非常少,并且支持参与者。与 Dask 不同,它很好地序列化了嵌套的 Python 对象依赖关系,并在进程之间高效地共享数据,线性扩展复杂的管道。与单个串行进程相比,具有额外节点的 Ray 在分布式哈希矢量器上提供了 12.9 倍的加速,在更复杂的任务上提供了 6.7 倍的加速。

可用的硬件对调度程序的性能也有很大的影响。如果此处使用 1 Gb/s 连接,额外的节点几乎没有任何优势。相比 10 Gb/s,100 Gb/s 将增加额外节点带来的好处,并改变测试后端之间的结果。与 Ray 相比,Dask 尤其会从 100 Gb/s 中获益更多。如果像 Spark 和 Hadoop 一样从分布式存储中获取数据,这将在一定程度上减少对高带宽网络的依赖。然而,大多数实际的管道将进行需要高带宽的数据传输。随着更多节点的出现,这些框架都应该使用 100 Gb/s,并且 AI 管道应该被规划为最小化网络流量并最大化分布式核心的使用。

链接

[## 阿帕奇/火花

阿帕奇火花。在 GitHub 上创建一个帐户,为 apache/spark 开发做出贡献。

github.com](https://github.com/apache/spark) [## 达斯克/达斯克

带有任务调度的并行计算。在 GitHub 上创建一个帐户,为 dask/dask 开发做贡献。

github.com](https://github.com/dask/dask) [## 光线-投影/光线

用于构建和运行分布式应用程序的快速而简单的框架。-射线-项目/射线

github.com](https://github.com/ray-project/ray) [## anttttti/Wordbatch

用于分布式人工智能处理管道的 Python 库,使用可切换调度器后端。- anttttti/Wordbatch

github.com](https://github.com/anttttti/Wordbatch) [## 与 Spark - Dask 1.2.2 文档的比较

它们都可以部署在相同的集群上。大多数集群被设计为支持许多不同的分布式系统…

docs.dask.org](http://docs.dask.org/en/stable/spark.html) [## 与 dask 第 642 期射线-项目/射线的比较

ray 看起来是个有趣的项目!我看到了与 dask (http://dask.pydata.org)的一些相似之处,特别是对于 ad-hoc…

github.com](https://github.com/ray-project/ray/issues/642)

Python NLP 标记化器的基准测试

原文:https://towardsdatascience.com/benchmarking-python-nlp-tokenizers-3ac4735100c5?source=collection_archive---------6-----------------------

让我们为 NLP 任务找到最快的记号赋予器

我喜欢构建和编写关于词袋分类模型的,但讨厌在我有大量文本要分析时等待分词器执行。记号赋予器是一个简单的函数,它将一个字符串分解成一系列单词(即记号),如下所示:

因为我已经在 NLP 领域工作了几年,所以我遇到了一些不同的符号化函数。在这篇博文中,我将对包括 NLTK、spaCy 和 Keras 在内的一些标记化工具进行基准测试(即计时)。

TLDR: 不要使用 NLTK 的 word_tokenize,使用 NLTK 的 regexp_tokenize

设置

在这篇博文中,我们将对一些不同的记号赋予者进行计时。显然,时间将取决于具体的计算机,但一般来说,我们正在寻找一个表现最好的。让我们从导入几个包开始。

我们将使用 Python 3.6,其他相关包的版本如下所示:

数据集

我是一名医疗保健数据科学家,因此在这篇博文中,我将使用公开提供的 MIMIC III 数据集,这是一组在马萨诸塞州波士顿的 Beth Israel Deaconess 医疗中心收集的经过身份验证的医疗数据。如果你想访问这个数据集,你可以遵循我的指示这里。让我们将数据加载到熊猫数据框架中。

这里我们将使用 MIMIC III 提供的 NOTEEVENTS.csv,它目前拥有超过 200 万条来自一系列临床记录类别的记录,包括出院总结、医生、会诊、药房、社会工作者、放射、护理等。注释包含在“文本”列中。我们可以使用以下公式计算每个音符的字符长度:

然后我们可以绘制一个直方图,看看我们有一系列不同的长度

对于这篇文章,我们只需要一个注释列表,所以让我们从熊猫数据帧中提取它们。

为了让后面的事情变得简单,让我们打乱音符的顺序,以防模拟数据集有顺序。

干净的文本

在这篇文章中,我们将为每个自定义标记器编写一些遵循这种结构的函数

在大多数 NLP 任务中,人们倾向于以某种方式清理数据,所以我们将对每个自定义标记器使用相同的清理功能。

如果我们将所有的标点符号和数字传递给 NLTK 的word_tokenize,我们会得到下面的列表

正如我们所看到的,NLTK 在一些标点符号上进行拆分,但并不是所有的标点符号和数字都包括在内。每个自定义记号赋予器在使用标点符号拆分时可能会有略微不同的规则。

对于我的特定 NLP 分类任务,我已经决定所有标点和数字都应该替换为空格,以消除它并防止标点附近的两个单词组合。我还假设单引号倾向于包含在一个缩写中,我想将[can]变成[cant],而不是两个标记[can,t],所以我们将用空字符替换单引号。为了完成这个任务,我创建了下面的clean_text函数

为了演示如何计时一个函数,我现在将计时clean_text

其展示了不同数量的音符以 100000 个音符结束所用的时间为 12.7 秒。请注意,如果你运行几次,你可能会得到稍微不同的数字,这取决于你的计算机的状态,但为了这篇文章的目的,我们将只运行一次。

NTLK 的 word_tokenize

标准的记号赋予器之一是包含在 NLTK 包中的word_tokenize。我们可以让我们的函数使用 clean_text 并计时(节省时间)如下:

这太令人失望了:仅仅标记 100000 张纸币就需要 5 分钟。如果你在为你的 NLP 单词袋模型使用矢量器的超参数,这有点烦人。请注意,清理功能在这个记号赋予器中起着最小的作用(291 秒中的 12 秒)。让我们看看我们是否能做得更好。

正则表达式标记器

标准 python 库中内置了 re 包,它代表正则表达式。该库包含快速搜索文本的功能。下面是我们使用正则表达式的 tokenize 函数:

太神奇了,看看正则表达式运行得多快!

很明显,NLTK word_tokenize必须给标记器增加额外的功能。我很好奇它包含了什么,所以我查看了源代码。我只知道它使用了一个树库标记器。然而,通过查看源代码,我发现了 NLTK 中另一个只使用正则表达式的标记器:regexp_tokenize

NLTK 的 regexp_tokenize

regexp_tokenize的功能和时序如下所示

这与正则表达式的实现不相上下,甚至可能略胜一筹!

空间记号化器

最近一直在看几个关于 spaCy 的教程。这个包的登陆页面上写着“图书馆尊重你的时间,并尽量避免浪费时间”,这让我很受鼓舞。spaCy 非常强大,有很多内置函数来帮助命名实体识别、词性标注、单词向量等等。然而,对于我们的简单任务,我们需要做的只是标记化。

我将加载“en”spaCy 包,并禁用命名实体 region、解析器和标记器。这将删除一些我们最终并不需要的默认选项,如果我们不禁用它们,这将需要时间。

时序如下所示:

如您所见,这不如 regexp 记号化器快,但至少与 NLTK 的word_tokenize相似。显然,在 spaCy 的 tokenizer 中必须有一些额外的缺省选项(稍后将详细介绍)。

Kera 的文本转单词序列

Keras 是一个非常流行的用 Python 构建神经网络的库。它还包含一个单词 tokenizer text_to_word_sequence(虽然没有那么明显的名字)。功能和时序如下所示:

这类似于 regexp 标记化器。如果你仔细观察,你会发现它也在使用正则表达式进行拆分。类似地,它也有过滤字符的选项,这使用了我们在clean_text中使用的同样的text.translate技术。

我们可以绘制所有这些测试的时间,如下所示

Benchmark of a few tokenizers

矢量器

到目前为止,我们一直在分析执行 tokenizer 函数的时间,这表明 reg exp 方法是最好的。然而,我们还没有调查过记号赋予器产生相同的结果!对于词袋分类器,我们倾向于使用带有某种矢量器(将标记转换成数字列的函数)的标记器。这里我将使用 scikit learn 包中的 CountVectorizer 并提取词汇。请注意,我将把 max_features 设置为 None,这样我就可以得到所有可能的 vocab,因为我注意到有一个函数不匹配!

下面是获取一个记号赋予器的 vocab 的代码,并对每个记号赋予器重复。

spAcy 是唯一一个和其他人没有相同词汇的记号赋予者。我们可以用下面的例子来看看 spaCy 的集合中缺少的 vocab:

这很有趣,因为它们都是收缩,这可能意味着 spaCy 处理收缩的方式不同。我们可以通过以下内容证实这一点:

这更好地解释了为什么 spaCy 比 regexp 记号化器耗时更长。

结论

在本文中,我们对一些不同的记号赋予者进行了基准测试。我们了解到 NLTK 的 word_tokenize 和 spaCy 在默认情况下内置了额外的功能,这大大增加了执行时间。如果你需要额外的功能,你必须增加执行时间!

正则表达式似乎是当前最快的实现,并且也包含在 NLTK 和 Keras 中。如果你知道更快的解决方案,请告诉我!

因为我已经在大多数项目中安装了 NLTK,所以我将切换到 regexp_tokenize 而不是 word_tokenize!

感谢阅读!

根据现代黑盒方法,用特征提取对简单模型进行基准测试

原文:https://towardsdatascience.com/benchmarking-simple-machine-learning-models-with-feature-extraction-against-modern-black-box-80af734b31cc?source=collection_archive---------17-----------------------

Photo by Austris Augusts on Unsplash

金融行业的人喜欢逻辑回归。似乎他们并不孤单:根据 2017 年 Kaggle 调查关于人工智能和数据科学的状况对于问题“在工作中使用哪些数据科学方法?”最受欢迎的答案logistic 回归为 63.5%。在第二个位置,我们找到了拥有 49.9%的决策树。这两种方法构成了一类非常容易解释的方法。

然而,要赢得一场 Kaggle 比赛,人们通常需要采用一种更现代的类似黑盒的算法,比如 boosted trees 。在 Kaggle 的调查中,被提升的树木以 23.9%的比例仅排在第八位。
(请注意,我们在这里将重点关注结构化数据——类似电子表格的数据。对于音频和图像等非结构化输入,情况将完全不同,很可能由深度学习主导。)

我自己为银行和公司实现了许多逻辑回归,并且知道许多人喜欢简单模型的可解释性。你知道它的内部齿轮和螺栓,因此可以解释模型是如何工作的。当你有模型的用户,他们想了解它是如何工作的,或者当——例如,在金融或制药行业——你与监管者打交道时,这变得特别重要,监管者会仔细检查你的模型和你的整个开发过程。

这篇博客试图回答的问题是

在实践中,简单的可解释模型(如逻辑回归)和现代方法(如提升树)之间的性能差异真的那么大吗?之前的基准研究表明确实如此。参见例如( Lim 等人 2000 )、( Caruana 等人 2006 )、( Caruana 等人 2008 )、(bisch al 等人 2014

然而,这些基准通常是在原始数据集上运行的。在实践中,您通常对较简单的模型所做的是手动特征提取:您合并某些列,移除有噪声或高度相关的特征,并转换某些特征,以尝试使它们相对于您的目标更有用或更线性。

与应用于原始和未处理数据的现代机器学习方法相比,手工制作的简单模型之间的差异可能没有人们可能天真地认为的那么大吗?

为了回答这个问题,我们将运行一个基准测试,它将包括可解释模型的特征提取。我们将它们的性能与没有特征提取的不太可解释的现代机器学习模型进行比较。

注意,这项工作最初是作为牛津大学的硕士论文完成的。在这篇博文中,我们将集中讨论主要观点和发现。如果你对包括所有细节的更深入的讨论感兴趣,你可以在这里找到论文。

基准的设置

在下面的讨论中,我们将所有算法分为两个不同的类别:

1.白盒模型:一种统计或机器学习模型,可以以人类可以理解的形式存在,从而可以将经济解释附加到预测过程的内部工作中。

2.黑盒模型:任何机器学习模型都无法简单解释其内部工作原理,因此本质上是一个黑盒。

白盒模型类将被允许使用额外的特征提取。为了保持这种比较的客观性,我们不能在其中包含任何手动步骤。相反,我们将依赖某些(无监督的)算法,如主成分分析,希望它们至少近似于人类会做的特征提取。我们将这些算法称为提取器

List of all models and algorithms used in this benchmark. The technical name given in this table will be used in the result plots further below. Footnote 1: The MARS model will be considered grey box. We treat it as if it has an inherent extractor and don’t combine it with the other extractors.

The feature extractors used in this benchmark are applied to a 3-dimensional S-curve. For this example all feature extractors are reconfigured to extract exactly 2 components. The colour coding visualizes the effect of the transformation. This figure was inspired by a similar plot from Jake Vanderplas.

数据集

将在 32 个不同的公开可用数据集上进行比较:

  • 16 个数据集涉及二元分类,
  • 5 是多类分类任务,
  • 11 涉及预测连续值的回归任务。

为了使这种比较在计算上可行,我们将把每个大型数据集下采样到 10,000 个观察值,而不进行替换。

The datasets used in this benchmark. Most of them are from the UCI Machine Learning Repository, some are (training) datasets from Kaggle. The AmesHousing dataset was taken directly from (De Cock 2011). The BostonHousing2, a corrected and amended version of BostonHousing, was taken from StatLib.

模型管道

基准测试将在 scikit-learn 中使用其方便的 管道 来完成。对于所有模型,我们将使用一个基本的管道:每个度量特征首先用中位数估算,然后标准化。每个分类特征都是一次性编码,然后标准化,使其与度量特征处于同等地位。然后再次合并度量和分类特征。之后,如果适用于当前设置,可以使用特征提取器,然后将模型拟合到训练数据。

The data processing pipeline

衡量标准

用于比较模型的指标有:

  • 解释回归问题的方差
  • 二元分类问题的 ROC 曲线下面积 (AUROC),我们将其转换为 Somers' D
  • F1-分数由每个类别及其对多类别分类问题的计数进行评估和加权。

从 AUROC 到 Somers' D 的转换只需通过以下方式即可完成:

Somers ' D =2AUROC-1

主要优点是,随机猜测目标的虚拟性能现在是 0%(而不是 AUROC 的 50%)。这将使我们的结果的规范化和聚合更加容易。

超参数优化

为了评估每个算法的最优超参数集,我们使用 60 次重复的随机搜索,其中我们从合理的分布中对每个超参数进行采样。我们对少于 2,000 个观察值的数据集进行了 5 重交叉验证,并对较大数据集进行了 80/20 训练测试分割,以此评估随机搜索。超参数优化中使用的指标与比较中使用的指标相同。

结果

我们在 10 次重复的 10 重交叉验证中评估每个算法。我们在( 、莫里纳罗、西蒙和普发 2005 )和( 金 2009 )研究的基础上选择了重复交叉验证,两者都比较了不同的模型评估策略。因此,我们获得每个数据集的每个指标的 100 个值。如前所述,每个算法都配置有一组最佳超参数。

为了评估算法的性能,我们使用了两种受先前文献启发的比较方法:首先,我们基于每个数据集的相对排名对所有算法进行比较,这将在下一节中介绍。接下来的部分将根据每个指标的标准化分数进行比较。这种标准化协调了所有数据集的得分,并使汇总和比较成为可能。

相对排名比较

为了首先评估算法,我们为每个数据集颁发奖牌给表现最好的模型。在数据集的所有折叠上具有最佳平均性能的模型被授予金奖。第二名和第三名分别获得银牌和铜牌。所有型号的奖牌榜如下所示。这些算法按奖牌数排序,首先是金牌,然后是银牌和铜牌。这类似于奥林匹克运动会等体育赛事中使用的排序。所有赢得至少一枚奖牌的算法都会显示出来。

Overall medals

对于回归问题XG boost 和 extra trees 分别以 4 枚金牌主导结果。三个白盒模型岭回归、拉索和线性 SVM 能够获得奖牌,其中岭回归甚至获得一枚金牌。随机森林表现非常一致,7 银 1 铜。在授予回归问题的 33 枚奖牌中,5 枚由白盒算法获得,产生率为 15%,28 枚由黑盒方法获得。就奖牌数回归问题而言,黑盒方法明显占主导地位,赢得了所有奖牌的 85%。

对于多级分类,15 枚奖牌被授予,其中 6 枚授予白盒方法,获得率为 40%,9 枚授予黑盒方法。两个白盒方法 QDA 和线性 SVC 各获得 1 枚金牌。

在授予二元分类的 48 个模型中,21 个被白盒赢得,产生率为 44%,27 个被黑盒模型赢得。线性 SVC 和 logistic ridge 方法表现良好,获得了 21 个可解释模型奖项中的 19 个。因此,对于二元和多元分类,就奖牌数而言,白盒和黑盒方法之间的差距是接近的。

对于多类问题,xgboost 在回归和二元分类中的优势似乎较弱。有趣的是,如果我们根据 F1 的成绩进行二元分类来授予奖牌,xgboost 只获得 2 金 1 铜(查看链接论文的附录中这些补充结果)。因此,这可能(部分)是 F1 指标的影响。然而,如果我们根据度量准确性来分配奖牌,xgboost 再次成为二元分类中排名最高的模型,获得 3 枚金牌、1 枚银牌和 2 枚铜牌。对于多级分类,它再次排在奖牌榜的中间。请注意,在对这里显示的指标执行超参数优化时,应该有所保留地进行这些比较。

最佳提取器

我们还为每个数据集的最佳提取者颁发奖牌(仅根据白盒模型评估),如下表所示。我们看到,除了使用原始特征( None ),只有 PCA 和 Kernel-PCA 方法获得了奖牌。

Best extractors medals

白盒排名

由于所有的奖牌榜都是由黑盒算法主导的,我们也只对白盒模型进行排名:第一个表显示了在没有使用附加提取器的情况下白盒算法的排名。第二个表显示了如果包括所有具有特征提取器的组合时的相同比较。

Medal ranking for white box models without any feature extractor (Note that we also list MARS as having no feature extractor, though we consider it to have the equivalent of a feature extractor build into the algorithm itself. This probably explains why MARS is dominating the table when no feature extraction methods are included but ranks lower when the other white box models are allowed to utilize a feature extraction algorithm.)

Medal ranking for white box models including feature extractors

我们看到,一些算法,如弹性网,单独在白盒模型上表现很好,但在整个表中消失了。这是因为它们在数据集上表现很好,而黑盒算法表现得甚至更好。

对于多类分类,如果没有应用特征提取,线性 SVC 根本不会出现在表中,但是使用提取器方法赢得了大多数奖牌。

标准化分数的比较

不同数据集和算法的结果必须归一化,以使它们相互之间具有可比性。为此,我们通过以下三个步骤处理数据:

1。移除不稳定的算法:不收敛且产生的结果远低于虚拟性能的算法被排除。一些算法提取器组合仅在一个数据集上不稳定。为了不使结果有偏差,我们删除了每个数据集的中值等于或低于-0.5 的任何算法。

2。Winsorize 回归问题的最差可能性能:二元分类问题的度量被限制在从-1.0(通过总是给最佳观察值最差分数的绝对最差性能)到+1.0(完美预测)的范围内。类似地,多类分类的加权 F1 分数范围从 0.0 到 1.0。相反,回归指标可以从负无穷大到+1.0。一些回归算法仅在少数褶皱上不稳定,因此在前面的步骤中没有被去除。为了不允许任何单个异常值显著影响总结果,并使回归和分类之间的比较更加平等,我们通过将较低的每个值设置为等于-1.0 来对回归问题的每个折叠的度量进行 winsorize。

3。针对特质效应进行归一化:对于每个数据集,预测新值的难度是不同的。原因在于不同程度的特质效应对每个观察值的影响。为了使每个数据集的分数更具可比性,执行以下归一化:

对于数据集和指标的每个组合,我们确定指标的 95%百分位数,涵盖所有算法和折叠。然后,数据集和指标组合的每个 CV 值通过将其结果除以该百分位进行归一化。

where ‘d’ denotes each dataset, ‘a’ each algorithm extractor pair and ‘c’ stands for a specific CV-fold. The percentile is taken over all algorithms and all folds, per metric and dataset.

在这种标准化之后,每个算法应该在所有数据集上显示相似的结果结构。我们可以用一个简单的箱线图来证实这一点,如下所示。请注意,这种标准化会导致值高于+1.0。

Results for the regression random forest before and after normalization for the metric explained variance by dataset. We see that after the normalization the results are of similar range. An aggregation of the results per algorithm over all datasets is now possible.

接下来,我们汇总所有数据集的所有标准化分数,计算每个算法的平均分数,并相应地对算法进行排序。我们还通过引导标准化分数来确定 95%的置信区间。

在下面的图中,我们将只显示一个模型的最佳白盒提取器。没有任何提取器的方法也将始终包括在内(所有组合的综合图可以在链接的论文中找到)。黑盒算法以深蓝色显示。如果应用于原始数据,白盒算法以青色显示,如果使用了提取器,则以红色显示。置信区间用灰色条表示。

Selection of the best binary classification algorithms in terms of their normalized Somers’ D values.

Selection of the best multiclass classification algorithms in terms of their normalized weighted F1 scores.

Selection of the best regression algorithms in terms of their normalized explained variance.

对于回归问题我们看到,除了神经网络之外,所有黑盒算法的表现都明显优于白盒方法。xgboost 算法是性能最好的算法。它能够解释比最佳白盒模型岭回归多 10%的方差(使用基于 RBF 的核主成分分析作为提取器)。

对于多类分类我们看到,没有任何提取器的所有白盒算法的性能明显更差,无法与其他方法竞争。虽然 xgboost 和神经网络具有最高的平均分数,但它们的表现仅比三种最佳白盒算法(逻辑回归、逻辑拉索和线性 SVC)好大约 1%。这三种方法甚至优于三种黑盒方法随机森林、内核 SVC 和袋装树。

对于二进制分类xgboost 算法比第二好的模型实现了高 1%的 Somers' D,第二好的模型是使用 RBF 类型的核 PCA 作为提取器的线性 SVC。以下方法似乎在相似的范围内聚类,从线性 SVC 的归一化 Somers ' D 0.93 到具有 0.89 的额外树分类器。它们由其他黑盒方法(除了 xgboost)和许多其他白盒算法组成,都带有提取器。下一个最好的算法(没有任何提取器的决策树)已经显示出性能显著下降到 0.82。

结论

从基准测试中,我们可以得出以下三个结论:

提取器提高了白盒模型的性能。主成分分析,包括其核变量,是最好的特征提取器:

对于大多数算法来说,它们的使用导致了性能的显著提高。对于许多数据集,尤其是对于二进制分类,使用不带任何提取器的原始要素也会产生白盒模型的竞争性结果。基于流形方法、k 均值和随机投影的其他方法表现较差。我们推测,流形方法可能在非结构化数据集(文本、图像)上实现更好的提取,这是它们最初开发的目的;似乎在结构化数据上,PCA 的更直接的变换更合适。

最好的算法:所有黑盒算法表现都很好,尤其是 xgboost。套索,脊和弹性网通常是最好的白盒模型

在我们的分析中,boosting 算法 xgboost 表现最好。这可能解释了它在机器学习竞赛中的普遍性。总的来说,所有的黑盒算法都表现良好,并取得了相似的分数。神经网络在分类任务上表现良好,但在回归数据集上表现较低(这可能是由于所选的网络结构和参数,因此不应得出过早的一般性结论)。与大多数其他黑盒算法相比,支持向量机在回归和二元分类问题上表现出较低的性能。对于二元分类问题,额外的树处于类似的较低范围。

线性结构模型,如线性和逻辑回归,在回归和分类任务中表现最好。通常正则化的方法(套索,山脊,弹性网)比非正则化的方法表现更好。线性支持向量机在分类问题上表现良好,但其回归版本表现较差。虽然 LDA 在结构上类似于逻辑回归,但它不能在分类任务上表现出类似的高性能。非线性结构朴素贝叶斯、QDA 和单一树的方法不能竞争,显然不能充分利用提取的特征。

具有特征提取的白盒模型能够在分类问题上与黑盒模型竞争;在回归问题上,黑盒算法似乎更胜一筹

虽然典型的黑盒模型表现出最好的性能,但顶级的白盒模型(包括特征提取)的得分仅略低。这对于二进制和多类分类都是显而易见的。

我们可以得出结论,对于分类问题,具有适当(理想的是手动)特征提取的简单模型可以与黑盒模型竞争。作为一个实际的建议,我们建议将手工构建的简单模型与黑盒模型进行对比。这可以提供手动特征提取是否足够或者是否可以改进的指示。

一项有趣的后续研究可以验证特征提取器是否也能提高黑盒方法的性能。还可以测试对度量和分类变量应用不同的特征提取器是否会导致不同的结果,因为它可能更好地处理这两种变量类型的不同性质。

我希望您发现这个基准很有趣,并且可以为您的下一个机器学习项目带来一些经验或灵感。如果这也符合你的亲身经历,请在下面的评论中告诉我。也许你们中的一些人已经用自己的基准进行了实验:你从中得出了什么结论?

免责声明:本文陈述的所有内容均为我个人观点,不代表任何雇主。

伯特在 EMNLP 2019

原文:https://towardsdatascience.com/bert-at-emnlp-2019-46db6c2e59b2?source=collection_archive---------34-----------------------

ml 评论

EMNLP 2019 上与 BERT 相关的论文

自然语言处理经验方法会议(EMNLP)于 2019 年 11 月 3 日至 11 月 7 日在香港举行。有很多有趣的论文,但我想强调一下关于伯特的论文。

揭露伯特的黑暗秘密

http://arxiv.org/abs/1908.08593

在这篇论文中,来自马萨诸塞大学洛厄尔分校的研究人员研究了跨 BERT 层和头部的自我注意机制。为此使用了 GLUE 任务的子集:MRPC、STS-B、SST-2、QQP、RTE、QNLI、MNLI。

实验:

  • BERT 中的特定关系中心。
  • 微调后自我注意模式的变化。
  • 注意语言特征。
  • 象征性的关注。
  • 禁用自我关注头。

Typical self-attention classes used for training a neural network. Both axes on every image represent BERT tokens of an input example, and colors denote absolute attention weights (darker colors stand for greater weights). The first three types are most likely associated with language model pre-training, while the last two potentially encode semantic and syntactic information.

有趣的发现:

伯特模型明显参数化过度。不同人的注意力模式是有限的。因此,禁用某些磁头不会导致精度下降,但会提高性能。

很有意思。这就是为什么蒸馏伯特有意义。

可视化和理解 BERT 的有效性

http://arxiv.org/abs/1908.05620

微软研究院的另一篇关于用酷炫的可视化理解 BERT 的表现的论文。

Training loss surfaces of training from scratch (top) and fine-tuning BERT (bottom) on four datasets. Pre-training leads to wider optima, and eases optimization compared with random initialization.

上图清楚地展示了这篇论文的主要思想:

  • 微调 BERT 的训练损失趋于沿优化方向单调减少,这使得优化变得容易并加速了训练收敛。
  • 微调过程对于过拟合是鲁棒的;
  • 预训练模型获得更平坦、更宽的最优解;

所以,不要为了你的任务而从零开始训练 BERT。微调比较好。

伯特模型压缩的病人知识蒸馏

http://arxiv.org/abs/1908.09355

微软的另一篇论文是关于知识提炼的。提出了一种通过病人知识蒸馏将大型 BERT 模型压缩成浅层模型的新方法。这种方法声称是第一次不仅在蒸馏中使用了输出分布,而且还使用了“老师”的隐藏状态。此外,“学生”试图模仿的只是[CLS]表征。与其他蒸馏方法相比,伯特-PKD 法优于蒸馏法,但不如蒂尼伯特法。

句子伯特:使用连体伯特网络的句子嵌入

http://arxiv.org/abs/1908.10084

代号:https://github.com/UKPLab/sentence-transformers

问题如下:来自 BERT 的嵌入适合语义相似性搜索吗?本文表明,BERT 开箱即用将句子映射到一个向量空间,该向量空间不太适合用于常见的相似性度量,如余弦相似性。该性能比普通手套嵌入的性能差。为了克服这个缺点,人们提出了句子-BERT (SBERT)。SBERT 在连体或三联体网络架构中微调 BERT。

SBERT architecture with classification objective function, e.g., for fine-tuning on SNLI dataset. The two BERT networks have tied weights (siamese network structure).

贝托,本茨,贝卡斯:伯特惊人的跨语言效果

http://arxiv.org/abs/1904.09077

本文探讨了多语言 BERT 作为零镜头语言迁移模型的跨语言潜力。

长话短说:BERT 有效地学习了一种良好的多语言表示,在各种任务中具有很强的跨语言零镜头迁移性能。

基于 BERT 和 DeepPavlov 的跨语言问答

原文:https://towardsdatascience.com/bert-based-cross-lingual-question-answering-with-deeppavlov-704242c2ac6f?source=collection_archive---------9-----------------------

DeepPavlov 是一个对话式人工智能框架,包含了构建聊天机器人所需的所有组件。DeepPavlov 是在开源机器学习框架 TensorFlowKeras 之上开发的。它免费且易于使用。本文描述了如何使用 DeepPavlov 的基于 BERT 的问答模型。

基于上下文的阅读理解是在给定的上下文(例如,维基百科中的一段话)中寻找问题答案的任务,其中每个问题的答案都是上下文的一部分。

问题一个n wering 系统可以让你的业务中的很多流程实现自动化。例如,它可以帮助你的雇主根据你的公司内部文件得到答案。此外,它还可以帮助您在辅导中检查学生的阅读理解能力。

例如:

上下文:

在气象学中,降水是大气中的水蒸气在重力作用下凝结的产物。降水的主要形式包括毛毛雨、雨、雨夹雪、雪、霰和冰雹。…当较小的水滴通过与云中的其他雨滴或冰晶碰撞而结合在一起时,就形成了降水。分散在各处的短时间的强降雨被称为“阵雨”

问题:

水滴在哪里与冰晶碰撞形成降水?

回答:

云内

近年来,基于上下文的问答任务引起了学术界的广泛关注。这一领域的一个重要里程碑是 tanford Qu estion 的发布。SQuAD 一个新的阅读理解数据集,由一组维基百科文章上的众包工作者提出的问题组成,其中每个问题的答案都是相应阅读文章中的一段文字或跨度。SQuAD 拥有 500+篇文章上的 100,000+个问答对,显著大于之前的阅读理解数据集1

小队数据集提出了无数的问题回答方法。在本文中,我将描述基于 BERT 的解决方案,它在 SQuAD 上的表现优于人类。

给伯特

BERT 是一种基于转换器的技术,用于预处理上下文单词表示,能够在各种自然语言处理任务中实现最先进的结果[2]。伯特论文被公认为最好的长篇论文👏计算语言学协会北美分会颁发的年度大奖。Google Research】发布了几个预训练的 BERT 模型,包括多语言、中文和英文的 BERT。

我们决定将 BERT 集成到三个流行的 NLP 任务的解决方案中:、文本分类标记和问题回答。在本文中,我们将详细告诉你如何在 DeepPavlov 中使用基于 BERT 的问答。文章的代码可以在 Colab 笔记本中找到。

如何在 DeepPavlov 中使用基于 BERT 的小队模型

只需对每个子发音的 BERT 输出应用两次线性变换,预训练的 BERT 就可以用于文本上的问题回答。第一/第二线性变换用于预测当前子发音是答案的开始/结束位置的概率。

两个模型都预测给定上下文中答案的开始和结束位置。

Credit: BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding

正如预期的那样,基于 BERT 的模型优于所有其他模型,并提供了良好的结果,接近人类的表现。

小队任务的 DeepPavlov 模型比较如下表所示(其中 EM 表示完全匹配)。

The results of the DeepPavlov SQuAD models

任何预先训练的模型都可以通过命令行界面(CLI)和 Python 进行推理。在使用模型之前,确保所有必需的包都已安装,然后您可以通过运行 interact (-d 表示下载预训练的模型)与模型进行交互:

python -m deeppavlov install squad_bert
python -m deeppavlov interact squad_bert -d

此外,您可以通过 Python 代码使用模型,如下所示:

跨语言零投射迁移

多语言 BERT (M-BERT)模型允许执行从一种语言(源语言)到另一种语言(目标语言)的零转换。英语作为源语言是一个很好的候选语言,因为英语的训练数据很容易获取。作为目标语言,你可以使用来自列表的 104 种用于训练 M-BERT 的语言中的任何一种。

我们的方法非常简单:我们在一种语言上微调基于 M-BERT 的模型,并在不同语言的测试集上评估该模型,从而允许我们测量该模型跨语言概括信息的程度。

正如您在下面的代码片段中看到的,我们通过提供一批上下文和一批问题来调用模型,作为输出,模型返回从上下文中提取的一批答案及其开始位置。这个代码片段演示了多语言问答模型,虽然是在英语数据集上训练的,但它能够从法语上下文中提取答案,即使问题是用不同的语言(片段中的英语)提出的。

为了衡量可迁移性,我们选择了三种词汇不重叠的语言:英语、俄语、汉语。

对于英语,我们使用众所周知的阵容。对于包含来自 2,108 篇维基百科文章的 10,014 个段落和 40,410 个问答对的中文 DRCD (Delta 阅读理解数据集)3。最后,作为一个俄罗斯班,我们使用 RuSQuAD 和 45k 对上下文问题。

实验结果可以在下表中找到。

The SQuAD model performance (F1/EM)

结果表明,M-BERT 创建了多语言表示,这使我们能够在零镜头跨语言模型转换设置中实现有希望的结果。你可以在这里找到更多关于 DeepPavlov 的问题回答模型。也可以使用我们的演示来测试我们基于 BERT 的模型。此外,我们刚刚为非正式英语发布了 Conversation BERT ,它在社交网络数据方面的表现优于所有其他模型。

参考资料:

  1. 小队:10 万+机器理解文本的问题
  2. BERT:用于语言理解的深度双向转换器的预训练
  3. DRCD:一个中文机器阅读理解数据集

伯特分类器:只是另一个 Pytorch 模型

原文:https://towardsdatascience.com/bert-classifier-just-another-pytorch-model-881b3cf05784?source=collection_archive---------9-----------------------

Valencia, Spain. Whenever I don’t do projects with image outputs I just use parts of my photo portfolio…. Per usual FRIEND LINK here

2018 年底,谷歌发布了 BERT ,它本质上是一个基于所有维基百科训练的 12 层网络。训练协议很有趣,因为与最近的其他语言模型不同,BERT 被训练为从两个方向考虑语言上下文,而不仅仅是单词左侧的内容。在的预训练中,BERT 屏蔽掉给定句子中的随机单词,并使用句子的其余部分来预测丢失的单词。Google 还通过在与其他语言模型规模相当的数据集上训练 BERT 来对其进行基准测试,并显示出更强的性能。

NLP 是一个我有点熟悉的领域,但是看到 NLP 领域拥有它的“ImageNet”时刻是很酷的,该领域的从业者现在可以相当容易地将最先进的模型应用于他们自己的问题。简单回顾一下,ImageNet 是一个大型开源数据集,在其上训练的模型通常可以在 Tensorflow、Pytorch 等库中找到。这些熟练的预训练模型让数据科学家花更多时间解决有趣的问题,而不是重新发明轮子,专注于数据集的监管(尽管数据集监管仍然非常重要)。你现在需要数千而不是数百万的数据集来开始深度学习。

为了工作,我在有限的能力范围内使用过几次 BERT,主要是基于我找到的其他教程。然而,我一直在推迟深入剖析管道并以我更熟悉的方式重建它…在这篇文章中,我只想更好地理解如何以我习惯的方式创建 BERT 管道,以便我可以开始在更复杂的用例中使用 BERT。主要是我对将 BERT 集成到各种网络的多任务集合中感兴趣。

通过这个学习过程,我的希望是展示虽然 BERT 是一个推动 NLP 边界的艺术模型,但它就像任何其他 Pytorch 模型一样,并且通过理解它的不同组件,我们可以使用它来创建其他有趣的东西。我真正想要的是克服我对使用 BERT 的恐惧/恐吓,并像使用其他预训练模型一样自由地使用 BERT。

资料组

所以在这篇文章中,我使用了经典的 IMDB 电影评论数据集。这个数据集有 50,000 条电影评论,每条评论都标有“正面”或“负面”的情绪。与我的其他帖子不同,我没有构建自定义数据集,部分原因是我不知道快速构建文本数据集的方法,我不想在这上面花太多时间,这一个很容易在互联网上找到。

总的来说,我同意这不是我能做的最有趣的事情,但是在这篇文章中,我更关注如何使用 BERT 构建一个管道。一旦管道到位,我们就可以根据自己的选择交换出数据集,用于更多样/有趣的任务。

分类架构

在这篇文章中,我将使用一个名为拥抱脸的团体的伯特 Pytorch port(很酷的团体,奇怪的名字…让我想到半条命拥抱脸)。通常最好是使用任何内置的网络来避免新移植实现的准确性损失…但谷歌对拥抱脸的移植竖起了大拇指,这很酷。

无论如何…继续…

我要做的第一件事是建立一个模型架构。为此我主要从拥抱脸的例子中拿出一个例子,叫做。目前,这个类在文档中看起来已经过时了,但是它是如何构建 BERT 分类器的一个很好的例子。基本上,您可以使用 BertModel 类初始化一个 BERT 预训练模型。然后,您可以根据需要添加额外的层作为分类器头。这与创建其他定制 Pytorch 架构的方式相同。

像其他 Pytorch 模型一样,您有两个主要部分。首先,您有 init,其中您定义了架构的各个部分,在这种情况下,它是 Bert 模型核心(在这种情况下,它是较小的小写模型,大约 110M 参数和 12 层),要应用的 dropout,以及分类器层。第二部分是前面的部分,在这里我们定义了如何将架构的各个部分整合到一个完整的管道中。

***class** **BertForSequenceClassification**(nn.Module):

    **def** __init__(self, num_labels=2):
        super(BertForSequenceClassification, self).__init__() self.num_labels = num_labels self.bert = BertModel.from_pretrained('bert-base-uncased') self.dropout = nn.Dropout(config.hidden_dropout_prob) self.classifier = nn.Linear(config.hidden_size, num_labels) nn.init.xavier_normal_(self.classifier.weight) **def** forward(self, input_ids, token_type_ids=**None**, attention_mask=**None**, labels=**None**): _, pooled_output = self.bert(input_ids, token_type_ids, attention_mask, output_all_encoded_layers=**False**) pooled_output = self.dropout(pooled_output) logits = self.classifier(pooled_output)

        **return** logits*

既然已经定义了模型,我们只需要弄清楚如何组织我们的数据,这样我们就可以输入数据并优化权重。在图像的情况下,这通常只是计算出我们需要应用什么样的转换,并确保我们得到正确的格式。对于 BERT,我们需要能够将字符串标记化,并将它们转换成映射到 BERT 词汇表中单词的 id。

Mendoza, Argentina. Lots of good wine!

BERT 数据预处理

使用 BERT 进行数据准备时,我们需要的主要功能是如何标记输入,并将其转换为 BERT 词汇表中相应的 id。拥抱脸为 BertModel 和 BertTokenizer 类增加了非常好的功能,你可以输入你想要使用的模型的名字,在这篇文章中,它是“bert-base-uncased”模型。

*tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')*

要对文本进行标记,您只需调用标记化器类的标记化函数。见下文。

*tokenized_text = tokenizer.tokenize(some_text)*

然后,一旦你把一个字符串转换成一个记号列表,你就必须把它转换成一个匹配 BERT 词汇表中单词的 id 列表。这一次,您只需对之前标记化的文本调用 convert_tokens_to_ids 函数。

*tokenizer.convert_tokens_to_ids(tokenized_text)*

有了这些基础知识,我们就可以组装数据集生成器,它总是像流水线中的无名英雄一样,这样我们就可以避免将整个东西加载到内存中,这是一种痛苦,会使在大型数据集上学习变得不合理。

自定义 BERT 数据集类

一般来说,Pytorch 数据集类是基本数据集类的扩展,您可以在其中指定如何获取下一个项目以及该项目的返回内容,在本例中,它是一个长度为 256 的 id 张量和一个热编码目标值。从技术上来说,你可以做长度为 512 的序列,但我需要一个更大的显卡。我目前正在一台配有 11GB GPU RAM 的 GTX 2080ti 上进行训练。在我之前的 1080 卡上,我只能舒服地使用 128 的序列。

*max_seq_length = 256
**class** **text_dataset**(Dataset):
    **def** __init__(self,x_y_list):self.x_y_list = x_y_list

    **def** __getitem__(self,index):

        tokenized_review = tokenizer.tokenize(self.x_y_list[0][index])

        **if** len(tokenized_review) > max_seq_length:
            tokenized_review = tokenized_review[:max_seq_length]

        ids_review  = tokenizer.convert_tokens_to_ids(tokenized_review)

        padding = [0] * (max_seq_length - len(ids_review))

        ids_review += padding

        **assert** len(ids_review) == max_seq_length

        *#print(ids_review)*
        ids_review = torch.tensor(ids_review)

        sentiment = self.x_y_list[1][index] *# color* 
        list_of_labels = [torch.from_numpy(np.array(sentiment))]

        **return** ids_review, list_of_labels[0]

    **def** __len__(self):
        **return** len(self.x_y_list[0])*

因为这是一段相当不错的未加注释的代码…让我们把它分解一下!

对于变量 x_y_list 的第一位。这是我在建立数据集时经常做的事情…它基本上只是一个 x 和 y 的列表,不管它们有多少。然后,我对特定的列表进行索引,根据需要检索特定的 x 或 y 元素。

如果有人看过我的其他图像管道,我基本上总是有这个,它通常是对应于测试或训练集的图像 URL 列表。在这种情况下,它是训练电影评论文本的测试,第二个元素是这些电影评论文本的标签。

***class** **text_dataset**(Dataset):
    **def** __init__(self,x_y_list):
        self.x_y_list = x_y_list*

所以不要再说了!其中最重要的部分是数据集类如何定义给定样本的预处理。

  1. 对于这个 BERT 用例,我们在“self.x_y_list[0][index]”检索给定的评论
  2. 然后如上所述用“tokenizer.tokenize”对该评论进行标记。
  3. 所有的序列需要长度一致,因此,如果序列长于最大长度 256,它将被截短为 256。
  4. 然后通过“tokenizer . convert _ tokens _ to _ IDs”将标记化和截断的序列转换成 BERT 词汇表 id
  5. 在序列短于 256 的情况下,现在用 0 填充直到 256。
  6. 该评论被转换成 torch 张量。
  7. 然后,该函数返回评论的张量及其一个热编码的正或负标签。
 ***def** __getitem__(self,index):

        tokenized_review = tokenizer.tokenize(self.x_y_list[0][index])

        **if** len(tokenized_review) > max_seq_length:
            tokenized_review = tokenized_review[:max_seq_length]

        ids_review  = tokenizer.convert_tokens_to_ids(tokenized_review)

        padding = [0] * (max_seq_length - len(ids_review))

        ids_review += padding

        **assert** len(ids_review) == max_seq_length

        *#print(ids_review)*
        ids_review = torch.tensor(ids_review)

        sentiment = self.x_y_list[1][index]
        list_of_labels = [torch.from_numpy(np.array(sentiment))]

        **return** ids_review, list_of_labels[0]

    **def** __len__(self):
        **return** len(self.x_y_list[0])*

培养

在这一点上,培训管道相当标准(现在 BERT 只是另一个 Pytorch 模型)。如果你想检查笔记本的第 21 块,我可以使用普通的循环训练。这款笔记本和我的其他笔记本之间唯一真正的区别是风格上的,我在网络本身之外使用了最终分类器层的 softmax。

*outputs = F.softmax(outputs,dim=1)*

最后一个有趣的部分是,我给网络的不同部分分配了特定的学习率。几个月前,当我浏览 fastai 视频时,我对这样做产生了兴趣,并发现它很有用。

这个部分做的第一件事是分配两个学习率值,称为 lrlastlrmain。 lrlast 相当标准,为 0.001,而 lrmain 则低得多,为 0.00001。其思想是,当网络的部分被随机初始化,而其他部分已经被训练时,你不需要对预训练的部分应用激进的学习速率而没有破坏速率的风险,然而,新的随机初始化的部分可能不会覆盖,如果它们处于超低的学习速率…因此,对网络的不同部分应用更高或更低的学习速率有助于使每个部分适当地学习。下一部分可以是积极的,而预训练部分可以进行逐步调整。

应用这一点的机制出现在字典列表中,您可以在其中指定应用于优化器(在本例中为 Adam 优化器)中网络不同部分的学习率。

*lrlast = .001
lrmain = .00001
optim1 = optim.Adam(
    [
        {"params":model.bert.parameters(),"lr": lrmain},
        {"params":model.classifier.parameters(), "lr": lrlast},       
   ])

optimizer_ft = optim1*

设置好学习速率后,我让它运行 10 个周期,每 3 个周期降低学习速率。网络从一个非常强的点开始…

*Epoch 0/9
----------
train total loss: 0.4340 
train sentiment_acc: 0.8728
val total loss: 0.4089 
val sentiment_acc: 0.8992*

基本上,用 Bert 预先训练的权重初始化网络意味着它已经对语言有了很好的理解。

*Epoch 9/9
----------
train total loss: 0.3629 
train sentiment_acc: 0.9493
val total loss: 0.3953 
val sentiment_acc: 0.9160*

在这个过程结束时,精确度提高了几个点,损失略有减少…我还没有真正看到模型通常如何在这个数据集上得分,但我认为这是合理的,现在足以表明网络正在进行一些学习。

在我的新 2080ti 卡上,这个数据集上的 10 个时代花了 243m 48s 才完成。顺便提一下,让卡和 Pytorch 一起工作有很多麻烦…主要是更新各种版本的东西。

Buenos Aires Metropolitan Cathedral

结束语

对我来说,这样做很重要,可以向自己表明,虽然 BERT 是最先进的,但当我试图将它应用于我自己的问题时,我不应该被吓倒。由于人们付出了大量努力将 BERT 移植到 Pytorch 上,以至于谷歌对其性能表示赞赏,这意味着 BERT 现在只是数据科学家在 NLP 盒子中的另一个工具,就像 Inception 或 Resnet 对于计算机视觉一样。

就性能而言,我认为我可以通过在最终分类器之前添加额外的层来挤出几个额外的百分点。这将允许在这个特定的任务中有更多的层。我也不太精通如何在 NLP 领域进行数据扩充,所以这将是其他需要检查的东西,可能使用其他经过训练的语言模型来生成合成文本...但是现在我有了一个 BERT 管道,并且知道我可以像对任何其他模型那样在其上构建自定义分类器…谁知道呢…这里有很多令人兴奋的可能性。

像往常一样,你可以在这里随意查看笔记本。为了简单起见,数据集也在 repo 中,所以如果你安装了 pytorch 和 pytorch-pretrained-bert 库,你应该可以使用了。

伯特为假人-一步一步教程

原文:https://towardsdatascience.com/bert-for-dummies-step-by-step-tutorial-fb90890ffe03?source=collection_archive---------0-----------------------

变压器 DIY 实用指南。经过实践检验的 PyTorch 代码,用于 NLU 的意向分类,经过 BERT 微调。

本文介绍了与 BERT 一起起飞所需的一切。我们提供了一个分步指南,介绍如何微调变压器(BERT)的双向编码器表示,以实现自然语言理解,并使用 LSTM 对其进行基准测试。

source: intention+belief=manifestation

动机

聊天机器人、虚拟助理和对话代理通常会将查询分类为特定的意图,以便生成最一致的响应。意图分类是预测任何给定用户查询的意图标签的分类问题。这通常是一个多类分类问题,其中查询被分配一个唯一的标签。例如,查询“匹兹堡内的豪华轿车服务费用是多少”被标记为“地面票价”,而查询“丹佛有什么样的地面交通工具”被标记为“地面服务”。查询“我想上午 8:38 从波士顿起飞,上午 11:10 到达丹佛”是“航班”意图,而“给我看看从旧金山到亚特兰大的航班的费用和时间”是“机票+航班时间”意图。

[## BERT NLP——如何构建问答机器人

通过亲自动手的 PyTorch 代码理解直觉,BERT 在 SQuAD 上进行了微调。

towardsdatascience.com](/bert-nlp-how-to-build-a-question-answering-bot-98b1d1594d7b)

上面的例子显示了意图标签的模糊性。用户可能会添加误导性的词语,导致多个意图出现在同一个查询中。针对意图分类提出了基于注意的学习方法(刘和莱恩,2016;咕等, 2018 。一种精心构建的网络被称为变压器。It 应用注意力机制来收集关于给定单词的相关上下文的信息,然后将该上下文编码到灵活表示该单词的丰富向量中。

在本文中,我们将演示 Transformer,特别是它的注意机制如何通过学习上下文关系来帮助解决意图分类任务。在展示了基于 LSTM 的分类器的局限性之后,我们介绍了 BERT:深度双向转换器的预训练,这是一种新的转换器方法,在大型语料库上进行预训练并且是开源的。本文的最后一部分展示了对 BERT 进行微调以完成意图分类任务,并在不可见的意图查询上实现最先进的准确性所必需的 Python 代码。我们使用 ATIS(航空旅行信息系统)数据集,这是一个标准的基准数据集,广泛用于识别客户查询背后的意图。

LSTM 的意向分类

数据

在我们之前的一篇文章的中,你会找到加载 ATIS 数据集的 Python 代码。在 ATIS 训练数据集中,我们有 26 个不同的意向,其分布如下所示。数据集非常不平衡,大多数查询都被标注为“flight”(代码 14)。

多类分类器

在查看 Transformer 之前,我们实现了一个简单的 LSTM 递归网络来解决分类任务。在通常的预处理、标记化和矢量化之后,4978 个样本被送入 Keras 嵌入层,该层将每个单词投影为维数为 256 的 Word2vec 嵌入。结果通过具有 1024 个单元的 LSTM 层。这产生了 1024 个输出,这些输出被提供给具有 26 个节点和 softmax 激活的密集层。使用分类交叉熵将在该管道末端创建的概率与原始标签进行比较。

正如我们在上面的训练输出中看到的,Adam 优化器卡住了,损失和准确性没有提高。该模型似乎预测了多数类在每一步的“飞行”。

当我们使用经过训练的模型来预测未知测试数据集上的意图时,混淆矩阵清楚地显示了模型如何过度适应大多数“飞行”类。

数据扩充

在解决分类任务时,处理不平衡数据集是一个常见的挑战。数据扩充是一个很好的解决方法。在这里,遇到 SMOTE 算法并不罕见,这是一种在不偏离预测的情况下增加数据集的流行选择。SMOTE 使用 k-最近邻分类器来创建合成数据点,作为紧密相关的真实数据点组的多维插值。不幸的是,我们在 ATIS 训练数据集中有 25 个少数民族类,留给我们一个过度代表性的类。SMOTE 无法工作,因为它无法找到足够多的邻居(最小值为 2)。替换过采样是 SMOTE 的一种替代方法,也不能提高模型的预测性能。

从 SNIPS 个人语音助手收集的 SNIPS 数据集,是一个用于自然语言理解的更近的数据集,是一个可用于在未来工作中增强 ATIS 数据集的数据集。

二元分类器

由于我们在扩充数据集方面不太成功,现在,我们将缩小问题的范围。我们定义了一个二进制分类任务,其中通过将“flight”查询折叠到一个名为“other”的类中,针对剩余的类对其进行评估。这个新数据集中的标签分布如下所示。

我们现在可以使用与之前类似的网络架构。唯一的变化是将密集层中的节点数减少到 1,将激活函数减少到 sigmoid,将损失函数减少到二进制交叉熵。令人惊讶的是,在给定用户查询的情况下,LSTM 模型仍然无法学会预测用户意图,如下所示。

在 10 个时期之后,我们在一个看不见的测试数据集上评估该模型。这一次,我们将所有样本都预测为“其他”,尽管在训练集中,“flight”的样本数是“其他”的两倍多。

使用 BERT 进行意图分类

我们现在关注 Transformer 的动机是,当数据集不平衡时,我们目睹了序列到序列模型在意图分类任务中的糟糕分类结果。在本节中,我们将介绍 Transformer 的一个变体,并实现它来解决我们的分类问题。我们将特别关注 2018 年末发布的变形金刚(BERT)双向编码器表示。

伯特是什么?

BERT 基本上是一个训练有素的 Transformer 编码器堆栈,基本版本有 12 个,大型版本有 24 个,相比之下,我们在上一篇文章的中描述的原始 Transformer 有 6 个编码器层。

[## 迷失在翻译中。被变形金刚发现。

破解 GPT-2 使用的变压器模型之谜,伯特

towardsdatascience.com](/lost-in-translation-found-by-transformer-46a16bf6418f)

BERT 编码器具有更大的前馈网络(基础和大型分别为 768 和 1024 个节点)和更多的注意力头(分别为 12 和 16)。伯特接受了维基百科和图书语料库的培训,这是一个包含超过 10,000 本不同流派书籍的数据集。下面你可以看到一个在专业语料库上预先训练的 BERT 的其他变体的图表。

source

伯特被发布给公众,作为 NLP 的一个新时代。它的开源模型代码打破了几项基于语言的困难任务的记录。大规模数据集上的预训练模型使任何构建自然语言处理的人都可以使用这个免费的发电站。从理论上讲,BERT 允许我们通过最少的特定任务微调来粉碎多个基准测试。

(source: Jay. Alammar, 2018)

BERT 的工作方式类似于 Transformer 编码器堆栈,它将一个单词序列作为输入,在新的序列进入时,该序列不断从一个编码器流向下一个编码器。每个序列的最终输出是一个 728 基数或 1024 大基数的向量。我们将使用这样的向量来解决我们的意图分类问题。

我们为什么需要伯特?

正确的语言表示是机器理解通用语言的关键。上下文无关模型,如 word2vec 或 GloVe 为词汇表中的每个单词生成单个单词嵌入表示。例如,“银行”一词在“银行存款”和“河岸”中有相同的表示。上下文模型根据句子中的其他单词生成每个单词的表示。作为一个语境模型,BERT 以双向的方式捕捉了这些关系。BERT 基于最近的工作和预训练上下文表示中的巧妙想法,包括半监督序列学习生成式预训练ELMoOpenAI TransformerULMFitTransformer。虽然这些模型都是单向或浅双向的,但 BERT 是完全双向的。

我们将使用 BERT 从 ATIS 查询文本数据中提取高质量的语言特征,并使用自己的数据在特定任务(分类)上微调 BERT,以产生最先进的预测。

准备 BERT 环境

请随意下载原版 Jupyter 笔记本,我们将根据本节的目标对其进行改编。

至于开发环境,我们推荐 Google Colab ,它提供免费的 GPU 和 TPUs,可以通过进入菜单选择:编辑- >笔记本设置- >添加加速器(GPU) 来添加。Colab 的一个替代方案是在谷歌云平台上使用一个 JupyterLab 笔记本实例,在请求谷歌增加你的 GPU 配额后,选择菜单 AI 平台- >笔记本- >新实例- > Pytorch 1.1 - >带 1 个 NVIDIA Tesla K80 。这将花费大约。每小时 0.40 美元(当前价格,可能会改变)。下面是验证您的 GPU 可用性的代码。

我们将通过 Hugging Face 为 BERT 使用 PyTorch 接口,目前,Hugging Face 是最广泛接受和最强大的 PyTorch 接口,用于与 BERT 一起使用。Hugging Face 提供了 pytorch-transformers 存储库,带有附加库,用于为自然语言处理连接更多预训练的模型:GPT、GPT-2、Transformer-XL、XLNet、XLM。

正如您在下面看到的,为了让 torch 使用 GPU,您必须识别并指定 GPU 作为设备,因为在训练循环的后面,我们将数据加载到该设备上。

现在,我们可以将数据集上传到笔记本实例。在继续之前,请运行我们上一篇文章中的代码,使用 Python 函数 load_atis() 对数据集进行预处理。

BERT 期望输入特定格式的数据,用特殊的标记来标记句子的开始(【CLS】)和分隔/结束(【SEP】)。此外,我们需要我们的文本标记成与 BERT 的词汇相对应的标记。

'[CLS]  i want to fly from boston at 838 am and arrive in denver at 1110 in the morning  [SEP]'['[CLS]', 'i', 'want', 'to', 'fly', 'from', 'boston', 'at', '83', '##8', 'am', 'and', 'arrive', 'in', 'denver', 'at', '111', '##0', 'in', 'the', 'morning', '[SEP]']

对于每个标记化的句子,BERT 需要输入 id,这是一个整数序列,用于将每个输入标记标识为其在 BERT 标记化器词汇表中的索引号。

BERT 聪明的语言建模任务屏蔽了输入中 15%的单词,并要求模型预测缺失的单词。为了让 BERT 更好地处理多个句子之间的关系,预训练过程还包括一项额外的任务:给定两个句子(A 和 B),B 很可能是 A 后面的句子吗?因此,我们需要通过使用注意掩蔽和片段掩蔽的概念来告诉 BERT 我们正在解决什么任务。在我们的例子中,一个查询中的所有单词都将被预测,并且我们不会在每个查询中有多个句子。我们定义下面的面具。

现在是时候使用我们的数据创建微调 BERT 所需的所有张量和迭代器了。

最后,是时候微调 BERT 模型了,这样它就可以输出给定用户查询字符串的 intent 类。为此,我们使用BertForSequenceClassification,这是正常的 BERT 模型,在顶部添加了一个线性层用于分类。下面我们展示了该模型的概要。编码器摘要仅显示一次。相同的摘要通常会重复 12 次。为了简单起见,我们只显示其中一个。我们可以在开头看到 BertEmbedding 层,后面是每个编码器层的一个 Transformer 架构: BertAttentionBertIntermediateBertOutput 。最后,我们有了分类器层。

当我们输入数据时,整个预训练的 BERT 模型和额外的未训练的分类层在我们的特定任务上被训练。训练分类器相对便宜。底层已经有了很好的英语单词表示,我们只需要训练顶层,在底层进行一些调整来适应我们的任务。这是迁移学习的一种变体。

BERT fine-tuned on the Intent Classification task for Natural Language Understanding

来自变量 train_loss_set 的训练损失图看起来棒极了。整个训练循环不到 10 分钟。

现在,是关键时刻了。伯特是否过度适应?还是比我们之前的 LSTM 网络做得更好?我们现在加载测试数据集并准备输入,就像我们对训练集所做的那样。然后,我们创建张量,并在评估模式下对数据集运行模型。

使用 BERT,我们能够在意图分类任务上获得好的分数(95.93%)。这表明,使用预先训练的 BERT 模型,可以使用 PyTorch 界面以最少的工作量和训练时间快速有效地创建高质量的模型。

结论

在本文中,我演示了如何在 PyTorch 笔记本中加载预先训练好的 BERT 模型,并在您自己的数据集上对其进行微调,以解决特定的任务。在处理自然语言理解任务时,注意力很重要。当与来自 Transformer 的强大的单词嵌入相结合时,意图分类器可以显著提高其性能,正如我们成功展示的那样。

我的新文章提供了经过实践检验的 PyTorch 代码,用于在小队数据集上对 BERT 进行微调的问题回答。

[## BERT NLP——如何构建问答机器人

通过亲自动手的 PyTorch 代码理解直觉,BERT 在 SQuAD 上进行了微调。

towardsdatascience.com](/bert-nlp-how-to-build-a-question-answering-bot-98b1d1594d7b)

这一领域为未来的工作打开了一扇大门,特别是因为自然语言理解是几项技术的核心,包括对话式人工智能(聊天机器人、个人助理)和即将到来的增强分析,这被 Gartner 列为组织很快将面临的首要破坏性挑战。理解自然语言对传统的分析和商业智能产生了影响,因为高管们正在通过文本查询和数据叙述快速采用智能信息检索,而不是带有复杂图表的仪表板。

谢谢你从我这里读到更多。

[## 自然语言处理中的文本表示

理解书面单词:温习 Word2vec、GloVe、TF-IDF、单词袋、N-grams、1-hot 编码…

towardsdatascience.com](/representing-text-in-natural-language-processing-1eead30e57d8) [## 虚拟生成对抗网络(GAN)——循序渐进教程

用防弹 Python 代码理解、构建和训练 GANs 的终极初学者指南。

towardsdatascience.com](/generative-adversarial-network-gan-for-dummies-a-step-by-step-tutorial-fdefff170391) [## 张量流初学者终极指南

如何从零开始实现线性回归和梯度下降!了解 TensorFlow 的基础知识一次…

towardsdatascience.com](/the-ultimate-beginner-guide-to-tensorflow-af82fd4b8626) [## 深度学习的不确定性。如何衡量?

使用 Keras 对认知和任意不确定性进行贝叶斯估计的实践教程。走向社会…

towardsdatascience.com](/my-deep-learning-model-says-sorry-i-dont-know-the-answer-that-s-absolutely-ok-50ffa562cb0b)

带有 Tensorflow hub 的 Keras 中的 BERT

原文:https://towardsdatascience.com/bert-in-keras-with-tensorflow-hub-76bcbc9417b?source=collection_archive---------2-----------------------

Strong Analytics ,我们的许多项目都涉及使用深度学习进行自然语言处理。在最近的一个项目中,我们努力鼓励孩子们自由探索在线,同时确保他们免受网络欺凌和在线虐待,而另一个项目涉及预测日历和电子邮件活动的可扣除费用。

任何 NLP 项目的一个关键组成部分是使用技术快速测试和迭代的能力。Keras 提供了一种非常快速的方法来原型化最先进的深度学习模型,因此是我们在工作中使用的重要工具。

之前的一篇文章中,我们展示了如何集成 ELMo 嵌入作为定制的 Keras 层,以简化使用 Tensorflow hub 的模型原型。 BERT ,谷歌推出的语言模型,使用变形金刚和预训练来实现许多语言任务的最先进水平。它最近被添加到 Tensorflow hub 中,简化了 Keras 模型中的集成。

Deeply bidirectional unsupervised language representations with BERT

让我们开始建造吧!首先,我们加载之前使用的相同 IMDB 数据:

接下来,我们使用 tf-hub 模型对数据进行标记,这简化了预处理:

接下来,我们使用 Keras 构建一个自定义层,集成 tf-hub 的 BERT。模型很大(110,302,011 参数!!!)所以我们微调层的子集。

现在,我们可以使用 BERT 层轻松构建和训练我们的模型:

Using a GPU for large models like BERT is advised!

相当简单!在 Github 上查看完整的笔记本,并创建很酷的东西!

想和芝加哥的顶级数据科学家团队一起从事各种行业中具有挑战性的 NLP、机器学习和 AI 工作?我们正在招聘有才华的数据科学家和工程师!

strong.io 了解更多信息,并在 careers.strong.io 申请

伯特不擅长 ____。

原文:https://towardsdatascience.com/bert-is-not-good-at-7b1ca64818c5?source=collection_archive---------20-----------------------

查看 BERT 语言模型的一些缺点

CC

如果你对 NLP 感兴趣,我毫不怀疑你已经广泛阅读了关于 BERT 的内容。谷歌的一组研究人员于去年年底首次推出了这种新的语言模型,看到这种新语言模型的性能并思考其潜力,这是非常了不起的。它已经为一些语言任务设定了新的标准,并且在 Medium 上不缺少教程,这些教程提供了许多可以用 BERT 完成的语言建模项目的见解。对于这个领域来说,这是令人着迷的一年,至少可以说有了这样的发展。

在所有的赞扬中,我一直对伯特可能没有击中要害的地方感兴趣。Allyson Ettinger 有一篇有趣的论文叫做“伯特不是什么:来自一套新的语言模型心理语言学诊断的教训”测试了一些语言失误。我强烈推荐阅读整篇论文,因为她对自己的过程和结果有一些非常好的解释,但这里只是提到了 BERT 不足之处的一些见解:

常识与语用推理

他抱怨说,在她吻了他之后,他无法去掉脸上的红色。他最后只是要求她不要再穿那件 ____。

阅读上面的句子,你可能很容易推断出缺少的单词是“口红”。你可能没有意识到你正在做的是“口红”这个词之前没有被提及,你只是从之前的句子中推断出它,而没有直接提及它是如何使用的。有一个读者可以理解的语用推理。

在她的研究中,Ettinger 发现 BERT 在这样的测试中可以做得很好,但是很少成功。伯特能够更喜欢好的完成(“口红”)而不是差的完成(“睫毛膏”),但没有压倒性的信心。她发现,研究结果表明,它对常识性场景中的答案不像人那样敏感。它未能在很大程度上把握前一句话提供的上下文。

否认

柯基犬不是 _____。

因此,如果你问“柯基犬是 ____”,你可能会有一百万个选项,比如“一只狗”或“一只宠物”,但它不是什么?你肯定可以想出一个答案(“一只猫”、“一把椅子”),但是当你这样做的时候,你可以看到这些是如何需要一点独特的创造力,什么是最合适的取决于你所谈论的更大的背景。

艾丁格发现,尽管伯特非常擅长正面(“是”),但肯定会与负面(“不是”)作斗争。它能够将名词与相近的直接描述词联系起来,但不能处理肯定或否定的措辞。这是论文中的一个例子:

知更鸟是一种 ____

伯特大预言:鸟、知更鸟、人、猎人、鸽子

知更鸟不是 ____

伯特大型预测:鸟,知更鸟,人,猎人,鸽子

你看到的不是 double,它预测了两个相同的名词!虽然表现出很强的联想能力,但它显然没有处理否定。这是一个看起来很简单的概念对 BERT 来说并不简单的领域。

还有一个问题没有在这里详细说明,我不会破坏伯特在句子中角色互换的斗争,所以如果你觉得这些见解有趣,一定要深入研究这篇论文。

BERT、RoBERTa、DistilBERT 和 XLNet——使用哪一个?

原文:https://towardsdatascience.com/bert-roberta-distilbert-xlnet-which-one-to-use-3d5ab82ba5f8?source=collection_archive---------1-----------------------

image source (https://www.maxpixel.net)

oogle 的 BERT 和最近基于 transformer 的方法席卷了 NLP 领域,在几个任务上超过了最先进的技术。最近,人们展示了相对于 BERT 的各种改进——在这里,我将对比主要的相似之处和不同之处,以便您可以选择在您的研究或应用中使用哪一种。

BERT 是一个双向转换器,用于对大量未标记的文本数据进行预训练,以学习一种语言表示,可用于微调特定的机器学习任务。虽然 BERT 在几个具有挑战性的任务上超过了 NLP 最先进的技术,但其性能的提高可以归功于双向转换器、掩蔽语言模型的新颖预训练任务和 Next 结构预测,以及大量数据和谷歌的计算能力。如果你还不熟悉 BERT 的基本技术,我推荐你快速阅读这篇 3 分钟的博文。

最近,出现了几种方法来改善 BERT 的预测指标或计算速度,但不能同时改善两者。

XLNet 和 RoBERTa 提高了性能,而 DistilBERT 提高了推理速度。下表对它们进行了比较!

Comparison of BERT and recent improvements over it

**使用更大的小批量、学习率和步长进行更长时间的训练,并在掩蔽程序上有所不同。

***原始出版物中给出的数字,除非另有说明。

XLNet 是一个大型双向转换器,它使用改进的训练方法、更大的数据和更强的计算能力,在 20 个语言任务上实现了优于 BERT 的预测指标。

为了改进训练,XLNet 引入了置换语言建模,其中所有的记号都被预测,但顺序是随机的。这与 BERT 的屏蔽语言模型相反,在该模型中,仅预测屏蔽的(15%)标记。这也与传统的语言模型形成对比,在传统的语言模型中,所有的标记都是以连续顺序而不是随机顺序预测的。这有助于模型学习双向关系,从而更好地处理单词之间的依赖性和关系。此外,Transformer XL 被用作基础架构,即使在没有基于排列的训练的情况下,它也表现出良好的性能。

XLNet 使用超过 130 GB 的文本数据和运行 2.5 天的 512 个 TPU 芯片进行训练,这两个数据都比 BERT 大得多。

罗伯塔 。【RoBERTa 是脸书大学推出的经过稳健优化的 BERT 方法,它是对 BERT 的再培训,具有改进的培训方法、1000%以上的数据和计算能力。

为了改进训练过程,RoBERTa 从 BERT 的预训练中移除了下一句预测(NSP)任务,并引入了动态屏蔽,使得屏蔽的令牌在训练时期期间改变。还发现较大的批量训练规模在训练过程中更有用。

重要的是,RoBERTa 使用 160 GB 的文本进行预训练,包括 16GB 的书籍语料库和 BERT 中使用的英语维基百科。附加数据包括 CommonCrawl 新闻数据集(6300 万篇文章,76 GB)、网络文本语料库(38 GB)和来自 CommonCrawl 的故事(31 GB)。这加上庞大的 1024 V100 特斯拉 GPU 的运行一天,导致罗伯塔的预训练。

因此,RoBERTa 在 GLUE 基准测试结果上优于 BERT 和 XLNet:

Performance comparison from RoBERTa.

另一方面,为了减少 BERT 或相关模型的计算(训练、预测)次数,自然的选择是使用较小的网络来逼近性能。有许多方法可以用来做到这一点,包括修剪、提取和量化,然而,所有这些都会导致较低的预测度量。

DistilBERT 学习了一个经过提炼的(近似)版本的 BERT,保留了 97%的性能但只使用了一半数量的参数( paper )。具体来说,它没有令牌类型的嵌入,pooler,并且只保留了 Google 的 BERT 的一半层。DistilBERT 使用一种称为蒸馏的技术,这种技术近似于谷歌的 BERT,即一个较小的神经网络代替一个较大的神经网络。这个想法是,一旦一个大的神经网络被训练,它的全部输出分布可以用一个较小的网络来近似。这在某种意义上类似于后验近似。贝叶斯统计中用于后验近似的一个关键优化函数是 Kulback Leiber 散度,自然也在这里使用。

:在贝叶斯统计中,我们是在逼近真实的后验概率(来自数据),而使用蒸馏,我们只是在逼近由更大的网络学习到的后验概率。

那么用哪一个呢?

如果你真的需要一个更快的推理速度,但可以在预测指标上妥协几个百分点,DistilBERT 是一个合理的选择,但是,如果你正在寻找最好的预测指标,你最好使用脸书的 RoBERTa。

从理论上讲,XLNet 的基于排列的训练应该能够很好地处理依赖性,并且从长远来看可能会工作得更好。

然而,Google 的 BERT 确实提供了一个很好的工作基准,如果你没有上述任何关键需求,你可以用 BERT 保持你的系统运行。

结论

大部分性能提升(包括 BERT 本身!)是由于增加的数据、计算能力或训练过程。虽然它们有自己的价值,但它们往往在计算和预测指标之间进行权衡。需要在使用更少数据和计算资源的同时提高性能的根本性改进。

更新

讨论 2020 年和 2021 年最新方法的博客第二部分可以在找到

作者在@SuleimanAliKhan 发推文。—我们正在招聘—

伯特:应用商店评论的情感分析

原文:https://towardsdatascience.com/bert-sentiment-analysis-of-app-store-review-db68f7721d94?source=collection_archive---------16-----------------------

利用最先进的模型分析应用商店的用户情绪

Photo by William Hook on Unsplash

本文为您提供了对 app store 公众用户的评论进行情感分析的必要步骤。在本教程中,我将使用基于中文的模型来测试 Bert 应用于英语以外的语言时的性能。无论您使用哪种模型,情感分析的步骤都是一样的。如果您不确定使用哪种模型,请查看下面的链接,了解有关 BERT 团队提供的预训练模型的更多信息。如果你是 BERT 的新手,请查看我之前关于使用 BERT 的多分类任务的教程。本教程有 5 个部分:

  1. 数据集准备
  2. 培养
  3. 预言;预测;预告
  4. 结果
  5. 结论

1.数据集准备

我将使用来自 Taptap 的评论,这是一个迎合中国市场的游戏应用商店。请随意使用您自己的数据集。你甚至可以在谷歌 Play 商店和苹果商店的评论上测试一下。如果是这种情况,请确保您对 BERT 使用的是英语模型。让我们来看看我们可以从 Taptap 的评论中获得的细节。

Image by Author. Taken from a review in Taptap.

这里有相当多有用的数据:

  • 用户发布的评论
  • 评分从 1 到 5
  • 竖起大拇指
  • 数数拇指朝下
  • 其他用户对此评论的回复

我们可以很容易地使用可用的数据来标记情感。如果你有时间的话,强烈建议你手工贴标签。在这种情况下,我将使用评级来确定标签。

  1. 负:1-3⭐
  2. 中立:4 名⭐
  3. 阳性:5 ⭐

我设法从几个游戏的用户评论中收集了相当多的数据集。我已经将数据集加载到三个数据帧中。

  1. 训练数据集
  2. 评估数据集
  3. 测试数据集

让我们看看训练评估的数据内容。两者结构相同。

Image by Author

  • Guid :注释的 id。
  • 标签:评论的情绪。标签是基于用户的评价。
  • Alpha :一次性栏。我刚填了一个。
  • 文本:用户的实际评论。

如果您在创建上面的数据帧时遇到问题,请随意使用下面的代码(相应地修改):

df_bert = pd.DataFrame({'guid': id_list,
    'label': label_list,
    'alpha': ['a']*len(count),
    'text': text_list})

测试数据会略有不同,因为它应该只包含 guid文本

Image by Author

完成后,让我们使用以下代码将其保存为 tsv 文件(相应地修改数据帧的名称):

df_bert_train.to_csv('data/train.tsv', sep='\t', index=False, header=False)
df_bert_dev.to_csv('data/dev.tsv', sep='\t', index=False, header=False)
df_bert_test.to_csv('data/test.tsv', sep='\t', index=False, header=True)

请注意,文件存储在数据文件夹中。您可以根据自己的使用情况随意修改,但文件名必须如下所示:

  • train.tsv
  • 开发 tsv
  • test.tsv

此外, test.tsv 数据必须有一个不同于 train.tsvdev.tsv 的头。将 test.tsv 的割台设置为 True

完成数据准备后,让我们进入下一部分。

2.培养

我们现在将开始训练和微调模型。确保您已经从官方站点中克隆了存储库。此外,您应该将以下文件和文件夹放在存储库中的某个位置:

  • 数据目录:存放 train.tsv、dev.tsv、test.tsv 的目录
  • Vocab 文件:Vocab . txt 文件。它与您下载的模型一起提供。我创建了一个新的模型文件夹,并将文件放入其中。
  • 配置文件:Config . JSON 文件。它也包含在模型中。同样,我把它放在模型文件夹中。
  • 初始模型:用于训练的模型。您可以使用基于预先训练的模型,或者从您已经微调的现有模型中恢复。我将它存储在型号文件夹中
  • 输出目录:模型将要写入的文件夹。您可以简单地为它创建一个空文件夹。

下一步是确定以下变量:

  • 最大序列长度:分词后最大总输入序列长度。长于此长度的序列将被截断,短于此长度的序列将被填充。默认值是 128,但在本教程中我将使用 256。
  • 训练批量:训练的总批量。默认值为 32。我将在本教程中使用 8,因为我只在一个 GeForce RTX 2080 上训练。
  • 学习率:Adam 的初始学习率。默认为 5e-5。我已经将值设置为 2e-5。
  • Num train epoch :要执行的训练总次数。我将只使用默认值 3.0

如果您不确定使用哪种 GPU,请运行以下命令找出答案:

nvidia-smi

我们需要修改 run_classifier.py 中的代码,因为这个用例有 3 个类。打开 python 文件,在cola processor(data processor)类中搜索 get_labels ()函数。将其更改为以下内容并保存:

def get_labels(self):
    """See base class."""
    return ["0", "1", "2"]

完成后,激活虚拟环境,并将目录更改为存储库的根目录。在终端中键入以下命令。

CUDA_VISIBLE_DEVICES=0 python run_classifier.py --task_name=cola --do_train=true --do_eval=true --data_dir=./data/ --vocab_file=./model/vocab.txt --bert_config_file=./model/bert_config.json --init_checkpoint=./model/bert_model.ckpt --max_seq_length=256 --train_batch_size=8 --learning_rate=2e-5 --num_train_epochs=3.0 --output_dir=./output/ --do_lower_case=False

运行它,您应该会看到以下输出:

Image by Author

它可能需要相当长的时间来训练,这取决于你使用的数据集的大小。一旦训练完成,终端将输出以下内容。

让我们进入下一步。

3.预言;预测;预告

将在输出文件夹中生成一个模型。请检查最高步骤数,以确定您拥有的最新型号。如果您不确定哪个型号是最新的,请打开检查点文件找出答案。在我的例子中,我将 37125 作为模型的最后一步。

Image by Author

在同一个终端中,运行以下代码(确保最大序列长度与您在培训中使用的长度相同):

CUDA_VISIBLE_DEVICES=0 python run_classifier.py --task_name=cola --do_predict=true --data_dir=./data/ --vocab_file=./model/vocab.txt --bert_config_file=./model/bert_config.json --init_checkpoint=./output/model.ckpt-37125 --max_seq_length=256 --output_dir=./output/

代码将在输出文件夹中生成一个 test_results.tsv 文件。在我的例子中,我得到了以下结果。

Image by Author

每列代表预测类别的概率或置信水平,最高的是模型预测的类别。

4.结果

是我们分析结果的时候了。第一个任务是加载 test_results.tsv,并根据最高预测概率将其转换为 dataframe。使用以下代码读取文件:

df_result = pd.read_csv('output/test_results.tsv', sep='\t', header=None)
df_result.head()

您应该有一个包含三列的测试数据的数据框架(我将其命名为 df_test_with_label):

  • 全局唯一标识符
  • 标签
  • 文本

创建一个新的数据帧,并使用 idxmax 映射结果。

df_predict = pd.DataFrame({'guid':df_test_with_label['guid'],
                            'label':df_result.idxmax(axis=1),
                            'text':df_test_with_label['text'],})
df_predict.head()

导入

完成后,让我们从 sklearn 导入以下度量函数来计算我们的模型的性能。

from sklearn.metrics import accuracy_score, precision_score, recall_score, confusion_matrix

准确(性)

你可以如下计算模型的精确度。

accuracy_score(df_test_with_label['label'], df_predict['label'])

结果得到 0.7033952594490711。

回忆

基于 sklearn 文档。召回率是比率tp / (tp + fn),其中tp是真阳性的数量,fn是假阴性的数量。召回直观上是分类器找到所有肯定样本的能力。最佳值为 1,最差值为 0。它还需要一个名为 average 的参数。我正在将它设置为

recall_score(df_test_with_label['label'], df_predict['label'], average='macro')

运行代码的结果是输出 0.6312777479889565。

精确

精度是比率tp / (tp + fp),其中tp是真阳性的数量,fp是假阳性的数量。精确度直观上是分类器不将阴性样品标记为阳性的能力。最佳值为 1,最差值为 0。同样,平均参数被设置为

precision_score(df_test_with_label['label'], df_predict['label'], average='macro')

精度比 recall 低一点,只有 0.6375505256。

混淆矩阵

仅仅有回忆和精确是不够好的,因为我们不知道哪个类有最好的预测,哪个类得到最差的结果。我们可以使用混淆矩阵方法来为我们提供这方面的更多见解。

confusion_matrix(df_test_with_label['label'], df_predict['label'])

我得到了以下输出。

Image by Author

我们可以看到,该模型在预测第二个标签(中性)时有一些困难。在这种情况下,我们可能需要对数据集进行一些修改,并再次尝试重新训练它。

5.结论

祝贺您完成本教程。让我们回顾一下今天所学的内容。

首先,我们开始为我们的情感分析项目准备数据集。这包括获取数据并根据提供的详细信息自动标记数据。在我们的例子中,我们使用应用评论等级作为情感的标签。我们把它定为三类,即消极、中立和积极。我们从数据集生成了三个 tsv 文件。

接下来,我们配置了所需的参数,如最大序列长度和批量大小。我们训练该模型,并使用它对测试数据进行预测。

最后,我们将结果加载到一个数据框架中,并使用 sklearn 的度量函数对其进行分析。所提供的见解允许我们确定模型的性能。

感谢阅读,希望你喜欢这篇教程。下一篇文章再见。祝你有美好的一天!❤️

参考

  1. https://towards data science . com/beginners-guide-to-Bert-for-multi-class ification-task-92f 5445 c2d 7 c
  2. https://github.com/google-research/bert
  3. https://sci kit-learn . org/stable/modules/classes . html # module-sk learn . metrics
  4. https://www.taptap.com/

3 分钟内介绍 BERT 技术

原文:https://towardsdatascience.com/bert-technology-introduced-in-3-minutes-2c2f9968268c?source=collection_archive---------3-----------------------

oogle BERT 是一种用于自然语言理解的预训练方法,它比以往任何时候都更好地执行各种 NLP 任务。

BERT 分两步工作,首先,它使用大量未标记数据,以无监督的方式学习一种语言表示,称为预训练。然后,预训练模型可以以监督的方式微调,使用少量标记的训练数据来执行各种监督任务。预训练机器学习模型已经在包括图像处理和自然语言处理(NLP)在内的各个领域取得了成功。

BERT 代表 B 方向En 编码器 R 代表 T 变压器。它基于 transformer 架构(Google 在 2017 发布)。通用转换器使用编码器和解码器网络,然而,由于 BERT 是预训练模型,它仅使用编码器来学习输入文本的潜在表示。

Photo by Franki Chamaki on Unsplash

技术

BERT 将多个变压器编码器堆叠在一起。transformer 基于著名的多头注意力模块,该模块在视觉和语言任务方面都取得了巨大的成功。有关注意力的回顾,请参见

伯特的艺术表演基于两点。首先,称为掩蔽语言模型(MLM)下一个句子预测(NSP) 的新颖的预训练任务。第二,大量的数据和计算能力来训练 BERT。

MLM 使得从文本中执行双向学习成为可能,即它允许模型从出现在之前和之后的单词中学习每个单词的上下文。这在以前是不可能的!之前最先进的方法叫做生成式预训练使用的是从左到右训练 ELMo 使用的是浅层双向训练。

MLM 预训练任务将文本转换成记号,并将记号表示用作训练的输入和输出。标记的随机子集(15%)在训练期间被屏蔽,即隐藏,并且目标函数是预测标记的正确身份。这与使用单向预测作为目标或者使用从左到右和从右到左训练来近似双向的传统训练方法形成对比。NSP 任务允许伯特通过预测一对句子中的下一句是否是正确的来学习句子之间的关系。为此,用 50%的随机对补充 50%的正确对,并训练模型。伯特同时训练 MLM 和 NSP 目标。

数据和 TPU/GPU 运行时

伯特使用了总共 33 亿个单词进行训练,其中 25 亿个来自维基百科,0.8 亿个来自图书语料库。训练是使用 TPU 完成的,而 GPU 的估计如下所示。

Training devices and times for BERT; used TPU and estimated for GPU.

使用 2.5K 至 392K 标记的样品进行微调。重要的是,超过 100K 训练样本的数据集在各种超参数上表现出稳健的性能。每个微调实验在单个云 TPU 上运行 1 小时以内,在 GPU 上运行几个小时。

结果

BERT 大大超过了 11 个最先进的 NLP 任务。这些任务分为三个主要类别,文本分类、文本蕴涵和 Q/A。在两个任务 SQUAD 和 SWAG 中,BERT 第一个超越了人类水平的表现!

BERT results from the paperhttps://arxiv.org/abs/1810.04805

在你的分析中使用伯特

BERT 可作为开源软件获得:【https://github.com/google-research/bert】T2,并针对 104 种语言进行了预训练,在 TensorFlow 和 Pytorch 中实现。

它可以针对几种类型的任务进行微调,如文本分类、文本相似性、问答、文本标注(如词性)、命名实体识别等。然而,预先训练 BERT 在计算上可能很昂贵,除非你使用 TPU 的或者类似于 Nvidia V100 的 GPU。

BERT 的人还发布了一个单一的多语言模型,该模型基于整个维基百科的 100 种语言。多语种的 BERT 比那些只接受一种语言训练的要低几个百分点。

评论

MLM 的 BERT 掩蔽策略使模型偏向实际单词。这种偏差对训练的影响没有显示出来。

更新:最近在 BERT-之上提出了几个新方法,这篇博文讨论了使用哪一个?

参考

[1]https://cloud.google.com/tpu/docs/deciding-pod-versus-tpu

[2]假设第二代 TPU,第三代快 8 倍。https://en.wikipedia.org/wiki/Tensor_processing_unit

[3]http://timdettmers . com/2018/10/17/tpus-vs-GPU-for-transformers-Bert/

使用 Keras 在 3 行代码中实现 BERT 文本分类

原文:https://towardsdatascience.com/bert-text-classification-in-3-lines-of-code-using-keras-264db7e7a358?source=collection_archive---------3-----------------------

2019–08–17:文章中的代码演示已经分享到 Google Colab 上。

BERT ( 来自变形金刚的双向编码器表示)是谷歌开发的深度学习模型。它代表了今年机器学习的重大突破之一,因为它在 11 个不同的自然语言处理(NLP)任务中取得了最先进的结果。此外,谷歌开源了代码,并提供了类似于 ImageNet 上预训练的计算机视觉模型的预训练模型供下载。由于这些原因,人们对 BERT 仍有很大的兴趣(尽管其他车型略微超过了它)。

虽然 BERT 打破了许多不同任务的记录,从问答(SQuAD v1.1)到自然语言推理,文本分类仍然是最实用和广泛适用的 NLP 任务之一。在本文中,我们将展示如何用少至 3 行代码将 BERT 应用于文本分类问题。为了实现这一点,我们将使用 ktrain ,一个类似 fastai 的接口到 Keras。 ktrain 是开源的,在这里可以获得

要安装 ktrain ,只需输入以下命令:

pip3 install ktrain

为了在 ktrain 和 Keras 中演示 BERT 文本分类,我们将使用在许多学术论文中使用的 IMDb 电影评论数据集对电影评论进行情感分析。目标是正确地将验证集中的每个电影评论分类为正面或负面。你可以从这里下载数据集,然后解压。首先,让我们导入 ktrainktrain.text 模块:

import ktrain
from ktrain import text

导入了 ktrain 之后,我们开始吧。

步骤 1:加载数据

我们将首先使用texts_from_folder函数从上面提取的文件夹中加载数据。

第一个参数应该是提取 Imdb 数据集的文件夹的路径。maxlen参数指定每个电影评论中要考虑的最大字数(较长的评论被截断到这个长度)。BERT 可以处理的最大长度为 512,但是如果可以的话,您会希望使用更少的长度来减少内存并提高速度。必须以特定的方式对文本进行预处理,以便在 BERT 中使用。这通过将preprocess_mode设置为‘Bert’来实现。如果需要的话,BERT 模型和词汇表将被自动下载。最后,texts_from_folder函数需要以下目录结构,aclImdb 文件夹已经符合该结构:

├── folder
    │   ├── train
    │   │   ├── class0       # folder for class 0 documents
    │   │   ├── class1       # folder for class 1 documents
    │   │   ├── class2       # folder for class 2 documents
    │   │   └── classN       # folder for class N documents
    │   └── test 
    │       ├── class0       # folder for class 0 documents
    │       ├── class1       # folder for class 1 documents
    │       ├── class2       # folder for class 2 documents
    │       └── classN       # folder for class N documents

步骤 2:加载 BERT 并将其包装在一个学习者对象中

get_learner的第一个参数使用 ktrain text_classifier函数来用随机初始化的最终密集层加载预训练的 BERT 模型。第二个和第三个参数分别是定型数据和验证数据。get_learner的最后一个参数是批量大小。我们基于谷歌对12GBGPU 的以下建议,使用 6 个小批量:

Seq Length corresponds to the maxlen argument from STEP 1.

第三步:训练模型

为了训练模型,我们使用了 ktrainfit_onecycle方法,该方法采用了1 周期学习率策略,该策略在训练的前半段线性增加学习率,然后在后半段降低学习率:

有关调整学习率的更多详情,请参见 ktrain 上的这篇文章。根据论文中的建议使用最大学习率 2e-5 (并通过执行 ktrain 学习率查找器确认)。

Keras 输出可以看出,这在单个历元中实现了 93.71% 的精度:

由于我们似乎没有过度拟合,如果需要的话,该模型可以针对更多的时期进行训练,以产生甚至更高的精度。例如,在这个数据集上,三个时期的训练可以产生超过 94% 的准确度。

关于伯特实践的几点思考

速度: 虽然 BERT 的表现令人印象深刻,但在训练和推理(即对新数据的预测)方面都相对较慢。试图通过压缩来提高 BERT 的速度似乎并不成功。出于这些原因,如果训练超过一个历元,您可能希望省略get_learner中的val_data参数,并且仅在训练结束时进行验证。这可以在 ktrain 中用learner.validate的方法完成,如这个 Google Colab 笔记本所示。鉴于 BERT 的缓慢,您还应该考虑更简单和更快的模型作为替代方案,以决定 BERT 提高的准确性是否值得。在某些情况下,你会惊讶地发现事实并非如此。

更新 2020-01–14:【蒸馏】可用于 加速变压器型号 。关于在 ktrain 中使用 DistilBERT 模型的教程,请参见 我们的新媒体帖子

内存: BERT 可能相当占用内存。如果您遇到可能表明您超出 GPU 内存限制的错误(例如Blas GEMM launch failedCUDA_ERROR_OUT_OF_MEMORY,您可以尝试减少步骤 2 中使用的batch_size参数或步骤 1 中使用的maxlen参数。

保存 BERT 模型: 在数据集上训练 BERT 后,可能需要将其保存到磁盘上,以便以后对新数据进行预测。如您所知,您可以分别使用model.save方法和 Keras 内置的load_model函数在 Keras 中保存和加载模型。然而,Keras load_model函数在这里不会像预期的那样工作,因为 BERT 使用了自定义层。在重新执行上述步骤 1 和 2 后,您可以使用 ktrain 中的learner.load_model方法加载模型,而不是使用 Keras 的内置load_model函数。这将正确工作,因为 ktrain 将自定义 BERT 层传递给 Keras 的load_model函数。或者,您可以使用对model.save_weightsmodel.load_weights的标准调用来保存和加载权重。(在这两种情况下,Keras 模型总是可以作为learner.model直接访问。)

文章源代码:这篇文章的源代码以下面这个 Jupyter 笔记本的形式提供:IMDb-伯特. ipynb 。笔记本包括估计好的学习率和对新数据进行预测的例子。请随意在您自己的数据集上进行尝试。

更多信息:有关 ktrain、的更多信息,请参见关于 ktrain 的教程笔记本和我们之前的 TDS 媒体出版物:

k Train:Keras 的一个轻量级包装器,用于帮助训练神经网络

Google Colab 上使用 ktrain ?另请参见BERT 在多分类设置中的演示

参考

  • ktrain 通过 keras_bert 包由赵 HG 支持 BERT 文本分类。

伯特来救援了。

原文:https://towardsdatascience.com/bert-to-the-rescue-17671379687f?source=collection_archive---------3-----------------------

在这篇文章中,我想展示如何将 BERT 应用于一个简单的文本分类问题。我假设您或多或少地熟悉 BERT 在高层次上是什么,并通过向您展示如何在您的工作中利用它来更加关注实践方面。粗略来说,BERT 是一个知道表示文本的模型。你给它一些序列作为输入,然后它左看右看几次,产生每个单词的向量表示作为输出。在他们的论文中,作者描述了两种使用 BERT 的方法,一种是“特征提取”机制。也就是说,我们使用 BERT 的最终输出作为另一个模型的输入。通过这种方式,我们使用 BERT 从文本中“提取”特征,然后在一个单独的模型中用于手头的实际任务。另一种方法是“微调”伯特。也就是说,我们在 BERT 上添加额外的层,然后一起训练整个东西。通过这种方式,我们可以训练我们的附加层,还可以改变(微调)层的权重。在这里,我想展示第二种方法,并介绍一个非常简单和流行的文本分类任务的分步解决方案——IMDB 电影评论情感分类。这个任务可能不是最难解决的任务,将 BERT 应用于它可能有点矫枉过正,但是这里显示的大多数步骤对于几乎每个任务都是相同的,不管它有多复杂。

在深入实际代码之前,让我们了解一下 BERT 的一般结构,以及在分类任务中使用它需要做些什么。如前所述,一般来说,BERT 的输入是一个单词序列,输出是一个向量序列。BERT 允许我们根据它的输出执行不同的任务。因此,对于不同的任务类型,我们需要稍微改变输入和/或输出。在下图中,您可以看到 4 种不同的任务类型,对于每种任务类型,我们可以看到模型的输入和输出应该是什么。

您可以看到,对于输入,在每个序列的开头总是有一个特殊的[CLS]标记(代表分类),还有一个特殊的[SEP]标记将输入分成两部分。

对于输出,如果我们对分类感兴趣,我们需要使用第一个令牌([CLS]令牌)的输出。对于更复杂的输出,我们可以使用所有其他的令牌输出。

我们对“单句分类”感兴趣(右上),所以我们将添加特殊的[CLS]标记,并将其输出作为线性层的输入,然后激活sigmoid,执行实际的分类。

现在让我们来理解手头的任务:给定一个电影评论,预测它是正面的还是负面的。我们使用的数据集是 PyTorch-NLP 库中的 50,000 条 IMDB 评论(25,000 条用于训练,25,000 条用于测试)。每个评论都被标记为posneg。在训练集和测试集中,正面评价和负面评价各占 50%。

你可以在这个笔记本里找到所有的代码。

1.准备数据

我们使用pytorch-nlp库加载数据:

train_data, test_data = imdb_dataset(train=True, test=True)

这个数据集中的每个实例都是一个字典,包含两个字段:textsentimet

{
    'sentiment': 'pos',  
    'text': 'Having enjoyed Joyces complex nove...'
}

我们为每个集合创建两个变量,一个用于文本,一个用于标签:

train_texts, train_labels = list(zip(*map(lambda d: (d['text'], d['sentiment']), train_data)))test_texts, test_labels = list(zip(*map(lambda d: (d['text'], d['sentiment']), test_data)))

接下来,我们需要标记我们的文本。伯特是用词块符号化来训练的。这意味着一个单词可以分解成多个子单词。例如,如果我对句子“嗨,我的名字是马頔”进行分词,我会得到:

tokenizer.tokenize('Hi my name is Dima')# OUTPUT
['hi', 'my', 'name', 'is', 'dim', '##a']

这种标记化在处理词汇之外的单词时是有益的,并且它可以帮助更好地表示复杂的单词。子词是在训练期间构建的,并且依赖于模型被训练的语料库。当然,我们可以使用任何其他的记号化技术,但是如果我们使用训练 BERT 模型的相同记号化器进行记号化,我们会得到最好的结果。PyTorch-Pretrained-BERT 库为我们提供了每个 BERTS 模型的标记器。这里我们使用基本的bert-base-uncased型号,还有其他几种型号,包括更大的型号。BERT 的最大序列长度是 512,因此我们将截断任何长于此长度的评论。

下面的代码创建标记器,标记每个评论,添加特殊的[CLS]标记,然后只获取训练集和测试集的前 512 个标记:

tokenizer = BertTokenizer.from_pretrained('bert-base-uncased', do_lower_case=True)train_tokens = list(map(lambda t: ['[CLS]'] + tokenizer.tokenize(t)[:511], train_texts))test_tokens = list(map(lambda t: ['[CLS]'] + tokenizer.tokenize(t)[:511], test_texts))

接下来,我们需要将每个评论中的每个标记转换成标记化器词汇表中的id。如果有一个标记不在词汇表中,标记器将使用特殊的[UNK]标记并使用它的 id:

train_tokens_ids = list(map(tokenizer.convert_tokens_to_ids, train_tokens))test_tokens_ids = list(map(tokenizer.convert_tokens_to_ids, train_tokens_ids))

最后,我们需要填充我们的输入,这样它将具有相同的大小 512。这意味着对于任何少于 512 个令牌的评论,我们将添加零以达到 512 个令牌:

train_tokens_ids = pad_sequences(train_tokens_ids, maxlen=512, truncating="post", padding="post", dtype="int")test_tokens_ids = pad_sequences(test_tokens_ids, maxlen=512, truncating="post", padding="post", dtype="int")

我们的目标变量目前是一个由negpos字符串组成的列表。我们将把它转换成布尔的numpy数组:

train_y = np.array(train_labels) == 'pos'
test_y = np.array(test_labels) == 'pos'

2.模型结构

我们将使用 PyTorch 和优秀的py torch-pre trained-BERT库来构建模型。实际上,这个库中已经实现了一个非常相似的模型,我们可以使用这个模型。对于这篇文章,我想自己实现它,这样我们可以更好地了解正在发生的事情。

在我们创建模型之前,让我们看看如何使用在 PyTorch-Pretrained-BERT 库中实现的 BERT 模型:

bert = BertModel.from_pretrained('bert-base-uncased')x = torch.tensor(train_tokens_ids[:3])
y, pooled = bert(x, output_all_encoded_layers=False)print('x shape:', x.shape)
print('y shape:', y.shape)
print('pooled shape:', pooled.shape)# OUTPUT
x shape :(3, 512)
y shape: (3, 512, 768)
pooled shape: (3, 768)

首先,我们创建 BERT 模型,然后我们创建 PyTorch 张量,其中包含来自我们训练集的前 3 条评论,并将其传递给它。输出是两个变量。让我们来理解所有的形状:x的大小是(3, 512),我们只取了 3 个评论,每个评论有 512 个标记。y的大小为(3, 512, 768),这是每个令牌的 BERTs 最终层输出。我们可以使用output_all_encoded_layer=True来获得所有 12 层的输出。使用大小为 768 的向量来表示每个评论中的每个标记。pooled的大小是(3, 768)这是我们的[CLS]令牌的输出,我们序列中的第一个令牌。

我们的目标是采用 BERTs 池输出,应用线性层和sigmoid激活。我们的模型看起来是这样的:

class BertBinaryClassifier(nn.Module):
    def __init__(self, dropout=0.1):
        super(BertBinaryClassifier, self).__init__() self.bert = BertModel.from_pretrained('bert-base-uncased')
        self.linear = nn.Linear(768, 1)
        self.sigmoid = nn.Sigmoid()

    def forward(self, tokens):
        _, pooled_output = self.bert(tokens, utput_all=False)
        linear_output = self.linear(dropout_output)
        proba = self.sigmoid(linear_output)
        return proba

PyTorch 中的每个模型都是一个nn.Module对象。这意味着我们构建的每个模型都必须提供 2 个方法。__init__ 方法声明了模型将使用的所有不同部分。在我们的例子中,我们创建了将要微调的 BERT 模型、线性层和 Sigmoid 激活。forward方法是正向传递期间运行的实际代码(类似于sklearnkeras中的predict方法)。这里我们将tokens输入传递给 BERT 模型。BERT 的输出是 2 个变量,正如我们之前看到的,我们只使用第二个变量(使用_名称是为了强调没有使用这个变量)。我们将汇集的输出传递给线性层。最后,我们使用 Sigmoid 激活来提供实际概率。

3.培训/微调

训练相当标准。首先,我们准备好张量和数据加载器:

train_tokens_tensor = torch.tensor(train_tokens_ids)
train_y_tensor = torch.tensor(train_y.reshape(-1, 1)).float()test_tokens_tensor = torch.tensor(test_tokens_ids)
test_y_tensor = torch.tensor(test_y.reshape(-1, 1)).float()train_dataset = TensorDataset(train_tokens_tensor, train_y_tensor)
train_sampler = RandomSampler(train_dataset)
train_dataloader = DataLoader(train_dataset, sampler=train_sampler, batch_size=BATCH_SIZE)test_dataset = TensorDataset(test_tokens_tensor, test_y_tensor)
test_sampler = SequentialSampler(test_dataset)
test_dataloader = DataLoader(test_dataset, sampler=test_sampler, batch_size=BATCH_SIZE)

我们将使用Adam优化器和二元交叉熵(BCELoss)损失,并训练 10 个时期的模型:

bert_clf = BertBinaryClassifier()
bert_clf = bert_clf.cuda()
optimizer = Adam(bert_clf.parameters(), lr=3e-6)
bert_clf.train()for epoch_num in range(EPOCHS):
    for step_num, batch_data in enumerate(train_dataloader):
        token_ids, labels = tuple(t.to(device) for t in batch_data)
        probas = bert_clf(token_ids)
        loss_func = nn.BCELoss()
        batch_loss = loss_func(probas, labels)
        bert_clf.zero_grad()
        batch_loss.backward()
        optimizer.step()

对于那些不熟悉 PyTorch 的人,让我们一步一步地看代码。

首先,我们创建上面定义的BertBinaryClassifier。我们通过应用bert_clf.cuda()将其移动到 GPU。我们用我们的模型参数(优化器将会更新)和一个学习率创建了 Adam 优化器,我发现效果很好。

对于每个时期中的每个步骤,我们执行以下操作:

  1. 通过应用.to(device)将我们的张量移动到 GPU
  2. bert_clf(token_ids)给出了概率(向前传递)
  3. loss_func(probas, labels)计算损失
  4. 将上一步的梯度归零
  5. 通过batch_loss.backward()计算并传播新的梯度
  6. 通过optimizer.step()更新与梯度相关的模型参数

经过 10 个时代,我得到了相当不错的结果。

结论

BERT 是一个非常强大的模型,可以应用于许多任务。对我来说,它为我的工作任务提供了一些非常好的结果。我希望这篇文章能帮助你更好地理解与 BERT 一起工作的实际方面。如前所述,您可以在本笔记本中找到代码

嵌入式投影仪中的 BERT 可视化

原文:https://towardsdatascience.com/bert-visualization-in-embedding-projector-dfe4c9e18ca9?source=collection_archive---------14-----------------------

这个故事展示了如何在 Tensorflow 的 Tensorboard 嵌入投影仪中可视化预训练的 BERT 嵌入。该故事使用了大约 50 个独特的句子及其通过 TensorFlow Hub BERT 模型生成的 BERT 嵌入。

BERT visualization in Embedding Projector

创造历史

为了生成 BERT 嵌入1,我使用了模型为BERT-base-uncased的 BERT 的 TF Hub 实现。在我的以前的故事中看到一个简短的介绍,或者在 Colab 上查看代码!

交互式嵌入式投影仪可视化包含两个数据集。第一个有 20 个随机句子,由这个随机句子生成器生成。第二个包含 23 个自制的句子,只有 36 个独特的标记。该数据集具有一小组标记,因此嵌入投影仪可以通过标记给点着色。

使用主成分分析的数据可视化

高维数据的可视化并不总是容易的。为了用 2D 或 3D 来表示数据以便我们可以看到,我们必须将数据投影到一个更低的维度,而不会丢失太多的信息。

一种方法是使用 PCA(主成分分析)[2]。PCA 找到正交基,从而将数据投影到这些基上,点之间的总差异是最大的。如果你对 PCA 更感兴趣,我在之前的一个故事中描述过。下图显示了一个单词的 100 个嵌入向量到其前两个主要成分的 2D 投影。

PCA for the embeddings of the word ‘city.’

使用 PCA,我们可以直观地识别嵌入数据集中的聚类。分析单词' city 和' game,'的嵌入,我们可以看到基于嵌入,有两种不同类型的点。

PCA for the embeddings of the words ‘city’ and ‘game

嵌入式投影仪

用 PCA 说明越来越多的数据并不总是最好的选择。谷歌的 TensorBoard 提供了一个嵌入式投影仪来使用 PCA、UMAP 3和 t-SNE [4]在 2D 或 3D 中可视化数据。不幸的是,嵌入式投影仪无法处理这么多样本的数据。它也不能显示超过 50 类的颜色。因此,这里使用的数据只包含几个句子。如果你想探索 TensorBoard 的可视化工具,我建议这个教程

我建议你激活颜色来获得单词/句子类别的感觉。下图显示了投影的视图。

Embedding Projector. Activate colors using the drop-down in the red circle!

让我们看看交互式投影仪中的 UMAP 投影、t-SNE 投影和主成分分析投影!我建议阅读这篇介绍来了解 UMAP 和 t-SNE 。或者看参考文献找原论文!

UMAP 和 t-SNE 都有同样的两个抽象步骤:

  1. 基于最近邻,保留连接、相似性和数据集的结构。
  2. 使用梯度下降优化低维表示。

UMAP 嵌入群

让我们用 UMAP 来形象化令牌之间的关系!

如果我们对 20 个随机句子数据集使用具有 5 个邻居的 UMAP,我们可以看到 UMAP 投影对句子具有单独的记号组。在下图中,我们可以看到句子的标记彼此接近。一个句子的标记有相同的颜色。

UMAP 2D projection with sentence colorization

如果我们使用第二个数据集,有 36 个标记的 23 个句子,我们也可以看到标记的颜色。让我们再次使用有 5 个邻居的 2D UMAP!在这里,我们可以看到,UMAP 组点标记水平,但句子的标记也有一个主要领域。

2D UMAP visualization: a) tokens of a sentence, b) token colorization, c) sentence colorization

摘要

这个故事展示了 20 个双 BERT 嵌入表示数据集的可视化,每个数据集包含大约 20 个不同的句子。这个故事包含了生成数据集的 Colab 代码和一个带有预加载数据的交互式可视化工具。

参考

1 Devlin,j .,Chang,M. W .,Lee,k .,& Toutanova,K. (2018 年)。 Bert:用于语言理解的深度双向转换器的预训练。 arXiv 预印本 arXiv:1810.04805

[2]h .霍特林(1933 年)。将复杂的统计变量分析成主要成分。 《教育心理学杂志》24 (6),417 页。

3麦金尼斯、希利和梅尔维尔(2018 年)。 Umap:一致流形逼近和投影降维。 arXiv 预印本 arXiv:1802.03426

[4]马滕博士和辛顿博士(2008 年)。使用 t-SNE 可视化数据。 机器学习研究杂志9(11 月),2579–2605。

自然语言处理搜索训练

原文:https://towardsdatascience.com/bert-your-new-search-ally-840d1c6cd2bc?source=collection_archive---------31-----------------------

来自变压器的双向编码器表示

名义评分从来都是零和博弈,而在搜索中,数学从来都是多和博弈。信息如何被索引、编译和传送背后的复杂结构是变量规模的逻辑因素。

通过 BERT(来自变压器的双向编码器表示)和 NLP(自然语言处理),这些结果的决定性度量变得更加突出。

类似于以先进先出(FIFO)方式运作的仓库,其中一个项目作为所选产品,影响产品需求要求供应。随着回报率的边际开始趋于平稳,引入可行的替代方案和细分市场成为并行市场的一个认知特征。毛巾需要一个架子,干净的毛巾需要一个架子,架子上有纸巾等等。

一旦市场运作建立起来,你的仓库就变成了一个物品的聚集地,足够占据全球发达家庭的浴室。为这些利益服务,你的运作开始规模化,因为对物流影响的需求成为一种定价游戏,以满足消费者的需求。毛巾仓库、主要支持产品和次要创新产品成为您的业务遍布全球的目录点。

作为前馈训练方法的供给和需求范例

这些产品变成了编码器,仓库变成了变压器,你每月邮寄的目录变成了搜索引擎。

当理想的复杂性是适当的词缀,而不是开发成功的邻近性时,解释机器学习理论就变成了一系列类似这些的隐喻。深入解释毛巾及其对卫生的影响,同时理解市场规模上消费者需求的开始,提供将这些实践用于商业的经验。

随着业务从一个产品扩展到一个仓库体验 (1:1) ,移动物品和填充空间的操作顺序开始划分和展开。随着越来越多的产品来满足需求和支持主要产品,空间本身变得共享,基于需求的倾向。

当运输成本超过利润的明显距离之外的地区的需求增加时,就需要额外的运输立足点。

100 英里,是对分化的兴起的一个有力的基础认识,同样地以 15 度的经度,作为时间。

在这一点上,企业现在跨两个仓库复制其方法,以支持具有独特产品的多个社区。在某些情况下,在社区 1 每户可能有更多人,需要更多毛巾,而社区 2 有更多淋浴,需要更多方式存放毛巾的情况下,也有抵消信息分发的特定需求。所应用的分隔空间的影响支持正在入库的货物数量的优化。

来自预训练数据源的参考编码

参考社区的利基部分,仓库抵消了额外的需求,并预测了社区的个人需求,以优化效率和利润。

编码器是企业的产品,因为它们是搜索引擎贡献的类型,每个企业都会在数字空间做出贡献。定义这些经验是成为一种等同的艺术形式,并列举评估其重量的原则。

这些编码器考虑了每条毛巾的重量值,提供了与被评定为较软的毛巾、纱线支数较多的毛巾以及购买频率较高的产品的更多一致性。

在这个意义上,权重是一个数学函数,它考虑了频率的总和。将总和的最高比率归因为最主要的;最有利。

这为消费者提供了理解他们想要寻找的信息如何不仅是真实的,而且为他们的体验提供了最佳解决方案的效率,因为它考虑了不直接可见但有影响力的数据。

这些编码器被认为是人工智能中过滤输入的节点。将价值表示划分为所提供的附加价值的概念是整个搜索体验的一部分,也是解决方案价值的单独加权。

解读语言相关性的转换策略

随着理解原则的积累,随着时间的推移,企业自身将向市场提供有竞争力的补充产品。对成功公司的观察,对机会本身的观察,就变成了一个分裂的交集,叠加在商品的使用上。

像这样的市场变得非常强劲,从颜色到定制,毛巾及其市场空间成为一个很好的例子,因为它们需要一定的操作经验,但价值基于简单的叙述。

随着这些市场的融合,该空间需要考虑最初的品牌、仓库和产品,同时还要根据其竞争和产品的评估标准来衡量其重量。

为这些市场提供公平的服务、目录、索引和搜索意味着理解个人的贡献,并将其作为进入市场的有效手段。从产品的数据,在这种情况下,神经节点的编码器的解释,然后有一个评估算法,转换加权统计的输出,以呈现一个结果。

NLP 输入操作和源的双向一致性

对数据、市场、产品供应、评论、购买和访问的观察被收集到一系列可测量的统计数据中,成为需求曲线。根据这条曲线,这种加权的实现方式被分解,然后被重构,以说明产品对空间的单独贡献,同时考虑市场的需求以及与该产品的交互。

这些空间现在遇到的次要方向不仅是产品及其【需求】的有效性,而且是其体验的“声誉”的以下性质。与所有产品加权统计数据同时连接在一起的是上下文信息,该信息还提供了对市场的洞察,以及所有其自身的交互。

简而言之,内容是围绕预期意图积累的支持信息的集合,以近似在没有直接对话或体验的情况下错过的解释摩擦。

多信息文本

页面交互是一个权重很大的指标,它提供了对在引导和定义个人花费时间的空间周围累积空间的价值的理解。这个空间中的词提供了独特的参考,为 fit 提供了解释。

录像

观看视频并与视频互动提供了对与 观看时间分享喜欢评论 的参与度的洞察。阐明这一指标,公司可以利用社区来提高对其产品的考虑。开发带有描述和术语的清晰标题,以与他们的产品保持一致,在这个公式中占据了更多的空间。关注他们对注释和字幕的贡献提供了另一个有利的需求因素。

复习

特定于产品的措辞内容和评论深度提供了对产品相关性的权重和深度的数字计算的洞察。将消费者的愿景与公司的愿景相一致成为一个有价值的标识符。

开放式数据

数据领域中产品的可用性,例如通过引擎索引的产品、开发的具有开放端点的 API,以及页面中可索引的结果都提高了相关性。

数据消费的自然语言处理算法

当试图理解空间能力的差异时,引擎必须测量作为一种结构体验的生存能力的适应需求。协调细致的数据,在这些数据中,给定的对象、产品和需求与空间中的确定性词语密切相关,it 部门不仅要重视相关性,还要重视空间中关系的方向性价值。

如果说毛巾是焦点,那么柔软、优雅和蓬松就是具有独立分量的形容词,也是验证该产品解决消费者需求的效率的前提。

标准化这些抽象成为机器的任务,参考引擎来收集和理解市场的生存能力。将这些向量建立为变量错综复杂,通知源词以下信息:属性、变量、质量和每个的加权值。

从人工智能和搜索的发展到这一点,与 BERT 交互的前提是由场景中现有的清晰焦点额外加入的。公司、品牌和市场定义这些错综复杂的变量并背诵它们,当他们产品的优势成为其所有特征的累积前景时,将验证他们的努力。

您可以从这些文章中找到更多关于 NLP 和 BERT 本身在搜索引擎中的技术集成的信息,开源 BERT:自然语言处理的最先进的预培训BERT 解释:NLP 的最先进的语言模型

感谢阅读,继续参考!

寻找更多的应用程序开发建议?在 TwitterGitHubLinkedIn 上关注。在线访问最新更新、新闻和信息,网址为 collectedview.io

2020 年 5 大免费股市 API

原文:https://towardsdatascience.com/best-5-free-stock-market-apis-in-2019-ad91dddec984?source=collection_archive---------0-----------------------

Photo by Chris Li on Unsplash

金融 API 市场增长如此之快,去年的帖子或平台今年都不是一个好的选择。所以在这个故事里,我会给大家展示我在 2019 年用过的最好的 5 个股市 API。

什么是股市数据 API?

股票市场数据 API 提供当前在市场上交易的金融资产的实时或历史数据。这些 API 通常提供公共股票、ETF、etn 的价格。

这些数据可用于生成技术指标,这些指标是建立交易策略和监控市场的基础。

数据

在这个故事中,我主要关心价格信息。对于其他数据,有一些其他的 API 主要用于用例,这里不做介绍。

我将讨论以下 API 以及它们的使用场合:

  • 雅虎财经
  • Google Sheets 中的 Google 金融
  • IEX 云
  • 阿尔法优势
  • 世界贸易数据
  • 其他 API(polygon . io、Intrinio、Quandl)

1.雅虎财经

Docs:y finance

雅虎财经 API 于 2017 年被关闭。所以你可以看到很多关于雅虎财经替代方案的帖子。然而,它回到了 2019 年的某个时候。所以你仍然可以使用雅虎财经获得免费的股市数据。雅虎的 API 是个人和企业级用户使用的股票数据 API 的黄金标准。

雅虎财经提供了超过 5 年的每日 OHLC 价格数据。而且免费又可靠。

有一个新的 python 模块 yfinance 包装了新的雅虎金融 API,你可以直接使用它。

# To install yfinance before you use it.
> pip install yfinance

下面是一个如何使用 API 的例子。请点击上面的 Github 链接查看完整的文档,您可以开始了。

2.谷歌金融

谷歌金融在 2012 年被弃用。然而,它并没有关闭所有的功能。Google Sheets 中有一个支持你获取股票营销数据的功能。在 Google Sheets 中它被称为 GOOGLEFINANCE

它的工作方式是键入如下内容,您将获得最后的股票价格。

GOOGLEFINANCE("GOOG", "price")

语法是:

GOOGLEFINANCE(ticker, [attribute], [start_date], [end_date|num_days], [interval])
  • 股票代号:证券要考虑的股票代号。
  • 属性(可选,默认为"price"):从 Google Finance 中获取关于ticker的属性。
  • start_date (可选):取历史数据时的开始日期。
  • end_date|num_days (可选):取历史数据的结束日期,或者从start_date开始返回数据的天数。
  • 间隔(可选):返回数据的频率;不是“每日”就是“每周”。

附上使用示例。

3.IEX 云

网址:https://iexcloud.io/

IEX 云是今年刚刚发布的新金融服务。它是从 IEX 集团的旗舰证券交易所分离出来的独立业务,是一个连接开发者和金融数据创造者的高性能金融数据平台。

与其他订阅服务相比,它非常便宜。9 美元/月,你几乎可以得到所有你需要的数据。此外,基本免费试用,你已经得到 500,000 核心讯息免费为每个月。

有一个 python 模块来包装他们的 API。你可以很容易的查出来: iexfinance

4.阿尔法优势

网址:https://www.alphavantage.co/

Alpha Vantage Inc .是各种免费 API 的领先提供商。它提供 API 来访问历史和实时股票数据、外汇数据和加密货币数据。

使用 Alphavantage,您可以每分钟执行多达 5 个 API 请求,每天执行 500 个 API 请求。每分钟 30 个 API 请求,每月 29.9 美元。

5.世界贸易数据

https://www.worldtradingdata.com/】网址:

此外,还提供了完整的日内数据 API 和货币 API 访问权限。对于那些需要更多数据点的人来说,从每月 8 美元到每月 32 美元的计划都是可用的。

目前有四种不同的计划可供选择。对于免费访问,每次请求最多可以获得 5 只股票(实时 API)。每天最多 250 个请求。订阅计划不是很贵,你可以得到一个

他们提供 URL,您的响应将是 JSON 格式。目前还没有可用的 python 模块来包装他们的 API。所以你得用 请求 或者其他 web 模块来包装自己的 API。

6.其他 API

****网址:https://polygon . io

仅美国股市每月 199 美元。对于初学者来说,这可能不是一个好的选择。

****网址:【https://intrinio.com】

只有实时股票市场每月 75 美元。此外,对于 EOD 的价格数据,它是 40 美元/月。你可以从我推荐的其他 API 获得几乎免费的 EOD 价格数据。尽管他们有 206 个价格提要、10 个金融数据提要和大量其他数据要订阅。价格对独立交易者来说并不友好。

****网址:https://www.quandl.com/

Quandl 是一个金融、经济和其他相关 API 的聚合市场。Quandl 将来自第三方市场的 API 聚合为服务,供用户购买他们想要使用的任何 API。

所以你需要订阅不同的市场来获得不同的财务数据。而且不同的 API 会有不同的价格体系。有些是免费的,有些是基于订阅或一次性购买的。

此外,Quandl 在其网站内有一个分析工具。

如果不在乎钱的话,Quandl 是个不错的平台。

包裹

学习和建立一个交易系统并不容易。但是财务数据是一切的基础。如果你有任何问题,请在下面提问。

用于异常检测的最佳聚类算法

原文:https://towardsdatascience.com/best-clustering-algorithms-for-anomaly-detection-d5b7412537c8?source=collection_archive---------3-----------------------

Photo by Agence Olloweb on Unsplash

让我首先解释一下任何通用的聚类算法是如何用于异常检测的。

使用聚类进行异常检测背后的主要思想是学习已经可用的数据(训练)中的正常模式,然后在提供新数据(测试)时使用该信息来指出一个点是否异常。

一般步骤(一般预处理后):
1 —根据你的数据选择最佳模型。
2 —将模型拟合到训练数据,该步骤的复杂程度取决于所选的模型,此时应进行一些超参数调整。
3-一旦收到新数据,将其与模型的结果进行比较,并确定它是正常点还是异常点,执行这种分类的方式高度依赖于模型(我将讨论如何为解释的模型执行),一些基于距离,而另一些使用概率。

4-如果随着时间的推移有任何类型的数据演变,则模型应在一段时间后重新训练,以便学习新的行为(否则这种新的行为可能总是被归类为异常)。

注意:当然聚类对于所有与异常检测相关的问题并不理想(就像任何其他方法一样,你知道,没有免费的午餐),但是将这种技术与其他类似智能特征提取的技术结合起来可以帮助你解决很多问题;例如,当你有时间序列,问题是一个值增加太快,但仍然在一个正常的范围内,会发生什么?将导数添加到聚类算法中可以帮助您找到异常。

基于密度的噪声应用空间聚类

DBSCAN 是一种基于密度的聚类算法(实际上 DBSCAN 代表Den sity-BasedSpatialClustering ofA**应用程序实际上,这是我个人喜欢 DBSCAN 的主要原因之一,不仅我可以检测到测试中的异常,而且训练中的异常也会被检测到,不会影响我的结果。**

在该模型中有两个关键参数:
eps: 两点之间视为邻居的最大距离。如果这个距离太大,我们可能会将所有的点聚集在一个巨大的集群中,然而,如果这个距离太小,我们甚至可能不会形成一个集群。
min_points: 形成一个聚类的最小点数。如果我们为这个参数设置一个较低的值,我们可能会得到很多非常小的聚类,但是,一个较大的值可能会停止创建任何聚类的算法,最终得到一个只有异常的数据集。

该算法创建聚类的方式是通过查看每个点有多少个邻居,考虑所有距离小于特定距离的邻居( eps )。如果多于个 min_points* 是邻居,则创建一个聚类,并且该聚类用邻居的所有邻居来扩展。但是,由于一张照片比一千张照片更有价值,我从这个媒体帖子中借用了这张照片来解释 DBSCAN 😗

Image obtain from the post “DBSCAN: What is it? When to use it? How to use it?

现在我们有了集群…

怎样才能检测出测试数据中的异常?

我所遵循的将点分类为异常或不异常的方法如下:
1-计算从新点到所有核心点的距离(仅计算核心点,因为它们实际上是定义聚类的点)并寻找最小值(到聚类内最近邻居的距离)。
2 —用 eps 比较到集群内最近邻居的距离,因为这是被认为是邻居的两个点之间的界限,这样,我们就可以用我们的测试数据发现是否有任何核心点实际上是邻居。
3-如果距离大于 eps 该点被标记为异常,因为它在聚类中没有邻居。

高斯混合模型

假设所有数据点都是由有限数量的高斯分布混合生成的概率模型。该算法试图恢复生成该分布的原始高斯分布。为此,它使用期望最大化(EM)算法,该算法初始化一个随机的 n 初始高斯分布,然后调整参数,寻找一个组合,使该分布生成的点的可能性最大化。

Figure obtained from Angus Turner’s blog: “Gaussian Mixture Models in PyTorch

高斯混合模型的问题之一是需要指定聚类数,另一种可能性是使用变分贝叶斯高斯混合,以避免这个问题。

当然,就像 K-Means 一样,由于集群的初始化是随机的,我们可能会得到一个对我们的问题来说不是最优的局部最小值。这个问题可以通过多次执行来解决,然后计算出概率的平均值。然而,如果模型需要投入生产,这种解决方案并不是最佳的,当模型需要部署在流环境中时,我仍然在寻找解决这个问题的最佳方法。

变分贝叶斯高斯混合

我不想在这里讲太多细节,scikit-learn 页面有完整的解释。但这种变异值得一提。该模型背后的思想类似于高斯混合,然而,实现是不同的,这里,代替 EM,使用变分推理算法。

这里,只需要指定最大数量的聚类,然后算法可以找到实际数量的聚类,并将不相关的聚类的权重设置为非常接近零。

当然,这种选择也不是完美的,有许多超参数可供选择,实际上比高斯混合模型中的要多。其中最重要的是权重 _ 浓度 _ 先验,它将在很大程度上影响你最终得到的有效聚类数。

怎样才能检测出测试数据中的异常?

一旦算法被训练,我们得到新的数据,我们可以把它传递给模型,它会给我们这个点属于不同聚类的概率。这里,可以设置阈值,即如果概率低于该值,则该点应该被视为异常。在贝叶斯高斯混合的情况下,有一件重要的事情要记住:不是所有的聚类都应该被考虑,记住算法忽略了不重要的聚类,给它们一个接近于零的权重(它们没有被移除,但是你可以知道哪些应该被移除),我过去所做的是检查点属于重要聚类的概率,为了做到这一点,我为聚类权重设置了一个阈值,以移除

为什么不是 K-Means?

虽然 K-Means 可能是其他应用程序中最著名和最常用的聚类算法,但它不太适合这个应用程序。

这样做的主要原因是,它仅适用于预期聚类具有非常规则的形状的情况,一旦不满足这一点,该模型就不能成功地分离聚类。

另一个原因是所有点都适合聚类,因此如果训练数据中有异常,这些点将属于聚类,并可能影响它们的质心,特别是聚类的半径。由于阈值距离的增加,这可能导致您无法检测到测试集中的异常。

另一种可能性是,你甚至会形成一个异常的集群,因为集群中的点数没有下限。如果你没有标签(你可能没有,否则有比聚类更好的方法),当新数据进来时,你可能认为它属于一个正常行为的聚类,而实际上它是一个完美定义的异常。

这种情况下的另一个缺点是需要事先指定聚类的数量,我们已经讨论过,在其他算法中有一些参数不容易调整,但我发现这一个特别棘手。由于我们的数据会随着时间而变化,所以聚类的数量也会变化,并且一旦我们将我们的模型部署到生产中,如果没有人的探索,就没有简单的方法来决定其他的。

怎样才能检测出测试数据中的异常?

对于 K-Means 来说,并非一切都是不好的,实际上这是测试阶段最简单的情况,因为我们有聚类的质心,形状预计会非常规则,我们只需要计算每个聚类的边界距离(通常最好不要选择到质心的最大距离,以防我们有异常值,根据您的数据,95%或 99%这样的值应该可以工作)。

然后,对于测试数据,计算到质心的距离。然后将该距离与每个聚类的边界进行比较,如果该点不属于任何聚类(距离>边界),则该点被归类为异常。

综上

我在这里介绍了一些聚类算法,并解释了如何使用它们进行异常检测(其中一些比其他方法更成功),显然这些不是唯一的方法,根据我处理的数据,我可能会偏向其中一些方法。

我真的认为 DBSCAN 和(贝叶斯)高斯混合模型是这个应用程序最有用的聚类算法。如果你刚开始接触异常检测,了解更多关于它们的信息是值得的,如果它们现在对你没有用,至少是你学到的新东西。

一些有趣的链接:

* [## DBSCAN:是什么?什么时候用?如何使用。

DBSCAN(带噪声的基于密度的应用程序空间聚类)是一种流行的无监督学习方法

medium.com](https://medium.com/@elutins/dbscan-what-is-it-when-to-use-it-how-to-use-it-8bd506293818) [## DBSCAN 如何工作,为什么要使用它?

首先,这是我在 medium 上的第一个故事,如果我做错了什么,我很抱歉。其次,我不太擅长…

towardsdatascience.com](/how-dbscan-works-and-why-should-i-use-it-443b4a191c80) [## 2.1.高斯混合模型-sci kit-学习 0.21.2 文档

高斯混合模型是一个概率模型,它假设所有的数据点都是从一个混合的高斯混合模型中产生的

scikit-learn.org](https://scikit-learn.org/stable/modules/mixture.html)

如果有更多的聚类算法,你发现有用的异常检测,我没有提到他们请让我知道,我很乐意扩大这个列表!

如果你想聊更多,请随时通过 LinkedIn 联系我!*

2020 年 Coursera 上的最佳数据科学课程

原文:https://towardsdatascience.com/best-data-science-courses-on-coursera-in-2020-f7de4ab414ff?source=collection_archive---------5-----------------------

如果你想提升你的数据科学职业生涯,选择什么课程

在线学习成为最受欢迎的学习形式之一。有了像数据营UdemyCoursera 这样的好平台,任何水平的人都能找到可以学习的东西。在这篇文章中,我想强调 Coursera 上目前提供的顶级数据科学课程。

Never stop learning! Increase your data science salary thanks to certification and new skills.

初级课程

你刚刚开始,你想学习 Python 的基础知识,以及如何编译你的第一个数据科学模型。你以前没有做过太多的数据科学或统计,你听说过一些术语,但这些对你来说只是时髦的词汇。你想从头开始积累你的知识。

密歇根大学的 Python 数据科学导论是目前最受欢迎的两门入门课程之一。它不做任何假设,你会从 Python 开始,然后遍历不同的数据结构(熊猫!)以及如何操纵它们。非常适合初学者。UMich 的另一门热门课程是 Python 数据结构,也是推荐给初学者的。

IBM 数据科学是由 9 门课程组成的专业证书。它从解释什么是数据科学,使用什么方法和工具开始,慢慢进入数据处理和数据可视化,最终达到机器学习。无论你是刚刚开始还是已经做了一点数据科学,这都是你简历上的一个很好的证明。

最后但同样重要的是,如果你想进入数据科学,你需要学习一些数学和统计学。不要担心,没有那么多,但你仍然应该对向量,矩阵的运算感到舒服,知道什么是均值,方差,偏差,并能够计算一些概率。这门课解释的就是:杜克大学的数据科学数学技能

中级课程

你已经有了一些经验,你已经开始对 Python 充满信心,你已经做了一些实验,现在你希望扩展你的知识。在这一点上,机器学习可能是你应该学会的。

华盛顿大学的机器学习专业是开始你的机器学习冒险的完美方式。本课程假设你精通 Python,了解数据结构,并带你了解机器学习的基本概念:分类和聚类算法。1 个专业的 4 门课程。

IBM 的应用人工智能课程是对深度学习和在云上部署深度学习模型的一个很好的探索。你将了解到像 Keras 和 Tensorflow 这样的深度学习框架(如果你还不知道的话)。这实际上是部署的问题。

专家课程

你至少有几年的经验,你是 Python 和使用数据科学提取信息的专家。您希望巩固您的知识,将它们放在一起,并了解数据科学的最新发展。

吴恩达在斯坦福大学开设的机器学习课程现在已经成为经典。Coursera 由吴恩达共同创建,这是该平台上的第一批课程之一。还有更多最新的课程,但这一门仍然很好地向你展示了机器学习背后的理论。强烈推荐!

由吴恩达再次创立的 deeplearning.ai 提供的深度学习专业化是一个获取关于深度学习及其应用的最新知识的地方。无论你想进入卷积神经网络,调整你的超参数或只是玩 LSTMs 本课程有一切。这绝对是我目前为止看到的最好的关于数据科学/机器学习这个层面的在线课程。

暂时就这样吧!

我希望你已经找到了你感兴趣的东西。如果您正在寻找学习数据科学的其他材料,请查看我关于您可能想要阅读的书籍的其他文章:

我也评论了一些适合数据科学家使用的笔记本电脑。

Data Science Job

最后,如果你想了解成为一名数据科学家意味着什么,那么看看我的书数据科学工作:如何成为一名数据科学家,它将指导你完成这个过程。

[## 加入我的时事通讯

技术、人工智能和数据科学新闻](https://creative-producer-9423.ck.page/c3b56f080d)

用 Scipy 线性化数据的最佳指数变换

原文:https://towardsdatascience.com/best-exponential-transformation-to-linearize-your-data-with-scipy-cca6110313a6?source=collection_archive---------13-----------------------

如何用 scipy 优化包找到拟合线性关系的最佳指数?

对于我们希望找到最优解的任何应用来说,迭代搜索都是必要的,但是问题的解不能以显式的形式表达。例如,机器学习中有很多算法使用迭代方法来寻找最佳参数集,如 Lasso 线性回归、梯度推进机器等。
在本文中,我们将尝试在 ETL 过程中使用数值方法,通过最佳指数变换将两个变量之间的非线性关系转换为线性关系。

作为一名数据科学家,我经常要检查不同变量之间的关系,并用它们总结一些关键指标。我最近遇到了一个评估发动机效率的项目,我想表达一种运输寿命期间的燃料消耗/速度比。案例研究变量之间的关系是非线性和单调递增的,所以我开始在谷歌上搜索是否有一种统计测试可以利用我的数据进行转换,使其更加线性,就像正态性的 box-cox 一样。
在这一点上,我想做一个实验:一个迭代过程,通过最小化一个成本函数线性化我的数据。
在我平时的工作中,我经常利用**scipy.optimize**模块寻找函数极小值,为什么不把它用于其他用途呢?
你可以更好地阅读官方文档中的**scipy.optimize**,其中提供了有用的解释和示例。

开始设置

在我的搜索中,我将重点放在了指数变换上,因为我们可以轻松地将指数设置为一个参数,并提供一个连续的探索范围。尽管这种选择排除了一些强非线性的界限,但它通常会返回好的结果。

让我们准备测试数据并创建两个相关变量 x,y ,其中 y 等于 x 的幂 e ,加上一些高斯噪声。为了方便起见,我也设置了依赖于指数的高斯噪声方差。

#test data setting
e = 2.465 #exp
x = np.arange(0,25,0.01)
y = x**e + np.random.normal(0,10**e,x.shape)

如果我们用**seaborn**回归图绘制数据,我们可以很容易地发现非线性关系。

成本函数

我们现在需要的是一个成本函数,一个我们想要最大化的线性关系的“好”的度量。一个很好的指标是皮尔逊积差相关系数 r ,它确定了两个变量之间线性相关的强度。
Pearson r 的取值在-1 和 1 之间,其中 1 为完全正线性相关,0 为无线性相关,1 揭示完全负线性相关;意思是 r = -1 和 r = 1 一样好。
因此,为了正确使用 Pearson r,我们将取其绝对取反值,因为**scipy.optimize**函数搜索最小值,而我们想要其最大值。

让我们定义成本函数:

#define cost function
def cost_function(e):
    #y and x are already defined
    r = np.corrcoef(y,x**e) #returns correlation matrix
    #print each iteration
    print('r value: {:0.4f} exp: {:.4f}'.format(r[0][1],e)) 
    return -abs(r[0][1])

优化功能

此时,我们必须调用其中一个 Scipy 方法。
合适的选择可能是**minimize_scalar**方法,因为我们的成本函数是标量函数。这个包背后的算法是 Brent 的方法,一个不需要梯度估计的求根算法。

我发现了一个非常详尽的视频,是奥斯卡·维利兹频道关于布伦特方法及其对德克尔和割线方法的依赖性的视频。检查出来,如果你想知道更多关于这一点,以及其他,优化功能。

让我们导入并调用**minimize_scalar**函数:

from scipy.optimize import minimize_scalarminimize_scalar(cost_function)

我们还可以设置一个搜索范围,避免指数的 0 值,这意味着 Pearson r 返回一个无效值,即使**numpy.corrcoeff** 可以处理它。

事实上,该系数定义为:

如果 x 被提升到 0,则标准偏差为 0,比率返回无效值。为了执行有界搜索,让我们调用:

minimize_scalar(cost_function,bounds=(0.1, 10), method='bounded')

结果列表如下:

r value: 0.9242 exp: 3.8815
r value: 0.8681 exp: 6.2185
r value: 0.9416 exp: 2.4371
r value: 0.9100 exp: 1.2663
r value: 0.9407 exp: 2.7565
r value: 0.9416 exp: 2.4255
r value: 0.9416 exp: 2.4861
r value: 0.9416 exp: 2.4815
r value: 0.9416 exp: 2.4819
r value: 0.9416 exp: 2.4819
r value: 0.9416 exp: 2.4819
r value: 0.9416 exp: 2.4819fun: -0.9416331392353501
 message: 'Solution found.'
    nfev: 12
  status: 0
 success: True
       x: 2.4818969221255713

仅仅 12 次迭代中,得到的指数是 2.482,非常接近我们用来生成数据的指数 2.465。

声音**fun**显示皮尔逊 r 的负绝对值的值,好像挺高的。让我们应用在 x、上找到的指数再次绘制 yx 我们将注意到一个强线性关系:

如果我们存储每个迭代指数和相关的皮尔逊系数,我们可以绘制 r-指数曲线。

其他测试

如果我们增加测试数据中噪音的影响会怎样?让我们在噪声发生器中增加高斯方差:

y = (x**e) + np.random.normal(0,20**e,x.shape)

优化函数的执行返回以下结果:

fun: -0.42597730774659237
 message: 'Solution found.'
    nfev: 13
  status: 0
 success: True
       x: 2.2958258442618553

找到的最佳指数不如以前的结果精确,但它仍然是一个很好的近似值。

噪声影响越大,由于噪声对岩心数据的影响越大,会导致错误的结果。

结论

优化方法是许多待开发应用的金矿。通过这篇文章,我不想教一种新技术,但我想促进这些有效方法在“不寻常”问题上的实验。

学习数据科学的最佳免费在线资源

原文:https://towardsdatascience.com/best-free-online-resources-for-learning-data-science-6dadb555b0c9?source=collection_archive---------19-----------------------

面向初学者和专业人士的数据科学学习资源综述

在完成生物信息学硕士学位后,我用 ML 研究了肠道中的微生物群落,我知道我的目标是在行业中找到一份数据科学家的工作,但也觉得我必须学习一段时间来准备面试,原因有两个:

1)在攻读理学硕士期间,我主要使用 Matlab 和一点 R,所以我不得不转向 Python 及其基本库。

2)例如,我对标准 ML 管道的一些主题和阶段不够熟悉——非常方便的是,我总是在一个非常有组织的表中接收我的数据,这些表具有已经设计和标准化的特征。然而,在现实世界中,大量的工作是找出如何通过特征工程将原始数据转换成表格数据。

在准备面试的过程中,我在网上找到了许多好的免费资源,其中大多数都提供入门级课程以及高级材料,对于已经在该领域工作的人来说,这些材料对进一步学习非常有用。在这篇博文中,我将与你分享我找到的最好的学习资源,所以不再多说——让我们开始吧。

1.谷歌的机器学习速成班 —这门课程彻底有效地将任何人——无论是初级 DS 还是完全的新手——带入机器和深度学习的世界,同时涵盖梯度下降和损失函数等重要概念,并介绍从线性回归到神经网络的主要算法。课程材料包括阅读材料、练习和笔记本,其中包含用 Tensorflow 实现并在 google Colab 上运行的真实代码,这意味着您无需安装即可运行它。

除了速成班之外,这个网站上还有大量关于数据科学和人工智能的材料,分为以下几类:

-课程-在这里,您可以找到对特定主题的深入探究,如聚类、推荐系统等。

  • Practica —“谷歌如何在产品中使用机器学习”的例子。

-指南—逐步指导常见 ML 问题的解决方案。

-词汇表-我最喜欢的资源,我认为每个数据科学家都应该在自己的桌面上放上这个。

链接:【https://developers.google.com/machine-learning/crash-course

2。 IBM 用 Python 实现的机器学习

本课程首先介绍两种主要类型的学习算法——有监督的和无监督的——之间的区别,然后对机器学习中的所有基本算法进行了很好的回顾,包括关于推荐系统的一章(我认为很有趣)。每章都以学习者可以在浏览器上运行的代码结尾,此外,一旦你完成了所有要求,你将收到一个徽章,以后可以在 LinkedIn、Twitter 等网站上分享。

链接到课程-

https://cognitive class . ai/courses/machine-learning-with-python

这里也有许多其他课程,涉及与数据科学家相关的许多主题,但也涉及与该领域没有直接联系但仍然有趣的其他主题,如区块链、反应式架构、比特币等。

链接到其他材料–

https://cognitiveclass.ai/courses

3。 AWS 的《数据科学的要素》

去年,亚马逊向其开发人员开放了在公司内运行的公共课程,结果是从 ML 基础知识到介绍其服务(例如 Neptune、ElastiCache)到使用 AWS 工具的特定应用程序(例如——使用 GluonCV 的计算机视觉、使用 QuickSight 的可视化)的各种主题的大量知识。

当我为 DS 面试做准备时,我发现他们的数据科学课程的元素非常有用,主要有两个原因,首先,它涵盖了从数据准备到模型培训和评估的标准 ML 管道的实践阶段,这很有帮助。 第二,每个主题都用实际的代码示例进行了介绍和解释,这些示例让我们对该领域的实际情况有了很好的了解,同时也展示了我不熟悉的 Pandas 和 Scikit Learn 的强大功能(您知道 SKlearn 包中有内置的数据集,您可以加载并用于您的个人实践吗? 我确实感谢这门课)。在这里,当你完成所有的要求时,你也会得到一个证书。

课程链接:

https://www.aws.training/Details/eLearning?id=26598

链接到所有材料:

https://www.aws.training/LearningLibrary?filters = language % 3a 1&search =&tab = digital _ courses

4。 快。艾

我必须承认,我从未完成这门课程,但我喜欢我做的部分,而且它非常受欢迎,所以我觉得有义务把它列入这个列表。在这里,您可以找到附有代码示例的长录音讲座(每次约 1.5 小时)。与列表中的其他课程相比,它们也有不同的课程,涵盖更高级的主题,包括计算机视觉和自然语言处理。我要说的是,当我第一次想开始这门课程时,我被它第一部分提到的技术要求吓住了,但后来我了解到所有笔记本都可以在 Google Colab 上运行,这意味着不需要安装和免费的 GPU。

课程链接–

https://www.fast.ai/

5。 摇摇晃晃学

Kaggle 是众所周知的获得数据科学实践经验的最佳场所,这要归功于它的大量有组织的数据集和许多竞赛,但它还有另一个很棒的部分,那就是他们的“学习”部分。你在这里会发现的并不完全是课程,而是如 Kaggle 自己所称的,带有许多互动练习的微型课程,旨在通过特定的库教授和提升从 Python for DS 到深度学习、SQL 和高级机器学习的所需技能。这可能是用最少的投入和时间扩展你的知识的最好方法。

https://www.kaggle.com/learn/overview

底线—数据科学是一个巨大的领域,有很多东西需要学习和了解,我敢说这里最重要的技能之一是保持更新和不断学习新技能和熟悉新技术的能力。我希望这些资源能对你的工作有所帮助,也希望在评论中听到其他有用的资源。

用 Python 进行蒙特卡罗模拟的最佳投资组合

原文:https://towardsdatascience.com/best-investment-portfolio-via-monte-carlo-simulation-in-python-53286f3fe93?source=collection_archive---------1-----------------------

从头到尾使用 Python 中的蒙特卡罗模拟寻找最佳投资组合

本文着重于通过蒙特卡罗模拟生成最优投资组合。我已经用 Python 实现了一个端到端的应用程序,本文记录了该解决方案,以便更多的读者能够从中受益。

文章将以通俗易懂的方式讲解投资管理所需的金融、数学和编程知识。

因此,这篇文章对数据科学家、程序员、数学家和那些对金融感兴趣的人很有用。

请阅读 fintech explainedisclaimer。这个应用程序是基于我的意见,他们可能是错误的。在投资之前,一定要向专业理财顾问寻求建议。

1.我们想达到什么目的?

假设我想投资 1000 美元一年。我所在的当地商业街银行提供的一年定期存款利率很低。因此,我对它提供的年回报率并不满意。因此,我决定投资股票,用我的 1000 美元购买不同公司的股票。尽管它们相对来说风险更大,但它们可能会帮助我在承担风险后获得更多回报。到目前为止,一切顺利。

我想以这样一种方式投资,即我可以通过承担最少的风险来获得最高的回报。对我来说,这是最佳投资组合,我将在本文中演示的应用程序将解释我们如何实现它。

代码上传到 Github 上,这里提供了链接

2.高层次的概念

我已经选择了 7 家有潜力的公司,我想通过购买它们的股票找到投资的最佳方式。

简而言之,我将执行以下步骤:

  • 我有兴趣将我的 1000 美元投资于以下 7 家公司的股票(资产):ZM、优步、SWI、RNG、CRWD、工作、SYMC。

注意:在我以后的文章中,我将用 Python 实现一个解决方案,它将决定我们应该投资的合适公司。它将使用传统的分析概念以及先进的机器学习概念。

  • 现在我们来问这个问题。我应该从我的 1000 美元投资资金中拿出多少来购买这些股票?传统上,新的投资者会平等地投资于他们的目标公司,但是资产可以互相转移,一些资产可能互相负相关。

因此,我们需要找到最佳的投资组合。最佳投资组合是以最低风险产生最高回报的投资组合。

  • 生成每一个可能的投资组合可能是压倒性的。因此,我将使用蒙特卡罗方法在 Python 中生成 10,000 多个不同的投资组合。

该方法围绕这样一个概念,即随着投资组合数量的增加,我们将更接近实际的最优投资组合。

  • 对于每个投资组合,我将生成其回报和风险。因此,我需要获取投资组合中每项资产的股票价格。
  • 最后,我将得出回报率/风险比,并从 10,000+个投资组合中选择回报率/风险比最高的投资组合。

这将是我们选择的最佳投资组合。

Photo by Ben White on Unsplash

注意:由于我对这个应用程序有很大的未来计划,我将以组件化的方式来架构和设计这个应用程序,以便这个应用程序在未来可以很容易地增强。我还将在本文中解释应用程序的架构和设计。

3.让我们开始吧:戴上我的金融帽子

  • 存在一种无风险利率,即投资者在不承担任何风险的情况下从其投资中获得的利率,例如购买政府国库券。
  • 风险和回报之间有一个权衡。如果投资者期望投资于比无风险利率风险更高的投资选择,那么他/她期望获得更多回报。这是为了补偿投资者承担的风险。到目前为止,这一切都说得通!
  • 投资者可以通过购买不同公司的股票开始他/她的投资之旅。让我从现在开始把这些交易称为 资产 。我们可以获得资产的历史股票价格,并计算它们的风险和回报。当我们开始在我们的投资组合中增加资产时,我们开始意识到这些资产中有一些是相互关联的。因此,资产可以彼此有关系,因此它们可以彼此一起移动。
  • 一个 投资组合 将资产组合在一起。我们知道,当资产组合在一起时,它们的净风险不仅仅是它们各自风险的简单总和。这里的诀窍是将投资组合视为一种资产,并计算其集体风险和回报。

阅读这篇解释投资管理如何运作的文章

[## 投资管理和因素

了解如何明智地投资

medium.com](https://medium.com/fintechexplained/investment-management-and-factors-ee9eb5aa0a24)

4.流程的 7 个步骤

概括地说,我们需要执行以下七个步骤,如下图所示:

这是我们的商业案例。我们需要实现的应用程序将以一种我们可以在未来轻松扩展和增强每个步骤的方式来执行这些步骤。我会在这篇文章中详细解释。

5.让我们专注于上述流程的第 5 步——风险和回报的衡量标准

对于每项资产,我们将生成以下衡量标准:

5.1.资产回报

第一步是计算你投资组合中资产的回报。

为了计算资产回报,我们需要执行以下两个步骤:

  1. 我们需要获取资产的历史每日价格

2.然后,我们需要通过计算以下等式来计算它们的几何收益:

产生回报是为了让我们能够标准化股票价格,以便进行比较。

5.2.资产预期平均收益

上面计算的资产回报都是二维的,因为有一个时间轴。我们现在需要计算一个数字来表示资产的收益。最常见的方法之一是计算回报的平均值,即预期回报。

为了计算资产预期平均收益,我们需要每只股票收益的均值:

5.3.从资产到投资组合预期收益

现在准备计算投资组合的预期收益。投资组合将资产组合在一起。投资组合中的资产已被分配了总投资额的一部分。例如,投资组合可能持有 40%的资产 ABC 和 60%的资产 DEF。

从资产的预期收益,我们可以计算出投资组合的预期收益。它通过计算加权平均值来计算:

5.4.投资组合风险

资产的风险可以用许多风险度量来计算。其中一个指标是标准差,它可以告诉我们资产的价格是如何偏离其均值的。例如,一些资产可能彼此负相关,这意味着随着第一个资产的价值下降,负相关资产的价值增加。这向我们表明,投资组合的风险不是单个资产风险的简单总和。

投资组合的波动性就是投资组合的风险。波动率的计算方法是使用以下公式计算每只股票收益的标准差以及每对股票之间的协方差:

在这种情况下,波动率是标准差,即投资组合的总风险。

标准差衡量平均值周围的值的离差。

5.5 使用夏普比率寻找最佳投资组合

我们本可以把钱投资到一个储蓄账户(无风险),在不承担任何风险的情况下获得回报。我们如何决定我们获得的回报是否值得我们承担的风险?因此,我们可以计算夏普比率。

最后一步是计算每个投资组合的夏普比率。夏普比率是相对于无风险利率的超额回报率,作为风险的相关衡量标准:

如果您想了解更多有关投资绩效衡量的信息,请阅读本文:

[## 我们如何衡量投资业绩?

解释我们如何评估和计算投资业绩

medium.com](https://medium.com/fintechexplained/how-do-we-measure-investment-performance-7970042c6ae8)

6.端到端运行 7 个步骤

为了简单起见,在我记录技术细节之前,我想一步一步地展示最终结果。我将采用自下而上的方法,因为这有助于我们更好地理解概念。

在这一节中,我将使用应用程序为每个步骤生成的可视图表来演示这个概念,以便我们可以更好地理解这个概念。

注意:我将在下面解释的所有数据都由代码自动保存在 Excel 电子表格中。

6.1 最终结果:展示最优组合

到目前为止,我们已经了解到,该应用程序将获取我们选择的 7 家公司的历史股票价格。然后,它将通过计算每个投资组合的回报、风险和夏普比率,生成 10,000+个投资组合。

在这些投资组合中,它将指明以下三个投资组合:

  1. 具有最大夏普比率的投资组合。这是我们的最佳投资组合
  2. 风险最小的投资组合。这是为那些有风险意识但不想承担高风险的投资者准备的投资组合。
  3. 对每项资产的投资平均分配的投资组合。如果我不使用这个应用程序,我会盲目地在资产中平均分配我的投资。因此,这个投资组合将表明,同等投资是否比我所有的其他选择表现更好。

因此,总共将有 10,001 个投资组合:

  1. 资产平均分配的投资组合
  2. 10,000 个随机生成的投资组合

我执行应用程序后,显示了 10'001 个投资组合及其风险回报权衡:

我们来回顾一下图表:

每个圈都是一个独特的投资组合。x 轴是风险,y 轴是投资组合的回报。投资组合的颜色是夏普比率。

我们可以看到,这种关系并不是完全线性的。当投资者将资产组合在一个投资组合中时,资产的同步运动可以帮助我们分散风险,这就是所谓的风险回报权衡。图表上有三颗钻石:

  1. 绿钻组合:这是我们选择的最优组合。对于每个投资组合,我们生成夏普比率。这是夏普比率最大的投资组合。它以最低的风险给了我们最高的回报。这个投资组合被命名为投资组合 2187。
  2. 黑钻石投资组合:这是我们平均分配的投资组合。我们可以看到平均分配的投资组合处于中间位置。它不如标有绿钻的投资组合 2187。我们还可以看到,如果我们平等地投资,对于同样的风险,有许多投资组合会产生更高的回报。因此,这意味着应用程序为我们生成了优秀的投资组合。事实上,所有位于 y 轴黑钻石上方、x 轴价值相同的投资组合都是比平均分配投资组合更好的投资组合,因为对于相同的风险,它们会产生更高的回报。
  3. 红钻组合:这是产生最低风险的组合。

这些是投资组合 2187 的细节。

需要注意的两个要点是:

  1. 它建议我们不要在工作上投资。
  2. 这也突显出,我们应该将大部分资金投资于 RNG 和 CRWD。

通过承担 41%的风险,投资组合的投资组合回报率为 130%。它的夏普比率大约是 316% (=130/41)。

6.2 第一步是获取股票价格

我们构建了一个获取过去 3 年历史股票价格的组件:

股票价格是时间序列数据。

这是代码存储在 excel 电子表格的 StockPrices 表中的数据快照,如下所示。

正如你所看到的,我们不能简单地比较 ZM 和 SYMC,因为它们的股票价格是不同的。因此,我们需要计算回报率来标准化股票价格。

6.3 然后我们需要产生回报

我们计算了每日几何收益:

返回的是时间序列数据。这是存储在 excel 电子表格的返回表中的数据的快照,如下所示。

注意:历史回报是正确的选择吗?我们是否应该制定不同的衡量标准?我将在未来实现一个优秀的应用程序,演示我们如何实现时间加权回报。

6.4 根据回报,我们需要生成协方差矩阵

然后,代码准备协方差矩阵:

协方差矩阵存储在 Excel 电子表格的协方差表中,如下所示:

6.5 下一步是生成 10001 个投资组合

代码生成 10'001 个投资组合,其中一个投资组合是我们在 7 项资产上平均分配投资的投资组合。对所有 10,000 个投资组合施加了一个约束,即它们的分配总和必须是 100%。这意味着我们只打算购买资产。

代码将投资组合绘制在风险回报图上,其中 y 轴是投资组合的回报,x 轴是投资组合的风险。

我们可以看到这三个投资组合都有标记。绿钻是我们的最佳投资组合。

投资组合存储在 Excel 电子表格的 MonteCarloPortfolios 表中,如下所示:

然后,我们可以找到投资组合 2187 的配置(我们的最佳投资组合如图所示),然后对该投资组合进行投资。

所有生成的投资组合的风险、回报和夏普比率存储在 MonteCarloPortfolioRatios 表中,如下所示:

7.让我们来设计应用程序:戴上我的技术帽子

最后,我将记录我实现的代码。

我将从解释如何架构和设计应用程序开始这一部分。我将详细解释每个组件和代码。

该应用程序的设计核心仅围绕一个概念:

当应用程序运行时,它将产生大量的数据,如股票价格、回报、协方差矩阵、投资组合及其分配以及风险、回报和夏普比率。Python 代码还会将所有这些数据保存在 Excel 电子表格中。

7.1 应用程序结构

请点击这里访问 GitHub 上的全部代码

以下文件夹结构是在 C: drive 中创建的。

以下 Python 文件放在code文件夹中

我们将在以后的文章中处理文档和测试文件夹。

7.2 让我们了解每个 Python 文件

Python 包

certify = = 2020 . 4 . 5 . 1
chardet = = 3 . 0 . 4
cycler = = 0 . 10 . 0
idna = = 2.9
kiwi solver = = 1 . 2 . 0
lxml = = 4 . 5 . 0
matplotlib = = 3 . 2 . 1
numpy = = 1 . 18 . 2
pandas = = 0 . 22 . 0
pandas-pandas

1.配置设置

目标是实现一个可配置的应用程序。未来的计划是实施更好的风险和回报指标。此外,我们希望代码自动获取正确的公司。

因此,我在代码中实现了一个存储可配置设置的区域:

文件名:settings.py

import numpy as np
import datetime as dt
from calculator import risk_return_calculatorclass settings:PriceEvent = 'Adj Close'
    ReturnType = 'Geometric'
    NumberOfPortfolios = 10000
    YearsToGoBack = 3
    RiskFreeRate = 0
    CompanyFetchMode = "PreFixed" #Auto
    MyCompanies = ['ZM','UBER','SWI','RNG','CRWD', 'WORK', 'SYMC']
    PortfolioOptimisationPath = 'C:\Temp\PortfolioOptimisation.xlsx'
    RiskFunction = risk_return_calculator.calculate_portfolio_risk
    ReturnFunction = risk_return_calculator.calculate_portfolio_expectedreturns
    AssetsExpectedReturnsFunction = risk_return_calculator.calculate_assets_expectedreturns
    AssetsCovarianceFunction = risk_return_calculator.calculate_assets_covariance
    DailyAssetsReturnsFunction = risk_return_calculator.calculate_daily_asset_returns[@staticmethod](http://twitter.com/staticmethod)
    def get_my_targets(min_risk):
        return np.arange(min_risk, 1.5, 0.05)[@staticmethod](http://twitter.com/staticmethod)
    def get_end_date():
        return dt.date.today()[@staticmethod](http://twitter.com/staticmethod)
    def get_start_date(end_date):
        return end_date - dt.timedelta(days=settings.YearsToGoBack*365)

需要注意的关键是,风险和回报函数,以及投资组合的数量和公司的符号都存储在这里。这将允许我们添加新的公司或生成新的投资组合,并改变风险函数,而不改变代码的其他部分。

当代码执行时,它将输出 excel 电子表格中的数据,这些数据将存储在PortfolioOptimisationPath = ‘C:\Temp\PortfolioOptimisation.xlsx’

2.对象工厂

该应用程序大量使用面向对象的设计。因此,在应用程序中实例化了许多对象。我们想从对象的使用中提取对象的创建。因此,对象工厂的职责是为我们实例化所需的对象。

如果我们想改变实现,那么我们只需要改变那里的逻辑。这将允许我们在将来轻松扩展功能。

文件名:object_factory.py

from chart_plotter import chart_plotter
from file_repository import file_repository
from monte_carlo_simulator import monte_carlo_simulator
from companies_extractor import static_companies_extractor as static_companies_extractor
from price_extractor import price_extractor
from calculator import metrics_calculatorclass object_factory:
    def __init__(self, settings):
        self.__settings = settings 

    def get_price_extractor(self, companies):
        return price_extractor(self.__settings.API, companies)def get_metrics_calculator(self):
        return metrics_calculatordef get_charts_plotter(self):
        return chart_plotter(self.get_metrics_calculator())def get_companies_extractor(self):
        return static_companies_extractor(self.__settings.MyCompanies)def get_portfolio_generator(self):
        return monte_carlo_simulator(self.get_metrics_calculator(), self.__settings.RiskFunction, self.__settings.ReturnFunction, self.__settings.NumberOfPortfolios)def get_file_repository(self):
        return file_repository(self.__settings.PortfolioOptimisationPath)

作为一个例子,在下一阶段,我们可以实现一个web_companies_extractor 类,通过删除维基百科网页来获取纳斯达克 100 公司的名称。我们所需要做的就是从函数get_companies_extractor()中返回web_companies_extractor,而不改变其余的代码。

3.公司提取器获取目标公司

公司提取器的唯一目的是返回一个数据框,其中填充了所有必需的公司信息。

文件名:companies_extractor.py

import pandas as pd
class static_companies_extractor:
    def __init__(self, my_companies):
        self.__my_companies = my_companiesdef get_companies_list(self, current_portfolio=None):
        return pd.DataFrame({'Ticker':self.__my_companies})

在这个实例中,顾名思义,静态公司提取器返回在 settings.py 文件中配置的公司的静态列表。

4.提取资产价格的价格提取器

价格提取器的目的是获取目标开始和结束日期所需资产的股票价格。

文件名:price_extractor.py

import pandas as pd
import numpy as np
import pandas_datareader.data as web
import matplotlib.pyplot as plt
import scipy.optimize as solver
import datetime as dt
from functools import reduceclass price_extractor:def __init__(self, api, companies):
        print('Initialised Price Extractor')
        self.__api = api
        self.__companies = companies
        passdef get_prices(self,  event, start_date, end_date):
        prices = pd.DataFrame()
        symbols = self.__companies['Ticker']
        tmp={}
        for i in symbols:
            try:
                tmp = web.DataReader(i, self.__api, start_date, end_date)
                print('Fetched prices for: '+i)                
            except:
                print('Issue getting prices for: '+i)
            else:
                prices[i] = tmp[event]            
        return prices

5.度量计算器计算夏普比率,并给我们我们的目标投资组合

文件名:calculator.py 第一类

class metrics_calculator:[@staticmethod](http://twitter.com/staticmethod)
    def calculate_sharpe_ratio(risk, returns, risk_free_rate):
        return (returns-risk_free_rate)/risk[@staticmethod](http://twitter.com/staticmethod)
    def get_max_sharpe_ratio(df):
        return df.ix[df['SharpeRatio'].astype(float).idxmax()][@staticmethod](http://twitter.com/staticmethod)
    def get_min_risk(df):
        return df.ix[df['Risk'].astype(float).idxmin()]

6.风险回报计算器,用于计算风险和回报

计算风险和回报的代码位于risk_return_calculator 类中。

文件名:calculator.py 第一类

import numpy as np
from functools import reduce
import pandas as pdclass risk_return_calculator:
    [@staticmethod](http://twitter.com/staticmethod)
    def calculate_assets_expectedreturns(returns):        
            return returns.mean() * 252[@staticmethod](http://twitter.com/staticmethod)
    def calculate_assets_covariance(returns):        
            return returns.cov() * 252[@staticmethod](http://twitter.com/staticmethod)
    def calculate_portfolio_expectedreturns(returns, allocations):
        return sum(returns * allocations)[@staticmethod](http://twitter.com/staticmethod)    
    def calculate_portfolio_risk(allocations, cov):
        return np.sqrt(reduce(np.dot, [allocations, cov, allocations.T]))[@staticmethod](http://twitter.com/staticmethod)
    def calculate_daily_asset_returns(stock_prices, return_type):
        return np.log(stock_prices / stock_prices.shift(1))

当我们引入高级风险指标时,我们将在这里添加指标,并相应地更改配置文件。这将允许我们在将来轻松地维护和增强这些特性。作为一个实例,我计划实现 EWMA 来计算资产的预期收益。我所要做的就是实现risk_return_calculator 中的方法,并指向settings.py 文件中所需的方法。

7.生成投资组合的蒙特卡罗模拟器

这是为我们生成 10,001 个投资组合的主要类。

文件名:monte_carlo_simulator.py

import pandas as pd
import numpy as npclass monte_carlo_simulator:
    def __init__(self, mc, risk_function, return_function, numberOfPortfolios):
        self.__numberOfPortfolios = numberOfPortfolios
        self.__risk_function = risk_function
        self.__return_function = return_function
        self.__mc = mcdef generate_portfolios(self, returns, covariance, risk_free_rate):

        portfolios_allocations_df = pd.DataFrame({'Symbol':returns.index,'MeanReturn':returns.values})
        extra_data = pd.DataFrame({'Symbol':['Return','Risk','SharpeRatio'], 'MeanReturn':[0,0,0]})
        portfolios_allocations_df = portfolios_allocations_df.append(extra_data, ignore_index=True)portfolio_size = len(returns.index)
        np.random.seed(0)#Adding equal allocation so I can assess how good/bad it is
        equal_allocations = self.get_equal_allocations(portfolio_size)
        portfolio_id = 'EqualAllocationPortfolio'
        self.compute_portfolio_risk_return_sharpe_ratio(portfolio_id, equal_allocations, portfolios_allocations_df, returns, covariance, risk_free_rate)#Generating portfolios        
        for i in range(self.__numberOfPortfolios):
            portfolio_id = 'Portfolio_'+str(i)
            allocations = self.get_random_allocations(portfolio_size)
            self.compute_portfolio_risk_return_sharpe_ratio(portfolio_id, allocations, portfolios_allocations_df,returns, covariance, risk_free_rate)
        return portfolios_allocations_dfdef compute_portfolio_risk_return_sharpe_ratio(self, portfolio_id, allocations, portfolios_allocations_df, returns, covariance, risk_free_rate):

        #Calculate expected returns of portfolio
        expected_returns = self.__return_function(returns, allocations)
        #Calculate risk of portfolio
        risk = self.__risk_function(allocations,covariance)
        #Calculate Sharpe ratio of portfolio
        sharpe_ratio = self.__mc.calculate_sharpe_ratio(risk, expected_returns, risk_free_rate)

        portfolio_data = allocations
        portfolio_data = np.append(portfolio_data,expected_returns)
        portfolio_data = np.append(portfolio_data,risk)
        portfolio_data = np.append(portfolio_data,sharpe_ratio)
        #add data to the dataframe            
        portfolios_allocations_df[portfolio_id] = portfolio_datadef get_equal_allocations(self, portfolio_size):
        n = float(1/portfolio_size)
        allocations = np.repeat(n, portfolio_size)
        return allocationsdef get_random_allocations(self, portfolio_size):

        allocations = np.random.rand(portfolio_size)
        allocations /= sum(allocations)
        return allocations

需要注意的关键是,它是用风险和回报函数实例化的。它只是生成一个分配相等的投资组合和 10,000 个分配随机生成的投资组合。每个投资组合的分配总和是 100%,这意味着我们只对购买资产感兴趣。

然后计算每个投资组合的风险、回报和夏普比率。

8.图表绘图仪绘制投资组合并标记最佳投资组合

这个文件为我们准备了所需的图表。

文件名:chart_plotter.py

import matplotlib.pyplot as pltclass chart_plotter:def __init__(self, mc):
        self.__mc = mcdef show_plots(self):
        plt.show()def plot_single_point(self, x,y,title,colour):
        plt.scatter(x=x, y=y, c=colour, marker='D', s=200)
        plt.annotate(title, # this is the text
                 (x,y), # this is the point to label
                 textcoords="offset points", # how to position the text
                 xytext=(0,10), # distance from text to points (x,y)
                 ha='center') # horizontal alignment can be left, right or centerdef plot_portfolios(self, df):
        # find min Volatility & max sharpe values in the dataframe (df)

        max_sharpe_ratio = self.__mc.get_max_sharpe_ratio(df)
        min_risk = self.__mc.get_min_risk(df)plt.scatter(df['Risk'], df['Return'],c=df['SharpeRatio'],cmap='RdYlGn', edgecolors='black')
        x = max_sharpe_ratio['Risk']
        y = max_sharpe_ratio['Return']
        name = max_sharpe_ratio['Portfolio']

        plt.title(str(len(df))+" Portfolios Risk-Return")
        plt.xlabel("Risk")
        plt.ylabel("Return")self.plot_single_point(x,y,'Max Sharpe Ratio: '+name, 'green')
        x = min_risk['Risk']
        y = min_risk['Return']
        name = min_risk['Portfolio']
        self.plot_single_point(x,y,'Min Risk: '+name, 'red')equal_allocations_portfolio = df.loc[df['Portfolio'] == 'EqualAllocationPortfolio']
        x = equal_allocations_portfolio['Risk'].values[0]
        y = equal_allocations_portfolio['Return'].values[0]
        name = equal_allocations_portfolio['Portfolio'].values[0]
        self.plot_single_point(x,y,'Portfolio: '+name, 'black')def plot_prices(self, closing_prices):
        ax = plt.gca()
        columns = [c for c in closing_prices.columns if c not in 'Date']
        closing_prices.plot(kind='line',use_index=True,y=columns,ax=ax, title='Asset (Stock) Prices')
        plt.show()def plot_returns(self, returns):
        ax = plt.gca()
        columns = [c for c in returns.columns if c not in 'Date']
        returns.plot(kind='line',use_index=True, y=columns,ax=ax, title='Asset (Stock) Returns')
        plt.show()def plot_correlation_matrix(self, df):
        cols = df.columns.values
        fig = plt.figure()
        ax = fig.add_subplot(111)
        cax = ax.matshow(df.corr(), interpolation='nearest')
        fig.colorbar(cax)ax.set_xticklabels(cols)
        ax.set_yticklabels(cols)
        plt.show()

9.文件存储库将所有数据保存在一个文件中

中间数据和最终投资组合一起存储在一个 excel 文件中。数据的保存由文件存储库执行。

文件名:file_repository.py

import pandas as pdclass file_repository:def __init__(self, directory):
        self.__writer = pd.ExcelWriter(directory, engine='xlsxwriter')def save_to_file(self, data, sheet_name=None):        
        data.to_excel (self.__writer, sheet_name=sheet_name, header=True)def close(self):
        self.__writer.save()

10.地图绘制者

蒙特卡洛模拟器在具有以下形状的数据框架中为每个投资组合生成分配以及风险、回报和夏普比率:

然而,海图绘制者期望风险、回报和夏普比率的 3x1D 阵列:

映射器将蒙特卡洛模拟器输出的数据映射为海图绘图仪所需的输入格式。

这是单一责任模式的一个例子。每个组件/类都有自己明确的职责。这个特性允许我们在将来轻松地维护和扩展应用程序。

文件名:mappers.py

import pandas as pd
class portfolios_allocation_mapper:
    [@staticmethod](http://twitter.com/staticmethod)
    def map_to_risk_return_ratios(input):
        portfolios = input.columns.values[2:]
        returns = input.loc[input['Symbol'] == 'Return'].values[0][2:]
        risks = input.loc[input['Symbol'] == 'Risk'].values[0][2:]
        sharpe_ratios = input.loc[input['Symbol'] == 'SharpeRatio'].values[0][2:]
        df = pd.DataFrame(
            {'Portfolio': portfolios,
            'Return': returns,
            'Risk': risks, 
            'SharpeRatio': sharpe_ratios})
        return df

11.最后一部分——主文件——胶水

当我们开始这篇文章时,我们概述了这个过程的 7 个步骤。

主文件按照正确的顺序执行这些步骤

我们是如何实现的?

我们实现了一个 Main.py 文件,它运行上述所有步骤:

from settings import settings
from object_factory import object_factory
from mappers import portfolios_allocation_mapperdef generate_optimum_portfolio():#instantiate the objects with the settings
    obj_factory = object_factory(settings)
    ce = obj_factory.get_companies_extractor()
    cp = obj_factory.get_charts_plotter()
    mcs = obj_factory.get_portfolio_generator()
    fr = obj_factory.get_file_repository()
    mc = obj_factory.get_metrics_calculator()#1\. Get companies
    companies = ce.get_companies_list()#2\. Get company stock prices

    end_date = settings.get_end_date()
    start_date = settings.get_start_date(end_date)
    closing_prices = obj_factory.get_price_extractor(companies).get_prices(settings.PriceEvent, start_date, end_date)#plot stock prices & save data to a file
    cp.plot_prices(closing_prices)    
    fr.save_to_file(closing_prices, 'StockPrices')#3\. Calculate Daily Returns    
    returns = settings.DailyAssetsReturnsFunction(closing_prices, settings.ReturnType)
    #plot stock prices & save data to a file
    cp.plot_returns(returns)
    fr.save_to_file(returns, 'Returns')#4\. Calculate Expected Mean Return & Covariance
    expected_returns = settings.AssetsExpectedReturnsFunction(returns)
    covariance = settings.AssetsCovarianceFunction(returns)
    #Plot & Save covariance to file
    cp.plot_correlation_matrix(returns)
    fr.save_to_file(covariance, 'Covariances')#5\. Use Monte Carlo Simulation
    #Generate portfolios with allocations
    portfolios_allocations_df = mcs.generate_portfolios(expected_returns, covariance, settings.RiskFreeRate)
    portfolio_risk_return_ratio_df = portfolios_allocation_mapper.map_to_risk_return_ratios(portfolios_allocations_df)

    #Plot portfolios, print max sharpe portfolio & save data
    cp.plot_portfolios(portfolio_risk_return_ratio_df)
    max_sharpe_portfolio = mc.get_max_sharpe_ratio(portfolio_risk_return_ratio_df)['Portfolio']
    max_shape_ratio_allocations = portfolios_allocations_df[[ 'Symbol', max_sharpe_portfolio]]
    print(max_shape_ratio_allocations)
    fr.save_to_file(portfolios_allocations_df, 'MonteCarloPortfolios')
    fr.save_to_file(portfolio_risk_return_ratio_df, 'MonteCarloPortfolioRatios')   

  fr.close()
#This function will execute the steps abovegenerate_optimum_portfolio()

注意函数generate_optimum_portfolio() 按正确的顺序执行步骤:

  1. 它首先实例化所需的对象
  2. 获取公司提取器以获取所需的公司。
  3. 获取价格提取器以检索资产价格
  4. 计算资产的日收益和协方差
  5. 调用蒙特卡洛模拟器生成投资组合及其回报、风险和夏普比率。
  6. 然后,绘图仪绘制所需的数据,文件存储库保存数据以供分析。

此功能演示了我们如何实现一个解决方案,将任务委托给负责执行其职责的功能。然后它帮助我们构建一个可维护的应用程序。

7.3.GitHub 中的完整代码

请点击此处访问 GitHub 上的完整代码

8.后续步骤

这是一个可行的解决方案,可以让我们获得最佳的投资组合。现在框架已经构建好了,我们可以轻松地增强它。我将添加以下功能:

  1. 使用优化器来建立一个有效的边界。这将通过先进的优化技术产生大量优秀的投资组合。
  2. 扩展 companies extractor 以生成包含所有 NASDAQ 100 公司的投资组合。
  3. 实施卓越的风险和回报措施,以及前瞻性协方差矩阵。
  4. 使用数据科学和机器学习的概念来帮助我们获得卓越和最佳的投资组合。
  5. 构建一个应用程序,为我们找到前 x 名,例如 10 家公司,然后运行最佳投资组合应用程序。

9.摘要

如果您希望看到这些后续步骤得以实施,请告诉我。此外,让我知道你如何喜欢这篇文章。

本文的重点是通过蒙特卡罗模拟生成最优投资组合。我已经用 Python 实现了一个端到端的应用程序,本文记录了该解决方案,以便更多的读者能够从中受益。

文章还深入浅出地解释了投资管理所需的金融、数学和编程知识。

希望有帮助。

注来自《走向数据科学》的编辑: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语

朱莉娅是量化金融的最佳语言吗?

原文:https://towardsdatascience.com/best-language-for-quantitative-finance-here-are-my-findings-f1f458be48b7?source=collection_archive---------5-----------------------

在过去的几个月里,我一直在研究日内量化策略。附带的结果是,我用 Python、C、Fortran 和 Julia 测试了类似任务的工作流。这是我的发现。

背景

为了给出已测试项目性质的背景,我将开始澄清:

  1. 这些项目与工具交易相关(即我设计和模拟衍生品市场算法/量化策略)。
  2. 我没有在这些策略中使用机器学习或人工智能技术,只是简单的统计和模拟。
  3. 处理的数据集很大,但并不庞大,通常我的模拟涵盖每个资产/工具的 3000 万个记录数据集,每个数据都使用多次,我做参数和蒙特卡罗分析。这意味着大量的迭代。
  4. 我不是专业的程序员,也不想成为一名程序员,我只想专注于市场逻辑和利用有利可图的优势的策略。

我的任务是找到一个合适的工具组合,既能表现得足够好,又能简化我的工作流程。因此,审查是基于这些技术的最终用户的观点。

这种情况有一些含义:

  1. 我需要一种可以轻松处理大型数据集的语言。
  2. 我需要速度。
  3. 我不需要那么高的速度来要求多核或并行处理。
  4. 我现在不需要机器学习或人工智能库。

这篇文章是我寻找最佳工作流程之旅的成果。这是对每种语言的优势和劣势的一种主观但有根据的看法。我希望你觉得有用和愉快。

开端:Python 和 R

接近这个领域意味着你可能会从 Python 或 R 开始,我也是。

早在数据科学术语出现之前,r 语言就已经是科学/学术团体进行统计的自然选择。r 是 S 语言的开源实现,它是 70 年代在贝尔实验室创建的。虽然 R 是革命性的,非常适合统计学,但我发现它很难掌握,并且在处理大型数据集时效率极低。我无法完成简单的任务,例如从 CSV 加载几年来的整个价格集。

交易模拟通常需要大量数据,如果您需要提前开始拆分数据,或者寻找其他加载方法,或者只是加载过程复杂,那么探索其他选项是值得的。这并不意味着 R 不能应付它,只是我不觉得它简单明了。数据加载是数据分析不可或缺的一部分,应开箱即用。

Quantitative finance ends up having large data sets. Storing and loading large amounts of data for simulation is necessary

令人惊讶的是,像加载一个平均/大尺寸的 CSV 这样的基本任务对于某些现代语言来说可能是一个障碍。将一个 200Mb 的 CSV 文件加载到内存中可能会在每次分析的第一阶段显示出一些弱点:数据加载和准备。

在过去的几年里,Python 一直是我的中小型项目的伙伴语言。Python 易于学习,易于编码,当与 Numpy 和 Pandas 结合使用时,在数据科学领域享有良好的声誉。Jupyter 作为一个交互式控制台也有助于使 Python 成为数据科学项目中最广泛选择的语言之一。它的成功部分是因为它是一种广泛使用的通用语言,也可以用于数据科学。这使得它对有编程背景的新人更有吸引力。

虽然 Python 很简单,但我们不能忘记 Numpy 和 Pandas 是通过外部库对该语言的扩展。它们不是语言的自然组成部分。Python 也是一种缓慢的数字处理器,因为它被设计成一种非常高级的松散类型语言。Python 爱好者会说你可以改进它,现代 Python 有 Cython 这样的东西和无数的解决方案。但如果我必须处理数字运算,我更喜欢自然的数字运算。

Python 中最有用的一点是使用数据帧的概念。DataFrames 是一个出色的策略,我已经将它融入到我的工作流程中(即使在使用普通数组执行密集的数字处理分析时)。数据框架允许在模拟/分析过程中丰富、调试和可视化所有工作流程。我将它们作为一个管道,模拟的不同步骤将它们的结果添加到分析中。我喜欢把它们想象成一个列表板,所有的结果、分数、测试和条件都被标注并在不同的模拟阶段之间传递。每个阶段都使用以前的数据,并将数据添加到板上,在模拟结束时,数据帧包含评估模拟策略的所有信息。

在使用 Python 的第一次测试中,我在加载大型数据集时遇到了很多问题,尤其是在我为此任务分配的小型服务器中。我也经历了糟糕的表现。虽然很容易得到一个更强大的服务器,但我决定让 C 试试。

C/C++

用 C 是不会错的。C 是成熟的,它几乎可以做任何事情,并且提供非常高效的代码。自从 ANSI C 标准在 1989 年制定以来,C 语言并没有实质性的改变。现代标准增加了功能、更可移植的数据类型和其他特性,但对于模拟来说,即使旧标准也适用。C++被广泛使用,但是面向对象的范例在这类任务中没有提供价值。我认为它的使用更多地与年轻人学习 C++而不是 C 有关,而不是与面向对象范例在这个特定领域的实际好处有关。

C 的主要问题是很难用它做复杂的事情。对于小的算法例程来说,它大放异彩,而要让它执行缓慢实际上是相当困难的。但最大的问题是速度和性能是通过指针来实现的,调试指针可能很有挑战性。

C/C++ language is widely used in HFT industry. It is the preferred choice when performance is paramount. OpenMP & MPI standards allow to easily implement parallel computing in C.

我开始开发一个 C 库来帮助模拟测试,当我设法得到合适的结果时,我注意到随着项目越来越大,调试的时间和复杂性在缓慢但稳定地增长。当这种情况发生时,这是一个早期的警告,表明项目在复杂性方面获得了太多的权重。我可能想用 c 做太多了。

c 是一个杰出的工具,它在 HFT 工业中被广泛使用,因为它是一个自然的执行者,但是你必须准备好应对需要熟练资源的长期项目。此外,某些在 Python 等语言中非常简单的任务在 c 语言中可能非常具有挑战性。调试也是一个大问题,这一点已经说过了。

Python + NumPy +熊猫

一旦我意识到用 C 做任何事情的复杂性,我就回到 Python,试图找到一种使用更小的子集和 SQL 的变通方法。这也有助于当时一位同事向我展示了一个名为back trader的库,我们花了几个联合会议来实施一些测试,我提议分析 DAX 开盘。

Backtrader 被证明是缓慢的,有时是一种负担,但它也有助于检测工作流程中的一些早期需求。如果您想要现成的东西,并且愿意为性能和定制付出代价,那么这是一个很好的库。根据我的经验,如果你在这个行业,你最终会想要一些更具体的策略。

有了从这些经历中获得的信息,我设法用 Jupyter 在 Python 中完全实现了所有东西,第一个策略也完全实现了。

Python is the cool chap of Data Science. While it is not the best in terms of performance. It is easy to learn and code language and can be applied to many different areas. In the last years it has become the preferred Data Science platform.

虽然看到积极的和不断增长的权益曲线是一件非常高兴的事情,但我注意到工作流程中存在严重的瓶颈。这个模拟对朱庇特来说太大了。我发现在 Jupyter 中包含蒙特卡罗或参数分析并不自然,也不清楚如何实现报告以交叉验证结果并确保在编程阶段没有错误。

Python 对于这项任务来说总体上也非常慢,而 Jupyter 在小型项目中被证明是一个很好的助手,但是在大型模拟中有点难以理解。

从所有问题来看,主要的问题显然是性能和代码缺乏结构。

声称在 2019 年进行结构化编程可能会被视为不合时宜,但事实上模拟程序与 80 年代的结构化编程有许多共同的根源。对于这些特定的任务,像面向对象或函数式编程这样的概念是不必要的复杂层次,我发现基本的、普通的、简单的结构化编程是解决这类问题的好方法。

我发现很难在 Python 中正确地构造代码;包/模块实现落后于 Python 在其他领域提供的简单性的平均水平。不过这是个人观点。

使用 Python 进行调试一如既往地简单,事实证明,与以前的 C 解决方案相比,这是一个很大的改进。

Python + C

下一个合乎逻辑的步骤是用 C 语言替换 Python 中速度较慢的部分。根据我第一次尝试纯 C 语言解决方案所获得的经验,我定义了一个例程层来处理模拟本身。由于这是集中在核心模拟例程更简单,因此更容易在 C 中调试和实现,而 Python 负责协调其他一切。

编排模拟工作流不需要速度,Python 提供了更友好的环境。C 例程打包在一个共享库(Windows 的 DLL,Unix 的 shared object)中,稍后使用 CTypes 从 Python 调用它。

这种结合使得 C 能够在 200/300 毫秒内通过序列化完成预加载所有数据(3000 万条记录)这样的事情——这只是为了举例说明 C 有多快。当不使用序列化时,CSV 读取也非常快,因为使用了固定长度的记录(比使用 Python 快得多)。在这样的速度下,不需要使用任何数据库。它只是一个普通的文件和内存。其余的统计分析也非常快,因为 C 允许通过使用指针和数组来实现快速算法。这种设置的瓶颈总是 Python 中的 Matplotlib。

在我看来,将 Python 和 C 语言结合起来是一个双赢的解决方案,可以让你两全其美。

FORTRAN 语言

我决定付出额外的努力来测试另外两种语言:Fortran 和 Julia。目标是在同一种语言中加入高级模拟工作流编码和低级回溯测试例程。尽管它远不是一种流行的语言,但我首先评估了 Fortran。

Fortran 是最古老的编程语言之一。撇开 COBOL 不谈,它可能是最古老的。虽然它曾经是科学和工程分析的首选,但在 90 年代它基本上被 Matlab 取代,但它在计算要求高的科学领域仍然保持强劲。

Fortran 现在是一种小众语言(目前在世界上最常用的编程语言列表中排名第 30 位),但它在高能物理、天体物理和分子动力学等专业领域仍然有活跃的社区。与 C 一起,它也是超级计算的主要编程语言。OpenMP 和 MPI 等标准定义了在内核和分布式计算机之间分配计算的方法,它们总是首先为 C 和 Fortran 实现。

If you think Fortran is dead, think twice. Astronomy, climate modelling, computational chemistry, fluid dynamics, physics, hydrological modelling, structural engineering, all of them use Fortran.

虽然现代 Fortran 与大多数人所想的(大写代码、goto 指令和穿孔卡片)毫无关系,但它的语法显示出了一些年龄。它允许一个好的代码结构,并且很容易学习(甚至是掌握)。我在将最后一个模拟移植到 Fortran 时的经验是,编码很容易,特别是用 C 编写的算法部分更容易用 Fortran 编写。结构化代码也优于 Python,尽管这是个人观点,我知道很多人不同意这种说法。

还有一些问题:与图形工具的集成更加困难,以及变量需要提前声明的事实(这是我不喜欢的),但在我看来,主要问题是调试非常困难,因为 Fortran 最终会调用 C 编译器。所以我的经验是调试 Fortran 比调试 Python+C 解决方案要难一些。

从积极的方面来看,Fortran 也有一些独特的解决方案来处理数组和结构化数据,其中包括自定义索引——array[2000:2020]是一个有效的索引范围,这是其他语言无法实现的——向量运算和初始化变量和结构的简单方法。

如果您需要速度并计划进行需要多 CPU 和/或多核的分析(HFT 工业界大量使用 C++),那么 Fortran 或 C 是合适的选择,AMD 和 Intel 保持其编译器部门同时销售 C++和 Fortran 编译器也不是偶然的。但是如果你不需要那么快的速度,最好是牺牲一些性能来换取一个更友好、更容易调试的环境和使用数据帧的可能性。

Fortran 性能惊人。Fortran 能够从一个 CSV 文件中读取一整年的价格,将它们转换为整数以避免精度损失,将它们向下舍入为合约价格,并在大约 1 秒钟内将它们存储到内存中。这意味着使用 20 年 1 分钟价格的策略将被载入内存,并准备在 20 秒内使用。它比我尝试过的任何其他语言都要好。

它对数组的自然使用也使得计算速度非常快。在许多运算中,Fortran 优于 c。信不信由你,60 年后,它仍然是头号数字处理器,它的结构非常适合模拟问题,因为它在设计时就考虑了这类问题。

朱莉娅,新来的

我最后尝试的语言是茱莉亚。随着经验的积累,以及 Julia 承诺用 C 语言的速度提供 Python 和 Pandas 的简单性,尝试 Julia 是必须的。

我发现这种语言很容易学习,而且结构合理。语法清晰,不啰嗦,一目了然。模块允许(一旦你理解了它们)充分地分离代码,就像它们分离域和变量一样。模块还允许轻松共享全局变量。

这种语言的某些方面在开始时有点令人费解。花了一些时间去理解什么是可变的,什么是不可变的。变量既不通过引用也不通过值传递,而是绑定到特定的对象。这样,如果我正确理解了这个机制,它就类似于 Python。

这种语言足够灵活,允许您强制使用类型(我发现这在这个领域很有用,因为它有助于优化内存使用和性能),但对于少量使用,如果您不想指定类型,则不需要指定类型。时间戳处理也非常简单,这与这个行业相关。

使用 Julia 感觉你是一个新技术的早期采用者。主要的担心是稳定性,而且你也要面对一个事实,那就是大多数人会选择 Python。

Julia 将向量符号和数据帧作为语言的一部分。事实上,数据帧并不是语言的一部分,而是作为一个库并入的——就像 Python 中的 Pandas 一样——但感觉上它们是语言的一部分,这是我在使用 Pandas 时没有体验到的。

数据加载比其他语言稍慢,但是我使用 CSV 和一个辅助数据帧来解析输入数据。通过直接转换和使用固定长度,我确信可以获得更好的性能。执行计算所需的总时间接近 C,所以一般来说,您不会注意到任何差异。

Julia 可能不像其他语言那样稳定和成熟。在我的 BSD 工作站上,我不得不直接从网站上下载最新版本,因为默认包含在发行版中的版本无法正确编译软件包。

正如已经提到的,Julia 易于编码并且相对容易学习——一旦你克服了语言的一些不太直观的方面,例如可变性/不变性、变量范围和模块如何工作。优点是数据帧和向量操作比 Python 更好地结合在一起。Julia 预先编译了代码,并且它被设计得很快。包安装服务也比 Python 更好地集成了。

总的来说,我的感觉是朱莉娅是这项任务的合适工具。它是现代的,易于学习,它更好地结合了操作矢量和数据帧的功能,性能远远优于 Python。它免除了您使用 C 代码(更难调试)或 Fortran(在行业中可能被视为更奇特的语言)的麻烦。唯一担心的是,由于不够成熟,你可能会担心大型项目中的问题,甚至是计算错误。我还没有发现这些,但我也没有花足够的时间学习这门语言。

摘要

定量金融学中发现的问题与科学模拟中发现的问题非常相似。

工作流程、向量运算、调试、代码清晰度、数据帧的存在和性能等方面是决定语言是否适合这项任务的关键因素。

对于要求最高的任务,C 和 Fortran 保持了成熟解决方案的地位,但它们在技能方面要求很高。Fortran 可能在这个特定的行业中并不常用,但是如果您想使用它,它非常适合。

对于较轻的用途,Python 是最简单的方法,但是对于某些任务来说,它会很慢。当使用 C 编写核心模拟任务时,Python 和 C 的结合可以很好地权衡简单性和性能。

茱莉亚是极有前途的,干净快速的语言。虽然我没有在这门语言上花足够的时间,但我觉得它可能是这份特殊工作的合适工具,因为缺乏成熟度是我指出的最大担忧。除此之外,它结合了所有现代功能和优势,这是有用的定量金融,它很容易学习,非常快。

对于资金充足的大型机构来说,这可能不是正确的选择,因为它可能被视为一个有风险的提议,但另一方面,个人和较小的组织可以通过早期采用来获得竞争优势。我个人的观点是,这是值得探索的,因为它可以有助于建立一个生产级的战略开发和分析工作流程,这是你想在这个行业长期需要的东西。

当 Pytorch-transformers 遇上 Fastai (w/ Google Colab)

原文:https://towardsdatascience.com/best-of-two-worlds-pytorch-transformers-meets-fastai-5fd51ef34b0f?source=collection_archive---------19-----------------------

Photo from Kapa65 at Pixabay

更新:

在我发表这篇文章后,我有幸得到了 fastai 创始人之一杰瑞米·霍华德的回应,他建议我们可以使用 fastai 的回调系统来简化这里的工作,而无需调整 fastai 库中的基本训练循环。

这似乎是一个简单的解决办法,然而,我已经尝试了很长时间(在 @waydegilli am 的帮助下),但并不能完全正确(训练指标根本没有改善……)。我已经在 fastai 论坛上解决了这个问题,并且幸运地让 Sylvain 检查了代码。然而,度量仍然不动,训练循环无效。

为了您的方便,我已经用所有的结果编辑了一个 Google Colab,如果您对问题所在有任何想法,我将不胜感激:

[## 谷歌联合实验室

编辑描述

colab.research.google.com](https://colab.research.google.com/drive/1KFlyttLs7aAX35lMLiDw9Bb0s_74ILMy#scrollTo=NPgXRybJk2XN)

鉴于我在使用回调系统时遇到的小缺陷,下面的解决方案,看似“愚蠢”的改变训练循环的方式,仍然是合并 fastai 和 Pytorch-transformers 的最佳方式。

介绍

如果你关注深度学习的趋势,尤其是 NLP,你不可能没有听说过 Fastai 或 Pytorch-transformers 。这两个库为 NLP 实践者提供了友好的 API 和灵活的定制能力来进行原型设计和实验。Fastai 是一个通用的深度学习库,具有精心配置的 API,以适应各种应用程序:例如,文本,视觉,表格和协同过滤。Pytorch-transformers 是一个用于自然语言处理(NLP)的最新预训练模型库,包括 SOTA 模型,如 BERT 和 GPT2。同样值得注意的是,它们都是建立在 Pytorch 之上的,因此在它们之间建立连接不会太困难。考虑到这两个库的优点,把它们结合起来,这样我们就可以通过同时使用这两个包来简化建模过程,这不是很好吗?

答案是肯定的,并且在这篇精彩的文章中有详细的记录。本文提供了将数据集转换为特殊形式的过程,这样它就可以适合 BERT 模型,而这又可以通过使用 fastai API 进行微调。这篇文章也激发了下面这篇文章的写作,这篇文章比较了伯特和乌尔菲特的表现。

[## Fastai 与 BERT 的集成

序言

medium.com](https://medium.com/@abhikjha/fastai-integration-with-bert-a0a66b1cecbe)

上述文章在解释实现中的所有必要细节方面做了令人惊讶的工作,因此这篇文章不会进一步讨论,而是主要通过解决 Pytorch-transformers 库(来自 pytorch-pretrained-bert)的更新引起的一个关键问题来做出贡献。

我们有一个问题

在 Pytorch-transformers 更新之前,上面提供的解决方案和代码都运行良好。如果您浏览了更新之前撰写的上述文章中的代码。您可能会遇到这样一个异常:

如果你像我一样,对 Pytorch-transformers 没有太多经验,你可能会感到非常困惑,想知道为什么它对其他人有效,但对我的机器无效!在没有深入探究异常回溯的情况下,我认为这是因为我的手电筒过时了。我将 Torch 更新到了最新版本,但是仍然收到了异常。

在阅读 Pytorch-transformers 文档后,我意识到这个异常是由 Pytorch-transformers 包中 API 的变化引起的。简而言之,在 Pytorch-transformers 更新之前的日子里,model()会在网络向前传递之后产生结果;更新之后,模型的 forward 方法生成一个元组,其第一个元素是原始模型输出。如果你想了解更多细节,请阅读这里

# If you used to have this line in pytorch-pretrained-bert:
loss = model(input_ids, labels=labels)# Now just use this line in pytorch-transformers to extract the loss from the output tuple:
outputs = model(input_ids, labels=labels)
loss = outputs**[0]**

现在我们找到了代码中断的原因,让我们想出一个解决方案。

解决办法

解决方案是我们需要修改 Fastai 的代码,以适应 Pytorch-transformers 中model()行为的变化。

代码的关键部分是basic_train.py中的loss_batch(),我们可以看到model()输出不是一个元组,而是直接发送给损失函数。

def loss_batch(model:nn.Module, xb:Tensor, yb:Tensor, loss_func:OptLossFunc=None, opt:OptOptimizer=None,
cb_handler:Optional[CallbackHandler]=None)->Tuple[Union[Tensor,int,float,str]]:
    "Calculate loss and metrics for a batch, call out to callbacks as necessary."
    cb_handler = ifnone(cb_handler, CallbackHandler())
    if not is_listy(xb): xb = [xb]
    if not is_listy(yb): yb = [yb]
    out = model(*xb) **# Here the output is NOT a tuple**
    out = cb_handler.on_loss_begin(out)if not loss_func: return to_detach(out), yb[0].detach()
         loss = loss_func(out, *yb)if opt is not None:
        loss,skip_bwd = cb_handler.on_backward_begin(loss)
        if not skip_bwd:                     loss.backward()
        if not cb_handler.on_backward_end(): opt.step()
        if not cb_handler.on_step_end():     opt.zero_grad()return loss.detach().cpu()

一旦我们在库中找到了确切的位置,更改就变得轻而易举了:简单地选择如下所示的model()输出中的第一个元素,并为该函数提供一个新名称:

def loss_batch_bert(model:nn.Module, xb:Tensor, yb:Tensor, loss_func:OptLossFunc=None, opt:OptOptimizer=None,
               cb_handler:Optional[CallbackHandler]=None)->Tuple[Union[Tensor,int,float,str]]:
    "Calculate loss and metrics for a batch, call out to callbacks as necessary."
    cb_handler = ifnone(cb_handler, CallbackHandler())
    if not is_listy(xb): xb = [xb]
    if not is_listy(yb): yb = [yb]
    out = model(*xb)[0] **# we take the first element as the model output
**    out = cb_handler.on_loss_begin(out)if not loss_func: return to_detach(out), yb[0].detach()
         loss = loss_func(out, *yb)if opt is not None:
        loss,skip_bwd = cb_handler.on_backward_begin(loss)
        if not skip_bwd:                     loss.backward()
        if not cb_handler.on_backward_end(): opt.step()
        if not cb_handler.on_step_end():     opt.zero_grad()return loss.detach().cpu()

现在我们有了一个新的loss_batch_bert()函数,我们需要它来替换 Fastai 中加载到我们环境中的原始loss_batch()。我们可以通过以下方式做到这一点:

***# To change the loss_batch function in the loaded fastai module***import sys
module_basic_train = sys.modules['fastai.basic_train']
module_basic_train.loss_batch = loss_batch_bert
sys.modules['fastai.basic_train'] = module_basic_train

然后我们调整后的loss_batch_bert()被嵌入到 Fastai 库中,它应该可以满足 Pytorch-transformers 的需求。剩下的都是 Fastai 魔法:组装一个Learner()物体,进行试衣!

只需两个周期的训练,我们就可以在私人排行榜上取得 98.427%的成绩!考虑到我们的短期训练和非常“普通”的训练循环,这还不错。

如果您没有更新 Fastai 库,请注意。如果您想在训练过程中查看准确性,您可以传递一个准确性回调函数。但是,accuracy 函数可能已经过时,它的 return 语句中包含一个小错误:

((y_pred>thresh) == y_true.byte())。浮动()。意思是()#缺乏。byte()

它可以被固定如下

*# The more recent version fastai implemented exactly this version thus you could just directly call a partial funtion*
*# accuracy_thresh*
**def** accuracy_thresh2(y_pred:Tensor, y_true:Tensor, thresh:float=0.5, sigmoid:bool=**True**)->Rank0Tensor:
    "Computes accuracy when `y_pred` and `y_true` are the same size."
    **if** sigmoid: y_pred = y_pred.sigmoid()
    **return** ((y_pred>thresh)**.byte()**==y_true.byte()).float().mean()

我希望这篇文章是有帮助的,特别是对那些不熟悉 Fastai 或 Pytorch-transformers 的人。

代码可以在这里的笔记本中找到。

如果您在此过程中遇到其他问题,请随时告诉我。

编码快乐!

数据科学项目的最佳实践

原文:https://towardsdatascience.com/best-practice-for-data-science-projects-d91193fbd0ff?source=collection_archive---------9-----------------------

https://www.knime.com/blog/analytics-and-beyond

由于计算机处理能力的提高,以及处理器和内存成本的降低,现在使用数据科学技术来分析大量数据是可行的。这种增长变成了工业上的严重需求。这导致了对数据科学家的严重需求。为了满足这种就业需求,来自不同背景的人已经开始将他们的职业道路转向数据科学。人们渴望进入这个领域,不幸的是,其中包括许多缺乏适当技能和对数据科学生命周期了解的人。这一缺点已经开始在行业中引发问题。

数据科学项目需要遵循几个步骤,为了保持连续性,这些步骤应该一起进行。没有一个系统的工作流程,很容易迷失在其中的一个步骤中。在工业中,当人们认为他们完成了一个项目时,他们经常努力使项目得到全面的运营支持,因为他们没有考虑到这些生命周期步骤。这是一个常见但严重的问题,原因是人们不知道或不理解术语“生产就绪”的含义。

在我的工作中,我遇到过声称准确率为 92%的工程师,而测试的准确率为 83%。此外,我还看到一些已部署的项目省略了一些关键步骤,而这些步骤仍然在工程师的笔记本中。一个月后,产品经理要求每两周进行一次模型培训,这给工程师们带来了震惊。本文的目标是更好地理解进行数据科学项目时所需的生命周期和工作流。

数据科学项目的性质要求在项目的每一步都进行许多测试。出于这个原因,数据科学项目的一个非常常见的做法是使用笔记本。在项目结束时,很可能会有跨多个笔记本的多余代码不会用于生产。当工程师完成一个步骤时,他们会频繁地将完成的步骤输出,让笔记本上的所有内容都变得杂乱无章,然后立即继续下一步。当代码运行到最后一步时,假设代码已经准备好投入生产,项目已经完成是错误的。这种误解会造成时间和金钱的损失。

什么是生产就绪?生产就绪包含多项检查:

1.它跑吗?

2.是否满足项目要求?

3.系统稳定吗?

4.是否可维护?

5.是否可扩展?

6.有记录吗?

让我们深入研究其中的每一个。

它跑吗?意思是代码运行正常吗?代码应该能够平稳运行,任何步骤都不需要任何干预或修改。如果你有一个好的理由,你可以做一些手动的步骤,但是好的实践是从数据采集到预测有一个连续的流程,这是生产中最可能需要的。一种非常常见但不好的做法是写下每一步的输出,然后再次读取前一步的输出。您希望避免每一步都从磁盘中写入和读取。将信息保存在内存中,并将信息传递给下一步,而不将其写入文件,这将提高软件的性能。如果分析数据也超出了内存容量,则成批接收和传递数据。

软件应该满足项目的需求。当工程师完成项目的最后一步时,他们经常跑到项目经理那里演示模型的度量标准(大部分是根据准确性定义的)。产品经理认为项目需求得到满足是错误的。此时,如果产品经理不具备理解和评估模型的技术知识,工程师应该鼓励经理指派另一名主题专家来询问这些问题:

1.数据是如何收集/采样的?工程师可以有意或无意地引入数据偏差。数据科学家可以采用相同的数据,并显示相同的结果为有利或不利。模型评估应该基于您正在查看的那些指标。

2.如何将数据分成训练/验证/测试组?数据的不适当分割可能导致生产结果的显著差异。对任意大小的数据集应用 80-20%的分割,并且不对倾斜的数据集进行分层是工程师经常犯的错误。如果数据集很小,以 80-20%的比例分割数据是可以的,但是如果数据集很大,比如 1000 万。在这种情况下,以 80–20 的比例分割将产生 800 万个训练集大小和 200 万个测试集大小。你真的想让你的测试集那么大吗?因此,正确率应该在 95–05%左右,这将产生 950 万个训练集和 50 万个测试集。如果你的数据量越来越大,你需要增加这个比率。对于大数据集,我的意思是超过 2000 万,使用 99–01%的分割率将为训练和测试提供合理的大小。

3.测试数据是否代表了模型将要使用的数据?工程师和产品经理应该始终考虑数据流动的速度,以及数据可能会随着时间的推移而变化。在一定时间内,有多少百分比的数据在变化?一项基本检查是确保项目完成后收到的数据仍然代表业务需求。

在得到这些问题的满意答案后,工程师和产品经理就可以说软件满足了项目的需求。

一个健壮的架构师并在项目开发之初最小化软件缺陷,将有助于工程师开发出一个稳定的系统,在开发过程中不需要剧烈的变化。

工程师可以理解项目的每一部分和每一行代码,因为他们创建了代码。然而,好的文档可以让新员工快速上手。新人应该不会花太多时间去理解现有的工作。好的可维护软件不应该太复杂而难以理解。工程师应该记住,运行代码的是计算机,而阅读和支持代码的是人。创造一个复杂的代码不是一种天赋,让它简单、易读和易懂。

数据科学家必须确保软件能够处理增加的工作量。可伸缩性将减少未来花费在项目上的总时间。如果该模型有效,它是否会随着数据增加 1,000,000 倍而扩展?

文档是项目的关键部分,缺少了它,项目就不完整。大多数情况下,文档是在项目结束时创建的。这是一种不良做法,因为在数据科学项目中,每一步都需要记录详细信息,以便进行充分的文档记录,而在项目结束时从记忆中回忆这些细节并不是一种可靠的做法。在开发项目的同时开始文档构建。确保记下每个步骤的要点,以避免遗漏关键步骤。

遵循这些步骤,增加了拥有健壮项目的机会。在建立一个项目结构之后,创建一个 Docker 映像并从这个映像开始工作是开发软件项目的一种安全而有效的方式。由于 Docker 镜像已经包含了一个操作系统和编程语言的所有依赖项,所以即使在开发过程中也很容易向不同的方向移动。这将避免为每次代码更改创建新映像的需要,因为只需要在更新 docker 文件时创建一个新映像。此外,docker 文件将提供一个独立于操作系统的产品。您可以在任何操作系统上部署这个 Docker 映像。

确保在项目结束时你有以下东西:

1.一切都已编写好脚本,笔记本上的所有代码都已实现。

2.上述六项检查中描述的产品就绪项目。

3.该系统展示了从开始(第一步)到结束(最后一步)的平稳流程。

4.docker 图像已生成。

最佳实践——创建 ETL 第 1 部分

原文:https://towardsdatascience.com/best-practices-creating-an-etl-part-1-bdb563381025?source=collection_archive---------16-----------------------

ETL(和 ELT 的表亲相差不远)是一个通常不会在大学教授的概念,至少不会在本科课程中教授。然而,ELT 在几乎每个公司的日常运营中都扮演着重要的角色。

ETL 是将数据填充到业务仪表盘和算法中的管道,这些仪表盘和算法为管理者提供重要的见解和指标。这些管道从将数据从操作数据库提取到数据仓库的非常简单的过程,到支持更复杂的转换和应用的复杂的分析层。

问题是,我们的许多 IT 毕业生没有学到这一非常重要的技能,如果他们决定从事数据科学或数据工程方面的职业,他们很可能会在日常生活中使用这一技能。虽然数据科学工作在技术上并不真正包括 ETL,但是他们所做的很多工作最终会与数据工程师交叉。

我们希望涵盖 ETL 和良好的 ETL 设计的基础。

一个好的 ETL 看起来像什么,关键组件是什么,是什么使管道可维护和健康?这些都是数据工程师和数据库经理在开始新项目之前需要问的重要问题。

这将是几篇文章中的第一篇。在这篇文章中,我们将涉及一些基本概念,如提取/加载原始数据和日志记录。这些都是重要的话题,有很多细微的差别,我们想开始讨论

我们还将在 2 月 23 日上午 10 点(太平洋时间)提供一个免费网络研讨会来讨论这个话题。我们希望您能参加!

操作到原始

作战数据库

您的 ETL 将接收的所有数据都有一些来源,这些来源代表现实生活中的一种或另一种事务。这些数据可以代表去医院就诊的患者、在社交媒体上发帖的人或购买产品的客户。有些人可能会问,为什么不能只分析来自操作数据库的数据,而要通过额外的步骤将数据处理到另一个系统中。

最大的问题是,试图运行从运营数据库中聚合和分析大型数据集的分析流程会降低客户运营数据库的速度。此外,操作数据库高度规范化,从分析的角度来看,这使得它们的查询效率很低。这就是开发这种或那种形式的数据仓库的原因。

下面是一个向 SQL Server 中批量插入数据的方法示例

流程的第一步是将数据提取为某种形式的原始格式。

原始文件提取

从操作数据库中提取数据的方式可能会有所不同。然而,最一致的方法之一是将数据提取到一个原始文件中,如 CSV 或 XML 文件。将数据提取到原始文件中有几个好处。第一,提取数据的直接链接限制了外部系统与操作数据库的交互。这将避免阻塞需要发生的重要操作任务。此外,它还创建了数据在提取时的快照。如果您因为管道中可能发生的问题而需要重新加载数据,这可能是有益的。

拥有这种数据备份是有益的,以防有人意外删除重要数据。然后你会很高兴有容易重装的生抽。应该在某个表中跟踪这些原始摘录,该表记录了加载了哪些文件以及它们存在于何处。这样,您可以轻松地自动进行任何重新加载。此外,文件应该有一个命名标准。

一个简单的例子是 date extracted _ DateRangeInTheFile _ business object(例如 2017 01 01 _ 2016 09 01 _ 2016 12 31 _ customers . CSV)

元数据库和日志

在开发一个自动化的、可维护的和健壮的系统时,跟踪 ETL 过程中发生的事情是至关重要的一步。您的跟踪和日志记录的范围取决于您的公司有多大,以及需要进行多少 ETL/ELT 和其他数据转换。较大的公司可能有一个标准化的工具,如 Airflow,来帮助管理 Dag 和日志记录。

但是,如果你是一家初创公司或者非科技公司,有一个简化的日志系统可能就可以了。该系统的目的是管理需要加载/已经加载的文件,跟踪已运行的存储过程、错误、依赖性等。

深入了解系统的这些方面将有助于维护、改进系统,并填充任何丢失或加载不正确的数据。这意味着您实际上需要创建 3-4 个表(至少)来跟踪正在运行的内容、运行时间、计算等。特别是当我们推动越来越多的自动化系统时,这将是确保系统可维护性的关键。

将原始数据加载到原始表格中

一旦您从操作数据库中提取了原始数据并用新的文件信息更新了元表,那么您就可以开始专注于加载数据了。

尝试在 raw 的初始加载中添加许多复杂的业务逻辑可能很有诱惑力。这似乎可以简化过程,减少加载数据的步骤。所以为什么要增加更多的步骤。事实是,在早期添加太多的逻辑会使跟踪错误发生的地方变得困难。错误发生在摘录中、业务逻辑中还是其他地方?此外,更新新逻辑变得更加困难,因为您必须分析更新逻辑的最佳位置。

所有这些额外的考虑使整个系统更难维护。这就是按原样加载原始数据非常重要的原因。如果需要进行重复数据消除逻辑或映射,则可以在管道的暂存部分进行。

将数据加载到原始数据库后,接下来的步骤是 QA 和将数据加载到临时数据库。我们将在下一篇文章中继续讨论。如果你想了解更多关于 ETL 开发/ 自动化的知识,那么就注册我们的 ETL 网络研讨会,在这里我们将从头到尾讨论创建 ETL 的过程。

TensorFlow 2.0 中 NLP 分类的最佳实践

原文:https://towardsdatascience.com/best-practices-for-nlp-classification-in-tensorflow-2-0-a5a3d43b7b73?source=collection_archive---------7-----------------------

使用数据管道、迁移学习和 BERT 实现 85%的情感分析准确率

Photo by Jirsak, courtesy of Shutterstock

当我刚开始从事深度学习工作时,我参加了 Coursera 和 fast.ai 课程,但后来我想知道接下来该何去何从。我开始问类似“我如何为一个模型开发一个数据管道?”以及“我如何实施最先进的研究?”。

这篇博文回答了这些问题。这篇文章涵盖了 TensorFlow 2.0 中深度学习模型的开发,从数据的摄取一直到深度学习决定 Yelp 评论的情绪(积极或消极)。读完这篇文章后,你也将能够使用 Huggingface 的变形金刚库 1来使用一种叫做迁移学习的新技术,并使用谷歌的“模型骨干”( BERT [2])在维基百科上预先训练,来创建最先进的模型。

此示例的完整代码

完整的代码位于我在 https://github.com/ralphbrooks/tensorflow-tutorials 的 GitHub 上

模型构建的最佳实践

深度学习成功的关键之一是快速迭代。如果我们要建立一个预测模型,存储一次数据并基于该数据编写多个实验模型是有意义的。如果我们要建立一个预测模型,我们希望建立一个数据管道,在那里我们可以查看信息行,但在我们训练模型之前,我们不必处理所有的信息。

为了说明这些最佳实践,我将介绍创建一个模型的步骤,该模型基于手机商店的 Yelp 评论来预测情绪(“负面”或“正面”情绪)。我将使用 Yelp API 提取与关键字“美国电话电报公司”相关的商店的随机评论。以及相关联的评级(“情绪”)。我们的目标是看看我们是否可以创建一个深度学习模型,仅基于文本就可以确定情感。

步骤 1:高效地存储原始、干净的数据

我们的目标是预测情绪。理解标签(Yelp 评级)和特征(评论)之间关系的 TensorFlow 抽象通常被称为模型。

该过程的第一步是考虑将输入到该模型中的必要输入。在这个阶段,将评论和情感评分作为一个逻辑分组来考虑是有帮助的。TensorFlow 将这种逻辑分组称为tf.train.Example.

对于我们的用例,我们应该从定义示例开始。该定义如下:

接下来,我们将把这些例子高效地存储在名为 TFRecords 的文件中。

写出此信息的示例代码如下所示:

总之,使用 TFRecords 进行存储允许您对数据进行初步清理,并有效地存储这些数据以供多个模型使用。

步骤 2:为特定于模型的数据转换构建管道

We create pipelines to transform our raw, clean data into something that is gradually ingested by a model. Photo by Neale Cousland- — Courtesy of Shutterstock

第二步是创建一个数据管道,将你的特征(评论)和标签(情感评分)从保存的文件(TFRecord)输入到某种类型的神经网络中。在 TensorFlow 中,可以使用tf.data.Dataset实现数据管道。

tf.data.Dataset在您的模型开始训练之前,设置您的转换,而不实际处理它们。如果您正在测试您的管道,这是至关重要的。换句话说,在数据转换的不同步骤中,您最不想做的事情就是等待 3-4 分钟,因为前一个转换步骤仍在所有可用数据上运行。最好让转换管道的每一步都在少量数据(单批数据)上操作,这样可以更快地调试管道。

以下代码将有助于使这一概念更加具体:

如下所示,管道也可以用来清理数据。

第三步:使用迁移学习法建立模型

在我们的例子中,我们试图理解人类语言和句子中包含的情感。第一个挑战是我们的数据有限;我们的模型将只检查 738 条评论,以确定情绪。

如果我们预测维基百科所有页面的缺失单词,深度学习模型将有足够的数据来检测基本的语言模式,但我没有足够的计算能力来处理这些信息。

由于这些限制,我们将查看另一家公司预先训练的模型,并使用我们有限的训练数据对该模型进行微调(这一概念通常称为迁移学习)。具体来说,我们将使用来自 Google 的 BERT 模型,它已经在 Wikipedia 信息上进行了训练。

另一个最佳实践是尽可能使用成熟的框架。一家名为 Hugging Face 的初创公司有一个名为 Transformers 的框架,可以更容易地使用预先训练的模型,下面的代码显示了如何将单词转换为数字(标记化)以及如何使用 BERT 模型(TFBertForSequenceClassification)

拥抱脸变压器框架也使我们的数据管道转换成 BERT 模型可以理解的东西变得容易。

步骤 4:训练和评估 NLP 模型

现在,我们准备训练模型。如果我们运行模型 3 次迭代(历元),我们看到的准确率为 85 %。

考虑到 Yelp 评级捕捉了用户的全部情绪,这仍然是好的,但在许多情况下,Yelp API 只给你实际文本评论的一部分。

85%准确度的可视化如下所示:

上面的矩阵显示了以下内容:

如果这个人表达的是负面情绪,那么分类器的准确率为 91%。

如果客户表达了积极的情绪,我们的模型在大约 66%的情况下是正确的。

祝贺你!您已经完成了博文的结尾,现在您有了一个从构建数据管道到拥有精确模型的过程。

参考资料:

  1. T. Wolf、l .处女作、V. Sanh、J. Chaumond、C. Delangue 和 A. Moi。拥抱脸的变形金刚:最先进的自然语言处理。arXiv 电子版,2019 年 10 月。

2)德夫林、张、李和图塔诺瓦。BERT:用于语言理解的深度双向转换器的预训练。arXiv 电子版,2018 年 10 月。

关于白猫头鹰教育

你想跟上当前人工智能的趋势吗?您是希望实时处理流数据,还是希望将模型部署到生产中?

如果是这样的话,我的公司可以提供帮助——请联系我们 https://www.whiteowleducation.com 分部

组织数据科学项目的最佳实践

原文:https://towardsdatascience.com/best-practices-organizing-data-science-projects-e14fee5a4c6d?source=collection_archive---------17-----------------------

目前启动数据科学项目的主要考虑因素是什么?

Photo by Siriwan Srisuwan on Unsplash

数据科学项目在大多数情况下意味着大量的数据工件(如文档、excel 文件、来自网站的数据、R 文件、python 文件),并且需要重复和改进每个步骤,理解每个决策背后的底层逻辑。

1)数据组织的目标

有几个目标要实现:

  1. 优化时间:我们需要优化时间,尽量减少文件丢失、复制代码的问题、解释决策背后原因的问题。
  2. 可再现性:对于数据科学项目来说,重复是一个活跃的组成部分,有一个好处是组织系统可以帮助轻松地重新创建你的代码的任何部分(或整个项目),现在,也许在未来的某个时刻(6 个月,1 年,2 年…)
  3. 提高项目的质量:有组织的项目通常意味着过程中的详细解释。在文档化的过程中,在解释每一步背后的原因的必要性下,更有可能发现错误和不一致。

2)开始一个新项目:开始

从一开始,为一个数据科学项目从一个好的组织开始是一个好的做法,而不是认为这是浪费时间,我们可以将其视为以不同方式节省时间的明智方法。

此外,因为我们是在一个组织中与其他人一起工作,所以理解每个人都有不同的工作流程和工作方式是很重要的。对于共享项目来说,不仅要对文件夹结构,而且要对每个文件夹的预期内容达成真正的共识,这是一个好主意。

3)使用控制版本

为什么必须使用控制版本?委派基本任务,如:

  • 有一个自动化的工作备份系统,这是非常有价值的必要工作。
  • 用于在整个项目期间处理文件的更改。此外,返回到以前的版本,以便检查一些东西。版本控制系统可以解决检查和检索先前更改的问题,并允许使用单个文件而不是复制文件。
  • 促进与他人合作的过程,使共享文件和继续处理文件变得容易。

一些最流行的工具是 GIT,SVN,Subversion…不管最终选择最好的想法是实现它。

4)记录一切

当我们谈论文件时,我们指的是:

  • 包含用于分析的文档
  • 中间数据集
  • 代码的中间版本

最具挑战性的决定是决定在一个文档上投入多少时间:时间太多,是的,这是浪费时间,时间太少,文档将是不完整和无用的。

5)改进流程

基本思想是评估过程和改进工作流程。

在完成一个项目或交付一些东西的时候,评估是否有需要改进的地方是一个好主意:更好地组织文件,或纠正记录文件的方式,不管最后是什么,这个想法是要理解任何过程都是不断运动的,你需要改进它。

结论

管理数据项目的组织意味着评估组织系统的目标是什么,如何组织数据,建立备份系统和版本控制的最佳方法,以及如何记录所有过程。

创建设计驱动的推荐架构的最佳实践

原文:https://towardsdatascience.com/best-practices-to-create-ai-driven-choice-architecture-6c355c178aae?source=collection_archive---------28-----------------------

Photo by NEW DATA SERVICES on Unsplash

我们每天都在做决定。早上醒来的那一刻,我们就开始有意识地做决定——无论是大事还是小事。我们选择起床、刷牙、选择服装、吃早餐等等。这些选择可以发生在任何时间任何地点——从杂货店这样的物理位置到数字网站。其中一些选择是有意创造的,而另一些则是在没有议程的情况下做出的。这种人为创造的选择通常是由营销和设计方面的专业人士设计的。然而,随着消费者之间的数字和物理交互不断融合,决策架构师正面临新的挑战,并使用人工智能作为这些新挑战的潜在解决方案。

我们已经与各种行业专业人士进行了交谈,并汇总了一些战略和战术解决方案,可以帮助改善基于人工智能的决策框架。通过使用推荐系统改进决策架构,我们相信它可以帮助消费者在日常生活中做出更好、更相关的决策。

这种系统使用历史消费者数据来建立决策模型,负责以两种方式帮助消费者做出决定:通过产品推荐或通过轻推,即使用小的心理技巧来轻推用户遵循特定路径的行为。然而,人类的兴趣是不断变化的,因此决策模型可能并不总是向消费者显示最相关的选项。例如,我们的位置、文化和社区数据可能不会总是在我们的模型中被捕获,这导致算法的结果不太准确。此外,算法无法根据用户新发现的兴趣或需求实时优化自身,从而将消费者引入歧途。

有各种战略和战术方法来处理这些错误。《预期设计》的作者 Joel van Bodegraven 建议使用反馈回路来帮助纠正人工智能提出的建议1。根据定义,反馈环直接从消费者那里获取反馈,以检查算法提供的推荐是否相关。如果不相关,算法设计者可以“重新训练”或修改模型,以改善其预测。从长远来看,这一战略举措有助于改善算法的结构,从而为消费者提供建议。

使用推荐系统帮助消费者做决定的另一个问题是,情感还有待于算法的理解,我们可以使用设计来帮助解决这个问题。我们发现,人类决策架构师 Satyendra Singh 知道是什么让人们做出决定。他提到“谨慎使用颜色会影响心情和感觉”[2]。通过使用颜色或某些视觉刺激,我们可以减少对决策模型错误的感知,同时实现反馈循环来帮助改进算法。这与极简设计相结合,可以在浏览不相关或容易出错的推荐时,以统一的方式更好地呈现各种选择。这就减少了选择的认知超载,如 希克斯定律 所述。

ROCeteer 的首席技术官 Heather Wilde 举了一个 Spotify 的例子,算法管理“每周发现”和“每日混合”播放列表,以减少用户的歌曲选择3。同样,Spotify 还允许用户通过其他“非算法”方式来发现歌曲,从而为他们的决策提供了灵活性。以这种方式,通过捆绑来自算法的结果来减少收听者的认知过载,同时通过呈现替代的捆绑选项来保留选择浏览的自由。同样,Dropbox 的产品营销主管 Veronica Wang 提到了她的团队使用的一种不同的方法。他们没有创建一个完全由人工智能驱动的自动化解决方案,而是将问题分解成更小的统计问题。这有助于他们理解用户的决策,并手动提出建议。她进一步提到,这种技术可以用来学习用户决策的细微差别,从而在未来开发完全自动化的解决方案。

这些战略和战术是实施过程,然而,要创建一个成熟的人工智能解决方案需要一个称职的团队。这个团队不仅负责设计系统,还负责监督系统的发展。创意总监兼设计顾问 Vincent Wanga 建议组建一个决策架构师团队,其中包括心理学家和社会学家,以及传统的设计师、营销人员和数据科学家。心理学家将理解人类情感和用户与产品的互动,而社会学家将从人种学的角度理解算法与用户文化和习俗的关系。这将最终培养人工智能系统更好地与观众产生共鸣,以帮助他们做出更好的个性化决定。

总之,人工智能肯定可以帮助 choice architects 缩小物理和数字领域决策融合的差距。然而,寻求实施这种解决方案的公司需要记住行业专家描述的这些战略和战术。

— — — — — — —

参考文献

1范·博德格雷文,J. 设计预期用户体验 (2017),UX 集体

[2]辛格,S. 色彩营销的影响 (2006),祖母绿洞察

3王尔德,H. 设计为你选择的产品 (2017),福布斯

数据科学家的最佳 Python 实践

原文:https://towardsdatascience.com/best-python-practices-for-data-scientists-11056edda8c7?source=collection_archive---------2-----------------------

让我们看看生产级代码的一些行业标准。

Photo by: Matthew Henry

人们常说,一开始从事数据科学家工作的人不会写出干净的代码,这是有原因的。像 EDA、特性选择和预处理这样的大部分先决工作都是在 Jupyter 笔记本上完成的,我们不太关心代码。

将职业从软件开发转向数据科学的人更擅长编写生产级代码。他们知道如何正确处理所有的错误案例、文档、模块化等等。很多公司有时候会要求 X 年的软件开发,因为他们知道软件开发人员可以写出更好的代码。

数据科学家为生产模型而编写的大部分代码并不遵循 PEP8 这样的行业标准。PEP 代表 Python 增强提案。A PEP 是一个文档,描述了为 Python 提出的新特性,并为社区记录了 Python 的各个方面,比如设计和风格。我们在 python 中看到的每一个特性,都是由致力于 python 开发的成员(这些人是来自谷歌、微软和其他大型跨国公司的开发人员)首先提出,然后进行评审的。

但是为什么我们需要遵循这些指导方针呢?

正如吉多·范·罗苏姆(Python 的创始人)所说,“代码被阅读的次数比它被编写的次数多得多。”您可能要花几分钟,或者一整天,编写一段代码来处理用户认证。一旦你写了,你就不会再写了。但是你一定要再读一遍。这段代码可能仍然是您正在进行的项目的一部分。每次你回到那个文件,你都必须记住代码做了什么,为什么要写它,所以可读性很重要。

现在,让我们来看一些 PEP8 指南。

命名风格

  1. 变量、函数、方法、包、模块
  • lower_case_with_underscores

2.类别和例外

  • CapWords

3.受保护的方法和内部函数

  • _single_leading_underscore(self, ...)

4.私有方法

  • __double_leading_underscore(self, ...)

5.常数

  • ALL_CAPS_WITH_UNDERSCORES

6.首选反向符号

elements = ...
active_elements = ...
defunct_elements ...

刻痕

使用 4 个空格,不要使用制表符。

进口

  1. 进口顺序如下
1\. python inbuilt packages import2\. third party packages import3\. local imports

线长度

尝试断开任何超过 80 个字符的行。

even_numbers = [var for var in range(100)
                if var % 2 == 0]

有时,不可能再换行了,尤其是在方法链接的情况下。

真空

  1. 在字典中,冒号和键值之间要留有空格。
names = {'gagan': 123}

2.在赋值和算术运算的情况下,在运算符之间留出空间。

var = 25
math_operation_result = 25 * 5

3.当作为参数传递时,运算符之间不要留空格

def count_even(num=20):
    pass

4.逗号后留空格。

var1, var2 = get_values(num1, num2)

证明文件

遵循 PEP 257 的 docstring 指南,学习如何记录你的 python 程序。

  1. 对于显而易见的函数,使用单行文档字符串。
"""Return the pathname of ``foo``."""

2.多行文档字符串应包括

Summary lineUse case, if appropriateArgsReturn type and semantics, unless None is returned

例子

class Car:
    """A simple representation of a car.

    :param brand: A string, car's brand.
    :param model: A string, car's model.
    """
    def __init__(self, brand, model):
        self.brand = brand
        self.model = model

结论

当你写代码时,简单是你首先应该想到的。以后你可能需要参考你的代码或者其他人的代码,这应该不需要太多的努力就能理解。

参考

  1. https://sphinxcontrib-Napoleon . readthedocs . io/en/latest/example _ Google . html # example-Google
  2. https://gist.github.com/sloria/7001839
  3. https://realpython.com/python-pep8/

给数据科学家的最佳提示

原文:https://towardsdatascience.com/best-tips-for-data-scientists-a52d7cace027?source=collection_archive---------26-----------------------

学习新技能,打造令人惊叹的产品,并在任何求职面试中大放异彩

我在本文中总结了数据科学家在职业生涯中取得进步的最佳技巧。无论你是刚刚开始,还是想从初级到中级或中级到高级,总有适合你的东西

Master any job interview as a data scientist

GitHub 项目组合

首先,你应该在 GitHub 上建立一个开源项目组合。我建议创建三个项目:

  1. 一个分类项目,你可以使用图像/文本的公共数据库(你可以从 Kaggle 下载一个——下一段会有更多的介绍)对它们进行分类,并通过监督/非监督学习(从 PCA 到神经网络,通过 DBScan,KNN 等)磨练你的技能。).
  2. 一个 NLP 项目,将分析来自特定主题的推文的情绪,并相应地将它们分类为积极/中性/消极。这是一个经典的问题——选择一个你感兴趣的话题,这样你就有一个好故事来讲述它。
  3. 一个搜集项目,你从不同的来源搜集信息——如果你是体育迷,可以搜集体育新闻;如果你对金融或数据科学感兴趣,可以搜集金融波动。最终目标可能是创建一个自动化的网站,提供抓取和提取的内容。很容易在面试中表现出来。

如果你更高级,那么你肯定应该尝试最新的机器学习算法。例如,您可以:

  • 试试 GANs(生成式广告网络)生成了一些脸或者猫。
  • 尝试用更简单的游戏进行强化学习。
  • 试试 GPT-2 和文本生成。

你在这里有无限的机会。你一定要展示你精通神经网络和它们的基本原理,比如 Keras,PyTorch,TensorFlow。

知道自己知道什么,不知道什么

即使这听起来显而易见,你也应该能够回答关于你的知识,特别是技术细节或问题的问题。

实际上,你会被问到的最重要的问题是在一个给定的项目中什么是最难的。如果你遇到了一个特殊的技术问题,为什么和它是什么。你是怎么克服的?这些是你应该准备回答的基本问题。

准备好更详细地谈论算法,你过去用过的不同方法。开诚布公地分享你遇到的问题。这只能在求职面试时有所帮助。

润色你的 LinkedIn 个人资料

数据科学家经常忽略的最后一件事是建立一个连贯的 LinkedIn 个人资料,解释你过去做了什么以及你现在在哪里。如果你在职业生涯中有任何空白,一定要被问到——在巴厘岛冲浪 6 个月没什么错,你应该诚实地说出当时的动机和你想要实现的目标。我认为一个好的理由是你想离开你的屏幕,想重新开始,想作为一个数字游民工作——有很多理由解释为什么这个选择对你的职业生涯也是最好的。

你还应该向你以前的雇主征求推荐信。他们可以直接在 LinkedIn 上写——只要几句话就够了。如果你的上一次离职不是真的计划好的,你对此感到痛苦,试着解释为什么,以及你对下一任雇主有什么期望。

你应该能够准确地说出你为什么想换工作。是因为你在寻找新的挑战吗?如果有,为什么你现在的工作不能拥有它们?清晰地讲述你以前的工作经历是一笔巨大的财富。

闪耀!

总结起来,要真正掌握数据科学家职位的面试,你应该做 3 件事:

  • 建立 GitHub 项目组合;
  • 知道每个项目中最难的部分是什么,以及你是如何克服的;
  • 润色你的 LinkedIn 个人资料。

祝好运!

Data Science Job

最后,如果你想了解成为一名数据科学家意味着什么,那么看看我的书数据科学工作:如何成为一名数据科学家,它将指导你完成这个过程。

如果你想了解更多,请阅读我关于成为数据科学家的其他文章:

医疗数据培训/评估/测试拆分的最佳用途

原文:https://towardsdatascience.com/best-use-of-train-val-test-splits-with-tips-for-medical-data-b9026ad7e4a4?source=collection_archive---------22-----------------------

这篇文章介绍了将数据分成训练集、验证集和测试集的适当方法,以及如何最大限度地利用这些集合。它还讨论了特定于医疗数据的概念,其动机是医疗数据的基本单位是患者,而不是实例。

基础知识

如果您已经熟悉将数据集分为训练集、验证集和测试集背后的原理,可以跳过这一部分。否则,以下是我们在机器学习中拆分数据的方式和原因。

用于监督学习的数据集由示例组成。根据任务的不同,一个例子可以是一幅图像、一段视频、一句话、一段文本或一段录音。每个示例都配有一个标签,例如,像“猫”或“狗”这样的类别

在项目开始时,数据科学家将所有示例分成三个子集:训练集、验证集和测试集。常用的比率有:

  • 70%培训,15% val,15%测试
  • 80%培训,10%评估,10%测试
  • 60%培训,20%评估,20%测试

(有关这些比率的更多说明,请参见下文。)。)

这三个集合的用法如下:

如图所示,让我们假设您有三个模型要考虑:模型 A、模型 B 和模型 c。这些可能是不同的架构(如 ResNet vs VGG vs AlexNet),也可能是同一模型的不同变体(如具有三种不同学习速率的 ResNet)。)步骤如下:

  1. 随机初始化每个模型
  2. 在训练集上训练每个模型
  3. 评估每个已训练模型在验证集上的性能
  4. 选择具有最佳验证集性能的模型
  5. 在测试集上评估这个选择的模型

为什么不能只用一个数据集呢?让我们想象一下,如果我们将所有的数据作为“训练集”,会发生什么当我们想要评估性能时,我们只需查看训练集的性能。现在,如果我们幸运的话,训练集的性能可能会反映出该模型在它从未见过的数据上的表现。但是如果我们运气不好,模型只是简单地记住了训练数据的例子,当我们给它一个从未见过的例子时,它就完全失败了(“过度拟合”)。我们没有办法弄清楚我们是幸运还是不幸——这就是为什么我们需要一个验证集。验证集由模型在训练中从未见过的示例组成,因此如果我们获得了良好的验证集性能,我们可以感到鼓舞的是,我们的模型已经学习了有用的可概括原则。

但是,如果我们有训练集和验证集,为什么我们还需要测试集呢?测试集很重要,因为“选择最佳模型”(基于验证性能)的步骤会导致某种形式的过度拟合。请这样想:假设您对数据尝试了一千种不同的模型或模型变体,并且您对所有这些模型都有验证集性能。选择具有最佳验证集性能的模型的行为本身就意味着您,人类,已经为验证集“调整”了模型细节。您在“验证集上的最佳模型”上看到的验证集的性能值本质上是夸大的。为了对这个“最佳模型”在它以前从未见过的数据上的表现获得一个非夸大且更可靠的估计,我们需要使用更多它以前从未见过的数据!这是测试集。测试集性能通常会略低于验证集性能。

现在让我们回过头来解决为训练、验证和测试分配多少数据的选择问题。许多人想知道什么是“正确的比率”——但不幸的是,没有关于使用什么比率的明确规则。我个人喜欢 70-15-15,但这是一个主观的选择。权衡如下:

  • 更多的训练数据是好事,因为这意味着你的模型看到更多的例子,从而有希望找到更好的解决方案。如果你有一个很小的训练数据集,你的模型将无法学习一般的原则,并将有很差的验证/测试集性能(换句话说,它不会工作。)
  • 更多的验证数据是好事,因为它可以帮助您更好地决定哪个模型是“最好的”如果您没有足够的验证数据,那么在您对哪个模型是“最好的”的估计中会有很多噪音,您可能不会做出好的选择。
  • 更多的测试数据是好的,因为它让你更好地感觉到你的模型对看不见的数据有多好。如果没有足够的测试数据,您对模型泛化能力的最终评估可能不准确。

不幸的是,您添加到一个集合中的任何数据都必须从另一个集合中移除。这就是为什么对于非常小的数据集,你可能想要使用像交叉验证这样的技术(这不在本文中讨论,但是如果你想了解更多,你可以查看本文。)

适当使用培训/验证/测试数据

本节的要点如下:YOTO ( Y ou O 仅使用 T est set O NCE。)

我不会拐弯抹角……如果一个数据科学家想要开发一个新模型来解决一个问题,他们检查了一吨不同模型的测试集性能,然后报告了最好的一个模型的测试集性能,这就是作弊。通过反复检查测试集的性能,他们使测试集过拟合。测试集性能度量不再是模型泛化能力的可靠指标。

现在,使用测试集的好方法是什么?在此之前,我们将首先讨论一个使用验证集的好方法。

验证集是您应该在关于模型架构和超参数的每个决策中使用的。例如,如果您使用的是神经网络模型,则使用验证集进行以下操作是合适的:

  • 选择层数(深度);
  • 选择每层神经元的数量(宽度);
  • 在每一层的 CNN 中选择内核的数量/形状;
  • 选择是否使用剩余连接以及在哪里;
  • 选择是否使用预训练特征提取器;选择要使用的特征提取器;选择是固定还是调整该特征提取器的权重;
  • 选择一个激活功能 : ReLU、Leaky ReLU、eLU 等。;
  • 选择是否使用退出;选择在模型中使用 dropout 的位置;选择退出概率;
  • 选择是否使用归一化,在哪里:批量归一化,权重归一化,图层归一化等。;
  • 选择一个优化器 : Adam、Adagrad、SGD 等。;
  • 选择一个学习率;
  • 选择一个损失函数:交叉熵、MSE、应用的定制损失等。;
  • 选择批量大小;
  • 选择是否使用规则化;选择正则化强度。

换句话说,你在机器学习项目上做的几乎所有工作都应该只使用训练集和验证集。您应该假装测试集不存在。

关于架构/超参数优化的补充说明:假设您拥有优化上面列表中每个模型特征的每个可能组合所需的计算资源是不现实的。然而,很有可能你至少会深入探究其中的一些。如果你对超参数优化策略的讨论感兴趣,可以看看这篇文章。如果您有 100 个 GPU 供您使用,您显然可以比只使用 1 个 GPU 进行更多的超参数优化。

一旦你决定了一个最好的模型——有史以来最棒的模型——基于你的验证数据集的无数次实验,是时候使用测试集了。你应该在测试集上运行你最棒的模型来看看它的性能。这就是你应该报告的模型的性能。

在许多论文中,经常将您最棒的模型的测试集性能与其他一些不太棒的模型的测试集性能进行比较。实际上,在这种情况下,您必须在其他一些不太好的模型上获得测试集性能…这是当前“train-val-test”分割方法的一个限制。你的论文的读者会在心理上使用测试集来选择模型。(但是,这仍然比你用测试集开发你最棒的模型要好,那是作弊。)

医疗数据注意事项

如果您正在处理一个医疗数据集,那么只使用一次测试集来测量您最棒的模型的性能是非常重要的,因为医疗数据几乎总是难以获取和清理。您不太可能轻易获得“另一个测试集”,因此您希望测试集必须使用一次,以便它提供模型泛化能力的最佳估计。如果您计划在真实环境中部署您的模型,这就变得更加重要。你不想声称你的“心脏病风险模型”在测试集上有 0.95 的 AUROC,而实际上你对测试集进行了过度拟合,真实的性能更像是 0.62……因为那样你将使用一个糟糕的模型,并给真正的患者提供对其心脏病风险的误导性估计。

由于偶尔滥用测试集,一些描述医学数据的机器学习模型的作者已经开始明确强调他们恰当地使用了他们的测试集。例如,在“一种用于从小数据集检测急性颅内出血的可解释深度学习算法” Lee 等人注意到,

为了评估模型的性能,在模型开发过程完成后,我们收集了两个独立的测试数据集,一个是回顾性的,另一个是前瞻性的。

换句话说,李等人甚至没有创建测试集,直到他们使用训练和验证数据集开发了一个模型。

这是另一个例子。在“基于低剂量胸部计算机断层扫描的三维深度学习的端到端肺癌筛查”中, Ardila 等人使用了不止一个测试集,他们指出,

两个测试集只运行一次,以避免影响模型开发。此外,所有从事建模和图像分析的个人对测试集中的诊断是盲的。

为医疗数据创建训练/验证/测试分割

医疗数据不同于其他类型的数据,因为分割必须由患者决定,而不是由个别例子决定。无论您处理的是医学图像、医学文本还是医学表格数据,这一点都适用。示例:

  • 影像任务:对胸片中的疾病进行分类。在大多数胸部 x 射线数据集中,同一患者贡献了多个胸部 x 射线。数据必须基于患者标识符而不是单个胸部 x 射线来分割,因为来自同一患者的胸部 x 射线高度相关。
  • 文本任务:根据描述的疾病对医疗记录进行分类。这里,同样,数据必须基于患者标识符进行分割,因为关于同一患者的病历高度相关。今天患有糖尿病和囊性纤维化的患者明天也会患有糖尿病和囊性纤维化。
  • 表格数据任务:根据从电子病历中收集的表格数据预测住院风险,包括诊断、程序、药物、人口统计和实验室值。假设您正在考虑一家大型医院五年内的数据。基本上可以保证,在此期间至少有一名病人不止一次入院。如果 Smith 先生已经入院 3 次,那么这 3 个入院实例中的每一个都应该被分配到同一个集合。

通常,患者标识符是病历号或 MRN。这是一种受保护的健康信息,因此,如果您使用去识别数据集,将会有一个随机生成的患者标识符来替换原来的 MRN。

总结

  • 要训练和评估机器学习模型,请将您的数据分成三组,分别用于训练、验证和测试。
  • 如果您正在开发一个新的机器学习模型,您应该使用验证集来最终确定模型和超参数。那么您应该只使用测试集一次,以评估您选择的模型的泛化能力。
  • 如果您正在处理一个医疗数据集,那么分割应该基于患者标识符,而不是基于单个的例子。

Credit: xkcd “machine learning”

关于特色图片

特色图片由维基百科上俄勒冈州三姐妹的图片修改而来,这三个相邻的火山被称为南姐妹火山、中姐妹火山和北姐妹火山。

原载于 2019 年 9 月 15 日http://glassboxmedicine.com

被人工智能打败:当人工智能赢了会发生什么?

原文:https://towardsdatascience.com/bested-by-ai-what-happens-when-ai-wins-22388706482d?source=collection_archive---------19-----------------------

在某些任务上,人工智能已经比你强了。这里有一些如何应对的想法。

Photo by JESHOOTS.COM on Unsplash

几个月前,我给我爸发了一篇文章 20 名顶级律师在一项受控研究中被法律人工智能击败,这篇文章(如标题所示)讨论了一项关于人工智能如何应用于法律领域的研究,以及它如何与专业律师对抗。这篇文章的一个含义是,在许多常见的法律需求方面,如合同审查或写遗嘱,人工智能可能会取代律师。

这是一篇关于 AI 的有趣文章和应用,我花了很多时间思考。我和我爸爸分享它可能看起来很无辜,事实也的确如此,只不过我爸爸是个律师。

是的,我有点想激怒他(我保证,这是充满感情的)。

现在,似乎几乎没有一个星期不会遇到一篇声称人工智能将夺走我们所有工作的文章(然后变成天网并杀死我们所有人)。人工智能正被应用到许多不同的应用中,它经常让人感觉任何人工智能项目的最终目标都是超越人类。

在游戏世界中经常可以看到人工智能与人类的明确版本,在这里,高级人工智能与专业游戏玩家进行对抗,作为人工智能能力和复杂性的基准。

为什么我们要教 AI 玩游戏?

似乎自从研究人员在探索和开发人工智能以来,他们也一直在教他们的 AI 玩游戏

不管你怎么想,教人工智能玩游戏绝对不是浪费时间和金钱。

War Games — 1983

在游戏中,有内在的规则和奖励。这使得游戏很容易教人工智能作为复杂任务的“可评分”代理。游戏帮助开发者追踪 AI 的进展。游戏提供了一种安全(没有真正的生命受到威胁)但强大的方式来测试人工智能的性能,因为人工智能的性能可以通过分数来量化。

通常测试一个游戏人工智能的巅峰是让它与一个人类冠军比赛。

人类对机器

人类冠军和人工智能之间最引人注目的早期对决之一发生在 1996 年的和 1997 年的,在那场比赛中, IBM 的深蓝扮演世界冠军棋手,加里·卡斯帕罗夫。虽然卡斯帕罗夫在 1996 年的第一场比赛中输掉了第一局,但他能够适应深蓝的下棋方式,并赢得了六局中的三局,赢得了比赛。

卡斯帕罗夫同意在 1997 年与深蓝复赛。这场比赛包括六场比赛。深蓝在第二场比赛中做出了一个意想不到的举动——它放弃了抓住一个暴露的棋子的机会,以做出一个从长期来看更有好处的举动。卡斯帕罗夫被这个看起来很像人类的举动迷惑了,这让卡斯帕罗夫无法继续比赛(有趣的是,这个举动可能是一个 bug 的结果)。不管是什么引发了这一举动,卡斯帕罗夫最终输掉了这场比赛。

按照现代标准,深蓝的人工智能相当初级。为了下棋,深蓝被编码为使用蛮力方法,在下一步棋之前分析许多不同的序列。当深蓝击败卡斯帕罗夫时,人们猜测人工智能在游戏中的下一个基准将是中国的围棋,这将很难使用相同的方法编写计算机代码,因为围棋中可能的走法和序列数量要多得多。人们推测人类可能要过 100 年才能被围棋人工智能打败。

AI 击败人类围棋冠军,堪比深蓝 vs 卡斯帕罗夫,2015 年随着 DeepMind 的 AlphaGo 开始成为主流。先是 AlphaGo 击败欧洲围棋冠军范辉 (2015),然后 2016 年 AlphaGo 迎战韩国冠军(当时国际头衔排名第二) Lee Sedol ,然后在 2017 面对中国冠军 柯洁(比赛时柯洁被多个围棋协会评为世界第一)。

AlphaGo 基于一个比它的精神前身深蓝复杂得多的框架。AlphaGo 利用深度学习学习如何下围棋。AlphaGo 的一个更新版本 AlphaGo Zero 完全是通过给它规则,然后和自己对弈来训练的。这个新的框架已经被应用到国际象棋和日本兵棋的游戏中,以及最新版本 AlphaZero 的围棋中。

国际象棋和围棋是人工智能战胜人类的两个流行例子,但还有更多人工智能在回合制游戏中击败人类的例子(如 Jeopardy ),人工智能一次只需要处理一件事,并有足够的时间来完成。

最近,研究人员已经将视频游戏作为人工智能的下一个伟大舞台。视频游戏是一个挑战,因为玩家需要实时响应,并且经常需要在游戏的许多不同方面之间分配注意力。OpenAI 和 DeepMind 今年分别因其 AI 玩 Dota 2 和星际争霸 2 而出现在新闻中。

尽管这些玩视频游戏的人工智能系统已经取得了一些相当大的成功,但是它们还没有像它们的回合制兄弟一样统治各自的游戏平台。要更深入地了解游戏人工智能的过去和现在,请阅读 Engadget 的 Jamie Rigg 的文章人工智能是比我们更好的游戏玩家,没关系

从败在艾手里恢复过来

在 AI 和人类冠军的每一次交锋中,在某种程度上,为人类而战的冠军是在捍卫我们物种的荣誉。失败是痛苦的。输给一个不是人类的对手更难。

1996 年和 1997 年,卡斯帕罗夫压力很大,他是备受尊敬和钦佩的国际象棋世界冠军。比赛之前,出版物被冠以“大脑的最后阵地”这样的标题。尽管卡斯帕罗夫自信地参加了比赛,但他明显感到沮丧,甚至对深蓝的意外举动感到慌乱。

我的父母经常告诉我,当你和一个两岁的孩子开始争论时,你已经输了。同样,当你面对人工智能时情绪激动,你已经输了。许多人把卡斯帕罗夫的失败归因于深蓝是如何进入他的头脑的。

Kasparov vs. Deep Blue 1997 Credit: Stand Honda, AFP, Getty Images

在他输了之后,卡斯帕罗夫实际上指责 IBM 作弊,在比赛中制造了一些阴谋论。当然,人工智能还没有发展到足以做出这种动作或开发新的策略,对吗?唯一的解释是人为干扰。至少在这种情况下,卡斯帕罗夫会输给另一个(狡猾的)人,而不是一台存在威胁的计算机。

一个人会感受到压力和情境。当人工智能进行这些比赛时,它并没有真正意识到它不仅仅是与另一个人工智能进行另一场训练比赛。对于人类来说,这些对抗的风险总是更高。

在与 AlphaGo 的第三局比赛后,Lee Sedol 实际上为输给 T1 道歉:

我不知道今天该如何开始或说些什么,但我想我必须先表达我的歉意。我本应该展示一个更好的结果,一个更好的结局,以及更好的比赛内容,我为不能满足很多人的期望而道歉。我有点无能为力。如果我回顾这三场比赛,第一场,即使我回去重做第一场比赛,我认为我也不可能赢,因为我当时误判了 AlphaGo 的能力。

Lee Sedol vs. AlphaGo 2016 Credit: AP

Lee Sedol 最终在与 AlphaGo 的五场比赛中赢了一场。在比赛结束时,尽管输掉了五场比赛中的四场,他说:

就我个人而言,我对这个结果感到遗憾,但我想对在比赛中支持和鼓励我的所有人表示感谢……在我人生的某些时刻,我曾质疑自己是否真正喜欢围棋,但我承认,我喜欢与 AlphaGo 的所有五场比赛。在我使用 AlphaGo 的经历之后,我开始对经典的信念产生了一点质疑,所以我有更多的研究要做。

在输给 AlphaGo 之后,冠军柯洁与李·塞多尔(Lee Sedol)有着类似的情绪,他花时间学习 AlphaGo 的打法。他从比赛中得到的启示是,人们对围棋的了解并不像他们认为的那样多,还有很多东西需要学习。他继续写关于从 AlphaGo 中学到的经验的书。

AlphaGo 和 AlphaZero 已经影响了国际象棋、日本兵棋和围棋等游戏的玩法。人们正在意识到,尽管传统智慧会告诉我们,但围棋大师对这项运动还有很多不了解的地方。拥有这种游戏的外部视野正在改变游戏的玩法。AI 不受惯例约束。

比赛 20 年后,卡斯帕罗夫能够更加冷静地反思他的经历。他已经撤销了对 IBM 深蓝团队的许多指控,并为此道歉。他还写了一本关于他面对人工智能的经历的书。他现在是一个乐观的倡导者,与人工智能合作,以实现更美好的未来。

作为学者输给艾

每两年,蛋白质结构建模领域的研究人员都会举行一次全球性的实验/竞赛,名为结构预测的关键评估(CASP) 。这项活动的目标是给研究人员一个在全球舞台上测试结构预测方法的客观方法。正如 Vox 的 Sigal Samuel 所说,CASP 很大程度上是一场“成年人的奇特科学竞赛。”

去年举行的 CASP13 大会的获奖作品是 DeepMind 的 AlphaFold。

这种类型的研究是许多生物学家毕生的工作,包括 Mohammed AlQuraishi 博士(哈佛大学),他在他的个人博客上写了一篇非常有趣的帖子,讲述了被 AI 击败的经历。在他的博客中,他写道担心自己被人工智能超越,当他意识到 AlphaFold 的见解与该领域的研究方向一致时,他感到如释重负,然后将 AlphaFold 的成功归功于其母公司 Alphabet 的雄厚资金。

他还反映出,DeepMind 以局外人的身份进入一个领域并取得重大进展的能力,多少表明了学术界和大型制药公司的结构性低效。学术界的竞争性质阻止了信息的公开共享(导致每个研究小组不得不自己重新发现东西,浪费时间和精力),制药公司往往专注于销售而不是新颖的研究。

最终,AlQuraishi 得出结论,AlphaFold 的发现是一件好事——在生物化学最重要的问题之一上取得了重大进展。这导致了该领域更高的可见度和所有相关研究人员的智力进步。谁(或什么)做了这个发现并不重要。他对研究人员适应人工智能的建议包括专注于需要更多概念突破的问题,并将更多工程化的问题留给人工智能研究小组。

当 AI 为我们和我们的工作而来时,我们该怎么办?

AI 未来很可能会淘汰一些工作岗位。哪些工作和什么时候做还不清楚。正如 Mohammed AlQuraishi 在 Vox 的 Sigal Samuel 采访中解释的那样(是的,我已经链接了这篇文章两次,它真的很好,我希望是我写的):

曾经有一段时间,很多人认为工作是有等级的——智力工作是最后被取代的,机械工作是第一位的。但那其实不清楚。很可能机械性的工作需要很长时间才能被取代,因为制造能做出特定手势的机器人实际上很难。智力较高层次的东西可能会更快地被取代。

正如我们从每个不得不直接面对人工智能淘汰前景的人类冠军那里学到的那样,我们可以选择将此视为学习和做一些不同事情的机会。人工智能为新的激动人心的工作提供了机会。随着人工智能在某些任务上变得比我们更好,我们只需要找到新的任务来承担。我们还需要在决定开发什么样的人工智能方面发挥积极作用,并确保交给人工智能的工作以道德的方式进行。

Real Genius — 1985

我爸爸十年前就告诉我不要去法学院,可能是在人工智能在法律中的应用被探索之前。人工智能在法律工作中的应用正在被探索,因为有机会让一些事情变得更加高效和有效,而不仅仅是为了好玩或***难律师(嗯,可能有一点)。

我父亲在我年轻时告诉我的另一件事是,我成年后最终从事的工作还没有被发明出来。从某种意义上说,他是对的。我不认为在 90 年代,为软件公司写关于数据科学和分析的专业博客已经成为主流。从不太字面的意义上来说,我认为他的意思是今天的需求不会与明天的需求相同,如果你适应性强、开放,你最终可以做一些人们以前没有做过的新事情。

每当我们发明一项新技术,工作就会被打乱。想想今天的农场和工厂与 100 年前相比是什么样子。准备引入人工智能的行业是人工智能可以提高效率的行业,有可能使最终消费者的生活变得更好,希望整个社会也是如此。

原文。经允许重新发布。

使用 Wav2Letter 的自动分段标准实现更好、更快的语音识别

原文:https://towardsdatascience.com/better-faster-speech-recognition-with-wav2letters-auto-segmentation-criterion-765efd55449?source=collection_archive---------6-----------------------

脸书·艾的新损失函数改进了 ASR 中一项已有十年历史的技术

2016 年,脸书人工智能研究院(FAIR)凭借 Wav2Letter 这款全卷积语音识别系统开辟了新天地。

在 Wav2Letter 中,FAIR 展示了基于卷积神经网络(CNN)的系统可以与传统的基于递归神经网络的方法表现一样好。

在本文中,我们将重点关注 Wav2Letter 的核心模块:自动分段(ASG)标准。

Architecture of the wav2letter model

在上面显示的 Wav2Letter 架构中,我们会发现 ASG 位于声学模型的右侧。

ASG in the wav2letter architecture diagram

使用 ASG 卷积方法,FAIR 报告了应用于 TIMIT 数据集时字母错误率(LER)的显著改善。

TIMIT Letter Error Rate

…以及短序列和长序列的速度提升,尽管 Wav2Letter 使用了纯 CPU 版本的模型进行基准测试。

Short sequence timing in ms

Long sequence timing in ms

从根本上说,ASG 准则是一种特殊类型的损失函数。

ASG 建立在像连接主义时间分类(CTC)这样的老算法上,这些算法长期以来一直是语音识别模型的支柱。

要理解 ASG,我们首先需要理解像 CTC 这样的算法所解决的具体问题。然后,我们将简要了解一下 CTC,这样我们就可以最终了解 ASG 与它的不同之处以及它的改进之处。

从声音到文字

Wav2Letter 的核心是一个声学模型,你可能已经猜到了,它从声波中预测字母

Wav2Letter’s acoustic model

具体来说,Wav2Letter 将音频处理成切片,通过各种卷积层,并输出每个音频切片的一组概率。每个概率集包含模型的字母字典中每个字母的估计值。

这意味着,对于一段音频,我们可以估计出当时说出的字母是“e”或“t”或“s”,或者任何其他可能的字母。

声学模型吐出了这些概率的链,其中链中的每一个环节都代表了特定字母在该时刻出现的估计。

这个链包含了我们声学模型的假设。为了达到我们的最终预测,我们需要将这个概率链转换成在音频片段中出现的最有可能的字母序列

对齐问题

记住 Wav2Letter 的声学模型基本上是一个声波到字母的分类器。该模型“看到”了一点声波输入,并说,“好的,这看起来像一个‘H’或者可能是一个‘S’。

但与静态图像不同,声波在时间中流动。如果我们的短语是“猫”,我们怎么知道说话者什么时候停止说“T”而转到“H”呢?

为了学习“这就是‘T’的样子”,Wav2Letter 需要理解口语话语如何随时间在字母之间过渡

只有理解了这些转换,模型才能开始将其声音的表示映射到正确的字母标签。

但是我们有一个问题。语音识别的训练数据通常只带有音频和文字记录,没有用于两者之间对齐的数据。我们可以输入一个三秒钟的.wav文件,其中有人说“猫”,旁边是一个.txt文件,其中有字母:“猫”。

我们知道在‘The’中‘T’在‘H’之前,但是抄本没有告诉我们何时

Example letter alignments from CTC (top) and ASG (bottom) over an audio segment

手动将每个字母与音频中的匹配时刻对齐非常耗时,而且在大规模应用中几乎不可能。我们也不能依赖像“一个字母持续 500 毫秒”这样肤浅的一般规则,因为人们说话的速度不同。

我们该怎么办?输入 CTC。

CTC 如何解决对齐问题

传统上,实践者用连接主义时态分类(CTC)算法解决了这种对齐数据的缺乏(难道你不喜欢这些名字吗?).

在这一节中,我们将只触及 CTC 的要点,这样我们就可以看到 ASG 的不同之处。你可以在这篇关于 distilt的伟大文章中读到关于 CTC 的更深入的解释。

对于每一段音频,CTC 预计所有可能字母的一组概率加上一个关键的特殊“空白”标记

Wav2Letter 的声学模型将其概率集的输出链输入 CTC,CTC 开始寻找最高概率输出。并且它在没有任何定时数据的情况下完成它。

怎么会?

让我们举一个简单的例子,一个说话者说“你好”的音频文件。

正如我们已经看到的,我们的输入是由我们的声学模型转换成每个音频片段上每个字母的一组概率的音频。

A chain of probabilities generated by the acoustic model

在这个例子中,我们假设我们的字母字典只包含' h' 'e' 'l' 'o '和之前提到的特殊空白标记,我将用它的正式学名来称呼它: squiggly e

每个时间片都有对每个字母的估计。较暗的单元格表示该字母的概率较高。信不信由你,这就是我们推断声音和字母之间可能的排列所需要的一切。

把这个字母网格想象成一个图形。

CTC 一列接一列地研究每一种可能的组合:

A graph of every valid CTC alignment for the word ‘cat’

这个图表给了我们音频中字母的每一种可能排列。(实际上,CTC 使用了动态编程技术,使得这个过程比听起来更有效率)。

CTC 对每个可能比对的概率求和。完成后,CTC 会显示片段的最可能比对。

更正式地说,CTC 的目标是通过这个可能的比对图最大化路径的总得分。

对于我们的“hello”示例,有两种可能性很高的对齐方式:

原始排列会从合理走向荒谬。

请注意,我们的第二次比对,虽然在技术上是有效的,但甚至没有包括一个“H”!其他的对齐方式可能是“HHHHHELLOO”或“HEELLLLLOO ”,以及不太可能的“oooooooooooo”和“LLLLLOOOOO”。

为了生成其最终输出,CTC 删除了个重复的字母

…并移除特殊的空白令牌,即弯曲的 e

随着重复和弯曲的 e 被移除,我们最终得到:“hello”作为我们最有可能的输出。

这个输出可以与我们音频的文字记录进行比较。我们可以计算我们的模型的损失对我们的副本的地面真相。不错!

让我们回顾一下。

CTC 完成了两件重要的事情:

首先,通过在可能的比对中蜿蜒前进,并链接极有可能的单个字母猜测,我们最终得到了对没有任何比对数据的音频的转录本的有效预测

这也允许 CTC 处理音频中的变化,例如当说话者停留在字母“h”上时,因为 CTC 可以在校准中多次包括“h”。当我们删除重复的,我们仍然以“你好”结束。

第二,我们的特殊波形 e 具有双重功能,既可以作为垃圾帧的分隔符(例如字母之间可能出现的无声或喘息),也可以作为重复字母的分隔符。

这使得模型可以处理噪声帧,因为它对任何字母都没有信心。此外,它让模型生成像“hello”这样的单词,即使“l”是一个重复的字母,CTC 会删除重复的字母。

好吧,那么 WTF 是 ASG?

自动分段标准(ASG)在两个方面不同于 CTC:

  1. 没有特别的空白标签(歪歪 e )。
  2. ASG 避免某种类型的正常化。

就是这样。

让我们来看看每一个。

没有空白令牌会让事情变得更简单、更快速

Wav2Letter FAIR 报告称,在实践中,使用特殊的空白令牌来处理字母之间的垃圾音频帧“没有任何优势”。

所以 ASG 拿走了这个令牌。对于重复的字母,ASG 用“2”代替空白符号。在我们的示例中,“hello”将变成“hel2o”。

A CTC graph the acceptable sequences of letters for ‘CAT’

An ASG graph of the acceptable sequences of letters for ‘CAT’. Notice that there’s no special token for junk frames.

通过去除特殊记号,ASG 大大简化了算法在生成比对时必须搜索的图形。这可能会导致报告的一些性能提升。

ASG 允许声学模型学习字母之间的关系

CTC 期望其输入在帧级别被标准化。对于由我们的声学模型创建的链中的每个概率集,每个字母的概率用该中其他字母的概率来归一化。

对于 CTC 来说,每一帧都是自己的小世界。重要的是找到跨帧的字母到字母预测的最高总和。

A CTC graph for all valid alignments for ‘CAT’ across five frames. Nodes connect to each other, but the lines don’t indicate a greater or lesser probability of a given connection.

由于各种技术原因,ASG 不做帧归一化。规范化的细节没有它所暗示的那么重要:

ASG 赋予了 Wav2Letter 的声学模型通常为语言模型保留的功能:学习字母之间转换可能性的能力。

在现实语言中,某些字母组合比其他字母组合更有可能出现。这种字母组合的可能性称为“转换”,可以提高模型的准确性。

有些转变显然比其他转变更有可能。例如,在英语中,“TH”比“TS”更有可能出现(如“tsar”或“采采蝇”等晦涩难懂的词)。

ASG 包含自己的权重矩阵,用于模拟每个字母之间可能的转换。像任何其他标准权重矩阵一样,这些权重通过反向传播来训练。

使用这个矩阵,ASG 允许声学模型学习转换分数——一个字母跟随另一个字母的可能性——并将它们烘焙到我们用来为我们的字母到字母预测生成最可能对齐的图形的边缘。

An ASG graph for ‘CAT’ unfolded over five frames. Edges (lines) between graph nodes contain learned scores for transitions between letters.

FAIR 的结果表明,声学模型的这种增强提高了 CNN 的准确性。

由于声学模型包含对字母序列的有用理解,Wav2Letter 的解码器在对其最终抄本评分时,实际上使用了来自声学模型的过渡数据以及来自其真实语言模型的输出。

ASG connected to beam-search in Wav2Letter decoder

结论

我们总结一下。

像 Wav2Letter 这样的语音识别系统面临一个令人烦恼的问题:很少有关于声音和转录如何在时间上对齐的数据。

但是为了生成准确的逐字母预测,我们需要知道一个字母何时开始,另一个字母何时结束,因为我们的声学模型学习将声波与某些字母相关联。

传统上,深度学习实践者用一种叫做 CTC 的算法来解决这个问题。尽管 CTC 在许多情况下工作得很好,但它包含了一个额外的令牌,这会增加复杂性并可能降低速度。它还包括一种限制声学模型可以学习多少的标准化形式。

ASG 是一种特殊类型的损失函数,它通过移除 CTC 的额外标记来改进 CTC,并允许声学模型使用其自己的权重矩阵来学习字母之间的过渡。

如果你想了解更多关于 Wav2Letter 或 ASG 的信息,请参考下面的参考资料。

参考

A.Hannun,用 CTC 进行序列建模(2017),Distill.pub

A.Graves,S Fernández,F. Gomez,J. Schmidhuber,连接主义时间分类:用递归神经网络标记未分段序列数据 (2006),第 23 届机器学习国际会议论文集

R.Collobert,C. Puhrsch,G Synnaeve, Wav2Letter:一个基于 ConvNet 的端到端语音识别系统 (2016),脸书人工智能研究

动词 (verb 的缩写)Pratap,A. Hannun,Q. Xu,J. Cai,J. Kahn,G. Synnaeve,V. Liptchinsky,R. Collobert, Wav2Letter++:最快的开源语音识别系统 (2018),人工智能研究

名词(noun 的缩写)Zeghidour,Q. Xu,V. Liptchinsky,N. Usunier,G. Synnaeve,R. Collobert,全卷积语音识别 (2018)

动词 (verb 的缩写)Liptchinsky,G. Synnaeve,R. Collobert,基于字母的语音识别与门控神经网络 (2019),脸书人工智能研究

J.拉弗蒂,a .麦卡勒姆,f .佩雷拉,条件随机场:分割和标记序列数据的概率模型 (2001)

Python 中更好的热图和相关矩阵图

原文:https://towardsdatascience.com/better-heatmaps-and-correlation-matrix-plots-in-python-41445d0f2bec?source=collection_archive---------1-----------------------

[更新 2020–04–12:下面描述的代码现在以 pip 包的形式提供—https://pypi.org/project/heatmapz/。这里还有一个 Google Colab 笔记本,你可以在那里看到几个例子,并且可以玩玩这个库

相关矩阵图

您已经知道,如果您有一个包含许多列的数据集,快速检查列间相关性的一个好方法是将相关性矩阵可视化为热图。

但是简单的热图是最好的方法吗?

为了便于说明,我将使用汽车数据集,其中包含许多汽车的各种特征。你也可以在这里找到带有标题列的数据的干净版本

让我们从制作数据集的关联矩阵热图开始。

太好了!绿色代表积极,红色代表消极。颜色越强,相关幅度越大。现在看上面的图表,思考以下问题:

  • 当你看图表时,你的眼睛首先跳到哪里?
  • 最强和最弱的相关对是什么(除了主对角线)?
  • 价格最相关的三个变量是什么?

如果你和大多数人一样,你会发现很难将色阶和数字对应起来,反之亦然。

区分积极和消极很容易,区分 0 和 1 也很容易。但是第二个问题呢?找到最高的负相关性和正相关性意味着找到最强的红色和绿色。为此,我需要仔细扫描整个网格。试着再回答一遍,注意你的眼睛是如何在剧情中跳跃的,有时还会去看图例。

现在考虑下面的情节:

除了颜色,我们还在热图中添加了尺寸参数。每个方块的大小对应于它所代表的相关性的大小,也就是说

(C1,c2) ~ abs(corr(c1,c2))

现在试着用后一个情节来回答问题。注意弱相关性是如何在视觉上消失的,你的眼睛会立即被吸引到高相关性的区域。还要注意,现在比较负值和正值(浅红色和浅绿色)更容易了,我们还可以比较相距更远的值。

如果我们在绘制数量级,将它们与代表物体的大小联系起来比与它的颜色联系起来要自然得多。这就是为什么在条形图上你会用高度来显示度量,用颜色来显示类别,而不是相反。

离散联合分布

让我们看看数据集中的汽车是如何根据马力和传动系统布局分布的。也就是说,我们希望将下表可视化

考虑以下两种方法

在第二个版本中,我们使用正方形大小来显示计数,这使得很容易确定哪个组是最大/最小的。它也给出了一些关于边缘分布的直觉,完全不需要参考颜色图例。

太好了。那么我是如何制作这些情节的呢?

为了制作一个常规的热图,我们简单地使用了 Seaborn 热图函数,并添加了一些额外的样式。

对于第二种,使用 Matplotlib 或 Seaborn 没有简单的方法。我们可以使用 biokit 的 corrplot ,但是它只对相关性有帮助,对二维分布不是很有用。

在 Matplotlib 中,构建一个健壮的参数化函数来制作带有大小标记的热图是一个很好的练习,所以我将一步一步地向您展示如何做。

我们首先使用一个简单的散点图,用正方形作为标记。然后,我们将修复一些问题,添加颜色和大小作为参数,使其对各种类型的输入更加通用和健壮,最后制作一个包装函数 corrplot ,它接受 DataFrame.corr 方法的结果并绘制一个相关矩阵,为更通用的 heatmap 函数提供所有必要的参数。

这只是一个散点图

如果我们想在由两个分类轴组成的网格上绘制元素,我们可以使用散点图。

看来我们有所发现了。但我说这只是一个散点图,在前面的代码片段中发生了很多事情。

由于散点图要求 xy 是数字数组,我们需要将列名映射到数字。由于我们希望轴刻度显示列名而不是那些数字,我们需要设置自定义的刻度刻度标签。最后是加载数据集的代码,选择列的子集,计算所有的相关性,融化数据框(与创建数据透视表相反)并将其列提供给我们的热图函数。

你注意到我们的正方形被放置在网格线交叉的地方,而不是在它们的单元格中居中。为了将方块移动到单元格中心,我们实际上将移动网格。为了移动网格,我们实际上将关闭主要的网格线,并将次要的网格线设置为正好在轴刻度之间。

那更好。但是现在左侧和底部看起来被裁剪了。这是因为我们的轴下限被设置为 0。我们将通过将两个轴的下限设置为-0.5 来解决这个问题。记住,我们的点是以整数坐标显示的,所以网格线是 0.5 坐标。

给它点颜色

现在有趣的部分来了。我们需要将相关系数的可能值范围 [-1,1] 映射到调色板。我们将使用发散调色板,从-1 的红色一直到 1 的绿色。看着Seaborncolorpalettes,似乎我们会做得很好

sns.palplot(sns.diverging_palette(220, 20, n=7))

但是,让我们首先翻转颜色的顺序,通过在红色和绿色之间添加更多的步骤使其更加平滑:

palette = sns.diverging_palette(20, 220, n=256)

Seaborn 调色板只是颜色组件的数组,因此为了将相关值映射到适当的颜色,我们需要最终将其映射到调色板数组中的索引。就是一个区间到另一个区间的简单映射:[-1,1]【0,1】(0,255)。更准确地说,这是该映射将采取的一系列步骤:

正是我们想要的。现在让我们在图表的右侧添加一个颜色条。我们将使用 GridSpec 建立一个 1 行和 n 列的绘图网格。然后,我们将使用该图最右边的列来显示颜色条,其余的列来显示热图。

有多种方法来显示一个颜色条,这里我们将使用一个非常密集的条形图来欺骗我们的眼睛。我们将绘制 n_colors 水平条,每一条都用调色板中各自的颜色来着色。

我们有自己的颜色条。

我们快完成了。现在,我们应该翻转垂直轴,这样我们就可以在主对角线上显示每个变量与其自身的相关性,使正方形稍微大一点,并使背景稍微亮一点,这样 0 附近的值就更容易看到。

但是让我们首先使整个代码更有用。

更多参数!

如果我们能让函数不仅仅接受一个相关矩阵,那就太好了。为此,我们将进行以下更改:

  • 能够将 color_min,color_maxsize_min,size_max 作为参数传递,以便我们可以将不同于[-1,1]的范围映射到颜色和大小。这将使我们能够在相关性之外使用热图
  • 如果没有指定调色板,使用连续调色板;如果没有提供颜色矢量,使用单一颜色
  • 如果没有提供大小向量,则使用恒定大小。避免将最小值映射到 0 大小。
  • 使 xy 成为唯一必需的参数,并将 size、color、size_scale、size_range、color_range、palette、marker 作为 kwargs 传递。为每个参数提供合理的默认值
  • 使用列表理解代替 pandas 应用map 方法,这样我们可以传递任何类型的数组作为 x,y,color,size 而不仅仅是 pandas。系列
  • 将任何其他 kwargs 传递给 pyplot.scatterplot 函数
  • 创建一个包装函数 corrplot ,它接受一个 corr() dataframe,熔化它,调用带有红绿发散调色板的热图,并将大小/颜色最小-最大值设置为[-1,1]

这有相当多的样板文件要一步一步地介绍,所以下面是完成后的样子。也可以在这个 Kaggle 内核中查看。

最后

现在我们已经有了 corrplotheatmap 函数,为了创建大小为正方形的关联图,就像本文开头的那样,我们只需做以下事情:

为了好玩,让我们制作一个图表,显示发动机功率在我们的数据集中的汽车品牌之间是如何分布的:

这就结束了关于改进热图可视化的这个简单想法的故事。

好奇更多?

有意见或问题吗?我在 @drazenxyz 发关于数据科学和构建软件产品的推文,所以请关注我,在那里见。

我还在 Blogboard Journal 上总结了这个行业的经验,你可以在那里找到一些文章,比如《营销优化的数据科学》Airbnb、Lyft、Doordash 的案例研究:

更好的目标营销:超越明显的营销组合模式

原文:https://towardsdatascience.com/better-target-marketing-going-beyond-the-obvious-with-marketing-mix-models-140d70f6844c?source=collection_archive---------29-----------------------

现实世界中的数据科学

数据科学如何创造更精确的跨渠道营销

Photo by Anastase Maragos on Unsplash

我最近开始和一个新客户合作。他们在营销工作中非常努力地进行测试和学习。他们积累了许多经验教训,可以分享。

其中一个教训是,数字广告放大了他们的无地址直邮广告(即地理定位直邮广告)的结果。

【关于直邮和数字之间的共生关系,已经有很多研究。例如, 《加拿大邮报》发表了一项研究 显示,先直接邮寄,再进行广告前宣传,可以提高 3%的积极性。尽管这种提升听起来很小,但它确实推动了行为上有意义的变化。】

使用数据科学超越表面现象

基于这一认识,他们的分析团队建议市场营销应该始终将他们的无地址邮件活动与数字广告结合起来。虽然这个结论似乎合乎逻辑,但它只是触及了更丰富洞察力的表面。

如果营销人员提出正确的问题,数据科学可以帮助他们得出更明智的结论。

我一直记得我从超级鼓舞人心的莱斯利·厄姆那里学到的一个技巧——5 个“为什么”。她告诉我们要找到新的想法,当有人回答一个问题时,要问 5 次“为什么”。它挖掘了看似显而易见的东西。每当我做分析的时候,我都是这么做的。

因此,如果我们知道数字广告放大了地理定位邮件的结果,下一个为什么可以探索宇宙中的细分市场——特定的地理区域在那里工作得更好还是更差?广告的时机有影响吗?重定目标是否能进一步提升放大效果?

但是怎么做呢?下面是我如何使用营销组合分析来帮助客户回答这些为什么。

营销组合分析的一个例子——数据科学如何使定位更有效

背景:我们为什么要做这个分析?

这个客户不直接向消费者销售。他们依靠其他专业人士向个人消费者销售。在大多数企业对企业(B2B)环境中,他们有销售代表定期与这些专业人士会面。销售代表在销售/营销组合中起着核心作用。营销人员用一些常见的方式来补充这些销售代表——早餐会、网络研讨会、电子邮件、杂志广告等等。

这种销售模式有 3 个潜在问题:

  • 让销售代表走遍全国与每个专业人员会面是非常昂贵的。
  • 随着我们忙碌的生活,安排销售会议变得越来越困难。
  • 营销部门分析了每种策略的投资回报率,但希望他们的努力更有针对性。

与我的新客户相似,他们知道不同的营销活动可以放大更昂贵的销售代表活动的结果。但是,他们不只是在这些活动上分层,而是希望更聪明地知道他们想在哪些活动上分层。这就是我和我的团队进行营销组合分析的地方。

过程:我们做了什么分析?

营销组合分析是在 r。

我们假设销售漏斗不同阶段的专业人士对营销和销售活动的反应可能不同。例如,新进入该行业的人可能需要更多的帮助,而熟悉产品的人可能需要更多的自助服务选项。所以我们为每个阶段建立了一个独立的回归模型。

我们研究了过去一年的营销活动如何影响这些专业人士的行为。我们感兴趣的是将合适的专业人员与最有效的营销活动组合配对。

这个模型后来变成了一个“计算器”。媒体团队用它来确定针对特定群体的活动是否值得投资。

虽然我不能透露所有的秘密,但我将分享我们从分析中获得的一些见解以及它们是如何有用的。

洞察力#1:一些策略的组合可以产生指数效应

模型的主要输出是专业人员根据营销和销售活动采取行动的可能性。这是我们编制的图表之一。它显示了某一部分专业人士“转换”的可能性,即从销售漏斗的一个阶段进入下一个阶段,通过针对他们的营销策略和销售活动的组合进行分组。这都是与没有针对他们的活动的基础相比较的。

对我们来说,看到前两个小节的巨大差异是令人惊讶的。顶部转换策略组合和第二个之间的区别是一组电子邮件。换句话说,如果我们针对一位专业人士,采用不包括电子邮件在内的多种策略,他们转向下一阶段的可能性是普通人的 163 倍。如果我们也通过电子邮件系列瞄准这些专业人士,他们转化的可能性会增加 390 倍!然而,电子邮件本身是图表底部的一小部分因素之一。组合的力量!

洞察力#2:无针对性的策略会对针对性产生很大的影响

数据营销人员必须面对的一个现实是,存在无法锁定的大众影响力。例如,在 B2B 中,我们可能会投放非个性化或无针对性的杂志广告。在 B2C(企业对消费者)中,我们可能会有电视、广播、广告牌等。不是一对一的。

当我们看大众媒体的影响时,我们可以看到,接触大众媒体较多的专业人士较少受到针对性战术的影响。这意味着,如果我们知道我们在某些地区或行业投放了大量的大众媒体,我们可以减少更多的个性化营销策略,尤其是成本更高的营销策略,如早餐会。

见解 3:某些行业不能便宜行事

我们了解到的另一件事是,某些行业对销售代表以外的任何人都不敏感。这意味着优先考虑这些行业的专业销售代表会产生更大的影响。同样,这意味着我们可以通过优先考虑更具可扩展性和更便宜的营销策略来节省资金,这些策略适用于接受目标营销的行业中的专业人士。

我希望这能启发你进一步思考,当数据分析突破了最明显的观察界限时,它是如何对营销人员更有帮助的。下次当你查看分析结果时,问 5 个“为什么”,看看你是否能找到一个更聪明的问题来问你的数据模型。

押注英格兰超级联赛

原文:https://towardsdatascience.com/betting-on-the-english-premier-league-making-money-with-machine-learning-fb6938760c64?source=collection_archive---------7-----------------------

用机器学习赚钱

足球是世界上最受欢迎的运动。全球数以百万计的人收看电视,为分数、结果和冠军进行庆祝、痛苦和打赌。专家认为,全世界的体育博彩产业价值高达 1 万亿美元。由于足球比赛的结果关系到如此多的金钱,能够利用过去的数据准确预测一支球队的结果是一个诱人的前景。利用世界上最赚钱的联赛——英格兰超级联赛过去的结果,让我们看看我们是否可以建立一个模型,正确预测足够的结果,以击败博彩公司,并在整个博彩季节中记录利润。

具体来说,这意味着什么?

  1. 找到、清理和组织一个(或三个)数据集。
  2. 使用个人领域知识产生几个预测特征。
  3. 训练、调整和测试高精度分类器。
  4. 使用最佳模型,使用真实赔率对一个赛季的足球比赛进行下注。
  5. 利润?也许,我们会看到!

1。查找数据和清理

首先,我们需要找到一些数据。粗略的谷歌搜索会导向 kaggle.com,一个充满了(相对)干净数据集的美妙的数据科学资源。由山姆·劳森编制的 1993-2018 年 EPL 结果似乎正是我们所需要的。英超历史上的每一场比赛都记录了主队、客场、全职进球(主客场)、结果和赛季,我们应该能够找出一些对预测结果有用的特征。我们将下载 CSV 文件,并使用 pandas 的 read_csv 函数将数据加载到 pandas 数据帧中。结果如下:

EPL Results 1993–2018 — First 10 rows. Date has been pushed to a datetime object for ease of indexing.

CSV 文件可以很好地加载到数据帧中,并且没有丢失值。然而,因为我们感兴趣的是能够预测某个特定的队是否会赢得、输掉或打平下一场比赛(而不仅仅是比赛的结果),我们需要改变数据帧的格式。具体来说,我们需要创建四个新列,一个“团队”列包含我们有兴趣下注的团队,一个“对手”列包含他们正在比赛的团队,“主场/客场”列表示“团队”列中的团队正在比赛,一个“积分”列表示感兴趣的团队是赢了、输了还是平了(这将是我们的目标变量)。要做到这一点,必须复制数据帧并将两者按行连接在一起。每个游戏将被表示两次,但是“队”和“对手”列中的值将被颠倒。

事实证明,填写“团队”和“对手”栏相当简单。在原始数据帧中,我们将“主场球队”列中的所有球队设置为新的“球队”列,将“客场球队”列中的所有球队设置为新的“对手”列。对复制的数据帧进行相反的操作,瞧!每个匹配现在被表示两次。

填写“主场/客场”一栏也相对简单。通过使用布尔索引,我们可以提取在主场比赛的球队的每个实例,并使用它来更新“HomeAway”列。计算“结果”列稍微复杂一些,但是通过一个循环和一些链式条件逻辑,我们可以完成它。如果您对实现这一点所需的代码感兴趣,请随时查看我的 GitHub 获取完整的脚本!

2。产生预测特征

主场还是客场

潜在预测兴趣的第一个特征已经被创建。一个球队打主场还是客场,应该对一个球队的成绩有影响。这几乎不需要太多的领域知识,因为这是所有团队运动中重复的格言。在主场比赛有一种不言而喻的优势,对于最好的球队来说,这种优势尤其明显。然而,为了证实我们的直觉,让我们看看球队在两个不同的赛季中是否在主场比在客场获得更多的积分。为此,我们将迭代一个球队列表,提取该赛季所有主客场比赛中收集的平均分数,并绘制每个球队两个平均分数的直方图。

上面的情节不言自明。两个赛季的每支球队在主场的得分都比客场多。因此,主场或客场似乎将是一个预测特征。

面对面获胜百分比

我想到的第二个预测功能是与每个对手的正面交锋的胜率。利用个人领域的知识,我意识到在英超联赛中有几场一边倒的竞争。比如维根竞技和曼联,英超交手过 16 次。曼联以 50 比 5 的总比分赢得了其中的 15 场比赛。这是曼联 94%的直接胜率。如果他们再次比赛,我认为维根会输。由于抽签的原因,计算这个百分比有点复杂。仅仅因为曼联有 94%的胜率,并不一定意味着维冈有 6%的胜率(尽管在这种情况下他们实际上有)。因此,我们必须单独计算每支球队,而不仅仅是一系列的对等比赛。

为了构造这个特性,我们必须用一个外部和一个内部 for 循环遍历两个列表。外部循环将包括每个团队,内部循环将包括每个对手。在内部循环的每一次完整迭代中构建一个从头到尾成功百分比的字典允许我们将字典映射到连接的数据帧中的一个新列。同样,如果你对代码感兴趣,请查看我的 GitHub

空前的胜率

直觉上,这似乎也是预测比赛的一个有用的特性。特别是在加强顶级球队和只参加过几次英超联赛的球队之间的差距方面。与上面的方式非常相似,我们将不得不迭代所有团队的列表,并构建一个包含每个团队的历史胜率的字典。将此映射到“对手”列,我们将得到一个新列,其中显示了我们感兴趣的团队所对阵的每个对手的历史胜率。

鉴于空前胜率和直接胜率之间的相似性,我们可能有理由担心两者之间的共线性。如果这两个特征高度相关,我们可以丢弃其中一个特征,而不会丢失任何由我们的模型解释的方差。此外,越简单越好!为了检查这两个变量是否有高度的相关性,我们将把它们彼此对照,并检查 r 的值。

下面的情节很直观。当球队与胜率较低的对手比赛时,他们的胜率会上升。然而,这并不是一个完美的相关性。当我们忽略四支历史胜率超过 50%的球队时,分数相差很大。因此,在这种情况下,我们不应该担心共线性,并且可以放心地在我们的模型中包含这两个特性。

R value of -0.51

连胜

这是一个旨在将心态和团队信心融入模型的特性。我们可能会认为,当一支球队赢得一场比赛时,他们赢得下一场比赛的几率会增加,因为这支球队处于“良好的状态”。当然,这也可能是纯粹的观察或确认偏差。特别是,这可能与一直被否定的NBA 热手假说有关。实现这个特性应该不会太难。

与上面的方式非常相似,我们必须遍历所有球队的列表,取出他们所有比赛的一部分,更新“连胜”列,并将所有更新的部分连接在一起。使用内部 for 循环和 dataframe 方法。iterrows()将允许我们初始化 streak 计数器,检查我们团队的结果,将该值附加到一个列表中,并更新计数器。在遍历了切片中的每一行之后,我们将得到一个列表,其中包含我们感兴趣的团队的连胜记录(如果团队输了或打平,则重置为 0)。该列表可以直接转换为“条纹”列,因为它具有相同的长度。

让我们也做一个快速检查,看看这个特性是否有任何数量的预测强度。在下面的图中,我观察了 8 支球队以及他们在连胜期间和所有时间里各自的胜率。第一张图显示了英超历史上最成功的 4 支球队,第二张图显示了 4 支不太成功的球队。我们注意到的是连胜的次数可能对胜率没有任何影响。也就是说,一个球队在 3 连胜之后不会比 5 连胜之后赢得更多的比赛。然而,与他们的历史百分比相比,大多数球队在连胜期间的胜率更高。这一特征看起来具有一定的预测性。

去年对手的联赛成绩

在 38 场比赛(1 个英超赛季)的过程中,每支球队在联赛中的成绩应该能够很好地表明他们的实力。这可能会在几个赛季中发生显著变化,但不太可能在一个赛季到下一个赛季之间发生很大变化。因此,如果我们有一个团队去年完成的信息,我们可能期望从信息中获得一些预测能力。不幸的是,我们的原始数据源没有关于联赛排名的信息,所以我们必须去搜索更多的数据。用户再次提交 Kaggle 进行救援,这是一个包含我们需要的所有信息的数据集。

由于符号和季节可用性方面的一些差异,从这个来源获取信息并将其加入到我们模型的功能中涉及到相当多的数据管理。团队名称不匹配,年份注释不同等等。幸运的是,Python 内置的字符串模块使得这些改变非常简单。如果你对发生的所有操作感兴趣,请查看 GitHub

联盟排名数据还包括其他潜在有用的信息,如每场比赛的进球,每场比赛的射门和其他统计数据。为了提高模型性能,这些可以作为特征添加。现在,我们将它们放在一边,开始建模!

3。训练/测试/调整高精度分类器

多项逻辑回归

虽然不总是像一些更新更先进的监督学习算法那样有趣,但回归模型仍然有很多优点。在将比赛分类为多个离散目标之一(赢、平或输)的情况下,逻辑回归是一个很好的起点。至少,它会给我们一个基线来与更复杂的模型进行比较。

因为我们的用例试图预测一个赛季的比赛,测试和训练集将被手动分配。从 1994-1995 年到 2015-16 年,每一季都会有训练集。测试集将是一个单一的赛季,即 2016-17 英超赛季。同样,模型中的 5 个特征是头对头胜率(对给定对手)、主场或客场、对手去年的联赛成绩、对手的历史胜率和连胜。目标是一个有三类的变量,赢、输或平。

将模型拟合到训练集,并对优化的 C (=0.1)运行网格搜索交叉验证,得到 0.595 的模型分数。因为这不是很清楚,我们可以查看分类报告进行更深入的分析。

Classification Report for Multinomial Logistic Regression

正如我们在上面的报告中看到的,赢和输有相当的精确度和回忆,但平局似乎更难预测。当考虑这个项目的总体目标时,我们必须考虑什么样的分类元素是最重要的。因为我们希望使用我们的模型来下注,所以我们希望相对确定模型预测的结果是正确的。因此,为了实现最佳性能,我们需要针对高精度进行优化,并且必然会忘记召回。

也就是说,我们的第一个模型精度相当差。或许,如果我们在数量上下注,我们就可以在输赢上赚钱,但精确度的提高会有很大帮助。因此,随机森林分类器似乎是一个很好的下一步。然而,在不涉及太多细节的情况下,随机森林分类器的表现比逻辑回归模型差。对于增加的复杂性来说,这是一个糟糕的折衷。还尝试了具有类似结果的支持向量机。由于它的表现最好,我们将坚持使用逻辑回归,看看我们是否能以另一种方式提高精度。

二元逻辑回归

回顾来自多项逻辑回归模型的分类报告,我们注意到抽奖相对难以预测。如果我们可以将两个类别合并为一个,改变模型来解决二分类问题,并提高精度,我们就可以增加我们的潜在利润。将平局类别合并为输或赢是很简单的,我们只需要决定我们最终想要赌哪个结果。相当随意地,我们将选择合并损失和平局,留下胜利作为单一类别(我们将打赌的结果)。使用上面详述的相同程序,训练和评估新模型导致下面的分类报告。

Classification report for two class logistic regression

正如所料,现在无用的损失/平局类别具有相当高的精确度和召回率。对我们的用例来说,更重要的是,预测获胜的算法精度已经提高到 0.67。这代表了与具有多项式分类的原始模型中的 0.60 相比的相当大的改进。这种精度的提高是值得的,代价是复杂性的损失。如果我们的模型预测一个队将赢得一场比赛是正确的(几乎)7/10 倍,那么作为一个投注者,我们可以只赌赢,并保证在数量上获利。再说一遍,回忆并不重要。当我们的模型预测成功时,我们希望相对确信它预测正确。

由于预测胜率的模型精度为 0.67,我们可以谨慎乐观地认为,当我们对整个赛季的游戏价值下注时,我们会赚钱。让我们看看我们是否能把这种信心直接带到银行!

4.模拟赌注

获得赔率

首先,我们需要博彩公司为我们的测试集(2016/17 英超赛季)中的每场比赛提供的赔率。谢天谢地,football-data.co.uk 为我们提供了保障。他们从数百个不同的来源收集和维护每个英超赛季每场比赛的投注赔率的大规模数据集。这是一个令人难以置信的资源,是专门为练习和通知投注策略。完美。

理想情况下,我们会为我们的模型预测会赢的每场比赛找到最佳的个人赔率,并只向该公司下注。然而,由于数据集中列出了如此多不同的公司和赔率,这是一项非常复杂的任务。相反,我们将使用 Bet365.com 网站提供的赔率,该网站是世界领先的在线赌博公司之一。在不涉及太多细节的情况下,我们将拿出 Bet365 以十进制格式提供的英超每支球队的全职比赛结果的赔率。每次我们的模型预测一个给定的团队获胜,我们将模拟一个 100 美元的赌注。如果我们的模型预测失败/平局,我们将放弃下注。

利润或损失

为了计算正确预测和下注情况下的利润,我们采用特定结果的十进制赔率,乘以我们的 100 美元赌注,然后减去纯利润的原始赌注。例如,如果主队获胜的给定赔率为 1.65,并且我们的模型正确预测了结果,我们将获得 165 美元。其中 100 美元是原始赌注,因此我们在这个赌注上的利润是 65 美元。如果我们赌输了(也就是说我们的模型预测主队会赢,但是他们没有赢),我们就输了 100 美元。在这种投注策略和利润评估下,让我们对 2016/17 赛季英超联赛的所有 20 支球队进行模拟投注。

我们总共下了 191 次 100 美元的赌注。这是一笔 19100 美元的财政支出。没有小的变化。模特表现如何?我们总共拿走了 20,124 美元。这是 1024 美元的纯利润。在完成一个英超赛季的 9 个月里,我们的投资产生了 5%的回报!请参见下表,了解按团队划分的下注和盈利/亏损明细。

Total bets placed and profit/loss recorded for every team in the EPL 2016/17

5.结论(和利润?)

所以我们的模型导致了 5%的模拟投资回报率!这是否意味着我们将采取我们的模式,去改变体育赌博的世界?大概不会。预测足球时,不可预测性实在太多了。也许 2016/17 赛季是有记录以来最容易预测的赛季之一?或者也许随着更多的电视收入流入这项运动,过去的结果在预测未来的比赛时将不再有用。然而,有了足够的资本投入,这种赌博策略和模式似乎会取得一些成功。

此外,进一步改善下注策略可能会带来更多收益。例如,在我们的模拟赛季中,我们在曼联身上下注接近 500 美元。领域知识告诉我们,曼联正处于历史的低谷,因此可能不会像历史预测的那样表现良好。就曼联而言,调整将他们的结果归类为胜利的概率阈值可以增加我们预测的精确度。

如果没有别的,这提供了一个有趣的案例研究,使用领域知识来构建一个相对简单和可解释的模型,该模型可以在一个狭窄定义的用例中表现很好。

如果您有任何问题或意见,请随时给我发消息;我很想听听!最后一次,检查 GitHub 如果你有兴趣阅读或重用我的任何代码。感谢阅读!

当心!金融中的数据科学技术不会让你做任何欺诈

原文:https://towardsdatascience.com/beware-data-science-technology-in-finance-will-not-let-you-do-any-fraud-56a1f183dbf2?source=collection_archive---------18-----------------------

你在生活中有没有做过诈骗的事情?我知道;-).请注意,现在在数据科学的帮助下,你的欺诈行为可以被发现。是啊!您没有看错,数据科学现在正在帮助金融部门进行欺诈检测。除此之外,数据科学在金融领域还做了什么?激动吗?还等什么,探索篇——

金融从来都是关于数据的。事实上,数据科学和金融是相辅相成的。甚至在数据科学这个术语被创造出来之前,金融界就已经在使用它了。

数据科学在金融行业中的应用

金融是数据的枢纽。金融机构是数据分析的最早用户和先驱之一。数据科学广泛应用于风险分析、客户管理、欺诈检测和算法交易等领域。

1.风险分析

风险分析是金融中数据科学和商业智能的关键领域之一。借助风险分析和管理,公司能够做出战略决策,提高公司的可信度和安全性。由于风险管理衡量损失的频率,并将其乘以损失的严重性,因此数据构成了风险管理的核心。风险管理是一个跨学科的领域,具备 数学、统计学和解决问题 的知识是必不可少的。虽然传统的结构化数据总是可以容纳在电子表格中,但更高级形式的数据是不结构化的。这种形式的大数据为机构提供了各种机会。

公司面临各种形式的风险。这些风险来源于竞争对手、信用、市场等。管理风险的主要步骤是识别风险、监控风险和确定风险的优先级。有大量可用的数据,如客户信息、金融交易。因此,机构在这种类型的数据上进行训练,以增加风险评分模型并优化其成本。风险管理的另一个重要方面是核实客户的信誉。为了分析信誉度,公司雇佣了数据科学家,他们使用 机器学习算法 来分析客户的交易。

2.实时分析

在传统分析中,数据处理是以批处理的形式进行的。也就是说,数据处理本质上只是历史的,而不是实时的。这给需要实时数据以了解当前情况的各种行业带来了问题。然而,随着技术的进步和动态数据管道的发展,现在可以以最小的延迟来访问数据。随着数据科学在金融领域的应用,机构能够跟踪交易、信用评分和其他金融属性,而没有任何延迟问题。

你查过 数据科学是如何改造教育领域的

3.消费者分析

消费者个性化是金融机构的主要业务。在实时分析的帮助下,数据科学家能够从消费者行为中获得洞察力,并能够做出适当的商业决策。像保险公司这样的金融机构利用消费者分析来衡量客户的终身价值,增加他们的交叉销售,以及减少零以下客户,以优化损失。

4.客户数据管理

金融机构需要数据。事实上,大数据已经彻底改变了金融机构的运作方式。数据的数量和种类是通过社交媒体和大量交易贡献的。

数据以两种形式出现-

  • 结构数据
  • 非结构化数据

虽然结构化数据更容易处理,但非结构化数据会带来很多问题。这种非结构化的数据可以用几个 NoSQL 工具来处理,可以借助MapReduce来处理。

商业智能是大数据最重要的方面。行业利用机器学习来产生关于客户的见解并提取商业智能。人工智能中有各种工具,如自然语言处理、数据挖掘和文本分析,可以从数据中产生有意义的见解。此外,机器学习算法通过对客户数据的全面分析来分析金融趋势和市场价值的变化。

通过Data flair 大数据教程系列 了解大数据的一切

5.提供个性化服务

金融机构负责向客户提供个性化服务。金融机构采用各种技术来分析客户信息,并对他们的互动产生洞察力。此外,金融机构正依靠基于语音识别和自然语言处理的软件来为其用户提供更好的交互性。

利用用户反馈的数据,金融机构能够对其客户需求进行可操作的洞察,从而增加利润。这将有助于这些机构优化其战略,并为其客户提供更好的服务。

6.欺诈检测

欺诈是金融机构的一大担忧。欺诈的危险随着交易数量的增加而增加。然而,随着大数据和分析工具的增长,金融机构现在可以跟踪欺诈行为。金融机构中最常见的欺诈之一是信用卡欺诈。这种类型欺诈的检测是由于算法的改进,提高了异常检测的准确性。此外,这些检测会提醒公司金融购买中的异常情况,促使他们冻结帐户,以最大限度地减少损失。

各种机器学习工具 也可以识别交易数据中的异常模式,并提醒金融机构对其进行进一步调查。银行还必须应对其他与保险相关的欺诈。使用几种聚类算法,公司能够分离和聚类看起来非常可疑的数据模式。

7.算法交易

算法交易是金融机构最重要的部分。在算法交易中,有复杂的数学公式和闪电般的计算帮助金融公司设计新的交易策略。大数据对算法交易产生了巨大影响,数据科学已成为其最重要的特征。

算法交易中存在的数据由大量数据流组成,并涉及测量和描述底层数据流的模型。分析引擎的目的是通过更好地理解海量数据集来预测未来市场。

摘要

数据科学的使用主要是在风险管理和分析领域。公司使用数据科学客户组合管理通过商业智能工具分析数据趋势。数据科学也被用于算法交易,机器学习在预测未来市场方面发挥着关键作用。

霍普,你喜欢读这篇文章。以下是一些你必须阅读文章

医疗数据科学

银行业中的数据科学

令人困惑的大脑

原文:https://towardsdatascience.com/bewildering-brain-332d5192e95b?source=collection_archive---------22-----------------------

像鲍勃·迪伦那样用机器学习写歌。

由,就在孩子死去之前,
每个人都得来看她的手,
但有太多的哼,
父亲,当我可以告诉你下来…

他的诗句不是由诗人或音乐家写的。它们是由经过鲍勃·迪伦完整歌词训练的神经网络编写的。
机器人能创造艺术吗?我把这个问题留给哲学家。在这个小实验中,我只会尝试使用机器学习尽可能准确地模仿迪伦的歌曲风格。

罗伯特·艾伦·齐默曼,又名鲍勃·迪伦,被许多人视为偶像和美国音乐无与伦比的堡垒,可以说是美国有史以来最受欢迎的音乐家。职业生涯跨越 6(!!)几十年和 38 张录音室专辑,很容易看出原因。哦,别忘了他的唱片销量已经超过 1 亿张,这使他成为有史以来最畅销的音乐艺术家之一。然而,今天让我们聚集在这里的是他的歌词。根据维基百科,他的歌词融合了广泛的政治、社会、哲学和文学影响,挑战流行音乐惯例,迎合新兴的反主流文化。
听起来很有趣吧?

这种特殊的背景和他独特的风格为他赢得了全世界的认可和无数的奖项。最负盛名的是 2016 年诺贝尔文学奖“因为在伟大的美国歌曲传统中创造了新的诗歌表达方式”。

他的签名风格是不会错的。

或者是?

He not busy being born is busy dying”. It’s Alright, Ma (I’m Only Bleeding) is one of his most celebrated masterpieces.

技术

为了这个小实验,我基于一个处理神经网络的框架。

值得一提的是,作为环境,我使用了 Jupyter NotebookPycharm ,所有的东西都是用 Python 3.6 开发的。

数据库中包括了从首张同名专辑到 2012 年的《暴风雨》的所有歌曲。我从马特·穆赫兰的网站上拿到了这个文件。这节省了我很多时间,所以谢谢马特!

我特别使用了两种算法/技术:马尔可夫链RNNs(递归神经网络)。我建议比较和分析哪一个输出更好的结果,以及它们的表现如何。

马尔可夫链

M arkov 链是随机过程,其主要特征是一个事件的概率完全依赖于前一个事件。这种缺乏记忆的特性被称为马尔科夫特性。** 听起来很复杂,但是超级简单易懂。**

如果我们把下雨理解为马尔可夫过程,下雨的概率只取决于昨天是否下雨。

有两种状态:下雨或不下雨。

如果我们在一个晴天,第二天下雨的概率是 40%,所以第二天有 60%的机会是晴天。

如果下雨,第二天有 30%的可能性会再下雨,70%的可能性会是晴天。

就这样,日复一日,我们可以只根据前一天的情况来计算下雨的概率:不管是不是雨季,不管全球变暖,也不管地理区域。

现在回到主题,我们可以将文本理解为一个马尔可夫过程,其中每个单词出现的概率只取决于前一个单词是哪个写的。这样,“预测文本”就成为可能。

为了将马尔科夫应用到迪伦的歌词中,我参考了汉斯·卡明的作品,他在那里预测了罗辑的歌词。这个想法是创建一个代表英语的二元马尔可夫链。更具体地,创建连续单词的元组字典。因为我们使用的是二元模型,而不是单个单词(unigrams),所以我们在预测中获得了更好的精度,最重要的是,模型创建的歌词具有更好的可读性。这意味着,句子的下一个单词是用前两个单词而不是单个最后一个单词来预测的。****

使用熊猫系列,我遍历了数据库中的所有歌词,并分别为行首、行尾和换行符(\n): "<START>""<END>""<N>"使用了特殊的标签。

为了进行预测,我们从字典中的键(None, "<START>")(必须是链中的第一个链接)开始,然后我们以随机的方式采样——但要考虑分布——列表中与该键相关的一个单词;我们将键移向我们刚刚采样的单词。我们继续这个过程,直到我们到达"<END>".

以下是该算法吐出的一些我最喜欢的短语:

你这个天使,你,你让我在你的羽翼下,你走进我放铅笔的房间的样子。

我一定会去大北方森林,作为临别礼物。夏天的白天,夏天的夜晚都过去了,我知道我只是没有体温?

我去告诉你,宝贝,昨天深夜我梦见风中泥土上的铃铛。我走向更高层次的忏悔,

我走进杯子上面一个瞎子的嘴里,他开始想我可以,我不能放开我的羔羊的心

我如何再次徘徊在我的膝盖上,不需要一个我遇见的女人,把希望放在她身上不要给我,宝贝,我会在这电话线里做任何事。

我怎么会生病。然后他们给他们带来衣服!呜-呼!我现在还不知道,你要找的不是我,宝贝。

来吧,看看你的窗台。我的公路鞋还要多久才会消失?

对任何路过的人来说,再也没有信了,没有!除非你从荒凉街寄出。

很明显,这些歌词尽管有着明显的丹麦风格,却感觉像是现实的剪影。就像他的作品的复制粘贴,不同诗句的拼贴创造了一首新歌。许多短语与鲍勃写的相同。
这是意料之中的,因为当我们使用二元模型搜索更高的可读性时,我们也减少了预测单词的方差。结果,我们得到 3 个或更多的单词来自同一首诗。使用单字也不是解决办法,因为不尊重单词的句法和形态顺序会失去意义:这将是一个随机顺序的单词汤。

马尔可夫链带来了易于实现和使用较少变量来预测结果的优势:但它也伴随着糟糕的预测。为了解决这个问题,我转向了一个更复杂的模型:递归神经网络,或 RNN。
另一个值得一提的细节:算法将继续预测,无论长度如何,直到到达链的末端(标签<END>)。这意味着运行该算法可以输出 2 个诗句,下一个可以输出 50 个。

“There must be some kind of way outta here” — Said the joker to the thief.

RNN(递归神经网络)

R ecurrent networks 是一种人工神经网络,它可以识别来自传感器、股票市场或政府机构的数据序列中的模式,如文本、基因组、笔迹、口头语言或数字时间序列。这些算法考虑了时间和顺序;它们有一个时间维度。

与马尔可夫链相比,递归网络具有记忆性。****

为了理解递归网络,首先你需要理解普通网络的基础知识:前馈网络。这两种类型的网络都被称为神经元,因为它们通过在网络节点中执行的一系列数学运算来传递信息。一个在不接触同一个节点超过一次的情况下携带信息直到结束,而另一个在同一个网络上循环运行。后一种叫做轮回

在前馈网络的情况下,给它们输入,你得到一个输出。在监督学习中,输出将是一个标签。这意味着数据被原始映射到一个类别识别模式,该模式决定,例如,用作输入的图像是否可以被分类为

另一方面,不仅将当前看到的例子作为输入,而且它们还考虑先前在时间上已经感知到的。****

在时间t-1做出的决定将影响稍后在时间t做出的决定。因此,递归网络有两个输入来源:现在和最近的过去,它们结合起来决定如何对新数据做出反应——就像人脑一样。

我们还需要分析长短期记忆(LSTM)** 的概念,以完成对完整过程的理解。
如果我把迪伦所有的歌都喂给我的网络,让它完成这首歌的歌名,会发生什么?**

乌克兰人想家了…

我们知道下一个词是 【蓝调】 (如果你不知道这首歌,你现在听它)。网络不会知道,因为这个信息不会重复很多次,或者它的发生不是足够近以至于不能被记住。

对于人类来说,如果一个短语出现在书名中,它一定是情节的重要部分,这是非常明显和直观的;即使是在它唯一出现的时候。与 RNN 相反,我们肯定会记得。即使他们忘记了,也有像 LSTM 网络这样的技术可以成功地处理这种情况。

当 rnn 记住所有的事情直到某个有限的深度时,LSTM 网络学会记住什么和忘记什么。

这允许 LSTM 网络到达并使用 RNNs 范围之外的存储器。由于被认为很重要,这些记忆首先被 LSTM 网络记住。

我们如何实现这一点?一般来说,循环网络有一个简单的结构,模块重复,数据流通过。简单的层通常是用简单的双曲正切(tanh)作为激活函数创建的。

另一方面,LSTM 网络具有更复杂的结构;将这些与其他几个函数结合起来,其中包括 sigmoids。它们不仅包括输入和输出门,还包括第三个门,我们称之为。它接收信息是否值得记忆。如果是否定的,则删除该信息。

决策是如何进行的?每个门都与一个权重相关联。对于每次迭代,sigmoid 函数应用于输入,作为输出,我们接收到一个介于 0 和 1 之间的值。0 表示没有东西通过,1 表示所有东西都通过。
之后,每层的每个值通过反向传播机制进行更新。随着时间的推移,这允许入口学习哪些信息是重要的,哪些是不重要的。

为了实现这一切,我基于格雷戈·苏尔马的文本预测器。我对模型做了一些小的修改,使其适应 Python 3,并对超参数做了一点改动,直到得到满意的结果。

模型是基于字符的:所有独特的字符都是用它们各自的频率计算出来的。张量是用它们指示的频率替换每个字符而创建的。输出的长度由一个参数预定义。在这种情况下,它是固定的。

更多细节,你可以在我的 GitHub 账户中查看我的代码。

*** [## 朗读/歌词 _ 预测

Markov 链与 RNNs 在文本预测上的比较—Alex ing/lyrics _ prediction

github.com](https://github.com/alexing/lyrics_prediciton)

技术细节说够了:让我们检查结果!

这里有趣的一点是,不仅可以看到最终结果,还可以看到算法在每次迭代中的学习过程。它是如何在短短的几个周期内从一堆字符变成一首首诗歌的。

我们还可以欣赏学习曲线,其中我们可以考虑损失函数如何最小化,直到它在不到 90k 次迭代中在接近 0.6 的渐近值附近建立。

迭代 0

5p4:HStdgoTxFtBy/IBBDJe!l5KT
HldE42:lt(-cdbA2lB2avwshp-w,M)cKyP]8 1arOsfsJSA
cWU6sU6E"JV54X9bfrxFV1EEnajkozd'Tk3iQkuUp02oekrQI-,,rAt-(PyfE6z-v7]8utBnD/Nxv:m;0Mw!)cYbnug
qo7t MXQhnq?X7qBTgKp9dJAojO2.87cN?:/0SJq:k
BS
yKDaj5G
0"U466;y8'7cxNLsYXVTUIxqbW0i0bZh8okns) Hf2?2R2hxddb;zXfv3J4iLfv-qOK4y[gaQuImW!XUyyBch9)GgcFB5f[Ri6?FaGno pBMQl hD ;tPUnyWuxg!B Qd6ot30tAlnLg2n?tLctfXTaz:9pIC3Z;fnA]A?q9k"B2r
m"eHTI"miA!d/iimz!/ndfzSKd.W[ALoLxE[l;PQI:PG ]EtUM4?(x4zBB-[wH;
GJT/JYA
zFGK9x05J1Ch[z2(/L4P?Ki
TYNK,7m

你什么都不知道,RNN 模特。冷启动后,用垃圾和随机字符初始化模型。

迭代 1000 次

temple at 
I hand you up to laby, 
You set you on always hole as madoo and use unknear, 
And thinking 
I want his dista, 
Coom on you make you." "What want 
Everybody was on 
Ira," ain't may bold by you.  
And the pend. 
Honey, day you don't eway you say" 
I mad in 
Game, 
No, contaw woman, 
How, way, 
Pryie you don't know, and couse 
I love are stone is sute curt suck block on 
Haye? 
Now, a make for etcide is lord, 
Walles 
And he lad feel, 
Take, blace 
And mave wease with nothing, 
But you

该模型在几次迭代中学习了哪些是创建迪伦歌曲的指示字符。也是它的形状:诗句的大小和基本的标点规则,如开始句子前的大写字母和逗号的用法。

迭代 2000

how. 
You never you been todred, 
Just crying her face to the night.  
Oh, uh, sang to time in you.  
Timb friend carbed as lace. 
We'll be the better does of my beantains, 
The mightenmed to cheat twist and you'll asy dressed them loves?  
With the mough seen of the facing gold, 
Take er can 
Man, wanded like mind for your morning the night up the feet the wond pring, 
Take did a grost ever neum. 
Pounsta fleason just comeless, them bads of me see there a womes of as too lotten up to turn, 
You

有些词已经是实词,词与词之间的形态关系开始显现:形容词和冠词作为名词的修饰语。动词后的间接修饰语、宾语和谓语。

迭代 4000 次

I world must be lady, babe, 
Ither didn't matked, don't remember helled things. 
They'll eter came life, mamber 
And the company together 
That 
I thinking for you, though protaured in the dance please 
Follower, 
I ain't never the one?  
Well, it air awa paries because a north that her in day you only think cannot the ground, her not a roll a mause where they're looked awhile, 
Can the 
Lad-eyes and the confesed white wiced to come me. 
You're in two if it is, slele noners, 
Ain't mes was blow

单词预测中的错误开始减少:词汇错误减少。

迭代 35000 次

with their highway.  
I cannon cloaked in a picture, 
It diamondy his man 
I'll see you even day he'd come there across, the moon after the parking, 
I'm dressed, 
I'm a bad line.  
Sanalured like a coller standing in a woman.  
I'll be banked inside, 
She sees - 
Shere road-luck in the dust he's well never know.  
With degreeing on a whole farms, but don't think twice and 
I took forwlet 
Johanna 
I never crash. 
I'm going to the jelf. 
All 
I never been don't know what 
I 
Night - 
Don't mean

对诗节有很好的形态学理解:即使歌词没有多大意义;它有诗歌或歌词的形式。

迭代 102000

guess he wat hope this nose in the last table if 
I don't mean to know. 
Well, 
I'm puts some dirty trouble for you in the law.  
Go dishes - 
And all the way from a cow, 
They'll stone you when you knew that, you are, you're gonna have to guess that

I after and flowing on you, laws are dead, might as 
I read is changed.  
I've taking for you, yesterday, a 
Martin 
Luther game was tried. 
He was without a home, 
Let the basement deep about hall."  
Well, 
I'm lose again the real land, 
Throw my

错误的数量已经明显减少。它看起来绝对像是人类写的。也许那个人超过了赞安诺的推荐剂量,但毕竟是人。

迭代 259000

guess in the confusion come with nothing in here together wrong. 
I saw sold, he puts in my bed.Going through the branchummy, 
There's an ended on the factiful longer and pierce of 
Blind expense 
And the wind blow you went, 
I've shine, 
Bent 
Before the world is on the snowfur warn - now, handled, your daughters are full of old, goes for dignity.  
Oh, you got some kid no reason to game 
Just and it's light and it evonces, 'round up 
Indian.  
Well, the bright the truth was a man patty

我们的网络学会了像鲍勃·迪伦那样写歌。

好吧,好吧。我接受。我们仍然有一些词汇错误,歌词可能没有太多意义。
即使一个人工智能生成的歌词仍然有这些小瑕疵,我们当然可以看到模型正确地学习了复制提供的数据集的风格。

如果我们考虑到网络是从零开始学习如何做这一切的,并且在开始时它对什么是字母或单词(甚至没有提到英语语法)没有任何理解,我们可以同意结果是令人惊讶的。我们能够检测数据集中的逻辑模式,并复制它们:网络没有任何时间输入语言是什么,或者在其上设置了什么规则,或者甚至正在处理的是来自医疗病人的临床图像或莎士比亚作品集。

结论和未来步骤

在这篇文章中,我计划比较两种完全不同的文本预测方法。一方面,马氏链带来了易于实现的优势。开发它们并不需要高深的理论或技术知识:但预测结果非常基本,而且没有达到预期。该领域的未来显然在于 rnn 的使用,即使实现、运行和测试它们需要很长时间、处理能力、张量的磁盘和存储器空间,特别是先进的技术和理论知识。

为了进一步提高精度,我们可以将后一阶段的输出预测与字典进行对比。这可以由从数据库或英语词典中提取的独特单词组成。通过这种方式,如果预测的单词不存在,我们可以消除它或者用具有最大相似性(较小距离)的单词来替换它。

同样,如果你愿意,你可以在我的公共 GitHub 账户中查看我的代码。

Let me ask you one question, is your money that good?
Will it buy you forgiveness, do you think that it could?

人工歌词还要多久才能到?谁将第一个挤出这个市场?已经有已故音乐家的全息旅行。罗伊·奥比森、迈克尔·杰克逊和图帕克就是一些值得一提的例子。这个“死后音乐”的新时代会成为人为作词的完美借口吗?

感谢阅读!

来源

[## 用机器学习预测逻辑的歌词

使用机器学习概念,我们可以分析 Logic 的嘻哈风格,并预测他实际会写的歌词。

towardsdatascience.com](/predicting-logics-lyrics-with-machine-learning-9e42aff63730) [## LSTMs 和递归神经网络初学者指南

数据只能反向理解;但它必须向前看。—索伦·克尔凯郭尔,期刊内容实际上…

skymind.ai](https://skymind.ai/wiki/lstm) [## 文本预测器—生成 Rap 歌词📄

递归神经网络语言建模

towardsdatascience.com](/text-predictor-generating-rap-lyrics-with-recurrent-neural-networks-lstms-c3a1acbbda79)***

超越 A/B 测试:多臂强盗实验

原文:https://towardsdatascience.com/beyond-a-b-testing-multi-armed-bandit-experiments-1493f709f804?source=collection_archive---------3-----------------------

基于 Thompson 抽样和蒙特卡罗模拟的 Google Analytics 随机 k 臂 bandit 检验研究

A/B 测试摘要

A/B 测试依赖于经典的统计显著性测试。当我们想出一个新的产品特性时,我们可能想在向整个用户群发布之前测试它是否有用。该测试包括两组:一个治疗组(可以使用新功能)和一个对照组。然后,我们为这两个群体测量一个关键指标:平均网站时间(社交网络),平均结账时间(电子商务),或点击率(在线广告)。对各组之间的差异进行统计显著性检验。

经典的统计检验(z-检验,t-检验)保证假阳性率不超过α,常设置为 5%。这意味着当治疗组和对照组之间没有差异时,测试将有 5%的机会发现统计学差异。

平衡 AB 测试会将等量的流量分配给每个组,直到达到足够的样本量。但是,我们不能根据观察到的情况在测试期间调整流量分配。因此,A/B 测试的缺点是显而易见的:如果治疗组明显优于对照组,我们仍然必须在对照组上花费大量的流量,以获得统计显著性。

多臂土匪

鉴于 A/B 测试是一种频繁的方法,我们也可以用贝叶斯方法进行测试。这是可以理解的,一旦我们看到一种治疗方法明显更好,我们就想马上增加更多的用户。多臂强盗实验以可控的方式使这成为可能。

多臂土匪实验的基础是贝叶斯更新。每种治疗(称为“arm”,参见下面的类别定义)都有成功的概率,这被建模为伯努利过程。成功的概率是未知的,由 Beta 分布建模。随着实验的继续,每个分支都接收用户流量,Beta 分布也相应更新。为了可视化更新过程,请看我之前的帖子这里

在这篇文章中,我使用了谷歌在线广告匹配分析的例子。假设有 K 个臂。每个臂是一个广告,其点击率( ctr )遵循 Beta 分布。实验的目标是找到点击率最高的广告。

汤普森取样

简而言之,汤普森抽样是一种贪婪的方法,总是选择期望报酬最大化的手臂。在 bandit 实验的每次迭代中,Thompson sampling 只是从每个手臂的 Beta 分布中抽取一个样本 ctr ,并将用户分配到具有最高 ctr 的手臂。

Applying Bayesian updating to the Beta distribution of each arm

bandit 实验的精妙之处在于 Thompson 采样和 Bayesian 更新同时进行。如果其中一个分支表现良好,则更新其 Beta 分布参数以记住这一点,并且 Thompson 采样将更有可能从该分支获得高 ctr在整个实验中,高性能的武器被奖励了更多的流量,而低性能的武器被惩罚了更少的流量。

蒙特卡洛模拟

鉴于 Beta 分布估计的是 ctr,我们需要知道我们对 ctr 的每个估计有多大的把握。如果我们对目前具有最高 ctr 的手臂足够有信心,我们可以结束实验。

Monte Carlo simulation

蒙特卡洛模拟的工作方式是多次从 K 支队伍中随机抽取样本,并根据经验计算每支队伍获胜的频率(最高 ctr )。如果获胜的一方以足够大的优势击败第二方,实验就终止了。

终止

Google Analytics 引入了“实验中剩余价值”的概念(更多细节此处)。在每次蒙特卡罗模拟中,计算剩余值。如果我们选择α = 5%,那么当蒙特卡罗模拟中 95%的样本的剩余值小于获胜手臂值的 1%时,实验终止。

模拟

上面已经定义了效用函数,把它们放在一起就很简单了。对于每次迭代,都会有一个新用户到来。我们应用 Thompson 采样来选择手臂,并观察用户是否点击。然后我们更新手臂的β参数,检查我们是否对获胜的手臂有足够的信心来结束实验。

注意,我引入了一个老化参数。这是在宣布获胜者之前必须运行的最小迭代次数。实验的开始是最热闹的时期,任何一个失败者都有可能成功。预烧期有助于防止在噪音稳定下来之前过早结束实验。

实际上,这也有助于控制新奇效果、冷启动和其他与用户心理相关的混淆变量。谷歌分析强迫所有的强盗实验运行至少 2 周。

优势

bandit 试验的主要优点是它比 A/B 试验更早终止,因为它需要更小的样本。在点击率为 4%和 5%的双臂实验中,在 95%的显著性水平下,传统的 A/B 测试需要每个处理组 11,165。如果每天有 100 名用户,这项实验将需要 223 天。然而,在 bandit 实验中,模拟在 31 天后结束,达到上述终止标准。

Amount of traffic sent to the losing arm on each day (“mistakes”).

bandit 实验的第二个优点是该实验比 A/B 测试犯的错误更少。平衡的 A/B 测试总是将 50%的流量发送到每个组。上图显示,随着实验的进行,越来越少的流量被发送到失败的那一方。

以下是如何在模拟中运行 5 臂土匪实验。我们看到红色的手臂(ctr 为 4.4%)在前 150 次迭代中被误认为是获胜的手臂,我们将多达 80%的流量转移到了失败的手臂。但真正的蓝臂(ctr 4.8%)迎头赶上,成为真正的赢家。

交易

天下没有免费的午餐,更小样本量的便利是以更大的假阳性率为代价的。虽然我曾根据经验使用α作为假阳性率来终止实验,但在重复模拟多次后,假阳性率高于α。

α vs. sample size (traffic) and probability of finding correct winner

根据经验,5%的α在大约 91%的情况下找到获胜的手臂,而不是 95%。我们设置的α越小,我们需要的样本量就越大(显示为红色),这与 A/B 测试的行为是一致的。

结论

事实证明,没有确定的赢家,对于产品经理、数据科学家和从业者来说,在做出选择之前,了解两种方法的优缺点是很重要的。在下列情况下,最好进行多臂 bandit 测试:

  • 当将用户发送到失败的一方的成本很高时。在这个例子中,将用户与不良广告匹配只会导致更少的收入。损失是可以承受的。在其他情况下,例如在测试两种不同的帐户恢复方法时,每个分支的失败都意味着永久失去一个用户,多分支 bandit 实验显然是更好的选择。
  • 对于用户流量不足的早期创业公司,多臂 bandit 实验效果更好,因为它需要的样本量更小,终止更早,比 A/B 测试更敏捷。
  • 当有两个以上的变体需要测试时,bandit 实验可以帮助我们快速找到赢家。在 bandit 实验中,通常一次测试 4~8 个变体,而 A/B 测试仅限于每次测试两组。

多臂 bandit 测试的一个明显限制是,每个臂必须由 Beta 分布建模,这意味着每次尝试一个臂,都会导致成功或失败。这有利于对点击率和转换率进行建模,但如果您正在测试哪个结账过程更快,您必须对平均值的差异进行 t 检验。

另一方面,当公司有足够大的用户群时,当控制第一类错误(误报)很重要时,当我们可以对照控制组一次一个地测试它们中的每一个时,A/B 测试是更好的选择。

延伸阅读

下面的博客涵盖了与 AB 测试相关的主题,以及对本文中提到的关键概念的更深入的回顾。

  • 可视化 Beta 分布和贝叶斯更新[ 链接
  • 理解置信区间[ 链接
  • A/B 测试的力量[ 链接
  • 你知道可信区间[ 链接
  • 代码在我的 Kaggle 笔记本里。

超越条形图和饼图

原文:https://towardsdatascience.com/beyond-bar-graphs-and-pie-charts-beb7f48cda5d?source=collection_archive---------12-----------------------

link

初学者指南

使用 Python、R、Tableau 和 RawGraphs 来有效而完美地交流数据

我明白。也许你忘了今天下午的报告。也许你有 5 分钟的时间在一天结束前把你老板想要的 3 张图片放在他的桌子上。也许你只是厌倦了在花费几个小时,甚至几天,清理和分析数据后处理和查看数据。我明白了,但是请不要拼凑一个条形图,添加一些颜色使它看起来更像是拼凑在一起的,然后把它扔到您的交付件上。有如此多的工具用于创建数据的可视化,而你在 Powerpoint 中创建一个基本的(无用的)饼状图是对自己不公平的,而你本可以创建一些漂亮的和信息丰富的东西。

即使你的视觉效果不是为了演示——也许它是你数据探索的一部分——你仍然要确保你是以一种能让你得出正确结论的方式来可视化它。

我们开始吧。

第一课:知道你能得到什么

有两种主要的工具可以用来创建视觉效果:编码包(例如 R 中的 ggplot2,Python 中的 seaborn 或 matplotlib)和可视化软件(例如表格、图表、草图)。这两者可以在不同的方面发挥作用,我们将使用一个关于难民的数据集来可视化其中的一些差异。

如果您希望在可视化数据的同时操作数据,那么编码包非常有用。例如,如果除了折线图之外,您还想显示它周围的置信带,那么添加到代码中就容易多了。或者,如果您在对数据执行回归过程之前创建可视化作为探索数据的一种方式,那么在代码中完成这一点也会更容易,因为只要它不符合您的交付成果,就不需要进行微调。最后,如果数据需要大量的清理,无论如何你都必须在你的代码中这样做,所以如果部分清理需要重做的话,创建可视化效果可能是有益的。

如果您试图创建模糊的视觉类型或编码大量信息,可视化软件非常有用。使用代码,根据变量的性质,您通常可以编码 2 个,也许 3 个额外的变量,但是更多的变量可以很容易地用软件编码,只需为您做一半的工作。尤其是当您的数据以奇怪的方式格式化时。为了对类似于左边条形图的图形进行编码,必须对数据进行重新组织,使难民类型本身成为一列,并且这些不同列中的数据必须进行组合。

如果数据集很小,这很简单,例如在本例中,但是如果您使用的是大型数据框,则可能很难对其进行重新格式化。

第二课:选择正确的图表

另一个可能影响你决定是使用编码平台还是可视化软件的因素是你想要制作的视觉效果的类型。下面是您可以在我前面提到的四个不同的包和平台中创建的图形类型。

type of graphs available for each program

很容易满足于条形图或饼图,但愿不会如此。饼状图包含在上面的列表中,用于最少的合适场合,但是如果你还没有弄明白,你应该避免使用它们。他们很少有效地交流信息,尤其是在并排比较几个饼图的时候。在这种情况下,使用堆积条形图要简单得多,如果这不可能,那么你就不应该比较它们。

另一个常见的错误是过度使用线图。如果 x 轴上的值是离散的,这意味着它们之间的空间没有逻辑值,那么 y 轴上的值不应该连接。如果 x 值可以重新排列或者不是数字(除了日期),请远离折线图。

从上面的列表中可以看出,并不是每种视觉都可以在每种平台上制作。是的,你总是可以做一个散点图或条形图,但是如果你想做一个圆形的树状图,你只能在 RawGraphs 中完成。或者,如果您想要制作美国的符号地图,最简单的方法是在 Tableau 中完成(加上 Tableau 有地图图层,可以添加这些图层以显示更多可能不在您的数据集中的信息)。

第三课:定制你的视觉效果,不要满足于橙色和蓝色

听着,我喜欢蓝色和橙色。作为弗吉尼亚大学的学生,这是我最喜欢的颜色组合。然而,当你的第 20 个图形仍然是蓝色和橙色的阴影,偶尔出现红色作为第三层时,它会变得很无聊。在代码和软件中,你可以选择你使用的颜色。现在,颜色不应该被随意使用。如果没有明确的、翔实的理由来添加色阶,就不要添加色阶。如果观察的颜色使用了与其大小、形状、长度等相同的信息,那么添加颜色只会让你的图表看起来更加混乱。

比较上面这两幅图。它们显示了同样多的信息,但是底部的一个用紫色阴影编码了难民的数量。是的,它看起来更漂亮,但它并没有给观众提供比第一张图更多的信息。

颜色也可以有偶然的含义。假设不是紫色,而是红色到绿色。这些颜色不仅对我们的色盲朋友不友好,而且我们在文化上也将红色与坏的联系在一起,将绿色与好的联系在一起。因此,如果 5 至 9 岁儿童的酒吧是亮红色,与绿色形成对比,我们可能会得出结论,即有太多的 5 至 9 岁儿童,这可能是真的,但可能不是视觉的目标。让我们看一个更糟糕的图表..

你能在这张图片上发现多少让你读起来更加困惑的东西?我们有年龄的字母顺序,令人困惑的 y 轴标签,以及编码申请人数的怪异色标。

对坐标轴上的值进行排序时,如果它们本质上不是序号/数字,则按升序或降序排列。这使得挑选最好的、最差的以及介于两者之间的东西变得容易得多。坐标轴的标签应该有目的地标注,如果您要比较具有相似信息的多个图表,请保持坐标轴的刻度不变。您不需要满足于列的名称,您可以通过一点点代码或在您的软件中进行一些编辑来定制它。最后,再次强调,要有意识地使用你的颜色。如果像这样的比例有意义(如果目标是 2000 名申请人,任何太低的都是不好的),那么使用这个色标。

第四课:小心你的编码方式

颜色并不是给你的视觉增加额外信息的唯一方式。您可以采用的另一种方法是将数据点的大小与一个附加变量相关联。

在这个视频中,点的颜色告诉你 2006 年有多少难民,而大小显示了 2015 年的难民人数。虽然仍然可以从中得出有效的结论,但是使用区域时要小心。作为人类,我们通常更容易理解长度和宽度的差异,而不是面积。

最后一点,编码数据不应该是你想要交流的主要数据。如果你真的想让某人从上一个条形图中得到的是应用程序的分布,那么用颜色来表示就不能有效地传达它。编码是针对次要数据的——包含这些数据是有用的,可以提供额外的洞察力,但对视觉效果可能不是至关重要的。

第五课:完全创建你的图形

作为例子的视觉效果是不完整的。再说一遍,除非他们是为了数据探索,不会制作幻灯片或演示文稿,否则除了简单地制作条形图,还有更多事情要做。如果你回头看看我制作的第一个图表,我使用 Python 中的 seaborn 包,并且没有包括 x 轴的标签,所以你不能从中得出任何结论。你不知道 0 和 1 是什么——据你所知,它们可能是猫和狗。添加标签,添加标题,添加图例。确保如果有人看了你的视频,但不理解你的数据,他们能够得出正确的结论。

有用的备忘单、代码和演练来帮助您

Seaborn 备忘单和示例代码

*sns.set_palette("Paired")sns.barplot(x='Sex', y='Applicants', data=data1).set_xticklabels(["Female","Male"])
plt.ylim(0,40000)
plt.title("Number of Refugee Applicants per Sex")sns.scatterplot(x='Marital Status', y='All', data=data2).set_xticklabels(["","Single","","Married","","Divorced/Separated","","Widowed"])
plt.ylabel("All Refugees")
plt.title("Number of Refugees by Marital Status")*

https://www.datacamp.com/community/blog/seaborn-cheat-sheet-python

ggplot2 备忘单和示例代码

*ggplot(data, aes(x=data$Year,y=data$Refugees,color=data$Continent)) + geom_line() + labs(title="Refugees by Continent",x="Year", y="Number of Refugees") + scale_color_discrete(name="Continent") + 
  scale_x_continuous(breaks=c(2006,2008,2010,2012,2014))*

https://www.rstudio.com/wp-content/uploads/2015/03/ggplot2-cheatsheet.pdf

Tableau 备忘单和演练示例

https://confluence.umd.edu/download/attachments/551683736/Tableau%20Cheat%20Sheet%2010-31-2016.pdf?api=v2

RawGraphs 演练示例

超越图卷积网络

原文:https://towardsdatascience.com/beyond-graph-convolution-networks-8f22c403955a?source=collection_archive---------5-----------------------

深入探讨高级图形神经网络架构

图形神经网络虽然是一个相当新的概念,但作为一种有趣的分析图形的方法,即深度学习方法,已经获得了巨大的普及。GNNs 能够自然地适应许多具有固有图形结构的真实世界数据集,已经在许多不同的领域找到了应用,从在线广告到道路交通预测和药物设计。这篇博文:图形神经网络的应用列举了 GNNs 已经取得显著成果的各种领域。

早期的 GNNs 将通过以迭代的方式传播邻居信息来学习目标节点的表示,直到达到稳定的固定点。然而,GNNs 很难停留在这种初生的形式,它很快采用了其他成功的深度学习领域的想法,进化到我们今天所知的图形卷积网络的架构。

图形卷积网络

顾名思义,图卷积网络(GCN),借鉴了卷积神经网络的思想,将它们重新定义为图的领域。至于图像,卷积框架的目的是捕捉图形节点的邻域信息。

Image Convolution and Graph Convolution

然而,gcn 有两种类型:光谱 gcn 和空间 gcn。基于频谱的方法通过从基于图形频谱理论的图形信号处理的角度引入滤波器来定义图形卷积。基于空间的方法将图卷积公式化为来自邻居的聚集特征信息。谱方法的一个缺点是,它需要同时处理整个图,这对于具有数十亿个节点和边的大型图(如社交网络图)来说是不切实际的。这种一起处理整个图形的要求带来的另一个缺点是,很难利用当今可用的并行处理能力。空间方法不受此影响,因为它们通过聚集相邻节点的信息直接在图形域中执行卷积。与采样策略一起,计算可以在一批节点中执行,而不是在整个图中执行,这有可能提高效率。

谱卷积方法的另一个痛点是,它们假设一个固定的图形,因此不能很好地推广到新的或不同的图形。另一方面,空间模型在每个节点上本地执行图形卷积,因此可以很容易地在不同的位置和结构上共享权重。由于所有这些因素,空间模型近年来吸引了越来越多的关注。

对于空间图形卷积,关键是学习函数 f,以通过聚合其自身的特征 Xi 和邻居的特征 Xj 来生成节点 vi 的表示。聚合函数必须是对节点排序的排列不变的函数,例如均值、求和及最大值函数。在特征聚合之后,诸如 Relu/Tanh 的非线性变换被应用于结果输出。为了探索节点影响范围的深度和广度,通常的做法是将多个图形卷积层堆叠在一起。每个隐藏的 GCN 层是聚合操作的一次迭代,随后是非线性激活。每个迭代/层使用来自前一个迭代/层的节点表示来获得当前迭代/层的表示。

GCN 的第一层促进一阶邻居之间的信息流动;第二层从二阶邻居,即从邻居的邻居获得信息。继续这样,通过堆叠多个层,每个节点的最终隐藏表示接收来自更远邻域的消息。

虽然 GCN 在节点级别上运行,但是图形池模块可以与 GCN 层交错,以将图形粗化为高级子结构。这种架构设计可用于提取图形级表示并执行图形分类任务。

由于 gcn 的效率不断提高,它们在许多应用领域产生了越来越好的结果,因此已经成为许多其他 GNN 模型的基准架构。

M 超越 GCNs,以下是适用于各种不同问题类别的一些更复杂的图形神经网络架构的分类:

1.图形注意网络

2.图形自动编码器

3.图形生成网络

4.图形时空网络

图形注意网络

注意机制几乎已经成为基于序列的任务的标准。注意机制有能力关注输入难题中最重要的部分。事实证明,这对于机器翻译和自然语言理解等任务尤其有益。由于注意力机制的模型容量增加,图形神经网络也可以受益于注意力模型。图形注意力网络类似于 GCNs,寻求聚合函数来融合相邻节点的表示、随机行走或来自多个候选模型的输出,以学习新的表示。关键的区别在于,图形注意力网络采用的注意力机制为更重要的节点、行走或模型分配更大的权重。注意力权重是通过端到端框架内的神经网络来学习的,该框架包括图形神经架构和注意力神经网络。

为了理解注意力机制如何应用于图结构数据,我们将看到如何使用注意力模型来聚集邻居节点信息以获得当前节点的表示。下图描述了不同之处:

在图(a)中,GCNs 在聚合过程中明确地将非参数权重 aij 分配给 vi 的邻居 vj,而图(b)中的图形注意力网络通过端到端神经网络架构隐含地捕获权重 aij,使得更重要的节点接收更大的权重。

类似地,对于基于随机行走的 GNN,不同的注意力权重被分配给不同的行走。图注意网络的优点是它们可以自适应地学习每个邻居的重要性。然而,由于必须计算每对邻居之间的注意力权重,计算成本和内存消耗迅速增加。

图形自动编码器

图形自动编码器旨在通过编码器学习低维向量,然后通过解码器重建图形。这些向量可以是节点级的,即每个节点一个向量,生成图的密集低维矩阵表示,或者是图级的,即捕获图的所有结构和节点信息的向量。图形自动编码器是学习图形嵌入的一种流行方法,因为它们生成中间向量表示。

典型的解决方案包括利用多层感知器作为编码器来获得节点嵌入;解码器经由链路预测机制重建节点的邻域统计,例如节点之间的边。编码器可以捕获节点的一阶和二阶信息。对于平面图,很多算法直接对邻接矩阵进行处理,构造一个新的信息丰富的稠密矩阵。对于属性图,图自动编码器模型倾向于使用 GCN 作为编码器的构建块。图自动编码器模型的另一个变体涉及使用图生成机制(在下一节中讨论)从嵌入中重新创建图。

下图描述了图形自动编码器模型的一般结构:

编码器使用 GCN 层来获得每个节点的潜在表示。解码器计算由编码器产生的节点向量之间的成对距离。在应用非线性激活函数之后,解码器重构图邻接矩阵。以这样的方式训练整个模型,使得计算的节点向量之间的简单成对距离(随后是非线性运算)足以再现图的边信息。也就是说,编码器和解码器被联合训练,因此学习到的节点表示使得解码器能够补充编码器。

在训练之后,解码器模块可以被断开以仅产生向量,并且将它们用作图/节点嵌入,其可以被用作进一步下游处理的输入。

图形生成网络

给定一个数据分布,图生成网络(ggn)的目标是根据特定的约束条件,从数据中生成合理的结构。也就是说,他们试图捕捉给定数据中隐含的实体及其关系,并试图将它们建模为图形结构。或者,给定一组观察到的图,ggn 可以尝试生成具有某些属性的新图。GGNs 的一个有前途的应用领域是化学化合物合成。在化学图形中,原子被视为节点,化学键被视为边。任务是在给定一组现有分子的情况下,发现具有某些化学和物理性质的新的可合成分子。GGNs 的另一个应用是在自然语言处理中,其中生成语义或知识图通常以给定的句子为条件。

然而,给定图的经验分布来生成图从根本上来说是具有挑战性的,这主要是因为图是复杂的数据结构。一种方法是将生成过程分解为交替形成节点和边。图的深度生成模型(DGMG)是这种方法的代表作品之一。DGMG 利用 GCN 来获得现有输入图的矢量表示。生成节点和边的决策过程以该向量为条件。DGMG 递归地向一个生长图提出一个节点,直到一个停止标准被唤起。在添加新节点后的每一步中,DGMG 反复决定是否给添加的节点添加边,直到决定变为假。

另一种方法是基于用于生成图像的生成对抗网络(GANs)。但是在对抗网络中,图卷积网络被用作构建块,而不是使用卷积神经网络。GAN 由一个生成器和一个鉴别器组成,两者相互竞争以提高生成器的真实性。首先,生成器从给定的数据分布中生成候选图。这个候选图通常被称为伪图。鉴别器的目的是从经验数据中鉴别出伪造的样本。此外,奖励网络可以与鉴别器并行引入,以鼓励生成的图拥有某些属性。鉴别器和奖励网络被馈送伪造图形的矢量表示;它们都单独输出一个分数,作为对生成器的反馈。以下是该架构的示意图:

上述两种方法的缺点是它们不能扩展到大的图,因为具有 n 个节点的图的输出空间是 n^2.

图形时空网络

时空图是其中节点和/或边特征随时间 t 变化的图结构。例如,道路交通网络可以建模为图,其中每个关键位置是一个节点,并且该位置的传感器在多个时间步长内监控该位置的交通速度;因此,节点值(该位置的交通速度)会随着时间不断变化。边可以简单地是成对的传感器或位置节点之间的距离。使用道路网络的空间图的时间信息,可以预测时空图的节点的未来时间步的交通。

交通预测问题的一个变体是出租车需求预测问题,其在智能交通系统中具有非常实际的使用案例,智能交通系统预先分配出租车资源以满足出行需求并减少浪费能量并恶化交通拥堵的街道上的空出租车。鉴于优步和 Ola 等在线运输市场的繁荣,这一点尤其有用。在交通预测的情况下,关键位置可以建模为节点,具有诸如这些位置的交通和天气状况的特征:这些随着一天或一个月的时间不断变化。节点标签可以是特定区域中请求的出租车数量,这也随时间变化,问题是预测未来时间步长的这些值。

图时空网络的核心思想是同时考虑空间依赖和时间依赖。许多当前的方法应用 GCNs 来捕捉空间依赖性,以及一些 RNN 或 CNN 来建模时间依赖性。一种称为扩散卷积递归神经网络(DCRNN)的方法引入扩散卷积作为图形卷积来捕获空间相关性,并使用具有门控递归单元(GRU)的序列到序列架构来捕获时间相关性。DCRNN 使用图形(扩散)卷积层处理 GRU 的输入,以便递归单元同时接收来自最后时间步长的历史信息和来自图形卷积的邻域信息。DCRNN 的优势在于,由于递归网络架构,它能够处理长期依赖性。

在上面的部分中,我们回顾了一些高级图形神经网络架构,这些架构利用了深度学习领域中用于各种问题的先前成功的架构。几乎所有这些都使用图卷积作为构建模块。即便如此,这些复杂的架构更适合某些类型的图形和/或问题用例,因此产生更好的结果。随着 GCNs 效率的提高,我们将会看到更多这样的变化出现,GNNs 的分类也将不断增长!

参考资料:

https://arxiv.org/abs/1901.00596

超越线性回归:GLMs 导论

原文:https://towardsdatascience.com/beyond-linear-regression-an-introduction-to-glms-7ae64a8fad9c?source=collection_archive---------5-----------------------

来自统计学背景,我第一次涉足数据科学和机器学习是通过线性回归。当时,我真的相信没有什么统计建模问题如此复杂,以至于不能用一个适当定义的线性回归模型来解决。

同时,我也认为包含 5000 个数据点的数据集是“大”的;学习 SAS 对我的职业生涯来说比学习 R 更有价值;《吸血鬼猎人巴菲》是有史以来最棒的电视剧。

我当时是本科生,世界观极其狭隘。

然而,在我大学二年级统计学课上定义的宇宙中,我实际上是对的。T2 真的没有复杂到无法用线性回归模型建模的问题。任何对线性回归模型来说太复杂的问题都被我们轻易隐藏了,所以实际上,在那个世界里不存在。

这凸显了许多数据科学家,尤其是那些职业生涯初期的数据科学家,可能会陷入的陷阱。

许多介绍性的机器学习课程只教给学生一组有限的可能模型(通常是线性和逻辑回归、决策树、朴素贝叶斯、支持向量机和神经网络),并且只提供使用数据集的示例,其中一个或多个模型是合适的。

这可能导致数据科学家错误地认为,所有监督学习问题都可以用一小组机器学习模型中的一个来解决。

但是,在机器学习入门课程中教授的模型肯定不是唯一的统计或机器学习模型。

其中一个很少在机器学习 MOOCs 或大学数据科学学位中教授的模型是广义线性模型或 GLM。GLMs 经常用于保险费设定,并且已经被证明是我职业生涯中迄今为止遇到的最有用的统计模型之一。

在本文中,我们将仔细研究这个高度通用但经常被忽视的模型。

线性回归概述

(多元)线性回归模型由三部分组成:

  1. 一个输出(或响应/相关)变量 Y,其中该变量的所有观测值都被假设为独立地取自具有恒定方差 s2 的正态分布;
  2. k 个输入(或解释/独立)变量的向量,X1,X2,…,Xk;和
  3. k+1 个参数的向量,b0,b1,…,bk,允许我们将 Y 的平均值表示为输入变量的线性组合:

这三个分量一起将 Y 的概率分布定义为 Yi ~ iid N(mi,s2),我们拟合线性回归模型的目的是确定参数值,这些参数值将最佳地定义我们数据的分布。

这可以使用几种不同的方法来完成,包括普通最小二乘法(通常用于较小的数据集)和梯度下降法(通常用于较大的数据集)。

线性回归的主要优势在于线性回归模型具有以下特点:

  • 快速训练和查询;
  • 不易过拟合,能有效利用数据,因此可应用于相对较小的数据集;和
  • 很容易解释,即使对非技术背景的人也是如此。

然而,线性回归的一个关键弱点是其背后的限制性假设,这对于模型提供良好的数据拟合来说必须成立。特别是正态假设。

根据定义,正态分布的数据是连续的、对称的,并且定义在整个数字线上。这意味着任何离散的、不对称的或只能在有限范围内取值的数据,都不应该用线性回归来建模。

任何学过本科统计学的人都知道,如果你的数据没有表现出一个或多个这些特征,你可以做一些工作。例如,如果我们的数据是倾斜的,我们可以通过取输出的对数或平方根来转换它。

然而,这可以被视为将我们的数据拟合到我们的模型的经典案例,这从来都不是问题的最佳解决方案。另一种方法是使用不同类型的回归模型,该模型专门设计用于非正态数据。这就是广义线性模型的用武之地。

介绍广义线性模型

广义线性模型(GLMs)可以被认为是多元线性回归模型的推广。glm 也由三个组件组成,这三个组件类似于线性回归模型的组件,但略有不同。具体来说,GLMs 由以下部分组成:

  1. 输出变量 Y,其中该变量的所有观察值被假设为从指数族分布中独立提取
  2. k 个输入变量的向量,X1,X2,…,Xk;和
  3. k+1 个参数的向量,b0,b1,…,bk,和一个链接函数 g() ,它允许我们将 g(E(Y)) 写成我们输入变量的线性组合。那就是:

其中 m = E(Y)。

同样,我们的目标是确定最佳参数值来定义 Y 的概率分布,但我们现在不再局限于 Y 仅遵循正态分布。

根据 GLM 假设,Y 现在可以遵循“指数族”内的任何概率分布,这不仅包括指数分布,还包括正态分布、伽玛分布、卡方分布、泊松分布、二项式分布(对于固定数量的试验)、负二项式分布(对于固定数量的故障)、贝塔分布和对数正态分布等。

几乎所有在本科和硕士统计学课程中教授的概率分布都是指数家族的成员。

我们的链接函数的目的是转换我们的输出变量,以便我们可以将它表示为我们的输入变量的线性组合(这是,而不是,将我们的输出变量转换为正态,正如人们经常错误地认为的那样)。

根据我们假设的输出分布的概率分布,有一些常用的连接函数。

例如:

因此,当指定 GLM 时,有必要指定输出概率分布函数和链接函数。

标准线性回归模型是 GLM 的一种特殊情况,其中我们假设正态概率分布和身份链接。

GLMs 优于线性回归的三种情况

在违反正态假设的情况下,GLMs 通常优于线性回归模型。可能发生这种情况的三种情况是:计数数据;扭曲的数据;和二进制数据。

让我们看看 GLMs 在这些情况下是如何使用的。

案例 1:计数数据

计数数据是任何只能取非负整数值的数据。顾名思义,它通常出现在对特定类型的事件在一段时间内的观察进行计数时。比如一个路口每年的车祸次数;或者进程每天失败的次数。

为了拟合 GLM 来计算数据,我们需要为我们的模型假设一个概率分布和链接函数。因为计数数据是离散的,所以概率分布也必须是离散的。

在这种情况下,最常见的选择是泊松或负二项分布,具有对数关联函数。

要将泊松或负二项式 GLM 拟合到我们的数据中,我们可以使用 Python 的 statsmodels 包,语法如下:

import pandas as pd 
import statsmodels.api as sm count_model = sm.GLM(count_data['Y'], sm.add_constant(count_data[['X1', 'X2']]), family=sm.families.Poisson(sm.genmod.families.links.log)).fit()

该语法假设我们的数据集是名为 count_data 的熊猫数据帧的形式,具有输出变量 Y 和输入变量 X1 和 X2,并且我们想要拟合泊松 GLM。

为了拟合负二项式 GLM,而不是泊松 GLM,我们需要做的就是将 sm.families.Poisson 改为 sm.families.NegativeBinomial

案例 2:扭曲的数据

尽管不对称数据可能会向两个方向倾斜。在实践中,您将遇到的大多数不对称数据都是右偏或正偏的,如下图所示的数据集。

如前所述,要对此数据拟合 GLM,我们需要选择一个概率分布和链接函数。我们的概率函数需要正偏,在这种情况下最常见的选择是带有对数链接的伽马分布。

要使用 statsmodels 包拟合带有数据对数链接的伽玛分布,我们可以使用与泊松 GLM 相同的语法,但用 sm.families.Gamma 替换 sm.families.Poisson

伽玛分布仅针对大于 0 的值定义。因此,如果我们的输出变量 Y 可以取负或零,那么在拟合模型之前,可能有必要通过向输出变量添加足够大的常数来转换我们的数据。

例如,如果我们的输出变量可以采用任何非负值,包括零,我们可以通过在拟合模型之前将 0.01 添加到所有 Y 值来转换它,将最小值移动到 0.01。

案例 3:二进制数据

与前两个示例一样,上述 GLM 可以使用 statsmodels 包进行拟合,使用与前面相同的语法,但将 sm.families.Poisson 替换为 sm.families.Binomial,将 sm.genmod.families.links.log 替换为 sm.genmod.families.links.logit

也就是说,如果我们假设我们的数据集名为 binary_data,并且我们的输入和输出变量与前面定义的一样,使用命令:

binary_model = sm.GLM(binary_data['Y'], sm.add_constant(binary _data[['X1', 'X2']]), family=sm.families.Binomial(sm.genmod.families.links.logit)).fit()

或者,我们也可以使用 Python scikit-learn 包的 sklearn.linear_model 来拟合这个模型。逻辑回归函数。

引用莎士比亚的话,“天地万物,远非你的哲学所能想象,”数据科学和机器学习不仅仅是普通入门 MOOC 的内容。

在本文中,我们介绍了一种许多早期职业数据科学家都不熟悉的模型,但这只是冰山一角,还有更多这种模型。

这并不是说,每个数据科学家都需要了解关于现有的每个统计或机器学习模型的一切。

然而,只要意识到数据科学不仅仅是基本模型,你就不太可能犯将数据拟合到模型的错误,而实际上你应该将模型拟合到数据。

Genevieve Hayes 博士是数据科学家、教育家和人工智能及分析专家,拥有Genevieve Hayes Consulting。你可以在LinkedIn或者Twitter上关注她。她还是 价值驱动数据科学 的主持人,这是一个每月两次的播客,面向希望最大化其数据和数据团队价值的企业。

想要发掘企业数据的价值,但不知道从何入手? 下载免费的数据科学项目探索指南。

超越柱状图:在科学中可视化性别不平等

原文:https://towardsdatascience.com/beyond-the-bar-plot-visualizing-gender-inequality-in-science-7d77f5a01953?source=collection_archive---------25-----------------------

Baby bar plots coming to life (pixabay/TK)

当你有来自 12 个国家超过 5 个维度的性别比例数据时,所有数据都显示“大约 25%”,你想在不去除复杂性的情况下制作一个引人注目的视觉效果,该怎么办?

《经济学人》的 Sarah Leo 最近写了一篇有趣的文章,她给出了一些图表的例子,这些图表是“ (1)误导性的,(2)令人困惑的,(3)未能阐明观点的”,以及她提出的修改意见。我对她的上一个例子很感兴趣,这个例子讲述了科学出版中性别失衡的故事,她没有提出更好的图表,而是征求意见。

Never give up! (Source)

我认为这种观想的主要问题是:

  • 作为读者,看着看着就要想太多!没有明显的颜色或图标代码,没有明显的国家分组暗示潜在的模式
  • 对数据本身的解读不清晰 —学科(竖线标记)被塞进一个单轴上,由一条从 0 到“健康科学”的横线连接,而各行似乎是按横线的总长度排序的,这让我很困惑:点是标记整体的比例,还是单独的数据点?比方说,在葡萄牙,我看到 26%的人表示“发明家”,27%的人表示“计算机科学”,36%的人表示“工程”,等等,所有这些都是相关联的——所以我也可以这样理解:有 26%的发明家,27%-26% = 1%的计算机科学家,36%-27%=9%的工程师等等,这不是作者的意图
  • 扭曲 —水平刻度范围从 0%到 60%,因此“健康科学”的数据位于可见图的最右侧,其他数据点位于中间。这给人一种印象,即女性的比例比实际高得多
  • 无限潜能的幻觉—蓝色水平线连接零点和数据点,而右边的空间呈现为空白。这给人一种错误的印象,即所绘制的只是一个 KPI,女性只要付出更多的努力,就可以提高和进一步提升。事实上,右边的所有空间都被填满了(而且是由男科学家填满的)

受 Sarah 的问题和评论部分一些有趣的评论的启发,我想出了其他可以说明文章要点的可视化示例,而没有遭受上面列出的问题。当我用 Python 制作这些图时,它们在美学意义上(字体、颜色等)还不能印刷。),但它们传达了我提出的主要设计思想。如果你愿意,你也可以查看代码

数据和故事

首先,为了理解图中的主要信息,我看了看《经济学人》中的故事以及Elsevier的原始报告。虽然最初的报告(也可以使用一些图形改造)详细分析了科学和技术许多方面的性别失衡,但这篇短得多的文章专注于一个简单的信息,即在所有调查的领域和国家,男性仍然主导着科学出版。两种文本中的照明都非常依赖于水平条形图,其中一行对应一个国家。

Elsevier report: an endless forest of seemingly identical violet-green bar plots.

《经济学人》的总结很好地抓住了全局,并立即指出了可视化该数据集的明显问题:所有这些数据看起来都相似。因为大多数时候,无论哪个国家,哪个科学学科,男性始终比女性多得多。这意味着,当我们试图按原样绘制数据时,会有很多:

  • 视觉冗余 —绝大部分空间都用于一个类别,“男人”,例如以空白空间或充满单一颜色的大区域的形式。这有一个危险的后果:为了节省空间和墨水,人们很容易在印刷版中削减轴的限制,正如《经济学人》的原始插图中所发生的那样,女性比例从 0%上升到 60%,扭曲了数据的视觉解释
  • 令人困惑的重复——因为我们展示了许多独立的图,但其中的数据看起来几乎相同

因此,在为摘要文章制作插图时,我们可以通过以下方式获得更清晰的图像:

  • 聚合学科 —通过识别诸如“STEM”、“生命科学”、“社会科学”、“专利申请”等集群,我们观察数据中的自然分组
  • 汇总国家 —这是一个棘手的问题,因为我们直觉上期望看到国家之间的差异,虽然我理解提供证据或惊喜的论点,但我仍然主张汇总。首先,我们不需要在视觉上展示一切——我们完全可以在文本中写下“性别最平等的国家是葡萄牙和巴西”。第二,基础数据实际上并不清楚国家类别的区别。我认为,总的来说,将这些伪国家聚集在一起比提供一个误导性的区分要好
  • 宁滨实际值——因为对于普通观众来说,21%和 23%之间的差异真的很重要吗?重要的是 20%和 50%之间的区别
  • 单独的图或插页中对聚合趋势的有趣异常值进行评论

这种复杂性的降低可能会立即解决原始情节中存在的“数据过多”问题。另一个更重要的问题是为了节省空间而削减 x 轴的限制,这个问题可以通过与编辑的仔细协商来解决。

但是,我们能在不降低复杂性的情况下找到更清晰的数据表示吗?我们来实验一下!

提议 1:热图

在第一个建议中,我抛弃了条形图的概念,取而代之的是热图,这使得数据点之间的模式更加明显。在这里,我没有将值编码为长度,而是使用颜色及其强度,并将我的数据呈现为颜色矩阵,其中科学学科对应于行,而被大陆分隔的国家对应于列。

颜色编码。我最初想遵循 Elsevier 文章中使用的颜色编码,但我发现它给人的印象是错误的。爱思唯尔将绿色用于男性,绿色最琐碎的含义是“正确”,因此这里有 95%的绿色瓷砖表明绿色值实际上是理想值。相反,我选择了灰色,并武断地将 40%设定为一个阈值,在这个阈值上,我开始使用蓝色来突出性别最平等的国家和学科。我发现 40%是视觉冲击和数据解读之间的一个很好的折中。我还使用颜色以 10%的步长做宁滨,但是如果有人真的想知道确切的数字,它仍然在图上。

几何。通过旋转初始几何图形,将学科排列成行,我更强调学科因素,而不是地理因素。此外,因为这些国家是按洲排列的,所以矛盾的是更容易看出它们中的哪一个是突出的。

提议 2:华夫饼

这里我没有使用条形或颜色,而是使用了华夫饼干图来说明性别比例。学科之间的区别不像热图中那样明显,但对科学领域男女比例的总体印象更相关。我发现在一个华夫饼干中有 16 块瓷砖不仅是精确度和通用性之间的一个很好的折衷,而且给出了 2 个研究组的单个华夫饼干大小。这种表现的缺点是它会触发赫尔曼网格错觉

色彩。我在这里纠结了一会儿。我发现同等强度的颜色传达出的一个群体优于另一个群体的印象不如不同强度的颜色好。我满足于给男人深蓝色,给女人浅绿色,这强调了男人仍然是大多数。我发现颠倒颜色——女性深蓝色,男性浅绿色——给人太多进度条的印象,在进度条上,浅色的瓷砖只是可以拿走的空瓷砖。但这也是一个品味问题。

Different waffle colorings.

提议 3:重塑酒吧情节

在这里,最初我想画一个有两个不同颜色区域的图形,一个区域“侵犯”了另一个区域,超出了平等的边界,但结果是,嗯,超级丑:

There is only that much ugliness a plt.axes() can take

所以我放弃了最初的想法,取而代之的是一个柱状图,但是重新发明了。

我再次把重点放在作为组织类别的学科上,并使用分散在一个学科中的各种形状的标记对不同的国家进行编码。为了更直观,我计算了各国的平均值,并画了一个条形图作为散点图的背景。关于特定国家的信息现在不太容易获得(如果图表是交互式的,标记选择得更仔细会更好),但离群值仍然很容易识别。

我决定使用竖线,并对两种性别(不仅仅是女性)相对应的部分进行着色,这样就能唤起一种重力的直觉,并在地块的上半部分放置一些重物,推动绿色和橙色区域之间的边界。

结论

对我来说,这是一次有趣且富有创造性的旅程,我希望我的结果能给你带来灵感!主要的信息是,条形图很容易想到,但是还有一大堆其他类型的图可以尝试。请在评论中告诉我你的想法。

一方面,科学家在国际上流动性极大,另一方面,要找出哪一个是可能影响科学界女性与男性比例的主导因素并不容易:是原籍国,还是现居国?报告本身的数据在给国家贴标签方面也不完美。原始数据来自 Scopus,性别归因于基于名字的科学家的名字(前提是他们输入完整的名字,而不仅仅是名字的首字母),国家被设置为由给定个人的第一篇论文的从属关系决定(遵循的逻辑是,人们主要在他们的原籍国发表他们的第一篇论文——这本身是一个有争议的假设,但不是完全不合理的)。但这意味着标有“法国”的柱状图并没有真正反映在法国工作的科学团体中的性别平衡,读者可能会如何解读它。相反,它告诉我们在法国发表第一篇论文的科学家中有多少人,无论他们的文化背景或目前的关系如何。

超越导数——次导数

原文:https://towardsdatascience.com/beyond-the-derivative-subderivatives-1c4e5bf20679?source=collection_archive---------23-----------------------

机器学习技术通常依赖于可微函数,但实际情况很少如此。我们能做些什么呢?

Not every function is so nice!

介绍

如果你已经克服了理解机器学习的最初几个障碍,那么你很可能听说过一种被称为梯度下降的技术。

当谈到最小化一个函数 f 时,我们可以用下面的规则更新我们对最小值 x 的猜测:

Old faithful (gradient descent).

这一切都很好,但往往有一个重要的细节被掩盖了。我们的函数 f 需要可微,这意味着我们可以计算它在所有可能的点 x 的导数。

停下来问自己:这是我们真的可以掩盖的细节吗?我是说,大多数函数都是可微的吗?退一步说,所有可能函数的空间是巨大的,你可能在街上遇到的典型函数可能是相当讨厌的。事实上,几乎每个函数在一个点上都是不可微的!这仍然是即使你限制为连续函数的情况。

损失函数的可微性

如果你有足够的勇气点击那个链接,那么你会很快意识到我们正在进入技术领域。但这不是重点——希望我们能在这里阐明这一点。

记住,在机器学习中,正在优化的函数通常是损失函数。我们来看一个简单的损失函数:绝对值函数。

f(x) = |x|, absolutely.

如果你已经有一段时间没学微积分了,那么记住导数的一种解释是该点切线的斜率。

绝对值函数是可微的函数的典型例子,特别是在点 x = 0 处。

如果你看看其他损失函数,你可能会惊讶地发现它们也是不可微的。那么是什么原因呢?

技术性的是,对于机器学习问题,我们真的只需要我们的损失函数在几乎每一点都是可微的。这实际上是一个技术术语,它被称为几乎处处可微。

但这仍然只是一个小小的修正。如果我们想把像梯度下降这样的东西推广到不可微的函数上呢?

定义次导数

如果你回头看看绝对值函数,你可以给出一个关于为什么它在 x = 0 处不可微的论点,因为在那一点没有唯一的切线斜率。

把在 x = 0 处的函数想象成一种尖边,然后你可以想象一大串不同斜率的线接触原点。

Play with this graph here!

让我们从切线斜率的概念出发,推广导数的概念。

次导数是导数的延伸。与导数不同,次导数不仅仅是一个数字,而是一个点的集合。形式上,一个点上的次导数是位于图中该点下的所有切线的斜率集合。

看一看。在下图中,点 x_0 处的函数(蓝色)至少有两条切线(红色)位于图形下方。这些切线的斜率构成了次导数。

The subderivative at a point is all slopes that lie beneath the graph.

它所要求的只是函数是凸的,这意味着在图上的任意两点之间画一条线保持在函数的同一侧。

为了把我们刚才所说的放到一个正式的定义中,我们可以把在一个点上的次导数(或次梯度)定义为:

这里使用了用于偏导数的相同符号,但是在这个上下文中,它用于表示点的集合,而不仅仅是单个值。

含义

那么现在我们已经定义了什么是次梯度,我们能继续修改梯度下降来得到…次梯度下降吗?事实上,我们可以!

有许多方法使用次导数作为导数的替代,我不会阻止你自己去寻找这些方法。

随着机器学习技术变得越来越复杂,它们将更有可能依赖于不可微的损失函数和优化。因为我们仍然想解决这些问题,所以我们有可行的技术来处理这些情况变得更加重要。

如果你想了解更多关于次梯度的知识,这里有很多关于它的好的幻灯片。这将是相当技术性的,但这不应该阻止你浏览或至少看漂亮的图片和方程!

一如既往,欢迎在下方评论联系!过去我真的很高兴收到人们的来信,这有助于我聚焦未来的文章!

超越歌词:音乐和数据可视化的交集

原文:https://towardsdatascience.com/beyond-the-lyrics-the-intersection-of-music-and-data-visualization-4a71039f447c?source=collection_archive---------26-----------------------

使用 Spotify API 和 Tableau 对歌词进行情感分析

关于数据科学,我最喜欢的事情之一是偶然发现一些最酷、最强大的工具,这些工具能让我立即做一些酷而强大的事情。我最近创建了一个 Spotify 开发者账户,学习了如何抓取歌词,了解了情感分析、词云以及其他 NLP 概念,并自学了如何使用一款名为 Tableau 的出色的交互式数据可视化软件。最重要的是,我有一个长长的清单,上面列有我接下来要处理的进一步的项目。

这两篇媒体文章帮助我朝着一个富有成效、不断向前发展的方向前进,如果我不给予它们信任,那将是我的失职。第一个名为“通过 Python 提取你最喜欢的艺术家的 Spotify 数据”,由 Rare Loot 提供。第二个叫做“Tableau 中的单词云:快速和简单”,作者是我最喜欢的数据科学作者之一 Parul Pandey。

[## 通过 Python 提取您最喜欢的艺术家的 Spotify 数据

Spotify 是世界上最受欢迎的流媒体平台之一。他们也有一个 API 供开发者使用…

medium.com](https://medium.com/@RareLoot/extracting-spotify-data-on-your-favourite-artist-via-python-d58bc92a4330) [## Tableau 中的单词云:快速简单。

使用 Tableau 轻松创建单词云。

towardsdatascience.com](/word-clouds-in-tableau-quick-easy-e71519cf507a)

创建雷达图,根据音频特征比较播放列表

在我从 Spotify 检索到我的客户 id 和客户秘密后,我想处理一个迷你项目来熟悉 API。我快速浏览了 Spotify 开发者发现页面,从社区成员已经开发的应用中获得灵感。我个人最喜欢的是播放列表艺术家探索

然后我读了一篇关于这个神秘的名为 spotipy 的库的文章,有了这样一个完美的名字,你可能会猜到我的下一步是什么……是的,一个不错的老 pip 安装。spotipy 库使您能够提取音频特征(例如,声音、能量、速度、舞蹈性、活力、响度、乐器性、语速、效价等。)来自任何给定的歌曲。这些词中的一些听起来可能是编造的(确实是),但这些音频功能实际上可以告诉你关于一首歌的很多信息,我很快就会知道。

所以唉,我开始摆弄一些代码。我从中获得灵感的第一篇嵌入式媒体文章向读者展示了如何提取你最喜欢的 Spotify 艺术家的特征数据。我想通过将一种音乐风格的内聚播放列表与另一种完全不同的音乐风格的内聚播放列表并列显示来偏离这个用例。我决定对比一个我有时无耻地听的悲伤播放列表(叫做“sad”),一个我 18 岁的弟弟做的最绝对不悲伤的播放列表(叫做“Hype Stuff”),一个我学习时听的器乐播放列表(叫做“academia”)。

设置如下所示:

import spotipy
import numpyusername = 'YOUR-SPOTIFY-USERNAME'
client_id  = 'YOUR-CLIENT-ID'
client_secret = 'YOUR-CLIENT-SECRET'
client_credentials_manager = SpotifyClientCredentials(client_id=client_id, client_secret=client_secret)

接下来,我为三个播放列表中的每一个制作了一个 Spotify URIs 列表,并提取了每首歌曲的音频特征,将它们放在一个字典中,播放列表名称作为键,特征数据列表作为值。如果你有兴趣看代码,看看下面的要点。

现在,有趣的是。下面是获取这些特征值并制作雷达图的代码。

rap music vs. sad music vs. instrumental music, all on one radar graph

如果你对 spotipy 库如何分析音乐以提取特征感到好奇,请访问此链接了解更多关于这些特征的信息。我最终只在我的雷达图上包括了 7 个特征,因为我对活跃度、响度或受欢迎程度不感兴趣。活跃度和响度不能告诉我任何关于音乐的深刻见解,流行度太主观了,无法推断出任何意义。

我认为除了化合价和能量,所有的特征都是不言自明的。配价描述了一首曲目所传达的音乐积极性。高价曲目听起来更积极(例如,快乐、愉快、欣快),而低价曲目听起来更消极(例如,悲伤、沮丧、愤怒)。对 rap 播放列表的价值要有所保留,因为我不确定这个功能更依赖于抒情内容还是节奏。能量是一种从 0.0 到 1.0 的度量,代表强度和活动的感知度量。通常,高能轨道感觉起来很快,很响,很嘈杂。例如,死亡金属具有高能量,而巴赫前奏曲在音阶上得分较低。很准确,对吧?这些描述可以很好地检查您生成的任何数据可视化。

上面的雷达图允许我们对每个播放列表的关键特征进行瞬间推断。例如,说唱音乐的节奏最快,说话最多,活力和舞蹈性得分最高。你可能想坐下来看下一个观察:器乐播放列表有最高的器乐分数,悲伤播放列表有最高的音响分数。尽管图表告诉我们人们可以很容易地对被检查的播放列表做出什么样的假设,但是想象一下研究你的“每周发现”播放列表是如何随着时间的推移而变化的,或者其他一些稍微模糊的事情。雷达图不仅强大,而且是一种艺术形式。成功制作它们的过程会让你觉得自己是一个超级老练的程序员。当您觉得已经从类似下面代码片段的 matplotlib 基础中毕业时,您应该继续学习雷达图。

import matplotlib.pyplot as plt
x = list(range(10))
y = list(range(10))
plt.plot(x, y)

当执行一个从概念到可视化的项目时,Python 和 matplotlib 一直是我的面包和黄油,但我渴望一些与我的技能相关的新东西,一些需要学习、黑客和修补才能达到最终目标的东西。进入 Tableau。我在 LinkedIn 上看到过无数的招聘信息,称 drop Tableau 是一项理想的资格,但我从来不知道它是什么,也不知道它有什么了不起。所以我做了一些功课,了解了它的功能。我得出的结论是,它最适合我的需求,因为它能让我更好地控制我的数据可视化,我认为这是这个项目最重要的方面。

最近在我的大数据课上学习了自然语言处理(NLP)技术后,我想看看我是否能从歌词中获得一些见解。我找到了一个名为 PyLyrics 的图书馆,只要你知道歌曲名和歌手,你就可以从任何一首流行歌曲中找到歌词。然后,我重新利用了一个旧脚本,将歌词整理成一个有用的单词列表。

用 Tableau 研究同一艺术家不同专辑的抒情内容

我想分析同一位艺术家不同专辑的抒情内容。我对研究蒙福之子乐团特别感兴趣,因为我认为他们的每张专辑都有一个非常集中的主题。此外,毫无疑问,蒙福之子乐团一直是我父亲最喜欢的乐队,所以我从小就学会了如何演奏“空气班卓琴”,并将他们的音乐放在心里。对于不知道的人来说,他们是一支英国民谣摇滚乐队,声音非常鲜明。主唱马库斯·芒福德(Marcus Mumford)经常被描述为拥有来自深深的激情和情感的严肃而沙哑的嗓音。

A photo of Mumford & Sons performing live and Marcus Mumford rocking out on the guitar

乐队的专辑 Wilder Mind 收录了名为“狼”、“怪物”、“蛇眼”和“宽肩野兽”的歌曲,但人们可能会说,他们所有歌词的核心都是这个强有力的爱情主题。另一方面,他们最近的专辑 Delta ,表达了空虚和渴望。它的特点是歌曲名为“指路明灯”,“画你”,“如果我说”,“女人”,“心爱的”,“溜走”。仅仅是歌名的并列就足以让我全力投入这个情感分析项目。我着手制作一个歌词的可视化,展示两张专辑之间的鲜明对比。

单词云是一种快速了解文本语料库中使用的单词的有趣方式,所以我做的第一件事是筛选歌词,并进行非常严格的数据清理。数据清理过程包括以下步骤:

  1. 将所有单词设为小写
  2. 删除停用词(注意:停用词是指“the”、“is”、“are”等词。).
  3. 删除标点符号,特别是带括号、省略号、逗号、句号、感叹号等的单词。
  4. 删除号码
  5. 删除长度小于 2 的单词,因为空字符串和单字符单词不应出现在语料库中

Here is the code you will need to clean any given corpus before making a word cloud

一旦完成,我就根据单词是从哪个专辑中提取的,制作了一个语料库词典(“语料库”的复数)。我使用一个计数器对象来获取每个语料库中每个单词的频率,然后将数据写入一个逗号分隔值(CSV)文件,稍后我会将该文件导入 Tableau。CSV 文件是根据下面提供的示意图构建的。

Schematic of column / variable layout of the CSV file that was imported into Tableau

当我在 Jupyter 笔记本上准备好所有可用的数据时,我使用 Python wordcloud 库为每个按相册分组的语料库生成了一个快速的单词云。你可以在下面看到结果。有趣的是,“爱”和“心”这两个词不难在下图的 4 个支线剧情中找到。每张专辑都有自己独特的高频词,非常有趣,让我们能够推断主题。

我仍然希望对我的单词云有更多的控制。我希望能够控制每个单词的颜色和大小——如果我真的想疯狂的话,甚至可以控制形状。所以我在我的桌面上启动了 Tableau,并摆弄它,直到我产生了一个我满意的可视化效果。如果你对我做了什么感到好奇,可以看看下面的 GIF。

Step-by-stop process of producing a word cloud in Tableau

Final result for Mumford & Sons lyrical word cloud by album

在上面的单词云中,可以看到各种蒙福之子乐团歌词中所有最常见的单词。每个词都被指定了一种颜色,这种颜色与歌词所属的专辑相关联(参见右侧的图例)。关于这个图有趣的一点是,最突出的词是“爱”和“心”,如果你观察足够长的时间,你可能会发现这些词多次出现。Wilder Mind 专辑包含了许多怪物和野兽的图像,像“眼睛”和“思想”这样的词跃然眼前。 Delta ,另一方面,包含像“永远”、“光”和“永恒”这样的词。这种通过简单观察哪些词突出来进行的内在情感分析表明,像词云这样的工具可以非常有力地帮助我们了解音乐。此外,研究的迫切需要——研究同一位艺术家不同专辑中的主题——可以用实际的歌词数据来探索,而不仅仅是音乐行业中知识渊博的专家。

使用 Tableau 基于情感分数比较流派

上一个项目涉及制作一个可视化的图像,以更有见地的方式检查歌词,但我意识到 CSV 文件实际上可以保存更多的变量,进一步告诉我们一些关于歌词的信息。例如,如果我们使用情感分析来研究给定歌曲子集中的词有多积极或消极呢?然后我们可以潜在地使用机器学习来根据歌曲的情感分布将歌曲分类成一个流派。好吧,我们先别得意忘形,但这一切都很有希望。

为了建立案例研究,我查看了两个流行的 Spotify 播放列表:Mood Booster 和朋克摇滚经典。我选择这两个播放列表没有别的原因,只是因为在我看来,它们在情感上截然相反。

Where the data actually comes from

流行音乐通常是关于爱情、金钱、聚会等的。,所以我们可以说歌词触及的话题通常比朋克摇滚乐轻松。我们可以得出的另一个有趣的对比是音乐创作的时间段。两个不同播放列表的歌曲集之间平均有十年的差距,所以这可能与我们将在可视化中看到的内容有关。

除了一个新元素:afinn 分数之外,我按照与前一个子项目几乎相同的过程收集数据。由 Finn RUP Nielsen 开发的 afinn 库提供了一种基于单词列表的 Python 情感分析方法。前提是,它将所有单词放在光谱的某个位置,其中-5 是可能存在的带负电最多的单词,0 是中性的,+5 是可能带正电最多的单词。如果你好奇,可以使用这个网络应用来感受一下它是如何工作的!

为了产生我为这个项目设想的 Tableau 可视化效果,我需要在我的 CSV 文件中增加一列(F4)。下面是新数据设置的示意图。请注意,列 1 (F1)现在包含流派类型,而不是专辑名称。然而,其他的一切都是完全一样的,所有相同的清理都必须完成,以获得不可避免地会填充新单词云的单词。

Schematic of column / variable layout of the CSV file that was imported into Tableau

既然你已经对单词云以及如何制作单词云有了很好的理解,我就不再赘述 Tableau 中的相同步骤了。让我们看看视觉效果吧!

Side-by-side comparison of word clouds for different genres, colored by sentiment score

如上图所示,与“情绪助推器”播放列表相比,“朋克摇滚经典”播放列表中的负面词汇明显更多。在“情绪助推器”播放列表中唯一高频出现的负面词是“地狱”一词,情绪得分为-4.0。显然,它也出现在许多朋克摇滚歌曲的歌词中。也就是说,朋克摇滚歌曲不纯粹是焦虑或充满负面情绪。歌词中提到了“爱”、“希望”、“想要”和“希望”。不过,总的来说,分析这两个词云非常有趣,尤其是在过滤掉频率小于 10 的词之后。

我希望我能解决的一个很大的限制是必须产生两个独立的单词云并并排比较它们。我的目标是有一个单词云,并根据两个不同的变量给单词着色:一个是流派(存储在 F1 中),另一个是 afinn 分数(存储在 F4)。我从来都不知道如何为一个图制作两种不同的色谱,但这仅仅是我制作 Tableau 的一个起点。

如何在家里尝试这个

如果你有兴趣复制这些项目中的任何一个,或者将这些工具提升到一个新的水平,所有的代码都可以在我的 GitHub 资源库中找到,关于这个项目:https://github.com/sejaldua/lyrical-sentiment-analysis。代码在名为 public_code.ipynb 的 Jupyter 笔记本中进行了清晰的组织和注释。如果您有任何问题,请随时通过 sejaldua@gmail.com与我联系。

结束语

如果你从这篇文章中学到了什么,我希望那就是从数据科学的角度研究音乐是一项无限的努力。还有音频特征提取、抒情情感分析、聆听行为等等,都在等待检验。还有许多不同的数据镜头和技术可以让你探索音乐。Spotify API 是一个真正的幸事,Tableau 使数据可视化看起来比你我都知道的要干净和容易得多。凡是你感兴趣的,就开始玩,然后用你的发现讲个故事。感谢您阅读我的第一篇文章!

如果你有兴趣了解更多我的作品,我欢迎你关注我的网站(【https://sejaldua.com)和/或 GitHub()。

偏见和算法公平

原文:https://towardsdatascience.com/bias-and-algorithmic-fairness-10f0805edc2b?source=collection_archive---------7-----------------------

现代商业领袖在由数据统治的全新世界中的新责任。

随着数据科学沿着炒作周期前进,并作为一项业务功能变得成熟,该学科面临的挑战也在增加。

过去几年,数据科学的问题陈述从“我们浪费了 80%的时间来准备数据”,到“生产部署是数据科学最困难的部分”,再到“缺乏可衡量的业务影响”。

但是,随着商业数据科学符合业务功能并克服早期问题,我们面临着新的挑战性问题陈述:

  • 数据伦理,
  • 模型可解释性和问责制,
  • 算法公平性

虽然数据科学家和商业领袖可以在很大程度上依赖技术进步来解决第一轮数据科学初期问题,但希望技术独自解决这些新挑战是错误的。

我个人承认,在如何使用数据方面,我天真了太久,在如何解决这个问题上,我被误导了。我不能一个人进去?

这不是一个学术上和法律上的全面讨论,而是我个人的经历和旅程的记录。为了更详细地了解人工智能中公平和问责的法律含义,我建议跟随桑德拉·沃希特博士并阅读,例如,“合理推理的权利:重新思考大数据和人工智能时代的数据保护法

黑盒没了吗?

我经历了对数据科学作用的理解的第一次挑战,当时逐渐消退的宣传再也不能为机器学习黑盒开脱。模型可解释性从一个意想不到的方向进入了我的思维:我的涉众。利益相关者比大多数数据科学家更关心模型的详细工作原理!这并不意味着我没有意识到黑匣子,但我是从降低风险的心态来处理它的。(交叉验证、对模型输入和输出的广泛测试、日志记录和监控、对模型使用的限制、诚信、快速失败和再次尝试……)

我过去和现在都认为数据科学是生产中的实验。虽然我以前认为黑盒只是需要安全措施来确保预测有意义,但我现在明白了为什么一些模型的可解释性不仅是为了问责,也是为了对预测有意义有实际信心。为了限制 ML 黑盒的人工愚蠢,我们需要模型可解释性来定义何时对表现良好的输入数据进行评分是安全的,何时最好不要对之前未看到的输入数据进行评分。

对于决策空间的插值,最大似然法是非常适合和强大的。不幸的是,使用 ML 将决策推断到新的和看不见的数据的不安全领域太容易和诱人了,这些数据从来不是模型训练和模型验证的一部分。

https://xkcd.com/605/, (CC BY-NC 2.5)

虽然 ML 黑箱在我的日常工作中只是一个灰箱,但模型可解释性给我提供了所需的信心,并提高了我们的能力约束人为的愚蠢,将我们的模型保持在充分理解的安全措施内。这意味着有时不提供分数更好。

Scikit

实现这一点的一个非常简单但非常强大的方法是,在你的训练数据上拟合一个独立的高斯混合模型,作为你的决策空间的置信边界。如果模型输入不在 GMM 的置信边界内,就不要返回模型输出。

目前,一方面,我希望数据科学领域的科学和技术进步将进一步解决模型可解释性问题,另一方面,作为一名数据科学家,我很乐意承担模型可解释性的责任。

偏见

虽然模型可解释性是商业数据科学功能本身所拥有的责任,但是数据伦理和算法公平不能仅仅由数据科学拥有!为什么?因为公平的模型是对精确模型的权衡,达到这种平衡意味着高级领导的责任。希望当你看到文章结尾的总结时,这开始变得更有意义。

事实是,任何从人类行为中产生或导出的数据点,本质上都受到我们人类似乎无穷无尽的偏见的影响。仅举几个例子:

群体内偏好和群体外消极:对我们自己社会群体中的人的偏好,而不是对惩罚或给群体外的人施加负担的偏好。在偏见和歧视中起重要作用的偏见。

基本归因错误:当我们倾向于将某人的行为归因于其性格的内在品质而非情境背景时。

负面偏见:当我们强调负面经历多于正面经历,这对社会判断和印象形成有重要影响。

刻板印象:当我们期望一个群体中的某个成员具有某些特征,却没有这个人的实际信息。

从众效应:当我们做或相信一些事情,因为许多其他人也这样做。

偏见盲点:我们看不到自己个人偏见的倾向。

我们所有的数据都是有偏见的,因为这个世界是有偏见的。

修正世界上的偏见超出了数据科学家的工作范围。然而,不要用 ML 模型来加强现有的偏见是一个数学问题,并且很快从纯粹的道德义务转变为现代数据科学家的工作要求。

解决数据科学中的偏见是一个极其复杂的话题,最重要的是,没有通用的解决方案或灵丹妙药。在任何数据科学家能够致力于减少偏差之前,我们需要通过参考以下公平树来定义我们业务问题环境中的公平:

The Fairness Tree, Adapted from http://www.datasciencepublicpolicy.org/projects/aequitas/

根据您的业务问题导航公平树绝非易事。举个例子(改编自这里的)假设你想设计一个 ML 系统来处理抵押贷款申请并且只有一小部分申请是由女性提出的。

  1. 群体无意识选择:我们在申请过程中完全忽略性别信息。因为贷方可能批准的数量有限,所以这些批准会根据客观的、性别中立的标准授予最有资格的个人。但是,删除性别和性别代理信息并不能解决历史偏见,通常也不是一个非常有效的减轻偏见的过程,正如我们将在下面美国人口普查数据的实例中看到的那样。
  2. 调整后的群体阈值:由于历史偏见使得女性看起来不如男性值得贷款,例如工作经历和育儿责任,我们对不同群体使用不同的审批阈值。
  3. 人口统计均等:批准率应反映集团申请的百分比。但这不会考虑抵押贷款违约的风险。
  4. 机会均等:有贷款能力的男女获得抵押贷款的比例相同。这似乎符合商业目标的按揭贷款,似乎是公平的。“有资格获得理想结果的个人应该有平等的机会被正确归类为这一结果。”(莫里茨·哈特)
  5. 精准平价:不发放贷款会对个人产生非常负面的影响。在机会均等的情况下,两个群体都有真正的正均等。但是,如果该模型在女性不偿还贷款(假阴性)方面的错误率是男性的两倍,那么该模型拒绝的有贷款资格的女性将是男性的两倍。因此,应该对模型进行调整,以使两组的批准和拒绝总数中模型出错的百分比相同。精确奇偶校验也是公平树所建议的(错误>惩罚性>小干预量)。

算法公平

确定公平的合适定义只是第一步。下一步是选择合适的偏差缓解策略。同样,减少偏见是一个复杂的话题,也没有通用的方法或灵丹妙药。下图显示了 IBM 的 AIF360 工具包中 3 个主要类别的缓解策略和现有实现:

IBM 的 trusted AI 是了解更多详情的绝佳资源:https://www . research . IBM . com/artificial-intelligence/trusted-AI/

TensorFlow 2.0 的对抗性去偏——一个例子

为了强调有偏见数据的挑战以及数据科学家可以做些什么,我们来看一下 1994 年美国人口普查收入数据集。

目标是一个分类模型来预测一个人的年收入是否超过 5 万美元。这个问题从根本上来说是有偏见的(性别薪酬差距、歧视等)。)且数据集包含敏感数据:种族性别。因此,我们从模型输入中移除敏感数据,试图建立一个组不知道的分类器。下图显示了我们用于解决问题的神经网络架构:

该架构使用一个编码器神经网络来创建一个共享数据嵌入,该数据嵌入为 3 个分类神经网络提供数据,目标是预测个人的工资、性别和种族。

在第一轮中,我们而不是使用任何对抗性梯度,并将模型训练为标准多头分类器,以查看我们尝试的群体无意识有多成功。下图显示了 20 个时期后的模型性能:

Epoch 20: Loss: 1.357 salary_accuracy: 0.829 sex_accuracy: 0.825 race_accuracy: 0.830

显然,删除敏感数据并不会让我们的模型组不知情。我们可以从剩下的数据中很好地预测性别和种族。这一点也不奇怪,因为我们的问题也是历史偏见,敏感数据与所有其他特征相关,例如教育、职业选择等。

我们将使用对抗性神经网络从共享数据嵌入中删除任何种族或性别相关信息。TensorFlow 2.0 的定制训练循环训练 4 个时期的 NN 头,以适应当前的共享数据嵌入,随后是编码器的对抗训练,使用来自性别和种族分类器的负梯度:

3 个神经网络头的目标是尽可能准确地对个人进行分类,而编码器的目标是提高工资分类器的准确性,同时消除性别和种族的可预测性

让事情变得更复杂的是,在我们对公平的定义中,我们还必须解决数据集中不同群体的严重不平衡。不平衡数据是现实世界数据集中的一个常见挑战,我们解决了模型的损失和准确性计算中的不平衡。这就是为什么我们使用与我们的数据批次不平衡相对应的自定义权重TF . nn . weighted _ cross _ entropy _ with _ logits()函数在神经网络输出层中进行线性激活以检索逻辑。

模型的对抗性训练的结果看起来如下:

我们成功地从编码器产生的共享数据嵌入中去除了种族和性别的可预测性。但由于世界存在偏见,薪资分类的准确性也受到了严重影响,尤其是对高收入者的可预测性。我想这没什么好惊讶的。

摘要和数据伦理

数据科学有能力改变业务,在降低 B2B 的风险和成本方面大有作为,并在 B2C 中提供创新的新产品。但是数据科学应用伴随着巨大的责任。我们必须不惜一切代价避免数据科学以不可解释和不可解释的方式自动强化偏见。****

这篇文章有望阐明一些重要的观点:

  • 公平和减少偏见是一个复杂的话题,我当然不是专家
  • 在我们生活的这个充满偏见的世界里,减少偏见会影响模型的准确性,我们会看到准确性与公平性之间的权衡困境。
  • 从模型输入中移除敏感数据并不会使您的模型组不知情或不公平。
  • 我们必须首先记录敏感数据,以便在模型的对抗性去偏中使用它。这对于解释数据保护和数据伦理“使用与用户需求成比例的数据”具有重要意义。数据保护法对个人数据非常明确,对个人可识别的敏感数据更为严格。不记录此类数据似乎是最简单、最安全的合规选择,而且表面上似乎是通过群体意识不到来促进公平。但是我们在上面的美国人口普查数据的例子中已经看到这是错误的!它可能符合数据保护法,但它没有实现公平。虽然数据保护促使企业不收集敏感数据,但道德数据使用实际上促使企业投资于安全合规的敏感数据收集。****

这就是高级商业领袖再次出现的原因,他必须做出决定并承担责任:

  • 模型的准确性与公平性,对收入有影响的决策
  • 避免收集敏感数据以实现理想的数据保护,而不是收集敏感信息以在公平的去偏见模型中合乎道德地使用数据,这是一个具有风险和成本影响的决策(例如,数据泄露、安全数据基础架构等)。)

Jan 是公司数据转型方面的成功思想领袖和顾问,拥有将数据科学大规模应用于商业生产的记录。他最近被 dataIQ 评为英国 100 位最具影响力的数据和分析从业者之一。

****在 LinkedIn 上连接:https://www.linkedin.com/in/janteichmann/

****阅读其他文章:https://medium.com/@jan.teichmann

线性模型中的偏差和方差

原文:https://towardsdatascience.com/bias-and-variance-in-linear-models-e772546e0c30?source=collection_archive---------7-----------------------

线性模型的偏差和方差权衡

我相信每个人过去都见过这个图表:

First figure in Scott Fortmann-Roe’s Understanding the Bias-Variance Tradeoff.

了解偏差-方差权衡详细介绍了权衡和误差,我强烈推荐。上图是帖子上的第一个图,显示了多个模型在不同偏差和方差误差下的预测。靶心是我们想要预测的真实值,蓝点是模型实际预测的值。在这篇文章中,我想尝试并直观地展示线性模型中偏差和方差的权衡。

为什么是线性模型?

因为它们很容易理解,并且提供了一种非常简单的方法来控制这些误差——通过正则化。众所周知,与非线性模型相比,普通最小二乘(OLS)回归可以给出方差较低的无偏结果。 (OLS 带 L2 点球)和拉索 (OLS 带 L1 点球)给出了有偏差的结果,与 OLS 相比方差低得多。惩罚程度由正则化系数λ控制。这反过来控制两个误差,我们将在下面看到。Lasso 实际上是一个特例,因为它积极地将系数估计值推至零,但有助于保持事物的前瞻性。你可以在这里阅读更多关于正规化的内容。

程序

我将坚持使用 Scott 的文章中用来从概念上描述错误的方法。我在这里任意挑选所有固定的数字。

  1. y = α+ βx + ϵ 模拟 500 个数据点,其中 ϵ ~ N(0,8),x ~ U(-2,2),α = 2β = 3。
  2. 重复第一步 1000 次,收集所有数据集。
  3. 对于每个集合,用固定的λ拟合 OLS、脊和套索模型,以预测 x = 3 时的 y预期预测应该是 2 + 3 x 3 = 11

现在我们有 3000 个(1000 个 OLS + 1000 个山脊+ 1000 个套索)预测,我们可以看看这些模型的真正“本质”。你可以在我的 GitHub 页面这里找到所有代码。

关于如何阅读情节的注释。我要你注意两件事。真实值(显示为黑色虚线)和模型的平均预测值(显示为相同颜色的虚线)之间的距离。这个距离就是模型的偏差(或偏差的平方)。与真实值(11)的大偏移是大偏差。
2。直方图的宽度是模型的方差。宽度越大,方差越大。

λ ~ 0

从一个非常小的λ值开始。这相当于没有罚分,因此我们可以预期在 OLS 对山脊和套索的结果是一样的。

情节没有给人惊喜。所有这三种分布都与真实值周围的平均值重叠。请注意分布是如何分散的。从 9 到 13 的预测中有很大的差异。

λ = 0.01

通过(非常)小的代价,很容易看到正则化的效果。分布已经向左移动(从平均值可以明显看出)。在山脊观察到一个小的偏差,在套索观察到一个相对较大的偏差。不清楚方差是否已经改变。

λ = 0.05

在λ = 0.05 时,Lasso 已经过于激进,偏差为 3 个单位。岭是足够接近,但看起来它有相同的方差。因此,对于这个数据来说,山脊还没有优势。

λ = 0.1

与上面几乎相似的结果。目前还很难注意到差异有任何变化。

λ = 0.5

更高的惩罚提供了一些(合理的)令人满意的线索。山脊上的偏差增加了近三个单位,但方差较小。Lasso 非常积极地推动β的零系数估计,导致结果偏差很大,但方差很小。

λ = 1 —一些好结果!

在这里,权衡显然已经改变了立场。以较高的偏置为代价,脊的方差较小。

λ = 5

为了让大家真正理解这一点,这里有一个非常大的惩罚。以更高的偏差为代价,脊上的方差很小。你可能永远不会需要这么大的罚款。但事实很清楚,较低的方差是以较高的偏差为代价的。

各种正则化值的偏差和方差

对一系列正则化值重复上述操作,可以得到清晰的图像。

  • 偏差计算为平均预测值和真实值之间的距离-真实值减去平均值(预测值)
  • 方差是平均预测值与平均值(预测值减去平均值(预测值))的平均偏差

这些图给出了相同的观察结果。OLS 的偏差最小,但方差最大。在λ = 0.2 左右(β变为 0,因此对于 x ) 的所有值,预测 y = α )后,山脊看起来像平滑移动,套索是恒定的。

理想分布

更好的数据选择可以给我们一个理想的预测抽样分布图。

由于重叠分布,山脊提供的优势在这里非常明显。岭给出一个稍有偏差的预测,但会给出一个比 OLS 更接近的预测。这才是脊的真正价值。一个小偏差,但更一致的预测。OLS 给出了一个公正的结果,但不是很一致。这很关键,OLS 给出了一个无偏的结果 平均,而不是一直 这就是线性模型中的偏差和方差权衡取

你可以在这里找到我在这篇文章中使用的所有代码。我建议您针对不同的λ值运行它,亲自查看变化。甚至可以在不同的数据集上使用它,看看是否可以看到一些重叠。如果你对这篇文章有任何建议,请随时和我打招呼。

我只想花点时间感谢让这篇文章成为可能的每一个人。一定要花点时间分享并表达你的感激之情。:)感谢阅读!

机器学习中的偏差和方差

原文:https://towardsdatascience.com/bias-and-variance-in-machine-learning-fbf17ac6f500?source=collection_archive---------22-----------------------

用简单的例子

这些概念对数据科学的理论和实践都很重要。他们也会出现在工作面试和学术考试中。

一个偏置预测器是偏心的,即它的预测始终是关闭的。不管它被训练得多好,它就是不明白。一般来说,这样的预测器对于手头的问题来说太简单了。不管数据有多丰富,它都不符合数据。

一个高方差预测器在某种意义上是相反的。当试图修正偏置和过度补偿时,通常会出现这种情况。人们已经从一个过于简单(即有偏见)的模型转向一个过于复杂(即方差很大)的模型。它过度拟合了数据。

介于这两者之间的是“最佳点”——最佳预测点。通常这不容易找到。数据科学家可以提供帮助。那是另一个故事了…

示例

输入是(比如说)华氏温度。我们希望它归类为舒适而非。训练集可以捕捉单个人或一组人的判断。

正如在别处提到的,这个问题不是线性可分的。简单地说,正确的解决方案应该表现为

Too low     -> uncomfortable    (U)
Just right  -> comfortable      (C)
Too high    -> uncomfortable    (U)

很明显,我们需要两个阈值,一个用于区分too lowjust right,一个用于区分just righttoo high

偏置

如果我们被限制只能使用一个怎么办?例如当我们的分类器只能够学习线性决策边界时。无论多么丰富的训练集都无济于事。我们就是无法得到中间预测的舒服和两个极端预测的不舒服

迈向更好的解决方案

如果我们有领域知识。也就是说,我们知道问题的特征。这里需要两个门槛。我们可以想出一个好的解决办法。

我们假设我们没有这样的领域知识。换句话说,我们需要一个通用的解决方案。

最近邻法

我们将考虑单个最近邻方法,因为它可以学习非线性决策边界,并且易于描述。我们将针对我们的问题来描述它。这有两个原因:(I)更清晰,以及(ii)便于讨论其变化。

Predict the temperature to be comfortable if at least half the people labeled it comfortable; uncomfortable if not.

现在假设算法在以下数据集上训练。每个温度都由 10 个人标注——C 或 U。

Temperature            10 … 45 50 55 60 … 80 … 100 ..
% who Labeled C         0 … 50 30 40 70 … 70 … 0

这个算法会把 45 标为 C,50 和 55 标为 U,60 标为 C,这好像不对。50 和 55 被认为不舒服。我们预计 45 也应该是。

这是怎么回事?我们只有 10 台贴标机。“他们有一半把 45 标成 C”是噪音,这是说得通的。随着更多的标记,这个分数可能会下降到 0.5 以下。

另一种看待这个问题的方式是,模型的预测具有很高的方差。这样想。想象一组不同的 10 个人来标记数据。在这套新设备上训练。45 岁时的预测不太可能是错误的。这太巧合了。也就是说,很可能在某个温度上预测是错误的。

因此,正如我们在示例中看到的,高方差预测器容易受到训练集中的噪声的影响。噪音不会重复出现。下次我们训练它时,它会在不同的输入上学习噪音。从一个用户的角度来看,他只是把它作为一个黑盒预测器,这些预测在训练运行中并不一致。

减少差异

那么我们如何从算法上解决这个问题?也就是说,不需要额外的标签(这会产生成本)。我们平滑数据,或者在预处理期间,或者作为算法的一部分。下面我们选择后者。我们用三个代替单个最近邻。为了简单起见,忽略计算效率的考虑,我们以下面的形式描述它:

For the input temperature T, get all the labelings of T, T-1, and T+1\. Predict T’s label to be the majority label among all these.

我们有一个更强大的分类器。每个预测将基于大小为 30 的标记样本——比我们从单个最近邻分类器获得的样本多三倍。与单阈值分类器相比,这个分类器的偏差更小。它本质上仍然能够学习非线性决策边界。

当然,与前两个分类器相比,这个新分类器的准确程度是一个经验问题。这涉及到对每个分类器的偏差和方差的综合影响的精确比较。简而言之,它需要一个合适的列车测试实证评估。那是另一个故事。

机器学习算法中的偏差

原文:https://towardsdatascience.com/bias-in-machine-learning-algorithms-f36ddc2514c0?source=collection_archive---------10-----------------------

算法何时出现偏差以及如何控制。

source: google

机器学习模型中的偏差

我参加了 Sharad Goyal 教授关于我们机器学习模型中各种类型的偏见的演讲,以及他最近在斯坦福计算政策实验室的一些工作的见解。这真的让我很兴奋,我做了一些研究,写了这篇关于机器学习偏见的笔记。让我们来谈谈偏见,以及为什么我们需要关心它。

机器学习中的偏差是什么?

偏见这个术语是由 Tom Mitchell 在 1980 年他的论文中首次提出的,这篇论文的标题是“学习归纳中对偏见的需要”。有偏差的想法是模型重视一些特征,以便更好地对具有各种其他属性的较大数据集进行概化。ML 中的偏差确实有助于我们更好地进行归纳,并使我们的模型对某些单个数据点不那么敏感。

对谁有影响?

但是,当我们对更一般化算法的假设产生系统性偏见的结果时,问题就出现了。很多时候,算法可能在某些特征上有偏差,即使我们忽略了我们的模型不需要加权的特征。他们通过从其他提供的特征中学习那些特征的潜在表示来做到这一点。

这是令人担忧的,因为机器学习模型已经开始在我们生活的各种关键决策中发挥更大的作用,例如;贷款申请、医疗诊断、信用卡欺诈检测、来自 CCTV 的可疑活动检测等。因此,机器学习中的偏见不仅会给出基于社会刻板印象和信仰的结果,还会在社会中放大它们。

如何识别和消除偏见?

你们中的许多人一定听说过亚马逊试图建立一个简历过滤工具,以及它最终是如何对女性产生偏见的。每个人都希望有一个能从数百份简历中筛选出五份简历的系统。当模型开始根据性别拒绝申请者时,它就出了问题,因此从未投入生产。另一个简单的例子可以在单词嵌入中看到。单词嵌入的引入对于各种自然语言理解问题来说是一场革命,因为它们能够捕捉单词之间的简单关系:

国王——男人+女人=王后

相同的词嵌入也捕捉到以下关系:

电脑程序员——男人+女人=家庭主妇

从数学上来说,这些单词嵌入可能没有错,并且正确地编码了数据,但是我们愿意在我们的机器学习算法中编码这些偏差吗?因此,我们需要消除这些偏差,使之成为我们算法中不可或缺的一部分。

对于研究机器学习各个方面的研究人员来说,这是一个非常活跃有趣的话题。我还查看了Sharad Goel教授和 James Zou 教授分别对我们的机器学习算法和在单词嵌入中的偏差进行的公平性测量。两者都试图解决同一个问题,但方法不同。詹姆斯教授最近的工作是量化和消除单词嵌入中的性别和种族偏见。在他题为《男人对于电脑程序员就像女人对于家庭主妇一样?去偏置单词嵌入”,他们与托尔加·博鲁克巴斯提出了一种方法,以几何方式修改嵌入,以消除性别刻板印象。最终的嵌入保留了女王和女性之间的关联,丢弃了接待员和女性之间的关联。鉴于 Sharad 教授最近的工作,“公平的衡量和错误衡量:公平机器学习的批判性评论”讨论了各种公平定义(如反分类、分类奇偶校验以及校准)如何受到显著的统计限制,并可能损害它们旨在保护的群体。他们还认为,基于对一个人可能产生的风险的准确估计,我们应该以同样的方式对待同样有风险的人。对机器学习中的公平和偏见的研究刚刚开始,看看它如何发展和塑造下一代的政策将是有趣的。

机器学习中的偏见:面部识别模型如何显示种族主义、性别歧视和年龄歧视的迹象

原文:https://towardsdatascience.com/bias-in-machine-learning-how-facial-recognition-models-show-signs-of-racism-sexism-and-ageism-32549e2c972d?source=collection_archive---------8-----------------------

通过年龄和性别预测的镜头检查面部识别中的偏见,以鼓励公平、负责和透明的机器学习的发展。

By: 【安珀】卡米莱里罗比·盖根雷切尔·米德塞巴斯蒂安·奥索里奥秦沛·邹********

Licensed from Adobe Stock

早在 2018 年,技术市场研究公司 Counterpoint 的一篇文章预测,到 2020 年,超过 亿部智能手机将配备面部识别功能。今天,苹果、三星、摩托罗拉、一加、华为和 LG 都提供具有面部识别功能的设备。

当我们把手机装进口袋,走到外面时,公共场所布满了面部识别摄像头,全球各地有数百家甚至数千家零售店使用面部识别摄像头。大多数大型零售商对他们使用面部识别来防盗守口如瓶,但像 this 这样的文章证实了像塔吉特和沃尔玛这样的大品牌已经在他们的商店里试验面部识别。

不久,这些商店和其他商店可能会推出面部识别功能,以提高商店忠诚度计划或定制服务。福布斯的一篇文章指出,忠诚度会员通常已经同意与品牌分享个人数据,因此通过面部识别增强忠诚度计划可能在不久的将来。这种趋势正在许多行业出现,从识别癌细胞到预测罪犯再次犯罪的可能性。

Licensed from Adobe Stock

随着它的迅速普及,我们觉得理解这项技术很重要,所以我们决定通过构建我们自己的卷积神经网络来探索图像检测和分类的内部工作方式,该网络能够从一个人的图像中预测他或她的年龄和性别。我们将使用通用行业基准的模型和数据集。然后,使用模型的预测,我们将进一步检查模型可能存在的任何偏差。尽管我们的发现可能无法完美代表当今商业部署中使用的模型,但该项目旨在揭示机器学习中的偏见,并强调公平、负责和透明的机器学习的深思熟虑的发展的重要性。

初步研究

近年来,对公平、负责和透明的机器学习领域的研究获得了极大的关注。在所有形式的机器学习中都发现了无意识的偏见,例如 Bolukbasi 等人,2016 在一种常用的文本分析技术中分析了性别偏见:在谷歌新闻文章上训练的单词嵌入。研究人员建立了一个模型来预测一个类比应该如何结束使用性别特定的词,如“男人是国王,女人是 _ _ _ _ _ _ _ _ _ _”,该模型将预测女性的对等词“女王”。在用谷歌新闻文章训练了模型之后,研究人员使用了非性别职业来观察女性。因为“男人对于电脑程序员就像女人对于 _ _ _ _ _ _ _ _ _ _”这个模型预测了“家庭主妇”。模型中其他极端的“女性”职业包括:“护士”、“接待员”、“图书管理员”和“理发师”,而极端的男性职业包括:“艺术大师”、“船长”、“哲学家”和“船长”。这些模型反映了在谷歌新闻等常用数据源中发现的社会偏见,这些数据源用于许多商业、政府和研究领域,却没有意识到或纠正性别偏见。

在许多面部分类模型中也是如此。 Buolamwini 等人,2018 分析了跨浅色和深色皮肤男性和女性的商业性别分类产品的准确性。他们的研究考虑了微软、Face++和 IBM 出售的产品,发现它们在男性和浅色皮肤的人身上表现得更好——下表显示了每个产品在从图像预测男性或女性的二元分类中的准确性。

鉴于政府和企业如今都在使用这些产品,这种差异令人担忧。这种偏见的证据正在许多行业中被发现,从使用 81%欧洲出生参与者数据集的基因组学医学研究( Popejoy 和 Fullerton,2016 )到刑事诉讼,这些刑事诉讼由模型告知,这些模型错误预测黑人被告重复犯罪的可能性是白人被告的两倍( Angwin 等人,2016 )。

在研究我们从图像中预测年龄和性别的具体问题时,我们发现执行这些预测的大多数模型都是在来自维基百科和 IMDB 的最受欢迎的 100,000 名男女演员上训练的。作为名人的数据集,训练数据主要是白人,男性比例更高,大多数名人看起来比同龄的非名人要年轻得多——这造成了对老年人进行分类的偏见。

我们的重点是试图量化这些偏见,并尝试纠正它们的方法。

型号选择

我们选择使用卷积神经网络(CNN)作为我们的主要模型也是基于我们最初的研究。年龄预测本质上是一个回归问题,因此使用通常使用分类损失函数训练的 CNN 不是一个明显的选择。然而,我们发现,CNN 在图像识别任务上一直表现良好,并且已经成为这类任务的行业标准。

在过去的十年中,ImageNet 大规模视觉识别竞赛已经成为 CNN 能力和准确性的试验场。他们在这些年度比赛中的出色表现使得 CNN 被大规模接受为图像分类任务的“首选”模型。ImageNet 竞赛是 1,000 个类别的分类竞赛,训练集中有超过 100 万个图像。学者和专业人士都在竞争,一路改进 CNN。2010 年至 2017 年间,竞赛中的分类误差从 28.2%降至 2.3%。

最终,我们采用了 VGG-Face 架构,一个 16 层 CNN,具有 13 个卷积层(一些具有下采样)、2 个全连接层和一个 softmax 输出。像我们这样的模型可以在这里找到。尽管分类损失函数并不理想地适合于年龄分类,但我们选择使用这种特定的模型,因为它具有出色的基准性能、丰富的文档以及我们对初始权重实施迁移学习的能力。我们最初的模式(在再培训之前)完全依赖于迁移学习,最初的来源可以在这里找到。

数据选择

模型最初训练的图像来自 IMDb 和维基百科。这些数据是利用 IMDb 10 万名最受欢迎的男女演员的名单收集的,包括他们的面部图像,并附有时间戳、出生日期和性别。在 100,000 名男演员和女演员中,20,284 人有可用数据,平均每个名人有 26 张照片,数据集中共有 523,000 张照片。

年龄标签基于 IMDb 和维基百科上记录的出生日期和图像的时间戳。这是假设出生日期在这些网站上是准确的。没有时间标记的照片被删除,因为照片中人的年龄无法确定。一些图像来自电影的剧照,并且图像的时间戳基于制作时间,但是制作时间延长的电影可能导致时间戳信息的一些不准确性。因此,图像的年龄标签可能存在一些不准确之处。

尽管维基百科和 IMDB 的数据集很大,而且标签也很好,但名人的照片可能并不能代表普通大众。为了提供我们的模型如何在公众面前表现的代表性测量,我们还采用了来自 UTKFace 数据集的图像来重新训练模型,并作为精确误差测量的测试集。UTK 的数据既有裁剪过的照片,也有未裁剪过的照片;每个数据集的示例如下所示。UTKFace 是一个大规模的人脸数据集,包含超过 20,000 张照片,并带有年龄、性别和种族的注释。

Examples of photos from each dataset

年龄预测

我们的模型是在来自 IMDB-Wikipedia 数据集的大约 450,000 张照片的子集上预先训练的;训练中未使用的剩余照片被指定为样本外测试集。下面显示了该测试集的平均预测值与实际年龄的对比。实际(每个注释)年龄在 x 轴上,平均预测年龄(根据我们的 CNN 模型)显示在 y 轴上。人们可能会预期,在大型数据集上训练的模型,在与训练集非常相似的图像上进行预测,会表现得很好,我们的观察结果与这一预期相符。

为了获得预测,我们评估了 softmax 输出的两种不同解释。CNN 的最后一层是 softmax 层,它输出给定图像属于 101 个类别中的每一个的概率,每个类别对应于一个年龄(0 到 100)。这些概率可以解释为加权平均值,即将图像属于每个类的概率乘以该类的值。或者,预测可以简单地是具有最大概率的类别的年龄。最大概率解释总是导致较高的误差,因此我们采用加权平均解释来进行预测。

我们选择关注平均绝对误差(MAE ),这是我们对误差的主要度量,因为它对异常值更稳健,并且是年龄预测问题中误差的明显行业标准度量。作为对比,本文从 2017 年开始引用了几个商用 API 预测年龄的 MAE,并将微软的 Face API 年龄预测工具的 MAE 列为 7.62 年。我们从维基百科图片预测人的年龄时的平均寿命是 5.3 年。

然而,我们知道,这种误差测量可能并不能很好地反映模型对非名人面孔年龄的预测。非名人图像通常在图像分辨率、照明和面部特征方面不同于名人照片,这应该会影响模型的预测能力。由于训练集中测试集的信息泄漏,MAE 也可能人为地低。例如,如果一个名人在数据集中有多个图像,并且一些图像最终出现在训练集和测试集中,神经网络可能只是“识别”一个熟悉的面孔并匹配 hir 或她的已知年龄,而不是“预测”他或她的年龄。因此,我们的下一步是对 UTK 数据集进行预测。

我们从预测 UTK 的一组裁剪照片的年龄开始。在没有仔细查看来自 UTK 和维基百科-IMDB 数据集的照片示例的情况下,我们假设裁剪后的照片与 CNN 最初训练的数据最相似。尽管我们预计该模型在本次实验中表现不佳,但我们仍然对该模型未能准确预测年龄的程度感到惊讶,特别是在老年人中。然而,经过进一步的研究,我们发现从 UTK 数据集裁剪的图像比从维基百科-IMDB 集中裁剪的图像更接近。这导致头发、耳朵和其他面部特征经常从图像中被裁剪掉。如果我们想要匹配模型最初被训练的照片的格式,我们最好使用未剪辑的照片。

然而,在重新运行该模型之前,我们还从未裁剪的 UTK 数据集中移除了标注年龄低于 16 岁的照片。我们删除这一年龄组的理由基于两个关键论点:首先,原始数据和 UTK 数据集对于 16 岁以下的人来说都是稀疏的。第二,我们的用例通常与非常年轻的人不太相关。

由此得出的预测大约有 10 年的平均误差。这代表了对裁剪数据集预测的显著改进,证实了我们的直觉,即测试集中的照片在裁剪、分辨率、光照等方面与原始训练数据中的照片非常相似是很重要的。

下一个明确的步骤是,通过重新训练神经网络的最后两个完全连接的层和 softmax 输出,尝试提高模型对非名人面孔的预测能力。我们保留了最初的 14 层及其权重不变,以保留神经网络的特征提取部分,这将需要大量的数据来重新训练,但允许我们微调生成预测的神经网络部分。

Retraining fully-connected layers

最初,我们使用 Adam 优化对 UTK 未裁剪数据的子集进行了 250 个时期的再训练。可视化显示了前 100 个时期,并在大约 30 个时期内实现了最低的验证损失。蓝线代表验证失败,橙色代表训练失败。我们为验证损失最低的模型保存了权重,以避免过度拟合。作为这个再训练过程的结果,我们在 UTK 非裁剪测试集上的预测有了实质性的提高。

再培训将我们的测试平均寿命从 10 年减少到大约 8.4 年。基于与测试集中的照片更相似的照片来调整完全连接的层的权重产生了明显的差异。UTK 的数据通常具有较低分辨率的照片,较差的照明,以及化妆较少的女性,因此原始模型的一些糟糕表现可以归因于图像中的这些审美差异。

除了这一改进之外,该模型在预测老年人的年龄方面仍然表现不佳。检查 UTK 数据集,我们观察到,像模型最初训练的维基百科数据集一样,绝大多数图像是 20 至 35 岁之间的人。我们推测,缺乏老年人的数据可能是导致该数据区域表现不佳的原因。

Proportion of Data in UTK Dataset By Gender & Age

不考虑重新训练整个神经网络的选项,有两种常用策略可用于尝试提高模型性能:调整损失函数以进一步惩罚该组的不良预测,或者复制训练数据的不良表现区域的每个数据点以有效地实现同样的效果。我们开始复制所有 60 岁以上的人的照片,然后试着把它们增加三倍。

通过创建超过 60 岁的人的多个图像,该模型因错误标注他们的年龄而进一步受到惩罚。大部分改进是通过复制照片获得的,将 MAE 从 8.4 提高到 7.9。通过将图像增加三倍,实现了 0.1 年 MAE 的微小增量改善。

除了简单地改进 CNN 的权重,我们还对检验模型预测的偏差感兴趣。我们按照人口统计学将我们的最佳模型(用三份 60 岁以上的图像重新训练)的预测分开,以检查模型性能的离散性。当按性别区分预测时,预测中的偏差似乎是相似的。总的来说,该模型一贯高估年轻女性的年龄,其程度超过男性,但低估老年女性的年龄可能没有男性严重。随着年龄的增长,两性之间的差异也在增加。对于老年人来说,这种差异的增加和准确性的下降可能是由于该地区的数据相对稀少。

********

另一个显著的对比可以通过按种族划分预测来进行。未裁剪的 UTK 数据集主要是高加索人的照片,因此毫不奇怪,该模型对高加索人的表现与它对整个数据集的表现相当。请注意,与测试数据中对亚洲人的截然不同的预测相比,对高加索人的预测是多么相似。亚洲人在照片中占少数,对于该种族的老年人来说,预测不太准确,而且非常不稳定。正如我们所料,正如这两个例子所证明的那样,对于拥有大量数据的人群,预测通常更准确,而对于在数据集中代表性较低的人群,预测则不太准确。

校正模型

为了进一步完善神经网络做出的预测,我们创建了一个二级模型,用于校正基于年龄、性别和种族的系统性低估或高估。通过这个模型的生成,我们对与人口统计组相关的不同程度的偏差有了更好的理解。

校正模型中使用的特征包括:卷积神经网络的预测年龄、人的性别(男性或女性)和人的种族(白人、黑人、亚洲人、印度人和其他人)。我们测试和调整了几个模型,以便选择最合适的校正模型,下表显示了每种类型中性能最好的模型。

我们尝试的模型没有一个能改进原始模型的输出。我们认为这是由于一套简单的特征,只考虑了一个人的预测年龄、种族和性别。考虑到人们在较高年龄时一贯的预测不足,这是令人惊讶的。作为第二个解决方案,我们测试了一些简单的试探法,看看它们是否能改善我们的预测。为了做到这一点,我们采用了不同年龄段、性别和种族的预测年龄和实际年龄之间的平均差异。结果如下表所示:

Average Difference Between Predicted and Actual Age, Grouped by Predicted Age, Race and Gender

性别预测

除了年龄预测,我们还建立了一个卷积神经网络来预测同一组图像的性别。性别分类是二元的,只考虑在各自数据集中确定的男性或女性。预训练的神经网络在 IMDB 和维基百科的名人数据集上表现非常准确,并以 99%的准确率预测了正确的性别。使用混合种族和非名人的 UTK 人脸数据集返回了低得多的 78%的整体准确率。准确率因种族和性别而有很大差异:从印度和白人男性的 98%的准确率到黑人女性的 46%的准确率。

Accuracy for Gender Prediction Model

结果显示了在研究中发现的类似的性别偏见,即该模型在女性图像上的表现始终低于男性照片。当比较所有类别时,该模型对黑人女性的照片表现最差。差异之大令人惊讶。所有种族的男性都被正确分类,准确率为 96%,而表现最好的女性种族只有 63%的准确率。如下图所示,女性的年龄进一步放大了这种不准确性。

Accuracy of Gender Predictions for Females Only

与我们在预测年龄时看到的类似,在测试数据中,年龄最大的受试者的性别预测表现最差。我们也看到了对黑人女性的偏见,这种偏见导致了所有年龄段的预测都不准确。

这些结果反映了训练数据集中的问题。训练数据中男性人数比女性多两到三倍,少数民族人数不足。最令人惊讶的是,鉴于训练数据集主要是白人,所有种族的男性结果都是如此——这表明种族并没有显著影响男性的性别预测。对于女性来说,种族扮演着重要的角色,这可以从所有年龄组的种族的不同准确性中看出。此外,该数据表明,对女性性别预测的最大偏差是年龄。

测试我们的模型

作为最后的测试(也是为了我们自己的享受),我们将模型指向我们自己和朋友。为此,我们收集了 51 张人们的脸部照片,其中包括他们在脸书的个人资料照片和亲自拍摄的照片。我们的目标是表明,我们重新训练的模型在预测年龄和性别方面比根据名人图片训练的原始模型更准确。

重新训练的模型在拍摄真人照片时表现优于原始模型,而原始模型在精心挑选和光线充足的脸书个人资料照片上表现更好。

我们认为,性能的差异与训练数据集的差异一致,在训练数据集中,人们策划的高质量脸书个人资料照片更接近地反映了名人形象,而真人照片更接近地反映了我们重新训练模型中使用的普通人。总体而言,重新训练的模型表现最佳,准确率提高了 10–20%。

结论

作为在不平衡数据集上训练的结果,我们 CNN 的预测尖锐地展示了其预测中的种族、性别和年龄偏见。通过重新训练和重新平衡数据,我们能够在减少偏倚方面取得增量改进,将年龄的初始 MAE 提高 24%。然而,这些改进只是渐进的变化。需要对更好地代表少数民族的平衡数据集进行深思熟虑的监管,以适当消除这些偏见。鉴于机器学习模型在企业和政府中的普遍存在,这一点尤为重要,这些模型是根据这些数据集进行训练的。有大量证据表明有偏见的模型对少数群体产生了影响,但由于知识差距、数据收集的成本以及部署这些模型时有限的制衡,变化是缓慢的。透明度和意识是重要的第一步,但要真正确保机器学习对每个人都是公平和负责的,还有更多工作要做。

GITHUB 资源库

****【https://github.com/rmmeade/APM_Faces_Proj/settings ****

资源

特别感谢奥斯汀德克萨斯大学的 Joydeep Ghosh、Shubham Sharma & Disha Makhija 博士的慷慨指导和建议。

年龄和性别预测 CNN 发自 Sefik Ilkin Serengil

UTK 人脸数据集

IMD b-维基百科数据集

性别差异:商业性别分类的交叉准确性差异

男人对于电脑程序员就像女人对于家庭主妇一样?去偏置词嵌入

基因组学在多样性上失败了

朱莉娅·安格温、杰夫·拉森、苏亚·马特和劳伦·基什内尔的《机器偏见》,ProPublica

人脸识别、卷积神经网络和子空间学习

预测模型中的偏差—第 1/2 部分

原文:https://towardsdatascience.com/bias-in-predictive-models-part-1-2-ebba5c9ab94b?source=collection_archive---------27-----------------------

对抗偏见的第一步是定义它。

摘要

人工智能已经在我们的生活中发挥了重要作用,很快它将做出越来越多改变生活的决定。人工智能的公平和偏见问题正在吸引越来越多的研究和立法者的关注。关于什么是偏倚以及如何测量偏倚,有几种可能的定义,每一种都有自己的优点,但也有适用性的限制。

使用哪一种是一个重要的(也不是很简单的)选择,公司,可能还有监管者都需要做出这个选择。

介绍

还记得最近关于亚马逊人工智能招聘工具对女性产生偏见的故事吗?幸运的是,他们的团队能够在模型投入生产之前发现问题。人工智能已经在我们的生活中发挥了重要作用,很快它将做出越来越多改变生活的决定。你会得到那份工作吗?贷款被批准了吗?你的产品会被推荐吗?你的社交媒体账户会被屏蔽吗?你的孩子会被那所大学录取吗?你会被“随机”选择进行深入的税务审计吗?甚至,你会提前出狱吗?并不是这个列表上的所有决定都已经被人工智能完成了,但是很多已经完成了,而且这个列表每年都在增长。

这个关于布劳沃德县累犯率的 ProPublica 分析中,显示(见下表)没有再犯的非裔美国人被(错误地)标记为高风险的可能性几乎是白人的两倍。

大多数类型的人工智能,如果任其自生自灭,将会延续它们被训练的历史数据中存在的任何趋势(包括偏见)。如果女性以前是劳动力的一小部分,这就是人工智能要学习的(就像亚马逊招聘工具的故事一样)。

有了这么多的利害关系,难怪这个话题越来越受到关注,无论是来自研究人员的还是现在来自立法者的

数字摘自本文

这个问题提出了两个高层次的问题:

  1. 什么是偏差,如何衡量偏差?
  2. 如果存在偏见,又能做些什么呢?

这两个问题都不容易回答。在这篇文章中,我们集中讨论偏见的定义和衡量方法。解决这个问题的方法将在后续讨论。

偏见的定义

在一个理想的世界里,每个人都希望他们的模型是“公平的”,没有人希望他们是“有偏见的”,但是这到底意味着什么呢?不幸的是,关于偏见或公平,似乎没有一个普遍认可的定义。

在这篇关于衡量模型公平性的不同方法的伟大文章中,谷歌 People + AI Research (PAIR)的常驻作家大卫·温伯格(David Weinberger)提出了不少于五个(!)定义什么是公平的方法各不相同,各有利弊。

有趣的是,一些更直观的方法,如“群体无意识”或“人口统计均等”有时并不适合现实生活中的问题。

【群体无意识】方法规定,如果完全忽略受保护的班级信息(如性别),结果将反映申请人的客观优点,这是公平的。如果结果是某个性别的代表比例失调,这就是“数据所显示的”。然而,在现实生活中,事情往往更复杂。性别信息可能隐藏在一些其他变量(代理)中,而源于过去可能存在的歧视的女性比例较低将会悄悄进入我们的新模型(就像亚马逊案例或这个谷歌翻译示例中发生的那样)。有些问题,比如医学诊断,可能直接取决于性别。在其他问题中,一些参数的意义可能间接取决于性别。例如,在简历分析中,女性就业中的某些差距可能表示产假,与一个人不能或不愿找到工作时的就业差距相比,产假具有不同的含义。总的来说,有时引用受保护的变量是可以的,甚至是可取的,不引用它们并不能保证不会有偏差。

另一种常见的方法,“人口统计均等”有效地假设了结果的均等。根据这一假设,如果有 30%的橙色申请人,我们希望看到 30%的橙色批准。“人口均等”的概念与“不同影响”标准非常相似,后者用于美国反歧视法律框架,监管信贷、教育、就业等领域。然而,这种方法的应用远非显而易见。这些橙色的申请者和蓝色的一样合格吗?什么应该算 100%?一些缩小差距的方法可能导致相似的人受到不同的待遇,这本身就可以被视为歧视。一个这样的案件甚至到达了最高法院,而一般的话题是法律讨论的主题,这超出了本概述的范围。

这种同等结果的假设在某些情况下可能是正确的,但它总是正确的吗?有时,由于与偏差无关的原因,受保护变量与输出相关。例如,某些疾病的发生率在不同性别或种族之间可能有很大差异。

最近,英特尔宣布他们实现了“全性别代表”,只有大约 27%的女性员工。“人口均等”的天真应用当然会失败,因为 27%远低于女性在总人口中的比例。英特尔可以这样说,因为他们只使用相关大学学位的毕业生作为参考,因为根据英特尔的说法,只有她们才是合格的女性候选人。

在统计学中,估计量的偏差定义为估计量的期望值与被估计参数的真值之间的差值。然而,在现实生活中,往往很难知道这个“真实价值”是什么。如果被拒绝的借款人获得了贷款批准,他们真的会偿还贷款吗?

有时我们有机会知道所有候选人的实际结果,包括被拒绝的候选人。例如,在这种情况下,该模型预测现有罪犯未来犯罪的可能性,在他们被释放几年后,我们可以知道谁实际上犯了另一个罪行,谁没有。在贷款案例中,被特定银行拒绝贷款的人可能仍然能够在其他地方获得贷款,并且信用局可能有关于他们随后付款的信息。对于这种情况,在已知实际结果的情况下,由谷歌大脑团队和加州大学伯克利分校“机器学习的公平性”教师 Moritz Hardt 提出的以下标准似乎是适用的:

应该调整系统,使两个类别的批准和拒绝总数中出错的百分比相同

换句话说,我们将对不良申请人的批准对优秀申请人的拒绝因不同阶层(如性别)差异太大的情况定义为有偏见(并希望避免)。注意,我们不需要假设任何关于正确批准或拒绝的比率。尽管很吸引人,但这一指标有些不太直观,当然,只有在实际结果已知时才适用,例如在对历史数据进行回溯测试时。

总之,有多种方法来定义和衡量偏见,这可能或多或少适合你的特殊问题。使用哪一种是一个重要的(也不是很简单的)选择,公司,可能还有监管者都需要做出这个选择。

在选择了某种检测偏差的方法后,下一个挑战是减轻偏差。一些减轻偏见的方法,包括现有的和新的,将在下一篇文章中讨论。

人工智能法庭决策中的偏见——在对抗之前发现它

原文:https://towardsdatascience.com/bias-in-the-ai-court-decision-making-spot-it-before-you-fight-it-52acf8903b11?source=collection_archive---------12-----------------------

Image by TPHeinz from Pixabay

法院判决中的机器学习

在不同的决策过程中,包括在司法实践中,机器学习的使用越来越频繁。由于法院判决对个人的个人和职业生活以及整个社会都有很大的影响,因此能够识别并理想地纠正人工智能(AI)系统中的偏见以避免该模型做出不公平或不准确的决定,从而潜在地放大我们社会中现有的不平等是很重要的。

优势

在法庭决策中使用机器学习的目标应该是使决策和决策过程更好,即更准确、公正、更快和成本更低。或许令人惊讶的是,AI 模型实际上可以帮助法官发现并打击自己的偏见。该系统可以根据历史统计数据,在法官的语言中检测到他或她注意力不集中、即将做出仓促决定或缺乏同情心时,向法官发出警告。该模型可以通过加权外部因素来实现这一点,这些因素可能会影响决策,如一天中的时间、温度甚至选举期即将到来的事实。正如丹尼尔·卡内曼在他的《思考,快与慢》中所描述的那样,在对以色列假释法官的研究中,这些外部因素对法官决策的影响已经显现出来。被观察的法官将遭受所谓的葡萄糖耗竭,这导致他们更倾向于在用餐休息后批准假释,每次用餐后批准率达到 65 %,而平均只有 35 %的假释请求获得批准。

现状

显然,在目前的技术阶段,只有某些法院判决或部分法院判决可以由算法做出。人工智能已被用于所谓的预测性警务,在这种情况下,基于可用的数据,算法可以帮助警方或法院就案件的特定方面做出决定。例如,这可以是批准假释、决定保释和确定适当的刑期。例如,法院可以使用这种软件来评估被告在假释期间再次犯罪的风险,如果获准保释,他是否会出庭,或者是否应该考虑缓刑。此外,机器学习也被用于判决的实际渲染。这些案件通常涉及小的民事法律纠纷,包括推翻或决定停车罚款。爱沙尼亚最近推出了试点机器人法官,将裁决涉及小额索赔的纠纷。

人工智能法院判决中的偏见

尽管优势很多,并且随着技术的进步,可能是无限的,但在法庭决策中部署人工智能的风险规避方法是至关重要的。在启动任何算法来代替人类法官做出裁决之前,我们必须确保它做出的决定至少与人类法官一样公正合理。欧盟委员会人工智能高级专家组认为,当一个人工智能系统合法、符合道德规范且强健时,它就是值得信赖的。

当谈论道德人工智能时,需要考虑的最大问题是算法本身或数据中是否存在偏差,无论是有意识的还是无意识的,因为它会影响和扭曲计算和预测过程。

  • 偏差可能是采样和测量中的错误造成的,导致数据不完整,基于太少的数据或仅仅是错误的。这是一种由于数据收集或生产过程的疏忽而导致使用错误数据的情况。这种偏差在理论上可以通过重新操作数据收集和生产系统并包括丢失的数据或替换坏的数据来纠正。然而,如果数据丢失是因为它根本就不存在,那么纠正偏差将是一项更加困难的任务。例如,当某些类型的犯罪实际上没有受到调查,因而一群罪犯由于警察的偏见做法而没有受到起诉时,就会发生这种情况。
  • 这些数据本身也可能带有反映社会不平等的偏见。目前最基本的偏见涉及种族和性别不平等,以及与个人的社会背景和性取向有关的不平等。这可以反映在内容本身以及数据的语言中,但不必明确提及。例如,案件事实和情况或被告行为的描述方式可能带有被告种族或社会阶层的信息偏见。根据种族不容忍程度较高的地区的历史数据预测与某一被告行为相关的风险的算法,可能反映出执法部门不成比例地针对非裔美国人,导致在收集数据的最终民意调查中这种数据的比例过高。
  • 此外,当数据反映了欺诈性信息、伪造的文件、伪造的证据或其他被操纵或非法的事实或受其影响时,不干净的数据(与干净的高质量数据相反)也可能导致偏差。这种偏见,如果被发现,会将整个人工智能系统的使用转移到一个潜在的非法领域,并增加开发者和用户的责任风险。

对抗偏见

一个建立在并使用坏的或肮脏的数据之上的模型有可能通过增加其工作产出(决策)与社会价值(平等待遇、公正程序等)之间的脱节,在社会中进一步传播歧视和不平等。),最终做出不公正或不准确的决定。因此,在人工智能系统部署之前或在更糟的情况下部署之后,发现并消除不公平的偏见(与故意引入的偏见相反)至关重要。

由于包括法院在内的公共领域使用的人工智能系统主要是由私营公司开发的,除非以这种方式明确编程,否则它们并不带有保护司法或人权的内在承诺。换句话说,这个系统是不道德的,除非它是如此。

AI 模型尽职调查

理想的情况是,由于人工智能对我们的生活和我们的基本人权具有巨大的潜在影响,人工智能将受到与其他重要部门类似(如果不是更严格的话)的监管,例如空中交通、卫生系统或法律实践。目前,在国家、欧洲和国际层面上有许多倡议正在进行,以界定人工智能监管的关键原则(见经合组织人工智能原则)。然而,目前任何定义明确的监管制度与其说是短期内可以实现的,不如说是乌托邦。与此同时,为了确保现在部署的人工智能系统能够尽可能公正和准确地做出决定,软件必须接受 T2 持续的审计。

无论它在首次部署时看起来有多准确,使用它的法院都必须持续确保它始终如一地执行,并做出公平的裁决,将质量与人类法官的裁决进行比较。虽然引入一种纠正措施来消除已识别的偏差在理论上是可行的,但的实践表明通过允许人为引入一些变量来使人工智能系统合乎伦理是非常困难的。

个案尽职调查

在对人工智能模型本身进行审核之后,整个人工智能法院决策模型的第二层是确保它从各个相关方的角度来看是可验证的。我们不应该忘记,人工智能系统没有感觉或关心,因此,如果它做出不公正的决定,它不会意识到这一点。此外,它也没有说明为什么会有这样或那样的裁决。因此,从本质上来说,它缺乏在案件当事人眼中值得信赖的核心价值——可解释性。

AI 可解释性或可解释性指的是一个尽职调查过程,该过程使有关各方能够要求对机器学习决策背后有法律或其他重大影响的解释,并可能对其提出质疑。尽管这是一般审计义务的一部分,但这一措施也要求各方有权在可能和合理的范围内访问人工智能模型使用的数据和生成的信息。

在实践中,揭示人工智能模型做出的决策的推理过程可能并不总是容易,甚至是不可能的。通常,可解释性最高级别的预测模型,如决策树和分类规则,缺乏预测准确性,反之亦然-神经网络通常非常准确,但对于它们如何进行计算却非常不透明。然而,即使在使用深度学习时,对 AI 模型的整体审计以及确保尽可能高的决策过程可追溯性将提供某种程度的透明度,从而具有可解释性。

人工智能培训

用于法院决策的人工智能系统通常不是由法院自己开发或实现的,而是由外包开发商或供应商开发或实现的。因此,决策者和相关方往往不了解和不理解系统是如何工作的,以及它是根据什么标准做出决策的。此外,人工智能系统可能不会完全取代人类法官和律师,而只是对他们进行补充。

在这两种情况下,如果法官和律师对所使用的人工智能模型、输入变量和预测方法有很好的理解,或者至少有一些理解,这将是有益的。现在用神经网络训练所有的律师和法官既不可行,也没有必要。然而,作为第一步,我们可以集中精力进行培训,以发现常规决策中的偏见和肮脏数据,从而使法律专业人员对歧视性语言或欺诈性数据的使用更加警觉。更高的偏见意识,结合对机器学习过程及其优势和局限性的基本理解,可以帮助相关各方对通过尽职调查提供的信息有所了解,并改善迄今为止不完善的人工智能模型在决策中的使用。

系统性变化

即使在软件部署之前和使用期间进行深入的尽职调查,以发现和修复任何潜在的偏差,也不足以做出完美、准确和公正的决策。收集到的数据中的偏差很有可能反映出社会中现存的不公正和不平等。除非在创建数据集时特别关注这种文化和社会规范和陈规定型观念,或者错误和不道德的执法做法和政策,除非有目的地纠正这些做法和政策,否则我们只会面临进一步扩大其偏见的风险。

只有在数据收集、制作和标记过程以及算法的使用有明确的规则、得到理解和监督的情况下,才能确保参与决策的所有行为者,无论是法官、律师、书记员还是执法当局,都努力确保最高水平的准确性和公正性。

如果我们无法部署一个无偏见的系统,或者一个让各方有足够理由相信它达成了公平决定的系统,一个中间解决方案可能是使用人工智能系统来补充人类决策。这样,我们可以加快司法程序,更深入地分析案件事实,或者在保护司法的同时节省费用。仅仅因为一项技术是可用的,并不意味着它应该取代现有的政策。

偏差、方差和正则化

原文:https://towardsdatascience.com/bias-variance-and-regularization-f3a0eefe99af?source=collection_archive---------23-----------------------

数据科学中的三个基本概念

每一个初露头角的数据科学家都面临着一个困境,那就是接受诸如过拟合、欠拟合、偏差、方差以及最后但并非最不重要的正则化等词汇。

我的一个有趣的同事会对所有数据科学问题给出相同的答案。“它必须被正规化”,然后笑着说。有趣的是,他会侥幸逃脱,因为大多数时候他是对的。

让我们看看这些术语,并把它们一个一个地铭刻在我们的记忆中。这是我对每个术语的理解,如果你觉得我错了,请随时纠正我。保留下图作为参考来理解这些概念。

source: https://towardsdatascience.com/understanding-the-bias-variance-tradeoff-165e6942b229

  • 偏差:假设你的机器学习模型在一组数据上表现非常糟糕,因为它没有推广到你所有的数据点。这是当你说你的模型有很高的偏见。当模型不合适时,会出现这种现象。
  • 方差:假设你的机器学习模型试图成功地解释一个数据集中的所有或大部分所有点。如果它在其他测试数据集上运行时表现不佳,则称之为高方差。因此,当模型过拟合时,就会出现偏差。
  • 正则化:用于处理高方差的回归方法称为正则化。正则化对过度拟合模型的作用是,通过惩罚回归系数,消除或最小化具有较大异常值的预测器列的影响。结果是一个更平滑的模型,可以很好地工作在具有类似数据的其他测试数据集上。

Source: https://en.wikipedia.org/wiki/Regularization_(mathematics)#/media/File:Regularization.svg

附加信息:

我通过 sklearn 使用了两种主要类型的正则化子。

  1. 这个正则化器基本上试图同时惩罚所有的系数。
  2. Lasso: Lasso 选择性地仅惩罚具有高异常值的预测值,并从模型中忽略这些预测值。因此,其结果是一个能很好地概括新数据的模型。

线性回归中的偏差、方差和正则化:套索、脊和弹性网——差异和用途

原文:https://towardsdatascience.com/bias-variance-and-regularization-in-linear-regression-lasso-ridge-and-elastic-net-8bf81991d0c5?source=collection_archive---------6-----------------------

Photo by pan xiaozhen on Unsplash

回归是一种非常流行和常见的机器学习技术。往往是学习机器学习的起点,线性回归对于容易理解的问题是一种直观的算法。它通常可以在你试图预测一个连续变量(一个可以取某个数值范围内的任何值的变量)时使用,线性回归和它的亲属通常是强有力的选择,并且几乎总是最好的起点。

线性回归

这个博客假设了普通最小二乘(OLS)线性回归的功能知识。你可以在这里这里或者这里阅读更多关于 OLS 线性回归

偏差-方差权衡

From Seema Singh

在机器学习中建立最佳模型的很大一部分是处理偏差-方差权衡。偏差是指模型的正确(或不正确)程度。一个非常简单的模型,犯了很多错误,据说有很高的偏差。一个在训练数据上表现良好的非常复杂的模型被称为具有低偏差。与偏差负相关的是模型的方差,它描述了如果一个预测因子发生轻微变化,预测可能会发生多大的变化。在上面提到的简单模型中,模型的简单性使得其预测值随预测值变化缓慢,因此方差较低。另一方面,我们复杂的低偏差模型可能非常适合训练数据,因此预测值会随着预测值的轻微变化而大幅变化。这意味着这个模型有很高的方差,它不能很好地推广到新的/看不见的数据。

低偏差/高方差模型表现出所谓的过度拟合,即模型有太多的术语,并在总体趋势之上解释数据中的随机噪声。这导致它对模型以前没有见过的数据表现不佳。高偏差/低方差模型表现出所谓的拟合不足,即模型过于简单/术语太少,无法正确描述数据中的趋势。同样,该模型将在新数据上苦苦挣扎。这两种模型类型都不理想,我们希望达到某种中间状态,在这种状态下,我们有适当数量的项来描述趋势,而不适合噪声。因此,我们需要某种特征选择,其中与因变量没有关系的预测因子在最终模型中没有影响。

Image from Sydney Firmin

偏差-方差权衡如上图所示。模型的总误差由三项组成:偏差、方差和不可约误差项。正如我们在图中看到的,我们的总误差最小化的最优解是在某个中等模型复杂度,偏差和方差都不高。

OLS 线性回归的弱点

线性回归找出使 R 最大 RSS 最小的系数值。但是这可能不是最好的模型,并且将为提供的每个预测值给出一个系数。这包括几乎没有预测能力的术语。这导致了一个高方差、低偏差的模型。因此,我们有潜力改进我们的模型,通过用偏差交换一些方差来减少我们的总体误差。这种交易以正则化的形式出现,其中我们修改我们的成本函数来限制我们的系数的值。这使得我们可以用过度的方差来换取一些偏差,从而潜在地减少我们的总体误差。

套索

The Lasso cost function, from Wikipedia

Lasso(有时风格化为 lasso 或 LASSO)在成本函数中添加了一个附加项,将系数值之和(L-1 范数)乘以一个常数λ。这个额外的项对模型不利,因为它的系数不能解释数据中足够的变化量。它还倾向于将上述不良预测器的系数设置为 0。这使得套索在特征选择中很有用。

然而,Lasso 对某些类型的数据感到困惑。如果预测值的数量(p)大于观测值的数量(n),Lasso 将最多选取 n 个预测值作为非零值,即使所有预测值都相关。Lasso 还将与共线要素(它们是相关的/强相关的)进行斗争,在这种情况下,它将只选择一个预测值来表示相关预测值的完整套件。这种选择也将以随机的方式进行,这不利于再现性和解释。

重要的是要注意,如果λ= 0,我们实际上没有正则化,我们将得到 OLS 解。当λ趋于无穷大时,系数将趋于 0,模型将只是一个常数函数。

里脊回归

Thanks to Kyoosik Kim

岭回归还在成本函数中增加了一个附加项,但取而代之的是对系数值的平方(L-2 范数)求和,并将其乘以某个常数λ。与 Lasso 相比,这个正则化项将减少系数的值,但不能强制系数正好为 0。这使得岭回归的使用在特征选择方面受到限制。然而,当 p > n 时,与 Lasso 不同,如果需要,它能够选择 n 个以上的相关预测因子。它还会选择共线特征组,发明者称之为“分组效应”

与 Lasso 非常相似,我们可以改变λ来获得具有不同正则化级别的模型,其中λ= 0 对应于 OLS,λ接近无穷大对应于常数函数。

有趣的是,对套索和岭回归的分析表明,这两种技术并不总是比另一种更好;人们必须尝试这两种方法来决定使用哪一种方法。

弹性网

Thanks to Wikipedia

弹性网包括 L-1 和 L-2 范数正则项。这给了我们套索和岭回归的好处。已经发现它具有比 Lasso 更好的预测能力,同时仍然执行特征选择。因此,我们可以两全其美,用山脊的特征组选择来执行 Lasso 的特征选择。

弹性网络带来了确定最优解的两个λ值的额外开销。

快速示例

使用 sklearn 中可用的波士顿住房数据集,我们将检查我们所有 4 个算法的结果。在这些数据的基础上,我对数据进行了缩放,并创建了 5 个额外的随机噪声“特征”,以测试每个算法过滤掉无关信息的能力。我不会做任何参数调整;我将实现这些现成的算法。你可以在 sklearn 的文档中看到默认参数。(线性回归套索山脊弹力网)。)我的代码很大程度上是从 Jayesh Bapu Ahire 的这篇文章中采用的。我的代码可以在我的 github 这里找到。

系数

Linear Regression Coefficients

我们可以看到,线性回归为我们的所有 5 个噪声特征分配了非零值,尽管它们都没有任何预测能力。有趣的是,这些噪声要素的系数大小与数据集中的一些真实要素相似。

Lasso Coefficients

正如我们所希望的,Lasso 做得很好,将我们的所有 5 个噪声特征减少到 0,以及数据集中的许多真实特征。这确实是一个比线性回归简单得多的模型

Ridge Regression Coefficients

岭回归犯了一个类似的错误,即非正则化线性回归,将系数值分配给我们的噪声特征。我们也看到一些特征具有非常小的系数。

Elastic Net Coefficients

很像套索,弹性网使几个特征的系数为 0。然而,它不像 Lasso 那样产生很多系数 0。

模型性能

Mean Squared Error of the different models

对于所提供的示例,根据 MSE,岭回归是最佳模型。这可能看起来违背直觉,但重要的是要记住岭回归模型用一些方差来换取偏差,最终导致总体误差更小。套索和弹性网模型用大量的方差换取了偏差,我们发现我们的误差增加了。

有趣的是,套索和弹性网比线性回归有更高的 MSE。但这是否意味着这些模型毫无疑问更糟糕呢?我认为不是,因为套索和弹性网模型也执行特征选择,这给了我们模型更好的可解释性。系数被解释为因变量的变化,预测值增加一个单位, 所有其他预测值保持不变。在复杂模型的情况下,不能合理地满足保持所有其他预测因子不变的假设。

最终,使用哪种模型最终取决于开始分析的目标。我们在寻找最好的预测吗?那么岭回归似乎是最好的。我们是否在寻找可解释性,寻找对底层数据的更好理解?那么弹性网可能是一条路要走。请记住,我没有参数调整。这些算法都有许多相关的参数,可以根据分析的目标调整这些参数来改进模型。作为数据科学从业者,我们的工作是定义这些期望(在分析开始之前),以帮助指导我们找到最佳解决方案。

结论

  1. 偏差-方差权衡是复杂模型和简单模型之间的权衡,其中中等复杂度可能是最好的。
  2. Lasso、Ridge Regression 和 Elastic Net 是普通最小二乘线性回归的修改,它们在成本函数中使用额外的惩罚项来保持较小的系数值并简化模型。
  3. 当数据集包含预测能力较差的要素时,Lasso 对于要素选择非常有用。
  4. 岭回归对于分组效果很有用,可以一起选择共线特征。
  5. 弹性网结合了套索和岭回归,有可能产生一个既简单又有预测性的模型。

机器学习中的人类偏见

原文:https://towardsdatascience.com/bias-what-it-means-in-the-big-data-world-6e64893e92a1?source=collection_archive---------20-----------------------

这对我们现代大数据世界意味着什么

偏见是人性不可避免的一部分。之前的研究表明,当人们分心时,认知偏差会优化大脑功能。偏见受到你的环境、经历的影响,并且很难消除。最小化偏见影响的一个方法是意识到你可能会遇到的偏见。

在这篇文章中,我将描述不同类型的偏见在机器学习项目中可能造成的一些影响。举例说明由这些偏见引起的问题的根源以及为什么偏见是有用的。

由于人类固有的偏见,偏见会反映在世界上存在的所有数据中。随着机器学习和大数据的日益普及和普及;世界上存在着难以想象的数据深度和可用工具。有了这些数据,偏见会影响数据和我们的推论。

偏差不仅仅存在于数据中,科学家在进行研究、实验或实现算法时也可能存在不可知的偏差。简单的步骤,例如在测试时不考虑某些参数或特性,可能会导致真正的后果。

Source

影响机器学习算法的偏差的术语是机器偏差。它与所用数据的偏差或研究者的偏差如何影响最终结果有关。机器偏差对现实世界有影响,会带来危险并强化系统偏差。

示例 1:图像识别中的采样偏差

对于自动驾驶汽车中的行人检测,有色人种更难分类。

Note: This was research from a scientific paper, which does not reflect commercial self-driving systems

这个具体问题是由采样偏差引起的,这是一种来自不平衡训练数据的偏差,它不能代表模型将在其中运行的环境。例如,只在美国农村的行人照片上训练的行人识别模型在多元文化的城市中不会很好地运行,因为来自两个人口的行人不会有相似的外观。

这个例子是在现实生活中实现的,因为社会正在向更多的自动驾驶汽车发展。这个问题很可能是由于在训练 CNN 算法时,训练数据中缺少来自代表性不足的背景的个体而引起的。这也可能是由于深色皮肤或深色衣服与背景之间的对比度较低的自然困难造成的。

示例 2:情感分析中的偏见

偏见偏见当算法接受来自数据源的细微偏见时,即使它被完美地采样。

用来描述这种偏见的经典例子是一个机器学习模型,它旨在区分照片中的男性和女性。训练数据包含厨房中女性的图片比厨房中男性的图片多,或者男性编码的图片比女性多,则算法被训练为由于数据中表示的真实世界中发生的偏见而对从事这些活动的人的性别做出不正确的推断。

情感分析是使用机器学习算法来检测文本主体的情感或主观情感。目前,这些算法通过利用预构建的单词嵌入来运行,单词嵌入是一种预设计的模型系统,用于产生从文本主体构建语言上下文的向量,以分析文本的情感。然而,几乎所有流行的单词嵌入都是在人类数据上训练的,如新闻文章( word2vec )或网页(手套)以及受到现实世界中偏见影响的

下面是使用手套嵌入和线性分类器构建的简单情感分析模型的输出示例。这个简单的情感分析模型的例子并没有反映消费者层面的系统。

text_to_sentiment("this example is pretty cool")
3.8899689260
text_to_sentiment("this example is ok")
2.7997773492
text_to_sentiment("meh, this example sucks")
-1.1774475917

这就是该系统的预期工作方式,即“相当酷”与其他积极的词相关,这给了它比“糟透了”更高的分数。

text_to_sentiment("Let's go get Italian food")
2.0429166109
text_to_sentiment("Let's go get Chinese food")
1.4094033658
text_to_sentiment("Let's go get Mexican food")
0.3880198556

偏见的影响出现了,因为带有单词“墨西哥”和“中国”的负面网页比带有单词“意大利”的负面网页多,所以带有“意大利”的情绪得分比其它单词更积极。

text_to_sentiment("My name is Emily")
2.2286179365
text_to_sentiment("My name is Heather")
1.3976291151
text_to_sentiment("My name is Yvette")
0.9846380213
text_to_sentiment("My name is Shaniqua")
-0.4704813178

这个例子与上一个类似,与不太常见的名字相比,更常见的名字往往出现在更积极的网页中,这提高了积极的情绪。

简单地说,种族偏见存在于情感分析系统中,因为种族偏见也出现在训练它的数据中。当单词的情感被网页训练时,在 GloVe 的情况下,种族单词或名字可能具有较低的情感,因为包含那些单词或名字的正面 web 评论和页面的数量较少。这在我们的模型中产生了种族偏见,因为给出的数据只会强化现实世界中存在的系统性偏见。

偏见以多种形式存在,例如刑事司法系统中带有预测模型的种族偏见并且很难纠正,因为它来自于现实世界中存在的偏见的反映。了解您正在处理的数据的领域知识,并意识到其中存在的复杂性,这一点很重要。

例子 3:算法偏差,策划“年度最佳播放”

有时候,这真的只是算法的问题。算法偏差是当算法,由于它是如何设计的,将有偏见内置。Spotify 每年都会根据你前一年听的歌曲创建一个播放列表。由于算法的设计,你两年前听的歌曲存在算法偏差。因为算法考虑了你听了多少前一个播放列表中的歌曲,它为那些歌曲建立了一个偏好。

但这并不是一件坏事

人类通常不会经历音乐偏好的剧烈变化。你前几年喜欢的歌曲在今年会变得更加有趣。偏差不是固有的负值,虽然算法中存在偏差,但算法在 Sporify 平台中是有效的。有偏差的训练数据是一种预处理数据。意识到这种偏见很重要,但这不一定是件坏事。

比如 LinkedIn 有一个 messenger 系统,有很棒的回复建议系统。这是因为 LinkedIn 训练其模型的信息更偏向于商务正式信息。有偏差的训练数据可以使基于使用它们的上下文的模型受益。LinkedIn 的回复推荐系统如果用于非正式的短信,效果不会很好,但对于基于职业生涯的专业网站中的商业信息来说是完美的。

重要的是要意识到在分析过程的每一步中可能出现的偏差。意识到偏见以及它们如何通过上下文影响我们的模型是很重要的,因为它可能是致命的缺陷,也可能是惊人的好处。随着世界上收集和分析的数据越来越多,了解数据的所有细节和复杂性非常重要。

理解机器学习算法就是算法很重要。在统计和编程的下面是简单地试图最大化或最小化一个等式的数学等式。说到底,大家都明白“垃圾进就是垃圾出”。

注意:因为我想把重点放在可能来自数据或模型实现的偏差形式上,所以我选择谈一点关于统计和机器学习偏差的技术定义。

参考

1 S. Plous,《偏见、定型和歧视的心理学:概述》 (2003 年),理解偏见和歧视(第 3-48 页)。美国纽约州纽约市:麦格劳-希尔公司。

[2] S. Lee 和 S. Lebowitz, 20 种让你的决定变得一团糟的认知偏见 (2015),商业内幕

3 B. Wilson,J. Hoffman 和 J.Morgenstern,物体检测中的预测不平等 (2019),arXiv

[4] A. Caliskan,J. J Bryson 和 A. Narayanan,从包含类人偏见的语言语料库中自动导出的语义 (2017),科学356 (6334),183–186。https://doi.org/10.1126/science.aal4230

[5] R. Speer,如何在不真正尝试的情况下制造一个种族主义的人工智能 (2017),ConceptNet 博客

[6] J. Angwin,J. Larson,S. Mattu 和 L. Kirchner,机器偏差 (2016),Propublica

大数据分析:Spark 和 Hadoop

原文:https://towardsdatascience.com/big-data-analysis-spark-and-hadoop-a11ba591c057?source=collection_archive---------8-----------------------

介绍大数据和用于处理大数据的不同技术,如 MapReduce、Apache Spark 和 Hadoop。

(Source: https://images.xenonstack.com/blog/10-vs-of-big-data.png)

大数据

据《福布斯》报道,每天产生大约 2.5 万亿字节的数据。尽管如此,这个数字预计在接下来的几年里会不断增加(90%的现有存储数据是在过去两年内产生的)1

大数据不同于存储在关系数据库中的任何其他大量数据的地方在于它的异构性。这些数据来自不同的来源,并且是用不同的格式记录的。

通常采用三种不同的数据格式化方式:

  • 非结构化 =无组织的数据(如视频)。
  • 半结构化 =数据以不固定的格式组织(如 JSON)。
  • 结构化 =数据以结构化格式存储(如 RDBMS)。

大数据由三个属性定义:

  1. =由于数据量大,在单台机器上存储数据是不可能的。我们如何在多台机器上处理数据以确保容错?
  2. 多样化=我们如何处理来自不同来源、使用不同模式格式化的数据?
  3. 速度 =如何快速存储和处理新数据?

可以使用两种不同的处理技术来分析大数据:

  • 批处理 =通常在我们关心数据的数量和种类时使用。我们首先存储所有需要的数据,然后一次性处理这些数据(这会导致高延迟)。一个常见的应用示例是计算每月工资总额。
  • 流处理 =如果我们对快速响应时间感兴趣,通常会采用。我们一收到数据就进行处理(低延迟)。一个应用示例可以是确定银行交易是否是欺诈性的。

大数据可以使用不同的工具进行处理,如 MapReduce、Spark、Hadoop、Pig、Hive、Cassandra 和 Kafka。每一种不同的工具都有其优势和劣势,这决定了公司可能决定如何使用它们[2]。

Figure 1: Big Data Tools [2]

现在,许多公司普遍使用大数据分析来预测市场趋势、个性化客户体验、加快公司工作流程等

MapReduce

当处理大量数据并且资源耗尽时,有两种可能的解决方案:水平扩展或垂直扩展。

在水平扩展中,我们通过添加更多相同容量的机器和分配工作负载来解决这个问题。如果使用垂直扩展,我们可以通过增加机器的计算能力(如 CPU、RAM)来进行扩展。

垂直缩放比水平缩放更容易管理和控制,并且在处理相对较小的问题时被证明是有效的。尽管如此,在处理大型问题时,水平缩放通常比垂直缩放更便宜、更快。

MapReduce 基于水平缩放。在 MapReduce 中,计算机集群用于并行化,从而更容易处理大数据。

在 MapReduce 中,我们将输入数据分成许多部分。然后,每个零件被发送到不同的机器进行处理,最后根据指定的 groupby 函数进行汇总。

Figure 2: MapReduce in action 3

阿帕奇火花

Apache Spark 框架是作为 MapReduce 的改进而开发的。让 Spark 从竞争对手中脱颖而出的是它的执行速度,比 MapReduce 快 100 倍左右(中间结果不存储,一切都在内存中执行)。

Apache Spark 通常用于:

  1. 读取存储和实时数据。
  2. 预处理大量数据(SQL)。
  3. 使用机器学习和流程图网络分析数据。

Figure 3: Apache Spark Libraries [4]

Apache Spark 可以配合 Python、R、Scala 等编程语言使用。为了运行 Spark,通常使用基于云的应用;如亚马逊网络服务、微软 Azure 和 Databricks(提供免费社区版)。

使用 Spark 时,我们的大数据通过弹性分布式数据集(rdd)实现并行化。rdd 是 Apache Spark 最基本的抽象,它获取我们的原始数据并将其划分到不同的集群(workers)中。RRD 是容错的,这意味着它们能够在任何一个工人失败的情况下恢复丢失的数据。

rdd 可用于在 Spark 中执行两种类型的操作:转换和操作(图 4)。

Figure 4: Apache Spark Workflow [5]

转换从 RDD 创建新的数据集,并返回结果 RDD(例如,通过关键操作进行映射、过滤和归约)。所有的转换都是惰性的,它们只在一个动作被调用时执行一次(它们被放在一个执行图中,然后在一个动作被调用时执行)。

取而代之的是使用动作从 Apache Spark 中获取我们的分析结果,并将一个值返回给我们的 Python/R 应用程序(例如收集和获取操作)。

为了在 Spark 中存储键/值对,使用对 rdd。rdd 对由存储在元组中的两个 RRD 组成。第一个元组元素用于存储键值,第二个元组元素用于存储值元素(key,value)。

Hadoop

Hadoop 是一组用 Java 编写的开源程序,可用于对大量数据执行操作。Hadoop 是一个可扩展、分布式和容错的生态系统。Hadoop 的主要组件有[6]:

  • Hadoop YARN =管理和调度系统资源,将工作负载划分到一个机器集群上。
  • Hadoop 分布式文件系统(HDFS) =是一个集群文件存储系统,旨在提供容错、高吞吐量和高带宽。它还能够以任何可能的格式存储任何类型的数据。
  • Hadoop MapReduce =用于从数据库中加载数据,对其进行格式化并对其进行定量分析。

Figure 5: Hadoop Ecosystem [7]

Hadoop 的一些应用示例有:搜索(如雅虎)、日志处理/数据仓库(如脸书)和视频/图像分析(如纽约时报)。

Hadoop 传统上是第一个大规模使用 MapReduce 的系统,尽管 Apache Spark 由于其更快的执行速度而成为许多公司的首选框架。

结论

大数据一词最初被用来描述一个问题:我们产生的数据超过了我们实际处理的能力。经过多年的研究和技术进步,大数据现在被视为一个机遇。由于大数据,人工智能和深度学习的最新进展已经成为可能,使机器能够执行几年前似乎不可能执行的任务。

联系人

如果你想了解我最新的文章和项目,请通过媒体关注我,并订阅我的邮件列表。以下是我的一些联系人详细信息:

文献学

1什么是大数据?—大数据世界入门指南。阿努什里·苏布拉马年,爱德华卡!。访问地点:https://www.edureka.co/blog/what-is-big-data/

[2]查看一些最著名的大数据工具及其优缺点,以分析您的数据。机器人之家。访问:https://www . houseofbots . com/news-detail/12023-1-see-some-best-known-big-data-tools-there-advantage-and-missives-to-analyze-your-data

3什么是 MapReduce?。莎娜.珀尔曼塔伦德。访问地点:【https://www.talend.com/resources/what-is-mapreduce/

[4] Apache Spark 文档。访问地点:【https://spark.apache.org/

[5]Apache Spark 的转换和操作是如何工作的…亚历克斯·安东尼,中号。访问:https://medium . com/@ aristo _ Alex/how-Apache-sparks-transformations-and-action-works-CEB 0d 03 b 00d 0

[6] Apache Hadoop 用 5 分钟或更短时间解释。什拉万蒂·登特姆达斯·克雷德拉。访问地址:https://www . credera . com/blog/technology-insights/open-source-technology-insights/Apache-Hadoop-explained-5-minutes-less/

[7] Hadoop 生态系统及其组件—完整教程。数据天赋。访问地址:https://data-flair . training/blogs/Hadoop-ecosystem-components/

大数据分析:用 PySpark 预测客户流失

原文:https://towardsdatascience.com/big-data-analytics-predicting-customer-churn-with-pyspark-19cd764f14d1?source=collection_archive---------10-----------------------

Photo by Leio McLaren (@leiomclaren) on Unsplash

对于任何基于订阅的商业模式来说,一个更紧迫的问题是什么让人们订阅,更重要的是退订。带上你的 Spotify-s、Pandora-s 或网飞-es。这些公司的核心收入来源于用户订阅费。因此,如何留住这些客户对他们的生存至关重要。

了解客户流失

在客户群的背景下,good ol' Wikipedia 将流失率定义为“在给定时间段内离开供应商的合同客户或订户的比例”。换句话说,有多少人在弃船(或大锅)?他们可能会订阅竞争对手的业务,或者完全放弃这项服务。

Design by Artpunk101

如果你错过了,大锅是服务的隐喻,泄漏是流失的隐喻。

更确切地说,如果我们的大锅漏得比灌得快,那么它将不可避免地干涸。这是我们当前项目的主要问题:预测哪些用户可能会取消在线音乐流媒体服务的订阅,更重要的是,为什么

让我们从检查我们拥有的数据集开始。

完整的数据集是一个非常细粒度的用户日志,存储在 AWS 上的 12 GB json 文件中——在这样的大小下,只有 Spark 这样的大数据框架才是可行的。为了理解可用的特性并构建我们的模型,我们将从使用一小部分数据开始(大约 128 MB)。该示例将在单台计算机上用于探索性数据分析。

第一步是加载我们的数据,如下所示:

让我们通过打印模式来享受丰富的数据:

root
 |-- artist: string (nullable = true)
 |-- auth: string (nullable = true)
 |-- firstName: string (nullable = true)
 |-- gender: string (nullable = true)
 |-- itemInSession: long (nullable = true)
 |-- lastName: string (nullable = true)
 |-- length: double (nullable = true)
 |-- level: string (nullable = true)
 |-- location: string (nullable = true)
 |-- method: string (nullable = true)
 |-- page: string (nullable = true)
 |-- registration: long (nullable = true)
 |-- sessionId: long (nullable = true)
 |-- song: string (nullable = true)
 |-- status: long (nullable = true)
 |-- ts: long (nullable = true)
 |-- userAgent: string (nullable = true)
 |-- userId: string (nullable = true)

探索性分析

粗略地看了一下数据,我们注意到有些行中缺少了用户 Id。经过进一步调查,似乎只有以下页面没有 userId :

+ — — — — — — — — — -+
|                page|
+ — — — — — — — — — -+
|                Home|
|               About|
| Submit Registration|
|               Login|
|            Register|
|                Help|
|               Error|
+ — — — — — — — — — -+

这让我们相信这些没有 ID 的页面点击来自那些没有注册、没有登录或者没有播放音乐的人。所有这些页面最终都会导致播放音乐。然而,由于这些行包含的大部分都是空值,所以在开始分析之前,我们将删除它们。

仅从上一节的特性名称列表中,我们就可以知道数据有多丰富。可以肯定地说,用户与应用程序的每一次交互都会被记录下来。

在不深入数据的情况下,我们首先需要定义变动。对于我们的项目来说,一个不安的用户就是访问了“取消确认”页面的人。这是用户确认取消请求的地方。此后,任何访问过该页面的用户都将被归类为“搅动者”,否则他们将被视为“非搅动者”。

对我们来说幸运的是,打印出页面特性中的类别表明它就有这样一个值。

+-------------------------+
|page                     |
+-------------------------+
|About                    |
|Add Friend               |
|Add to Playlist          |
|Cancel                   |
|***Cancellation Confirmation***|
|Downgrade                |
|Error                    |
|Help                     |
|Home                     |
|Login                    |
|Logout                   |
|NextSong                 |
|Register                 |
|Roll Advert              |
|Save Settings            |
|Settings                 |
|Submit Downgrade         |
|Submit Registration      |
|Submit Upgrade           |
|Thumbs Down              |
|Thumbs Up                |
|Upgrade                  |
+-------------------------+

通过查看随机用户活动的一些选定列,我们可以获得更好的洞察力。

+--------------------+-------------+---------+-----+---------+
|              artist|itemInSession|   length|level|     page|
+--------------------+-------------+---------+-----+---------+
|         Cat Stevens|            0|183.19628| paid| NextSong|
|        Simon Harris|            1|195.83955| paid| NextSong|
|         Tenacious D|            2|165.95546| paid| NextSong|
|          STEVE CAMP|            3|201.82159| paid| NextSong|
|             DJ Koze|            4|208.74404| paid| NextSong|
|           Lifehouse|            5|249.18159| paid| NextSong|
|Usher Featuring L...|            6|250.38322| paid| NextSong|
|                null|            7|     null| paid|Thumbs Up|
|            Harmonia|            8|655.77751| paid| NextSong|
|           Goldfrapp|            9|251.14077| paid| NextSong|
+--------------------+-------------+---------+-----+---------+

或者我们可以观察一天中什么时候歌曲播放最多。结果是在中午或午餐时间。

xkcd-like scatter plot

特色工程

既然我们已经清楚地确定了流失的用户,那么是时候戴上数据科学的帽子,尝试确定流失率的影响因素了。如果一个人对服务不满意,他会怎么做? 我将尝试用以下 6 个工程特性来回答这个问题:

  1. 用户播放歌曲的平均小时数

也许没有享受这项服务的人倾向于在每天不同的时间播放音乐。很明显,这两组之间的差异可以忽略不计。搅动和非搅动用户之间的实际值分别为 11.74 和 11.71。只差了 1 分 48 秒。然而,我们将把它保留在我们的模型中,因为一旦我们把它与我们将要创建的其他特性结合起来,它可能会被证明是有用的。

2。性别

我们的音乐流媒体服务可能对某一性别更有吸引力。值得调查的是,某一性别是否在被搅动的用户中被过度代表。我们将为性别创建一个虚拟变量,男性的值为 1,女性的值为 0。

通过按性别和流失率对用户进行分组,我们可以清楚地看到,在流失率较高的群体中,男性的比例过高。62%的呕吐过的用户是男性,而非呕吐过的用户中只有 51%是男性。所以男性更有可能取消订阅。

+-----+------------------+
|churn|   avg(gender_dum)|
+-----+------------------+
|    1|0.6153846153846154|
|    0|0.5144508670520231|
+-----+------------------+

3。活动天数

刚刚注册这项服务的人可能还没有对这项服务形成真正的看法。首先,他们没有足够的时间尝试所有不同的功能。人们也需要时间来适应任何新软件。这在理论上应该会让那些订阅时间不长的新用户更有可能取消订阅或流失。

事实证明,我们的理论是准确的,新用户比老用户更有可能取消。

4。会话数量

更频繁登录的用户享受这项服务是有道理的,因为他们使用它的频率更高了。有人登录的次数越多,就越有可能继续使用我们的服务。

事实证明这是准确的。类似于日活动功能,新用户或不经常使用该服务的人更有可能取消。

5。每期平均歌曲数量

重要的不仅仅是会议的数量,还有质量。即使对于偶尔播放音乐的用户来说,他们仍然可以每次持续收听大量歌曲。表明体验良好,尽管他们使用的次数很少。

虽然差别很小,但肯定是看得见的。这种影响可能不如前两个计算的特征那么显著,但它足够明显,可以保留在我们的分析中,并找出它的相关性。

6。遇到的错误数量

我们能收到的最烦人的消息之一是错误消息。尤其是干扰我们全神贯注的东西,如流媒体电影或音乐。平均而言,经历更多错误的用户应该更有可能取消他们的服务,因为他们有过更糟糕的经历。我们来看看判决结果。

事实证明,兴奋的用户经历的错误更少。这可能是因为非搅动用户活跃的时间范围更长。因此,我们使用这项服务的时间越长,就越有可能出错。从各方面考虑,错误率很低。

构建我们的模型

随着我们的功能得到适当的设计,我们将训练三个模型,并选择最好的一个:

  1. 逻辑回归
  2. 随机森林
  3. 梯度增强树

在我们构建模块化代码的尝试中,我们编写了一个函数,为每个模型构建一个管道并运行它。如果我们想要在具有不同超参数的数据上训练我们的模型,也需要参数网格。

在从超参数的组合中找到最佳拟合模型后,它由我们的函数返回。然后,我们可以将每个模型应用于我们的测试数据,并通过使用标准的评估度量来计算它的准确性。在这种情况下,我们将使用 F1 的分数。

F1 分数是精确度和召回率的加权平均值。这是一个很好的衡量一般问题的方法,因为它不会仅仅因为假阳性或假阴性而严重扭曲。当我们的阶级分布不均匀时,这一点特别有用,这正是我们现在的情况。

最终结果是:

The F1 score for the logistic regression model is: 0.825968664977952
The F1 score for the random forest model is: 0.8823529411764707
The F1 score for the gradient-boosted tree is: 0.8298039215686274

通过使用相同的指标,我们可以很容易地比较所有 4 个模型,并得出结论,在这个“较小”的数据集中,预测用户流失最准确的模型是随机森林分类器。

全数据集训练

下一步是获取我们的功能代码,并在 AWS 上的集群上运行它。我们在尝试对整个数据集进行分析时遇到了几个问题。虽然这些问题看起来很小,但考虑到 Spark 集群处理数据所花费的时间,解决它们需要很长时间。

首先,集群上的熊猫版本已经过时。我们通过简单地将有问题的方法从“toPandas()”改为“show()”来解决这个问题。虽然输出看起来不那么吸引人,但它达到了目的。

其次,Spark 在一定时间后超时,这使得超时前的结果无用。我能找到的唯一可行的解决方案是增加集群大小,以缩短处理代码所需的时间。

这是一个令人惊讶的问题,因为 Spark 是一个大数据框架,所以预计会有很长的处理时间。

第三,鉴于超时问题以及处理一个模型上的数据需要多少时间,对超参数执行网格搜索被证明是特别具有挑战性的。所以为了我们自己的理智,我们使用默认参数作为我们选择的分类器。

最后,最大的问题发生在模型评估阶段。即使模型被训练得没有任何明显的问题,我仍然得到下面的错误消息,并且找不到解决方法。

Exception in thread cell_monitor-17:
Traceback (most recent call last):
  File "/opt/conda/lib/python3.6/threading.py", line 916, in _bootstrap_inner
    self.run()
  File "/opt/conda/lib/python3.6/threading.py", line 864, in run
    self._target(*self._args, **self._kwargs)
  File "/opt/conda/lib/python3.6/site-packages/awseditorssparkmonitoringwidget-1.0-py3.6.egg/awseditorssparkmonitoringwidget/cellmonitor.py", line 178, in cell_monitor
    job_binned_stages[job_id][stage_id] = all_stages[stage_id]
KeyError: 1256

我无法正确地衡量准确性或找到随机森林分类器的混淆矩阵。不幸的是,我们只能假设,当使用 AWS 上的集群训练完整数据集时,该模型的性能会更好。

特征重要性

从商业角度来看,模型的准确性并不是决策者唯一感兴趣的事情。他们还想知道到底是什么促使人们取消或退订他们的服务。下图显示了每个特性在决策中的确切作用。

+--------------+----------+
|feature       |importance|
+--------------+----------+
|days_active   |0.4959    |
|n_sessions    |0.2146    |
|avg_play_hour |0.1355    |
|avg_sess_songs|0.1009    |
|n_errors      |0.0386    |
|gender_dum    |0.0145    |
+--------------+----------+

事实证明,在预测用户流失时,活跃天数和流媒体音乐的会话数是最重要的特征。

结论

概括地说,我们利用 PySpark,或者 Python 的 Spark。有了这个框架,我们构建了一个端到端的机器学习工作流。该工作流可以通过分析每个用户与所述服务的交互来识别音乐流服务的潜在客户。

数据探索这一步非常有趣,因为我们可以从用户的习惯中清楚地看到他们的行为。至少可以说,看看一些会议持续了多长时间,持续到多晚,以及音乐类型在一天的不同时间是如何变化的,是很有趣的。

工程特征集中于各种行为。它们包括与服务的互动,或者注重时间和个性而不是音乐品味的聆听习惯。这些行为还包括对服务满意度的测量,例如用户遇到的错误总数。在训练我们的模型之前,所选择的特征被缩放到范围[0,1],以便较大的值不会扭曲模型。最后,我们发现我们组中最好的模型是随机森林分类器。我们试图在完整的数据集上训练它,以获得更好的结果。

大数据分析有其独特的挑战。调试如此漫长的过程被证明是非常耗时的。但最后,这是一个非常有趣的练习,结果更有趣。

未来的改进

尽管有些模型表现得出人意料地好,我还是很想看看对最成功的模型进行交叉验证的结果。微调超参数可能会产生模型的优化版本,该版本可能足够健壮以用于生产。但是为了达到这个结果,我们要么需要更多的电脑,要么需要更多的咖啡。

大数据与海洋运输的环境影响。

原文:https://towardsdatascience.com/big-data-and-environmental-impact-of-the-maritime-transportation-299030dbb929?source=collection_archive---------27-----------------------

我们如何利用机器学习和大数据来拯救地球。

封面照片是住在港口附近的人都知道的一个例子。平均而言,每一艘停泊在欧洲港口的船只,都有另一艘在外面等待,等待的环境影响与停泊在港口内的环境影响相比较。我们发现这种影响可以减少 80%。

在我们之前的文章【1】中,我们提到我们发现了奇怪船只行为的数字痕迹。船只花费大量时间在港口和锚地附近停泊或移动。
这些等待时间以及港口内的等待时间对当前和未来船舶的燃料消耗以及温室气体、颗粒物、NOₓ和 SOₓ的排放造成了重大影响,增加了港口运营对当地环境的影响。
欧盟( EU Regulation 2015/757 )要求自 2018 年 1 月 1 日起,所有船只在欧盟区域内从事进出欧盟区域的航运活动时,必须申报 CO₂。这些数据包括在港口停泊期间的 CO₂排放量,但不包括在港口外等待期间的排放量。

我们对这些等待时间和相关排放的估计感兴趣,因为它们不会带来任何价值,并且是由港口拥挤或船长或货船基于经济的决策造成的。

文章由四部分组成:

  • 数据预处理,我们给出等待轨迹的细节。
  • CO₂排放的可用数据,其中我们概述了不同制度下不同船舶的 CO₂排放数据的估算算法。
  • CO₂的总排放量,我们比较港口和国家的综合排放量。
  • 呼吁采取行动,我们提出了减少海岸线附近 CO₂排放量的两种方法,并量化了这些方法的可能结果。

Trajectories of the vessels waiting to enter Le Havre port.

数据预处理。

Mariquant 从 2016 年初到 2018 年年中,从一家 AIS 数据提供商获得散货船和油轮的每小时数据。该数据包含来自约 19 000 艘有记录的独特船只的信息,作为未压缩的拼花文件大约占用 100 Gb。

我们有一个多边形库,有大约 8 000 个港口和 20 000 个锚地和等候区。大多数时候,锚泊多边形位于端口多边形之外,我们使用图形算法来确定哪个锚泊属于哪个端口。

我们使用随机森林分类器[2]来寻找船只轨迹上的等待点。您可以在之前的文章“从 AIS 数据的海洋中创建海上航线”【1】中找到我们方法的详细信息。

除了用于路线准备的保守检查外,我们还增加了额外的入口-出口检查。如果 80%的轨迹段之间的角度小于 15 度,则我们排除所有的开始和结束轨迹段。

在这种方法中,上图中那些看似直的短直线实际上是“卷曲的”,如下图所示。

关于 CO₂排放量的现有数据。

大多数船只不使用测量排放的仪器方法;而且,相当比例的船舶甚至没有燃油流量计。因此,可用的报告(如3和[5])是从理论估计构建的。一些初创企业/扩大规模的企业对这个问题有部分解决方案,但没有一个被业界接受。
此外,测量结果总有可能被船员轻易篡改(就像传感器周围的过滤器)。

This photo presumably shows a smoke trail of the Russian aircraft carrier; however, this is a photoshopped image of the Mount Etna eruption. Original image: Istituto Nazionale di Geofisica e Vulcanologia, Sezione di Catania.

令人失望的是,留给我们的要么是技术效率的理论估计,要么是船东/管理公司提供的数据。我们决定使用来自 EU-MRV 系统的报告数据,因为它被认为是由独立评估人验证并被欧盟委员会接受的。

对于每艘船(IMO ),该数据包含:

  • 总燃料消耗量[百万吨]*
  • CO₂总排放量[百万吨]
  • MS 管辖范围内港口间所有航程的 CO₂排放量[m 吨]
  • 从 MS 管辖的港口出发的所有航程的 CO₂排放量[m 吨]
  • MS 管辖范围内港口所有航次的 CO₂排放量[m 吨]
  • 在 MS 管辖范围内的港口泊位发生的 CO₂排放量[m 吨]
  • 每公里年平均 CO₂排放量[千克 CO₂ /英里]
  • 在海上度过的总时间[小时]

-此处的“m 吨”是公吨

根据现有数据,无法直接计算油耗和 CO₂排放量。燃料消耗与船速呈非线性(立方)关系。它还取决于浪高、海流和风速、螺旋桨类型,甚至取决于船体的状况(藤壶会增加燃料消耗)。考虑到这些限制,我们知道我们可以获得 CO₂排放量的高水平估计。

在锚泊过程中,船舶可能不使用主发动机,而是使用所谓的辅助发动机来提供电力、热量、动力泵等。另一个限制是对这些发动机排放的估计,因为它不依赖于主发动机的性能。一些研究[4]估计,辅助发动机产生大约 30%的总排放量。考虑到这些因素,我们决定用 CO₂/seconds 在港外航行时的音调来估算排放量。

co2_table['em/s'] = (co2_table['Between'] + co2_table['Depart'] + co2_table['Arrive'])/(co2_table['Time'] * 3600)

有趣的是(因为原始数据需要验证),有一些极端的异常值,我们决定忽略:

输入缺失数据

EU-MRV 系统拥有 2018 年进入欧盟港口的船只数据,这只是我们数据库中的一部分船只。因此,我们需要找到一种方法来估计这些不存在的船只的排放量。

根据现有数据计算排放量的可能性

船舶发动机排放可能与船舶特征、其宽度、LoA(总长度)和 DWT(载重量)相关。为了验证我们的假设,我们可以运行主成分分析 (PCA)并可视化相关性。

from sklearn.preprocessing import StandardScaler
data = train[['beam','loa','dwt', 'em/s']].values
scaler = StandardScaler()
scaler.fit(data)
strain = scaler.transform(data)from sklearn.decomposition import PCA
pca = PCA(n_components=3)
pca.fit(strain[:,0:3], strain[:,3])  
print(pca.explained_variance_ratio_)
ps_train = pca.fit_transform(strain[:,0:3])pres_df = pd.DataFrame(data=ps_train, columns=["pca-one", "pca-two", "pca-three"]).assign(y=strain[:,3])import seaborn as sos
g = sns.PairGrid(pres_df, vars=["pca-one", "pca-two", "pca-three"], height=5, palette="rocket",
                 hue="y")
g = g.map_diag(plt.hist, edgecolor="w")
g = g.map_offdiag(plt.scatter, edgecolor="w", s=40)

可以清楚地看到数据中有一些聚类。

Pair grid of the PCA dimension scatter plots and emission levels (as hue)

t-SNE 分析是另一种通常对数据可视化非常有用的方法,但在这种情况下,它不能提供清晰的图像。

Results of the T-SNE analysis

回归模型的选择

发动机排放回归模型的结果高度依赖于训练集的选择。因此,我们需要使用交叉验证来选择可能的回归变量。我们使用 Scikit-learn[2]实现各种回归变量。

from sklearn.linear_model import BayesianRidge
from sklearn.tree import DecisionTreeRegressor
from sklearn.ensemble import ExtraTreesRegressor
from sklearn.neighbors import KNeighborsRegressor
from sklearn.gaussian_process import GaussianProcessRegressor
from sklearn.linear_model import Lasso
from sklearn.model_selection import cross_val_score
from sklearn.gaussian_process.kernels import DotProduct, WhiteKernel
from sklearn.ensemble import GradientBoostingRegressorN_SPLITS = 12

estimators = [
    BayesianRidge(),
    DecisionTreeRegressor(max_features='sqrt', random_state=0),
    ExtraTreesRegressor(n_estimators=80, random_state=0),
    KNeighborsRegressor(n_neighbors=15),
    RandomForestRegressor(random_state=0, n_estimators=80, n_jobs=-2),
    Lasso(alpha=0.1),
    GaussianProcessRegressor(kernel = DotProduct() + WhiteKernel(), normalize_y = True),
    GradientBoostingRegressor(n_estimators = 500, max_depth = 4,    min_samples_split = 2, learning_rate = 0.01, loss = 'ls', max_features = 'sqrt')
]scores = pd.DataFrame()
for estimator in estimators:scores[estimator.__class__.__name__] = \
        np.sqrt(np.abs(cross_val_score(
            estimator, ps_train, train['em/s'].values, scoring='neg_mean_squared_error',
            cv=N_SPLITS
        )))

我们得到了以下结果:

Average value and standard deviation of the RMSE for various regressors.

有趣的是,K-neighbors 回归给出了平均误差和标准偏差的最佳或次佳结果。它的性能与梯度提升一样好,并且优于随机森林。由于 K 近邻和梯度推进是完全不同的方法,我们可以尝试使用它们的集合。由于所有可用数据的限制,我们做这个练习纯粹是为了练习本身

我们使用来自 Scikit-learn[2]的投票回归器作为集合的基础,并且我们对 N_fold 运行的结果进行平均。

from sklearn.ensemble import VotingRegressordef predict_voting_fold(ereg, X_full, y_full, N_Fold, X_test, y_pred):
    mask = np.random.choice([True, False], len(X_full), p=[0.75, 0.25])
    ereg.fit(X_full[mask,:], y_full[mask])

    if y_pred is None:
        y_pred = np.reshape(ereg.predict(X_test), (-1, 1))
    else:
        for regressor in regressors:
            y_pred = np.concatenate((y_pred, np.reshape(ereg.predict(X_test), (-1, 1))), axis=1)
    if y_pred.shape[1] == N_Fold:
        return y_pred
    else:
        y_pred = predict_voting_fold(ereg, X_full, y_full, N_Fold, X_test, y_pred)
        return y_predregressors = [kn, gb]
estimators=[(regressor.__class__.__name__, regressor) for regressor in regressors]
ereg = VotingRegressor(estimators=estimators, n_jobs=-1)

对于训练集和测试集,结果如下:

Train 0.00033457086294885844
Test 0.0003675358631052121

这比测试样本的简单平均要好得多:

Train 0.0003324765794757066
Test  0.0003685629826696926

现在,我们可以计算剩余船只的排放水平,并计算欧洲海岸附近海事部门的温室气体排放量。

CO₂排放总量

我们发现港口外的排放量至少与泊位处的排放量相当:

  • 2016 年港口外的排放量为 2 86 万公吨 co₂(2018 年泊位排放量的 88 %)
  • 2017 年,他们贡献了至少 3 32 万公吨的 co₂(2018 年泊位排放量的 102 %)
  • 2018 年前六个月,它们是 1 588 000 公吨。

这一排放水平相当于丹麦、瑞典或葡萄牙等国家年排放量的大约 8%(根据“全球碳地图集】)。

2017

由于大量的港口停靠,瓦莱塔、鹿特丹、直布罗陀、汉堡和安特卫普是 CO₂生产的前五名。安特卫普每次停靠港口的排放量最小,瓦莱塔最大。前 50 名中每次停靠港口排放量最大的港口是——斯海弗宁根(鹿特丹和安特卫普附近的锚地)、南沃尔德转运区(英国东南海岸附近的地区)、福斯港、布林迪西和康斯坦察港。

排放量最大的国家是联合王国,尽管主要原因是直布罗陀。接下来的两年,马耳他、罗马尼亚、波兰、挪威和荷兰(2016 年为丹麦)的港口碳排放量值得关注。

CO2 emissions by vessels and by capital city

马耳他(全国)、荷兰、法国、挪威(因为奥斯陆的排放量最低)和比利时的船舶排放量占首都排放量的比例最大。我们使用的是来自欧洲绿色城市指数—西门子全球碳地图集和其他来源的 CO₂排放数据。

2018

2018 年上半年,鹿特丹成为最大的排放源,其次是瓦莱塔、直布罗陀和汉堡。伦敦港取代安特卫普成为 CO₂五大生产商之一。前 50 名中每次停靠港口排放量最高的港口是奥克尼港、米尔福德港、瓦莱塔、阿姆斯特丹和格丁尼亚。

2018 年,英国仍是最大的 CO₂生产国。worths 的每停靠港口排放量是在马耳他、挪威、斯洛文尼亚、荷兰和罗马尼亚。

CO2 emissions by vessels and by capital city (percentage is projected)

与 2017 年一样,马耳他、荷兰、法国、挪威和比利时的船舶排放量与首都城市排放量之比最大。

呼吁采取行动

我们认为,至少有两种方法可以减少近海海域的碳足迹:

  1. 港口优化——从“先来先服务”转向“及时”服务模式。
  2. 由于经济决策而减少等待时间。

量化这些可能性的结果可以如下进行:

Port of Valetta waiting times. Yellow - outliers, green — opportunity for optimisation.

  1. 我们可以将等待时间建模为两个因素:
  • 常规端口入口-出口,其中入口-出口时间近似为高斯(可能是偏斜的)分布。
  • 经济决策导致的异常等待时间,例如,将船舶转到浮动仓库、港口在周末不运营等。我们通过稳健 Z-score 方法选择它们作为极端异常值。

2.政治决策可以减少由异常等待时间造成的大部分排放。

3.定期的港口进出时间可以最小化到至少中间时间。港口作业优化可以实现这种减少。

根据对 2018 年上半年全欧洲可能减少的估计,通过政策变化,我们可以实现 357,000 m 吨,通过港口运营优化,我们可以实现 878,000 m 吨。这些减少构成了总体温室气体排放减少 77%。

当查看不同国家的减排机会时,可以看到联合王国和比利时的港口优化机会的减排量大于排名第二的国家(相应地为意大利和希腊)的当前总排放量。
港口优化可实现的减排比例最大的前 5 个国家是阿尔巴尼亚(80%)、挪威(77%)、芬兰、爱沙尼亚(各 69%)和克罗地亚(64%)。
总的来说,与港口优化相比,由于实施新政策导致的减少量较小。由于新政策,降幅最大的前五个国家是斯洛文尼亚(37%)、马耳他(36%)、罗马尼亚、瑞典和保加利亚(各 30%)。

Heatmap with emissions around the ports aggregated by week 2016–2018

关于 Mariquant

Mariquant 是一家专注于分析工具开发的公司。我们相信,在海事行业持续广泛地采用数据驱动的分析方法将会产生巨大的价值。然而,较差的数据质量、覆盖范围和庞大的数据量对许多人来说是一个障碍,导致他们经常走上自上而下的分析之路,其中涉及大量的手动工作。

在 Marquant,我们通过采用亚马逊(Amazon)和谷歌(Google)等公司开发的尖端技术来挑战这些障碍,但同时保持对海事行业需求的高度关注。引入全自动、数据驱动的分析允许扩展到海事中发现的单个案例的数量级,从而允许及时、准确和慎重的商业决策。

参考

  1. 阿列克谢·诺维科夫,“从 AIS 数据的海洋中创建海上航线”,(https://towards data science . com/creating-sea-routes-from-the-sea-of-ais-data-30 BC 68d 8530 e)
  2. 佩德雷戈萨sci kit-learn:Python 中的机器学习,JMLR 12,第 2825–2830 页,2011 年。
  3. Lasse Johansson,Jukka-Pekka Jalkanen,Jaakko Kukkonen,“2015 年全球航运排放高时空分辨率评估”,《大气环境》,第 167 卷,2017 年,第 403–415 页,
    ISSN 1352–2310,https://doi.org/10.1016/j.atmosenv.2017.08.042
    (http://www . science direct . com/science/article/pii/s 1352231017305563)
  4. 海事工作组,“波罗的海海洋环境保护委员会,2017 年波罗的海航运排放”,德国汉堡,2018 年 9 月 25 日至 27 日,(https://portal . helcom . fi/meetings/MARITIME % 2018-2018-503/meeting documents/4-3% 20 排放% 20from %波罗的海% 20Sea %航运%20in%202017.pdf
  5. 《2013-2015 年全球航运的温室气体排放》国际清洁交通理事会(2017):1–38。

数据处理和数据访问中的大数据架构

原文:https://towardsdatascience.com/big-data-architecture-in-data-processing-and-data-access-d03cff195e21?source=collection_archive---------2-----------------------

早在 1998 年,我就开始了作为 Oracle 数据库开发人员和管理员的职业生涯。在过去的 20 多年里,令人惊讶的是,它是如何通过包括关系型 OLTP(在线事务处理)数据库、数据仓库、ETL(提取、转换和加载)和 OLAP(在线分析处理)报告、大数据以及现在的人工智能、云和物联网在内的技术来处理不断增长的数据量的。所有这些技术都得益于计算能力的快速增长,特别是在处理器、内存、存储和网络速度方面。本文的目的是总结,首先是如何处理大量数据的基本原则,其次是一个思考过程,我希望它可以帮助您更深入地了解数据领域的任何新兴技术,并在当前和未来的技术浪潮中提出正确的架构。

在数据管道中,数据通常经过两个阶段:数据处理和数据访问。对于任何类型的数据,当它进入一个组织(在大多数情况下有多个数据源)时,它很可能不是干净的,或者不是可以由组织内外的最终业务用户直接报告或分析的格式。因此,首先需要数据处理,这通常包括数据清理、标准化、转换和汇总。最终的数据随后呈现在数据访问层,准备好进行报告并用于各方面的分析。数据处理有时也被称为数据准备、数据集成或 ETL 其中,ETL 可能是最受欢迎的名字。

数据处理和数据访问有不同的目标,因此通过不同的技术实现。大数据的数据处理从一开始就强调“扩展”,这意味着只要数据量增加,处理时间仍应在给定可用硬件的预期范围内。总的数据处理时间从几分钟到几小时到几天不等,这取决于数据量和处理中逻辑的复杂程度。另一方面,数据访问强调秒级的“快速”响应时间。在高层次上,数据处理的可扩展性主要是通过并行处理来实现的,而快速数据访问是通过基于访问模式的数据结构优化以及服务器上可用内存量的增加来实现的。

数据处理

为了清理、标准化和转换来自不同来源的数据,数据处理需要触及即将到来的数据中的每一条记录。一旦记录干净并最终确定,工作就完成了。这从根本上不同于数据访问—后者导致不同用户和/或应用程序对相同信息的重复检索和访问。当数据量很小时,与数据访问相比,数据处理的速度不是一个大问题,因此通常发生在最终数据所在的同一个数据库中。随着数据量的增长,人们发现数据处理必须在数据库之外进行,以绕过数据库系统造成的所有开销和限制,而数据库系统显然不是为大数据处理而设计的。这是 ETL 和 Hadoop 分别开始在数据仓库和大数据时代发挥关键作用的时候。

大数据处理的挑战在于,要处理的数据量始终处于硬盘能够容纳的水平,但远远超过给定时间可用的计算内存量。高效数据处理的基本方法是将数据分成更小的部分,然后并行处理它们。换句话说,通过首先在编程中启用并行处理来实现可伸缩性,使得当数据量增加时,并行进程的数量将增加,同时每个进程继续处理与以前相似的数据量;第二,随着并行进程数量的增加,添加更多具有更多处理器、内存和磁盘的服务器。

大数据的并行处理首先是通过数据库系统中的数据划分技术和 ETL 工具实现的。对数据集进行逻辑分区后,可以并行处理每个分区。Hadoop HDFS(高度分布式文件系统)以最具可扩展性的方式采用了相同的原则。HDFS 所做的是将数据划分为数据块,每个数据块的大小不变。然后,这些块被分发到不同的服务器节点,并由元数据存储记录在所谓的 Names 节点中。当数据进程开始时,进程的数量由每个服务器节点上的数据块和可用资源(例如,处理器和存储器)的数量来确定。这意味着 HDFS 支持大规模并行处理,只要你有足够的处理器和多台服务器的内存。

目前 Spark 已经成为内存中最流行的大规模数据处理快速引擎之一。有意义吗?虽然内存确实变得更便宜了,但它仍然比硬盘更贵。在大数据领域,要处理的大数据量总是远大于可用的内存量。那么 Spark 是怎么解决的呢?首先,Spark 利用了具有多个数据节点的分布式环境中的内存总量。然而,内存量仍然不够,如果任何组织试图将大数据放入 Spark 集群,成本可能会很高。让我们考虑一下 Spark 适合什么类型的处理。数据处理总是从将数据从磁盘读取到内存开始,最后将结果写入磁盘。如果每个记录在写入磁盘之前只需要处理一次,这是典型的批处理情况,那么 Spark 与 Hadoop 相比不会有优势。另一方面,Spark 可以在数据转换的多个步骤中将数据保存在内存中,而 Hadoop 不能。这意味着 Spark 在多次迭代处理同一数据时具有优势,这正是分析和机器学习所需要的。现在考虑以下问题:由于可能有数十或数百个这样的分析过程同时运行,如何以一种经济高效的方式扩大您的处理规模?显然,单纯依靠内存中的处理并不能完全解决问题,大数据的分布式存储,如 Hadoop,仍然是补充 Spark 计算的大数据解决方案中不可或缺的一部分。

数据处理领域的另一个热门话题是流处理。它在降低处理速度方面提供了很大的优势,因为在给定的时间点,每当数据到达时,它只需要处理少量的数据。但是,它在两个方面不如批处理灵活:第一个方面是输入数据需要以“流”模式进入,第二个方面是某些需要跨时间段聚合的处理逻辑仍然需要在之后进行批处理。

最后,云解决方案提供了基于数据量(即并行进程的数量)以更动态的方式扩展分布式处理系统的机会。这在企业内部很难实现,因为需要规划、预算和购买新的服务器。如果容量规划不当,大数据处理可能会受到硬件数量的限制,或者额外购买导致资源浪费而未被使用。云上的处理获得了基础设施弹性的巨大优势,这可以为以更具成本效益的方式实现最佳规模提供更多保证。

A brief history of techologies for data processing

数据访问

与数据处理相比,数据访问具有非常不同的特征,包括:

  1. 数据结构在很大程度上取决于应用程序或用户需要如何检索数据
  2. 需要很好地理解数据检索模式,因为大量用户或应用程序可能会重复检索一些数据。
  3. 每次检索的数据量应该是有目标的,因此应该只包含可用数据的一小部分。

根据上述原则,在过去 20 年中出现了几个里程碑,反映了如何访问不断增长的数据量,同时仍能在几秒钟内返回所请求的数据:

  1. 数据仓库:避免了当数据量很大时代价很高的表连接。这里出现了“事实表”的概念,其中所有的列都放在一起,而不像关系数据库那样遵循数据库规范化原则。
  2. 列存储:每一列都被存储和索引,因此可以单独访问。当一行有许多列,而查询一次只检索几列时,这比传统关系数据库的基于行的访问提供了更快的响应时间。
  3. NoSQL 数据库:完全消除了连接和关系结构,以更具体的方式适应快速数据检索。
  4. 内存数据库:通过将整个数据库或整个表保存在内存中来提供快速性能。

下表给出了每种数据库类型的一些流行示例,但并不打算给出一个完整的列表。请注意,一个数据库可以结合一种以上的技术。例如,Redis 是 NoSQL 数据库,也是内存数据库。此外,从数据仓库和列存储中检索数据会利用并行过程在任何适用的时候检索数据。因为根据用户和/或应用程序的数据内容、数据结构和检索模式,可能有许多不同类型数据库的选择,所以数据访问是一个组织需要快速和不断发展的领域。出于不同的目的,同时拥有不同类型的数据库或工具也应该是常见的。

总结

正如我们所看到的,数据处理和数据访问之间的一个重要区别是,数据访问最终来自客户和企业的需求,选择正确的技术可以推动未来的新产品开发并增强用户体验。另一方面,数据处理是公司的核心资产,大规模处理和产生高质量的数据是公司与数据一起成长的基本推动因素。当数据量增长时,许多公司经历了其数据处理系统的停滞,并且从头开始重建数据处理平台是昂贵的。并行数据处理的原理和可伸缩性需要从一开始就仔细考虑和设计。数据处理还与数据管理和数据集成密切相关,这三者对于任何数据密集型组织的成功都至关重要。此外,每个组织现在都面临着来自开源社区和第三方供应商的大数据解决方案的许多选择。清楚地了解数据处理和数据访问之间的差异,不仅可以让 it 和业务领导构建可靠的数据架构,还可以做出正确的决策,稳步扩展和更新 IT。

大数据架构—处理大数据的艺术

原文:https://towardsdatascience.com/big-data-architecture-the-art-of-handling-big-data-bc565c3a7295?source=collection_archive---------6-----------------------

利用大数据的最佳方式

介绍

因此,到目前为止,我们已经了解了公司如何根据从大数据分析中获得的洞察力来执行他们的计划。但是你听说过制定一个关于如何进行大数据分析的计划吗?不完全是。那是什么?满足您的好奇心,当一家公司考虑在其业务中应用大数据和分析时,这是最重要的部分。
一家公司想到在业务中应用大数据分析,他们只是随意地这么做了。似乎毫不费力,不是吗?

B UT,在任何业务中应用大数据分析都绝非易事。这并不像看起来那么容易。它需要强大的大数据架构来从大数据和分析中获得最佳结果。这是大数据分析的基础。它可以被认为是企业实现目标的最终途径。大数据架构师开始设计路径时,首先要了解目标和目的,即需要到达的最终目的地,并说明不同路径的优缺点。
这是一项痛苦的任务,但通过正确的规划和适当的工具是可以实现的。

迈出进入大数据世界的第一步

设计大数据架构的传统流程是这样的-
架构师与利益相关者会面,了解公司的目标,然后用适当的硬件和软件系统规划处理框架。提前规划这个系统对成功至关重要。

我何时需要大数据架构?

F 利用大数据需要大数据架构,但不是每个人都需要。数百 GB 数量级的数据不需要任何类型的架构。除非人们无法一致地处理数 TB 或数 Pb 级的数据,并且未来可能需要扩展,否则他们不需要大数据架构。此外,当您想要投资大数据项目并拥有多个大数据来源时,您可以使用大数据架构。

大数据架构

Big Data Architecture

  • 源层 大数据源是管理大数据架构的数据源。架构的设计在很大程度上依赖于数据源。这些数据来自许多来源,格式也各不相同。其中包括关系数据库、公司服务器和物联网设备等传感器、第三方数据提供商等。该数据可以是批量数据,也可以是实时数据。这些来源很快就堆积了大量的数据。大数据架构的设计使得它能够处理这些数据。
  • 数据接收 这是第一层,来自众多来源的大数据从这里开始。这一层负责对数据进行分类,以便数据平稳地流入体系结构的下一层。这一层的主要目标是将数据无故障地传输到数据架构的其他层。通常,Kafka 流或 REST APIs 用于摄取。

你应该转行大数据的 8 个理由

  • 存储层这一层是大数据的接收端。它从各种数据源接收数据,并以最合适的方式存储数据。这一层甚至可以根据系统的要求改变数据的格式。例如,批处理数据通常存储在分布式文件存储系统中,例如 HDFS,其能够以不同的格式存储大量数据。另一方面,结构化数据只能用 RDBMS 存储。这完全取决于数据的格式和我们需要它的目的。
  • 分析层 公司采用大数据的唯一目标是从中获得洞察,从而做出数据驱动的决策。为了让用户能够分析大数据,大数据架构中最重要的一层是分析层。该分析层与存储层交互,以获得有价值的见解。该架构需要多种工具来分析大数据。结构化数据易于处理,而分析非结构化数据则需要一些高级工具。
  1. 批处理 由于数据规模如此庞大,该架构需要一个批处理系统来过滤、聚合和处理数据,以便进行高级分析。这些是长时间运行的批处理作业。这包括从存储层读取数据,处理数据,最后将输出写入新文件。 Hadoop 是 it 最常用的解决方案。
  2. 实时处理 实时处理到达的数据是大数据世界最热门的趋势。因此,大数据架构必须包括一个捕获和存储实时数据的系统。这可以通过简单地将实时数据接收到数据存储中进行处理来实现。该架构需要一个健壮的系统来处理实时数据。
  • BI 层 该层接收最终的分析输出,并将其复制到适当的输出系统。不同类型的输出是针对人类查看者、应用程序和业务流程的。获得大数据解决方案的整个过程包括从多个来源获取数据、重复数据处理操作以及将结果绘制到报告或仪表板中。这些报告随后被公司用于制定数据驱动的决策。

挑战

H 掌握大数据并不是一件容易的事情。获得大数据解决方案是一项极其复杂的任务,因为它需要大量组件来管理来自多个数据源的数据接收。构建、测试和排查大数据流程是一项极具挑战性的任务。为了优化性能,各种组件之间需要适当的同步。

大数据技术仍在不断发展。大数据技术正在带来新的变化,有助于构建优化的系统。虽然 Hive 和 Pig 等Hadoop技术已经稳定下来,但 Spark 等新兴技术仍在每个新版本中不断引入广泛的变化和增强。根据您的业务需求选择正确的技术是大数据架构的关键。

实施大数据架构会带来很多安全挑战。洞察依赖于集中存储的静态数据。但是访问这些数据是一项具有挑战性的任务,因为这些数据可能被多个应用程序和平台接收和使用。在数据泄露司空见惯的时代,实施强大的安全系统成为保护数据免遭各种盗窃的必要条件。一开始就必须与服务提供商签署服务级别协议,以确保您的数据安全。

坚持住!!!
大数据如何为 Flipkart 争光

从 B 到 A 的大数据:Hadoop 分布式文件系统— HDFS

原文:https://towardsdatascience.com/big-data-from-b-to-a-the-hadoop-distributed-filesystem-hdfs-992612cbf8aa?source=collection_archive---------28-----------------------

HDFS 概念理解指南

Photo by imgix on Unsplash

随着数据的显著增长,在机器网络上存储大量信息变得非常必要。因此,需要一个可靠的系统,称为分布式文件系统,来控制数据的存储和检索。然而,随着这种基础设施的实现,出现了许多挑战,例如,在不丢失数据的情况下处理硬件故障。

在本文中,我们将关注 Hadoop 的分布式文件系统——HDFS,它的设计、架构和数据流。

HDFS 的设计

Hadoop 分布式文件系统(HDFS)是一个分布式文件系统,旨在:

在商用硬件上运行。

Hadoop 旨在运行于多家供应商提供的价格合理的设备上。硬件的性质在集群中提供了极大的可扩展性;坏的单元可以容易地被替换,而不需要昂贵的成本。尽管在大型集群中,硬件故障的概率变得更高,但 HDFS 将继续工作,不会有明显的变化。

高度容错

HDFS 是为处理大文件而设计的,它将大文件分成块,复制大文件,并将其存储在不同的集群节点中。因此,它具有高度容错和可靠的能力。

处理非常大的数据集

HDFS 旨在存储千兆字节或兆兆字节甚至千兆字节范围内的大型数据集。

流式传输数据并提供高吞吐量

假设数据在写入后永不更改的一次写入模式简化了复制。由于这种模式和独立的并行处理,数据吞吐量加快。

HDFS 的建筑

HDFS 有一个主/从架构。它包括:

  • NameNode:称为主节点。它管理文件系统名称空间,并执行打开、关闭和重命名文件和目录等操作。它维护文件系统树和元数据(数据块数 ***** 、副本等)。)用于树中的所有文件和目录。NameNode 还维护和管理从属节点。

与元数据相关联的文件有:

  • FsImage:文件系统元数据的持久检查点。
  • EditLogs:它包含相对于最新的 FsImage 对文件系统所做的所有修改。
  • DataNode:称为从节点。它根据客户端或 namenode 的请求执行读写操作,并定期向 NameNode 报告它正在存储的数据块列表。
  • 次 NameNode : 通常运行在单独的物理机上。它的作用是定期合并来自 NameNode 的 FsImage 和 EditLogs。这可以防止编辑日志变得太大。Is 还将合并的 FsImage 的副本存储到持久存储中,这可以在 NameNode 失败的情况下使用。

从 Hadoop 版本 0.21.0 开始,引入了一种新类型的 namenode,称为 备份节点 ,通过接收来自 namenode 的编辑来维护名称空间的最新状态,此外还有一个 检查点节点 ,它创建了一个名称空间的检查点来替换第二个 namenode。

*Block: 一个磁盘有一个块大小,是它能读写的最小数据量。HDFS 的文件被分成块大小的块,作为独立的单元存储。在 HDFS 中,块的默认大小是 128 MB (Hadoop 2.x)和 64 MB (Hadoop 1.x)。

数据流

阅读文件

A client reading data from HDFS from Hadoop The definitive guide

要从 HDFS 读取文件,客户端打开它希望读取的文件,分布式文件系统与 NameNode 通信以获取元数据。NameNode 用块的数量、它们的位置和它们的细节来响应。然后,客户端对分布式文件系统返回的流调用 read(),并连接到文件中第一个块的第一个(最近的)datanode。当一个块结束时,DFSInputStream 将关闭到 datanode 的连接,然后为下一个块寻找最佳的 datanode。这对于客户端来说是透明的,从客户端的角度来看,它只是在读取一个连续的流。当客户端完成读取时,它调用 FSDataInputStream 上的 close()。

写文件

A client writing data to HDFS Hadoop The definitive guide

当客户端想要将文件写入 HDFS 时,它调用 DistributedFileSystem 上的 create(),distributed file system 与 namenode 通信以在文件系统的命名空间中创建一个新文件,其中没有与之相关联的块。如果文件不存在,并且客户机有适当的权限,NameNode 创建文件;否则,文件创建会失败,并且客户端会抛出 IOException。DistributedFileSystem 返回一个 FSDataOutputStream,供客户端开始向其写入数据。当客户端写入数据时,DFSOutputStream 会将其拆分为数据包,然后写入一个内部队列,称为数据队列。数据队列由数据流处理器使用,它的职责是通过挑选合适的 datanodes 列表来存储副本,从而要求 namenode 分配新的块。datanodes 的列表形成了一个管道。数据流处理器将数据包传输到管道中的第一个 datanode,后者存储数据包并将其转发到管道中的第二个 datanode,依此类推。DFSOutputStream 还维护一个等待 datanodes 确认的内部数据包队列,称为 ack 队列。只有当数据包被管道中的所有 datanodes 确认时,才会从 ack 队列中删除该数据包。当客户端完成数据写入时,它在流上调用 close()。此操作将所有剩余的数据包刷新到 datanode 管道,并在联系 namenode 以发出文件完成的信号之前等待确认。namenode 已经知道文件是由哪些块组成的(通过请求块分配的数据流),因此它只需等待块被最小化复制,然后就可以成功返回。

总之,HDFS 是一个可靠的分布式文件系统,可以跨大数据集群存储大文件。它被设计成可伸缩、高度可用和容错的。它的体系结构有助于管理机器网络中的分布式存储,并在硬件出现故障时维护副本。

“从 B 到 A 的大数据”系列文章涵盖了所有大数据概念:业务概念、工具、框架等。

更多类似的文章,请确保关注以获取最新的更新。

你也可以在我的社交媒体简介 Linkedin Twitter上加入我。

电子商务个性化中的大数据,解释

原文:https://towardsdatascience.com/big-data-in-ecommerce-personalization-explained-580efa0dec50?source=collection_archive---------27-----------------------

大数据无处不在。你曾经在网上提供的所有信息,你浏览器中保存的所有 cookies,你曾经使用过的所有网上银行应用程序——所有这些都存储了你的大量详细信息。这就是为什么当你在网上搜索某样东西时,你会发现无论你走到哪里,都有相同产品的广告跟着你。

不一定是坏事。虽然有些人反对收集大数据,但仍然有足够的空间将大数据理论化并用于商业目的。这方面最有前景的领域之一是营销,因为用户数据是健康营销组合的主要成分。在这里,个性化成为大数据应用中最常被利用的用例之一,并被证明具有高投资回报率。

背后的原因很简单。营销和销售都是为了了解客户的痛点和欲望。过去需要数年的市场研究,现在只需要几天甚至几个小时就可以从网上购物者的个人资料中收集数据,并通过电子商务开发进行操作。

让我们仔细看看大数据在营销方面的几个突出应用,特别是它在哪些方面推动了产品和服务的个性化。

创建建议

这可能是电子商务中最常见的大数据应用之一。我们在访问在线商店时,会根据之前的购买情况不断处理个性化推荐。

大数据有助于发现产品依赖关系,这些依赖关系不容易用肉眼发现。当应用于潜在客户——未知用户或以前没有购买过的访问者时,推荐尤其闪亮。

通过实时分析他们的行为,企业可以根据已经看过的产品更新“推荐”商品,从而促使他们购买。

利用客户关怀

提供高水平的客户支持是利用大数据和提高品牌忠诚度的另一个很好的方式,尽管这一点被忽视了。

为了在客户服务中成功利用大数据,您需要实现数据访问的民主化。您的所有支持代表都应该能够访问客户信息、他们的购买历史和高级分析能力,这些数据集通常是销售、营销和首席管理人员的特权。

这些大数据层必须以易于理解的格式呈现,因为客户服务代表处理客户问题的时间有限。

例如,客户服务代理可以通过以下方式个性化客户体验:

  • 利用客户的购买历史提供相关的折扣和促销。
  • 使用同一人群中其他客户的购买来追加销售相关产品。
  • 分析购买行为,挑出出现问题最多的产品或客户类别。这一情报将有助于先发制人地解决此类客户的担忧。

树立忠诚度

你如何和某人成为朋友?你创造了一种关系。他们对你有所了解。你对他们有所了解。

客户忠诚度也差不多。与你的电子商务客户的友好关系很重要。新客户意味着业务增长,但忠诚的客户是企业生存的基础。大数据有助于为您的每一位客户建立丰富的档案,然后利用它来发展与他们的关系。

您可以通过分析客户购买的产品类型来个性化促销,包括基于他们购买的产品的大小、颜色和类型的特殊促销。

例如,如果一个人买了一件特定尺寸和类型的蓝色 t 恤(比如说 V 领),那么考虑到他们在你的商店购买这些商品的常见频率,你可以为他们提供这种特定类型服装的即时折扣。这样的推荐给人一种你了解客户的感觉,只要你提供了他们真正感兴趣的东西,他们就更有可能购买。

建立忠诚度的另一个好方法是使用客户的账单或送货地址提供本地化的折扣或促销。这种本地化可以是任何东西,从基于他们当地假日度假的促销到围绕他们的所在地建立的特殊送货折扣。

深入非结构化数据

结构化数据按类别存储在数据库中,包括企业运营所需的所有客户信息。非结构化数据不能以同样的方式进行分类。您在数据库中找不到包含该信息的特定行或列。

通常,当我们谈论非结构化数据时,我们谈论的是存储在您站点外部的信息。关于你的品牌的社交媒体出版物是非结构化数据的一个例子。

但是,您可以使用监控工具收集这些信息。例如,某些数字服务可以收集你的品牌在网络上的提及率。这些数据可以帮助你分析围绕你的品牌名称的情绪,暗示人们在试图与你互动时在寻找什么,甚至指出他们可能感兴趣的产品。您可以使用这些数据围绕特定产品和客户需求构建内容。

充分利用时间

一些大数据计划必须围绕及时执行来构建。购物者的注意力持续时间很短。这就是为什么通过提供他们目前需要的产品来尽快抓住他们的注意力是至关重要的。

利用大数据,这种实时个性化是可能的。这里的原则保持不变——利用你拥有的关于用户的所有信息,建立个性化的购物体验。

这些努力必须与先进的分析框架交织在一起,例如建立在数据科学和机器学习基础上的分析框架。这些技术可以帮助您在旅途中调整策略,并在单个用户会话中产生影响。

有许多服务,如 Evergage、Marketo 或 PureClarity,可以根据访问者的位置实时个性化推荐产品。例如,这些服务可以看到来自特定位置的人倾向于购买特定的产品。然后,他们在推荐中显示这些产品,或者触发连接的网络商店为这些产品提供特殊折扣。

最后的话

除了谷歌和其他知名商业智能提供商提供的常规分析之外,即使是最小的电子商务公司也拥有大量数据。如果你不根据已经掌握的数据采取行动,你可能会与已经在利用这些数据的竞争对手打一场硬仗。

开始为客户打造个性化体验并不难。从丰富他们的个人资料开始。然后尝试使用这些信息来提供个性化的推荐。一旦你看到投资回报率在增长,就转而收集非结构化数据,并应用人工智能服务来筛选有价值的见解。

Apache NiFi 和 Kafka Docker 示例

原文:https://towardsdatascience.com/big-data-managing-the-flow-of-data-with-apache-nifi-and-apache-kafka-af674cd8f926?source=collection_archive---------2-----------------------

在 Hadoop 生态系统中,Apache NiFi 通常用于摄取阶段。Apache NiFi 提供了一种可伸缩的方式来管理系统之间的数据流。当你试图从 A 点到 B 点获取信息时,会出现许多问题。例如,网络可能出现故障,软件崩溃,人们犯错误,数据可能太大、太快或格式错误。NiFi 将在幕后处理这些问题,以便开发人员可以专注于应用程序本身。

NiFi 的一些特性包括:

保证交货

NiFi 保证数据的传递。这是通过有效使用专门构建的持久预写日志和内容存储库来实现的。

数据缓冲/压力释放

当给定的数据源超过处理或交付链的某个部分时,Nifi 可以缓冲数据。NiFi 还支持在指定时间过后删除排队数据的能力。

优先排队

NiFi 允许为如何从队列中检索数据设置一个或多个优先级方案。默认情况下是最早的优先,但有时应该先提取最新的数据、先提取最大的数据或其他自定义方案。

服务质量

有些时候,数据必须在几秒钟内处理和交付才能有价值。NiFi 使管理员能够将延迟优先于吞吐量或容忍度等。

术语

Apache NiFi 围绕着处理器的思想。处理器是图中工作的节点。这通常包括对数据执行某种操作、将数据加载到 NiFi 或将数据发送到某个外部系统。处理器一些例子是:

  • GetFile:加载文件的内容
  • UpdateAttribute:更新流文件属性(即 schema.name ),然后其他处理器可以访问这些属性
  • PublishKafka:将流文件的内容作为消息发送给 Apache Kafka

另一方面,进程组是处理器及其连接的集合。控制器服务可用于创建它们的进程组中的所有处理器。

控制器服务的一些示例包括:

  • AvroSchemaRegistry:在注册表中存储 Avro 模式,然后其他控制器服务可以检索这些模式
  • AvroRecordSetWriter:以 Avro 格式编写和编码数据

NiFi 中的另一个关键概念是流文件。流文件是图形中给定位置的数据和一些附加元数据。我们可以通过点击一个连接的 【列表队列】 下拉菜单选项来查看流文件。

例如,以下流文件具有唯一的 id 和文件名。

通过点击视图,我们可以看到实际数据从一个处理器转移到另一个处理器。

体系结构

NiFi 在主机操作系统上的 JVM 中执行。

网络服务器

与大多数软件不同,Apache NiFi 的管理是通过用户界面完成的。

流量控制器

处理与处理器相关的所有逻辑。

流文件存储库

流文件存储库是 NiFi 存储流中当前活动的流文件的元数据的地方。

内容存储库

内容存储库是给定流文件的实际内容所在的地方。可以指定多个文件系统存储位置,以减少争用。

出处储存库

出处储存库是存储所有出处事件数据的地方。本质上,起源事件数据告诉你什么时候发生了什么。

NiFi 还能够在集群中运行,使其能够无限扩展。

NiFi 集群中的每个节点对数据执行相同的任务,但是每个节点对不同的数据集进行操作。Apache ZooKeeper 用于选举集群协调器并自动处理故障转移。管理员可以通过任何节点的用户界面与 NiFi 集群进行交互,任何更改都会复制到集群中的所有节点。

密码

在本例中,我们将获取一个 CSV 文件并将其发布到 Kafka。我们将使用 docker 来设置我们的环境。将以下内容复制到docker-compose.yml并运行docker-compose up -d

接下来,在你的主机上打开浏览器,进入localhost:8080/nifi

在左上方的配置中,将一个处理器拖到主面板上。选择并配置 GenerateFlowFile 处理器每 60 秒运行一次,这样我们就不会不断地生成数据。

我们将使用一个简单的数据集,其中包含 30 个人的工作经验和薪水。

YearsExperience,Salary
1.1,39343.00
1.3,46205.00
1.5,37731.00
2.0,43525.00
2.2,39891.00
2.9,56642.00
3.0,60150.00
3.2,54445.00
3.2,64445.00
3.7,57189.00
3.9,63218.00
4.0,55794.00
4.0,56957.00
4.1,57081.00
4.5,61111.00
4.9,67938.00
5.1,66029.00
5.3,83088.00
5.9,81363.00
6.0,93940.00
6.8,91738.00
7.1,98273.00
7.9,101302.00
8.2,113812.00
8.7,109431.00
9.0,105582.00
9.5,116969.00
9.6,112635.00
10.3,122391.00
10.5,121872.00

同样,通过将数据粘贴到自定义文本属性来配置 GenerateFlowFile

注意:任何粗体属性为必填,其余为可选。

将处理器拖到主面板上,并选择更新属性。对于 UpdateAttribute 处理器,在 properties 下,单击右上角的加号。然后,创建一个值为 test.schemaschema.name 属性。

现在,我们将创建控制器服务。右击主面板,选择配置

在这里,我们可以为我们的处理器组创建所有的控制器服务。

点击右上角的加号,选择 AvroSchemaRegistry 。在 properties 选项卡下,创建一个名为 test-schema 的新属性,并将下面的模式粘贴到 value 字段中。

{
   "type" : "record",
   "namespace" : "Test",
   "name" : "Employee",
   "fields" : [
      { "name" : "YearsExperience" , "type" : "float" },
      { "name" : "Salary" , "type" : "float" }
   ]
}

我们还需要 CSVReader。在 properties 选项卡下,将其配置为使用 schema name 属性,即 AvroSchemaRegistry ,并将第一行视为列标题。

最后,创建一个 AvroRecordSetWriter ,并将其配置为使用 AvroSchemaRegistry

在继续之前,请确保通过单击最右侧的闪电图标来启用所有控制器服务。

现在我们已经完成了控制器服务的设置,我们将通过运行以下命令来创建一个 Kafka 主题。

docker-compose exec kafka  \
kafka-topics --create --topic test --partitions 1 --replication-factor 1 --if-not-exists --zookeeper zookeeper:2181

验证它是否正常工作。

docker-compose exec kafka  \
kafka-topics --describe --topic test --zookeeper zookeeper:2181

创建 PublishKafkaRecord ,并对其进行如下配置。

请务必检查自动终止关系,因为这是我们图表中的最后一个处理器。

要创建处理器连接,请在它们之间拖动箭头。

最后,要开始流程,右键单击每个处理器并选择 start 。如果一切都按预期运行,那么每个原始行都应该被写回。

docker-compose exec kafka  \
  kafka-console-consumer --bootstrap-server localhost:29092 --topic test --from-beginning --max-messages 30

大数据同步:确保大数据准确性的 5 种方法

原文:https://towardsdatascience.com/big-data-synchronization-5-ways-to-ensure-big-data-accuracy-4c4801b021ad?source=collection_archive---------13-----------------------

Source

如果你拥有一家电子商务商店,或者甚至去过电子商务商店,你一定经历过“缺货”或“断货”的问题。然而,上周我有一次非常奇怪的经历。我在网上搜索我最喜欢的运动鞋,发现它们有现货。所以,我去商店买了一个,但是你猜怎么着,他们没有。他们两天前就没货了,但他们仍然在网站上显示有货。

缺货是很常见的事情,没什么好奇怪的。然而,这个问题已经恶化,因为许多这些公司正在努力同步来自他们运行的不同系统的数据,包括存储大数据的系统。当从这些系统流入的数据与现实世界中发生的事情不充分同步时,客户可能会失望。

大数据同步是一个关键问题。这是因为数据资源正在以极快的速度提取数据,将它们同步成单一版本的事实有点困难。

例如,如果你销售智能手机,你可能会有采购和库存系统,存储和报告零件。生产系统报告成品制造中消耗了多少零件,销售系统报告可供销售的产品,工程系统报告产品的最新版本级别,并提供安全的 CAD 大数据。

无论如何,如果所有系统不能同步反映你所销售的智能手机的最新精度,那么肯定会出现故障,这可能会让消费者和销售人员失望。此外,它还会导致根据不准确的数据做出糟糕的管理决策。

如果组织想要利用大数据的力量,保持其准确性和同步性是当务之急。这里有五种方法可以确保任何规模的系统实现大数据同步!

1。规划您的数据更新流程

如果没有适当的规划,采用大数据项目注定会失败。组织可能会在他们甚至不知道如何使用的东西上浪费大量的时间和资源。他们经常雇佣开发人员来构建他们没有足够知识的系统。无论您计划开发应用程序还是修改现有应用程序和/或将新的大数据源纳入您的 it 系统,需求规划都应包括您将如何同步所有传入数据。因此,数据可以尽可能的新鲜和准确。

数据更新流程的规划应包括数据更新和与主数据集同步的频率。同时,应将这一频率传达给最终用户,以便他们提前了解数据限制是什么。

2。开发数据同步方法

数据同步是在源数据存储和目标数据存储之间建立一致性的过程,反之亦然。谈电子商务网站,主要目标是数据的适当同步。已经有许多网站制定了数据同步政策和更新程序,用于同步其任务关键型交易数据。然而,它们不一定解决了大数据问题。

大数据有大量的数据源和极高的数据交付速度。但是,数据的时间戳和数据来自的时区的信息需要同步,才能知道最新的数据在哪里。必须面对数据更新过程的现实。并非所有数据都可以实时更新,因此必须决定何时将数据与主数据同步,以及是在夜间进行批量数据同步,还是全天以预定的批量突发模式进行同步。

简而言之,此类流程应记录在 IT 运营指南中,并且每次您向流程中添加新的大数据信息源时,都应更新这些流程。

3。获取用于同步的商业工具

为了在多个设备之间保持信息备份和更新,有一些商业工具提供了一种方便的同步方式,可以帮助数据同步。

这些工具可以帮助您完成大数据同步工作,并自动执行部分数据同步操作。

这里有几个重要的同步商业工具,可以帮助您进行大数据同步工作。此外,它们还可以自动执行部分数据同步操作。

这是一个备份和文件同步程序。GoodSync 工具用于同步两个目录之间的文件,例如在一台计算机上或在一台计算机和另一台存储设备之间,例如,另一台计算机、可移动磁盘、闪存驱动器或智能手机,或者在一台计算机和远程计算机或服务器之间。

GoodSync for business 为任何其他数据源、目的地或系统提供完整的企业数据备份和同步解决方案。GoodSync 控制中心提供 GoodSync 工作站和服务器的文件同步、备份和发布活动的集中管理和报告。GoodSync 工具的特点是实时同步、备份和恢复以及审计跟踪。

Mozy Sync 是一款基于网络的文件同步应用,适用于 Windows 和 Mac,它可以复制文件夹的数据,并在紧急情况下重建数据。这是一个为小型办公室提供云备份的经济高效的工具。Mozy Sync 是一款易于操作的工具,包含备份和恢复以及同步计划等功能。

这是一个易于使用的云备份和存储程序,可以根据用户的需求进行定制,如指定每台机器上应该备份哪些文件夹和文件,每天/晚上搜索备份更新的数量和时间,以及如何/谁可以访问存储的数据。这个数据同步工具是各种规模企业的满意解决方案。

用于 Windows、Linux 或 Mac 的文件同步工具,可分析文件夹数据,分离常用文件并创建其备份副本。这是一个开源工具,可用于独立审计。FreeFileSync 定期更新,开发得非常好。

它提供了许多选项,包括您希望使用哪种比较方法来比较文件,以及您更喜欢哪种类型的同步,例如镜像、复制或仅更新。作为用户,您可以选择在系统启动时实时同步文件夹。

4。考虑移动设备和下载的限制

每个人都使用移动设备。然而,每个人的互联网都有互联网带宽限制,这些设备无法快速处理大量的数据下载,这些设备上的常驻销售和库存数据可能并不总是与主数据库中的真实数据同步。作为最终用户沟通过程的一部分,它必须让用户了解这些潜在的数据准确性限制。

5。搜索可以协助数据同步的服务提供商

大数据云处理器之一 Amazon Web Services EMR 认识到了数据同步问题。它有数据同步方法,使他们能够为您执行同步。如果您对云中的数据处理感到兴奋,您可以询问您的云供应商它可以提供什么服务来确保您的大数据的最新和最高质量的表示。

是否相信大数据是否会改变世界的炒作。除此之外,大数据的准确性至关重要。上述方法确保了从访问大数据和交易数据的应用程序提供的数据是准确的。

评论

我希望你们喜欢阅读这篇启发性的文章。请在下面评论您用于同步大数据的策略,或者您如何应对大数据准确性问题。

大数据:正在彻底改变世界的艺术和科学

原文:https://towardsdatascience.com/big-data-the-art-science-that-is-revolutionizing-the-world-a2a596122c55?source=collection_archive---------29-----------------------

深入研究将极大改善我们生活方方面面的技术

Picture from Unsplash

大数据:原因、方式和内容

近年来,信息技术经历了迅猛发展:

  • 传感器现在便宜得离谱。
  • 计算能力有了巨大的增长。
  • 到处都有连接互联网的设备(智能手机、活动支架、智能手表、电视、汽车……现在甚至连热拌食品都有 wifi 了!)

这些因素和其他因素导致可用数据急剧增加。今天,我们能够产生、存储和发送比历史上任何时候都多的数据。

以至于在 2015 年,据估计 90%的可用数据都是在两年前创建的。从那以后,数据生成的速度只增不减。

事实上,据估计,目前每天会产生 2.5 万亿次数据。这是第一代 Iphone 的 2.5 倍 1⁰ ⁷字节,相当于 1 亿倍的存储容量。

所有这些数据就是俗称的大数据。要被认为是大数据,它必须符合以下特征,即所谓的 3 Vs 规则:

  • 必须是高变化的数据。
  • 那就是增加的音量。
  • 并以巨大的速度。

大数据带来的数据科学的繁荣

然而,这些海量的数据导致了一个新的问题:

我们用它做什么?

可用的数据如此之多,以至于人类不可能从中研究和提取有价值的信息。从这些数据中分析和发现模式和见解需要几代人的时间。

幸运的是,电脑可以帮助我们。此外,在过去的几年里,机器学习算法的发展取得了巨大的进步。这些算法,加上我们以如此低的成本拥有的几乎无限的计算能力,导致了我们目前正在试验的数据科学的急剧扩展。

数据是提高业务成效的增长最快的驱动力。为了创造竞争优势,越来越多的组织使用他们的数据来提高效率、销售和营销效果。但是,现在大部分的数据仍然没有连接和充分利用。这就是数据科学在解决这个问题上发挥作用的地方。

目前使用的主要数据科学是:

数据工程

数据工程的重点是建立适当的基础设施,以促进组织内部的数据流动,并使这些数据准备成为有用的格式。

数据分析

数据分析侧重于从数据中发现有用的信息。数据科学的这一分支涉及对数据的描述和诊断分析,解释发生了什么以及为什么会发生。它还涉及数据可视化方面(这是一个完全独立的领域)

机器学习

机器学习是专注于让计算机从数据中学习的科学(和艺术)。他们通过学习导致特定结果的过去数据的特定特征之间的相关性来做到这一点,因此当向他们提供新数据时,他们可以做出准确的预测。

深度学习

深度学习是机器学习的一个子领域,专注于复制智能生物用于学习的学习机制。他们通过用简单的概念解构复杂的概念来做到这一点,因此,以一种分层的方式学习。使用人工神经网络来实现这一点。

数据科学的目标和路径

如前所述,如今数据严重脱节和利用不足,这门科学的最终目标是能够从原始数据(没有价值)到智慧,这最终将有助于决策,因为它将由客观信息驱动。

下图很好地传达了这一概念:

Figure by Author

总之,数据科学是一套从数据中自动提取知识的基本原则、流程和技术。最终目标是改进决策,所有任务都应服从于这一目标。

数据科学之路,从容易和不太有价值到困难和最有价值,如下所示:

Figure by Author

处理大数据的技术

后一种数据科学是围绕大量数据开发的,但是,当数据量如此之大,以至于单台计算机无法对其进行分析并提取有意义的见解时,并行分析(和大数据技术)就开始发挥作用了。

以下是一个典型的大数据基础架构示例。用于形成和使用大数据生态系统的一些技术包括:

  • 批量:Hadoop,Hive,Apache Spark
  • 溪流:阿帕奇卡夫卡
  • 基础设施:Cloudera、Hortonworks、Mapr
  • 自动化:Ansible,Chef,Jenkins,Airflow,Luigi
  • 容器和集群管理:Docker、Mesos、DC/OS、Kubernetes、Marathon
  • 语言:Scala,Java,Python
  • 数据库:SQL(是的,你需要非常擅长 SQL 😃),NoSql 数据库,时间系列数据库
  • 索引:弹性搜索
  • 可视化:基巴纳,格拉法纳

在接下来的系列文章中,我们将重点关注大数据架构的数据分析和机器学习方面,具体来说,我们将使用 Apache Spark 及其 Python 实现:PySpark。

因此,如果您想了解更多关于这一令人惊叹的技术以及如何执行一些现实世界的项目,请继续关注下一篇文章!

Apache Hadoop —什么是 YARN | HDFS | MapReduce

原文:https://towardsdatascience.com/big-data-what-is-apache-hadoop-3dafda16c98e?source=collection_archive---------20-----------------------

目前,围绕大数据有很多炒作。在接下来的文章中,我将试图澄清人们所说的大数据和提供了一种称为 Hadoop 的核心技术的高级概述,该技术在工业中用于存储和处理大量数据。

大数据中的 是指数据量。随着电子商务、社交媒体和物联网设备等技术的出现,自 21 世纪初以来,整个社会产生的数据量一直在呈指数级增长。据估计,到 2025 年,全球数据圈将从 2018 年的 33 吉字节(1 吉字节相当于 1 万亿吉字节)增长到 175 ZB。

许多组织正在转向 Apache Hadoop 和其他大数据技术,利用这些大量数据的价值来推动业务决策。

数据越多,处理数据所需的计算能力就越强。谈到计算能力,您有两种选择:

  • 垂直扩展(即更多 RAM、内核和硬盘)
  • 水平扩展(即分布式计算)

纵向扩展的问题之一是,由于各种限制,在可预见的未来,处理器速度将徘徊在 4 GHz 左右。此外,较高等级组件的成本不是线性的。换句话说,两个系统比一个规格两倍的系统花费更少。

因此,公司主要使用分布式计算进行数据处理(即商业分析、训练机器学习模型)。分布式计算听起来很简单,但在实践中,需要考虑很多因素。例如,不同的系统如何共享信息,我们如何将问题分解,以便每个系统都可以同时处理它,如果一个或多个节点出现故障,我们该怎么办。

根据官方文档,Apache Hadoop 是一个开源框架,允许跨计算机集群分布式处理大型数据集。Apache Hadoop 项目分为 HDFS、YARN 和 MapReduce。

HDFS (Hadoop 分布式文件系统)

假设您在某个初创公司担任数据工程师,负责建立存储面向客户的应用程序产生的所有数据的基础设施。您决定使用硬盘驱动器作为主要的非易失性存储介质,因为固态驱动器太贵,而磁带对于任何类型的处理都太慢。传统上,您会将存储(存放数据的地方)和计算(处理数据的地方)分开。在这类系统中,数据将通过一个非常快速的网络传输到计算机,然后由计算机进行处理。事实证明,从时间的角度来看,在网络上移动数据是非常昂贵的。或者,我们可以在存储数据的地方处理数据。数据局部性是从分离存储和计算的彻底转变,分离存储和计算曾经是处理大规模数据系统的流行方式。Hadoop 是最先采用这种方法的技术之一。由于显而易见的原因,通过网络传输 mapReduce 代码比试图将数 Pb 的数据发送到程序所在的地方要快得多。数据局部性从根本上消除了网络瓶颈,从而实现了线性可伸缩性。

现在,问题来了,我们如何无缝地访问存储在不同节点上的数据。显然,我们不希望每次需要访问硬盘上的文件时都必须远程访问计算机。Hadoop 分布式文件系统为我们解决了这个问题。HDFS 实现为主从架构,由一个 NameNode(主节点)和一个或多个 DataNodes(从节点)组成。NameNode 负责告诉客户端将数据发送到哪个节点,或者在检索的情况下,哪个节点包含它们正在寻找的数据。然后,客户端可以连接到 DataNode 并开始传输数据,而不再需要 NameNode 的参与。前面的过程使 Hadoop 能够有效地水平扩展。

默认情况下,HDFS 会在集群中存储您文件的三个副本。在这种情况下,发生了一些故障,暂时只有两个副本,你永远不会知道,因为这都是由 NameNode 在幕后处理的。

存储在 HDFS 的文件是只读的。一旦你写了一个文件,它将会有那个内容,直到它被删除。这个实现细节意味着 HDFS 不需要进行同步的改变,而同步的改变会在分布式系统中引起多个问题。

YARN(又一个资源谈判者)

除了用于管理计算资源之外,关于 YARN 没有太多可说的。在 YARN 之前,大多数资源协商都是在操作系统级别处理的。后者会导致多重低效。因此,社区发明了 YARN 来更智能地在集群上分配工作负载,并告诉每台计算机应该运行什么以及应该给它多少资源。

MapReduce

在编程中,map 通常意味着将一些函数应用于列表中的每个元素,并将每个操作的结果作为列表返回。需要注意的是,地图函数的应用顺序并不重要。假设您想将一个映射函数应用于一个包含一万亿个整数的列表。当由单台计算机顺序执行时,需要一段时间。因此,我们可以将负载分布在集群内部的许多节点上,以便并发处理。换句话说,每个节点将在列表的子集上执行 map 函数。考虑到应用映射函数的顺序并不重要,我们避免了分布式系统中最大的挑战之一,即让不同的计算机就完成事情的顺序达成一致。

传统的 reduce 操作将函数和列表作为参数,将函数应用于列表的前两个元素,获取结果,然后将函数重新应用于结果和下一个元素,继续这个过程,直到到达列表的末尾。在 Hadoop 中,reduce 从 map 阶段获取结果,按键将它们分组,并执行聚合操作,如求和、计数和平均。

使用 Hadoop 的主要好处之一是它抽象出了在分布式系统上运行代码的所有复杂性。完全相同的 MapReduce 代码可以在 10,000 个节点的集群或单台笔记本电脑上运行。因此,开发变得更容易,出错的机会也更少。

最后的想法

Hadoop 简化了集群内不同节点之间的数据存储和处理。Hadoop 利用数据局部性来处理大量数据,而无需通过网络发送。HDFS 负责处理分布式系统中的许多复杂问题,比如当一个节点不可避免地出现故障时如何处理。使用 MapReduce,我们可以分解一个工作负载,并将其分布在多台计算机上并发执行,然后在 Reduce 阶段之后可以获得聚合结果。

具有弹性搜索的大型快速人在回路 NLP

原文:https://towardsdatascience.com/big-fast-nlp-with-elasticsearch-72ffd7ef8f2e?source=collection_archive---------2-----------------------

第一部分:关键词工厂TL;dr:如果你 1)在 Elasticsearch 中存储你的数据 2)使用[clio-lite](https://github.com/nestauk/clio-lite#keywords-getting-under-the-hood)包中的clio_keywords函数,指向你的 Elasticsearch 端点 3)在 Flask 应用中托管它,比如这个

第二部分:上下文搜索引擎TL;dr:如果你 1)将你的数据存储在 Elasticsearch 中 2)使用[*clio-lite*](https://github.com/nestauk/clio-lite)托管一个 lambda API 网关 3)用你自己的前端询问它,或者使用像 searchkit 这样的开箱即用的东西,你可以使成为其中之一

许多 NLP 数据科学家目前的日常工作范式是打开笔记本电脑,启动 Python 或 R,制作一些模型,总结一些结论。这对于探索性分析来说非常有效,但是如果你需要把一个人(比如一个专家,你的老板,甚至你自己)放入循环中,这可能会变得非常慢。在这篇由两部分组成的博客中,我将试图让你相信有更大、更快的方法来实现 NLP。

Big fast human-in-the-loop NLP (Photo by Stephen Hateley on Unsplash)

人在回路 NLP 和我

在我Nesta的日常工作中,我开发工具和基础设施,让人们能够做出更好的决策,让人们能够利用最新的数据做出这些决策。我们为地方、国家和国际决策者和资助者提供工具,他们依赖于与科学、技术和社会的最新创新保持同步。由于这些人对他们的决定负责,这通常排除了采用黑盒程序的工具。“人在回路中的自然语言处理”是我们解决这些需求的方式,尤其是因为非结构化文本数据是最丰富、最可用和最新的数据形式之一。

弹性搜索

数据工程师、数据库管理员和 devops 工程师都应该熟悉“elastic stack”(elastic search 是其核心),它是存储和分析日志文件或构建搜索引擎的首选技术,尽管他们中的许多人可能不太了解数据科学研究的巨大潜力。与此同时,许多数据科学家充其量对作为数据存储技术的 Elasticsearch 有一个基本的了解。

简而言之 : Elasticsearch 是一个搜索引擎的数据库,因为 数据的存储方式 而能够进行闪电般的搜索。

在 Elasticsearch 中,文档被存储为词频向量(一个被称为“倒排索引”的过程),并且文档频率是为每个词预先计算的。这意味着几件事:

  1. 一个术语接一个术语的同现以令人难以置信的速度快速从中提取
  2. 重要术语可通过标准数据科学‘TF-IDF’程序即时识别

从数据科学家的角度来看,Elasticsearch 数据库是一个非常基本(但功能强大)的预训练模型,用于提取关键字、同义词、相似文档和离群值。在这个由两部分组成的博客中,我将使用开箱即用的功能来触及所有这些内容(尽管当然也可以采用更复杂的方法)。

第一部分:关键词工厂

最简单的情况:允许非专家识别他们自己的关键字和同义词

生成关键字(或同义词)列表是数据科学家的一项常见 NLP 任务。它可以有从维度减少到主题建模的应用,并且还可以通过向人类分析师提供可以用于更费力的任务的一组数据驱动的术语来用于人在回路中的分析。

许多数据科学家会使用适当的 python(或 R)包来处理这个问题,以便产生相当静态的输出,这对于报告或论文来说是很好的。大多数时候,我们都希望我们的结果能够被非专家访问,但是实际上,人们最终得到的是他们所得到的:静态输出。我们有哪些可供非专家使用的可扩展且灵活的工具?

Python(或 R)包:错误工作的正确工具

有大量基于 python 的方法可以解决这个问题,如主题建模(如潜在的狄利克雷分配或相关性解释)、单词向量聚类(如单词嵌入或香草计数向量)或使用共现矩阵或网络。

所有这些方法都可以给出非常合理的结果,老实说,我并不想在感知准确性上击败这些方法。如果我的任务是进行一次性的特别分析,我可以考虑以上任何一种方法。

然而,我喜欢可扩展、可共享和灵活的问题解决方案:

  • 可伸缩性:我建议的所有 python 解决方案都要求数据和模型驻留在内存中。对于大量的文档或大量的词汇,内存消耗会很大。对此的一个解决方案是以牺牲模型的“深度”为代价对数据进行采样。
  • 可共享性:如果你没有在非专家的笔记本电脑上安装 python 包,同时又希望你的设置与他们的笔记本电脑兼容,你如何与他们共享结果?两种可能是在远程服务器上托管你的机器学习模型(可以是从集群模型到共生矩阵的任何东西)(但是要小心那巨大的内存开销!),或者您可以预先生成静态的关键字集(这非常简单)。
  • 灵活性:想象一下,你想用多一个文档来更新你的模型,或者决定就地过滤你的数据——用常规的机器学习模型来做这件事并不简单。您的最佳方法可能是为每个预定义的过滤器预生成一个模型,这在计算上是昂贵的。

弹性搜索:适合工作的合适工具

请记住,Elasticsearch 实际上是一个预先训练好的词共现模型,可以根据词的重要性进行过滤,这就很清楚为什么它可以动态地生成关键字列表。此外,我们应用于 Elasticsearch 的任何方法都具有内在的可扩展性、可共享性和灵活性:

  • 可伸缩性 : Elasticsearch 的性能高达 Pb 级。
  • 可共享性 : Elasticsearch 通过一个简单的 REST API 公开数据上的方法。要完成复杂的任务,您可以简单地将一些托管在远程服务器上的轻量级 python 代码串在一起。
  • 灵活性:更新您的“模型”就像向服务器添加新文档一样简单。按任何字段过滤数据都是一项基本操作。

“重要文本”集合

原则上,我们可以从零开始实现我们自己的提取关键词的程序,但是有一些快捷方式,你可以通过使用 Elasticsearch 的开箱即用功能来使用。

下面的 python 代码包装了一个对 Elasticsearch API 的查询(用您自己的端点替换URL,用您想要查询的数据库中的字段名称替换FIELD_NAME):

*import requests
import json

def make_query(url, q, alg, field, shard_size=1000, size=25):
    """See [this gist](https://gist.github.com/jaklinger/6a644956f32e3e8b0d5e41c543ee49e1) for docs"""
    query = {"query" : { "match" : {field : q } },
             "size": 0,
             "aggregations" : {
                 "my_sample" : {
                     "sampler" : {"shard_size" : shard_size},
                     "aggregations": {
                        "keywords" : {
                            "significant_text" : {
                                "size": size,
                                "field" : field,
                                alg:{}
                             }
                        }
                    }
                }
            }
        }
    return [row['key'] 
            for row in requests.post(f'{url}/_search',
                                     data=json.dumps(query),
                                     headers={'Content-Type':'application/json'}).json()['aggregations']['my_sample']['keywords']['buckets']]*

在幕后,该查询执行以下操作:

  1. 在字段field中查找包含文本query的所有文档。
  2. field中提取size最高有效项,根据jlh算法计算。

最重要的是,增加shard_size的大小将增加你的“模型”的稳定性(和深度),代价是计算性能。实际上,您只会期望您的模型在极少数情况下变得不太稳定——在这种情况下,您可以构建一个解决方法。

tweeks 之前的性能:arXiv 数据

我的 Elasticsearch 数据库中有 arXiv 的所有科学出版物,下面是它对以下查询的抽象文本的表现:

*python pandas['pandas', 'numpy', 'package', 'scipy', 'scikit', 'library', 'pypi', 'cython', 'github']-----------------------------elasticsearch['kibana', 'lucene', 'hadoop', 'retrieving', 'apache', 'engine', 'textual', 'documents', 'ranking']-----------------------------machine learning['learning', 'training', 'algorithms', 'neural', 'supervised', 'automl', 'intelligence', 'deep', 'tasks']----------------------------------------------------------drones and robots['robot', 'drones', 'robotics', 'robotic', 'humanoid', "robot's", 'drone', 'autonomous', 'mobile']-----------------------------*

…这是开箱即用的功能!一些简单的批评是:

  1. 无论是在查询中还是在结果中,n 元语法都没有被利用。例如,machine learning被视为{machine, learning},而不是{machine learning, machine, learning}
  2. 搜索结果中出现停用词并非不可能。
  3. 样本外的拼写错误根本不会被处理。
  4. 名词的复数和所有格形式以及所有动词的变化都单独列出。

我不打算在这里解决后两点,但是处理它们是相当琐碎的。例如,拼写错误至少可以用两种方式处理,例如使用:

为了处理 n-gram 查询(比如machine learning)我在我的 Elasticsearch 数据库中创建了一个包含预标记摘要的字段,在其中我已经识别了 n-gram。请注意,该字段的“模式”可在此处找到。如果你想知道,我通过使用基于 wiki tionaryn-grams 的查找表来处理我的 n-grams(但是更数据驱动的方法也可以)。

虽然我自己没有实现这一点,但是可以对复数/所有格/变形进行类似的预处理,有效地将所有非简单形式的术语替换为它们的简单形式。

最后,为了避免返回停用词的潜在尴尬,我使用我的make_query函数从数据中生成它们:

*and of but yes with however[‘however’, ‘but’, ‘not’, ‘answer’, ‘with’, ‘the’, ‘is’, ‘of’, ‘to’, ‘a’, ‘in’, ‘and’, ‘that’, ‘no’, ‘this’, ‘we’, ‘only’, ‘for’, ‘are’, ‘be’, ‘it’, ‘can’, ‘by’, ‘on’, ‘an’, ‘question’, ‘also’, ‘have’, ‘has’, ‘which’, ‘there’, ‘as’, ‘or’, ‘such’, ‘if’, ‘whether’, ‘does’, ‘more’, ‘from’, ‘one’, ‘been’, ‘these’, ‘show’, ‘at’, ‘do’]*

我只是将这些从返回的结果中排除。

把所有的放在一起

在 arXlive 网站上查看正在运行的关键字工厂,其特色是 n-grams 和停用词移除。你可以使用[clio-lite](https://github.com/nestauk/clio-lite#keywords-getting-under-the-hood)包中的clio_keywords函数制作自己的 Flask 应用程序。玩得开心!

第二部分:上下文搜索引擎

考虑一个技术性很强的数据集,比如来自全球最大的物理、定量和计算科学预印本库 arXiv 的数据集。假设您不是博学的学者,您会采取什么策略来查找与 大数据和安全 相关的 arXiv 最新研究?如果你在 arXiv 上进行精确的搜索,你会发现自己有一组不错的结果,但问题是,当你搜索 大数据 时,你可能没有意识到你还想在查询中包括一些不太相关的术语,如 {hadoop、spark、云计算} 。如果在 云计算和安全 领域有一些你一直错过的重大突破,会怎么样?(TL;博士 这是相同的搜索与一个‘上下文’搜索引擎 )

我将把这个问题分成两部分,通过使用 Python 中的一些 Elasticsearch 功能来解决它:

  • 首先,你如何在不是天才的情况下做出一个像样的搜索查询?
  • 其次,如何定义新奇?

做一个像样的查询,而不是一个天才

回到制作一个像样的搜索查询的问题。天才可能会采取哪些方法?嗯,他们可以沿着'关键词扩展的路线走下去,例如通过考虑所有的 {hadoop、spark、云计算} 以及 大数据 ,以及所有的* 以及 安全 这可能是一条很有前途的道路,我们已经在之前的博客中编写了工具来帮助实现这一点。然而,“关键字扩展”方法的主要问题是它缺少 上下文 。对此的一个自然扩展是'文档扩展',谢天谢地,Elasticsearch 内置了这个特性。*

更像这样

好吧,老实说,Elasticsearch 的 更像是——这个 查询实际上是‘关键词扩展++’,而不是‘文档扩展’,就像你在向量空间中想象的那样。在引擎盖下,从您想要“扩展”的输入文档中选择有代表性的术语(根据高度可配置的过程)。与纯粹的“关键词扩展”方法相比,这样做的优点在于,与所有输入项共现的项被认为比那些仅与输入项的子集共现的项更重要。结果是,可以假设用于播种“文档扩展”的扩展的关键字集具有高度的上下文相关性。

所以我的策略是:

  • 对 Elasticsearch 进行常规查询,检索 10-25 个最相关的文档。这些将是我们的“种子”文档。
  • 使用种子文档,用一个 more-like-this 查询跟进。

这种策略看起来有点像这样(实际上代码要多一点,所以实际上看起来像这个):

***# Make the initial vanilla query** r = simple_query(url, old_query, event, fields)
data, docs = extract_docs(r)**# Formulate the MLT query** total = data['hits']['total']
max_doc_freq = int(max_doc_frac*total)
min_doc_freq = int(min_doc_freq*total)
mlt_query = {"query":
             {"more_like_this":
              {"fields": fields,  **# the fields to consider**
               "like": docs,  **# the seed docs**
               "min_term_freq": min_term_freq,
               "max_query_terms": max_query_terms,
               "min_doc_freq": min_doc_freq,
               "max_doc_freq": max_doc_freq,
               "boost_terms": 1.,
               "minimum_should_match": minimum_should_match,
               "include": True  **# include the seed docs**
              }
             }
            }**# Make the MLT query** query = json.dumps(dict(**query, **mlt_query))
params = {"search_type":"dfs_query_then_fetch"}
r_mlt = requests.post(url, data=query,
                      headers=headers,
                      params=params)**# Extract the results** _data, docs = extract_docs(r_mlt)*

注意,我通过 AWS API Gateway 在 Lambda 函数中提供此功能。部署上述功能的代码也可以在同一个 repo 中找到。

定义新颖性

新奇没有特别狭窄的定义,我承认我对这个博客的定义会相当狭窄…

新奇通常可以被定义为任何(或更多)的{新的、原创的、不寻常的},我的定义将跨越{原创的、不寻常的}概念。更正式一点(但不是很正式)我是问 Elasticsearch 里每个文档的以下问题:

你和你最近的邻居有多大的不同?

只是为了理清这里的逻辑:如果文档的总样本是不平衡的,那么一个属于小众话题的文档会和一般的文档有很大的不同。我们可以通过比较最近的邻居来避免这种情况。还有什么比再次使用more-like-this(完整代码在此)更好的获取最近邻居的方法呢:

*mlt_query = {
    "query": {
        "more_like_this": {
            "fields": fields,  **# field you want to query**
            "like": [{'_id':doc_id,     **# the doc we're analysing**
                      '_index':index}], 
            "min_term_freq": 1,
            "max_query_terms": max_query_terms, 
            "min_doc_freq": 1,
            "max_doc_freq": max_doc_freq, 
            "boost_terms": 1., 
            "minimum_should_match": minimum_should_match,
            "include": True
        }
    },
    "size":1000,  **# the number of nearest neighbours**
    "_source":["_score"]
}**# Make the search and normalise the scores** r = es.search(index=index, body=mlt_query)
scores = [h['_score']/r['hits']['max_score'] 
          for h in r['hits']['hits']]**# Calculate novelty as the distance to a low percentile** delta = np.percentile(scores, similar_perc)
return 1 - delta*

自然,任何包含“不寻常”概念的像样的新颖性定义都应该包含坏数据,因为人们希望这些数据是不寻常的。我发现,通过对 arXiv 数据应用上面的新颖性评分器,我能够找出一大堆糟糕的数据,比如抄袭的和“评论的文章。我继续给这些标上 0 的新奇度,但是我相信你可以找到自己的方法!

这种新颖性评分方法的一个缺点是实现起来相对较慢(它必须在逐个文档的基础上计算),因此我对我的 Elasticsearch 数据库中的所有文档进行了预处理。

把所有的放在一起

因此,通过过度使用 Elasticsearch 的 more-like-this 查询,我们能够进行广泛的搜索,同时衍生出一种非常轻量级的新奇度。查看[clio-lite](https://github.com/nestauk/clio-lite)以更好地理解代码,并且如果您想看到这在行动中,请查看 arXiv 数据的hierar xy搜索引擎。请注意,我还使用了与第一部分中描述的相同的预处理,以及本博客中描述的数据清理。感谢阅读!

大 O——危险的实用介绍

原文:https://towardsdatascience.com/big-o-a-perilously-practical-introduction-d476d597c942?source=collection_archive---------32-----------------------

什么是大 O,我们为什么要关心它?

大 O 符号是我们可以表达不同算法的性能的一种方式,更重要的是,它们如何相对于输入的大小增长。在这里,我将尝试用一些简单的实例来说明我们为什么应该关注它。快结束的时候,我把这些数据用可视化的方式呈现出来,帮你带走。大 O 是一个巨大的主题,我会愚蠢地试图在这篇文章中涵盖所有相关的内容,所以我也建议查看进一步阅读/查看中列出的其他来源!

想象你在一家不可靠的公司工作,开发可以分析 Instagram 数据的软件。软件设计的一个主要因素可能是它处理规模的能力。

Source: Geralt, via Pixabay

当你想对你的 100 个 Instagram 粉丝进行一些超级有意义的分析时,使用一个好的算法可能并不那么重要。你可以在几毫秒内计算出你想要的任何东西,不管你选择如何进行。但是当涉及到科勒·卡戴珊和她的 1 亿追随者时,使用一个扩展性差的算法可能会相当昂贵。你的老板可能希望你想出一个能在几秒钟内返回相关数据的函数。如果你做错了一点点,也许你会花上几年的时间!

一般来说,大 O 假设一个算法的上限,这或多或少代表了最坏情况的行为。这很好,因为当你把事情弄糟时,事情不会变得更糟。衡量最佳情况的场景没有那么有用。例如,如果您想使用特定的排序算法对您的关注者进行排序,但他们已经排序了,那么这并不能真正告诉我该算法的性能。

It’s not hard to be faster than Hide The Pain Harold

此外,当我们想要以一种独立于机器的方式比较算法时,大 O 是有用的。很有可能你的 2019 年 MacBook Pro 升级了所有规格,运行任何算法的速度都比这家伙 2001 年的笔记本电脑快。此外,与这些怪物相比,你的笔记本电脑可能很糟糕。因此,在比较算法时,我们不希望这影响我们的发现。

因为我想展示规模对算法的影响,所以我将在同一台机器上运行所有的基准测试。更重要的是随着规模的增加所用时间的趋势,而不是实际所用时间本身。我可能会提醒你这一点,因为这很重要。

模特:(字面意思?)

为了展示不同算法复杂度的伸缩性,我选择在 ruby 中将 7 个不同的 Instagram 账户建模为 7 个独立的数组。为了简单起见,每个数组都包含唯一的整数来代表每个唯一的 Instagram 关注者。每个后续账户都被建模为比前一个账户多 10 倍的关注者。稍后你会看到这是如何让我们发现一些趋势的。

以下是幸运选中的 Instagram 账户:

  • 我的金鱼: 10 个追随者(我和我的家人)
  • 我: 100 个追随者(只有 8 个实际的追随者,占我自己创建的 92 个账户)
  • 我爸爸: 1000 个粉丝(他有好看的鸟照片)
  • 我的狗:一万关注者(狗很可爱)
  • 我想象中的女朋友: 10 万粉丝
  • 詹妮弗·安妮斯顿:100 万粉丝(她仅用了 5 小时 16 分钟就达到了 100 万——这是更重要的吉尼斯世界纪录之一)
  • 剑桥公爵夫妇:1000 万粉丝
  • 科勒·卡戴珊: 1 亿粉丝(大家的最爱!)

流程:

为了有条理地展示这些例子,我进行了以下步骤。

首先,我使用 Ruby 和一个名为 Benchmark 的模块来编写脚本并处理计算。基本上,Benchmark 允许我测量执行某些代码段所需的时间。

在运行的时候,我确保将我对每个账户的追随者应用每个算法所花的时间记录到一个文件中。

然后,对于日志,我随后使用 Python 处理数据,并将其转换成一个与 Plotly 非常互动的图形,其结果你可以在这篇博文的结尾预览。

不同的时间复杂性:

这是文章的要点。下面的每一小节都将描述算法,以及它们在处理 10 个追随者和 1 亿追随者时的表现。再一次,试着去掉趋势,而不是实际花费的时间!

O(1):常数

当所需的运算次数相同时,不管输入的大小如何,算法都是 O(1)。

在这个例子中,我只是返回每个 follower 数组中的第一个 follower。不管数组中有 100 万还是 1000 万个追随者,都需要相同数量的步骤来获得最终结果,因此理论速度是相同的。

我们最感兴趣的数字是最右边下方表格中的真实值。这些都是以秒来衡量的。它们是超级小的数字,但是不要担心,随着我们的进行,你将获得更好的数量感。为了减少混乱,在随后的部分中,我将只发布下面的表。

顺便说一下,如果你对如何理解这个输出感兴趣,可以看看这个博客中的‘入门’‘基准# bmbm’部分。此外,如果您想找到代码或日志的副本,或者如果您想在自己的设备上运行它,请在页面底部找到我的 GitHub 链接。

O(n):线性

当性能与输入数据集的大小成正比增长时,算法是线性的。

在这里,我只是返回一个更近的 Instagram follower(一个位于数组中 90%的位置,由‘target’标记)。我使用的是 Ruby 内置的可枚举#find,它从数组的开头开始,按顺序检查数组中的每一项,直到找到匹配项。

如你所见,每个后续账户的处理时间大约要长 10 倍,这是我们对线性复杂度的预期,因为每个账户都有 10 倍多的关注者。

O(log n):对数

在这里,我试图执行与上面完全相同的任务。这里的不同之处在于,我使用的是 Ruby 的内置方法 Array#bsearch ,它的工作方式是不断将数组一分为二,直到找到目标。你已经通过一步完成了数据集的一半。

请注意,为了使用 Array#bsearch,数组必须已经排序。

正如你所看到的,用这个二分搜索法处理粉丝每增加 10 倍所花费的时间几乎可以忽略不计。为了进行比较,在这种情况下,用这种算法从 1 亿人中找到一个特定的追随者似乎是有效的,然后在上面的线性搜索中从 100 人中找到一个。这个实现的伸缩性非常好。哇!

此外,如果将此与 O(1)进行比较,您可能会注意到它并没有太大的不同。

O(n log n):线性算法

这是执行对数运算 n 次的结果。一些流行的排序算法,比如合并排序、快速排序和堆排序,平均花费 n log n 时间。

在这个例子中,我随机打乱了所有关注者的顺序。从这里,我开始了基准测试,并记录了将它们重新排序所需的时间。我从这里借用了一个合并排序的实现。

如果进行比较,它似乎比上面的线性算法扩展性差得多。花了大约 8 分钟的时间将科勒·卡戴珊的粉丝重新排序。事情不会变得更糟了…是吗?

O(n):二次

二次算法通常是指运算次数是输入次数的平方。

嵌套 for 循环是一个常见的例子。

在这里,我模拟了 Instagram 账户的每个关注者向同一账户的每个其他关注者介绍自己的互动。是的,听起来很奇怪。

想象你和 10 个人坐在一个房间里。你是第一个向房间里的其他人介绍自己的人——一次一个人。一旦你完成了,你看着其他人也做同样的事情。这需要一些时间。现在想象一下,在一场音乐会上与 10,000 名其他人做同样的事情,你可能会在那里呆上几个月,甚至更久。你几乎不可能在同一个地方理解科勒·卡戴珊的其他 1 亿名追随者。你永远也完成不了。世界以这种方式终结。

如果您查看基准测试结果,关注者每增加 10 倍,就需要大约 100 倍的时间,因此需要 100 倍的运算量。处理 10 万个 Instagram 粉丝用了将近 10 分钟。

请注意,我甚至连 100 万以上的粉丝都没有。让我解释一下为什么——这不是因为我懒。如果我试图等待 100 万美元,需要 15 个小时(好吧,我想我可以在一夜之间完成)。处理公爵的 1000 万需要 64 天,处理科勒·卡戴珊的 1 亿粉丝需要将近 18 年。哎呀!

我想你现在明白了。二次比线性差得多。每当您需要处理大规模数据时,请远离它。

超越二次…

是的,存在诸如指数、阶乘和更高次多项式的算法。在许多情况下,它们是不切实际的,所以我想我就此打住。我们不想在这个危险的公司丢掉工作!

将所有这些放在一起:

这是我们绘制在图表上的所有数据点。请注意,我们图上的两个轴都使用对数刻度。轴上的每个刻度值代表大小增加 10 倍,而不是线性缩放。这是为了让我们可以正确地可视化我们的数据,因为它覆盖了一个巨大的规模(相信我,它看起来很可怕的法线)。

图中线条上升得越平缓,算法就越能有效地随大小缩放。如果我包括指数和阶乘,他们会直线上升!

我本来想写一个很酷的总结,但我觉得这个人已经写得很好了:

如果你想下载并自己玩这个,我已经把它放在我的 GitHub 页面这里

所有的代码,以及这篇文章,都是在一天的时间里完全从头开始写的。随着时间的推移,我会尽量更新它。利用一些好的算法,做事情比我做省力 10 倍好 100 倍!

谢谢!

进一步阅读/查看:

这一页,https://www.bigocheatsheet.com,很好地总结了这里所涵盖的内容。我肯定会花时间尽可能多的去理解。

这一页,https://discrete.gr/complexity,更详细地介绍了这个主题,并且有大量的练习题供你不及格(无论如何,这是第一次)。

如果你更喜欢视频,CS Dojo 在这里也很好地解释了这个主题的介绍。他在 YouTube 上有超过 100 万的用户是有原因的。

用于模型监控的 BigQuery 和 Data Studio

原文:https://towardsdatascience.com/bigquery-and-data-studio-for-model-monitoring-7ce9062a2ab1?source=collection_archive---------23-----------------------

监控模型性能的简单方法

这篇文章将讨论机器学习(ML)模型生命周期中的一个阶段:模型的性能监控。这是您在处理需要持续维护的简单在线系统时面临的事情之一。在许多地方,您可以看到一旦您离线评估了模型,ML 模型的生命周期就结束了。然而,在大多数实际用例中,情况并非如此。

我们生活在一个动态的世界中,数据分布随时都在变化,这就意味着两个月前您认为是好的模型可能不再是好的了。让我们以销售预测为例:人们的行为每次都在变化,改变你的销售的外部变量随时都可能发生。另一个简单的例子是预测天气,一年前训练的模型的表现可能不如有新数据的新模型。许多预测应用程序也是如此。因此,我们需要某种方法来持续监控所有这些变化,并且如果必要的话,根据更新的数据重新训练我们的模型。

在这篇文章中,我们将展示一种简单的方法来监控我们模型的性能,方法是遵循两个简单的步骤:调度和报告。

计划您的预测并保存在 BigQuery 上

如果你读到这篇文章,你已经离线训练并验证了一个模型。你已经经历了很多工作:数据探索、数据清洗、数据处理、特征工程、模型优化等。但是你仍然觉得你没有完成任务。你可能想知道什么时候你应该重新培训你的模型。让我假设我们已经有了可以运行的东西:**

*python launch_predictions.py --date current*

我们可以得到任何需要的预测。这太棒了!我们已经有了最重要的东西。现在是时候安排这些预测并将其存储在 BigQuery 中了。

为了安排我们的预测,我建议两种可能性:一种简单而好,另一种更复杂但对许多情况来说更好。先说最简单的。

克朗。UNIX 系统中使用最广为人知的调度程序。通过简单的语法,您可以安排任何您想要的进程。在您的 UNIX 机器上,运行 crontab -e 并添加如下内容。

** * * 15 0 0 docker run launch_predictions --date current*

按照前面的示例,您可以使用简单的语法来调度预测器。这个 docker 容器将每 15 分钟被触发一次。如果您的过程是轻量级的和简单的,这是非常有用的。然而,我们的工作流越复杂,维护 cron 作业就变得越复杂。所以我们转向第二个候选人,一个工作流程编排者。

工作流协调器。第二种选择是使用一些工作流程编排器,如**如果您的用例更复杂,最好使用工具来调度和监控工作流。例如,您希望监控您的数据管道以及一些管道崩溃的位置和原因。有了 Airflow,我们可以将我们的数据管道开发成有向无环图,使用 GUI 对它们进行调度和监控。这非常有用,比 cron 调度程序覆盖了更多的用例,尤其是在数据科学领域。

Airflow GUI

让我们将数据存储在 BigQuery 上。 Data Studio 兼容更多数据源,不仅仅是 BigQuery,但是在本帖中,我们将只使用 BigQuery。这里我有一个好消息,将数据保存到 BigQuery 就像将熊猫数据帧导出到 CSV 一样简单!
Pandas 的库已经实现了将我们的数据帧直接转储到 BigQuery 的功能。我们将需要安装 python 包pandas-gbq
及其依赖项。然后使用功能熊猫。DataFrame.to_gbq 。如果你想做的不仅仅是将数据存储到 BigQuery 中,我推荐使用包Google-cloud-big query
****

使用 Data Studio 构建仪表板

现在我们已经准备好在 BigQuery 中探索所有的预测。在潜入仪表板之前只是一小步。我们需要创建已处理数据的视图。在 BigQuery 中,这非常容易,因为它提供了一个网站 IDE 来生成 SQL 查询。我们需要进行 SQL 查询并生成一个视图。现在,我们准备好可视化我们的数据了!

Creating a view using BigQuery web's UI

现在让我们转到数据工作室。我们可以使用一些模板来创建我们的仪表板。不过,我鼓励你从头开始写一份报告。在短短几个小时内,我们将成为 Data Studio 的大师,并能够创建有价值的报告。我们可以使用多个数据源来构建我们的仪表板。如果我们关注了这篇文章,我们可能需要选择 BigQuery 和我们的视图。如果我们的数据已经导入,我们需要知道 Data Studio 会缓存它,我们就可以开始播放,而不用担心每次都认为它在查询 BigQuery。我们可以决定数据刷新的频率:每 12 小时(默认)、每 4 小时或每小时。当然,你也可以手动恢复数据——在谷歌文档中有更多关于它如何内部工作的信息。
我们已经导入了数据,是时候开始试验和创建我们的仪表板了。我们有多种方法来可视化我们的数据:动态表格、气泡图、条形图等。我鼓励您使用最适合我们用例的产品!

Data Studio report for sales forecasting online evaluation

上图显示了一个真实案例中的示例,在该案例中,我们对销售预测模型进行了评估,以确定最终销售额。预测存储在 BigQuery 中,用于以后的分析。这个仪表板和一些离线评估的不同之处在于,它会每天更新新的销售额。我们将能够看到我们的性能是否随着时间的推移而下降,或者我们的模型是否稳定。

安排并通过电子邮件发送我们的报告

最后,Data Studio 的另一个有用特性是报告调度。我们可以安排用电子邮件发送报告,这样我们的团队就不会错过任何东西!

Report email scheduling with Data Studio

结论

这篇文章解释了一个简单但强大的方法来监控我们的模型的性能。这里我们不讨论模型的系统健康监控;这超出了本文的范围,Data Studio 可能不是我们最好的工具。

随着时间的推移,您会监控我们模型的性能吗?您有自动化的培训和部署吗?我期待着阅读我们对这一主题的经验的评论。

免费使用 BigQuery 无需信用卡:发现、学习和分享

原文:https://towardsdatascience.com/bigquery-without-a-credit-card-discover-learn-and-share-199e08d4a064?source=collection_archive---------9-----------------------

如果您在注册 BigQuery 时遇到了困难,不用担心——现在注册并开始查询比以往任何时候都容易。新的沙盒模式甚至包括免费存储,不需要信用卡。

重要更新 : 我在 2020 年离开了谷歌,加入了雪花——所以我无法保持更新我的旧帖子。如果你想尝尝雪花啤酒,加入我们吧——我在❄️.玩得很开心

[## 雪花审判

signup.snowflake.com](https://signup.snowflake.com/)

详见官方博文《无信用卡查询:BigQuery 沙箱介绍》。在这里,我们将把重点放在尽快开始使用和查询上。

步骤 0:创建帐户

进入 BigQuery web U I,然后按照提示进行操作。在 60 秒内,不到 4 个步骤,你就可以开始查询了。

步骤 1:我的第一个查询

根据维基百科,让我们找出谁是最著名的艾伦。将此查询输入到新的 BigQuery web UI 中,然后单击“运行”:

SELECT title, SUM(views) views
FROM `fh-bigquery.wikipedia_v3.pageviews_2019`
WHERE DATE(datehour) BETWEEN '2019-01-01' AND '2019-01-10'
AND wiki='en'
AND title LIKE r'Alan\_%'
GROUP BY title
ORDER BY views DESC
LIMIT 10

原来艾伦·图灵是 2019 年前 10 天在英文维基百科中浏览量最多的艾伦。尝试查找其他名称或时间段。你能猜出谁是最有名的史蒂夫吗?

如果您不熟悉 BigQuery 的标准 SQL,我们来分析一下这个查询:

  • 这给了我每个标题的总浏览量。
  • FROM fh-bigquery.wikipedia_v3.pageviews_2019``:扫描维基百科 2019 年浏览量表。这张桌子是我共享的。
  • WHERE datehour BETWEEN ‘2019–01–01’ AND ‘2019–01–10’:我们只打算扫描 2019 年的前 10 天。
  • 有很多维基百科——我只想把重点放在英文版上。这个过滤器工作得很好,因为表 primary clustering 是我想要查询的 Wikipedia。哦,如果我过滤掉en.m——手机版英文维基百科——我会收到不同的结果。
  • AND title LIKE r’Alan\_%’:查询所有以“艾伦 _”开头的维基百科页面。该过滤器与通过标题的次级聚类一起工作得很好。注意,我在做LIKE的时候需要躲避_
  • GROUP BY title:我们将为每个标题获得SUM(views)
  • ORDER BY views DESC:根据哪个页面的浏览量最多对结果进行排序。
  • LIMIT 10:我们只想看到前 10 名。

这里发生了一些有趣的事情:

步骤 2:创建自己的表格

假设我们想深入研究关于栈溢出的张量流的所有问题。我们可以编写这样的查询:

SELECT view_count, answer_count, DATE(creation_date) date, title 
FROM `bigquery-public-data.stackoverflow.posts_questions`
WHERE 'tensorflow' IN UNNEST(SPLIT(tags, '|'))
ORDER BY view_count DESC
LIMIT 10

Top ten Tensorflow questions on Stack Overflow, by total # of views

这个查询使用了 1.66 GB 的免费配额,每个类似的查询都有类似的成本。我们可以做得更好:将您感兴趣的数据提取到一个新表中。有了 BigQuery 的沙盒模式,现在你还可以免费获得 10 GB 的存储空间。因此,我们可以将所有 Tensorflow 问题提取到一个新的表中,而不是每次都在整个数据集上运行新的查询。

要创建新表,首先创建一个数据集。请注意,如果没有与您的帐户相关联的信用卡,BigQuery 会将任何表的生存期限制为 60 天。

Create a new dataset inside your BigQuery project. Lifetime of a table will be limited to 60 days in sandbox mode.

为了在之前的查询中创建一个新表,BigQuery 现在支持 DDLDML SQL 命令:

CREATE TABLE `deleting.tensorflow_questions`
AS
SELECT view_count, answer_count, DATE(creation_date) date, title 
FROM `bigquery-public-data.stackoverflow.posts_questions`
WHERE 'tensorflow' IN UNNEST(SPLIT(tags, '|'))

现在,我可以在新表上编写这样的查询:

SELECT view_count, answer_count, date, title 
FROM `deleting.tensorflow_questions`
ORDER BY view_count DESC

好消息:这个查询现在只扫描 3 MB,这给了我更多的自由去试验。我每个月可以免费执行 30 多万次这样的查询!

分享

使用 BigQuery,你可以与你最亲密的朋友或全世界分享你的结果和发现。这在新的 web UI 上还没有实现,但是在 BigQuery classic web UI 上真的很容易:

How to share a BigQuery table on the classic UI

使用 Data Studio 可视化

多种工具和框架可以直接连接到 big query——我们喜欢它们。现在,在新的 BigQuery web UI 中,您可以快速地将结果导入 Data Studio:

Visualizing query results with Data Studio

更进一步

纽约的自行车

原文:https://towardsdatascience.com/bikes-of-new-york-6e0bbe5507f8?source=collection_archive---------23-----------------------

Photograph by Hannah McCaughey/Map by Norman Garbush.

有很多关于花旗自行车的故事,以及它如何改变了一些纽约人的出行方式。但是,花旗自行车不仅仅是一种交通工具,它是一个丰富数据的深井,等待着被争论、分割和转换,以找到一两颗关于城市如何运动的智慧珍珠,甚至可能是一些有趣的事实。

作为一名有抱负的数据科学家,使用花旗自行车数据集是一次有趣丰富的经历,其中不乏令人沮丧的插曲,还有啊哈!瞬间。

因为数据集适合伟大的可视化,我想我会在不到一周的时间里自学如何使用 D3.js 可视化库,并将其用于这个项目——天真,我知道。我对精通 D3 的陡峭学习曲线知之甚少,更不用说成为专家了。

这时,关键部分出现了,我决定专注于一些我力所能及的事情。

使用大数据集的挑战

花旗自行车的数据集不止几个,所以我决定把重点放在最后一年,从 2018 年 1 月到 2019 年 2 月。仅此一项就给我留下了 19,459,370 个数据点。是的,你没看错。这是一个爆炸加载,在一个熊猫数据帧上——而不是。甚至不要让我开始尝试绘制变量之间的任何关系。

我一直有这样的想法,数据越多越好,所以我从来没有真正想过有太多的数据是一个挑战。但它真的是。不仅仅是因为加载时间,而且正如我之前提到的,在如此大的数据集上使用可视化库只会给我留下一串错误和超时消息,此外还有 RAM 内存有限的问题。所以为了处理大数据集,内存管理应该是你的首要任务之一。

幸运的是,经过一点努力和创造性的思考,我能够扭转局面。首先,我开始从数据集中随机抽取样本,然后我有了自己的啊哈!时刻:我可以使用 SQL 查询创建我想要可视化的数据和关系的子集,然后将 SQL 查询结果转换成大多数可视化库可以处理的 CSV 文件。问题解决了。

数据

既然我已经和你分享了我的一些痛苦,我也应该分享一些我的结果。

如前所述,从 2018 年 1 月到 2019 年 2 月,共登记了 19,459,370 次旅行。经过一些清理、切片和争论,我的最终工作数据集减少到 17,437,855 次。这些只是订户的旅行,因为我决定放弃临时乘客和一日游顾客。

根据花旗自行车的月度报告,花旗自行车的年度会员总数现已达到 150,929 人。让我们来看看他们是谁。

谁在骑花旗自行车?

没有太多关于每个用户的信息,但是从数据中,我们可以得到基于总用户数的年龄和性别。这些汇总并没有给出准确的订阅者数量,而是给出了样本的基本分布。

这是一个很好的学习机会,可以利用 Plotly 制作一些互动的情节。我发现一开始理解图层次可能有点繁琐。Plotly 的图表令人惊叹,因为尽管它是使用 Python 和 Django 框架构建的,但在前端它使用了 JavaScript 和 Dr.js 库— 所以毕竟,我确实使用了一点 D3 . js

订阅者的最高出生年份类别是从 1987 年到 1991 年。让我再次声明一下,Citi Bike 目前有 150,929 名订户,为了获得这些订户的分布情况,我对乘客数据使用了聚合函数,如下面的代码片段所示。

Pandas DataFrame Capturing Birth Year SQL Query

Subscribers by Year of Birth

Code for Interactive Plotly Bar Chart

从性别来看,大多数骑手都是男性。

Pandas DataFrame from SQL query to identify Gender distribution

An interactive bar chart showing subscribers by gender. Male (1), Female (2)

他们要骑多久?

平均行程持续时间为 13 分钟,这意味着用户不会长途骑行——记住,我放弃了临时骑手和一次性客户。

我们还可以看看一周中每天的平均出行次数,正如所料,工作日的出行次数略高于周末。展示了周末乘车和工作日通勤之间的区别。

An interactive plot where circle size represents the average trip duration.

最后,我对骑行的长度和一年中的某一天之间的关系感兴趣。

An interactive plot showing the number of trips per day of the year.

该图给出了全年对花旗自行车需求波动的完整图像,当天气较暖时,4 月至 10 月期间的需求较高。这让我对天气和一天旅行次数之间的关系感到好奇,所以我用来自国家海洋和大气管理局的数据创建了一个新的熊猫数据框架,在我的原始数据框架中有每天的天气摘要。

然后我使用 Scikit Learn 库运行了一个多元回归算法。

Multiple Regression using Scikit Learn

事实证明,每天旅行次数的 62%的差异可以用天气来解释。

他们要去哪里?

一些花旗自行车停靠站肯定比其他更受欢迎。为了绘制最受欢迎的地图,包括骑行的开始和结束,我使用了叶子库。

但在我实际制作一个交互式地图之前,我运行了一个 SQL 来获取骑行量排名靠前的花旗自行车停靠站。我第一次试着把它们都映射出来,但是最终,程序崩溃了。所以我决定接受 100 美元。

A video that captures the functionality of a Folium interactive map

Code to create an interactive map using the Folium library

乘客量排名前五的车站是:

  • 潘兴广场北,1,576,381 人次
  • 西 21 街和第六大道,1,148,192 次出行
  • 东 17 街&百老汇,1,121,953 次出行
  • 百老汇和东 22 街,109,7314 次出行
  • 百老汇和东 14 街 96,901 次旅行

具体来说,这些是中央车站、麦迪逊广场公园、联合广场公园和熨斗大厦附近的码头站。

30657 号自行车呢?

最后,我想表彰去年出行次数最多的自行车,30657 — 你现在想知道你是否曾经骑过它,是吗?

骑了 2776 次,总共行驶了 36448 分钟,这辆自行车可能比我更了解纽约。所以,作为临别礼物,我将把自行车 30657 留给你,这样你就可以看到它的运行。

来源

让花旗自行车为纽约工作的天使

花旗自行车博客

利用树叶创作互动犯罪地图

花旗自行车月报——2019 年 3 月

使用 Pandas 和 SQLite 的大型数据文件

D3 . js 的搭便车指南

动画 Deck.gl 弧线

着色器之书

用逻辑回归进行二元分类

原文:https://towardsdatascience.com/binary-classification-with-logistic-regression-31b5a25693c4?source=collection_archive---------10-----------------------

在线广告点击率的估算

在绩效营销中,一个重要的关键绩效指标(KPI)是由点击率(CTR)给出的。点击率是点击特定链接的用户与查看页面、电子邮件或广告(ad)的用户总数的比率。

估计 CTR 是一个二元分类问题。当用户观看广告时,他要么点击(y=1)要么不点击(y=0)。只有两种可能的结果,让我们使用逻辑回归作为我们的模型。与用于推断连续变量的线性回归相反,逻辑回归用于估计任意数量的离散类。我给出了一个简单的可视化,它为三个主要的数据科学问题提供了正确的模型:

How to choose a model

在这个故事中,在将学到的一切应用于 Kaggle 的“点击率预测”挑战之前,我想先引导您了解逻辑回归的技术细节。

二元逻辑回归:理论

逻辑回归的特征在于一个逻辑函数来模拟标签 Y 变量 X 的条件概率

The conditional probability.

在我们的例子中,Y 表示被点击或未被点击的状态,X 表示我们想要选择的特征(例如设备类型)。

我们将使用 m 个观察值,每个包含 n 个特征。对于它们中的每一个,我们将有 m 个 n+1 维的行向量 xᵢ。我们的标签 Y 只能是 0 或 1。参数将在 n+1 维的列向量θ中给出。

Definitions of Y, X and Θ.

用户点击给定观察值 X 的条件概率可以建模为 sigmoid 函数。

The conditional probability modeled with the sigmoid logistic function.

逻辑回归的核心是 sigmoid 函数。sigmoid 函数将连续变量映射到闭集[0,1],然后可以将其解释为概率。右手边的每个数据点被解释为y=1,左手边的每个数据点被推断为y=0

A plot of the sigmoid function with labeled sample data.

衍生(可选)

在推导条件概率时,sigmoid 函数自然出现。我们可以用贝叶斯定理来表示 P(Y|X)

Bayes’ theorem

根据贝叶斯解释

  • P(Y|X)为后验,
  • P(Y)为先验,
  • 和 P(X)作为归一化因子。

我们将拟合数据的后验和先验,并且必须去掉未知的概率 P(X)。这可以通过使用补充条件概率来完成。

Complement conditional probability.

当将后验概率除以互补条件概率并取对数时,我们得到对数优势(logit)

The logit can be modeled as a linear function of X.

这里我们假设 logit 是 X 中的线性函数!现在,我们只需撤销对数并求解后验概率,即可导出 sigmoid 函数

Sigmoid derivation.

最大似然估计

到目前为止,我们已经用一组参数θ模拟了后验概率。我们如何确定θ的最佳选择?用户点击的条件概率等于 sigmoid 函数。所有情况的概率总和必须等于 1。因为我们只有两种情况,所以我们可以找到一种优雅的方式在一个表达式中表达这两种概率:

The probability mass function of the Bernoulli distribution.

右边是伯努利分布的概率质量函数(PMF)。伯努利分布描述了一个随机变量,它可以采取两种结果中的一种,比如我们的标签被点击或未被点击。现在,为了确定我们的参数θ,我们需要在只给定一个样本的情况下,最大化复制总体分布的概率。这种方法被称为最大似然估计 (MLE)。我们主要是将样本中每个事件的所有概率结合起来。这种联合概率被称为似然性,它与概率有许多共同之处,但主要集中在参数上

The likelihood.

我们可以将上面的函数最大化,但是为了方便起见(为了获得更漂亮的导数),我们将对数应用于可能性。我们可以这样做,因为对数是单调递增的,因此保留了最大值的位置。通过应用对数,乘积变成和

The log-likelihood.

为了最大化对数似然,我们可以使用微积分。极值点的导数必须等于零

The first derivative of the log-likelihood.

sigmoid 函数的导数(可选)

在最后一个结果中,我们使用了 sigmoid 函数对θ的导数。推导过程如下

Derivation of the derivative of the sigmoid function.

牛顿-拉夫森

为了执行 MLE,我们必须找到对数似然的一阶导数的根。我们可以使用牛顿-拉夫森求根算法来完成这项任务。牛顿-拉夫森法是最大化对数似然的标准方法。它需要计算二阶导数。在我们的例子中,我们可以通过分析来确定它。在其他情况下,二阶导数在计算上是昂贵的,我们可以使用梯度下降(上升)进行优化。二阶导数由下式给出

The second derivative of the log-likelihood.

牛顿-拉夫森方法告诉我们如何更新每次迭代的参数。

Newton-Raphson iteration.

估计 CTR

在这个故事的第二部分,我们想编写我们自己的逻辑回归实现。我制作的 Jupyter 笔记本已经作为要点出版。我们将使用“点击率预测”Kaggle 竞赛的数据。下载数据后,我们对其进行解包,并在对完整集进行训练之前准备一个 10000 行的样本。

unzip avazu-ctr-prediction.zip
gunzip train.gz
head -n10000 train > train_sample.csv

然后,我们将 CSV 加载到 panda 数据帧中,并将其分为训练集和测试集

df = pd.read_csv('train_sample.csv')
msk = np.random.rand(len(df)) < 0.8
train = df[msk]
test = df[~msk]

现在你应该关注特性探索,但是为了简单起见,我选择了列 device_type、C1、C15C16 作为特性列。然后我可以准备我的特征矩阵 X 并使用点击列作为标签

m = len(train)
X_train = np.ones((m, 5))
X_train[:,1] = train.device_type.to_numpy()
X_train[:,2] = train.C1.to_numpy()
X_train[:,3] = train.C15.to_numpy()
X_train[:,4] = train.C16.to_numpy()y_train = train.click.to_numpy()

为了使我们的算法工作,我们需要先前导出的对数似然的一阶和二阶导数,其可以编码如下

def DLogLikelihood(X, y, theta):
    res = np.zeros(theta.shape[0])
    for i in range(0, X.shape[0]):
        x_i = X[i]
        y_i = y[i]
        res += x_i * (y_i - sigmoid(np.dot(theta, x_i)) )
    return resdef DDLogLikelihood(X, theta):
    res = np.zeros((theta.shape[0], theta.shape[0]))
    for i in range(0, X.shape[0]):
        x_i = X[i]
        sigma = sigmoid(np.dot(theta, x_i))
        res += np.outer(x_i, x_i) * sigma * ( 1 - sigma ) 
    return -res

迭代 Netwon-Raphons 步骤和我们的逻辑回归算法然后

def NewtonRaphsonTheta(X, y, theta):
    return theta - np.dot(
        np.linalg.inv(DDLogLikelihood(X, theta)),
        DLogLikelihood(X, y, theta))def logisticRegression(X, y, epochs=100):
    theta = np.zeros(X.shape[1])
    for i in range(epochs):
        theta = NewtonRaphsonTheta(X, y, theta)
    return theta

通过调用logisticRegression(X, y),我们将迭代计算参数θ,然后可以用它来预测用户的点击概率

def predict(X, theta):
    res = np.zeros(X.shape[0])
    for i in range(len(res)):
        x = X[i]
        res[i] = sigmoid(np.dot(theta, x))
    return res

对于试运行,我们得到以下概率

theta = logisticRegression(X_train, y_train, epochs=100)
y_pred = predict(X_test, theta)print(y_pred)
[0.18827126 0.16229901 … 0.16229901 0.16229901 0.16229901]

为了评估该模型,我将测试集的预测与它们的实际值进行了比较,结果显示该模型相当差。为了改进,我们可以在特征选择上花更多的时间,在更多的数据上进行训练,同时不断地用评估指标测量模型性能,如对数损失ROC 曲线。

总结

  • 逻辑回归用于多分类问题
  • 如果我们只有两个类,则使用二元逻辑回归
  • P(Y|X)由 sigmoid 函数建模,该函数从(-∞,∞)映射到(0,1)
  • 我们假设 logit 可以建模为线性函数
  • 为了估计参数θ,我们最大化对数似然
  • 伯努利分布是具有两种可能结果的离散分布,用于二元分类
  • 我们使用牛顿-拉夫森作为求根器,因为我们可以很容易地计算对数似然的二阶导数

[2]:统计学习的要素,t .哈斯蒂,r .蒂布拉尼,j .弗里德曼https://web.stanford.edu/~hastie/ElemStatLearn/

HandySpark 简化二元分类器评估

原文:https://towardsdatascience.com/binary-classifier-evaluation-made-easy-with-handyspark-3b1e69c12b4f?source=collection_archive---------13-----------------------

Photo by SJ Baren on Unsplash

TLDR;

HandySpark 是一个 Python 包,旨在改善 PySpark 用户体验,尤其是在涉及到探索性数据分析时,包括可视化功能,以及现在的二进制分类器的扩展评估指标。

使用 Google Colab 亲自尝试一下:

[## 谷歌联合实验室

使用 HandySpark 探索泰坦尼克号

colab.research.google.com](https://colab.research.google.com/github/dvgodoy/handyspark/blob/master/notebooks/Exploring_Titanic.ipynb)

检查存储库:

[## dvgodoy/handyspark

HandySpark——带来熊猫般的能力,激发数据帧——dvgodoy/HandySpark

github.com](https://github.com/dvgodoy/handyspark)

介绍

在我之前的帖子中,我介绍了 HandySpark ,这是我为 PySpark 开发的一个包,用来帮助缩小熊猫Spark 数据帧之间的差距。

今天,我很高兴地宣布新版本的发布,它不仅解决了分层操作的一些性能问题(现在应该快几倍了!),而且使得评估二进制分类器更加容易。

二元分类任务

我们将使用一个简单的二进制分类任务来说明 HandySpark 提供的扩展评估功能:再一次使用泰坦尼克号数据集预测乘客存活率。

让我们首先设置好一切,然后加载我们的数据:

Setting everything up and loading the Titanic dataset 😃

要评估一个模型,我们需要先训练它。为了训练一个模型,我们需要首先清理数据集。所以,就从这点开始吧!

使用 HandySpark 清理数据

我们知道Age, CabinEmbarked缺少值。你可以使用[isnull](https://dvgodoy.github.io/handyspark/handyspark.html#handyspark.HandyFrame.isnull)方法很容易地检验这一点。

为了让我们的模型和管道尽可能简单,让我们只使用数字 变量,比如AgeFareSibSpParch.

对于输入Age的缺失值,我们可以只对每个缺失值使用一个简单平均值,对吗?但是你真的认为一等舱、二等舱和三等舱的男女乘客的年龄差不多吗?

让我们使用[stratify](https://dvgodoy.github.io/handyspark/handyspark.sql.html#handyspark.sql.dataframe.HandyFrame.stratify)操作来检查一下,就像这样:

hdf.stratify(['Pclass', 'Sex']).cols['Age'].mean()Pclass  Sex   
1       female    34.611765
        male      41.281386
2       female    28.722973
        male      30.740707
3       female    21.750000
        male      26.507589
Name: Age, dtype: float64

这显然是有区别的……女性比男性年轻,阶级越低,乘客越年轻。毫不奇怪,我会说…

那么离群值呢?我们可以使用图基的栅栏方法来识别然后栅栏值被认为是极端的。对于Fare,我们有多少离群值?

hdf.cols['Fare'].outliers(k=3)Fare    53
Name: outliers, dtype: int64

请记住,图基的栅栏非常敏感——他们假设高于 k 乘以四分位数间距(IQR) 的一切都是极值。在我们的例子中,它导致了 53 个异常值!你可以尝试不同的 k 值来校准它,尽管…

所以,让我们用我们发现的数据来清理它。首先,我们根据给定PclassSex的平均值填充缺失的Age值。接下来,我们使用 Tukey 的方法保护 Fare值:

Cleaning up!

建立模型

一旦我们有了干净的数据集,我们就可以建立一个简单的分类器来预测乘客是否在泰坦尼克号灾难中幸存。让我们使用 Spark 的RandomForestClassifier来完成这个任务。

但是,记住 Spark ML 算法需要将所有特征整齐地组装成一个特征向量。此外,该特征向量不接受缺失的值。

这个怎么处理?我们可以简单地使用 HandySparkimputerfencer方法来创建相应的变压器来填充缺失值和隔离异常值。然后,我们将这些变压器添加到我们的管道中,我们就可以开始了!

Training a classifier and making predictions

我们的预测是什么样子的?让我们把数据帧做成一个手帧,看看我们的标签和分类器生成的预测:

predictions.toHandy().cols[['probability', 'prediction', 'Survived']][:5]

First 5 rows from our predictions

概率列包含一个向量,其概率分别与类别 0 和 1 相关联。为了评估的目的,我们需要成为阳性病例的概率,因此我们应该查看概率向量的第二个元素。预测栏显示了相应的,假设阈值为 0.5

评估模型

我们的模型有多好?我们可以只计算具有匹配预测和幸存列的行的比例,这就是我们的准确度。然而,事实证明,准确度是而不是评价二元分类器的一个很好的标准。

为了真正说明我们的模型有多好,我们需要其他指标,如真阳性率 ( TPR ,也称为召回)、假阳性率 ( FPR )和精度,这将 随我们选择的阈值而变化*,从而将预测概率转化为预测类别(0 或 1*

如果我们检查每一个可能的阈值并计算这些度量,我们可以为给定的模型建立接收器工作特性 ( ROC )曲线和精度召回 ( PR )曲线。

这就带来了另一个问题:如何利用这些曲线比较两个模型?它们可能在不同的点交叉,对吗?解决这个问题的一个方法是查看曲线下的面积:粗略地说,面积越大,模型越好。这样我们就可以计算 ROC**** 曲线下的面积( AUROCROC AUC ,或者有时只是 AUC )和 PR** 曲线下的面积( PR AUC )。

如果你想了解所有这些指标的更多信息,请查看这些帖子:被困惑矩阵接收器操作特性曲线揭秘了解 AUC — ROC 曲线了解 ROC 曲线(互动)。

使用 PySpark 评估模型

我们既有好的也有一些坏的消息……好的消息是: PySpark 给了我们两个 ROC AUC 和 PR AUC。坏消息是: PySpark 只给了我们那个:-(

Using PySpark Evaluator to get ROC AUC and PR AUC

如果我们想用不同的阈值做实验呢?出手相救:-)

使用 HandySpark 评估模型

HandySpark 扩展了 PySpark 的BinaryClassificationMetrics,因为它的 Java 对应物已经有了几个检索指标和阈值的方法,现在由 HandySpark 公开。但是也有新实现的方法。

HandySpark 还可以使用包含预测概率标签的数据帧作为自变量,如下要点所示:

Plotring ROC and PR curves, getting metrics by threshold and confusion matrices with HandySpark!

让我们深入研究评估模型的所有这些新的可能性。

绘制曲线

一张图片胜过千言万语!所以,让我们从使用plot_roc_curveplot_pr_curve方法的两条曲线的开始。就这么简单:

fig, axs = plt.subplots(1, 2, figsize=(12, 4))
bcm.plot_roc_curve(ax=axs[0])
bcm.plot_pr_curve(ax=axs[1])

ROC and PR curves

瞧啊!现在我们可以说,如果我们愿意接受 20%的假阳性率,我们将得到 60%以上的真阳性率。够好吗?酷!

你会问,我们应该使用哪个阈值来实现这一点?

阈值和指标

我们可以使用getMetricsByThreshold方法获得所有阈值和相应的指标。它返回一个 Spark 数据帧,然后我们可以过滤出感兴趣的指标(在我们的例子中,FPR 介于 19%和 21%之间):

bcm.getMetricsByThreshold().filter('fpr between 0.19 and 0.21').toPandas()

Thresholds for FPR between 19% and 21%

我们需要的误报率最多为 20%,那么对应的阈值为 0.415856 。这将给我们 68.1%的真阳性率 ( 召回)和 68.3%的精度

我们还可以查看使用特定的阈值构建的混淆矩阵,这产生了我们刚刚获得的指标。

混淆矩阵

混淆矩阵可以,呃… 混淆!;-)为了尽量减少阅读时可能产生的任何误解,我已经用标记了列和行,所以你不需要猜测哪个类先出现,哪个是预测值和实际值。

用你选择的阈值调用print_confusion_matrix就行了,就这么简单:

bcm.print_confusion_matrix(.415856)

Confusion Matrix — not so confusing anymore 😃

最后的想法

我的目标是改善 PySpark 用户体验,让执行数据清理模型 评估变得更加容易。不用说,这是一项正在进行的工作,我已经计划了更多的改进。

如果你是使用 PySpark 的数据科学家,我希望你尝试一下 HandySpark让我知道你对它的想法:-)

[## dvgodoy/handyspark

HandySpark——带来熊猫般的能力,激发数据帧——dvgodoy/HandySpark

github.com](https://github.com/dvgodoy/handyspark)

如果你有任何想法、评论或问题,请在下方留言或联系我 推特

生物信息学:代码与生物学相遇的地方

原文:https://towardsdatascience.com/bioinformatics-where-code-meets-biology-faa2b99cdfcb?source=collection_archive---------5-----------------------

医疗保健的未来简介

你和我有 30 亿个共同点。或者接近它。不只是你和我,其他人都一样。

这些东西会是什么呢?

我喜欢运动。你知道吗?

机器学习怎么样?我很喜欢。

我们可以继续努力,找出答案,但要达到 30 亿美元还需要一段时间。

即使我们成功了,我们也会比较错误的东西。

好吧,什么是正确的事情?

我们的 DNA。或者更具体地说,结合形成核酸的核碱基,这些核酸链在一起构成我们的 DNA。

DNA 是生命的语言。这是为所有生物奠定基础的密码。

就像一本书是由字母表的字母组合而成,你和我是由大约 32 亿个核碱基组合而成——腺嘌呤(A)、胸腺嘧啶(T)、胞嘧啶(C)和鸟嘌呤(G)。这个集合序列被称为基因组。

如果我们把 32 亿左右的 A、C、G 和 T 放在一起,30 亿左右是匹配的,但 2000 万到 3000 万是不同的。这些差异可以解释为什么我是金发而你是不同的颜色。如果你也是金发碧眼,我们可以把它添加到共同点列表中。

Although most of our DNA is the same, if we looked closely, we’d find a few differences. A difference of 1 letter is known as a SNP (single nucleotide polymorphism).

我在这里漏掉了一些东西,例如,不同的字母组如何编码蛋白质,其他组如何组成基因,基因内部如何有不同的版本等等。

为什么?

因为 DNA 是一种复杂的动物。理解所有 32 亿个字母是如何相互作用的仍然是一个很大的研究课题。众所周知,一个人不可能理解这样一种语言。

这就是计算机力量的来源。当生命的语言遇到自然的语言。这也是生物信息学出现的地方。

生物信息学结合了生物学、计算机科学、数学、统计学的原理来理解生物学数据。

寻找复制的起源

Coursera 生物信息学专业中的第一个示例问题涉及寻找复制的起源。复制起点是复制开始的基因组序列。

在你出生之前,你开始是一个单细胞,然后一个在两个之间,两个变成四个,最后,四个变成你。对于第一个分裂的细胞,它必须复制自己的基因组。后续的每个细胞也是如此。

了解了这一点,你就可以开始想象寻找复制的起源是多么有价值。

比如说有一组细胞内含有非常擅长抗癌的蛋白质。我们怎样才能获得更多这样的细胞来增强我们的防御呢?

一种方法可能是在我们的好细胞中寻找原始复制,找到它,然后利用这些信息在体外产生更多的细胞,然后再把它们放回体内。

让我们试试。

故事时间

因为你的生物学家朋友知道你一直在练习你的编码技能,她来找你寻求帮助。

A fictional sequence of 1000 nucleobases which combine to create a DNA sequence of a strong cancer-fighting cell.

经过多次实验,从上面的细胞样本中切下部分 DNA,观察细胞是否会复制。她认为她已经找到了复制的起源。

可以肯定的是,她想知道它在整个序列中出现了多少次,以及它是否足够重要,足以成为复制的真正起源。

她给你看文件,然后你开始工作。

The code you write for your friend to find how many times a pattern occurs in a sequence of DNA.

稍加修改后,您认为您的代码可以运行了。它通过 DNA 序列寻找模式,如果找到匹配,它更新计数器。当它到达 DNA 模式的末尾时,它返回计数(该模式在 DNA 序列中出现的次数)。

“什么格局?”你问。

“TGTAGTGTG。”

你帮你的朋友运行代码。

结果返回为 18。

她发现的模式在好细胞的 DNA 序列中出现了 18 次。

“这有意义吗?”你问。

“它发生一次的概率小于 0.004%,所以 18 次肯定意味着什么,但我必须核实一下。”

你擅长编码,但不擅长统计,你的生物学家朋友也不擅长。她回到实验室找到她的统计学家朋友,进行更多的测试。

这里发生的是几个领域的结合。你的生物学家朋友通过实验发现了一个潜在的复制起源的方法,但这是漫长而乏味的。为了帮忙,你提供了一些你的计算机科学技能。然后找出你的结果是否有统计学意义。

这种不同领域的交叉是生物信息学发挥作用的一个例子。每个领域都带来了真知灼见,但将它们放在一起会让它们更有价值。

医疗保健的未来

上面的场景是一个简化的例子,真实世界中的生物信息学需要更多的步骤。

首先,你如何得到一个基因组?

幸运的是,在过去的几十年里,这部分已经有了快速的发展。第一个人类基因组测序花了 23 年时间,世界各地的团队和数十亿美元。现在,你可以在几天内以不到 15,000 美元的价格完成这项工作。

好了,你有了一个基因组,现在你要做什么?

好问题。这是用不同的统计和计算方法探索 DNA 的新方法正在积极研究的地方。

你在上面看到的 DNA 序列是线性的,单个字符串。但实际的 DNA 是不同的,它由两条链组成(一条链是另一条链的反面),不同的区域并不总是以相同的方式相互作用。所以找到一个模式可能不像我们看到的那样简单。

好吧,假设你对基因组有了更多的了解,它是如何被应用的呢?

生物信息学最有趣的应用是个性化医疗。为个人量身定制的医疗保健,而不是为个人量身定制的医疗保健。

我有幸亲眼看到的一个项目是由 Max Kelsen 开发的免疫疗法结果预测或 IOP。目标是使用全基因组数据来开发预测癌症患者免疫治疗结果的工具。有些患者对免疫疗法的反应比其他人好,为什么?答案会隐藏在它们的基因组中吗?

生物信息学的应用也不仅限于预测癌症治疗的结果。

营养基因组学研究食物和基因组的相互作用。想象一个专门针对你的 DNA 制定的饮食计划。

我爸爸每天都要服用一些药物来缓解他的帕金森氏症和老年痴呆症的症状。服用它们的最初几年并不顺利。只是在尝试了几轮不同的药物后,他才发现一些没有让他感觉更糟的药物。药物基因组学——根据一个人的基因组制造药物——能帮助其他人更快找到合适的药物吗?

健康和科技不会很快消失。我们只是触及了这两个领域交汇处的表面。

我进入生物信息学是几天前开始的,在 Coursera 上开始了生物信息学专业。但是随着我学习和经历的增多,我一定会分享我的发现。请务必继续关注。

这篇文章的视频版本可以在 YouTube 上找到。

为了计算 0.004%的数字,将(1000–9+1)*(0.25)⁹(长度为 9 的 A,C,G,T 的某个模式出现在 A,C,G,T 的随机序列中的概率)的结果四舍五入到最接近的千分之一。

像 23 和 me 这样的公司进行基因测试的费用要低得多,然而,这些服务使用基因分型而不是全基因组测序。

生物数据科学和为什么领域专业知识和背景是王道

原文:https://towardsdatascience.com/biological-data-science-and-why-domain-expertise-and-context-is-king-in-55562787721?source=collection_archive---------22-----------------------

如果我给你看一张猫的照片,告诉你那是一只粉红色的熊猫,你会相信我吗?

如果我给你看一张猫的照片,告诉你那是一只粉红色的熊猫,你会相信我吗?你将如何证实我告诉你的是真的?你可以天生做到这一点,因为你有一个内置的神经元网络(不要与神经网络混淆),你可以自己决定算法的图像分类是否正确。在 ImageNet 的情况下,这大约是 94%的精确度。在生物数据科学中,这是不可能的,这就是为什么它如此依赖于专业知识和背景。

Stanford CS231n

生物数据科学和验证结果

如果我给你看一个金发的基因序列,并告诉你它是雀斑的编码,你会怎么做?你会相信我的话吗?我是说,我们才刚认识,而且是在网上认识的。你已经那么信任我了吗?!

不,很可能你必须依靠第二种算法,最有可能是爆炸,来告诉你我给你的基因序列是什么。

这就是生物数据科学如此依赖领域专业知识和背景的原因。如果你不能相信产生结果的算法,那么你也不能相信你的结果。

随着每天收集的生物学数据的爆炸式增长,将领域专业知识和生物学背景与数据科学技能结合起来变得更加重要。虽然查看基因组信息的庞大数据集并进行分析很容易,但这往往会导致重大错误。

举个例子,使用一个n×m矩阵的 n 个特征和 m 个患者。如果你用这个矩阵来运行一个二维卷积神经网络,你将会暗示相邻的样本有关系。对于独立的人来说,这是不正确的。

由于背景的重要性,确保你将生物数据科学工作与健康剂量的领域专业知识相结合,以确保你以正确的方式做酷的事情。

我叫亚历山大·泰特斯,我有旅行癖。我经常陷入沉思,迷失在树林中,而且经常同时迷失在两者之中。我的人生使命是重新定义职业成功,将个人和职业追求都包括在内。你可以在LinkedInTwitter上找到我,在网上分享一些想法 **

生物与非生物/人工智能

原文:https://towardsdatascience.com/biological-versus-non-biological-artificial-intelligence-9dee32a1517d?source=collection_archive---------17-----------------------

Photo by richard thomposn on Unsplash

什么是智能?

伟大的哲学家苏格拉底(公元前 470/469-公元前 399)说过“我知道我很聪明,因为我知道我什么都不知道”。阿尔伯特·爱因斯坦(1879-1955)认为想象力是智慧而非知识的真正标志。而斯蒂芬·霍金(1942–2018)将智力视为适应变化的能力。人们创造了许多理论来解释生物智能,如查尔斯·斯皮尔曼(1863-1945)的理论,霍华德·厄尔·加德纳(1943-)的多元智能理论和罗伯特·斯腾伯格(1949-)的三元智能理论。根据斯皮尔曼的理论,智力被定义为以富有成效的方式获取和使用知识的能力。多元智能理论将智能定义为创造一种有效的产品或提供一种在文化中受到重视的服务的能力,以及使一个人有可能解决生活中的问题的一套技能,以及找到或创造问题解决方案的潜力,这涉及到收集新知识。智力三元论可能是最全面的理论。它将人类智力定义为一种精神活动,旨在有目的地适应、选择和塑造与个人生活相关的现实世界环境。这意味着智力是一个人在一生中理性处理环境变化的能力。这个定义与斯蒂芬·霍金的定义不谋而合,因为两人都认为适应能力是智力的主要标志。适应意味着处理复杂情况的能力,以及对新情况迅速而成功地做出反应的能力。智慧的其他标志包括但不限于,从模糊或矛盾的信息中理解意义,使用理性解决问题,以普通、理性的方式理解和推断,应用知识操纵环境,认识到不同因素在一种情况下的相对重要性,以及从经验中学习或理解。这就产生了区分生物智能和非生物或人工智能的需要。

人类对抗机器

如果你看了德国的“心算器”,鲁迪格·甘姆和他惊人的快速心算大型算术表达式的能力,以及记忆 81^100 等大幂幂的能力,你很可能会称他为天才。

然而,由一台机器执行复杂的算术和逻辑运算并不意味着这台机器就是一台智能机器。另一方面,人类过去常常低估智力的真正标志。我们过去常常认为认知过程是理所当然的,例如辨别面孔、识别物体、识别语言声音、解决问题和从经验中学习。具有这些认知能力的机器绝对是真正的智能机器。下表提供了人机之间的快速比较。

人工智能

人工智能旨在模仿/逆向工程和增强生物智能,以建立能够在结构化/非结构化、静态/动态和完全/部分可观察的环境中自主运行和交互的智能系统/过程。这通常包括借鉴人类智能的特征,如情境意识、决策、解决问题、从环境中学习并适应环境的变化。机器可以增强我们的肌肉和认知能力(智力增强——IA)。

Credit: Alaa Khamis

人工智能是一种不断发展的技术,而不是一种全新的技术,因为它的种子可以追溯到古典哲学家,以及他们在将人类思维建模为符号系统方面的努力,这导致了作为思维过程的“连接主义”。人工智能包含许多子领域,如感知、知识表示、认知推理、机器学习、数据分析、问题解决、分布式人工智能和表演。机器学习(ML)是最著名的人工智能形式,因为它在汽车、精准农业/智能农业、认知医疗、金融科技和消费电子等不同领域具有强大且日益多样化的商业收入流..

Credit: Alaa Khamis

在下一篇文章中,我将谈论人工智能的三次浪潮:人工狭义智能(AI)、人工通用智能(AGI)和人工超级智能(ASI)。

生物医学图像分割:注意力 U 网

原文:https://towardsdatascience.com/biomedical-image-segmentation-attention-u-net-29b6f0827405?source=collection_archive---------8-----------------------

通过在标准 U-Net 上附加注意门来提高模型的灵敏度和准确性

医学图像分割已经被积极地研究以自动化临床分析。深度学习模型一般需要大量的数据,但获取医学图像既繁琐又容易出错。

Attention U-Net 旨在自动学习关注不同形状和大小的目标结构;因此,Oktay 等人的论文名称“学习在哪里寻找胰腺”

关注优图网之前的相关作品

优信网

U-Nets 通常用于图像分割任务,因为它的性能和对 GPU 内存的有效使用。它的目标是以较少的训练样本实现可靠的临床使用的高精度,因为获取带注释的医学图像可能是资源密集型的。阅读更多关于优信网的信息。

尽管 U-Net 具有出色的表示能力,但它依赖于多级级联卷积神经网络来工作。这些级联框架提取感兴趣的区域并进行密集预测。这种方法导致计算资源的过度和冗余使用,因为它重复提取低级特征。

注意模块

【需要注意】Jetley 等推出端到端可训练的注意模块。注意门常用于自然图像分析和自然语言处理。

注意力被用于执行特定于类的池化,这导致更准确和鲁棒的图像分类性能。这些注意力地图可以放大相关区域,从而显示出优于几个基准数据集的泛化能力。

软硬注意

注意力函数的工作原理是通过迭代区域提议和裁剪来使用图像区域。但这通常是不可微的,并且依赖于强化学习(一种基于采样的技术,称为强化)进行参数更新,这导致优化这些模型更加困难。

另一方面,软注意是概率性的,并且利用标准的反向传播,而不需要蒙特卡罗采样。Seo 等人的的软注意方法通过实现非均匀、非刚性的注意图来展示改进,该注意图更适合于在真实图像中看到的自然物体形状。

关注优信网有什么新内容?

注意门

为了提高分割性能, Khened 等人Roth 等人依靠附加的在先对象定位模型来分离定位和后续分割步骤。这可以通过在 U-Net 架构之上集成注意力门来实现,而无需训练额外的模型。

因此,结合到 U-Net 中的注意门可以提高模型对前景像素的灵敏度和准确性,而不需要显著的计算开销。注意门可以逐渐抑制不相关背景区域的特征反应。

注意门在连接操作之前实现,以仅合并相关的激活。源自背景区域的梯度在反向传递期间被向下加权。这允许基于与给定任务相关的空间区域来更新先前层中的模型参数。

基于网格的门控

为了进一步改善注意机制, Oktay 等人提出了网格注意机制。通过实现基于网格的选通,选通信号不是用于所有图像像素的单个全局向量,而是适应于图像空间信息的网格信号。每个跳过连接的选通信号聚集来自多个成像尺度的图像特征。

通过使用基于网格的选通,这允许关注系数更具体地针对局部区域,因为它增加了查询信号的网格分辨率。与基于全局特征向量的门控相比,这实现了更好的性能。

软注意技术

附加软注意用于句子到句子的翻译( Bahdanau 等人Shen 等人)和图像分类( Jetley 等人Wang 等人)。虽然这在计算上更昂贵,Luong 等人已经表明,软注意可以比乘法注意实现更高的准确性。

体系结构

下面是注意力 U-Net 的图解。

我的注意力 U-Net 实验

我将使用 Drishti-GS 数据集,其中包含 101 幅视网膜图像,以及光盘和光学杯的注释掩膜。50 幅图像用于训练,51 幅用于验证。

实验设置和使用的指标将与 U-Net 相同。

模型在 13 分钟内完成训练;每个时期大约需要 15 秒。

用于比较的几个 U-Net 模型之间的度量,如下所示。

测试从模型处理一些看不见的样本开始,以预测光盘(红色)和光学杯(黄色)。下面是对注意力优网、 UNet++优网的测试结果,以供对比。

结论

Attention U-Net 旨在通过在标准 U-Net 上附加注意门来进一步提高分割精度,并使用更少的训练样本。

Attention U-Net 消除了某些分割架构所需的外部对象定位模型的必要性,从而提高了模型对前景像素的灵敏度和准确性,而没有显著的计算开销。

Attention U-Net 还结合了基于网格的门控,这使得注意力系数更具体地针对局部区域。

阅读其他 U-Net 架构:

[## 生物医学图像分割:U-Net

使用非常少的训练图像,并产生更精确的分割。

towardsdatascience.com](/biomedical-image-segmentation-u-net-a787741837fa) [## 生物医学图像分割:UNet++

通过一系列嵌套、密集的跳过路径提高分段准确性

towardsdatascience.com](/biomedical-image-segmentation-unet-991d075a3a4b)

这里是 PyTorch 代码的注意 U-Net 架构:

[## 数据科学家:21 世纪最肮脏的工作

40%的吸尘器,40%的看门人,20%的算命师。

towardsdatascience.com](/data-scientist-the-dirtiest-job-of-the-21st-century-7f0c8215e845)

生物医学图像分割:U-Net

原文:https://towardsdatascience.com/biomedical-image-segmentation-u-net-a787741837fa?source=collection_archive---------13-----------------------

使用非常少的训练图像工作,并产生更精确的分割

图象分割法

假设我们想知道一个物体在图像中的位置以及这个物体的形状。我们必须给图像中的每个像素分配一个标签,这样具有相同标签的像素就属于那个对象。与对象检测模型不同,图像分割模型可以提供图像中对象的精确轮廓。

图像分类、目标检测和图像分割的区别

图像分类帮助我们对图像中包含的内容进行分类。目标是回答“这个图像里有猫吗?”,通过预测是或否。

物体检测指定物体在图像中的位置。目标是识别“这张图片中的猫在哪里?”通过围绕感兴趣的对象绘制边界框。

图像分割为图像中的每个对象创建一个像素式遮罩。目标是通过对所需标签中的每个像素进行分类来识别图像中不同对象的位置和形状。

优信网

在本文中,我们将探索由奥拉夫·龙内伯格、菲利普·费舍尔和托马斯·布罗克斯撰写的 U-Net 。这篇论文发表在 2015 MICCAI 上,在 2019 年 11 月有超过 9000 次引用。

关于优信网

U-Net 用于生物医学图像的许多图像分割任务,尽管它也用于自然图像的分割。U-Net 已经超越了先前 Ciresan 等人的最佳方法,赢得了 ISBI 2012 EM(电子显微镜图像)分割挑战赛。

需要更少的训练样本 深度学习模型的成功训练需要数千个带注释的训练样本,但是获取带注释的医学图像是昂贵的。U-Net 可以用较少的训练样本进行端到端的训练。

精确分割 精确分割掩模在自然图像中可能并不重要,但是医学图像中的边缘分割误差导致临床设置中的结果不可靠。尽管训练样本较少,但 U-Net 可以产生更精确的分段。

U-Net 之前的相关工作

如上所述, Ciresan 等人致力于神经网络分割神经元膜,用于电子显微镜图像的分割。网络使用滑动窗口通过提供像素周围的局部区域(小块)作为输入来预测每个像素的类别标签。

相关工作的限制:

  • 由于滑动窗口、扫描每个补丁以及重叠造成的大量冗余,它非常慢
  • 无法确定滑动窗口的大小,这会影响定位精度和上下文使用之间的权衡

体系结构

U-Net 具有优雅的架构,扩展路径或多或少与收缩路径对称,并产生 u 形架构。

收缩路径(下采样) 看起来像一个典型的 CNN 架构,通过连续堆叠两个 3×3 卷积(蓝色箭头),然后是一个 2×2 最大池(红色箭头)进行下采样。在每一个下采样步骤中,通道的数量都会翻倍。

扩展路径(上卷积) 一个用于上采样的 2x2 上卷积(绿色箭头)和两个 3x3 卷积(蓝色箭头)。在每个上采样步骤中,通道数量减半。

在每个 2×2 上卷积之后,由于每个卷积中边界像素的丢失,特征图与来自收缩路径(灰色箭头)的相应层的连接提供了从收缩路径到扩展路径的定位信息。

最终层 一个 1x1 卷积,将特征图映射到所需数量的类。

我在优信网上的实验

我将使用 Drishti-GS 数据集,这与 Ronneberger 等人在论文中使用的数据集不同。该数据集包含 101 个视网膜图像,以及光盘和视杯的注释掩模,用于检测青光眼,青光眼是世界上失明的主要原因之一。50 幅图像将用于训练,51 幅用于验证。

韵律学

我们需要一组指标来比较不同的模型,这里我们有二元交叉熵、Dice 系数和交集。

二元交叉熵 二元分类的常用度量和损失函数,用于衡量误分类的概率。

我们将使用 PyTorch 的 binary _ cross _ entropy _ with _ logits。与 Dice 系数一起用作训练模型的损失函数。

骰子系数

预测值和实际值之间重叠的常用度量标准。计算方法是 2 预测值和实际值之间的重叠面积()除以预测值和实际值组合的总面积(*)。**

该度量的范围在 0 和 1 之间,其中 1 表示完美和完全的重叠。

我将使用这个度量和二进制交叉熵作为训练模型的损失函数。

交集超过并集

一个简单(然而有效!)用于计算预测遮罩与地面真实遮罩的准确度的度量。计算预测值与实际值之间的重叠面积( )并除以并集面积( 预测值与实际值)的计算。

类似于 Dice 系数,该度量的范围从 0 到 1,其中 0 表示没有重叠,而 1 表示预测值和实际值之间完全重叠。

培训和结果

为了优化该模型以及随后的 U-Net 实现以进行比较,使用具有 1e-4 学习率的 Adam 优化器和每 10 个历元具有 0.1 衰减(伽马)的 Step LR 来训练超过 50 个历元。损失函数是二进制交叉熵和 Dice 系数的组合。

该模型在 11 分 33 秒内完成训练,每个历元用时约 14 秒。总共有 34,527,106 个可训练参数。

具有最佳性能的时段是时段# 36(50 个中的一个)。

  • 二元交叉熵:0.3319
  • 骰子系数:0.8367
  • 并集上的交集:0.8421

用几个看不见的样本测试模型,预测光盘(红色)和光学杯(黄色)。

从这些测试样本来看,结果相当不错。我选择了第一张图片,因为它的左上角有一个有趣的边缘,这里有一个错误的分类。第二个图像有点暗,但没有问题得到部分。

结论

U-Net 架构非常适合生物医学图像分割,尽管仅使用 50 幅图像进行训练,但仍取得了非常好的性能,并且具有非常合理的训练时间。

阅读周等人关于 UNet++的文章:

* [## 生物医学图像分割:UNet++

通过一系列嵌套、密集的跳过路径提高分段准确性

towardsdatascience.com](/biomedical-image-segmentation-unet-991d075a3a4b)

关注 U-Net:

[## 生物医学图像分割:注意力 U 网

通过在标准 U-Net 上附加注意门来提高模型的灵敏度和准确性

towardsdatascience.com](/biomedical-image-segmentation-attention-u-net-29b6f0827405)

嗨!,我是叮当。我喜欢构建机器学习项目/产品,我在向数据科学写关于它们的文章。在媒体上关注我或者在 LinkedIn 上联系我。

以下是优信网的 PyTorch 代码:*

生物医学图像分割:UNet++

原文:https://towardsdatascience.com/biomedical-image-segmentation-unet-991d075a3a4b?source=collection_archive---------9-----------------------

通过一系列嵌套、密集的跳过路径提高分段准确性

在这篇文章中,我们将探索由美国亚利桑那州立大学的周等人编写的用于医学图像分割的嵌套 U-Net 架构。这篇文章是 U-Net 文章的延续,我们将比较 UNet++和 Ronneberger 等人的原始 U-Net。

UNet++旨在通过在编码器和解码器之间包含密集块和卷积层来提高分割精度。

分割精度对于医学图像是至关重要的,因为边际分割误差会导致不可靠的结果;因此将被拒绝用于临床设置。

尽管数据样本较少,但为医学成像设计的算法必须实现高性能和高精度。获取这些样本图像来训练模型可能是一个消耗资源的过程,因为需要由专业人员审查的高质量的未压缩和精确注释的图像。

UNet++有什么新功能?

下面是 UNet++和 U-Net 架构的图解。

UNet++在原有的 U-Net 基础上增加了 3 项功能:

  1. 重新设计的跳过路径(显示为绿色)
  2. 密集跳跃连接(以蓝色显示)
  3. 深度监督(以红色显示)

重新设计的跳过路径

在 UNet++中,重新设计的跳过路径(显示为绿色)被添加进来,以弥合编码器和解码器子路径之间的语义鸿沟。

这些卷积层的目的是减少编码器和解码器子网的特征图之间的语义差距。因此,对于优化者来说,这可能是一个更直接的优化问题。

U-Net 中使用的 Skip 连接直接连接编码器和解码器之间的特征映射,从而融合语义不同的特征映射。

然而,使用 UNet++时,来自同一密集块的先前卷积层的输出与较低密集块的相应上采样输出融合。这使得编码特征的语义级别更接近在解码器中等待的特征映射的语义级别;因此,当接收到语义相似的特征图时,优化更容易。

skip 路径上的所有卷积层都使用大小为 3×3 的核。

密集跳跃连接

在 UNet++中,密集跳过连接(蓝色显示)在编码器和解码器之间实现了跳过路径。这些密集块受 DenseNet 的启发,目的是提高分割精度并改善梯度流。

密集跳跃连接确保所有先前的特征图被累积并到达当前节点,因为沿着每个跳跃路径的密集卷积块。这在多个语义级别生成全分辨率特征图。

深度监督

在 UNet++中,增加了深度监督(红色显示),这样就可以修剪模型来调整模型复杂度,平衡速度(推理时间)和性能

对于精确模式,所有分割分支的输出被平均。

对于快速模式,从一个分割分支中选择最终分割图。

周等人进行了实验以确定具有不同修剪水平的最佳分割性能。使用的度量标准是交集/并集推理时间

他们对四个分割任务进行了实验:a)细胞核,b)结肠息肉,c)肝脏,以及 d)肺结节。结果如下:

与 L4 相比,L3 的推理时间平均减少了 32.2%,同时略微降低了 Union 的交集。

L1 和 L2 等更激进的修剪方法可以进一步减少推理时间,但代价是显著的分割性能。

当使用 UNet++时,我们可以调整用例的层数。

我在 UNet++上的实验

我将使用 Drishti-GS 数据集,这与 Ronneberger 等人在论文中使用的数据集不同。该数据集包含 101 个视网膜图像,以及光盘和视杯的注释掩模,用于检测青光眼,青光眼是世界上失明的主要原因之一。50 幅图像将用于训练,51 幅用于验证。

韵律学

我们需要一组指标来比较不同的模型,这里我们有二元交叉熵、Dice 系数和交集。

二元交叉熵 二元分类常用的度量和损失函数,用于度量误分类的概率。

我们将使用 PyTorch 的 binary _ cross _ entropy _ with _ logits。与 Dice 系数一起用作训练模型的损失函数。

骰子系数

预测值和实际值之间重叠的常用度量标准。计算是 2 重叠面积(预测值和实际值之间)除以总面积(预测值和实际值的组合*)。

该度量的范围在 0 和 1 之间,其中 1 表示完美和完全的重叠。

我将使用这个度量和二进制交叉熵作为训练模型的损失函数。

并集上的交集

一个简单(然而有效!)用于计算预测遮罩与地面真实遮罩的准确度的度量。计算重叠面积( 在预测值和实际值之间)并除以并集面积( 预测值和实际值)的计算。

类似于 Dice 系数,该度量的范围从 0 到 1,其中 0 表示没有重叠,而 1 表示预测值和实际值之间完全重叠。

培训和结果

为了优化该模型,训练超过 50 个时期,使用具有 1e-4 学习率的 Adam 优化器,以及每 10 个时期具有 0.1 衰减(伽马)的 Step LR 。损失函数是二进制交叉熵和 Dice 系数的组合。

模型在 27 分钟内完成了 36.6M 可训练参数的训练;每个时期大约需要 32 秒。

具有最佳性能的纪元是纪元# 45(50 个中的一个)。

  • 二元交叉熵:0.2650
  • 骰子系数:0.8104
  • 并集上的交点:0.8580

用于比较的几个 U-Net 模型之间的度量,如下所示。

测试从模型处理一些看不见的样本开始,以预测光盘(红色)和光学杯(黄色)。以下是 UNet++和 U-Net 的测试结果,以供比较。

从指标表来看,UNet++在交集方面超过了 U-Net,但在骰子系数方面落后。从定性测试结果来看,UNet++已经成功地正确分割了第一幅图像,而 U-Net 做得并不太好。同样由于 UNet++的复杂性,训练时间是 U-Net 的两倍。人们必须根据它们的数据集来评估每种方法。

结论

UNet++旨在通过一系列嵌套的密集跳过路径来提高分割精度。

重新设计的跳过路径使得语义相似的特征图的优化更加容易。

密集跳跃连接提高了分割精度并改善了梯度流。

深度监督允许模型复杂性调整,以平衡速度和性能优化。

阅读另一个 U-Net:

[## 生物医学图像分割:U-Net

使用非常少的训练图像,并产生更精确的分割。

towardsdatascience.com](/biomedical-image-segmentation-u-net-a787741837fa) [## 生物医学图像分割:注意力 U 网

通过在标准 U-Net 上附加注意门来提高模型的灵敏度和准确性

towardsdatascience.com](/biomedical-image-segmentation-attention-u-net-29b6f0827405) [## 数据科学家:21 世纪最肮脏的工作

40%的吸尘器,40%的看门人,20%的算命师。

towardsdatascience.com](/data-scientist-the-dirtiest-job-of-the-21st-century-7f0c8215e845) [## 7 个必不可少的人工智能 YouTube 频道

如何跟上最新最酷的机器学习进展

towardsdatascience.com](/7-essential-ai-youtube-channels-d545ab401c4)

以下是 UNet++架构的 PyTorch 代码:

洛杉矶的鸟类数据探索[第一部分]

原文:https://towardsdatascience.com/bird-data-exploration-in-los-angeles-part-1-fe0292313083?source=collection_archive---------26-----------------------

这是我正在进行的一系列文章的第 1 部分,在这些文章中,我正在试验收集和建模 Bird scooter 数据。在这一部分中,我将介绍我的项目目标,并讨论一个地理区域的鸟类数据收集。请继续关注我在未来几周开发这个项目的其余部分。查看我的代码 这里

动机

作为洛杉矶或其周边城市的居民,很难错过微动力运动(电动滑板车、电动自行车等)的影响。)对景观的影响。作为这些产品的狂热用户,以及总体上微移动性的支持者,我长期以来一直对研究这些车辆的用户行为感兴趣。具体来说,我想研究这些车辆如何在特定地区行驶,并研究微型汽车公司如何最大限度地利用它们。

直到最近,我还以为是因为提供这些车辆的公司(伯德、莱姆、优步、Lyft 等。)没有公开的 API,我的研究将受到数据缺乏的限制。然而,我看到了 Conor McLaughlin 的一篇很棒的博客文章(链接此处),展示了如何获取和询问鸟类数据以获得洞察力。

介绍

背景:在我的简化模型中,公司员工(通常称为“充电者”)有两种类型的机会来干预/影响特定区域的滑板车分销。第一个是在一天开始的时候,踏板车的初始位置被设定。第二种是全天,当充电器拿起滑板车,给它们的电池充电,然后把它们放在某个地方供骑车人使用。

目标:我的模型将尝试回答以下问题:

  1. 全天最大化使用(从而最大化收入)的踏板车的最佳初始位置是什么?现实世界中看到的摆放是否可以改进?
  2. 我们能找到充电器重新分配踏板车位置的最佳“干预点”吗?

注意事项:从一开始,我的模型就有一些明显的限制:

  1. 我不了解伯德的成本模型,即派出充电器进行干预的成本。因此,我将不得不做出一些假设,以确定干预成为更有利可图的选择的“断点”。
  2. 我将离散时间和空间,并可能粗粒度收集数据,以产生可靠的结果。因此,我将无法准确地获取收入(波导的收入模式涉及骑行启动费,随后是每分钟使用费)。这意味着我将使用试探法和平均值来量化收入,这可能不会与每次乘坐获得的收入完全一致。
  3. 正如将在收集 Bird 数据一节中讨论的那样,我实际上可以获得的数据受到 Bird API 的限制。由于公司 Bird 可以访问更多自己的数据,我的模型不太可能超过 Bird 数据科学团队使用的优化器。也就是说,我对这个项目的个人目标是获得关于这个数据集的实践经验,并希望实现体面的模型性能。

程序概述

我的方法如下:

  1. 收集地理数据以建立一个感兴趣的区域:这将是我随着时间的推移监测鸟类分布的区域。
  2. 收集搜索区域的鸟类数据:我计划在足够长的时间内频繁地收集给定区域内所有鸟类的数据,以捕捉重要的趋势。
  3. 执行探索性数据分析并开始模型开发。
  4. 使用收集的数据来预测未来鸟类的位置。
  5. 通过使用未来鸟的位置预测来预测一天中鸟群的效用。
  6. 确定最佳干预点/初始位置,以最大化车队效用。

收集数据

尽管我希望我的模型适用于任意的地理区域,但我希望使用洛杉矶的社区进行初始测试和概念验证开发。因此,我需要做以下事情:

  1. 收集感兴趣区域的地理数据
  2. 收集这些地区的鸟类踏板车数据

收集地理数据

为了搜索一组邻域,我需要 GIS 数据来提供这些邻域边界的坐标。令人欣慰的是,洛杉矶县维护着一个强大的 GIS 数据门户(链接此处),它提供了一个包含洛杉矶县所有社区的 shapefile。

首先,我使用geopandas将洛杉矶县邻域 shapefile 的内容读入一个数据帧。

L.A. County GIS dataset type: <class 'geopandas.geodataframe.GeoDataFrame'>

正如我们所见,洛杉矶县 shapefile 以shapely多边形的形式提供了边界坐标,这对于可视化和地理空间分析非常理想。具体来说,我想关注洛杉矶西边的社区(靠近我的公寓),所以我过滤了数据帧,并将所有需要的社区合并到一个多边形列表中。

注意,对于每个邻域,在将它们展平到最终的search_areas列表之前,我强制所有的多边形变成多重多边形。这是为了解释一些实际上多多边形的邻域几何图形。例如,观察威尼斯的几何图形:

Venice geography type: <class 'shapely.geometry.multipolygon.MultiPolygon'>
Number of Venice constituent Polygons: 2

对于由不连续部分组成的邻域,洛杉矶县数据集将几何表示为多多边形。我的方法将这些邻域展平,并将所有的邻域/子区域存储在一个列表中。然后,我将邻近区域可视化,以确认 GIS 数据代表了我预期的区域。

gmaps visualization of L.A. neighborhoods.

在尝试了一系列不同的绘图/可视化方法后,我选定了gmaps,这是一个在 Jupyter 笔记本上显示谷歌地图的插件(https://github.com/pbugnion/gmaps))。它为添加图层/数据点提供了直观的命令,并为额外的上下文提供了开箱即用的关键地图细节显示。唯一的缺点是该工具不是免费的,需要一个谷歌云平台账号。提供的令牌是我自己的,所以请谨慎刷新请求。

收集河边数据

另外,我还想探索为我的家乡加州河滨收集地理数据。我从下载河岸城市限制数据开始(链接此处)。

正如我们所见,Riverside 提供的边界数据与洛杉矶不同:作为路径列表(shapelylinestring)。因此,我使用了polygonize_full的方法将片段合并在一起。

gmaps visualization of Riverside.

收集鸟类数据

接下来,我需要为我的搜索区域捕获鸟的位置数据。

据我所知,Bird 没有公开可用的 API。幸运的是,WoBike 资源库的贡献者(https://github.com/ubahnverleih/WoBike/blob/master/Bird.md)似乎已经找到了一种为 Bird 逆向开发 RESTful API 的方法。他们的方法似乎是通过假冒 iOS 用户登录来获得 API 认证。

使用这个 API,我做了以下工作:

  1. 通过模拟 iOS 登录获取身份验证令牌。
  2. 搜索特定区域(表示为坐标多边形)并获取单个踏板车的数据
'eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJBVVRIIiwidXNlcl9pZCI6IjlhNjVkYjRjLTU4NDctNDU1OS05ZDFmLWIzY2Y5Mjg1ODhmNyIsImRldmljZV9pZCI6IjI5M2ZlYzhjLWE2YTUtMTFlOS05YjViLWEwOTk5YjEwNTM1NSIsImV4cCI6MTU5NDY5MjM4OH0.09T6VCGDt-mWz6oYiGawzl0gJa-a4Fq2Y3qaOqVE8nA'

我们已经成功获得了一个 API 令牌!现在,我将测试查找附近鸟类的功能。

成功!我们有附近鸟类的名单。我们将使用gmaps做一些快速可视化,以确认鸟的位置是合理的。但是首先,我们将定义几个辅助函数。

gmaps visualization of Birds around test location.

看起来这些鸟大概在圣莫尼卡市中心,这一点得到了证实。正如将在下一节中讨论的,很难确定鸟儿离搜索点的确切距离(即搜索半径)。

收集地理区域的鸟类数据

我们现在将把它们放在一起。我们已经确定我们可以捕捉和可视化地理区域和鸟类的位置。使用这两个函数,我们将尝试为一个地理区域(而不是一个搜索点周围)收集鸟类的位置。

虽然 Bird 的“附近的踏板车”API 端点有一个半径参数,但我无法成功使用它。经过一些实验,我观察到无论我为搜索半径指定什么值,都会返回相同的一组鸟(除了将半径设置为 0,这会产生一个空结果)。也许其他用户发现指定半径更成功;然而,鉴于我无法使用它,我构建了一个方法来收集我感兴趣区域内所有鸟类的位置。

下面更详细地提到了所有的底层功能;然而,我将在这里给出我的方法的概述。给定一个搜索区域,我定位包含的鸟类如下:

  1. 我在搜索区域内的一个有代表性的点放下一个搜索点,收集附近的鸟。
  2. 收集的鸟被添加到集合中。由于每只鸟都有一个(纬度,经度)位置,所以可以在收集到的鸟周围形成一个凸多边形。我们称之为覆盖区域。
  3. 当被覆盖的区域仍然包含在搜索区域内时,我们继续搜索。
  4. 覆盖区域的顶点现在成为收集附近鸟类的一组新的搜索点。
  5. 如果在特定搜索点周围没有发现鸟在搜索区域内,该搜索点被认为是“死胡同”,其搜索结果被丢弃。
  6. 然而,如果在特定搜索点周围找到的任何鸟在搜索区域内,其搜索的全部结果都被添加到找到的鸟的集合中,新的覆盖区域(凸多边形)被计算,并且新的搜索点集合由新的覆盖区域的顶点形成。
  7. 为了确保多个搜索点不会恢复相同的鸟类,使用重复数据删除将搜索结果限制为仅新的(即,先前未发现的)鸟类。
  8. 这个过程一直持续到覆盖区域包含搜索区域或者所有搜索点都成为死胡同。

如果一个搜索区域由多个搜索区域组成(洛杉矶的例子就是这种情况),那么这个过程在每个组成搜索区域上独立运行,并且对结果进行重复数据删除以保持唯一性。

我们现在将把我们的搜索算法应用到之前可视化的洛杉矶社区。此算法肯定不是获取此数据的最有效方式,因此请等待几分钟来完成此搜索。

现在我们已经验证了我们的搜索算法定位了一些鸟,我们将可视化位置以及搜索区域(显示为红色)和我们的搜索算法覆盖的区域(蓝色)。请注意该算法如何从搜索区域的中间开始搜索,并在每次迭代中逐渐向外扩展。由于发现的鸟的数量,这种可视化可能需要一两分钟。

gmaps visualization of the Bird search algorithm searching over several L.A. neighborhoods. Note how the covered areas (blue) start from the center of the search areas (red) and expand outward with each iteration until all Birds (pink) are found.

这种可视化势不可挡,运行缓慢。我们可以使用gmaps热图功能提高可视化速度并简化视图。

好多了!正如我们所观察到的,鸟类的分布因我们观察的区域而异。这些观察还取决于一天中的时间(在本例中,是太平洋标准时间下午 6 点)和一周中的日期(星期日)。大体上,我们看到鸟类最密集地集中在威尼斯和圣莫尼卡的市中心/沿海地区,越是内陆的郊区人口越稀少。

我们现在将收集的数据保存到一个 csv 文件中,这样我们就可以在以后引用它,而不必运行我们的搜索算法。然而,首先我们将附加数据收集时间的时间戳,因为这对于评估我们搜索区域内的鸟类分布如何随时间变化至关重要。

后续步骤

在这一部分中,我能够构建一个可靠的算法来捕获数据(位置、电池电量等。)用于特定地理区域内的鸟类滑行车。从这里开始,我的下一步将是设置一个 cron 作业,在一天中以一定的间隔重复执行这个任务。一天的鸟类数据足以进行一些早期探索性数据分析和假设生成。从那里,这个过程将被扩展到捕获几周的数据,从而创建用于全面分析的数据集。

Bist-Parser:依赖解析器的端到端实现

原文:https://towardsdatascience.com/bist-parser-an-end-to-end-implementation-of-a-dependency-parser-5caf04a2cc12?source=collection_archive---------33-----------------------

本文是关于依赖解析的第二篇也是最后一篇文章。我们将为您提供一些简单的实施指南和工具来帮助您改进它。

词汇

  • 树库是注释句法或语义句子结构的解析文本语料库。依赖树库是使用不同的方法创建的:要么直接感谢人工注释器,要么使用自动解析器提供第一次解析,然后由注释器检查。一种常见的方法是使用确定性过程,通过 head 规则将现有的树库翻译成新的语言。建立一个高质量的树木库既费时又费钱。
  • CoNLL-U —计算自然语言学习-Universal 是 CoNLL-X 格式的修订版。来自树库的句子被分开,每个单词或标点符号被放置在不同的行上。以下每一项都跟在单词后面,用表格隔开:
    –ID:句子中的单词索引,从 1 开始
    –FORM:词形或标点符号
    –LEMMA:词形的引理或词干
    –UPOS:通用词性标签
    –XPOS:语言特定词性标签;将不会在我们的模型
    中使用–专长:形态特征的无序列表,由通用依赖关系定义;表示名词的性别和数量,动词的时态等。
    –HEAD:单词的头,表示与当前单词相关的单词的索引
    –DEPREL:通用依赖关系;表示两个词(动词的主语或宾语,名词的限定词等)之间的关系。)
    –DEPS:特定于语言的部分依赖;不会在我们的型号
    中使用–杂项:评论或其他注释

An example of CoNLL-U format

  • 条目是一个单词,或者一个句子中的标点符号。它有多个属性,如上所述。一个句子通常是条目的串联(单词本身是条目的属性:它的形式),由空格分隔。

实施

Bist 解析器的实现来自其论文的作者。Xiezhq Hermann 在 GitHub 上发布了一个更新。你可以在这里找到。它在 Python 3.x 上工作,使用 torch 0.3.1(有或没有 Cuda)。它非常完整,可以按原样使用。然而,为了使代码适应您的数据或对其进行升级,您必须完成每个模块,这可能是一项艰巨的任务。文章的这一部分将引导您浏览所有文件和流程。

通用依赖(UD)是一个语法注释的开放社区框架。它提供了极大地帮助开发依赖解析器的语料库和工具。

从 UD,你可以下载你选择的句子语料库(任何可用的语言,甚至古法语!),按原样使用它们,并开始用这种类型的命令训练您的 Bist 解析器:

python src/parser.py --outdir [results directory] --train training.conll --dev development.conll --epochs 30 --lstmdims 125 --lstmlayers 2 [--extrn extrn.vectors]

您可以在这里详细描述超参数,通过文件 parser.py 被模型捕获

你可能知道,当你在一个语料库上训练一个模型的时候,模型是偏向这个语料库的。你可以在多个语料库上训练你的模型,以使它更加一般化。有几种技术可以让你增加分数,以 TreeBank 嵌入为例。这里,我们只是连接了一些树库,没有任何进一步的处理。

实用工具

  • 创建一个 ConllEntry 类:每个条目都有众所周知的属性:id,form,lemma,Universal PoS tag,language Specific PoS tag,morphological features,head of current word,dependency relation,enhanced dependency relation,commentation。这些属性是根据通用依赖项 CoNLL-U 格式定义的。这种格式有助于模型理解它的输入是什么,以及它应该预测什么。
  • 读取一个 CoNLL-U 文件,并将每个句子转换成一个 ConllEntry。
  • Count 词汇表:这个函数创建一个 ConllEntry 属性的计数器,并允许您了解这些属性是如何分布在您的数据集中的。如果您想要确定数据集中最常用的单词或关系,此函数会很有用。

mstlstm

该文件包含您的模型。你所有的超参数和大部分的监测工作都发生在这个文件中。

方法 forward 遍历句子中的每个条目。它首先计算每个条目属性的向量。通过我们的模型,我们得到了描述单词、词性标签和专长的多个向量。然后将这些向量连接起来,为每个条目形成一个维度更大的向量。这些条目然后连接在一起形成句子向量。

首先,它将条目转换成向量。这里,主要属性是单词、词条(onto)和词性标签(PoS)的嵌入。但是,我们建议您尽可能添加更多功能。例如,你可以使用单词的特征来表示名词是单数还是复数,它的性别或者时态…嵌入这些特征可以让你的 BiLSTM 找到更多的模式。

Evolution of PoS embedding on two dimensions

然后,它向 BiLSTM 提供这些向量(for = forward,back = backward)。第 52 行评估句子的得分。这是创建完全加权有向图的部分。在第 57 行,它计算关系分数。这是这个模型中一个有趣的技巧:不是同时评估所有的可能性(|可能性| = |弧|。|labels|,这太高了),它首先预测依赖项,然后预测关系。关于错误错误错误我们以后再看。

在下面的插图中,您可以看到依赖项评估在批处理中的演变。深蓝色单元格对应一个加重的弧线。这个例子来自一个典型的法语句子,“在被认为是例行公事的情况下,体育运动中发生的骚乱。“你可以发现句子中的拼写错误;这在树银行中并不罕见。

Les commotions cérébrales sont devenu si courantes dans ce sport qu’on les considére presque comme la routine.

这句话中值得注意的是单词“ devenu ”,它是词根(即主词),以及由单词“ que ”和“ comme”分隔的三个明确定义的命题。

Evolution of dependency scores for the sentence “root Les commotions cerebrales sont devenu si courantes dans ce sport que on les considere presque comme la routine.”

Scores figure (1) — Initialization

Scores figure (2) — 200 sentences

Scores figure (3) — 1000 sentences

Score figure (4) — 6000 sentences

在上面的插图中,我们可以更好地理解我们的神经网络的进化。每一列对应一个作为头的标记,每一行对应一个作为从属的标记,每一个单元格对应从头到从属的弧的分数(或权重)。

我们认识到图 1 中的随机初始化,其中所有的分数都在零附近,我们在矩阵中看不到任何形状。
在第二张图中,我们可以看到 PoS =行列式向量已被考虑在内,我们可以在它们的列中辨认出一个形状。目前,行的变化不太明显。
在第三幅插图中,我们可以清楚地看到由“”分隔的两个命题弧线在它之前定义得很好,在它之后就不那么清晰了。标点符号与词根“ devenu 联系得很好。
在最后一个中,我们对主弧线有了清晰的认识,模型获得了信心,分数值也更加扩张。

一旦预测了依赖关系,模型就预测了关系类型。这里是每个关系的得分图,考虑到预测的关系,给出正确的依赖关系。

Relation score figure (1)— Initialization

Relation score figure (2) — 200 sentences

Relation score figure (3) — 1000 sentences

Relation score figure (4) — 6000 sentences

预测的关系类型用黄色表示,最不正确的关系类型用红色表示。

经过一些训练,预测变得越来越有信心。

该模式的主要方法是。它首先打乱句子,每次以不同的顺序训练模型。然后,为每个句子调用方法 前进 。这将更新权重,返回一个分数 e 并更新两个列表 errslerrs 。回想一下, e 对预测人头不同于金人头(参考,来自语料库)的每个令牌进行计数。 errs 计算弧预测损失,而 lerrs 计算标签预测损失。然后将误差和 lerrs 相加,产生反向传播损失:eers

改进和一些结果

为了建立一个更有效的模型,您应该尝试添加单词 dropout 作为一个超参数,并尝试不同的值。我们试过 0,0.25,0.33,0.5,0.9,1 作为数值,最好的是 0.9。它强制模型从其他向量中学习比单词更多的东西。

您还可以分离每个特征,并在每个特征上使用嵌入。这将允许更大的灵活性和对模型更多的理解。

通过这样的实现,我们在法国红杉(通用依存)树库上获得了 87.70 的 LAS 分数,而没有在这个语料库上进行专门的训练(在标签翻译之后,因为我们的标签与 UD 的不同)。

一旦训练好了依赖关系解析器,就可以使用依赖关系和关系来更好地理解数据。即使 NLU 模型能够找到许多模式,添加这些输入也是你应该考虑的真正收益。

本文的来源如下:

脸书先知的比特币预测价格建模

原文:https://towardsdatascience.com/bitcoin-predictive-price-modeling-with-facebooks-prophet-b66efd0169a0?source=collection_archive---------10-----------------------

Two Bitcoin price predictions (blue and red lines) generated using Facebook’s Prophet package. The actual price data is in green, while the shaded areas denote the respective uncertainty in the estimate. As you can the uncertainty increases into the future. This is particularly the case with the tighter fitting price model (red).

这是一个快速浏览脸书的先知机器学习包使用比特币的例子。它假设您具备基本的 Python 知识,并对熊猫有所了解。

Prophet 是脸书为时间序列数据开发的开源预测程序。这个想法是,它应该使完全自动的预测变得容易,即使有杂乱的数据,而且它目前在 R 和 Python 中可用。在这篇文章中,我将使用 Python 2.7。

注来自《走向数据科学》的编辑: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语

安装 Prophet

如果你已经安装了 pip,你需要做的就是打开一个控制台,输入

pip install fbprophet

在 Windows 上,我遇到了一些与 Anaconda 相关的依赖问题,不得不首先运行

conda clean --all
conda update pystan

下载和准备数据

一旦你安装好了,我们将导入我们需要的模块

import quandl as qd
import pandas as pd
import numpy as npimport fbprophet
import matplotlib.pyplot as plt

Quandl 是一个惊人的存储库,拥有大量极其不同的数据集。你需要注册一个免费账户并生成一个 API。那我们准备开始了。首先从 Quandl 下载比特币市场数据,去掉零值(由于某种原因,价格数据在初始行中包含零)

KEY = "YOUR_API_KEY"
qd.ApiConfig.api_key = KEYbitcoin = qd.get("BCHAIN/MKPRU")
bitcoin = bitcoin.loc[(bitcoin !=0).any(1)]

这将价格数据放入一个名为比特币的熊猫数据框架中。要检查前几行,请键入

bitcoin.head()

您应该得到一个名为“值”的列和一个日期时间索引

 Value
Date 
2010–08–17 0.076900
2010–08–18 0.074000
2010–08–19 0.068800
2010–08–20 0.066700
2010–08–21 0.066899

现在,我们想将记录的数据绘制在线性图表上(原因将在后面变得明显),所以用比特币为记录的价格值创建一个新列

bitcoin["log_y"] = np.log(bitcoin["Value"])

与先知一起工作

我们需要做的第一件事是做点家务。Prophet 要求我们将“日期”列的名称改为“ds ”,而我们的 y 列应该简单地称为“y”

bitcoin = bitcoin.rename(columns={"Date": "ds", "log_y" : "y"})

Prophet 所做的大部分工作都发生在幕后,但是有一些超参数允许我们轻松地微调我们的模型。我们将只调整change point _ prior _ scale参数。

转折点基本上是趋势突然改变方向的点,例如反转。Prophet 可以自动为您找到这些点,尽管您可以自己定义它们,尽管对于大型和特殊的数据集来说这是不切实际的。嘿,这就是机器的作用,对吧?change point _ prior _ scale参数基本上允许您选择您希望变点与数据匹配的紧密程度。

构建任何模型的目标是能够将其推广到其他数据/场景,并获得类似的结果。所以我们不希望我们的模型过多地跟随训练数据,这叫做过拟合。同样,拟合不足也会产生泛化能力差的模型。

因此,我们将使用这个超参数进行所有微调。该值越高,拟合越紧密,同样,该值越低,拟合越松散。在这个演示中,我选择的值(0.0015 和 0.015)之间相隔一个数量级。

priors = [0.0015, 0.015]
prophets, labels = [], []
for prior in priors:
    prophet = fbprophet.Prophet(changepoint_prior_scale=prior)
    prophet.fit(bitcoin)

    prophets.append(prophet)
    labels.append(r"CP Prior = " + str(prior))

此时,您应该有一个包含两个 prophet 对象的列表和一个用于绘制的标签列表。下一步是使用这些 prophet 对象来生成预测对象。(我们还将使用 changepoint_prior_scale 值前缀重命名“ds”列,以便跟踪数据。)

forecasts = []
for prophet in prophets:
    forecast = prophet.make_future_dataframe(periods=365 * 2,                                                    freq="D")
    forecast = prophet.predict(forecast)

    forecast = forecast.rename(columns={"ds" : str(priors[prophets.index(prophet)]) + "_ds"})
    forecasts.append(forecast)

差不多就是这样。如果一切顺利,您应该已经生成了两个预测对象的列表(实际上只是熊猫数据帧)。让我们将它们合并成一个数据帧,并将其中一个' _ds '列重命名为' Date ',删除另一个。

output = pd.merge(forecasts[0], forecasts[1], how = "inner", left_on = "0.0015_ds", right_on = "0.015_ds")
output = output.rename(columns={"0.0015_ds": "Date"}).drop("0.015_ds", axis=1)

最后,我们将索引设置为“日期”列

output = output.set_index(‘Date’)

我们现在将在一张图表上绘制所有内容

fig, ax = plt.subplots(1, 1, figsize=(10, 8))
ax.plot(output.index, output["yhat_x"], label=labels[0])
ax.fill_between(output.index, output["yhat_upper_x"], output["yhat_lower_x"], alpha=0.6, edgecolor = "k")ax.plot(output.index, output["yhat_y"], "r", label=labels[1]);
ax.fill_between(output.index, output["yhat_upper_y"], output["yhat_lower_y"], alpha=0.6, edgecolor = "k")
ax.plot(bitcoin.ds, bitcoin.y, color="green", linewidth=3, label=r"Bitcoin price (logged)")
a=ax.get_yticks().tolist()
ax.set_yticklabels(np.round(np.exp(a), 1))
plt.legend(loc="upper left")
plt.ylabel(r"Price /$")
plt.show()

“y_hat”标签是 Prophet 提供的估计值,x 或 y 后缀表示数据最初来自哪个数据框架(这里 x 是 0.0015 参数值,y 是 0.015)。

结论

这里的目标只是简单地摆弄一下 Prophet 包,我认为比特币会成为一个有趣的数据集。

仅仅通过目测,我认为从比特币最大化的角度来看,这两个预测都非常合理,我的意思是它们符合许多看涨投资者认为价格会发生的情况。

蓝色拟合可能有点不合适,但你可以看到,随着时间的推移,估计的不确定性保持相当稳定,甚至到未来。一般来说,它提供了更多的概括空间,但对趋势变化的反应可能太慢。因此我认为这是不可靠的。我不认为价格会长期保持这种趋势。

另一方面,红色拟合似乎过度拟合了数据。它紧紧跟随历史价格波动,并对趋势变化做出快速反应,然而不确定性真的会在未来爆发,使得这个预测也不可靠,尽管红色趋势更可信一些。

就我个人而言,我并不觉得这种价格预测特别有用,但关注这一点并观察脸书算法的结果会很有趣。

一口大小的蟒蛇食谱

原文:https://towardsdatascience.com/bite-sized-python-recipes-52cde45f1489?source=collection_archive---------12-----------------------

Python 中有用的小函数的集合

Photo by Jordane Mathieu on Unsplash

免责声明:这是我在网上找到的一些有用的小函数的集合,主要在 Stack Overflow 或者 Python 的文档页面上。有些人可能会看,但无论如何,我都在我的项目中使用过它们,我认为它们值得分享。你可以在我试图保持更新的笔记本中找到所有这些,以及一些额外的评论。

除非必要,我不打算过度解释这些功能。那么,让我们开始吧!

从两个列表中创建字典:

>>> prod_id = [1, 2, 3]
>>> prod_name = ['foo', 'bar', 'baz']
>>> prod_dict = dict(zip(prod_id, prod_name))>>> prod_dict
{1: 'foo', 2: 'bar', 3: 'baz'}

从列表中删除重复项并保留顺序:

>>> from collections import OrderedDict>>> nums = [1, 2, 4, 3, 0, 4, 1, 2, 5]
>>> list(OrderedDict.fromkeys(nums))
[1, 2, 4, 3, 0, 5]*# As of Python 3.6 (for the CPython implementation) and
# as of 3.7 (across all implementations) dictionaries remember
# the order of items inserted. So, a better one is:*
>>> list(dict.fromkeys(nums))
[1, 2, 4, 3, 0, 5]

创建多级嵌套字典:

创建一个字典作为字典中的值。本质上,它是一本多层次的字典。

from collections import defaultdict**def** multi_level_dict():
    *""" Constructor for creating multi-level nested dictionary. """* **return** defaultdict(multi_level_dict)

例 1:

>>> d = multi_level_dict()
>>> d['a']['a']['y'] = 2
>>> d['b']['c']['a'] = 5
>>> d['x']['a'] = 6>>> d
{**'a'**: {**'a'**: {**'y'**: 2}}, **'b'**: {**'c'**: {**'a'**: 5}}, **'x'**: {**'a'**: 6}}

例二:

给出了一个产品列表,其中每个产品需要从其原产地运送到其配送中心(DC),然后到达其目的地。给定这个列表,为通过每个 DC 装运的产品列表创建一个字典,这些产品来自每个始发地,去往每个目的地。

**import** random
random.seed(20)# Just creating arbitrary attributes for each Product instance
**class** Product:
    **def** __init__(self, id):
        self.id = id
        self.materials = random.sample(**'ABCD'**, 3)self.origin = random.choice((**'o1'**, **'o2'**))
        self.destination = random.choice((**'d1'**, **'d2'**, **'d3'**))
        self.dc = random.choice((**'dc1'**, **'dc2'**))

    **def** __repr__(self):
        **return f'P{**str(self.id)**}'**products = [Product(i) **for** i **in** range(20)]# create the multi-level dictionary
**def** get_dc_origin_destination_products_dict(products):
    dc_od_products_dict = multi_level_dict()
    **for** p **in** products:
        dc_od_products_dict[p.dc][p.origin].setdefault(p.destination, []).append(p)
    **return** dc_od_products_dictdc_od_orders_dict = get_dc_origin_destination_products_dict(products)
>>> dc_od_orders_dict
{**'dc1'**: {**'o2'**: {**'d3'**: [P0, P15],
                **'d1'**: [P2, P9, P14, P18],
                **'d2'**: [P3, P13]},
         **'o1'**: {**'d1'**: [P1, P16],
                **'d3'**: [P4, P6, P7, P11],
                **'d2'**: [P17, P19]}},
 **'dc2'**: {**'o1'**: {**'d1'**: [P5, P12], 
                **'d3'**: [P10]},
         **'o2'**: {**'d1'**: [P8]}}}

请注意,当您运行以上两个示例时,您应该在输出中看到defaultdict(<function __main__.multi_level_dict()>...)。但是为了结果的易读性,这里删除了它们。

返回嵌套字典最内层的键和值:

**from** collections **import** abc

**def** nested_dict_iter(nested):
    *""" Return a generator of the keys and values from the innermost layer of a nested dict. """* **for** key, value **in** nested.items():
        *# Check if value is a dictionary* **if** isinstance(value, abc.Mapping):
            **yield from** nested_dict_iter(value)
        **else**:
            **yield** key, value

关于此功能,有几点需要说明:

  • nested_dict_iter函数返回一个生成器
  • 在每个循环中,字典值被递归地检查,直到到达最后一层。
  • 在条件检查中,为了通用性,使用了[collections.abc.Mapping](https://docs.python.org/3/library/collections.abc.html#collections.abc.Mapping)而不是dict。这样就可以检查容器对象,比如dictcollections.defaultdictcollections.OrderedDictcollections.Counter
  • 为什么是yield from?简短而不完整的回答:它是为需要从生成器内部调用生成器的情况而设计的。我知道一个简短的解释不能做到任何公正,所以检查这个 so 线程以了解更多信息。

例 1:

>>> d = {'a':{'a':{'y':2}},'b':{'c':{'a':5}},'x':{'a':6}}
>>> list(nested_dict_iter(d))
[('y', 2), ('a', 5), ('a', 6)]

示例 2: 让我们从上面的dc_od_orders_dict中检索键和值。

>>> list(nested_dict_iter(dc_od_orders_dict))
[('d3', [P0, P15]),
 ('d1', [P2, P9, P14, P18]),
 ('d2', [P3, P13]),
 ('d1', [P1, P16]),
 ('d3', [P4, P6, P7, P11]),
 ('d2', [P17, P19]),
 ('d1', [P5, P12]),
 ('d3', [P10]),
 ('d1', [P8])]

多个集合的交集:

def get_common_attr(attr, *args):
    """ intersection requires 'set' objects """ return set.intersection(*[set(getattr(a, attr)) for a in args])

例:找出前 5 个products中的共同组成材料(如果有的话)。

>>> get_common_attr(**'materials'**, *products[:5])
{'B'}

第一场比赛:

从符合条件的 iterable 中查找第一个元素(如果有的话)。

first_match = next(i **for** i **in** iterable **if** check_condition(i))# Example:
>>> nums = [1, 2, 4, 0, 5]
>>> next(i for i in nums if i > 3)
4

如果没有找到匹配,上面的实现抛出一个StopIteration异常。我们可以通过返回一个默认值来解决这个问题。既然来了,就让它成为一个函数吧:

**def** first_match(iterable, check_condition, default_value=**None**):
    **return** next((i **for** i **in** iterable **if** check_condition(i)), default_value)

例如:

>>> nums = [1, 2, 4, 0, 5]
>>> first_match(nums, lambda x: x > 3)
4
>>> first_match(nums, lambda x: x > 9) # returns nothing
>>> first_match(nums, lambda x: x > 9, 'no_match')
'no_match'

动力组:

集合 S 的幂集是 S 的所有子集的集合。

import itertools as it**def** powerset(iterable):s = list(iterable)
    **return** it.chain.from_iterable(it.combinations(s, r)
                                  **for** r **in** range(len(s) + 1))

例如:

>>> list(powerset([1,2,3]))
[(), (1,), (2,), (3,), (1, 2), (1, 3), (2, 3), (1, 2, 3)]

定时器装饰器:

显示每个类/方法/函数的运行时。

**from** time **import** time
**from** functools **import** wraps

**def** timeit(func):
    *"""* **:param** *func: Decorated function* **:return***: Execution time for the decorated function
    """* @wraps(func)
    **def** wrapper(*args, **kwargs):
        start = time()
        result = func(*args, **kwargs)
        end = time()
        print(**f'{**func.__name__**} executed in {**end - start**:.4f} seconds'**)**return** result

    **return** wrapper

例如:

**import** random# An arbitrary function
@timeit
**def** sort_rnd_num():
    numbers = [random.randint(100, 200) **for** _ **in** range(100000)]
    numbers.sort()
    **return** numbers>>> numbers = sort_rnd_num()
sort_rnd_num executed in 0.1880 seconds

计算文件中的总行数:

**def** file_len(file_name, encoding=**'utf8'**):
    **with** open(file_name, encoding=encoding) **as** f:
        i = -1
        **for** i, line **in** enumerate(f):
            **pass
    return** i + 1

举例:你当前目录的 python 文件有多少行代码?

>>> from pathlib import Path>>> p = Path()
>>> path = p.resolve()  # similar to os.path.abspath()
>>> print(sum(file_len(f) for f in path.glob('*.py')))
745

只是为了好玩!创建长标签:

>>> s = "#this is how I create very long hashtags"
>>> "".join(s.title().split())
'#ThisIsHowICreateVeryLongHashtags'

以下不是一口大小的食谱,但不要被这些错误咬到!

注意不要混淆可变和不可变对象!
示例:用空列表作为值初始化字典

>>> nums = [1, 2, 3, 4]
# Create a dictionary with keys from the list. 
# Let's implement the dictionary in two ways
>>> d1 = {n: [] for n in nums}
>>> d2 = dict.fromkeys(nums, [])
# d1 and d2 may look similar. But list is mutable.
>>> d1[1].append(5)
>>> d2[1].append(5)
# Let's see if d1 and d2 are similar
>>> print(f'd1 = {d1} \nd2 = {d2}')
d1 = {1: [5], 2: [], 3: [], 4: []} 
d2 = {1: [5], 2: [5], 3: [5], 4: [5]}

不要在遍历列表时修改它!

示例:从列表中删除所有小于 5 的数字。

错误实现:迭代时移除元素!

nums = [1, 2, 3, 5, 6, 7, 0, 1]
for ind, n in enumerate(nums):
    if n < 5:
        del(nums[ind])# expected: nums = [5, 6, 7]
>>> nums
[2, 5, 6, 7, 1]

正确实施:

使用列表理解创建一个新列表,只包含您想要的元素:

>>> id(nums)  # before modification 
2090656472968
>>> nums = [n for n in nums if n >= 5]
>>> nums
[5, 6, 7]
>>> id(nums)  # after modification
2090656444296

你可以在上面看到,[id](https://docs.python.org/3/library/functions.html#id)(nums)在前面和后面被检查,以表明实际上这两个列表是不同的。因此,如果在其他地方使用该列表,并且改变现有列表很重要,而不是创建一个同名的新列表,则将它分配给切片:

>>> nums = [1, 2, 3, 5, 6, 7, 0, 1]
>>> id(nums)  # before modification 
2090656472008
>>> nums[:] = [n for n in nums if n >= 5]
>>> id(nums)  # after modification
2090656472008

目前就这样了(查看第二个小型博客这里)。如果你也有一些经常使用的小函数,请告诉我。我会尽量让的笔记本在 GitHub 上保持最新,你的也可以在那里结束!

我可以在 Twitter LinkedIn上联系到。

一口大小的蟒蛇食谱——第 2 卷

原文:https://towardsdatascience.com/bite-sized-python-recipes-vol-2-385d00d17388?source=collection_archive---------32-----------------------

Python 中有用的小函数的集合

Photo by Jordane Mathieu on Unsplash

免责声明:这是我在网络上找到的一些有用的小函数的集合,主要在堆栈溢出或 Python 的文档页面上。有些可能看起来微不足道,但无论如何,我都在我的项目中使用过它们,我认为它们值得分享。你可以在我试图保持更新的笔记本中找到它们(以及一些额外的评论)。如果你感兴趣,你可以在这里查看我的第一篇关于小型函数的博客!

除非必要,我不打算过度解释这些功能。那么,让我们开始吧!

返回可迭代的前 N

**import** itertools **as** it**def** first_n(iterable, n):
    *""" If n > len(iterable) then all the elements are returned. """***return** list(it.islice(iterable, n))

示例:

>>> d1 = {3: 4, 6: 2, 0: 9, 9: 0, 1: 4}
>>> first_n(d1.items(), 3)
[(3, 4), (6, 2), (0, 9)]
>>> first_n(d1, 10)
[3, 6, 0, 9, 1]

检查一个可迭代的所有元素是否都相同

**import** itertools **as** it**def** all_equal(iterable):
    *""" Returns True if all the elements of iterable are equal to each other. """*g = it.groupby(iterable)
    **return** next(g, **True**) **and not** next(g, **False**)

例如:

>>> all_equal([1, 2, 3])
False
>>> all_equal(((1, 0), (True, 0)))
True
>>> all_equal([{1, 2}, {2, 1}])
True
>>> all_equal([{1:0, 3:4}, {True:False, 3:4}])
True

当您有一个序列时,下面的替代方法通常会更快。(如果您正在处理非常大的序列,请确保自己进行测试。)

**import** itertools **as** it**def** all_equal_seq(sequence):
    *""" Only works on sequences. Returns True if the sequence is empty or all the elements are equal to each other. """***return not** sequence **or** sequence.count(sequence[0]) == len(sequence)

例如:你有一份卡车清单,可以查看它们是在仓库里还是在路上。随着时间的推移,每辆卡车的状态都会发生变化。

**import** random
random.seed(500)*# Just creating an arbitrary class and attributes* **class** Truck:
    **def** __init__(self, id):
        self.id = id
        self.status = random.choice((**'loading-unloading'**, **'en route'**))**def** __repr__(self):
        **return f'P{**str(self.id)**}'** trucks = [Truck(i) **for** i **in** range(50)]

早上你查看了一下,发现第一辆卡车是en route。你听说另外三个人也离开了仓库。让我们验证一下:

>>> all_equal_seq([t.status **for** t **in** trucks[:4]])
True

**None**求和

当你有numpy阵列或者pandas系列或者数据帧时,选择是显而易见的:[numpy.nansum](https://docs.scipy.org/doc/numpy/reference/generated/numpy.nansum.html)或者[pandas.DataFrame/Series.sum](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.sum.html)。但是如果你不想或者不能使用这些呢?

**def** sum_with_none(iterable):**assert not** any(isinstance(v, str) **for** v **in** iterable), **'string is not allowed!'** **return** sum(filter(**None**, iterable))

这是因为[filter](https://docs.python.org/3/library/functions.html#filter)None视为身份函数;即删除 iterable 的所有 falsy 元素。

例如:

>>> seq1 = [None, 1, 2, 3, 4, 0, True, False, None]
>>> sum(seq1)
**TypeError**: unsupported operand type(s) for +: 'int' and 'NoneType'>>> sum_with_none(seq1)  # Remember True == 1
11

检查 N 或更少的项目是否真实

**def** max_n_true(iterable, n):
    *""" Returns True if at most `n` values are truthy. """***return** sum(map(bool, iterable)) <= n

例如:

>>> seq1 = [None, 1, 2, 3, 4, 0, True, False, None]
>>> seq2 = [None, 1, 2, 3, 4, 0, True, False, 'hi']
>>> max_n_true(seq1, 5)
True
>>> max_n_true(seq2, 5)  # It's now 6
False

检查 Iterable 中是否只有一个元素为真

**def** single_true(iterable):
    *""" Returns True if only one element of iterable is truthy. """*i = iter(iterable)
    **return** any(i) **and not** any(i)

函数的第一部分确保迭代器有任何真值值。然后,它从迭代器中的这一点开始检查,以确保没有其他真值。

示例:使用上面的几个函数!

*# Just creating an arbitrary class and attributes* **class** SampleGenerator:
    **def** __init__(self, id, method1=**None**, method2=**None**, method3=**None**,
                 condition1=**False**, condition2=**False**,
                 condition3=**False**):
        *"""
        Assumptions:
        1) One and only one method can be active at a time.
        2) Conditions are not necessary, but if passed, maximum one can have value.
        """

        # assumption 1* **assert** single_true([method1, method2, method3]), **"Exactly one method should be used"** *# assumption 2* **assert** max_n_true([condition1, condition2, condition3], 1), **"Maximum one condition can be active"**self.id = id

下面的第一个样本(sample1)是有效的,但是其他样本违反了至少一个假设,导致了一个AssertionError(为了避免混乱,我没有在这里显示任何一个。)在笔记本上运行它们,亲自查看错误。

>>> sample1 = SampleGenerator(1, method1=**'active'**)  *# Correct* >>> sample2 = SampleGenerator(2, condition2=**True**)  *# no method is active* >>> sample3 = SampleGenerator(3, method2=**'active'**, method3=**'not-active'**)  *# more than one method has truthy value* >>> sample4 = SampleGenerator(4, method3=**'do something'**, condition1=**True**, condition3=**True**)  *# multiple conditions are active* >>> sample5 = SampleGenerator(5)  *# nothing is passed*

写入 CSV 时跳过冗余标题

假设你需要运行一系列的模拟。在每次运行结束时(可能需要几个小时),您记录一些基本的统计数据,并希望创建或更新一个用于跟踪结果的restults.csv文件。如果是这样,您可能希望在第一次之后跳过将头写入文件。

首先,让我们创建一些数据来使用:

**import** pandas **as** pd
**import** random*# An arbitrary function* **def** gen_random_data():
    demands = [random.randint(100, 900) **for** _ **in** range(5)]
    costs = [random.randint(100, 500) **for** _ **in** range(5)]
    inventories = [random.randint(100, 1200) **for** _ **in** range(5)]
    data = {**'demand'**: demands, 
            **'cost'**: costs, 
            **'inventory'**: inventories} **return** pd.DataFrame(data)*# Let's create a few df* df_list = [gen_random_data() **for** _ **in** range(3)]

现在,让我们假设我们需要在df_list数据帧一创建好就把它们写入orders.csv

**import** osfilename = **'orders.csv'
for** df **in** df_list:
    df.to_csv(filename, index=**False**, mode=**'a'**, 
              header=(**not** os.path.exists(filename)))

如果您不需要一次循环一个相似的数据帧,下面的替代方法是将它们写入文件的简洁方法:

pd.concat(df_list).to_csv(‘orders2.csv’, index=False)

将 CSV 文件转换为 Python 对象

假设您需要创建 Python 对象的集合,其中它们的属性来自 CSV 文件的列,并且文件的每一行都成为该类的一个新实例。然而,假设您事先不知道 CSV 列是什么,因此您不能用期望的属性初始化该类。

下面,您可以看到实现这一点的两种方法:

**class** MyClass1(object):
    **def** __init__(self, *args, **kwargs):
        **for** arg **in** args:
            setattr(self, arg, arg) **for** k, v **in** kwargs.items():
            setattr(self, k, v) **class** MyClass2:
    **def** __init__(self, **kwargs):
        self.__dict__.update(kwargs)

MyClass1中,我们可以同时传递argskwargs,而在MyClass2中,我们利用了特殊的[__dict__](https://stackoverflow.com/a/19907498)属性。

示例:让我们使用这两种实现将上面示例中的orders.csv文件转换成对象。

**import** csvfilename = **'orders.csv'** class1_list = []
class2_list = []**with** open(filename) **as** f:
    reader = csv.DictReader(f)**for** row **in** reader:class1_list.append(MyClass1(**row))
        class2_list.append(MyClass2(**row))# Let's check the attributes of the first row of class1_list
>>> print(f'first row = {vars(class1_list[0])}')
first row = {'demand': '821', 'cost': '385', 'inventory': '1197'}

暂时就这样了。如果你也有一些经常使用的小函数,请告诉我。我会尽量在 GitHub 上保持笔记本的最新状态,你的笔记本也可以放在那里!

我可以在 Twitter LinkedIn上联系到。

Ruby 中的按位排序

原文:https://towardsdatascience.com/bitwise-sorting-in-ruby-47f27bbd9ebf?source=collection_archive---------12-----------------------

想象一下,你运营着一个 NBA 篮球招募网站。您希望根据以下三个属性对全国所有大学篮球运动员进行排名:

  1. 玩家的个人评分(1-10)
  2. 玩家的团队等级(1-10)
  3. 玩家的会议等级(1-10)
  4. 玩家的 ID(任意数字)

几个玩家的例子,排名是这样的:

Player 1: rating 10, team rating 10, conference rating 10
Player 2: rating 10, team rating 10, conference rating 5
Player 3: rating 10, team rating 5,  conference rating 10
Player 4: rating 10, team rating 5,  conference rating 5
Player 5: rating 5,  team rating 10, conference rating 10
Player 6: rating 5,  team rating 10, conference rating 5

如果你采用天真的方法,对所有球队的所有球员进行排序可能是一个昂贵的计算。举例来说,让我们假设有 1,000,000 个玩家需要评估。使用嵌套排序,我们可以构建如下内容:

Player = Struct.new(:id, :rating, :team_rating, :conf_rating)# setupid = 1.step
[@players](http://twitter.com/players) = 1_000_000.times.map do 
  Player.new(id.next, rand(0..10), rand(0..10), rand(0..10))
end# I want to sort by player rating descending,
# then team rating descending,
# then conference rating descending,
# then by id descending.def sort_naively
  [@players](http://twitter.com/players).group_by(&:rating).sort.reverse.map do |rb|
    rb[1].group_by(&:team_rating).sort.reverse.map do |tb|
      tb[1].group_by(&:conf_rating).sort.reverse.map do |cb|
        cb[1].group_by(&:id).sort.reverse.map do |ib|
          ib[1]
        end
      end.flatten
    end.flatten
  end.flatten
end

平均来说,使用这种方法对 1,000,000 条记录进行排序需要大约 2000 毫秒。考虑到记录集的大小,这还不错。然而,深度嵌套的数组结构使用了大量的内存,大约 219MB。这是 Ruby 应用程序中的一个常见问题,但是因为我们有一个 GC,所以我们通常是安全的。总而言之,对于较小的数据集来说,这是一个可用的算法,但我认为我们可以对它进行改进。

我们可以使用Array.sort_by进行排序,它看起来更漂亮,并传入一个值数组进行排序:

@players.sort_by do |p| 
  [p.rating, p.team_rating, p.conf_rating, p.id]
end.reverse

…但这更慢。在我的测试中,平均需要 10 秒钟。然而,它使用了 80MB 的内存,所以这是一个小的改进。在低内存环境中,这可能会派上用场,但让我们探索另一种排序方法,一种通过利用巧妙的位运算来节省时间和内存的方法。

如果你不熟悉按位运算,它们在 C 等低级语言中被广泛用于对位进行运算。在 Ruby 中,主要的按位运算符有:

&  -> AND
|   -> OR
^   -> XOR
~   -> NOT
<<  -> LEFT SHIFT
>>  -> RIGHT SHIFT

关于这些功能的详细解释可以在这里找到,这超出了本文的范围。对于这篇文章,我们只需要一个关于| (OR)<< (LEFT SHIFT)的解释者

如果你已经了解了这么多,你可能对计算机的工作原理有了很好的了解,这些位就是 1 和 0。按位运算符对这些位进行运算。

Bitwise | (OR)基本上接受两个参数,第一个和第二个位,并返回一个新位,其中第一个位的值为 1,第二个位的值为 1,在缺少 1 的地方添加 1。例如:

integer  |  bit  | operator | other bit  |  new bit |  result
      0  | 0000  |    |     |      0001  |    0001  |       1
      1  | 0001  |    |     |      0001  |    0000  |       1
      2  | 0010  |    |     |      0001  |    0011  |       3
      3  | 0011  |    |     |      0001  |    0011  |       3
      4  | 0100  |    |     |      0001  |    0101  |       5
      5  | 0101  |    |     |      0010  |    0111  |       7
     10  | 1010  |    |     |      0101  |    1111  |      15

另一方面,按位<< (LEFT SHIFT)将位左移一定数量的位置,在该位的末尾添加 0。例如:

integer  |   bit  |  operator  |  number  |  result  | integer
      1  |     1  |     <<     |     1    |      10  |       2
      2  |    10  |     <<     |     1    |     100  |       4
      3  |    11  |     <<     |     1    |     110  |       6
     10  |  1010  |     <<     |     2    |  101000  |      40

我们可以利用这两个操作来使我们的排序算法变得更加智能。由于排序优先顺序总是rating > team_rating > conf_rating > id,因此,无论其他等级是什么,等级为 10 的玩家将总是排在等级为 9 的玩家之上,以此类推。在评级相同的玩家之间,具有较好团队评级的玩家将被整体评级更高,等等。

为了使用按位操作符实现这种排序,我们应该在 Player 结构中添加一个新参数bit_rank。新代码如下所示:

Player = Struct.new(
  :id, 
  :rating, 
  :team_rating, 
  :conf_rating, 
  :bit_rank  # <- new attribute
)# setupid = 1.step
[@players](http://twitter.com/players) = 1_000_000.times.map do 
  Player.new(id.next, rand(0..2), rand(0..2), rand(0..2))
end#now, calculate the bit rank for each player
@players.each do |p| 
  p.bit_rank = p.rating << 30 |
    p.team_rating << 25 |
    p.conf_rating << 20 |
    p.id
end

简而言之,这个新的bit_rank属性是一个数字(一个很大的数字),代表玩家的整体等级。我们在 30 个位置上移动评级,团队评级 25 个位置,会议评级 20 个位置,然后对所有三个位置加上 ID 运行按位OR。例如,一个 ID 为 1 并且在所有三个类别中都被评为 10 的玩家将拥有11_083_448_321bit_rank。当查看该值的位表示时,这是很直观的,它是:

0101001010010100000000000000000000101010 01010 01010 0000000000000000000001
^     ^     ^     ^
|     |     |     |__player ID = 1
|     |     |
|     |     |__player conference rating (10 = 01010)
|     |
|     |__player team rating (10 = 01010)
|
|__player rating (10 = 01010)

同一个全是 5 的玩家会有一个5_541_724_161bit_rank,当在 bit 镜头中看到时:

0010100101001010000000000000000000100101 00101 00101 00000000000000000001
^     ^     ^     ^                   
|     |     |     |__player ID = 1
|     |     |
|     |     |__player conference rating (5 = 00101)
|     |
|     |__player team rating (5 = 00101)
| 
|__player rating (5 = 00101)

…有道理。

bit_rank将排序优先级嵌入到自身中,其中玩家各自的评级被转移到位等级的适当区域,并且它们都被向左移动足够远,以在最后仍然按 ID 排序。

现在我们已经了解了bit_rank正在做什么,让我们看看运行这样一个复杂的操作需要什么代码:

@players.sort_by(&:bit_rank)

对,就是这样。因为bit_rank是 Struct 的一个属性,所以可以使用旧的Symbol.to_proc ruby magic 来调用它。如果我们在 Rails 领域,这可能是模型的一个属性,使得排序和排名非常容易。

但是,当您查看时间和内存使用情况时,使用这种方法确实很出色。

平均而言,将该属性添加到百万个玩家对象中的每一个会使设置阶段增加 200 毫秒,但是基于该属性的排序会将排序时间减少到 500 毫秒。总之,以前的800ms build + 2000ms sort = 2800ms操作现在变成了1000ms build + 500ms sort = 1500ms!我们将排序时间减少了 1300 毫秒,提高了 46%!我们添加的排序属性越多,效率也会成倍提高。

然而,内存的使用是难以置信的。为了刷新,最初的简单排序使用了 219MB 的内存,主要是因为它要排序到10 + (10*10) + (10*10*10) + (10*10*10*10) = 11,110个独立的、已排序的数组中。当使用bit_rank排序方法时,我们的操作只使用了 16MB,也就是少了 203MB,减少了 92%,因为我们没有任何嵌套数组。实际上,所有的内存占用都来自于构建 1,000,000 个玩家的数组。

使用这种方法非常适合大型数据集上的简单排序,提供了一种简单的方法来对多个值进行排序,并且在内存不足的环境中非常有用。

探索位操作符背后的想法来自参与代码的问世,我强烈推荐参与其中。如果你还没有完成挑战,你也可以完成。

希望你喜欢这篇文章。你可以在推特github 上找到我。

黑箱模型实际上比逻辑回归更容易解释

原文:https://towardsdatascience.com/black-box-models-are-actually-more-explainable-than-a-logistic-regression-f263c22795d?source=collection_archive---------3-----------------------

SHAP 价值观是不可理解的。但是,从它们开始,可以用对概率的影响来表达模型选择(这是一个人类更容易理解的概念)

可解释的和强大的之间永恒的斗争

从事数据科学家工作的人更清楚这一点:围绕机器学习的一个主要陈词滥调是,你必须在以下两者之间做出选择:

  • 简单、可靠和可解释的算法,如逻辑回归;
  • 强大的算法可以达到更高的精度,但代价是失去任何可懂度,如梯度增强或支持向量机。这些模型通常被称为“黑箱”,意味着你知道什么进入什么出来,但没有办法了解在引擎盖下实际发生了什么。

在下文中,我们将表明,不仅不需要在能力和可解释性之间做出选择,而且更强大的模型甚至比更肤浅的模型更具可解释性。

数据

举例来说,我们将使用最著名的数据集之一:标志性的泰坦尼克号数据集。我们有一堆关于泰坦尼克号乘客的变量,我们想预测每个乘客生还的可能性有多大。

我们可以处理的变量有:

  • Pclass:票类;
  • 性:乘客性;
  • 年龄:乘客年龄;
  • SibSp:泰坦尼克号上兄弟姐妹/配偶的数量;
  • Parch:泰坦尼克号上父母/孩子的数量;
  • 票价:客运票价;
  • 装船:装船港。

(注:为了简单起见,去掉了一些其他变量,几乎没有进行任何数据预处理)。

数据看起来是这样的:

Data, first 5 passengers

好的老罗格

对于分类问题,逻辑回归常被用作基线。

在对定性特征(机票等级、乘客性别和装货港)进行一次性编码后,我们对训练数据进行简单的逻辑回归拟合。在验证集上计算的准确度总计为 81.56%

从这个模型中我们能得到什么启示?因为逻辑回归是这样建立的

分析围绕着 β 进行。很容易看出,在 xⱼ 每增加 1 个单位,几率就会增加exp(βⱼ倍。

解释很简单:年龄增加一岁将导致几率增加 0.961 倍。

那就是:

  • 盖伊 A,25 哟:生存几率= 3
  • 除了年龄(26 岁)之外,其他变量都与 A 相同:生存几率= 3× 0.961 = 2.883

这个模型在可解释性方面的局限性是不言而喻的:

  • exp(βⱼ) 和赔率之间的关系是线性的,例如,2 或 12 yo 之间的差异与 52 和 62 yo 之间的差异相同;
  • 不允许相互作用,例如,无论乘客是在一等舱还是三等舱,60 岁对生存概率有相同的影响。

尝试黑盒:Catboost 和 SHAP

现在让我们尝试一个“黑盒”模型。在这个例子中,我们将使用 Catboost ,这是一种在决策树上进行梯度提升的算法。

对相同的训练数据执行快速 Catboost(没有任何超参数调整)(这次不需要一键编码)会导致验证数据的 87.15% 准确度。

正如我们所料, Catboost 的表现大大超过了 LogReg (87.15%对 81.56%) 。到目前为止,不足为奇。

现在,机器学习中 64,000 美元的问题是:如果 Catboost 在预测未知数据的存活率方面比 LogReg 好得多,我们难道不应该信任它,而不要太担心齿轮

嗯,看情况。如果是 Kaggle 比赛,答案可能是“是”,但总体来说是“肯定不是!”。如果你想知道为什么,只要看看一些高调的事件,如亚马逊"性别歧视人工智能招聘工具"或微软"种族主义聊天机器人"。

因此,为了弄清楚 Catboost 正在做出什么决定,另一个叫做SHAP(SHapley Additive explaints)的工具来帮助我们了。SHAP(可能是机器学习可解释性的最先进水平)诞生于 2017 年,这是一种对任何预测算法的输出进行逆向工程的聪明方法。

对我们的数据和 Catboost 输出应用 SHAP 分析会生成一个矩阵,它与原始数据矩阵具有相同的维数,包含 SHAP 值。SHAP 价值观是这样的:

SHAP values, first 5 passengers

SHAP 值越高,生存的概率越高,反之亦然。此外,大于零的 SHAP 值导致概率增加,小于零的值导致概率减少。

每个 SHAP 值表示,这是这里的重要部分,个体变量的观测水平对该个体最终预测概率的边际效应

这意味着:假设对于第一个人,我们知道除了年龄以外的所有变量。那么它的 SHAP 和就是-0.36-0.76+0.05-0.03-0.3-0.08 =-1.48。一旦我们知道了个人的年龄(也考虑了年龄和其他变量之间的相互作用),我们就可以更新总和:-1.48 +0.11 =-1.37。

SHAP:房间里有一头大象

你可以使用SHAP 专用的 Python 库来获得奇特的图(基本上包含关于 SHAP 值的描述性统计)。例如,您可以很容易地获得一个按特征细分的总结每个观测值的 SHAP 值的图。在我们的例子中:

你能看见房间里的大象吗?

如果你把这幅图给外行(甚至是你的老板)看,他可能会说:“漂亮的颜色。但是下面的尺子是什么?那些是美元吗?公斤?年?”

简而言之, SHAP 值对于人类(甚至对于数据科学家)来说都是不可理解的。

从形状到预测概率

概率的概念更容易理解。其实还不止这些:是先天的(毕竟这也是人们一直坐飞机的原因)。

From SHAP to Predicted Probability

希望从 SHAP 转移到概率,最显而易见的事情是绘制相对于 SHAP 和(每个个体)的预测生存概率(每个个体)。

显而易见,这是一个确定性函数。也就是说,我们可以无误地从一个量转换到另一个量。毕竟,两者唯一的区别是概率必然在[0,1]内,而 SHAP 可以假设任何实数。因此:

其中 f(。)是单调递增的 s 形函数,它将任何实数映射到[0,1]区间(为简单起见,f()可以是有界在[0,1]中的普通插值函数)。

From SHAP to Predicted Probability — An example

就拿个人来说吧。假设,已知除年龄以外的所有变量,其 SHAP 和等于 0。现在假设相对于年龄的 SHAP 值是 2。

我们知道函数 f()来量化年龄对预测生存概率的影响就足够了:简单来说就是 f(2)-f(0)。在我们的例子中,它是 f(2)-f(0) = 80%-36% = 44%

毫无疑问,的生存概率比的 SHAP 更容易理解。更容易理解的是:说这个个体年龄导致 SHAP 上升 2 或概率上升 44%?

那又怎样?

基于我们刚刚看到的,从上面看到的 SHAP 矩阵开始,应用公式就足够了:

获取以下内容:

Impact on predicted probabilities, first 5 passengers

例如,拥有一张三等票将第一个乘客的生存概率降低了-4.48%(对应于-0.36 SHAP)。请注意,3 号乘客和 5 号乘客也在三等舱。由于与其他特征的相互作用,它们对概率的影响(分别为-16.65%和-5.17%)是不同的。

可以对这个矩阵进行几种分析。我们只是报道一些情节作为例子。

Marginal Effect of Passenger Age

Marginal Effect of Passenger Fare

Interaction Effect: Passenger Fare vs. Ticket Class

红线表示平均效应(一组中所有个体的平均年龄效应),而蓝带(平均标准偏差)表示同一组中个体之间年龄效应的可变性。可变性是由于年龄和其他变量之间的相互作用。

这种方法的附加价值在于:

  • 我们可以用概率而不是 SHAP 值来量化影响。例如,我们可以说,平均而言,与 0-10 岁相比,60-70 岁的人存活概率会降低 27%(从+14%到-13%);
  • 我们可以想象非线性效应。比如看客运票价,生存概率上升到一点后略有下降;
  • 我们可以表现互动。例如,乘客票价与机票等级。如果这两个变量之间没有相互作用,这三条线将是平行的。他们表现出不同的行为。蓝线(头等舱乘客)票价略有下降。特别有趣的是红线(三等舱乘客)的趋势:在乘坐三等舱的两个相同的人之间,支付 50-75 英镑的人比支付高达 50 英镑的人生存的可能性高约 15%(从-10%到+5%)。

包扎

像逻辑回归这样的简单模型做了大量的简化。黑盒模型更灵活,因此更适合复杂(但非常直观)的现实世界行为,如非线性关系变量之间的相互作用

可解释性意味着以人类可以理解的方式表达模型的选择,基于他们对现实的感知(包括复杂的行为)。

我们已经展示了一种将 SHAP 值转化为概率的方法。这使得我们有可能将黑盒功能可视化,并确保它与我们对世界的认识(定性和定量)一致:一个比简单模型描述的世界更具多面性的世界。

把密码给我!

代码可在此处找到:

[## smazzanti/TDS _ black _ box _ models _ more _ explaible

此时您不能执行该操作。您已使用另一个标签页或窗口登录。您已在另一个选项卡中注销,或者…

github.com](https://github.com/smazzanti/tds_black_box_models_more_explainable/blob/master/Shap2Probas.ipynb)

尽情享受吧!

黑盒及其入侵

原文:https://towardsdatascience.com/black-boxes-and-their-intrusion-620aa3c4c56b?source=collection_archive---------22-----------------------

到目前为止,人工智能领域已经成功地扩展到各个领域,并提供了前所未有的惊人支持和成果。但是,在每个英雄的故事中,都有一个对手。

Black Box visual

黑匣子:在科学、计算和工程中, 黑匣子 是一种设备、系统或对象,可以根据其输入和输出来查看,而无需了解其内部工作情况。它的实现是“不透明的”(黑色)。几乎任何东西都可能被称为黑匣子:一个 晶体管 ,一个 算法 ,或者是 人脑

你可能听说过在软件开发过程中发生的黑盒测试,测试人员不知道被测试项目的内部结构/设计/实现,但是模型的工作被验证。

基本算法,如两个数字的 LCM,看起来比较简单,即使有时花费时间被认为是容易的,因为理解和解释这些算法的工作是容易掌握的。但是,当涉及到人工神经网络、卷积神经网络、递归神经网络等深度学习时,算法变得太复杂,人脑无法计算。它们包含许多隐藏层,不容易被与计算机通信的人追踪到。

Perceptron design

此外,当设计和实现深度学习模型时,它们被制作成便于使用,用户只需在几秒钟内给出输入并获取输出,而无需任何关于事物内部如何工作的先验知识。

无论深度学习模型能够提供多么准确的结果,任何应用都没有必要总是遵循某些预定义的规则。例如,在识别疾病的组织学数字的医学研究中,研究人员必须知道模型如何给出任何结果,以及它是在什么基础上得出结论的。“它真的知道自己在做什么吗?还是瞎猜的?”。在任何测试中绝对不允许出现任何不寻常或异常的模式。

任何代码如果易于调试,都被认为是干净或令人愉快的。如果对于任何给定的模型,假设一个输入给出一个假阳性输出,人们应该能够找出机器在哪里采取了错误的步骤,并使它学习一个更好的方法。但是由于所有的内部过程都是隐藏的和复杂的,它被认为是在一个“黑匣子”里。你只知道输入和输出。

医疗领域对深度学习的接受需要来自其他领域的证据,医学专家希望看到它在现实生活的其他关键领域取得成功,如自动驾驶汽车、机器人等。尽管基于深度学习的方法取得了巨大的成功,但仍然缺乏一种像样的深度学习算法理论。这是机器学习社区公认的。黑盒可能是另一个主要挑战,黑盒功能的法律影响可能是一个障碍,因为医疗专家不会依赖它。如果结果出错,谁能负责?

解开黑盒是一个重大的研究问题,为了解决这个问题,深度学习科学家正在努力解开这个众所周知的黑盒。一个解决方案建议开发一个工具包,显示每个单个神经元激活的视觉效果。因此,每个神经元的贡献是可见的,并且任何错误都可以很快被识别。

Example of a deep visualization toolbox implemented for face recognition.

最近在 5 月,来自麻省理工学院和其他地方的研究人员开发了一种交互式工具,首次让用户看到和控制自动机器学习系统如何工作。目的是建立对这些系统的信心,并找到改进它们的方法。

黑洞机器学习

原文:https://towardsdatascience.com/black-hole-machine-learning-d7387a4bd30e?source=collection_archive---------14-----------------------

奇点研究

通过理论物理的神经网络

主持人: Sketchviz

# http://www.graphviz.org/content/cluster
graph G {
    node [style=filled,color=pink];
    q0 -- H0 -- U -- V0 -- W0 -- A;
    q1 -- H1 -- U -- V1 -- W0 -- B;
    q2 -- H2 -- U -- V2 -- W1 -- C;
    q3 -- H3 -- U -- V3 -- W1 -- D;
    q4 -- H4 -- U -- V4 -- W2 -- E;
}

在本文中,我们提供了一些链接,链接到使用张量网络的重要而有趣的代码和软件,张量网络是一种用于引力物理学和黑洞研究的数学工具。我们感兴趣的代码将涉及机器学习和人工智能的应用。我们将回顾张量网络的简史,并稍微解释一下它们是什么,我们将解释它们如何将理论物理与机器学习联系起来,并深入了解为什么谷歌这样的巨头会聘请李奥纳特·苏士侃这样的物理学家来咨询他们的人工智能和机器学习算法。我们还将展示量子计算如何发挥作用,以及如何使用量子计算机创建量子增强的人工智能和量子机器学习算法,迫使我们重新思考我们理解信息处理的方式。

用于 TensorFlow 的 Google tensor network 库

今年早些时候(2019 年 6 月),谷歌的人工智能博客发布了一篇关于为其臭名昭著的 TensorFlow 机器学习平台建造的名为“ TensorNetwork 的图书馆的帖子。它是为张量网络的操作而建立的(我们将进入张量网络的简史,并在下面解释它们是什么)。谷歌开发这个库的工作是与 X 、谷歌的 moonshot factory 创新技术以及Perimeter Institute for theory Physics共同完成的。今年早些时候,周界研究所参与了一个黑洞的成像。除了在 Github 上发布代码,他们还撰写了三篇关于 TensorNetwork 库的应用和性能基准的研究论文:

TensorNetwork:物理和机器学习库

TensorFlow 上的 TensorNetwork:使用树张量网络的自旋链应用

用于机器学习的 TensorNetwork】

如果你有兴趣阅读 TensorNetwork 的文档并深入研究代码,你可以查看阅读文档页面。那么,为什么这么大惊小怪?张量网络有什么特别的,黑洞和机器学习有什么关系?什么是……张量网络?

张量网络简史

张量网络是物理学家使用的张量的图形符号,至少可以追溯到 20 世纪 70 年代,由罗杰·彭罗斯在他的图形符号中提出。他还在他的书现实之路中多次提到张量网络是如何应用于物理学的。另一个有点晦涩但非常透彻的文本是 Predrag Cvitanovic 所著的《群论:鸟迹、李氏和例外群》一书。这本书实际上在几年前我还是大学生的时候就引起了我的注意,就在它第一次发行后不久,特别是因为我想了解量子引力,以及人们如何使用如此迷人的视觉工具来做一些非常深奥的数学。

这些张量的图形表示不仅仅是漂亮,它们实际上构成了当今理论物理中一些最深刻和最基本的概念的基础。物理学家和数学家使用它们来描述量子信息理论、AdS/CFT 通信、弦理论和全息原理,如、罗杰·彭罗斯、胡安·马尔德塞纳和约翰·普雷斯基尔。

其他张量网络机器学习实现

量子激励张量网络的监督学习

在本文中,E. Miles Stoudenmire 和 David J. Schwab 使用张量网络模型对手写数据 MNIST 进行机器学习分类,使用“矩阵乘积状态”。他们能够获得 1%的误差。他们还“讨论了张量网络形式如何给学习模型赋予额外的结构,并提出了一种可能的生成解释”。他们的代码可以在 Github 库中找到。

Quimb

Quimb 是一个 python 库,用于量子信息和多体计算,包括张量网络。它速度快,并针对效率进行了优化。它主要用于物理问题的应用,但也可以适用于其他应用。它可以在 GPU 上运行,并且可以以几何自由的方式计算张量运算和表示。它可以用tensorflowpytorch优化任何张量网络

它对于量子计算机的模拟是有用的,因为它已经在 IBM Qiskit 中为计算进行了设置。对于许多问题,模拟是有效的,但是对于感兴趣的解空间不受某种对称性限制的高维计算,当然需要量子计算机来代替 Quimb 提供的经典模拟。

量子机器学习和一种新的信息论

在他的文章NISQ 时代的量子计算和超越中,John Preskill 描述了在“嘈杂的中间规模量子(NISQ) ”硬件上量子计算的当前状态。在他的讲座中,他讨论了一种量子信息理论,类似于谷歌与数学物理学家约翰·c·贝兹和计算机科学家迈克·斯泰共同撰写的论文物理、拓扑、逻辑和计算:一块罗塞塔石碑。论文的一个主题是我们应该重新思考信息论。

特别是,谷歌的论文解释了如何通过张量网络从量子物理学的角度思考信息论。毫不奇怪,量子计算中的标准符号量子电路图本身就是一个张量网络。

加速!

在 Google TensorNetwork 库的一个简短教程中,我展示了如何使用边的同时收缩来提供计算的实质性加速。该代码计算边顺序收缩的运行时间,然后计算边同时收缩的运行时间。

def one_edge_at_a_time(a, b):
  node1 = tn.Node(a)
  node2 = tn.Node(b)
  edge1 = node1[0] ^ node2[0]
  edge2 = node1[1] ^ node2[1]
  edge3 = node1[2] ^ node2[2]
  tn.contract(edge1)
  tn.contract(edge2)
  result = tn.contract(edge3)
  return result.tensordef use_contract_between(a, b):
  node1 = tn.Node(a)
  node2 = tn.Node(b)
  node1[0] ^ node2[0]
  node1[1] ^ node2[1]
  node1[2] ^ node2[2]
  # This is the same as
  # tn.contract_between(node1, node2)
  result = node1 @ node2
  return result.tensora = np.ones((1000, 1000, 10))
b = np.ones((1000, 1000, 10))%%time
one_edge_at_a_time(a, b)CPU times: user 15.7 s, sys: 1.88 s, total: 17.6 s
Wall time: 14.3 s

[29]:

array(10000000.)

这将依次收缩三条边,首先是红色,然后是绿色,然后是蓝色,如使用 Graphviz 生成的图像所示:

# http://www.graphviz.org/content/cluster
graph G0 {
    node [style=filled,color=pink];
    edge [color = red];
    a -- b;
    edge [color = green];
    a -- b;
    edge [color = blue];
    a -- b
}

主持于 Sketchviz

%%time
use_contract_between(a, b)CPU times: user 495 ms, sys: 145 ms, total: 639 ms
Wall time: 1.75 s

[33]:

array(10000000.)

数学上,这转化为三阶张量的内积:

contracting 3 edges between two nodes “a” and “b”

如本文文章中所述,拥有这样的算法可以在高维张量上执行更高效的计算,从而提供显著的加速(高达 100 倍)。加入新的“ 张量处理单元【TPUs】”后,谷歌设计了更高效的张量计算,用于机器学习目的,你就拥有了一个极其强大的机器学习框架,从硬件到云计算软件再到最终用户应用。

这能用来做什么?

到目前为止,张量网络方法已经在图像识别、多类分类问题、计算机视觉、物理学、材料科学、生物技术、量子化学和生物物理学中得到应用。由于 TensorNetwork 提供了一种将张量网络集成到标准神经网络层的简单方法,因此它们可以用于任何涉及神经网络的机器学习任务。

虽然这些方法对大多数机器学习社区来说可能是新的,但它们在物理和数学中有很长的应用历史,因此理论和概念理解在数学和理论物理社区中已经很好地建立。这提供了一种理解机器学习的新方法,并在受“黑盒”方法论困扰的领域提供了新的直觉。努力理解人工智能为什么做出某些决定并得出特定结论是一个问题,这导致人们担心人工智能在某些商业解决方案的应用中会有多大的偏见,例如人工智能辅助的招聘。随着执法部门现在在许多城市应用人工智能,确保人工智能是公平的,而不是做出不人道的决定,也成为许多人关注的问题。除此之外,张量网络方法可以在机器学习任务和计算效率方面提供改进,在更大规模上投资研究和实施这些方法似乎是明智的。

如果你有想法要分享,有问题,或者你需要量子机器学习的咨询服务,请通过 LinkedIn 联系作者,访问奇点网站,或者查看 Github 教程

责怪游戏,而不是玩家

原文:https://towardsdatascience.com/blame-the-game-not-the-player-467e33d8044b?source=collection_archive---------13-----------------------

博弈论如何帮助我们理解为什么有时每个人都会输

一名网球运动员决定在下一场比赛前服用兴奋剂,以便胜过对手。一个零售商决定在周日继续营业,因为他的竞争对手也开始这样做了。可口可乐降低饮料价格以获得市场份额优势,迫使百事可乐也这样做。

所有这些假设场景有什么共同点?它们都是博弈论专家所谓的囚徒困境的例子。

In Germany, retailers are by law required to close on Sundays. (Photo credit: Unsplash)

囚徒困境:当所有人都输了

在它的原始形式中,囚徒困境可以表述如下。两个罪犯(假设他们抢劫了一家银行)被逮捕并送进了监狱,彼此之间无法交谈。缺乏证据的检察官让他们每个人做一笔交易:他们每个人都可以选择指责另一名嫌疑人(“叛逃”),或者保持沉默(“相互合作”)。如果两人都保持沉默,两人都将只服刑 1 年。如果一方指责另一方,而另一方保持沉默,说话的一方将退出,而另一方将服刑 5 年。如果双方互相指责,他们都将服刑 3 年。

Outcomes of the Prisoner’s Dilemma (source)

如果囚犯们按照自己的最大利益行事,他们会怎么做?第一个犯人想:“不管对方做什么,我叛逃总是好的。如果他保持沉默,我就自由了。如果他叛逃,我只会服刑 3 年(而不是我合作的话会服刑 5 年)。”第二个囚犯也是这么想的,所以,如果两个人都是为了各自的最大利益而行动,那么两个人都会叛变,两个人都会服刑三年。

然而,这里有一个难题:如果双方合作,双方都会更好(只服刑 1 年)。

更一般地说,当任何一方通过不合作获得优势时,我们随时都会面临囚徒困境,但如果双方都合作会更好。回到上面的例子:如果两个网球运动员都不服用兴奋剂,他们的情况会更好,但每个人都可以通过服用兴奋剂获得优势,如果两个人都服用兴奋剂,优势就会被抵消。如果两家零售商都可以在周日休息一天,情况会更好,但如果另一家不开门,两家都可以通过开门获得市场份额优势(如果两家都这样做,就会抵消)。可口可乐可以通过降低价格来获得市场份额的优势,如果百事可乐也这样做,这种优势就会被抵消。

囚徒困境的结果,双方玩家都倒戈,也被称为博弈的纳什均衡,以数学家约翰·纳西命名。纳什证明了每个双人游戏都有这样一个均衡,双方都不想改变主意。然而,在囚徒困境中,这种均衡对双方都是有代价的:这不是最优结果。

Shanghai covered in Smog. (Photo credit: Unsplash)

公地的悲剧

当涉及两个以上的当事人时,囚徒困境变得更加有趣,这种情况也被称为 公地悲剧 问题。

考虑一下过度捕捞的问题。如果每个人都捕捞足够的鱼来保持鱼的数量稳定,那么每个渔场都会变得更好。然而,每一个渔场都可以通过比可持续捕捞量稍多的捕捞量来获得相对于竞争对手的微小优势。但是如果所有的渔场都这样做,很快鱼类种群将会完全崩溃。过度捕捞是这个游戏的纳什均衡不好的直接后果。

空气污染又是一个例子。如果所有国家都限制碳排放,每个国家都会变得更好。然而,每个国家都可以通过比其他国家稍微多污染一点来获得优势。但如果每个国家都遵循这一战略,我们的情况都会变得更糟。

在商界,假期是公地悲剧的另一种形式。如果每个人都有相同的假期,那么所有的员工都会受益。然而,每个员工都可以通过比他们的同事少休一点假期来获得一点优势,证明他们的忠诚,并使他们更有可能获得加薪或晋升。因此,每个人都会少休息几天。这种情况下的纳什均衡是每个人都将零休假。从博弈论的角度来看,应该对科技公司提供的“无限假期”持怀疑态度。

在我自己的工作领域,头衔膨胀是公地问题悲剧的又一个例子。如果职位名称能真实地反映基础工作,招聘经理和求职者都会受益。然而,每个招聘经理都可以通过将他们的数据/业务分析师职位宣传为数据科学家职位,从而在求职者市场中获得些许优势。然而,如果每个人都开始这样做,这种影响就会减弱,很快每个人都会成为数据科学家。(与此同时,我的大多数数据科学家朋友都去了其他职位,如机器学习工程师。)

The Redwood trees in California are another example for a Prisoner’s Dilemma. Each individual tree can gain an edge in received sunlight by growing slightly larger than the others, which is diminished if every tree does so.

改变游戏

纳什证明了每个博弈都有一个均衡,我们在上面看到了很多“坏”均衡的例子,如果每个人都理性地按照自己的最大利益行事,那么每个参与者的情况都会更糟。

博弈论的一个关键观点是,游戏可以被有意设计成具有“好”均衡。机制设计(或逆博弈论)领域,位于经济学和博弈论的交叉点,处理这个问题。

例如,在德国,法律不允许零售商在星期天开门营业,除了全年中几个特定的星期天。立法者做出这一决定并不是出于宗教原因,而是为了保证每个人至少有一天休假(鉴于纳什均衡另有所指)。

为了解决员工不休假的问题,一些公司开始支付他们休假的费用。然而,从博弈论的角度来看,这一政策是错误的,因为它无助于解决问题的根源,即糟糕的纳什均衡。为了解决这个问题,雇主应该改为强制规定最低休假时间,这将有效地改变纳什均衡。据美国有线电视新闻网报道,一些公司正在试验这一政策。

过度捕捞的问题呢?在的《裸体经济中,查理斯·惠兰讲述了澳大利亚南部海岸林肯港龙虾社区的引人入胜的故事。社区对可以设置的龙虾陷阱的总数设定了限制,然后出售这些陷阱的许可证。新来者进入这个市场的唯一途径是从另一个捕虾人那里购买一个这样的许可证。Wheelan 指出,这种许可制度使得龙虾数量激增,同时也提高了龙虾养殖者的工作效率。

Fishing boats in Egypt (Photo credit: Unsplash)

结论:知道自己在玩什么游戏

“寻找以诚实为主导策略的游戏。那就做好自己吧。”(布莱恩·克里斯蒂安和汤姆·格里菲斯,《赖以生存的算法》

一些游戏的糟糕结果仅仅是因为游戏的架构,而不是因为玩家。博弈论帮助我们识别问题中的“坏”纳什均衡,如过度捕捞、空气污染、休假政策、体育运动中的兴奋剂、商店营业时间等等。另一方面,机制设计(或逆博弈理论)帮助我们重新设计这些问题,使得纳什均衡对每个参与者来说都是一个更好的结果。龙虾陷阱许可,最低强制休假日政策,以及规定的商店营业时间都是改变纳什均衡的机制设计的例子。

也许博弈论最重要的一课是知道你在哪个游戏中。如果你处于囚徒困境或公地悲剧类型的游戏中,要知道每个人都有损失,但没有人有错。

Blender 2.8 油脂铅笔脚本和生成艺术

原文:https://towardsdatascience.com/blender-2-8-grease-pencil-scripting-and-generative-art-cbbfd3967590?source=collection_archive---------8-----------------------

Quick, Draw! — Flock — Conway’s Game of Life

什么:学习 Blender Grease-Pencil 工具的基本脚本,重点是作为具体游乐场的生成艺术。话少,代码多(评论)例子多。

为什么?主要是因为我们可以。还因为 Blender 是一个非常丰富的生态系统,而 2.8 版本的Grease-Pencil是一个强大而通用的工具。生成艺术是展示工具潜力的迷人方式:如果你喜欢 Python,但不喜欢学习处理,或者仍然不确定是否要尝试 p5.js 或 Three.js,这里你会找到完美的游乐场。

: Python ≥ 3.6 和 Blender 2.8 。我从其他关于生成艺术的资源中获得了灵感,特别是马特·皮尔森的《生成艺术》一书和 Kadenze 在线课程。

地点/时间:此时此地。也可以在这里找到完整的代码(以及 Blender utils 在这里)。

设置

在 Blender 中,您可以使用 Python 控制台编辑器中的代码(一定要充分利用自动完成功能)

Python Console Editor

Text Editor

或者你可以更容易地运行。文本编辑器中的脚本。始终切换系统控制台,以便检查 Python 输出。有用的快捷键是用于运行脚本的alt+P和用于重新加载文件内容的alt+R。除非你只是玩玩或者做做实验,否则我建议用专用的 IDE 编写代码,然后回到 Blender 来验证结果。

这些都是开始的必要条件。这里是准备好油脂铅笔(GP)实例的代码。

层次结构是这样工作的:每个 GP 对象可以有多个,这是一个组织你的工作的抽象。在一个层中,你可以创建笔划,这是一系列与材质相关的点。同一层的不同笔画可以有不同的材质。笔划位于中,这是 GP 对象的时间维度。我们将在后面的动画部分看到更多关于帧的内容,对于静态内容,我们只需要一个目标帧来绘制我们的笔划。

gp_layer = init_grease_pencil()
gp_frame = gp_layer.frames.new(0)

有了这个可重复使用的框架,我们就可以开始绘图了。

一个 GP 笔划仅仅是具有属性的点的集合。这里举例说明画线的方法。

对于给定的 GP 帧,创建一个新的笔划,定义长度(点数)并设置每个点的 3D 坐标。然后,您可以在屏幕上显示您的笔划(由于有了display_mode标志,在 3D 空间中是可编辑的)并在第 0 帧通过

gp_layer = init_grease_pencil()
gp_frame = gp_layer.frames.new(0)

draw_line(gp_frame, (0, 0, 0), (1, 1, 0))

我们可以通过重用之前的draw_line方法来绘制一个正方形,或者我们可以通过计算坐标和添加更多的点来更好地从头开始构建我们的正方形。类似的,移动到三维形状,以建立一个立方体。

From 0 to 3 Spatial Dimensions

下面的代码改为画一个圆。注意draw_cyclic 标志关闭循环(先连接最后一个笔画点)。

GP 现在是一等公民,因此可以依赖通用 Blender 对象的任何更高级别的实用程序/方法。对于笔画来说是不一样的,但这给了我们机会去学习/理解更多关于计算机图形学的基本机制,以及随之而来的数学。
例如,我们可以使用旋转矩阵旋转我们的圆(只是一堆点)。

有了这两种方法,人们可以通过

def draw_sphere(gp_frame, radius: int, circles: int):
    angle = math.pi / circles
    for i in range(circles):
        circle = draw_circle(gp_frame, (0, 0, 0), radius, 32)
        rotate_stroke(circle, angle*i, 'x')

从这些基本组件和步骤中,您可以组合出几乎无限多种结果。下面是一些基本的例子,我用这些代码和一些数学模型来生成数据。

材料

材料是探索新维度的一种方式,试图逃离单调现实的沉闷。

Grease Pencil Materials

通过将其material_index属性设置为相应的材质索引,可以将每个笔划与特定的材质相关联。笔画粗细可以在创建时通过line_width属性设置。

gp_stroke = gp_frame.strokes.new()
gp_stroke.display_mode = '3DSPACE'  # allows for editing# The new lines needed to customize stroke thickness and material
gp_stroke.line_width = 100
gp_stroke.material_index = 1

请注意,一些属性位于层级别,而另一些属性位于材质级别。然后,您可以手动调整材质,并从用户界面获得实时反馈,但对于厚度,您可以只在层级别进行调整,除非您开始使用效果或修改器。

Basic Shapes with Different Materials

材料也可以通过编程来创建,但这是一篇专门文章的内容。现在享受一些我摆弄基本材料选项的结果。

动画

Dope Sheet Editor for Grease Pencil Mode

帧是你最好的动画朋友。它们是你讲述故事的媒介;你可以在 Blender 中激活时间轴上的画布。从代码的角度来看,就是创建新的帧并访问它们来管理笔画。

在这个脚本中,我们设置目标帧数和相对距离,相应地更新场景变量,然后遍历这些帧,在时间轴中的每个目标位置创建一个。gp_layer.frames.new方法需要时间线上新帧的索引作为参数,如果已经存在,它将抛出一个错误。您也可以通过gp_layer.frames[index]访问帧,但是请注意帧列表中的索引不一定与时间轴帧号相匹配(因为帧的间距可能不同)。为此,你可以检查框架对象的frame_number属性。

Kinetic Rotating Square

在前面的例子中,我们使用了gp_layer.frames.new,它返回一个新的空白帧,没有过去的记忆。如果你要画全新的东西,可以用这个。相反,如果你对重用先前帧中绘制的内容感兴趣,你应该使用gp_layer.frames.copy(gp_frame),其中gp_frame是一个实际的帧实例。这将给定帧的内容复制到下一个可用的时间轴位置。

下面的动画完全使用这种方法,每帧只绘制一个新线段,复制之前已经绘制的所有线段,并在每个线段绘制之间添加“立方体扩展效果”。

Dragon and Koch Curves

这真的是编写基本动画的全部知识。这里是我根据这篇文章的内容创作的一些例子。

3D L-Systems — Kinetic Rotating Square —Hexagon CA

作为奖励,我在这里接上了一张草图——RNN 模型和相关的快,画吧!数据集,用于绘制代理的漂亮网格。

结论

在这篇文章中,我们介绍了油脂铅笔脚本的基础,重点是示例和方向的生成艺术。

关于 Grease-Pencil 没有太多要说的,如果不是要变得有创造性,拿出你自己有用的/有创造性的用例,当然利用 Blender 巨大的潜力。以混合为目标,例如混合 3D 和 2D,或者“艺术数据可视化”。

相反,我想以围绕生成艺术的建议结束,从一些基本的食谱和有效的创作惯例开始:

  • 探索并结合多种数学函数和模型
  • 从其他领域获得灵感(如生物学、建筑学、心理学、物理学)
  • 分解现实和其他人的作品并试图复制
  • 设计和试验可重用原子方法和对象的可组合层次
  • 重新解释:以不同的方式可视化属性、对象和动作
  • “不要做相机能做的,做它不能做的”

必须开始探索的话题(有些高度相关):

最后,我强烈建议潜入机器学习和相关的生成模型。这些技术的结果不言自明。

“我听而忘,我看而记,我做而理解”——孔子

可以在我的insta gramTwitter【CS stuff】上找到更多。

比较句子得分

原文:https://towardsdatascience.com/bleu-bert-y-comparing-sentence-scores-307e0975994d?source=collection_archive---------16-----------------------

Blueberries — Photo by Joanna Kosinska on Unsplash

本故事的目标是理解 BLEU,因为它是 MT 模型的一种广泛使用的测量方法,并研究它与 BERT 的关系。

这是我的项目的第一个故事,我尝试在神经机器翻译(NMT)问题中使用 BERT 情境化嵌入向量。我对机器翻译比较陌生,因此,欢迎任何建议。

句子相似度

当涉及到机器翻译或其他自然语言处理(NLP)问题时,过程的输出是文本,测量结果的正确性并不简单。

评估机器翻译算法我们要问的问题是“这个翻译有多好?”或者“目标语言中的句子和源语言中的句子有多接近?”

为了理解这个问题,在这里我们将看看它的一个更简单的版本:“在同一种语言中的两个句子有多相似?”

在这个故事中,让我们使用以下袖珍句子:
s0: James Cook was a very good man and a loving husband. s1: James Cook was a very nice man and a loving husband. s2: James Cook was a bad man and a terrible husband. s3: James Cook was a nice person and a good husband. s4: The sky is blue today and learning history is important.

我想建议大家花一分钟思考一下句子之间的相似性,它们与第一个句子有多接近!

蓝色

BLEU:双语评价替角提供评分比较句子1。最初,它是为翻译开发的,使用参考翻译来评估预测的翻译,然而,它也可以用于句子相似性。这里很好的介绍了 BLEU(或者阅读原文)。

BLEU 背后的想法是统计句子中匹配的 n-grams 。一元词是一个单词(token),二元词是一对两个单词,以此类推。在这种情况下,单词的顺序无关紧要。

为了消除错误的分数(例如,“the the the the”给“猫吃鸟”一个相对较好的分数),引入了这个计数的修改版本。这个修改的单字精度惩罚了在参考文本中多次使用同一个单词。

BLEU 不能处理单词同义词,但是,它是一种快速、廉价的算法,与语言无关,并且与人类评估相关。

伯特

BERT:来自变压器的双向编码器表示是一个上下文化的单词嵌入(以及更多)[2]。这里是对 BERT 的一个很棒的总结(或者阅读原文)。

单词嵌入是映射到单词的向量,以帮助计算机理解单词。虽然“猫”或“狗”对计算机来说很难处理,但它们的矢量表示更适合。对嵌入映射的一个期望是相似的单词必须彼此靠近。

根据上下文,上下文化单词嵌入向量对于相同的单词具有不同的嵌入。BERT 嵌入的一个技巧是,它是用分隔符CLSSEP训练的,这些分隔符也有上下文相关的嵌入向量。原论文中建议这些嵌入可以作为句子级嵌入。这里,我们将使用每个句子的CLS分隔符的嵌入向量作为句子的嵌入。[CLS] This is a sentence with separators . [SEP]

向量距离

这里,我们将使用相应的CLS句子级嵌入的欧几里德距离和余弦相似度来计算句子之间的相似度。

Euclidean distance

Cosine similarity

欧几里德距离的范围是[0,∞),因此,为了匹配其他分数,让我们使用函数 f(x)=(1/1.2)^x 来获得(0,1)分数。该函数产生相对接近于 BLEU 的分数。余弦相似度具有正确的范围,但是,它与 BLEU 分数没有可比性。为了评估结果,我们必须调查句子之间的相对分数,而不是其他分数。

相似性得分

这是一个使用 BLEU 的分数表。正如我们所看到的,BLEU 认为第二个句子与第一个句子很接近(只有一个单词发生了变化),但是它不能处理第四个句子的同义词。还有一个完全不同的句子得分比较高。

具有平滑功能的 BLEU 解决了后一个问题。

具有欧几里德距离的 BERT 获得了与 BLEU 相对相似的分数,但是它也处理同义词。BERT 向量的余弦相似性具有与空间相似性得分相似的得分。

Spacy 是一个工业级的自然语言处理工具。Spacy 使用嵌入向量的单词,句子的向量是其标记向量的平均值。更多关于空间相似性这里

BLEU and BERT scores of the pocket sentences, similarity to the first sentence

贝特斯科尔

(2019 年 11 月 6 日更新)

这是一个更新,因为我最近发现了一篇文章,其想法是使用 BERT 来评估机器翻译系统[4]。作者表明,与之前的分数(如 BLUE)相比,BERTScore 与人类判断的相关性更好。

BERTScore 与这里介绍的相似,但是,BERTScore 使用标记级 BERT 嵌入向量的相似性,而我们使用句子级嵌入。

摘要

这个故事介绍了评估句子相似性的 BLEU 分数,并将其与 BERT 向量距离进行了比较。这些例子试图说明定义一个相似的句子意味着什么是多么困难,这两种方法显示了定量测量某种相似性的可能答案。附在这个故事上的代码提供了 BLEU 和 BERT 以及 Spacy 的基本用法。对于详细的介绍,提供了额外的链接。

相应的代码在 Google Colab 中有。

参考

1帕皮尼,k .,鲁科斯,s .,沃德,t .,,朱,W. J. (2002 年 7 月). BLEU:一种自动评估机器翻译的方法。计算语言学协会第 40 届年会论文集(第 311-318 页)。计算语言学协会。

[2] Devlin,j .,Chang,M. W .,Lee,k .,& Toutanova,K. (2018 年)。 Bert:用于语言理解的深度双向转换器的预训练。 arXiv 预印本 arXiv:1810.04805

3林春燕,吴凤珍(2004 年 7 月).使用最长公共子序列和 skip-bigram 统计自动评估机器翻译质量。第 42 届计算语言学协会年会论文集(第 605 页)。计算语言学协会。

[4]张,t .,基肖尔,v .,吴,f .,温伯格,K. Q .,&阿奇,Y. (2019)。 BERTScore:用 BERT 评估文本生成。 arXiv 预印本 arXiv:1904.09675

用伯特的故事学习 NMT

  1. BLEU-BERT-y:比较句子得分
  2. 嵌入关系的可视化(word2vec,BERT)
  3. 机器翻译:简要概述
  4. 使用 BERT 识别单词的正确含义
  5. 机器翻译:与 SOTA 相比
  6. 使用 TensorFlow 2.0 的简单 BERT】

蒙住自己的眼睛,获得更好的商业智慧

原文:https://towardsdatascience.com/blindfold-yourself-for-better-business-intelligence-a87ee02e71b0?source=collection_archive---------25-----------------------

Streaming Business Intelligence can notify you before you take the wrong step. © Sergey Khakimullin

实时 BI 和查询未来 BI 的区别

流业务智能允许业务分析师使用交互式 BI 工具来可视化动态信息。但是这种能力掩盖了工具的真正价值,即查询未来。通过应用不断评估的算法,现在可以查询过去、现在和未来。

串流 BI 持续实时查询串流数据。例如,这个 BI 仪表板根据传感器读数和汽车发出的 GPS 位置数据,实时显示一级方程式赛车的路线。当接收到输入时,BI 工具在屏幕上闪烁数据更新。

但这种实时的视觉盛宴隐藏了流式商务智能的强大功能。神奇之处在于当你看着屏幕时,它能评估连续的答案;流式 BI 会记住查询,并随着数据的每次变化不断重新评估它们。

流式商务智能使自助商务智能像自动回拨客户支持一样工作。你可以要求系统给你回电,挂断电话,然后继续你的业务,而不是等待代理。当客服代表准备好了,他们会打电话给你

流式 BI 类似于自动回拨 BI:当您的问题得到回答时,它会给您打电话。该呼叫可以通过电子邮件、文本消息或您可以用 API 编程的任何基于推送的响应来传递。或者,当事件没有发生时,您可以被调用。举个例子:如果一个超过我前面 F1 赛车的机会 3 圈都没有发生,发短信给我

以下是一些质疑未来的商业智能问题的真实例子:

  • 告诉我,当一位高价值客户将一件产品添加到他的购物车中,但 5 分钟后才结账
  • 当两次可疑登录在 5 分钟内相继发生时,请告诉我
  • 告诉我什么时候一艘船离港口有一个小时的路程,但是没有地方停靠
  • 告诉我飞机航线上什么时候预报有风暴
  • 当我的供应链中任何 100,000 个零件的订单超过一个小时没有得到确认时,请告诉我
  • 告诉我什么时候任何生产线开始降低产量。
  • 根据我的交易算法,告诉我什么时候是交易谷歌股票的好时机
  • 当我的司机走错方向时告诉我

自助式流媒体商务智能有助于打破只看过去的思维,并且像十年前颠覆性的自助式商务智能一样,有望改变每个企业使用数字数据的方式。

流式 BI 也适用于数据科学

自适应学习是数据科学,相当于人类通过不断观察环境来学习。自适应学习不是只在数据湖上训练模型,而是在变化的数据流上训练模型。

查询未来问题可以包括机器学习和 AI 模型。因此,您也可以在不观察的情况下,针对不断变化的实时条件应用预测分析。

流式商业智能允许分析师提出一类新的关于未来的商业问题,而不仅仅是已经发生的事情。这项技术使商业用户能够在一个新的计算方向上进行搜索:向前,而不是向后。

通过在你不在的时候不断回答问题,流式商务智能技术有助于实现预测未来情况并据此采取行动的业务流程。

了解更多信息

更多关于串流 BI,阅读 如何查询未来 和本 3 分钟 如何查询未来中序列。 如需了解更多关于在串流商务智能中应用数据科学模型的信息,请阅读 为什么您应该了解串流数据科学

关于作者

马克·帕尔默是 TIBCO 软件公司分析部的 SVP。作为 StreamBase 的 CEO,他被《时代》杂志评为将改变你生活的 科技先锋之一 。更重要的是,他是两个酷孩子的骄傲父亲。

交易中的布林线统计

原文:https://towardsdatascience.com/bollinger-bands-statistics-in-trading-dcc8783a8f88?source=collection_archive---------15-----------------------

有很多交易者使用布林线。我也喜欢布林线。它使用统计数据,并将统计数据带入交易世界。但是有多准确呢?在时间序列中使用标准差是正确的方法吗?一起来了解一下吧!

Bollinger Bands

没有领先指标

作为交易者,我们大多数人使用 OHLC 蜡烛图/条形图(开盘-盘高-盘低-收盘)。这张图表向我们展示了过去发生的事情。我们可以清楚地看到一家酒吧在哪里开业、搬迁和关闭。我们使用许多指标。它们都告诉我们过去发生了什么。对我来说;没有领先指标。过去的就过去了!然而,这是有可能的。如果我们有足够的过去的数据,我们将有足够的基础资产的统计数据。

数据数据数据…

我们需要数据!数据是关键。数据就是一切。我们需要从可靠的来源获取数据。在本文中,我将向您展示如何使用 Python 免费下载数据。我要用 AlphaVantage。

首先;请在 AlphaVantage 网站注册一把免费钥匙。请注意,我不隶属于他们。

现在让我们使用 Python 下载数据。

def load_data(sym="EUR", to_sym="USD", interval="5min", dtype=2, intraday=False, outputsize="full"):
    key = "ENTER_YOUR_KEY"
    if dtype == 1: # Download stock
        if intraday:
            url = "[https://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&interval={}&symbol={}&apikey={}&datatype=csv&outputsize={](https://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&interval={}&symbol={}&apikey={}&datatype=csv&outputsize={)}".format(interval, sym, key, outputsize)
        else:
            url = "[https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&symbol={}&apikey={}&datatype=csv&outputsize={](https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&symbol={}&apikey={}&datatype=csv&outputsize={)}".format(sym, key, outputsize)
    elif dtype == 2: # Download forex
        print("FX")
        if intraday:
            url = "[https://www.alphavantage.co/query?function=FX_INTRADAY&interval={}&from_symbol={}&to_symbol={}&apikey={}&datatype=csv&outputsize={](https://www.alphavantage.co/query?function=FX_INTRADAY&interval={}&from_symbol={}&to_symbol={}&apikey={}&datatype=csv&outputsize={)}".format(interval, sym, to_sym, key, outputsize)
        else:
            url = "[https://www.alphavantage.co/query?function=FX_DAILY&from_symbol={}&to_symbol={}&apikey={}&datatype=csv&outputsize={](https://www.alphavantage.co/query?function=FX_DAILY&from_symbol={}&to_symbol={}&apikey={}&datatype=csv&outputsize={)}".format(sym, to_sym, key, outputsize)
    elif dtype == 3: # Download Crypto
        url = "[https://www.alphavantage.co/query?function=DIGITAL_CURRENCY_DAILY&symbol={}&market={}&apikey={}&datatype=csv&outputsize={](https://www.alphavantage.co/query?function=DIGITAL_CURRENCY_DAILY&symbol={}&market={}&apikey={}&datatype=csv&outputsize={)}".format(sym, to_sym, key, outputsize)
    print("Downloading", url)
    print("---")
    df = pd.read_csv(url)# rename columns
    if dtype == 3:
        df.rename(columns={'timestamp': 'Date', 'open (USD)': 'Open', 'high (USD)': 'High', 'low (USD)': 'Low', 'close (USD)': 'Close', 'volume': 'Volume'}, inplace=True)
    else:
        df.rename(columns={'timestamp': 'Date', 'open': 'Open', 'high': 'High', 'low': 'Low', 'close': 'Close', 'volume': 'Volume'}, inplace=True)
    df.sort_values(by="Date", ascending=True, inplace=True)
    print("Data loaded:", len(df), "rows")
    return df# Options
sym = "EUR"
to_sym = "USD" # only for fx and cryptocurrency
intraday = False # False: Daily
interval = "5min" # 1min 5min 15min 30min 60min - only if intraday is set to True
dtype = 2 # 1: stock 2: fx 3: crypto# load data
df = load_data(sym, to_sym, interval, dtype, intraday)

我们已经下载了我们的数据,下面是它的样子。

df['Close'].plot(figsize=(15, 10))

EURUSD Daily Closing Prices

这是欧元兑美元的日线图。现在我们需要做的是在图表上添加布林线并计算统计数据。

def add_bb(df, dev=2, lb=20, col="Close", lines=100):
    df['MA'] = df[col].rolling(lb).mean()
    df['STD'] = df[col].rolling(lb).std()
    df['OVB'] = df['MA'] + df['STD'] * dev
    df['OVS'] = df['MA'] - df['STD'] * dev
    plot_candles(df, lines=lines)
    get_stats(df, dev=dev)

请注意,我添加了两个新函数。第一个绘制蜡烛线,第二个计算并打印出布林线过去的统计数据。让我们快速定义这些函数。

def plot_candles(df, lines=100):
    df['Bar'] = df['High'] - df['Low']
    df['Body'] = abs(df['Close'] - df['Open'])
    df['Up'] = df['Close'] > df['Open']
    df['Color'] = np.where(df['Up'], "g", "r")
    if lines > 0:
        db = df[-lines:].reset_index(drop=True).reset_index()
    else:
        db = df.reset_index(drop=True).reset_index()
    plt.figure(figsize=(15, 10))
    plt.bar(db['index'], bottom=db['Low'], height=db['Bar'], color="#000000", width=0.2)
    plt.bar(db['index'], bottom=np.where(db['Up'], db['Open'], db['Close']), height=db['Body'], color=db['Color'], width=0.9)
    plt.plot(db['OVB'], color="b")
    plt.plot(db['OVS'], color="b")
    plt.show()def get_stats(df, high_col="Close", low_col="Close", high_dev="OVB", low_dev="OVS", dev=2):
    total = len(df)
    inside = len(df[(df[high_col]<=df[high_dev]) & (df[low_col]>=df[low_dev])])
    upside = len(df[df[high_col]>=df[high_dev]])
    downside = len(df[df[low_col]<=df[low_dev]])
    i = np.round(inside / total * 100, 2)
    u = np.round(upside / total * 100, 2)
    d = np.round(downside / total * 100, 2)
    # Print the stats
    print("Total bars:", total)
    print("Deviation", dev)
    print("Inside: ", i, "%", sep="")
    print("Up side: ", u, "%", sep="")
    print("Down side: ", d, "%", sep="")

现在让我们继续运行 add_bb()函数,看看结果

dev = 2 # standard deviation
lb = 20 # simple moving average (SMA) of last 20 bars including the final bar
lines = 500 # plot last 500 bars only
add_bb(df, dev=dev, lb=lb, lines=lines)

EURUSD Candlestick chart with Bollinger Bands

非常好的烛台图表在一个棘手的方式!这是布林线在两个标准差内的统计数据:

Total bars: 5000
Deviation 2
Inside: 89.96%
Up side: 5.3%
Down side: 4.36%

内意味着,总棒线收在 2 个标准差之间;上边意味着,总棒线收在上边带之上,下边意味着,总棒线收在下边带之下。

现在我们看到的是标准布林线的“过去”统计数据。请随意更改设置。例如,您可以用 200 SMA 设置一个标准差。

布林线准确吗?

如果你有统计学背景,你应该知道,标准差在正态分布数据中更有效。然而,收盘价不是正态分布的。您可以很容易地看到,运行下面的代码:

df['Close'].hist(bins=500, figsize=(15, 10))

EURUSD closing prices histogram

你可能认为这看起来像正态分布,但我可以很容易地说,它不是。它应该是这样的:

Normal distribution

这就是我所说的完美钟形曲线。如果你有这样的直方图,你可以有更好的统计,告诉你更多。波段之间的距离不会像布林线一样宽。

标准差告诉我们什么?

标准差表示:68.26%的数据落在平均值的一个标准差内,95.44%的数据落在平均值的两个标准差内,99.74%的数据落在平均值的三个标准差内。然而,如果我们使用一个标准偏差进行测试,结果如下:

Total bars: 5000
Deviation 1
Inside: 44.96%
Up side: 28.96%
Down side: 25.7%

可以尝试股票、外汇、加密货币;它们都给你相似的结果。在我看来,这一点也不准确!

结论

从统计学上来说,布林线可能无法满足你的需求。然而,你可以使用你最喜欢的交易策略,仍然可以获利!

**免责声明 **

我不是专业的财务顾问。这篇文章和代码,分享仅用于教育目的,而不是财务建议。你要对自己的输赢负责。

本文的全部代码可以在这个资源库中找到:

[## atillayurtseven/TheCurve

此时您不能执行该操作。您已使用另一个标签页或窗口登录。您已在另一个选项卡中注销,或者…

github.com](https://github.com/atillayurtseven/TheCurve/blob/master/Bollinger Bands Statistics.ipynb)

啊也;记得在以下社交渠道关注我:

中等
推特
交易视图

直到下次;保持安全,交易安全!!!

阿蒂拉·尤尔特塞文

来自《走向数据科学》编辑的注释: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语

图书推荐引擎

原文:https://towardsdatascience.com/book-recommender-engines-4c9d5b33db62?source=collection_archive---------23-----------------------

我决定建立几个推荐引擎,这样我就可以更好地探索它们如何运作的幕后。我构建了两个引擎,每个都推荐书籍。一个是基于合作者,另一个是基于内容。

第一部分:合作者引擎

使用 collaborator 引擎,推荐是基于用户与产品的交互方式。这包括购买或评价一个项目,以及观看或收听媒体。我选择了图书穿越公司的数据集作为这个引擎,因为它包含了用户评分。

探索性数据分析

一旦我清理了数据,我想看一下评级,看看评分范围是什么样子的。评分范围为 1-10 分,在 12.3 万本被评分的书中,这些用户似乎喜欢他们所读的大部分内容。8 是最受欢迎的评级,很少有低于 5 的评级:

接下来,我想看看这些用户最喜欢的书是什么:

可爱的骨头 远超其他。这个数据集是在 2004 年创建的,而《可爱的骨头》是在 2002 年发布的,所以这个时间确实符合这本书在当时的受欢迎程度。

推荐者

接下来,我根据每个用户对多少本书的评价抽取了一个数据样本,并通过推荐器运行。我从一组用户样本开始,他们每个人都评价了 100 多本书。然后我测试了把各种书名输入系统,看看有什么书会被推荐。这里有一个例子:

在这种情况下,我要求根据 《采访吸血鬼》 推荐书籍。右边是建议。我在列表的顶部展示了三个封面,以提醒这三个标题也是安妮·赖斯的,所以在这里推荐它们是合适的。两部其实和采访吸血鬼是一个系列的。

这里有些书是我意想不到的,比如《宋飞正传》或《老实人 T21》。然而,我的用户群实际上很小,所以它推荐的书籍是基于非常精选的读者群。

我试着把我的样本集中那些评价超过 100 本书的用户数量改为 50 本书,我的分数变得更差了。所以我试着把复习的书增加到 200 多本,我的分数变得更好了。这是出乎意料的,因为我们真的需要更多的用户样本来获得更平衡的推荐。有了这个用户群,很可能与那些评价更多书的人走得更少会给我们一个更志同道合的子集。

第二部分:内容引擎

使用基于内容的引擎,推荐是基于产品的特性进行的。考虑到这一点,我选择了来自 Kaggle 的 Goodreads 数据集,因为它包含了每个标题的特征信息,比如流派和平均评级。

探索性数据分析

清理完数据后,我想看看流派划分是什么:

浪漫和幻想似乎让大多数其他类型相形见绌,这是我在转向模型时记住的事情。

推荐者

我根据出版年份提取了一个样本。在这种情况下,我调出了 1900 年及以后出版的所有书籍。与上一个引擎一样,我测试了将各种书名放入系统中,看看有什么书会被推荐。不过,我也想看看我之前测试过的一些相同的书,比如采访吸血鬼:

这一次,你可以看到它没有推荐任何其他安妮·赖斯的书籍。事实上,有一本图画书列出来了,如果你给一只老鼠一个饼干。这不太符合年龄。我不会向阅读《吸血鬼访谈》的人推荐一本绘本。

看到这一点,我备份并调整了我要放入模型的数据列。我测试了各种字段,从评级数量到页数,再到是否包含作者或流派。虽然我注意到结果中有一些有趣的变化,例如当我删除页面作为一个功能时,出现了更多的儿童图画书,但我最好的结果仍然是包括所有书籍特定的数据列。

然而,根据推荐的书目来看,这个方向似乎是有缺陷的。分数看起来很大,但仔细看,结果并不那么好。问题是,对于基于内容的引擎,我们需要比我在这个数据集中所拥有的更多的数据。拥有书籍描述将是一个良好的开端。更完整的内容更好地描述了这本书的真实内容。

结论

在这两个引擎中,collaborator 引擎给我的基于书籍主题的推荐比 content 引擎稍好。后者给出了更好的分数,但仔细看,我可以看到主题也不匹配。但这并不意味着我会排除使用基于内容的引擎。对于这种引擎,我建议引入更多的描述性内容,并使用自然语言处理来评估单词之间的关系,并在此基础上提出建议。

接下来的步骤

我确实看到了这些引擎的巨大潜力。如果我在这个项目上有更多的时间,我会采取并建议考虑以下步骤:

  1. 收集更大的主数据集来测试模型。我的 collaborator 引擎需要更多的用户评分才能更加平衡,而我的内容引擎需要更多的描述性内容。因此需要更大更完整的数据集。一个可以通过网络搜集或 API 收集,包括产品描述和用户评论。
  2. 我也没有时间去做的一件事是研究如何导入外语包。如何在数据中处理外文图书将是下一步需要考虑的事情。要么导入一个可以处理外来字符的包,要么从数据集中删除它们。
  3. Goodreads 集合中有一些与作者相关的数据,我没有机会测试,比如作者类型和平均评分。我想看看这是否有助于获得更好的推荐。
  4. 最后,我将探索在引擎上添加一个基于网络的前端的选项,该引擎具有消费者友好的界面。

该项目的完整代码可在 GitHub 上获得。干杯!

书评:用 Scikit-Learn 和 TensorFlow 实践机器学习:构建智能系统的概念、工具和技术

原文:https://towardsdatascience.com/book-review-hands-on-machine-learning-with-scikit-learn-and-tensorflow-concepts-tools-and-643e93a51016?source=collection_archive---------21-----------------------

如果您对 Python 编程很熟悉,并且希望从一位经验丰富的从业者那里快速了解 Python 中的经典和深度学习技术,那么 Aurélien Géron 所著的《使用 Scikit-Learn 和 TensorFlow 进行机器学习:构建智能系统的概念、工具和技术》可能是一本适合您的书!

哪个奥雷连恩?

Aurélien Géron 最出名的可能是他在 2013 年至 2016 年期间领导 YouTube 视频分类团队的角色。在创办了人工智能培训和咨询公司 Kiwisoft 之后,他现在住在新加坡。

跳进来了!

在“用 Scikit-Learn 和 TensorFlow 进行机器学习实践”中,Géron 肯定会加入进来。在前 30 页中,他概述了机器学习(ML)系统,ML 系统中的主要挑战,以及对模型测试和验证的思考。

在接下来的 40 页中,他将带您体验一个实际操作的端到端 ML 项目。Géron 向您展示了应该如何思考构建问题、选择性能指标、获取数据、执行一些探索性数据分析和可视化以了解数据集、为您的模型准备数据、选择和训练模型、微调模型,以及最后启动、监控和维护系统。如果听起来很多,那就是很多!但是,所有这些都是有益的,非常值得一试。

经典 ML

Géron 随后概述了分类器(ML 解决方案的一个常见类别),然后介绍了使用线性和逻辑回归、支持向量机(SVM)、决策树、集成方法的实际操作,然后花一些时间了解如何使用主成分分析(PCA)处理维度缩减。

这是对经典 ML 的快速而激烈的介绍,但它提供了许多实用的提示和技巧,将帮助您作为数据科学家建立良好的直觉。

“用 Scikit-Learn 和 TensorFlow 进行动手机器学习”更适合高级新手。您已经需要熟悉 Python 编码,如果没有统计学背景,一旦您开始做自己的建模项目,您很可能会做出糟糕的选择。但是如果你是一个“向我展示代码”类型的学习者,这是一个非常好的接触实用 ML 的方式,你可以在以后“填补空白”!

深度学习

在 230 页致力于经典 ML 之后,Géron 直接进入神经网络和深度学习——ML 中最迷人和发展最快的领域之一。

为了保持本书注重实践和代码的性质,Géron 直接进入代码,让您开始使用 tensor flow——构建和训练神经网络最流行的库之一(另一个是 Pytorch)。一旦他让你了解了让代码运行的基本知识,他就会后退一步,提供神经网络的概念介绍。盖伦从生物系统开始,然后转向感知器、多层感知器和反向传播。

从那里,它回到代码。Géron 教授如何训练多级感知器(MLP)和深度神经网络(DNN)。有一整节是关于训练深度神经网络的,包括优化技术,如重用训练层,加速优化的方法,以及通过正则化减少训练数据集过度拟合的技术。

Géron 随后介绍了在多台服务器上分发 TensorFlow 的实用性——这是训练任何实际模型的必要组成部分。他接下来深入研究了卷积神经网络(CNN)和递归神经网络(RNN 的)——两种最常见的深度学习配置。

然后,他引入了自动编码器的概念——可以有效降低数据维度的神经网络。他在这本书的结尾简要介绍了强化学习的广阔领域。

新版本即将推出

这本书的新版本将于 2019 年 10 月发布。它还不可用,但看内容,似乎在经典的 ML 部分进行了一点修剪,并对深度学习进行了实质性的升级。新版在转向 Tensorflow 之前,增加了一个关于神经网络库 Keras 的部分,并增加了关于自然语言处理、生成对抗网络和大规模部署 Tensorflow 模型的内容。

总结

绝对值得等待新版。虽然经典 ML 的基础没有太大变化,但看起来“用 Scikit-Learn 和 TensorFlow 进行机器学习”得到了很好的升级,似乎有一堆更新的内容——在这个领域,两年(上一版于 2017 年出版)是一生的时间!

如果你在寻找能让你成为数据科学家的“那一本书”,这本书可能不是。但是,如果您对编码很熟悉,并且希望了解数据科学家是如何思考和工作的,“使用 Scikit-Learn 和 TensorFlow 进行机器学习实践”是对该领域的一个很好的介绍!

最初发表于【https://flatironschool.com】

书名越来越长了吗?

原文:https://towardsdatascience.com/book-titles-are-getting-longer-1c341fbd4829?source=collection_archive---------17-----------------------

印刷世界趋势的数据分析

photo from Pixabay

几周前,我注意到受欢迎的文学代理人宋东元表达了我一度怀疑的东西,的书名越来越长。

这一趋势似乎很有趣,因为其他媒体似乎正朝着相反的方向发展。例如,我们知道的歌名 s 随着我们注意力的持续时间而缩短。为什么文学小说的世界会有所不同?

为了调查这一说法,我使用《纽约时报》的书籍 AP 收集了自 2011 年以来所有畅销书的数据。下面我将展示更长的标题只是图书世界的众多趋势之一。

小说标题真的越来越长了

为了证实书名确实越来越长,我从《纽约时报》的纸质和电子书小说列表中抓取了所有可用的畅销书。然后我统计了一下这些小说标题的字数。下面是 2011 年 2 月以来每个月小说标题平均字数的剧情。

很明显,自 2016 年以来,有明显的上升趋势。小说标题从平均 2.5 个单词增加到现在的近 3 个。

为了再次确认这一点,我还计算了小说标题中的字母数量。这里,回归线再次显示出明显的上升趋势。现在的小说标题很可能是 14 个字母,而不是 12 个。

为什么标题越来越长?

仔细观察最长的书名,我注意到它们中的许多都来自著名的系列——最引人注目的是“有龙纹身的女孩”系列。以下是标题中包含 7 个或 7 个以上单词的畅销书列表。其中许多是其他成功作品的续集或前传。

作为一个既定系列的一部分,这些标题需要参考过去的工作,使它们不那么简洁。此外,不是出自著名三部曲的小说通常仍然是由知名作家创作的(如尼尔·盖曼、弗雷德里克·巴克曼)。卖给现有的读者群意味着这些作者能够摆弄他们的书名,变得更有创造性。

我怀疑向电子阅读器和网上购买的转变也影响了小说的命名。在网上,远离拥挤的书架,读者不必一次阅读多本书。他们不需要等待一些有力的标题来吸引眼球。此外,从我公认的轶事经验来看,书店和机场售货亭这些天似乎主要出售非小说类书籍。另一方面,小说可以自由的小众和怪异,就像卖小说的互联网一样。

小说标题还告诉了我们什么?

正如我几年前注意到的,最受欢迎的小说似乎都围绕着一个迷人的词——“女孩”。根据 2019 年的更新数据,似乎“女孩”仍然是销量最高的一个词。

Word Cloud of the most popular terms in fiction book titles

然而,这并不意味着小说标题不会随着时间的推移而改变。在 2018 年,“黑暗”和“死亡”等词的流行程度赶上了“女孩”。像孩子的名字一样,最流行的名字往往会演变并反映当前的情绪。

“深色”是 2016 年后的趋势

2016 年后,小说标题的基调似乎发生了微妙但明显的转变。我们可以通过绘制特定单词每年的流行度来看出这一点。例如,“爱”最近已经失宠,而“夜”却成了时尚。同样,在书名中,“光”为“暗”让路。

此外,出于我无法理解的原因,含有“死亡”一词的小说似乎在偶数年很受欢迎。似乎像巨人的一样,死神不喜欢奇数。

非小说类书籍的长度是一样的

我应用于小说畅销书的分析可以很容易地应用于非小说畅销书。下面我画出了每年的字数/非小说标题。右边是每年的信件/标题数量。正如我们所见,没有明显的延长趋势。

left — number of words in nonfiction titles per year : right — number of letters in nonfiction titles per month

鉴于非小说类作品很少成为一个系列的一部分,而且它们仍然在大商店里卖得很好,这并不令人惊讶。事实上,非小说类书籍与小说类书籍还有其他显著的不同。例如,下面是小说和非小说标题的字数直方图。

left — histogram of Fiction Titles : right — histogram of non-fiction titles

很明显,非小说类畅销书每个标题的字数分布更广。事实上,许多书的封面上只有一个词(例如,“Bossypants”,“Sapiens”,“Moneyball”,“Hunger”,“Freakonomics”)。

非小说类书籍的其他趋势

检查非小说标题中最受欢迎的词,我们看到重点较少是神秘事件,而更多是政治家的传记。这解释了“美国”和“总统”等词的常见用法(如“特朗普”和“肯尼迪”)。

Word Cloud of the most popular words in Nonfiction Book Titles

或许正是因为这种政治品质,非小说类的标题在后特朗普时代变得更加负面。随着时间的推移,绘制这些头衔的平均情绪(或积极性),我们看到 2016 年后急剧下降。

average sentiment of non-fiction titles per year (<0 has negative sentiment)

事实上,一些最负面的书名围绕特朗普时代的主题,并在过去 2 年出版。

Some example of political books with negative titles in the past 2 years.

其他发现——女性阅读更多的小说

美国国家艺术基金会的调查数据表明,女性阅读更多的小说作品,而男性则更关注非小说类书籍。在研究了小说类和非小说类畅销书的区别之后,我很清楚这个观察是正确的。

这一点最好通过比较 NYT 对他们畅销书的描述来看。我们先看看小说书。

小说词汇云

下面我列出了小说描述中最常见的词语。左边的云仅从图中删除了“The”和“a”。在右边,所有常见的英语单词都被删除,只留下独特的单词。

Word Clouds for the Descriptions of Fiction Bestsellers

很明显,畅销小说往往是' 系列丛书之一' ',极有可能是' 三部曲 '。通常涉及一个' 女人'——要么是一个' 律师 ,要么是一个' 代理人 。或者更好一点,一个' 神探 '。在' 她的 '旅途中,我们的主角将有可能' 调查 '一个' 杀手 '。也许是一个' 的案子 '一个' 的被害人的朋友 '或' 的旧爱 '。在这个过程中,她将' '回归到' '到'',挖掘' 秘密 ',' 发现'凶手* '甚至可能找到'【T75]她甚至可能会在这个过程中找到一个新的家庭。*

非虚构

非小说类畅销书的相同词云如下图。在左边,所有主要的英语停用词都被删除。在右边,它们被包括在内,但是“the”和“a”被删除。

***

Word Clouds for the Descriptions of Non-Fiction Bestsellers*

在非小说中,主角似乎更有可能是男性。 他的 '故事很可能是一个' 回忆录 ',一个' 传记 '或者干脆是他一生的' '记述 '可能他是一个' 美国总统 '。又或许他是一个' 记者 '或' 喜剧演员 '谁只想' 告诉 '他的’生活故事 '对于第一个'时间。他的书很可能会是' '幽默的 '和' 政治的 '。它可能是' 讨论'死亡 ',' 关系 ',' 家庭 '或' 战争 '。不管是哪种方式,他都一定会挥洒大量笔墨看着' '背影 ',看着他的'',讲述他的' '个人'故事* ',也许,还会抱怨他的' 母亲 '。***

最后的想法

传统观点认为,媒体主要是由消费者塑造的。尽管如此,阅读小说的人口比例仍在下降,而且越来越以女性为主。此外,互联网颠覆了旧的发行模式,为文学界的所有参与者创造了新的激励。这导致了一些有趣的趋势。小说标题越来越长,而非小说标题却没有。非小说类书籍变得越来越负面,而小说类书籍的趋势更加微妙(黑暗书籍的扩散)。最后,男性和女性在阅读习惯上似乎有所不同。随着我们在文化和政治上的分裂,我们的印刷媒体也应该效仿。

线性代数到深度学习 5 本书

原文:https://towardsdatascience.com/books-on-machine-learning-c99e77140270?source=collection_archive---------16-----------------------

我最喜欢的学习机器学习的书

Photo by Mads Schmidt Rasmussen on Unsplash

一些关于机器学习的最好的书籍在网上免费发布。我甚至认为,只要有一台笔记本电脑和互联网,你就可以学习任何关于它的知识——从最基本的线性代数到最先进的深度学习,甚至是强化学习。

在过去的几个月和几年里,通过利用网上所有的资源,我学到了很多东西。事实上,我所知道的关于机器学习的几乎一切都要归功于令人敬畏的计算机科学社区,当谈到分享知识时,他们是如此开放。现在我想回报一些东西。

如果你想研究机器学习或深度学习,如果你已经熟悉了基础知识,这篇博客中的书是你可以得到的最好的一些书。此外,这并不意味着是一个完整的列表,而是各种主题的精选资源的集合。有一本关于线性代数的书。一本是关于统计和概率的书。一个关于统计机器学习。最后两个关于深度学习。我尽可能地提供了链接。他们来了。

谢尔登·埃克斯勒正确地完成了线性代数

读这之前你需要的只是高中数学。在此基础上,这本书向你介绍了机器学习所需的向量和矩阵思维,甚至更多的深度学习。即使你不能马上明白为什么你会需要这些东西,线性代数确实是不可或缺的。我认为这本书让我很容易坚持下去。我在网上找到的版本有点旧,但这在这里真的无关紧要。

约翰·赖斯的数理统计和数据分析

概率和统计属于同一范畴。所以这本书教你们两个,前几章讲的是概率相关的内容,比如随机变量和分布,后几章讲的是估计和假设检验,我认为这是统计学的内容。由于机器学习本质上应用于概率和统计,了解它们很重要。

Trevor Hastie 等人的《统计学习的要素》

这绝对是关于经典机器学习及其所有常用算法的最全面、最有用的书籍之一。同一本书有一个稍微简化的版本,叫做统计学习导论,这是关于机器学习的第一本很棒的书。如果 ESL 的书太复杂或者 ISL 的书太简单的话,你可以把它们并排使用。

神经网络和深度学习,作者迈克尔·尼尔森

这本书带你从头开始学习神经网络,它做得非常好。它对反向传播的解释是我见过的最好的解释。这本书还涵盖了卷积神经网络(CNN),虽然没有那么广泛。这本书最大的好处是让你为下一本书做好准备,这本书要复杂得多。

Ian good fellow 等人的深度学习

如果上一本书相当于在深度学习的世界里学习如何骑自行车,这本书会教你如何驾驶卡车。它非常数学化,包含的内容比上一个多得多,包括 rnn 和许多我还远远不理解的更高级的东西。所以我也只看了一部分。无论如何,它可以说是神经网络方面最重要的书。第二部分特别有趣,因为它介绍了深度学习中使用的许多强大的架构。虽然很高级,但只要有一点数学天赋和毅力,这是可行的。

希望这些书可以帮助你更好地理解机器是如何学习的,无论你的水平或背景如何。但是如果你从零开始,你应该从线性代数和概率/统计开始,然后继续做机器学习,最后是深度学习。另一条建议是,一旦你已经掌握了基本知识,你就不需要从头到尾地阅读书籍,可以随意挑选那些你认为相关或感兴趣的章节。而如果某个东西还是太超前,就倒回去几章,以后再来讲。不要让它使你气馁。即使机器学习不是微不足道的,但留下来的想法和概念,就像许多神经网络一样,真的没有那么难。只需要一点数学和基本的编程技能就可以开始了。从这里开始,真的没有什么可以阻止你进行前沿的机器学习。

使用 Python 提高效率和处理 Excel 文件

原文:https://towardsdatascience.com/boost-your-efficiency-and-process-excel-files-with-python-cae650c85d6c?source=collection_archive---------8-----------------------

使用 Python 加载、转换、修改和保存 Excel 文件,以改进您的报告流程

做数据工作,就会接触 excel。即使你自己不使用它,你的客户或同事也会使用它。Excel 的伟大之处就在于它本身:适用于较小数据集的表格计算。但是我一直很讨厌那种有一百万行几百列的 excel 表格。这种工作簿速度慢,往往在一些计算后崩溃。所以我开始使用 python 来处理大型 excel 文件,这提供了另一个很大的优势:你可以创建可重复的代码并提供文档。让我们跳进来吧!

用 Python 读取 Excel 文件

我们要处理的文件包含近一百万行和 16 列:

Python 提供了read_excel()来读取 Excel 文件作为数据帧:

import pandas as pd
import numpy as np
df = pd.read_excel(...\\Excel-Tutorial.xlsx')

如你所见,到目前为止数据看起来很干净,但我们的列标题似乎是错误的。许多 excel 地图包含标题或其他信息来引导读者。我们可以跳过这部分,定义一个标题行:

df = pd.read_excel('…\\Excel-Tutorial.xlsx', header=[1]).reset_index()

参数header=[1]指定我们希望使用 excel 表格中的第二行作为标题。跳过所有以前的行。

用熊猫做一些计算

营销部门的一个典型问题可能是,我们每年在不同国家的销售额是多少:

我们在 86 毫秒内完成了这个计算。用 Python 处理 Excel 文件的一个很大的优点是,任何类型的计算都比在 Excel 中快得多。操作越复杂,速度优势越大。

另一个需求可能是销售部门需要按年份和类别分组的每个国家的数据。因为他们要向全国市场提供数据,我们必须将计算结果保存在不同的工作表中:

将结果保存为 Excel

下一步,我们想再次将文件保存为 Excel 格式,以便提供给销售和市场部。我们将创建一个pd.ExcelWriter对象并创建不同的工作表:

很容易,不是吗?让我们看看新创建的工作簿:

如你所见,我们的数据帧被正确保存到指定的工作表中。在我们把好的结果发给两个部门后,第二天我们就收到了一封邮件:他们要求一些格式化和可视化。因为我们每个月都必须转换这种数据,所以我们决定也用 Python 来执行这些任务。

格式化和可视化

要添加格式和可视化,我们必须再次创建一个 writer 对象:

如您所见,代码的第一部分与第一个示例中的相同。我们创建一个 writer 对象。xlsxwriter让我们访问 Excel 的功能,如图表和格式。为了访问这个特性,我们需要获得工作簿对象workbook = writer.book和工作表对象worksheet = writer.sheet['Sales_Sums']。在本例中,我们将在第一张纸上进行修改。我们添加一个图表,指定数据的范围(=Sales_Sums!$B$2:$B$7')并将其添加到工作表的单元格A9中。

同样,我们为销售数据添加格式。我们在范围B2:B7上添加了一个 3 色标,以在视觉上突出显示低值或高值。我们还调整了第一列和第二列的宽度worksheet.set_column(0,1,30)。我们还格式化了销售数据的列标题,并将其重命名为2019 Sales Data。最后一步,我们保存文件:

这个结果比 Excel 好得多,提供了一个很大的优势。下个月我们只需点击一下就能复制出完全相同的文件。

结论

Python 非常适合处理 Excel 文件。您可以更轻松地处理大文件,创建可重复的代码,并为您的同事提供文档。我们还看到了我们可以轻松访问 Python 的高级功能。您可以自动化整个报告流程。

延伸阅读:

创建图表:

[## 使用 Pandas 和 XlsxWriter 创建 Excel 图表

使用 Pandas 和 XlsxWriter 创建带有图表的 Excel 文件的介绍。

pandas-xlsxwriter-charts . readthedocs . io](https://pandas-xlsxwriter-charts.readthedocs.io/)

带有熊猫透视的 Excel 报表:

[## 从熊猫数据透视表生成 Excel 报表

上一篇数据透视表文章描述了如何使用 pandas pivot_table 函数在一个

pbpython.com](https://pbpython.com/pandas-pivot-report.html)

用 Python 格式化 Excel 文件:

[## 教程 2:向 XLSX 文件添加格式

在上一节中,我们使用 Python 和 XlsxWriter 模块创建了一个简单的电子表格。这转换了…

xlsxwriter.readthedocs.io](https://xlsxwriter.readthedocs.io/tutorial02.html)

如果您喜欢中级数据科学,并且尚未注册,请随时使用我的推荐链接加入该社区。

提升您的图像分类模型

原文:https://towardsdatascience.com/boost-your-image-classifier-e1cc7a56b59c?source=collection_archive---------12-----------------------

提高分类器准确性的技巧

图像分类被认为是一个即将解决的问题。有趣的部分是当你不得不使用你所有的狡猾来获得额外的 1%的准确性。我在参加 Analytics Vidhya 主办的 英特尔场景分类挑战赛时遇到过这样的情况。我非常喜欢这场比赛,因为我试图从我的深度学习模型中提取所有的汁液。下面的技术通常可以应用于手头的任何图像分类问题。

问题

问题是将给定的图像分为 6 类

Data Classes

我们收到了来自世界各地的各种自然场景的 ~25K 图片

渐进调整大小

它是一种技术,在训练 CNN 从较小到较大的图像尺寸的同时,顺序地调整所有图像的尺寸。渐进调整在他精彩的 fastai 课程“程序员实用深度学习”中有简要描述。使用这种技术的一个很好的方法是使用较小的图像大小(比如 64x64)训练一个模型,然后使用该模型的权重在 128x128 等大小的图像上训练另一个模型。每个较大比例的模型在其架构中结合了先前较小比例的模型层和权重。

Progressive Resizing

法斯泰

fastai 库是一个强大的深度学习库。如果 FastAI 团队发现一篇特别有趣的论文,他们会在不同的数据集上进行测试&研究如何对其进行调整。一旦成功,它将被纳入他们的图书馆,并随时可供其用户使用。该库包含许多内置的艺术(SOTA)技术。fastai 建立在 pytorch 类型的基础上,对于大多数任务(如果不是所有任务的话)都有很好的默认参数。一些技术是

  1. 循环学习率
  2. 单周期学习
  3. 结构化数据的深度学习

合理权重初始化

在检查可用的标准数据集时,我偶然发现了 Places365 数据集。Places365 数据集包含来自 365 个场景类别的 180 万幅图像。挑战中提供的数据集与该数据集非常相似,因此在该数据集上训练的模型已经学习了与我们自己的分类问题相关的特征。因为我们问题中的类别是 Places365 数据集的子集,所以我使用了用 places365 权重初始化的 ResNet50 模型。

型号砝码以 pytorch 砝码的形式提供。下面的实用函数帮助我们将数据正确地加载到 fastai 的 CNN 学习器中。

混合增强

混合增强是一种增强类型,其中我们通过两个现有图像的加权线性插值来形成新图像。我们取两幅图像,根据它们的张量对它们进行线性组合。

Mixup Augmentation

λ是从贝塔分布中随机抽样的。尽管论文的作者建议使用λ=0.4,但是 fastai 库中的默认值被设置为 0.1

Mixup Augmentation in fastai

学习速率调谐

学习率是训练神经网络最重要的超参数之一。 fastai 有办法找出一个合适的初始学习率。这种技术被称为循环学习率,我们以较低的学习率进行试验&以指数方式增加学习率,记录下学习过程中的损失。然后我们绘制损失与学习率的关系图&选择损失最大的学习率。

LR finder in fastai

Loss is steepest at 1e-06

该库还为我们自动处理带重启(SGDR)的随机梯度下降。在 SGDR,学习率在每个时期开始时被重置为最初选择的值,该值随着时期减少,如在余弦退火中。这样做的主要好处是,由于学习率在每个时期开始时被重置,学习者能够跳出局部最小值或可能陷入的鞍点。

SGDR in fastai

一般敌对网络

gan 是 Ian Goodfellow 在 2014 年推出的。gan 是由两个网络组成的深度神经网络架构,两个网络相互对立。GANs 可以模拟任何数据分布。他们可以学习生成与任何领域的原始数据相似的数据——图像、语音、文本等。我们使用 fast.ai 的 Wasserstein GAN 实现来生成更多的训练图像。

GANs 涉及训练两个神经网络,一个称为生成器,它生成新的数据实例,而另一个称为鉴别器评估它们的真实性,它决定每个数据实例是否属于实际的训练数据集。你可以在这里查阅更多关于它的

GAN generated sample images

去除混淆图像

训练神经网络的第一步是根本不接触任何神经网络代码,而是从彻底检查你的数据开始。这一步至关重要。我喜欢花大量的时间(以小时为单位)浏览数以千计的例子,理解它们的分布并寻找模式。

-安德烈·卡帕西

正如安德烈·卡帕西所说,“数据调查”是重要的一步。根据数据调查,我发现有一些图像包含 2 个或更多的类。

方法 1

使用以前训练的模型,我对整个训练数据进行预测。然后丢弃那些预测不正确但概率得分大于 0.9 的图像。这些是模型明显分类错误的图像。深入调查后,我发现这些图片被贴标签的人贴错了标签。

Confusing Images

我还从训练集中删除了那些预测概率在 0.5 到 0.6 范围内的图像,理论上图像中可能存在不止一个类别,因此模型为每个类别分配了大致相等的概率。通过观察这些图像,这个理论最终被证明是正确的

方法 2

fast.ai 提供了一个方便的小部件“图像清理器小部件”,允许您为模型清理和准备数据。ImageCleaner 用于清理不属于数据集的图像。它连续渲染图像,并让您有机会从文件系统中删除该文件。

测试时间增加

测试时间增强包括获取原始图像的一系列不同版本,并通过模型传递它们。然后从不同版本计算平均输出,并作为图像的最终输出。

Test Time Augmentation in fastai

以前也使用过一种类似的技术,叫做 10 作物测试。我第一次在 ResNet 报纸上读到关于 10 作物技术的报道。10 裁剪技术包括沿着四个角裁剪原始图像,沿着中心裁剪一次,得到 5 个图像。对它的倒数重复同样的操作,得到另外 5 幅图像,总共 10 幅图像。然而,测试时间增加比 10 作物技术更快

组装

机器学习中的集成是一种使用多种学习算法来获得比单一算法更好的预测性能的技术。组装效果最好

  1. 组成模型具有不同的性质。例如,将 ResNet50 和 InceptionNet 组合起来会比将 ResNet50 和 ResNet34 组合起来有用得多,因为它们在本质上是不同的
  2. 成分模型具有较低的相关性
  3. 改变每个模型的训练集;所以会有更多的变化

在这种情况下,我通过选择最大发生类来整合所有模型的预测。如果有一个以上的类出现次数最多,我会随机选择其中一个类。

结果

公共排行榜—排名 29 (0.962)

私人排行榜—排名 22 (0.9499)

结论

  1. 渐进调整大小是一个很好的开始。
  2. 必须花时间理解你的数据并将其可视化。
  3. 一个伟大的深度学习库,如 fastai,带有合理的初始化参数,肯定会有所帮助。
  4. 尽可能随时随地使用迁移学习,因为它通常会带来好的结果。最近,深度学习&迁移学习甚至被应用于结构化数据,所以迁移学习绝对应该是首先尝试的。
  5. 像混音增强,TTA,循环 LR 等最先进的技术肯定会帮助你提高 1%或 2%的准确率。
  6. 始终搜索与您的问题相关的数据集&如果可能的话,将它们包含在您的训练数据中。如果存在在这些数据集上训练的深度学习模型,则使用它们的权重作为模型的初始权重。

增压算法解释

原文:https://towardsdatascience.com/boosting-algorithms-explained-d38f56ef3f30?source=collection_archive---------2-----------------------

理论、实现和可视化

与许多关注单个模型完成的高质量预测的 ML 模型不同,boosting 算法试图通过训练一系列弱模型来提高预测能力,每个弱模型补偿其前任的弱点。

One is weak, together is strong, learning from past is the best

要理解 Boosting,关键是要认识到 boosting 是一个通用算法,而不是一个特定的模型。Boosting 需要您指定一个弱模型(例如回归、浅层决策树等),然后对其进行改进。

解决了这个问题,是时候探索弱点的不同定义和相应的算法了。我将介绍两种主要算法:自适应增强(AdaBoost)和梯度增强。

1.adaboost 算法

1.1 弱点的定义

AdaBoost 是一种专门为分类问题开发的提升算法(也称为离散 AdaBoost)。弱点由弱估计量的误差率来识别:

在每次迭代中,AdaBoost 识别错误分类的数据点,增加它们的权重(在某种意义上,减少正确点的权重),以便下一个分类器将额外注意使它们正确。下图说明了权重如何影响简单决策树桩(深度为 1 的树)的性能

How sample weights affect the decision boundary

现在确定了弱点,下一步是找出如何组合模型序列,使整体随着时间的推移变得更强。

1.2 伪代码

研究人员提出了几种不同的算法。这里我将介绍最流行的方法 SAMME,这是一种处理多分类问题的特定方法。(【朱,】邹,S. Rosset,T. Hastie,“多级 AdaBoost”,2009 )。

AdaBoost 使用增强的样本权重训练一系列模型,根据误差为各个分类器生成“置信度”系数α。低误差导致大α,这意味着在投票中更高的重要性。

the size of dots indicates their weights

1.3 Python 中的实现

Scikit-Learn 通过 SAMME (多分类的特定算法)提供了 AdaBoost 的一个很好的实现。

参数: base_estimator :对象,可选(默认=无)

构建增强系综的基本估计量。如果None,则基本估计量为DecisionTreeClassifier(max_depth=1)

n_estimators :整数,可选(默认值=50)

增强终止时估计器的最大数量。在完美匹配的情况下,学习过程会提前停止。

learning_rate : float,可选(默认=1。)

学习率将每个分类器的贡献缩小learning_rate

算法 : {'SAMME ',' SAMME。R'},可选(default='SAMME。r’)

如果是萨姆。那就用 SAMME。r 实升压算法。base_estimator必须支持类别概率的计算。如果是“SAMME ”,则使用 SAMME 离散增强算法。

random_state : int,RandomState instance 或 None,可选(默认为 None)

2.梯度推进

2.1 弱点的定义

梯度推进解决问题的方式有所不同。梯度增强不是调整数据点的权重,而是关注预测和实际情况之间的差异。

weakness is defined by gradients

2.2 伪代码

梯度增强需要微分损失函数,并且适用于回归和分类。我将使用一个简单的最小二乘法作为损失函数(用于回归)。分类的算法也有同样的想法,但是数学稍微复杂一些。( J. Friedman,贪婪函数逼近:梯度推进机)

Gradient Boosting with Least Square

以下是弱估计量 H 如何随时间推移而建立的可视化。每次我们将新的估计量(在这种情况下,max_depth =3 的回归树)拟合到损失梯度(在这种情况下,LS)。

gradient is scaled down for visualization purpose

2.3 Python 中的实现

同样,你可以在 Scikit-Learn 的中找到渐变提升函数。

回归:

损失 : {'ls ',' lad ',' huber ','分位数' },可选(默认='ls ')

分类:

损失 : { '偏差','指数' },可选(默认= '偏差')

其余的都一样

learning_rate : float,可选(默认值=0.1)

n_estimators : int(默认值=100)

梯度增强对过拟合相当稳健,因此较大的数量通常会产生更好的性能。

子样本:浮点型,可选(默认值=1.0)

用于拟合单个基础学习者的样本分数。如果小于 1.0,这将导致随机梯度增强。subsample与参数n_estimators交互。选择subsample < 1.0会导致方差减少,偏差增加。

标准:字符串,可选(default="friedman_mse ")

衡量分割质量的函数。

优势和劣势

  1. 易于解释:boosting 本质上是一个集合模型,因此很容易解释它的预测
  2. 预测能力强:通常 boosting > bagging (random forrest)>决策树
  3. 适应过度拟合:见本文
  4. 对异常值敏感:由于每个弱分类器都致力于修复其前任的缺点,因此该模型可能会过于关注异常值
  5. 难以扩展:因为每个评估器都是建立在它的前辈之上的,所以这个过程很难并行化。

总结

助推算法代表了一种不同的机器学习视角:将一个弱模型变成一个更强的模型,以修复其弱点。现在您已经了解了 boosting 的工作原理,是时候在实际项目中尝试一下了!

升压和 AdaBoost 解释清楚

原文:https://towardsdatascience.com/boosting-and-adaboost-clearly-explained-856e21152d3e?source=collection_archive---------2-----------------------

Time to visualize the full iceberg !

直观的解释

助推技术最近在 Kaggle 竞赛和其他预测分析任务中有所上升。我会尽量解释清楚 Boosting 和 AdaBoost 的概念。最初的文章发表在我的个人博客上:https://maelfabien.github.io/machinelearning/adaboost/

在本文中,我们将讨论:

  • 快速回顾一下装袋
  • 装袋的极限
  • 增压的详细概念
  • 计算中的升压效率
  • 代码示例

我最近为我正在关注和/或构建的一些教程创建了一个专门的 GitHub 库。我还添加了 ML recaps:

https://github.com/maelfabien/Machine_Learning_Tutorials

一、装袋的局限性

接下来,考虑一个二元分类问题。我们要么将观察分类为 0,要么分类为 1。这不是文章的目的,但为了清楚起见,让我们回忆一下装袋的概念。

Bagging 是一种代表“引导聚合”的技术。本质是选择 T 个 bootstrap 样本,在这些样本中的每一个上安装一个分类器,并并行训练模型。通常,在随机森林中,决策树是并行训练的。所有分类器的结果然后被平均到一个装袋分类器中:

Formula for a Bagging Classifier

这个过程可以用下面的方式来说明。让我们考虑 3 个分类器,它们产生一个分类结果,可能是对的,也可能是错的。如果我们绘制 3 个分类器的结果,那么在某些区域分类器会出错。这些区域用红色表示。

Example case in which Bagging works well

这个例子非常完美,因为当一个分类器错误时,另外两个是正确的。通过投票分类器,你获得了很大的准确性!但是正如你可能猜到的,当所有的分类器在相同的区域出错时,也有 Bagging 不能正常工作的情况。

出于这个原因,发现助推背后的直觉如下:

  • 我们需要依次训练模型,而不是训练并行模型
  • 并且每个模型应该关注先前分类器表现差的地方

二。升压简介

a.概念

上述直觉可以这样描述:

  • 在整套设备上训练 h1 型
  • 使用 h1 表现不佳的区域的夸大数据来训练模型 h2
  • 用 h1 ≠ h2 的区域的夸大数据训练模型 h3

我们可以按顺序训练模特,而不是按平行训练模特。这就是助推的本质!

Boosting 通过随时间调整误差度量来训练一系列低性能算法,称为弱学习器。弱学习者是错误率略低于 50%的算法,如下图所示:

A weak classifier, achieving just under 50% error rate

b.加权误差

我们如何实现这样的分类器?通过在整个迭代中加权误差!这将给予先前分类器表现不佳的区域更多的权重。

让我们考虑 2D 图上的数据点。他们中的一些会被很好地分类,其他的不会。通常,当计算错误率时,归因于每个错误的权重是 1/n,其中 n 是要分类的数据点的数量。

Unweighted Errors

现在,如果我们对误差施加一些权重:

Weighted Errors

您现在可能会注意到,我们对没有很好分类的数据点给予了更多的权重。下面是加权过程的一个示例:

Example of weighting process

最后,我们希望构建一个强大的分类器,可能如下所示:

Strong Classifier

c.树桩

你可能会问,一个人应该实现多少个分类器才能让它正常工作?每一步是如何选择每个分类器的?

答案就在所谓树桩的定义里!树桩定义了一个一级决策树。主要思想是,在每一步,我们想找到最佳的树桩,即最佳的数据分割,使总误差最小化。你可以把一个树桩看做一个测试,其中的假设是,位于一侧的所有东西都属于 1 类,位于另一侧的所有东西都属于 0 类。

树桩可能有多种组合。让我们看看在这个简单的例子中有多少种组合?让我们花一分钟来数一数。

3 data points to split

嗯,答案是……12!这可能看起来令人惊讶,但却很容易理解。

12 Stumps

我们可以进行 12 种可能“测试”。每条分隔线边上的“2”简单地表示这样一个事实,即在一边上的所有点可能属于类 0 或类 1。因此,有两个测试嵌入其中。

在每次迭代 t 时,我们将选择 ht,即通过最大程度地降低总体错误率来最好地分割数据的弱分类器。回想一下,差错率是一个修改后的差错率版本,它考虑了之前介绍的内容。

d.寻找最佳分割

如上所述,通过在每次迭代 t 识别最佳弱分类器 ht,通常是具有 1 个节点和 2 个叶子(树桩)的决策树,找到最佳分裂。假设我们试图预测一个想借钱的人是否会是一个好的还款人:

Identifying the best split

在这种情况下,在时间 t 的最佳分割是保留支付历史,因为这种分割产生的加权误差最小。

请注意,像这样的决策树分类器实际上可能比简单的树桩更深。这将是一个超参数。

e.组合分类器

下一个逻辑步骤是将分类器组合成一个符号分类器,根据一个点将位于边界的哪一侧,它将被分类为 0 或 1。这可以通过以下方式实现:

Combining classifiers

你认为有可能改进分类器的方法吗?

通过在每个分类器上增加权重,避免对不同的分类器给予相同的重要性。

AdaBoost

f.包装它

让我们用一小段伪代码来总结一下到目前为止我们所介绍的内容。

Pseudo-Code

需要记住的关键要素是:

  • z 是一个常量,它的作用是将权重归一化,使它们加起来等于 1!
  • αt 是我们应用于每个分类器的权重

我们完事了。这个算法叫做 AdaBoost 。为了完全理解所有的升压方法,这是需要理解的最重要的算法。

三。计算

Boosting 算法训练起来相当快,这很好。但是既然我们考虑了每一个可能的残肢并且递归地计算指数,为什么它们训练起来很快呢?

好吧,这就是奇迹发生的地方。如果我们适当地选择αt 和 Z,那么在每一步应该改变的权重简化为:

Weights after choice of α and Z

这是一个非常强的结果,并且它与权重应该随着迭代而变化的说法不矛盾,因为被错误分类的训练样本的数量下降了,并且它们的总权重仍然是 0.5!

  • 没有要计算的 Z
  • 没有α
  • 无指数

还有另一个技巧:任何试图分割两个分类良好的数据点的分类器都不会是最佳的。甚至不需要计算。

四。我们来编码吧!

现在,我们将通过一个手写数字识别的简单例子来快速了解如何在 Python 中使用 AdaBoost。

现在让我们加载数据:

x 包含长度为 64 的数组,这些数组是简单的扁平 8×8 图像。这个数据集的目的是识别手写数字。让我们来看看一个给定的手写数字:

8x8 image of a handwritten “4”

如果我们坚持深度为 1(树桩)的决策树分类器,下面是如何实现 AdaBoost 分类器:

它应该会取得 26%左右的成绩,这一成绩还有很大的提高空间。关键参数之一是顺序决策树分类器的深度。准确性如何随着决策树的深度而提高?

在这个简单的例子中,深度为 10 时达到最高得分,准确率为 95.8%。

四。结论

已经讨论过 AdaBoost 是否过拟合。最近,它被证明在某些点上过度拟合,人们应该意识到这一点。AdaBoost 也可以用作回归算法。

AdaBoost 广泛用于人脸检测,以评估视频中是否有人脸。关于这个话题我很快会再做一篇文章!在下一篇文章中,我们还将介绍渐变提升:)

我希望这篇文章清楚地介绍了 AdaBoost 的概念,并且现在对你来说已经很清楚了。如果您有任何问题或评论,请不要犹豫,发表评论。

参考资料:

[1]https://www . coursera . org/lecture/ml-classification/learning-boosted-decision-stumps-with-AdaBoost-bx5YA

[2]https://ru . coursera . org/lecture/ml-class ification/learning-boosted-decision-stumps-with-AdaBoost-bx5YA

3https://www.youtube.com/watch?v=UHBmv7qCey4

使用人工智能提升我们的教育系统和劳动力

原文:https://towardsdatascience.com/boosting-our-educational-system-and-our-workforce-using-ai-a676afacb9cd?source=collection_archive---------24-----------------------

Photo by Ian Schneider on Unsplash

在任何国家,最重要的资源是人力资本。熟练的劳动力和运转良好的教育体系是高附加值服务的基础。随着人工智能的扩散,我们预计现有的工作实践将被打破,从而不仅创造新的机会,也带来新的挑战。

在过去的一年里,我们看到了很多预测。一些专家预测,在未来几年,大约 40%的工作岗位将会消失。其他人说人工智能革命将创造数百万个新岗位,其中一些甚至还没有被发明出来。

Image: World Economic Forum

这没有什么新鲜的。如果我们看一看银行推出自动柜员机时的情况,我们可以看到类似的模式。随着自动取款机的使用,许多人预测银行出纳员的时代将会结束。然而,统计数据显示并非如此。1985 年,美国有 6 万台自动取款机和 48.5 万名银行出纳员。2002 年,自动取款机的数量增加到 352,000 台,银行出纳员的数量增加到 527,000 名。

我们对此的解释是,许多人发现使用新机器很方便;因此,银行交易的数量开始激增。另一方面,银行开始关注更好的客户服务;从而为他们的分支机构增加更多的员工来处理更复杂的任务。我们也可以在今天的网上银行中看到这种模式。尽管一些银行关闭了几家分支机构,90%的交易都在网上进行,但美国银行员工的数量实际上是一样的。这证明了这不仅仅是自动化接管人类工作的问题。

将会发生什么的真相很可能介于两者之间。让我们明确一点,在大多数情况下,AI 不会接管工作,但它会自动执行该工作内的特定任务。实质上,就业市场将发生如下变化:

  • 有些工作将会过时,比如开车。无人驾驶汽车将能够在不需要人类司机的情况下运送人员和货物。
  • 有些工作受 AI 影响不会太大,比如护理。在护理行业中,人的因素仍然是至关重要的。
  • 一些新的工作将会被创造出来,比如器官创造者,他们的角色将会是从有机材料中开发器官和身体部分。
  • 许多现有的工作将永远改变。这些工作从低收入的工作如店员到高收入的工作如律师。人工智能将增加他们的任务,以使他们更安全,更快,更精确。

为了准备这场革命,我们需要帮助今天和明天的工人适应和获得新技能。我们可以通过实施以下措施来实现这一目标:

总人口

Photo by mauro mora on Unsplash

任何人工智能战略的第一步都是告知公众人工智能如何显著改善他们的生活质量。马耳他进行的一项调查。人工智能特别工作组发现,尽管 60%的受访者听说过人工智能,但他们并不了解它到底是什么。最初,只有 42%的受访者认为他们与人工智能系统互动过,但当他们面对具体的例子时,这一数字飙升至 80%。人们没有意识到他们正在使用人工智能,因为计算机系统没有明确提到它。因此,帮助人们理解如何识别人工智能系统是至关重要的。这样做,他们可以利用它的潜力,同时摆脱他们可能有的潜在恐惧。

为了解决这个问题, 政府将发起一场全国性的人工智能意识运动 ,旨在让人们放心,并帮助他们建立对人工智能的信任。

劳动力

Photo by Josue Isai Ramos Figueroa on Unsplash

考虑到对就业市场的影响可能相当复杂, 将成立一个智囊团 来解决这些问题。它的作用将是开展研究,提出具体行动,在不同利益攸关方之间开展对话,制定培训路径和起草潜在的激励措施。这样做,我们希望确定未来的技能差距,并帮助受影响行业的工作人员提高技能。

弱势工人也将受益于国家再培训计划,该计划旨在通过短期课程和在职培训帮助他们发展新的数字技能。 还将支持雇主 利用外部培训计划。为此,我们将利用由欧洲社会基金(ESF)资助的€500 万英镑“投资于技能”方案。

教师

Photo by Polargold on Unsplash

教育工作者是积极创造未来劳动力的人。正因为如此,他们必须 配备最好的人工智能工具 旨在协助他们(但不产生任何额外负担)。 人工智能组件将被引入课程 导致教学学位,从而确保新教师得到良好的装备。另一方面,知名教育工作者将被告知与他们有关的新发展,从而使他们意识到存在的不同机会。 各级培训也将提供 。希望从国外获得认证的教育工作者也可以通过 财务报销计划 获得认证。

每年,教育部计划组织一次关于人工智能教育的年度会议,旨在实现这些目标,同时也庆祝良好的实践。通过国际专家的参与,先进的教学方法将立即传播给马耳他的教育工作者。

学生

Photo by Nicole Honeywill on Unsplash

还将推出针对学生及其家庭的不同举措。这些包括但不限于:

  • 人工智能家庭挑战赛 是一个家庭、学校和社区在导师的指导下共同努力使用人工智能解决挑战的计划。
  • AI 主题周末 和各年龄段孩子的动手工作坊。
  • 人工智能奥林匹克竞赛 旨在挑战学生使用人工智能解决现实世界的问题。获胜的队伍将参加全球人工智能大会

学校也将受益于个性化人工智能学习系统的部署。 教育 AI 系统 将管理义务教育阶段儿童的升学情况;定制他们的道路,为他们提供渐进的个性化学习曲线。

从管理的角度来看,人工智能将被引入所有级别,从而有助于数据的收集和汇总。然后, 人工智能管理系统 将预测分析趋势,帮助决策者做出明智的决定。这种系统的结果可能是多种多样的;例如推出新的儿童政策或干预措施,而这些政策或措施并没有在教育系统中取得应有的进展。当然,这项措施是一个长期目标,只有在教育工作者、工会、家长、学生和其他利益相关者的积极参与下才能实现。

所有这些项目都将由一个专门的工作组负责,该工作组的任务是在全国范围内将人工智能引入教育。

毕业生和研究生

Photo by Logan Isbell on Unsplash

马耳他大学在 AI 方面已经走在前列。人工智能系起源于 90 年代初,在过去的几年里,其课程的学生人数大幅增加。然而,不管他们的研究领域是什么,毕业生理解人工智能的好处是至关重要的。正因为如此,马耳他大学将在不同院系开设的所有课程 中开设 AI 选修课。

此外,该大学将推出一个 人工智能平台 ,这是一个大学内部的跨学科实体,旨在促进不同院系和机构在未来几年的合作。这样一来,该大学将能够增加学生、学者、研究领域和专业的数量。它还将促进与公共和私人组织的合作,从而加速人工智能的意识。

马尔他艺术、科学和技术委员会(MCAST) ,也将在其所有课程中引入必要的人工智能组件。它还将在未来五年推出专门针对人工智能的研究生课程。**

教育部还将支持民办高等教育机构,帮助其 开发 AI 相关模块

为了保持这一势头,政府还将每年提供 50 个奖学金 来帮助更多的学生从事研究生水平的人工智能研究。此外,高等教育奖学金计划(TESS)仍将用于 支持海外留学学生 。此外,任何获得硕士或博士学位的人将有资格获得分别为期一年或两年的(收入的第一个€6 万英镑)。

前方的路

Photo by Xan White on Unsplash

还有很长的路要走。这将有助于我们缩小教育差距,确保每个人都充分发挥自己的潜力,支持处于危险中的儿童,重新培训我们的劳动力,塑造未来的专业人士。这并不容易,前方的路将带领我们探索未知的领域。可以肯定的是,我们正朝着把马耳他变成人工智能发射台的正确方向前进。我们不仅在努力用人工智能来塑造我们的岛屿,而且在未来的几年里也在努力塑造我们邻近的大陆。

AI 战略的完整文档可以在这里下载https://Malta . AI

AI 策略的总结可以在这里找到!

阿列克谢·丁力教授 是马耳他大学的 AI 教授。二十多年来,他一直在人工智能领域进行研究和工作,协助不同的公司实施人工智能解决方案。他的工作被国际专家评为世界级,并赢得了几个当地和国际奖项(如欧洲航天局、世界知识产权组织和联合国等)。他出版了几本同行评审的出版物,并且是马耳他的一部分。由马耳他政府成立的人工智能工作组,旨在使马耳他成为世界上人工智能水平最高的国家之一。

使用谷歌云数据目录推进数据治理之旅

原文:https://towardsdatascience.com/boosting-the-data-governance-journey-with-google-cloud-data-catalog-d67acc3e3ffb?source=collection_archive---------24-----------------------

关于 Google Cloud 中数据发现和元数据管理的思考

Photo by Jesse Bowser on Unsplash

我们生活在信息时代,我相信没有人不同意公司现在可以访问前所未有的大量数据。因此,从可靠性角度管理数据资产自然变得越来越复杂。

我所说的管理数据资产是指:

  • 寻找负担得起的储物解决方案;
  • 使用最合适和最新的信息进行业务绩效和营销分析;
  • 授予消费者适当的访问权限;
  • 遵守隐私法规,如 GDPR、HIPAA 和 CCPA

—仅列出一些挑战。

我敢打赌,与数据管理相关的讨论是目前企业对话中的五大问题之一,我经常将它们视为更大问题的一部分,名为数据治理。不幸的是,尽管对数据治理的兴趣在过去几年中显著增长,但是没有一个通用的解决方案可以解决所有方面的问题。

在这条漫长的道路上,有指导公司的原则和最佳实践。然而,尽管人们可能会找到任何高层次的指导,但我已经认识到(自从我开始从事数据治理工作以来),对于大多数公司来说,确定合适的工具来解决每个元素仍然是一个挑战。话虽如此,让我们来看看常见的数据治理构建块:

50 most common words compiled from a bunch Data Governance related documents I’ve read in 2019 (thanks jasondavies.com/wordcloud for the amazing word cloud generator!)

现在,请看看谷歌云数据目录的文档。可能你已经注意到了上图中突出显示的大多数单词在那里都用得很多。这是因为数据目录无疑由治理基础工具组成,这意味着选择合适的目录解决方案增加了数据治理之旅的成功机会。

让我们深入了解该产品如何适应数据治理环境!

数据发现

数据分布在多个数据源和格式上,从数据仓库到流媒体渠道……数据目录目前处于测试版,并原生集成到 3 个最常用的谷歌云数据处理和存储工具中: BigQueryPub/SubStorage

此处的“本地”是指,一旦您在组织的某个 GCP 项目中启用了数据目录,并向用户和/或服务帐户授予了正确的 IAM 角色,由这些服务管理的资产就可以被编入索引并通过目录被发现。BigQuery 数据集、表和视图以及发布/订阅主题会被自动索引,而存储桶需要用户定义的配置

随后,列出所有 BigQuery 资产就是执行搜索的问题,这可以通过使用 Data Catalog 的 UI 或 API 来完成。就像选择一个复选框一样简单,如下图所示:

BigQuery assets search in the Data Catalog UI

相同的用例适用于发布/订阅和存储资产。此外,数据分析师可以利用类似 Gmail 的搜索机制,使用广泛而灵活的搜索语法来细化他们的查询,该搜索语法可以处理简单的关键字和限定谓词。

分类和元数据

数据发现为治理增加了巨大的价值,但是当处理太多数据时,即使是最有经验的分析师也会迷失方向。那么,个人或第三方系统如何检查数据源是否可信呢?它的数据是最新的吗?它的数据从哪里来?有什么机密信息吗?发现机制本身通常不会回答这些问题,或者只是部分地回答。这里,数据分类登场了。

可以根据多个方面对数据进行分类:存储类型、质量、可信度、法规遵从性、弃用状态等等。数据目录提供了基于模板和标签的可定制分类机制,允许用户以各种形式对其数据进行分类。

它从集成系统中读取的信息集,加上用户提供的用来丰富其分类模式的信息,被称为元数据对于 Data Catalog 的用户来说,这是一个重要的概念,因为系统不会存储任何属于索引资产的数据。数据目录仅存储和管理元数据。

下图显示了从 BigQuery 收集的关于给定表的信息数据目录的示例。它代表了所谓的技术元数据。这种元数据通常由源系统管理,不直接由用户更改。

Technical Metadata example

另一方面,下图显示了一种与[虚构的]公司业务严格相关的元数据——毫不奇怪,所谓的业务元数据

Business Metadata example

请注意突出显示的字符串:它们指的是根据审计清单和法规遵从性对 BigQuery 资产进行分类的模板。这种模板可以用来对尽可能多的资产进行分类,以便在所有资产之间保持业务元数据的组织和标准化。

快速提示:通过使用 Data Catalog 的 API,可以构建简单的代码来自动化创建和更新标签的过程,正如我在这个资源库中展示的:【https://github.com/ricardolsmendes/datacatalog-tag-manager】

数据管理

虽然 Data Catalog 实际上并不访问数据,但它确实是一个数据管理工具。举个普通的例子,它的标记机制可能被数据公民用来跟踪数据。它存放在哪里?用哪个系统来管理?可能会存档甚至删除吗?

精心设计的“模板+标签数据管理模式”当然可以利用 Data Catalog 的搜索功能(已经在数据发现部分提到过),因为资产可以通过它们的标签轻松找到,从而建立一个数据管理框架。我的意思是:可以通过用来创建附加到资产上的标签的模板和标签的值来找到资产。看看tag搜索限定符文档,看看它是如何工作的:

The tag search qualifier (https://cloud.google.com/data-catalog/docs/how-to/search-reference)

想想看,创建一个带有archive_atdelete_at字段的模板是可能的。这种模板可用于将标签附加到数据资产。适当的查询允许数据管理器(为什么不允许自动化过程?)使用数据目录来查找哪些资产包含要在给定日期存档或删除的数据,以便可以对这些资产采取行动。然后,我会说“数据目录支持基于元数据的数据管理”。有道理?

目录

所有上述特征和元数据构建了一个目录。尽管我们正在讨论服务的名称,“cat a log”可以定义如下:名词——系统地排列的带有描述性细节的项目的完整枚举。所以,是的,我们可以检查数据治理的目录组件!

不仅如此,在这种情况下,目录还包含对当今企业至关重要的技术方面:

  1. 它是基于云的;
  2. 它可以按需扩展:无论你公司的数据仓库和数据流有多大,元数据都会得到适当的管理;
  3. 用户按量付费:谁用的多,付费就多;谁用的少,付的就少。

Pricing overview — effective January 22, 2020 (https://cloud.google.com/data-catalog/pricing)

最后,从为所有公司元数据构建集中存储库的意义上来说,它提高了透明度。拥有正确证书的人将拥有所有公司资产元数据的真实来源,让参与数据治理计划的各方清楚底层数据发生了什么。

多用户参与选项

在结束之前,说几句关于用户参与度的话。数据公民拥有独特的技能组合。无论您擅长编程还是在使用 GUI 组件时表现更好,您都能够利用数据目录获得更好的治理体验。

我相信这一点,因为该产品既可以从本机 UI 使用,也可以从 API 使用。对于那些不想编码的人来说,用户界面可以在 https://console.cloud.google.com/datacatalog找到。对于开发人员来说,可以通过简单的 REST 调用或使用惯用的客户端库来访问 API,这促进了代码的整洁并降低了错误率(基于我的个人经验)。目前,客户端库可用于 Python、Java 和 NodeJShttps://cloud . Google . com/data-catalog/docs/reference/libraries

顺便说一下,我个人的偏好是利用客户端库尽可能地自动化与目录相关的任务。

最终考虑

嗯,我在第一段提到了可靠性。当然,可靠性是主观的,但是我试图将例子和想法与数据治理概念和数据目录特性联系起来。这种混合中的特性与概念相匹配的方式使我依赖 Google Data Catalog 作为一流的元数据管理工具。我不打算在这里下定论,但是我希望这篇文章能够帮助公司决定何时在一个或另一个解决方案之间设计他们的数据治理策略。

正如我在本文中强调的,数据目录并不适合所有的数据治理需求。然而,作为谷歌云平台的一部分,它可以与其他 GCP 本地产品一起使用,以满足更多需求,如存档加密访问控制

如果你决定采用这种方法,请成为我的客人来交流知识和经验。

就这些了,伙计们!

参考

使用 vim+tmux 提升您的数据科学工作流程

原文:https://towardsdatascience.com/boosting-your-data-science-workflow-with-vim-tmux-14505c5e016e?source=collection_archive---------7-----------------------

Photo by SpaceX on Unsplash

和大多数同行一样,我在 Jupyter 生态系统中开始了我的数据科学职业生涯。Jupyter 是一个很好的环境,易于设置,提供了有用的内置功能。

在某些时候,我仍然觉得我需要超越。笔记本固有的一些限制开始扼杀我的生产力。仅举几个例子:

  • 笔记本的版本控制是有问题的。我一直害怕将包含客户数据的笔记本输出发送到网上。此外,在代码实际上没有改变的情况下,让 git 跟踪输出修改是非常不方便的。
  • 尽管最近取得了一些进展,但是在 Jupyter 环境中,像高级搜索和替换这样的编辑功能仍然非常有限。
  • 当项目变大时,同时打开几个笔记本是很常见的。从一台笔记本浏览到另一台笔记本是一件痛苦的事情,尤其是当它们隐藏在互联网标签的海洋中时。浏览器是用来搜索的,不是为了代码而开发的!

因此,我积极寻找替代方案,幸运的是,我遇到了一群很酷的家伙,他们教会了我老式的代码开发方式。它依赖于 vim + tmux 组合,该组合结合了一个强大的终端嵌入式编辑器和一个多路复用器。它们一起提供了高级编辑功能以及数据浏览所需的交互性。此外,该工作流程可以完全通过键盘操作,从而节省了大量时间,因为您不再需要不断地在键盘和鼠标之间切换。

你可能想知道为什么我没有考虑使用像 Pycharm 这样的 IDE。嗯,有两个主要原因。首先,ide 不是真正可移植的,作为一名顾问,我倾向于在许多不同的环境中工作。其次,也是更重要的一点,在黑屏上工作看起来更酷,你可以执行代码,以(几乎)思考的速度从一个窗格移动到另一个窗格。

这篇文章首先旨在指导您建立一个基于 vim + tmux 的基本但实用的数据科学环境。我还将展示这样的设置如何提高您的项目生产率。

免责声明:要阅读这篇文章,你需要对 vim 有基本的了解。如果你是个彻头彻尾的新手,也许可以先看看这篇 文章 再回来。

Tmux

Tmux 是一个命令行工具,可以在一个终端窗口中启用多个窗口和窗格。技术上,它被称为多路复用器。安装就像sudo apt-get install tmux一样简单。然后,您可以使用以下内容创建第一个会话:

tmux new -s mycoolproject

在一个会话中,您可以使用前缀命令ctrl+b和一些特定的键来控制窗口和窗格。例如,ctrl+b “产生窗口的水平分割。然后,您可以使用ctrl+b arrows在窗格之间导航。

tmux 的一大优势是它允许我们并行运行多个会话。这对于在不同项目之间快速切换非常方便,不会有弄乱脚本的风险。您可以使用ctrl+b d脱离当前会话,使用tmux ls列出现有会话,并使用tmux a -t <session name>连接到不同的会话。

Quick overview of tmux capabilities.

定制 tmux 相当容易,您只需要编辑位于您的主目录中的配置文件.tmux.conf。例如,许多人喜欢将前缀命令重新绑定到ctrl+a

我的目的只是在这里提供一个 tmux 的简要概述,但是如果你想了解更多,还有很多很棒的教程。这个小抄也值得看一看。

❤️维姆❤️

我喜欢维姆。真的。Vim 是那些像黑咖啡、周日早晨慢跑或戈达尔电影一样的东西之一,起初可能会觉得有点刺耳,但随着时间的推移和练习,它会变得越来越令人愉快。

有人说学习曲线很陡。是真的。但是,当你开始掌握新的快捷方式或宏来大大提高你的生产力时,这也是非常有益的。

Vim 是一个高度可定制的文本编辑器,直接嵌入在终端中。默认情况下,Vim 存在于所有类似 Unix 的系统中。无需安装。基本配置的功能有限,但您可以快速添加功能(如语法突出显示、自动完成等..)通过调整或添加插件到.vimrc,配置文件位于您的主目录中,在启动编辑器时加载。

我在这个回购中做了一个简单的.vimrc。它将帮助您重复下面描述的步骤。然而,我强烈建议建立自己的配置文件,以便更好地感受 vim 的精神。

在本教程中,我们将使用三个插件:

  • vimux ,使 vim 能够与 tmux 交互
  • vim-pyShell ,一个专门为简化 ipython 的使用而设计的 vimux 包装器
  • vim-cellmode ,ipython 的类 matlab 代码块执行

安装插件最简单的方法是通过插件管理器。我个人使用 vim-plug ,但是还有很多其他好的选择。

Vim-plug 易于安装。它只需要一个 bash 命令:

curl -fLo ~/.vim/autoload/plug.vim  [https://raw.github.com/junegunn/vim-plug/master/plug.vim](https://raw.github.com/junegunn/vim-plug/master/plug.vim)

然后你只需要在call plug#begin()call plug#end()之间的.vimrc中指定想要的插件,如下图所示。

First lines of .vimrc

要安装插件,打开.vimrc执行命令:PlugInstall。然后重启 vim 来获取配置文件。

代码执行

一旦我们的插件启动并运行,我们就可以开始从 vim 向终端发送指令。

在 tmux 会话中,用 vim 打开一个 python 脚本。在正常模式下,您可以使用命令:call StartPyShell()从新安装的插件中调用专用函数来启动 ipython 终端。默认情况下,这将在屏幕底部创建一个窗格,并启动一个 ipython 会话。

代码可以通过以下方式执行:

  • 逐行发送指令。为此,将光标移动到所需的行并运行命令:call RunPyShellSendLine()
  • 发送用##{/##}分隔的代码块。在这种情况下,转到程序块并调用RunTmuxPythonCell(0)

Sending commands directly from vim to the shell with vimux

这已经很酷了,但它实际上需要相当多的输入。我们能做得更好吗?

通过相关映射提高您的生产力

自动化重复性任务。这是缩短开发时间从而提高生产力的秘密。好消息是 vim 真的很擅长这个。

主要思想在于为最常见的任务创建映射。让我们仔细看看如何实际实现映射。同样,这是在.vimrc中完成的。在下面的代码片段中,第 2 行和第 3 行分别将快捷键,ss,sk映射到 ipython 启动和停止命令,而第二个块定义了代码执行的映射。

众所周知,数据科学中的大部分时间都用于数据准备。这一步严重依赖于数据帧操作。因此,定义与基本操作相关的映射,如:

  • 打印数据帧的第一个元素:,sdh
  • 打印数据帧信息:,sdi
  • 绘制数据帧的内容:,spp
  • 显示直方图:,sph
  • 显示变量的内容:,so
  • 获取一个 iterable 的长度:,sl

会为你节省很多时间吗?此外,由于检查是通过将光标下的变量/对象传递给后端函数来执行的,因此不会因为大量的打印和输出而污染您的脚本。不需要额外的输入。

让我们看看这些映射是如何工作的!

Few mappings were sufficient to really boost my productivity!

总结想法

将 vim 的高级编辑功能与一些设计良好的映射结合起来,确实提高了我的生产率。这个工作流程帮助我满足了工作中固有的紧迫的最后期限。的确,它需要大量的初始投资,但我相信,从节省时间和工作舒适度来看,回报要高得多。

让我对 vim 惊叹不已的是无穷无尽的定制可能性。所以要有创意,开始破解.vimrc并实现你自己的映射!

感谢阅读!如果你喜欢这类内容,你可能也会对这个帖子感兴趣。请随意关注我的 Medium ,不要错过我的下一篇关于如何在数据科学中使用 vim 的文章。你也可以通过使用我的附属链接加入 Medium 来支持我的写作。

自助抽样

原文:https://towardsdatascience.com/bootstrap-sampling-31bc54e7193a?source=collection_archive---------24-----------------------

无论何时处理数据,您应该做的第一件事就是调查相关的统计属性。特别是,您可能有兴趣知道您的数据是否遵循已知的分布。

为什么这很重要?想想你的数据分析的目标:一旦你有了一个观察样本,你想计算一些统计数据(即均值、标准差……),以及建立置信区间和进行假设检验。为此,您需要假设您的数据遵循已知的分布,如正态分布、X 平方分布或 T-student 分布。

不幸的是,大多数时候你的数据是在没有已知分布的情况下呈现给你的,因此你不知道它们的密度函数的形状。在这里,Bootstrap 抽样提供了帮助:这种技术的目的是在不知道潜在分布形状的情况下评估其统计数据和属性。

它是如何工作的?想象一下,给你提供了一组数据(你的人口),你得到了一个大小为 n(T1)的样本。

现在,如果你对你的初始样本进行 B 次重采样(你可以把 B 设置成你想要的大小。一般来说,它被设置为等于或大于 10000),您将生成 B 个进一步的样本,每个样本的长度为 n (有可能出现一个或多个重复的值)。

现在,对于每个样本,您可以计算感兴趣的参数的估计值。这将是每个样本 T( x^ 1)的通用函数,我们称之为θ̂1.

现在,这个想法是,如果我们收集所有我们计算的统计数据,我们可以生成一个初始人口的概率函数的近似值。近似分布的一个标准选择是观测数据的经验分布函数

在统计学中,经验分布函数是与样本的经验测量相关的分布函数。它是一个累积分布,在每个 n 数据点上跳跃 1/ n 。在公式中:

其中 1 为指示函数,其二进制值为 1(如果 xi 小于 t )或 0(如果 xi 大于 t )。直觉上,它是一个“经验”CDF:事实上,我们不知道 x 小于 t 的概率,然而每当 x 实际上小于 t 时,该函数就将其值增加 1/ n 。这个函数的形状是这样的:

所以,你能做的是使用这个经验函数,而不是概率分布,来计算相关的统计数据和置信区间。此外,如果 n (每个样本的大小)足够大,您可以用正态分布来近似您的估计的概率分布,得到:

Bootstrap 抽样是一种强大的技术:同样,从一个未知的分布,您可以近似一个概率分布,以便您可以计算相关的统计数据。

启动 ML 项目——使用声音对风扇故障进行分类

原文:https://towardsdatascience.com/bootstrapping-an-ml-project-using-sound-to-categorise-fan-failures-9ce04694ee85?source=collection_archive---------30-----------------------

有时候,与其瞄准宏伟的计划,不如先做些简单有趣的事情来证明它是可行的。

Start a project to only cover the core essentials first. Photo by LUM3N on Unsplash

我什么意思?

任何开始数据科学项目的人通常都会对其潜力感到兴奋,并会伸手摘星星,在你知道之前,你已经有了一个极其雄心勃勃和复杂的项目,但你不知道从哪里开始。结果是你永远不会开始,因为你永远不会得到足够的“钩子”。

注意:如果你想直接进入机器学习项目,那么可以随意跳过。

钩子?

就像你需要一条鱼咬住鱼钩,这样你才能成为一名成功的渔夫,在你认为你能成功之前,这些事情你都需要先咬上一口。因此,例如,如果您要制作一个仅在有人走过时(而不是车辆、宠物、树叶或野生动物)才打开的安全摄像头,那么过一会儿您就会看到以下列表:

  • 夜视摄像头(因为安全灯关闭时它看不见)
  • 一盏红外线灯照亮该区域,以便摄像机可以看到它
  • 安全灯
  • 能够以足够快的速度处理帧的便携式设备或计算机
  • 一个特殊的额定电源电压开关,可以使用便携设备的 GPIO 引脚打开和关闭
  • 外部配件,包括防水盒和处理设备的电源接口
  • 相机上记录的大量数据可以用来训练你的模型
  • 标记所有的数据,这样它就知道一个人是用来训练你的模型的

唷!这是一个很长的列表,这只是我从几分钟内得到的,我们甚至没有讨论我们将使用什么机器学习解决方案或输出或控制系统来设置它。

你现在可以看到为什么有人可能永远不会开始这样做,通常这种类似的想法是阻止公司投资数据科学的原因。给他们一个巨大的工作量估计来实现他们的宏伟愿景,他们可能会看起来病得像条狗并要求你离开。

让这种想法持续太久,你可能会陷入工具箱谬误(见下文),并且永远不会完成任何属于你自己的数据科学项目(可能会复制或跟随某人已经完成的项目)。造成这种情况的原因是:

你一下子目标定得太大了。太多的事情依赖于其他事情准备好了,这从来没有发生过。

将您的项目分解成您想要测试的关键概念,并从那里开始。其他的都是次要的。

工具箱谬误

这有点跑题,但在这里非常相关(而且通常是从不开始任何事情的原因)。这是我最近遇到的事情,我必须说这确实是我放弃许多爱好或从未完成我想做的事情的原因。

从本质上说,要做某事,你需要其他事情已经发生。例如,你需要 X 才能做 y。有一个非常好的视频(贴在这里)很好地解释了这一点。

因此,如果你想成为一名数据科学家,你需要研究数据科学并坚持下去,否则很快你就会成为一名数据科学家。

信不信由你,多年来我一直把装订书籍作为一种爱好,但我已经很多年没有这样做了。我还能认为自己是一个吗?也许不是。

回到核心,保持简单

回到我们关于安全灯的例子,把它分解成核心概念“我能通过我在摄像机上看到的东西来控制什么吗?”为了解释这一核心概念,您只需要来自开放数据集中的一些视频数据(或静态图片),应用基于视觉的系统对物体进行分类,并根据它们在屏幕上的位置来决定是否打开 LED。你甚至可以让它变得简单,只需要把你的算法标记在一个。csv”文件,对于图像 X 或者在视频上的时间 X,它将打开某些东西。

这只需要:

  • 一组免费的数据
  • 一台计算机(你主要的数据科学一台就行)
  • 核心算法(你可以在别人的作品上构建,或者研究并构建你自己的)
  • 也许是一个发光二极管打开或关闭

这更可行,也更容易计划和分解到工作中。尝试从这一点,很快…

V oila!你做过一些数据科学!

当然,它不会在晚上工作或经受住外面的天气,但你已经做了核心部分,其他部分是你以后可以添加的。没有这一核心功能,其他部分就毫无意义。

祝贺您完成了您的第一个【概念验证】 (PoC)。

现在,让我们来谈谈我的迷你项目,看看球迷窃窃私语(因为善于倾听球迷,以确定他们的烦恼)。这是一个不错的小项目,涵盖了“可能吗?”,使事情变得简单,而且我能够以很少的成本做到这一点。我对扩展和填充它来覆盖我知道它薄弱的领域不感兴趣。

Yes, I am playing on the whole “horse whispering” thing. Photo by richard savickas on Unsplash

范窃窃私语?

有没有抱怨过你的家用电器坏了,客户服务部门让你拿着设备对着电话,这样他们就可以听了?或者你有没有遇到过这样的情况:你的车出了问题,机械师不用打开发动机罩就能诊断出问题所在?在这两种情况下,他们都在寻找与特定故障相关的特征噪音或声音。

电机和风扇故障的最大来源是轴承问题(例如缺乏润滑)。这通常会导致电机/风扇的声音轮廓发生变化(通常是典型的呜呜声或研磨声)。这实际上是一个很多地方都有兴趣通过听来探测的领域(这里和这里)。

但是为什么倾听有用呢?在第一个例子中,制造商可以快速诊断某些故障,而无需设备进入或维修工程师外出。这一切都节省了成本,因为呼叫在时间和金钱上可能是昂贵的。另一个优势是,如果您知道家用电器上的电机已经或即将出现故障,您可以确保服务工程师携带正确的部件(这对拥有大量不同产品组合的制造商来说非常重要),从而再次节省成本。

核心项目问题

对于一个人来说,可能需要很多年才能识别出机器发出的噪音是什么意思,但你训练机器学习做到这一点有多容易呢?

这是我希望通过 PoC 解决的指导性问题,因此我将重点放在诊断电风扇的故障上,因为它更容易安全地获取和诱发故障。

我在网上购买了一台风扇,然后让它出现了几个(可逆的,我不是钱做的)故障,它们是:

  • 正常:风扇在正常状态下运行,没有故障(当我提到故障或类别时,我确实包括在那里)
  • 塑料薄膜阻塞:一块塑料被引入旋转翅片的路径
  • (想想你小时候放在自行车辐条上的卡片)
  • 重量不佳:一个重物被连接到一个鳍上,使其失去平衡
  • 捕捉侧:一个小的延伸部分被添加到一个翅片上,因此它开始摩擦风扇外壳的内部

现在,所有这些故障听起来微不足道,但通常在严重故障之前,在恶化到故障点之前,首先会出现一个小麻烦,这应该说明,如果可以检测到一个小的不便,那么通过早期干预就可以完全避免一个更具破坏性的问题。

然后,我开始在三种可用的风扇速度(低速、中速和高速)下记录这些故障的十秒钟片段,以增加噪声水平和特征的可变性。我用我的手机来模拟录音设备的质量,类似于我的第一个例子(客户将设备放在手机上,以便客户服务可以听到它)。每个组合重复五次,产生 60 个样本。对于故障模式的每一次重复,我会移除故障并重新应用它,因此记录中会引入一点可变性。

我选择了五个重复,这样我可以在其中的三个上训练,剩下的两个将用于测试集(36 个训练和 24 个测试文件)。

当时的情况是:

  • 执行快速傅立叶变换以将声音转换成模型可以被训练的频谱
  • 通过使用大约 0.1 kHz 宽的滚动平均值平滑得到的频谱以减少噪声
  • 然后,我只以 0.01 kHz 的步长从 1 到 18 kHz 取数据点
  • 这样做是为了标准化和减少数据集的大小
  • 然后我可以训练一个随机森林分类器,看看它是否能区分这四个类别
  • 记得我也改变了风扇速度,所以希望分类器不会受到影响
  • 然后,我在模型上使用了测试集,这样我就可以得到一些结果来比较它在看不见的数据上的表现
  • 预测值和实际值显示在混淆矩阵
  • 这些将实际值(真实值)与预测值进行对比
  • 如果模型是完美的,那么所有的值都在一条对角线上
  • 任何偏差都会告诉你它错误地标注了哪些类,以及它们应该属于哪个组
  • 在分类问题中,这通常是一个非常强大的调试工具

Photo by Josh Kahen on Unsplash

哒哒!

看看下面的结果,他们还不算太差!考虑到模型的基础,我们没有对噪声做任何复杂的处理(比如背景噪声的去除)。

A confusion matrix (or contingency table depending who you talk to) of results. Perfect classification is to have all items on the diagonal.

但是等等,还有更多!

关于随机森林的一个有趣的事情是能够查询它使用什么特性来做决定。对我们来说,这些是模型用来分配类别的频率,更有趣的是,你可以确定哪些频率对于识别某些类别比其他类别更重要。(注意:这个特性重要性做得有点粗糙,但传达了主要观点)。

为了显示这些重要性,我绘制了一个图表,其中包含每个类别的示例,并为每个被归类为重要的频率画了一条垂直虚线。这给出了:

Feature importances for classifying fan classes

现在你可以明白为什么这个模型可以很容易的区分出不同的类,因为它们的形状和能力都很不同。您还可以查看每个类别的重要频率(如上图所示):

  • “抓边”(红色):低频
  • “正常”(蓝色):中频
  • “加权差”(绿色):中频和高频
  • “塑料薄膜障碍”(黄色):频率跨越整个可用范围

拿走

使用简单的技术,可以训练机器学习算法来几乎完美地区分每个故障类别(95.8%的准确率),而且还可以确定哪些频率对于分类每个故障是重要的。

这个例子的缺点是只使用了一个风扇,背景噪声被最小化并保持一致,并且分析/数据准备是基本的。一个更严格的模型将涵盖这些领域,并可以发展成为一个有趣的小演示(也许当我有更多的空闲时间)。

我希望您喜欢使用机器学习来解决实际问题的短暂尝试!

雪花中的规模自举

原文:https://towardsdatascience.com/bootstrapping-at-scale-in-snowflake-3e04a225ff5e?source=collection_archive---------30-----------------------

有时候,当统计学家在抽样数据时,他们喜欢在获取下一个数据之前先把每一个数据放回去。这被称为带有替换的随机抽样,相对于没有替换的随机抽样,这是更常见的事情。

一个在野外这样做的例子是在一个随机森林的训练中,这是我写这篇文章的原因。

所有的雪花内置采样功能都是围绕采样而进行的,没有替换。这意味着您只需对每一行做一次决定——根据情况决定是进还是出。

自举的困难在于,这有点像把骑自行车作为一种爱好;正确地做它是相当昂贵的。

一种简单但完全准确的引导 10,000 行的方法是:

这使得源表中的所有 150,000 个客户每次都有均等的机会被选中,不管他们已经被选中了多少次。

一定有更好的办法!答案当然是我们需要一个“足够好”的替代方案。毕竟我们是在采样,所以如果这意味着性能的提高,精度水平通常是灵活的。

所以让我们看看我们是否能想出一个不同的方法。

目标是引导“雪花 _ 样本 _ 数据”中 150,000 条记录的 60%。“TPCH_SF1”。“客户”表。

我们希望在表上进行一次迭代(从算法的意义上来说),因此如果可能的话,在每一行上只做一次决策。我们需要想出一种方法来多次选择它,但要保持在样本的参数范围内。

一个简单的修改,如果我们任意地决定十次扫描表就足够了,那么我们可以每次只选择 6%,就像这样:

这一点都不好。首先,我们对每一行都处理了十次,我们根本没有真正量化不准确性,我们只是编造了一个数字。

所以让我们看看每次迭代时每一行发生了什么,我们将考虑两个极端:总是被选中,从不被选中。

经过一定次数的迭代后,不可避免地会有一个点(就像我们在澳大利亚说的那样),每个记录都有一个“公平的结果”。所以我们需要一种划定界限的方法。出于本练习的目的,让我们允许用户指定两件事:

  1. 样本的所需大小,以原始表的百分比表示
  2. 一个百分比值,当永远不会被选中的概率低于它时,我们停止迭代。想象这是一条水平线,你可以放在上面图表的某个地方。

方程式时间!

提醒一下,目标是 60%的样本。

暂时忘记“替换”部分,每次选择一行的概率:

或者没有被选中,只是翻转一下:

1–0.6 = 0.4

右边的值是我们希望用户指定的。正如你所看到的,它总是减少,我们将不断增加迭代,直到我们达到它。

因此,我们可以概括地表达这一点,然后求解它,以计算出我们应该进行多少次迭代:

太好了,现在我们有公式可以用了。

现在,让我们回到雪花。请记住,我们实际上并不想进行多次迭代。但是棘手的是,没有任何方法可以让一行在一个结果集中出现不止一次… 还是有?!?!?!

输入 UDTFs

我真的很喜欢udtf,他们有办法实现优雅的解决方案,而不是糟糕的样板文件。

看看这个:

我们可以用这个来一举两得。首先,它将应用该公式,根据我们发明的阈值计算出一个很好的迭代次数(即被选择的机会数)。

然后,礼貌地将样本分数除以该数,并写出该行数。

为了进行演示,UDTF 的输出本身如下所示:

select * from table(SAMPLE_PROBABILITY(0.6::double,0.00001::double))

公式说我们应该做 13 次迭代,0.6/13 = 0.0465384615

换句话说,我们将给予每行 13 次机会,每次尝试的概率为 0.04615384615。

我们需要做的就是像这样加入这个 UDTF:

的原始结果:

SELECT customer.*
FROM "SNOWFLAKE_SAMPLE_DATA"."TPCH_SF1"."CUSTOMER" customer,table(SAMPLE_PROBABILITY(0.6::double,0.00001::double))

实际上是 150,000 * 13 = 1,950,000 行,但是我们添加了 WHERE 子句:

where uniform(0::float, 1::float, random()) < SAMPLE_PROBABILITY

这会生成一个介于 0.0 和 1.0 之间的随机数,并删除低于阈值的行。

一个 100%正确的实现应该给我们 90,000 行(150,000 * 0.6)。这个(使用我选择的输入)似乎每次都能产生 89,000 到 91,000 之间的结果。

当然,正如我们所希望的那样,有可能出现重复。你甚至可以在搜索结果的第一页看到:

在我们的 150,000 表上,返回大约 90,000 条记录,在一个 x-small 仓库上是一秒多一点。

推断统计的自举

原文:https://towardsdatascience.com/bootstrapping-for-inferential-statistics-9b613a7653b2?source=collection_archive---------21-----------------------

数据科学家的工具包—引导、采样、置信区间、假设检验

Photo by Nathan Dumlao on Unsplash

Bootstrap 是一种强大的基于计算机的统计推断方法,它不依赖于太多的假设。仅仅从一个样本数据中形成一个抽样分布是很神奇的。我的统计推断不需要公式。不仅如此,事实上,它还广泛应用于其他统计推断如置信区间、回归模型,甚至机器学习领域。

在这篇文章中,我们将主要讨论两件事

  1. 建立置信区间
  2. 假设检验

链接到 github 获取代码和数据集。

一.置信区间

在现实世界中——我们并不真正了解我们的真实人口。因为这可能是地球上的全部人口,也可能是一家公司过去、现在和未来的交易。 我们只是不知道参数的真实值。 所以我们依靠抽样分布来推断这些大群体的一些参数。

假设检验和我们建立置信区间的方式有许多不同的名称:

  • t 检验
  • 双样本 t 检验
  • z 检验
  • 卡方检验

可以使用自举方法来代替这些。我们将通过一个示例来了解如何使用抽样分布为我们感兴趣的参数建立置信区间。

目标:假设我们想知道喝咖啡的人的平均身高是多少

方法 1:使用自举方法

我们有所有喝咖啡者的数据集。` coffee_full.csv

coffee_full = pd.read_csv(‘coffee_dataset.csv’)

由此,我将创建一个包含 200 个数据点的样本数据集。让我们称它为红色咖啡。这是因为在现实中我们从来没有得到完整的人口

coffee_red = coffee_full.sample(n=200)

在我们的数据集中喝咖啡的人的比例

[coffee_red[‘drinks_coffee’]==True].mean()---Output---
0.595

在我们的数据集中,喝咖啡的人的平均身高

coffee_red[coffee_red[‘drinks_coffee’]==True]['height'].mean()---Output---
68.119 inches

让我们从样本中引导出一个置信区间

# Let's first create an empty list for storing means of bootstrapped samples
boot_means = []# Let's write a loop for creating 1000 bootstrapped samples
for i in range(1000):
    bootsample = coffee_red.sample(200, replace=True)
    bootsample_mean = bootsample.[bootsample[‘drinks_coffee’]==True]['height'].mean()
    boot_means.append(bootsample_mean)boot_means = np.array(boot_means)

对于 95%的置信区间,我们从每一侧截取 2.5%,然后从抽样分布中截取这些值,这将给出我们认为参数“具有 95%置信度”的范围

# we build 95% in the middle portionnp.percentile(boot_means, 2.5), np.percentile(boot_means, 97.5)---Output---
(66.00, 67.59)

我们可以将这些值解释为我们认为人群中所有喝咖啡者的平均身高有 95%置信度的界限

为了形象化这一点,让我们看下图

plt.hist(boot_means, alpha=0.7);
plt.axvline(np.percentile(boot_means, 2.5), color='red', linewidth=2) ;
plt.axvline(np.percentile(boot_means, 97.5), color='red', linewidth=2) ;

Confidence Interval from our boot-sample mean

置信区间解释

我们有 95%的把握认为所有喝咖啡的人的平均身高在 66.0 到 67.59 英寸之间

让我们回过头来看看人口的实际意义是什么

coffee_full[coffee_full[‘drinks_coffee’]==True][‘height’].mean()---Output---
66.44 inch

我们可以看到我们最初的平均身高在 95%的置信区间内

方法 2:传统的内置方法(T 检验)

python 中已经内置了许多构建置信区间的传统方法。 这里有一个不错的 stackoverflow 链接

import statsmodels.stats.api as smX1 = coffee_red[coffee_red['drinks_coffee']==True]['height'] 
X2 = coffee_red[coffee_red['drinks_coffee']==False]['height']cm = sm.CompareMeans(sm.DescrStatsW(X1), sm.DescrStatsW(X2))print (cm.tconfint_diff(usevar='unequal'))

请注意,自举方法和使用传统方法内置的时间间隔几乎相同

二。假设检验

作为一名数据科学家,你必须首先将问题转化为所谓的假设。然后你需要用数据来证明哪个假设可能是真的。

假设我们想问一个问题,所有喝咖啡的人的平均身高是否大于 70 英寸。

这里我们将不得不定义什么叫做零假设和交替假设。零假设是在我们收集数据之前就被默认为真的东西。替代假设是我们试图用数据来证明的东西

Null and Alternate hypothesis for our use case

方法 1:检查是否可能为空(引导)

我们可以引导一组样本数据,反复计算样本均值,建立样本分布和置信区间,以确定在一定置信水平下总体均值的合理值

means = []for i in range(10000):
   bootsample = sample_df.sample(n=150, replace = True)
   bootsample_mean = bootsample[bootsample['drinks_coffee']==True]
   means.append(bootsample_mean['height'].mean())means = np.array(means)np.percentile(means, 2.5), np.percentile(means, 97.5)---Output---
(66.00, 67.59)

我们可以看到我们 95%的置信区间是(66.0,67.59)。值 70 超出了 95%的置信区间,因此可以肯定地说替代假设不成立。我们未能拒绝我们的无效假设

方法 2:模拟零假设

我们从假设零假设为真开始。如果我们要模拟最接近零假设的值,我们就会知道抽样分布是什么样的

在这种情况下,我们将从正态分布进行模拟

null_vals = np.random.normal(loc = 70, scale = np.std(means), size =10000)

70 是我们假设的平均值

这里的每个模拟图都代表了零假设的一个可能的平均值。我们现在可以问这样一个问题,样本均值落在这个分布的什么位置

plt.hist(null_vals, alpha=0.7);
plt.axvline(sample_mean, color = 'red', linewidth=2);

我们可以看到,它远远低于这个分布,我们不认为它可能来自这个零假设值。因此我们可以说我们的零假设是正确的

p_value = (null_vals > sample_mean).mean()
p_value--Output--
1.0

大 p 值表明我们不能拒绝我们的零假设。这意味着我们的人口平均数确实小于或等于 70

  • 我们将 p 值计算为大于样本均值的模拟抽奖的比例
  • 在此,p 值以图形方式表示大于突出显示红线的所有值的曲线下面积。基本上是所有的数据

结束语:

波士顿 Airbnb 分析

原文:https://towardsdatascience.com/boston-airbnb-analysis-f46bcda1713a?source=collection_archive---------16-----------------------

波士顿到处都是历史名胜和古迹,充满了爱国主义精神。让自由之声响起来!下面简单分析一下波士顿 Airbnb。为了更详细的分析,这里是我的笔记本Github 库以及所有需要的代码。

Original photo by Anthony Delanoix on Unsplash

介绍

答 irbnb 已经成为许多旅行者的首选,不仅是在世界各地寻找住宿的时候,也是在到达一个城市之前探索这个城市的时候。当考虑在目的地过夜时,人们会想要一个“家外之家”。因此,Airbnb 为市场重塑了一个独特的、鼓舞人心的蓝海,“蓝海战略是同时追求差异化和低成本以开辟新的市场空间和创造新的需求。”在蓝海,需求是创造出来的,而不是争夺出来的。Airbnb 为顾客和主人提供了双赢的局面;虽然顾客可以以较低的价格获得住宿,但主人可以通过出租他们的房产来赚钱。

为了进一步了解波士顿如何利用 Airbnb,我分析了波士顿 Airbnb 从 2019 年 2 月到 2020 年 2 月的房源。本分析中使用的数据集是根据Creative Commons CC0 1.0 Universal(CC0 1.0)“公共领域专用”许可证从 Airbnb 数据库内部获取的。该数据集报告了波士顿寄宿家庭的列表活动。该数据集包含超过 6150 个物业列表,包括但不限于主机信息,价格,邻里,设施,取消政策和评论。

分析及其结果只是观察性的,不是正式研究的结果。下面列出了一些常见的业务问题,引导我们通过分析来创建一个模型,该模型可以根据一些特征来预测租赁价格。

商业问题

1.波士顿所有 Airbnb 的价格在 2019 年全年如何波动?
2。波士顿 Airbnb 租赁价格的高峰/非高峰时间是什么时候?
3。Airbnb 房源最多的主机是谁?
4。波士顿哪些社区的挂牌数量最多?
5。波士顿最贵的社区是哪些?
6。哪些是基于平均评论数的热门社区
7。波士顿 Airbnb 的房源大部分是哪种类型的房间?
8。波士顿 Airbnb 有哪些影响价格的功能?我们可以根据预测模型预测新房源的租赁价格吗?

数据准备和探索

B 在深入研究数据集之前,应该清理数据,并为探索和建模做好准备。因此,删除了几个特征,以确保最终的数据集只包含为我们的分析增值的特征(变量)。以下质量和整洁问题已得到解决;例如,价格列中有美元符号($)和逗号(,)的地方被清理了。另外,日期列被转换为日期时间,并且删除了许多缺少值的列。虽然删除了一些有缺失值的行,但是cleaning _ fee特性只有少量的空值;因此,这些字段被赋予了最常见的值。

  1. 质量问题
    -某些功能
    中的数据缺失-中的数据类型错误日期 功能
    -便利设施 中的源类型,其中字段与符号错综复杂
  2. 整洁问题
    -具有多个表示的特征: 房间类型、便利设施和邻里清洁
    -注释reviewer _ name中的源类型,其中有些字段用符号表示,有些用不同的语言编写。

接下来,我们将调查价格分布,以确保我们删除离群值,或主机,他们列出了每晚的合理价格。

根据显示所有列表中价格分布的直方图,每晚 500 美元的最高价格是合理的。每晚超过 500 美元的列表是异常值。虽然我们可能认为 500 美元很高,没有反映 Airbnb 的概念,但在波士顿的一些社区,这是可以接受的。

如上所述,虽然 500 美元是一个合理的租金价格,但该地块表明,大多数房源价格在每晚 50 美元至 200 美元之间,这比 500 美元更有意义。然而,出于更广泛的分析目的,每晚 500 美元将是我们进一步分析中每晚最高房价的分界点。

波士顿所有 airbnb 的价格在 2019 年全年如何波动?

时间序列图显示了 Airbnb 房源价格迅速上涨的两个时期。阴影区域显示价格上涨的日期。水平线代表全年的平均租金

  • 从 2019 年 4 月 8 日到 2019 年 4 月 21 日的期间,平均价格的增长高于整体平均价格。经过进一步的调查,这种增长是由于波士顿马拉松,世界上最古老和最具挑战性的比赛之一。马拉松比赛于 4 月 15 日星期一举行。
  • 2019 年 12 月 25 日至 2020 年 2 月 7 日期间,价格有所上涨,这是意料之中的,因为它将迎来圣诞节和新年前夜。
  • 2019 年 2 月和 2020 年 2 月之间平均价格的显著差异。虽然 2019 年是房价最低的时期,价格范围在每晚 136 美元至 200 美元之间,但 2020 年的价格从每晚 234 美元开始。
  • 总体而言,波士顿 Airbnb 的非高峰期出现在 2019 年 2 月和 3 月,高峰期出现在 2019 年 4 月至 10 月。价格在 11 月份下降,直到 12 月份趋势再次上升。

波士顿 airbnb 租赁价格的高峰/非高峰月份有哪些?

每月价格趋势图显示了波士顿 Airbnb 房源价格的高峰和非高峰月份。红色区域表示每晚平均价格高于每晚所有列表的总体平均价格的月份,而绿色区域表示每晚平均价格低于每晚所有列表的总体平均价格的非高峰月份。

  • 2019 年的 2 月、3 月、4 月初、11 月和 12 月的大部分时间是价格低于每晚 215 美元的非高峰月。
  • 2019 年 4 月下半月、5 月、7 月、8 月、9 月、10 月上半月、12 月底以及 2010 年 1 月和 2 月是价格高于每晚 215 美元的高峰月份。

波士顿 airbnb 的房源大部分是哪种类型的房间?

Airbnb 房东可以列出这些房间类型中的一种或全部:整个家庭/公寓、私人房间或共享房间。该图显示,整个住宅/公寓占波士顿周围 3775 个列表中的 63.91%。其次是有 2061 个房源的包房和只有 71 个房源的合租房,仅占 1.2%

airbnb 房源最多的主机是谁?

正如我们从条形图中看到的,Sonder 在 6140 个列表中占有大约 10%的份额,其次是 Kara,155 个,Bluebird,154 个,Mike,142 个。这四个主机约占全部列表的 25%。其他主机的列表数量范围从 1 到 89 个列表。

根据 Inside Airbnb 的说法,注意到“主人可能会列出同一公寓中的独立房间,或者多个公寓或住宅的整体情况”是至关重要的。拥有多个房源的房东更有可能在经营一家企业,不太可能住在该房产内,而且违反了旨在保护住宅的大多数短期租赁法律。”

波士顿哪些社区的挂牌数量最多?波士顿哪些社区被认为是最贵的?
根据平均评论数,哪些是热门街区?

下面生成的热图将进一步阐述这些数字,因为它不仅显示了每晚房价较高的区域,还显示了大多数房源所在的区域。

Heat Map of Boston airbnb properties based on price

虽然条形图显示多切斯特和牙买加平原是数据集中房源数量最多的两个街区,但箱线图显示了最昂贵的两个街区之间的完整比较,其中不包括提到的前两个街区。

Art by Carrie Wagner on Etsy

  • 唐人街的平均房价最高,约为 226 美元,而在六个最贵的社区中,“芬威”的平均房价为 200 美元。
  • 大多数房源的价格在每晚 289 美元到 131 美元之间,这表明了这些社区的合理价格。

此外,根据平均评论数得出的热门街区的结果用下面生成的热图进行了修饰,因为它显示虽然 North End 不占房源的最高数量,但它在 2019 年对波士顿 Airbnb 房源的平均评论数最高。

Heat Map of Boston airbnb properties based on number of review

数据建模

C 创建一个预测租金价格的模型需要更多的数据准备和清理工作,以确保数据集不包含任何分类变量和缺失值。由于缺失值已经被丢弃或估算,这里最重要的步骤是评估分类特征:哪些是二元的,哪些是多层次的。然后,通过为每个唯一值获取虚拟对象来重新编码这些特征。便利设施栏需要对其领域进行更多的评估,将所有的便利设施分成单独的栏。

该模型旨在说明波士顿 Airbnb 租赁价格的驱动因素。波士顿 Airbnb 中有哪些影响价格的功能?此外,我们能否根据预测模型来预测新房源的价格?因此,数据集被分为解释变量和响应变量,其中价格作为目标,所有其他特征作为独立变量。在预测和获得普通最小二乘法的概要之前,数据集被分成 80%训练和 20%测试,包括具有 4725 个样本的训练集和具有 1182 个样本的测试集。

评估和结论

Complete results can be found here.

根据回归结果,调整后的 R(选择调整后的 R 而不是 R,因为它考虑了功能的数量)表明,列出的功能可以解释波士顿 Airbnb 价格中 61%的可变性。接下来,我们将了解哪些功能比其他功能具有更大的权重和影响,然后确定模型中的功能之间是否存在显著的关系。如果每个特征的 p 值小于 0.05,我们得出结论,有足够的证据表明,我们有 95%的信心认为价格和特征之间存在显著的线性关系。

波士顿 Airbnb 有哪些影响价格的功能?
我们能否根据预测模型来预测新房源的价格?

条形图细化了价格和最有影响的功能之间的关系。我们可以得出结论,一些特征与波士顿 Airbnb 的租赁价格呈强正相关,而其他特征则呈负相关。此外,该模型验证了我们之前关于最广阔、最受欢迎的社区的发现。

根据之前的调查,我们得出结论,以下列出的功能通过提高或降低租赁价格,对预测波士顿 Airbnb 房源的价格具有更大的影响:

  1. 便利设施:
    —电动仿形床
    —楼梯门
    —洗衣机/烘干机
    —热水壶
    —卫生间固定扶手
    —私人浴室
    —房间遮光帘
  2. 物业类型:
    —平房
    —酒店式公寓
    —小房子
    —酒店
    —房子
  3. 街区:
    —后湾
    —皮革区
    —南波士顿海滨
    —唐人街
    —市区
    —马特潘
    —海德公园
  4. 其他房屋规则和特点:
    —取消政策:严格
    —房型:全屋/公寓

精神食粮

  • 回归结果具有调整后的 R,表明列出的特征可以解释波士顿 Airbnb 价格中 61%的可变性。

我们能找到更好的模型,有更高的准确度和更高的 R 来解释大部分的变异吗?

  • 根据 OLS 回归结果,某些要素不具有统计显著性,因为它们的 p 值(用于确定模型中要素之间是否存在显著关系)高于 0.005。牢记在心;线性关系可能具有统计显著性(p 值低),但是,它不能解释因变量的大部分可变性(调整后的 R 值不高)。

这是否意味着移除这些独立变量会改善我们的模型?

参考

  1. 价值创新|蓝海工具和框架。【https://www.blueoceanstrategy.com/tools/value-innovation/】

波士顿数据分析师和科学家就业市场:2019 年 8 月更新

原文:https://towardsdatascience.com/boston-job-market-for-data-analysts-and-scientists-august-2019-update-1e057bb7bca?source=collection_archive---------27-----------------------

大多数招聘公司、顶级工具和技术等

介绍

这是我的原始项目的 2019 年 8 月更新,我的目标只是探索大波士顿地区数据分析师和数据科学家的就业市场。

这些图片仅来自在 Indeed 上发布的职位列表,搜索条件为“数据分析师”或“数据科学”,因此仅代表选择在 Indeed 上发布的公司。因为这是上一篇文章的更新,所以我在这里只展示视觉效果。要详细了解所采取的步骤和所做的假设,请查看我在的原始项目中的完整演示。

最受欢迎的职位

这里我们简单列出了 10 个最常见的职位。当然,最普通的头衔在最上面,比如“数据科学家”和“数据分析师”。这里需要注意的一点是,波士顿市场上有大量的“高级”图书。

波士顿招聘数据分析师和科学家最多的公司

这是波士顿就业市场的一个有趣的代表。总部位于波士顿的 Liberty Mutual 在数据科学领域占据了 8 个不同的领先位置。而大多数工作是在医疗保健和制药行业,这更符合波士顿的情况。

最低工作经验年限

这大概是你所期望的最常见的最低工作经验年限在 1-3 年的范围内。有趣的是,在 4 中看到同样的下降(这是我在我的原始帖子中看到的)表明人们宁愿使用漂亮的 round 5+而不是 4。分析师职位和科学职位之间似乎没有太大的区别。

最低教育水平

这就是你所期望的。然而,我认为数据科学岗位更需要硕士学位,甚至学士和硕士学位也是如此。

最受欢迎的工具和技术

超过 60%的职位列表中仍然需要(或提到)Excel。当然,python 和 sql 紧随 excel 之后,R 比我预期的(希望的)多一点,只在四分之一的清单中被提及。

感谢阅读!

同样,要详细了解所采取的步骤和所做的假设,请查看我在的原始项目中的完整演示。我真的很想对这里的一些描述数据做更多的工作,所以如果你有任何我可以问的更多问题的想法,或者要添加到列表中的工具/技术,请在下面评论。

Ubuntu 18.04 上的机器人实时物体检测

原文:https://towardsdatascience.com/bot-realtime-object-detection-in-overwatch-on-ubuntu-18-04-5571c4c85ec6?source=collection_archive---------17-----------------------

在本教程中,我会告诉你,如何安装 Overwatch,从你的实际游戏中收集图像数据,在上面训练模型,并将这个模型应用于实时物体检测。

为此,请确保您已经安装了 Tensorflow。最好有 GPU 支持,以获得更快的速度。没有它,你将会有更小的 fps,训练模型将会花费相当多的时间,并且实时性能可能无法实现。

Part1:在 Ubuntu 18.04 上安装 Overwatch

在几次使用 Wine 和 DXVK 安装 Overwatch 的失败尝试后,我开始使用 Flatpak,它似乎很容易在 Linux 上运行 Windows 应用程序。事实也的确如此,除了驱动程序版本的特殊时刻。稍后将详细介绍。

在已安装的 Flatpak 和 Battle.net 启动器上运行这些命令:

sudo apt install flatpak gnome-software-plugin-flatpak
sudo flatpak remote-add --if-not-exists flathub https:**//**dl.flathub.org**/**repo**/**flathub.flatpakrepo
sudo flatpak remote-add --if-not-exists winepak https:**//**dl.winepak.org**/**repo**/**winepak.flatpakrepo
sudo flatpak install winepak com.blizzard.Overwatch

重新启动电脑后,键入:

sudo flatpak run com.blizzard.Overwatch

你会看到:

Niiiice, aren’t?

为了更多的 FPS 和流畅的体验,你需要安装额外的 nvidia 驱动程序(因为现在游戏使用 OpenGL 引擎)。在少数情况下,没有图形驱动,游戏根本无法运行。

重要提示:您当前从 nvidia-smi 命令输出的版本和 flatpak 版本必须相同。否则,你会得到错误时,点击播放在看守部分在 Battle.net 发射器。请注意,你需要两个版本的 Flatpak 驱动程序。

例如,目前我有这个版本的 nvidia 驱动程序:

Version of drivers: 410.104

下一步:我检查 Flatpak 中是否有该版本的驱动程序:

flatpak remote-ls flathub | grep nvidia

是的,在 FlatHub 有 410-104 版本的 Nvidia 运行时包(不要在这里放屏幕,因为输出很大)。

这样我就可以使用这些命令在 Flatpak 中安装 32 位和 64 位版本(提醒,您需要这两个版本!):

flatpak install flathub org.freedesktop.Platform.GL32.nvidia-410–104
flatpak install flathub org.freedesktop.Platform.GL.nvidia-410-104

如果一切顺利,你就可以开始游戏了!

Yeaaah!

最后:为了录制和获得更舒适的 fps,进入选项-视频,选择窗口模式,1280*720 分辨率,30 fps 锁定和低设置。当你在玩警戒时,当模型一起工作时,这允许你在游戏中达到大约 30/3 = 10 fps 性能。是的,运行模型是一个详尽的过程,你的 GPU 会 100%的工作。实际上取决于你的 GPU。但在我的 1060 上这是真的。

在本教程的下一部分,我将向你展示如何为你的模型获取训练数据,训练模型(如果你想的话),并在游戏时进行实时检测。

附言:如果你坚持选择正确的驱动程序,请查看这篇小文章(你也可以找到更多解释)如何克服这个问题:

[## 如何让使用 OpenGL 构建的 Flatpak 应用和游戏与专有的 Nvidia 显卡一起工作…

一些用 OpenGL 支持构建并打包成 Flatpak 的应用程序和游戏无法用专有的 Nvidia 启动…

www.linuxuprising.com](https://www.linuxuprising.com/2018/06/how-to-get-flatpak-apps-and-games-built.html)

第二部分:记录游戏过程并准备训练图像

让我们安装这些库,它允许我们捕获游戏:

pip3 install --user pyscreenshot
pip3 install --user mss

安装 Overwatch 后,你可以使用 simplestream.py 实时记录游戏过程(大约 80-100 fps)

请看第 17 行:在这里您选择屏幕的一部分来捕获。你需要用显示器字典中的值来适应你的窗口游戏。请随意用值替换这一行代码,这样您会感觉最舒服。例如,我对它们进行了硬编码,并在屏幕中央设置了监视窗口;你可能更喜欢把窗口放在左上角等等。花几分钟在上面;你只能做一次。

只需在控制台中键入:

python3 simplestream.py

回到游戏中。当你完成后,点击窗口框架,并按下 q。脚本完成,你可以在这里看到输出. avi 文件。那是你的玩法,会在哪个模型上训练。

重要提示:您第一次可以使用 my repo 中的训练模型,不要制作图像、训练模型等(请跳过这一步,进入下一部分)。如果你会从结果中得到启发,欢迎使用你自己的数据来训练你自己的模型。

获取图像

为了从 output.avi 中提取帧,你需要 ffmpeg:所以让我们安装它吧!

pip3 install --user ffmpeg

使用 ffmpeg 从创建的视频中获取帧(首先创建文件夹/图像!):

ffmpeg -i output.avi -vf fps=10 images/thumb%04d.jpg -hide_banner

这让我们每秒钟从视频输出. avi 中获得 10 帧,并将这些帧(图像)保存在图像文件夹中。

用 python3 resizer.py 调整大小

你可以用 now resizer.py 让图片比现在更小。

python3 resizer.py

我评论了第 20 行,因为发现,分辨率 960540 最适合初始分辨率在 1280720 左右的图片。嘶!第 20 行和第 21 行做的东西一样,所以你可以用你最喜欢的那一行)。但是不要忘记评论另一行——否则你会破坏你的图像!(开个玩笑——在这种情况下,你将每张图片的大小调整两次,结果会非常糟糕)。

用标签标注

我们来注释图像。为此,我建议使用标签。

git clone [https://github.com/tzutalin/labelImg.git](https://github.com/tzutalin/labelImg.git)
cd labelImg
sudo apt-get install pyqt5-dev-tools
sudo pip3 install -r requirements/requirements-linux-python3.txt
make qt5py3
python3 labelImg.py

pip3 为什么不装 labelImg?因为我已经试过了,不能启动这个程序。所以从源代码安装只是一种方式,对我来说很有效。你可以试着从 pip3 安装,也许你可以启动它并节省几分钟。

我使用一个类“bot”来注释图像,因为我想检测 bot(显然,不是吗?).如果你想检测很多类,这部分消耗的时间会增加很多,因为你出错和选择错误类的机会很高(特别是当你在帧上有很多对象的时候)。

因此,现在您需要注释 images/train 和 images/test 文件夹中的每个图像。这是耗时的部分,所以要冷静,专心,不要动作太快。

重要:删除至少没有一个类的坏帧。如果您丢失了至少一个文件,您将无法为此图像创建注释。而且模型训练还没有开始,因为你将没有等量的图像和 xml 文件(注释)!

创建测试和训练目录

为此,使用 split.py:

python3 split.py

此脚本中的代码:

Place this script in place, where exists images as subdirectory

之后,将 images 文件夹放在 object_detection 文件夹中,进入 tensorflow 部分(第 3 部分)。

第三部分:张量流部分

你可以跳过这一部分,第一次使用我训练过的模型(我在一个 github repo 上提供了所有文件)。在这两种情况下,您都需要安装这些库:

pip3 install pillow
pip3 install lxml
pip3 install jupyter
pip3 install matplotlib
pip3 install opencv-python opencv-contrib-python
sudo apt install protobuf-compiler

这部分是最费时间的,在这个过程中你会遇到很多问题。我的指南基于来自的精彩教程。它适用于 windows 10,但区别并不太大。只有当你想用你自己的数据训练你自己的模型时(比如从 quickplay match 中检测 Hanzo ),你才可以做下面所有的步骤。

下载模型,重新加载原型,重新加载变量(别忘了把/home/Dmitry 改成/home/your_username/):

git clone [https://github.com/tensorflow/models.git](https://github.com/tensorflow/models.git)
cd models-master/research
protoc object_detection/protos/*.proto — python_out=.
export PYTHONPATH=$PYTHONPATH:`pwd`:`pwd`/slim
sudo gedit ~/.bashrc 
export PYTHONPATH=$PYTHONPATH=/home/dmitriy/models/research:/home/dmitriy/models/research/slim
source ~/.bashrc

来自研究目录:

sudo python3 setup.py build
sudo python3 setup.py install

然后运行(在注释完所有图像后):

python3 xml_to_csv.py

这将在\object_detection\images 文件夹中创建一个 train_labels.csv 和 test_labels.csv 文件。在 generate_tfrecord.py 中进行更改。例如,我的文件:

如您所见,您需要在第 30–35 行修改所有的类(在我的例子中是“bot”)。其他的你都不需要改变。之后(从 object_detection 文件夹):

python3 generate_tfrecord.py --csv_input=images/train_labels.csv --image_dir=images/train --output_path=train.record
python3 generate_tfrecord.py --csv_input=images/test_labels.csv --image_dir=images/test --output_path=test.record

它们在\object_detection 中生成一个 train.record 和一个 test.record 文件。这些将用于训练新的对象检测分类器。

从 tensorflow zoo 下载模型作为配置,并放入 object_detection/training 文件夹:

wget [http://download.tensorflow.org/models/object_detection/faster_rcnn_inception_v2_coco_2018_01_28.tar.gz](http://download.tensorflow.org/models/object_detection/faster_rcnn_inception_v2_coco_2018_01_28.tar.gz)
tar xvzf faster_rcnn_inception_v2_coco_2018_01_28.tar.gz

在 labelmap.pbtxt 中进行更改。例如,我的文件:

所以,比如你想检测半藏类,就把 bot 改名为半藏。

然后在 fast _ rcnn _ inception _ v2 _ pets . config 中进行更改。

代码:

我们开始吧:

将第 9 行的 num_classes 更改为您的类的总数。例如,如果我只想检测一个机器人,它将是 1;

在第 106 行将 fine_tune_checkpoint 更改为放置 fast _ rcnn _ inception _ v2 _ pets . config 的路径;

在第 112 行 nums_steps 更改为你想要训练模型的多少(通常 10–20k 就够了);

在第 122 行 input_path 处切换到您的 train.record 所在的位置;

在第 124 行 label_map_path 更改为您的 labelmap.pbtxt 所在的位置;

将第 128 行的 num_examples 更改为\images\test 目录中的图像数;

在第 136 行 input_path 处切换到您的 train.record 所在的位置;

在第 138 行 label_map_path 更改为 labelmap.pbtxt 所在的位置。

请注意正确地更改这些路径!

并将这些文件(labelmap.pbtxt 和 faster _ rcnn _ inception _ v2 _ pets . config)放在 training 文件夹中。

将 train.py 从旧文件夹移到主文件夹。

之后,你可以开始训练:

python3 train.py --logtostderr --train_dir=training/ --pipeline_config_path=training/faster_rcnn_inception_v2_pets.config tensorboard --logdir=’training’

请确保 inference_graph 为空或未创建。

python3 export_inference_graph.py --input_type image_tensor --pipeline_config_path training/faster_rcnn_inception_v2_pets.config --trained_checkpoint_prefix training/model.ckpt-10000 --output_directory inference_graph

请随意将 model.ckpt-number_of_epochs 更改为您的号码。因此,如果您训练了 1000 个历元,请将 trained _ check point _ prefix training/model . ckpt-10000 更改为 trained _ check point _ prefix training/model . ckpt-1000。

这将在\ object _ detection \ inference _ graph 文件夹中创建一个 freezed _ inference _ graph . Pb 文件。的。pb 文件包含对象检测分类器。

对于教程的下一部分,您需要来自\object_detection\training 文件夹的 freezed _ inference _ graph 和 labelmap.pbtxt。还有 fast _ rcnn _ inception _ v2 _ pets . config,文件夹 protos,utils,training 和 core。

因此,在某个地方创建 object_detection 文件夹,并将其全部移入其中。现在,您已经准备好了最后一部分(第 4 部分:实时检测)。

第四部分:运行实时检测

经过上述所有的艰苦工作,这一步成为最容易的一步。

如果你只是想测试训练模型,然后下载我的回购使用以下命令:

git clone [https://github.com/Oysiyl/Bot-object-detection-in-Overwatch.git](https://github.com/Oysiyl/Bot-object-detection-in-Overwatch.git)

然后将此文件夹重命名为 object_detection,并移动到此文件夹。

我建议你第一次运行 Object_detection_image.py,以确保一切正常。所以运行这些:

python3 Object_detection_image.py

在等待初始化 Tensorflow 并将模型加载到 GPU 内存中大约 5-10 秒后,您将看到此图片,其中包含两个已识别的框(按 Q 退出):

I think, we might customize text on boxes later

以及检测到的箱子的坐标:

So, bots are successfully detected. Niiice!

我们将在(realtime_detect_stream.py)之后运行的脚本代码:

运行 realtime_detect_stream.py(要退出,请单击框架窗口并按 Q 键):

python3 realtime_detect_stream.py

如果你有超宽显示器或者只有第二台显示器,体验会更舒服。你会看到实时对象检测!我不能在这里显示一个漂亮的屏幕,因为我只有一个全高清显示器,实际上游戏窗口和识别游戏的窗口都不合适。

Such that

小提示:您可以将 123 行更改为 cv2.resize(img,(300,300))并获得更健壮的图片(或选择更多少量的像素):

You are almost see the whole picture

退出后,您会看到 output2.avi 文件已经创建。在这里,您可以观看视频,了解模型的表现:

额外部分:使用训练过的模型击败机器人

嘶!确定谁是你的敌人后,你就可以打败他。所以,opencv 可以用机器人检测盒子的坐标。您可以使用 pyautogui 来击败他们!

pip3 install --user pyautogui
sudo apt-get install python3-tk python3-dev

不同的距离对精确度有很大的影响。请看这个演示:

这是从更大的距离(我使用 WASD 接近目标):

我在鳏夫制造者身上测试过。所以,一秒钟的延迟让她可以毫无延迟地瞄准并打出有力的一击,而不是无力的一击。你只要向机器人走去,opencv 就会检测到机器人,并在他周围建一个盒子,然后程序就会尝试投篮。我用盒子中头部的可能位置来表示这一点,所以程序将继续移动相机到这一点,并在达到这一点后单击。

请注意,使用 time.sleep(1.0)会导致在录制视频时损失 1 秒,因为程序暂停了 1 秒(10 fps)。你可以用 time.sleep(1.0)把这一行改成 pyautogui。PAUSE=1.0 并在单击返回到默认 pyautogui 设置后添加(通过以下方式— pyautogui。暂停=0.01)。我不建议你这么做,因为 programm accuracy 会做出一些奇怪的动作(比如向目标点移动时开枪)。使用这些方法的好处——当你瞄准时,你记录的视频将是完整的,不会丢失 10 fps (1 秒)。

重要提示:要从 pyautogui 中获得正确的操作,您需要在游戏选项-视频-显示模式中进行更改,并设置为“无边框窗口”。如果没有这个程序,每次都不能正确的点击和移动你的相机到任意的位置。不要忘记,如果你想记录这个,你需要改变显示器字典(看第 116 行),因为你的游戏窗口现在将是无边框窗口,而不是之前的窗口。

这段代码插入 realtime_detect_stream.py 中的名称定义之后。如果你不知道在哪里添加,看看这个完整的例子:

重要代码行的简短说明:

在行 152 中,我们仅选择通过 90%极限检测的盒子;第 167–181 行—找到盒子的坐标;使用 if 语句(第 183-185 行)每帧只需要选择和跟踪一个框。这很重要,因为如果模型检测到两个或更多的盒子,她会从一个跳到另一个,没有任何动作(但它的工作并不完美,有些问题)。

然后我们找到了中心 x 和中心 y 坐标——我们的模型将移动到这一点。用于移动计算的 moveX 和 moveY。如果移动得很大(第 191-194 行),我们将使这个移动变得更小——提高移动精度(第 195-198 行):如果模型接近目标(5 px 或更小),使下一个移动等于 0(因此不允许在这个轴上移动,在大于 5 的另一个轴上移动)。如果我们达到了“中心”,模型将执行我们假设的一组动作(第 204-212 行)。在这里你可以尝试使用 pyautogui。没有时间的暂停。睡眠(1.0)。如果我们还没有到达“中心”,那么根据当前摄像机位置的坐标执行移动(第 214-226 行)。

在每一帧的下一行画一个圆(我们要移动的点),并输出许多文本,直接放在你的帧上以便进一步监控(这非常非常有用,当出错时)。例如,当 defeat_bots.py 移动不是你无法理解的时候,那些监视输出可以帮助你看到,在下一帧中什么模型将做,哪些移动选择,接下来在哪个方向移动,多少像素...您可以注释这些输出(第 232–237 行)。

在第 240 行,opencv 将给定的帧保存到视频中,然后向您展示这一帧(第 241 行)。像往常一样,按键盘上的 Q 将停止程序,保存视频(第 250 行)后,opencv 将关闭(第 251 行)。

Monitoring outputs in upper left corner

正如你从下面的图像中看到的,模型在中心射击机器人,并开始向下一个目标移动。这是我激活的 ult,程序现在不能这样做。我只是好奇 ult 是否在模型准确性上有所努力(但没有发现任何努力)。我用 WASD 组合按角色表演所有的动作。

运行 defeat_bots.py:

python3 defeat_bots.py

像往常一样,去训练室值班。如果 opencv 检测到至少一个机器人——程序将使用鼠标移动相机到这个识别的边界框,并点击直到框消失(机器人被击败)。耶希!

加成:在训练室其他英雄 vs bots 上测试并不难。例如,将第(204–212)行的动作更改为仅 pyautogui.click()允许您使用这样的字符,其主要攻击是左键单击:

Such as bastion (Beep-beep!)

正如你所看到的,侦查并不依赖于所选的英雄,考虑到英雄的游戏性和他/她拥有的能力的差异,你可以为几乎任何你想要的英雄采用脚本。

重要:本文中的所有内容,尤其是额外部分,都是出于科学目的和我的好奇心。我不建议你用模型对抗其他玩家,因为:

零:当物体远离或者英雄只看到物体的一部分时,模型无法检测到。你需要训练模型理解效果(比如每个英雄的莱因哈特盾或者最后通牒能力)。

第一:因为你需要在大约一千个(!!!)类认每个英雄(现在 30 左右)每个皮肤(不知道多少)。

第二:你需要在许多不同的地图上训练(因为不同的环境,在绿洲上训练的模型在南极洲几乎不工作)。

第三:我的数据集有近 600 张图片,经过 1000 步训练,应该足以在一张没有任何皮肤的地图上检测一个类(机器人)(但你看这种检测远远不够理想)。想象一下,你需要创建和注释多少图像才能达到好的效果。以及训练时需要多少计算能力才能得到好的结果并达到至少每秒 60 帧的实时速度。

第四:模特不能动!我不知道逻辑如何实现这一点。

此外,因为这是作弊,你可能应该被禁止,当与真人,而不是机器人玩。

希望你成功,这项工作将激励你从这个游戏或另一个(你最喜欢的)更有趣的模型。

祝你愉快,这是你应得的!

机器人罗斯:教电脑画画

原文:https://towardsdatascience.com/bot-ross-teaching-a-computer-to-paint-f5a9c9ef908?source=collection_archive---------12-----------------------

我承认,我不是一个非常好的艺术家。至少不用刷子和颜料。我可以用钢笔或铅笔做出可信的努力,前提是你不是在寻找像人手或马这样棘手的东西。但是打开油彩,一切都结束了——我能做的最好的就是用花哨的颜色画出一些难以辨认的斑点。尽管,或者可能是因为完全没有绘画能力,我发现电视名人画家鲍勃·罗斯非常迷人。他温和的表达和轻松的方式是忙碌世界中的安慰。罗斯的演讲更迷人的一面是他保证,只要有足够的练习,任何人都可以学会画画。

“天赋是一种追求的兴趣。任何你愿意练习的事情,你都可以做到。”— 鲍勃·罗斯

这是一个非常吸引人的想法,也是我想要分享的观点。我坚信努力工作和实践会超越一些模糊的“天赋”概念。罗斯在绘画时看起来如此平静,如此沉浸在他在画布上创造的阿拉斯加小乡村荒野中。我也想探索那片荒野。但是我很忙。我有很多工作要做,还有很多论文要写。我能走捷径吗?鲍勃·罗斯说如果我愿意练习,我可以画得像他一样。但是我能找到一个算法来帮我做这个练习吗?我可以教电脑画画吗?

这对人工智能来说是个棘手的问题。我们能不能把这个问题组织成计算机可以解决的形式?教电脑画画是什么意思?我想要实现的是一个系统,在这个系统中,我可以用最少的投入,用最少的努力创作出一幅新颖的画。我想缩短练习的过程。我想要的是能把我花哨的斑点变成类似鲍勃·罗斯画作的东西,而不用自己去学。

I call it “Toothpaste Mountain”

在很大程度上,人工智能算法的工作原理是预测。给定一个输入,他们预测一个最有可能满足一些期望标准的输出,以最小化误差。在这种情况下,我们需要一种算法,给定我的一个 blobby 创作,它可以预测(并显示)这幅画是鲍勃·罗斯自己画的会是什么样子。它需要在我半无能的输入和鲍勃·罗斯式的输出之间有效地转换

我们越来越接近把这个问题变成一个可解决的问题。我们需要的是一组训练数据——一组与真正的鲍勃·罗斯对等物配对的 blobby 绘画。为了实现这一点,我们需要经历一个艰苦的逆向工程过程——获取完整的鲍勃·罗斯画作,并为每一幅画创建一个 blobby 等价物。我们将鲍勃·罗斯绘画中的所有元素——雄伟的山脉、安静的河流、舒适的小屋、飘动的云彩和快乐的小树——用模糊的正确形状将它们渲染成简单的彩色斑点。我称这种风格为“Blob Ross”。

(The original is on the left)

在一个好朋友的帮助下,我制作了 250 多幅 Blob Ross 画作,并与鲍勃·罗斯原作配对,这是一个很小但希望足够的训练数据集。这是计算机将学习的数据,例如,推断一片皇家蓝色应该被渲染为一些戏剧性的阿拉斯加山脉,而一条青色应该成为一条蜿蜒的河流。

现在我们只需要一个可以学习解决这个问题的算法。在这种情况下,我在过去几篇文章中介绍的神经网络不会成功。正如我们所了解的,这些算法(像大多数机器学习算法一样),基于最小化错误的原则工作。他们产生的结果将是整个训练集中错误最少的,平均。但这是个问题。我来解释一下原因。

So majestic

这是一些鲍勃·罗斯画作中的山脉。虽然他们都是他的风格,但他们也有很大的不同——他们有不同的颜色,他们有不同的明暗图案,他们的形状也非常不同。试图预测这一点的传统算法会试图分割差异——它会试图准确地在所有罗斯山脉的中间找到颜色和形状。很可能会产生卡其色污迹。但是有更好的方法。

相对而言,人工智能中使用的大多数技术和算法都非常古老。神经网络,比如我用来识别中世纪杆臂的神经网络,(可以说)是在 20 世纪 40 年代首次描述的。现代机器学习中使用的许多其他技术甚至更古老。但我们在这篇文章中使用的技术是一个真正的新发明:“生成对抗网络”或“GAN”。

GAN 仅在几年前的 2014 年首次提出。GANs 负责一些最令人兴奋和最令人恐惧的计算机生成图像的最新创新,包括“deepfake”技术,它可以无缝地将一张新面孔粘贴到演员的身体上(通常是裸体的)。

虽然 GANs 建立在神经网络的概念上,但他们也引入了一个非常有趣的创新。GAN 不仅仅使用一个神经网络,而是使用两个,以一种相互竞争的方式工作。

第一个网络是“发电机”。对于给定的输入数据——在我们的例子中是我们的 Blob Ross 画作——它会产生一个预测图像——它认为鲍勃·罗斯会从该输入中得到什么。我叫它“机器人罗斯”。像其他神经网络一样,生成器开始随机做出选择,随着时间的推移,通过获得成功的反馈,学习做出更好的选择。但是它的不同之处在于它从哪里得到反馈。

第二个网络是一个“鉴别器”,它是发电机网络的反馈源。鉴别器被给予生成器的预测图像和真实的鲍勃·罗斯画作,并被要求猜测哪个图像是哪个。换句话说,它学会了区分由生成器生成的“假”鲍勃·罗斯画作和真品。

在鉴别器正确地检测到假货的情况下,这作为负反馈被提供给生成器,并且它调整它的过程,直到它能够更成功地欺骗鉴别器。通过以这种方式训练,生成器学会避免“卡其色污迹”问题。虽然它的第一次尝试非常模糊,但它很快就知道鉴别器可以很容易地检测到这一点。它变得更加狡猾,产生更清晰的图像,试图模仿真正的鲍勃·罗斯画作中的形状。结果是,经过足够长时间的训练后,生成器可以生成一幅有点令人信服的鲍勃·罗斯画作的复制品。

让我们看看实际情况是怎样的。

上面是一个输入图像(Blob Ross),它所基于的真实绘画(鲍勃·罗斯),以及生成器第一次尝试从该输入进行预测(Bot Ross)。在这个例子中,生成器从未见过真正的鲍勃·罗斯的画——它必须从它见过的其他画中进行归纳。不出所料,我们到处都是卡其色污迹。没有明确的细节,通过取每个区域的平均颜色,我们得到了一个模糊的中间地带。但是就像原来鲍勃·罗斯说的,通过练习,它可以做得更好!随着时间的推移,有了鉴别者的反馈,机器人罗斯学会了做得更好。

上面的图片是在训练过程中从这个模型的更高级版本中截取的。您可以看到生成器正在学习添加更多细节。树干得到了一些阴影,天空呈现出更多的纹理,松树开始形成它们特有的锯齿状边缘。但是我们也看到了其他一些有趣的发展。图像中有奇怪的线条和重复的斑点。这些是生成器的人工制品——它努力为大面积的空白空间创造细节,并倾向于重复相同的模式。

最终,经过数百轮训练后,生成器学会了避开这些赝像中最糟糕的部分,其结果即使人眼无法分辨,至少也变得可信得多。

它在绘画的某些区域比其他区域表现得更好。罗斯几乎在他的每一幅画中都用几笔娴熟的笔触描绘了标志性的松树,这些松树被精细地再现出来——斑点被赋予了锯齿状的松针边缘和锋利的尖端。因为松树出现在许多训练数据中,每次看起来都或多或少相同,所以 Bot Ross 能够很好地复制它们。这幅画的天空是令人愉悦的云彩和阳光的模糊——因为这里没有太多的细节,Bot Ross 已经知道他可以用任何他喜欢的模糊污迹填充天空,而鉴别者不会知道。

但是这个舒适的小木屋有点乱。这对机器人罗斯来说是一场完美的挑战风暴。在训练数据中,小木屋远不如山脉或松树常见。更糟糕的是,每幅画中的小屋看起来都非常不同。因此,机器人罗斯努力学习如何画它们。他提出了一个被雪覆盖的屋顶的建议,但大部分仍然只是一个斑点。

有意思的是,Bot Ross 把这个渲染成了雪景。他不是简单地平均训练画的颜色,而是根据构图——可能是光秃秃的树木等等——决定这应该是一个白雪皑皑的场景还是郁郁葱葱的场景,并给画适当地着色。看看其他例子,可以看出 Bot Ross 做出的一些有趣的选择。

你可以看到他有时很好,有时很坏。更多约定俗成的元素表现得相当好,但任何不寻常的东西都变成了模糊形状的混乱。

然而,对博特·罗斯来说,真正的挑战是看他如何与我的一件原创作品交易。这是我早期的画,“牙膏山”,旁边是它的“机器人罗斯”解释。

还不错!虽然没有完全达到原版鲍勃·罗斯的标准,但只要练习几个小时,肯定比我能做到的要好。现在没有必要让任何人浪费无数的时间在画架前埋头苦干,把刷子上的魔鬼打出来,或者寻找更多的酞青。有了这个机器人罗斯模型,任何人都可以立即像鲍勃·罗斯一样画画!

对我来说,Bot Ross 和 GANs 最有趣的一点是“假装”做某事和实际做那件事是一样的。我们的模型通过学习假装绘画来学习绘画,通过学习使自己的输出与真实的东西无法区分。这与图灵在 1950 年的论文《计算机械与智能》中提出的“模仿游戏”有明显的相似之处,这也是“图灵测试”概念的起源。简而言之,这个想法不是试图回答“机器能思考吗?”,这导致了毫无意义的哲学思考,我们应该解决一个更实际的问题:“一台机器能假装以一种足以说服人类观察者的方式思考吗?”换句话说,不要问“机器能思考吗?”,问“如果我分不清,又有什么关系?”

图灵写得比我在这里的篇幅更详细,说明了为什么这是一条富有成效的探究路线。但我认为机器人罗斯为这一论点提供了耐人寻味的支持。在图灵发表关于这个主题的论文半个多世纪后,我们继续了解学习和模仿之间复杂而密切的关系,以及假装做某事和实际上能够做某事之间微小的、可能不存在的差异。正如鲍勃·罗斯所描述的,博特·罗斯从未体验过绘画的快乐。它从未想象过自己行走在自己创造的微小景观中。但是看它的画,能看出区别吗?有关系吗?

感谢阅读!本系列上一篇文章,关于文本生成,可用 此处 。这个系列的结论将于下个月出版。

瓶颈:加速边缘智能的可学习特征压缩

原文:https://towardsdatascience.com/bottlenet-1d93b9393dd8?source=collection_archive---------38-----------------------

仅将 316 字节的数据上传到云中用于 ImageNet 分类

神经网络要么部署在本地设备上,要么部署在云服务器上。如果它非常大,那么唯一的选择就是云服务器。使用云服务的缺点是你需要上传一个比较大的输入的通信成本。将有价值的原始数据交给云所有者也会损害隐私。所以问题是为什么不卸载特性而不是原始输入呢?特征通常是稀疏的,我们可以在特征空间中实现更高的压缩比。BottleNet 是一篇介绍特征压缩方法的论文,该方法只需要将 316 字节的数据卸载到云服务器,以便在 ImageNet 数据集上进行推理。

BottleNet adds two extra units into an existing neural network. 1. A convolutional layer for reducing the channel/spatial dimensions 2. A lossy compressor (e.g. JPEG). Photo by author.

给定一个深度神经网络(DNN),我们插入一个减少空间和信道维度的卷积层。然后,我们将卷积的简化特征传递给 JPEG 压缩。这导致平均大小为 316 字节的数据需要上传到云中,以便进行其余的推理!比 JPEG 压缩的 224x224 图像少很多(平均 26667 字节)!在云上使用卷积层来恢复原始特征尺寸,然后进行 JPEG 解压缩。

Learnable dimension reduction and restoration units along the (a) channel and (b) spatial dimension of features. Photo by author.

但是如何训练一个中间有不可微层(JPEG)的神经网络呢?近似!因为一对压缩器和解压缩器可以用一个恒等函数来近似,所以我们简单地把它导数设为 1。

Embedding non-differentiable compression (e.g., JPEG) in DNN architecture. We approximate the pair of JPEG compressor and decompressor units by identity function to make the model differentiable in backpropagation. Photo by author.

因此,总之,我们在神经网络中添加了一组层(瓶颈单元),以减少将原始输入图像传输到云服务器的通信成本。如果我们有一个边缘设备,最好在初始层中插入瓶颈单元,以避免边缘设备的高计算成本:

Bottleneck Unit — all the reduction, compression, decompression, restorations units altogether. Photo by author.

如果我们简单地在中间特性上应用 JPEG 压缩,并将其卸载到云上用于下游层的其余计算,会发生什么?巨大的精度损失!但是如果在训练神经网络的同时意识到中间存在 JPEG 压缩单元,那么精度损失会变得更小。下图显示了这两种方法之间的精确度差距:

Accuracy loss will be much lower if the network is aware of the presence of JPEG compression on its features. RB1 in this figure refers to the first residual block of the ResNet-50 model. Photo by author.

https://arxiv.org/abs/1902.01000 找到更多关于 BottleNet 的信息。

这项工作已发表在 2019 年低功耗电子与设计国际研讨会(ISLPED)上。https://ieeexplore.ieee.org/document/8824955/

有界聚类

原文:https://towardsdatascience.com/bounded-clustering-7ac02128c893?source=collection_archive---------23-----------------------

一种适用于有限规模聚类的聚类算法

想象一个非常现实的场景,你所在城镇的几个家庭计划一起去旅行。

为了节省运输费用,他们想租几辆小型公共汽车。当然,越少越好。为了使交通安排高效和愉快,他们希望每个家庭都呆在同一辆小巴上,并根据地理位置将这些家庭分开,以避免多余的弯路。

Our input data of families, each pin indicates location and number of people who want to join the roadtrip.

用数学的方法来说,我们有n个家庭,每个家庭f的家庭成员数量是s(f),每辆小型货车的座位数量是mnk小巴中家庭的有效划分是指每辆小巴中家庭成员的总数不超过小巴的载客量。一个好的隔断是指每辆小型货车经过的距离最小。一个大的分区,是一个在最小化小客车数量和最小化每辆小客车行驶距离之间进行权衡的优化分区。

本帖包含伪代码。对于真正的代码你可以去 这里

听起来相当困难,是吗?

确实如此。一辆小型公共汽车的情况可以很容易地简化为背包,使得手头的问题在计算上是 NP 困难的(更准确地说,是 NP 完全的,但是谁在计算)。因此,很明显,如果我们想大规模解决这个问题,我们并不是在寻找一个精确的解决方案。

我们能做什么?

让我们把它分成两步:

  1. 给定一个常数k,找到一个k小型公共汽车家庭的(启发式)最佳划分。
  2. 找最好的k

步骤(1)将为我们构建好的分区,而步骤(2)将帮助我们找到一个好的分区。

步骤 I -有界 K-均值聚类

顾名思义,要为给定的k找到一个分区,我们将使用著名的 K-Means 聚类算法的一个变体,该算法受本文中的启发。

类似于 K-Means,我们将实现迭代算法,该算法在寻找每个聚类的质心(更新步骤)和将点分配到最近的质心(分配步骤)之间交替。在这个变体中,分配步骤也将确保集群保持它们的有界大小。

让我们更精确些,从头开始。经典的 K 均值算法大致是这样的:

1    centroids <- random *k* points
2    do *n_iter* times:
2.1     clusters <- each point assigned to closest centroid
2.2     centroids <- point closest to center in each cluster
3    return clusters

现在,考虑到有界簇的变化,我们将以如下方式修改步骤2.1,即分配步骤:

(2.1).1   points <- sort points by weight, in descending order
(2.1).2   for each point in points:
(2.1).2.1    centroids <- sort centroids by distance from point
(2.1).2.2    centroid <- first centroid in centroids for which total
                         weight + point's weight does not exceed *m*
(2.1).2.3    add point to cluster corresponding to centroid

你可以在这里看到代码。

Iterative process of updating clusters, starting from random guess of centroids.

K-Means 需要记住的另一件事是,这个过程容易不稳定,它可能终止的局部最小值高度依赖于第一次随机猜测。
因此,习惯上要重复执行几次算法,并选择最佳结果。根据 sklearn.cluster.KMeans默认是 10 次重复,我们也跟着做。

Example of 4 different repetitions of the algorithm, with 4 different random initial centroids. In bold is the best outcome. Circled are areas where clusters are not well separated, indicating the suboptimality of the outcome.

第二步-选择最佳 K 值的肘法

好了,现在我们知道了如何为固定数量的小巴k找到一个好的分区,那么我们如何才能找到“最好的”k

在最小化小公共汽车的数量和最小化每辆小公共汽车行驶的距离之间做出适当的权衡并不容易。

幸运的是,有些聪明人已经想了很多,常见的做法是用肘法,大致是这样的:

1   min_k <- sum(weights) / max cluster size
2   max_k <- min_k + number of sizes to try
3   for each k between min_k and max_k:
3.1    cost_k, clustrs_k <- Bounded K-Means Clustering
4   l <- line between (min_k, kcost_min_k) and (max_k, cost_max_k)
5   opt_k <- (k, cost_k) of maximal distance from l

Elbow Method: (i) perform K-Means Clustering for a range of different values of k, (ii) draw line between edge values, (iii) find value of k that its cost is furthest from the line.

让我们看看我们的家庭旅行数据是什么样的:

Partitioning our input data into the optimal number of clusters, k=8. In our input we had 45 families, with total 82 people, and minibuses of size 12.

复杂性分析

让我们分析我们的有界 K 均值聚类的一次迭代。记住我们表示:n家庭数量,m小型公共汽车最大尺寸,k小型公共汽车数量。

  • 在每个赋值步骤中,我们有:
    ➪按权重排序点:n*log(n)
    ➪对于每个点:排序质心k*log(k),添加到第一个有效质心k
    ➪总计O(n*log(n) + n*(k*log(k) + k)) = O(n*log(n)*k*log(k))
  • 在每个更新步骤中:
    每个聚类中的最大点数为n,或者当权重为整数时为m
    所以,对于每个集群我们需要:
    ➪计算集群的中心:n
    ➪找到离中心最近的点:n
    所以对于所有集群:O(k*n)
  • 因此,每次迭代都有O(n*log(n)*k*log(k))复杂度

如果我们在每次聚类运行中执行x迭代直到收敛,并且y以不同的随机初始状态运行,我们得到O(x*y*n*log(n)*k*log(k))

现在记住,我们要对不同数量的k进行此操作。让我们将K表示为我们想要尝试的最大值,将z表示为不同k的数量,然后我们得到总数O(x*y*z*n*log(n)*K*log(K))

肘方法在K中具有线性复杂度,这不会改变我们的最终结果😅。

收场白

我个人在这个问题上的经历是,我真的不得不在工作中解决类似的问题。我的第一反应是使用贪婪的局部搜索,我知道这在类似的几何问题中非常有效。

然而,我挑战自己走出自己的舒适区,并向一些同事和同行寻求建议。很高兴, Orian Sharoni 很快作出回应,向我推荐了两篇论文(有界 K 均值聚类+肘方法),这两篇论文总结了所有内容。比我想象的多花了几个小时,但是我设计的解决方案更优雅,而且很可能更接近最优(没有测试过,但是我的直觉告诉我)。

总之,作为一名算法开发人员,尤其是在快节奏的初创企业中工作的人,当我只想完成某件事时,使用 go-to-methods 会有所帮助。但是,偶尔,它甚至更有助于探索新的想法,学习新的方法,并扩大我的大脑“去算法”库。

希望你喜欢和我一起踏上这段旅程,也希望你今天拓展了你的心智图书馆🤓

向伯特鞠躬

原文:https://towardsdatascience.com/bow-to-bert-2695cdb19787?source=collection_archive---------36-----------------------

单词向量经过多年的发展,已经知道了“记录剧本”和“播放唱片”之间的区别。它们已经从一个每个单词都与其他每个单词正交的世界,发展到一个单词向量根据上下文变化的地方。给单词向量打上蝴蝶结是为分类等任务构建文档向量的常用方式。但是伯特不需要弓,因为从顶部[CLS]记号射出的向量已经为特定的分类目标准备好了…

自然语言处理(NLP)在过去十年中经历了一次复兴。人们对能够像人一样理解和处理语音/文本的嵌入、变形和语言模型感到非常兴奋。这种进步是不折不扣的。像总结文档、机器翻译、完成句子和对话这样的功能,现在正在尝试并取得了一些成功。事实上,这是一个从自然语言处理到 NLU(自然语言理解)的演变过程。伯特(来自变压器的双向编码器表示)模型归因于德夫林等人。艾尔。恰好是这个领域目前的领导者。

传统的自然语言处理毫不犹豫地让理解它正在处理的单词/文本。它甚至没有尝试。但这并不意味着它完全无用。事实上,在对通用文档进行分类时,一个热词向量用一个蝴蝶结(词袋)绑在一起,这些年来做得还不错。当然,理解单词的语义/上下文并相应地对文档进行分类会更好。这就是像 BERT 这样的新语言模型带来的东西——尽管有一些花费。

这篇文章的目的是看看单词向量从一个热点到上下文的演变。我们从没有朋友的单词开始,作为一个热点向量,它是一个正交单词空间的基础,其大小与词汇表的大小一样。我们转到单词嵌入,它结合了同现统计,使单词有一个固定的朋友圈。最后是考虑到上下文的 BERT 嵌入,从而根据情况让单词交新朋友或解除当前朋友的好友关系。友谊是用余弦相似度来衡量的。我们从不同的句子/上下文中提取相同和相似的单词,并查看它们对应的单词向量的余弦相似性是否与我们对这些单词在这些句子中的含义的理解相吻合。这基本上是这篇文章的主旨。

最后,这里的重点是单词嵌入的这些进步对我们意味着什么,我们如何应用它们并从中受益,而不是这些进步如何实现的技术细节。我们在这里浏览一些代码片段,但是完整的代码可以在 github 上重现结果。

在讨论单词向量之前,我们先简要回顾一下 BoW。在即将发布的帖子中,我们也需要它来从 one-hot 和 fastText 单词向量构建文档向量。在本系列的下一篇文章中,我们将针对几个分类任务,针对伯特[CLS]令牌向量来评估这样的文档向量。

1.一袋单词

在单词袋(BoW)方法中,文档向量是组成文档的单词的数字向量的加权和。权重可以简单地是该单词在该文档中的频率计数、一个 tf-idf 值或其他变化。

Equation 1: The BoW vector for a document is a weighted sum of word-vectors When w_i is one-hot then p = N. When w_i is obtained from fastText, Glove, BERT etc… p << N

弓形向量的一个明显缺点是文档中单词的顺序没有区别,如下图所示。

Figure 1. source

2.词向量

等式 1 中有字向量 w_i 的选项。传统的 NLP 从使用一个热点向量开始,而最近(从 2003 年开始)的参与者使用其他向量进行实验,以解决这些一个热点向量的缺点。

2.1 长而一热

在传统的 NLP 中,每个单词都是一个与其他单词正交的向量。单词向量长度 p 等于 N ,即单词空间的维数。第字的向量在第位置为 1,在其他位置为 0。因此得名一热矢量。简单来说,第字向量是第个维度的字空间中第个维度的基向量。

那么文档就是这个 n 维单词空间中的一个点/向量,坐标是{ W^j_i }。实际上,等式 1 中的 W^j_i 可以是 jth 文档中带字的的频数,也可以是类似 tf-idf 的变体。下图演示了 shred-bag-tag 操作,该操作将文档转换为单词空间中的向量。

Figure 2. In word space, a BoW vector for a document is a point. It is a weighted (the word count in this case) sum of the one-hot word vectors making up the document.

一键词向量的一些问题

  1. 太长:和正在处理的文本语料库中的词汇量一样长。这是一个计算上的缺点
  2. 无意义的记号:单词被当作只是没有意义的记号,与其他单词没有关系。您可以将语料库中的单词 good 替换为一些垃圾单词,如gobbeek和 BoW care——只要这个新单词gobbeek还没有出现在语料库中。事实上,您可以将语料库中的每一个 N- 单词替换为一些随机的不冲突的单词,BoW 将为您提供相同的文档向量。
  3. 没有上下文/位置感知:每个单词只有一个向量,并且每个单词向量都与所有其他向量正交。因此不存在上下文/位置相关单词向量或与其他单词的关系的问题。但在现实中,我们知道文字是复杂的存在。
  • 一个给定的词有不同程度的同义词和反义词。好/更好/最好 & 好/不好/更差例如
  • 句子中同一个词的位置相关意义。记录播放vs播放记录播放记录的含义随着位置的转换而变化
  • 多义——明亮的可以表示闪亮的,或者例如智能的
  • 谐音— run 可以是棒球中的名词 run ,也可以是动词 run

2.2 短、密、固定

对更好的单词数字向量的努力始于 2013 年的 word2vec ,随后是 GlovefastText 。我们在这里的例子中使用了 fastText 单词嵌入,但是结论同样适用于其他例子。所有这些单词嵌入都是基于分布假设得出的,该假设陈述:

语义相关的单词将具有与其他单词相似的共现模式

根据这一假设,如果两个词通常保持相同的公司(其他词),那么这两个词是语义相关的。这些算法利用维基百科等大量文本来计算每个单词与所有其他单词的共现模式。这样获得的单词的数字向量表示作为优化过程的一部分对此进行编码。这里获得的字向量在两个方面比一键向量有所改进。

2.2.1 词向量现在更短了

这里得到的单词向量的长度 pN 小很多很多。虽然 N (一个热词向量的长度)可以达到几十万,但是 p 更像是 50 或者 100 或者 300。这是一个巨大的计算优势。

2.2.2 单词现在有朋友了

在这个一热的世界里,所有的单词都是相互独立的——这不是一个有用的场景。单词好的坏的更好的都正交。在分布假设下获得的单词向量在某种程度上弥补了这一点。它们使单词能够相互联系,在某种程度上模仿对文本的理解。

假期休假论文这些词为例。单词假日休假与其他单词如旅行海滩等一起出现。它们拥有相似的单词组合——因此它们与其他单词有相似的共现模式。所以他们的词向量通过更加相似/平行来反映这一点。超过什么?比他们更相似/平行的是一个像一样的词。这也符合我们对这些词的自然理解。从 fastText 中读取 300 维( p = 300)单词向量,我们可以很容易地计算这些单词的余弦相似度。运行fast text _ word _ similarity . py

pipenv run python ./fasttext_word_similarity.py holiday vacation paper

显示出假期假期之间的相似性比预期的大得多。

Cosine Similarity: holiday & vacation : 0.7388389
Cosine Similarity: holiday & paper : 0.2716892
Cosine Similarity: vacation & paper : 0.27176374

从诸如文档分类的更大任务的角度来看,使所有的词向量都正交是没有帮助的。BoW 文档向量是从等式 1 中的单词向量构建的。当使用一个热门单词向量时,具有相似但不同单词的两个句子将表现出零余弦相似性。而是与快速文本单词向量的非零相似度。例如,与类似于“研究论文”的句子相比,句子“享受假期”将具有更类似于“享受你的假期”的弓形向量。运行fast text _ sentence _ similarity . py我们看到前两个句子的余弦相似度更大。

pipenv run python ./fasttext_sentence_similarity.py

# words not found in fasttext.. 0
Cosine Similarity: enjoy your holiday & have a fun vacation : 0.72311985
Cosine Similarity: enjoy your holiday & study the paper : 0.5743288
Cosine Similarity: have a fun vacation & study the paper : 0.51478416

2.2.3 但是仍然没有上下文意识

与单词的上下文和位置相关的问题没有通过分布假设来解决。这是我们在 2.1 节中列出的唯一热门词向量的最后一个缺点。即使一个单词已经有利地获得了与其他单词的一些关系,一个单词仍然由单个**相同的向量表示,无论它出现在文本中的什么地方。

例如,板球中的音高与音乐中的音高不同。与音乐中的 pitch 相比,板球中的 pitch 这个词与众不同。所以他们真的没有很多共同的朋友,所以应该有不同的表现。如果板球球场的训练语料来自体育部门,音乐球场的训练语料来自艺术部门,他们会的。但事实并非如此,考虑到上下文和词汇的多样性,这种方法也无法扩展。这里为一个单词获得的嵌入是它出现的所有上下文的平均值,因此失去了上下文…这导致了 BERT 所属的最新一批语言模型。

3.简短、密集且上下文敏感

诸如 ELMOGPT-2伯特的语言建模工具允许获得知道它们的位置和环境而变形的词向量。请参考杰·阿拉姆马的优秀系列文章、插图伯特、ELMO 等人的文章(NLP 如何破解迁移学习注释转换器等……了解这是如何实现的。我们直接跳到使用 BERT 来观察它生成的上下文,以及有意义的单词的位置感知向量。

预先训练好的 BERT 模型可以下载,它们有运行 BERT 的脚本,并从任何和所有层获取单词向量。我们在这里使用的基本情况 BERT 模型采用了 12 层(变换器块),并且产生具有 p = 768 的字向量。下面的脚本getbertwodvectors . sh读入一些句子,为每个句子中的每个单词生成单词嵌入,并且从 12 层中的每一层生成。

Script to obtain BERT embeddings

我们从第 11 层提取嵌入(为什么是第 11 层?你也可以试试其他的。 Bert As a Service 使用第 11 层:)用于我们的工作并计算余弦相似度。

Process BERT embeddings and compute cosine similarity

我们的目标是展示 BERT 单词向量是基于上下文变化的。以下面三句话为例。

  • 录制播放**
  • 播放 记录
  • 游戏

第二句话里的这个词应该和第三句话里的比较像,和第一句话里的比较不像。我们可以想出任何数量的像上面这样的三元组来测试 BERT 嵌入做得有多好。这里有一堆这样的三元组,结果显示伯特能够找出这个单词的上下文。

Figure 3. BERT embeddings are contextual. Each row show three sentences. The sentence in the middle expresses the same context as the sentence on its right, but different from the one on its left. All three sentences in the row have a word in common. The numbers show the computed cosine-similarity between the indicated word pairs. BERT embedding for the word in the middle is more similar to the same word on the right than the one on the left.

当分类是更大的目标时,不需要从 BERT 嵌入中构建 BoW 句子/文档向量。文档开头的[CLS]标记包含一个为特定分类目标而微调的表示。但是对于一个聚类任务,我们确实需要处理单个的 BERT 单词嵌入,并且可能在顶部使用 BoW 来产生我们可以使用的文档向量。我们将在以后的文章中讨论这些问题。

3.结论

我们跟踪了词向量从长/稀疏/一键到短/密集/动态的演变。这是一个从一个单词没有朋友的地方(one-hot,orthogonal),到有朋友圈的地方(例如 fastText),以及目前可以适应和找到朋友的地方(例如 BERT)的旅程。这些进步逐步提高了我们对文本建模的能力。

就这样,我们结束了这篇文章。在下一篇文章中,我们将继续评估这些词向量,以完成几个分类任务。

BPDR:一种新的降维技术

原文:https://towardsdatascience.com/bpdr-a-new-dimensionality-reduction-technique-f570eea3fc65?source=collection_archive---------14-----------------------

一种新的降维方法介绍。

介绍

LDA、PCA 或 t-SNE 等降维算法是分析未标记(或标记)数据并获得更多有关其结构和模式信息的强大工具。降维使我们能够可视化高维数据集,这对模型选择非常有帮助。我认为,机器学习的这一子集——称之为数据探索——与其对手(如监督学习或深度学习)相比,还远远不够发达。

我的观点: 如果有人开始一个新的机器学习项目,他们做的第一件事将是对数据进行探索性分析。不同的研究人员对这一步应该有多深入有他们自己的想法,然而,数据探索的结果是关于手边的数据集获得的知识。当研究人员遇到各种问题,如模型选择和超参数调整时,这些知识被证明是非常有价值的。

通过从根源开始,开发漂亮的数据探索算法,为用户提供关于数据集底层模式的质量信息,我们可以从整体上开发更好的机器学习管道。

Some binary numbers. (Photo Credit: Fotomay/Shutterstock)

BPDR 背后的想法是受我在大学里为一个班级写的图像压缩器的启发。这个想法就是位打包:将不同的数据点编码成一个长二进制字符串。

我将省略算法是如何构造的许多细节。对于那些对这个算法的“幕后”感兴趣的人来说,代码可以在我的 GitHub 这里查看。

该算法

该算法的概述如下:原始数据列(必须都是数字)首先按重要性排序。然后将数据归一化,以 0 为中心。接下来,构建了 N 个 128 位的字符串来表示我们试图减少到的 N 个组件。规范化数据按照其功能重要性的顺序被二进制打包成 128 位字符串。最后,我们剩下的是可以转换回整数的压缩二进制数。

对于将减少到 2 列的 4 列数据集,二进制打包如下所示:

binary string 1 -> 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0  (128-bits)
                  | most important  |2nd important col|
                   -----------------------------------binary string 2 -> 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0  (128-bits)
                  |3rd important col|4th important col|
                   ------------------------------------> repeat this packing for each row

再一次,这部分是作为算法如何工作的一般概述,然而,它不是很深入。

如何使用 BPDR

我构建了 BPDR 模块,以便它模仿 Scikit-Learn 包中其他维度算法的工作方式。下面是它在 iris 数据集上的一个使用示例。

首先, BPDR 仓库需要从 GitHub 中克隆出来。导航到 BPDR 目录后,运行pip install -r requirements.txt以获得运行算法的正确包。现在,我们终于准备好打开一个新文件,并开始探索数据。

首先,我们必须将所需的包导入到我们的模块中:显然,我们将使用 BPDR,以及所有流行的 iris 数据集和 matplotlib 进行一些可视化:

from bitpack import BPDR
from sklearn import datasets
import matplotlib.pyplot as plt

接下来,我们加载数据集:

iris = datasets.load_iris()
iris_data = iris.data
iris_targets = iris.target>>> iris_data[0]
[5.1 3.5 1.4 0.2]

我们看到有 4 列(都是数字)。让我们将这个数据集减少到 2 列,以便我们可以用图形显示减少的组件。我们首先需要创建一个 reduction 对象的实例,并初始化它的参数。

bpdr = BPDR(n_components=2)

接下来,通过调用 fit_transform 函数,传入的数据将被减少并返回到一个新数组中:

bpdr_data = bpdr.fit_transform(iris_data, iris_targets)>>> bpdr_data[0]
[7.686143364045647e+17, 4.0992764608243425e+18]

因为我们传入了标签,所以我们可以查看一些方差度量,这些度量评估缩减的数据对原始数据的解释程度:

>>> print(bpdr.variances)
[3.476833771196913e+36, 4.83034889579370e+36, 9.75667133492751e+36]>>> print(bpdr.scaled_variances)
[0.5774239158754918, 0.8022123454852088, 1.6203637386392993]>>> print(bpdr.mean_variance)
6.021284667306044e+36

有关如何计算这些差异的更多信息,请访问存储库的文档。

最后,我们现在有了一个 2 列宽的数据集,可以用图表显示出来。当组件 1 绘制在 X 轴上,组件 2 绘制在 Y 轴上时,图形如下所示:

Iris dataset after BPDR reduction

图中不同的颜色代表了花的不同标签。很明显,每个标记组都有不同的聚类。这种结构表明该算法很好地在较低的维度中表示了完整的数据。作为比较,我们看同样的图,但是使用主成分分析:

Iris dataset after PCA reduction

BPDR 归约实际上创建了一个比 PCA 更具线性可分性的数据集。这并不意味着 BPDR 算法对所有数据都是更好的算法,它只是意味着它值得研究,尤其是在执行线性回归类型的模型时。

本文的所有代码都可以在 GitHub 库的 Jupyter 笔记本中找到。

大脑:一个谜

原文:https://towardsdatascience.com/brain-a-mystery-5b1511e56f88?source=collection_archive---------34-----------------------

“我们能拥有的最美丽的经历是神秘的。”——阿尔伯特·爱因斯坦

介绍

人类拥有最密集的神经元(860 亿)。这赋予了我们所拥有的智慧,我们辨别抽象概念、做出跨领域决策和进行天马行空式思考的能力。如果你只是观察自己每天的行为,很有可能你会感到惊讶。最棒的是,当你试图对大脑实际上是如何工作的提出自己的假设,并审视这些预先存在的框架时,这不亚于欣赏一件宁静的艺术品。在这篇文章中,我将试图展示是什么让大脑如此强大,以及理解大脑的一些框架和方法,以及它是如何学习的。

是什么让大脑如此特别

Picture taken from https://commons.wikimedia.org/wiki/File:Neuron.jpg

  1. 根据神经元学说,神经元是大脑的基本结构和功能单位。
  2. 神经元通过细胞体将信息以电脉冲的形式从树突传递到轴突。这需要维持体内和体外之间的离子电势差,这占据了身体每日葡萄糖消耗的大约 20 %。
  3. 髓鞘通过缠绕轴突来辅助电脉冲尖峰的快速无损长距离通信。这是通过一种称为跳跃传导的机制发生的,在这种机制中,尖峰从 Ranvier(髓鞘间隙)的一个节点跳跃到另一个节点。这表明大脑是如何完美地包含了无损信号传输的概念。
  4. 两个神经元之间的连接被称为突触,它可以具有电和化学性质。电用于反射等功能的快速传输,化学用于学习和记忆。
  5. 激发神经元是一个能量密集型过程,因此所有神经元不会同时激发。这表明大脑中可能有一种惊人的能量优化调度算法。
  6. 神经网络中权重的概念可能是受赫比可塑性概念的启发,赫比可塑性通常被理解为一起放电的细胞
  7. 大脑有各种各样的重要组成部分,并且每一个都是相互联系的。对我来说最有趣的是丘脑,它就像一个基站,从我们的感觉器官接收输入信号,然后将其传递到大脑皮层,大脑皮层通常被称为这场表演的明星。
  8. 说到资源管理,大脑是很棒的。大脑执行的许多任务都是无意识完成的,因此我们可以进行多任务处理,如大规模并行计算。
  9. 有许多神经元的子网络,它们也构成了一个更大网络的一部分,并与更小的网络相连。
  10. 说到学习和记忆,大脑有不同的方式。
  • 短期或工作记忆是我们有意识的、动态的记忆。
  • 长期记忆或情景记忆是我们能够回忆起的过去的记忆。有趣的是,它是有偏见的,这在跟踪相关信息而不是所有信息时非常有用。
  • 操作性条件反射是一类学习,其中奖励或惩罚会影响学习过程。这可能启发了强化学习领域。
  • 我们记忆和学习的本质是语义的。它不仅仅是基于过去经验存储的纯粹信息,而且在形成概念的各种记忆片段之间也存在相互依赖。

惊人的想法和作品

虽然有许多伟大的作品旨在模拟大脑的活动,但这些是我最喜欢的。

人工神经网络

这些网络受到神经元生物网络的启发。每个节点代表一个神经元,权重表示来自该节点的信号有多重要。有一个激活函数作为信号通过的阈值,并且通过相对于真实标签反向传播损耗来进行学习。神经网络的许多伟大的变种有 CNN,RNN,甘,自动编码器等等。

神经图灵机

图灵机是一个杰出的数学模型,由艾伦·图灵发明,由程序、磁带和寄存器组成。本文由 DeepMind

神经图灵机

使用类似于图灵机的架构,但保持一切差异,以便学习可以通过梯度下降进行,但附加了一个附加的内存组件,可以使用注意机制进行交互。这是数字计算机设计和生物学结合的一个独特的交叉点。

持续学习

如果我们从某个发行版中学到一些概念,我们实际上可以在不同的发行版中使用这些概念。这就好像一个人学会了如何在特定的环境中用特定的菜肴吃饭,也可以在别的地方吃不同的菜肴。因此,任务保持不变,但分布发生了变化。在这种情况下,神经网络需要在整个数据集上再次训练。这是由 Friedemann Zenke 等人在本文中提出的

通过突触智能不断学习

如该文件所述

“在这项研究中,我们引入了智能突触,将这种生物复杂性引入人工神经网络。“每个突触都会随着时间的推移积累与任务相关的信息,并利用这些信息快速存储新的记忆,而不会忘记旧的记忆。”

迁移学习

原则是通过执行特定任务获得的知识被用来解决不同的问题,而这些问题在某种程度上是相似的。这在计算机视觉和自然语言处理中非常流行,其中使用预先训练的模型,然后进行微调以执行特定的任务,通常会产生很好的结果。谈到计算机视觉,有 ResNet、InceptionNet,对于 NLP,有 BERT、GPT-2 等等。

深度强化学习

AlphaGo、AlphaStar、MuZero 都是令人震惊的创新,它们使用不同味道的深度强化学习来展示特定任务中的超人智能,如玩星际争霸、围棋、象棋、雅达利游戏等,主要使用基于深度神经网络架构的奖励机制来优化奖励功能。强化学习的主要变体是基于模型的、基于价值学习的和基于策略梯度的。

使用统计不变量的学习

这是由 Vladmir Vapnik 等人在论文中提出的。

重新思考统计学习理论:使用统计不变量学习。

如该文件所述

‘在 LUSI 范式中,为了构造期望的分类函数,学习机计算特定于问题的统计不变量,然后以保持这些不变量的方式最小化期望误差;因此,这既是数据驱动的学习,也是不变量驱动的学习。

‘在这个新的范例中,首先选择(使用不变量)一个包含所需解决方案的容许函数子集,然后使用标准训练程序选择解决方案

‘LUSI 方法可用于提高所得解的精度,并减少必要的训练样本数量。’

蛋白质折叠分析和基因组编辑

虽然这并不直接模拟人脑或其任何活动,但旨在利用先进技术更深入地分析构成大脑的生物成分。像 AlphaFold 这样的最新创新可以预测体内特定蛋白质的结构,这可以帮助科学家了解它在体内的作用。由于蛋白质是每个细胞的重要组成部分,对它的深入了解可以解开许多关于大脑行为方式的秘密。

同样,基因组编辑也被科学家普遍用于研究细胞和理解它们的基本工作,最著名的技术是 CRISPR-Cas9。对基因序列的更深入了解可以回答许多关于我们的大脑如何世代进化的问题。

大脑器官样

这是一个在实验室环境中使用人体干细胞人工开发的迷你大脑。这对于理解大脑发展的不同阶段非常有用,并可能提供关于大脑的更深入的见解。

结论

作为人类,我们发展概念,从更少的数据中学习。这可能是由于嵌入我们基因中的进化信息。尽管如此,每次我遇到一个新想法时,模拟大脑活动的工作量都让我震惊。对我来说,理解大脑的动机不是人工智能,而是欣赏这样一个奇妙的创造。更令我惊讶的是,计算机科学、数学、生物学、心理学和其他领域是如何走到一起,用一种共同的语言进行交流,试图解释自然。

这个难题可能会有缺失的部分,也许将大脑建模为一个独立的单元可能不是一个好主意,因为大脑的功能在很大程度上取决于感觉器官如何感知环境以及各种内部器官作为一个整体系统如何立即行动。

然而,正如艾伦·图灵所说

“发明一台可以用来计算任何可计算序列的机器是可能的。”

也许我们已经有了那台机器。

基于金字塔场景分析的脑肿瘤分割

原文:https://towardsdatascience.com/brain-tumour-segmentation-using-pyramid-scene-parsing-pspnet-198168d22235?source=collection_archive---------17-----------------------

用数据做酷事!

简介

癌症是自古以来人类面临的最致命的疾病之一。全世界每年有近 30%的人口死于癌症。如果肿瘤在早期被发现,存活的机会会大大增加。深度学习(CNN)已经改变了计算机视觉,包括对医学图像的诊断。在这篇文章中,我们将利用 CNN 的力量从脑 MRI 图像中检测和分割肿瘤。

见下图中带有肿瘤的脑部 MRI 图像示例和分割结果。左图是绿色肿瘤的脑部核磁共振扫描。右图用红色显示了肿瘤的机器预测。这是惊人的准确!

Tumor prediction example

我们已经与初创公司合作,使用语义分割构建各种应用程序。请联系我们,了解更多信息。

语义分割

语义分割是将图像中的像素标记为一类。在上图中,我们将图像中的所有像素标记为肿瘤或背景类。已经公布了许多基于深度学习的高效语义分割方法,例如(按时间顺序) :

  1. FCN
  2. UNet
  3. SegNet
  4. 扩张的回旋
  5. 深度实验室(v1 和 v2)
  6. 精制网
  7. 金字塔场景解析网络
  8. DeepLab v3

对于这个博客,我们选择了 PSP-Net,因为它非常有效,并且比许多先进的方法如 U-net,FCN,DeepLab (v1,v2)和扩张卷积等都要好。

DeepLabV3 是另一个流行且强大的模型。我最近写了一篇关于如何使用 DeepLabV3 以 30 FPS 进行语义分割的博客

要了解以上列出的不同分段架构的更多信息,请参考这篇帖子

金字塔场景解析网

最新的场景解析框架大多基于全卷积网络(FCN)。基于深度卷积神经网络(CNN)的方法促进了动态对象理解,但仍然面临着考虑不同场景和无限制词汇的挑战。一个例子是船被误认为汽车。这些错误是由于对象的相似外观造成的。但是当查看关于场景被描述为河边的船屋之前的上下文的图像时,应该产生正确的预测。

准确的场景分类依赖于对全局场景类别的先验知识。金字塔池模块通过应用具有大内核的池层来帮助捕获这些信息。使用膨胀卷积(参考:膨胀卷积论文)对 Resnet 进行修改,并增加了一个金字塔池模块。该模块将来自 ResNet 的特征映射与并行池层的上采样输出连接起来,其中内核覆盖整个图像、图像的一半和一小部分。

下图描述了 PSPNet 架构。你可以在他们的论文这里中读到更多关于 PSPNet 的内容。

PSPNet Architecture

利用 PSPNet 建立脑图像分割模型

数据集

数据集是从 Kaggle 获得的。之所以选择这种方法,是因为标记的数据是二进制掩模图像的形式,易于处理并用于训练和测试。或者,这款来自 VGG 集团的基于网络的注释工具可以用来标记自定义数据集。

数据集遵循以下文件夹层次结构:

资料组

| _ images—png 格式的 RGB 图像

| _ masks 屏蔽 png 格式的 RGB 图像,其中区域填充有各自的标签值。

我们的标签是:1 代表肿瘤,0 代表其他

例如:

假设像素(10,10)属于肿瘤,它包含值 1。

培训框架

虽然存在许多令人惊叹的框架来使用 Keras 培训和评估语义分割模型,但以下 repo 因其易用性、支持的不同模型数量以及最新的文档而脱颖而出:

https://github.com/divamgupta/image-segmentation-keras

我们选择了“vgg_pspnet”,这是一个在预训练的 vgg 主干网上实现的 pspnet。

要遵循的步骤是:

一旦安装了回购,就可以开始培训了!

# Navigate to the **Semantic_segmentation/image-segmentation-keras** folder**import keras****from keras.models import model_from_json****import keras_segmentation as ks**# Initialise the pretrained model .# Note that the input height and width need not be same as image height and width since the network takes care of the input sizes.**model = ks.models.pspnet.vgg_pspnet( n_classes=2,****input_height=384,****input_width=384)**# Training**model.train(****train_images = “datasets/brain/images”,****train_annotations = “datasets/brain/masks”,****checkpoints_path = “ckpts/brain” , epochs=50 ,****auto_resume_checkpoint = True,****steps_per_epoch = 50****)**

通过训练好的模型运行推理

# Load Neural Network**model = ks.predict.model_from_checkpoint_path(‘ckpts/brain’)**# Predicted output will be a mask image similar to the mask images specified in the input**pred_mask = ks.predict.predict( model = model , inp = ‘image.png’ )**

下面是我们在数据集的一个小子集上获得的结果。虽然数据集很容易过拟合,但高精度的结果显示了这种方法的潜力。

图像顺序:原始图像(左)、预测遮罩(中)、覆盖遮罩边界(右)

结论

希望你喜欢这个博客,并尝试自己的代码。这个博客表明,我们可以使用预训练的模型在半天的工作中获得良好的分割结果!它真正展示了基于深度学习的计算机视觉的力量。

我们可以将该代码扩展到任何具有待分割特征的医学图像。例子包括不同种类的癌症肿瘤、微生物、骨折、洞等。

我有自己的深度学习咨询公司,喜欢研究有趣的问题。我已经帮助许多初创公司部署了基于人工智能的创新解决方案。在 http://deeplearninganalytics.org/的入住我们的酒店。如果你有一个我们可以合作的项目,那么请通过我的网站或者在info@deeplearninganalytics.org联系我

你也可以在https://medium.com/@priya.dwivedi看到我的其他作品

参考文献:

大脑 1:0 人工智能

原文:https://towardsdatascience.com/brains-1-0-ai-190091808760?source=collection_archive---------16-----------------------

为什么生物大脑仍然领先于任何已经建立的人工智能…或者未来许多年将要建立的人工智能。

Brains are still way ahead of any AI available today

当阿尔伯特·爱因斯坦说“深入观察自然,然后你会更好地理解一切”时,他脑海中没有人工智能(AI)。他提醒我们,每一种理论都需要与它应该解释的现实“保持联系”。人工智能也是如此,这是一项基于脑科学的数十年科学研究产生的技术,从基础神经科学到其计算神经科学表弟,经过数学,物理和计算机科学。

如果我们遵循爱因斯坦的建议,并像他建议的那样“研究自然”,我们将会被生物智能如何将当前(和可预见的未来)的人工智能甩在身后而震惊。

自然智能充满了计算杰作,使学习和适应不断变化的世界变得如此流畅和无缝,以至于对机器的所有者,我们人类来说,它实际上是不可见的。

据说“科技在看不见的时候处于最佳状态”

只有揭开这个难以看到的生物技术及其奇迹的面纱,我们才能真正与人工智能进行有意义的比较,并真正认识到它的局限性。

我们大脑中不断发生而我们却没有意识到的事情是什么?

让我们更仔细地看看我们的大脑每天都在发生什么。

自然智能的“计算核心”是神经元,在典型的大脑中,人类平均拥有大约 100 个神经元。

Humans have around 500 trillion learning synapses

神经元通过尖峰信号(低压电流的小脉冲)相互通信,其中神经元尖峰信号可以参与表示图像特征的存在(例如,苹果中的“红色”)。当神经元倾向于被一起激活时,它们之间的连接,称为突触,倾向于得到加强。这就是为什么“红色”往往与“苹果”联系在一起:它们的重复出现导致编码这些特征和物体的神经元之间的突触联系在一起——这是一种解释我们倾向于统计的大脑如何工作的机械基底:它帮助我们在我们原本混乱的世界中找到规律性。

这些“连线”——或学习——事件从形成的那一刻起,就一直在我们的大脑中发生。让我们估计一下这些个体学习事件在人的一生中会发生多少次。

假设一个典型的人平均有 1000 亿个神经元,500 万亿个突触,平均 20 亿秒的寿命,并假设大脑中的每个神经元每秒发出一个尖峰信号(这是一个较低的估计…我们的神经元比这更活跃!),它使大脑中能够改变突触(阅读:引起学习)的棘波总数达到惊人的 700 亿次!

There are as many learning episodes in a typical brain life as there are stars in the universe

也就是说,我们大脑中一个学习片段的次数至少等于,或者多于 1 后面跟着 24 个 0…..巧合的是这也是宇宙中恒星的估计数量。

这意味着当你读完这篇文章时,你的大脑已经学习了数千次。

为什么?如果不是这样,请想一想!以技能学习为例,技能学习被定义为通过训练获得和提高感知、认知或运动能力的能力。技能学习是所有动物生存的一种基本能力,这一事实证明了人类可以通过实践来提高迄今为止认知和行为心理学测试的几乎每一项任务。

虽然学习发生的时间尺度在几分钟到更长的时间尺度之间变化,但是上面概述的基本神经和突触机制是潜在学习机制的基础。我们的神经元不停地激活和重组我们大脑中的突触。

让我们举一个平凡的例子:学习个体的视觉身份。一个人可能会错误地认为,你所需要做的就是看和学习一张脸的图片,你就完成了。但是,不出所料,人会随着时间而改变(见图)。

Face are not only learned once….

在这个例子中,如果你遇到了 30 出头的唐纳德·特朗普,而不是在他担任美国总统的日子里,你可能会有片刻的停顿和不和谐,但你的大脑会迅速适应并“封装”这个新的、进化的唐纳德·特朗普形象,以你个人的名义描绘美国总统。

这个不断调整一个人的表象的例子——这些表象是感性的,但也是运动的和认知的——在我们的大脑和生活中是规律而不是例外。我们的家、工作场所、我们交往的人、我们需要使用和更新的技能,都在随着时间而变化:没有什么是真正稳定的。

虽然生物进化已经想出了如何设计我们的自然智能来应对现实,但今天的人工智能肯定没有。

设计可以展示这种“持续”(或终身,或持续)学习的人工智能是一个未解决的问题,其中人工智能可以在预定数据集的情况下被训练以实现高水平的性能,但不能在人类居住的典型世界中持续学习。在我们的世界中,来到我们面前的数据并不是整齐地准备在数据集中,而是出乎意料地、毫无预警地来到我们面前。没有人告诉我们‘听着,鲍勃,我将向你展示 300 幅西红柿的图片,学会它’。西红柿会毫无预兆地来来去去……我们需要把它们都学会!

No AI will be successful without lifelong (continual) learning

最终,需要在具有挑战性的部署场景中与人类共存的机器以及更多通用人工智能系统,将需要展现出与人类相同的惊人学习能力。

目前,传统设计的人工智能无法做到这一点,这不仅限制了机器与人类一起工作的能力,还限制了机器挑战人类智能最高台阶的能力。

基于统计分析的脸书品牌营销

原文:https://towardsdatascience.com/brand-marketing-on-facebook-using-statistical-analysis-7ec4210999b0?source=collection_archive---------19-----------------------

Photo by Carlos Muza on Unsplash

推广品牌和从数据中获取洞察力的技巧和诀窍

假设有一天你想开一家公司。在这个时代,最重要的事情之一就是你公司的影响力。如果公司是基于人们日常生活中使用的某些产品而成立的,那么很可能你在市场上已经有很多竞争对手了。现在,重要的是战胜激烈的竞争。所以,现在人们可以接触到你的公司的地方不仅仅是广告牌。这是一个社交媒体,人们一天要浏览三次他们的新闻。平均而言,一个美国人每年在社交媒体上花费 705 个小时。失败的几率微乎其微,即使你真的失败了,你也没什么可失去的。

所以,让我们假设你的公司正式参与社交媒体上的品牌营销。你已经建立了一个脸书或 Instagram 页面,因为要营销的品牌是一个化妆品品牌(不是化妆品的大粉丝,但使用的数据集是化妆品品牌的)。您回复客户问题,关注粉丝,发布重要新闻,并感谢您的支持者的支持。除此之外,你是否采取了足够的行动来监控和分析你的工作结果?如果你从事社交媒体,那么你当然应该衡量这些活动。有没有更好的了解方式?说起来容易做起来难,听起来很讽刺,是吧?

Source:https://infigosoftware.in/facebook-as-a-marketing-platform/

社交媒体指标是让你深入了解你的社交媒体营销表现的数据和统计。下面的博客解释了其中的一些指标。

为了满足本博客的目的,我们将指标分为四个不同的类别:

  • 知名度:这些指标阐明了你当前和潜在的受众。
  • 参与度:这些指标显示了受众如何与你的内容互动。
  • 转化:这些指标展示了你社交参与的有效性。
  • 消费者:这些指标反映了活跃客户对你的品牌的想法和感受。

Source: https://www.slideshare.net/SidharthGuleria/boost-your-business-using-facebook-instagram

我将概括地介绍所有类别,而不会深入每个类别的具体细节。因此,为了更好地理解整个事情,以下是你需要知道的一些指标:

到达:帖子到达的不同人群或用户总数。

浏览量:一个帖子被用户看到的次数。一个帖子可以被 n 个人看到 m 次。因此,总浏览量变成了 m*n。一篇文章在你的新闻订阅源中显示的次数,不考虑这篇文章被点击的次数。人们可能会看到同一帖子的多个印象。例如,某人可能会在新闻订阅源中看到一次页面更新,如果他的朋友分享了它,就会看到第二次。

页面点赞总数:点赞显示你在脸书的受众规模。随着时间的推移,这个数字应该会增加。如果你几个月来一直有相同数量的喜欢,这意味着两种情况之一:
1)你失去的喜欢和你得到的一样多。新朋友没有关注你

参与度:表示用户在帖子上执行一个动作的次数。敬业度是你可以追踪的最重要的脸书指标之一。主观上,参与是人们确实喜欢你分享的内容的标志。但参与度如此重要的另一个原因是,它可能会让你的帖子更多地暴露给你的受众。这包括喜欢、评论、分享以及观看过你的视频或点击过你的链接和照片的人。它还包括点击评论者姓名、喜欢某条评论、点击你的页面名称,甚至通过举报你的帖子给出负面反馈的人。

消耗:这一指标类似于参与度,但消耗并不一定会产生故事 消费=链接点击量+照片浏览量+视频播放量+其他点击量(其中一些确实会产生故事)

总交互:正如我们所知,主要动机是增加查看帖子的人数,并增加与帖子的交互(如,评论,分享)次数,以便创建一个故事,它会自动出现在查看者的朋友的新闻提要中。总互动量是根据终身后参与用户(故事已创建)和终身后消费者(故事未创建)执行的操作计算的。请注意这些指标,稍后会用到它们。
总互动=喜欢+评论+分享

帖子类型:脸书上有四种类型的帖子:视频、照片、状态、链接。人类的普遍倾向是看图像,阅读和分享它们。状态通常较长,人们不愿意阅读。因此,人们自然倾向于观看视频、图片和状态,并对其做出反应。

去年(2018 年),脸书承认在其算法中优先考虑视频,特别强调直播视频。如果你能创建视频内容,你就有更好的机会获得新闻源。所以,你会看到后来的可视化有点偏向视频帖子。

付费点赞:通过脸书的广告活动,有多少人喜欢你的页面。

脸书页面分析提供了与这些指标相关的数据和统计信息。所以,我所做的是我有一个名为 Morto 等人的数据集,它给出了脸书特定化妆品匿名品牌的广告指标。数据集总共有 500 条记录,其中有 19 列定义了这样的指标值。现在,回到这个博客的下一部分,开始 R 编程。

R 是一种统计编程语言。R 拥有大量的统计和图表方法。它包括机器学习算法,线性回归,时间序列,统计推断。R 中有各种各样的包,可以轻松地完成数据科学领域的任务。关于 R 理论上的详细信息,请访问https://en . Wikipedia . org/wiki/R _(programming _ languagehttps://www.tutorialspoint.com/r/index.htm获得 R 编程语言语法的帮助。
我在项目中绘制了各种数据可视化,这将有助于任何外行做出决定,即什么实际上有助于将广告拉近最终用户。
:以下观察和数据分析是凭直觉完成的,然后做了一些修改以从中获得最佳结果。

  1. 首先,页面总点赞数取决于以下脸书邮报指标 :
    总浏览量
    总浏览量
    帖子类型(照片、状态、视频、链接)
    工作日
    一天中的某个小时

在多元回归分析的帮助下,我们获得了所有上述指标的系数,这将帮助我们确定每个指标的重要性,这有助于增加我们的页面喜欢。

为什么要多元回归?多元回归是线性回归在两个以上变量之间关系的延伸。在简单线性关系中,我们有一个预测变量和一个响应变量,但在多元回归中,我们有不止一个预测变量和一个响应变量。

我们使用 r 中的 lm() 函数创建回归模型。该模型使用输入数据确定系数的值。接下来,我们可以使用这些系数预测一组给定预测变量的响应变量的值。

data<-read.csv("Morto_Et_Al.csv")input<-read.csv(file = "facebook.csv", sep = ",")[ ,c('PTL','LPTReach','LPTImpressions','Type','Weekday','Hour')]model<-lm(PTL~LPTReach+LPTImpressions+Type+Weekday+Hour,data=input)a <- coef(model)[1]
XLPTReach <- coef(model)[2]
XLPTImpressions <- coef(model)[3]
XTypePhoto <- coef(model)[4]
XTypeStatus <- coef(model)[5]
XTypeVideo <- coef(model)[6]
XWeekday <- coef(model)[7]
Xhour <- coef(model)[8]

2。
预测分析:这里,使用通过多元回归分析获得的系数来生成一个方程,其中,将变量的值代入该方程,根据帖子的类型来预测喜欢的数量。

x1 <- readline("What is the total reach?")
x1 <- as.numeric(x1)
x2 <- readline("What is the value for total impressions?")
x2 <- as.numeric(x2)
x6 <- readline("What is weekday?")
x6 <- as.numeric(x6)
x7 <- readline("Which is the hour of the day?")
x7 <- as.numeric(x7)x<-c("Photo","Status","Video")
type<-readline("What is the type of post?")if("Photo" %in% type) {
Y = a + XLPTReach*x1+XLPTImpressions*x2+XTypePhoto*2.5+XWeekday*x6+Xhour*x7Z = a + XLPTReach*x1+XLPTImpressions*x2+XTypePhoto*3+XWeekday*x6+Xhour*x7} 
else if ("Status" %in% x) {
Y = a + XLPTReach*x1+XLPTImpressions*x2+XTypeStatus*1.4+XWeekday*x6+Xhour*x7
Z = a + XLPTReach*x1+XLPTImpressions*x2+XTypeStatus*2+XWeekday*x6+Xhour*x7} 
else if ("Video" %in% x) {
Y = a + XLPTReach*x1+XLPTImpressions*x2+XTypeVideo*4+XWeekday*x6+Xhour*x7
Z = a + XLPTReach*x1+XLPTImpressions*x2+XTypeVideo*5+XWeekday*x6+Xhour*x7
}

3.后工作日 v/s 总到达量,后工作日 v/s 总展示量:
这里,我绘制了一个线形图来显示后工作日如何影响总到达量和展示量的关系。结果显示,在工作日 3 发布的帖子在 reach 上给出了最好的结果,并且同一帖子在第二天有最大的展示次数。有道理,不是吗?

day1<- subset(data,Weekday==1)
mean1R <- mean(day1$LPTReach)
mean1I <- mean(day1$LPTImpressions)day2<- subset(data,Weekday==2)
mean2R <- mean(day2$LPTReach)
mean2I <- mean(day2$LPTImpressions)day3<- subset(data,Weekday==3)
mean3R <- mean(day3$LPTReach)
mean3I <- mean(day3$LPTImpressions)day4<- subset(data,Weekday==4)
mean4R <- mean(day4$LPTReach)
mean4I <- mean(day4$LPTImpressions)day5<- subset(data,Weekday==5)
mean5R <- mean(day5$LPTReach)
mean5I <- mean(day5$LPTImpressions)day6<- subset(data,Weekday==6)
mean6R <- mean(day6$LPTReach)
mean6I <- mean(day6$LPTImpressions)day7<- subset(data,Weekday==7)
mean7R <- mean(day7$LPTReach)
mean7I <- mean(day7$LPTImpressions)v<-c(mean1R,mean2R,mean3R,mean4R,mean5R,mean6R,mean7R)
t<-c(mean1I,mean2I,mean3I,mean4I,mean5I,mean6I,mean7I)png(file = “Weekday_TotalReach.png”)
plot(v,type = “o”,col = “red”, xlab = “Weekday”, ylab = “Total Reach”,
main = “Chart for analysis of total reach”)
dev.off()png(file = “Weekday_TotalImpressions.png”)
plot(t,type = “o”,col = “blue”, xlab = “Weekday”, ylab = “Total Impressions”,
main = “Chart for analysis of total impressions”)
dev.off()

4。帖子类型总浏览量,帖子类型总浏览量
这里用一个条形图来表示帖子类型和浏览量、浏览量之间的关系。它有助于比较每种文章类型的影响。结果显示,“视频”比其他类型的帖子更能提升你的品牌。

photodf <- subset(data,Type=="Photo")
meanPR <- mean(photodf$LPTReach)
meanPI <- mean(photodf$LPTImpressions)
#meanPLikesP <- mean(photodf$PTL)statusdf <- subset(data,Type=="Status")
meanSR <- mean(statusdf$LPTReach)
meanSI <- mean(statusdf$LPTImpressions)
#meanPLikesS <- mean(statusdf$PTL)videodf <- subset(data,Type=="Video")
meanVR <- mean(videodf$LPTReach)
meanVI <- mean(videodf$LPTImpressions)
#meanPLikesV <- mean(videodf$PTL)linkdf <- subset(data,Type=="Link")
meanLR <- mean(linkdf$LPTReach)
meanLI <- mean(linkdf$LPTImpressions)
#meanPLikesL <- mean(linkdf$PTL)ValueR <- c(meanPR,meanSR,meanVR,meanLR)
ValueI <- c(meanPI,meanSI,meanVI,meanLI)Post <- c("Photo","Status","Video","Link")png(file = "barchart_reach&postType.png")
barplot(ValueR,names.arg = Post,xlab = "Post Type",ylab = "Total Reach",col = "blue", main = "Total Reach v/s Post Type",border = "red")
dev.off()png(file = "barchart_Impressions&postType.png")
barplot(ValueI,names.arg = Post,xlab = "Post Type",ylab = "Total Impressions",col = "red", main = "Total Impressions v/s Post Type",border = "blue")
dev.off()

5。总交互 v/s 总到达次数,总交互 v/s 总印象数
使用线性回归,绘制一个图表,显示总交互对总到达次数、印象数的依赖性,这反过来实际上会允许许多观众访问页面。

ReachInt<-data$LPTReach
ImpressionInt<-data$LPTImpressions
LikesInt<-data$PTL
TotalInt<-data$Total.Interactionsrelation <- lm(TotalInt~ReachInt)
png(file = "linearregression(ReachvsInteractions.png")
plot(ReachInt,TotalInt,col = "blue",main = "Reach v/s Interactions",cex = 1.3,pch = 16,ylab = "Total Interactions",xlab = "Total Reach")
dev.off()relation <- lm(TotalInt~ImpressionInt)
png(file = "linearregression(ImpressionsvsInteractions.png")
plot(ImpressionInt,TotalInt,col = "red",main = "Impressions v/s Interactions",cex = 1.3,pch = 16,ylab = "Total Interactions",xlab = "Total Impressions")
dev.off()relation <- lm(LikesInt~TotalInt)
png(file = "linearregression(LikesvsInteractions.png")
plot(TotalInt,LikesInt,col = "violet",main = "Likes v/s Interactions",cex = 1.3,pch = 16,xlab = "Total Interactions",ylab = "Total Page Likes")
dev.off()

6。付费帖子总影响力:
当你付钱给脸书来提升一个帖子时,该帖子的总影响力会增加。因此,为了确定一个帖子是否有报酬,我们使用了一个决策树,该决策树显示如果总数达到> 10470,则该帖子是一个有报酬的帖子。因此,根据目前的数据集,如果你必须让帖子达到大约 1 万人,你需要为此付费,脸书最终会推广它。

data1<-read.csv(“facebook.csv”)
library(party)
png(file = “Paid(FullData).png”)
output.tree <- ctree(Paid[1:100] ~ ReachInt[1:100] +                          ReachInt[1:100],data = data1)
plot(output.tree)
dev.off()

7.有多少参与帖子的用户已经喜欢上了该页面?我绘制了饼图来显示分布情况。结果显示,70%参与帖子的人是已经喜欢该页面的人。现在,这个统计有助于在他们的朋友中传播帖子,也激发他们喜欢帖子或者页面。

LPEuser1<-data$LPEuser
LEngaged1<-data$LEngaged
divi.result <- (LPEuser1/LEngaged1)*100
LPEuser1mean<-mean(divi.result)
LEngaged1mean=100-LPEuser1mean
x<-c(LPEuser1mean,LEngaged1mean)
piepercent<- round(100*x/sum(x), 1)png(file = “Engaged_users.png”)
pie(x,labels=piepercent, main = “Engaged users %”, col = rainbow(length(x)))
legend(“topright”, c(“Users already liked the page”,”Others”), cex = 0.8,fill = rainbow(length(x)))
dev.off()

8。参与用户,消费占印象的比例:
到目前为止,我们一直专注于直接影响页面总点赞的参数。现在,间接影响总页面喜好的因素,即参与用户、消费者、消费被考虑在内。这里,统计数据被绘制在一个饼状图上,这有助于确定每种类型帖子的消费者百分比、总覆盖范围中的参与用户百分比以及总印象中的消费百分比和参与用户百分比。

这有助于显示特定的帖子类型是否适合增加互动次数和推广帖子。

LPConsumptions<-photodf$LPConsumptions
LPTimpressions<-photodf$LPTImpressions
LEngaged2<-photodf$LEngaged
divi.result<-(LPConsumptions/LPTimpressions)*100
divi.result2<-(LEngaged2/LPTimpressions)*100
LEngaged2mean<-mean(divi.result)
LPConsumptionsmean<-mean(divi.result2)
others<-100-(LEngaged2mean + LPConsumptionsmean)
x<-c(LEngaged2mean,LPConsumptionsmean,others)
piepercent<- round(100*x/sum(x), 1)
png(file = "Impressions_Engaged_Consumptions(photo).png")
pie(x,labels=piepercent, main = "Engaged Users,Consumptions from total impressions(photo)%", col = rainbow(length(x)))
legend("topright", c("Engaged users%","Lifetime Post Consumptions%","Others%"), cex = 0.8,fill = rainbow(length(x)))
dev.off()LPConsumptions<-statusdf$LPConsumptions
LPTimpressions<-statusdf$LPTImpressions
LEngaged2<-statusdf$LEngaged
divi.result<-(LPConsumptions/LPTimpressions)*100
divi.result2<-(LEngaged2/LPTimpressions)*100
LEngaged2mean<-mean(divi.result)
LPConsumptionsmean<-mean(divi.result2)
others<-100-(LEngaged2mean + LPConsumptionsmean)
x<-c(LEngaged2mean,LPConsumptionsmean,others)
piepercent<- round(100*x/sum(x), 1)
png(file = "Impressions_Engaged_Consumptions(status).png")
pie(x,labels=piepercent, main = "Engaged Users,Consumptions from total impressions(status)%", col = rainbow(length(x)))
legend("topright", c("Engaged users%","Lifetime Post Consumptions%","Others%"), cex = 0.8,fill = rainbow(length(x)))
dev.off()LPConsumptions<-videodf$LPConsumptions
LPTimpressions<-videodf$LPTImpressions
LEngaged2<-videodf$LEngaged
divi.result<-(LPConsumptions/LPTimpressions)*100
divi.result2<-(LEngaged2/LPTimpressions)*100
LEngaged2mean<-mean(divi.result)
LPConsumptionsmean<-mean(divi.result2)
others<-100-(LEngaged2mean + LPConsumptionsmean)
x<-c(LEngaged2mean,LPConsumptionsmean,others)
piepercent<- round(100*x/sum(x), 1)
png(file = "Impressions_Engaged_Consumptions(video).png")
pie(x,labels=piepercent, main = "Engaged Users,Consumptions from total impressions(video)%", col = rainbow(length(x)))
legend("topright", c("Engaged users%","Lifetime Post Consumptions%","Others%"), cex = 0.8,fill = rainbow(length(x)))
dev.off()LPConsumptions<-linkdf$LPConsumptions
LPTimpressions<-linkdf$LPTImpressions
LEngaged2<-linkdf$LEngaged
divi.result<-(LPConsumptions/LPTimpressions)*100
divi.result2<-(LEngaged2/LPTimpressions)*100
LEngaged2mean<-mean(divi.result)
LPConsumptionsmean<-mean(divi.result2)
others<-100-(LEngaged2mean + LPConsumptionsmean)
x<-c(LEngaged2mean,LPConsumptionsmean,others)
piepercent<- round(100*x/sum(x), 1)png(file = "Impressions_Engaged_Consumptions(link).png")
pie(x,labels=piepercent, main = "Engaged Users,Consumptions from total impressions(link)%", col = rainbow(length(x)))
legend("topright", c("Engaged users%","Lifetime Post Consumptions%","Others%"), cex = 0.8,fill = rainbow(length(x)))
dev.off()

因此,以上是作为一名业余爱好者在 R 中完成的统计数据分析,以获得对真实世界数据集的实际操作经验。所以,下次你开始营销你的品牌时,在脸书上做,看着它像野火一样蔓延。此外,一定要检查这些指标,它们会帮助你评定你的营销技巧😊

巴西重金属:使用 NLP 和 LDA 的探索性数据分析

原文:https://towardsdatascience.com/brazilian-heavy-metal-an-exploratory-data-analysis-using-nlp-and-lda-f92324d0381e?source=collection_archive---------21-----------------------

对巴西两大重金属乐队歌词的分析:Angra 和塞普尔图拉

Let’s see how to get there

动机

在我的大部分时间里,我习惯于试验一些 NLP 技术,我注意到即使有过多的可用资源,也很难找到一些与数据分析相关的 NLP 技术内容,与文本挖掘等数据的一般知识相关。

在 Github 中有很多脚本、应用博客文章、带代码的存储库是非常酷的,但至少对我来说,分析是这项技术最出彩的地方,因为任何人都可以编写脚本,但只有少数人可以提取数据知识。

这里的想法是得到我喜欢的两个乐队的歌词,检查他们的文学特征,并试图找到他们之间的一些联系或区别。

对于关于 NLP、LDA 等非常深入和技术性的帖子,请随意直接跳到这篇帖子的末尾,并选择许多关于这些主题的非常好的参考资料。

这就是这篇文章的内容,它深深地启发了机器学习加的伟大工作。

为什么是 Angra 和坟墓?

重金属是世界上最无国界的音乐风格之一,我想用 Python、LDA、NLP 和一些想象力以简单的方式展示我的国家最具标志性的两个乐队及其文学特征(你会在主题的“解读”中看到。

关于乐队

坟墓

Sepultura 是一支来自贝洛奥里藏特的巴西重金属乐队。该乐队于 1984 年由兄弟马克斯和伊戈尔·卡瓦拉组建,是 20 世纪 80 年代末和 90 年代初凹槽金属、鞭挞金属和死亡金属流派的主要力量。Sepultura 也被认为是 20 世纪 80 年代末和 90 年代初至中期的第二波重金属乐队之一。

Source: Jamie Martinez

官方网站Spotify 中的坟墓

Angra

Angra 是一支成立于 1991 年的巴西重金属乐队,自成立以来经历了一些阵容变化。在 Rafael Bittencourt 的带领下,这支乐队在日本和欧洲获得了一定程度的知名度。

Source: sztachetki

Angra 官方网站——Spotify 中的 Angra

问题

我一直对这些乐队有一些私人问题,我将尝试用这个笔记本来回答:

  • 1)Angra 和《坟墓》的文学特征是什么?
  • 2)他们谈论的是哪种类型的主题?
  • 3)谁的话题更具多样性?

一些限制

应用技术

自然语言处理

自然语言处理(NLP) 是计算机科学、信息工程和人工智能的一个子领域,涉及计算机和人类(自然)语言之间的交互,特别是如何对计算机进行编程以处理和分析大量自然语言数据。

主题建模

在机器学习和自然语言处理中,主题模型是一种统计模型,用于发现文档集合中出现的抽象“主题”。主题建模是一种常用的文本挖掘工具,用于发现文本中隐藏的语义结构。主题模型也被称为概率主题模型,它指的是用于发现大量文本主体的潜在语义结构的统计算法。

潜在狄利克雷分配

在自然语言处理中,潜在狄利克雷分配 (LDA)是一种生成统计模型,它允许通过未观察到的组来解释观察集,从而解释为什么数据的某些部分是相似的。例如,如果观察是收集到文档中的单词,那么它假设每个文档是少量主题的混合物,并且每个单词的出现都归因于文档的一个主题。LDA 是主题模型的一个例子。

代码和数据

所有代码、数据集和图像都存储在 这个 Github repo 中。

数据提取和加载

为了提取歌词,我使用了[PyLyrics](https://github.com/geekpradd/PyLyrics)库和脚本。重要提示:自去年以来,本库没有任何更新/错误修复。下面我们可以导入一些库,并开始对我们的数据进行小的预处理。

包装器获取了 325 首歌曲,包括艺术家、歌词和专辑。

一个主要的挑战是,这些乐队通常用多种语言(英语和葡萄牙语)创作歌曲。为了简单起见,我们将只关注英语。

为了过滤 PT-BR 歌曲,我将使用使用 Google API 检查语言的textblob库。主要的警告是,如果你重新运行很多次,你可能会收到代码HTTP Error 429: Too Many Requests

这里我们可以看到,在 325 首歌词中,38%来自 Angra,62%来自坟墓。Angra 有 96% (119) 的歌词在 EN 中,而 Sepultura 有 96% (194) 的歌词在 EN 中。

来自 Angra 的 PT-BR 中最出色的歌曲是CAA e caador专辑《猎人与祈祷》中的一首歌。在阴影之殿专辑中的歌曲迟到的救赎是 EN/PT-BR 中的一首好歌。

Sepultura 在 PT-BR 中有一些歌曲,如《野蛮的毁灭》中的 Filhos do Mundo ,and 中的 Prenuncio 和《遗骸》专辑中的 A Hora E A Vez Do Cabelo Nascer ,这是 Mutantes 的一首翻唱歌曲。PT-BR 中最引人注目的Policia 宋。

删除了所有 PT-BR 歌词后,让我们快速检查一下这些乐队的所有专辑。

乍一看,考虑到我们的数据框架,我们可以看到这两个乐队之间的第一个区别,Sepultura 有一个更大的唱片集和更多的歌曲。

这可以用这样一个事实来解释,即使两个乐队在更换他们的主要歌手时都面临着中断(Angra 的安德烈·马托斯edu·法拉斯基和塞普尔图拉的马克斯·卡瓦拉拉)塞普尔图拉在中断后发行了 8 张专辑(都是与德里克·格林一起发行的),同时 Angra 发行了 6 张;而 Sepultura 是一支多产的乐队。

让我们记住这个信息,因为也许在这个分析的第二个瞬间,它可以被解释。

我们来看看每张专辑的平均歌曲数。

当我们目测 Sepultura 甚至没有更多的专辑,但每张专辑有更多的歌曲。

开始我们的分析文本分析的一个重要方面是 数据预处理 。在这里,我们实际上可以忽略所有的分析,因为预处理负责去除数据中的所有噪声,并对所有数据进行归一化,以获得有意义的结果。卡维塔·加内桑对这个话题做了很好的分析,我强烈推荐这本书。

第一步将是删除所有歌词的所有英文停用词。

PS:我个人不喜欢使用现成的停用词表,因为每个领域都需要特定的词子集来定义某个词是否重要。但是为了简单起见,让我们保持这种方式。马蒂娜·普列塞的这篇好文章详细解释了这一点。就实现而言,ML 专家的这篇文章可能是互联网上最好的资源。

在停用词移除之后,让我们对这两个带使用的最频繁的词进行快速的视觉检查。换句话说:他们作文中用得最多的词是什么?

如果我可以在这里进行一些分类,根据最常见的表达方式来定义 Angra 歌词,将会是这样的:

  • 时间关系:TimeDayWaitNight
  • 感受:LikeHeartSoulLie
  • 移动和距离:ComeWayAwayCarry
  • 生活与心灵:LifeLetKnowDreamMindLiveinsideLeave
  • 世界的绝对状态:Die
  • 典型的重金属陈词滥调:Oh

现在,快速验证一下《坟墓》的歌词:

现代世界的状态:DeathWarHateDieLiePainLoseFearBloodWorld

动作、距离、时间:WayComeStopMakeRiseTimeThinkHearKnow

思想问题:LiveMindFeelWantLookInside

潜在的差异

《坟墓》和《Angra》讨论的主题存在一些潜在的差异,如:

  • Sepultura 的创作文学轴集中于与死亡相关的事物/情感主题、痛苦、战争、仇恨(如果你已经不知道,Sepultura 在 PT-BR 中的意思是“坟墓”)相关的主题,这些主题被认为是最具攻击性/沉重的主题;
  • Angra 有一个更轻松的主题,更多地谈论涉及时间流逝的存在主义问题,以及一些与梦有关的感觉和与内部冲突有关的感觉的歌曲

我们来看一下相对于两个乐队最常用词的词云,只根据乐队使用的所有词汇做一个小对比。

主要词汇 Angra:

  • lifetimeknowheartdayawayknowdream

主要词汇 Sepultura:

  • waylifedeathworldmind

词汇多样性

根据 Johansson (2009)的说法,词汇多样性是在一篇文章中使用了多少不同单词的一种度量。词汇多样性的实际应用由 McCarthy 和 Jarvis (2010)给出。他们说 LD 是文本中使用的不同单词的范围,范围越大表明多样性越高

这里需要特别考虑的是,重金属歌曲不应该包含太多不同的词,也就是说,词汇丰富。这是因为在大多数情况下,每个乐队可以遵循一个单一的艺术概念,并针对一些主题形成他们的创作努力,当然也因为大多数时候这种歌曲有许多合唱。

例如(关于乐队概念) Avatasia 这是一个重金属的超级组合,谈论小说、幻想和宗教;而在另一边梦幻剧场谈论从宗教现代政治的几乎一切。

有了这个免责声明,让我们检查这个乐队的词汇多样性。

这两个乐队在词汇多样性上几乎没有差异,即使使用不同的词汇来塑造他们的主题,他们在主题出现的频率上也没有实质性的词汇差异。

单词 N-Grams

根据维基百科, n-gram 是来自给定文本或语音样本的 n 个项目的连续序列。根据应用,项目可以是音素、音节、字母、单词或碱基对。

在其他情况下,n-gram 是包含 n 个单词的序列,可以用来模拟某个序列出现在语料库中的概率,在我们的情况下,n-gram(s)可以在他们的文学词典中检查 n 个单词的最频繁组合。

为了简单起见,我们将集中讨论二元模型和三元模型的组合。

N-Grams Angra

在这里我们可以看到一些东西:

  • 你是”是n=2中的顶级组合。这表明,除了 Angra 的全部歌曲外,还有一些歌词包含了传递给另一个人的某种信息。
  • 最常见的二元模型之一是carry on,但这是有数据原因的:在这个数据集中,我们有包含歌曲 Carry OnAngels CryHoly Live磁盘,这导致了重复计数
  • me cathycathy come重唱背后的原因似乎是因为来自凯特·布什的一首名为 呼啸山庄 的翻唱歌曲大量重复了这一合唱;
  • 我们有传统的重金属歌曲合唱填料陈词滥调oh oh出现

  • carry on timeon time forgetremains past carry中再次出现进位,
  • Cathy这个词出现在三字组:heathcliff me cathyme cathy comecathy come home
  • 一些类似ha ha ha的奇怪模式,可能是因为数据清理

N-Grams 坟墓

在这些双图中,我们已经可以看到更多关于《坟墓》的主题,和我之前提到的残忍相关的主题。一些提及:

  • 歌曲“ Choke ”有一个非常重复的合唱,这有助于这个双字母组合的组成。
  • 经典的“T29”词根“T30”也是如此,它有一个非常引人注目的合唱

让我们来看看三个字母:

在这里,我们看到基本相同的模式,部分三元组面对一些非常惊人的合唱。

现在我们对这两个乐队的主题有了一些了解,然而,随之而来的一个问题是:在这个主题中,每首作品背后潜在的主题是什么?,也就是说,乐队理念中的主题具有多样性?,如果我们能把这些歌曲按照它们的文学成分分组会怎么样?

这里是我们要使用 LDA 的地方。

皱胃向左移

首先,我们将在各自的数据框架内过滤每位艺术家:

为了区分主题,我会为每个艺术家任意选择 7 个主题(可以多一点或少一点),这只是为了教学和保持简单。

换句话说:给定所有 Angra 和 Sepultura 的歌词,他们通常写得最多的前 7 个主题是什么?

主题 Angra

话题坟墓

主题分布

主题分布 Angra

我们可以看到,Angra 的大部分主题都集中在主题 4,0,2 上,我称之为主题随着时间的推移观察和了解世界(#4)随着时间的推移面对痛苦(#0)在生活中梦想来来去去(#2)

  • Topic #4: eyes time life ive world love say inside know got
  • Topic #0: time dont day away way youre face pain just cause
  • Topic #2: let come like away day life wont wonder cold dreams

现在让我们检查一下墓地:

主题分布图

《坟墓》聚焦于一些主题,如生命与恐惧时光流逝(#3)活在痛苦与死亡的世界(#5),活在战争与流血的世界

  • Topic #3: dont just away time fear youre know life right look
  • Topic #5: end theres dead world death feel eyes pain left alive
  • Topic #0: war live world hear trust feel walk believe blood kill

每个主题的字数

这里只是一个表格,供我们查看这两个乐队的文学部分渗透的主题中的单词顺序。

这里特别强调的是,在这个数据框架中,还考虑了该词在主题中的频率和普通性。

Angra 每主题字数

每个主题的字数

带单词分布的主题绘图

这里有了pyLDAvis库,我们可以通过视觉检查来看看主题是如何分布的。由pyLDAvis展示的图表被称为主题间距离图,它存在于一个二维平面中,其中心通过计算主题间的距离来确定,然后通过使用多维缩放将主题间距离投影到二维平面上

这样,我们就能够解释每个主题的组成,以及哪些术语在某个主题中最有用。

关于 LDAVis 最全面的介绍可以在 c .Sievert、& Shirley,K. (2014)中找到。LDAvis:一种可视化和解释主题的方法。交互式语言学习、可视化和界面研讨会论文集(第 63-70 页)

Angra 所有主题的 LDA 图

所有坟墓主题的 LDA 图

结论

最初,我脑子里有 3 个问题,关于使用 NLP 和 LDA 的整个旅行,我个人认为我有一些答案。

1)Angra 和坟墓有什么文学特征?

Sepultura 有一个更具侵略性的文学作品,他们谈论死亡、战争和痛苦,他们唱了几次面对死亡的歌词。他们大部分时间都在抗议一个失落或病态的世界。

他们谈论的是哪种类型的主题?
答案 : Angra: 时间,灵魂,命运。死亡、战争和痛苦的世界。

谁的话题更具多样性?
回答:使用任意数量的 7 个话题我们可以看到,Sepultura 在话题分布方面更具多样性。

更多想法和待办事项

  • 包括曲目名称
  • 比较墓地时代(马克斯—德里克)
  • 比较 Angra 时代(马托斯—法拉斯基—廖尼)
  • 曲目之间的相似性(基于内容)
  • Angra·LSTM 音乐歌词生成器
  • 话题演变
  • 每张专辑的主题
  • 使用 LSTM 的歌词生成

参考资料和有用的链接

机器学习加——Python 中的 LDA 如何网格搜索最佳主题模型?

Susan Li为西雅图的酒店建立一个基于内容的推荐系统

Susan Li自动生成与的酒店描述

Shashank kapa diaPython 中的端到端主题建模:潜在狄利克雷分配(LDA)

Meghana Bhange——数据增强的北极猴子歌词生成器

格雷格·拉弗蒂——LDA 关于哈利·波特的文本

代码学院——利用机器学习分析泰勒·斯威夫特的歌词

亚历山大·贝尔音乐歌词分析:利用自然语言处理创建基于歌词的音乐推荐器

卡车和啤酒——令人惊叹的项目与歌词刮刀

安德斯·奥尔森-斯旺森——自然语言处理和说唱歌词

布兰登·彭图罗——德雷克——利用自然语言处理理解他的歌词

简并态重金属与自然语言处理—第一部分

简并态重金属与自然语言处理—第二部分

简并态重金属与自然语言处理—第三部分

Packt _ Pub——使用深度(多层)LSTM 生成歌词

穆罕默德·马阿马里——人工智能生成泰勒·斯威夫特的歌词

笔记本泰勒·斯威夫特的歌词——Colab 中的链接

恩里克 a.单词级 LSTM 文本生成器。用神经网络创建自动歌词

Ivan Liljeqvist利用人工智能生成歌词

Sarthak Anand音乐发生器

富兰克林王——作词生成

托尼·贝尔特拉梅利——深度歌词

打破假设

原文:https://towardsdatascience.com/breaking-assumptions-8c5198459fd4?source=collection_archive---------33-----------------------

Photo by Martin Olsen on Unsplash

本周在机器学习课程中,我们讨论了戴维斯-波尔丁指数 (DBI)。与大多数(如果不是全部)聚类有效性度量一样,DBI 要求您至少有两个聚类。

为什么?

这是一个边界条件。公式本身要求这样做,因为作者使用了需要两个集群的指标。他们认为你至少想要两个。毕竟,为什么会有人想要单个集群呢?

输入集群能力。不是研究最多的领域。但是如果你要聚集数据,你应该能够证明你的数据应该被聚集。有一些数据,只是没有足够好的聚类来证明该方法。就像我最近处理的一个学生成绩数据集,其中的聚类没有任何关于数据的有用信息。我花了太多时间得出结论,应该只有一个集群。

如果我能够像比较其他所有星团一样,比较一个星团的 DBI,那该有多好,多奇妙。换句话说,我想要一个包含可聚集性概念的有效性度量。

这具有内在的意义。如果我们要判断数据应该分成多少个簇,为什么一个不是有效的数字呢?因此,我有了一个新的宠物研究项目:DBX-Davies-Bouldin Extended。这是找到研究领域的一个不错的方法。

你的假设是你观察世界的窗口。每隔一段时间就把它们擦掉,否则光线就照不进来了。~艾萨克·阿西莫夫

根据我的经验,人们会做出三种假设。

  • 经验
  • 传统
  • 简单

让我们更深入地看看这些假设以及它们的动机。

经验

你看过苹果新的 测试不可能的 广告吗?我不得不承认,我觉得这种风格和信息有点刺耳。然而,广告中有一个有用的信息。你不知道你不知道什么。

人是被自己的经历和理解所限制的。一个在美国生活了一辈子的 10 岁孩子,可能从来没有遇到过汽车在马路对面行驶的国家。这超出了他们的经验。同样,如果你被困在一个山洞里看着影子,这就是你所知道的一切。一个世界引起阴影的可能性可能超出了你的理解。

我们这些学者同样受到经验的限制。无论你是穿着有护肘的夹克还是穿着扎克伯格风格的帽衫,你的学术经历都和你的同事们大同小异。这个“把人们放进盒子里”有着促进思维过程一致性的不幸效果。当你把范围限制在某一特定领域的研究人员时,尤其如此。

打破经验窠臼的方法就是多经历。和另一个部门的研究员喝咖啡。参加一个全新领域的课程。或者,如果可以的话,去一个新的地方。我的妹夫,来自饲养航海家,这样说。

旅行是独特的,它打开你的世界观,迫使你面对你的假设,因为你面对的是现实。没有什么能比走出你的舒适区,体验真实的世界,而不是别人描绘的世界,更快地改变你的视角。这里没有任何过错。走出去,亲身体验这个世界。~ 布雷迪@养航海家

传统

另一个常见的假设类别是传统。学术界当然热爱它的传统。看在上帝的份上,每次毕业典礼我们都戴上帽子,穿上长袍,扮演中世纪的僧侣。但是传统并不局限于服饰和礼仪,它也渗透到我们的研究中。

传统意味着投票给所有阶层中最不起眼的人,我们的祖先。这是死人的民主。传统拒绝屈服于那些碰巧四处走动的小而傲慢的寡头政治。~ GK 切斯特顿

明确一点,我不是说传统不好。对于 2d 图形来说,X 轴总是水平的,Y 轴总是垂直的,这是非常有用的。但是每个领域、子领域和专业都有自己的假设。

例如,K-Means 假设大致各向同性的集群。一想到那些没有经过预处理就盲目聚集名义数据的好心人,我就不寒而栗。如果那些天真的聚类者知道这个假设,他们可能会质疑它,并在这样做的过程中发现了聚类的层次方法。

简单

这可能是我们最常见的假设。当我们可以假设某些事情是固定的时,事情就简单多了。在基础物理学中,我们假设引力、光速和时间都是常数。事实上,所有这些都可能有所不同。上面戴维斯-波尔丁的例子就属于这一类。考虑到所使用的度量标准,使用多个集群会更简单。

人生来不是为了解决宇宙的问题,而是为了发现自己要做什么;并把自己限制在自己理解的范围内。~歌德

就像传统一样,简单也可能是一件好事。一个简单的模型通常比一个复杂的模型表现得更好,一个简单的问题解决方案几乎总是更可取的。

然而,有时需要额外的复杂性。如果一旦发现了线性和逻辑回归,我们就撒手不管,到此为止,我们可能永远也不会发现我们今天使用的大量技术。

最后的想法

仅此而已。我们都有自己的假设。和大多数事情一样,这些假设可以是正面的,也可以是负面的。理解这些假设会让我们成为更好的研究者……老实说,会让我们成为更好的人。

当我们坐下来阅读一篇新论文时,我们应该问这些问题来指导我们的分析。

  • 从经验中可以做出什么样的假设?
  • 这个领域的传统假设是什么?
  • 做了哪些简化来减少问题?

回答这些问题将提高我们对论文的理解,并开辟新的研究领域。

明智地假设!

你知道当你假设… ~一个我们都忘记了的人会发生什么

让伯特崩溃

原文:https://towardsdatascience.com/breaking-bert-down-430461f60efb?source=collection_archive---------2-----------------------

NLP 中最新里程碑的完全分解

伯特是什么?

BERT 是来自变压器的双向编码器表示的缩写。它是谷歌在 2018 年末开发并发布的一种新型语言模型。像 BERT 这样的预训练语言模型在许多自然语言处理任务中起着重要的作用,如问题回答、命名实体识别、自然语言推理、文本分类等。

BERT 是基于微调的多层双向变压器编码器。在这一点上,引入变压器架构是很重要的。

什么是变压器?

2017 年,谷歌发表了一篇题为《注意力就是你所需要的一切》的论文,提出了一种基于注意力的结构来处理序列模型相关问题,比如机器翻译。传统的神经机器翻译大多使用 RNN 或 CNN 作为编解码的模型库。然而,谷歌基于注意力的变压器模型抛弃了传统的 RNN 和 CNN 公式。该模型高度并行工作,因此在提高翻译性能的同时,训练速度也极快。

让我们退一步理解注意力。

什么是注意力?

注意机制可以被视为模糊记忆的一种形式。内存由模型的隐藏状态组成,模型选择从内存中检索内容。在我们深入研究注意力之前,让我们简单回顾一下 Seq2Seq 模型。传统的机器翻译基本上是基于 Seq2Seq 模型。该模型分为编码器层和解码器层,由 RNN 或 RNN 变体(LSTM、GRU 等)组成。).编码器向量是从模型的编码器部分产生的最终隐藏状态。该向量旨在封装所有输入元素的信息,以帮助解码器做出准确的预测。它充当模型解码器部分的初始隐藏状态。Seq2Seq 模型的主要瓶颈是需要将源序列的全部内容压缩到一个固定大小的向量中。如果文本稍长,很容易丢失文本的一些信息。为了解决这个问题,注意力应运而生。注意机制通过允许解码器回顾源序列隐藏状态,然后将其加权平均值作为附加输入提供给解码器,从而缓解了这个问题。顾名思义,使用注意力,该模型在解码阶段选择最适合当前节点的上下文作为输入。注意力和传统的 Seq2Seq 模型主要有两个区别。第一,编码器向解码器提供更多的数据,编码器会向解码器提供所有节点的隐藏状态,而不仅仅是编码器最后一个节点的隐藏状态。

https://jalammar.github.io/images/seq2seq_7.mp4

第二,解码器不直接使用所有编码器提供的隐藏状态作为输入,而是采用一种选择机制来选择与当前位置最匹配的隐藏状态。为此,它试图通过计算每个隐藏状态的得分值并对得分进行 softmax 计算来确定哪个隐藏状态与当前节点最密切相关,这允许隐藏状态的较高相关性具有较大的分数值,而较不相关的隐藏状态具有较低的分数值。然后,它将每个隐藏状态乘以其 softmaxed 分数,从而放大分数高的隐藏状态,淹没分数低的隐藏状态。这种评分练习在解码器端的每个时间步进行。

https://jalammar.github.io/images/attention_process.mp4

现在让我们把整个事情放在一起,在下面的视觉化中,看看注意力过程是如何工作的:

  1. 注意力解码器 RNN 接受令牌的嵌入,以及一个初始的解码器隐藏状态。
  2. RNN 处理它的输入,产生一个输出和一个新的隐藏状态向量(h4)。输出被丢弃。
  3. 注意步骤:我们使用编码器隐藏状态和 h4 向量来计算这个时间步骤的上下文向量(C4)。
  4. 我们将 h4 和 C4 连接成一个向量。
  5. 我们将这个向量通过一个前馈神经网络(一个与模型联合训练的网络)。
  6. 前馈神经网络的输出表示该时间步长的输出字。
  7. 重复接下来的时间步骤

https://jalammar . github . io/images/attention _ tensor _ dance . MP4

回到变形金刚

变压器模型使用编码器-解码器架构。在 Google 公布的论文中,编码器层由 6 个编码器堆叠而成,解码器层也是如此。每个编码器和解码器的内部结构如下-

该编码器由两层组成,一个自注意层和一个前馈神经网络。自我关注帮助当前节点不仅关注当前单词,而且获得上下文的语义。解码器也包含了编码器提到的两层网络,但在两层中间还有一个关注层,帮助当前节点获取需要关注的关键内容。

以下是变压器架构的详细结构-

让我们来分解一下各个组件。

自我关注

自我关注是 Transformer 把对其他相关词的“理解”转化为我们正在处理的词的一种方式。

首先,自我关注计算出三个新的向量。在本文中,向量的维数是 512 维。我们分别称这三个向量为查询、键和值。这三个向量是通过将字嵌入向量与一个随机初始化的矩阵(在该论文中维数是(64,512))相乘而产生的,该矩阵的值在反向传播过程中被更新。

接下来,我们计算自我注意的分数值,它决定了当我们在某个位置对一个单词进行编码时,对输入句子的其余部分的注意程度。该小数值的计算方法使用查询和键向量。然后我们把结果除以一个常数。这里我们除以 8。这个值一般是上面提到的矩阵第一维的平方根,也就是 64 的平方根 8。然后我们对所有分数进行 softmax 计算。结果是每个单词与当前位置的单词的相关性。自然,当前职位的词相关度肯定会大。最后一步是将值向量与 softmax 结果相乘并相加。结果是当前节点的自我关注值。

这种通过查询和关键字之间的相似度来确定值的权重分布的方法被称为比例点积注意力。

多头注意力

这篇论文更强大的部分是在自我关注中添加了另一种机制,称为“多头”关注,它不只是初始化一组 Q,K,V 矩阵。而是多组初始化,transformer 用了 8 组,所以最后结果是 8 个矩阵。

前馈神经网络不能接受 8 个矩阵,所以我们需要一种方法将 8 个矩阵减少到 1 个。为此,我们首先将 8 个矩阵连接在一起,得到一个大矩阵,然后将这个组合的矩阵乘以一个随机初始化的矩阵,得到一个最终的矩阵。我们来看一下整个过程。

变压器以三种不同的方式使用多头注意力:

  1. 在“编码器-解码器注意”层中,查询来自前一个解码器层,存储器键和值来自编码器的输出。这允许解码器中的每一个位置关注输入序列中的所有位置。这模仿了序列到序列模型中典型的编码器-解码器注意机制。
  2. 编码器包含自我关注层。在自关注层中,所有的键、值和查询都来自同一个地方,在这种情况下,是编码器中前一层的输出。编码器中的每个位置可以关注编码器的前一层中的所有位置。
  3. 类似地,解码器中的自关注层允许解码器中的每个位置关注解码器中的所有位置,直到并包括该位置。我们需要防止解码器中的向左信息流,以保持自回归特性。我们通过屏蔽(设置为 softmax 输入中与非法连接相对应的所有值,在比例点积注意中实现这一点。这将在解码器部分更详细地讨论,我们将讨论掩蔽。

位置编码

到目前为止,我们还没有办法解释 transformer 模型中输入序列中单词的顺序。为了解决这个问题,转换器向编码器和解码器层的输入添加了一个额外的矢量位置编码。尺寸与嵌入尺寸相同。这个位置编码的值被加到嵌入的值上,并作为输入发送到下一层。位置编码有很多选项,既有学习的,也有固定的。

剩余连接和层标准化

在编码器和解码器中,在两个子层的每一个周围使用残差连接,随后进行层归一化。跳过连接或剩余连接用于允许梯度直接流过网络,而不经过非线性激活函数。非线性激活函数本质上是非线性的,导致梯度爆炸或消失(取决于权重)。跳跃连接在概念上形成了一条“总线”,它直接穿过网络,反过来,梯度也可以沿着它反向流动。标准化有助于解决称为内部协变量移位的问题。内部协变量移位是指在神经网络内发生的协变量移位,即从(比方说)第 2 层到第 3 层。这是因为,随着网络的学习和权重的更新,网络中特定层的输出分布会发生变化。这迫使更高层适应这种漂移,从而减慢学习速度。在神经网络中对输入进行归一化处理后,我们就不必担心输入特征的规模会有很大差异。为了理解层规范化,将其与批规范化进行对比是很有用的。小批量由具有相同数量特征的多个实例组成。小批量是矩阵,如果每个输入是多维的,则是张量,其中一个轴对应于批量,另一个轴对应于特征尺寸。批量归一化将输入要素跨批量维度进行归一化。图层归一化的关键特征在于它对要素间的输入进行归一化。在批次规范化中,统计数据是跨批次计算的,并且对于批次中的每个示例都是相同的。相比之下,在图层规范化中,统计数据是跨每个要素计算的,并且独立于其他示例。

将剩余连接和层规范化结合在一起。

解码器

回到 Transformer 架构图,我们可以看到解码器部分和编码器部分类似,只是底部有一个被屏蔽的多头注意力。Mask 表示屏蔽某些值的掩码,以便它们在参数更新时不会产生影响。Transformer 模型中有两种遮罩—填充遮罩和序列遮罩。填充掩码用于所有缩放的点积关注,而序列掩码仅用于解码器的自关注。

填充掩码解决了输入序列长度可变的问题。具体来说,我们在一个较短的序列后填充 0。但是如果输入序列太长,左边的内容被截取,多余的直接丢弃。因为这些填充的位置其实是没有意义的,我们的注意机制不应该聚焦在这些位置上,所以需要做一些处理。具体做法是在这些位置的值上加一个非常大的负数(负无穷大),这样 softmax 之后这些位置的概率就会接近 0!填充掩码实际上是一个张量,每个值都是一个布尔值,false 的值就是我们要处理的地方。

序列掩码被设计成确保解码器看不到未来的信息。也就是说,对于一个序列,在 time_step t,我们的解码输出应该只取决于 t 之前的输出,而不是 t 之后的输出,这是特定于变压器架构的,因为我们没有 rnn 可以顺序输入序列。这里,我们一起输入所有内容,如果没有掩码,多头注意力将考虑每个位置的整个解码器输入序列。我们通过生成一个上三角矩阵来实现这一点,其中上三角的值全部为零,并将该矩阵应用于每个序列。

对于解码器的自关注,使用缩放的点积关注,并且添加填充掩码和序列掩码作为 attn_mask。在其他情况下,attn_mask 等于填充掩码。

另一个细节是解码器输入将向右移动一个位置。这样做的一个原因是,我们不希望我们的模型学习如何在训练期间复制我们的解码器输入,但是我们希望学习给定编码器序列和特定的解码器序列,这已经被模型看到,我们预测下一个单词/字符。如果我们不移动解码器序列,模型学习简单地“复制”解码器输入,因为位置 i 的目标单词/字符将是解码器输入中的单词/字符 i 。因此,通过将解码器输入移动一个位置,我们的模型需要预测位置 i 的目标单词/字符,在解码器序列中只看到单词/字符 1,…,i-1 。这阻止了我们的模型学习复制/粘贴任务。我们用句首标记填充解码器输入的第一个位置,因为这个位置会因为右移而为空。类似地,我们将一个句子结束标记附加到解码器输入序列,以标记该序列的结束,它也被附加到目标输出句子。

输出层

在完全执行解码器层之后,为了将结果向量映射到词汇表中的单词,在末尾添加了完全连接层和 softmax 层。

线性层是一个简单的完全连接的神经网络,它将解码器堆栈产生的矢量投影到一个更大的矢量中,称为 logits 矢量。让我们假设我们的模型知道 10,000 个独特的英语单词(我们模型的“输出词汇”),这些单词是从它的训练数据集学习来的。这将使 logits 向量有 10,000 个像元宽,每个像元对应一个唯一单词的分数。这就是我们如何解释线性层之后的模型输出。然后,softmax 层将这些分数转化为概率(全部为正数,总和为 1.0)。选择概率最高的像元,并产生与之相关的单词作为该时间步长的输出。

回到伯特

BERT 基于变压器架构。它是一个深度的、双向的深度神经网络模型。BERT 的关键技术创新是将 Transformer 的双向训练应用于语言建模。这与以前从左到右或者结合从左到右和从右到左训练来查看文本序列的努力形成对比。BERT 采用了一种叫做屏蔽语言建模的新技术(我们将在后面看到),这种技术允许在模型中进行双向训练,这在以前是不可能的。一般来说,Transformer 包括两个独立的机制——一个读取文本输入的编码器和一个为任务生成预测的解码器。由于 BERT 的目标是生成一个语言模型,所以只有编码器机制是必要的。

谷歌最初发布了两个版本,如下图所示。这里 L 代表变压器的层数,H 代表输出的维度,A 代表多头关注的数量。在这两个版本中,前馈尺寸被设置为 4 层。

BERTBASE: L=12,H=768,A=12,总参数=110M

伯特拉奇:L=24,H=1024,A=16,总参数= 340 米

使用 BERT 有两个阶段:预训练和微调。在预训练期间,模型在不同的预训练任务中在未标记的数据上被训练。对于微调,首先用预先训练的参数初始化 BERT 模型,并且使用来自下游任务的标记数据微调所有参数。每个下游任务都有单独的微调模型,即使它们是用相同的预训练参数初始化的。BERT 的一个显著特征是跨不同任务的统一架构。预训练架构和最终的下游架构之间的差异很小。在微调过程中,所有参数都会被微调。

BERT 预培训流程

BERT 预训练阶段由两个无监督的预测任务组成,一个是掩蔽语言模型,另一个是下一句预测。

掩蔽语言模型——由于 BERT 使用的双向功能(双向)和多层自我注意机制的影响,为了训练深度双向表示,输入标记的某个百分比(论文中为 15%)被简单地随机掩蔽,然后预测那些被掩蔽的标记。与标准 LM 中一样,对应于掩码标记的最终隐藏向量被馈送到词汇表上的输出 softmax 中。与从左到右的语言模型预训练不同,MLM 目标允许表示融合的左侧和右侧的上下文,这使得预训练深度双向变换器成为可能。虽然这允许获得双向预训练模型,但缺点是预训练和微调之间存在不匹配,因为[MASK]标记在微调期间不会出现。为了减轻这一点,作者并不总是用实际的[MASK]标记替换“被屏蔽”的单词。训练数据生成器随机选择 15%的标记位置进行预测。如果选择了第 I 个令牌,则它被替换为(1)80%时间的[掩码]令牌(2)10%时间的随机令牌(3)10%时间的未改变的第 I 个令牌。BERT 损失函数只考虑屏蔽值的预测,而忽略非屏蔽字的预测。因此,该模型比方向模型收敛得更慢,这一特性被其增强的上下文感知所抵消。

下一句预测--。为了训练理解句子关系以及单词之间的语义关系的模型,BERT 还为二进制化的下一句预测任务进行了预训练,该任务可以非常容易地从任何文本语料库中生成。为 A 和 B 选取一些句子,其中 50%的数据 B 是 A 的下一句,剩下 50%的数据 B 在语料库中随机选取,学习相关性。增加这种预训练的目的是很多自然语言处理任务如问答和 NLI 需要理解两个句子之间的关系,这样预训练的模型才能更好地适应这类任务。

为了帮助模型在训练中区分这两个句子,输入在进入模型之前以下列方式处理:

  1. 在第一个句子的开头插入一个[CLS]标记,在每个句子的结尾插入一个[SEP]标记。
  2. 指示句子 A 或句子 B 的句子嵌入被添加到每个记号。句子嵌入在概念上类似于词汇为 2 的标记嵌入。
  3. 向每个标记添加位置嵌入,以指示其在序列中的位置。Transformer 论文中介绍了位置嵌入的概念和实现。

为了预测第二个句子是否确实与第一个句子相关联,执行以下步骤:

  1. 整个输入序列经过变压器模型。
  2. 使用简单的分类层(权重和偏差的学习矩阵),将[CLS]令牌的输出转换成 2×1 形状的向量。
  3. 用 softmax 计算 IsNextSequence 的概率。

在训练 BERT 模型时,屏蔽 LM 和下一句预测一起训练,目标是最小化两种策略的组合损失函数。

记号化——BERT 不把单词看作记号。相反,它着眼于单词块。这意味着一个单词可以分解成多个子单词。这种标记化在处理词汇之外的单词时是有益的,并且它可以帮助更好地表示复杂的单词。

伯特模型输入

BERT 的输入可以是单个句子,也可以是单词序列中的一对句子(例如,[问题,答案])。对于给定的单词,其输入表示可以由三部分嵌入求和组成。嵌入的可视化表示如下所示:

令牌嵌入表示单词向量。第一个词是 CLS 标志,可用于后续分类任务。对于非分类任务,可以忽略 CLS 标志。片段嵌入用于区分两个句子,因为预训练不仅是一个语言模型,而且是一个以两个句子作为输入的分类任务。位置嵌入编码词序。

针对下游 NLP 任务的 BERT 微调

对于每个下游 NLP 任务,我们只需将任务特定的输入和输出插入到 BERT 中,并端到端地微调所有参数。在输入端,来自预训练的句子 A 和句子 B 可以类似于释义中的句子对、蕴涵中的假设-前提对、问题回答中的问题-段落对等。在输出端,记号表示被馈送到输出层用于记号级任务,例如序列标记或问题回答,而[CLS]表示被馈送到输出层用于分类,例如蕴涵或情感分析。相比于前期训练,微调相对便宜。

BERT 可以用于各种各样的语言任务,同时只在核心模型中增加了一个小的层:

  1. 通过在[CLS]令牌的转换器输出之上添加分类层,类似于下一句分类来完成诸如情感分析的分类任务。
  2. 在问题回答任务中(例如,SQuAD v1.1),软件接收关于文本序列的问题,并被要求在序列中标记答案。使用 BERT,可以通过学习标记答案开始和结束的两个额外向量来训练问答模型。
  3. 在命名实体识别(NER)中,软件接收文本序列,并被要求标记文本中出现的各种类型的实体(人、组织、日期等)。使用 BERT,可以通过将每个令牌的输出向量馈送到预测 NER 标签的分类层来训练 NER 模型。

用于特征提取的 BERT

微调方法并不是使用 BERT 的唯一方法。您可以使用预先训练的 BERT 来创建上下文化的单词嵌入。然后,您可以将这些嵌入内容添加到您现有的模型中——本文展示的这个过程产生的结果与在诸如命名实体识别等任务上微调 BERT 相差不远。

哪一种向量最适合作为情境化嵌入?这取决于任务。该文件检查了六个选项(与得分为 96.4 的微调模型相比):

希望你喜欢读这篇文章,就像我喜欢写它一样!我要承认并感谢网上一些非常惊人的资源(列在参考文献中),它们帮助我提炼了 BERT 背后的概念,我在编写这篇文章时广泛借鉴了这些资源。

参考

[## 可视化神经机器翻译模型(Seq2seq 模型的机制,注意)

翻译:中文(简体),韩文观察:麻省理工学院的深度学习艺术讲座引用此贴…

jalammar.github.io](https://jalammar.github.io/visualizing-neural-machine-translation-mechanics-of-seq2seq-models-with-attention/) [## 图示的变压器

讨论:黑客新闻(65 分,4 条评论),Reddit r/MachineLearning (29 分,3 条评论)翻译…

jalammar.github.io](https://jalammar.github.io/illustrated-transformer/)

分解相关性

原文:https://towardsdatascience.com/breaking-down-correlation-2067628e29a0?source=collection_archive---------18-----------------------

相关性是发现数量关系的第一步,值得注意。相关性被定义为数量之间的关联,例如,当人们的收入增加时,销售额可能会增加

在我们深入研究数学之前,我们需要理解协方差。协方差是变量之间关联的统计度量

Cov(x,y)= E[(x—E[x])(y—E[y])]]

上面的等式是协方差的等式,让我们来分解它

e 表示一个变量的期望值,这个值就是平均值。x-E[x]只不过是从平均值中减去 x 值,最终得到平均值的偏差。我们对 y 做同样的事情,乘以 x 和 y 相对于各自平均值的偏差。这可以被认为是一堆像这样的矩形

对于 x 和 y 的每个值,我们得到这样的矩形,平均矩形的对角向量给出了这样的关系,如果数据点沿着相同的方向,它可以是大的和正的,如果它们沿着相反的方向,我们得到一个大的和负的对角向量

如果变量是不相关的,对角线向量应该平均抵消,我们得到的量值是 0

这和相关性有什么关系?协方差值仍然与 x 和 y 处于相同的范围内,例如,cov(x,y) = 7.8 和 cov(a,b) = 6.4,我们可以看到两者正相关,但不能说哪一个强相关。相关性通过测量可变性来标准化该值,以便在一致的范围内获得值

皮尔逊相关系数

皮尔逊方法是使用最广泛的相关系数,它涉及用 x 和 y 的单个标准偏差的乘积来标准化协方差。这导致变量之间的线性关联,这意味着它用一条线来描述关系,听起来熟悉吗?是的,这听起来像是最合适的路线。让我们回到这一部分

可以看出,分子是协方差,分母使用标准偏差将值从-1 标准化到 1,这使得解释更容易。

如果变量 x 和 y 是独立的,系数接近于 0,而不是相反,让我们来看看为什么

回归线和相关系数之间有明显的相似性。通过最小化点之间的距离来计算最佳拟合线,这在数学上等同于相关方程分子中的偏差。所以相关性可以安全地写成

ρ = b (sx/sy)

其中 b =斜率

说了这么多,相关性并不等同于斜率。通过可变性测量标准化的斜率给出了相关系数!瞧啊。。换句话说,因为最佳拟合线没有考虑变量的可变性,所以我们可以得到具有高相关系数的较小斜率

所以下次当你遇到这两种方法的相似之处时,请注意这一点。使用相关性的缺点是它对异常值很敏感,因为它使用平均值,标准差来计算关系

另一种解释相关系数的方法是,把它平方,我们得到的是 x 变量解释的 y 的方差比例,听起来很熟悉吧?是的,这是用于衡量线性 ML 模型性能的 R2 指标

对于 eg,相关的平方= (-0.85)给出大约 72%

这是因为在最小二乘法中,我们从总数中计算误差平方和的比例,并减去 1,以获得正确解释的可变性,这在数学上等同于相关系数的平方,这也解释了数据的可变性

这些是看待相关性的一些方式,事实上,还有 13 种方式,所以下次我们学习一个指标时,作为数据科学家,我们应该愿意以多种方式看待它们,因为每个指标都以某种方式与其他指标相关联

干杯!

在《PyTorch》中分解莱昂·加蒂斯的神经风格转移

原文:https://towardsdatascience.com/breaking-down-leon-gatys-neural-style-transfer-in-pytorch-faf9f0eb79db?source=collection_archive---------13-----------------------

Neural Style Transfer performed on an image of a cat.

2015 年 Leon Gatys 等人在他们的论文“艺术风格的神经算法”(arXiv:1508.06576v2)中提出了一种神经风格转移的方法。我总是着迷于神经网络模型能够进行风格转移,当时结果对我来说就像魔术一样。在这篇短文中,我想详细介绍使用 PyTorch 实现原始的神经类型转换算法。

我知道网上有很多教程。然而,我发现它们都很令人困惑,而且对于这项任务来说过于复杂。在有些沮丧之后,我决定自己实现原始论文中的方法,试图将技术分解到最小的部分,而不使用任何花哨的东西。这个实验的目标更多的是理解这个方法的理论,而不是在产品中实现这个模型,我希望这篇文章对你理解神经风格转移模型有所帮助。

首先,我想回顾一下 NST 方法的基础——特征提取。卷积神经网络享有完全连接或递归神经网络都无法享有的东西——可解释的提取特征。如果你熟悉卷积层如何传播信号,你最有可能看到激活图和滤波器可视化。如果没有,Francois Chollet 的《用 Python 进行深度学习》5.4 节是很好的参考。另外,Ian Goodfellow 等人的《深度学习》中的图 1.2 是一个很好的参考。

为什么这很重要?我们知道更深层次的神经网络提取更多的一般特征。在卷积神经网络的情况下,网络的较低层提取非常局部的特征,例如边、角和颜色。在更深的层中,这些边和角被组合在一起以表示越来越多的全局特征,例如形状、面部,有时甚至是整个物体,例如计算机键盘。

Gatys 等人的方法基于卷积网络的独特能力,能够在网络的不同层提取不同尺度的特征。他们认为,网络较低层的混合可以提取纹理和配色方案,而较深层的一层可以提取图像的整体结构,我们可以在一幅图像中以某种方式组合这些特征,以实现风格转移。他们在实验中表明这确实是可能的,为进一步研究打开了神经类型转移的整个领域。

我希望你在这一点上不要太迷茫(如果有的话),因为神经类型转移的方法论一开始有点混乱,但是,最终,非常简单明了。

我们从 2 个图像开始:第一个图像是我们希望提取内容的图像。我用的是在网上找到的一只猫的图片,所以想把猫的内容提取出来。

The image of a cat I wish to stylize.

第二个图像是我们希望提取样式的图像。通常情况下,我们希望使用具有强烈风格的图像,这样风格的转换将在美学上令人愉快。实验表明艺术品的效果最好。但是,您可以从任何图像中提取您想要的样式。我确信如果我们想的话,我们可以提取上面这张图片的风格。

以下是我用于神经风格转移模型的一些作品:

The style images we are going to transfer the style from.

实现

我们将使用 VGG19 模型进行风格转换。VGG19 常用于原始风格转换实现,但这不是必需的。有可能许多其他较新的模型可以提供更好的特征提取结果,但是社区将它们留给实验。VGG19 是一个简洁、紧凑的模型,在原始论文中也使用了它。因此,我们也将使用它,试图获得尽可能接近原始论文的结果。

Gatys 等人提出使用 VGG19 模型提取 2 组特征。使用模型的“block4_conv2”层,从内容图像中提取第一组特征,即内容特征。第二组特征,即风格特征,使用“block1_conv1”、“block2_conv1”、“block3_conv1”、“block4_conv1”、“block5_conv1”层从风格图像中提取。

为什么我们从 5 层而不是 1 层中提取样式?本文中的图 1 很好地比较了使用 VGG19 模型不同层的样式和内容重建。所以,答案是:从经验上来说,如果我们使用这五层,这种风格看起来更有吸引力。层数和其他因素的实验会产生特定的结果,我们会根据经验选择最佳结果,就像神经机器学习中的任何其他模型一样。请注意,如果我们使用不同的模型而不是 VGG19,几乎可以肯定的是,我们将不得不为内容和样式提取选择一些其他的图层集。

因此,我定义了自定义 VGG 导数,如下所示:

现在,当我们定义了 VGG 特征提取器网络后,我们就可以继续了。

Gatys 等人提到,为了获得更好的结果,他们将最大汇集层替换为平均汇集层:

Replacing the Max Pooling layers with the AVG Pooling layers.

理解我们的 VGG19 网络作为静态特征提取器执行,并且权重在训练过程中不会改变,这一点很重要。因此,让我们把梯度计算锁定在网络参数上:

Turn off the gradient computation in the VGG parameters.

好了,现在,当我们的网络被锁定时,我们可以从内容和样式图像中提取内容和样式特征。

我们可以通过 VGG 网络传递内容图像并收集“block4_conv2”层的输出来提取内容特征。现在,产生的激活是 CxHxW 尺寸。Gatys 建议将激活图展开成二维张量 CxH*W,因此我们也将这样做:

Extracting the content features and unrolling them.

请注意,我们必须将激活从计算图中分离出来,因为我们不希望梯度流过它们。让我们先把内容特性放在一边,我们稍后会用到它们。

现在,我们需要从样式图像中提取样式。我们通过我们的 VGG 网络传递样式图像,并采集“block1_conv1”、“block2_conv1”、“block3_conv1”、“block4_conv1”、“block5_conv1”层的输出来实现这一点。然后,我们将“展开”它们,就像我们处理内容激活一样。

有一个额外的步骤涉及到从样式图像中提取样式。特征本身不足以提取图像的风格。然而,Gatys 等人提出计算每一层激活的空间相关性。我们可以通过计算每层的格拉米矩阵来做到这一点。格拉米矩阵是输入张量的列和这些列的转置的点积。在格拉米矩阵中,我们可以看到哪些空间特征支配着其他空间特征:

Gram matrix calculation.

将样式提取放在一起会产生:

我们分离激活的原因与我们分离内容图像的激活的原因相同:我们将在损失计算中使用它们作为目标值。因此,我们不希望梯度流过它们。

这是该方法的关键思想。我们将从高斯噪声中定义一个图像,然后我们将在图像空间中执行参数搜索,其中参数是这个噪声图像的像素。当我们在我们的假设空间中找到一个图像,并且这个图像在内容图像的激活和风格图像的激活的 Gram 矩阵中具有最小的损失时,我们将会感到满意。结果图像将具有内容图像的内容和样式图像的样式。

也就是说,原始论文中的等式(1)和(4–5)定义了损耗。我使用 Adam optimizer 在图像空间中执行搜索。我们可以按照以下方式定义噪声图像和优化器:

The noise image and the optimizer definition.

注意,许多实现建议使用 L-BFGS 优化算法。然而,为了使事情更容易理解,并表明我们使用哪个优化器并不重要,我使用 Adam 优化器。

现在,我们开始优化循环。该过程可总结如下:

  1. 从 VGG 中获取噪声图像的内容激活
  2. “展开”噪声图像的内容激活
  3. 计算内容图像的内容激活和噪声图像的内容激活之间的内容损失:SSE
  4. 从 VGG 中获取噪声图像的样式激活
  5. “展开”噪声图像的样式激活
  6. 计算噪声图像的风格激活的每一层的 Gram 矩阵
  7. 将每个图层的加权样式损失相加
  8. 将加权的风格和内容损失加在一起
  9. 反向传播

10.更新噪声图像的像素

11.重复 1–10

基本上,在每次迭代中,我们都要提取噪声图像的内容和风格。然后,我们将通过计算损失来比较噪声图像的内容和风格与内容图像的内容和风格图像的风格。然后,我们将这些损失加在一起,但我们将在此之前对它们进行加权,以引入一种风格-内容平衡机制。该损失将为我们提供当前噪声图像在内容上离内容图像有多远以及在风格上离风格图像有多远的估计。然后,当我们执行反向传播时,我们计算总损失相对于图像像素的梯度,因此我们知道应该在哪个方向上调整当前噪声图像中的像素,以在内容和风格上更接近参考图像。

这是模型的训练循环,请注意,我省略了一些通过阅读本文可以容易理解的次要细节。:

The main training loop for the Neural Transfer Model.

添加变化损失是为了使图像看起来更好,其定义如下:

值得一提的是,内容、风格和变化损失之间的平衡非常重要。每一次风格转换都需要你调整每一次损失的贡献,这可以根据经验来衡量。

结果

以下是我通过运行原始的神经类型转移模型获得的一些结果。

样式提取

Style (right) extracted out of the original image (left).

Style (right) extracted out of the original image (left).

Style (right) extracted out of the original image (left).

Style (right) extracted out of the original image (left).

风格转移

Style transferred to the cat image.

最初的方法有一个主要缺点:每次我们想要执行样式转换时,我们都必须运行优化算法。此外,使用原始方法执行样式转换在计算上非常昂贵(至少对于 Adam 优化器来说是这样),因此它不太适合在线使用或生产。

存在一些使用神经网络参数搜索代替图像参数(像素)搜索的其他神经类型转移方法。这些模型允许为每种想要提取的样式训练一个单独的网络,然后许多内容图像可以在一次转发中被风格化。这样的车型更适合生产。事实上,我正计划研究一些这样的模型,并希望在不久的将来写下它们,这样我们就可以将结果与 Leon Gatys 等人的原始论文进行比较。

我在本文中使用的代码可以在这里免费获得。回购还包括打包模型,您可以在 2 个图像上运行,以执行神经风格转移。

感谢您的阅读!

编辑 :下面是我在训练中记录的一些形成噪音的有趣 gif:

分解平均精度(mAP)

原文:https://towardsdatascience.com/breaking-down-mean-average-precision-map-ae462f623a52?source=collection_archive---------1-----------------------

数据科学工具包的另一个指标

Photo by Şahin Yeşilyaprak on Unsplash

如果你遇到过 PASCAL 视觉对象类(VOC)MS 上下文中的公共对象(COCO) 挑战,或者涉足过涉及信息检索和重新识别(ReID)的项目,那么你可能会非常熟悉一种叫做 mAP 的度量标准。

平均精度(mAP)或有时简称为 AP 是一种流行的度量标准,用于测量执行文档/信息检索和对象检测任务的模型的性能。

一组查询的平均精度(mAP)由维基百科定义如下:

Mean average precision formula given provided by Wikipedia

其中 Q 是集合中查询的数量,AveP(q)是给定查询 Q 的平均精度(AP)。

该公式本质上告诉我们的是,对于给定的查询 q,我们计算其相应的 AP,然后所有这些 AP 得分的平均值将为我们提供一个称为 mAP 的数字,它量化了我们的模型在执行查询方面的表现。

这个定义让在这个领域刚刚起步的人(比如我)感到困惑。我有一些问题,比如这组查询是什么?还有 AP 是什么意思?只是精度的平均值吗?

本文希望解决这些问题,并为目标检测和信息检索任务计算 mAP。本文还将探讨为什么 mAP 是信息检索和对象检测任务的一个合适且常用的度量。

概述

  1. 初级读本
  2. 用于信息检索的 AP 和 mAP
  3. 用于对象检测的 AP 和 mAP

1.底漆

查准率和查全率是两个常用的度量标准,用来判断给定分类模型的性能。为了理解 mAP,我们需要首先回顾一下精度和召回率。

越是“有名”的精确和回忆

在统计学和数据科学领域,分类中给定类别的精度,即所谓的阳性预测值,是指真阳性(TP)与预测阳性总数的比值。公式给出如下:

Precision formula of a given class in classification

类似地,召回,也称为分类中给定类别的真阳性率或灵敏度,被定义为 TP 与真实阳性总数的比率。公式给出如下:

Recall formula of a given class in classification

仅仅通过查看公式,我们就可以推测,对于一个给定的分类模型,在它的精确度和召回性能之间存在一个折衷。如果我们使用神经网络,这种权衡可以通过模型的最终层 softmax 阈值来调整。

为了提高我们的精度,我们需要减少 FP 的数量,这样会降低我们的召回率。同样,减少 FN 的数量会增加我们的回忆,降低我们的精确度。对于信息检索和对象检测的情况,我们经常希望我们的精度很高(我们预测的阳性是 TP)。

(source)

精确度和召回率通常与其他指标一起使用,如准确性、F1 分数、特异性、真阴性率(TNR)、接收器操作特性(ROC)、提升和增益。

不太“出名”的精确度和召回率

但是,说到信息检索,定义就不同了。

根据 Wiki 的定义,精度定义为与用户查询相关的检索文档与检索文档的比率

Precision formula for information retrieval given by Wiki

保持术语类似于上面定义的公式,相关文件可以被视为一个 TP。

默认情况下,precision 会考虑所有检索到的文档,但是,也可以在给定数量的检索到的文档上评估 precision,这通常称为截止等级,在这种情况下,仅通过仅考虑其最顶层的查询来评估模型。这种测量称为 k 处的精度或 P@K

让我们用一个例子来更好地理解这个公式。

定义典型的信息检索任务

信息检索中的典型任务是用户向数据库提供查询,并检索与该查询非常相似的信息。现在让我们用一个带有三个真实值(GTP)的例子来计算精度。

附加术语:基本事实阳性是被标记为阳性的数据。换句话说,相关文件。

我们将定义以下变量:

  • q 成为用户查询
  • g 是数据库中的一组标记数据
  • d(i,j)是一个得分函数,以显示对象 I 与 j 有多相似
  • 其中 G 的有序集合根据得分函数 d(,)
  • k 是 G '的指数

User querying G with a document Q

在用 Q 计算了每个文档的 d(,)之后,我们可以对 G 进行排序并得到 G’。

假设模型返回以下 G '

Model returned sorted query results G’

使用上面的精度公式,我们得到以下结果:

P@1 = 1/1 = 1

P@2 = 1/2 = 0.5

P@3 = 1/3 = 0.33

P@4 = 2/4 = 0.5

P@5 = 3/5 = 0.6

P@n = 3/n

类似地,Wiki 定义的召回公式被给出为与用户查询相关的检索文档与相关文档的比率。

Recall formula for information retrieval given by Wiki

在这种情况下,召回率不如运行返回查询的所有文档将导致微不足道的 100%召回率有用,因此召回率本身通常不被用作度量。

回到大纲

2.信息检索的平均精度和映射

熟悉 precision@k 之后,我们现在可以继续计算平均精度。这将使我们更好地衡量我们的模型对查询结果 G '进行排序的能力。

AP@n formula

其中,GTP 指的是基本事实正的总数,n 指的是你感兴趣的文档的总数,P@k 指的是精度@k,而 rel@k 是相关性函数。相关性函数是指示函数,如果排名 k 的文档是相关的,则该指示函数等于 1,否则等于 0。

回想一下精度的定义,我们现在将使用它来计算 G '中每个文档的 AP。使用上面所示的相同例子,

Calculation of AP for a given query, Q, with a GTP=3

这个查询的总 AP 是 0.7。需要注意的一点是,因为我们知道只有三个 GTP,所以 AP@5 等于总 AP。

对于另一个查询 Q,如果返回的 G '排序如下,我们可以得到完美的 AP 1:

Calculation of a perfect AP for a given query, Q, with a GTP=3

在这种情况下,AP 所做的是惩罚那些不能用 TPs 引导集合来排序 G '的模型。它提供了一个数字,能够根据得分函数 d(,)量化排序的优劣。通过将精度之和除以总 GTP 而不是除以 G '的长度,可以更好地表示只有几个 GTP 的查询。

计算地图

对于每个查询 Q,我们可以计算相应的 AP。用户可以对这个带标签的数据库进行任意多的查询。地图只是用户进行的所有查询的平均值。

mAP formula for information retrieval

注意:这和维基百科的公式一样,只是写法不同。

回到大纲

3.目标检测的平均精度和 mAP

计算 AP(传统 IoU = 0.5)

并集上的交集

为了计算物体检测的 AP,我们首先需要理解 IoU。IoU 由预测边界框和地面真实边界框的交集面积和并集面积的比率给出。

(source)

IoU 将用于确定预测的边界框(BB)是 TP、FP 还是 FN。由于假设每个图像中都有一个对象,因此不评估 TN。让我们考虑下面的图像:

Image with a man and horse labeled with ground truth bounding boxes (source)

该图像包含一个人和一匹马,以及它们对应的地面真实边界框。让我们暂时忽略马。我们在这个图像上运行我们的对象检测模型,并且接收到这个人的预测边界框。传统上,如果 IoU > 0.5,我们将预测定义为 TP。可能的情况如下所述:

真正(IoU > 0.5)

IoU of predicted BB (yellow) and GT BB (blue) > 0.5 with the correct classification

假阳性

在两种可能的情况下,BB 将被视为 FP:

  • IoU < 0.5
  • 重复 BB

Illustrating the different scenarios a predicted BB (yellow) would be considered as FP

假阴性

当我们的目标检测模型错过了目标,那么它将被认为是一个假阴性。两种可能的情况如下:

  • 根本没有检测的时候。

No detection at all

  • 当预测 BB 的 IoU > 0.5 但分类错误时,预测 BB 将为 FN。

FN BB as the predicted class is a horse instead of a person

精确度/召回曲线(PR 曲线)

正式定义了 TP、FP 和 FN 之后,我们现在可以计算测试集中给定类的检测精度和召回率。每个 BB 都有其置信度,通常由其 softmax 层给出,并用于对输出进行排序。请注意,这与信息检索的情况非常相似,只是我们没有使用相似性函数 d(,)来提供排名,而是使用模型预测的 BB 的置信度。

插值精度

在绘制 PR 曲线之前,我们首先需要知道[ 1 中引入的插值精度。插值精度 p_interp 是在每个召回级别 r 上计算的,取该r的最大测量精度。公式如下:

Interpolated Precision for a given Recall Value (r)

其中 p(r)是召回 r 时的测量精度。

他们内插 PR 曲线的目的是减少由检测等级的微小变化引起的“摆动”的影响。

这样一来,我们现在可以开始绘制 PR 曲线了。考虑一个具有 3 TP 和 4 FP 的 person 类的例子。我们通过上面定义的公式计算相应的精度、召回率和插值精度。

Calculation table for plotting PR curve with an example of 3 TP and 4 FP. Rows correspond to BB with person classification ordered by their respective softmax confidence

然后通过 PR 曲线下的面积计算 AP。这是通过将召回平均分为 11 个部分来实现的:{0,0.1,0.2,…,0.9,1}。我们得到以下结果:

Calculation of AP for the above example

再举一个例子,我想让你参考乔纳森·惠的这篇写得很好的文章【2】

计算地图

用于对象检测的 mAP 是为所有类别计算的 AP 的平均值。还需要注意的是,对于一些论文,它们交替使用 AP 和 mAP。

计算 AP 的其他方法

参考[ 5 ],COCO 提供了六种计算 AP 的新方法。

这些方法中的三种在不同的 iou:处对 BB 进行阈值处理

  • AP:IoU = 0.50 时的 AP:0.05:0.95(主要挑战指标)
  • AP@IoU=0.5(如上所述的传统计算方法)
  • AP @ IoU = 0.75(BBs 的 IoU 需要> 0.75)

对于主 AP,0.5:0.05:0.95 意味着从 IoU = 0.5 开始,步长为 0.05,增加到 IoU = 0.95。这将导致在十个不同的 iou 上 AP 阈值的计算。进行平均以提供奖励定位更好的检测器的单个数字。

其余三种方法是跨尺度计算AP:

  • 小型物体的 AP^small: AP:面积< 32² px
  • AP^medium: AP for medium objects: 32² < area < 96² px
  • AP^large: AP for large objects: area > 96 像素

这将允许更好地区分模型,因为一些数据集比其他数据集具有更多的小对象。

回到大纲

发现错误?随意评论!

特别感谢德里克 韦杰 对本文的校对和反馈。

随时通过TwitterLinkedIn与我联系!****

如果你对我参与过的其他项目感兴趣,可以随时访问我的Github**

对于我的其他作品:

  1. 使用 Python、pandas、seaborn 和 scikit-learn 进行探索性数据分析的入门包
  2. 我如何通过 6 个简单的步骤将人体动作分类器提高到 80%的验证准确率

参考资料:

  1. 由 Mark Everingham、Luc Van Gool、Christopher K. I. Williams、John Winn 和 Andrew Zisserman 发起的 PASCAL 视觉对象类(VOC)挑战
  2. https://medium . com/@ Jonathan _ hui/map-mean-average-precision-for-object-detection-45c 121 a 31173
  3. https://makarandtapaswi . WordPress . com/2012/07/02/intuition-behind-average-precision-and-map/
  4. https://en . Wikipedia . org/wiki/Evaluation _ measures _(information _ retrieval)# Mean _ average _ precision
  5. http://cocodataset.org/#detection-eval
  6. https://tarangshah . com/blog/2018-01-27/what-is-map-understanding-the-statistic-of-choice-for-comparisng-object-detection-models/

分解评论文章

原文:https://towardsdatascience.com/breaking-down-review-articles-6a85a897c3fb?source=collection_archive---------23-----------------------

使用评论文章来帮助你过渡到新的研究领域

开始一个新的研究领域似乎是一项艰巨的任务。尤其是当该领域每年发表的论文数量呈指数级增长时。这种快速增长使得跟上当前的研究实践变得极其困难。更高的更替率意味着更少的公认标准,因为新的工作专注于提出下一个最好的想法,而不是重复当前的方法。如果你开始不加选择地阅读一篇又一篇被广泛引用的论文,你会感觉像一个永无止境的迷宫。

The never-ending agony of reading referenced paper after referenced paper.

那么,这是否意味着我们一旦开始努力跟上,就注定要失败呢?不,一点也不,尤其是如果你有计划的话。

评论或调查文章是了解新领域的好方法。它们包括该领域最初问题的历史信息,以及过去试图解决这些问题的研究成果。目前的方法是在某种程度上提出来与其他方法进行比较。拥有明确的问题领域可以帮助你根据你的情况或兴趣找出你应该集中精力做什么。此外,综述文章最好的部分是它们充当了一个精心策划的参考文献列表,您可以使用它来了解更多关于该方法的细节。现在我想让你向我介绍一下我是如何为我的博士研究和我的兴趣分解评论文章的。

我如何浏览一篇评论文章

我最近想知道更多关于当前推荐系统如何集成深度学习的信息。如果你不知道,推荐系统使用用户和商品的过去信息来预测或推荐未来用户与新商品的互动。例如,在一个电影推荐器中,电影是项目,个人可能是用户。这个问题的交互方式因格式和对不同类型数据的访问而异。它可以是一个评级系统(1-5),也可以是一个👍或者👎,也可能只是用户之前是否看过这部电影。

查找评论文章

Arxiv 和谷歌学术是寻找评论文章的好地方。谷歌学术可以绑定到一个大学账户上,这样你在校园网上可以看到的任何文章都可以在校外看到。然而,在这里,我只使用 Arxiv,因为任何人阅读这篇文章都是免费的。

专家提示:如果你发现一篇你无法获得的优秀科学论文,通过电子邮件联系作者,他们很可能会给你寄一份。

在搜索了 Arxiv 之后,我决定选择论文“基于深度学习的推荐系统:调查和新观点”我最终选择这篇文章有几个原因。

  1. 这是最近的一篇论文。随着 2019 年 7 月发布的最新版本,它应该包含了该领域的大多数最新进展。
  2. 这篇综述发表在 ACM 上。注意,一篇论文发表了并不代表它就是好的。在这种情况下,同行评审过程应该有助于确保没有重大贡献被遗漏。
  3. 报纸的版面。作者将工作分成清晰的部分,使其更容易分析和理解所有评论文章如何适应更大的画面。

分解它

好了,现在我们有了一篇评论文章,我们可以开始一点一点地分解它。作为一种组织信息的方式,我通常会尝试将文章分成不同的部分。当试图将多篇文章的观点结合起来,并为将来的参考提供一个好的总结时,这是特别有用的。

写作原因

一些评论文章提供了他们写评论文章的动机。他们的动机是确定他们希望涵盖的研究范围以及了解你可能感兴趣的其他文章的一个很好的方式。

在过去的几年里,对传统推荐系统的一些调查已经被提出…然而,有一个缺乏对基于深度学习的推荐系统的广泛评论。就我们所知,只有两个相关的简短调查[7,97]正式发表…鉴于深度学习在推荐系统中应用的日益普及和潜力,一个系统调查将具有很高的科学和实用价值。我们从不同的角度分析了这些作品,并对这一领域提出了一些新的见解。为此,超过 100 项研究在本次调查中入围并分类

通过这一小段摘录,我们知道作者写这篇论文是对 100 多篇关于深度学习在推荐系统中的使用的文章的广泛系统调查。此外,它旨在提供一个不同的视角,而不是在该领域的前两个审查文件。

定义

检查并查看作者是否对他们在评论中涉及的主题进行了详细描述总是有好处的。明确的定义有助于消除由于该领域中的非标准术语而导致的任何可能的误解。

推荐系统估计用户对项目的偏好主动向他们推荐用户可能喜欢的项目【1,121】。推荐模型通常分为三类【1,69】:协同过滤基于内容的混合推荐系统

现在,我们可以将本文中介绍的每个推荐系统分为三个不同的类别。然后,他们继续定义每个类别。

协同过滤通过 l 从用户-项目历史交互中获得,或者是显性的(例如用户以前的评级)或者是隐性的反馈(例如浏览历史)来进行推荐。基于内容的推荐主要基于 c 跨项目的比较和用户的辅助信息。多种多样的辅助信息,如文本、图像和视频都可以考虑在内。混合模型是指整合了两种或两种以上推荐策略的推荐系统【8,69】。

A flowchart showing the relationship between types of recommender systems.

因此,一个推荐系统,使用用户如何与项目互动的过去信息,是协同过滤。使用关于用户或项目的信息来确定不同项目或用户的相似性,然后基于该相似性进行推荐的系统是基于内容的推荐器。最后,如果推荐器结合了不同的方法,它就是一个混合系统。

应用程序和数据

确定所回顾的方法旨在回答的问题的种类对于理解当前和未来的研究方向是至关重要的。对于推荐系统,我们想知道当前系统的目的以及每个系统所需的数据类型。

在行业中,对于许多在线网站和移动应用来说,推荐系统是增强用户体验和促进销售/服务的重要工具。例如,在网飞上观看的 80%的电影来自推荐[43],60%的视频点击来自 YouTube 的主页推荐[30] … Covington 等人[27]提出了一种基于深度神经网络的推荐算法,用于 YouTube 上的视频推荐。Cheng 等人[20]提出了一个用于 Google Play的具有宽 T36 深模型的 T32 应用推荐系统。Shumpei 等人[113]为雅虎新闻提出了一个基于 RNN 的 T34 新闻推荐系统 T35。

对于这些应用程序中的每一个,我们可以想象需要不同来源和格式的数据。令人欣慰的是,作者提供了一个表格,对每个来源的评审工作进行了分类。现在,我们只需要阅读四篇文章,而不是浏览所有的 100 篇评论文章,看看他们是否使用视频作为输入来源。

This table shows how the authors categorize publications based on the data source and task.

未来研究和未决问题

在论文的最后部分,作者讨论了该领域的开放问题和未来研究的途径。如果你是一个刚刚进入这个领域的人,这可能是一个获得未来项目和工作方向想法的好地方。

  1. 从用户和项目中联合学习
  2. 可解释性
  3. 更深入
  4. 机器推理
  5. 跨域
  6. 多任务学习
  7. 可量测性
  8. 更好、更统一、更难的评估

这些都是你感到舒适后开始新项目的好地方。

把所有的放在一起

通读本文后,我们对推荐系统的内容、原因和位置有了更好的理解。遗憾的是,在这一点上,我们离成为该领域的专家还差得远。然而,我们可以开始了解该领域的研究是如何分类的,以及我们可以阅读哪些论文来获得更多信息。

我希望这是一个有用的练习,看看如何将综述论文分解,以帮助更好地理解新的研究领域。虽然这肯定不是审查论文的唯一方法,但我发现这些技巧对我很有帮助。

如果你有问题或者你想分享一些你用来审阅论文的技巧,请在下面留下你的评论。

最初发表于【https://www.coreydeon.com】

引文

1 S. Zhang,L. Yao,A. Sun,和 Y. Tay,基于深度学习的推荐系统:调查和新观点 (2019),ACM 计算调查(CSUR) 52.1: 5

用 PyTorch 和月球着陆器打破 Richard Sutton 的政策梯度

原文:https://towardsdatascience.com/breaking-down-richard-suttons-policy-gradient-9768602cb63b?source=collection_archive---------8-----------------------

Lunar Lander Artwork from https://70sscifiart.tumblr.com/post/157053475728/1969-nasa-concept-art-of-the-apollo-11-lunar

在 21 世纪初,已经发表了一些关于强化学习中的政策梯度方法(以一种或另一种形式)的论文。最值得注意的是 Richard Sutton 等人的“利用函数逼近进行强化学习的策略梯度方法”

在这篇短文中,我们将试着理解带有一些怪癖的普通策略梯度算法。此外,我们将使用策略梯度算法训练一个智能体来解决 CartPole 和 LunarLander OpenAI 健身房环境。完整的代码实现可以在这里找到。

策略梯度算法位于策略优化深度强化学习方法家族的核心,例如(异步)优势行动者-批评家和信任区域以及近似策略优化。许多其他算法也与策略梯度算法有许多相似之处。

策略梯度和深度 Q 学习方法之间的差异是非常明显的。在策略梯度的情况下,我们优化重要的东西,即策略的性能,而不是诸如动作值之类的替代度量。此外,与确定性策略相反,策略梯度算法能够学习随机策略。最后,策略梯度是基于策略的算法,而深度 Q 学习是基于策略的算法,这使得它们的样本效率不同(策略梯度方法具有较低的样本效率)。

理查德·萨顿和安德鲁·巴尔托的《强化学习》的第 13 章详细描述了算法的策略梯度系列。此外,我发现这个开放人工智能资源有助于所涉及的数学背后的直觉;我强烈推荐通读这两本书。

理论背后的政策梯度算法

在我们实现策略梯度算法之前,我们应该复习一下算法中涉及的具体数学知识。数学非常简单易懂,并且在很大程度上是从上面提到的 OpenAI 资源中重新解释的。

首先我们定义 tau 为一个轨迹或一系列动作以及执行这些动作所获得的相应奖励。

An abstraction of a trajectory

现在,我们可以将奖励函数定义为轨迹奖励的贴现或无贴现(对于情节任务)总和。在实践中,我们会发现,即使对于偶发的任务,使用奖励的折扣总额也更有益,定义如下:

Discounted sum of the rewards, obtained from a trajectory

其次,我们将性能度量 J 定义为来自最近一批轨迹(在当前策略执行下获得)的报酬的某个函数的期望值。

Performance measure

让我们更深入地研究一下性能指标。根据期望的定义,我们得到:

Expanding the expectation over the trajectory

重要的是要明白,我们希望使用性能测量的梯度来优化我们的策略(代理)。因此,我们得到以下结果:

Adding the gradient wrt the parameters of the policy

现在,有一个很好的技巧或对数导数技巧,它来自下面的恒等式:

log-derivative trick

我们可以使用这个技巧,用概率和轨迹对数概率的梯度的乘积来代替轨迹概率的梯度,或者:

Adding the log-probability of the trajectory

如果我们仔细观察右边,我们可以注意到它本身就是一个期望:

Bringing the integral back to expectation

但是轨迹的对数概率是多少呢?原来我们可以用链式法则来定义轨迹上的概率:

Chain rule can be used to define the probability distribution over the trajectory space

直觉上,这个链式法则很有意义。我们从一些初始状态分布中抽取初始状态。然后,由于我们的行动是随机的,我们在行动空间中选择一个有一定概率的行动,这就是我们的策略。最后,过渡模型也是随机的;因此,我们乘以从前一个状态转移到下一个状态的概率。我们继续这个过程,直到我们到达集的结尾。

现在,让我们看看轨迹空间上的对数概率分布:

Log-probability over the trajectory space

让我们计算相对于策略参数的轨迹空间上的对数概率的梯度:

Calculating the gradient of the log-probability over the trajectory space

我们看到只有政策概率分布依赖于政策参数。因此,其余项的值为零。最后,我们可以将所有的数学计算放在一起,得出:

The gradient of the performance measure can be approximated by sampling

现在,由于性能度量的梯度是一个期望值,我们可以用抽样来估计它,这非常容易。我们将在当前策略下生成几个轨迹(因为策略梯度是一个策略上的算法),然后将计算我们从代理(策略)获得的加权(通过 R(tau))对数概率的平均值。

我们将使用从时间 t 到本集结束的折扣奖励的总和,而不是折扣奖励的总和。这些被称为奖励-继续,在政策梯度方法中更频繁地使用,因为在时间 t 之后提交的行为不应对这些行为发生之前获得的奖励产生任何影响。

Rewards-to-go

熵加成

在代码中,我们还将使用熵加成来阻止严格的确定性。思路相对简单:我们在策略优化过程中,从“损失”中减去策略的熵。如果代理人对自己的行为过于自信,那么政策的熵就会变小,红利就会消失。策略的熵是强化学习中反复出现的主题,并用于其他算法,如软演员-评论家。

基线

我们还将使用一个基线。基线是在不影响期望值的情况下从 R(τ)中减去的量,因为通常基线是特定于状态的量。我们将使用特定州的轨迹回报平均值作为基线。

基线减少了政策梯度估计的差异。直觉上,这很有意义,尤其是在横翻筋斗的情况下。假设我们的代理可以平衡杆子 2 秒钟。这是好事还是坏事?如果在这一集之前,代理人平均平衡了 1 秒钟,那么是的,这是更好的表现。在这种情况下,策略梯度将被估计为正,并且代理将朝着进一步改进的方向迈出一步。

然而,如果代理在事件发生前平均平衡极点 3 秒,则策略梯度将被估计为负,并且我们仍将朝着正确的方向迈出这一步,远离使代理平衡极点 2 秒的参数。如果我们不使用基线,1 秒和 3 秒以及 10 秒的插曲都会导致相似的梯度方向;因此,培训可能需要更长的时间。

需要注意的是,对于像 LunarLander 这样更复杂的问题,基线不太直观,因为我们有正面和负面的奖励,奖励的规模也不同。

PyTorch 实现

代码和算法背后的数学一样简单明了。然而,能够将数学语言翻译成代码本身就是艺术,我发现这部分有时是最困难的。

既然我们知道可以通过抽样来估计性能度量的梯度,我们就应该对其采取行动。我们将在当前政策下播放 N 集 LunarLander,并在这些集上累积一批轨迹。注意,由于策略梯度是一种随机策略算法,我们将用从代理网络的逻辑中获得的相应概率来对我们的行为进行采样。**

因此,我们将累积所有行动逻辑和行动的对数概率,以及 N 集内所有行动的回报,以计算策略梯度的近似值。我们还将计算熵奖金和奖励去。

以下是播放一集环境并收集所有轨迹和相应计算值的循环:

The play_episode method

在下面的要点中,你可以看到如何从你的轨迹中获得奖励来计算奖励:

Discounted rewards-to-go method

因此,在算法训练的一个时期,我们有 N 个轨迹,或者更准确地说,N 个行动对数概率数组和 N 个奖励数组。现在,我们需要做的就是用相应的奖励值来“加权”我们用当前策略收集的行动的对数概率。这样,我们获得了 N 个“加权”行动对数概率数组。通过取“加权”对数概率的平均值,我们最终可以得到政策梯度估计值:

Calculating the policy “loss” and the entropy bonus

现在,当我们拥有策略梯度算法的所有移动部分时,我们可以通过根据我们的策略梯度估计采取步骤来解决环境问题:

Solving the CartPole or LunarLander environments

月球着陆器截图

以下是我在训练月球着陆器任务的代理时捕捉到的一些截图:

**

In the beginning of training the agent is acting maximally random as the distribution over actions is approximately uniform

As training progresses the agent chooses better actions and learns how to generalize

收敛度量

Average return over 100 episodes for Lunar Lander environment

Policy entropy for the Lunar Lander agent. Later in the training process the agent becomes more certain about the actions it takes

Average return over 100 episodes for Cart Pole environment

Policy entropy for the Cart Pole agent.

感谢您的阅读!

打破聚集的聚类过程

原文:https://towardsdatascience.com/breaking-down-the-agglomerative-clustering-process-1c367f74c7c2?source=collection_archive---------9-----------------------

如何将聚合聚类应用于数据的详细步骤

16S rRNA species tree with Neighbour Joining Cluster method and Kimura-2 Parameter model using 1000 bootstrap from my thesis “ CHEMICAL AND MOLECULAR TAXONOMY ACTINOMYCETES ISOLATE FROM JAMBI, TIMOR, AND LOMBOK (2015)

如果你没有认出上面的图片,这是意料之中的,因为这张图片大多只能在生物杂志或教科书中找到。我上面的是一个物种进化树,这是一个物种共享的历史生物树,目的是看它们彼此之间有多接近。更一般地说,如果你熟悉层次聚类,它基本上就是这样。准确地说,我上面所说的是自下而上的聚集聚类方法来创建一棵被称为邻居加入的系统发育树。

准备好通过 365 Data Science 上的折扣价向所有专家学习数据科学吧!

[## 为数据科学夏季做好准备- 65%折扣| 365 数据科学

选择一条职业道路,掌握你想要的特定工作角色的技能——数据科学家、数据分析师或商业…

365datascience.pxf.io](https://365datascience.pxf.io/c/3452806/1037878/11148)

凝聚聚类

介绍

在机器学习中,无监督学习是一种在没有任何指导或标签的情况下推断数据模式的机器学习模型。无监督学习家族中包括许多模型,但我最喜欢的模型之一是凝聚聚类。

凝聚聚类或自下而上聚类本质上是从一个个体聚类(每个数据点被视为一个个体聚类,也称为)开始,然后每个聚类计算它们彼此之间的距离。彼此距离最短的两个集群将合并,创建我们所谓的节点。新形成的集群再次计算其集群成员与该集群之外的另一个集群的距离。重复该过程,直到所有数据点都被分配到一个称为的簇。结果是一个名为树状图的基于树的对象表示。

提醒一下,虽然我们看到了数据应该如何聚类的结果;聚集聚类并没有给出我们的数据应该如何被聚类的确切数字。应该由我们来决定分界点在哪里。

Dendrogram as the output of the Agglomerative Clustering

让我们试着更详细地分解每一步。为了简单起见,我将只使用最常见的参数来解释凝聚星团是如何工作的。

距离测量

我们通过测量数据点之间的距离来开始凝聚聚类过程。具体是怎么算出来的?我举一个哑数据的例子。

#creating dummy data
import pandas as pd
dummy = pd.DataFrame([[30,100,5],
              [18, 200, 2],
              [35, 150, 7],
             [48, 300, 4],
             [50, 200, 6]], index = ['Anne', 'Ben', 'Chad', 'Dave', 'Eric'], columns =['Age', 'Expense($)', 'Distance(KM)'])

Dummy data of 5 peoples with 3 dimensions

假设我们有 5 个不同的人,他们有 3 个不同的连续特征,我们想看看如何对这些人进行聚类。首先,我们需要决定我们的聚类距离度量。

最常用的距离测量方法之一叫做 欧几里德距离

Euclidean distance calculation

用一个简单的术语来说,欧几里得距离是从 x 点到 y 点的直线。我将通过我们的虚拟数据中 Anne 和 Ben 之间的距离来举例说明。

在虚拟数据中,我们有 3 个特征(或尺寸)代表 3 个不同的连续特征。在这种情况下,我们可以使用下面的公式计算安妮和本之间的欧几里德距离。

如果我们把所有的数字放在一起。

使用欧几里德距离测量,我们获得安妮和本之间的欧几里德距离为 100.76。类似地,将测量应用于所有数据点将产生以下距离矩阵。

import numpy as np
from scipy.spatial import distance_matrix#distance_matrix from scipy.spatial would calculate the distance between data point based on euclidean distance, and I round it to 2 decimalpd.DataFrame(np.round(distance_matrix(dummy.values, dummy.values), 2), index = dummy.index, columns = dummy.index)

Euclidean distance matrix of the dummy data

之后,我们合并矩阵中最小的非零距离来创建我们的第一个节点。在这种情况下,是本和埃里克。

Merging event between two data point to create a node

对于新的节点或集群,我们需要更新我们的距离矩阵。

现在我们有了 Ben 和 Eric 的新聚类,但是我们仍然不知道(Ben,Eric)聚类到其他数据点之间的距离。我们如何计算新的聚类距离呢?为此,我们需要首先设置链接标准。

连锁标准

链接标准是精确测量距离的地方。这是我们建立的一个规则,用来定义集群之间的距离。

有许多联动标准,但这次我只使用最简单的联动,称为 单联动 。它是如何工作的?我会在下面的图片中展示它。

Representation of Single linkage criterion

在单一连锁标准中,我们将我们的距离定义为聚类数据点之间的最小距离。如果我们把它放在一个数学公式里,它会是这样的。

其中聚类 X 到聚类 Y 之间的距离由分别是 X 和 Y 聚类成员的 X 和 Y 之间的最小距离定义。

让我们举一个例子。如果我们将单一连锁标准应用于我们的虚拟数据,比如 Anne 和 cluster (Ben,Eric)之间的数据,它将被描述为下图所示。

在单一连锁标准下,我们得到 Anne 到 cluster (Ben,Eric)之间的欧氏距离为 100.76。将单一连锁标准应用于我们的虚拟数据将产生以下距离矩阵。

Updated distance matrix

现在,我们有了新聚类到另一个数据点之间的距离。虽然如果你注意到,安妮和乍得之间的距离现在是最小的。在这种情况下,下一个合并事件将发生在 Anne 和 Chad 之间。

我们保持合并事件发生,直到所有的数据都聚集到一个集群中。最后,我们将获得一个树状图,其中所有数据都被合并到一个集群中。

#importing linkage and denrogram from scipyfrom scipy.cluster.hierarchy import linkage, dendrogram
import matplotlib.pyplot as plt#creating dendrogram based on the dummy data with single linkage criterionden = dendrogram(linkage(dummy, method='single'), 
labels = dummy.index)
plt.ylabel('Euclidean Distance', fontsize = 14)
plt.title('Dendrogram of the Dummy Data')
plt.show()

Final Dendrogram of the Agglomerative Clustering

确定聚类的数量

我们已经得到了树状图,那么我们该怎么处理它呢?我们将使用它来为我们的数据选择一些集群。记住,树状图只向我们展示了数据的层次结构;它并没有准确地给出最佳的集群数量。

确定聚类数的最好方法是目测我们的树状图,并选择某个值作为我们的分界点(手动方式)。通常,我们选择切割最高垂直线的分界点。我会用下面的图片展示一个例子。

Dendrogram with a cut-off point at 60

水平线与垂直线相交的次数将产生该组的数目。

选择 60 的截止点将给出两个不同的聚类(Dave 和(Ben,Eric,Anne,Chad))。选择不同的分界点也会给我们不同的集群数量。例如,如果我们将截止点移到 52。

Dendrogram with a cut-off value at 52

这一次,以 52 为截止点,我们将得到 3 个不同的集群(Dave,(Ben,Eric)和(Anne,Chad))。

最后,我们决定哪个聚类数对我们的数据有意义。在这种情况下,拥有数据的领域知识肯定会有所帮助。

当然,我们可以通过特定的方法自动找到集群的最佳数目;但是我相信确定聚类数的最好方法是通过观察聚类方法产生的结果。

凝聚聚类模型

假设我会选择值 52 作为我的分界点。这意味着我最终会有 3 个集群。有了这些知识,我们可以将它实现为一个机器学习模型。

from sklearn.cluster import AgglomerativeClusteringaglo = AgglomerativeClustering(n_clusters=3, affinity='euclidean', linkage='single')
aglo.fit_predict(dummy)

凝聚聚类模型将产生[0,2,0,1,2]作为聚类结果。然后,我们可以将聚类结果返回给虚拟数据。在我的例子中,我将其命名为“Aglo-label”。

dummy['Aglo-label'] = aglo.fit_predict(dummy)

Clustered data via Agglomerative Clustering

现在,我的数据已经被聚类,并准备进一步分析。有必要分析结果,因为无监督学习仅推断数据模式,但它产生何种模式需要更深入的分析。

结论

凝聚聚类是层次聚类家族中的一员,它通过合并每个单独的聚类进行工作,这一过程一直重复,直到所有数据都成为一个聚类。

聚集聚类采取步骤是:

  1. 每个数据点被指定为单个聚类
  2. 确定距离测量值并计算距离矩阵
  3. 确定合并集群的链接标准
  4. 更新距离矩阵
  5. 重复该过程,直到每个数据点成为一个聚类

用一个树状图,然后我们选择我们的截止值来获得该类的数目。

最后,凝聚聚类是一种无监督的学习方法,目的是从我们的数据中学习。如何解释聚类结果仍然取决于我们。

我在这里提供笔记本的 GitHub 链接作为进一步参考。

访问我的 社交媒体!

如果您没有订阅为中等会员,请考虑通过我的推荐订阅。

分解有效 Git 工作流的基础

原文:https://towardsdatascience.com/breaking-down-the-basics-of-an-effective-git-workflow-a94c53c3fa99?source=collection_archive---------19-----------------------

作为一名初露头角的数据科学家,我们学到的第一件事就是如何使用而不破坏 Git。我们课程中的所有内容都是通过 GitHub Enterprise repository 提供给我们的,因此能够使用 Git repositories 并将其克隆到我们自己的机器上是一项非常重要的技能。我们将负责根据当地教师对课程的需求来更新他的作品库,并维护一个提交作品和项目的运行库。不用说,精通 Git 中的基本命令对我们来说是成败的关键。

然而,在项目进行七周后,我们开始了我们的第一个真正的团队项目,而我,这个受虐狂,想要确保我的团队制定出一个集中的 Git 存储库,以真正掌握真正的 Git 工作流是什么感觉。虽然我们熟悉 Git,但我想探索一下对于我的三人小组来说,一个易于使用但有效的 Git 工作流的元素是什么样的。这并不是详尽的指南,而是如何让 Git 和 GitHub 为较小的团队工作的基本参考。

所以,我们来分解一下步骤。在我的假想团队“Nate”和“David”中,我们决定为即将到来的项目创建一个新的神经网络模型。为了创建这个特性,我们需要在分支中工作。分支允许我们的团队在这个项目的几个方面工作,而不会潜在地覆盖团队成员的个人工作。

The simple Git workflow in our group, visualized.

合并

因此,对于 Nate 来说,创建一个特性分支并将其合并回分支,他需要遵循以下步骤。

1.从远程库原点拉最新的分支

$ git pull origin master

2.创建特征分支神经网络

$ git checkout -b neural-net

3.Nate 正在开发他的功能,注意其他团队成员可能正在开发的文件的变化。他添加要登台的文件,提交更改,并将它们推送到远程存储库。

# add all files in local repository directory, or add files individually
$ git add .# commit files to the HEAD of "neural-net"
$ git commit -m "a short but descriptive commit message"# push commits to remote repository "origin"
$ git push origin neural-net

4.我们现在准备好让神经网络跟上主设备的速度。在 Nate 从他的远程神经网络分支中取出最新的提交之后,他从远程存储库中取出 master 以确保对 master 的更改反映在他的合并中

$ git pull origin neural-net
$ git checkout neural-net
$ git pull origin master

在这里,内特仍然在分支神经网络中,但是从分支中提取变化。

5.内特将神经网络合并到主机。他必须首先从远程存储库中检出主分支。他可能不得不再次拉出主机,这取决于他的本地主机在提交历史中的位置。

$ git checkout master
$ git pull origin master
$ git merge neural-net
$ git branch -d neural-net

这将提交历史保存在神经网络中。冲突可能会发生,但是只要团队意识到他们所做的改变,这些冲突就可以被最小化。在这个序列中,内特还在“分支”命令中添加了“-d”标记,以删除神经网络分支,因为他已经完成了他的特性的实现。

重置基础

将主分支“重新基准化”到特征分支上也是为了将分支合并在一起,并保留提交历史。Nate 不会合并,而是将提交给 master 的神经网络分支重新定基。

“Rebasing”从分支引入新的提交,如果有提交还不在特性分支中,将其添加到特性分支,并将来自特性的提交添加到主分支之上。在本例中,Nate 的提交将是 HEAD 中的最新提交,但也将包含来自 master 的任何更改。例如,下面是 rebase 方法的一种更详细的工作方式:

# Create a new branch off of master
$ git checkout master
$ git pull
$ git checkout -b neural-net
$ git push neural-net# Add some commits
$ git commit -a -m "descriptive yet short commit message"
$ git commit -a -m "another descriptive yet short commit message"
$ git push neural-net# Get the latest changes off of master and rebase neural-net
$ git checkout master
$ git pull
$ git checkout neural-net
$ git rebase master
$ git push -f neural-net

从这里开始,神经网络现在将与同步。

内特完成了他的神经网络特征。在团队的同意下,Nate 会:

$ git checkout master
$ git pull
$ git checkout neural-net
$ git rebase master
$ git push -f neural-net
$ git checkout master
$ git merge --no-ff neural-net
$ git push master

最后,内特的特征现在将成为分支的一部分。

这简单吗?假设,是的,它与我们班上熟悉的 Git 工作流相对相似,任何熟悉 Git 的人都可以为他们工作。然而,正如人类做的许多事情一样,事情发生,而使用 Git,这些事情被称为“合并冲突”。

合并冲突

所以,让我们假设在上面的一个 merge 中,Nate 检查他的存储库的状态,Git 向 Nate 抛出这个消息:

$ git status 
# On branch contact-form 
# You have unmerged paths. 
#     (fix conflicts and run “git commit”) 
# 
# Unmerged paths: 
#     (use “git add <file>…” to mark resolution) 
# 
# both modified: stocks.html 
no changes added to commit (use “git add” and/or “git commit -a”)

Git 不喜欢 Nate 版本的“stocks.html”与当前的提交历史不同。最有可能的原因是 David 可能已经更改了“stocks.html”的内容,将这些更改提交给了 master、,而 Nate 在尝试合并其功能之前无法从 master 获得最新的提交。

好消息是这个问题可以解决。Git 很好地标记了文件中“stocks.html”中的问题区域,方法是将它包含在一个如下所示的标记中:

“<<<<<<< HEAD” and “>>>>>>> [other/branch/name]"

“HEAD”是对当前检出分支中最后一次提交的引用。你可以把“头”想象成“当前分支”。“stocks.html”中的合并冲突示例可能如下所示:

<<<<<<< HEAD or neural-netNate's list of stocks=======David's list of securities>>>>>>> masterA LIST OF STOCKS

Git 概述了哪些行不同步,并相信用户可以手动解决这些问题:

Nate's list of stocksA LIST OF STOCKS

这确保了神经网络拥有相同版本的 stocks.html

然后,Nate 会将这些更改提交给主模块

$ git add stocks.html
$ git commit -m "Merged master fixed conflict."

注意:并非所有的文件类型或编辑器都会标记这些冲突,但是 Git 在描述终端中的合并冲突时总是会突出显示冲突存在的位置。然而,Git 有一个内置的 GUI,它可以引导您处理冲突,并允许合并冲突的相对简单的集成。

打破彩票假说

原文:https://towardsdatascience.com/breaking-down-the-lottery-ticket-hypothesis-ca1c053b3e58?source=collection_archive---------13-----------------------

从麻省理工学院 CSAIL 有趣的论文中提炼思想:“彩票假说:寻找稀疏、可训练的神经网络”。

我最近读过的最有趣的论文之一是“彩票假说:寻找稀疏的、可训练的神经网络”(https://arxiv.org/abs/1803.03635)。我已经将内容浓缩成一篇简短的博文,这可能会帮助你快速理解文章中的观点。

动机

神经网络的剪枝技术可以将训练网络的参数数量减少 90%以上,而不会影响精度。具有较少参数的网络降低了存储需求,并且可以花费较少的时间来执行推断。

Simplified example of pruning a trained network. Removing a parameter is equivalent to removing a connection between neurons.

听起来不错,给我报名吧!但是训练大型网络可能非常昂贵。如果我们可以训练一个与修剪后的网络具有相同拓扑(形状)的网络,这不是很好吗?不幸的是,用修剪过的网络的拓扑来训练网络产生的网络比原始的未修剪过的网络具有更低的精度。

Simplified example of pruning a trained network (above). Simplified example of training a network with the topology of the pruned network using a new random weight initialization (below)

这篇论文的作者想问为什么用修剪过的网络拓扑来训练网络会产生更差的性能。

彩票假说

“一个随机初始化的密集神经网络包含一个子网络,该子网络被初始化,以便在隔离训练时,它可以在最多相同次数的迭代训练后匹配原始网络的测试精度。”

他们发现,通过保留来自未修剪网络的原始权重初始化,可以用修剪后的网络拓扑来训练网络,并在相同次数的训练迭代内实现相同或更好的测试精度。

Simplified example of pruning a trained network (above). Simplified example of training a network with the topology of the pruned network using the original weight initialization from(below)

彩票类比

好吧,看起来很简单。但是彩票是怎么回事呢?假设你的目标是找到一张中奖彩票。如果你买了一张票,赢得钱的机会很小。但是如果你买了一百万张票,很可能你的一些票会赢得一些钱(虽然这可能不盈利)。

在这个类比中,购买大量门票就像为您的任务设置了一个过度参数化的神经网络。神经网络通常有超过一百万个参数!彩票中奖就相当于训练了一个神经网络,对你的任务有很高的准确率。最后,获胜的标签指的是达到高精度的修剪子网的权重初始化。

识别中奖彩票

本文提出了两种剪枝策略,可以找到获胜的票(达到高精度的子网)。

一次性修剪

  1. 随机初始化神经网络
  2. 训练网络
  3. 将每个层中具有最低幅度的权重的 p%设置为 0(这是修剪)
  4. 将修剪后的网络权重重置为其原始随机初始化

应该注意到,到输出神经元的连接以正常修剪速率的一半被修剪。

迭代剪枝

迭代修剪只是迭代地应用一次性修剪的步骤。作者发现迭代修剪比一次性修剪产生更小的修剪子网络。

结果

迭代修剪策略被应用于全连接架构、卷积架构和具有剩余连接的卷积架构(ResNet)。作者在 MNIST 和 CIFAR-10 图像分类数据集上研究了迭代剪枝技术。他们的修剪策略也适用于不同的优化器(SGD、momentum、Adam)、dropout、weight decay、batchnorm 和 residual connections。

修剪后的子网络比原来的小 10-20 %,并且在最多相同的迭代次数下达到或超过了原来的测试精度。这些结果支持彩票假说。修剪后的子网络也具有更好的泛化能力,因为训练和测试精度之间的差异更小。

讨论

为什么网络会收敛到使用其总参数的一小部分来解决一个任务?“获胜”的初始化已经接近完全训练的值了吗?没有。实际上,在训练过程中,它们比其他参数变化更大!作者推测,获胜的初始化可能落在损失景观中特别适合优化的
区域。他们提出了“彩票猜想”,即随机梯度下降在超参数化网络中寻找并训练一张中奖彩票(子网)。

限制

这篇论文展示了有趣的结果,这些结果有助于更好地理解深度神经网络是如何学习的。不幸的是,他们提出的迭代修剪策略没有提供显著的实际好处。

迭代修剪在计算上是昂贵的,因为它涉及每次尝试训练网络 15 次。这使得作者很难研究像 ImageNet 这样的大型数据集。作为未来的工作,作者希望找到更有效的剪枝策略。

通过将参数数量减少 80–90 %,降低了网络的存储需求。权重矩阵仍然具有相同的维数,但是更加稀疏。用于修剪后的子网络的前馈步骤仍然需要以相同的计算复杂度计算矩阵乘法,因此训练和推断并没有明显更有效。作为未来的工作,他们建议基于非数量级的剪枝策略可以找到更小的剪枝子网。

感谢阅读!

2019 年闯入数据科学

原文:https://towardsdatascience.com/breaking-into-data-science-in-2019-889111e5c34f?source=collection_archive---------6-----------------------

我从商业到数据科学之旅的感悟

https://unsplash.com/photos/rk_Zz3b7G2Y

介绍

我记得当时想闯入数据科学领域,就好像是在昨天一样。我刚刚在上海开始了我的海外学期,参加了几场关于数据科学和机器学习的讲座和客座演讲。然而,我以前从未编写过代码(除了一些基本的 SQL),不知道从哪里开始。最初的网络搜索导致了更多的困惑,而不是洞察力,因为许多人推荐了许多不同的数据科学途径。有些人甚至认为,没有博士学位就不可能成为数据科学家。

这篇文章采用了不同的方法。我不打算尝试提供一条通向数据科学的万能之路。相反,我将详述我尝试进入数据科学的经历,我希望这对有抱负的数据科学家可能有用。

第 1 部分:学习如何编码

在尝试做其他事情之前,我开始学习如何编码。因为我认为一些指导会有所帮助,所以我决定参加纽约市数据科学院为期 12 周的数据科学训练营。该计划包括一个处理 Python、R 和 SQL 的在线准备课程,必须在实际参加训练营之前完成。

码,码,码

事后看来,我希望我把更多的注意力放在练习编码上,而不是试图学习一门编程语言。我后来意识到,编程是一项主要通过不断重复练习获得的技能。我后来自己发现并研究了一些很棒的书籍,其中包括针对 Python 的“艰难地学习 Python”和针对 R 的“ R for Data Science ”。因为我以前已经使用过 SQL,所以我只需要回顾一下主要的命令。如果你想要一个更完整的 SQL 指南,我推荐你开始学习模式分析的 SQL 课程

在学习编码的过程中,你会遇到很多很多问题。继续走。克服这些错误并检查你的错误在以后会非常有价值。当我在 Jupyter 笔记本上练习 Python 时,我总是记录我所有的错误,这样我就能在以后回顾它们。这导致了一个个性化的代码片段库和有趣的发现,直到今天我还在依赖它。

Python 还是 R?

有许多因素会影响一个人在 Python 和 r 之间的选择。我是否希望能够方便地使用各种工具来进行数据的统计分析?那么 R 大概就是要走的路。我是否想学习一种更通用的语言,可以应用于数据分析之外的许多事情?在这种情况下,Python 可能是您的首选。然而,根据我的经验,选择一个并开始编码才是最重要的。找出你喜欢的语言,不要只依赖第三方的建议。

如果你想变得非常多才多艺,我建议你找到一个最喜欢的,但也能使用另一个。对我来说幸运的是,纽约数据科学学院用 R 和 Python 两种语言教授全部课程。我个人更喜欢使用 Python 进行机器学习,但同时也喜欢使用 tidyverse 进行 R 中的数据分析,tidy verse 是一个为数据科学设计的 R 包集合。

第二部分:复习统计数据

作为一名商科专业的学生,我在大学里除了学习一些经济和金融课程外,还学习了基础统计学课程。因此,深入研究统计数据并不意味着面对我从未见过的东西,但事实证明这仍然是一个相当大的挑战。在我看来,特别是在 2019 年,只知道如何使用机器学习包,如 scikit-learn,既不足以有效地实践数据科学,也不足以让你在数据科学领域找到工作。

记录你的进步

为了以一种集中的方式组织我需要知道的一切,我开始为每个主题创建带有摘要的 Word 文档。网上有一些所谓的“小抄”,但是,我通常发现它们缺乏深度。此外,正如我在本文开头所强调的,对于任何与数据科学有关的事情,都没有通用的解决方案。所以,建立自己定制的数据科学查找库是一个好习惯。

我在训练营听课的时候记笔记,晚上提炼和复习。虽然这需要付出很多努力,但随着讲座的进行,它极大地促进了对越来越复杂的算法的理解。

掌握基本面

关于这个话题的最后一点:在任何情况下,都不要跳过基础知识。虽然尝试跳到花哨的算法一开始看起来很诱人,但在我看来,将大部分时间花在基础上是更好的选择。除了讲座,我还看了几本关于统计学和统计学习的书。在我看来,关于统计学习最好的书是 Daniela Witten,Robert Tibshirani 和 Trevor Hastie 的《统计学习导论:R 语言应用》。不同的书采取不同的方法。因此,将侧重于算法的口头解释的书籍与深入技术细节的书籍结合起来,证明是对我时间的一项不错的投资。我也对互联网上流传的所有流行词汇感兴趣,但最终发现,在考虑向您的数据科学技能集添加新功能之前,您首先必须建立非常坚实的基础。

多问问题

如果你碰巧像我一样参加了一个新兵训练营,利用你的教练。尽可能多问问题。不要等到遇到严重的问题才开始提问。甚至向更有经验的人展示您的代码,并寻求提高其效率的方法,都可能被证明是极其有用的。

万一你不能得到专业的帮助,不要绝望。有很多在线社区和资源可以帮助你回答你的问题。很可能,你不是第一个遇到这个问题的人。最重要的是,自己想出解决方案会帮助你更容易记住它。

其他要温习的东西

根据你的背景,复习基本的线性代数和微积分可能也是一个好主意。我会建议你或者翻翻旧的线性代数或微积分笔记,或者参加在线课程,比如麻省理工学院免费开放的线性代数课程。如果你有兴趣阅读学术论文和更多的技术书籍,这一点尤为重要。

第 3 部分:构建项目组合

完成至少四个项目

如果你想在数据科学领域找到一份工作,这第三步至关重要。为了让你的潜在雇主相信他们应该雇用你,并应用你到目前为止学到的东西,试着完成至少四个主要项目。

如果你像我一样,参加纽约市数据科学学院训练营,那么你必须完成三个项目,涵盖数据科学生命周期的所有方面。这些项目将涵盖从数据可视化的数据采集到机器学习的所有内容。最后,顶点计划允许你选择任何你想做的主题。你应该利用这个机会在就业市场上为自己定位,瞄准你梦想中的雇主。例如,如果你的目标是将数据科学应用于医疗保健数据,那么试着找到一个解决该领域问题的项目,例如预测糖尿病的发病。

不要止步于此

如果你真的想打入一个特定的行业,就不要止步于四个项目。搜索可能与你的理想雇主相关的数据,并进行实验。建立一些有趣的东西,写一篇关于你的项目的文章或博客。你在某个特定领域展示自己的能力和兴趣越多,这个行业的人就越有可能对你印象深刻。

不要太花哨

在选择项目时,选择听起来新奇的东西是很有诱惑力的。不要那样做。至少不是马上。确保你的项目从开始到结束都是可靠的,并且包含尽可能少的错误。让别人检查你的项目并为你审阅。在训练营期间,我向我的同学和导师展示了我所有的项目。获得对你工作的不同意见将有助于你改进未来的项目。

第四部分:努力找工作

准备是关键

如果你想在数据科学招聘过程中取得成功,尽可能地做好准备。在 HackerRank 上查看编码挑战,熟悉被问到的问题类型,也许最重要的是,记录你的面试过程。与机器学习理论一样,你应该创建一个文档,在其中描述和评估你在面试时的经历。

然后,在每次面试之前,将该文档与您的机器学习理论文档一起查看,并确保您避免重复错误。在开始编码挑战之前,通过在 HackerRank 上完成一些任务来热身也可能是有帮助的。

学习如何推销自己

如果你想要一份数据科学方面的工作,你将不得不与许多其他申请人竞争。通过创造你的个性化叙事让自己与众不同。为什么你是最佳人选?你为什么选择这些具体的项目?为什么首先选择数据科学?因为你将不得不在几乎每一次面试中介绍自己,所以确保你精心准备了一个强有力的叙述,可以根据你的目标公司进行调整。

当你在做的时候,也要为你的项目准备推介。不是每个潜在雇主都想听你描述你所有的项目。也许某个特定的项目引起了将要面试你的人的注意。确保你能够深入描述每个项目,但也有一个后备的推介,以防你只需要对你的项目做一个简短的描述。

在其他人面前练习这些技巧。想想你在家里可能会说什么,比不上站在你不认识的人面前试图解释你的项目。如果你去上学或参加新兵训练营,和你的同学一起练习推销自己,并给彼此建设性的反馈。这样做,你也许能在第一次面试前避免几个错误。

网络

在完成纽约数据科学学院的训练营后,所有毕业生都被鼓励参加一个招聘伙伴活动,在这个活动中你可能会找到你未来的雇主。在参加这类活动之前,学会如何推销自己和你的项目是绝对重要的。参加这类活动时要有闯劲。调查将要参加活动的招聘经理和招聘人员。在活动期间,尽可能快地找出你和公司之间是否有合适的人选。递简历,要名片。另一个非常重要的建议是:不要只和一两个人说话。即使有可能非常适合,也不要把自己限制在潜在工作机会的数量上。在一定时间的互相了解和交换联系方式后继续前进。

社交是一项需要练习的技能。对我来说幸运的是,训练营为学生们提供了大量关于如何驾驭社交活动的建议和技巧。确保了解社交中的行为准则(例如,给每位出席的招聘经理写一封好的跟进邮件)。

然而,与项目一样,不要止步于此。与你周围的人建立关系网。数据科学是一个迷人的领域,有许多迷人的人。如果你在学校或训练营,和你的同学联系。在 LinkedIn 上寻找有趣的人。参加你所在城市的数据科学会议。有很多建立关系网的机会,你做得越多,你就会做得越好。

不要放弃

找工作可能很难。你可能会参加许多面试,只是为了让人们告诉你他们不会雇用你。除非你运气好,能马上找到工作,否则找工作可能会是一个非常令人沮丧的过程。不要绝望。如果你坚持不懈,不断完善自己和简历,最终会有人注意到的。坚持相信你会得到你想要的工作机会。与之前经历过数据科学招聘过程的人交谈,你会发现他们中的许多人都经历过许多令人沮丧的面试。那些成功的人和那些失败的人之间的区别,归根结底,与坚持斗争和不屈服的能力有很大关系。

结论

2019 年成为一名数据科学家并不容易。你将不得不跨越许多障碍,克服许多挑战。然而,通过这一过程的回报是巨大的。你不仅可以做你喜欢做的事情,还可以和来自各种不同背景的聪明人打交道。只要迈出第一步,其余的就会跟上。开始追随你的激情。如果你花的时间比别人长,那没关系,重要的是你的意志力。确保你每天都在稳步提高,最终会让你到达你想去的地方。

打破我的小马:破解密码的频率分析

原文:https://towardsdatascience.com/breaking-my-little-pony-frequency-analysis-for-breaking-ciphers-68facd7e528f?source=collection_archive---------11-----------------------

在第一次成为父母之前,我花了很多时间思考我的生活将要发生的各种变化。我没有预料到的一个变化是我将会用多少代码来说话。你的孩子总是在倾听和学习,所以用不了多久,你和你的另一半就会停止在他们面前发送未加密的信息。就在今天早上,当我和妻子在我们三岁的女儿面前聊天时,我们在某个特定的上下文中将“玩具”称为“分心机制”。

我的女儿还没有足够的理解力来破解我们的小代码(尽管它即将到来),但它确实让我开始思考密码和代码,于是一个博客诞生了。作为一门新兴的数据科学,我认为您可以使用某种统计分析来破解简单的代码,果然您可以!在这篇博客中,我们将讨论频率分析以及如何破解一个简单的密码。

密码和代码

首先,让我们澄清一些术语。大多数人对什么是“密码”和“代码”有一个大致的概念,但是定义一些术语是值得的。

密码和代码都是加密信息的一系列步骤。它们将明文信息转换成只能用一些辅助来源解密的信息。在密码的情况下,它通常是一个密钥,在代码的情况下,它通常是一个密码本。大多数人可以互换使用这两个术语,但还是有区别的。用密码加密的文本通常会与原始文本的字符数相同。代码通常使用一串字符或数字来表示单词或短语。

我上面的例子是一个代码,因为我用一个单词代替了一个短语。如果我们要对“玩具”这个词进行加密,我们可以改为“座位”(t=s,o=e,y=a,s=t)。

简单替代密码

我们要看的密码是简单的替代密码。简单的替代密码只是将字母表中的每个明文字母作为字母表中的另一个字母进行加密。这是一对一的替换,所以密文中的一个给定字母总是等同于明文中的同一个字母。这里有一个使用 PyCipher 库的例子:

密码使用密钥来加密数据。对于简单的替换,我们使用一个密码字母。你可以看到替换是如何工作的。每一个明文‘a’都变成了密文‘w’,每一个‘b’都变成了‘h’,以此类推……所以我们的明文‘密码’就变成了‘xwytdkl’。请注意,按照惯例,当使用简单替换进行加密时,您将返回去掉标点符号和全部大写的密文,原因很明显,您使其更难被破解。

频率分布

有很多可能的密码密钥(26!实际上)所以理论上简单的替代密码很难破解。即使抛开现代计算能力,如果你知道原始语言和一点频率分布,手动破译 100 或更多字符的信息实际上是非常可行的。

大多数语言都有一定的特点。一些字母和一些字母序列比其他字母出现得更频繁。在普通的英语文本中(比如说,超过 100 个字符),' e '通常出现的频率最高,其次是' t '和' a '。字母“x”、“q”和“z”出现得最少。

https://en.wikipedia.org/wiki/Letter_frequency

知道了这一点,并且知道给定的密文将总是替换其对应的明文,您就可以开始有根据地猜测哪些密文字母对应于哪些明文字母。

我的小马驹密码

为了开始做一些频率分析并说明更多的概念,我从我的小马:友谊是魔法 wiki 的一篇随机文章中抓取(并稍微修改)了以下文本:

NWVKIF UWVYC TWY AFYXAKIL CD QKIWCI UNVCCIKYEP HP EIK QEANLEDDL CDP IWKCE XDFP XDYIP. UNVCCIKYEP'Y AFACAWN LIYAMF, XVHNAYEIL DFNAFI HP UWVYC, KIUIKY CD EIK WY 'XDYIP' WY TINN. EIK QVCAI OWKG, CEKII XAFG WFL QPWF HVCCIKUNAIY, AY YAOANWK CD CEWC DU CEI XDFP YGP YGAOOIK.

如上所述,您不太可能得到标点和空格都完好无损的密文,但是我这样做是为了说明一些概念。首先我们可以算出每个密文字母的频率:

正如我们所看到的,看起来“I”、“C”和“Y”是出现频率最高的字母。让我们假设‘I’密码等价于明文中的‘e ’,并进行替换(替换用小写字符表示)。

NWVKeF UWVYC TWY AFYXAKeL CD QKIWCe UNVCCeKYEP HP EeK QEANLEDDL CDP eWKCE XDFP XDYeP. UNVCCeKYEP'Y AFACAWN LeYAMF, XVHNAYEeL DFNAFe HP UWVYC, KeUeKY CD EeK WY 'XDYeP' WY TeNN. EeK QVCAe OWKG, CEKee XAFG WFL QPWF HVCCeKUNAeY, AY YAOANWK CD CEWC DU CEe XDFP YGP YGAOOeK.

好不了多少,但我们还有一些锦囊妙计。例如,我们知道最常见的两个、三个和四个字母的单词。

http://www.practicalcryptography.com/ciphers/simple-substitution-cipher/

我们这里有几个两个字母的单词要试一下。因为我们知道第二个最频繁出现的密文字符是“C”,让我们试着用“t”来代替它,它是英语中第二个最频繁出现的字符。我们有几个以“C”开头的两个字母的单词,以“t”开头的最常见的两个字母的单词是“to”,所以我们也假设密文“D”等于明文“o”。

NWVKeF UWVYt TWY AFYXAKeL to QKeWte UNVtteKYEP HP EeK QEANLEooL toP eWKtE XoFP XoYeP. UNVtteKYEP'Y AFAtAWN LeYAMF, XVHNAYEeL oFNAFe HP UWVYt, KeUeKY to EeK WY 'XoYeP' WY TeNN. EeK QVtAe OWKG, tEKee XAFG WFL QPWF HVtteKUNAeY, AY YAOANWK to tEWt oU tEe XoFP YGP YGAOOeK.

现在事情开始明朗了。我们现在正文里有' tEe '和' tEKee ',可以猜测密文' E '是明文' h ',密文' K '是明文' r '。我还没有解决这个问题,但是很明显,由于撇号的作用,Y 是 s。同样,如果“K”是“r”,“E”是“h ”,那么“eWKtE”就变成了“eWrth ”,所以“W”很可能是“a ”:

NaVreF UaVst Tas AFYXAreL to Qreate UNVttershP HP her QhANLhooL toP earth XoFP XoseP. UNVttershP's AFAtAaN LesAMF, XVHNAsheL oFNAFe HP UaVst, reUers to her as 'XoseP' as TeNN. her QVtAe OaKG, three XAFG aFL QPaF HVtterUNAes, As sAOANar to that oU the XoFP sGP sGAOOer.

等等,等等。最终我们得到了我们的信息:

lauren faust was inspired to create fluttershy by her childhood toy earth pony posey. fluttershy's initial design, published online by faust, refers to her as 'posey' as well. her cutie mark, three pink and cyan butterflies, is similar to that of the pony sky skimmer.

那怎么样?我不知道小蝶是这样的!

当然,在这种情况下,我们也有标点符号和间距的线索。显然,没有这些线索就很难破译一个文本,但是你仍然可以使用频率分析,你可以开始查看字符的的频率。

一般来说,密码学家会将文本分解成二元模型、三元模型或四元模型(分别为两个、三个和四个字符组)。这些组也有频率分布。四元图“TION”出现得非常频繁,但是“QKPC”从来没有出现过。

为了编程求解,密码学家将从尝试随机密钥来解密文本开始。然后,他们将文本分割成四元组,并乘以每个四元组可能是英语中的四个字符块的概率(或适合度),然后用稍微改变的键再试一次。因为概率非常小,而且它们可能是在大样本上计算的,所以您可以使用对数变换来防止算术下溢(算术下溢是一种计算结果,其绝对值小于计算机在其 CPU 上的内存中实际可以表示的值)。下面是一个公式示例:

这里有一个简单的换元题自己试试!我把标点符号留在了这里,如果你是手写的话,这样会更快更容易。玩得开心!

EIP. YD, CEI QDNDFIN TWY RVYC EIKI WFL EI CDNL OI CD CINN PDV CEWC CEI QDHKW YCKAGIY WC LWTF. NIC OI CINN PDV- EI TWY SIKP QDFLIYQIFLAFM. ISIKPCAOI CEI MIFIKWN AY WTWP EI MDIY WNN IN EIUI YVXKIOD DF OI. CVKL.

YXIWGAFM DU CEI MIFIKWN - HICTIIF PDV WFL OI A CEAFG EI'Y HIIF MICCAFM EAY CEAFM DF TACE DFI DU CEDYI QWXDY UKDO CEI OANACWKP XDNAQI. CEI HAM HKVFICCI TACE CEI CTD NWBP IPIY CEWC WKI NWBP AF DXXDYACI LAKIQCADFY. PDV GFDT CEI DFI. TEIFISIK YEI'Y AF CDTF WNN DU W YVLLIF EI EWY XKIYYAFM HVYAFIYY INYITEIKI CD WCCIFL CD WFL NIWSIY QDNDFIN CVKL AF QEWKMI. YEI WNTWPY HKAFMY OI QACKVY TEIF YEI'Y AF CDTF (NDFM YCDKP) YD A NAGI EIK, HVC A EWSI FD ALIW TEWC CEIP YII AF IWQE DCEIK.

WFPTWPY, MDCCW MD. QDHKW YCKAGIY WC LWTF. EWAN CD CEI MNDKADVY KISDNVCADF WFL NDFM NASI DVK LIWK NIWLIK!

用对抗性攻击破坏神经网络

原文:https://towardsdatascience.com/breaking-neural-networks-with-adversarial-attacks-f4290a9a45aa?source=collection_archive---------1-----------------------

我们使用的机器学习模型有内在缺陷吗?

正如你们许多人可能知道的那样,深度神经网络是一种高度表达的机器学习网络,已经存在了几十年。2012 年,随着计算能力的提高和工具的改进,一系列名为 ConvNets 的机器学习模型开始在视觉识别任务上实现最先进的性能。到目前为止,机器学习算法的工作还不够好,当它不能做正确的事情时,任何人都不会感到惊讶。

2014 年,谷歌和 NYU 的一组研究人员发现,在输入中用一种不可思议但精心构建的轻推来欺骗 ConvNets 太容易了。让我们看一个例子。我们从一个熊猫的图像开始,我们的神经网络以 57.7%的置信度正确识别出它是一只“熊猫”。添加一点精心构建的噪声,同一个神经网络现在认为这是一个有 99.3%置信度的长臂猿图像!很明显,这是一种视错觉——但是对于神经网络来说。你和我可以清楚地分辨出两幅图像看起来都像熊猫——事实上,我们甚至不能分辨出一些噪声被添加到原始图像中以构建右侧的对立示例!

Source: Explaining and Harnessing Adversarial Examples, Goodfellow et al, ICLR 2015.

2017 年,另一个小组证明了这些对立的例子可以推广到现实世界,表明当打印出来时,对立构造的图像将在不同的光照和方向下继续欺骗神经网络:

Source: Adversarial Examples in the Physical World. Kurakin et al, ICLR 2017.

另一项有趣的工作,名为“犯罪的附属品:对最先进的面部识别技术的真实和秘密的攻击”表明,人们可以通过构造对抗眼镜来欺骗面部识别软件,从而完全避开面部检测。这种眼镜也可以让你扮演其他人:

Source: Accessorize to a Crime: Real and Stealthy Attacks on State-of-the-Art Face Recognition. Sharif et al.

不久之后,另一个研究小组展示了各种构建停车标志的方法,这些方法可以通过在停车标志上放置各种贴纸来欺骗模型。这种干扰被设计成模仿涂鸦,因此“隐藏在人类的精神中”

The left image shows real graffiti on a Stop sign, something that most humans would not think is suspicious. The right image shows a physical perturbation applied to a Stop sign. The systems classify the sign on the right as a Speed Limit: 45 mph sign! Source: Robust Physical-World Attacks on Deep Learning Visual Classification.

“对抗性补丁”,NIPS 2017 上发表的一篇论文演示了如何生成一个补丁,可以放置在分类器视野内的任何地方,并使分类器输出一个目标类。在下面的视频中,香蕉被正确地归类为香蕉。贴上印有烤面包机的贴纸并不足以愚弄网络,它仍然继续将其归类为香蕉。然而,通过精心构建的“对抗性补丁”,很容易欺骗网络,使其认为这是一台烤面包机:

Source: Adversarial Patch: https://arxiv.org/pdf/1712.09665.pdf

引用作者的话,“这次攻击意义重大,因为攻击者在构建攻击时不需要知道他们攻击的是什么图像。在生成一个对抗性补丁后,该补丁可以在互联网上广泛分发,供其他攻击者打印和使用。”

Source: Adversarial Patch: https://arxiv.org/pdf/1712.09665.pdf

这些例子告诉我们,当我们的神经网络被对手以这种方式明确攻击时,它仍然非常脆弱。让我们潜得更深!

这些攻击有什么了不起的?

首先,正如我们在上面看到的,在对立例子的不正确分类中很容易获得高置信度——回想一下,在我们看到的第一个“熊猫”例子中,网络对看起来像熊猫的实际图像的确定度(57.7%)低于我们右边看起来像长臂猿的对立例子(99.3%)。另一个有趣的点是如何察觉到我们需要添加的小噪音来愚弄系统——毕竟,很明显,添加的噪音不足以愚弄我们人类。

It’s easy to attain high confidence in the incorrect classification of an adversarial example. Source: Explaining and Harnessing Adversarial Examples, Goodfellow et al, ICLR 2015.

第二,对立的例子不太依赖于用于该任务的特定深度神经网络——为一个网络训练的对立例子似乎也会混淆另一个网络。换句话说,多个分类器把同一个(错误的)类别分配给一个对立的例子。这种“可转移性”使攻击者能够在所谓的“黑盒攻击”中欺骗系统,在这种攻击中,他们无法访问模型的架构、参数甚至是用于训练网络的训练数据。

我们有好的防御吗?

不完全是。让我们快速看一下到目前为止已经提出的两类防御:

对抗训练

防御这些攻击的最简单和最暴力的方法之一是假装是攻击者,生成许多针对您自己网络的对抗性示例,然后显式地训练模型不被它们愚弄。这提高了模型的通用性,但还不能提供有意义的健壮性级别——事实上,它最终只是一个打地鼠游戏,攻击者和防御者只是试图胜过对方。

防御性蒸馏

在防御蒸馏中,我们“训练第二个模型,其表面在攻击者通常试图利用的方向上是平滑的,使他们难以发现导致错误分类的敌对输入调整”[6]。其工作的原因是,与第一个模型不同,第二个模型是在主模型的“软”概率输出上训练的,而不是来自真实训练数据的“硬”(0/1)真实标签。这种技术被证明在防御敌对攻击的初始变体方面取得了一些成功,但被最近的攻击击败,如 Carlini-Wagner 攻击,这是当前评估神经网络对抗敌对攻击的鲁棒性的基准。

为什么捍卫神经网络如此困难?

让我们试着对这里发生的事情有一个直觉。大多数时候,机器学习模型工作得很好,但只对它们可能遇到的所有可能输入中的很小一部分起作用。在高维空间中,每个单独输入像素中非常小的扰动就足以引起神经网络中点积的巨大变化。因此,很容易将输入图像推到我们的网络从未见过的高维空间中的一点。这是要记住的关键点:高维空间非常稀疏,以至于我们的大多数训练数据都集中在一个非常小的区域,称为流形。虽然我们的神经网络根据定义是非线性的,但我们用来训练它们的最常见的激活函数,整流器线性单元,或 ReLu,对于大于 0 的输入是线性的。

The Rectifier Linear Unit, or the ReLu compared to the Sigmoid and the Tanh activation functions.

ReLu 因其易于训练而成为首选激活功能。与 sigmoid 或 tanh 激活函数相比,它们在高激活时简单地饱和到上限值,从而使梯度“停留”在非常接近 0 的位置,ReLu 在 0 右侧的任何地方都有非零梯度,使其更加稳定,训练速度更快。但是,这也使得将 ReLu 激活函数推到任意高的值成为可能。

看看这个在可训练性和对抗攻击的鲁棒性之间的权衡,我们可以得出结论,我们一直使用的神经网络模型存在固有缺陷。优化的简易性是以模型容易被误导为代价的。

下一步是什么?

这里真正的问题是,我们的机器学习模型在训练分布之外表现出不可预测和过度自信的行为。对立的例子只是这个更广泛问题的一个子集。我们希望我们的模型在他们从未见过的地区运行时,能够表现出适当的低置信度。我们希望它们在生产中使用时“优雅地失败”。

根据该领域的先驱之一 Ian Goodfellow 的说法,“许多最重要的问题仍然悬而未决,无论是在理论上还是在应用上。我们还不知道防御敌对的例子在理论上是没有希望的努力,还是一个最优策略会给防御者一个优势。在应用方面,还没有人设计出真正强大的防御算法,可以抵御各种各样的对抗性示例攻击算法。”

如果没有别的,对立例子的话题让我们了解了大多数研究人员一段时间以来一直在说的话——尽管有了突破,但我们仍处于机器学习的初级阶段,在这方面还有很长的路要走。机器学习只是另一种工具,容易受到敌对攻击,这可能会在一个我们通过自动驾驶汽车和其他自动化将人类生命托付给它们的世界中产生巨大影响。

参考

这里是上面提到的论文和文章的链接。我也强烈推荐看看 Ian Goodfellow 关于这个话题的博客。

  1. 解释和利用对立的例子,古德菲勒等人,ICLR 2015 年。
  2. 物理世界中的对立例子。库拉金等人,ICLR,2017 年。
  3. 犯罪的附属品:对最先进的人脸识别技术的真实而隐秘的攻击。谢里夫等人。
  4. 对深度学习视觉分类的鲁棒物理世界攻击。艾克霍尔特等人。
  5. 对抗性补丁。布朗等人。
  6. 用对抗性例子攻击机器学习。打开 AI 博客。

打破机器学习中小数据集的魔咒:第 2 部分

原文:https://towardsdatascience.com/breaking-the-curse-of-small-data-sets-in-machine-learning-part-2-894aa45277f4?source=collection_archive---------2-----------------------

现实世界中的 DS

数据大小如何影响深度学习模型,以及如何处理小数据集?

这是打破机器学习中小数据集的诅咒系列的第二部分。在 第一部分 中,我已经讨论了数据集的大小如何影响传统的机器学习算法,以及一些缓解这些问题的方法。在第 2 部分,我将讨论深度学习模型性能如何依赖于数据大小,以及如何使用较小的数据集来获得类似的性能。

PS:感谢 瑞秋托马斯 的反馈

Source: Movie Scene from Pirates of the Caribbean[source]

概述

以下是我将在本文中简要讨论的话题:

  1. 影响神经网络训练的关键因素
  2. 克服优化困难的方法
  3. 解决缺乏普遍性的问题
  4. 结论

1。训练神经网络的关键因素

神经网络是深度学习模型的基本构建模块。然而,深度神经网络有数百万个参数要学习,这意味着我们需要多次迭代才能找到最佳值。如果我们有少量数据,运行大量迭代会导致过度拟合。大型数据集有助于我们避免过度拟合和更好地概括,因为它可以更有效地捕捉固有的数据分布。

以下是影响网络优化过程的几个重要因素:

  1. 优化算法:梯度下降是用于神经网络的最流行的优化算法。算法性能直接取决于训练数据的大小。我们可以尝试用较小的训练集(随机梯度下降是我们用单个数据点进行更新时的极端情况)来更新权重,这使得训练过程快速,但是更新具有较大的波动。用整个数据集进行训练使得训练在计算上昂贵且缓慢。 AdamRMSpropAdagrad随机梯度下降是梯度下降的几种变体,其优化了梯度更新过程并提高了模型性能。查看这个博客详细了解梯度下降的各种版本。除了梯度下降之外,还有其他不同的优化技术,如进化算法(EA)和粒子群优化算法(PSO)可能有巨大的潜力。
  2. 损失函数:损失函数在优化过程中也起着至关重要的作用,精心选择的损失函数有助于改进训练过程。铰链损耗就是这样一个例子,它使得用小数据集进行训练成为可能。
  3. 参数初始化:参数的初始状态对优化过程影响很大。选择不当的初始值会导致发散和陷入鞍点或局部最小值的问题。此外,这增加了训练过程对训练数据的要求。
  4. 数据量:数据量是训练神经网络非常关键的一部分。更大的数据集可以帮助我们更好地学习模型参数,改进优化过程并赋予泛化能力。

如何用小数据集训练

Fig 1: Basic implications of fewer data and possible approaches and techniques to solve it

我们已经在的上一篇文章中讨论了一些上述技术。我们将在这一部分讨论与深度学习更相关的剩余技术。

2.克服优化困难的方法

1。转移学习:

迁移学习是指将从一个任务学到的知识运用到另一个任务中,而不需要从头开始学习。它直接处理用于训练神经网络的智能参数初始化点。这项技术已广泛用于计算机视觉任务,并在深度学习在行业中的广泛应用中发挥了重要作用。现在公认的是,基于 Imagenet 数据训练的 ResNet 等模型的初始层学习识别图像中的边缘和拐角,并且后续层建立在这些特征之上以学习更复杂的结构。最后一层学习将图像分类到 1000 个类别中的一个。对于任何数据看起来类似于 Imagenet 的新问题,我们可以从预训练的 Imagenet 模型开始,更改最终的层,并根据我们的数据集对其进行微调。由于较低层的特征仍然保持相关,该过程使得优化过程更快,并且减少了训练新模型所需的数据量。

感谢 Fast.ai 库,我们可以使用迁移学习建立图像分类模型,只需几行代码和几百张训练图像,仍然可以获得最先进的结果。

最近,同样的方法也成功地应用于自然语言处理。乌尔姆菲特伯特AWD-LSTMGPT2 就是几个可以用于自然语言处理中迁移学习的模型。这些模型被称为语言模型,因为它们试图学习基本的语言结构,并基于之前看到的/上下文单词来预测句子中的下一个单词。这种转移学习的想法听起来非常类似于计算机视觉,但只是在最近几年才得到尝试和完善。查看这个牛逼的博客,更好地理解语言模型。

2。问题简化:

问题减少方法是指将新数据或未知问题修改为已知问题,以便可以使用现有技术轻松解决。假设我们有许多语音剪辑,我们希望根据声音来源将它们分成不同的类别。深度学习的最新进展表明,LSTM 或 GRU 等序列模型确实擅长此类任务。然而,小数据集可能是一个交易破坏者,并且为这种用例找到迁移学习的好模型也是非常困难的。我最近参加了 Fast.ai v3 课程,发现了一个解决这类问题的聪明方法。我们可以使用各种可用的库(如 LibROSA )将语音剪辑转换成图像,并将其简化为图像分类问题。现在,我们可以将合适的计算机视觉架构与迁移学习结合使用,令人惊讶的是,这种方法即使在非常小的数据集上也能提供类似的性能。请查看这个博客以获得更好的理解和代码。

3.用更少的数据学习

a)一次学习:人类有能力学习甚至一个单一的例子,仍然能够以非常高的精度区分新的物体。另一方面,深度神经网络需要海量的标注数据进行训练和泛化。这是一个很大的缺点,一次性学习是一种即使使用小数据集来训练神经网络的尝试。有两种方法可以实现这一点。我们可以修改我们的损失函数,使其能够识别微小的差异,并学习更好的数据表示。暹罗网络就是这样一种通常用于图像验证的方法。

Fig 2: A basic representation of Siamese network[source]

b)暹罗网络:给定一组图像,暹罗网络试图找出两个给定图像有多相似。该网络具有两个相同的子网络,具有相同的参数和权重。子网由卷积块组成,并且具有完全连接的层,并且向末端提取特征向量(大小为 128)。需要比较的图像集通过网络提取特征向量,计算特征向量之间的距离。模型性能取决于训练图像对(图像对越接近,性能越好),并且模型被优化,使得我们对于相似的图像获得较低的损失,而对于不同的图像获得较高的损失。Siamese network 是一个很好的例子,说明我们如何修改损失函数,并使用更少但高质量的训练数据来训练深度学习模型。查看下面的视频获得详细解释。

一次性学习的另一种方法是为模型创建一个类似人脑的记忆。这可能是谷歌 Deepmind 为一次性学习提出的神经图灵模型背后的灵感来源。

c)记忆增强神经网络:神经图灵机是记忆增强神经网络的一部分,它试图为神经网络创建一个外部记忆,这有助于短期学习。NTM 基本上由一个称为控制器的神经网络和一个称为记忆库的 2D 矩阵组成。在每个时间步,神经网络从外界接收一些输入,并向外界发送一些输出。然而,网络也具有从存储器位置读取的能力和向存储器位置写入的能力。请注意,如果我们使用索引提取内存,反向传播将不起作用。因此,控制器使用模糊操作来读取和写入,即,它在读取和写入时为每个位置分配不同的权重。控制器对存储器位置产生权重,这允许它以可区分的方式指定存储器位置。NTM 在自然语言处理任务中表现出了巨大的潜力,可以超越 LSTM,在各种任务中学习得更好。查看这个伟大的博客,深入了解 NTM

Fig 3: A basic representation of NTM[source, source]

d)零投学习:零投学习是指解决不属于训练数据的任务的方法。这确实可以帮助我们处理在培训中没有看到的类,并减少数据需求。有各种各样的方法来制定零短学习的任务,我将讨论一种这样的方法。在这种方法中,我们试图预测给定图像的语义表示,即给定一幅图像,我们试图预测图像类的 word2vec 表示。所以简单来说,我们可以认为这是一个回归问题,深度神经网络试图通过处理其图像来预测该类的向量表示。我们可以使用标准的神经架构,如 VGG16ResNet ,并修改最后几层以输出一个单词向量。这种方法有助于我们找到看不见的图像的词向量,我们可以使用它通过最近邻搜索来找到图像类别。代替回归,我们还可以将最后一层作为图像特征和词向量的点积,并找到相似性,这有助于我们学习视觉语义嵌入模型。阅读设计文件了解更多详情。另外,看看这个博客来看看零距离学习的实践。

Fig 4: Learning Label Embedding from the image features[Souce]

4.更好的优化技术

元学习(学会学习):元学习处理从给定数据中寻找学习的最佳方式,即学习模型的各种优化设置和超参数。请注意,实现元学习有多种方法,让我们讨论一种这样的方法。元学习框架通常由一个网络组成,该网络有两个模型:

A)称为优化的神经网络或学习器,其被视为低级网络并用于预测。

b)我们有另一个神经网络,称为优化器或元学习器或高级模型,它更新低级网络的权重。

这导致了双向嵌套训练过程。我们采取了低级网络的多个步骤,形成了元学习者的单个步骤。我们还在低级网络的这些步骤结束时计算元损失,并相应地更新元学习器的权重。这个过程有助于我们找出最佳的训练参数,使学习过程更加有效。关注这个牛逼的博客详细了解和实现。

Fig 5: Meta-learning in action[Souce]

3。解决缺乏普遍性的问题

1。数据扩充:

在处理小数据集而不过度拟合时,数据扩充可以是一种有效的工具。这也是一个很好的技术,使我们的模型不变的大小,平移,视点,照明等变化。我们可以通过以下几种方式扩充我们的数据来实现这一点:

  1. 水平或垂直翻转图像
  2. 裁剪和/或缩放图像
  3. 更改图像的亮度/清晰度/对比度
  4. 将图像旋转一定角度

Fig 6: Various data augmentation techniques to create more data[source]

Fast.ai 有一些最好的数据扩充转换函数,这使得数据扩充任务非常容易,只需要几行代码。查看这个令人敬畏的文档,了解如何使用 Fast.ai 实现数据增强。

2.数据生成:

a)半监督学习:很多时候,我们有大量可用的数据,但只有其中的一部分被标记。大型语料库可以是任何公开可用的数据集或专有数据。在这种情况下,半监督学习可以很好地解决标记数据少的问题。一种这样的方法是建立一个模型,该模型学习标记数据中的模式,并试图预测被称为伪标记的未标记数据的类别。一旦我们有了这些伪标签,我们就可以使用带标签和伪标签的数据来为我们的原始任务训练模型。我们可以使用各种监督或非监督模型来生成伪标签,并可以设置预测概率的阈值来选择合适的伪标签数据进行训练。我们还可以探索主动学习,其中模型指定哪些数据点对训练最有用,我们可以只获得一小部分数据,以便模型可以有效地学习。合作教学合作学习也是在这种情况下有所帮助的类似方法。

b)甘:生成对抗网络是一种生成模型,能够生成看起来非常接近真实数据的新数据。GAN 有两个组件,称为生成器和鉴别器,它们在我们训练模型时相互作用。生成器尝试生成假数据点,鉴别器尝试识别生成的数据是真的还是假的。假设我们想要创造新的狗的形象。生成器创建假狗照片,这些照片与真狗照片一起提供给鉴别器。鉴别器的目的是正确地识别真实和伪造的图像,而发生器的目的是产生鉴别器不能辨别为伪造的图像。在模型的适当训练之后,生成器学习生成看起来像真实的狗图像的图像,并且可以用于创建新的数据集。

Fig 7: A typical representation of GAN[source]

我们还可以使用 LSTM 的生成模型来生成文本文档或声音,这些可以用作训练数据。查看这个博客获得详细解释。

结论:

在这一部分中,我们讨论了影响深度神经网络训练的各种因素,以及一些可以帮助我们用小数据集进行训练的技术。在我们的大多数用例中,我们通常没有非常大的数据集,这种技术为我们训练模型并获得令人满意的性能开辟了新的途径。在这个博客系列中,我试图列出各种常用的技术,而训练将小数据。然而,这个列表并不详尽,只能作为进一步探索的起点。请查看链接和参考资料,以获得对上面讨论的一些技术的详细理解和实现。

关于我:研究生,旧金山大学数据科学硕士;Trulia 从事计算机视觉的实习生&半监督学习;3 年以上使用数据科学和机器学习解决复杂业务问题的经验;有兴趣与跨职能部门合作,从数据中获得见解,并应用机器学习知识来解决复杂的数据科学问题。 LinkedIn 作品集 GitHub 往期帖子

参考

  1. 关于语言模型的帖子,从经典方法到最近的预训练语言模型
  2. 利用 fastai 库在音频分类方面取得巨大成果
  3. 神经网络中使用的优化算法类型和优化梯度下降的方法
  4. 甘斯从零开始 1:深度介绍。PyTorch 和 TensorFlow 中的代码
  5. 深度学习专业化
  6. 神经图灵机的解释
  7. 设计:深度视觉语义嵌入模型
  8. 零距离学习
  9. 从零到研究——元学习导论
  10. Fast.ai 文档

英国脱欧:不文明战争向我们展示了欧盟公投是如何用数据科学赢得的

原文:https://towardsdatascience.com/brexit-the-uncivil-war-showed-us-how-the-eu-referendum-was-won-with-data-science-3d727ee03fc0?source=collection_archive---------8-----------------------

在第四频道/ HBO 的《英国退出欧盟:不文明的战争》上周上映后,有一件事没有得到应有的讨论,那就是数据科学的广泛使用是脱欧运动战胜所有困难的主要原因。在本文中,我将讨论数据科学如何改变政治格局。

2016 年欧盟公投时的传统民调几乎一致显示,留欧最有可能获胜。即使是像奈杰尔·法拉奇这样的脱欧支持者也在装腔作势地表示,如果失败(以及为了另一次公投),他们将继续战斗,直到结果出来,因为结果会很接近。当它到来时,所有人都感到震惊,包括政治家和政治评论家。

传统民调如何出错

作为“保持自我”的坚定支持者,我记得自己在法国南部的父母家中看到选举结果,一直看到深夜,大约凌晨 3 点钟,我面无血色地上床睡觉。一觉醒来,我最担心的事情被证实了,我们将离开欧盟。我的伴侣听到这个消息后哭了,她出生在德国,但却是英国公民,她去了英国唯一的欧盟学校之一。她觉得自己的身份被剥夺了。

第二天,政治后果是巨大的,这是我们今天仍在处理的事情。结果出来后,人们广泛讨论的是民调怎么全错了,这是近年来反复发生的事情,5 个月后唐纳德·川普当选白宫时又发生了一次。这再次震惊了每一位严肃的政治评论家,据迈克尔·沃尔夫称,甚至唐纳德·特朗普本人也感到震惊。

甚至 2017 年英国大选的结果也出乎意料,那次选举产生了一个无多数派议会。此后不久,我写了传统民意调查是如何消亡的,强调唯一正确预测无多数议会结果的民意调查是一项实验性的 YouGov 民意调查,它使用了更现代的数据科学技术

简而言之,传统的民意调查定期询问统计相关数量的人(大约 2000 人)对各种问题的看法。这一选择代表了选民中不同的人口统计数据,例如年龄、性别和收入。然后,民意测验专家通过这些人口统计数据来衡量全国范围内的意见波动。

YouGov 的实验性民意调查使用了更现代的技术,他们进行了更大规模的采访样本(约 50,000 人),而不太关心公平的人口分布。然后,他们使用多层回归和后分层来识别人口中的选民群。本质上是将选民划分为更细的人口统计数据,并在此基础上对波动进行加权。

虽然这本身是一个重要的话题,但更重要的问题不是传统的投票模型如何出错,而是为什么出错。

什么英国退欧:不文明战争向我们展示了数据科学在欧盟公投中的应用

上周,第四频道播出了他们谈论已久的英国退欧:不文明的战争。对于那些还没有看过这部电影的人来说,这是一部长篇剧,基于对事件关键人物的广泛采访,从英国退出欧盟公投宣布到结果。

这部剧由詹姆斯·格拉汉姆编剧,讲述了本尼迪克特·康伯巴奇(Benedict Cumberbatch)出色地扮演了备受争议的政治战略家多米尼克·卡明斯(Dominic Cummings),以及他是如何策划脱欧运动的。

有趣的是,它把他描绘成一个纯粹专注于赢得公投的人,而不是结果会是什么样子,以及他是否认为这是正确的。

他的政治目标似乎是,他不同意英国政治阶层管理英国的方式,并想破坏它。其他人可能称之为打倒当权派,或者在美国,抽干沼泽。他认为英国退出欧盟全民公决是实现这一目标的手段。

如果所有的报道都是准确的,那么《英国退出:不文明的战争》应该是脱欧运动如何赢得欧盟公投的不带偏见的写照。自从《不文明的战争》上映以来,大多数对《离开》的批评似乎都集中在两件事上;这出戏掩盖了 T2 的脱欧运动是如何违反选举法的。

以及竞选活动如何依靠种族主义和反移民情绪获胜。

没有更广泛讨论的是数据科学的使用如何引领整个运动,以及是什么让 Leave 比 remove 运动更具优势,并且很可能赢得了这场运动。更重要的是,这对政治的未来意味着什么。

多米尼克·卡明斯向所有批评者指出的是,他没有决定信息,而是让数据决定。这就是他们如何抓住对选民打击最大的核心信息;土耳其即将加入欧盟,我们给欧盟的 3 . 5 亿英镑应该用于资金不足的国民保健服务。这两者都没有被发现或证明是准确的。

在《英国脱欧:不文明的战争》中,我们看到多米尼克会见了扎克·马辛汉姆,他是加拿大政治咨询和技术公司 AggregateIQ 的创始人。据推测,脱欧运动在 AggregateIQ 上花费了 350 万英镑,占其 700 万英镑限额的 50%,其中花费了 7449079 英镑。

那是他们津贴的很大一部分,所以他们一定在这家公司有很多存款。此外,英国退欧:不文明的战争邪恶地描绘了多米尼克与扎克的会面,他说他们可以利用“另一方不知道存在的 300 万额外选民”。然后多米尼克说他要“黑掉系统[选民]”给一些目瞪口呆的保守派政客。

在《英国退出欧盟不文明战争》中,它向我们展示了 Dominic 如何让 AggregateIQ 的一组数据科学家被关在一个阴暗的侧室中,作为一个独立于脱欧运动其余部分的项目。

人们看到他们做的第一件事是发起一场运动,了解不同选民群体对欧盟不同问题的看法。他们通过给人们机会赢得一个集合赌注来做到这一点,这在统计上几乎不可能赢得(50 亿分之一的机会)。然后,他们利用这项研究的发现,为选民中的不同部分创建行为微目标信息。

结果发现,在公投期间,他们提供了超过 10 亿条脸书广告,其中包含各种支持脱欧的信息。例如,不那么“种族主义”的选民可能收到了鲍里斯·约翰逊的照片,上面写着,“我支持移民,但最重要的是,我支持有控制的移民”。而其他人收到诸如“土耳其有 7600 万人口。土耳其正在加入欧盟。好主意??"。

Older people were targetted with adverts on how the money we send to the UK could be spent on the NHS

People who were animal lovers would have received adverts like these

And supposed tea lovers or patriots would have received messages like these

如果他们点击了相关的广告,他们会收到一大群围绕同一主题的连续广告,强化了这一观点。卡明斯之前曾谈到过在欧盟公投前的最后 10 天,他们如何扣住大部分预算,并将其投入到这类广告中。他说,在此期间,大约有 700 万人成为目标。

在英国退出欧盟这场不文明的战争中,脱欧运动团队甚至质问为什么广告没有在电视和新闻周期中被提及,他们认为对方根本不知道发生了什么。

2016 年 6 月 23 日,17,410,742 人投票脱离欧盟,16,141,241 人投票留在欧盟。

为什么数据科学正在改变政治格局?

当然,任何稍微关注西方新闻的人都可能听说过剑桥分析公司丑闻。剑桥分析公司(Cambridge Analytica)由罗伯特·默瑟(亿万富翁人工智能专家)和唐纳德·川普的财政支持者兼竞选首席执行官史蒂夫·班农(另类右翼媒体斯文加利)创建和运营。剑桥分析揭发者 Christopher Wyle 强调了 AggregateIQ 与剑桥分析的密切联系。

这一丑闻向我们表明,通过滥用脸书的用户数据,他们可以对整个选民进行心理分析。使用一个名为 myPersonality 的病毒式个性应用程序,他们能够将个性类型与人们在脸书上的喜好进行交叉参考,以高度准确地描述人们的特征

收集的数据被用于描述选民的算法,成为欧盟公投和美国大选的重要武器。怀尔甚至描述了史蒂夫·班农如何在他的“心理战”中将这些工具称为武器,目的是在全世界引发民族主义民粹主义运动。

虽然有些人可能反对这种形式的政治操纵,并认为这很可怕。积极的一面是,由于唐纳德·特朗普当选后的巨大政治压力,剑桥分析公司现已关闭,脸书打击了第三方数据泄露问题,使这些数据科学工具得以建立,GDPR 保护欧洲公民意味着你现在可以更好地控制如何使用你的个人数据。下次再发生这种事,可能就不会那么容易或者不被注意了。

不幸的是,像剑桥分析公司这样的其他公司仍然存在,而且只要有足够的需求,它们还会继续存在。政客们在竞选上花了大量的钱,当然,他们会使用最新的技巧和技术来争取胜利。

预计这将成为新的常态

如果你对欧盟公投或唐纳德·特朗普(Donald Trump)当选的结果不满意,你可能会对这一事实感到困惑。这只是因为国家民粹主义运动抢先一步。

自从我们进入数字时代,我们分享越来越多的关于自己的数据,并创造更多的信息渠道。现代营销和广告越来越注重为不断细化的目标群体创造相关的个性化信息,政治只是这个市场的另一个客户。

数据科学将找到将我们的信息拼凑在一起的方法,以创建我们的个人资料,确保正确的信息到达我们手中。政治活动会找到方法来研究我们对特定问题的情绪状态,并创造信息来引发我们特定的投票反应。平台将继续存在,使那些有针对性的活动信息能够到达我们这里。

如果说英国退欧:不文明的战争让我明白了什么,那就是留欧运动未能拥抱数据科学爆炸中可用的最新工具和技术。他们也可能瞄准了脱欧运动的目标选民,以及那些懒得出去投票的选民。像传统的民意测验专家一样,他们使用了几十年的老技术,却没有得到正确的结果。

这是我们在人工智能的未来必须面对的众多伦理困境之一。

是时候让政治步入 21 世纪了

我们现在生活在所谓的后真相时代,它已经不再是理性辩论中的赞成和反对,而是发射信息“手榴弹”(不管它们是真是假),以一种情绪化的方式与选民产生共鸣,然后要求反对派“灭火”。

这可能是一条双行道,我当然不是说撒谎是可以接受的,完全有可能建立更好的事实核查工具,在未来对虚假信息进行实时核查,以帮助解决这一问题。但我要说的是,争论各方的竞选活动都需要从剑桥分析公司和 AggregateIQ 那里学到,旧的政治方式已经一去不复返,数据科学将会继续存在。赢家是在游戏中保持领先的人。

** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 可以在 Twitter @NoWayAsh 关注我。我欢迎您的反馈、评论和意见。

弥合数据科学家和管理层之间的差距

原文:https://towardsdatascience.com/bridging-the-gap-between-data-scientists-and-management-64c798de7dfe?source=collection_archive---------31-----------------------

现实世界中的数据科学

数据科学家应该向他们的老板解释的关于机器学习的五个概念

“If I could predict the winning lottery numbers I wouldn’t be stuck listening to your fishing stories.”

机器学习功能强大

毫无疑问,人们明白机器学习是一个强大的工具。利用你过去发生的一切来预测未来;从过去的错误中学习并相应地调整。机器学习不是依赖人的记忆和直觉,而是使用计算机和统计数据来完成繁重的工作。有了合适的支撑结构,它可以成为一个强大的工具,但它绝不是完美的。

它不是水晶球。

在一个理想的世界里,企业中的每个人都应该理解工作的所有细微差别以及它所包含的内容,但这是完全错误的。大多数工作都不是这样。这种缺乏理解必然会引发问题。

请求者可能不知道引擎盖下的所有东西是如何工作的——特别是考虑到这不是他们的工作——但是他们知道他们应该使用它。机器学习工作如此受欢迎是有原因的,因为它对决策有影响。然而,毫无疑问,许多公司只关注这些角色,因为他们知道竞争对手是这样的。Arthur Samuel 于 1959 年首次引用了“机器学习”一词,但这项工作本身主要是在最近几年才开始起步的。所以自然地,许多人不会确切地知道机器学习需要什么以及幕后的跑腿工作。

对于一些人来说,机器学习过程只是一个黑盒。向数据科学家寻求答案,稍后再回来询问他们的预测。就是这样。

请求者不知道他们的请求真正意味着什么,这绝不是一个新概念,自从“商务休闲装”出现以来,这个概念就一直存在。这并不是说没有多少请求者知道机器学习项目需要什么。这只是一种不平衡,如果可以设定现实的期望,那么每个人的工作都会得到改善。

有些人认为机器学习预测 100%准确无误,当事情没有实现时,他们会表现得很惊讶。其他人希望将公司无权访问的信息包含在数据集中。

这绝不仅仅是管理层的责任。不能有效地传达期望是数据科学家应该警惕的责任。管理层不是你工作中的专家,所以你有责任向他们解释你在做什么。

通过向管理层澄清您实际上在幕后做什么,并解释应该如何利用您的模型,不仅可以帮助他们做出更好的决策,还可以简化数据科学家的流程,并避免未来出现问题。

下面我将介绍五个概念,它们有助于弥合这一差距,并有可能改善每个相关人员的工作流程。

模型的准确性取决于数据的质量

向决策者表明,数据问题将延续到模型中,要么降低预测能力,要么可能使整个过程无效。

假设你正在对你班上的学生进行一项研究。这是一个基本的调查,包括人口统计和意见的问题,也是匿名的。在收集了所有的文件后,你浏览了所有的回复,注意到一项调查,调查中选择了爱斯基摩人、印度人,并选择不说出他们的种族。你扫视房间,也许有人真的是三者兼而有之,但你必须对这种调查保持警惕。一个高中生没有认真对待一项调查,这真的是不可能的吗?

也许你会排除一些更有问题的调查…

随着组织收集更多的数据,管理这些数据的质量变得日益重要。毕竟,数据是组织的命脉。

- 约翰·鲍曼,SAS 见解编辑

问任何 DBA,尤其是大公司的 DBA,关于他们数据的准确性,他们可能会叹口气,耸耸肩。这不是他们的错,一旦数据库开始变大,警告和问题开始积累,就没有时间或资源来确保一切 100%准确。

数据质量始终是一个问题。在知道数据可能有问题的情况下做出决定,比假设数据是好的情况下做出决定要好。该模型并不关心数据对真实世界是否准确,它必须假设数据对真实世界准确,以便进行评估。可以在代码中检查异常值和高杠杆值,但即使这些检查也只能修复这么多。

对数据集进行数据验证是一个良好的开端。然而,根据数据的大小,检查一个数据样本可能要花费相当多的时间。最重要的是,如果有些数据超出了您的专业知识范围,那么与那些能够对数据执行嗅探测试并确保所有数据都在他们那一端得到检查的人一起工作将会受到极大的赞赏。

模型只知道给它的数据

告诉决策者,该模型仅限于您输入的数据(以及该数据的所有衍生数据)。如果它不在输入中,那么它就没有被完全考虑。

预测模型只考虑趋势和给定的信息。如果您想要将其他变量考虑在内,则需要在建立模型的训练数据中考虑这些变量。

假设您开发了一个模型,用于预测您的公司在接下来的几个月中将会处理的客户服务电话的数量。您包括与销售增长、一年中的时间和人员配备相关的值。对你的预测感到满意,你把它交给你的老板。

“看起来棒极了!这是否说明了我们将在第四季度发布的服务应用?”

你的心有点沉。你是怎么量化的呢?您知道您在数据仓库中也没有任何这些信息。也许你可以找一些东西来预测电话量将减少多少,并看看这将释放多少员工人数。

你说你会尽你所能…

虽然一个变量的某些部分可以解释另一个变量的一些影响,如人员配备和一年中的时间,但如果没有明确提到某个具体因素,人们就不能自信地声称该模型解释了它。增加新的变量不仅会改变预测,还会改变其他变量的影响。系数和误差会改变。

为了克服这一点,要让你的模型中哪些因素被考虑,哪些因素没有被考虑。列出一些管理层想要包含/考虑的变量,看看你能做些什么。这样,你至少有一个他们想要研究的基线,并能够调整。

机器学习只是一堆统计学和计算机编程的串联

虽然开玩笑很有趣,但要明确你并不是真的在看水晶球做预测。有些变量可以很好地添加到模型中,但是如果它们不能以某种形式量化,那么你就不走运了。

信不信由你,预测模型实际上并没有预见未来。它们只是一堆统计计算和计算机算法,由比其他人聪明得多的人创造,由其他极其聪明的人实现。

即使对于更高级的过程,如图像处理,虽然它本身不是一个数字,但它是一个数值过程。在幕后,图像被分解到像素级别并被赋予值,然后将这些像素中的图案与它们被赋予的标签进行比较。

模型中可以包含的内容的限制是可以转化为数字的内容。如果它可以被量化,那么很有可能会做一些伟大的事情来解释它。只要设计数据集的人能把它转换成适当的格式,那就没问题。

比方说,你试图预测一本书会有多受欢迎。这将很容易包括与同一作者的其他书籍的流派流行度和平均亚马逊评论相关的因素。然而,添加一些像书的节奏或者情节有多有趣的东西会有点复杂。

另一个值得关注的方面是,模型和统计测试需要满足某些假设。如果你建立了一个忽略它们的模型,那么你的结果可能是好的,或者从长远来看它们可能是完全错误的。这是业余建模者(比如我自己)经常跳过的陷阱(比如我自己)。

以线性回归模型的假设为例。感谢统计解决方案没有让我记住它们。

  • 线性关系
  • 多元正态性
  • 没有或很少多重共线性
  • 无自相关
  • 同方差性

线性回归是一个简单明了的模型,通常可以用一两行代码实现。确保所有潜在的假设都得到满足通常比建模者想要处理的更麻烦,但是我们每次都应该这样做。不满足这些假设可能意味着一个人们认为具有高度预测性的模型实际上偏向于一个或另一个变量。

对于一个具有统计稳健性的模型,它需要所有的参数都达到某种可接受的水平。什么样的水平取决于制作数据集和模型的人。

如果一个模型需要 x、y 和 z 为真才能做出准确的预测,只有 x 和 z 可能不够。

我知道这是真正的突破。

第三个想法是,大多数预测和预报为每个预测提供了某种置信区间。这个想法取决于你所做的预测的确切类型,但是对于大多数类型来说,这通常在某种形式上是正确的。围绕预测有一系列不确定性。没有 100%肯定的预测(除非它是一个已解决的问题),因此,即使是非常可能的预测也有一些回旋的余地。

大多数预测仅仅给出了可能性最高的事件,这并不是说它仍然将较小的发生几率归因于另一个事件。

当你玩彩票的时候,一个模型会在你每次买彩票的时候预测你不会每次都中奖,这是正确的。然而,有一个非零的机会赢得彩票,所以最终,有人会赢,尽管赔率完全对他们不利。

对于彩票中奖者来说,这个模型可能是错误的,但这并不是说它对其他彩票参与者来说仍然是错误的。

就解决方案而言,管理层应该清楚,添加易于量化(且可用)的数据是一个更简单的过程。有时,占位符因子可以解决某些变量的缺点,但应该小心确保占位符代表您认为它是什么。当管理层想要增加一个新的因素时,询问他们是否知道如何量化感兴趣的变量。也许他们知道一些你不知道的事情。

过去的表现不代表未来的结果

这是你在投资中经常看到的一句话,也适用于预测模型。即使你有可以追溯到史前时代的数据,有精确的列,有数十亿的变量,也不可能一直给出 100%准确的预测。至少现在还没有。为了做出预测,需要考虑的因素太多了。

投资中经常提起的一个案例是关于通用电气。

早在 20 世纪初,通用电气就是美国家庭的基石。他们大规模生产各种电器,甚至在二战期间帮助盟军的努力。从 1981 年到 2001 年,该公司的价值从 250 亿美元增长到 1300 亿美元。通用电气被誉为股市中最安全的选择之一。买入并在未来几年获得稳健的财务增长。

通用电气太大而不能倒。

然后大衰退来袭。通用电气股价下跌,股息下降。数以千计的工作岗位被削减以弥补损失,消息传出后股票下跌更多。截至 2018 年 11 月,通用电气的估值为 726.3 亿美元。时至今日,通用电气仍在尽最大努力恢复元气,重返其数十年来的巅峰。

对于普通投资者来说,通用电气在 2008 年之前是一个稳赚不赔的投资。虽然有人预测了大衰退,但普通投资者根本没想到通用电气会遭受如此沉重的打击。

很难做出预测,尤其是对未来。

-约吉贝拉

没有什么是完美的,尤其是一个预测。如果你预测你的销售部门下个月将增加多少客户,那么你可能是在假设下周销售电话不会被禁止的情况下运行的(政治可能是一个奇怪的空间)。因此,除非你预测销售是非法的,否则你的模型是在销售电话是合法的假设下运行的。

在产生影响之前,我们不知道这些因素对目标是否有影响,除非您可以预测这些其他因素何时会发生变化,否则您不可能有一个 100%准确的模型。

模型总是在仍有可能出错的信念下运行。这些模型并不神奇,它们的创造者无法预见的事件不会在模型中得到解释。他们能依靠的只有过去和已知的变化。

让管理层明白,预测模型通常假设当前趋势会继续。模型中没有特别说明的一切都被视为随机误差。很难解释这种意外,因为,这是意料之外的。

根据预测采取行动可以改变结果

为了检查模型在生产中的成功,将实际发生的情况与当时预测的情况进行比较是有意义的。然而,必须记住,为修正预测而采取的行动会改变结果。

如果解释不当,管理层可能会认为模型完全错误,并取消预测。

一艘船即将参加它的处女航。就在它出发之前,一名导航员指出,在他们的航线上将会有一场大风暴。船上的人听到了这个预测,并为他们的健康担忧。船起航了,每个人都为这次旅行的命运感到紧张。

这次航行最终很顺利,一次阳光充足、万里无云的美丽航行。到达目的地后,人们谴责导航员让他们担心,并注意到整个旅途中没有一滴雨。

乘客们不知道的是,船长已经改变了航线,选择了一条更加安全的路线,完全避开了风暴。

与结果不符的预测不一定是错的。预测模型将根据当前趋势选择最有可能的结果,一旦决策者听到这些预测,他们当然会采取行动。

然而,人们可能会认为这是一种完全免除数据科学家责任的方式,在某种程度上听起来确实如此。要么预测是对的,我是个天才,要么预测是错的,这不是我的错。

这是一个滑坡。当第一次开发一个模型时,很容易用其他过去的实例来验证模型,以检查模型的准确性。然而,一旦模型被生产化,就很难辨别出预测是错误的或者采取了适当的行动。你需要回去,调整适当的输入,看看新修订的预测现在与现实有多接近。

商业环境中许多机器学习项目的目的是了解公司目前的发展方向,同时提供对不同因素(如竞争对手和客户模式)的一些“假设”分析。

向请求者说明,在做出预测之后和事件发生之前所做的任何更改都不会在预测中得到考虑。为了根据实际发生的情况准确测试模型,您需要返回并包括在完成初始预测后所做的调整。

结论

我们涵盖的五个概念将有望为请求者提供一些关于机器学习的期望。

  • 模型的准确性取决于数据的质量
  • 模型只知道给它的数据
  • 机器学习只是一堆统计学和计算机编程的串联
  • 过去的表现并不代表未来的结果
  • 根据预测采取行动可以改变结果

现在,这绝不是一个全面的清单,更像是我希望在这个过程中早些时候向我的上级明确表达的想法。作为大企业的一部分,人们对你专业知识的理解和专业知识本身一样重要。这很不幸,但这是可以通过适当的沟通和合作来解决的事情。

如果你还有其他建议,欢迎在下面分享(或者愤怒的邮件给我)。

作为离散傅里叶变换预处理的汉明和汉宁函数简介

原文:https://towardsdatascience.com/brief-introduction-of-hamming-and-hanning-function-as-the-preprocessing-of-discrete-fourier-8b87fe538bb7?source=collection_archive---------9-----------------------

source: https://www.tek.com/sites/default/files/u811871/hamming-t.png

大多数人的第一个问题是,为什么我们在离散傅里叶变换(DFT)或者快速傅里叶变换(FFT)中需要预处理?在回答问题之前,你必须知道 DFT 和 FFT 的区别。我以前在这里讨论过这个话题,如果你想知道更多细节,你可以看看。重点是 FFT 是做 DFT 的最快方法。

答案是频谱泄漏。什么是频谱泄漏?频谱泄漏是指将“未完成的”波传递到 FFT。我说的未完成的波是指,当它像这样传递到 FFT 时,具有非整数周期的波。

当你把这个信号传递给 FFT,结果是这样的

Woah,功率很高,尤其是 4 Hz 频段。这很明显,因为我们将一个纯 4 Hz 正弦波传递给 FFT。但是看起来FFT‘认为’我们的纯信号是 4 Hz 左右波的叠加。

如果将“完成”信号传递给 DFT,结果将会不同。这个“完整的”4 Hz 正弦波

当把它传递给 FFT 时,结果会是这样的

这就是预期的结果!我们的输入信号是 4 Hz 正弦波,因此 DFT 频谱图中的功率频率仅为 4 Hz。而且显示的功率也没有之前那么大。由于 python 代码对空格和制表符非常敏感,我在这里只给你一个代码的 GitHub 链接,而不是在这里显示,因为如果我在这里提供它,所有的空格和制表符都会被弄乱。

这种现象被称为光谱泄漏。这是因为 DFT 假设我们的输入信号是一个‘完整’周期信号DFT 假设我们的信号完全按照输入重复。所以当我们通过‘不完整’版本的 4 Hz 正弦波时,DFT 会看到这样的情况。

让我们检查该信号的 FFT 输出,这是结果

类似于之前未完成的 4 Hz 正弦波的 FFT 输出不是?是的,除了这个加长版的外,功率上升更高(看 y 轴刻度)。绘制如上图的代码是通过这个链接完成的。

为了清除噪声并获得理想的输出(参见“4 Hz 正弦波的 FFT”图)是,我们必须知道信号的周期并在正确的时间对其进行切割(正好在信号周期结束时切割)。但是,在现实世界中,我们不知道信号的周期,而且现实世界中的信号充满了噪声和干扰,所以在正确的时间切割它是不可能的。解决方案是开窗函数

傅立叶变换中的窗口函数是,调整 FFT 信号输入的起点和终点的尝试与此类似。在这个故事中,我们将涵盖 2 窗口函数,汉宁函数,和汉明函数。

汉宁函数是这样写的

汉明函数是这样的

其中 M 是 FFT 的数据集输入中的数据量,n 是从 0 到 M-1 的数。

所以 Hanning 和 Hamming 将输出一个数组,这个数组中的数字与数据集中的数据数量成正比。如果我们绘制汉宁和汉明函数的输出,我们将得到如下两个图

这里是代码的链接来创建上面的情节。

为了调整信号,我们将信号乘以汉恩和哈姆的输出。作为一个例子,我们乘以我们未完成的 4 赫兹正弦波对汉恩和哈姆,然后我们的波形将是这样的。

让我们进行 FFT 处理,我们会得到这样的图形。

看,FFT 中错误频带的功率降低了(包括正确频带,它正在接近“正确”值)。我们可以看到错误频段的功率并没有完全消除,只是可以降低。如果我们在这个实验中观察 FFT 的结果,那么在汉明函数和汉宁函数之间没有真正的区别。这里的是代码的链接,用于创建汉宁/汉明函数处理的信号图及其 FFT 结果。

重要的一点是,无论是否经过窗函数处理,FFT 图中最主要的频率始终相同,为 4 Hz。所以,如果你只是想知道信号中占主导地位的一个频率是什么,我认为你不需要加窗函数。当您想要在数据集中找到一个以上的主导信号时,我认为这些窗口函数会有很大的帮助,因为当存在泄漏时,主导信号周围的一些频带的功率会盖过您想要找到的第二个、第三个或 etc 信号。当然,如果你想平滑 FFT 的结果,你需要一个窗口函数。

参考资料:

https://www . crystal instruments . com/dynamic-signal-analysis-basics,2019 年 9 月 29 日访问

马尔可夫链简介

原文:https://towardsdatascience.com/brief-introduction-to-markov-chains-2c8cab9c98ab?source=collection_archive---------2-----------------------

定义、属性和 PageRank 示例。

Credit: Free-Photos on Pixabay

本帖与 巴蒂斯特·罗卡 共同撰写。

介绍

1998 年,劳伦斯·佩奇(Lawrence Page)、谢尔盖·布林(Sergey Brin)、拉吉夫·莫特瓦尼(Rajeev Motwani)和特里·维诺格拉德(Terry Winograd)发表了《PageRank 引文排名:给网络带来秩序》(The PageRank Citation Ranking:bring Order to The Web),他们在文章中介绍了谷歌起源时现在著名的 Page rank 算法。二十多年后,谷歌已经成为一个巨人,即使算法已经发展了很多,PageRank 仍然是谷歌排名算法的一个“符号”(即使很少有人能真正说出它在算法中仍然占据的权重)。

从理论的角度来看,有趣的是注意到对 PageRank 算法的一种常见解释依赖于简单但基本的马尔可夫链数学概念。我们将在本文中看到,马尔可夫链是随机建模的强大工具,对任何数据科学家都有用。更特别的是,我们将回答一些基本问题,如:什么是马尔可夫链,它们有什么好的性质,可以用它们做什么?

概述

在第一部分,我们将给出理解什么是马尔可夫链所需的基本定义。在第二节中,我们将讨论有限状态空间马氏链的特殊情况。然后,在第三节我们将讨论马氏链的一些基本性质,并用许多小例子来说明这些性质。最后,在第四节中,我们将链接 PageRank 算法,并通过一个玩具示例来了解如何使用马尔可夫链对图中的节点进行排序。

注。这个职位需要概率和线性代数的基础知识。具体来说,将使用以下概念:条件概率特征向量全概率定律

什么是马尔可夫链?

随机变量和随机过程

在介绍马尔可夫链之前,让我们先快速回顾一下概率论中一些基本但重要的概念。

首先,在非数学术语中,随机变量 X 是一个变量,其值被定义为随机现象的结果。这个结果可以是一个数(或“类数”,包括向量),也可以不是。例如,我们可以将随机变量定义为掷骰子的结果(数字)以及掷硬币的结果(不是数字,除非你指定 0 为正面,1 为反面)。还要注意,随机变量的可能结果空间可以是离散的,也可以是连续的:例如,正态随机变量是连续的,而泊松随机变量是离散的。

然后,我们可以将随机过程(也称为随机过程)定义为由集合 T 索引的随机变量的集合,这些随机变量通常代表不同的时刻(我们将在下文中假设)。最常见的两种情况是:要么 T 是自然数的集合(离散时间随机过程),要么 T 是实数的集合(连续时间随机过程)。例如,每天抛硬币定义了一个离散时间随机过程,而股票市场期权的价格连续变化定义了一个连续时间随机过程。不同时刻的随机变量可以彼此独立(抛硬币的例子)或以某种方式相关(股票价格的例子),并且它们可以具有连续或离散的状态空间(每个时刻的可能结果的空间)。

Different kind of random processes (discrete/continuous in space/time).

马尔可夫性质和马尔可夫链

存在一些众所周知的随机过程族:高斯过程、泊松过程、自回归模型、移动平均模型、马尔可夫链等。这些特殊的案例,每一个都有特定的属性,让我们可以更好地研究和理解它们。

使随机过程的研究容易得多的一个性质是“马尔可夫性质”。马尔可夫性质以一种非常非正式的方式表示,对于随机过程,如果我们知道该过程在给定时间的值,我们将不会通过收集关于过去的更多知识来获得关于该过程未来行为的任何附加信息。用稍微更数学的术语来说,对于任何给定的时间,给定当前和过去状态的过程的未来状态的条件分布仅取决于当前状态,而完全不取决于过去状态(无记忆特性)。具有马尔可夫性质的随机过程称为马尔可夫过程

The Markov property expresses the fact that at a given time step and knowing the current state, we won’t get any additional information about the future by gathering information about the past.

基于前面的定义,我们现在可以定义“齐次离散时间马尔可夫链”(为了简单起见,在下文中称为“马尔可夫链”)。一个马尔可夫链是一个具有离散时间和离散状态空间的马尔可夫过程。因此,马尔可夫链是一个离散的状态序列,每个状态都来自一个离散的状态空间(有限的或非有限的),并且遵循马尔可夫性质。

在数学上,我们可以用以下方式表示马尔可夫链

其中在每个时刻,该过程在离散集合 E 中取其值,使得

那么,马尔可夫性质意味着我们有

请再次注意,最后一个公式表达了这样一个事实,即对于给定的历史(我现在所在的位置和我之前所在的位置),下一个状态(我接下来要去的位置)的概率分布只取决于当前状态,而不取决于过去的状态。

注。在这篇介绍性的文章中,我们决定只描述基本的齐次离散时间马尔可夫链。然而,也存在非齐次的(时间相关的)和/或时间连续的马尔可夫链。我们不会在下面讨论这些模型的变体。还要注意,上面给出的马尔可夫性质的定义是极其简化的:真正的数学定义包括过滤的概念,这远远超出了这个适度介绍的范围。

表征马尔可夫链的随机动态

在前一小节中,我们已经介绍了与任何马尔可夫链相匹配的一般框架。现在让我们来看看我们需要什么来定义这样一个随机过程的一个特定“实例”。

首先注意,不验证马尔可夫性质的离散时间随机过程的完整特征可能是痛苦的:给定时间的概率分布可能取决于过去和/或未来的一个或多个时刻。所有这些可能的时间相关性使得对该过程的任何适当描述都可能是困难的。

然而,由于马尔可夫性质,马尔可夫链的动态很容易定义。事实上,我们只需要指定两件事:一个初始概率分布(即时刻 n=0 的概率分布)表示为

以及一个转移概率核(它给出了对于任何一对状态,一个状态在时间 n+1 继承到另一个状态的概率)

已知前两个对象,过程的完全(概率)动态被很好地定义。事实上,这一过程实现的概率可以用递归的方法计算出来。

例如,假设我们想知道流程前 3 个状态的概率是(s0,s1,s2)。所以,我们想计算概率

这里,我们使用全概率定律,即拥有(s0,s1,s2)的概率等于拥有第一个 s0 的概率,乘以拥有 s1 的概率(假设我们之前拥有 s0),乘以拥有最终 s2 的概率(假设我们之前依次拥有 s0 和 s1)。数学上,它可以写成

然后出现了由马尔可夫假设给出的简化。事实上,对于长链,我们将获得最后状态的严重条件概率。然而,在马尔可夫的情况下,我们可以简化这个表达式

这样我们就有

由于它们完全表征了过程的概率动态,因此许多其他更复杂的事件可以仅基于初始概率分布 q0 和转移概率核 p 进行计算。值得给出的最后一个基本关系是相对于时间 n 的概率分布而言的时间 n+1 的概率分布的表达式

有限状态空间马尔可夫链

矩阵和图形表示

这里我们假设在 E 中有 N 个有限的可能状态:

然后,初始概率分布可以由大小为 N 的行向量 q0 来描述,并且转移概率可以由大小为 N×N 的矩阵 p 来描述,使得

这种记法的优点是,如果我们用原始向量 qn 来表示步骤 n 的概率分布,则它的分量由下式给出

那么简单的矩阵关系此后成立

(此处不详述证明,但可以非常容易地恢复)。

When right multiplying a row vector representing probability distribution at a given time step by the transition probability matrix, we obtain the probability distribution at the next time step.

因此,我们在这里看到,将概率分布从一个给定的步骤发展到下一个步骤,就像将初始步骤的行概率向量乘以矩阵 p 一样简单

有限状态空间马尔可夫链的随机动态可以容易地表示为有值定向图,使得图中的每个节点是一个状态,并且对于所有的状态对(ei,ej),如果 p(ei,ej)>0,则存在从 ei 到 ej 的边。那么边缘的值就是这个相同的概率 p(ei,ej)。

示例:《走向数据科学》读本

让我们举一个简单的例子来说明这一切。考虑一个虚构人物对数据科学读者的日常行为。对于每一天,有 3 种可能的状态:读者这一天没有访问 TDS(N),读者访问了 TDS 但是没有阅读完整的帖子(V),以及读者访问了 TDS 并且阅读了至少一个完整的帖子(R)。所以,我们有下面的状态空间

假设在第一天,该读者有 50%的机会只访问 TDS,有 50%的机会访问 TDS 并阅读至少一篇文章。描述初始概率分布(n=0)的向量为

假设观察到以下概率:

  • 当读者一天不访问 TDS,他有 25%的机会第二天仍然不访问,50%的机会只访问,25%的机会访问和阅读
  • 当读者访问 TDS 一天没有阅读,第二天有 50%的机会再次访问而没有阅读,有 50%的机会访问并阅读
  • 当读者访问并阅读了一天,他有 33%的几率第二天不访问(希望这个帖子不会有这种效果!),33%的几率只访问,34%的几率再次访问和阅读

然后,我们有下面的转移矩阵

根据前面的小节,我们知道如何为读者计算第二天(n=1)每个状态的概率

最后,这个马尔可夫链的概率动态可以用图形表示如下

Graph representation of the Markov chain modelling our fictive TDS reader behaviour.

马尔可夫链属性

在这一节中,我们将只给出一些基本的马氏链性质或特征。这个想法不是要深入数学细节,而是给出一个使用马尔可夫链时需要研究的兴趣点的概述。正如我们已经看到的,在有限状态空间的情况下,我们可以将马尔可夫链描绘成一个图,请注意,我们将使用图形表示来说明下面的一些特性。然而,应该记住,这些性质不一定局限于有限状态空间的情况。

还原性、周期性、短暂性和重现性

在这一小节中,让我们从描述一个状态或整个马尔可夫链的一些经典方法开始。
首先,我们说一个马尔可夫链是不可约的,如果它有可能从任何其他状态到达任何状态(不一定在一个时间步内)。如果状态空间是有限的,链可以用一个图来表示,那么我们可以说一个不可约马氏链的图是强连通的(图论)。

Illustration of the irreducibility property. The chain on the left is not irreducible: from 3 or 4 we can’t reach 1 or 2. The chain on the right (one edge has been added) is irreducible: each state can be reached from any other state.

如果当离开一个状态时,返回到该状态需要 k 个时间步长的倍数(k 是所有可能返回路径长度的最大公约数),则该状态具有周期 k。如果 k = 1,那么状态被认为是非周期的,如果一个完整的马尔可夫链的所有状态都是非周期的,那么它就是非周期的。对于一个不可约的马尔可夫链,我们还可以提到这样一个事实:如果一个状态是非周期的,那么所有的状态都是非周期的。

Illustration of the periodicity property. The chain on the left is 2-periodic: when leaving any state, it always takes a multiple of 2 steps to come back to it. The chain on the right is 3-periodic.

如果当我们离开一个状态时,有一个非零的概率表明我们再也不会回到这个状态,那么这个状态就是暂时的。相反,如果我们知道,在离开一个状态之后,我们会以概率 1 返回到那个状态,那么这个状态就是循环的(如果它不是短暂的)。

Illustration of the recurrence/transience property. The chain of the left is such that: 1, 2 and 3 are transient (when leaving these points we can’t be absolutely sure that we will come back to them) and 3-periodic whereas 4 and 5 are recurrent (when leaving these points we are absolutely sure that we will come back to them at some time) and 2-periodic. The chain on the right has one more edge that makes the full chain recurrent and aperiodic.

对于一个循环状态,我们可以计算平均循环时间,即离开该状态时的预期返回时间。注意,即使收益概率等于 1,也不意味着期望收益时间是有限的。因此,在循环状态中,我们可以区分正循环状态(有限预期返回时间)和零循环状态(无限预期返回时间)。

平稳分布、极限行为和遍历性

在这一小节中,我们将讨论马尔可夫链所描述的(随机)动态的某些特征。

状态空间 E 上的概率分布π被称为稳定分布,如果它验证了

正如我们所做的

然后,平稳分布验证

根据定义,一个稳定的概率分布是这样的,它不会随着时间而演化。因此,如果初始分布 q 是一个平稳分布,那么它将在所有未来时间步保持不变。如果状态空间是有限的,p 可以用一个矩阵来表示,π可以用一个原始向量来表示,那么我们有

再一次,它表达了一个事实,即一个稳定的概率分布不会随时间演化(正如我们看到的,概率分布乘以 p 就可以计算下一个时间步的概率分布)。注意,一个不可约的马尔可夫链有一个稳定的概率分布,当且仅当它的所有状态都是正循环的。

与平稳概率分布相关的另一个有趣的性质如下。如果链是递归正的(因此存在平稳分布)和非周期的,那么不管初始概率是多少,当时间步长趋于无穷大时,链的概率分布收敛:链被称为具有一个极限分布,它就是平稳分布。在一般情况下,它可以写成

让我们再次强调这样一个事实,即没有对初始概率分布的假设:不管初始设置如何,链的概率分布都收敛于稳定分布(链的平衡分布)。

最后,遍历性是与马尔可夫链的行为相关的另一个有趣的属性。如果一个马尔可夫链是不可约的,那么我们也说这个链是“遍历的”,因为它证明了下面的遍历定理。假设我们有一个应用程序 f(。)从状态空间 E 到真实线(例如,它可以是每个状态中的成本)。我们可以定义这个应用沿着给定轨迹的平均值(时间平均值)。对于第 n 个第一项,它表示为

我们还可以计算应用 f 在集合 E 上的平均值,集合 E 由固定分布(空间平均值)加权,表示为

那么遍历定理告诉我们,当轨迹变得无限长时的时间均值等于空间均值(由平稳分布加权)。遍历属性可以写成

换句话说,在极限情况下,轨迹的早期行为变得可以忽略不计,只有长期稳定行为在计算时间平均值时才真正重要。

回到我们的 TDS 阅读器示例

我们再次考虑 TDS 阅读器的例子。在这个简单的例子中,链显然是不可约的、非周期的,并且所有状态都是循环正的。

为了展示可以用马尔可夫链计算的有趣结果,我们想看看状态 R(状态“访问和阅读”)的平均重现时间。换句话说,我们想回答以下问题:当我们的 TDS 读者在某一天访问并阅读时,在他再次访问和阅读之前,我们平均要等待多少天?让我们试着直观地了解一下如何计算这个值。

首先,我们表示

所以我们想在这里计算 m(R,R)。在离开 R 后的第一步推理中,我们得到

但是,这个表达式需要知道 m(N,R)和 m(V,R)才能计算 m(R,R)。这两个量可以用同样的方式表示

因此,我们有 3 个含有 3 个未知数的方程,当我们求解这个系统时,我们得到 m(N,R) = 2.67,m(V,R) = 2.00,m(R,R) = 2.54。状态 R 的平均重现时间的值是 2.54。因此,我们看到,通过一些线性代数,我们设法计算出状态 R 的平均重现时间(以及从 N 到 R 的平均时间和从 V 到 R 的平均时间)。

为了结束这个例子,让我们看看这个马尔可夫链的平稳分布是什么。为了确定平稳分布,我们必须解下面的线性代数方程

所以,我们必须找到与特征值 1 相关的 p 的左特征向量。解决这个问题,我们得到下面的平稳分布

Stationary distribution of our “TDS reader” example.

我们还可以注意到π(R) = 1/m(R,R),稍微思考一下,这是一个非常符合逻辑的恒等式(但在这篇文章中我们不会给出更多细节)。

由于链是不可约的和非周期性的,这意味着,从长远来看,概率分布将收敛到稳定分布(对于任何初始化)。换句话说,无论我们的 TDS 阅读器的初始状态是什么,如果我们等待足够长的时间并随机选择一天,那么我们有一个概率π(N)读者在这一天不访问,一个概率π(V)读者访问但不阅读,以及一个概率π(R)读者访问并阅读。为了更好地掌握收敛特性,让我们看一下下图,该图显示了从不同起点开始概率分布的演变以及(快速)收敛到稳定分布

Visualisation of the convergence of 3 differently initialised probability distributions (blue, orange and green) towards the stationary distribution (red).

一个经典的例子:PageRank 算法

现在是时候回到 PageRank 了!在进一步讨论之前,让我们提一下这样一个事实:我们将要给出的 PageRank 的解释并不是唯一可能的,而且原始论文的作者在设计该方法时并不一定考虑到了马尔可夫链。然而,下面的解释有一个很好理解的优点。

随机网络冲浪者

PageRank 试图解决的问题如下:我们如何通过使用页面之间的现有链接对给定集合中的页面进行排序(我们可以假设该集合已经被过滤,例如在一些查询中)?

为了解决这个问题并能够对页面进行排序,PageRank 大致如下进行。我们认为一个随机的网上冲浪者在最初的时间是在一个页面上。然后,该冲浪者通过对每个页面点击指向所考虑的集合中的另一个页面的链接之一来开始随机导航(假设不允许链接到该集合之外的页面)。对于给定的页面,所有允许的链接都有同等的机会被点击。

这里我们有一个马尔可夫链的设置:页面是不同的可能状态,转移概率由从一个页面到另一个页面的链接来定义(加权使得在每个页面上所有链接的页面都有相等的机会被选择),并且无记忆属性由冲浪者的行为清楚地验证。如果我们还假设所定义的链是循环正的和非周期性的(使用一些小技巧来确保我们满足这个设置),那么在很长时间之后,“当前页面”概率分布收敛到稳定分布。所以,不管起始页面是什么,如果我们选择一个随机的时间步长,很长时间后每个页面都有可能(几乎是固定的)成为当前页面。

PageRank 背后的假设是,在平稳分布中最有可能的页面也一定是最重要的(我们经常访问这些页面,因为它们从在这个过程中也经常被访问的页面接收链接)。然后,静态概率分布为每个状态定义了 PageRank 的值。

玩具的例子

为了让这一切更清楚,让我们考虑一个玩具的例子。假设我们有一个很小的网站,有 7 个从 1 到 7 的页面,页面之间有链接,如下图所示。

为了清楚起见,在先前的表示中没有显示每个转换的概率。然而,由于“导航”被认为是完全随机的(我们也谈论“随机行走”),使用简单的以下规则可以容易地恢复这些值:对于具有 K 个外部链接的节点(具有 K 个到其他页面的链接的页面),每个外部链接的概率等于 1/K。因此,概率转移矩阵由下式给出

其中 0.0 值已被替换为“.”为了可读性。在任何进一步的计算之前,我们可以注意到,这个马尔可夫链是不可约的,也是非周期的,因此,在长期运行之后,系统收敛到一个平稳分布。正如我们已经看到的,我们可以通过求解下面的左特征向量问题来计算这个平稳分布

通过这样做,我们获得了每页的 PageRank 值(稳定分布的值)

PageRank values computed on our toy example that contains 7 pages.

这个小网站的页面排名是 1 > 7 > 4 > 2 > 5 = 6 > 3。

外卖食品

这篇文章的主要观点如下:

  • 随机过程是随机变量的集合,通常随时间进行索引(索引通常代表离散或连续时间)
  • 对于随机过程,马尔可夫性质表示,给定现在,未来的概率独立于过去(该性质也称为“无记忆性质”)
  • 离散时间马尔可夫链是具有离散时间指标的随机过程,它验证了马尔可夫性
  • 马氏链的马氏链性质使得对这些过程的研究变得更加容易,并且允许导出一些有趣的显式结果(平均重现时间,平稳分布…)
  • 对 PageRank 的一种可能的解释(不是唯一的解释)在于想象一个网上冲浪者随机地从一个页面导航到另一个页面,并且将页面上的诱导的稳定分布作为排名的一个因素(粗略地说,处于稳定状态的最常被访问的页面必须是由其他非常常被访问的页面链接的页面,然后必须是最相关的)

最后,让我们再一次强调,在处理随机动态时,马尔可夫链对于问题建模是多么强大。由于其良好的特性,它们被用于各种领域,如排队理论(优化电信网络的性能,其中消息必须经常竞争有限的资源,并且当所有资源都已被分配时被排队)、统计学(众所周知的“马尔可夫链蒙特卡罗“随机变量生成技术是基于马尔可夫链的”)、生物学(生物种群进化的建模)、计算机科学(隐马尔可夫模型是信息论和语音识别中的重要工具)以及其他。

显然,马尔可夫链在建模和计算方面提供的巨大可能性远远落后于这篇适度的介绍,因此,我们鼓励感兴趣的读者阅读更多关于这些完全在(数据)科学家工具箱中占有一席之地的工具的信息。

感谢阅读!

Baptiste Rocca 写的其他文章:

[## 机器学习中不平衡数据集的处理

面对不平衡的班级问题,应该做什么,不应该做什么?

towardsdatascience.com](/handling-imbalanced-datasets-in-machine-learning-7a0e84220f28) [## 整体方法:装袋、助推和堆叠

理解集成学习的关键概念。

towardsdatascience.com](/ensemble-methods-bagging-boosting-and-stacking-c9214a10a205)

posted @ 2024-10-13 15:31  绝不原创的飞龙  阅读(585)  评论(0)    收藏  举报