之前遇到过一次记录下来了,第一次遇到
翻看之前的记录,首先想着如何让pycharm准确地显示错误。
1:os.environ[‘CUDA_LAUNCH_BLOCKING’] = '1’,模型前加这句,但是我在train文件中已经加了,还是不清楚报错原因。
2:使用cpu运行,将模型中所有的.cuda删除掉,to(device)的device改为cpu。
报错原因:Target -2 is out of bound。
2.1:于是去train文件用到交叉熵的地方追根溯源。
3:首先想到的就是pred和target维度不匹配导致无法计算交叉熵,于是打印了一下pred:[list4]:大小都是(1,40,480,640)。打印了一下target:[list4]:大小都是(1,480,640)。在交叉熵中通过for 循环遍历,送到交叉熵函数中。维度大小是匹配的。
维度匹配那么就是数值大小有问题了,仔细看了一下target_scale里面的数值,从[0到40],标签中的0代表空像素,然后pred里面的数值各种数值都有,接着重要的事情就发生了:
当我执行过 final_out, segmap16, segmap8, segmap4, sobel_edge, sobel_gt = model(sample)
这一行时,**target_scale里面的数值竟然发生了变换。里面的数值都减1,导致0变为-1,40变为39了。**因此在交叉熵时候targets_m = targets_m_1 - 1
,导致标签中为-1的像素值变成了-2。
4:这里有两个问题,①:为什么target_scale里面的数值发生了变换?
②:如何解决Target为-2的问题?
5:对于第一个问题:
我感到很奇怪,我又没有使用target_scale,为什么里面的数值发生了变换?
但是可以肯定的是执行过model后,发生变换,变换的原因要去model里面找。
于是我一步一步的debug model。
找到了model中唯一用到label的地方,且labe=sample[‘label’]是经过这一行改变的:
sobel_edge, sobel_gt = self.conf1(edge_map, label)
然后跳到另一个文件中:
label = label - 1
label_select = torch.clip(label, min=0, max=40)
label_one_hot = F.one_hot(label_select.to(torch.int64), 40).permute(0, 3, 1, 2)
为了对label进行one-hot编码,我首先删除掉了标签中数值为0的像素点,因为0代表空。
所以就是这句代码导致target里面的数值发生改变:
label = label - 1
label减1后,没有进行新的变换,导致减一的label继承下来,导致经过model之后的target数值发生改变。
代码修改为:
new_label = label - 1
label_select = torch.clip(new_label , min=0, max=40)
重新修改后,target=-2的情况就解决了,但是:
targets_m = targets_m_1 - 1
target_m_1中包含有-1,进行交叉熵计算的时候肯定是不行的,但是不减又不行因为要删除空像素,且类别为40。需要对target进行select_mask操作,接着我根据:
loss_all = self.ce_loss(inputs, targets_m.long())
跳到:
self.ce_loss = nn.CrossEntropyLoss(
torch.from_numpy(np.array(weight)).float(),
reduction='none',
ignore_index=-1
)
发现了参数中包括:ignore_index=-1,他会主动忽视掉索引为-1的值,因此自动屏蔽,不需要任何操作,就这个点想了很久没想明白,太大意了,没有看到这个参数,之前见到以为从来不会用到,这下打脸了。
!!!!!!!!!!!!!!!!!花了一上午终于解决了,完结撒花!!!!!!!!!!!!!!!!!