2.1.卷积层

卷积

​ 用MLP处理图片的问题:假设一张图片有12M像素,那么RGB图片就有36M元素,使用大小为100的单隐藏层,模型有3.6B元素,这个数量非常大。

识别模式的两个原则:

  1. 平移不变性(translation invariance):不管检测对象出现在图像中的哪个位置,神经网络的前面几层应该对相同的图像区域具有相似的反应,即为“平移不变性”。
  2. 局部性(locality):神经网络的前面几层应该只探索输入图像中的局部区域,而不过度在意图像中相隔较远区域的关系,这就是“局部性”原则。最终,可以聚合这些局部特征,以在整个图像级别进行预测。

从全连接层到卷积

​ 需要将输入和输出变形为矩阵(宽度,高度),因为现在处理的信息含有空间上的信息

​ 将权重变形为四维张量,从(h,w)到(h’,w’),记录输入图的横纵坐标,对输出图的横纵坐标的影响。
h i , j = b i , j + ∑ k ∑ l w i , j , k , l x k , l = b i , j + ∑ a ∑ b v i , j , a , b x i + a , i + b v 是 w 的重新索引 v i , j , a , b = w i , j , i + a , j + b h_{i,j} = b_{i,j}+\sum_{k}\sum_{l}w_{i,j,k,l}x_{k,l}=b_{i,j}+\sum_{a}\sum_bv_{i,j,a,b}x_{i+a,i+b}\\ v是w的重新索引 v_{i,j,a,b} = w_{i,j,i+a,j+b} hi,j=bi,j+klwi,j,k,lxk,l=bi,j+abvi,j,a,bxi+a,i+bvw的重新索引vi,j,a,b=wi,j,i+a,j+b
​ 索引 a a a b b b通过在正偏移和负偏移之间移动覆盖了整个图像。对于隐藏表示中任意给定位置 ( i , j ) (i,j) (i,j)处的像素值 h i , j h_{i,j} hi,j,可以通过 x x x中以 ( i , j ) (i,j) (i,j)为中心对像素进行加权求和得到,加权使用的权重为 v i , j , a , b v_{i,j,a,b} vi,j,a,b

平移不变性

x x x的平移导致 h h h的平移 h i , j = b i , j + ∑ a ∑ b v i , j , a , b x i + a , i + b h_{i,j}=b_{i,j}+\sum_{a}\sum_bv_{i,j,a,b}x_{i+a,i+b} hi,j=bi,j+abvi,j,a,bxi+a,i+b, v v v应该不依赖于 i , j i,j i,j,它是整张图的权重,则我们可以让 v i , j , a , b = v a , b v_{i,j,a,b}=v_{a,b} vi,j,a,b=va,b,则
h i , j = b i , j + ∑ a ∑ b v a , b x i + a , i + b h_{i,j} =b_{i,j}+\sum_{a}\sum_bv_{a,b}x_{i+a,i+b} hi,j=bi,j+abva,bxi+a,i+b
​ 这就是2维卷积,数学上叫做2维交叉相关

​ 这样的简化让权重矩阵简化了不少

局部性

h i , j = b i , j + ∑ a ∑ b v a , b x i + a , i + b h_{i,j} =b_{i,j}+\sum_{a}\sum_bv_{a,b}x_{i+a,i+b} hi,j=bi,j+abva,bxi+a,i+b

​ 在评估 h i , j h_{i,j} hi,j时,我们不应该用远离 x i , j x_{i,j} xi,j的参数,那么,可以只取一个小范围:

​ 当 ∣ a ∣ , ∣ b ∣ > Δ |a|,|b|>\Delta a,b>Δ时,使得 v a , b = 0 v_{a,b}=0 va,b=0
h i , j = b i , j + ∑ a = − Δ Δ ∑ b = − Δ Δ v a , b x i + a , j + b h_{i,j}= b_{i,j}+\sum^\Delta_{a=-\Delta}\sum^\Delta_{b=-\Delta} v_{a,b}x_{i+a,j+b} hi,j=bi,j+a=ΔΔb=ΔΔva,bxi+a,j+b
对全连接层使用平移不变性和局部性得到了卷积层
h i , j = b i , j + ∑ a ∑ b v i , j , a , b x i + a , i + b ⟹ h i , j = b i , j + ∑ a = − Δ Δ ∑ b = − Δ Δ v a , b x i + a , j + b h_{i,j} =b_{i,j}+\sum_{a}\sum_bv_{i,j,a,b}x_{i+a,i+b} \Longrightarrow h_{i,j}= b_{i,j}+\sum^\Delta_{a=-\Delta}\sum^\Delta_{b=-\Delta} v_{a,b}x_{i+a,j+b} hi,j=bi,j+abvi,j,a,bxi+a,i+bhi,j=bi,j+a=ΔΔb=ΔΔva,bxi+a,j+b

卷积层

二维交叉相关

在这里插入图片描述

​ 对应数字相乘再相加。

二维卷积层

在这里插入图片描述

输入 X : n h × n w X:n_h \times n_w X:nh×nw

W : k h × k w W:k_h \times k _w W:kh×kw

偏差 b ∈ R b\in \R bR

输出 Y : ( n h − k h + 1 ) × ( n w − k w + 1 ) Y:(n_h-k_h+1)\times (n_w-k_w+1) Y:(nhkh+1)×(nwkw+1) (卷积核横向和纵向滑动的次数)
Y = X ⋅ W + b Y =X\cdot W +b Y=XW+b
W W W b b b是可学习的参数

在这里插入图片描述

边缘检测:中间大,周围是负数

由于对称性,交叉相关和卷积在实际使用中没有区别

一维和三维交叉相关

1.一维

y i = ∑ a = 1 h w a x i + 1 y_i = \sum^h_{a=1} w_ax_{i+1} yi=a=1hwaxi+1

​ 文本,语言,时序序列

2.三维


y i , j , k = ∑ a = 1 h ∑ b = 1 w ∑ c = 1 d w a , b , c x i + a , j + b , k + c y_{i,j,k} = \sum ^h _{a=1}\sum^w_{b=1} \sum^d_{c=1} w_{a,b,c} x_{i+a,j+b,k+c} yi,j,k=a=1hb=1wc=1dwa,b,cxi+a,j+b,k+c
​ 视频,医学图像,气象地图

​ 卷积层将输入和核矩阵进行交叉相关,加上偏移后得到输出,核矩阵和偏移是可学习的参数,核矩阵的大小是超参数。

代码实现

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


def corr2d(X, K):  # X是输入矩阵,K是核矩阵 2D卷积
    """计算二维互相关运算"""
    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]])
Y = corr2d(X, K)
print(Y)

'''卷积层,卷积层在进行互相关运算后,加上偏置产生输出,那么卷积层被训练的参数是卷积核权重和标量偏置'''


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  # 前向传播函数调用corr2d并进行偏置


'''将带有h×w卷积核的卷积层称为h×w卷积层'''

# 检测图像中不同颜色的边缘
X = torch.ones((6, 8))
X[:, 2:6] = 0
print(X)
# 如果元素相同,则输出为0,不同则非0
k = torch.tensor([[1.0, -1.0]])
Y = corr2d(X, k)
print('边缘检测结果:\n', Y)

# 这个K只能检测垂直边缘,将X转置后:
Z = corr2d(X.t(), k)
print('垂直边缘检测结果:\n', Z)

'''学习卷积核'''

# 构造一个二维卷积层,它具有1个输出通道和形状为(1,2)的卷积核
conv2d = nn.Conv2d(1, 1, kernel_size=(1, 2), bias=False)

# 这个二维卷积层使用四维输入和输出格式(批量大小、通道、高度、宽度),
# 其中批量大小和通道数都为1


X = X.reshape((1, 1, 6, 8))
Y = Y.reshape((1, 1, 6, 7))
lr = 3e-2  # 学习率

for i in range(10):
    Y_hat = conv2d(X)
    l = (Y_hat - Y) ** 2  # 均方误差
    conv2d.zero_grad()
    l.sum().backward()
    # 迭代卷积核
    conv2d.weight.data[:] -= lr * conv2d.weight.grad
    if (i + 1) % 2 == 0:
        print(f'epoch {i + 1}, loss {l.sum():.3f}')

print("训练结果:", conv2d.weight.data.reshape((1, 2)))

个人理解

​ 卷积的动机是为了减少训练的参数,模式识别的特点(平移不变性,局部性)也保证了这样是合理的。

相关推荐

  1. 李沐21_多输入多输出通道——自学笔记

    2024-07-20 21:20:03       39 阅读
  2. 什么叫

    2024-07-20 21:20:03       65 阅读
  3. 李沐20_里的填充和步幅——自学笔记

    2024-07-20 21:20:03       34 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-20 21:20:03       141 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-20 21:20:03       156 阅读
  3. 在Django里面运行非项目文件

    2024-07-20 21:20:03       129 阅读
  4. Python语言-面向对象

    2024-07-20 21:20:03       141 阅读

热门阅读

  1. Python正则表达式

    2024-07-20 21:20:03       27 阅读
  2. 【SpringBoot】SpringAOP实现公共字段自动填充

    2024-07-20 21:20:03       25 阅读
  3. Netty的线程模型是怎么样的

    2024-07-20 21:20:03       24 阅读
  4. python入门教程,小白10分钟快速入门

    2024-07-20 21:20:03       27 阅读
  5. 【Webpack】HMR 热更新

    2024-07-20 21:20:03       25 阅读
  6. Fisher-Yates 算法-数组元素随机交换

    2024-07-20 21:20:03       32 阅读
  7. C++ 中值传递和引用传递的区别?

    2024-07-20 21:20:03       24 阅读
  8. MATLAB的基础知识

    2024-07-20 21:20:03       28 阅读
  9. 【Vue】vue2 vue-awesome-swiper 刷新无法自动滚动解决

    2024-07-20 21:20:03       27 阅读
  10. 【Go系列】模块和协同开发

    2024-07-20 21:20:03       27 阅读
  11. C++中size_t怎么用

    2024-07-20 21:20:03       25 阅读