序数分类器预测缺失最高类别问题求助
序数分类器预测缺失最高类别问题的解决
问题背景
我基于以下资料实现序数分类器:
- 核心思路来源:《用任意分类器训练序数回归的简单技巧》
- 代码参考:Stack Overflow上的序数分类器使用问答
训练数据集包含5个有用性等级类别(1-5),但使用参考代码对测试集预测时,仅能输出1-4的等级结果,训练集(n=1000)和测试集(n=15000)样本量均充足。
原始代码
from sklearn.base import clone import numpy as np from sklearn.neighbors import KNeighborsClassifier # 补充缺失的导入 class OrdinalClassifier(): def __init__(self, clf): self.clf = clf self.clfs = {} def fit(self, X, y): self.unique_class = np.sort(np.unique(y)) if self.unique_class.shape[0] > 2: for i in range(self.unique_class.shape[0] - 1): # 为每个序数阈值拟合一个二分类器 binary_y = (y > self.unique_class[i]).astype(np.uint8) clf = clone(self.clf) clf.fit(X, binary_y) self.clfs[i] = clf def predict_proba(self, X): clfs_predict = {k: v.predict_proba(X) for k, v in self.clfs.items()} predicted = [] for i, y in enumerate(self.unique_class): if i == 0: # V1 = 1 - Pr(y > V1) predicted.append(1 - clfs_predict[i][:, 1]) elif y in clfs_predict: # Vi = Pr(y > Vi-1) - Pr(y > Vi) predicted.append(clfs_predict[i - 1][:, 1] - clfs_predict[i][:, 1]) else: # Vk = Pr(y > Vk-1) predicted.append(clfs_predict[i - 1][:, 1]) return np.vstack(predicted).T def predict(self, X): return self.unique_class[np.argmax(self.predict_proba(X), axis=1)] knn = KNeighborsClassifier() oc = OrdinalClassifier(knn) oc.fit(X_train, y_train) oc.predict(X_test)
问题原因
代码中predict_proba方法的条件判断逻辑错误:
- 当类别数为5时,
self.clfs的键是0、1、2、3(对应4个二分类器) - 遍历
self.unique_class([1,2,3,4,5])时,对于y=4(i=3),判断y in clfs_predict即检查4是否在{0,1,2,3}中,结果为False,导致该类别的概率计算错误,进而最高类别5的概率无法成为最大值,最终预测结果中不会出现5。
修正方案
将predict_proba方法中的elif y in clfs_predict改为elif i in clfs_predict,因为clfs的键是循环索引i,而非类别值y。
修正后的predict_proba方法:
def predict_proba(self, X): clfs_predict = {k: v.predict_proba(X) for k, v in self.clfs.items()} predicted = [] for i, y in enumerate(self.unique_class): if i == 0: # V1 = 1 - Pr(y > V1) predicted.append(1 - clfs_predict[i][:, 1]) elif i in clfs_predict: # Vi = Pr(y > Vi-1) - Pr(y > Vi) predicted.append(clfs_predict[i - 1][:, 1] - clfs_predict[i][:, 1]) else: # Vk = Pr(y > Vk-1) predicted.append(clfs_predict[i - 1][:, 1]) return np.vstack(predicted).T
额外检查项:确认训练集y_train中确实包含所有5个类别,可通过print(np.unique(y_train))验证,避免因训练集类别缺失导致的问题。
内容的提问来源于stack exchange,提问作者DoubiXu
相关产品推荐
相关产品推荐

