(解决问题追加酬谢)自己复现的resnet的deelabpv3效果差很多(与torch官方的比),不收敛,一直没找到原因,使用的数据集,train脚本都一样

(解决问题有酬谢)自己复现的resnet的deelabpv3效果差很多(与torch官方的比),不收敛,一直没找到原因,使用的数据集,train脚本都一样。


import torch.nn as nn
import torch
from torchinfo import summary
import netron
import onnx
from onnx import shape_inference

from torch.nn import functional as F


class BottleNeck(nn.Module):
    """搭建BottleNeck模块"""

    expansion = 4

    def __init__(self, in_channel, out_channel, stride, padding, dilation):
        super(BottleNeck, self).__init__()
        self.stride = stride
        self.res = nn.Sequential(
            nn.Conv2d(in_channel, out_channel * self.expansion, kernel_size=1, stride=stride, bias=False),
            nn.BatchNorm2d(out_channel * self.expansion)
            )

        self.conv1 = nn.Conv2d(in_channel, out_channel, kernel_size=1, stride=1, bias=False)
        self.bn1 = nn.BatchNorm2d(out_channel)  # BN层, BN层放在conv层和relu层中间使用
        self.conv2 = nn.Conv2d(out_channel, out_channel, kernel_size=3, stride=stride, padding=padding, bias=False,
                               dilation=dilation)
        self.bn2 = nn.BatchNorm2d(out_channel)
        self.conv3 = nn.Conv2d(out_channel, out_channel * self.expansion, kernel_size=1, stride=1, bias=False)
        self.bn3 = nn.BatchNorm2d(out_channel * self.expansion)  # Residual中第三层out_channel扩张到in_channel的4倍
        self.relu = nn.ReLU(inplace=True)

    # 前向传播
    def forward(self, x):
        identity = x
        out = self.conv1(x)
        out = self.bn1(out)
        out = self.relu(out)
        out = self.conv2(out)
        out = self.bn2(out)
        out = self.relu(out)
        out = self.conv3(out)
        out = self.bn3(out)

        # out = self.relu(self.bn1(self.conv1(x)))
        # out = self.relu(self.bn2(self.conv2(out)))
        # out = self.bn3(self.conv3(out))

        identity = self.res(identity)

        out = self.relu(identity + out)

        return out


class BottleNeck1(nn.Module):  # 无残差结构的,因为发现torch的deeplabv3_resnet50结构只有layer中第一层bottleneck需要卷积残差,其他层直接加就可以
    """搭建BottleNeck模块"""

    expansion = 4

    def __init__(self, in_channel, out_channel, stride, padding, dilation):
        super(BottleNeck1, self).__init__()

        self.conv1 = nn.Conv2d(in_channel, out_channel, kernel_size=1, stride=1, bias=False)
        self.bn1 = nn.BatchNorm2d(out_channel)  # BN层, BN层放在conv层和relu层中间使用
        self.conv2 = nn.Conv2d(out_channel, out_channel, kernel_size=3, stride=stride, padding=padding, bias=False,
                               dilation=dilation)
        self.bn2 = nn.BatchNorm2d(out_channel)
        self.conv3 = nn.Conv2d(out_channel, out_channel * self.expansion, kernel_size=1, stride=1, bias=False)
        self.bn3 = nn.BatchNorm2d(out_channel * self.expansion)  # Residual中第三层out_channel扩张到in_channel的4倍
        self.relu = nn.ReLU(inplace=True)

    # 前向传播
    def forward(self, x):
        identity = x.clone()

        out = self.conv1(x)
        out = self.bn1(out)
        out = self.relu(out)
        out = self.conv2(out)
        out = self.bn2(out)
        out = self.relu(out)
        out = self.conv3(out)
        out = self.bn3(out)

        # out = self.relu(self.bn1(self.conv1(x)))
        # out = self.relu(self.bn2(self.conv2(out)))
        # out = self.bn3(self.conv3(out))

        out = self.relu(identity + out)
        return out


class Branch(nn.Module):

    def __init__(self, in_channel, out_channel, kernel_size, dilation, padding):
        super(Branch, self).__init__()

        self.conv1 = nn.Conv2d(in_channel, out_channel, kernel_size=kernel_size, padding=padding, dilation=dilation, stride=1, bias=False)
        self.bn1 = nn.BatchNorm2d(out_channel)  # BN层, BN层放在conv层和relu层中间使用
        self.relu = nn.ReLU(inplace=True)

    def forward(self, x):
        out = self.relu(self.bn1(self.conv1(x)))
        return out

class ASPPPooling(nn.Module):
    def __init__(self, in_channels, out_channels):
        super(ASPPPooling, self).__init__()
        self.conv1 = nn.Sequential(
                    nn.AdaptiveAvgPool2d(1),
                    nn.Conv2d(in_channels, out_channels, 1, bias=False),
                    nn.BatchNorm2d(out_channels),
                    nn.ReLU()
        )

    def forward(self, x):
        size = x.shape[-2:]
        out = self.conv1(x)
        out = F.interpolate(out, size=size, mode='bilinear', align_corners=False)
        return out


class Deeplab(nn.Module):

    def __init__(self, numberclass):  # in_channel=out_channel=64
        super(Deeplab, self).__init__()
        self.conv1 = nn.Sequential(nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3, bias=False),
                                   nn.BatchNorm2d(64),
                                   nn.ReLU()
                                   )
        self.polling = torch.nn.MaxPool2d(kernel_size=3, stride=2, padding=1, dilation=1, ceil_mode=False)
        self.laye1backbone1 = BottleNeck(64, 64, stride=1, dilation=1, padding=1)
        self.laye1backbone2 = BottleNeck1(256, 64, stride=1, dilation=1, padding=1)
        self.laye1backbone3 = BottleNeck1(256, 64, stride=1, dilation=1, padding=1)

        self.laye2backbone1 = BottleNeck(256, 128, stride=2, dilation=1, padding=1)
        self.laye2backbone2 = BottleNeck1(512, 128, stride=1, dilation=1, padding=1)
        self.laye2backbone3 = BottleNeck1(512, 128, stride=1, dilation=1, padding=1)
        self.laye2backbone4 = BottleNeck1(512, 128, stride=1, dilation=1, padding=1)

        self.laye3backbone1 = BottleNeck(512, 256, stride=1, dilation=1, padding=1)
        self.laye3backbone2 = BottleNeck1(1024, 256, stride=1, dilation=2, padding=2)
        self.laye3backbone3 = BottleNeck1(1024, 256, stride=1, dilation=2, padding=2)
        self.laye3backbone4 = BottleNeck1(1024, 256, stride=1, dilation=2, padding=2)
        self.laye3backbone5 = BottleNeck1(1024, 256, stride=1, dilation=2, padding=2)
        self.laye3backbone6 = BottleNeck1(1024, 256, stride=1, dilation=2, padding=2)

        self.laye4backbone1 = BottleNeck(1024, 512, stride=1, dilation=2, padding=2)
        self.laye4backbone2 = BottleNeck1(2048, 512, stride=1, dilation=4, padding=4)
        self.laye4backbone3 = BottleNeck1(2048, 512, stride=1, dilation=4, padding=4)
        self.branch1 = Branch(2048, 256, kernel_size=1, padding=0, dilation=1)
        self.branch2 = Branch(2048, 256, kernel_size=3, padding=12, dilation=12)
        self.branch3 = Branch(2048, 256, kernel_size=3, padding=24, dilation=24)
        self.branch4 = Branch(2048, 256, kernel_size=3, padding=36, dilation=36)
        self.branch5 = ASPPPooling(2048, 256)
        self.result = nn.Sequential(nn.Conv2d(256 * 5, 256, 1, bias=False),
                                    nn.BatchNorm2d(256),
                                    nn.ReLU(),
                                    nn.Dropout(0.5)
                                    )

        self.result1 = nn.Sequential(nn.Conv2d(256, 256, 3, padding=1, bias=False),
                                     nn.BatchNorm2d(256),
                                     nn.ReLU()
                                     )
        self.final = nn.Conv2d(256, numberclass, 1, padding=0, bias=False)

    def forward(self, x):
        out = self.conv1(x)
        out = self.polling(out)
        out = self.laye1backbone1(out)
        out = self.laye1backbone2(out)
        out = self.laye1backbone3(out)
        out = self.laye2backbone1(out)
        out = self.laye2backbone2(out)
        out = self.laye2backbone3(out)
        out = self.laye2backbone4(out)
        out = self.laye3backbone1(out)
        out = self.laye3backbone2(out)
        out = self.laye3backbone3(out)
        out = self.laye3backbone4(out)
        out = self.laye3backbone5(out)
        out = self.laye3backbone6(out)
        out = self.laye4backbone1(out)
        out = self.laye4backbone2(out)
        out = self.laye4backbone3(out)
        out1 = self.branch1(out)
        out2 = self.branch2(out)
        out3 = self.branch3(out)
        out4 = self.branch4(out)
        out5 = self.branch5(out)
        out = self.result(torch.cat((out1, out2, out3, out4, out5), 1))
        out = self.result1(out)
        out = self.final(out)
        out = F.interpolate(out, size=x.shape[-2:], mode='bilinear', align_corners=False)

        return out


你用的自己训练数据和训练脚本,这是问题所在,你的超参数,数据增强不足等都是原因

我这有完整写好的ResNet50,包括完整网络和优化器,损失函数等,你可以看看,不会的话我给你讲解:
https://github.com/Junzhou-Chen/classification

如果您使用的是自己的训练数据和训练脚本,并且调用的是torchvision中的deeplabv3_resnet50模型,那么确保以下几个方面的一致性可能有助于解决问题:

  1. 数据预处理:检查您在训练过程中使用的数据预处理步骤是否与官方实现一致。确保输入数据的预处理方式(如缩放、裁剪、归一化等)与官方实现相同。

  2. 数据集的多样性和质量:确保使用的训练数据集与官方实现中使用的数据集在多样性和质量上相似。如果训练数据集与测试数据集有明显的分布差异,可能会导致模型在测试集上表现不佳。

  3. 学习率和优化器:检查您在训练脚本中设置的学习率和优化器是否与官方实现一致。学习率和优化器的选择对模型的收敛性能至关重要。

  4. 训练时间和迭代次数:确保您的训练时间和迭代次数与官方实现相似。如果您的训练时间或迭代次数不足,模型可能没有足够的时间来学习有意义的特征。

  5. 损失函数:检查您在训练过程中使用的损失函数是否与官方实现相同。使用与官方实现一致的损失函数可以确保训练过程的一致性。

如果您仔细检查了上述因素,并且仍然存在问题,可能需要进一步排查其他因素,例如网络结构的定义、权重初始化、模型评估指标等。

此外,您还可以尝试使用其他的超分辨率算法作为对比,看看是否能够改善效果。有时候,不同的算法在不同的数据集或场景下表现更好。

回答部分参考、引用ChatGpt以便为您提供更准确的答案:

根据提供的代码和描述,复现的resnet的deeplabv3效果与torch官方的结果相比差距较大且不收敛。有几个可能的原因和解决方法如下:

  1. 学习率调整:尝试调整学习率的大小,如果学习率过大可能会导致模型无法收敛,而学习率过小则会导致收敛速度较慢。可以尝试使用较小的学习率并逐渐增加,观察模型是否能够收敛。
  2. 正则化和归一化:确保在训练过程中对数据进行适当的正则化和归一化处理,以避免梯度爆炸或梯度消失等问题。可以尝试添加正则化项(如L1或L2正则化)或使用批归一化(Batch Normalization)技术。
  3. 损失函数选择:检查使用的损失函数是否与任务相匹配。对于分类任务,常用的损失函数包括交叉熵损失函数(Cross Entropy Loss)等。
  4. 数据集准备:确保数据集的质量和准确性。检查数据集是否包含噪声、缺失值或标注错误等问题。此外,还可以尝试使用数据增强技术(如随机裁剪、旋转、翻转等)来增加数据的多样性。
  5. 网络结构:检查网络结构是否正确,确保输入和输出的维度匹配,并检查是否正确连接了各个模块和层。可以对比官方实现的网络结构与复现的网络结构,确保一致。
  6. 训练时长和迭代次数:尝试增加训练时长和迭代次数,给模型更多的学习时间和机会,观察是否有改善。

综上所述,通过调整学习率、正则化和归一化、选择适当的损失函数、检查数据集质量、检查网络结构以及增加训练时长和迭代次数等方法,可能有助于解决复现的resnet的deeplabv3效果差且不收敛的问题。

注意:由于无法查看完整的训练脚本和数据集,以上只是一些常见的问题和解决方法的示例,具体问题的解决可能需要进一步的调试和分析。

调用的函数是这个 self.model1 = torchvision.models.segmentation.deeplabv3_resnet50(pretrained= False,num_classes=1,pretrained_backbone=False),没有使用加载权重,损失函数是torch.nn.functional.binary_cross_entropy_with_logits,所以我自己写的代码里最后面也不需要加sigmod激活

引用gpt回答 有帮助的话 采纳一下
根据你提供的代码和信息,你自己实现的Deeplabv3模型与PyTorch官方版本相比效果差的原因可能有:

  1. 模型结构不同导致
    看代码你的Deeplabv3结构与官方版还是有一些差异,例如残差连接方式,ASPP模块等实现不同,这可能是导致结果差异的一个重要原因。需要确保模型结构完全一致。
  2. 训练超参数不当
    学习率、优化器、Batch Size等超参数设置会明显影响最终结果。需要调整使其与官方代码或文献中的设置一致。
  3. 权重初始化方式不同
    模型权重初始化方法也会对收敛速度和结果造成影响。建议使用官方代码中相同的初始化方式。
  4. 数据预处理方式不同
    输入数据的归一化、增强等预处理也可能导致结果偏差。需要确认与官方实现一致。
  5. 过拟合问题
    如果是过拟合,可以适当调整模型复杂度,添加正则化,增大训练集等来解决。
    建议逐一检查上述方面,定位导致结果差异的具体原因,逐步调整代码和参数,最终应该可以达到与官方模型相当的效果。