如何用Python不调用scikit-learn的score()函数计算模型偏差D
自定义计算拟合优度偏差D的Python实现
实现思路
- 仅依赖numpy完成数值计算,不引入scikit-learn相关工具
- 严格按照给定公式计算,对Y=0的特殊场景按规则单独处理对数项
- 加入极小值
epsilon避免除0、log(0)等数值异常问题 - 提供循环实现(易读)和向量化实现(高效)两种版本,适配不同使用场景
代码实现
首先导入依赖:
import numpy as np
基础循环版本(逻辑清晰,适合小数据量)
def calculate_deviance(Y, E_Y, epsilon=1e-10): """ 计算拟合优度偏差D 参数: Y: 真实观测值数组,形状为(n_samples,) E_Y: 模型预测的期望值数组,形状为(n_samples,) epsilon: 极小值,避免对数计算和除法出现数值错误 返回: D: 偏差值 """ deviance_sum = 0 for y, ey in zip(Y, E_Y): if y == 0: # 按规则Y=0时对数项为0,仅计算减法部分 term = 0 - (y - ey) else: ratio = y / (ey + epsilon) log_term = np.log(ratio) term = y * log_term - (y - ey) deviance_sum += term return 2 * deviance_sum
向量化版本(计算效率高,适合大数据量)
def calculate_deviance_vectorized(Y, E_Y, epsilon=1e-10): """ 向量化实现的偏差计算函数 """ # 筛选Y不为0的样本位置 non_zero_mask = Y != 0 term_array = np.zeros_like(Y, dtype=np.float64) # 计算Y不为0的样本项 y_non_zero = Y[non_zero_mask] ey_non_zero = E_Y[non_zero_mask] ratio = y_non_zero / (ey_non_zero + epsilon) term_array[non_zero_mask] = y_non_zero * np.log(ratio) - (y_non_zero - ey_non_zero) # 计算Y为0的样本项 term_array[~non_zero_mask] = 0 - (Y[~non_zero_mask] - E_Y[~non_zero_mask]) return 2 * np.sum(term_array)
使用示例
# 测试样本 Y = np.array([0, 2, 3, 5, 0, 7]) E_Y = np.array([0.5, 1.8, 3.2, 4.9, 0.1, 6.8]) # 调用计算 print(calculate_deviance(Y, E_Y)) print(calculate_deviance_vectorized(Y, E_Y))
注意事项
- 输入的Y和E_Y需要保证长度一致,否则会出现计算错误
- epsilon取值可根据实际精度需求调整,默认1e-10可覆盖绝大多数场景
- 若输入Y为整数类型,建议先转换为浮点类型再传入函数,避免整数除法导致的精度损失
内容的提问来源于stack exchange,提问作者V.T
相关产品推荐
相关产品推荐

