Pytorch:不支持非正步幅
Pytorch: non-positive stride is not supported
我有一些 MRI 扫描,其中每次扫描都是一组 31 个 RGB 图像。输入数据的维度是(通道、深度、高度、宽度)。图像为 png,每次扫描都是一个包含其 31 个图像的文件夹。
我创建了一个自定义数据集 class:
class TrainImages(Dataset):
def __init__(self, csv_file, root_dir, transform=None):
self.annotations = pd.read_csv(csv_file)
self.root_dir = root_dir
self.transform = transform
def __len__(self):
return len(self.annotations)
def __getitem__(self, index):
img_path = os.path.join(self.root_dir, str(self.annotations.iloc[index, 0]).zfill(5))
image = torch.from_numpy(np.array([np.array(Image.open(os.path.join(str(img_path),"rgb-"+str(i)+".png"))) for i in range(31)]).transpose(3,0,1,2).astype(np.float32))
y_label = torch.tensor(int(self.annotations.iloc[index, 1]))
return (image, y_label)
然后,我创建了一个小型 3D CNN class:
class CNN2(nn.Module):
def __init__(self):
super(CNN2, self).__init__()
self.conv_layer1 = self._conv_layer(3, 12)
def _conv_layer(self, in_c, out_c, conv_kernel_size=3, padding=0):
layer = nn.Sequential(
nn.Conv3d(in_c, out_c, conv_kernel_size, padding),
)
return layer
def forward(self, x):
out = self.conv_layer1(x)
return out
然后,我尝试将一次扫描输入 CNN2 对象:
x=torch.unsqueeze(dataset[0][0], 0)
x.shape #torch.Size([1, 3, 31, 512, 512])
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
data = x.to(device)
model = CNN2().to(device)
model(x)
但是它产生了这个错误:
---------------------------------------------------------------------------
RuntimeError Traceback (most recent call last)
<ipython-input-24-c89306854a22> in <module>
1 model = CNN_test().to(device)
----> 2 model(x)
/opt/conda/lib/python3.7/site-packages/torch/nn/modules/module.py in _call_impl(self, *input, **kwargs)
725 result = self._slow_forward(*input, **kwargs)
726 else:
--> 727 result = self.forward(*input, **kwargs)
728 for hook in itertools.chain(
729 _global_forward_hooks.values(),
<ipython-input-22-ac66ca7a2459> in forward(self, x)
14
15 def forward(self, x):
---> 16 out = self.conv_layer1(x)
17
18 return out
/opt/conda/lib/python3.7/site-packages/torch/nn/modules/module.py in _call_impl(self, *input, **kwargs)
725 result = self._slow_forward(*input, **kwargs)
726 else:
--> 727 result = self.forward(*input, **kwargs)
728 for hook in itertools.chain(
729 _global_forward_hooks.values(),
/opt/conda/lib/python3.7/site-packages/torch/nn/modules/container.py in forward(self, input)
115 def forward(self, input):
116 for module in self:
--> 117 input = module(input)
118 return input
119
/opt/conda/lib/python3.7/site-packages/torch/nn/modules/module.py in _call_impl(self, *input, **kwargs)
725 result = self._slow_forward(*input, **kwargs)
726 else:
--> 727 result = self.forward(*input, **kwargs)
728 for hook in itertools.chain(
729 _global_forward_hooks.values(),
/opt/conda/lib/python3.7/site-packages/torch/nn/modules/conv.py in forward(self, input)
571 self.dilation, self.groups)
572 return F.conv3d(input, self.weight, self.bias, self.stride,
--> 573 self.padding, self.dilation, self.groups)
574
575
RuntimeError: non-positive stride is not supported
然而,当我刚刚创建一个 Conv3D
对象并传入相同的扫描时,没有错误结果:
x=torch.unsqueeze(dataset[0][0], 0)
m=nn.Conv3d(3,12,3)
out=m(x)
我认为错误可能与输入数据的维度有关,但我不明白“非正步幅”是什么意思。我也很困惑,为什么当我将数据传递给 Conv3D
对象时没有发生错误,但是当我将相同的数据传递给 CNN
class 的实例时却发生错误做同样的事情。
问题不在于您的输入形状,它与您的图层初始化有关。您基本上已经使用此行定义了 3D 卷积:
nn.Conv3d(in_c, out_c, conv_kernel_size, padding)
问题是nn.Conv3d
函数头如下:
torch.nn.Conv3d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True, padding_mode='zeros', device=None, dtype=None)
注意 stride
是如何放在 padding
之前的。在您的代码中,变量 padding
最终被分配给 stride
参数。
要解决这个问题,您可以使用关键字参数指定参数名称,即 padding=padding
。这消除了位置参数 stride
和 padding
.
的歧义
class CNN2(nn.Module):
def __init__(self):
super(CNN2, self).__init__()
self.conv_layer1 = self._conv_layer(3, 12)
def _conv_layer(self, in_c, out_c, conv_kernel_size=3, padding=0):
layer = nn.Sequential(
nn.Conv3d(in_c, out_c, conv_kernel_size, padding=padding))
return layer
def forward(self, x):
out = self.conv_layer1(x)
return out
我有一些 MRI 扫描,其中每次扫描都是一组 31 个 RGB 图像。输入数据的维度是(通道、深度、高度、宽度)。图像为 png,每次扫描都是一个包含其 31 个图像的文件夹。
我创建了一个自定义数据集 class:
class TrainImages(Dataset):
def __init__(self, csv_file, root_dir, transform=None):
self.annotations = pd.read_csv(csv_file)
self.root_dir = root_dir
self.transform = transform
def __len__(self):
return len(self.annotations)
def __getitem__(self, index):
img_path = os.path.join(self.root_dir, str(self.annotations.iloc[index, 0]).zfill(5))
image = torch.from_numpy(np.array([np.array(Image.open(os.path.join(str(img_path),"rgb-"+str(i)+".png"))) for i in range(31)]).transpose(3,0,1,2).astype(np.float32))
y_label = torch.tensor(int(self.annotations.iloc[index, 1]))
return (image, y_label)
然后,我创建了一个小型 3D CNN class:
class CNN2(nn.Module):
def __init__(self):
super(CNN2, self).__init__()
self.conv_layer1 = self._conv_layer(3, 12)
def _conv_layer(self, in_c, out_c, conv_kernel_size=3, padding=0):
layer = nn.Sequential(
nn.Conv3d(in_c, out_c, conv_kernel_size, padding),
)
return layer
def forward(self, x):
out = self.conv_layer1(x)
return out
然后,我尝试将一次扫描输入 CNN2 对象:
x=torch.unsqueeze(dataset[0][0], 0)
x.shape #torch.Size([1, 3, 31, 512, 512])
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
data = x.to(device)
model = CNN2().to(device)
model(x)
但是它产生了这个错误:
---------------------------------------------------------------------------
RuntimeError Traceback (most recent call last)
<ipython-input-24-c89306854a22> in <module>
1 model = CNN_test().to(device)
----> 2 model(x)
/opt/conda/lib/python3.7/site-packages/torch/nn/modules/module.py in _call_impl(self, *input, **kwargs)
725 result = self._slow_forward(*input, **kwargs)
726 else:
--> 727 result = self.forward(*input, **kwargs)
728 for hook in itertools.chain(
729 _global_forward_hooks.values(),
<ipython-input-22-ac66ca7a2459> in forward(self, x)
14
15 def forward(self, x):
---> 16 out = self.conv_layer1(x)
17
18 return out
/opt/conda/lib/python3.7/site-packages/torch/nn/modules/module.py in _call_impl(self, *input, **kwargs)
725 result = self._slow_forward(*input, **kwargs)
726 else:
--> 727 result = self.forward(*input, **kwargs)
728 for hook in itertools.chain(
729 _global_forward_hooks.values(),
/opt/conda/lib/python3.7/site-packages/torch/nn/modules/container.py in forward(self, input)
115 def forward(self, input):
116 for module in self:
--> 117 input = module(input)
118 return input
119
/opt/conda/lib/python3.7/site-packages/torch/nn/modules/module.py in _call_impl(self, *input, **kwargs)
725 result = self._slow_forward(*input, **kwargs)
726 else:
--> 727 result = self.forward(*input, **kwargs)
728 for hook in itertools.chain(
729 _global_forward_hooks.values(),
/opt/conda/lib/python3.7/site-packages/torch/nn/modules/conv.py in forward(self, input)
571 self.dilation, self.groups)
572 return F.conv3d(input, self.weight, self.bias, self.stride,
--> 573 self.padding, self.dilation, self.groups)
574
575
RuntimeError: non-positive stride is not supported
然而,当我刚刚创建一个 Conv3D
对象并传入相同的扫描时,没有错误结果:
x=torch.unsqueeze(dataset[0][0], 0)
m=nn.Conv3d(3,12,3)
out=m(x)
我认为错误可能与输入数据的维度有关,但我不明白“非正步幅”是什么意思。我也很困惑,为什么当我将数据传递给 Conv3D
对象时没有发生错误,但是当我将相同的数据传递给 CNN
class 的实例时却发生错误做同样的事情。
问题不在于您的输入形状,它与您的图层初始化有关。您基本上已经使用此行定义了 3D 卷积:
nn.Conv3d(in_c, out_c, conv_kernel_size, padding)
问题是nn.Conv3d
函数头如下:
torch.nn.Conv3d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True, padding_mode='zeros', device=None, dtype=None)
注意 stride
是如何放在 padding
之前的。在您的代码中,变量 padding
最终被分配给 stride
参数。
要解决这个问题,您可以使用关键字参数指定参数名称,即 padding=padding
。这消除了位置参数 stride
和 padding
.
class CNN2(nn.Module):
def __init__(self):
super(CNN2, self).__init__()
self.conv_layer1 = self._conv_layer(3, 12)
def _conv_layer(self, in_c, out_c, conv_kernel_size=3, padding=0):
layer = nn.Sequential(
nn.Conv3d(in_c, out_c, conv_kernel_size, padding=padding))
return layer
def forward(self, x):
out = self.conv_layer1(x)
return out