首页 > 编程知识 正文

pytorch metal,pytorch gpu版本

时间:2023-05-05 08:20:43 阅读:126082 作者:2405

用Pytorch实现ResNet34网络用Pytorch实现ResNet网络

主要是为了学习Pytorch构建神经网络的基本方法,通过参考深度学习框架Pytorch:的入门和实践书籍,作者眯起了眼睛的音响

1.RESNET网络什么是RESNET(deepresidualnetwork )深度残差网络。 Kaiming He等人提出的一种新的卷积神经网络结构,其最重要的特征是网络大部分由如图1所示的残差单元组成,很多参数相同的残差单元连接在一起构成基本块,很多基本块

图一残差单元1.1 ResNet34网络具体结构的具体结构如下图所示。

图2 )2:ResNet34的具体结构是,除了第一个连接池和最后一个池完全连接之外,网络中有许多结构相似的单元,而这些重叠单元共有的是具有跨层直接连接的shortcut

不同层数的ResNet的配置列表:

1.2 ResNet34网络的原理和优点目前还不太清楚,需要补充。

2.Pytorch代码实现2.1实现代码importtorchastfromtorchimportnfromtorch.nnimportfunctionalasfclassresidualblock (nn.module ) 33666 shortcut=None ) :super(residualblock,self(_init__ ) self.left=bias=False ),nn.batch norm 2d (out charm outchanel,3,1,nn.batchnorm2d(outchanel ) ) self.right=shortcutdefforward ) self, x ) :out=self.left(x ) residual=xifself.rightisnoneelseself.right ) x ) out=residualreturnf.relu ) out ) out 包括yer,其中每个layer在多个residual block子模型中实现residual block并使用__make_layer__函数的num _ classes=1000 (: ' ) 2,3,bias=True ),nn.batchnorm2d(64 ),nn.relu ) inplace=true ),nn.max pool 2d (3,2,1 ) ) self.layer1 3 stride=2) self.layer3=self._ _ make _ layer 512,3,stride=2) self.fc=nn.linear(512,num_classes ) out多个residual block : paraminchannel 33603360 paramoutchannel 33603360 param block _ num : param stride 33603360 return 3:

nn.Conv2d(inchannel,outchannel,1,stride,bias=False), nn.BatchNorm2d(outchannel) ) layers = [] layers.append(ResidualBlock(inchannel,outchannel,stride,shortcut)) for i in range(1,block_num): layers.append(ResidualBlock(inchannel,outchannel)) return nn.Sequential(*layers) def forward(self, x): x = self.pre(x) x = self.layer1(x) x = self.layer2(x) x = self.layer3(x) x = self.layer4(x) x = F.avg_pool2d(x,7) x = x.view(x.size(0),-1) return self.fc(x) 2.2 整体思路

根据ResNet网络的特点,我们将模型分成两部分,主Model和子Model,子Model实现由多个残差单元组成的一个layer,主Model将最开始的卷积池化和最后的池化全连接以及中间的多个拥有不同参数的layer组合起来,形成ResNet网络。

2.3 代码分析 2.3.1 ResidualBlock 部分 class ResidualBlock(nn.Module): def __init__(self,inchanel,outchanel,stride=1,shortcut=None): super(ResidualBlock,self).__init__() self.left=nn.Sequential( nn.Conv2d(inchanel,outchanel,3,stride,1,bias=False), nn.BatchNorm2d(outchanel), nn.ReLU(inplace=True), nn.Conv2d(outchanel,outchanel,3,1,1,bias=False), nn.BatchNorm2d(outchanel) ) self.right=shortcut def forward(self, x): out=self.left(x) residual = x if self.right is None else self.right(x) out += residual return F.relu(out)

class ResidualBlock(nn.Module)
如果想要用Pytorch实现一个模型,必须要先继承nn.Module类,这样我们就可以不手动实现反向传播的过程,只需要实现初始化模型部分以及前向传播部分即可

__init__

该函数负责实现模型的初始化,模型中的各个参数,各神经层需要在该函数中设置

可以看到在该层中我们首先使用了一个super(ResidualBlock,self).__init__(),以此来调用nn.Module的构造函数,还有一种调用方式是nn.Module.__init__(self)

在构造函数中我们可以定义可学习参数或者子Module。如果是定义一个可学习参数,必须封装成Parameter,例如nn.Parameter(torch.randn(out._features))。Parameter是一种特殊的Variable ,但是是默认是需要求导的。

另外,在这里我们还使用了nn.Sequential以及其他的一些在nn包里面实现的Module

nn.Sequential
Sequential类似于一个列表,只不过列表里面的内容是一个一个的Module,假设我们定义了一个Sequential,对于这个Sequential传入一个input,Sequential会按内部模型定义的顺序处理这个input,最终返回一个output给我们

torch.nn.Conv2d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True, padding_mode='zeros')
实现了一个简单的二维卷积层,参数含义如下:

in_channels 输入的通道数out_channels 输出的通道数kernel_size 卷积核的大小stride 卷积核移动的步数padding 图像矩阵每个维度填充0的个数

nn.BatchNorm2d(num_features, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)

实现一个二维的批标准化
用来保证每一个隐藏层的激活输入都具有相同的分布,BN就是通过一定的规范化手段,把每层神经网络任意神经元这个输入值的分布强行拉回到均值为0方差为1的标准正态分布,解决梯度消失的问题
具体可以参考

num_features 定义了特征数 即(N,C,W,H)中的C

forward(self, x)
实现该模型前向传播的过程,最终返回结果值

2.3.2 ResNet部分 class ResNet34(nn.Module): """ 实现主module:ResNet34 ResNet34包含多个layer,每个layer又包含多个residual block 用子model实现residual block,用__make_layer__函数实现layer """ def __init__(self,num_classes=1000): """ 构建ResNet34网络的各层结构 :param num_classes: """ super(ResNet34,self).__init__() self.pre=nn.Sequential( nn.Conv2d(3,64,7,2,3,bias=True), nn.BatchNorm2d(64), nn.ReLU(inplace=True), nn.MaxPool2d(3,2,1) ) self.layer1 = self.__make_layer__(64,128,3) self.layer2 = self.__make_layer__(128,256,4,stride=2) self.layer3 = self.__make_layer__(256,512,6,stride=2) self.layer4 = self.__make_layer__(512,512,3,stride=2) self.fc = nn.Linear(512,num_classes) def __make_layer__(self,inchannel,outchannel,block_num,stride=1): """ 构建layer,包含多个residual block :param inchannel: :param outchannel: :param block_num: :param stride: :return: """ shortcut = nn.Sequential( nn.Conv2d(inchannel,outchannel,1,stride,bias=False), nn.BatchNorm2d(outchannel) ) layers = [] layers.append(ResidualBlock(inchannel,outchannel,stride,shortcut)) for i in range(1,block_num): layers.append(ResidualBlock(inchannel,outchannel)) return nn.Sequential(*layers) def forward(self, x): x = self.pre(x) x = self.layer1(x) x = self.layer2(x) x = self.layer3(x) x = self.layer4(x) x = F.avg_pool2d(x,7) x = x.view(x.size(0),-1) return self.fc(x)

实现了ResNet模型的主要部分,将许多ResidualBlock整合在一起,大部分地方的实现方法和ResidualBlock Module差不多
这里实现了一个__make_layer__方法用来拼接任意数量的具有相同参数的残差单元,返回layer

转载于:https://www.cnblogs.com/DLKKILL/p/10939904.html

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。