计算McFadden's R-squared遇ValueError:长度需1却给定118649的解决咨询
修复McFadden's R-squared计算中的ValueError错误
问题背景
尝试手动计算逻辑回归的McFadden's R-squared时触发维度不匹配错误,相关代码及错误信息如下:
原代码
# Calculate McFadden's R-squared log_likelihood_model = -np.sum(y * np.log(y_pred_prob) + (1 - y) * np.log(1 - y_pred_prob)) y_pred_null = np.mean(y) # Predicting the mean of y as a null model log_likelihood_null = -np.sum(y * np.log(y_pred_null) + (1 - y) * np.log(1 - y_pred_null)) mcfaddens_r2 = 1 - (log_likelihood_model / log_likelihood_null) print("McFadden's R-squared:", mcfaddens_r2)
错误输出
/usr/local/lib/python3.10/dist-packages/pandas/core/ops/__init__.py in to_series(right) 237 else: 238 if len(left.columns) != len(right): --> 239 raise ValueError( 240 msg.format(req_len=len(left.columns), given_len=len(right)) 241 ) ValueError: Unable to coerce to Series, length must be 1: given 118649
错误原因
错误核心是y为pandas Series/DataFrame类型,而y_pred_null是单个标量(均值)。pandas执行元素级运算时会严格校验维度:若左侧是多列DataFrame,要求右侧长度等于列数,但此处y_pred_null长度为1,与y的118649条样本量冲突,触发广播逻辑错误。
修复方案
有两种简洁的修复方式:
方案1:将y转换为numpy数组
绕过pandas的维度校验逻辑,直接用numpy数组计算:
import numpy as np # 若y是pandas对象,先转为numpy数组 y = np.array(y) # Calculate McFadden's R-squared log_likelihood_model = -np.sum(y * np.log(y_pred_prob) + (1 - y) * np.log(1 - y_pred_prob)) y_pred_null = np.mean(y) # numpy会自动将标量广播为与y匹配的形状 log_likelihood_null = -np.sum(y * np.log(y_pred_null) + (1 - y) * np.log(1 - y_pred_null)) mcfaddens_r2 = 1 - (log_likelihood_model / log_likelihood_null) print("McFadden's R-squared:", mcfaddens_r2)
方案2:生成与y同形状的空模型预测值
让y_pred_null的维度与y完全一致,避免广播冲突:
import numpy as np # Calculate McFadden's R-squared log_likelihood_model = -np.sum(y * np.log(y_pred_prob) + (1 - y) * np.log(1 - y_pred_prob)) # 生成和y形状完全相同的数组,每个元素都是y的均值 y_pred_null = np.full_like(y, np.mean(y)) log_likelihood_null = -np.sum(y * np.log(y_pred_null) + (1 - y) * np.log(1 - y_pred_null)) mcfaddens_r2 = 1 - (log_likelihood_model / log_likelihood_null) print("McFadden's R-squared:", mcfaddens_r2)
额外优化提示
若使用scikit-learn逻辑回归模型,可直接调用log_loss函数简化计算:
from sklearn.metrics import log_loss log_likelihood_model = -log_loss(y, y_pred_prob, normalize=False) log_likelihood_null = -log_loss(y, [np.mean(y)]*len(y), normalize=False) mcfaddens_r2 = 1 - (log_likelihood_model / log_likelihood_null)
内容的提问来源于stack exchange,提问作者Kezz
相关产品推荐
相关产品推荐

