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

statsmodels powerdiscrepancy测试报错:样本数匹配仍触发ValueError

statsmodels powerdiscrepancy 触发 ValueError:维度一致仍报错

问题场景

调用statsmodels.stats.gof.powerdiscrepancy做拟合优度检验时,已确认观测集(真实标签Y)和模型预测结果的维度均为(140,),但仍抛出错误:

ValueError: observed and expected need to have the same number of observations, or e needs to add to 1
中文翻译:观测值与期望值需拥有相同的观测数量,或期望值总和需为1

复现代码

def discrepancy_test(Y, result):
    """
    针对分类问题变量计算拟合优度检验
    参数
    ----------
    Y : np.array
        真实标签数组
    result : Result实例
        训练好的分类模型结果
    """
    from statsmodels.stats.gof import powerdiscrepancy
    import pandas as pd
    
    print(Y.shape, result.predict().shape)
    dtest = powerdiscrepancy(Y, result.predict())
    pd.DataFrame(dtest, columns=['variables', 'p_value'])


discrepancy_test(Y, result_pr)

运行输出:

(140,) (140,)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[120], line 1
----> 1 discrepancy_test(Y, result_pr)

Cell In[119], line 15, in discrepancy_test(Y, result)
      3 """
      4 Calculate discrepancy test for the variables of the classification problem
      5 
   (...)
     12 
     13 """
     14 print(Y.shape, result.predict().shape)
---> 15 dtest = powerdiscrepancy(result.predict(), Y)
     16 pd.DataFrame(dtest, columns=['variables', 'p_value'])

File c:\Users\user\AppData\Local\Programs\Python\Python310\lib\site-packages\statsmodels\stats\gof.py:153, in powerdiscrepancy(observed, expected, lambd, axis, ddof)
    151     e = nt * e
    152 else:
--> 153     raise ValueError('observed and expected need to have the same '
    154                      'number of observations, or e needs to add to 1')
    155 k = o.shape[axis]
    156 if e.shape[axis] != k:

ValueError: observed and expected need to have the same number of observations, or e needs to add to 1

问题根源

这个错误的核心不是维度不匹配,而是**powerdiscrepancy对expected参数的定义和你传入的内容不匹配**:

  • 该函数接受两种类型的expected输入:
    1. 与observed同维度的逐样本期望值(比如每个观测对应的连续预测值);
    2. 总和为1的概率分布(对应类别的期望占比)。
  • 但分类模型的predict()默认返回的是类别标签(如0/1、类别ID),这类值既不是逐样本的连续期望值,总和也不可能为1,因此触发校验错误。

解决办法

根据你的检验需求,选择以下两种方式之一:

方式1:传入类别计数(适合检验类别分布拟合度)

先统计真实标签和预测标签的类别出现次数,再传入函数:

def discrepancy_test(Y, result):
    from statsmodels.stats.gof import powerdiscrepancy
    import numpy as np
    import pandas as pd

    # 统计真实标签的类别计数
    observed_counts = np.bincount(Y)
    # 统计预测标签的类别计数
    predicted_counts = np.bincount(result.predict())
    
    print(observed_counts.shape, predicted_counts.shape)
    dtest = powerdiscrepancy(observed_counts, predicted_counts)
    return pd.DataFrame(dtest, columns=['variables', 'p_value'])

方式2:传入逐样本预测概率(适合检验单样本拟合度)

如果模型支持输出概率,调用predict_proba()获取每个样本对应真实类别的预测概率,作为期望值传入:

def discrepancy_test(Y, result):
    from statsmodels.stats.gof import powerdiscrepancy
    import pandas as pd
    import numpy as np

    # 获取所有样本的类别概率矩阵
    probs = result.predict_proba()
    # 提取每个样本对应真实类别的概率
    expected_probs = probs[np.arange(len(Y)), Y]
    
    print(Y.shape, expected_probs.shape)
    dtest = powerdiscrepancy(Y, expected_probs)
    return pd.DataFrame(dtest, columns=['variables', 'p_value'])

注意:powerdiscrepancy本质是检验观测分布与期望分布的差异,输入需为计数数据或概率/连续预测值,而非原始类别标签序列。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 21:21:49