Python3 SVM图像训练出现KeyError: 'NU'问题求助
分析并解决SVM自定义函数中的KeyError: 'NU'问题
看起来你在自定义SVM相关函数时踩了个典型的类型匹配坑——咱们来一步步拆解问题,搞定这个报错。
报错根源
你的classWiseData函数逻辑里存在一个关键矛盾:
- 你先用
CLASSES = len(np.unique(labels))算出类别数是2,然后初始化了一个以数字0、1为键的字典; - 但你的实际标签
labels里存的是字符串类型(比如报错里的'NU',还有另一类'u')。当循环执行data[y[i]].append(x[i])时,程序试图用字符串'NU'去访问字典的键,可字典里根本没有这个键,直接触发KeyError。 - 至于sklearn的SVM能正常跑,是因为它内部自动处理了字符串标签的映射,不需要你手动做这一步。
两种可行解决方案
方案1:把字符串标签转成数字(推荐,适配你原有的函数逻辑)
你可以先给字符串标签做个数字映射,让字典的键和标签类型统一。要么在调用函数前预处理标签,要么在函数内部直接处理:
方法A:在函数内部自动处理映射
修改后的classWiseData函数:
def classWiseData(x,y): # 获取所有唯一标签,创建字符串→数字的映射表 unique_labels = np.unique(y) label_to_idx = {label: idx for idx, label in enumerate(unique_labels)} data = {} # 用数字键初始化字典 for idx in range(len(unique_labels)): data[idx] = [] for i in range(x.shape[0]): # 把当前标签转成数字后再作为键 data[label_to_idx[y[i]]].append(x[i]) for k in data.keys(): data[k] = np.array(data[k]) return data
方法B:提前预处理标签再传入
如果你不想改函数,也可以先把标签转成数字:
# 先做标签映射 unique_labels = np.unique(labels) label_map = {label: idx for idx, label in enumerate(unique_labels)} numeric_labels = np.array([label_map[label] for label in labels]) # 再调用原函数 data = classWiseData(image_data, numeric_labels)
方案2:直接用字符串标签当字典键
如果不想折腾类型转换,直接用原始的字符串标签作为字典的键更直观,修改后的函数如下:
def classWiseData(x,y): data = {} # 用所有唯一字符串标签初始化字典 for label in np.unique(y): data[label] = [] for i in range(x.shape[0]): # 直接用原始字符串标签访问字典 data[y[i]].append(x[i]) for k in data.keys(): data[k] = np.array(data[k]) return data
注意:用这个方案的话,你后续的accuracy函数里,predict方法返回的结果也得是字符串类型(和原始标签一致),不然对比的时候会出错。
验证修改
不管用哪种方案,修改后再调用data = classWiseData(image_data,labels),应该就能正常生成类别字典了,后续的模型训练和准确率计算环节也不会再报错。
内容的提问来源于stack exchange,提问作者kapil kap's
相关产品推荐
相关产品推荐

