pytorh学习笔记:根据图示写相应神经网络以及对相应的debug进行修改

 

各位小伙伴大家好,很高兴又能和你见面,,在这篇博客中我将记录我再暑期学习中出现的debug以及修改debug的过程

首先我们先来看看作业要求

 所使用的网络结构:

 由上网络结构我们易知此网路我们需要用到残差结构,所以我们可以参考resnet的写法来写这个网络结构

resnet代码写法可以参考我之前写的Pytorch学习笔记:RNN的原理及其手写复现_后来后来啊的博客-CSDN博客

使用pytorch搭建ResNet并基于迁移学习训练(超详细 |附训练代码)_后来后来啊的博客-CSDN博客

使用pytorch搭建ResNet并基于迁移学习训练(超详细 |附训练代码)_后来后来啊的博客-CSDN博客这篇博客当中,我们定义了一个model函数

所以在此我们也在model.py中定义我们的网络结构

首先我先写了以下代码来实现这个网络结构

import torch
import torch.nn as nn
import torchsummary

class ResidualBlock(nn.Module):
    def __init__(self, in_channels, out_channels, stride=1, groups=1):
        super(ResidualBlock, self).__init__()
        self.conv1 = nn.Conv2d(in_channels, out_channels, kernel_size=1, stride=stride, padding=0)
        self.conv2 = nn.Conv2d(out_channels, out_channels, kernel_size=3, stride=1, padding=1, groups=groups)
        self.conv3 = nn.Conv2d(out_channels, out_channels, kernel_size=1, stride=1, padding=0)
        self.relu = nn.ReLU(inplace=True)

        if stride != 1 or in_channels != out_channels:
            self.downsample = nn.Sequential(
                nn.Conv2d(in_channels, out_channels, kernel_size=1, stride=stride, padding=0),
                nn.BatchNorm2d(out_channels)
            )
        else:
            self.downsample = None

    def forward(self, x):
        identity = x

        out = self.conv1(x)
        out = self.relu(out)

        out = self.conv2(out)
        out = self.relu(out)

        out = self.conv3(out)

        if self.downsample is not None:
            identity = self.downsample(x)

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

        return out


class Network(nn.Module):
    def __init__(self):
        super(Network, self).__init__()
        self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=2, padding=1)
        self.lconv1 = nn.Conv2d(32, 32, kernel_size=3, stride=2, padding=1, groups=32)
        self.conv2 = nn.Conv2d(32, 64, kernel_size=1, stride=1)
        self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1, groups=1)
        self.conv4 = nn.Conv2d(128, 128, kernel_size=1, stride=1)
        self.conv5 = nn.Conv2d(128, 256, kernel_size=3, stride=2, padding=1, groups=128)
        self.conv6 = nn.Conv2d(256, 256, kernel_size=1, stride=1)
        self.conv7 = nn.Conv2d(256, 512, kernel_size=1, stride=1)
        self.avgpool = nn.AvgPool2d(kernel_size=20)
        self.fc = nn.Linear(2048, 10)  # 修改全连接层的输入维度
        self.softmax = nn.Softmax(dim=1)
        self.relu = nn.ReLU(inplace=True)

        self.residual_block = ResidualBlock(128, 128, stride=2, groups=1)

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

        x = self.lconv1(x)
        x = self.relu(x)

        x = self.conv2(x)
        x = self.relu(x)

        x = self.conv3(x)
        x = self.relu(x)

        x = self.conv4(x)
        x = self.relu(x)

        x = self.residual_block(x)

        x = self.conv5(x)
        x = self.relu(x)

        x = self.conv6(x)
        x = self.relu(x)

        x = self.conv7(x)
        x = self.relu(x)

        x = self.avgpool(x)
        x = x.view(x.size(0), -1)
        x = self.fc(x)
        x = self.softmax(x)

        return x


model = Network()
model = model.cuda()

# Print the model summary to the console
torchsummary.summary(model, (3, 640, 640))

但是我再跑网络的时候发现该结构运行的准确率只有40%左右,于是我我打印出网络结构层级和输出尺寸等信息

 发现该网络缺少下采样(batchnorm,dropout)等方法的多使用,且总参数 相比较而言偏少

于是我想在每层卷积后都加个下采样会是什么样

import torch
import torch.nn as nn
import torch.nn.functional as F
import torchsummary

class ResidualBlock(nn.Module):#公式:O=(W-F+2P)/S+1
# 构造方法(构造函数中至少需要传入2个参数:进出的通道数。残差块的一个最主要的作用就是改变信号的通道数)
    def __init__(self, in_channels, out_channels, stride=1, groups=1, downsample=None):
        super(ResidualBlock, self).__init__()
        self.conv5 = nn.Sequential(
            nn.Conv2d(in_channels=in_channels, out_channels=out_channels, kernel_size=1, stride=1, bias=False),
            nn.BatchNorm2d(out_channels))

        self.conv6 = nn.Sequential(nn.Conv2d(in_channels=64, out_channels=128, kernel_size=3, stride=1, padding=1, groups=128, bias=False),
        nn.BatchNorm2d(128),
        nn.ReLU)

        self.conv7 = nn.Sequential(nn.Conv2d(in_channels=64, out_channels=128, kernel_size=1, stride=1, bias=False),
        nn.BatchNorm2d(128),
        nn.ReLU())

        self.conv8 = nn.Sequential(nn.Conv2d(in_channels=64, out_channels=128, kernel_size=3, stride=2, padding=1, groups=128, bias=False),
        nn.BatchNorm2d(128),
        nn.ReLU())

        self.conv9 = nn.Sequential(nn.Conv2d(in_channels=64, out_channels=128, kernel_size=1, stride=1, bias=False),
        nn.BatchNorm2d(128),
        nn.ReLU())

        self.downsample = downsample

        if stride != 1 or in_channels != out_channels:
            self.downsample = nn.Sequential(
                nn.Conv2d(in_channels=64, out_channels=128, kernel_size=1, stride=stride, bias=False),
                nn.BatchNorm2d(256))

    def forward(self, x):
        identity = x
        if self.downsample is not None:
            identity = self.downsample(x)

        out = self.conv5(x)
        out = self.conv6(out)
        out = self.conv7(out)
        out = self.conv8(out)
        out = self.conv9(out)

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

class Network(nn.Module):
    def __init__(self, num_classes=1000):
        super(Network,self).__init__()
        self.conv1 = nn.Sequential(nn.Conv2d(in_channels=3, out_channels=32, kernel_size=3, stride=2, padding=1, bias=True),
                                   nn.BatchNorm2d(32),
                                   nn.ReLU())

        self.conv2 = nn.Sequential(
            nn.Conv2d(in_channels=32, out_channels=32, kernel_size=3, stride=2, padding=1, groups=32, bias=True),
            nn.BatchNorm2d(32),
            nn.ReLU())

        self.conv3 = nn.Sequential(
            nn.Conv2d(in_channels=32, out_channels=64, kernel_size=1, stride=1, bias=True),
            nn.BatchNorm2d(64),
            nn.ReLU())

        self.conv4 = nn.Sequential(
            nn.Conv2d(in_channels=64, out_channels=64, kernel_size=3, stride=2, padding=1, groups=64, bias=True),
            nn.BatchNorm2d(64),
            nn.ReLU())

        self.residual_block = ResidualBlock(64, 128, stride=2)

        self.conv10 = nn.Sequential(
            nn.Conv2d(in_channels=256, out_channels=256, kernel_size=3, stride=1, padding=1, groups=256),
            nn.BatchNorm2d(256),
            nn.ReLU())

        self.conv11 = nn.Sequential(
            nn.Conv2d(in_channels=256, out_channels=256, kernel_size=1, stride=1),
            nn.BatchNorm2d(256),
            nn.ReLU())

        self.conv12 = nn.Sequential(
            nn.Conv2d(in_channels=256, out_channels=512, kernel_size=1, stride=1),
            nn.BatchNorm2d(512),
            nn.ReLU())

        self.Avgpool = nn.AdaptiveAvgPool2d((1,1))#将输入的特征图的大小调整为1x1x512

        self.fc = nn.Linear(512, num_classes)



        def forward(self, x):
            out = self.conv1(x)
            out = self.conv2(x)
            out = self.conv3(x)
            out = self.conv4(x)

            out = self.residual_block(x)

            out = self.conv10(x)
            out = self.conv11(x)
            out = self.conv12(x)

            out = self.Avgpool(x)
            out = torch.flatten(x, 1)
            out = self.fc(x)
            return out

model = Network()
model = model.cuda()
#
# # Print the model summary to the console
torchsummary.summary(model, (3, 640, 640))

这是我重新写的一个网络结构,但是出现了相当多的报错,有小伙伴能在不看的情况下把这些报错都改过来吗,有的话评论区扣1,好了回归正题

首先我们遇到的报错是

根据报错原因说的是这个错误意味着`torch.nn.modules.activation.ReLU`不是`Module`的子类

我们再来自习看代码发现在16行我们使用的是nn.ReLU,但是正确使用方法应该是nn.ReLU()

更改后是第二个报错

 根据报错信息可知是因为输入值不能被groups整除,重新查看网络发现,这是因为我在 定义残差 网络是复制输入那一坨nn.Sequential的时候出现了问题,再看网络时候发现就是输入输出出现了问题

于是改成了

 但是接下来又出现了

 这个报错,思考了我许久,又去看原先定的网络结构,然后 上csdn上 看了这篇博客:NotImplementedError raise NotImplementedError_"s/module.py\", line 201, in _forward_unimplemente_Matthew2333的博客-CSDN博客

该博客说是因为我们forward函数出了错误,再细看网络发现在NetWork中,forward函数中的self没有像正确定义后出现紫色字样,这是因为我们把forward函数定义在了def  __init__中,正确 做法应该是俩个def齐平

如下图

 然后出现了最让我头疼的报错

 最终在改博客中得到解决:解决Given groups=1,weight [128,64,4,4], so expected inputs [32,32,64,64] to have 64 channels类似错误_萨姆西的博客-CSDN博客

根据博主说的是因为我们在输入是打成了x,而不是out,再看看 报错地方正是99行

 我们修改后面的x为out试试,发现变成了

 紧接着报错就变成了

 代码说我们在残差网络中我们输入的是128,但是需要的是256

 由图可以看到我们在定义downsample的时候,输出写成了128才出现了该错误

于是我们改成

虽然此处解决了,但是还可以使用其他方法,这里给大家提供一种思路 

 第1,2点可以用在model的out = self.conv9(out)中,例如

out = self.conv9(out.clone().detach())

最终打印出网络

----------------------------------------------------------------
        Layer (type)               Output Shape         Param #
================================================================
            Conv2d-1         [-1, 32, 320, 320]             896
       BatchNorm2d-2         [-1, 32, 320, 320]              64
              ReLU-3         [-1, 32, 320, 320]               0
            Conv2d-4         [-1, 32, 160, 160]             320
       BatchNorm2d-5         [-1, 32, 160, 160]              64
              ReLU-6         [-1, 32, 160, 160]               0
            Conv2d-7         [-1, 64, 160, 160]           2,112
       BatchNorm2d-8         [-1, 64, 160, 160]             128
              ReLU-9         [-1, 64, 160, 160]               0
           Conv2d-10           [-1, 64, 80, 80]             640
      BatchNorm2d-11           [-1, 64, 80, 80]             128
             ReLU-12           [-1, 64, 80, 80]               0
           Conv2d-13          [-1, 256, 40, 40]          16,384
      BatchNorm2d-14          [-1, 256, 40, 40]             512
           Conv2d-15          [-1, 128, 80, 80]           8,192
      BatchNorm2d-16          [-1, 128, 80, 80]             256
           Conv2d-17          [-1, 128, 80, 80]           1,152
      BatchNorm2d-18          [-1, 128, 80, 80]             256
             ReLU-19          [-1, 128, 80, 80]               0
           Conv2d-20          [-1, 128, 80, 80]          16,384
      BatchNorm2d-21          [-1, 128, 80, 80]             256
             ReLU-22          [-1, 128, 80, 80]               0
           Conv2d-23          [-1, 128, 40, 40]           1,152
      BatchNorm2d-24          [-1, 128, 40, 40]             256
             ReLU-25          [-1, 128, 40, 40]               0
           Conv2d-26          [-1, 256, 40, 40]          32,768
      BatchNorm2d-27          [-1, 256, 40, 40]             512
             ReLU-28          [-1, 256, 40, 40]               0
    ResidualBlock-29          [-1, 256, 40, 40]               0
           Conv2d-30          [-1, 256, 40, 40]           2,560
      BatchNorm2d-31          [-1, 256, 40, 40]             512
             ReLU-32          [-1, 256, 40, 40]               0
           Conv2d-33          [-1, 256, 40, 40]          65,792
      BatchNorm2d-34          [-1, 256, 40, 40]             512
             ReLU-35          [-1, 256, 40, 40]               0
           Conv2d-36          [-1, 512, 40, 40]         131,584
      BatchNorm2d-37          [-1, 512, 40, 40]           1,024
             ReLU-38          [-1, 512, 40, 40]               0
AdaptiveAvgPool2d-39            [-1, 512, 1, 1]               0
           Linear-40                 [-1, 1000]         513,000
================================================================
Total params: 797,416
Trainable params: 797,416
Non-trainable params: 0
----------------------------------------------------------------
Input size (MB): 4.69
Forward/backward pass size (MB): 251.57
Params size (MB): 3.04
Estimated Total Size (MB): 259.30
----------------------------------------------------------------

进程已结束,退出代码0

但是在使用该网络的时候又出现了报错

这个报错让我听没有头绪得,因为他说这个错误通常是由于在计算梯度时,某个变量被就地修改(inplace operation)导致的,于是我上csdn查了一下,然后在博客:报错解决:one of the variables needed for gradient computation has been modified by an inplace operation_y4ung的博客-CSDN博客

中说是因为使用了+=,于是返回 model更改为

最终问题解决 ,代码成功跑起

最后附上model.py和train.py

model.py

import torch
import torch.nn as nn
import torch.nn.functional as F
import torchsummary

class ResidualBlock(nn.Module):#公式:O=(W-F+2P)/S+1
# 构造方法(构造函数中至少需要传入2个参数:进出的通道数。残差块的一个最主要的作用就是改变信号的通道数)
    def __init__(self, in_channels, out_channels, stride=1, groups=1, downsample=None):
        super(ResidualBlock, self).__init__()
        self.conv5 = nn.Sequential(
            nn.Conv2d(in_channels=in_channels, out_channels=out_channels, kernel_size=1, stride=1, bias=False),
            nn.BatchNorm2d(out_channels))

        self.conv6 = nn.Sequential(nn.Conv2d(in_channels=128, out_channels=128, kernel_size=3, stride=1, padding=1, groups=128, bias=False),
        nn.BatchNorm2d(128),
        nn.ReLU())

        self.conv7 = nn.Sequential(nn.Conv2d(in_channels=128, out_channels=128, kernel_size=1, stride=1, bias=False),
        nn.BatchNorm2d(128),
        nn.ReLU())

        self.conv8 = nn.Sequential(nn.Conv2d(in_channels=128, out_channels=128, kernel_size=3, stride=2, padding=1, groups=128, bias=False),
        nn.BatchNorm2d(128),
        nn.ReLU())

        self.conv9 = nn.Sequential(nn.Conv2d(in_channels=128, out_channels=256, kernel_size=1, stride=1, bias=False),
        nn.BatchNorm2d(256),
        nn.ReLU())

        self.downsample = downsample

        if stride != 1 or in_channels != out_channels:
            self.downsample = nn.Sequential(
                nn.Conv2d(in_channels=64, out_channels=256, kernel_size=1, stride=stride, bias=False),
                nn.BatchNorm2d(256))

    def forward(self, x):
        identity = x
        if self.downsample is not None:
            identity = self.downsample(x)

        out = self.conv5(x)
        out = self.conv6(out)
        out = self.conv7(out)
        out = self.conv8(out)
        out = self.conv9(out)

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

class Network(nn.Module):
    def __init__(self, num_classes=1000):
        super(Network,self).__init__()
        self.conv1 = nn.Sequential(nn.Conv2d(in_channels=3, out_channels=32, kernel_size=3, stride=2, padding=1, bias=True),
                                   nn.BatchNorm2d(32),
                                   nn.ReLU())

        self.conv2 = nn.Sequential(
            nn.Conv2d(in_channels=32, out_channels=32, kernel_size=3, stride=2, padding=1, groups=32, bias=True),
            nn.BatchNorm2d(32),
            nn.ReLU())

        self.conv3 = nn.Sequential(
            nn.Conv2d(in_channels=32, out_channels=64, kernel_size=1, stride=1, bias=True),
            nn.BatchNorm2d(64),
            nn.ReLU())

        self.conv4 = nn.Sequential(
            nn.Conv2d(in_channels=64, out_channels=64, kernel_size=3, stride=2, padding=1, groups=64, bias=True),
            nn.BatchNorm2d(64),
            nn.ReLU())

        self.residual_block = ResidualBlock(64, 128, stride=2)

        self.conv10 = nn.Sequential(
            nn.Conv2d(in_channels=256, out_channels=256, kernel_size=3, stride=1, padding=1, groups=256),
            nn.BatchNorm2d(256),
            nn.ReLU())

        self.conv11 = nn.Sequential(
            nn.Conv2d(in_channels=256, out_channels=256, kernel_size=1, stride=1),
            nn.BatchNorm2d(256),
            nn.ReLU())

        self.conv12 = nn.Sequential(
            nn.Conv2d(in_channels=256, out_channels=512, kernel_size=1, stride=1),
            nn.BatchNorm2d(512),
            nn.ReLU())

        self.Avgpool = nn.AdaptiveAvgPool2d((1,1))#将输入的特征图的大小调整为1x1x512

        self.fc = nn.Linear(512, num_classes)



    def forward(self, x):
        out = self.conv1(x)
        out = self.conv2(out)
        out = self.conv3(out)
        out = self.conv4(out)

        out = self.residual_block(out)

        out = self.conv10(out)
        out = self.conv11(out)
        out = self.conv12(out)

        out = self.Avgpool(out)
        out = torch.flatten(out, 1)
        out = self.fc(out)
        return out

model = Network()
model = model.cuda()
#
# # Print the model summary to the console
# torchsummary.summary(model, (3, 640, 640))

train.py

import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader, Dataset
from torchvision import transforms
from torchvision.models import resnet50, resnet101
from PIL import Image
import os
import model

class LogoDataset(Dataset):
    def __init__(self, root_dir, transform=None):
        self.root_dir = root_dir
        self.transform = transform
        self.image_files = []
        self.labels = []
        self.label_to_int = {}  # 创建一个字典来映射label和整数的关系
        self.int_to_label = {}  # 创建一个字典来映射整数和label的关系
        label_count = 0

        for label in os.listdir(root_dir):
            label_dir = os.path.join(root_dir, label)
            if os.path.isdir(label_dir):
                self.label_to_int[label] = label_count
                self.int_to_label[label_count] = label
                label_count += 1
                for image_file in os.listdir(label_dir):
                    self.image_files.append(os.path.join(label_dir, image_file))
                    self.labels.append(label)

    def __len__(self):
        return len(self.image_files)

    def __getitem__(self, idx):
        image = Image.open(self.image_files[idx]).convert("RGB")
        label = self.labels[idx]
        label = self.label_to_int[label]  # 使用字典将label转换为整数

        if self.transform:
            image = self.transform(image)

        return image, torch.tensor(label)


data_transform = transforms.Compose([
    transforms.Resize((640, 640)),
    transforms.RandomHorizontalFlip(),
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])

train_dataset = LogoDataset("E:/wingstudio/four/logo_data/train", transform=data_transform)
test_dataset = LogoDataset("E:/wingstudio/four/logo_data/test", transform=data_transform)

train_loader = DataLoader(train_dataset, batch_size=4, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=4, shuffle=False)

class LogoClassifier(nn.Module):
    def __init__(self, num_classes):
        super(LogoClassifier, self).__init__()
        self.base_model = model.Network()
        self.fc = nn.Linear(1000, num_classes)

    def forward(self, x):
        x = self.base_model(x)
        x = self.fc(x)
        return x

def train(model, train_loader, criterion, optimizer, device):
    model.train()
    running_loss = 0.0

    for images, labels in train_loader:
        images = images.to(device)
        labels = labels.to(device)

        optimizer.zero_grad()

        outputs = model(images)
        loss = criterion(outputs, labels)

        with torch.autograd.set_detect_anomaly(True):
            loss.backward()

        optimizer.step()

        running_loss += loss.item() * images.size(0)

    epoch_loss = running_loss / len(train_loader.dataset)
    return epoch_loss


def test(model, test_loader, criterion, device):
    model.eval()
    running_loss = 0.0
    correct = 0

    with torch.no_grad():
        for images, labels in test_loader:
            images = images.to(device)
            labels = labels.to(device)

            outputs = model(images)
            loss = criterion(outputs, labels)

            running_loss += loss.item() * images.size(0)
            _, predicted = torch.max(outputs, 1)
            correct += (predicted == labels).sum().item()

    epoch_loss = running_loss / len(test_loader.dataset)
    accuracy = correct / len(test_loader.dataset)
    return epoch_loss, accuracy

def main():
    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

    model = LogoClassifier(num_classes=5)
    model = model.to(device)

    criterion = nn.CrossEntropyLoss()
    optimizer = optim.SGD(model.parameters(), lr=0.01)

    for epoch in range(40):
        train_loss = train(model, train_loader, criterion, optimizer, device)
        test_loss, test_accuracy = test(model, test_loader, criterion, device)

        print(
            f"Epoch {epoch + 1}/{40}, Train Loss: {train_loss:.4f}, Test Loss: {test_loss:.4f}, Test Accuracy: {test_accuracy:.4f}")



if __name__ == "__main__":
    main()

当然在这个网络结构基础上我有个朋友跑出来的正确率稍微更高一点,同样作者厚着脸皮要来了,这里@下原作者:灼清回梦_-CSDN博客

他的model.py

import torch
import torch.nn as nn
import torchsummary
import matplotlib.pyplot as plt

class ResdualBlock(nn.Module):
    def __init__(self, in_channels, out_channels, stride):
        super(ResdualBlock, self).__init__()
        self.conv0 = nn.Conv2d(in_channels=64, out_channels=128, kernel_size=1, stride=1, bias=False)
        self.bn0 = nn.BatchNorm2d(128)
        self.relu = nn.ReLU()

        self.conv1 = nn.Conv2d(in_channels=128, out_channels=128, kernel_size=3, stride=1, padding=1, groups=128, bias=False)
        self.bn1 = nn.BatchNorm2d(128)
        self.relu = nn.ReLU()

        self.conv2 = nn.Conv2d(in_channels=128, out_channels=128, kernel_size=1, stride=1, bias=False)
        self.bn2 = nn.BatchNorm2d(128)

        self.conv3 = nn.Conv2d(in_channels=128, out_channels=128, kernel_size=3, stride=2, padding=1, groups=128, bias=False)
        self.bn3 = nn.BatchNorm2d(128)

        self.conv4 = nn.Conv2d(in_channels=128, out_channels=256, kernel_size=1, stride=1, bias=False)
        self.bn4 = nn.BatchNorm2d(256)

        self.shortcut = nn.Sequential()

        if stride != 1 and in_channels != out_channels:
            self.shortcut = nn.Sequential(nn.Conv2d(in_channels, out_channels=256, stride=2, kernel_size=1, bias=False),
                                          nn.BatchNorm2d(out_channels))

    def forward(self, x):
        identity = x

        out = self.conv0(x)
        out = self.bn0(out)
        out = self.relu(out)

        out = self.conv1(out)
        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(out)

        out = self.conv4(out)
        out = self.bn4(out)

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


class Network(nn.Module):
    def __init__(self, num_classes=1000):
        super(Network,self).__init__()
        self.conv5 = nn.Sequential(
            nn.Conv2d(in_channels=3, out_channels=32, kernel_size=3, stride=2, padding=1),
            nn.BatchNorm2d(32),
            nn.ReLU(inplace=True)
        )
        #320*320*32

        self.conv6 = nn.Sequential(
            nn.Conv2d(in_channels=32,out_channels=32,kernel_size=3,stride=2,padding=1,groups=32),
            nn.BatchNorm2d(32),
            nn.ReLU(inplace=True)
        )
        # 320*320*32

        self.conv7 = nn.Sequential(
            nn.Conv2d(in_channels=32, out_channels=64, kernel_size=1, stride=1),
            nn.BatchNorm2d(64),
            nn.ReLU(inplace=True)
        )
        #320*320*64

        self.conv8 = nn.Sequential(
            nn.Conv2d(in_channels=64, out_channels=64, kernel_size=3, stride=2,padding=1,groups=64),
            nn.BatchNorm2d(64),
            nn.ReLU(inplace=True)
        )
        #160*160*64

        self.layer1 = self.make_layer(64,256)

        self.conv9 = nn.Sequential(
            nn.Conv2d(in_channels=256,out_channels=256,kernel_size=3,stride=1,padding=1,groups=256,bias=False),
            nn.BatchNorm2d(256),
            nn.ReLU(inplace=True)
        )

        self.conv10 = nn.Sequential(
            nn.Conv2d(in_channels=256,out_channels=256,kernel_size=1,stride=1,bias=False),
            nn.BatchNorm2d(256),
            nn.ReLU(inplace=True)
        )

        self.conv11 = nn.Sequential(
            nn.Conv2d(in_channels=256, out_channels=512, kernel_size=1, stride=1, bias=False),
            nn.BatchNorm2d(512),
            nn.ReLU(inplace=True)
        )
        #80*80*512

        self.avgpool = nn.AdaptiveAvgPool2d((1,1))#1*1*512

        self.fc = nn.Linear(512,num_classes)

    def make_layer(self, in_channels, out_channels, stride=2):
        layer = []
        layer.append(ResdualBlock(in_channels,out_channels,stride))
        return nn.Sequential(*layer)

    def forward(self,x):
        out = self.conv5(x)
        out = self.conv6(out)
        out = self.conv7(out)
        out = self.conv8(out)

        out = self.layer1(out)

        out = self.conv9(out)
        out = self.conv10(out)
        out = self.conv11(out)

        out = self.avgpool(out)
        out = torch.flatten(out,1)
        out = self.fc(out)
        return out

model = Network()
model = model.cuda()

# Print the model summary to the console
torchsummary.summary(model, (3, 640, 640))

他的train.py

import torch
from torchvision import datasets, models, transforms
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader
import time


import numpy as np
import matplotlib.pyplot as plt
import os
from tqdm import tqdm

image_transforms = {
    'train': transforms.Compose([
        transforms.RandomResizedCrop(size=256, scale=(0.8, 1.0)),
        transforms.RandomRotation(degrees=15),
        transforms.RandomHorizontalFlip(),
        transforms.CenterCrop(size=224),
        transforms.ToTensor(),
        transforms.Normalize([0.485, 0.456, 0.406],
                             [0.229, 0.224, 0.225])
    ]),
    'test': transforms.Compose([
        transforms.Resize(size=256),
        transforms.CenterCrop(size=224),
        transforms.ToTensor(),
        transforms.Normalize([0.485, 0.456, 0.406],
                             [0.229, 0.224, 0.225])
    ])
}

dataset = 'E:\wingstudio/four\logo_data'
train_directory = os.path.join(dataset, 'train')
valid_directory = os.path.join(dataset, 'test')

batch_size = 32
num_classes = 5
print(train_directory)
data = {
    'train': datasets.ImageFolder(root=train_directory, transform=image_transforms['train']),
    'test': datasets.ImageFolder(root=valid_directory, transform=image_transforms['test'])
}


train_data_size = len(data['train'])
valid_data_size = len(data['test'])

train_data = DataLoader(data['train'], batch_size=batch_size, shuffle=True, num_workers=0)
valid_data = DataLoader(data['test'], batch_size=batch_size, shuffle=True, num_workers=0)

print(train_data_size, valid_data_size)

class ResdualBlock(nn.Module):
    def __init__(self, in_channels, out_channels, stride):
        super(ResdualBlock, self).__init__()
        self.conv0 = nn.Conv2d(in_channels=64, out_channels=128, kernel_size=1, stride=1, bias=False)
        self.bn0 = nn.BatchNorm2d(128)
        self.relu = nn.ReLU()

        self.conv1 = nn.Conv2d(in_channels=128, out_channels=128, kernel_size=3, stride=1, padding=1, groups=128, bias=False)
        self.bn1 = nn.BatchNorm2d(128)
        self.relu = nn.ReLU()

        self.conv2 = nn.Conv2d(in_channels=128, out_channels=128, kernel_size=1, stride=1, bias=False)
        self.bn2 = nn.BatchNorm2d(128)

        self.conv3 = nn.Conv2d(in_channels=128, out_channels=128, kernel_size=3, stride=2, padding=1, groups=128, bias=False)
        self.bn3 = nn.BatchNorm2d(128)

        self.conv4 = nn.Conv2d(in_channels=128, out_channels=256, kernel_size=1, stride=1, bias=False)
        self.bn4 = nn.BatchNorm2d(256)

        self.shortcut = nn.Sequential()

        if stride != 1 and in_channels != out_channels:
            self.shortcut = nn.Sequential(nn.Conv2d(in_channels, out_channels=256, stride=2, kernel_size=1, bias=False),
                                          nn.BatchNorm2d(out_channels))

    def forward(self, x):
        identity = x

        out = self.conv0(x)
        out = self.bn0(out)
        out = self.relu(out)

        out = self.conv1(out)
        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(out)

        out = self.conv4(out)
        out = self.bn4(out)

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

###开始拼接上下部分,要求图片大小先裁剪为640*640
class Network(nn.Module):
    def __init__(self, num_classes=1000):
        super(Network,self).__init__()
        self.conv5 = nn.Sequential(
            nn.Conv2d(in_channels=3, out_channels=32, kernel_size=3, stride=2, padding=1),
            nn.BatchNorm2d(32),
            nn.ReLU(inplace=True)
        )
        #320*320*32

        self.conv6 = nn.Sequential(
            nn.Conv2d(in_channels=32,out_channels=32,kernel_size=3,stride=2,padding=1,groups=32),
            nn.BatchNorm2d(32),
            nn.ReLU(inplace=True)
        )
        # 320*320*32

        self.conv7 = nn.Sequential(
            nn.Conv2d(in_channels=32, out_channels=64, kernel_size=1, stride=1),
            nn.BatchNorm2d(64),
            nn.ReLU(inplace=True)
        )
        #320*320*64

        self.conv8 = nn.Sequential(
            nn.Conv2d(in_channels=64, out_channels=64, kernel_size=3, stride=2,padding=1,groups=64),
            nn.BatchNorm2d(64),
            nn.ReLU(inplace=True)
        )
        #160*160*64

        self.layer1 = self.make_layer(64,256)

        self.conv9 = nn.Sequential(
            nn.Conv2d(in_channels=256,out_channels=256,kernel_size=3,stride=1,padding=1,groups=256,bias=False),
            nn.BatchNorm2d(256),
            nn.ReLU(inplace=True)
        )

        self.conv10 = nn.Sequential(
            nn.Conv2d(in_channels=256,out_channels=256,kernel_size=1,stride=1,bias=False),
            nn.BatchNorm2d(256),
            nn.ReLU(inplace=True)
        )

        self.conv11 = nn.Sequential(
            nn.Conv2d(in_channels=256, out_channels=512, kernel_size=1, stride=1, bias=False),
            nn.BatchNorm2d(512),
            nn.ReLU(inplace=True)
        )
        #80*80*512

        self.avgpool = nn.AdaptiveAvgPool2d((1,1))#1*1*512

        self.fc = nn.Linear(512,num_classes)

    def make_layer(self, in_channels, out_channels, stride=2):
        layer = []
        layer.append(ResdualBlock(in_channels,out_channels,stride))
        return nn.Sequential(*layer)

    def forward(self,x):
        out = self.conv5(x)
        out = self.conv6(out)
        out = self.conv7(out)
        out = self.conv8(out)

        out = self.layer1(out)

        out = self.conv9(out)
        out = self.conv10(out)
        out = self.conv11(out)

        out = self.avgpool(out)
        out = torch.flatten(out,1)
        out = self.fc(out)
        return out

resnet_net = Network()
Network.cuda(resnet_net)

loss_func = nn.CrossEntropyLoss()
optimizer = optim.SGD(resnet_net.parameters(),lr=0.01)

def train_and_valid(model, loss_function, optimizer, epochs=50):
    device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
    history = []
    best_acc = 0.0
    best_epoch = 0

    for epoch in range(epochs):
        epoch_start = time.time()
        print("Epoch: {}/{}".format(epoch+1, epochs))

        model.train()

        train_loss = 0.0
        train_acc = 0.0
        valid_loss = 0.0
        valid_acc = 0.0

        for i, (inputs, labels) in enumerate(tqdm(train_data)):
            inputs = inputs.to(device)
            labels = labels.to(device)
            optimizer.zero_grad()
            outputs = model(inputs)
            loss = loss_function(outputs, labels)
            loss.backward()
            optimizer.step()
            train_loss += loss.item() * inputs.size(0)
            ret, predictions = torch.max(outputs.data, 1)
            correct_counts = predictions.eq(labels.data.view_as(predictions))
            acc = torch.mean(correct_counts.type(torch.FloatTensor))
            train_acc += acc.item() * inputs.size(0)

        with torch.no_grad():
            model.eval()

            for j, (inputs, labels) in enumerate(tqdm(valid_data)):
                inputs = inputs.to(device)
                labels = labels.to(device)
                outputs = model(inputs)
                loss = loss_function(outputs, labels)
                valid_loss += loss.item() * inputs.size(0)
                ret, predictions = torch.max(outputs.data, 1)
                correct_counts = predictions.eq(labels.data.view_as(predictions))
                acc = torch.mean(correct_counts.type(torch.FloatTensor))
                valid_acc += acc.item() * inputs.size(0)

        avg_train_loss = train_loss/train_data_size
        avg_train_acc = train_acc/train_data_size

        avg_valid_loss = valid_loss/valid_data_size
        avg_valid_acc = valid_acc/valid_data_size

        history.append([avg_train_loss, avg_valid_loss, avg_train_acc, avg_valid_acc])

        if best_acc < avg_valid_acc:
            best_acc = avg_valid_acc
            best_epoch = epoch + 1

        epoch_end = time.time()

        print("Epoch: {:03d}, Training: Loss: {:.4f}, Accuracy: {:.4f}%, \n\t\tValidation: Loss: {:.4f}, Accuracy: {:.4f}%, Time: {:.4f}s".format(
            epoch+1, avg_valid_loss, avg_train_acc*100, avg_valid_loss, avg_valid_acc*100, epoch_end-epoch_start
        ))
        print("Best Accuracy for validation : {:.4f} at epoch {:03d}".format(best_acc, best_epoch))

        torch.save(model,dataset + '_model_' + str(epoch + 1) + '.pt')
    return model, history

num_epochs = 40
trained_model, history = train_and_valid(resnet_net, loss_func, optimizer, num_epochs)
torch.save(history,dataset+'_history.pt')

history = np.array(history)
plt.plot(history[:, 0:2])
plt.legend(['Tr Loss', 'Val Loss'])
plt.xlabel('Epoch Number')
plt.ylabel('Loss')
plt.ylim(0, 2)
plt.show()

plt.plot(history[:, 2:4])
plt.legend(['Tr Accuracy', 'Val Accuracy'])
plt.xlabel('Epoch Number')
plt.ylabel('Accuracy')
plt.ylim(0, 1)
plt.show()

# 六、使用模型进行预测
# 加载训练好的模型
model = torch.load(dataset+'_model_'+str(num_epochs)+'.pt')
model.eval()

# 定义预测函数
def predict_image(image_path):
    image = image_transforms['test'](Image.open(image_path))
    image_tensor = image.unsqueeze_(0)
    input = image_tensor.to("cuda:0")
    output = model(input)
    index = output.data.cpu().numpy().argmax()
    return index

# 预测新的图像是个啥
from PIL import Image
image_path = r'E:\wingstudio\four\logo_data\test\burger king\ankamall_image_106.jpg'
print("这张图片标签索引是:",predict_image(image_path))

def predict(model, image_path):
    # 加载图像并进行预处理
    image = Image.open(image_path)
    image_tensor = image_transforms['test'](image).float()
    image_tensor = image_tensor.unsqueeze_(0)
    input = input = image_tensor

    # 将输入传递给模型并获取输出
    output = model(input.cuda())

    # 获取预测结果并转换为类别标签
    _, predicted = torch.max(output.data, 1)
    class_index = predicted.cpu().numpy()[0]
    return data['train'].classes[class_index]


# 预测again
image_path = r'E:\wingstudio\four\logo_data\test\burger king\ankamall_image_106.jpg'
print("这张图片是:", predict(trained_model, image_path))

以上就是全部内容了,我还会继续向更加优秀的博主和up主学习,看到这个应该也是真爱粉了,大家一起共勉吧

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Apollo是一个来自华为的开源项目,是一个面向大规模机器学习的高效神经网络训练框架。而VSCode是一款由微软开发的轻量级代码编辑器。所以,Apollo VSCode Debug指的是在使用Apollo框架进行开发时,通过VSCode编辑器来进行调试。 在进行Apollo VSCode Debug之前,需要进行一些准备工作。首先,确保已经安装了VSCode编辑器以及相应的Apollo插件。其次,需要有一个Apollo的项目代码,在VSCode中进行打开。 接下来,我们可以通过以下几个步骤来进行Apollo VSCode Debug。 第一步,配置调试环境。在VSCode的工具栏中选择"调试",点击"添加配置"。在弹出的配置文件中,填相关的调试信息,例如调试模式、入口文件等。这些信息将用于配置调试器。 第二步,设置断点。在代码中选择想要调试的位置,点击行号旁边的空白区域,添加断点。断点将会在程序执行到该处时暂停,方便我们对代码进行调试。 第三步,运行调试。点击VSCode工具栏中的"调试"按钮,选择刚刚配置的调试环境。然后,点击"开始调试"。Apollo框架会在VSCode中启动,并根据我们的配置信息运行。 第四步,调试代码。当程序执行到我们设置的断点位置时,会自动暂停运行。这时,我们可以通过在VSCode中的调试面板上看到当前的变量值、堆栈信息等。通过逐步执行、观察变量变化等方式来调试代码。还可以使用控制台面板来输入调试命令,与程序进行交互。 最后,我们可以根据调试过程中的问题,对代码进行修改和优化。在调试结束后,点击调试器面板的"关闭"按钮,结束调试状态。 通过Apollo在VSCode中进行调试,可以提高开发效率,快速定位问题,促进代码的开发和调试过程。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值