如何计算多元Pandas DataFrame的KL散度?兼谈高斯过程训练早停
KL散度是否适用于多元分布?
KL散度完全可以用于多元分布,不管是连续型还是离散型多元分布都适用。不过要注意两个关键点:
- KL散度是不对称的:( D(P||Q) \neq D(Q||P) ),所以你需要明确是计算“前10个样本的分布P相对于后10个样本的分布Q的散度”,还是反过来,或者取两者的均值。
- 计算的前提是能准确估计两个多元分布的概率密度函数(PDF)。
多元KL散度的计算方法
情况1:假设自变量服从多元高斯分布
如果你的5个自变量可以近似为多元高斯分布,多元KL散度有解析解,公式如下:
对于两个多元高斯分布 ( P \sim \mathcal{N}(\mu_P, \Sigma_P) ) 和 ( Q \sim \mathcal{N}(\mu_Q, \Sigma_Q) ),KL散度为:
[
D(P||Q) = \frac{1}{2} \left( \text{tr}(\Sigma_Q^{-1}\Sigma_P) + (\mu_Q - \mu_P)T\Sigma_Q{-1}(\mu_Q - \mu_P) - k - \ln\left(\frac{\det(\Sigma_P)}{\det(\Sigma_Q)}\right) \right)
]
其中 ( k ) 是自变量的维度(这里是5),( \text{tr} ) 是矩阵迹,( \det ) 是矩阵行列式。
用Python实现的示例:
import numpy as np from scipy.stats import multivariate_normal # 假设前10个样本的自变量矩阵为X_prev,后10个为X_new X_prev = df_prev[['x1','x2','x3','x4','x5']].values X_new = df_new[['x1','x2','x3','x4','x5']].values # 估计多元高斯参数 mu_p = np.mean(X_prev, axis=0) sigma_p = np.cov(X_prev.T) mu_q = np.mean(X_new, axis=0) sigma_q = np.cov(X_new.T) # 计算KL散度 def kl_multivariate_gaussian(mu_p, sigma_p, mu_q, sigma_q): k = len(mu_p) sigma_q_inv = np.linalg.inv(sigma_q) term1 = np.trace(sigma_q_inv @ sigma_p) term2 = (mu_q - mu_p).T @ sigma_q_inv @ (mu_q - mu_p) term3 = np.log(np.linalg.det(sigma_q) / np.linalg.det(sigma_p)) return 0.5 * (term1 + term2 - k + term3) kl_val = kl_multivariate_gaussian(mu_p, sigma_p, mu_q, sigma_q)
情况2:非参数估计(无分布假设)
如果自变量不服从高斯分布,用核密度估计(KDE)近似PDF,再通过数值积分计算KL散度:
from sklearn.neighbors import KernelDensity import scipy.integrate as integrate # 拟合KDE模型 kde_p = KernelDensity(kernel='gaussian', bandwidth=0.5).fit(X_prev) kde_q = KernelDensity(kernel='gaussian', bandwidth=0.5).fit(X_new) # 定义被积函数:p(x) * log(p(x)/q(x)) def integrand(x): log_p = kde_p.score_samples([x])[0] log_q = kde_q.score_samples([x])[0] return np.exp(log_p) * (log_p - log_q) # 数值积分(根据自变量实际取值范围设置上下限) bounds = [(df['x1'].min(), df['x1'].max()), (df['x2'].min(), df['x2'].max()), (df['x3'].min(), df['x3'].max()), (df['x4'].min(), df['x4'].max()), (df['x5'].min(), df['x5'].max())] kl_val, _ = integrate.nquad(integrand, bounds)
更优的早停替代方案
你的初步方案通过样本分布相似性判断,但样本分布相似不代表模型性能不再提升,反之亦然。更直接的早停逻辑应围绕模型是否还能从新增样本中获得有效信息,推荐以下几种方案:
1. 验证集性能监控(最常用)
- 维护独立验证集,每次迭代后用验证集评估模型的预测误差(如MSE、MAE、对数似然)。
- 设置阈值:比如连续5次迭代,验证误差的下降幅度小于1e-5,满足条件则停止训练。
- 优势:直接关联模型实际性能,贴合早停核心目标。
2. 高斯过程后验变化监控
高斯过程是贝叶斯模型,新增样本会更新后验分布,可监控:
- 后验均值变化:比较新增样本前后,验证集上后验均值差异的L2范数,连续多次小于阈值则停止。
- 后验协方差收缩:监控后验协方差矩阵的迹的变化,迹越小模型不确定性越低,当迹的变化量连续小于阈值时停止。
- 证据下界(ELBO):若使用变分高斯过程,ELBO的变化可衡量拟合提升,连续多次ELBO上升幅度小于阈值则停止。
3. 样本冗余度度量
- 计算新增样本与已有训练集的最小马氏距离(考虑特征相关性),若连续N个新增样本的最小马氏距离都小于阈值,说明样本冗余,无新信息。
- 或用余弦相似度(适用于标准化特征),判断新增样本是否落在已有样本的密集区域。
4. 核参数稳定性监控
高斯过程的核函数参数(如RBF核的长度尺度、噪声项)会随训练样本增加逐渐收敛。监控这些参数的变化量,当连续多次迭代参数的相对变化小于阈值(如1%),说明模型已稳定,无需继续训练。
内容的提问来源于stack exchange,提问作者alvarella

