1 深度学习框架介绍
一般而言,pytorch适合初学者上手深度学习,本课程中也是使用pytorch作为框架进行学习。
- PyTorch是一个Python的深度学习库。它最初由Facebook人工智能研 究小组开发,而优步的Pyro软件则用于概率编程。
- 最初,PyTorch由Hugh Perkins开发,作为基于Torch框架的LusJIT的 Python包装器。PyTorch在Python中重新设计和实现Torch,同时为 后端代码共享相同的核心C库。
- 除了Facebook之外,Twitter、GMU和Salesforce等机构都采用了 PyTorch。
- 到目前,据统计已有80%的研究采用PyTorch,包括Google
下面为一段pytorch代码编写的Unet网络结构程序。
import torch
from torch import nn
from torch.nn import functional as F
class Conv_Block(nn.Module):
def __init__(self,in_channel,out_channel):
super(Conv_Block, self).__init__()
self.layer=nn.Sequential(
nn.Conv2d(in_channel,out_channel,3,1,1,padding_mode='reflect',bias=False),
nn.BatchNorm2d(out_channel),
nn.Dropout2d(0.3),
nn.LeakyReLU(),
nn.Conv2d(out_channel, out_channel, 3, 1, 1, padding_mode='reflect', bias=False),
nn.BatchNorm2d(out_channel),
nn.Dropout2d(0.3),
nn.LeakyReLU()
)
def forward(self,x):
return self.layer(x)
class DownSample(nn.Module):
def __init__(self,channel):
super(DownSample, self).__init__()
self.layer=nn.Sequential(
nn.Conv2d(channel,channel,3,2,1,padding_mode='reflect',bias=False),
nn.BatchNorm2d(channel),
nn.LeakyReLU()
)
def forward(self,x):
return self.layer(x)
class UpSample(nn.Module):
def __init__(self,channel):
super(UpSample, self).__init__()
self.layer=nn.Conv2d(channel,channel//2,1,1)
def forward(self,x,feature_map):
up=F.interpolate(x,scale_factor=2,mode='nearest')
out=self.layer(up)
return torch.cat((out,feature_map),dim=1)
class UNet(nn.Module):
def __init__(self):
super(UNet, self).__init__()
self.c1=Conv_Block(3,64)
self.d1=DownSample(64)
self.c2=Conv_Block(64,128)
self.d2=DownSample(128)
self.c3=Conv_Block(128,256)
self.d3=DownSample(256)
self.c4=Conv_Block(256,512)
self.d4=DownSample(512)
self.c5=Conv_Block(512,1024)
self.u1=UpSample(1024)
self.c6=Conv_Block(1024,512)
self.u2 = UpSample(512)
self.c7 = Conv_Block(512, 256)
self.u3 = UpSample(256)
self.c8 = Conv_Block(256, 128)
self.u4 = UpSample(128)
self.c9 = Conv_Block(128, 64)
self.out=nn.Conv2d(64,98,3,1,1)
self.Th=nn.Sigmoid()
def forward(self,x):
R1=self.c1(x)
R2=self.c2(self.d1(R1))
R3 = self.c3(self.d2(R2))
R4 = self.c4(self.d3(R3))
R5 = self.c5(self.d4(R4))
O1=self.c6(self.u1(R5,R4))
O2 = self.c7(self.u2(O1, R3))
O3 = self.c8(self.u3(O2, R2))
O4 = self.c9(self.u4(O3, R1))
return self.Th(self.out(O4))
可以看出,pytorch代码可以较为简介同时也能分模块地编写深度学习网络结构,同时其前向传播阶段也较为清晰。
2 卷积神经网络
2.1 卷积的基本概念
数字图像是一个二维的离散信号,对数字图像做卷积操作其实就是利用卷积核(卷积模板)在图像上滑动,将图像点上的像素灰度值与对应的卷积核上的数值相乘,然后将所有相乘后的值相加作为卷积核中间像素对应的图像上像素的灰度值,并最终滑动完所有图像的过程。
在这样的一个过程中我们可以提取到图像的各个维度上的特征,比如使用Laplace卷积核可以获得图像的锐化后特征,而使用高斯卷积核可以获得图像模糊后的特征。
2.2 为什么要使用卷积神经网络?
在处理图片(大型数组)时,MLP存在严重的参数爆炸:如果我们选则全连接层,假设我们输入1200万像素的图片,选则Batch_Size为8,第一个隐藏层神经元数量为128,综合上面条件,我们需要计算第一层w的数量可以达到10亿以上!
所以采用卷积神经网络可以通过计算卷积核内的参数有效地降低参数维度。而在卷积神经网络的实现过程中还需要用上两个基础操作,也就是填充(Padding)、步长(Stride)和池化(Pooling)。
2.3 一个简单的卷积神经网络-Lenet
其基本结构如上图,每个卷积块中的基本单元是一个卷积层、一个sigmoid激活函数和平均汇聚层。请注意,虽然ReLU和最大汇聚层更有效,但它们在20世纪90年代还没有出现。每个卷积层使用5×5卷积核和一个sigmoid激活函数。这些层将输入映射到多个二维特征输出,通常同时增加通道的数量。第一卷积层有6个输出通道,而第二个卷积层有16个输出通道。每个2×2池操作(步幅2)通过空间下采样将维数减少4倍。卷积的输出形状由批量大小、通道数、高度、宽度决定。
由于网络结构较为简单,其代码也较好实现。
import torch
from torch import nn
from d2l import torch as d2l
net = nn.Sequential(
nn.Conv2d(1, 6, kernel_size=5, padding=2), nn.Sigmoid(),
nn.AvgPool2d(kernel_size=2, stride=2),
nn.Conv2d(6, 16, kernel_size=5), nn.Sigmoid(),
nn.AvgPool2d(kernel_size=2, stride=2),
nn.Flatten(),
nn.Linear(16 * 5 * 5, 120), nn.Sigmoid(),
nn.Linear(120, 84), nn.Sigmoid(),
nn.Linear(84, 10))
最终得到网络结构图
至此就可以实现一副28*28的灰度数字图像到0-9这十类之间的一个映射关系,最终达到分类效果。