编辑:我可以解决它(希望它能满足我的要求)。但我不明白为什么它现在有效。我把我的解决方法放在底部。会很棒,如果有人能启发我,为什么它有效(或者为什么笔记本没有它也能工作)。
我使用本教程中的代码:
https://amaarora.github.io/posts/2020-09-13-unet.html#understanding-input-and-output-shapes-in-u-net
它在我的笔记本代码中运行。
现在我尝试为我的模型调整此代码。因此,我将它复制到我的 model.py 中,它只有一个类 AENet 并相应地调整它。但是 PyCharm 已经发出警告
对象“编码器”不可调用 对象“解码器”不可调用
当我从终端调用它时,程序中断了。
之前:
class AENet(nn.Module):
def __init__(self,input_dim, block_size):
super(AENet,self).__init__()
self.input_dim = input_dim
self.cov_source = nn.Parameter(torch.zeros(block_size, block_size), requires_grad=False)
self.cov_target = nn.Parameter(torch.zeros(block_size, block_size), requires_grad=False)
self.encoder = nn.Sequential(
nn.Linear(self.input_dim,128),
nn.BatchNorm1d(128,momentum=0.01, eps=1e-03),
nn.ReLU(),
nn.Linear(128,8),
nn.BatchNorm1d(8,momentum=0.01, eps=1e-03),
nn.ReLU(),
)
self.decoder = nn.Sequential(
nn.Linear(8,128),
nn.BatchNorm1d(128,momentum=0.01, eps=1e-03),
nn.ReLU(),
nn.Linear(128,self.input_dim)
)
def forward(self, x):
z = self.encoder(x.view(-1,self.input_dim))
return self.decoder(z), z
在我对 AENet 类进行复制+粘贴和改编后,它看起来像这样
class Block(nn.Module):
def __init__(self, in_ch, out_ch):
super().__init__()
self.conv1 = nn.Conv2d(in_ch, out_ch, 3)
self.relu = nn.ReLU()
self.conv2 = nn.Conv2d(out_ch, out_ch, 3)
def forward(self, x):
return self.conv2(self.relu(self.conv1(x)))
class Encoder(nn.Module):
def __init__(self, chs=(1, 64, 128, 256, 512, 1024)):
super().__init__()
self.enc_blocks = nn.ModuleList([Block(chs[i], chs[i + 1]) for i in range(len(chs) - 1)])
self.pool = nn.MaxPool2d(2)
def forward(self, x):
ftrs = []
for block in self.enc_blocks:
x = block(x)
ftrs.append(x)
x = self.pool(x)
return ftrs
class Decoder(nn.Module):
def __init__(self, chs=(1024, 512, 256, 128, 64)):
super().__init__()
self.chs = chs
self.upconvs = nn.ModuleList([nn.ConvTranspose2d(chs[i], chs[i + 1], 2, 2) for i in range(len(chs) - 1)])
self.dec_blocks = nn.ModuleList([Block(chs[i], chs[i + 1]) for i in range(len(chs) - 1)])
def forward(self, x, encoder_features):
for i in range(len(self.chs) - 1):
x = self.upconvs[i](x)
enc_ftrs = self.crop(encoder_features[i], x)
x = torch.cat([x, enc_ftrs], dim=1)
x = self.dec_blocks[i](x)
return x
def crop(self, enc_ftrs, x):
_, _, H, W = x.shape
enc_ftrs = torchvision.transforms.CenterCrop([H, W])(enc_ftrs)
return enc_ftrs
class AENet(nn.Module):
def __init__(self, input_dim, block_size, enc_chs=(1, 64, 128, 256, 512, 1024), dec_chs=(1024, 512, 256, 128, 64), num_class=1,
retain_dim=True, out_sz=(256, 640)):
super(AENet,self).__init__()
self.input_dim = input_dim
self.cov_source = nn.Parameter(torch.zeros(block_size, block_size), requires_grad=False)
self.cov_target = nn.Parameter(torch.zeros(block_size, block_size), requires_grad=False)
self.encoder = Encoder(enc_chs)
self.decoder = Decoder(dec_chs)
self.head = nn.Conv2d(dec_chs[-1], num_class, 1)
self.retain_dim = retain_dim
self.out_sz = out_sz
def forward(self, x):
print(f'FOR X: we have the dimensions {x.shape}')
z = self.encoder(x[None, None, :])
print(f'FOR Z: we have the dimensions {z.shape}')
out = self.decoder(z[::-1][0], z[::-1][1:])
out = self.head(out)
if self.retain_dim:
out = F.interpolate(out, self.out_sz)
print(f'FOR O: we have the dimensions {out.shape}')
return out, z
我的解决方法:
z = self.encoder.forward(x[None, None, :])
out = self.decoder.forward(z[::-1][0], z[::-1][1:])
为什么我需要直接调用类的方法,而它在 jupyter notebook 中像上面那样直接工作?