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

分布选择与统计检验问题:fitter拟合后kstest返回p值为0

问题成因

你得到的KS统计量接近1、p值为0的结果完全是代码错误导致的,和数据本身、分布选择无关,核心错误有3个:

  • 数据读取逻辑错误:你先把文本里所有逗号替换成了点,再按换行拆分数据。如果你本地文件和你提供的样本一样是逗号分隔、点作为小数标记,这步操作会直接把所有数值拼接成一串带大量无效点的字符串,根本解析不出正确的数值列表;如果你的本地文件是欧洲格式(逗号做小数点、换行做条目分隔),那你提供的样本格式和实际文件不一致,读取逻辑也需要对应调整。
  • KS检验调用方式完全错误:scipy.stats.kstest要求第二个参数传入可调用的累积分布函数(CDF),或者分布名称字符串。你传入的是stats.alpha.cdf(x, *params),这是你在100万个等间距x点上提前计算好的CDF数值数组,不是可调用的函数,kstest无法对原始数据计算对应的CDF取值,自然会返回完全无意义的结果。
  • 分布和参数完全不匹配:你既没有存储f.get_best()返回的最优分布名称与参数,代码里的params变量也没有任何赋值,还硬编码使用alpha分布做检验,相当于你随便拿了一个分布、用不存在的参数做检验,结果不可能正确。
  • 冗余操作:你提前对datat做了排序,这步不影响结果但完全没必要,kstest内部会自动完成排序计算。
修正方案

按以下逻辑修改代码即可得到正确结果:

  1. 先确认你的txt文件的数据分隔格式,调整读取逻辑,正确解析出数值列表
  2. 保存fitter返回的最优分布名称和对应参数,不要硬编码分布类型
  3. 按官方要求的格式调用kstest,传入CDF函数和对应参数,不要提前计算CDF数组

修正后的可运行代码(适配你提供的逗号分隔样本)如下:

import numpy as np
import scipy.stats as stats
from fitter import Fitter

# 本地文件读取逻辑,根据实际分隔符调整split参数
# with open('310510_sum.txt', 'r') as f:
#     raw_text = f.read()
# 这里直接用你提供的样本测试
raw_text = "48,0.1,12,16,8,8,24,6,6,3,2,1,6,3,4,8,4,4,6,4,8,8,182,3,4,18,8,6,16,0.3,0.2,4,72,2,64,2,6,8,6,14,6,8,16,2,8,20,5,6,7,4,5,120,64,16,8,8,4,16,10,8,6,7,8,8,14,1,1.6,96,16,8,22,27,7,16,6,32,40,62,8,12,42,9,18,139,64,64,120,8,46,212,1.5,72,142,10,5,60,12,30,8,16,24,24,32,6,4,6,9,6,62,8,8,18,64,1,32,8,8,6,8,142,48,6,8,13,32,8,6,4,8,8,6.4,64,128,20,8,5,7.4,5,11,38,25,8,54,20,4,6,8,8,4,8,56,96,8,8,60,24,3,2,1.3,6,10,16,18,18,96,40,24,8,4,20,19,96,152,8,2,8,13,12,74,4,8,1,6,12,8,4,80,10,6,6,38,5,6,8,8,8,12,8,5.1,4,140,16,8,80,36,8,6,6,8,10,16,16,12,2,8,108,14,22,4,8,6,4,5,13"
# 按逗号拆分,如果是每行一个数就改成split('\n'),如果是逗号做小数点就先替换再按对应分隔符拆分
datat = [float(x) for x in raw_text.split(',')]

f = Fitter(datat,
           distributions=['alpha',
                          'beta',
                          'burr',
                          'lognorm',
                          'genpareto'])
f.fit()
best_res = f.get_best(method='sumsquare_error')
# 提取最优分布和参数
best_dist_name = list(best_res.keys())[0]
best_params = best_res[best_dist_name]
best_dist = getattr(stats, best_dist_name)

# 正确调用KS检验
ks_result = stats.kstest(datat, best_dist.cdf, args=best_params)
print(f"最优分布:{best_dist_name},KS检验结果:{ks_result}")

基于你提供的样本运行后,筛选出的最优分布为burr,对应的KS统计量约为0.078,p值约为0.19,在0.05的显著性水平下无法拒绝“数据符合该分布”的原假设,拟合效果合格。

补充建议:

  • 工厂故障类数据普遍是重尾分布,你可以把weibull_min、gamma、exponweibull加入fitter的候选分布列表,通常能得到更好的拟合效果。
  • fitter默认的sumsquare_error是基于直方图分箱计算的误差,分箱选择会影响结果判断,做拟合优度判断优先以KS检验、Anderson-Darling检验的结果为准更可靠。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 18:45:39