Scipy分布拟合中NLLF Loss数值异常问题咨询
正态分布数据拟合对数正态分布后NLLF低于原生正态分布的问题
我生成了10000个标准正态分布的数据点,分别计算其在原生正态分布(使用生成数据的真实参数)和拟合后的对数正态分布上的NLLF(负对数似然函数),结果发现对数正态分布的NLLF反而更低,且二者数值接近,这和预期不符。
代码示例
import scipy.stats mu, sigma = 0, 1 X = scipy.stats.norm(loc=mu, scale=sigma) x = X.rvs(size=10000) print('Norm NLLF:', scipy.stats.norm.nnlf((mu, sigma), x)) params = scipy.stats.lognorm.fit(x) print('LogNorm NLLF:', scipy.stats.lognorm.nnlf(params, x))
运行结果
Norm NLLF: 14369.799291446736 LogNorm NLLF: 14366.683866496474
原因分析
- 抽样误差与参数适配性:原生正态分布使用的是生成数据的真实参数,但样本是随机生成的,存在抽样波动,并非完美的正态分布;而对数正态分布的参数是针对当前样本做的最大化似然估计,完全适配这个特定样本的特征,因此可能在该样本上获得更高的似然(更低的NLLF)。
- 对数正态分布的灵活性:Scipy中的对数正态分布支持
loc(位置)参数,通过调整该参数可以将分布平移,覆盖负数区域,从而近似拟合正态分布的数据,进一步提升了对当前样本的适配能力。
修正方案
若要验证数据是否符合正态分布,应比较拟合后的正态分布与拟合后的对数正态分布的NLLF,而非使用生成数据的真实参数。修改后的代码如下:
import scipy.stats mu, sigma = 0, 1 X = scipy.stats.norm(loc=mu, scale=sigma) x = X.rvs(size=10000) # 拟合正态分布参数并计算NLLF norm_fit_params = scipy.stats.norm.fit(x) print('Fitted Norm NLLF:', scipy.stats.norm.nnlf(norm_fit_params, x)) # 拟合对数正态分布参数并计算NLLF lognorm_fit_params = scipy.stats.lognorm.fit(x) print('LogNorm NLLF:', scipy.stats.lognorm.nnlf(lognorm_fit_params, x))
运行后,拟合后的正态分布NLLF会低于对数正态分布,符合数据的真实分布特征。
另外需注意:对数正态分布的原始定义仅适用于正数数据,若数据包含负数,该分布本就不是合适的候选模型,验证前应先确认数据的定义域与分布的适配性。
内容的提问来源于stack exchange,提问作者Hadar Shavit
相关产品推荐
相关产品推荐

