mirror of
https://github.com/cheetahlou/CategoryResourceRepost.git
synced 2025-11-16 22:23:45 +08:00
mod
This commit is contained in:
93
极客时间专栏/程序员的数学基础课/概率统计篇/19 | 概率和统计:编程为什么需要概率和统计?.md
Normal file
93
极客时间专栏/程序员的数学基础课/概率统计篇/19 | 概率和统计:编程为什么需要概率和统计?.md
Normal file
@@ -0,0 +1,93 @@
|
||||
<audio id="audio" title="19 | 概率和统计:编程为什么需要概率和统计?" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/32/12/323278c892e1300daff5a7dd8d2c9412.mp3"></audio>
|
||||
|
||||
你好,我是黄申。
|
||||
|
||||
通过第一个模块的学习,我想你对离散数学在编程领域中的应用,已经有了比较全面的认识。可以看出来,数据结构和基础算法体现的大多数都是离散数学的思想。这些思想更多的时候是给我们提供一种解决问题的思路,在具体指导我们解决问题的时候,我们还需要更多的数学知识。
|
||||
|
||||
比如说,在机器学习、数据挖掘等领域,概率统计就发挥着至关重要的作用。那关于概率统计,我们需要掌握哪些知识呢?这些知识究竟可以用在什么地方呢?第二模块的第一节,我们就来聊聊这些问题,让你对这一模块的学习做到心中有数。
|
||||
|
||||
## 概率和统计里有哪些需要掌握的概念?
|
||||
|
||||
在第一个模块中,我们认为所有事件都是一分为二的,要么必然发生,要么必然不发生。换句话说,事件的发生只有必然性,没有随机性。但是现实生活中,我们常常会碰到一些模棱两可的情况。
|
||||
|
||||
比如,你读到一则新闻,它报道了某个娱乐圈明星投资了一家互联网公司。那么,这则报道是属于娱乐新闻,还是科技新闻呢?你仔细读了读,觉得全篇大部分的内容都是讲述这家互联网企业的发展,而只有少部分的内容涉及了这位明星的私生活。你可能会说,这篇新闻80%的可能属于科技新闻,只有20%的可能属于娱乐新闻。这里面的数字表示了事件发生的可能性。**概率**(Probability)就是描述这种可能性的一个数值。
|
||||
|
||||
在概率的世界里,有很多概念。但是这几个非常基本的概念,你一定要知道。
|
||||
|
||||
我们用**随机变量**(Random Variable)来描述事件所有可能出现的状态,并使用**概率分布**(Probability Distribution)来描述每个状态出现的可能性。而随机变量又可以分为**离散型随机变量**(Discrete Random Variable)和**连续型随机变量**(Continuous Random Variable)。
|
||||
|
||||
这几个概念非常简单,但是其实也很抽象。我举个具体的例子,帮你加深印象。
|
||||
|
||||
假设我们使用一个随机变量x来表示新闻类型,如果在100篇新闻中,有60篇是娱乐新闻,有20篇是科技新闻,有20篇是体育新闻,那么你看到娱乐新闻的概率就是60%,看到科技新闻的概率就是20%,看到体育新闻的概率就是20%。而这三组数据就可以构成变量x的**概率分布**P(x)。
|
||||
|
||||
在这个概率分布中,我们只有一个随机变量x,现在我再添加另一个随机变量y,表示新闻属于国际的还是国内的。这个时候,新的概率分布就需要由x和y这两个变量联合起来才能决定,我们把这种概率称为**联合概率**(Joint Probability)。
|
||||
|
||||
比如说,刚才那100篇新闻中有30篇是国际新闻,而这30篇中有5篇是科技新闻,那么国际科技新闻的联合概率就是5/100=5%。不同的x和y取值的组合,就对应了不同的联合概率,我们用P(x, y)来表示。
|
||||
|
||||
对于离散型随机变量,通过联合概率P(x, y)在y上求和,就可以得到P(x),这个P(x)就是**边缘概率**(Marginal Probability)。对于连续型随机变量,我们可以通过联合概率P(x, y)在y上的积分,推导出边缘概率P(x)。边缘概率有啥用呢?有的时候,情况看起来很复杂,而我们其实只需要研究单个事件对概率分布的影响就可以了。这个时候,边缘概率可以帮助我们去除那些我们不需要关心的事件,把联合概率转换为非联合概率,例如从P(x, y)得到P(x),从而忽略y事件。
|
||||
|
||||
对于多个随机变量,还有一个很重要的概念是**条件概率**。我估计很多人可能搞不清楚这个概念。我还是举例子跟你说。比如说,我们现在假设100篇中有30篇是国际新闻,而这30篇中有5篇是科技新闻,那在国际新闻中出现科技新闻的概率是多少呢?
|
||||
|
||||
这时候,我们就需要条件概率了。也就是某个事件受其他事件影响之后出现的概率,放到咱们的例子里,在国际新闻中出现科技新闻的概率就是5/30=16.67%,在科技新闻中出现国际新闻的概率就是5/20=25%。
|
||||
|
||||
说了这么多,不知道你有没有一种感觉,**其实<strong><strong>概率论研究**</strong>的就是这些概率**<strong>之间相互转化的关系**</strong>,比如联合概率、条件概率和边缘概率</strong>。通过这些关系,概率论中产生了著名的**贝叶斯定理**(Bayes’ theorem)。加上变量的独立性,我们就可以构建**朴素贝叶斯(Naive Bayes)分类算法**,这个算法在机器学习中的应用非常广泛,我们后面也会有一节课专门来讲。
|
||||
|
||||
此外,基于概率发展而来的信息论,提出了很多重要的概率,例如**信息熵**(Entropy)/ **香农熵**(Shannon Entropy)、**信息增益**(Information Gain)、**基尼指数**(Gini)等。这些概念都被运用到了**决策树**(Decision Tree)的算法中。
|
||||
|
||||
提到概率论,就一定要提统计学。这是因为,**概率和统计****其实是互逆的。**怎么个互逆呢?概率论是对数据产生的过程进行建模,然后研究某种模型所产生的数据有什么特性。而统计学正好相反,它需要通过已知的数据,来推导产生这些数据的模型是怎样的。因此统计特别关注数据的各种分布、统计值及其对应的统计意义。
|
||||
|
||||
比如,现在有一大堆的新闻稿,我们想知道这里面有多少是娱乐新闻,有多少是科技新闻等等。我们可以先拿出一小部分采样数据,逐个来判断它属于哪个类型。比如说,分析了10篇之后,我们发现有7篇是科技新闻,2篇是娱乐新闻,1篇是体育新闻,那么从统计结果来看,三个类型的概率分别是70%、20%和10%。然后,我们根据从这个小采样得来的结论,推测出科技新闻、娱乐新闻和体育新闻所占的比例。这就是统计学要做的事情。
|
||||
|
||||
在真实的世界里,我们通常只能观测到一些数据,而无法事先知道,是什么模型产生了这些数据,这时候就要依赖统计学。所以,海量数据的分析、实验和机器学习,都离不开统计学。
|
||||
|
||||
## 概率和统计可以帮我们做什么?
|
||||
|
||||
弄清楚这些基本概念之后,我们来看看概率和统计的知识能帮我们做点什么。
|
||||
|
||||
首先,我还是要提到复杂度分析。你可能会奇怪,之前讨论的复杂度分析好像没有涉及到概率啊。这是因为,在计算平均复杂度的时候,我们其实做了一个假设:所有情况出现的概率都是一样的。
|
||||
|
||||
我以最简单的查找算法为例。假设一个数组包含了n个元素,我们对其中的元素采取逐个扫描的方式,来查找其中的某个元素。如果这个元素一定会被找到,那么最好时间复杂度是O(1),最差时间复杂度是O(n),平均时间复杂度是O((n+1)/2)。
|
||||
|
||||
等等,为什么平均复杂度是O((n+1)/2)呢?我们假设一共扫描了n次,第1次扫描了1个元素,第2次扫描了2个元素,一直到第n次扫描了n个元素,那么总共的扫描次数是(1+2+…+n) = ((n+1)*n)/2,然后除以n次,得到每次扫描的元素数量平均值是(n+1)/2,所以时间复杂度就是O((n+1)/2)。
|
||||
|
||||
我把上述求和式改写成下面这样:
|
||||
|
||||
如果1/n是每种情况发生的概率,那么平均的扫描次数就是,不同情况下扫描次数按照概率进行的加权平均。问题来了,为什么这n种情况发生的概率都是1/n呢?这是因为之前我们做了一个默认的假设,我们每种情况发生的概率是一样的。但在实际生活中,概率很可能不是均匀分布的。
|
||||
|
||||
比如说,一个网站要对它的用户发放优惠券,那我们就需要先找到这些用户。我们用一个长度为n的数组代表某个网站的用户列表。我们假设第一个注册用户ID是1,第二个注册用户的ID是2,以此类推,最近刚刚注册的用户ID为n。如果网站的发放策略是倾向于奖励新用户,那么被查找的用户ID有很大的概率会非常接近n,因此平均复杂度就会非常接近O(n)。相反,如果网站的发放策略是倾向于奖励老用户,那么搜索的用户ID有很大的概率是非常接近1的,因此平均复杂度会非常接近O(1)。
|
||||
|
||||
你可以看到,现实中每种情况出现的可能性是不一样的,这也就意味者概率分布其是不均匀的。而不均匀的概率分布,最终会影响平均复杂度的加权平均计算。因此,要想获得更加准确的复杂度分析结果,我们必须要学习概率知识。
|
||||
|
||||
除此之外,概率和统计对于机器学习和大数据分析而言更为重要。对于机器学习而言,统计的运用是显而易见的。机器学习中的监督式学习,就是通过训练样本,估计出模型的参数,最后使用训练得出的模型,对新的数据进行预测。通过训练样本来估计模型,我们可以交给统计来完成。在机器学习的特征工程步骤中,我们可以使用统计的正态分布,**标准化**(standardization)不同取值范围的特征,让它们具有可比性。
|
||||
|
||||
此外,对机器学习算法进行效果评估时,AB测试可以减少不同因素对评测结果的干扰。为了获得更可靠的结论,我们需要理解统计意义,并为每个AB测试计算相应的统计值。
|
||||
|
||||
最后,概率模型从理论上对某些机器学习算法提供了支持。朴素贝叶斯分类充分利用了贝叶斯定理,使用先验概率推导出后验概率,并通过变量之间相互独立的假设,把复杂的计算进行大幅的简化。简化之后,我们就可以把这个算法运用在海量文本的分类任务上。
|
||||
|
||||
而决策树使用了信息熵和信息增益,挑出最具有区分力的条件,构建决策树的结点和分支。这样构建出的树,不仅分类效率更高,而且更利于人脑的理解。谷歌的PageRank算法利用马尔科夫链的概率转移,有效地刻画了人们浏览互联网的行为,大幅提升了互联网搜索的体验。
|
||||
|
||||
## 学习这部分内容,需要做哪些准备?
|
||||
|
||||
听我说了这么多专栏的内容,你是不是有点担心,专栏的内容太深奥,不好理解。甚至在想,有没有必要做些准备?
|
||||
|
||||
学习不是件容易的事,因此进步的过程,从来不会轻松。努力需要你自己来,但是我也会从我的角度出发助力你的学习。我会争取讲清楚每个知识点背后的前因后果,以及不同知识点之间的联系,避免平铺直叙地罗列一堆理论和公式。但是,这部分内容,有公式是不可避免的,我尽量只保留那些最核心的公式。因此,即使你之前不太了解概率和统计,也没有关系。只有跟着我的节奏,搞懂每一节的重点,相信你很快就能领悟其中的精髓。
|
||||
|
||||
另外,我们无法脱离应用来讲知识,不然就本末倒置了。毕竟,我们学任何知识,都是为了用的。机器学习的知识纷繁复杂,涉及广泛,很多问题甚至是跨学科、跨领域的。不过,你不用担心,这里面会有太多看不懂的名词。我在讲解的时候,尽量给你抽象出最核心的部分,讲清楚来龙去脉,让你了解它整体的运作方式,不影响你对核心知识点的吸收。
|
||||
|
||||
当然,你可以适度地补一些概率知识,这样理解起来会更快。我在之前的[加餐三](https://time.geekbang.org/column/article/79048)中推荐了几本书,你可以找来看看,了解一些基本概念。另外,你可以准备一些实际工作和项目中的问题。例如,你之前参与的任务,哪些可以使用概率论来解决?碰到的难题有哪些?你是如何解决的?带着这些问题,再来看我的专栏,并且多在留言区写下你的疑问和收获,这样效果会更好。
|
||||
|
||||
## 小结
|
||||
|
||||
概率中的概念看起来很多,但是,其实最重要就是你耳熟能详的这几个:随机变量、概率分布、联合概率、条件概率和边缘概率。它们是整个概率的基础,我后面会详细来讲。
|
||||
|
||||
通过这些概念之间的相互推导,我们可以得到贝叶斯定理,这是朴素贝叶斯等系列算法的核心。而在概率基础之上发展而来的信息论,定义了信息熵、信息增益和基尼指数等,构成了决策树等系列算法的核心。
|
||||
|
||||
概率研究的是模型如何产生数据,统计研究的是如何通过数据来推导其背后的模型。所以说,概率和统计其实是互逆的。
|
||||
|
||||
概率和统计的运用非常多,我这里主要讲了三个方面。第一,概率可以帮助我们进行更精准的复杂度分析;第二,概率统计更多的是用在机器学习和大数据分析中;第三,概率统计还可以用在各种机器学习的算法中。这些内容,在之后的章节我会进行非常详细的讲解。
|
||||
|
||||
## 思考题
|
||||
|
||||
之前你对概率统计的认识是什么样的呢?对这块内容,你觉得最难的是什么?
|
||||
|
||||
欢迎留言和我分享,也欢迎你在留言区写下今天的学习笔记。你可以点击“请朋友读”,把今天的内容分享给你的好友,和他一起精进。
|
||||
217
极客时间专栏/程序员的数学基础课/概率统计篇/20 | 概率基础(上):一篇文章帮你理解随机变量、概率分布和期望值.md
Normal file
217
极客时间专栏/程序员的数学基础课/概率统计篇/20 | 概率基础(上):一篇文章帮你理解随机变量、概率分布和期望值.md
Normal file
@@ -0,0 +1,217 @@
|
||||
<audio id="audio" title="20 | 概率基础(上):一篇文章帮你理解随机变量、概率分布和期望值" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/9e/eb/9e2f2a69c8a0fb5a6ad39ea465a25eeb.mp3"></audio>
|
||||
|
||||
你好,我是黄申。
|
||||
|
||||
相信你对变量这个概念并不陌生,数学方程式和编程代码里经常会用到变量。那什么是变量呢?我们在概率中常说的**随机变量**( random variable)和普通的**变量**(variable)又有什么不同呢?
|
||||
|
||||
这些问题其实很简单,我一说你就明白了。
|
||||
|
||||
在没有发生运算之前,普通变量的值并不会发生变化,也就是说,它可以取不同的值,但是一旦取值确定之后,它总会是一个固定的值,除非有新的运算操作。而随机变量的值并不固定,比如说,某个随机变量可能有10%的概率等于10,有20%的概率等于5,有30%的概率等于28等等。
|
||||
|
||||
我们上节说了,随机变量根据其取值是否连续,可分为离散型随机变量和连续型随机变量。举几个例子,抛硬币出现正反面的次数以及每周下雨的天数,都是离散的值,所以对应的随机变量为离散型。而汽车每小时行驶的速度和银行排队的时间,都是连续的值,对应的随机变量为连续型。换句话,从计算的角度来说,我们可以直接求和得出的,就是“离散的”,需要用积分计算的,就是“连续的”。
|
||||
|
||||
而随机变量的取值对应了随机现象的一种结果。正是结果的不确定性,才导致了随机变量取值的不确定性,于是我们就引入了概率。我们可以说,每种值是以一定的概率出现的。
|
||||
|
||||
## 概率分布
|
||||
|
||||
随机变量的每种取值的出现都遵从一定的可能性,把这个可能性用具体的数值表示出来就是**概率**。如果将随机变量所有可能出现的值,及其对应的概率都罗列出来,我们就能获得这个变量的概率分布。
|
||||
|
||||
我们拿最简单的抛硬币事件来看。从理论上说来,出现正面和反面的概率都是50%(我们假设不存在硬币站立的情况)。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/53/8e/534e71694ac590887737299ddcd5f48e.png" alt="">
|
||||
|
||||
我们可以通过一小段Python代码,做个模拟实验,验证一下这个分布。
|
||||
|
||||
```
|
||||
import random
|
||||
import pandas as pd
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
def flip_coin(times):
|
||||
data_array = np.empty(times)
|
||||
weights_array = np.empty(times)
|
||||
weights_array.fill(1 / times)
|
||||
|
||||
for i in range(0, times): #抛times次的硬币
|
||||
data_array[i] = random.randint(0, 1) #假设0表示正面,1表示反面
|
||||
|
||||
data_frame = pd.DataFrame(data_array)
|
||||
data_frame.plot(kind = 'hist', legend = False) #获取正反面统计次数的直方图
|
||||
data_frame.plot(kind = 'hist', legend = False, weights = weights_array).set_ylabel("Probability") #获取正反面统计概率的直方图
|
||||
plt.show()
|
||||
|
||||
flip_coin(10)
|
||||
|
||||
```
|
||||
|
||||
该代码随机生成若干次的0或1(0表示硬币正面朝上,1表示硬币反面朝上)。下表是我生成10次的结果,其中正面4次,反面6次。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/b0/37/b0d2b522b903b2adcf706d47312a3537.png" alt="">
|
||||
|
||||
对应的正反面次数和概率直方图如下,而概率的直方图就表示了其概率分布。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/07/9d/07b7a79563da20219034a3eb0afd3c9d.png" alt="">
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/34/eb/34703edccffa3b566924c785ffb17eeb.png" alt="">
|
||||
|
||||
通过修改flip_coin函数中的数字,我们可以修改抛硬币的次数。我又尝试“抛了”100次,得到的结果是正面47次,反面53次。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/be/2e/beb0f943c9f4c0900d2d53a8afdcb42e.png" alt="">
|
||||
|
||||
接下来是抛10000次的结果,正面是4982次,反面是5018次。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/2c/ec/2caf3cf4ee18c553e48524c01c5680ec.png" alt="">
|
||||
|
||||
你可能已经发现了,根据计算机模拟的结果所统计的概率,并不是精确的正反面各50%。如果你运行同样的代码,也会发现类似的情况。这是因为理论上的概率,是基于无限次的实验。而我们这里实验的次数是有限的,是一种统计采样。
|
||||
|
||||
从10次、100次到10000次,我们能看到,概率会变得越来越稳定,越来越趋近于正反各50%的分布。也就是说,**统计的采样次数越多,越趋近于我们理论上的情况**。因此,从这个统计实验我们可以看出,**概率分布描述的其实就是随机变量的概率规律**。
|
||||
|
||||
抛硬币正面次数、每周下雨天数这种离散型随机变量,对应的概率分布是很好理解的,但是对于连续型的随机变量,如何理解它们的概率分布呢?
|
||||
|
||||
如果我们把连续的值离散化,你会发现这个问题其实不难理解。就拿汽车每小时行驶的公里数来说吧。现实生活中我们通过汽车的仪表盘所读取速度,都是整数值,例如每小时60公里。也许比较高档的车会显示数字化的速度,带有小数位,但实际上汽车最精确的速度是一个无限位数的小数,是从0到最高公里数的一个任意数值。所以仪表盘所显示的数字,是将实际速度离散化处理之后的数字。除了仪表盘上的速度,汽车行驶在时间维度上也是连续的。类似地,我们还需要对时间进行离散化,比如每分钟查看仪表盘一次并读取速度值。
|
||||
|
||||
好的,理解了这些之后,我同样使用代码来随机一些行驶速度的数据。第一次模拟,假设我们手头上有一辆老爷车,它的仪表盘最小刻度是5,也就是说,它只能显示55、60、65这种公里数。然后我们每1分钟采样一次(读一次仪表盘),那么1小时内我们将生成60个数据。示例代码如下:
|
||||
|
||||
```
|
||||
def check_speed(time_gap, speed_gap, total_time, min_speed, max_speed):
|
||||
|
||||
times = (int)(total_time / time_gap) #获取读取仪表盘的次数
|
||||
|
||||
data_array = np.empty(times)
|
||||
weights_array = np.empty(times)
|
||||
weights_array.fill(1 / times)
|
||||
|
||||
for i in range(0, times):
|
||||
if (speed_gap < 1):
|
||||
data_array[i] = random.random() * max_speed #随机生成一个最高速和最低速之间的速度
|
||||
else:
|
||||
data_array[i] = random.randint(0, max_speed / speed_gap) * speed_gap #随机生成一个最高速和最低速之间的速度,先除以speed_gap然后乘以speed_gap进行离散化
|
||||
|
||||
data_frame = pd.DataFrame(data_array)
|
||||
bin_range = np.arange(0, 200, speed_gap)
|
||||
data_frame.plot(kind = 'hist', bins = bin_range, legend = False) #获取时速统计次数的直方图
|
||||
data_frame.plot(kind = 'hist', bins = bin_range, legend = False, weights = weights_array, ).set_ylabel("Probability") #获取时速统计概率的直方图
|
||||
plt.show()
|
||||
|
||||
check_speed(1, 5, 60, 0, 200)
|
||||
|
||||
```
|
||||
|
||||
对生成的60个数据,我们统计其出现在每个速度区间的频次以及相应的概率。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/92/da/92e5097642a26c6ff5d0ac727e7e1dda.png" alt="">
|
||||
|
||||
我们将频次和概率以直方图的形式来展示。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/08/66/08ec24a94441da4f4c59b5ec65e5bf66.png" alt="">
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/5f/e8/5f2c939a75584eadd38fce7eac68e5e8.png" alt="">
|
||||
|
||||
第二次模拟,假设我们把车升级到当今的主流车,仪表盘的最小刻度已经到1了,然后时间维度上,我们细分到0.1分钟,那么1小时我们将生成600个数据。我们还可以进行第三次、第四次、甚至是无穷次的模拟,每次模拟的时候我们都将行驶速度的精度进一步提升、将时间间隔进一步缩小,让两者都趋近于0,那么我们的模拟就从离散逐步趋近于连续的值了。
|
||||
|
||||
随机变量的概率分布由离散型的直方图变为了连续型的曲线图。通过下面的图,你可以看到这整个演变的过程。
|
||||
|
||||
当速度间隔和时间间隔(精度)逐步缩小的时候,直方图的分组(bin)就越小,所以你会看到x轴上的数据越浓密,y轴上的数据越平滑。当间隔或精度无穷小并趋近于0的时候,y轴的数据就会随着x轴连续变化而变化。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/d6/29/d6bad265a25873d453bc326740688829.png" alt="">
|
||||
|
||||
不过,当时间间隔小于数秒时,我们需要考虑随机产生的数据是否具备真实性,毕竟现实中汽车的速度不可能在数秒中从0到200公里,因此临近两次的采样数据不能相差太大。
|
||||
|
||||
上面我通过两个模拟实验,分别展示了离散型和连续型概率的分布。其实,人们在实际运用中,已经总结出了一些概率分布,我这里挑几个最常见的给你讲解。
|
||||
|
||||
首先我们来看看离散分布模型。常用的离散分布有伯努利分布、分类分布、二项分布、泊松分布等等,这里我重点给你介绍两个。
|
||||
|
||||
第一个是**伯努利分布**(Bernoulli Distribution),这是单个随机变量的分布,而且这个变量的取值只有两个,0或1。伯努利分布通过参数λ来控制这个变量为1的概率,我把具体的公式列出来,并画了张图便于你理解。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/ef/10/efb6477333146f0ee91302532fc46210.png" alt="">
|
||||
|
||||
或者写作:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/66/03/664d462b28f84da64951ae0b3516f103.png" alt="">
|
||||
|
||||
其中x只能为0或1。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/1a/d0/1a64837e5e00b4be301c25da3eb56bd0.png" alt="">
|
||||
|
||||
从这个图也可以看出,之前抛硬币的概率分布就属于伯努利分布。
|
||||
|
||||
另一个是**分类分布**(Categorical Distribution),也叫Multinoulli分布。它描述了一个具有k个不同状态的单个随机变量。这里的k,是有限的数值,如果k为2的时候,那么分类分布就变成了伯努利分布。我把这个分布的公式和图解都列了出来。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/0b/28/0b4e8b39a81b24946f6baf3ac7d1ee28.png" alt="">
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/a2/0a/a2142147a07d4bc4cd45b730cac6850a.png" alt="">
|
||||
|
||||
离散型随机变量的状态数量是有限的,所以可以通过伯努利和分类分布来描述。可是对于连续型随机变量来说,状态是无穷多的,这时我们就需要连续分布模型。比较经典的连续分布有正态分布、均匀分布、指数分布、拉普拉斯分布等等。如果你只需要掌握一个的话,那肯定是正态分布。
|
||||
|
||||
这个分布可以近似表示日常生活中很多数据的分布,我们经常使用它进行机器学习的特征工程,对原始数据实施标准化,使得不同范围的数据具有可比性。所以,如果想要学习机器学习,一定要掌握正态分布。
|
||||
|
||||
**正态分布**(Normal Distribution),也叫高斯分布(Gaussian Distribution)。我把这个分布的公式列在这里:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/6e/34/6e732d5fdca4786ead38e439493a8d34.png" alt="">
|
||||
|
||||
在这个公式中有两个参数,μ表示均值,σ表示方差。看这个公式不太直观,我们来看一看对应的分布图。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/b5/82/b514674826625cfec19bbe3bfec89e82.png" alt="">
|
||||
|
||||
从这个图可以看出,越靠近中心点μ,出现的概率越高,而随着渐渐远离μ,出现的概率先是加速下降,然后减速下降,直到趋近于0。蓝色区域上的数字,表示了这个区域的面积,也就是数据取值在这个范围内的概率。例如,数据取值在[-1σ, μ]之间的概率为34.1%。
|
||||
|
||||
现实中,很多数据分布都是近似于正态分布的。例如人类的身高体重。拿身高来说,大部分人都是接近平均值身高,偏离平均身高越远,相对应的人数越少。这也是为什么正态分布很常用的原因。
|
||||
|
||||
正态分布可以扩展到多元正态分布或多维正态分布(Multivariate Normal Distribution),不过最实用的还是一元标准正态分布,这种分布的μ为0,σ为1。在专栏后面的内容里,我会详细介绍如何使用这种分布,进行特征值的标准化。
|
||||
|
||||
## 期望值
|
||||
|
||||
理解了概率分布,你还需要了解期望值。为什么要了解期望值呢?
|
||||
|
||||
期望值,也叫数学期望,是每次随机结果的出现概率乘以其结果的总和。如果我们把每种结果的概率看作权重,那么期望值就是所有结果的加权平均值。它在我们的生活中十分常见,例如计算多个数值的平均值,其实就是求期望值,只不过我们假设每个数值出现的概率是相同的。
|
||||
|
||||
上一节,我提到如何使用概率来解决复杂度分析,通过概率的加权平均来获得平均时间复杂度,就是时间复杂度的期望值。当然,这个概念能帮助你解决的实际问题远不止这些。
|
||||
|
||||
在我看来,一个问题只要满足两个要素,我们就可以考虑使用期望值:
|
||||
|
||||
第一个要素,在这个问题中可能出现不同的情况,而且各种情况的出现满足了一定的概率分布;
|
||||
|
||||
第二个要素,每种情况都对应一个数值,这个数值代表了具体的应用含义。
|
||||
|
||||
如果你觉得这个还是过于抽象,我再回到本节的案例给你讲解。我先给你提个问题:给定了行驶速度的概率分布,如何计算汽车在1小时内每分钟行驶的平均速度?我们还从比较容易理解的离散型随机变量开始。
|
||||
|
||||
没错,这个问题的答案就是使用1小时所行驶的总距离除以60分钟。以之前的每分钟读取仪表盘、仪表盘最小刻度是5为例。概率分布如下图。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/fb/a3/fb92ed0e83943a61579c55759fa0caa3.png" alt="">
|
||||
|
||||
1小时行驶的总距离为每种速度乘以用该速度行驶的时间的乘积之总和。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/b3/3d/b31d1664765392d57c21f1ffd3a2b53d.png" alt="">
|
||||
|
||||
1小时内每分钟平均的行驶速度为总距离除以60分钟。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/6c/c2/6c9704ffe74872dde0930ecc02d0e7c2.png" alt="">
|
||||
|
||||
将上述式子变化一下,我们可以得到:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/7c/cd/7c65637c636ec02333334f4478ecbacd.png" alt="">
|
||||
|
||||
你会发现,每分钟的平均值,就是每种速度的加权平均,而每种速度的权重就是其在概率分布中出现的概率。汽车可能按照不同的速度行驶,每种速度都有一个出现的概率,就是我前面提到的第一个要素。而每种速度所对应的每分钟多少公里这个数值,就是第二个要素。结合这两个要素,计算得到的平均值,也是汽车每分钟行驶速度的期望值。
|
||||
|
||||
那么,对于连续型的随机变量,这种期望值应该如何计算呢?我们需要使用下面的积分公式:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/5c/3b/5c206d77edcc3c2a282fab733fba4f3b.png" alt="">
|
||||
|
||||
## 总结
|
||||
|
||||
通过这讲的内容,你对概率的基本知识应该有所了解。本讲中,我通过抛硬币和汽车驾驶的例子,讲述了概率论中一些最基本,也是最重要的概念,包括随机现象、随机变量、概率分布和期望值。
|
||||
|
||||
离散型的随机变量在计算机编程中的应用更为广泛。它可以和排列组合的思想结合起来,通过不同排列或组合的数量,计算每种情况出现的概率。如果把这种概率和每种情况下的复杂度数值结合起来,就可以计算复杂度的期望值。
|
||||
|
||||
另外,离散型概率也可以运用在机器学习的分类算法中。例如,对于文本进行分类时,我们可以通过离散型随机变量,表示每个分类或者每个单词出现的概率。当然,仅靠今天的内容,还不足以让我们打造一个分类算法。我们还需要了解联合概率、条件概率、贝叶斯定理等重要的概念。下一讲,我会详细解释它们。
|
||||
|
||||
## 思考题
|
||||
|
||||
每天我们的朋友圈都会浮现很多新的“动态”。假设我们按照字数,把这些动态分为以下几类:10个字以内,10~30个字,30~50字,50~100字,100字以上。
|
||||
|
||||
尝试统计一下你朋友圈某个时间段的动态,看看每个类有多少条,转换成概率分布应该如何表示?你的分布和今天介绍的哪个概率分布最接近?请注意,统计字数时只需要看你朋友自己所写的内容,无需考虑转发的文章。
|
||||
|
||||
欢迎留言和我分享,也欢迎你在留言区写下今天的学习笔记。你可以点击“请朋友读”,把今天的内容分享给你的好友,和他一起精进。
|
||||
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
<audio id="audio" title="21 | 概率基础(下):联合概率、条件概率和贝叶斯法则,这些概率公式究竟能做什么?" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/82/31/829587c1688417156b9545737e335f31.mp3"></audio>
|
||||
|
||||
你好,我是黄申。
|
||||
|
||||
上一节我介绍了随机现象、随机变量以及概率分布这些比较简单的概念。学习这些概念是为了做什么呢?其实就是为了更精确地描述我们生活中的现象,用数学的视角看世界,以此解决其中的问题。
|
||||
|
||||
但是实际生活中的现象并非都会像“投硬币”那样简单。有很多影响因素都会影响我们去描述这些现象。比如,看似很简单的“投硬币”,我们其实只是考虑最主要的情况,粗暴地把硬币出现的情况一分为二。比如说,不同类型的硬币是否会影响正反面的概率分布呢?站立的情况如何考虑呢?再比如说,在汽车速度的例子中,经过的交通路线,不同的路线是否会影响速度的概率分布呢?
|
||||
|
||||
一旦影响因素变多了,我们需要考虑的问题就多了。想要解决刚才那几个问题,更精确地描述这些现象,我们就需要理解几个新的概念,联合概率、条件概率以及贝叶斯法则。从数学的角度来说,这些概念能描述现实世界中更为复杂的现象,建立更精细的数学模型。比如,我们后面要讲的朴素贝叶斯算法就是建立在联合概率、条件概率和边缘概率之上的。所以,这一节的内容也非常重要,你一定要认真学习并且掌握。
|
||||
|
||||
## 联合概率、条件概率和边缘概率
|
||||
|
||||
最近,我一直在操心儿子的教育问题,所以一直在研究他班级的成绩单。为了弄清我儿子在班级上的成绩排名,我向老师要了张全班成绩的分布表。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/cf/3d/cf93c9001c0638f0e85c033a3d9aa23d.png" alt="">
|
||||
|
||||
这张表中有两个随机变量,一个是学生的性别,一个是分数区间。我们很容易就可以得出,这个班中男生的概率是P(男生)=10/20=50%,90分及以上的学生的概率是P(90-100)=4/20=20%。那全班考了90分以上的男生的概率是多少呢?我们只要找到90分以上的男生人数,用这个人数除以全班总人数就行了,也就是P(男生, 90-100)=2/20=10%。
|
||||
|
||||
你有没有发现,“90分以上的男生”这个概率和之前单独求男生的概率或90分以上的概率不一样。之前只有一个决定因素,现在这个概率由性别和分数这两个随机变量同时决定。这种由多个随机变量决定的概率我们就叫**联合概率,<strong>它的概率分布就是**联合概率分布</strong>。随机变量x和y的联合概率使用P(x, y)表示。我算出了这个例子里所有的联合概率分布。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/24/6b/2428d89357f2a27e0e9f0a4efa97d06b.png" alt="">
|
||||
|
||||
这里的例子只有两个随机变量,但是我们可以很容易扩展到更多的随机变量,比如再增加一个学科的变量。那么,我们就可以观测这样的数据:“班级上女生的数学考了90分及以上的概率是多少?”,其中女生是关于性别变量,数学是关于学科变量,而90分及以上是关于分数变量。
|
||||
|
||||
那么联合概率和单个随机变量的概率之间有什么关联呢?对于离散型随机变量,我们可以通过通过联合概率P(x, y)在y上求和,就可以得到P(x)。对于连续型随机变量,我们可以通过联合概率P(x, y)在y上的积分,推导出概率P(x)。这个时候,我们称P(x)为**边缘概率**。
|
||||
|
||||
除了边缘概率的推导,多个变量的联合概率和单个变量的概率之间还存在一个有趣的关系。在解释这个关系之前,让我先来介绍**条件概率**。
|
||||
|
||||
条件概率也是由多个随机变量决定,但是和联合概率不同的是,它计算了给定某个(或多个)随机变量的情况下,另一个(或多个)随机变量出现的概率,其概率分布叫做**条件概率分布**。给定随机变量x,随机变量y的条件概率使用P(y | x)表示。
|
||||
|
||||
回到成绩分布的案例。我能理解在不同的阶段,男生和女生的成绩可能无法直接相比。所以我更关心的是,自己儿子和其他男生相比是否落后了。那么我的脑子里就产生了这样一个问题:“在男生中,考90分及以上的概率是多少?”。
|
||||
|
||||
仔细看,这个问题和前面几个有所不同,我只关心男生这个群体,所以解答应该是找到考了90分以上的男生之人数,然后用这个人数除以男生总人数(注意,不再是全部总人数)。根据上述表格的数据来计算,P(90-100|男生)= 2/10=20%。
|
||||
|
||||
解释清楚了条件概率,我就可以列出概率、条件概率和联合概率之间的“三角”关系了。简单的说,联合概率是条件概率和概率的乘积,采用通用的公式来表达就是:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/51/54/5100c87e5cdec55d5e7eac4f9531a154.png" alt="">
|
||||
|
||||
同样的道理,我们也可以得到:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/e4/40/e496e2cf7a9bb127dc38b1220b6e8140.png" alt="">
|
||||
|
||||
我们仍然可以使用成绩的案例,来验证这个公式。为了更清晰地表述这个问题,我们使用如下的符号:
|
||||
|
||||
<li>
|
||||
|男, 90-100|表示考了90分以上的男生人数;
|
||||
</li>
|
||||
<li>
|
||||
|男|表示男生人数;
|
||||
</li>
|
||||
<li>
|
||||
|全班|表示全班人数。
|
||||
</li>
|
||||
|
||||
男生中考了90分及以上的概率为P(90-100 | 男生) = |男生, 90-100| / |男生|,全班中男生的概率为P(男) = |男生| / |全班|。如果我们将p(90-100 | 男生) 乘以 P(男) 会得到什么结果呢?
|
||||
|
||||
(|男, 90-100| / |男生|) * (|男生| / |全班|) = |男, 90-100| / |全班|
|
||||
|
||||
咦,这不就是全班中男生考了90分及以上的联合概率吗?其实,概率、条件概率和联合概率之间的这种“三角”关系,也是著名的贝叶斯定理的核心,下面我来详细解释什么是贝叶斯定理,以及它可以运用在什么场景之中。
|
||||
|
||||
## 贝叶斯定理
|
||||
|
||||
我们假设有这样一个场景,我想知道男生考了90~100分的概率有多少,来评估一下儿子在男生中算什么水平。可是老师出于隐私保护,并没有把全班数据的分布告诉我,她说道“我可以告诉你全班考90~100分的概率,以及90~100分中男生的概率,但是不能告诉你其他信息了”。这个时候,贝叶斯定理就可以帮上忙啦。
|
||||
|
||||
刚刚我们提到:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/51/54/5100c87e5cdec55d5e7eac4f9531a154.png" alt=""><img src="https://static001.geekbang.org/resource/image/e4/40/e496e2cf7a9bb127dc38b1220b6e8140.png" alt="">
|
||||
|
||||
所以就有:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/d0/79/d082a9fc31d9378f4511dc23807df179.png" alt="">
|
||||
|
||||
这就是非常经典的贝叶斯法则。为什么说经典呢?是因为它有很多应用的场景,比如朴素贝叶斯,你可以多多熟悉一下这个公式。在这个公式中,还包含了先验概率(Prior Probability)、似然函数(Likelihood)、边缘概率(Marginal Probability)和后验概率(Posterior Probability)的概念。
|
||||
|
||||
在这里面,我们把P(x)称为先验概率。之所以称为“先验”,是因为它是从数据资料统计得到的,不需要经过贝叶斯定理的推算。
|
||||
|
||||
P(y | x)是给定x之后y出现的条件概率。在统计学中,我们也把P(y | x)写作似然函数L(y | x)。在数学里,似然函数和概率是有区别的。概率是指已经知道模型的参数来预测结果,而似然函数是根据观测到的结果数据,来预估模型的参数。不过,当y值给定的时候,两者在数值上是相等的,在应用中我们可以不用细究。
|
||||
|
||||
另外,我们没有必要事先知道P(y)。P(y)可以通过联合概率P(x, y)计算边缘概率得来,而联合概率P(x, y)可以由P(y|x) * P(x)推出。针对离散型和连续型的边缘概率推导分别如下:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/8b/d6/8bed8df818f0ebb7367ccfc2d27549d6.png" alt=""><img src="https://static001.geekbang.org/resource/image/8d/61/8d2a747caa6a629c6c38f6fc26c8ec61.png" alt="">
|
||||
|
||||
而P(x|y)是根据贝叶斯定理,通过先验概率P(x)、似然函数P(y | x)和边缘概率P(y)推算而来,因此我们把它称作后验概率。
|
||||
|
||||
回到刚刚的案例,我可以通过这样的式子来计算男生考90-100分的概率:
|
||||
|
||||
P(90-100 | 男生) = (P(男生 | 90-100) * P(90 -100)) / P(男生)
|
||||
|
||||
我只需要数数看,班上男生有多少、总人数多少,就能算出P(男生)。在加上之前,老师告诉我的P(男生 | 90-100)和P(90 -100),就能推算出P(90-100 | 男生)了。这个例子就是通过先验概率,推导出后验概率,这就是贝叶斯定理神奇的地方,也是它最主要的应用场景。
|
||||
|
||||
## 随机变量之间的独立性
|
||||
|
||||
说到多个随机变量的联合和条件概率,你可能会产生一个问题:这些随机变量是否会相互影响呢?比如,性别和分数之间有怎样的关系?性别是否会影响分数的概率分布?在之前的成绩分布表中,我们可以得到:
|
||||
|
||||
p(90-100 | 男生) = 20%
|
||||
|
||||
p(90-100 | 女生) = 20%
|
||||
|
||||
p(90-100) = 20%
|
||||
|
||||
所以,p(90-100 | 男生) = p(90-100 | 女生) = p(90-100),也就是全班中考90分及以上的概率、男生中考90分及以上的概率、以及女生中考90分及以上的概率,这三者都是一样。以此类推到其他的分数区间,同样如此,那么,从这个数据上得出的结论是性别对考分的区间没有影响。反之,我们也可以看到p(男生 | 90-100) = p(男生 | 80-90) = p(男生 | 70-80) = … = p(男生) = 50%,也就是说考分区间对性别没有影响。这种情况下我们就说性别和分数这两个随机变量是**相互独立**的。
|
||||
|
||||
相互独立会产生一些有趣的现象,刚刚我们提到:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/84/d9/84b5540ed5aec766f05d1a01d734e8d9.png" alt=""><img src="https://static001.geekbang.org/resource/image/98/d5/986898f743d134c4d4d0b6b6718f39d5.png" alt="">
|
||||
|
||||
另外,将p(x | y) = p(x)带入贝叶斯公式,就可以得出:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/5e/43/5ea567d9b3f7129f1ae34f8186d46443.png" alt="">
|
||||
|
||||
变量之间的独立性,可以帮我们简化计算。举个例子,假设有6个随机变量,而每个变量有10种可能的取值,那么计算它们的联合概率p($x_{1}$, $x_{2}$, $x_{3}$, $x_{4}$, $x_{5}$, $x_{6}$),在实际中是非常困难的一件事情。
|
||||
|
||||
根据排列,可能的联合取值,会达到10的6次方,也就是100万这么多。那么使用实际的数据进行统计时,我们也至少需要这个数量级的样本,否则的话很多联合概率分布的值就是0,产生了数据稀疏的问题。但是,如果假设这些随机变量都是相互独立的,那么我们就可以将联合概率p($x_{1},$ $x_{2}$, $x_{3}$, $x_{4}$, $x_{5}$, $x_{6}$)转换为p($x_{1}$) * p($x_{2}$) * p($x_{3}$) * p($x_{4}$) * p($x_{5}$) * p($x_{6}$)。如此一来,我们只需要计算p($x_{1}$)到 p($x_{6}$ )就行了。
|
||||
|
||||
不过,班主任刚刚打电话给我,说之前的数据表格有点笔误,实际的分布应该是这样的:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/a9/be/a960147eb4468c870a104a471c73b6be.png" alt="">
|
||||
|
||||
你再推算一下,就会发现p(分数 | 性别) = p(分数)和 p(性别 | 分数) = p(性别)并不成立,所以两者不再是相互独立的。所以下面这个式子就不再成立了,这点你在计算的时候需要注意。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/5e/43/5ea567d9b3f7129f1ae34f8186d46443.png" alt="">
|
||||
|
||||
在实际项目中,我们会假设多个随机变量是相互独立的,并基于这个假设大幅简化计算,降低对数据统计量的要求。虽然这个假设通常是不成立的,但是仍然可以帮助我们得到近似的解。相比较实现的可行性和求解的精确度,可行性更为重要。在讲解朴素贝叶斯方法中,我会充分利用这一点,从有限的训练样本中构建分类器。
|
||||
|
||||
## 总结
|
||||
|
||||
这一讲我继续讨论了概率分布相关的内容,不过这次的重点是多个随机变量相关的联合概率、条件概率、边缘概率。这里概念有点多,但是都很重要,因为这三者之间的推算关系,直接构成了贝叶斯定理的核心,所以你要花点时间理解并记住它们。
|
||||
|
||||
而贝叶斯定理定义了先验概率、后验概率和似然函数,后验概率和似然函数及先验概率的乘积成正比关系。此外,通过多个变量之间的独立性,我们可以简化联合概率的计算问题。贝叶斯定理和变量之间独立性的假设,对后面理解朴素贝叶斯算法很有帮助。
|
||||
|
||||
如果有一定数量的标注数据,那么通过统计的方法,我们可以很方便地得到先验概率和似然函数,然后推算出后验概率,最后依据后验概率来做预测。这整个过程符合监督式机器学习的模型训练和新数据预测这两个阶段,因此朴素贝叶斯算法被广泛运用在机器学习的分类问题中。下一节中,我们详细讨论这个算法。
|
||||
|
||||
## 思考题
|
||||
|
||||
大年三十晚上,爷爷奶奶发红包。爷爷准备的红包是4个50元的,6个100元的。奶奶准备的红包是8个50元的,4个100元的。全家人随机抽,你运气很好,拿到一个100元的红包。请问这个红包来自爷爷的概率有多少?来自奶奶的概率有多少?
|
||||
|
||||
欢迎留言和我分享,也欢迎你在留言区写下今天的学习笔记。你可以点击“请朋友读”,把今天的内容分享给你的好友,和他一起精进。
|
||||
140
极客时间专栏/程序员的数学基础课/概率统计篇/22 | 朴素贝叶斯:如何让计算机学会自动分类?.md
Normal file
140
极客时间专栏/程序员的数学基础课/概率统计篇/22 | 朴素贝叶斯:如何让计算机学会自动分类?.md
Normal file
@@ -0,0 +1,140 @@
|
||||
<audio id="audio" title="22 | 朴素贝叶斯:如何让计算机学会自动分类?" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/b0/7f/b0397dfbe090fbf67e9e6dd03ab4d67f.mp3"></audio>
|
||||
|
||||
你好,我是黄申。今天我们来聊聊朴素贝叶斯。
|
||||
|
||||
在开始正式的内容之前,我想问你一个问题,你是如何区分苹果、甜橙和西瓜的?你可能要说了,这个问题还用得着讲吗?是不是你们博士都喜欢将简单的问题复杂化?还真不是,如果你将计算机想象成一个两三岁的孩子,你会怎么教一个孩子区分这些水果呢?
|
||||
|
||||
比如我曾经就和一个小朋友有过这样一段对话:
|
||||
|
||||
小朋友:黄叔叔,你和我讲讲,什么样的水果才是苹果呀?
|
||||
|
||||
我:圆形的、绿色的水果。
|
||||
|
||||
小朋友:那西瓜也是圆形的、绿色的呀?
|
||||
|
||||
我:嗯……苹果也有可能是黄色或红色的,但西瓜不是。
|
||||
|
||||
小朋友:那甜橙也是圆形的、黄色的呀?
|
||||
|
||||
我:好吧,你看到的大部分情况下的甜橙都是黄色的,而苹果只有很少情况(少数品种)是黄色的。而且你还可以尝尝,它们的味道也是不同的。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/0e/db/0e626ddb70a0f4c7133e0a54d18c8fdb.png" alt="">
|
||||
|
||||
哈哈,你是不是觉得想要描述清楚,并没有想象中的那么容易?但是,在这个对话中,有两点我觉得你需要关注一下:
|
||||
|
||||
<li>
|
||||
我使用了“可能”“大部分情况”“很少情况”等等这种词语,这些词包含了**概率**的概念;
|
||||
</li>
|
||||
<li>
|
||||
我使用了**多个条件**来判断一个水果属于哪个类别。
|
||||
</li>
|
||||
|
||||
基于此,我接下来就要聊聊,我们是如何通过数学的思想和方法,系统性地解决这个问题的。这其中,**朴素贝叶斯**(Naive Bayesian)就提供了一个切实可行的方案。不过,在深入了解它之前,我们还需要做点准备工作。
|
||||
|
||||
## 如何将原始信息转化为计算机能看懂的数据?
|
||||
|
||||
事实上,计算机并不像两三岁的小孩那样,可以看到水果的颜色、形状和纹理,或者能尝到水果的味道。**我们需要将水果的特征转化为计算机所能理解的数据**。**最常用的方式就是提取现实世界中的对象之属性,并将这些转化为数字。**
|
||||
|
||||
以水果为例,你会提取它们的哪些属性呢?我会考虑这些,比如:形状、外皮颜色、斑马纹理、重量、握感、口感。我手边刚好有一个苹果、一个甜橙和一个西瓜,我把它们的属性分别统计了一下,你可以看看。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/0c/8c/0c4508f42a2179d4de22654ffe17778c.png" alt="">
|
||||
|
||||
然后,我们需要这些属性转化为计算机能够理解的东西——数字,也就是说,我给每种属性都定义了具体的数值,用来代表它们的具体属性。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/8c/5d/8ce159eb36bbed80bda6ab7f6d10bc5d.png" alt="">
|
||||
|
||||
比较细心的话,你可能已经发现了,我偷偷地把重量由连续值转化成了离散值,这是因为朴素贝叶斯处理的都是离散值。
|
||||
|
||||
好了,仅仅3个水果还不足以构成朴素贝叶斯分类所需的训练样本。为了保证训练的质量,我们可以继续扩展到10个水果。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/e0/08/e0f92302ec5f9a7353177644db88a408.png" alt="">
|
||||
|
||||
## 朴素贝叶斯的核心思想
|
||||
|
||||
我们现在已经拿到了这10个水果的数据,那如果现在我手上有一个新的水果,它也有一定的形状、颜色、口感等等,你怎么判断它是哪种水果呢?
|
||||
|
||||
之前的文章我们讲过先验概率、后验概率、条件概率和贝叶斯法则,它们是朴素贝叶斯分类的核心组成部分。通过贝叶斯法则,我们可以根据先验概率和条件概率,推导出后验概率。首先让我们快速回想一下贝叶斯公式。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/0e/57/0ed1d08bd7a3197231ec1b596cadd857.png" alt="">
|
||||
|
||||
上一节,我已经详细解释了这个公式的推导和每一部分的含义,这里再强调一下贝叶斯定理的核心思想:**用先验概率和条件概率估计后验概率**。
|
||||
|
||||
那具体到这里的分类问题,我们该如何运用这个公式呢?为了便于理解,我们可以将上述公式改写成这样:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/00/2a/00cdccfb26258a21de50862ccd22a52a.png" alt="">
|
||||
|
||||
其中,c表示一个**分类**(class),f表示属性对应的**数据字段**(field)。如此一来,等号左边的P(c|f)就是待分类样本中,出现属性值f时,样本属于类别c的概率。而等号右边的P(f|c)是根据训练数据统计,得到分类c中出现属性f的概率。P©是分类c在训练数据中出现的概率,P(f)是属性f在训练样本中出现的概率。
|
||||
|
||||
看到这里,你可能要问了,这里的贝叶斯公式只描述了单个属性值属于某个分类的概率,可是我们要分析的水果每个都有很多属性啊,这该怎么办呢?
|
||||
|
||||
别急,朴素贝叶斯在这里就要发挥作用了。这是基于一个简单假设建立的一种贝叶斯方法,并假定数据对象的不同属性对其归类影响时是相互独立的。此时若数据对象o中同时出现属性fi与fj,则对象o属于类别c的概率就是这样:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/51/32/51a8c96cd9a8ae06acdff25a87438332.png" alt="">
|
||||
|
||||
现在,我们应该已经可以用10个水果的数据,来建立朴素贝叶斯模型了。
|
||||
|
||||
其中,苹果的分类中共包含3个数据实例,对于形状而言,出现2次不规则圆、1次圆形和0次椭圆形,因此各自的统计概率为0.67、0.33和0.00。我们将这些值称为,给定一个水果分类时,出现某个属性值的**条件概率**。以此类推,所有的统计结果就是下面这个表格中这样:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/50/22/504f97b994046fc3fee82690acdd5622.png" alt="">
|
||||
|
||||
对于上表中出现的0.00概率,在做贝叶斯公式中的乘积计算时,会出现结果为0的情况,因此我们通常取一个比这个数据集里最小统计概率还要小的极小值,来代替“零概率”。比如,我们这里取0.01。在填充训练数据中从来没有出现过的属性值的时候,我们就会使用这种技巧,我们给这种技巧起个名字就叫作**平滑**(Smoothing)。
|
||||
|
||||
有了这些条件概率,以及各类水果和各个属性出现的先验概率,我们已经建立起了朴素贝叶斯模型。现在,我们就可以用它进行朴素贝叶斯分类了。
|
||||
|
||||
假设我们有一个新的水果,它的形状是圆形,口感是甜的,那么根据朴素贝叶斯,它属于苹果、甜橙和西瓜的概率分别是多少呢?我们先来计算一下,它属于苹果的概率有多大。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/4b/10/4b9b7fc57f85344a90fde596b58ef110.png" alt="">
|
||||
|
||||
其中,apple表示分类为苹果,shape-2表示形状属性的值为2(也就是圆形),taste-2表示口感属性的值为2。以此类推,我们还可计算该水果属于甜橙和西瓜的概率。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/49/1e/490bc17c05070918564c20b943daed1e.png" alt="">
|
||||
|
||||
比较这三个数值,0.00198<0.00798<0.26934,所以计算机可以得出的结论,该水果属于甜橙的可能性是最大的,或者说,这个水果最有可能是甜橙。
|
||||
|
||||
你可能已经注意到了,这几个公式里的概率乘积通常都非常小,在物品的属性非常多的时候,这个乘积可能就小到计算机无法处理的地步。因此,在实际运用中,我们还会采用一些数学手法进行转换(比如取log将小数转换为绝对值大于1的负数),原理都是一样的。
|
||||
|
||||
内容比较多,我稍微总结一下。朴素贝叶斯分类主要包括这几个步骤:
|
||||
|
||||
<li>
|
||||
准备数据:针对水果分类这个案例,我们收集了若干水果的实例,并从水果的常见属性入手,将其转化为计算机所能理解的数据。这种数据也被称为**训练样本**。
|
||||
</li>
|
||||
<li>
|
||||
建立模型:通过手头上水果的实例,我们让计算机统计每种水果、属性出现的先验概率,以及在某个水果分类下某种属性出现的条件概率。这个过程也被称为**基于样本的训练**。
|
||||
</li>
|
||||
<li>
|
||||
分类新数据:对于一颗新水果的属性数据,计算机根据已经建立的模型进行推导计算,得到该水果属于每个分类的概率,实现了分类的目的。这个过程也被称为**预测**。
|
||||
</li>
|
||||
|
||||
## 朴素贝叶斯分类VS其他分类算法
|
||||
|
||||
用朴素贝叶斯进行分类的内容差不多就是这样,你可能要问了,朴素贝叶斯是唯一的分类算法吗?现实中需要分类的场景那么多,朴素贝叶斯都适用吗?确实,我们有很多种分类算法,它们也都有各自的优劣。我这里就把朴素贝叶斯和常用的几种分类算法做个总结和比较。
|
||||
|
||||
<li>
|
||||
和**KNN最近邻**相比,朴素贝叶斯需要更多的时间进行模型的训练,但是它在对新的数据进行分类预测的时候,通常效果更好、用时更短。
|
||||
</li>
|
||||
<li>
|
||||
和**决策树**相比,朴素贝叶斯并不能提供一套易于人类理解的规则,但是它可以提供决策树通常无法支持的模糊分类(一个对象可以属于多个分类)。
|
||||
</li>
|
||||
<li>
|
||||
和**SVM支持向量机**相比,朴素贝叶斯无法直接支持连续值的输入。所以,在前面的案例中,我将连续值转化成了离散值,便于朴素贝叶斯进行处理。
|
||||
</li>
|
||||
|
||||
为了便于你理解记忆,我这里也做一下总结。
|
||||
|
||||
如果一个分类的应用场景中,待分类对象的属性值大部分都是离散的(或者很容易转化为离散的)、需要支持模糊分类,并且需要快速可靠的实时分类,那么这种场景通常就非常适合使用朴素贝叶斯方法。
|
||||
|
||||
## 总结
|
||||
|
||||
今天我从一个看似非常简单的判断水果的例子出发,介绍了如何通过物体的属性及其数值,让计算机理解现实世界中的事物,并通过朴素贝叶斯方法来对其进行分类。
|
||||
|
||||
在朴素贝叶斯方法的推导过程中,我给你讲了如何使用贝叶斯法则,将后验概率的估计转换为先验概率和条件概率。朴素贝叶斯训练过程包括基于样本数据的先验概率和条件概率统计,分类过程就包括了使用贝叶斯法则,结合新样本的属性数据以及训练好的模型数据,进行最终的预测。
|
||||
|
||||
最后,我将朴素贝叶斯和其他常见分类算法,比如KNN近邻、决策树、SVM向量机,做了对比。朴素贝叶斯适用离散属性值中,训练过程耗时长但是分类预测速度快,支持模糊分类。这一节的内容比较偏理论,下一节,我会着重来讲朴素贝叶斯的应用场景,告诉你哪些场合下更适合使用朴素贝叶斯法。
|
||||
|
||||
## 思考题
|
||||
|
||||
除了文本分类,你还知道什么地方可以使用朴素贝叶斯方法来处理分类问题?
|
||||
|
||||
欢迎留言和我分享,也欢迎你在留言区写下今天的学习笔记。你可以点击“请朋友读”,把今天的内容分享给你的好友,和他一起精进。
|
||||
|
||||
|
||||
144
极客时间专栏/程序员的数学基础课/概率统计篇/23 | 文本分类:如何区分特定类型的新闻?.md
Normal file
144
极客时间专栏/程序员的数学基础课/概率统计篇/23 | 文本分类:如何区分特定类型的新闻?.md
Normal file
@@ -0,0 +1,144 @@
|
||||
<audio id="audio" title="23 | 文本分类:如何区分特定类型的新闻?" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/82/ae/822cde2518a1ba58be19fa9600378bae.mp3"></audio>
|
||||
|
||||
你好,我是黄申。
|
||||
|
||||
你平时应该见过手机App推送的新闻吧?你有没有觉得这些App的推荐算法很神奇?它们竟然可以根据你的喜好来推荐新闻。想要实现这些推荐算法,有一个非常重要的步骤就是给新闻分类。可是,新闻头条这种综合性的平台,需要处理的新闻都是海量的,我们不可能完全靠人工手动处理这些事情。这个时候,我们就要用到计算机技术,来对文本进行自动分类。
|
||||
|
||||
上一节,我给你介绍了如何利用朴素贝叶斯方法,教会计算机进行最基本的水果分类。基于水果分类,今天我们继续深入分类这个话题,告诉你如何利用自然语言处理和朴素贝叶斯方法,对新闻这种长篇文本进行分类。
|
||||
|
||||
## 文本分类系统的基本框架
|
||||
|
||||
想要实现一个完整的文本分类系统,我们通常需要进行这些步骤:
|
||||
|
||||
### 1.采集训练样本
|
||||
|
||||
对于每个数据对象,我们必须告诉计算机,它属于哪个分类。上一节的水果案例里,我们给每个水果打上“苹果”“甜橙”和“西瓜”的标签,这就是采集训练样本。
|
||||
|
||||
同样,我们可以给每一篇新闻打上标签,也就是说,我们首先要分辨某条新闻是什么类型的,比如是政治的、军事的、财经的、体育的,还是娱乐的等等。这一点非常关键,因为分类标签就相当于计算机所要学习的标准答案,其质量高低直接决定了计算机的分类效果。此外,我们也可以在一开始就预留一些训练样本,专门用于测试分类的效果。
|
||||
|
||||
### 2.预处理自然语言
|
||||
|
||||
在水果的案例中,当我们把这些水果的特征值提取出来后,能很容易地将它们的属性转化成计算机所能处理的数据,可是这一步对于文本而言就没有那么容易了。好在专家们已经发明出了一套相对成熟的方法,包括词包(bag of words)、分词、词干(Stemming)和归一化(Normalization)、停用词(Stopword)、同义词(Synonyms)和扩展词处理。这里你只需要了解有这么些方法就可以了,我们使用这些方法的目的就是让计算机能够理解文本,所以如果你对刚才提到的这些专业词汇比较陌生,完全不用担心,这并不会影响对后面知识的理解。
|
||||
|
||||
### 3.训练模型
|
||||
|
||||
训练模型就是算法通过训练数据进行模型拟合的过程。对于朴素贝叶斯方法而言,训练的过程就是要获取每个分类的先验概率、每个属性的先验概率以及给定某个分类时,出现某个属性的条件概率。
|
||||
|
||||
### 4.实时分类预测
|
||||
|
||||
算法模型在训练完毕后,根据新数据的属性来预测它属于哪个分类的过程。对于朴素贝叶斯方法而言,分类预测的过程就是根据训练阶段所获得的先验概率和条件概率,来预估给定一系列属性的情况下属于某个分类的后验概率。
|
||||
|
||||
整个流程大致可以用下图来描述:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/65/42/65d4db7dbe14f24ae820cff5a83ff242.png" alt="">
|
||||
|
||||
这四个步骤你大致了解就可以了,这里面有两点我会重点讲一下,一是对文本中的自然语言进行预处理,并从文本集合建立字典;另一个是如何使用建好的字典,统计朴素贝叶斯方法所需的数据。自然语言的预处理是让计算机“理解”人类语言的关键步骤,如果没有这一步,计算机就无法将大量的自然语言转换成自己可以处理的数据。而条件概率和先验概率是朴素贝叶斯方法所必须的,因此如何准确地统计它们也是需要详细解释的。
|
||||
|
||||
## 基于自然语言的预处理
|
||||
|
||||
和之前的水果案例相比,新闻这种文本数据最大的区别在于,它包含了大量的自然语言。那么如何让计算机理解自然语言呢?我们的计算机体系没有思维,要理解人类的语言在现阶段是不现实的。但是,我们仍然可以对自然语言进行适当的处理,将其变为机器所能处理的数据。
|
||||
|
||||
首先,我们要知道,文本的的重要属性是什么,这样我们才能提取出它的特征。怎么才能知道哪些属性是重要的呢?
|
||||
|
||||
我举个例子,假如说,有人给你一篇几千字的文章,让你在10秒钟之内说出文章大意,你会怎么办?我想大部分人的解决方案是“**找关键词**”!没错,我们也可以交给计算机用同样的办法。而计算机处理文本的基本单位就是字和单词,这就是人们最常用的方法:词袋(Bag of words)模型。
|
||||
|
||||
这种模型会忽略文本中的词语出现的顺序以及相应的语法,将整篇文章仅仅看做是一个大量单词的组合。文本中每个词的出现都是独立的,不依赖于其他词的出现情况。讲到这里,你有没有发现在词包模型中,所有单词相互之间是独立的,这个假设和朴素贝叶斯模型的独立假设是不是一致呀?
|
||||
|
||||
没错!这里我们就可以很巧妙地将朴素贝叶斯和文本处理结合起来了。不过先不要急,我们还要掌握一些方法,才能将文本中的长篇大论处理成关键词。
|
||||
|
||||
### 1.分词
|
||||
|
||||
计算机处理自然语言的基本单位是单词和词组。对于英语等拉丁语系的语言来说,单词之间是以空格作为自然分界符的,所以我们可以直接使用空格对句子进行分割,然后来获取每个单词。但是,中文、日文、韩文这些语言在书写的时候,词和词之间并没有空格可以进行自然分界,所以我们就需要使用一些算法,来估计词语之间的划分,我们将这个过程称为**分词**。
|
||||
|
||||
这里有一个给中文句子分词的例子,你可以看一看。
|
||||
|
||||
```
|
||||
分词前:今天我们一起来学习计算机学科中的数学知识
|
||||
分词后:今天 我们 一起 来 学习 计算机 学科 中 的 数学 知识
|
||||
|
||||
```
|
||||
|
||||
是不是觉得给句子分词很简单?这是因为你的中文水平比较高,你想想,计算机怎么才能知道如何分词呢?我们有很多现成的分词模型可以使用。我这里介绍两种目前比较主流的分词模型,你只需要了解就行。
|
||||
|
||||
第一种是**基于字符串匹配**。其实就是扫描字符串。如果发现字符串的子串和词相同,就算匹配成功。匹配规则通常是“正向最大匹配”“逆向最大匹配”“长词优先”。这些算法的优点是只需使用基于字典的匹配,因此计算复杂度低;缺点是处理歧义词效果不佳。
|
||||
|
||||
第二种是**基于统计和机器学习**。这类分词基于人工标注的词性和统计特征,对中文进行建模。训练阶段,根据标注好的语料对模型参数进行估计。 在分词阶段再通过模型计算各种分词出现的概率,将概率最大的分词作为最终结果。常见的序列标注模型有**隐马尔科夫模型**(HMM,Hidden Markov Model)和**条件随机场**(CRF,Conditional Random Field),我们后面章节会讲到,这里我先不展开。
|
||||
|
||||
### 2.取词干和归一化
|
||||
|
||||
我们刚才说了,相对中文而言,英文完全不需要考虑分词。不过它也有中文不具有的单复数、各种时态,因此它需要考虑**取词干**(stemming)。取词干的目标就是为了减少词的变化形式,将派生词转化为基本形式,就像下面这样:
|
||||
|
||||
```
|
||||
将am,is,are,was,were全部转换为be
|
||||
将car,cars,car’s,cars’全部转换为car
|
||||
|
||||
```
|
||||
|
||||
最后,我们还要考虑大小写转化和多种拼写(例如color和colour)这样的统一化,我们把这种做法称为**归一化**。
|
||||
|
||||
### 3.停用词
|
||||
|
||||
无论何种语言,都会存在一些不影响(或基本不影响)相关性的词。有的时候干脆可以指定一个叫**停用词**(stop word)的字典,直接将这些词过滤,不予以考虑。例如英文中的a、an、the、that、is、good、bad等。中文“的、个、你、我、他、好、坏”等。
|
||||
|
||||
如此一来,我们可以在基本不损失语义的情况下,减少数据文件的大小,提高计算机处理的效率。当然,也要注意停用词的使用场景,例如用户观点分析,good和bad这样的形容词反而成为了关键。不仅不能过滤,反而要加大它们的权重。
|
||||
|
||||
### 4.同义词和扩展词
|
||||
|
||||
不同的地域或者不同时代,会导致人们对于同样的物品叫法也不同。例如,在中国北方“番茄“应该叫“西红柿”,而台湾地区将“菠萝”称为“凤梨”。对于计算机而言,需要意识到这两个词是等价的。添加同义词就是一个很好的手段。我们可以维护如下一个同义词的词典:
|
||||
|
||||
```
|
||||
番茄,西红柿
|
||||
菠萝,凤梨
|
||||
洋山芋,土豆
|
||||
泡面,方便面,速食面,快餐面
|
||||
山芋,红薯
|
||||
鼠标,滑鼠
|
||||
……
|
||||
|
||||
```
|
||||
|
||||
有了这样的词典,当看到文本中出现“番茄”关键词的时候,计算机系统就会将其等同于“西红柿”这个词。有的时候我们还需要扩展词。如果简单地将Dove分别和多芬、德芙简单地等价,那么多芬和德芙这两个完全不同的品牌也变成了同义词,这样做明显是有问题的。那么我们可以采用扩展关系,当系统看到文本中的“多芬”时将其等同于“Dove”,看到“德芙”时将其等同于“Dove”。但是看到“Dove”的时候并不将其等同于“多芬”或“德芙”。
|
||||
|
||||
通过词包模型的假设,以及上述这些自然语言处理的方法,我们可以将整篇的文字,切分为一个个的单词,这些是表示文章的关键属性。你不难发现,每个单词可以作为文章的属性,而通过这些单词的词频(出现的频率),我们很容易进行概率的统计。下面我对分类的先验概率、单词的先验概率、某个分类下某个单词的条件概率分别给出了示例。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/20/90/204896aa4fd777102d579764cbf08d90.png" alt=""><img src="https://static001.geekbang.org/resource/image/83/f3/83baf008f9888a6afb6ec5720270aaf3.png" alt=""><img src="https://static001.geekbang.org/resource/image/7e/77/7ed70239e88b4fffaaa7d26e93305877.png" alt="">
|
||||
|
||||
在上表中,你会发现某些单词从未在某个分类中出现,例如“航母”这个词从未在“体育”和“娱乐”这两个分类中出现。对于这种情况,我们可以使用**平滑**(smoothing)的技术,将其词频或条件概率设置为一个极小的值。这里,我设置了最小的词频,也就是1。
|
||||
|
||||
有了这些单词属性以及相应的概率统计,下一步就是如何使用朴素贝叶斯模型进行文本的分类了。
|
||||
|
||||
## 运用朴素贝叶斯模型
|
||||
|
||||
首先我们先来回顾下,上一节推导的朴素贝叶斯公式。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/51/32/51a8c96cd9a8ae06acdff25a87438332.png" alt="">
|
||||
|
||||
在新闻分类中,**o**就表示一篇文章,而**c**表示新闻的种类(包括政治、军事、财经等等)。而属性字段**f**就是我们从文档集而建立的各种单词。公式等号左边的**P(c|f)**就是待分类新闻中,出现单词f时,该新闻属于类别c的概率。而等号右边的P(f|c)是根据训练数据统计,得到分类c中出现单词f的概率。P( c )是分类c在新闻训练数据中出现的概率,P(f)是单词f在训练样本中出现的概率。
|
||||
|
||||
我们用刚才表格中的数据来计算下“中国航母”这个短语属于每个分类的概率。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/dc/ef/dc38e39930981fd69a4021a4b9fda4ef.png" alt=""><img src="https://static001.geekbang.org/resource/image/1b/d1/1b0c4ffb16a1cca9f3a3f211a7a69dd1.png" alt=""><img src="https://static001.geekbang.org/resource/image/24/8d/24420c243fe5c2f439654596be6f2c8d.png" alt=""><img src="https://static001.geekbang.org/resource/image/f4/5a/f4bc1a5f6737296e49385ae9c809465a.png" alt=""><img src="https://static001.geekbang.org/resource/image/ad/91/ad93545cdbf0214e81ac589e17d60491.png" alt="">
|
||||
|
||||
可以看出来,“中国航母”这个短语本身属于“政治”和“军事”分类的可能性最高,而属于“财经”的可能性最低。需要注意的是,我在上述公式使用了中文词便于你的理解,在真正的实现中,我们需要将中文词和中文分类名称转换为数字型的ID,以提高系统的效率。
|
||||
|
||||
当然,一篇文章所包含的不同的单词数量要远远大于2个,之前如果我们只看“中国航母”这个短语,那么它属于“政治”和“军事”的概率基本一致。如果我们考虑更长的文章(也就是更多的单词),那么这个情况也许就会发生变化。为了支持更多的单词,我们将上述公式扩展为:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/92/1e/929ef79bdb208063ad744c285e51231e.png" alt="">
|
||||
|
||||
这里需要注意一个很实际的问题:文章的篇幅很长,常常会导致非常多的P(f|c)连续乘积。而P(f|c)通常是非常小的数值,因此最后的乘积将快速趋近于0以至于计算机无法识别。这里可以使用我们之前提到的一些数学手法进行转换,比如取log,将小数转换为绝对值大于1的负数。这样的转换,虽然会改变每篇文章属于每个分类的概率之绝对值,但是并不会改变这些概率的相对大小。
|
||||
|
||||
## 总结
|
||||
|
||||
在这一讲中,我讲了一个文本分类系统的几个关键步骤,其中最重要的是自然语言的处理和分类模型的训练和预测。
|
||||
|
||||
自然语言的处理是关键的预处理步骤,它将文本转换成计算机所能处理的数据。常见方法包括中文分词,英文的取词干和归一化,还有适用于各种语言的停用词、同义词和扩展词等。如果不考虑这些词出现的先后顺序,以及表达的深层次语义,那么我们就可以使用词包的方法,将大段的文章和语句转化成单词所组成的集合。之后,我们就能统计每个单词属于每个分类的条件概率,以及分类和单词的先验概率。
|
||||
|
||||
一旦将文章表示为单词的集合,我们就会发现,朴素贝叶斯的模型非常适合文章的分类。因为所有单词出现的词频都是离散值,非常适合统计概率。此外,许多新闻之类的文章本身也是跨了多个领域,因此有可能属于多个分类,朴素贝叶斯也能支持这点。我们针对“中国航母”这个短语进行了测试,发现其属于“政治”和“军事”分类的可能性最高。不过要注意的是,文章可能包含非常多的单词,朴素贝叶斯模型中的连续乘积会导致过小的值,甚至计算机都无法处理。为了避免这种情况,我们可以使用log的数学变换。
|
||||
|
||||
## 思考题
|
||||
|
||||
你也许已经通过“中国航母”这个简单的例子,见识到了计算机自动分类的神奇功效。使用同样的分类模型和概率分布,你能否计算一下“美国电影”属于政治、军事、财经、体育和娱乐分类的概率,分别是多少?
|
||||
|
||||
欢迎留言和我分享,也欢迎你在留言区写下今天的学习笔记。你可以点击“请朋友读”,把今天的内容分享给你的好友,和他一起精进。
|
||||
|
||||
|
||||
153
极客时间专栏/程序员的数学基础课/概率统计篇/24 | 语言模型:如何使用链式法则和马尔科夫假设简化概率模型?.md
Normal file
153
极客时间专栏/程序员的数学基础课/概率统计篇/24 | 语言模型:如何使用链式法则和马尔科夫假设简化概率模型?.md
Normal file
@@ -0,0 +1,153 @@
|
||||
<audio id="audio" title="24 | 语言模型:如何使用链式法则和马尔科夫假设简化概率模型?" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/20/fc/207b007240e15cf081d84c73e79f67fc.mp3"></audio>
|
||||
|
||||
你好,我是黄申。
|
||||
|
||||
之前我给你介绍了用于分类的朴素贝叶斯算法。我们讲了,朴素贝叶斯算法可以利用贝叶斯定理和变量之间的独立性,预测一篇文章属于某个分类的概率。除了朴素贝叶斯分类,概率的知识还广泛地运用在其他机器学习算法中,例如语言模型、马尔科夫模型、决策树等等。
|
||||
|
||||
今天我就来说说,基于概率和统计的语言模型。语言模型在不同的领域、不同的学派都有不同的定义和实现,因此为了避免歧义,我这里先说明一下,我们谈到的语言模型,都是指基于概率和统计的模型。
|
||||
|
||||
## 语言模型是什么?
|
||||
|
||||
在解释语言模型之前,我们先来看两个重要的概念。第一个是链式法则,第二个是马尔科夫假设及其对应的多元文法模型。为什么要先说这两个概念呢?这是因为链式法则可以把联合概率转化为条件概率,而马尔科夫假设通过变量间的独立性来减少条件概率中的随机变量,两者结合就可以大幅简化计算的复杂度。
|
||||
|
||||
### 1.链式法则
|
||||
|
||||
链式法则是概率论中一个常用法则。它使用一系列条件概念率和边缘概率,来推导联合概率,我用一个公式来给你看看它的具体表现形式。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/de/0c/de5d37d9392a18225b4f9d522b4f180c.png" alt="">
|
||||
|
||||
其中,$x_{1}$到$x_{n}$表示了n个随机变量。
|
||||
|
||||
这个公式是怎么来的呢?你还记得联合概率、条件概率和边缘概率之间的“三角”关系吗?我们用这三者的关系来推导一下,最终我们可以得到链式法则。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/35/a2/35bbc4bd80d8fba7bd6a63c1cdbd86a2.png" alt="">
|
||||
|
||||
推导的每一步,都是使用了三种概率之间的关系,这个应该不难理解。
|
||||
|
||||
### 2.马尔科夫假设
|
||||
|
||||
理解了链式法则,我们再来看看马尔可夫假设。这个假设的内容是:任何一个词$w_{i}$出现的概率只和它前面的1个或若干个词有关。基于这个假设,我们可以提出**多元文法(Ngram)模型**。Ngram中的“N”很重要,它表示任何一个词出现的概率,只和它前面的N-1个词有关。
|
||||
|
||||
我以二元文法模型为例,来给你解释。按照刚才的说法,二元文法表示,某个单词出现的概率只和它前面的1个单词有关。也就是说,即使某个单词出现在一个很长的句子中,我们也只需要看前面那1个单词。用公式来表示出来就是这样:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/b0/e9/b0bc4bb97ba4b233e0ae9db0291059e9.png" alt="">
|
||||
|
||||
如果是三元文法,就说明某个单词出现的概率只和它前面的2个单词有关。即使某个单词出现在很长的一个句子中,它也只看相邻的前2个单词。用公式来表达就是这样:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/a6/94/a619504d5c698f0c519904cd6eddf094.png" alt="">
|
||||
|
||||
你也许会好奇,那么一元文法呢?按照字面的意思,就是每个单词出现的概率和前面0个单词有关。这其实说明,每个词的出现都是相互独立的。用公式来表达就是这样的:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/52/25/523ff06450418d4d91d8e6d2756e1025.png" alt="">
|
||||
|
||||
弄明白链式法则和马尔科夫假设之后,我们现在来看语言模型。
|
||||
|
||||
假设我们有一个统计样本文本$d$,$s$表示某个有意义的句子,由一连串按照特定顺序排列的词$w_{1},w_{2},…,w_{n}$组成,这里$n$是句子里单词的数量。现在,我们想知道根据文档d的统计数据,$s$在文本中出现的可能性,即$P(s|d)$,那么我们可以把它表示为$P(s|d)=P(w_{1}, w_{2}, …, w_{n} | d$)。假设我们这里考虑的都是在集合d的情况下发生的概率,所以可以忽略$d$,写为$P(s)=P(w_{1}, w_{2}, …, w_{n})$。
|
||||
|
||||
到这里,我们碰到了第一个难题,就是如何计算$P(w_{1}, w_{2}, …, w_{n})$要在集合中找到一模一样的句子,基本是不可能的。这个时候,我们就需要使用链式法则。我们可以把这个式子改写为:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/2f/23/2fe51ac1be8efbad2082627860aada23.png" alt="">
|
||||
|
||||
咋一看,问题似乎是解决了。因为通过文档集合C,你可以知道$P(w_{1})$,$P(w_{2}|w_{1})$这种概率。不过,再往后看,好像$P(w_{3}|w_{1},w_{2})$出现概率很低,$P(w_{4}|w_{1},w_{2},w_{3})$出现的概率就更低了。一直到$P(w_{n}|w_{1}, w_{2}, …, w_{n-1})$,基本上又为0了。我们可以使用上一节提到的平滑技巧,减少0概率的出现。不过,如果太多的概率都是通过平滑的方式而得到的,那么模型和真实的数据分布之间的差距就会加大,最终预测的效果也会很差,所以平滑也不是解决0概率的最终办法。
|
||||
|
||||
除此之外,$P(w_{1}, w_{2}, …, w_{n})和P(w_{n}|w_{1}, w_{2}, …, w_{n-1})$还不只会导致0概率,它还会使得模型存储空间的急速增加。
|
||||
|
||||
为了统计现有文档集合中$P(w_{1}, w_{2}, …, w_{n})$这类值,我们就需要生成很多的计数器。我们假设文档集合中有m个不同的单词,那么从中挑出$n$个单词的可重复排列,数量就是$m^{n}$。此外,还有$m^{n-1}$, $m^{n-2}$等等。这也意味着,如果要统计并存储的所有$P(w_{1}, w_{2}, …, w_{n})$或$P(w_{n}|w_{1}, w_{2}, …, w_{n-1})$这类概率,就需要大量的内存和磁盘空间。当然,你可以做一些简化,不考虑单词出现的顺序,那么问题就变成了可重复组合,但是数量仍然非常巨大。
|
||||
|
||||
如何解决0概率和高复杂度的问题呢?马尔科夫假设和多元文法模型能帮上大忙了。如果我们使用三元文法模型,上述公式可以改写为:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/6d/b1/6dfe1f3c267787677090a611fee964b1.png" alt="">
|
||||
|
||||
这样,系统的复杂度大致在(C(m, 1) + C(m, 2) + C(m, 3))这个数量级,而且$P(w_{n}|w_{n-2}, w_{n-1})$为0的概率也会大大低于$P(w_{n}|w_{1}, w_{2}, …, w_{n-1})$ (其中$n>>3$)为0的概率。当然,多元文法模型中的N还是不能太大。随着N的增大,系统复杂度仍然会快递升高,就无法体现出多元文法的优势了。
|
||||
|
||||
## 语言模型的应用
|
||||
|
||||
基于概率的语言模型,本身不是新兴的技术。它已经在机器翻译、语音识别和中文分词中得到了成功应用。近几年来,人们也开始在信息检索领域中尝试语言模型。下面我就来讲讲语言模型在信息检索和中文分词这两个方面里是如何发挥作用的。
|
||||
|
||||
### 1.信息检索
|
||||
|
||||
信息检索很关心的一个问题就是相关性,也就是说,给定一个查询,哪篇文档是更相关的呢?为了解决相关性问题,布尔模型和向量空间检索模型都是从查询的角度出发,观察查询和文档之间的相似程度,并以此来决定如何找出相关的文档。这里的“相似程度”,你可以理解为两者长得有多像。那么,语言模型如何来刻画查询和文档之间的相关度呢?
|
||||
|
||||
它不再使用相似度定义,而是采用了概率。一种常见的做法是计算$P(d|q)$,其中$q$表示一个查询,$d$表示一篇文档。$P(d|q)$表示用户输入查询$q$的情况下,文档$d$出现的概率是多少?如果这个概率越高,我们就认为$q$和$d$之间的相关性越高。
|
||||
|
||||
通过我们手头的文档集合,并不能直接获得$P(d|q)$。好在我们已经学习过了贝叶斯定理,通过这个定理,我们可以将$P(d|q)$重写如下:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/de/67/de8d794df4e2758063f5ffb26546c467.png" alt="">
|
||||
|
||||
对于同一个查询,其出现概率$P(q)$都是相同的,同一个文档$d$的出现概率$P(d)$也是固定的。因此它们可以忽略,我们只要关注如何计算$P(q|d)$。而语言模型,为我们解决了如何计算$P(q|d)$的问题,让$k_{1}, k_{2}, …, k_{n}$表示查询q里包含的$n$个关键词。那么根据之前的链式法则公式,可以重写为这样:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/d7/66/d78ba0db38a575269eff4f6cb89afa66.png" alt="">
|
||||
|
||||
为了提升效率,我们也使用马尔科夫假设和多元文法。假设是三元文法,那么我们可以写成这样:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/e9/13/e977fb4b682e67a8693f1b76f1febe13.png" alt="">
|
||||
|
||||
最终,当用户输入一个查询$q$之后,对于每一篇文档$d$,我们都能获得$P(d|q)$的值。根据每篇文档所获得的$P(d|q)$这个值,由高到低对所有的文档进行排序。这就是语言模型在信息检索中的常见用法。
|
||||
|
||||
### 2.中文分词
|
||||
|
||||
和拉丁语系不同,中文存在分词的问题。如果想进行分词,你就可以实用语言模型。我举个例子给你解释一下,你就明白了。
|
||||
|
||||
最普遍的分词方法之一是基于常用词的词典。如果一个尚未分词的句子里发现了存在于字典里的词,我们就认为找到一个新的词,并把它切分出来。这种切分不会出现完全离谱的结果,但是无法解决某些歧义。我下面来举个例子,原句是“兵乓球拍卖完了”。我在读的时候,会有所停顿,你就能理解分词应该如何进行。可是,仅仅从书面来看,至少有以下几种分词方式:
|
||||
|
||||
```
|
||||
第一种,兵乓|球|拍卖|完了
|
||||
第二种,兵乓球|拍卖|完了
|
||||
第三种,兵乓|球拍|卖完|了
|
||||
第四种,兵乓|球拍|卖|完了
|
||||
|
||||
```
|
||||
|
||||
上面分词的例子,从字面来看都是合理的,所以这种歧义无法通过这句话本身来解决。那么这种情况下,语言模型能为我们做什么呢?我们知道,语言模型是基于大量的语料来统计的,所以我们可以使用这个模型来估算,哪种情况更合理。
|
||||
|
||||
假设整个文档集合是D,要分词的句子是$s$,分词结果为$w_{1}$, … $w_{n}$,那么我们可以求$P(s)$的概率为:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/c7/34/c74b222e54b6c2a9a6385a988896f334.png" alt="">
|
||||
|
||||
请注意,在信息检索中,我们关心的是每篇文章产生一个句子(也就是查询)的概率,而这里可以是整个文档集合D产生一个句子的概率。
|
||||
|
||||
根据链式法则和三元文法模型,那么上面的式子可以重写为:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/d4/be/d4cfe338d5aed842cd1b366008a551be.png" alt="">
|
||||
|
||||
也就是说,语言模型可以帮我们估计某种分词结果,在文档集合中出现的概率。但是由于不同的分词方法,会导致$w_{1}$到$w_{n}$的不同,因此就会产生不同的$P(s)$。接下来,我们只要取最大的$P(s)$,并假设这种分词方式是最合理的,就可以在一定程度上解决歧义。我们可以使用这个公式来求解:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/1c/dc/1cfeaeb018f38f86c448b57b61525adc.png" alt="">
|
||||
|
||||
其中,$W_{i}$表示第$i$种分词方法。
|
||||
|
||||
回到“兵乓球拍卖完了”这句话,如果文档集合都是讲述的有关体育用品的销售,而不是拍卖行,那么“兵乓|球拍|卖完|了”这种分词的可能性应该更高。
|
||||
|
||||
## 小结
|
||||
|
||||
这一节,我介绍了基于概率论的语言模型,以及它在信息检索和中文分词领域中的应用。这一节的公式比较多,你刚开始看可能觉得有点犯晕。不用急,我给你梳理了几个要点,你只要掌握这几个要点,依次再进行细节学习,就会事半功倍。
|
||||
|
||||
第一,使用联合概率,条件概率和边缘概率的“三角”关系,进行相互推导。链式法则就是很好的体现。
|
||||
|
||||
第二,使用马尔科夫假设,把受较多随机变量影响的条件概率,简化为受较少随机变量影响的条件概率,甚至是边缘概率。
|
||||
|
||||
第三,使用贝叶斯定理,通过先验概率推导后验概率。在信息检索中,给定查询的情况下推导文档的概率,就需要用到这个定理。
|
||||
|
||||
如果你记住了这几点,那么不仅能很快的理解本篇的内容,还能根据实际需求,设计出满足自己需要的语言模型。
|
||||
|
||||
## 思考题
|
||||
|
||||
在中文分词的时候,我们也可以考虑文章的分类。比如,这样一句话“使用纯净水源浇灌的大米”,正确的切分应该是:
|
||||
|
||||
```
|
||||
使用|纯净|水源|浇灌|的|大米
|
||||
|
||||
```
|
||||
|
||||
如果我们知道这句描述来自于“大米”类商品,而不是“纯净水”类商品,那么就不会错误地切分为:
|
||||
|
||||
```
|
||||
使用|纯净水|源|浇灌|的|大米
|
||||
|
||||
```
|
||||
|
||||
想想看,如何对我介绍的语言模型加以改进,把分类信息也包含进去?
|
||||
|
||||
欢迎留言和我分享,也欢迎你在留言区写下今天的学习笔记。你可以点击“请朋友读”,把今天的内容分享给你的好友,和他一起精进。
|
||||
|
||||
|
||||
121
极客时间专栏/程序员的数学基础课/概率统计篇/25 | 马尔科夫模型:从PageRank到语音识别,背后是什么模型在支撑?.md
Normal file
121
极客时间专栏/程序员的数学基础课/概率统计篇/25 | 马尔科夫模型:从PageRank到语音识别,背后是什么模型在支撑?.md
Normal file
@@ -0,0 +1,121 @@
|
||||
<audio id="audio" title="25 | 马尔科夫模型:从PageRank到语音识别,背后是什么模型在支撑?" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/70/f8/70f1f6dd08c67ab0af19e4ea416453f8.mp3"></audio>
|
||||
|
||||
你好,我是黄申。
|
||||
|
||||
上一节,我们介绍了基于概率的语言模型。概率语言模型的研究对象其实是一个词的序列,以及这个词序列出现的概率有多大。那语言模型是不是也可以用于估算其他序列出现的概率呢?答案是肯定的。
|
||||
|
||||
通过上一节我们知道,语言模型中有个重点:马尔科夫假设及对应的多元文法模型。如果我们把这一点进一步泛化,就能引出马尔科夫模型。也就是说,只要序列的每个状态之间存在转移的概率,那么我们就可以使用马尔科夫模型。有时候情况会更复杂,不仅每个状态之间的转移是按照一定概率进行的,就连每个状态本身也是按照一定概率分布出现的,那么还需要用到隐马尔科夫模型。
|
||||
|
||||
今天这一节,我们就来学习马尔科夫模型、隐马尔科夫模型,以及它们在PageRank和语音识别中的应用。
|
||||
|
||||
## 马尔科夫模型
|
||||
|
||||
在介绍语言模型的时候,我们提到了马尔科夫假设,这个假设是说,每个词出现的概率和之前的一个或若干个词有关。我们换个角度思考就是,**每个词按照一定的概率转移到下一个词**。怎么个转移呢?我来解释一下。
|
||||
|
||||
如果把词抽象为一个状态,那么我们就可以认为,状态到状态之间是有关联的。前一个状态有一定的概率可以转移到到下一个状态。如果多个状态之间的随机转移满足马尔科夫假设,那么这类随机过程就是一个马尔科夫随机过程。而刻画这类随机过程的统计模型,就是**马尔科夫模型**(Markov Model)。
|
||||
|
||||
前面讲多元文法的时候,我提到了二元文法、三元文法。对于二元文法来说,某个词出现的概率只和前一个词有关。对应的,在马尔科夫模型中,如果一个状态出现的概率只和前一个状态有关,那么我们称它为**一阶马尔科夫模型**或者**马尔科夫链**。对应于三元、四元甚至更多元的文法,我们也有二阶、三阶等马尔科夫模型。
|
||||
|
||||
我们先从最简单的**马尔科夫模型-马尔科夫链**开始看。我画了一张示意图,方便你理解马尔科夫链中各个状态的转移过程。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/90/b9/90537ae6b49b65b154d2084e6e8385b9.jpg" alt="">
|
||||
|
||||
在这张图中,你可以看到,从状态A到B的概率是0.1,从状态B到状态C的概率是0.2等等。我们也可以使用状态转移表来表示这张图。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/10/44/108c8b522bd4ff6d1793230260c2c644.png" alt="">
|
||||
|
||||
我们可以根据某个应用的需要,把上述状态转移表具体化。例如,对于语言模型中的二元文法模型,我这里列出了一个示意表。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/90/f4/90796185dff6955b48cb300ea11839f4.png" alt="">
|
||||
|
||||
当然,除了二元文法模型,马尔科夫链还有很多应用的场景。
|
||||
|
||||
Google公司最引以为傲的PageRank链接分析算法,它的核心思想就是基于马尔科夫链。这个算法假设了一个“随机冲浪者”模型,冲浪者从某张网页出发,根据Web图中的链接关系随机访问。在每个步骤中,冲浪者都会从当前网页的链出网页中随机选取一张作为下一步访问的目标。在整个Web图中,绝大部分网页节点都会有链入和链出。那么冲浪者就可以永不停歇地冲浪,持续在图中走下去。
|
||||
|
||||
在随机访问的过程中,越是被频繁访问的链接,越是重要。可以看出,每个节点的PageRank值取决于Web图的链接结构。假如一个页面节点有很多的链入链接,或者是链入的网页有较高的被访问率,那么它也将会有更高的被访问概率。
|
||||
|
||||
那么,PageRank的公式和马尔科夫链有什么关系呢?我先给你看一张Web的拓扑图。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/84/bf/842598a61f0edc622552544603dbe9bf.jpg" alt="">
|
||||
|
||||
其中A、B、C等结点分别代表了页面,而结点之间的有向边代表了页面之间的超链接。看了这张图中,你是不是觉得Web拓扑图和马尔科夫链的模型图基本上是一致的?我们可以假设每张网页就是一个状态,而网页之间的链接表明了状态转移的方向。这样,我们很自然地就可以使用马尔科夫链来刻画“随机冲浪者”。
|
||||
|
||||
另外,在最基本的PageRank算法中,我们可以假设每张网页的出度是$n$,那么从这张网页转移到任何下一张相连网页的概率都是$\frac{1}{n}$,因此这个转移的概率只和当前页面有关,满足一阶马尔科夫模型的假设。我在之前的拓扑结构中添加了转移的概率。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/ea/5d/ea12a997c4dff97a31991021860d0c5d.jpg" alt="">
|
||||
|
||||
PageRank在标准的马尔科夫链上,引入了随机的跳转操作,也就是假设冲浪者不按照Web图的拓扑结构走下去,只是随机挑选了一张网页进行跳转。这样的处理是类比人们打开一张新网页的行为,也是符合实际情况的,避免了信息孤岛的形成。最终,根据马尔科夫链的状态转移和随机跳转,可以得到如下的PageRank公式。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/9a/b2/9afb3366f6b4d4c9aeeebc7e59e96bb2.png" alt="">
|
||||
|
||||
其中,$p_{i}$表示第$i$张网页,$M_{i}$是$p_{i}$的入链接集合,$p_{j}$是$M_{i}$集合中的第$j$张网页。$PR_{(p_{j})}$表示网页$p_{j}$的PageRank得分,$L_{(p_{j})}$表示网页$p_{j}$的出链接数量,$\frac{1}{L_{(p_{j})}}$就表示从网页$p_{j}$跳转到$p_{i}$的概率。$α$是用户不进行随机跳转的概率,$N$表示所有网页的数量。
|
||||
|
||||
从最简单的马尔科夫链,到多阶的马尔科夫模型,它们都可以刻画基于马尔科夫假设的随机过程,例如概率语言模型中的多元文法和PageRank这类链接分析算法。但是,这些模型都是假设每个状态对我们都是已知的,比如在概率语言模型中,一个状态对应了单词“上学”,另一个状态对应了单词“书包”。可是,有没有可能某些状态我们是未知的呢?下面我们就来详细说说这种情况。
|
||||
|
||||
## 隐马尔科夫模型
|
||||
|
||||
在某些现实的应用场景中,我们是无法确定马尔科夫过程中某个状态的取值的。这种情况下,最经典的案例就是语音识别。使用概率对语音进行识别的过程,和语言模型类似,因此我们可以把每个等待识别的词对应为马尔科夫过程中的一个状态。不过,语音识别所面临的困难更大。为什么呢?你先看看下面这个句子。这个句子里全都是拼音,你能看出它表示什么意思吗?
|
||||
|
||||
```
|
||||
ni(三声) zhi(一声) dao(四声) wo(三声) zai(四声) deng(三声) ni(三声) ma(一声)
|
||||
|
||||
```
|
||||
|
||||
中国有句古话说得好,“白纸黑字”,写在文档里的文字对于计算机是确定的,“嘛”“吗” “妈”不会弄错。可是,如果你说一句“你知道我在等你吗”,听众可能一直弄不明白为什么要等别人的妈妈,除非你给他们看到文字版的内容,证明最后一个字是口字旁的“吗”。另外,再加上各种地方的口音、唱歌的发音或者不标准的拼读,情况就更糟糕了。
|
||||
|
||||
计算机只知道某个词的发音,而不知道它具体怎么写,对于这种情况,我们就认为计算机只能观测到每个状态的部分信息,而另外一些信息被“隐藏”了起来。这个时候,我们就需要用隐马尔科夫模型来解决这种问题。隐马尔科夫模型有两层,一层是我们可以观测到的数据,称为“输出层”,另一层则是我们无法直接观测到的状态,称为“隐藏状态层”。我画了一张图方便你理解。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/77/75/77593998432b6290808a80c63b830f75.jpg" alt="">
|
||||
|
||||
其中,$x_{1},x_{2},x_{3}$等等属于隐藏状态层,$a_{12}$表示了从状态$x_{1}$到$x_{2}$的转移概率,$a_{23}$表示了从状态$x_{2}$到$x_{3}$的转移概率。这一层和普通的马尔科夫模型是一致的,可惜在隐马尔科夫模型中我们无法通过数据直接观测到这一层。我们所能看到的是,$y_{1},y_{2},y_{3}$等等代表的“输出层”。另外,$b_{11}$表示了从状态$x_{1}$到$y_{1}$的输出概率,$b_{22}$表示了从状态$x_{2}$到$y_{2}$的输出概率,$b_{33}$表示了从状态$x_{3}$到$y_{3}$的输出概率等等。
|
||||
|
||||
那么在这个两层模型示例中,“隐藏状态层”产生“输出层”的概率是多少呢?这是一系列条件概率决定的,具体的公式我列在这里。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/80/7a/80bd25ad15e9d852cbea8b4ef1f4a67a.png" alt="">
|
||||
|
||||
如果你觉得这个两层的模型不太好理解,我来给你说个浅显易懂的例子。假设正在进行普通话语音识别,计算机接受了一个词组的发音。我在下面列出了它的拼音。
|
||||
|
||||
```
|
||||
xiang(四声)mu(四声) kai(一声)fa(一声) shi(四声)jian(四声)
|
||||
|
||||
```
|
||||
|
||||
假设根据我们手头上的语料数据,这个词组有多种可能,我列出两种。
|
||||
|
||||
### 第一种情况
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/f7/88/f7df10338a0fda0fbecc9046fc6ea388.jpg" alt="">
|
||||
|
||||
第一种情况下,三个确定的状态是“项目”“开发”和“时间”这三个词。从“项目”转移到“开发”的概率是0.25,从“开发”转移到“时间”的概率是0.3。从“项目”输出“xiang(三声)mu(四声)”的概率是0.1,输出”xiang(四声)mu(四声)”的概率是0.8,输出“xiang(四声)mu(一声)”的概率是0.1,“开发”和“时间”也有类似的输出概率。
|
||||
|
||||
这个时候你可能会奇怪,“项目”的普通话发音就是“xiang(四声)mu(四声)”,为什么还会输出其他的发音呢?这是因为,前面说的这些概率都是通过历史语料的数据统计而来。在进行语音识别的时候,我们会通过不同地区、不同性别、不同年龄等等的人群,采集发音的样本。如此一来,影响这个发音的因素就很多了,比如方言、口音、误读等等。当然,在正常情况下,大部分的发音还是标准的,所以“项目”这个词输出到“xiang(四声)mu(四声)”的概率是最高的。
|
||||
|
||||
好,有了这些概率的分布,我们来看看“项目开发时间”这个词组最后生成的概率是多少。在两层模型的条件概率公式中,我代入了具体的概率值并使用了如下的推导:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/7f/f4/7fd2cf482bbd849ff0dfb64d90e3a9f4.png" alt="">
|
||||
|
||||
### 第二种情况
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/d9/01/d9e15463a4a6d6e227f614da19d2c601.jpg" alt="">
|
||||
|
||||
在第二种的可能性中,三个确定的状态是“橡木”“开发”和“事件”这三个词。从“橡木”转移到"开发"的概率是0.015,从“开发”转移到“事件”的概率是0.05。从“橡木”输出“xiang(一声)mu(四声)”的概率是0.2,输出“xiang(四声)mu(四声)”的概率是0.8,“开发”和“事件”也有类似的输出概率。和第一种情况类似,我们可以计算“橡木开发事件”这个词组最后生成的概率是多少,我用下面这个公式来推导:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/c9/07/c91f4ed6837cd11e6231c237a2ab9707.png" alt="">
|
||||
|
||||
最后比较第一种和第二种情况产生的概率,分别是P(项目)x0.0027和P(橡木)x0.000459。假设P(项目)和P(橡木)相等,那么“项目开发时间”这个词组的概率更高。所以“xiang(四声)mu(四声)kai(一声)fa(一声)shi(四声)jian(四声)”这组发音,计算机会识别为“项目开发时间”。从中我们可以看出,尽管“事件”这个词产生“shi(四声)jian(四声)”这个发音的可能性更高,但是“橡木开发事件”这个词组出现的概率极低,因此最终计算机还是选择了“项目开发时间”,隐藏的状态层起到了关键的作用。
|
||||
|
||||
## 总结
|
||||
|
||||
马尔科夫模型考虑了n个状态之间的转移及其对应的关系。这个状态是比较抽象的含义,在不同的应用领域代表不同的含义。在概率语言模型中,状态表示不同的词,状态之间的转移就代表了词按照一定的先后顺序出现。在PageRank这种链接分析中,状态表示不同的网页,状态之间的转移就代表了人们在不同网页之间的跳转。
|
||||
|
||||
在马尔科夫模型中,我们知道了每种状态及其之间转移的概率,然后求解序列出现的概率。然而,有些现实的场景更为复杂,比如说我们观测到的不是状态本身,而是状态按照一定概率分布所产生的输出。针对这种情况,隐马尔科夫模型提出了一种两层的模型,同时考虑了状态之间转移的概率和状态产生输出的概率,为语音识别、手写识别、机器翻译等提供了可行的解决方案。
|
||||
|
||||
隐马尔科夫模型需要回答的最主要问题是:给定一个模型和某个特定的输出序列,如何找到最可能产生这个输出的状态序列?在本节中,我使用了“项目开发时间”这个例子展示隐马尔科夫模型是如何工作的。不过这个例子很简单,我只比较了两种可能性。但是,实际中可能性是非常多的,如果我们使用穷举法,那么复杂度一定很高。
|
||||
|
||||
我们可以把两层的模型看作图结构。其中,状态和输出是结点,转移和输出关系是边,相应的概率是边的权重,这个时候我们就可以对Dijkstra算法稍加修改,来找出权重乘积最大的最优路径,提升查找的效率。我们还可以利用状态序列之间存在的先后关系,使用基于动态规划的维特比(Viterbi)算法来找出最优路径。
|
||||
|
||||
## 思考题
|
||||
|
||||
机器翻译会使用大量的语料,自动学习不同语言之间词和词的匹配。如果在机器翻译中使用隐马尔科夫进行建模,你认为“隐藏状态层”表示的是什么?“输出层”表示的又是什么?
|
||||
|
||||
欢迎留言和我分享,也欢迎你在留言区写下今天的学习笔记。你可以点击“请朋友读”,把今天的内容分享给你的好友,和他一起精进。
|
||||
113
极客时间专栏/程序员的数学基础课/概率统计篇/26 | 信息熵:如何通过几个问题,测出你对应的武侠人物?.md
Normal file
113
极客时间专栏/程序员的数学基础课/概率统计篇/26 | 信息熵:如何通过几个问题,测出你对应的武侠人物?.md
Normal file
@@ -0,0 +1,113 @@
|
||||
<audio id="audio" title="26 | 信息熵:如何通过几个问题,测出你对应的武侠人物?" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/c2/2c/c2bcc73f203ce00c6360ff0e4e205f2c.mp3"></audio>
|
||||
|
||||
你好,我是黄申。
|
||||
|
||||
之前和你聊了概率在朴素贝叶斯分类算法中的应用。其实,概率在很多像信息论这样的应用数学领域都有广泛的应用。信息论最初就是运用概率和统计的方法,来研究信息传递的。最近几十年,人们逐步开始使用信息论的概念和思想,来描述机器学习领域中的概率分布,并衡量概率分布之间的相似性。随之而来的是,人们发明了不少相关的机器学习算法。所以接下来的几节,我来介绍一些基于信息论知识的内容。
|
||||
|
||||
信息论的概念比较枯燥,为了让你更轻松地学习,让我从一个生动的案例开始。最近我在朋友圈看到一个小游戏,叫“测一测你是金庸笔下的哪个人物?”。玩这个游戏的步骤是,先做几道题,然后根据你的答案,生成对应的结果。下面是我几位朋友答题之后得到的结果。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/55/f1/55ea8faffde5fd7450518903b9d3f3f1.jpeg" alt="">
|
||||
|
||||
这种测试挺好玩的,而且好像有很多类似的,比如测星座啊、测运势啊等等。那你知道这种心理或者性格测试的题目是怎么设计的吗?
|
||||
|
||||
通常,这种心理测试会有一个题库,包含了许多小题目,也就是从不同的方面,来测试人的性格。不过,针对特定的测试目标,我们可能没必要让被测者回答所有的问题。那么,问卷设计者应该如何选择合适的题目,才能在读者回答尽量少的问题的同时,相对准确地测出自己是什么“性格”呢?这里,我们就需要引入基于概率分布的信息熵的概念,来解决这个问题。
|
||||
|
||||
## 什么是信息熵?
|
||||
|
||||
我还是拿刚刚那个“测测你是哪个武侠人物”的小游戏举例子。我设计了一个测试题,你可以看看下面这个图表。这个表里一共有10个人物。每个人物都有性别、智商、情商、侠义和个性共5个属性。相应地,我会设计5道题目分别测试这5个属性所占的比例。最后,将测出的5个属性和答案中的武侠人物对照,就可以找到最接近的答案,也就是被测者对应的武侠人物。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/40/93/40a23d486077a05edd6dd7f308fb1193.png" alt="">
|
||||
|
||||
这个过程非常简单,你应该很容易就能理解。在这个设计过程中,起决定性作用的环节其实就是,如何设计这5道题目。比如,题目的先后顺序会不会直接影响要回答问题的数量?每个问题在人物划分上,是否有着不同的区分能力?这些都是信息熵要解决的问题。
|
||||
|
||||
我们先来看,这里的**区分能力**指的是什么呢?每一个问题都会将被测试者划分为不同的人物分组。如果某个问题将属于不同人物分组的被测者,尽可能地划分到了相应的分组,那么我们认为这个问题的**区分能力较强。<strong>相反,如果某个问题无法将属于不同人物分组的被测者划分开来,那么我们认为这个问题的**区分能力较弱</strong>。为了帮你进一步理解,我们先来比较一下“性别”和“智商”这两个属性。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/8d/f3/8d79a177252ded1ca2bacc392e3471f3.png" alt=""><img src="https://static001.geekbang.org/resource/image/ca/0b/caf124bd2df93a642b2e83404562d60b.png" alt="">
|
||||
|
||||
首先,性别属性将武侠人物平均地划分为一半一半,也就是说“男”和“女”出现的先验概率是各50%。如果我们假设被测试的人群,其男女性别的概率分布也是50%和50%,那么关于性别的测试题,就能将被测者的群体大致等分。
|
||||
|
||||
我们再来看智商属性。我们也将武侠人物划分为2个小集合,不过“智商高”的先验概率是80%,而“智商中等”的先验概率只有20%。同样,我们假设被测试的人群,其智商的概率分布也是类似地,那么经过关于智商的测试题之后,仍然有80%左右的不同人物还是属于同一个集合,并没有被区分开来。因此,我们可以认为关于“智商”的测试题,在对人物进行分组这个问题上,其能力要弱于“性别”的测试题。
|
||||
|
||||
上述这些是不是都很简单?这些都是我们按照感觉,或者说经验来划分的。现在,我们试着用两个科学的度量指标,**信息熵**(Entropy)和**信息增益**(Information Gain),来衡量每道题目的区分能力。
|
||||
|
||||
首先,怎么来理解信息熵呢?信息熵,我们通常简称为熵,其实就是用来刻画给定集合的**纯净度**的一个指标。你可能要问了,那纯净度是啥呢?我举个例子给你解释一下。比如说,一个集合里的元素全部是属于同一个分组,这个时候就表示最纯净,我们就说熵为0;如果这个集合里的元素是来自不同的分组,那么熵是大于0的值。其具体的计算公式如下:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/f9/c0/f9da465b8601bb84b97022afd88cbac0.png" alt="">
|
||||
|
||||
其中,$n$表示集合中分组的数量,$p_{i}$表示属于第$i$个分组的元素在集合中出现的概率。
|
||||
|
||||
你可能要问了,这个公式是怎么来的呢?想要解释这个,我们还要从**信息量**说起。熵的公式是用来计算某个随机变量的信息量之期望,而信息量是信息论中的一个度量,简单来说就是,当我们观察到某个随机变量的具体值时,接收到了多少信息。而我们接收到的信息量跟发生事件的概率有关。事情发生的概率越大,产生的信息量越小;事情发生的概率越小,产生的信息量越大。
|
||||
|
||||
因此,我们想要设计一个能够描述信息量的函数,就要同时考虑到下面这三个特点:
|
||||
|
||||
<li>
|
||||
信息量应该为正数;
|
||||
</li>
|
||||
<li>
|
||||
一个事件的信息量和它发生的概率成反比;
|
||||
</li>
|
||||
<li>
|
||||
$H(x)$与$P(x)$的对数有关。其中$H(x)$表示$x$的信息量,$P(x)$表示$x$出现的概率。假设有两个不相关的事件$x$和$y$,我们观察到这两个事件同时发生时获得的信息量,应该等于这两个事件各自发生时获得的信息量之和,用公式表达出来就是$H(x,y)=H(x)+H(y)$。之前我们说过,如果$x,y$是两个不相关的事件,那么就有$P(x,y)=P(x)*P(y)$。
|
||||
</li>
|
||||
|
||||
依照上述这三点,我们可以设计出信息量公式:$H(x)=-log(P(x), 2)$。函数log的使用是体现了$H(x)$和$P(x)$的对数关系(我们可以使用其他大于1的数字作为对数的底,我这里使用2只是约定俗成。而最开始的负号是为了保证信息量为正)。这个公式可以量化随机变量某种取值时,所产生的信息量。最后,加上计算随机变量不同可能性所产生的信息量之期望,我们就得到了熵的公式。
|
||||
|
||||
从集合和分组的角度来说,如果一个集合里的元素趋向于落在同一分组里,那么告诉你某个元素属于哪个分组的信息量就越小,整个集合的熵也越小,换句话说,整个集合就越“纯净”。相反,如果一个集合里的元素趋向于分散在不同分组里,那么告诉你某个元素属于哪个分组的信息量就越大,整个集合的熵也越大,换句话说,整个集合就越“混乱”。
|
||||
|
||||
为了帮你理解运用,这里我再举几个例子帮助你更好地消化这个公式。我们首先来看一个集合,它只包含了来自A组的元素。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/f4/5e/f44a38aaf3b1685bd8532618dcd0b75e.png" alt="">
|
||||
|
||||
那么集合中分组的数量$n$为1,A分组的元素在集合中出现的概率为100%,所以这个集合的熵为-100%*log(100%, 2) = 0。
|
||||
|
||||
我们再来看另一个集合,它只包含了来自A组和B组的元素,其中A、B两组元素数量一样多,各占一半。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/9f/6d/9f05be8a2b461f376d8e22356c9df06d.png" alt="">
|
||||
|
||||
那么集合中分组的数量$n$为2,A和B分组的元素在集合中出现的概率各为50%,所以这个集合的熵为2*(-50%*log(50%, 2)) = 1,高于刚才那个集合。
|
||||
|
||||
从上述两个集合的对比可以看出,一个集合中所包含的分组越多、元素在这些分组里分布得越均匀,熵值也越大。而熵值表示了纯净的程度,或者从相反的角度来说,是混乱的程度。
|
||||
|
||||
好了,你已经知道单个集合的熵是如何计算的了。那么,如果将一个集合划分成多个更小的集合之后,又该如何根据这些小集合,来计算整体的熵呢?之前我们提到了信息量和熵具有加和的性质,所以对于包含多个集合的更大集合,它的信息量期望值是可以通过每个小集合的信息量期望值来推算的。具体来说,我们可以使用如下公式:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/cd/d3/cd8f5873383759df7782b37f125bb1d3.png" alt="">
|
||||
|
||||
其中,$T$表示一种划分,$P_{v}$表示划分后其中某个小集合,$Entropy(P_{v})$表示某个小集合的熵, 而$\frac{|Pv|} {|P|}$ 表示某个小集合出现的概率。所以这个公式其实就表示,**对于多个小集合而言,其整体的熵等于各个小集合之熵的加权平均**。而每个小集合的权重是其在整体中出现的概率。
|
||||
|
||||
我用个例子进一步解释这个公式。假设A、B、C三个集合是一个大的整体,我们现在将C组的元素和A、B组分开。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/9e/a3/9e2c0629e7ae441eb8b6cb234bb613a3.png" alt="">
|
||||
|
||||
根据之前单个集合的熵计算,A和B组元素所组成的小集合,它的熵是1。而C组没有和其他组混合,所形成的小集合其熵为0。在计算前两个小集合的整体熵时,A组和B组形成的集合出现的概率为$\frac{2}{3}$,而C组形成的集合出现概率为$\frac{1}{3}$,所有整体熵$=\frac{2}{3} * 1 + \frac{1}{3} * 0 = 0.67$。
|
||||
|
||||
## 什么是信息增益?
|
||||
|
||||
如果我们将划分前后的整体熵做个对比,你会发现划分后的整体熵要小于划分之前的整体熵。这是因为每次划分,都可能将不同分组的元素区分开来,降低划分后每个小集合的混乱程度,也就是降低它们的熵。我们将划分后整体熵的下降,称为**信息增益**(Information Gain)。如果划分后整体熵下降的越多,信息增益就越大。我列出公式便于你的理解。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/72/79/7268dcacc996164ba51a499db45de679.png" alt="">
|
||||
|
||||
其中T表示当前选择的特征,$Entropy§$表示选择特征$T$之前的熵,$Entropy(P_{v})$表示特征$T$取值为$v$分组的熵。减号后面的部分表示选择T做决策之后,各种取值加权平均后整体的熵。
|
||||
|
||||
$Gain(P,T)$表示两个熵值之差,越大表示信息增益越多,应该选择这维特征$T$。
|
||||
|
||||
我们把这个概念放到咱们的小游戏里就是,如果一个测试问题能够将来自不同分组的人物尽量的分开,也就是该划分对应的信息增益越高,那么我们就认为其区分能力越高,提供的信息含量也越多。好,说到这里,让我们从游戏的最开始出发,比较一下有关性别和智商的两个测试题。
|
||||
|
||||
在提出任何问题之前,我们无法知道被测者属于哪位武侠人物,因此所有被测者属于同一个集合。假设被测者的概率分布和这10位武侠人物的先验概率分布相同,那么被测者集合的熵为10*(-1 * 0.1 * log(0.1, 2))=3.32。
|
||||
|
||||
通过性别的测试问题对人物进行划分后,我们得到了两个更小的集合,每个小集合都包含5种不同的人物分组,因此每个小集合的熵是(-1 * 5 * 0.2 * log(0.2, 2)) = 2.32,两个小集合的整体熵是0.5 * 2.32 + 0.5 * 2.32 = 2.32。因此使用性别的测试题后,信息增益是3.32 - 2.32 = 1。
|
||||
|
||||
而通过智商的测试问题对人物分组后,我们也得到了两个小集合,一个包含了8种人物,另一个包含了2种人物。包含8种人物的小集合其熵是(-1* 8 * 0.125 * log(0.125, 2)) = 3,包含2种人物的小集合其熵是(-1* 2 * 0.5 * log(0.5, 2)) = 1。两个小集合的整体熵是0.8 * 3 + 0.2 * 1 = 2.6。因此使用智商的测试题后,信息增益是3.32 - 2.6 = 0.72,低于基于性别的测试。所以,我们可以得出结论,有关性别的测试题比有关智商的测试题更具有区分能力。
|
||||
|
||||
信息增益和信息熵是紧密相关的。如果说信息熵衡量了某个状态下,每个分组的纯净程度或者说混乱程度,那么信息增益就是比较了不同状态下,信息熵的差异程度。
|
||||
|
||||
## 总结
|
||||
|
||||
这一讲中,我们从一个有趣的人物性格测试开始,探讨了如何高效率地进行问卷调查。其中主要包含了两个要点:信息熵和信息增益。熵的计算是基于集合内各组元素分布的概率来进行的。而信息增益是集合划分前后整体熵的差值。对某个集合进行划分,都会将其中元素细分到更小的集合,而每个细分的集合纯净度就会提高,整体熵就会下降,其中下降的部分就是信息增益。
|
||||
|
||||
了解信息熵和信息增益的定义之后,我们可以用它们来安排测试问题的先后顺序。其核心的思路是,利用信息增益找出区分力最强的测试题。如果一道测试题可以将来自不同分组的元素分隔开来,那么就说它是有区分力的。如果分隔后,每个细分的集合其熵越趋近于0,那么我们说这个测试题的区分力越强。
|
||||
|
||||
## 思考题
|
||||
|
||||
假设一个集合包含了64个元素,而每个元素的分类都互不相同,那么这个集合的信息熵是多少?仔细观察一下你所计算的结果,和二进制有没有什么联系?
|
||||
|
||||
欢迎留言和我分享,也欢迎你在留言区写下今天的学习笔记。你可以点击“请朋友读”,把今天的内容分享给你的好友,和他一起精进。
|
||||
104
极客时间专栏/程序员的数学基础课/概率统计篇/27 | 决策树:信息增益、增益比率和基尼指数的运用.md
Normal file
104
极客时间专栏/程序员的数学基础课/概率统计篇/27 | 决策树:信息增益、增益比率和基尼指数的运用.md
Normal file
@@ -0,0 +1,104 @@
|
||||
<audio id="audio" title="27 | 决策树:信息增益、增益比率和基尼指数的运用" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/60/e3/60e7143bfe1f4be56eb8dd417894a0e3.mp3"></audio>
|
||||
|
||||
你好,我是黄申。
|
||||
|
||||
上一节,我通过问卷调查的案例,给你解释了信息熵和信息增益的概念。被测者们每次回答一道问题,就会被细分到不同的集合,每个细分的集合纯净度就会提高,而熵就会下降。在测试结束的时候,如果所有被测者都被分配到了相应的武侠人物名下,那么每个人物分组都是最纯净的,熵值都为0。于是,测试问卷的过程就转化为“如何将熵从3.32下降到0”的过程。
|
||||
|
||||
由于每道问题的区分能力不同,而我们对问题的选择会影响熵下降的幅度。这个幅度就是信息增益。如果问卷题的顺序选择得好,我们可以更快速地完成对用户性格的判定。这一节我们就继续这个话题,看看如何获得一个更简短的问卷设计,把这个核心思想推广到更为普遍的决策树分类算法中。
|
||||
|
||||
## 如何通过信息熵挑选合适的问题?
|
||||
|
||||
为了实现一个更简短的问卷,你也许很自然地就想到,每次选择问题的时候,我们可以选择信息增益最高的问题,这样熵值下降得就最快。这的确是个很好的方法。我们来试一试。
|
||||
|
||||
我们现在开始选择第一个问题。首先,依次计算“性别”“智商”“情商”“侠义”和“个性”对人物进行划分后的信息增益。我们得到如下结果:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/9f/11/9f135e031841f15012ed997a1dd30a11.png" alt="">
|
||||
|
||||
显然,第一步我们会选择“侠义”,之后用户就会被细分为3组。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/7c/42/7cd2a03c7b5fd5f6b94e69c89b70c142.png" alt=""><img src="https://static001.geekbang.org/resource/image/a1/b8/a12483f003569c79899c143d28c332b8.png" alt=""><img src="https://static001.geekbang.org/resource/image/09/10/0957e7645a48a21e9409886963270b10.png" alt="">
|
||||
|
||||
针对第一组,我们继续选择在当前这组中,区分力最强、也是就信息增益最高的问题。根据计算的结果我们应该选择有关“性别”的问题,然后进一步地细分。后续的步骤依次类推,直到所有人物都被分开,对于第二组和第三组我们也进行同样地操作。整个过程稍微有点复杂,为了帮你理解,我把它画成了一个图。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/9d/1c/9db1ccd4fd4aa2cd03d74f02811abb1c.png" alt="">
|
||||
|
||||
从这个图可以看出来,对于每种人物的判断,我们至多需要问3个问题,没有必要问全5个问题。比如,对于人物J和C,我们只需要问2个问题。假设读者属于10种武侠人物的概率是均等的,那么我们就可以利用之前介绍的知识,来计算读者需要回答的问题数量之期望值。每种人物出现的概率是0.1,8种人物需要问3个问题,2种人物需要问2个问题,那么回答问题数的期望值是0.8 * 3 + 0.2 * 2 = 2.8(题)。
|
||||
|
||||
如果我们每次不选熵值最高的问题,而选择熵值最低的问题呢?
|
||||
|
||||
我计算了一下,最差的情况下,我们要问完全部5个问题,才能确定被测者所对应的武侠人物。而且问4个问题的情况也不少,回答问题数的期望值会在4到5之间,明显要多于基于最高熵来选择题目的方法。当然,如果测试的目标和问题很多,基于熵的问题选择其运算量就会比较大,我们就可以通过编程来自动化整个过程,最终达到优化问卷设计的目的。
|
||||
|
||||
好了,现在我们总结一下,如何才能进行高效的问卷调查。最核心的思想是,根据当前的概率分布,挑选在当前阶段区分能力更强的那些问题。具体的步骤有三个。
|
||||
|
||||
第一步,根据分组中的人物类型,为每个集合计算信息熵,并通过全部集合的熵值加权平均,获得整个数据集的熵。注意,一开始集合只有一个,并且包含了所有的武侠人物。
|
||||
|
||||
第二步,根据信息增益,计算每个问卷题的区分能力。挑选区分能力最强的题目,并对每个集合进行更细的划分。
|
||||
|
||||
第三步,有了新的划分之后,回到第一步,重复第一和第二步,直到没有更多的问卷题,或者所有的人物类型都已经被区分开来。这一步也体现了递归的思想。
|
||||
|
||||
其实,上述这个过程就体现了训练**决策树**(Decision Tree)的基本思想。决策树学习属于归纳推理算法之一,适用于分类问题。在前面介绍朴素贝叶斯的时候,我说过,分类算法主要包括了建立模型和分类新数据两个阶段。决定问卷题出现顺序的这个过程,其实就是建立决策树模型的过程。
|
||||
|
||||
你可以看到,整个构建出来的图就是一个树状结构,这也是“决策树”这个名字的由来。而根据用户对每个问题的答案,从决策树的根节点走到叶子节点,最后来判断其属于何种人物类型,这个过程就是分类新数据的过程。
|
||||
|
||||
让我们把问卷案例泛化一下,将武侠人物的类型变为机器学习中的训练样本,将问卷中的题目变为机器学习中的特征,那么问卷调查的步骤就可以泛化为决策树构建树的步骤。
|
||||
|
||||
第一步,根据集合中的样本分类,为每个集合计算信息熵,并通过全部集合的熵值加权平均,获得整个数据集的熵。注意,一开始集合只有一个,并且包含了所有的样本。
|
||||
|
||||
第二步,根据信息增益,计算每个特征的区分能力。挑选区分能力最强的特征,并对每个集合进行更细的划分。
|
||||
|
||||
第三步,有了新的划分之后,回到第一步,重复第一步和第二步,直到没有更多的特征,或者所有的样本都已经被分好类。
|
||||
|
||||
有点需要注意的是,问卷案例中的每类武侠人物。都只有一个样本,而在泛化的机器学习问题中,每个类型对应了多个样本。也就是说,我们可以有很多个郭靖,而且每个人的属性并不完全一致,但是它们的分类都是“郭靖”。正是因为这个原因,决策树通常都只能把整体的熵降低到一个比较低的值,而无法完全降到0。这也意味着,训练得到的决策树模型,常常无法完全准确地划分训练样本,只能求到一个近似的解。
|
||||
|
||||
## 几种决策树算法的异同
|
||||
|
||||
随着机器学习的快速发展,人们也提出了不少优化版的决策树。采用信息增益来构建决策树的算法被称为[**ID3**](https://zh.wikipedia.org/wiki/ID3%E7%AE%97%E6%B3%95)(Iterative Dichotomiser 3,迭代二叉树3代)。但是这个算法有一个缺点,它一般会优先考虑具有较多取值的特征,因为取值多的特征会有相对较大的信息增益。这是为什么呢?
|
||||
|
||||
你仔细观察一下信息熵的定义,就能发现背后的原因。更多的取值会把数据样本划分为更多更小的分组,这样熵就会大幅降低,信息增益就会大幅上升。但是这样构建出来的树,很容易导致机器学习中的过拟合现象,不利于决策树对新数据的预测。为了克服这个问题,人们又提出了一个改进版,[C4.5算法](https://zh.wikipedia.org/wiki/C4.5%E7%AE%97%E6%B3%95)。
|
||||
|
||||
这个算法使用**信息增益率**(Information Gain Ratio)来替代信息增益,作为选择特征的标准,并降低决策树过拟合的程度。信息增益率通过引入一个被称作**分裂信息**(Split Information)的项来惩罚取值较多的特征,我把相应的公式给你列出来了。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/1d/a2/1d2d93ed55bfe09f256a9b72ca6c88a2.png" alt="">
|
||||
|
||||
其中,训练数据集$P$通过属性$T$的属性值,划分为$n$个子数据集,$|Pi|$表示第$i$个子数据集中样本的数量,$|P|$表示划分之前数据集中样本总数量。 这个公式看上去和熵很类似,其实并不相同。
|
||||
|
||||
熵计算的时候考虑的是,集合内数据是否属于同一个类,因此即使集合数量很多,但是集合内的数据如果都是来自相同的分类(或分组),那么熵还是会很低。而这里的分裂信息是不同的,它只考虑子集的数量。如果某个特征取值很多,那么相对应的子集数量就越多,最终分裂信息的值就会越大。正是因为如此,人们可以使用分裂信息来惩罚取值很多的特征。具体的计算公式如下:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/01/c4/01f28b759dae3e5fa7139535984eb6c4.png" alt="">
|
||||
|
||||
其中$Gain(P,T)$是数据集$P$使用特征$T$之后的信息增益,$GainRatio(P,T)$是数据集$P$使用特征$T$之后的信息增益率。
|
||||
|
||||
另一种常见的决策树**是CART算法**(Classification and Regression Trees,分类与回归树)。这种算法和ID3、C4.5相比,主要有两处不同:
|
||||
|
||||
<li>
|
||||
在分类时,CART不再采用信息增益或信息增益率,而是采用基尼指数(Gini)来选择最好的特征并进行数据的划分;
|
||||
</li>
|
||||
<li>
|
||||
在ID3和C4.5决策树中,算法根据特征的属性值划分数据,可能会划分出多个组。而CART算法采用了二叉树,每次把数据切成两份,分别进入左子树、右子树。
|
||||
</li>
|
||||
|
||||
当然,CART算法和ID3、C4.5也有类似的地方。首先,CART中每一次迭代都会降低基尼指数,这类似于ID3、C4.5降低信息熵的过程。另外,基尼指数描述的也是纯度,与信息熵的含义相似。我们可以用下面这个公式来计算每个集合的纯度。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/99/69/99ac2d02888b882c6a411316b037d369.png" alt="">
|
||||
|
||||
其中,$n$为集合$P$中所包含的不同分组(或分类)数量。如果集合$P$中所包含的不同分组越多,那么这个集合的基尼指数越高,纯度越低。
|
||||
|
||||
然后,我们需要计算整个数据集的基尼指数。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/de/3f/de267e07a31038e848d4396a45ccf23f.png" alt="">
|
||||
|
||||
其中,$m$为全集使用特征$T$划分后,所形成的子集数量。$P_{j}$为第$j$个集合。
|
||||
|
||||
无论是何种决策树算法,来自信息论的几个重要概念:信息熵、信息增益、信息增益率、基尼指数都起到了重要的作用。如果你能很好的学习并运用这些概念,那么决策树这种类型的算法就不难理解了。
|
||||
|
||||
## 总结
|
||||
|
||||
通过这两节的介绍,我想你对信息熵、信息增益、基尼指数等信息论的概念,以及基于这些概念的决策树分类算法应该有了一定了解。决策树算法的优势在于,容易理解和实现。此外,对于通过样本训练所得的树结构,其每个结点都是基于某个数据特征的判定,对于我们的阅读和解释来说都是很方便的。
|
||||
|
||||
当然,决策树也有不足。之前我已经提到,这类算法受训练样本的影响很大,比较容易过拟合。在预测阶段,如果新的数据和原来的训练样本差异较大,那么分类效果就会比较差。为此人们也提出了一些优化方案,比如剪枝和随机森林。如果感兴趣,你可以自己去研究一下。
|
||||
|
||||
## 思考题
|
||||
|
||||
刚刚我提到了,如果每次都选择使得信息增益最小的问题,那么构建出来的答题路径就相对冗长。你可以自己动手计算一下用户要回答问题数的期望。
|
||||
|
||||
欢迎留言和我分享,也欢迎你在留言区写下今天的学习笔记。如果你有朋友对决策树感兴趣,你可以点击“请朋友读”,把今天的内容分享给他,说不定就帮他解决一个问题。
|
||||
77
极客时间专栏/程序员的数学基础课/概率统计篇/28 | 熵、信息增益和卡方:如何寻找关键特征?.md
Normal file
77
极客时间专栏/程序员的数学基础课/概率统计篇/28 | 熵、信息增益和卡方:如何寻找关键特征?.md
Normal file
@@ -0,0 +1,77 @@
|
||||
<audio id="audio" title="28 | 熵、信息增益和卡方:如何寻找关键特征?" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/61/c4/616a4ff6f935f886342813d5dfb4c4c4.mp3"></audio>
|
||||
|
||||
你好,我是黄申。今天我们来说说特征选择。
|
||||
|
||||
我们已经讨论过信息熵和信息增益在决策树算法中的重要作用。其实,它们还可以运用在机器学习的其他领域,比如特征选择。你可能对“特征选择”这个名词不太熟悉,没有关系,我先花点时间,给你介绍一下什么是特征选择,以及机器学习为什么需要这个步骤。
|
||||
|
||||
## 什么是特征选择?
|
||||
|
||||
在编程领域中,机器学习已经有了十分广泛的应用,它主要包括监督式学习(Supervised Learning)和非监督式的学习(Unsupervised Learning)。监督式学习,是指通过训练资料学习并建立一个模型,并依此模型推测新的实例,主要包括分类(Classification)和回归(Regression)。
|
||||
|
||||
无论是在监督学习还是非监督学习中,我们都可以使用特征选择。不过,我今天要聊的特征选择,会聚焦在监督式学习中的特征处理方法。因此,为了说清楚特征选择是什么,以及为什么要进行这个步骤,我们先来看看监督式机器学习的主要步骤。
|
||||
|
||||
机器学习的步骤主要包括数据的准备、特征工程、模型拟合、离线和在线测试。测试过程也许会产生新的数据,用于进一步提升模型。在这些处理中,特征工程是非常重要的一步。
|
||||
|
||||
“特征”(Feature),是机器学习非常常用的术语,它其实就是可用于模型拟合的各种数据。前面讲朴素贝叶斯分类时,我解释了如何把现实世界中水果的各类特征转化为计算机所能理解的数据,这个过程其实就是最初级的特征工程。当然,特征工程远不止原始特征到计算机数据的转化,还包括特征选择、缺失值的填补和异常值的去除等等。这其中非常重要的一步就是特征选择。
|
||||
|
||||
越来越多的数据类型和维度的出现,会加大机器学习的难度,并影响最终的准确度。针对这种情形,特征选择尝试发掘和预定义任务相关的特征,同时过滤不必要的噪音特征。它主要包括特征子集的产生、搜索和评估。我们可以使用穷举法来找到最优的结果,但是如果特征有$N$个,那么复杂度会达到$O(2^{N})$。所以穷举法并不适合特征数量庞大的问题,比如我们之前讲过的文本分类。
|
||||
|
||||
因此,在这个领域诞生了一类基于分类标签的选择方法,它们通过信息论的一些统计度量,看特征和类标签的关联程度有多大。这里我还是使用文本分类的案例,来展示如何基于信息论,来进行特征选择。
|
||||
|
||||
## 利用信息熵进行特征选择
|
||||
|
||||
我们之前讲过如何为文本数据提取特征。对于一篇自然语言的文章,我们主要使用词包(Bag of Words)模型和分词,把完整的文章切分成多个单词或词组,而它们就表示了文章的关键属性,也就是用于机器学习的特征。
|
||||
|
||||
你会发现有些文本预处理的步骤已经在做特征选择的事情了,比如“停用词”。它会直接过滤一些不影响或基本不影响文章语义的词,这就是在减少噪音特征。不过,我之前也提到了,停用词的使用过于简单粗暴,可能会产生适得其反的效果。例如在进行用户观点分类时,“good”和“bad”这样的停用词反而成为了关键。不仅不能过滤,反而要加大它们的权重。
|
||||
|
||||
那么,我们怎么能知道哪些特征是更重要的呢?对于分类问题,我们更关心的是如何正确地把一篇文章划分到正确的分类中。一个好的特征选择,应该可以把那些对分类有价值的信息提取出来,而过滤掉那些对分类没有什么价值的信息。既然如此,我们能不能充分利用分类标签来进行挑选呢?答案是肯定的。前两节,我描述了信息熵和信息增益的工作原理。这里,我就可以使用它们来进行特征选择。
|
||||
|
||||
首先,我们来看这个问题,什么是对分类有价值的特征?
|
||||
|
||||
如果一个特征,经常只在某个或少数几个分类中出现,而很少在其他分类中出现,那么说明这个特征具有较强的区分力,它的出现很可能预示着整个数据属于某个分类的概率很高或很低。
|
||||
|
||||
这个时候,对于一个特征,我们可以看看包含这个特征的数据,是不是只属于少数几个类。举个例子,出现“电影”这个词的文章,经常出现在“娱乐”这个分类中,而很少出现在“军事”“政治”等其他分类中。
|
||||
|
||||
是否属于少数几个类这一点,可以使用信息熵来衡量。我用$Df_{i}$来表示所有出现特征$f_{i}$的数据集合,这个集合一共包含了$n$个分类$C$,而$c_{j}$表示这$n$个分类中的第$j$个。然后我们就可以根据$Df_{i}$中分类$C$的分布,来计算熵。我们用这个公式来计算:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/4f/6e/4f316dd9824e5522a71a8de54102796e.png" alt="">
|
||||
|
||||
如果熵值很低,说明包含这个特征的数据只出现在少数分类中,对于分类的判断有价值。计算出每个特征所对应的数据集之熵,我们就可以按照熵值由低到高对特征进行排序,挑选出排列靠前的特征。
|
||||
|
||||
当然,这个做法只考虑了单个特征出现时,对应数据的分类情况,而并没有考虑整个数据集的分类情况。比如,虽然出现“电影”这个词的文章,经常出现在“娱乐”这个分类中,很少出现在其他分类中,但是可能整个样本数据中,“娱乐”这个分类本来就已经占绝大多数,所以“电影”可能并非一个很有信息含量的特征。
|
||||
|
||||
为了改进这一点,我们可以借用决策树中信息增益的概念。我们把单个特征f是不是出现作为一个决策条件,将数据集分为$Df_{i}$ 和$D\bar{f_{i}}$ ,$Df_{i}$表示出现了这个特征的数据,而$D\bar{f_{i}}$表示没有出现这个特征的数据。那么使用特征$f_{i}$进行数据划分之后,我们就能得到基于两个新数据集的熵,然后和没有划分之前的熵进行比较,得出信息增益。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/a6/34/a6a9e6ce3eab1fa755488f8c82c1ac34.png" alt="">
|
||||
|
||||
如果基于某个特征的划分,所产生的信息增益越大,说明这个特征对于分类的判断越有价值。所以,我们可以为计算基于每个特征的划分,所产生的信息增益,然后按照增益值由高到低对特征进行排序,挑选出排列靠前的特征。
|
||||
|
||||
## 利用卡方检验进行特征选择
|
||||
|
||||
在统计学中,我们使用卡方检验来检验两个变量是否相互独立。把它运用到特征选择,我们就可以检验特征与分类这两个变量是否独立。如果两者独立,证明特征和分类没有明显的相关性,特征对于分类来说没有提供足够的信息量。反之,如果两者有较强的相关性,那么特征对于分类来说就是有信息量的,是个好的特征。为了检验独立性,卡方检验考虑了四种情况的概率:$P(f_{i},c_{j})$ 、$P(\bar{f_{i}} ,\bar{c_{j}})$、$P(f_{i},\bar{c_{j}})$和$P(\bar{f_{i}},c_{j})$。
|
||||
|
||||
在这四种概率中,$P(f_{i},c_{j})$和$P(\bar{f_{i}} ,\bar{c_{j}})$表示特征$f_{i}$和分类$c_{j}$是正相关的。如果$P(f_{i},c_{j})$很高,表示特征fi的出现意味着属于分类$c_{j}$的概率更高;如果$P(\bar{f_{i}} ,\bar{c_{j}})$很高,表示特征$f_{i}$不出现意味着不属于分类$c_{j}$的概率更高。
|
||||
|
||||
类似地,$P(f_{i},\bar{c_{j}})$和$P(\bar{f_{i}},c_{j})$表示特征$f_{i}$和分类$c_{j}$是负相关的。如果$P(f_{i},\bar{c_{j}})$很高,表示特征$f_{i}$的出现意味着不属于分类$c_{j}$的概率更高;如果$P(\bar{f_{i}},c_{j})$很高,表示特征$f_{i}$不出现意味着属于分类$c_{j}$的概率更高。
|
||||
|
||||
如果特征和分类的相关性很高,要么是正向相关值远远大于负向相关值,要么是负向相关值远远大于正向相关值。如果特征和分类相关性很低,那么正向相关值和负向相关的值就会很接近。卡方检验就是利用了正向相关和负向相关的特性。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/9e/3d/9ec2338131ede3bd92b5abdc798ad33d.png" alt="">
|
||||
|
||||
其中,$N$表示数据的总个数。通过这个公式,你可以看到,如果一个特征和分类的相关性很高,无论是正向相关还是负向相关,那么正向相关和负向相关的差值就很大,最终计算的值就很高。最后,我们就可以按照卡方检验的值由高到低对特征进行排序,挑选出排列靠前的特征。
|
||||
|
||||
## 总结
|
||||
|
||||
在之前水果的案例中,可用的特征并不是很多,每种特征都是有价值的。对于文本分类,每种单词或词组都是特征,再加上多元文法,特征的数量会成倍的增加。过多的特征会影响模型分析的速度和准确度。
|
||||
|
||||
对于监督式学习而言,我们没有必要进行$O(2^{N})$这种数量级的特征子集搜索,而是直接考虑特征和分类标签直接的关系。这个时候信息论等统计度量就可以帮上忙了,它们可以衡量特征和分类之间的关联程度,从而判断哪些特征对于分类来说更重要。
|
||||
|
||||
无论是使用何种统计度量,我们都可以计算相应的数值、排序、并得到排名靠前的若干特征。从文本分类的角度来说,我们只会挑选对分类最有价值的那些单词或词组,而去除其他不重要的那些词。如果特征选择得当,我们既可以减少模型存储的空间,还可以提升分类的准确度。当然,过度的减少特征最终会导致准确度的下降,所以对于不同的数据集要结合实验,要把握一个合理的度。
|
||||
|
||||
## 思考题
|
||||
|
||||
在之前介绍决策树的时候,我除了解释信息增益,还阐述了基尼指数的概念。既然信息增益可用于特征选择,那么基尼指数是不是也可以呢?你可以试着写出相应的公式。
|
||||
|
||||
欢迎留言和我分享,也欢迎你在留言区写下今天的学习笔记。你可以点击“请朋友读”,把今天的内容分享给你的好友,和他一起精进。
|
||||
|
||||
|
||||
187
极客时间专栏/程序员的数学基础课/概率统计篇/29 | 归一化和标准化:各种特征如何综合才是最合理的?.md
Normal file
187
极客时间专栏/程序员的数学基础课/概率统计篇/29 | 归一化和标准化:各种特征如何综合才是最合理的?.md
Normal file
@@ -0,0 +1,187 @@
|
||||
<audio id="audio" title="29 | 归一化和标准化:各种特征如何综合才是最合理的?" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/a7/af/a7f5d5780fee0ca744917215d407f2af.mp3"></audio>
|
||||
|
||||
你好,我是黄申,今天我来说说特征值的变换。
|
||||
|
||||
上一节我讲了如何在众多的特征中,选取更有价值的特征,以提升模型的效率。特征选择是特征工程中的重要步骤,但不是全部。今天,我来说说特征工程中的另一块内容,数值变换。也就是说,我们可以使用统计中的数据分布,对连续型的数值特征进行转换,让多个特征的结合更有效。具体怎么理解呢?我下面就来详细讲一讲。
|
||||
|
||||
## 为什么需要特征变换?
|
||||
|
||||
我们在很多机器学习算法中都会使用特征变换。我使用其中一种算法线性回归作为例子,来解释为什么要进行数值型特征的变换。
|
||||
|
||||
我们之前介绍的监督式学习会根据某个样本的一系列特征,最后判定它应该属于哪个分类,并给出一个离散的分类标签。除此之外,还有一类监督式学习算法,会根据一系列的特征输入,给出连续的预测值。
|
||||
|
||||
举个例子,房地产市场可以根据销售的历史数据,预估待售楼盘在未来的销售情况。如果只是预估卖得“好”还是“不好”,那么这个粒度明显就太粗了。如果我们能做到预估这些房屋的售价,那么这个事情就变得有价值了。想要达成这个预测目的的过程,就需要最基本的**因变量连续回归分析**。
|
||||
|
||||
因变量连续回归的训练和预测,和分类的相应流程大体类似,不过具体采用的技术有一些不同。它采用的是研究一个或多个随机变量$y_{1}$,$y_{2}$,…,$y_{i}$与另一些变量$x_{1}$,$x_{2}$,…,$x_{k}$之间关系的统计方法,又称**多重回归分析**。
|
||||
|
||||
我们将$y_{1}$,$y_{2}$,…,$y_{i}$称为因变量,$x_{1}$,$x_{2}$,…,$x_{k}$称为自变量。通常情况下,因变量的值可以分解为两部分,一部分是受自变量影响的,即表示为自变量相关的函数,其中函数形式已知,可能是线性也可能是非线性函数,但包含一些未知参数;另一部分是由于其他未被考虑的因素和随机性的影响,即随机误差。
|
||||
|
||||
如果因变量和自变量为线性关系时,就称为**线性回归模型**;如果因变量和自变量为非线性关系,则称为**非线性回归分析模型**。今天我们要说的是回归中常用的多元线性回归,它的基本形式是:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/13/70/1350fcaad0a241fae13896bf85fa4d70.png" alt="">
|
||||
|
||||
其中,$x_{1}$,$x_{2}$,…,$x_{n}$是自变量,$y$是因变量,$ε$是随机误差,通常假定随机误差的均值为0。而w0是截距,$w_{1}$,$w_{2}$,…,$w_{n}$是每个自变量的系数,表示每个自变量对最终结果的影响是正面还是负面,以及影响的程度。如果某个系数大于0,表示对应的自变量对结果是正面影响,这个自变量越大,结果就越大。否则就是负面影响,这个自变量越大,结果就越小。而系数的绝对值表示了影响程度的大小,如果绝对值趋于0,表示基本没有影响。
|
||||
|
||||
线性回归也是统计概率中常用的算法。不过它的实现通常会涉及很多线性代数的知识,所以下一个模块的时候,我会再详细介绍这个算法。这一节,你只需要知道线性回归所要达到的目标,以及怎么使用它就可以了。
|
||||
|
||||
线性回归和其他算法相比,有很强的可解释性。我们可以通过回归后为每个自变量确定的系数,来判哪些自变量对最终的因变量影响更大。可是,在正式开始线性回归分析之前,还有一个问题,那就是不同字段的数据没有可比性。
|
||||
|
||||
比如,房屋的面积和建造的年份,它们分别代表了不同的含义,也有不一样的取值范围。在线性回归中,如果直接将没有可比性的数字型特征线性加和,那么模型最终的解释肯定会受影响。
|
||||
|
||||
这里我用Boston Housing数据集对房价数据进行回归分析,这个数据来自70年代美国波斯顿周边地区的房价,是用于机器学习的经典数据集,你可以在Kaggle的网站([https://www.kaggle.com/c/boston-housing#description](https://www.kaggle.com/c/boston-housing#description))下载到它。这个数据一共有14个特征或者说自变量,而有1个目标值或者说因变量。
|
||||
|
||||
这里,我只使用其中的train.csv。使用一小段Python代码,我们就能很快的得到一个线性回归的结果。
|
||||
|
||||
```
|
||||
import pandas as pd
|
||||
from sklearn.linear_model import LinearRegression
|
||||
|
||||
|
||||
df = pd.read_csv("/Users/shenhuang/Data/boston-housing/train.csv") #读取Boston Housing中的train.csv
|
||||
df_features = df.drop(['medv'], axis=1) #Dataframe中除了最后一列,其余列都是特征,或者说自变量
|
||||
df_targets = df['medv'] #Dataframe最后一列是目标变量,或者说因变量
|
||||
|
||||
|
||||
regression = LinearRegression().fit(df_features, df_targets) #使用特征和目标数据,拟合线性回归模型
|
||||
print(regression.score(df_features, df_targets)) #拟合程度的好坏
|
||||
print(regression.coef_) #各个特征所对应的系
|
||||
|
||||
```
|
||||
|
||||
使用上述代码之前,请确保你已经按照了Python中的sklearn和pandas包。运行这段代码,你可以得到如下的结果:
|
||||
|
||||
```
|
||||
0.735578647853312
|
||||
[-4.54789253e-03 -5.17062363e-02 4.93344687e-02 5.34084254e-02
|
||||
3.78011391e+00 -1.54106687e+01 3.87910457e+00 -9.51042267e-03
|
||||
-1.60411361e+00 3.61780090e-01 -1.14966409e-02 -8.48538613e-01
|
||||
1.18853164e-02 -6.01842329e-01]
|
||||
|
||||
```
|
||||
|
||||
因为不是所有的数据都是可以使用线性回归模型来表示,所以我们需要使用regression.score函数,来看拟合的程度。如果完美拟合,这个函数就会输出1;如果拟合效果很差,这个函数的输出可能就是一个负数。
|
||||
|
||||
这里regression.score函数的输出大约为0.74,接近于1.0。它表示这个数据集使用线性模型拟合的效果还是不错的。如果你还是不理解,不用担心,具体的我们会在线性代数部分详细解答。这里你可以简单的理解为,0.74仅仅表示我们可以使用线性回归来解决Boston Housing这个问题。
|
||||
|
||||
这里,你更需要关注的是每个特征所对应的权重,因为它们可以帮助我们解释哪个特征对最终房价的中位值有更大的影响。参看train.csv中的数据,你会发现最主要的两个正相关特征是nox(系数为3.78011391e+00)和age(系数为3.87910457e+00)。其中nox表示空气污染浓度,age表示老房子占比,也就是说空气污染越多、房龄越高,房价中位数越高,这好像不太合乎常理。我们再来看看最主要的负相关特征rm(系数为-1.54106687e+01),也就是房间数量。房间数量越多,房价中位数越低,也不合理。
|
||||
|
||||
造成这些现象最重要的原因是,不同类型的特征值没有转换到同一个可比较的范围内,所以线性回归后所得到的系数不具有可比性,因此我们无法直接对这些权重加以解释。
|
||||
|
||||
## 两种常见的特征变换方法
|
||||
|
||||
该怎么解决这个问题呢?我们就需要对特征值进行转换。今天我介绍两种最常见的变换方法:归一化和标准化。
|
||||
|
||||
### 归一化
|
||||
|
||||
我们先来看最常用的方法,**归一化**(Normalization)。它其实就是获取原始数据的最大值和最小值,然后把原始值线性变换到[0,1]之间,具体的变换函数为:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/0f/1e/0ff408fa0e7a547d2a874a76e39cc31e.png" alt="">
|
||||
|
||||
其中$x$是原始值,$max$为样本数据的最大值,$min$为样本数据的最小值,$x’$是变换后的值。这种方法有个不足最大值与最小值非常容易受噪音数据的影响。
|
||||
|
||||
这里面需要注意的是,“归一化”这个词在不同的领域的含义可能不同。这里我们特指基于最大和最小值的变换。
|
||||
|
||||
接下来,我们来看看在Python中如何实现归一化,以及归一化对回归后系数的影响。
|
||||
|
||||
```
|
||||
from sklearn.preprocessing import StandardScaler
|
||||
from sklearn.preprocessing import MinMaxScaler
|
||||
|
||||
|
||||
minMaxScaler = MinMaxScaler() #基于min和max值的归一化
|
||||
|
||||
|
||||
df_normalized = minMaxScaler.fit_transform(df) #对原始数据进行归一化,包括特征值和目标变量
|
||||
df_features_normalized = df_normalized[:, 0:-1] #获取归一化之后的特征值
|
||||
df_targets_normalized = df_normalized[:, -1] #获取归一化之后的目标值
|
||||
|
||||
|
||||
#再次进行线性回归
|
||||
regression_normalized = LinearRegression().fit(df_features_normalized, df_targets_normalized)
|
||||
print(regression_normalized.score(df_features_normalized, df_targets_normalized))
|
||||
print(regression_normalized.coef
|
||||
|
||||
```
|
||||
|
||||
其中,df还是之前加载的dataframe。运行这段代码,你可以得到如下结果:
|
||||
|
||||
```
|
||||
0.7355786478533118
|
||||
[-0.05103746 -0.08448544 0.10963215 0.03204506 0.08400253 -0.16643522
|
||||
0.4451488 -0.01986622 -0.34152292 0.18490982 -0.13361651 -0.16216516
|
||||
0.10390408 -0.48468369]
|
||||
|
||||
```
|
||||
|
||||
你可以看到,表示拟合程度的分数没有变,但是每个特征对应的系数或者说权重,发生了比较大的变化。仔细观察一下,你会发现,这次最主要的正相关特征是age(0.4451488)和tax(0.18490982),也就是老房子占比和房产税的税率,其中至少房产税的税率是比较合理的,因为高房价的地区普遍税率也比较高。而最主要的负相关特征是rad(-0.34152292)和lstat(-0.48468369),rad表示高速交通的便利程度,它的值越大表示离高速越远,房价中位数越低。而lstat表示低收入人群的占比,这个值越大房价中位数越低,这两点都是合理的。
|
||||
|
||||
### 标准化
|
||||
|
||||
另一种常见的方法是基于正态分布的z分数(z-score)标准化(Standardization)。该方法假设数据呈现标准正态分布。
|
||||
|
||||
什么是标准正态分布呢?我们之前介绍过,正态分布是连续随机变量概率分布的一种。在现实生活中,大量随机现象的数据分布都近似于正态分布。
|
||||
|
||||
我这里再快速回顾一下这种分布的特点。
|
||||
|
||||
它以经过平均数的垂线为轴,左右对称展开,中间点最高,然后逐渐向两侧下降,分布曲线和x轴组成的面积为1,表示不同事件出现的概率和为1。平均数和标准差是正态分布的关键参数,它们会决定分布的具体形态。而标准正态分布是正态分布的一种,平均数为0,标准差为1。
|
||||
|
||||
理解了什么是标准正态分布,我们来看看z分数这个方法是如何运作的。实际上,z分数标准化是利用标准正态分布的特点,计算一个给定分数距离平均数有多少个标准差。它的具体转换公式如下:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/af/01/af7092087da728c5c36819cf2ae68f01.png" alt="">
|
||||
|
||||
其中$x$为原始值,$u$为均值,$σ$为标准差,$x’$是变换后的值。
|
||||
|
||||
经过z分数的转换,高于平均数的分数会得到一个正的标准分,而低于平均数的分数会得到一个负的标准分数。更重要的是,转换后的数据是符合标准正态分布的。你通过理论或者具体的数值来推导一下,就会发现转换后的数据均值为0,标准差为1。
|
||||
|
||||
和归一化相比,z分数这样的标准化不容易受到噪音数据的影响,并且保留了各维特征对目标函数的影响权重。
|
||||
|
||||
下面我们来看看,在Python中如何实现标准化,以及标准化对回归后系数的影响。
|
||||
|
||||
```
|
||||
standardScaler = StandardScaler() #基于Z分数的标准化
|
||||
|
||||
|
||||
standardScaler.fit(df)
|
||||
df_standardized = standardScaler.transform(df) #对原始数据进行标准化,包括特征值和目标变量
|
||||
|
||||
|
||||
df_features_standardized = df_standardized[:, 0:-1] #获取标准化之后的特征值
|
||||
df_targets_standardized = df_standardized[:, -1] #获取标准化之后的特征值
|
||||
|
||||
|
||||
#再次进行线性回归
|
||||
regression_standardized = LinearRegression().fit(df_features_standardized, df_targets_standardized)
|
||||
print(regression_standardized.score(df_features_standardized, df_targets_standardized))
|
||||
print(regression_standardized.coef
|
||||
|
||||
```
|
||||
|
||||
其中,df还是之前加载的dataframe。运行这段代码,这次你得到的结果如下:
|
||||
|
||||
```
|
||||
0.7355786478533118
|
||||
[-0.07330367 -0.04144107 0.12194378 0.04074345 0.09805446 -0.19311408
|
||||
0.29767387 -0.02916672 -0.34642803 0.34477088 -0.21410757 -0.19904179
|
||||
0.11218058 -0.46369483]
|
||||
|
||||
```
|
||||
|
||||
表示拟合程度的分数任然没有变。再次对比不同特征所对应的系数,你会发现这次最主要的正相关特征还是age(0.29767387)和tax(0.34477088),但是相比之前,明显房产税的税率占了更高的权重,更加合理。而最主要的负相关特征还是rad(-0.34152292)和lstat(-0.48468369),这两点都是合理的。
|
||||
|
||||
## 总结
|
||||
|
||||
今天我介绍了在机器学习领域里,如何使用统计里的数据分布来进行特征值的转换。这里,我帮你梳理了几个要点,便于你的记忆。
|
||||
|
||||
第一点,为什么有时候需要转换特征值?因为不同类型的特征取值范围不同,分布也不同,相互之间没有可比性。因此在线性回归中,通过这些原始值分析得到的权重,并不能代表每个特征实际的重要性。
|
||||
|
||||
第二点,如何使用归一化进行特征值转换?这里的归一化是指使用特征取值范围中的最大值和最小值,把原始值转换为0到1之间的值。这样处理的好处在于简单易行,便于理解。不过,它的缺点也很明显,由于只考虑了最大最小值,因此很容易受到异常数据点的干扰。
|
||||
|
||||
第三点,如何使用标准化进行转换?经过标准化处理之后,每种特征的取值都会变成一个标准正态分布,以0为均值,1为标准差。和归一化相比,标准化使用了数据是正态分布的假设,不容易受到过大或过小值的干扰。
|
||||
|
||||
掌握了上面几个点,你就能很好的理解这一节的内容了。在实际的数据分析或者是统计建模的项目中,对于数值型的特征要保持敏感,看到它们的时候都要考虑一下,是不是需要进行特征值的转换?这样就能避免由于多种特征的不同分布而产生的误导性结论。
|
||||
|
||||
## 思考题
|
||||
|
||||
今天我们使用了三种方式处理Boston Housing的数据,并训练出三种线性回归的模型。请尝试使用这些模型的predict方法,对test.csv数据进行预测,看看每种模型的预测效果。(提示:如果你在train.csv上使用了某种特征值的转换,那么相应的test.csv数据也需要经过同样的处理。)
|
||||
|
||||
欢迎留言和我分享,也欢迎你在留言区写下今天的学习笔记。你也可以把今天的内容分享给你的好友,和他一起在实战中重新理解数学。
|
||||
@@ -0,0 +1,81 @@
|
||||
<audio id="audio" title="30 | 统计意义(上):如何通过显著性检验,判断你的A/B测试结果是不是巧合?" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/a4/6e/a49e26b6e8d327e138d5dc5a61fe4b6e.mp3"></audio>
|
||||
|
||||
你好,我是黄申,今天我们来聊聊统计意义和显著性检验。
|
||||
|
||||
之前我们已经讨论了几种不同的机器学习算法,包括朴素贝叶斯分类、概率语言模型、决策树等等。不同的方法和算法会产生不同的效果。在很多实际应用中,我们希望能够量化这种效果,并依据相关的数据进行决策。
|
||||
|
||||
为了使这种量化尽可能准确、客观,现在的互联网公司通常是根据用户的在线行为来评估算法,并比较同类算法的表现,以此来选择相应的算法。在线测试有一个很大的挑战,那就是如何排除非测试因素的干扰。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/a9/8a/a9e5a362fabdaf3d591a7cfb33ff308a.png" alt="">
|
||||
|
||||
从图中可以看出,自2016年1月12日开始,转化率曲线的趋势发生了明显的变化。假如说这天恰好上线了一个新版的技术方案A,那么转化率上涨一定是新方案导致的吗?不一定吧?很有可能,1月12日有个大型的促销,使得价格有大幅下降,或者有个和大型企业的合作引入了很多优质顾客等,原因有非常多。如果我们取消12日上线的技术方案A,然后用虚线表示在这种情况下的转化率曲线,这个时候得到了另一张图。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/0f/92/0ffe01ec3c4c75764bc94577ff07d492.png" alt="">
|
||||
|
||||
从图中可以发现,不用方案A,反而获得了更好的转化率表现,所以,简单地使用在线测试的结果往往会导致错误的结论,我们需要一个更健壮的测试方法,A/B测试。
|
||||
|
||||
A/B测试,简单来说,就是为同一个目标制定两个或多个方案,让一部分用户使用A方案,另一部分用户使用B方案,记录下每个部分用户的使用情况,看哪个方案产生的结果更好。这也意味着,通过A/B测试的方式,我们可以拿到使用多个不同方法之后所产生的多组结果,用于对比。
|
||||
|
||||
问题来了,假设我们手头上有几组不同的结果,每组对应一个方案,包含了最近30天以来每天的转化率,如何判断哪个方案的效果更好呢?你可能会想,对每一组的30个数值取平均数,看看谁的均值大不就好了?但是,这真的就够了吗?
|
||||
|
||||
假设有两组结果需要比较,每一组都有5个数据,而且这两组都符合正态分布。我用一张图画一下这两个正态分布之间的关系。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/4c/e3/4c50716807e2eb5178bb37052b9c48e3.png" alt="">
|
||||
|
||||
从这张图可以看出,左边的正态分布A均值μ1比较小,右侧的正态分布B均值μ2比较大。可是,如果我们无法观测到A和B这两个分布的全部,而只根据这两个分布的采样数据来做判断,会发生什么情况?我们很有可能会得出错误的结论。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/51/29/511dc74701343b3b546af00004d91929.png" alt="">
|
||||
|
||||
比如说,在这张图的采样中,红色的点表示B的采样,它们都是来自B分布的左侧,而蓝色的点表示A的采样,它们都是来自A分布的右侧。如果我们仅仅根据这两组采样数据的均值来判断,很可能会得出“B分布的均值小于A分布均值”这样的错误结论。
|
||||
|
||||
A/B测试面临的就是这样的问题。我们所得到的在线测试结果,实际上只是一种采样。所以我们不能简单地根据每个组的平均值,来判断哪个组更优。那有没有更科学的办法呢?在统计学中,有一套成熟的系统和对应的方法,今天我们就来讲讲这种方法。
|
||||
|
||||
为了让你能够充分理解这个,我先介绍几个基本概念,显著性差异、统计假设检验和显著性检验、以及P值。
|
||||
|
||||
## 显著性差异
|
||||
|
||||
从刚刚那两张正态分布图,我们可以分析得出,两组数据之间的差异可能由两个原因引起。
|
||||
|
||||
第一,两个分布之间的差异。假设A分布的均值小于B分布,而两者的方差一致,那么A分布随机产生的数据有更高的概率小于B分布随机产生的数据。第二,采样引起的差异,也就是说采样数据不能完全体现整体的数据分布。我在之前的图中,用来自A、B两组的10个数据展示了采样所导致的误差。
|
||||
|
||||
如果差异是第一个原因导致的,在统计学中我们就认为这两组“有显著性差异”。如果差异是第二种原因导致的,我们就认为这两组“无显著性差异”。可以看出来,**显著性差异**(Significant Difference),其实就是研究多组数据之间的差异,是由于不同的数据分布导致的呢,还是由于采样的误差导致的呢?通常,我们也把“具有显著性差异”,称为“差异具有统计意义”或者“差异具有显著性”。
|
||||
|
||||
这里你还需要注意“差异具有显著性”和“具有显著差异”的区别。如前所说,“差异具有显著性“表示不同的组很可能来自不同的数据分布,也就是说多个组的数据来自同一分布的可能性非常小。而“具有显著差异”,是指差异的幅度很大,比如相差100倍。
|
||||
|
||||
不过,差异的显著性和显著差异没有必然联系。举两个例子,比如说,两个不同的数据分布,它们的均值分别是1和1.2,这两个均值相差的绝对值很小,也就是没有显著差异,但是由于它们源自不同的数据分布,所以差异是具有显著性的。再比如说,来自同一个数据分布的两个采样,它们的均值分别是1和100,具有显著的差异,但是差异没有显著性。
|
||||
|
||||
## 统计假设检验和显著性检验
|
||||
|
||||
统计假设检验是指事先对随机变量的参数或总体分布做出一个假设,然后利用样本信息来判断这个假设是否合理。在统计学上,我们称这种假设为**虚无假设**(Null Hypothesis),也叫原假设或零假设,通常记作**H0**。而和虚无假设对立的假设,我们称为**对立假设**(Alternative Hypothesis),通常记作**H1**。也就是说,如果证明虚无假设不成立,那么就可以推出对立假设成立。
|
||||
|
||||
统计假设检验的具体步骤是,先认为原假设成立,计算其会导致什么结果。若在单次实验中产生了小概率的事件,则拒绝原假设H0,并接受对立假设H1。若不会产生小概率的事件,则不能拒绝原假设H0,从而接受它。因此,统计学中的假设是否成立,并不像逻辑数学中的绝对“真”或“假”,而是需要从概率的角度出发来看。
|
||||
|
||||
那么,问题来了,多少才算是“小概率”呢?按照业界的约定俗成,通常我们把概率不超过0.05的事件称为“小概率事件”。当然,根据具体的应用,偶尔也会取0.1或0.01等。在假设检验中,我们把这个概率记为α,并称它为显著性水平。
|
||||
|
||||
显著性检验是统计假设检验的一种,顾名思义,它可以帮助我们判断多组数据之间的差异,是采样导致的“偶然”,还是由于不同的数据分布导致的“必然“。当然,这里的“偶然”和“必然”都是相对的,和显著性水平α有关。显著性检验的假设是,多个数据分布之间没有差异。如果样本发生的概率小于显著性水平α,证明小概率事件发生了,所以拒绝原假设,也就是说认为多个分布之间有差异。否则呢,接受原假设,认为多个分布之间没有差异。换句话说,显著性水平α即为拒绝原假设的标准。
|
||||
|
||||
## P值
|
||||
|
||||
既然已经定义了显著性检验和显著性水平,那么我们如何为多组数据计算它们之间差异的显著性呢?我们可以使用P值(P-value)。P值中的P代表Probability,就是当H0假设为真时,样本出现的概率,或者换句话说,其实就是我们所观测到的样本数据符合原假设H0的可能性有多大。
|
||||
|
||||
如果P值很小,说明观测值与假设H0的期望值有很大的偏离,H0发生的概率很小,我们有理由拒绝原假设,并接受对立假设。P值越小,表明结果越显著,我们越有信心拒绝原假设。反之,说明观测值与假设H0的期望值很接近,我们没有理由拒绝H0。
|
||||
|
||||
在显著性检验中,原假设认为多个分组内的数据来自同一个数据分布,如果P值足够小,我们就可以拒绝原假设,认为多个分组内的数据来自不同的数据分布,它们之间存在显著性的差异。所以说,只要能计算出P值,我们就能把P值和显著性水平α进行比较,从而决定是否接受原假设。
|
||||
|
||||
## 总结
|
||||
|
||||
今天我从互联网公司常见的A/B测试实验入手,给你讲解了一个更科学的方法来比较不同算法的效果,它就是统计学里的差异显著性检验。这个方法包含了一些你平时可能不太接触的概念,你首先需要理解显著性差异、统计假设检验和P值。其中最为重要的就是显著性差异的概念,因为这是差异显著性检验区别于简单的平均值方法的关键。
|
||||
|
||||
为了便于你的记忆,我这里再用一个形象的比喻来带你复习一遍。
|
||||
|
||||
儿子考了90分,我问他:“你比班上平均分高多少?”如果他回答:“我不太确定,我只看到了周围几个人的分数,我猜大概高出了10分吧”,那么说明他对“自己分数比平均分高出10分”这个假设信心不足,结论有较大的概率是错误的,所以即使可能高了10分,我也高兴不起来。
|
||||
|
||||
如果他回答:“老师说了,班级平均分是88分,我比平均分高出了2分”,那我就很开心了,因为老师掌握了全局的信息,她说的话让儿子对“自己分数比平均分高出2分”的假设是非常有信心的。即使只高出了2分,但是结论有很大的概率是正确的。
|
||||
|
||||
理解了概念之后,我们就要进入实战环节了。其实显著性检验的具体方法有很多,例如方差分析(F检验)、t检验、卡方检验等等。不同的方法计算P值的方法也不同,在下一节,我会用A/B测试的案例来详细解释。
|
||||
|
||||
## 思考题
|
||||
|
||||
在对比两组数据的差异时,如果不断增加采样次数,也就是样本的数量,使用平均值和使用显著性检验这两者的结论,会不会逐渐变得一致?
|
||||
|
||||
欢迎留言和我分享,也欢迎你在留言区写下今天的学习笔记。你可以点击“请朋友读”,把今天的内容分享给你的好友,和他一起精进。
|
||||
@@ -0,0 +1,197 @@
|
||||
<audio id="audio" title="31 | 统计意义(下):如何通过显著性检验,判断你的A/B测试结果是不是巧合?" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/1e/97/1e387237fc0143ab4c377e9886189a97.mp3"></audio>
|
||||
|
||||
你好,我是黄申,今天我们接着来聊显著性检验。
|
||||
|
||||
上一节,我介绍了差异显著性检验的概念,它是指从统计的角度来说,差异的产生有多大的概率、是不是足够可信。这点和数值差异的大小是有区别的。既然我们不能通过差异的大小来推断差异是否可信,那么有没有什么方法,可以帮助我们检验不同数据分布之间,是否存在显著差异呢?具体的方法有不少,比如方差分析(F检验)、t检验、卡方检验等等。我这里以方差分析为例,来讲这个方法是如何帮助我们解决AB测试中的问题。
|
||||
|
||||
## 方差分析
|
||||
|
||||
**方差分析**(Analysis of Variance, ANOVA),也叫**F检验**。这种方法可以检验两组或者多组样本的均值是否具备显著性差异。它有四个前提假设,分别是:
|
||||
|
||||
<li>
|
||||
随机性:样本是随机采样的;
|
||||
</li>
|
||||
<li>
|
||||
独立性:来自不同组的样本是相互独立的;
|
||||
</li>
|
||||
<li>
|
||||
正态分布性:组内样本都来自一个正态分布;
|
||||
</li>
|
||||
<li>
|
||||
方差齐性:不同组的方差相等或相近。
|
||||
</li>
|
||||
|
||||
根据第三个前提,我们假设数据是正态分布,那么分布就有两个参数,一个是平均数,一个是方差。如果我们仅仅知道两个分组的平均值,但并不知道它们的方差相差多大,那么我们所得出的两个分布是否有显著差异的结论就不可靠了。
|
||||
|
||||
为了突出重点,我们先假设咱们的数据都符合上述四个前提,然后我来详细讲解一下方差分析的主要思想。最后,我会通过Python语言来验证各个假设和最终的F检验结果。
|
||||
|
||||
这里,我使用之前提到的A/B测试案例,通过方差分析来检验多种算法所产生的用户转化率有没有显著性差异。我们把“转化率”称为“因变量”,把“算法”称为“因素”。这里我们只有算法一个因素,所以所进行的方差分析是单因素方差分析。在方差分析中,因素的取值是离散型的,我们称不同的算法取值为“水平”。如果我们比较算法a和b,那么a和b就是算法这个因素的两个水平。
|
||||
|
||||
我们假设只有两种算法a和b参与了A/B测试。为了检验这些算法导致的转化率,是不是存在显著的差异,我们进行一个为期10天的测试,每天都为每种算法获取一个转化率。具体的数据我列在下面这张表格中。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/f3/92/f349be3fe72cba0460f0868605413592.png" alt="">
|
||||
|
||||
我使用$Y_{ij}$来表示这种表格中的数据,$i$表示第$i$次采样(或第$i$天),$j$表示第$j$种水平(或第$j$种算法)。以上面这张表格为例,$Y_{51}=0.34$。
|
||||
|
||||
如果我们把每种算法导致的转化率看作一个数据分布,那么方差分析要解决的问题就是:这两个转化率分布的均值,是不是相等。如果我把两种数据分布的均值记做μ1和μ2,那么原假设H0就是μ1=μ2。而对立假设H1就是μ1 <> μ2。
|
||||
|
||||
之前我们提到,差异是不是显著性,关键要看这个差异是采样的偶然性引起的,还是分布本身引起的。方差分析的核心思想也是围绕这个展开的,因此它计算了三个数值:SST、SSM和SSE。SST表示所有采样数据的**因变量方差**(Total Sum of Squares),我把它的计算公式列在这里。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/fd/ad/fd07b019affee5b704308fffd71cb0ad.png" alt="">
|
||||
|
||||
在这个公式中, $Y_{ij}$如前所说,表示了第$i$天第$j$种算法所导致的转化率。而$\overline{\overline Y}$表示了10天里,2种算法全部20个数据的平均值。SSM表示数据分布所引起的方差,我们称它为**模型平方和**(Sum Of Squares for Model),它的计算公式如下:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/d9/13/d926ab132444cec5e367b9ee535f7f13.png" alt="">
|
||||
|
||||
在这个公式中,$n_{j}$为水平$j$下的观测数量,在我们的案例中为10。$\overline Y_{j}$为第$j$个水平的平均值,在案例中为算法a或算法b在这10天的平均值。$\overline Y_{j}-\overline{\overline Y}$表示的是某个算法的采样均值和所有采样均值之间的差异,$n_{j}$是相应的权重。我们这里的两个算法都被测试了10天,所以权重相同。根据我们的案例,SSM是0.00018。SSE表示采样引起的方差,我们称它为**误差平方和**(Sum of Squaress for Error)。它的计算公式如下:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/84/2f/842aad0e8d589da4fe66d8e0473bc22f.png" alt="">
|
||||
|
||||
根据我们的案例,SSE是0.01652。我们刚刚介绍的三个统计量,SST、SSM和SSE这三者的关系其实是这样的:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/23/88/239c3e46ab61cbf12046507d2188a488.png" alt="">
|
||||
|
||||
你可以把这三者的公式代入,自己证明一下等式是否成立。由此可以看出,SST是由SSM和SSE构成的。如果在SST中,SSM的占比更大,那么说明因素对因变量的差异具有显著的影响;如果SSE的占比更大,那么说明采样误差对因变量的差异具有更显著的影响。我们使用这两部分的比例来衡量显著性,并把这个比例称为F值。具体公式如下:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/a6/74/a667bf48f002c85be85c604dd12bce74.png" alt="">
|
||||
|
||||
在这个公式中,s是水平的个数,n为所有样本的总数量,s-1为分布的自由度,n-s为误差的自由度。你可能对自由度这个概念比较陌生,这里我稍微解释一下。
|
||||
|
||||
**自由度**(degree of freedom),英文缩写是df,它是指采样中能够自由变化的数据个数。对于一组包含n个数据的采样来说,如果方差是一个固定值,那么只有n-1个数据可以自由变化,最后一个数的取值是给定的方差和其他n-1个数据决定的,而不由它自己随意变化,所以自由度就是n-1。这也是为什么在计算一组数的方差时,我们在下面这个公式中使用的除数是n-1,而不是n。
|
||||
|
||||
回到方差分析,对于SSM来说,如果SSM是固定的,那么对于s个水平来说,只能有s-1个组数据自由变化,而最后一组数据必须固定,所以对应于SSM的自由度为s-1。对于SSE来说,如果SSE是固定的,那么对于n个采样、s个水平数据来说,只有n-s个数据是可以自由变化的。因为每个水平中,都要有一个数据需要保证该组的平均值$\overline Y_{j}$而无法自由变化。
|
||||
|
||||
在我们的案例中,s为不同算法的个数,也就是水平的个数s为2,采样数据的个数n为20,所以分布的自由度为2-1=1,误差的自由度为20-2=18。
|
||||
|
||||
在我们的案例中,F=(0.00018/(2-1))/(0.01652/(20-2))=0.196125908。有了F值,我们需要根据F检验值的临界表来查找对应的P值。我列出了这张表的常见内容,你可以看看。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/4c/42/4ca490378b2816d293b47c26a56ad642.png" alt="">
|
||||
|
||||
通过这张表以及n和m的值,我们可以找到,在显著性水平α为0.05的时候,F值的临界值。如果大于这个临界值,那么F检验的P值就会小于显著性水平α,证明差异具有显著性。
|
||||
|
||||
在咱们的案例中,n=20,m=s-1=1,所以对应的F值为4.414。而我们计算得到的F值为0.196,远远小于4.414,因此说明差异没有显著性。虽然算法a所导致的平均转化率要比算法b的相对高出约2%(要注意,2%的相对提升在转化率中已经算很高了),但是由于差异没有显著性,所以这个提升的偶然性很大,并不意味着算法a比算法b更好。
|
||||
|
||||
如果需要,你可以在网上相关的统计资料里查找到完整的F检验临界值表。
|
||||
|
||||
## 使用Python代码进行验证
|
||||
|
||||
除了手动的计算,我们还可以用一些Python的代码来验证手动计算是不是准确。
|
||||
|
||||
首先,我们要确保自己安装了Python的扩展包statsmodels。如果没有安装,你可以在命令行中输入下面这行:
|
||||
|
||||
```
|
||||
pip install -U statsmodels
|
||||
|
||||
```
|
||||
|
||||
我们可以把下列数据输入一个oneway.csv文件。
|
||||
|
||||
```
|
||||
algo,ratio
|
||||
a,0.29
|
||||
a,0.36
|
||||
a,0.32
|
||||
a,0.29
|
||||
a,0.34
|
||||
a,0.24
|
||||
a,0.27
|
||||
a,0.29
|
||||
a,0.31
|
||||
a,0.27
|
||||
b,0.29
|
||||
b,0.33
|
||||
b,0.31
|
||||
b,0.30
|
||||
b,0.31
|
||||
b,0.26
|
||||
b,0.25
|
||||
b,0.30
|
||||
b,0.28
|
||||
b,0.29
|
||||
|
||||
```
|
||||
|
||||
安装完了statsmodels,并建立了数据文件oneway.csv,我们就可以运行下面这段Python代码来进行F检验了。
|
||||
|
||||
```
|
||||
import pandas as pd
|
||||
from statsmodels.formula.api import ols
|
||||
from statsmodels.stats.anova import anova_lm
|
||||
import scipy.stats as ss
|
||||
|
||||
|
||||
# 读取数据,d1对应于算法a,d2对应于算法b
|
||||
df = pd.read_csv("/Users/shenhuang/Data/oneway.csv") #设置为你自己的文件路径
|
||||
d1 = df[df['algo'] == 'a']['ratio']
|
||||
d2 = df[df['algo'] == 'b']['ratio']
|
||||
|
||||
|
||||
# 检测两个水平的正态性
|
||||
print(ss.normaltest(d1))
|
||||
print(ss.normaltest(d2))
|
||||
|
||||
|
||||
# 检测两个水平的方差齐性
|
||||
args = [d1, d2]
|
||||
print(ss.levene(*args))
|
||||
|
||||
|
||||
# F检验的第一种方法
|
||||
print(ss.f_oneway(*args))
|
||||
|
||||
|
||||
# F检验的第二种方法
|
||||
model = ols('ratio ~ algo', df).fit()
|
||||
anovat = anova_lm(model)
|
||||
print(ano
|
||||
|
||||
```
|
||||
|
||||
我们假设用于A/B测试的两个算法是相互独立且随机的,所以这里只检测了正态分布性和方差齐性。
|
||||
|
||||
其中,ss.normaltest分别测试了两个水平的正态分布性,两次结果如下:
|
||||
|
||||
```
|
||||
NormaltestResult(statistic=0.16280747339563784, pvalue=0.9218214431590781)
|
||||
NormaltestResult(statistic=0.4189199849120419, pvalue=0.8110220857858036)
|
||||
|
||||
```
|
||||
|
||||
ss.normaltest的原假设是数据符合正态分布,两次检验P值都是远远大于0.05的,所以原假设成立,这两者都符合正态分布。
|
||||
|
||||
而ss.levene分析了两者的方差齐性,同样P值都是远远大于0.05,因此符合方差齐的前提。
|
||||
|
||||
```
|
||||
LeveneResult(statistic=0.7944827586206901, pvalue=0.38450823419725666)
|
||||
|
||||
```
|
||||
|
||||
ss.f_oneway和anova_lm都可以进行F检验。ss.f_oneway给出的结果比较简洁。
|
||||
|
||||
```
|
||||
F_onewayResult(statistic=0.19612590799031476, pvalue=0.663142430745588)
|
||||
|
||||
```
|
||||
|
||||
而anova_lm提供了更多的信息,但是两种F检验函数都证明了我们之前的手动推算结果是正确的。
|
||||
|
||||
```
|
||||
df sum_sq mean_sq F PR(>F)
|
||||
algo 1.0 0.00018 0.000180 0.196126 0.663142
|
||||
Residual 18.0 0.01652 0.000918 NaN NaN
|
||||
|
||||
```
|
||||
|
||||
## 总结
|
||||
|
||||
方差分析可以帮助我们检测差异的显著性,它分析的内容是受一个或多个因素影响的因变量在不同水平分组的差异。不过单因素的方差分析要求因变量属于正态分布总体,并具有方差齐性。如果因变量的分布明显的是非正态,或者方差的差异很显著,那么我们就不能直接使用这种方法。对于方差不齐的情况,我们可以选择适当的函数,例如对数、倒数等等,对原始数据进行转换,直到方差齐性变得显著,或者剔除明显属于“均值±标准差”之外的数据。
|
||||
|
||||
当然,对于非正态分布的数据,我们也可以使用非参数的分析。非参数检验是在总体的方差知道很少的情况下,利用样本数据对总体分布形态等进行推断的方法。名字中的“非参数”的由来,就是因为这种检验方法在推断过程中不涉及有关总体分布的参数,而只是进行分布位置、分布形状之间的比较,因此不受总体分布的限定,适用范围比较广。常见的非参数检验包括二项分布检验、K-S检验、卡方检验等等。
|
||||
|
||||
## 思考题
|
||||
|
||||
请尝试使用Python语言实现你自己的方差分析函数,然后通过测试数据来比较你实现的函数和Python扩展包里的函数(例如statsmodels.stats.anova.anova_lm或scipy.stats.f_oneway)。
|
||||
|
||||
欢迎留言和我分享,也欢迎你在留言区写下今天的学习笔记。你可以点击“请朋友读”,把今天的内容分享给你的好友,和他一起精进。
|
||||
|
||||
|
||||
99
极客时间专栏/程序员的数学基础课/概率统计篇/32 | 概率统计篇答疑和总结:为什么会有欠拟合和过拟合?.md
Normal file
99
极客时间专栏/程序员的数学基础课/概率统计篇/32 | 概率统计篇答疑和总结:为什么会有欠拟合和过拟合?.md
Normal file
@@ -0,0 +1,99 @@
|
||||
<audio id="audio" title="32 | 概率统计篇答疑和总结:为什么会有欠拟合和过拟合?" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/eb/ae/eb2d8f3499cb74b45eb8914c225b4aae.mp3"></audio>
|
||||
|
||||
你好,我是黄申。
|
||||
|
||||
在概率统计这个模块中,我们讲了很多监督式机器学习相关的概念。你可能对朴素贝叶斯、决策树、线性回归这类监督式算法中的一些概念还是不太清楚。比如说,为什么要使用大量的文档集合或者语料库来训练一个朴素贝叶斯模型呢?这个过程最后得到的结果是什么?为什么训练后的结果可以用于预测新的数据?这里面其实涉及了很多模型拟合的知识。
|
||||
|
||||
为了帮助你更好地理解这些内容,今天我就来说说监督式学习中几个很重要的概念:拟合、欠拟合和过拟合,以及如何处理欠拟合和过拟合。
|
||||
|
||||
## 拟合、欠拟合和过拟合
|
||||
|
||||
每种学习模型都有自己的假设和参数。虽然朴素贝叶斯和决策树都属于分类算法,但是它们各自的假设和参数都不相同。朴素贝叶斯的假设是贝叶斯定理和变量之间的独立性,而决策树的假设是集合的纯净程度或者混乱程度。我们这里所说的参数,是指根据模型假设和训练样本推导出来的数据,例如朴素贝叶斯中的参数是各种先验概率和条件概率,而决策树的参数是各个树结点以及结点上的决策条件。
|
||||
|
||||
了解了什么是模型的假设和参数,我们来看看什么是模型的**拟合**(Model Fitting)。在监督式学习中,我们经常提到“训练一个模型”,其实更学术的说法应该是“拟合一个模型”。
|
||||
|
||||
拟合模型其实就是指通过模型的假设和训练样本,推导出具体参数的过程。有了这些参数,我们就能对新的数据进行预测。这样说有些抽象,我画了张一元回归的图来帮助你理解。假设我们的数据点分布在一个二维空间。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/e3/97/e3e14adcdd0b0ffee6f75a4077c4d997.png" alt="">
|
||||
|
||||
其中黑色的点表示训练数据所对应的点,x轴表示唯一的自变量,y轴表示因变量。根据这些训练数据,拟合回归模型之后,所得到的模型结果是一条黑色的曲线。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/89/18/89f0c825e42edfe114d7170dc8695618.png" alt="">
|
||||
|
||||
有了这条曲线,我们就能根据测试数据的x轴取值(如图中的x’)来获取y轴的取值(如图中的y’),也就是根据自变量的值来获取因变量的值,达到预测的效果。这种情况就是**适度拟合**(right fitting)。
|
||||
|
||||
可是,有的时候拟合得到的模型过于简单,和训练样本之间的误差非常大,这种情况就是**欠拟合**(Under Fitting)。比如下面这根黑色的曲线,和第一根曲线相比,它离数据点的距离更大。这种拟合模型和训练样本之间的差异,我们就称为**偏差**(Bias)。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/71/b5/71b543dad1c6626cda01e57af80137b5.png" alt="">
|
||||
|
||||
欠拟合说明模型还不能很好地表示训练样本,所以在测试样本上的表现通常也不好。例如图中预测的值y’’和测试数据x’对应的真实值y’相差很大。
|
||||
|
||||
相对于欠拟合,另一种情况是,拟合得到的模型非常精细和复杂,和训练样本之间的误差非常小,我们称这种情况为**过拟合**(Over Fitting)。比如下面这根黑色的曲线,和第一根曲线相比,离数据点的距离更近,也就是说偏差更小。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/c4/a6/c4b5efe5ea3878edfe0ebc183d85f5a6.png" alt="">
|
||||
|
||||
初学者通常都会觉得过拟合很好,其实并不是这样。过拟合的模型虽然在训练样本中表现得非常优越,但是在测试样本中可能表现不理想。为什么会这样呢?这主要是因为,有的时候,训练样本和测试样本不太一致。
|
||||
|
||||
比如,用于训练的数据都是苹果和甜橙,但是用于测试的数据都是西瓜。在上图中,测试数据x’所对应的y值应该是y’,而不是预测的y’’。这种训练样本和测试样本之间存在的差异,我们称为**方差**(Variance)。在过拟合的时候,我们认为模型缺乏泛化的能力,无法很好地处理新的数据。
|
||||
|
||||
类似地,我以二维空间里的分类为例,展示了适度拟合、欠拟合和过度拟合的情况。仍然假设训练数据的点分布在一个二维空间,我们需要拟合出一个用于区分两个类的分界线。我分别用三张图展示了这三种情况下的分界线。
|
||||
|
||||
首先,第一张是适度拟合的情况。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/79/f3/79fae3f45a2f3637057aac2ce027ebf3.png" alt="">
|
||||
|
||||
这张图中,蓝色的点表示分类1的训练数据点,红色的点表示分类2的训练数据点。在适度拟合的时候,分界线比较好的区分了蓝色和红色的点。
|
||||
|
||||
在欠拟合的时候,模型过于简单,分界线区分训练样本中蓝色和红色点的能力比较弱,存在比较多的错误分类。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/e6/6c/e6d0aec1c5386d0f5c9f5849d3c2766c.png" alt="">
|
||||
|
||||
在过拟合的时候,模型过于复杂,分界线区分训练样本中蓝色和红色点的能力近乎完美,基本上没有错误的分类。但是,如果测试样本和这个训练样本不太一样,那么这个模型就会产生比较大的误差。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/d8/41/d823f53d598cb5f3285546a6b881aa41.png" alt="">
|
||||
|
||||
在常见的监督式学习过程中,适度拟合、欠拟合和过拟合,这三种状态是逐步演变的。我也用一张图来解释这个过程。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/f4/1b/f44c549733d640a4e80eb7c1048ccb1b.png" alt="">
|
||||
|
||||
在这个图中,x轴表示模型的复杂程度,y轴表示预测的误差。蓝色曲线表示模型在训练样本上的表现,它和x轴之间的距离表示了偏差。而红色曲线表示模型在测试样本上的表现,它和蓝色曲线之间的距离表示了方差。
|
||||
|
||||
从图的左侧往右侧看,模型的复杂度由简单逐渐复杂。越复杂的模型,越近似训练样本,所以偏差就不断下降。可是,由于过于近似训练样本,模型和测试样本的差距就会加大,因此在模型复杂度达到一定程度之后,在训练样本上的预测误差反而会开始增加,这样就会导致训练和测试样本之间的方差不断增大。
|
||||
|
||||
在这个图中,最左边是高偏差、低方差,就是我们所说的欠拟合,最右边是低偏差、高方差,就是我们所说的过拟合。在靠近中间的位置,我们希望能找到一个偏差和方差都比较均衡的区域,也就是适度拟合的情况。
|
||||
|
||||
## 如何处理欠拟合和过拟合?
|
||||
|
||||
解释了什么是模型拟合、欠拟合和过拟合,我们下面来说说,有哪些常见的处理过拟合和欠拟合的方法。
|
||||
|
||||
想要解决一个问题,我们先要搞清楚产生这个问题的原因。**欠拟合问题,产生的主要原因是特征维度过少,拟合的模型不够复杂,无法满足训练样本,最终导致误差较大**。因此,我们就可以增加特征维度,让输入的训练样本具有更强的表达能力。
|
||||
|
||||
之前讲解朴素贝叶斯的时候,我提到“任何两个变量是相互独立的假设”,这种假设和马尔科夫假设中的一元文法的作用一致,是为了降低数据稀疏程度、节省计算资源所采取的措施。可是,这种假设在现实中往往不成立,所以朴素贝叶斯模型的表达能力是非常有限的。当我们拥有足够的计算资源,而且希望建模效果更好的时候,我们就需要更加精细、更加复杂的模型,朴素贝叶斯可能就不再适用了。
|
||||
|
||||
比如,在最近非常火的电影《流浪地球》中,计算机系统莫斯拥有全人类文明的数字资料库。假设我们手头也有一个庞大的资料库,也有莫斯那么强大的计算能力,那么使用一元文法来处理数据就有点大材小用了。我们完全可以放弃朴素贝叶斯中关于变量独立性的假设,而使用二元、三元甚至更大的N元文法来处理这些数据。这就是典型的通过增加更多的特征,来提升模型的复杂度,让它从欠拟合阶段往适度拟合阶段靠拢。
|
||||
|
||||
相对应的,**过拟合问题产生的主要原因则是特征维度过多,导致拟合的模型过于完美地符合训练样本,但是无法适应测试样本或者说新的数据**。所以我们可以减少特征的维度。之前在介绍决策树的时候,我提到了这类算法比较容易过拟合,可以使用剪枝和随机森林来缓解这个问题。
|
||||
|
||||
剪枝,顾名思义,就是删掉决策树中一些不是很重要的结点及对应的边,这其实就是在减少特征对模型的影响。虽然去掉一些结点和边之后,决策树对训练样本的区分能力变弱,但是可以更好地应对新数据的变化,具有更好的泛化能力。至于去掉哪些结点和边,我们可以使用前面介绍的特征选择方法来进行。
|
||||
|
||||
随机森林的构建过程更为复杂一些。“森林”表示有很多决策树,可是训练样本就一套,那这些树都是怎么来的呢?随机森林算法采用了统计里常用的可重复采样法,每次从全部n个样本中取出m个(m<n),然后构建一个决策树。重复这种采样并构建决策树的过程若干次,我们就能获得多个决策树。对于新的数据,每个决策树都会有自己的判断结果,我们取大多数决策树的意见作为最终结果。由于每次采样都是不完整的训练集合,而且有一定的随机性,所以每个决策树的过拟合程度都会降低。
|
||||
|
||||
从另一个角度来看,过拟合表示模型太复杂,而相对的训练数据量太少。因此我们也可以增加训练样本的数据量,并尽量保持训练数据和测试数据分布的一致性。如果我们手头上有大量的训练数据,则可以使用交叉验证(Cross Validation)的划分方式来保持训练数据和测试数据的一致性。其核心思想是在每一轮中,拿出大部分数据实例进行建模,然后用建立的模型对留下的小部分实例进行预测,最终对本次预测结果进行评估。这个过程反复进行若干轮,直到所有的标注样本都被预测了一次而且仅一次。如果模型所接受的数据总是在变化,那么我们就需要定期更新训练样本,重新拟合模型。
|
||||
|
||||
## 总结
|
||||
|
||||
第二模块中,我介绍了很多概率统计中常用的概念。随机变量和它的概率分布体现了事物发生的不确定性。而条件概率、联合概率和边缘概率体现了多个随机变量之间的关系以及是不是相互独立,通过这三者的关系,我们可以推导出贝叶斯定理。在贝叶斯定理和变量独立性假设的基础之上,我讲了朴素贝叶斯算法中的公式推导,以及如何使用先验概率来预测后验概率。由于朴素贝叶斯假定多个变量之间相互独立,因此特别适合特征维度很多、特征向量和矩阵很稀疏的场景。基于词包方法的文本分类就是个非常典型的例子。
|
||||
|
||||
文本分类涉及了词与词之间相互独立的假设,然后延伸出多元文法,而多元文法也广泛应用在概率语言模型中。语言模型是马尔科夫模型的一种,而隐马尔科夫模型在马尔科夫模型的基础之上,提出了两层的结构,解决了我们无法直接观测到转移状态的问题。
|
||||
|
||||
由概率知识派生而来的信息论,也能帮助我们设计机器学习的算法,比如决策树和特征选择。统计中的数据分布可以让特征值转换更合理,而假设检验可以告诉我们哪些结论是更可靠的。
|
||||
|
||||
由于很多监督式学习都是基于概率统计的,所以我使用了一些学习算法来进行讲解。你会发现,概率和统计可以帮助这些算法学习训练样本中的特征,并可以对新的数据进行预测,这就是模型拟合的过程。
|
||||
|
||||
## 思考题
|
||||
|
||||
学习完了概率和统计模块,你觉得自己最大的收获和感触是什么?
|
||||
|
||||
欢迎留言和我分享。你可以把今天的内容分享给你的好友,和他一起精进。
|
||||
|
||||
|
||||
Reference in New Issue
Block a user