深度学习笔记之卷积神经网络(三)卷积示例与池化操作

news2024/11/13 20:45:37

深度学习笔记之卷积神经网络——卷积示例与池化操作

  • 引言
    • 卷积神经网络:卷积层
      • 卷积层的计算过程
    • 池化层描述
      • 池化层的作用——降低模型复杂度,防止过拟合
      • 池化层执行过程
      • 池化层代码示例
    • 池化层的作用——平移不变性
    • 卷积加池化作为一种无限强的先验
    • 池化层的反向传播过程

引言

上一节介绍了卷积的另一特点——筛选数据特征。并通过神经网络的反向传播过程,我们能够对卷积核内的参数进行更新,得到从数据中提取到更优质特征的卷积核。

本节对卷积操作进行示例,并继续介绍池化操作。

卷积神经网络:卷积层

在之前的卷积神经网络反向传播示例中,我们仅仅使用单通道的灰度图片作为输入,并使用 1 1 1个卷积核执行卷积运算。

但在 3 3 3通道的彩色图片中,每个通道均使用对应的卷积核执行卷积操作。也就是说:对于彩色图片,如果依然使用 3 × 3 3 \times 3 3×3大小的卷积核执行卷积运算,对于该图片的卷积核格式 ( Shape ) (\text{Shape}) (Shape)是: 3 × 3 × 3 3 \times 3 \times 3 3×3×3
需要注意的是,虽然对每个通道分别进行卷积操作,但是 3 × 3 × 3 3 \times 3 \times 3 3×3×3卷积核矩阵是‘一个卷积核’。并且各分量之间仅起到一个‘并行’作用。仅仅是用矩阵合在一起。

在卷积神经网络的卷积层中,针对一个图像数据,不一定仅使用 1 1 1个卷积核来执行卷积操作,而是通过构建若干个卷积核针对同一个数据进行卷积操作。这意味着:针对同一数据,可以得到不同卷积结果,其结果数量与卷积核数量相同

这里使用 PyTorch \text{PyTorch} PyTorch中的二维卷积 Conv2d \text{Conv2d} Conv2d执行过程示例。

为了简化运算,使用元素值均为 1 1 1的矩阵作为数据。其数据格式表示如下:

import torch
from torch import nn as nn

SampleInput = torch.ones(1,3,3,3)

这明显是一个 4 4 4维张量。各维度的物理意义表示为:

  • 1 ⇒ 1 \Rightarrow 1 数据数量—— 1 1 1图片数据
  • 3 ⇒ 3 \Rightarrow 3 图片数据通道数——彩色图片。
  • 3 ⇒ 3 \Rightarrow 3 图片数据的 ( Width ) (\text{Width}) (Width)
  • 3 ⇒ 3 \Rightarrow 3 图片数据的 ( Height ) (\text{Height}) (Height)

卷积层设置如下:

Conv1 = nn.Conv2d(
    in_channels=3,
    out_channels=1,
    kernel_size=(2,2)
)

其中:

  • in_channels=3表示该卷积层对于样本数据的输入通道数 3 3 3
  • out_channels=1表示输出通道数,也就是针对每个输入数据,使用的卷积核数量
  • kernel_size=(2,2)表示针对每个通道的卷积核的大小
  • 关于Stride,Padding等参数均使用默认值

我们观察卷积核的权重信息以及它的返回结果格式:

print(Conv1.state_dict()["weight"].shape)
print(Conv1(SampleInput).shape)

返回结果如下:

torch.Size([1, 3, 2, 2])
torch.Size([1, 1, 2, 2])

其中权重 ( Weight ) (\text{Weight}) (Weight)的格式可看作是: 1 1 1 3 × 2 × 2 3 \times 2 \times 2 3×2×2大小的卷积核。而对应的输出结果格式表示为:针对 1 1 1个数据, 1 1 1个卷积核产生的大小为 2 × 2 2 \times 2 2×2的卷积结果。

同理,如果将卷积层中的out_channels参数进行修改,可得到不同格式的权重和输出结果

Conv1 = nn.Conv2d(
    in_channels=3,
    out_channels=10,
    kernel_size=(2,2)
)

torch.Size([10, 3, 2, 2])
torch.Size([1, 10, 2, 2])

卷积层的计算过程

观察它的计算过程:

print(SampleInput)
print("------" * 10)
print(Conv1.state_dict()["weight"].shape)
print(Conv1.state_dict()["weight"])
print(Conv1.state_dict()["bias"])
print(Conv1(SampleInput).shape)
print(Conv1(SampleInput))

返回结果如下:

tensor([[[[1., 1., 1.],
          [1., 1., 1.],
          [1., 1., 1.]],

         [[1., 1., 1.],
          [1., 1., 1.],
          [1., 1., 1.]],

         [[1., 1., 1.],
          [1., 1., 1.],
          [1., 1., 1.]]]])
------------------------------------------------------------
torch.Size([1, 3, 2, 2])
tensor([[[[-0.2332,  0.0908],
          [ 0.0909,  0.1832]],

         [[ 0.2570,  0.1007],
          [-0.1385, -0.2769]],

         [[-0.1610, -0.2174],
          [ 0.1630,  0.2141]]]])
tensor([0.0693])
torch.Size([1, 1, 2, 2])
tensor([[[[0.1420, 0.1420],
          [0.1420, 0.1420]]]], grad_fn=<ThnnConv2DBackward0>)
  • 将各通道的卷积核对相应通道执行卷积运算
    { Convolution [ ( 1 , 1 , 1 1 , 1 , 1 1 , 1 , 1 ) , ( − 0.2332 , 0.0908 0.0909 , 0.1832 ) ] = ( 0.1317 , 0.1317 0.1317 , 0.1317 ) Convolution [ ( 1 , 1 , 1 1 , 1 , 1 1 , 1 , 1 ) , ( 0.2570 , 0.1007 − 0.1385 , − 0.2769 ) ] = ( − 0.0577 , − 0.0577 − 0.0577 , − 0.0577 ) Convolution [ ( 1 , 1 , 1 1 , 1 , 1 1 , 1 , 1 ) , ( − 0.1610 , − 0.2174 0.1630 , 0.2141 ) ] = ( − 0.0013 , − 0.0013 − 0.0013 , − 0.0013 ) \begin{cases} \text{Convolution} \left[\begin{pmatrix} 1,1,1 \\ 1,1,1 \\ 1,1,1 \end{pmatrix},\begin{pmatrix} -0.2332,0.0908 \\ 0.0909,0.1832 \end{pmatrix}\right] = \begin{pmatrix} 0.1317,0.1317 \\ 0.1317,0.1317 \end{pmatrix} \\ \text{Convolution} \left[\begin{pmatrix} 1,1,1 \\ 1,1,1 \\ 1,1,1 \end{pmatrix},\begin{pmatrix} 0.2570,0.1007 \\ -0.1385,-0.2769 \end{pmatrix} \right] = \begin{pmatrix} -0.0577,-0.0577 \\ -0.0577,-0.0577 \end{pmatrix} \\ \text{Convolution} \left[\begin{pmatrix} 1,1,1 \\ 1,1,1 \\ 1,1,1 \end{pmatrix},\begin{pmatrix} -0.1610, -0.2174 \\ 0.1630, 0.2141 \end{pmatrix}\right] = \begin{pmatrix} -0.0013,-0.0013 \\ -0.0013,-0.0013 \end{pmatrix} \end{cases} Convolution 1,1,11,1,11,1,1 ,(0.2332,0.09080.0909,0.1832) =(0.1317,0.13170.1317,0.1317)Convolution 1,1,11,1,11,1,1 ,(0.2570,0.10070.1385,0.2769) =(0.0577,0.05770.0577,0.0577)Convolution 1,1,11,1,11,1,1 ,(0.1610,0.21740.1630,0.2141) =(0.0013,0.00130.0013,0.0013)
  • 将各卷积结果对应位置相加,并在对应位置加上偏置项 bias \text{bias} bias
    各项均相同,用 ∗ ∗ ** 简写,注意要加偏置项。
    ( 0.0137 − 0.0577 − 0.0013 + 0.0693 , ∗ ∗ ∗ ∗ , ∗ ∗ ) = ( 0.142 , 0.142 0.142 , 0.142 ) \begin{pmatrix} 0.0137 - 0.0577 - 0.0013 + 0.0693,** \\ **,** \end{pmatrix} = \begin{pmatrix} 0.142,0.142 \\ 0.142,0.142 \end{pmatrix} (0.01370.05770.0013+0.0693,,)=(0.142,0.1420.142,0.142)

最终和计算机的计算结果相同。

池化层描述

池化层的作用——降低模型复杂度,防止过拟合

如果说卷积 ( Convolution ) (\text{Convolution}) (Convolution)操作是提取数据中信息特征的分布,那么池化就是对这个描述信息特征的分布进行降采样 ( DownSampling ) (\text{DownSampling}) (DownSampling)。而降采样的目的是:数据特征基本不变的条件下,消减数据特征的大小,使其在卷积神经网络的计算过程中(前馈计算/反向传播过程)减少参数的计算量

这个计算量主要是指卷积核中参数更新的次数减少,但更新的特征却基本没有减少。因而池化层降低了模型的复杂度,从而实现防止过拟合 ( Overfitting ) (\text{Overfitting}) (Overfitting)的效果。

  • 这里说的‘参数的更新次数’是指卷积神经网络反向传播过程中,卷积核内权重对各输出特征梯度的累加数量。关于卷积神经网络反向传播见传送门
  • 可以将池化理解成数据特征的'收缩'。

池化层执行过程

具体的池化层主要包含两种——平均池化 ( Average Pooling ) (\text{Average Pooling}) (Average Pooling)最大池化 ( Max Pooling ) (\text{Max Pooling}) (Max Pooling)

  • 平均池化示例,已知一个 4 × 4 4 \times 4 4×4特征图像表示如下:
    这里说的‘特征图像’可能是一个输入的灰度图像,也可能是某卷积层的输出结果,不影响。
    特征图像示例
  • 使用 2 × 2 2 \times 2 2×2池化窗口对其进行平均池化操作:
    就是对窗口内涵盖的特征结果取平均值。
    { 1 + 3 + 2 + 9 4 = 3.75 1 + 4 + 5 + 6 4 = 4 1 + 1 + 1 + 2 4 = 1.25 2 + 2 + 3 + 1 4 = 2 ⇒ [ 3.75 1.25 4 2 ] \begin{cases} \begin{aligned} & \frac{1 + 3 + 2 + 9}{4} = 3.75 \\ & \frac{1 + 4 + 5 + 6}{4} = 4 \\ & \frac{1 + 1 + 1 + 2}{4} = 1.25 \\ & \frac{2 + 2 + 3 + 1}{4} = 2 \end{aligned} \end{cases} \Rightarrow\begin{bmatrix} 3.75\quad 1.25 \\ 4\quad2 \end{bmatrix} 41+3+2+9=3.7541+4+5+6=441+1+1+2=1.2542+2+3+1=2[3.751.2542]
  • 同理,使用 2 × 2 2 \times 2 2×2池化窗口对其进行最大池化操作:
    { max ⁡ { 1 , 2 , 3 , 9 } = 9 max ⁡ { 1 , 4 , 5 , 6 } = 6 max ⁡ { 1 , 1 , 1 , 2 } = 2 max ⁡ { 2 , 2 , 3 , 1 } = 3 ⇒ [ 9 2 6 3 ] \begin{cases} \max \{1,2,3,9\} = 9 \\ \max \{1,4,5,6\} = 6 \\ \max \{1,1,1,2\} = 2 \\ \max \{2,2,3,1\} = 3 \end{cases} \Rightarrow \begin{bmatrix} 9 \quad 2 \\ 6 \quad 3 \end{bmatrix} max{1,2,3,9}=9max{1,4,5,6}=6max{1,1,1,2}=2max{2,2,3,1}=3[9263]

观察池化的过程,如果将该过程看做采样的话,那么这个采样的目的是:一个值来描述当前窗口信息的综合情况。而池化后的结果就是特征图像描述信息的缩影
特征图像左半VS右半

  • 上例中‘特征图像’的左半部分与右半部分相比,左半部分的数值结果存在较大的数值;
  • 并且左半部分数值‘比较活跃’,数值之间相差的更大;相反,右半数值相比之下更加稳定。

而这些特征在最大池化结果中,都有体现:

  • 左半、右半特征最值结果比较: 9 > 2 ; 6 > 3 9 > 2;6 >3 9>2;6>3
  • 左半、右半特征方差结果比较:
    S Left = 2.25 > 0.25 = S Right \mathcal S_{\text{Left}} = 2.25 > 0.25 = \mathcal S_{\text{Right}} SLeft=2.25>0.25=SRight

池化层代码示例

从代码角度观察池化操作,这里对某一个卷积结果进行池化操作:
没有涉及到激活函数。仅重点观察池化的具体效果。

  • 定义卷积池化操作:
    其中池化操作中的 m , n m,n m,n表示池化窗口的宽、高。为了简化起见,其步长就是池化窗口的宽度。
import numpy as np
import cv2
import torch
from torch import nn as nn

Conv1 = nn.Conv2d(
    in_channels=3,
    out_channels=1,
    kernel_size=(2,2))

def Pooling(data, m, n,mode):
    assert mode in ["Max","Avg"]
    a, b = data.shape
    img_new = []
    for i in range(0, a, m):
        line = []
        for j in range(0, b, n):
            x = data[i:i + m, j:j + n]
            if mode == "Max":
                line.append(np.max(x))
            else:
                line.append(np.sum(x) / (n * m))
        img_new.append(line)
    return np.array(img_new)
  • 将图像数据作为输入,得到对应的卷积平均池化最大池化的输出结果:
    这里选择 2 × 2 2 \times 2 2×2大小的池化窗口,对应步长为 2 2 2
PicPath = "C:/Users/Administrator/Desktop/PicSample.jpg"
img = cv2.imread(PicPath)
cv2.imshow("img",img)

imgInput = torch.transpose(torch.FloatTensor(img),0,2).unsqueeze(0)
ConvOut = Conv1(imgInput)
ConvOut = torch.transpose(ConvOut.squeeze(0),0,2).detach().numpy()
cv2.imshow("ConvOut",ConvOut)

PoolInput = np.squeeze(ConvOut)
# MaxPooling
img_MaxPool = Pooling(PoolInput, 2, 2,mode="Max")
# AvgPooling
img_AvgPool = Pooling(PoolInput, 2, 2,mode="Avg")
cv2.imshow("img_MaxPool",img_MaxPool)
cv2.imshow("img_AvgPool",img_AvgPool)
cv2.waitKey(0)

对应原始数据卷积结果,最大/平均池化结果分别表示如下:

  • 原始数据与卷积结果:
    这里卷积过程中,卷积核是随机产生的,如果效果不好,请多试几次~
    原始数据与卷积结果
  • 卷积结果以及对应的池化结果:
    从图像的角度观察,卷积结果的特征信息基本没变化,但是图像大小(像素点数量)缩减为原来的 1 4 \begin{aligned}\frac{1}{4}\end{aligned} 41.
    卷积结果与池化结果(含大小比例)

池化层的作用——平移不变性

平移不变性的基本描述是:输入做少量平移时,池化能够帮助输入的表示近似不变
引自《深度学习》(花书) P207 9.3 池化

首先,卷积神经网络对于位置是非常敏感的。如果样本输入发生一些平移,也就是说,如果说同一个事物,基于它产生的两个图像之间仅仅差若干个像素,对于神经网络的学习结果都会产生巨大的变化。就像这样:
从人的角度观察,虽然存在少许偏差,但它依然是同一个事物;但在卷积神经网络的角度,可能会对图片中事物的判别发生错误。
像素平移
关于平移不变性的示例如下:

  • 某一维数据特征在通过卷积层,激活函数后的局部结果表示如下:
    ( 0.1 , 1.0 , 0.2 , 0.1 , ⋯   ) (0.1,1.0,0.2,0.1,\cdots) (0.1,1.0,0.2,0.1,)
  • 如果该数据特征左移了一个元素/像素,导致再次通过卷积层、激活函数后的局部结果相比之前变化如下:
    这意味着,第一个位置由新的元素替代,该结果的最后一个元素被‘踢掉’。
    ( 0.3 , 0.1 , 1.0 , 0.2 , 0.1 ⋯   ) (0.3,0.1,1.0,0.2,0.1\cdots) (0.3,0.1,1.0,0.2,0.1)

这意味着:该输出结果随着左移产生新元素的加入,所有元素的位置均发生了变化。如果仅看局部位置,针对局部位置执行池化窗口 3 3 3步长 1 1 1最大池化操作,两个输出结果对应的池化结果分别是:
{ ( 0.1 , 1.0 , 0.2 , 0.1 , ⋯   ) ⟹ Pool ( 1.0 , 1.0 , ⋯   ) ( 0.3 , 0.1 , 1.0 , 0.2 , 0.1 ⋯   ) ⟹ Pool ( 1.0 , 1.0 , 1.0 , ⋯   ) \begin{aligned} \begin{cases} (0.1,1.0,0.2,0.1,\cdots) \overset{\text{Pool}}{\Longrightarrow} (1.0,1.0,\cdots) \\ (0.3,0.1,1.0,0.2,0.1\cdots) \overset{\text{Pool}}{\Longrightarrow} (1.0,1.0,1.0,\cdots) \end{cases} \end{aligned} (0.1,1.0,0.2,0.1,)Pool(1.0,1.0,)(0.3,0.1,1.0,0.2,0.1)Pool(1.0,1.0,1.0,)
可以发现,局部位置池化后的结果相比之前的池化结果,相当于第一位增加了一个 1.0 1.0 1.0,最后一位可能消掉了一个结果,中间过程的所有结果均未发生变化。而这个增加的 1.0 1.0 1.0和其相邻的结果相同,都是这个局部区域最大值 1.0 1.0 1.0。相当于被模糊掉了

之所以会出现这种现象,是因为平移产生的像素 0.3 0.3 0.3没有影响这个局部区域最大值 1.0 1.0 1.0的地位,执行最大池化时,大概率会被同化掉。也就是说,最大池化单元仅仅对周围的最大值比较敏感。

卷积加池化作为一种无限强的先验

如果将卷积层、激活函数、池化层看作是一个复杂层,我们可以将这个复杂层看作是基于权重有一个无限强先验的全连接神经网络模型。为什么要这么说 ? ? ?
为了区别于前面,我们将‘卷积层’描述为‘由卷积级、探测级(激活函数)、池化级’构成的复杂层。详见《机器学习》(花书) P208 9.3 池化

  • 基于卷积函数的基本性质,在每次迭代过程中,卷积级的参数部分只有卷积核大小的数量。这也是它和全连接神经网络的主要区别。

    卷积级的输出结果中,每一个元素(像素点)均只由卷积核中的参数以及被卷积核覆盖的输入(像素点)决定。也就是说,每一次卷积级的计算,它的权重空间仅由卷积核大小数量的权重参数约束着。这意味着权重空间的约束性很强
    相反,全连接神经网络的权重空间相比之下更加广阔,因为每一个输入都存在一个权重与其相对应,全连接层每个神经元的输出均由所有输入对应的权重共同决定。也就是《深度学习》(花书) P211 9.3 池化中提到的‘局部连接关系’。

  • 如果仅仅是卷积级内的局部连接关系,还不至于是无限强的先验,关键在池化级。因为池化级(依然以最大池化级为例)探测级输出的特征结果强行地归属于其局部区域内的最大值

    在极大似然估计与最大后验概率估计中介绍了投掷硬币的例子。在投掷质地均匀硬币 10 10 10次, 7 7 7正面朝上 3 3 3反面朝上。如果没有先验概率的干预,仅通过极大似然估计来判别正面向上的概率,其概率结果为:
    ln ⁡ P ( X ∣ θ ) = ln ⁡ [ P 7 × ( 1 − P ) 3 ] = 7 ln ⁡ P + 3 ln ⁡ ( 1 − P ) ∂ ln ⁡ P ( X ∣ θ ) ∂ P ≜ 0 ⇒ 7 P + 3 1 − P = 0 ⇒ P = 0.7 \begin{aligned} \ln \mathcal P(\mathcal X \mid \theta) & = \ln \left[\mathcal P^7 \times (1 - \mathcal P)^3\right] \\ & = 7 \ln \mathcal P + 3 \ln(1 - \mathcal P) \\ \frac{\partial \ln \mathcal P(\mathcal X \mid \theta)}{\partial \mathcal P} \triangleq 0 & \Rightarrow \frac{7}{\mathcal P} + \frac{3}{1 - \mathcal P} = 0 \\ & \Rightarrow \mathcal P = 0.7 \end{aligned} lnP(Xθ)PlnP(Xθ)0=ln[P7×(1P)3]=7lnP+3ln(1P)P7+1P3=0P=0.7

    但这个结果并不符合我们的认知:投掷质地均匀硬币正面朝上的概率是 0.5 0.5 0.5反面朝上的概率是 0.5 0.5 0.5。因而针对参数 θ \theta θ,追加了一个先验概率 P ( θ ) \mathcal P(\theta) P(θ)均值 μ = 0.5 \mu=0.5 μ=0.5,方差 σ = 0.1 \sigma=0.1 σ=0.1的高斯分布,使用最大后验概率估计求解概率 P \mathcal P P
    arg ⁡ max ⁡ θ P ( θ ∣ X ) ∝ arg ⁡ max ⁡ θ P ( X ∣ θ ) ⋅ P ( θ ) ⇒ ln ⁡ [ P ( X ∣ θ ) ⋅ P ( θ ) ] = ln ⁡ [ P 7 × ( 1 − P ) 3 ] + ln ⁡ [ 1 0.1 × 2 π exp ⁡ { − ( p − 0.5 ) 2 2 × 0.01 } ] ⇒ ∂ ln ⁡ [ P ( X ∣ θ ) ⋅ P ( θ ) ] ∂ P ≜ 0 ⇒ 3 1 − P + 7 P − 100 × ( P − 1 2 ) = 0 \begin{aligned} \mathop{\arg\max}\limits_{\theta} \mathcal P(\theta \mid \mathcal X) & \propto \mathop{\arg\max}\limits_{\theta} \mathcal P(\mathcal X \mid \theta) \cdot \mathcal P(\theta) \\ \Rightarrow \ln [\mathcal P(\mathcal X \mid \theta) \cdot \mathcal P(\theta)] & = \ln \left[\mathcal P^7 \times (1- \mathcal P)^3\right] + \ln \left[\frac{1}{0.1 \times \sqrt{2 \pi}} \exp \left\{-\frac{(p - 0.5)^2}{2 \times 0.01}\right\}\right] \\ \Rightarrow \frac{\partial \ln \left[\mathcal P(\mathcal X \mid \theta) \cdot \mathcal P(\theta)\right]}{\partial \mathcal P} \triangleq 0 & \Rightarrow \frac{3}{1 - \mathcal P} + \frac{7}{\mathcal P} - 100 \times \left(\mathcal P - \frac{1}{2}\right) = 0 \end{aligned} θargmaxP(θX)ln[P(Xθ)P(θ)]Pln[P(Xθ)P(θ)]0θargmaxP(Xθ)P(θ)=ln[P7×(1P)3]+ln[0.1×2π 1exp{2×0.01(p0.5)2}]1P3+P7100×(P21)=0
    最终求解 P ≈ 0.558 \mathcal P \approx 0.558 P0.558。相比于未含先验的 0.7 0.7 0.7,它已经将该结果拉向了我们的认知范围内。这里关于最大池的思路同理,并且它比上述的先验更强——强行等于某个局部最大值,而不是一个概率分布范围。也就是说:该值以 1 1 1的概率等于其局部区域内的最大值。这就相当于使用一种无限强的先验,强行引导输出值等于某个具体结果

池化层的反向传播过程

由于池化层仅是一个收缩的操作,因而它无法从卷积神经网络中学习到特征信息。但它同样需要通过反向传播将信息传递给上层的探测级
仅仅起到一个传递梯度的操作。
而这个梯度传递操作的核心是:池化前后梯度之和保持不变

  • 平均池化
    将梯度均分给池化之前池化窗口内的所有特征点。如果池化时采用 2 × 2 2 \times 2 2×2池化窗口,步长 Step=2 \text{Step=2} Step=2的操作,已知一个池化后 2 × 2 2 \times 2 2×2梯度信息,那么它池化前的梯度信息表示为:
    [ 1 0.8 0.4 0.6 ] ⇒ [ 0.25 0.25 0.2 0.2 0.25 0.25 0.2 0.2 0.1 0.1 0.15 0.15 0.1 0.1 0.15 0.15 ] \begin{bmatrix} 1 \quad 0.8 \\ 0.4 \quad 0.6 \end{bmatrix} \Rightarrow \begin{bmatrix} 0.25 \quad 0.25 \quad 0.2 \quad 0.2 \\ 0.25 \quad 0.25 \quad 0.2 \quad 0.2 \\ 0.1 \quad 0.1 \quad 0.15 \quad 0.15 \\ 0.1 \quad 0.1 \quad 0.15 \quad 0.15 \\ \end{bmatrix} [10.80.40.6] 0.250.250.20.20.250.250.20.20.10.10.150.150.10.10.150.15
  • 最大池化
    在执行最大池化时,记住选择最大值的位置;在反向传播时,将梯度结果返还给对应位置,其他位置梯度为 0 0 0。基于上述的池化要求,其最大池化的前向传播与反向传播表示如下:
    [ 5 3 1 2 1 2 3 2 4 2 2 5 3 6 1 1 ] ⟹ FeedFoward [ 5 3 6 5 ] [ 1.0 0 0 0 0 0 0.8 0 0 0 0 0.6 0 0.4 0 0 ] ⟸ Barkward [ 1.0 0.8 0.4 0.6 ] \begin{bmatrix} 5 \quad 3 \quad 1 \quad 2 \\ 1 \quad 2 \quad 3 \quad 2 \\ 4 \quad 2 \quad 2 \quad 5 \\ 3 \quad 6 \quad 1 \quad 1 \\ \end{bmatrix} \overset{\text{FeedFoward}}{\Longrightarrow} \begin{bmatrix} 5 \quad 3 \\ 6 \quad 5 \end{bmatrix} \\ \begin{bmatrix} 1.0 \quad 0 \quad 0 \quad 0 \\ 0 \quad 0 \quad 0.8 \quad 0 \\ 0 \quad 0 \quad 0 \quad 0.6 \\ 0 \quad 0.4 \quad 0 \quad 0 \\ \end{bmatrix} \overset{\text{Barkward}}{\Longleftarrow} \begin{bmatrix} 1.0 \quad 0.8 \\ 0.4 \quad 0.6 \end{bmatrix} 5312123242253611 FeedFoward[5365] 1.0000000.800000.600.400 Barkward[1.00.80.40.6]

相关参考:
CNN卷积层的多输入\输出通道你搞清了吗?
池化层详细介绍
《深度学习》(花书) 9.3 池化

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/511325.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

在vs2019中调试qt5.9.3为例

vs2019中其实可以调试qt&#xff0c;此环境配置qt5.9.3和vs2019&#xff0c;当前配置&#xff0c;作为一个记录&#xff0c;也方便大家查看。 vs配置qt环境 首先需要配置好qt在vs2019&#xff0c;可以打开网址https://download.qt.io/archive/vsaddin/2.8.1/&#xff0c; 我准…

【C++】继承和多态、public、private、protected、重写

区分继承与多态、辨别public、protected、private 继承与多态的概念继承与多态的区别与联系区别&#xff1a;联系&#xff1a;示例结果&#xff1a; 继承和访问的权限说明示例&#xff1a;结果 结论 继承与多态的概念 面向对象三大原则&#xff1a;封装、继承、多态。继承是一种…

探索Vue的组件世界-自定义指令

目录 自定义指令 钩子函数参数 使用 什么时候用 在Vue体系下创建一个自定义指令 使用自定义指令及示例要求 全局注册一个自定义指令 自定义指令 全局创建vue自定义指令 Vue.directive("demo", {// 只调用一次&#xff0c;指令第一次绑定到元素时调用。// 在…

MySQL常用SQL

目录 库操作 查询数据库 创建数据库 删除数据库 选择数据库 表操作 查看表 创建表 查看表结构 查看建表sql 删除表 &#xff08;整表删除&#xff09; CRUD操作 insert增加 update修改 delete删除 select查询 去重distinct 空值查询 union合并查询 带in子查询 …

浏览器从输入URL到页面渲染加载的过程(浏览器知识体系整理)

文章目录 前言一、梳理主干流程二、浏览器接收url并开启一个新进程1. 浏览器是多进程的2. 浏览器内核是多线程的3. JS引擎单线程的原因4. GUI渲染线程与JS引擎线程互斥 二、解析URL三、DNS域名解析1. DNS是什么&#xff1f;2. IP和域名的关系3. 域名服务器概念图4. DNS域名解析…

使用 OpenCV 进行基于 ESP32 CAM 的目标检测和识别

概述:基于 ESP32 CAM 的目标检测和识别 本教程介绍了使用OpenCV基于 ESP32 CAM的目标检测和识别主题。OpenCV 是一个开源的图像处理库,不仅在工业界而且在研发领域都得到了非常广泛的应用。 这里对于对象检测,我们使用了cvlib 库。该库使用 COCO 数据集上的预训练 AI 模型…

Flume系列:Flume Sink使用

目录 Apache Hadoop生态-目录汇总-持续更新 1&#xff1a;HDFS Sink HDFS小文件的处理 HDFS存入大量小文件的影响&#xff1a; HDFS小文件处理&#xff1a; 2&#xff1a;logger Sink 3&#xff1a;写入Kafka - 可以使用kafka channel代替 Apache Hadoop生态-目录汇总-持…

力扣sql中等篇练习(十八)

力扣sql中等篇练习(十八) 1 银行账户概要 1.1 题目内容 1.1.1 基本题目信息1 1.1.2 基本题目信息2 1.1.3 示例输入输出 1.2 示例sql语句 # Write your MySQL query statement below SELECT u.user_id,u.user_name,u.creditIFNULL(t1.c1,0) credit,case when u.creditIFNULL…

分享一个无需账号完全免费的 ChatGPT-4 的平台

AIGC从入门到精通教程 1. 访问 SteamShip2. 进入创建页面,选择新建一个 GPT-4 实例。3. 完成创建后,您便可以尽情体验 GPT-4本教程收集于: AIGC从入门到精通教程 大家都知道,ChatGPT4.0是要订阅Plus(一个月20美元)后才能体验的。 今天就给大家弄一个白嫖ChatGPT4.0的教程…

DEJA_VU3D - Cesium功能集 之 107-卫星探测效果

前言 编写这个专栏主要目的是对工作之中基于Cesium实现过的功能进行整合,有自己琢磨实现的,也有参考其他大神后整理实现的,初步算了算现在有差不多实现小140个左右的功能,后续也会不断的追加,所以暂时打算一周2-3更的样子来更新本专栏(每篇博文都会奉上完整demo的源代码,…

c++STL之常用的算法

目录 常用的遍历算法 for_each() transform() for_each()和transform&#xff08;&#xff09;算法比较 常用的查找算法 adjacent_find() binary_search count() count_if() find() 常用的排序算法 merge() sort() random_shuffle() reverse() 常用的拷…

基于`IRIS`,动态解析`HL7`消息

文章目录 基于IRIS&#xff0c;动态解析HL7消息什么是HL7HL7 版本HL7 消息结构段&#xff08;Segment&#xff09;字段&#xff08;Field&#xff09; HL7 数据类型在IRIS中查看HL7数据结构传统方式拼写HL7消息结构动态对象解析HL7消息结构。 基于IRIS&#xff0c;动态解析HL7消…

SpringCloud:微服务保护之隔离和降级

1.FeignClient整合Sentinel SpringCloud中&#xff0c;微服务调用都是通过Feign来实现的&#xff0c;因此做客户端保护必须整合Feign和Sentinel。 1.1.修改配置&#xff0c;开启sentinel功能 修改OrderService的application.yml文件&#xff0c;开启Feign的Sentinel功能&…

详细版易学版TypeScript - 类

一、类 - 类的属性和方法 class MyPreson {// 类的属性// 属性需要在类里先定义并确定类型&#xff0c;才可以在constructor里面用this访问name: stringage: numberconstructor(name: string, age: number) {this.name name;this.age age;}// 类的方法sendStr(str: string) {…

工业4.0时代来临,POWERLINK协议在千兆网卡下的性能

“工业 4.0”的高歌猛进&#xff0c; “智能制造”&#xff0c;“智慧工厂”的呼声越来越响亮。这些需求使得数据传输量越来越大&#xff0c;实时性越来越高&#xff0c;因此我们将 POWERLINK 从 100Mbps 升级到1000Mbps。测试下POWERLINK这种工业总线协议的性能&#xff0c;最…

jest基础指示

describ&#xff08;类似java中的class&#xff0c;在这里定义的变量可以在所有it中使用&#xff09; 针对某一方面的测试&#xff0c;一个描述性的东西&#xff0c;针对某一个方面的测试&#xff0c;或者说是一个作用域 一组测试用例的集合。 有两个参数&#xff0c;参数1 &…

Vue 3.0 学习笔记

Vue 3 学习笔记 文章目录 Vue 3 学习笔记[toc]一、初识vue3二、 常用Composition API&#xff08;组合式API&#xff09;**1. setup函数****2. ref函数****3. reactive函数****4. Vue3.0中的响应式原理****Vue2.x的响应式****Vue3.x的响应式** **5. reactivce对比ref****6. set…

为什么我在大厂待了三个月就选择离开?我聊聊应届生该选择大厂还是小公司

我在互联网大厂只待了3个月就离开了&#xff0c;主要原因不是大厂的福利或者薪资不够好&#xff0c;只是因为我发现在大厂里每天都有开不完的会&#xff0c;忙碌到没有自己的生活。当时我每天10点上班&#xff0c;晚上要工作到11甚至是12点&#xff0c;甚至半夜两三点都接到过工…

LangChain-Agents 入门指南

LangChain-Agents 入门指南 LangChain-Agents 入门指南注册 Serpapi运行高级 Agents API 测试运行 Google Search其它 Here’s the table of contents: LangChain-Agents 入门指南 LangChain是一个使用LLMs构建应用程序的工具箱&#xff0c;包含Models、Prompts、Indexes、Mem…

Vue3-黑马(二)

目录&#xff1a; &#xff08;1&#xff09;vue3-ref与reactive &#xff08;2&#xff09;vue3-基础-属性绑定与事件绑定 &#xff08;3&#xff09;vue3-基础-表单绑定 &#xff08;1&#xff09;vue3-ref与reactive ref函数可以把普通的数据变成响应式的数据&#xff0…