使用fastai的unet_learner做迁移学习报Target 20越界错误如何解决?
错误原因
这个报错的核心是模型输出的类别数和实际标签中的最大值不匹配:fastai的分割模型默认使用codes数组的长度作为输出类别数,索引从0开始计数。
从你提供的信息可以直接定位问题:
- 你的标签中存在数值
20,意味着需要codes数组至少有21个元素(索引范围0~20) - 你输出的
codes数组只有20个元素,最大索引为19,完全匹配不上标签的20值,因此触发越界错误。
进一步排查可以打印len(codes)和dls.c验证:dls.c是fastai识别的类别数,此时输出一定是20,和你的标签最大值20不匹配。
解决方法
根据你的实际类别数二选一处理:
情况1:你确实有21个类别(标签值范围0~20)
你在转换codes数组时指定了dtype='<U17',限制了字符串长度,同时大概率遗漏了最后一个类别Palustrine Aquatic Bed。修改codes生成逻辑即可:
# 去掉固定字符串长度限制,直接转换 codes = np.array(classes_list) # 确认长度为21后再传入dls print(len(codes))
重新生成dls后,dls.c会变为21,匹配标签的最大值。
情况2:你实际只有20个类别(标签值范围1~20,从1开始计数)
这种情况需要把标签值统一减1,映射到0~19的索引范围,和20个长度的codes对应。你可以在创建dls时自定义标签处理逻辑:
def label_func(fn): label_path = pathB/"labels"/f"{fn.stem}_P.png" # 读取标签后把所有值减1 y = np.array(Image.open(label_path)) - 1 return PILMask.create(y) # 生成dls的时候传入自定义的y处理逻辑 dls = SegmentationDataLoaders.from_label_func( pathB, bs=8, fnames = fnames, label_func = label_func, codes = codes )
处理完成后再执行unet_learner和fine_tune即可正常运行。
内容的提问来源于stack exchange,提问作者OctoCatKnows
相关产品推荐
相关产品推荐

