我正在尝试创建一个神经网络,输入是L(来自Lab格式)的图像,输出是ab维度。我能够顺利地传入L维度,但我在尝试输出ab维度时遇到了困难。输出应该为1x2xHxW的形状,其中H和W分别是输入图像的高度和宽度。以下是我目前的网络结构:
class Model(nn.Module): def __init__(self): super(Model, self).__init__() # 从torchvision.model库获取resnet18模型 self.model = models.resnet18(pretrained=True) self.model.conv1 = nn.Conv2d(1, 64, kernel_size=7, stride=2, padding=3, bias=False) # 将我们的模型的全连接层替换为输出2048特征向量的层 self.model.classifier = nn.Sequential() # 添加自定义的分类层 self.fc1 = nn.Linear(1000, 1024) self.Dropout1 = nn.Dropout() self.PRelU1 = nn.PReLU() self.fc2 = nn.Linear(1024, 512) self.Dropout2 = nn.Dropout() self.PRelU2 = nn.PReLU() self.fc3 = nn.Linear(512, 256) self.Dropout3 = nn.Dropout() self.PRelU3 = nn.PReLU() self.fc4 = nn.Linear(256, 313) # self.PRelU3 = nn.PReLU() self.softmax = nn.Softmax(dim=1) self.model_out = nn.Conv2d(313, 2, kernel_size=1, padding=0, dilation=1, stride=1, bias=False) self.upsample4 = nn.Upsample(scale_factor=4, mode='bilinear') def forward(self, x): # x是我们的输入数据 x = self.model(x) x = self.Dropout1(self.PRelU1(self.fc1(x))) x = self.Dropout2(self.PRelU2(self.fc2(x))) x = self.Dropout3(self.PRelU3(self.fc3(x))) x = self.softmax(self.fc4(x)) return x
回答:
我不太明白你所说的“ab维度”是什么意思,也不确定“L格式”指的是什么,但我可以告诉你如何使用CNN来生成图像。
通常你会使用自编码器,但这取决于任务。自编码器以图像作为输入,类似于普通的分类任务,减少维度。但与分类不同的是,你不会压平特征图并添加分类层,而是进行上采样和反卷积操作。所以你先“编码”图像,然后再“解码”它。在开始上采样之前的中间层被称为瓶颈层。不需要密集层和softmax激活函数。
这是一个使用PyTorch模型的自编码器示例(针对cifar10数据集):
class Model(nn.Module): def __init__(self): super(Model, self).__init__() """ 编码器 """ self.conv1 = nn.Conv2d(3, 32, kernel_size=(5, 5)) self.batchnorm1 = nn.BatchNorm2d(32) self.conv2 = nn.Conv2d(32, 64, kernel_size=(4, 4), stride=3) self.batchnorm2 = nn.BatchNorm2d(64) self.conv3 = nn.Conv2d(64, 128, kernel_size=(3, 3), stride=3) self.batchnorm3 = nn.BatchNorm2d(128) self.maxpool2x2 = nn.MaxPool2d(2) # 不使用 """ 解码器 """ self.upsample2x2 = nn.Upsample(scale_factor=2) # 不使用 self.deconv1 = nn.ConvTranspose2d(128, 64, kernel_size=(3, 3), stride=3) self.batchnorm1 = nn.BatchNorm2d(64) self.deconv2 = nn.ConvTranspose2d(64, 32, kernel_size=(4, 4), stride=3) self.batchnorm2 = nn.BatchNorm2d(32) self.deconv3 = nn.ConvTranspose2d(32, 3, kernel_size=(5, 5)) self.batchnorm3 = nn.BatchNorm2d(3) def forward(self, x, train_: bool=True, print_: bool=False, return_bottlenecks: bool=False): """ 编码器 """ x = self.conv1(x) x = self.batchnorm1(x) x = F.relu(x) x = self.conv2(x) x = self.batchnorm2(x) x = F.relu(x) x = self.conv3(x) x = self.batchnorm3(x) bottlenecks = F.relu(x) """ 解码器 """ x = self.deconv1(bottlenecks) x = self.batchnorm1(x) x = F.relu(x) x = self.deconv2(x) x = self.batchnorm2(x) x = F.relu(x) x = self.deconv3(x) x = torch.sigmoid(x) return x
在这个示例中,我没有使用“maxpool”和“upsample”,但这取决于你的模型。Upsample
基本上是maxpool的反操作,你可以将ConvTranspose2d
看作是卷积的反操作(尽管这并不是完全正确的解释)。
所以你基本上希望“解码器”部分是“编码器”部分的相反(或镜像版本)。为每一层确定维度、核大小等可能会相当棘手,但你基本上需要设置它们,使得架构几乎是对称的,并且模型的输出维度是你想要生成的图像的大小。
这是一个“生成图像”的架构可能的样子: