动手学PyTorch(李沐)11 ---- 卷积层

卷积层

平移不变性和局部性

W 是学习来的一个东西,所以正反顺序并无太大关系。

​

核矩阵的大小就是局部性,核矩阵大一点就是遍历的范围大一点。

卷积核大、网络层数可能不如卷积核小,网络深的效果好

抖动厉害的可能是数据多样性比较大,或者是批量大小过小,抖动对实验没有影响,关键在于模型效果要越来越好。 解决抖动问题可以调高学习率或者批量变大


填充和步幅(超参)

每一次卷积计算得到的特征图维度都会小于原来的图像。解决这个问题的方法就是填充原图像

填充方法:

填充一行,特征图就增加一行,填充一列,特征图就增加一列。

通常填充核的大小减一的值,这样做使得特征图不会变小。

这里是需要55层

总结:

QA:

  1. 填充通常使得输入和输出的大小不变,通常设为核大小减1的情况。通常来说步幅为1比较好,单如果计算量过大则可以调大步幅。
  2. 卷积核的尺度一般选奇数,便于填充。
  3. 卷积核比较小的情况下,需要使用一个深的神经网络来观察到更多的信息。
  4. 使用网格搜索可以找到更合适的超参。
  5. autoglun可以实现自动调参。
  6. 同等维度变化下,卷积核越大的代价越大。

实现

互相关运算

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

def corr2d(X,K):
  """二维互相关,输入矩阵X, 核矩阵K"""
  h,w = K.shape
  Y = torch.zeros((X.shape[0] - h + 1,X.shape[1] - w + 1))
  for i in range(Y.shape[0]):
    for j in range(Y.shape[1]):
      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)

实现卷积层

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

卷积层的一个简单应用,检测图像中不同颜色的边缘

x = torch.ones((6,8))
x[:,2:6] = 0
x

在这里插入图片描述

k = torch.tensor([[1.0,-1.0]])

1代表白变黑,-1代表黑变白

y = corr2d(x,k)
y

在这里插入图片描述
卷积核k只能检测垂直边缘

corr2d(x.t(),k)

在这里插入图片描述
学习有x生成y的卷积核

# 黑白图片输入通道为1,彩色图片输入通道为3,第一个参数是输出通道,第二个参数是输入通道,kernel_size是1*2大小
conv2d = nn.Conv2d(1,1,kernel_size=(1,2),bias=False)
x = x.reshape((1,1,6,8))
y = y.reshape((1,1,6,7))

for i in range(10):
  y_hat = conv2d(x)
  # 均方误差
  l = (y_hat - y)**2
  # 梯度置0
  conv2d.zero_grad()
  # 反向传播计算梯度
  l.sum().backward()
  conv2d.weight.data[:] -= 3e-2*conv2d.weight.grad
  if (i+1) % 2 == 0:
    print(f'bath{i+1},loss {l.sum():.3f}')

在这里插入图片描述
所学卷积核的权重张量

conv2d.weight.data.reshape((1,2))

在这里插入图片描述

填充与步幅

在所有侧边填充1各像素

import torch
from torch import nn

def comp_conv2d(conv2d,X):
  # 在输入维度前面添加一个通道数和批量大小数,这里是将X提升到四维(1,1,8,8)
  X = X.reshape((1,1)+ X.shape)
  Y = conv2d(X)
  # Y是四维,返回的时候去掉前面两维看起来更直观
  return Y.reshape(Y.shape[2:])
# padding 上下左右各填充一行
conv2d = nn.Conv2d(1,1,kernel_size = 3,padding = 1)
X = torch.rand(size=(8,8))
comp_conv2d(conv2d,X).shape

在这里插入图片描述
填充不同的高度和宽度

# 上下填充两行,左右填充一列
conv2d = nn.Conv2d(1,1,kernel_size = (5,3),padding = (2,1))
comp_conv2d(conv2d,X).shape

在这里插入图片描述

conv2d = nn.Conv2d(1,1,kernel_size=(7,5),padding=(3,2))
comp_conv2d(conv2d,X).shape

在这里插入图片描述
设置高度和宽度的步幅为2

# 上下左右填充1,步幅为2
conv2d = nn.Conv2d(1,1,kernel_size=3,padding=1,stride=2)
comp_conv2d(conv2d,X).shape

在这里插入图片描述

conv2d = nn.Conv2d(1,1,kernel_size = (3,5),padding=(0,1),stride=(3,4))
comp_conv2d(conv2d,X).shape
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值