重置所有文件与main一致,新增app.py(Gradio推理前端)
This commit is contained in:
@@ -1,99 +1,113 @@
|
||||
"""
|
||||
这个文件是模型的定义文件,请不要擅自修改,如有疑问微信群里反馈
|
||||
单独运行本文件将会输出模型结构
|
||||
目前的话是一个36层的模型,模型总量应该是在80M左右 如果到时候还是欠拟合的话再考虑去做更深的结构
|
||||
模型定义文件 - ResNet-34
|
||||
author : yukun-hh
|
||||
date : 2026-4-10
|
||||
|
||||
"""
|
||||
#神经网络模型库
|
||||
import torch
|
||||
from torch import nn
|
||||
from torch.nn import functional as F
|
||||
from torchsummary import summary
|
||||
#残差块
|
||||
class Resblock(nn.Module):
|
||||
def __init__(self, input_channels,output_channels,use_1x1conv=False,strides=1):
|
||||
"""
|
||||
|
||||
:param input_channels: 进入残差块时的原通道
|
||||
:param output_channels: 输出时的通道数
|
||||
:param use_1x1conv: 如果输入和输出通道不相等时,需要用一个1x1的卷积层对原来的输入进行一个通道提升
|
||||
:param strides: 默认1,如果大于1起到缩小张量的作用
|
||||
"""
|
||||
|
||||
class BasicBlock(nn.Module):
|
||||
"""
|
||||
ResNet-34 基础残差块:3x3 -> 3x3
|
||||
若需要下采样或通道变化,则在跳跃连接中使用 1x1 卷积
|
||||
"""
|
||||
expansion = 1
|
||||
|
||||
def __init__(self, in_channels, out_channels, stride=1, downsample=None):
|
||||
super().__init__()
|
||||
self.conv1 = nn.Conv2d(input_channels,output_channels,kernel_size=3,padding=1,stride=strides)
|
||||
self.conv2 = nn.Conv2d(output_channels,output_channels,kernel_size=3,padding=1,stride=1)
|
||||
if use_1x1conv:
|
||||
self.conv3 = nn.Conv2d(input_channels, output_channels,kernel_size=1, stride=strides)
|
||||
else:
|
||||
self.conv3 = None
|
||||
self.bn1 = nn.BatchNorm2d(output_channels)
|
||||
self.bn2 = nn.BatchNorm2d(output_channels)
|
||||
def forward(self,X):
|
||||
Y = F.relu(self.bn1(self.conv1(X)))
|
||||
Y = self.bn2(self.conv2(Y))
|
||||
if self.conv3 is not None:
|
||||
X = self.conv3(X)
|
||||
Y += X
|
||||
return F.relu(Y)
|
||||
self.conv1 = nn.Conv2d(in_channels, out_channels, kernel_size=3, stride=stride, padding=1, bias=False)
|
||||
self.bn1 = nn.BatchNorm2d(out_channels)
|
||||
self.conv2 = nn.Conv2d(out_channels, out_channels, kernel_size=3, stride=1, padding=1, bias=False)
|
||||
self.bn2 = nn.BatchNorm2d(out_channels)
|
||||
self.relu = nn.ReLU(inplace=True)
|
||||
self.downsample = downsample
|
||||
|
||||
class Net():
|
||||
"""
|
||||
模型的主要结构就在这里了,到时也好该和调用
|
||||
现在必须实现的方法:
|
||||
目前还是以图片缩放到256*256构建残差块
|
||||
"""
|
||||
net = nn.Sequential()
|
||||
def resnet_block(self,input_channels, num_channels, num_residuals,
|
||||
first_block=False):
|
||||
"""
|
||||
:param input_channels: 输入维度
|
||||
:param num_channels: 输出维度
|
||||
:param num_residuals: 单个残差层的残差块数
|
||||
:param first_block: 第一块不用下采样 特殊控制
|
||||
:return: list[nn.Module]
|
||||
"""
|
||||
blk = []
|
||||
def forward(self, x):
|
||||
identity = x
|
||||
|
||||
for i in range(num_residuals):
|
||||
if i == 0 and not first_block:
|
||||
blk.append(Resblock(input_channels, num_channels,
|
||||
use_1x1conv=True, strides=2))
|
||||
else:
|
||||
blk.append(Resblock(num_channels, num_channels))
|
||||
return blk
|
||||
def __init__(self):
|
||||
b1 = nn.Sequential( nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3),
|
||||
nn.BatchNorm2d(64), nn.ReLU(),
|
||||
nn.MaxPool2d(kernel_size=3, stride=2, padding=1)
|
||||
)
|
||||
"""
|
||||
7×7 卷积层,输出通道 64,步长 2,填充 3
|
||||
(3×256×256)->(64×128×128)
|
||||
批归一化 relu层
|
||||
最大池化
|
||||
(64×128×128)->(64×64×64)
|
||||
"""
|
||||
b2 = nn.Sequential(*self.resnet_block(64, 64, num_residuals=3, first_block=True))
|
||||
b3 = nn.Sequential(*self.resnet_block(64, 128, num_residuals=4))
|
||||
b4 = nn.Sequential(*self.resnet_block(128, 256, num_residuals=6))
|
||||
b5 = nn.Sequential(*self.resnet_block(256, 512, num_residuals=3))
|
||||
self.net = nn.Sequential(b1, b2, b3, b4, b5,nn.AdaptiveAvgPool2d((1,1)),nn.Flatten(), nn.Linear(512, 4))
|
||||
def get_network(self):
|
||||
return self.net
|
||||
out = self.conv1(x)
|
||||
out = self.bn1(out)
|
||||
out = self.relu(out)
|
||||
|
||||
out = self.conv2(out)
|
||||
out = self.bn2(out)
|
||||
|
||||
if self.downsample is not None:
|
||||
identity = self.downsample(x)
|
||||
|
||||
out += identity
|
||||
out = self.relu(out)
|
||||
return out
|
||||
|
||||
|
||||
class Net(nn.Module):
|
||||
|
||||
def __init__(self, num_classes=4, dropout=0.5):
|
||||
super().__init__()
|
||||
|
||||
self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3, bias=False)
|
||||
self.bn1 = nn.BatchNorm2d(64)
|
||||
self.relu = nn.ReLU(inplace=True)
|
||||
self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)
|
||||
|
||||
layers_config = [
|
||||
(3, 64, 1), # layer1
|
||||
(4, 128, 2), # layer2
|
||||
(6, 256, 2), # layer3
|
||||
(3, 512, 2), # layer4
|
||||
]
|
||||
|
||||
self.in_channels = 64
|
||||
self.layer1 = self._make_layer(layers_config[0])
|
||||
self.layer2 = self._make_layer(layers_config[1])
|
||||
self.layer3 = self._make_layer(layers_config[2])
|
||||
self.layer4 = self._make_layer(layers_config[3])
|
||||
|
||||
self.avgpool = nn.AdaptiveAvgPool2d((1, 1))
|
||||
self.dropout = nn.Dropout(dropout)
|
||||
self.fc = nn.Linear(512, num_classes)
|
||||
|
||||
def _make_layer(self, config):
|
||||
num_blocks, out_channels, stride = config
|
||||
downsample = None
|
||||
layers = []
|
||||
|
||||
if stride != 1 or self.in_channels != out_channels:
|
||||
downsample = nn.Sequential(
|
||||
nn.Conv2d(self.in_channels, out_channels,
|
||||
kernel_size=1, stride=stride, bias=False),
|
||||
nn.BatchNorm2d(out_channels),
|
||||
)
|
||||
|
||||
layers.append(BasicBlock(self.in_channels, out_channels, stride, downsample))
|
||||
self.in_channels = out_channels
|
||||
|
||||
for _ in range(1, num_blocks):
|
||||
layers.append(BasicBlock(self.in_channels, out_channels))
|
||||
|
||||
return nn.Sequential(*layers)
|
||||
|
||||
def forward(self, x):
|
||||
x = self.conv1(x)
|
||||
x = self.bn1(x)
|
||||
x = self.relu(x)
|
||||
x = self.maxpool(x)
|
||||
|
||||
x = self.layer1(x)
|
||||
x = self.layer2(x)
|
||||
x = self.layer3(x)
|
||||
x = self.layer4(x)
|
||||
|
||||
x = self.avgpool(x)
|
||||
x = torch.flatten(x, 1)
|
||||
x = self.dropout(x)
|
||||
x = self.fc(x)
|
||||
return x
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
Net_new = Net()
|
||||
X = torch.rand(size=(1, 3, 256, 256))
|
||||
summary(Net_new.get_network(), input_size=(3, 256, 256))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
model = Net(num_classes=4)
|
||||
summary(model, input_size=(3, 256, 256))
|
||||
|
||||
Reference in New Issue
Block a user