该项目是按照别人的视频搭建起来的ResNet34网络,视频参考
开放集环境下的垃圾分类,训练的已知类数量为24,未知类数量为16。
数据集来源
下载好数据集以后,我自己写了自定义数据类GARBAGE40_Dataset()
测试集包含了所有的40个垃圾类别。
网络结构
因为把初始化函数__init__()打错了,所以调了很久的bug,这种因为打错而调试的bug还是让我废了很大功夫才找出来,期间也发现了卷积网络的输入输入通道数输错了。
TypeError: init() got an unexpected keyword argument ‘downsample’
代码
Resnet.py
'''
python3.7
-*- coding: UTF-8 -*-
@Project -> File :pythonProject -> Resnet
@IDE :PyCharm
@Author :YangShouWei
@USER: 296714435
@Date :2022/2/18 11:48:27
@LastEditor:
'''
import torch.nn as nn
import torch
class BasicBlock(nn.Module):
expansion = 1 # 表示主线上的卷积层使用的卷积核个数相同。
def __init__(self,in_channel, out_channel, stride=1, downsample=None):
"""
18层和34层的残差结构
:param in_channel: 输入特征通道数
:param out_channel:输出特征通道数
:param stride: 步长
:param downsample: 下采样参数
"""
super(BasicBlock,self).__init__()
self.conv1 = nn.Conv2d(in_channels=in_channel,out_channels=out_channel,
kernel_size=3, stride=stride, padding=1,bias=False)
self.bn1 = nn.BatchNorm2d(out_channel)
self.relu = nn.ReLU()
self.conv2 = nn.Conv2d(in_channels=out_channel, out_channels=out_channel,
kernel_size=3, stride=1, padding=1, bias=False)
self.bn2 = nn.BatchNorm2d(out_channel)
self.downsample = downsample
def forward(self,x):
identity = x
if self.downsample is not None:
identity = self.downsample(x) # 捷径分支的输出
out = self.conv1(x)
out = self.bn1(out)
out = self.relu(out)
out = self.conv2(out)
out = self.bn2(out)
out += identity # 主线输出和捷径输出相加,然后再relu
out = self.relu(out)
return out
class Bottleneck(nn.Module):
expansion = 4 # 主线上的卷积核个数在变化,每一个残差结构中的第三层卷积层中的卷积核个数是第一层、第二层卷积核个数的四倍。
def __init__(self, in_channel, out_channel, stride=1, downsample=None):
"""
50层、101层、152层残差结构
:param in_channel:
:param out_channel:
:param stride:
:param downsample:
:return:
"""
super(Bottleneck, self).__init__()
# super(Bottleneck, self).__init__()
self.conv1 = nn.Conv2d(in_channels=in_channel, out_channels=out_channel,
kernel_size=1, stride=1, bias=False) # sequeeze channels
self.bn1 = nn.BatchNorm2d(out_channel)
#-----------------------------------------------
self.conv2 = nn.Conv2d(in_channels=out_channel, out_channels=out_channel,
kernel_size=3, stride=stride, bias=False,padding=1)
self.bn2 = nn.BatchNorm2d(out_channel)
#-----------------------------------------------
self.conv3 = nn.Conv2d(in_channels=out_channel,out_channels=out_channel*self.expansion,
kernel_size=1, stride=1,bias=False) # unsqueeze channels
self.bn3 = nn.BatchNorm2d(out_channel*self.expansion)
self.relu = nn.ReLU(inplace=True)
self.downsample = downsample
def forward(self, x):
identity = x
if self.downsample is not None:
identity = self.downsample(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 += identity
out = self.relu(out)
return out
class ResNet(nn.Module):
def __init__(self, block, blocks_num, num_classes=1000, include_top=True):
"""
:param block: 残差结构
:param blocks_num: 使用残差结构数目
:param num_classes: 训练类别数量
:param include_top:方便以后搭建更复杂的网络
"""
super(ResNet, self).__init__()
self.include_top = include_top
self.in_channel = 64
self.conv1 = nn.Conv2d(3, self.in_channel, kernel_size=7, stride=2,
padding=3,bias=False)
self.bn1 = nn.BatchNorm2d(self.in_channel)
self.relu = nn.ReLU(inplace=True)
self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)
# 卷积层堆叠
self.layer1 = self._make_layer(block, 64, blocks_num[0])
self.layer2 = self._make_layer(block, 128,blocks_num[1],stride=2)
self.layer3 = self._make_layer(block, 256,blocks_num[2],stride=2)
self.layer4 = self._make_layer(block, 512,blocks_num[3],stride=2)
if self.include_top:
self.avgpool = nn