如何在Python中计算预测数组的负对数似然
计算正态分布假设下的负对数似然
核心思路
既然假设每个实际值对应的预测值服从正态分布,我们可以基于正态分布的概率密度函数推导负对数似然。对于单个实际值 ( y ),若其对应的预测值服从 ( \mathcal{N}(\mu, \sigma^2) ),则该样本的负对数似然为:
[
\text{NLL}(y) = 0.5 \times \left( \ln(2\pi) + \ln(\sigma^2) + \frac{(y - \mu)2}{\sigma2} \right)
]
其中:
- ( \mu ) 是对应预测值子列表的均值
- ( \sigma^2 ) 是对应预测值子列表的方差
整体的负对数似然可以是所有样本NLL的总和,或者平均值(根据需求选择)。
Python实现步骤
我们用numpy来高效完成数值计算,无需依赖额外工具包:
- 导入依赖
import numpy as np
- 转换数据格式
把列表转成numpy数组,方便批量计算均值和方差:
# 示例数据(替换成你的实际数据) Y = [2.5, 4.2, 6.7] predictions = [ [2.3, 2.6, 2.4] + [2.5]*97, # 对应Y[0]的100个预测值 [4.1, 4.3, 4.0] + [4.2]*97, # 对应Y[1]的100个预测值 [6.5, 6.8, 6.6] + [6.7]*97 # 对应Y[2]的100个预测值 ] # 转成numpy数组 Y_np = np.array(Y) predictions_np = np.array(predictions)
- 计算每个样本的均值和方差
# 计算每个子列表的均值(axis=1表示按行计算) mu = np.mean(predictions_np, axis=1) # 计算每个子列表的样本方差(ddof=1表示除以n-1,符合无偏估计;若用总体方差则ddof=0) sigma_sq = np.var(predictions_np, axis=1, ddof=1)
- 计算负对数似然
# 避免方差为0导致除以0的情况,给极小值 sigma_sq = np.maximum(sigma_sq, 1e-10) # 计算单个样本的NLL nll_per_sample = 0.5 * (np.log(2 * np.pi) + np.log(sigma_sq) + ((Y_np - mu) ** 2) / sigma_sq) # 整体负对数似然(可选总和或均值) total_nll = np.sum(nll_per_sample) mean_nll = np.mean(nll_per_sample) print(f"整体负对数似然(总和):{total_nll}") print(f"平均负对数似然:{mean_nll}")
注意事项
- 方差为0的处理:如果某个预测值子列表的所有值完全相同,方差会为0,此时需要给方差加一个极小值(如
1e-10),避免计算中出现除以0的错误。 - 方差的选择:如果你的预测值是总体的全部数据,用
ddof=0计算总体方差;如果是样本,用ddof=1计算无偏样本方差,根据你的数据场景选择。 - 数据维度:确保
Y的长度和predictions的子列表数量一致,否则会出现维度不匹配的错误。
内容的提问来源于stack exchange,提问作者Gabriel Turner
相关产品推荐
相关产品推荐

