全连接层到卷积
全连接层的问题
假设输入为36M的特征维度,运算量将进入上亿级别的,需要巨大的运算力。
全连接层到卷积
由于输入和输出变为矩阵(宽度,高度),因此权重由二维张量变为4维张量
原则一 平移不变性
对于计算时,
对于
的取值无影响,所以
原则二 局部性
当评估时,不会用到远离
的参数
互相关运算
严格来说,卷积层是个错误的叫法,因为它所表达的运算其实是互相关运算(cross-correlation),而不是卷积运算。在卷积层中,输入张量和核张量通过互相关运算产生输出张量。
注意,输出大小略小于输入大小。这是因为我们需要足够的空间在图像上“移动”卷积核,所以卷积核只与图像中每个大小完全适合的位置进行互相关运算。 所以,输出大小等于
代码
互相关运算
import torch
from torch import nn
from d2l import torch as d2l
# 二维互相关运算
def corr2d(X,K):
"""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]):
# X[i:i+h,j:j+w]*K 两个矩阵进行运算
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))
# 偏差为0
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
# 在该卷积核的运算下,只有当两列数字发生变化时才会出现除0之外的数字
# 从而判断边缘
K = torch.tensor([[1.0, -1.0]])
Y = corr2d(X, K)
print(Y)
#对水平边缘的检测
corr2d(X.t(), K.T)
学习由X生成Y的卷积核
# 输入通道数 输出通道数 w b
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#均方误差作为loss
#反向传播前 梯度设成0
Conv2d.zero_grad()
#梯度下降
l.sum().backward()
#学习率=3e-2
Conv2d.weight.data -= 3e-2 * Conv2d.weight.grad
#每两次梯度下降后打印一次loss
if (i+1) % 2 ==0:
print(f"batch {i+1}, loss{l.sum():.3f}")
#查看学习后的卷积核
Conv2d.weight.data.reshape((1,2))