pytorch中resnet_通过Pytorch实现ResNet18

pytorch中resnet_通过Pytorch实现ResNet18对于像我这样刚刚入门深度学习的同学来说,可能接触学习了一个开发工具,却没有通过运用来熟练的掌握它。而ResNet是深度学习里面一个非常重要的backbone,并且ResNet18实现起来又足够简单,所以非常适合拿来练手。我们这里的开发环境是:python3.6.10pytorch1.5.0torchvision0.6.0cudatoolkit10.2.89cudnn7.6.5首先,我们需…

大家好,又见面了,我是你们的朋友全栈君。

对于像我这样刚刚入门深度学习的同学来说,可能接触学习了一个开发工具,却没有通过运用来熟练的掌握它。而ResNet是深度学习里面一个非常重要的backbone,并且ResNet18实现起来又足够简单,所以非常适合拿来练手。

我们这里的开发环境是:

python 3.6.10

pytorch 1.5.0

torchvision 0.6.0

cudatoolkit 10.2.89

cudnn 7.6.5

首先,我们需要明确ResNet18的网络结构。在我自己学习的一开始,我对于ResNet的ShortCut机制的实现不是很清楚,当你知道怎么实现这个机制之后,那么剩下的部分也就没有什么挑战了。

论文中,ResNet各种层数的结构如下:pytorch中resnet_通过Pytorch实现ResNet18

我们观察,实际可以将ResNet18分成6个部分:

1. Conv1:也就是第一层卷积,没有shortcut机制。

2. Conv2:第一个残差块,一共有2个。

3. Conv3:第二个残差块,一共有2个。

4. Conv4:第三个残差块,一共有2个。

5. Conv5:第四个残差块,一共有2个。

6. fc:全连阶层。pytorch中resnet_通过Pytorch实现ResNet18

明确这些部分之后,我们就可以开始着手实现啦!

首先,咱们实现残差块:

import torch

import torch.nn as nn

import torch.nn.functionl as F

#定义残差块ResBlock

class ResBlock(nn.Module):

def __init__(self, inchannel, outchannel, stride=1):

super(ResBlock, self).__init__()

#这里定义了残差块内连续的2个卷积层

self.left = nn.Sequential(

nn.Conv2d(inchannel, outchannel, kernel_size=3, stride=stride, padding=1, bias=False),

nn.BatchNorm2d(outchannel),

nn.ReLU(inplace=True),

nn.Conv2d(outchannel, outchannel, kernel_size=3, stride=1, padding=1, bias=False),

nn.BatchNorm2d(outchannel)

)

self.shortcut = nn.Sequential()

if stride != 1 or inchannel != outchannel:

#shortcut,这里为了跟2个卷积层的结果结构一致,要做处理

self.shortcut = nn.Sequential(

nn.Conv2d(inchannel, outchannel, kernel_size=1, stride=stride, bias=False),

nn.BatchNorm2d(outchannel)

)

def forward(self, x):

out = self.left(x)

#将2个卷积层的输出跟处理过的x相加,实现ResNet的基本结构

out = out + self.shortcut(x)

out = F.relu(out)

return out

接着,我们实现ResNet18模型:

class ResNet(nn.Module):

def __init__(self, ResBlock, num_classes=10):

super(ResNet, self).__init__()

self.inchannel = 64

self.conv1 = nn.Sequential(

nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1, bias=False),

nn.BatchNorm2d(64),

nn.ReLU()

)

self.layer1 = self.make_layer(ResBlock, 64, 2, stride=1)

self.layer2 = self.make_layer(ResBlock, 128, 2, stride=2)

self.layer3 = self.make_layer(ResBlock, 256, 2, stride=2)

self.layer4 = self.make_layer(ResBlock, 512, 2, stride=2)

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

#这个函数主要是用来,重复同一个残差块

def make_layer(self, block, channels, num_blocks, stride):

strides = [stride] + [1] * (num_blocks – 1)

layers = []

for stride in strides:

layers.append(block(self.inchannel, channels, stride))

self.inchannel = channels

return nn.Sequential(*layers)

def forward(self, x):

#在这里,整个ResNet18的结构就很清晰了

out = self.conv1(x)

out = self.layer1(out)

out = self.layer2(out)

out = self.layer3(out)

out = self.layer4(out)

out = F.avg_pool2d(out, 4)

out = out.view(out.size(0), -1)

out = self.fc(out)

return out

到此,一个ResNet18网络就搭建完成了,不过,仅仅是搭建完成还是远远不够的,让我们拿它来练练手。笔者在jupyter notebook上使用CIFAR10数据集来测试我们的ResNet18模。

from resnet import ResNet18

#Use the ResNet18 on Cifar-10

import torch.optim as optim

import torchvision

import torchvision.transforms as transforms

#check gpu

device = torch.device(“cuda” if torch.cuda.is_available() else “cpu”)

#set hyperparameter

EPOCH = 10

pre_epoch = 0

BATCH_SIZE = 128

LR = 0.01

#prepare dataset and preprocessing

transform_train = transforms.Compose([

transforms.RandomCrop(32, padding=4),

transforms.RandomHorizontalFlip(),

transforms.ToTensor(),

transforms.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010))

])

transform_test = transforms.Compose([

transforms.ToTensor(),

transforms.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010))

])

trainset = torchvision.datasets.CIFAR10(root=’../data’, train=True, download=True, transform=transform_train)

trainloader = torch.utils.data.DataLoader(trainset, batch_size=BATCH_SIZE, shuffle=True, num_workers=2)

testset = torchvision.datasets.CIFAR10(root=’../data’, train=False, download=True, transform=transform_test)

testloader = torch.utils.data.DataLoader(testset, batch_size=100, shuffle=False, num_workers=2)

#labels in CIFAR10

classes = (‘plane’, ‘car’, ‘bird’, ‘cat’, ‘deer’, ‘dog’, ‘frog’, ‘horse’, ‘ship’, ‘truck’)

#define ResNet18

net = ResNet18().to(device)

#define loss funtion & optimizer

criterion = nn.CrossEntropyLoss()

optimizer = optim.SGD(net.parameters(), lr=LR, momentum=0.9, weight_decay=5e-4)

然后开始跑模型:

#train

for epoch in range(pre_epoch, EPOCH):

print(‘\nEpoch:%d’ % (epoch + 1))

net.train()

sum_loss = 0.0

correct = 0.0

total = 0.0

for i, data in enumerate(trainloader, 0):

#prepare dataset

length = len(trainloader)

inputs, labels = data

inputs, labels = inputs.to(device), labels.to(device)

optimizer.zero_grad()

#forward & backward

outputs = net(inputs)

loss = criterion(outputs, labels)

loss.backward()

optimizer.step()

#print ac & loss in each batch

sum_loss += loss.item()

_, predicted = torch.max(outputs.data, 1)

total += labels.size(0)

correct += predicted.eq(labels.data).cpu().sum()

print(‘[epoch:%d, iter:%d] Loss:%.03f| Acc:%.3f%%’

% (epoch + 1, (i + 1 + epoch * length), sum_loss / (i + 1), 100. * correct / total))

#get the ac with testdataset in each epoch

print(‘Waiting Test…’)

with torch.no_grad():

correct = 0

total = 0

for data in testloader:

net.eval()

images, labels = data

images, labels = images.to(device), labels.to(device)

outputs = net(images)

_, predicted = torch.max(outputs.data, 1)

total += labels.size(0)

correct += (predicted == labels).sum()

print(‘Test\’s ac is:%.3f%%’ % (100 * correct / total))

print(‘Train has finished, total epoch is%d’ % EPOCH)

如果不出意外,这个模型就已经跑起来了,到这里,咱们就已经完成的实现了一个ResNet18网络,这个模型的jupyter notebook源码我已经放到了github上,如果这片文章对你有帮助,那就给我star一下吧:samcw/ResNet18-Pytorch​github.compytorch中resnet_通过Pytorch实现ResNet18

参考:

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/141371.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • acwing-371. 牧师约翰最忙碌的一天(2-SAT)「建议收藏」

    acwing-371. 牧师约翰最忙碌的一天(2-SAT)「建议收藏」牧师约翰在 9 月 1 日这天非常的忙碌。有 N 对情侣在这天准备结婚,每对情侣都预先计划好了婚礼举办的时间,其中第 i 对情侣的婚礼从时刻 Si 开始,到时刻 Ti 结束。婚礼有一个必须的仪式:站在牧师面前聆听上帝的祝福。这个仪式要么在婚礼开始时举行,要么在结束时举行。第 i 对情侣需要 Di 分钟完成这个仪式,即必须选择 Si∼Si+Di 或 Ti−Di∼Ti 两个时间段之一。牧师想知道他能否满足每场婚礼的要求,即给每对情侣安排Si∼Si+Di 或 Ti−Di∼Ti,使得这些仪式的时

    2022年8月9日
    1
  • 服务器的文件不能修改器,荒野行动gg修改器脚本安装文件运行出错「建议收藏」

    服务器的文件不能修改器,荒野行动gg修改器脚本安装文件运行出错「建议收藏」PrivateDeclareFunctionCreateDirectoryLib”kernel32″Alias”CreateDirectoryA”(ByVallpPathNameAsString,lpSecurityAttributesAsSECURITY_ATTRIBUTES)AsLongPrivateTypeSECURITY_ATTRIBUTESnLengthAsLonglpSecurityD…

    2022年9月5日
    4
  • navicat mac激活码【2021.7最新】

    (navicat mac激活码)2021最新分享一个能用的的激活码出来,希望能帮到需要激活的朋友。目前这个是能用的,但是用的人多了之后也会失效,会不定时更新的,大家持续关注此网站~IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.net/100143.html…

    2022年3月22日
    59
  • 2012年计算机工作总结,计算机教师工作总结2011-2012

    2012年计算机工作总结,计算机教师工作总结2011-2012计算机教师工作总结2011-20122010-2011第一学期计算机教学工作总结郑龙勤本学期,我任教24,25,26,27班的计算机应用基础教学,同时兼任学校的中职资助、机房维护等工作。在各位领导和老师的热心支持和帮助下,我认真做好教学工作,积极完成学校布置的各项任务。下面我把2010-2011年第一学期的工作做简要的汇报。一、学校制度执行情况平时积极参加全校教职工会议,认真学习学校下达的文件,关…

    2022年5月12日
    33
  • ssh脚本自动登录怎么回事_自动注册账号app脚本

    ssh脚本自动登录怎么回事_自动注册账号app脚本ssh脚本登录1.什么是ssh指纹使用/etc/ssh/ssh_host_rsa_key.pub公钥加密生成的字符串,用来校验或验证连接的远程主机2.如何使用脚本登录ssh方案1:使用expectspawnsshroot@172.16.16.7-p36000expect”*Areyousureyouwanttocontinueconnecting(ye…

    2022年10月31日
    0
  • Android进阶-第三方框架使用汇总「建议收藏」

    Android进阶-第三方框架使用汇总「建议收藏」imageloading框架:1.1Glide1.1Glide:一、Glide-GettingStartedGlide:Glide就像Picasso,能从许多资源上加载和显示图片,也照顾了缓存和做图片操作的时候保持一个低的内存影响,它已经被官方谷歌应用程序(如GoogleI/O的应用程序2015)和Picasso一样受欢迎,在本系列中,我们将探索Glide在Picas

    2022年5月11日
    36

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号