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)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值