查看全课大纲(第 64 / 82 节)
- 1.函数与数据泛化
- 2.向量:从几何直觉到高维空间
- 3.矩阵与张量
- 4.特征值与特征向量:矩阵变换的不动方向
- 5.凸函数:从向量求导的矩阵记号到好优化的函数形状
- 6.概率与统计:机器学习的数学基础
- 7.独立性与随机变量:贝叶斯公式与二项分布
- 8.期望、方差与协方差:随机变量的数字画像
- 9.联合概率:当一条轴不够用的时候
- 10.概率分布(一):从伯努利到伽马函数
- 11.概率分布(二):贝塔、泊松、正态与两个贝叶斯故事
- 12.机器学习的模型:找输入与输出的关系
- 13.机器学习的应用
- 14.过拟合
- 15.机器学习的分类
- 16.有监督学习:从房价预测说起
- 17.损失函数
- 18.梯度下降(上):更新规则与学习速率
- 19.梯度下降(2)
- 20.牛顿方法
- 21.KNN简介
- 22.距离测算
- 23.朴素贝叶斯
- 24.朴素贝叶斯的实际应用
- 25.信息熵:决策树构建的度量基础
- 26.信息增益与决策树的构建
- 27.ID3算法
- 28.决策树节点的划分
- 29.CART树
- 30.Bagging
- 31.Boosting:自适应提升算法
- 32.Gradient Boosting
- 33.线性模型:回归与分类的同一副骨架
- 34.最小二乘:把最优参数直接解出来
- 35.最小二乘法的几何与概率视角
- 36.极大似然:给最小二乘一个概率出身
- 37.逻辑回归(1):把线性模型接到分类上
- 38.逻辑回归(2):损失函数与多分类
- 39.---- 手造数据: 5 个样本, 2 个特征; x2 几乎 = 2*x1 (偏差手工指定, 无随机) ----
- 40.讲师例: 向量 "23014" -- 三把范数尺子量同一个向量
- 41.优化方法(1):坐标下降与前向选择
- 42.优化方法(2):前向策略与最小角回归
- 43.拉格朗日乘子法(1):从无约束到等式约束
- 44.拉格朗日乘子法(2):等式约束下的平行条件与拉格朗日函数
- 45.拉格朗日乘子法(3):不等式约束与 KKT 条件
- 46.最大间隔:把分类问题变成优化问题
- 47.拉格朗日对偶问题:把 w 和 b 全部换成 α
- 48.支持向量:边界上的少数派
- 49.SVM 计算过程:一笔到底算完,再走进核方法
- 50.贝叶斯公式:概率即信念
- 51.隐含变量和概率模型:给看不见的原因建模
- 52.EM 算法:期望与最大化的迭代
- 53.琴生不等式:EM 的数学钥匙
- 54.三个硬币问题:EM 的复盘与衔接
- 55.高斯混合模型:用隐变量解释双峰数据
- 56.隐马尔可夫模型
- 57.隐马尔可夫模型(2):前向算法与动态混合模型
- 58.隐马尔可夫模型在 NLP 中的运用
- 59.EM 算法:把「为什么收敛」推到底
- 60.HMM 在 NLP 中的运用:从分词到机器翻译
- 61.HMM 参数估计:Baum-Welch 的三块拉格朗日
- 62.高维下的高斯模型
- 63.主题模型:从词袋到隐含主题
- 64.Dirichlet 分布(1)
- 65.Dirichlet 分布(2)
- 66.统计学习内容回顾
- 67.K-means 算法
- 68.PCA 降维
- 69.SVD 降维
- 70.从聚类到流形
- 71.局部线性嵌入
- 72.随机邻域嵌入:SNE 与 t-SNE
- 73.无参模型:让数据自己说话
- 74.高斯过程:函数空间里的正态分布
- 75.高斯过程(2):噪声、正则化与核的线性组合
- 76.神经网络简介:从感知器到自编码器
- 77.反向传播:把误差一层层传回去
- 78.卷积神经网络(CNN):让特征自己学出来
- 79.循环神经网络(RNN):给网络装上记忆
- 80.深度学习回顾:静态一类,动态一类
- 81.增强学习(1):蒙特卡洛、树搜索与 Q-learning
- 82.强化学习(2):从乌鸦吃核桃到井字棋的 value 回传
Dirichlet 分布(1)
约 27 分钟
小象实战讲义 · 机器学习算法精讲
在进入完整的主题模型之前,我们需要掌握一个关键的数学工具——狄利克雷分布(Dirichlet Distribution),名字来自 19 世纪数学家狄利克雷。它是理解后续隐含狄利克雷分配(LDA)等模型的基础。本节我们将深入探讨狄利克雷分布的定义、性质及其直观含义,理解它为何被称为”分布的分布”,并初步了解其在多层概率模型中的作用。
💡 核心导读
- 狄利克雷分布的定义:一个定义在 维单纯形上的概率分布,其采样结果是一个向量,且向量各分量之和为1。
- 伽马函数的作用:作为阶乘在实数域的推广,用于构造狄利克雷分布的概率密度函数。
- “分布的分布”:狄利克雷分布的采样结果本身可以作为一个概率分布(例如,多项分布的参数),因此它是生成分布的分布。
- 参数 的直观影响: 全相等且大于1时,采样点向中心集中;全相等且小于1时,采样点向边缘(角落)集中; 不相等时,分布偏向对应分量大的那个角落。
- 从单层到多层隐含变量模型:通过引入狄利克雷分布,可以将模型的参数(如硬币的正面概率 )也视为随机变量,由超参数 控制,从而构建层次化贝叶斯模型——这正是 LDA 等主题模型的核心思想。
从分布到”分布的分布”
我们熟悉的正态分布,采样产生一个实数值(高维正态则产生一个普通向量)。而狄利克雷分布是一种定义在 维空间中的多元分布:它的随机变量 是一个 维向量,参数 也是一个 维向量——给两个分量 ,生成的就是二维数据;给 ,生成的就是三维数据。这与上一节的观察一脉相承:高维空间的数据,可以由高维的参数来控制。
它最神奇的特性是:从该分布中采样得到的一个样本 ,其各分量之和恒为 1,即 。比如采出 ,三个分量加起来必须是 1。这意味着这个向量 本身就可以被视作一个概率分布——例如它可以作为某个三取值随机变量 取各值的概率。一个分布采样出来的结果又是分布,所以我们常说狄利克雷分布是”分布的分布”。
采样结果落在什么位置上?所有满足各分量非负、总和为 1 的点,构成 维空间中的单纯形(Simplex):
- 时,单纯形是连接 与 的一条线段,线上任何一点横纵坐标之和恒为 1。
- 时,单纯形是由三个顶点 、、 围成的一个三角面,面上任何一点三个坐标之和都是 1。
狄利克雷分布要做的,就是决定”在这条线段/这块三角面上,哪些地方容易被采到、哪些地方不容易被采到”。
伽马函数:阶乘的延伸
狄利克雷分布的概率密度函数中使用了伽马函数。它可以从阶乘讲起:,,,……把 这些点画在坐标系里,它们随着 不断增大。一个自然的问题是:有没有一条连续的曲线,能穿过所有整数阶乘对应的点? 事实证明是有的——阶乘只是这条连续曲线在整数点上的特例,这条曲线就是伽马函数 。
伽马函数是阶乘在实数域(甚至复数域)上的推广。对于正整数 ,有 。例如,,,,。有了它,我们甚至可以求 这样的”非整数阶乘”——其值就是 。
在狄利克雷分布中,伽马函数主要用于归一化常数部分,确保概率密度函数在全空间的积分为 1。
狄利克雷分布的数学形式与参数
一个 维的狄利克雷分布,其概率密度函数为:
其中:
- 是随机变量,满足 且 。
- 是分布的参数,要求 。
- 是归一化常数,称为多元贝塔函数,由伽马函数定义: 。
当 时,狄利克雷分布退化为我们熟悉的贝塔分布。因此,狄利克雷分布是贝塔分布向高维的推广。
参数 的直观影响
参数 控制着采样点在单纯形上的集中趋势: 全相等时分布是对称的——全为 1 时是单纯形上的均匀分布;全大于 1(如 、)时中间取点概率最大、越到边缘越小;全小于 1(如 )时边缘上取到的概率反而最大、中间较小。若 不对称,值大的那个分量对应的角落概率最大。我们可以通过一个二维(即贝塔分布)的采样实验来直观感受。
import random
def dirichlet_sample(alphas):
"""从狄利克雷分布(参数为alphas)中采样一个点(伽马采样法)"""
samples = []
for a in alphas:
# 从形状参数为a、尺度参数为1的伽马分布采样,再归一化
samples.append(random.gammavariate(a, 1))
total = sum(samples)
return [s / total for s in samples]
random.seed(42)
print("不同参数下贝塔分布(二维狄利克雷)的采样示例(每组采样5次):")
print("-" * 60)
test_cases = [(1, 1), (5, 5), (2, 8), (0.5, 0.5), (0.2, 5)]
for alpha in test_cases:
print(f"\nα = {alpha}:")
for i in range(5):
sample = dirichlet_sample(alpha)
print(f" 第{i+1}次采样: x1 = {sample[0]:.4f}, x2 = {sample[1]:.4f} (和为 {sum(sample):.4f})")不同参数下贝塔分布(二维狄利克雷)的采样示例(每组采样5次):
------------------------------------------------------------
α = (1, 1):
第1次采样: x1 = 0.9758, x2 = 0.0242 (和为 1.0000)
第2次采样: x1 = 0.5601, x2 = 0.4399 (和为 1.0000)
第3次采样: x1 = 0.5415, x2 = 0.4585 (和为 1.0000)
第4次采样: x1 = 0.9608, x2 = 0.0392 (和为 1.0000)
第5次采样: x1 = 0.9477, x2 = 0.0523 (和为 1.0000)
α = (5, 5):
第1次采样: x1 = 0.3473, x2 = 0.6527 (和为 1.0000)
第2次采样: x1 = 0.2900, x2 = 0.7100 (和为 1.0000)
第3次采样: x1 = 0.6317, x2 = 0.3683 (和为 1.0000)
第4次采样: x1 = 0.5236, x2 = 0.4764 (和为 1.0000)
第5次采样: x1 = 0.5532, x2 = 0.4468 (和为 1.0000)
α = (2, 8):
第1次采样: x1 = 0.2798, x2 = 0.7202 (和为 1.0000)
第2次采样: x1 = 0.1886, x2 = 0.8114 (和为 1.0000)
第3次采样: x1 = 0.0577, x2 = 0.9423 (和为 1.0000)
第4次采样: x1 = 0.1927, x2 = 0.8073 (和为 1.0000)
第5次采样: x1 = 0.3483, x2 = 0.6517 (和为 1.0000)
α = (0.5, 0.5):
第1次采样: x1 = 0.3373, x2 = 0.6627 (和为 1.0000)
第2次采样: x1 = 0.1020, x2 = 0.8980 (和为 1.0000)
第3次采样: x1 = 0.2737, x2 = 0.7263 (和为 1.0000)
第4次采样: x1 = 0.1821, x2 = 0.8179 (和为 1.0000)
第5次采样: x1 = 0.9507, x2 = 0.0493 (和为 1.0000)
α = (0.2, 5):
第1次采样: x1 = 0.0000, x2 = 1.0000 (和为 1.0000)
第2次采样: x1 = 0.0000, x2 = 1.0000 (和为 1.0000)
第3次采样: x1 = 0.0556, x2 = 0.9444 (和为 1.0000)
第4次采样: x1 = 0.0000, x2 = 1.0000 (和为 1.0000)
第5次采样: x1 = 0.1281, x2 = 0.8719 (和为 1.0000)观察输出,我们可以总结规律:
- :均匀分布。线段上任何点被采样的概率相同,采样值散布在整个区间,没有集中或避让的趋势。
- :所有分量相等且大于1。采样点向中心 附近集中(五次都在 0.29~0.63 之间),不会跑到极端位置。
- :分量不相等。 远大于 ,采样点倾向于使 的分量更大( 全部不超过 0.35),即靠近 这个角落。
- :所有分量相等且小于1。采样点向两端集中——0.1020 和 0.9507 都紧贴端点,中间区域相对较少。
- :一个分量极小、一个较大。分布强烈偏向 大的方向,同时 极小使 几乎总是贴着 0(三次采出 0.0000),偶尔才蹦出一个稍大的值。
为了更清晰地验证 全小于 1 时”边缘概率大、中间概率小”的特性,我们做一次 100 次采样的统计:
import random
def dirichlet_sample(alphas):
"""从狄利克雷分布(参数为alphas)中采样一个点(伽马采样法)"""
samples = []
for a in alphas:
samples.append(random.gammavariate(a, 1))
total = sum(samples)
return [s / total for s in samples]
def sample_and_count(alpha, num_samples=100):
"""采样并统计x1落在角落区域与中心区域的比例"""
left_count = 0 # x1 靠近 0 端
right_count = 0 # x1 靠近 1 端
center_count = 0
for _ in range(num_samples):
x1 = dirichlet_sample(alpha)[0]
if x1 < 0.1:
left_count += 1
if x1 > 0.9:
right_count += 1
if 0.4 <= x1 <= 0.6:
center_count += 1
return left_count, right_count, center_count
random.seed(42)
alpha_small = (0.5, 0.5)
left, right, center = sample_and_count(alpha_small, 100)
print(f"采样总数: 100")
print(f"x1 落在 [0, 0.1) 的比例: {left/100:.3f}")
print(f"x1 落在 (0.9, 1.0] 的比例: {right/100:.3f}")
print(f"x1 落在 [0.4, 0.6] 的比例: {center/100:.3f}")
print(f"两个角落的总比例: {(left+right)/100:.3f}")采样总数: 100
x1 落在 [0, 0.1) 的比例: 0.230
x1 落在 (0.9, 1.0] 的比例: 0.180
x1 落在 [0.4, 0.6] 的比例: 0.090
两个角落的总比例: 0.410可以看到,当 分量都小于 1 时,落在两个角落区域的比例合计 0.410,远高于落在正中间的 0.090——边缘吸引、中间排斥,验证了上面的规律。
构建层次化概率模型:从硬币到LDA
狄利克雷分布最重要的应用之一是构建层次化贝叶斯模型。我们通过回顾之前的隐含变量模型来理解这种层次结构。
先回顾硬币问题:隐含变量 (选哪枚硬币)取 0 或 1, 的概率是 ——参数 控制着整个模型。如果 不是硬币而是一枚骰子, 就可以取 1 到 6,对应概率 ,而且所有 相加必须等于 1——这正是隐含变量 的基础概率分布,它自己就是一个单纯形上的点。
这个 以前是需要估计的参数。现在我们换一种思维方式:把 也当成一个随机变量。它从何而来?假设 本身是从一个狄利克雷分布中采样得到的—— 有几维( 有几种取值),狄利克雷就有几维。于是我们得到一个层层向上的生成过程:
- 超参数层:固定一个超参数 (例如 )。
- 参数层:从狄利克雷分布 中采样,得到参数 (例如 ,也可能采出 )。
- 隐含变量层:对于第 次实验,根据 这个分布采样隐含变量 (以 0.3 的概率取 0,以 0.7 的概率取 1)。
- 观测数据层:根据 的值,从对应的分布中采样观测数据 。
由狄利克雷采样生成, 由 采样生成,每个 再由 生成——两层隐含变量。而位于最顶端的 ,就是整个模型真正的参数,我们称之为超参数(hyperparameter)。以前 和 都是”参数”,现在它们都可以被看作隐含变量。这就是 LDA(Latent Dirichlet Allocation,隐含狄利克雷分配) 的雏形。
顺带一提这段工作的来历:LDA 是 2003 年提出的经典论文,三位作者中,David Blei 当时这是他读博士期间的工作(后来成为哥伦比亚大学教授),Michael Jordan 是 UC Berkeley 教授、统计学习领域的旗帜性人物,Andrew Ng(吴恩达)后来曾出任百度的首席科学家。这篇论文引用量极高,它引入的多层贝叶斯模型影响深远。
LDA 这个模型当然不只是用来掷硬币的——用它来解释”看了 H T T H 之后预测下一个结果”完全没问题,原先硬币由 控制,现在由更上层的参数控制。但它最重要的应用在自然语言:把”硬币”换成上一节说的主题硬币——宗教硬币、计算机硬币等等,模型立刻就能描述文档的生成。
用主题模型的语言把整个生成过程重新说一遍:
- 每个词 是我们看到的观测,它由一个主题 决定。
- 而一篇文档的主题混合 (即”这位同学手里各类硬币的比例”)不是一个值——它的维度等于主题个数 ,这个 是人为固定的参数,不是模型学出来的。
- 最上层由超参数 控制生成 ;对文档中的每个词,根据 采样主题 ,再根据主题 采样词 。
- 整个过程重复:一篇文档 个词,语料库共 篇文档。
还缺一块拼图:给定主题 ,词 的概率怎么取?掷硬币时它是一个伯努利分布,由参数 控制;而现在给定一个 topic,词是整个词表上的一个复杂的离散分布,而且每个 topic 各不相同。我们把这些分布排成一个矩阵:行是 个主题(),列是词表里的 个词()。比如”宗教硬币”那一行,god 这个词的概率很大;“计算机硬币”那一行,出现最多的是 Windows,而 god 的概率几乎为零。这个 的矩阵我们记作 ,它作用在”生成词”的那一步—— 取几,就去 里取第几行,再按那一行的分布采出具体的词。
为了直观展示这个生成过程,我们模拟一个简化版的文档生成:两个主题、三个词的词表。首先从狄利克雷分布生成文档的主题分布 ,然后为每个词根据 选择一个主题,最后根据选定主题的词分布(即 的对应行)生成具体的词。
import random
def dirichlet_sample(alphas):
"""从狄利克雷分布(参数为alphas)中采样一个点(伽马采样法)"""
samples = []
for a in alphas:
samples.append(random.gammavariate(a, 1))
total = sum(samples)
return [s / total for s in samples]
def categorical_sample(probs):
"""根据概率分布probs进行类别采样"""
r = random.random()
cumulative = 0.0
for i, p in enumerate(probs):
cumulative += p
if r < cumulative:
return i
return len(probs) - 1 # 防止浮点误差
random.seed(42)
# 两个主题,词表三个词:['学习', '数据', '算法']
# β 矩阵:每个主题在词表上的分布
phi_0 = [0.1, 0.6, 0.3] # 主题0的词分布 P(词|主题0)
phi_1 = [0.7, 0.1, 0.2] # 主题1的词分布 P(词|主题1)
beta = [phi_0, phi_1]
# 超参数alpha,控制文档的主题分布(偏向主题1)
alpha = [2, 5]
# 1. 从狄利克雷分布生成文档的主题分布 theta
theta = dirichlet_sample(alpha)
print(f"主题 0 的词分布 φ_0: {phi_0}")
print(f"主题 1 的词分布 φ_1: {phi_1}")
print(f"\n文档的主题分布 θ: [{theta[0]:.3f}, {theta[1]:.3f}]")
# 2. 生成一个包含5个词的文档
vocab = ['学习', '数据', '算法']
document = []
for word_idx in range(5):
# a. 根据主题分布theta,为当前词选择一个主题z
z = categorical_sample(theta)
# b. 根据选定的主题z,从β的第z行(该主题的词分布)中采样一个词
word = categorical_sample(beta[z])
print(f"生成第{word_idx+1}个词: 主题z={z}, 词='{vocab[word]}'")
document.append(vocab[word])
print(f"\n生成的文档(词序列): {document}")主题 0 的词分布 φ_0: [0.1, 0.6, 0.3]
主题 1 的词分布 φ_1: [0.7, 0.1, 0.2]
文档的主题分布 θ: [0.140, 0.860]
生成第1个词: 主题z=1, 词='学习'
生成第2个词: 主题z=1, 词='学习'
生成第3个词: 主题z=1, 词='学习'
生成第4个词: 主题z=0, 词='数据'
生成第5个词: 主题z=1, 词='学习'
生成的文档(词序列): ['学习', '学习', '学习', '数据', '学习']在这个例子中,超参数 偏向主题 1,采样得到的文档主题分布 确实给了主题 1 更大的权重(注意这是随机采样,换一次运行 会不同,只是总体上偏向主题 1)。随后,每个词先按 选主题(5 个词里 4 个选了主题 1),再按该主题的词分布( 的对应行)生成具体的词——主题 1 下”学习”概率最大(0.7),所以文档里”学习”最多;第 4 个词恰好按 14% 的概率抽到了主题 0,于是从 中采出了它概率最大的词”数据”(0.6)。这正是 LDA 中”超参数 → 文档主题分布 → 每个词的主题 → 每个词”的完整层次化生成过程。
📝 动手练一练
- 概念辨析:为什么说狄利克雷分布是”分布的分布”?请用掷骰子的例子类比说明。假设有一个六面骰子,每个面朝上的概率不同,这个概率分布本身如果是随机的,可以用什么分布来描述它?
👉 点击查看参考答案
狄利克雷分布之所以被称为"分布的分布",是因为从该分布中采样得到的结果(一个各分量和为1的向量)本身就可以作为一个概率分布。例如,一个六面骰子,其概率分布可以表示为 ,满足 。如果我们认为这个概率分布 不是固定的,而是随机变化的(比如,每次换一个质地不均匀的骰子),那么描述 这个"分布"如何随机变化的分布,就是一个六维的狄利克雷分布 。其中超参数 控制了这些不同骰子概率分布的总体倾向(例如,是否倾向于公平,还是倾向于某些数字)。- 代码实验:修改上面”构建层次化概率模型”部分的代码,将超参数 改为 。重新运行多次(可以修改随机种子),观察生成的文档主题分布 有什么特点?生成的文档在用词上是否会表现出更强的”主题专一性”或”主题混合性”?
👉 点击查看参考答案
将 `alpha = [2, 5]` 修改为 `alpha = [0.5, 0.5]`。由于 分量都小于1,根据狄利克雷分布的性质,采样得到的文档主题分布 会倾向于"极端化",即要么几乎全是主题0,要么几乎全是主题1,而较少出现两者混合均匀的情况。这意味着生成的文档更可能只由一个主导主题构成,用词上也更集中于该主题对应的词分布中的高频词,从而表现出更强的"主题专一性"。你可以通过多次运行并打印 的值来验证这一点。本章小结
本节我们深入学习了狄利克雷分布,这是理解现代主题模型的关键数学基础。我们掌握了它的定义(单纯形上各分量和为 1 的分布)、作为”分布的分布”的核心特性、伽马函数与概率密度形式,以及参数 如何控制采样点的集中趋势(全大于 1 居中、全小于 1 逼边、不对称偏角)。更重要的是,我们看到了如何把传统模型中的参数 升级为由超参数 控制的随机变量,得到”超参数 → 参数分布 → 隐含变量 → 观测”的层次结构,加上主题-词矩阵 ,LDA 的完整框架已经在眼前。
📋 行动清单
- 理解”分布的分布”:确保能用自己的话解释为什么狄利克雷分布的采样结果可以作为一个概率分布。
- 可视化参数影响:在脑海中或纸上画出不同 参数下,二维狄利克雷分布(贝塔分布)采样点的大致密度图(中心集中、均匀、角落集中)。
- 模拟层次生成:运行并理解本节中简化版文档生成的代码,尝试修改超参数 和主题词分布 ,观察生成文档的变化,体会”超参数 → 文档主题分布 → 词”的层次生成逻辑。
—— 小象教研组
配套资料 · 直接下载
课件、代码、数据集等配套资料全部免费,点击即可直接下载,无需分享或解锁。