深度学习卷积层
分类猫和狗的图片
使用一个相机采集图片(12M像素), RGB图片有36M元素, 使用100大小的单隐藏层MLP, 模型有3.6B元素, 远多于世界上所有猫和狗总数(900M狗, 600M猫), 所以如果采用原始的MLP解决需要16亿的参数, 那么卷积神经网络提供了一个新的解决办法
两个原则
- 平移不变性: 不论分类是在那个地方看应当都是差不多的
- 局部性: 只需要观察一部分数据, 不需要观察全局的数据
全联接层到卷积层
将图片表示到矩阵
- 将输入和输出变形为矩阵(宽度, 高度), 因为需要保留图片信息
- 将权重变形为4-D张量(h, w), 到(h’, w’)
hi,j=∑k,lwi,j,k,lxk,l=∑a,bvi,j,a,bxi+a,j+b h_{i,j} = \sum_{k,l}w_{i,j,k,l}x_{k,l} = \sum_{a,b}v_{i,j,a,b}x_{i+a,j+b} hi,j=k,l∑wi,j,k,lxk,l=a,b∑vi,j,a,bxi+a,j+b
vvv是www的重新索引(排列)使得vi,j,a,b=wi,j,i+a,j+bv_{i,j,a,b}=w_{i,j,i+a,j+b}vi,j,a,b=wi,j,i+a,j+b
hi,jh_{i,j}hi,j是输出, xxx代表输入, www代表之前全联接层的权重(4维)
应用平移不变性
x的平移导致h的平移hi,j=∑a,bvi,j,a,bxi+a,j+bh_{i,j}=\sum_{a,b}v_{i,j,a,b}x_{i+a,j+b}hi,j=∑a,bvi,j,a,bxi+a,j+b
v不应该依赖(i, j)
解决方案: vi,j,a,b=va,bv_{i,j,a,b}=v_{a,b}vi,j,a,b=va,b
hi,j=∑a,bva,bxi+a,j+b
h_{i,j} = \sum_{a,b}v_{a,b}x_{i+a,j+b}
hi,j=a,b∑va,bxi+a,j+b
这就是二维的交叉相关
应用局部性
hi,j=∑a,bva,bxi+a,j+b
h_{i,j} = \sum_{a,b}v_{a,b}x_{i+a,j+b}
hi,j=a,b∑va,bxi+a,j+b
当评估hi,jh_{i,j}hi,j时, 我们不应该用远离xi,jx_{i,j}xi,j的参数, 解决方案, 当∣a∣,∣b∣>Δ|a|, |b| > \Delta∣a∣,∣b∣>Δ时, 使得va,b=0v_{a,b}=0va,b=0
hi,j=∑a=−ΔΔ∑b=−ΔΔva,bxi+a,j+b
h_{i,j}=\sum_{a=-\Delta}^{\Delta}\sum_{b=-\Delta}^{\Delta}v_{a,b}x_{i+a,j+b}
hi,j=a=−Δ∑Δb=−Δ∑Δva,bxi+a,j+b
卷积层
二维交叉相关

- Input: 输入
- Kernel: 卷积核, 核窗口
- Output: 输出
通过核窗口不断平移扫描输入的数据, 最终得到输出, 这就是二维交叉相关
二维卷积层

- 输入X:nh∗nwX: n_h * n_wX:nh∗nw, 高 * 宽的矩阵
- 核W:kn∗kwW: k_n * k_wW:kn∗kw
- 偏差b∈Rb \in \Rb∈R
- 输出Y:(nh−kn+1)∗(nw−kw+1)Y: (n_h - k_n + 1) * (n_w - k_w + 1)Y:(nh−kn+1)∗(nw−kw+1)
Y=X∗W+bY = X * W + bY=X∗W+b
WWW和bbb是可学习参数
不同卷积核
不同的卷积核所学习(提取)的特征是不同的

交叉相关和卷积
二维交叉相关
yi,j=∑a=1h∑b=1wwa,bxi+a,j+b
y_{i,j} = \sum_{a=1}^h\sum_{b=1^w}w_{a,b}x_{i+a,j+b}
yi,j=a=1∑hb=1w∑wa,bxi+a,j+b
二维卷积
yi,j=∑a=1h∑b=1ww−a,−bxi+a,j+b
y_{i,j}=\sum_{a=1}^h\sum_{b=1}^ww_{-a,-b}x_{i+a,j+b}
yi,j=a=1∑hb=1∑ww−a,−bxi+a,j+b
由于对称性, 在实际中没有区别, 卷积的区别在于w−a,−bw_{-a,-b}w−a,−b, 实际是反着(镜面)来的
一维和三维交叉相关
一维
yi=∑a=1hwaxi+a
y_i = \sum_{a=1}^hw_ax_{i+a}
yi=a=1∑hwaxi+a
文本, 语言, 时序序列
三维
yi,j,k=∑a=1h∑b=1w∑c=1dwa,b,cxi+a,j+b,k+c
y_{i,j,k} = \sum_{a=1}^h\sum_{b=1}^w\sum_{c=1}^dw_{a,b,c}x_{i+a,j+b,k+c}
yi,j,k=a=1∑hb=1∑wc=1∑dwa,b,cxi+a,j+b,k+c
视频, 医学图像, 气象地图
总结
- 卷积层将输入和核矩阵进行交叉相关, 加上偏移后得到输出
- 核矩阵和偏移是可学习的参数
- 核矩阵的大小是超参数
代码实现
互相关运算
import torch
from torch import nn
from d2l import torch as d2l
def corr2d(X, K):
"""计算互相关运算
@param X: 输入
@param K: 核
"""
# 行数和列数
h, w = K.shape
# 输出的高=输入的高 - 核的高 + 1, 输出的宽=输入的宽 - 核的宽 + 1,
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的数据, 然后不断偏移和核矩阵做点积
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)
# output: tensor([[19, 25], [37, 23]])
卷积层
class Conv2D(nn.Module):
def __init__(self, kernel_size):
super().__init__()
# 卷积核是可学习的 kernel_size * kernel_size的矩阵
self.weight = nn.Paramter(torch.rank(kernel_size))
self.bias = nn.Parameter(torch.zeros(1))
def forward(self, x):
return corr2d(x, self.weight) + self.bias
学习X和Y生成卷积核
conv2d = nn.Conv2d(1, 1, kernel_size=(1, 2), bias=False)
# reshape(批量大小数, 通道数量, , )
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}')
更多推荐

所有评论(0)