使用pytorch搭建resnet50

前期准备

导入需要的包

import torch
import torch.nn as nn
import torch.nn.functional as F
import matplotlib.pyplot as plt
import os, PIL
import numpy as np
from torch.utils.data import DataLoader,Subset
from torchvision import transforms
from torchvision.datasets import ImageFolder

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
plt.rcParams["font.sans-serif"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False

遍历并展示图片数量

path = "./data/bird_photos"
f = []
for root, dirs, files in os.walk(path):
    for name in files:
        f.append(os.path.join(root, name))
print("图片总数:",len(f))

图片总数: 565

导入数据

transform = transforms.Compose([
    transforms.Resize(224), #统一图片大小
    transforms.ToTensor(),
    transforms.Normalize([0.485, 0.456, 0.406],[0.229, 0.224, 0.225]) #标准化
])
data = ImageFolder(path, transform = transform)
print(data.class_to_idx)
print(data.classes)

{‘Bananaquit’: 0, ‘Black Skimmer’: 1, ‘Black Throated Bushtiti’: 2, ‘Cockatoo’: 3}
[‘Bananaquit’, ‘Black Skimmer’, ‘Black Throated Bushtiti’, ‘Cockatoo’]

可视化数据

def imageshow(data, idx, norm = None, label = False):
    plt.figure(dpi=100,figsize=(12,4))
    for i in range(15):
        plt.subplot(3, 5, i + 1)
        img = data[idx[i]][0].numpy().transpose((1, 2, 0))
        if norm is not None:
            mean = norm[0]
            std = norm[1]
            img = img * std + mean
        img = np.clip(img, a_min = 0, a_max=1)
        plt.imshow(img)
    
        if label:
            plt.title(data.classes[data[idx[i]][1]])
        plt.axis('off')
        plt.tight_layout(pad=0.5)
    plt.show()

norm = [[0.485, 0.456, 0.406],[0.229, 0.224, 0.225]]
np.random.seed(22)
demo_img_ids = np.random.randint(564,size = 15)
imageshow(data, demo_img_ids, norm = norm, label = True) 

在这里插入图片描述

配置数据集

torch.manual_seed(123)
train_ds, test_ds = torch.utils.data.random_split(data, [452,113])
train_dl = DataLoader(train_ds, batch_size = 8, shuffle=True, prefetch_factor=2) #prefetch_factor 加速训练, shffule 打乱数据
test_dl = DataLoader(train_ds, batch_size = 8, shuffle=False, prefetch_factor=2 )

再次检查数据

dataiter = iter(train_dl)
print("batch img shape: ", dataiter.next()[0].shape)
print(“batch label shape:”, dataiter.next()[1].shape)

构建模型

import torch
import torch.nn as nn
from torchvision.models import resnet50

class resnet_50(nn.Module):
    def __init__(self):
        super(resnet_50, self).__init__()
        self.conv1 = nn.Conv2d(3, 64, kernel_size=7,stride = 2,padding=3)
        self.bn = nn.BatchNorm2d(64)
        self.relu = nn.ReLU(inplace=True)
        self.pool1 = nn.MaxPool2d(kernel_size=3, stride=2 ,padding=1)
        
        self.layer1 = self.make_layer(BottleBlock, [64,64], 3)
        self.layer2 = self.make_layer(BottleBlock, [256,128], 4)
        self.layer3 = self.make_layer(BottleBlock, [512,256], 6)
        self.layer4 = self.make_layer(BottleBlock, [1024,512], 3)
        
        self.avgpool = nn.AdaptiveAvgPool2d((1, 1))
        self.fc = nn.Sequential(
            nn.Flatten(),
            nn.Linear(2048,4))
        
    #创建一个拼接的模块    
    def make_layer(self, module, filters, n_layer):
        filter1, filter2 = filters
        layers = nn.Sequential()
        layers.add_module('0', module(filter1, filter2))
        
        filter1 = filter2*4
        for i in range(1, n_layer):
            layers.add_module(str(i), module(filter1, filter2))
        return layers
        
    def forward(self,x):
        out = self.conv1(x)
        out = self.bn(out)
        out = self.relu(out)
        out = self.pool1(out)
        
        out = self.layer1(out)
        out = self.layer2(out)
        out = self.layer3(out)
        out = self.layer4(out)      
        
        out = self.avgpool(out)
        return self.fc(out)
        


class BottleBlock(nn.Module):
    def __init__(self, in_c, out_c):
        super().__init__()
        self.conv1 = nn.Conv2d(in_c, out_c, kernel_size=1)
        self.bn1 = nn.BatchNorm2d(out_c)
        self.ac = nn.ReLU(inplace=True)
        
        self.conv2 = nn.Conv2d(out_c, out_c, kernel_size=3, padding=1)
        self.bn2 = nn.BatchNorm2d(out_c)
        
        self.conv3 = nn.Conv2d(out_c, out_c * 4, kernel_size=1)
        self.bn3 = nn.BatchNorm2d(out_c * 4)
        
        if in_c != out_c * 4:
            self.downsample = nn.Sequential(
                nn.Conv2d(in_c, out_c * 4, kernel_size=1),  
                nn.BatchNorm2d(out_c * 4)
                )
            
        else: self.downsample = nn.Identity()
        
    def forward(self, x):
        out = self.conv1(x)
        out = self.bn1(out)
        out = self.ac(out)
        out = self.conv2(out)
        out = self.bn2(out)
        out = self.ac(out)
        out = self.conv3(out)
        out = self.bn3(out)
        x = self.downsample(x)
        
        return self.ac(x + out)

直接调用的话从torchvision.models调用resnet50()即可

模型结构

resnet_50(
(conv1): Conv2d(3, 64, kernel_size=(7, 7), stride=(2, 2), padding=(3, 3))
(bn): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(relu): ReLU(inplace=True)
(pool1): MaxPool2d(kernel_size=3, stride=2, padding=1, dilation=1, ceil_mode=False)
(layer1): Sequential(
(0): BottleBlock(
(conv1): Conv2d(64, 64, kernel_size=(1, 1), stride=(1, 1))
(bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(ac): ReLU(inplace=True)
(conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(conv3): Conv2d(64, 256, kernel_size=(1, 1), stride=(1, 1))
(bn3): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(downsample): Sequential(
(0): Conv2d(64, 256, kernel_size=(1, 1), stride=(1, 1))
(1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
)
)
(1): BottleBlock(
(conv1): Conv2d(256, 64, kernel_size=(1, 1), stride=(1, 1))
(bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(ac): ReLU(inplace=True)
(conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(conv3): Conv2d(64, 256, kernel_size=(1, 1), stride=(1, 1))
(bn3): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(downsample): Identity()
)
(2): BottleBlock(
(conv1): Conv2d(256, 64, kernel_size=(1, 1), stride=(1, 1))
(bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(ac): ReLU(inplace=True)
(conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(conv3): Conv2d(64, 256, kernel_size=(1, 1), stride=(1, 1))
(bn3): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(downsample): Identity()
)
)
(layer2): Sequential(
(0): BottleBlock(
(conv1): Conv2d(256, 128, kernel_size=(1, 1), stride=(1, 1))
(bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(ac): ReLU(inplace=True)
(conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(conv3): Conv2d(128, 512, kernel_size=(1, 1), stride=(1, 1))
(bn3): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(downsample): Sequential(
(0): Conv2d(256, 512, kernel_size=(1, 1), stride=(1, 1))
(1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
)
)
(1): BottleBlock(
(conv1): Conv2d(512, 128, kernel_size=(1, 1), stride=(1, 1))
(bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(ac): ReLU(inplace=True)
(conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(conv3): Conv2d(128, 512, kernel_size=(1, 1), stride=(1, 1))
(bn3): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(downsample): Identity()
)
(2): BottleBlock(
(conv1): Conv2d(512, 128, kernel_size=(1, 1), stride=(1, 1))
(bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(ac): ReLU(inplace=True)
(conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(conv3): Conv2d(128, 512, kernel_size=(1, 1), stride=(1, 1))
(bn3): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(downsample): Identity()
)
(3): BottleBlock(
(conv1): Conv2d(512, 128, kernel_size=(1, 1), stride=(1, 1))
(bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(ac): ReLU(inplace=True)
(conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(conv3): Conv2d(128, 512, kernel_size=(1, 1), stride=(1, 1))
(bn3): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(downsample): Identity()
)
)
(layer3): Sequential(
(0): BottleBlock(
(conv1): Conv2d(512, 256, kernel_size=(1, 1), stride=(1, 1))
(bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(ac): ReLU(inplace=True)
(conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(conv3): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1))
(bn3): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(downsample): Sequential(
(0): Conv2d(512, 1024, kernel_size=(1, 1), stride=(1, 1))
(1): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
)
)
(1): BottleBlock(
(conv1): Conv2d(1024, 256, kernel_size=(1, 1), stride=(1, 1))
(bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(ac): ReLU(inplace=True)
(conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(conv3): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1))
(bn3): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(downsample): Identity()
)
(2): BottleBlock(
(conv1): Conv2d(1024, 256, kernel_size=(1, 1), stride=(1, 1))
(bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(ac): ReLU(inplace=True)
(conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(conv3): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1))
(bn3): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(downsample): Identity()
)
(3): BottleBlock(
(conv1): Conv2d(1024, 256, kernel_size=(1, 1), stride=(1, 1))
(bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(ac): ReLU(inplace=True)
(conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(conv3): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1))
(bn3): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(downsample): Identity()
)
(4): BottleBlock(
(conv1): Conv2d(1024, 256, kernel_size=(1, 1), stride=(1, 1))
(bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(ac): ReLU(inplace=True)
(conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(conv3): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1))
(bn3): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(downsample): Identity()
)
(5): BottleBlock(
(conv1): Conv2d(1024, 256, kernel_size=(1, 1), stride=(1, 1))
(bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(ac): ReLU(inplace=True)
(conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(conv3): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1))
(bn3): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(downsample): Identity()
)
)
(layer4): Sequential(
(0): BottleBlock(
(conv1): Conv2d(1024, 512, kernel_size=(1, 1), stride=(1, 1))
(bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(ac): ReLU(inplace=True)
(conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(conv3): Conv2d(512, 2048, kernel_size=(1, 1), stride=(1, 1))
(bn3): BatchNorm2d(2048, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(downsample): Sequential(
(0): Conv2d(1024, 2048, kernel_size=(1, 1), stride=(1, 1))
(1): BatchNorm2d(2048, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
)
)
(1): BottleBlock(
(conv1): Conv2d(2048, 512, kernel_size=(1, 1), stride=(1, 1))
(bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(ac): ReLU(inplace=True)
(conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(conv3): Conv2d(512, 2048, kernel_size=(1, 1), stride=(1, 1))
(bn3): BatchNorm2d(2048, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(downsample): Identity()
)
(2): BottleBlock(
(conv1): Conv2d(2048, 512, kernel_size=(1, 1), stride=(1, 1))
(bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(ac): ReLU(inplace=True)
(conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(conv3): Conv2d(512, 2048, kernel_size=(1, 1), stride=(1, 1))
(bn3): BatchNorm2d(2048, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(downsample): Identity()
)
)
(avgpool): AdaptiveAvgPool2d(output_size=(1, 1))
(fc): Sequential(
(0): Flatten(start_dim=1, end_dim=-1)
(1): Linear(in_features=2048, out_features=4, bias=True)
)
)

训练

import copy
def train_model(epoch, model, optim, loss_function, train_dl, test_dl=None,lr_scheduler = None):
    for k in range(epoch):
        model.train()
        train_acc,train_len = 0, 0 
        history={"train_loss":[],
                "train_acc":[],
                "val_loss":[],
                "val_acc":[],
                'best_val_acc': (0, 0)}
        best_acc = 0.0
        for step, (x, y) in enumerate(train_dl):
            #print(step)
            x,y = x.to(device), y.to(device)
            y_h = model(x)
            optim.zero_grad()
            loss = loss_function(y_h, y)
            loss.backward()
            optim.step()
            predict = torch.max(y_h,dim=1)[1]
            train_acc += (predict == y).sum().item()
            train_len += len(y)
            trainacc = train_acc/train_len*100
            history['train_loss'].append(loss)
            history['train_acc'].append(trainacc)
             
        val_loss = 0.0
        val_acc,val_len = 0, 0  
        if test_dl is not None:
            model.eval()
            with torch.no_grad():
                for _, (x,y) in enumerate(test_dl):
                    x,y = x.to(device), y.to(device)
                    y_h = model(x)
                    loss = loss_function(y_h, y)
                    val_loss += loss.item()
                    predict = torch.max(y_h,dim=1)[1]
                    val_acc += (predict == y).sum().item()
                    val_len += len(y)
            acc = val_acc/val_len*100
            history['val_loss'].append(val_loss)
            history['val_acc'].append(acc)
        if (k+1)%5 == 0:
            print(f"epoch: {k+1}/{epoch}\n   train_loss: {history['train_loss'][-1]},\n   train_acc: {trainacc},\n   val_acc: {acc},\n   val_loss: {history['val_loss'][-1]}")
        if lr_scheduler is not None: 
            lr_scheduler.step()    
        if best_acc< trainacc:
            best_acc = acc
            history['best val acc']= (epoch, acc)
            best_model_wts = copy.deepcopy(model.state_dict())
    print('=' * 80)
    print(f'Best val acc: {best_acc}')        
    return model, history, best_model_wts
model = model.to(device)
loss_fn = nn.CrossEntropyLoss()
optims = torch.optim.Adam(model.parameters(), lr = 1e-2)
lr_scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(optims, 50, last_epoch=-1)
model, history, best_model_wts = train_model(50, model, optims, loss_fn, train_dl, test_dl,lr_scheduler)

epoch: 5/50
train_loss: 1.847571849822998,
train_acc: 55.309734513274336,
val_acc: 63.05309734513275,
val_loss: 50.35431948304176
epoch: 10/50
train_loss: 0.7257082462310791,
train_acc: 67.2566371681416,
val_acc: 73.45132743362832,
val_loss: 38.31608283519745
epoch: 15/50
train_loss: 2.0622646808624268,
train_acc: 71.90265486725663,
val_acc: 76.32743362831859,
val_loss: 39.227920800447464
epoch: 20/50
train_loss: 0.4547763168811798,
train_acc: 74.33628318584071,
val_acc: 82.30088495575221,
val_loss: 30.020944364368916
epoch: 25/50
train_loss: 0.8759856820106506,
train_acc: 78.53982300884957,
val_acc: 82.96460176991151,
val_loss: 28.743371352553368
epoch: 30/50
train_loss: 0.47582224011421204,
train_acc: 84.2920353982301,
val_acc: 87.16814159292035,
val_loss: 22.805100582540035
epoch: 35/50
train_loss: 0.0441904254257679,
train_acc: 86.28318584070797,
val_acc: 90.929203539823,
val_loss: 17.29164396226406
epoch: 40/50
train_loss: 0.03551850467920303,
train_acc: 92.69911504424779,
val_acc: 94.69026548672566,
val_loss: 13.524833716917783
epoch: 45/50
train_loss: 0.6849393248558044,
train_acc: 92.69911504424779,
val_acc: 96.46017699115043,
val_loss: 7.896297907456756
epoch: 50/50
train_loss: 0.22759416699409485,
train_acc: 95.57522123893806,
val_acc: 97.78761061946902,
val_loss: 7.045370555715635
================================================================================
Best val acc: 97.78761061946902

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,下面是一个简单的例子: ```python import torch.nn as nn import torch.utils.model_zoo as model_zoo __all__ = ['ResNet', 'resnet18'] model_urls = { 'resnet18': 'https://download.pytorch.org/models/resnet18-5c106cde.pth', } def conv3x3(in_planes, out_planes, stride=1): """3x3 convolution with padding""" return nn.Conv2d(in_planes, out_planes, kernel_size=3, stride=stride, padding=1, bias=False) class BasicBlock(nn.Module): expansion = 1 def __init__(self, inplanes, planes, stride=1, downsample=None): super(BasicBlock, self).__init__() self.conv1 = conv3x3(inplanes, planes, stride) self.bn1 = nn.BatchNorm2d(planes) self.relu = nn.ReLU(inplace=True) self.conv2 = conv3x3(planes, planes) self.bn2 = nn.BatchNorm2d(planes) self.downsample = downsample self.stride = stride def forward(self, x): residual = x 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: residual = self.downsample(x) out += residual out = self.relu(out) return out class ResNet(nn.Module): def __init__(self, block, layers, num_classes=1000): self.inplanes = 64 super(ResNet, self).__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) self.layer1 = self._make_layer(block, 64, layers[0]) self.layer2 = self._make_layer(block, 128, layers[1], stride=2) self.layer3 = self._make_layer(block, 256, layers[2], stride=2) self.layer4 = self._make_layer(block, 512, layers[3], stride=2) self.avgpool = nn.AdaptiveAvgPool2d((1, 1)) self.fc = nn.Linear(512 * block.expansion, num_classes) def _make_layer(self, block, planes, blocks, stride=1): downsample = None if stride != 1 or self.inplanes != planes * block.expansion: downsample = nn.Sequential( nn.Conv2d(self.inplanes, planes * block.expansion, kernel_size=1, stride=stride, bias=False), nn.BatchNorm2d(planes * block.expansion), ) layers = [] layers.append(block(self.inplanes, planes, stride, downsample)) self.inplanes = planes * block.expansion for i in range(1, blocks): layers.append(block(self.inplanes, planes)) 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 = x.view(x.size(0), -1) x = self.fc(x) return x def resnet18(pretrained=False, **kwargs): """Constructs a ResNet-18 model. Args: pretrained (bool): If True, returns a model pre-trained on ImageNet """ model = ResNet(BasicBlock, [2, 2, 2, 2], **kwargs) if pretrained: model.load_state_dict(model_zoo.load_url(model_urls['resnet18'])) return model ``` 这是一个标准的 ResNet18 的 PyTorch 实现,其中包括了 `BasicBlock` 和 `ResNet` 两个类,以及 `resnet18` 函数,用于构建 ResNet18 模型。你可以在 `ResNet` 类中自定义层数和其他参数,如 `num_classes`(分类数目)等。在 `resnet18` 函数中,你可以通过设置 `pretrained=True` 来加载预训练权重。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱挠静香的下巴

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值