手动计算Log Loss与Scikit-Learn cross_val_score结果不符问题
Scikit-Learn cross_val_score与手动Log Loss计算不一致的原因及解决
核心问题
你手动计算Log Loss时用了predict()返回的类别标签,而log_loss函数需要的是模型输出的概率值,这和cross_val_score内部计算neg_log_loss的逻辑完全不同。
具体差异
- 你的手动代码中,
y_train_pred = clf_logreg.predict(X_train)返回的是离散的类别(0或1)。当把这类标签代入log_loss时,相当于强制将概率设为1(对应预测类别)或0(非预测类别),一旦样本预测错误,log(0)会被近似为极大的负值,最终损失值被大幅拉高,这就是你看到的train_loss和val_loss远高于cross_val结果的原因。 cross_val_score使用scoring='neg_log_loss'时,内部会自动调用模型的predict_proba()方法,获取每个样本属于各类别的概率分布(比如二分类场景下返回[[1-p, p], ...]),再基于这些概率计算对数损失,这才是log_loss的正确使用方式。
修正后的手动计算代码
把predict()替换为predict_proba(),并提取对应类别的概率(以二分类为例,取正类概率[:, 1]):
kfold = KFold(n_splits=10) train_loss = [] val_loss = [] for train_index, val_index in kfold.split(X, y): clf_logreg = LogisticRegression() X_train, X_val = X[train_index], X[val_index] y_train, y_val = y[train_index], y[val_index] clf_logreg.fit(X_train, y_train) # 替换predict为predict_proba,取正类概率 y_train_pred_proba = clf_logreg.predict_proba(X_train)[:, 1] y_val_pred_proba = clf_logreg.predict_proba(X_val)[:, 1] train_loss.append(log_loss(y_train, y_train_pred_proba)) val_loss.append(log_loss(y_val, y_val_pred_proba)) clf_logreg.fit(X,y) y_error = cross_val_score(clf_logreg, X, y, cv=kfold, scoring='neg_log_loss') print("cross_val log_loss: ", -y_error) print("\ntrain_loss: ", train_loss) print("\nval_loss: ", val_loss)
修正后,手动计算的val_loss会和cross_val log_loss的结果一致(误差在浮点精度范围内)。
内容的提问来源于stack exchange,提问作者Ulisses Morais
相关产品推荐
相关产品推荐

