深度学习——卷积层代码【笔记】

本文介绍了如何使用PyTorch实现二维卷积运算,并通过实例演示了卷积核如何检测图像边缘。随后,通过学习卷积层参数来适应性地检测颜色变化,同时探讨了填充、步幅在卷积过程中的作用。

1.导入包

import torch
from torch import nn
from d2l import torch as d2l

2.卷积层的相关运算:跟着沐神手写二维交叉运算。我承认我是一个打字员


def corr2d(X, K):
    '''计算二维互相关运算'''
    kh, kw = K.shape  # 把卷积核的高和宽赋值给kh=K.shape[0],kw=K.shape[1]
    xh, xw = X.shape  # 把输入X的高和宽赋值给xh,xw
    Y = torch.zeros((xh - kh + 1, xw - kw + 1))  # 定义输出Y的矩阵大小
    for i in range(Y.shape[0]):  # 获取Y矩阵的 高
        for j in range(Y.shape[1]):  # 获取Y矩阵的 宽
            Y[i, j] = (X[i:i + kh, j:j + kw] * K).sum()  # i + kh就是矩阵适应卷积核的大小
# a * b 这个*就是卷积运算
    return Y

3.写完之后我们验证一下:

看看输出是不是Output 

X = torch.tensor([[0, 1, 2], [3, 4, 5], [6, 7, 8]])
K = torch.tensor([[0, 1], [2, 3]])
print(corr2d(X, K))

输出结果:

tensor([[19., 25.],
        [37., 43.]])

4.实现二维卷积层:y=wx+b。w是卷积核自动生成,b是偏置

class Conv2D(nn.Module):
    def __init__(self, kernel_size):
        super(Conv2D, self).__init__()
        self.weight = nn.Parameter(torch.rand(kernel_size))  # 均匀分布权重w
        self.bias = nn.Parameter(torch.zeros(1))  # 偏置b

    def forward(self, x):
        return corr2d(x, self.weight) + self.bias

5.写好之后我们进行一个简单的应用,检测图像中不同颜色的边缘  1代表黑色 0是白色

X = torch.ones((6, 8))
X[:, 2:6] = 0
'''
tensor([[1., 1., 0., 0., 0., 0., 1., 1.],
        [1., 1., 0., 0., 0., 0., 1., 1.],
        [1., 1., 0., 0., 0., 0., 1., 1.],
        [1., 1., 0., 0., 0., 0., 1., 1.],
        [1., 1., 0., 0., 0., 0., 1., 1.],
        [1., 1., 0., 0., 0., 0., 1., 1.]])
'''

设置卷积核,如果颜色一样 输出是 0 如果不一样输出非0

K = torch.tensor([[1.0, -1.0]])  # 如果颜色一样 输出是 0 如果不一样输出非0
Y = corr2d(X, K)
Y
'''
tensor([[ 0.,  1.,  0.,  0.,  0., -1.,  0.],
        [ 0.,  1.,  0.,  0.,  0., -1.,  0.],
        [ 0.,  1.,  0.,  0.,  0., -1.,  0.],
        [ 0.,  1.,  0.,  0.,  0., -1.,  0.],
        [ 0.,  1.,  0.,  0.,  0., -1.,  0.],
        [ 0.,  1.,  0.,  0.,  0., -1.,  0.]])
        
1代表 从白到黑
-1代表 从黑到白
'''

但是 此刻的卷积核只能检测垂直的边缘,如果给图像转置后,横向检测后就检测不出来

corr2d(X.t(), K)
'''
tensor([[0., 0., 0., 0., 0.],
        [0., 0., 0., 0., 0.],
        [0., 0., 0., 0., 0.],
        [0., 0., 0., 0., 0.],
        [0., 0., 0., 0., 0.],
        [0., 0., 0., 0., 0.],
        [0., 0., 0., 0., 0.],
        [0., 0., 0., 0., 0.]])

全是0 代表颜色不变化,错误
'''


所以,卷积核要学习。下面用到的是Conv2d系统提供的不是上面写的哪个。

①卷积层的有关设置,输入通道是1,因为是矩阵(黑白图像。彩色是3).输出也是1。卷积核的大小是1*2.

conv2d = nn.Conv2d(1, 1, kernel_size=(1, 2), bias=False)  # in_channels输入通道是1,矩阵

②给输入X和真实值Y reshape

通道数是1,样本数是1.大小是6*8

X = X.reshape((1, 1, 6, 8))  # 通道数1,样本维1, 输入X大小6*8
Y = Y.reshape((1, 1, 6, 7))

③进行训练

for i in range(38):
    Y_hat = conv2d(X)  # 预测值
    l = (Y_hat - Y) ** 2  # loss
    conv2d.zero_grad()  # 梯度为0
    l.sum().backward()  # 标量才能反向传播,所以l.sum()
    conv2d.weight.data[:] -= 3e-2 * conv2d.weight.grad  # 梯度下降
    if (i + 1) % 2 == 0:
        print(f'batch{i + 1},loss{l.sum():.3f}')

# 得到的卷积核K
print(conv2d.weight.data.reshape((1,2)))

得到学习的卷积核:tensor([[ 1.0000, -1.0000]])


二 填充和步幅

①获取填充后的输出 从序号2开始

import torch
from torch import nn


# 填充和步幅 
def comp_conv2d(conv2d, X):
    X = X.reshape((1, 1) + X.shape)  # 通道数1,样本维1, 输入X维度大小
    Y = conv2d(X)  # 调用conv2d函数
    return Y.reshape(Y.shape[2:])  # Y是4D,从序号2开始取

②padding=1,四周填充1行 8=8-3+1+1*2

conv2d = nn.Conv2d(1, 1, kernel_size=3, padding=1)  # 左右都填充一行 8-3+1+  2
X = torch.rand(size=(8, 8))
print(comp_conv2d(conv2d, X).shape)  # 输出torch.Size([8, 8])

③填充不同的高度padding=(2, 1)

# 填充不同的高度
conv2d = nn.Conv2d(1, 1, kernel_size=3, padding=(2, 1))  # 左右都填充一行 h:8-3+1+2*2   w 8-3+1+1*2 = 8
X = torch.rand(size=(8, 8))
print(comp_conv2d(conv2d, X).shape)  # torch.Size([10, 8])

2.①padding=1, stride=2步幅为2,填充1的输出大小的计算 输入的维度整除步长 8/2=4

8-3+1+2/2

conv2d = nn.Conv2d(1, 1, kernel_size=3, padding=1, stride=2)
print(comp_conv2d(conv2d, X).shape)  # torch.Size([4, 4])

②复杂:(8-3+0+3)/3=2     ( 8-5+1+4)/4=2

conv2d = nn.Conv2d(1, 1, kernel_size=(3, 5), padding=(0, 1), stride=(3, 4))
print(comp_conv2d(conv2d,X).shape)  # torch.Size([2, 2])  (8-3+0+3)/3  (8-5+1*2+4)/4

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值