用了一段时间PYTORCH,感觉这个开始用着很得劲的,所以把BUG梳理一下,再接再厉,祝大家写的一手好BUG,
并能调的通。- —— -
图像分割任务相对特殊的就是他的标签,是类别图,这也是pytorch有意思的一点。
pytorch的NLLLoss2d用来做n类图像分割,接受的每个数据的标签是 W x H 的标签图,每个像素上是该元素的类别号从0开始,到C-1,官方文档是这么描述的:
#Input: (N,C,H,W) where C = number of classes
#Target: (N,H,W) where each value is 0 <= targets[i] <= C-1
所以这种标签图mask在转tensor的时候不能用ToTensor,直接用torch.from_numpy(mask)就好啦。
下为我用的代码的这一部分(放在继承类class MyFolder(ImageFolder)的def __getitem__(self, index)里),写的不好,还请指正:
mask=np.array(mask)[...,0]
#这句为啥一会儿解释,实在是因为BUG,加这么一句调好了两个BUG,神不神奇。
mask_label=np.zeros(mask.shape,dtype=np.int64)
for i,label in enumerate(self.labels[1:]):
mask_label[np.where(mask==label)]=i+1
mask_label=mask_label.astype(np.int64)
好的,下面说下为啥要在上面转类型,因为计算loss的函数规定标签图必须为torch.cuda.LongTensor(如果放进cuda的话),不然就会出这个BUG:
TypeError: CudaClassNLLCriterion_updateOutput received an invalid combination of arguments - got (int, torch.cuda.FloatTensor, !torch.cuda.IntTensor!, torch.cuda.FloatTensor, bool, NoneType, torch.cuda.FloatTensor), but expected (int state, torch.cuda.FloatTensor input, torch.cuda.LongTensor target, torch.cuda.FloatTensor output, bool sizeAverage, [torch.cuda.FloatTensor weights or None], torch.cuda.FloatTensor total_weight)
解决方案分两种:
一种是一开始就在处理数据是用.astype(np.int64)转成long的格式,到时转tensor自动变torch.cuda.LongTensor
还有一种是在转成tensor后放到cuda里前使用Tensor.type(torch.LongTensor)进行转换。
感谢大佬 http://blog.csdn.net/u011276025/article/details/73826562,这个BUG是学习他的自己总结的。
2.cuda bug:
RuntimeError: cuda runtime error (59) : device-side assert triggered at /pytorch/torch/lib/THC/generic/THCStorage.c:32
这个BUG看了好久,大家普遍认为是标签出了问题,仔细断点查找数值变化发现一个人的标签中出现-1,发生了类似的错误:
所以我重新产生了一个0矩阵,只变我的标签像素对应的类别号,这样就滤去了样本标签中可能存在的问题。
问题也可能是别的,我的错误可以这么解决,大致就是:标签有问题!