为类别不平衡优化:动态半径Radius Neighbors Classifier准确率计算
多分类动态半径Radius Neighbors Classifier的准确率计算方案
你当前的代码存在核心问题:每个分类器仅训练了单一类别的样本,直接调用score得到的是"将所有测试样本判定为该类"的准确率,完全不符合多分类任务的评估逻辑。下面是正确的实现步骤和代码:
修正思路
- 关联分类器与类别:存储每个分类器对应的类别标签,避免后续预测时混淆。
- 样本匹配判断:对每个测试样本,遍历所有分类器,用
radius_neighbors检查样本是否在该类的半径范围内存在邻居,收集所有匹配的候选类别。 - 确定最终预测类别:根据匹配结果采用对应规则:
- 仅一个类别匹配:直接归为该类
- 多个类别匹配:投票选择出现次数最多的类
- 无类别匹配:选择距离该样本最近的类作为预测结果
- 计算整体准确率:将所有测试样本的预测标签与真实标签对比,用准确率指标评估。
修正后的代码
from sklearn.neighbors import RadiusNeighborsClassifier from sklearn.metrics import accuracy_score from collections import Counter # 定义每个类的动态半径 class_radius = { 'class1': 0.5, 'class2': 0.7, 'class3': 0.6, 'class4': 0.1, 'class5': 0.2, 'class6': 0.8, 'class7': 0.6 } # 存储分类器及其对应的类别标签 classifier_pairs = [] for class_label, radius in class_radius.items(): # 筛选当前类的训练样本 X_class = X_resampled[y_resampled == class_label] y_class = y_resampled[y_resampled == class_label] if len(X_class) == 0: continue # 训练对应半径的分类器 classifier = RadiusNeighborsClassifier(radius=radius) classifier.fit(X_class, y_class) # 同时保存类别和分类器 classifier_pairs.append( (class_label, classifier) ) # 自定义多分类预测函数 def predict_dynamic_radius(X_test): y_pred = [] for sample in X_test: sample = sample.reshape(1, -1) # 适配模型输入维度 matched_classes = [] # 遍历所有分类器,检查样本是否匹配当前类 for class_label, clf in classifier_pairs: # 获取半径内的邻居索引,无邻居则返回空数组 neighbors_in_radius = clf.radius_neighbors(sample, return_distance=False) if len(neighbors_in_radius[0]) > 0: matched_classes.append(class_label) # 根据匹配结果确定最终预测类别 if len(matched_classes) == 1: y_pred.append(matched_classes[0]) elif len(matched_classes) > 1: # 多匹配时采用投票策略 class_count = Counter(matched_classes) y_pred.append(max(class_count, key=class_count.get)) else: # 无匹配时选择距离最近的类 min_distance = float('inf') best_class = None for class_label, clf in classifier_pairs: # 计算样本到当前类最近样本的距离 nearest_dist, _ = clf.kneighbors(sample, n_neighbors=1) if nearest_dist[0][0] < min_distance: min_distance = nearest_dist[0][0] best_class = class_label y_pred.append(best_class) return y_pred # 生成测试集预测结果 y_pred = predict_dynamic_radius(X_test) # 计算整体准确率 overall_accuracy = accuracy_score(y_test, y_pred) print(f"多分类任务整体准确率: {overall_accuracy}")
关键说明
- 替换
predict为radius_neighbors:predict在无半径内邻居时会返回训练集第一个样本的标签,无法准确判断样本是否属于当前类,必须用radius_neighbors检查邻居存在性。 - 灵活调整分类规则:如果你的任务有特殊需求(比如更看重某类的召回率),可以修改匹配后的决策逻辑,比如给特定类的匹配结果加权。
内容的提问来源于stack exchange,提问作者shel coop
相关产品推荐
相关产品推荐

