深度学习:PyTorch卷积层入门与实战

释放双眼,带上耳机,听听看~!
本文介绍了卷积神经网络中的卷积层实现,包括卷积运算和边缘检测。通过PyTorch进行实际项目实战,帮助读者深入理解深度学习中的卷积神经网络。

本文已参与「新人创作礼」活动,一起开启掘金创作之路

【深度学习】:《PyTorch入门到项目实战》(十一):卷积层

深度学习:PyTorch卷积层入门与实战

卷积神经网络(CNN):卷积层实现

之前已经介绍了基本的神经网络知识以及一些处理过拟合欠拟合的概念。现在我们正式进入卷积神经网络的学习。CNN是⼀类强⼤的、为处理图像数据⽽设计的神经⽹络。基于卷积神经⽹络架构的模型在计算机视觉领域中已经占主导地位,当今⼏乎所有的图像识别、⽬标检测或语义分割相关的学术竞赛和商业应⽤都以这种⽅法为基础。对于计算机视觉而言,面临的一个重大挑战就是数据的输入可能会很大。例如,我们有一张64×times 64的图片,假设通道数为3,那么它是数据量相当于是一个64×64×3=1228864times 64times 3=12288的特征向量。当我们要操作更大的图片时候,需要进行卷积计算,它是卷积神经网络中非常重要的一部分。

1.引入

让我们举个例子,假设给了我们这样一张图片
深度学习:PyTorch卷积层入门与实战

让电脑去搞清楚这张照片里有什么物体,我们可能做的第一件事是检测图片中的垂直边缘。比如说,在这张图片中的栏杆就对应垂直线,与此同时,这些行人的轮廓线某种程度上也是垂线,这些线是垂直边缘检测器的输出。同样,我们可能也想检测水平边缘,比如说这些栏杆就是很明显的水平线,所以如何在图像中检测这些边缘?
我们可以构建一个3×33times3的矩阵,我们也称为过滤器或者核函数(kernel)。下面我们通过Andrew Ng的解释来看看为什么这个能做边缘检测?

深度学习:PyTorch卷积层入门与实战

上图一个简单的6×6图像,左边的一半是10,右边一般是0。如果你把它当成一个图片,左边那部分看起来是白色的,像素值10是比较亮的像素值,右边像素值比较暗,我使用灰色来表示0,尽管它也可以被画成黑的。图片里,有一个特别明显的垂直边缘在图像中间,这条垂直线是从黑到白的过渡线,或者从白色到深色。所以,当我们用一个3×3过滤器进行卷积运算的时候,这个3×3的过滤器结果,在左边有明亮的像素,然后有一个过渡,0在中间,然后右边是深色的。卷积运算后,我们得到的是右边的矩阵。还有许多其他的边缘检测方法,关于具体的计算机视觉任务,我们在后续介绍,接下来我们来看看卷积具体是怎么计算的

2.卷积运算

下面我们来看看卷积具体是怎么计算的,给一个输入矩阵和一个核函数,我们将从输入特征的左上角开始与核函数求内积,然后在进行滑动窗口,求下一个内积。得到我们的输出,具体计算如下

0×0+1×1+3×2+4×3=191×0+1×2+4×2+3×5=253×0+4×1+6×2+7×3=374×0+1×5+2×7+3×8=430times0+1times1+3times2+4times3 = 19\
1times0+1times2+4times2+3times5 = 25\
3times0+4times1+6times2+7times3 = 37\
4times0+1times5+2times7+3times8 = 43

深度学习:PyTorch卷积层入门与实战

可以看出,通过卷积计算后,我们的原始数据特征变小了。假设输入矩阵为n×nntimes n,核函数(Kernel)为f×fftimes f,通常核是一个方阵形式。那么得到的输出结果为(n−f+1)×(n−f+1)(n-f+1)times (n-f+1)

3 代码实现

3.1下面我们来简单的实现卷积运算

"""导入相关库"""
import torch
from torch import nn
def corr2d(X,K):
    """定义卷积运算"""
    h, w = K.shape#核的shape,通常这里的h和w是相等的
    Y = torch.zeros((X.shape[0]-h+1, X.shape[1]-w+1))#初始化输出结果
    for i in range(Y.shape[0]):#输出矩阵的第i行
        for j in range(Y.shape[1]):#输出矩阵的第j列
            Y[i,j] = (X[i:i+h,j:j+w] * K).sum()#计算对应内积
    return Y 

下面我们来测试一下是否正确

X = torch.Tensor([[0.0,1.0,2.0],[3.0,4.0,5.0],[6.0,7.0,8.0]])
K = torch.Tensor([[0.0,1.0],[2.0,3.0]])
corr2d(X,K)

可以看出和我们之前的结果一致.

3.2 构造卷积层

之前我们介绍了如何构造线性层,激活函数,以及drop-out,类似的,我们通过定义一个类来定义卷积层

class Conv2D(nn.Module):
    """定义二维卷积层"""
    def __init__(self, kernel_size):#定义核函数的大小,这是一个超参数
        super().__init__()
        self.weight = nn.Parameter(torch.rand(Kernel_size))#学习的参数
        self.bias = nn.Parameter(torch.zeros(1))#学习的参数
    def forward(self, x):
        return corr2d(x,self.weight)+self.bias#计算卷积结果

3.3 检测图像颜色边缘

首先我们定义一个X,假设1代表灰色,0代表白色

X = torch.ones(6,6)
X[:,2:4] = (0.0)
X

下面我们进行边缘检测,在这里我们构造一个1×21times2的核函数

K = torch.tensor([[1.0,-1.0]])
K
Y = corr2d(X,K)
Y

其中,1表示从灰色到白色的垂直边缘,-1表示从白色到黑色的垂直边缘

上述定义的核只能检测垂直边缘,现在假设我们对X进行转置,我们想要检测水平边缘

Y = corr2d(X.t(),K)
Y

可以看见此时的核函数(Kernel)不能够检测水平边缘,我们需要对kernel也进行转置

Y = corr2d(X.t(),K.t())
Y

3.4 学习卷积核

刚刚是我们自己定义的卷积核,但是当如果我们需要进行更复杂的计算时,直接定义卷积核是很困难的,我们下面来看看能不能通过输入和输出矩阵来学习到我们的卷积核,这里我们定义损失函数为Y和卷积层输出的平方误差。

# 构造⼀个⼆维卷积层,它具有1个输出通道和形状为(2,2)的卷积核
conv2d = nn.Conv2d(1,1, kernel_size=(1, 2), bias=False)
# 这个⼆维卷积层使⽤四维输⼊和输出格式(批量⼤⼩、通道、⾼度、宽度),
# 其中批量⼤⼩和通道数都为1
X = X.reshape((1, 1, 6, 6))
Y = Y.reshape((1, 1, 6, 5))
lr = 3e-2 # 学习率
for i in range(10):
    Y_hat = conv2d(X)#计算卷积
    l = (Y_hat - Y) ** 2#损失函数
    conv2d.zero_grad()
    l.sum().backward()#反向传播计算梯度
    # 迭代卷积核
    conv2d.weight.data[:] -= lr * conv2d.weight.grad
    if (i + 1) % 2 == 0:
        print(f'epoch {i+1}, loss {l.sum():.3f}')

可以看出经过10次迭代后,误差已经较低了,我们下面看看学习到的卷积核参数

conv2d.weight

结果和我们之前定义的1,-1基本接近。
本章介绍了如何进行卷积计算以及定义卷积层,后续介绍padding、多维卷积、池化层等。
深度学习:PyTorch卷积层入门与实战
本章的介绍到此介绍,如果文章对你有帮助,请多多点赞、收藏、评论、关注支持!!

本网站的内容主要来自互联网上的各种资源,仅供参考和信息分享之用,不代表本网站拥有相关版权或知识产权。如您认为内容侵犯您的权益,请联系我们,我们将尽快采取行动,包括删除或更正。
AI教程

如何通过观测云优化OpenAI使用体验

2023-12-10 18:22:14

AI教程

FastGPT:构建专属知识库和AI客服助手的快速工具

2023-12-10 18:29:00

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索