You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Scipy Gaussian KDE报错:矩阵非正定,如何估算样本密度?

嘿,这个问题我之前处理过,根源在于你的样本量太小啦!

问题原因分析

你给出的示例里只有3个3D数据点,样本数量刚好等于数据维度。这种情况下,样本的协方差矩阵是奇异的(秩不足),而scipy.stats.gaussian_kde默认会基于样本协方差矩阵做Cholesky分解——但奇异矩阵不是正定的,自然就抛出LinAlgError了。哪怕是实际数据,如果样本量接近或小于维度,也会碰到这个问题。

解决方案

下面给你几种可行的修复方法,按需选择:

方法1:给协方差矩阵加正则化项

直接给协方差矩阵添加一个极小的对角矩阵,强制让它变成正定矩阵,这样就能顺利完成Cholesky分解了:

from scipy.stats import gaussian_kde
import numpy as np

A = np.array([[0.078377 , 0.76737392, 0.45038174], 
              [0.65990129, 0.13154658, 0.30770917], 
              [0.46068406, 0.22751313, 0.28122463]])
B = np.array([[0.40209377, 0.21063273, 0.75885516], 
              [0.91709997, 0.79303252, 0.65156937]])

# 初始化KDE对象
kde = gaussian_kde(A.T)
# 添加正则化:给协方差矩阵加一个极小的单位矩阵倍数
epsilon = 1e-6
kde.covariance = kde.covariance + epsilon * np.eye(kde.d)

# 现在可以正常计算密度了
result = kde(B.T)
print(result)

你也可以通过调整covariance_factor来增大带宽,让密度估计更平滑,间接避免奇异矩阵问题:

# 自定义带宽因子(比默认值大,会让密度更平滑)
kde.covariance_factor = lambda: 0.5
# 更新协方差矩阵
kde._compute_covariance()
# 再计算密度
result = kde(B.T)

方法2:改用sklearn的KernelDensity类

sklearn.neighbors.KernelDensity对小样本/高维数据的兼容性更好,支持直接设置带宽,不需要手动处理协方差矩阵:

from sklearn.neighbors import KernelDensity
import numpy as np

A = np.array([[0.078377 , 0.76737392, 0.45038174], 
              [0.65990129, 0.13154658, 0.30770917], 
              [0.46068406, 0.22751313, 0.28122463]])
B = np.array([[0.40209377, 0.21063273, 0.75885516], 
              [0.91709997, 0.79303252, 0.65156937]])

# 初始化KDE,设置合适的带宽(可根据数据调整)
kde = KernelDensity(kernel='gaussian', bandwidth=0.5)
kde.fit(A)
# 计算对数密度,再转换为原始密度
log_density = kde.score_samples(B)
result = np.exp(log_density)
print(result)

方法3:针对极小样本的特殊处理

如果你的实际数据样本量确实远小于维度,核密度估计可能不是最优选择。可以考虑:

  • 先对数据做降维(比如PCA),降低维度后再做密度估计
  • 改用**混合高斯模型(GMM)**来拟合数据分布,再计算点的密度

内容的提问来源于stack exchange,提问作者usernumber

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 06:52:45