ResNet训练单通道图像分类网络(Pytorch)

前言

 ResNet是一个比较成熟的深度学习分类模型,目前有ResNet-18、ResNet-34、ResNet-50、ResNet-101、ResNet-152,同时,该分类模型常用于RGB(三通道)彩色图像的分类任务,如在ImageNet的训练;而在单通道图像(灰度图像)的训练和测试较少。如何使ResNet在单通道图像上训练,如何修改网络模型参数和读取图像,本文将一一进行讲解。

步骤

第一步:构建数据集

  • 数据集的结构应该是这样的
    在这里插入图片描述
  • 图像的格式:8bit,jpg格式

第二步:修改网络模型

  • 法1:直接修改定义的ResNet网络模型
     在model.py中,修改ResNet的第一层卷积层输入通道为1(彩色为3)
self.conv1 = nn.Conv2d(1, self.in_channel, kernel_size=7, stride=2,padding=3, bias=False)
  • 法2:在train.py文件中,进行如下修改,也可以达到法1的效果
model = resnet18(num_classes=3)
model.conv1 = nn.Conv2d(1, 64, kernel_size=7, stride=2, padding=3, bias=False)
model = model.to(device)

第三步:修改读取数据方式

  • 一般我们用torchvision.datasets.ImageFolder()读取数据,但在读取单通道数据时,此函数会自动将单通道图像转换为三通道图像(r=g=b),此时如果不进行其他操作,就会报错

  • 这是ImageFolder()函数的定义:留意读取的图像为PIL图像,且会转换为RGB格式
    在这里插入图片描述
    在这里插入图片描述

  • 修改方法:
     修改transform(图像预处理操作)
      添加transforms.Grayscale(1),将图像转换为单通道图像(经实验,图像矩阵的数据并不会发生变化)
      transforms.Normalize修改如下,第一个参数为mean,第二个参数为std,因为是单通道,所以进行Z-Score时仅需要对一个通道进行操作
    在这里插入图片描述

data_transforms = {
    'train': transforms.Compose([
        transforms.Grayscale(1),
        transforms.RandomResizedCrop(224),
        transforms.RandomHorizontalFlip(),
        transforms.ToTensor(),
        transforms.Normalize([0.485, ], [0.229, ])
    ]),
    'val': transforms.Compose([
        transforms.Grayscale(1),
        transforms.Resize(256),
        transforms.CenterCrop(224),
        transforms.ToTensor(),
        transforms.Normalize([0.485, ], [0.229, ])
    ])
}

第四步:训练分类网络并测试(注意测试时transform与‘val’方式一样)

总结

 ResNet训练单通道主要修改两个部分,一个是ResNet模型第一层卷积层的in_channels=1,另一个是transform中添加Grayscale(1)以及修改Normalize。其实很简单,只是有时忽略了ImageFolder会自动将灰度图转换为RGB图,导致出错,希望本文能帮助您!

参考资料:

可以参考这位up主github里面的Test5_resnet,并在此基础上进行上述修改,训练自己的灰度图像!
https://github.com/WZMIAOMIAO/deep-learning-for-image-processing/tree/master/pytorch_learning

以下是一个简单的例子,使用ResNet50模型进行图像去噪,使用PyTorch实现。 首先,需要导入必要的库和模块: ```python import torch import torch.nn as nn import torchvision.models as models ``` 然后,我们需要定义一个新的ResNet50模型,将其用于图像去噪。我们可以通过继承ResNet50类,并在其中添加一些新的层来实现这个目标。 ```python class DenoisingResNet50(models.ResNet): def __init__(self, num_classes=1000): super().__init__(block=models.Bottleneck, layers=[3, 4, 6, 3], num_classes=num_classes) self.conv1 = nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1, bias=False) self.encoder = nn.Sequential(*list(self.children())[:-2]) self.decoder = nn.Sequential( nn.ConvTranspose2d(2048, 1024, kernel_size=3, stride=2, padding=1, output_padding=1, bias=False), nn.BatchNorm2d(1024), nn.ReLU(inplace=True), nn.ConvTranspose2d(1024, 512, kernel_size=3, stride=2, padding=1, output_padding=1, bias=False), nn.BatchNorm2d(512), nn.ReLU(inplace=True), nn.ConvTranspose2d(512, 256, kernel_size=3, stride=2, padding=1, output_padding=1, bias=False), nn.BatchNorm2d(256), nn.ReLU(inplace=True), nn.ConvTranspose2d(256, 128, kernel_size=3, stride=2, padding=1, output_padding=1, bias=False), nn.BatchNorm2d(128), nn.ReLU(inplace=True), nn.ConvTranspose2d(128, 64, kernel_size=3, stride=2, padding=1, output_padding=1, bias=False), nn.BatchNorm2d(64), nn.ReLU(inplace=True), nn.ConvTranspose2d(64, 3, kernel_size=3, stride=1, padding=1, bias=False), nn.Sigmoid() ) def forward(self, x): x = self.conv1(x) x = self.encoder(x) x = self.decoder(x) return x ``` 这里,我们添加了一个新的卷积层`conv1`,用于处理输入的图像。然后,我们使用`nn.Sequential`定义了一个新的编码器和解码器,用于将输入的图像编码为低维特征向量,并将其解码为输出的图像。 在`decoder`中,我们使用了反卷积层(`nn.ConvTranspose2d`)和批量归一化(`nn.BatchNorm2d`)来将特征向量解码为输出图像。最后,我们使用`nn.Sigmoid`来限制输出在0到1之间。 现在,我们已经定义了一个新的ResNet50模型,我们可以使用它来进行图像去噪。以下是一个简单的例子: ```python model = DenoisingResNet50(num_classes=1000) criterion = nn.MSELoss() optimizer = torch.optim.Adam(model.parameters(), lr=0.001) # Load the data train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=32, shuffle=True) valid_loader = torch.utils.data.DataLoader(valid_dataset, batch_size=32, shuffle=False) # Train the model for epoch in range(10): for images, labels in train_loader: # Add noise to the images noisy_images = torch.clamp(images + 0.1 * torch.randn_like(images), min=0, max=1) # Forward pass outputs = model(noisy_images) loss = criterion(outputs, images) # Backward and optimize optimizer.zero_grad() loss.backward() optimizer.step() # Evaluate the model with torch.no_grad(): total_loss = 0 for images, labels in valid_loader: # Add noise to the images noisy_images = torch.clamp(images + 0.1 * torch.randn_like(images), min=0, max=1) # Forward pass outputs = model(noisy_images) loss = criterion(outputs, images) total_loss += loss.item() * len(images) mean_loss = total_loss / len(valid_dataset) print(f"Epoch [{epoch+1}/10], Validation Loss: {mean_loss:.4f}") ``` 在这个例子中,我们使用`MSELoss`作为损失函数,并使用Adam优化器来训练模型。我们还使用`DataLoader`来加载训练和验证数据集,并在每个epoch结束时计算验证损失。 在训练过程中,我们首先将输入的图像添加一些噪声,然后将其输入到模型中进行训练。在验证过程中,我们也使用相同的方式来生成噪声图像,并将其输入到模型中进行评估。 最后,我们打印出每个epoch的验证损失。您可以根据需要修改此示例以满足您的需求。
评论 23
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值