增强树的概率校准
**背景:**概率校准的开创性论文:http://www . cs . Cornell . edu/~ caru ana/Niculescu . scldbst . CRC . rev 4 . pdf
增强决策树通常会产生良好的准确度、精确度和 ROC 面积。然而,因为来自增强的输出不是很好校准的后验概率,所以增强产生差的平方误差和交叉熵。它倾向于保守地预测概率,意味着更接近于中间值而不是极端值。以下是提升对预测概率的影响:
校准良好的分类器是概率分类器,其模型的输出可以直接解释为置信度。例如,校准良好的(二元)分类器应该对样本进行分类,使得在它给出接近 0.8 的预测值的样本中,大约 80%实际上属于正类。下图比较了不同分类器的概率预测的校准情况:
默认情况下,LogisticRegression 返回校准良好的预测,因为它直接优化了对数损失。相反,其他方法返回有偏差的概率;带着不同的偏见。
执行概率预测校准的两种方法是:基于 Platt 的 sigmoid 模型的参数方法和基于保序回归的非参数方法。应使用不用于模型拟合的测试/验证数据进行概率校准。
普拉特标度:
普拉特的缩放相当于在分类器输出上训练逻辑回归模型。
您实际上创建了一个新的数据集,它具有相同的标签,但只有一个维度(未校准分类器的概率输出)。然后,在这个新的数据集上进行训练,并将未校准的分类器的概率输出作为这个校准方法的输入,该方法返回一个校准的概率。在 Platt 的情况下,我们本质上只是对未校准分类器相对于真实类别标签的概率输出执行逻辑回归。
逻辑回归模型是 f(x)= y。y 是输入数据的真实标签,x 是基本分类器的预测概率。现在,您使用逻辑回归的预测概率作为校准分类器的真实概率。
保序回归:
其思想是拟合分段常数非减函数,而不是逻辑回归。分段常数非递减意味着阶梯形。通过池相邻违规者算法(PAVA)实现。PAVA 是线性排序保序回归的线性时间(和线性记忆)算法。
训练保序回归的方法是相似的:
f(x) = y,y 是输入数据的真实标签,x 是基本分类器的预测概率。等渗模型将通过 x(基础分类器的预测概率)对数据进行分类,然后拟合一个阶跃函数来给出真实标签的概率。
其他资源:
http://fastml . com/classifier-calibration-with-Platts-scaling-and-isotonic-regression/
https://jmetzen.github.io/2015-04-14/calibration.html
【https://scikit-learn.org/stable/modules/calibration.html
解释概率概念:参数估计的贝叶斯推断。
介绍
在之前的博文中,我提到了机器学习和统计模型中参数估计的最大似然法。在这篇文章中,我们将回顾另一种使用贝叶斯推理的参数估计方法。我还将展示如何将这种方法视为最大似然法的推广,以及在什么情况下这两种方法是等价的。
假设了一些概率论的基础知识,例如边际概率和条件概率。这些概念在我的系列的第一篇文章中有解释。此外,了解高斯分布的一些基本知识也很有帮助,但这不是必需的。
贝叶斯定理
在介绍贝叶斯推理之前,有必要了解一下贝叶斯定理。贝叶斯定理真的很酷。它的有用之处在于,它允许我们使用一些我们已经拥有的知识或信念(通常称为先验)来帮助我们计算相关事件的概率。例如,如果我们想找出在炎热晴朗的日子里卖冰淇淋的概率,贝叶斯定理为我们提供了工具,让我们利用先验知识来判断在任何其他类型的日子里(下雨、刮风、下雪等)卖冰淇淋的概率。).我们稍后会详细讨论这一点,所以如果你还不明白,请不要担心。
数学定义
数学上,贝叶斯定理被定义为:
其中 A 和 B 是事件, P(A|B) 是事件 A 发生的条件概率,假设事件 B 已经发生( P(B|A) 具有相同的含义,但是具有 A 和 B 反转的角色)以及 P(A) 和
例子
数学定义常常让人觉得太抽象和可怕,所以让我们用一个例子来理解这一点。我在介绍性博客文章中给出的一个例子是关于从一包传统扑克牌中挑选一张牌。一副牌中有 52 张牌,其中 26 张为红色,26 张为黑色。假设我们知道这张牌是红色的,那么这张牌是 4 的概率是多少?
为了把它转换成我们在上面看到的数学符号,我们可以说事件 A 是牌是 4 的事件,事件 B 是牌是红色的。因此,上式中的 P(A|B) 就是我们例子中的 P(4|red) ,这就是我们要计算的。我们之前计算出这个概率等于 1/13(有 26 张红牌,其中两张是 4),但是让我们用贝叶斯定理来计算。
我们需要找到右边各项的概率。它们是:
- P(B|A) = P(red|4) = 1/2
- P(A) = P(4) = 4/52 = 1/13
- P(B) = P(红色)= 1/2
当我们将这些数字代入上述贝叶斯定理的方程时,我们得到 1/13,这就是我们所期待的答案。
贝叶斯定理是如何让我们整合先验信念的?
上面我提到了贝叶斯定理允许我们整合先验信念,但是仅仅通过上面的等式很难看出它是如何允许我们这样做的。因此,让我们看看如何使用上面的冰淇淋和天气示例来实现这一点。
让 A 代表我们卖冰淇淋的事件,B 代表天气的事件。然后我们可能会问在给定的天气类型下,在任何一天卖出冰淇淋的可能性有多大?从数学上来说,这可以写成 P(A =冰淇淋销售额| B =天气类型),相当于等式的左侧。
*右手边的 P(A)是被称为**先验的表达式。*在我们的例子中,这是 P(A =冰淇淋销售额),即不管外面的天气如何,销售冰淇淋的(边际)概率。P(A)被称为先验,因为我们可能已经知道冰淇淋销售的边际概率。例如,我可以查看这样的数据:潜在的 100 人中有 30 人实际上在某个地方的某个商店购买了冰淇淋。所以我的 P(A =冰淇淋销售额)= 30/100 = 0.3,在我了解天气之前。这就是贝叶斯定理允许我们整合先验信息的方式。
***注意:*我在上面提到过,我可以从商店中找到数据来获得先验信息,但是没有什么可以阻止我编造一个完全主观的先验,这个先验不是基于任何数据的。有人可能会根据个人经验或特定领域的知识得出一个先验知识,但重要的是要知道最终的计算将会受到这个选择的影响。我会在后面的文章中更详细地讲述先前信念的强度如何影响结果。
贝叶斯推理
定义
现在我们知道什么是贝叶斯定理以及如何使用它,我们可以开始回答问题什么是贝叶斯推理?**
首先,【统计】推断是从数据中推断出关于人口或概率分布的性质的过程。在我之前关于最大可能性的文章中,我们做到了这一点。根据一组观察到的数据点,我们确定了平均值的最大似然估计。
贝叶斯推断因此就是使用贝叶斯定理从数据中推导出关于人口或概率分布的属性的过程。就这样。
对分布使用贝叶斯定理
到目前为止,我上面给出的例子都是用一个数字来表示贝叶斯定理方程中的每一项。这意味着我们得到的答案也是个位数。但是,也可能有单个数字不合适的时候。
在上面的冰淇淋例子中,我们看到卖冰淇淋的先验概率是 0.3。然而,如果 0.3 只是我的最佳猜测,但我对这个值有点不确定。概率也可以是 0.25 或者 0.4。在这种情况下,我们先前信念的分布可能更合适(见下图)。这种分布被称为先验分布。
2 distributions that represent our prior probability of selling ice on any given day. The peak value of both the blue and gold curves occur around the value of 0.3 which, as we said above, is our best guess of our prior probability of selling ice cream. The fact that f(x) is non-zero of other values of x shows that we’re not completely certain that 0.3 is the true value of selling ice cream. The blue curve shows that it’s likely to be anywhere between 0 and 0.5, whereas the gold curve shows that it’s likely to be anywhere between 0 and 1. The fact that the gold curve is more spread out and has a smaller peak than the blue curve means that a prior probability expressed by the gold curve is “less certain” about the true value than the blue curve.
以类似的方式,我们可以用分布来表示贝叶斯定理中的其他项。当我们处理模型时,我们通常需要使用分布。
贝叶斯定理的模型形式
在上面贝叶斯定理的介绍性定义中,我使用了事件 A 和 B,但是当贝叶斯定理的模型形式在文献中陈述时,通常使用不同的符号。我们来介绍一下。
我们通常会看到θ,而不是事件 A,这个符号叫做θ。θ是我们感兴趣的,它代表了一组参数。因此,如果我们试图估计高斯分布的参数值,那么θ代表均值μ和标准差σ(数学上写为θ= {μ,σ})。
而不是事件 B,我们会看到数据或者 y = {y1,y2,…,yn}。这些代表数据,即我们拥有的一组观察值。我将在等式中显式使用数据,希望让等式不那么神秘。
所以现在模型形式的贝叶斯定理被写成:
我们已经看到 P(θ)是先验分布。它代表了我们对参数真实值的信念,就像我们的分布代表了我们对卖冰淇淋概率的信念。
P(θ|数据)*左边称为后验分布。*这是一个分布,代表我们对参数值的信念,在我们计算了右侧的所有数据后,将观察到的数据考虑在内。
P(data |θ)是我们以前遇到过的东西。如果你坚持到我上一篇关于最大可能性的文章的结尾,那么你会记得我们说过 L(数据;μ,σ) 是似然分布(对于高斯分布)。嗯P(data |θ)*正是这个,是似然分布的变相。有时候会写成ℒ*(θ;数据)但这里是一回事。
因此,我们可以使用用我们的可能性更新的先验信念来计算我们参数的后验分布。**
这给了我们足够的信息来通过一个使用贝叶斯推断的参数推断的例子。但是首先…
为什么我完全不顾 P(数据)?
*嗯,除了数据的边际分布之外,它并没有什么特别的名字,尽管它有时被称为证据。记住,我们只对参数值感兴趣,但是 P(data) 对它们没有任何引用。实际上, *P(数据)*甚至都没有评估到一个分布。只是一个数字。我们已经观察了数据,所以我们可以计算 P(数据)。一般来说,计算 *P(数据)是非常困难的并且有很多方法可以计算它。Prasoon Goyal 的这篇博客文章解释了这样做的几种方法。
P(data) 之所以重要,是因为得出的数字是一个归一化常数。概率分布的必要条件之一是一个事件所有可能结果的总和等于 1(例如,在 6 面骰子上掷出 1、2、3、4、5 或 6 的总概率等于 1)。归一化常数通过确保分布的和(我应该说是整数,因为它通常是一个连续分布,但现在这样说太迂腐了)等于 1,来确保最终的后验分布是一个真实的概率分布。
在某些情况下,我们不关心分布的这种性质。我们只关心分布的峰值出现在哪里,而不管分布是否正态化。在这种情况下,许多人把贝叶斯定理的模型形式写成
其中∝表示“成比例”。这清楚地表明,真实的后验分布不等于右侧,因为我们没有考虑归一化常数 P(数据)。
贝叶斯推理例子
干得好,走了这么远。在所有那些理论之后,你可能需要休息一下。但是,让我们继续看一个推理可能会派上用场的例子。我们要用的例子是,计算氢键的长度。你不需要知道氢键是什么。我只是用这个作为例子,因为它是我在读博士期间想出来帮助一个朋友的(我们当时在生物化学系,这就是为什么它当时是相关的)。
I’ve included this image because I think it looks nice, helps to break up the dense text and is kind of related to the example that we’re going to go through. Don’t worry, you don’t need to understand the figure to understand what we’re about to go through on Bayesian inference. In case you’re wondering, I made the figure with Inkscape.
让我们假设氢键在 3.2-4.0 之间(在谷歌上快速搜索给了我这个信息。ngströ是一个距离单位,其中 1 等于 0.1 纳米,所以我们谈论的是非常微小的距离)。这些信息将构成我的先验知识。就概率分布而言,我将把它重新表述为均值μ = 3.6,标准差σ = 0.2 的高斯分布(见下图)。
Our prior probability for the length of a hydrogen bond. This is represented by a Gaussian distribution with mean μ = 3.6Å and standard deviation σ = 0.2Å.
现在,我们看到了一些数据(5 个数据点是从平均值为 3,标准偏差为 0.4 的高斯分布中随机产生的,准确地说)。在现实世界中,这些数据将来自科学实验的结果,该实验给出了测量的氢键长度(图 3 中的金点)。我们可以从数据中推导出一个可能性分布,就像我们在上一篇关于最大可能性的文章中所做的那样。假设数据是从一个可以用高斯分布描述的过程中生成的,我们得到了一个由下图中的黄金曲线表示的似然分布。请注意,5 个数据点平均值的最大似然估计值小于 3(约 2.8)
Prior probability for the distance of a hydrogen bond in blue and the likelihood distribution in gold derived from the 5 gold data points.
现在我们有两个高斯分布,蓝色代表先验,金色代表可能性。我们不关心归一化常数,所以我们有计算非归一化后验分布所需的一切。回想一下,表示高斯分布概率密度的等式是
所以我们要把其中的两个相乘。我不会在这里讨论数学,因为它变得很乱。如果你对数学感兴趣,那么你可以在本文的前 2 页看到它的表现。由此产生的后验分布在下图中显示为粉红色。
The posterior distribution in pink generated by multiplying the blue and gold distributions.
现在我们有了氢键长度的后验分布,我们可以从中得出统计数据。例如,我们可以使用分布的期望值来估计距离。或者我们可以计算方差来量化我们结论的不确定性。根据后验分布计算的最常见的统计数据之一是众数。这通常用作感兴趣参数真实值的估计,称为最大后验概率估计,或简称为图估计。在这种情况下,后验分布也是高斯分布,因此平均值等于众数(和中值),氢键距离的 MAP 估计值位于分布的峰值,约为 3.2。
结束语
为什么我总是用高斯函数?
你会注意到,在我所有涉及分布的例子中,我都使用高斯分布。一个主要原因是它使数学变得容易多了。但是对于贝叶斯推理的例子,它需要计算 2 个分布的乘积。我说这很乱,所以我没有做数学。但即使我自己没有做数学计算,我也知道后验概率是高斯分布。这是因为高斯分布有一个特殊的属性,使得它很容易处理。就高斯似然函数而言,它与自身共轭。这意味着,如果我把一个高斯先验分布乘以一个高斯似然函数,我将得到一个高斯后验函数。后验分布和先验分布都来自同一个分布族(它们都是高斯分布)这一事实意味着它们被称为共轭分布。在这种情况下,先验分布被称为共轭先验。
在许多推理情况下,可能性和先验被选择成使得结果分布是共轭的,因为这使得数学更容易。数据科学中的一个例子是潜在狄利克雷分配(LDA) 这是一种无监督学习算法,用于在几个文本文档(称为语料库)中查找主题。在埃德温·陈的博客中可以找到关于 LDA 的很好的介绍。
在某些情况下,我们不能简单地选择先验或似然性来计算后验分布。有时可能性和/或先验分布看起来很可怕,手工计算后验概率是不容易或不可能的。在这些情况下,我们可以用不同的方法来计算后验分布。最常见的方法之一是使用一种叫做马尔可夫链蒙特卡罗方法的技术。Ben Shaver 写了一篇名为的精彩文章,介绍了马尔可夫链蒙特卡罗方法,以一种非常通俗易懂的方式解释了这种技术。
当我们得到新数据时会发生什么?
贝叶斯推理的一个伟大之处是,你不需要大量的数据来使用它。1 次观察足以更新先验。事实上,贝叶斯框架允许你在数据到来时实时迭代更新你的信念。它是这样工作的:你对某事有一个先验的信念(例如一个参数的值),然后你接收一些数据。你可以像上面那样通过计算后验分布来更新你的信念。之后,我们会收到更多的数据。所以我们的后验变成了新的先验。我们可以用从新数据导出的可能性来更新新的先验,并且我们再次得到新的后验概率。这个循环可以无限期地继续下去,所以你会不断地更新你的信念。
卡尔曼滤波器(及其变种)就是一个很好的例子。它被用于许多场景,但可能是数据科学中最引人注目的是它在无人驾驶汽车上的应用。我在攻读数学蛋白质晶体学博士期间使用了一种叫做无味卡尔曼滤波器的变体,并为实现它们的开源包做出了贡献。为了更好的直观描述卡尔曼滤波器,请看这篇博文:卡尔曼滤波器如何工作,图片由蒂姆·巴布提供。
利用前科作为规则
我们在上述氢键长度示例中生成的数据表明,2.8 是最佳估计值。然而,如果我们仅根据数据进行估计,我们可能会有过度拟合的风险。如果数据收集过程出现问题,这将是一个巨大的问题。我们可以用先验知识在贝叶斯框架中解决这个问题。在我们的例子中,使用以 3.6 为中心的高斯先验得到后验分布,给出氢键长度的 MAP 估计值为 3.2。这表明当估计参数值时,我们的先验可以作为正则化器。
我们对先验概率和可能性的权重取决于两个分布之间的相对不确定性。在下图中,我们可以直观地看到这一点。颜色同上,蓝色代表先验分布,金色代表可能性,粉色代表后验分布。在左图中,您可以看到我们的先验(蓝色)比可能性(金色)分散得少得多。因此,后验概率更像前验概率。右图中的情况正好相反。
因此,如果我们希望增加参数的正则化,我们可以选择缩小与可能性相关的先验分布。
米歇尔·格林写了一篇名为贝叶斯先验和过度拟合的真相的文章,更详细地讨论了这个问题,并给出了如何设定先验的建议。
什么时候 MAP 估计等于最大似然估计?
当先验分布均匀时,MAP 估计等于 MLE。下面是一个均匀分布的例子。
Uniform distribution
我们可以看到的是,均匀分布对 x 轴(是一条水平线)上的每个值赋予相等的权重。直观上,它表示缺乏关于哪些值最有可能的任何先验知识。在这种情况下,所有的权重都分配给了似然函数,因此当我们将先验乘以似然性时,得到的后验与似然性完全相似。因此,最大似然法可以看作是 MAP 的一个特例。
*当我开始写这篇文章时,我真的没有想到它会这么长,所以非常感谢你能走这么远。我真的很感激。一如既往,如果有任何不清楚的地方或者我在上面犯了一些错误,请随时留下评论。在本系列的下一篇文章中,我可能会尝试讨论我在这篇文章中忽略的标准化常数 *P(数据)的边缘化问题。当然,除非有人想让我看别的东西;)
感谢您的阅读。
概率概念讲解:简介
这些年来,我阅读了许多关于概率论不同方面的文本和文章,每一篇似乎都需要不同程度的先决知识来理解正在发生的事情。我绝不是这一领域的专家,但我觉得我可以通过写一系列通俗易懂的文章来解释概率中的各种概念。这是该系列的第一篇,将介绍一些基本的定义。
定义和符号
概率通常与至少一个事件相关联。这个事件可以是任何事情。玩具事件的例子包括掷骰子或者*从袋子里拿出一个彩球。*在这些例子中,事件的结果是随机的(你不能确定当你掷骰子时骰子将显示的值),所以代表这些事件结果的变量被称为随机变量(通常缩写为 RV)。
我们经常对知道随机变量取某一值的概率感兴趣。例如,当我掷出一个 6 面骰子时,它落在 3 上的概率是多少?“公平”这个词在这里很重要,因为它告诉我们骰子落在六个面中任何一个面上的概率;1,2,3,4,5 和 6 相等。直觉上,你可能会告诉我答案是 1/6。正确!但是我们如何用数学方法来写呢?首先,我们需要明白,这里的随机变量是与掷骰子相关的事件的结果。通常,随机变量用大写字母表示,这里,我们用 X 表示。因此,我们想知道 X = 3 的概率是多少。但是由于数学家在记东西的时候很懒,所以问“概率是多少?”就是用字母 p,因此我们可以写“当我掷出一个 6 面骰子,它落在 3 上的概率是多少?”数学上为“P(X=3)”
概率的三种类型
上面介绍了随机变量的概念和概率的一些符号。然而,概率可能变得相当复杂。也许首先要明白的是,概率有不同的类型。可以是边缘、关节或条件。
边际概率: 如果 A 是一个事件,那么边际概率就是那个事件发生的概率,P(A)。举例:假设我们有一副传统扑克牌,边际概率的一个例子是从一副牌中抽出一张红色牌的概率:P(red) = 0.5。
联合概率: 两个或多个事件相交的概率。从视觉上看,它是维恩图上两个事件圆圈的交点(见下图)。如果 A 和 B 是两个事件,那么这两个事件的联合概率记为 P(A ∩ B)。举例:从一副牌中抽出一张牌是红色且数值为 4 的概率为 P(红色和 4) = 2/52 = 1/26。(一副传统扑克牌中有 52 张牌,两张红色的是红心和方块)。稍后我们将更详细地讨论这个例子。
条件概率: 条件概率是在已知其他事件已经发生的情况下,某些事件发生的概率。如果 A 和 B 是两个事件,那么假设 B 已经发生,A 发生的条件概率记为 P(A|B)。例:给定我们抽了一张红卡,一张牌是四的概率是 P(4|red) = 2/26 = 1/13。(一副牌有 52 张,26 张红的,26 张黑的。现在因为我们已经挑选了一张红色的卡片,我们知道只有 26 张卡片可供选择,因此为什么第一个分母是 26)。
Venn diagram showing the ‘space’ of outcomes of 2 events A and B. In the diagram the 2 events overlap. This overlap represents the joint probability, i.e. the probability of both event A and event B happening. If there was no overlap between the events then the joint probability would be zero.
链接概率类型:一般乘法规则
一般乘法法则是一个美丽的等式,它将三种概率联系在一起:
示例的进一步解释
有时,区分联合概率和条件概率可能会非常令人困惑,因此,使用从一副扑克牌中挑选一张牌的示例,让我们尝试将这种差异彻底搞清楚。
在这种情况下,我们想找出选择一张红和 4 的概率,即联合概率 P(红和 4) 我想让你想象所有 52 张牌都面朝下,然后随机选择一张。在这 52 张牌中,2 张为红色,4 张(4 张为方块,4 张为红心)。因此联合概率是 2/52 = 1/26
在这种情况下,我们想找出选择一张 4 的概率,假设我知道这张牌已经是红色的,即条件概率, *P(4|red),*我想让你再次想象拥有所有 52 张牌。然而,在随机挑选一张牌之前,你要对牌进行分类,并选择所有 26 张红色的牌。现在你把这 26 张牌面朝下,随机选一张。同样,其中两张红牌是 4,所以条件概率是 2/26 = 1/13
或者,如果你喜欢数学,我们可以使用上面定义的一般乘法规则来计算联合概率。我们首先重新排列,使联合概率 P(A ∩ B)成为等式的主体(换句话说,让我们把 P(A ∩ B)放在等号的左边,其他的放在右边)。重新排列后我们得到 P(A ∩ B) = P(A|B) ✕ P(B)。设 A 是牌是 a 4 的事件,B 是牌是红色的事件。P(A|B) = 1/13 正如我们上面说的和 P(B) = 1/2(一半的牌是红色的)。因此 P(A ∩ B) = 1/13 ✕ 1/2 = 1/26。
概率规则:“与”和“或”
“与”规则
我们已经看到了伪装成联合概率的“和”场景,但是我们还不知道如何计算“和”场景中的概率。我们来看一个例子。假设我们有两个事件:事件 A——掷一枚公平的硬币,事件 B——掷一枚公平的骰子。我们可能有兴趣知道掷出 6 和硬币正面朝上的概率。因此,为了计算掷出 6 和硬币落地头的联合概率,我们可以重新排列上面的一般乘法规则,得到 P(A ∩ B) = P(A|B) ✕ P(B) **。我们知道事件 A 是掷硬币,B 是掷骰子。所以 P(A|B) term 问"*假设我在骰子上掷出 6,硬币正面朝上的概率是多少?"*这就是我们直观地理解抛硬币的结果并不取决于骰子的滚动。据说这些事件是独立的。在这种情况下,无论我们掷什么骰子,掷硬币的结果都是一样的。数学上我们将此表示为 P(A|B) = P(A)。因此当事件相互独立时,联合概率就是事件的个体边际概率的乘积:P(A ∩ B) = P(A) ✕ P(B)。**所以 p(硬币落地人头和滚动 a 6)= p(a =人头,B=6) = 1/2 ✕ 1/6 = 1/12。
注意,我写的是 P(A =正面,B=6)。事件之间的逗号是联合概率的简写(你会在文献中看到这一点)。
应该注意的是,在许多真实世界的场景中,事件被假定为独立的,即使实际情况并非如此。这主要是因为它使数学变得简单多了。好处是结果通常非常有用。朴素贝叶斯方法可能是数据科学中最常见的例子,通常在文本分类问题中给出相当好的结果。
‘或’规则
根据“和”法则,我们必须将个体概率相乘。当我们处于“或”的情况时,我们必须将个体概率相加,然后减去交集。数学上我们把这个写成 P(A∩B)= P(A)+P(B)-P(A∩B)。你会问我们为什么要这么做?这又回到了上图中的维恩图。如果我们把 A 的圆和 B 的圆相加,那就意味着我们把交点加了两次。因此,我们需要减去交集。
所以让我们改变上面的例子,找出掷出 6 或者硬币正面朝上的概率。这就是 P(硬币落地人头或滚动 A 6)= P(A =人头∩B = 6)= 1/2+1/6-1/12 = 6/12+2/12-1/12 = 7/12
请注意,∩符号被称为“并集”,用于“或”场景。
有些时候我们不需要减去交集。当维恩图中的两个圆不重叠时,就会发生这种情况。当两个事件的圆圈不重叠时,我们说这些事件是互斥的。这暗示交集为零,数学上写成 P(A ∩ B) = 0。让我们做一个涵盖这种情况的例子。假设我们掷骰子,我们想知道掷出 5 或 6 的概率。这些事件是互斥的,因为我不能掷出 5 和 6。因此,它们在维恩图中的圆不重叠。所以掷出 5 或者 6 的概率等于 1/6 + 1/6 = 2/6 = 1/3(我们什么都没减去)。
包裹
谢谢你能走到这一步。如果有的话,我希望我的漫谈对你来说是可以理解的,即使你没有学到任何新的东西。如果有任何不清楚的地方或者我在上面犯了一些错误,请随时留下评论。在本系列的后续文章中,我将介绍一些更高级的概念。下一篇文章将解释最大似然,并通过一个例子来说明。
概率概念解释:边缘化
介绍
在这篇文章中,我将解释边缘化的概念,并通过一个例子来解决一个相当简单的最大似然问题。这篇文章需要一些基本概率概念的知识,你可以在我这个系列的介绍性博客文章中找到解释。
什么是边缘化
边缘化是一种需要对一个变量的可能值求和来确定另一个变量的边际贡献的方法。这个定义听起来有点抽象,所以让我们试着用一个例子来说明这一点
假设我们对天气如何影响英国人的快乐感兴趣。我们可以用数学方法把它写成 P(幸福|天气),即在给定天气类型的情况下,某人幸福水平的概率是多少。
假设我们有测量某人快乐程度的设备和定义,还记录了英格兰和苏格兰的天气情况。现在,苏格兰人总体上比英格兰人更幸福是可行的。问题是,人们总是有一个国籍,所以我不能在测量中摆脱它。所以我们实际测量的是 P(幸福,国家|天气),也就是说,我们同时在看幸福和国家。
边缘化告诉我们,如果我们对所有国家的可能性求和,就可以计算出我们想要的数量(记住,英国由 3 个国家组成:英格兰、苏格兰和威尔士),即 P(幸福|天气)= P(幸福,国家=英格兰|天气)+ P(幸福,国家=苏格兰|天气)+ P(幸福,国家=威尔士|天气)。
就是这样!边缘化告诉我们,只要把一些概率相加,就能得到想要的概率量。一旦我们计算出我们的答案(它可以是单个值或分布),我们就可以得到我们想要的任何属性(推论)。
相关定义
如果这个概念听起来与你相似,但你以前没有听说过边缘化,这可能是因为你听说过它被称为一个不同的名字。有时这种方法被称为**,即剔除有害变量。**积分本质上是一个变量“相加”的另一种说法,你正在求和的变量被称为“有害变量”。因此,在上面的示例中,“*country”*变量是有害变量。
如果您正在使用概率图形模型,那么边缘化是一种您可以执行精确推理的方法(即,您可以从您感兴趣的分布中写下精确的数量,例如,可以从分布中精确计算出平均值)。在这个语境中边缘化是一种方法,有时与 同义使用,变量消去。
例子:骰子未知的骰子游戏。
我将仔细阅读世界上最好的数学和计算晶体学家之一艾利·j·麦考伊写的精彩的喜欢可能性论文中给出的例子。如果你正在寻找关于骰子的各种最大似然概念(如对数似然、中心极限定理等)的很好的介绍。)那么我强烈推荐。
假设我们有四个骰子:4 面骰子,6 面骰子,8 面骰子和 10 面骰子(如下所示)。
The 4 dice that we have. From left to right: 4-sided die, 6-sided die, 10-sided die and an 8-sided die
游戏
- 我把一个六面和一个八面的骰子放在一个红色的盒子里,一个四面和十面的骰子放在一个蓝色的盒子里。
- 我从红色和蓝色的盒子中随机选择一个骰子,并把它们放入黄色的盒子中。
- 我从黄色盒子里随机选择一个骰子,掷骰子,告诉你结果。
玩游戏后,我们被告知结果是 3。我们要回答的问题是:骰子最初最有可能来自红盒子还是蓝盒子?
Graphic depiction of the game described above
接近解决方案
为了解决这个问题,我们必须计算出当我们掷出 3, L (box=red| dice roll=3)时,骰子从红色盒子中取出的可能性,以及当我们掷出 3, L (box=blue| dice roll=3)时,骰子从蓝色盒子中取出的可能性。无论哪个概率最高,都是我们给出的答案。
那么我们如何计算L(box =红色|掷骰子=3)和L(box =蓝色|掷骰子=3)?
首先要知道的是,可能性和概率通过以下等式相关联:
关于这一点的解释,请参见我关于最大似然的帖子的结尾。
这意味着,可能性, L (box=red| dice roll=3),相当于在骰子来自红色盒子的情况下,找出掷出 3 的概率,即 P (dice roll=3 | box=red)。同样L(box =蓝色|掷骰子=3) = P (掷骰子= 3 | box =蓝色)。
让我们假设我们已经从红盒子中选择了一个骰子。它可以是六面或八面模具。我有 50%的机会选择两个死者中的一个。假设我选择六面骰子。也就是说,我必须从黄色盒子中选择六面骰子,然后掷出 3。因此这种情况下的概率由下式给出:
只是为了说明一下。“1/2”来自于我有 50%的机会从红色盒子中随机选择 6 面骰子,因为它也包含 8 面骰子。“1/6”是因为我有一个 6 面骰子,因此有 1/6 的机会掷出 3。
请注意,答案中没有包含任何关于从黄色盒子中挑选 6 面骰子的概率的内容。这是因为在这种情况下,从黄色盒子中挑选六面骰子的概率是 1(您可能认为是 1/2,因为黄色盒子包含 6 面骰子和我从蓝色盒子中挑选的任何骰子)。这是因为我们正在计算从 6 面骰子**掷出 3 的条件概率,假设骰子来自红色盒子。**因此,在另一个场景中,我们在黄色框中选择另一个骰子是不可能的,因为另一个骰子最初来自蓝色框。给定我们从红框中选择的条件,我们只能从黄框中选择 6 面骰子,因此从黄框中选择 6 面骰子的概率是 1。
以类似的方式,我们可以计算结果为 3 的概率,我们实际上已经从红盒子中挑选了 8 面骰子。这一次的概率是
我们现在已经完成了计算骰子来自红盒子的概率所需的几乎所有工作。记住,红盒子只包含 6 面和 8 面骰子,所以我们要做的就是找出骰子是 6 面还是 8 面的概率。从的介绍文章中,我们知道在或的情况下,我们需要将概率相加。因此,骰子来自红盒子的概率是
对于那些不熟悉上式中数字之间的“wavey”等号的人来说,它的意思是“大约等于”。真正的答案是 0.1458333333……(3 永远继续下去,我们说这是 3 的循环),但我变懒了,只给出了小数点后 3 位的答案(即四舍五入到小数点后 3 位)。为了明确我们没有给出准确答案的事实,我们通常使用“wavey”等号。
我们可以对蓝盒子做同样的计算
骰子最初来自蓝盒的概率更高,因此使用最大似然法,我们可以得出骰子最有可能来自蓝盒的结论。
那个例子中的边缘化在哪里?
对于那些观察力非常敏锐的人来说,你会注意到我在那个例子部分一次都没有使用“边缘化”这个词。这是因为我想让你直观地理解如何计算从盒子中挑选骰子的概率。
如果你看上面蓝框的等式,你会看到我们把所有可能性的概率加在一起,即挑选 4 面骰子和 10 面骰子。这是边缘化!我们对讨厌的变量(骰子)求和。注意,在那个游戏中,我们根本没有观察到我们选择的骰子,我们也不需要观察!我们需要知道的只是结果(掷骰子= 3)和骰子的所有可能值。这就是它如此强大的原因。我们可以计算出我们从未观察到的事情的概率。只要我们知道有害变量的可能值,我们总是可以使用它来执行边缘化,并计算不同变量的分布。
注释
这是我让我们写一些更可怕的方程的部分,但是请耐心听我说,我会尽力让它变得容易理解。
让我们想想我们刚刚在示例中做了什么。我们从联合概率开始, P (掷骰子,骰子|盒子)(即掷骰子是 3,骰子是我们选择掷骰子的骰子,盒子是我们选择骰子的原始盒子;蓝色或红色)。一旦我们执行边缘化,我们就以条件概率结束, P (掷骰子|盒子)。这是边缘化的主要好处之一。我们可以从联合概率到条件概率。
事实上我们也可以从联合概率到边际概率。如果你看到边缘化的数学定义,这就是你会看到的典型形式。如果你还没看好数学定义,…你很幸运。你马上就要看到了。
大的 ol’ ∑是懒惰的数学家符号,表示“把所有的东西加起来”,它下面的*【y】告诉我们应该把什么加起来。所以等式是这样说的,“如果你想要 X 的边际概率(等号的左边),那么你需要把 Y 的每个可能结果的 X 和 Y 的联合概率加起来”*。
联合概率有时很难处理,所以我们可以使用概率中的一般乘法规则重写右边的联合概率,我在介绍性博客帖子中展示过。
最右边的等式是条件分布和边际分布的乘积,有时边际分布更容易计算。
正如我之前提到的,∑告诉我们“将一切相加”。我没有提到的是,只有当变量为*“离散”时,才会使用特定符号。*我的意思是,变量只能取有限数量的值。在前面的例子中,我们对离散的讨厌变量求和(例如,英国国家只能是英格兰、威尔士或苏格兰,骰子只有有限的结果数,例如 6 面的从 1 到 6)。但是离散值不一定是有限的。例如,它们可以是所有的正整数(即正整数),如 1、2、3、…。等等。
然而,当我们处理在给定范围内具有无限个可能值的变量时(例如,0 到 10 米之间的距离测量可以具有无限个值,例如 5 米、5.1 米、5.01 米、5.001 米、5.0001 米……等等),我们将这些变量称为“连续变量,并且我们不使用∑符号。相反,我们使用∫。这个符号仍然告诉我们,我们必须把所有的东西加起来,但是我们知道这个讨厌的变量是连续的,所以我们把边际化写成
这与上面离散变量情况下的边际化方程意思相同。结尾的“d y ”告诉我们要积分什么(“积分”是我们在处理连续变量时对“加法”的称呼)。
“d y 是必要的原因是,如果我们不声明它,我们要积分的东西并不总是很明显。考虑干扰变量是围绕圆的角度的情况。我们知道角度在 0 到 360 度之间,或者更专业地说,我们喜欢用弧度来代替我们所说的从 0 到 2π的角度
Source: Wikipedia. Radians in a circle
所以我们可能会想写
我们知道我们需要对从 0 到 2π的值进行积分,但是我们是对 X 的值进行积分还是对 Y 的值进行积分呢?全世界的数学家都渴望为上述暴行打我一巴掌。
为了解决这个问题,我们将“d y 放在最后,以明确我们正在对 0 和 2π之间的 Y 值进行积分,这意味着我们也知道答案是 X 上的边际分布(如下)。
对那些感兴趣的人来说,积分从 0 到 2π的角度是我们在 X 射线晶体学中必须做的事情,这是我博士学位的领域,因为有一个叫做相位问题。这基本上是一个问题,我们不能在实验中测量“相位”,而相位可以像角度一样被数学处理。因此,为了计算我们观察到的数据的理论分布,我们必须忽略这些阶段。
亚当·凯莱赫在他的因果包中使用边缘化来消除混杂变量的影响。他还使用一般乘法法则,把边际化写成我们上面讨论过的条件分布和边际分布的乘积。你可以在他的博客中读到。
结束语
概率的链式法则
在上面的计算中,我们实际上使用了一个相当普通的概率程序,甚至没有意识到这一点。我们使用的结果是概率的链式法则(不要与微分的链式法则混淆)。它指出
它允许我们将联合概率(左侧)写成条件概率和边际概率(右侧)的乘积
这在计算联合分布时经常用到,因为正如我们已经提到的,确定条件概率和边际概率更容易。
要查看我们在哪里使用了上面的结果,请记住我们使用了等式
比较这些等式,我们可以让 A =骰子滚动,B =骰子,C =盒子。这意味着我们可以把上面等式的左边写成
现在让我们来理解这些。
- P (掷骰子= 3|骰子= 6 面,盒子=红色)是我们掷出 3 的概率,假设我们拿起 6 面骰子,它在红色盒子里。这等于 1/6。
- P (骰子= 6 面|盒子=红色)是我们从红色盒子中选择 6 面骰子的概率。这等于 1/2。
因此,我们得到 1/2 ✕ 1/6,这正是我们在这个例子中通过直觉确定的结果。
这里我们用三个变量展示了链式法则。如果你看看维基百科上链式法则的定义(看起来更可怕),你会看到它对于四个变量和无限多个变量的样子。
这看起来很可怕,但想法是一样的。我们在左边有一个联合概率分布,我们想把它写成右边的条件概率和边际概率的乘积。
用于贝叶斯推理
如果你读了我以前关于贝叶斯推理的文章,你会知道贝叶斯定理的模型形式被写成
我提到过,我们经常不计算分母 P(数据),也称为归一化常数,因为在许多情况下它可能太难计算,我们并不总是需要它。
在某些情况下,我们可以精确计算,边缘化会有所帮助。如果我们将边缘化方程写成与上述“符号”部分中连续变量情况相同的形式,我们得到
显而易见,我们通过所有可能的参数值对右侧进行积分。在某些情况下,我们可以精确地或近似地计算这个表达式,这样我们就可以得到一个归一化的后验分布。
再次感谢你能走到这一步。我知道这篇文章包含了很多数学知识,但我希望它有意义。如果有什么不清楚的,你想让我写的或者我可以改进的地方,请不要犹豫让我知道。
谢谢大家!
概率概念解释:最大似然估计
介绍
在这篇文章中,我将解释什么是参数估计的最大似然法,并通过一个简单的例子来演示这种方法。有些内容需要基本概率概念的知识,如联合概率的定义和事件的独立性。我已经写了一篇关于这些先决条件的博文,所以如果你认为你需要复习,请随意阅读。
什么是参数?
通常在机器学习中,我们使用一个模型来描述产生观察到的数据的过程。例如,我们可以使用随机森林模型来分类客户是否会取消服务订阅(称为流失建模),或者我们可以使用线性模型来预测公司将产生的收入,具体取决于他们可能在广告上花费多少(这将是线性回归的一个例子)。每个模型都包含自己的一组参数,这些参数最终定义了模型的外观。
对于线性模型,我们可以写为 y = mx + c 。在本例中, x 可以代表广告支出,而 y 可能是产生的收入。 m 和 c 是该型号的参数。这些参数的不同值将产生不同的线条(见下图)。
Three linear models with different parameter values.
所以参数定义了模型的蓝图。只有为参数选择了特定的值,我们才能得到描述给定现象的模型的实例。
最大似然估计的直观解释
最大似然估计是一种确定模型参数值的方法。发现参数值使得它们最大化由模型描述的过程产生实际观察到的数据的可能性。
上面的定义听起来可能仍然有点晦涩,所以让我们通过一个例子来帮助理解这一点。
假设我们从某个过程中观察到了 10 个数据点。例如,每个数据点可以代表学生回答一个特定的考试问题所需的时间长度(以秒为单位)。下图显示了这 10 个数据点
The 10 (hypothetical) data points that we have observed
我们首先必须决定我们认为最能描述数据生成过程的模型。这部分很重要。至少,我们应该对使用哪种模型有一个好的想法。这通常来自于一些领域的专业知识,但我们不会在这里讨论。
对于这些数据,我们假设数据生成过程可以用高斯(正态)分布来充分描述。对上图的直观观察表明,高斯分布似乎是合理的,因为这 10 个点中的大部分都集中在中间,只有少数点分散在左右两边。(在只有 10 个数据点的情况下匆忙做出这种决定是不明智的,但考虑到这些数据点是我生成的,我们会照做的)。
回想一下,高斯分布有两个参数。平均值μ和标准差σ。这些参数的不同值会产生不同的曲线(就像上面的直线一样)。我们想知道哪条曲线最有可能产生我们观察到的数据点?(见下图)。最大似然估计是一种方法,可以找到μ和σ的值,从而得到最符合数据的曲线。
The 10 data points and possible Gaussian distributions from which the data were drawn. f1 is normally distributed with mean 10 and variance 2.25 (variance is equal to the square of the standard deviation), this is also denoted f1 ∼ N (10, 2.25). f2 ∼ N (10, 9), f3 ∼ N (10, 0.25) and f4 ∼ N (8, 2.25). The goal of maximum likelihood is to find the parameter values that give the distribution that maximise the probability of observing the data.
生成数据的真实分布是 f1 ~ N(10,2.25),即上图中的蓝色曲线。
计算最大似然估计
现在我们对什么是最大似然估计有了直观的理解,我们可以继续学习如何计算参数值。我们找到的值称为最大似然估计(MLE)。
我们将再次用一个例子来证明这一点。假设我们这次有三个数据点,并且我们假设它们是从一个由高斯分布充分描述的过程中产生的。这几点是 9,9.5,11。我们如何计算高斯分布μ和σ的参数值的最大似然估计?
我们要计算的是观察所有数据的总概率,即所有观察数据点的联合概率分布。要做到这一点,我们需要计算一些条件概率,这可能会变得非常困难。所以在这里我们要做第一个假设。假设每个数据点独立于其他数据点生成。这个假设使数学变得容易多了。如果事件(即生成数据的过程)是独立的,那么观察所有数据的总概率是单独观察每个数据点的乘积(即边际概率的乘积)。
观察由高斯分布产生的单个数据点 *x,*的概率密度由下式给出:
符号P(x;μ,σ) 是为了强调它后面出现的符号是概率分布的参数。因此,它不应该与条件概率(通常用垂直线表示,例如 P(A| B))混淆。
在我们的例子中,观察三个数据点的总(联合)概率密度由下式给出:
我们只需计算出导致给出上述表达式最大值的 μ 和 σ 的值。
如果你在数学课上学过微积分,那么你可能会意识到有一种技术可以帮助我们找到函数的最大值(和最小值)。这叫做*分化。*我们要做的就是找到函数的导数,将导函数设置为零,然后重新排列方程,使感兴趣的参数成为方程的主题。瞧,我们就有了参数的最大似然值。我现在将介绍这些步骤,但我将假设读者知道如何对常见函数进行微分。如果你想要更详细的解释,请在评论中告诉我。
对数可能性
上面的总概率表达式实际上很难区分,所以几乎总是通过取表达式的自然对数来简化。这绝对没问题,因为自然对数是一个单调递增的函数。这意味着,如果 x 轴上的值增加,y 轴上的值也会增加(见下图)。这很重要,因为它确保了概率对数的最大值出现在与原始概率函数相同的点上。因此,我们可以用更简单的对数似然代替原始似然。
Monotonic behaviour of the original function, y = x on the left and the (natural) logarithm function y = ln(x). These functions are both monotonic because as you go from left to right on the x-axis the y value always increases.
Example of a non-monotonic function because as you go from left to right on the graph the value of f(x) goes up, then goes down and then goes back up again.
对原始表达式进行记录可以得到:
这个表达式可以用对数定律再次简化,得到:
这个表达式可以求导以找到最大值。在这个例子中,我们将找到均值μ的极大似然估计。为此,我们取函数对μ的偏导数,给出
最后,将等式左侧设置为零,然后重新排列μ,得出:
这就是μ的最大似然估计。我们也可以用σ做同样的事情,但我将把它留给有兴趣的读者做练习。
结束语
最大似然估计总能以精确的方式求解吗?
不是简短的回答。更有可能的是,在现实世界中,对数似然函数的导数在分析上仍然是难以处理的(即,手动区分函数太难/不可能)。因此,像期望最大化算法这样的迭代方法被用于寻找参数估计的数值解。尽管如此,总体想法还是一样的。
那么为什么是最大似然而不是最大概率呢?
这只是统计学家的迂腐(但有充分的理由)。大多数人倾向于交替使用概率和可能性,但统计学家和概率理论家区分两者。通过查看等式,可以更好地找出混淆的原因。
这些表达式是相等的!那么这意味着什么呢?我们先定义一下 P(数据;μ,σ) ?表示*“用模型参数μ和σ观察数据的概率密度”*。值得注意的是,我们可以将其推广到任何数量的参数和任何分布。
另一方面 L(μ,σ;data) 表示*“给定我们观察到的一堆数据,参数μ和σ取某些值的可能性。”*
上面的等式表明,给定参数的数据的概率密度等于给定数据的参数的似然性。但是,尽管这两个东西是相等的,但可能性和概率密度从根本上提出了不同的问题——一个是关于数据的问题,另一个是关于参数值的问题。这就是为什么这种方法被称为最大似然而不是最大概率。
最小二乘最小化何时与最大似然估计相同?
最小平方最小化是机器学习中估计模型参数值的另一种常用方法。事实证明,当模型被假设为高斯型时,MLE 估计相当于最小二乘法。如需更深入的数学推导,请查看这些幻灯片。
通过理解它们的目标,我们可以直观地解释这两种方法之间的联系。对于最小二乘参数估计,我们希望找到使数据点和回归线之间的总平方距离最小的线(见下图)。在最大似然估计中,我们希望最大化数据的总概率。当假设高斯分布时,当数据点越接近平均值时,就找到了最大概率。由于高斯分布是对称的,这相当于最小化数据点和平均值之间的距离。
Regression line showing data points with random Gaussian noise
如果有任何不清楚的地方或者我在上面犯了一些错误,请随时留下评论。在下一篇文章中,我计划介绍贝叶斯推理以及它如何用于参数估计。
感谢您的阅读。
概率概念讲解:概率分布(导论第 3 部分)
在我的第一篇和第二篇介绍性文章中,我介绍了符号、基本概率定律和公理。这些都是让数学家兴奋的事情。然而,当我们使用概率分布时,概率论在实践中经常是有用的。
概率分布被用于许多领域,但我们很少解释它们是什么。通常假设读者已经知道了(我假设的比我应该假设的更多)。所以我将在这篇文章中解释它们是什么。
什么是概率分布?
回想一下,随机变量的值是随机事件的结果(如果这对你没有任何意义,请参阅第一篇介绍文章)。例如,随机变量可能是掷骰子或掷硬币的结果。
一个 概率分布 是一个随机变量的所有可能结果及其对应概率值的列表。
举一个具体的例子,这里是一个公平的 6 面骰子的概率分布。
The probability distribution for a fair six-sided die
明确地说,这是一个有限支持的离散单变量概率分布的例子。这有点拗口,所以让我们试着把这句话分解并理解它。
这意味着如果我选择任何两个连续的结果。我找不到介于两者之间的结果。例如,如果我们认为 1 和 2 是掷出六面骰子的结果,那么我不能有介于两者之间的结果(例如,我可以有 1.5 的结果)。在数学中,我们会说结果列表是可数的(但我们不要沿着定义和理解可数和不可数集合的道路走下去。变得很奇怪)。你大概能猜到当我们得到连续概率分布时,情况就不再是这样了。
单变量= 表示我们只有一个(随机)变量。在这种情况下,我们只有掷骰子的结果。相反,如果我们有不止一个变量,那么我们说我们有一个多元分布。在我们有两个变量的特定情况下,我们经常说这是一个二元分布。
这意味着结果的数量是有限的。支持本质上是定义了概率分布的结果。所以我们例子中的支撑是。一、二、三、四、五、六。由于这不是无限数量的值,这意味着支持是有限的。
函数介绍
为什么我们要讨论函数?
在上面滚动六面骰子的例子中,只有六种可能的结果,所以我们可以在表格中写下整个概率分布。在许多情况下,结果的数量可能要大得多,因此写一个表格会很乏味。更糟糕的是,可能的结果的数量可能是无限的,在这种情况下,祝你好运写一张表。
为了解决为每个分布写一个表的问题,我们可以定义一个函数来代替。该函数允许我们简洁地定义概率分布。
因此,让我们首先定义一个函数,然后我们将移动到用于概率分布的函数。
什么是函数?
在非常抽象的层面上,函数是一个接受输入并返回输出的盒子。在绝大多数情况下,函数实际上必须对输入做一些事情,以使输出有用。
让我们定义我们自己的函数。假设这个函数接受一个数字作为输入,在输入的数字上加 2,然后返回新的数字作为输出。我们的函数(作为一个盒子)看起来像这样:
The abstract depiction of a function as a box that takes input and returns an output. In this case, the function adds 2 to the input.
因此,如果我们的输入是 5,我们的函数会将它加上 2,并返回输出 5+2 = 7。
函数符号
现在,为我们想要创建的每个函数绘制上面的图表是很乏味的。相反,我们使用符号/字母来表示图表,使其更加简洁。我们不用“输入”这个词,而是用“x”;我们不用“函数”这个词,而是用“f”;我们不用“输出”这个词,而是用“f(x)”。所以上图现在可以写成
Our function is written with symbols instead of words to make this more concise
这更好,但是,我们仍然有一个问题,我们必须画一个图来理解这个函数在做什么。但是我们是数学家,我们不想因为画一个盒子而浪费宝贵的能量,所以我们想出了一个更好的写函数的方法,这意味着我们不需要画任何东西。我们可以从数学上定义我们的函数为
Our function is now written without having to draw arrows and boxes.
这相当于上图,因为我们可以清楚地看到函数 f 的输入是 x,我们已经调用了函数 f,我们知道该函数将 2 加到输入中,并返回 x + 2 作为输出。
值得注意的是,函数和输入的字母选择是任意的。我可以说“a”是输入,我可以调用函数“add_two ”,所以我的函数是
Another way of writing the same function
而这个完全等同于上面的功能。
其中一个主要的收获是,通过一个函数,我们可以看到如何转换任何输入。对于函数 f(x) = x+ 2,我们知道如果输入是 x=10 或者输入是 x=10000 该怎么办。所以我们不需要像之前那样写下一个表格。
我想在这里说明的最后一点是,我们将要使用的函数只能将数字作为输入和输出。但是,函数可以把你喜欢的任何东西作为输入,输出你喜欢的任何东西(甚至不输出任何东西)。例如,我们可以用编程语言编写一个函数,将一个文本字符串作为输入,输出该字符串的第一个字母。以下是 Python 编程语言中此函数的一个示例
用图形表示函数
假设函数的主要好处之一是让我们知道如何转换任何输入,我们也可以使用这些知识来显式地可视化函数。让我们坚持我们的例子 f(x) = x+2。图形看起来是这样的:
Graphical representation of our function f(x) = x + 2
我们可以沿着底部的水平轴读取,因为我们的输入数字和左侧垂直轴上的相应数字是输出值 f(x) = x+2。例如,我们可以看到,代表函数的蓝线与垂直(白色)线在 x=1 处与水平(白色)线 f(x) = 3 相交的点相交。这从图形上说明了 f(1) = 1 + 2 = 3。
函数的参数
函数最重要的特征之一是参数。参数是你在函数中找到的数字,你不需要把它作为输入。在我们的例子中,f(x) = x + 2,数字“2”是一个参数,因为我们需要它来定义函数,但我们没有把它作为函数的输入。
参数之所以重要,是因为它们在决定输出时起着直接的作用。比如我们定义另一个函数 h(x) = x+3。函数 f(x) = x+2 和我们的新函数 h(x) = x+3 之间的唯一区别是参数的值(我们现在有了“3”而不是“2”)。这种差异意味着对于相同的输入,我们得到的输出是完全不同的。让我们用图表来看一下。
The difference between our functions f(x) = x + 2 and h(x) = x + 3
参数可以说是概率(分布)函数最重要的特征,因为它们定义了函数的输出,告诉我们随机过程中某些结果的可能性。在数据科学中出现的问题中,我们经常试图估计参数,我以前写过两种方法可以用来估计它们:最大似然估计和贝叶斯推断。
现在我们准备用函数的语言来讨论概率分布。
概率质量函数:离散概率分布
当我们使用概率函数来描述离散概率分布时,我们称之为概率质量函数(通常缩写为 pmf)。
记得在关于概率概念的第一篇介绍文章中,我们用大写字母 X 表示的随机变量的概率,取一个小写字母 X 表示的值,记为 P(X=x)。因此,如果我们使用掷骰子作为随机变量,我们可以将骰子落在数字 3 上的概率写成 P(X=3) = 1/6。
概率质量函数,我们称之为 f,返回一个结果的概率。因此,概率质量函数写为:
我知道这变得有点可怕和数学化,但是请原谅我。我们上面看到的等式说,概率质量函数“f”只是返回结果 x 的概率。
所以让我们回到公平的 6 面骰子的例子(你可能已经厌倦了这个例子)。概率质量函数 f 只返回结果的概率。因此掷出 3 的概率是 f(3) = 1/6。就是这样。
因为概率质量函数返回概率,所以它必须遵守我在之前的文章中描述的概率规则(公理)。也就是说,概率质量函数输出 0 和 1 之间的值,并且所有结果的概率质量函数(pmf)之和等于 1。数学上我们可以把这两个条件写成
我们已经看到,我们可以把离散概率分布写成表格和函数。我们也可以用图形来表示骰子滚动的例子
Graphical representation of the probability distribution for outcomes of rolling a fair six-sided die
离散概率分布示例:伯努利分布
一些概率分布出现得如此频繁,以至于它们被广泛研究并被命名。一种经常出现的离散分布叫做伯努利分布。它描述了有两种可能结果的过程的概率分布。这方面的一个例子是掷硬币,结果是正面或反面。
伯努利分布的概率质量函数为
这里,x 表示结果,取值为 1 或 0。所以我们可以说正面= 1,反面= 0。p 是表示结果为 1 的概率的参数。因此,在一个公平的硬币的情况下,正面或反面落地的概率是 0.5,我们将设置 p = 0.5。
通常我们想明确概率密度函数中包含的参数,所以我们写
请注意,我们使用分号来分隔输入变量和参数。
概率密度函数:连续概率分布
有时我们关心有连续结果的随机变量的概率。例子包括从人群中随机选取的成年人的身高,或者出租车司机在下一份工作之前必须等待的时间。对于这些例子,随机变量最好用连续概率分布来描述。
当我们用一个概率函数来描述一个连续的概率分布时,我们称之为概率密度函数(通常缩写为 pdf)。
概率密度函数在概念上比概率质量函数稍微复杂一些,但是不要担心,我们会实现的。我认为最简单的方法是从一个连续概率分布的例子开始,然后讨论它的性质。
连续概率分布示例:正态分布
正态分布可能是所有概率和统计中最常见的分布。它出现如此频繁的一个主要原因是由于中心极限定理。我们不会在这篇文章中深入探讨,但这里有一篇由卡森·福特撰写的名为“科学家需要知道的唯一定理数据”的好文章,它解释了什么是定理以及它与正态分布的关系。
正态分布的概率密度函数定义为
其中,参数(即分号后的符号)代表总体的均值μ(分布的中心点)和标准差σ(分布的分布程度)。
如果我们将平均值设为 0(μ= 0),标准差设为 1 (σ=1),那么我们得到的分布如下所示
Normal distribution with mean = 0 and standard deviation equal to 1
正态分布是一个具有无限支持度的连续单变量概率分布的例子。所谓无限支持,我的意思是我们可以计算负无穷大和正无穷大之间所有结果的概率密度函数值。在数学中,我们有时会说它被支撑在整实线上。
连续概率分布的性质
首先要注意的是,纵轴上的数字从零开始向上。这是一个概率密度函数必须遵守的规则。概率密度函数的任何输出值都大于或等于零。用数学术语来说,我们会说输出是非负的,或者用数学方法写成
然而,与概率质量函数不同,概率密度函数的输出是而不是概率值。这是一个非常重要的区别,其中一个我很抱歉忘记了。
为了从概率密度函数中得到概率,我们需要找到曲线下的面积。因此,从均值= 3、标准差= 1 的分布示例中,我们可以通过找到下图中所示的面积来确定结果介于 0 和 1 之间的概率
The area shaded is the probability of the outcome being between 0 and 1.
数学上我们可以这样写
我们可以把这个理解为“(左手边)0 和 1 之间的概率密度函数的积分等于随机变量的结果在 0 和 1 之间的概率(右手边)”。
请原谅我没有明确地介绍积分以及它们是如何工作的(在我的关于边缘化的帖子中,我对积分有一个简短的概念性介绍,但它没有教你如何计算它们)。如果你不知道它们,那么你现在需要知道的是,这是一种求曲线下面积的数学方法,在这种情况下,它给出了结果的概率。也许我需要写一个简短的系列来介绍微积分。
我们现在已经看到了概率密度函数的另一个性质。也就是说,两个结果之间的概率,比如‘a’和‘b’,是这两个点之间的概率密度函数的积分(这相当于找到由‘a’和‘b’点之间的概率密度函数产生的曲线下的面积)。数学上这是
请记住,我们仍然必须遵循概率分布规则,即所有可能结果的总和等于 1 的规则。如果我们把范围从“负无穷大”一直设置到“正无穷大”,我们就可以涵盖所有可能的值。因此,要使函数成为概率密度函数,以下条件必须成立
这表示负无穷大和正无穷大之间曲线下的面积等于 1。
关于连续概率分布,需要知道的一件重要事情(从概念上来说,这可能很难理解)是,随机变量等于特定结果的概率是 0。例如,如果我们试图得到结果等于数字 2 的概率
这可能在概念上看起来很奇怪,但是如果你理解微积分,那么它应该会更有意义。我不打算在这篇文章中讨论微积分。相反,我想让你们从这个事实中得到的是,我们只能谈论发生在两个值之间的概率。或者我们可以问一个结果大于或小于特定值的概率。我们不能询问一个结果等于特定值的概率。
眼尖的读者可能已经注意到,我使用了“小于()”符号,而不是“小于或等于(≤)”和“大于或等于(≥)”符号。对于连续的概率分布,这实际上并不重要,因为它们是相同的。我的意思是
所以随机变量在 a 和 b 之间取值的概率等于它在 a 和 b 之间取值的概率。
参数的重要性
我们看到参数值可以改变函数的输出值,概率分布也一样。
Two normal distributions with different parameters give completely different probability outcomes.
在上图中,我们绘制了两个正态分布的概率密度函数。蓝色分布的参数值μ=0,σ=1,而红色分布的参数值μ=2,σ=0.5。
现在可以更清楚地看到为什么使用错误的参数值会产生与您预期的结果相差很大的结果。
摘要
哇!那比我预期的要长得多。让我们总结一下要点:
- 概率分布是结果及其相关概率的列表。
- 我们可以用表格写小分布,但是用函数概括大分布更容易。
- 代表离散概率分布的函数称为概率质量函数。
- 代表连续概率分布的函数称为概率密度函数。
- 代表概率分布的函数仍然必须遵守概率规则
- 概率质量函数的输出是概率,而由概率密度函数产生的曲线下的面积代表概率。
- 概率函数的参数在定义随机变量结果的概率中起着核心作用。
我最初想在这篇文章中讨论多元分布,但它太长了,所以我们将在以后的文章中讨论它。
现在你已经对概率分布有了基本的了解,看看肖恩·欧文的这篇伟大的文章,它涵盖了数据科学中常用的概率分布。他出色地解释了为什么数据科学中会出现每种分布,所以这是对概率分布更实际的观察。更详细的概率分布列表,请查看维基百科页面(列表很长)。
一如既往,感谢你读到这里。我希望这是有用的,你从中学到了一些东西。请随时留下您的意见、建议和问题。
概率概念讲解:概率规则(导论第二部分)
当我写本系列的第篇介绍性文章时,我介绍了一些基本的概率概念(边际概率、条件概率和联合概率、独立性和互斥性,以及组合概率的“与”和“或”规则)。然而,我错过了一些其他的基本规则,我认为这些规则是理所当然的,并假设读者在我写后续文章时已经知道了。
因此,在这篇文章中,我将介绍概率论中的一些核心规则。如果你是这方面的新手,那么我推荐你在这里浏览一下的第一篇介绍性文章,这样你就可以熟悉符号和一些定义。
概率规则(公理)
当数学家探索新的数学领域时,他们通常从一套定义他们能做什么的规则开始。这有点像是第一个发明足球(soccer)的游戏,并制定规则说’只有 11 名球员在球场上为球队效力,你不能用手触球,越位规则等’。一旦制定了这些规则,球员和经理们就可以自由地探索和创造新的球技和花式团队。
概率论(以及一般的数学)没有什么不同。我们把这些规则叫做 公理 。一旦规则被设定,数学家们就会疯狂地探索新的定理和结果。只要坚持公理,那么你就可以做你想做的事情
让我们过一遍概率公理。
公理 1
第一条规则规定事件发生的概率大于或等于零。其实我们可以更进一步说,事件发生的概率在 0 到 1(含)之间。
让我们用数学方法来写。如果我们说一个事件的概率在 0 和 1 之间(包括 0 和 1 ),那么我们可以这样写
当我说“事件”时,我的意思是“发生了一些事情”。例如,我们可能在谈论明天的天气,而结果可能是明天下雨。所以明天下雨的概率可能是 0.5。数学上,我们把它写成
有可能把结果归入一个事件,说一个事件是明天下雨或下雪的结果。这样,一个 事件实际上就是一个结果的集合。
公理 2
这条规则规定**至少一个可能结果发生的概率是 1。**我冒昧地进一步说,如果你把所有可能结果的概率加起来,你会得到概率 1。核心数学家会纠缠我,因为围绕这个有一些警告,但对于我们将遇到的大多数情况,第二个声明将成立。
让我们以滚动一个公平的 6 面骰子为例。如果我掷骰子,那么六个结果中有一个是可能的。骰子会落在 1,2,3,4,5 或 6 上。因此我至少得到其中一个结果的概率是 1。概率等于 1 意味着我们确定。
我的第二个观点仍然成立。有六分之一的可能性,掷出其中任何一个的概率是 1/6。所以如果我们把得到 1,2,3,4,5 或 6 的概率加起来,我们得到 1。见下文
P(骰子= 1) + P(骰子= 2) + P(骰子= 3) + P(骰子= 4) + P(骰子= 5) + P(骰子= 6)= 1/6+1/6+1/6+1/6+1/6+1/6+1/6 = 6/6 = 1。
写出总和中的所有项是非常乏味的,特别是当你有数百个结果时,所以为了简化它,数学家会写
是的,那个看起来像“E”的大符号只是告诉我们把东西加起来,它上面和下面的东西告诉我们从哪里开始和结束。所以这里说“从 i=1 开始,一直到 I = 6”。
因此,我们现在可以将语句*“所有可能结果的个体概率相加将等于 1”*数学上为:
我们用一个特殊的术语来代替“所有可能的结果”——它被称为样本空间。因此,6 面骰子的结果 1、2、3、4、5 和 6 实际上是样本空间。数学上,样本空间用ω表示。所以我们也可以用数学方法把上面写为
公理 3
这条公理可能是最难理解的,但是我在介绍互斥性的文章中提到了它。我先陈述公理,然后举例说明。
公理说如果两个事件是互斥的(即两个事件不能同时发生),那么其中一个事件发生的概率等于它们发生的个体(边际)概率之和。我告诉过你这很令人困惑。让我们用第一篇介绍性文章中的例子来澄清这一点。
假设我们掷出一个 6 面骰子,我们想知道掷出 5 或 6 的概率。这些事件是 互斥 因为我不能同时掷出一个 5 和一个 6。所以掷出 5 或 6 的概率等于掷出 5 的概率加上掷出 6 的概率:1/6 + 1/6 = 2/6 = 1/3。
数学上我们可以把这个公理写成
假设结果 1 和结果 2 是互斥的(它们不可能同时发生)。
我知道这篇文章很可能比我以前的文章更枯燥,考虑到我在这个系列中的其他文章也都是关于数学的,我认为覆盖一些理解更高级的东西经常需要但却被错误假设的基础知识是很重要的。
下一篇文章也将是介绍性的,我的目的是解释什么是概率分布,以及你可以得到的不同类型(离散、连续、单变量和多变量)。
感谢阅读
使用 Python 和 Numpy 的加权抛硬币游戏中的概率
本周一个简短有趣的问题:
两个玩家正在玩一个游戏,从玩家 1 开始,他们掷一枚不一定是公平的硬币。第一个抛头的人获胜。一枚硬币正面朝上的概率是 p 。参与人 1 赢得比赛的概率是多少?
Photo by Andriyko Podilnyk on Unsplash
我们可以用 python 中的一个简单函数来探讨这个问题。让我们编写一个接受两个参数的函数:1。)要玩的游戏的数量,以及 2。)抛硬币导致正面的概率(设置为默认值 0.5 或 50%)。
我们姑且称这个函数为“P1 _ 赢 _ 概率 _ 加权 _ 硬币 _ 游戏”
我们可以用下面的代码模拟这个游戏:
import numpy as npdef P1_win_prob_weighted_coin_game(num_games, prob_heads=.5):
player_one_wins = 0
for n in range(0,num_games):
num_flips = 0
win = 0
while win == 0:
turn = np.random.uniform(0,1)
num_flips += 1
if turn <= prob_heads:
if num_flips % 2 != 0:
player_one_wins += 1
win += 1
return float(player_one_wins)/float(num_games)
现在,让我们一步一步地简单介绍一下。
import numpy as npdef P1_win_prob_weighted_coin_game(num_games, prob_heads = 0.5):
player_one_wins = 0
我们从导入 numpy 开始,因为我们可以利用它的随机选择功能来模拟这个游戏的抛硬币机制。
我们定义函数的名称,并指定两个参数。我们将默认正面概率设置为 0.5,以防我们只是想使用公平硬币指定一些游戏来查看结果。显然,我们可以在这里随意输入自定义概率。
我们还为玩家 1 赢得的游戏数量设置了一个全局计数器,每轮模拟从 0 开始。
for n in range(0,num_games):
num_flips = 0
win = 0
while win == 0:
turn = np.random.uniform(0,1)
num_flips += 1
现在,对于指定模拟次数(例如,range(0,num_games ))的每场游戏,我们将从零开始计算掷硬币的次数。这既能记录游戏进行了多长时间,也能帮助我们在一次正面朝上的情况下确定谁是赢家。
我们还指定了一个获胜条件“win ”,它将帮助我们知道游戏何时完成。当 win 仍然等于零时,玩家继续掷硬币。每“转”一次构成硬币的一次翻转,它是在 0 和 1 之间随机选择的十进制值。每走一个回合,我们的 num_flips 计数器就加一。
if turn <= prob_heads:
if num_flips % 2 != 0:
player_one_wins += 1
win += 1
如果随机选择的“回合”值小于或等于我们设置的“prob_heads”值,我们认为这是一个获胜条件。
我们可以这样理解:如果翻转头部的概率是 0.6,那么 0 和 1 之间的 60%的值可以被解释为头部翻转(例如,0.0 和 0.6 之间的所有值)。
一旦满足获胜条件,我们就检查硬币被抛了多少次。因为参与人 1 总是第一个掷硬币,我们知道奇数次掷硬币意味着参与人 1 是最后一个走的,因此是赢家。如果玩家 1 赢了游戏,我们在函数的顶部给我们的玩家 1 赢计数器加 1。我们还将“win”的值更改为 1.0,这将中断当前游戏,并在预设的模拟次数内开始下一个游戏。
return float(player_one_wins)/float(num_games)
一旦所有模拟运行完毕,该函数将返回玩家 1 赢得的游戏数除以所玩游戏的总数。这将表示为十进制的获胜百分比。
好吧!现在我们已经写好了函数,让我们用一枚硬币玩 50,000 次游戏,看看会有什么结果:
P1_win_prob_weighted_coin_game(50000)0.66848
在超过 50,000 场比赛中,我们看到一号玩家有明显的优势。事实上,玩家 1 有大约 2/3 的机会因为先抛硬币而赢得游戏,即使使用公平硬币。
如果我们调整硬币正面朝上的概率呢?如果硬币有 75%的机会正面朝上呢?
P1_win_prob_weighted_coin_game(50000, .75)0.80066
在 75%的抛硬币中,一个有重量的硬币朝上,玩家 1 有 80%的机会获胜。
如果我们真的降低头部出现的可能性呢?比方说,如果正面只出现 1%的几率呢?
P1_win_prob_weighted_coin_game(50000, .01)0.50498
只有当我们大幅度降低正面朝上的可能性时,两个玩家才有大致相同的获胜机会。
有趣的东西!你可以随意摆弄这个函数,看看不同的模拟次数和正面概率如何影响玩家 1 获胜的可能性。
感谢阅读!
概率第一部分:每个人的概率。
受我正在上的一门概率论课程的启发,这篇博客试图在直观的层面上解释概率数学理论的基础。顾名思义,这篇文章是为每个人准备的,不管他的数学水平和能力如何。将会有一些数学,但是请随意跳过这些部分。重要的东西出现在数学之间。
如果你正在读这篇文章,那么在某个时候你已经遇到了机遇。机遇与自然交织在一起,就像行星围绕太阳旋转,或者我们的遗传密码解开并从一代转化到下一代。但与宇宙运动定律不同,机会是不确定的。每次你玩掷骰子的游戏,或者出门前忘记查看天气,或者点击音乐流媒体服务上的下一步,你都是在赌运气。这一切都无法确定宇宙将会扮演什么角色。
正如我们所知,机遇是指某件事情发生的可能性——比如你掷骰子,或者你回家的路上阳光灿烂。概率是对某件事情发生的可能性的度量,即你掷出 6 的概率是 1/6(当然假设骰子是你所期望的)。
在日常生活中,概率是我们试图预测自然,让我们面对它,人类储存了什么的最佳猜测。例如,你可能想知道今天你会有三个看起来很棒的甜甜圈,裹着糖屑(就像上面的一样)。
概率论是我们测量宇宙中不确定性的尝试。
这是一个宇宙如何发挥作用的完美例子。当我今天早上开始写这篇文章时,阳光灿烂。一整天都是这样,除了在回家的路上,你瞧,一片失控的乌云散开了。出乎意料!
对机会和概率的数学研究可以追溯到 16 世纪的意大利和法国。在此期间,文艺复兴时期的数学家杰拉尔莫·卡尔达诺、皮耶·德·费玛和布莱士·帕斯卡主要关心的是计算他们在掷骰子游戏中获胜的几率。然而,正如我们所知,现代概率理论是在 20 世纪随着测度理论的发展而进步的。
测度论的目标是构建一种比较数学中集合的相对大小的系统方法。由于一个事件发生的概率恰好是该事件发生的可能性的度量,测度论成为研究概率的自然框架。
测量理论的问题(对我们来说)是它很快变得非常抽象。尽管如此,我还是会试着介绍研究概率的数学框架,而不会深入测度论。让我们看看能走多远。
激励人心的例子
考虑一个掷两个公平骰子的游戏。我们想测量任何一次掷骰子累积到一个给定数字的可能性。例如,如果我们掷出 3 和 6,我们得到 9。数学上,我们可以用函数 X 来表示,取对(3,6)到 9:
X(3,6) → 9
我们想要考虑所有这些掷骰子的可能组合的集合。我们称这个集合为ω(大写ω,我们可以简洁地列举如下
ω= {(I,j): 1 ≤ i,j ≤ 6}
对(3,6)则是ω的成员,我们写为:(3,6)∈ω*。*
然而,如果我们考虑给定掷骰子的总数为 9 的事件,那么存在不止一个可能的组合,即配对:
A = {(3,6),(4,5),(5,4),(6,3) }
对上述集合中的任何一对进行 X(采样)评估,我们将得到 9。注意集合 A 不是ω的一个元素(成员),但它显然包含了ω的元素!所以我们需要一些基于ω的东西,只是更宽泛。
这激发了事件* 、ℱ的族的概念,它包含来自ω的元素的所有可能的组合,包括ω本身的整体,以及表示为∅.的空集本质上,ℱ是一组集合,因此为了一致性,单个卷采用{(3,6)}。
集合 a 则是 ℱ 的一个元素,即 A ∈ ℱ。
现在我们有了一组事件,我们可以继续我们的目标,测量这些事件的可能性。我们做这件事的数学上精确的方式是相当复杂的,但是凭直觉(甚至可能是现实的),我们可以把一个事件的概率看作是该事件相对于某件事情发生的总体可能性的可能性。为此,如果 F ∈ ℱ是任何事件,那么计算其概率的一种方法是:
ℙ(F) = 尺寸 (F)/ 尺寸(ω)
当然,模糊之处在于 F 或ω的大小的确切含义,但这是另一天的辩论!在我们的简单示例中,这相当容易:
在一个骰子的情况下,一次掷骰有 6 个结果,姑且称之为θ= { 1,2,3,4,5,6}。掷出 1 只有一种方法,所以
ℙ(1) = 尺寸 ({1})/ 尺寸(θ)= 1/6
在ω_ 1 上,系列事件的元素的一个例子是{1,2},我们可以将其解释为滚动 1 或 2,这具有概率
ℙ({1,2}) = 大小 ({1,2})/ 大小(ω_ 1)= 2/6 = 1/3
在有两个骰子的情况下,有 6 = 36 种可能的结果,ω的定义如上所述。然后
ℙ((1,2)) = 尺寸 ({(1,2)})/ 尺寸(ω)= 1/36
并如上取 A:
ℙ(A) = 尺寸 (A)/ 尺寸(ω)= 4/36 = 1/9
配备了一组结果ω、一系列事件ℱ和一个概率测度ℙ,我们几乎拥有了展示概率论基本思想所需的一切。缺少的成分是我们在本节开始时定义的函数:x。这个函数是一个棘手的对象,处理它需要一些小心。换句话说,需要更多的数学知识,我们很快会讲到。现在,我将声称我们可以使用 X 对示例游戏的随机性进行编码。
*从技术上讲,ℱ就是我们所说的ω上的𝝈-algebra。
背景
这个鼓舞人心的例子给了我们足够的材料来更全面地描述这个场景。
三元组(ω,ℱ,ℙ)被称为一个概率空间如果ℙ(ω= 1。在这种情况下,将ℱ元素发送到区间[0,1]中的数字的映射,
ℙ:ℱ →[0,1]
被称为概率度量。
要求ℙ*(ω)= 1 反映了这样一个逻辑:在(ω、* ℱ 、 ℙ )的世界里,从ω开始一定会有什么事情发生。
元素 A ∈ ℱ被称为事件,而元素𝛚(小写ω)∈ω(等价于{𝛚} ∈ ℱ)被称为基本事件(或实现)。
ℱ中的事件由基本事件组成(或者缺少基本事件,例如你 不 掷出两个 6 的事件)。
下一步是定义随机变量的概念。我们的直觉告诉我们,这一定是某种随机取值的变量。从数学上来说,这并不容易定义。正式定义将以如下方式遵循我们的直觉:
当我们衡量一个事件的概率时,我们从衡量我们有多大可能 观察到 一个事件开始。
在骰子示例中,我们可以观察到两个骰子的和以四种方式为 9,按集合 a 的元素列出。我们通常会从一组结果开始做同样的事情,并测量可能导致该结果的可能性集合的大小。
我们将此形式化如下:设 x:ω→ℝ是一个函数,它将基本事件从ω发送到实数线(即我们熟悉的所有常用数字)。那么函数 x 将是一个随机变量如果任意子集 b 的逆像⊂ℝ(符号⊂用来表示 b 是ℝ的子集)包含在ℱ.中
一个函数的 给定集合 b 的逆像 是它发送给 b 的元素的集合,对于 x:ω→ℝ,这里定义为:**
x⁻(b)= {𝛚∈ω:x(𝛚)⊂b }**
其中 B ⊂ ℝ 。
例如,如果我们从两个骰子游戏的工作示例中返回到函数 X。则 9 的逆像(取{9}为ℝ的子集)为
X⁻ ({9}) = {(i,j)∈ω:x((I,j)) = 9}
= {(i,j)∈ω:I+j = 9 }
= {(3,6), (4,5), (5,4), (6,3)}
= A
我们知道 A ∈ ℱ.到目前为止,一切顺利。事实上,既然我们把空集、∅作为ℱ的一部分包括在内,那么事实证明,ℝ的任何子集的逆像都在ℱ.所以 X 满足条件,它是一个随机变量。
*实际上,这个条件是一个技术要求,在大多数(计算)设置中我们不必担心。相反,我们会更关心我们最终使用的设置是否合理。
随机变量和随机性
将数学与我们的直觉联系起来,我们如何解释形式条件 x:ω→ℝ是一个随机变量** if X⁻ (B) ∈ ℱ对于实数的任何子集 B ⊂ ℝ?我们可以这样想:**
如果我们做一些观察,b,也就是 ℝ 中可量化的,那么 X⁻ (B)就是可能事件的集合,通过它 随机变量 x 引出 B 。换句话说,相对的 大小 X⁻ (B)是 b 的 几率 由 x 的 随机生成机制**
事实上,这正是我们在使用概率度量来度量B 的可能性时所做的事情:**
ℙ(x⁻(b))=ℙ({𝛚∈ω:x(𝛚)⊂b })**
受这种等价性的激励,以及对直觉连贯性的渴望(通常我们不会用逆像来思考事件!),我们可以简单地写
ℙ(X ⊂ B)代替ℙ(X^{-1}(B))
我们可以把这个表示理解为随机变量 X 落在 B 的 概率。
然而,集合包含符号看起来有点笨拙,只是为了技术上的完整性。我们可以通过书写使东西更容易阅读
ℙ(X = B)代替ℙ(X ⊂ B)
我们把这个理解为 X 等于 B 的 概率,简单来说就是随机变量 X 取值 B 的概率。
回到我们的例子,如果我们取 B = {9},然后简单地写 9 而不是{9},我们可以恢复掷骰子游戏中两个数总和为 9 的概率的通常符号:
ℙ(X = 9) = 1/9
最后,我们可以采取一种更直接的方法来测量概率,从一个感兴趣的事件开始,比如产生一些观察的 A ∈ ℱ。为了测量其可能性,我们从评估该事件的随机变量开始:
B = X(A) = {X(𝛚): 𝛚 ∈ A}
然后我们计算:
ℙ(a)= ℙ(x(a)= ℙ(x = ℙ(b)
根据上下文,选择更清楚的符号。
奖金
给定任何一组𝕌,我们说如果ℙ(𝕌= 1,𝕌几乎必然发生。这就解释了题目。
由 Patrick Fore 在 Unsplash 上拍摄的照片
原载于 2017 年 11 月 23 日jontysinai . github . io*。*
概率第 2 部分:条件概率
这是我写的关于概率的系列博客的第二篇。在这篇文章中,我介绍了条件概率的基本概念,它允许我们在概率计算中加入额外的信息。条件概率背后的思想自然会引出概率论中最重要的思想,即贝叶斯定理。与第一篇文章一样,你可以在这里读到,这种方法是用测度论的数学思想来解释条件概率。同样,和第一篇文章一样,这篇文章是给任何人看的,不管你是否学过数学。
掷骰子的游戏
在我的上一篇文章中,我讨论了概率作为一种测量事件不确定性的方法。我们认为概率是给一个事件产生特定结果的机会分配一个权重,我们相对于其他可能的结果来衡量这个权重。我们定义了一个事件空间,我们称之为ω。在这个事件空间中,我们定义了一个随机变量 x,作为一个函数,它将每个事件映射到我们观察到的结果,在ℝ:的实际线上编码为数字
x:ω→ℝ.
结果的概率是相对于整个事件空间大小的映射到该结果的可能事件数量的大小:**
ℙ :ℱ → [0,1]。
我们称可能事件的集合为随机变量的原像*。如果 b 是一个结果,那么 b 的原像是 X⁻ (B),b 的概率是原像的相对大小,由 ℙ (X⁻ (B))给出*
例如,在上一篇文章的骰子示例中,我们考虑了掷出两个骰子并把数字相加的实验,如果我们观察到一个结果* 9,那么有四个可能的事件加起来可能是 9,即(3,6)、(4,5)、(5,4)和(6,3)。我们称这个集合为 A。由于ω中有 36 种可能的结果,因此我们可以通过 A 相对于ω的相对大小来衡量得到 9 的概率。如果 X 是代表我们实验的随机变量,那么 A 是观察 X = 9 的原像,A 的概率是*
ℙ (一)= 4/36 = 1/9。
思考过去
然而,如果我们能够整合以前发生过的事件的信息会怎么样呢?例如,假设我们不是一次滚动两个骰子,而是一次滚动一个。在这种情况下,根据第一次掷骰的结果,得到 9 的概率会有所不同。为了说明这一点,我们来看一个例子,我们的第一次掷骰子是 3。在第一个场景中,在掷骰子之前,总共有 36 种可能的配置。然而,现在我们已经观察到一个骰子为 3,配置的总数减少了,即集合:**
B = {(3,1),(3,2),(3,3),(3,4),(3,5),(3,6) }。
在这种情况下,只有一种可能的结果是 9:我们在第二次掷骰子时得到 6。我们现在怎么计算 9 的概率?在这篇博文的结尾,我们将会看到计算总不确定性需要概率论中一个基本而重要的结果,即贝叶斯定理*。我们将朝着这一点努力,但现在我们将从最简单的场景开始。*
利用我们已经知道的
我们已经把问题简化为我们已经掷出了 3 的事件,所以我们所有的不确定性仅仅在于第二次掷出。在这种情况下,我们看到总共只有 6 个可能的事件,其中只有个导致 9。使用与上一篇文章相同的逻辑,我们已经掷出 3 个的概率为 9,* 概率为 :*
ℙ (观察一个 9 |滚一个 3) = 1/6。
首先要注意的是,这种概率高于完全不确定的情况,其中 ℙ (A) = 1/9。这是有道理的,因为掷出 3 极大地增加了我们得到 9 的机会,即使 6 个配置中只有一个是有效的。为了更好地理解这一点,假设我们第一次没有掷出 3,那么我们的可能事件空间,我们称之为𝚯(capital 希腊字母“theta”)有 30 种可能的配置。在这个空间上,有 3 种可能的构形通向 9,即(4,5),(5,4)和(6,3)。因此,假设我们在第一次掷骰子时没有掷出 3,那么得到 9 的概率是:
ℙ (观察一个 9 |没有滚过一个 3) = 3/30 = 1/10,
这比完全不确定的情况要少,甚至比我们第一次掷出 3 的情况还要少。很明显,第一次掷出 3 会增加我们得到 9 的机会。
其实比那个更笼统。任何增加我们到达 A 的机会的掷骰子,毕竟是 X = 9 的前像,将会增加我们的机会。这个基本思想可以用图表来解释。
概率的形状
让我们回到之前的陈述,我说过结果 B 的概率是由它的原像的相对大小给出的:
ℙ(b)=size(x⁻(b))/尺寸(ω)。
让我们用图形来解释这意味着什么。我们可以将ω中的事件可视化为阴影区域,例如集合 X⁻ (B),为简单起见,我们简单地将其标记为 b,如下所示:
虽然这些可视化只是一种启发,对于测量概率来说太不精确,但它们有助于可视化不同事件如何相互作用,以及它们的概率可能如何相互作用。
例如,如果 A 是我们的掷骰数加起来为 9 的事件,我们可以把它包括在我们的图中,现在很清楚,这个事件正好在一点上与 B 相交:对(3,6)。
这是导致 9 的一种配置,第一次掷出 3。但是,既然这是ω中的一个点,为什么我们不把它的概率度量为 ℙ( (3,6))= 1/36 呢?那要看我们在找什么了。我们尤其对 9 的概率感兴趣,因为我们已经掷出了 3* 。如果我们已经掷出了一个 3,那么我们就不在整个空间ω中了。*
像(2,4),(1,5)和(4,1)这样的构型对我们来说已经不存在了,所以显然我们必须重新定义我们感兴趣的空间。
重估尺寸
要了解如何做到这一点,让我们回到 A 和 B 的图表。如果我们已经掷出了 3,那么我们可用的可能配置就从整个ω缩小到了集合 B!这个收缩动作也排除了 A 中的一些配置,除了(3,6),它在 A 和 b 的交集中,我们可以形象地把它想成:
现在,当我们假设概率为 9,假设我们掷出了 3,我们必须重新评估我们如何在现在可能的情况下衡量大小。9 的原像现在只是交集。由于假设事件 B 已经发生(通过事件空间收缩到 B 来可视化),我们测量原像相对于 B 的大小,因此
ℙ (观察 a 9 |滚 a 3)=ℙ(a | b)= size(a∩b)/size(b)= 1/6
条件概率
我刚才所展示的被称为事件的条件概率。它是事件 A 的概率,条件取决于事件 B。通过将条件视为对事件空间大小的限制,我们可以将给定 B 的条件概率度量为
ℙ (A| B) =大小(a∩b)/大小(b)。
我们可以通过记住任何事件的概率是由该事件相对于整个集合的大小给出的来使这一点更加直观,即:
ℙ (B) =尺寸(b)/尺寸(ω)。
轻微的手动重排给出:
尺寸(B) =尺寸(ω)ℙ(b)、
因为大小(ω)总是正的,所以我们可以这样做。我们可以得到集合 A ∩ B 的类似公式。将这两个公式代入我们的条件概率表达式,得到
ℙ (A| B) =尺寸(ω)ℙ(a∩b)/尺寸(ω)ℙ(b)、
这简化为
ℙ(a | b)=ℙ(a∩b)/ℙ(b)。
回归直觉
直观地说,给定 B,A 的概率等于 A 和 B 的概率除以恰好为 B 的概率。通过推导示例中的公式,我们将这种划分理解为事件空间的收缩。数学上这种收缩动作被称为事件空间的到条件空间的投影。
从初等数学中我们立即知道,为了避免除法错误,B 的概率不能为零。事实上,这加强了我们的直觉,因为我们不能以不可能的事件为条件!
最后,我们可以把交集看作是我们感兴趣的事件对条件事件的限制。的确,A 和 B 的交集可以认为是集合 A 到集合 B 的投影*,也就是条件空间。*
总而言之,我们可以把 条件概率 *看成是投射到某个(更小)条件空间 上的概率。*
贝叶斯定理:概率的基本性质
事实证明,交集是对称的:A 到 B 的投影与 B 到 A 的投影是相同的。事实上,前面的图加强了这一点。
基于同样的程序,我们可以很容易地推导出条件概率
ℙ(b | a)=ℙ(a∩b)/ℙ(a)。
再一次,因为 ℙ (A)是正的并且不可能是零,我们可以使用数学上的手算来推导交集概率的表达式:
ℙ(a∩b)=ℙ(b | a)ℙ(a)。
这就说 A 和 B 的概率是给定 A 的 B 的条件概率乘以恰好 A 的概率。**
直觉上,如果我们考虑 B 的条件概率,假设 A 已经发生,并且我们考虑 A 的概率,那么我们必须考虑两者的概率。
但是我们从前面知道,如果我们有了交集的概率,我们可以投影 B 的条件空间来计算逆概率:给定 B 的条件概率*,由下式给出:*
ℙ(a | b)=ℙ(a∩b)/ℙ(b)} =ℙ(b | a)ℙ(a)/ℙ(b)。
这个最终结果被称为贝叶斯定理。
在这个公式中,如果 A 是我们感兴趣的事件,B 是条件事件,那么数量
ℙ
被称为给定 b 的后验概率
数量
ℙ
被称为给定 b 的可能性
最后是数量
ℙ (一)
简单地称为 a 的先验概率。
直观上,A 的先验是 A 在考虑任何其他事件之前的原始概率。可能性虽然被视为 B 的条件概率,但也可以被认为是 A 依赖 B 的可能性的度量。要理解为什么,回想一下我们通过考虑交集的对称性来推导出可能性在公式中的位置。最后后验是条件作用于 b 后 A 的最终概率
贝叶斯定理的重要性
从根本上说,贝叶斯定理通过考虑我们的总不确定性*,给了我们一种测量条件概率的方法。这是我在这篇文章前面承诺的观点。在本例中,我们可以通过考虑贝叶斯定理中的所有量来直接测量 ℙ (观察 a } 9 |掷出的 a ^ 3),而不是一次考虑一个,然后列举第一次掷出 a ^ 3 后总事件空间如何变化。*
我将把这作为一个练习,但是通过仔细考虑可能性(提示:回忆一下我们如何利用交集的对称性得出可能性),你可以计算后验概率,并且看到它产生相同的结果。**
虽然从我使用测量理论直觉推导条件概率的基本例子中并不明显,但在某些情况下,计算可能性比直接测量感兴趣的后验概率要容易得多。这篇文章旨在介绍条件概率,所以我不会在这里详细介绍。然而,对于那些感兴趣的人,我建议阅读已故的大卫·麦凯的书的第三章《信息论、推理和学习算法*,这里有免费的。*
虽然 ITILA(缩写为)已经被更现代的机器学习教科书所取代(考虑到机器学习的研究速度,它们也不会过时太久),但它仍然是学习算法的基本参考,特别是从概率的角度来看。
偶然性呢?
人们有一种自然的倾向,认为条件概率是一种因果关系。如果我们以 B 为 A 的条件,这是否意味着 B 导致 A。一般来说,情况并非如此,陷入这个陷阱是危险的。事实上,在推导过程中,我认为条件作用在某种意义上是对称的,如果我们能以 B 为条件,那么我们也能以 a 为条件。事实上,贝叶斯定理要求我们认为条件概率(后验概率)取决于它们的条件逆*(可能性)。*
因果关系是统计学中最难理解的概念之一。这要求我们重新思考统计关系的建模方式。将来,根据我对基本思想的理解程度,我希望能写一系列关于因果推理的类似博客。
卢卡斯·布拉塞克在 Unsplash 上拍摄的照片
原载于 2018 年 12 月 23 日jontysinai . github . io*。*
学习机器学习—概率论基础
介绍
在这个系列中,我想探索一些来自统计学的介绍性概念,这些概念可能对那些学习机器或刷新知识的人有所帮助。这些主题是数据科学的核心,并且经常出现在丰富多样的主题中。从头再来一遍总是好的——这样我们可能会发现以前隐藏的新知识,所以让我们继续。
第一部分将介绍概率论的基础知识。
可能性
既然我们已经有了这么好的数学工具,为什么我们还需要概率呢?我们用微积分来处理无穷小尺度上的函数,并测量它们如何变化。我们发展了代数来解方程,我们还有几十个其他的数学领域来帮助我们解决我们能想到的几乎任何类型的难题。
困难的是,我们都生活在一个混乱的宇宙中,在这个宇宙中,很多时候事情都无法精确测量。当我们研究真实世界的过程时,我们想要了解扭曲我们实验的无数随机事件。不确定性无处不在,我们必须驯服它来满足我们的需求。这就是概率论和统计学发挥作用的时候。
如今,这些学科处于人工智能、粒子物理、社会科学、生物信息学以及我们日常生活的中心。
如果我们要讨论统计学,最好先确定什么是概率。其实这个问题没有单一的最佳答案。我们将在下面讨论概率论的各种观点。
常客概率
想象一下,给了我们一枚硬币,我们想检查它是否公平。我们如何解决这个问题?让我们试着做一些实验,如果正面朝上,记下 1,如果看到反面,记下 0。重复这 1000 次投掷,并计算每个 0 和 1。在我们进行了一些冗长的实验后,我们得到了这些结果:600 个正面(1)和 400 个反面(0)。如果我们接着计算过去出现正面或反面的频率,我们将分别得到 60%和 40%。这些频率可以解释为硬币正面朝上或反面朝上的概率。这被称为一种频率主义者对概率的观点。
条件概率
我们经常想知道一个事件发生的概率,如果其他事件已经发生的话。我们把一个事件的条件概率 A 给定事件 B 写成 P(A | B) 。以下雨为例:
- 如果我们看到打雷,下雨的可能性有多大
- 假设天气晴朗,下雨的可能性有多大?
从这张欧拉图我们可以看出 P(Rain | Thunder) = 1 :看到打雷的时候总是在下雨(是的,不完全是这样,但我们在例子中会把这当成是真的)。
那 *P(雨|晴)*呢?从视觉上看,这个概率很小,但是我们如何用数学公式来表达它,并进行精确的计算呢?条件概率定义为:
换句话说,我们将下雨和晴天的概率除以晴天的概率。
从属和独立事件
如果一个事件的概率不以任何方式影响另一个事件,则称该事件是独立的。以掷骰子第一次和第二次得到 2 的概率为例。这些事件是独立的。我们可以这样表述
但是为什么这个公式有效呢?首先,让我们将第一次和第二次投掷的事件重命名为 A 和 B 以消除符号混乱,然后将掷骰子的概率明确重写为我们目前看到的两次掷骰子的联合概率:
而现在把 P(A) 乘以 P(B) (没什么变化,可以抵消掉)回想一下条件概率的定义:
如果我们从右向左阅读上面的表达式,我们会发现 P(A | B) = P(A) 。基本上,这意味着 A 独立于 B!同样的道理也适用于 P(B) 并且我们完成了。
贝叶斯概率观
有一种看待概率的替代方法叫做贝叶斯方法。统计学的频率主义方法假设存在一个我们正在寻找的模型参数的最佳具体组合。另一方面,贝叶斯方法以概率方式处理参数,并将它们视为随机变量。在贝叶斯统计中,每个参数都有自己的概率分布,它告诉我们参数给定数据的可能性有多大。从数学上讲,这可以写成
这一切都始于一个简单的定理,它允许我们基于先验知识计算条件概率:
尽管简单,贝叶斯定理有着巨大的价值,广泛的应用领域,甚至是统计学的一个特殊分支——贝叶斯统计。如果你对贝叶斯定理是如何推导出来的感兴趣,有一篇关于贝叶斯定理的非常好的博文——一点也不难。
分布
什么是概率分布?这是一个告诉我们在一些实验中不同可能结果的概率的定律,以数学函数的形式表达。正如每个函数一样,分布可能有一些参数来调整其行为。
当我们测量抛硬币事件的相对频率时,我们实际上已经计算了所谓的经验概率分布。事实证明,我们世界中的许多不确定过程都可以用概率分布来描述。例如,我们的硬币结果有一个伯努利分布,如果我们想在 n 次试验后计算正面概率,我们可以使用二项式分布。
引入一个类似于可能在概率环境中使用的变量的概念是很方便的——随机变量。每个随机变量都有一个分配给它的分布。随机变量按照惯例用大写字母书写,我们可以用 ~ 符号来指定分配给变量的分布。
这意味着随机变量 X 根据伯努利分布分布,成功概率(头数)等于 0.6 。
连续和离散概率分布
概率分布有两种形式:离散分布处理的是具有有限可数数值的随机变量,就像硬币和伯努利分布一样。离散分布由称为概率质量函数(PMF)的函数定义,连续分布处理连续随机变量,这些变量(理论上)可以有无穷多个值。想想用噪声传感器测量的速度和加速度。连续分布由称为概率密度函数(PDF)的函数定义
这些类型的分布在数学处理上有所不同:你通常会对离散分布使用求和 ∑ ,对连续概率分布使用积分 ∫ 。以期望值为例:
样本和统计数据
假设我们正在做人类身高的研究,渴望发表一篇令人瞠目结舌的科学论文。我们测量了街上一些陌生人的身高,因此我们的测量是独立的。我们从真实总体中随机选择数据子集的过程称为抽样。统计是用于使用样本中的值来汇总数据的函数。您之前可能遇到的统计数据是样本均值:
另一个例子是样本方差:
这个公式从整体上捕捉了所有数据点与其平均值的差异。
如果我想要更多呢?
你想深入学习概率论和统计学?太好了!无论你是想对机器学习背后的理论有一个坚实的理解,还是仅仅出于好奇,你肯定会从这些知识中受益。
- 入门级 : 可汗学院是一个很棒的免费资源。这门课程将以非常直观和简单的形式让你了解基础知识
- 拉里·乏色曼的《统计学》是一个伟大而简洁的资源,它将向你展示统计学中几乎所有的重要主题。注意,这本书假设你熟悉线性代数和微积分
- 高级水平:我敢打赌,到这个时候,你会量身定制你的个人阅读清单🙃
如果你喜欢这篇文章,请留下💚。它让我知道我在帮忙。
用“人工智能挑战者全球人工智能大赛”解决问题
参加中国数据科学平台 AI Challenger 主办的计算机视觉大赛的体会
在这篇文章中,我将分享我在中国机器学习竞赛中解决视频分类问题的经验。
竞争对手有很多数据科学平台。我们过去常常想到 ka ggle——最受欢迎的一个。无论如何,有许多其他平台为数据科学家提供了具有挑战性的任务,现在是探索它们的好时机。这就是为什么我和我的队友 Alexey Grigorev 参加了中国平台 AI Challenger 的短视频实时分类比赛。非常感谢卡格尔大师阿图尔·库津成为我们这次比赛的导师。他帮助我们提出创造性的想法,并为我们提供了一台 GPU 服务器。
竞争描述
视频数据集大约 2 TB 大,并被分成训练集和验证集。有 2 个测试集:测试 A 和测试 b。每个视频可能有 1 到 3 个标签,因此这是一个多标签分类。例如,下面是一个视频帧,有两个类:钢琴和婴儿
以下是可能的标签的完整列表:
这场比赛有一个复杂的评估标准。除了准确性之外,时间限制也被作为一个评估指标。您可能会认为它是从输入一个视频到输出一个预测所用的总时间。
最后,将这两个公式考虑在内,以提交的结果和参考点之间的加权距离来计算综合指标。你可以在这里阅读更多关于指标的信息。
关键的想法是,组织者希望从数据科学社区获得一种可用于工业的高速应用。对于提交材料,参赛者必须加载图像 docker 包。
训练神经网络
我们混合使用了神经网络和更简单的模型来为最终预测做一个集成。我们尝试了不同的网络架构。最好的结果是使用 se_resnet50。“挤压和激励”模块以最小的计算成本提高了 resnet 模型的质量。您可以在本出版物中了解更多关于该架构的信息。作为训练模型的基线,我们从提取第一帧开始。学习率为 0.001,每 30 个时期衰减 10。时代的总数是 150。作为一个优化器,具有重量衰减和动量的随机梯度下降被用于更快的收敛。有趣的是,尽管事实上我们有多标签和多类问题,但我们用 BCEwithlogitsloss 得到了不好的结果。相反,我们使用交叉熵损失,这大大提高了准确性。质量差距的原因可能是数据中缺乏多标签的例子。我们花一些时间思考如何预测多个标签。例如,我们训练了一个二元分类器来预测一个例子是否有一个或多个标签。另一个问题是课程的门槛。我们分析了类别分布并计算了类别的权重。这个想法是,如果二进制分类器预测一个例子有一个以上的标签,则添加一些系数来加权。在这种情况下,我们可以达到一些我们以前没有考虑到的类的阈值。
无论如何,我们没有对类使用阈值,因为根据度量标准,我们知道给定一个具有多个标签的示例,最好只预测其中一个标签,而不是预测一个多余的标签。用这样的方法做实验,让多类预测模型更加稳定,还有很大的空间。
尝试经典的 ML 算法进行组合
解决方案的另一部分是,我们在全局汇集后从神经网络中提取特征,并将这些特征用作更简单的分类器的输入,如梯度增强、逻辑回归和支持向量机。最终集成由四个最好的单一模型(神经网络、对数注册、SVM、catboost)与多数投票分类器组合而成。这个模型在测试 A 中给了我们 0.76 分,但不幸的是这不足以让我们进步。
聚合视频帧并面临新问题
下一步是将聚合添加到神经网络训练中。现在,我们从每个视频中提取五个随机帧,并使用最频繁的标签作为单个预测。我们做了同样的事情来提取经典模型的新特征,效果非常好,我们在验证上得到了 0.91。我们对这些结果感到高兴。截止日期前一周,我们决定提交,但现在我们面临着时间问题。模型是快速的,但是根据规则,还需要考虑视频预处理的时间。我们注意到提取一帧大约需要 0.03-0.05 毫秒。不幸的是,这不允许我们匹配提交限制。
然后,我们决定使用聚合来训练模型,但在一个随机帧上进行预测。这比我们之前没有任何聚合的模型要好一些。验证的得分为 0.81,测试 A 的得分为 0.79,单次预测的时间约为 0.11 毫秒。我们有一个在 GPU 上解码视频以加快进程的想法,但我们没有足够的时间来管理如何使用 docker。这是我们的销售渠道:
竞争氛围
let me add some words about competition organization. AIChallenger pretends to be a global data science platform, but it has a lot of work before it gets there. We faced technical problems while participating, mostly with the docker submission. This Challenge was organized by MeiTu company (美图). For example competition started on 3rd of september but information about the docker instructions appeared on website only up to 12th of october. All instructions were in Chinese language. We accidentally got to know that organizers were assisting participants in Chinese messenger WeChat, but it was also in Chinese and didn’t help foreign competitors. The funny thing was that even the submit button was in Chinese. We once even wrote a comment on the forum to encourage organizers to solve technical problems, but it only partly helped. In the future i hope we will see a better level of organization and technical support.
结束语
我们的比赛就这样结束了。尽管我们没能提交最好的模型,但还是值得一试。我们了解了如何解决这类机器学习问题。此外,在这个项目上工作了近 3 个月后,我们现在有了一个很好的管道,你可以在 github 这里找到。
然而,一个好的趋势是,挑战规则迫使竞争对手考虑设计一种用于生产的算法。因此,除了建模之外,它还有助于提高代码优化和创建可重用管道的技能。最后,我想鼓励大家探索新的数据科学平台,并继续参加比赛,以更好地应对这些挑战。
流程博客#6 —可视化
该过程
本周,我们的 sprint 专注于使用专业软件 Tableau 和 2015 年西雅图 911 电话的数据集来创建数据的可视化。因为当我们被分配任务时,我刚刚参加了最后一次期中考试,我想没有比减压更好的事情了——推而广之,就是聚会。最后,我把自己的想象提供给了一个 UW 的学生,他在希腊生活之外寻找一个可以参加的派对,但却不知道何时何地可以找到一个。为了回答我的用户组关于何时何地可以找到最好的聚会的问题,我创建了三个可视化工具:
Visualization 1: Number of Noise Complaints by Weekday
Visualization 2: Number of Noise Complaints by Hour of the Day
Visualization 3: Areas in the U-District with 20+ Noise Complaints
我将搜索范围限制在 U 区附近,因为它离大学很近,并且只使用了噪音投诉或酒精/大麻违规的记录,因为大多数好的聚会往往会将喧闹的气氛与某种形式的物质结合起来。(顺便说一句,如果你想知道,数据显示你应该在周五、周六或周日晚上 10 点左右去东北第 19 大道的 45xx 街区,这样你就可以在警察打电话之前享受一下了)。
那又怎样?
我在创建可视化时遇到的一个主要问题是,我的标准似乎太宽泛了。例如,噪音投诉电话不仅是由喧闹的聚会产生的,而且未成年人被发现饮酒并不总是在聚会上。然而,我认为我的可视化是基于相关性的,而不是基于因果关系的,这意味着电话录音数量较多的一天或地区比电话较少的地区更有可能举行聚会。这就是为什么“where”可视化只包括具有 20 个或更多记录的块,因为我觉得这是一个合适的样本大小,可以作为一个可能由于不仅仅是巧合而有呼叫进入的区域来包括。在未来,我认为,如果有机会,我可以找到一个与数据更直接相关的研究问题,或者寻找一个与我正在研究的问题更密切相关的数据集。
未来
在不久的将来,我可以看到可视化技术在为我和我的朋友们寻找一个住在校外的公寓或房子方面是有用的。利用网上的房源,我可以根据卧室数量或其他限制因素对可能的地方进行排序。我还可以使用我们在本周 sprint 中获得的数据集,使用 Tableau 中可用的地图可视化,检查最安全的区域在哪里,同时仍然靠近校园。鉴于我和我的朋友们在寻找一个离校园合理距离内的合适地点时遇到了一些困难,我觉得可视化可能会在我们继续寻找的过程中证明是非常有用的。
用 Python 处理 XML—element tree
初学者指南
“shallow focus photography of spider web” by Robert Anasch on Unsplash
了解如何使用 Python ElementTree 包解析、浏览、修改和填充 XML 文件,用于循环和 XPath 表达式。作为一名数据科学家,您会发现理解 XML 对于 web 抓取和解析结构化文档的一般实践都是非常有用的
可扩展标记语言 (XML)是一种标记语言,它通过定义一组机器可读和人类可读格式的规则来编码文档。从 SGML(标准通用标记语言)扩展而来,它让我们描述文档的结构。在 XML 中,我们可以定义自定义标签。我们也可以使用 XML 作为交换信息的标准格式。
- XML 文档有几个部分,叫做 元素 ,由一个开始和一个结束标签 定义。标签是一种标记结构,以
<
开始,以>
结束。开始标记和结束标记之间的字符(如果有的话)是元素的内容。元素可以包含标记,包括其他元素,这些元素称为“子元素”。 - 最大的顶级元素称为 根 ,它包含所有其他元素。
- 属性是存在于开始标记或空元素标记中的名称-值对。XML 属性只能有一个值,并且每个属性在每个元素中最多只能出现一次。
这里有一张movies.xml
的快照,我们将在本教程中使用:
<?xml version="1.0"?>
<collection>
<genre category="Action">
<decade years="1980s">
<movie favorite="True" title="Indiana Jones: The raiders of the lost Ark">
<format multiple="No">DVD</format>
<year>1981</year>
<rating>PG</rating>
<description>
'Archaeologist and adventurer Indiana Jones
is hired by the U.S. government to find the Ark of the Covenant before the Nazis.'
</description>
</movie>
<movie favorite="True" title="THE KARATE KID">
<format multiple="Yes">DVD,Online</format>
<year>1984</year>
<rating>PG</rating>
<description>None provided.</description>
</movie>
<movie favorite="False" title="Back 2 the Future">
<format multiple="False">Blu-ray</format>
<year>1985</year>
<rating>PG</rating>
<description>Marty McFly</description>
</movie>
</decade>
<decade years="1990s">
<movie favorite="False" title="X-Men">
<format multiple="Yes">dvd, digital</format>
<year>2000</year>
<rating>PG-13</rating>
<description>Two mutants come to a private academy for their kind whose resident superhero team must oppose a terrorist organization with similar powers.</description>
</movie>
<movie favorite="True" title="Batman Returns">
<format multiple="No">VHS</format>
<year>1992</year>
<rating>PG13</rating>
<description>NA.</description>
</movie>
<movie favorite="False" title="Reservoir Dogs">
<format multiple="No">Online</format>
<year>1992</year>
<rating>R</rating>
<description>WhAtEvER I Want!!!?!</description>
</movie>
</decade>
</genre>
<genre category="Thriller">
<decade years="1970s">
<movie favorite="False" title="ALIEN">
<format multiple="Yes">DVD</format>
<year>1979</year>
<rating>R</rating>
<description>"""""""""</description>
</movie>
</decade>
<decade years="1980s">
<movie favorite="True" title="Ferris Bueller's Day Off">
<format multiple="No">DVD</format>
<year>1986</year>
<rating>PG13</rating>
<description>Funny movie on funny guy </description>
</movie>
<movie favorite="FALSE" title="American Psycho">
<format multiple="No">blue-ray</format>
<year>2000</year>
<rating>Unrated</rating>
<description>psychopathic Bateman</description>
</movie>
</decade>
</genre>
元素树简介
XML 树结构使得导航、修改和移除在程序上相对简单。Python 有一个内置的库, ElementTree ,它有读取和操作 XML(和其他类似结构的文件)的函数。
一、导入ElementTree
。使用ET
的化名是很常见的做法:
**import xml.etree.ElementTree as ET**
解析 XML 数据
在提供的 XML 文件中,有一个描述电影的基本集合。唯一的问题是数据很乱!这个收藏有很多不同的管理者,每个人都有自己的方式将数据输入文件。本教程的主要目标是用 Python 阅读和理解文件,然后解决问题。
首先你需要用ElementTree
读入文件。
**tree = ET.parse('movies.xml')
root = tree.getroot()**
现在已经初始化了树,您应该查看 XML 并打印出值,以便理解树是如何构造的。
**root.tag**'collection'
在顶层,您会看到这个 XML 植根于collection
标签。
**root.attrib**{}
对于循环
通过使用一个简单的“for”循环,可以很容易地迭代根中的子元素(通常称为“子元素”)。
**for child in root:
print(child.tag, child.attrib)**genre {'category': 'Action'}
genre {'category': 'Thriller'}
genre {'category': 'Comedy'}
现在你知道根collection
的孩子都是genre
。为了指定流派,XML 使用属性category
。根据genre
元素,有动作片、惊悚片和喜剧片。
通常,了解整个树中的所有元素是很有帮助的。一个有用的功能是root.iter()
。
**[elem.tag for elem in root.iter()]**['collection',
'genre',
'decade',
'movie',
'format',
'year',
'rating',
'description',
'movie',
.
.
.
.
'movie',
'format',
'year',
'rating',
'description']
有一种查看整个文档的有用方法。如果将根传递给.tostring()
方法,就可以返回整个文档。在 ElementTree 中,这个方法采用了一种稍微奇怪的形式。
由于 ElementTree 是一个功能强大的库,它不仅可以解释 XML,还必须指定显示为字符串的文档的编码和解码。
您可以扩展iter()
函数的用途,以帮助查找感兴趣的特定元素。root.iter()
将列出根下与指定元素匹配的所有子元素。这里,您将列出树中movie
元素的所有属性:
**for movie in root.iter('movie'):
print(movie.attrib)**{'favorite': 'True', 'title': 'Indiana Jones: The raiders of the lost Ark'}
{'favorite': 'True', 'title': 'THE KARATE KID'}
{'favorite': 'False', 'title': 'Back 2 the Future'}
{'favorite': 'False', 'title': 'X-Men'}
{'favorite': 'True', 'title': 'Batman Returns'}
{'favorite': 'False', 'title': 'Reservoir Dogs'}
{'favorite': 'False', 'title': 'ALIEN'}
{'favorite': 'True', 'title': "Ferris Bueller's Day Off"}
{'favorite': 'FALSE', 'title': 'American Psycho'}
{'favorite': 'False', 'title': 'Batman: The Movie'}
{'favorite': 'True', 'title': 'Easy A'}
{'favorite': 'True', 'title': 'Dinner for SCHMUCKS'}
{'favorite': 'False', 'title': 'Ghostbusters'}
{'favorite': 'True', 'title': 'Robin Hood: Prince of Thieves'}
XPath 表达式
很多时候元素没有属性,它们只有文本内容。使用属性.text
,可以打印出这个内容。
现在,打印出电影的所有描述。
**for description in root.iter('description'):
print(description.text)**'Archaeologist and adventurer Indiana Jones is hired by the U.S. government to find the Ark of the Covenant before the Nazis.'None provided.
Marty McFly
Two mutants come to a private academy for their kind whose resident superhero team must oppose a terrorist organization with similar powers.
NA.
WhAtEvER I Want!!!?!
"""""""""
Funny movie about a funny guy
psychopathic Bateman
What a joke!
Emma Stone = Hester Prynne
Tim (Rudd) is a rising executive who “succeeds” in finding the perfect guest, IRS employee Barry (Carell), for his boss’ monthly event, a so-called “dinner for idiots,” which offers certain
advantages to the exec who shows up with the biggest buffoon.Who ya gonna call?
Robin Hood slaying
打印出 XML 很有帮助,但是 XPath 是一种查询语言,用于快速方便地搜索 XML。然而,理解 XPath 对于扫描和填充 XML 至关重要。ElementTree
有一个.findall()
函数,它将遍历被引用元素的直接子元素。
在这里,您将搜索 1992 年上映的电影树:
**for movie in root.findall("./genre/decade/movie/[year='1992']"):
print(movie.attrib)**{'favorite': 'True', 'title': 'Batman Returns'}
{'favorite': 'False', 'title': 'Reservoir Dogs'}
函数.findall()
总是从指定的元素开始。这种类型的功能对于“查找和替换”来说非常强大。你甚至可以搜索属性!
现在,只打印多种格式的电影(一个属性)。
**for movie in root.findall("./genre/decade/movie/format/[@multiple='Yes']"):
print(movie.attrib)**{'multiple': 'Yes'}
{'multiple': 'Yes'}
{'multiple': 'Yes'}
{'multiple': 'Yes'}
{'multiple': 'Yes'}
集思广益,为什么在这种情况下,print 语句返回multiple
的“是”值。想想“for”循环是怎么定义的。
提示:在 XPath 内部使用'...'
返回当前元素的父元素。
**for movie in root.findall("./genre/decade/movie/format[@multiple='Yes']..."):
print(movie.attrib)**{'favorite': 'True', 'title': 'THE KARATE KID'}
{'favorite': 'False', 'title': 'X-Men'}
{'favorite': 'False', 'title': 'ALIEN'}
{'favorite': 'False', 'title': 'Batman: The Movie'}
{'favorite': 'True', 'title': 'Dinner for SCHMUCKS'}
修改 XML
早些时候,电影的名字是绝对的混乱。现在,再把它们打印出来:
**for movie in root.iter('movie'):
print(movie.attrib)**{'favorite': 'True', 'title': 'Indiana Jones: The raiders of the lost Ark'}
{'favorite': 'True', 'title': 'THE KARATE KID'}
{'favorite': 'False', 'title': 'Back 2 the Future'}
{'favorite': 'False', 'title': 'X-Men'}
{'favorite': 'True', 'title': 'Batman Returns'}
{'favorite': 'False', 'title': 'Reservoir Dogs'}
{'favorite': 'False', 'title': 'ALIEN'}
{'favorite': 'True', 'title': "Ferris Bueller's Day Off"}
{'favorite': 'FALSE', 'title': 'American Psycho'}
{'favorite': 'False', 'title': 'Batman: The Movie'}
{'favorite': 'True', 'title': 'Easy A'}
{'favorite': 'True', 'title': 'Dinner for SCHMUCKS'}
{'favorite': 'False', 'title': 'Ghostbusters'}
{'favorite': 'True', 'title': 'Robin Hood: Prince of Thieves'}
在未来修正后面 2 中的 2。这应该是一个查找和替换的问题。编写代码以找到标题“Back 2 the Future”并将其保存为变量:
**b2tf = root.find("./genre/decade/movie[@title='Back 2 the Future']")
print(b2tf)**<Element 'movie' at 0x10ce00ef8>
注意,使用.find()
方法返回树的一个元素。很多时候,编辑元素中的内容更有用。
将 Back 2 未来元素变量的title
属性修改为“回到未来”。然后,打印出变量的属性以查看您的更改。通过访问元素的属性,然后给它分配一个新值,可以很容易地做到这一点:
**b2tf.attrib["title"] = "Back to the Future"
print(b2tf.attrib)**{'favorite': 'False', 'title': 'Back to the Future'}
将您的更改写回 XML,以便它们在文档中永久固定。再次打印出您的电影属性,以确保您的更改生效。使用.write()
方法来做这件事:
**tree.write("movies.xml")****tree = ET.parse('movies.xml')
root = tree.getroot()****for movie in root.iter('movie'):
print(movie.attrib)**{'favorite': 'True', 'title': 'Indiana Jones: The raiders of the lost Ark'}
{'favorite': 'True', 'title': 'THE KARATE KID'}
{'favorite': 'False', 'title': 'Back to the Future'}
{'favorite': 'False', 'title': 'X-Men'}
{'favorite': 'True', 'title': 'Batman Returns'}
{'favorite': 'False', 'title': 'Reservoir Dogs'}
{'favorite': 'False', 'title': 'ALIEN'}
{'favorite': 'True', 'title': "Ferris Bueller's Day Off"}
{'favorite': 'FALSE', 'title': 'American Psycho'}
{'favorite': 'False', 'title': 'Batman: The Movie'}
{'favorite': 'True', 'title': 'Easy A'}
{'favorite': 'True', 'title': 'Dinner for SCHMUCKS'}
{'favorite': 'False', 'title': 'Ghostbusters'}
{'favorite': 'True', 'title': 'Robin Hood: Prince of Thieves'}
修复属性
multiple
属性有些地方不正确。使用ElementTree
根据电影的格式来固定指示器。首先,打印format
属性和文本,看看哪些部分需要修复。
**for form in root.findall("./genre/decade/movie/format"):
print(form.attrib, form.text)**{'multiple': 'No'} DVD
{'multiple': 'Yes'} DVD,Online
{'multiple': 'False'} Blu-ray
{'multiple': 'Yes'} dvd, digital
{'multiple': 'No'} VHS
{'multiple': 'No'} Online
{'multiple': 'Yes'} DVD
{'multiple': 'No'} DVD
{'multiple': 'No'} blue-ray
{'multiple': 'Yes'} DVD,VHS
{'multiple': 'No'} DVD
{'multiple': 'Yes'} DVD,digital,Netflix
{'multiple': 'No'} Online,VHS
{'multiple': 'No'} Blu_Ray
这个标签需要做一些工作。
您可以使用正则表达式来查找逗号——这将告诉您multiple
属性应该是“是”还是“否”。使用.set()
方法可以很容易地添加和修改属性。
**import re****for form in root.findall("./genre/decade/movie/format"):
# Search for the commas in the format text
match = re.search(',',form.text)
if match:
form.set('multiple','Yes')
else:
form.set('multiple','No')****# Write out the tree to the file again
tree.write("movies.xml")****tree = ET.parse('movies.xml')
root = tree.getroot()****for form in root.findall("./genre/decade/movie/format"):
print(form.attrib, form.text)**{'multiple': 'No'} DVD
{'multiple': 'Yes'} DVD,Online
{'multiple': 'No'} Blu-ray
{'multiple': 'Yes'} dvd, digital
{'multiple': 'No'} VHS
{'multiple': 'No'} Online
{'multiple': 'No'} DVD
{'multiple': 'No'} DVD
{'multiple': 'No'} blue-ray
{'multiple': 'Yes'} DVD,VHS
{'multiple': 'No'} DVD
{'multiple': 'Yes'} DVD,digital,Netflix
{'multiple': 'Yes'} Online,VHS
{'multiple': 'No'} Blu_Ray
移动元素
一些数据被放在了错误的年代。使用你所学到的关于 XML 和ElementTree
的知识来查找和修复十年数据错误。
在整个文档中打印出decade
标签和year
标签将会很有用。
**for decade in root.findall("./genre/decade"):
print(decade.attrib)
for year in decade.findall("./movie/year"):
print(year.text)**{'years': '1980s'}
1981
1984
1985
{'years': '1990s'}
2000
1992
1992
{'years': '1970s'}
1979
{'years': '1980s'}
1986
2000
{'years': '1960s'}
1966
{'years': '2010s'}
2010
2011
{'years': '1980s'}
1984
{'years': '1990s'}
1991
这两年是错误的十年,是 2000 年代的电影。使用 XPath 表达式找出这些电影是什么。
**for movie in root.findall("./genre/decade/movie/[year='2000']"):
print(movie.attrib)**{'favorite': 'False', 'title': 'X-Men'}
{'favorite': 'FALSE', 'title': 'American Psycho'}
为了转移 x 战警的数据,你必须在动作片中添加一个新的十年标签,即 2000 年代。可以使用.SubElement()
方法将这个标签添加到 XML 的末尾。
**action = root.find("./genre[@category='Action']")
new_dec = ET.SubElement(action, 'decade')
new_dec.attrib["years"] = '2000s'**
现在分别使用.append()
和.remove()
将 x 战警电影添加到 2000 年代,并将其从 20 世纪 90 年代删除。
**xmen = root.find("./genre/decade/movie[@title='X-Men']")
dec2000s = root.find("./genre[@category='Action']/decade[@years='2000s']")
dec2000s.append(xmen)
dec1990s = root.find("./genre[@category='Action']/decade[@years='1990s']")
dec1990s.remove(xmen)**
构建 XML 文档
很好,所以你可以把整部电影推进到一个新的十年。将您的更改保存回 XML。
**tree.write("movies.xml")****tree = ET.parse('movies.xml')
root = tree.getroot()****print(ET.tostring(root, encoding='utf8').decode('utf8'))**
结论
ElementTree 是一个重要的 Python 库,允许您解析和导航 XML 文档。使用 ElementTree 将 XML 文档分解成一个易于使用的树结构。如果有疑问,打印出来(print(ET.tostring(root, encoding='utf8').decode('utf8'))
)——使用这个有用的 print 语句一次性查看整个 XML 文档。
参考文献
产品分析偏差和 KPI
产品分析是一个具有挑战性的领域,它是产品、产品经理和用户之间的连接层。它要求你理解产品的技术层面,以及如何量化用户对它的反应。
产品分析最大限度地利用了数字中的硬性事实和用户的软性主观接受。你面临着天平的两端——这些数字是否显示了我们的期望,如果没有,为什么?
你的用户不是代码行。他们是独立的,多样的,有时是出乎意料的。关于我们用户的先验知识,结合心理学和社会假设,就像统计一样,是你工具箱的一部分。
在这篇文章中,我将回顾我在过去的分析项目中遇到的一些社会偏见事件。
早期采用者偏见
你的用户希望每个版本都有更好的产品,而公司正在努力满足他们。产品版本之间的比较,无论是新的硬件版本、应用程序版本还是新的设计,通常都以时间线图的形式进行,比较显示新版本与旧版本的关键指标。这种比较通常会在最初的几天或几周内显示出强烈的积极迹象,最终会减少并变得积极,但不如最初几天那么强烈。
让我们假设苹果发布了一款新的 iPhone 设备,它拥有更好的 Siri(苹果个人助理)算法。为了表明改变的成功,决定使用的 KPI 是“每个活跃用户每天使用 Siri 的平均次数”,这表明一个更好的算法将使用户更经常地使用 Siri。
同样,这是一个假设的图表,我们将使用它作为早期适配器偏差的例子。我们可以看到,在最初的几天里,所选择的度量天空火箭也有很高的方差,直到两个星期过去了,度量仍然高于以前的版本,但没有最初几天那么高。
Hypothetical Graph — Siri Usages per Active User
这张图表没有显示的是谁是新 iPhone X 的用户?他们是持有之前 iPhone 8 版本的同一批用户吗?
第一批接触任何产品新版本的用户被称为早期采用者,他们不同于一般人群。他们致力于产品,并等待看到它的变化。能不能把 iPhone 死忠粉丝和广大用户比一比?
削弱这种偏差的一种方法是将采用率与测量图平行,并消除版本之间的过渡时间,或者将比较限制在同一人群中。只看最终采用新版本的用户,将允许我们在假设任何变化都是由于用户与新版本的交互方式而不是由于选择性用户偏见的情况下,在 iPhone 版本之间进行比较。然而,同样的用户在遇到变化时也会有不同的反应,这就给我们带来了下一个心理偏差。
新奇效果
来自 维基百科:
“新奇效应是指当新技术开始实施时,绩效最初有所提高的趋势,这不是因为学习或成就的任何实际提高,而是对新技术兴趣增加的反应”
这是发布新版本或新功能后多次看到的另一种心理反应。用户会部分地与变化互动,只是因为它是新的,而不是它的价值。这种偏见倾向于损害我们对用户短期和长期影响的观点。你会发现,一旦 AB 测试获得所需的显著性值,这种偏差也会停止 AB 测试,事实上,如果实验运行更长时间,P 值将稳定在非显著性水平。有关这方面的更多信息,请点击此处:
[## 社会产品实验挑战
当谈到社交应用功能时,你会发现有太多关于用户如何接受新的或改变的观点…
towardsdatascience.com](/social-product-experimentation-challenges-3298546a6b0f)
默认效果
产品经理广泛使用产品中的默认设置,这是一个强有力的工具,可以将用户推向期望的行为。这就是让用户先决定或替用户选择与要求用户通过选择加入或选择退出默认选项来主动实施更改之间的区别。你可能在购买机票时见过这种情况,航空公司会自动将行李保险添加到你的订单中,而无需询问,你需要明确取消这一选择。
回到产品分析,更改产品中的默认设置将推动衡量标准的变化,但不是因为用户已经更改或发现了产品中的新价值。您的用户会倾向于坚持默认设置,因为需要做出改变,并且当他们不确定如何评估手头的其他选项时。
平衡 KPI
KPI(关键绩效指标)是以稳健清晰的方式衡量您朝着目标前进的最佳方式。一些关键绩效指标在不同行业中是通用的,如 MAU(每月活跃用户),而一些更具体,如市场的平均订单价值(AOV)。
就像偏见的例子一样,KPI 也可能讲述一个可能误导或不能展现全貌的故事。
受平均订单价值 KPI 驱动的市场公司可能会尝试推荐价格更高的产品,或者在漏斗中添加另一个步骤,以推荐向购物车添加更多商品,从而增加最终订单价值。只看 AOV 会显示所选 KPI 的改进,但会忽略另外两个 KPI:
完成订单漏斗的用户百分比——因漏斗中引入的额外步骤而降低。
回头客的百分比——由于推荐价格更高的产品而不是最符合用户需求的产品而下降。
使用相互平衡的多个 KPI 是看到全貌的方法,并且可以避免会增加一个 KPI 而降低另一个 KPI 的极端行为。一些文章将这些 KPI 称为计数器 KPI。
这三篇文章很好地列出了一般应用程序、市场和创业公司的不同 KPI。
产品组织越来越多地谈论数据如何成为他们决策过程的核心。但是,什么…
medium.com](https://medium.com/product-breakdown/product-management-analytics-what-metrics-should-you-be-measuring-241609b1950d) [## 10 个重要的市场 KPI
市场是非常强大的。他们席卷了我们经济的方方面面,改变了商品和…
medium.com](https://medium.com/@algovc/10-marketplace-kpis-that-matter-22e0fd2d2779) [## 十二金刚:在推销你的创业公司之前,你必须知道的 12 个关键绩效指标
对于一家公司的创始人来说,深入了解公司的关键绩效至关重要…
medium.com](https://medium.com/startupsco/the-dirty-dozen-12-kpis-you-must-know-before-pitching-your-startup-9791192bbda5)
让我们以主要在数量和质量之间平衡的 KPI 元组列表结束。当然,一些 KPI 可以有多个选项。
ARPU(每用户平均收入)
与
活跃用户中付费用户的百分比
你的优质产品与你的所有用户相关
CPI(每次安装成本)或 CAC(客户获取成本)
与
LTV(生命周期价值)
您的 CPI 活动是否会导致用户质量下降
从所有交易中防止欺诈交易(真阳性)
与
合法交易丢失(假阳性)
您是否在防止欺诈的同时也伤害了合法用户
完成购买漏斗的用户百分比
与来自购买用户的返回购买用户百分比
推动购买,同时忽略用户不满
解决的支持票证百分比
与
重新打开的票证百分比
支持数量或质量
感谢阅读,
哈雷尔·雷查维娅,
Viber 数据分析师
产品分析——如何衡量软件开发的成功
能衡量的就能完成。如今,随着低成本数据的出现和新技术浪潮的到来,这一点尤其正确,新技术使我们能够更深入地分析数据。
我们如何判断我的产品开发是否高效?
我的新软件发布成功了吗?
我们需要跟踪什么遥测数据?
这些问题出现得太频繁了,一劳永逸地解决这些问题很重要。让我给你看一个回答所有这些问题的框架!
一些方法
人们经常用来评估产品质量的一个经典方法是基于业务绩效指标;获取、销售、保留。从理论上看,这似乎是个好主意,但是这个要求太高了。如果你发布了一个有新特性的更新,如何快速评估设计是否成功?通过分析记忆是否会随着时间的推移而减少?这将花费太多的时间来看到一个效果,这是不好的,因为它阻止你快速失败和重复,直到软件产生期望的结果。
另一种方法是评估给定群组的使用情况。这是有道理的。您可以将一个群组与新设计进行比较,也可以将一个群组与旧设计进行比较(通过 A / B 测试或谨慎选择相似的时间段)。然而,这种方法虽然比第一种好,但并不仅仅针对产品开发。换句话说,这个方法对于产品团队来说不够具体。如果销售部门改变了流程,或者营销部门在公司网站上遇到了技术问题,该怎么办?不够好。
心脏框架
这个框架是由谷歌风险团队开发的。我喜欢这样的事实:它实现起来非常简单,并且直接与产品和设计团队交流!
HEART 框架是一个框架,它使你能够根据设计目标(你通过设计一个特性想要达到什么)将一个版本分解成更小的成功度量。
主要的设计目标是:
- 快乐:让用户更快乐地使用你的新功能或界面。
- 参与度:方便用户发现你的特色并与之互动。
- 采用:让用户在一段时间内对你的软件更加上瘾。
- 留存:让用户随着时间的推移对你的软件越来越上瘾。
- 任务成功:确保用户可以轻松完成操作。
HEART Framework
在这里,重要的是要理解度量本身是没有用的。您需要确保:
- 您的软件已正确标记(标记是使用遥测技术创建数据的操作,遥测技术可用于测量用户的操作)。MixPanel、Google Analytics 和 Kissmetrics 等好工具都是低成本的。
- 您在发布之后跟踪度量标准。
- 您要确保根据您将向团队提供的极具可操作性的见解进行纠正和改进!
流程
HEART Framework measurement process
要记住的事情
这个练习是由特征完成的。即使您的软件版本包含 3 个不同的特性,您也希望单独验证它们。
功能将有多个目标。通常,需要 2-3 个目标的组合。例如,如果你想优化保留,你也要确保你的功能被用户采用。尽管如此,如果你有一个专门的产品分析师,你可能想更细化。否则,保留一些您能够保持的指标(2-3)。
确保您可以测量每个指标。提醒您确保将这些指标用作标记文档。从长远来看,这会节省你很多时间。
与您的团队一起审核指标结果。验证每个指标后,作为一个团队对其进行评审。与其他更高层次的指标相比,这将使团队真正了解哪些方面可以改进。
结论
自从我在我的公司实施了这个框架,讨论和焦点已经明显转移到真正重要的事情上:产品是否符合我们的期望,用户对我们的产品是否满意。这也使我对软件标记有了一个系统的方法,从经验来看,这通常是不完美的。
我强烈建议实现这个框架和方法,因为在与产品团队、以产品为中心的组织中的设计师进行交互时,这个方法确实不言自明。
人工智能时代的产品定义
十年前,软件正在吞噬世界。但是,现在看起来人工智能正在吞噬世界。没有一天不发布新的算法、框架或库,使得将复杂的数学转化为杀手级产品变得更加容易。然而,有一点似乎很明显,那就是人工智能软件的产品定义。
原因并不太难理解。定义人工智能产品很难,也没有行业标准的方法论可言。在这篇文章中,我不会试图提供任何银弹,而只是分享一些想法和经验。但是在我们跳到基于人工智能的软件的具体例子之前,让我们先来看两个来自软件世界的典型例子。
传统软件开发
我们对产品定义的大部分直觉和方法来自传统的软件开发。在理想的情况下,构建软件产品包括以下步骤:从关于消费者行为的业务假设开始,从假设中导出规范,根据规范构建软件,测试软件是否符合规范,在生产中部署软件,以及确定假设的有效性。
一个电子商务网站的商业假设的例子可能是“如果我们实现一次点击结账过程,那么这将导致更高的转化率”。商业假设是对商业直觉的编纂,这可能是由大量的市场研究提供的。然而,一旦一个假设被公式化,它的前提(如果和那么之间的部分)的范围通常是非常狭窄和简单的。
产品规格只不过是满足商业假设前提的必要和充分条件的表示。对于上述假设,相应的规范可以是一键结账流程的线框。注意,我们可以明确地从假设中推导出规格说明。根据规范构建软件是一件复杂的事情。然而,一旦构建完成,检查它是否满足规范是相对简单的。该规范为构建和测试软件提供了充分的基础。
规范和测试之间的联系尤其重要。为了测试的目的,一个软件被视为一个给定输入产生输出的系统。传统的软件测试依赖于一个完整的、独立的测试预言的存在,即枚举所有可能的输入并为每个输入生成预期输出的方法,独立于软件本身。鉴于此,测试的目标是“简单地”验证软件是否为每个输入产生正确的输出。测试预言来自规范,而规范又来自假设的前提。因此,(前提)假设的简单性和狭隘性在传统软件开发的可行性中起着决定性的作用。
在传统的软件开发中,开发团队的目标是通过根据业务直觉构建软件来为业务产生价值。业务假设和产品规范一起构成了业务和软件之间的重要桥梁,也是每个人交互的共同基础。因此,假设和规范需要以产品经理、软件开发人员和测试人员可以理解的方式编写。
在传统的做事方式(即瀑布)中,不同的步骤(如假设生成或规范)是为整个产品顺序执行的。每个步骤都由不同的专家小组执行,并在不同步骤之间进行详细交接。事实证明这是一种相当低效的做事方式。因此,在更现代的敏捷/精益方法中,产品在短时间的迭代中被构建成小块。名义上,整个团队参与执行每个切片的所有步骤。典型地,假设和规范被编纂在一个用户故事或一个近亲中。
学术科学计算
另一端是在物理学和相关领域常见的高性能科学计算。例子包括预测亚原子粒子行为的晶格量子色动力学,以及许多学科中的计算流体动力学。在科学计算中,编写一个软件来寻找某个问题的(通常是近似的)答案。
科学计算很少考虑到上面提到的假设/规范分裂。考虑晶格量子色动力学的例子。这里的基本假设是“如果我们用量子色动力学理论来计算物理量,那么它们将非常接近我们从实验中得到的结果”。构建一个软件来测试这一假设的规范可能包括量子色动力学方程和“构建一个软件来根据这些方程计算物理量”的戒律。这实际上是对晶格量子色动力学的合理描述,但作为规范并不好,因为它对我们测试软件没有帮助。
使用不同技术的组合来执行科学计算的测试:精确可解的情况(可能有一些输入的输出可以使用替代方法精确计算),限制条件(通常结果在某些限制下容易计算,例如输入趋向于零或无穷大),以及试探法(给定以前的经验,输出是否“有意义”)。与商业软件测试相比,科学计算中的测试覆盖率,即测试中包含的(输入,输出)对的比例,通常要低得多。此外,测试方法需要对领域有非常深刻的理解。通常,这不是一个问题,因为软件的构建和测试通常是由科学家完成的,而他们恰好也是领域专家。
一般来说,科学计算中的假设和软件之间没有明确的解耦。这导致了规范的概念没有多大用处。因此,完整而独立的测试预言是不存在的:软件是根据输入(问题)来计算输出(答案)的。如果我们有另一种计算答案的方法,那么我们就不需要首先编写软件了!
人工智能产品
就其核心而言,人工智能软件开发非常类似于学术科学计算,因为假设与软件紧密耦合,导致不存在测试预言。然而,基于人工智能的商业产品的构建方式与传统软件开发非常相似;受商业直觉的驱使。此外,基于人工智能的产品往往是在看起来非常类似于传统软件开发团队的团队中开发的,只是增加了一个或多个数据科学家。其核心性质和开发方法之间的这种阻抗使得产品定义对于基于人工智能的产品来说非常具有挑战性。
具体来说,让我们考虑一个电子商务网站推荐系统的典型例子。基于商业直觉的一个可能的假设可能是“如果向客户展示相关产品,那么转换率将会增加”。这个几乎显而易见的假设抓住了建立推荐系统背后的基本动机。此外,它的优点是任何参与构建电子商务软件的人都容易理解。它也足够广泛,可以支持非常强大的人工智能算法的开发。
但是,从定义产品的角度来看,这个假设并不好。不可能从中得出明确的规范。问题在于“相关”一词的模糊性——在这种情况下什么是相关的?当涉及到派生产品规格,以及构建和测试软件时,它并不是非常有用。
那么这给我们留下了什么?在我们继续深入之前,让我们试着去理解构建一个商业假设所涉及的不同维度。我认为,我们需要考虑两个主要的相关方面。
第一个维度是假设的一般性。传统的软件开发基于这样一种假设,即可以将市场研究和商业直觉提取到一组狭窄但有用的假设中,然后用这些假设来构建软件。另一方面,基于人工智能的算法的全部力量来自于能够从非常一般的假设出发。考虑前面提到的推荐系统的情况。我们可以将假设缩小到“如果我们向试图购买尿布的男性用户展示啤酒,那么这将增加篮子的大小。”显然,在这种情况下,我们将能够从中导出精确的规范,并构建软件来支持它。在这种情况下,恭喜你,你刚刚建立了你的第一个基于规则的系统!如果我们要利用人工智能的力量,那么这种狭隘的假设不是答案。
第二个维度是假设的可理解性。这种可理解性是关于普通产品开发团队的所有成员都知道的公共词汇。考虑假设“给定一个上下文(由用户的历史、用户的特征、产品目录定义),以及在具有相似上下文的历史数据上训练的两个算法,其中相似性按照*,如果基于来自具有较高分数的算法的推荐来显示产品,那么这将导致较高的尽管上面的假设对于支持算法开发来说是足够通用的,但是在目前,对于产品开发中的非数据科学家来说,它几乎是不可理解的。*
我们需要记住另一个重要的约束。真正面向业务的数据科学人才稀缺。因此,在谷歌和脸书这样的巨头之外,基于人工智能的产品将继续被开发,至少在不久的将来,在数据科学家、商业分析师、软件开发人员和软件测试人员的多样化团队中,他们充其量对彼此的领域有着肤浅的了解。
鉴于上述限制,我们不能完全牺牲可理解性。另一方面,如果我们要利用人工智能的力量,那么我们也不能完全牺牲通用性。然而,这里要注意的重要一点是,在大多数情况下,没有必要开发“最好的”或最强大的算法。相反,我们需要的是开发一个“足够好”的解决方案。然而,当你在构建一个新的东西时,通常不可能计算出达到“足够好”阶段所涉及的工作量(根据工时),也就是说,你不能用时间框来确定一个可行的解决方案!
事实上,足够好的界限可以也应该根据商业现实来设定。缺少的是常用词汇。为了理解共享词汇的重要性,让我们考虑一下科学研究的例子,特别是科学方法。通过敏捷和精益运动,科学方法已经在软件开发社区中得到推广。很大程度上没有强调的是,在一个学科中拥有一个通用词汇对于科学方法起作用的重要性。典型的科学方法包括试图通过建立一个假设来理解一个现象,从它构建一个理论,运行模拟和实验来验证它。这些步骤中的每一步通常由不同的科学家小组执行,他们可能不深入了解彼此的工作。然而,他们详细了解的是每一部作品中的主张和结果。这是可能的,因为它们共享一个词汇表。在物理学中,这个词汇通常是建立在数学之上的。在化学方面,除了数学和化学反应的语言。其他科学学科也是如此。
我们当前的软件开发词汇很大程度上是由 web 开发设定的。这种主要由线框构成的词汇在构思基于人工智能的产品时完全没有用,可能应该是第一个需要扔出窗外的东西。
与物理学一样,人工智能的常用词汇也建立在数学之上,更重要的元素是概率论和统计、线性代数和优化原理。人工智能产品开发的词汇表必须由上述的“用户友好”子集组成。例如,一个人能够创建和解释一个线框,而不需要理解 API 调用是如何进行的,或者市场研究是如何完成的。人工智能的“线框”相当于什么?我认为一个好的起点是描述性统计,即业务假设和产品规格至少需要使用描述性统计的词汇来编写。
在人工智能时代,另一个需要受到挑战的公认观点是,市场研究和软件开发是完全不同和分离的学科,软件的目标是提供一种验证商业假设的方法,而不是提供信息。对于基于人工智能的软件来说,这个假设显然是错误的。由于基于人工智能的软件中假设和软件之间的紧密耦合,几乎不可能将学习(或探索)和实践(或利用)阶段分开。有鉴于此,重要的是不仅要把人工智能作为验证商业直觉的工具,还要把它作为建立商业直觉的工具。
事实上,一旦一个人有了足够的知识,相关的动作要么可以直接导出,要么可以经常使用现成的人工智能算法来计算出相关的动作。因此,人工智能产品假说的主要焦点可能应该是学习,而不一定是做。而什么是需要学习的信息也应该由 AI 来告知。
与任何新的范式转换技术一样,业务流程需要一段时间才能跟上。AI 也不例外。从长远来看,我相信在更广泛的产品开发社区中对人工智能的基本理解是解决方案。然而,从短期来看,我们不能指望产品经理一夜之间成为数据科学家。然而,我们可以期待他们成为数据素养。另一方面,我们应该期待数据科学家从他们的算法中抬起头来,理解企业价值创造的基础。
产品发布公告:Mateverse 高级— V 1.0
让你在 5 分钟内训练 ML 模型,并将机器学习引入 IFTTT 的产品变得更加先进。
S 我们中的一些人已经在我们的业务中实现了机器学习,还有一些人仍在考虑使用它。统计数据预测,到 2021 年,人工智能的使用将大幅增加。许多人反复写了人工智能技术将如何变革的主题,并将人工智能称为第三次工业革命。我们不打算深入探讨这个问题,但让我们来看看 Mateverse 是如何出现的。
TL;博士对人工智能在社会中的巨大影响的故事是:机器学习正在渗透到每一个其他商业组织。因此,这使得他们的流程(内部和外部)变得非常简单。
从大公司开始,以满足独特客户需求的多种销售转换达到顶峰,开始进入较小的组织。诸如分析、销售台、用户界面等领域在小公司中经历了巨大的转变。现在,消息比以往传播得更快。
Source: McKinsey Global Institute
坦率地说,除了成本之外,没有什么能阻止较小的组织实现较大的组织所能实现的。**这种昂贵的事情对较小的组织来说是一种折磨。**很快,通过开源算法和预训练的人工智能模型的可用性,人工智能及其重要的对等物机器学习变得可以访问。
另一个没有被很多人注意到的事实是当如此猖獗的适应在世界各地的公司中发生的时候,猜猜谁是 ML 项目出问题的首当其冲者?他们是分析师和数据科学家,他们独自承担推动分析的任务,几乎没有其他部门的帮助。有很多数据科学家跳槽或从事非常不满意的工作的案例,要么是因为他们没有机会做他们力所能及的事情,要么是因为他们被迫在基础设施不足的情况下完成喜马拉雅山的任务。
我们真的不能责怪任何人,考虑到人工智能和人工智能是非常新的技术,试图摆脱他们周围的炒作和恐惧。
我们在 Mate Labs 开始构建我们的产品——**Mate verse,**在确定和了解所有的基础上好吧,行业的斗争已经在我们之前尝试过的各种项目中进行。当我们一段时间以来试图为机器学习中涉及的巨大而平凡的过程找到一个可靠的解决方案时, Mateverse V1.0 终于问世了。点燃…时代…与世界上的科技公司斗争,并在一个致力于帮助我们将人工智能带给大众的社区中寻找意愿。
斗争(勇气)是真实的。
在用 Mateverse beta 版本测试了这个想法之后,我们从大型跨国公司背后的小型企业和分析师那里得到了压倒性的回应,这些小型企业和分析师以前不知道 ML 如何帮助他们的业务,或者没有太多的发挥空间。mate verse 无需为建模编写一行代码,使公司部署预测模型变得简单了数倍,并为他们的业务带来了加速的影响。
回到阻碍企业实施 ML 的因素,我们将把这些点联系起来,并与您讨论如何和*,其中* Mateverse 是一个成本削减者,也是一个“努力削减者”。
也许,带你了解 Mateverse 如何削减成本和精力的最佳方式是通过机器学习的步骤。让我们举一个构建预测分析模型的最佳例子
虽然自动化机器学习中的当前解决方案看起来如下:
获取数据— ->完美的预测
绝对不是那样的。
惹恼数据科学家的最好方法是假设手头有一些数据就太容易了。更糟糕的是,不完整和不一致的数据永远无法完成一个项目。
尽管如此,我们还是有办法让数据科学家更容易更快地部署模型,我的意思是,快得多。
为了部署预测模型(举个最好的例子),所涉及的步骤可以总结如下:
- 数据收集
在数据收集阶段,Mateverse 支持所有常见类型的数据库 HDFS/RDBMS/NoSQL,或者你可以只上传一个 CSV 文件,数据库就创建好了。就这么简单。
Image 1 — Mateverse Workflow chart
2。数据准备
数据准备从连接数据库中的多个表开始。这需要使用 SQL 脚本的技能,这是一项有点乏味的任务。现在, Mateverse 为用户提供了一个图形界面来做这件事。表连接功能允许最终用户以 7 种不同的方式创建混合数据集。
此外,在大多数情况下,一个数据分析师/科学家团队处理一个数据集,由于数据集的数量和大小,他们会将其划分为子集。然而,多人同步处理同一个数据集以前从未得到过支持。现在,通过 Mateverse 的 pro-collaboration 平台,团队管理员可以分配/委派职责,每个成员可以同时处理同一个数据集,同时保持对团队其他成员所做编辑的更新。
3。数据清理
数据清理的经典方法包括分析师和数据科学家在多个步骤之间周旋,同时专注于几个点。收集的数据并不总是完美的形式。事实上,从来都不是。假设从零售商店收集数据,可能会有一些丢失的值未能在系统中注册,或者以难以检索的格式存储。如果没有丢失数据,也可能有不适合、不相关或不可用的数据。数据也可能被混淆、歪曲和归类到错误的部分。如果听这个很难,处理这些错误是数据人员一直在努力的事情。因此,当数据科学家被期望在一夜之间转变数据时,难怪他们会感到沮丧。
Mateverse V1.0 — Automated Data Cleaning
从技术角度来说,一些数据清理方法是—缺失值处理、数据标记化和异常值检测。
Mateverse 已经把这个变成了一键式流程。你怎么问?我们已经建立了一个智能系统,它已经在成千上万的数据集上进行了准确的训练。
Mateverse V1.0 — Manual Data Cleaning
4。数据格式化
数据处理的这一部分是数据科学家仔细研究的又一套乏味的方法。这是数据科学家确保被清理的数据中没有错误,然后对其应用转换的地方。理解收集的数据是机器学习的主要工作人工。除非这部分数据准备能够得出准确的预测,否则机器的学习可能会犯下严重的错误。
一组规则指导这一阶段的数据准备。这些规则/方法包括:分类、聚类、回归和排序。再次以零售业为例,这些规则集可以帮助机器学习给定数据之间的关系。明显的分类,像性别或者年龄*,或者不那么明显的聚类,像消费习惯,财务能力等等。只有过了这个阶段,数据科学家才能松一口气,因为她/他的大部分工作已经完成。*
Mateverse 将消除流程中涉及的过多人工工作,并让专家们花费大量时间来试验不同类型的模型。
Image 2 — Comparison- Mateverse vs other automated ML platforms
既然我们已经建立了近乎完美的数据集,下一步就是训练一个预测模型。这涉及到两个步骤:
5。算法选择
机器学习的核心在于选择合适的算法。算法的作用是从准备好的数据中做出解释。特定算法的选择取决于最终模型的预期功能。这些算法从统计算法到基于树的算法,再到贝叶斯算法。事实上,有无数种可能的算法。
数据科学家对数百种算法进行实验,以最终选择能够获得最佳结果的算法。
6。超参数优化/模型训练
根据模型试图解决的特定问题,在模型上使用超参数调整。超参数调整可创建最佳预测模型。这是一个复杂的过程,优化机器学习的这一部分是一项艰巨的任务。
Mateverse V1.0 — Automated Machine Learning
Mateverse 通过模仿数据科学家处理问题的方式,使前面提到的步骤成为一键操作的过程,反过来优化数据科学家的工作,就像她的助理 T21 一样。
7。可视化效果
你会发现数据分析师对他们的可视化很挑剔,这并不罕见,因为正确和适当的可视化会给数据带来价值和清晰度。我们在 Mateverse 中支持超过四打可视化图表。
Mateverse has in-built support for an array of visualization charts, some of which are shown here.
8。部署
Mateverse 允许在数据流上部署模型,预测是实时的,并且在现场*。你可以部署在 Mateverse 的仪表盘上进行实时更新,也可以使用 API 将其集成到自己的产品中。*
如果你认为这个平台对你有帮助,请在这里告诉我们。
关于
在 Mate Labs 我们已经构建了 Mateverse ,一个机器学习平台,在这里你可以在几分钟 s 内构建定制的 ML 模型,而无需编写一行代码*。我们的平台让每个人都能轻松构建和训练机器学习模型,无需编写一行代码。欢迎致电mate @ mate labs . in联系我们***
让我们携起手来。
在 Twitter 上与我们分享你的想法。
如果你有新的建议,请告诉我们。我们的耳朵和眼睛总是为真正令人兴奋的事情而张开。
生产数据科学
面向生产的协作数据科学工作流
去年,在萨塔利亚,我正在进行一个合作数据科学项目。项目进展顺利,但是我和我的合作者忽略了好的实践,当探索和建模数据时,我们没有记住我们最终是在构建一个产品。当我们自动化生产我们的最佳模型时,这些疏忽在工作接近尾声时浮出水面。
在我们完成这个项目后,我寻找现有的方法来开展协作数据科学,并在脑海中留下一个最终产品。我只能找到一些关于这个主题的资源,而且我找到的资源只集中在特定的领域,比如数据科学的测试。此外,在与数据科学学生交谈时,我了解到他们也没有学习良好的编码实践或与其他人合作的有效方法。
我从查看可以轻松应用于数据科学的软件开发实践开始。最直接的选择是使用 Python 虚拟环境来确保工作的可重复性,使用 Git 和 Python 打包工具来简化软件的安装和贡献过程。尽管我知道这些实践和工具,但通过遵循在线数据科学教程,我养成了只分享 Jupyter 笔记本的习惯。 Jupyter 笔记本适用于独立的探索性分析,但仅靠笔记本不足以创造产品。然而,我不想放弃笔记本,因为它们是一个很好的工具,提供了一个交互式的非线性平台,适合探索性分析。那时,我一方面有探索性分析,另一方面有生产化,我想把它们结合在一个简单的工作流程中。
敏捷软件开发中的一个通用工作流交替进行新特性的开发和重构。这个循环允许包含满足当前用户需求的新特性,同时保持代码库的精简和稳定。在数据科学中,为用户开发新功能被通过数据探索寻找洞察力所取代。这一观察引出了生产数据科学工作流的中心主题:探索-重构循环。
如上图所示,探索-重构循环交替进行探索和重构。探索通过分析增加了新的洞察力,从而增加了项目的复杂性。重构通过将部分分析整理到产品代码库中来降低复杂性。换句话说,生产代码库是用于获得洞察力的代码的一个提炼版本。最重要的是,洞察力部分来自代码,主要来自演绎推理。数据科学家使用代码,就像夏洛克·福尔摩斯使用化学来为他的推理路线获取证据一样。
Jupyter notebooks 允许我们使用格式化文本叙述我们的推论,并在同一文档中编写支持代码。然而,文本解释通常不被重视,并且被冗长的代码所掩盖。因此,在数据科学中,重构应该包括代码和基于文本的推理。将来自 Jupyter 笔记本的代码重构为 Python 包将演绎推理变成了笔记本的主角。在代码的支持下,笔记本变成了一块画布,通过使用文本来证明关于数据的一个观点。这类似于文化编程,其中文本被用来解释和证明代码本身。在这种观点下,所有的细节都被剥离,笔记本是文本和代码的结合。
同样,在中,定量信息的视觉显示, Tufte 将信息图形定义为数据墨水和非数据墨水的组合。数据墨水是代表数据的墨水量,非数据墨水代表其余部分。因为承载信息的是数据墨水,所以数据墨水应该是信息图形的主角。当非数据墨水抢镜时,信息稀释了无信息内容。Tufte 建议通过合理地最大化数据墨水和最小化非数据墨水来改善信息图形。同样,当把笔记本看作推理的手段时,文字应该是主角;文本不应被代码遮蔽。这导致了重构笔记本的一个简单规则:文本重于代码。
我在软件开发中遇到过类似的想法:功能是资产,代码是负债。换句话说,功能是软件应该提供的,同时保持一个小的代码库,因为代码库越大,维护成本越高,出现错误的几率也就越大。数据墨水优于非数据墨水、文本优于代码、功能优于代码的共同点是,在工作中要考虑到与他人的合作,也就是说,要关心人们在工作中的体验。
类似地, Python 、吉多·范·罗苏姆的创造者指出代码被读取的次数比它被编写的次数多得多。的确, Python 的设计强调可读性。忽略可读性,我们可以通过不清理代码来节省一个小时,而每个合作者可能会损失两个小时来理解它。如果我们与三个人合作,节省了一个小时,六个小时可能会浪费在挫折中。所以,如果每个人都这样做,每个人都输了。相反,如果每个人都与他人一起工作,那么每个人都是赢家。此外,当谈到其他人时,我不仅指我们的合作者,也指我们未来的自己。原因是,几个月后我们很可能会忘记我们现在正在做的事情的细节,我们将处于与我们的合作者相似的地位。出于这些原因,以下原则在整个生产数据科学工作流程中设定了主题:让其他人和你未来自己的生活更轻松。
放松他人的生活和探索-重构循环是生产数据科学工作流的本质。在这个工作流程中,我们从建立一个项目开始,这个项目的结构强调协作,协调勘探和生产。有了这个结构,我们进入探索-重构循环的第一阶段:探索。在这里,我们使用 Jupyter 笔记本来分析数据,形成假设,测试它们,并使用获得的知识来建立预测模型。一旦我们完成了一个分析,我们在文本代码规则的指导下重构笔记本的主要部分。代码从笔记本流向生产代码库,推理线成为笔记本的主角。探索和重构然后迭代直到我们到达最终产品。
点击了解生产数据科学工作流程。
使用自定义 IPython 扩展进行富有成效的研究
在过去的一年里,我对数据科学和机器学习越来越感兴趣。在这样做的时候,我注意到每次我想进行一些研究时,我都必须在 IPython 和 Jupyter notebook 中执行相同的重复任务,这使我脱离了心流。为了解决这个问题,我构建了一些定制的 IPython 扩展,极大地提高了我的工作效率。我想和你们分享这些扩展,我是如何构建它们的,以及我如何在日常研究中使用它们。扩展的示例代码可以在下面找到。此外,在这篇文章的第二部分中,我还谈到了我是如何将 BigQuery 支持直接构建到 IPython 中的。
作为深入研究数据科学和机器学习的必然副作用,我一直在写大量的 Python,我真的很喜欢。Python 实际上是数据科学的通用语。这产生了一个令人难以置信的工具和技术生态系统。我特别喜欢用 Jupyter 笔记本在 IPython 、尤其是内部做研究分析。说到快速原型和探索,Jupyter 是一个梦想。它允许我以一种简单、直观的方式快速尝试想法。这也迫使我记录下我是如何找到一个问题的最终解决方案的,这在重新整理一些我很久没看的旧工作时非常有用。
当我第一次启动 iPython/Jupyter 时,我几乎总是预先导入相同的模块:
如果您从事大量的数据科学工作,这应该是您非常熟悉的前奏。如果没有,这些是使用 python 进行研究和分析时使用的一些核心数据处理和可视化库。
在将完全相同的样板文件输入 20 个笔记本后,我开始寻找将这些导入文件自动放入我的环境的方法。
输入自定义 IPython 扩展。扩展允许您连接到您的 IPython 环境,并根据您的需要修改它。这正是我要找的🙏🏻。我首先制作了自己的自定义扩展,将所有这些库导入到研究环境中,并配置了 matplotlib。
首先,如果你想知道: InteractiveShell
业务是关于什么的,那是 Python 的类型提示语法的一部分。我已经习惯了使用这种语法,因为当它与 VSCode 的 Python 扩展一起使用时,它提供了很好的开发人员工效学,这是我的首选 Python 开发环境。load_ipython_extension
基本上是 ipython 扩展的main()
函数;当一个扩展最初通过%[re]load_ext
被加载时,它被调用,并用于引导扩展,以及“注册魔法”(稍后将详细介绍!).上面,我使用 enable_matplotlib() 以及 push() 方法来代替必须手写这个前奏。
一旦我有了扩展的框架,我就写了一个简单的setup.py
脚本,用来符号化扩展,这样我就可以从任何笔记本上加载它。在运行设置脚本之前,我添加了install_requires
作为对我是否处于正确环境的健康检查。
这几乎是我开始工作所需要的全部。一旦我运行了python setup.py develop
,我就可以在任何笔记本或 IPython shell 上使用我的扩展了!
注意,我在那里使用了 *reload_ext*
,这样,如果我重新运行该命令,它仍然会工作(因为 *reload_ext*
是幂等的)。
我只需要这一行就可以加载我想使用的所有库。随着时间的推移,这种按键的节省真的对我很有帮助。此外,通常当我在命令行上打开 IPython 时,这是因为我有一个想快速尝试的想法。在加载时拥有我需要的所有库使我保持流畅,而不必记住(或复制/粘贴)样板文件。
继续阅读这篇博文的第 2 部分,看看如何使用✨cell magic✨直接从 IPython 查询 BigQuery 。
使用定制 IPython 扩展进行富有成效的研究,第 2 部分:BigQuery 魔术
在完成了用于导入数据科学库的自定义 IPython 自动加载器扩展之后,我试图为自己节省更多的时间。我想通过从 IPython 查询 BigQuery 直接访问我的数据仓库中的数据。这篇博文描述了我解决这个问题的方法。我在底部添加了一个“附录”,展示了使用我的扩展对 BigQuery HackerNews 数据集进行的一些示例分析。
然而,我应该指出,BigQuery Python 客户端实际上内置了 IPython 支持。我在不知道这一点的情况下构建了我的扩展,但我仍然发现这个练习很有用,因为它揭开了 IPython 扩展的神秘面纱。
我使用 Google 的 BigQuery 作为我的首选数据仓库;它非常健壮,速度非常快,易于使用,而且性价比超高。大多数时候,我发现自己在查询 BigQuery,并使用 BigQuery 的 python 客户端库将结果加载到 dataframe 中。如果我可以在 IPython 单元格中键入一个 SQL 查询,并让单元格在 BigQuery 上执行该 SQL 并将结果存储在 DataFrame 中,这不是很棒吗?我希望能够做这样的事情:
事实证明,通过使用单元格魔术,在 IPython 中将 BigQuery 的 SQL 直接嵌入笔记本单元格是可能的。单元格魔术是那些看起来像%%this
的命令,它读取整个单元格的内容并调用注册的魔术函数,这两个位置参数line
和cell.``line
包含用于调用单元格魔术的行的字符串,例如%%bq
行。cell
参数也是一个包含单元格其余内容的字符串,不包括行。
如果我们以上面的例子为例,魔术函数bq
将被调用,其中"--name hn_daily_comment_counts"
作为line
参数,而"SELECT\n...\nday ASC;"
——或者初始行之后的剩余单元格的内容——作为cell
参数。
我们可以将 BigQuery python 客户端与 cell magic API 一起使用,让 magic 函数查询 BigQuery 并返回结果。
正如你在上面看到的,我在一个ResearchEnvMagics
类中包含了我所有的魔法(在这个例子中只有一个)。重要的是,这个类继承自 IPython 的 Magics 类,并且附加了@magics_class
装饰器。
我还使用了 IPython 的 magic_arguments 包,以便允许向我的 cell magic 传递额外的配置参数,类似于您在命令行上使用的。这是 IPython magics 的一个常见模式,因此他们为它提供了一个内置的包,这太棒了!
这里的最后一步是通过扩展加载钩子向 IPython 注册这些 magics:
这就是全部了!现在,magic 功能已注册,可以在 Jupyter 笔记本中使用,轻松进行研究并获得见解。
当然,在构建了这个 BigQuery magic 之后,有一天晚上我通过挖掘客户端库 API 文档发现它已经随 IPython magics 一起发布了😑。我希望在某个地方已经记录了这一点*,但是我仍然喜欢构建它,并且在 IPython 中学到了很多关于细胞魔法的知识。下一步,我想弄清楚如何为 BigQuery 单元格魔术添加 SQL 语法突出显示。*
我希望您觉得这很有用,如果您在研究环境中使用特殊的定制 IPython magics,请在评论中告诉我!愿意分享信息和建议。请查看下面的内容,了解 BigQuery 的 HackerNews 数据集中一些示例查询的扩展。
Simple example using BigQuery to display daily comment counts.
A more advanced example looking at comment “shocks” by taking the weekly moving average and dividing it by the weekly moving standard deviation.
Cleaning, annotating, and charting the data from the previous query. Note that I used scale() above while I was examining the data in order to de-mean it. Apparently, a post on dealing with alienation was a huge driver of comments on HackerNews around the 2008–2010 time. Very poignant, and probably deserves an article unto itself.
用数据流生产 ML 模型
Source (PublicDomainPicture): https://pixabay.com/en/baby-boy-child-childhood-computer-84627/
在我的数据科学职业生涯中,我面临的一个关键挑战是将探索性分析的发现转化为可扩展的模型,为产品提供动力。在游戏行业,我建立了几个预测模型来识别玩家流失,但将这些模型投入生产总是很困难。我曾经写过 Twitch 上用于生产模型的一些流程,但是每个产品团队都需要独特的方法和不同的基础设施。
在意外收获,我们授权我们的数据科学团队拥有产品化模型的过程。我们没有依赖工程团队将模型规范转化为生产系统,而是为我们的数据科学家提供缩放模型所需的工具。为了实现这一点,我们使用预测模型标记语言( PMML )和谷歌的云数据流。以下是我们在意外收获构建和部署模型的工作流程:
- 模型是用 R 或 Python 离线训练的
- 训练有素的模型被翻译到 PMML
- 数据流作业接收用于生产的 PMML 模型
这种方法使数据科学家能够在本地使用采样数据集来训练模型,然后在我们的整个数据集上使用结果模型规范。步骤 3 可能需要工程团队的一些初始支持,但只需要设置一次。使用这种方法意味着我们的数据科学团队可以使用 PMML 支持的任何预测模型,利用托管数据流服务意味着团队无需担心维护基础架构。
本教程介绍了使用 Java SDK for Cloud Dataflow 从 R 中训练的离线模型转换为产品化模型的步骤。本教程中的所有代码都可以在我的 github 档案中找到。我们使用可用于 BigQuery 的出生率公共数据集,并训练一个线性回归模型来基于许多因素预测婴儿出生体重。数据流作业从公共数据集中读取记录,将训练好的回归模型应用于每条记录,并将结果写入我们的 BigQuery 项目中的一个表。这是我们的数据科学团队在为客户构建定制模型时采用的工作流,例如使用随机森林模型进行线索评分。
我们需要做的第一件事是熟悉出生率数据集,它记录了 1969 年至 2008 年间美国的出生人数。本中的帖子提供了关于该数据集的更多详细信息。我们使用 BigQuery web 接口编写一个查询来对数据集进行采样。该查询为每次出生提取以下属性:
- **年份:**出生的年份
- **复数:**分娩的孩子数
- apgar_5min: 新生儿出生 5 分钟后的健康评分
- **母亲 _ 年龄:**母亲的年龄
- **父亲 _ 年龄:**父亲的年龄
- **妊娠周数:**进入妊娠的周数
- 这位母亲生了几个孩子
- 母亲已婚:孩子出生时,母亲已婚吗?
- 体重 _ 磅:婴儿的体重(我们预测的)
为了在 R 中处理这个数据集,我们使用了优秀的 bigrquery 库,这使得将 BigQuery 结果读入数据帧变得很容易。我们提取一个样本数据集如下:
**library**(bigrquery)
project <- "gcp_project_id"sql <- "
SELECT year, plurality, apgar_5min, mother_age, father_age,
gestation_weeks, ever_born, mother_married, weight_pounds
FROM `bigquery-public-data.samples.natality`
order by rand()
LIMIT 10000
"df <- query_exec(sql, project = project, use_legacy_sql = **FALSE**)
然后,我们可以对数据集进行各种操作,如summary(df)
和hist(df$df$weight_pounds)
,这将生成下面的图表,显示婴儿体重在采样数据集中的分布。
Distribution of birth weights in the sampled data set.
接下来,我们训练一个线性回归模型来预测出生体重,并计算误差指标:
lm <- lm(weight_pounds ~ ., data = df)
summary(lm)cor(df$weight_pounds, predict(lm, df))
mean(abs(df$weight_pounds - predict(lm, df))) sqrt(mean(abs(df$weight_pounds - predict(lm, df)^2)))
这会产生以下结果:
- 相关系数:0.335
- 平均误差:0.928
- RMSE: 6.825
模型性能相当弱,可以探索其他算法和功能来改进它。由于这篇文章的目标是专注于将模型产品化,因此经过训练的模型就足够了。用于训练模型的完整笔记本可在这里获得。
翻译成 PMML 下一步就是把训练好的模型翻译成 PMML。 r2pmml R 包和 jpmml-r 工具使这一过程变得简单,并支持各种不同的算法。第一个库将 R 模型对象直接转换成 PMML 文件,而第二个库需要将模型对象保存到 RDS 文件,然后运行命令行工具。我们使用第一个库直接进行翻译:
**library**(r2pmml)
r2pmml(lm, "natality.pmml")
这段代码生成下面的 pmml 文件。PMML 文件格式指定用于模型的数据字段、要执行的计算类型(回归)以及模型的结构。在这种情况下,模型的结构是一组系数,定义如下:
<RegressionTable intercept="7.5619">
<NumericPredictor name="year" coefficient="3.6683E-4"/>
<NumericPredictor name="plurality" coefficient="-2.0459"/>
<NumericPredictor name="apgar_5min" coefficient="9.4773E-5"/>
...
<NumericPredictor name="mother_married" coefficient="0.2784"/>
</RegressionTable>
我们现在有了一个模型规范,可以将其产品化并应用于我们的整个数据集。
使用云数据流进行产品化 使用 Dataflow Java SDK 时,您可以定义一个要在一组对象上执行的操作图,服务将根据需要自动配置硬件进行扩展。在这种情况下,我们的图是一组三个操作:从 BigQuery 读取数据,计算每条记录的模型预测,并将结果写回 BigQuery。本教程生成以下数据流 DAG:
The Dataflow graph of operations used in this tutorial.
我们使用 IntelliJ IDEA 来创作和部署数据流作业。虽然设置 Java 环境超出了本教程的范围,但是用于构建项目的 pom 文件可以在这里获得。它包括对数据流 sdk 和 JPMML 库的以下依赖关系:
<dependency>
<groupId>com.google.cloud.dataflow</groupId>
<artifactId>google-cloud-dataflow-java-sdk-all</artifactId>
<version>2.2.0</version>
</dependency><dependency>
<groupId>org.jpmml</groupId>
<artifactId>pmml-evaluator</artifactId>
<version>1.3.9</version>
</dependency>
如上图所示,我们的数据流工作由三个步骤组成,我们将详细介绍这三个步骤。在讨论这些步骤之前,我们需要创建管道对象:
PmmlPipeline.Options options = PipelineOptionsFactory
.fromArgs(args).withValidation().as(PmmlPipeline.Options.class);
Pipeline pipeline = Pipeline.create(options);
我们创建一个管道对象,它定义了应用于对象集合的一组操作。在我们的例子中,管道正在对一组 TableRow 对象进行操作。我们将一个选项类作为输入传递给 pipeline 类,该类为数据流作业定义了一组运行时参数,例如用于运行作业的 GCP 临时位置。
管道中的第一步是从公共 BigQuery 数据集中读取数据。从这一步返回的对象是 TableRow 对象的一个p 集合。特征查询字符串定义要运行的查询,并且我们指定在运行查询时要使用标准 SQL。
private static final String featureQuery =
"SELECT year, plurality, apgar_5min ... weight_pounds\n" +
"FROM `bigquery-public-data.samples.natality`";pipeline.apply(BigQueryIO.read().fromQuery(featureQuery)
.usingStandardSql().withoutResultFlattening())
下一步是将模型预测应用于数据集中的每条记录。我们定义了一个 PTransform 来加载模型规范,然后应用一个 DoFn 在每个 TableRow 上执行模型计算。
.apply("PMML Application", new PTransform<PCollection<TableRow>,
PCollection<TableRow>>() {model = new RegressionModelEvaluator(PMMLUtil.unmarshal(
Resources.getResource("natality.pmml").openStream()));return input.apply("To Predictions", ParDo.of(
new DoFn<TableRow, TableRow>() {
@ProcessElement
public void processElement(ProcessContext c) throws Exception {
/* Apply Model */
}})))
应用模型代码段如下所示。它检索 TableRow 以创建估计值,为 pmml 对象创建输入字段的映射,使用模型估计出生体重,创建新的 TableRow 以存储出生的实际和预测体重,然后将此对象添加到此 DoFn 的输出中。总而言之,这个应用步骤加载模型,定义一个函数来转换输入集合中的每个记录,并创建预测对象的输出集合。
TableRow row = c.element();HashMap<FieldName, Double> inputs = new HashMap<>();
for (String key : row.keySet()) {
if (!key.equals("weight_pounds")) {
inputs.put(FieldName.create(key), Double
.parseDouble(row.get(key).toString()));
}
}Double estimate =(Double)model.evaluate(inputs)
.get(FieldName.create("weight_pounds"));TableRow prediction = new TableRow(); prediction.set("actual_weight", Double.parseDouble(
row.get("weight_pounds").toString())); prediction.set("predicted_weight", estimate);c.output(prediction);
最后一步是将结果写回 BigQuery。在本课的前面,我们定义了将记录写回 BigQuery 时要使用的模式。
List<TableFieldSchema> fields = new ArrayList<>();
fields.add(new TableFieldSchema()
.setName("actual_weight").setType("FLOAT64"));
fields.add(new TableFieldSchema()
.setName("predicted_weight").setType("FLOAT64"));
TableSchema schema = new TableSchema().setFields(fields);.apply(BigQueryIO.writeTableRows()
.to(String.format("%s:%s.%s", PROJECT_ID, dataset, table))
.withCreateDisposition(BigQueryIO.Write.CreateDisposition
.CREATE_IF_NEEDED).withSchema(schema));pipeline.run();
我们现在已经定义了一个管道,可以运行它来为整个数据集创建预测。这个类的完整代码清单可以在这里找到。运行这个类将启动一个数据流作业,该作业将生成上面显示的 DAG,并将提供许多 GCE 实例来完成该作业。下面是一个用于运行此管道的自动缩放示例:
Autoscaling the Model Predicting Task
当作业完成时,输出是 BigQuery 项目中的一个新表,它存储了出生率数据集中所有记录的预测和实际权重。如果我们想要运行一个新的模型,我们只需要在数据流作业中指向一个新的 PMML 文件。运行离线分析和数据流项目所需的所有文件都可以在 Github 上获得。
数据流是一个伟大的工具,使数据科学家能够将他们的模型产品化。它提供了一个可扩展到大型数据集的托管环境,并使数据科学团队能够拥有更多生产流程。