例子:图片分类猫和狗,使用传统全连接层处理图片数据需要的参数量超级大所以需要找别的方法。
图片分类两个原则:平移不变性(识别器不会因为像素位置而发生改变),局部性(不需要看到完整部分,只要看部分)
对全连接层使用平移不变性和局部性得到卷积层(交叉相关)。
卷积:1、卷积层将输入和核矩阵进行交叉相关,加上便宜后得到输出
2、核矩阵和偏移是可学习的参数
3、核矩阵的大小是超参数
如图例子所示,我们会根据想要的效果学习到相应的卷积核参数,所以卷积核可以用来提取特征。
图像卷积-互相关运算代码
import torch
from torch import nn
form d2l import torch as d2l
def corr2d(X,K):
h,w = X.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):
self.weight = nn.Parameter(torch.rand(kernel_size))
self.bias = nn.Parameter(torch.zero(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]])
Y = corr2d(X,K)
Y
corr2d(X.t(),K)#t()转置
梯度下降算法
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
conv2d.zero_grad()
l.sum().backward()
conv2d.weight.data[:]-=3e-2*conv2d.weight.grad
if (i+1)%2==0:
print(f'batch{i+1},loss {l.sum():.3f}')
conv2d.weight.data.reshape((1,2))