TowardsDataScience-博客中文翻译-2022-二十六-
TowardsDataScience 博客中文翻译 2022(二十六)
神经网络实际上是如何工作的——Python 实现第 2 部分(简化)
在这篇文章中,我们继续揭穿神经网络是一个我们不太明白其工作原理的黑箱的理论。我们的目标是以一种容易理解的方式实现神经网络。万一有些概念不能马上讲清楚,请查阅参考资料部分的前几篇文章。
在本文结束时,您应该能够在给定输入数据的情况下,通过一个具有许多功能和训练示例的网络实现数据的单次转发。
让我们从数据和我们将使用的神经网络架构开始。
数据和神经网络架构
我们将使用包含 3 个特征和395
训练示例的数据,如下图Figure 1
所示。神经网络是浅层的-它在输入层有 3 个节点(因为我们有 3 个特征),一个 4 个神经元的隐藏层,和一个输出神经元。
图 1: 数据和神经网络。该数据包含 3 个特征(x1、x2 和 x3)和 395 个以 y 为因变量的示例。该网络是一个 3–4–1 NN,即具有 3 层的 NN——3 个输入值,4 个隐藏层节点,1 个输出值(来源:作者)。
参数初始化
为了执行向前传递,我们需要定义参数(权重和偏差)的初始值。我们将从标准正态分布中随机生成所需的权重,并将偏差设置为零。进行参数初始化时,最重要的概念是确保权重和偏差矩阵具有所需的维数。在执行矩阵乘法时,尺寸错误会给我们带来问题。
概述重量和偏差矩阵的尺寸(参见链接)
初始化参数时,有两条规则需要考虑:
等式 1:权重和偏差矩阵的维数(来源: Post )。
- 层
**l**
(**wˡ**
)的权重矩阵将具有****(nˡ, n^(l-1))**
的维度,即wˡ
的行数将等于当前层l
中神经元的数量,列数将等于前一层l-1
中神经元的数量。** - 偏置矩阵将有
**nˡ**
行和 1 列。这只是矢量引用:上一篇。 - 例如,在我们的例子中,我们在隐藏层需要 4 乘 3 的权重矩阵。请记住,我们在输入层不需要权重,因为那里不发生任何计算,我们只是传递输入值。
注 1: 输入数据必须为(n,m)维,其中 n 为特征数,m 为训练样本数。也就是说,每个训练示例将作为输入矩阵 x 中的一列出现。
符号:本文中,
dim(A)=(r, c)
表示矩阵A
的维数为 r 乘 c,其中 r 为行数,c 为列数。nˡ是层 l 中神经元的数量。在上面所示的架构中,n⁰=3
、n¹=4
和n²=1
。
参数初始化之后,接下来要做的事情是执行实际的计算。
实际计算
在任何给定的层 l,进行以下两个计算:
等式 2: 在第 1 层完成的计算。在等式 2–1 中,权重矩阵与输入矩阵相乘并添加偏差,而在第二个等式中应用激活。
等式 2–1:权重矩阵与输入相乘,并添加偏差。注意,这里的输入可以是实际的输入值,也可以是前一层l-1
的值。这些方程的计算需要我们理解矩阵乘法和矩阵加法。如果A
中的列数等于B
中的行数,则两个矩阵A
和B
可以相乘为A·B
。记住A·B
和 B·A
不一样(矩阵乘法不可交换)。此外,相加的两个矩阵必须具有相同的维数。
等式 2–2:激活函数gˡ
应用于Equation 2–1
的结果,成为l
层的输出。请注意,在生成的矩阵/向量上使用激活不会影响其维度。
现在让我们将所有这些放入 Python 代码中
对于每一层,我们将初始化参数,然后执行所需的计算。在输入层,即层0
没有计算发生,因此我们直接进入隐藏层,即层1
。
第 1 层的计算
(参考Equation 1
中的规则)对于隐藏层,layer 1
,我们需要一个维度为(n¹,n⁰)
的权重矩阵(即当前层的神经元数乘以上一层的神经元数。这是 4 乘 3。我们需要(n¹, 1)
作为偏差,也就是 4 乘 1。为了便于打印出数据,我们现在不使用本文开头定义的数据(我们将在本文后面这样做)。我们将使用下面的子集。
图 2: 将输入数据转换成输入矩阵。输入矩阵的每一行都包含特征数据。如果每一行都包含训练示例,我们需要转置 x ,然后乘以权重矩阵(来源:作者)。
输出:
X: [[ 9 14 10 11 8]
[ 9 16 8 12 9]
[ 9 16 7 10 9]]
X shape: (3, 5)
w1: [[-0.14441 -0.05045 0.016 ]
[ 0.08762 0.03156 -0.20222]
[-0.03062 0.0828 0.02301]
[ 0.0762 -0.02223 -0.02008]]
w1 shape: (4, 3)
b1: [[0.]
[0.]
[0.]
[0.]]
第 1–5 行:导入所需的包,并定义输入数据。输入数据X
具有维度(3, 5)
,3 个特征和 5 个训练样本。
回忆(特征数量影响输入层神经元数量):输入层神经元数量始终等于特征数量,因此,我们在输入层有 3 个神经元。
第 7–12 行:根据Equation 1
中的两条规则初始化参数。dim(w¹) = (n¹, n⁰) = (4,3)
。
输出:
f11 shape: (4, 5)
w2: [[0.01866 0.04101 0.01983 0.0119 ]]
w2 weights: [[0.01866 0.04101 0.01983 0.0119 ]]
b2: [[0.]]
y0: [[0.03629 0.03134 0.04005 0.03704 0.03582]]
y0 shape: (1, 5)
y_hat: [[0.50907 0.50783 0.51001 0.50926 0.50895]]
y_hat shape: (1, 5)
第 1–2 行: w1 乘以输入矩阵x
。dim(w1)=(4, 3)
和dim(x)=(3, 5)
,因此dim(w1·x)=(4,5)
基于矩阵乘法的规则。
注 2: 最初,我们说(而且是矩阵加法的一个规则)两个矩阵 A 和 B 只有维数相同才能相加。但是
dim(w¹·x)=(4, 5)
但是dim(b¹)=(n¹, 1) =(4, 1)
然而我们在第 1 行添加了它们。这是为什么呢?Numpy 包裹来救我们了。“广播一词描述了 NumPy 在算术运算过程中如何处理不同形状的数组。在某些约束条件下,较小的阵列在较大的阵列中“广播”,以便它们具有兼容的形状。来源: Numpy 文件。
在阵列广播之后,dim(b¹)
变成了(4,5)
,因此,z11=w¹·x+b¹
也变成了 4 乘 5 的矩阵。
第 4 行到第 10 行:应用 Sigmoid 激活来获得第 1 层 f11 的输出。这是该层中所有神经元的输出。
第 12–24 行:显示了输出层的计算。如预期的dim(w²)=(n², n¹)=(1, 4)
和dim(b²)=(n², 1)=(1, 1)
。这里我们还需要应用数组广播的概念。
注 3: 输出为 1 乘 5 矩阵。你期望你期望的是一个单一的数字吗?请记住,此输出是我们数据中所有 5 个训练示例的预测向量。换句话说,使用 Numpy 允许我们以如此高效的方式通过网络传递所有的训练示例。不要担心输出向量上的值,因为这只是数据基于随机初始化的权重通过网络的一次传递。
我们需要在模型学习的训练期间优化参数值。训练网络需要前向传递/传播(如本文所讨论的)和反向传播。后者允许我们使用一些损失函数来评估模型,计算函数相对于参数的偏导数,并相应地调整参数值。这个过程是迭代的,通过网络传递整个数据集(正向传递)和反向传递(反向传播)的过程构成一个完整的迭代。这就是所谓的新纪元。我们将在接下来的文章中讨论所有这些。
在我们结束之前,让我们写一些代码,对开始提到的数据集进行一次完整的前向传递(我们将直接从https://kipronokoech.github.io/assets/datasets/marks.csv加载数据)。
输出:
w1 shape: (4, 3)
w2 shape: (1, 4)
X shape: (3, 395)
w1 shape: (4, 3)
b1 shape (4, 1)
w2 shape: (1, 4)
b2 shape (1, 1)
f1 shape (4, 395)
z2.shape (1, 395)
yhat shape (1, 395)
关于上面的代码,有几点需要注意:
- 我们需要传递维度为
(# features, # training examples)
的输入特征数据。通常,在熊猫数据帧(df
)中,我们在行中有训练示例,在列中有特征,但我们需要输入矩阵中的数据,因此我们转置了第 107 行的X
。 - 正向传递的输出
yhat
是所有训练示例的预测向量。出于这个原因,我们对数据上的 395 个训练例子进行了yhat(1, 395)
。 - 此时,我们没有使用目标变量(
y
)。我们将在反向传播和模型评估中使用它。
参考资料:
我们已经在前一节中讨论了单个神经元的计算。本文讨论了一个完整的浅 3-4-1nn 的单前锋传球。接下来,我们的重点将是理解反向传播。
请以每月 5 美元的价格注册 medium 会员资格以便能够阅读我和其他作者在 medium 上的所有文章。
你也可以订阅,当我发表文章时,你可以把我的文章发到你的邮箱里。
感谢您的阅读,欢迎下次光临!!!
神经网络的实际工作方式— Python 实现(简化)
对于很多人来说,神经网络(NN)是一个黑匣子。我们知道它的工作原理,但我们不明白它是如何工作的。本文将通过一些例子来展示神经网络实际上是如何工作的,从而揭开这一信念的神秘面纱。如果这篇文章中有些术语不太清楚,我已经写了两篇文章来涵盖真正的基础知识:第一篇和第二篇。
数据和架构
在第一个示例中,让我们考虑一个简单的情况,其中我们有一个包含 3 个特征、一个目标变量和一个训练示例的数据集(实际上我们永远不会有这种数据,但是,这将是一个非常好的开始)。
事实 1:数据的结构影响建模所选择的架构。事实上,数据集上特征的数量等于输入层中神经元的数量。在我们的例子中,如下图所示,我们有 3 个特征,因此架构的输入层必须有 3 个神经元。
隐藏层的数量影响学习过程,因此根据应用来选择。具有几个隐藏层的网络被称为深度神经网络(DNN)。在这个例子中,我们正在处理一个浅层神经网络。我们在输入/第一层有 3 个神经元,在隐藏层有 4 个神经元,在输出层有 1 个神经元,这是一个 3–4–1 神经网络。
图 1 —左:数据,右:神经网络架构(来源:作者)。
记号
让我们先设置一些符号,这样我们就可以毫不含糊地使用它们。为此,让我们重新绘制上面的体系结构,以显示神经网络中使用的参数和变量。
图 2:带有变量和参数的 3–4–1 神经网络我们需要在给定输入值的情况下计算输出ŷ(来源:作者)。
以下是我们将使用的符号:
- x⁰ᵢ-iᵗʰ输入值。输入层(层 0)的特征 I 的值,
- nˡ——l 层中的神经元数量。如图 2 所示,第一/输入层有三个神经元,n⁰ =3,第二/隐藏层有 4 个单元,因此 n =4,最后,对于输出层,n =1。网络中有 L 层。在我们的例子中,L=2(记住,我们不把输入算作一个层,因为这里不发生任何计算),
- m——训练样本的数量。在我们的例子中,m=1,
- wˡⱼᵢ
- 第一层中 jᵗʰ神经元的 zˡⱼ加权输入,
- f ˡ ⱼ gˡ是层 l 的激活函数,
- bˡⱼ——l 层 jᵗʰ神经元上的偏置****
矩阵和矩阵运算
为了有效地进行神经元运算的计算,我们可以使用矩阵和向量作为任何给定层的输入、权重和偏差。我们现在将有以下矩阵/向量和运算:
- 输入为 x,
- 权重作为矩阵 wˡ到达层 l,
- 层 1 中的偏差为矢量 bˡ,
- zˡ = wˡ∙f^(l-1)—是层中所有神经元的加权输入,l . Medium.com 在格式上有限制。f 是来自前一层的输入的幂(l-1)。
- 点积-对于任意两个等长的向量 a 和 b,点积 a∙b 定义为:
等式 1:点积 a∙b(来源:作者)。
aᵢ bᵢ是向量 a 中的 iᵗʰ元素和 b 中的 iᵗʰ元素之间的标量乘法*
- f ˡ = gˡ(zˡ+bˡ)将是层 l 的输出
矩阵乘法
两个矩阵只有兼容才能相乘。当且仅当第一个矩阵的列数等于第二个矩阵的行数时,称两个矩阵相乘是相容的。因此,对于 A(m,n)和 B(n,p),那么 A∙B 的阶为(m,p)(见下图 2)。
图 3: Multix 乘法(来源:作者)。
重要提示:矩阵乘法是不可交换的,也就是 A∙B 不等于 B∙A,要确定你是按照正确的顺序把它们相乘。
矩阵加法
两个矩阵 A 和 B 只有在维数相同的情况下才能相加,比如说 A(m,n),那么 B 也一定是(m,n)阶的,结果 A+B 也是(m,n)维的。
在我们的网络中利用矩阵运算需要我们为输入、权重和偏差找到合适的维度。
单个神经元的计算
为了演示在一个神经元中完成的计算,让我们考虑在隐藏层的第一个神经元中的计算(注意,权重是随机生成的,并且在开始时将偏差设置为 0)。在本节中,我们基本上假设我们有一个单神经元网络,即 3–1 个神经元。
图 4:单个神经元——隐藏层的第一个神经元(来源:作者)。
在这种情况下,我们有 3 个输入值 5、6 和 6,以及相应的权重 0.01789、0.00437 和 0.00096。神经元通过计算 z ₁₁来衡量输入,加上偏差 b ₁₁,最后,对结果应用激活函数(我们将使用 sigmoid 函数)来获得 f ₁₁,从而产生输出。
加权输入:
等式 2:加权输入是相应输入值和权重的乘积之和。这相当于 1×3 权重矩阵和 3×1 输入矩阵/向量之间的点积。
z¹₁₁ = (0.01789*5) + (0.00437*6) + (0.00096*6) = 0.12143
添加偏置,然后应用 sigmoid 激活函数:
Sigmoid 激活函数
f¹₁₁ = g(z¹₁₁+b¹₁₁) = g(0.12143+0) = 1÷(1+e^(−0.12143)) = **0.530320253**
这个神经元输出 0.5303。
把这个放到 Python 代码中
首先,我们需要随机生成权重,并将 bias 设置为零。
输出:
**Weights: [[0.01789 0.00437 0.00096]]
Weights shape: (1, 3)
Bias: [[0.]]
Bias shape: (1, 1)**
第 1–4 行:导入 numpy,设置其输出值的精度为小数点后 5 位。除非明确设置了另一个精度级别,否则 numpy 在第 3 行后执行的所有计算都将保留 5 位小数。
第 5–8 行:在第 6 行,一个随机种子被设置为 3(可以是任何数字)。播种确保生成的随机数是可预测的,即每次运行代码时生成的随机数都是相同的。第 8 行实际上使用标准的正态分布生成随机数。为什么要乘以 0.01?我们希望该数字较小(介于 0 和 1 之间)。我们将在下一篇文章中对此进行更多的讨论
第 11–14 行只打印出矩阵的参数值和尺寸(参见下文,了解权重和偏差矩阵形状的调整,非常重要!!!)
>>>尺寸重要说明<<<
We need to get dimensions of weights and biases matrices correctly. Given the number of neurons in each layer, the dimension for the matrices can be deduced as:
Dimensions for matrices of weights and biases (Source: Author).
- The weights matrix for layer l (wˡ) will be of dimension (nˡ, n^(l-1)), that is, wˡ will have the number of rows equal to the number of neurons in the current layer, l, and the number of columns will be equal to the number of neurons in the previous layer, l-1.
- The bias matrix will have nˡ rows and 1 column. This is just a vector.
In our network, we have n⁰=3 input values and n¹ =1 neuron in the output, therefore, dim(w¹) = (n¹, n⁰) = (1, 3) and dim(b¹) = (n¹, 1) = (1,1). Hope this justifies the choice of shapes for the matrices of weights and biases.
Next is to multiply weights with input, add bias and apply sigmoid function.
输出:
**input shape: (3, 1)
f11: [[0.12141]]
The output: [[0.53032]]**
第 1–4 行定义输入并打印形状。如果不对输入进行整形,结果将是 shape (3,)的数组。应该避免称为秩 1 数组的(,)性质的数组,因为它们会在矩阵乘法过程中引起问题。reshape(-1,1)函数告诉 numpy 根据给定的值的数量动态设置数组的行数并保持列数为 1。在我们的例子中,我们有 3 个输入值,因此我们有(3,1)作为输入形状。*
第 5 行到第 13 行 —将权重矩阵与输入矩阵相乘以获得加权输入并添加偏差,然后对结果应用 sigmoid 激活。当乘以第 6 行中的矩阵时,注意顺序——TT 是权重矩阵乘以输入,而不是相反(还记得上一节中的矩阵乘法规则吗?).
并且输出为 0.5303 。注意,它与我们之前得到的相匹配。
将代码放在一起
现在让我们把所有这些放在一起
输出:
**Weights: [[0.01789 0.00437 0.00096]]
Weights shape: (1, 3)
Bias: [[0.]]
Bias shape: (1, 1)
input values: [[5]
[6]
[6]]
input shape: (3, 1)
output [[0.53032]]**
OneNeuronNeuralNetwork 类有两个参数——权重和偏差——由 magic/dunder 函数 init 初始化。
每次从类中创建对象时,都会调用 init 函数。init 方法让类初始化对象的属性,没有其他用途——来源:Udacity.com
我们使用 sigmoid_function 作为静态方法,因为它是一个普通的函数,不必接收第一个参数“self”。我们只是把它放在课堂上,因为它与这里的内容相关,否则就不是强制性的了。
正向传递中整个网络的计算
我们在上一节已经讨论了单个神经元的计算。在下一篇文章的中,我们将讨论在给定一些数据的情况下,整个网络如何执行单次转发。
请以每月 5 美元的价格注册成为 medium 会员,以便能够在 medium 上阅读我和其他作者的所有文章。
感谢您的阅读,欢迎下次光临!!!
NLP 是如何在医疗保健信息学中得到利用的
原文:https://towardsdatascience.com/how-nlp-is-being-leveraged-in-healthcare-informatics-283a53c8035e
医疗保健行业仍有如此多的非结构化文本数据可供利用
来自像素的免费使用照片
动机
医疗保健是“影响”可见且具体的领域之一。你看到人们的生命得到拯救,生活质量得到改善,并找到了治愈困扰不同人群数十年的疾病的方法。有许多报告和论文讨论了医疗保健信息学和人工智能(AI)市场不断增长的规模。其中一位来自 B2B 研究公司 Markets and Markets,他估计今年全球自然语言处理(NLP)在医疗保健和生命科学领域的市场规模为18 亿美元。它还提到,该市场预计将增长,到 2026 年价值将达到 43 亿美元。自然,将最先进的技术引入这一领域的努力至少从三十年前就开始了。在我看来,医疗保健领域仍有许多未开发的工作领域,数据科学、人工智能和新技术可以在降低成本、提高流程效率和透明度以及改善治疗和诊断方面发挥关键作用。特别是,由于医疗保健中产生的大量非结构化文本数据,自然语言处理方法变得更加重要。
在这篇文章中,我研究了可以在医疗保健中使用的各种数据源,NLP 如何在各种操作中使用和利用的应用,以及在医疗保健中使用 NLP 可以获得什么好处。这篇文章希望对那些正在考虑攻读医疗保健信息学学位的人或任何想进行研究或进行涉及健康相关数据集的附带项目的人有所帮助。
医疗保健中的数据源
EMR 和 EHR
电子病历(EMR)和电子健康记录(EHR)是医疗保健领域的经典数据源。例如,MSIS 和 TMSIS 数据库是由美国社会安全局管理的。它们包含关于医疗补助接受者的信息、他们的人口统计信息和各种健康指标。最终的缺点是由于安全和隐私的限制,很难访问数据。通常,这些数据存储在安全的飞地中,只允许授权用户使用特殊的身份验证方法访问它们。即使是这些授权用户,当他们想要使用数据时,也经常被要求访问和停留在保护这些数据的数据中心。
其他非结构化临床数据
除了 EMR 和 EHR 记录之外,其他临床数据还包括医生和抄写员的笔记、医学图像、医嘱条目和各种管理记录,这些都是日常临床操作的副产品。这些文档包含许多自然语言,这使得 NLP 技术更加有用。然而,它们通常是非结构化的,所以您需要注意细节,以确保从这些文档中解析出的信息是准确的。
保险数据
保险数据包括关于每个保险产品所包含的特定保单和索赔记录的信息。分析保险数据与其他健康记录的组合将能够为患者提供更个性化的治疗和保险产品。
审查数据
由于物联网技术的出现,健康监测应用程序(如 FitBit)生成的数据现在与云同步,公司和机构可以实时访问这些数据。这是一种以前没有的大数据。然而,用户必须更加谨慎地对数据做出假设,因为与在受控实验或调查环境中收集的数据相比,数据更容易出现各种统计错误。例如,从 FitBit 收集的数据可能不代表研究人员希望了解的整体兴趣人群,因为此类应用程序的用户可能有不同于平均人群的特定倾向。
社会化媒体
社交媒体是研究人员以前无法获得的另一个有价值的数据来源。推文、Meta 和 Instagram 帖子中的评论、来自 reddit 和 buzzfeed 的文本数据都是社交媒体数据的例子。这些是有价值的,因为它们有时是疾病爆发、暴力、精神健康问题等的前兆。或者针对某些话题指向特定的舆论。请看这篇论文,例如,它讨论了使用实时社交媒体数据来检测和远程监控艾滋病结果的方法。[2]
自然语言处理在医疗保健中的应用及其收益
降低成本
许多患者依靠电话来获得诊断或与临床机构交流。在这个过程中会产生巨大的成本。结合 NLP 和深度学习方法制作的移动应用程序或聊天机器人可以解决这个问题。
提高行政事务的效率
可以利用 NLP 方法从医生笔记、医疗政策文档等中提取信息。这将实现高效的计费、准确的预先授权批准和医疗政策评估[3,4,5,6]。
NLP 对于组织各种文档也很有用。在临床过程中会产生大量的医疗文档。假设医生或医学研究人员想要查阅过去 8 年中与疾病 X 相关的所有笔记,那么除非有一个“文档分类和标记”系统,否则很难找到这些资源。编纂医疗程序和治疗方法也很有价值。使用特定的“代码”将有助于医生、保险公司和管理人员更容易地相互沟通,而不必参考复杂的术语。在这些情况下,包括主题建模和语料库分类在内的 NLP 方法可以派上用场。最后,当快速响应和效率很重要时,汇总文档是必要的。围绕提取一段文本的要点的语料库摘要技术的 NLP 研究在最近二十年中已经取得了很大的进展,因此有助于摘要更专业的内容,例如医生笔记。
治疗最优化
医生需要做两件事来优化对个体患者的治疗——个体的具体特征和他们如何体验疾病的细节。为了获得这些信息,医生和病人之间应该进行坦诚的对话。然而,由于各种各样的原因,从对陌生人敞开心扉的焦虑到害怕被评价等等,这些对话经常不会发生。患者有时会更放心地与他们信任的人或相处时间较长的人交谈,包括亲密的朋友和家人。但更重要的是,他们经常在社交媒体上畅所欲言,分享自己的真实感受和经历。在某种程度上,社交媒体已经成为一个类似日记的空间,人们在这里写下他们的日常生活,分享他们的实际意见,以获得网络上其他人的支持和同情。这就是社交媒体非常有价值的原因。
我们可以使用 NLP 方法分析患者在社交媒体上发表的帖子和评论,从这种分析中获得的见解有助于医生确定要强调的积极结果和要跟进的消极结果。[5]此外,将病人告诉医生的话与他们告诉自己亲密圈子里的人的话进行比较,可以帮助医生确定他们如何才能改善病人与临床医生之间的沟通。
预防
许多新形式的非结构化数据,如来自社交媒体的帖子和评论,往往可以指向更大的健康趋势。它们的范围从某些司法管辖区的阿片类药物滥用模式到某个国家某些年龄组自杀风险的增加。例如,应用于社交媒体数据的 NLP 方法已被证明是筛选自杀风险和疾病爆发的有效方法。看看这张纸。[7]
我们研究另一个关于川崎病(KD)的例子。具有 NLP 功能的 CDSS(计算机化临床决策支持系统)已经证明了其提醒临床医生在紧急情况下考虑川崎病(KD)的潜力。[3,4,5,6]这种 NLP 工具在 22 例后来被诊断为 KD 的患者的急诊科总结中进行了培训。然后,它被应用到 253 份急诊病历中,这些病历都是关于被诊断为 KD 或其他发热性疾病的儿童的。在识别 KD 高可能性患者的任务中,该工具的敏感性得分为 93.6%,特异性得分为 77.5%。
偏置
当然,NLP 并不是解决医疗保健领域所有问题的神方法。我们需要考虑和警惕的一个主要问题是“算法偏差”。在我们用于 NLP 的许多临床数据源中,一定存在多种偏差。例如,医生的偏见将被嵌入到医生笔记中。自然,使用这些数据源得出的结果和分析在某种程度上也会包含数据中的相同偏差。在大多数情况下,这种偏见会被强化。这就是为什么许多人机交互(HC)研究越来越多地关注如何使算法更加透明、可解释,并且不受渗透到所使用数据中的偏见的影响。
参考
[1] 医疗保健和生命科学市场中的 NLP(2021),市场和市场
[2] S. Young,C. Rivers,B. Lewis,使用实时社交媒体技术检测和远程监测艾滋病毒结果的方法 (2014),PubMed
[3] A. Kulkarni,文本分析&医疗保健中的 NLP:应用&用例 (2020),Lexalytics 公司博客
[4] S. Rangasamy,R. Nadenichek,M. Rayasam,A. Sozdatelev,医疗保健中的自然语言处理 (2018),麦肯锡公司博客
[5] R. Attrey,A. Levit,自然语言处理在医疗保健中的前景 (2018),西安大略大学医学杂志
[6] 自然语言处理在医疗保健领域的 14 大用例,马鲁蒂理工大学实验室
[7] G. Coppersmith,R. Leary,P. Crutchley 和 A. Fine,社交媒体的自然语言处理作为自杀风险的筛选 (2018),生物医学信息学见解
关于作者
数据科学家。在密歇根大学刑事司法行政记录系统(CJARS)经济学实验室担任副研究员。即将入学的信息学博士生。他喜欢运动、健身、烹饪亚洲美食、看 kdramas 和制作/表演音乐。结帐他的 网站 !
如何不被时间序列模型所迷惑
原文:https://towardsdatascience.com/how-not-to-be-fooled-by-time-series-forecasting-8044f5838de3
知道什么时候你看到的是看起来准确的预测,什么时候预测实际上非常准确
尼古拉斯·卡佩罗在 Unsplash 上的照片
很容易被时间序列模型骗。我见过能够(似乎)准确预测最随机趋势的模型,如股票和密码价格,使用的是大多数人不完全理解的先进技术。时间序列在这方面真的像魔术一样吗?执行正确的数据操作,应用足够复杂的模型,很快,对未来任何日期索引线的预测都惊人地准确?
如果你看到了我所描述的同样的事情,并且持怀疑态度,你有这种感觉是对的。通常发生的情况是,分析师正在传递一系列单步预测,这些预测在数据的验证切片上看起来是准确的。分析师得出结论,他们创建的模型足够强大,可以准确预测未来的许多时期。这可能会有意或无意地发生——如果要我猜的话,我会说大多数分析师,他们通常会看到基于横截面数据构建模型的例子,从来没有想过向数据集添加时间元素可能会对他们的模型产生什么影响。时间序列不同于其他机器学习,必须采取额外的预防措施,否则结果会令人误解。
自相关的作用
一部电视剧的现在通常与其过去高度相关。这被称为序列的自回归(AR)特性,或自相关。具体来说,任何给定的值都可能非常接近它之前的值。
这一事实的含义比它们初看起来更深刻。让我们考虑一个线性模型,它有一个自回归分量、一个趋势分量和一个季节分量,例如:
作者图片
该函数表示前一个值(x_{t-1}
)乘以因子α,序列的“季节性(s_t
)、序列的“趋势(t_t
)和误差项(e_t
)确定序列中的下一个值。假设您想将该模型应用于真实数据,特别是预测未来 10 个月的数据。你有 100 个月的观察时间来做这件事:
作者图片
作者图片
数据有了,就准备模型吧。要从列出的方程中获得第一项,即自回归项,我们可以使用 pandas 的shift()
方法:
data['AR1'] = data['Target'].shift()
对于季节性,我们可以使用傅立叶变换,而不是使用月份值,傅立叶变换使用波函数来模拟季节性:
data['MonthSin'] = data['Month'].apply(
lambda x: np.sin(np.pi * x/(12/2))
)
data['MonthCos'] = data['Month'].apply(
lambda x: np.cos(np.pi * x/(12/2))
)
最后,我们可以使用数据集中已经存在的year
变量来模拟趋势。
现在,我们有了我们需要的所有三个组成部分:前一个序列的价值(x_{t-1}
)、趋势(t_t
)和季节性(s_t
)。我们假设误差项(e_t
)是随机的,无法建模。所以,让我们写一个正常的机器学习管道,看看会发生什么。
data_processed = data[
[
'Target',
'AR1',
'MonthSin',
'MonthCos',
'Year'
]
].dropna()
data_processed.head()
作者图片
我们使用 scikit-learn 来分割我们的数据,这样最后 10 个观察值就在测试集中。
y = data_processed['Target']
X = data_processed.drop('Target',axis=1)
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=10, shuffle=False
)
剩下的就是小菜一碟了。训练线性模型:
lr = LinearRegression()
lr.fit(X_train,y_train)
对看不见的测试数据进行预测:
pred = lr.predict(X_test)
最后,评估误差:
mean_absolute_error(y_test,pred)
这将返回值 3.8。我们甚至可以画出结果。
sns.lineplot(
y='Target',
x='Date',
data=data.reset_index(),
label='actuals',
)
sns.lineplot(
y=pred,
x=data.index[-10:],
label='predictions',
)
plt.rcParams["figure.figsize"] = (8,6)
plt.show()
作者图片
看起来相当不错!假设您向您的主管展示了该模型,他们同意该模型是准确的,并且应该实施。但是等等,一个问题。该模型严重依赖上一个序列的值来预测下一个值。如果我们不知道所有十个步骤的前一个值,我们如何将这个模型扩展到未来呢?
做到这一点的一种方法是扩展我们的方程,以便可以使用多步骤过程动态评估线性模型。考虑在原始等式中,不是使用实际的过去值作为输入,而是使用过去值的预测,因此第二预测步骤可以写成:
作者图片
更一般地说,我们可以说:
作者图片
其中 j 是预测范围内的任意时段。这是将你的预测延伸到未来时期的可靠方法。问题解决了。除此之外,我们遇到了两个问题:
- 为此,编写预测评估程序需要做大量的额外工作。
- 我们的模型没有经过这种方式的测试,所以测试集度量可能会产生误导。
我们可能认为第二点没什么大不了的,但实际上,正如我们将看到的,这是一件大事。因为在测试集中,我们知道我们所做的所有 10 个预测的 AR1 值,所以我们报告的错误性能被大大夸大了(或者你可以说缩小了,因为越小越好)。我们的图表也很容易让人误解。这个模型实际上没有那么精确,至少 10 步内没有。
我们可以使用 scalecast 包有效地演示这一点。我们将使用相同的数据并将相同的术语添加到Forecaster
对象中:
from scalecast.Forecaster import Forecasterf = Forecaster(y=data['Target'],current_dates=data.index)f.set_test_length(10)
f.generate_future_dates(10)
f.add_seasonal_regressors('month',sincos=True,raw=False)
f.add_seasonal_regressors('year')
f.add_ar_terms(1)
然后我们称之为模型。但是,我们要用两种不同的方式来称呼它。第一种方法是 scalecast 的默认方法,其中测试集预测是通过我们已经介绍过的动态预测过程进行的。在测试集中,AR1 的值不再是已知的,但相反,它是 10 个步骤中的 9 个步骤的预测值(在步骤 1 中,我们使用实际值,因为我们知道它是什么)。第二个模型将与我们评估的没有 scalecast、非动态评估的模型完全相同,其中我们总是知道测试集中 AR1 的值:
f.set_estimator('mlr')
f.manual_forecast(call_me='mlr_dynamic')
f.manual_forecast(call_me='mlr_non-dynamic',dynamic_testing=False)
然后我们绘制结果图:
f.plot_test_set()
plt.rcParams["figure.figsize"] = (8,6)
plt.show()
作者图片
上图中的红线是我们之前评估的模型,同样的趋势,同样的预测值。橙色线是我们用同样的输入获得的结果,但是是动态测试模型。差别很大!以至于,事实上,测试 MAE 下降到 9.1,或者几乎差 2.5 倍!
f.export('model_summaries')[['ModelNickname','TestSetMAE']]
作者图片
哇哦!现在我们需要解释我们的主管发生了什么事。
更广泛的影响
这意味着什么?我可以用同样的输入运行同样的模型,似乎可以预测任何事情,我是说任何事情,如果我不动态测试误差项的话。下面,显示的图显示了一条红线,它是非动态评估的预测,以及一条橙色线,它显示了模型在完整测试集上的更公平表示,即真正的样本外预测。所有应用的模型都属于多元线性回归类。
标准普尔 500 指数
以下是我对 2021 年开始后不久标准普尔 500 唯一训练数据的预测:
作者图片
我可以预测到它的急剧上升,也几乎可以预测到它开始下跌的准确时间。
比特币
2021 年 12 月,我本可以预测到最近的比特币崩盘:
作者图片
新冠肺炎(新型冠状病毒肺炎)
通过使用一个主要机场的航班乘客作为代理,我可以预测到 2015 年新冠肺炎疫情航空旅行的下降,以及随后的复苏!!
作者图片
请记住,所有这些模型都是在一个数据集上训练的,并在他们从未见过的数据切片上进行验证。因此,我只能断定,我偶然发现了世界上最强大的模型之一。不错!
如何避免制造误导模型
所以,很明显,我不可能预测到这些事情。但是,我们有多经常看到这样的结果,当实际上,除了一系列单步预测之外,分析师试图传递高度准确的模型?这些模型中有很多没有受到挑战,因为它们是用先进的机器学习算法构建的,或者是由不了解情况的分析师构建的。无论它们看起来多么花哨,无论它们的解释多么雄辩,高级模型,包括递归神经网络和 LSTMS,都不是魔法。他们无法预测不可预知的事情。这并不意味着没有高智商的人在用它们做着不可思议的工作,只是意味着当它们被不正确地应用时,它们会变得极具误导性。
所以,现在我们知道不该做什么了。在第二部分中,我们探索了可以帮助我们建立不会欺骗的高效时间序列模型的验证技术。它们在测试集上看起来不那么准确,但它们更擅长预测未来,这正是我们在预测时真正关心的。因此,如果你感兴趣的话,可以订阅并注册电子邮件通知。本分析中使用的所有数据都是虚构的,通过公共 API 获得,或者通过麻省理工学院许可获得。看到这里的笔记本我创造的。
如何(不)做 MLOps
原文:https://towardsdatascience.com/how-not-to-do-mlops-96244a21c35e
凯文·Ku 在 Unsplash 上的照片
如何(不)做 MLOps
最初发表于我的博客。
我的公司——嗯,我的团队——组织了一个叫做读报俱乐部的组织。这个想法是让我们每个人向整个团队提交一篇论文,我们觉得这篇论文很吸引人,并且与我们的工作相关。因此,对于几周前举行的论文展示会议,我决定展示“使用反模式避免 MLOps 错误”。
自去年以来,我们一直在关注 MLOps 和 ML Engineering。我主要是一名数据科学家,但也是 MLOps 团队的一员,我发现这篇文章与我们的工作非常相关。
“正如设计模式编纂最佳软件工程实践一样, 反模式 提供了一个词汇来描述有缺陷的实践和方法。”
这些实践包括整个 ML 模型部署生命周期的步骤,包括性能跟踪、监控等部署后任务。定义了九种反模式。我也加入了我在建造模型和大规模部署它们的经验中的一些想法。
💡还有一个关于 数据交换 的不错的播客,你可以听听。
现在从这些反模式开始…
数据泄露
我们试图避免的最大和最常见的问题之一是数据集中的信息泄露。模型使用了不应该使用的数据/信息(或在推断过程中不可用的数据/信息),这在我们的评估阶段给了我们不正确的结果。当训练-测试分割不是按顺序进行时,时间序列数据也容易出现这种情况。对于不平衡数据,执行不正确的过采样是另一个例子——在将数据分成训练集和测试集之前进行过采样。其他示例包括预处理阶段,在训练测试分割之前,再次执行标准归一化。
立即行动,不要反思
大多数时候,来自我们模型的预测被直接使用,没有任何检查、过滤甚至检验。这导致围绕概念漂移和错误预测的问题。
避免这种情况的一个好方法是定义系统和过程来研究数据和预测的偏差。数据漂移仪表板—可以监控和跟踪数据指标的简单仪表板在这里非常有用,即使是手动检查。预测也可以通过这样的仪表板,简单的聚合指标和图表可以用来跟踪预测的分布。如果在违反某些阈值时发出警报,就可以避免大量的调试工作。
地毯下的调谐
虽然我不一定理解这是严格的反模式,但我绝对认为这是一个很好的指导原则,可以节省大量的金钱和时间。这与超参数是如何调整的有关。作者提出,超参数空间的随机搜索(在定义的范围内)产生了计算上廉价并且与网格搜索等效的替代方案。这会给你的迭代(周期)和成本带来很大的不同。记录与超参数相关的一切也是非常重要的,以便它是可重复的(包括使用的随机种子)。
我个人发现像权重和偏见和 Neptune.ai 这样的工具在这里非常有用。这些工具成倍地增加了你的实验周期,这是在大多数公司应用 ML 解决问题时最重要的实践。
PEST——感知的经验优势
机器学习研究是由理论建议的经验验证和确认驱动的。对应用机器学习研究的新贡献包括(I)验证以前未验证的理论建议,(ii)结合经验验证的新理论建议,或(iii)对现有学习管道的有效扩充,以产生改进的经验性能。作者提到,通常新提出的 ML 方法的经验验证是不充分的,有缺陷的,或发现有所欠缺的,这导致了术语 PEST 的定义。他们谈到需要相同的实验管道来比较和评估 ML 模型。
不良信用转让
该反模式讨论了未能正确识别性能提高的原因。虽然您的模型架构和那些超级调整的超参数将提升您的性能,但未能将(可能的)收益归因于其他任务,如巧妙的问题表述、某些预处理步骤等。可能会导致未来的问题。
扩展前面提到的数据漂移仪表板,并使用实验跟踪工具,人们应该能够从部署的每个模型中定义推论,以便能够适当地进行属性划分。
给自己的考试打分
这些都是不正确的评估和验证实践所带来的问题。测试和评估数据应独立采样,对于稳健的性能分析,应在模型开发完成之前保持隐藏,并且只能用于最终评估。
解决这个问题的一个方法是投资特色商店。这些可以是独立的地面真相系统,由数据管道驱动,定期创建您的训练测试数据集,确保您总是可以有看不见的测试集。
一劳永逸
说到模特训练,我们很多人都是这种心态。这个反模式讨论了概念漂移和建立模型再培训作业和管道的合理需求。围绕贝叶斯模型已经有了一些工作,用于概念漂移的检测和适应。
前面提到的推断仪表板可以帮助捕捉这些漂移,只需通过人工检查。当然,这也可以自动化。
带着矛盾的心情交流
预测很重要,但预测中的不确定性可能更重要。对于基于模型预测做出决策的情况,以及这些决策是否至关重要(与财务、健康等相关)。)那么这些不确定性就变得至关重要了。报告预测不确定性的机制变得很重要,如果出现问题,可以启用后备系统和更有信心的模型。
最后,数据危机即服务
回到特征(数据)存储的概念。每一个产生你的数据的管道都应该被记录下来,并且详细的信息应该被传达。一种有效的方法是构建与要素存储同步的数据目录。这确保了新的管线可以容易地创建和调度,遵守特征存储的预定义标准,并且更重要的是,设置了能够在需要时复制这些管线的过程。这也有助于跟踪数据血统。
作者的建议
几十年来,技术债务一直让工程师望而却步。技术债务对我们来说(读 ML 的人)并不真正与软件工程相关,但它与数据管道、模型管道、模型(再)培训工作、反馈机制等等都有关系。
为了解决这些问题,他们提出了一些具体建议:
- 使用这些反模式来设置流程以避免这些错误
- 使用断言来跟踪数据质量
- 记录数据传承并创建“审计跟踪”
- 出现错误时,使用集合和后备系统
- 在多个层面确保人在回路中的操作能力
如何不和图表撒谎
原文:https://towardsdatascience.com/how-not-to-lie-with-charts-3516b38a680b
数据可视化
如何不和图表撒谎
你可以用数据可视化来告知,或者误传。如果你想做前者,而不是后者,我们会考虑要避免的事情。
改编自著名的短语* —作者的形象
数据被用来说服我们——提出一个论点。数据科学家或数据记者想要讲述一个关于一个想法、一项研究、一个理论、一项新技术的故事。
但有时有一个隐藏的议程。
也许是一个政客在推动一个党派议程,或者是一个营销主管试图销售一种产品,但有时数据的呈现方式是设计师希望你做一些他们想要的事情——也许是为他们的政策投票,或者也许是购买一台新的洗衣机或冰箱。
我们可能希望数据公平地呈现给我们,但情况并非总是如此。那么,我们能做些什么来发现那些可能想要误导我们的人,以及我们如何确保我们不会无意中误导他人呢?
让我们考虑一下图表是如何对我们撒谎的(然后我们会看一些真实的例子)。
图表说谎的 5 种方式
Alberto Cairo 告诉我们,使用图表欺骗观众有五种方法:
- 使用设计不佳的图表
- 显示可疑的数据
- 显示不足的数据
- 隐藏不确定性
- 暗示误导模式
Cairo 是在媒体中使用图表的权威。他在为西班牙和巴西的主要报纸工作时学会了印刷媒体行业。现在他是佛罗里达州迈阿密大学传播学院视觉新闻学的骑士教席,也是私人和政府组织的顾问。
Cairo 也是许多书籍的作者,包括真实艺术:数据、图表和交流地图和功能艺术:信息图形和可视化介绍。
但是上面列出的欺骗方法来自于图表如何说谎:对视觉信息变得更聪明(从现在开始, HCL )。这本优秀的书以一个必要的章节开始,讲述了图表是如何工作的,但很快就进入了主题的实质:他们如何对我们撒谎,如何发现他们在对我们撒谎,以及自己如何不这样做。
糟糕的设计
图表设计不佳的原因有很多。在同一个图表上对不同的测量使用不同的刻度,例如,扭曲图形的比例,选择错误的基线(如果它不是零,你需要思考为什么不是)或使用三维图表。
饼图
有些人会说,简单地使用饼图是糟糕的设计,因为数据通常可以通过其他方式更好地交流。
他们说得有道理。
如果一个饼图有两个或三个以上的部分,它们可能很难解释,因为我们不太擅长判断一个饼图部分所代表的数量。与相同数量的饼图相比,更容易看出一堆柱形图之间的差异,这就是为什么条形图通常比饼图更可取。
想象一下你正在考虑安装太阳能电池板——当天气晴朗时,你可能会这么做。看看这张一年日照时间的饼状图:
饼图-作者图片
哪个月阳光最充足?七月,五月?哪个阳光最少?看起来是一月或十二月。
现在看一个显示相同数据的条形图:
条形图-作者提供的图像
这里不需要猜测。哪一列更大是完全清楚的,并且您对月份之间的数字差异有更好的了解。
也许没有饼图那么吸引人,但是数据更清晰。
但是,如果普通的饼状图很难解释,三维饼状图可能会特别有问题。
三维图表
看看下面的图表,它是由 HCL 中的一个例子启发而来的。想象一下,饼图代表我的公司在小部件制造领域的市场份额(我是橙棕色部分)。
作者从 图表如何说谎 的例子中获得灵感,作者 Alberto Cairo
看来我做得不错!我没有主导市场,但我的份额看起来很大。
但这不是真的。
3D 效果并没有给出真实的画面。我的饼图部分,也就是从其他饼图中挤出来的部分,看起来很大,但实际上是四个饼图部分中最小的。
这张更常规的图表显示了实际情况。
作者图片
基线效果
下一张图有一个不同的问题。数据来自 HCL,显示了在奥巴马总统任期内美国学校毕业率的改善情况。两个图表显示了相同的数据,但左边的图表显示了成就的明显变化——最后一列的长度是第一列的两倍多——但这是误导性的,因为使用的基线不是零而是 70%(美国政府公布的原始图表比这张图表更引人注目,但说明了同样的问题)。
作者提供的图片
右边的图表是一个更真实的零基线条形图,显示增长是真实的,但没有左边的图表让我们相信的那么剧烈。
如果图表不是从零开始,那么你必须知道为什么不是。例如,气候变化否认者有一个臭名昭著的图表,它绘制了 0 到 100 摄氏度范围内的温度变化。在这种尺度下,全球气温的变化几乎不明显。但这显然是无稽之谈,因为水的冰点和沸点(0 和 100)与气候变化没有多大关系。这是一个明显的例子,零基线是完全不合适的。大多数合理的图表显示了最近几年平均温度的变化,相对较小的温度变化更容易被看到。
可疑的数据
2018 年,据报道,某家英国银行存在性别薪酬差异问题。媒体抓住标题数字不放,称女性薪酬比男性低 44%左右。以下是英国政府官方网页的一个片段(暂时关注左边的图表):
银行的性别薪酬差距,2018 年-英国政府转载于开放政府许可 v3.0
但是,尽管报纸抓住了这些数字,但它们并没有说明全部情况。虽然总体来说女性确实比男性挣得少,但世界银行报告称,做同样工作的男性和女性的薪酬相似。到底发生了什么?
在比较类似的工作时,没有明显的性别工资差距。但是有一个问题。
标题数字的原因是从事低收入工作的妇女比男子多,所以这些妇女的总收入当然低于男子。
世行不存在性别薪酬差距问题,而是存在机会均等问题。
右边的图表显示,大多数高薪雇员是男性,女性倾向于从事低薪工作。
这仍然是一个问题,但不是报告的问题!
解决性别薪酬差距问题相对简单——给女性加薪就行了。但是,改变公司各个层面的性别比例需要更长的时间——你不能解雇大部分男性,雇佣更多女性,因为那样会因为公司的不良行为而惩罚员工个人。你必须等待人们继续前进或者退休。
有时需要多挖掘一点才能找到真实的故事。
数据不足
有时,我们可能会被缺乏数据或不清楚到底在测量什么所误导。
不要忘记通货膨胀
当政客们想要吹嘘他们在任期内如何资助某事或工资如何上涨时,他们通常会引用绝对数字——资助增加了 X 百万美元,平均工资增加了 Y 千英镑。
根据经合组织的数据,这是 2001 年至 2020 年间英国的平均工资。
2001 年至 2020 年英国平均工资——作者图片,数据来源:OECD
蓝线显示实际增加的 GB 磅数。2001 年平均工资为 22,371 英镑,2020 年为 36,987 英镑。这相当于增加了 14616 GPB,增幅约为 65%。
现在,如果我是一位执政时间很长的首相,我可能会忍不住指出,如此显著的增长是在我的任期内发生的。但这并不完全正确。
由于通货膨胀,现在英镑的价值比 10 年前要低,所以 2001 年的英镑价值比 2020 年的英镑高,所以这种增长并不像乍看上去那样。
图表中的红线使用 2020 英镑的值作为平均工资的衡量标准,正如你可以看到的那样,工资的增长没有那么急剧。2001 年的起点是 31,542 英镑(2020 年),2020 年的起点当然与之前的 36,987 英镑(2020 年)相同。现在,这比 2020 年增加了 5,445 英镑,或在 10 年内增加了约 17%——不太好!
如果你看到一个政客声称国防经费、护士工资、对外援助资金、教育预算或其他任何东西都大幅增加,确保他们使用的是经过适当调整的数据。如果你正在研究这样的证据,那么确保你也是。
阿尔贝托·开罗在他的书中提供了一个类似的例子。它对近年来最卖座的电影提出了质疑,并发现尽管按照现代标准,实际数字看起来很小,但电影《大白鲨》仍然是最大的财务成功之一。
我们所说的平均是什么意思
上面的例子是合理的,因为我们看到的是一段时间内的工资轨迹,而不是某个人的收入。
但是如果我们对普通英国人的实际工资感兴趣,这是一个有用的图表吗?
平均实际上是什么意思?大多数人的收入都在这个平均工资左右吗?
根据经合组织,他们对平均值的定义如下:
“平均工资的计算方法是将基于国民账户的工资总额除以整个经济中的平均雇员人数,然后乘以每个全职雇员每周平均工作时间与所有雇员每周平均工作时间的比率。”
换句话说,它是工资的平均值,并根据人们工作的实际时间进行调整。
但是,正如 Alberto Cairo 指出的那样,当一位政治家说减税将意味着普通人减税 X 美元时,这意味着什么呢?一般人是谁?
平均值可以是一组数据的统计平均值、中值或众数。这个词的日常用法通常是统计平均值,即某一特定测量值的总和除以这些测量值的个数。
但是平均数可能会被少数非常高的薪水扭曲,英国国家统计局(ONS)更喜欢使用中位数,这是范围的中心点,也就是说,50%的工人收入高于这个数字,50%的工人收入低于这个数字。
国家统计局 2021 年的工时和收入年度调查显示,全职工人的平均工资为 38,552 英镑,中位数为 31,285 英镑。差别很大。
所以,我们需要明确一点,我们说的是平均工资还是一般人的工资。
清楚不确定性
所有模型都是近似值。它们必须如此,因为它们是现实的简化版本。要想百分之百准确地预测一个事件,唯一的方法就是使用时间机器。即便如此,如果《回到未来》电影可信的话,那也可能行不通。
但是当我们看到 a 候选人在选举中有 75%的胜算时,我们自然会相信他们真的会赢,如果他们赢不了,我们就会抱怨说民意测验专家说的是错的。75%的胜算,当然还有 25%的败局。但试图说服一个押注热门人选的人相信,如果选举再举行 100 次,我们的候选人将赢得其中的 75 次,是没有用的。
缓解这个问题的一种方法是使用误差线。这是我们之前看到的相同的降雨量数据,但是让我们假设这是一个预测。误差棒显示我们的预测误差在正负 10%以内。
作者图片
误导模式
相关性并不意味着因果关系——这是统计学家的口头禅。仅仅因为两个变量变化的方式看起来像是有联系的,并不意味着一个直接影响另一个。例如,冰淇淋销售和晒伤之间可能有某种关系。那么,我们是否可以得出结论,吃冰淇淋会导致晒伤?
显然不是。
这种不太可能的相关性是由一个混杂变量引起的。在这里是太阳。当天气晴朗时,更多的人被晒伤,也有更多的人吃冰淇淋。晒伤病例和冰淇淋消费量都在上升,但它们都依赖于第三个变量,而不是相互依赖。
然而,有时混杂变量不太明显。在 HCL 中,Cairo 给出了一个很好的例子。散点图似乎显示,吸烟的人越多,预期寿命越长——这至少是一个意想不到的发现。然而,仔细观察,它实际上表明,富裕国家的人比贫穷国家的人更长寿,吸烟更多,而贫穷国家的人往往寿命更短。在中等收入国家,人们的寿命和吸烟率各不相同。将数据组合在一张图表上显示出奇怪的相关性,但当突出显示国家财富时,很容易看出正是这一点对预期寿命产生了重大影响。
我希望通过图表可能说谎的五种方式的小旅行是有用的,并将帮助你更深入地思考如何呈现你的数据。当然,真正的专家是 Alberto Cairo,他给出了比我更多的例子,我强烈推荐他的书。
一如既往地感谢阅读。如果你想知道我什么时候发表文章,你可以在 Medium 上订阅(见下面的链接),或者,你可以得到我偶尔的免费时事通讯,Substack 上的技术文件。
参考
书
图表如何说谎:让视觉信息变得更聪明作者 Alberto Cairo,W. W. Norton &公司(2019)
《真实的艺术:数据、图表和地图的交流》,作者 Alberto Cairo,New Riders (2016)
功能艺术:信息图形和可视化介绍作者 Alberto Cairo,New Riders (2012)
*报价
“谎言有三种:谎言、该死的谎言和统计数据”这句话经常被认为是马克·吐温说的,但它的起源https://en.wikipedia.org/wiki/Lies,_damned_lies,_and_statistics可能早于他的用法。
本文包含附属链接。
如何不用 Python 做意大利面
原文:https://towardsdatascience.com/how-not-to-make-spaghetti-out-of-python-7f4d96d4000b
遵循这些简单的准则,避免让你的 Python 代码看起来像一盘热意大利面
介绍
P ython 是你梦想中的编程语言;它很容易写,使用简单,并且有一个生态系统,甚至可以把一条鲸鱼炸出水面。考虑到这一点,很容易理解为什么许多初学者和希望自学编程的有抱负的程序员选择 Python 作为他们学习的第一语言。如此易于理解,如此具有宣示性的一大好处是,许多人可以不费吹灰之力就能接触到这种语言并尝试使用它。
然而,可访问性是一把双刃剑。此外,自学成才的程序员是一把双刃剑,作为一个自学成才的程序员,我可以证实,这些问题中的一些肯定在早期适用于我,甚至在我学习 Python 的时候,那是在我开始编写计算机程序之后。参与技术的好处之一是每天都有变化,或者你可以从旧的事物中学到新的东西。虽然学习如何以最容易理解和一致的方式格式化 Python 代码的最好方法可能是通读 PEP8 指南,但这个列表可能对那些想让自己的 Python 看起来更好的人也有帮助。此外,还有一些有用的提示没有包含在 pep 8 compliance 中,但无论如何都可能会改进代码的某些方面,以使其更具可读性。事不宜迟,让我们来看看一些简单的准则,您可以在 Python 团队中利用它们来相应地组织和呈现代码。
最小参数
我想分享的第一个好建议就是在编写函数时少用参数。功能通常应该有一个单一的逻辑目标。在某些情况下,这可能是一个多步骤的过程,这就是一种称为提取的技术真正可以派上用场的地方,这种技术将在本文中进一步讨论。函数确实不应该有一个扩展的参数列表,除非这对函数来说是完全必要的。例如,绘图就是一个很好的例子。
参数实际上会大大降低函数调用的速度,尤其是在使用关键字参数时。相反,尽量减少这些争论当然是个好主意。它不仅会消除这样的代码
def hello(x, y, anexample, anotherargument, anothername, anothername, anothername, anothername):
return(nothing)
但是它也将帮助我们函数的用户更容易地调用这些函数。在这方面,另一个可以利用的优势是不同类型的论点。在某些情况下,使用关键字或默认的位置参数是有意义的,而在某些情况下,它没有多大意义。
逻辑分离
你可以做的一件事就是在你的代码中使用逻辑分离,这样可以让你的代码更容易阅读,同时也更有意义。这适用于多种不同的方式,例如定义之间的空白。没有文档字符串或任何使用空白进行逻辑分隔的堆叠在一起的函数的问题是,很难区分函数的开始和结束位置。当然,缩进肯定会对此有所帮助,但通过在函数和类之间创建更多的分离,它肯定会使您的代码更加易读和简单。
逻辑分离代码的另一个可能更重要的方面是通过函数。相关代码,以及直接依赖于另一个方法的代码可能应该用那个方法和它一起定义。这使得人们更容易理解正在发生的事情。相信我,当到处都是纠缠不清的方法定义时,很难弄清楚到底发生了什么,并且您需要不断地找出发生了什么。当函数没有恰当地命名时,这变得更加困难。
提取,血统
我推荐用来清理 Python 代码的下一项技术是抽取。在这个列表的所有选项中,我想说拔牙可能是最有价值的。提取是我在自己的代码中经常使用的一种技术。在许多情况下,您可能有一个解决特定问题的函数的想法,当您有了这个想法并想要测试您的方法时,在担心代码的细节之前,先放下您的想法是最有意义的。
在这种情况下,提取技术适合你!使用提取,您可以最小化特定函数中的所有调用,以使该函数更具可读性。这是一个类似这样的多阶段过程。
- 首先,命名你的部分代码,并通过子程序定义你的目标。换句话说,我需要采取步骤 1、2 和 3 来得到结果,所以 1、2 和 3 都是我们函数的子程序。在我们对代码的哪些部分可以并且应该被提取有了一个好的想法之后,我们进入第二步。
- 第二步是提取这些代码部分。为此,请从函数中移除相应的代码。
- 提取的最后一步是将所有这些代码片段包装到它们各自的方法中,最后从我们提取的原始函数中调用这些方法。
如果您想更深入地分析和演示如何在代码中使用抽取技术来改进代码,我实际上有一整篇文章专门讨论这个主题。如果你想了解更多,你可以在这里阅读:
[## 更多的方法意味着更好的代码
towardsdatascience.com](/more-methods-means-better-code-1d3b237f6cf2)
键入您的参数
下一个技巧是我在 Python 中忽略的一个长类型技巧。这是键入要提供给函数的参数。很明显为什么 Python 程序员经常忽略这一点。除非正在使用一些很酷的魔法(例如 multiple dispatch ),否则键入参数在语法上对语言没有任何作用。然而,在两种特定情况下,它肯定会有所帮助。首先是简单地分析你的代码。知道一个论点的细节,什么方法可以用于一个论点,等等,要容易得多。当你看一个函数的时候,如果类型是指定的。
此外,这种类型规范非常适合 Python 支持的文档系统。也就是说,虽然对于创建伟大的、可工作的代码来说并不完全必要,但它确实提供了相当多的好处,而且除了多花几秒钟来输入冒号和类名之外,不会花费任何成本。
命名约定很重要!
学习一门新语言时的一个新手错误是没有意识到这门语言特有的命名惯例。作为程序员,我们为什么要使用命名约定?命名惯例允许我们仅仅通过观察事物来区分它们是什么,而不是实际上需要找出它们是这个还是那个。您可能已经注意到,因为使用了大写,所以很容易区分 Python 包中的方法、类和命名别名。在 Python 中,
- 所有大写字母通常是为诸如 mime 和解释器之类的东西保留的,但它可能最常用于表示全局或环境变量。
- 第一个大写字母代表一个构造函数。
- 所有小写字母都表示定义的变量,除非小写字母后面有括号,否则它们表示函数调用。
- 在 Python 中,模块通常也用小写字母表示。
结论
计算机编程这个错综复杂的网络是不断增长和持续的,因此我们的学习过程也必须是持续的。代码约定以及任何个人或组织编写代码的方式总有改进的空间。也就是说,如果有人想让自己的 Python 代码更加平易近人、更加漂亮,这些技巧中的一些肯定会派上用场。
在这个列表所涵盖的主题中,我可以肯定地说,关键的焦点应该是你将方法放在哪里,以及你如何定义你的方法。虽然这并不是所有软件的情况,当然,甚至不是很接近,我喜欢考虑引入标准元语言或 SML 的方法论。这种语言的核心思想是,每个函数只做一件事,并接受一个参数来做这件事。虽然这可能不是关于通用编程规模的最恰当的建议,但肯定可以从这个想法中吸取一些教训。希望这些建议就像意大利面中的橄榄油,你再也不用担心为你的意大利面代码找到番茄酱了!
隐藏层数如何影响自动编码器潜在表示的质量
自动编码器中超参数调谐—第 1 部分
Clark Van Der Beken 在 Unsplash 上拍摄的照片
介绍
你可能已经知道自动编码器潜在表示包含了输入数据的最重要的特征,当它的维数明显低于输入数据的维数时。
自动编码器潜在表示的质量取决于许多因素,例如隐藏层数、每层中的节点数、、潜在向量的维数、、、隐藏层中激活函数的类型、、、、优化器的类型、学习速率、数量、、技术上,这些因素被称为自动编码器模型 超参数 。
获得这些超参数的最佳值称为超参数调整。机器学习中有不同的超参数调整技术。一个简单的技术是手动调整一个超参数(这里是隐藏层数),同时保持其他超参数值不变。
今天,在这一集里,我将向你展示隐藏层的数量是如何影响自动编码器潜在表现的质量的。
我们使用的数据集
我们将使用 MNIST 数据集 (见最后的引文)在这里建立自动编码器模型。
获取并准备 MNIST 数据集(作者代码)
方法
我们将建立三个具有不同架构的自动编码器模型,这些模型仅取决于隐藏层的数量,而模型中的其他超参数值保持不变。我将使用几种可视化技术来验证结果。
具有一个隐藏层的自动编码器
(图片由作者提供)
上述自动编码器架构可以编码如下。
用一个隐藏层定义自动编码器架构(作者代码)
(图片由作者提供)
现在,我们可以训练模型了。
(作者代码)
(图片由作者提供)
现在,我们可以看到编码后压缩的 MNIST 数字。
(作者代码)
带有一个隐藏层的自动编码器的输出(图片由作者提供)
此输出不够清晰,无法区分 MNIST 数据集中的每个数字,因为单个隐藏图层不足以捕捉 MNIST 数据中大多数复杂的非线性模式(关系)。
我们可以将上面的输出与原始的 MNIST 数字进行比较。
(作者代码)
原 MNIST 数字(图片由作者提供)
现在,我们可以在潜在空间中可视化测试 MNIST 数据,以查看具有一个隐藏层的自动编码器模型如何能够区分九个数字。
(作者代码)
可视化潜在空间中的测试 MNIST 数据(图片由作者提供)
这些数字在潜在空间中没有清晰的独立簇。这意味着仅具有一个隐藏层的自动编码器模型不能清楚地区分测试 MNIST 数据中的九个数字。
作为一个解决方案,我们可以增加自动编码器模型中的隐藏层数。
具有两个隐藏层的自动编码器
(图片由作者提供)
上述自动编码器架构可以编码如下。
定义具有两个隐藏层的自动编码器架构(作者代码)
(图片由作者提供)
现在,我们可以像以前一样训练模型。
(图片由作者提供)
现在,我们可以看到编码后压缩的 MNIST 数字。
具有两个隐藏层的自动编码器的输出(图片由作者提供)
此输出比前一个输出好得多,因为两个隐藏层可以捕获 MNIST 数据中大量复杂的非线性模式(关系)。但是,这个结果仍然离最初的 MNIST 数字相差甚远。
原 MNIST 数字(图片由作者提供)
现在,我们可以在潜在空间中可视化测试 MNIST 数据,以查看具有两个隐藏层的自动编码器模型如何能够区分九个数字。
可视化潜在空间中的测试 MNIST 数据(图片由作者提供)
与之前的输出相比,一些数字在潜在空间中有清晰的独立簇,而一些没有。这意味着具有两个隐藏层的自动编码器模型可以在一定程度上区分测试 MNIST 数据中的九个数字,但不是完美的!
作为一个解决方案,我们可以进一步增加自动编码器模型中的隐藏层数。
具有三个隐藏层的自动编码器
(图片由作者提供)
上述自动编码器架构可以编码如下。
定义具有三个隐藏层的自动编码器架构(作者代码)
(图片由作者提供)
现在,我们可以像以前一样训练模型。
(图片由作者提供)
现在,我们可以看到编码后压缩的 MNIST 数字。
三层隐藏自动编码器的输出(图片由作者提供)
此输出比前两个输出好得多,因为三个隐藏层可以捕获 MNIST 数据中大多数复杂的非线性模式(关系)。除此之外,这个输出足够接近原来的 MNIST 数字,但它并不完美!
原 MNIST 数字(图片由作者提供)
现在,我们可以在潜在空间中可视化测试 MNIST 数据,以查看具有三个隐藏层的自动编码器模型如何能够区分九个数字。
可视化潜在空间中的测试 MNIST 数据(图片由作者提供)
与前两个输出相比,大部分数字在潜在空间中具有清晰的独立簇。这意味着具有三个隐藏层的自动编码器模型可以清楚地区分测试 MNIST 数据中的九个数字。
结论
您可以尝试进一步增加自动编码器模型中的隐藏层数。当您这样做时,由于模型变得更加复杂,有许多隐藏层,这可能会导致过拟合,从而显著降低自动编码器潜在表示的质量。为了减轻自动编码器模型中的过拟合,您可以尝试不同的正则化技术,如 辍学 或 提前停止 。
在这篇文章的结尾,我想用一张图片向您展示三种自动编码器模型的输出,并与原始的 MNIST 数据进行比较。
自动编码器输出一张图片(图片由作者提供)
最上面一行代表原始的 MNIST 数据。随着我们一个接一个地增加 autoencoder 模型中隐藏层的数量,autoencoder 潜在表示的质量也会提高!我们可以考虑进一步增加隐藏层的数量,但这可能会导致我前面提到的过度拟合。
今天的帖子到此结束。
如果您有任何问题或反馈,请告诉我。
阅读下一篇(推荐)
- 深度学习中的自动编码器介绍
https://rukshanpramoditha.medium.com/an-introduction-to-autoencoders-in-deep-learning-ab5a5861f81e
- 自动编码器潜在向量的维度如何影响潜在表示的质量
- 自动编码器如何在降维方面优于 PCA
- 全集我的 神经网络与深度学习教程
点击图片进入我的神经网络和深度学习课程(作者截图)**
支持我当作家
我希望你喜欢阅读这篇文章。如果你愿意支持我成为一名作家,请考虑 注册会员 以获得无限制的媒体访问权限。它只需要每月 5 美元,我会收到你的会员费的一部分。
**https://rukshanpramoditha.medium.com/membership
非常感谢你一直以来的支持!下一篇文章再见。祝大家学习愉快!**
MNIST 数据集信息
- ****引用:邓,l,2012。用于机器学习研究的手写数字图像 mnist 数据库。 IEEE 信号处理杂志,29(6),第 141–142 页。
- ****来源:http://yann.lecun.com/exdb/mnist/
- 许可:Yann le Cun(NYU 库朗研究所)和 Corinna Cortes (纽约谷歌实验室)持有 MNIST 数据集的版权,该数据集在知识共享署名-共享 4.0 国际许可(CC BY-SA)下可用。您可以在此了解有关不同数据集许可类型的更多信息。**
鲁克山普拉莫迪塔
2022–08–23
政策梯度如何让你登上月球
RL 实践课程—第 7 部分
墨西哥霍尔博克斯的贾戈达和凯(图片由作者提供)
策略梯度是一系列强大的强化学习算法,可以解决复杂的控制任务。在今天的课程中,我们将从头开始实现普通的渐变政策和登月🌗。
如果您是强化学习的新手,请查看 课程简介 以了解基础知识和术语。
同样,你可以在 这个资源库 中找到今天课程的所有代码👇🏽
喜欢吗?在 GitHub 上给它一颗星
内容
- 政策梯度如何上月球?🚀🌙
LunarLander
环境- 基线代理
- 欢迎政策梯度🤗
- 策略梯度代理
- 关键要点
- 家庭作业📚
- 下一步是什么?
1.政策梯度如何上月球?🚀🌙
为了登上月球,我们使用宇宙飞船,这是一个巨大的、模块化的工程,结合了令人难以置信的力量和温和的精度。
在我们旅程的开始,我们使用强大的火箭(如下图所示)来帮助宇宙飞船摆脱地球的引力。
两枚火箭将我们的宇宙飞船推入太空
一旦火箭耗尽,宇宙飞船将它们安全地释放到地球的海洋中,并开始其 385,000 公里(239,000 英里)的月球之旅。
三天后,我们的宇宙飞船接近月球,并开始绕月球运行。这部精湛戏剧的最后一幕是登陆。
宇宙飞船释放了一个装置,月球着陆器,月球的引力场向下拉向它的表面。我们整个任务的成功取决于这个装置的平稳着陆。
月球着陆器(维基共享资源)
在今天的讲座中,我们将使用强化学习来训练一个代理(又名控制器)将这个设备降落在月球上。
此外,我们将使用 OpenAI 中的LunarLander
环境作为着陆问题的一个方便(和简化)的抽象。
最后,这就是您今天要实现的代理如何在月球上着陆。
2.LunarLander
环境
在进入建模部分之前,让我们快速熟悉一下LunarLander
环境。
状态
代理获得具有 8 个分量的状态向量:
- 目前在 2D 世界的位置: x 和 y
- 沿这两个轴的速度: vx 和 vy
- 相对于垂直方向的角度位置 θ :
- 角速度 ω ,捕捉设备绕自身轴的旋转。
- 两个二进制信号( s1 和 s2 )指示设备的两个腿中的哪一个(如果有的话)与地板接触。
动作
有 4 种可能的操作:
0
无所事事。- 启动左引擎。
2
点燃主引擎(中央)。3
点燃右侧发动机。
奖励
在这种环境下,奖励函数被设计成向代理人提供足够的信号。这使得训练更加容易。
这是着陆器在每个时间步得到的奖励:
- 如果着陆器远离着陆垫,它会得到负奖励。
- 如果发生事故,它将获得额外的-100 分。
- 如果是休息,它会获得额外的+100 点。
- 每条腿着地+10 分。
- 启动主引擎每帧-0.3 分。
- 发射侧边引擎每帧-0.03 分。
- 最后,解决了 200 分。
奖励工程的利弊
奖励工程是一种建模技巧,通过向代理提供频繁的反馈来帮助 RL 代理学习。奖励很少的环境更难解决。
然而,它也有两个缺点:
👉🏽设计奖励功能很难,就像你看到
LunarLander-v2
奖励后可能想象的那样。在人们找到鼓励代理学习正确行为的奖励函数之前,通常要进行大量的反复试验。👉🏽奖励塑造是环境特定的,它将被训练的代理的泛化限制在稍微不同的环境中。此外,这限制了在模拟上训练的 RL 代理到真实世界环境的可移植性。
3.基线代理
👉🏽notebooks/01 _ random _ agent _ baseline . ipynb
像往常一样,我们使用一个随机代理来获得问题的快速基线。
接下来,我们使用 100 集来评估这个代理,以获得着陆器的总奖励和成功率:
然后我们画出结果
终于意识到我们的代理人是一个彻底的灾难
Reward average -198.35, std 103.93
Succes rate = 0.00%
*由于代理固有的随机性,当您在笔记本电脑上运行笔记本时,这些数字不会完全相同。无论如何,成功率几乎肯定是 0%。
另外,你可以看一段这个随机代理的视频,来说服自己我们还远远没有解决问题。
失败时间
事实证明,登上月球并不是一件容易的事(多么令人惊讶)
让我们看看政策梯度如何帮助我们登上月球。
4.欢迎政策梯度🤗
任何强化学习问题的目标都是找到一个最大化累积回报的最优策略。
到目前为止,在课程中,我们已经使用了基于值的方法,如 Q-learning 或 SARSA 。这些方法以间接的方式找到最优策略,首先找到最优 Q 函数,然后使用这个 Q 函数按照ε-贪婪策略选择下一个最佳动作。这样他们就能得出最优策略。
****另一方面,基于策略的方法直接找到最优策略,而不必估计最优 Q 函数。
基于策略的方法的两个基本步骤如下:
第一步。政策参数化
我们使用神经网络模型来参数化最优策略。这个政策被建模为一个随机政策,与确定性政策相反。我们称之为策略网络,我们将其表示为
策略取决于参数 θ
随机政策和勘探与开采的权衡
随机策略将一个给定的观察(输入)映射到一个概率列表,每个概率对应一个可能的动作。
为了选择下一步要采取的操作,代理会根据操作的概率对其进行采样。因此,随机策略自然地处理探索与利用的权衡,而没有像ε这样的超参数技巧(如 Q-learning 中使用的ε-贪婪技巧)。
在LunarLander-v2
环境中,我们的随机策略将有 8 个输入和 4 个输出。4 个输出中的每一个都代表采取 4 个行动中的每一个的概率。
策略网络的架构是一个您需要试验的超参数。我们今天要用的是一个有 64 个单元的隐藏层。
政策网(图片由作者提供)
解决我们的 RL 问题就相当于找到了这个神经网络的最优参数。
但是我们如何找到这个网络的最佳参数呢?
第二步。寻找最佳参数的政策梯度
评估一项政策有多好很容易:
- 首先,我们对 、N 随机剧集遵循该策略,并收集每集的总报酬
- 第二,我们平均这个 N 总报酬,得到一个整体绩效指标。这个表达式就是总报酬的经验平均值。
此外,总报酬以及 J 取决于策略参数 θ,a 我们的目标是找到使 J 最大化的参数 θ 。
同样,有不同的算法来解决这个最大化问题(例如,遗传优化),但通常在深度学习中,基于梯度的方法是王道👑。
基于梯度的方法是如何工作的?
我们从政策参数θ₀的初始猜测开始,我们希望找到一组更好的参数,θ₁
θ₁和θ₀的区别在于我们在参数空间中行进的方向。
问题是,增加 J 的最佳方向是什么?
而答案就是……这个渐变。****
什么事?
一个函数 J 相对于一个参数向量 θ 的梯度就是我们需要从 θ 到产生 J 的最大增量的方向。
J 相对于θ的梯度
但是,我们在梯度方向上应该移动的距离呢?
这是另一个(非常流行的)超参数:学习率α****
配备了梯度和适当调整的学习率,我们做一步梯度上升,以提出一个更好的参数θ₁向量
梯度上升的一步
如果我们迭代重复这个公式,我们将获得更好的政策参数,并有望解决环境问题。
****
这就是梯度上升如何帮助我们找到最优的政策网络参数。
剩下的问题是,我们如何计算这些梯度?
估计政策绩效的梯度
为了实现这个算法,我们需要一个可以数值计算的策略性能梯度的表达式。
利用一点微积分和统计学,我们可以从数学上证明,政策参数可以用轨迹样本来近似,这些轨迹样本是用当前政策收集的,如下 :
其中轨迹𝛕是直到情节结束所观察到的状态和所采取的动作的序列
重要的是要强调这样一个事实,即这些轨迹必须使用当前政策参数来收集。
符合策略与不符合策略的算法
策略梯度方法是基于策略的算法,意味着我们只能使用在当前策略下收集的经验来改进当前策略。
另一方面,使用非策略算法,如 Q-learning,我们可以保留使用旧版本策略收集的轨迹的回放记忆,并使用它们来改进当前策略。
此外,上面的公式对应于最简单的政策梯度方法。然而,有这个公式的变化,取代每轨迹总回报 R(τᵢ)
每集总奖励
其他成功指标。
特别是,我们将在本课程中看到两个版本,一个在今天,另一个在下节课:
- 给定动作后的累积奖励,又名奖励-继续****
- ****优势函数,是当前策略的 Q 函数和 V 函数的区别。
如果我们已经有了一个公式,为什么还需要其他公式来估计梯度?
政策梯度公式的所有 3 个变量都有相同的期望值,所以如果你使用一个非常大的轨迹样本,这 3 个数字将非常相似。然而,就计算性能而言,我们只能负担得起一小组轨迹,因此这些估计的可变性很重要。
特别
- 奖励去的版本有一个比原来的公式更低的方差
- 并且优势功能版本甚至比奖励去版本具有更小的方差。
较低的方差导致更快和更稳定的策略学习。
今天,我们将实现奖励到去的版本,因为它几乎与原始的累积奖励的香草政策梯度公式一样复杂。在下一讲中,我们将看到如何估计优势函数并得到更好的结果。
想了解细节吗?
由于本课程的目的是给你一个实践这个主题的方法,我将数学术语保持在最低限度。
如果你想了解从上面推导政策梯度公式的所有步骤,我推荐你阅读 Wouter van hees wijk的这篇 优秀博文📝。**
5.策略梯度代理
👉🏽notebooks/03 _ vanilla _ policy _ gradient _ with _ rewards _ to _ go . ipynb
让我们实现最简单的策略梯度代理,其中策略梯度公式中的权重是阶段性的回报。
超参数只有 3:
learning_rate
是政策梯度更新的大小。hidden_layers
定义策略网络架构。gradient_weights
是每个时间步的奖励:即从当前时间步到剧集结束的奖励总和。
我们使用 Tensorboard 设置了基本的日志记录,并开始训练我们的 VPGAgent:
训练逻辑封装在[src/vgp_agent.py](https://github.com/Paulescu/hands-on-rl/blob/main/04_lunar_lander/src/vpg_agent.py)
中的agent.train()
函数中。该函数本质上是一个具有n_policy_updates
次迭代的循环,在每次迭代中,我们:
- 收集
batch_size
轨迹的样本 - 使用随机梯度上升更新策略参数。
- 将度量记录到 Tensorboard
- 可能评估当前代理,如果它是我们目前找到的最好的代理,将其保存到磁盘。
什么是正确的
**batch_size**
使用方法?每次策略更新的轨迹数量(又名
batch_size
)是一个超参数,你需要调整它以确保你的训练在合理的时间内收敛到最优解。👉🏽如果
batch_size
太低,您将得到非常嘈杂的梯度估计,并且训练将不会收敛到最优策略。👉🏽相反,如果
batch_size
太大,训练循环会不必要地变慢,而你会坐着等🥱
标绘训练结果
当模型正在训练时,我们到终端并按如下方式启动 Tensorboard 服务器:
$ tensorboard --logdir tensorboard_logs
如果您访问控制台上打印的 URL,您会看到一个类似于此的图表,其中横轴是代理到目前为止收集的轨迹总数,纵轴是每集的总奖励。
1M 步后每集总奖励(图片由作者提供)
我们清楚地看到代理正在学习,并在 100 万步后实现了大约 250 英镑的平均总回报。
由于总报酬不是一个非常直观的衡量标准,我们在100
新剧集的培训结束时直接评估代理,并检查登陆成功率:
Reward average 245.86, std 30.18
Succes rate = 99.00%
哇哦!99%的准确率已经很不错了吧?
让我们快速休息一下,回顾一下,然后展示作业。我们走吧。
休息和补水的时间到了(图片由作者提供)
6.关键要点
今天我想让你睡在这三样东西上:
- 首先,策略梯度(PG)算法直接参数化最优策略,并使用梯度上升算法调整其参数。
- 第二,与深度 Q 学习相比,PG 算法更稳定(即对超参数不太敏感),这很好。
- 最后,PG 算法的数据效率更低,因为它们不能重用旧的轨迹来更新当前的策略参数(即它们是基于策略的方法)。这是我们需要改进的地方
7.家庭作业
- 你能找到一个更小的网络来解决这种环境吗?我用了一个隐藏层 64 个单位,但我觉得这是矫枉过正。
- 你能通过适当调整
batch_size
来加速收敛吗?
8.下一步是什么
在下一课中,我们将介绍一种新的技巧来提高策略梯度方法的数据效率。
敬请关注。
爱情,
活下去。
学习。
想支持我吗?
你喜欢阅读和学习关于 ML、AI 和数据科学的知识吗?
无限制地访问我在 Medium 上发布的所有内容,并支持我的写作。
👉🏽今天使用我的 推荐链接 成为会员。
**https://pau-labarta-bajo.medium.com/membership
👉🏽订阅 datamachines 简讯 。
👉🏽 跟着我 上媒。
祝你愉快🤗
避寒胜地**
时间序列数据的排序如何识别异常行为
行业笔记
时间序列数据的排序如何识别异常行为
通过简单的 python 脚本告知您的维护策略并防止故障
美国公共电力协会在 Unsplash 上拍摄的照片
温度和压力等传感器读数有助于了解资产的“正常”行为。当读数偏离该标准时,它可能是损坏或低效运行的指示,如果不加以纠正,可能会导致代价高昂的设备故障。因此,这些数据有助于形成任何主动维护或检查活动。
例如,问题是温度与许多因素有关;资产的工作强度(例如生产水平)、环境温度和冷却效率。这使得寻找和识别真正关注的温度水平和变化变得棘手,可能需要昂贵的数据专家,有时我们只是没有收集足够的数据来获得准确的结果,或者没有兴趣在这方面投资。
然而,我们可以做一些更简单的事情。
如果我们有多种资产,例如发电机,我们可以将每个发电机的行为相对于其他发电机进行排序。通过随着时间的推移跟踪这一排名,我们可以寻找行为变化的证据。然后可以对此进行标记,以便进行深入调查。代码非常简单,不需要昂贵复杂的模型就可以获得结果。
本文侧重于工程应用,但很容易看出如何将其应用于任何受多种因素影响的基准测试。
一个例子
让我们以发电机为例,假设您有 20 台不同发电机的历史发电量和温度读数。只考虑发电机正常生产的时间。发电机 A 是 2016 年排名最高的生产商(最高产量),也是最热门的——这并不奇怪,我们知道这两者是相关的。在同一年,发电机 B 是最冷的(第 19 位)之一,具有中等的包装生产水平(第 11 位)。在接下来的四年里,这些相同类型的排名持续稳定,所以我们有信心这是他们的“标准”。
然而,在 2021 年,发现发电机 A 是该年第二热的,但却是最低的生产者之一。好像有什么不对劲,为什么还是这么热?此外,发电机 B 现在是第七热的发电机,但其生产值没有改变。这也很奇怪,这种发电机在这些生产水平下不会运行得这么热,还会发生什么呢?
只看温度读数可能会忽略发电机 A 的异常温度,因为从表面上看,温度读数没有太大变化,是它们与发电的关系发生了变化。孤立地看待这两者可能没有突出问题。同样,B 可能已经被遗漏,因为发电机仅是第七热的,因此可能被认为不够热而不必担心。
这是一个首过指标,现在应该对这两项资产进行全面的数据调查。当时还有什么在影响这个系统?例如,资产是否长期离线?通讯中断了吗?传感器精度有问题吗?是否存在可能导致此类行为的已知问题?回答这些问题,了解检查或主动工作是否符合您的利益。
代码
这个例子使用 python 中的 pandas 库。一般来说,工作流程是:
- 源时间序列数据 —以:时间戳、资产、世代、温度的形式
- 按期望的时间间隔分组——获得年或月平均值、总和、偏差等。
- 申请排名
- 分析结果
下面是更详细的工作流程。
准备要排序的数据
# import pandas library
import pandas as pd# read in timeseries data, may be via csv or queried direct
# from a database
df = pd.read_csv(r'filepath\filename.csv')# create a variable for your desired time interval
# i.e. year or month
df['year'] = pd.to_datetime(df['TimeStamp']).dt.to_period('Y')# group the data by generator and year and find the aggregate values
#e.g. average temperature over the year
df2 = df.groupby(['GeneratorId','year']).agg({'average_temp': ['std', 'mean'], 'generation': ['std', 'sum']})# write to excel
df2.to_csv(r'filepath\filename.csv', index = False)
虽然您可以在这一步应用排名,但我建议导出数据子集,并对照实际值进行检查。这将确保脚本像预期的那样工作,并可能使您以后免受代码中任何讨厌的错误的困扰。
对数据进行排序
这个函数非常简单,一旦读回 python apply:
df2['average_temp_rank'] = df_year.groupby('year')['average_temp_mean'].rank(pct=True)
这将把温度等级应用到名为“average_temp_rank”的新列中。对其他要排序的值重复此操作,如 generation sum,就这样!
分析一下
然后可以在 python 或 excel 中进行进一步的分析,以跟踪这些排名是如何变化的。一种方法可以是趋势代排名:温度排名比率,这是保持稳定还是变得不匹配?
上面没有提到的是一段时间内的标准差排名。温度波动是否超过正常值?特别是在发电机中,这些频繁的波动会导致材料因这些变化而膨胀和收缩,从而导致损坏。
深入挖掘
如前所述,这部分是关键。排名分析将为我们提供一些线索,表明有什么地方出了问题,从而引发更广泛的调查。
虽然这是一个简化的例子,但显然排名分析可以有一系列有用的应用。请在评论中告诉我你如何在你的行业中使用它们。
https://medium.com/@hollydalligan/membership
NLP 基准有多可靠?
原文:https://towardsdatascience.com/how-reliable-are-nlp-benchmarks-fb1a0a70e26a
WiC 数据集案例研究
尼尔·托马斯在 Unsplash 上的照片
排行榜的争夺
如今,对数据集和构造越来越多的关注是研究模型学习何种行为的自然结果。这种关注导致研究人员建立基准平台,如 GLUE 及其继任者 SuperGLUE [1]基准,旨在成为语言理解任务的优秀评估平台。尽管许多研究人员开展研究,为这些基准的排行榜提供主要工作,但很少有人关注开箱即用和问题的关键边缘,评估数据集的充分性。上下文中的单词(WiC)数据集[2]是 SuperGLUE 基准中的数据集之一,它通常用于评估 NLP 系统的词义消歧[3]能力。这篇文章将评估这样一个数据集的质量及其在评估 NLP 性能中的用途。
WiC 数据集
WiC 数据集包括由两个句子对组成的例子,这两个句子对共享一个多义(多种意义)单词的出现,该单词被称为中枢单词。词义消歧是 NLP 模型的一项高级任务,研究人员为这项任务做了大量的工作,制作了一个二元分类数据集。二元分类任务是一个问题,其目标是识别在两个句子中两次出现的中心词是否具有相同的含义:
表 WiC 数据集片段[ 作者图片 ]
这些例子是使用三种广泛的词汇资源半自动构建的:WordNet、VerbNet 和 Wiktionary。作者在构建 WiC 数据集时遵循的程序已在[2]中描述。我们按照同样的过程自行重建 WiC 数据集;因此,我们能够以 93.4%的准确度检索测试集的目标标签。逆向工程背后的动机不是为了作弊,而是为了更深入地分析测试集(即 Welch t-Test,分析单个目标标签的性能等。),我们需要知道测试集上的目标标签。此外,通过仅设置两个启发式规则成功地再现数据集表明,WiC 严重依赖于资源,并且几乎完全是自动构造的任务。它应该是基于知识的,并允许语言模型产生它们的下降粒度函数来区分词义。
数据集被组织成三个部分(训练集、验证集和测试集),并且仅针对训练集和验证集提供监督。原始论文中报告了三个数据集的大小:
表 WiC 数据集分割的统计[ 作者的图片]
在分析 WiC 数据集后,可以概括出三个值得注意的问题。
1。独特枢纽词的不同分布
第一个问题涉及训练集、验证集和测试集中的唯一关键词的分布的显著差异。特别是,训练集遵循长尾分布,而验证集和测试集是均匀分布的,如图 1 所示:
图 1:不同数据集部分的样本分布[ 作者图片 ]
尽管研究人员打算鼓励模型学习通用函数并避免在训练集上过度拟合,但数据分割之间的这种不平衡分布将使一些中枢产生偏差,并阻止模型学习正确的粒度函数来预测正确的类。
2。不平衡标签
第二个问题是关于中心词的不平衡标注。尽管所有三个数据集拆分都经过精心设计,具有平衡的目标标签,但对于单个 pivot 单词的目标标签来说,情况并非如此。在图 2 和图 3 中,我们报告了数据集中出现的两个只有真或假标签的枢纽词示例:
图 2:中心词“academy”的不平衡目标标记示例[ 作者的图像 ]
图 3:枢纽词“furniture”的不平衡目标标注示例【作者的图片】
训练集的显著百分比(12.93%,包括不止一次出现)显示了这个问题。这可能会导致学习中的偏差,并导致模型过度适应特定的中枢。由于大型神经语言模型已被证明是非常有效的样本,因此在训练和测试集的重要部分上存在过度拟合的高风险。此外,当用具有这样缺陷的数据集训练时,该模型无法学习感觉的粒度。对于这些枢轴样本,可以认为模型预测是任意的。
3。词典标注
第三个问题是,一些句子对是根据它们的词典角色而不是意义或词义来标记的。这种效应可能依赖于词源,Wiktionary,它将动词分为及物动词和不及物动词。最后一个缺陷可能会误导模型,因为它完全违背了任务的目标。当检查图 4 中的样本时,甚至人类也会感到困惑。
图 4:作者根据词典角色图像标注的一个例子
好,我们来评价一下质量…
我们执行了 5 个不同的实验集,旨在深入评估基准的质量。我们在所有实验中使用了 3 种不同的机器学习方法:SVM、MLP 和余弦相似度。此外,我们使用各种数据扩充技术来理解 WiC 数据集构建约束及其对学习的可能影响,获得了 13 个额外的训练集。执行扩充步骤是为了测量(1)分布转移和(2)不同场景中的枢轴重叠的影响。
首先,我们使用 SVM 模型执行网格搜索,从 14 个可用数据集(包括原始数据集)中识别并选择性能最佳的数据集。随后,选择的数据集被用于执行与 MLP 模型的实验。相比之下,第三种方法基于余弦相似性,并且不包括任何训练步骤。在这种方法中,使用 BERT [4]构建每对中两个句子的向量表示。余弦相似性分数被评估,并且使用阈值导出输出。在最初的文章之后,我们进行了同样的 3 组子实验。此外,由于我们对调查训练/验证和测试集之间的分布差异的影响感兴趣,我们执行了 Welch t-Test。
由于我们没有一个完整的实验数据集,我们使用训练集设计了 K-Fold 验证程序。特别地,我们将训练集分成 5 个折叠,使用 4 个折叠用于训练目的,并丢弃剩余的 1 个折叠。评估在原始验证集上进行。我们将该实验的显著性水平设置为“事实标准”值的 5%,这是文献中大多数实验中常用的。该值意味着,如果 P 值结果小于显著性水平,则可以认为两个群体之间的差距具有统计显著性。
Welch t 检验结果报告在表 3 中:
表 3。韦尔奇 t 检验结果[ 图片作者 ]
实验中使用的群体数据如图 5 所示:
图 5。Welch t-Test 对训练、验证和测试数据集进行 K 倍验证[ 图片作者 ]
Welch t-检验结果清楚地显示了可能与 WiC 数据集的构造缺陷和上述数据的不同分布有关的显著差异。在 Welch t 测试结果之后,我们分析了目标类(真和假)的准确性。令人惊讶的是,在其中一个目标标签中,所有模型的表现都更好。虽然余弦相似性在真实标签上被极化,但是其他两个模型(SVM 和 MLP)在错误类别上报告了更好的性能。
另一个非常重要的结果来自对错误预测的详细分析。这种暗示来自于这样一个事实,即有几个模型锁定了某些精度值。因此,分析这些错误,我们发现 638 个样本中的 81 个,或 12.7%,被所有模型错误预测。因此,我们决定运行一个涉及一些人类主管的最终实验,因为强力胶基准声明“任务应该超出当前最先进系统的范围,但可以由大多数受过大学教育的英语使用者解决。”[3].
特别是,我们提取了这 81 个没有目标标签的常见错误预测(61 个正确,20 个错误),我们要求一小组人类主管提供标签。分析它们,我们注意到 50 个错误分类的中枢词在训练数据集上不存在,并且剩余的 31 个错误分类的中枢中的 24 个遭受不平衡的目标标签效应。此外,错误预测样本的标签分布(61 个真和 20 个假)证明了我们关于不平衡分布和低质量监督的假设。
人类专家测试表明,高级母语者在这些错误预测的数据子样本上报告了 52.93%的准确度值。这些实验表明,构造缺陷影响 WiC 数据集,使其成为 NLP 模型和人类专家无法完成的任务。
结论
WIC 数据集是超级胶水基准中包含的数据集之一。它被设计用来测量 NLP 的一个基本问题,即词义消歧任务(WSD)。具体而言,它提出了一种创新的方法来完成 WSD 任务,即将其转移到二元分类任务(对/错)中,目标是识别一个中枢词在两个观察到的句子中是否具有相同的含义。虽然将 WSD 任务转换成二进制分类问题可以被认为是一种非常创新的解决方案,但是所产生的数据集显示出低水平的质量,特别是在表达词义的粒度方面提供的知识水平不足。
训练集和验证测试集之间的分布差异限制了分类模型的预期性能。因此,最常用的分类模型(SVM、余弦相似度和 MLP)表现出不超过 68%准确度的低性能。此外,韦尔奇 t 检验结果表明,如果误差不超过 5%,排行榜结果就不能被认为是显著的。
最后,额外的调查表明,12.7%的验证集样本不能被任何模型正确预测,因为:
- 在常见的错误预测中,61.72%的关键词不存在于训练数据集上,模型没有任何数据样本可供学习。
- 对于剩余的 38.28%可学习的中枢词,77.42%的中枢遭受不平衡的目标标签。
建议
首先,如果您想在 WiC 数据集上评估您的模型,请仔细考虑😊。然后,调整 WiC 数据集以修复其中出现的许多构造缺陷:
- 定型集应该遵循与验证集和测试集相同的分布。
- 除了整个数据集级别上的平衡目标标签之外,每个中枢词也应该具有平衡的目标标签。
此外,我们认为应该扩展人类监督测试。事实上:
- 在 WiC 论文中,人类基线建立在以下基本思想之上:“我们从测试集中随机抽取了四组 100 个实例,其中两个注释者之间有 50 个实例重叠。”[2].然而,像为一项任务设定一个黄金标准这样的强有力的结果可能不会用这种初步评估来表述。
- 除了测试集检查之外,训练集和评估集应该由人类主管检查。词义消歧问题(WSD)即使对人类来说也是一项复杂的任务,并且 WSD 数据集,尤其是如果从词典编纂来源自动生成的话,应该非常小心地处理评估过程。
- 如果可能的话,整个训练、评估和测试集应该由人类专家进行检查(而不是随机选择 100 个样本),因为许多研究人员依赖这个基准而不质疑质量,并且他们使用它来评估他们昂贵的机器学习模型的性能。如果我们仔细观察强力胶基准测试的排行榜,我们可以看到一些昂贵的型号的行为几乎就像抛硬币一样。
参考书目
- Wang,a .,Pruksachatkun,y .,Nangia,n .,Singh,a .,Michael,j .,Hill,f .,Bowman,S. R. (2019)。强力胶:通用语言理解系统的一个更棘手的基准。doi:10.48550/ARXIV.1905.00537
- 皮列瓦尔,麻省理工学院,卡马乔-科拉多斯,J. (2019)。WiC:用于评估上下文相关意义表达的上下文相关单词数据集。
- 洛雷罗 d .豪尔赫 A. (2019)。语言建模是有意义的:通过 WordNet 传播表示以实现全覆盖的词义消歧。计算语言学协会第 57 届年会会议录。https://doi.org/10.18653/v1/p19-1569
- Devlin,j .,Chang,m .,Lee,k .,Toutanova,K. (2018 年)。BERT:用于语言理解的深度双向转换器的预训练。
科学贡献如何变成一个有毒的环境
原文:https://towardsdatascience.com/how-science-contribution-has-become-a-toxic-environment-6beb382cebcd
意见
计算机科学是如何继承了其他学科同样的错误的
图片由作者用OpenAIDALL-E 生成
同行评议是学术研究的核心,如果你想在任何科学期刊上发表论文,无论是医学、物理学还是生物学期刊,这都是必不可少的一步。尽管在计算机科学领域,引领潮流的不是期刊,而是会议,选择将被选中并发表的幸运论文,他们也使用同行评议。同样,事实上,项目委员会也进行同行评审。
结果是,机器学习/人工智能领域的研究包含了与其他学科相同的问题,创造了一个不是基于期刊编辑,而是基于会议委员会的权力系统。
什么是同行评议?这是为了什么?为什么有人认为它是有毒文化的基础?如何改进?这对计算机科学界有什么影响?本文试图回答这些问题
看到所有瑕疵的眼睛
什么是同行评议?给出一个明确的答案是困难的。多年来,它似乎已经成为一种必要的礼仪形式,以安抚对一篇科学文章的命运负有责任的神秘实体。
因此,同行评议就像诗歌、爱情或正义。但这与资助申请或第三方审查的论文有关”——理查德·史密斯
没有人能够独立评估自己的工作质量;研究人员通常无法在自己的研究中发现错误和缺陷。同行评审的最初想法是,外部研究人员(同行)应该在发表前评估一篇科学文章的质量,并提供如何改进稿件的建议。
在最经典的同行评议形式中,科学期刊的编辑收到一份手稿,然后选择两位该领域的专家阅读并提供意见。通常情况下,编辑在阅读稿件后会选择该领域的两名相关专家,他们会提供匿名意见(针对稿件作者)。在审查结束时,作者会收到期刊的决定和/或在某些情况下收到一系列评论,如果他们想发表自己的作品,就必须对这些评论做出回应。
这个系统后来不断发展,现在每个期刊都使用自己的版本。有些期刊先把手稿寄给一位顾问;其他人选择至少三或四个评审者。在其他情况下,即使是审稿人也不知道是谁写的稿子(双盲)。
这种模仿——与我见过的系统相差不远——比扔硬币好不了多少,因为在论文是否应该发表的问题上,审稿人之间的一致程度比你可能会偶然想到的好不了多少— 理查德·史密斯
俱乐部成员的价值
图片由作者用OpenAIDALL-E 生成
如今,同行评议被用于各种领域,无论是发表文章还是分配资金。各机构召集专家进行同行评审,并决定哪些项目应该获得资助。
另一方面,专家评审的文章或项目会增加价值。毕竟,在同行评审期间,作者会经历一个严格的过程,如果有错误或弱点,评审者会要求他们改正。如果作者不改正他们手稿中的弱点,只有一种命运:退稿。
最负盛名的期刊和会议以拥有有史以来最高的退稿率而自豪(《自然》杂志每周收到的 200 篇论文中,只有不到 8%被接受)。此外,科学家希望在这些期刊上发表文章,因为他们的研究更有声望(或者至少更大的感知价值)与他们相关。
此外,一篇发表在期刊上或被著名会议接受的文章,平均来说,会被更多的引用,得到更多的宣传,被更多的读者阅读。所有这些都转化为职业发展,赢得声望很高的奖项等等。
但真的是这样吗?这些有声望的报纸的文章被拒绝或被遗弃在门外是没有价值的吗?
“我们是由我们的朋友来评判的。
我们错了,先生。犹大保持优秀的公司。——出自电影《T4》调侃 (1996)
计算机科学怎么还有人类审稿人
即使是关于最复杂的人工智能的文章,仍然要经过人类审稿人的手。在计算机科学中,手稿的路径是以预印本的形式发布在 arXiv 上,然后提交给会议,根据 arXiv 上和会议手稿中的审稿人的指示进行修改,如果被接受,还会添加一个会议链接。一篇文章的价值取决于会议的价值,而会议的接受率越低,会议的声望就越高。
与科学文章一样,同行评议在计算机科学领域也是盲目的。会议通常使用单盲审查,作者不知道审查者的姓名。为了减少偏见,更有声望的会议已经实施了双盲评审,评审者不知道作者是谁。理论上,这可以防止同行评议偏向或偏向作者。
最重要的会议包括元审查者,以确保过程在科学上是严格的。元审稿人是该领域的专家,当审稿人没有就手稿的命运达成一致意见时,他应该做出最终决定。
谁看守望者?
图片由作者用OpenAIDALL-E 生成
“同行评审的实践是基于对其效果的信任,而不是基于事实”。— 来源
同行评议严重影响了研究人员的生活。“发表或灭亡”是学术界的常用表达。事实上,科学家是由他们的出版物质量来评估的。然而,评估通常不在于评估他们的研究的相关性,而在于评估他们的出版物的影响因子(重要性)。由于同行评议是选择哪些手稿可以发表的关键步骤,你可能想知道这一过程是否运作良好和/或其缺陷是什么。
“对同行评议的一个主要批评是,几乎没有证据表明这一过程实际上是有效的,它实际上是对高质量科学工作的有效筛选,它实际上提高了科学文献的质量”——来源
对同行评议过程的第一个反对意见是,我们没有精确的标准来定义一篇文章或一个好的研究提案的质量。是什么让一篇文章有价值?或者说,是什么让一个研究提案能够带来有趣的发现?从某种意义上说,重要的研究是事后发现的(衍生应用、被引用的次数等等)。
2008 年的一项研究表明,通过向几家期刊提交一篇有八处故意错误的文章,在 420 名审稿人当中,不到一半的审稿人只发现了两处错误。事实上,任何经历过同行评审的人都会有这样的印象,即许多决定都是武断的;评论者的评论特别严厉,只是因为他们受到匿名保护,而不是以良好科学的名义。
此外,专家人数有限,随着提交率的增加,我们没有足够的合格人员来进行审核。另一方面,同行评审没有报酬;它是研究人员提供的免费服务,没有任何报酬。多年来,学术界工作人员的工作量增加了,因此许多研究人员拒绝了出版商的请求。这导致手稿作者收到的评论质量很差,或者在发表前不得不等待很长时间。
截图是作者在 PubMed 上用简单的关键词研究拍摄的。如图所示,关于一切的出版物呈指数增长。
同行评议的另一个严重问题是它并非没有偏见。事实上,几项研究表明,授予奖学金对少数民族和妇女不利。此外,知名作者更有可能被知名期刊接受,无论他们的工作质量如何,从而使不平等的循环永久化,知名作者可以获得奖励和资助,而其他人分享其中的碎屑。
新科学,旧罪恶
图片由作者用OpenAIDALL-E 生成
最近,爱德华·李教授发表了一篇博客文章,批评同行评议是有毒文化出现的原因。他注意到,一方面,会议项目委员会如何保持一定的接受率,许多论文被拒绝而没有真正的原因,或者他们用“缺乏新颖性”来证明拒绝的合理性。
“我们中有太多的人使用自托马斯·库恩以来就过时的科学概念,认为一门学科的进步是新事实的积累”——爱德华·李
这种对新奇事物断断续续的追求正是源于这种过时的科学观。除了成为许多研究人员的障碍之外,它还不允许他们发表对未来工作至关重要的工作(不同的方法,相同的想法在其他领域的应用)。毕竟,没有任何作品是完全原创的,而是基于前人的见解。
此外,作为一个评论家带来了相当大的优势。在计算机科学中,有机会在文章发表前阅读文章会导致不公平的优势。匿名审稿人往往与作者有利益冲突,他们的文章也同样提交给会议。结果是他们有更多的动机拒绝竞争对手的文章。
2017 年,莫斯科的高等经济学院为一座“匿名同行评审者纪念碑”揭幕。
Lee 建议质量差的文章设法发表(因为经过一些修改后,它们会被提交给每一次会议,直到被接受)。另一方面,许多博士生和其他学生反而对这种拒绝文化感到沮丧,以至于离开学术界。
此外,即使有截止日期,大多数文章都是在最后 24 小时内(甚至是截止日期之后)提交的,这导致了所谓的“紧急审查”有限的阅读时间和压力导致对每篇文章的关注减少(一些研究人员有时不得不阅读 1000 多篇论文)。因此,在类似的情况下,评论看起来更像是随机选择。
事实上,主要会议收到过多的文章和接受率甚至逐年下降,截至 2022 年:
- AAAI: 9000 份申请,15 %的接受率
- ICML: 5630 份手稿,21 %的接受率
- NeurIPS: 9122 份手稿,25 %的接受率
在这些前提下,如果审稿人将阅读所有这些手稿或只限于阅读标题和摘要,这是有争议的。如果是这样的话,这就不允许评估手稿的价值或将其标记为“缺乏新颖性”因此,如此数量的文章,很难相信如此大量的被拒绝的手稿是不值得的。
来自河两岸的回忆
任何攻读博士学位的人都必须在某个时候提交至少一篇文章。通常情况下,要求发表至少一篇文章(如果不是更多)才能为自己的博士论文辩护。
每个会议或科学期刊都有具体的手稿格式指南。虽然其中一些是有争议的,并不总是清楚的,但他们必须不假思索地遵循。
浏览不同的提交指南本身就是一个挑战。
第一步显然是为了避免案头拒绝(当编辑决定由于“缺乏新颖性”或缺乏相关性的手稿将不会被转发给审稿人)。回复是一封没有人情味的电子邮件,实际上和每一份被拒绝的稿件都一样。典型的感觉是,手稿实际上并没有被阅读,而是被某个随机过程丢弃了。
仁慈的审稿人建议接受提交的手稿。图片由来自 unsplash 的 Jan Antonin Kolar 拍摄
惊心动魄的等待过后,点评往往令人失望。事实上,许多评论与手稿无关。此外,评论的语气相当咄咄逼人,仿佛目的是攻击提交的作品。此外,评论者经常试图通过建议他们引用自己的文章来增加他们的统计数据,即使这些文章与主题无关。
“作者应该引用 XXXX 的开创性工作,该工作在(另一个完全不同的领域)的背景下使用了类似的模型”——我收到的一位真正的评论家评论的释义
近年来,能够在学术界获得稳定的工作职位已经变得非常具有竞争力。能否获得一个职位通常取决于出版物的数量或质量。这导致了掠夺性期刊和会议的泛滥。事实上,近年来,向付费期刊或会议提交稿件的邀请越来越多,这些期刊或会议保证以出版换取报酬。
每次发表文章或参加会议后,我的邮箱都会被掠夺性期刊和会议的邮件淹没。这些通常是不知名的会议,声称有声望的研究人员(来自不知名的机构和公司)出席,并且似乎与你感兴趣的领域只有模糊的关联。
“NLP 似乎不是你们(公司)的重中之重,因为在离截止日期 3 天的时候,没有人注册参加(虚假的 NLP 会议)”—摘自掠夺性会议销售代表的真实电子邮件,我忽略了之前的所有电子邮件。
虽然这些会议显然没有价值,但许多绝望的研究人员经常参加,希望他们可以提升自己的简历。
掠夺性会议试图抓住另一个作者。图片来源:卡米尔·苏莫塔尔斯基来自 unsplash
另一方面,做一个评论者也不容易。随着越来越少的人可以进行同行评审,你经常会被联系(即使是不完全属于你领域的文章)。虽然审稿人不得不阅读充满方法错误的文章,但通常高质量的手稿会被其他审稿人拒绝。在这些情况下,不清楚编辑如何决定继续(拒绝或接受)。
这些期刊提供了一种格式,在这种格式中,它们实际上推动追求新奇,并使用多种选择(1 个优秀,5 个差)综合一个人的评论,几乎就像是对猫途鹰的评论。这给人的印象是,编辑更感兴趣的是新颖的文章,而不是调查结果的整体质量。
甚至阿尔伯特·爱因斯坦也有一篇手稿被《物理评论》拒绝因此,我们不应该认为拒绝等同于质量差
此外,当您需要成为审核者时,您必须在很短的时间内完成审核。虽然会议和期刊对手稿有严格的文字限制,但作者将大部分结果放在附录中(有时肯定会滥用它),阅读起来很累。就我个人而言,我发现所有对附录的不断引用令人讨厌,这使得阅读一篇文章相当痛苦。
如何自救科学
一篇有趣的文章表明,很难量化同行评审的有益效果。通过分析计算机科学领域的 9000 篇评论和 2800 篇投稿,作者注意到同行评议过程的排名和引用数量的影响之间没有相关性。事实上,从长远来看,被会议拒绝的论文对计算机科学产生深远影响的例子数不胜数:
- PageRank 的手稿在 1998 年被 SIGIR 拒绝。
- word2vec 手稿收到大会弱拒绝和强拒绝。
- 介绍辍学的文章在 2012 年被 NIPS 拒绝。
- 还有, YOLO ,卡尔曼滤波器,变压器 XL ,罗伯塔手稿被一个会议拒绝。
一些改善同行评审的尝试正在进行中。正如经常被批评的那样,评论者滥用盲评来评判带有特别敌意的文章。一方面,有一些实验,审稿人的名字在稿件决定后被公布。在其他情况下,作者的评论和回复会被发布。
像《自然》这样的期刊在投稿前给编辑提供了询问的机会。会议可以设立一个服务台,在截止日期前提交摘要或征求建议。这将有助于作者在提交前改进手稿。
此外,收到数千份提交材料的会议应该增加审查人员的数量,以确保更高质量的审查。此外,向审稿人支付服务费可以确保质量。事实上,通常被选中的评审者会要求他们自己的研究团队成员帮助他们或进行评审(这对博士生来说是一个额外的负担)。或者至少在职业发展或申请资金时,应该考虑作为评审者的服务。
另一方面,编辑和元审稿人的权力几乎是绝对的,因此应该保持平衡,特别是在审稿人在决策上存在分歧的情况下。目前,虽然这些尝试令人鼓舞,但还不够,应该深入讨论这一制度。
提交你的手稿。来自 unsplash 的 Abolfazl Ranjbar 的图像
还有,在 ArXiv 上提交的文章,对于一个研究者的职业生涯应该更有价值。同行评审可以在 ArXiv 上进行,而不需要截止日期,使评审者有足够的时间和压力(也许通过授予作者答辩权)。甚至将注册和验证用户的评论作为一种公开的同行评审。因此,我们可以尝试从以编辑为中心的模式转向以社区为中心的模式。
离别的思念
美国国立卫生研究院的一名评审员正在评估一项拨款提案。图片来源:此处
每天都有越来越多的文章被提交,其中许多文章几乎没有相关性,有明显的错误,甚至有科学不端的例子。因此,我们需要能够区分哪些文章是相关的,哪些是不相关的。多年来,解决方案一直是同行评议,我们盲目相信期刊和会议的权威,但现在是时候对该系统进行批判性分析了。
然而,通过当今科学支柱的同行评议并非没有问题。结果是许多文章仅仅因为一个武断的决定而被拒绝。评论者的评论常常是傲慢的,甚至不完全恰当。毕竟,匿名保证了一个没有责任的权力位置。同行评议最终导致一个昂贵的过程,延长出版时间,并不能保证成功。
甚至计算机科学和新学科也不能幸免于历史上影响其他学科的问题。当越来越多的论文产生,研究人员的职业生涯严重依赖于出版物时,我们应该重新思考科学的一个不可触及的支柱,同行评议。
我相信任何提交文章的人都遇到过挫折,如果你愿意在评论中分享你的故事,我很高兴听到。
如果你觉得有趣:
你可以寻找我的其他文章,你也可以 订阅 在我发表文章时得到通知,你也可以在LinkedIn上连接或联系我。感谢您的支持!
这是我的 GitHub 知识库的链接,我计划在这里收集代码和许多与机器学习、人工智能等相关的资源。
**https://github.com/SalvatoreRa/tutorial
或者随意查看我在 Medium 上的其他文章:
附加资源
- 关于枪枪,这里查这里和这里
- 关于“匿名审稿人纪念碑”,请点击这里,这里,这里和这里
- 博士生与学术倦怠:此处,此处,此处
- 计算机系博士生苦苦挣扎:此处,此处
- 更多关于被会议拒绝的开创性论文:这里
- 关于如何重新思考计算机科学同行评议的文章:此处
- 关于掠夺性会议:这里、这里、这里、这里**
SciPy 和 Scikit-learn 如何优化模型的响应
看看一些方便的优化功能,从预测切换到处方!
拥有一个复制基本事实的健壮模型是很好的,但是能够找到将最小化或最大化其响应的特性值可能会更好。理解为什么用巧克力饼干🍪!
语境
想象一下,你刚刚被一家巧克力饼干厂雇佣了!
很棒的工作,不是吗?
作为一名数据科学家,你的老板要求你在流程的第一步工作,这时所有的配料(面粉、黄油、糖等)都已经准备好了。)混合在一起,因为操作人员面临的主要问题是,他们有时会在面团中结块……这会危及饼干的质量!😱
好消息是他们已经能够测量:
- 配料的主要特性(如面粉的含水量,黄油的柔软度),
- 混合器的设置(其速度、温度等。),
- 和面团中的结块率,从 0 到 10% (5%是临界阈值)
数据是干净的,结构良好(不用提醒你,这是虚构的😂)而且不用花太多时间,你就可以创建一个模型,可以满怀信心地预测面团中块状物的百分比。
为了展示您的模型有多健壮,您将所有人聚集在搅拌机周围,向模型输入当前批次的属性,并宣布面团将具有(灾难性的!)7%的包干率。
当混合操作结束时,每个人都可以看到你的模型是正确的…但是,最终,面团必须被扔掉…
你的老板看着你说:
"有些参数我们可以控制(搅拌器的速度、我加的水量),有些参数我们无法控制(面粉的湿度、房间的确切温度等)。).
请使用您的模型告诉我们,对于每一批,如何微调生产参数以最大限度地降低废品率。
这是一个严峻的事实:你的随机森林模型表现良好,但是,作为 100 个决策树的组合,它是完全非线性的…这使得你不可能找到一个最佳值,因为你可以用一个简单的线性方程解决…
好消息是 SciPy 确实提供了一些方便的优化功能来帮助您;让我们来发现如何!
建模
为了举例,我们将使用一个“过于简单”的模型,但是对于更复杂的问题,原理是一样的。
假设面团块率(Y)受两个主要参数的影响,存储在“X”NumPy 数组中:
nb_samples = 15np.random.seed(22)
X = np.random.randint(1, high=10, size=(nb_samples, 2))print(X)y = X[:, 0] / X[:, 1]
print(y)
输出:
[[6 5]
[1 5]
[7 7]
[5 9]
[5 3]
[9 8]
[3 9]
[9 6]
[5 3]
[3 2]
[7 4]
[4 3]
[8 8]
[8 8]
[5 5]][1.2 0.2 1\. 0.55555556 1.66666667 1.125 0.33333333 1.5 1.66666667 1.5 1.75 1.33333333 1\. 1\. 1\. ]
注意:完整笔记本的链接在文章的最后提供📑
因为我们有一个“适当的”(但很简单的)数据集,所以让我们用一个简单的 Scikit-Learndecision tree regressor创建一个非线性模型:
model = DecisionTreeRegressor(max_depth=4)
model.fit(X, y)
model.score(X, y)#0.9343996768065437
画出它的样子:
plt.figure(figsize=(15, 15))
tree.plot_tree(model)
plt.show()
决策树表示法—作者图片
我们可以观察到,根据 X[0]和 X[1]的值,该决策树有 8 种可能的输出。
SciPy 优化库
SciPy Optimize 库提供了一组函数来最小化(或最大化)目标函数。唯一的预防措施是您应该选择与您的用例相对应的一个:
- 使用“最小化” = >的局部(多变量)优化在您有标量/线性函数要求解时非常有用,该函数假定有一个最优值,如下面的凸函数(x +y):
f(x,y)= x+y-作者图片
- “双重退火”全局优化 = >当你有一个非线性函数,意味着随机搜索最优解时,这是很有用的。这是我们在使用集合树(Random Forest,XGBoost 等)等模型时遇到的典型情况。).
决策树示例-作者图片
在开始最优搜索之前,我们需要创建一个目标函数,返回我们的非线性模型的结果:
def objective(v):
return model.predict(np.array([v]))[0]
然后,只需设置每个特征的边界(X[0]和 X[1])并启动优化过程:
bounds = [[1, 10], [1, 10]]result = dual_annealing(objective, bounds, maxiter=100)print(f"Status: {result['message']}")
print(f"Total Evaluations: {result['nfev']}")
print(f"Minimum reached: {result['fun']}")
print(f"Solution vector: {result['x']}")
输出:
Status: ['Maximum number of iteration reached']
Total Evaluations: 410
Minimum reached: 0.2
Solution vector: [1.78224412 9.35220569]
通过将边界设置为等于原始要素的空间,该函数可以提出一对值来有效地最小化目标函数:
1 号优化结果—作者提供的图片
现在让我们用 X[1]上的约束来重现这个过程,次于 4:
bounds = [[1, 10], [1, 4]]result = dual_annealing(objective, bounds, maxiter=100)print(f"Status: {result['message']}")
print(f"Total Evaluations: {result['nfev']}")
print(f"Minimum reached: {result['fun']}")
print(f"Solution vector: {result['x']}")
输出:
Status: ['Maximum number of iteration reached']
Total Evaluations: 404
Minimum reached: 1.3333333333333333
Solution vector: [4.32296802 1.87272909]
优化结果 n 2 —作者提供的图片
该算法再次能够找到给定边界内的最小可能值(1.333)。
最大化或目标化
与其最小化函数,还不如尽量最大化或者达到一个特定的值。在这种情况下,你只需要修改目标函数。
- 通过在结果前添加“-”来最大化 = >
- 瞄准 = >通过在结果计算中包含目标
最大化示例:
def objective_max(v):
return -model.predict(np.array([v]))[0]bounds = [[1, 10], [1, 10]]result = dual_annealing(objective_max, bounds, maxiter=100)print(f"Status: {result['message']}")
print(f"Total Evaluations: {result['nfev']}")
print(f"Maximum reached: {-result['fun']}")
print(f"Solution vector: {result['x']}")# Output
Status: ['Maximum number of iteration reached']
Total Evaluations: 410
Maximum reached: 1.75
Solution vector: [8.0829203 4.2638071]
优化结果 3 —作者提供的图片
从现在开始,再也没有理由让面团结块了,巧克力曲奇的质量是安全的🍪🍪🍪
相应的代码存储在这里:
https://github.com/pierrelouisbescond/medium_articles/blob/main/medium_optimize.ipynb
请不要犹豫,浏览我在 Medium 上的其他文章:
https://pl-bescond.medium.com/pierre-louis-besconds-articles-on-medium-f6632a6895ad
分析师应该如何打发时间?
原文:https://towardsdatascience.com/how-should-analysts-spend-their-time-e390872ceb70
如何多做重要的工作,少做不重要的工作
当我在谷歌开始建立机器学习模型时,我首先看到的是下图。它强调了编写实际的机器学习代码只是我要做的全部工作的一小部分。事实证明这是真的。
但是处理数据不仅仅是机器学习,那么对于数据分析师来说,这个图表是什么样的呢?
答案并不简单。有些时候,专注于构建仪表板和底层数据模型是有意义的,而有些时候,专注于分析和洞察更有意义。
考虑到这一点,这是我对分析师平均一周生活的评估。
作者图片
正如机器学习一样,有许多不同的任务与分析一样有价值。
然而,一个常见的话题是,数据人员花费超过 50%的时间被动工作,经常处理数据问题或试图查找或访问数据。这方面的例子有:
- 一位利益相关者提到,仪表板中的 KPI 看起来与上周不同,您必须回答这是为什么
- dbt 中的数据测试失败,您必须了解问题的根本原因是什么
- 你想为一个新的客户群使用一个数据点,当你在 Looker 中搜索时,有五种不同的定义,但不清楚使用哪一种
不同地分配时间
以下是数据分析师如何分配时间的另一种选择
作者图片
那么,有什么不同呢?
更多的分析时间
分析师应该做…等等…分析。他们应该有在上班的路上获得灵感的自由,并在午餐时间得到答案。这种类型的工作通常需要长时间的专注,准备好合适的工具,并且接受花半天时间在可能没有结果的工作上是可以的。
我看到,当数据分析师与其他人(如用户研究)密切合作时,这一点做得特别好,他们可以快速制定假设,在知道并非所有测试都是全垒打的情况下,让 A/B 测试运行良好。
“花额外的时间来确保你在做正确的工作,而不是把工作做好,通常是最值得花的时间”
处理数据问题花费的时间更少
我接触过的数据团队每天要花 20%以上的时间处理数据问题,随着规模的扩大,这变得更加棘手。当您是一个小型数据团队时,您可以查看一些数据模型来找到根本原因。随着规模的扩大,您开始有几十个其他数据人员依赖您的数据模型,工程系统在您没有得到通知的情况下崩溃,您不知道会影响您的数据模型的代码更改。
减少查找要使用的数据的时间
随着数据团队规模的扩大,寻找正确数据的难度也呈指数级增长。当你是一个小团队时,你知道所有东西在哪里。随着您的规模越来越大,这变得越来越困难,并且您经常会遇到同一个指标有多个定义的问题。当你变得非常大的时候,在最坏的情况下,仅仅是访问正确的数据就要花费几个月的时间。
为了寻找最佳的时间分配
每个人的最佳分配是不同的,但我的猜测是你有改进的空间。最重要的第一步是仔细考虑如何度过你的时间。
“我建议每周花几分钟时间回顾过去的一周,记下你是如何度过时间的。如果你经常这样做,你会对自己是否合理利用时间有一个惊人的了解。”
寻找正确的数据
数据目录在理论上是伟大的,但是它们经常不能实现它们的潜力。相反,它们最终成为事后的想法,与破窗理论没有太大不同的事情开始发生。一旦人们停止维护数据目录中的几个数据点,你也可以把整个东西扔出窗外。幸运的是,事情正在朝着正确的方向发展,许多人正在思考如何让定义和元数据更贴近人们日常使用的工具。
减少处理数据问题所花费的时间
在过去的几年中,数据团队变得越来越大,并且正在创建更多的数据。当你是一个五人数据团队时,处理数据问题是很容易的。当有几十个数据人员都在创建不同的数据时,事情就不那么简单了。
作者图片
我们需要能够将当您是一个较小的数据团队时使生活变得简单的一些东西应用到较大的数据团队中。如何做到这一点的一些想法:
- 每个数据资产都应该有一个所有者
- 将数据资产封装到具有公共和私有访问端点的域中,因此并非所有人都可以访问所有数据
- 与共享所有权的数据生产者形成闭环,以便尽可能在上游捕获问题
- 让每个人都能够调试数据问题,这样他们就不必每次都上报给同样的几个“数据英雄”
“不要将每个数据问题都视为临时火灾,而是投资于基本的数据质量和控制,以降低数据问题再次发生的可能性”
如果您对如何改善您在数据团队中的工作有一些想法,请告诉我!
2022 年公司应该如何处理数据?
原文:https://towardsdatascience.com/how-should-companies-handle-data-in-2022-922595d9ea4c
随着工具、角色和数据架构的不断变化,有时很难跟上数据科学的最新行业方法。但我们是来帮忙的:本周,我们将重点介绍几篇出色的帖子,它们涉及技术、数据和商业交叉领域的广泛话题。(寻找其他主题的精彩读物?向下滚动。)我们开始吧:
- 有效数据治理的想法还有意义吗?Louise de ley ritz和 Molly Vorwerck 最近的文章中发人深省的前提是,数据治理未能兑现其简化以数据为中心的工作流的承诺。但作者也认为,现在恢复和重塑这一概念还为时不晚,这样它才能与业务需求和现代数据堆栈相协调。
- 权力大,责任大 。人工智能和算法驱动的决策的最新进展正在渗透到我们生活的方方面面。对于特拉维斯·格林(Travis Greene)来说,大量消耗数据的科技巨头的巨大社会和经济足迹必须伴随着更高的透明度和问责制——这是谷歌、Meta 和其他公司有很大发展空间的两个领域。
- 混合数据组织的承诺 。在各种形状、大小和配置的数据团队中呆了 15 年后, Matthew Dawson-Paver 对什么可行,什么不可行有了很强的认识。他的图解概述解释了为什么将自治数据团队和业务或产品团队与嵌入式数据专家相结合的混合结构通常是最佳方法。
- 企业如何找到合适的数据科学家? 在担心工具、框架和团队结构之前,有必要雇佣技能与公司目标和使命一致的数据科学家。为了做到这一点, Rose Day 建议少关注筛选过程的技术层面,多关注有助于确定共同兴趣和价值观的对话。
如果你想了解关于数据和商业的最新文章,请收藏我们来自行业专栏的笔记。
照片由 Serhat Beyazkaya 在 Unsplash 上拍摄
等等,还有呢!(但你知道。)我们最近也在其他领域发表了精彩的文章,我们不能不分享其中任何一篇。这里有几个你绝对不想错过的:
- Nura Kawa 引入了 class maps,这是一个新颖的可视化工具,它解释了分类算法的结果(包括 R 和 Python 中的例子!).
- 在他的最新贡献 , 迈克尔·布朗斯坦展示了特征传播是如何在图形机器学习应用中处理缺失特征的一种高效、可扩展的方法。
- 如果你想在本周得到一份实践指南,你一定不会错过 Rashida Nasrin Sucky 的卡方相关测试患者指南和。
- 对于那些对理论感兴趣的人来说,古斯塔夫·希尔的深入研究关系机器学习的迷人世界绝对会成功。
- 我们永远不会厌倦可以帮助实现更大利益的数据科学项目——比如喜马拉雅·比尔·施雷斯塔最近对学习曲线效应的探索,以及它如何推动可再生能源技术进入良性循环。
我们希望你度过了愉快的一周,充满了学习和新想法。感谢您一如既往地支持我们出版的作品。
直到下一个变量,
TDS 编辑
我们应该如何考虑数据血统?
原文:https://towardsdatascience.com/how-should-we-be-thinking-about-data-lineage-541ca5ab83d0
全面了解您的数据和分析生态系统
为什么数据血统现在如此热门?
数据血统是目前所有数据治理中谈论最多的话题之一,这是有充分理由的。
随着数据沿袭工具的发展,沿袭已经开始在释放数据的全部价值方面拥有越来越大的潜力。现在,人们对使用沿袭作为真正实现组织数据可操作化的途径,并使数据供应链具有弹性、健壮和可靠感到非常兴奋。
投资于采用数据驱动文化的组织高度重视沿袭,因为它使业务中各个级别的团队成员能够理解和信任数据管道,并有望更快地做出数据驱动的决策。它让您的团队充满信心,能够对不断变化的市场条件数据做出快速反应,并做出及时、准确的决策。而且,当出现问题时,它可以帮助数据生产者诊断这些问题,并快速恢复业务。
出于这些原因以及更多原因,数据谱系已经成为数据治理世界的最新必备工具,许多新的数据谱系工具,包括商业的和开源的,已经涌现出来。但是血统仍然很难完全理解,也很难实现。
数据血统到底是什么?
数据谱系是元数据更有趣、更有用的应用之一。它让数据用户更好地了解他们的数据,并清楚地了解他们的数据来自哪里;它要去哪里;以及它是如何改变的,由谁改变的,以及为什么改变。简而言之,它通过为您提供一个更完整、自上而下的数据和分析生态系统图,实现了更好的数据治理。
但是有不同类型的血统,每种类型服务于不同的目的,解决不同的问题。
- 业务沿袭—业务沿袭提供了数据如何从其来源流向其消费地的概要视图。对于希望了解数据来源以及数据是否可信,但又不想迷失在细节中的分析师来说,这是一个重要的工具。
- 技术谱系— 技术谱系则更详细,它允许数据工程师和更多的技术用户尽可能详细地查看基础设施和数据转换;查看表、列和查询级别沿袭。并跟踪数据在管道中的传输,让他们确认一切正常运行。
在您的业务概念、它们之间的关联方式以及它们的技术规范之间,存在着很大一部分难以捉摸的语义层。这一层决定了您的业务定义和您的技术谱系如何相互关联,它不像业务或技术谱系本身那样经常被讨论,但是它提供了关于哪些数据资产对您的组织真正重要的有价值的见解。它还为核心业务概念提供了关键的“事实来源”。连接这些层的能力使我们能够映射所有权和管理权的概念,完成图片并交叉您组织的社交图和数据图。
根据您需要了解的内容(无论是验证信任的关键业务数据来自何处,还是您的数据系统是否正常工作),这些不同类型的沿袭适合不同的需求。
数据沿袭如何帮助解决数据和业务问题
lineage 提供的洞察力使数据用户能够解决在大量互联数据中遇到的各种问题:
- 数据故障排除—如果您的组织依赖于一个关键的数据模型来做出实时决策,而该模型失败了,lineage 使您的团队能够跟踪数据流并确定错误的根本原因。
- 影响分析-如果您正在对数据源进行更改,lineage 允许您在数据流中向前看,以准确预测并准备好对模型的影响,并提醒下游数据使用者更改即将到来。
- 发现和信任——沿袭使数据科学家能够了解在哪里可以向模型添加必要的数据集,并确定这些数据集的所有者以推动流程。它还可以让数据科学家对其模型中数据的质量和来源放心。
- 数据隐私法规(GDPR 和 PII 映射)— Lineage 帮助您的数据隐私和合规团队确定 PII 在您数据中的位置。例如,在 GDPR 请求的情况下,lineage 可以确保您需要删除的所有数据都已删除,从而确保您的组织符合法规要求。
- 数据资产清理/技术迁移-在从一个系统或技术到另一个系统或技术的清理或迁移过程中,lineage 允许您识别和保留最重要的数据,以便将其移动到新设备。
- 数据评估—当您需要识别和分类对您的组织最关键的数据和分析时,lineage 允许您回顾数据供应链,并了解哪些源系统正在推动真正的业务价值和业务决策。
如何实现数据沿袭?
正如我在本系列的第一篇文章中所说的,数据沿袭是在数据从数据源流向消费者的过程中理解、记录和可视化数据的过程。这可能包括数据在传输过程中经历的所有转换—数据是如何转换的?什么变了?为什么呢?
太好了。但是你如何从技术上回答这些问题呢?实现沿袭有三个步骤:
- 收集新的世系相关元数据
- 将这些信息与您已经拥有的(或之前收集的)知识相结合
- 以对您的用例有用和适用的方式表示信息
收集血统
收集数据沿袭有几种不同的方法,每种方法都有其优点。根据您的用例以及您收集血统的系统,一种方法可能比另一种更适合您。
在这些不同的系统中,数据沿袭收集通过以下方式完成:
- 该系统通过其应用编程接口(API)来公开沿袭。这种方法最常见于现代商业信息(BI)和数据可视化工具,如 Tableau 或 Looker。当提供这些工具的数据被编目时,从表到仪表板的数据流(沿袭)也被记录。
- 该系统在运行时发出明确的沿袭信息,越来越多的公司在构建数据管道时采用这种方法。通常,这种基于推送的运行时沿袭方法在运行时被写出到文件或调用沿袭收集系统中的 API,并且它是极其健壮和准确的信息。一些转换系统,如 dbt,本身就能做到这一点。但是如果您正在创建自己的管道,那么自己发布这些信息是一个很好的实践。这可能需要对您的管道代码进行一些返工,但它非常可靠。你可以从 OpenLineage 的创建者 Julien LeDem 那里读到更多关于这个想法的内容。
- 解析系统的转换代码以自动创建技术谱系是一种在系统没有明确发出关于数据谱系的结构化元数据时使用的方法,并且生成谱系视图的唯一方式是通过解析代码。这种对现有代码进行静态分析的方法可能很脆弱,无论是通过 CI/CD 还是其他方式,当需要重新扫描时,您都需要某种方式来触发或检测。
- 手动沿袭条目——无论您使用什么系统来存储和维护沿袭,都应该绝对支持手动建模、扩充或修正从自动化系统收集的沿袭。虽然这听起来令人畏惧,而且肯定不性感,但是如果您的系统不支持扩充和覆盖血统,您将会走进死胡同。
当您考虑这些系统中的每一个时,您还需要决定是否要依赖您的数据先前建立的谱系(这可能容易收集,也可能不容易收集),或者在您编目数据时映射一个新的声明性谱系,实际上编写新的代码,说明“这个数据依赖于 X,那个依赖于 y。”
无论您决定什么,无论您的用例是什么,选择确保您的血统是可靠的、健壮的和值得信赖的系统是至关重要的。
用知识图表示和协调世系
不管你如何收集你的数据血统,有一件事是肯定的,那就是你必须能够以一种灵活的、支持简单进化的方式来存储和管理它。表现血统的最好方式之一是通过知识图;知识图是健壮的、可扩展的——如果您需要添加数据源的话——并且它们可以表示数据的多个层和视图——例如语义的或技术的——并且支持在这些视图之间导航。
现在有两种很好的方法来表示血统,一种是 OpenLineage 标准,另一种是语义标准 PROV-O (一种在 RDF 中描述出处的开放标准)。这两种表示都非常适合将出处信息合并到知识图或其他基于图的表示中。
但是为什么知识图在这里如此重要呢?首先,您会发现,当您从不同的系统收集血统信息时,这些信息可能是不完整的或矛盾的。通过推理和图表分析,知识图表可以以可靠的方式帮助整理矛盾的信息,并且还可以轻松地允许您添加额外的信息——无论是通过手动输入还是从另一个系统收集——而不会丢失您收集的任何原始信息。图表也可以很好地表现血统的演变以及它是如何随时间变化的。
利用血统
当然,拥有一个基于知识图的谱系表示法不仅仅是让解决矛盾和添加新信息变得容易——它也让谱系更容易付诸行动。显然,这使得创建基于图形的血统信息可视化变得容易,以便于探索,特别是当您在语义层和技术层之间移动时。
但是除此之外,它使得操作血统变得非常容易。使用基于图的查询和推理,当管道出现问题时,实现上游生产者和消费者的通知变得很容易;易于在数据集之间传播状态信息;易于进行根本原因问题分析和变更管道的影响分析;这样的例子不胜枚举。
凭借数据血统取胜
数据沿袭使您的组织能够全面了解您的数据,从数据的来源到数据的聚合方式,再到数据在传输过程中为了提供知识和意义而经历的任何转换!由于这种可见性,lineage 确保使用准确、完整和可信的数据来推动您的业务向前发展。
血统有很多。建立可靠的 it 观需要努力和深思熟虑。虽然没有灵丹妙药——当你建立一个数据驱动的文化时,许多东西必须聚集在一起——但如果你投入工作并把它做好,它将具有难以置信的价值。我希望这篇文章能够帮助您思考如何让 lineage 为您和您的团队工作。
群体学习如何工作——区块链和机器学习相结合以获得更好的解决方案
群体学习简介
埃德加·恰帕罗在 Unsplash 上拍摄的照片
估计数字显示,一辆自动驾驶汽车每天可以产生万亿字节的数据。这些数据用于训练机器学习模型,以便汽车可以在道路上及时做出决策。
医院应用机器学习来更快地识别疾病。这些应用至关重要,尤其是对于高传染性疾病。患者不知道答案的时间越长,因此不能正确隔离自己,传染给他人的风险就越大。
它是如何工作的?在训练阶段,一个程序接收到数百万张带有标签的 x 光图像,例如,肺结核或肺炎。
最初,该程序随机预测疾病的类型,因为它在这个阶段没有学到任何东西。但是接下来,每次它猜出疾病,就和标签(肺结核还是肺炎?)并记录预测的错误程度。
该算法调整“标度”/参数/权重以最小化预测误差。优化器继续运行,直到它有把握地预测。
主要问题
我上面提到的机器学习系统面临着几个问题。
- 违反数据保密性/数据隐私法规的风险。
- 由于需要中央服务器来交换信息而导致速度缓慢和数据重复。
想象一下,医院 A 希望通过使用机器学习来更快地获得结核病(TB)的结果。但是医院没有太多以前病人的肺结核病例。它没有足够的标记数据来训练模型。
很好解决吧?去别的医院拿数据就行了。不幸的是,由于数据保密性的考虑,这是不可能的。这是不道德的。
自动驾驶汽车中的传感器和摄像头产生的万亿字节的数据怎么办?如果一辆车学会识别一辆自行车,它应该与所有其他节点共享该信息。但是考虑到数据量的海量,怎么做呢?
群体学习
群体学习是一种数据隐私保护框架,它使用区块链来分散基于机器学习的系统。数据或“知识”不会集中到一个中心位置,以允许医院或汽车之间的共享。
让我们来看看机器学习解决方案的四种构建方式,以便更好地理解。
本地学习
在本地学习环境中,例如,不同医院之间没有联系。所有的培训都在当地进行,并且停留在当地。一家医院不能与其他医院共享数据或知识,至少不能以自动化的方式。
一辆汽车学会识别一棵树,但不能与其他汽车分享。这是一个非常有限的结构。
局部/边缘学习。图片由作者提供。受研究文章中一篇的启发。
中央学习
数据和神经网络参数被发送到中央学习中的专用服务器。所有节点(医院或汽车等。)访问它,这样,信息就被共享了。
我认为这种设置甚至不如本地学习有用。随着数据的增加,考虑到数据隐私问题,这是不切实际的。至少在本地学习中,这两个问题是不存在的,训练完成的模型可以手动分享。
中枢学习。图片由作者提供。灵感来自于研究文章中的一篇。
联合学习
这种类型的部署是当今许多系统中使用的一种。这几乎和群体学习一样好。但是,仍然有一个中心位置。
系统在本地训练,原始数据留在本地的边缘。但是学习——神经网络刻度盘/参数/权重——被转移到一个中心位置。
这解决了隐私问题。模型“学习”只是一堆数字,并不透露病人或司机的信息。但是,中心位置仍然是一个薄弱环节。
联合学习。图片由作者提供。灵感来源于研究文章中的一篇。
群体学习
群体学习没有中心位置。就像在联合学习中一样,训练是在本地/边缘执行的。但是在 SL 的情况下,甚至学习也不能通过一个中央专用服务器共享。
这些实体使用区块链技术交流学习成果。
如研究论文所述,
新节点通过区块链智能合同注册,获得模型,并执行本地模型训练,直到满足定义的同步条件。接下来,在开始新一轮训练之前,通过群应用程序编程接口(API)交换模型参数,并将其合并以创建具有更新参数设置的更新模型。
群体学习。图片由作者提供。受研究文章中的一个启发。
最后的想法
群体学习(SL)是区块链和机器学习协同工作的一个令人兴奋的演示。这看起来是完美的解决方案。我提到了自动驾驶汽车,但研究的重点是疾病识别。数据保密至关重要。
群体学习背后的团队对三种疾病进行了测试。白血病、涡轮虫病和新冠肺炎。结果很有希望。值得看看研究文章。
群体学习这个名字的灵感来自于动物的集体行为,它们聚集在一起实现共同的目标。蜜蜂需要寻找新家时会蜂拥而至。你可能见过鸟类以一种美丽而同步的方式形成。
每个动物(节点)只有一个微小的信息,通过联合和交流,他们可以实现伟大的事情。这就是 SL 的意义所在。
暂时就这样了。感谢阅读。
参考
[2]https://github.com/HewlettPackard/swarm-learning
教学如何让我为项目管理做好准备
原文:https://towardsdatascience.com/how-teaching-prepared-me-for-project-management-128aef7e9e37
杰森·古德曼在 Unsplash 上的照片
我成为数据科学家已经两年多了。在我的部门,我们有机会成为特定项目的项目经理。开始工作大约 3 个月后,我晋升为项目经理(PM ),负责我部门的 5 种主要产品的质量检查(QC)过程。所有这些产品每年都会更新,其中三个在网上面向公众。我已经担任过 3 次这个角色,同时还是一个单独的面向学校员工的项目的项目经理。
但是这和题目所说的教学有什么关系呢?在此之前,我是一名教师。随着我做项目经理的时间越来越长,我发现我以前的教学经验让这个角色变得如此舒适。我将在这里与你分享这些相似之处,因为我描述了迄今为止作为项目经理的经历。
创建课程=创建项目时间表
在教学中,你所教的东西是由课程来指导的。课程是一个时间表,记录了你要教什么,什么时候教,以及你教这些概念的顺序。这些课程是由教师根据州教育部门指定的主题设计的。
作为项目经理,相当于课程表的是项目时间表。这是一份包含您和您的团队发布产品所需完成的主要步骤的文档。这将包括何时创建某些特性,何时进行质量检查,以及何时获得涉众的批准或反馈。我作为一名教师创建课程的经验使得创建项目时间表变得更加容易,因为它们的结构是相似的。
了解学生的能力=了解团队的能力
教师了解学生的能力,因此他们知道为未来的课程提供多少脚手架。这一点很重要,尤其是如果你的课程(甚至课堂)是建立在学生们上一堂课的基础上。你通常会在最初通过评估发现这些技能。
蒂姆·莫斯霍尔德在 Unsplash 上的照片
对于担任 QC PM 角色的团队成员,我进行了技能调查。它询问他们的技能以及他们喜欢的质量控制任务。结合他们在办公室的角色,我可以根据这些数据分配适当的质量控制任务。
满足学生需求=满足团队成员需求
学生需要支持才能在教育中取得成功。这对于每个孩子来说都是独一无二的,取决于他们之前的教育经历和学习风格。这是什么通知教师什么误解应该预期和什么支持需要到位的每一课。对于那些在这门学科上苦苦挣扎的学生,或者那些遭遇不幸导致学习困难的学生来说,情况尤其如此。
对于项目经理来说,学生的需求转化为团队成员的需求。你的团队成员使你的产品成功。你需要满足他们的需求,这样才能实现。这意味着提供以下项目:
- 任务和时间表的清晰说明
- 提供产品所需的数据或数据位置
- 为你的团队成员提供基于用户需求的指导
- 了解团队成员的能力,以便分配适当的任务
- 当团队成员遇到个人情况时,给予他们支持(例如当他们需要休息时,知道并尊重他们)
课程计划=说明准备
照片由格伦·卡斯滕斯-彼得斯在 Unsplash 拍摄
当学生学习新概念时,他们当然是第一次看到它们。由于这个原因,步骤和解释需要清楚。为了确保这一点,教师为他们的课程制定了教学计划。这充当了教师如何向一组给定的学生教授该概念的指示或方向。
我的 QC PM 角色的课程计划相当于为给定产品的每组 QC 任务制作页面。这些将基于产品经理的请求。从那里开始,我会对每项任务进行一步一步的指导。这将包括产品的图片在步骤可能会不清楚,特别是对于那些第一次看到产品。根据我们回顾会的反馈,我会不断地收到对这种方法的称赞,因为这些指导是如此的清晰。这个反馈也来自一个加入我们团队的人,他对其中一个产品完全不熟悉。
当场回答问题=当场解决问题
尽管你认为你已经涵盖了你的学生在学习一个概念时可能会有的所有误解,但更有可能的是,通常还有另一个你没有考虑到的误解。从那以后,你所能做的就是解决误解,并记住下次如何处理它。
照片由🇻🇪·何塞·g·奥尔特加·卡斯特罗·🇲🇽在 Unsplash 上拍摄
我的质量控制过程第一次并不是万无一失。对于某些任务,尽管我与产品项目经理进行了交谈,但我并没有涵盖所有内容。我们是人类。经前综合症会忘记一些事情。执行质量控制任务的人会推荐一种更省时的替代质量控制方法。因为我们有 4 个发布阶段,所以产品质量控制也有 4 个阶段。如果在一个早期 QC 阶段提出了最佳替代方法,我会立即将其纳入下一个 QC 阶段。
不要低估教学技巧
感谢您花时间阅读这篇文章!如果你是老师,要知道你的技能可以转移到项目管理中。我们基本上是在用产品和成人来交换学生。对于那些在你的项目经理候选人中寻找教师的人来说,要知道他们的教学经验会让他们在项目管理方面有一个你没有预料到的领先优势(但现在你会想到,如果你读了这篇文章😊).
如果你喜欢在媒体上阅读,并愿意进一步支持我,你可以使用我的推荐链接注册一个媒体会员。这样做可以用你的会费的一部分在经济上支持我,我将不胜感激。
另外,如果你喜欢这篇文章,可以看看下面类似的文章:
</7-reasons-you-should-blog-during-your-data-science-journey-4f542b05dab1>
如果你有任何问题,请随时在 Linkedin 和 Twitter 上发表评论或联系我们。对 Twitter 上的 DM 开放。
下次见!
约翰·德杰苏斯
贝塔分布如何联系分类和投掷硬币
这个问题源于对一家旧金山初创公司的采访
假设你有一枚硬币,但对正面概率一无所知。假设它在 0 和 1 之间均匀分布是合理的(因为我们还没有看到任何数据,所以没有理由优先选择任何概率)。现在,你投掷 10 次,看到 6 个正面和 4 个反面(虽然 60% 是最合理的估计,但也可能是一枚公平的硬币)。根据这些新信息,概率的分布是如何变化的?原来,它现在是一个测试版。现在让我们考虑排序。
假设您从一个均匀分布中生成了 n 个样本,并将它们放入一个数组中。然后,对数组进行排序,并询问排序后数组中第一项的分布情况(或第 n 个样本中的最小值),第二项的分布情况,依此类推。这些恰好有一个贝塔分布。现在把制服换成任何阳光下的连续分布(或其他)。我们也可以用这个技巧来描述它的顺序统计量!
我们可以看到测试版在两个看似不相关的应用程序中弹出。它们之间有什么关系?在这篇博客中,我们将把这两者联系起来,并展示它们是怎么一回事。
你可以在这里看到贝塔分布的全密度函数:https://en.wikipedia.org/wiki/Beta_distribution,但是这篇文章我们需要记住的是,它与 p(x-1).成正比(1-p)(y-1) 其中 p 是我们建模的正面概率, x 是我们从硬币上看到的正面数量, y 是我们从硬币上看到的反面数量。让它与 px.(1-p)y 成比例会更自然,但我们有一个很好的理由让-1 成比例。见[这里](http://nt.number theory - Why is the Gamma function shifted from the factorial by 1? - MathOverflow)和这里。
与投掷硬币相关的概率密度函数和顺序统计(涉及对数组进行排序并挑选出不同位置的元素)都可以在数据科学中找到用途,从定义关键性能指标(KPI)到假设检验。
I)背景:贝氏更新与测试
贝塔分布因其是二项式和伯努利分布的参数 p 的“共轭先验”而闻名。这是什么意思?从贝叶斯法则开始。如果我们有两个事件 A 和 B ,贝叶斯规则描述了以 A 发生为条件的 B 的概率,可以写成:
用 Latex 为本文创建的方程。
如果我们将 A 解释为观察到一些数据的事件,将 B 解释为一些模型,我们可以将 P(B) 认为是我们观察到数据之前模型的“先验概率”,将 P(B|A) 认为是我们观察到数据之后模型的“后验概率”(并因此更新了模型)。
这显示在下面的彩色方程式中。
用 Latex 为本文创建的方程。
在我们的上下文中,我们可以将描述硬币正面概率的参数 U 解释为“模型”。抛硬币看到 a 正面和 b 反面的事件就是我们收集的数据。根据贝叶斯方程匹配颜色方案,我们得到以下结果:
用 Latex 为本文创建的方程。
这就是“共轭先验”部分的用武之地。如果我们假设先验(绿色部分), P(p < U < p+δp) 是带有参数 x-1 和 y-1 的贝塔分布(记住,这意味着硬币到目前为止已经向我们展示了 x 正面和 y 反面),那么紫色的后验也是带有更新参数 x+a-1 和的贝塔分布首先,让我们把等号改成比例号,这样我们就不用担心烦人的归一化常数了。
在 PowerPoint 中为本文创建的等式。
数据(红色)的概率就是二项式分布,我们提到贝塔先验与p(x-1)(1-p)(y-1成比例。插上这些
在 PowerPoint 中为本文创建的等式。
我们意识到的最终结果只是另一个 Beta 分布,它的参数已经更新为 (x+a-1) 和 (y+b-1)
就像我们已经提前看到了 x 正面和 y 反面,额外的投掷向我们展示了 a 更多的正面和 b 更多的反面。因此,如果我们一开始就看到了 (x+a) 正面和 (y+b) 反面,那么更新后的模型将会得到同样的东西。
这可以用下图来概括。它说当 U 是参数为 a 和 b 和 X 条件为 U=p 是参数为 n 和 p 的二项式,那么条件为 X=x 的 U 变成参数为 a+x 和 b+n-x 【T 请注意配色方案,因为我们将使用它。
等式(1):二项分布的贝它贝叶斯更新,x。在 PowerPoint 中为本文创建的等式。
II)背景:订单统计和 Beta
假设我们有一些连续的概率分布。我们想找到它的订单统计数据。例如,估算你所在国家的中等家庭收入。你可以选取一些家庭(比如说 n )作为样本,按照收入升序排列,然后选取列表中的中间一个。一般来说,如果我们有 n 个数据点,对它们进行升序排序,取第 k 个,这叫做第 k 个“顺序统计量”(我们必须对数据进行排序才能得到它,它是一个总结数据的单一统计量)。顺序统计对于从有限样本中估计中位数和其他分位数非常重要(通常在数据科学的上下文中用作 KPI)。那么测试版对他们有什么帮助呢?通过以下方式:
- 事实:如果我们知道逆 CDF (CDF 从分布的定义域中取一点,并返回分布小于它的概率;逆 CDF 将一个概率作为输入,并返回一个点,使得下面的概率质量等于该概率),我们可以首先生成一个均匀的随机数 U ,然后将它传递给逆 CDF,以从分布中获得一个样本 X 。这是逆变换采样方法的基础,用于从任何连续分布中生成随机样本,前提是我们可以轻松找到其逆 CDF。只需生成制服并将其插入逆向 CDF..
- 注释:如果我们有一个数组,[ X_1,X_2,…,X_n ] 来自一个分布的样本,如果我们对这个数组进行排序,得到的数组表示为:[ X_(1),X_(2),…,X_(n) 。这个排序后的数组是订单统计数据的数组。
现在,如果我们想要生成具有逆 CDF F_X^-1(x) 的某些分布的 n 阶统计量,我们可以通过两种方式着手:
- 下图右分支:生成 n 个均匀随机数,然后对它们应用逆 CDF,排序。
- 下图的左分支:生成 n 个均匀随机数,先排序再应用逆 CDF。
图 2:获得任何连续分布的顺序统计的两种方法。要么先生成一致性,使用逆变换采样映射到分布,然后进行排序(右分支),要么先对一致性进行排序,然后对排序后的值应用逆 CDF。在 PowerPoint 中为本文创建。
对于左分支,作为中间步骤,我们得到均匀分布的顺序统计量。碰巧这些都是贝塔分布的。因此,要获得一般分布的第 k- 个 n 个顺序统计量,您可以首先生成代表均匀阵列的第 n 个 k 个顺序统计量的 Beta 分布,然后将您想要的任何分布的逆 CDF 应用于该 Beta 分布。
III)连接两个
现在,我们需要做的就是确定均匀分布( U_(k) )的 k 阶统计量是什么样的β。
- U_(k) 是一个均匀随机数,条件是 k-1 其他均匀数小于它, n-k-1 大于它。
- 我们可以把这个我们想要应用条件的均匀随机数想象成一个硬币。如果我们生成另一个制服,它低于它,我们认为这是一个头。否则,我们认为它是一个尾巴。这个数字的值就是硬币正面的概率(与 Beta 出现的联系)。
- 因此,我们正在处理的事件,即 (k-1) 制服位于感兴趣的制服之下而 (n-k) 位于制服之上,这相当于说我们将硬币抛了很多次,观察到了 (k-1) 正面和 (n-k) 反面。
- 我们已经看到,这种硬币的正面概率是β分布,参数为 k 和 n-k+1 。但是这个概率相当于我们的利益一致。因此,它也必须由相同贝塔分布给出。
我们可以在第一部分的末尾画一个类似于等式-1 的东西,并使用相同的配色方案来观察事物如何排列以产生结果。
等式(2):使用来自等式(3)的贝塔贝叶斯更新来推断均匀分布的顺序统计量的分布。在 PowerPoint 中为本文创建。
IV)悖论:测量统一订单统计的分布
正如我们建立了均匀分布的次序统计量的差是贝塔分布一样,我们可以将同样的技术应用于均匀分布的次序统计量的差。比如 10 制服抽的时候 U_(6)-U_(3) 的分布是怎样的?
我们已经可以看到这个差异将会在 0 和 1 之间。事实上,我们可以稍微修改一下我们用来推断 U_(k) 是β的推理,参数是 k 和 n-k+1 (硬币正面的概率分布,显示给我们的是 k-1 正面和 n-k 反面)。
当时,我们将从 0 到 U_(k) 的区间映射为硬币正面朝上的概率。现在,间隔是从 U_(j) 到 U_(k) 。根据定义,我们已经看到 (k-j-1) 制服属于这个区间。所以我们从假想的硬币上观察到的头像数量现在是 (k-j-1) 。而剩下的(n-2-(k-j-1))=**(n-k+j-1)制服已经在这个区间之外落地了( n-2 在最前面,因为我们这次排除了 U_(k) 和 U_(j) 对应的两个制服)。这相当于从硬币上看到许多尾巴。所以,这应该是一个带有参数 k-j 和 n-k+j. 的贝塔分布,但是,如果你看一下维基百科关于顺序统计的文章中关于顺序统计的概率分布的文章,这同意分布是贝塔但说参数是 k-j 和 n-k+j+1 。我们的报价似乎只差一个错误。如果维基百科的文章是正确的,我们的推理哪里出错了?
另一条攻击线
让我们探索另一条推理路线。关于 U_(6)-U_(4) 与 U_(4)-U_(2) 的分布,你觉得有什么可说的吗?如果我们想象一下 10 均匀随机数将 0 和 1 之间的区间分成 11 大致相等的部分会怎么样?原来 U_(k)-U_(j) 的分布和 U_(k-i)-U_(j-i) 的分布是一样的(移位两个顺序统计量)。这甚至适用于 i=j ,这给了我们 U_(k-j)-U_(0)。在这里, U_(0) 被解释为分布可以取的最小值(对于均匀分布是0;与 U_(1) 相反,后者是 n 个样本中的最小值,而不是 0 。现在问题回到寻找第 k 阶统计量的分布,我们知道它是 Beta,带有之前的参数 k 和 n-k+1 。只是这一次,我们需要用 k-j 代替 k ,这就给了我们参数: k-j-1 和 n-j+k+1 。现在我们同意维基百科的文章了!
这整个论点取决于这样一个事实,即当它们的指数移动时,统一的顺序统计量的差异保持它们的分布(通过 i 的减法)。所以我们将从视觉上证明这一点。
1 —映射到圆
首先,让我们在 (0,1) 上取对应均匀分布的线,卷成一个圆。
为本文创建的图片使用:https://github.com/ryu577/pyray
在直线上均匀地生成三个(或 n )点将等同于在圆上均匀地生成三个点,因为我们总是可以将直线滚动到圆上,然后再返回直线。如果直线的任何部分都不可能得到其中一个点(均匀的定义),那么圆的任何部分也不可能得到。
2 —先旋转圆圈
我们已经确定,在圆上均匀地随机生成 n 个点,然后将其分解成一条线,这与首先在这条线上生成 n 个点是一样的。如果我们在把圆分解成直线之前,把它旋转任意角度,θ,会怎么样?这也不会改变结论,因为圆的每一部分都同样可能得分,旋转它也不会改变这个事实。
为本文创建的图片使用:【https://github.com/ryu577/pyray
3 —生成额外的制服,以选择在解开的位置
因为我们可以在以我们喜欢的方式解开圆之前选择旋转圆的随机角度,所以我们也可以在圆上生成另一个均匀的数字(除了我们已经生成的 n 之外),然后旋转,使得该数字在该点解开之前与水平轴对齐。但这使得这个过程相当于在圆上生成 n+1 个均匀随机数,旋转使得其中任意一个与横轴接触,然后解开。
为本文创建的图片使用:【https://github.com/ryu577/pyray
最后,展开围绕该点的圆。
为本文创建的图片使用:https://github.com/ryu577/pyray
这将使我们在解开的线上的 0 和 n 点处留下一个点。而那 n 个点均匀分布在上面。
4 —将不同的点标记为绿点
现在妙语连珠了。我们可以将这四个点中的任何一个标记为初始的“绿点”,来解开这条线。下图显示了四种选择的最终统一线条:
为本文创建的图片使用:https://github.com/ryu577/pyray
我们看到,点 1 和 2 之间的距离可以是 U_(1)-U(0),U_(2)-U_(1),U_(3)-U_(2) 或 U_(2)-U(1) 中的任何一个,这取决于我们解开的绿点的选择。但既然那是相同的距离,那么顺序统计量中的那些差异就一定具有相同的分布。我们在这里证明了 U_(k+1)-U_(k) 的分布是平稳的,但是这个论证一般可以推广到 U_(k)-U_(j) 。
修正原论点
最初论点的主要问题是,我们现在看的是一个区间, |U-U'| ,其中 U 和 U' 是两个独立的均匀随机数。虽然单一的均匀分布是平坦的 Beta(1,1)分布,但这个区间不是。它实际上是一个 Beta(1,2)分布。换句话说,时间间隔的分布就像我们已经扔过一次硬币,观察到了反面。
这是因为 |U-U'| 和我们生成两个制服时的 U_(2)-U_(1) 分布是一样的。通过上面的论证,我们可以转移这个,并得出分布与U _(2–1)-U _(1–1)= U _(1)-U _(0)= U _(1)相同的结论。从第三节我们知道,这就像扔硬币,观察一个反面或 Beta(1,2)。这里有一个同样结果的几何证明。
考虑到第二个 2 参数将会修正我们之前看到的一个错误。
- U_(k)-U_(j) 的分布与| U-U’|的分布相同,条件是 k-j-1 内有其他均匀数, n-k-2 外有其他均匀数。 |U-U'| 无任何条件的分布为 Beta(1,2)
- 我们可以把我们想要应用条件的这个区间想象成一个硬币。如果我们生成另一个制服,它落在区间内,我们认为是一个头。否则,我们认为它是一个尾巴。这个数字的值就是硬币正面的概率(与 Beta 出现的联系)。
- 因此,我们正在处理的事件,即 (k-j-1) 制服位于我们感兴趣的区间内而 (n-k-2) 位于区间外的事实,相当于说我们投掷硬币很多次,观察到 (k-1) 正面和 (n-k-2) 反面。
- 根据之前的观察,如果正面概率是带有参数 x 和 y 的β先验,并且我们观察到 a 附加正面和 b 附加反面,则参数更新为 a+x 和 b+y,我们得到期望的结果。这显示在下面的等式中,该等式将我们所说的一切映射到等式-2(使用相同的配色方案)。
等式(3):应用来自等式(2)的贝塔贝叶斯更新来推断制服的两个次序统计量之间的差异的分布。在 PowerPoint 中为本文创建的等式。
如果你喜欢这个故事,成为推荐会员:)
https://medium.com/@rohitpandey576/membership
PyTorch 卷积如何工作或者如何将两个卷积折叠成一个
或者仔细看看深度学习工程师的卷积
本文有两个目标。第一个是展示如何将两个 PyTorch 卷积合并成一个。如果你想要实现,滚动文章到最后。
第二,主要目标是通过卷积合并的例子更仔细地研究卷积实现。我们将学习它们是如何被存储和使用的,特别是在 PyTorch 中,没有像 im2col 这样的核心细节。
在我们开始研究实现之前,让我们记住我们在做什么。
先说术语。神经网络或计算图形是应用于输入对象或其他操作输出的一组操作(层)。我们对计算机视觉和卷积感兴趣,所以输入对象会是一张图片:大小为[通道数 X 高度 X 宽度]的张量,其中通道数最常为 3 (RGB)。中间输出将被称为特征图。特征图在某种意义上是同一张图片,只是通道的数量是任意的,张量的每个单元称为一个特征,而不是一个像素。为了能够在一次运行中同时运行几个图像,所有这些张量都有一个额外的维度,其大小等于该批(一次运行)中对象的数量。
现在让我们继续讨论互相关。它经常与卷积混淆,但为了我们的目的,这两种运算必须加以区分。什么是神经网络环境中的互相关?首先,互相关是有核的。核是一个形状为[通道数 X 核高 X 核宽]的张量。并且互相关操作可以被表示为沿着输入特征图滑动离开内核,如同在 gif 上一样。每次我们将一个核应用于一段输入时,我们将相应的核权重与特征相乘,并将它们相加,从而在输出通道中获得一个新的特征。
wikipedia.org[wikipedia.org)
是时候告诉你什么是卷积了。卷积几乎是互相关的,只有核相对于水平和垂直轴被反映。这种差异通常被忽略,因为它对于理解神经网络并不重要,但这次这种差异很重要,因为我们将直接使用权重。
您可能已经注意到,上述卷积从一组通道中创建了一个通道。在神经网络中,卷积从一组通道创建另一组通道。这是通过将上述几个内核同时存储在卷积层中来实现的,每个内核生成一个通道,然后将它们连接起来。这种卷积的核心的最终尺寸是:[每个输出的通道数 X 每个输入的通道数 X 核心高度 X 核心宽度]
PyTorch 和许多其他框架中卷积层的下一部分是 bias。偏置是每个输出通道的附加项。因此,偏置是一组参数,大小等于输出通道的数量。
是时候记住我们的任务了。任务是将两个卷积合并成一个。为什么这是可能的?简而言之,卷积和偏置加法是线性运算。并且线性运算的组合是线性运算。如果这个解释不够清楚,也不要难过。下面的例子将在实践中证明这一说法。
先说最简单的情况。一个任意大小的卷积,第二个 1x1。他们都没有偏见。两者都从一个通道生成一个通道。1x1 的卷积使得这种情况更加简单。实际上,它意味着将特征图乘以一个常数。所以,你可以简单地用这个常数乘以第一次卷积的权重。
让我们使它变得更有趣。现在让第一个卷积将任意数量的通道转换成另一个任意数量的通道。在这种情况下,我们的 1x1 卷积将是中间特征映射通道的加权和。这意味着你可以对产生这些通道的权重进行加权求和。
让我们把它变得更有趣。现在让我们的卷积将任意数量的通道转换成另一个任意数量的通道。在这种情况下,我们的 1x1 卷积将是中间特征映射通道的一组加权和。这里的逻辑是一样的。有必要将产生中间特征的权重与来自第二卷积的权重相加。
现在,是时候放弃对二次卷积大小的限制了。为了简化,我们来看一个一维卷积。内核 2 的操作“k”会是什么样子?
让我们添加内核大小为 2 的额外卷积“v ”:
重新格式化等式:
最后,让我们添加一些零。
我们得到了什么?结果是与核 3 的卷积。并且该卷积中的核是应用于第一卷积的填充权重与由第二卷积的权重创建的核的互相关的结果。对于其他尺寸的内核,对于二维情况和多通道情况,相同的逻辑起作用。但是我不会为这些复杂的情况提供数学知识,相反,我会向你展示如何将这个想法转化为代码。
现在让我们加上偏见。我们将从第二个卷积中的偏差开始。让我提醒你,偏置是一个矢量,其大小等于输出通道的数量,然后与卷积的输出相加。这意味着我们只需要把第二个卷积的偏差放到结果中。
给第一个卷积加上一个偏差稍微复杂一点。因此,我们将分两个阶段走。首先,我们注意到在卷积中使用偏差相当于创建一个额外的特征图,其中每个通道的特征将是常数并且等于偏差参数。然后将此特征添加到卷积的输出中。
但是我们不想每次都创建这个额外的特征,我们想以某种方式改变卷积参数。我们可以做到。仅仅注意到在恒定特征图上应用卷积之后,将获得另一个恒定特征图就足够了。动机很简单——无论我们把窗户放在哪里,切片都是一样的。因此,我们只需对该特征图进行一次卷积,看看每个通道上有哪些特征,然后进行偏差处理。
剩下的只是把它们都包装在一个函数中,去掉维度的神奇常数。
在文章的最后,我想说我们的函数不会对每个卷积都起作用。在这个实现中,我们没有考虑填充、膨胀、步幅或组。但尽管如此,我展示了我想要的一切。进一步改进它可能没有什么意义,因为我只见过一次将两个卷积折叠成一个卷积的任务,这里是,即使在这里,第二个卷积也是 1x1。
如何通过 XLA 加速您的 PyTorch GPU 培训
原文:https://towardsdatascience.com/how-to-accelerate-your-pytorch-training-with-xla-on-aws-3d599bc8f6a9
PyTorch/XLA 的力量以及亚马逊 SageMaker 培训编译器如何简化其使用
按作者
在我们过去的许多帖子中(例如这里),我们都强调了管理培训成本的重要性。我们一直在寻求通过迭代过程 1 来提高训练运行时性能的方法。 分析 我们的工作负载,以确定性能瓶颈和资源利用不足,以及 2 . 优化 我们的工作负载以消除瓶颈并提高资源利用率。
在这篇文章中,我们探索了通过使用 XLA 编译来优化我们 PyTorch 训练步骤的潜力。我们将从 XLA 的简介开始。接下来我们将演示它在 AWS 上的使用,并展示Amazon sage maker Training Compiler如何简化它的配置。我们将以 XLA 带来的一些(当前的)限制来结束。
放弃
我们在这篇文章中的目的是介绍加快 PyTorch/XLA 培训的潜在机会。我们的目的不是认可它的使用,也不是认可我们将提到的任何其他培训工具的使用。与往常一样,最佳培训配置高度依赖于您的模型的具体细节。我开篇的那首诗是为了娱乐目的收录的(我忍不住)。尽管有其含义,但不能保证 PyTorch/XLA 会加快你的训练。虽然我们的重点(和演示)将是 Amazon SageMaker 培训环境,但我们讨论的大部分内容也适用于其他培训环境。
与 XLA 的 JIT 编译
最初创建是为了加速 TensorFlow 工作负载,XLA(代表T5 AcceleratedLlinearA**代数采用 Just in Time (JIT)编译技术来优化底层加速器的计算图。更具体地,在运行时,XLA 编译器将分析与模型相关联的完整计算图,将连续的张量运算融合在一起,并输出用于底层加速器的最佳机器代码。这与标准方法相反,在标准方法中,每个张量运算都是独立优化的。融合图形组件可以通过多种方式提高性能,包括:**
- 减少总体机器级操作(FLOPS)的数量,
- 减少需要由 CPU 加载到加速器中的计算内核的数量,以及
- 减少计算图的内存占用。释放的空间可用于增加训练批次大小,这可能会进一步提高性能。
如 XLA 概览页面所示,优化整个图表而非单个操作有可能减少培训时间。
顺便提一句,XLA 的另一个优势是它是专门为支持新的后端设备而设计的。更多详情请参见此处的和此处的。
XLA 换火炬
与 TensorFlow 相反,为 PyTorch 实现 XLA 提出了一个独特的挑战,我们将在下面的小节中解释。
急切执行与图形执行
深度学习框架可以根据它们表示和执行机器学习模型的模式进行分类。一些框架,最著名的是 TensorFlow(在 v1 中默认,在 v2 中通过 tf.function ),支持图模式,其中模型首先被表示为计算图(在 Python 中),然后由单独的执行引擎处理和执行(例如,在 C++中)。其他框架,比如 PyTorch,急切地执行它们的模型,也就是说,模型不是存储在数据结构中,而是直接执行每一行代码。许多人认为 Eager 模式更容易调试,并且支持更强的编程表达能力。这通常被视为 PyTorch 框架最近越来越受欢迎的原因(截至本文撰写之时)。
查看这篇文章了解更多关于这两种执行模式的区别。
显然,考虑到图定义和图执行之间的分离,XLA 的 JIT 编译机制与图模式的执行方法非常一致。支持 XLA 和急切执行模式需要更多创意。有几种方法可以解决这个问题(参见本文的第 2 节进行简单的调查)。正如我们将看到的,在 PyTorch/XLA 库中引入和使用的方法是懒惰张量系统。
PyTorch/XLA
PyTorch/XLA 是一个 Python 库,其创建的主要目的是使用 XLA 编译来支持在 Google Cloud TPUs 上进行基于 PyTorch 的训练(例如,参见这里的)。PyTorch/XLA 的基本方法是惰性张量系统。惰性张量是一种定制的张量类型,在 PyTorch/XLA 中被称为 XLA 张量。与标准 PyTorch 张量相反,操作不会立即(或“急切地”)执行,而是收集到形成中间表示(IR)图的操作序列中。当被提示时(例如,在每个训练步骤结束时),IR 图被传递到 XLA 编译器,在那里它经历对底层加速器的优化。通过这种方式,惰性张量系统支持领域特定编译** (DSC),同时保持热切执行的外观和感觉,这是 PyTorch 培训框架的标志。虽然使用惰性张量可以在不改变模型定义的情况下进行 XLA 编译,但了解标准张量和 XLA 张量之间的细微差别很重要。关于懒惰张量的更多细节以及如何理解他们的行为,请务必查看这篇内容丰富的帖子。**
用于 GPU 的 PyTorch/XLA
虽然 API 文档描述 PyTorch/XLA 支持所有 XLA 设备、包括 GPU,但是您可能会发现,在撰写本文时,对 Google Cloud TPUs 的支持已经被高度优先考虑。天真地搜索“py torch/GPU 上的 XLA”会出现几个关于其支持的免责声明,以及一些创建自定义 GPU 支持构建的非官方说明(例如,参见 this github issue )。
令人欣慰的是,一些云服务提供商已经创建了 docker 映像,专门支持 GPU 上的 PyTorch/XLA。在 GCP 可用支持见此处,在 AWS 最新支持图片见此处。在下一节中,我们将使用亚马逊 SageMaker 培训服务提供一个在 GPU 上使用 PyTorch/XLA 的例子。
py torch/AWS 上的 XLA
在下面的代码块中,我们展示了如何使用 torch_xla,PyTorch/XLA Python 模块来训练一个 HuggingFace 视觉转换器模型。为了突出 torch_xla 流和标准流之间的区别,我们实现了这两个流,并添加了一个“ is_xla ”标志来在它们之间切换。代码假设我们将在一个有 8 个 GPU 的实例上运行。我们强调了一些 XLA 特有的代码行。
import time
import torch
import os
import json
from torch.utils.data import Datasetnum_gpus = 8
**is_xla = True**if is_xla:
import torch_xla.core.xla_model as xm
import torch_xla.distributed.parallel_loader as pl
if os.environ.get('XRT_WORKERS') is None:
**# Add ENVARS required for XLA** host=json.loads(os.environ["SM_HOSTS"])[0]
os.environ["XRT_WORKERS"] = f'localservice:0;{host}:43857'
os.environ['XRT_SHARD_WORLD_SIZE'] = '1'
os.environ['XRT_HOST_ORDINAL'] = '0'
os.environ['FI_EFA_USE_DEVICE_RDMA'] = '1'
os.environ['NCCL_PROTO'] = 'simple'
os.environ['XLA_FIX_DIV_FP64'] = '1'
os.environ['OFI_NCCL_NIC_DUP_CONNS'] = str(num_gpus)
os.environ["GPU_NUM_DEVICES"] = str(num_gpus)
else:
# DDP setup
import torch.distributed as dist
def setup(rank, world_size):
os.environ['MASTER_ADDR'] = os.environ.get('MASTER_ADDR',
'localhost')
os.environ['MASTER_PORT'] = os.environ.get('MASTER_PORT',
str(2222))
dist.init_process_group('nccl', rank=rank,
world_size=world_size)
# wrap the model with DDP
def wrap_model(model,local_rank):
from torch.nn.parallel import DistributedDataParallel as DDP
model.to(torch.cuda.current_device())
model = DDP(model,device_ids=[local_rank])
return model# A fake dataset
class FakeDataset(Dataset):
def __len__(self):
return 10000000
def __getitem__(self, index):
rand_image = torch.randn([3, 224, 224], dtype=torch.float32)
label = torch.tensor(data=[index % 1000], dtype=torch.int64)
return rand_image, labeldef build_model():
from transformers import ViTForImageClassification, ViTConfig
return ViTForImageClassification(ViTConfig(num_labels=1000))def main(rank, world_size=num_gpus):
dataset = FakeDataset()
model = build_model()
**if is_xla:
device = xm.xla_device()
rank = xm.get_local_ordinal()** model = model.to(device)
else:
setup(rank, world_size)
torch.cuda.set_device(rank)
model = wrap_model(model,rank)
batch_size = 128
optimizer = torch.optim.Adam(model.parameters())
data_loader = torch.utils.data.DataLoader(
dataset,
batch_size=batch_size,
num_workers=12)
**if is_xla:
data_loader = pl.MpDeviceLoader(data_loader, device)** loss_function = torch.nn.CrossEntropyLoss()
t0 = time.perf_counter()
for idx, (inputs, targets) in enumerate(data_loader, start=1):
if not is_xla:
inputs = inputs.to(torch.cuda.current_device())
targets = targets.to(torch.cuda.current_device())
targets = torch.squeeze(targets,-1)
optimizer.zero_grad()
outputs = model(inputs)
loss = loss_function(outputs['logits'], targets)
loss.backward()
**if is_xla:
xm.optimizer_step(optimizer)
else:
optimizer.step()** if rank == 0 and idx%1000 == 0:
batch_time = time.perf_counter() - t0
print(f'step: {idx}: mean step time is {batch_time/1000}')
t0 = time.perf_counter() if not is_xla:
dist.destroy_process_group()def _mp_fn(index):
main(index)if __name__ == "__main__":
if is_xla:
import torch_xla.distributed.xla_multiprocessing as mp
else:
import torch.multiprocessing as mp
mp.spawn(_mp_fn, nprocs=num_gpus, join=True)
为了在 Amazon SageMaker 中运行培训脚本,我们需要对我们的培训作业进行编程,以使用其中一个 docker 映像,该映像包含一个 torch_xla 版本,该版本经过专门配置和调整,可以在 Amazon SageMaker 的 GPU 培训实例上运行。
**image_uri = "763104351884.dkr.ecr.us-east-1.amazonaws.com/" \
"huggingface-pytorch-trcomp-training:1.11.0-" \
"transformers4.21.1-gpu-py38-cu113-ubuntu20.04"**from sagemaker.pytorch import PyTorch
estimator = PyTorch(entry_point='train.py',
role=<role>,
instance_type='ml.p4d.24xlarge',
instance_count=1,
**image_uri=image_uri**)estimator.fit()
诚然,我们上面分享的培训脚本有点乱。特别是环境变量设置,需要大量的反复试验,(以及一些逆向工程)。在下一小节中,我们将展示如何使用 Amazon SageMaker Training 编译器获得一个更简洁、更通用的解决方案。
亚马逊 SageMaker 培训编译器
亚马逊 SageMaker 训练编译器是亚马逊 SageMaker 的一项功能,旨在加速 SageMaker 管理的 GPU 实例上深度学习模型的训练。在引擎盖下,SageMaker Training 编译器通过以我们上面描述的方式使用 XLA 编译来实现训练加速。对于其 PyTorch 支持,SageMaker Training 编译器加载一个定制构建 torch_xla 的 docker 映像,自动配置培训环境供其使用,并启动 xla 培训作业。特别是,SageMaker Training 编译器设置了所有模糊的(未记录的)环境变量,从而将用户所需的操作减少到几个简单的步骤。
下面的代码块展示了如何用 Amazon SageMaker 培训编译器启动我们的 PyTorch 培训工作。
from sagemaker.huggingface import HuggingFace, TrainingCompilerConfigdistribution={'pytorchxla': {'enabled': True}}estimator=HuggingFace(entry_point='train.py',
role=<role>,
instance_type='ml.p4d.24xlarge',
instance_count=1,
transformers_version='4.21.1',
pytorch_version='1.11.0',
compiler_config=TrainingCompilerConfig(),
distribution=distribution)estimator.fit()
请注意,如果您的训练脚本使用了 HuggingFace transformer 模型,您可以通过使用高级 Huggingface 训练器 API 来进一步简化 SageMaker 训练编译器(和 torch_xla)的使用,如特性文档中所述。
请务必查看功能文档了解更多详情。关于不同使用模式的示例,参见 API 文档。
结果
在下表中,我们比较了 Vision Transformer 在使用和不使用 XLA 编译时的运行时性能,以每秒个样本来衡量。
XLA 编译对每秒采样数的影响—越高越好(作者)
应用 XLA 编译将我们模型的性能提高了 ~15% 。我们再次强调,XLA 编译的潜在好处非常依赖于模型的细节。在不同的 ML 模型上运行相同的实验可能会产生非常不同的比较结果。
请注意,XLA 跑的步长时间稳定下来需要大约 10,000 步,或者接近一个小时。这是 XLA 编译的一个已知症状。
XLA 限制
在使用 XLA 编译器之前,了解它的一些限制是很重要的。
模型依赖性
在这篇文章中,我们强调了这样一个事实,XLA 为提供了潜在的性能提升,但不是性能提升的保证。您是否会从使用 XLA 中受益,如果会,性能会有多显著,都高度依赖于您的模型的具体情况。在某些情况下,例如当模型包含动态形状的张量时,您可能会发现使用 XLA 会降低性能。虽然通常很难预测你的模式是否“XLA 友好”,但有几个资源(如此处)应该可以为你提供一些一般性的指导。
正如我们在上面的例子中看到的,XLA 编译是一个发生在多个训练步骤中的过程。根据您的模型,训练步长收敛到其 XLA 最优值可能需要几分钟或更长时间。特别是,如果你的整体训练持续时间相对较短,你可能看不到使用 XLA 的好处。
调试和实验的局限性
PyTorch 培训框架及其热切的执行策略流行的原因之一是它简化了调试和实验。在 PyTorch 中,人们可以计算任何中间张量的值,而不需要跳来跳去这样做(如在图形模式执行中)。通过采用 XLA 汇编,我们基本上放弃了这一点。可以通过支持 XLA 和非 XLA 流来减轻这种限制(如上面的脚本所示),但是,我们看到的行为总是有可能是 XLA 流所独有的。
使调试和实验变得复杂的另一个因素是我们的训练依赖于定制的 torch_xla 构建。截至本文写作时,还没有官方的 torch_xla Python 包。在受控环境中评估 XLA 行为的一个选项是从 CSP 的映像库中提取 XLA 特定的 docker 映像(或者使用 SageMaker 的本地模式来完成)。PyTorch/XLA 文档包括配置 torch_xla 在 CPU 上运行的指令。然而,您可能会发现在本地 GPU 上运行 docker 映像更具挑战性。无论如何,以这种方式进行调试和试验显然是有局限性的,而且远非理想。
代码调整
使用 torch_xla 需要大量的代码修改。这些可以分为两种类型,使用 torch_xla 所需的对培训流程的调整,以及使用 torch_xla 时作为最佳实践推荐的调整。在上面的代码示例中,我们演示了一些最基本的所需的修改。在实践中,经常需要额外的修改来保存和加载模型,集成自动混合精度等等。这里记录了所需的调整。这里有几个资源,比如这里的这里的和这里的,描述了推荐的改编以最大限度地利用 torch_xla。这些通常旨在最大限度地减少 XLA 汇编的次数。只有当模型可以被 XLA 编译一次并在所有后续步骤中重用时,它们才会从使用 XLA 中受益。需要频繁 XLA 编译的模型(例如,张量具有动态形状的模型)不会从使用 torch_xla 中受益。引用这篇推荐的博客文章,其中包括使用 torch_xla 的最佳实践,“编译一次,经常执行”。****
代码修改,不管它们是必需的还是推荐的,都会使 torch_xla 的使用复杂化。如果你选择维持 XLA 和非 XLA 的资金流动,这一点尤其正确。
摘要
XLA 汇编有可能大大加快培训速度,进而节省培训成本。不幸的是,在撰写本文时,GPU 对 PyTorch 中 XLA 编译的支持仍然处于 TPU 的次要地位。值得庆幸的是,像 AWS 这样的 CSP 已经创建了定制版本,让我们可以从 XLA 编译中获益。我们只能希望未来能提高 torch_xla 的可用性和易用性,特别是在 GPU 上。这种改进将包括:
- 一座官方多用途火炬 xla 建筑,
- torch_xla 和标准 torch API 流的一致性,
- 将 XLA 支持合并到官方 PyTorch 包中(如在 TensorFlow 中),以及
- 改进了使用文档,特别是在 GPU 上。
同时,“试一试,看看你的代码飞起来吧”😃。
如有任何意见、问题或更正,请随时联系我。
如何使用 Tweepy (Python)从 Twitter API 访问数据
Twitter API 允许你做很多事情,包括检索 tweet 数据。为了访问这些数据,您需要一个开发人员帐户。使用 Twitter API 应该是一件容易的事情,但是有时候图片和简单的代码可以帮你避免一些挫折。
本教程介绍了:
- 如何设置 Twitter 开发者账户
- 使用 tweepy (Python)访问 Twitter 数据
如何设置 Twitter 开发者账户
1.)创建一个 twitter 账户,如果你还没有的话。
如果你已经有了 twitter,你可以跳过这一步。图像由迈克尔·加拉尼克拍摄。
2.)在 twitter 开发者账户页面,你会被要求回答几个问题。例如,我被要求输入电话号码、国家和用例。下一步是阅读并同意开发者协议。
迈克尔·加拉尼克的图片。
3.)验证你的邮箱。
迈克尔·加拉尼克的图片。
4.)验证您的电子邮件后,您将被发送到欢迎屏幕。命名你的应用程序,然后点击获取密钥。
迈克尔·加拉尼克的图片。
5.)您现在可以访问您的密钥了。请确保将您的信息保存到安全的位置。您将需要它们使用 twitter api 来访问数据。对于 OAuth 2.0 来说,这些信息已经足够了。
迈克尔·加拉尼克拍摄的图片。
使用 tweepy 访问 Twitter 数据
本节简要介绍如何使用 Python tweepy 库访问 twitter 数据。要开始使用这个库,您需要通过 pip 安装它。
pip install tweepy
pip 安装套件
搜索过去 7 天的推文
下面的代码将搜索并返回过去 7 天的推文,每个请求最多 100 条推文。这段代码搜索包含#petday 标签的英文 tweets(而不是 retweets)。
请注意,为了获取过去 7 天之前的推文,您需要使用search_all_tweets
方法,该方法仅在您升级到学术研究产品跟踪或其他提升的访问级别时可用。这里有一个关于使用这种方法的博客。
使用 paginator 一次获得超过 100 条推文
如果你需要超过 100 条推文,你必须使用分页器方法并指定限制,即你想要的推文总数。将 limit=1000 替换为您想要的最大 tweets 数。
把 limit=1000 换成你想要的最大推文数量( gist )。
常见问题+ Twitter API 资源
本节旨在提供关于身份验证和 twitter API 的常见问题的答案和/或资源。自然,如果有人评论这篇博文,我会尽我所能回答这里的问题。
本节尽力提供人们在使用 Twitter API 和 tweepy 时遇到的常见问题。
OAuth 1.0 和 OAuth 2.0 有什么区别?
这里有一个很好的 stackoverflow 答案。 synopsys 也有一篇很棒的文章介绍了签名工作流程如何适用于每一种情况。
我如何做一些事情,比如获得用户的关注者,喜欢一条推文的用户等等?
Twitter 上有一个全面的指南这里。
结论
本教程是关于 Twitter API 入门的。未来的教程将介绍如何导出 twitter 数据以及情感分析。如果您对本教程有任何问题或想法,请在下面的评论中或通过 Twitter 联系我们。
【https://community.cnvrg.io/】原载于。
如何用 Python 访问关系数据库
原文:https://towardsdatascience.com/how-to-access-relational-databases-in-python-f711cb38e235
使用数据库适配器的简单指南
关系数据库管理系统(RDBMS)无处不在。
它们提供了一种储存大量信息的简单方法。此外,在 SQL 的帮助下,访问、维护和修改存储在其中的数据变得非常容易。
也就是说,这样的安排带有一定的警告。如果您希望从存储在数据库中的信息中获得洞察力,您会受到 SQL 提供的命令的限制。
虽然 SQL 允许您执行连接或利用聚合函数,但它不提供执行更高级技术的方法,如执行统计测试或构建预测模型。如果你希望执行这样的操作,你将需要 Python 的帮助。
这就引出了一个问题:如何在响应 SQL 查询的数据库上实现 Python 代码?
数据库适配器
要访问 Python 中的数据库,您需要使用一个数据库适配器。
Python 通过其模块提供数据库适配器,允许访问主要数据库,如 MySQL、PostgreSQL、SQL Server 和 SQLite。
此外,所有这些模块都依赖 Python 的数据库 API (DB-API)来管理数据库。因此,用于管理数据库的代码在所有数据库适配器中都是一致的。
一旦您能够成功地与一个关系数据库通信,您就应该能够与所有关系数据库通信。
利用数据库适配器需要理解关键对象和方法,这些对象和方法将用于促进与相关数据库的交互。
个案研究
一个简单的演示可以展示数据库适配器的特性。
因为我使用 PostgreSQL,所以我需要依赖于 psycopg2 模块。
这项研究将使用一个名为“test_db”的数据库。这个数据库包含一个名为“Person”的表,其中包含用 Mockaroo 生成的假数据。
以下是数据预览:
代码输出预览(由作者创建)
- 连接到数据库
首先,我们需要建立到数据库的连接,这样我们就可以使用 Python 与它通信。我们可以通过创建一个连接对象来实现。
创建连接对象时,您需要为其提供定位和访问数据库所需的信息。这包括主机、用户名、密码和数据库名称。
2.从 Python 向数据库写入查询
既然我们已经连接到数据库,我们应该能够直接从 Python 编写对数据库的查询。
尽管我们现在使用的是 Python,但我们将需要继续使用 SQL 查询来检索任何信息。
在编写任何查询之前,我们需要创建一个光标对象。
光标对象使用执行方法来执行给定的查询。可以用 fetchall 方法检索查询的结果输出。
让我们使用这个过程来选择 Person 表中的前 5 行。
代码输出(由作者创建)
如输出所示,每一行都表示为一个元组。
要获得表的列名,可以使用 cursor 对象上的 description 属性。
代码输出(由作者创建)
3。使用数据库执行高级分析
虽然我们可以用 Python 编写对数据库的 SQL 查询,但是如果我们只能做这些,那么使用适配器就没有什么意义了。
让我们对“Person”表中的数据执行一个操作,这是我们单独使用 SQL 查询无法完成的。
为此,我们应该首先在 Python 中将表存储为 pandas 数据框。
代码输出(由作者创建)
现在,我们可以全权处理这些数据了。
举个例子,让我们来看看这个数据集中男性和女性的平均收入。
代码输出(由作者创建)
我们可以看到,女性的平均收入高于男性。然而,没有迹象表明这种差异具有统计学意义。
我们可以利用 Python 的 SciPy 模块来进行 t 检验,看看是否有证据表明男女收入不一样。
代码输出(由作者创建)
由于 Python 的实用性,我们能够从我们的数据中学到更多!我们现在知道,从统计数据来看,男女之间的收入差距很大。
当然,由于数据是假的,我们进行的任何分析就像在沙漠中洗桑拿一样有用,但你会明白的。
4。直接从 Python 修改数据库
在研究过程中,可能需要创建、删除或修改数据库中的表。这样的操作也可以从 Python 中完成。
在我们的例子中,假设不是有两个分别包含名字和姓氏的列,而是只需要一个存储全名的列。
我们可以通过以下步骤实现这一点:
- 创建一个名为“名称”的新列
- 通过串联“名字”和“姓氏”列中的值,向“姓名”列添加值
- 删除“名字”和“姓氏”列
我们可以用下面的代码来执行这些步骤:
注意:代码中一个非常重要的内容是第 12 行中的提交方法。在 Python 中对数据库进行的任何修改都不会自动提交到数据库中。因此,必须调用此方法才能使更改生效。
当您返回数据库时,可以看到应用的更改。
代码输出(由作者创建)
数据库适配器的一个非常有用的特性是,它们允许您撤销任何不需要的修改(只要它们没有被提交)。
使用回滚方法,您可以将数据库恢复到上次提交时的状态。
5。终止与数据库的连接
一旦完成了与数据库的通信,就可以用 close 方法结束与数据库的连接。
结论
照片由 Prateek Katyal 在 Unsplash 上拍摄
SQL 和 Python 有各自独特的优点和缺点。
令人欣慰的是,有了数据库适配器,您可以在研究中利用这两种工具,并获得两个世界的最佳效果。
为了更全面地了解您可以使用特定的数据库适配器做什么,我建议您花一些时间阅读它的文档,以了解更多关于您可以使用的工具的信息。
我祝你在数据科学的努力中好运!
如何赢得数据科学面试
增强您竞争优势的综合工具包
伊恩·施耐德在 Unsplash 上的照片
介绍
随着数据的数量、速度和种类日益增加,组织对合格的数据科学家和分析师的需求也在增加,以便能够利用和释放这些数据的价值。然而,根据我参加面试小组或与人交往的经验,我相信许多潜在的候选人很难通过面试阶段,因为他们没有完全意识到他们应该事先准备的样本问题。出于这个原因,在本教程中,我旨在介绍和讨论候选人可能遇到的最相关的理论和实践问题。
我应该指出,这篇文章是一个工具包,它让您对各种数据科学概念和机器学习工具有一个基本的了解;然而,你需要更深入地挖掘所讨论的话题,进一步增加你的知识,以便在处理面试问题时变得完全自信。
第一部分:理论部分
面试官会有兴趣测试你在统计学、机器学习、技术栈等领域的知识。因此,第一部分将展示数据科学领域正在发展的七个类别中最相关的理论问题。
一)统计
- 说明总体和样本之间的区别:总体是所有感兴趣的个体的集合,而样本是在研究中代表总体的精选集合。
- 什么是假设检验?统计推断工具,使用样本数据来确定是否应该拒绝关于总体参数的陈述。由 H0 表示的零假设是关于总体参数的一个试探性假设,由 H1 表示的另一个假设与零假设的内容相反。
- p 值表示什么?在假设检验中用作可以拒绝零假设的最小显著性水平。p 值越低,你越有可能拒绝零假设,我们不能在小于 p 值的显著性水平上拒绝 H0。
- I 型和 II 型错误有什么区别?第一类错误称为假阳性,是当 H0 为真时拒绝它的错误,而被称为假阴性的第二类错误是当它为假时保留 H0 的错误。
- 如果两个随机变量 X 和 Y 是独立的,意味着什么?这意味着知道 X 却不知道 Y,反之亦然。
- 什么是中心极限定理?它描述了当我们有一个大样本量时,样本均值应该是正态分布的,因此样本均值将趋于总体均值,样本方差将等于总体方差除以样本量,而不管原始总体的分布如何。
- 解释相关性和协方差的区别?相关性提供了两个变量的线性关系的强度和方向,而协方差度量了两个变量的联合线性关系的方向。
- 什么是大数定律?当我们进行大量实验时,平均结果将非常接近预期结果,或者换句话说,样本平均值将变得更接近总体平均值。
- 如何处理异常值?我们可以用平均值或中值来改变它,标准化和缩放数据,应用对数变换,甚至删除这些值。
II)机器学习
10.列举有监督和无监督学习的区别。
监督和非监督 ML 之间的差异
11.什么是混淆矩阵?用于评估分类模型性能的 N×N 矩阵,其中 N 是目标类的数量。它将实际目标值与模型预测值进行比较。
12.解释准确度、精确度、召回率和 F-1 评分之间的区别。 准确度是模型正确预测的分类数除以预测数。 Precision 告诉我们有多少正确预测的病例结果是阳性的(TP/TP+FP)。回忆告知我们使用我们的模型(TP/TP+FN)能够正确预测多少实际阳性病例。F1 分数是精确度和召回率的调和平均值。
13.讨论决策树和随机森林算法的区别。决策树是一种受监督的算法,主要用于回归和分类,它通过将数据分割成子区域并预测叶节点的平均值,将数据集分解成越来越小的子集,而随机森林通过重复对训练数据进行重采样和替换来训练树的集合,并对树进行投票以进行最终预测。
14.定义逻辑回归,给出两个业务用例。它是一个二元分类器,估算一个实例属于某一类的概率,并据此做出预测。它可以用来预测企业中的潜在客户,或在营销活动中寻找新客户。
15.什么是偏倚和方差权衡,如何解决? 偏差是由于使用的算法过于简化而在模型中引入的误差,它会导致拟合不足。方差是由于过于复杂的算法而在模型中引入的误差,由此它在训练集中表现得非常好,但是在测试集中表现得很差,并且它导致过度拟合。偏差-方差权衡试图通过 : 交叉验证、维度缩减和特征选择等方法,将这两种误差源降至最低。
16.什么是过度拟合,如何对抗?当模型在训练集上表现良好,但在看不见的测试数据上未能很好地推广时,就会出现这种情况。为了克服这一点,我们可以增加训练集,执行特征选择,应用正则化技术,早期停止,或使用交叉验证。
III)深度学习
17.什么是深度学习,为什么最近一段时间开始流行?它试图模仿人脑的功能,使用许多层神经元从输入神经网络的数据中逐步提取更高层次的特征。由于生成的数据量的增加和运行这些模型所需的计算资源的增长,它已经变得流行起来。
IV) 自然语言处理
18.NLP 有哪些用例?它帮助计算机理解不同任务的语言,如语音识别、情感分析、文本摘要、文本分类、翻译、问答、聊天机器人和命名实体识别。
19.提供词袋和 TF-IDV 的区别。单词袋使用词频表示文本,没有上下文或顺序,而 TF-IDV 通过将术语频率或出现次数乘以逆文档频率来测量单词重要性,该逆文档频率消除了常见的不必要术语。
V) Python 库
20.定义 pandas 库和数据框架。Pandas 库建立在 NumPy 之上,为 Python 提供了易于使用的数据结构和数据分析工具。数据框是 pandas 中主要的二维数据结构,包含不同类型的列
21.什么是 scikit-learn?它是一个开源的 Python 库,为各种有效的预测数据分析工具采用了统一的接口,这些工具包括:机器学习、预处理、交叉验证和可视化算法。
VI) 科技栈
22 。Git 是什么?一个版本控制系统,允许用户跟踪源代码的变化。在 GitHub 或 GitLab 等网站上,数据团队可以使用 Git 推送、拉取和审查代码库。
23.Docker 是什么?在开发数据科学解决方案时,它确保了可移植性和可再现性,团队成员可以创建和部署隔离的环境来运行应用程序及其依赖关系。
24.什么是阿帕奇气流?It 是一个开源工具,可以用来编写和调度 Python 中的工作流,并监控模型训练或数据抓取等过程。
25.什么是 API?它是应用程序编程接口的首字母缩写,可以用作任何两台机器或应用程序之间的中间人,这些机器或应用程序希望在一组规则内相互连接,以完成指定的任务。
VII) 其他应用
26.确定 A/B 测试的目标,并给出一个用例。它通过两个变量的随机测试来检验用户体验。它可以被实施,以找出最佳的网上促销和营销策略的业务。
27.定义推荐系统并提及其类型。这是一个建议工具,评估一个平台可能为用户提供的备选方案。有两种主要类型:内容过滤 RS,基于学习用户过去喜欢或认为有用的内容来推荐项目,以及协作过滤 RS,基于学习具有相似品味的其他用户喜欢或认为有用的内容来推荐项目。
第二节:实用部分
面试官也很想测试你在 Python、SQL 和 r 等编程语言方面的技术专长和熟练程度,因此,在这一部分,我将展示并讨论一些你可能在面试中看到的编码示例。
I- SQL 编码练习
我将展示的第一个实际例子是关于 SQL,一种用于与关系数据库通信的编程语言。任务是提取按账户类型分段的 2022 年客户量、平均年龄、通话次数、通话时间平均年龄至少为 40** 。让我们假设我们必须使用两个表,分别叫做帐户和电话。**
**select** k.account_type, **count**(**distinct** k.account_id) as number_customers, round(**avg**(k.customer_age),0) as avg_age, count(distinct c.call_id) as number_calls, **sum**(c.talk_time) as total_talk_time
**from** accounts as k
**join** calls as c
**on** k.account_id = c.account_id
**where** k.start_date as date >= cast('2022-01-01' as date)
**group by 1 --account_type
having** avg(customer_age) >= 40
**order by** 2 **--number_customers**
以下是我希望你明确关注和理解的构建模块:
1。选择 ,这简单地说明我们想要提取变量名称:account_type、account_id 等。
2。计数和独特的 允许我们计数独特的(独特的)帐户 id,以生成客户总数;同样的方法也适用于呼叫,我们通过计算唯一呼叫 id 的数量来获得总呼叫数。
3。Count、sum 和 avg 是用于从数据中获得洞察力的统计度量。
4。 从 中识别出表的名称。
5。Join使我们能够基于一个公共唯一键合并两个表之间的数据。有不同类型的连接:左连接、右连接、内连接和外连接,您应该考虑这些连接。例如,当左表(表 1)或右表(表 2)中有匹配记录时,外连接返回所有记录,而 as* 内连接选择在两个表中都有匹配值的记录。还有一个 union 选项,可以合并两个表的数据。*
6。 其中 表示我们用来提取数据的条件。例如,在上面的例子中,我们指定只需要某个日期(2022 年初)之后的数据。
7。Group by 用于按类别进行聚合,在我们的例子中是 account_type。
8。拥有 从聚合结果中过滤出行。在我们的示例中,我们按照要求过滤平均年龄超过 40 岁的人的聚合结果。
9。Order by* 按 asc(默认)或 desc 排序数据。*
II- Python 编码练习
任务将是开发一个功能,可以作为您的帐户登录网关。它应该要求您输入您的密码,如果在两次尝试内匹配正确的密码,您将能够登录。否则,您的访问应该被阻止。
*def user_login(password):
i = 0
while i < 3:
user_input = input('Input the password:')
if user_input == password:
print('You have successfully logged in.')
break
if i == 2:
print('You are not the authorized user.')
i+=1
return*
Python 功能测试
以下是我希望您重点了解的构件:
1-函数的用法和结构:Python 中的术语函数打包了一组语句,你可以在代码中随时执行这些语句。函数的主要部分有:* 函数名、参数、函数体和返回部分。*
2-While语句启用迭代,当某些条件为真时,代码块将重复执行。一旦条件评估为假,代码的下一部分被执行。要提前结束 while 循环,应使用中断语句。在我们的示例中,while 循环用于要求用户在一定的尝试次数内输入密码,当它收到正确的密码时,while 循环将停止(break 语句),否则它将继续,直到最后一次允许的尝试,这将自动阻止访问。
在 Python 知识方面,也要精通熊猫的操作和方法以及数据扯皮技术。你可以查看我的另一篇关于 实践中的熊猫 的文章,我正在添加一个数据营 熊猫小抄的链接:Python 中的数据争论 。
结论和最终想法:
最后,我在本教程中展示了候选人在面试中可能会遇到的最相关的理论问题,无论是在统计学、机器学习、自然语言处理还是技术堆栈方面。我还展示并解释了两个实际操作的编码练习,这些练习描述了一些重要的概念和技巧,候选人应该有信心并有能力在面试中使用。然而,我强烈建议延长你的准备时间,进行额外的阅读,以确保你覆盖并掌握了面试中所有的关键知识。出于这个原因,我在下面列出了一些书籍和在线表格的建议,它们应该是这个工具包的补充资源。
我祝你在准备和职业生涯中一切顺利。如果您需要任何指导或支持来获得技术数据科学家或分析师职位,请联系我们。
其他资源:
你可以在图书馆起源找到这些书的 PDF 版本:
- 统计的艺术:从数据中学习
- 用于数据分析的 PythonWes McKinney
- 数据分析的 SQL:将数据转化为洞察力的高级技术作者 Cathy Tanimura
- 用 Scikit-learn 和 Pytorch 进行机器学习Sebastian rasch ka,Yuxi (Hayden) Liu,Vahid Mirjalili
我还建议查看 Data Camp 网站上的 数据科学备忘单 ,这也是利用你在 Python/SQL 编程、机器学习和人工智能方面的专业知识的有益来源。
FAANG 商业智能工程师/数据分析师如何通过技术面试(Excel)
就数据而言,Excel 是最通用的工具之一。您可以在 Excel 中处理所有数据,从数据输入到数据操作到数据分析到数据报告再到数据自动化。
米卡·鲍梅斯特在 Unsplash 上的照片
难怪它是几乎所有 it 公司(无论是哪个行业)的数据分析师的必备条件。
如果你要参加 FAANG(或任何公司)的数据分析师面试,以下是你需要准备的五大 excel 公式。
1.COUNTIF
COUNTIF 是一个高级 IF 函数,它将条件应用于多个区域中的单元格,并计算满足所有条件的次数。
举个例子,在亚马逊的 Excel 面试中,我被问到的一个问题是关于帕累托原则的。
根据 wikipedia.com—
帕累托法则的说法,对于许多结果来说,大约 80%的后果来自 20%的原因(“关键的少数”)。
我得到了一个数据集**,其中包含按产品类别和产品 ID 划分的销售额。我的任务是找出占销售额 80%的产品 id 集。
作者图片
解决方法— 有多种方法,这个可以解决。为了解决这个问题,我们需要统计占总销售额 80%的畅销产品的数量。我使用了 COUNTIF 和 SUM 公式的组合。
这是我所做的—
- 用
求出所有销售额的总和 total_sales= SUM(C1:C600) - 通过
Sales _ 80 = 0.8 * total _ Sales找出总销售额的 80% - 按销售额对数据集进行降序排序。
- 通过—
cum _ Sales(D 列)=SUM($C$1:C2) 计算每行的累计销售额 - 通过下面的公式
COUNTIF(D1:D600,"< =" & $H$5) 找出 cum_sales 大于 Sales_80(H5)的产品 id 数
结果将给出占销售额 80%的最畅销产品 id 的数量。
仅仅使用 COUNTIF 函数就可以解决另一个数据集和另外三个问题。
2.DATEDIF
出于某种原因,DATEDIF 不是 Excel 中列出的函数。我说的列出的意思是,你打字的时候不会得到任何建议。但是它仍然得到支持。
DATEDIF 函数可以让您减去两个日期,并以指定的时间频率输出结果,如日、月、年等。
答:在亚马逊的面试中,有一个问题是关于学生的数据集**,带有出生日期和班级等属性。我的任务是找出 2003 年 3 月 10 日以后出生的学生的年龄,他们在 a 区。
解决方案— 一如既往,解决问题有多种方法。我使用 DATEDIF 函数来计算年龄,并使用多个 IF 公式来筛选来自 A 区且出生于 2003 年 3 月 10 日之后的学生。最终的公式看起来像这样—
=IF(section="A ",If (dob > DATE(2003,3,10), DATEDIF (dob,today()," y ")," ")," ")
了解这些函数确实可以将任务简化为一行,而不是计算多个中间列。
同一个数据集的另一个问题是计算 2002 年 4 月 3 日之前出生且年龄超过 12 岁的 A 区学生的数量。
解决方法——我分两步解决了。首先我把满足这个标准的学生标为 1,其他的标为 0。然后,我对这一列求和,得到满足要求标准的学生人数。这可以进一步简化,但在当时,这就是我的想法。
Col F= IF(B1="A ",IF(C1 < DATE(2002,4,3),IF(DATEDIF(C1,today()," y") > 12,1,0),0)
= SUM(列 F)
使用 COUNTIFS 的简化版本(类似于 CountIF,但您可以指定多个条件)
=COUNTIFS(B1:B60,“A”,C1:C60,“<”&日期(2002,4,3),E1:E60,“>”&12)
B 列=节,C 列=出生日期,E 列=年龄(计算为 DATEDIF(C1,今日()," y"))
还有另一个数据集。接下来的三个问题回答了哪种选择对一家公司来说是最好的。使用 datedif 和 Sum 函数可以很容易地解决所有这些问题。
3.索引/匹配
INDEX 返回区域或数组中给定位置的值。MATCH 函数返回给定范围内满足指定条件的单元格的索引。这两个函数一起可以帮助查找精确匹配或大于或小于查找值的值。这种组合类似于 VLOOKUP。但是使用 VLOOKUP 有一些缺点。首先,它默认假设表数组中的第一列是按字母顺序排序的。第二个是,不能使用 VLOOKUP 在第一列之外的任何列中查找值。
亚马逊采访中的一个数据集**是关于每个地区的销售额和利润。这个数据集中有两个问题。
作者图片
a. 首先是找到具有指定销售额的地区的名称。
解决方案——我在这里尝试使用 VLOOKUP,当它不起作用时,我意识到了 VLOOKUP 的局限性。所以,我改用指数匹配。
这是一个简单的公式,它给我的正确答案是南方—
=INDEX(A2:A9,MATCH(13440,B2:B9,0))
第二个问题是找出利润最低的地区。
解— 我在这里用了同样的公式。刚刚用最小利润改变了销售值,我又得到了正确答案。
=INDEX(A2:A9,MATCH(MIN(C2:C9),C2:C9,0))
4.求和乘积
根据 support.microsoft.com, SUMPRODUCT 函数返回相应区域或数组的乘积之和。默认操作是乘法,但是加法、减法和除法也是可能的。
虽然我没有经常使用这个公式,但在这次采访中的一个问题中使用了它。
在这个数据集**中,给出了雇员及其加入日期。任务是找出在一月、二月、三月等月份有多少员工加入。
解决方案— 同样,有多种方法可以做到这一点,我在采访中没有使用 SUMPRODUCT。但是如果使用 SUMPRODUCT,这是最简单的。公式可以这样写—
=SUMPRODUCT((月(乙$7:乙$81) = 1)(乙\(7:乙\) 81<>)*
我们正在获取一个数组,其中加入日期的月份(B 列)等于 1(代表一月),然后用它乘以另一个数组来处理空值。关于第二部分的更多细节在这里—如果你传递一个空值给这个函数,MONTH 函数返回 1。这将被计入不准确的一月份。因此,我们创建一个数组/范围来指示非空值,并将 1 标记为非空,0 标记为空。这将处理空值,并为 SUMPRODUCT 函数提供一个数组。
5.苏米夫
SUMIF 函数返回满足指定条件的某个范围内的值的总和。
尽管面试中没有直接基于这个公式的问题,但这是一个简单且常用的函数,可以帮助回答需要选择性求和的问题。例如,在带有出生日期和班级等属性的学生数据集**中,可能会要求您查找 a 部分学生完成的项目总数。SUMIF 可用于轻松找到答案。
这是我作为数据分析师经常使用的五个非常有用的 excel 函数。我希望这些信息对你有用,并祝你在接下来的面试/准备中好运。
额外提示:尝试通过应用这些函数来解决问题。有时,我们会读到一些功能,并对其使用感到自信。但是我们在面试的时候回忆不起来(亲身经历)。获取一个数据集并使用这些函数解决几个问题确实有助于组合多个函数并理解它们的应用场景。
感谢阅读!
下次见……
*所有数据集已完全改变,保持了相同的采访概念。实际采访中没有公布任何数据。提供的解决方案是我自己的。
FAANG 商业智能工程师如何通过技术面试(SQL)
所有数据职业的一个共同技能是 SQL。学习它永远不会出错。无论是处理结构化数据还是非结构化数据,在这个过程中的某个时刻都需要 SQL。
在我最近在 FAANG 的面试中,SQL 是最先测试的技能之一。您可以在本文中了解整个过程。
如果你要参加 FAANG(或任何公司)的数据分析师面试,以下是你需要准备的五大 SQL 概念。
1。常用表表达式— 常用表表达式也称为 cte,是 SQL 中最被低估的概念之一。加入很重要,但是 cte 可以让你和你的继任者的生活变得非常容易。CTE 基本上是一个临时命名的数据集,可在进一步的 CTE/选择/插入/更新语句中使用。
它的引入是为了简化 SQL 查询。您可以将它们视为查询中的一个变量。你用With <CTE Name> as(Select …)
来声明它
然后,可以在后续 SQL 代码中的任何地方调用这个 CTE,就像使用预声明的变量一样。要使用 CTE,您可以使用join
、on
关键字将它与其他表/视图/cte 连接起来。
请注意,cte 不仅仅是为了面试。它们也在我的日常工作中广泛使用。
2。row _ number()— row _ number 函数与 rank()和 dense_rank()非常相似。基本的区别在于处理分区中有平局的情况。rank 函数将相同的序列号分配给所有的连接,并跳过下一个序列号。Dense_rank()复制所有绑定值的序列号,而不跳过序列中的下一个数字。而 Row_number()只是为所有绑定的行任意分配一个递增的序列号。对于像查找薪水最高的前 10 名员工这样的问题,row_number 非常有用。
3。自我联接— 在我参加过的所有 SQL 面试中,一个常见的问题是基于自我联接的。自连接最广泛地用于查找父子链接。我个人在工作中多次使用这个概念来显示客户经理及其主管、直接隶属于某个集团经理的所有员工等等。
4。Case when 语句— Case When
语句主要用于根据不同的标准对一列进行分类/宁滨。比如,如果你想根据学生的考试成绩来显示他们的分组,你可以写一个这样的 case 语句
case
when marks >= 60 then 'First'
when marks >= 45 then 'Second'
when marks >= 33 then 'Third'
else 'Fail'
end as Division
这使得 case 语句非常有用。它通常也用于创建不同类型的标志。
5。窗口函数/聚合— sum、min、max 和 average 等聚合是分析师工具箱中不可或缺的一部分。窗口功能可以显示每一行的计算结果。例如,显示累积和,显示前一个或下一个值。这些只是使用窗口函数可以做的几件事。我强烈建议你很好地理解这个概念。这将为您节省一些时间和冗长的代码。
要了解更多 SQL 概念,请参考这篇关于日期函数的文章。
在我看来,你可以用这五个概念和内置的日期函数来清除所有的 SQL 访问。就 SQL 技能而言,你将是一个强有力的候选人。
我祝你旅途顺利。
感谢阅读!
下次见……
附注——你们中的很多人都在 Linkedin 上寻找实际的问题。我在 NDA,不能分享实际的问题文件。我也不能单独回答你们所有人的问题。但是我保证上面阐述的概念涵盖了所有被问到的问题。
如何解决缺失值替换问题
原文:https://towardsdatascience.com/how-to-ace-the-missing-value-replacement-problem-408bd9506b11
解决数据科学中最常见问题的 5 大专业技巧
照片由 Unsplash 上的 Moises Alex 拍摄
缺失值替换听起来可能微不足道,但它可能是机器学习过程中最重要的一步。你做的方式会对你的机器学习模型产生很大的影响。
此外,由于您将创建一些新数据,因此您对组织中的数据部门负有一些基本责任。数据是最重要的资产之一。因此,作为一名数据科学家,如果您使用缺失值替换来创建新数据,您必须向业务人员证明输出的合理性。
在本文中,我将向您展示 ace 缺失值替换的 5 大技巧,让您在如此重要的主题上看起来像个专家。我将使用 K-最近邻(KNN)算法作为缺失值替换算法。但是,这些提示也适用于其他缺失值替换方法。
让我从我将在这个故事中使用的数据集开始。我在 Kaggle 上发现了一个非常有趣的数据集,名为宇宙飞船泰坦尼克号(本文末尾提供了数据源引用)。这是基于一个虚构故事的数据。泰坦尼克号飞船是一艘星际客轮,被时空异常击中。虽然飞船完好无损,但几乎一半的乘客被运送到了另一个维度!
作者在 Unsplash +数据表上的 Guillermo Ferla 照片
听起来很熟悉泰坦尼克号的问题,但它更具未来感!该数据包含乘客的详细信息,如母星球、目的地、年龄和各种服务。许多列缺少值。所以现在让我们来看看最重要的技巧,它将帮助你弥补缺失的价值。
1.确定并定义什么是缺失的价值
识别和定义什么是缺失值的最好方法是进行可视化。它避免使用任何预先的概念。这是一张地球的柱状图。我们清楚地看到有什么东西不见了。这是识别和定义缺失值的好方法。我们可以说缺失值是一片空白。由于每个乘客都有一个家园星球,我们需要用一些价值来取代空白。
按母星划分的乘客数量条形图(图片由作者提供)
一个类似的柱状图显示了客房服务和年龄。
客房服务和年龄(图片由作者提供)
对于客房服务,零值是很常见的。这是正常的,因为不是所有的乘客都需要客房服务。然而,对于年龄,有零值,而且它们不是最常见的。即使我们在未来,我确定未出生的人不算乘客!所以年龄的零值肯定是一个缺失值。
2。确定目标变量中缺失值的比例
通常,丢失值的努力是在机器学习的上下文中完成的。因此,检查与目标类相关的缺失值非常重要。如果相对于目标类的数据分布保持平衡,缺失值替换通常可以很好地工作。
数据集中的目标变量是乘客是否因为被运送到另一个维度而迷路。下图显示了母星相对于目标变量的分布。我们可以观察到两个目标类的空白值的比例是相似的。此外,缺失值的比例非常小。这意味着替换丢失的值不会显著改变数据的形状。这是一个好消息,我们可以自信地将缺失的价值理念传达给数据和业务人员。不会引起公司内部数据大神的任何恐慌!
家园星球与目标阶级(图片由作者提供)
我们使用如下所示的箱线图分析,对数字列 Age 进行类似的分析。您将观察到两个目标类的盒图或多或少是相似的。此外,零值(即要替换的值)远离中值。这意味着没有很多零值。因此,我们不会彻底改变数据的形状,从而让公司中的数据之神高兴!
年龄与目标阶层(图片由作者提供)
3.对替换算法进行前后检查
现在,我们已经准备好使用“替换母星”和“年龄”字段中缺失的值。对于这项工作,最有效的算法之一是 K-最近邻(KNN)算法。该算法将尝试查找具有缺失值的记录的最近邻。对于数值,它将替换为最近邻的平均值。对于分类值,它将替换为最常见的值。
一旦算法被执行,对有多少值被替换进行热图分析是非常有用的。
热图前后的 KNN(图片由作者提供)
我们可以观察到所有缺失的年龄和母星值都被替换了。对于客房服务等字段,我们没有选择替换缺失值,所以前后保持不变。
4.太好了,丢失的值被替换。但是用什么?
太好了,KNN 算法神奇地替换了丢失的值。但是用什么?我们只有明白置换后什么是价值,才能对置换算法有信心。
这一步取决于你所使用的算法。在本文中,我使用了 KNN,所以我将详细说明这个算法的方法。由于 KNN 是基于寻找最近邻的,因此了解被替换值的最近邻是什么会很有用。可以帮助可视化“接近度”的算法之一是降维算法 TSNE(t-分布式随机邻居嵌入)。
此处显示的是绘制在 2D 散点图上的 TSNE 结果。
TSNE 谈 KNN 结果(图片由作者提供)
绿点表示数据点有缺失值,已使用 KNN 算法替换。紫色点是没有缺失值的数据点。由于大多数绿点被紫点包围,我们可以对 KNN 的方法有信心。这表明 KNN 是一种很好的方法,因为缺失值的最近邻并不太远。
有一个孤立的绿点集群,在下图中放大了。更仔细的观察表明,即使它是一个孤立的聚类,也有一些邻居帮助填充了缺失的值。
放大到孤立的集群(图片由作者提供)
我们还可以基于目标类验证比例,并将其与早期的结果进行比较。下图是对母星的分析。我们可以观察到空白值(4%)被地球(+2%)、欧罗巴(+1%)和火星(+1%)所取代。这是有道理的,因为大多数母星对应于地球,其次是欧罗巴和火星。
核实前后地球的比例(图片由作者提供)
类似地,我们可以观察到大多数零年龄值已经被 12 -14 岁和 24-25 岁所取代。整体直方图没有太大变化,这是个好消息。
验证前后年龄比例(图片由作者提供)
5.验证缺失值替换是否改进了模型
所以现在是我们一直在等待的时刻。我们需要证明管理缺失价值的所有努力是否值得。展示这一点的最佳方式是训练和测试机器学习模型两次——在缺失值替换之前和之后。
替换前后的混淆矩阵(图片由作者提供)
ROC 分上去了,说明所有缺失值替换的努力都是值得的!哪怕是 1%的分数提升,也能帮助在 Kaggle 董事会上升,为银河系的乘客们讨回公道!
结论
总之,缺失值替换会更改数据。因此,重要的是要有足够的证据来证明为什么会改变以及改变了什么。这里描述的 5 个技巧将帮助你解决丢失值替换的问题。
观看演示并亲自尝试
你可以访问我的网站做缺失值替换以及其他没有编码的分析:https://experiencedatascience.com
这是我的 Youtube 频道上的一步一步的教程和演示。您将能够使用零编码根据您的数据定制演示。
请订阅,以便在我发布新故事时随时获得通知。
https://pranay-dave9.medium.com/subscribe
如果你喜欢你所读的,你也可以通过我的推荐链接加入 Medium 。这是支持我的直接方式,我会非常感谢你。
https://pranay-dave9.medium.com/membership
数据源引用
资料在这里:https://www . ka ggle . com/competitions/space ship-titanic/overview
正如规则(https://www.kaggle.com/competitions/spaceship-titanic/rules中所规定的,在第 7 A 节中,数据可以用于任何目的。
A.数据访问和使用。您可以出于任何商业或非商业目的访问和使用竞赛数据,包括参加竞赛和 Kaggle.com 论坛,以及学术研究和教育。
如何在 Python 日志运行中期添加调试模式
原文:https://towardsdatascience.com/how-to-add-a-debug-mode-for-your-python-logging-mid-run-3c7330dc199d
Python 技巧和窍门
动态配置日志记录的调试模式
作者创建的图片|使用了来自canva.com的免费内容许可元素
让我们面对它,python 的日志工作是复杂的。如果您想在 python 应用程序中添加- debug-mode 或- verbose,该怎么办?您希望激活它会在日志“调试”级别创建一个控制台输出或日志文件,而您的默认值是“信息”级别。当你有一个脚本时,这很容易,你只需要做一个:
这很简单。但是没有足够的教程或简单的解释来跨模块这么做。这只是改变脚本记录器。我会给你一个框架,你可以应用到你所有的应用。
我们想要达到的目标
标准
让我们简单地说出我们想要什么。我们需要以下标准:
- 跨多个模块进行日志记录的简单框架。
- 一种在所有模块的日志记录应用程序的中途改变特性的方法,无论是日志记录级别、处理程序、配置文件等等。
任何人(大多数情况下是用户)都可以在应用程序运行的任何时候启动日志调试模式,无论是作为输入还是中途|作者创建的图像|使用来自 canva.com的免费内容许可元素
当你在 ONE 脚本中开始时,有大量的教程涵盖了日志记录的基础知识。但是为什么新手找登录过多个模块的教程那么难?
这家伙同意了,谢天谢地他已经写下来了:
[## 适用于所有数据科学应用的可重复使用的 Python 日志模板
towardsdatascience.com](/the-reusable-python-logging-template-for-all-your-data-science-apps-551697c8540)
他的方向是正确的,但是,这并没有帮助我们选择改变所有动态日志的方面。这需要一些信息。
关于记录器的必需背景信息
我不会深入解释 Python 日志包的概念。我假设您对 python 日志包有一些基本的了解。我不想重新发明轮子,所以这里有一个文档链接:
https://docs.python.org/3/library/logging.html
和一个链接到一个很好的解释伐木工。
https://www.geeksforgeeks.org/logging-in-python/
然而,有几个相关的概念我需要提及:
- 有多种方法来配置记录器:编写函数/类,dictConfig,使用 logging.basicConfig,一个配置 YAML 文件等。第一个是我发现在运行应用程序时最通用的,所以这是我遵循的框架
- 每当您启动 logging.getLogger(name)时,都会创建一个子记录器。如果括号是空的,那么它就是根日志记录器。众所周知,为每个模块创建一个子类是最佳实践。
- 这个超级重要。当子记录器未指定记录级别(即信息、调试、警告等)时。)那么它将继承父类的设置。在大多数情况下,我们的例子是根日志记录器。
作者创建的图像
你明白我的意思了吧。我们将在每个模块中初始化一个子类,但是将从根日志记录器继承级别。我们可以在应用程序中途改变根日志记录器的日志级别,这将应用于所有子日志记录器。
框架:步骤和解释
这个框架真的很难在一篇文章中解释,所以我把完整的例子放在 GitHub 的仓库里:
https://github.com/Causb1A/logging-debug-mode [## GitHub-caus B1 A/logging-debug-mode:补充 TDS 文章的存储库
github.com](https://github.com/Causb1A/logging-debug-mode)
如果你正在努力遵循下面列出的步骤。从 main.py 开始一步一步调试存储库代码,然后你就会明白它是如何工作的了。
下面是我们将要实现的目标:
作者创建的图像
如上所述,我们将创建一个 main.py 来启动应用程序,它连接到 logger 类的文件夹和模块中。Module_1 和 Module_2 都是运行应用程序所需的 python 模块,但是 module_1 从 module_2 中获取了一个函数。所有模块都使用一个名为 Logger()的实例化类。你不必为此使用单例类,你可以有一个普通的类或函数。我用它来为将来的实现保持日志的通用性。
为了启动“调试模式”,我们将在 module_1.py 中有一个函数,用于启动根记录器中的调试级别。
步骤 1:文件创建
像这样创建文件:
作者创建的图像
忽略 pycache。
- 有一个名为 logger 的文件夹,并确保有一个 init。巴拉圭
- 有一个名为 my_app(或您的应用程序名称)的文件夹,并确保有 init。巴拉圭
- 在你的日志文件夹中放一个 logger.py
- 创建一个 main.py 作为主运行文件
- 将你的应用程序模块放在我的应用程序或者你的模块所在的任何其他文件夹中
- 可选:放置一个测试文件夹并在此测试记录器特性
步骤 2:日志记录类
它位于 logger.py 中的 Logger 文件夹中。就像我前面说的,它不一定是一个类,也不一定是一个单独的类。您可以只定义函数而不定义类。只要确保你相应地修改了框架。
对于那些问:什么是单例类?
python 中的单例类允许你创建一个类的实例。这个实例贯穿程序的整个生命周期。想象一个你实例化一次的类对象。这个类不能被再次实例化。您可以在任何 python 模块中的整个程序中访问和更改该实例的变量,而不必再次实例化该类。
对于单例类的细节以及它们为什么工作,我不会重新发明轮子。这里有一个很好的解释:
我们在这里使用它的原因是为了拥有一个具有我们想要的特性的全局记录器类。所以每次我们启动一个子日志类,它都遵循我们定义的相同框架。我为将来的实现留下了一个单独的类,例如,它可以作为一个全局类来保存所有的子记录器作为属性。或者在类的属性发生变化后,可以用它来重新定义日志。我发现拥有一个全局单实例类更加通用;儿童记录器的集中访问点。对于我们所说的“调试模式”,这不是必需的。
下面是 logger.py 文件。
这些函数对于文档字符串来说是不言自明的,但是需要注意几个重要的元素。
- def new(cls):这是使这个类成为单例的部分,它检查实例是否为 none。如果是,它将实例化一个实例。否则,它将返回相同的实例。因为这是一个日志记录器,我们不需要再实例化。
- def get_logger(self,logger_name):这是我们将在所有模块中调用的函数,用于启动子记录器。
- 处理程序:这里我们创建了两个处理程序,一个终端输出和一个文件处理程序。将来,您也可以使用这个单例类来处理处理程序。
- def add_handlers():函数 add handlers 检查它是否没有复制处理程序。如果您的应用程序中碰巧需要重新创建一个子记录器,这个函数将停止重复的处理程序。如果将来您希望重新编写这个类以适应更多的处理程序管理,请小心不要重复处理程序。
- def set_debug_mode(self,debug_mode:bool):该函数将调试根记录器设置为调试级别。这意味着所有子记录器都将从调试根记录器继承这个特性。
第三步:不要忘记 init。py!
我们希望 logger 文件夹像一个包一样被对待。所以在 init 内。记录器文件夹的 py,放入:
第四步:主页面
在 main.py 或运行整个应用程序的主模块中,必须启动 logger 类,并将根级别日志设置为 INFO。这必须在您运行应用程序中的任何其他内容之前发生。
见下方 my main.py
注意,我调用 logger()实例化该类来创建一个子 Logger?每次调用 Logger()时,我们会实例化一个类吗?singleton 类中的 get_logger 函数?不,因为单例类的目的是只有一个实例,所以它将返回相同的现有实例。
步骤 5:在任何模块中使用 logger 类
为了在每个模块中使用 singleton logger 类,我们需要导入 logger 类并调用 get_logger。记住,良好的日志记录实践意味着您需要为每个模块创建一个子日志记录器,所以一定要将模块 name 放在每个函数中。
下面是 Github 资源库中“module_2.py”的一个例子。
步骤 6:在应用程序中途更改调试级别
现在,我们要做的是,在应用程序中途将 root logger 更改为 debug 模式。还记得步骤 2 中有一个 set_debug_mode 函数吗?该函数将根级别日志记录器更改为 debug。在 Github 存储库中的 module_1.py 中,我通过调用该函数来更改类属性。
参见下面的 module_1.py。
函数 does_something()只是一个示例函数,向您展示用例。
这个模块有什么作用?
函数 run()是整理一切以显示用例的函数。让我们一步一步来。
第 16 行:这调用了函数 does_something()记住,此时日志记录仍处于日志记录状态。信息级别。所以在控制台/日志文件中,你只会看到信息。
第 18 行:这调用了另一个模块中的函数 does_something_module_2()。在步骤 4 中可以看到相同的模块。记住,日志还在日志。信息级别,所以只会看到信息。
第 23 行:将根日志记录器级别更改为 DEBUG。所有模块子记录器都将从此继承。
第 26 行:与第 16 行相同,但是这一次启动了调试模式,日志级别为 Logging.DEBUG
第 29 行:与第 18 行相同,但是现在启动了调试模式,日志级别为 logging。甚至在另一个模块中调试。你已经完成了,你已经在一个模块中初始化了调试模式,并且它在每个其他的模块中继续初始化日志类。
以下是运行该文件时的输出。
作者创建的图像
步骤 7:应用到您的应用程序中
要将框架应用到您的应用程序:遵循步骤 1–6,但是不使用 module_1.py、module_2.py 和 main.py,而是将记录器放在您的模块中。
当将根级别更改为调试级别时,可以有一个函数来触发它。例如,解析来自调试模式或用户输入的参数。不管你想触发什么。
额外测试功能
我已经在测试库中包含了一些测试函数,只是为了测试 singleton 类的各种特性。测试是不言自明的。
我们取得的成就
我们在存储库和步骤 1–7 中实现的是,我们已经将 logger 类框架应用于应用程序,并在应用程序中途触发日志记录级别的更改。
最后的话
希望这有助于您在 python 应用程序中更多地管理日志,并为您更多地使用 singleton 类打开大门。
如果你喜欢这篇文章,请留下掌声和关注支持!
或者,如果您有兴趣加入 Medium 社区,这里有一个推荐链接:
https://medium.com/@adrian.causby15/membership [## 通过我的推荐链接加入 Medium-Adrian caus by
medium.com](https://medium.com/@adrian.causby15/membership)
如何分两步在 Python 运行中添加转义
Python 技巧和窍门
使用装饰函数为 Python 应用程序创建一个简单的出口
作者创建的图片|使用了来自canva.com的免费内容许可元素
你有一个运行在无限循环上的 Python 脚本/应用程序/函数,或者你有一些功能需要你在运行时间过长时安全退出程序。怎样才能安全退出程序?也许 ctrl+C,但这并不总是最安全的方式,非技术人员可能不知道这一点。也许你已经有了一个启动 ML 建模的函数,这个函数可能需要太长时间。
在这里,我将为您提供一个装饰框架,您可以在任何函数上使用它来添加安全停止程序的能力,如果您按下指定的键。在我们的例子中是“退出”键。
那么这里的标准是什么呢?
- 创建一个可以包装任何函数的装饰器,这样如果函数运行时间过长,我们可以用 escape 键安全地停止它
图片由作者创建|使用来自 canva.com的免费内容许可元素
Github 存储库
我已经把这个框架放在了 GitHub 的仓库里,你可以在这里找到:
https://github.com/Causb1A/escape-hatch/tree/main [## GitHub-caus B1 a/Escape-hatch:Escape hatch python 库,以补充 TDS 文章
github.com](https://github.com/Causb1A/escape-hatch/tree/main)
我可能会提到知识库的各个方面。如果使用存储库,从 main.py 开始,然后从那里进入调试模式。你可以在 my_app/api_utils.py 中找到 escape hatch
必备知识
在深入细节之前,我只想介绍一下我使用装饰函数和装饰工厂来做这件事。如果你不确定这些是如何工作的,请在这里阅读更多信息:
在一个非常高的层次上,装饰器是一个接受另一个函数并扩展后一个函数的行为的函数。
把它想象成一个包装器:
图片由作者创建|使用来自 canva.com的免费内容许可元素
你可以用装饰器包装任何函数,它基本上会围绕函数执行一些东西。所以无论何时你调用一个包装了装饰器的函数,它都会执行装饰器,并且函数会在装饰器中执行。这将使我们的例子更有意义。
步伐
步骤 1:定义装饰器
创建一个新的模块,在资源库中,我把这个模块叫做 api_utils.py,我在这里定义了 decorator 函数,把它叫做 escape hatch。
上面的函数是我们的装饰器,我们可以用它包装任何函数。如果我启动一个由这个装饰器包装的函数,每当我按下 escape 键,它就会暂停程序(杀死主线程)。
有几点需要注意:
- 第 34 行表示一个上下文管理器,它监听任何键盘动作,如果有一个要发生,它将启动第 26 行,暂停程序
- 第 40 行是执行函数的地方
步骤 2:使用我们的装饰函数
现在我们如何使用它?很简单,就像这样:
注意——如果您在存储库中跟踪,这个文件在 my_app/module_1.py 中
就像上面一样简单,现在无论何时你想使用 escape hatch,只要像上面第 5 行那样在任何函数之前简单地包装它。之后使用@escape_hatch 和函数。开始消息和结束消息是可选的。
Function_that_runs_forever()是一个永远运行的函数,用来测试逃生舱。让我们来测试一下:
作者创建的图像
我特意将一些消息移到右边,这样我们可以清楚地看到哪个部分是装饰包装器。
发生了什么事?
- 逃生舱装饰开始,打印出一些东西,它听我们的键盘,看看我们是否按下退出。
- 我们的实际函数 _that_runs_forever()开始运行。这种打印机正在运行,除非我停止它,否则它会一直运行下去。
- 然后我按下 escape 键,装饰器停止这个函数并打印出用户终止的程序。
这就对了。功能正常的逃生出口。
额外步骤 3:捕捉键盘中断
有时,取决于你的应用程序做什么,使用键盘杀死主线程有时会引发 KeyboardInterrupt 异常并输出回溯。输出回溯可能不是您想要的。要解决这个问题,您可以添加一个 try,除了我在存储库的 main.py 中所做的:
注意在第 11 行我捕捉到了异常。
最后的话
希望以上内容可以帮助你更好地理解装饰函数,并允许你为那些运行时间过长的函数提供一个逃生出口。您可以操纵装饰器来使用不同的键,或者甚至是其他东西来启动 stop。一切触手可及。
如果你喜欢这篇文章,请留下掌声和关注支持!
或者,如果您有兴趣加入 Medium 社区,这里有一个推荐链接:
https://medium.com/@adrian.causby15/membership [## 通过我的推荐链接加入 Medium-Adrian caus by
medium.com](https://medium.com/@adrian.causby15/membership)
感谢 Marcell Orban 与我一起为我们的应用程序编写框架。
如何在 Python 中将图像添加到 Matplotlib 绘图中
原文:https://towardsdatascience.com/how-to-add-an-image-to-a-matplotlib-plot-in-python-76098becaf53
使用 Matplotlib 读取图像数据并将其添加到绘图中
向现有地块添加外部图像或图标不仅增加了美感,还从整体角度增加了其清晰度。外部图像可以是公司或产品的标志、国家的旗帜等。这些图像有助于巩固传达给读者的信息。
Python 中有不同的图像处理包。一些著名的包括 OpenCV、imageio、scikit-image、Pillow、NumPy、SciPy 和 Matplotlib。Matplotlib 是 Python 中最著名的数据分析和可视化包之一。在这篇文章中,我将分享使用 Python 中的 Matplotlib 读取图像、显示图像并将其添加到现有绘图中的步骤。事不宜迟,我们开始吧。
图片由格伦·卡斯滕斯-彼得斯在 Unsplash 拍摄
数据
我从一个数据帧df
开始,如下图所示。df
包含 2011 年至 2021 年全球太阳能光伏(PV)装机容量。这一数据是从(IRENA,2021 年)获得的。
条形图
在这一步,我用df
创建了一个规则的条形图。相同的代码在下面的代码块中。我删除了情节的图例,包括它的框架。我把右边和顶部的刺设置为不可见。此外,我在图中添加了网格线。
使用 for 循环遍历df
的每一行,我使用plt.text(x, y, s)
将顶部每一条的值相加,其中,
x
是年在 X 轴上的位置,从 0 到 10(包括 10)y
和s
均基于df
的值,即全球太阳能光伏年装机容量,单位为千兆瓦。
fig, ax = plt.subplots(figsize = (12, 8))df.plot(kind = “bar”, ax = ax)plt.ylabel(“GW”)#Remove legend along with the frame
plt.legend([], frameon = False)plt.title(“Global Installed Capacity of Solar PV”)# Hide the right and top spines
ax.spines.right.set_visible(False)
ax.spines.top.set_visible(False)#Set xticks rotation to 0
plt.xticks(rotation = 0)#Add grid line
plt.grid(axis = “y”)#Adding value labels on top of bars
for i in range(len(df)):
installed = df.iloc[i][0]
plt.text(x = i — 0.2,
y = installed + 5,
s = str(installed))#Add source
plt.text(8, -100, “Source: IRENA, 2022”)plt.savefig(“../output/global solar pv trend.jpeg”,
dpi = 300)
plt.show()
结果,我得到了下面的图表,它展示了在过去十年里太阳能光伏在全球范围内的急剧增长。
显示 2011 年至 2021 年全球太阳能光伏装机容量的柱状图。图片作者。
阅读图像
可以使用 Python 中的不同包读取图像,如 Matplotlib、OpenCV、ImageIO 和 PIL (GeeksforGeeks,2022)。在上面的图中,我想在顶部中心的某个地方添加一个太阳能电池板的图标。我用绘画软件手工绘制了一个太阳能电池板的标志。使用 Matplotlib 的图像模块读取该图像,如下所示:
读取包含太阳能电池板标识的图像文件。图片作者。
这里,logo
是形状(520,720,4)的 3D NumPy 数组。三维(3D)数组由 3 个嵌套层次的数组组成,每个维度一个(Adamsmith,2022)。
logo
具有(M,N,4)的形状。520 和 720 是指图像的行数和列数。4 是指具有 RGBA 值(0–1 浮点或 0–255 整数,包括透明度)的图像,即红色、绿色、蓝色和 Alpha 的值(Matplotlib,2020)。
显示图像数据
包含 RGB(A)数据的logo
可使用plt.imshow(logo)
在 2D 常规光栅上显示为图像。根据logo
的形状,该图在 X 轴和 Y 轴上分别以 720 和 520 为界限,如下图所示:
使用 Matplotlib 显示图像数据。图片作者。
将图像添加到 Matplotlib 图
为了将logo
图像添加到条形图中,我创建了一个 OffsetBox(一个简单的容器艺术家),并在其中传递了logo
。缩放设置为 0.15,即图像原始尺寸的 15%。这个 OffsetBox 被命名为 imagebox,因为它包含图像。
接下来,我创建了一个 AnnotationBbox,它是 imagebox 的容器。我在图(5700)的顶部中心为它指定了一个xy
位置,并隐藏了框架。这在下面的代码中表示,该代码与条形图的代码块一起使用:
from matplotlib.offsetbox import (OffsetImage, AnnotationBbox)#The OffsetBox is a simple container artist.
#The child artists are meant to be drawn at a relative position to its #parent.
imagebox = OffsetImage(logo, zoom = 0.15)#Annotation box for solar pv logo
#Container for the imagebox referring to a specific position *xy*.
ab = AnnotationBbox(imagebox, (5, 700), frameon = False)
ax.add_artist(ab)
因此,我可以将太阳能电池板的徽标与显示全球太阳能光伏趋势的条形图一起添加。
在条形图上添加太阳能电池板的标志。图片作者。
接下来,我想在太阳能电池板周围加一个圈来突出它。条形图中的 X 轴和 Y 轴具有不同的刻度。X 轴上的每个小刻度以 1 年为步长,而 Y 轴上的每个小刻度以 100 GW 为步长。因此,使用plt.Circle((x,y),r)
和ax.add_patch(circle)
添加一个circle
会使其在图中显得不均匀。
相反,我使用了一个散点图,其中心与 AnnotationBbox 的中心相同。我将半径s
设置为 20000,marker
设置为“o”形,color
设置为“红色”,facecolors
设置为“无”,在太阳能电池板周围添加一个圆。
plt.scatter(5, 700, s = 20000, marker = “o”,
color = “red”, facecolors = “none”)
结果图如下所示。
在条形图上的太阳能电池板标志周围添加一个圆圈。图片作者。
结论
在现有地块上添加图像或图标可以增加视觉吸引力和感知度。在这篇文章中,我逐步描述了如何使用 Matplotlib 将外部图像读取为二进制格式的 NumPy 数组,以及如何显示图像数据并将其添加到条形图中。在这种情况下,我提供了一个简单的例子,在显示太阳能光伏装机容量全球趋势的条形图顶部添加一个太阳能电池板的徽标。这篇文章的笔记本可以在这个 GitHub 库中找到。感谢您的阅读!
参考
亚当史密斯,2022。如何用 Python 创建 3D NumPy 数组
极客 forGeeks,2022。用 Python 阅读图像。
IRENA,2021。统计时间序列:可再生能源趋势。
Matplotlib,2020。matplotlib . axes . axes . im show
如何在 Scikit-learn 中向预训练模型添加新数据
机器学习
关于如何在 scikit-learn 中使用 warm_start=True 和 partial_fit()的分步教程
当您从头开始构建机器学习模型时,通常会将数据集分为训练集和测试集,然后在训练集上训练您的模型。然后,您在测试集上测试您的模型的性能,如果您得到一些不错的东西,您可以使用您的模型进行预测。
但是,如果新数据在某个时候变得可用,该怎么办呢?
换句话说,如何训练一个已经训练好的模型?还是那句话,如何给一个已经训练好的模型添加新的数据?
在本文中,我试图使用 scikit-learn 库来回答这个重要的问题。你可以查看vid hi Chugh的这篇有趣的文章,了解你什么时候需要重新训练你的模型。
对于前一个问题,一个可能的(琐碎的)解决方案是通过使用新旧数据从头开始训练模型。然而,如果第一次训练需要很长时间,这种解决方案就不能扩展。
问题的解决方案是向已经训练好的模型中添加样本。这个 scikit-learn 允许你在某些情况下这样做。只要遵循一些预防措施。
Scikit-learn 提出了两种策略:
- 部分拟合
- 热启动
为了说明如何在 Scikit-learn 中向预训练模型添加新数据,我将使用一个实际的例子,使用由 Scikit-learn 库提供的众所周知的 iris 数据集。
热启动
热启动是一些 Scikit 型号提供的参数。如果设置为 True,则允许在随后的 f it 调用中使用现有的 fit 模型属性来初始化新模型。
例如,您可以在随机森林分类器中设置warm_start = True
,然后您可以定期拟合模型。如果对新数据再次调用 fit 方法,新的估计器将被添加到现有的树中。这意味着使用 warm_start = True 不会改变现有的树。
warm_start = True
是否应该而不是用于在可能存在概念漂移的新数据集上进行增量学习。概念漂移是数据模型中的一种漂移,它发生在输出和输入变量之间的基本关系发生变化时。
为了理解warm_start = True
是如何工作的,我描述一个例子。这个想法是为了表明,如果我添加新数据,使用 warm_start = True 可以提高算法的性能,新数据与原始数据具有相同的分布,并且与输出变量保持相同的关系。
首先,我加载由 Scikit-learn 库提供的 iris 数据集:
from sklearn import datasetsiris = datasets.load_iris()
X = iris.data
y = iris.target
然后,我将数据集分成三部分:
X_train
,y_train
—40%数据的 80%训练集(48 个样本)X_test
,y_test
—测试集 40 个数据的 20%(12 个样本)X2, y2
—新样本(60%的数据)(90 个样本)
from sklearn.model_selection import train_test_splitX1, X2, y1, y2 = train_test_split(X, y, test_size=0.60, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X1, y1, test_size=0.20, random_state=42)
我会用X2
和y2
重新训练模型。
请注意,训练集非常小(48 个样本)。
我训练模型,用warm_start = False
:
from sklearn.ensemble import RandomForestClassifiermodel = RandomForestClassifier(max_depth=2, random_state=0, warm_start=False, n_estimators=1)
model.fit(X_train, y_train)
我算了一下分数:
model.score(X_test, y_test)
它给出了以下输出:
0.75
现在,我用新数据来拟合这个模型:
model.fit(X2, y2)
先前的拟合删除了已经学习的模型。然后,我计算分数:
model.score(X_test, y_test)
它给出了以下输出:
0.8333333333333334
现在我用 warm_start = True 构建一个新模型,看看模型得分是否增加。
model = RandomForestClassifier(max_depth=2, random_state=0, warm_start=True, n_estimators=1)
model.fit(X_train, y_train)
model.score(X_test, y_test)
它给出了以下输出:
0.75
现在,我拟合模型并计算分数:
model.n_estimators+=1
model.fit(X2, y2)
model.score(X_test, y_test)
它给出了以下输出:
0.9166666666666666
增量学习提高了分数!
部分拟合
Scikit-learn 提供的向预训练模型添加新数据的第二个策略是使用partial_fit()
方法。并非所有的模型都提供这种方法。
虽然warm_start = True
参数不改变模型已经学习的属性参数,但是部分拟合可以改变它,因为它从新数据中学习。
我再次考虑虹膜数据集。
现在我用一个SGDClassifier
:
from sklearn.linear_model import SGDClassifier
import numpy as npmodel = SGDClassifier()
model.partial_fit(X_train, y_train, classes=np.unique(y))
第一次运行 partial_fit()方法时,我还必须将所有的类传递给该方法。在这。例如,我假设我知道 y 中包含的所有类,尽管我没有足够的样本来表示它们。
我算了一下分数:
model.score(X_test, y_test)
它给出了以下输出:
0.4166666666666667
现在,我将新样本添加到模型中:
model.partial_fit(X2, y2)
我计算分数:
model.score(X_test, y_test)
它给出了以下输出:
0.8333333333333334
添加新数据提高了算法的性能!
摘要
恭喜你!您刚刚学习了如何在 Scikit-learn 中向预训练模型添加新数据!您可以使用设置为True
的warm_start
参数或partial_fit()
方法。然而,并非 Scikit-learn 库中的所有模型都提供向预训练模型添加新数据的可能性。因此,我的建议是检查文档!
你可以从我的 Github 库下载本教程中使用的代码。
如果你读到这里,对我来说,今天已经很多了。谢谢!你可以在这个链接阅读我的趋势文章。
相关文章
保持联系!
作为数据分析师如何增值
原文:https://towardsdatascience.com/how-to-add-value-as-a-data-analyst-8a6ae900b82a
成为“真正的”数据分析师的旅程
让我们先快速总结一下关于分析的三个常见误解:
- 分析是统计。【T4 号】
- Analytics 就是数据新闻/营销/讲故事。【T8 号】【T9 号】
- 分析是决策。(不!)
由 Alexander Sinn 在 Unsplash 上拍摄
误解 1:分析与统计
虽然他们使用的工具和公式相似,但分析师和统计学家接受的培训却截然不同(点击此处了解更多】):
分析帮助你形成假设,提高你的问题质量。
统计帮助你测试假设,提高你的答案质量。
误解 2:分析与新闻/营销
分析不是营销。区别在于,分析是关于扩大决策者的视角,而营销是关于缩小它。
分析是关于扩大决策者的视角,而营销是关于缩小它。分析师首先服务于他们的决策者。
同样,数据新闻/讲故事是以小的方式捕捉许多人的兴趣,而分析是以大的方式服务于少数人的需求。分析师首先服务于他们的决策者。(点击了解更多。)
数据新闻/讲故事是以小的方式捕捉许多人的兴趣,而分析是以大的方式服务于少数人的需求。
误解 3:分析与决策
分析服务于决策,但它是一个独立的角色。*
如果我是你的分析师,我不会在这里为你选择(即使我可能比你有更多的领域专业知识)。你必须把我提升为决策者,这样做才合乎道德。
如果你想让某人作为分析师和决策者的混合体工作,要明白你是在要求两个角色合二为一,并明确分配这一职责。(了解更多这里。)
*我经常被问到的一个问题是,“如果我被要求服务的决策者不称职,我们该怎么办?”完全正确——如果你的决策者不熟练,事情会变得棘手。这里的负责人为我解答。
业余分析师对专业分析师
现在我们已经回顾了一些关于这个角色的误解,我们准备好回到我们的旅程,看看业余分析师和专业分析师之间的区别。在我以前的文章【1】【2】【3】中,我们已经详细讨论了前 7 个问题,现在我们为第 8 个问题做准备。
专业数据与业余数据的区别# 8——知道如何增加价值
人们一直将“了解业务”列为分析师职责的一部分,但很少有人清楚地解释这与他们的价值有什么关系。
那些受雇于混合角色的人做了一件让那些没有混合角色的人困惑的工作。
困惑的部分原因是误解了决策者的工作和分析师的工作之间的区别(见上文)。你们中那些被雇佣为决策者和分析师混血儿的人做了大量的工作来迷惑那些没有被雇佣的人。这可能有助于澄清事情:
- 一个 分析师 为他们的决策者服务。
- 一个 决策者 为他们的业务服务。
如果你是两种角色的混合体,了解业务就是赌注。作为一名决策者,定义应该如何增加价值、设置优先级以及抓住机会优化业务是你的直接责任。我可以就这个话题写很多东西,但是这篇博文是关于分析师的,所以让我们把重点放在非混合版本上。
做什么和为什么做,这取决于决策者。怎么做取决于分析师。
决策者什么时候需要分析师?当他们没有时间自己处理、探索和总结所有可用的潜在有用信息时。换句话说,分析师充当决策者的某种感觉器官。决策者的工作是将信息转化为更好的行动,如果他们不能获得大量信息,这是没有希望的。这就是分析师介入的地方。
应用你的倾听技巧是另一种分析,正如我在这个视频中解释的。
要有价值,分析师必须学会有效地为决策者服务。你知道什么比商业知识更好吗? 听力技巧。 是的,这份工作涉及到另一种分析:与真人对话,而不仅仅是一堆数据。你还需要出色的 沟通技巧 ,因为你将增强你的决策者的感觉 …所以你需要将信息顺利地从你的屏幕传入你的决策者的大脑。什么和为什么,都在他们身上。怎么做,取决于你。
在三种数据科学专业人士中,分析师是最有可能继承决策宝座的人。
分析师为决策者服务的一个基本方式是充当他们的搜索引擎。决策者想知道一些关于业务的事实,你为他们查找。这是反应式分析,我们倾向于认为它是分析中的初学者——专家的工作是主动的:都是关于从数据中提取灵感。(点击了解更多。)
分析师在模糊中茁壮成长。他们的天赋是探索,这使他们特别善于预见和应对危机。
分析师能做出的最有价值的贡献是激励决策者考虑他们不知道需要考虑的行动方案。换句话说,成功地搜寻值得了解的未知事物。
努力成为真正创新者的商业领袖投资于分析。
在繁荣时期,我们称这种工作为“推动创新”**“寻找新的机会加以利用”当情况变得艰难时,我们开始谈论“识别威胁”和“防患于未然”在困难时期,看起来不错的创新助推器变成了必须的安全网,但两者都是一枚硬币的两面:探索信息,以激励领导者提出他们可能不会考虑的问题。(得到这些问题的答案是一项不同的工作。)了解更多这里。
分析师的工作是用发人深省但合格的可能性来激励高管。
专注于为决策者服务的分析师努力工作,尽可能地发挥作用:他们主动探索数据,预测后续问题,通常避免浪费决策者的时间。要做到这一点,他们必须逐渐培养出除了有趣的东西之外对重要的东西的敏锐嗅觉,这意味着他们自然会吸收一些决策者的专业知识。
分析师能做出的最有价值的贡献是激励决策者考虑他们不知道需要考虑的行动方案。
如果你不了解决策者如何利用信息来选择行动,你就无法产生可操作的洞察力。尽管从技术上讲,洞察力的可操作性不是分析师的责任——而是决策者的责任——但在实践中,随着时间的推移,这一界限变得模糊。
这就是为什么在数据科学专业人士的三种中,分析师是最有可能继承决策宝座的人……如果这是他们想要的工作的话。(还有很多东西要学,这些都不是免费的,如果数据是你的真爱,那么不建议你做出改变。)
当谈到培养判断事物发展方向并对不断变化的环境做出灵活反应的能力时,没有什么比分析更重要了。
总结这一节,业余爱好者经常错过分析的要点,对价值来自哪里缺乏一致的理解。专业分析师是这样理解的:
如果你是一个决策者的混合体,你的价值由你的决策和行动的质量来判断。你的分析技能是达到这一目的的手段——分析只是你武库中的众多武器之一。
工作的一部分是问一些(困难的)问题。
如果你是一个纯粹的分析师,你的价值取决于你为决策者服务的能力,既包括反应性的(通过查找回答他们特定问题的数据),也包括前瞻性的(通过探索数据来启发他们考虑新的方向,使他们更具创新性和抵御威胁的能力)。从任何地方开始,除了你的决策者的需求和优先事项,注定会把你引入歧途。
本文到此为止。在下一个中,我们将继续业余分析师和专业分析师之间的最后两个差异: 专业数据与业余数据的差异# 9——对时间的不同思考
专业数据与业余数据的差异# 10——对卓越的细致入微的看法
让我知道你是否喜欢这个话题,不要忘记与你的社区分享你最喜欢的见解!
专业数据与业余数据的差异#1-#3
软件技能;轻松处理大量数据;不受数据科学偏见的影响。包含在第 1 部分中。
*
专业数据与业余数据的差异# 4 –# 6
了解职业;拒绝成为数据江湖骗子;对确认偏差的抵抗力。包含在第 2 部分中。
专业数据与业余数据的差异#7
对数据的现实预期。包含在第 3 部分中。
https://kozyrkov.medium.com/how-to-form-realistic-expectations-about-data-622e85ab62cb
喜欢作者?与凯西·科兹尔科夫联系
让我们做朋友吧!你可以在 Twitter 、 YouTube 、 Substack 和 LinkedIn 上找到我。有兴趣让我在你的活动上发言吗?使用这种形式取得联系。*
如何解决机器学习中的数据偏差
原文:https://towardsdatascience.com/how-to-address-data-bias-in-machine-learning-c6a45db53b8d
理解偏差到底是什么并采取正确的措施来防止它在数据科学领域非常有用。
在 Unsplash 上由 Bodie Pyndus 拍摄的照片
嗯,公司在机器学习的帮助下,花费了大量的收入来帮助发展他们的业务。作为一个主要参与数据清理和数据准备以及为公司执行有价值的预测的人,当试图在生产中部署ML 模型时,还有一个更重要的因素需要考虑。在这段时间里,我们还应该考虑人工智能的伦理含义以及我们的模型在预测结果时有多大的偏差。因此,最根本的问题应该是机器学习中的偏见到底是什么。现在让我们来处理机器学习的这个领域,这样我们就可以产生一个健壮的模型,它也考虑了伦理因素。
什么是数据偏差?
Alexander Schimmeck 在 Unsplash 上拍摄的照片
每当我们向 ML 模型提供数据时,数据的质量以及特征与结果的关联程度通常决定了预测模型的质量。如果存在与结果不高度相关的特征,那么从最简单的模型到最复杂的模型,成功使用这些模型的可能性极小。因此,作为数据科学家或机器学习工程师,必须考虑的最重要的方面是给予各种模型的数据质量。
现在我们正在慢慢接近数据偏差的定义。如果你能耐心听我说,你会得到几行字的解释。因为我们已经知道数据形成了模型在测试数据(看不见的数据)上实际表现如何的基础,所以假设数据的质量决定了模型在测试数据上表现如何是基本的。如果我们用于 ML 模型的数据包含一组特定类的大量信息,那么它们在这些特定类上的表现可能比在其他类上的表现更好。
为了将它放在上下文中,想象我们正试图根据一系列特征(如地区、性别、种族、社会地位、收入和工作)来预测一个人是否会拖欠贷款。因此,可能会有一些高度适用于模型预测的要素。当我们考虑像‘性别’这样的例子,并看到很大一部分被代表的人是男性时,模型将会了解很多关于男性借款人的情况,以及与女性借款人相比,他们是否会偿还贷款。类似的论点也可以用在种族身上。通过这种方式,该模型天生就知道,身为“男性”拖欠贷款的几率会更低,反之亦然。当我们考虑诸如准确度之类的指标来衡量模型的表现时,我们可能会夸大其表现,尽管它在少数类中表现不佳。这就是所谓的数据偏差,即与其他类别的特征相比,某些类别的特征被过度表示。
虽然偏见可能经常是无意的,但它们的存在对受其影响的人群来说却是非常重要的。想想亚马逊的招聘算法系统地筛选出女性候选人的例子。同样,微软的** Twitter 机器人因其提供的结果和产生的反馈而被指控为种族主义者。如果结果显示模型结果更偏向于特定的人群,则用户将来更有可能会失去信任并且永远不会使用这些模型。**
在经历了这么长的解释之后,我们可以得出结论,应该采取措施来克服这个问题,这样我们就可以对模型建立更多的信任。
如何克服机器学习中的数据偏差
借助正确的策略和工具,有许多方法可以减少数据偏差。减少偏差的第一个方法是了解偏差发生的确切位置。如果我们知道应该关注哪些领域可能存在偏差,我们就可以采取正确的措施来确定有助于在很大程度上减少这种偏差的行动。现在让我们回顾一下可以在很大程度上减少偏差的各种方法。
确定正确的机器学习模型
当我们使用各种 ML 模型时,无论我们是在进行有监督的机器学习还是无监督的机器学习,偏差都可能是模型学习输入和输出之间的各种表示,这有助于它学习它。如果我们要改变模型中的几个超参数或几组东西,那么我们就会得到最好的模型,所有类别的性能往往会非常一致。
想象一下,你的团队要求你设计一个机器学习模型,它可以根据年龄、性别、血压等一系列特征来捕捉一个人是否有更高的患癌几率。有一些模型可以学习诸如性别和年龄等特征的表示。与其他因素相比,这些特征有时可以被使用并被赋予更大的重要性。如果是这种情况,根据模型,特定性别或年龄患癌症的可能性更高。因此,在这种情况下,模型可能会有偏差,因为它只是基于性别或年龄作为一个重要因素来预测结果。应对这一挑战的最好方法之一是使用各种工具来构建模型的可解释性。如果我们首先知道为什么模型做出了决定,我们就可以确定模型是否有偏差。有一些工具,如 LIME (本地可解释的模型不可知解释),也可以帮助我们确定为什么模型会给出一个特定的决定,从而帮助医生。还有其他工具,如 SHAP (沙普利值)也可以用于可解释性。让你的团队了解为什么模型会给出特定的决策或结果是件好事。
为使用的数据提供适当的文件
记录数据有两方面的帮助。首先,它有助于我们理解模型中的各种特征及其对结果的影响。第二,它也可能导致这样的情况,我们可以通过观察数据的分布来识别数据中的偏差。拥有适当的数据文档还可以确保使用它的其他人了解对模型预测有影响的各种特征的存在,以及模型中各种组的存在或过度表示。
因此,当我们试图使用数据建立一个具有机器学习的解决方案时,如果有提供的功能的文档会很方便。考虑一个预测给定文本是阳性还是阴性的例子。在这种情况下,我们将在自然语言处理(NLP) 的帮助下查看各种特性。当我们使用这个解决方案时,如果有一个我们用来预测文本情感的数据和特征的文档,它会非常有用。如果有大量的正面文本,只有少量的负面文本,那么当有负面评论时,模型很难做得很好。此外,查看所使用的各种功能的文档可以帮助我们更好地理解数据以及每个功能在模型预测中的影响程度。如果有适当的数据文档,以便团队成员在使用机器学习模型进行预测之前可以访问并完全理解这些数据,这是可能的。
评估各种类别的模型性能
当构建可用于生产的 ML 模型时,它们往往对我们数据中的一组特定类别表现良好。当我们考虑保护的特征时,比如年龄、性别和性别,与其他人相比,它们可以在某个群体或类别中表现良好。为了消除偏见,我们必须确保模型在所有类别上都表现良好,而不仅仅是在一个类别上。因此,我们必须考虑每个子组的性能,并了解所有组的性能是否一致。这样,就很有可能减少模型中的偏差。
考虑这样一种情况,您的模型在测试数据(看不见的数据)上表现很好,用于预测一封邮件是垃圾邮件还是火腿。我们知道,在现实生活中,我们的大部分邮件都是垃圾邮件,只有少数情况下会有垃圾邮件。因此,可用于训练模型的数据在很大程度上包含类别不平衡,与垃圾邮件相比,垃圾邮件的数量更多。在这种情况下,如果我们评估每个单独类的性能,而不是完全关注数据,这将非常有用。这样,我们很好地评估了每个单独类别的性能,而不是整个数据,从而减少了对特定类别(多数类别)的偏差。
传播更多的意识
虽然有许多合格的数据科学家在解决公司中一些最复杂的问题,但也有少数人不太重视人工智能的道德方面。传播对机器学习中存在偏见的认识可能非常有用,特别是当可以采取行动打击偏见时。在在线课程中添加更多关于机器学习伦理方面的内容也可能是有益的。
当看最近的新闻时,我们了解到像谷歌和微软这样的公司正在采取措施传播更多关于人工智能伦理的意识。类似地,组织可以采取行动,也可以让人们更加意识到数据偏差问题及其对各种受保护类别的影响。当他们采取正确的步骤,对模型预测更加透明时,许多人可以信任这些黑箱模型,并在他们未来的努力中使用它们。
结论
总而言之,我们已经看到,在用于预测的机器学习模型中可能存在数据偏差。采取正确的步骤来消除数据中的偏见可能会很方便,特别是当我们承认人工智能的道德方面时。为消除机器学习中的偏差,可以遵循的步骤是确定正确的 ML 模型,评估各种类别的模型性能,并传播更多的偏差意识。感谢您花时间阅读这篇文章。也欢迎分享你的想法。
如果你想获得更多关于我的最新文章的更新,并且每月只需 5 美元就可以无限制地访问中型文章,请随时使用下面的链接来添加你对我工作的支持。谢了。
https://suhas-maddali007.medium.com/membership
以下是您联系我或查看我作品的方式。
GitHub: 苏哈斯马达利(Suhas Maddali)(github.com)
LinkedIn: (1)苏哈斯·马达利,东北大学,数据科学| LinkedIn
中等:苏哈斯·马达利——中等
使用 Esquisse 快速分析数据
原文:https://towardsdatascience.com/how-to-analyze-data-quickly-without-tableau-but-close-66eb1f2fffd2
回顾-工具-数据科学
Esquisse——一个进行数据分析和可视化的免费工具
由凯西·霍纳在 Unsplash 上拍摄的照片以及作者提供的附加图片
介绍
你知道当你得到一个新的大规模数据集作为你的项目的一部分,你需要很快得到它的“感觉”是什么感觉吗?你可以从查看数据的头部开始,在终端或 Jupyter 笔记本中打印出摘要,或者直接在 Excel 中打开。此外,您可以使用 matplotlib 或 ggplot2 创建一些概览图来熟悉该数据集。
但现在不是了!我最近遇到了漂亮的开源工具 esquisse,它大致遵循了著名的商业工具 Tableau 的概念。我把它称为一个工具,但实际上,它是一个 R 包,允许你通过拖放来加载数据和创建漂亮的可视化效果。
本文将向您介绍免费的开源工具 Esquisse 及其特性。这包括加载数据、选择变量和数据可视化类型、过滤、绘图完成和导出。
Esquisse 和设置
埃斯奎塞
各大洲的预期寿命;作者图片
此加载项的目的是让您快速浏览数据以提取其中包含的信息。您可以使用{ggplot2}创建可视化,使用{dplyr}过滤数据并检索生成的代码。来源:Esquisse 网站
如上所述,Esquisse 是一个 R 包,因此,您可以很容易地将其集成到您的分析脚本中。但是当然,您可以在没有特定数据项目的情况下使用它。它被写成一个闪亮的应用。
在屏幕的顶部,您可以选择特定的图,如条形图、箱线图或散点图。此外,它还显示了加载的数据集的所有变量(列)。您可以将这些映射到您的 x 轴和 y 轴、颜色、大小和组。但稍后会详细介绍。屏幕的中间是画布和结果图。每当更改您的数据映射时,都会更新此信息。底部有注释你的图,改变布局,过滤数据,甚至导出产生的 ggplot2 代码的功能。
设置
要安装 Esquisse,只需在您的 R 终端中写入以下代码:install.packages("esquisse")
使用library("esquisse")
加载库
在本文中,我使用 Gapminder 数据集展示了一些可视化示例。Gapminder 的数据是在知识共享署名 3.0 未授权许可下发布的。请看这里如何设置:为你的下一个数据科学项目准备的 7 个数据争论 R 函数
然后你可以调用 Esquisse。这将允许您选择(1)R 环境中的数据,(2)从任何已安装的包中选择数据,(3)上传 CSV 或 xls 文件,(4)复制和粘贴数据,或者(5)使用 Google 电子表格。
esquisser()
数据导入选项;作者图片
另一种方法是通过将数据框传递给 esquisser 函数来调用 Esquisse。esquisser(gapminder)
特征
在这一节中,我将详细介绍 Esquisse 出色的数据分析和可视化特性。第一个功能是导入或使用数据。这一点,我在前一节已经解释过了。
数据表视图
数据表视图;作者图片
导入数据并单击左侧第二个表格图标后,您将看到数据的表格视图。我觉得这个很有用。这将有助于您检查是否所有数据点实际上都是可用的。此外,如果您的一些可视化看起来与预期不同,它将帮助您仔细检查您的数据。就我个人而言,我经常使用搜索功能。此外,您可以使用每个列标题上的小箭头对数据进行排序。不可能在表格视图中过滤数据。相反,您需要关闭表格视图并点击页面底部的数据按钮。在本文的后面部分会有更多的介绍。
通过拖放创建数据图
可用的图表类型;作者图片
Esquisse 提供了几种常用的图形类型。这些包括线图和点图、面积图和条形图、平铺图、箱线图和地图。需要指出的是,在数据映射期间,您可以选择“自动”。该工具将根据您的制图和数据为您推荐一种图表类型。
数据映射;作者图片
在图表类型选择旁边,您会看到数据集的可用列(变量)。蓝色代表数值变量,橙色告诉我们它们是分类变量。
您可以将这些变量拖到下面的部分来映射您的数据。x 和 y 表示将数据映射到数据可视化轴。在上图中,我在 x 轴上绘制了大陆,在 y 轴上绘制了人口。这对于盒状图或者在这种情况下的小提琴图来说很有效。“填充”部分允许您操作图表的任何颜色。这适用于箱线图、小提琴图、条形图和面积图。您可以使用“颜色”部分根据变量应用颜色。这最适合线条,而不是我们使用“填充”部分的区域。请参见下面的折线图示例。我们在点图中使用大小来控制点的大小。“组”允许我们比较不同组之间的数据。下面的例子会产生类似的结果,但是不会应用不同的颜色。“Facet”在任何可视化中都是一个强大的特性。它允许您创建数据的“小倍数”。一个比较复杂数据的好方法。
数据映射部分颜色(大洋洲大陆的过滤器);作者图片
数据过滤
数据过滤;作者图片
通常我会在创建可视化表示之前根据一些要求过滤数据。在这里过滤数据是一个很好的功能。为此,请按底部的“数据”按钮。您将看到一个弹出窗口,其中包含您的数值和分类变量及其范围。您可以使用滑块和选项来过滤数据。
为您的可视化做最后的润色
图形标注;作者图片
在映射数据、选择合适的图表类型和一些过滤之后,您可以对您的图表进行注释。在左下角,你可以找到“标签和标题”。您可以指定标题和副标题、标题、x 轴和 y 轴的标签以及颜色图例。
绘图选项;作者图片
你可能还想调整你的情节的一些选项。比较上面的图像以查看选项。这些包括轴限制、转换(log10)等。翻转坐标可以方便地将垂直条形图转换为水平条形图。
外观选项;作者图片
最后,通过“外观”,您可以选择特定的调色板,并选择一个 ggplot2 主题。我选择了“经济学家怀特”主题,你也可以在图片中看到。
出口
导出选项;作者图片
按下图右侧的“下载图标”,您将看到多种输出格式。按下“更多选项”,你会看到一个带有额外选项的专用屏幕,比如操作宽度和高度。
代码导出;作者图片
同样有用的是,您可以导出底层代码。因为 Esquisse 在内部使用 ggplot2 来生成这些图形,所以代码将在您自己的 R 脚本中精确地再现任何给定的图形。这也将增强我们对 ggplot2 的理解,方法是使用 Esquisse 创建一个图,然后查看代码以了解这是如何完成的。酷毙了。
结论
本文向您介绍了免费的开源工具 Esquisse 及其特性。这包括加载数据、选择变量和数据可视化类型、过滤、绘图完成和导出。
我发现当我需要快速理解一个新的数据集并创建一些用于交流的初始图时,它特别有用。我将这个工具整合到我的专业工作流程中。但是你对此怎么看?请在评论中分享。
如果你想阅读更多关于我的旅程,请考虑关注我,或者如果你不是一个媒体成员,请考虑加入这里。非常感谢。
谢谢你,
格雷果
https://gscheithauer.medium.com/membership
凯西·霍纳在 Unsplash 上拍摄的照片以及作者提供的其他图片
如何在 MATLAB 中制作动画
原文:https://towardsdatascience.com/how-to-animate-plots-in-matlab-fa42cf994f3e
一种简单的数据动画制作方法
动画 MATLAB 情节[由作者创建]
图表可能会令人厌烦。没有办法。如果你不是数据爱好者,不喜欢用简单的线、条或点来讲述一个故事,那么情节可能很难引起注意。一个动画可以是一个很好的工具,把观众包装成一个图表。我们的眼睛被训练来观察移动的物体,所以如果你是一名数据科学家或工程师,报告一些有趣的数据,让它随着时间的推移而发展,使它变得引人入胜。让运动为你讲述这个故事。到本文结束时,您将有一个框架来开发有趣的动画,这可能会帮助您获得下一次晋升,打动您的教授,或者只是提高您作为数据处理者的技能。
在本文中,我将假设你有一些关于创建数据和基本绘图的 MATLAB 编码背景。这并不是使情节生动的唯一方法;只是在我看来最直观的方法。想分享方法就留下评论吧!在本例中,我们将使用带有动态标题的三维线条和散点。但是,该方法可以扩展到您选择的绘图类型。事不宜迟,我们开始编码吧!
清除一切
我发现在开始你的主代码之前,最好的做法是清除命令窗口,变量,并关闭所有的图形窗口。我们将添加以下三行代码来实现这一点。
clc
clear variables
close all
创建或导入数据
这一步对于您的数据集来说是唯一的。对于这个例子,我们可以基于任意的数学函数创建一个数据集。您可能有一个导入的数据集,或者您可能已经创建了自己的数据,但是如果您试图按照这个示例进行操作,请使用我在这里使用的函数。在这个例子中, t 是时间(在动画中以秒为单位标注),而 x 、、 y 、 z 、是描述粒子位置的空间数据。
% Creating Data to Animate
% Time array
t = linspace(0, 6, 100);% Particle coordinates
x = 4*sin(t);
y = 0.5*x.^2;
z = x.*cos(t);
初始化绘图
下一步是定义我们的情节特征。这包括创建动态标题和轴标签。动态标题包括四舍五入到两位小数的轨迹的当前时间(这些不是实时秒)。注意,我在这里对文本使用了 LaTeX 解释器;我发现它比默认文本更好看。接下来,您可以添加网格线,使轴的比例相等,并更改 3D 打印的视角。
% Setting up the Plot
figure; hold on
title(sprintf('Trajectory\nTime: %0.2f sec', t(1)), 'Interpreter', 'Latex');
xlabel('x', 'Interpreter', 'Latex')
ylabel('y', 'Interpreter', 'Latex')
zlabel('z', 'Interpreter', 'Latex')
grid minor % Adding grid lines
axis equal % Equal axis aspect ratio
view(-37.5,30); % Setting viewing angle
查看和保存动画
对于这种方法,这两个步骤是结合在一起的,但是如果需要,可以删除保存步骤。如果要保存动画,我们需要创建一个文件名变量, animation.gif 。为了在动画之前正确调整轴的大小,我们绘制了没有颜色的轨道。接下来,我们初始化线和散点变量, p 和 m 。在 for 循环中,我们可以简单地在每次迭代中更新 p 和 m 的 x、y 和 z。对于这条线,我们将希望把它从初始点更新到我们当前的步骤, k 。对于散布点和标题,我们只需要当前步骤。我们包括一个延迟(暂停(0.01) ),可以调整它来改变显示的动画速度(与保存的不同)。 gif 速度)。
下一个代码块是用来保存的,所以如果你愿意,你可以在这个步骤之前结束的循环,从 MATLAB 的图形窗口中观看你的动画。让我解释一下这段代码中发生了什么。 getframe 功能将人物窗口捕捉为电影帧,而 frame2im 将其转换为 RGB 图像。函数 rgb2ind 将图像转换为带有相关颜色图的索引图像。在循环的的第一个索引(在处 k 处 =1)处,我们初始化。gif* 文件,包含索引图像、颜色映射、文件名、文件类型、循环计数和动画帧之间的延迟。对于 k 的其他值,我们以类似的方式将下一个动画帧添加到现有文件中。*
% Create file name variable
filename = 'animation.gif';% Plotting with no color to set axis limits
plot3(x,y,z,'Color','none');% Plotting the first iteration
p = plot3(x(1),y(1),z(1),'b');
m = scatter3(x(1),y(1),z(1),'filled','b');% Iterating through the length of the time array
for k = 1:length(t)
% Updating the line
p.XData = x(1:k);
p.YData = y(1:k);
p.ZData = z(1:k); % Updating the point
m.XData = x(k);
m.YData = y(k);
m.ZData = z(k); % Updating the title
title(sprintf('Trajectory\nTime: %0.2f sec', t(k)),...
'Interpreter','Latex'); % Delay
pause(0.01) % Saving the figure
frame = getframe(gcf);
im = frame2im(frame);
[imind,cm] = rgb2ind(im,256);
if k == 1
imwrite(imind,cm,filename,'gif', 'Loopcount',inf,...
'DelayTime',0.1);
else
imwrite(imind,cm,filename,'gif','WriteMode','append',...
'DelayTime',0.1);
end
end
现在,您可以将它添加到其余的代码中并运行它。您的图形窗口将显示您的动画,您将找到一个文件(名为animation . gif),其中保存了包含您的动画的代码。如果操作正确,您的绘图应该如下所示(点的速度可能不同):
轨迹动画【作者创作】
本文到此为止。感谢您的阅读!如果你不想错过更多的 MATLAB、Python 和工程文章,请关注我并订阅我的电子邮件。看看我的其他文章吧!
如何在 Python 中制作情节动画
原文:https://towardsdatascience.com/how-to-animate-plots-in-python-2512327c8263
了解制作数据动画以创建动态视觉效果的基础知识
动画情节[由作者创作]
当今世界对数据的需求越来越大。公司和个人通过机器学习使用它来预测股票价格,跟踪运动员的健康状况,研究特定城市的房价……可能性是无限的。虽然原始数据是基础,但它能讲述的故事更重要。讲述这个故事是工程师和数据科学家的工作。视觉可能是使用数据传达想法的最佳方式之一。想一想,你是愿意看一行行的数据,还是看几幅概括这些数据的图表?像大多数人一样,你可能认为剧情听起来更好。虽然并不总是必要的,但在情节中加入动画可以为你的故事提供额外的意义。
到本文结束时,您应该能够重现上述情节,并使用该框架创建自己的精美动画。
Emile Perron 在 Unsplash 上的照片
对于本文,我将假设您对 Python 以及如何执行基本的数据操作和绘图有一点了解。请记住,这不是使用 Python 动画功能的唯一方法,所以如果你有其他想法,请在下面分享你的方法!我们将使用三维线和散点来创建轨迹,但这些概念可以扩展到其他绘图类型,如二维线、条形图、饼图、等高线等。
导入包
Python 有大量用于数据分析的库,所以我们将使用其中的几个。让我们开始一个新的脚本,并导入这个项目所需的包:
# Importing Packages
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import animation
- NumPy 将用于创建数值数组和使用三角函数(为了方便调用,定义为 np )
- 来自 Matplotlib 的 Pyplot 将用于绘制图形(为便于调用,定义为 plt
- Axes3D 将用于为我们的绘图创建三维轴
- 来自 Matplotlib 的动画将用于通过重复调用我们稍后将定义的函数来创建我们的动画
创建数据集
在我们考虑绘制任何东西之前,我们需要创建要绘制的数据。对于这一部分,我使用正弦函数和一个从 0 到 20 运行的时间数组创建了一些位置数据(我在动画中任意标注为秒)。
# Time Array
t = np.linspace(0, 20, 100)
# Position Arrays
x = np.sin(np.pi/5 * t)
y = np.sin(np.pi/3 * t)
z = np.linspace(0, 100, 100)
# Setting up Data Set for Animation
dataSet = np.array([x, y, z]) # Combining our position coordinates
numDataPoints = len(t)
我认为这一部分非常简单明了。你可以改变时间和位置数组来创建新的轨迹。数据集和 numDataPoints 变量将在我们的动画函数中使用,我们将在接下来定义。
动画功能
为了给我们的人物制作动画,我们将使用一个名为 FuncAnimation 的函数,来自导入的 animation 类。您可以在这里访问这两个的文档。 FuncAnimation 要求我们创建自己的函数来更新线、点等。,我们将其定义为 animate_func 。
def animate_func(num):
ax.clear() # Clears the figure to update the line, point,
# title, and axes # Updating Trajectory Line (num+1 due to Python indexing)
ax.plot3D(dataSet[0, :num+1], dataSet[1, :num+1],
dataSet[2, :num+1], c='blue') # Updating Point Location
ax.scatter(dataSet[0, num], dataSet[1, num], dataSet[2, num],
c='blue', marker='o') # Adding Constant Origin
ax.plot3D(dataSet[0, 0], dataSet[1, 0], dataSet[2, 0],
c='black', marker='o') # Setting Axes Limits
ax.set_xlim3d([-1, 1])
ax.set_ylim3d([-1, 1])
ax.set_zlim3d([0, 100])
# Adding Figure Labels
ax.set_title('Trajectory \nTime = ' + str(np.round(t[num],
decimals=2)) + ' sec')
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z')
我们首先注意到被传递到 animate_func 中的 num 变量。这是当前动画步骤的索引。当我们将 animate_func 传递给 FuncAnimation 时,它将迭代我们的 num 变量。我们可以使用该变量来遍历我们之前创建的数据集。
该功能从清除图形开始。这将删除线、点、原点、轴标签和标题。然后添加更新的轨迹线(从 0 到号)和点位置(在步骤号)。我们的原点在这个图中保持不变,所以你会注意到 num 没有出现,因为我们没有改变原点。接下来,该函数定义了我们不变的轴限制。如果希望轴随着数量的增加而变化(使轴成为动态的),可以删除轴限制。
最后,该函数定义了我们的标题和轴标签。标签很简单,只是我们的 x 、 y 和 z 用于笛卡尔坐标。作为一点额外的功能,我们有一个显示轨迹时间数组的动态标题, t. 我们正在显示它(四舍五入到第二个小数位)并在每次迭代中更新它。注意,这些不是实时秒。
绘制我们的动画
最后一步实际上是使用 FuncAnimation 绘制我们的动画。我们首先用三维轴创建我们的图形对象。然后我们使用 FuncAnimation ,它将图形、我们之前创建的动画函数、一个间隔值和一个帧值作为输入。间隔是以毫秒为单位的帧之间的延迟,而帧仅仅是你希望显示的帧数。这最后两个是可选参数,但是如果我想调整动画的外观,我喜欢包含它们。
# Plotting the Animation
fig = plt.figure()
ax = plt.axes(projection='3d')
line_ani = animation.FuncAnimation(fig, animate_func, interval=100,
frames=numDataPoints)
plt.show()
您可以运行代码,如果操作正确,您的绘图应该如下所示(点的速度可能不同):
轨迹动画【作者创作】
保存我们的动画(可选)
如果你想把你的动画保存为。gif 文件,您可以使用下面的代码做到这一点。
# Saving the Animation
f = r"c://Users/(Insert User)/Desktop/animate_func.gif"
writergif = animation.PillowWriter(fps=numDataPoints/6)
line_ani.save(f, writer=writergif)
你需要选择一个位置来保存它,并将其存储为变量 f 。您可以在枕套中调整每秒帧数、 fps 、变量。我将 numDataPoints 变量(定义为 FuncAnimation 中的帧数)除以 6 ,使动画长度为 6 秒。
本文到此为止。感谢您的阅读!如果您不想错过更多的 Python 和工程文章,请关注我并订阅我的电子邮件。我已经写了一些其他的文章,所以也来看看吧!
如何用机器学习回答问题
原文:https://towardsdatascience.com/how-to-answer-questions-with-machine-learning-6c21357a44fc
看看班数据集,它的顶级 NLP 模型,以及它们是否过度拟合。
你曾经想要建立一个算法来做你的功课吗?虽然技术还没到位,但我们已经接近了。
图 1:在 SQuAD 2.0 数据集上具有最高精确匹配(EM)分数的模型— src 。图片作者。
2016 年,斯坦福大学的研究人员发布了一个问答数据集来训练 NLP 模型。从那时起,已经提交了数百个模型,每个模型都经过精心调整,与数据集相匹配。虽然它们拥有令人印象深刻的准确性,但我们预计在多次重用相同的数据集后会有一些过度拟合。
在这篇文章中,我们利用加州大学伯克利分校的一个团队的研究来确定这些模型是否 A)过度拟合数据集和 B)能够概括。我们将保持高水平。
事不宜迟,我们开始吧。
0 —技术 TLDR
问答(QA)模型是基于自然语言处理的模型,旨在基于文本段落回答问题。斯坦福问答数据集(SQuAD)于 2016 年推出,以方便 QA 模型的训练。该库还存储开源 NLP 模型提交,其中一些已经超过了人类基线。
与其他流行的数据集一样,我们预计会观察到自适应过度拟合,因此加州大学伯克利分校的研究人员开发了新的数据集来估计模型的可推广性和自适应过度拟合的影响。令人惊讶的是,模型没有很好地概括,但也没有表现出过度拟合。
1 —但是,实际上发生了什么呢?
好了,让我们稍微慢下来,理解一下 SQuAD 数据集,一些最好的 NLP 模型,以及用于估计自适应过拟合的方法。
1.1 —什么是班数据集?
斯坦福问答数据集 (SQuAD)的引入是希望进一步推进问答(QA)建模领域。这是一个阅读理解数据集,由段落、问题和答案组成。这些段落来自维基百科,问题/答案通过亚马逊的机械土耳其人众包。
注意有两个版本。班 1.1 版不包含无法回答的问题,但班 2.0 版包含。
1.2 —让我们看一个例子
在下面的图 2 中,我们可以看到一个小队的段落以及来自微软亚洲研究院的算法 r-net+ 的预测。
图 2:小队数据源和建模示例— src 。图片作者。
左边紫色的文字是关于我们主题的信息,在这个例子中是超级碗 50,它是从维基百科(合法地)获取的。右边是关于文本的问题,接下来是可接受的答案和一些模型的预测。
这些算法怎么可能胜过人类?嗯,让我想想…
2 —哪种类型的模型表现最好?
大部分功劳归于两个模型:BERT 和 XLNet。
2.1 —伯特
来自变压器的双向编码器表示(BERT) 于 2018 年推出,并在 NLP 世界掀起风暴。它普及了双向学习的概念,这是一个在我们感兴趣的事物的两边利用信息的概念。
在这个总体框架内,BERT 利用了两种培训策略。
在图 3 中,我们可以看到这些策略中的第一个,叫做屏蔽 LM (MLM) 。
图 3:第二个令牌被屏蔽的 BERT 示意图。图片作者。
在一句话中,MLM 屏蔽(删除)了训练数据中的一个已知标记,并试图使用丢失标记周围的上下文来预测其值。这种方法依赖于双向学习,可以产生很好的性能。
第二种被称为下一个序列预测(NSP) ,它只是试图确定两个句子是否顺序相关。训练数据在真实序列和随机序列之间平均分配,真实序列是观察到的一个接一个出现的两个句子,随机序列是两个可能不相关的句子。
有了这个基线结构,工程师可以添加额外的层,使模型适合他们的任务。一个例子是添加最终分类层来执行情感分析。
为了简洁起见,我们将继续,但是查看更多资源的评论。
2.2 — XLNet
2020 年 XLNet 发布,解决了 BERT 的一些缺点。根据该项目的首席研究员 Quoc Le 的一条推文,XLNet 在 20 多项任务中超过了 BERT。
让我们用一个简化的例子来看看 XLNet 是如何达到这种性能水平的。
import itertools
perms = itertools.permutations(['A','M','C'])print(list(perms))
# Output:
# [('A', 'M', 'C'), ('A', 'C', 'M'),
# ('M', 'A', 'C'), ('M', 'C', 'A'),
# ('C', 'A', 'M'), ('C', 'M', 'A')]
在上面的代码中,我们使用 python 的 itertools 库来显示 3 个令牌的所有排列。 A 和 C 代表单词, M 代表我们试图预测的未知令牌。
伯特的一个缺点是,它的双向训练缓慢而复杂。另一方面,XLNet 是一个严格的自回归模型,它利用排列来收集上下文信息。
图 XLNet 训练结构的例子。在这里,令牌可以根据排列顺序而变化。图片作者。
XLNet 在文本生成任务中经常优于 BERT 的一个主要原因是 BERT 假设屏蔽记号的独立性,以非屏蔽记号为条件。然而,英语可以表现出大量的顺序依赖性,所以这一假设通常是不成立的。XLNet 还实现了一些花哨的技术技巧,比如 Transformer-XL 的一个段递归机制和相对编码方案。但是(不幸的是)我们不会深入讨论这个问题。
3-当前模型是否过度拟合数据集?
现在我们已经了解了数据集和一些顶级建模技术,让我们继续这篇文章的最后一个主题。
3.1 —评估方法
这篇论文的作者试图确定这些模型是否表现出自适应过度拟合,这是一种当许多模型在同一数据集上拟合和调整时发生的现象。
为了做到这一点,我们在下面的等式中列出了潜在的偏差…
图 5:损失分解方程— src 。图片作者。
在图 5 中,我们已经定义了每个关键术语,但是让我们简要地讨论一下每个术语的含义…
- 适应性缺口(绿色):训练和样本外(OOS)测试小队数据损失的差异。使用正确的方法选择我们的测试集,这个值应该非常小。
- 分布差距(蓝色):小队与新 (New York Times,Reddit,Amazon)数据训练损失之差。当自然分布发生变化时,例如数据源,我们期望模型表现不同。这个值可能很大。
- 一般化差距(红色):训练和 OOS 测试损失小队数据之间的差异。与第一个项目符号一样,我们认为这个值很小。
所有这些加起来就是由于模型的概括能力造成的损失。
3.2 —结果
首先,在任何模型中几乎没有适应性过度拟合的证据。在 SQuAD 数据集上的 OOS 模型性能与在新数据集上测试的模型的 OOS 性能线性相关。从数学上来说,这意味着我们的适应性和泛化能力差距有相似的值。
这个结果相当令人惊讶,因为像 MNIST 和 ImageNet 这样的著名数据集都表现出自适应过拟合。随着越来越多的研究人员开发针对这些数据集优化的模型,这些模型往往会失去通用性。然而,我们没有看到同样的现象。
第二,在适应新数据集时,性能有了显著下降。换句话说,分配差距很大。更具体地说,NYT、亚马逊和 Reddit 数据集分别表现出 3.8、14.0 和 17.4 F1 点的平均性能下降。
虽然我们可能会直觉地认为这种性能下降是由于语法和句子结构的恶化,但作者研究了两组下降,无法找到结论性的解释。
4—总结和后续步骤
虽然缺乏结论性的解释可能不令人满意,但仍有一些采取下一步措施的机会。但是,在我们开始之前,让我们快速回顾一下…
问答模型基于文本来回答问题。SQuAD 是一个 QA 数据集,它促进了 QA 应用程序的 NLP 工作。顶级 QA 模型包括 BERT 和 XLNet,但是它们仍然不能很好地推广到其他数据集。最后,令人惊讶的是,在 SQuAD 数据集上几乎没有自适应过度拟合的证据。
既然我们对要点已经非常清楚了,那就让我们来看一些潜在的后续步骤…
- 构建可解释性能差异的数据集比较指标。使用一些标准诊断,作者无法确定为什么模型在 Reddit 和亚马逊文本上的表现相对于维基百科文本如此糟糕。
- 看看偏倚-方差权衡和训练数据大小之间的关系。对于高度特定的大型数据集,我们期望看到过度拟合,但数据大小和偏差之间的关系并不为人所知。
- 全面改进 QA 模式。尽管一些模型在特定领域非常有效,但要像人类一样进行概括,它们还有很长的路要走。
感谢阅读!我会再写 21 篇文章,把学术研究带到 DS 行业。查看我的评论,链接到这篇文章的主要来源和一些有用的资源。
如何应用人工蜂群算法解决非常规问题
图片由 Silv3rXArt 提供。经许可使用。
解谜取乐。学习一种新的算法。双赢。全部代码。
我在上一篇文章中提到的人工蜂群(ABC)算法相当灵活,但它是否足够灵活来解决一个非常规问题;一个逻辑难题?答案变成了“为什么不呢?”。因此,我们将详细讨论如何建模和求解。经历这个过程也许能帮助你发现其他问题,做出更明智的商业决策。
本文的非常规问题是受门萨日历启发的火柴棍拼图。目标是燃烧火柴棒,以在每一列和每一行中获得指定数量的燃烧段。
火柴杆拼图。图片由作者提供。
我们将使用 ABC 算法来解决这个问题。
在解决过程中探索解决方案。图片由作者提供。
为什么是火柴杆
在 AAXIS Digital ,我和我的同事们经常会遇到并解决需要打破常规思考的复杂业务问题。同时,我也是一个活跃的工程师和谜题爱好者社区的一员,这个社区叫做 Rowdy 谜语者。因此,对于商业和娱乐,你可以说逻辑问题是我的难题。
我在吵闹谜语小组遇到了这个谜题。如果你觉得应该手动解决;我同意。我们去了,很有趣。但是在我看来,通过计算来解决它是一个有趣且值得的练习。
一位智者曾经说过:“如果你只有一把锤子,那么一切看起来都像钉子。”虽然这句古老的格言中有智慧,但我认为 ABC 算法更像一把瑞士军刀,你可以用它来解决不同类型的问题。我们对其应用的不同例子看得越多,我们就越能更好地识别日常优化问题中的模式,这将使我们能够做出更明智的商业决策。
烧伤婴儿烧伤
现在,我希望你相信这是一个值得做的任务,让我们更详细地看看这个难题。概括地说,目标是“燃烧”火柴棒,以获得每一列和每一行中燃烧段的指定总数。让我们看一看。
火柴杆拼图。图片由作者提供。
一个典型的 NxN 网格包含几个不同大小的火柴棍,只能从头烧到尾(没有跳过的部分),可以是未燃、部分燃或完全燃。目的是燃烧火柴杆,以在每列和每行中获得指定数量的燃烧段。
例如,要获得第 6 行(顶行)的燃烧计数 3,我们可以燃烧 3 段棒 1(棒号在棒的头部)或两段棒 1 和棒 7 的所有段。但是,刻录 stick 7 的所有片段(以到达 stick 7 的最后一个片段)是不可能的,因为我们会违反 a 列的刻录计数。因此,刻录 stick 1 的 3 个片段是唯一的可能性。
不断重复这个逻辑过程,谜题就解决了!
让我们解决这个问题
现在我们已经讨论了如何手动解谜,让我们来看看解决技巧。
问题中的每一根火柴棍都像是栈。每一段都应该从上到下烧(后进先出)。以下是一个备选解决方案示例。
候选解决方案。图片由作者提供。
这个解可以表示为每根火柴杆从顶端燃烧的段数。火柴杆 1 有 3 段燃烧,火柴杆 2 有 2 段燃烧,等等。因此,数学表达式为:
[3,2,3,1,0,2,0,1,2,2,3]
给定这个解决方案和电路板,我们现在可以用数学方法计算出每行和每列中烧坏的部分。有了这个候选解决方案,我至少能想到四种技术来计算解决这个问题:
蛮力:有 11 根棍子,最多 5 段可以烧。你可以进行强力全空间扫描,依次烧掉所有 11 根棍子。但是,这有什么意思呢?不过说真的,随着空间随着更多的行和列而扩展,强力将花费太长的时间并且变得不切实际。
逻辑:人们可以像数独一样解决它。按顺序应用必要和充分条件。然而,大多数问题都需要回溯的实现;这是一种技术,您可以从停止的地方进行存储,这样,如果选择的路径没有产生解决方案,您可以继续。这需要复杂的代码、内存使用,并且看起来越来越像暴力。此外,很难将这种技术推广到其他问题。
蒙特卡洛模拟(Monte Carlo Simulation):这种技术在这个维基页面上有更详细的描述,它使用随机猜测来解决问题。一万只不停打字的猴子可能会偶然发现解决方案,方法是随机设置有多少段被烧掉,然后测试答案是否接近;冲洗并重复。也许这对某些问题有用,但是大多数问题既没有时间也没有猴子来得到满意的解决方案。此外,我不能把我的手指放在它上面,但是关于猴子和点燃的火柴的一些事情似乎是错误的!
进化算法:这些算法从随机的初始群体(候选解)中构建,这些群体会不断变异,每一代都会变得更好,朝着一个解努力。遗传算法、蜂群算法、蚁群算法、粒子群算法以及人工蜂群算法都属于这一类。 ABC 算法受蜂群觅食行为的启发,在多个点随机探索解空间,随着每一个连续的世代收敛到更好的解。这使得它成为这个问题和其他业务决策案例的理想选择,因为它们可能没有完美的解决方案,或者可能需要太长时间才能得到一个。
让那些蜜蜂工作
人工蜂群(ABC) 算法由 Karaboga 于 2005 年[1]推出,“是一种基于群体的元启发式算法,用于优化数值问题,其灵感来自蜜蜂的智能觅食行为”(Karaboga)。
我的上一篇文章 [2]在对各种标准测试函数和业务问题进行测试时,分解了 ABC 算法的细节、目的和应用。但是,这里有一个快速总结:
该模型由四个基本组件组成:
- 食物来源代表正在解决的问题的解决方案。
- 雇佣蜜蜂在食物源周围搜索,对其进行微调,并使其进化以产生更多的花蜜。
- 看客蜜蜂观察被雇佣的蜜蜂,探索最有希望的食物来源。这确保了越有希望的食物来源越能被开发。
- 侦察蜂随机选择新的食物来源,以确保我们不会陷入局部最小值。
蜜蜂活动解 Himmelblau 函数。图片由作者提供。
通过对蜜蜂活动的进一步研究,在解决 Himmelblau 函数的同时,我们可以更好地理解上述组成部分。在周期 1 中(左上角),蜜蜂随机分布,每个点代表(X,Y)平面中被开发的食物源。当被雇佣的蜜蜂评估花蜜时,它们开始倾向于函数的 4 个最小值。旁观的蜜蜂被分配到最有希望的食物来源。同时可以看到侦察蜂随机出现,以确保评估整个空间,并且我们不会错过局部最小值。到第 25 个周期,大多数蜜蜂都集中在 4 个解决方案上。
这个解决方案的代码库和我上一篇文章的代码库是一样的,可以在这里找到。
清楚明白的细节
概括地说,问题如下:
火柴杆拼图。图片由作者提供。
网格在配置文件 config matchplay-1 . ini(PHP ini 文件格式)中被捕获
stack[] = B6,C6,D6,E6,F6 ;1
stack[] = B5,B4,B3,B2 ;2
stack[] = F5,E5,D5,C5 ;3
stack[] = C4,C3 ;4
stack[] = D4,E4 ;5
stack[] = F4,F3,F2 ;6
stack[] = A3,A4,A5,A6 ;7
stack[] = E3,D3 ;8
stack[] = A2,A1 ;9
stack[] = C2,D2,E2 ;10
stack[] = F1,E1,D1,C1,B1 ;11rCounts = "3,4,2,3,4,3"
cCounts = "3,3,3,4,3,3"
“堆栈”数组从头到脚定义了每个棒的位置。例如,棍子 1 通过 F6 占领 B6。每行和每列的拼图的理想烧焦段数分别在计数和计数变量中给出。该配置文件在 MatchplayFoodSource 脚本中解析如下:
每一个 B6,C6 类型的符号都被转换成坐标([1,5],[2,5]等)并被存储。
剩下的部分是为给定的解决方案定义花蜜。然后,解决方案可以表示为下面的数组:
[3,2,3,1,0,2,0,1,2,2,3]
候选解决方案。图片由作者提供。
解决方案数组中的第一个数字是 3。这意味着棒 1(在最顶端)应该在它的 5 个片段中的 3 个中燃烧。斗杆 2(垂直)被烧成两段。诸如此类。
给定这个可能的解,我们可以将目标函数定义为候选解和理想解之间的均方根(RMS)误差。由于理想的解决方案是每一行和每一列中被烧毁的段的计数,我们可以通过编程来“计数”每一行和每一列中被烧毁的段,如图所示。
**╔════════╦═══╦═══╦═══╦═══╦═══╦═══╗**
║ **Row ║ 1 ║ 2 ║ 3 ║ 4 ║ 5 ║ 6** ║
**╠════════╬═══╬═══╬═══╬═══╬═══╬═══╣**
║ Ideal ║ 3 ║ 3 ║ 3 ║ 4 ║ 3 ║ 3 ║
╠════════╬═══╬═══╬═══╬═══╬═══╬═══╣
║ Actual ║ 4 ║ 3 ║ 2 ║ 3 ║ 4 ║ 3 ║
╠════════╬═══╬═══╬═══╬═══╬═══╬═══╣
║ Error ║-1 ║ 0 ║ 1 ║ 1 ║-1 ║ 0 ║
╚════════╩═══╩═══╩═══╩═══╩═══╩═══╝**╔════════╦═══╦═══╦═══╦═══╦═══╦═══╗**
║ **Column ║ 1 ║ 2 ║ 3 ║ 4 ║ 5 ║ 6** ║
**╠════════╬═══╬═══╬═══╬═══╬═══╬═══╣**
║ Ideal ║ 3 ║ 4 ║ 2 ║ 3 ║ 4 ║ 3 ║
╠════════╬═══╬═══╬═══╬═══╬═══╬═══╣
║ Actual ║ 2 ║ 3 ║ 3 ║ 4 ║ 3 ║ 4 ║
╠════════╬═══╬═══╬═══╬═══╬═══╬═══╣
║ Error ║ 1 ║ 1 ║-1 ║-1 ║ 1 ║-1 ║
╚════════╩═══╩═══╩═══╩═══╩═══╩═══╝
现在我们有了烧坏部分的行和列计数,我们可以计算均方根。
函数值= ∑(行数-最佳行数)+ ∑(列数-最佳列数)
Function Value = (1+0+1+1+1+0) + (1+1+1+1+1+1) = 10
对于上一节中提出的解决方案,函数值是 10。
在上面的第一个循环中,从 0 到$dimensions,我检查了烧毁的段,并根据行(索引 0)和列(索引 1)进行计数。在上面的第二个循环中,我计算了理想值(堆栈数)和实际值(fsCount)之间的均方根差。
nectar 值在 AbstractFoodSource 类中处理如下:
现在是蜂蜜
现在我们已经掌握了血淋淋的细节,让我们看看几个解决方案。使用 configMatchPlay-1.ini 运行 ABC 算法时,其输出如下:
ABC 算法在比赛中的输出。
可视化解决方案,我们得到:
困惑与解答。图片由作者提供。
快速检查显示,解决方案是正确的,因为我们只从头部开始燃烧,没有跳过部分。根据谜题的规则,一些木棒没有燃烧,一些部分燃烧,另一些完全燃烧。为了帮助验证图像中的解决方案,沿着行和列显示了分段计数,这些计数加起来就是所需的结果。ABC 算法探索的候选解决方案如下所示。
在此过程中探索解决方案。图片由作者提供。
完成这个谜题后,让我们尝试一个更复杂的,网格不是正方形的,而是 5x10 的。
谜题 2:一个长方形的谜题。图片由作者提供。
该算法正确地缩小到解决方案。
探索难题 2 的解决方案。图片由作者提供。
最终正确的解决方案是:
矩形难题的解答 2。图片由作者提供。
现在,让我们来看看这个难题有不止一个解的情况。
谜题 3。图片由作者提供。
不出所料,ABC 算法准确地识别出了这个难题的两个正确答案,并且两个答案都准确地遵守了所有规则,如下所示:
谜题 3 的解答。图片由作者提供。
我现在要稍微修改一下上面的谜题,让它不可解。
无法解决的难题 4。图片由作者提供。
在行 1 中,列 C 棒必须被烧断以在该行中得到烧断段计数 4。相同的逻辑显示第 3、5 和 6 行。这意味着 C 列应该至少有 4 个段被烧毁。我们故意把 3 放在 C 列,让它不可解。
ABC 算法在运行时会生成一个足够接近所呈现的难题的解决方案,将目标函数最小化为 2。他们有 6 个人。
无法解决的难题的多种解决方案。图片由作者提供。
X/Y 轴上的数字显示了燃烧的总段数。如果燃烧段的总数显示为红色,则表示与理想解有偏差,并显示在数字旁边。例如,理想的解决方案应该在第 1 行中有 4 个燃烧段。然而,上面的解决方案 1 示出了(3,1),其中 3 是烧毁的段,1 是第 1 行的错误。
以下是解决这个难题时探索出的解决方案。
探索谜题 4 的解决方案。图片由作者提供。
虽然这可能不是难题的解决方案,但如果这是现实世界的问题,计算出的解决方案仍可用于做出明智的业务决策。现实世界中的业务问题可能通常没有完美的解决方案,因为不可能对控制问题适合度的所有规则进行编码。拥有多个解决方案可以为企业主提供他们可以评估和采取行动的选项。
综上
在这篇文章中,我们看了为什么,什么,以及如何解决逻辑难题火柴杆烧伤。我们深入研究了实现细节和代码片段,以理解算法及其应用。我们强调了 ABC 算法如何被证明足够灵活地应用于这个难题,以及当不存在精确解时,它如何给出近似的“足够好”的解。
虽然通过计算来解决这个特殊的逻辑难题可能有些矫枉过正,但我相信从这个过程中学到的知识可以应用到你在工作或学习中将要面临和必须解决的问题上。一般来说,进化算法,特别是 ABC 算法,只是程序员解决逻辑难题和现实世界挑战的工具之一。作为解决方案架构师,我们处在一个独特的位置,能够识别并解决通常很困难的挑战。这样做不仅可以降低企业的成本,还可以释放资源来完成其他高价值的任务。
衣服也许不能造就人,但算法可以造就程序员。
在这里探索代码。
参考
[1]卡拉博加,德尔维斯。“人工蜂群算法。”http://www.scholarpedia.org/article/Artificial_bee_colony_algorithm2010 年第 5 期第 3 期:6915。
[2]拉姆,纳雷什。“实现人工蜂群算法解决商业问题”,《走向数据科学》,https://towardsdatascience.com,(2022 年 3 月)。
构建人工智能解决方案的框架
商业人工智能
构建人工智能解决方案的框架
在实践中构建有影响力的人工智能解决方案的方法。
罗伯特·蒂曼在 Unsplash 上的照片
人工智能在实践中
如果你遵循一个坚实的框架,在实践中构建机器学习或人工智能解决方案可能会很简单。我使用这个框架在各种行业用例中交付人工智能解决方案,包括:高风险客户识别、文档分类、客户细分和流失预测。
该框架跨越六个核心领域:业务捕捉、人工智能问题框架、数据策略、人工智能系统设计、可行性评估和绩效评估。
最好从业务捕获开始,然后在构建原型解决方案时完成其余部分。
定义:我在这里将原型定义为你构建的解决方案,它可以在小范围内运行以证明这个概念。
使用这种方法的优点:
- 对推动商业价值的前期关注。
- 通过价值与可行性评估,识别人工智能/人工智能解决方案投资机会的能力。
- 数据源和解决方案设计的审计跟踪。
- 将商业问题转化为 ML/AI 解决方案的框架。
- 一份参考设计文档,方便您和工程师扩展您的解决方案。
作者图片
业务捕获
在业务捕获阶段,您与您的业务 SME 或分析师一起设计您的业务问题。以下是这方面的一些指南:
- 业务领域&负责人:把这些记下来作为参考,你会想知道如果你的实验室成功了,谁有可能资助全面部署。
- 利益相关者及其角色:你要记下 SME 联系人是谁,他们的角色或头衔是什么,分析师是谁,数据科学家,发起人等等。
- 问题:写出需要解决的业务问题,你应该通过与你的业务 SME 交谈来了解这个问题。如果问题看起来太复杂,把它分解成更简单的子问题,分别解决。考虑回答以下问题:是什么推动了变革?谁拥有流程?成功的解决方案是什么样的?
- 业务收益:如果实施您的解决方案,您将评估业务收益。最初,这将是基于最佳可能结果的“信封背面”计算。原型构建完成后,您将对其进行优化。您将希望从数量和质量上表达这种商业利益。
AI 问题取景
一旦你抓住了你的业务问题,你可以尝试在一个高层次上用 AI&ML 的术语来框定它。
- 价值主张:尝试理解谁是最终用户,他们的目标是什么,以及他们将如何从机器学习或人工智能中受益。
- 决策:智能系统可以有效地做出决策。审视你的系统正在做出或补充的决策,规模和频率。在受监管的行业,如银行业,通常存在对“黑箱”模型的限制。因此,你也需要了解决策过程的可解释性。
- ML 服务:您的智能解决方案可能需要您利用云平台或 ML PaaS 提供的 ML 或 AI 服务的组合。这是一个很有用的练习,可以在一个较高的层次上对这些进行分析,并决定它们可能是什么。广义地说,ML 服务分为以下几类:语言、NLP 和文本提取、计算机视觉和语音识别。
- 机器学习:并不是所有的解决方案都需要你建立一个定制的机器学习模型。你应该评估你是否需要这样做。你应该注意到,构建你自己的定制 ML 解决方案通常比利用 ML 服务更复杂。
数据策略
数据是你的机器学习引擎的汽油,所以详细地捕捉你的数据需求是很重要的。最初考虑你对训练和推理的要求。如果你正在训练一个机器学习模型,什么特征可能是预测性的?如果只是做推断,需要哪些数据?例如,如果您正在构建一个 ID 验证引擎,您可能需要一些照片 ID,您需要知道如何捕获这些数据。
数据管理和采购
在这里,您也应该考虑您的数据管理和采购方法。
您使用结构化/半结构化数据、非结构化数据,还是两者都使用?
处理结构化和半结构化数据与非结构化数据有不同的要求。您存储数据的方式、处理成本、可用容量是需要考虑的一些因素。
在 GDPR 体系下,工业界对数据及其使用有严格的规定。你会想要有一个遵守这些的策略。了解个人数据是否被使用、数据来源、数据的主要联系人以及您计划存储数据的时间,将有助于您通过不可避免的数据审核。
最后,您将希望获得您的采购成本,数据不是免费的,如果需要昂贵的数据,您的价值主张可能会大打折扣。
数据标记
在一个行业环境中,你可能想要采取一种受监督的机器学习方法,但你可能没有带标签的数据。您需要在这里指定您的数据标记策略。你是在使用像 AWS 的 Mechanical Turk 这样的服务,还是会使用无监督学习来创建你的标签?
偏差缓解
您需要了解数据集中的偏差,并制定管理它们的策略。偏见的例子有:
- 赞助偏见 *:你的数据来源是来自赞助代理吗?赞助机构倾向于隐瞒可能损害声誉的数据。例如,一家烟草公司收集的关于烟草对健康影响的数据。
- 自我选择偏差 :一种选择偏差,你的数据来源于那些自愿提供数据的人。这是大多数调查数据*。
*资料来源:机器学习工程,安德烈·布尔科夫(2020),第。44–47
人工智能系统设计
查看您的智能应用程序的细节。你应该使用商业捕捉和人工智能问题框架练习来帮助你了解这里。需要考虑的事项有:
- 方法:以书面形式描述你打算采取什么方法来解决你的问题。你应该很清楚自己需要什么样的机器学习服务,是否需要训练一个模型。
- 性能要求:你期望的最低性能标准是什么?您应该从您在测试数据上构建或使用的任何模型的延迟需求和性能的角度来考虑这一点。您的绩效目标应该符合您的业务需求。
- 输出:你的输出是什么?您的智能系统会为另一个应用程序提供推理服务,还是会用于生成洞察仪表板?这将对您以后选择的设计模式产生影响。
- 研究:你需要了解已经存在的可能解决你的问题的应用的前景。寻求“开箱即用”的解决方案通常比试图重新发明轮子更有效。另一件要考虑的事情是你试图解决的问题是否是一个典型的 ML 用例。关于 ML 项目的成功有很多不确定性,这有助于了解这个问题在过去是否已经解决,从而给你一个成功机会的概念。
- 高级解决方案设计:规划您的端到端解决方案设计。如果您的解决方案是云原生的,请保持在服务级别,不要进入 ML 管道的细节(如果您正在训练模型)。这些图表对工程师很有用,他们可能会在某些时候帮助您进行生产规模调整。
- 机器学习策略:如果你正在训练你自己的模型,列出你将尝试的模型和基线模型。这里值得一提的是每个模型的局限性。你还应该在这里画出一个更详细的机器学习管道,包括数据分离、数据争论、特征工程、模型训练&评估循环等步骤。一旦你训练的任何 ML 模型投入使用,你可能需要粗略地定义你的监控策略。考虑您希望监控的属性,如何设置基准性能和监控计划。作为标准,您可能希望监控数据质量、模型质量/性能、模型偏差漂移和特征属性。
- 模型训练&评估:你对训练、验证和测试数据集的划分是怎样的?你将使用什么策略来调整你的超参数和测试你的模型?
- 平台、工具和基础设施:想想你需要的服务以及它们会花你多少钱。如果你使用像 AWS 这样的云平台,有无数的机器学习服务可以利用,你可以使用 AWS 计算器工具来估计成本。其他云平台也有类似的选择,包括 Azure 和 GCP。
性能赋值
无论你是在培训你自己的定制模型,还是在利用现有的 ML 服务,你都应该根据你规定的要求来跟踪他们的表现。
对于定制的机器学习解决方案,您应该有一个科学严谨的策略来评估模型性能,以防止过度拟合,并最大化您的模型在生产中正常工作的机会。
ML 培训和评估流程(图片由作者提供)
可行性的估计
您应该记住,您的最终目标是构建一个可以在生产中工作并为您的业务增加价值的模型。一旦您确定了所有的需求并构建了原型,您将对您的解决方案的可伸缩性有更好的理解。这里要考虑的事情有:
- 数据基础设施:数据访问、数量和质量。
- ML/解决方案:可用技术资源、现有解决方案、解决方案知识。
- 流程&系统:实现您的解决方案需要任何业务流程变更、系统调整或组织变更吗?
- 诀窍:技术和领域知识对你有用吗?提高团队技能以满足需求需要多长时间?
- 解活:你的解活要多久?
应用人工智能倡议组织 发布了一份白皮书,为你提供了一种评估你的智能解决方案可行性的方法。
价值与可行性
您应该能够评估您的解决方案的价值和可行性。你想去寻找具有高价值和高可行性的解决方案,很少有你设计的解决方案一开始就符合这一类别。你应该重新审视最初的设计,看看你是否能找到一种可行性更高的方法。如果您所在的组织处于智能应用采用曲线的早期,您可以考察其中的几个解决方案,看看哪里有投资机会。
注意:在业务捕获阶段,您已经估计了您的解决方案的价值。
可行性分数和值只是为了说明概念,不应当真(图片由作者提供)
- 左上:目前很难做但商业价值很高的理想项目。
- 左下:垃圾,商业价值相对较低,可行性低。
- 右下:低垂的果实,商业价值低但可行性高。
- 右上:火箭,商业价值高,可行性高。
最后的想法
应用人工智能解决商业问题很难。因为所有的活动部件,尽可能标准化你的方法以使过程更有效是绝对值得的。在这里,你可以随意使用对你有用的东西,并在你需要的地方进行调整。
⭐️ 我喜欢通过分享我在野外的数据科学经验来帮助人们。如果你还不是会员,可以考虑订阅 Medium,从我这里获得更多有用的内容。
https://johnadeojo.medium.com/membership
如何深入理解集成机器学习方法中的软投票和硬投票
如何通过从头开始构建执行投票的算法来完全理解软投票和硬投票的工作原理
由 Unsplash 上的 Element5 数码拍摄
背景
不久前,我在阅读一本名为《接近(几乎)任何机器学习问题》的书,作者是 Abhishek Thakur(参见https://www . Amazon . co . uk/approximate-Almost-Machine-Learning-Problem-ebook/DP/b 089 p 13 qht),当时我看到了一些在集成学习中实现软投票和硬投票的代码。
我有三个问题-
- 我不完全理解代码。
- 它只适用于二进制类(恰好有两个类的分类问题)。
- 我不明白为什么没有人使用 sckikit-learn 实现。
事实证明,第三点的答案是,你可以学到很多关于这些算法在做什么,从而通过从头开始构建它们来获得更全面的理解,因此我开始自己构建它们,并有一些次要目标-
- 抓住机会尽可能多地学习 numpy 数组、数组切片和矢量化运算。
- 挑战自己不断重构代码,直到我优化了算法,遵循“Pyhtonic 方式”,尽可能减少代码行。
本文的其余部分对我的发现提供了完整的解释。
快速回顾集合方法中的软投票和硬投票
集成方法将两个或多个独立的机器学习算法的结果集合在一起,试图产生比任何单个算法都更准确的集体结果。
在软投票中,每个类别的概率被平均以产生结果。例如,如果算法一以 40%的概率预测到一个物体是岩石,而算法二以 80%的概率预测到它是一个地雷,那么该集合将以(80 + 40) / 2 = 60%的概率预测到该物体是一个地雷。
在硬投票中,考虑每个算法的预测,集合选择具有最高票数的类别。例如,如果三种算法预测特定葡萄酒的颜色为“白色”、“白色”和“红色”,则整体将预测“红色”。
入门指南
我们将需要导入几个库,设置一些常量,并在输出中设置科学符号为“off ”,以提高结果的可读性..
我们还需要一些数据作为分类的输入。make_classification_dataframe
助手函数将数据创建为结构良好的DataFrame
,带有特性名称和命名目标。
注意,类的数量被设置为 3。这一点很重要,因为我们将为非二进制分类(即超过 2 个类别)求解软投票和硬投票算法。
为非二进制情况精心设计的解决方案适用于二进制,但我见过的其他代码示例只适用于二进制。
例如,在岩石和矿井的例子中,如果对象可以是“岩石”、“矿井”或“炸弹”,则有 3 个类需要可以处理非二进制情况的算法(只有“岩石”和“矿井”)。
作者图片
交叉折叠验证
交叉折叠验证被选为评估算法性能的方法,而不是更简单的train_test_split
,因为它通常提供更准确的算法性能指标。
scikit-learn
中实现的一个问题是,没有办法访问我们从头开始构建软投票和硬投票所需的潜在概率和折叠预测。
cross_val_predict
助手函数提供了实现这一点的代码,完整的解释可以在我关于如何为交叉折叠验证绘制混淆矩阵的文章中找到
请注意,我为本文添加了predicted_proba
,并引入了对try, except
块的需求,因为并非所有算法都支持概率,并且没有一致的警告或错误来显式捕获。
在我们开始之前,让我们快速看一下一个算法的cross_val_predict
..
Wall time: 309 ms
Accuracy of Logistic Regression: 0.6821array([0, 0, 1, ..., 0, 2, 1])
一切都相当简单明了。cross_val_predict
已返回概率和预测类,预测类已显示在单元格输出中。
第一组数据被预测为属于类 0、第二类 0、第三类 1 等。
为多个分类器进行预测
我们需要做的下一件事是为几个分类器生成一组预测和概率,这样投票就有了聚合的对象。选择的算法是一个随机森林,一个 XG boost 和一个额外的随机森林,使用下面的代码实现…
Wall time: 17.1 s
Accuracy of Random Forest: 0.8742
Wall time: 24.6 s
Accuracy of XG Boost: 0.8838
Wall time: 6.2 s
Accuracy of Extra Random Trees: 0.8754
predictions
是一个简单的列表,包含每个算法的一个预测类数组...
[array([2, 0, 0, ..., 0, 2, 1]),
array([2, 0, 2, ..., 0, 2, 1], dtype=int64),
array([2, 0, 0, ..., 0, 2, 1])]
predicted_probas
有点复杂。这是一个简单的列表,包含每个预测算法的数组。每个数组都有形状(10000,3)。对此解释如下-
- 10,000 是样本数据集中的数据点数。每个数组针对每组数据都有一行
- 3 是我们的非二元分类器中的类的数量
输出中的第一行可以解释如下-
对于第一种算法,第一组数据(即DataFrame
中的第一行)有 17%的概率属于类别 0,2%的概率属于类别 1,81%的概率属于类别 2。
我记得我第一次看到来自predcited_proba
方法的输出时,我感到非常困惑,所以希望这个解释能拯救我第一次感觉到的困惑!
[array([[0.17, 0.02, 0.81],
[0.58, 0.07, 0.35],
[0.54, 0.1 , 0.36],
...,
[0.46, 0.08, 0.46],
[0.15, 0\. , 0.85],
[0.01, 0.97, 0.02]]),
array([[0.05611309, 0.00085733, 0.94302952],
[0.95303732, 0.00187497, 0.04508775],
[0.4653917 , 0.01353438, 0.52107394],
...,
[0.75208634, 0.0398241 , 0.20808953],
[0.02066649, 0.00156501, 0.97776848],
[0.00079027, 0.99868006, 0.00052966]]),
array([[0.33, 0.02, 0.65],
[0.54, 0.14, 0.32],
[0.51, 0.17, 0.32],
...,
[0.52, 0.06, 0.42],
[0.1 , 0.03, 0.87],
[0.05, 0.93, 0.02]])]
从头开始实现软投票和硬投票
这里我们已经到了文章的主要部分。软投票和硬投票只需几行 Python 代码就可以实现,如下所示。
然而,这并不是我的第一次尝试。我的第一次尝试没有那么“Pythonic 化”,包含了更多的代码,但实际上它的可读性更好。
如果你想看我的第一次尝试,看看这个— …
如果你完全理解下面的代码,你可以跳过下一节,但我认为它非常复杂,很难阅读和理解,所以我在下面提供了完整的解释。
在我们继续之前,有必要指出,软投票的表现比表现最好的单个算法高出 0.3% (88.68%对 88.38%)。
Accuracy of Random Forrest: 0.8742
Accuracy of XG Boost: 0.8838
Accuracy of Extra Random Trees: 0.8754
Accuracy of Soft Voting: 0.8868
Accuracy of Hard Voting: 0.881
投票算法的解释
软投票的代码
array([[0.18537103, 0.01361911, 0.80100984],
[0.69101244, 0.07062499, 0.23836258],
[0.50513057, 0.09451146, 0.40035798],
...,
[0.57736211, 0.05994137, 0.36269651],
[0.09022216, 0.01052167, 0.89925616],
[0.02026342, 0.96622669, 0.01350989]])
numpy mean
函数沿 0 轴(列)取平均值。理论上,这应该是软投票的全部内容,因为这已经创建了 3 组输出的平均值,并且看起来是正确的。
但是,舍入误差行的值并不总是等于 1,这很麻烦,因为每个数据点都属于概率为 1 的三个类别之一…
0.9999999826153119array([0.18537103, 0.01361911, 0.80100984])
这是非常不幸的,但很容易补救。因为我们希望所有 3 个类的概率对于每个数据点加 1,所以我们需要做的就是将最后一列中的值设置为 1-其他列中值的总和…
1.0array([0.18537103, 0.01361911, 0.80100986])
现在一切看起来都很好,每一行的概率加起来是 1,就像它们应该的那样。
然而,我们仍然需要知道类别预测(即,对于每一行,软投票预测了类别 0、1 或 2)。幸运的是,numpy
库中精彩的argmax
函数能够在一行代码中实现这一点...
array([2, 0, 0, ..., 0, 2, 1], dtype=int64)
argmax
函数只是沿着axis
参数中指定的轴选取数组中最大值的索引,因此它为第一行选取 2,为第二行选取 0,为第三行选取 0,依此类推。
硬投票的代码
使用 Python 列表理解和numpy
数组函数,可以在一行代码中实现硬投票算法...
np.array(predictions).T
语法只是转置了数组的数组,因此它不是 3 行和 10,000 列,而是 10,000 行和 3 列...
(3, 10000)array([[2, 2, 2],
[0, 0, 0],
[0, 2, 0],
...,
[0, 0, 0],
[2, 2, 2],
[1, 1, 1]], dtype=int64)
然后 list comprehension 有效地获取每个元素(行)并对其应用statistics.mode
,从而选择从算法中获得最多投票的分类...
array([2, 0, 0, ..., 0, 2, 1], dtype=int64)
使用 Scikit-Learn
手工制作的软投票和硬投票算法确保了我们对正在发生的事情有一个全面的了解,所以是时候走捷径,使用scikit-learn VotingClassifier
为我们做所有的工作了...
Wall time: 1min 4s
Wall time: 55.3 s
Accuracy of SciKit-Learn Soft Voting: 0.8868
Accuracy of SciKit-Learn Hard Voting: 0.881
令人欣慰的是,scikit-learn
实现产生了与 scratch 构建算法完全相同的结果——软投票的准确率为 88.68%,硬投票的准确率为 88.1%。
好吧,让我们把厨房的水槽扔过去!
那么,通过在投票中包含广泛的分类算法,我们究竟可以在准确度测量方面实现多大的改进呢?
在这里,我们将把投票中使用的算法数量扩展到 6 个,看看我们能从整体中挤出多少性能…
方法 1:使用临时构建的投票
Wall time: 14.9 s
Accuracy of Random Forest: 0.8742
Wall time: 32.8 s
Accuracy of XG Boost: 0.8838
Wall time: 5.78 s
Accuracy of Extra Random Trees: 0.8754
Wall time: 3min 2s
Accuracy of Neural Network: 0.8612
Wall time: 36.2 s
Accuracy of Support Vector Machine: 0.8674
Wall time: 1.65 s
Accuracy of Light GMB: 0.8828
Accuracy of Soft Voting: 0.8914
Accuracy of Hard Voting: 0.8851
Wall time: 4min 34s
方法 2:使用 SciKit-Learn 和 cross_val_predict
Wall time: 4min 11s
Wall time: 4min 41s
Accuracy of SciKit-Learn Soft Voting: 0.8914
Accuracy of SciKit-Learn Hard Voting: 0.8859
Wall time: 8min 52s
方法 3:使用 SciKit-Learn 和 cross_val_score
Accuracy of SciKit-Learn Soft Voting using cross_val_score: 0.8914
Wall time: 4min 46s
结论
3 种不同的方法对软投票准确性的评分一致,这验证了研究并表明临时构建投票算法工作正常。
向混合中添加神经网络、支持向量机和光 GMB,使得软投票的准确度从 88.68%提高了 0.46%,达到 89.14%,并且新的软投票准确度比最佳个体算法(XG Boost 为 88.38%)好 0.76%。还需要注意的是,加入比 XG Boost 精度分数低的光照 GMB 将整体性能提高了 0.1%!
这些都是边际收益,所以选择使用软投票最终是增加复杂性与实现改进的影响和含义之间的平衡。
如果这是一场 Kaggle 竞争,那么 0.76%可能会很大,可能会让你在排行榜上一飞冲天。如果你对矿石进行分类,你会想要额外的准确性,而如果你对红葡萄酒和白葡萄酒进行分类,你可能会喜欢简单的分类。
总之,通过这项研究并从头开始构建软投票和硬投票算法,对理解它们有了很大的改善,这将帮助数据科学家在构建现实世界的预测机器学习算法时做出正确的选择。
最后一点:Scikit 的局限性——学习硬投票
在这篇文章的研究中,我遇到了一个完全的障碍,出现了一个我无法理解的错误消息,结果发现这是因为在某个地方的库中有一个 bug,这意味着下面的组合不起作用
- 数据集中的目标是非二进制的(即分类有两个以上的类)。
scikit-learn
通过设置voting="hard"
被用于硬表决。- 估计器包括一个
catboost.CatBoostClassifier
(其他一些分类器产生相同的结果)。
您可以使用下面的代码尝试这种组合,您将获得一个ValueError: could not broadcast input array from shape (2000,1) into shape (2000)
。注意:我特意使用了cross_val_score
来保证这个 bug 不是由cross_val_predict
帮助函数中的任何东西引起的。
然而,本文中开发的从头实现硬投票的代码确实支持这种组合,所以如果您需要在非二进制分类的硬投票中包含一个CatBoost
,本文提供了唯一的方法,直到错误被修复。
**ValueError**: could not broadcast input array from shape (2000,1) into shape (2000)
感谢您的阅读!
如果你喜欢读这篇文章,为什么不看看我在 https://grahamharrison-86487.medium.com/的其他文章呢?此外,我很乐意听到您对这篇文章、我的任何其他文章或任何与数据科学和数据分析相关的内容的看法。
如果你想联系我讨论这些话题,请在 LinkedIn 上找我—https://www.linkedin.com/in/grahamharrison1或者发邮件给我ghar rison @ Lincoln college . AC . uk。
如果你想通过订阅来支持作者和全世界 1000 个为文章写作做出贡献的人,请使用下面的链接(注意:如果你使用这个链接免费注册,作者将收到一定比例的费用)。
https://grahamharrison-86487.medium.com/membership
如何自动化和简化您的机器学习实验工作流程
ArgParse 是一个有用的模块,我用它来执行多个 ML 实验,并在 web 应用程序中清晰地报告观察结果
无论是为了确定最佳模型,还是为了了解模型对数据或超参数的不同变化的细微差别,您都需要进行大量的机器学习实验。结果可能是有趣的,使模型选择的过程。
作为我工作的一部分,我通常不得不执行一些 ML 实验,这些实验可以是——(比如)测试降维技术、文本预处理技术(在 NLP 模型的情况下)的有效性,或者像处理测试集大小这样的简单事情。无论哪种方式,您都可能不得不多次运行一个代码,并记录所有观察结果以便以后进行比较。这与超参数调整过程略有不同,我们的目的是确定最适合我们问题的技术。
因此,在过去的几年中,我从机器学习社区中获得了一些东西,并将其转化为一个整洁的工作流程。
问题
先建一个小问题。我们可以尝试使用 Sklearn 的 make_classification 方法,通过人工生成高维数据集来解决二元分类任务的情况。
我生成了一个包含 1000 个实例和 30 个特征(15 个信息性特征和 15 个冗余特征)的数据集,并测试了以下内容:
- 两种降维技术——主成分分析(PCA)和局部线性嵌入(LLE)
- 两种类型的期望输出维度(来自降维技术)— 5 维和 10 维(因为我们有 30 维数据)。
- 三种机器学习分类器—逻辑回归、SVC 和随机森林分类器。
这样,我们有 12 个不同的实验(2 x 2 x 3)来得到所有不同组合的结果。手动运行所有的实验会令人疲惫不堪,所以我使用了一些 python 库和工具来简化它。
如您所见,运行 12 个不同实验的目的是为了选择更好地解决问题的适当技术。在训练 ML 分类器时,我们还需要包括超参数调整(为了解释简单,我将跳过这一步)。
该过程
首先,我将制作一个代码框架,包含所有必要的预处理步骤、模型训练和模型评估。
第二步是将以下集成/更改添加到代码框架中:
- 将代码保存在
.py
文件中(以防 Jupyter 笔记本用于训练模型)。 - 使用 Argparse 模块包装代码,该模块帮助我们在命令行中使用用户定义的参数运行代码。
- 在一个
.sh
文件中用所有用户定义的参数编写一个循环。这个 shell 脚本将用于多次运行.py
文件,每次我们都使用for loop
来更改参数。 - 将结果和工件(如果有的话)发布到 web 应用程序。
代码
我列出了循环实验的所有步骤,现在让我们来看看我准备的代码框架。在arguments
块上做一个记录。这些是用户定义的参数,或者是我们在实验过程中感兴趣的参数。
上面显示的是一个简单的降维和二进制分类代码。准确度分数被用作定义分类模型性能的度量。
代码的顶部提到了用户定义的参数。我们希望将 argparse 包装器集成到这些参数中。过程相当简单。
我们添加了parse_args()
函数来包含所有用户定义的参数。整个代码封装在另一个名为main(args)
的函数中,该函数接受参数。如您所见,argparse 的集成很容易。
Shell 脚本
现在,我们已经准备好了带有代码的argparse_automate.py
文件和所有用户定义参数的 argparse 包装器。下一步是创建如下所示的 shell 脚本:
loop.sh
将 python 文件与所有参数循环在一起。我们只需要使用命令行来运行 shell 脚本,所有 12 个实验将一个接一个地运行。echo
选项将打印用于特定运行的特定参数(如果需要,您可以删除它)。
注意:即使其中一个实验出现错误,循环仍会继续运行。
工件和 Web 应用程序
在这个例子中,我没有保存任何 ML 工件,比如可视化、模型保存文件或者结果。将对应于每组参数的工件保存起来,并将它们排序到它们自己的特定文件夹中,这将非常方便。
在 Python 中创建嵌套文件夹的一种简单方法是使用路径库:
path = f'output/{dim_red_type}/{n_comp}/{classifier}/'Path(path).mkdir(parents=True, exist_ok=True)
每个实验都有一个文件夹,所有的结果都可以方便地访问。
更进一步,所有这些结果和工件都可以在一个 Streamlit web 应用程序中显示。它看起来会像这样:
Streamlit Web 应用程序(图片由作者提供)
在上面 Streamlit web 应用程序的屏幕截图中,我包含了一个带有单选按钮(在左边)的过滤器选项,可以用来切换所需的参数。通过这种方式,不同实验和人工制品的结果可以在一个地方查看,不会太混乱。这对于以清晰的方式向不精通机器学习的客户展示结果非常有帮助。
与本文相关的代码可以在这个 GitHub repo 中找到。您可以根据您的项目进行修改。
可能存在比我在本文中使用的方法更好的方法。如果你知道有什么技术可以改进我建议的工作流程,请随时告诉我!
感谢阅读,干杯!
**Want to Connect?**Reach me at [LinkedIn](https://www.linkedin.com/in/rohithteja/), [Twitter](https://twitter.com/rohithtejam), [GitHub](https://github.com/rohithteja) or just [Buy Me A Coffee](https://www.buymeacoffee.com/rohithteja)!
如何在 LinkedIn 上自动创建帖子
原文:https://towardsdatascience.com/how-to-automate-creating-posts-on-linkedin-f87a5484be00
LinkedIn API 上的 Python 和 Postman 教程
LinkedIn API 不是一个容易使用的 API。我花了几乎一整天的时间试图弄清楚如何设置访问令牌来在 LinkedIn 上创建文章。
但是…
我最后得出的结论是 LinkedIn API 写不了文章。而是分享一篇文章。它可以在经过身份验证的用户的个人资料上发布文本。
白白在这上面花费那么多时间真令人沮丧。但并不是因为这篇博文就没用了。
在这篇文章中,我将告诉你如何比我花更少的时间。您将能够设置访问令牌,以便您可以在下一个使用 LinkedIn API 的项目中使用它。
本教程重点介绍在 LinkedIn 个人资料上发布文本、媒体和/或 URL 链接所需的设置。
让我们做吧,这样你就能做了。
先决条件
创建一个新的 LinkedIn 应用程序或从 LinkedIn 开发者门户选择一个现有应用程序。
注意,您需要为您的应用程序创建一个新的 LinkedIn 页面(如果您还没有的话)。
默认情况下,应用程序将被授予三脚 OAuth 权限。
配置应用程序
从门户中选择您的应用程序。然后,单击“Auth”选项卡查看您的申请凭证。
您将看到客户端 id 和客户端密码。您将需要它们作为环境变量,所以将它们复制并粘贴到 shell 文件中,如下所示:
**export** LINKEDIN_CLIENT_ID=<**your** client id>
**export** LINKEDIN_CLIENT_SECRET=<**your** client secret>
如果您使用的是 Linux,打开这个~/.bashrc
文件并添加上面的行。类似地,对于 Mac,如果默认 shell 是 bash,将这两行添加到~/.bash_profile
。如果 zsh,把他们加到~/.zshrc
。
确保运行source ~/.bashrc
、source ~/.bash_profile
或source ~/.zshrc
(取决于您的 shell 和机器)来使环境变量对您的 shell 可用。
最后,添加重定向链接。示例:[https://dev.example.com/auth/linkedin/callback](https://dev.example.com/auth/linkedin/callback)
我把它作为脑波媒介网址。所以做你想重定向到的任何页面。确保它是一个绝对的 URL(带有协议),就像例子一样。
请求授权码
在 LinkedIn 开发人员门户中,选择您的应用程序后,转到“产品”选项卡。
选择我们需要在本教程中访问的两个产品:
- 在 LinkedIn 产品上分享
- 使用 LinkedIn 产品登录
在 LinkedIn 上分享并使用 LinkedIn 产品登录。(作者截图)
让我们来看看下面的代码片段,以获得授权代码:
import requests
import os
import webbrowser**def** authorize():
"""Authorizes the user and opens a browser window to get the code."""url = "https://www.linkedin.com/oauth/v2/authorization"
payload = {
"response_type": "code",
"client_id": os.getenv("LINKEDIN_CLIENT_ID"),
"redirect_uri": "<your redirect link>",
"state": "SADvGFt74M36bgwLoe753",
'scope': 'r_liteprofile r_emailaddress w_member_social',
}
response = requests.Request("GET", url, params=payload)
url = response.prepare().url
webbrowser.**open**(url)**if** __name__ == "__main__":
authorize()
如您所见,这里的url
是要获得授权的端点,而payload
是要发送给服务器的参数。
然后,你会得到一个通过webbrowser.open()
功能在你的浏览器中打开的 URL,你将允许应用程序被授权。
授权应用程序“测试”。(作者截图)
最后看网址。您会发现链接了授权码的重定向 URL。
让我们了解一下有效载荷由哪些部分组成:
response_type
是我们希望从服务器得到的响应类型。在这种情况下,我们希望获得一个授权码。所以,我们将它设置为code
。client_id
是您在创建应用程序时生成的客户机 id。尽管您已经将它粘贴到了环境变量中。redirect_uri
是您在上一节中设置的 URL。state
参数用于防止 CSRF 攻击,可选但推荐使用。scope
是你需要访问的权限。
本教程选择的 OAuth 2.0 范围。(作者截图)
例如,如果重定向 uri 是https://medium.com/the-brainwave
而state
是SADvGFt74M36bgwLoe753
,那么浏览器上的 URL 将是这样的:https://medium.com/the-brainwave?code=<YOUR_AUTHORIZATION_CODE>&state=SADvGFt74M36bgwLoe753
其中<YOUR_AUTHORIZATION_CODE>
是一个很长的字符串,您需要复制并粘贴到下一步的code
参数中以获得访问令牌。
获取访问令牌
在下面的函数中,您将通过向 access token 端点发送 post 请求来获取访问令牌:
**def** get_access_token(code):
"""Returns an access token."""url = "https://www.linkedin.com/oauth/v2/accessToken"
payload = {
"grant_type": "authorization_code",
"code": code,
"redirect_uri": "<your redirect link>",
"client_id": os.getenv("LINKEDIN_CLIENT_ID"),
"client_secret": os.getenv("LINKEDIN_CLIENT_SECRET"),
}
response = requests.post(url, params=payload)
**return** response.json()["access_token"]**if** __name__ == "__main__":
# authorize()
code = "<YOUR_AUTHORIZATION_CODE>"
**print**(get_access_token(code))
其中grant_type
的值为authorization_code
,code
是您从上一步中获得的授权码。我们讨论了除了client_secret
之外的其余参数,T3 是您粘贴到环境变量中的凭证。
现在,您可以使用访问令牌向 LinkedIn API 发出请求。
使用 Postman 测试您的应用程序
现在使用访问令牌测试您的应用程序。邮递员是一个很好的工具。
打开 Postman,进入授权选项卡,选择授权类型为OAuth2.0
。然后,选择Access Token
选项并粘贴您在上一步中获得的访问令牌。
要在 LinkedIn 上发帖,你需要有一个授权用户的 ID。您可以通过向me
端点发送请求来获取 ID:
GET [https://api.linkedin.com/v2/me](https://api.linkedin.com/v2/me)
简单到对这个https://api.linkedin.com/v2/me
端点的 GET 请求。
在响应的最后,您将看到用户的 ID。复制并粘贴它,因为您将在下一步中需要它。
创建帖子
现在,您可以通过向用户生成内容(UGC) API 端点发送 post 请求来创建 POST。所以:
POST [https://api.linkedin.com/v2/ugcPosts](https://api.linkedin.com/v2/ugcPosts)
最后,转到 Postman 上的body
选项卡,用以下参数填充请求体:
{
"author": "urn:li:person:<YOUR ID FROM THE PREVIOUS STEP>",
"lifecycleState": "PUBLISHED",
"specificContent": {
"com.linkedin.ugc.ShareContent": {
"shareCommentary": {
"text": "A text from LinkedIn API."
},
"shareMediaCategory": "ARTICLE",
"media": [
{
"status": "READY",
"description": {
"text": "The description field coming from LinkedIn API."
},
"originalUrl": "https://blog.linkedin.com/",
"title": {
"text": "Testing LinkedIn API"
}
}
]
}
},
"visibility": {
"com.linkedin.ugc.MemberNetworkVisibility": "PUBLIC"
}
}
并用上一步中的 ID 替换<YOUR ID FROM THE PREVIOUS STEP>
。
这应该会创建一个包含以下文本的帖子:“来自 LinkedIn API 的文本。”分享本文链接:https://blog.linkedin.com/
最后的想法
我们已经讨论了如何认证和授权您的 LinkedIn 帐户。这允许您访问 API 的一些功能,如创建帖子和共享媒体内容。
除非您想更改权限,否则您只需被授权一次。所以不用担心!您将能够使用该 API 而无需任何进一步授权来创建和自动化您的 LinkedIn 帖子。
现在就获得免费的 Python 电子书,学习为你的下一个项目编写高效 Python 代码的 5 种方法。
信用
https://ezzeddinabdullah.medium.com/membership
如何用 Python 自动化猴子的工作
原文:https://towardsdatascience.com/how-to-automate-monkey-jobs-with-python-1910a3219fd2
基于 Windows GUI 的双因素身份认证流程示例
没有人喜欢所谓的“ ”猴子工作 ”,不需要任何创造力的重复性工作。但是我们总是(几乎)有一个选择,我们可以自动完成这些类型的任务,把我们的时间投入到更有成就感的事情上。
在这篇文章中,我们将看到如何通过将 GUI(图形用户界面)应用于一个特定的用例来自动化需要与 GUI(图形用户界面)交互的过程。
用例
数据提取过程需要自动化。只有当请求是从某个 VPN(虚拟专用网)执行时,执行数据提取的 API 才可用。为了能够连接到 VPN:
- 我们必须使用 Windows 虚拟机。
- 我们将使用 RDP(远程桌面协议)连接到它。
- 该虚拟机中安装了一个脉冲安全客户端。
糟糕的是,Pulse 安全客户端每 8 小时从 VPN 断开一次,并且需要双因素认证过程才能重新连接。
(其他更推荐的选项,可能是向网络管理员请求 VPN 隧道)。 ¯\_(ツ)_/¯
连接到脉冲安全 VPN 的过程:
1 .必须按下连接按钮。
作者图片— Pulse 安全接口(断开连接)
2 .将需要一个双因素令牌
按作者分类的图像-双因素弹出窗口
3.必须复制(从小部件或其他来源)和粘贴(在上一个弹出窗口中)双因素令牌:
按作者分类的图像—双因素小部件
4.几秒钟后,连接将成功建立
作者图片— Pulse 安全接口(已连接)
由于我们希望每天自动执行数据提取,因此我们必须找到一种无需人工干预即可自动执行重新连接过程的方法。
解决办法
对于我们的解决方案,我们需要:
Le 看不出前面的流程是怎么实现的(完整代码在最后):
连接到脉冲安全 VPN 的过程:
1 .必须按下连接按钮。
作者图片— Pulse 安全接口(断开连接)
2 .将需要一个双因素令牌
按作者分类的图像-双因素弹出窗口
3.必须复制(从小部件或源)和粘贴(在上一个弹出窗口中)双因素令牌:
按作者分类的图像—双因素小部件
4.几秒钟后,连接将成功建立
作者图片— Pulse 安全接口(已连接)
在 RDP 会议中自动化基于 GUI 的流程的问题
在设置了前面代码的执行并检查一切都正常工作后,您可能会遇到一个问题: i 如果在我们查看 Windows VM 桌面时执行脚本,一切都将正常工作,而如果我们关闭或最小化该会话,该过程将失败。
解决方案比将其归咎于量子物理学中的观察者效应更简单。
通过 Ghipy
由于执行过程是基于图形用户界面的(我们使用图形用户界面来模拟用户和 Pulse Secure 之间的交互),并且使用 RDP 建立连接,因此必须考虑一些重要事项:
远程桌面(RDP)为运行 Windows 操作系统的远程计算机提供虚拟活动桌面。有两个潜在问题:
当使用远程桌面连接到远程计算机时,关闭远程桌面会锁定计算机并显示登录屏幕。在锁定模式下,计算机没有 GUI,因此任何当前运行或预定的 GUI 进程都将失败。
因此,不能像往常一样关闭或最小化 RDP 会话,每次注销都必须使用以下命令:
tscon.exe RDP-Tcp#27 /dest:console
其中,必须从 Windows 任务管理器中获取#27(会话 id 号),并且必须使用该号更新命令:
作者图片-任务经理 RDP 会议
在 CMD 中执行前面的命令后,RDP 会话将被关闭,但桌面仍将是活动的,因此我们的 GUI 相关代码不会失败。
RDP 会话总是必须以先前的命令结束。如果有人登录到该虚拟机并以任何其他方式退出,该脚本将由于缺少活动桌面而失败。
识别 GUI 中的对话框/窗口
在前面的代码中,我们已经看到了如何将 Pywinauto 与给定应用程序的接口连接起来:
app2 = pywinauto.Application().connect(path_to_EXE)
但是如果我们需要关注这个应用程序生成的弹出窗口,事情会变得更复杂,我们将不得不识别这个对话框/弹出窗口的名称(在 GUI 本身中)。为此,我们有不同的选择:
- 在交互模式下使用 pywinauto 和 Python 可以实时看到我们在屏幕上看到的界面列表。
from pywinauto import Desktop
windows = Desktop(backend="uia").windows()
print([w.window_text() for w in windows])
- 使用 UI 检查工具浏览屏幕上的不同界面。我们可以将鼠标悬停在某个对话框/弹出窗口上,以获取其名称:
作者提供的图片—ui inspect
app3 = pywinauto.Application(backend="uia").connect(title_re="Pulse Secure")
完整代码
结论
在本文中,我们看到了如何自动化一个显然总是需要人工干预的过程(双因素身份验证),并且我们已经将该解决方案应用于一个数据工程过程。
我们已经解释了如何使用 Pywinauto 来自动化基于 GUI 的任务,以及如何在其他用例中使用它。
最后,我们已经看到了自动化基于 GUI 的过程可能出现的问题,显然是 quantum cut(实际上更简单)的问题,以及它们可能的解决方案。
“The success formula: solve your own problems and freely share the solutions.”
― [**Naval Ravikant**](https://twitter.com/naval/status/1444741381579177984)
如何在 Kubernetes 和 S3 上自动化您的 Mongo 数据库备份
计划并自动执行从 Kubernetes 集群到 AWS S3 的数据库备份
如果您运行的是 MongoDB 之类的自托管数据库,那么您很可能享受不到托管服务提供的自动备份的好处。
本文是关于如何使用 Kubernetes CronJobs 在 Kubernetes 集群上为 MongoDB 安排自动备份作业,并将这些备份存储在 AWS S3 桶中。
计划定期执行备份作业,从数据库中提取数据,承担 IAM 角色以获取凭据,然后上传到 S3—按作者排序的图像
我们将关注一个独立的 MongoDB 设置,同样的原则也适用于副本集和其他数据库。
由于许多组织使用 Terraform 来管理基础设施,我们将直接用 Terraform 格式编写 CronJob。
技术栈
- MongoDB
- 库伯内特斯
- AWS S3
- 将(行星)地球化(以适合人类居住)
- 码头工人
内容
- 创建地形模块(可选)
- 使用所需的工具创建 Docker 映像
- 定义变量和数据
- 创建一个 S3 存储桶来存储备份
- 创建 IAM 角色和 Kubernetes 服务帐户
- 将 MongoDB 的密码存储为 Kubernetes 的秘密
- 创建库伯内特克朗乔布
- 部署基础设施
- 说明
让我们开始吧!
需求:
本项目使用 Terraform 与 AWS 提供商和 Kubernetes 提供商。
请随意查看官方教程配置 EKS 集群以启动并运行 Kubernetes 集群。
创建地形模块(可选)
为了在基础设施即代码存储库中保持结构化和整洁,我喜欢将逻辑任务划分为子模块。
请注意,这是可选的,您可以将下面创建的模板包含在基础设施源代码中的任何位置。
让我们在模块目录中创建一个目录数据库备份:
使用所需的工具创建 Docker 映像
为了执行备份,我们需要从数据库中转储数据,并将其上传到 S3。
我们将使用方便的mongodump来转储数据,并使用 AWS CLI 将数据转储上传到 S3。
在上面创建的 Terraform 模块中,添加一个目录 mongodb ,并在这个新目录中创建一个 Dockerfile ,其内容如下:
*# Dockerfile# Base on Amazon Linux 2 (will be running on AWS EKS)
FROM amazonlinux:2RUN yum install -y unzip# Install AWS CLI
RUN curl -sOL [https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip](https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip) \
&& unzip awscli-exe-linux-x86_64.zip \
&& ./aws/install# Install MongoDB CLI tools
RUN curl -sOL [https://fastdl.mongodb.org/tools/db/mongodb-database-tools-amazon2-x86_64-100.6.0.rpm](https://fastdl.mongodb.org/tools/db/mongodb-database-tools-amazon2-x86_64-100.6.0.rpm) \
&& yum install -y mongodb-database-tools-amazon2-x86_64-100.6.0.rpm*
构建该映像并将其推送到您的映像存储库
让我们构建这个映像,并确保以正确的平台为目标——如果您在运行集群的机器之外的其他机器上进行开发(比如带有 M1 芯片的 Macbook ),这一点尤其重要。
*export REPOSITORY_URL=<your repository URL, e.g. on AWS ECR>
export TAG=<COMMIT_HASH> # Should be commit hash, but can be an arbitrary stringdocker build --tag="$REPOSITORY_URL:$TAG" --platform=linux/amd64 .*
要推送映像,请确保您已登录到您的存储库(运行 docker 登录,然后运行:
*docker push "$REPOSITORY_URL:$TAG"*
定义变量并获取数据
我们需要定义一些 Terraform 配置变量,并获取将在该项目的其余部分使用的数据。请随意调整这些以适应您当前的设置。
在文件名 variables.tf 中,添加以下内容:
*# variables.tfvariable "kubernetes_namespace" {
type = string
}variable "kubernetes_cluster_name" {
description = "Kubernetes cluster where the backup job and permissions service account should be deployed"
type = string
}variable "container_image_repository" {
description = "URL of the Docker image used in the CronJob container"
type = string
}variable "container_image_tag" {
description = "Tag of the Docker image used in the CronJob container"
type = string
}variable "database_host" {
description = "MongoDB host URL"
type = string
}variable "database_user" {
description = "MongoDB user"
type = string
}variable "database_password" {
description = "MongoDB password"
type = string
sensitive = true
}*
在名为 data.tf 的文件中,添加以下内容:
*# data.tfdata "aws_caller_identity" "current" {}data "aws_eks_cluster" "kubernetes_cluster" {
name = var.kubernetes_cluster_name
}*
创建一个 S3 存储桶来存储备份
我们需要一个可靠的位置来存储我们的备份,AWS S3 公司提供了良好的保证,而且价格实惠,使用方便。
创建一个地形文件 s3-bucket.tf ,内容如下:
*# s3-bucket.tfresource "aws_s3_bucket" "database_backup_storage" {
lifecycle {
# Prevent destroying the backups storage in case of accidental tear down
prevent_destroy = true
} bucket = "database-backup-storage"
}*
或者,我们可以添加一个生命周期策略来自动删除超过 7 天的备份。在同一文件中,添加以下内容:
*# s3-bucket.tf...resource "aws_s3_bucket_lifecycle_configuration" "database_backup_storage_lifecycle" {
bucket = aws_s3_bucket.database_backup_storage.bucket
rule {
id = "delete-old-backups-7d"
status = "Enabled"
filter {} expiration {
days = 7
}
}
}*
创建 IAM 角色和 Kubernetes 服务帐户
我们的备份作业需要将备份上传到 S3 的权限。更具体地说,我们需要创建:
- 一个 IAM 角色,其策略允许 S3:PutObject 在备份 S3 桶中操作
- 一个 Kubernetes 服务帐户提供一个 web 身份令牌,允许备份作业承担 IAM 角色上传到 S3
要了解更多信息,这里有关于 AWS EKS 上服务帐户的 IAM 角色的文档。
在名为 access-control.tf 的文件中,添加以下内容:
*# access-control.tflocals {
service_account_name = "database-backup" oidc_provider = replace(
data.aws_eks_cluster.kubernetes_cluster.identity[0].oidc[0].issuer,
"/^[https:///](https:///)",
""
)
}resource "aws_iam_role" "role" {
name = "database-backup-role" assume_role_policy = jsonencode({
Version = "2012-10-17",
Statement = [
{
Effect = "Allow",
Principal = {
Federated = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:oidc-provider/${local.oidc_provider}"
},
Action = "sts:AssumeRoleWithWebIdentity",
Condition = {
StringEquals = {
"${local.oidc_provider}:aud" = "sts.amazonaws.com",
"${local.oidc_provider}:sub" = "system:serviceaccount:${var.kubernetes_namespace}:${local.service_account_name}"
}
}
}
]
}) inline_policy {
name = "AllowS3PutObject"
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = [
"S3:PutObject",
]
Effect = "Allow"
Resource = "${aws_s3_bucket.database_backup_storage.arn}/*"
}
]
})
}
}resource "kubernetes_service_account" "iam" {
metadata {
name = local.service_account_name
namespace = var.kubernetes_namespace annotations = {
"eks.amazonaws.com/role-arn" = aws_iam_role.role.arn
"eks.amazonaws.com/sts-regional-endpoints" = true
}
}
}*
创建库伯内特克朗乔布
我们可以使用 Terraform 以 HCL 格式定义我们的 CronJob(参见 kubernetes_cron_job )。注意,我们可以在 Kubernetes 清单格式(yaml/json)中应用相同的配置。
在名为 backup-cronjob.tf 的文件中,添加以下内容:
*# backup-cronjob.tfresource "kubernetes_cron_job" "database_backup_cronjob" {
metadata {
name = "database-backup-mongodb-daily"
namespace = var.kubernetes_namespace
} spec {
schedule = "0 5 * * *" // At 05:00
concurrency_policy = "Replace"
suspend = false
successful_jobs_history_limit = 3
failed_jobs_history_limit = 3 job_template {
metadata {}
spec {
template {
metadata {}
spec {
restart_policy = "Never" service_account_name = kubernetes_service_account.iam.metadata[0].name container {
name = "database-backup"
image = "${var.container_image_repository}:${var.container_image_tag}"
command = ["/bin/sh", "-c"]
args = [
"mongodump --host=\"$MONGODB_HOST\" --username=\"$MONGODB_USER\" --password=\"$MONGODB_PASSWORD\" --gzip --archive | aws s3 cp - s3://$S3_BUCKET/$S3_BUCKET_PREFIX/$(date +\"%Y%m%d-%H%M%S-%Z\").archive.gz"
] env {
name = "MONGODB_HOST"
value = var.database_host
}
env {
name = "MONGODB_USER"
value = var.database_user
}
env {
name = "MONGODB_PASSWORD"
value = var.database_password
} # Note that you can also set the DB password as a Kubernetes Secret then get it as
# env {
# name = "MONGODB_PASSWORD"
# value_from {
# secret_key_ref {
# name = "mongodb"
# key = "mongodb-password"
# }
# }
# } env {
name = "S3_BUCKET"
value = aws_s3_bucket.database_backup_storage.bucket
}
env {
name = "S3_BUCKET_PREFIX"
value = "mongodb"
}resources {
limits = {
cpu = "1000m"
memory = "1000Mi"
}
requests = {
cpu = "100m"
memory = "256Mi"
}
}
}
}
}
}
}
}
}*
部署基础设施
既然我们的备份模块已经准备就绪,我们就可以将其与基础架构的其余部分一起部署了。
您可以在 Terraform 代码中放置以下代码片段,例如在 main.tf 中:
*module "mongodb_backup" {
source = "${path.root}/modules/database-backup" kubernetes_namespace = "<your namespace>"
kubernetes_cluster_name = "<your cluster name>"
container_image_repository = "<Value of REPOSITORY_URL>"
container_image_tag = "<Value of TAG>"
database_host = <MongoDB host>
database_user = <MongoDB user>
database_password = <MongoDB password> tags = {
Name = "database-backup-mongodb"
}
}*
一旦应用了 terraform 基础设施( terraform apply) ,您应该会看到有一个 CronJob 启动并运行:
说明
它是如何工作的
A Kubernetes CronJob 调度作业作为能够执行给定任务的 pod 运行。在这种数据库备份实施的情况下,每个计划的作业将执行以下步骤:
- 连接到位于$MONGODB_HOST 的独立主机
- 使用mongodump将数据转储为压缩(gzip)文件,并将结果打印到标准输出。这里有三件事:(1)我们压缩以减少上传负载的大小,(2)我们存档以将数据转储到单个文件中(这是可选的,但可以防止转储到不区分大小写的文件系统时出现问题——参见警告这里的),(3)我们将转储打印到标准输出,以便能够通过管道将其传输到 AWS CLI。**
- 将压缩的归档文件通过管道传输到 AWS CLI
- 通过以下方式从标准输入(管道)复制到 S3 时段:
**aws s3 cp - s3://$S3_BUCKET**
如何恢复数据
- 将最新的数据从 S3 下载到您的本地或目标 Mongo 主机(即您希望恢复数据的位置):
2.使用 mongorestore 实用程序:
**mongorestore --gzip --archive=/path/to/backup [--host $HOST --username $USERNAME --password $PASSWORD]**
重要的
- 该时间表应该根据您的需要进行更改——上面的设置是相对于您的 Kubernetes 集群时区的 5:00。
- MongoDB 备份被配置为使用单个实例。相应地更改副本集的配置(参见 操作日志 的用法)。
- MongoDB 服务器的版本必须与备份转储所源自的数据库的版本相匹配。
最终注释
当运行自托管数据库时,需要采取额外的步骤来设置防止数据丢失的措施—以防灾难、意外删除、硬件故障等。
令人欣慰的是,最常见的数据库提供了生成和恢复备份的工具,像 AWS S3 这样的云存储解决方案是可靠的,经济的,并且使用方便。
利用像 Kubernetes CronJob 这样的作业调度程序,我们可以创建一个自动解决方案,在专注于构建令人惊叹的应用程序的同时,负责备份数据🎉!
如果你觉得这个教程有用,并且你想支持高质量文章的制作,考虑给我买杯咖啡!
你可以点击“关注”按钮来获取我的最新文章和帖子!
如何自动设计高效的神经网络
原文:https://towardsdatascience.com/how-to-automatically-design-an-efficient-neural-network-ee842a631885
神经结构搜索的简明介绍
Ethan Sykes 在 Unsplash 上拍摄的照片
如果你曾经使用过深度学习方法,你可能已经知道,每当你考虑一个新的数据集,你的模型的性能就非常依赖于网络的架构。
这就是为什么 虽然 微调预训练网络可以在你的旅程中帮助你,但你可能必须尝试多种模式才能找到你的最佳选择。在某些情况下,您甚至可能需要调整所选网络的某些层,以获得更好的预测能力。
这个过程可能会很快变得乏味和重复,尤其是当您需要在多个数据集上执行相同的任务时。这就是为什么知道不总是手动设计或选择您的网络架构,而是在一定条件下自动完成是可能的。这被称为 神经架构搜索(NAS) ,是 AutoML 的一个子领域,旨在自动设计神经网络。
为什么以及何时应该使用 NAS
NAS 非常方便,特别是当你想通过自动化过去手动完成的工作(设计神经网络)将基于深度学习的解决方案扩展到数十甚至数百个数据集时。
最重要的是,生成的架构不仅在预测能力方面,而且在内存大小和推理时间方面都是高效的。例如,谷歌的模型NAS-FPN【1】实现了比 SOTA 物体检测模型更好的准确性/延迟权衡。
执行 NAS 需要什么
寻找一个好的网络架构可能就像大海捞针。只要想想可能的神经操作类型(全连接、卷积、LSTMs 等)的数量。),以及它们参数的可能组合(例如卷积层的内核大小)和网络的可能深度。所有这些变量导致了无限多的候选架构。
因此,为了明智地找到最佳候选,您需要为 NAS 算法提供如下所示的 3 个元素:
NAS 的一般框架[8]
- 搜索空间 𝒜 : 包含可以采样的候选架构集合。为了定义一个搜索空间,你需要定义可能的神经操作和网络的转换动力学(即网络的节点是如何连接的)。后者要求事先知道最终网络应该是什么样子,但这并不总是强制性的。例如,一种常见的做法是将最终的网络视为层的堆叠,其中每一层都表示为一个有向无环图,就像 DARTS [2]中那样。
- 评估策略: 用于评估每个采样网络的性能。标准做法是使用模型的预测能力(例如,交叉熵用于分类任务)。一些工作引入了正则化项,以便通过限制网络的大小来实现准确性/等待时间的折衷。例如,在 AdaBERT[3]中,重模型通过在损失函数中整合推理触发器(浮点运算)的数量来进行惩罚。
- 搜索策略 :一旦从搜索空间中对架构进行了采样,并且使用评估策略对其性能进行了评估,搜索策略就会告诉 NAS 算法接下来要对什么架构进行采样和评估。搜索策略通常定义了大多数 NAS 方法之间的根本区别。
在接下来的部分中,我将介绍三种常用的 NAS 方法以及它们的一些优缺点。
具有强化学习的 NAS
使用强化学习来寻找方便的体系结构是 NAS 中的标准做法。例如在[4]中,作者观察到网络的节点和连接可以通过字符串来表示。
因此,他们设计了一个名为“ 控制器 ”的递归单元,生成网络架构字符串。相应的网络在任务数据集上被训练,并且验证准确性被转换成用于通过策略梯度方法更新控制器权重的回报信号。
具有强化学习的 NAS 的一般框架[4]
与许多其他方法相比,基于 RL 的架构搜索更彻底地探索搜索空间,并且对每个采样的架构具有更准确的性能估计。因此,RL-NAS [4]在流行的数据集上取得了最先进的结果也就不足为奇了。然而,它主要受到时间和硬件资源效率问题的困扰。例如,为 CIFAR-10 分类任务找到一个最佳架构需要 3 000 个 GPU 小时,而不是所有的公司和机构都能够负担得起这样的费用。
许多策略可以用来显著提高普通 RL-NAS 的效率,例如跨层共享参数权重(也称为参数共享),以减少可学习权重的数量和搜索空间的大小,这基本上是在[5]中完成的。
具有进化算法的 NAS
进化算法是基于启发式搜索的算法,主要受达尔文进化和自然选择过程的启发。在深度学习中,这些算法最初用于优化神经网络的权重,最近它们被推广到架构搜索。
进化方法的独创性在于在优化过程中使用随机抽样而不是梯度下降。这种随机抽样使用三次:
- 在 初始化步骤 中,生成候选架构的随机初始群体。该群体是全局搜索空间𝒜的子集,并且可以是任意大小。每一个人(建筑)都被评估,并选出最合适的。
- 在 交叉步骤 中,利用初始种群中最适合的个体(即最高性能的架构)的特征,随机产生新的个体。
- 在 变异步骤 中,对新种群的个体进行随机的细微修改,生成新的个体。
最后两步与 适应性评估和选择步骤 一起进行,直到满足收敛标准。
进化 NAS 的一般框架(图表改编自[6])
NAS 中的进化算法主要区别在于如何进行交叉和变异。为了探索 NAS 中流行的进化方法,我推荐你阅读这篇出色的调查【6】。
可区分 NAS
RL 和进化算法的时间和资源效率问题导致了基于微分梯度的方法的出现,例如 DARTS [2]和 GDAS [7]。
在这些算法中,所寻求的架构是相同单元(或层)的堆叠。每个单元被表示为由 N 个节点 (表示中间数据状态)和 K 条边 组成的有向无环图(DAG ),其中每一个都表示从 E 个可能的候选神经操作 (密集层、卷积层等)中采样的转换操作。).
下图中:N = 4 个节点,K = 6 条边,E = 3 个候选操作。
网络单元的 DAG 表示。在每条边上有三种不同采样概率的候选操作。(来源 [2])
该算法的目标是为 DAG 中的每条边选择最佳的神经操作。为此,为每个边缘内的每个候选操作分配随机采样概率,这给出了一个 E * K 概率矩阵。在每个学习步骤中,使用这些概率对架构进行采样。在评估了网络的性能之后,我们使用反向传播来更新参数权重和采样概率。
假设采样过程是不可微的,我们使用一个重新参数化的技巧将分类样本放松为连续可微的样本。
GDAS 和 DARTS 的主要优势在于,我们同时在寻找最佳架构和学习网络的权重,这使得训练比基于 RL 的方法快得多。这个叫做 一次性 NAS 。
然而,如果你没有应用一个合适的训练开始时间和学习率时间表,这种并行优化可能会变得不稳定。事实上,为权重和架构优化选择一个方便的学习速率对于获得满意的结果绝对至关重要。
外卖信息
神经结构搜索是一种强大的自动化方法,允许自动设计神经网络。如果部署正确,所选架构在预测能力、内存需求和推理时间方面产生令人满意的结果。
例如,当在单个数据集上工作或用于有限的用途时,使用现成的预先训练的网络最初可能工作得很好。但请记住,这些网络通常有数千万个参数(ResNet-50 有 24M 个参数,BERT-base 有 110M 个参数)。因此,每当您考虑扩展您的解决方案时,您迟早会意识到您必须考虑轻型模型,NAS 是一个值得认真考虑的真正选择。
然而,即使 NAS 旨在通过自动化架构设计过程来使深度学习更容易为科学界所接受,我相信大多数当前的方法都需要专家干预来确保它们的效率和稳定性。
参考文献
[1]吉亚西,高尔纳茨&林,宗毅&乐,郭。 NAS-FPN:学习用于对象检测的可扩展特征金字塔架构 (2019)。
[2]刘,&西蒙扬,卡伦&杨,。飞镖:差异化架构搜索 (2018)。
[3]陈、李道元、、邱、王明辉、李、、丁、林、黄、林、周、。 AdaBERT:具有可区分神经架构搜索的任务自适应 BERT 压缩 (2020)。
[4] Zoph,Barret & Le,Quoc。具有强化学习的神经架构搜索 (2016)。
[5] Pham,Hieu & Guan,Melody & Zoph,Barret & Le,Quoc & Dean,Jeff。通过参数共享进行高效的神经架构搜索 (2018)。
[6]刘、余巧和孙、延安和薛、张和冰、和晏、盖瑞和谭、凯。进化神经结构搜索综述 (2021)。
[7]董,宣仪&杨,易。在四个 GPU 小时内搜索健壮的神经架构 (2019)。
[8]埃尔斯肯,托马斯&梅岑,简&哈特,弗兰克。神经架构搜索:一项调查 (2019)。
如何自动生成 VGG 图像标注文件
原文:https://towardsdatascience.com/how-to-automatically-generate-vgg-image-annotation-files-41d226e6d85
使用语义数据集更快地训练实例分割
克里斯蒂安·威迪格在 Unsplash 上拍摄的照片
在计算机视觉领域,实例分割是目前最热门的话题之一。它包括图像中对象的检测/分割,即特定对象的定位及其所属像素的关联。像任何一种机器学习系统一样,需要大量的图像来训练主干架构。更具体地说,需要大量的注释来训练神经网络的定位功能。注释是一项耗时的活动,并且可以决定项目是否会成功。因此,必须小心处理它以提高生产率。
在卫星图像领域,可以利用免费数据集来利用研究人员或注释人员以前所做的工作。这些数据集通常由研究人员在从开源图像中构建它们,对它们进行前后处理,并使用它们来训练和测试他们自己的人工智能研究系统之后发布。语义分段和实例分段略有不同,但是在建筑物的情况下,一个分段可以帮助另一个分段。事实上,建筑往往是独特的,可以在任何图像上进行视觉分离。利用这种考虑,可以从二进制标签图像为每个建筑物生成单独的掩模,然后用于更快地训练实例分割算法,如掩模 RCNN。注释不必手动执行,这是该技术的主要优点。这里有一些如何做的提示!
JSON 文件格式
Mask RCNN Matterport 实现以及FAIR detector 2平台正在使用 JSON 文件为训练图像数据集加载注释。这种文件格式在许多计算机科学应用程序中使用,因为它允许以一对属性-值格式轻松存储和共享字母数字信息。它是为 JavaScript 语言构建的,但现在,它被用于许多其他编程语言,如 Python。已经构建了专用库,能够在 Python 代码中生成和解析 JSON 格式的数据作为文本文件。在 VGG 注释工具格式中,Mask RCNN 使用的典型 JSON 文件将具有以下形状:
对于子集,一个 JSON 注释文件收集所有的注释数据。每个图像注释都堆积在一个大的 JSON 文件中。
- 一个图像由它的名称和它在磁盘上的大小来标识。这个标识符由四个属性描述:图像的名称(文件名)、它在磁盘上的大小(大小)、带注释的形状(区域)以及图像上的一些元数据(文件属性)。这个区域属性本身由一个元素列表描述,该列表表示可以在图像上绘制的不同注释。
- 每个注释可以由一对两个元素描述:形状描述( shapes_attributes )和注释数据( region_attributes )。 shapes_attributes 描述由注释的形状( name )和两个整数有序列表( all_points_x 和 all_points_y )组成,它们代表形成掩膜注释的点的 x 和 y 坐标。注释数据 region_attributes 可以被调整,并且注释类可以被保存用于多类分割目的。
- 第四个标识符属性被命名为 file_attributes ,可以用来存储关于带注释图像的任何信息。
在语法方面,让我们注意花括号{}通常用于分隔相同类型的元素,以及引用描述一个元素的属性。方括号[]也用于表示参数列表。关于对,属性通常由包含其名称的字符串描述,并由:字符分隔值/数组。
幸运的是,Python 有一个库供我们读写 JSON 文件。使用 import json 代码片段可以很容易地加载它,用通用语法读写一个文本文件。让我们在下一章推导如何将二进制标签图像转换成 VGG 注释,特别是如何用 JSON 语法编写注释文件。
正在生成注释 JSON 文件
本文提出的主要思想是将二进制标签图像转换成 VGG 注释格式的 mask JSON 文件。二进制标签图像的每个形状被个性化,以将它变成用于例如分割的掩模元素。转换主要通过 Python 中易于使用的著名 OpenCV 图形库来执行。
- 第一行是构建正确的文件夹路径到地面真相标签和光学图像文件夹,并创建将被写入注释的 JSON 文件。
- 首先,使用 cv2.findContours 函数将二值蒙版裁剪成轮廓。大多数转换(阈值、灰度转换)实际上并不需要,因为数据已经是二进制图像。cv2.findContours 函数提供了一个轮廓列表,作为点的列表,这些点的坐标以图像的参考表示。
- 在我的屋顶项目的背景下,我只对大型建筑屋顶感兴趣,因此可以使用自定义 OpenCV 函数来导出屋顶的表面,然后将它们转换为平方米,并只选择有足够面积的屋顶。在这种情况下,可以使用 Ramer–Douglas–peu cker(RDP)算法来简化和近似检测到的轮廓,以便更紧凑地存储注释数据。此时,您应该有一个表示在二进制图像上检测到的轮廓的点列表。
- 现在,你需要将整个轮廓点列表转换成一个大的 via_region_data.json 文件,用于掩膜 RCNN 算法。对于 JSON 注释,数据需要具有第一段中指定的格式。在将数据推送到 JSON 文件之前,将主要使用字典。
- 根据轮廓周围[]的数量,您将需要特定数量的[:,0]来获取适当的数据。描述轮廓的整数数组必须用。tolist()参数,然后将其放入 JSON 属性。制作 VGG 注释 JSON 文件非常类似于俄罗斯娃娃。您可以创建一个空字典,指定它的一个(或多个)属性的值,然后将其作为更高级别的属性的值进行传递,以将其封装到更大的字典中。让我们注意,对于多类分割或对象检测, region_attributes 可以包含一个属性类,其中对象的实际类在 shape_attributes 参数中指定。
- 最后,每个图像数据都存储在一个大的“jsonf”元素中,用它的名称+大小字符串作为标识符,然后将所有数据放入一个 JSON 文件中。这样做非常重要,因为如果每次运行新图像时都在 JSON 文件中写入,JSON 文件的 Mask RCNN 导入将会失败。这是由于 json.load() 只读取第一组花括号{}的内容,将无法解释下一组。
就是这样!让我们看看这个过程的结果是什么!
检查注释显示
这个小章节将展示上述过程的图形使用。我主要使用美国地质调查局通过国家地图服务公开发布的美国城市图片(芝加哥、奥斯汀、旧金山)。美国地质调查局、国家地理空间计划提供的地图服务和数据。这项服务是开源的,所以你可以对数据做任何你想做的事情!在本文中,我处理了德克萨斯州奥斯汀附近的非常高分辨率的影像(空间分辨率= 0.3 米/像素)。
- 第一幅图像是视觉彩色图像,通常以 GeoTiff 格式与一起提供。tif 扩展也包含嵌入的地理空间数据。它以美国城市环境的城市场景为特色。渲染是用三个光谱视觉图像构建的:常见的蓝色、绿色和红色。但是在更复杂的影像背景下,影像供应商可以提供近红外影像,以便能够生成 CNIR(彩色+近红外影像)来分析光谱影像的不同方面。
德克萨斯州奥斯丁的卫星图像来自美国地质调查局国家地图项目
- 第二个图像显示二进制标签图像。可以看出,地面真实包含了与建筑物相关联的每一个像素,甚至是具有弯曲形状的最小像素。每个建筑都可以单独识别,因为建筑不能重叠,这证明了这一点。
来自 USGS 国家地图计划的德克萨斯州奥斯汀的建筑地面真相
- 第三个图像由二进制标签 one 和 cv2.findContours()函数检测到的轮廓组成,在它上面用红色突出显示。显示的轮廓是来自 OpenCV 函数的原始数据,并且没有被过滤掉,因此即使最小的建筑物也被表示出来。需要注意的是,cv2.findContours 函数是逐像素的变换:由一个像素连接的两个建筑物将被分割在一起,而仅一行暗像素就足以将两个靠近的建筑物分开。
图片由作者提供,基于美国地质调查局国家地图数据
- 第四幅图像显示了带有过滤后的近似轮廓的二进制标签图像。正如第二章所说,在我的屋顶项目中,我对面积小于一百平方米的建筑不感兴趣。还执行轮廓近似以减小注释文件的大小。因此,仅在大型建筑物周围绘制轮廓,并且在某些情况下,轮廓与建筑物形状不完全匹配,从而影响轮廓近似。
图片由作者根据美国地质调查局国家地图数据制作
- 第五个也是最后一个图像显示了通常的实例分割可视化,可以使用 inspect_roof_data.ipynb 等工具绘制。大型建筑的屋顶被单独分割,属于这些屋顶的像素被单独关联。此处使用的笔记本将从 via_region_data.json 文件加载注记,因此,如果您可以像这样显示带注记的卫星影像,您的数据集就可以训练实例分割掩膜 RCNN 算法了!
图片由作者提供,基于美国地质调查局国家地图数据
结论
本文展示的过程展示了如何将语义数据集转化为实例分割训练数据集。然后,它可以用来有效地训练掩模 RCNN 算法。该流程还可以重复使用和修改,以适应具有不同输入标签形状的数据集,如 ka ggleSartorius Cell Instance Segmentationcompetition 等
希望你觉得这几行有趣且有用😀如果你喜欢我的内容,你可以关注我的帐户来获得更多的 deeptech 主题!C u😉🚀
如何避免数据科学中的错误
原文:https://towardsdatascience.com/how-to-avoid-mistakes-in-data-science-20d6f9c4274b
意见
了解数据科学中各种错误的发生,尤其是在构建机器学习代码时,对于数据科学和人工智能的从业者来说是有用的。在本文中,我们将探索避免这些错误并提高生产率的步骤。
简·安东宁·科拉尔在 Unsplash 上拍摄的照片
机器学习和数据科学正被广泛应用。机器学习的一些很酷的应用是在自动驾驶汽车和银行业,根据一系列特征判断一个人是否会拖欠贷款。机器学习也被用于从制药、零售、制造和农业行业开始的大量其他行业。
许多数据科学家和机器学习工程师被雇用来利用海量数据,并分别基于业务用例生成有价值的预测。
然而,当实践者试图在人工智能领域构建这些应用程序时,经常会遇到问题。现在,我们将讨论一系列数据科学中可能发生错误的方式,这些错误发生在使用人工智能完成业务需求的任务时,以及采取措施在很大程度上避免这些错误时。我们探索了数据科学失败的一些简单方式,并采取正确的实际步骤来确保在构建应用程序时避免这些失败。
数据科学和机器学习中的错误
由 Sarah Kilian 在 Unsplash 上拍摄的照片
当构建有趣的机器学习应用程序时,有时从业者有可能在该领域犯错误。结果,为了给团队留下深刻印象而做的工作的质量被降到了最低。因此,看看数据科学中的各种错误并寻找减少它们的方法在很大程度上提高了生产力。以下是一些主要发生在数据科学领域的错误。
未能理解 ML 模型中的偏差
威尔·梅尔斯在 Unsplash 上拍照
有时,模型可能有很好的能力来很好地执行测试集。当我们发现我们没有充分训练模型来利用它们在进行机器学习预测时的全部潜力时,模型中的偏差就会发生。这可能主要是由于没有调整超参数,没有给出足够的数据,以及没有添加会对模型产生重大影响的特征。
为了避免这种情况,必须用可用数据适当地训练模型,同时确保模型在产生的误差方面达到全局最小值。这将确保我们获得最好的机器学习模型。
考虑到根据年龄、互联网服务类型和其他因素等一系列特征来预测客户是否会离开(离开服务)互联网服务的任务,可以看出,在这种情况下,我们必须使用复杂的机器学习模型来进行预测。使用不太复杂的模型,如逻辑回归,可能并不总能捕捉到趋势和来自该数据的洞察力,因为存在大量复杂的关系。如果我们使用逻辑回归模型,它很可能会有很大的偏差,因为它不能捕捉趋势。解决这个问题的最好方法之一是添加更复杂的模型,并改进机器学习预测。
不了解业务需求
照片由 Timon Studler 在 Unsplash 上拍摄
机器学习和数据科学中经常使用的技术令人印象深刻,令人着迷。有机会看看这些模型如何提取数据,并从中理解和获得有用的见解,这似乎是一个令人印象深刻的壮举。您组织中的许多团队可能正在努力实现机器学习:他们希望像其他人一样加入到生产高质量工作的行列中。然而,在数据科学之旅中询问质量问题以及机器学习是否是手头特定业务问题的可行解决方案总是一个好的步骤。
考虑使用数据科学来预测一个人是否会买房子的例子。在这种情况下,数据科学可能是最有用的,因为准确预测数据将为公司节省数百万美元和收入。他们可以根据预测更好地规划预算,并确保数据科学在整个过程中获得良好的价值。因此,在尝试将机器学习应用于大量问题之前,理解业务需求是重要的一步。
未能消除数据中的异常值
有时候,你已经和你的团队很好地讨论了业务和应用机器学习的需求,并产生了结果和良好的预测。然而,用于训练 ML 模型的数据可能有大量的异常值。在这种情况下,大量值位于某个值范围内,而其他值明显高于或低于数据的平均值。在这种情况下,模型在训练集上表现良好,但在以前没有见过的数据上不能很好地概括。
这些异常值的存在会影响大量机器学习模型的性能。因此,应努力消除它们,并确保这些模型实时正常运行。可以采取措施很好地识别它们。其中一些步骤包括找到标准偏差,并查看距离平均值 2 个偏差之间的值。这将确保我们获得手头数据的最佳预测。
数据集中异常值的例子包括用一组其他变量预测汽车价格。当我们试图预测各种汽车的价格时,考虑到诸如里程、马力和其他因素,由于人为错误会遇到异常值的情况。在这些情况下,当使用包含异常值的数据集训练模型时,模型的表现会比不包含异常值的数据集差得多。因此,从各种要素中移除这些异常值可能是构建有效解决方案的一个进步。
未能使用正确的特征工程技术
在 Unsplash 上拍摄的 ThisisEngineering RAEng
ML 模型预测中使用的特征决定了它们在未知数据上的表现。因此,赋予我们的模型对各种特性的正确访问权,并实现创建新特性的策略,可以提高这些模型的性能。此外,使用特征化和创建新要素有助于通过使用各种图来更好地探索数据。这些图通常可以帮助获得有价值的见解,并可以交给业务部门,以便他们做出数据驱动的决策。
在机器学习中,我们要输入到 ML 模型的数据中经常会有大量缺失值。缺少数据的现实问题的一些例子包括贷款违约预测、心脏病预测和癌症诊断预测。所有这些例子都包含含有缺失值的特征。这导致模型在该数据上表现不佳。对于数据可能包含丢失的工资信息的信用欺诈检测等问题,执行特征工程非常方便。用整个工资的平均值或众数来计算这些值就可以了。
如果您有兴趣了解更多关于各种特征化技术的知识,您可以看看我之前的文章,我在文章中非常详细地提到了它们,并给出了实际的例子。下面是链接。
哪些特征工程技术可以提高机器学习预测?|作者 Suhas Maddali | 2022 年 11 月|迈向数据科学(medium.com)
假设深度学习可以解决任何问题
照片由 Sai Kiran Anagani 在 Unsplash 上拍摄
随着各种公司实施的技术创新和更新战略的兴起,获取大量数据变得越来越容易,这些数据可以被提取出来,并可供大量团队用来执行机器学习相关任务。后来还发现,随着数据量的增加,使用深度学习变得更加合适。
虽然使用深度神经网络(深度学习)确实可以提高数据的性能,但团队经常期望解释为什么模型首先给出预测。正是在这段时间内,深度学习的方法可能会失败,特别是当可解释性是特定 ML 应用程序的最重要要求之一时。
考虑这样一种情况,即根据体重、血压和身体质量指数等一系列因素来诊断患者是否患有癌症。由于我们有大量来自癌症患者的数据,使用深度学习来预测几率会更容易得出结论。然而,在癌症诊断的情况下,解释深度学习模型的预测同样重要。由于深度学习模型的本质更加复杂,它们能够提取错综复杂的关系,因此它们变得更难解释为什么它们首先给出预测。因此,在这种情况下,使用简单的机器学习模型将是一种很好的方法,这些模型分别对从业者、医生和患者来说是高度可解释的。
结论
看完这篇文章后,希望你已经理解了使用机器学习和深度学习为产品构建有趣的 AI 应用程序时可能出现的一些错误。采取文章中提到的步骤可以在很大程度上帮助应对这些挑战,同时提高效率。感谢您花时间阅读这篇文章。
如果你想获得更多关于我的最新文章的更新,并且每月只需 5 美元就可以无限制地访问中型文章,请随时使用下面的链接来添加你对我工作的支持。谢了。
https://suhas-maddali007.medium.com/membership
以下是您联系我或查看我作品的方式。
GitHub: 苏哈斯马达利(苏哈斯马达利)(github.com)
YouTube:https://www.youtube.com/channel/UCymdyoyJBC_i7QVfbrIs-4Q
LinkedIn: (1)苏哈斯·马达利,东北大学,数据科学| LinkedIn
培养基: 苏哈斯·马达利—培养基
如何成为一名伟大的数据科学家
原文:https://towardsdatascience.com/how-to-be-a-great-data-scientist-f22973b20a4e
成为能够提供强大模型和最大影响的数据科学家
萨姆·穆卡达姆在 Unsplash 上拍摄的照片
在过去十年左右的时间里,数据科学已经成为一种流行的职业选择。Glassdoor 将数据科学家评为 2021 年美国第二好工作。目前有数百个训练营、大学课程和 MOOCs 可以帮助你发展成为数据科学家和在该领域找到工作所需的技能。
一旦你获得了第一份工作,你如何确保自己继续以正确的方式发展自己的技能和经验?你不会有一门课程可以学习,也不会总是有一个好的导师来指导你。你所学的课程将使你成为一名优秀的数据科学家,但经验将使你达到一名伟大的数据科学家的水平。
“学习数据科学的最好方法是做数据科学。”,
Chanin Nantasenamat
以上引自 Chanin Nantasenamat 的优秀帖的话非常真实。一旦你掌握了大多数数据科学项目教给你的技能,成为一名数据科学家的最好方式就是通过实践。你将从作为数据科学家的第一份工作中获得一般经验,但我认为一名新兴数据科学家应该关注几个关键领域。这些领域将使你成为一名数据科学家,不仅可以提供强大的模型,还可以为组织带来最大的影响。
在本文的剩余部分,我将涵盖以下四个方面,重点介绍如何获得经验,以及它们为什么会帮助您成为一名出色的数据科学家。
- 数据专长
- 深厚的统计学知识
- 端到端知识
- 知道何时简化
数据专业知识
数据是任何数据科学产品的基础。我们都听说过“垃圾进垃圾出”这句话,它与数据质量的重要性有关,但在准备和选择数据时,还有许多其他的考虑因素。
模型通常不会根据所有可用的数据进行训练,而是使用样本。深入了解您的数据以确保您选择的样本具有代表性,并且不会在您的模型中引入偏差,这一点非常重要。通过分析研究数据将有助于您了解应该使用哪些功能,应该放弃哪些功能。它可以帮助您选择最合适的模型和评估方法。
Andrej Karpathy 在他的博客“训练神经网络的诀窍”(非常值得一读)中非常好地捕捉了这一过程。他将这一过程描述为“与数据融为一体”。
“与数据融为一体”,安德烈·卡帕西
一个伟大的数据科学家对数据有着深入的了解,并对什么会出错有着一定程度的直觉,这种直觉只能来自经验。如何发现错误以及如何处理错误。如何浏览数据以了解数据集中存在的相关性和模式。模型投入生产后如何处理数据,以及可能出现的问题。数据有缺陷的机器学习模型不一定会失败或产生错误。你可能会以一个糟糕的模式告终。
统计方面的渊博知识
统计学是数据科学家如何成为数据科学家的答案。统计学是一种工具,让我们能够选择正确的数据,探索它,清理它,分析它。建立强大的机器学习也取决于你统计知识的质量。了解如何优化您的模型、解释输出和评估性能,都需要深入了解各种统计方法。
“我一直在说,未来 10 年最性感的工作将是统计学家,我不是在开玩笑。”哈尔·瓦里安
对统计技术有深入的了解,并且了解如何以及何时将这些方法应用到数据科学中,这是一个伟大的数据科学家的与众不同之处。如果没有足够的统计培训和经验,你将面临构建大量糟糕模型的危险。
端到端知识
只有投入使用,数据科学产品才会产生价值和影响。为了能够使用一个模型,它必须被操作成一个面向业务的系统。这可能是一个 Tableau 仪表盘或一个移动应用程序,但无论是哪一个端点,让数据科学产品在某个地方可用都需要基础架构。
从开发到生产,模型所需的基础设施是复杂的,并且在整个过程中需要多种不同的技能。这些技能来自多个领域,包括开发运维、数据工程、软件工程、IT 安全和数据科学。
“想法除非付诸实施,否则一文不值”,德里克·西弗斯
数据科学家不可能成为所有这些领域的专家。但是一个优秀的数据科学家应该对部署流程的每个领域有足够的了解,以便与这些领域的专家进行有意义的对话。至少在上面列出的领域中获得高水平的知识对于理解更大的图景并能够对模型部署所需的基础设施的决策做出贡献也是很重要的。
知道何时简化
数据科学家的主要角色是用数据解决有价值的业务问题。在许多情况下,这并不意味着使用最先进的算法。像大多数其他业务职能一样,数据科学需要产生良好的投资回报。因此,花时间尝试实现最先进的新技术来弥补模型分数中的几个百分点,可能没有商业意义。特别是如果一个标准的、众所周知的更简单的技术将更快地解决问题。
“当有疑问时简化”,埃里克·里斯
一个伟大的数据科学家知道何时做出这种取舍。实际上,从选择算法到编写代码,知道何时简化以及何时引入更多复杂性是成为一名伟大的数据科学家的关键要素。
一个真正伟大的数据科学家能够以产生最大价值的方式解决有价值的业务问题,在许多情况下,这种方式会产生持久的价值。要做到这一点,数据科学家需要理解并在复杂性和简单性之间做出正确的权衡。能够成功地在生产中部署模型,并在模型出现后保持其稳定和新鲜。同时确保这些数据科学产品是强健的、高质量的和公正的。
这就是为什么我认为本文涵盖的四个领域是新数据科学家发展经验并成为伟大数据科学家的最重要的地方。
感谢阅读!
如何成为一名高效的数据科学经理
原文:https://towardsdatascience.com/how-to-be-an-effective-data-science-manager-dbdea96b783c
来自数据科学和分析领导者的经验和思考
B 成为一名数据科学经理是许多数据科学家的梦想。我喜欢看奥运会。我们看到不同国家的体育英雄争夺金牌。不幸的是,参加奥运会比赛的机会是为少数有天赋的人准备的。对于我们其他人来说,我们的舞台就是工作场所。我们想获得金牌,这是数据科学经理的职位。
然而,数据科学正处于一个充满挑战的时代。数据科学的宣传已经过去了。我们正面临两大挑战:
- “我们如何生产它?”:超过 90%的数据科学解决方案仍然难以生产。在生产模式之外,相对于所付出的努力,企业采用率仍然很低。
- “把钱给我看看!”资金稀缺,每个人都在争夺首席财务官。高管们已经看到了数据分析和报告在实现数据驱动型决策方面的优势。但是,许多人不相信数据科学项目的好处。
等等,我不是自愿参加的。我认为成为一名数据科学经理就是要领导一个数据科学家团队。你知道,领导和激励团队去实现。这听起来太难了。
问题是数据科学仍然是一个成熟的职业。在我工作过的许多公司里,通常都是绿地或棕色地带。大家都知道完善的营销团队是做什么的。然而,并不是每个人都知道数据科学。在没有数据科学的情况下,公司已经运营了多年。
做一个“好”的数据科学管理者还不够;我们需要高效的数据科学经理。我已经有了多年练习这门黑暗艺术的经验。我已经得到了痛苦的教训,我希望它能让你少受一些。高效意味着实现我们的愿景,一名数据科学经理领导一个成功的数据团队,提供有价值的预测模型,并受到组织的喜爱。
关于我自己,我是一名合格的精算师(有时被称为原始数据科学家),在数据科学和分析领域度过了漫长的职业生涯。近十年来,我在不同规模、地域和风格的团队中担任过许多数据领导角色。我正处于一个阶段,我可以将我的知识回馈给社区,并帮助未来的数据领导者。
我喜欢开发让人们容易记住这些内容的方法。因此,我们将使用 PPT 的缩写。不,这不是我们最喜欢的幻灯片。这是 P 人、 P 过程、 T 技术。
人
你不了解罗根·保罗 GIF 由 SHOWTIME 体育。2021.从 Giphy 中检索
当我第一次成为数据科学经理时,我知道我必须与人合作,但我没有意识到这是如此复杂和具有挑战性。通过编码,我们得到错误反馈,然后重新运行。对于人来说,反馈很少,“重新运行”并不简单。
如果你和我一样,我们花了几十年来学习和提升我们的数据科学技能。这包括商业学位、精算资格和技术认证。
然而,数据科学经理的必备要求是人际技能。那么,我们在哪里学习人际交往技巧呢?MBA 学位就够了吗?这可能会有帮助,但是我们真的通过生活学校学习人际交往技能。我个人尝试过各种方式,有的成功,有的不成功。然而,所有这些都是宝贵的经历,让我在数据领导之旅中走到了今天。
我们是成功的数据科学家,因为我们提供了优秀的数据科学解决方案。你可能已经被奖励为高级数据科学家,或者已经被任命为数据科学经理。然而,让你来到这里的东西不会让你到达你想去的地方。
作为一名数据科学经理,你将与许多人一起工作。为简单起见,我们将他们分为内部人员和外部人员。
内部人员
内部人员包括你的团队中的所有人,直接的或邻近的部门。这包括您的直接下属、您的数据同事、更广泛的技术团队或其他部门团队成员(取决于数据科学团队的位置)。
要成功部署数据科学解决方案,您需要他们的全力支持。我们需要和数据工程师一起工作来获取和生产我们的数据。另一个技术团队需要了解您的部署计划。所有其他部门团队成员需要了解您团队的能力和交付。
内部人员期望协作。因此,我的建议是从了解他们现有的流程开始,并让他们与数据科学团队保持一致。这包括更广泛的战略、项目优先级和人员依赖性。没有必要创造自己的世界,因为它会导致进一步的筒仓。虽然数据科学团队的各个方面都处于初创阶段,但我们需要利用现有的文化来铺平道路。
另一个建议是定期与他们交流。有时候,我们都在谈生意,只有在有项目的时候才会去见人。然而,了解你周围发生的一切是值得的。有时你可能能够直接提供帮助,有时你可能是一个好的倾听者。
当我开始担任数据科学经理时,我花了太多时间与其他业务领导和利益相关者在一起。我认为我的高绩效团队是自我激励的个人贡献者。我没有错,但是他们需要更多的透明度和我的指导,特别是因为许多数据科学项目都有模糊的范围。当我通过员工调查收到这个反馈时,我重新安排了我的日程表,花了更多的时间与团队单独或集体相处。从那以后,团队不仅更加快乐,而且作为我的合作伙伴,他们在一起解决业务问题时更具创新性。
外部人员
外部人员包括团队以外的所有人员。这包括你的直接利益相关者和更广泛的组织。
对于直接利益相关者,你需要保持良好的关系。该团队以前很可能交付过成功的工作,并且有相当多的信任。因此,我的建议是培养这种关系,并在团队之间建立更紧密的关系。
对于更广泛的组织来说,这可能非常模糊——的确如此。作为一个新的(或“未知的”)团队,更广泛的组织不知道你这个闪亮的团队,也不知道它能为他们做什么。我们的目标是识别他们。我的建议是向你的直接利益相关者和同事寻求推荐。一旦确定了他们,不要只向他们推销数据科学。你需要了解他们做什么,他们的愿望,以及你如何(或不)能够帮助使用数据科学。
当我开始担任数据科学经理时,我花了太多时间与我已经认识的利益相关者在一起。这很好,直到我的主管问我如何在组织的所有团队中嵌入数据科学。从那以后,我有意识地努力去认识新的利益相关者。虽然一开始不舒服,但他们非常感谢“酷”技术团队伸出援手。如今,我发现我的职责还包括更广泛的数据科学和分析传播。
流程
郁郁葱葱的室内设计 GIF。2021.检索自 Giphy
让我从我最近看到的 LinkedIn feed 说起:
初创公司可能需要十年的时间才能建立起来。
第一年:留在游戏中
第二年:找到适合市场的产品
第三年:寻找付费客户
第四年:建立团队和委派
第 5 年:按比例构建流程
第 6-10 年:继续游戏
那就是 10 年一夜成名
资料来源:Andrew Gazdecki
如前所述,数据科学仍然是一个新兴的职业。我们需要把它当成一个新公司。
当数据科学经理职位存在时,该公司通常需要三年以上的时间。如果他们已经超过 10 年,并且您想要进一步发展团队,那么构建一个可扩展的过程仍然是正确的行动。
那么,我们需要哪些流程呢?我将涉及三个主要重点领域:
人员流程
在澳大利亚,咖啡是我们的宗教之一。如果你想结识新朋友,请他们喝杯咖啡。如果你想和你的团队呆在一起,请他们喝杯咖啡。如果你想让顾客开心,请他们喝杯咖啡。
关键是人们不会神奇地一起工作。特别是,混合工作安排给团队协作带来了挑战。
有效的数据科学经理必须探索和实施健康的习惯,以实现团队的潜力。《孙子兵法》的作者老子雄辩地劝告我们:
注意你的想法;它们变成了习惯。注意你的习惯;他们变成了角色。注意你的性格;它成为你的命运。”——老子
例如,我是敏捷目标设定的 OKR(代表“目标和关键结果”)的忠实粉丝。它启动了一个季度对话,讨论我们努力实现的目标。然后,我们每周召开会议,讨论哪些可行,哪些不可行。在本季度末,我们将举办一次回顾展,为下一届 OKR 提供素材。此外,我还鼓励团队成员不断接受指导和反馈。
以上是交付的人员流程的示例,但是我们还需要社交的人员流程。是的,我们需要有意识地对待我们的社交生活。毕竟,我们花了很多时间在工作上。
当我开始担任数据科学经理时,创建人员流程感觉像是微观管理。作为一个“宏观”的人事经理,我让会议和“流程”自发地运行,这在团队或工作量小的时候工作得很好。随着我们越来越大,事情变得越来越混乱,团队很难跟上。这时,团队要求创建一个人员流程来更好地管理我们的时间和人员。在人们压力较小的地方,情况确实有很大的不同,因为他们知道实现结果所需的关键人物和步骤。
部署流程
在数据科学团队的早期,部署是非常临时的。平均而言,我看到数据科学团队在头三年里产生了 1 到 3 个生产模型。对于小型团队,通常只是简单的刷新、重新校准或故障排除。
想象一下,如果我们想要生产 20 或 50 个模型。我们要么需要一支庞大的数据科学家队伍,要么需要一个强大的流程。从我的经验来看,你的 CFO 会选择后者。开发时间也需要考虑在内,这将是非常耗时的。
数据科学团队的成功将取决于您的团队快速可靠地交付模型的能力。根据我的经验,MLOps 是一条可行之路,它是以可扩展和可靠的方式生产机器学习工件的实践。顾名思义,它涉及应用和适应软件工程和 DevOps 原则。
然而,即使是 MLOps 仍然是一个绿地区域。虽然有原则和例子,但你需要为团队设计一些有用的东西。作为提示,从简单开始,看看你是否能利用现有的市场工具。这不是一场关于构建宏伟(也称为复杂)解决方案的竞赛,而是关于实现商业价值——以及我们如何高效、一致和可靠地实现商业价值。
过去,我通过频繁的“作战室”来推动部署敏捷性。索伦·克尔凯郭尔曾说“进步可以倒着理解;但它必须向前发展”。当我们的团队落后于计划时,或者我们只是想超越预期时,这是真实的。快速和协作的沟通一次一个地解决了我们部署过程中的实际改进。例如,我们将数据部署流程从 4 周缩短到了 1 到 2 周,而且我们仍然对进一步改进持乐观态度!
销售流程
哇,我是数据科学家;我不是销售人员。是的,你不是销售人员。但是你要对团队的管道负责。如果你处于成熟期的早期,工作管道看起来相当空。我们可以从以此为生的销售朋友那里学到一些东西。
从上面的人员部分,我们应该已经确定了我们的直接利益相关者和几个潜在的利益相关者。对于你现有的客户,你需要采取主动的方法。一个常见的错误是等待业务请求。问题是请求可能很小,比如数据刷新或一些样本数据。我们希望数据科学能够带来巨大的商业价值,因此,您需要将数据科学团队视为业务合作伙伴,而不仅仅是服务提供商。
首先,你可以要求参与利益相关者的定期计划和战略会议。这会让你了解他们的背景、挑战和期望。从那时起,您将能够更好地确定数据科学可以在哪些方面发挥作用。然后,开始与他们建立定期的合作会议,以建立需求。
过去,我采用看板方法取得了很大的成功。该委员会分为几个关键的机会阶段,如潜在客户、联系、合格、提议、异议、成交和推荐。它创造了一个非常视觉化的表现,对我的注意力和展示给别人都很有效。
科技
黑豹魔法 GIF。2019.检索自 Giphy
作为一名数据科学经理,您负责“为什么”、“做什么”和“怎么做”。对于“如何”这一部分,技术扮演了一个巨大的使能角色。
有两种主要的思想流派:建造或购买。构建意味着您的团队从头开始编写解决方案,包括通过容器化部署的各种脚本,如 Python 和 SQL。购买意味着您的团队获得了一个针对给定目的预先配置好并随时可用的解决方案。
两种方案的总成本比较是复杂的。从成本的角度来看,构建“更便宜”,因为有许多开源选项。然而,我们吸收了构建时间、维护操作和额外的人员。购买期权的认购费用更高。然而,它是现成的,并由供应商不断维护和改进。
在一个高效的数据科学团队中,技术问题是从能力而不是成本上显现出来的。您的高绩效团队渴望展示他们在构建定制和制作精良的数据产品方面的编码能力。
如上所述,数据科学是一种应用我们的定量、技术和商业技能的商业职业。因此,团队的成功基于其在正确的时间交付业务成果的能力。
有鉴于此,时间可能不是我们的朋友,选择买入往往是明智的。这些供应商的工具大多允许定制,所以你可以手动操作。它还使数据科学团队能够解决更多的业务问题,并创造更大的组织影响。
一旦团队交付了成果和规模,技术选项仍然存在。到那时,你会意识到创新的界限,需要定制和制作精良的数据解决方案。
当我开始担任数据科学经理时,我在最佳技术比较上花了太多时间。我想做出准确的“数据”驱动的决策。然而,这些比较花了几个月的时间,人们仍然不同意“最好”的技术。我意识到我们需要在特征分析的基础上考虑组织和团队文化。在那里,我们进行了价值验证,并收集了以前没有的真正的组织反馈。这创建了一个更强大的业务案例,并允许我们同时交付业务价值。
一起前进
B 成为一名高效的数据科学经理并不容易,但这是可以实现的。我们把大部分的知识都奉献给了最新的数学技巧和技术。现在,我们需要调整我们对人、流程和技术的软技能的学习。
当你处于早期阶段或学习成为一名数据科学经理时,诱惑是学习每一门管理课程并煮沸海洋。然而,他们通常涵盖一般的管理技能,如沟通和规划。在新兴的数据科学专业中,我们还需要更多具体的资源。
感谢您阅读本文!请在下面的评论区添加你最喜欢的建议。
如果你喜欢这篇文章,并希望看到更多的内容,请考虑加入媒体会员,使用下面的链接来支持我和其他作者:
https://albertsuryadi.medium.com/membership
另外,看看我下面的其他媒体文章:
关于作者: 阿尔伯特·苏亚迪 是为前瞻性组织提供高级分析和数据科学能力的公认领导者。他被公认为分析团队(实践社区)的领导者,该团队授权并激励他人超越现状。
用随机森林击败萨格马克·迪帕
原文:https://towardsdatascience.com/how-to-beat-sagemaker-deepar-with-random-forest-a358f115841f
建模变得简单
借助速度提高 3 倍的免费可解释模型,将您的 KPI 提高 15%
在 Unsplash 上由 Victoire Joncheray 拍摄的照片
如果你正在阅读这篇文章,你要么考虑对你的多时间序列数据集使用亚马逊 SageMaker DeepAR 算法,要么你已经被一个算法“卡住”——不知道如何进一步改进它。
你的数据集可能是什么样子。Airtable(数据由作者提供)
在深入研究尼提格里提技术之前,你应该考虑以下几点:
DeepAR pros
- 不需要数据科学专业知识 —如果你对数据科学一无所知,就不要继续阅读了。使用 DeepAR,它几乎不需要任何处理数据和创建预测模型的知识。
- 稳定性 —指标的方差很低,因为结果随着时间的推移相当稳定。你(一开始)看到的,就是你(将来)得到的。
- ——你会使用一种最先进的算法,很可能是亚马逊自己在自己的销售数据上使用的。因此,向你的非技术同事推销可能更容易。
DeepAR cons
- SageMaker 所需专业知识—*SageMaker 手册 长达 3447 页。虽然 DeepAR 只有 16 页,但你必须仔细阅读它们,并遵循以下说明:格式化你的数据(即类别标签),手动和自动调整超参数,回答 AWS 实例需求,并正确地将数据输入模型。*
- 刚性&黑盒——要改进一个现有的 DeepAR 模型并不是一件容易的事情。有一个小的、固定的超参数列表,如果您已经使用了超参数优化(您应该使用它),那么更改它们的值是没有用的!).此外,没有足够好的解释来说明模型的这些特征的重要性,所以很难在CRISP-DM阶段重申,或者只是向客户解释他的模型中到底发生了什么。**
- 成本 —模型在 AWS 上的训练运行时间既耗费时间又耗费金钱。
这就是你如何为你的 DeepAR 模型提供数据和超参数。是不是很奇怪?
如果你还和我在一起,你要么相信(像我一样)利大于弊,要么只是好奇想看看未来会怎样。无论哪种方式,我的经验告诉我,使用 3 倍的速度、相对免费和更易解释的模型,可以将 DeepAR 得分提高 15%,甚至可以在相当稀疏的销售数据上做到这一点。但这并不是一项容易的任务:我能给你的只有热血、汗水和一小时的编码,一直到胜利。
你准备好了吗?
1.了解你的工具
分组,分组,别忘了分组
首先,用正确的工具集来解决这个问题是至关重要的。由于数据的本质是有序序列,**很容易使用对循环*** 预处理数据,这些循环一个接一个地迭代日期和产品(如machinelingmastery所示)。尽管如此,我还是劝你——不要那样做!如果你下了那个兔子洞,你可能再也出不来了,因为你的管道需要几个小时才能运行。*
相反,去认识你的新好朋友: pandas Groupby operation ,以及它所有的奇妙小伙伴:rolling,expanding,cumsum,cumcount,diff,sum,min,max,mean,pct_change,rank,head,tail,first,last,bfill,ffill,shift,nunique 等…当然,还有**group byqueen:apply。(lambda x:your_function(x))**
把事情理清楚
在将 Groupby 结果连接回 DataFrame 之前,不要忘记按正确的顺序排序 sort _ values(),并且记住 bfill 和 ffill 函数很容易在不同的组之间溢出。使用 groupby + merge 更安全,因为它将确保那些丢失的值被正确组上计算的值填充。**
维护自己
测试您所做操作的输入和输出的正确性总是一个好主意,即使只是通过键入一个简单的 断言 命令。通过使用 assert ,您可以确保您对数据所做的假设(稍后用于您的计算)是正确的。相信我,当数据变得复杂时,如果没有那些有用的小断言,就很难搞清楚到底发生了什么。
只是你的定期-正常-每天 5 天滚动窗口的最低,最高,平均和总和的产品销售在整个国家,为每种产品。很简单,对吧?
->还有输出。Airtable(数据由作者提供)
2.小心(列车与站台之间的)空隙
如果数据集是完整的,即:
行数=时间戳数 X 索引数
这一点可以跳过。否则,您可能应该填充那些缺失的观察值,这样您就可以正确理解目标在时间戳上的真实分布。
您的数据集不完整的一个常见原因也在于我们的多指标时间序列数据集的性质:销售数据往往包括实际销售的信息,而没有任何零售额。如果精度很重要,并且您希望您的模型知道销售何时不会发生,那么就用零行来填充它。
另一件要记住的事情是有时候时间戳可能不是以日期的形式出现。考虑一个预测学生毕业的模型。在这个模型中,时间特征可能是学生到目前为止获得的学术学分,而不仅仅是一些无用的日历日期。
零很重要!Airtable(数据由作者提供)
3.你在这里的目标是什么?
DeepAR 将预测您的定量需求。但是如果时机比数量更重要呢?例如,您的最终目标是对每天每个城市的每种产品进行合理的销售预测,因为您必须为库存产品规划空间。但对你来说,更重要的是正确预测任何数量的产品将被出售的日期,因为任何数量大于零意味着你将向芝加哥的仓库发送一辆满载香蕉的新卡车。你不介意在这条赛道上装载一些额外的香蕉,但在根本没有香蕉出售的时候派出一辆新的卡车,可能是对你金钱的巨大浪费。如果对你来说是这样,时间比数量更重要,你应该考虑把你的目标转换成二进制的:大于 0 的数量为 1,否则为 0。
有时候,仅仅一根香蕉就能改变一切。照片由在 Unsplash 上的实体模型图形拍摄
但是我们如何在同一个模型中既有二元预测又有定量预测呢?简单——我们将训练一个两步模型:第一步预测销售是否会发生,第二步将预测仅在预测销售的时间内** 销售多少数量。不要担心我们在这里添加的额外工作,因为即使这是两个目标不同的不同型号,它们也可以使用完全相同的功能。**
然后…瞧!我们现在有一个分类问题。Airtable(数据由作者提供)
最后,关于物质的目标,如何解决任何挑战的一个重要建议:花一些时间浏览文献,最好是学术文献。你可能会从那些已经在这方面花费了大量时间并决定分享他们的成果的好心的研究人员那里得到一些关于如何定义和解决你的问题的好主意。所以,站在那些巨人的肩膀上。****
4.改变你的视角
像 ARIMA 或 RNN 这样的时间序列算法知道如何处理你的时间序列数据集,一个索引一个索引。另一方面,像 Random Forest 和 XGBoost 这样的监督算法不会。它们将每一行与其他行分开处理,您不应该向它们提供时间戳列。因此,我们必须将我们的数据结构转换成截面 ( Groupby.shift 将会很方便)。但是,如果您真的走这条路,请记住,对于日期、城市和产品的每种组合,您必须只有一行,所以要提前分组。
将它输入到没有日期列的模型中,行的顺序并不重要。Airtable(数据由作者提供)
警告信息
- 添加这些滞后要素将会在每个组的第一个时间戳中添加缺少数据的像元,请考虑将这些行一起移除或为它们赋予一些有意义的值。你唯一不能做的就是用原始销售数据填充它们,因为那只是直接的目标泄露。
- 注意不要将行移动到错误的方向,从而创建未来销售特征而不是历史销售特征,这将再次导致泄漏。
5.丰富你的故事
数据完整性、项目目标和问题视角非常重要,但是如果没有一套好的特性来辅助故事情节,预测可能会做得很差。我们的故事有两种特征:(独立的)😗***
- 时间固定特征 往往来源于类别(即地点、名称、品牌),可以用通常的方式处理, 目标编码 是一种降低稀疏性的方法。只需记住在训练中计算,保存计算的统计数据,并在测试中重新应用它们,而无需再次计算。
- 的时间相关特性既可以用点 4 中提到的移位来丰富,也可以用 滚动窗口 聚合器来丰富,如点 1 的示例输出。与时间相关的功能也可能包含一些有用的数据,如 扩展聚合器,即对于每个时间戳,直到该时间戳的平均销售额。最后,还有 全列车统计,比如在每个时间戳中有整个列车期间的销售总和(或加权总和)。这些特性包含一些产品“永远正确”的数据,就像一个时间固定特性。例如,随着时间的推移,香蕉在总销售额中的权重为 50%,因此在 total_sales 特性中,包含香蕉的每一行将得到 0.5。**
投资这个故事,它会回报你的投资。农 V 在 Unsplash 上拍照
这里的一个关键问题是数据管道。你应该有一个有效的功能管道** —记住,管道将为训练和测试运行两次,它们之间有一些差异(因为一些计算将只发生在训练中,并复制到测试)。确保每个功能完全独立于其他功能,这样您就可以添加和删除功能,而不必担心它们对其他功能的影响。**
6.建模,正确的方法
最后,面包和黄油。以下是一些特定于时间序列的建模建议:
- 像在点 2 中那样填充缺失的时间戳后,您的数据集可能会变得完全不平衡。对销售行进行上采样,使其等于零销售额的行数。这将增加目标的信号,可以帮助您的模型更好地学习。
- ****不要随意拆分你的数据。在时间上分割它(训练=过去,测试=最后的时间戳),并且在部署之前总是记住在你的整个数据集上重新训练你的模型(训练+测试)。这样,部署的模型将根据尽可能接近新数据的数据进行训练。
- 记住删除任何带有未来信息的特性,或者任何不再出现的时间戳(具体日期不行,具体月份可以接受)。
基本上与每个 ML 模型相关的其他要点:
- ****去掉高度相关的特征。它们的贡献很小,但会对相关特征的系数产生偏差。
- ****根据客户的 KPI 优化您的决策门槛!这可能会带来巨大的改进,而且应用起来相当简单:计算 0 到 1 之间的 100 个不同阈值的 KPI 值,并选择使训练数据的 KPI 最大化的阈值。
- 为不同的算法尝试不同的超参数,绘制衡量指标对模型复杂性的改进的训练与测试图。确保你足够接近“刚好合适”:一方面,你的模型没有过度训练和学习你的训练数据的随机性,另一方面,你的模型训练得足够努力,以达到令人满意的结果。
7.额外的优势
多个组的多个模型
有时,您的数据非常庞大和复杂,模型很难收敛到最佳解决方案。例如,香蕉和苹果的销售模式确实不同,但是不同城市的苹果销售模式也确实不同。它可能不会就此停止,因为同一座城市的一些商店在周末和节假日会卖出更多的苹果,而且,出于某种未知的原因,他们可能还会在每个月的第三周卖出更多的苹果。
在这种情况下,以及在任何其他情况下,努力在数据中找到有意义的组,然后在每个不同的组上训练独立的模型(从点 5 开始的所有规则适用于每个模型)。你会惊讶地发现这一步是如何进一步改进你的模型的,即使在你已经将特征工程和超参数优化挤压到骨骼之后。更不用说,DeepAR 可能不容易分成不同的模型,因为每个模型需要的观察最少,或者只是训练更多模型所需的额外时间和金钱,所以您将拥有与生俱来的优势。
当有许多锁着的门并且很难找到主人时,使用许多钥匙。照片由 Alp Duran 在 Unsplash 上拍摄
你如何找到这些群体?您可以使用分类特征(例如每个城市、每个项目、每个季度的模型),或者——这可能与时间序列数据更相关——您可以将具有相似销售模式的组聚集在一起。例如,创建一个在训练中的最后一个时间戳之前的最后 6 天中某个城市中某个产品的二进制销售额总和的特征。这个特性的范围自然是从 0 到 6,因此您可以为这 7 组中的每一组训练一个单独的模型。因此,如果在最后一次约会之前的最后 6 天里,休斯顿的枣椰被卖了 3 次,而洛杉矶的接骨木莓被卖了 5 次,那么休斯顿的枣椰和洛杉矶的接骨木莓将被放入不同的模型中。最后,使用统计学你总能找到有意义的群体:记住不同群体可能的分裂列表,对这些群体进行目标编码,并查看分裂的平均值是否“足够”不同。您也可以使用卡方检验来完成这项任务。
摘要
针对多个时间序列数据的亚马逊 SageMaker DeepAR 模型是一种最先进的算法,由一家科技巨头开发。不需要 DS 知识,相当稳定可靠。尽管如此,它并不总是交付最好的结果,即使结果是合理的,它们也很难被解释,并且总是耗费大量的时间和金钱。
我认为,技术娴熟的数据科学家可以做得更好。如果她:使用 Groupby 命令,确保数据完整且充分,正确定义目标,将时间序列操纵成横截面,工程师洞察力特征,训练模型推进并达到最佳可实现的精度,甚至为不同的组训练不同的模型 —
她能够并将打败 DeepAR
欢迎分享您的反馈,并通过 LinkedIn 联系我。
感谢您的阅读,祝您好运!🍀
如何成为更好的数据科学团队
原文:https://towardsdatascience.com/how-to-become-a-better-data-science-team-1dc21693d9f9
意见
作为一名数据科学家,协作是关键
目录
- 介绍
- 规划和修饰
- 利益相关方更新
- 回顾展
- 摘要
- 参考
介绍
我写的很多文章,以及一般的文章,都聚焦于一个单一的数据科学家,所以我想聚焦于一些不同的东西本身。那就是——数据科学团队。但是首先,让我们定义一下通常是由什么组成。虽然这不是一成不变的,但这里有一个数据科学团队的例子:一些数据科学家、一名数据工程师、一名业务/数据分析师、一名数据科学经理等。这里的要点不是谁组成团队,而是团队如何一起工作。话虽如此,让我们看看改善您的数据科学团队的工具和方法,无论您是数据科学家、经理还是技术招聘人员。
规划和修饰
第一个工具是计划和训练的结合。这些术语可能有点混乱,所以让我们先定义一下。
整理属于组织的范畴,但这个过程与计划(在某些公司是)的区别在于,它是对你积压工作的第一次审查,这些工作可能由几张吉拉入场券或你的团队加班加点完成的一般任务组成,但尚未被优先纳入活动流程。
你可以把计划想得更具体,在一个sprint
的层面上,即使你不使用吉拉,你仍然可以每周、每两周或任何你认为合适的节奏来计划,并记录更多的检查。你通常会做的是讨论即将到来的项目,但更重要的是,特定项目在给定的一周或一段时间内的可消化的任务,等等。
以下是在规划和修饰方面进行合作的几点收获和好处:
- 分配特定任务的努力程度
- 赋予重要性或者优先权
- 避免冗余
- 向自己强调本周你关注的是什么
- 如果有人做过类似的工作,可以帮助你/让任务更有效率
同样,根据你的公司或者你是否使用敏捷环境,这些术语可能会改变或者完全相同,但是重要的是你的团队的总体组织。
利益相关方更新
照片由 LinkedIn 销售解决方案在 Unsplash 上拍摄
在成为一名数据科学家的过程中,利益相关者的更新不会被过多地讨论,因为这段时间通常更专注于学习算法、代码本身以及它们各自的底层概念。
利益相关者可以定义为最终分配您的任务或项目的人,或者将消化您的最终项目及其对业务的影响的人。也就是说,利益相关者的角色并不相同;他们可以是数据科学经理、产品经理、销售工程师等。
你当然可以通过吉拉门票、Slack messages、Google 幻灯片等等更新利益相关者。然而,关键不在于你使用的平台,而在于你分享信息和更新的方式。
以下是您和您的团队可以有效更新利益相关者的一些方法:
- 如果您不是数据科学家,数据科学主题可能会令人困惑,所以请确保您放弃了只有数据科学家才知道的不必要的术语
- 用为什么/为什么/如何/结果的方法解释一个项目。这里有一个你可以提出的问题的例子:
—项目是什么?
—为什么这个项目会发生?
—它是如何解决的?
—其结果是什么?
- 使用前后比较,如下所示:
—以前的目标是什么,现在是什么?
此外,查看特定数据组的细分,例如,按地理位置、州、周末、类型等。
有许多方法可以解释和更新您的数据科学项目,最重要的是您如何阐明它们。
回顾展
照片由 LinkedIn 销售解决方案在Unsplash【4】上拍摄。
最后,是您的特定数据科学团队的回顾。这通常是两周一次或每月一次的对之前发生的一些情况的彻底讨论。
虽然计划和准备是在项目或任务之前,涉众的更新是在项目或任务期间以及任务结束时,但是回顾包括了在相同的整个时间框架内发生的所有事情。
在这次回顾性讨论中,您通常会看到一些东西:
- 什么进展顺利?
- 有哪些可以改进的地方?
- 向前发展的新机会是什么?
- 针对表现出色的员工的具体标注
- 在下一次回顾会之前,我们应该跟进哪些行动项目?
所有这些问题和领域通常会涵盖给定时间内发生的所有重要事情。你会更好地意识到什么对团队、公司和你自己是重要的。
摘要
虽然提高自己将改善团队,但还有其他更以团队为中心的事情可以关注,最终使您的数据科学团队整体变得更好。
总而言之,以下是您的数据科学团队作为一个整体可以改进的三种方式:
** Planning and Grooming* Stakeholder Updates* Retrospectives*
我希望你觉得我的文章既有趣又有用。如果您同意或不同意这些特定的工具和方法,请随时在下面发表评论。为什么或为什么不?关于数据科学团队的改进,您认为还有哪些工具和方法值得一提?这些当然可以进一步澄清,但我希望我能够为数据科学团队提供一些更独特的工具和方法。
我不属于这些公司中的任何一家。
请随时查看我的个人资料、 Matt Przybyla 、和其他文章,并通过以下链接订阅接收我的博客的电子邮件通知,或通过点击屏幕顶部的订阅图标 的 ,如果您有任何问题或意见,请在 LinkedIn 上联系我。
订阅链接:https://datascience2.medium.com/subscribe
引荐链接:【https://datascience2.medium.com/membership】T22
(如果你在 Medium* 上注册会员,我会收到一笔佣金)*
参考
[1]Lala Azizli 在 Unsplash 上拍摄的照片,(2021)
[2]2017 年埃斯特·扬森斯在 Unsplash 上拍摄的照片
[3]照片由 LinkedIn 销售解决方案在Unsplash(2020)上拍摄
[4]照片由 LinkedIn 销售解决方案在 Unsplash 上拍摄,(2018)
如何成为命令行向导
原文:https://towardsdatascience.com/how-to-become-a-command-line-wizard-5d78d75fbf0c
你可能从未上过的最有用的计算机科学课
在我的职业生涯中,我一直观察到的一件事是,最有生产力的数据科学家和工程师通常有一个共同点:他们是命令行奇才。他们可以在计算机的文件系统中导航,在日志文件中搜索模式,管理作业、源代码和版本控制,所有这些都可以从命令行进行,而不需要依赖鼠标和图形用户界面的缓慢导航。
然而,对于不熟悉 shell 工具的人来说,这种命令行“魔法”并不是标准计算机科学课程的典型组成部分。麻省理工学院的一门关于掌握命令行的课程被恰当地命名为“CS 教育的缺失学期”。
这篇文章是我个人的 10 节课的“命令行魔术 101”课,面向那些希望更多地使用命令行而不是图形用户界面的读者。我们将介绍 shell 和 path 变量、别名、文件权限、流和管道、高效的作业管理、tmux、ssh、git 和 vim 等基础知识。
让我们开始吧。欢迎来到 CLW 101 大楼。
1.贝壳
当你打开终端时,你会看到一个外壳,比如 bash (borne again shell)或者 ZSH (z-shell)。shell 实际上是一种完整的编程语言,可以访问某些标准程序,这些程序允许文件系统导航和数据操作。您可以通过键入以下命令找到您正在运行的 shell:
echo $SHELL
在 bash 中,每次您启动一个新的 shell 时,shell 都会加载一系列在.bashrc
文件中指定的命令,该文件通常位于您的主目录中(如果您使用 Mac,通常会有一个.bash_profile
文件代替)。在该文件中,您可以指定有用的东西,如路径变量或别名(下面将详细介绍)。
2.路径变量
当您在 shell 中键入某些程序的名称时,例如python
、cat
或ls
,shell 如何知道从哪里获得该程序呢?这就是路径变量的用途。该变量存储 shell 查找程序的所有路径的列表,用冒号分隔。您可以通过键入以下命令来检查路径变量:
echo $PATH
您可以使用以下命令向 path 变量添加额外的目录:
export PATH="my_new_path:$PATH"
最好将这个命令添加到您的 bashrc 文件中,这样当您启动一个新的 shell 时,您的附加目录总是在您的路径中。
3.别名
别名是您可以定义的自定义命令,以避免反复输入冗长的命令,例如:
alias ll="ls -lah"
alias gs="git status"
alias gp="git push origin master"
别名也可以用来为您的开发工作流创建安全措施。例如,通过定义
alias mv="mv -i"
如果您要移动的文件已经存在于新目录下,您的终端将会警告您,这样您就不会意外地覆盖您不想覆盖的文件。
一旦您将这些别名添加到 bashrc 文件中,当您启动一个新的 shell 时,它们总是可用的。
4.文件权限和 sudo
当多个用户共享一台机器时,设置文件权限很重要,它决定了哪个用户可以对哪些数据执行哪些操作。当您键入ls -l
时,您将看到当前目录中的文件及其权限,如下所示:
-rwxrwxrwx
这里,
rwx
分别代表读取、写入和执行权限- 3 个
rwx
块分别用于(1)用户,(2)用户组,和(3)其他所有人。在给定的示例中,所有这 3 个实体都具有读、写和执行权限。 - 破折号表示这是一个文件。除了破折号,你还可以看到一个代表目录的
d
或者一个代表符号链接的l
。
可以用chmod
编辑文件权限。例如,如果您想为自己创建一个可执行文件,您可以键入
chmod u+x my_program.py
👉如果一个文件是可执行的,shell 如何知道如何执行它?这是在文件的第一行用‘hash bang’指定的,比如对于 bash 脚本用
#!/bin/bash
,对于 python 脚本用#!/bin/python
。
最后,还有一个特殊的“超级用户”,他拥有所有文件的所有权限。您可以运行任何命令,就像超级用户在命令前面写下sudo
一样。您还可以通过执行以下命令来启动独立的 sudo shell
sudo su
⚠️小心使用须藤。有了 sudo,你可以修改控制电脑硬件的代码,一个错误就可能让你的电脑无法使用。记住,权力越大,责任越大。
5.流动和管道
流操作符>
将输出从程序重定向到文件。>>
做同样的事情,但是它附加到一个现有的文件,而不是覆盖它,如果它已经存在的话。这对于记录您自己的程序很有用,如下所示:
python my_program.py > logfile
另一个有用的概念是管道 : x | y
执行程序 x,并将 x 的输出导入程序 y。例如:
cat log.txt | tail -n5
:打印 log.txt 的最后 5 行cat log.txt | head -n5
:打印 log.txt 的前 5 行cat -b log.txt | grep error
:显示 log.txt 中包含字符串“error”的所有行,以及行号(-b)
6.管理作业
如果你从命令行运行一个程序(如python run.py
,程序将默认在前台运行,并阻止你做任何其他事情,直到程序完成。当程序在前台运行时,您可以:
- 键入 control+C,它将向程序发送 SIGINT(信号中断)信号,指示机器立即中断程序(除非程序有办法在内部处理这些信号)。
- 键入 control+Z,这将暂停程序。暂停后,可将节目带到前台(
fg
)或发送到后台(bg
)继续播放。
为了立即在后台启动您的命令,您可以使用&
操作符:
python run.py &
👉如何知道哪些程序当前正在后台运行?使用命令
jobs
。这将显示正在运行的作业的名称及其进程 id(PID)。
最后,kill
是一个向后台运行的程序发送信号的程序。举个例子,
kill -STOP %1
发出停止信号,暂停程序 1。kill -KILL %1
发送终止信号,永久终止程序 1。
我个人 Macbook 的带有 tmux 的终端上的四个终端窗格(图片由作者提供)。
7.tmux
tmux
(“终端多路复用器”)使您能够轻松创建新的终端并在它们之间导航。这非常有用,例如,您可以使用一个终端来导航您的文件系统,而使用另一个终端来执行作业。使用 tmux,您甚至可以同时拥有这两者。
👉学习 tmux 的另一个原因是远程开发:当您注销远程机器时(有意或无意),所有在您的 shell 中运行的程序都会自动终止。另一方面,如果您在 tmux shell 中运行您的程序,您可以简单地脱离 tmux 窗口,注销,关闭您的计算机,稍后再回到那个 shell,就好像您从未注销过一样。
下面是一些帮助您开始使用 tmux 的基本命令:
tmux new -s run
创建名为“运行”的新终端会话- control-BD:分离此窗口
tmux a
:附加到最新窗口tmux a -t run
:附加到名为‘运行’的窗口- control-B ":在下面添加另一个终端面板
- control-B%:在右侧添加另一个终端面板
- control-B➡️:移动到右边的终端面板(类似于左、上、下)
8.SSH 和密钥对
ssh
是登录远程机器的程序。为了登录远程机器,您需要提供用户名和密码,或者使用一个密钥对,由一个公钥(两台机器都可以访问)和一个私钥(只有您自己的机器可以访问)组成。
ssh-keygen
是一个生成这种密钥对的程序。如果您运行ssh-keygen
,默认情况下,它将创建一个名为id_rsa.pub
的公钥和一个名为id_rsa
的私钥,并将它们放入您的~/.ssh
目录中。您需要将公钥添加到远程机器,现在您应该知道,您可以通过管道将cat
、ssh
和一个流操作符连接在一起:
cat .ssh/id_rsa.pub | ssh user@remote 'cat >> ~/.ssh/authorized_keys'
现在,您只需提供您的私钥,就可以使用 ssh 到 remote 了:
ssh remote -i ~/.ssh/id_rsa
更好的做法是创建一个包含所有 ssh 验证配置的文件~/.ssh/config
。例如,如果您的config
文件如下:
Host dev
HostName remote
IdentityFile ~/.ssh/id_rsa
然后只需输入ssh dev
就可以登录 remote。
9.饭桶
git
是一个版本控制系统,允许你从命令行有效地浏览你的代码的版本历史和分支。
👉注意
git
与 GitHub 不同:git
是一个独立的程序,可以在本地笔记本电脑上管理代码的版本,而 GitHub 是一个远程托管代码的地方。
以下是一些基本的 git 命令:
git add
:指定下次提交时要包含哪些文件git commit -m 'my commit message'
:提交代码变更git checkout -b dev
:创建一个名为‘dev’的新分支,并检查该分支git merge dev
:将 dev 合并到当前分支。如果这会产生合并冲突,你需要手动修复这些冲突,然后运行git add file_that_changed; git merge --continue
git stash
:恢复所有更改,git stash pop
将其恢复。如果您对主分支进行了更改,然后决定您实际上希望这些更改成为一个单独的分支,这将非常有用。git reset --hard
:永久恢复所有更改
下面是一些处理远程主机(例如 GitHub)的基本 git 命令:
git clone
:将代码仓库的副本克隆到您的本地机器上git push origin master
:将更改推送到远程主机(如 GitHub)git pull
:从遥控器拉最新版本。(这个和跑git fetch; git merge;
一样)。
👉在能够运行像
git push origin master
这样的命令之前,您需要使用 ssh 密钥对进行认证(参见第 8 课)。如果您使用 GitHub,您可以简单地将公钥粘贴到您的配置文件设置下。
10.精力
Vim 是一个强大的基于命令行的文本编辑器。至少学习 vim 中最基本的命令是一个好主意:
- 每隔一段时间,您可能必须登录到一台远程机器,并在那里更改代码。vim 是一个标准程序,因此通常可以在您使用的任何机器上使用。
- 运行
git commit
时,默认情况下 git 打开 vim 来写提交消息。所以至少你会想知道如何写、保存和关闭一个文件。
关于 vim,需要理解的最重要的一点是有不同的操作模式。一旦您启动 vim,您就进入了导航模式,您可以用它来浏览文件。键入i
启动编辑模式,在该模式下可以对文件进行修改。键入Esc
键退出编辑模式并返回导航模式。
导航模式的有用之处在于,您可以使用键盘快速导航和操作文件,例如:
x
删除一个字符dd
删除整行b
(后退)转到上一个单词,n
(下一个)转到下一个单词:wq
保存您的更改并关闭文件:q!
忽略您的更改并关闭文件
更多(更多!)vim 键盘快捷键,查看这个 vim cheatsheet 。
最后的想法
祝贺您,您已经完成了“命令行向导 101”。然而,我们在这里仅仅触及了表面。为了获得灵感,请考虑以下问题:
给定一个文本文件和一个整数
k
,以递减的频率打印文件中最常用的k
个单词(及其出现的次数)
作为一名数据科学家,我的第一个冲动可能是启动一个 jupyter 笔记本,将数据加载到 pandas 中,然后使用 pandas agg
之类的功能。然而,对于一个经验丰富的命令行向导来说, 这是一个命令行程序 :
tr -cs A-Za-z '' | tr A-Z a-z | sort | uniq -c | sort -rn | sed ${1}q
这看起来和本文开头展示的稳定扩散的想象没有太大区别。的确是魔法。
在你走之前…
喜欢这个故事? 订阅 ,我的最新内容会直接进入你的收件箱。还不是中等会员? 加入我的推荐链接 并解锁无限制访问本平台发布的所有内容。想保持联系吗?关注我上 中LinkedIn和Twitter。**
寻找更多提高工作效率的技巧?查看下面链接的文章👇
* *
如何在 2022 年成为一名自由职业数据科学家
原文:https://towardsdatascience.com/how-to-become-a-freelance-data-scientist-in-2022-e6ce4ea9ce23
关于建立投资组合、获得新客户和创造稳定的额外收入的建议
在 Unsplash 上由Towfiqu barb huya拍摄的照片
由于新冠肺炎疫情,如今的就业形势发生了巨大的变化。除了全职工作,人们现在还可以灵活地从事兼职工作,作为额外的收入来源。
当我进入数据科学领域时,我最初的目标是在这个行业找到一份工作。然而,一旦我找到了一份工作,我意识到我有能力做得更多。在家工作意味着我不必经常参加社交活动。我再也不用来回奔波去工作了。
这不仅节省了时间。它节省了能源。一天工作结束时,我不再疲惫不堪,这意味着我能够承担工作之外的任务。
在本文中,我将向您介绍我作为数据科学自由职业者的经历。我还将为您提供如何开始成为数据科学自由职业者的提示。
首先,让我们看看自由职业对于数据科学的利与弊。
优势
从事自由职业最大的好处是你可以和来自世界各地的人一起工作。机会是无穷无尽的,你学会从许多不同的角度看待一个问题。
你还可以选择要做的项目种类——当你有一份全职工作时,这并不总是可能的。
另外,作为全职员工,你只能在一个行业工作。当自由职业者时,你从事的每个项目都会给你提供一个新领域的领域经验。
当你在许多不同的领域从事各种各样的工作时,你的投资组合就会增长。您不会拘泥于单一的工作方式,可以快速适应新的工作流程。你的学习能力会提高。
不足之处
成为一名数据科学自由职业者没有什么坏处。首先,数据科学领域的自由职业者数量有限。
通常是大中型公司雇佣数据科学家,这些公司倾向于雇佣全职员工,而不是自由职业者。与数据科学家相比,对自由职业网站开发人员/设计师的需求更高。
自由职业也不能保证工作安全,你需要积极寻找新的任务。因此,在从事自由职业的同时保持全职工作是一个好主意,尤其是在刚开始的时候。
可用的演出类型
作为一名自由职业的数据科学家,你可以一次性为组织建立机器学习模型。有时,随着新数据的到来,您甚至可以获得报酬来持续维护和更新这个模型。
然而,您的选择不仅限于模型构建。
由于我的全职工作是在营销领域,我在这方面有一些经验。我利用这一点,以及我的数据技能,帮助客户确定他们的目标受众,并提出营销策略。
另一项非常受欢迎的技能是数据收集。我曾与个人和公司合作,收集外部数据来帮助他们的研究或模型构建任务。
我已经做了一段时间的自由职业技术作家。我为出版物撰写数据科学教程和技巧——无论是一次性的还是基于合同的。我还被要求为该行业的初学者举办数据科学培训研讨会和在线课程。
根据你的技能,你还可以承担许多其他的任务。您可以帮助组织部署和监控他们的机器学习模型。你可以咨询公司,根据你分析的数据给他们提供建议。如果您是数据可视化方面的专家,您可以基于可用数据为客户端创建交互式仪表板。
如何找到一份自由职业
当人们第一次想到成为自由职业者时,他们的思维会跳到 Fiverr 和 Upwork 这样的平台上。
然而,仅仅在这些网站上注册并发送工作建议并不足以让你得到很多工作。这些平台已经高度饱和。为了引起他们的注意,你需要先找几份工作来建立你的投资组合。
我建议先在这些平台之外创建一个投资组合。大多数雇主都在平台之外联系我——通过 LinkedIn 或电子邮件。
我的大部分自由职业都是通过博客找到的。在像 Medium 这样的平台上坚持写作之后,一些出版物曾找过我,让我成为一名技术作家。
我曾经创建了一个集群模型并创建了一个关于 Medium 的教程,之后我被一个想要为他的组织建立一个类似模型的人雇佣。
一个客户看到了我在抓取 Twitter 上的教程,并雇佣我为他建立一个网页抓取器。另一家公司雇用了我,因为我在 Medium 上发表了一篇分析,因为他们想做类似的事情来确定他们的目标受众。
由于我的关系网,我也找到了一些工作。大学的朋友和同事曾经推荐过我。
人们更喜欢在有信任的时候雇佣员工。你更有可能从与你能力相当的人那里得到一份工作,而不是从一个你刚刚向他提出建议的人那里。
如果你成为一名全职自由职业者,一个不利之处是你最终会失去这个网络。你不再有同事或经理推荐你担任职务。因此,我建议参加当地的数据科学活动或在线社区,在那里你可以与同行业的其他专家交流。
其他提示
一旦你完成了一项自由职业任务,一定要向你的客户寻求建议。推荐证明你做了令人满意的工作,并且会让未来的客户对你的产品充满信心。这增加了你再次被雇佣的机会。
像 Upwork 和 Fiverr 这样的平台通常会在每个类别的第一页展示他们评价最高的自由职业者。如果你在这些平台上工作,一封推荐信会增加你被关注的机会。这使得你更有可能再次被类似的职位聘用。
此外,确保始终为你的客户提供高质量的工作。我的许多自由职业安排都是一次性的,因为客户喜欢我的工作质量,他们决定继续和我合作。
如果你始终按时交付成果,并满足客户的期望,他们也会考虑聘用你来完成未来的任务,而不是接触其他候选人。
本文到此为止!我希望它对您有所帮助,并祝您的数据科学之旅好运。
如何成为一名机器学习工程师
原文:https://towardsdatascience.com/how-to-become-a-machine-learning-engineer-66bd55f17c67
如何在今年成为 ML 工程师的一步一步的指导
作者创造的形象,人就是作者
人工智能工程的世界在召唤你,这正是我们今天要讨论的,如何在 2022 年成为一名机器学习工程师。我是桑德罗,我作为一名 ML 工程师已经工作了大约一年,同时也从事其他数据工作。如果你像我一样曾经计划从你的大学生活过渡到 ML 工程世界,或者从一份不同的工作进入这个令人兴奋的领域并得到你的第一份工作,这篇文章是给你的。
我将向您介绍如果我今天重新开始我会采取的步骤,以及我将关注的具体内容,然后给你一个大概的时间估计,告诉你应该在每个领域关注多长时间,这样你就可以在一年中逐步提高自己的技能。最后,我们会给出很多具体的建议,告诉你如何将这些技能转化为工作机会,以及在哪里可以学到这些技能。
硬技能
我把这篇文章分成 7 部分,第一部分是学习正确的技能。老实说,要成为一名 ML 工程师,你需要知道很多不同的东西,但实际的硬技能,即你将需要转换数据、训练模型以及最重要的将其投入生产的实际技能是必不可少的,其他的大多是很好知道的。这些硬技能定义了你,没有它们你真的找不到一份 ML 工程师的工作。
我认为你的技能集是一个机器学习管道,你必须在日常生活中建立、维护并不断改进。
ML 管道的简化源文章
现在,什么是机器学习管道,它是一个计算机软件,首先从数据源中提取数据,然后将其转换为预测或训练模型,最后部署这个模型,以便其他人可以通过各种数据输入全天候使用它。现在,如果我们后退一步,开始识别所有这些框所共有的最重要的技能,这是第一个技能,即成为一名优秀的软件工程师,这实际上是 ML 工程师的一半。如果你是计算机科学出身,那么恭喜你已经有 50%的成功了。如果不是,我们会马上研究如何建立那套技能。编程、数据结构、算法和计算机体系结构将影响你所做的一切。能够用 80%的 Python 写干净的结构良好的代码,
KDnuggets 软件杆来源
从文件中读取、记录日志、构建 API、编写转换函数,对于您所做的一切都是非常有用的技能。当然,在这个领域中还有很多其他的编程语言,比如 Java 和 C++,但是 Python 显然是大多数 ML 和数据工作的主导语言。因此,软件工程显然是你应该关注的第一技能,因为它影响你将要从事的一切工作。现在从上到下,我认为 R 更多的是数据科学和分析语言,但 SQL 是必须的。如果我们回到我们的管道类比,数据准备的整个左边部分是你需要知道的事情,以使任何项目进行下去。
我想说你至少可以了解 Pandas 和 SQL,SQL 无处不在,大部分企业数据仍然在关系数据库中。此外,SQL 语法在许多较新的数据工具中非常常见,您可以在 pandas 和 spark 中使用它,仅举两个例子。确保至少学习 SQL 的基础知识和如何编写查询,花几周时间专注于它已经足够了。
现在,一旦您从数据源提取了我们的数据,您可能会有一个 CSV 或 Parquet 文件,您将需要一些方法来转换您的数据。行业标准是 Pandas,它将真正帮助你将数据转化为对机器学习有用的东西。这意味着标准化,去除异常值,潜在地验证数据没有问题,以及大量的功能工程。虽然同样的工作有很酷的大数据工具,但我会主要关注 Pandas 和一些 Numpy,直到你有了第一份工作,因为它的语法和功能是黄金标准,我绝对会专注于这一点。从这里开始,类似的技术变得更加新奇,比如说,你可以在工作中学习它们。我认为 Numpy 非常有用,是熊猫的基础,但是纯熊猫 90%的时候会带你去那里。
现在您已经提取、转换和加载了数据,也称为 ETL 管道。让我们来看看你们都已经知道的极其重要的东西,那就是机械学习,ML 工程师中的 ML。也就是说,理解机器学习以及使其工作和推广的基础数学和统计学是非常重要的,也是工作的另一半。在这方面,我至少会关注 Sklearn、XGBoost 以及 Tensorflow 或 Pytorch。
虽然现在每个人都知道深度学习,但不要忘记至少也要学习随机森林、XGBoost 和一些线性回归,你肯定会发现它们在生产中比你现在可能预期的要多得多。有了 ML 知识,也就知道如何选择模型,这意味着能够在测试集上测试您的作品,并使用常见的度量标准(如准确性、召回率、F1 等)对它们进行评估,以确定适合您用例的最佳超参数集和模型类型。
正如许多人所说,机器学习是一种艺术形式,你永远无法充分了解你工作的这一方面,但因为我知道你们中的一些人会过于专注于它,所以我只想说,不要只专注于它,因为这份工作真的不仅仅是擅长 ML。我知道我们都被这些可爱的算法迷住了,但请记住,这只是工作的 50%,甚至更少。到目前为止,我们提到的硬技能组合已经非常强大了,如果你非常了解这些基本技能,你可能只需要知道这些技能就可以申请大多数工作,所以我强烈建议你把最初的大部分时间花在这些方面。
这个过程中的最后一部分,可能也是最容易被忽视的部分,我知道我刚才说了没有它你也能找到工作,但是当你知道这个难题的最后一个关键部分时,你找到工作的机会就会大大增加。这就是如何部署模型以及我们刚刚描述的整个管道。我将其总结为 MLOps,代表机器学习操作,它是一套旨在可靠有效地在生产中部署和维护 ML 模型的实践。
MLOps 的定义来源维基百科
它基本上位于 ML、数据工程(这是我在数据准备中总结的)和 DevOps 的交叉点上。换句话说,你如何在每月的第一天从你的 SQL 数据库中导出数据,用 Pandas 转换它,用 Tensorflow 训练一个模型,最后用 API 在云中部署它。
免责声明:我现在会提到很多可能会让你不知所措的流行词汇和复杂技术,但不要害怕,因为每个公司都会使用不同的术语,我会在最后告诉你你真正应该关注哪些术语。就背景而言,大多数公司每年至少一次不断改进和更换部件或扩展他们的技术堆栈,你不可能跟踪所有这些。
说到这里,让我们考虑一下我们的工作流,假设我们编写代码并将其推送到 GitHub,一旦完成,我们就有一个像 Jenkins 或 Airflow 这样的工具,它使用触发器下载代码,然后继续构建所谓的 docker 映像,并使用 Ansible 这样的技术将它们部署到几个集群,Kubernetes 将管理这些 pod 或容器,并向用户公开一些 API。
我们之所以有这样的管道,是因为它们是循环的,所以如果我将新代码推送到我的 GitHub 仓库,整个管道将再次运行,并自动部署新代码,希望不会被黑客攻击,用户可以立即使用,或者等到每月的第一天,Jenkins 再次触发最新的代码进行培训。
迷茫?没关系,这非常复杂,有时在这个过程中会涉及 100 种技术和多种云。对于你的第一份工作,我会说只关注最重要的,并在你工作的时候从那里开始迭代。
如果你有一些空闲时间,一定要关注 Docker,它是大多数这些技术的核心,我认为几乎每个人都在使用它,简而言之,它是一种构建简单的小程序包的技术,该程序包包含在云中或集群上运行应用程序所需的所有代码。另一个非常受欢迎的技术类别是编排工具,如 Airflow 或 Jenkins,简单地说就是确保您的代码运行,例如,每周二早上 5 点或者当您的一个队友将代码推送到特定的 git 存储库时。虽然还有许许多多的事情需要了解,但我确信,如果你知道软件工程、机器学习和 MLOps 这四类技能,你一定会找到一份机器学习工程师的工作。
从哪里学习这些技能
我把它放在自己的部分,这样它就不会让技能部分太混乱。显然,一个很好的起点是大学世界里的任何东西,你在数据和计算机科学中选择的每一门学科都将是你找工作的一个有价值的盟友。如果你还在那里,尝试选择数据科学或计算机科学作为辅修专业,如果你有学士论文或硕士论文等项目,请确保只是运行一个需要你建立一个机器学习算法的问题,你可以将它作为文件夹部分的一个项目。
如果你已经不在大学了,不要担心,外面有那么多好的资源,真的不再需要了。如果我因为某种原因忘记了我已经学过的所有东西,从零开始,我会从学习课程开始,最好最后能拿到证书。首先,从 Coursera 上的一个非正式课程开始,或者只是在 Python 上观看 youtube 视频,直到你能够创建能够正常工作的脚本。现在从这里开始,你可以在数据世界中处理实际的证书,因为我不想为一家公司做太强的广告,让我只说大型科技公司谷歌、IBM 和微软拥有数据世界中几乎所有东西的证书和课程。
他们会很有挑战性,这就是他们真正存在的目的,让你在就业市场上更有价值。所以我给你的建议是,选择一家公司,获得数据科学、数据工程或最好的 ML 工程证书。这也将教会你非常有价值的云技能,这是我没有提到的,因为有些人有谷歌,有些人有 AWS,有些人有 Azure,你需要哪一个取决于你申请的公司。
仅举一个具体的例子,谷歌云机器学习工程师证书是我个人推荐的,它将教会你我刚才提到的一切,但要知道,你应该知道基础知识,并在开始学习之前真正专注于软件工程和机器学习,因为它不是初学者教程。把这些证书想象成你拥有的相关证书越多,公司就会越喜欢你。但是同样要确保不要过度关注一个领域。
获得工作经验
现在,虽然靠自己学习所有这些技能肯定是可能的,但我强烈建议你在工作中学习。如果你还在上大学,许多公司会提供实习的机会,这是你能得到工作的最好方式。如果你正试图进入这一领域,这也适用于你,但我会在实习结束后给你一些可能更好的建议。对于实习来说,进入门槛要低得多,有许多非常有用的途径可以让你获得初级工程职位。我知道,目前作为机器学习工程师的实习机会非常少,这肯定会在未来几年发生变化。然而,如果我们想一想什么是真正的 ML 工程师,我们会发现它是许多其他领域的交汇点,这些领域提供实习或工作机会,如数据科学,数据工程和软件工程。你能在这些领域得到的任何工作或实习都应该是有价值的,也许你不能一直做 ML,但肯定有一些机会在你工作的时候做一点。
ML 工程师从采购的概述
我个人在学习期间开始了软件工程实习,然后在我的学士学位在一家公司进行了数据科学/数据工程/软件工程实习之后,我在攻读硕士学位期间继续在这些领域获得工作经验。
如果你已经工作了,并且不打算再学习,我会试着说服我的雇主再找一些在这些领域的副业。只要记住,你对数据或软件所做的一切都会让你离成为机器学习工程师更近一步。我知道向你的老板推销包括机器学习在内的内部项目可能令人害怕,但如果你向他展示你的解决方案可以节省时间,而且你真的有动力,他们肯定会喜欢。一个非常常见的例子是,对收到的电子邮件进行分类,并需要路由到正确的人,通常公司有太多的方法,一些简单的机器学习真的可以节省你的公司很多时间,所以真的坐下来想想 easy ML 可以帮助你当前的公司,也许你最终会为你的投资组合提供一个很好的项目,并且你可以获得报酬。
创建一个 ML 组合或应用程序
学了这么多之后,你需要能够向招聘经理或招聘人员展示你确实知道这些技能,你将如何做到这一点?无论是如上所述的工作经验,还是你需要创建一个文件夹,或者如果你在大学里,写论文并进行项目,向他们展示你可以做到这一点。
你现在可以创建一个网站、Linkedin 个人资料或博客,人们可以去那里看看你的资历和你做过的项目,然后说哇,这家伙真的知道如何建立机器学习模型并将其投入生产。我个人经历了获得计算机科学硕士学位的经典之路,并与人合著了一些小论文,但如果你能够构建一个功能正常的机器学习应用程序,并将其部署给其他人使用,这真的是你能做的最大的事情之一,可以帮助你获得注意,获得工作,并向雇主展示你知道这些技能。
创建机器学习工程师简历
合乎逻辑的下一步是为机器学习工程师创建一份简历,正如你已经知道的那样,你将需要一份简历或简历来申请你潜在想要申请的任何工作。所以,把你所有的技能、证书和项目都写在一张纸上。所有这些技能和项目实际上会为你创造这份简历,我不打算撒谎,但拥有一些 STEM 领域的学位也是许多工作的一个要求,但正如计算机科学中的一切表明你可以交付质量一样,项目也将发挥作用。如果你正在寻找更多的指导,我确实有一个完整的视频,带你完成为机器学习工程师创建简历的过程,真的可以通过这个视频从头开始创建你的个人简历。
Linkedin 是你的朋友
自从我制作了这个简历视频后,Linkedin 在招聘过程中的重要性急剧增加,我每周都会收到招聘人员和其他求职者的信息。因此,如果你想在这个领域找份工作,我真的会把我们到目前为止讨论过的所有信息放在你的个人资料上,这些证书和项目会确保人们注意到你,让你出现在他们的搜索中。很多时候,招聘人员会注意到你,并希望能够帮助把你“推销”给潜在的雇主。
此外,如果你正在申请,许多人会查看你的 LinkedIn 个人资料,查看你迄今为止做了什么,你在哪里工作,你在数据社区从事什么工作。这确实是人们倾向于跟踪你的第一个地方,让它成为一次对他们来说很好的经历真的可以走很长的路。
如何分配你的时间?
正如我在开始时承诺的,我将把我们在这个视频中讨论的所有内容放到一个更大的画面中,这样你就可以找出你的弱点,并利用所有这些技能打下良好的基础。我之前已经提到过,但是在我们处理其他方面之前,你应该至少有 1 年编程、数据科学家、数据工程师的经验,或者 STEM 领域的学士学位。
我知道很多人会在网上告诉你,你可以在几个月内做到,但即使是最积极的个人,我也要说这是不现实的。也就是说,我强烈建议你至少花一年时间在编程上,当然,这可以是在你攻读学位、数据科学或机器学习项目的时候。
现在,在你了解编程的基本方法之后,我会把我的时间分成 30%编程,20%机器学习,20%数据科学,15%数据工程和 15% MLOps。这些数字都是我编的吗?是的,我做了,但我绝对可以支持他们,而且也很难拿出更明智的东西,因为最终所有这些方面都包括编程和版本管理 pip 包或任何东西。我想说,只要你牢记自己的目标,从头到尾把所有的时间都花在建设项目上,你就会得到正确的时间分配,而不用想太多。
那我为什么要提呢?嗯,我觉得很多人最终只做了机器学习和调整花哨的深度学习模型,而忘记了其他的,只是要确保也将它们投入生产,这是数据科学家或人工智能研究员与机器学习工程师之间的主要区别。
结论
这是一个很大的挑战,不要害怕,我的朋友们,每天迈出一步,你很快就会到达你想去的地方。
如果你想知道他们在工作面试中可能会问你什么具体的问题,我制作了一个关于机器学习工程师面试问题的完整视频,它会给你一些提示,告诉你可能需要在哪些方面投入更多时间。
通常机器学习会在最意想不到的领域发展。虽然大趋势仍然是越大越好,越来越多的倡导者告诉我们,我们也可以用更少的钱做到这一点。我坚信这种发展不仅会让机器学习变得更容易,还会教会我们更有效地使用更大的模型
如果你喜欢这篇文章,我会很高兴在 Twitter 或 LinkedIn 上联系你。
一定要看看我的 YouTube 频道,我每周都会在那里发布新视频。
如何成为更高效的数据科学家
原文:https://towardsdatascience.com/how-to-become-a-more-efficient-data-scientist-357df86cda4d
网上有数百万篇关于如何提高效率的文章。我们不会在这里分享任何一个,因为生产力的概念是…一个棘手的问题。很多时候,我们很难区分提高生产力的要求和过度劳累的压力。
另一方面,效率是一个具有内在灵活性的概念。它鼓励我们充分利用给定的情况,但随着环境的变化,混乱有时是不可避免的,人们是复杂的存在。当我们有效率的时候,我们让事情变得简单(或者至少不会比他们需要的更复杂),保存能量而不是烧掉它。
成为一名高效的数据科学家意味着什么?本周,我们选择了几篇优秀的文章,试图从多个角度解决这个问题。无论您是大型团队的一员,还是单独的顾问、其他数据专业人员的经理或贵公司的最新分析师,我们认为您都可以在这里找到一些可靠、可行的见解。
- 结果比你花在一个项目上的时间更重要 。 Samuel Flender 解开了杠杆的概念,并提出了三个策略,可以帮助数据从业者重新专注于产生最大影响,而不是最努力或最长时间的工作。
- 面向未来的生产数据管道艺术 。Marian Nodine 说随着时间的推移,数据产品的质量以及对使用和解释数据的支持都会下降。为了让您(和您的同事)的生活更轻松,Marian 强调了建造具有长保质期的坚固管道的四个基本标准。
- 学习如何有效地对数据请求进行优先级排序 。来自业务利益相关者的持续不断的时间敏感查询已经打乱了无数数据团队的计划。正如玛丽·勒费夫尔解释的那样,问五个具体的问题并获得适当的语境可以帮助你在不失去焦点(或朋友)的情况下筛选请求。
鲍里斯·邓南德在 Unsplash 上的照片
- 做好记录至关重要 。Robert Yi在谈到围绕即席分析请求的一系列类似挑战时,强调了记录您在为组织内其他团队服务时所做工作的重要性。它不仅使你的努力可见,还可以简化未来的项目,并允许你随着时间的推移发现模式。
- 确定数据项目价值的框架 。如果你喜欢用结构化的方法来解决复杂的问题,看看乔丹·g .的方法,来决定哪个项目应该放在你清单的首位。它将促使你量化预期的时间承诺、成功概率和潜在影响,并导致更明智的决策。
- 定义指标的重要性 。如果你的数据不可靠,你就不太可能成为一名高效的数据科学家。这就是为什么高建议将你的承诺——作为个人贡献者或团队的一部分——整理成文,以提供高质量的数据和见解,并就衡量成功的明确标准达成一致。
如果你还有时间多读几本一流的书,以下任何一点都不会错:
- 我们将我们最新的月刊致力于最近几个月最令人兴奋和发人深省的技术进步之一:文本到图像人工智能工具的出现和日益广泛的采用。
- 在她的第一篇 TDS 文章中,露西·迪金森在逻辑回归的背景下揭开了分类变量的神秘面纱。
- 人工智能如何改变现代教育系统?高中毕业班 Sanjay Adhikesaven 、 Abyan Das 和 Monish Muralicharan 在探索最新创新的收益和风险方面处于独特的地位。
- 我们很高兴分享由 TDS 新作者卡洛斯·科斯塔撰写的关于 CUDA——一种通用 GPU 接口——的四部分系列文章。如果你不熟悉这个话题,第一部分是最好的开始。
- 驾驭办公室政治(尤其是在大型企业环境中)是任何数据训练营都无法教授的技能。凯西·科兹尔科夫通过鼓励数据科学家提出正确的问题填补了这些空白。
谢谢你一如既往的支持。如果你想产生最大的影响,考虑成为中层成员。
直到下一个变量,
TDS 编辑
如何更好地部署您的机器学习模型
原文:https://towardsdatascience.com/how-to-better-deploy-your-machine-learning-model-6f179483a289
我反对自制解决方案和替代方案的理由
安德烈·德·森蒂斯峰在 Unsplash 上拍摄的照片
每周,我都要花相当多的时间从研究和工程两方面学习机器学习(ML ),因为我是一名博士生,因为我已经做了相当长一段时间的软件开发人员。在浏览时,我不断看到这些教程,介绍如何使用一些声称“最快”或最简单的 python 库来部署 ML 模型。然而,我认为使用 python web 框架来部署您的 ML 模型并不是最好的选择。
这篇文章将解释为什么我认为你不应该依赖 python web 框架来部署你的 ML 模型,并提出一个替代方案。然而,这不是一个使用建议选项的教程。尽管如此,这是我正在努力发布的东西,所以请继续关注。
为什么 Python 框架不是正确的选择
使用 python 框架部署模型的第一个缺点是您必须构建它。是的,你可以找到一些带有不错的模板的存储库,甚至是一个基于 web 框架的框架,但是你仍然需要做一些修改。问问任何一个经验丰富的软件开发人员,他们都会告诉你,任何一段新代码都有可能出现错误。所以对于每一个新的软件,你都需要处理测试和维护。知道维护占软件总成本的 70%左右,你应该在添加新东西之前三思。
我围绕这一点进行了多次讨论,我一直听说构建这些应用程序是机器学习工程师的工作,这是真的。尽管如此,您并没有让开发人员使现有的应用程序更加健壮,而是添加了一个新的应用程序。
其次,我遇到的所有实现都模糊了 ML 框架和应用程序代码之间的界限,违反了关注点分离原则。因此,您需要进行的任何更新都会更加复杂,因为应用程序代码是与 ML 框架耦合在一起的。随着复杂性的增加,引入新 bug 的可能性也会增加。在某些情况下,当从一个 ML 框架跳到另一个框架时,由于 CUDA 驱动程序不匹配,您甚至可能需要更新您的基础设施。所以想象一下,你有多个研究团队,每个团队都想出于合理的原因使用不同的框架。想想所有的“同步”会议和“设计”讨论,以及需要发生的“重构”工作。
最后,python web 框架不是为机器学习而设计的,因为有一个硬件组件不容易抽象。此外,您将需要处理只在 CPU 或 GPU 上运行的情况,我甚至没有谈论多 GPU 或多节点推理。
这是可以理解的,看到自制的框架建立了一段时间,因为这些推理框架大多是非常新的。然而,如果你正在开始新的东西,我不明白你为什么要走那条路。如果您仍然选择使用自制的实现,您必须明白,在修复错误或重构样板代码时,您并没有为您的工作增加价值。所以确保你有一个合理的理由。
此外,一个人应该明白简单和容易之间的区别。使用现有的遗留自制实现很容易,因为它已经存在,但是当进行更新非常复杂时,使用起来就不简单了。
一种可能的选择
我将这一部分命名为“可能的替代”,因为这不是部署您的 ML 模型的最终方法。然而,这是一个我知道并使用的方法,我认为这是一个比我所知道的任何自制实现更好的解决方案。
我建议的替代方案是 NVIDIA Triton 推理服务器。但是,我想澄清一下,我和英伟达没有任何隶属关系。此外,它是开源的,所以我不建议你买什么。
为什么选择 NVIDIA Triton 推理服务器?
首先,英伟达是创作者。我知道你不应该通过封面来判断一本书,但众所周知,他们为任何与 GPU 和 ML 相关的东西都提供了坚实的产品。最重要的是,你可以确定它将支持未来任何新的 GPU 架构或 ML 框架,并且你不必处理任何驱动程序问题。如果你以前和 CUDA 或者 NCCL 车手打过交道,你就会明白我在说什么。此外,它经过高度优化,可以在 NVIDIA GPUs 上运行,这是行业标准,并有 CPU 支持。
第二,好用。从高层次来说,要部署一个新的模型,首先要将模型二进制文件保存在模型库中,它可以是您的本地硬盘驱动器、网络卷或任何 blob 存储,如 S3。然后创建一个描述输入、输出、调度和硬件要求的文本配置文件。之后,使用管理 API 加载模型。最后,应用程序或用户可以通过推理 API 使用模型。
作者图片
因此,部署一个新模型减少到几个 API 调用,这有多种优势:
- 您的团队没有在样板代码上花费时间,而是通过将大部分时间花在模型上来更加关注增加价值。
- 您缩短了上市时间。一旦运行了推理服务器,就不需要为新模型做额外的工作了。
- 它赋予研究人员权力。由于部署模型很简单,研究人员或者没有软件工程背景的人可以将新模型部署到开发环境中进行测试,这减少了您的支持团队的负担。
- 删除瀑布任务。如果另一个应用程序使用推理结果,任何其他团队都可以部署模型来测试集成,而不是等到您构建自制的推理服务器。我知道你可以在团队之间签订合同,但是问问任何一个经验丰富的开发人员最近的集成进展如何。
- 帮助在开发过程的早期发现问题。由于部署模型很容易,研究团队可以使用与生产环境中相同的堆栈,这有助于在过程的早期发现问题,比如超过 SLA 的响应时间。相比之下,研究团队正在选择模型,而工程团队正在构建推理服务器。一旦完成,他们意识到模型响应时间超过了 SLA,需要从头开始。
最后,它功能丰富。Triton 附带了许多特性,从简单用例到更复杂的用例,我知道其中一些特性很难实现,比如调度器或用 C API 访问共享内存。此外,它几乎支持我们今天拥有的所有 ML 框架,因此 Triton 的单个实例可以部署任何格式的模型,并且所有这些都有多个优点:
- 维护成本降低,尤其是对于复杂的功能。你与 NVIDIA 和社区分摊维护成本(因为它是开源的)。此外,如果你也想减少社区中的浪费,你可以公开 bug 请求,甚至可以投稿。
- 给研究人员更多的灵活性和自主权。研究团队可以为每个模型选择合适的框架。当一个 ML 框架没有特定的模型架构可用,并且研究人员想要避免从头构建它时,就会发生这种情况。
- 您可以访问您的团队没有能力或知识来构建的功能。如果您查看文档,您会发现一些功能需要具有特殊和罕见才能的员工,通过使用 Triton 这样的工具,您可以免费获得它(嗯,有些免费,因为成本包含在 GPU 价格中)。
结论
我在 ML 模型部署方面没有几十年的经验,我在本文中提出的论点可能有漏洞。然而,根据我有限的经验,我发现使用这样的工具会使生活变得更容易,并且可以将注意力集中在最终产品上。
此外,除了检查 Triton 推理服务器之外,另一个信息是在编写自制实现之前,总是先寻找现有的东西,尤其是在当前的创新速度下。
在你走之前
在 Twitter 上关注我,在那里我会定期发关于软件开发和机器学习的微博,或者在 Youtube 上关注我,在那里我会分享实践视频教程。
如何将数字数据与熊猫绑定
原文:https://towardsdatascience.com/how-to-bin-numerical-data-with-pandas-fe5146c9dc55
用熊猫离散化数值变量,介于,cut,qcut 和值计数之间
介绍
宁滨也称为分桶或离散化,是一种常见的数据预处理技术,用于将连续数据的间隔分组到“箱”或“桶”中。在本文中,我们将讨论使用 python 熊猫库计算宁滨数值的 4 种方法。
Pawel Czerwinski 在 Unsplash 上拍摄的照片
方法
为了便于说明,我们创建了以下合成数据。
import pandas as pd # version 1.3.5
import numpy as npdef create_df(): df = pd.DataFrame({'score': np.random.randint(0,101,1000)}) return dfdf = create_df()df.head()
这些数据包括 1000 名学生从 0 到 100 的学习成绩。任务是将数值分数分为“A”、“B”和“C”三个等级,其中“A”是最好的等级,“C”是最差的等级。
作者图片
1.& loc 之间
Pandas
*.between*
方法返回一个包含 True 的布尔向量,无论相应的 Series 元素在边界值 left 和 right[1]之间。
参数
left
:左边界right
:右边界inclusive
:包含哪个边界。可接受的值是 {“两者”、“两者都不是”、“左”、“右”}。
让我们根据以下间隔将学生的分数分成几个等级:
- 答:(80,100)
- 乙:(50,80)
- 丙:[0,50]
其中方括号[
和圆括号)
分别表示边界值包含和不包含。
我们识别哪些score
位于感兴趣的区间之间,并为其分配相应的grade
值。对于等级“A”和“B ”,只有右边界包含在内,因此我们将right
传递给inclusive
参数。对于等级“C ”,两个边界都包含在内,因此我们将both
传递给inclusive
参数。
df.loc[df['score'].between(0, 50, 'both'), 'grade'] = 'C'
df.loc[df['score'].between(50, 80, 'right'), 'grade'] = 'B'
df.loc[df['score'].between(80, 100, 'right'), 'grade'] = 'A'
作者图片
这是每个箱子里的学生人数
df.grade.value_counts()
作者图片
这种方法需要为每一个 bin 添加一行新的代码,因此它只适用于 bin 很少的情况。
2.切口
将值装入离散区间。当您需要将数据值分段和排序到箱中时,请使用 cut。这个函数对于从连续变量到分类变量也很有用[2]。
基于与上述示例相同的间隔对学生进行分组。这些是所使用的参数:
x
:要入库的输入数组。必须是一维的。bins
:标量序列:定义允许非均匀宽度的 bin 边缘。labels
:指定退回箱子的标签。必须与生成的条柱长度相同。include_lowest
: (bool)第一个区间是否应该左包含。
bins = [0, 50, 80, 100]
labels = ['C', 'B', 'A']
df['grade'] = pd.cut(x = df['score'], bins = bins, labels = labels, include_lowest = True)
我们创建一个包含面元边界值的bins
列表和一个包含相应面元标签的labels
列表。
作者图片
这是每个箱子里的学生人数
df.grade.value_counts()
作者图片
结果与第一个示例相同。
3.qcut
基于分位数的离散化函数。根据等级或样本分位数将变量离散化为大小相等的桶[3]。
在前面的例子中,我们已经为每个年级定义了分数区间,这导致每个年级箱中的学生数量不均匀。在下面的例子中,我们尝试将学生分成 3 个年级组,每个组有相同(大约)数量的学生。我们有 1000 名学生,因此每个库应该有大约 333 名学生。首先根据分数对学生进行排名,前三分之一、中三分之一和后三分之一的学生分别被分配到“A”、“B”和“C”等级。
以下是以下示例中使用的参数:
x
:要入库的输入数组。必须是一维的。q
:分位数的个数。十分位数为 10,四分位数为 4,等等。分位数的交替排列,例如[0,. 25,. 5,. 75,1。]对于四分位数。labels
:指定退回箱子的标签。必须与生成的条柱长度相同。retbins
: (bool)是否退回(箱子,标签)。如果条块以标量形式给出,则非常有用。
df['grade'], cut_bin = pd.qcut(df['score'], q = 3, labels = ['C', 'B', 'A'], retbins = True)
df.head()
作者图片
将retbins
作为True
传递会返回容器边界。
print (cut_bin)
>> [ 0\. 36\. 68\. 100.]
箱子的间隔如下:
- 丙:[0,36]
- 乙:(36,68)
- 答:(68,100)
我们可以使用.value_counts()
检查每个年级组中有多少学生。理想情况下,每个箱子应该有大约 333 名学生。
df.grade.value_counts()
作者图片
4.值计数
虽然 pandas .value_counts
通常用于计算一个系列中唯一值的数量,但它也可用于使用bins
参数[4]将值分组到半开的箱中。
df['score'].value_counts(bins = 3, sort = False)
默认情况下,.value_counts
按值的降序对返回的序列进行排序。将sort
设置为False
,按照索引的升序对系列进行排序。
作者图片
序列索引是指每个 bin 的区间范围,其中方括号[
和圆括号)
分别表示边界值包含和不包含。返回系列的值指示每个箱中有多少条记录。
与.qcut
示例不同,每个箱中的记录数量不一定相同(大约)。.value_counts
不会将相同数量的记录分配到每个等级箱中,而是根据最高和最低分数将分数范围分成三个相等的部分。分数的最小值为 0,最大值为 100,因此 3 个部分的范围约为 33.33。这也解释了为什么除了最低的左边界之外,仓的边界是 33.33 的倍数。
我们还可以通过传入一个边界列表来定义 bin 的边界。
df['score'].value_counts(bins = [0,50,80,100], sort = False)
作者图片
这给出了与实施例 1 和 2 相同的结果。
摘要
在本文中,我们研究了如何使用.between
、.cut
、.qcut
和.value_counts
对连续值进行装箱。上面例子的 Colab 笔记本可以在这里找到。
参考
[1] 熊猫之间
【2】熊猫切
熊猫 qcut
[4] 熊猫价值统计
如何提高熊猫的速度,在几毫秒内处理 1000 万行数据集
按照预期的方式使用熊猫
照片由supreme拍摄
介绍
"太好了…另一篇关于如何让熊猫速度提高 n 倍的文章."
我想我已经说过无数次了,在过去的两年里我一直在用熊猫。最近看到的一条说“让熊猫快 71803 倍”。
但我不会给你这种承诺。我将向你展示如何以最快的方式使用熊猫。因为你不能加快已经很快的东西。没道理?
让我问你这个问题。当我说“摸摸你的右耳”时,你用哪只手当然,右手。把你的左手放在头上,你不会碰到你的右耳。那会很奇怪。
嗯,使用这些函数,熊猫文档清楚地说明了慢而不是最快的方法,也会很奇怪。
这就是为什么本文将向您展示 Pandas 中一些最常见的数据操作的最佳实践。你甚至可以将这些最佳实践视为“常识”,因为这就是熊猫的创造者打算如何使用他的图书馆。
获得由强大的 AI-Alpha 信号选择和总结的最佳和最新的 ML 和 AI 论文:
https://alphasignal.ai/?referrer=Bex
高效索引
先说最基础的操作。具体来说,我们将看到选择行和列的最快方法。如你所知,熊猫有两个索引操作符——loc
和iloc
。尽管它们的差异对于小数据集来说关系不大,但随着数据量的增加,它们会变得非常明显。
首先,对于选择一行或多行,iloc
更快。
相比之下,loc
最适合选择带有标签的列:
>>> tps.loc[:, ["f1", "f2", "f3"]]
对于采样列或行,内置的sample
函数是最快的。您可能认为通过 NumPy 使用随机索引进行采样会更快,但事实并非如此:
# Sampling rows
>>> tps.sample(7, axis=0)
# Sampling 5 columns and 7 rows
>>> tps.sample(5, axis=1).sample(7, axis=0)
有效替换值
大多数时候,我看到人们使用loc
或iloc
来替换数据帧中的特定值:
的确,这种方法似乎是最快的,因为我们指定了要替换的值的确切位置,而不是让 Pandas 来搜索它。但是,这种方法很笨拙,而且没有replace
快:
速度是replace
的第一个好处,其次是它的灵活性。上面,我们用NaN
替换了所有的问号——这是一个基于索引替换的多次调用操作。
另外,replace
允许使用列表或字典同时改变多个值:
当用一个值列表替换另一个值列表时,它们将具有一对一的索引到索引的映射。你可以更具体地使用字典,比如:
使用嵌套字典可以更细化:
当您只想影响特定列的值时,嵌套替换会有所帮助。这里,我们只替换education
和income
列中的值。
replace
还有其他好处,包括基于正则表达式的替换,这可以在文档中读到。
https://ibexorigin.medium.com/membership
高效迭代
对整列或数据帧应用操作的黄金法则是永远不要使用循环。这是行之有效的陈词滥调。但是,我明白了——如何在不循环的情况下操作整个数组?
诀窍是开始将数组视为向量,将整个数据帧视为矩阵。毕竟 ML 模型就是这么接受数据的——说白了都是多变量向量值函数。
从线性代数中,我们知道对向量的运算是对整个向量进行的,不管是乘法、加法等等。幸运的是,这种对数学向量进行操作的思想在 Pandas 和 NumPy 中实现为矢量化。
因此,如果您想在一个或多个列上执行任何数学运算,很有可能该运算在 Pandas 中是矢量化的。例如,像+、-、*、/、**这样的内置 Python 操作符就像对向量一样工作。
为了体验一下矢量化,让我们对大规模数据集执行一些操作。我们将选择 Kaggle TPS 九月竞赛的约 1M 行数据集:
让我们用熊猫apply
函数对几列进行一些数学运算。那是熊猫最快的内置迭代器。
我们将用apply
在三列上运行这个函数,并检查运行时间:
1M 行数据集为 19.3 秒。还不错。现在,看看当我们将列作为向量而不是标量传递时会发生什么。无需修改功能:
37 毫秒!这比最快的迭代器快了大约 600 倍。但是我们可以做得更好—在 NumPy 阵列上使用时,矢量化甚至更快:
只需添加.values
即可获得熊猫系列的底层 NumPy ndarray。NumPy 数组速度更快,因为它们不像 Pandas 系列那样执行额外的索引调用和数据类型检查。
让我们快速疯狂吧
我们应该到此为止吗?熊猫还有一些锦囊妙计。不过,公平的警告是,除非你有超过 100 万行,否则这些不会给你带来太多好处。
好了,我们开始吧。首先,我们将把数据集的大小增加十倍,给自己一个挑战:
大约 9gb,这应该足够了。哦,顺便说一下,如果这种规模的数据集对你来说是一个问题,请查看我关于驯服这些野兽的文章:
现在,我们将继续使用我们的crazy_function
,从 NumPy 矢量化作为基线开始:
对于 10M 行的数据集,大约 0.3 秒。当我用apply
试着这样做的时候,它甚至在一个小时内都没有完成。
现在,让我们进一步改进运行时。第一个候选人是农巴。我们通过 pip ( pip install numba
)安装并导入它。然后,我们将用jit
功能来装饰我们的crazy_function
。JIT 代表 just in time,它将纯 Python 和 NumPy 代码翻译成本机指令,从而大大提高了速度。
现在,我们像运行任何其他函数一样运行它:
我们实现了大约 1.5 倍的速度提升。请注意,Numba 最适用于包含许多原生 Python 循环、大量数学运算的函数,甚至更好的是 NumPy 函数和数组。
Numba 可以做得更多,包括并行计算和基于 GPU 的编译。查看文档。
如果你不在乎额外的依赖,我给你介绍一下熊猫的eval
功能。有两个版本- pd.eval
(更高级)和df.eval
(在数据帧的上下文中)。像 Numba 一样,您应该在数据帧中至少有+10,000 个样本才能看到改进。但是一旦你这样做了,你将会看到速度上的巨大好处。
让我们在df.eval
的上下文中运行我们的crazy_function
:
没有矢量化或 Numba 快,但它有几个好处。首先,通过避免引用 DataFrame 名称,您编写的代码要少得多。接下来,它显著加快了对数据帧的非数学运算,如布尔索引、比较等等。
当你不做数学运算时,评估你在pd.eval
中的陈述。我建议从文档中查看使用eval
的注意事项。
注意,即使对于 10M 行的数据集,我们也是在毫秒的范围内讨论。
包装
我们讨论的大部分内容摘自 Pandas 文档中信息丰富的 提高速度 部分。我们已经涵盖了最重要和最有效的方法,忽略了小细节。我强烈建议你通过它来获得更多的速度提示。
https://ibexorigin.medium.com/membership https://ibexorigin.medium.com/subscribe 💔-step-feature-selection-guide-in-sklearn-to-superchage-your-models-e994aa50c6d2>
如何使用内存映射文件提升 PyTorch 数据集
原文:https://towardsdatascience.com/how-to-boost-pytorch-dataset-using-memory-mapped-files-6893bff27b99
本文将讨论实现使用内存映射文件的 PyTorch 数据集的原因和步骤
埃尔奥诺雷·凯梅尔在 Unsplash 上的照片
介绍
W 在训练神经网络时,最常见的速度瓶颈之一就是数据加载模块。如果我们通过网络传输数据,除了预取和缓存之外,没有其他简单的优化方法可以应用。
但是,如果数据在本地存储中,我们可以通过将整个数据集合并到一个文件中来优化文件读取操作,然后我们可以将该文件映射到主内存中,这样我们就不需要为每个文件读取进行昂贵的系统调用,而是让虚拟内存管理器来处理内存访问。
这段短暂旅程中的几站:
- 什么是内存映射文件
- 什么是 PyTorch 数据集
- 实现我们的定制数据集
- 基准
- 结论
什么是内存映射文件?
我们称一个内存映射文件,这个文件的内容直接分配给 虚拟内存 的一个段,这样我们可以在那个段上执行任何操作,就像在当前进程中我们可以访问的主存的任何其他部分一样。
由于虚拟内存所代表的额外抽象层,我们可以映射到比我们机器的物理容量大得多的内存文件中。运行进程所需的内存段(称为 页 )由虚拟内存管理器从外部存储器中取出并自动复制到主内存中。
使用内存映射文件的好处:
- 提高 I/O 性能,通过系统调用的正常读/写操作比本地内存中的更改要慢得多
- 该文件以一种“懒惰”的方式加载,通常一次只加载一页,因此即使对于较大的文件,实际的 RAM 利用率也是最小的。
什么是 PyTorch 数据集
Pytorch 提供了两个主要模块,用于在训练模型时处理数据管道:数据集和数据加载器。
DataLoader 主要用作数据集的包装器,它提供了许多可配置的选项,如批处理、采样、预取、混排等。,并抽象出大量的复杂性。
数据集是我们拥有大部分控制权的实际部分,我们实际上必须编写为训练过程提供数据的方式,这包括将样本加载到内存中并应用任何必要的转换。
从高层来看,我们要实现树函数:【_ _ init _ _】、len,以及 _ _ getitem _ _;我们将在下一节看到一个具体的例子。
实施我们的定制数据集
接下来,我们将看到上述三个函数的实现。
最重要的部分在 init,中,我们将使用 numpy 库中的NP . memmap()函数来创建一个 ndarray ,它由映射到文件的内存缓冲区支持。
ndarray 将从一个 iterable(最好是一个生成器来填充,以将内存利用率保持在最低水平),这样我们就可以保持对数据集支持的数据的形式和类型的高度适应性。我们还可以提供一个转换函数,当从数据集中检索时,该函数将应用于输入数据。
关于更全面的视图和其他示例,实际项目也在 Github 上这里。
还有两个实用程序类型的函数,我们在上面给出的代码中使用过。
基准
为了展示一个性能提升的真实例子,我将内存映射数据集实现与以经典惰性方式读取文件的普通数据集实现进行了比较。这里使用的数据集由 350 个 jpg 图像组成。基准测试的代码可以在这里看到。
从下面的结果中,我们可以看到我们的数据集比普通的数据集快 30 倍以上:
数据集比较
结论
本文中给出的实现决不是产品级的,但是其背后的思想是非常有效的,在使用中型到大型文件时,内存映射文件方法还有更多的用途。
感谢你的阅读,我希望你会发现这篇文章很有帮助,如果你想了解最新的编程和机器学习新闻以及一些优质的模因:),你可以在 Twitter 上关注我这里或者在 LinkedIn 上联系这里。
参考
如何提升你的 GNN
原文:https://towardsdatascience.com/how-to-boost-your-gnn-356f70086991
改善图形神经网络的技巧和诀窍
图形神经网络(GNN)是新的酷小子。它的名字听起来很花哨,数学很先进,GNNs 在各种任务上表现出最先进的性能。
GNNs 提供了一种在图结构数据上使用深度学习技术的方法。图结构数据无处不在:从化学(如分子图),到社交媒体(如社交网络),还有金融投资(如风险投资网络)。
在我的硕士论文期间,我在一个由投资者、创业公司和个人组成的投资网络上,使用 GNNs 预测了创业公司的未来融资轮次。当我实现 GNN 模型(R-GCN 和 HGT)时,基线随机森林模型已经相当强大(AUC = 0.69)。
我很高兴看到先进的 GNN 将如何提高我的成绩。令我惊讶的是,GNN 模型总是落后于基线模型的表现。增加层数和隐藏尺寸没有帮助。所以我开始研究,发现我并不是唯一一个有 GNN 关系问题的人。
如果这听起来对你来说很熟悉(很可能是这样,否则你为什么要费心阅读这篇枯燥的博客文章),我可能有一些提高你的 GNN 模型性能的技巧。
什么是 GNNs 来着?
在我们讨论如何改进 gnn 之前,让我们快速回顾一下它们是如何工作的。关于图形神经网络的伟大而深入的介绍,请查看来自 DeepFindr (或一些 literature⁴)的 Youtube 频道
假设我们有一个简单的图表,如下所示:
包含节点特征的图(图片由作者提供,改编自 DeepFindr)
图
图包含节点(I,j,k)和连接这些节点的边(e)。此外,该图还包括每个节点(X1,…)的节点特征,可能还包括每条边(黑色)。目标节点用黄色表示,它的 1 跳邻居用蓝色表示,2 跳邻居用绿色表示。包括不同类型节点的图被称为“异构”图,就像我们的例子一样。
消息传递
节点在步骤 0 的嵌入只是它的特征向量(由特征 X1,X2……组成)。为了获得我们的目标节点 I(黄色)的新的(l + 1)节点嵌入 h,我们从它的相邻节点 j(蓝色)、它自己的表示以及潜在的边特征 e(黑色)中提取所有嵌入,并且聚集这些信息。这显示在下面的公式中。但是,请记住,目前大多数著名的 GNN 架构都没有利用边缘 features⁵.之后,我们可以将这些新的节点嵌入用于各种任务,例如节点分类、链路预测或图形分类。
通用 GNN 层公式
GNNs 的问题
在实践中 最近在各个领域的许多研究发现,GNN 模型并没有提供预期的 performance⁵ ⁶ ⁷.当研究人员将它们与更简单的基于树的基线模型进行比较时,GNNs 无法超越甚至匹配基线。
其他研究人员对 GNNs⁸.有时表现不佳提供了理论上的解释根据他们的实验,GNNs 仅执行特征去噪,而不能学习非线性流形。因此,他们主张将 GNNs 视为图学习模型的一种机制(例如,用于特征去噪),而不是一个完整的端到端模型。
修理
为了弥补这些缺点,提高你的 GNN,我找到了 3 个主要的技巧/想法:
- 利用 GNN 中的边缘特征
- GNNs 自我监督预培训
- 单独托辞&下游任务
让我们来详细了解一下。
利用边缘特征
利用边要素的想法在很大程度上取决于您正在处理的数据类型。如果您的数据包含(多维)边要素,利用边要素可以提高模型的性能。
然而,很少建立的 GNN 模型架构支持多维边缘 features⁵.我使用的一个简单的工作方法是创建人工节点:
人工节点 通过使用人工节点,你可以继续使用你之前使用的相同模型。我们唯一要改变的是图表本身,它会变得更复杂一点。不是边保存边特征,而是每条边将成为自身的一个节点(浅蓝色)连接到原始的深蓝色节点。
添加人工节点前后的投资网络元图(图片由作者提供)
这样,您可以通过将边要素作为人造节点的节点要素传递给模型来间接利用边要素。如果边要素与任务相关,这可以提高模型的性能,但也会增加复杂性。您可能需要考虑向模型中添加更多的 GNN 图层(以允许更多的邻居跃点)。人工结节导致 AUC 增加约 2%。
你自己的 Edge 特性架构 你也可以创建自己的 GNN 层实现。这听起来很难;但是,如果你使用一个图形学习库,比如 DGL ,这肯定是可行的。我建议您使用现有的 GNN 实现(见这里)并根据您的需要进行调整。
作为一个例子,我基于 GAT ⁰和 R-GCN 的现有思想制定了自己的实现,我称之为 Edge-GCN:
我自己的边缘-GCN 公式(v 代表节点,e 代表边缘,sigma 是非线性激活函数[在这种情况下是 RELU],alpha 是每个关系类型的学习注意力分数,c 是归一化常数)
边 GCN 使用注意机制来学习所有不同关系类型的边相对于节点特征的重要性。如果您对 DGL 的实施感兴趣,请联系我。E-GCN 架构将 GNN 模型的 AUC 结果提高了约 2%(人造节点也是如此)。
自我监督的预培训
这可能是提高你的 GNN 性能的最重要的技巧。尽管预训练 GNNs 已经在理论上进行了探索,但在实践中的应用仍然是 rare⁶ ⁷ ⁸.
这个想法与计算机视觉和自然语言处理领域的概念非常相似。以语言模型 BERT 为例,它被训练来预测句子中的屏蔽词(这是自我监督的,因为它不依赖于标记的数据)。我们通常不太关心预测屏蔽词的具体任务。然而,由于模型了解特定单词如何相互关联,因此得到的单词嵌入对于许多不同的任务非常有用。
自我监督
我们想要使用自我监督任务来预训练 GNN 模型节点嵌入。在有噪声的标签的情况下,这可能是特别有益的,因为自我监督过程提供了更多的“有标签的”例子(因为我们不需要为预训练提供标签),并且可能也不容易有噪声。
如果我们的最终目标是对节点进行分类,我们可以在整个图上使用链接预测作为自我监督的预训练任务。在链接预测中,我们试图预测两个节点之间是否存在边(=链接)。因此,我们训练 GNN 来区分图中的真实边和人工引入的假边(“用于链接预测的负采样”)。由于我们只是简单地添加伪边并移除图中现有节点之间的真实边,因此我们不依赖任何标记的数据。接下来,我们可以使用从链路预测 GNN 模型得到的节点嵌入作为另一个节点分类模型的输入。
将自我监督的预训练管道添加到模型中,其 AUC 分数惊人地增加了 14%,使这成为最有影响力的技巧。
单独的借口和下游任务
到目前为止,我们只讨论了在自我监督的任务(“借口”)上对 GNN 进行预训练,以及在最终(“下游”)任务上使用相同的 GNN 架构。然而,我们不必为这两个任务使用相同的模型架构。您还可以组合不同的 GNN 架构。或者更有希望的是:
两全其美 如前所述,GNN 层可能无法在各种情况下高效学习。因此,我们可以使用 GNN 模型,通过自我监督的预训练来创建节点嵌入,并将这些嵌入传递给经典的机器学习算法或完全连接的神经网络层,以用于最终的下游任务。这种架构可以用于许多不同的下游任务,从图形分类到节点分类和回归。
该模型将受益于将访问图中包含的所有信息的能力与非线性流形学习属性相结合。此外,该模型继承了更简单的机器学习算法的一些好处,如减少训练时间和更好的可解释性。在我们的实验中,基于树的模型(例如随机森林)对于节点分类的下游任务显示出特别强的性能,因此可以从那里开始。
接下来,您可以看到包含所有三个提出的想法的最终管道的图形概述:
最终管道使用边缘特征、自我监督预训练和下游随机森林模型对图中的节点进行分类(X 表示特征,E 表示学习嵌入,h 表示隐藏节点表示)(图片由作者提供)
这种架构代表了我们的最终模型,AUC 得分为 78.1(另一个+ 1.5%),或以 AUC 衡量的总性能增加 17%(基础 R-GCN 模型:AUC = 66.6)。
结论
在这篇博文中,我们讨论了图形神经网络模型的缺点以及提高模型性能的三个主要技巧。结合这些技巧,我能够将我的最终 GNN 模型的 AUC 提高 17%(其他指标甚至更高)。
首先,如果您的数据包含边特征,并且您认为它们对最终的预测任务很有帮助,那么您可以尝试利用边特征。第二,使用自我监督的目标预先训练 GNN 模型通常有益于最终模型的性能。它可以增加训练样本的数量,有时还可以减少固有噪声。第三,测试前文本和最终预测任务的不同架构可以提高模型的预测能力。
这些技巧对你有用吗?如果你有任何补充或反馈,请在评论区告诉我!GNN 调音快乐!
参考
[1] Michael Schlichtkrull、Thomas N. Kipf、Peter Bloem、Rianne van den Berg、Ivan Titov 和 Max Welling。用图卷积网络对关系数据建模,2017。
[2]胡,董,王宽三,。异构图形转换器,2020。
[3]https://deepfindr.com,2020 年。
[4]达维德·巴丘、费德里科·埃里卡、阿莱西奥·米凯利亚、马尔科·波德达。图形深度学习的温和介绍,2020
[5]杨。NENN:在图形神经网络中结合节点和边特征,2020
[6]费德里科·埃里卡、马尔科·波德达、达维德·巴丘和阿莱西奥·米凯利。用于图形分类的图形神经网络的公平比较,2020。
[7]克莱门特·加斯托、西奥菲勒·卡尼尔和让-米歇尔·达勒。创业融资成功的外部因素的不同重要性:早期阶段的竞争和成长期的网络,2019。
[8]蒋德军,吴振兴,谢长玉,,陈,廖奔,王哲,,曹东升,,侯廷军.图形神经网络可以为药物发现学习更好的分子表示吗?2021.
[9]黄 NT 和前原诚司。重温图形神经网络:我们所拥有的只是低通滤波器,2019。
[10]Petar veli kovi、Guillem Cucurull、Arantxa Casanova、Adriana Romero、Pietro Liò和 Yoshua Bengio。图注意力网络,2018。
11 卡罗·哈普雷希特。使用图形神经网络预测未来融资轮次,2021
[12]华伟·胡、、约瑟夫·戈麦斯、马林卡·兹特尼克、珀西·梁、维贾伊·潘德和朱尔·莱斯科维奇。预训练图神经网络的策略,2019。
[13] Jacob Devlin,Chang Ming-Wei,Kenton Lee 和 Kristina Toutanova。BERT:面向语言理解的深度双向转换器预训练,2018。
如何建立全超参数整合的贝叶斯岭回归模型
我们如何处理控制正则化强度的超参数?
在这篇博文中,我们将描述一种贝叶斯岭回归算法,其中代表正则化强度的超参数被完全积分。在【github.com/rnburn/bbai】有一个实现。
设 θ = (σ, w )表示具有权重 w 和方差σ的正态分布误差的线性回归模型的参数。
如果 X 表示具有 p 个回归量
和 n 行的满秩 n×p 矩阵,则 θ 指定可能的
目标值 y 的概率分布
假设我们观察到 y 并假设 y 是由未知参数的线性模型产生的。贝叶斯推理方法寻求量化我们对给定观测值的未知参数 θ 的信念。
应用贝叶斯定理,我们可以将概率改写为
我们指的是
- P( θ | y )作为后验分布
- P( y | θ )作为似然函数
- P( θ )先验分布
先验分布描述了我们在观察到 y 之前对 θ 的信念,后验分布描述了我们在观察到 y 之后更新的信念。
假设先验分布可以表示为
其中 h(⋅,η) 表示由我们称之为超参数η参数化的概率分布族
。
传统的贝叶斯线性回归方法使用了所谓的共轭先验。一族先验 h(⋅,η)是共轭的,如果后验也属于该族
共轭先验在数学上是方便的,因为连续观测可以被视为对分布族的参数进行连续更新,但是要求 h(⋅η是共轭的是一个强假设。
注意:关于与其他贝叶斯算法的更详细的比较,请参见附录 A。
我们将描述一种算法,其中
- 先验被选择为收缩 w ,反映了先前的假设,即 w 不是
预测性的,并且对于其他参数近似为非信息性的。 - 我们在超参数上完全积分,因此不需要任意选择η。
让我们首先考虑一下,先验无信息意味着什么。
如何挑选无信息的前科?
注意:这里对非信息先验的介绍紧跟 Box & Tiao 的书统计分析中的贝叶斯推断的第 2 章。
假设 y 是均值为 0 但方差未知的正态分布产生的数据。设σ表示标准差,ℓ表示似然函数
假设我们在σ上施加统一的先验,使得后验概率为
累积分布函数是
其中 N 是某个归一化常数。
但是现在让我们假设我们用方差来代替标准差。将 u=σ代入累积分布函数,我们得到
因此,我们看到选择σ上的一致先验等价于选择不适当的先验
超方差。一般来说,如果 u=φ(θ ) 是参数化似然函数的另一种方式,其中φ是某种单调的一对一函数。那么 u 上的一致先验等价于选择一个先验
超过θ。
那么,如果选择对参数化敏感,什么时候使用统一的先验有意义呢?
让我们考虑观察值 y ^⊤ y 的变化是如何影响可能性的。
具有零均值、
n=10 和不同的 y ^⊤ y 值的正态分布数据的标准差的似然函数。
正如我们从图中看到的,随着 y ^⊤ y 的增加,似然函数的形状发生了变化:它变得不那么尖锐并且更加分散。
注意,我们可以将似然函数改写为
在哪里
因此,在参数 log σ中,可能性具有以下形式
在哪里
我们说似然函数是对数σ中的数据转换,因为除了位置和观察值仅用于移动曲线之外,关于似然曲线的一切都是已知的。
均值为零、
n=10、 y ^⊤ y 不同值的正态分布数据的对数标准差的似然函数。
当似然函数是参数中的转换数据时,对非信息先验使用统一函数是有意义的。在观察数据之前,我们没有理由选择一个参数范围[a,b]而不是另一个相同宽度的范围[t + a,t + b],因为如果观察到的数据平移 t,它们相对于似然曲线的位置是相等的。
现在,让我们回到挑选我们的前科。
挑选正则化贝叶斯线性回归先验
对于参数σ,我们使用无信息先验
这相当于在参数 log σ上使用统一的先验。对于 w ,我们想要一个收缩权重的信息先验,反映权重不可预测的先验信念。让η表示控制
收缩程度的超参数。然后我们使用协方差矩阵为(σ/λ_η) I 的球形正态分布
请注意,我们还没有描述η如何参数化λ,我们还将对η进行积分,因此我们另外有一个η的先验(称为超先验),因此
我们的目标是先验 P(η)是无信息的。所以我们想知道:在什么参数化中,P( y |η)会被数据翻译吗?
收缩先验如何参数化?
在考虑如何参数化λ之前,我们先来刻画一下λ的似然函数。
展开被积函数,我们有
在哪里
和
注意#1 与 w 无关,因此关于 w 的积分等同于在非标准化高斯上的积分。
注意:回想一下归一化高斯积分的公式
因此,
接下来让我们考虑σ上的积分。
放
然后我们可以重写
在改变变量之后,我们可以把关于σ的积分表示为伽马函数的一种形式。
考虑一个积分
放
然后
和
其中γ表示伽马函数
因此,我们可以写
设 U 、σ和 V 表示 X
的奇异值分解,从而
让ξ₁,ξ₂,…表示σ的非零对角线元素。放λ=σ^⊤σ。那么λ是一个对角矩阵,有ξ₁,ξ₂,…和
注意:为了实现我们的算法,我们将只需要矩阵 V 和σ的非零对角元素,这可以通过部分奇异值分解来有效地计算。参见 LAPACK 函数 gesdd 。
放
那么我们可以把 h 和 g 改写成
和
这里我们采用术语
放
那么 r 是范围从 0 到 1 的单调递增函数,
我们可以认为 r 是特征向量的平均收缩因子。
现在,让我们通过用平均值替换单个特征向量收缩来进行近似:
将近似值代入似然性,我们就得到
我们看到近似的可能性可以表示为
因此,这种可能性大约是对数 r(λ)中的数据转换。
因此,如果我们
让η代表平均收缩率,我们可以获得近似无信息先验
并使用超级优先级
注意:为了求 r 的倒数,我们可以使用一个标准的求根算法。
对 r(λ)求导得到
利用导数和牛顿算法的变体,我们可以快速迭代得到 r⁻ (η)的解。
做预测
拟合贝叶斯模型的结果就是后验分布 P( θ | y )。让我们考虑在给定一个新的数据点 x 的情况下,如何使用该分布进行预测。
我们将从计算预期目标值开始
和
注意:为了计算包含η的表达式的期望值,我们需要对后验分布 P(η| y )进行积分。我们没有积分的解析形式,但是我们可以用一个自适应积分来高效精确地积分。
为了计算方差,我们有
和
从 E[σ | y ]开始,回想一下
和
因此,
注意:伽玛函数具有属性
所以,
和
因此
对于 e[ww^t|y],我们有
算法概述
我们已经看到,计算关于预测的统计数据涉及对后验分布 P(η| y )的积分。我们将简要地勾画出计算这种积分的算法。我们描述它只是为了计算 w 的期望值。其他期望值可以通过简单的修改来计算。
过程 SHRINK-INVERSE 应用牛顿算法用 r 和 r '求根来计算 r⁻。
为了计算超参数后验积分,我们利用自适应求积算法。在不同的求值点上,用加权和来近似积分。
一般来说,使用的评估点数越多,近似值就越精确。自适应求积算法比较不同细化级别的积分近似值,以逼近误差,并增加评估点数,直到达到所需的容差。
注意:我们省略了所使用的求积算法的细节,仅在较高层次上进行描述。有关具体求积算法的更多信息,请参考高斯-埃尔米特求积法和双曲正切法。
实验结果
为了更好地理解算法在实践中是如何工作的,我们将设置一个小的
实验数据集,并将贝叶斯算法的模型拟合与普通最小二乘法(OLS)和岭回归模型拟合进行比较,以便最小化数据集的留一交叉验证(LOOCV)的误差。
实验的全部源代码可以在 github.com/rnburn/bbai/example/03-bayesian.py 的 T2 获得。
生成数据集
我们将从设置数据集开始。对于设计矩阵,我们将使用均值为零的高斯和协方差矩阵 K 随机生成一个 20 乘 10 的矩阵 X ,其中
我们将从具有单位方差的球形高斯中生成具有 10 个元素的权重向量,并且我们将重新调整权重,使得信号方差等于 1。
那我们就开始吧
其中 ε 是从具有单位方差的高斯分布中提取的 20 个元素的向量。
下面是设置数据集的 Python 代码。
拟合模型
现在,我们将拟合贝叶斯岭回归模型、OLS 模型和具有正则化强度设置的岭回归模型,以便最小化 LOOCV 的均方误差。
我们可以使用以下等式来测量每个模型的样本外误差方差
这样做给了我们
模型的样本外性能
我们看到贝叶斯和岭回归模型都能够防止过度拟合,并获得更好的样本外结果。
最后,我们将比较贝叶斯模型和 OLS 模型的估计噪声方差。
这给了我们
σ的模型估计
结论
当将贝叶斯方法应用于岭回归时,我们需要解决:我们如何处理控制正则化强度的超参数?
一种选择是使用点估计,其中超参数的值被选择来优化一些度量(例如,可能性或交叉验证)。但是这种方法违背了使用概率分布表示参数可信度的贝叶斯方法,特别是如果可能性在超参数的特定值附近不是很强的峰值。
通常使用的另一种选择是应用超参数先验的已知分布(例如半柯西分布)。这种方法给出了超参数的后验分布,并且在实践中可以很好地工作,但是先验分布的选择有些武断。
在这篇博客文章中,我们展示了一种不同的方法,我们选择了一个超参数先验分布,以便近似无信息。我们开发了在给定非信息先验的情况下计算标准预测统计的算法,并且我们通过一个小例子证明了它比使用选择的超参数的点估计来优化留一交叉验证更有利。
附录 A:与其他贝叶斯算法的比较
这里,我们将对 scikit-learn 的贝叶斯岭回归算法做一个简单的比较。
Scikit-learn 的算法利用共轭先验,因此仅限于使用伽马先验,这需要四个任意选择的小值超参数。此外,它需要参数α和λ的初始值,然后根据数据进行更新。
算法的性能可能对这些参数值的选择很敏感,scikit-learn 的文档提供了一个曲线拟合示例,其中默认值表现不佳。
相比之下,我们提出的算法不需要初始参数;并且因为超参数被积分,表现差的值对后验概率质量贡献很小。
我们可以看到,我们的方法处理曲线拟合的例子,不需要任何调整。
完整的曲线拟合对比示例可在 github.com/rnburn/bbai/blob/master/example/04-curve-fitting 的获得。
本帖最初发表于buildingblock.ai/bayesian-ridge-regression。
如何建立一个代码搜索工具使用 PyTorch 变压器和骚扰
利用联合文本和代码嵌入进行搜索。
你有没有因为懒得自己写而在 google 上找一段代码片段?我们大多数人都是!那么从头开始构建自己的代码搜索工具怎么样?这就是我们将在这个项目中努力做的事情。我们将使用 StackOverflow 问题和相应代码样本的并行数据集来构建一个系统,该系统能够根据现有代码片段与自然语言表达的搜索查询的“匹配”程度来对它们进行排序。
如果你想尝试这种方法,在博客的末尾有一个 Colab 笔记本链接。
系统描述:
系统图:作者照片
我们试图建立一个系统,它能够接受用自然语言表达的问题,然后从成千上万的 Python 代码片段中返回与这个问题最匹配的代码片段。
它是如何工作的?
该系统将基于代码片段的学习嵌入和“如何做”问题的嵌入。搜索部分将使用 Annoy,这是 Python/C++中的近似最近邻实现。
数据:
我们将使用stat QC数据集,其中有从堆栈溢出中自动挖掘的(问题,代码片段)对。
数据集的样本如下所示:
问题:如何使用 python 从 MongoDB 中的 10 亿个文档中获取随机的单个文档?
代码:
import randomcollection = mongodb[""collection_name""]rand = random.random() # rand will be a floating point between 0 to 1.
random_record = collection.find_one({ 'random' => { '$gte' => rand } })
数据集有 85,294 个单代码片段答案和 60,083 个多代码片段答案。
预处理:
代码和问题都是字符串,所以我们需要在将它们输入模型之前对它们进行标记化。因为我们是在处理代码,所以我们不能使用常规的预先训练好的记号赋予器,因此必须自己构建。
首先,我们需要我们的标记器来拆分特殊字符,如“_”或“=”,并正确地拆分 camelCase 变量名。
我们分两步走:
- 在 camelCase 中,在特殊字符周围添加空格,在单词周围添加空格。
- 用空格预标记训练一个拥抱脸标记器。
这将产生以下结果:
问题- >
如何使用 python 从 MongoDB 中的 10 亿个文档中获取一个随机的单个文档?
标记化问题- >
['[CLS]','如何','到','得到',' a ','随机','单个','文档','从',' 1 ','比尔',' # #离子','文档','在','蒙戈',' db ','使用',' python ','?','[SEP]']
代码片段- >
class MyLabel(Label): pass
class AwesomeApp(App):
def build(self):
return MyLabel()
令牌化代码->
['[CLS]',' class ',' my ',' label ','(',' label ',')',':',' pass ',' class ',' awesome ',' app ','(',' app ',')',':',' def ',' build ','(',' self ',')',':',' return ',' my ',' label ','(',')',',','[SEP]']
ML 部分:
系统的 ML 部分。作者图解。
在这一部分中,我们将训练一个模型,它能够将一个字符串(代码片段或问题)映射到一个大小为 256 的固定维度向量。我们将应用于该输出向量的约束是,我们希望问题的向量与其对应的代码片段的向量之间的相似性高,而在所有其他情况下具有低的相似性。
我们使用双线性相似性度量:
其中 W 是可学习的参数。详见“通用音频表征对比学习”。
为了学习有用的嵌入,我们需要正面的例子,它们是成对的“如何做”问题和它们相应的代码片段。我们还需要一个反例,它将是该批中的所有其他向量。这意味着正对的表示将被推到更高的相似性得分,而我们将样本向量和批中所有不相关向量之间的相似性引导到更低的值。
x_i 和 y_j 是该批的嵌入向量。
我们希望批次矩阵尽可能接近恒等式。
这种进行对比学习的方法摘自上面提到的论文。它允许在某种程度上获得“自由”的反例,因为它们已经被计算为批处理的一部分。与其他方法(如三元组丢失)相比,它还有一个很大的优势,因为我们可以获得 batch_size -1 个负样本,而不是每个正样本只有一个负样本,这迫使编码器学习更多有区别的嵌入。
将文本输入映射到固定的 dim 向量的全部意义在于,它通过使用近似最近邻算法使搜索部分更加有效。
搜索部分:
一旦我们将所有的代码片段编码成向量,并建立一个模型以同样的方式编码一个新问题,我们就可以开始系统的搜索部分了。我们将使用一个名为的库来骚扰。
使用 Annoy 将允许我们在 O(log(n))时间内查询 n 个代码片段的数据集。
# We define the Annoy Indext = AnnoyIndex(len(samples[0]["vector"]), "angular")# We add all the vectors to the indexfor i, sample in enumerate(samples):
t.add_item(i, sample["vector"])# We then build the trees for the approximate searcht.build(100)# We can use it to query the NN of a question vectorindexes = t.get_nns_by_vector(search_vector, n=3, search_k=-1)
搜索查询的示例结果:
如何转义 HTML 特殊字符?
# Search Result 1 -->
raw_html2 = raw_html.replace('\\n', '')
# Search Result 2 -->
def escape(htmlstring):
escapes = {'\"': '"',
'\'': ''',
'<': '<',
'>': '>'}
# This is done first to prevent escaping other escapes.
htmlstring = htmlstring.replace('&', '&')
for seq, esc in escapes.iteritems():
htmlstring = htmlstring.replace(seq, esc)
return htmlstring
# Search Result 3 -->
mytext.replace(r"\r\n", r"\n")
# Query encoded in 0.010133743286132812 seconds
# Search results found in in 0.00034046173095703125 seconds
如何唯一化列表?
# Search Result 1 -->
seen = set()
L = []
if 'some_item' not in seen:
L.append('some_item')
seen.add('some_item')
# Search Result 2 -->
def is_duplicate(a,b):
if a['name'] == b['name'] and a['cost'] == b['cost'] and abs(int(a['cost']-b['cost'])) < 2:
return True
return False
newlist = []
for a in oldlist:
isdupe = False
for b in newlist:
if is_duplicate(a,b):
isdupe = True
break
if not isdupe:
newlist.append(a)
# Search Result 3 -->
>>> L = [2, 1, 4, 3, 5, 1, 2, 1, 1, 6, 5]
>>> S = set()
>>> M = []
>>> for e in L:
... if e in S:
... continue
... S.add(e)
... M.append(e)
...
>>> M
[2, 1, 4, 3, 5, 6]
M = list(set(L))
# Query encoded in 0.006329536437988281 seconds
# Search results found in in 0.0003654956817626953 seconds
我们可以看到,这个系统可以在几毫秒内,从 145,000 个可能的答案中找到相关的代码片段。
结论
在这个小项目中,我们训练了一个 transformer 模型来预测文本和代码的嵌入。这些嵌入然后被用来建立一个 KNN 搜索索引使用近似最近邻在苦恼。通过使用更大的问题/代码数据集或通过对不同的对比学习策略进行基准测试,这种方法还可以进一步改进。
您可以通过克隆存储库来运行自己的查询:
或者通过运行这个 colab 笔记本:
参考资料:
如何在 R 和 caret 中建立完整的分类模型
机器学习
一个完整的例子,展示了如何使用 R 和脱字符包来运行分类任务
r 是一种主要用于统计的编程语言,但它也为机器学习提供了有效的库。在本教程中,我描述了如何使用 r。
该任务包括以下步骤:
- 问题定义
- 数据集预处理
- 模特培训
- 模型评估
1 问题定义
这个例子的目的是通过 K-Neighbors 分类器来预测心脏病发作。这个例子使用了 hearts 数据集,该数据集在 CC0 公共领域许可下可在 Kaggle 上获得。
在我之前的文章中,我已经使用 scikit-learn 和 pycaret 用 Python 分析了这个数据集。在这篇文章中,我试图解决 r。
下图显示了数据集的摘录:
作者图片
作为输入特性,我考虑了所有的列,但是最后一列被命名为 output,我将其视为目标类。
为了解决这个问题,我使用了 caret 库,它可以按如下方式安装:
install.packages('caret')
caret 包(Cclass ificationAndREgressionTraining)对于分类和回归任务来说是一个非常有用的 R 包。它提供了预处理、模型训练、模型预测和模型评估的功能。
安装完成后,我如下导入插入符号包:
library(caret)
然后,我将 hearts 数据集作为数据帧加载:
df <- read.csv('heart.csv')
我还将种子设置为一个随机数,以使实验具有可重复性:
set.seed(12)
2 数据集预处理
现在,我转换数据集进行训练。我对数据集执行以下操作:
- 编码输出列
- 缩放和居中输入列
- 将数据集分成训练集和测试集
- 设置交叉验证方法
如前所述,我将输出列视为一个目标类,因此我将它编码如下:
df$output <- as.factor(df$output)
factor()
函数将向量编码为类别或因子。
然后,我通过缩放和居中来规范化输入列,如下所示:
preProcess <- c("center","scale")
简单地说,我定义了一个预处理变量,它包括两个操作:居中和缩放。然后,我将把这个变量作为输入传递给训练函数。
现在,我准备通过使用 caret 库提供的createDataPartition()
函数将数据集分成训练集和测试集:
i <- createDataPartition(y = df$output, times = 1, p = 0.8, list = FALSE)
该函数返回指定如何拆分数据的索引。我不得不 0.8 的百分比分裂。现在我分割数据集:
training_set <- df[i,]
test_set <- df[-i,]
最后,我通过定义以下变量来设置交叉验证,我将把这些变量作为训练函数的输入:
trControl <- trainControl(method = "repeatedcv",number = 10,repeats = 10)
我已经将方法设置为重复交叉验证,折叠次数设置为 10,重复次数设置为 10。
3 模型训练
我准备好训练模型了。我使用 caret 提供的train()
函数如下:
model <- **train**(output ~ ., method='knn', data = training_set, metric='Accuracy',preProcess = preProcess, trControl=trControl)
我已经将模型设置为 knn (K-Nearest Neighbors),将数据设置为training_set
,将优化度量设置为Accuracy
,将预处理技术设置为之前定义的preProcess
,将训练控制设置为之前定义的trControl
变量。
训练过程真的很简单😃
4 模型评估
一旦模型被训练,我就可以评估它的性能。我使用 predict()函数来预测测试集的输出:
test_set$pred <- predict(model, test_set)
为了计算指标,我必须将输出转换成一个因子,如下所示:
test_set$factor_pred <- as.factor(test_set$pred)
test_set$factor_truth <- as.factor(test_set$output)
现在,我计算精度:
precision <- **posPredValue**(test_set$factor_truth, test_set$factor_pred)
召回:
recall <- **sensitivity**(test_set$factor_truth, test_set$factor_pred)
混乱矩阵:
cm <- **confusionMatrix**(test_set$pred, test_set$output)
精确度可以从混淆矩阵中提取:
accuracy <- cm$overall[1]
我还计算了对应于混淆矩阵的表:
confusion_matrix <- cm$table
作者图片
为了绘制 ROC 曲线,我使用 pROC 库:
library(pROC)
test_set$pred <- predict(model, test_set,probability=TRUE)
roc_curve = **roc**(test_set$output, predictor=factor(test_set$pred,ordered = TRUE))
plot(roc_curve, col="red", lwd=3)
roc()
函数接收概率形式的预测,所以我通过 predict()函数设置probability=TRUE
再次计算预测。
作者图片
roc()
函数并不绘制实际的 ROC 曲线,而是绘制灵敏度对特异性曲线。实际的 ROC 曲线绘制的是灵敏度对特异性。
摘要
恭喜你!您刚刚学习了如何在 R 中运行一个完整的分类任务!该示例使用了 caret 包,其中包括用于模型定型和评估的函数。
您可以在我的 Github 资源库中找到本文中描述的完整示例。
请继续关注,了解一些关于 R 的新知识!
如果你读到这里,对我来说,今天已经很多了。谢谢!你可以在这篇文章中读到更多关于我的信息。
相关文章
来自社区
机器学习
View list6 stories
评估指标
View list2 stories
数据预处理
View list12 stories
参考
如何不用代码轻松构建一个计算机视觉项目
一个初学者友好的,无代码的水果探测器解决方案。还有,把模型上传到网上给大家看看!
凯文·克罗斯比在 Unsplash 上拍摄的照片
⚠️读了我在⚠️博客中的原帖
要不要建个 app 检测什么东西?猫对狗,检测一个水果有多熟,在图像中寻找品牌?
你想仅仅标记一些图像,制作一个模型并测试它而不需要做很多工作吗?
如果你的答案是肯定的,那么这篇文章是给你的!
我将向您展示如何为您的探测器构建一个应用程序,并将其放入互联网供所有人查看。
最后,你会有这样的东西给你的同事和朋友看:🤗https://huggingface.co/spaces/Kili/plastic_in_river
您将能够上传一个测试图像,模型将返回盒子和标签。太神奇了!⚡️
免责声明:你需要在你的电脑上安装 git 来上传文件到 HuggingFace Spaces。如果没有,也不用担心!它非常容易安装。跟着这个:https://git-scm.com/downloads
这将是该项目的工作流程:
项目的工作流程
- 首先,你必须为你的项目收集图像。要不要从长颈鹿身上检测出斑马?获取两只动物的图像。无论你想探测什么,你都需要图像。这个点在工作流程中是白色的,意味着你必须在你的电脑上完成工作。
- 标签图像在工作流程中显示为蓝色,这是因为您将使用 Datature 的标签工具。 Datature 是一家专门为数据标注和模型训练构建用户友好工具的公司。
- 您还将使用 Datature 的工具来训练一个模型,以一种无代码且非常简单的方式。
- 一旦模型被训练,你将把它下载到你的电脑,把所有的文件放在一起(这些文件我会提供给你)
- 当所有文件放在一起时,您将把它们上传到🤗HuggingFace Spaces 和您的模型就可以使用了!🚀
1.查找图像
在计算机视觉项目中,我们需要做的第一件事是收集图像。如果我们想训练一个深度神经网络,我们需要成千上万的图像。
幸运的是, Datature 使用非常先进的模型,并且可能经过预先训练,这意味着我们只需要从头开始训练模型时所需图像的一小部分。
每个类大约有 100 张图片就足够了。例如,如果你想检测 t 恤和裤子,你需要 100 张 t 恤和 100 张裤子的图像。这个例子当然也适用于其他情况。例如,你可以有 100 张有猫和狗的图片,所以你得到 100 个猫的例子和 100 个狗的例子。
如果存在类别不平衡也没关系,例如,如果您的项目是检测晴天和多云,您可以有 120 张晴天图像和 100 张多云图像。但重要的是,模型有最少数量的图像,100 左右应该足够了。
收集所有图像,并将它们存储在电脑的一个文件夹中。
2.标签图像
在数据中创建一个账户,并为您的用例创建一个项目。来自 Datature 团队的这个教程解释了如何创建一个项目和标记图像。
https://data ture . io/blog/train-and-visualize-face-mask-detection-model
这篇博文详细介绍了如何:
- 创建 Datature Nexus 帐户(免费试用)
- 创建项目
- 上传图像
- 创建类
- 注释图像
- 在图像中创建矩形框
- 给每个盒子分配一个类别
对于每个图像,您将注释一个框(对象在哪里?)和一个类(这个对象是什么?).
只读标签部分,之后,在项目概述中,你应该看到你的图像统计,标签分布等。例如,项目概述应该是这样的:
标注后的项目概述示例
在这个例子中,我有一个名为香蕉的项目,我标记了 16 个图像,我有 3 个类别:成熟、可食用和无效。这只是一个例子,所以要确保每门课至少有 100 个例子!
3.火车模型
一旦我们有了图像,我们就可以训练我们的模型了!我们必须在 Nexus 中创建一个“工作流”。尝试使用上一节的文档和博客文章:https://data ture . io/blog/train-and-visualize-face-mask-detection-model来执行以下步骤:
- 建立训练工作流程:选择训练-测试分流比,选择增强,选择模型设置
- 火车模型
- 监控模型:丢失、精度和召回
- 导出模型
该模型将需要大约 1 小时的训练,之后你应该会看到这一点
完成培训示例
转到工件并下载张量流模型
工件下载示例
当在计算机中导出一个. zip 文件并带有训练好的模型参数时,本节就完成了。
4.创建一个🤗HuggingFace 帐户
模型已经训练好了,我们已经把它作为. zip 文件下载到我们的计算机上。但是我们如何与之互动呢?
我们可以通过上传到 Huggingface Spaces 与它互动。我们还需要一些网站前端的代码,这些代码你可以在本教程中找到。
Huggingface Spaces 是 Huggingface 的一个网站,人们可以在这里展示自己的模特并与她们互动。按“最喜欢”对空间进行排序,并浏览一些空间:)
这些是步骤
- 创建 Huggingface 帐户
- 创建一个空间
- 为空间写一个名称。请记住,该网站将是公开的,因此请选择一个与该应用程序的功能相匹配的名称!例如:香蕉分析或类似的东西
- 选择 Streamlit 作为 Space SDK
- 选择公共
- 完成空间分配后,将存储库克隆到本地计算机上的一个文件夹中
- 或者,使用文本编辑器打开 README.md 并更改项目的表情符号
5.收集所有文件并上传到🤗拥抱面部空间
现在我们有了属于🤗我们电脑里的空间。我们必须将所有文件复制到那里,并将所有内容上传到🤗使用 git 的空间。
首先,将模型文件(saved_model/ folder,label_map.pbtxt 文件)复制到该文件夹中
然后,在文件夹中创建这个 Gist 中的 3 个文件:https://Gist . github . com/anebz/2 f 62 caea B1 f 24 AABB 9 F5 D1 a 60 a4 C2 d 25
app.py
该文件包含上传图像、加载模型、进行预处理以及从模型中获取预测的代码。
请注意带有#TODO 的行,您必须更改这些行!
尤其是第 112–115 行中的 color_map,这些是每个类的方框的颜色。打开 label_map.pbtxt 文件,查看为每个类分配了什么 label_id,并使用此 label_id 为颜色分配 RGB 值。在这个例子中,我只有两个类,因此只有两种颜色。如果有更多的类,请按照示例的格式添加更多的行:
1: [255, 0, 0],
记住,除了最后一行,每一行的末尾都要有一个逗号!
packages.txt 和 requirements.txt 是将要安装在🤗空间。这些文件非常重要,没有它们代码将无法运行。
最终,文件夹应该是这样的
文件夹概述
- saved_model/ 是位于。你之前从 Datature 下载的 zip 文件
- label_map.pbtxt 在。你之前从 Datature 下载的 zip 文件
- 。gitattributes 已经在文件夹中了🤗空间
- README.md 在您从🤗空间
- app.py 是你用我在文章前面写的代码创建的文件
- requirements.txt 是您用我在本文前面写的代码行创建的文件
- packages.txt 是您用我在本文前面写的代码行创建的文件
一旦我们需要的所有文件都在文件夹中,我们就可以把它推到🤗空间。打开 Git Bash 并逐个粘贴这些命令:
- git 添加。
- git commit -m“添加的文件”
- git 推送
该应用程序将需要一些时间来上传文件,尤其是模型文件。git 推送完成后🤗Space 需要几分钟来构建应用程序,并在中显示我们的应用程序🤗空间。
如果 git 显示关于模型文件太大的错误,请查看这些帖子:https://discuse . hugging face . co/t/uploading-large-files-5gb-to-HF-spaces/12001/4和https://discuse . hugging face . co/t/uploading-files-big-than-5gb-to-model-hub/4081/6
最后你的 app 会出现类似这样的:https://huggingface.co/spaces/anebz/test
你可以上传一张图片,模型需要几秒钟加载,然后你会看到预测。项目完成!🏋️
结论
你的项目完成了,恭喜你!!你能够从零开始快速创建一个应用程序,只使用几百张图片。你只需要在你的电脑上安装 Git,不需要 Python 或者不需要编写任何代码。
⚠️‼️如果你试图做这个项目,遇到错误或困难,不要犹豫,与我联系!我将非常乐意帮助你。
感谢您的阅读!
如何从零开始构建数据湖—第 2 部分:连接组件
如何利用流行技术构建数据工程沙盒的完整教程
在这一系列文章中,我将指导您建立自己的数据湖基础设施作为数据工程沙箱。在这一部分中,我将展示如何连接我们的数据湖基础设施的各种服务。在第一部分中,我已经展示了如何用 docker 托管必要的服务,并解释了各个配置选项。
一旦组件“相互对话”,您将能够实施自己的数据工作流,并将技术和大数据方法用于自我测试!您将能够利用该平台来了解设置、实施附带项目、概念验证、使用案例或使用这些技术来学习其他教程。大多数数据任务可以通过这种基础设施实现自动化。在“生产”环境中,服务也可以作为 docker 化的服务托管在 AWS EC2 实例上,但是对于我们的沙箱,使用 docker 在本地托管它们就足够了。
图片由 Unsplash.com 的加勒特·西尔斯拍摄
我们使用以下技术组合:
- Apache NiFi 来处理和分发数据。
- Apache NiFi Registry 用于存储、管理和版本控制 NiFi 资源。
- Apache Airflow 以编程方式创作、安排和监控工作流。
- Postgres 作为一个对象关系数据库。
- pgAdmin 作为 postgres 数据库的管理和开发平台。
- MinIO 作为本地托管的、S3 兼容的对象存储。
- 码头工人来主持我们的服务。
著名的Hello world!
最早是在 Brian Kernigsham 的《语言 B 入门教程》一书中提到的,后来因《C 编程语言》一书而出名(来源)。如今,许多教程仍然使用将Hello world!
写入终端的任务来检查用户是否已经完成了设置阶段,并准备好投入编码挑战。
在本文中,我们将实现服务间通信的Hello world!
:通过设置服务交互的超级简单的例子。我将指导您为每一对需要相互通信的服务建立连接。之后,您将能够继续自己的工作,充分利用数据湖基础设施的全部功能。
如果您还没有设置 docker 容器,也还没有运行您的组件,那么请继续阅读本系列的第 1 部分。我们将从停止的地方继续:我们将 docker-compose.yml 文件从这里复制到我们的本地计算机,并使用docker-compose up
启动服务。
到目前为止,我们的服务仍未连接,但是我们的目标基础设施将如下所示:
数据湖组件—由作者创建的图像。维基百科的图标。
在以下章节中,我们将连接:
- postgres 数据库的 pgAdmin
- Apache NiFi 到 NiFi 注册表(反之亦然)
- Apache NiFi 到 postgres 数据库
- 阿帕奇 NiFi 到 MinIO
- 到 postgres 数据库的 Apache 气流
- 阿帕奇气流到阿帕奇尼菲
- 阿帕奇气流到 MinIO
让我们直接进入 pgAdmin 的设置吧!
pgAdmin
服务运行后,您可以在浏览器中访问 pg admin:http://localhost:5050/
如果您在启动 docker 容器后第一次访问该服务,它会要求您设置一个主密码。选择一个你能记住的密码。
我们想通过连接到 postgres 数据库并对该数据库运行一个简单的查询来从 pgAdmin 对其说Hello world!
。
pgAdmin:你好,postgres 数据库
单击页面中间“快速链接”下的“添加新服务器”,或者右键单击左上角的“服务器”,然后选择“创建”->“服务器…”。
我们需要配置连接细节以添加新的数据库服务器:
- 在常规选项卡中:为您的数据库服务器选择一个名称,例如
postgres_db
- 在连接选项卡中:“主机名/地址”是而不是“本地主机”,而是postgres 容器的 IP 地址——因为容器需要通过 docker 网络相互通信。因为我们在一个用户定义的网络(
dataworld
)上,我们可以只使用主机名mypostgres
而不是固定的 IP 地址,让 docker 在后台处理 DNS 解析。 - 在连接页签中:端口是 postgres 数据库的标准应用端口—
5432
。 - 在连接选项卡中:用户名和密码在
docker-compose.yml
中被指定为 postgres 服务的环境变量(如果还没有更改的话,则为postgres
和postgres
)。
连接设置—由作者创建的图像。
除了使用主机名,我们还可以通过获取 postgres 容器的 ID 并检查它以检索其 IP 地址来标识我们的数据库:
获取容器 ID:
检查容器,将返回的行过滤为 IP 地址为:
这是相当麻烦的,特别是因为每当我们重启我们的容器时,我们将不得不重新开始,因为 docker 网络中容器的 IP 地址可能会改变。使用主机名并让 Docker 在我们在 docker-compose.yml 中定义的用户定义的网络中解析它要容易得多。
连接到数据库后,我们现在可以运行查询了。右击数据库,选择查询工具。
pgAdmin 中的查询工具—由作者创建的图像。
为了测试一切是否正常,让我们运行下面的查询来检查连接——我们自己的小版本“hello world!”。sql :
恭喜你!PgAdmin 现在连接到 postgres 数据库了!
阿帕奇尼菲
如果您的 docker 服务正在运行,您将能够通过http://localhost:8091/NiFi/联系到 NiFi。注意:您可能会看到消息The Flow Controller is initializing the Data Flow
。NiFi 将需要一分钟(在您启动服务之后)才能到达应用程序,因为领导者选举周期需要首先完成。
我们希望连接到:
- NiFi 注册表
- postgres 数据库
- 米尼奥
你好,NiFi 注册中心
为了将 NiFi 连接到 registry,我们首先需要在 registry 中创建一个“bucket”来存储和组织我们的数据流。继续操作并打开位于http://localhost:18080/nifi-registry/的注册表。
- 单击窗口右上角的扳手符号。
- 点击右侧的“新桶”。
- 为您的存储桶输入一个名称,例如
myfirstbucket
。
NiFi 注册表—创建新的存储桶—图片由作者创建。
我们现在可以将 NiFi 的流程组和流程存储在新创建的 bucket 中。
请注意,默认情况下没有配置任何权限。在这个实例中,有权访问注册表的每个人都可以查看、创建和修改存储桶。有关保护系统的信息,请参见系统管理员指南。
前往http://localhost:8091/nifi/,点击右上角的three bars
进入controller setting
。然后点击选项卡registry client
和右侧的plus-symbol
。
选择任何你喜欢的名字,并添加以下网址:http://myregistry:18080
。Docker 将再次在 docker 网络上将主机名解析为容器的 IP 地址。
Nifi —添加注册中心客户端—由作者创建的图像。
既然我们已经向 NiFi 添加了注册客户机,那么让我们测试它的功能:创建一个新的进程组,其中包含一个或两个虚拟处理器。
右键点击流程组,选择Version
->-Start version control
:
Nifi —启动过程组的版本控制—由作者创建的图像。
现在我们能够选择我们想要使用哪个注册中心和存储桶来进行版本控制(如果我们已经配置/创建了多个的话),以及在注册中心中应该以哪个名称对流程组进行版本控制。输入名称,还可以选择输入描述和版本注释。
NiFi —将流文件版本保存到由作者创建的注册表图像中。
单击“保存”后,您会注意到流程组的左上角有一个绿色复选标记。这意味着组的当前状态被保存到桶中!如果我们更改了内部的某些内容,例如将处理器移动到另一个位置、更改某些配置或添加/删除处理器,复选标记将会被一个灰色的星号取代。这个星号象征着对底层流程的一些未提交的更改。
NiFi —过程组版本控制状态的变化—由作者创建的图像。
要在注册表的桶中存储最新的更改,右键单击处理器组,然后单击Version
- > Commit local changes
。绿色复选标记将再次出现。如果我们想要放弃更改,我们可以选择Revert local changes
,过程组将被重置为保存到注册表的最新版本。Local(在注册表的上下文中)是指 Nifi 实例,而不是您的本地计算机。
NiFi —提交本地更改—图片由作者创建。
我们现在已经有了 Apache NiFi 数据流和 ETL 管道的完整版本控制系统!我们可以检查本地更改,将它们提交到注册表中,或者从注册表中取出最新版本的进程组。对我们的工作进行版本控制,并且能够跟踪变更,这极大地改善了我们的开发工作!
当我们创建一个新的进程组时,我们甚至可以从注册表中导入一个存储的进程组的特定版本(作为一个模板):
NiFi —从注册表导入模板—由作者创建的图像。
在接下来的几章中,当我们连接到其他服务时,请随意使用这个特性!
Apache NiFi:你好 postgres 数据库
为了能够查询 postgres 数据库,我们需要配置:
- 一个
DBCPConnectionPool
,它包含数据库的连接细节 - 微型工作流程:
- 第一个处理器创建一个空的流文件来触发后续的处理器
- 第二处理器执行对数据库的查询
- 第三个处理器用于在查询执行后查看队列中的数据。
JDBC 控制器 postgres
当创建控制器服务时,总是在需要它们的最顶层进程组中创建它们——甚至可能是根进程组。控制器服务只能在创建它们的组以及所有后续子组中访问。
为了能够设置连接到 postgres 数据库的控制器服务,我们需要下载 postgres 的当前 JDBC 驱动程序,例如从这里。下载完成后,将postgresql-42.3.1.jar
文件(或您使用的任何版本)复制到 docker 挂载的目录/nifi/jdbc/
。这个过程对于任何其他数据库都是一样的,我们总是需要将 NiFi 指向 jdbc-driver jar-file。
通过左侧当前过程组的gear-symbol
按钮进入 NiFi 中的控制器配置。在Controller services
选项卡中,点击右侧的plus-symbol
添加一个新控制器。从可用控制器的长列表中选择DBCPConnectionPool
并点击Add
。
编辑新创建的控制器的属性,如下所示:
- 数据库连接 URL:
jdbc:postgresql://mypostgres:5432/postgres
- 数据库驱动类名:
org.postgresql.Driver
- 数据库驱动位置:
/opt/nifi/nifi-current/jdbc/postgresql-42.3.1.jar
(注意,我们配置的是 docker 容器内部的路径,而不是本地机器上的路径!) - 数据库用户:
postgres
(或您在设置过程中更改的任何名称) - 密码:
postgres
(或您在设置过程中更改的任何密码)
NiFi—JDBC 控制器的属性—微型工作流程:
点击Apply
并通过选择描述新创建的控制器的线的lightning-symbol
并在打开的窗口中选择Enable
来启用服务。
处理器
为此版本的Hello world!
创建三个处理器:
- 处理器:GenerateFlowFile——作为我们数据流的起点。
- 处理器:ExecuteSQL —在 postgres 数据库上执行查询。
- Processor: RouteOnAttribute —作为一个虚拟处理器,这样我们可以查看队列中的流文件。
用success
流程按顺序连接处理器。
生成流文件
在GenerateFlowFile
处理器中,将调度选项Run Schedule
更改为60 sec
,并将调度选项Execution
更改为Primary node
。这样,我们可以确保无论何时启动处理器时,主节点都会创建一个流文件,从而触发我们的 ETL 管道。每隔 60 秒就会创建另一个流文件——除非我们事先停止了处理器。这是一个简单的技巧,可以精确地触发我们的流水线一次:在调度时间再次完成之前启动然后停止GenerateFlowFile
处理器。
NiFi —调度处理器—图片由作者创建。
执行 SQL
在ExecuteSQL
处理器中,选中主配置中failure
旁边的复选框,以便在查询失败时自动终止进程。在properties
选项卡中,将Database Connection Pooling Service
属性更改为新创建的postgresql_connectionpool
,并将字段SQL select query
编辑为数据库连接的测试查询。一个例子可能是:
如果您的 DBCPConnectionPool 没有出现在可用的控制器服务列表中,请确保您已经在同一个处理器组或其上的任何处理器组中创建了 DBCPConnectionPool。不能选择当前组之外或之下的流程组的控制器服务!
NiFi —配置 executeSQL 处理器—图片由作者创建。
我们不需要配置最后一个处理器,因为我们只是将它作为一个替身来使用,以便能够检查通向它的队列中创建的流文件。您的处理器流程应该如下所示:
NiFi —处理器流程—图片由作者创建。
一旦启动了前两个处理器,就会创建一个流文件,并触发 ExecuteSQL 处理器。ExecuteSQL 处理器之后的流文件现在将包含我们从数据库中查询的数据。您可以通过右击队列并选择List queue
来检查数据。您可以下载队列中的每个项目,或者通过单击右侧的符号在浏览器中查看其内容。
NiFi —检查队列的流文件—作者创建的图像。
浏览器检查(格式化视图)中的流文件内容如下所示:
NiFi —队列中的文件内容—作者创建的图像。
这意味着我们已经成功地从 NiFi 查询了数据库!我们离全功能数据湖架构又近了一步!
阿帕奇·尼菲:你好,米尼奥
在我们连接 NiFi 之前,我们必须配置 MinIO。您可以在浏览器中的http://localhost:9001/dashboard下访问该服务。用户名和密码通过环境参数MINIO_ACCESS_KEY
和MINIO_SECRET_KEY
在 docker-compose.yml 文件中配置。除非您在创建容器之前更改了它们,否则它们是minio_admin
和minio_password
。
配置 MinIO
点击左侧导航栏中的Buckets
,点击右上角的Create Bucket
。为您的存储桶选择一个名称,例如miniobucket
,保留默认配置并点击Save
。请注意如何命名您的存储桶,名称必须在 3 到 63 个字符之间,并且只能由小写字母、数字、点和连字符组成!
MinIO bucket —作者创建的图像。
创建 bucket 后,在本地创建一个名为minio_testfile.txt
的新文件,内容为This is the content of a testfile from MinIO.
。
选择您的桶并点击Browse
。创建一个名为test
的新目录,并在其中点击Upload file
符号上传minio_testfile.txt
。在下一步中,我们将配置 NiFi 从 MinIO 中检索这个文件!
MinIO 桶内容—由作者创建的图像。
配置 NiFi
为了能够在 NiFi 中创建从 MinIO 检索文件的管道,我们还需要配置 NiFi。在本地绑定挂载的目录/nifi/credentials/
中创建一个名为credentials.properties
的文件。
该文件的内容是 MinIO 的环境变量的值——如果您没有在您的 docker-compose.yml 文件中更改它们,credentials.properties
文件的内容将是:
如有必要,更改键值。
转到http://localhost:8091/nifi/并创建一个新的进程组。在组内,为GenerateFlowFile
、FetchS3Object
和RouteOnAttribute
类型各创建一个处理器。用success
关系连接处理器。由于 MinIO 与 S3 兼容,我们可以将 NiFi 的所有 S3 处理器与 MinIO 端点一起使用!
NiFi —处理器流程—图片由作者创建。
再次更改GenerateFlowFile
处理器的调度选项Run Schedule
到60 sec
以及调度选项Execution
到Primary node
。这样,我们可以确保无论何时启动处理器,都会创建一个流文件,触发我们的 ETL 管道。
在FetchS3Object
处理器中,勾选复选框以自动终止failure
上的关系,并配置以下属性:
- 桶:
miniobucket
- 对象键:
test/testfile.txt
(我们需要配置桶内的完整路径,包括目录) - 端点覆盖 URL:
http://myminio:9000
(用我们的私有 MinIO 实例之一覆盖 AWS S3 的端点) - 凭证文件:
/opt/nifi/nifi-current/credentials/credentials.properties
(容器内指定的路径)
NiFi—fetchs 3 对象处理器配置—图片由作者创建。
如果您想为 NiFi 创建一个单独的技术 MinIO 用户,您只需更新本地目录中的credentials.properties
文件。
运行您的管道——您可以通过启动和停止GenerateFlowFile
处理器或右键单击它并选择“恰好运行一次”选项来完成此操作。通过右键单击通向RouteOnAttribute
处理器的队列,我们可以检查流文件。
NiFi —检查队列的流文件—作者创建的图像。
我们现在可以验证我们的文件确实被 NiFi 检索和加载了:
NiFi —流文件内容—由作者创建的图像。
恭喜,我们又连接了两个服务!我们现在可以从 MinIO 和 postgres 数据库中检索和写入数据。如果我们以后从 MinIO 切换到实际的 S3 存储,我们只需删除被覆盖的端点 URL 并更新我们的凭证文件。
气流
为了让 Airflow 能够连接到 MinIO(以及 S3 或其他 S3 兼容的存储设备),我们需要在 Airflow 服务上安装一个 python 包。我们可以通过挂载一个requirements.txt
文件来做到这一点。在本地挂载的目录(./airflow/requirements/requirements.txt
)中创建以下文件,内容如下:
创建文件后,我们需要重启 docker 服务。启动时,Airflow 会自动安装文件中提到的所有软件包。当 docker 检查必要的包时,这可能会使启动延迟几秒钟,但不会太长。
一旦你完成了这个准备步骤,让我们到达气流中的Hello world!
。
阿帕奇气流:你好 postgres 数据库
在我们创建任何代码之前,我们需要在 Airflow 中配置连接细节。在http://localhost:8085/admin/的浏览器中打开服务,点击顶栏中的Admin
- > Connections
。默认情况下,Airflow 附带了许多连接,但是让我们为我们的目的创建一个新的连接。
点击Create
,填写必要的详细信息:
Conn Id
:mypostgres_connection
-稍后我们可以用它来检索连接细节的 ID。Conn Type
:Postgres
-从下拉菜单中选择。Host
:mypostgres
- Docker 将解析主机名。Schema
:postgres
-数据库名称(该标签具有误导性)Login
:postgres
-或者您在 docker-compose.yml 文件中设置的用户名。Password
:postgres
-或者您在 docker-compose.yml 文件中设置的任何密码。Port
:5432
-docker 网络中数据库的标准端口。
点击保存:
气流连接-由 autor 创建的图像。
现在我们可以开始写 DAG 了。DAG(有向无环图)是气流的核心概念,它定义了任务、它们的依赖关系和时间表(在这里阅读更多内容)。
DAG 指定任务,更重要的是,指定任务应该执行的顺序。我们甚至可以将任务配置为仅在一个(或多个)先前任务失败时执行。Airflow 附带了许多所谓的任务“操作符”——这意味着我们可以用 Python、Bash、Druid、Hive、MSSQL 甚至 PostgreSQL 等等编写任务!所有 Dag 都是 Python 文件,但是操作符中的代码取决于操作符的类型。
例如,我们可以使用 postgres 操作符来执行 postgres 数据库中的 SQL 代码。或者,我们可以使用 python 操作符编写一个小的 python 程序,该程序反过来在数据库上执行查询。我们选择哪种方案取决于我们的用例。为了这个Hello postgres database!
,让我们创建一个简单的 postgres 操作符,它将在我们的数据库中创建一个空表。
注意:根据您的 Airflow 版本,您需要不同的导入路径。本文的 docker-compose.yml 文件中使用的 docker 映像使用了旧版本1.10.9
。我在代码摘录中包含了新的 Airflow 版本的导入路径。
在本地挂载的目录下创建一个文件:airflow/dags/hello_postgres.py
,内容如下:
为了能够多次执行 DAG,我们在 DAG 中有两个任务:第一个任务删除已经存在的表,第二个任务创建表。如果我们不包括第一个任务,DAG 将在第二次和任何后续执行中失败,因为它无法成功执行创建查询。通过参数postgres_conn_id
传递连接细节,我们不必担心代码中的主机名、用户名或密码。
保存文件,等待它出现在你的网页浏览器的DAGS
视图中。根据您的 DAG,这可能需要一些时间。一旦它被列出,在左边激活它,并点击“触发 DAG”在右手边。
我们现在可以在 pgadmin 的界面中验证创建的表:
pgAdmin —表格的验证—由作者创建的图像。
恭喜你!我们现在能够从 Airflow 调度任务来执行数据库上的代码!
阿帕奇气流:你好阿帕奇尼菲
从 Airflow DAG 连接到 NiFi 使我们能够更新处理器属性、更改处理器的内容(如 sql 语句)、启动或停止处理器、列出/更改/启动控制器等等。Apache NiFi 为多种配置目的提供了一个深入的 REST-API。我们可以检索和配置对象,如控制器、流、处理器、处理器组、端口、标签、漏斗、策略,甚至将事务提交到特定的输入端口。对于我们的Hello world!
目的,我们将创建一个简单的 GET 请求。您是使用 API 的包装库,如 nipyapi 还是使用官方 REST-API 编写自己的逻辑和请求,取决于您的用例。我个人喜欢直接使用 REST API,因为它的文档非常详细。
首先,让我们为 NiFi 服务创建一个气流连接,如下所示:
Conn ID
:mynifi_connection
Conn Type
:Postgres
由于没有NiFi
连接类型,因此我们使用 postgres 作为替身。Host
:http://mynifi
Port
:8080
这是网络内部的端口,不是我们对外映射的那个!
气流连接-由 autor 创建的图像。
接下来,我们需要创建一个 DAG。我利用请求库来创建对GET /nifi-api/processors/{id}
REST-API 端点的请求。在文档中我们可以看到必要的 URI 和预期的回报——一个 ProcessorEntity JSON 对象:
NiFi REST API 文档—由 autor 创建的图像。
为了检索连接细节并在脚本中构建我们的 URI,我们使用了 Airflow 的 BaseHook 模块,并将我们的连接 ID ( mynifi_connection
)传递给它。如果您使用下面的脚本,不要忘记将 processor_id 字符串改为您自己的!
根据您在生产中的设置,您将首先需要通过端点POST /nifi-api/access/token
检索带有用户名/密码组合的访问令牌。之后,您必须在下面的代码中添加不记名令牌。幸运的是,在我们简化的设置中,这是不必要的。我们可以对 REST API 进行未经验证的调用,如下所示:
如果您按照说明操作,您将能够在 DAG 的日志中看到以下信息行:
如果是,那么恭喜您,我们连接了服务!您现在可以基于这个Hello world!
构建工具和 API 调用来配置处理器或启动/停止处理器。如果您有进一步的兴趣,查看我的文章,了解如何通过执行以下模式将气流与成熟的 ETL 管道连接起来:
- 预定气流 DAG 执行准备任务,
- 气流触发了 Apache NiFi 中的处理器,
- NiFi 执行一个 ETL 过程,
- 气流等待 NiFi 完成,
- 气流继续执行其他任务。
但是够了,下一章在等着你!我们就要完成了,所以如果你已经走了这么远,感谢你的关注!我不会耽搁你太久——让我们一起完成这个项目和我们的下一(也是最后一)章吧!
阿帕奇气流:你好米尼奥/S3
Airflow 提供了一个 S3Hook,我们可以使用它无缝连接到 S3 或 S3 兼容的存储设备,如 MinIO!如前所述,为了使用钩子,我们需要在我们的 Airflow 服务上安装包boto3
,方法是在我们的本地airflow/requirements/requirements.txt
文件中添加一行boto3
,并重启 Airflow docker 服务。虽然我们不会直接导入boto3
,但如果没有它,我们将无法使用 Airflow 的airflow.hooks.S3_hook
模块。
重启气流后,在Admin
->-Connections
GUI 下建立新的连接:
Conn ID
:myminio_connection
Conn Type
:S3
由于没有NiFi
连接类型,因此我们使用 postgres 作为替身。Extra
:由以下 JSON 组成:
不要忘记用您自己的密钥替换访问密钥,您可能已经在您的 docker-compose.yml 文件中覆盖了这些密钥。
气流连接——图片由作者创作。
为了最初在 MinIO 中与文件交互,我们将实现两个简单的操作:将文件写入 MinIO 和从 MinIO 中的文件读取。为此,S3Hook 提供了两个简单易用的函数:load_file
和read_key
。
在您的本地airflow/dags
存储库中创建一个新的 DAG(例如,名为hello_minio.py
)并复制粘贴下面的代码。第一个任务将把一个名为my-test-upload-file.txt
的文件上传到我们的 MinIO bucket 中的test
目录。
执行 DAG,完成后,检查操作是否成功:
- 在 MinIO 中,您应该在
test
目录的miniobucket
桶中找到一个新文件。 - 在任务的气流日志中,您应该能够看到下面的行
File contents: 'This is the content of a testfile from MinIO.'.
,描述了之前测试文件的文件内容。请注意,我们在这里使用的文件与我们在前面的 Hello-MinIO-from-NiFi 示例中为 NiFi 使用的文件相同。
连接设置完成后,我们现在可以开始使用连接的组件了!
回顾和总结想法
在这篇文章中,我们了解到
- 如何配置我们的服务,
- 如何把我们的服务互相连接起来,
- 如何利用整体基础设施和
- 服务之间如何交互和通信。
我邀请您在这个超级简单但广泛的基础设施上进行测试、试验和实现概念验证。大多数数据工程任务都可以使用现有的工具来实现!
作为一个快速提醒,我们可以使用
- Apache NiFi 处理和分发数据。
- Apache NiFi Registry 用于存储、管理和版本控制 NiFi 资源。
- Apache Airflow 以编程方式创作、安排和监控工作流。
- PostgreSQL 作为对象关系数据库。
- 作为 PostgreSQL 的管理和开发平台。
- MinIO 作为对象存储——向来自 minIO 的人们大声疾呼,因为他们的社区版拥有标准版和企业版的所有功能!
- 主持我们的服务。
一如既往,我们永远不会停止学习,所以如果您想了解更多,请随时查看以下链接
- 这个系列的第一部分
- Docker 的自定义桥
- 码头工人的集装箱及其命名的重要性
- Docker 的重启策略
- Docker 的环境变量在 compose
- 资源、客户端和会话之间的 boto3 差异。
- 如何将气流与 NiFi ETL 管道连接
- 阿帕奇气流
- 阿帕奇尼菲
- Apache NiFi 注册表
- Nifi 注册管理机构的系统管理员指南
- PostgreSQL
- pgAdmin
- MinIO
如何构建一个不会回来困扰你的数据产品
作者图片
当数据科学遇到生产工程
回想一下,您曾被要求将数据科学分析转变为可重复、受支持的报告或仪表板,以适应贵公司的生产数据管道和数据架构。也许你之前进行了原型分析,该解决方案信息丰富且运行良好,因此你的老板要求你将其投入生产。也许你发现自己不断地为相同类型的分析、培训和测试新模型重新提取数据,你想自动化整个过程以节省宝贵的时间。
或者,您的生产数据产品可能会遇到问题。也许你有数据科学支持的仪表板,你已经开发并投入生产,但用户对它们越来越失望,并失去信任。也许你会发现自己在浪费时间来支持现有的生产仪表盘和报告,这阻碍了你从事更新、更有趣的项目的能力。
将数据产品投入生产本身就是一门艺术。如果做得好,自动化可以提高数据科学团队工作的准确性、可信度和速度。如果做得不好,自动化会导致错误的增加,从而传播挫折感和不信任感。
许多最初的数据科学分析从零开始,并通过手工制作的管道处理所有数据。因为他们从定制的数据流程开始,数据科学家后来可能会陷入个人管理管道的责任中。他们花额外的时间检查他们的管道,以检测新出现的问题,及时修复它们,并在产品的消费者失去信任时,采取必要的措施来恢复失去的信任。
当将仪表板投入生产时,您不仅要考虑数据、报告和用户的情况,还要考虑数据和用户群在未来将如何变化。现在,一份报告对当前用户来说可能是清晰而准确的,尤其是因为你可以回答他们可能有的任何问题。但是,数据漂移可能会导致将来的报告不准确。一个你平时不怎么接触的经理可能会看到你的报告,但不能清楚地理解它,也不知道去哪里寻求帮助来理解它。因此,数据产品的质量以及对使用和解释数据产品的支持都会随着时间的推移而降低。
这些年来,我既是首席数据架构师,负责设计数据流程的管道,也是首席数据科学家,利用工程数据开发生产流程和可视化中使用的模型。
这篇文章整理了我一路走来学到的一些经验。我描述了生产数据管道的四个理想属性——不言自明、值得信赖、适应性强和有弹性。为了使数据管道正常运行,您需要在三个不同的数据处理阶段提供脚手架,包括您用作输入的数据(第一英里)、您向用户呈现结果的方式(最后一英里)以及数据处理和模型开发的运行和执行(中间的一切)。综合考虑,这两个轴提供了 12 个不同的接触点,每个接触点都有一个或多个重要的考虑事项需要解决。在我发布我的生产报告、仪表板和/或模型之前,这里是我在这些接触点上解决的一些考虑和重要问题。
三个管道阶段
我们说链条的强度取决于它最薄弱的一环。在数据管道中也是如此。数据产品的强度取决于构成产品的数据、管道和流程中最薄弱的部分。然而,在数据产品的情况下,许多这些“链接”不在你的控制之下。
你如何打造最强大的产品?你关注的是在你的特定管道部分的三个阶段——输入、输出和执行——中的每一个阶段需要加强的最重要的东西。
你的第一英里:你是从正确的东西开始的吗?此阶段的关注点集中在您放入管道或模型的输入数据上。您支持用户的能力取决于您开始时输入数据的质量。输入数据中的故障和降级通常不受您的控制,但会严重影响您的数据产品被接收和接受的程度。
你的最后一英里:你的数据产品带来了理解、信任和信心吗?您可能有一个很棒的数据产品,可能真的能满足需求,但所有这些都没有实际意义,除非用户理解报告,并对其底层数据的新鲜度和准确性有信心。“最后一英里”中的关注点集中在建立和维护这种信任上,这种信任不仅来自于您当前的报表查看者,也来自于将来可能查看该报表的任何人。
在你、未来的你和你未来的替代者之间的旅程:你让事情变得简单了吗?好的数据产品会存在很长一段时间。寿命和可维护性的考虑集中在您自己的特定提取、转换和加载过程上。数据管道出现故障,可能由于调度效率低下而降级,并可能产生规模问题。数据输入改变或消失。随着时间的推移,在使用您的数据生成的模型中,您可能会看到数据漂移或模型漂移。
支持一个生产过程可能很耗时,您希望为您自己、与您一起工作的其他人(他们可能会分担您的工作量)以及任何可能取代您的人简化维护过程。
四个重要标准
第二个轴包括不同的质量标准——让你的产品更强大的标准。我用四个标准来评估我的数据产品对未来数据问题和用户挑战的弹性。产品是否自明?T2 能激发信任和信心吗?随着数据输入的变化,是否容易适应?是否可靠、准确、维护?在开发生产管道时,仔细注意这些有助于减少未来维护任务所需的时间。
不言而喻:一旦你把你的数据产品投入生产,那些你不直接与之互动的人可能正在看着它。数据产品越简单明了,就越容易支持未来的用户。您希望尽可能地置身事外,同时仍能提供良好的支持。
随着时间的推移,您或其他人将需要进行一定量的监控和维护,以确保数据产品保持更新和准确。保持一个较低的心理负荷,以便拿起报告并学习,或者提醒自己报告是如何工作的,有助于这种维护。
值得信任:信任很难得到,也很容易失去。通常,当您第一次交付一个数据产品时,会有很多希望和一些信任。对于报表或仪表板,当用户获得报表或仪表板的长期感觉时,信任才会真正发展:
- 回答他们的问题
- 使用准确的数据
- 保持最新
- 提供一种可靠的方法来解决他们所看到的问题或潜在问题
如果用户开始怀疑这些事情中的任何一件,信任开始被侵蚀,报告不再像开始时那样有用。重复或重叠的关注点意味着产品最终会从他们的雷达上消失,用户会尝试用不同的方法来回答他们的问题。
适应性:数据输入和形状随时间变化。模式会改变。键值的分布发生变化。地方停止报告数据。数据集可以增长和扩展到超出您的数据处理和查询所能有效处理的范围。所有这些都会影响自动化流程交付准确及时的产品的能力。
作为一名数据科学家,您不希望花费时间频繁而详细地查看您的每一个产品,以确保您注意到数据中的所有小故障以及所有可能看起来不正确的地方。相反,最好是将监控任务委托给自动化系统,并以较慢的节奏对每个报告进行详细的深入研究。您可以自动监控的内容包括:
- 对一个或多个输入数据流的架构的相关更改
- 您正在使用的关键字段中数据形状的相关更改
- 数据量的显著增加或减少
- 最近使用的记录和当前时间之间有明显的滞后
- 关于数据量或滞后的趋势
除了监控相关问题之外,当有人注意到问题时,您需要做好准备,做出反应并制定解决方案,避免过度复杂化。确切地知道在哪里寻找是第一步,但是以一种易于适应和维护的方式设置您的数据过程也是成功的关键。
当你在设计和建立你的管道时,要考虑到你未来的自己(或者可能是你的替代者)。将定期重新训练模型的过程自动化,以考虑数据的变化。有一个检查您的数据和模型的节奏,以确保它们仍然符合您在设置初始流程时所做的假设。
可靠:可靠性是关于你的管道和模型的执行效果。在这种情况下,管道可靠性与管道中的流程执行和计时相关。这与适应性(如上)形成对比,适应性与正在处理的实际数据有关。
为了确保可靠性,您需要确保组成管道的不同部分是可靠的,并且编排这些部分的流程是健壮的。
当数据和模型构建管道自动化时,您没有关于正在执行什么、是否遇到任何问题或者甚至结果数据产品看起来像什么的即时和集中的反馈。为此,为了了解不同部分或阶段的可靠性,有一个监控系统会有所帮助,该系统会集中这些信息并提醒您需要注意的事情。
要监控整个流程的每个处理阶段,就要监控每个阶段的可靠性。监控阶段包括检查以下内容:
- 其输入数据得到了及时更新
- 该阶段在预期的时间开始执行
- 该阶段已成功完成
- 在任何下游阶段需要读取其结果之前完成的阶段
把东西放在一起
当形成我的初始生产质量系统时,我在流水线的每个阶段都提出具体的问题,集中在前面提到的问题上。通过系统地研究这些问题,我能够解决所有 12 个接触点的质量问题。
不言自明/第一英里:
- 我使用的数据是否有据可查?
- 我使用的数据是否符合其预期用途?
- 我是否尽可能多地重用现有的工程管道,以降低整体维护工作量,并确保我的使用与相同数据项的其他使用一致?
不言自明/最后一英里:
- 报告或仪表板的呈现方式是否易于访问和理解,甚至对于将要查看它的人也是如此,并且不需要我的解释?
- 我是否使用了最终用户理解的词汇和可视化,并且他们理解的方式和我完全一样?
- 我是否以一种直观且易于从数据产品本身获取的方式提供了良好的支持文档和信息?
自明/介于:
- 数据流程的要求、约束和实现是否记录得足够好,以便可能接替我进行维护的其他人能够理解?
值得信赖/第一英里:
- 我连接到输入数据的方式在生产管道中得到很好的支持吗?
- 维护我正在使用的数据集的人是否明确支持我?
- 这些输入数据在未来很长一段时间内可能会被保留吗?
- 什么时候我可能需要检查以确保数据仍然被维护?
- 我如何报告我在输入数据中看到的任何问题?
- 谁负责通知我数据有问题?
- 谁负责解决这些问题?
值得信赖/最后一英里:
- 用户如何知道他们何时可以相信报告是准确的和最新的?
- 是否有一种有效的和/或自动化的方式将可能的问题传达给最终用户?
- 是否有一个清晰且可访问的流程,供用户报告与数据或报告有关的问题,以及通知用户是否有任何补救流程?
值得信赖/介于两者之间:
- 我是否制定了定期的计划来审查数据和报告,以确保数据管道仍然运行良好,并且报告符合要求?
- 在什么情况下应将此报告标记为已弃用?
- 如果报告被否决,我如何确保用户得到通知?
适应性强/第一英里:
- 我的分析依赖于输入数据中的哪些要素?
- 我如何知道这些特性是否不再受支持,是否受到模式更改的影响,或者是否以可能影响我的分析的方式改变了形状?
- 我如何知道数据的规模是否增长到了需要重构过程的程度,以便跟上产品对新鲜度的要求?
适应性强/最后一英里:
- 产品或报告的设置方式是否便于申请变更和/或新功能?
适应性强/介于两者之间:
- 我是否为重新检查需求建立了一个定期的时间表,以确保我仍然在生产用户需要和期望的东西?
- 用户指出需求变化的过程是什么,这些变化是如何解决的?
- 当输入以某种相关方式改变时,重构和重新测试数据管道的过程是什么?
可靠/第一英里:
- 我的流程是否很好地融入了组织中的数据实践和工程生产系统?
- 我是否有自动通知系统来监控输入数据的可用性、新鲜度和可靠性?
可靠/最后一英里:
- 谁负责仪表板本身的持续监控、审查、故障排除和维护?
- 内部报告和解决问题的职责和程序是否明确到位?
可靠/介于:
- 我的管道中的每个阶段都及时执行和完成了吗?
- 在任何阶段,处理时间和/或正在处理的数据量是否存在漂移,这可能表明管道功能下降?
结论
将一个数据产品投入生产所面临的挑战,不仅仅是一次性地或作为一个原型让某样东西表现良好。从一开始就适当关注与生产相关的问题,可以最大限度地减少您在生产中产品的日常维护任务上花费的时间,从而提高您的整体生产效率。
当您第一次构建一个数据产品时,您会考虑可以使用哪些数据,以及如何在您的产品中最好地使用这些数据来满足目标用户的需求。对于分析师或数据科学家来说,这通常有点像是单独的工作。
将产品投入生产更多的是团队的努力。通常还有其他人——可能是数据工程团队——负责确保您所依赖的数据源保持准确和最新。您希望以最适合他们的方式连接他们的数据。你也有你的用户——现在是一群更加开放的人——他们会使用你的产品。你希望他们信任你的产品。你希望尽可能简单地使用和理解你的产品。最后,你有自己的数据管道。当发生影响其功能的事情时,您希望尽快知道。
本文中的 12 个接触点以及与每个接触点相关的问题为您的产品化过程提供了一个结构。关注这些问题将有助于防止你陷入支持困境,并给你更多的时间来发挥创造力和创造新事物。
玛丽安·诺丁是 Mighty Canary 的首席数据科学家。
Mighty Canary 是一家专注于构建工具的公司,旨在帮助数据和分析专业人员增加对其报告的信任,并减少他们支持旧报告所花费的时间。
如何在 2022 年建立一个机器学习演示
原文:https://towardsdatascience.com/how-to-build-a-machine-learning-demo-in-2022-5bda6cd99743
了解为什么你应该在 2022 年为你的机器学习模型制作演示,以及如何以适合你的需求、技能和受众的方式来做这件事。
Artturi Jalli 在 Unsplash 上拍摄的照片
为什么演示现在至关重要
机器学习模型的交互式演示越来越受欢迎。毕竟,就像一幅画胜过千言万语一样,没有什么比让别人直接与你的模型互动来产生兴趣更好的了。如果你有兴趣跟上最近的趋势,或者正在为你自己的演示寻找灵感,我强烈推荐关注 @ak92501 twitter 账户。
其中的一个例子是一个模特将肖像照片转换成网飞神秘秀所用风格的插图的演示。演示的易用性和用不同的输入照片快速测试模型的能力是这个项目如此迅速地变得如此受欢迎的部分原因。
您可能希望构建交互式演示的原因有很多:
- 在开发过程中让同事测试模型
- 原型,以寻求对新想法的投资
- 传播研究成果,可能作为研究论文的附录
- 建立一个作品集
无论你的理由是什么,这篇文章都将提供一些提示和建议来充分利用这个机会。
如何在 2022 年建立一个互动演示
在 2022 年,有多种方法可以为你的机器学习模型构建一个交互式演示。你选择哪一个取决于:
- 你的目标受众
- 你的软件工程技能
- 你的货币预算
- 你的时间预算
- 您的需求(交互性、灵活性)
作者提供的图像(徽标是其各自所有者的财产)
本文将介绍三种方法:公共笔记本共享、全栈和应用程序库。
TLDR —我应该使用哪种方法?
本文的其余部分将详细介绍关于这三种方法您需要了解的内容。如果你想快速回答,下面的表格应该会有帮助!
2022 年机器学习演示构建不同方法的比较。作者图片
经验法则:
- 在代码可见性有用而交互性不重要的情况下,与技术受众分享?使用 Google Colab(或同等工具)
- 演示成为成熟产品的可能性大吗?从长远来看,采用全栈方法可能会节省您的时间
- 如果以上都不是,那就用应用程序库和拥抱脸空间托管吧
公共笔记本共享(Google Colab)
Jupyter notebooks(以及之前的 iPython)在巩固 Python 作为机器学习的领先编程语言方面发挥了重要作用。虽然不是没有缺点,但通过支持交互式数据探索和迭代开发,笔记本迅速成为机器学习爱好者的重要工具。但是,如果远程访问需要托管,设置 Jupyter 环境可能会很困难,而且可能会很昂贵。
Google Colab 是这一领域的重要颠覆者——它通过提供完全托管的笔记本体验,无需任何设置或维护,实现了机器学习的大众化,并提供了对昂贵计算资源的免费访问。
Colab 使得共享笔记本并让其他人与之交互变得轻而易举,即使这需要 GPU 加速。例如, fastai 文档甚至最近的 fastai 书籍都可以作为 Colab 笔记本使用,允许人们在浏览材料时运行和修改代码。
大多数笔记本都可以在 Colab 上运行,不需要太多的工作,一些小部件可以让用户输入他们自己的数据。如果笔记本是在公共 Github repo 上进行版本控制的,那么只需共享一个如下格式的链接:
[https://colab.research.google.com/github/$ACCOUNT/$REPO/blob/$BRANCH/$PATH_TO_NOTEBOOK](https://colab.research.google.com/github/$ACCOUNT/$REPO/blob/$BRANCH/$PATH_TO_NOTEBOOK)
其中$ACCOUNT
是 Github 账户,$REPO
是存储库,$BRANCH
是分支,$PATH_TO_NOTEBOOK
是ipynb
文件的完整路径。
如果你有兴趣与大众分享你的作品,Colab 笔记本不是最好的选择。然而,它们是非常强大的工具,可以轻松地将想法传达给技术同行。以至于几乎所有机器学习的新发展都倾向于将配套的 Colab 笔记本作为标准。作为一个例子,我探索了一种全新的基于补丁的自我监督方法,使用由我自己提供的输入数据(在这种情况下,是我的猫 Jasmine 的照片)。它让我对这项新的研究有了更好的理解,而且对我来说是免费的。
我的猫 Jasmine 的新自我监督方法的 Google Colab 截图,笔记本位于https://Colab . research . Google . com/github/Facebook research/Mae/blob/main/demo/Mae _ visualize . ipynb
总的来说,交互性非常有限。解决这个问题的一个可能方法是使用一个库,比如 Gradio ,它允许直接在笔记本上创建基本的用户界面。Gradio 将在应用程序库部分详细介绍。
为了完整起见,我应该提到亚马逊网络服务宣布 SageMaker Studio Lab ,它类似于 Google Colab,具有一些优势,如持久存储。我还没有机会探索它,但理论上它可以以类似于 Google Colab 的方式使用。
Colab 笔记本的优点:
- 免费使用 GPU 计算
- 与 Git 紧密集成以促进共享
- 完全受管,无需设置或维护
Colab 笔记本的缺点:
- 仅限于技术观众,不适合外行观众
- 默认情况下交互性有限,可以使用 Gradio 等库来改进
- GPU 可用性时好时坏
- 需要一些外部存储(例如存储模型人工制品)
全栈
这种创建交互式演示的方法要求最高,但从长远来看,这种方法可能会有回报。它是全栈式的,因为它涉及两个组件:
- 一个后端负责将模型作为 REST API 进行加载和服务
- 一个前端提供 UI 元素与后端交互
显而易见的缺点是,它需要对这两个组件都感到舒适,或者至少愿意学习。然而,这种方法是最灵活的,可以用作部署成熟生产环境的垫脚石,而无需从头开始。
在深入下面的后端和前端组件之前,我们先来看看全栈方法的优缺点。
全栈模式的优势:
- 根据需要灵活调整
- 可以包括其他功能,如身份验证
- 可用作生产部署的基础,无需从头开始
- 可以针对性能进行优化
全栈方法的缺点:
- 需要后端和前端开发知识
- 耗时的开发和部署
- 需要基础设施进行部署
后端
对后端开发的不同技术栈的详尽讨论超出了本文的范围。然而,鉴于大多数从事机器学习应用的机器学习工程师至少熟悉 Python,我们将重点关注基于 Python 的后端解决方案。
后端开发的不同工具:通用 web 框架、服务库和特定于框架的服务库。图片由作者提供。
后端的目标是充当模型的包装器,以便可以通过来自前端的HTTP
请求来查询它,这被称为服务于的模型。为了做到这一点,人们通常会使用 web 框架。很长一段时间以来, Flask 是基于 Python 的 web 框架的标准,并且确实仍然非常流行。然而, FastaAPI 正迅速成为新宠,这要归功于令人印象深刻的性能和对异步操作的本机支持。本文是理解如何使用 FastAPI 部署简单模型的一个很好的起点,而本教程提供了一个完整的概述,介绍了使用 GPU 支持服务 PyTorch 模型所需的所有步骤。
使用 FastAPI 这样的通用框架需要编写大量样板代码,只是为了让您的 API 端点启动并运行。如果为一个演示部署一个模型是您唯一感兴趣的事情,并且您不介意失去一些灵活性,那么您可能想要使用一个专门的服务框架。一个例子是 BentoML ,它将允许您为您的模型获得一个优化的服务端点,并且比一般的 web 框架运行得更快,开销更少。特定于框架的服务解决方案,如 Tensorflow Serving 和 TorchServe 通常提供优化的性能,但只能分别用于服务使用 Tensorflow 或 PyTorch 训练的模型。
前端
前端负责提供一个用户界面,与服务于模型的后端进行交互。在大多数情况下,它将是一种输入数据(如用于自然语言处理的文本,或用于计算机视觉的图像)和显示模型输出的手段。将这个用户界面放在 web 浏览器中可以让您的演示不需要额外的依赖就可以访问。
前端开发是您可能不得不放弃 Python 的地方。虽然像 Skulpt 和 Brython 这样的库支持在浏览器中使用 Python,但我强烈推荐使用 Javascript,因为非常大的社区意味着教程很多,如果需要,寻求帮助会容易得多。用 Javascript 构建用户界面的两个最流行的库是React(ML 演示的教程)和vue . js(ML 演示的教程)。使用一个通用的框架将会给你定制用户界面的灵活性。
部署
一旦您的后端和前端组件准备就绪,就必须将它们部署到公共可访问的地方。再说一遍,灵活性是这个游戏的名字。像 Heroku 这样的服务为应用程序的部署提供了托管(和免费,取决于使用)体验。Amazon Web Services、Azure 或 Google Cloud 等公共云提供商可能是一个选择,一个小的演示可能很适合他们的免费层产品。
无论您决定走哪条路,我建议您考虑使用 Docker 将您的演示容器化。通过这种方式,相同的容器映像被用于开发期间的本地测试和在您的托管提供商上的部署,有助于避免由于环境变化而带来的不良后果。
应用程序库
那么,如果您想要的东西几乎和全栈方法一样灵活,但是没有开发需求,该怎么办呢?你很幸运,因为在过去的几年里,Python 库的出现使得只用几行代码就可以创建令人印象深刻的交互式演示。在本文中,我们将关注两个最有前途的库: Gradio 和 Streamlit 。下面将探讨这两者之间的显著差异,但高层次的想法是相同的:消除全栈部分中概述的大部分痛苦的后端和前端工作,尽管代价是一些灵活性。
格拉迪欧
Gradio 已经在 Google Colab 部分提到过,因为它可以用来为笔记本添加交互元素。如库的入门页面所示,构建一个接口只需要几行 Python 代码。
import gradio as grdef greet(name):
return "Hello " + name + "!!"iface = gr.Interface(fn=greet, inputs="text", outputs="text")
iface.launch()
如果您在笔记本电脑上工作,用户界面会立即显示出来。如果从脚本运行,浏览器窗口将打开并指向http://localhost:7860
。之所以这样做,是因为 Gradio 本质上是在后台为您运行一个 API 服务器,从而负责全栈一节中讨论的大部分工作。它曾经利用 Flask 来创建本地 API 服务器,但是最近转向使用 FastAPI 。
在上面的代码片段中,greet
函数将被替换为您的模型的推理代码。注意,inputs
和outputs
都被设置为文本,所以 UI 将自动默认为处理基于文本的任务所必需的小部件。类似的小部件存在于最常见的用例中,包括计算机视觉和音频处理。此外,Gradio 还提供了非常方便的功能,例如,如果显示的输出是意外的(例如,如果处理失败),可以截图或让用户进行标记。
如果你想与世界分享你的用户界面,在launch
方法中使用share=True
参数将为你提供一个指向你的演示的gradio.app
URL。请注意,这只是将请求转发到您的机器,因此只有当您的脚本或笔记本正在运行时,它才会起作用,并且链接会在 72 小时后自动过期。请参阅下面关于拥抱面部空间托管的部分,以解决这些限制。
由几行代码生成的文本输入和输出的默认 Gradio UI。作者截图。
Gradio 专注于为机器学习模型构建用户界面,这意味着它将为您处理几乎所有事情,并且开箱即用,只需很少的配置。
格拉迪欧的优点:
- 开箱即可快速轻松设置
- 直接在笔记本上运行
- 绝对不需要网络开发知识
- 应用程序易于共享
- 内置 UI 元素的良好选择
- 截图或输出标记等功能对于演示来说非常方便
梯度的缺点:
- 对用户界面布局的有限控制
- 不适合复杂的应用程序(例如状态管理、缓存)
细流
Streamlit 是一个构建和共享数据应用的库。他们的策展画廊展示了数据可视化应用、仪表盘、互动教程,当然还有机器学习演示的例子。
Streamlit 可用于构建复杂的应用程序,与 Gradio 相比,其代价是进入门槛更高。例如,它不能直接在笔记本上运行—命令行工具用于从脚本启动应用程序。采用实时重新加载方法,对代码所做的更改会自动反映在浏览器中运行的应用程序中,从而允许快速迭代。
Streamlit 附带了一些高级功能,如缓存,这有助于防止长时间运行的任务(例如下载和准备用于推理的模型)不必要地运行多次,以及构建有状态应用程序的能力(在用户会话期间保留信息)。这些功能使用例超越了简单的机器学习演示。在 UI 方面,该库有大量内置的小部件,并可以通过第三方组件的支持进一步扩展。
Streamlit 提供名为 Streamlit Cloud 的应用共享托管服务。在撰写本文时,可以使用 Streamlit Cloud 和免费计划部署一个私有(需要认证)和无限的公共应用。或者,Streamlit 应用程序很容易容器化,并使用 Docker 进行部署。
如果你对部署 Gradio 和 Streamlit 应用程序都感兴趣,拥抱面部空间可能是一个不错的选择。
细流的优点:
- 快速设置
- 缓存和状态管理等高级功能允许构建复杂的应用程序
- 大量内置 UI 小部件可供选择
- 高度可定制的 UI 布局
- 通过支持自定义第三方组件进行扩展
Streamlit 的缺点:
- 共享应用程序不像使用 Gradio 那么简单
- 复杂的应用程序需要对高级 web 开发概念有所了解
- 与笔记本不兼容
- 缺少 ML 演示的一些基本的内置特性(例如,意外输入/输出的标记)
拥抱脸空间革命
当拥抱脸将空间添加到他们的 ML 产品和工具生态系统中时,部署使用 Gradio 或 Streamlit 开发的应用变得更加容易。空间类似于 Github 页面——代码被提交给存储库,应用程序被自动构建和服务。创建空间时,您可以在 Streamlit、Gradio 和 Static(或多或少复制 Github Pages 的静态网站托管功能)之间进行选择。然后,空间会自动设置为容纳您选择的库。版本控制和用户喜欢空间的能力等有用功能使其成为部署公共机器学习演示的绝佳体验。
类似于谷歌 Colab 如何使训练最先进的机器学习模型所需的计算资源的访问民主化,拥抱面部空间允许任何人主持演示供世界检验。这意味着整个机器学习工作流,从模型训练到交互式演示的部署,现在都可以免费进行,而且几乎完全是用 Python 编写的。
✨如果你喜欢这个内容,请花时间到 在媒体上关注我,并查看我在平台上的其他帖子。我的大部分内容,包括这个故事,也发表在我的个人网站( nicjac.dev ) ✨上
如何用 PyTorch 和 GPU 构建用于 NLP 任务的神经网络
使用 Google Colab 对文本数据建模的框架
斯蒂夫·约翰森摄:https://www . pexels . com/photo/blue-red-and-black-abstract-painting-2130475/
T 他的文章旨在作为一个框架,使用 Python、神经网络和 GPU 来解决自然语言处理(NLP)问题。虽然理解这里的一切需要很高的数学水平,但我写这篇文章的目的是让一个完全的初学者或经验丰富的老手从中有所收获。我希望一个初学者带走解决 NLP 问题的一般框架,而一个老手可能使用它作为在 PyTorch 中将模型推送到 GPU 的参考。
我们开始吧!
NLP:数据和预处理
尽管数据清理不是建模过程中最令人兴奋的方面,但它无疑是最重要的。数据清理和预处理指的是将原始文本数据结构化和格式化成我们可以建模的东西。对这一过程的关注可以成就或破坏后续模型的统计推断。我们将使用来自 NLTK(用于 NLP 的 Python 库)语料库模块的数据,该模块包括电影评论及其真相分类(无论评论是正面还是负面)。让我们首先导入我们将需要的模块并下载必要的数据…
该项目的相关进口报表
在 NLP 中有很多被抛弃的术语——让我们介绍一些更相关的术语…
- 文集—文档的集合
- 文档 —来自语料库的文本主体
- 令牌—文档中的单词列表
- 词汇 —词汇
用粗笔画,所有包含#ElonMusk 的 tweets 就是一个语料库的例子。包含#ElonMusk 的所有 tweet 集合中的每个 tweet 都是一个文档。因此,每个文档中的每个单词都是一个令牌。这个环境中的词汇属于社交词汇;也就是使用#ElonMusk 时在社交语境中使用的词汇。
为了开始 Python 中的预处理,我们将创建两个列表。第一个列表包含电影评论语料库中的每个文档。第二个列表包含基本事实,一个对应于评论是正面还是负面的值(“正面”或“负面”)。
创建文档及其各自类别的列表
让我们看一下每个列表中的单个元素,这样我们就可以更好地了解我们正在处理的数据…
文件[0]:
"plot : two teen couples go to a church party..."
这是文档列表中的众多电影评论之一。
猫[0]:
0
这是与上述电影评论相对应的类别(负面)。请注意,在代码中,我们是如何将负数(' neg ')转换为 0,将正数(' pos ')转换为 1 的——这对于我们的神经网络模型是必要的。
我们的目标是建立一个神经网络,可以学习电影评论中常用的词,这些词可以是积极的,也可以是消极的。在此之前,我们需要清理一下电影评论文本。
让我们构建一个函数来清理和预处理每个文档。
预处理和清洗改编自数据营
再一次,让我们分解一些语言学术语…
- 令牌化 —将文档转换为令牌列表
- 词干化——孤立词根(示教 = 示教)
- 终止词——无信息贡献的词( the 、和、同为)
预处理功能为每个文档建立一个标记器和一个词干器。我们通过遍历列表中的每一个文档,并从删除所有标点符号和减少所有单词开始。在某些情况下,我们需要考虑不同的情况,但为了简单起见,我们将' GREAT' 和' great 视为同一事物。
接下来,我们将标记器应用于文档,创建一个单词列表,在其中应用停止单词移除和词干。如果这个列表中有一个单词存在于 NLTK 预定义的停止单词列表中,我们会将其从单词列表中删除。这里的目标是开发尽可能小的单词列表,同时保持尽可能多的关于原始文档的信息。换句话说,如果我们有一长串不相关的信息,我们会给我们的模型带来不必要的噪音,让它更难学习。例如,“”很可能出现在正面和负面的电影评论中。因此,在清理后的文本中包含“”和“”不会帮助我们的模型学习。
最后,我们将把剩下的单词“T42”转换成“教学”。“-ing”结尾是为了语法目的而存在的,但是这个词的词根意义没有改变,所以我们打算以类似的方式在所有文档中对其进行建模。再一次,我们想最小化我们的模型面临的噪音,所以它有最好的学习机会。
既然我们已经预处理了文档,我们需要开发一个文档术语矩阵,即所谓的文档术语矩阵。这听起来可能很复杂,但它实际上是一个文档矩阵和每个文档中的术语。也许更合适的名称是文档-令牌矩阵,因为每行对应一个文档,每列对应一个令牌以及它在文档中出现的次数。这意味着对于所有文档中的每一个标记,都有一个用于的列,其中矩阵中的每个值都对应于它在该文档中出现的次数。
让我们为预处理的电影评论数据建立一个文档术语矩阵。
创建文档术语矩阵并将其转换为数据框架
现在我们准备开始构建我们的语言模型。我想强调的是,我们仍然可以做大量的事情来进一步预处理这些数据。在继续构建模型之前,我们可以应用降维技术、聚类算法等等,从我们的文档(文档术语矩阵)中进一步提取有意义的信息。虽然深入探讨降维技术超出了本文的范围,但我想留下一些我创建的资源来进行降维主题的教育…
事不宜迟,让我们进入有趣的部分,构建模型。
NLP:使用 GPU 在 PyTorch 中构建神经网络模型
在本节中,我们将构建神经网络来学习如何对电影评论进行分类。我们还将学习如何使用 PyTorch 和 GPU,通过并行化来提高训练速度。我推荐使用 Google Colab 和他们的免费 GPU 层来开始。如果您对直观理解并行化及其如何加速计算感兴趣,请查看下一篇文章的直觉部分。
训练任何机器学习或人工智能的第一步是将数据分割成训练和测试集。我不会在模型开发的哲学上花太多时间,我们将一起构建每个组件。如果你有兴趣更深入地理解我通常所说的建模艺术,请随意阅读以下文章…
首先,我们将数据分成训练集和测试集。
为我们的分类模型创建电影评论的训练和测试集
现在我们已经准备好建立我们的分类模型了。我非常支持边做边学(在这里是编码)。然而,理解构成人工智能模型的基础数学是有好处的。让我们从代码开始,提供一些关于我们所做的数学选择的直觉。
PyTorch GPU 二进制分类模型
在这种情况下,神经网络最重要的功能选择是输出层的激活功能。摆在我们面前的任务是一个二进制分类任务,因此我们需要将一个输入分类为两个类别之一( 1 或 0,正或负)。我们选择一个 sigmoid 激活函数来做这件事。该激活函数将其输入压缩到对应于电影评论是否正面的概率中。如果概率大于 50%,我们会说电影评论是正面的,否则我们会说它是负面的。我们的神经网络将通过调整其权重来学习输入到概率的正确映射,以改进其对训练集中的基本事实的预测。一旦我们训练了我们的模型,我们将用测试集来测试它;我们这样做是为了确保我们的模型不会记忆 ( 过度拟合)训练集中的观察值。
注意,在上面的代码块中,我们包含了一个语句。到(' cuda')' 。这会将模型推送到 GPU,因此当开始训练过程时,它会自动并行化。这将显著提高培训过程的绩效。
注意:使用 GPU 时最常见的错误之一是在使用 GPU 时试图访问存储在 CPU 中的内存,反之亦然。永远记住变量在内存中的存储位置。
我们现在准备使用训练数据来训练模型。
PyTorch GPU 模型培训
在模型被充分训练后,我们需要测试它的表现如何样本外。我们将使用我们的模型尚未见过的测试数据来确定我们的模型对新数据的分类能力。这将确保我们的神经网络模型实际上是在学习一些东西,而不仅仅是过度拟合训练数据。
创建一个二元测试集来与基本事实进行比较
print(classification_report(y_hat_int, y_test))
precision recall f1-score support
0 0.87 0.88 0.88 258
1 0.87 0.86 0.87 242
accuracy 0.87 500
macro avg 0.87 0.87 0.87 500
weighted avg 0.87 0.87 0.87 500
使用分类报告功能,我们可以比较模型的预测和实际情况,以确定模型的准确性。
上面的打印输出告诉我们,我们的模型在确定哪些电影评论是正面的,哪些是负面的方面做得非常好!
一些最后的想法…
这里我们观察到相对平衡的支持,测试集中正面和负面评论的数量。需要注意的是,在我们的训练和测试集中,我们通常希望有一个像这样平衡的类表示。如果类别不平衡,我们的模型可以学习猜测出现最多的类别,这意味着它真的没有学到任何东西。
这在异常检测问题(如洗钱和医疗保险欺诈)中很常见,因为异常的发生通常只占数据的一小部分(比如 0.01%)。因此,一个模型仅仅通过猜测出现最多的类就可以获得大约 99.99%的准确率。
当然,这是一个有趣的问题,我们可以在另一篇文章中探讨!
参考文献
https://www.kaggle.com/datasets/nltkdata/movie-review
Bo Pang and Lillian Lee. 2004\. A Sentimental Education: Sentiment Analysis
Using Subjectivity Summarization Based on Minimum Cuts. In ACL.
非常感谢您的阅读!我希望你喜欢这篇文章——如果你有任何问题,请随时发表评论或联系我们:roman@quantguild.com。
如果你有兴趣了解更多,请查看 Quant Guild !
Quant Guild 是我创办的一所在线学校,你可以在那里学习包括数学、统计学、计算机科学和数据科学在内的主题。
如果你对更多免费课程和资源感兴趣,或者想在 Quant Guild 支持我们,你可以看看我们的…
除此之外,下期再见!
RMP
如何为面板数据建立混合 OLS 回归模型
a 面板数据集(来源:世界发展指标数据在 CC BY 4.0 license )(图片由作者提供)
以及使用 Python 和 statsmodels 对其拟合优度的详细分析
在本文中,我们将了解面板数据数据集,我们将学习如何使用 statsmodels 和 Python 为真实世界的面板数据集构建和训练一个池化 OLS 回归模型。
训练池化 OLSR 模型后,我们将学习如何使用调整后的 R 平方、对数似然、AIC 和回归的 f 检验来分析训练模型的拟合优度。我们将通过对其残差的详细分析,更深入地了解模型的拟合优度。
与固定效应、随机效应和随机系数模型一起,混合 OLS 回归模型恰好是面板数据集的一个普遍考虑的模型。事实上,在许多面板数据集中,混合 OLSR 模型经常被用作比较其他模型性能的参考或基线模型。
本文是面板数据分析系列文章的第 1 部分:
- 如何为面板数据集建立混合 OLS 回归模型
- 了解固定效应回归模型
- 随机效应回归模型的实用指南
什么是面板数据?
面板数据集包含在一段时间内为一个或多个唯一可识别的个人或“事物”收集的数据。在面板数据术语中,为其收集数据的每个个体或“事物”被称为一个单元。
以下是面板数据集的三个真实例子:
弗雷明汉心脏研究:弗雷明汉心脏研究是一项长期的实验,于 1948 年在马萨诸塞州的弗雷明汉市开始。每年,来自 5000 多个个体的健康数据被捕获,目标是识别心血管疾病的风险因素。在这个数据集中,单元是一个人。
格伦菲尔德投资数据 :这是一个流行的研究数据集,包含 10 家美国公司 20 年来积累的公司业绩数据。在这个数据集中,单位是一家公司。
英国家庭小组调查 :这是对英国家庭样本的调查。自 1991 年以来,每个抽样家庭的成员都被问到一系列问题,他们的回答被记录下来。随后的每一年都要对相同的家庭样本进行一次访问。这项调查的目的是分析英国发生的社会经济变化对英国家庭的影响。在这个数据集中,单元是一个家庭。
在建立面板数据集时,研究人员为每个单元测量一个或多个称为变量的参数,并以表格形式记录它们的值。变量的例子有个人的性别、种族、体重和血脂水平,或公司的员工人数、流通股和 EBITDA。请注意,一些变量可能会随着时间的推移而变化,而另一些则保持不变。
该数据收集练习的结果是一个三维数据集,其中每行代表一个独特的单元,每列包含该单元的一个测量变量的数据,z 轴包含该单元被跟踪的时间周期序列。
面板数据集来自纵向研究,其中研究人员希望研究测量变量对一个或多个响应变量的影响,如一家公司的年度投资或一个国家的 GDP 增长。
真实世界面板数据集
以下面板数据包含了七个国家从 1992 年到 2014 年的人均 GDP 年增长率。除了 GDP 增长数据,该面板还包含每个国家总资本形成的同比增长:
a 小组数据集(来源:世界发展指标数据 CC BY 4.0 license )(图片由作者提供)
在上面的数据集中,每个国家(“单位”)在相同数量的时间段内被跟踪,产生了所谓的平衡面板。不平衡或不均衡面板是指在不同的时间段跟踪不同的单元。
上面的数据集也是一个固定面板(相对于旋转面板)的例子,因为我们在每个时间段都在跟踪同一组国家。
在本文的其余部分,我们将看看数据面板是固定的和平衡的。
在面板数据集中,属于一个单元的数据点集称为组。通常,单位和组这两个词在关于面板数据集的讨论中可以互换使用。
回到世界银行的数据集,假设我们希望研究总资本形成的增长和一个国家的 GDP 增长之间的关系。为此,我们形成以下回归目标:
回归目标
我们的目标是精确定义一个国家总资本形成的增长与该国每年经历的 GDP 增长之间的关系。
回归策略
我们的策略将是选择和拟合一个适合面板数据集,特别是 WB 面板数据的回归模型。我们的回归模型应该允许我们将国家 i 在时间段(年份) t 经历的年 GDP 增长表示为某个函数 f(.)在 t 时间段内 i 国家总资本形成的年增长率。
以符号形式:
在时间周期 t,国家 I 的 GDP 增长是国家 I 在时间周期 t 的总资本形成增长的函数
在上面的回归方程中, ε_it 是回归的残差,它捕捉了 i 国家在 t 年期间的同比增长的方差,这是模型无法能够“解释”的。
混合 OLS 回归模型
如前所述,混合 OLS 回归模型通常是一个很好的起点,也是几个面板数据集的参考模型。我们将研究它对世界银行数据集的适用性。
为此,我们将通过将国家和年份视为两列来“展平”面板数据,如下所示:
展平版本的面板数据集(图片由作者提供)
我们的因变量(内生变量)和解释变量(外生变量)如下:
因变量y= GDP _ PCAP _ 长城 _PCNT
解释变量X= GCF _ 长城 _PCNT
数据集可以在 这里下载 。
使用 Pandas ,我们将把这个展平的面板数据集加载到内存中,使用 Seaborn ,我们将绘制 plot y 对 X.
我们将从导入所有必需的包开始,包括我们将在本文后面使用的包:
**import** pandas **as** pd
**import** scipy.stats **as** st
**import** statsmodels.api **as** sm
**import** statsmodels.graphics.tsaplots **as** tsap
**from** statsmodels.compat **import** lzip
**from** statsmodels.stats.diagnostic **import** het_white
**from** matplotlib **import** pyplot **as** plt
**import** seaborn **as** sns
将展平的数据集加载到 Pandas 数据框中:
df_panel = pd.**read_csv**('wb_data_panel_2ind_7units_1992_2014.csv', **header**=0)
使用 Seaborn 绘制所有国家所有时间段的 GDP 增长与总资本形成增长的关系图:
sns.**scatterplot**(**x**=df_panel[**'GCF_GWTH_PCNT'**],
**y**=df_panel[**'GDP_PCAP_GWTH_PCNT'**],
**hue**=df_panel[**'COUNTRY'**]).**set**(**title**=
'Y-o-Y % Change in per-capita GDP versus Y-o-Y % Change in Gross capital formation')plt.**show**()
我们看到下面的情节:
国内生产总值同比增长%与总资本形成同比增长%的国家散点图(图片由作者提供)
在数据面板中,所有国家的 GDP 年同比增长率与总资本形成年同比增长率之间似乎存在线性关系。这对使用 OLS 技术拟合线性模型来说是个好兆头。
但是,我们也在响应变量 GDP_PCAP_GWTH_PCNT 中观察到了 异方差 的迹象。具体地,对于不同的 GCF_GWTH_PCNT 值,GDP_PCAP_GWTH_PCNT 的方差不是常数。对于使用 OLS 估计技术来说,这不是一个好兆头。
无论如何,让我们继续用 OLS 回归模型来拟合这个扁平的数据面板。在本文的后面,我们将看到如何使用一组拟合优度测试来度量模型的适用性。
混合 OLS 回归模型方程如下:
汇集的 OLS 回归模型方程(图片由作者提供)
在面板数据集上训练模型的目的是找到拟合系数 β_cap_1 和 β_cap_0 。 β_cap 中的“cap”表示它是模型估计的系数的值,而不是总是未知的真实(群体水平)值 β 。
ε 是拟合模型的残差,是具有一定均值和方差的随机变量。如果 OLS 估计技术正确地完成了它的工作,ε将具有为零的平均值,并且ε将具有以 GCF_GWTH_PCNT 为条件的恒定方差(即 ε 将不是异方差的),并且 ε 将不是自相关的。
我们将使用 statsmodels 的OLS
类来构建和拟合 OLS 回归模型,如下所示:
定义 y 和 X 变量:
y_var_name = **'GDP_PCAP_GWTH_PCNT'** X_var_names = [**'GCF_GWTH_PCNT'**]
从数据面板中切出 y 矢量:
pooled_y=df_panel[y_var_name]
从数据面板中切出 X 矩阵:
pooled_X=df_panel[X_var_names]
添加回归截距的占位符。模型拟合时,这个变量的系数就是回归模型的截距 β_0 。
pooled_X = sm.**add_constant**(pooled_X)
构建 OLS 回归模型:
pooled_olsr_model = sm.**OLS**(**endog**=pooled_y, **exog**=pooled_X)
在()y,X)数据集上训练模型并获取训练结果:
pooled_olsr_model_results = pooled_olsr_model.**fit**()
打印培训总结:
**print**(pooled_olsr_model_results.**summary**())
我们得到以下输出:
WB 数据集上混合 OLS 回归模型的训练输出(图片由作者提供)
如何解释混合 OLSR 模型的训练输出
首先要注意的是拟合系数的值: β_cap_1 和 β_cap_0
β_cap_0 = 0.9720,β_cap_1=0.2546
这两个系数都被估计为在 p
The trained Pooled OLS model’s equation is as follows:
The trained Pooled OLS regression model (Image by Author)
How to interpret the Pooled OLSR model’s performance
We will analyze whether Pooled OLS model is the adequate model for our regression problem. We will analyze the model’s goodness-of-fit using direct measures and tests such as R 平方 和 F 检验 以及对数似然和 AIC 分数处显著不同于 0,并且也通过残差分析间接不同。
通过 R 平方、f 检验、对数似然和 AIC 分析拟合优度
调整后的 R 平方 测量的是中由 X 解释的总方差的分数,在考虑了由于包含回归变量而损失的自由度之后,为 0.619 或约 62%。这当然不是一个糟糕的数字,但仍然没有什么值得欣喜若狂的。
测量模型参数联合显著性的回归的 F 检验 产生了 261.4 的检验统计量,p 值为 2.15e-35,从而使我们得出结论,模型的系数估计在 p 值为<001 时联合显著。
该模型的对数似然为-300.29, AIC 得分为 604.6。这些拟合优度值本身是没有意义的,除非我们将它们与竞争模型进行比较。在我下周的文章中,我们将在相同的数据面板上建立一个固定效应模型,并使用这两种方法来比较有限元模型和混合 OLSR 模型的拟合质量。
残差分析
让我们分析拟合模型的残差为 正态性 、 异方差性 和 相关性——影响线性模型拟合优度的三个属性。****
回想每个原始残差ε_ it = y _ OBS _ it—y _ pred _ it,即 GDP_PCAP_GWTH_PCNT 的观测值和预测值之间的差值。让我们打印出包含训练模型的原始残差的 Pandas Series
对象:**
打印(pooled _ olsr _ model _ results . resid)
模型的原始残差
以下是残差的平均值:
******print**(**'Mean value of residual errors='**+**str**(pooled_olsr_model_results.resid.**mean**()))****
Mean value of residual errors=**3.682354628259836e-16**
平均值实际上为零,这是使用 OLS 估计技术的预期结果。
残差是正态分布的吗?
让我们绘制残差的 Q-Q 图:
****sm.**qqplot**(data=pooled_olsr_model_results.**resid**, **line**=**'**45**'**)plt.**show**()****
混合 OLS 模型的残差 Q-Q 图(图片由作者提供)
这是我们观察问题的第一个迹象。残差的 Q-Q 图是对正态性的直观检验,它清楚地表明拟合模型的残差不是正态分布的。Q-Q 测试的结果由 Jarque-Bera 和综合测试 的输出支持,用于显示在训练总结的底部面板中的常态。两个测试都表明残差在 p < .001 处不是正态分布的。
正态性的 JB 检验和综合检验的结果(图片由作者提供)
即使残差不是正态分布的,混合 OLS 估计仍然是面板数据回归问题的最佳线性无偏估计。残差的非正态性不影响 OLS 回归模型的蓝色性。
具有非正态分布的残差的一个缺点是,人们不能 为模型的预测建立可靠的置信区间 。我们可以容忍小的偏离正态分布,但是大的偏离会使正态分布或学生的 t 分布失效。因此,可靠的置信区间不能(也不应该)计算。
残差是齐次的吗?
如果 OLSR 模型的残差是异方差的,即残差的方差在 X 的所有值上不是常数,则 OLS 估计器不是 有效的 (尽管它仍然是 无偏的 )。
让我们目视检查残差,看看残差相对于 X 的曲线中是否存在任何趋势:
****fig, ax = plt.**subplots**()fig.**suptitle**('Raw residuals of Pooled OLS versus X')plt.**ylabel**('Residual (y - mu)')plt.**xlabel**(**'X='**+**str**(X_var_names[0]))ax.**scatter**(pooled_X[X_var_names[0]], pooled_olsr_model_results.**resid**, **s**=4, **c**=**'**black**'**, **label**=**'**Residual Error**'**)plt.**show**()****
我们看到下面的情节。对于 X 的不同值,残差似乎没有恒定的方差。我用红色箭头标出了差异趋势:
混合 OLS 模型的残差与 x 的关系图。该图显示异方差残差(图片由作者提供)
可以通过运行白色测试来确认异方差,其中我们将回归 X 上的残差平方,并测试所得回归模型系数的显著性,如下所示:
****keys = [**'Lagrange Multiplier statistic:'**, **'LM test\'s p-value:'**,
**'F-statistic:'**, **'F-test\'s ' 'p-value:'**]results = **het_white**(**resid**=pooled_olsr_model_results.**resid**, **exog**=pooled_X)print(**'Results of the White test for heteroskedasticity of residual errors ===> '**)
print(**lzip**(keys,results))****
我们看到以下输出:
******Results of the White test for heteroskedasticity of residual errors ===>
[(‘Lagrange Multiplier statistic:’,** 9.918681580385458**), (“LM test’s p-value:”,** 0.007017552347485667**), (‘F-statistic:’,** 5.186450932829045**), (“F-test’s p-value:”,** 0.006582734100668208**)]******
LM 检验的 p 值是< .001 indicating a 对残差是同伦齐次的 White 检验的零假设的拒绝。
如前所述,混合 OLS 回归模型将产生总体值的无偏估计,即使拟合模型的残差是异方差的。但是残差中的异方差将违反高斯-马尔可夫假设中的一个,该假设使 OLS 估计量成为手头问题的最佳线性无偏估计量。具体而言,当残差是异方差的时,OLS 估计器变得 低效 ,即,它失去了在所有可能的线性无偏估计器中生成具有最低可能方差的预测的能力。当残差是异方差的时,OLS 估计量会低估或高估参数估计中的方差,导致参数估计的标准误差被遗漏指定。由于标准误差用于计算置信区间,参数估计的置信区间也变得不正确。对于与模型预测相关的标准误差和置信区间,也可以看到相同类型的不规范。
残差与响应变量 y 相关吗?
让我们绘制相对于 y=GDP_PCAP_GWTH_PCNT 的残差:
****fig, ax = plt.**subplots**()fig.**suptitle**('Raw residuals of Pooled OLS versus y')plt.**ylabel**('Residual (y - mu)')plt.**xlabel**('y')ax.**scatter**(pooled_y, pooled_olsr_model_results.**resid**, **s**=4, **c**=**'**black**'**, **label**=**'**Residual Error**'**)plt.**show**()****
我们得到如下的情节:
混合 OLS 模型相对于 y=GDP_PCAP_GWTH_PCNT 的残差图(图片由作者提供)
在残差和 y 之间似乎有一个线性趋势。使用 皮尔逊 r 的相关性测试证实了这一视觉判断:
****keys = [**'Pearson\'s r:'**, **'p-value:'**]results = st.**pearsonr**(**x**=pooled_y, **y**=pooled_olsr_model_results.**resid**)print(**'Results of the Pearson\'s r test of correlation between the residual errors and the response variable y ===>'**)**print**(**lzip**(keys,results))****
我们看到以下输出:
******Results of the Pearson's r test of correlation between the residual errors and the response variable y ===>**
[("**Pearson's r:**", 0.6149931069935411), ('**p-value:**', 3.996454333518694e-18)]****
第一个值 0.61499 是残差和之间的相关量(~ 61%),第二个值 3.99645e-18 是结果的 p 值。我们将忽略报告的 p 值,因为我们知道残差远非正态分布。无论如何,报道的相关性(61%)本身明显大于零,因此是显著的。**
回归残差和响应变量之间的高度相关性表明,我们的混合 OLSR 模型缺少重要的解释变量,否则这些变量将能够“解释”这种相关性。无论该国的人均 GDP 增长率( y )如何变化,总资本形成率( X )都无法解释已经以与 y 相关和异方差的形式泄漏到残差中。
残差是自相关的吗?
让我们绘制残差的自相关函数(ACF)图:
****tsap.**plot_acf**(**x**=pooled_olsr_model_results.**resid**)**plt**.show()****
我们看到下面的情节:
混合 OLSR 模型残差的自相关图(图片由作者提供)
滞后 0 时 1.0 的完美相关性将被忽略,因为一个数总是与其自身完美相关。但我们看到滞后 1、2 和 3 处的残差之间存在显著的自相关。
正如残差中的异方差一样,残差中的自相关违反了高斯-马尔可夫假设中的一个假设,该假设使 OLS 估计量变蓝。具体来说,自相关残差会导致标准误差被遗漏指定(低估),从而导致 t 值(或 z 值)被高估,并且参数估计的置信区间被遗漏指定。实际上为零(即无关紧要)的系数可能被错误地报告为非零(重要)。
调查结果摘要
总之,我们发现我们为世界银行数据集构建的混合 OLS 回归模型具有以下特性:
- 其调整后的 R 平方约为 62% 对于真实世界的数据集来说,这并不坏。
- 发现模型的参数系数在 p<0.001 处显著。
- f 检验表明参数系数在 p<0.001 处联合显著。
- 模型的残差不是正态分布的,这意味着与模型预测相关的标准误差和置信区间可能不完全可靠。
- 残差是异方差的,这意味着模型参数的参数显著性 t 检验结果、参数估计的相应置信区间以及 f 检验结果并不完全可靠。该结论适用于与模型预测相关的标准误差和置信区间。
- 残差与响应变量y相关,这意味着模型遗漏了重要的回归变量,否则这些变量将与y相关,它们的缺失导致相关性的余额泄漏到残差中。******
- 残差在滞后 1、2 和 3 处是自相关的,这意味着模型参数估计的标准误差可能被低估,而报告的 z 值(或 t 值)相应地被高估。从功能上讲,残差中的自相关意味着回归模型的一般不规范。
总的来说,混合 OLSR 模型的残差分析指向了手头问题的回归模型的错误规范。我们也许可以用面板数据集的另外两种回归模型中的一种做得更好,即固定效应和随机效应回归模型。
在我下周的文章中,我们将深入探讨固定效应回归模型,并研究如何在世界银行数据集上构建和拟合 FE 模型。我们将比较它与集合 OLSR 模型的拟合优度。
这里是本文使用的世界银行数据集的 下载链接 。
下面是本文中使用的完整源代码:
参考文献、引文和版权
数据集
世界发展指标世界银行数据 CC BY 4.0 license 。 下载链接
纸质和图书链接
巴蒂·h·巴尔塔吉, 面板数据的计量经济分析 ,第 6 版,施普林格**
威廉·h·格林, 计量经济分析 ,第 8 版, 2018,培生****
形象
本文中所有图片的版权归 CC-BY-NC-SA 所有,除非图片下面提到了不同的来源和版权。
如何用 Python 构建实时转录 App
原文:https://towardsdatascience.com/how-to-build-a-real-time-transcription-app-in-python-7939c7b02614
使用 AssemblyAI 和 Streamlit 的分步教程
介绍
实时转录应用程序是一种实时提供语音实时转录的应用程序。这种应用程序使用语音识别引擎将口语转化为文本,然后实时显示在屏幕上。该应用程序可以用于各种目的,包括转录讲座,会议和会议。
使用实时转录应用程序有几个好处。首先,它可以帮助你捕捉发生的想法和对话。这对于在快节奏环境下工作或者有很多想法的人来说特别有用。其次,可以帮助你提高沟通能力。这是因为你可以看到自己怎么说话,别人怎么说话。这有助于你找出可以改善沟通的地方。第三,该应用程序也可能被听力有困难的人或学习英语的人使用,因为该应用程序可以帮助实时转录音频,以便用户可以在说话时看到屏幕上的文本。然后,可以对转录的文本应用自然语言处理,以供进一步分析。
在本文中,我们将探索如何使用 AssemblyAI API 作为后端,Streamlit 作为前端,用 Python 构建一个实时转录应用程序。
为了补充本文,您还可以观看视频版本:
如何使用 AssemblyAI 和 Streamlit 在 Python 中构建实时转录 Web 应用
实时转录应用程序的高级概述
在本文中,我们将用 Python 构建一个实时转录 web 应用程序,它将允许我们实时执行语音到文本的转录。
为此,我们将利用 Python 中的几个库,如下所示:
- 我们将用来存放所有输入和输出小部件的 web 框架。
websocket
—允许应用程序与 AssemblyAI API 交互。asyncio
—允许应用程序以并行方式执行所有各种音频输入和输出。base64
—允许应用程序在音频信号发送到 AssemblyAI API 之前对其进行编码和解码。json
—读入由 AssemblyAI API 生成的音频输出(即转录文本)。pyaudio
—对通过端口音频库输入的音频进行处理。os
和pathlib
—用于浏览项目的各个文件夹,并执行文件处理和操作。
设置工作环境
要在您自己的电脑上重新创建实时转录应用程序,我们可以从创建名为transcription
的 conda 环境开始:
conda create -n transcription python=3.9
您可能会看到安装 Python 库依赖项的提示,当您这样做时,点击键盘上的Y
按钮进行确认并继续。
一旦我们创建了 conda 环境,您就可以按如下方式激活它(您需要在每个编码会话中执行此操作):
conda activate transcription
在您的编码会话之后,您可以退出 conda 环境,如下所示:
conda deactivate
下载 GitHub repo
现在,我们通过 GitHub 下载实时转录 app 的完整回购如下:
git clone [https://github.com/dataprofessor/realtime-transcription](https://github.com/dataprofessor/realtime-transcription)
进入realtime-transcription
文件夹,如下所示:
cd realtime-transcription
接下来,我们可以安装应用程序使用的必备库:
pip install -r requirements.txt
获取 AssemblyAI API 密钥
访问 AssemblyAI API 非常简单,从向 AssemblyAI 免费注册开始。
接下来,登录到您的帐户后,您将在右侧面板中找到 API 密钥,如以下截屏所示。
如何获取 AssemblyAI API 的截屏?
现在您已经将 API 密匙复制到内存中,您将希望将其粘贴到位于名为.streamlit
的文件夹中的secrets.toml
文件中(即文件路径为.streamlit/secrets.toml
),该文件应该包含以下内容:
api_key = ‘xxxxx’
其中xxxxx
应该由 API 键替换。
在下一步中,我们可以通过st.secrets[‘api_key’]
命令检索这个 API 密钥。
运行实时转录应用程序
在运行实时转录应用程序之前,我们先来看看工作目录的内容(如 Bash 中的tree
命令所示):
实时转录文件夹的内容。
我们现在准备推出实时转录应用程序:
streamlit run streamlit_app.py
这将在新的互联网浏览器窗口中打开应用程序:
实时转录 app 截图。
现在,让我们在下面的截屏中看看应用程序的运行情况。
应用程序运行的截屏。
代码的解释
在这里,我们将解释应用程序的底层代码。
- 第 1–8 行 —导入 web 应用程序使用的必备库。
- 第 10–13 行 —启动应用程序使用的会话状态。
- 第 15–22 行 —通过
text_input
小部件提供用于接受用户音频参数输入的输入小部件。 - 第 24–31 行 —上述代码块提供的输入音频参数用于通过
pyaudio
打开音频流。 - 第 33–46 行 —定义了 3 个自定义函数(如
start_listening
、stop_listening
和download_transcription
),这些函数将在代码的后面被调用,我们稍后会谈到。 - 第 49 行 —通过
st.title
命令显示应用的标题。 - 第 51–62 行 —使用
st.expander
命令显示该应用的关于信息。 - 第 64–67 行 —创建 2 列(即通过
st.columns
命令)用于放置开始和停止按钮(即通过按钮部件中的on_click
选项使用start_listening
和stop_listening
)。 - 第 69–139 行 —音频输入和输出的处理在这里执行,音频信号被发送到 AssemblyAI API,在那里转录的文本以 JSON 格式获得。这段代码是由 Misra Turp 和 Giorgios Myrianthous 开发的代码修改而来。
- 第 141–144 行 —显示转录下载按钮,然后删除文件。
结论
恭喜你,你已经使用 AssemblyAI API 用 Python 构建了一个实时转录 app。正如本文前面提到的,该应用程序有几个使用案例(例如听写文章或电子邮件,用于提高沟通技巧,为重听人抄写等。).诸如自然语言处理的进一步顶层分析然后可以应用于转录的文本。
接下来读这些
- 数据科学如何掌握 Python
下面是数据科学需要的必备 Python - 如何掌握数据科学的熊猫
下面是数据科学需要的必备熊猫 - 如何用 Python 构建 AutoML App
使用 Streamlit 库的分步教程 - 学习数据科学的策略
打入数据科学的实用建议 - 如何免费搭建一个简单的作品集网站
不到 10 分钟从头开始的分步教程
✉️ 订阅我的邮件列表,获取我在数据科学方面的最佳更新(偶尔还有免费赠品)!
关于我
目前,我是 Streamlit 的全职开发人员。此前,我是泰国一所研究型大学的生物信息学副教授,数据挖掘和生物医学信息学负责人。在我下班后的时间里,我是一名 YouTuber(又名数据教授)制作关于数据科学的在线视频。在我做的所有教程视频中,我也在 GitHub 上分享 Jupyter 笔记本(数据教授 GitHub page )。
https://data-professor.medium.com/membership
在社交网络上与我联系
YouTube: http://youtube.com/dataprofessor/
网站: http://dataprofessor.org/
LinkedIn: https://www.linkedin.com/company/dataprofessor/
推特: https://www.twitter.com/thedataprof
脸书: http://facebook.com/dataprofessor/
GitHub: https://github.com/dataprofessor/
Instagram:
如何建立不连续数据的回归模型
原文:https://towardsdatascience.com/how-to-build-a-regression-model-for-discontinuous-data-bf4b493a491f
我们将研究如何对不连续数据的一种常见情况进行建模
大多数现实世界中生成数据的过程都受现实世界事件的支配。随着季度业绩的公布和天灾人祸的消息,股票价格会暴跌和飙升。随着金融危机、衰退和供应冲击的爆发,失业和油价等宏观经济指标会经历突然的趋势逆转。
以在足够长的时间内收集的任何真实世界的时间序列数据为例,你很难不发现至少一个趋势的急剧上升或下降,其严重程度足以将序列分为“之前”和“之后”部分。
在这种情况下,分析师的工作不仅是建立一个对这种不连续性稳健的统计模型,而且还要估计导致这些不连续性的事件的影响。
研究人员开发了许多技术来实现这双重目标。我们将在不连续(或几乎不连续)数据的常见情况下研究这样一种技术。
我们来看看下面这张图表,显示了美国从 2002 年 1 月 1 日到 2020 年 1 月 1 日的每周失业率。该数据包含了一次大衰退,即从 2007 年 12 月延续到 2009 年 6 月的“T2 大衰退”。
美国劳工统计局,失业率[UNRATE],检索自弗雷德,圣路易斯美联储银行;2022 年 6 月 18 日(公共领域数据)
如果我们希望为这些数据构建一个回归模型,我们至少有以下几种不同的方法:
- 我们可以构建一个分段回归模型,对上述数据集的三个不同部分进行建模,即衰退之前、期间和之后的部分。
- 我们可以使用一种称为回归扭结设计的回归技术。
- 我们可以用一个隐马尔可夫模型进行实验。具体来说,一个 2 状态马尔可夫转换自回归(MSAR)模型。这两种状态将表示衰退和非衰退阶段。MSAR 模型也应该能够代表在这样的时间序列数据集中必然存在的自相关。
- 最后,我们可以简单地选择在衰退期不对数据建模,从而将衰退期压缩到零宽度区域。因此,与前三种方法相反,我们不会对衰退期间时间序列的行为感兴趣。因此,我们也需要准备好丢失包含在经济衰退期数据集中的信息。
但是,如果我们简化这一点,有些人可能会说,这是一个不正确的决定,在时间序列的衰退阶段丢弃数据点,这就为以下有趣的线性模型打开了大门:
失业率的回归不连续模型(图片由作者提供)
在上面的模型中:
- β_0 为截距。
- β_1 是时间周期变量的系数。 Time_Period 为正整数,取 1、2、3 等。我们引入这一变量是为了捕捉经济衰退之前和之后这两个数据部分的月环比趋势。
- β_2 是 虚拟变量 历元的系数。我们将位于衰退开始之前的数据集部分的纪元设置为 0,将位于衰退阶段结束之后的数据集部分的纪元设置为 1。
- ϵ 是一个误差项,它捕捉了我们的模型无法解释的未评级方差。
这里有一个到数据集的链接,该数据集包含就业率、时间段和纪元变量。它不包含衰退阶段包含的数据点。
建立和训练回归模型
让我们使用 Python、Pandas 和 statsmodels 来构建和训练这个模型。
我们首先将数据集加载到 Pandas 数据框架中:
**import** pandas **as** pd
**import** statsmodels.formula.api **as** smf
**import** statsmodels.graphics.tsaplots **as** tsa
**from** matplotlib **import** pyplot **as** pltdf = pd.read_csv(**'unemployment_rate_us_fred.csv'**, header=0)
接下来,让我们用 Patsy 语法构造回归表达式。
reg_exp = **'UNRATE ~ Time_Period + Epoch'**
在上面的表达式中,请注意,回归截距并未明确提及,但是当我们使用它来构建模型时,statsmodels 会自动包含它。
让我们使用 statsmodel 构建 OLS 模型。我们将回归表达式和数据集作为参数传递:
regdis_model = smf.**ols**(**formula**=reg_exp, **data**=df)
接下来,让我们训练模型并打印训练总结:
regdis_model_results = regdis_model.**fit**()
**print**(regdis_model_results.**summary**())
我们看到以下输出。我在输出中突出了几个有趣的区域:
回归模型的训练输出(图片由作者提供)
分析模型性能
在右上角,我们观察到调整后的 R 平方为. 925。该模型能够解释 92.5%的失业率差异。
在调整后的 R 平方的正下方,我们看到 Statsmodels 报告了用于回归分析的 F 检验的输出。已经为我们计算了 F 统计量,其值为 1220,p 值为 1.09E-111。f 检验的输出表明,在 p 为< .001 时,模型的系数是共同显著的,这意味着,该模型在解释未评级的方差方面比均值模型做得更好(在这种情况下,做得好得多)。
让我们将注意力转向输出的中心部分,在这里我们可以看到系数估计值、它们的标准误差、p 值和估计值周围的置信区间。我们看到,所有三个系数的估计值在< .001.
The coefficient of 时间段的 p 值处是显著的(— 0.0525),这表明在衰退阶段的任一侧,在时间段中,失业率估计会以 0.0525(约 5%)的平均率下降。回想一下,在我们的数据集中,单位时间段是一个月。
最后,纪元的系数提供了一个有趣的见解。其值为 6.3757。我们的模型估计,2008 年至 2009 年的大衰退已经导致美国失业率平均增加了 6.3757%,95%的置信区间相当窄,从 6.111%到 6.641%。
残差分析
让我们看看 statsmodels 报告的残差正态性的 Jarque-Bera 和综合测试 的结果:
两个测试的 p 值都在 0.05 以上,从而验证了测试的默认假设,即残差呈正态分布。这意味着,我们可以依赖模型报告的置信区间估计。这是好消息。
然而,德宾-沃森检验的统计数据在< 2.0 indicating a positive auto-correlation among the residual errors. The test’s finding is vindicated by the following auto-correlation plot:
Auto-correlation plot of the residual errors (Image by Author)
The above plot can be produced by executing the following two lines of code:
tsa.**plot_acf**(regdis_model_results.**resid**)
plt.**show**()
The plot shows a strong auto-correlation at LAG-1, which means that each value in the time series of residual errors is correlated with the value that immediately precedes it in the time series. Since values at LAG 1 and LAG 2 are correlated, and LAG 2 and LAG 3 are similarly correlated, LAG 1 and LAG 3 are also correlated but to a lesser extent. Thus we see a gently sloping curve of correlations at the other lags also.
A strong auto-correlation of this type in the residuals implies that our model is missing one of more key explanatory variables. Or, the entire functional form of our model may need to be revisited. Perhaps, one of the other three kinds of models suggested at the beginning of the article would prove to be more effective in explaining the variance in UNRATE.
Nevertheless, our plucky little linear model seems to have held up well to the scrutiny. It has allowed us to model the discontinuity that 出来,我们将引入失业数据集中。它不仅估计了大衰退双方的失业趋势,还为我们提供了一种科学估计大衰退对失业率影响的方法。
参考文献、引文和版权
数据集
美国劳工统计局,失业率[UNRATE],从圣路易斯美联储银行检索;https://fred.stlouisfed.org/series/UNRATE。(在公共领域可用)。本文中使用的数据集的精选版本 可以从这里 下载。
形象
本文中的所有图片版权归 Sachin Date 所有,版权归 CC-BY-NC-SA 所有,除非图片下面提到了不同的来源和版权。
如果您喜欢这篇文章,请关注我的Sachin Date以获得关于回归、时间序列分析和预测主题的提示、操作方法和编程建议。
如何用 Python 构建一个简单的 Kafka 生产者和消费者
阿帕奇卡夫卡建筑简介。
Johannes Plenio 在 Pexels.com 拍摄的照片
建议的点播课程
我的一些读者联系我,要求提供点播课程,以了解更多关于 阿帕奇卡夫卡 的知识。这是我推荐的 3 个很好的资源:
>>>还不是中等成员?考虑与我的 推荐链接 签约,以获得 Medium 必须提供的一切,费用低至每月 5 美元!
介绍
在您作为数据工程师的职业生涯中,您会自然而然地超越批处理(这意味着查询有界数据集),并熟悉流处理中使用的工具。在流处理中,数据是无限的,并且在查询时可能是不完整的。
业界领先的流数据框架之一是 Apache Kafka 。Kafka 是一个工具,它允许工程师根据主题实时生成数据。消费者可以读取和处理存储在这些主题中的数据。
从概念上讲,主题类似于数据库中的表,但是主要的区别在于,在数据库中记录可以被覆盖,而 Kafka 将主题作为日志来维护,这些日志是只附加事件的有序集合。主题可以存储为单个日志,也可以水平扩展为分区。
在本教程中,您将学习如何构建一个本地 Apache Kafka 集群。你还将学习如何使用 Python 在卡夫卡中创建生产者和消费者。尽管有许多 Kafka Python 库,但在这里你会熟悉由 Confluent 提供的一个。
要安装这个库,使用下面的pip
命令:
***pip3 install confluent-kafka***
一旦安装了库,您将能够在您的应用程序中导入它。
在讨论生产者和消费者之前,下一节将带您通过 Docker 设置一个本地 Kafka 集群。
用 Docker 运行一个本地 Kafka 集群
为了在本地运行 Kafka 集群,你需要两样东西:Kafka 经纪人和动物园管理员。
代理是一台机器- 托管一个或多个分区 -负责处理向这些分区写入新事件或从中读取事件的请求。根据具体的用例,Kafka 集群可以由一台机器或一个机器网络组成
相反,Zookeeper 被定义为一种集中式服务,它在分布式系统中提供灵活和健壮的同步,并跟踪 Kafka brokers 的状态以及主题和分区。
设置它们最方便的方法是使用 Docker compose 文件来运行多个容器,并使用一个配置脚本启动所有的东西。
在本教程中,您将使用存储在 this GitHub repo 中的docker-compose.yaml
文件(记得保存在与 Kafka 生产者和消费者 Python 文件相同的目录中)。通过打开docker-compose.yaml
,你会看到下面的代码:
上面的配置文件和 confuent 'Apache Kafka 快速入门 页面上共享的模板几乎一模一样。
如您所见,它利用了 融合图像 的优势,因此运行它将确实创建两个容器,一个用于代理,一个用于 Zookeeper。要通过 CLI 构建这两个容器,请使用以下命令:
***docker-compose up -d***
这将引导您看到提示:
*Status: Downloaded newer image for confluentinc/cp-zookeeper:7.0.1
Status: Downloaded newer image for confluentinc/cp-kafka:7.0.1
Creating zookeeper ... done
Creating broker ... done*
恭喜你!您已经通过 Docker 在本地成功建立了一个 Kaka 集群。
打造一个卡夫卡制作人
既然您的 Kafka 集群正在后台运行,那么有趣的部分来了:用 Python* 构建一个生成器。*
要编写一个生产者,您应该创建一个生产者实例,发送数据并监听确认。在下面的例子中,您将使用 Faker 模拟关于用户的虚假数据的生成,并将它们写入到user-tracker
主题中。要执行的步骤如下:
- 导入所需的库并创建一个 faker 对象:
*from confluent_kafka import Producer
from faker import Faker
import json
import time
import logging
import random fake=Faker()*
-
配置日志的格式。每当有新事件可用时,日志将被附加到主目录中的一个
producer.log
文件中: -
通过指定 Kafka 集群的端口来创建生成器:
-
定义一个负责确认新消息或错误的回调函数。当一个有效的信息变得可用时,它被解码成
utf-8
并以首选格式打印出来。相同的消息也会附加到日志文件中: -
编写一个生产者循环,模拟当前月份中十个用户注册事件的创建。每条消息都从字典转换成 json 格式发送给 Kafka:
如您所见,在向 Kafka 发送数据之前,main()
函数正在调用poll()
向生产者请求任何以前的事件。如果找到,事件被发送到回调函数(回执)。在这种情况下,p.poll(1)
意味着允许 1 秒的超时。
最后,生产者也被刷新(p.flush()
),这意味着阻塞它,直到先前的消息被有效地传递,使它同步。
构建 Kafka 生成器的完整代码可从这里获得。如果您现在尝试使用以下命令通过 CLI 运行它:
***python kafka_producer.py***
输出将是发送到 Kafka 集群上的user-tracker
主题的消息(以及写入producer.log
文件的消息),终端将显示确认,如下所示:
通过 CLI 运行 Kafka 生成器的结果
建立一个卡夫卡式的消费者
在卡夫卡的作品中,消费者生来就是为了阅读并经常清理、转换或丰富来自主题的信息。在其核心,消费者作为一个无限循环运行,等待消息被传递到他们正在收听的主题。**
可以从头开始阅读消息(主题中的第一条消息)或从主题中的特定位置开始阅读,称为偏移,由 Zookeeper 跟踪。**
下面的代码将向您展示如何构建 Python 消费者:
-
导入
Consumer
库并创建消费者实例。您需要传递 Kafka 集群正在运行的端口、一个消费者组名称,以及偏移重置(,在这里消费者应该开始读取): -
确定应该消费的主题的名称并订阅它。如果有不止一个主题可用,您可以使用
list_topics().topics
命令列出它们的名称: -
为了开始接收事件,您创建了一个无限循环来轮询主题,寻找任何可用的消息。用户始终可以调整到从特定偏移开始和停止:
特别是,以下代码的行为方式如下:
- 如果没有消息,它就一直等待,
- 如有错误,将显示
- 当消息为资金时,将被解码为
*utf-8*
:
构建 Kafka 消费程序的完整代码可在这里获得。如果您现在在终端中打开两个窗口并再次运行生成器:
***python kafka_producer.py***
其次是消费者:
***python kafka_consumer.py***
您会注意到,由生成的生成的消息将在短暂延迟后开始显示在使用者窗口中:
通过 CLI 运行 Kafka 消费程序的结果
这意味着您的消费者正在按预期工作…成功了!**
结论
在本文中,您开始了解 Kafka,特别是如何使用 Python confluent_kafka
包创建一个简单的 Kafka 生产者和消费者。
《T4》是一个很基本的例子,说明了如何利用卡夫卡作为一种技术(只是触及了表面!但是应该给你一个架构的概念,以及如何开始构建更高级的逻辑。**
来源
你可能也会喜欢
*💔-nanodegrees-you-should-consider-to-advance-your-data-engineering-career-in-2021-baf597debc72> 💔-ways-to-create-tables-with-apache-spark-32aed0f355ab> *
如何构建一个 Streamlit 应用程序来从 YouTube 视频中提取主题
AssemblyAI 的主题检测功能概述
想象一下,运行一个平台,用户定期上传自己的视频。你将如何对这些不断增长的内容进行分类,并在相关类别中进行标记,以便将来的访问者可以轻松找到它们?
第一种方法是分析用户补充的元数据。这通常是文本格式。它可以是一个标题或描述,有时是一系列标签——(这就是 Youtubers 所做的)
但是如果这些元数据丢失了呢?你还能对视频内容进行分类吗?
本帖将尝试通过使用assembly ai语音转文本 API 及其话题检测 特性 来回答这个问题。我们将了解这项功能是如何工作的,以及如何将它嵌入到从 Youtube 视频中提取主题的 Streamlit 应用程序中。
最后将提供演示和代码 💻。
事不宜迟,让我们来看看🔍。
👉如果你想了解更多关于 AssemblyAI API 的知识,我建议你阅读我之前的两篇文章:
一种新颖的话题检测方法
AssemblyAI 提供了一个人工智能支持的功能,可以提取音频或视频文件中的主题。
我发现这个功能有趣的地方是 AssemblyAI 如何处理主题检测问题。
令人惊讶的是,它似乎没有使用经典的无监督 NLP 技术,如潜在狄利克雷分配(LDA)或潜在语义索引(LSI)。
相反,AssemblyAI 应用的是一个包含 689 个类别的标准化分类法上的多标签分类。
乍一看,这似乎有点牵强,但是在多个例子上运行 API 之后,结果证明是相当令人信服的。我们将在演示中看到更多相关内容。
AssemblyAI 使用的分类法被称为 IAB 分类法。它由互动广告局维护,这是一个为在线广告制定行业标准的美国组织。因此,它被出版商用来轻松地组织他们的网站内容。这也使得提取的主题适合于上下文定位场景。
这是一个详细描述 IAB 分类的表格。
我仔细看了一下,发现它确实涵盖了广泛的主题。以下是一些例子:
- 关于汽车的话题
作者截图
- 关于服装的话题
作者截图
- 关于政治的话题
作者截图
现在你可以争辩说,你的音频文件可能集中在一些不属于这个分类的非常具体的主题上。在这种情况下,您可以使用 AssemblyAI 首先获取脚本,然后使用定制方法自己执行提取。
如何激活话题检测功能?
就像激活内容审核特性一样,激活主题检测就是在请求体中添加一个参数。该参数是iab_categories
键,必须设置为真。
要执行转录和主题检测,您可以使用以下 shell 命令从终端调用 API:
使用 Python,这可以转化为:
当您发送 POST 请求时,会向处理队列提交一个转录作业。此任务是异步的,可能需要一些时间才能完成。
为了等待处理队列完成并在之后获取输出,您可以很容易地想象一个 while-loop ,它会休眠一段时间并继续运行,直到处理完成。
一旦转录完成,您应该得到以下输出。
作者截图—带话题检测的转录
有一些常见的东西:你可以查看 API 文档来了解更多关于这些字段的信息。
新增的是返回话题检测结果的**iab_categories_result**
键。
每个结果对应于音频文件的一部分(该部分由start
和end
时间戳界定),并且具有提取的主题列表(也称为标签),这些主题按照相关性的降序排序。
例如,马丁·路德·金演讲的第一部分分为:
- 事件和选举>政治事件
- 新闻和政治政治政治政治问题 T21
- 新闻与政治>政治
从 YouTube 视频中提取主题🎥
这个周末我有一些空闲时间,所以我构建了一个从 Youtube 视频中提取主题的 Streamlit 应用程序。
在寻找可视化结果的直观方式时,我首先遇到了streamlit-timeline,这是一个 Streamlit 组件,允许您可视化带有时间编码事件的交互式时间线。
作者 GIF
我考虑显示视频中同时开始的部分,而不是事件。然而,我很快就面临着在每张幻灯片中嵌入相应视频的问题。
这时候我转到了 streamlit-player 。
该组件允许您在 Streamlit 中嵌入 Youtube 视频,通过正确的参数设置,它甚至可以使视频在特定的时间戳开始和结束:这对于用例来说是完美的。
试玩!🚀
在分享代码之前,这里有一个一分钟的视频演示。
作者的视频——使用 AssemblyAI 从 Youtube 视频中提取主题的 Streamlit 应用程序演示
这款应用非常简单:它首先要求你提供一个视频网址,一旦你点击了转录按钮,它就会执行一系列任务:
- 它从 YouTube 视频中提取音频
- 它把音频上传到 AssemblyAI 服务器
- 它提交一个带有主题提取的转录作业
- 它获取结果并保存它们
- 它显示输出:对于每个结果,它嵌入相应的视频部分、转录的文本以及提取的主题列表。
该应用已上线。你可以在这里试用一下https://share.streamlit.io/ahmedbesbes/assemblyai/main/app.py****:注意,它使用的是我的 API 密匙,链接到一个自由计划账户。如果每月使用量超过其限制,您将无法转录视频。
但是,您仍然可以可视化一些预先计算的示例。
如果你想在本地运行应用程序,代码可以在 Github 上找到。您可以通过简单地安装需求并启动 Streamlit 命令来运行它。
**git clone** [**git@github.com**](mailto:git@github.com)**:ahmedbesbes/assemblyai.git
cd assemblyai/
pip install requirements.txt
streamlit run app.py**
如果您对代码有任何疑问,请随时联系我们。
深入挖掘参考资料
- https://docs . assembly ai . com/audio-intelligence # topic-detection-iab-classification
- https://github.com/okld/streamlit-player
- https://towards data science . com/how-to-transcripte-and-analyze-audio-files-with-python-and-assembly ai-22660 dbf8e 66
- https://towards data science . com/how-to-moderate-audio-data-using-python-and-assembly ai-a5eab 9910730
感谢阅读🙏
这是我在 AssemblyAI 系列的第三篇文章。我希望您能从这个软件和我们构建的 Streamlit 应用程序中学到一些有用的东西。
不要犹豫克隆代码或运行它。如果你有问题,你可以联系我。
下一个帖子将是关于 AssemblyAI 的最后一个帖子:它将涵盖实时转录,敬请关注。
今天就这些了。下次见!👋
新到中?你可以每月订阅 5 美元,并解锁各种主题的无限文章(技术、设计、创业……)你可以通过点击我的推荐链接来支持我
**https://ahmedbesbes.medium.com/membership
如何构建成功的仪表板
原文:https://towardsdatascience.com/how-to-build-a-successful-dashboard-359c8cb0f610
一份清单,来自某个制造了几个不成功产品的人
在我人生的这个阶段,我想我已经设计了一百多个不同的仪表盘。随着我越来越资深并开始管理一个团队,我对这些任务变得越来越谨慎——质疑每个仪表板请求的实际需求和期望值。构建一个有效的仪表板实际上需要时间——当需求没有被正确定义时,它会很快变成一个数月的噩梦(最终没有人使用它)。
人们通常会很快要求一个新的仪表板。构建仪表板是做一些实际上有形的事情,也就是说,你正在构建一个可以在“真实世界”中发布的产品(与研究相反,研究更抽象)。但是最终,如果没有一个明确的问题可以由仪表板解决,或者如果构建仪表板的成本比它将创造的价值更重要,那么接受这个项目可能是浪费时间。
由于您的时间很宝贵,下面是一个清单,遵循它可以增加您的仪表板项目的成功机会。
在 Unsplash 上由 Carlos Muza 拍摄的照片
步骤#1:定义用例及受众
在开始实际工作之前,您应该清楚一些事情,特别是:您为什么要构建这个仪表板,以及为谁构建。
“艰难的选择,轻松的生活。容易的选择,艰难的生活。”——杰西·格雷戈雷克
根据我的经验,在这个阶段,重要的是要明确什么是用例,不是用例,以及谁是目标受众。如果你在一开始就做出这些“艰难”的选择,这会让你的生活变得更容易——所以请确保正确回答以下问题:
- 这个仪表盘试图解决什么问题?这将是需要回答的第一个问题。如果你的仪表板不能解决任何问题,人们就不会使用它。通过清楚地定义问题,您可以更好地了解仪表板将产生什么价值,这可以帮助您估计您在这个项目中的个人投资应该是多少(参见我的文章“如何选择要处理的数据项目”以获得更多信息!)
- 对什么不会有用?清楚仪表盘的用处和用处,可以让你确保自己没有使用仪表盘,也就是说,过多的信息淹没了界面,使其难以使用。它对内部品牌也非常有用——如果很明显你的仪表板只对做 X 有用,你的仪表板在内部会被称为做 X 的仪表板。
- 谁将是该仪表板的受众?为您的受众量身定制体验。例如,如果你的读者不熟悉你所报道的业务,你应该在数据中加入更多的内容。如果他们不知道如何使用过滤器,你就不应该添加过滤器。如果他们主要使用他们的移动设备,确保它是移动友好的。招募一些能够代表你的受众的测试人员——他们可以给你关于任何模型和最终产品的反馈。
- 你如何知道你的仪表板是否成功?这是一个棘手的问题,经常被忽视。在这个项目结束时,你会希望有一个简单的标准来决定这是成功还是失败。它可以是基于使用的(例如,“每月有超过 X 人连接到仪表板”),也可以是基于项目的(例如,“大多数项目 Y 的决策都是基于仪表板提供的数据”)。
第二步:基准//寻找灵感
既然你对成功的样子和你应该建立的东西有了一个清晰的想法,现在是时候更好地了解你的受众以及他们与数据的关系了。他们在数据之旅中处于什么位置?他们目前在使用哪些数据?他们的数据梦想是什么?理解它们是让您的仪表板成功的关键:
- 我们的组织过去是否尝试过解决这个问题?如果你不了解过去,你如何建设未来?如果一个解决方案在过去已经被尝试过,学习什么可行,什么不可行可能是非常强大的。
- 哪些仪表板受您的受众欢迎?你的受众已经在内部消费数据,他们可能已经习惯于看到以某种方式呈现的数据。他们是否习惯于看到它被特定维度分割?他们会喜欢你遵循特定的命名惯例吗?研究这些仪表板可以给你一个项目该做和不该做的清单。
- 没有这个仪表板,您的受众目前过得怎么样?了解你的受众目前在没有仪表盘的情况下做了什么,有助于理解他们需要仪表盘的最低价值是什么,换句话说,你的仪表盘最少应该做什么,并相应地优先考虑功能
步骤#3:原型和构建
仪表板的用户体验在仪表板的成功中起着重要的作用,而分析师们常常忽略了它的重要性。请不要忘记,仪表板是一种有形的产品,应该定期使用,确保这一点的最佳方式是与您的潜在用户一起开发它:
- 首先制作模型。建立模型(尤其是简单的,在电子表格上)并让你的潜在用户运行它,可以让你确保你覆盖了他们所有的用例,并且 UX 是理想的。保持简单专注于它试图解决的问题。想一想【倒金字塔原理】如何呈现数据。对正确类型的数据使用正确的可视化。
- 让你的潜在高级用户运行这些模型。用一些实际数据填充模型,并展示给你的 beta 测试人员(你在步骤 1 中确定的)。观察他们如何使用模型(即他们的用户旅程),以及他们是否能够自己找到所需的信息。如果他们没有,或者他们的用户之旅很痛苦——重复并再试一次。
你令人敬畏的嘲笑(作者图片)
- 构建仪表板!现在一切都已经通过了验证,你的 beta 测试人员也欣喜若狂,继续构建仪表板吧。确保数据加载足够快,不同部分之间保持一致,并且数字使用正确的格式。
第四步:测试,测试,测试
在发布之前确保仪表板工作似乎是显而易见的。但是“作品”是什么意思呢?这意味着“你的观众能够找到他们正在寻找的信息”,它有多个组成部分:
- 数字是否正确/它们是否匹配不同的数据源?没有什么比一个报告“错误”数字的仪表盘更具破坏性的了——你的听众可能会立刻失去信任。查看报告相同指标的其他仪表板和数据源,并验证您是否报告了相同的内容。
- 主要用户旅程是否按预期运行?在步骤 3 中,您确定了一系列关键用户旅程(CUJs)。试着按照这些建议去做,看看你是否能够完成关键任务——如果你不能,你应该解决这个问题。
- 不同的测试人员对最终产品满意吗?最后一次向你的 beta 测试人员寻求帮助,让他们在仪表盘上尽情驰骋。特别注意他们的问题——这些问题通常是缺少了什么或没有足够的上下文,以及仪表板可能没有按预期工作的信号。
第五步:记录一切
还记得在步骤 2 中,当你发现有人已经试图解决这个问题并记录了他们的努力时,你有多开心吗?现在是你回报的时候了!
- 数据来自哪里,如何转换?确保开始一个产品需求文档(PRD ),以记录数据来自哪里以及您正在应用哪种潜在的转换(以及为什么)。
- 你实际构建这个仪表盘的所有步骤是什么?将它添加到 PRD 中——这对你开始另一个项目后接手的同事很有用。
- 还有其他一些潜在的考虑吗?使用 beta 测试人员提出的问题(来自步骤 4)建立一个 FAQ,并直接从仪表板链接(可能在 PRD 旁边)。
第六步:发布杰作
你完了!现在是时候走向市场,向世界展示您的非凡作品,并接受祝贺信息了:
- 向所有相关利益方发送发布电子邮件。确保你写好了发布邮件,你只有一次机会留下第一印象。
- 考虑组织一次培训。如果仪表盘有点复杂,或者只面向少量用户,那么组织一次培训来确保他们知道如何使用它,并从中获得最大价值可能会很有意思。这也是为将来的迭代收集反馈和/或特性请求的好方法。
- 确定您的仪表板可被发现。如果您有一个集中的知识管理系统,请确保您的仪表板是该系统的一部分,并且您已经尽可能地对其进行了优化,以便能够找到它。
步骤 7:验证你的仪表板是成功的
还记得您在步骤 1 中为该仪表板定义的成功标准吗?现在是时候使用它,并了解你是否成功了。您是否获得了预期的用户数量?您的仪表板是否帮助正确的人做正确的事情?如果没有——调查哪里出了问题,要么修复它,要么从中吸取教训。如果是的话——庆祝吧,因为生命太短暂了。
你完了!嗯……暂时的。
因为仪表板是一种有形的产品,应该定期使用,而且一旦发布了仪表板,很多事情都可能出错(例如,目标受众可能会随着时间的推移而改变,一般需求也可能会发生变化,上游数据源可能会更新,等等。)—您应该确保您有适当的流程来维护它并相应地更新它。启动是一回事,确保它长期成功是另一回事(我将在另一篇文章中谈到这一点)..我想请继续关注。)
希望你觉得这篇文章很有见地,我的这篇长文没有让你厌烦。你会在这个清单上添加什么吗?请在评论区告诉我!
感谢阅读!
如果你觉得“有趣”,可以看看我的其他文章:
</7-tips-to-avoid-public-embarrassment-as-a-data-analyst-caec8f701e42>
如何在 BigQuery 中使用 SQL 构建唯一的 MD5 行散列(加上一些相关的东西)
使用原生 BigQuery 功能在 SQL 中生成动态的、唯一的行标识符
不是那种杂碎。在 Unsplash 上由 Richard T 拍摄的照片
动机
您可能有许多不同的原因想要为 BigQuery 数据集中的每一行数据构建散列,但它们主要与 BigQuery 中没有强制主键这一事实有关。
这意味着您的数据可能包含重复的行,无论是来自上游数据收集或传输错误、错误配置的数据摄取工具,还是仅仅因为意外加载了某个内容两次。
或者别的什么。谁知道呢?
无论重复的来源是什么,你都应该试着理解它们是什么,并可能把它们过滤掉(如果你关心这类事情,也要找出根本原因……仅供参考,你可能应该这样做)。
如果的数据中确实有的重复行,那么一旦你开始应用更复杂的转换(如连接),你就有放大错误并使下游流程、模型和决策无效的风险,这会耗费来之不易的信任,并可能导致其他不可预测的、不想要的结果。
或者也许没人会注意到。那会更好还是更坏?
无论您的数据来自何处,在任何数据质量保证流程(以及数据转换流程)中,确认源数据的每一行都是独一无二的,这始终是一个有价值的步骤,既能让您安心,又能让下游数据消费者和系统放心。
散列函数的一个简化定义是,它是一个从任意字符串输入中输出唯一的固定长度字符串的函数。它实际上比这更专业一点,因为它是一个字节数组,但它的行为像一个字符串,所以这是一个很好的看待它的方式。
需要理解的最重要的几点是:
- 对输入的任何更改都会导致不同的散列
- 它只有一种工作方式——您不能从散列中反算输入,但是您可以验证输入是否相同
- 散列使您能够检查输入是否完全相同,这对于有效的验证非常有用,尤其是在不同的系统之间,因为这样您就可以使用相同算法的特定语言实现
情况
我们将部署一些不同的本地函数和技术,以优雅、简洁和动态的方式解决这个问题。
对于这些例子,我们将使用zoo_elephants
表,它包含一些虚构的大象的西瓜年消费量的完全虚构的数据,并且是公共的,因此任何经过身份验证的 BigQuery 用户都可以查询。数据中没有重复项(但我们希望/需要证明这一点)。要检查 BigQuery 控制台中的数据,请执行以下查询:
SELECT *
FROM flowfunctions.examples.zoo_elephants
您将在结果面板中看到数据,带有简单的模式:
animal STRING,
name STRING,
year INT64,
watermelons INT64
解决办法
这是一个极其健壮和强大的函数,它(在许多用例中)使您能够向一个公共表表达式添加一列,该表达式是每行的 JSON 表示。要了解其工作原理,请尝试以下查询:
WITH
inbound_zoo_elephants AS (
SELECT *
FROM flowfunctions.examples.zoo_elephants
) SELECT *,
TO_JSON_STRING(inbound_zoo_elephants) AS row_json
FROM inbound_zoo_elephants
您将看到输出数据现在有一个额外的列,包含数据的 JSON 表示,例如第一行的row_json
列包含值:
{"animal":"Elephant","name":"Beepbeep","year":2018,"watermelons":1032}
如果在函数中添加一个true
可选pretty_print
参数:
TO_JSON_STRING(inbound_zoo_elephants, true) AS row_json
然后你可以把它打印得很漂亮,用换行符来表示行中的数据:
{
"animal": "Elephant",
"name": "Beepbeep",
"year": 2018,
"watermelons": 1032
}
这个输出较长,但更容易阅读,这可能是有用的。然而,在我们的用例中,额外的空白是不必要的。
2。 MD5()
现在对于散列函数…有几个不同的选项,给出不同长度和类型的输出。我们将使用一个简单的 MD5 ,尽管它显然被加密破解,返回 16 个字符,足以满足我们的用例。其他选项有 FARM_FINGERPRINT (返回一个可变长度的有符号整数) SHA1 、 SHA256 和 SHA512 ,分别返回 20、32 和 64 字节,对于密码用例更安全。然而,MD5 显然是最短的一个,因此它占用较少的屏幕空间(加上这不是一个加密用例),所以我们要用它:
WITH
inbound_zoo_elephants AS (
SELECT *
FROM flowfunctions.examples.zoo_elephants
),add_row_json AS (
SELECT *,
TO_JSON_STRING(inbound_zoo_elephants) AS row_json
FROM inbound_zoo_elephants
) SELECT *,
MD5(row_json) AS row_hash
FROM add_row_json
您将看到第一行的row_hash_column
值类似于:
xFkt7kQAks91FtJTt5d5lA==
这包含字母数字以及特殊字符,这将有助于我们的目标,但可能会导致其他问题。
例如,您需要三次单击它来选择它,如果您双击它,那么您只会得到第一个特殊字符(在本例中:=)之前的字符串。如果你像我一样,是一个容易犯人为错误的人,这可能是个问题。
继续,试着选择它。然后取消选择它。然后再次选择它。挺烦的吧?
3。 到 _ 十六进制
我们将用来整理这个输出的最后一个函数将把上一步的杂乱的输出转换成一个整洁的十六进制字符串,它本质上是一个包含数字和字母组合的字符串。
WITH
inbound_zoo_elephants AS (
SELECT *
FROM flowfunctions.examples.zoo_elephants
),add_row_json AS (
SELECT *,
TO_JSON_STRING(inbound_zoo_elephants) AS row_json
FROM inbound_zoo_elephants
),add_row_hash AS (
SELECT *,
MD5(row_json) AS row_hash
FROM add_row_json
) SELECT *,
TO_HEX(row_hash) AS hex_row_hash
FROM add_row_hash
执行这段代码,您会看到hex_row_hash
列的值类似于:
c4592dee440092cf7516d253b7977994
现在是 32 个可爱的小写十六进制字符。
试着双击它,你会意识到选择它的体验是一种更加人性化的交互。在一生中,这将为您节省大约33%
点击选择该选项所需的次数,这相当于更低的错误率和更低的重复性劳损几率。
注意,输出将只包含小写字母,所以如果您特别喜欢大写字母(我没有),那么您可以合理地将TO_HEX
行改为:
UPPER(TO_HEX(row_hash)) AS hex_row_hash
这给出了输出:
DCBADCD29D37091C34BAFE4EE114DBA0
然而,这是一个多余的步骤,所以我们不会这样做。另外,我只喜欢对 SQL 关键字使用大写字母,因为我发现用我人类的(也有些蹩脚的)眼睛扫描和理解代码结构更快更容易。
因此,现在公共表表达式结构的查询已经很清楚了,每个 CTE 名称都清楚地描述了它所采取的特定操作:
WITH
inbound_zoo_elephants AS (
SELECT *
FROM flowfunctions.examples.zoo_elephants
),add_row_json AS (
SELECT *,
TO_JSON_STRING(inbound_zoo_elephants) AS row_json
FROM inbound_zoo_elephants
),add_row_hash AS (
SELECT *,
MD5(row_json) AS row_hash
FROM add_row_json
),add_row_hash_hex AS (
SELECT *,
TO_HEX(row_hash) AS hex_row_hash
FROM add_row_hash
)SELECT *
FROM add_row_hash_hex
对于开发和调试来说,这是一个非常有用的结构,但是非常冗长,不太有用。作为第一步,现在我们知道所有的步骤都起作用了,我们可以重构代码,使其更加简洁:
WITH
inbound_zoo_elephants AS (
SELECT *
FROM flowfunctions.examples.zoo_elephants
)SELECT *,
TO_HEX(MD5(TO_JSON_STRING(inbound_zoo_elephants))) AS hex_row_hash
FROM inbound_zoo_elephants
这是较短的,但仍然不可重复使用。让我们把它打包成一个简单的函数,以便在需要的时候快速简单地重用它。
CREATE OR REPLACE FUNCTION `flowfunctions.hash.hex_md5_row_hash`(row_json STRING)
AS (
TO_HEX(MD5(row_json))
);
您可以通过更改project_id
(上面代码中的flowfunctions
)和dataset_name
(代码中的hash
)在您自己的项目和数据集中重新创建它。
实际上,我喜欢添加一行描述,以便用户可以就地查看文档,这样可以最大限度地减少任务切换,并添加有价值的本机可用元数据。此外,知道将row_json
参数作为TO_JSON_STRING (cte_name)
传入也很重要,所以我在描述选项中解释了这一点:
CREATE OR REPLACE FUNCTION `flowfunctions.hash.hex_md5_row_hash`(row_json STRING)
OPTIONS (
description="Returns: [STRING] Hexadecimal encoding of an MD5 hash of the JSON string representation of a row. The row_json argument should be passed as TO_JSON_STRING(cte_name) where cte_name is the name of a prior common table expression"
)
AS (
TO_HEX(MD5(row_json))
);
太好了!现在在控制台中看起来是这样的:
漂亮整洁。
执行
现在我们可以这样调用函数:
SELECT flowfunctions.hash.hex_md5_row_hash(row_json STRING)
或者镜像前一个查询的语法:
WITH
inbound_zoo_elephants AS (
SELECT *
FROM flowfunctions.examples.zoo_elephants
)SELECT *,
flowfunctions.hash.hex_md5_row_hash(inbound_zoo_elephants) AS hex_row_hash
FROM inbound_zoo_elephants
这可能比前一个版本更冗长,所以您可能实际上只想使用前一个版本,消除不必要的(在本例中)函数依赖:
TO_HEX(MD5(TO_JSON_STRING(inbound_zoo_elephants))) AS hex_row_hash
无论哪种方式,为了实现最终证明数据集中没有重复项的目标,我们需要在查询中再执行一个步骤来比较总行数和唯一行数:
WITH
inbound_zoo_elephants AS (
SELECT *
FROM flowfunctions.examples.zoo_elephants
),add_row_hash AS (
SELECT *,
TO_HEX(MD5(TO_JSON_STRING(inbound_zoo_elephants))) AS hex_row_hash
FROM inbound_zoo_elephants
)SELECT
COUNT(*) AS records,
COUNT(DISTINCT hex_row_hash) AS unique_records
FROM add_row_hash
它返回:
太棒了。
由于records
的值与unique_records
匹配,我们可以得出结论,每一行都是唯一的。太好了,我们可以继续我们的分析,而不用担心重复及其影响。
实际上,考虑到前面提到的我糟糕的视力,我将添加一个红色/绿色图标,这样我就不需要做任何复杂的心算了:
WITH
inbound_zoo_elephants AS (
SELECT *
FROM flowfunctions.examples.zoo_elephants
),add_row_hash AS (
SELECT *,
TO_HEX(MD5(TO_JSON_STRING(inbound_zoo_elephants))) AS hex_row_hash
FROM inbound_zoo_elephants
)SELECT
COUNT(*) AS records,
COUNT(DISTINCT hex_row_hash) AS unique_records,
CASE
WHEN COUNT(*) = COUNT(DISTINCT hex_row_hash)
THEN '🟢' ELSE '🔴'
END AS unique_check_icon
FROM add_row_hash
唷,现在我不需要在脑子里比较任何数字,绿灯让我知道一切都好:
很好看。
虽然在这样一个简单的例子中使用这种技术显然有点不必要,但实际上它确实有助于在更复杂的查询中快速识别潜在的差异和问题。
以快速可靠的方式检查更多行的列匹配或相似性,而不必离开 BigQuery 控制台工作流,这是一个强大的小生产力提升。小幅度的生产力提升积少成多…
结论
你可能会想:
- 这篇文章不应该是关于简单的行散列,而不是行复制测试、固执己见的 SQL 结构断言、无意义的函数开发或让 BigQuery 显示愚蠢的交通灯吗?
- 难道你不能用更少的代码,使用不同的 and 联合和子查询之类的东西来实现同样的事情吗?
对此我会回答:
- 是啊,我知道。然而,这种看待问题的方式引出了一些相邻的有用的技术,这些技术值得研究,因为它们可以在许多其他方面得到应用。另外,我问你一个问题:你更喜欢哪种类型的旅行……a)直接到达目的地而不分心的旅行,还是 b)到达目的地但沿途发现许多新奇有趣的地方的旅行?
- 是啊,管它呢。在生活和代码中,总是有很多方法可以实现任何事情。有些人有缺点,有些人有机会,但大多数人两者都有。实际上,您可能想知道哪些行实际上是重复的,这样您就可以标记和/或过滤和/或用于数据质量保证,这种技术为您提供了这种能力。现在,您还将拥有一个可靠的惟一连接键,它可以充当(非强制)主键。此外,复杂的嵌套子查询和怪异的自连接扭曲可能很快变得无法阅读或直觉,根据SQL 的禅:
TFSQL10.1:可读性计数
写干净的、模块化的、顺序的代码是一个好主意,目标是使它不仅功能性强、效率高,而且易于阅读和理解。不过,我跑题了:
在 BigQuery 中构建唯一行散列的简单方法:
TO_HEX(MD5(TO_JSON_STRING(input_data)))
如果你需要一个如何定义input_data
的解释,那么检查上面的TO_JSON_STRING()
部分。
如果您觉得这(以及其他相关材料)有用和/或有趣,请跟我来,并查看我的开源项目转换流程以获得更多工具和技术来扩展您的 BigQuery 超能力。
如果你还不是会员,加入 Medium 这个活跃、充满活力和激情的数据人社区,每月只需 5 美元就能获得无限的故事。也有很多其他人,但是如果你对数据感兴趣,那么这里就是你要去的地方…
如何使用 Python 构建一个 Web 应用程序来转录和总结音频
一本实用指南,总结您最喜爱的数据科学 Spotify 播客,并简化它以创建 web 应用程序
来源: flaticon
Spotify 的播客剧集的特点是非常长,这很容易让你沮丧或分散你的注意力。你有没有想过把播客里看起来很吸引人,但你在那一刻的心情总结一下?获取播客的要点并最终说服你听完它可能是个好主意。
在本教程中,我们将构建一个 web 应用程序来转录和总结《裸数据科学》中的一集,该集探讨了不同的数据科学主题,并提供了成为数据科学家的实用技巧。
该应用程序将使用 Streamlit 构建,而 AssemblyAI API 将允许我们转录和总结 Spotify 播客的剧集。首先,这个 API 使用自动语音识别将音频转换成文本,然后生成文本摘要。让我们开始新的冒险吧!
目录
第 1 部分:转录和总结音频
本教程将分为两个部分。第一部分主要展示如何应用 AssemblyAI API 来总结我们播客的内容。在第二部分中,我们将使用 Streamlit 来开发 web 应用程序。这些是以下步骤:
- 从收听笔记中提取剧集的 URL
- 发送转录请求
- 检索转录和摘要
1.从收听笔记中提取剧集的 URL
Listen Notes 是一个强大的播客搜索引擎和在线数据库,提供访问播客数据的 API,并允许基于它构建新的服务和应用。在本教程中,我们将使用 Listen Notes API 从我们的目标播客中检索该集的 url。
- 首先,您需要创建一个帐户来检索数据,并订阅免费计划来利用 Listen Notes API。有了这个计划,你每个月最多可以有 300 个请求,这足够你处理个人项目了。
- 然后,在 Listen Notes 中进入播客的页面,点击你感兴趣的剧集,选择“使用 API 获取该剧集”。
- 之后,您可以将语言代码更改为 Python,并从选项列表中单击 requests,以便以后使用库请求。
- 复制代码并将其粘贴到您的笔记本/脚本中。
我们正在向 Listen Notes Podcast API 的端点发送一个 GET 请求,这是一个从 Listen Notes API 检索数据的策略操作。最后,我们将最终输出保存为一个 JSON 对象,其中还包括以后需要的剧集的 URL。
我们还导入了一个 JSON 文件,名为 secrets.json ,它非常类似于一个字典,因为它由一组键值对组成。它需要包含分别用于 AssemblyAI 和 Listen Notes 的 API 键。您需要在您的帐户中访问它们。
{
"api_key":"<your-api-key-assemblyai>",
"api_key_listennotes":"<your-api-key-listennotes>"
}
2.发送转录请求
我们现在向 AssemblyAI 的转录端点发送一个 POST 请求,而不是发出一个 GET 请求。post 方法用于将音频 URL 上传到程序集 AI。
这一步对于获取转录和摘要是很重要的,如果我们设置 auto_chapter 等于 True,那么就包含了转录和摘要。如果我们将 auto_chapter 设置为 False,我们将只获得转录。之后,我们保存转录反应的 id。
3.检索转录和摘要
最后,我们可以通过向 Assembly AI 发送 GET 请求来获得转录和摘要。在响应状态完成之前,我们需要发出一些请求。稍后,我们将结果保存到两个不同的文件中,一个 txt 文件用于转录,一个 JSON 文件用于摘要。
最重要的步骤已经完成。我们可以查看摘要:
[
{
"summary": "Having a big bang is one of the most common causes of data science project failures. This episode explains why it's better to aim for suboptimal solutions at the start of a project and how you can avoid the big bang problem by following an ancient Japanese philosophy.",
"headline": "Having a big bang is one of the most common causes of Data science project failures.",
"gist": "Avoid the big bang problem.",
"start": 2110,
"end": 37530
},
{
"summary": "This week we are going to talk about another mental model that we found very useful in our experience leading data science projects and teams. It's common to see in business when you start approaching a data intensive problem data initial planning, and then you have some initial directions to go with the root cause. Could be that when you ask a good problem solver or people who are interested in problem solving to find a solution for something, we often want to go for the best solution that there is.",
"headline": "This week we are going to talk about another mental model that we found useful in our experience leading data science projects and teams.",
"gist": "The problem model model.",
"start": 41790,
"end": 200986
},...}]
第 2 部分:创建 Web 应用程序
现在你已经能够理解转录和总结播客的主要部分,我们可以切换到第二部分。目标是用 Streamlit 创建一个应用,这是一个免费的开源框架,允许使用 Python 用几行代码构建应用。
在第一行代码中,我们只是导入 python 库并定义函数,这些函数重现了前面显示的步骤。此外,我们还创建了一个 zip 文件,其中包含带有转录的文件和带有摘要的文件。
现在,我们可以定义应用程序的主要部分。首先,我们使用st.markdown
显示应用程序的主标题。在我们创建了一个左侧面板工具条之后,使用st.sidebar
来输入我们发布的剧集 id。插入 id 后,我们点击“提交”按钮。
在我们按下按钮后,应用程序将执行所有步骤来转录和总结该集的音频。几分钟后,结果将显示在网页上。如果您想下载输出,可以使用 download 按钮,将转录和摘要保存到 zip 文件中。
编写完所有代码后,可以将其保存到文件 summ_app.py 中,并在终端上使用以下命令行运行代码:
streamlit run summ_app.py
自动返回本地 URL 和网络 URL。你可以点击其中一个链接,瞧!现在,你有一个了不起的应用程序,转录和总结你最喜欢的播客!
应用程序的完整代码
为了更好地理解,最好显示 web 应用程序使用的所有代码。
最终想法:
我希望这篇教程对开始使用 AssemblyAI 和 Streamlit 有用。在这个案例研究中,它被应用于转录播客的音频。这里的 GitHub 代码是。还有很多其他可能的应用,比如 zoom 通话,youtube 视频。更多信息,请查看 AssemblyAI 官方网站的文档及其 youtube 频道。感谢阅读。祝您愉快!
其他相关文章:
你喜欢我的文章吗? 成为会员 每天无限获取数据科学新帖!这是一种间接的支持我的方式,不会给你带来任何额外的费用。如果您已经是会员, 订阅 每当我发布新的数据科学和 python 指南时,您都会收到电子邮件!
如何使用通过多功能数据工具包获取的数据构建 Web 应用程序
数据库,网络应用
关于如何构建 Web 应用程序的分步教程,结合了 Streamlit Python 库和多功能数据工具包。
图片由 Unsplash 上的 Taras Shypka 拍摄
在过去的几个月里,我参与了一个非常有趣的项目,叫做多功能数据工具包(VDK)。VDK 是一个非常强大的框架,用于在数据库中接收不同格式的数据,包括 CSV 文件、JSON 对象,甚至 REST API 服务提供的数据。
VDK 兼容几种类型的数据库,包括但不限于 sqlite、Trino DB、Impala、Postgres 和 Snowflake。
VDK 由 VMware 实施,是一款开源软件。更多信息可以参考官方 VDK Github 库。
在我以前的文章中,我描述了 VDK 的不同方面,包括:
在本文中,我将描述如何使用通过 VDK 存储的数据来构建一个基于 Streamlit 的 web 应用程序,Streamlit 是一个流行的 Python 库,用于快速轻松地构建网站。
您可以在页面底部找到与本文中描述的示例相关的完整代码。
要配置环境以使用 VDK,您可以参考以前的文章。
文章组织如下:
- VDK 概况
- 场景的定义
- VDK 的数据接收
- VDK 的数据处理
- 构建 Streamlit 应用程序。
1 VDK 概述
通用数据工具包(VDK)是一个框架,允许您开发,部署,运行和管理数据作业。数据作业是一种数据处理工作量。您可以定义两种类型的数据作业:
- 摄取作业,将不同来源的数据推送到数据湖。通常,通过接收作业,您接收由数据提供者提供的原始数据。
- 处理已经包含在数据湖中的作业,您可以在其中操作您的数据。这个想法是建立精选的数据集,你可以用它来做进一步的分析。
关于 VDK 的更多细节,你可以阅读我以前的一篇文章,题为多功能数据工具包概述。
2 场景的定义
此场景的目标是构建一个显示美国天然气价格和温度之间关系的应用程序。
该应用程序使用 VDK 来摄取和处理以下两个 CSV 数据集:
- 1997-2020 年天然气价格
- 【1910 年至 2020 年美国气候极端指数
天然气价格数据集包含 5,953 条记录,由美国能源信息管理局(EIA)提供。每个记录包含天然气的每日价格。对于每条记录,以下信息可用:
- 日期(每天提供)
- 价格(美元)
下表显示了数据集的摘录:
作者图片
美国极端气候指数数据集包含 112 条记录。对于每条记录,可以下载许多参数。数据分析师选择以下信息:
- 日期(每年提供一次)
- 远高于正常的最低温度百分比
- 远低于正常的最低温度百分比。
下表显示了数据集的摘录:
作者图片
要运行此示例,您需要:
- 多功能数据工具包
- Trino DB
- Trino 的多功能数据工具包插件
- 细流
有关如何为 Trino 安装多功能数据套件、Trino DB、Streamlit 和多功能数据套件插件的更多详细信息,请参考此链接。
3 VDK 的数据接收
数据摄取上传到 CSV 文件的数据库输出中,如前一节所述。对于每个数据集,通过以下步骤执行数据接收:
- 删除现有的表(如果有)
- 创建新表格
- 直接从 CSV 获取表格值。
前面的所有步骤构成了一个数据摄取作业。
要访问 CSV 文件,此示例需要有效的互联网连接才能正常工作。例如,我只考虑第一个数据集(天然气价格),但对于其他数据集,过程是相同的。
3.1 删除现有表格
我将这一步写成一个 SQL 命令,如果表存在的话,就删除它:
DROP TABLE IF EXISTS natural_gas_prices
3.2 创建新表
现在,我定义了一个新步骤,该步骤创建了一个新表,其中将包含 CSV 文件:
CREATE TABLE natural_gas_prices (
Date varchar,
Price double
)
3.3 摄取值
为了从 CSV 获取值,我定义了一个 Python 脚本,它将 CSV 文件作为熊猫数据帧读取,然后通过 VDK 提供的send_tabular_data_for_ingestion()
方法获取它:
def run(job_input: IJobInput): url = "https://datahub.io/core/natural-gas/r/daily.csv"
df = pd.read_csv(url) job_input.send_tabular_data_for_ingestion(
df.itertuples(index=False),
destination_table="natural_gas_prices",
column_names=df.columns.tolist(),
)
4 VDK 的数据处理
数据处理包括两个步骤:
- 用天然气价格的平均值构建年度视图
natural_gas_prices
- 合并两个表,前一个和
climate_extremes_index
。
4.1 建筑年景
要构建年度视图,只需操作natural_gas_prices
表,如下所示:
CREATE TABLE average_gas_price_by_year AS(SELECT extract(YEAR from CAST(Date AS date)) AS Year,
avg(Price) AS Price
FROM natural_gas_prices.
GROUP BY extract(YEAR from CAST(Date AS date))
)
因此,我创建了一个新表,名为average_gas_price_by_year
。
下表显示了生成的表的示例:
作者图片
4.2 合并两个表
最后一步,我合并了两个表climate_extremes_index
(从第二个 CSV 文件中提取的表)和average_gas_price_by_year
。值在区间[0,1]中被归一化,从而使它们之间的比较成为可能。
CREATE TABLE merged_tables AS(SELECT Year,(Price / (SELECT max(Price) FROM average_gas_price_by_year)) AS NormPrice,(MuchAboveNormal / (SELECT max(MuchAboveNormal) FROM climate_extremes_index WHERE CAST(climate_extremes_index.Date AS integer) IN (SELECT Year from average_gas_price_by_year))) AS NormTemperatureMuchAboveNormal,(MuchBelowNormal / (SELECT max(MuchBelowNormal) FROM climate_extremes_index WHERE CAST(climate_extremes_index.Date AS integer) IN (SELECT Year from average_gas_price_by_year))) AS NormTemperatureMuchBelowNormalFROM average_gas_price_by_year INNER JOIN climate_extremes_indexON average_gas_price_by_year.Year = CAST(climate_extremes_index.Date AS integer))
在前面的查询中,对于 select 中的每个字段,除了Year
,我按照最大值对字段进行规范化。为了获得字段的最大值,我构建了另一个内部查询。
5 构建 Streamlit 应用
现在我已经准备好构建最终的应用程序了。首先,我导入所有需要的库:
import altair as alt
import numpy as np
import pandas as pd
import streamlit as st
import trino
我将使用altair
构建一些图表,并使用trino
连接到 Trino 服务器。
现在,我连接到服务器:
conn = trino.dbapi.connect(
host="localhost",
port=8080,
user="root",
catalog="mysql",
http_scheme="HTTP",
verify=True,
schema="energy",)
我写了一篇减价文,题目是:
st.markdown("# Does the Natural Gas Price in the US depend on the temparature?")
现在,我从数据库中读取数据:
df = pd.read_sql_query(f"SELECT Year, NormPrice, NormTemperatureMuchAboveNormal, NormTemperatureMuchBelowNormal FROM merged_tables",conn,)
我制作了这张图表:
palette = ["#ff9494", "#ff5252", "#8B0000"]indicators = ["NormPrice",
"NormTemperatureMuchAboveNormal",
"NormTemperatureMuchBelowNormal",
]price_bar = (alt.Chart(df)
.mark_bar(size=30)
.encode(x="Year:O", y="NormPrice:Q", color=alt.value("#8B0000"))
)temp_list = ["MuchAboveNormal", "MuchBelowNormal"]
temp_type = st.selectbox("Select Temperature", temp_list, key="temp_type")temp_line = (
alt.Chart(df)
.mark_line()
.encode(x="Year:O", y=f"NormTemperature{temp_type}:Q", color=alt.value("#ff9494")))c = (price_bar + temp_line).properties(height=350, width=800)
st.altair_chart(c)
最后,我从终端运行应用程序:
streamlit run dashboard.py
下图显示了最终输出:
作者图片
摘要
在本文中,我描述了如何将 VDK 与 Streamlit 集成来构建一个 Web 应用程序。首先,我在 VDK 下载、消化和处理数据,然后我在 Streamlit 中构建了 Web 应用程序。
你可以在 VDK 官方 Github 库中的 examples 一节下找到这个例子的完整代码。
对于多功能数据工具包的问题或疑问,您可以直接加入他们的公共 slack workspace 或他们的邮件列表或在 Twitter 上关注他们。
相关文章
如何打造一个 AI 服装设计师
原文:https://towardsdatascience.com/how-to-build-an-ai-fashion-designer-575b5e67915e
基于 StyleGAN 和 GANSpace 的服装语义编辑
ClothingGAN 演示[图片由作者提供]
概观
这是我的老项目clothing an的一篇报道。该项目使用 StyleGAN 用 AI 生成服装设计,并使用袖子、尺码、连衣裙、夹克等属性对其进行语义编辑。您也可以如上图所示进行风格转换,首先生成 2 个不同的服装设计(输出 1),使用不同的种子编号。然后,它将生成第三个设计(输出 2),该设计混合了前两个设计。然后,您可以调整希望它从两个原始设计中继承多少风格或结构。
概述
- 灵感
- 我是如何建造的
- 训练风格 GAN 模型
- 用 GANSpace 进行语义编辑
- 用 Gradio 构建 UI
- 部署到巨大的空间
灵感
GAN 或生成对抗网络是一种生成模型,它能够通过学习大型图像数据集的概率分布来生成图像。我总是觉得 GANs 很吸引人,因为它使我能够创作出高质量的艺术或设计,即使没有绘画方面的技术或艺术技巧。最近在 GAN 上看到很多人脸编辑演示,但在其他数据集上很少看到语义操纵。因此,我创建了 ClothingGAN 应用程序,你可以与人工智能合作设计衣服,而不需要很高的技术专业知识。
我是如何建造的
第一步,要有一个可以生成服装的生成模型。我没有设法找到一个公共模型,可以产生一个体面的质量图像,因此我决定用样式训练我自己的甘服装模型。然后我使用 GANSpace,一种基于潜在空间的语义编辑方法,来提供编辑功能。它在 GAN 潜在空间中找到重要的方向,这些方向可能代表某些视觉属性,然后我手动标记这些属性。最后,我使用 Gradio 库构建了演示界面,并将其部署到 HuggingFace 空间。
训练风格 GAN 模型
我使用了 StyleGAN2-ADA[2]模型,因为在项目进行的时候,最新的 StyleGAN 模型是 StyleGAN2-ADA 模型。但是,您可能希望使用当前最新版本 StyleGAN3。虽然我不确定 StyleGAN3 与我的方法或我正在使用的其他库有多兼容。
为了训练模型,我使用了由dong eun Yoo在PixelDTGAN【1】论文中创建的服装数据集。该数据集具有 84,748 幅图像,包括 9,732 幅具有干净背景的上部服装图像,这些图像与剩余的 75,016 幅时装模特图像相关联。我只使用了背景干净的服装图片。因此,用于训练 StyleGAN 模型的总图像大约是分辨率为 512×512 的 9k 图像。这是作者网站上分享的数据集的链接。PixelDTGAN 论文受麻省理工学院许可。
LookBook 数据集一览[图片由作者提供,数据集由 PixelDTGAN[1] 提供]
我不会讨论如何训练模型的具体步骤,因为我之前已经就这个主题写了一篇文章。只需对所选数据集执行相同的步骤。
这是训练后的结果。
由训练模型生成的设计的样本和插值[图片由作者提供]
用 GANSpace 进行语义编辑
语义图像编辑是在给定的源图像中修改语义属性(例如样式或结构)的任务。例如,修改一个人的头发颜色,同时保留这个人的身份。图像编辑的应用范围很广,从照片增强、用于艺术和设计目的的风格处理到数据扩充。语义图像编辑通常有两个目标:允许同时对多个属性进行连续操作,并在保持图像真实性的同时尽可能多地保留源图像的身份。
现有的使用 GANs 的语义图像编辑方法可以主要分为图像空间编辑或潜在空间编辑。图像空间编辑学习直接将源图像转换成目标域中的另一图像的网络。这些方法通常只允许二进制属性改变,而不允许连续改变。这些方法的例子有 pix2pix、StarGAN 和 DRIT++等。
相反,潜在空间编辑通过操纵跨越 GAN 模型的潜在空间的输入向量来间接操纵图像。这些方法主要集中于在潜在空间中寻找代表生成图像的语义属性的路径。在这些路径中导航输入向量允许连续编辑属性。
无监督、自我监督和监督的潜在空间编辑方法都已被提出。gan space【3】在潜在或特征空间中使用主成分分析(PCA)以无监督的方式寻找重要方向。使用闭型因子分解也可以类似地找到重要方向(来自 SeFa 论文)。自监督方法也能够在没有标签的情况下找到这些方向,因为它们生成自己的标签,但是通常受限于几何属性,例如旋转或缩放。另一方面,像 InterfaceGAN 这样的监督方法需要标签信息或方法的属性分类器。
GANSpace[3] 讨论了预训练的 GAN 模型在对生成的图像进行造型时的使用。GAN 模型学习将噪声分布 z 映射到图像分布的函数。因此,给定不同的噪声输入 z,产生的输出将会不同。然而,深度学习模型通常是一个黑箱,它并不明确知道噪声输入和生成的输出之间的关系,因此无法明确控制输出。然而,GAN 模型可以被调整为在给定类标签的情况下生成特定的类输出,如条件 GAN 中所研究的。然而,在训练期间,需要数据集的标签信息来调节 GAN 模型,这对于某些情况可能是不可行的。
另一方面,GANSpace 的论文[3]提出,可以在 z 潜在空间中找到某些重要的方向,z 潜在空间表示生成的输出中的已知语义概念,例如输出的风格。为了找到这个方向,对于几个样本观察中间层中的激活,并且从中间网络激活空间中的值计算 PCA 方向 v。然后,方向 v 将被转移以在 z 潜在空间中找到对应方向 u。整个过程如下图所示,取自 GANSpace 的论文。
在 GAN 潜在空间中识别 PCA 方向的 2D 图解[来源: GANSpace 论文[3]
可以在不同层中计算重要方向 u,并且每层中的方向可以表示不同的语义概念。在早期层中找到的方向通常表示高级特征,如布料结构,而在最后几层中找到的方向通常表示低级特征,如光照或颜色。通过在这些已知的方向上操纵噪声输入 z,我们可以将生成的输出操纵到期望的特征。下图显示了在不同 GAN 模型中应用 GANSpace 方法时的操作结果。
GANSpace 的结果是不同的模型。[来源:甘斯佩斯论文[3]
在训练好的模型中寻找方向
这里将显示的代码是在 Google Colab 上测试的,你可以跟随我的笔记本或者在你自己的环境中,但是如果你跟随 Colab 环境之外的环境,确保你的环境有预先安装在 Colab 中的依赖项。
如果你想跟随,这是教程笔记本
首先,我们需要安装 GANSpace 所需的依赖项。
!pip install ninja gradio fbpca boto3 requests==2.23.0 urllib3==1.25.11`
运行完代码后重启运行时,然后克隆 GANSpace repo。
!git clone https://github.com/mfrashad/ClothingGAN.git%cd ClothingGAN/
运行以下代码进行进一步设置。确保您位于 GANSpace 文件夹中。
!git submodule update --init --recursive!python -c "import nltk; nltk.download('wordnet')"
接下来,我们必须修改 GANSpace 代码来添加我们的定制模型。对于 StyleGAN2,我们需要模型文件的 PyTorch 版本。因为我们的 StyleGAN 模型文件在 Tensorflow 中。pkl 格式,我们需要用 rosinality 做的转换器把它改成 pytorch 格式。pt 文件。只要按照这个笔记本里的步骤就可以了。(该项目是在正式的 StyleGAN2 PyTorch 版本实现之前完成的,如果您的模型文件已经存在,您可以跳过这一部分。pt 或 Pytorch 格式)。
接下来,回到 GANspace 文件夹,修改models/wrappers.py
来添加我们的模型文件。首先,转到 StyleGAN2 类,在config
变量中添加我们的模型名称和输出分辨率。
我在 models/wrappers . py[Image by Author]的第 117 行的配置变量中添加了分辨率为 512x512 的“lookbook”模型
接下来,再向下滚动一点,在checkpoints
变量中添加到模型的链接。要生成到我们模型的链接,只需将模型文件上传到 Google drive,并使用这个站点生成到它的直接链接。
我在 models/wrappers.py 文件的第 149 行添加了一个新的生成器模型“lookbook”
将模型添加到文件中之后。运行visualize.py
c 脚本进行 PCA,并在向计算出的主成分方向移动输入时可视化视觉变化。
用于 PCA 和可视化变化的命令[图片由作者提供]
--use_w
选项意味着我们将操纵中间潜在代码w
,而不是 StyleGAN 中的原始潜在代码z
。num_components
是指定你想保留多少个方向或主成分。最大组件将是 512 或输入z
或w
尺寸。--video
选项是在主成分方向上移动时生成视觉变化的视频,而不仅仅是生成图像。该脚本可能需要大约 30 分钟才能完成。
一旦完成,它将在 out 文件夹中生成可视化的更改。对我来说,它在out/StyleGAN2-lookbook
文件夹下。
生成的可视化输出[图片由作者提供]
我们将看一下style/ipca/summ/components_W.jpg
,因为它可视化了前 14 个主要组件。
前 14 个主成分的可视化[图片由作者提供]
从上图中,我们可以开始选择要放入演示中的主要组件,并给它们贴上标签。例如,在我看来,C0 可以标记为袖长,C1 为夹克,C2 和 C3 为外套,C4 和 C5 为服装的亮度,C6 为较短的服装。
您还可以在附加文件sampX_real_W.jpg
中看到不同样本的可视化,以确保由主成分引起的变化在不同样本之间保持一致。还有 9 个额外的样本是由visualize.py
脚本生成的。
这是另一个例子的可视化。
不同样本的主要成分的可视化[图片由作者提供]
你可以看到,即使是不同的样品(袖长为 C0,夹克为 C1 等),变化也大致一致。
此外,您还可以在comp
或inst
文件夹中看到每个组件的可视化视频。主成分本身以.npz
的格式保存在cache/components/
文件夹中
计算出的主成分文件的位置[图片由作者提供]
一旦我们有了组件,我们就可以开始构建演示 UI 了。
用 Gradio 构建 UI
Gradio 是一个 python 库,它使得用几行代码构建 ML 项目的 UI/demo 变得极其容易。下面是 Gradio 有多简单的一个例子:
示例代码和使用 Gradio 生成的应用程序[图片由作者提供]
当你想把你的 ML 应用程序演示成一个单一的函数时,Gradio 是合适的。
首先,我们需要将发电机模型和主要组件加载到内存中。
然后,我们将定义一个效用函数来操作指定方向的w
输入,并使用生成器生成图像。
最后,我们可以定义主函数generate_image
并使用 Gradio 库为该函数构建 UI。
这就是结果!
带有 Gradio 的演示用户界面[图片由作者提供]
Gradio 还将提供一个链接,您可以在那里分享您的朋友或任何人都可以尝试演示。然而,演示的主机并不是永久的,Colab 服务器被限制在 12 或 24 小时后才会自行终止。对于永久托管,您可以简单地在云中或您自己的服务器上运行代码。但幸运的是,拥抱脸创造了 Spaces ,一个你可以简单上传你的 ML 应用并永久免费托管的平台(如果你想要 GPU 需要付费)。此外,它与 Gradio 和 Streamlit 完美集成,开箱即用。
部署到巨大的空间
首先,前往空间并登录/注册您的帐户。然后单击“创建新空间”。
拥抱脸空间主页[图片由作者提供]
然后,选择您想要的名称和许可证,并选择 Gradio 作为 space SDK。
创造新空间[作者图片]
接下来,克隆拥抱脸回购。
[图片由作者提供]
就我个人而言,在推送回购时,我遇到了一个身份验证问题,我不得不使用令牌作为身份验证方法,方法是将远程 URL 设置为:
https://HF_TOKEN@huggingface.co/spaces/mfrashad/Test
或者你也可以在 URL 中使用你的拥抱脸账户的用户名和密码进行认证。
https://HF_USERNAME:PASSWORD@huggingface.co/spaces/mfrashad/Test
一旦克隆完成,我们就可以开始创建演示所需的文件。在 Spaces repo 中需要 3 个重要的文件:requirements.txt
指定要与pip install
一起安装的所有 python 依赖项,packages.txt
指定要与apt install
一起安装的依赖项,以及包含 Gradio 演示代码的主 python 文件app.py
。
此外,您需要使用 git-lfs 将任何二进制文件上传到 repo,例如图像。
所以我所做的只是将我们在 Colab 中的所有代码复制到 Spaces repo 中。删除图像、二进制文件和演示不需要的文件。把我们笔记本里所有的 python 代码放到一个 python 文件app.py
里。然后创建requirements.txt
和packages.txt
。一旦完成,简单地git push
和瞧!该演示将在拥抱脸空间提供给任何人尝试(假设你没有任何错误)。
关于代码的完整内容,你可以查看clothingan Space repo中的文件。
您的共享空间演示将显示在您的个人资料和共享空间主页上[图片由作者提供]
恭喜你!你设法一直读到这一点,并希望设法做好一切。对于更多的挑战,您可以尝试训练自己的 StyleGAN 模型,并应用语义编辑。例如,我也将相同的方法应用于角色和时装模型的生成。
字符生成和语义编辑[图片由作者提供]
如果你喜欢阅读这样的教程,并希望支持我成为一名作家,可以考虑注册成为一名媒体会员。每月 5 美元,你可以无限制地阅读媒体上的故事。如果你注册使用我的链接,我会赚一小笔佣金。
https://medium.com/@mfrashad/membership
另外,看看我的其他故事。
参考
[1] Yoo,d .,Kim,n .,Park,s .,Paek,A. S .,& Kweon,I. S. (2016 年 10 月)。像素级域转移。在欧洲计算机视觉会议(第 517–532 页)。斯普林格,查姆。
[2]t . Karras,m . Aittala,j . hells ten,Laine,s .,Lehtinen,j .,& Aila,T. (2020 年)。用有限数据训练生成性对抗网络
[3]哈尔科宁、赫茨曼、莱蒂宁和巴黎(2020 年)。Ganspace:发现可解释的 gan 控制。神经信息处理系统的进展, 33 ,9841–9850。
如何从零开始建立一个情感语调分析器
原文:https://towardsdatascience.com/how-to-build-an-emotional-tone-analyzer-from-scratch-ea286b8ee4de
如何构建一个高性能的情感语调分析器来与 IBM Watson 竞争,而无需支付每 API 交易费用
介绍
在最近的一篇文章中,我展示了如何使用 IBM Watson 的“声调分析器”,它可以将文本的情感分析直接嵌入到用 Python(或其他语言)编写的机器学习应用程序中。
本文继续开发和解释 Python 代码,探索与一个虚构的在线女装零售商的客户反馈相关的开放许可数据集,使用 tone analyzer 预测客户写评论时的情绪。
在结论中,我注意到 IBM Watson 的免费定价计划将客户限制在每月 2,500 个 API 调用,如果我选择对所有 23,000 个数据点执行代码,那么它们的计量成本将是 202 美元(~ 149 美元),并且代码运行将花费大约 4 个小时。
当我思考 IBM Watson Tone Analyzer 的利与弊时,我开始思考如何自己编写类似的东西,对客户在编写自由文本格式反馈时的情绪做出有用的预测,但这样会执行得更快,并避免大型数据集的交易成本。
本文的其余部分解释了我如何从头开始构建一个情感语调分析器,以及它与 IBM Watson 服务的比较。
构建情感语调分析器
1.获取一些数据
首先要做的是获得一些数据来再次构建和测试,我已经选择重用开放许可女装在线零售数据集(https://www . ka ggle . com/nica potato/women-ecommerce-clothing-reviews)。
这些数据是在“CC0:公共领域”许可下授权的,这意味着“你可以复制、修改、分发和执行这些作品,即使是出于商业目的,都无需征得许可”(详见 https://creativecommons.org/publicdomain/zero/1.0/)
作者图片
我使用的数据集是第一篇文章的输出数据集,该文章对 2000 行进行了采样,然后使用 IBM Watson API 调用的每月免费配额来返回客户体验的主要情绪(Emotion
)和一个指示该情绪有多强烈的分数(Emotion Score
)。
我还将数据集的副本放入df_reviews_raw
中,以便稍后进行比较。
2.分为培训和验证/坚持
这里,我选择以 80/20 的比例对两个数据帧进行采样,而不是采用更常见的方法返回 4 个 numpy 数组(X_train, y_train, X_test, y_test = train_test_split(df_reviews, test_size=0.2, random_state=42)
)。
原因是,稍后我需要将评论“矢量化”成一组新的特征,如果将训练和测试数据保留为 DataFrame 而不是 numpy 数组,这将更容易做到。
最后,分割的数据帧被深度复制,以避免在我们开始向分割的数据帧添加新特征时会发生的SetWithCopyWarning
。
训练数据将用于 k-fold 交叉验证,有效地充当训练和测试数据,而验证/排除数据将在建模结束时用于判断性能和避免过度拟合。
3.重新平衡培训数据
Joy 0.901569
Sadness 0.082026
Anger 0.008559
Fear 0.007846
Name: Emotion, dtype: float64
数据严重不平衡,超过 90%的数据被归类为“快乐”情绪。在开发过程中,我尝试了让数据不平衡或重新平衡,重新平衡产生了一个模型,该模型对拒不合作的数据集表现得更好,因此数据需要重新平衡…
这段代码对数据进行了重新采样,提供了与原始数据帧相似的行数,但对 4 种情绪进行了平均采样
Anger 350
Fear 350
Joy 350
Sadness 350
Name: Emotion, dtype: int64
4.特征工程
下一步是使用TfidfVectorizer
对评论文本进行矢量化。这是通过分析文本中与目标变量相关的单字(单个单词)和双字(两个连续单词的组合)来实现的。
然后可以手动检查这些 ngrams,看它们是否有意义,然后将其附加到数据上,以提供可用于预测性机器学习分类算法的数字特征。
TfidfVectorizer
已经被安装和改造。这意味着作为一个模型,TfidfVectorizer
已经被构建为使用训练数据来驱动一组预测,然后生成(转换)的数据已经从模型返回。
看一看已经产生的东西就更容易理解了
作者图片
我们的训练数据中的 1400 行中的每一行都有一组 300 个标记化的单词(标记化只是用唯一的数字或标记替换英语单词的过程)。
这 300 个单词中的每一个都有一个值,表明它在评论文本中使用了多少。
5.评估特征工程
从这里开始,我们只需要一小段代码来看看哪些英语单词和单词与 4 种情绪最相关,这将提供一个常识性的检查,以确定该方法是否有效…
Joy:
Most correlated unigrams: fits, great, comfortable, got, true, nice, pounds, love, perfect, bad, length, lay, petite, much, disappointed, across, pulled, though, bust, skirt
Most correlated bigrams: true size, runs slightly, need wear, dry clean, fabric bad
Sadness:
Most correlated unigrams: wanted, sad, disappointed, get, saw, like, pounds, great, wore, love, lay, size, even, much, material, received, first, would, across, still
Most correlated bigrams: need wear, runs slightly, going back, fabric bad, pounds usually
Fear:
Most correlated unigrams: across, pulled, shoulders, fear, squareapple, underlayer, types, si, narrow, done, space, slightly, romper, different, way, vest, chest, part, glad, guess
Most correlated bigrams: runs slightly, types fabric, small athletic, little short, space arms
Anger:
Most correlated unigrams: problem, strike, flat, pounds, idea, dressy, purchased, deep, zipper, mentioned, small, shows, appears, reviewers, lay, sheer, reviews, pants, cami, pink
Most correlated bigrams: need wear, pounds usually, reviewers mentioned, sale price, runs slightly
这看起来很合理。与快乐、悲伤、恐惧和愤怒相关联的单词看起来确实可信。当“轻微跑动”出现在快乐、悲伤和恐惧中时,二元模型看起来不太合理。
总的来说,我们拥有的似乎是一组合理的数据,可以进入预测模型构建阶段。
6.建立模型
6.1 选择 X 和 y(特征和目标)数据
在开发期间,我确实尝试构建了一个仅使用矢量化单词的模型,但是我发现,如果我将Review Rating
和Review Polarity
作为特征包括在内,那么针对验证/保留集的性能就会提高,这就是将这些列应用于带有df_reviews_train.iloc[:,[3,5]
的矢量化单词的原因。
6.2 超参数调谐
RandomForestClassifier(bootstrap=False, max_depth=40, max_features='sqrt', min_samples_split=5, n_estimators=200, random_state=42)
TUNED_HYPER_PARAMS_500
字典包含我在开发过程中通过在 5 个数据折叠上执行 500 次迭代的RandomizedSearchCV
确定的超参数,因为 2500 次拟合需要相当长的时间,所以我从文章中省略了这一点,只使用了最佳参数。要了解全部细节,请查看 GitHub 项目。
7.评估模型
7.1 根据培训和测试数据进行评估
初始评估是通过将训练数据分成 5 个部分,并使用每个部分作为训练/测试集来评估模型的准确性…
作者图片
使用混淆矩阵来可视化性能也是有用的。如果你对如何为 k 倍交叉验证建立混淆矩阵的完整解释感兴趣,我已经在另一篇文章中解释了细节
作者图片
k 倍交叉验证的平均准确度为 0.9835714285714285,非常高。混淆矩阵显示,实际上是“快乐”的 17 个数据点被预测为“悲伤”,但除此之外,预测看起来确实非常好。
“恐惧”和“愤怒”是 100%准确的,这看起来很可疑。这可能是因为训练数据中非常少的数量或数据点被分类为恐惧和愤怒,并且已经被向上采样,所以这些记录中的变化非常小,这使得算法很容易以高精度进行预测。
这表明有必要根据包含 4 种情绪(包括罕见情绪)原始比例的验证/拒绝数据来评估绩效。
7.2 根据验证/拒绝数据进行评估
请注意,该模型现在适用于完整的 X_train 和 y_train 数据集。这是因为 k-fold 交叉验证使模型适合 5 个数据集,每个数据集占训练数据的 80%。
针对 100%的训练数据而不是 80%的训练数据完成拟合极有可能产生更准确的模型。
作者图片
相对于验证/保留集的准确度是 90.32%,这并不坏,但不幸的是,由于数据集如此不平衡,仅仅猜测每个记录的“Joy”将是具有 92.3%准确度的粗糙模型。
尽管原始模型的 f1 分数会更低,但无论如何,本文的重点是演示如何从头开始构建情感语调分析器。这种方法是合理的,只是如果选择的源数据不那么不平衡,性能会好得多。
8.将预测添加到数据集
记住 IBM Watson 的输出,它产生了两个特性
- 主要情绪
- 主要情感的得分
下面的代码通过将这些功能添加到验证/保留数据中,然后执行手动、直观的检查来查看它们是否合理,从而模拟该功能。
下面的代码添加了这些功能。应当注意的是,model.predict_proba(X_val)
返回 shape (351,4)的 numpy 数组,即验证数据中的每条记录 1 行,4 列-4 种情绪中的每种情绪 1 列,其值等于每种情绪的概率。
由于期望的结果是主要情绪的分数,因此ALPHABETICAL_EMOTION_MAP
为pd.Series(predicted_classes).map(ALPHABETICAL_EMOTION_MAP).to_numpy()
建立映射,以提取每行上预测情绪的分数。
作者图片
从快速,视觉检查,它看起来都很合理。第一个记录被 IBM Watson 预测为 0.796461 的“Joy”,被 scratch-build tone analyzer 预测为 0.777917 的“Joy”。所有前 10 个记录看起来都很合理,包括 IBM Watson 预测为“愤怒”和自制分析器预测为“悲伤”的第 8 行(预测是针对负面情绪之一)。
9.对整个数据集进行预测
在最初的文章中,我使用 IBM Watson 对 2,000 个采样行进行预测,但是源数据包含 23,000 行。我不愿意花 202 美元(约 149 英镑)买全套,所以在做了这么多艰苦的工作后,我决定不在我的分析中加入情感因素。
现在我有了一个临时构建的情绪语气分析器,最后一步是用它来预测源数据中所有 23,000 行的客户情绪…
Wall time: 21.2 s
我们做到了!scratch build emotional tone analyser 的运行时间为 21.2 秒,而 IBM Watson API 调用运行 23,000 个数据点需要 4 个多小时,成本为零,而 IBM Watson 的每 API 调用成本为 202 美元(约 149 英镑)。
剩下的就是比较结果,看看他们如何叠加…
Joy 0.7940
NaN 0.1235
Sadness 0.0685
Anger 0.0075
Fear 0.0065
Name: Emotion, dtype: float64
Joy 0.863239
Sadness 0.135490
Anger 0.000712
Fear 0.000559
Name: Emotion, dtype: float64
结论
与 IBM Watson 对 2000 行样本的预测为 79.4%相比,我们的临时构建的情感语气分析器对 23,000 行完整数据集的预测为 86.3%。
13.5%的评论被 scratch 算法预测为“悲伤”,而 IBM Watson 的预测为 6.9%。IBM Watson 在 12.4%的情况下未能做出预测,但临时构建的算法总能做出预测。“愤怒”和“恐惧”看起来相差 10 个数量级,但在两个数据集中的相对百分比非常低。
由于我们不知道 IBM Watson 是如何构建的,也不知道它自己的预测有多准确,这使得评估我们自己的算法的真正准确性非常困难,而且情绪无论如何都可能是主观的。在一次试验中,一个评论者可能会说他们有大约 53%的人感到悲伤,但实际上他们可能已经接近其他的情绪,甚至可能已经感觉到了各种情绪的混合。
作为评估的进一步阶段(本文之后),我采用了 scratch built 算法的输出,并使用它来识别与 Power BI 仪表板中的评论文本相关联的积极(快乐)和消极(悲伤、愤怒或恐惧)情绪。
这个过程和我所获得的知识将会是未来一篇文章的主题,但是我可以说的是,预测的情绪为观想增加了真正的洞察力。
通过“悲伤”、“愤怒”和“恐惧”过滤的评论将仪表板用户直接带到负面评论,这些评论是最有用的,因为它们可以用于改进评论主题的产品和服务。
感谢您的阅读!
如果你喜欢读这篇文章,为什么不看看我在 https://grahamharrison-86487.medium.com/的其他文章呢?此外,我很乐意听到您对这篇文章、我的任何其他文章或任何与数据科学和数据分析相关的内容的看法。
如果你想联系我讨论这些话题,请在 LinkedIn 上找我—【https://www.linkedin.com/in/grahamharrison1 或者发电子邮件到ghar rison @ Lincoln college . AC . uk。
如果你想通过订阅来支持作者和全世界 1000 个为文章写作做出贡献的人,请使用下面的链接(注意:如果你使用这个链接免费注册,作者将收到一定比例的费用)。
https://grahamharrison-86487.medium.com/membership
如何在 Pytorch 中建立图像字幕模型
原文:https://towardsdatascience.com/how-to-build-an-image-captioning-model-in-pytorch-29b9d8fe2f8c
如何在 Pytorch 中构建图像标题模型的详细分步说明
亚当·达顿在 Unsplash 上的照片
在本文中,我将解释如何使用 Pytorch 深度学习库构建图像字幕模型架构。除了解释模型架构背后的直觉,我还将提供模型的 Pytorch 代码。
请注意,本文写于 2022 年 6 月,因此 Pytorch 的早期/未来版本可能略有不同,本文中的代码也不一定有效。
什么是图像字幕?
顾名思义,图像字幕是将图像输入到人工智能模型,并接收描述/总结图像内容的文本字幕作为其输出的任务。例如,如果我将以下图片输入到图像字幕模型中:
该模型将返回类似“狗在水中跑”的文本标题。图像字幕模型由两个主要组件组成:CNN(卷积神经网络)编码器和语言模型/RNN(某种可以产生文本的 NLP 模型)解码器。CNN 编码器存储关于输入图像的重要信息,解码器将使用这些信息生成文本字幕。
为了训练图像字幕模型,最常用的数据集是 Flickr8k 数据集和 MSCOCO 数据集。你可以在这里找到 Flickr 数据集的下载链接,在这里找到 MSCOCO 数据集的链接。Flickr8k 数据集由 8000 幅图像组成,每幅图像都有 5 个不同的标题来描述图像,而 MSCOCO 数据集由 328000 幅图像组成。从入门的角度来看,推荐使用 Flickr 数据集,因为它不像 MSCOCO 那么大,更容易处理。但是如果您试图构建一个可以在生产中部署/使用的模型,那么 MSCOCO 可能更好。
编码器-解码器模型架构
正如我之前提到的,编码器-解码器架构由两个组件组成:一个卷积神经网络,用于对图像进行编码(即将其转换为丰富的嵌入表示),一个递归神经网络(或 LSTM),将该图像作为输入,并接受训练,使用一种称为教师强制的机制对字幕进行顺序解码。下面是这个模型的一个很好的示意图:
作者图片
CNN:通常,CNN 往往是这种模型架构中计算量最少/最复杂的部分。为什么?因为大多数图像字幕模型倾向于使用迁移学习来简单地加载已经存在的强大 CNN 架构的预训练权重。例如,在本文中,我将使用将加载到 Pytorch 的 torchvision 库中的 Inception V3 CNN 网络。然而,除了《盗梦空间》,你还可以使用许多其他的 CNN,如雷斯网、VGG 或 LeNet。我为 CNN 使用迁移学习而不是从头开始训练它的主要原因是因为这个任务是如此的普遍和广泛。它不需要 CNN 学习非常具体的东西(CNN 的唯一目的是为图像创建丰富的嵌入)。模型必须学习的对图像字幕有益的任何特征将在整个模型的训练过程中学习,并且其权重将被微调。
以下是 CNN 编码器的 Pytorch 型号代码:
import torch
import torch.nn as nn
import torchvision.models as modelsclass CNNEncoder(nn.Module):
def __init__(self, embed_size):
super(CNNEncoder, self).__init__()
self.inception = models.inception_v3(pretrained=True,
aux_logits=False)
self.inception.fc = nn.Linear(self.inception.fc.in_features,
embed_size)
self.relu = nn.ReLU()
self.dropout = nn.Dropout(0.5)
def forward(self, input):
features = self.inception(input)
return self.dropout(self.relu(features))
如你所见,这是一个相对简单的 CNN 架构。唯一的区别是,我们采用初始网络的最后一个完全连接的层,并手动将其更改为映射/连接到我们希望我们的特征嵌入的嵌入大小(以及 RNN 解码器将作为输入接受的大小)。
RNN 解码器:不像 CNN 的,我们通常不使用 RNN/LSTM 的迁移学习。如果您熟悉 LSTM 架构,您会知道训练是按顺序进行的,每个连续的单元在下一个单元之前被训练。LSTM 的输入通常只是前一个单元的隐藏状态和前一个 LSTM 单元的输出。然而,对于该模型,我们将连接由 CNN 产生的特征嵌入和 LSTM 的先前输出,并将该连接的张量传递到 LSTM 中。你可以从整个编码器-解码器架构的图像中看到这一点:
作者图片
这是 LSTM 的 Pytorch 代码:
class DecoderRNN(nn.Module):
def __init__(self, embed_size, hidden_size, vocab_size):
super(DecoderRNN, self).__init__()
self.embed = nn.Embedding(vocab_size, embed_size)
self.lstm = nn.LSTM(embed_size, hidden_size)
self.linear = nn.Linear(hidden_size, vocab_size)
self.dropout = nn.Dropout(0.5)
def forward(self, features, captions):
embeddings = self.dropout(self.embed(captions))
embeddings = torch.cat((features.unsqueeze(0), embeddings),
dim=0)
hiddens, _ = self.lstm(embeddings)
outputs = self.linear(hiddens)
return outputs
这个模型中的一些超参数必须由你来选择(特别是 hidden_size 和 embed_size 参数;我只是两个都用了 256)。vocab 大小是一个参数,您必须根据所使用的数据集进行计算。在上面的模型代码中,像许多/大多数 LSTM 架构一样,为了实际获得每个单元格预测的单词,我使用了一个线性层,该层采用隐藏层并将其映射到 vocab。更重要的一点是,在这个模型中,我从头开始生成单词 embeddings。正如你在 LSTM 代码中看到的,我使用了一个神经网络。嵌入层,它接受 vocab 中每个单词的一键编码,并将它们转换为 embed_size 的嵌入。现在,我们通常不会从零开始生成单词嵌入(例如,许多人只是使用转换器权重),因为这延长了训练过程,但是因为我们使用 LSTM 作为解码器,所以我们不能真正加载预训练的权重并使用它们。
class Encoder_Decoder(nn.Module):
def __init__(self, embed_size, hidden_size, vocab_size):
super(Encoder_Decoder, self).__init__()
self.cnn = CNNEncoder(embed_size)
self.decoderRNN = DecoderRNN(embed_size, hidden_size,
vocab_size)
def forward(self, images, captions):
features = self.cnn(images)
outputs = self.decoderRNN(features, captions)
return outputs
我们通过将 CNN 的输出作为解码器 LSTM 的输入来连接两个模型,并返回 LSTM 的最终输出。这个最终的编码器-解码器模型是我们将在我们的数据上训练的实际模型(不是另外两个)。
对编码器-解码器模型的修改
虽然上面描述的模型架构已经是构建图像字幕模型的好方法,但是还有几种方法可以修改模型,使其更加强大。
注意机制:在高层次上,当解码器生成字幕的每个单词时,注意机制允许模型注意(或本质上关注)图像的相关部分。例如,以前面一只在水上奔跑的狗为例,当解码器为单词“狗”加字幕时,注意力机制将允许模型专注于包含狗的图像的空间区域。
我们可以使用两种类型的注意力机制:
软注意:软注意涉及通过考虑/注意图像的多个部分来构造单词——每个部分的程度不同。基本上,只要把它想象成使用——有时是许多——图像的不同部分,每个部分都有不同的强度。图像的某些部分将比图像的其他部分被更强烈地考虑。
硬注意:硬注意涉及到考虑图像的多个部分,但是与软注意相反,图像的每个被考虑的部分具有相同的强度。换句话说,在生成特定单词时,被选择的图像的每个部分(即,模型“关注的”)被完全考虑,而未被选择的图像部分被完全忽略。
在我们将 CNN 产生的特征嵌入馈送到解码器之前,为了添加注意机制,我们添加了将应用于特征嵌入的单独的线性/注意层。下面是一些伪代码/Pytorch 代码演示软注意:
self.attention = nn.Linear(embed_size, embed_size)
self.softmax = nn.Softmax()attention_output = self.softmax(self.attention(feature_embedding))
feature_embedding = feature_embedding * attention_output
softmax 用于创建特征嵌入的概率分布。将这些概率与原始特征嵌入相乘将产生新的嵌入层,我们将把该新的嵌入层馈送给解码器。
使用转换器作为解码器:使用像 BERT 这样强大的转换器是构建更好的图像字幕模型的下一步。虽然这似乎是一个显而易见的选择,但在现实中却更具挑战性。这是因为转换器的固有结构限制了它只能输入单词和文本。例如,BERT 被预先训练了像下一句预测和掩蔽语言建模这样的任务,这使得它很难将文本之外的东西纳入其输入。要将变压器端到端地纳入培训过程,需要一个特殊的/经过修改的变压器。有一些这方面的论文发表过,像这个和这个。
我希望您觉得这些内容很容易理解。如果你认为我需要进一步阐述或澄清什么,请在下面留言。
参考
MSCOCO 数据集:https://cocodataset.org/#home
Flickr8k 数据集:https://www.kaggle.com/datasets/adityajn105/flickr8k
使用 venv 和 PyPI 构建和分发 Python 包
Python 是一个开源平台,建立在无数付费和自由开发者的基础上。当以面向对象编程(OOP)风格编码时,它的灵活性和可重用代码得到了最好的利用。当我们创建可以重复使用的类和函数时,我们展示了 OOP。这些类最好的例子可能是在 Python 包中实现的。
当开发一个 python 包时,问自己一个问题总是好的,“谁将会或可能会从这些代码变得用户友好和易于访问中受益?”答案通常是很多,特别是如果它是在广泛的应用程序中实现的一个普通的重复任务,并且代表了其他程序员或不太喜欢数学的外行用户所面临的问题。
第一步:注册 pypi.org 账户
报名账号:https://pypi.org/****。Python 包索引(PyPI)是 Python 编程语言的软件仓库
步骤 2:升级 pip 版本
python3 -m pip install --upgrade pip
步骤 3:配置您的环境
理想情况下,您在特定于包的环境中开发您的包。因此,一旦您导航到一个文件夹目标 package_name/ ,您将运行下面的命令。我们这样做,所以我们有一个空白的石板来在一个干净的工作环境中安装所需的依赖项。导航到最终创建包的文件夹后。我们可以使用命令:
python3 -m venv env
这将在您现有的工作目录中创建一个名为“env”的文件夹,它代表您的环境的名称。
如果你正在使用 VS 代码(强烈推荐),那么你可以通过点击 Ctrl+ shift+ P (PC)或 Cmd+ shift+ P (Mac)并选择“选择解释器”来选择这个环境,并从下拉列表中选择你的虚拟环境。
如果您喜欢在 VSCode 中从命令行控制,您可以使用:
source env/bin/activate
步骤 4:文件结构
您的包的生成文件结构应该类似于以下内容:
package_name/
├── LICENSE
├── setup.cfg
├── setup.py
├── README.md
├── MANIFEST.in
├── env/
├── package_name/
│ ├── __init__.py
│ └── example.py
└── tests/
│ ├── __init__.py
└── └── tests.py/
因此,让我们看一下上面列出的接下来几个文件的创建过程。
init。巴拉圭
您的 init。py 文件应该是空的,用来让 python 知道你正在使用一个类,因为它有助于初始化它。你可以选择在这里放一些包依赖项,但是大多数应该在 example.py 文件中运行。你将需要一个 init。包中每个子文件夹的 py 。所以如果你有更多的子包,你会有更多的 init。每个对应文件夹中的 py 文件。
README.md
这应该是一个信息性的降价文件。它为用户提供了如何使用软件包的信息。这将最终出现在你的 pypi.org 主页上。这里可以看到我的例子:https://pypi.org/project/psmpy/。最好保持这种信息丰富,并尽可能面向用例。
Setup.py 文件
不需要静态 setup.cfg 和 setup.py 都可以。所以选一个吧。一个 setup.cfg 在技术上是首选。
- setup.cfg =静态安装文件
- setup.py =动态设置文件
下面是一个 setup.py(动态文件)的示例:
from pathlib import Path
from setuptools import find_packages, setupdependencies = ['matplotlib', 'numpy', 'pandas',
'seaborn', 'sklearn', 'scipy', 'sklearn']# read the contents of README file
this_directory = Path(__file__).parent
long_description = (this_directory / "README.md").read_text()setup(
name='example-package',
packages=find_packages(),
version='0.0.1',
description='Propensity score matching for python and graphical plots',
author='Author name here',
[author_email='](mailto:author_email='askline1@gmail.com)author**@example**.com',
long_description=long_description,
long_description_content_type='text/markdown',
license='MIT',
project_urls={
"Bug Tracker": "[https://github.com/](https://github.com/adriennekline/psmpy)",
},
classifiers=[
"Programming Language :: Python :: 3.6",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
],
install_requires=dependencies,
setup_requires=['pytest-runner'],
tests_require=['pytest==4.4.1'],
test_suite='tests',
)
以及 setup.cfg(静态)文件的示例:
[metadata]
name = example-package
version = 0.0.1
author = Example Author
author_email = author**@example**.com
description = A small example package
long_description = file: README.md
long_description_content_type = text/markdown
url = https://github.com/pypa/sampleproject
project_urls =
Bug Tracker = https://github.com/pypa/sampleproject/issues
classifiers =
Programming Language :: Python :: 3
License :: OSI Approved :: MIT License
Operating System :: OS Independent
[options]
package_dir =
= src
packages = find:
python_requires = >=3.6
[options.packages.find]
where = package_name
批准
这里有一个麻省理工学院许可证的例子(这很可能是你需要的)。还有其他选择——https://choosealicense.com/【2】。下面是我自己工作中使用的麻省理工学院许可证的一个例子:
Copyright (c) 2022 Author namePermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
清单. in
您可以在这里列出所有要包含在软件包发行版中的额外文件。这将确保您的 license.txt 和 README.md 将由最终用户下载并随您的软件包一起安装。
include LICENSE
include README.md
示例. py
这里是您构建类的地方。您可以在这里引入其他函数、子包和库。
from .functions import cohenD
import numpy as np
from scipy.special import logit, expit
from sklearn.neighbors import NearestNeighbors
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.linear_model import LogisticRegression
import math
import pandas.api.types as ptypes
import seaborn as sns
sns.set(rc={'figure.figsize': (10, 8)}, font_scale=1.3)class PsmPy:
"""
Matcher Class -- Match data for an observational study.
Parameters
----------
data : pd.DataFrame
Data representing the treated group
treatment : str
Column representing the control group
indx : str
Name of index column
exclude : list (optional)
List of variables to ignore in regression/matching.
target : str (optional)
Outcome variable of interest, will ignore in regression/matching
----------
"""def __init__(self, data, treatment, indx, exclude=[], target='outcome'):
# variables generated during matching
# assign unique indices to test and control
self.data = data.dropna(axis=0, how="all") # drop NAN rows.
.
.
第五步。构建您的包
在构建你的轮子和发行版之前,你需要将你的虚拟环境 venv 改回你的基础环境。你需要安装麻绳。Twine 是一个将 Python 包发布到 PyPI 的工具。它为源代码和二进制发行版提供构建[3]。
$ conda activate base(base) $ pip install twine
(base) $ pip install build
创建源和轮分布:
source——一个主要是源代码
wheel 的分发包——一个经过处理的分发包,可以更快地安装
sdist =源分布
bdist_wheel =轮分布
(base) $ python setup.py sdist bdist_wheel
这将在您的目录中添加一个 dist 文件夹:
package_name/
├── LICENSE
├── setup.cfg
├── setup.py
├── README.md
├── venv/
├── **dist/** │ ├── **package_name-0.1.0-py3-none-any.whl**
│ ├── **package_name-0.1.0.tar.gz** ├── **build**
├── **package_name.egg-info**
├── package_name/
│ ├── __init__.py
│ └── example.py
└── tests/
步骤 6:上传/分发您的包
使用命令将您的包上传到 PyPI:twine upload dist/*。系统将提示您输入之前创建的用户名和密码!
(base) $ twine upload dist/*Uploading distributions to [https://upload.pypi.org/legacy/](https://upload.pypi.org/legacy/)
Enter your username: **YOUR_USER_NAME**
Enter your password: **YOUR_PASSWORD**
Uploading package_name-0.1.0.tar.gz
100%|██████████████████████████████████████████████████████████████| 2.5k/2.5k [00:01<00:00, 2.1kB/s]
您还可以将您的发行版上传到 TestPyPI 进行测试(可选):
(base) $ twine upload -r testpypi dist/*
你现在可以通过 pip 命令从 pypi.org 安装你自己的软件包。请注意,当您更新您的软件包时,您需要更改版本号,否则将无法上传到 pypi.org。
作者图片
快乐创作!
参考
[1]打包 Python 项目,https://Packaging . Python . org/en/latest/tutorials/Packaging-Projects/,访问时间:2022 年 4 月 11 日
【2】选择开源许可,https://choosealicense.com/访问时间:2022 年 4 月 13 日
【3】Twine,https://pypi.org/project/twine/访问时间:2022 年 4 月 13 日
如何利用谷歌云生态系统构建和扩展数据平台
使用 Google 的工具堆栈构建数据平台的电子商务之旅
亚历山大·布西在 Unsplash 上拍摄的照片
从头开始构建数据平台既令人兴奋又令人畏惧。
无论你是早期还是晚期公司,你在建立基础数据平台方面的选择将可能对未来几年的业务产生重大影响。
当然,****最初的目标应该是解决最燃眉之急的业务问题(例如,减少重复和手动分析)。
然而,长期目标应该是通过简化您的决策过程来帮助您扩展业务。
考虑到这两个目标,这篇博文将展示我们的电子商务** 之旅,使用 Google 的工具栈从零开始构建一个数据平台。**
****首先,我们将解释促使我们决定构建数据平台的业务需求。
****然后,我们将分享我们在项目开始时使用了哪些谷歌工具,以及我们的数据架构是如何围绕可用的谷歌云服务发展的。
****最后,如果你自己决定走这条路,我们会指出构建数据平台时需要注意的事项。
决策:为什么要构建数据平台?
在电子商务领域突然繁荣之后,我们建立数据平台的计划始于 2020 年。
随着增长高于预期,我们经历了两个重大的** 问题影响了我们的决策过程:**
- 问题#1 |初始需求:
作为一家拥有 40 多家店铺的电子商务公司,我们遇到了数据孤岛问题。换句话说,我们的主要数据来源——销售历史、绩效营销数据来源(谷歌分析和 15+其他流量来源)、财务报告等。,被孤立了。
这导致业务部门的手动工作增加,即他们手动下载来自不同来源的数据,并将它们重叠在 Google Sheets 中,以创建跨数据集洞察。因此,我们需要一个详细的控制框架。
因此,我们对数据平台的初始业务需求是解决数据孤岛问题,并自动创建跨数据集(和跨部门)的数据洞察。
- 一期#2 |长期需求:
为了给我们的客户提供更好的服务,我们 需要开发更高级的分析用例:
- 优化库存水平的需求预测模型。
- 创造更好的时事通讯的市场篮子分析模型。
- 利用竞争对手的价格制定更好的定价策略的动态定价模型。
- 客户细分模型,以便更好地了解客户的购物偏好,并为他们提供定制优惠和忠诚度折扣。
因此,我们对数据平台的长期需求是通过开发更高级的分析用例来帮助我们扩大业务规模。
牢记这两个要求,我们将分享我们构建和扩展数据平台的旅程。
开发:如何构建和扩展数据平台?
在达成构建数据平台的跨业务和技术决策后,我们开始评估最适合我们的云解决方案。
主要标准是云提供商支持我们扩大(或缩小)并且我们可以轻松控制成本。****
当谈到扩展标准时,所有云提供商都能够按照我们的业务要求支持我们。然而,云供应商之间的定价不同,我们评估谷歌云在我们计划使用的服务上提供了更多折扣。此外,由于我们已经大量使用 GoogleAds,我们更容易获得内部和外部咨询支持。****
这也是我们决定收购谷歌云平台的原因。
因此,我们开始构建我们的初始数据层:
初始数据架构[图片由作者提供]
如上图所示,初始数据架构由以下几层组成:
- #1:数据收集层: 呈现最初必须导入到我们的数据仓库中的最相关的数据源。
- #2:数据集成层: 呈现用于导入电子商务数据集的 cron jobs 和用于导入效果营销数据集到我们的数据仓库的漏斗. io 平台。
- #3:数据存储层: 呈现选中的数据仓库解决方案,即 BigQuery 。
- #4:数据建模与表示层 :呈现选择的数据分析平台,即 Looker 。
总结我们最初的工作:
- 首先,我们致力于创建数据存储层,将来自两个主要数据源集群(商店电子商务数据集和绩效营销源)的数据导入 BigQuery。**
- ****其次,我们通过使用 Looker 开发跨数据集自助数据模型,开始创建 数据建模&表示层 。
我们在 Google Cloud 中构建数据平台的初始资源可以量化如下:
- 2 个工具— BigQuery 和 Looker ,
- 6 人— 负责管理数据管道(cron jobs + Funnel.io 平台)和初始分析需求(数据建模),
- ****3 个月——从收购谷歌云到展示第一份分析见解。
必须提到的是,最初,我们没有专门的数据团队来构建数据平台。
相反,我们在两个部门之间分配工作——来自 IT 部门的五名同事(负责数据管道)和来自业务开发部门的一名同事(负责数据建模)。
借助列出的资源和组织结构,我们实现了最初的业务目标,并自动化了跨数据集数据洞察的创建。
从那时起,对数据洞察的业务需求开始增长,计划是开始开发更高级的分析用例。
这导致了数据架构的变化和新 Google 服务层的扩展:
*****改变了数据架构[图片由作者提供] **********
从上面提供的图片可以看出,我们用 数据预处理层 扩展了我们的数据架构,并开始使用新的谷歌云服务和工具:
- 云存储 —用于在谷歌云中存储我们的外部文件。
- 云运行 —用于部署用 Python 开发的分析管道,并包装为 Flask 应用程序。
- Google Functions—用于编写简单、单一用途的函数,附加到云服务发出的事件上。
- 谷歌工作流 —用于编排需要以特定顺序执行的连接分析管道。
- Google Colab—用于创建快速 PoC 数据科学模型。
随着数据架构的扩展,我们的资源有所增长:
- 从 2 到 7 工具——从到只使用只使用biqquery 和 Looker,我们开始使用云存储、云运行、谷歌功能、谷歌工作流、谷歌 Colab。
- 从两个团队(IT 和业务开发)的 6 人增加到一个团队(数据和分析)的 8 人— 数据和分析团队成立,现在对所有数据层拥有完全的所有权。
- 从 3 个月的初步洞察到 2 年多的持续开发— 我们正在逐步开发更高级的分析用例。
这就是我们目前所处的位置——积极致力于提供新的、更先进的分析用例,以简化我们的决策过程并更好地支持我们的客户。
最后,我们将分享如果您从零开始构建数据平台,应该关注什么的主要要点。
总结一下:需要注意什么?
在开始构建云中的数据平台之前,请考虑以下两个主题:
- 你的优先事项和当务之急是什么? —优先处理数据平台应该立即为您解决的用例,这些用例可以立即产生商业价值。
- 你的制约因素是什么?— 思考并量化一切—从软件和人力资源到所需的时间和精力、内部知识水平和资金资源。
在这一部分,请记住两个方面:
- 从速赢开始 —不要直接钻研数据科学和机器学习模型开发,而是从速赢用例(通常是描述性统计用例)开始。
- 实事求是— 在设定数据平台目标时,重要的是要实事求是地考虑在给定的当前约束条件下,什么是可行的。
此外,在数据平台的开发过程中,要特别注意以下几点:
- 构建数据管道 —正确开发的数据管道将为您节省金钱、时间和精力。开发管道是开发中最关键的部分,也就是说,您的管道经过适当的测试,并向业务用户提供新数据,而不会因为各种数据和系统异常而不断中断。
- 组织和维护数据仓库— 有了新的数据源,数据仓库会很快变得混乱。为更好的数据仓库组织实现开发标准和命名约定。
- 数据预处理— 考虑尽早获得数据预处理工具,通过对数据集进行去规范化来提高仪表板性能并降低计算成本。
- 数据治理和安全— 制定关于数据生命周期(数据收集、存储、处理和处置)的内部标准和数据政策。
通过列出这些要点,我们结束了我们的帖子。
如果你决定建立自己的数据平台,我们希望这篇文章对你有所帮助。
*鸣谢:感谢我的同事 Stefan Gajanovic ,他帮助我们将改变后的数据架构可视化。
如何构建有效(且有用)的仪表板
原文:https://towardsdatascience.com/how-to-build-effective-and-useful-dashboards-711759534639
基于真实例子的四步法
Firmbee.com在 Unsplash 上拍照
我全职做数据分析师已经快两年了。我还记得我第一次被要求做一个仪表板:老实说,我不知道从哪里开始。所以我的直觉告诉我直接跳到数据中,开始到处写 SQL 查询(见下面的步骤 3)…结果我得到了一堆没有明确答案的问题和没有实际用途的代码。
通过实践,我一直在开发一种四步法(我仍在微调)来避免这种情况,并确保我构建的仪表板首先是有效的,而且是有用的。
成功构建仪表板最困难的部分是什么?不是而是创建构成仪表板本身的数据可视化,其余的都是:理解仪表板的目的,描绘它应该是什么样子,并最终反映所做的工作。
在这篇文章中,我想带你经历这四个步骤。无论您是一名整天构建数据可视化的经验丰富的分析师,还是一名不时使用仪表板的业务用户,我希望您会发现这些指南非常有用。
第一步:问正确的问题
首先,问问自己是在什么背景下产生了对新仪表板的需求。为此,您可以从提出仪表板请求的“5ws”开始:谁?什么?什么时候?在哪里?为什么?如果您正在为其他人或与其他人一起构建这个仪表板,请一起进行这一阶段的反思。
正如我经常强调的,为什么最重要。无论是关于建立一个仪表板,还是在早上醒来,这个问题的明确答案将指导你的工作,并在你建立仪表板的整个过程中激励你:这个仪表板为什么要存在?
要考虑的另一个重要方面是您将构建的仪表板的未来用途。为什么要花费数小时构建一个未被充分利用的仪表板?确保你对以下问题有一些明确的答案:
- 这个仪表板满足了其他工具、图表或仪表板无法满足的什么需求?
- 这个仪表板有什么用途?
- 谁将使用该仪表板?
- 该仪表板的使用频率如何?
为了说明我的观点,让我们举一个例子:你公司的 CEO 来找你要一个仪表板。在她离开房间之前,确保你得到了关于背景(让我们假设这个仪表板是为了在某些地区推出新产品)、为什么必须建立仪表板的原因(她目前没有关于这个特定项目的指标,她需要一些来监控项目的成功)、最终用户(在这种情况下,是首席执行官和项目团队成员)和仪表板的使用频率(每周一次项目周回顾)。****
第二步:画出目标
现在,您对这个未来仪表板的详细情况有了更清楚的了解,您可以继续前进并绘制您的仪表板的目标图。这一步的目标不是设计一个非常详细的仪表板视图,而是画出 2 或 3 个主图,并显示一些关键信息。
出于这个目的,我个人更喜欢与每个利益相关者单独进行公开讨论,然后花一些时间将我所有的想法收集到一个大纲中。但一些同事习惯于在与利益相关者讨论主题的同时绘制大纲。选择最适合你的方法(或两者的组合)。
在你的大纲中,你至少应该已经确立了:
- ****您想要跟踪的指标及其确切定义(例如,在这个特定用例中,“收入”的确切含义是什么?利益相关者如何定义“成本”?)
- ****汇总级别(例如,数据是每天还是每月都需要?应该比较两个个人客户还是两个客户群?)
- ****时间范围(例如,数据应该与去年的数字相比还是与上周的数字相比?是一年预测还是一秒预测?)
在我之前的例子中,在采访了 CEO 和项目团队成员后,大纲可能是这样的:
Marie Lefevre,使用 Excalidraw 构建
第三步:提取数据并整理成形
正如我前面提到的,我曾经在出现对仪表板的需求后立即进入第三步。查询数据和创建图表是数据分析师的典型任务,不是吗?
有趣的是,我注意到,如果我事先遵循步骤 1 和 2,这些任务会进行得更顺利、更快。考虑到业务用户的需求和手中的仪表板概要,现在您“只”需要获取数据并相应地格式化数据,以创建相关的数据可视化。随着最终结果的不确定性减少,您将减少与利益相关者之间的交流,在您从零到一个惊人的仪表板的过程中,节省您的一些时间和压力。
在当前的例子中,我从财务部门的数据库中查询数据,这是项目团队同意的。对于输出表,我每周显示一行,计算字段(产生的收入、售出的单位、平均价格)显示为列。最终,我在公司的 BI 工具中构建了仪表板。这里我用谷歌数据工作室:
玛丽·勒费夫尔,使用数据工作室建造
第四步:反思已经完成的工作
尽管您实际上构建了这个仪表板,但是您的工作还没有完成。记住:一个成功的仪表板是一个有用的仪表板。****
为了让它变得有用,第一步是让用户知道你的仪表板存在并准备好使用。根据上下文和最终用户,您甚至可以共享一个仍在开发中的版本。在前面的例子中,您可能与一个或两个项目团队成员共享仪表板的草稿版本,而不是与 CEO 共享。
在所有情况下,计划一次演示会议,在会上您将引导仪表板用户了解其主要功能。向他们展示该仪表板如何满足他们表达的需求:
- 他们在哪里可以找到他们需要的指标?
- 他们应该如何使用过滤器来查看与他们个人相关的指标?
- 他们应该如何解读每张图表?
最后但同样重要的是:对反馈持开放态度。仪表板用户可能不会马上向您提问,但是随着时间的推移,可能会出现一些问题。为了确保仪表板用户不会因为某种原因处理某个块并放弃使用它,在仪表板发布后几天或几周再回到他们那里。反馈会议可以通过非正式讨论或后续会议进行。
您可以向仪表板用户提出的典型问题包括:您上次使用仪表板是什么时候?出于什么目的?它符合你的期望吗?你对此有疑问吗?您在使用它或解释某些指标时是否面临任何困难?这将允许您事后再次检查您是否正确地构建了用户需求,以及构建仪表板时的执行是否顺利。
还可能发生的是,用户根本不会使用你的仪表板。我知道,这听起来违背直觉,令人沮丧。在这种情况下,你最好的办法还是回去找他们,调查为什么会这样。仪表盘太复杂,不好用吗?是不是它加载太慢了?需求是否发生了变化,以至于显示的指标不再相关?根据他们的回答,你将能够调整仪表板,使其更加相关。****
…然后重复!
我不是一夜之间想出这个办法的。我过去常常直接跳到数据中。然后我注意到一些背景和对用户需求的更好的定义会帮助我在仪表板方面变得更好。最后,在真正的“数据查询”部分之前,我理解了绘制轮廓的附加价值。根据经验,我知道反馈和自我反省有助于你随着时间的推移提高技能。
你呢,随着时间的推移,你是如何提高你的仪表板技能的?你成功构建仪表盘的秘诀是什么?不要犹豫,在评论区分享你的观点吧!
你喜欢读这篇文章吗? 成为 的一员,加入一个不断成长的充满好奇心的社区吧!
**https://marie-lefevre.medium.com/membership **
生成性对抗网络(GANs),解释和演示
原文:https://towardsdatascience.com/how-to-build-gans-to-synthesize-data-64334b877f70
gan 如何工作以及如何使用它们来合成数据
图 1 —一个人的合成图像,完全由 GAN 生成。图片来源:https://thispersondoesnotexist.com/。许可证:https://github . com/luci drains/style gan 2-py torch/blob/master/LICENSE(麻省理工学院)
如果你在深度学习领域工作,你可能听说过 GANs,或者https://arxiv.org/abs/1406.2661(good fellow 等人,2014)。在本帖中,我们将解释什么是 gan,并通过真实的例子讨论一些用例。我在这个帖子里加了一个我的 甘操场 的链接,叫 MP-GAN (多用途甘)。我在 github 准备了这个操场作为研究框架,欢迎大家用它来自己训练探索 GANs。在附录中,我介绍并讨论了我在 GAN 训练中使用这个操场所做的一些实验。
*https://github.com/tsubu01/MP-GAN
高级解释
生成模型
gan 是 生成 深度学习架构家族的一部分,其目标是 生成 合成数据,而不是预测现有数据点的特征,就像分类器和回归器的情况一样(两者都属于称为 判别 模型的模型家族。在我以前的一些帖子中讨论的对象检测神经网络,像 对象检测器 YOLOv3 和CenterNet,是分类器和回归器的组合,因此也是判别模型)。在我们现在不讨论的其他生成机器学习模型中,有 变分自动编码器(VAEs)扩散模型 , 受限玻尔兹曼机器 (RBMs)。
为什么要生成数据?
- 为了改进鉴别模型的训练- 一些应用,例如自动驾驶,需要非常大的里程数据。此外,为了安全起见,模型需要在边缘情况下进行广泛的训练,如事故、未遂事故和其他车辆的异常行为,而实际收集的数据中没有足够的例子。其他例子:基于图像的火灾探测系统;集成电路生产线中的自动缺陷检测:欺诈检测算法和多传感器机器故障检测系统的合成场景(表格数据合成)。
- 商业——许多吸引人的图像在现实中很难或不可能创作出来,或者手工绘画既昂贵又耗时(即使使用专用软件)。在这种情况下,人工生成的图像可以是一个公平的替代品。例如:亚麻广告中的合成卧室图像,或者牙膏广告中的合成人脸(如图 1 所示)。
- 艺术——如果你在媒介方面经验丰富,那么生成模型就是一种工具——就像画笔一样。一些艺术家是产生视觉上吸引人的人造图像的专家。
氮化镓结构和流程
顾名思义,GANs 由两个对立的神经网络组成——一个是 生成器 (或 G),试图生成数据的合成样本,另一个是 鉴别器 (或 D),试图区分合成样本和真实样本。d 实际上是一个 分类模型 。让我们假设我们想要自动化我们的邮件系统。我们训练一个连接到相机的机器人手臂读取信封上的邮政编码,但我们担心我们没有足够的样本,机器人会被硬例子弄糊涂。因此,我们希望生成许多合成的手写数字图像来增强训练集。初始化 D 和 G 后的基本训练流程如下:
- 冻结 G,只在几个真实的和几个合成的图像(由 G 生成)上训练 D。
- 冻结 D,仅训练 G,损失对应于 D 正确分类为“合成样品”的样品比率。
- 评估结果,并重复直到达到满意的性能(如果在阶段 2 呈现给 D 的真实与合成图像的比率是 50/50,那么理想的结果是在阶段 3,D 在 50%的时间内对合成和真实示例都进行了错误分类)。
GAN 的高级结构在图 2 中的以下两个图示中给出:
图 2 — Gan 训练阶段。上图:第一阶段——鉴别器训练区分真实图像和合成图像。真实图像和合成图像被交替地馈送到 d。训练损失是鉴别器分类误差的二进制交叉熵损失。下图:第二阶段——发电机训练以合成看起来真实的图像。只有合成图像与标签“0”一起被传递到鉴别器,表示它们是合成的。训练损失是鉴别器分类误差(小误差→大 G 损失)的补码上的二元交叉熵损失。图片来源:作者。
正如可以预料的那样,起初,G 和 D 都不擅长他们所做的事情。在最初的训练步骤中,😄 不知道有效的数字图像应该是什么样子,G 也不知道。但是,通过提供给 D 训练阶段的标签(“真实的”、“合成的”),D 获得了真实数据样本应该是什么样子的一些知识。几个例子之后,D 在将样本分类为真实样本和合成样本方面略有提高(记住——在这一点上,合成样本很糟糕,因此不难理解其中的区别)。然后我们冻结它的参数,并训练 G。当 D 抓住欺诈行为,推动 G 生成看起来像 D 感知为真实的样本时,发生的损失,等等。图 3 展示了训练 GAN 以生成手写数字“8”的样本的过程。
图 3 —使用 MP-GAN 生成手写数字图像样本。左上:训练期间生成的数字“8”的样本。左栏是训练时期的数量。右上:训练过程中鉴别器对真实图像和合成图像进行分类的准确度。左下和右下:学习潜在空间的两个网格探索。训练集是来自 MNIST 的手写数字“8”的 1024 幅图像。图片来源:作者。
生成模型背后的一些图解数学
对高分辨率彩色图像(如人脸)使用 GANs 进行实验是非常计算繁重的,因此为了简单起见,让我们将讨论限制在 MNIST 数据,例如手写数字的 28x28 像素灰度图像。(MNIST 是对 NIST 数据、科恩(Cohen,g .)、阿夫沙尔(Afshar,s .)、塔普森(Tapson,j .)、&范沙克(van Schaik,a .)(2017)。em NIST:MNIST 对手写信件的扩展。检索自http://arxiv.org/abs/1702.05373。是由 勒村、科尔特斯和伯格斯 创造的。MNIST 数据集是在知识共享协议的条款下提供的,共享 Alik3 3.0 许可,参见许可细节此处。
我们将论证每个数字图像是一个 28×28 = 784 维的向量,每个坐标的值等于相应像素的灰度级。这个图像空间的体积是有限的,但却是巨大的:它是一个由 256⁷⁸⁴不同坐标组合或图像组成的超立方体。
自然,这个空间的大部分体积对应的是完全没有意义的图像。一小部分空间对应有意义的图像,一个更小的静止部分对应数字图像。
让我们用研究人员使用的术语来表述我们的步骤和目标:
- 生成合成的数字图像相当于在 784 维空间中召唤出一个向量,在真实数字图像的密集分布的斑点内的某处,其中数字图像的概率分布很高。
- 虽然我们可以相对容易地将给定的向量分类为有效或无效的数字图像(通过训练分类器),但是在数字图像斑点内变出向量的相反过程是困难的。这主要是因为有效的数字图像不是简单地集中在一个或几个漂亮的球形斑点中。相反,它们分散在这个 784 维空间的无数细丝中;作为一个快速演示,考虑一组有效数字图像,然后将所有图像向右移动一个像素——这将形成另一组有效数字图像,但与 784 维空间中的第一组非常远。
- 因此,我们正在修改我们的任务——学习从 另一个 (潜在)空间中的美好、舒适和已知的分布(例如高斯)到 784 维图像空间中的有效数字图像的细丝的变换。
- 完成这些后,我们可以从潜在空间的密集区域中提取点,以生成更多真实图像的样本。G 和 D 学习的变换如图 4 所示。
图 4 —图像空间的图示。中心:MNIST 图像是 784 维空间(这里简化为 3 维空间)中的向量。有效的数字图像在这个空间中显示为点的斑点(黄色的云)。斑点的数量是天文数字,并且它们的边界没有很好地定义(取一个表示‘8’的向量,并且将一个随机像素值增加 1——它仍然有效吗?重复)。斑点之间的无效图像空间的体积要大得多(例如,每个可能的 28x28 噪波都是该空间中的一个点)。生成器学习从潜在空间(左侧,简化为二维)到有效数据斑点的变换(黑色箭头)。鉴别器学习从图像空间到一维概率轴的变换,指示其输入是真实的(1)还是合成的(0)。图片来源:作者。
关于这个修改后的任务有几点:
- 每当这个学习函数将一个潜在点转换成一个无效图像时(由鉴别器判断),所产生的损失将它稍微推向一个有效图像斑点。
- 根据定义,与来自稀疏部分的点相比,该模型将对来自潜在空间中分布的密集部分的更多示例进行训练,并且因此将更有动力将它们转换成有效图像(即,有效图像斑点的中心附近)。假设上述学习过程是有效的,这将最终导致潜在空间分布的密集部分中的点转换为有效图像斑点的密集区域中的图像。这实际上意味着,如果您通过输入来自正态分布噪声的样本来训练 GAN,那么您可以期望来自靠近原点的区域的样本产生有效的数据样本,而来自远离原点的噪声样本产生不太真实的数据样本。查看附录中的实验部分,看看当我们遍历潜在空间时,生成的样本如何变化。
如果我们从头开始训练鉴别器(GANs 通常就是这种情况),那么生成器试图学习的轮廓在开始时是非常不准确的(因为鉴别器不知道任何更好的东西),但是它们随着每个鉴别器学习阶段而改善。然而,如果我们有某种程度上训练过的分类器,我们可以用它作为我们的鉴别器,并为生成器的训练有一个良好的开端。
训练 GANs 的一些挑战
GAN 训练的细节因用户而异。有的练 D 走几步,再练 G,等等。有些人每走一步就在它们之间切换。在我的 MP-GAN 框架中,每个 G 训练步骤(批次)之前都有一个 D 训练步骤,分为两部分:前半部分显示真实数据,后半部分显示合成数据。
使用 亚当 优化器通常被认为是一种好的做法,可能是因为动量有助于稳定非常嘈杂的训练过程。正如我在实验一节中所展示的,这种做法似乎是有实证依据的。
注意,训练 GANs 比训练判别模型更棘手。特别是,原始论文的作者 Goodfellow 等人提到了 、、、后来被称为、、、,其中 G 将潜在空间中的多个点映射到相同的输出,或者输出空间中的一个狭窄区域。如果训练过程不平衡,并且 G 与 D 相比训练过多,就会发生这种情况。例如,如果在训练中的某一点,D 碰巧比其他数字更擅长对数字“0”的真实和合成图像进行分类,并且它停止训练,那么 G 会被鼓励将所有潜在点转换为“0”,等到 D 再次开始训练时,G 可能已经很高兴地陷入局部最小值,没有离开的动机(除非它因没有生成其他数字而受到某种惩罚)。
另一个使 GAN 训练困难的问题是过程的内在不稳定性,因为训练试图同时最小化两个损失函数,但它交替地这样做,每次采样一个损失图并更新参数,然后是另一个,但随着一个模型的参数改变,这也会影响另一个模型的损失。
结论
GANs,即生成对抗网络,是一种深度学习机制,通过两个模型之间的训练竞争来学习生成新的数据样本——生成器和鉴别器。
由于问题的内在不稳定性和模式崩溃的风险,训练 gan 比训练判别模型更棘手。
使用我在附录中提出的框架,有可能建立和训练 GANs 的各种架构,并研究其训练的动态。
看看我的 GAN 实验,往下几行!
访问我以前的帖子:
决策树,解释
CenterNet,已解释
YOLOv3,解释
附录 1 —代码示例
在这一节中,我将介绍我使用 github 中准备的 GAN playground (MP-GAN)做的几个 GAN 实验。
欢迎您从我的 MP-GAN(多用途 GAN)存储库中进行分叉,并尝试不同的 GAN 架构、数据集和训练场景。这个项目支持图像(目前只有单通道)和表格数据。
https://github.com/tsubu01/MP-GAN
实验 1 —优化器对训练收敛的影响
我使用我的 MP-GAN github 框架来训练两个相同的架构,一个使用 SGD 优化器,另一个使用 Adam 优化器。对发生器的输出进行采样揭示了第一个时期的差异。我的发现支持了多个来源的说法——Adam optimizer 确实更适合这项任务。图 5 给出了一个例子。
图 5 —左图:(上图)经过 10 个时期的训练后,SGD 优化器的合成图像。右图:(上)使用 Adam 优化器。在这两种情况下,学习率衰减为 0.9。底部一行是来自 MNIST 数据集的真实图像的随机样本。图片来源:作者。
实验 2——比较从零开始的收敛和使用预训练鉴别器的收敛
我假设,虽然根据定义,生成器 D 是从零开始训练的,但是不应该有数学上的基本原因来解释为什么鉴别器需要从零开始训练。常见的原因是实际的——通常我们只是没有一个训练有素的模型来分类真实和合成的图像。但是,如果我们确实有一个经过训练的鉴别器(例如,来自以前的训练),使用它应该不会损害生成器的收敛性。在图 6 中,我比较了来自从零开始用鉴别器训练的生成器的样本,与当鉴别器取自先前训练会话时的生成器训练的样本。可以看出,在 10 个时期之后,使用预训练鉴别器的 GAN 产生比从零开始训练的 GAN 更高级和更真实的样本。然而,在 50 个时期之后,从零开始训练的 GAN 似乎已经赶上来了(图 7)。如上所述,两次运行中合成样本中某些数字的缺乏可能表明模式崩溃。
图 6-左:从零开始经过 10 个时期的训练后的合成数字图像(顶行)。右图:使用预训练的鉴别器,在 10 个时期的训练后合成的数字图像(顶行)。下面几行是来自 MNIST 的真实图像。图片来源:作者。
图 7——从零开始 50 个训练时期后的随机合成数字图像(左),对比使用预训练的 D(右)。图片来源:作者。
按照这个思路,我添加了一个选项来冻结鉴别器参数并节省训练时间。我发现,正如预期的那样,总的训练时间缩短了,但并不显著,因为在这种架构中,鉴别器比生成器小得多(40k 参数对 1M 参数)。
另一个可能具有有趣含义的实验(我还没有做过)是采用在数据集上训练的常规分类器(可能——使用您希望通过合成更多数据来改进的同一分类器!)并将其用作预训练的鉴别器并加速生成器训练收敛,冻结或不冻结大多数鉴别器参数以节省时间。
实验 3——探索潜在空间的轨迹
一个很好的实验是观察潜在空间中的相邻点是否转换成相似的图像。在图 8 中,我创建了一个 2D 坐标网格,并将其嵌入到潜在的 100 维空间中,其中其他 98 个坐标保持固定在 0(左右窗格来自潜在空间中的两个不同平面)。在左边,我们可以看到合成“9”到“4”再到“1”之间的平滑过渡。在右边,合成图像平滑地从“3”变换到“9”、“8”和“7”。有趣的是,我发现在所有的实验中,接近 0 的区域并没有转换成有意义的数字。我相信其原因是发生器中的非线性(泄漏 ReLU 激活)使得 0 成为潜在空间中的数字斑点之间的自然边界,这使得点接近多个数字祖先区域之间的 0 边界点。
图 8 —通过在潜在空间转换 10x10 网格合成的图像。左窗格和右窗格在嵌入网格的子空间上有所不同。图片来源:作者。
附录 2 —技术细节
我为在 MP-GAN 基础设施中试验 MNIST 图像数据集而创建的 GAN 具有以下结构:鉴别器(图 9)是 CNN(卷积神经网络),其具有由漏失层分隔的两个卷积,以具有 sigmoid 激活的密集层结束。生成器(图 10)从密集层开始,然后是整形,将潜在维度输入向量转换为图像形状。然后去卷积层增加空间维度,直到达到期望的形状,然后最终卷积使用特征维度中的信息来生成最终的 1 通道图像。我尝试在鉴别器中用批次名替换掉的人——但这并没有改善结果。
图 9 —鉴别器。卷积具有泄漏的 ReLU 激活,致密层具有 s 形激活。图片来源:作者。
图 10 —发电机。图片来源:作者。
不要因为鉴别器参数显示为不可训练而惊慌。这是由于该流水线中训练流的具体实现:在阶段 2——训练发生器中,我们实际上训练了整个 GAN 模型,但是鉴别器参数被冻结。*
如何在 Python 中为大数据工作流构建强大的气流 Dag
将您的气流管道扩展到云
图片由 Solen Feyissa 通过 Unsplash 拍摄
气流 DAGs for(真的!)大数据
Apache Airflow 是用于编排数据工程、机器学习和 DevOps 工作流的最流行的工具之一。但是它有一个重要的缺点。开箱即用,Airflow 将在本地运行您的计算,这意味着您只能处理适合您的机器资源的数据集。
要在大于内存的数据集上使用 Airflow 进行计算,您可以将包含繁重工作负载的特定 Airflow 任务扩展到 Dask 集群。这篇博客将向您展示如何为大于内存的数据集构建气流 Dag,而只需对您现有的 Python 代码进行最小的更改。
我们将详细介绍一个例子。你可以在这个专门的库中找到其他气流 DAG 的例子。
如何使用 Dask 扩展气流 ETL 任务
气流工作流程由Tasks
和DAGs
定义,并由Executors
协调。为了将繁重的工作流委托给 Dask,我们将在一个包含繁重计算的Task
中旋转一个盘绕的集群,并返回结果,在本例中是一个。 value_counts()
掠过一列兴趣。因为这个结果很容易被存储到内存中,所以我们可以立即关闭集群以限制成本,并在本地的下一个任务中继续使用这个结果。
免责声明:我在 Coiled 工作,是一名数据科学传播者。Coiled由Dask的最初作者马修·洛克林(Matthew Rocklin)创立,是一个面向分布式计算的开源 Python 库。
定义您的气流 ETL DAG
DAG
将包含以下 3 个Tasks
:
- 旋转盘绕的集群,对整个数据集执行繁重的计算,然后关闭集群;
- 使用结果计算汇总统计数据,并将这些数据保存到 CSV 文件中;
- 使用 result 查找前 100 名最活跃的 Github 用户,并将它们保存到一个 CSV 文件中。
让我们从使用@dag
装饰器定义一个气流DAG
开始,向它传递脚本中前面定义的default_args
以及一些您可以调整的其他参数。
# define DAG as a function with the @dag decorator
@dag(
default_args=default_args,
schedule_interval=None,
start_date=datetime(2021, 1, 1),
catchup=False,
tags=['coiled-demo'],
)
def airflow_on_coiled():
启动你的 Dask 集群
先来定义一下我们的第一个 Task
。
这就形成了一个名为“气流-任务”的盘绕式集群,由 20 个 Dask 工人组成,每个工人运行一个指定的盘绕式软件环境,以确保他们拥有所有正确的依赖关系。
# define Airflow task that runs a computation on a Coiled cluster @task()
def transform(): # Create and connect to Coiled cluster
cluster = coiled.Cluster(
name="airflow-task",
n_workers=20,
software="rrpelgrim/airflow",
) client = Client(cluster)
然后,我们可以将存储在 S3 上的数据集读入 Dask 数据帧,并计算出我们感兴趣的结果。在这里,我们加载 2015 年的 Github 存档数据(子集仅包括 PushEvents ),并通过调用.value_counts()
计算全年每个用户的 PushEvents 数量。
# Read CSV data from S3
ddf = dd.read_parquet(
's3://coiled-datasets/github-archive/github-archive-2015.parq/',
storage_options={"anon": True, 'use_ssl': True},
blocksize="16 MiB",
) # Compute result number of entries (PushEvents) per user
result = ddf.user.value_counts().compute()
因为我们现在在本地得到了结果,所以我们可以关闭集群来限制我们的成本。请注意,这实际上只是一种形式,因为 Coiled 会在 20 分钟不活动后自动关闭您的集群。
# Shutdown Coiled cluster
cluster.close()
return result
转到卷云仪表板,我们可以看到这个计算花费了我们 5 美分。不,这不是打印错误😉这意味着您可以使用盘绕自由层每月免费运行这个气流 DAG 示例多达 200 次。
本地使用结果
我们已经利用云资源获得了我们感兴趣的结果,现在我们可以在本地继续执行以下任务。因为 Coiled 在您自己的机器上本地运行,所以读写本地磁盘很简单。
我们将生成result
熊猫系列的汇总统计数据,并将其保存到一个 CSV 文件中:
@task()
def summarize(series):
# Get summary statistics
sum_stats = series.describe() # Save to CSV
sum_stats.to_csv(
f'{storage_directory}usercounts_summary_statistics.csv'
)
return sum_stats
并获取前 100 名最活跃用户的用户名和推送事件数量:
@task()
def get_top_users(series):
# Get top 100 most active users
top_100 = series.head(100) # Store user + number of events to CSV
top_100.to_csv(f'{storage_directory}top_100_users.csv') return top_100
最后但同样重要的是,我们将指定我们希望气流Tasks
运行的顺序,并实际调用DAG
函数来触发工作流。
# Call task functions in order
series = transform()
sum_stats = summarize(series)
top_100 = get_top_users(series) # Call taskflow
airflow_on_coiled()
干得好,都准备好了!现在,您可以将 Airflow DAG Python 脚本添加到您的dags
文件夹(默认为:~/airflow/dags
)中,并根据需要运行或调度它。
重要提示:默认情况下,气流禁用 *pickling*
。您必须启用它才能运行 Dask 任务。你可以通过编辑你的 *airflow.cfg*
文件或者通过使用 *export AIRFLOW__CORE__ENABLE_XCOM_PICKLING = True*
设置相应的环境变量来实现。在启动 Airflow 服务器之前,请执行此操作。 如果你在苹果 M1 机器上工作,你可能想看看这篇关于使用 conda 安装 PyData 库的博客。具体来说,确保在您的本地和集群软件环境中既没有安装 *blosc*
也没有安装 *python-blosc*
库。
更多气流 DAG 示例
在专用的 带盘管的气流库中,您将找到另外两个使用 Dask 的气流 DAG 示例。示例包括常见的气流 ETL 操作。
请注意:
- JSON-to-Parquet 转换 DAG 示例要求您将 Airflow 连接到亚马逊 S3。您可以在气流文件中找到操作说明,点击。您还需要使用
storage_options
关键字参数将您的 AWS 秘密传递给to_parquet()
调用。 - XGBoost DAG 示例仅适用于> 20GB ARCOS 数据集的约 250MB 子集。要在整个数据集上运行它,请查看本教程。
https://coiled.io/blog/common-dask-mistakes/
使用 DaskExecutor 运行所有气流 ETL 任务
上面报告中的气流 DAG 示例从气流任务的中的启动盘绕簇。您还可以选择不同的架构,并在盘绕式集群上的 Airflow DAG 中运行所有任务。然后,您可以使用 Coiled 的自适应伸缩功能,根据工作负载来增减工作人员的数量。
为此,从使用气流的默认SequentialExecutor
切换到DaskExecutor
。使用除默认 SequentialExecutor 之外的任何 Airflow executor 还需要设置一个专用的数据库后端,Airflow 可以在那里存储与您的工作流相关的元数据。一旦完成,将DaskExecutor
指向一个已经运行的盘绕星团。
您可以通过在您的airflow.cfg
文件中进行以下更改来做到这一点,该文件默认存储在~/airflow/中。
- 设定
executor = DaskExecutor
- 设置
cluster_address = <cluster_IP_address/cluster_port>
。您可以使用cluster.scheduler_address
访问该地址 - 设置集群的 TLS 设置:
tls_cert
、tls_key
和tls_ca
。您可以使用client.security.tls_key
和client.security.tls_cert
来访问它们。注意tls_ca
的值与tls_cert
相同。
然后,您可以在 Coiled 上运行整个气流 DAG。
在启动盘绕式集群的脚本中包含一个cluster.adapt(minimum=1, maximum=20)
将确保集群根据工作负载在设定的最小和最大工作数量(在本例中为 1 到 20)之间自适应地伸缩。
取得联系
在这里关注我,在 Twitter 关注了解更多类似的内容。
原载于 2022 年 1 月 7 日https://coiled . io。
如何用简单的话构建 REST API
原文:https://towardsdatascience.com/how-to-build-rest-api-in-simple-words-2aa779749186
行业笔记
作为数据科学家使用 Flask 和 Docker 创建 REST API 的行动手册
我最近开发了一个名为 OWL 的上下文化的最相似单词 API 服务。OWL API 是使用 Flask 和 Docker 开发的高级 NLP 服务。该服务通过托管在 RapidAPI 市场上的一系列 REST APIs 与社区共享。这对我来说是一个伟大的旅程,所以我决定与你分享它发展的各个阶段。
本文描述了如何使用 Flask 和 Docker 构建 REST API 的分步指南。您可以在您的数据科学项目以及您正在开发的任何其他 web 应用程序中使用该指南。另外,这篇文章是“…用简单的话”系列的一部分,在这里我与你分享我的经验。这个系列之前帮助了很多数据科学爱好者。希望对你也有帮助。
如果您想阅读更多关于 OWL API 的内容,请查看下面的文章。
步骤 1 —创建 app.py
首先,您必须编写一个 Python 脚本,将 RESTful 端点映射到一个函数。我们给剧本取名app.py
。在这个例子中,RESTful 端点是/general/<N>/<WORD>
,其中general
是一个常量,N
和WORD
是两个变量。通过这些变量,用户可以将数据发送到 RESTful 端点的相应函数,即similar_words(N, WORD)
。在服务器上部署后,您在 Python 脚本中定义的 RESTful 端点将被添加到主机的 URL 中。
import os
import sys
from flask import Flask, jsonify, request
from flask_httpauth import HTTPBasicAuthimport gensim.downloader as api
sys.path += [os.getcwd()]
from src.core.word_clusterizer import WordClusterizer
from src.backend.wrapper import GensimWrapperauth = HTTPBasicAuth()
app = Flask(__name__)MODEL = api.load('glove-wiki-gigaword-300')**@app.route('/general/<N>/<WORD>', methods=['GET'])**
**def similar_words(N, WORD):** model = GensimWrapper(MODEL)
try:
wc = WordClusterizer(model=model, word=WORD, top_n=int(N)
wc.fit()
results = wc.result
except KeyError:
results = 'Nothing is found!'
**return jsonify(results)**if __name__ == '__main__':
port = os.environ.get("PORT", 8080)
**app.run(host='0.0.0.0', port=port, debug=True)**
不用说,RESTful 端点的相应功能是您的数据科学项目的核心。在这种情况下,它是一个单词相似性服务,与当前的解决方案相比,它以更大的粒度提取最相似的单词。
步骤 2 —创建 Dockerfile 文件
您需要一个 Docker 映像,在启动服务器时运行app.py
。要构建这样的 Docker 映像,您需要一个如下所示的 Docker 文件。
# MAINTAINER YOUR_NAMEFROM **pdrm83/nlp-essentials:latest**RUN pip install --upgrade pip
COPY . /project/
RUN pip install .**WORKDIR /project/src/.**
ENV PYTHONPATH /project
ENV PORT 8080**EXPOSE 8080**
EXPOSE 80**CMD ["python3", "app/app.py"]**
在 docker 文件中,您必须打开/暴露设置app.py
运行的端口。正如您在步骤 1 中看到的,我将app.py
脚本设置为在定义为port = os.environ.get("PORT", 8080)
的端口上运行。这一行意思是,从环境中把port
变量设置为PORT
的值,如果设置了,否则设置为 8080。
在这种情况下,PORT
没有预先设置。因此,我必须确保在 docker 文件中打开端口 8080。我通过 Dockerfile 文件中的EXPOSE 8080
做到了这一点。如果PORT
先前在环境中被设置为除 8080 之外的任何值,您必须通过添加EXPOSE XXXX
在 docker 文件中打开该端口。
注意,我在名为nlp-essentials
的 Docker 映像创建的环境中运行CMD ["python3", "app/app.py"]
。这是我之前通过安装所有需要的库构建的 Docker 映像。这张 Docker 图片保存在我的 Dockerhub 账户pdrm83
中,需要时使用。每当我想更新 API 服务时,就会拉出nlp-essentials
映像。这有助于在我每次想要更新 API 时不安装所有需要的库。最后,但同样重要的是,由于我将app.py
存储在ROOT/src/app/.
中,所以我将WORKDIR /project/src/.
添加到 Dockerfile 中。你不能复制这一行。你只需要根据你的代码库的文件结构在 Dockerfile 中正确地配置它。
步骤 3 —启动服务器
简而言之,您必须使用docker build -f <<DOCKERFILE_NAME>> -t <<IMAGE_NAME>>
构建 docker 映像,然后使用docker run -i -p 80:8080 <<IMAGE_ID>>
运行它。IMAGE_ID
是您在上一步中创建的 Docker 图像的 id。注意,我将端口 8080 映射到 80,因为app.py
在端口 8080 上运行,我想在端口 80 上为用户提供 API 服务。最后,您必须确保端口 80 在您使用的任何机器上都是开放的。
有很多方法可以让用户访问你的服务。不过,我想给你介绍一个名为 ngrok 的很酷的服务,它可以让你通过三个简单的步骤让你的电脑上网😮。这 3 个步骤简单如下:
- 下载
ngrok.zip
和unzip /path/to/ngrok.zip
。 - 运行
ngrok authtoken YOUR_OWN_TOKEN
- 运行
ngrok http 80
运行ngrok http 80
之后,ngrok 服务在ngrok.io
域上为您的项目创建一个专用的 URL,看起来像下面的链接。
[http://YOUR_DEDICATED_SUBDOMAIN.ngrok.io/](http://d9500fdc2530.ngrok.io/)
你的服务现在在互联网上对每个人都是可利用的。你不需要任何花哨的云服务就能把你的 API 服务推向市场。这不是很神奇吗?你可以在下面的文章中读到为什么我认为 ngrok 对你向社区提供 API 服务非常有用。
遗言
软件产品最值得推荐的架构之一是 API 架构。这个架构帮助你设计模块化和可重用服务,这些服务也易于维护。例如,有一些有效的解决方案来测试和记录一系列 REST APIs,帮助您轻松地维护它们。在本文中,我描述了如何为您的数据科学项目构建一个 RESTful API 。除了 RESTful 之外,还有其他类型的 API 协议,这不是本文的重点。
感谢阅读!
如果你喜欢这个帖子,想支持我…
https://pedram-ataee.medium.com/membership
如何建立成功的数据团队
原文:https://towardsdatascience.com/how-to-build-successful-data-teams-cd394e8c1d55
成为数据科学家的过程围绕着发展你的个人技能和知识库。然而,如果你聚集了一群敏锐的、高度熟练的数据专家,并期望顺畅的工作流程和直观的协作只是发生在和之间,你可能会不愉快地感到惊讶。建立一个团队需要工作——很多工作。
本周,我们选择了关于让数据团队茁壮成长的要素的最佳近期文章。我们挑选的一些关注集体框架,而另一些强调个人贡献者在更大的群体中蓬勃发展的必要技能。你可以根据你的团队目前面临的挑战来选择你自己的冒险,或者只是……全部阅读。它们值得你花时间。
- 把合适的人聚在一起 。如果没有计划,一群有经验、有技能的专业人士将不会变得比其各个部分的总和还要多。正如安吉丽卡·洛·杜卡所强调的,组建一个团队需要雇佣与他们的优势相匹配的人,在专家和多面手之间找到合适的平衡,并给个人分配他们可以真正发挥作用的任务和项目。
- 如何衡量成功 。KPI(关键绩效指标)已成为一种广泛使用的工具,用于衡量组织在实现共同目标方面的进展。 Barr Moses 认为,对于数据团队来说,定义和执行正确的 KPI 更加重要,有时甚至更加困难。她的文章就如何为数据团队创建有效的 KPI 提供了一些见解。
- 在不同数据类型之间移动的能力是必不可少的 。“归根结底,数据消费是数据团队的最终交付成果,”路易斯·维拉斯科说。他继续阐述了团队在构建其他利益相关者可以信任的数据架构时所面临的常见挑战,并介绍了多语言框架的概念,以解决数据网格范式的一些棘手问题。
- 数据团队的首要原则可能是什么? 亚当·斯罗卡关于成为一名高效数据科学家的四条规则是针对每个团队成员的个人执行标准的。然而,它们同样适用于团队层面,在其他关键思想中,对有用性的偏好强于复杂性,对简单性的偏好强于新颖性。
Heather McKean 在 Unsplash 上拍摄的照片
- 通过框定问题的正确方式增加价值 。我们可以接受没有愚蠢的问题,但这并不意味着所有的问题都是平等的。“如何做”和“做什么”有它们的位置,但是对于 Genevieve Hayes 博士来说,“如果你想最大化你作为数据科学家的价值,你需要开始问为什么。这不仅会对你自己的工作产生积极影响,也会对你公司的其他数据从业者产生积极影响。
- 如何以你内部客户的需求为中心 。每个数据团队都位于面向服务和面向产品之间。Maeda Hanafi 对最近一个项目的详细介绍——一个笨重的可视化调试工具的重新设计——展示了当团队创建产品来增强其他合作伙伴和利益相关者的能力时,他们是如何做到这两者的。
- 用你团队的工作讲述一个令人信服的故事。如果你的团队没有很好地与你的同事沟通,你所有的分析、见解和建议都不会产生最大的影响——特别是如果他们没有你那么懂数据的话。为了提高你的演示技巧,我们提供了两份精彩的阅读材料:布莱恩·罗普克的 创造精彩演示的八个技巧 和艾瑞克·伯格博士的 数据专业人士必备的五个演示技巧 。(这总共是 13 个有用的提示,供你们这些记分员参考。)
想再找几本其他题材的阅读推荐?乐意效劳:
- 我们刚刚推出了新的作家研讨会系列,其中有一个关于为您的数据科学、ML 或其他技术文章寻找读者的全面指南。我们客观吗?不。真的真的很好吗?是的。
- 如果你错过了,我们最近与医疗保健数据分析师 Rashi Desai 聊了聊在你选择的数据职业道路上找到成功。
- 如果你想让你的 Matplotlib 技能更上一层楼,这里有一个由 Bex T. 编写的高级教程
- 数据可视化中的包容性设计会有所不同——这里是 Leonie Monigatti 关于创建色盲友好图表和绘图的实践入门。
如果你想支持我们作者的工作,考虑成为一个媒体成员;它也使整个 TDS 档案(以及其他付费媒体文章)对你开放。
直到下一个变量,
TDS 编辑
如何使用 Keras 函数式 API 构建张量流模型
使用 Keras Functional API 构建定制模型的示例和代码
Keras Functional API 提供了一种在 TensorFlow 中构建灵活复杂的神经网络的方法。功能 API 用于设计非线性网络。在本文中,您将发现 Keras Functional API 用于创建网络:
- 是非线性的。
- 共享图层。
- 有多个输入和输出。
Keras 序列模型
我们使用了 CNN 教程中的 Sequential API,用 Keras 和 TensorFlow 建立了一个图像分类模型。顺序 API 包括堆叠层。一层接着一层,直到最后的致密层。这使得用顺序 API 设计网络变得简单明了。
parameters = {"shape":28, "activation": "relu", "classes": 10, "units":12, "optimizer":"adam", "epochs":1,"kernel_size":3,"pool_size":2, "dropout":0.5}
# Setup the layers
model = keras.Sequential(
[
layers.Conv2D(32, kernel_size=(parameters["kernel_size"], parameters["kernel_size"]), input_shape =(parameters["shape"], parameters["shape"], 1),activation=parameters["activation"]),
layers.MaxPooling2D(pool_size=(parameters["pool_size"], parameters["pool_size"])),
layers.Conv2D(64, kernel_size=(parameters["kernel_size"], parameters["kernel_size"]), activation=parameters["activation"]),
layers.MaxPooling2D(pool_size=(parameters["pool_size"], parameters["pool_size"])),
layers.Flatten(),
layers.Dropout(parameters["dropout"]),
layers.Dense(parameters["classes"], activation="softmax"),
]
)
顺序 API 将您限制为一个输入和一个输出。但是,在某些情况下,您可能希望设计具有多个输入和输出的神经网络。例如,给定一个人的图像,您可以设计一个网络来预测几个属性,如性别、年龄和头发颜色。这是一个单输入多输出的网络。为此,需要顺序 API 。绘制网络图显示各层以线性方式排列。
keras.utils.plot_model(model, "model.png",show_shapes=True)
作者图片
Keras 功能模型
设计功能模型与开发顺序模型略有不同。让我们来看看这些不同之处。
定义输入
第一个区别是创建输入层的要求。使用顺序 API,您不必定义输入层。在第一层定义输入形状就足够了。
输入层包含要传递给网络的数据的形状和类型。
inputs = keras.Input(shape=(parameters["shape"], parameters["shape"], 1))
inputs.shape
# TensorShape([None, 28, 28, 1])
inputs.dtype
# tf.float32
如果数据是一维的,则定义输入图层时不考虑批次大小。
inputs = keras.Input(shape=(784,))
连接层
下一个区别是如何使用函数式 API 连接各层。为了创建连接,我们创建另一个层并将inputs
层传递给它。将每一层都视为一种功能,可以更好地理解这一点。由于这些层是函数,它们可以用参数调用。例如,让我们将inputs
传递给一个Conv2D
层。
conv2D = layers.Conv2D(32)
x = conv2D(inputs)
x
# <KerasTensor: shape=(None, 26, 26, 32) dtype=float32 (created by layer 'conv2d_7')>
在上面的例子中,我们创建了一个Conv2D
层,作为一个函数调用它并传递输入。作为传递到卷积层的结果,结果输出的形状不同于初始的inputs
形状。
函数式 API Python 语法
上面的例子显示了如何定义和连接网络。但是,语法可以简化。简化版看起来像这样:
conv2D = Conv2d(...) (inputs)
conv2D()
类似于conv2D.__call__(self,....)
。Python 对象实现了__call__()
方法。Keras 层也实现这个方法。该方法返回给定输入张量的输出。
inputs = keras.Input(shape=(parameters["shape"], parameters["shape"], 1))
conv2D = layers.Conv2D(32, kernel_size=(parameters["kernel_size"], parameters["kernel_size"]), input_shape =(parameters["shape"], parameters["shape"], 1),activation=parameters["activation"])(inputs)
conv2D
# <KerasTensor: shape=(None, 26, 26, 32) dtype=float32 (created by layer 'conv2d_8')>
创建模型
让我们向网络中添加几个层,以演示如何在使用 Functional API 定义层时创建 Keras 模型。
parameters = {"shape":28, "activation": "relu", "classes": 10, "units":12, "optimizer":"adam", "epochs":1,"kernel_size":3,"pool_size":2, "dropout":0.5}
inputs = keras.Input(shape=(parameters["shape"], parameters["shape"], 1))
conv2D = layers.Conv2D(32, kernel_size=(parameters["kernel_size"], parameters["kernel_size"]), input_shape =(parameters["shape"], parameters["shape"], 1),activation=parameters["activation"])(inputs)
maxPooling2D = layers.MaxPooling2D(pool_size=(parameters["pool_size"], parameters["pool_size"]))(conv2D)
conv2D_2 =layers.Conv2D(64, kernel_size=(parameters["kernel_size"], parameters["kernel_size"]), activation=parameters["activation"])(maxPooling2D)
maxPooling2D_2 = layers.MaxPooling2D(pool_size=(parameters["pool_size"], parameters["pool_size"]))(conv2D_2)
flatten = layers.Flatten()(maxPooling2D_2)
dropout = layers.Dropout(parameters["dropout"])(flatten)
ouputs = layers.Dense(parameters["classes"], activation="softmax")(dropout)
当传递inputs
和outputs
时,使用**keras.Model**
函数创建一个 Keras 模型。
model = keras.Model(inputs=inputs, outputs=outputs, name="mnist_model")
我们可以绘制模型来确认它与我们使用顺序 API 定义的模型相似。
keras.utils.plot_model(model, "model.png",show_shapes=True)
作者图片
功能 API 模型的训练和评估
在功能 API 和顺序 API 中,训练和评估模型是相同的。keras.Model
利用fit
和evaluate
方法。
(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()
x_train = x_train.astype("float32") / 255
x_test = x_test.astype("float32") / 255
model.compile(
loss=keras.losses.SparseCategoricalCrossentropy(from_logits=True),
optimizer=keras.optimizers.RMSprop(),
metrics=["accuracy"],
)
history = model.fit(x_train, y_train, batch_size=64, epochs=2, validation_split=0.2)
test_scores = model.evaluate(x_test, y_test, verbose=2)
print("Test loss:", test_scores[0])
print("Test accuracy:", test_scores[1])
作者图片
保存和序列化功能 API 模型
模型保存和序列化在函数式 API 和顺序式 API 中工作相同。例如,我们可以使用model.save()
保存整个模型。
model.save("saved_model")
del model
model = keras.models.load_model("saved_model")
model.summary()
作者图片
如何将功能模型转换为顺序 API 模型
通过创建一个Sequential
实例并添加层,可将带有线性层的功能模型转换为顺序模型。
seq_model = keras.models.Sequential()
for layer in model.layers:
seq_model.add(layer)
seq_model.summary()
作者图片
如何将顺序模型转换为功能 API 模型
类似地,我们可以将时序网络转换为功能模型。
inputs = keras.Input(batch_shape=seq_model.layers[0].input_shape)
x = inputs
for layer in seq_model.layers:
x = layer(x)
outputs = x
func_model = keras.Model(inputs=inputs, outputs=outputs, name="func_mnist_model")
func_model.summary()
作者图片
标准网络模型
让我们看看如何使用功能性 Keras API 定义标准神经网络。
多层感知
我们首先定义一个具有多个隐藏层的神经网络,并绘制模型。
inputs = keras.Input(shape=(parameters["shape"], parameters["shape"], 1))
dense1 = layers.Dense(128)(inputs)
dropout = layers.Dropout(parameters["dropout"])(dense1)
dense2 = layers.Dense(128)(dropout)
dropout1 = layers.Dropout(parameters["dropout"])(dense2)
outputs = layers.Dense(parameters["classes"], activation="softmax")(dropout1)
model = keras.Model(inputs=inputs, outputs=outputs, name="mnist_model")
keras.utils.plot_model(model, "model.png",show_shapes=True)
作者图片
卷积神经网络
接下来,我们看看如何使用函数式 API 定义卷积神经网络。该网络具有卷积层、汇集层、扁平化层和致密层。
inputs = keras.Input(shape=(parameters["shape"], parameters["shape"], 1))
conv2D = layers.Conv2D(32, kernel_size=(parameters["kernel_size"], parameters["kernel_size"]), input_shape =(parameters["shape"], parameters["shape"], 1),activation=parameters["activation"])(inputs)
maxPooling2D = layers.MaxPooling2D(pool_size=(parameters["pool_size"], parameters["pool_size"]))(conv2D)
conv2D_2 =layers.Conv2D(64, kernel_size=(parameters["kernel_size"], parameters["kernel_size"]), activation=parameters["activation"])(maxPooling2D)
maxPooling2D_2 = layers.MaxPooling2D(pool_size=(parameters["pool_size"], parameters["pool_size"]))(conv2D_2)
flatten = layers.Flatten()(maxPooling2D_2)
dropout = layers.Dropout(parameters["dropout"])(flatten)
outputs = layers.Dense(parameters["classes"], activation="softmax")(dropout)
model = keras.Model(inputs=inputs, outputs=outputs, name="mnist_model")
keras.utils.plot_model(model, "model.png",show_shapes=True)
作者图片
递归神经网络
让我们看看使用函数式 API 的双向 LSTM 的定义。该网络包含一个嵌入层。
inputs = keras.Input(784,)
embedding = layers.Embedding(512, 64, input_length=1024)(inputs)
bidirectional1 = layers.Bidirectional(layers.LSTM(64, return_sequences=True))(embedding)
bidirectional2 = layers.Bidirectional(layers.LSTM(64,))(bidirectional1)
dense1 = layers.Dense(32, activation='relu')(bidirectional2)
outputs = layers.Dense(1, activation='sigmoid')(dense1)
model = keras.Model(inputs=inputs, outputs=outputs, name="lstm_model")
keras.utils.plot_model(model, "model.png",show_shapes=True)
作者图片
共享层模型
使用功能 API 定义层可以创建共享特定层的网络。网络中会多次使用共享层。
共享输入层
本例定义了一个 CNN,两个卷积模块共享一个输入层。然后我们使用concatenate
层连接这些模块的输出。之后,我们将结果传递给一个DropOut
层,最后传递给完全连接的层。
inputs = keras.Input(shape=(parameters["shape"], parameters["shape"], 1))
conv2D = layers.Conv2D(32, kernel_size=(parameters["kernel_size"], parameters["kernel_size"]), input_shape =(parameters["shape"], parameters["shape"], 1),activation=parameters["activation"])(inputs)
maxPooling2D = layers.MaxPooling2D(pool_size=(parameters["pool_size"], parameters["pool_size"]))(conv2D)
flatten1 = layers.Flatten()(maxPooling2D)
conv2D_2 = layers.Conv2D(64, kernel_size=(parameters["kernel_size"], parameters["kernel_size"]), activation=parameters["activation"])(inputs)
maxPooling2D_2 = layers.MaxPooling2D(pool_size=(parameters["pool_size"], parameters["pool_size"]))(conv2D_2)
flatten2 = layers.Flatten()(maxPooling2D_2)
# merge layers
merged_layers = layers.concatenate([flatten1, flatten2])
dropout = layers.Dropout(parameters["dropout"])(merged_layers)
outputs = layers.Dense(parameters["classes"], activation="softmax")(dropout)
model = keras.Model(inputs=inputs, outputs=outputs, name="mnist_model")
keras.utils.plot_model(model, "model.png",show_shapes=True)
绘制网络图显示了不同层之间的联系。
作者图片
共享特征提取层
在本例中,我们创建了一个由两个双向 LSTMs 共享的嵌入层。共享特征提取层允许在网络中多次共享相同的特征提取器。例如,在两个输入之间共享此信息可以使用较少的数据训练网络成为可能。
inputs = keras.Input(784,)
embedding = layers.Embedding(512, 64, input_length=1024)(inputs)
bidirectional1 = layers.Bidirectional(layers.LSTM(64, return_sequences=True))(embedding)
bidirectional2 = layers.Bidirectional(layers.LSTM(64, return_sequences=True))(embedding)
# merge layers
merged_layers = layers.concatenate([bidirectional1, bidirectional2])
dense1 = layers.Dense(32, activation='relu')(merged_layers)
outputs = layers.Dense(1, activation='sigmoid')(dense1)
model = keras.Model(inputs=inputs, outputs=outputs, name="lstm_model")
keras.utils.plot_model(model, "model.png",show_shapes=True)
作者图片
接下来,让我们讨论多输入多输出场景。
多输入多输出模型
具有多个输入和输出的网络也可以使用函数式 API 来定义。这对于顺序 API 是不可能的。
多输入模型
在本例中,我们定义了一个网络,它采用两个不同长度的输入。我们将输入传递给密集层,并使用add
层对它们求和。
input1 = keras.Input(shape=(16,))
x1 =layers.Dense(8, activation='relu')(input1)
input2 = layers.Input(shape=(32,))
x2 = layers.Dense(8, activation='relu')(input2)
# equivalent to `added = tf.keras.layers.add([x1, x2])`
added = layers.Add()([x1, x2])
out = layers.Dense(4)(added)
model = keras.Model(inputs=[input1, input2], outputs=out)
keras.utils.plot_model(model, "model.png",show_shapes=True)
作者图片
多输出模型
功能 API 支持定义具有多输出的模型。下面的例子定义了一个具有两个输出层的卷积神经网络。例如,给定一个人的图像,这个网络可以预测性别和头发颜色。
image_input = keras.Input(shape=(parameters["shape"], parameters["shape"], 3), name="images")
x = layers.Conv2D(filters=32,kernel_size=(3,3),activation='relu')(image_input)
x = layers.MaxPooling2D(pool_size=(2,2))(x)
x = layers.Conv2D(filters=32,kernel_size=(3,3), activation='relu')(x)
x = layers.Dropout(0.25)(x)
x = layers.Conv2D(filters=64,kernel_size=(3,3), activation='relu')(x)
x = layers.MaxPooling2D(pool_size=(2,2))(x)
x = layers.Dropout(0.25)(x)
x = layers.Flatten()(x)
x = layers.Dense(128, activation='relu')(x)
x = layers.Dropout(0.25)(x)
gender_prediction = layers.Dense(3, activation='softmax')(x)
age_prediction = layers.Dense(3, activation='softmax')(x)
model = keras.Model(
inputs=image_input,
outputs=[gender_prediction, age_prediction],
)
keras.utils.plot_model(model, "model.png",show_shapes=True)
作者图片
使用相同的图层图表来定义多个模型
Functional API 还支持使用相同的层定义多个模型。这是可能的,因为使用函数式 API 创建模型只需要输入和输出。例如,这适用于编码解码器网络架构。
encoder_input = keras.Input(shape=(28, 28, 1), name="img")
x = layers.Conv2D(16, 3, activation="relu")(encoder_input)
x = layers.Conv2D(32, 3, activation="relu")(x)
x = layers.MaxPooling2D(3)(x)
x = layers.Conv2D(32, 3, activation="relu")(x)
x = layers.Conv2D(16, 3, activation="relu")(x)
encoder_output = layers.GlobalMaxPooling2D()(x)
encoder = keras.Model(encoder_input, encoder_output, name="encoder")
encoder.summary()
x = layers.Reshape((4, 4, 1))(encoder_output)
x = layers.Conv2DTranspose(16, 3, activation="relu")(x)
x = layers.Conv2DTranspose(32, 3, activation="relu")(x)
x = layers.UpSampling2D(3)(x)
x = layers.Conv2DTranspose(16, 3, activation="relu")(x)
decoder_output = layers.Conv2DTranspose(1, 3, activation="relu")(x)
autoencoder = keras.Model(encoder_input, decoder_output, name="autoencoder")
autoencoder.summary()
Keras 功能 API 的优势和劣势
Keras Functional API 在设计非线性网络时非常方便。如果您认为您可能需要将网络转换为非线性结构,那么您应该使用函数式 API。函数式 API 的一些优势包括:
- 与子类化
[Model](https://www.tensorflow.org/guide/keras/custom_layers_and_models)
的相比,它的更少冗长。 - 创建一个
Input
的要求确保了所有的功能网络都将运行,因为传递错误的形状会导致立即出错。 - 功能模型更容易绘制和检查。
- 易于序列化和保存功能模型,因为它们是数据结构。
然而,使用函数式 API 的一个缺点是它不支持动态架构,如递归网络或树形网络。
功能 API 最佳实践
在使用 Keras Functional API 时,请牢记最佳实践:
- 始终打印网络概要给以确认各层的形状符合预期。
- 将网络绘制到确保各层按照你的预期连接。
- 命名图层以便于在网络图和概要中识别。比如说
Conv2D(...,name="first_conv_layer")
。 - 使用与层相关的变量名,例如
conv1
和conv2
用于卷积层。这将在检查地块和网络摘要时阐明图层的类型。 - 没有创建自定义训练循环,而是使用
**keras.Model**
来创建模型,因为这样更容易通过fit
方法训练模型,并使用evalaute
方法评估它们。
最后的想法
在本文中,您发现可以使用顺序 API 在 Keras 中设计神经网络。特别是,我们涵盖了:
- 如何在 Keras 中定义功能模型?
- 如何训练和评估 Keras 序列网络?
- 定义具有多个输入和输出的 Keras 网络。
- 如何绘制和检验 Keras 序列模型?
- 基于 Keras 序列网络的特征提取。
在 LinkedIn 上关注我获取更多技术资源。
如何建立自己的 GPT J 游乐场
原文:https://towardsdatascience.com/how-to-build-your-own-gpt-j-playground-733f4f1246e5
利用 Streamlit、拥抱脸和 AWS 创建您自己的文本生成应用程序
蒂埃里·勒迈特在 Unsplash 上的照片
这是怎么回事?
当 OpenAI 为其 GPT-3 模型发布游乐场时,社区很快创建了各种令人印象深刻的演示,其中许多可以在棒极了的 GPT-3 Github repo 中找到。
但是如果我们想创建我们自己的文本生成平台呢?GPT-3 是专有的,使用 API 来生成文本会让我们付出代价。这也意味着我们必须将我们的数据发送到 OpenAI。理想情况下,我们想做的是在我们控制的环境中托管一个开源文本生成模型和一个游乐场应用程序。
看起来我们很幸运。2021 年, Eleuther AI 创造了 GPT-J,一个开源的文本生成模型,与 GPT-3 竞争。当然,该模型在 Hugging Face (HF)模型中心上可用,这意味着我们可以利用亚马逊 SageMaker 中的 HF 集成来轻松部署该模型。为了创建一个与模型交互的 web 界面,我们可以使用 Streamlit ,它允许我们只使用 Python 就能编写 web 应用程序:)
那我们开始吧!教程的完整代码可以在这个 Github repo 中找到。
部署 GPT J 模型
拥抱脸的人已经让在亚马逊 SageMaker 上部署像 GPT-J 这样的 6B 参数模型变得非常容易,几乎没有任何不便。来自 HF 团队的 Philipp Schmid 在他的博客文章中概述了这个过程——所有需要的就是 24 行代码:
在 SageMaker 上部署 GPT-J 的代码(信用:https://www.philschmid.de/deploy-gptj-sagemaker
一旦我们在 SM 笔记本中运行此代码,将需要几分钟时间来部署端点。终端准备就绪时,SM 控制台会告诉我们:
作者图片
创建 web 界面
设置 EC2
一旦模型部署在 SageMaker 端点上,我们就可以在笔记本上运行推理请求。但是为什么就此打住呢?借助 Streamlit 的力量,我们可以轻松创建自己的 GPT J 游乐场!
我们需要的只是一台服务器,我们可以在其中托管 Streamlit 应用程序并访问 SM 端点。如果我们选择在与端点相同的帐户中的 EC2 实例上这样做,我们可以通过 SM 提供的 API 访问端点:
作者图片
我们需要做的只是提供一个小型 EC2 实例,例如 t3.medium,因为它将只托管 web 应用程序。一旦实例启动并运行,我们就安装 miniconda 并通过 pip install 安装所需的库:
为了连接到我们的端点,我们还需要将我们的凭证从 EC2 传递到 SageMaker。有很多方法可以做到这一点,更多信息请查看 AWS 文档。在本教程中,我将使用一个共享凭证文件。
创建简化应用程序
现在我们可以开发我们的 Streamlit 应用程序,这非常简单。让我们首先定义一个方法来处理模型有效负载和响应的预处理和后处理:
现在我们需要一个文本字段,我们可以在其中输入提示,调用我们的 generate_text() 方法,并显示模型响应:
就是这样!非常简单,不是吗?
测试应用程序
让我们测试一下这个设置!我们可以使用streamlit run
我们将看到一个文本框,我们可以在那里输入我们的提示和一个运行按钮,将调用我们的 GPT-J 模型。让我们在文本框中输入一个提示,然后运行模型。几秒钟后,它应该返回生成的文本:
作者图片
就这样——我们刚刚在自己的 playground 应用程序中用 GPT-J 模型生成了第一个文本!
结论
有许多方法可以改善这个游乐场,其中一些是:
- 新生成的文本可以用作模型的新提示。这将使我们能够继续就同一主题编写文本。
- 防止模型在句子中间停止。
- 引入参数来影响生成的文本,例如温度和最高温度。你可以在这篇博文的中找到更多关于这些参数和文本生成的信息。
我希望你觉得这个教程有用,如果你有任何问题或意见,请联系我们。
【2022 年 5 月 11 日编辑:我现在已经发表了一篇 的博文 讲述了如何使用这个 GPT-J 游乐场的应用来完成(几乎)任何 NLP 任务。】
如何使用 SQL 计算 BigQuery 中的百分比
比较一行对所有行总和的贡献
为什么要用总数的百分比?
假设你有一个销售咖啡的电子商务网站,你有三种不同类别的产品:阿拉比卡、罗布斯塔和利百丽卡。
在一份报告上,你看到 2022 年 6 月,你卖出了阿拉比卡的34.5 万€,罗布斯塔的11.2 万€,利百丽卡的13 万€。从绝对值来看,你会注意到阿拉比卡咖啡是你最大的收入来源,但从百分比来看,它代表了你本月销售额的 73%** 。**
这个想法是看一行对所有行的总和的贡献
为了避免通过将一个值除以所有值的总和来手动计算该百分比,我们将学习如何使用 SQL 来帮助我们,并帮助回答以下问题:
- 什么产品对我们公司的收入贡献最大?
- 随着时间的推移,我们国家的市场份额如何演变?
在本文中,我们的数据来自于谷歌商品电子商务网站。对于我们的分析,我们的表包含销售的产品、产品名称和类别以及产生的收入。
我们的基本数据表。(图片由作者提供)
产品类别对总收入的贡献
对于我们的第一个业务问题,我们想知道每个产品类别对我们总收入的贡献有多大。
首先,我们需要计算每个产品类别的总收入。
我们计算每个产品类别的总收入。
因此,我们得到一个表,每个产品类别和产生的收入各占一行。
每个产品类别的总收入。(图片由作者
我们的网店总共有 21 个类目,如果做营收之和(revenue_per_category
字段之和),得到174 万(也就是我们的网店总营收)。
现在,要获得总收入的百分比,我们需要将每个类别的收入除以总收入。
为了实现这一点,不使用JOIN
子句,您可以使用OVER()
子句。让我们深入细节:
在顶部的WITH
子句中,我们有一个计算每个类别收入的第一个查询。在我们的主语句中,在*
之后有两行:
- 第一行计算总收入(您实际上并不需要它,它只是为了突出语法并展示如何使用窗口函数)
- 第二行计算每个类别的收入份额。
你可以注意到我们使用了一个SAFE_DIVIDE
函数,以防我们除以 0(意味着我们的总收入为 0)。该函数将返回收入份额的NULL
值,而不是抛出“除以 0”错误。
每个类别的收入份额。(图片由作者提供)
这就是你如何在 Data Studio 中用饼状图绘制它:
每个产品类别占我们总收入的份额。(图片由作者提供)
服装类别是贡献最大的类别,与其他和办公室并列。
我们可以看到,我们有两个不同的类别其他和其他。
- 其他是我们数据中标注为“其他”的类别。
- 其他是因为 Data studio 在数据点过多的时候会截断结果。这里我们只显示 10 个切片,但是我们有 21 个类别。通过这样做,Data Studio 将所有剩余的类别组合成一个名为 others 的类别。
一段时间内产品类别对收入的贡献
对于我们的第二个业务问题,我们想知道我们的产品类别的收入份额是如何随着时间变化的。
为此,我们将计算每个产品类别每月的收入,然后计算该月每个产品类别占总收入的百分比。
首先,我们需要计算每个类别在一段时间内的总收入(在我们的例子中是每个月)。我们每月增加第二个GROUP BY
。
因此,每个月每个产品类别和产生的收入各占一行。
我们每个类别的每月总收入。(图片由作者提供)
为了查看随时间的变化,我们不查看 21 个类别,而是放大第一个业务问题中看到的前 4 个类别:服装、其他、办公用品和饮料。
您可以注意到,我们创建了一个子查询,它封装了我们的ratio
字段,在我们计算出每月总数的百分比后,过滤所需的类别。如果我们之前进行了筛选,总收入将只代表这四个类别。
我们在这个查询中的窗口函数与本文前一部分中使用的非常相似,除了我们的OVER()
子句现在将每个月划分为分区。
这导致了以下结果:
几个月来我们前四大类别总收入的百分比。(图片由作者提供)
我们可以观察到 Other 类别肯定是跟踪错误或被贴错标签,因为它不会在一个月内返回,并且是 2016 年 8 月至 9 月期间唯一出现的类别。
随着时间的推移,我们确实看到这三个类别占我们商店收入的 60%,而在 2017 年 1 月,“办公室”类别的贡献超过了以往。
结论
如果我们在 SQL 中学习这种方法,它可以节省手动计算的时间,并且能够为许多类别/维度扩展这种计算。
这也是因为并不是所有的数据仓库系统都提供了一种有效的方法来计算一个比率或总份额。BigQuery 的情况并非如此。
其他系统,如亚马逊红移或雪花有一个名为ratio_to_report()
的窗口函数,它计算我们在本文中看到的内容。数据可视化系统,如 Tableau 或 QlikSense,也使计算总百分比变得更加容易。
感谢您的阅读;我希望这篇文章给了你计算和理解它背后的方法的关键。
MySQL 中如何用分组计算中位数
原文:https://towardsdatascience.com/how-to-calculate-medians-with-grouping-in-mysql-abb22a3e5097
学习高级 MySQL 查询来计算不同场合的中位数
在任何编程语言中,计算一组数据的中值都非常简单,即使在 Excel 中,也可以直接使用内置或第三方中值函数。但是,在 MySQL 中,median 函数不是原生支持的。为了得到中间值,我们需要编写一些带有子查询的智能查询。
在本帖中,我们将揭开 MySQL 中计算中位数的查询的神秘面纱。特别是,我们将演示如何计算分组字段的中位数。如果一个列有多个类别,这些类别的中位数应该单独计算,那么逐个计算每个类别的中位数就变得很麻烦。在这篇文章中,你可以通过一个简单的查询来计算所有类别的中位数。此外,您还将学习如何同时计算多个列的中位数。
准备
首先,我们需要一个 MySQL 服务器,创建一个数据库和表,并插入一些虚拟数据进行处理。我们将使用 Docker 在本地启动一个 MySQL 8 服务器:
# Create a volume to persist the data.
$ docker volume create mysql8-data
# Create the container for MySQL.
$ docker run --name mysql8 -d -e MYSQL_ROOT_PASSWORD=root -p 13306:3306 -v mysql8-data:/var/lib/mysql mysql:8
# Connect to the local MySQL server in Docker.
$ docker exec -it mysql8 mysql -u root -proot
mysql> SELECT VERSION();
+-----------+
| VERSION() |
+-----------+
| 8.0.31 |
+-----------+
1 row in set (0.00 sec)
要编写复杂的 SQL 查询,建议使用 IDE 而不是控制台。IDE 的好处是代码完成、代码格式化、语法突出显示等。在本文中,我们将使用 DBeaver ,这是一个通用的数据库管理工具,可用于管理各种关系数据库和 NoSQL 数据库。然而,任何 IDE 都可以工作。您甚至可以复制本文中演示的查询,并直接在 MySQL 控制台中运行它们。
对于 DBeaver,如果遇到“不允许检索公钥”错误,应该编辑连接并为驱动程序添加以下两个用户属性:
# User properties
useSSL: false
allowPublicKeyRetrieval: true
更多 DBeaver 的设置,请查看本帖。
然后运行以下查询来创建数据库、创建表并插入一些虚拟数据:
CREATE DATABASE products;
CREATE TABLE `products`.`prices` (
`pid` int(11) NOT NULL AUTO_INCREMENT,
`category` varchar(100) NOT NULL,
`price` float NOT NULL,
PRIMARY KEY (`pid`)
);
INSERT INTO products.prices
(pid, category, price)
VALUES
(1, 'A', 2),
(2, 'A', 1),
(3, 'A', 5),
(4, 'A', 4),
(5, 'A', 3),
(6, 'B', 6),
(7, 'B', 4),
(8, 'B', 3),
(9, 'B', 5),
(10, 'B', 2),
(11, 'B', 1)
;
以“经典”方式计算中位数
既然数据库和数据已经设置好了,我们可以开始计算中位数了。传统的解决方案是使用 SQL 变量:
SELECT AVG(sub.price) AS median
FROM (
SELECT @row_index := @row_index + 1 AS row_index, p.price
FROM products.prices p, (SELECT @row_index := -1) r
WHERE p.category = 'A'
ORDER BY p.price
) AS sub
WHERE sub.row_index IN (FLOOR(@row_index / 2), CEIL(@row_index / 2))
;
median|
------+
3.0|
此查询的要点:
@row_index
是一个 SQL 变量,在FROM
语句中初始化,并在SELECT
语句中为每一行更新。- 应该对将要计算中值的列(本例中的
price
列)进行排序。不管是升序还是降序排序都没关系。 - 根据对中位数的定义,中位数是中间元素的值(总计数为奇数)或两个中间元素的平均值(总计数为偶数)。在本例中,类别 A 有 5 行,因此中位数是排序后第三行的值。
FLOOR(@row_index / 2)
和CEIL(@row_index / 2)
的值都是 2,这是第三行。另一方面,对于具有 6 行的类别 B,中值是第三和第四行的平均值。
这个解决方案简单易懂。但是,如果表有许多类别,我们需要为每个类别运行查询,这很麻烦,并且结果不容易存储和比较。
为了解决这个问题,我们需要一个使用GROUP BY
、GROUP_CONCAT
和 SUBSTRING_INDEX
的非经典解决方案。
灵活计算中位数
让我们一步一步来。最终的查询乍看起来可能很复杂。然而,一旦你知道它是如何工作的,它实际上更容易理解,你可以根据自己的用例自由地改变它。
让我们首先获得每个类别的所有排序价格:
SELECT
category,
GROUP_CONCAT(price ORDER BY p.price) AS prices,
COUNT(*) AS total
FROM products.prices p
GROUP BY p.category
;
category|prices |total|
--------+-----------+-----+
A |1,2,3,4,5 | 5|
B |1,2,3,4,5,6| 6|
注意,如果你的表有很多数据,GROUP_CONCAT
不会包含所有的数据。在这种情况下,通过以下方式增加GROUP_CONCAT
的限值:
SET GROUP_CONCAT_MAX_LEN = 100000;
您可以将限制设置为适合您的用例的数字。但是,如果您的表包含太多数据,您可能会遇到内存问题。在这种情况下,您需要编写一些脚本,以更智能的方式执行数据处理和计算。尽管如此,本文中提供的解决方案适用于大多数中小型表。
然后,让我们获得每个类别的中间元素,我们需要检查总计数是奇数还是偶数,并相应地处理它:
SELECT
sub1.category,
sub1.total,
CASE WHEN MOD(sub1.total, 2) = 1 THEN SUBSTRING_INDEX(SUBSTRING_INDEX(sub1.prices, ',', CEIL(sub1.total/2)), ',', '-1')
WHEN MOD(sub1.total, 2) = 0 THEN SUBSTRING_INDEX(SUBSTRING_INDEX(sub1.prices, ',', sub1.total/2 + 1), ',', '-2')
END AS mid_prices
FROM
(
SELECT
p.category,
GROUP_CONCAT(p.price ORDER BY p.price) AS prices,
COUNT(*) AS total
FROM products.prices p
GROUP BY p.category
) sub1
;
category|total|mid_prices|
--------+-----+----------+
A | 5|3 |
B | 6|3,4 |
我们使用MOD
函数来检查总数是奇数还是偶数。使用了两次SUBSTRING_INDEX
函数来提取中间元素。让我们更详细地演示一下它是如何工作的:
-- Categoy A, 5 rows:
SUBSTRING_INDEX('1,2,3,4,5', ',', CEIL(5/2)) => '1,2,3'
SUBSTRING_INDEX('1,2,3', ',', -1) => 3
-- Categoy B, 6 rows:
SUBSTRING_INDEX('1,2,3,4,5,6', ',', 6/2 + 1) => '1,2,3,4'
SUBSTRING_INDEX('1,2,3,4', ',', -2) => '3,4'
最后,让我们计算中间元素的平均值,以获得每个类别的中值:
SELECT
sub2.category,
CASE WHEN MOD(sub2.total, 2) = 1 THEN sub2.mid_prices
WHEN MOD(sub2.total, 2) = 0 THEN (SUBSTRING_INDEX(sub2.mid_prices, ',', 1) + SUBSTRING_INDEX(sub2.mid_prices, ',', -1)) / 2
END AS median
FROM
(
SELECT
sub1.category,
sub1.total,
CASE WHEN MOD(sub1.total, 2) = 1 THEN SUBSTRING_INDEX(SUBSTRING_INDEX(sub1.prices, ',', CEIL(sub1.total/2)), ',', '-1')
WHEN MOD(sub1.total, 2) = 0 THEN SUBSTRING_INDEX(SUBSTRING_INDEX(sub1.prices, ',', sub1.total/2 + 1), ',', '-2')
END AS mid_prices
FROM
(
SELECT
p.category,
GROUP_CONCAT(p.price ORDER BY p.price) AS prices,
COUNT(*) AS total
FROM products.prices p
GROUP BY p.category
) sub1
) sub2
;
category|median|
--------+------+
A |3 |
B |3.5 |
干杯!两个类别的中值计算正确。这比传统的解决方案要多一点代码。然而,它更透明,因此更容易理解。此外,它更加灵活,您可以针对不同的用例轻松调整查询,而不仅仅是使用分组来获得不同类别的中值。
奖金-计算多列的中间值
在中间值以上,只计算一列。有了新的解决方案,我们可以很容易地计算多个列的中位数。让我们首先用一些虚拟数据创建一个新表:
CREATE TABLE `products`.`orders` (
`order_id` int(11) NOT NULL AUTO_INCREMENT,
`price` float NOT NULL,
`quantity` float NOT NULL,
PRIMARY KEY (`order_id`)
);
INSERT INTO products.orders
(order_id, price, quantity)
VALUES
(1, 2, 50),
(2, 1, 40),
(3, 5, 10),
(4, 3, 30),
(5, 4, 20)
;
请注意,这些数据是假的,只是为了演示,因此越简单越好。
用于计算多个列的中间值的查询可以很容易地从上面的查询修改而来。不同之处在于,我们不再需要按类别分组,而是需要对需要计算中值的每一列重复查询:
SELECT
CASE WHEN MOD(sub2.total, 2) = 1 THEN sub2.mid_prices
WHEN MOD(sub2.total, 2) = 0 THEN (SUBSTRING_INDEX(sub2.mid_prices, ',', 1) + SUBSTRING_INDEX(sub2.mid_prices, ',', -1)) / 2
END AS median_of_price,
CASE WHEN MOD(sub2.total, 2) = 1 THEN sub2.mid_quantities
WHEN MOD(sub2.total, 2) = 0 THEN (SUBSTRING_INDEX(sub2.mid_quantities, ',', 1) + SUBSTRING_INDEX(sub2.mid_prices, ',', -1)) / 2
END AS median_of_quantity
FROM
(
SELECT
sub1.total,
CASE WHEN MOD(sub1.total, 2) = 1 THEN SUBSTRING_INDEX(SUBSTRING_INDEX(sub1.prices, ',', CEIL(sub1.total/2)), ',', '-1')
WHEN MOD(sub1.total, 2) = 0 THEN SUBSTRING_INDEX(SUBSTRING_INDEX(sub1.prices, ',', sub1.total/2 + 1), ',', '-2')
END AS mid_prices,
CASE WHEN MOD(sub1.total, 2) = 1 THEN SUBSTRING_INDEX(SUBSTRING_INDEX(sub1.quantities, ',', CEIL(sub1.total/2)), ',', '-1')
WHEN MOD(sub1.total, 2) = 0 THEN SUBSTRING_INDEX(SUBSTRING_INDEX(sub1.quantities, ',', sub1.total/2 + 1), ',', '-2')
END AS mid_quantities
FROM
(
SELECT
COUNT(*) AS total,
GROUP_CONCAT(o.price ORDER BY o.price) AS prices,
GROUP_CONCAT(o.quantity ORDER BY o.quantity) AS quantities
FROM products.orders o
) sub1
) sub2
;
median_of_price|median_of_quantity|
---------------+------------------+
3 |30 |
再次欢呼,果然有效!
目前,计算中位数的功能还没有在 MySQL 中实现,因此我们需要自己编写一些查询来计算它们。本文介绍了两种解决方案。第一种是使用 SQL 变量的经典解决方案。第二个是新的,用GROUP_CONCAT
和SUBSTRING_INDEX
完成。第二个代码多一点,但是可扩展性更好。您可以使用它来计算不同类别的相同字段的中位数,也可以计算多个字段的中位数。
相关文章:
如何用管道链接 Pyspark 中的函数
原文:https://towardsdatascience.com/how-to-chain-functions-in-pyspark-with-pandas-pipe-1915ed7ebc34
用熊猫管法的 pyspark 等效链多函数
动机
如果你是一个 Pandas 用户,你可能遇到过 Pandas DataFrame .pipe()
方法,它允许用户对数据帧或系列应用可链接的函数。如果你对熊猫.pipe()
不熟悉,这里有一个快速的例子和开始使用它的动机。
照片由 Helio Dilolwa 在 Unsplash 上拍摄
什么是熊猫 **.pipe()**
?
参数
func
:应用于系列/数据框的功能args
:位置参数传递给func
kwargs
:传递给func
的关键字参数
退货
object
:返回类型func
在本例中,我们有 3 个函数对数据帧进行操作,f1
、f2
和f3
,每个函数都需要一个数据帧和参数作为输入,并返回转换后的数据帧。
def f1(df, arg1):
# do something return # a dataframedef f2(df, arg2):
# do something return # a dataframedef f3(df, arg3):
# do something return # a dataframedf = pd.DataFrame(..) # some dataframe
如果不使用.pipe()
,我们将以嵌套的方式应用函数,如果有多个函数,这可能看起来很难理解。
f1(f2(f3(df, arg3 = arg3), arg2 = arg2), arg1 = arg1)
为了遵循函数执行的顺序,必须从“由内向外”阅读。首先执行最内部的功能f3
,然后执行f2
,最后执行f1
。
.pipe()
避免嵌套,允许使用点符号(.
)链接函数,使其更具可读性。.pipe()
还允许传递位置参数和关键字参数,并假设函数的第一个参数指向输入数据帧/序列。
df.pipe(f3, arg3 = arg3).pipe(f2, arg2 = arg2).pipe(f1, arg1 = arg1)
遵循与.pipe()
链接在一起的功能的执行顺序更直观;我们只是从左向右读。
Pyspark 是大数据处理中熊猫的流行替代品。在本文中,我们将研究如何使用以下方法链接 pyspark 函数:
- 派斯帕克的
.transform()
方法 - 创建一个 Pyspark,相当于熊猫的
.pipe()
方法
数据
这是我们将在示例中使用的合成数据。
df = spark.createDataFrame([('John', 30, 180, 90, 'm'), ('Karen', 27, 173, 60, 'f')], ['name', 'age', 'height', 'weight', 'gender'])
df.show()+-----+---+------+------+------+
| name|age|height|weight|gender|
+-----+---+------+------+------+
| John| 30| 180| 90| m|
|Karen| 27| 173| 60| f|
+-----+---+------+------+------+
该数据集包含两个人 John 和 Karen 的年龄、身高、体重和性别信息。任务是:
- 找到他们的身体质量指数(身体质量指数)
- 将
gender
列中的小写字符串转换为大写
我们创建以下函数来计算身体质量指数,它是以千克为单位的重量除以以米为单位的高度的平方。
def calculate_bmi(df):
df = df.withColumn('bmi', f.round(f.col('weight')/(f.col('height')/100)**2,2))
return df
改变
pyspark.sql.DataFrame.transform
是链接自定义转换的简明语法。
参数
func
:获取并返回数据帧的函数
以下是如何在数据帧上应用calculate_bmi
功能。
df.transform(calculate_bmi).show()+-----+---+------+------+-----+
| name|age|height|weight| bmi|
+-----+---+------+------+-----+
| John| 30| 180| 90|27.78|
|Karen| 27| 173| 60|20.05|
+-----+---+------+------+-----+
我们可以将多个转换和其他 DataFrame 方法链接在一起。在下面的例子中,我们计算了身体质量指数并将gender
列大写。
(df
.transform(calculate_bmi)
.withColumn('gender', f.upper('gender'))
.show())+-----+---+------+------+------+-----+
| name|age|height|weight|gender| bmi|
+-----+---+------+------+------+-----+
| John| 30| 180| 90| M|27.78|
|Karen| 27| 173| 60| F|20.05|
+-----+---+------+------+------+-----+
与 Pandas 的.pipe()
不同,Pyspark 的.transform()
不向输入函数(func
)传递参数。克服这一限制的一种方法是使用 python 的部分函数。
让我们扩展一下身体质量指数的例子。我们发现体重和身高机器没有很好地校准,因此我们必须对测量的身高和体重进行补偿,以获得正确的身体质量指数。下面是实现这一点的函数。
def offset(df, height_offset, weight_offset):
df = (df
.withColumn('height', f.col('height') + height_offset)
.withColumn('weight', f.col('weight') + weight_offset)
)
return df
为了使用.transform()
在数据帧上应用偏移函数,我们使用 python 的functools.partial
方法来创建分部函数,该函数允许我们将参数传递给offset
函数。
from functools import partial(df
.transform(partial(offset, height_offset = 2, weight_offset = -0.5))
.transform(calculate_bmi)
.withColumn('gender', f.upper('gender'))
.show())+-----+---+------+------+------+-----+
| name|age|height|weight|gender| bmi|
+-----+---+------+------+------+-----+
| John| 30| 182| 89.5| M|27.02|
|Karen| 27| 175| 59.5| F|19.43|
+-----+---+------+------+------+-----+
或者,我们可以创建一个相当于 Pandas .pipe()
的 pyspark,它接受位置和关键字参数。
自定义 Pyspark 管道方法
我们创建了一个.pipe()
函数,并执行了一个 monkey 补丁,将它作为pyspark.sql.DataFrame
类的一个方法包含进来。
from pyspark.sql import DataFramedef pipe(self, func, *args, **kwargs):
return func(self, *args, **kwargs)DataFrame.pipe = pipe
参数
func
:数据框上应用的输入功能args
:位置参数kwargs
:关键字参数
让我们来看一些例子。
无参数函数
与.transform()
类似,.pipe()
可以接受没有任何参数的输入函数。
df.pipe(calculate_bmi).show()+-----+---+------+------+------+-----+
| name|age|height|weight|gender| bmi|
+-----+---+------+------+------+-----+
| John| 30| 180| 90| m|27.78|
|Karen| 27| 173| 60| f|20.05|
+-----+---+------+------+------+-----+
λ函数
.pipe()
也可以接受 lambda 函数。
df.pipe(lambda df: df.withColumn('bmi', f.round(f.col('weight')/(f.col('height')/100)**2,2))).show()+-----+---+------+------+------+-----+
| name|age|height|weight|gender| bmi|
+-----+---+------+------+------+-----+
| John| 30| 180| 90| m|27.78|
|Karen| 27| 173| 60| f|20.05|
+-----+---+------+------+------+-----+
带关键字参数的函数
由.pipe()
接收的关键字参数将被传递给offset
函数。我们还可以将多个.pipe()
功能链接在一起。
(df
.pipe(offset, height_offset = 2, weight_offset = -0.5)
.pipe(calculate_bmi)
.withColumn('gender', f.upper('gender'))
.show())+-----+---+------+------+------+-----+
| name|age|height|weight|gender| bmi|
+-----+---+------+------+------+-----+
| John| 30| 182| 89.5| M|27.02|
|Karen| 27| 175| 59.5| F|19.43|
+-----+---+------+------+------+-----+
带有位置参数的函数
.pipe()
也适用于位置参数。
(df
.pipe(offset, 2, -0.5)
.pipe(calculate_bmi)
.withColumn('gender', f.upper('gender'))
.show())+-----+---+------+------+------+-----+
| name|age|height|weight|gender| bmi|
+-----+---+------+------+------+-----+
| John| 30| 182| 89.5| m|27.02|
|Karen| 27| 175| 59.5| f|19.43|
+-----+---+------+------+------+-----+
摘要
在本文中,我们给出了链接函数的动机。在 Pyspark 中将定制函数链接在一起的本地方法是使用pyspark.sql.DataFrame.transform
方法。这种方法的缺点是不允许向输入函数传递参数。为了克服这个限制,我们演示了如何将.transform()
与functools.partial
结合使用,或者在 Pyspark 中创建一个自定义的.pipe()
方法。
如何选择预测模型
原文:https://towardsdatascience.com/how-to-choose-a-forecasting-model-fa9c4a2e75b8
选择时间序列方法的决策树
尼克·希利尔在 Unsplash 上的照片
由戈西亚·科莫尔和克劳迪娅·邦尼撰写,由约斯特·德·泰耶评论。
关键要点:
- 在处理时间序列时,经典的统计方法不能直接适用,所以一定要使用特定于时间序列的方法
- 理解业务问题和数据对于选择最合适的模型至关重要
- 选择模型只是模型训练、评估、改进和操作的激动人心的旅程的开始
简介
对于在动荡环境中运营的任何企业来说,预测都是一项至关重要的职能。捕捉经济和未来需求的可变性是对变化做出快速反应并调整供应、采购、物流等业务的关键技能。预测的好处包括降低库存成本、减少浪费、减少缺货和实现更高的服务水平。
时间序列分析是一种特定的方法,可以帮助企业提高其预测能力。它分析在一段时间间隔内收集的一系列等距数据点,以提取数据的有意义的统计数据并预测其未来值。
然而,随着数据科学的日益普及和数据的日益复杂,可能的时间序列模型的数量可能会多得令人难以招架。您是否需要一个简单的解决方案来最好地获取历史销售额,或者您的业务是否严重依赖于需要考虑的外部因素?这些是在数据探索期间需要询问的示例问题,以便为分析问题选择最适合的模型。在本文中,我们将介绍我们的方法来执行时间序列建模,包括分析问题框架,数据探索和我们的时间序列模型选择的新框架。
- 分析问题框架
在我们方法的第一阶段,业务问题被转化为分析问题,因此,范围被定义。这一步对于建立分析方法至关重要。一般来说,分析性问题框架包括定义要测试的假设、要提取的变量和整体解决方案的成功标准。然而,时间序列分析需要额外的步骤来扩展标准的人工智能方法。
一般来说,时间序列解决方案的总体目标是最小化预测的误差。通过提高需求预测的准确性,这可以转化为企业避免不必要的库存或最后一分钟运费的成本。通过分析确定这一目标非常重要,它将决定感兴趣的变量、时间范围、预测粒度和数据层次。
时间范围被定义为我们预测数据的时间段。例如,采购团队需要提前 10 周订购特定数量的材料。在这种情况下,预测范围至少是 10 周,10 周可能提供最好的准确性。根据业务问题,选择正确的时间范围以在正确的时间从解决方案中获得可操作的见解非常重要。
预测粒度被定义为时间维度,其中数据被格式化用于预测,例如每周、每月或每年。例如,每周预测将需要子周预测粒度来包含数据中的模式。还应该确定粒度以获得最佳洞察力,但粒度也会受到数据可用性的影响。
在开始对数据进行预测分析之前,了解产品层次结构非常重要。最佳层次结构的选择不仅取决于业务问题,还取决于数据的可用性。例如,如果产品经常变化,但它们的组成非常相似,那么将相似的产品分组并一起预测会很有趣
2。数据探索和需求
数据探索通常包括将数据分成训练集和测试集、异常值检测和识别缺失值。这些步骤也可以用时间序列数据来执行,但是需要额外的步骤来开始建模。
当使用时间序列数据时,重要的是检测数据中任何与时间相关的模式,这有助于理解手头的问题并在以后选择模型。当季节性因素影响一周中的天数【1】等数据时,时间序列中就会出现季节性模式。通过绘制数据或在数据探索阶段进行季节性分解,可以更清楚地识别这些模式。
特征工程是对模型质量有很大影响的一个步骤。在时间序列中,可以设计不同类型的特征,例如日期时间特征、滞后特征和滚动窗口统计。参见一篇关于时间序列模型特征工程的伟大文章【2】。
除了历史数据,还有其他外部因素可以帮助更好地预测未来。我们称这些变量为“外部因素”。在这个数据探索阶段,识别这些变量、理解它们并转换它们以适应模型是很重要的。例如,汽车销售可以帮助预测汽车零部件的需求。通过将这一外部因素添加到解释变量中,可以提高预测模型的性能。
3。选择型号
时间序列数据具有许多影响未来值的特征,因此我们创建了一个决策树来帮助选择最佳拟合模型。这里有一个如何使用决策树的例子:
首先,检查数据集中有多少个数据点。我们的经验法则是数据集应该包含至少 2 个预测周期。如果不是这样,你需要收集更多的数据。
通过计算观察值之间的差异实现股票价格数据集中平稳性的示例。图灵感来自:【https://otexts.com/fpp2/stationarity.html】T2
如果你有足够的数据,平稳性评估。平稳数据被定义为在一段时间内具有恒定的方差和均值。您可以运行一个增强的 Dickey-Fuller (ADF)测试来统计检查这一点,但是您也可以在绘制一段时间的数据时直观地看到这一点。为了实现平稳性,使用时间 t 和 t-1 的观测值之间的差值,而不是时间 t 的观测值。
观测数据的季节分解示例。图灵感来源:https://machine learning mastery . com/decompose-time-series-data-trend-seasonity/
接下来,您需要确定数据的季节性。通过分解时间序列数据,您可以识别数据的趋势、季节模式和残差。最常用的方法是经典的季节分解法,但也有其他方法(例如 X11 分解、座位分解)。如果您的数据不是季节性的,您可以在 ARMA(X)和指数平滑之间进行选择,这取决于您是否需要向模型中添加外部变量。
如果您的数据不是静态的,则需要检查趋势是否是线性的,以便在线性和非线性模型之间进行选择。在非线性时间序列中,序列的当前值不是过去观测值的线性函数。当应用于来自线性模型的残差时,BDS 测试可以检测省略的非线性结构的存在。然而,就像经典回归分析一样,数据的非线性可以通过预测或预测变量(如 log())的转换来忽略。此外,如果非线性数据可以划分为线性周期,则可以执行分段线性分析。然而,非线性模型,包括基于集合建模或神经网络的模型,以其高性能而闻名,并允许在预测中纳入外部变量,这有助于解释结果。
4。模型性能和操作
有许多关于时间序列评估指标的优秀文章,我们建议阅读这些[3–5]。此外,定制的度量标准可以被设计成在特定的组织中工作得最好,并且可以被业务涉众容易地解释。您的预测模型也可以用简单的方法作为基准,如简单预测或移动平均法。
预测是使用历史数据完成的,正如机器学习中经常发生的那样,使用一个训练过的模型将导致随着时间的推移误差越来越大。模型生命周期监控对于及时发现性能下降至关重要,样本外预测是一种有效的规避方法,它通过一段时间内的滚动窗口训练模型。
最后,重要的是要记住,选择一个模型只是这个过程的开始。彻底的实验和随后的模型改进将确保它尽可能准确。需要考虑模式的运作,包括如何将其纳入现有系统和业务流程。
结论
时间序列建模是各种业务的基本技能。通过了解业务问题和数据,选择最合适的模型,训练和评估模型,并迭代地改进和操作它,企业可以提高他们的预测能力,并做出更好的数据驱动的决策。我们希望通过遵循这些步骤并使用系统化的方法,您可以选择满足业务需求的预测模型,并帮助您做出更准确的预测。
所有图片均由作者提供。
参考文献:
【1】hynd man,R.J .,& Athanasopoulos,G. (2021)预测:原理与实践,第 3 版,OTexts:澳大利亚墨尔本。OTexts.com/fpp3.访问时间为 2022 年 3 月 4 日。
如何为您的数据科学项目选择有效的视觉效果
免费下载指南,帮助您选择合适的产品
作者图片
视觉沟通是每个专业人士必备的技能。决策在很大程度上依赖于数据,这些数据的数量如此之大,以其原始格式是无法消费的。因此,应用某种程度的图形抽象是必要的。
Dataviz 已经成为一种共享的“语言”,将数据整理成更容易理解的形式,突出模式和异常值。传统上,商业世界在讲故事和技术分析之间划了一条明显的界限,而今天,公司更看重那些跨越这两个领域的人。公民数据科学家 ( 一词由 Gartner 创造,指的是能够执行简单或中等复杂的分析任务,但其主要工作职能不在统计和分析领域本身的人)的崛起是事实。
制作设计良好、有说服力且清晰的图表是任何数据科学家的关键能力,这一切都始于选择正确的类型。这篇文章将有望让你掌握基本的视觉“语法”,以创建强有力地描绘你的想法的引人注目的可视化。
有一个图表!
寻求选择有效可视化的第一步是理解你的数据,这样你就可以清楚地定义你想要传达给最终用户的信息:
‣:它是什么类型的?名义上?序数?比例?区间?(—见下面的备忘录)
‣需要什么样的分组?‣不同的数据部分如何相互关联?
‣最普遍的价值观是什么?
‣他们的比例重要吗?
‣它们是如何随时间变化的?
‣:顺序重要吗?
每个星盘都有一个基于其属性的特定目标,所以第二步是选择一个与你的目标一致的观想。这不是一个简单的任务,有很多关于这个主题的文献——我将在本文的下一部分向您介绍最流行的方法。
在本节中,我将尝试缩小常见 dataviz 目标的范围,并解释您可能面临的最常见案例背后的决策过程。这不是一个全面的列表,肯定会有例外,但是理解基础知识是至关重要的。我们将首先描述用例,然后给出一个可以在这个类别中回答的示例问题,最后添加最流行的图表类型和一个可视化示例。
n.b. :在这些例子中,我将使用我在 中制作的图表,但这些概念也适用于在其他应用程序/库中制作的图表。
**Quick Memo on Data Types****✅ Qualitative** data cannot be measured numerically, but can be described through language:
‣ **Nominal** data have distinct values, but without a built-in order, e.g. country, gender, customer name.
‣ **Ordinal** data have a ranked or positioned value but the magnitude of the differences is not well defined, e.g. satisfaction scale: low, medium, high.**✅ Quantitative** data can be measured numerically:
‣ **Intervals** are data where the **absolute** differences are significant (addition and subtraction operations can be performed), e.g. cost.
‣ **Ratios** are data where the **relative** differences are significant (multiplication and division operations may be performed), e.g. you cannot sum up the rainfall in a week, but you can calculate the average, or you can say this week's rainfall is two times higher than last week.All quantitative variables are in turn divided into two types:
‣ **Discrete** data have finite possible values, obtained by counting, e.g. number of children a family has (0, 1, 2, 3, etc).
‣ **Continuous** data cannot be counted, but are obtained by measuring – hypothetically they are infinite, e.g. a building’s height (20.450m, 20.451m, etc).
准备好了吗?我们走吧!
➊——指标
‣ 最适合:告知你的听众一个具体的数据点或数值。这不是“真正的图表”,但经常在 KPI 仪表板中使用,以引起对关键数字的注意。
‣ 样本用例:本周销售总数。
‣ 图表类型:单个指示器(如数字、增量和仪表)。
指标示例[本周销售总数]
➋ —名义数据比较
‣ 最适合:比较没有特定顺序的值。
‣ 样本用例:每个国家的产品销售额。
‣ 图表类型:条形图,最好按字母顺序标注。
名义数据示例[每个国家的产品销售额]
➌——排名
‣ 最适合:两个或多个子集相对大小的排序。
‣ 样本用例:人均可支配收入最高的国家。
‣ 图表类型:以降序排列的条形图,强调高值,或以升序排列,强调低值。
排名示例[每个国家最高可支配收入]
➍ —时间序列
‣ 最适合:通过内在化趋势、模式和可变性,比较在相同时间段内进行的测量,通常用于预测。
‣ 样本用例:股票价格分析。
‣ 图表类型:折线图,其中 x 轴绘制时间增量,y 轴精确显示被测量变量的值。
时间序列示例[股票价格分析]
➎相关性
‣ 最擅长:确定两个或多个变量如何可能有正或负的关系或者根本没有关系。
‣ 样本用例:总账单和小费之间的差异。
‣ 图表类型:当涉及两个变量时:带有线性回归线的散点图(显示趋势)。—对于三个变量:气泡图(尺寸为第三维)。
相关性示例[左:总账单和小费之间的差异—右:相同,基于用餐人数]
➏ —偏差
‣ 最适合:测量数值和参考值之间的差异,例如数据点与平均值或中值的差异。
‣ 样本用例:本月的气温与上月的中值对比。
‣ 图表类型:包含偏离参考线的折线图,以强调整体模式。—或者:发散条形图,以强调测量结果。
偏差示例[本月温度与上月中值的对比]
➐ —分布
‣ 最佳:说明人口中事件发生的频率。
‣ 样本用例:受访者的年龄分布。
‣ 图表类型:柱状图。
分布示例[受访者的年龄分布]
➑——作文
‣ 最适合:测量整体的单个值。
‣ 样本用例:各部门对总预算的分配。
‣ 图表类型:条形图,其中条形大小对应于总值的百分比。饼图通常不太能有效地展示数据。
构成示例[各部门总预算的分配]
➒ —原始数据
‣ 最适合:查看精确数值,或比较单个数值。这不是“真正的可视化”,但经常用于需要深入到成分记录的分析中。
‣ 样本用例:公司的薪酬记录。
‣ 图表类型:表格。
原始数据示例[公司的薪酬记录]
➓ —不确定性
Nearly every dataset we work with has some uncertainty generated from **inefficient representation of data** (summary statistics) and **statistical inference** (data sample and probability), so how we choose to represent this can influence how the data is perceived by decision makers, who are usually more comfortable with certain messages.
‣ 最适合:表示测量中可能值的范围,即给出测量精度的一般感觉。
‣ 样本用例 : A 级成绩预测。
‣ 图表类型:折线图、条形图、散点图等中的误差线。
不确定性示例[A-level 成绩预测]
常用图表选择工具包
dataviz 的艺术不仅仅是将数据转换成图表;这也是关于知道如何以一种有意义的方式呈现你的数据和信息。选择正确的图表不是一项简单的任务,通常没有单一或理想的答案。为了帮助您在多个选项之间做出选择,有几个工具包可供您参考。
以下是我策划的工具列表:
➊——安德鲁·阿贝拉博士的极端呈现法
也许最著名的决策图是 Andrew Abela 博士的极端呈现 方法论,其中图表分为四种类型:比较、组成、分布、关系。
➋——金融时报视觉词汇
尽管英国《金融时报》的目标读者是记者,但他们指南的内容对任何可视化数据的人来说都是普遍适用的。它概述了九个类别和 70 多种图表类型,并描述了在实践中如何以及何时使用这些图表。
麻省理工学院许可证:链接
➌——dataviz 项目
这个项目展示了一个交互式的可视化目录,不仅按名称和功能分类,还按数据类型和形状分类。
从数据到文本的➍—
From Data to Viz 是一个图表选择工具,它会引导您找到最适合您的 Dataviz 需求的图表,并链接到构建它的代码(R、Python 和 D3)。
麻省理工学院许可证:链接
➎——可视化宇宙
可视化宇宙是图表、Dataviz 书籍和按流行和趋势排列的工具的绝佳指南。它是由谷歌新闻实验室和 T21 合作设计的。
外卖食品
有两大类图表:一类允许观众探索数据,另一类快速清晰地传达见解。在这两种情况下,最重要的是要记住简单是王道:简单明了地讲述一个清晰的故事,让你的观众明白,这比展示复杂的图表,把注意力从关键信息上引开,要有力得多。
对于 Dataviz 来说,简单是王道
也就是说,祝你第一次(或下一次)dataviz 之旅好运。
🆓 👉如果你想收藏本文中讨论的可视化用例,你可以从我的 Gumroad 页面下载一个免费的 pdf。
感谢阅读!
我经常在媒体上写关于领导力、技术&的数据——如果你想阅读我未来的帖子,请‘关注’我 !
我的新书《技术智慧》现已面世— 先睹为快 !
梯度推进中如何选择估计量的个数
一个简单的循环来调整你的模型
布莱登·特罗洛普在 Unsplash 拍摄的照片
介绍
在数据科学中,目前有许多算法可供使用。因此,一种有用的技术是将它们结合在一个模型中,以获得各自的优点,从而得到一个更准确的模型。
使用 Scikit-Learn,您会发现随机森林算法,即 bagging 类集成模型。另一方面,您还会发现 Boosting 模型,它按顺序训练估计器,将一个模型的结果传递给下一个模型,试图改进预测,直到它们达到最佳结果。
创建梯度增强估计器时,您会发现这个超参数n_estimator=100
的默认值为 100 棵树,需要创建这些树才能得到结果。很多时候,我们只是将它设置为默认值,或者根据需要增加,甚至使用网格搜索技术。
在这篇文章中,我们将找到一个简单的方法来得到一个单一的数字来训练我们的模型。
梯度推进
使用这个类**from** sklearn.ensemble **import** GradientBoostingRegressor
可以从 Scikit-Learn 加载梯度增强。梯度推进算法可用于分类或回归模型。它是一个基于树的估计器,这意味着它由许多决策树组成。
树 1 的结果会产生错误。这些误差将被用作采油树 2 的输入。同样,上一个模型的误差将被用作下一个模型的输入,直到它达到n_estimators
值。
每个模型都会符合前一个模型的误差。图片由作者提供。
由于每个估计量都将符合前一个估计量的误差,因此预期预测的组合将优于任何一个单独的估计量。每次迭代后,我们都使模型变得更复杂,减少了偏差,但增加了方差。所以我们必须知道何时停止。
让我们看看现在该如何做。
准备模型
这个练习的代码很简单。我们所要做的就是在每次迭代后循环一次,并检查哪一次我们有最低的误差。
让我们从选择数据集开始。我们将使用来自 seaborn 库的 car_crashes 数据集(这是 BDS 许可下的一个开放数据)。
# Dataset
df = sns.load_dataset('car_crashes')
下面快速看一下数据。我们将尝试使用其他特征作为预测值来估计total
的数量。既然是实数输出,我们就说回归模型。
车祸数据集,来自 seaborn。图片由作者提供。
快速查看相关性。
# Correlations
df.corr().style.background_gradient(cmap='coolwarm')
数据集中的相关性。图片由作者提供。
好的,没有严重的多重共线性。我们可以看到ins_premium
和ins_losses
与total
没有很好的关联,所以我们在模型中不考虑它们。
如果我们检查丢失的数据,没有
# Missing
df.isnull().sum()
0
很好,现在让我们拆分数据。
# X and y
X = df.drop(['ins_premium', 'ins_losses', 'abbrev', 'total'], axis=1)
y = df['total']# Train test
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=22)
我们可以创建一个管道来缩放数据并对其建模(缩放这些数据真的不是很有必要,因为它们已经处于相同的缩放比例,基于十进制)。接下来,我们将数据拟合到模型中,并预测结果。
我使用了 500 个 T4 为 0.3 的估值器。
学习率是我们达到最小误差所采取的步长。如果我们使用的值太高,我们可能会超过最小值。如果我们用一个太小的数字,我们甚至可能无法接近它。所以,你可以考虑的一个经验法则是:如果你有大量的评估者,你可以使用较低的学习率值。如果你只有几个估值器,最好使用更高的学习率值。
steps = [('scale', StandardScaler()),
('GBR', GradientBoostingRegressor(n_estimators=500, learning_rate=0.03)) ]# Instance Pipeline and fit
pipe = Pipeline(steps).fit(X_train, y_train)# Predict
preds = pipe.predict(X_test)
现在评估。
# RMSE of the predictions
print(f'RMSE: { round(np.sqrt(mean_squared_error(y_test, preds)),1 )}')**[OUT]: RMSE: 1.1**# Mean of the true Y values
print(f'Data y mean: {round( y.mean(),1 )}')**[OUT]: Data y mean: 15.8**
很好。我们的 RMSE 大约是平均值的 6.9%。平均来说,我们就差这么多。
确定估计量的数量
现在,让我们检查一种方法来调整我们的模型,选择最佳数量的估计量来训练,这将使我们的错误率最低。
就像我说的,我们真的不需要缩放这个数据,因为它已经是相同的比例了。所以我们来拟合一下模型。
#Model
gbr = GradientBoostingRegressor(n_estimators=500, learning_rate=0.3).fit(X_train, y_train)
现在是好东西了。梯度推进中有一种方法,允许我们迭代每个训练好的估计器的预测,从 1 到 500。因此,我们将创建一个循环,遍历gbr
模型中的 500 个估计器,使用方法staged_predict()
预测结果,计算均方误差,并将结果存储在列表errors
中。
# Loop for the best number
errors = [ mean_squared_error(y_test, preds) for preds in gbr.staged_predict(X_test)]# Optimal number of estimators
optimal_num_estimators = np.argmin(errors) + 1
接下来,我们可以绘制结果。
#Plot
g=sns.lineplot(x=range(500), y=errors)
g.set_title(f'Best number of estimators at {optimal_num_estimators}', size=15);
最佳估计数。图片由作者提供。
我们看到最低的错误率是用 34 个估值器。因此,让我们用 34 个估计器重新训练我们的模型,并与用管道训练的模型的结果进行比较。
# Retrain
gbr = GradientBoostingRegressor(n_estimators=34, learning_rate=0.3).fit(X_train, y_train)# Predictions
preds2 = gbr.predict(X_test)
正在评估…
# RMSE of the predictions
print(f'RMSE: { round(np.sqrt(mean_squared_error(y_test, preds2)),1 )}')
**[OUT]: RMSE: 1.0**# Data Y mean
print(f'Data y mean: {round( y.mean(),1 )}')**[OUT]: Data y mean: 15.8**
我们从 6.9%降到了现在的 6.3%。近似的好 9%。我们来看几个预测。
两个模型的预测。图片由作者提供。
有趣的结果。第二个模型的一些预测比第一个要好。
在你走之前
我们从 Scikit-Learn 中学习了如何确定调整 a GradientBoostingRegressor
的最佳估计数。这是一个超参数,可以在这种集合模型中发挥作用,它按顺序训练估计量。
有时,在几次迭代之后,模型可能会开始过度拟合,因此它会开始过多地增加方差,从而影响预测。
我们看到,在这种情况下,一个简单的循环可以帮助我们找到最优解。但是,当然,对于大型数据集来说,计算起来可能很昂贵,所以一个想法是首先尝试一个较低的n_estimators
,看看您是否能尽快达到最小误差。
下面是 GitHub 中的完整代码。
如果你喜欢这个内容,请关注我的博客。
http://gustavorsantos.medium.com/
在 LinkedIn 上找到我。
这个练习是基于参考文献中 Aurélien Géron 的优秀教科书。
参考
https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.GradientBoostingClassifier.html https://www.amazon.com/Hands-Machine-Learning-Scikit-Learn-TensorFlow/dp/1098125975/ref=pd_lpo_2?pd_rd_w=DBmLe&content-id=amzn1.sym.116f529c-aa4d-4763-b2b6-4d614ec7dc00&pf_rd_p=116f529c-aa4d-4763-b2b6-4d614ec7dc00&pf_rd_r=81QQEFQYR0K7ZTFRHMJD&pd_rd_wg=iPGdg&pd_rd_r=1b48e671-181a-44bc-8d3b-7b6384e9edcd&pd_rd_i=1098125975&psc=1
如何选择神经网络的最佳学习速率
通过示例调整最重要的神经网络超参数的指南
使用 ML 和 DL 算法时,超参数调整或优化是一个主要挑战。超参数几乎控制了这些算法中的一切。
在我的神经网络超参数分类帖子中,我已经用一个合适的分类图讨论了 12 种神经网络超参数。**
这些超参数决定了运行神经网络模型的时间和计算成本。它们甚至可以决定网络的结构,最终直接影响网络的预测精度和泛化能力。
在这些超参数中,最重要的神经网络超参数是用α(α)表示的 学习率 。
DL 初学者总会问学习率有多重要。我可以这样回答这个问题。
在训练神经网络时,如果只允许我调整一个超参数,我会毫不犹豫地选择调整学习率。
让我们深入了解更多细节,找出什么是学习率,以及它如何影响神经网络的训练过程。
神经网络的学习率是多少?
学习率是神经网络中最重要的超参数。可以在任何优化算法中找到,如 RMSprop、Adam、梯度下降等。
**from tensorflow.keras.optimizers import RMSprop
RMSprop(**learning_rate=0.001**, ...)**
在训练过程的开始,网络的参数(权重和偏差)用随机值初始化,但是这些不是给出最小误差或损失的最佳值。这就是我们继续培训的原因。
在网络的每个训练步骤(迭代)中,将向前传播步骤中计算的结果与地面真实(实际)值进行比较,以计算误差或损失分数。然后,在反向传播步骤中反向传播该误差,以调整权重和偏差的初始值,从而在接下来的训练步骤中最小化该误差。我们继续训练,直到误差最小。
为了计算每个训练步骤的预测值和实际值之间的误差,需要一个 损失函数 。在训练过程中,我们的目标是尽可能将损失函数最小化。为了最小化损失函数,我们需要一个 优化器 (优化算法)。
在 Keras 中,优化器可以定义为一个函数,如RMSprop()
、Adam()
、SGD()
等。学习率可以被指定为函数中的一个关键字参数,就像我之前展示的那样。
当我们绘制相对于单个重量值(x 轴)的损失函数(y 轴)时,我们得到 2D 平面中的误差曲线。
当我们绘制相对于两个权重值(x 和 y 轴)的损失函数(z 轴)时,我们得到 3D 平面中的误差曲线。这种类型的 3D 曲线通常被称为 误差山 ,通常用于描述与学习率和 DL 算法优化相关的事情!
现实世界的神经网络最终会有成千上万的权重值。当神经网络有那么多的权重时,我们无法想象误差曲线的可视化!
误差山就像一座有山峰和山谷的真正的山。峰值代表高误差值,而谷值代表低误差值。想象权重的随机初始值在那座山的一个顶峰。
在优化过程中,算法需要采取一系列微小的步骤来降低误差山,以最小化误差。每一小步都有两个属性:方向和大小。
步长的方向由梯度(导数)决定。为了得到方向,我们应该计算误差对重量值的导数。
步长由学习速率决定。它决定了优化器下降误差曲线的快慢。有了较大的学习率,优化器会采取较大的步骤来降低错误率。在学习率较低的情况下,优化器会采取较小的步骤来降低错误率。
学习率如何影响神经网络的训练过程
接下来我们想了解的是学习率如何影响神经网络的训练过程。确定神经网络模型的最佳学习速率非常重要。
这里将讨论四种不同的场景:
- 以较小的学习速率(α1)缓慢收敛
- 以较大的学习率(α2)在最小值附近振荡
- 学习率非常大的振荡和发散(α3)
- 以最优学习率(α4)适当收敛
让我们详细讨论每个场景。
场景 1:以较小的学习速率缓慢收敛
****收敛慢(图片由作者提供,用 draw.io 制作)
当学习率远小于最佳值时会发生这种情况(α1 << α4). The algorithm takes very small steps to descend the error mountain in order to reach the minimum. So, the convergence happens very slowly and the algorithm takes a lot more time to converge. But, the convergence is guaranteed if we allow the algorithm to run for a long period of time with a high number of epochs! So, it is time-consuming even if we get accurate results.
Scenario 2: Oscillating around the minimum with a large learning rate
****过冲并在最小值附近振荡)(图片由作者提供,使用 draw.io 制作)
当学习率大于最佳值(α2 > α4)时会出现这种情况。如图所示,当算法采取大的步骤来降低误差山时,优化器在第一步中超过了最佳权重,并且在下一步中再次超过。该算法试图达到最小值,但它仍然远离最小值。在最后的步骤中(接近最小值),优化器在最小值附近振荡,并且永远不会达到最小值,即使我们在很长一段时间内以大量的时期运行该算法。无论如何,这允许我们在早期获得一个较低的(但不是最佳的)误差值,比前一种情况更快!
场景 3:学习率非常大的振荡和发散
****超调振荡发散(图片由作者提供,用 draw.io 制作)
当学习率远大于最优值(α3 >> α4)时会出现这种情况。因为学习率 非常 大,所以算法从不试图下误差山。相反,它会在第一步中超出最佳权重,并在接下来的步骤中继续超出。在最初的几个步骤之后,随着优化器偏离最小值,错误开始增加。在最后的步骤中,优化器在一个比开始的错误值更高的错误附近振荡。这个过程叫做 振荡发散 。这是最坏的情况,因为算法结束时的误差比开始时更大!
场景 4:以最优学习速率适当收敛
我们应该避免以上三种情况,尤其是第三种。通过改变 Adam 优化器的学习速率,最佳学习速率在α1 和α2 (α1 < α4 < α2). With the optimal learning rate, the algorithm reaches the minimum in a short period of time with a considerably fewer number of epochs!
Guidelines for choosing the optimal learning rate with examples
This is the most important section of this article. I’ll use an example to show you how the above four scenarios actually happen during the training process.
Approach
I’ll train a 浅层自动编码器模型在 MNIST 数据集 (见最后的引文)之间出现几次。我将从默认的学习率值 0.001 开始,然后按照下面的指导方针,为您提供一个找到最佳学习率的 系统方法 。
(作者代码)
指导方针
- ****最好从优化器的默认学习率值开始。这里,我使用 Adam 优化器,其默认学习率值为 0.001。当训练开始时,监视模型在最初几个时期的表现。我得到了以下训练和验证损失值。
输出 1 (图片作者提供)
很明显,在每个时期之后,训练和验证损失都减少了。因此,您应该继续运行模型,直到所有的时期(这里是 70 个)都完成。完成训练过程后我得到了以下情节。
输出 2 (图片作者提供)
最好也在最后几个时期监控模型的性能。
输出 3 (图片作者提供)
通过查看图(输出 2),我们可以确定初始学习率太小,收敛发生得非常慢。这对应于场景 1。所以, α1 = 0.001 (默认值)。当事情发生这样的时候,我们有两个选择。
- ****显著增加历元数,以相同的学习速率再次训练模型。注意,这很费时间。通过增加历元的数量(这里,我们从 70 增加到 130),我们给模型更多的时间来进一步收敛。我在完成全部 130 个纪元后得到了下面的情节。
输出 4 (图片作者提供)
我还监控了模型在过去几个时期的表现。
输出 5 (图片作者提供)
增加历元数后,模型的性能提高了(主持输出 3 和输出 5 的最后几行)。该模型消耗了更多的时间来获得这种性能改进。这是这个选项的缺点。所以,不如试试第二种选择。
- ****增加学习率的值。注意,在这里,我们不增加历元的数量。这里设置为 70。新的学习率是 0.01。完成训练后我得到了以下情节。
输出 6 (图片作者提供)
我还监控了模型在最初几个时期的性能。
输出 7 (图片作者提供)
通过增加学习率的值,该算法在早期和中期很快降低了误差山。因此,我们在早期获得了较低的误差值。您可以通过比较输出 1 和输出 7 来确认这一点。另一个证实是,学习率为 0.01 的模型仅用了大约 20 个历元就达到了 0.16 的误差,但是具有默认学习率值(0.001)的模型用了大约 40 个历元才达到相同的误差。
让我们看看模型在最近几个时代的表现。
输出 8 (图片作者提供)
我们可以将这个输出与输出 3 进行比较。查看两个输出的最后一行。在输出 8 中,训练和验证损失都显著高于输出 3 中的相应值。即使算法在学习率较大的早期和中期给出了较低的误差值,但仍远未达到最小值。这对应于场景 2。所以, α2 = 0.01 。
现在,很明显,最佳学习率(α4)应该在α1 和α2 之间的某个位置(0.001 < α4 < 0.01).
- ****尝试α1 和α2 之间的不同学习率值。我推荐你从下侧开始。因此,我们可以将这些值增加为 0.0015、0.002 和 0.0025。这是结果。
learning_rate=0.0010
: Val — 0.1278,Train — 0.1292,第 70 个历元learning_rate=0.0015
: Val — 0.1264,Train — 0.1280,第 70 个历元learning_rate=0.0020
: Val — 0.1265,Train — 0.1281,第 70 个历元learning_rate=0.0025
: Val — 0.1286,Train — 0.1300 在第 70 个历元
通过观察上述结果,我们可以得出结论,最佳学习率出现在 0.0015 和 0.0020 之间的某处。所以,我们可以尝试以下数值。
learning_rate=0.0016
: Val — 0.1259,Train — 0.1276,第 70 个历元learning_rate=0.0017
: Val — 0.1258,Train — 0.1275,第 70 个历元learning_rate=0.0018
: Val — 0.1267,Train — 0.1280,第 70 个历元
通过查看上述结果,我们可以得出结论,最佳学习率为 0.0017,这可能因这些因素而异。
****注意:这个最佳学习率仅用 70 个时期就给出了比我们用 130 个时期以 0.001 的学习率获得的结果更好的结果!
不是以默认的学习率值或任何其他小的学习率值开始,如果你以非常大的学习率开始,你可以通过查看前几个时期的训练和验证损失来知道它。
输出 9 (图片作者提供)
启动误差在第 5 个时期增加!该模型将在下一个纪元开始振荡发散!这种情况发生在学习率很大的时候(这里我用了 10!).这对应于场景 3。所以, α3 = 10 。
输出 10 (图片作者提供)
当你得到一个类似上面的图时,考虑显著降低学习率,然后用你新的学习率再次训练模型。
决定学习率值的因素
有各种因素影响学习率的值。它们包括:
- 网络结构(宽度和深度)
- 神经网络架构的类型(例如 MLP、CNN、AE)
- 数据集的性质
- 优化器的类型(例如,RMSprop 优化器的最佳学习率不会是 Adam、SGD 等其他优化器的最佳值。)
- 随机状态涉及一些函数,如 train_test_split() 和某些 DL 算法
在 Keras 优化器中更改默认学习率
默认情况下,Keras 为其优化器的学习率提供了一个默认值。在大多数情况下,该值为 0.001。从默认的学习率值开始比较好。但是,在大多数情况下,我们需要改变这个值。
默认情况下,Keras 将优化器的类型定义为模型的 compile()方法中的字符串标识符。
**# As a string identifier
model.compile(**optimizer="rmsprop"**,...)**
当以这种方式定义优化器时,没有调整学习率值的选项。默认学习率值将应用于优化器。
要更改默认值,我们需要避免使用优化器的字符串标识符。相反,我们应该为优化器使用正确的函数。在本例中,它是 RMSprop()函数。新的学习率可以在该函数的learning_rate
参数中定义。
**from tensorflow.keras.optimizers import RMSprop
model.compile(**optimizer=RMSprop(learning_rate=0.005)**,...)**
静态与动态学习率
到目前为止,我们使用静态学习率。我们仅在培训后更改了学习率的值。所以,值是静态的!相反,动态学习率在训练期间改变其值。在大多数情况下,动态学习率比静态学习率表现得更好。
要了解更多关于动态学习率的信息,请阅读我的文章,Keras 优化器中的学习率计划和衰减。**
结论
学习率是最重要的神经网络超参数。它在训练网络的时候可以决定很多事情。
在 Keras 的大多数优化器中,默认的学习率值是 0.001。这是培训入门的推荐值。
当调整任何超参数时,不仅仅是学习率,我们应该总是试图缩小超参数的最佳值所在的范围。
调整学习率时,有必要在每个时期结束时监控训练和验证损失。您可以使用由model.fit()
方法返回的 历史 对象中存储的信息绘制一个图。您还可以在训练过程中实时查看这些值。确保在model.fit()
方法中设置了verbose=2
来打印每个时期的值。
最后,我可以说,
调整神经网络的学习速率是很棘手的。这只能通过在每个时期后监控训练和验证损失并遵循系统方法来实现。这不是一次性的、容易的过程。这是一个迭代的任务!一旦获得,最佳值会随着这些因素而变化。
今天的帖子到此结束。
如果您有任何问题或反馈,请告诉我。
阅读下一篇(推荐)
- Keras 优化器中的学习率计划和衰减
- 神经网络超参数分类
- 参数 Vs 超参数:有什么区别?
- 全集我的 神经网络与深度学习教程
(作者截图)
支持我当作家
我希望你喜欢阅读这篇文章。如果你愿意支持我成为一名作家,请考虑 注册会员 以获得无限制的媒体访问权限。它只需要每月 5 美元,我会收到你的会员费的一部分。
**https://rukshanpramoditha.medium.com/membership
非常感谢你一直以来的支持!下一篇文章再见。祝大家学习愉快!**
MNIST 数据集信息
- ****引用:邓,l,2012。用于机器学习研究的手写数字图像 mnist 数据库。 IEEE 信号处理杂志,第 29 卷第 6 期,第 141–142 页。
- ****来源:http://yann.lecun.com/exdb/mnist/
- 许可:Yann le Cun(NYU 库朗研究所)和 Corinna Cortes (纽约谷歌实验室)持有 MNIST 数据集的版权,该数据集在知识共享署名-共享 4.0 国际许可(CC BY-SA)下可用。您可以在此了解有关不同数据集许可类型的更多信息。**
鲁克山普拉莫迪塔
2022–09–21**
如何为神经网络选择合适的激活函数
用视觉表征分析不同类型的激活函数——神经网络和深度学习课程:第五部分
图片由作者提供,使用 draw.io 和 matplotlib 制作
介绍
在我们的 神经网络和深度学习课程 的第 1 部分中,正如这里介绍的,我们已经讨论了在神经网络模型中使用激活函数的主要目的。
在隐藏层和输出层的每个节点,激活函数被应用于称为 z 的输入的加权和(这里输入可以是原始数据或前一层的输出)。
今天,我们将讨论神经网络中使用的以下不同类型的激活函数。
不同类型的激活功能(图片由作者提供,用 draw.io 制作)
可视化表示将帮助您理解激活功能的功能定义和不同的使用场景。
文末:
- 你会对什么时候使用哪个激活功能有一个清晰的认识。
- 你会明白不同激活功能的定义。
神经网络中不同层的激活函数
神经网络通常由三种类型的层组成:输入层、隐藏层和输出层。
输入层仅保存输入数据,不执行任何计算。因此,这里没有使用激活函数。
我们必须在神经网络的隐藏层中使用非线性激活函数。这是因为我们需要在网络中引入非线性来学习复杂的模式。如果没有非线性激活函数,具有许多隐藏层的神经网络将成为一个巨大的线性回归模型,对于从现实世界的数据中学习复杂的模式是无用的。神经网络模型的性能将根据我们在隐藏层内部使用的激活函数的类型而显著变化。
我们还必须在神经网络的输出层内部使用激活函数。激活函数的选择取决于我们想要解决的问题的类型。
线性与非线性函数
大多数激活函数是非线性的。然而,我们也在神经网络中使用线性激活函数。例如,我们在解决回归问题的神经网络模型的输出层中使用线性激活函数。一些激活函数由两个或三个线性分量组成。这些函数也被归类为非线性函数。
区分线性和非线性函数将是有用的。一个线性函数(称为 f )接受输入 z 并返回输出 cz ,它是输入与常数 c 的乘积。数学上,这可以表示为 f(z) = cz 。当 c=1 时,函数按原样返回输入,不对输入进行任何更改。线性函数的图形是一条单一直线。
任何非线性函数都可以归类为非线性函数。非线性函数的图形不是一条直线。它可以是一个复杂的模式,也可以是两个或多个线性组件的组合。
不同类型的激活功能
我们将讨论神经网络中常用的激活函数。
1.Sigmoid 激活函数
Sigmoid 激活函数(图片由作者提供,用 latex 编辑器和 matplotlib 制作)
主要特性:
- 这也称为逻辑回归模型中使用的逻辑函数。
- sigmoid 函数有一个 s 形的图形。
- 显然,这是一个非线性函数。
- sigmoid 函数将其输入转换为 0 到 1 之间的概率值。
- 它将较大的负值转换为 0,将较大的正值转换为 1。
- 对于输入 0,它返回 0.5。值 0.5 被称为阈值,其可以决定给定的输入属于哪两类。
用法:
- 在早期,sigmoid 函数被用作 MLPs、CNN 和 RNNs 中隐藏层的激活函数。
- 然而,在 RNNs 中仍然使用 sigmoid 函数。
- 目前,我们通常不将 sigmoid 函数用于 MLPs 和 CNN 中的隐藏层。相反,我们在那里使用 ReLU 或 Leaky ReLU。
- 当我们构建二元分类器时,必须在输出层使用 sigmoid 函数,在该分类器中,根据函数返回的输入的概率值,将输出解释为类标签。
使用 sigmoid 函数的二元分类(图片由作者提供,用 draw.io 制作)
- 当我们构建多标签分类模型时,使用 sigmoid 函数,在该模型中,每个相互包含的类有两个结果。不要将这与多类分类模型相混淆。
【sigmoid 函数多标签分类(图片由作者提供,用 draw.io 制作)
弊端:
由于以下缺点,我们通常不在隐藏层中使用 sigmoid 函数。
- sigmoid 函数存在梯度消失的问题。这也被称为梯度的饱和。
- sigmoid 函数收敛较慢。
- 它的输出不是以零为中心的。因此,这使得优化过程更加困难。
- 由于包含了 e^z 项,该函数的计算量很大。
2.Tanh 激活函数
Tanh 激活函数(图片由作者提供,用 latex 编辑器和 matplotlib 制作)
关键特性:
- 双曲正切函数的输出范围总是在-1 和+1 之间。
- 像 sigmoid 函数一样,它有一个 s 形图形。这也是一个非线性函数。
- 使用双曲正切函数优于 sigmoid 函数的一个优点是双曲正切函数以零为中心。这使得优化过程更加容易。
- 双曲正切函数比 sigmoid 函数具有更陡的梯度。
用法:
- 直到最近,tanh 函数被用作 MLPs、CNN 和 RNNs 中隐藏层的激活函数。
- 然而,在 RNNs 中仍然使用 tanh 函数。
- 目前,我们通常不为 MLPs 和 CNN 中的隐藏层使用 tanh 函数。相反,我们在那里使用 ReLU 或 Leaky ReLU。
- 我们从不在输出层使用双曲正切函数。
弊端:
由于以下缺点,我们通常不在隐藏层中使用双曲正切函数。
- 双曲正切函数有消失梯度问题。
- 由于包含了 e^z 项,该函数的计算量很大。
3.ReLU 激活功能
ReLU 激活函数(图片由作者提供,用 latex 编辑器和 matplotlib 制作)
主要特性:
- ReLU(RectivedLlinearUnit)激活函数是 sigmoid 和 tanh 激活函数的一个很好的替代品。
- 发明 ReLU 是深度学习取得的最重要突破之一。
- 这个函数没有消失梯度的问题。
- 这个函数的计算开销很小。认为 ReLU 的收敛速度比 sigmoid 和 tanh 函数快 6 倍。
- 如果输入值为 0 或大于 0,ReLU 函数按原样输出输入。如果输入小于 0,ReLU 函数输出值 0。
- ReLU 函数由两个线性分量组成。因此,ReLU 函数是分段线性函数。实际上,ReLU 函数是一个非线性函数。
- ReLU 函数的输出范围可以从 0 到正无穷大。
- 收敛速度比 sigmoid 和 tanh 函数快。这是因为 ReLU 函数对于一个线性分量具有固定导数(斜率),而对于另一个线性分量具有零导数。因此,使用 ReLU 功能,学习过程要快得多。
- 使用 ReLU 可以更快地执行计算,因为函数中不包含指数项。
用法:
- ReLU 函数是现代 MLP 和 CNN 神经网络模型中隐藏层的默认激活函数。
- 我们通常不在 RNN 模型的隐藏层中使用 ReLU 函数。相反,我们使用 sigmoid 或 tanh 函数。
- 我们从不在输出层使用 ReLU 函数。
缺点:
- 使用 ReLU 函数的主要缺点是它有一个垂死的 ReLU 问题。
- 积极面的价值可以非常高。这可能导致训练期间的计算问题。
4.泄漏 ReLU 激活功能
Leaky ReLU 激活函数(图片由作者提供,用 latex 编辑器和 matplotlib 制作)
主要特点:
- 泄漏 ReLU 激活函数是默认 ReLU 函数的修改版本。
- 和 ReLU 激活函数一样,这个函数没有消失渐变的问题。
- 如果输入值是大于 0 的 0,leaky ReLU 函数就像默认 ReLU 函数一样输出输入。但如果输入小于 0,leaky ReLU 函数输出一个由 αz 定义的小负值(其中 α 为小常数值,通常为 0.01, z 为输入值)。
- 它没有任何导数为零的线性分量(斜率)。因此可以避免将死的 ReLU 问题。
- 使用泄漏 ReLU 的学习过程比默认 ReLU 更快。
用法:
- ReLU 函数的相同用法也适用于泄漏 ReLU 函数。
5.参数 ReLU (PReLU)激活功能
主要特性:
- 这是 ReLU 函数的另一个变体。
- 这几乎类似于泄漏的 ReLU 函数。唯一的区别是值 α 变成了一个可学习的参数(因此得名)。我们将 α 设为网络中每个神经元的参数。所以 α 的最优值是从网络中学习的。
6.ReLU6 激活功能
ReLU6 激活函数(图片由作者提供,用 latex 编辑器和 matplotlib 制作)
主要特点:
- ReLU 和 ReLU6 之间的主要区别在于,ReLU 允许在正侧有非常高的值,而 ReLU6 在正侧限制为值 6。任何大于或等于 6 的输入值都将被限制为值 6(因此得名)。
- ReLU6 函数由三个线性分量组成。这是一个非线性函数。
7.Softmax 激活功能
Softmax 激活功能(图片由作者提供,用 latex 编辑器制作)
主要特点:
- 这也是一个非线性激活函数。
- softmax 函数计算一个事件(类)在 K 个不同事件(类)上的概率值。它计算每个类的概率值。所有概率的总和是 1,意味着所有事件(类)是互斥的。
用法:
- 我们必须在多类分类问题的输出层使用 softmax 函数。
使用 softmax 函数进行多类分类(图片由作者提供,使用 draw.io 制作)
- 我们从不在隐藏层中使用 softmax 函数。
8.二元阶跃激活函数
二进制步进激活函数(图片由作者提供,用 latex 编辑器和 matplotlib 制作)
关键特性:
- 该功能也被称为阈值激活功能。我们可以为阈值设置任何值,这里我们指定值为 0。
- 如果输入大于阈值,该函数输出值 1。如果输入等于或小于阈值,此函数输出值 0。
- 这会输出一个二进制值,0 或 1。
- 二元阶跃函数由两个线性分量组成。正因为如此,这个函数是一个分段线性函数。实际上,二元阶跃函数是一个非线性函数。
- 这个函数不是光滑函数。
用法:
- 实际上,我们通常不在现代神经网络模型中使用这个函数。
- 然而,我们可以用这个函数来解释理论概念,如“激发一个神经元”,“感知器的内部工作原理”。因此,阶跃函数在理论上是重要的。
9.身份激活功能
身份激活功能(图片由作者提供,用 latex 编辑器和 matplotlib 制作)
主要特性:
- 这也被称为线性激活函数。
- 当我们谈论激活函数时,这是唯一被认为是线性函数的函数。
- 该函数按原样输出输入值。不会对输入进行任何更改。
用法:
- 此函数仅用于解决回归问题的神经网络模型的输出层。
带恒等函数的回归(图片由作者提供,用 draw.io 制作)
- 我们从不在隐藏层中使用标识函数。
10.Swish 激活功能
Swish 激活功能(图片由作者提供,用 latex 编辑器和 matplotlib 制作)
主要特性:
- 该函数由 sigmoid 函数乘以输入 z 构成。
- 这是一个非线性函数。
- 该图非常类似于 ReLU 激活函数的图。
- 曲线比 ReLU 激活函数更平滑。这种平滑度在训练模型时非常重要。函数在训练时容易收敛。
用法:
- 该功能仅用于隐藏层。
- 我们从不在神经网络模型的输出层使用这个函数。
缺点:
- Swish 函数的主要缺点是计算量大,因为函数中包含了 e^z 项。这可以通过使用下面定义的称为“硬刷”的特殊功能来避免。
11.硬嗖嗖(H-Swish)激活功能
硬 Swish (H-Swish)激活功能(图片由作者提供,用 latex 编辑器和 matplotlib 制作)
主要特点:
- 该图与 Swish 函数的图相同。
- 这在计算上是廉价的,因为 sigmoid 函数被线性模拟代替。
用法:
- 硬 Swish 的用法类似于 Swish 激活功能的用法。
摘要
激活函数只是数学函数。激活函数应该具有的主要特征是该函数应该是可微分的,因为这是模型训练中反向传播的要求。
选择正确的激活函数是主要的挑战,它可以被认为是一种超参数调整,其中程序员通过理解问题定义并考虑模型的性能和损失函数的收敛性来手动选择激活函数。
选择正确激活功能的一般准则
这里总结了上面讨论的不同激活功能的使用场景。当您训练自己的神经网络模型时,您可能会发现这很有用。
- 在神经网络的输入层节点中不需要激活函数。因此,在定义输入层时,您不需要担心激活函数。
- 输出层激活函数取决于我们想要解决的问题的类型。在回归问题中,我们使用一个节点的线性(恒等)激活函数。在二元分类器中,我们使用具有一个节点的 sigmoid 激活函数。在多类分类问题中,我们使用 softmax 激活函数,每个类一个节点。在多标签分类问题中,我们使用 sigmoid 激活函数,每个类一个节点。
- 我们应该在隐藏层中使用非线性激活函数。通过考虑模型的性能或损失函数的收敛性来做出选择。从 ReLU 激活功能开始,如果你有一个垂死的 ReLU 问题,试试 leaky ReLU。
- 在 MLP 和 CNN 神经网络模型中,ReLU 是隐藏层的默认激活函数。
- 在 RNN 神经网络模型中,我们对隐藏层使用 sigmoid 或 tanh 函数。双曲正切函数具有更好的性能。
- 只有身份激活函数被认为是线性的。所有其他激活函数都是非线性的。
- 我们从不在隐藏层中使用 softmax 和 identity 函数。
- 我们只在隐藏层中使用 tanh、ReLU、ReLU 的变体、swish 和 hard swish 函数。
- 最近的研究发现了 swish 和 hard swish 函数。
今天的帖子到此结束。感谢阅读!
通过 订阅我的 邮箱列表 ,再也不会错过一个精彩的故事。我一点击发布按钮,你就会在收件箱里收到每一篇文章。
如果你愿意,你可以 注册成为会员 来获得我写的每一个故事的全部信息,我将会收到你的一部分会员费。
一如既往,祝大家学习愉快!
鲁克山普拉莫迪塔
2022–01–19
2022 年如何选择合适的数据科学岗位
原文:https://towardsdatascience.com/how-to-choose-the-right-data-science-position-in-2022-f940efd0a10a
意见
选择毕业生、职业改变者或当前数据科学家的职位
蜜桃红·坎普斯·菲利佩在 Unsplash 上的照片
当你在寻找数据科学领域的工作时,无论你是一名有经验的候选人,一名新毕业生,还是一名转行者,都有很多事情要考虑。这是一个多步骤的过程,有多种类型的面试,既令人不知所措,又令人生畏。你从哪里开始?
像任何其他事情一样,要获得一份数据科学家的工作,你必须迈出第一步,对于数据科学求职来说,这个过程的第一步就是瞄准正确的职位。
锁定正确的职位对于缩小你的搜索范围和找出你最需要的技能是至关重要的。在这篇文章中,我将研究两种类型的数据科学职位的一些特征,分析驱动和算法驱动的职位,以及这些角色是否适合你。
这篇文章将回答三个主要问题。
- 数据科学家职位有哪些类型?
- 它们之间有什么区别?
- 你怎么知道哪个适合你?
如果你想了解这个话题,但你更喜欢看而不是读,你可以去我的 YouTube 频道看我关于这个话题的视频。
我们开始吧!
目录
寻找目标位置
我说的找到你的目标位置是什么意思?你可能认为数据科学家是你的目标职位。然而,数据科学是一个相当广阔的领域。在这个更大的保护伞下有许多职位,如数据分析师、应用科学家和研究科学家。为了让你的求职和准备工作更容易管理,你需要缩小搜索范围,找到适合你的职位。
为此,你首先需要了解不同类型的数据科学家职位。这些类型决定了面试过程的样子,也决定了一个有竞争力的候选人的标准。
如果我们想要非常全面,我们可以将所有数据科学家职位分为四种类型:分析、算法、统计和工程。数据科学家职位的这种分类在我的另一篇博客文章 中进行了总结:面试你的第一份数据科学家工作:期待什么以及如何准备 ,其中包括不同类型职位的详细描述和示例。这四种类型今天仍然适用于大多数科技公司。
出于这篇博客的目的,我将更深入地研究两种类型:分析和算法。这两个角色是最受欢迎的,我知道你们大多数人都在寻找符合这两个类别的职位。
其他两种类型的数据科学家角色,统计和工程,在数据科学家头衔下相对少见。此外,对数据科学家工程角色的要求可能与数据工程师角色非常相似,所以我不打算在这篇文章中涉及这一点。
因此,总的来说,我们将数据科学家的职位分为两类——分析驱动的和算法驱动的。分析驱动的职位包括数据分析师、产品分析师、数据科学家-分析和产品数据科学家。算法驱动的职位包括数据科学家-算法、数据科学家-机器学习以及其他与“科学家”相关的头衔,如应用科学家或研究科学家。****
在我们深入探讨这两种职位之间的差异之前,我想强调的是,在成熟的科技公司,这两种职位之间的差异要明显得多。像 Meta、Lyft、Airbnb 和网飞这样的大公司拥有庞大而成熟的数据科学团队,他们将团队中的各种职位分为分析驱动和算法驱动两类。
然而,较小的公司,尤其是初创公司,可能会有更灵活的数据科学家角色,更多的是两者的结合。
现在让我们深入这两种立场,了解它们的异同。
分析驱动的角色
让我们从分析驱动的角色开始。这种类型的角色可能涉及许多不同的事情,例如查看日志、用户数据和系统性能数据等。这些数据科学家将能够通过基于数据的详细调查提出建议来推动业务决策。****
这是一个技术性的角色,但也有很多交流。这包括帮助利益相关者做出明智的决策,执行探索性分析,定义业务指标,以及进行数据可视化,如仪表板。
让我们看看一些工作岗位,了解一下确切的要求。
首先,数据科学家——媒体技术在苹果公司的职位。苹果公司对这个职位的要求是:
- 有清晰表达和翻译问题的经验,并能运用统计技术,利用现有数据得出答案
- 数据查询技能( SQL 和/或 Spark 等)。)
- 具有使用用于数据处理和开发的脚本语言的经验(例如 Python、R 或 Scala)****
- 具有统计数据分析、多变量分析、 AB 测试和抽样方法的专业知识
- 强大的沟通和协作技能
- 自我激励,好奇心强,具有批判性思维能力和处理模糊问题的能力
很高兴拥有,但不是必需的:
- 理解机器学习算法,包括回归、聚类、分类和神经网络
- C、C++、ObjC 或 Swift 软件开发经验
(来源:https://jobs . apple . com/en-ca/details/200273199/data-scientist-media-technologies)**
乍一看,这是一个典型的入门级数据科学家职位。它没有指定的经验水平,但核心技能包括 SQL,数据处理和开发的脚本语言,统计数据分析的专业知识,以及 A/B 抽样方法。较强的沟通和协作技能也是期望的。
除了核心技能,其他技能都是 C,C++的软件开发经验。了解机器学习算法,包括回归聚类和分类,也会有所帮助。但是请注意,这些都是很好的,但不是硬性要求。
接下来我们有一个更高级的职位— 数据科学家,Meta 的分析。这份工作列出了以下最低要求。
- ****5 年以上数据科学实践经验,数据分析技能,愿意用数据弄脏自己的手
- SQL 、 Python 、 R 的专家知识
- 有与多个跨职能合作伙伴合作的经验,并能根据数据影响决策
- 有在最少指导下启动和推动项目完成的经验
- 实验- AB 测试
- 数学、统计学或相关技术领域的学士学位,或同等的实践经验。
(来源:https://www.metacareers.com/v2/jobs/652052339161686/)**
因此,Meta 正在寻找一个拥有五年以上数据操作经验的人。一个热爱数据工作并拥有高超数据分析技能的人。
该公告指出,所需的核心技能包括 SQL、Python 和 r 的专业知识。这是与各种利益相关者和决策者合作以更好地理解数据的经验之外的技能。具备 A/B 测试的实验知识也是一个优势。
这些是典型的分析驱动型职位的职位发布,通过比较他们的共同点,我们可以更多地了解对分析角色的期望。
他们都有与产品和业务相关的共同责任,例如:“产品愿景”、“产品创意”和“做出业务决策”。这些角色还经常提到与 A/B 测试相关的关键词,如:实验设计、假设检验等。
最后,大多数职位都强调精通 SQL。另一方面,你可能会发现,python、R、机器学习知识等脚本语言经常被列在 nice to have 类别下。
因此,总而言之,担任分析角色的数据科学家将使用他们的技术知识来收集数据,然后解释这些数据以帮助做出业务决策。你不仅需要技术知识,还需要沟通等软技能,才能在这种类型的角色中取得成功。
算法驱动的角色
接下来,我们有算法驱动的立场。这些角色也被称为数据科学家——机器学习。在这种类型的角色下,你仍然是一名数据科学家,但你不是致力于业务和产品洞察,而是经常致力于开发或改进机器学习模型,以实现各种商业目的,如进行预测。
在这个职位上,你将需要有更强的编码技能,因为你有时会被期望与软件工程师一起工作,部署模型或为模型训练建立管道。
为了更好地理解这种类型的角色,让我们来看一个典型的算法跟踪位置。微软数据科学家企业云职位。微软对这个职位的最低要求是:
- 硕士优先,高级学位和/或定量领域的行业经验,如数据科学,统计学,机器学习,应用数学,计算机科学
- 2 年以上相关分析工作经验,包括数据提取、分析和统计建模****
- 在校期间课外的分析活动也包括在内
- 熟练使用一种或多种编程或脚本语言,如 Python、C#或类似语言
- 在数据结构、问题解决、算法设计和复杂性分析方面有很强的基础
- 熟悉常见的机器学习、深度学习框架,如 Pytorch/Tensorflow
- 能够在多项目、快节奏的团队环境中有效协作和运输
- 在进入新领域和通过模糊性进行管理时自学的能力和动机
- 良好的口头和书面沟通技巧
职责:
- 对特殊云中多个来源的大量数据进行数据清理、丰富和分析
- 利用代码( Python 或类似代码)分析数据并构建统计和机器学习模型和算法
- 利用机器学习方法开发和测试新模型,运行计算实验和执行超参数调整****
(来源:https://careers.microsoft.com/us/en/job/1256345)**
微软正在寻找的核心技能包括建立统计、机器学习模型和算法,开发和测试新模型,运行计算实验和执行超参数调整。此外,您需要精通一种或多种编程或脚本语言,如 Python。
相比之下,这是数据科学家 Lyft 发布的另一个更有经验的职位——算法。根据招聘信息,该职位的职责包括:
- 5 年以上科技公司产品相关专业经验
- 与工程师、产品经理和商业伙伴合作,从数学角度和商业背景两个方面提出问题
- 执行探索性数据分析以深入了解问题
- 开发并适应统计、机器学习或优化模型
- 写入生产型号代码;与软件工程师合作,在生产中实施算法
- 设计和实施模拟和现场实验
- 分析实验和观察数据;交流调查结果;促进发布决策
(来源:https://startup.jobs/data-scientist-algorithms-lyft-1703961)**
它需要 5 年以上的专业经验。所需的核心技能是探索性数据分析、开发和拟合机器学习或优化模型。此外,您需要编写生产模型代码。
那么,这些帖子有什么共同点呢?首先,他们都强调机器学习,使用“机器学习方法”和“机器学习算法”等短语。你还会看到相关的关键词,比如“探索性数据分析”、“超参数调优”等。
你会发现这些角色还需要精通 Python 等脚本语言。另一方面,与分析角色不同,你不太可能找到关键词或强调开发业务洞察力、使用 SQL 或运行 A/B 测试实验。
因此,算法驱动的角色需要很强的技术技能,但不会让你经常做出商业决策或产品建议。
比较分析驱动和算法驱动的角色
乔恩·泰森在 Unsplash 上的照片
现在,我们已经了解了两种不同的角色和招聘信息,这两者之间有什么区别?只是一个角色和机器学习有关,另一个不相关吗?
这绝对是最大的区别。然而,这不是唯一的事情。分析驱动的路线更侧重于从数据中获得业务洞察力。虽然是技术岗位,但是软技能尤其重要。相比之下,算法驱动的赛道更注重技术。你应该在技术交付和与技术同事的合作上做更多的工作。
另一个需要注意的重要区别是分析驱动的途径往往有更多的工作需求。该角色是市场上最常见的数据科学家工作类型。虽然这并不意味着没有算法驱动的角色,但这是在选择目标职位时需要考虑的事情。
哪个职位适合你?
那么既然知道了区别,那么如何选择一个适合自己的岗位呢?你的兴趣当然是选择角色的一个重要因素。尽管如此,我还是想根据你的背景,对选择进行更客观的讨论。
有几年经验的数据科学家
假设你已经是一名有几年经验的数据科学家,你正在找工作,要么是因为你想换一家公司,要么是因为你想在一个不同的领域工作。对你来说,如果你能展示相关的行业经验,大多数科技公司的所有类型的数据科学职位都可以。
在一家初创公司工作,希望进入更大的公司
现在想象一下,你已经在一家初创公司的分析轨道上工作了两年。如果你想继续从事分析行业,但想跳槽到一家大型上市公司,比如谷歌(Google)或 Meta,你将有很大的机会在所有候选人中获得面试机会,因为你拥有他们想要的确切经验。
但是如果想换到算法或者机器学习的赛道呢?如果你能够证明你已经参与了与机器学习相关的项目,例如拥有处理特定数据和开发模型的第一手经验,你仍然有很大的机会成为有竞争力的候选人。
如果你一直在不断学习,比如获得在线硕士学位或参加在线课程,算法课程也可能适合你。因此,如果你有数据科学家的经验,你通常可以胜任任何一种职位。
新毕业生
如果你是一名新毕业生,没有任何工作或实习经验,该怎么办?在这种情况下,合适的职位类型将取决于你所完成的课程。
一般来说,如果你主修统计学或者你上过很多统计学课程,或者如果你从商学院毕业但上过与定量分析相关的课程,那么数据科学家分析轨道可能是你的最佳选择。
另一方面,如果你主修计算机科学,或者已经学习了大量的编码和机器学习课程,那么数据科学、算法/机器学习角色可能最适合你。
职业改变者
如果你是一个职业改变者呢?这些是我收到最多问题的人。我接触过的大多数转行者要么是从非技术岗位(如业务分析师或顾问)转行到数据科学家岗位。他们也可能从非科技公司,如保险公司或零售商店公司,转变为科技公司。在这种情况下,我的一般建议是专注于分析驱动的角色。
我给出这个建议有两个原因。首先,analytics track 的空缺数量最多。第二,由于你已经有了一些行业经验,产品知识和业务指标对你来说可能会变得非常直观,这是分析方向的一个关键要求。这会让你的过渡更加顺利。不是说转行很容易,但是需要的时间线和付出的努力绝对是需要考虑的关键因素。
如果你对机器学习有热情,并且花时间在编码方面打下基础,我不会阻止你去找算法驱动的职位。一般来说,如果你没有准备好这些技能,从头开始可能需要几个月甚至几年的时间。这就是为什么我一般不建议转行者走算法驱动的道路。****
结论
这就是为你找到合适的数据科学家职位所需要知道的一切!一旦你知道了目标职位,你就已经迈出了第一步,可以开始朝着获得一份数据科学家的工作迈进了。弄清楚你的目标是什么这个简单的行为会在你采取下一步行动时给你指引方向。
说到下一步,如果你想了解更多关于这个过程的下一步,获得面试,看看我在的博客上的后续文章。你也可以在我的频道上看那个话题的相应视频。
感谢阅读!
如果你喜欢这个帖子,想支持我…
- 订阅我的 YouTube 频道
- 跟我上 中 !
- 连接上 Linkedin !
- 前往emmading.com/resources获取更多关于数据科学面试技巧和策略的免费资源!
*** [## 第一份数据科学家工作的面试:期待什么以及如何准备
towardsdatascience.com](/interviewing-for-your-first-data-scientist-job-what-to-expect-and-how-to-prepare-1f3f9a977e14) ***
如何选择要处理的数据项目
原文:https://towardsdatascience.com/how-to-choose-which-data-projects-to-work-on-c6b8310ac04e
如果你有一个合理利用时间的方法,你可以优化你创造的价值
作为一名业务/数据分析师/科学家,经常会有过多的项目需要处理。知道如何选择正确的项目会对你的职业生涯和你工作的公司产生巨大的影响。
当你开始领导一个团队时,这一点变得尤为重要,但这不是通常教授的内容。在这篇文章中,我提供了一个简单的方法来对不同的项目进行排序,并决定在哪些项目上投入时间。
#1:了解数据世界的现实
- 很多项目没有转化为现实生活中的影响。几年前,Gartner 估计 60%的大数据项目会失败。这个数字后来被认为过于保守,真实值接近 85% [1]。相反,几个项目就能产生巨大的影响。
- 选择一个数据项目(并在其中投入时间)与投资一家初创公司非常相似——你可以有几个“获奖项目”和许多无法上市的项目。使用这种观点可以帮助你建立自己的时间投资理论,并确保优化你创造的价值。
数据项目的时间投资矩阵(图片由作者提供)
#2:给你的潜在项目打分
- 成功概率:这个项目成功的可能性有多大?我所说的成功是指——将对现实生活产生影响,也就是说,将引发变化,而这些变化可以归因于您的项目?
- 影响:这个项目的影响有多大?你的项目能为公司赚多少钱?
- 时间:你需要多长时间来完成这个项目?你花在一个项目上的时间越多,留给其他人的时间就越少。
- (可选)学习:做这个项目你会学到什么?如果是 tie,考虑“长期投资”可能会很有意思——基本上这个项目会教会你/公司多少东西。
#3:定义你的时间投资理论和你的多样化策略
- 时间量:一个季度你能接手多少项目?根据你在公司的经验,或者如果你正在管理一个团队,这种情况可能会彻底改变。
- 风险偏好:你对风险的接受程度如何?你更喜欢稳扎稳打,还是可以接更多本来就有风险的项目?
- 根据以上所述,你如何最大化你的影响力?你会选择一些高回报、高风险的项目,还是会选择很多回报有保证的小项目?
真实场景的例子
让我们假设您正在为一家客户关系管理(CRM)公司工作,并且您正在支持业务团队的数据需求。您从以下五个问题开始第三季度:
- #1:仪表板提问:销售团队想要一个仪表板来跟踪特定产品的销售情况。这个问题非常简单,但是由于这是一个将由多个利益相关方使用的仪表板,因此达成一致将非常耗时。
- #2:推销提问:合作伙伴管理团队正在组织一次推销,以将一个重要客户转化为更高价位的客户,希望您的帮助。这个问题也很简单,只需要几天时间。这项任务的影响不一定重要,但你相信如果你找到一种方法来实际衡量这个要求,可能会有一些潜力。
- #3:排名提问:收购团队希望更聪明地确定他们的潜在客户,并希望您能根据他们转化为付费客户的可能性对他们的潜在客户进行排名。他们目前使用的模型非常简单,你相信有很多事情可以做。这样一个项目的影响可能是惊人的,但建立一个模型并获得内部的认同将需要大量的工作。
- # 4:A/B 测试提问:销售团队(再次)尝试一种新的销售方法,并希望帮助他们建立一个实验来了解潜在的影响。从你收集的信息来看,这并不是一个真正的破坏性变化——如果有影响的话,应该是相当渐进的——而且从你做的快速功效分析来看,这个实验很有可能没有返回任何具有统计意义的结果。但是这个团队仍然想要完成它。
- #5:“新指标”提问:。您的管理层希望开发一种新的“活动流失率”指标,即一种跟踪客户何时停止使用产品的指标,以便合作伙伴管理团队能够尽快接触到这些“有风险”的客户。该项目似乎很有趣,但是快速的内部文献回顾显示,该团队在过去几年中已经试图建立这样的指标,但每次都失败了(主要是由于内部政治)。
根据您从所有不同项目中收集的背景信息以及您对自己能力的评估,您对每个项目的评分如下:
项目记分卡示例(图片由作者提供)
这允许您构建以下图表,其中 x=时间承诺,y=期望值:
时间承诺 x 期望值矩阵(图片由作者提供)
由此看来,你应该优先考虑 3 个项目:排名项目,销售项目和仪表板项目。
现在,如果你有时间做所有这些项目,一切都好!但如果没有,这就是你的“时间投资”论点发挥作用的地方——它将帮助你在这些“关系”中做出决定,并得出最终清单。现在你已经为这个季度做好了一切准备!
注意:上表中的所有数字都应该基于你自己对情况的理解、你的能力以及你的投资论文。对于两个从事相同项目的不同的人来说,这个表格会有很大的不同——这个框架只是让你合理化你的决策过程的一种方式。
改善决策过程的其他技巧
- 寻找跨职能合作的项目。最终,您项目的成功取决于它是否会被实施/使用(这部分不是在您的控制之下)。尽早与不同的利益相关者达成一致非常重要,这样才能确保成功。
- 寻找时机合适的项目。优秀的足球运动员会跟着球走——当球落地时,最好的足球运动员已经在那里了。了解你所在行业的发展方向,并坚持到底。
- 深入了解赢家。有时候,加倍投资成功的项目比从头开始另一个项目或试图修复一个失败的项目更容易、更有影响力。在确定优先顺序时要冷酷无情。
- 在每个季度末回顾你的投资策略。了解自己做得好(或做得不好)的地方,不断改进策略。
你会给这份清单添加什么吗?在评论里告诉我吧!
感谢阅读!
如果你觉得“有趣”,可以看看我的其他文章:
https://medium.com/@jolecoco/what-training-at-the-gym-teaches-you-about-training-models-931e5878dc14 https://medium.com/@jolecoco/the-art-of-turning-fuzzy-concepts-into-operational-metrics-part-1-9140b79d54b2
如何清理乱七八糟的熊猫栏目名称
原文:https://towardsdatascience.com/how-to-clean-messy-pandas-column-names-20dc7400cea7
不需要正则表达式
动机
真实世界的数据是混乱的。我们经常收到来自不同列命名格式的多个来源的数据,对它们进行标准化可能是一件麻烦的事情。尽管有这些麻烦,但在数据清理过程的早期将列名标准化为通用格式仍然很重要,以便更好地促进下游任务。正则表达式通常用于清理混乱的列名,但是编写正则表达式来处理各种混乱的情况可能会很乏味。这就是史基比出现的时候。
不足的
skippy通常用于提供熊猫数据框架中变量的汇总统计数据。然而这不是我们今天感兴趣的。Skimpy 的一个较少使用的函数是clean_columms
便利函数,它有助于解决熊猫列名混乱的问题。
Skimpy 为标准化列名提供了一些常见的格式。下表显示了不同案例样式的结果列名。这些大小写样式在使用的大小写和分隔符方面有所不同。
作者图片
让我们看看如何使用 skimpy 来执行列名清理。
安装 Skimpy
pip install skimpy
导入库
import pandas as pd
from skimpy import clean_columns
让我们创建一个玩具数据集来看看 Skimpy 是如何工作的。
columns = ['_Customer__name',
'customer_génder',
'customer age',
'billingAddress',
'delivery** address ',
'item(Description)',
'quantity/Volume',
'total.price']
messy_df = pd.DataFrame(data = [], columns=columns, index=[0])
我们的玩具数据集具有混乱的列名的常见元素,包括重音符号、不同的分隔符、大小写和多个空格。
作者图片
蛇案
skimpy 标准化的默认格式是snake
case 样式。蛇形大小写样式用下划线替换空格和符号分隔符,并将所有字符转换为小写。
clean_df = clean_columns(messy_df)
clean_df.columns.tolist()>>
['customer_name',
'customer_gender',
'customer_age',
'billing_address',
'delivery_address',
'item_description',
'quantity_volume',
'total_price']
烤肉串盒
kebab
大小写样式类似于 snake 大小写,除了它使用破折号分隔符而不是下划线。
clean_df = clean_columns(messy_df, case = 'kebab')
clean_df.columns.tolist()>>
['customer-name',
'customer-gender',
'customer-age',
'billing-address',
'delivery-address',
'item-description',
'quantity-volume',
'total-price']
骆驼箱
Camel
大小写样式开始使用大写字符作为分隔符,每个字符串的第一个字符是小写的。
clean_df = clean_columns(messy_df, case = 'camel')
clean_df.columns.tolist()>>
['customerName',
'customerGender',
'customerAge',
'billingAddress',
'deliveryAddress',
'itemDescription',
'quantityVolume',
'totalPrice']
帕斯卡案例
Pascal
除了每个字符串的第一个字符是大写字母之外,大小写样式类似于 camel case。
clean_df = clean_columns(messy_df, case = 'pascal')
clean_df.columns.tolist()>>
['CustomerName',
'CustomerGender',
'CustomerAge',
'BillingAddress',
'DeliveryAddress',
'ItemDescription',
'QuantityVolume',
'TotalPrice']
恒定情况
Constant
大小写样式使用下划线分隔符,并将所有字符改为大写。
clean_df = clean_columns(messy_df, case = 'const')
clean_df.columns.tolist()>>
['CUSTOMER_NAME',
'CUSTOMER_GENDER',
'CUSTOMER_AGE',
'BILLING_ADDRESS',
'DELIVERY_ADDRESS',
'ITEM_DESCRIPTION',
'QUANTITY_VOLUME',
'TOTAL_PRICE']
替换字符串
clean_columns()
还提供替换字符串的选项。这对于纠正拼写错误的列名或将列重命名为标准格式非常有用。例如,我们可能希望将Address
缩短为Addr
,将Description
缩短为Desc
clean_df = clean_columns(messy_df, case = 'pascal', replace = {'Address':'Addr', 'Description':'Desc'})
clean_df.columns.tolist()>>
['CustomerName',
'CustomerGender',
'CustomerAge',
'BillingAddr',
'DeliveryAddr',
'ItemDesc',
'QuantityVolume',
'TotalPrice']
结论
处理混乱的列名是数据科学工作流的一部分,对于具有大量列和不同命名格式的数据集来说,这可能相当乏味。在本文中,我们研究了如何在不使用 regex 的情况下,使用 skimpy 将列名快速标准化为不同的常见大小写样式。
加入 Medium 阅读更多这样的故事。
如何在 Python 中清理数据
原文:https://towardsdatascience.com/how-to-clean-your-data-in-python-8f178638b98d
关于如何清理你的数据以启动你的个人项目的详细指南
在 Unsplash 上由Towfiqu barb huya拍摄的照片
当我参加大学的定向阅读项目(一个小型研究项目,本科生由研究生指导)时,我只修了 R 课程的两个统计学。虽然这些课程教会了我很多关于如何操作数据、创建数据可视化和提取分析的知识,但在这个项目中从事我的第一个个人项目让我意识到我从未处理过“杂乱的数据”。这些课程涉及预先清理和处理的数据集,但没有教学生如何清理数据集,这为开始个人项目制造了障碍。因此,我希望这篇文章可以作为一个起点,让你学会如何有效地清理你的数据来启动你的个人项目。
在这篇文章中,我将使用 网飞电视节目和电影数据集 ,其中有许多不一致和缺失的数据。
目录
- 调查你的数据
- 看缺失数据的比例
- 检查每列的数据类型
- 如果有多列字符串,检查尾随空格
- 处理缺失值 (NaN 值)
- 从数据集中提取更多信息以获得更多变量
- 检查各列的唯一值
除特别注明外,所有图片均为作者所有。
第一步:调查你的数据
在对数据集执行任何清理或操作之前,您应该浏览一下您的数据,以了解您正在处理的变量,这些值是如何基于它们所在的列来构造的,也许您可以对需要解决的不一致之处有一个粗略的想法,否则它们在分析阶段会很麻烦。在这里,根据您想要进行的分析,您还可以删除某些不需要的列。
1.打印数据集的前几行
这里,我打印了数据集的前 7 行,但是您可以打印 5 行或 10 行。我建议将它保持在 10 以下,否则对于您当前正在尝试做的事情来说,它会太过沉重——快速浏览数据集。
这样做可以让您很好地了解可能要处理的数据类型、需要执行转换或清理的列,以及能够提取的其他数据。
在我们更仔细地看这个之前,让我们执行下一步。
2.将变量保存到列表中
您希望这样做是为了让能够方便地访问数据集的不同列,尤其是当您希望对不同的列子集执行相同的转换时。
3.在每一栏中记下你必须解决的潜在问题。
为了保持条理,请注意您在数据集中看到的问题(通过像在步骤 1 中一样浏览您的数据集)。
上面的这张图片代表了我瞥一眼数据集所能看到的,也是你在查看数据集时应该考虑的事情。这里有几件事让我印象深刻:
- 有些列缺少值。如果不在过程的早期处理和解决,这可能会给分析和绘图带来许多问题。
- 有带文字和数字的栏目,比如
date_added
、duration
。如果我们想按日期制作时间序列图或其他图来探索持续时间与其他变量的关系,这可能是个问题。 - 有两列包含由逗号连接在一起的多个不同的单词。如果我们想制作剧情探索
**listed_in**
(流派)的分布或者网飞上的演员,这是一个问题。 - 其他列可能会丢失值。下一步看如何用检查哪些列有缺失值和它们有多少缺失数据。
第二步:看缺失数据的比例
从这段代码中,您可以很容易地查看数据集中缺失值的分布,从而很好地了解需要处理哪些列来解决缺失值问题。
从输出中,您可以收集到以下见解:
director
列丢失数据的百分比最高,约为 30%cast
和country
列也有相当比例的缺失数据~ 9%date_added, rating
和duration
没有那么多缺失数据~ 0% - 0.1%- 幸运的是,大多数其他列都不是空的。
你的下一个问题可能是,我如何处理这些缺少值的列?
有几种方法可以处理它:
- 完全删除该列。如果这个专栏对你的分析不是那么重要,那就放弃它。
- 保持纵队。在本例中,因为的
**director, cast**
和**country**
列对我的分析相当重要,所以我将保留它们。 - 插补——用替代值替换缺失数据的过程。在这里,这样做是不可能的,因为大多数数据是字符串值,而不是数值。然而,我将会写一篇文章,更详细地讨论插补,为什么和什么时候应该使用它,以及如何在 R 和 Python 中借助一些包来使用它。
在我继续之前,我将提出跨行丢失值的问题。
在某些情况下,您可能想要检查数据集的所有行中缺失值的分布(假设您的数据集没有大量的观察值/行)。从这里,你可以根据这些行对你的分析的重要性从上面的选项中选择。例如,数据集包含随时间变化的记录数据。即使一行可能包含丢失的值,您也可能不希望删除它,因为您希望保留重要的时间信息。
在我向您展示如何处理 NaN 值之前,让我们继续第 3 步,即使是在保留列之后。
步骤 3:检查每一列的数据类型
在这里,您可以看到除了release_year
之外,所有的列都将object
作为它们的数据类型。在 pandas 中,object 表示字符串或混合类型(数值和非数值类型混合)。从我们的数据集中,您将能够判断哪些列是严格的字符串和混合类型。
步骤 4:如果你有字符串列,检查尾随空格
在我们知道我们正在处理的数据类型之后,让我们确保使用strip
删除任何尾部字符和空白。
步骤 5:处理缺失值(NaN 值)
回到缺失值的列,我们来看看这些列:director, cast, country, date_added, rating, duration
。我们可以根据这些列是字符串类型还是混合类型来对它们进行分段。
String: director, cast, country, rating
(这里是一个字符串,不能混合,因为数值分开就没有任何意义)
混装:date_added, duration
NaN
在熊猫中表示不是数字。它是一个特殊的浮点值,不同于 Python 中的NoneType
。NaN
处理数值可能会很烦人,尤其是当你想过滤掉它们用于绘图或分析的时候。为了让我们的生活更容易,让我们用别的东西代替这些 NaN 值。
对于字符串类型的值,我们可以用""或" None "或任何可以向您表明该条目中没有任何值的字符串来替换NaN
值。在这里,我使用fillna
函数将它替换为“”。因为它不是一个就地函数,所以我将更改后的值重新分配给数据集中的列。
在这里,您一定注意到我遗漏了持续时间列。这是因为我们稍后将对该专栏做一些事情。
第六步:看看是否有其他变量,你可以从其他变量中提取出来
对于混合类型的值,在我们处理缺失值问题之前,让我们看看是否可以提取一些数据来使我们的分析更丰富或处理更容易。
查看date_added
,我们可以看到它包含了电影/节目被添加的月份、日期和年份。与其将所有这些信息放在一列,为什么不试着将它们分开呢?这样,我们可以选择隔离月或年如何与其他变量交互,而不是查看date_added
,因为它的粒度会使任何趋势都难以发现。
下面,我编写了代码,不仅将信息分成另外两列,还过滤掉了带有NaN
值的行,并用 0 替换它们,就像之前用""做的一样。
现在,新的数据集包含了month_added
和year_added
列。这将允许我们稍后进行一些趋势分析。
看一下duration
,除了它是一个混合类型之外,在这个列中还有 2 个不同的时间单位。这是一个问题,因为我们处理的是两种不同类型的内容,它们的时间度量不同。因此,如果我们保持原样,制作duration
的图表将很难理解。好的一面是有很多方法可以处理这个问题。我选择的处理方式是通过将内容类型分为两个不同的数据集,自然,持续时间列将只是数字,只有一种时间单位。通过这种方式,您可以轻松清晰地使用这些值进行绘图。
因为duration
列既有字符串又有数字,我还必须创建一个函数来从该列中提取数字,以便可以将它插入到两个新数据集的列中。
步骤 7:检查列的唯一值
除了可能丢失的值之外,一旦执行分析,可能会遇到损坏的值。为了检查这一点,我们可以检查一些列的唯一值。让我们以数据集的前 5 行作为起点。
检查所有列的唯一值,尤其是标题、导演和演员,可能不是一种策略,因为可能有大量的唯一值需要检查。相反,让我们关注一个潜在唯一值的列表,这些值可能更容易检查,也更重要,因为它对未来的分析可能更有洞察力。粗略地看一下数据集,列country, rating, listed_in
可能是感兴趣的。让我们先检查评级栏,因为这似乎是处理起来最简单的一个。
使用 Python 的内置函数unique
,可以很容易地获得类似 rating 的列的唯一值。让我们试试那个!
这似乎很有趣。为什么电影分级的独特类型中有 74 分钟、84 分钟和 66 分钟?还有为什么会有 UR(未评级)和 NR(未评级)?它们的意思不是一样的吗?让我们通过提取具有这些奇怪条目的行来进一步研究这个问题。
使用这个代码块,我们可以看到 3 个不同的行包含这个奇怪的评级,它实际上属于 length 列。我们还可以看到问题所在的行号,这将有助于修复条目。
在快速搜索之后,我们可以通过将“错误评级”(实际上是持续时间)移到“长度”栏并输入正确的评级来修复这些条目。
对于 rating 列中的 UR 和 NR 值,我们应该在netflix_shows
数据集中使用 NR 的地方保持一致性,并将 UR 值改为 NR。
现在我们已经清理了rating
列,让我们看看国家和listed_in
列。到目前为止,您一定已经意识到提取唯一值不像rating
列那么容易。这是因为这些列中的值是由逗号连接在一起的单词,这使得提取单词集并从中找到唯一的单词变得更加困难。
我们将如何解决这个问题是通过为这个特例实现一个独特的函数。
首先,让我们思考一下什么样的数据结构可以轻松地赋予我们唯一的值。如果你猜对了,那你就对了!考虑到它的能力以排序的顺序存储相同类型的独特元素,这是一个适合我们想要做的数据结构。
然后,为了提取那些用逗号连接的单词,我们可以使用split
函数来用逗号分割字符串。
使用该函数后,我们可以很容易地获得country
和listed_in
列的唯一值。
接下来,让我们检查唯一国家的列表,看看是否有任何不一致或错误。通过这样做和一点谷歌搜索,我们可以看到这个列表有一些问题:
- 苏联和俄罗斯都有
- 西德/东德和德国都有
我们可以通过对数据集进行一些修改来轻松解决这个问题。
至于流派列表,我们可以看到有些流派我们可能不想或不需要包括在内。因此,我们可以很容易地将其从数据集中删除,以使我们的分析更少混淆。
在电视节目和电影数据集中,都有“电视节目”和“电影”类型。从技术上讲,这不是一个流派,但可能是内容类型的标签。为了证实这一点,我们应该打印出这些“流派”在各自数据集中出现的次数。
假设是,如果这些“流派”出现在数据集的所有行中,这意味着它们只是标签。否则,我们将不得不进一步调查这些“类型”代表什么。
因为“流派”的数量小于数据集的大小,所以让我们使用代码的输出来检查这些行。
因为我已经编写了专门输出列表中行索引的代码,所以我们可以很容易地使用该列表和iloc
函数来获得行的视图。
看一下这些行,现在很明显“电视节目”和“电影”类型被用来表示这些内容一开始就没有类型。既然我们理解了这意味着什么,我们可以选择在我们的分析中排除或包含它。在这里,我选择包括它,因为它不影响我的分析。
虽然这一步很繁琐,但它也很重要,因为它允许我们找到数据集中一眼看去隐藏的问题。
步骤 8:将清理后的数据集连接在一起以创建另一个数据集[可选]
这一步是可选的,但是如果你想把清理过的电视节目和电影数据集放在一个地方,你应该连接它们。
就是这样!您已成功清理此数据集。请记住,每个人都有自己的数据清理方法,其中很多都是通过努力理解数据集实现的。然而,我希望这篇文章能帮助你理解为什么数据科学家要花 80%的时间清理他们的数据集。非常严肃地说,这篇文章强调了数据清理的重要性,更重要的是,需要一个好的数据清理方法来帮助你保持你的工作有条不紊,如果你需要在分析过程中回头再看的话。你可以在这里查看完整的笔记本。
感谢阅读。你可以在LinkedIn和Twitter上查看我!
如何收集行为数据
原文:https://towardsdatascience.com/how-to-collect-behavioral-data-2a891fad6bc5
数据工程师和分析师指南
本帖所有图片均由作者创作
你的公司推出了一款新产品,而你的任务是建立行为数据基础设施?或者,您可能需要使用现代工具来改造现有的基础架构?
有几种不同的技术(CDI、CDP、ELT)可用于收集行为数据,同时,还有许多工具(Segment、Rudderstack、Airbyte 等)具有跨越多种技术的功能。
我知道在这个迷宫中穿行并做出明智的决定是令人生畏且耗时的。不过,你很幸运,在我担任 Integromat 增长主管期间,我花了大量时间做这件事,并在我建立探索数据工具的地方 astorik 时,继续跟踪所有新的数据工具和技术。
本指南的目标是介绍各种行为数据收集技术以及每种技术下的流行工具。但是首先,我想解释一下为什么行为数据很重要,以及它来自哪里。
为什么要收集行为数据?
行为数据是用户在与产品交互时执行动作或事件的结果,因此也被称为事件数据或产品使用数据。
行为数据为团队提供两个主要目的——了解产品如何被使用或不被使用(用户行为),以及在各种接触点建立个性化的客户体验以影响用户行为。
要了解产品的使用情况,需要事先对您想要测量其使用情况的功能进行检测,即跟踪用户执行的事件,并将这些事件发送给第三方工具进行分析。类似地,您需要跟踪事件,基于这些事件,您希望通过下游激活工具触发活动和体验。
启动新功能而不事先对其进行测试是一个典型的错误——它剥夺了分析这些功能如何使用(如果有的话)以及在相关事件发生(或不发生)时触发应用内体验或消息的机会。
行为数据从哪里来?
虽然我提到的事件发生在你的产品中,但是行为数据的实际来源可以是嵌入在你的产品中的外部工具或服务。出于对简单性的热爱,我喜欢将数据源分类为主要的和次要的。
主要数据源
您的核心产品— web 应用、移动应用、智能设备、或由专有代码驱动的组合 — 是主要或第一方行为数据源。
如果您的产品是使用无代码工具构建的,您将没有行为数据的主要来源——您将依赖无代码工具为您提供行为数据(通过 webhooks 或与数据收集工具的集成)。
要从主要来源收集数据,可以使用客户端和服务器端 SDK 或数据收集工具提供的 API。
次要数据源
二级数据源包括您的客户直接或间接与之交互的所有外部或第三方工具——用于认证、支付、应用内体验、支持、反馈、参与和广告的工具。
当第三方工具嵌入到您的核心产品体验中时,客户会间接地或不知不觉地与第三方工具进行交互。示例包括用于身份验证的 Auth0、用于支付的 Stripe 和用于应用内体验的 AppCues 从用户的角度来看,即使在与这些外部工具交互时,他们也在使用你的产品。
客户还与外部工具互动,这些工具显然不是核心产品体验的一部分,但却是不可或缺的接触点。通过 Zendesk 打开一张支持票,通过 Typeform 留下反馈,通过 Intercom 打开一封电子邮件,或者在脸书上做一个广告——这些都是有助于理解客户旅程的互动。
记住第三方工具会生成大量数据也很有帮助,但并不都是事件数据。就事件和对象而言,您究竟可以收集什么取决于您使用的数据收集工具所提供的集成。
要从二级来源收集数据,您可以使用数据收集工具提供的源集成,也可以编写自己的代码。
收集行为数据的技术和工具
就像现代数据领域的所有层一样,数据收集层在过去几年中经历了很多活动,推出了几个非常受欢迎的开源产品。
随着核心功能被扩展到覆盖相邻的用例,产品之间的重叠也在增加。
CDI 和 CDP 的区别
CDI 或客户数据基础设施是一个不太常见的术语,经常与 CDP 或客户数据平台混淆。
没有基础设施就没有平台—CDP 本质上是 CDI 之上的一层,它提供了一组功能,可以使用可视化界面对数据进行一些很酷的处理。
CDI 是一个独立的解决方案,没有 CDP 也可以存在,而 CDP 由一些 CDI 供应商作为附件出售。
CDI 的主要方面如下:
- CDI ( 客户数据基础设施)专门用于从主要或第一方数据源收集行为数据,但一些解决方案也支持少量次要数据源(第三方工具)。
- 数据通常同步到云数据仓库,如 Snowflake、BigQuery 或 Redshift,但大多数 CDI 解决方案也能够将数据同步到第三方工具。
- 所有 CDI 供应商都提供各种数据收集 SDK 和 API
- 一些 CDI 解决方案存储数据的副本,一些使其可选,一些则不。
CDP 的核心功能包括身份解析,以及用户使用拖放 UI(无需编写 SQL)构建受众并将其同步到外部工具的能力。
CDI 和 CDP 工具
关系和人物角色分别是细分市场的 CDI 和 CDP 产品。mParticle 采用了一种略有不同的方法,它在标准版中提供了 CDI 功能以及身份解析,而在高级版中则提供了受众培养功能。Segment 和 mParticle 都支持数据仓库和大量第三方工具作为目的地,并存储数据的副本,以便以后需要时可以访问。
RudderStack 事件流和 Jitsu 是开源的 CDI 解决方案,定位为分段连接的替代方案。这两种产品都支持仓库和第三方工具,但 RudderStack 提供了更广泛的目的地目录。
Snowplow 是唯一一个称自己为行为数据平台的 CDI 解决方案。它也是开源的,与其他产品不同,Snowplow 不支持第三方工具,因为它专注于仓库和一些开源项目作为目的地。
其他值得研究的 CDI 解决方案是 Freshpaint,它提供无代码或隐式跟踪,元路由器是一种服务器端 CDI,只在私有云实例中运行。
下面的链接将带您到各自工具的集成目录:
ELT 工具
ELT 工具专门用于从大量第三方工具(二级来源)中提取所有类型的数据,并将数据加载到云数据仓库中。也就是说,并非 ELT 工具提供的所有集成都支持行为数据或事件数据。
ELT 工具不存储任何数据,也不支持第三方工具作为目的地。
Airbyte 是一个开源的 ELT 工具,有一个不断增长的连接器库和一个繁荣的贡献者社区。Airbyte 提供了 150 多个工具的源连接器,如 Zendesk 、 Intercom 、 Stripe 、 Typeform 和脸书广告,其中许多工具都会生成事件数据。Airbyte 还提供了一个连接器开发包(CDK ),您可以使用它来构建由 Airbyte 社区成员维护的集成。
其他 ELT 供应商包括 Fivetran、Stitch 和 Meltano(也是开源的)。
如前所述,CDI 解决方案还提供了与一些第三方工具的源代码集成,但这些集成不如 ELT 工具提供的集成全面和深入。
在考虑是使用 ELT 工具还是 CDI 工具的源集成从第三方工具中提取数据时,请考虑以下几点:
- CDI 是从主要或第一方数据源(web 和移动应用程序以及物联网设备)收集行为数据的最佳选择
- ELT 是收集所有类型数据的最佳工具,包括来自二级数据源的行为数据,二级数据源是推动各种客户体验的第三方工具。
产品分析工具
Amplitude、Mixpanel、Indicative、Heap 和 PostHog(开源)是专门用于行为数据分析的工具。与此同时,所有这些都提供了 SDK 和 API 来从您的主要(第一方)数据源收集数据。
产品分析工具本质上存储了您的数据副本,并允许您导出数据(通常需要额外付费)。您还可以使用 Airbyte 与振幅、混合面板或后日志的集成,将数据从这些工具导出到 Airbyte 支持的目的地。
然而,重要的是要记住,除了分析之外,还有很多行为数据的激活用例。
作为一种最佳实践,公司必须建立一个数据仓库来存储他们收集的所有数据的副本——使用专门构建的数据收集工具(CDI 和 ELT)更有效,防止供应商锁定,并且更有意义。
定制跟踪解决方案
如果现成的解决方案不适合您,您可以随时构建一个定制的跟踪服务,从您的应用程序中收集数据,并将其同步到您的仓库和下游应用程序。也就是说,有了这种解决方案的第一手经验,我可以告诉你,维护和故障排除不是小事,挫折是真实的。
更重要的是,有这么多不同风格的 CDI 和 ELT 解决方案可用,构建自己的解决方案并不是对工程资源的最佳利用。事实上,工程师通常讨厌构建集成——你可能就是其中之一,所以如果我错了,请告诉我。
结论
CDI 工具是专门为行为数据构建的,我强烈建议采用一种工具从主要或第一方数据源收集数据,并坚持使用 ELT 工具从第二或第三方数据源收集数据。
既然您已经对收集行为数据以进行分析和激活所需的工具有了更好的了解,那么在决定跟踪哪些事件以及将哪些数据发送到哪个目的地时,不要忘记与各个团队的利益相关者进行协作。
如何比较两个或多个分布
原文:https://towardsdatascience.com/how-to-compare-two-or-more-distributions-9b06ee4d30bf
因果数据科学
比较分布的完整指南,从可视化到统计测试
封面图片,由作者使用nightcafe生成
比较变量在不同组中的经验分布是数据科学中的一个常见问题。特别是,在因果推断中,当我们不得不评估随机化的质量时,问题经常出现。
当我们想要评估一项政策(或 UX 特色、广告活动、药物……)的因果效应时,因果推断的黄金标准是https://en.wikipedia.org/wiki/Randomized_controlled_trial随机对照试验,也称为 A/B 测试 。在实践中,我们选择一个样本进行研究,并将其随机分为对照组和治疗组,并比较两组之间的结果。随机化确保两组之间的唯一差异是平均治疗,因此我们可以将结果差异归因于治疗效果。
T21 的问题是,尽管进行了随机分组,两组人永远不会完全相同。然而,有时候,他们甚至不“相似”。例如,我们可能在一个群体中有更多的男性,或者老年人,等等..(我们通常称这些特征为协变量或控制变量)。当这种情况发生时,我们不能再确定结果的差异仅仅是由于治疗,而不是由于不平衡的协变量。因此,在随机化之后,检查所有观察到的变量在各组之间是否平衡以及是否没有系统性差异总是很重要的。另一个选择是分层抽样,为了事先确定某些协变量是平衡的。
在这篇博文中,我们将看到比较两个(或更多)分布的不同方法,并评估它们之间差异的大小和重要性。我们将考虑两种不同的方法,视觉和统计。这两种方法通常在直觉和严谨之间进行权衡:从图中,我们可以快速评估和探索差异,但很难判断这些差异是系统性的还是由噪声造成的。
例子
让我们假设我们需要对一组个体进行一项实验,我们已经将他们随机分成了 T21 治疗组和对照组。我们希望它们尽可能具有可比性,以便将两组之间的任何差异仅归因于治疗效果。我们还将治疗组分成不同的组,用于测试不同的治疗方法(例如同一药物的微小变化)。
对于这个例子,我模拟了一个 1000 人的数据集,我们观察到他们的一系列特征。我从[src.dgp](https://github.com/matteocourthoud/Blog-Posts/blob/main/notebooks/src/dgp.py)
导入数据生成过程dgp_rnd_assignment()
,从[src.utils](https://github.com/matteocourthoud/Blog-Posts/blob/main/notebooks/src/utils.py)
导入一些绘图函数和库。
from src.utils import *
from src.dgp import dgp_rnd_assignment
df = dgp_rnd_assignment().generate_data()
df.head()
数据快照,图片由作者提供
我们有 1000 个人的信息,为此我们观察gender
、age
和每周income
。每个个体被分配到治疗组或对照组group
,接受治疗的个体被分配到四个治疗组arms
。
两组——地块
让我们从最简单的设置开始:我们想要比较treatment
和control
组的收入分布。我们首先探索视觉方法,然后统计方法。第一个的优势是直觉而第二个的优势是严谨。
对于大多数可视化,我将使用 Python 的[seaborn](https://seaborn.pydata.org/)
库。
箱线图
第一种视觉方法是 箱线图 。箱线图是汇总统计和数据可视化之间的一个很好的折衷。框的中心代表中位数,而边界分别代表第一(Q1)和第三四分位数 (Q3)。相反,须状物延伸到框外超过 1.5 倍四分位数间距 (Q3 — Q1)的第一个数据点。胡须外的点被单独标绘,通常被认为是 异常值 。
因此,箱线图提供了汇总统计数据(方框和胡须)和直接的数据可视化(异常值)。
sns.boxplot(data=df, x='Group', y='Income');
plt.title("Boxplot");
治疗组和对照组的收入分布,按作者分类
看起来treatment
组中的income
分布稍微分散一些:橙色的盒子更大,它的须覆盖的范围更广。然而,箱线图的问题在于它隐藏了数据的形状,告诉我们一些汇总统计数据,但不显示实际的数据分布。
柱状图
绘制分布图最直观的方式是直方图。直方图将数据分组到等宽的箱中,并绘制每个箱内的观察数量。
sns.histplot(data=df, x='Income', hue='Group', bins=50);
plt.title("Histogram");
治疗组和对照组的收入分布,按作者分类
这个情节有多个问题:
- 由于两组有不同数量的观察值,这两个直方图是不可比的
- 箱的数量是任意的
我们可以解决第一个问题,使用stat
选项来绘制density
而不是计数,并将common_norm
选项设置为False
来分别归一化每个直方图。
sns.histplot(data=df, x='Income', hue='Group', bins=50, stat='density', common_norm=False);
plt.title("Density Histogram");
治疗组和对照组的收入分布,按作者分类
现在两个直方图有可比性了!
然而,一个重要的问题仍然存在:箱子的大小是任意的。在极端情况下,如果我们将数据聚集得更少,我们最终会得到最多一个观测值的箱,如果我们将数据聚集得更多,我们最终会得到单个箱。在这两种情况下,如果我们夸大,情节就失去了信息性。这是一个经典的偏差-方差权衡。
内核密度
一种可能的解决方案是使用 核密度函数 ,该函数试图用连续函数近似直方图,使用核密度估计(KDE) 。
sns.kdeplot(x='Income', data=df, hue='Group', common_norm=False);
plt.title("Kernel Density Function");
治疗组和对照组的收入分布,按作者分类
从图中可以看出,income
的估计核密度在treatment
组中似乎具有“更厚的尾部”(即更高的方差),而各组之间的平均值似乎相似。
内核密度估计的问题是它有点像黑盒,可能会掩盖数据的相关特征。
累积分布
两个分布的更透明的表示是它们的 累积分布函数 。在 x 轴的每个点(income
),我们绘制了具有相等或更低值的数据点的百分比。累积分布函数的主要优点是
- 我们不需要做出任何任意的选择(例如,箱的数量)
- 我们不需要执行任何近似(例如,用 KDE),但是我们代表所有的数据点
sns.histplot(x='Income', data=df, hue='Group', bins=len(df), stat="density",
element="step", fill=False, cumulative=True, common_norm=False);
plt.title("Cumulative distribution function");
治疗组和对照组的累积收入分布,按作者分类的图像
我们应该如何解释这个图表?
- 由于两条线在 0.5 (y 轴)处交叉,这意味着它们的中值是相似的
- 由于橙色线位于左侧蓝线的上方和右侧蓝线的下方,这意味着
treatment
组的分布为较粗的尾部
Q-Q 图
一个相关的方法是Q-Qplot,其中 q 代表分位数。Q-Q 图绘制了两种分布的分位数。如果分布相同,我们应该得到一条 45 度线。
Python 中没有原生的 Q-Q plot 函数,尽管statsmodels
包提供了一个[qqplot](https://www.statsmodels.org/dev/generated/statsmodels.graphics.gofplots.qqplot.html)
函数,但它相当麻烦。所以,我们就手工做。
首先,我们需要使用percentile
函数计算两组的四分位数。
income = df['Income'].values
income_t = df.loc[df.Group=='treatment', 'Income'].values
income_c = df.loc[df.Group=='control', 'Income'].values
df_pct = pd.DataFrame()
df_pct['q_treatment'] = np.percentile(income_t, range(100))
df_pct['q_control'] = np.percentile(income_c, range(100))
现在我们可以绘制两个分位数分布图,加上 45 度线,代表基准完美拟合。
plt.figure(figsize=(8, 8))
plt.scatter(x='q_control', y='q_treatment', data=df_pct, label='Actual fit');
sns.lineplot(x='q_control', y='q_control', data=df_pct, color='r', label='Line of perfect fit');
plt.xlabel('Quantile of income, control group')
plt.ylabel('Quantile of income, treatment group')
plt.legend()
plt.title("QQ plot");
Q-Q 图,作者图片
Q-Q 图提供了与累积分布图非常相似的洞察:治疗组的收入具有相同的中值(线在中心交叉),但尾部更宽(点在左端线的下方,右端线的上方)。****
两组—测试
到目前为止,我们已经看到了不同的方式来可视化分布之间的差异。可视化的主要优势是直觉:我们可以观察差异并直观地评估它们。
然而,我们可能希望更加严谨并尝试评估分布之间差异的统计显著性,即回答问题“观察到的差异是系统性的还是由于采样噪声?”。
我们现在要分析不同的测试来区分两个分布。
t 检验
第一个也是最常见的测试是学生 t 测试。t 检验一般用于比较均值。在这种情况下,我们想要测试income
分布的平均值在两组中是否相同。两均值比较检验的检验统计量由下式给出:
t 检验统计,作者图片
其中 x̅ 是样本均值,而 s 是样本标准差。在温和条件下,检验统计量渐近分布为学生 t 分布。
我们使用来自scipy
的ttest_ind
函数来执行 t 检验。该函数返回测试统计和隐含的 p 值。
from scipy.stats import ttest_ind
stat, p_value = ttest_ind(income_c, income_t)
print(f"t-test: statistic={stat:.4f}, p-value={p_value:.4f}")t-test: statistic=-1.5549, p-value=0.1203
检验的 p 值为 0.12,因此我们不拒绝治疗组和对照组的无差异的零假设意味着。
****注意:t 检验假设两个样本中的方差相同,因此它的估计是在联合样本上计算的。韦尔奇的 t 检验允许两个样本中的不等方差。
标准化平均差(SMD)
一般来说,当我们进行随机对照试验或 A/B 试验时,最好始终对治疗组和对照组的所有变量进行均值差异测试。****
然而,由于 t-检验统计的分母取决于样本量,t-检验受到了批评,因为它使得 p 值很难跨研究进行比较。事实上,我们可能在差异非常小但样本量很大的实验中获得显著结果,而在差异很大但样本量很小的实验中获得不显著结果。
已经提出的一个解决方案是标准化平均差异(SMD)** 。顾名思义,这不是一个适当的测试统计,而只是一个标准化的差异,可以计算如下:**
标准化平均差异,作者图像
通常,低于 0.1 的值被认为是“小”差异。
良好的做法是收集所有治疗组和对照组变量的平均值,以及两者之间的距离测量值——t 检验或 SMD——到一个名为平衡表的表格中。我们可以使用[causalml](https://causalml.readthedocs.io/en/latest/about.html)
库中的[create_table_one](https://causalml.readthedocs.io/en/latest/causalml.html#module-causalml.match)
函数来生成它。正如这个函数的名字所暗示的,平衡表应该总是你在执行 A/B 测试时出现的第一个表。
from causalml.match import create_table_one
df['treatment'] = df['Group']=='treatment'
create_table_one(df, 'treatment', ['Gender', 'Age', 'Income'])
平衡表,作者图片
在前两列中,我们可以看到治疗组和对照组不同变量的平均值,标准误差在括号中。在最后一列中,SMD 值显示所有变量的标准化差异超过 0.1,表明两组可能不同。
曼恩-惠特尼 U 检验
另一种测试是曼-惠特尼 U 测试。此检验的零假设是两组具有相同的分布,而另一个假设是一组比另一组具有更大(或更小)的值。
与我们到目前为止看到的其他检验不同,Mann–Whitney U 检验对异常值不可知,并且集中于分布的中心。
测试程序如下。
- 合并所有数据点并对其进行排序(按升序或降序)
- 计算u₁=r₁n₁(n₁+1)/2,其中 R₁ 为第一组数据点的排名之和, n₁ 为第一组的点数。
- 为第二组类似地计算 U₂ 。
- 测试统计数据由 u₂).min(u₁给出
在两个分布之间没有系统性等级差异的零假设下(即,相同的中值),检验统计量是具有已知均值和方差的渐近正态分布。
计算 R 和 U 背后的直觉如下:如果第一个样本中的值都大于第二个样本中的值,那么 R₁ = n₁(n₁ + 1)/2 ,因此 U₁ 将为零(可达到的最小值)。否则,如果两个样本相似, U₁ 和 U₂ 将非常接近 n₁ n₂ / 2 (可达到的最大值)。
我们使用来自scipy
的mannwhitneyu
函数来执行测试。
from scipy.stats import mannwhitneyu
stat, p_value = mannwhitneyu(income_t, income_c)
print(f" Mann–Whitney U Test: statistic={stat:.4f}, p-value={p_value:.4f}")Mann–Whitney U Test: statistic=106371.5000, p-value=0.6012
我们得到的 p 值为 0.6,这意味着我们没有拒绝治疗组和对照组中income
分布相同的无效假设。
****注:关于 t 检验,对于两个样本中的不等方差存在一个版本的曼恩-惠特尼 U 检验,即布鲁纳-芒泽尔检验。
排列测试
一个非参数的替代方法是排列测试。这个想法是,在零假设下,两个分布应该是相同的,因此洗牌标签group
不应该显著改变任何统计数据。
我们可以选择任何统计数据,并检查其在原始样本中的值与其在group
标签排列中的分布相比如何。例如,让我们使用治疗组和对照组之间的样本均值的差异作为检验统计量。****
sample_stat = np.mean(income_t) - np.mean(income_c)stats = np.zeros(1000)
for k in range(1000):
labels = np.random.permutation((df['Group'] == 'treatment').values)
stats[k] = np.mean(income[labels]) - np.mean(income[labels==False])
p_value = np.mean(stats > sample_stat)
print(f"Permutation test: p-value={p_value:.4f}")Permutation test: p-value=0.0530
排列测试给出的 p 值为 0.053,意味着在 5%的水平上零假设的弱非拒绝。
我们如何解读p 值?这意味着数据中的均值差异大于置换样本均值差异的 1–0.0560 = 94.4%。
我们可以可视化测试,通过绘制测试统计量相对于样本值的排列分布。
plt.hist(stats, label='Permutation Statistics', bins=30);
plt.axvline(x=sample_stat, c='r', ls='--', label='Sample Statistic');
plt.legend();
plt.xlabel('Income difference between treatment and control group')
plt.title('Permutation Test');
排列的平均差异分布,按作者分类的图像
正如我们所看到的,样本统计量相对于置换样本中的值来说非常极端,但并不过分。
卡方检验
卡方检验是一种非常强大的检验,主要用于检验频率差异。
卡方检验的最不为人知的应用之一是测试两个分布之间的相似性。的想法是将两个组的观察结果结合起来。如果两个分布是相同的,我们将期望在每个箱中观察到相同的频率。重要的是,为了使测试有效,我们需要在每个箱中有足够的观察值。
我生成与控制组中income
的十分位数分布相对应的箱,然后计算处理组中每个箱中的预期观察数,如果两个分布相同的话。
# Init dataframe
df_bins = pd.DataFrame()
# Generate bins from control group
_, bins = pd.qcut(income_c, q=10, retbins=True)
df_bins['bin'] = pd.cut(income_c, bins=bins).value_counts().index
# Apply bins to both groups
df_bins['income_c_observed'] = pd.cut(income_c, bins=bins).value_counts().values
df_bins['income_t_observed'] = pd.cut(income_t, bins=bins).value_counts().values
# Compute expected frequency in the treatment group
df_bins['income_t_expected'] = df_bins['income_c_observed'] / np.sum(df_bins['income_c_observed']) * np.sum(df_bins['income_t_observed'])
df_bins
按作者分类的媒体夹和频率、图像
我们现在可以通过比较治疗组中预期的(E)和观察到的(O)数量来进行测试。测试统计由下式给出
卡方检验统计,图片由作者提供
其中由 i 和 O 索引的面元是面元 i 中的观察数据点数,而 E 是面元 i 中的预期数据点数。由于我们使用对照组中income
分布的十分位数来生成箱,我们预计治疗组中每个箱的观察数量在所有箱中是相同的。检验统计量渐近分布为卡方分布。
为了计算测试的统计量和 p 值,我们使用了来自scipy
的chisquare
函数。
from scipy.stats import chisquare
stat, p_value = chisquare(df_bins['income_t_observed'], df_bins['income_t_expected'])
print(f"Chi-squared Test: statistic={stat:.4f}, p-value={p_value:.4f}")Chi-squared Test: statistic=32.1432, p-value=0.0002
与迄今为止所有其他测试不同,卡方检验强烈拒绝两个分布相同的无效假设。为什么?
原因在于两个分布具有相似的中心但不同的尾部,卡方检验沿着整个分布测试相似性,而不仅仅是在中心,就像我们在之前的测试中所做的那样。
这个结果告诉了一个警示故事:在从 p 值得出盲目的结论之前,理解你实际测试的是什么是非常重要的!
科尔莫戈罗夫-斯米尔诺夫试验
Kolmogorov-Smirnov 检验可能是比较分布的最流行的非参数检验。Kolmogorov-Smirnov 测试的想法是比较两组的累积分布。特别地,Kolmogorov-Smirnov 检验统计量是两个累积分布之间的最大绝对差。
Kolmogorov-Smirnov 检验统计,图片由作者提供
其中 F₁ 和 F₂ 是两个累积分布函数,而 x 是基础变量的值。Kolmogorov-Smirnov 检验统计量的渐近分布是 Kolmogorov 分布。
为了更好地理解测试,让我们画出累积分布函数和测试统计量。首先,我们计算累积分布函数。
df_ks = pd.DataFrame()
df_ks['Income'] = np.sort(df['Income'].unique())
df_ks['F_control'] = df_ks['Income'].apply(lambda x: np.mean(income_c<=x))
df_ks['F_treatment'] = df_ks['Income'].apply(lambda x: np.mean(income_t<=x))
df_ks.head()
累积分布数据集快照,按作者分类的图像
我们现在需要找到累积分布函数之间的绝对距离最大的点。
k = np.argmax( np.abs(df_ks['F_control'] - df_ks['F_treatment']))
ks_stat = np.abs(df_ks['F_treatment'][k] - df_ks['F_control'][k])
通过绘制两个累积分布函数和检验统计量的值,我们可以直观地看到检验统计量的值。
y = (df_ks['F_treatment'][k] + df_ks['F_control'][k])/2
plt.plot('Income', 'F_control', data=df_ks, label='Control')
plt.plot('Income', 'F_treatment', data=df_ks, label='Treatment')
plt.errorbar(x=df_ks['Income'][k], y=y, yerr=ks_stat/2, color='k',
capsize=5, mew=3, label=f"Test statistic: {ks_stat:.4f}")
plt.legend(loc='center right');
plt.title("Kolmogorov-Smirnov Test");
Kolmogorov-Smirnov 检验统计,图片由作者提供
从图中我们可以看到,在income
~650 处,检验统计量的值对应于两个累积分布之间的距离。对于income
值,我们在两组之间有最大的不平衡。
我们现在可以使用scipy
中的kstest
功能进行实际测试。
from scipy.stats import kstest
stat, p_value = kstest(income_t, income_c)
print(f" Kolmogorov-Smirnov Test: statistic={stat:.4f}, p-value={p_value:.4f}")Kolmogorov-Smirnov Test: statistic=0.0974, p-value=0.0355
p 值低于 5%:我们拒绝两个分布相同的零假设,有 95%的置信度。
****注 1:KS 检验过于保守并且很少拒绝零假设。 Lilliefors 检验使用检验统计的不同分布,即 Lilliefors 分布,来纠正这种偏差。
****注 2:KS 测试使用非常少的信息,因为它只比较一个点的两个累积分布:最大距离点。 Anderson-Darling 测试和 Cramér-von Mises 测试则通过积分比较整个区域的两种分布(两者之间的差异在于平方距离的加权)。
多组-图
到目前为止,我们只考虑了两组的情况:治疗组和对照组。但是如果我们有多组?我们在上面看到的一些方法可以很好地扩展,而另一些则不行。
作为一个工作示例,我们现在将检查income
的分布在处理arms
中是否相同。
箱线图
当我们有许多个一位数的组时,盒图可以很好地缩放,因为我们可以并排放置不同的盒子。****
sns.boxplot(x='Arm', y='Income', data=df.sort_values('Arm'));
plt.title("Boxplot, multiple groups");
按作者分列的各治疗部门的收入分布图
从图中可以看出,income
在不同治疗组中的分布是不同的,编号越高的治疗组平均收入越高。
小提琴情节
结合汇总统计和内核密度估计的箱线图的一个非常好的扩展是小提琴图。violin 图沿 y 轴显示单独的密度,这样它们就不会重叠。默认情况下,它还在内部添加了一个微型箱线图。
sns.violinplot(x='Arm', y='Income', data=df.sort_values('Arm'));
plt.title("Violin Plot, multiple groups");
按作者分列的各治疗部门的收入分布图
至于箱线图,小提琴图表明不同治疗部门的收入是不同的。
脊线图
最后,脊线图绘制了沿 x 轴的多个核密度分布,比小提琴图更直观,但部分重叠。不幸的是,matplotlib
和seaborn
都没有默认的脊线图。我们需要从[joypy](https://github.com/leotac/joypy)
导入。
from joypy import joyplot
joyplot(df, by='Arm', column='Income', colormap=sns.color_palette("crest", as_cmap=True));
plt.xlabel('Income');
plt.title("Ridgeline Plot, multiple groups");
按作者分列的各治疗部门的收入分布图
脊线图再次表明,编号越高的治疗组收入越高。从该图中,也更容易理解不同形状的分布。
多组—测试
最后,让我们考虑比较多组的假设检验。为了简单起见,我们将集中讨论最流行的一种:f 检验。
f 检验
在多个小组中,最受欢迎的测试是 F-test 。f 检验比较不同组间变量的方差。这种分析也称为方差分析,或 ANOVA 。
实际上,f 检验统计量由下式给出
f 检验统计,按作者分类的图像
其中 G 为组数, N 为观察次数, x̅ 为总体平均值, x̅g 为组内平均值 g 。在组独立性的零假设下,F 统计量为 F 分布。
from scipy.stats import f_oneway
income_groups = [df.loc[df['Arm']==arm, 'Income'].values for arm in df['Arm'].dropna().unique()]
stat, p_value = f_oneway(*income_groups)
print(f"F Test: statistic={stat:.4f}, p-value={p_value:.4f}")F Test: statistic=9.0911, p-value=0.0000
测试 p 值基本为零,意味着强烈拒绝跨治疗组income
分布无差异的零假设。
结论
在这篇文章中,我们已经看到了很多不同的方法来比较两个或更多的分布,包括视觉上的和统计上的。这是许多应用中的主要问题,尤其是在因果推断中,我们使用随机化使治疗组和对照组尽可能具有可比性。
我们也看到了不同的方法可能更适合不同的情况。视觉方法有助于建立直觉,但统计方法对于决策是必不可少的,因为我们需要能够评估差异的大小和统计意义。
参考
[1]学生,一个平均数的可能误差 (1908),生物计量学。
[2] F. Wilcoxon,用等级方法进行个体比较 (1945),生物统计学通报。
[3] B. L .韦尔奇,涉及几个不同总体方差时“学生”问题的推广 (1947), Biometrika 。
[4] H. B. Mann,D. R. Whitney,关于两个随机变量中的一个是否随机大于另一个的检验 (1947),《数理统计年鉴》。
[5] E. Brunner,U. Munzen,《非参数伯伦斯-费希尔问题:渐近理论和小样本近似法》 (2000 年),《生物统计学杂志》。
[6] A. N. Kolmogorov,Sulla determinizione empirica di una legge di distribuzione(1933 年), Giorn .Ist。斜体的阿图尔。。
[7] H. Cramér,论基本错误的构成 (1928),斯堪的纳维亚精算杂志。
[8] R. von Mises,Wahrscheinlichkeit statistik und wahrheit(1936),《美国数学学会公报。
[9] T. W. Anderson,D. A. Darling,基于随机过程的某些“拟合优度”标准的渐近理论 (1953),《数理统计年鉴》。**
相关文章
密码
你可以在这里找到 Jupyter 的原始笔记本:
***https://github.com/matteocourthoud/Blog-Posts/blob/main/notebooks/distr.ipynb ***
感谢您的阅读!
我真的很感激!🤗如果你喜欢这个帖子并且想看更多,可以考虑 关注我 。我每周发布一次与因果推断和数据分析相关的主题。我尽量让我的帖子简单而精确,总是提供代码、例子和模拟。**
还有,一个小小的 免责声明 :我写作是为了学习所以错误是家常便饭,尽管我尽力了。当你发现他们的时候,请告诉我。也很欣赏新话题的建议!
最后但同样重要的是,热烈感谢Adrian Olszewski的许多有用的评论!**
如何使用 SQL 在 BigQuery 中计算移动平均值
原文:https://towardsdatascience.com/how-to-compute-a-moving-average-in-bigquery-using-sql-15f3fedd7489
消除变化,发现趋势,并在 Data Studio 中将其可视化
股市站(信用:https://unsplash.com/@behy_studio
问题是
当查看时序数据时,决策可能会受到随机、短期波动(加密货币的价格、报告的新冠肺炎病例数量)的影响。
这就是为什么使用移动平均线(也称为移动平均线或滚动平均线)最有助于消除短期波动并突出长期趋势。
例如,新冠肺炎测试站和实验室可能整周批量报告病例(或者周末关闭时不报告),加密货币股票市场价格可能会在几天之间的值之间快速振荡。
举例来说,在查看 Covid 19 新案例时,您可能已经在谷歌搜索上看到了下图:
来自谷歌搜索的 Covid 19 个新案例(图片由作者提供)
你会注意到图例中浅蓝色的线显示了 7 天的平均值。这正是我们将在本文中学习做的事情😎
您可以在下面的 Data Studio 中看到它的显示:
数据工作室中显示的 Covid 19 个新病例(图片由作者提供)
解决方案
在本文中,我们将根据谷歌新冠肺炎公开赛数据计算 7 天移动平均线。
在这种情况下,选择 7 天是很重要的(因为我们可以计算 14 天、30 天等等的移动平均值)。
在这里,我们选择 7 天,因为这是一个相当短的时期,我们希望保持每周视图(例如,周一至周日),这将更好地代表电晕测试站或测试中心的速度(报告可能在周末,或在一周的特定间隔)。
但是对于不同的用例,我们可能会选择不同的时间框架。我们的示例是大约 7 天的周期,但是也可以按 12 周的周期来计算。视情况而定,框架也可以是天、周、季、年。
此外,您可以将移动平均值应用于任何数值,如收入、用户数量等……)
我们的解决方案将使用 解析函数 。这些函数允许我们计算或获取一组行的值,并为每一行返回一个单个结果。这就像在不执行维度连接或分组的情况下在单个表中旅行或浏览一样。
要了解更多关于 聚合解析函数 ,你可以在这里看看👇🏼
https://cloud.google.com/bigquery/docs/reference/standard-sql/aggregate_analytic_functions
对于这个实验,我们使用来自公共 BigQuery 数据集的新冠肺炎公共数据。
您可以通过以下链接获得更多信息👇🏼
https://cloud.google.com/blog/products/data-analytics/free-public-datasets-for-covid19
要找到我们将逐步解释的完整脚本,您可以直接转到步骤#3、并在 BigQuery 中运行它。
步骤#1:转换和分组
首先,我们希望得到我们的特定变量(new_confirmed
)按期望的时间段聚合(在我们的例子中是每天)。
上面的查询返回一个包含每天新确诊病例的表。
每日新增确诊病例
通过使用查询编辑器和结果表之间的浏览数据按钮,我们可以在 Data Studio 上很好地显示每日新增确诊病例如下:
数据工作室每日新增确诊病例(图片作者提供)
这只是第一步,但这是一个好的开始,坚持住😅
第二步:如何计算我们的移动平均线?
我们之前计算了每日新增确诊病例的数量,其中输出是一天中每行和新增病例数量的表格。我们将该列命名为new_cases
。
我们将使用一个聚合分析函数来获得我们的移动平均值。该函数将如下所示:
*AVG(new_cases) OVER(ORDER BY UNIX_DATE(date) RANGE BETWEEN 6 PRECEDING AND CURRENT ROW)*
我们输入我们想要新案例的平均值 AVG(new_cases) ,并且我们希望这个平均值包括当前行值当前行和前面的 6 行(以及我们表中的每一行)。
然后,您将得到以下输出:
移动平均每行的输出
让我们手动计算,从2022–02–06开始,7 天平均值将返回:
(155439+214542+241049+716294+831347+970542+929533)/7
这给出了 579820,85 ,我们四舍五入到你在2022–02–06 的seven_days_ma
栏中看到的值。**
但是,我们需要解决一个微妙的问题。你也可以这样写
*AVG(new_cases) OVER(ORDER BY date ROWS BETWEEN 6 PRECEDING AND CURRENT ROW)*
那么使用 RANGE 或者 ROWS 的区别是什么呢?
这些行将查看当前行之前的行数,以便将它们包含在我们的平均值中。因此,在我们的例子中,该函数将查看当前行,然后查看之前的“物理”6 行,并计算平均值。但是如果有遗漏的日期呢?
这就是 RANGE 派上用场的地方,如果表由于某种原因缺少日期,那么行将回溯到 6 天以前。范围将产生一个基于日期值本身的窗口。
以失踪日期为例:
ma_rows 使用行框架,ma_range 使用范围框架
您可以在这里看到,ma_rows
正在使用行计算 7 天移动平均线,ma_range
正在使用范围计算我们的移动平均线,由于缺少日期(2022–02–03),它们计算的值并不完全相同。
通常,建议使用范围,因为它不是基于物理行,而是基于逻辑值。唯一的区别是日期字段需要使用 UNIX_DATE()函数进行转换。
步骤 3:在我们的查询中应用公式
现在,我们可以把所有这些放在一起,这是完整的脚本。
第一个 WITH 子句计算每个日期的所有新确诊病例。在 " — Main Query" 注释下,我们应用我们的移动平均函数,并且我们还在顶部的另一个查询中对其进行舍入(因为我们不能通过 OVER()子句使用舍入函数)。
这为我们提供了以下输出:
移动平均查询的结果以表格的形式显示
这就是我们如何得到我们的 7 天移动平均线!🍻然后就可以在 Data studio 上显示了
现在,是时候闪耀✨了
然后,我们可以使用 Datastudio 来显示我们的结果,这为我们提供了新冠肺炎案例和浅蓝色 7 天移动平均线的良好概览。
数据工作室中显示的 Covid 19 个新病例(图片由作者提供)
该方法可用于任何类型的时间序列和变量。有趣的部分是 聚合解析函数 的使用。他们使这个练习变得容易得多,即使他们一开始并不容易理解。
我希望你会喜欢这个方法,这篇文章会帮你节省一些时间。但更重要的是,我希望这将帮助您更轻松地使用 SQL 和 BigQuery!是一个很好的练习技巧的用例!
是时候深入研究一些数据了!🤓
如何用 Python 中的 TF-IDF 计算网站上的文本相似度
一种简单有效的 TF-IDF 和 Pandas 文本相似度方法
作者图片
在数据挖掘和自然语言处理领域,计算两个文本之间的相似度是一项非常有用的活动。这既允许隔离异常,又允许对特定问题进行诊断,例如博客上非常相似或非常不同的文本,或者将相似的实体归入有用的类别。
在本文中,我们将使用发布的脚本来抓取博客并创建一个小型语料库,在此基础上应用基于 Python 中 TF-IDF 的相似性计算算法。
具体来说,我们将使用一个名为 Trafilatura 的库,通过网站地图从目标网站检索所有文章,并将它们放在 Pandas 数据框架中进行处理。
我邀请读者阅读我在上面链接的文章,以更详细地了解提取算法是如何工作的。
为了简单起见,在这个例子中,我们将分析 diariodiunanalista.it,这是我自己用意大利语写的关于数据科学的博客,以便了解是否有彼此过于相似的文章。在这个过程中,我会诊断我自己的工作,也许会提出一些很酷的见解!
这在搜索引擎优化上有很大的反响——事实上,类似的文章会引发内容蚕食的现象:当属于同一网站的两篇文章在谷歌上争夺相同的位置。我们希望避免这种情况,识别这些情况是避免这种情况的第一步。
要求
我们需要的库是 Pandas,Numpy,NLTK,Sklearn,TQDM,Matplotlib 和 Seaborn。
让我们将它们导入到 Python 脚本中。
此外,我们需要运行nltk.download('stopwords')
命令来安装 NLTK 停用词。停用词是对句子的意义没有重要贡献的词,我们需要它们来预处理我们的文本。
创建数据集
让我们运行上面提到的文章中的软件。
数据收集过程。图片作者。
让我们来看看我们的数据集。
我们数据集的预览。图片作者。
从 URL 的分类中,我们注意到所有的帖子是如何被收集在 /posts/ 下的——这允许我们只隔离实际的文章,而忽略页面、类别、标签等等。
我们使用下面的代码来应用这个选择
我们数据集的预览。图片作者。
这是我们的语料库。在写这篇文章的时候,大约有 30 篇文章——因此它是一个非常小的语料库。对于我们的例子来说,它仍然是好的。
文本预处理
我们将应用一些简单的文本预处理来复制一个真实的应用程序管道。这可以扩展到补充读者的要求。
预处理步骤
我们将应用这些预处理步骤:
- 删除标点符号
- 小写应用程序
这将在一个非常简单的函数中完成,该函数使用标准的字符串和 NLTK 库。
TF-IDF 矢量器(我们将很快定义)将使用这个函数来规范化文本。
相似度计算算法
首先,让我们通过将停用词保存在一个变量中来定义它们
ita_stopwords = stopwords.words('italian')
现在我们从 Sklearn 导入 TfIdfVectorizer,向它传递预处理函数和停用词。
TF-IDF 矢量器会将每个文本转换成它的矢量表示。这将允许我们将每个文本视为多维空间中的一系列点。
我们计算相似度的方法是通过对构成我们正在比较的文本的向量之间的余弦值进行计算。相似度值介于-1 和+1 之间。值+1 表示两个基本相等的文本,而-1 表示完全分离。****
我邀请感兴趣的读者在专门的维基百科页面上阅读更多关于这个主题的内容。
现在我们将定义一个名为compute_similarity
的函数,它将使用矢量器将文本转换为数字,并应用该函数计算 TF-IDF 向量的相似性余弦。
让我们测试代码
我们以意大利语维基百科的两段文字为例。
Figlio 第二次将 giudice sardo Ugone II 引入 Arborea 和 Benedetta,推动了 padre 的文化和政治发展,并加强了 Arborea 和所有其他独立地区的自治。考虑到 300 年的一个重要数字,促进了农业组织的发展,颁布了《农村法典》,成功地完成了包括埃莉诺拉在内的立法工作
《绿巨人》是 2008 年路易斯·莱特里尔导演的一部电影。爱德华·诺顿的男主角,同样为车安和扎克·佩恩的风景作出了贡献;超级英雄的首要任务是完成所有提议中的最终版本,而不是在漫威传统大学里完成所有的投资。他的个人风格是古典风格的“巨人之歌”,在世界范围内独树一帜,不是最好的暗杀。
让我们应用cosine_similarity
函数来测试这两个文本有多相似。我期待一个相当低的值,因为它们处理不同的主题,并且不使用相同的术语。
该算法在两段文本上的应用。图片作者。
这两个文本显示出非常低的相似性,接近于 0。现在让我们用两个相似的文本来测试一下。我将把第二个文本的一部分复制到第一个文本中,保持相似的长度。
该算法在两段文本上的应用。图片作者。
相似度现在是 0.33。它似乎工作得很好。
现在,我们以成对的方式将该方法应用于所有语料库。
让我们详细了解这段代码是做什么的。
- 我们创建一个名为
M
的 30x30 矩阵 - 我们在数据帧上逐行迭代以访问
article_i
- 我们再次在相同的数据帧上逐行迭代,以访问
article_j
- 我们在
article_i
和article_j
上运行 compute_similarity 来获得相似性 - 我们将这个值保存在 M 中的位置
i
、j
m 可以很容易地转换成熊猫的数据帧,这使我们能够用 Seaborn 建立一个热图。
相似性热图。图片作者。
热图根据获得的相似性值,使用更亮或更暗的颜色突出显示异常。
让我们对代码做一个小小的修改,只选择相似度大于 0.40 的元素。
通过高于 0.4 的值过滤的相似性热图。图片作者。
我们看到相似性指数大于 0.4 的 4 个页面。
我们特别看到这些组合:
- 训练模型前要做的 6 件事->机器学习的最大障碍——过度拟合
- 训练模型前要做的 6 件事->什么是机器学习中的交叉验证
- 什么是机器学习中的交叉验证->机器学习中最大的障碍——过拟合
- 什么是机器学习->机器学习和深度学习有什么区别
这些对中的一些对之间的相似性也存在于显示高相似性的其他对中。
这些文章分享了这个主题,即机器学习和一些最佳实践。
结论
在这篇文章中,我们看到了一个简单而有效的算法来识别一个网站的相似页面或文章,用同样有效的方法刮。
接下来的步骤将包括更深入的分析,以理解为什么这些文章有很高的相似性。数据挖掘和 NLP 工具,如 Spacy,非常方便,允许进行词性(词性)和 NER(命名实体识别)分析。
研究最常用的关键词也会同样有效!
如果你想支持我的内容创作活动,欢迎点击我下面的推荐链接,加入 Medium 的会员计划。我将收到你投资的一部分,你将能够以无缝的方式访问 Medium 的大量数据科学文章。
https://medium.com/@theDrewDag/membership
你的数据挖掘方法是什么?一般怎么发现内容相似等异常?用评论分享你的想法👇
感谢您的关注,很快再见!👋
如何使用移动平均线在 SQL 中进行时间序列预测
预测未来的逐步指南
请务必点击 订阅此处 千万不要错过另一篇关于数据科学指南、技巧和提示、生活经验等的文章!
介绍
随着大数据和机器学习的出现,预测建模在商业中从未如此普遍。事实上,企业在运营中利用预测建模来保持竞争力几乎是必不可少的。
为什么?
通过准确预测未来会发生什么,它给你带来了几个好处:
- 这给了你更多的时间来制定策略和执行你的计划。给自己更多的时间让你有机会更彻底地思考你的策略,并最终减少出错的机会。
- 它可以帮助你进行资源分配。通过能够预测上升或下降的趋势,您可以将资源从预期具有较低 ROI 的计划中分配出来,并将它们转移到具有较高 ROI 的计划中。
- 它让你比你的竞争对手跑得更快。通过能够预测未来会发生什么,您可以更加迭代地重新评估和调整,从而保持敏捷和适应性。
有几种类型的预测模型,但在本文中,我们将重点关注一种非常有价值的类型,称为时间序列预测。
时间序列预测到底是什么?
时间序列预测简单地说就是根据历史数据对未来事件进行预测。如果你不清楚这一点,这里有一些企业如何使用时间序列预测的例子:
- 预测下个月对产品的需求,以确定库存的累积量
- 估计明年可能辞职的员工数量,以主动制定满足公司需求的招聘计划
- 对几只股票的未来价格进行建模,以确定将哪只股票加入公司的投资组合
请注意,所有的例子都涉及到对未来事件的预测,以便企业能够积极主动地计划和执行。
就模型本身而言,有几种类型的时间序列模型被广泛采用,但我们将重点关注最基本的时间序列模型,即简单移动平均线。
请务必点击 订阅此处 千万不要错过另一篇关于数据科学指南、技巧和提示、生活经验等的文章!
如何在 SQL 中进行简单的时间序列预测
现在,我们将向您展示如何使用简单移动平均线(SMAs)进行基本的时间序列预测。
SMA 是一种用于预测长期趋势的计算方法,它采用给定指标在过去一段特定时间内的平均值。请注意,在预测未来指标的精确值时,SMA没有有用。但是,它们仍然可以为您提供有用的信息,我们将在下面的示例中看到。
为了在 SQL 中计算 SMAs,您只需要做两件事:
- 日期栏
- 表示要预测的指标或值的列
表名:每周转换
假设我们有以下数据,它显示了一家公司从 2021 年 5 月 14 日到 2021 年 8 月 20 日每周的转化次数。
为了计算转换的 7 天 SMA,我们可以使用以下代码:
SELECT
Date, Conversions,
AVG(Conversions) OVER (ORDER BY Date ROWS BETWEEN 6 PRECEDING AND
CURRENT ROW) as SMA
FROM daily_sales
这将产生以下表格和图表:
很简单,对吧?注意上图中蓝线的波动性。在这种情况下,你可以凭直觉猜测转化率呈上升趋势,但这并不总是那么容易。
通过查看 7 日 SMA,我们可以收集以下信息:
- 我们可以看看一个指标的总体趋势。基于这一时间段,每周转化率呈上升趋势。
- 我们可以合理猜测指标的 SMA 走向。如果最近的周线转换高于当前的 SMA,那么 SMA 应该继续上升。相反,如果转化率持续低于当前的 SMA,我们应该期待它开始下降。
现在,您知道了如何构建和解释 SQL 中最基本的时间序列模型之一!
感谢阅读!
一定要 订阅这里 千万不要错过另一篇关于数据科学的指南、诀窍和技巧、生活经验等文章!
不确定接下来要读什么?我为你选了另一篇文章:
💔-most-valuable-data-science-skills-that-increased-my-salary-by-60-89b4bbe0b34f>
还有一个:
-特伦斯·申
- 如果您喜欢这个, 订阅我的中 为独家内容!
- 同样,你也可以 跟我上媒
- 报名参加我的个人简讯
- 关注我上LinkedIn其他内容
如何构造深度图像分类器
原文:https://towardsdatascience.com/how-to-conformalize-a-deep-image-classifier-14ead4e1a5a0
Julia 中的共形预测——第二部分
具有不同程度不确定性的共形预测集。图片作者。
深度学习很受欢迎,对于图像分类等一些任务来说,它非常强大。但众所周知,深度神经网络(DNN)可能不稳定(Goodfellow、Shlens 和 Szegedy 2014)且校准不佳。保形预测可以用来减轻这些缺陷。
在共形预测系列文章的第一篇部分中,我们看了基本的底层方法以及如何使用[ConformalPrediction.jl](https://github.com/pat-alt/ConformalPrediction.jl)
在 Julia 中实现 CP。该系列的第二部分是一个更加面向目标的操作指南:它演示了如何通过几行代码整合内置于Flux.jl
中的深度学习图像分类器。
🎯手头的任务
手头的任务是使用著名的 MNIST 数据集(LeCun 1998)预测手写数字图像的标签。通过MLDatasets.jl
,在 Julia 中导入这个流行的机器学习数据集变得非常容易:
using MLDatasets
N = 1000
Xraw, yraw = MNIST(split=:train)[:]
Xraw = Xraw[:,:,1:N]
yraw = yraw[1:N]
🚧构建网络
从图像输入到标签的映射建模将依赖于一个简单的多层感知器(MLP)。深度学习的一个很棒的 Julia 库是Flux.jl
。但是等等...ConformalPrediction.jl
对MLJ.jl
训练的模特不起作用吗?没错,但幸运的是存在一个Flux.jl
到MLJ.jl
的接口,即MLJFlux.jl
。该界面仍处于早期阶段,但对于习惯于在Flux.jl
中构建神经网络的任何人(比如我自己)来说,它已经非常强大且易于使用。
在Flux.jl
中,您可以为这个任务构建一个 MLP,如下所示:
using Flux
mlp = Chain(
Flux.flatten,
Dense(prod((28,28)), 32, relu),
Dense(32, 10)
)
其中(28,28)
只是输入尺寸(28x28 像素图像)。由于我们有十位数,所以我们的输出维数是10
。关于如何仅仅依靠Flux.jl
构建 MNIST 图像分类器的完整教程,请查看本教程。
我们可以在MLJFlux.jl
中做完全相同的事情,如下所示:
using MLJFlux
builder = MLJFlux.@builder Chain(
Flux.flatten,
Dense(prod(n_in), 32, relu),
Dense(32, n_out)
)
这里我们依靠@builder
宏来尽可能无缝地从Flux.jl
过渡到MLJ.jl
。最后,MLJFlux.jl
已经提供了许多帮助函数来定义普通网络。在这种情况下,我们将使用带有自定义生成器和交叉熵损失的ImageClassifier
:
ImageClassifier = @load ImageClassifier
clf = ImageClassifier(
builder=builder,
epochs=10,
loss=Flux.crossentropy
)
生成的实例clf
是一个模型(在MLJ.jl
的意义上),所以从这一点上我们可以依赖标准的MLJ.jl
工作流。例如,我们可以用数据包装我们的模型来创建一个机器,然后在维持集上对其进行评估,如下所示:
mach = machine(clf, X, y)
evaluate!(
mach,
resampling=Holdout(rng=123, fraction_train=0.8),
operation=predict_mode,
measure=[accuracy]
)
我们这个非常简单的模型的准确性并不惊人,但是对于本教程的目的来说已经足够好了。对于每幅图像,我们的 MLP 为每个可能的数字返回一个 softmax 输出:0,1,2,3,…,9。由于每个单独的 softmax 输出的值在 0 和 1 之间,yₖ ∈ (0,1),这通常被解释为概率:yₖ ≔ p(y=k|X)。边缘情况(即接近零或一的值)表明预测确定性较高。但这只是预测不确定性的启发式概念(Angelopoulos 和 Bates 2021)。接下来,我们将使用共形预测把这种试探性的不确定性概念变成一种严格的不确定性概念。
🔥整合网络
由于clf
是车型,所以也兼容我们的包:ConformalPrediction.jl
。为了整合我们的 MLP,我们只需要调用conformal_model(clf)
。由于生成的实例conf_model
也只是一个模型,我们仍然可以依赖标准的MLJ.jl
工作流。下面我们首先用数据包装它,然后拟合它。
using ConformalPrediction
conf_model = conformal_model(clf; method=:simple_inductive, coverage=.95)
mach = machine(conf_model, X, y)
fit!(mach)
啊…我们完成了!让我们在下一节看看结果。
📊结果
下图 2 显示了结果。图 2 (a)显示了高度确定的预测,现在在保形预测的严格意义上定义:在每种情况下,保形集(就在图像下面)只包括一个标签。
图 2 (b)和图 2 (c)分别显示了集合大小为 2 和 3 的预测越来越不确定。他们证明了 CP 能够很好地处理具有高度随机不确定性的样品:数字四(4)、七(7)和九(9)具有某些相似性。数字五(5)和六(6)以及三(3)和八(8)也是如此。即使看了很多例子(甚至对一个人来说),这些可能也很难相互区分。因此,看到这些数字经常一起出现在共形集合中就不足为奇了。
图 2 (a): 随机选择大小|C|=1 的预测集。图片作者。
图 2 (b): 随机选择大小为|C|=2 的预测集。图片作者。
图 2 (c): 随机选择大小为|C|=3 的预测集。图片作者。
🧐评估
为了评估保形模型的性能,可以使用特定的性能测量来评估模型是否被正确指定和良好校准(Angelopoulos 和 Bates 2021)。我们将在以后的另一篇文章中更详细地讨论这个问题。现在,请注意这些措施已经在ConformalPrediction.jl
中可用,我们将在这里简要展示它们。
至于其他许多事情,ConformalPrediction.jl
利用了MLJ.jl
的现有功能进行模型评估。特别是,我们将在下面看到如何在我们的机器上使用通用的evaluate!
方法。为了评估我们的保形预测器的正确性,我们可以使用定制的性能度量emp_coverage
来计算经验覆盖率。关于模型校准,我们将查看模型的条件覆盖。对于自适应的、校准良好的共形模型,条件覆盖率很高。评估条件覆盖率的一个常用方法是规模分层覆盖率。用于此目的的自定义措施称为size_stratified_coverage
,别名为ssc
。
下面的代码使用交叉验证实现了模型评估。我们上面使用的简单归纳分类器不是自适应的,因此与接近 0.95 的总经验覆盖率相比,获得的条件覆盖率较低,因此符合上面指定的期望覆盖率。
_eval = evaluate!(
mach,
resampling=CV(),
operation=predict,
measure=[emp_coverage, ssc]
)
println("Empirical coverage: $(round(_eval.measurement[1], digits=3))")
println("SSC: $(round(_eval.measurement[2], digits=3))")
Empirical coverage: 0.957
SSC: 0.556
当使用自适应预测集时,我们可以获得更高的自适应性(SSC ):
conf_model = conformal_model(clf; method=:adaptive_inductive, coverage=.95)
mach = machine(conf_model, X, y)
fit!(mach)
_eval = evaluate!(
mach,
resampling=CV(),
operation=predict,
measure=[emp_coverage, ssc]
)
println("Empirical coverage: $(round(_eval.measurement[1], digits=3))")
println("SSC: $(round(_eval.measurement[2], digits=3))")
Empirical coverage: 0.99
SSC: 0.942
我们还可以使用一个定制的Plots.jl
方法来查看这两种方法的结果集大小(图 3)。根据上述情况,自适应方法的传播范围更广,这反映出“该程序有效地区分了简单和硬输入”(A. N. Angelopoulos 和 Bates,2021)。
plt_list = []
for (_mod, mach) in results
push!(plt_list, bar(mach.model, mach.fitresult, X; title=String(_mod)))
end
plot(plt_list..., size=(800,300),bg_colour=:transparent)
图 3:两种方法的集合大小分布。图片作者。
🔁概述
在这个简短的指南中,我们看到了使用ConformalPrediction.jl
在 Julia 中整合深度学习图像分类器是多么容易。几乎任何在Flux.jl
中训练的深度神经网络都与MLJ.jl
兼容,因此只需几行代码就可以整合。这使得将不确定性试探法转化为严格的预测性不确定性估计变得非常容易。我们还看到了保形预测器的性能评估。敬请关注更多内容!
🎓参考
安吉洛普洛斯,阿纳斯塔西奥斯 n,斯蒂芬贝茨。2021."保形预测和无分布不确定性量化的简明介绍."https://arxiv.org/abs/2107.07511。
古德菲勒、伊恩·J、黄邦贤·史伦斯和克里斯蒂安·塞格迪。2014."解释和利用对立的例子."https://arxiv.org/abs/1412.6572。
勒昆,扬恩。1998." MNIST 手写数字数据库."
原载于 2022 年 12 月 5 日 https://www.paltmeyer.comhttps://www.paltmeyer.com/blog/posts/conformal-image-classifier/。
如何用 Python 连接到雪花数据库
原文:https://towardsdatascience.com/how-to-connect-to-a-snowflake-database-with-python-a8f710c3afab
了解如何使用雪花连接器或 SQLAlchemy Python 包与雪花进行交互,并利用本文中提供的模板。
建议的点播课程:
你是想通过成为 数据工程师 还是 机器学习工程师 来推进自己的职业生涯吗?我强烈建议您查看以下课程:
- 数据工程纳米学位 → 精品课程!
- 用 Apache Kafka 进行数据流&Apache Spark nano degree
- Python 高级编码问题(StrataScratch)→我找到的准备 Python 的最佳平台& SQL 编码面试到此为止!比 LeetCode 更好更便宜。
>>>还不是中等会员吗?考虑与我的 推荐链接 签约,以获得 Medium 必须提供的一切,费用低至每月 5 美元!
介绍
我是在 2017 年第一次接触雪花的,当时我所在的公司决定从 Redshift 迁移到一个更具可扩展性的基于计算的* claud 数据仓库,以满足他们不断增长的分析需求并支持 BI 工具。*
当时我是一名数据分析师,主要通过 DBMS 查询雪花。几年过去了,现在,作为一名数据工程师,我投入时间构建数据管道,通过 Python 自动地连接、查询、插入和更新数据到雪花中。 你是不是很好奇想了解它是怎么做到的?
一晃几年过去了,现在,作为一名数据工程师,我投入时间构建数据管道,通过 Python 自动连接、查询、插入和更新数据到雪花中。你很想知道这是怎么做到的吗?
在本文中,您将学习如何通过 Python 与雪花数据库交互,或者使用snowflake.connector
或者sqlalchemy
包。
当通过 Python 启用对雪花的安全认证时,这两个包都支持许多技术,但是根据我的经验,两个最流行的选项是externalBrowser
认证和default
认证,因此我将在我的例子中使用它们。
现在,让我们通过创建一些您可以在自己的项目中使用的有用的代码模板来一起探索这两种方法。
方法 1:使用雪花连接器连接
使用Snowflake Connector
的第一步是按照官方文档的建议下载软件包:
***pip install snowflake-connector-python**or **pip install snowflake-connector-python==<version>***
然后,您需要在代码中导入它:
*import snowflake.connector*
外部浏览器认证
snowflake.connector
包括一个connect()
函数,该函数可以用作一个构造函数,用于创建到数据库的连接。
函数允许您指定多个参数,其中一些是建立连接所必需的,一些是可选的。
其中一个参数是authenticator
。引用官方文档,如果您设置了authenticator = 'externalbrowser'
,那么将使用以下方式尝试验证:
*“*your web browser and* ***Okta****,* ***ADFS****, or any other SAML 2.0-compliant* ***identity provider******(IdP)*** *that has been defined for your account*”.*
例如,如果您的团队使用 Okta 作为身份提供者,您将只需要指定USER_EMAIL
而不需要传递用户password
。这是一个您可以立即使用的模板,只需替换您的凭据即可:
优点:'externalbrowser'
认证允许您与您的personal user
建立到 SF 的连接。它的灵活性使它成为您在本地测试新脚本时的首选连接选项,因为您不需要任何凭证shared user
( 这增加了您的自主权)。**
CONS:每次你建立一个新的连接,你的浏览器就会自动打开一个新窗口,这有点烦人,但没什么大不了的…
当您运行上面的代码时,它返回一个连接对象 con_eb
,该对象又有一个名为cursor()
的方法。在实际与 SF 交互之前,您还需要创建一个光标对象* con_eb.cursor()
,为了方便使用,它被保存在db_cursor_eb
变量下。***
示例#1:创建表格
在第一个例子中,我通过将 SQL 命令传递给游标对象execute()
方法,在我的首选模式中创建了一个TRANSACTIONS
表:
命令一执行,您就可以通过运行db_cursor_eb.fetchone()[0]
来验证它是否成功,在这种情况下会返回消息Table TRANSACTIONS successfully created.
*****INFO:** snowflake.connector.cursor:query: [CREATE OR REPLACE TABLE SCHEMA_NAME.TRANSACTIONS ( TR...]**INFO:** snowflake.connector.cursor:query execution done**INFO:** root:Table TRANSACTIONS successfully created.***
通常fetchone()
检索查询结果集的下一行,但是因为在这种情况下我只是创建一个空表,所以它只是返回执行状态。在生产中显示非常方便的信息!
默认身份验证
如果不指定authenticator
参数,那么在底层,雪花将使用它的内部(默认)验证器。
但是,在这种情况下,你需要通过角色USER_NAME
和PASSWORD
。这些应该是你个人的证件或者是某个shared user
的证件。除了这两处小小的改动,该模板与上一个非常相似:
优点:这通常是生产中使用的连接方法,因为它不会通过您的浏览器触发嘈杂的身份验证,也不需要任何额外的身份检查。
CONS: 在建立连接之前,你需要请求分配一个角色和密码。但这是一点小小的代价,真的…
和以前一样,我创建了一个名为db_cursor_def
的光标对象。
示例 2:插入到表格中
我现在将使用db_cursor_def.execute()
方法将数据插入到在第一个例子中创建的TRANSACTIONS
表中。
要插入的记录将从现有的SOURCE_TABLE
中检索,并用SELECT
命令查询:
注意,我将查询LIMIT
设置为1500
记录。
然后我调用了游标对象 rowcount
属性,该属性返回最后一次执行所产生的行数,以检查这是否正是插入到TRANSACTIONS
表中的行数:**
*****INFO:** snowflake.connector.cursor:query: [INSERT INTO SCHEMA_NAME.TRANSACTIONS (TRX_ID, SOURCE_...]**INFO:** snowflake.connector.cursor:query execution done**INFO:** root: Total rows inserted: 1500***
方法 2:使用 SQLAlchemy 连接
另一种连接和交互雪花的方法是使用SQLAlchemy
。首先,您需要运行以下命令:
***pip install --upgrade snowflake-sqlalchemy***
它将同时安装snowflake.sqlalchemy
和sqlalchemy
,以防还没有。
然后,您应该从sqlalchemy
导入create_engine
方法,从snowflake.sqlalchemy
导入URL
方法:
***from snowflake.sqlalchemy import URL
from sqlalchemy import create_engine***
外部浏览器认证
实际上,要建立与sqlalchemy
的连接,您需要调用create_engine
方法并传递一个[connection string](https://docs.snowflake.com/en/user-guide/sqlalchemy.html#connection-string-examples)
给它。
不过,为了方便,可以使用 [snowflake.sqlalchemy.URL](https://docs.snowflake.com/en/user-guide/sqlalchemy.html#connection-string-examples)
的方法构造连接字符串,连接到数据库:
如您所见,为了连接到externalbrowser
认证,您应该指定的参数与snowflake.connector
完全相同。
在执行查询之前,最好先创建一个连接对象:engine_1_con = engine1.connect()
。然而,值得一提的是,甚至直接在engine_1
上调用execute()
方法也可以。
示例# 3:从表中选择+ FetchAll()
这个例子的目的是向您展示如何使用一个SELECT
语句检索插入到TRANSACTIONS
表中的整个数据集,使用fetchall()
将数据集中的所有行提取到data
并将第一列的内容保存到一个名为trx_ids
的列表中:
我想向您展示一个如何使用fetchall()
的简单例子,因为在构建数据管道时,您可能会在代码中一次又一次地调用这个方法。
正如所料,检索到的查询1500 rows
和我创建的列表中的前五个trx_ids
显示如下:
*****INFO:** snowflake.connector.cursor:query: [SELECT * FROM SCHEMA_NAME.TRANSACTIONS;]**INFO**: snowflake.connector.cursor:query execution done**INFO:** root:Number of rows retrieved: 1500**Output:**[3440508402, 482408596, 476831653, 3224085714, 3871714048]***
默认身份验证
通过default
认证连接到带有sqlalchemy
的雪花使用与之前完全相同的语法,并且与snowflake.connector
完全一样,您将需要用USER_NAME
替换USER_EMAIL
并指定一个PASSWORD
:
示例# 4:从表格中选择+转换为熊猫 DF
在最后一个例子中,我将向您展示如何使用sqlalchemy
引擎创建熊猫数据帧。
这可以通过将engine_2
和sql
查询传递给 pandas read_sql()
函数来轻松实现:
因此,如果你计划和熊猫一起工作,我会推荐你用sqlalchemy
连接到Snowflake
来利用这些内置的方法。
结论
在本文中,您已经了解了通过 Python 使用不同类型的认证,有两种主要的方式来连接和交互雪花数据库。****
雪花在数据行业越来越受欢迎,因此我希望我上面分享的代码模板将有助于加快您作为数据分析师查询雪花、作为数据科学家创建训练数据集或作为数据工程师构建自动化 ETL 管道的日常任务。
来源
给我的读者一个提示
这篇文章包括附属链接,如果你购买的话,我可以免费给你一点佣金
如何连接到云运行服务中的 GCP 云 SQL 实例
使用私有 IP 在几分钟内连接到云 SQL 实例
图片由 Pixabay 的崔斯特·多·乌尔登提供
如果你使用谷歌云平台(GCP),在你的云运行服务中访问云 SQL 是很常见的。这应该是一个简单的任务,因为云 SQL 和云 Run 都在同一个网络中。但是,当你自己做的时候,你可能无法在短时间内成功完成,因为网上的许多文档要么已经过时,要么过于复杂。经过几个小时的反复试验,我终于让它工作了。我认为写下我的解决方案是值得的,这样也可以节省其他人的时间。如果你做对了,其实很简单。
设置云 SQL
由于 Cloud SQL 和 Cloud Run 都在 Google 云平台上,所以最好通过私有 IP 连接,以最小化网络延迟。如果“私有 IP”选项尚未启用,请启用它。记下稍后将使用的网络和私有 IP 地址。
作者图片
作者图片
创建 VPC 连接器
虚拟专用云(VPC) 是物理网络的虚拟版本,在谷歌的生产网络内部实施,可用于连接平台上创建的所有类型的资源。这实际上是一个非常复杂和抽象的概念。现在,你只需要明白无服务器 VPC 访问允许云功能、云运行服务和应用引擎应用使用它们的私有 IP 访问 VPC 网络中的资源。让我们创建一个 VPC 连接器,我们的云运行服务可以使用它来连接到我们的云 SQL 实例。
在顶部搜索框中搜索“无服务器 VPC 接入”,然后选择“无服务器 VPC 接入(VPC 网络)”。然后单击“创建连接器”创建一个新的 VPC 连接器:
作者图片
按如下方式填写表格:
- 给它一个唯一的名称。
- 选择与您的云 SQL 实例和云运行服务相同的区域。这一点非常重要,否则您将无法使用这个连接器连接到云 SQL 实例。
- 选择与您的云 SQL 实例相同的网络。如果你有多个网络,这也很重要。
- 为“子网”选择“自定义 IP 范围”。
- 指定 IP 范围以覆盖您的云 SQL 实例的私有 IP 地址。在本例中,它被设置为“10.104.0.0”。IP 范围不能与现有范围冲突。
现在,您可以单击“创建”来创建 VPC 连接器。应该注意的是,VPC 连接器不是免费的。它们实际上使用起来相当昂贵。因此,当不再需要它们时,一定要记得删除它们。
配置云运行服务帐户
云运行服务账号,默认为 计算引擎默认服务账号 ,应该有 云 SQL 客户端 角色,有权限连接云 SQL。
在 IAM 页面上,搜索“计算引擎默认服务帐户”,然后单击铅笔按钮为其添加云 SQL 客户端角色:
作者图片
作者图片
创建云运行服务
最后,让我们创建一个云运行服务,并使用刚刚创建的 VPC 连接器将它连接到我们的云 SQL 实例。尝试在 GCP 平台找到“云跑”,点击“创建服务”创建一个新的:
重要的是,选择与云 SQL 实例和 VPC 连接器相同的区域。关于如何自动部署云运行服务的更详细介绍,这篇文章可能会有所帮助。
出于演示目的,我们通常会选择“允许所有流量”和“允许未经身份验证的调用”。如果需要,您可以使用 IAM 添加更细粒度的身份验证。
现在展开“容器、变量和秘密、连接、安全性”部分,并指定连接和环境变量。我们先设置连接。单击“连接”选项卡,然后单击“添加连接”来添加新的连接。选择要连接的云 SQL 实例。然后选择在上一步中创建的“VPC 连接器”。请注意,如果连接器的区域不同于正在创建的云运行服务的区域,则不会显示 VPC 连接器。
然后我们需要为我们的数据库连接创建一些环境变量,这些变量将在我们的云运行服务中使用:
非常重要!我们需要将我们的云 SQL 实例的私有 IP 地址指定为 DB 主机,而不是像某些教程中显示的“127.0.0.1”或“localhost”,否则无法工作。
环境变量将在您的云运行服务的代码中使用,以连接到云 SQL 实例。如果您使用 SQLAlchemy 连接到 MySQL 数据库,代码将如下所示:
如果需要,您可以查看相应的文章,了解如何使用 SQLAlchemy 来执行普通 SQL 查询和创建 ORM 模型。
现在,您应该能够从云运行服务连接到您的云 SQL 实例。试一试!
结论
如果我们在 Cloud Run 上托管我们的后端代码,我们需要连接到 Cloud SQL 是很常见的。然而,虽然看起来微不足道,但是有很多陷阱会导致连接失败。在本文中,我们已经介绍了一般的设置过程,还强调了可能会导致几个小时的努力时间的陷阱。这篇文章的主要内容如下:
- SQL 实例和 VPC 连接器的网络应该相同。
- SQL 实例、VPC 连接器和云运行服务的区域应该相同。
- 应该在云运行服务中使用 SQL 实例的私有 IP 进行连接。
如何连接运行在 AWS EC2 上的 Jupyter 服务器
原文:https://towardsdatascience.com/how-to-connect-with-jupyter-server-running-on-aws-ec2-efa309f47c51
使用本地端口转发连接到 AWS EC2 上的 Jupyter 服务器
PC:https://pixabay.com/photos/network-server-system-2402637/
如今,数据科学家、ML 工程师、产品经理、客户成功工程师、讲师、学生和许多其他堆栈持有者都喜欢使用 jupyter 笔记本,原因有很多。但是,有时我们试图运行的任务可能会消耗资源,并且我们可能在本地机器上没有足够的资源。
在这种情况下,我们可以依靠 AWS EC2,我们可以使用首选的操作系统、内存和存储创建 EC2 实例。
生成 EC2 实例很容易,在线订购您喜欢的食物,您不需要对云计算有任何深入的先验知识。
我们知道,不是每个数据科学家、ML 工程师、讲师或学生都有云计算或 AWS 服务方面的专业知识。但是每个人在处理 ML 模型的时候肯定都有对计算资源的要求。EC2 可以帮助你。在这篇文章中,我将帮助你开始使用它。
今天我们将会看到,
- 如何启动 AWS EC2 实例?
- 如何通过 ssh 连接到 EC2 实例?
- 如何在 EC2 上安装 Anaconda/Miniconda?
- 如何使用端口转发连接到 EC2 上的 jupyter 服务器?
如何启动 AWS EC2 实例?
在这里,我将向你展示如何启动一个 Ubuntu 实例。你需要确保你有一个 AWS 账户&账户上的点数很少。
步骤 01-登录 AWS 控制台并访问 EC2 控制台。
PC:作者
步骤 02-进入 EC2 控制台后,点击Launch Instance
PC:作者
步骤 03:它将带您到可以配置实例的页面。你需要
- 给你的实例一个名字。我正在使用
my-jupyterlab
PC:作者
- 选择 AMI(亚马逊维护的图像),我用的是
Ubuntu
。
PC:作者
- 选择实例类型,这里我使用
t2.medium
进行演示。您可以选择具有所需足够内存的实例类型
PC:作者
- 创建或选择一个现有的密钥对(这个密钥将用于 shh 到您的 EC2 实例中)。当你创建一个新的密匙时,使用
rsa encryption
下载.pem
文件来和 Openssh 一起使用。当您单击创建新的密钥对时,它将自动下载私钥。保管好它!!!
PC:作者
PC:作者
- 选择您需要的存储量。我选择
4Gb
,因为我只为这个演示创建它。
PC:作者
我将其他配置保留为默认值。您可以根据需要随意配置它们。
一旦一切配置完毕,点击Launch Instance
启动您的实例。在 EC2 仪表板上,检查您的实例状态是否为RUNNING
。
PC:作者
如何通过 ssh 连接到 EC2 实例?
- 希望您已经成功启动了一个实例。接下来,您需要做的是将您下载的私钥移动到您的 ssh 目录中。(假设你已经在
~/Downloads
下载了密钥。您的密钥文件名和扩展名可能会不同。但是为了通过 Openssh 连接到您的实例,它需要是.cer or .pem
,我的密钥文件是my-jupyterlab.cer
$ mv ~/Downloads/my-jupyterlab.cer ~/.ssh/
- 打开一个终端,运行下面的命令,通过 ssh 连接到您的实例。您可以从实例仪表板中找到您的实例的公共 IP 地址。大多数时候 ubuntu EC2 实例的实例名是
ubuntu
,你可以根据需要更改它。您可以通过使用实例仪表板来找到如何做到这一点。让我让你用那个提示找到它。
PC:作者
## ssh -i [path-to-private-key] [username@public-IP]$ssh -i ~/.ssh/my-jupyterlab.cer ubuntu@3.80.109.97
它将提示是否将指纹添加到您的本地机器。键入yes
并按下enter
继续。
如何在 EC2 上安装 Anaconda/Miniconda?
您可以通过多种方式在 EC2 实例上安装 Jupyterlab。我更喜欢使用 Anaconda/Miniconda 来管理我的 python 环境。因此,让我向您展示如何安装 Miniconda,创建一个 conda 环境并在其中安装 Jupyterlab(在连接到 EC2 实例的终端上按照下面的步骤操作)
- 下载 Miniconda 安装程序
$ wget [https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh](https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh)
- 运行安装程序
$ sh ./Miniconda3-latest-Linux-x86_64.sh
遵循安装过程并完成它。
- 运行 conda init 配置以确保您已经将 conda 添加到您的路径中
$ conda init bash
- 一旦成功
exit
从您的 ssh 连接&再次连接到您的 EC2。 - 创建一个 conda 环境并安装 Jupyterlab(逐个运行命令)
$ conda create --name jupyter python=3.8
$ conda activate jupyter
$ conda install jupyterlab
- 启动 Jupyterlab 服务器
$ jupyter lab
如何使用端口转发连接到 EC2 上的 jupyter 服务器?
好了,现在一切都准备好了。
通常,当我们启动一个 jupyter 服务器时,它将运行在http://localhost:8888/lab上。但是如果你打开你的浏览器,尝试访问这个地址,你会得到消息Your site connot be reached
。这是因为在这种情况下,jupyter 服务器运行在 EC2 实例的 localhost 上,而不是在本地机器上。
那么我们如何通过浏览器进入 jupyter 实验室呢?让我们明白我们有什么,我们没有什么
- 我们可以通过 ssh 访问 EC2 实例
- 我们无法访问运行在 EC2 上的 jupyter 服务器
- 但是我们的 EC2 实例可以访问运行在本地主机上的 jupyter 服务器
- 我们可以在本地机器上访问本地主机
所以我们能做的是,我们可以告诉我们的机器监听我们的 localhost:8888 上的流量,并通过安全隧道将所有内容转发到 EC2 的 localhost:8888。
这个过程就是众所周知的local port forwarding
。
PC:作者
那么怎么做呢?确保您已经完成了上述所有步骤,并且您的 jupyter 服务器已经启动并运行在 EC2 上。
打开另一个终端,运行下面的命令
## ssh -L [PORT-on-your-machine]:[IP-jupyter-server-on-ec2]:[PORT-jupyter-server-on-ec2] [username]@[public IP of EC2] -i [path to private key]$ ssh -L 8888:127.0.0.1:8888 ubuntu@3.80.109.97 -i ~/.ssh/mr-jupyterlab.cer
一旦你在你的另一个终端上运行这个程序(你在 EC2 上启动了哪个 jupyter 服务器),你将会看到如下的消息
PC:作者
在浏览器上复制并粘贴 URL http://localhost:8888/lab?token=xxxxxxxxxxxxxxxxxxxxxx
。
PC:作者
恭喜,现在您已经可以访问运行在 EC2 实例上的 jupyter 服务器了。
我们已经看到了如何启动 EC2 实例,在其上安装 anaconda,启动 jupyter 服务器&从本地机器的任何地方访问它。您可以根据需要用资源配置 EC2 实例,并毫无顾虑地构建 ML 模型。EC2 具有自动缩放功能,这在我们需要更多资源时非常有用。但那是另一天的话题。
了解云计算对现在的每个人都很重要。希望这篇文章能帮助你开始了解云计算的旅程。
编码快乐!!!
如何在 Power BI 中使用 DAX 表达式控制颜色
原文:https://towardsdatascience.com/how-to-control-colors-with-dax-expressions-in-power-bi-ef7e5c767eff
我们现在可以添加长期视觉效果的着色规则。但是,我们如何使用 DAX 表达式来控制这些颜色,并试图遵循 IBCS 规则呢?
介绍
几周前,我发表了一篇关于信息设计的文章:
https://medium.com/cloud-workers/three-simple-rules-for-information-design-52db54864b47
概括一下:
IBCS 是一家为信息设计创造了一套规则的公司。
IBCS 帮助我们利用其规则来改进我们的报道。
我把原来的 8 条成功法则浓缩成了 3 条简单易用的法则:
1.你的信息是什么?
2.使用一致的符号。
3.去掉不必要的东西。
信息设计的一个重要原则是在我们的报告中避免不必要的颜色。
例如:
当您想要显示数据的时间序列时,您希望如下图所示:
图 1 —时间序列的示例报告(作者提供的图表)
如您所见,每个周期有三种不同的填充颜色:
- 实际周期是黑色的
- 所有过去的时期都是灰色的
- 所有未来期间都有对角线条纹
这样做的原因是为了让用户容易发现实际数字,并能够快速区分过去和预测数据。
不幸的是,我们不能在 Power BI 中为列视觉使用对角线条纹。
但是我们可以使用 DAX 来检测周期,并根据该列相对于实际周期的位置来选择颜色。
准备
为了能够实现如下所示的解决方案,您需要一个包含两个附加列的日期表:
- 年度指数
- 蒙特辛德克斯
我在关于 Power BI 和 DAX 的第一篇文章中提到了这些专栏:
💔-ways-to-improve-your-reporting-with-an-expanded-date-table-2d983d76cced>
此列计算从实际日期开始的周期数。
实际日期( Now() )在报告中的数据刷新期间进行评估。
您可以在 DAX 日期表中使用以下表达式来添加这些列:
- " MonthIndex ",DATEDIFF(EOMONTH(Now(),0),EOMONTH([Date],0),MONTH)
- “YearIndex”,YEAR([Date]) — YEAR(Now())
如果使用存储在源系统中的日期表,可以在那里添加这些列。
在 SQL Server 中,可以使用以下语句设置这些列的值(变量@Today 包含语句à GETDATE()的执行日期):
UPDATE [dbo].[Date]
SET [YearIndex] = DATEDIFF(yyyy, @Today, [Date]);
UPDATE [dbo].[Date]
SET [MonthIndex] = DATEDIFF(mm, @Today, [Date]);
重要提示:以下示例中的数据有一个日期表,实际日期设置为 2012 年 3 月 9 日。
Power BI 中的颜色
我们可以通过两种不同的方式在 DAX 表达式中使用颜色名称:
1.我们将鼠标悬停在 Power BI 中的调色板上,并写入颜色名称。
例如:
a.黑色
b.灰色
c.浅灰色
d.红色
e.蓝色
2.或者,我们可以单击“更多颜色…”,选择一种颜色并记下该颜色的十六进制值。
例如:
a.#000000 黑色
b.#FFFFFF à白色
c.#DCDCDC à浅灰色
d.#FF0000 红色
e.# 0000FF 蓝色
有了这些信息,我们可以创建 DAX 度量,它返回颜色名称或颜色代码。
概念验证
现在,我们想看看它是如何工作的。
我们创建一个柱形图,其中一个度量值和日历层次结构被分配给 X 轴。
作为默认颜色,我们看到我们的列是蓝色的。但是我们想把这个换成灰色。
第一步是创建一个固定颜色的基本测量:
Dynamic Color PoC = "Grey"
然后,我们将此度量作为表达式分配给列:
图 2 —第一次测试(作者提供的图)
结果看起来像这样:
图 3 —第一次测试的结果(作者提供的数据)
如果我们将测量值更改为以下值:
Dynamic Color PoC = "Red"
我们得到以下结果:
图 4 —红色测试(作者提供的图片)
现在,我们知道了如何给柱形图分配颜色。
我们可以进入下一步,给年份分配动态颜色。
控制每年的颜色
我将通过每个步骤来构建解决方案。这样,你就很容易理解为什么这个解决方案会有效。
第一步是创建一个度量,看看如何使用日期表中的 YearIndex 列:
Dynamic Colors =
VAR ActualYearIndex = SELECTEDVALUE('Date'[YearIndex])
RETURN
ActualYearIndex
为了检查结果,我们向报告中添加了一个带有日期层次结构和两个度量值(带有要显示的值的度量值和新的动态颜色度量值)的矩阵。
结果显示在矩阵中,如下所示:
图 5 —动态颜色测量,步骤 1(作者提供的图片)
如您所见,2021 年的 YearIndex 为 0,前一年为负数。下一年是正数。
第二步是使用这个结果根据 YearIndex 设置颜色。
为了实现这一点,我们将动态颜色度量扩展为以下表达式:
Dynamic Color =
VAR ActualYearIndex = SELECTEDVALUE('Date'[YearIndex])
VAR YearColor =
SWITCH(TRUE
,ActualYearIndex < 0, "Grey"
,ActualYearIndex = 0, "Black"
,ActualYearIndex > 0, "LightGrey"
)
RETURN
YearColor
如您所见,我们使用开关()函数为每个 YearIndex 值分配一种颜色。
矩阵中的结果如下所示:
图 6 —每年颜色矩阵(作者提供的图)
柱形图中的结果如下所示:
图 7 —每年动态颜色的柱形图(由作者提供)
这是一个(几乎)完美的起点。
但是当我们深入到月份级别时会发生什么呢?
在这种情况下,颜色将继承与年份相同的颜色。
但对于 2021 年,我们将在月份级别看到相同的配色方案。
我们希望三月是黑色,三月之前的几个月是灰色,三月之后的几个月都是浅灰色。
添加月份
要将相同的动态逻辑添加到月级别,我们可以扩展现有逻辑来编写以下度量:
Dynamic Color =
VAR ActualYearIndex = SELECTEDVALUE('Date'[YearIndex])
VAR ActualMonthIndex =
IF( HASONEVALUE('Date'[MonthIndex])
,SELECTEDVALUE('Date'[MonthIndex])
,99
)
VAR YearColor =
SWITCH(TRUE
,ActualYearIndex < 0, "Grey"
,ActualYearIndex = 0, "Black"
,ActualYearIndex > 0, "LightGrey"
)
VAR MonthColor =
SWITCH(TRUE
,ActualMonthIndex < 0, "Grey"
,ActualMonthIndex = 0, "Black"
,ActualMonthIndex > 0, "LightGrey"
)
RETURN
IF(ActualMonthIndex = 99
,YearColor
,MonthColor)
这里的关键是我们如何评估 ActualMonthIndex。
我们使用 HASONEVALUE() 函数来检查当前过滤上下文是只包含一个月还是包含多个月。
在年份级别,此函数将返回 FALSE,因为实际筛选器上下文中包含多个值。
在月级别,筛选器上下文只包含一个值。因此,该函数将返回 TRUE。
剩余的测量使用相同的逻辑,但是两次。
月级别的柱形图如下所示:
图 8 —每月动态颜色的柱形图(由作者提供)
当然,你可以使用除了黑色和灰色以外的颜色。
但是考虑到有些用户不能区分那么多颜色。例如,请看下图:
图 9 —彩色和黑白(作者提供的图片)
这里我添加了两个红色和绿色的矩形。
然后我复制了这些矩形,并把它们转换成黑白图片。
如你所见,两个灰色矩形之间的差异不再那么大。
在为报表选择颜色时,您必须考虑这些影响。
结论
设计报告时,信息设计是一个重要因素。
我们需要避免陷入在报告中使用过多颜色的陷阱。
权力 BI 诱惑我们使用太多的颜色,但我们需要知道我们在做什么。
例如,文章在 Power BI 桌面中使用报表主题— Power BI |微软学习教你如何在 Power BI 中使用主题。
但是即使是色盲主题也使用了很多不同的颜色。
然后,当你看到可下载的自定义主题时,情况变得更糟。
更不用说 YouTube 上的视频了,比如这个:
他开始做得很好,但是后来他用了那么多颜色,完全走错了方向。
当我们将这个视频中的最终报告转换为黑白时,结果非常暗,尽管数据的对比度仍然可以。但是不同的酒吧不容易发现。
请记住,典型的商业用户并不关心颜色,只要数据准确且易于使用。
参考
IBCS —国际商务交流标准—IBCS 规则的网站,提供该规则手册的在线版本。
我使用 Contoso 样本数据集,就像我以前的文章一样。你可以从微软这里免费下载 ContosoRetailDW 数据集。
Contoso 的数据可以在麻省理工学院的许可下自由使用,正如这里的所描述的。
我扩大了数据集,使 DAX 引擎工作更努力。
在线销售表包含 7100 万行(而不是 1260 万行),零售表包含 1850 万行(而不是 340 万行)。
https://medium.com/@salvatorecagliari/membership
如何用 Python 和熊猫把 CSV 文件转换成 XLSX 文件
如何使用 Python 转换文件的示例
亚历克斯·丘马克在 Unsplash 上的照片
ython 是一种非常灵活的编程语言。有人会说这是“万事通,无所不能”;但是,在我看来,它在许多任务中提供帮助的能力——从“基本编程”到机器学习——是 Python 的真正力量。
几天前,我想分析一些可以从网站上下载的数据,以便用 Tableau 做一些练习。不幸的是,当我试图下载 excel 格式的数据时——这是 Tableau 可以接受的格式之一——我收到了一条错误消息。所以我试着下载 CSV 格式的数据,没有任何问题。
事实是,Tableau 甚至接受 CSV 文件,但我们必须做一些调整,我更喜欢使用 XLSX 文件。所以问题是:我如何将 CSV 文件转换成 XLSX?嗯,我会用 Python!因此,在本文中,我们将看到如何做到这一点。
数据的来源
我想分析欧洲的粮食产量,我发现粮农组织网站给了我们一些数据(链接此处)可以下载使用。但是当我试图下载 XLXS 中的数据时,出现了错误:
粮农组织网站的错误。图片作者。
当然,我已经尝试了我能做的任何事情:我试了几次重新下载数据,改变选择,改变电脑,等等…但是我仍然得到同样的错误。所以,我试着用 CSV 格式下载它们,然后…砰!第一时间下载数据。
所以,现在,我遇到了将 CSV 文件转换成 XLSX 文件以加载到 Tableau 中的问题。让我们看看我是怎么做的。
用熊猫将 CSV 转换为 XLSX
因为我们处理的是 CSV,所以我们可以像往常一样打开熊猫:
import pandas as pd#opening data
grain = pd.read_csv('grain.csv')#showing head
grain.head()
下载的数据帧。图片作者。
如果我们稍微研究一下数据,我们会发现有些国家的产值为 0 吨。因此,在保存 Tableau 的数据之前,因为我们使用 Python,所以删除这些行可能是个好主意。我们可以用下面的代码来实现:
#selecting rows with 'Value'!=0
grain = grain.loc[grain['Value']!=0]
现在,我们终于准备好将 CVS 转换成 XLSX 我们可以通过下面的代码轻松做到这一点:
#saving to xlsx
grain.to_excel('grain_excel.xlsx')
这样,我们简单地将文件保存在 XLSX 中,将其命名为“grain_excel.xlsx”。
概括代码
假设我们只想转换文件,而不清理数据;我们可以创建这样一个简单的脚本:
import pandas as pd#opening data
open_data = pd.read_csv('input_file.csv')#saving to xlsx
open_data.to_excel('output_file.xlsx')
上面的代码只是打开一个你需要命名为“input_file.csv”的 CSV 文件,返回一个 Excel 文件,命名为“output_file.xlsx”。您可以将此代码另存为”。py”文件,并在需要时运行它。就这么简单。
结论
我们已经看到,如果我们需要,将 CSV 文件转换成 XLSX 文件是多么容易。熊猫是一个非常强大的库,可以帮助我们完成这个简单的任务。
然后,如果我们需要多次做这样的转换,我们可能会创建一个通用的”。py”转换器文件,这样我们就可以在任何需要的时候运行它,它可以非常快速轻松地完成工作。
我们一起连线吧!
LINKEDIN (向我发送连接请求)
如果你愿意,你可以 订阅我的邮件列表 这样你就可以一直保持更新了!
考虑成为会员:你可以免费支持我和其他像我一样的作家。点击 这里的 成为会员。
如何在 Python 中将 Shapefile 转换为 DataFrame
原文:https://towardsdatascience.com/how-to-convert-a-shapefile-to-a-dataframe-in-python-a6ca9a893504
数据操作
如何在 Python 中将 Shapefile 转换为 DataFrame
GeoPandas Python 库概述,附带一个分步示例
由 Unsplash 上的 GeoJango Maps 拍摄
数据科学应用程序通常需要处理地理空间中数据。Shapefiles 是存储使用基于文件的数据库组织的地理空间数据的文件。GIS 专业人员、地方政府机构和企业使用 Shapefiles 进行制图和分析。
在这篇博文中,我将通过一个实际的例子描述一种用 Python 处理地理空间数据的优雅方式。我将使用 GeoPandas ,这是一个 Python 库,用于处理地理空间数据,如绘图、分析和绘图。GeoPandas 扩展了如此受欢迎的 Pandas 库来处理地理数据。我还将看看如何使用matplotlib
绘制结果。
可以通过以下命令安装 GeoPandas:
pip3 install geopandas
本教程组织如下:
- 加载数据集
- 绘图数据
- 几何上的操作
加载数据集
要加载地理数据集,我可以利用read_file()
函数,它会自动检测数据集的格式。如果文件是 shapefile,我应该确保包含 shapefile 的文件夹也包含。prj,。dbf,还有。shx 文件。
在本教程中,我利用了由 Map Cruzin 提供的包含意大利兴趣点的数据集。这个 shapefile 来源于OpenStreetMap.org,并在开放数据公共开放数据库许可 (ODbL)下获得许可。
**import** geopandas **as** gpddf **=** gpd.read_file('../../Datasets/italy-points-shape/points.shp')
df.head()
作者图片
几何字段可能包含点、多线、多边形等。数据集可能包含多个几何字段,但只能将一个几何字段设置为活动的。这可以通过set_geometry()
功能来完成。
df **=** df.set_geometry('geometry')
该文件作为 GeoPandas 数据帧加载。因为 GeoPandas 数据帧是 Pandas 数据帧的子类,所以我可以对我的 GeoPandas 数据帧使用 Pandas 数据帧的所有方法。例如,我可以通过shape
属性显示记录的数量:
df.shape
该数据集包含 47,427 个文件。
绘图数据
我可以绘制第一张地图,通过 GeoPandas 提供的plot()
功能。如果一个文件包含多个几何图形
df.plot()
作者图片
以前的地图太小,因此可以使用matplotlib
进行改进。首先,我可以增加体型。我定义了一个具有所需大小的subplot()
,然后将ax
变量传递给地理数据框架图:
import matplotlib.pyplot as pltfig, ax = plt.subplots(1, 1, figsize=(15, 15))
df.plot(ax=ax)
作者图片
我也可以根据类型栏改变点的颜色。这种类型的图称为 Chorophlet 图。我计算了不同类型的数量:
len(df['type'].value_counts())
有 301 种不同的类型。为了提高地图的可读性,我删除了点数小于 300 的类型。
target_types = df[‘type’].value_counts() > 300 tc = target_types[target_types == True].index**def** myfilter(x):
**return** x **in** tcdf['delete'] **=** df['type'].apply(**lambda** x: myfilter(x))
df **=** df[df['delete']]
现在我检查剩余类型的数量
len(df['type'].value_counts())
有 26 种类型。
现在,我简单地通过将column
属性传递给plot()
函数来绘制 Chorophlet 地图。我可以通过设置legend=True
来显示图例。
fig, ax **=** plt.subplots(1, 1, figsize**=**(15, 15))
df.plot(ax**=**ax, column**=**'type', legend**=True**, cmap**=**'viridis')
作者图片
有趣的是,大多数景点都位于意大利北部。
几何上的操作
GeoPandas 允许直接在几何域上进行许多操作。例如,我可以计算出每个点离给定点的距离,即意大利首都罗马。我通过points_from_xy()
函数将坐标转换成几何图形:
rome_longitude **=** [12.496365]
rome_latitude **=** [41.902782]
rome_point **=** gpd.points_from_xy(rome_longitude,rome_latitude)
然后,我计算df
中每个点离rome_point
的距离。我使用distance()
功能,该功能应用于活动几何图形:
df['distance'] **=** df['geometry'].distance(rome_point[0])
作者图片
我通过增加距离对数据集进行排序
df **=** df.sort_values(by**=**'distance', ascending**=True**)
最后,我只选择罗马附近的兴趣点,即距离小于 0.2
df_rome **=** df[df['distance'] **<** 0.2]
然后,我绘制出最终的数据帧:
fig, ax **=** plt.subplots(1, 1, figsize**=**(15, 15))
df_rome.plot(ax**=**ax, column**=**'type', legend**=True**, cmap**=**'viridis')
作者图片
摘要
恭喜你!您刚刚学习了如何通过 GeoPandas 用 Python 表示地理数据!
您已经了解了如何使用 GeoPandas 对地理数据执行高效操作。尽管 Pandas 在许多任务上表现出色,但它并不适合在位置感知应用程序中处理地理空间数据。GeoPandas 通过向 Pandas 添加非常适合地理空间数据的功能来解决这个问题。
你可以从我的 Github 库下载本教程的代码。
如果你已经走了这么远来阅读,对我来说今天已经很多了。谢谢!你可以在这篇文章中读到更多关于我的信息。
相关文章
如何将您的自定义模型转换为 TensorRT
原文:https://towardsdatascience.com/how-to-convert-your-custom-model-into-tensorrt-5a2ea1dec2e4
ML 提示和技巧/ TPAT
用 TPAT 缓解你紧张的疼痛
如果您曾经和 TensorRT 一起工作过,那么您可能会遇到类似的错误,对吗?
[E] [TRT] UffParser:验证器错误:resize/ResizeNearestNeighbor:不支持的 operation _ ResizeNearestNeighbor
在这篇博客中,我们将向您展示如何将带有自定义运算符的模型转换成 TensorRT,以及如何避免这些错误!
(图片来源:Rafael Pol 在 Unsplash 上拍摄的
Nvidia tensort是目前使用最广泛的 GPU 推理框架,能够优化使用 Pytorch 、 Tensorflow 、 mxnet 或 PaddlePaddle 构建的机器学习模型,以便在 NVIDIA 硬件上高效运行它们。众所周知,使用 TensorRT 图的 推理与本地运行模型相比,显著提高了推理速度和吞吐量 。
TensorRT 代表了最流行的深度学习框架和 NVIDIA 硬件之间的桥梁(来源:https://docs . NVIDIA . com/deep learning/TensorRT/quick-start-guide/index . html)
虽然使用 tensort 推理有很多好处,但是由于支持的操作符数量有限,真正的难点是手写 tensort 插件,以便支持在 tensort 中没有现成支持的自定义操作符。这使得部署过程变得不必要的复杂,并且可能需要几个小时甚至几天来优化和成功部署 tensort 模型,这需要编写多个定制 tensort 操作符。
TensorRT 插件自动生成工具-TPAT
近日,腾讯和 NVIDIA 公布了tensort Plugin Autogen 工具——TPAT,这是一款开源工具,可以支持开放神经网络交换(ONNX) 格式的所有运营商,端到端生成 tensort 插件。
(来源:https://www.tencent.com/en-us/media/library/images.html)
这是一个真正的游戏规则改变者,我们在 Forsight 立即开始使用它,以便进一步优化我们 ModelZoo 中的一些模型,并从我们的硬件中挤出更多的性能。
TPAT 实现了 TensorRT 插件的自动生成,TensorRT 型号的部署可以简化,不再需要人工干预。
TPAT 需要的唯一输入是 ONNX 模型和定制操作符的名称映射。TPAT 优化过程基于 TVM 深度学习编译器 ,对定形算子进行自动调优,自动生成高性能 CUDA 内核。必要的 CUDA 内核和运行时参数写在 TensorRT 插件模板中,用来生成动态链接库,可以直接加载到 TensorRT 中运行。
TPAT 确实是一个神奇的工具,因为它提供了以下优于手写插件和本地 TensorRT 操作符的优势:
⦁ 改善运营商覆盖:支持 ONNX、Tensorflow 和 PyTorch 的所有运营商
支持 TPAT 的运营商列表(来源:https://github.com/Tencent/TPAT/blob/main/docs/Operators.md
⦁ 全自动化:端到端全自动生成用户指定的 tensorrt 插件
⦁ 高性能:大部分操作者的性能都超过了手写或原装 tensorrt 插件
TPAT vs 手写插件性能对比(来源:https://github . com/腾讯/TPAT/blob/main/docs/Compare _ handled . MD)
TPAT 与原生 TensorRT 插件性能对比(来源:https://github . com/腾讯/TPAT/blob/main/docs/Optimize _ TensorRT . MD)
在 NVIDIA Jetson AGX Xavier 上使用 TPAT
为了使用 TPAT 和 TensorRT 优化您的模型,并在 NVIDIA Jetson AGX Xavier 上运行它,您应该使用以下 Docker 文件而不是 TPAT 报告中包含的文件来成功构建 TPAT Docker 映像。
FROM nvcr.io/nvidia/l4t-tensorflow:r32.4.4-tf1.15-py3RUN apt-get update && apt-get install build-essential cmake -yRUN wget -O "clang+llvm-9.0.1-aarch64-linux-gnu.tar.xz" https://github.com/llvm/llvm-project/releases/download/llvmorg-9.0.1/clang+llvm-9.0.1-aarch64-linux-gnu.tar.xz \&& tar -xvf clang+llvm-9.0.1-aarch64-linux-gnu.tar.xz && mkdir -p /usr/local/llvm/ \&& mv clang+llvm-9.0.1-aarch64-linux-gnu/* /usr/local/llvm/RUN python3 -m pip install --upgrade pipRUN pip3 install buildtools onnx==1.10.0RUN pip3 install pycuda nvidia-pyindexRUN apt-get install gitRUN pip install onnx-graphsurgeon onnxruntime==1.9.0 tf2onnx xgboost==1.5.2RUN git clone --recursive https://github.com/Tencent/TPAT.git /workspace/TPAT && cd /workspace/TPAT/3rdparty/blazerml-tvm && mkdir build && cp cmake/config.cmake build && cd buildRUN sed -i 's/set(USE_LLVM OFF)/set(USE_LLVM \/usr\/local\/llvm\/bin\/llvm-config)/g' /workspace/TPAT/3rdparty/blazerml-tvm/build/config.cmakeRUN sed -i 's/set(USE_CUDA OFF)/set(USE_CUDA ON)/g' /workspace/TPAT/3rdparty/blazerml-tvm/build/config.cmakeRUN cd /workspace/TPAT/3rdparty/blazerml-tvm/build/ && cmake .. && make -j8ENV TVM_HOME="/workspace/TPAT/3rdparty/blazerml-tvm/"ENV PYTHONPATH="$TVM_HOME/python:${PYTHONPATH}"
您可以使用以下命令构建 Docker 映像:
sudo docker build . -t tpat:master
注意:您应该连接外部存储器,并在那里构建 docker 映像,因为映像本身相当大,而 AGX 的内置内存有限。
成功构建映像后,您可以使用以下命令运行 Docker 容器:
sudo docker run --gpus all --shm-size=1g --ulimit memlock=-1 --ulimit stack=67108864 -it tpat:master
启动容器后,您应该确保您的 TPAT Makefile 中的计算能力对应于您的设备的计算能力。为了在 Jetson AGX Xavier 上成功构建 TPAT 插件,你应该在这个行上用-arch=sm_72
替换-arch=sm_75
。
现在你应该已经拥有了使用 TPAT 为你的模型自动生成定制插件所需的一切!
如何使用 TPAT 生成一个自定义的 TensorRT 插件?
为了在 Jetson Xavier AGX 上使用 TPAT 优化模型中的某些运算符,请遵循以下步骤。
首先,您应该运行需要以下参数的onnx_to_plugin.py
脚本:
usage: onnx_to_plugin.py [-h] -i INPUT_MODEL_PATH -o OUTPUT_MODEL_PATH
[-n [NODE_NAMES [NODE_NAMES ...]]]
[-t [NODE_TYPES [NODE_TYPES ...]]]
[-p PLUGIN_NAME_DICT]optional arguments:
-h, --help show this help message and exit
-i INPUT_MODEL_PATH, --input_model_path INPUT_MODEL_PATH
Please provide input onnx model path
-o OUTPUT_MODEL_PATH, --output_model_path OUTPUT_MODEL_PATH
Please provide output onnx model path which used for
tensorrt
-n [NODE_NAMES [NODE_NAMES ...]], --node_names [NODE_NAMES [NODE_NAMES ...]]
Please provide the operator name that needed to
generate tensorrt-plugin
-t [NODE_TYPES [NODE_TYPES ...]], --node_types [NODE_TYPES [NODE_TYPES ...]]
Please provide the operator type that needed to
generate tensorrt-plugin
-p PLUGIN_NAME_DICT, --plugin_name_dict PLUGIN_NAME_DICT
Please provide the dict of op name and plugin name
that will be generated by TPAT, such as : {"op_name" :
"plugin_name"}
我们提供了一个示例命令,该命令优化了model.onnx
图中的loop_function_1/OneHotEncoding/one_hot
运算符,并输出包含优化后的tpat_onehot
运算符的model_tpat.onnx
图:
OPENBLAS_CORETYPE=ARMV8 python3 onnx_to_plugin.py \
-i “model.onnx” \
-o “model_tpat.onnx” \
-p “{\”loop_function_1/OneHotEncoding/one_hot\” : \”tpat_onehot\”}”
运行该命令的结果是一个优化的 ONNX 图,其中不支持的操作符被 TPAT 生成的操作符替换。你可以在TPAT/python/trt_plugin/lib/
中找到 TPAT 生成算子动态库,应该命名为tpat_onehot.so
。
注意:您应该在运行 TPAT 转换脚本的命令前添加 *OPENBLAS_CORETYPE=ARMV8*
,以修复 Jetson Xavier AGX 设备上发生的 问题 。
model.onnx 图中的 OneHot 运算符与 model_tpat.onnx 图中的 tpat_onehot 运算符(来源:作者使用 Netron 生成的图片)
将 TPAT-翁克斯图优化成张量图
trtexec
是一款无需开发自己的应用程序即可快速利用 TensorRT 的工具。trtexec
工具有三个主要用途:
- 根据随机或用户提供的输入数据对网络进行基准测试。
- 从模型生成序列化引擎。
- 从生成器生成序列化定时缓存。
https://docs.nvidia.com/deeplearning/tensorrt/developer-guide/index.html#trtexec-ovr
可以使用下面的trtexec
命令将模型转换成 TensorRT 平面图格式:
trtexec --onnx=model_tpat.onnx \
--saveEngine=model.plan \
--buildOnly --verbose --fp16 \
--workspace=6000 --noTF32 \
--plugins=”./python/trt_plugin/lib/tpat_onehot.so”
请注意,您必须提供 TPAT 优化运算符的路径。
成功转换模型后,您可以使用以下命令来测量 TensorRT 模型性能:
trtexec --loadEngine=model.plan \
--verbose --workspace=4096 \
--streams=16 --threads \
--plugins=”./python/trt_plugin/lib/tpat_onehot.so”
就这样,您已经使用 TPAT 成功转换了 tensort 不支持的运算符,并优化了 tensort 图。你可以尝试这个过程,并在评论中分享你的见解和结果!
我们希望这篇博客对你有用,请看看我们团队在 Forsight 写的其他一些博客,如果你有任何问题,请随时通过 info@forsight.ai 联系我们!
https://medium.com/swlh/construction-feat-tf2-object-detection-api-4465a3937c87
参考
- https://github.com/Tencent/TPAT-TensorRT 插件自动生成工具()
- 腾讯和英伟达开源 TensorRT 插件自动生成工具 TPAT(https://www.codetd.com/en/article/13743533)
如何说服你的老板相信你的 ML/DL 模型
原文:https://towardsdatascience.com/how-to-convince-your-boss-to-trust-your-ml-dl-models-671f707246a8
使用 LIME 的机器学习模型可解释性,或者如何解释为什么模型做出了特定的预测
准确性与可解释性(图片由作者提供)
简介
一些公司经理或利益相关者对机器学习模型预测持悲观态度。因此,数据科学家有理由让他们相信模型预测是可信的,也是人类可以理解的。因此,我们不仅需要专注于创建强大的机器学习/深度学习模型,还需要使模型能够被人类解释。
可解释性在许多方面都有帮助,例如帮助我们理解模型如何做出决策,它证明模型预测是正确的并获得洞察力,建立对模型的信任,并且它帮助我们改进模型。有两种类型的 ML 模型解释——全局和局部。
- 本地解读回答问题,为什么模型做出这个具体的预测?
- 全球解读回答了这个问题,预测最重要的特征是什么?
可解释性是人类能够理解决策原因的程度[Miller,Tim 2017]
在本文中,我们将关注本地可解释性,而我们将涉及:
- 固有的可解释模型
- 局部解释方法:石灰
- 实际工作—解释玩具数据集上的 XGBoost 模型预测
- 石灰的利弊
1.固有的可解释模型
固有解释模型的好例子是线性回归和决策树。
1.1 线性回归
线性回归背后的直觉是,它将目标预测为输入特征的加权和。
线性回归公式(图片作者提供)
基于线性回归的假设函数,解释是如此容易。很清楚哪个特征贡献更大,哪个特征对预测最重要。但是任何事情都是有代价的——模型的正确性取决于训练数据中的关系是否满足某些假设,例如线性、正态性、同方差性、独立性、和无多重共线性。
可以在 上一篇 中看到线性回归算法的详细解释。
1.2 决策树
决策树也很容易解释。此外,它还可以处理特征之间的非线性关系,这是线性回归算法所无法做到的。决策树是通过基于某些标准(即基尼指数)进行分割来构建的,其中数据集的不同子集是通过分割来创建的。我们可以遵循从根节点到叶节点的树的结构,并理解为什么模型做出特定的预测。下面是一个可视化决策树示例。
决策树示例(图片由作者提供)
如果你想了解更多关于决策树是如何工作的,你可以访问我的上一篇文章。
2。局部解释方法:石灰
随着模型变得越来越复杂,预测能力越来越强,对预测的解释也变得复杂。复杂模型,也称为黑盒模型,如 XGBoost、随机森林和神经网络,本质上是不可解释的,因此它们需要额外的方法来理解它们的预测性质。 LIME 是一种局部解释方法,解释如何对黑盒 ML 模型进行单独预测。LIME 背后的直觉是,它创建了代理模型(即线性回归、决策树),该模型被训练为近似底层黑盒模型的预测。LIME 不是训练一个全局代理模型,而是专注于训练局部代理模型,以解释个体预测。这是下图所示的石灰配方。
石灰配方(图片由作者提供)
局部代理模型的数学表达式是:
哪里…
- 我们要解释的一个例子
- f-原始模型(即深度神经网络,XGBoost)
- g-代理模型(即线性回归、决策树)
- π_x 邻近度,它定义了新生成的数据集应该有多大。
- l 损失(即均方误差、交叉熵)
- ω(g)-模型复杂性
- G-一系列可能的解释(即所有可能的线性回归模型、线性回归、套索、岭)
在实践中,用户应该确定模型的复杂性,这意味着选择替代模型可以使用的最大数量的特征和样本。
3。实际工作 XGBoost 模型的可解释性
在这一节中,我们将讨论 LIME 的实际实现。我们将在来自 sklearn 的玩具数据集 load_breast_cancer 上做一个实验,这是一个带有标签的数据集,包含关于乳腺癌状况的信息,即它是良性还是恶性的。
步骤 1:导入库和数据集
首先,我们需要使用 pip 安装石灰来安装石灰包
数据帧结果(作者照片)
第二步:构建 XGBoost 模型
加载数据集后,让我们将数据分为训练和测试部分,使用默认超参数创建一个简单的 XGBoost 模型,并计算混淆矩阵和预测精度。
结果表明,该模型的准确率为 96%;现在是解释个别预测的时候了。
第三步:创建代理模型
现在我们创建一个 lime 表格解释器对象,它将尝试解释单个样本。将在新创建的包含 5000 个扰动样本的数据集上训练代理模型。
步骤 4:解读单个样本。
在这种情况下,我将尝试对两个随机样本进行解释。一个样本被正确分类,而另一个被错误分类。
示例 1(图片由作者提供)
示例 2(图片由作者提供)
如可视化所示,颜色 蓝色和橙色** 分别代表 消极和积极** 联想。
第一个样本是正确分类的示例,它被分类为良性类。让我们来回答这个问题— 为什么这个样本被归类为良性?因为代理模型说如果特征【最差纹理】 ≤21.05 或者【最差凹点】 > 0.06 或者【最差凹点】 > 0.12 或者【面积误差】 ≤ 18.17 或者【平均凹点】 > 0.1 那么他们倾向于预测为良性。该样本的所有特征值都满足这些条件,因此该示例被分类为良性。
第二个样本分类错误。问题— 为什么这个样本被错误地归类为良性,尽管它是恶性的?因为从上面的可视化来看,代理模型说前五个特征中的三个特征满足良性属性,并且它们的特征的加权和大于满足恶性属性的特征的加权和。这就是为什么这个特殊样本被错误分类的原因。
4。石灰的利弊
石灰法的优点是它使解释更人性化。尽管我们讨论了使用表格数据的例子,但是 LIME 也可以用于文本和图像数据。LIME 的缺点之一是采样的数据点来自高斯分布,忽略了特征之间的相关性。此外,有时解释可能不稳定。因为 LIME 是一个近似值,所以当法律要求您完全解释预测时,它不是一个充分的方法。
结论
综上所述,LIME 是一个强有力的方法,它回答了我为什么要相信 ML 模型,以及为什么该模型做出了这个具体的预测?它创建了一个局部代理模型,与初始黑盒模型有很好的近似,这使得个体解释更容易。由于模型是可解释的,数据科学家也更容易让管理者和利益相关者相信预测是可信的。
*希望你喜欢:),这里也是我 GitHub 上的*全代码 。
下一篇文章将是关于任何 ML/DL 模型的全局可解释性。
你可以 关注我 上 中 保持通知。
如果你想了解更多关于应用数据科学的知识,这里有 我的 YouTube 频道 。
*https://www.youtube.com/channel/UCvlF0PPaQ2GAuqYKJT4UpJQ
参考文献:
[1] Molnar,Christoph“可解释的机器学习。让黑盒模型变得可解释的指南”(2019)
[2]米勒,蒂姆“人工智能中的解释:来自社会科学的见解”(2017)
[3]马尔科·图利奥·里贝罗《机器学习的模型不可知可解释性》(2016)*
如何破解 R 中打开的 NetCDF 文件并提取数据为时间序列
获取免费的气候数据可能很棘手——以下是方法
作者图片
今天,很多事情都可以用气候和天气数据来分析:农业生产、旅游、销售、应急管理、建筑、移民、过敏或你每年的冰淇淋零食。但是我们从哪里得到这些数据呢?
幸运的是,我们在无云的夜晚看到的许多闪亮的轨道光点——卫星——正在为我们收集数据做大量艰苦的工作。这些卫星背后的许多倡议甚至让我们所有人免费使用这些数据。但是一些免费的数据可能不像人们想象的那么容易获取。
我第一次碰到一个.nc
文件时非常沮丧。最初,我很兴奋地发现我需要的数据显示“免费下载”,但我几乎立即放弃了我想做的事情,因为我不知道如何阅读这个文件,它有一个我从未见过的奇怪的'.nc'
结尾。最初的谷歌搜索对我来说毫无意义:大量 MATLAB 和 Python 的教程——那时我只知道一些非常基本的 R 。
最终,我学会了如何做这件事,以及此后的许多其他事情(在这个过程中,我流了一些眼泪),但我陷入了“也许我是唯一一个不知道这件事的人”这种老掉牙的骗子思维陷阱。我从来没有想过为它写一个教程。最近,我的一个朋友在一个 nc 文件上遇到了类似的问题;我把我的剧本发给她,几天后她发短信给我:“保存。你应该把这个公之于众!”。
本教程早就应该发布了。因此,如果您陷入了类似的困境,或者您也意识到 NetCDF 文件已经存在:我希望本教程能够有所帮助!
什么是 NetCDF?
卫星数据是 大量 的数据;大量多维数据(纬度、经度、时间和一个变量——或者更多!-感兴趣的,比如温度)。
通常,我们可以看到按日、周、月或年描述平均温度的分析…但原始数据远不止这些。例如,一些从 Envisat 卫星测量水温的传感器一天几次收集数据。然后对这些进行处理,以考虑混浊度和其他质量控制方面,并每天给你一个“干净”的值。通常情况下,您不必担心这一部分(不过,如果您感兴趣,可供下载的数据通常有关于如何清理的附加文档)。
但是产生的数据仍然是大量的数据,并且大量的数据意味着巨大的文件大小。因此,卫星数据必须打包成小文件,以便像你我这样的人可以轻松下载和访问。输入 NetCDF。
NetCDF 文件是开放地理空间联盟的标准。它代表“网络公共数据表单”(虽然,如果你问我,称它为“公共”有点夸张)。NetCDF 文件允许所有这些数据放在一个小文件中,我们可以轻松下载。不过,在 NetCDF 文件中存储气候、其他环境和生物信息学数据确实越来越普遍了。所以我们不妨习惯使用它们!
有一些软件使得探索 NetCDF 文件看起来更简单,但是它们也有局限性。有些只适用于 Windows,需要许可证,或者需要您安装额外的程序,而有些则严格用于可视化数据。但有时您可能需要对这些类型的数据做不同的事情,可能需要一个温度的时间序列数据集来用于您自己的业务或研究数据,而这些其他选项无法帮助您。使用像 R 这样的语言访问 NetCDF 文件给了你更多的控制和定制选项,让你可以对可用的数据做些什么。
如 Unidata 中所述,这些是 NetCDF 文件的主要特征:
- 机器无关(不管你用的是 Windows 还是 Mac 无论您想用 R、Julia、Python 还是 MATLAB 来研究 nc 文件,您都可以!)
- 面向多维数组的数据(也称为栅格数据或网格数据)
- 自描述(文件元数据和属性包含在文件本身中)
- 可移植(可由任何操作系统访问,与它们如何存储和读取数据无关)
数据源
根据您需要的数据来自世界的哪个部分,有时可能比其他地方更难获得可靠的数据集。幸运的是,你可以从哥白尼、 CEDA 或 NOAA (以及更多来源)免费下载大量好数据。气温、土地温度;森林覆盖、植被物候;海洋、湖泊和河流温度;这样的例子不胜枚举。大部分使用 NetCDF 格式(文件以.nc
结尾)。
对于本教程,我将使用来自 GloboLakes 的数据。我特意从下载了阿蒂特兰湖的数据,其中包含从 1995 年到 2016 年的湖面水温(LSWT) 的每日观测数据,这些数据来自 Envisat 和 ERS-2 卫星上不同辐射计的组合(如果感兴趣,在提供的链接中有更多关于它们如何组合和协调的细节)。我将指导您如何访问数据,并将其转换成一个时间序列,保存在一个【normal】data . frame 和.csv
文件中。
让我们开始吧:如何打开那个文件
我假设这不是你第一次使用 R,并且你已经将你的工作目录setwd()
设置为你保存.nc
下载的地方。你可以在这里访问本教程的完整 R 脚本。
首先,装入我们需要的包:
# ncdf4: this package lets you manipulate netCDF files. Unlike the ncdf package, the ncdf4 supports both NetCDF3 and NetCDF4 formats.**> library(ncdf4)****> library(tidyverse)** # because who can live without the tidyverse?
我们将使用nc_open
功能打开您的.nc
文件。我们会将文件存储在our_nc_data
vector 中,并立即打印出来,以探索其中的内容(记住,了解您的数据是任何分析过程中必不可少的第一步!).
**> our_nc_data <- nc_open("/your_path/file.nc")****> print(our_nc_data)**
您应该得到一个变量及其详细信息的列表,如下所示:
File GloboLakes/LAKE00001479-GloboLakes-L3S-LSWT-v4.0-fv01.0.nc
**6 variables** (excluding dimension variables):
short **lake_surface_water_temperature**[lon,lat,time]
**_FillValue:** -32768
**units: Kelvin**
scale_factor: 0.0099999
add_offset: 273.1499938
**long_name: lake surface skin temperature**
valid_min: -200
valid_max: 5000
**comment:** The observations from different instruments have been combined.
**standard_name: lake_surface_water_temperature**
short **lswt_uncertainty**[lon,lat,time]
**<its metadata similar to the first one above>** byte **quality_level**[lon,lat,time]
**<its metadata similar to the first one above>** byte **obs_instr**[lon,lat,time]
**<its metadata similar to the first one above>** byte **flag_bias_correction**[lon,lat,time]
**<its metadata similar to the first one above>** int **lakeid**[lon,lat]
**<its metadata similar to the first one above>**
我们的六个变量是湖面水温(lswt)、lswt 不确定性、质量水平、仪器(obs_instr)、旗偏差校正和 LakeID。
它还应该打印一个维度列表和一个全局属性列表:
3 dimensions:
**lat Size:23
long_name: latitude
standard_name: latitude**
units: degrees_north
valid_min: -90
valid_max: 90
axis: Y
reference-datum: geographical coordinates, **WGS84** projection **lon Size:24
long_name: longitude
standard_name: longitude**
units: degrees_east
valid_min: -180
valid_max: 180
axis: X
reference-datum: geographical coordinates, **WGS84** projection ** time Size: 2622** *** is unlimited ***
long_name: reference time of the lswt file
standard_name: time
** units: seconds since 1981-01-01 00:00:00
calendar: gregorian**49 global attributes:
**<more metadata that you can explore on you own>**
花一分钟通读信息,了解你的数据。注意,对于这个 GloboLakes 文件:
- 我们有 6 个变量(在本教程中,我们将重点放在第一个变量上,lake _ surface _ water _ temperature[lon,lat,time];注意单位是开尔文)。
- 请注意 3 个维度的详细信息(纬度= 23,经度= 24,时间= 2622;自 1981–01–01 00:00:00 公历以来,纬度和经度以北纬和东经度为单位,时间单位以秒为单位)
- _FillValue 是表示缺失值的方式(我们稍后需要将其更改为 R 识别为缺失值的“NA”)。
- 您可以自己探索全局属性(基本上是更多的元数据)
由于我们下载了一个湖的每日 LSWT 数据,现在我们对我们的数据有了更多的了解,我们可以有把握地说:我们有阿蒂特兰湖 24×23(经度×纬度)切片的 2622 天的平均开尔文 LSWT 数据。我认为用视觉更简单:
ncdf 文件中数据的可视化表示。图片作者。
让我们把坐标和时间维度作为它们自己的变量
现在您知道了文件中的内容,就更容易知道如何调用每个变量以及您实际需要哪些变量。为了确保您调用了正确的变量,您可以使用函数attributes()
来获取文件中变量和维度的名称。然后我们将用函数ncvar_get()
把的纬度、经度、时间提取到自己的对象中。我们还将用函数ncatt_get()
提取它们的一些属性。
**> attributes(our_nc_data$var)
> attributes(our_nc_data$dim)**# Get latitude and longitude with the ncvar_get function and store each into their own object:**> lat <- ncvar_get(our_nc_data, "lat")
> nlat <- dim(lat) #to check it matches the metadata: 23****> lon <- ncvar_get(our_nc_data, "lon")
> nlon <- dim(lon) #to check, should be 24**# Check your lat lon dimensions match the information in the metadata we explored before:**> print(c(nlon, nlat))**# Get the time variable. Remember: our metadata said our time units are in seconds since 1981-01-01 00:00:00, so you will not see a recognizable date and time format, but a big number like "457185600". We will take care of this later**> time <- ncvar_get(our_nc_data, "time")
> head(time)** # just to have a look at the numbers **> tunits <- ncatt_get(our_nc_data, "time", "units")** #check units **> nt <- dim(time)** #should be 2622
你还和我在一起吗?
现在让我们提取表面温度数据
我们继续使用ncvar_get()
函数获取变量,使用ncatt_get()
获取属性。
#get the variable in "matrix slices"
**> lswt_array <- ncvar_get(our_nc_data, "lake_surface_water_temperature")
> fillvalue <- ncatt_get(our_nc_data, "lake_surface_water_temperature", "_FillValue")****> dim(lswt_array)** #to check; this should give you 24 23 2622#right away let's replace the nc FillValues with NAs
**> lswt_array[lswt_array==fillvalue$value] <- NA
> lswt_array**
我们完成提取了!
到目前为止一切顺利!但是我们仍然有不可读(至少不是人类可读)的时间。此外,我们仍然在处理 4D 的情况,变量在它们自己的对象中,为了获得时间序列,我们仍然需要将其展平到 2D“正常”或更方便的数据框架。
人类可读时间
如果我们打印我们的tunits
,它会提醒我们时间变量是“自 1981–01–01 00:00:00 以来的秒数”。但是如果我们打印time
我们仍然会看到一个类似“457185600”的数字。我们可以将其转换为“正常”的年-月-日格式:
**> time_obs <- as.POSIXct(time, origin = “1981–01–01”, tz=”GMT”)****> dim(time_obs) #should be 2622****> range(time_obs)** [1] "1995-06-28 12:00:00 GMT"
[2] "2016-12-31 12:00:00 GMT"#Looks good
太好了!现在,你知道你的数据在你的元数据所说的范围内,而不是一个疯狂的长数字:在 1995 年到 2016 年之间。
现在让我们看看您之前创建的 lswt_array
数组的每个“切片”是 23 个纬度和 24 个经度点的时间点,每个纬度时间的组合都有自己的开尔文温度记录(打印dim(lswt_array)
应该返回“24 23 2622”)。
中数据的可视化表示。nc 文件(湖的轮廓、日期和其他特定值仅在您使用与我相同的 GloboLakes 文件时适用)。注意我说的“切片”是什么意思。作者图片
如果你打印lswt_array
,你会看到一个类似矩阵的“切片”。在这个特定的数据集中,您还会注意到有许多缺失值(NAs)。会不会只是前两个被印出来?您可以使用以下代码打印不同的单个切片,其中括号内的信息应该是:[lon, lat, slice]
并且 slice 是 1 到 2622 之间的一个数字(时间变量的大小,换句话说,就是数据集中的天数)。
# try it out:**> lswt_slice <- lswt_array[ , , 2123]
> lswt_slice <- lswt_array[ , , 25]** # and why not, draw it out:
**> image(lon, lat, lswt_slice)**
在尝试了 1-2622 之间的几个随机切片后,我注意到中心周围有许多缺失值,所以我仔细检查了湖泊所在的纬度和经度范围以及数据集包含的范围。事实证明,我们的数据网格中有很多空间是在陆地上,而不是在湖泊上,所以自然地,没有这些点的水温数据。
所以我在谷歌地图上做了一个快速的手动检查,这个湖大约在 14.61n-14.75n 和 91.3W-91.10W 之间。我们的整个数据超过了这个区域。
为了使我们的最终文件更小,我们将去掉那些额外的点。只是还没有。我们仍然没有数据框架,只有 4 个独立的变量或对象。如果我们现在从 lswt_array 中删除 NAs,我们以后将无法知道剩余的值中哪些属于哪个 lon、lat 和 time。
让我们构建数据框架
首先,我们创建整个矩阵,以免丢失匹配的时间和温度:
#Create 2D matrix of long, lat and time**> lonlattime <- as.matrix(expand.grid(lon,lat,time_obs))** # this might take several seconds#reshape whole lswt_array**> lswt_vec_long <- as.vector(lswt_array)
> length(lswt_vec_long)** # by now it should be 1447344#Create data.frame**> lswt_obs <- data.frame(cbind(lonlattime, lswt_vec_long))**
您的lswt_obs
现在应该是这样的:
**> head(lswt_obs)**
Var1 Var2 Var3 lswt_vec_long
1 -91.775 14.125 1995-06-28 12:00:00 <NA>
2 -91.725 14.125 1995-06-28 12:00:00 <NA>
3...
没关系。但是让我们给这些列起一个合适的名字。
**> colnames(lswt_obs) <- c(“Long”,”Lat”,”Date”,”LSWT_Kelvin”)****> head(lswt_obs)**
Long Lat Date LSWT_Kelvin
1 -91.775 14.125 1995-06-28 12:00:00 <NA>
2 -91.725 14.125 1995-06-28 12:00:00 <NA>
3...
现在我们正在到达那里。事实上,它已经有了你需要的数据,但是它仍然有许多不必要的东西,这将导致一个巨大的。我们不需要的 csv 文件。
让我们把它整理成一个有用的数据框
正如我之前所说,我们在陆地上有很多空地。但是如果您尝试几个 lswt_slices,您会看到网格中还有一些湖泊空间在不同的日期有缺失值(NAs)。由于我们今天的目标是获得一个时间序列数据框架,我认为我们可以从这里走两条路(可能会有更多,如果你想采取不同的方法,请在评论中告诉我!):
选项 1:选择一对特定的坐标[lat,lon],只保留该特定位置随时间变化的温度数据,删除其他所有数据(如果愿意,也可以用几对坐标来做这件事)。使用此选项,您可以拥有不同坐标的多个时间序列(每个时间序列都有不同数量的 NAs,您必须根据您对数据的处理来决定以后如何处理)。
选项 2:只删除所有的 NAs(不管你是否删除那些在水面上的 NAs ),然后取所有可用温度数据到日期的平均值,得到整个可用湖面区域每天的平均 LSWT。有些日期会比其他日期有更多的值。
最终结果将是相同的(一个带有日期和温度的数据帧),但是您的温度值可能会略有不同。
选项的可视化表示。作者图片
对于本教程,我将选择选项 2。请记住:只要你“全盘托出”你对最终文档中的数据所做的一切,以便它可以被适当地解释和复制,(几乎)一切都是有效的!
# Bold move time: remove all rows with NA in LSWT_Kelvin:
**> lswt_final <- na.omit(lswt_obs)**
唷!那就少了很多数据!您可以通过dim()
查看:
**> dim(lswt_obs)**
**1447344** 4**> dim(lswt_final)**
**15308 ** 4
我们仍然有超过 2622 个日期(15308),因为我们在同一天仍然有几个温度点(此外,2622 不是 1995-2016 年之间的总天数,因为卫星也有寿命-或困难)。
在构建我们的时间序列数据集时,我们不再需要纬度和经度,因为我们将按日期计算平均温度。让我们来解决这个问题:
# remove lat & long columns
**> lswt_final <- lswt_final[-c(1:2)]
> lswt_final
** Date LSWT_Kelvin
<chr> <chr>
1 1995-06-28 12:00:00 296.63999
干得好。但是现在你可以看到在列名(日期和 LSWT 开尔文)下面有一个<chr>
提醒我们它们都是以字符或字符串的形式存储的(如果你没有看到它们,你可以用glimpse()
来检查你的数据类型)。让我们来解决这个问题,因为我们不能接受字符串的mean()
!
**> lswt_final$Date <- as.Date(lswt_final$Date)
> lswt_final$LSWT_Kelvin <- as.double(lswt_final$LSWT_Kelvin)**
太棒了。现在让我们来看看日平均温度:
**> lswt_final <- lswt_final %>%
group_by(Date) %>%
summarize(Mean_K = mean(LSWT_Kelvin))**
**> lswt_final**
Date Mean_K
<date> <dbl>
1 1995-06-28 297.79
2 1995-07-11 297.07
3 1995-07-17 296.99
4 ...**> dim(lswt_final)** 2622 2
# that seems about right!!!
呜哇!基本上,你完成了,但是让我们给它一个最后的触摸,把开尔文变成摄氏度。
**> lswt_C <- lswt_final %>%
mutate(LSWT_C = Mean_K-273.15)**
现在你知道了!您现在可以使用它,或者将其保存在.csv
文件中,或者以您需要的任何形式保存。
# save as csv
**> write.csv(as.data.frame(lswt_C), "GloboLakes_Atitlan_TS_95_16.csv", row.names=T)**
以下是您现在拥有的简单线图(请记住,这些数据仍需要清理):
作者图片
现在,您可以继续使用这些数据做任何您需要的事情了!
点击查看的完整脚本。
不要害怕 NetCDF 文件!
因此,如果你选择语言和专业知识是 r,不要让一个你以前从未见过的神秘的不受欢迎的文件吓得你不敢完成你想的项目。现在就去打开那些 nc 文件吧!
我试图使这成为一个浓缩的教程,为你的进一步清理和分析提供一个基本的时间序列,但是如果你已经迷上了,并且想知道更多 nc 文件背后的理论和你能做的其他事情,这里是我使用的参考和其他推荐的进一步阅读:
- Unidata Data Services and Tools for Geoscience(“一个提供数据服务、工具和网络基础设施领导力的社区,旨在推进地球系统科学并增加教育机会”)。
- 本教程中使用的数据来自 Carrea,L. & Merchant,C.J. 2019。 GloboLakes:湖泊表面水温(LSWT)v 4.0(1995–2016)。环境数据分析中心。
- David W. Pierce 的 ncdf4 包的文档
- 这个视频快速演示了如何将 ncdf 文件与 Panoply、QGIS 和 Python 等其他工具一起使用
- 鲍曼,p;米塞夫博士;Merticariu,v;范虎生于 2021 年。阵列数据库:概念、标准、实现。大数据杂志。
如何破解 Spotify 数据科学技术屏面试
要了解 Spotify 技术屏幕,您应该知道的确切 Python/SQL 命令和实验主题列表
图片来源: @felipepelaquim
如果你正在准备 Spotify 的技术筛选或技术面试,那么你很可能在寻找以下问题的答案:
- 我该如何开始准备 Spotify 数据科学技术面试?
- 我能从 Spotify 数据科学技术采访中得到什么?
本文将涵盖以下主题:
**- Tech Screen Duration
- Part 1: Python Question
- Part 2: SQL Question
- Part 3: A/B Testing Question**
技术屏幕持续时间
这个技术面试大约需要 45 分钟,分为三个部分:Python、SQL 和实验。
图片来源: cottonbro
第 1 部分:Python 问题
第一个技术屏幕问题通常是数据争论或数据转换问题,这应该在 Python 中进行,尽管您也可以在 SQL 中进行。这个问题旨在了解你是否能利用 Python 中的过滤、聚合等一些基本概念。是否可以利用两个最流行的库: Pandas 和 NumPy。
示例问题
如何修复某个特定设备的数据因为某种原因减半的数据中的 bug?
学习 Pandas 中的基本功能,如分组、求和、平均、过滤(单值和多值),如:
- df.groupby("x")
- df.groupby("x")["y"]。sum()
- df.groupby("x")["y"]。avg()
- df[df["x"] == k]
- df[df.x.isin([k,l])】
学习 Numpy: 中的基本过滤功能
- df["new_vb"] = np.where(条件,条件为真时的值,条件为假时的值)
第 2 部分:SQL 问题
技术屏幕上的第二个问题是 SQL 中的编码问题,您需要了解基本的 SQL 函数来过滤数据,执行两个数据之间的连接,同时深入了解 A/B 测试的概念。
要解决这个问题,你需要熟悉 A/B 测试背后的基本概念,例如控制组与实验组,选择主要的成功或绩效指标,并对这两组中的每一组进行计算。你需要了解的关于 A/B 测试解决这个问题的一切都可以在这里找到:https://towardsdatascience . com/simple-and-complet-guide-to-A-B-testing-c 34154d 0 ce 5 A
要解决这个问题,请学习以下 SQL 中的基本函数:
- 选择
- 计数
- AVG
- 左连接,右连接
- 其中
- 分组依据
- 有
- 排序依据
- 极限值
您应该能够计算指标,如每个控制和实验组的平均屏幕时间,其中用户信息在一个表中,而屏幕时间在另一个表中。这意味着您应该能够连接两个表,并且只为参与 A/B 测试的用户保留数据(左连接或右连接),这取决于您选择的表顺序。
例如:
您需要记住的一点是,您只需要 A/B 测试用户在 A/B 测试开始后的使用数据。
第 3 部分:A/B 测试问题
面试的第三部分也是最后一部分是关于 A/B 测试的。这些是静态问题,你可以在每一次与实验相关的面试中找到,例如:
- p 值
- 统计显著性
- 假设检验
- t 检验与 z 检验
- 置信区间
- 第一类和第二类错误
- 更多
研究以下两篇博文,它们包含了所有基本的统计概念,如 p 值等,以及关于 A/B 测试的内容,然后你将能够回答在技术屏幕的最后部分提出的所有问题。
图片来源: cottonbro
免责声明 :你可以在 Glassdoor.com 等网站上找到更多关于 Spotify 或任何其他公司面试问题类型的信息。
如果你喜欢这篇文章,这里有一些你可能喜欢的其他文章:
https://tatev-aslanyan.medium.com/data-sampling-methods-in-python-a4400628ea1b https://medium.com/analytics-vidhya/pyspark-cheat-sheet-big-data-analytics-161a8e1f6185 https://tatev-aslanyan.medium.com/bias-variance-trade-off-in-machine-learning-7f885355e847 https://levelup.gitconnected.com/predicting-bitcoins-price-with-recurrent-neural-networks-a27b4d2d839
感谢阅读
我鼓励你 加入 Medium*来拥有* 完整访问我所有关于数据科学、机器学习、AI 和其他主题的文章。
关注我 中阅读更多关于各种数据科学和数据分析话题的文章。更多机器学习的动手应用,数学和统计概念查看我的*Github*账号。
欢迎反馈,可在LinkedIn上联系。****
快乐学习!