(四)卷积神经网络 -- 1 (1) 二维卷积层

1. 二维卷积层

卷积神经网络(convolutional neural network)是含有卷积层(convolutional layer)的神经网络。
本章中,将介绍其中最常见的二维卷积层,包含高和宽两个空间维度,常用来处理图像数据。
本节中,将介绍简单形式的二维卷积层的工作原理。


1.1 two dimentional cross-correlation

1.1.1 概念

虽然卷积层得名于卷积(convolution)运算,但通常在卷积层中使用更加直观的互相关(cross-correlation)运算。
在二维卷积层中,一个二维输入数组和一个二维核(kernel)数组通过互相关运算输出一个二维数组。

二维互相关运算的含义,可以结合下图进行较为直观的理解:

如上图所示,二维输入数组的高和宽均为3,其形状记为 3 × 3 3 \times 3 3×3或(3,3);
二维核(kernel)数组的高和宽分别为2,其形状记为 2 × 2 2 \times 2 2×2

其中,核数组在卷积计算中,又称卷积核或过滤器(filter)。
卷积窗口(又称卷积核窗口)的形状,取决于卷积核的高和宽,即 2 × 2 2 \times 2 2×2

p × q p \times q p×q卷积或 p × q p \times q p×q卷积核,说明卷积核的高和宽分别为 p p p q q q
卷积窗口形状为 p × q p \times q p×q的卷积层,称为 p × q p \times q p×q卷积层。

上图中的阴影部分,分别为输入的第一个计算区域、核数组以及对应的输出。有输出的计算公式为:
0 × 0 + 1 × 1 + 3 × 2 + 4 × 3 = 19 0\times0+1\times1+3\times2+4\times3=19 0×0+1×1+3×2+4×3=19


在二维互相关运算中,卷积窗口从输入数组的最左上方开始,按从左往右、从上往下的顺序,依次在输入数组上滑动。
当卷积窗口滑动到某一位置时,窗口中的输入子数组与核数组按元素相乘并求和,得到输出数组中相应位置的元素。
上图中的二维输出数组的高和宽分别为2,其中的4个元素由二维互相关运算得出:

0 × 0 + 1 × 1 + 3 × 2 + 4 × 3 = 19 , 1 × 0 + 2 × 1 + 4 × 2 + 5 × 3 = 25 , 3 × 0 + 4 × 1 + 6 × 2 + 7 × 3 = 37 , 4 × 0 + 5 × 1 + 7 × 2 + 8 × 3 = 43. 0\times0+1\times1+3\times2+4\times3=19,\\ 1\times0+2\times1+4\times2+5\times3=25,\\ 3\times0+4\times1+6\times2+7\times3=37,\\ 4\times0+5\times1+7\times2+8\times3=43. 0×0+1×1+3×2+4×3=19,1×0+2×1+4×2+5×3=25,3×0+4×1+6×2+7×3=37,4×0+5×1+7×2+8×3=43.



1.1.2 代码示例

import tensorflow as tf
print(tf.__version__)
2.0.0
示例1:corr2d
# 二维互相关运算
def corr2d(X, K):
    h, w = K.shape
    Y = tf.Variable(tf.zeros(shape=(X.shape[0]-h+1, X.shape[1]-w+1)))
    for i in range(Y.shape[0]):
        for j in range(Y.shape[1]):
            # tf.Variable.assign: Assigns a new value to the variable.
            # X[i:i+h, j:j+w]: Left to right, up to down.
            Y[i,j].assign(tf.cast(tf.reduce_sum(X[i:i+h, j:j+w] * K), dtype=tf.float32))
    return Y
X = tf.constant([[0,1,2],[3,4,5],[6,7,8]])
K = tf.constant([[0,1],[2,3]])
Y = corr2d(X, K)
Y

输出:

<tf.Variable 'Variable:0' shape=(2, 2) dtype=float32, numpy=
array([[19., 25.],
       [37., 43.]], dtype=float32)>

示例2:Conv2D

二维卷积层将输入和卷积核做互相关运算,并加上一个标量偏差来得到输出。
卷积层的模型参数包括了卷积核和标量偏差。在训练模型时,通常先对卷积核进行随机初始化,然后不断迭代卷积核和偏差。

下面基于上文定义的corr2d函数,来实现一个自定义的二维卷积层:

class Conv2D(tf.keras.layers.Layer):
    def __init__(self, units):
        super().__init__()
        self.units = units
        
    def build(self, kernel_size):
        self.w = self.add_weight(name='w',
                                 shape=kernel_size,
                                 initializer=tf.random_normal_initializer())
        self.b = self.add_weight(name='b',
                                 shape=(1,),
                                 initializer=tf.random_normal_initializer())
        
    def call(self, inputs):
        return corr2d(inputs, self.w) + self.b

其中,在构造函数__init__里,声明weightbias这两个模型参数。前向计算函数forward则是直接调用corr2d函数再加上偏差。


示例3:edge detection

卷积层的简单应用:检测图像中物体的边缘,即找到像素变化的位置。

a. 构造一张 6 × 8 6\times 8 6×8的图像(即高和宽分别为6像素和8像素):
中间4列为黑(0),其余为白(1)。

X = tf.Variable(tf.ones((6,8)))
X[:,2:6].assign(tf.zeros(X[:,2:6].shape))
X

输出:

<tf.Variable 'Variable:0' shape=(6, 8) dtype=float32, numpy=
array([[1., 1., 0., 0., 0., 0., 1., 1.],
       [1., 1., 0., 0., 0., 0., 1., 1.],
       [1., 1., 0., 0., 0., 0., 1., 1.],
       [1., 1., 0., 0., 0., 0., 1., 1.],
       [1., 1., 0., 0., 0., 0., 1., 1.],
       [1., 1., 0., 0., 0., 0., 1., 1.]], dtype=float32)>

b. 构造一个 1 × 2 1 \times 2 1×2的卷积核K:
当它与输入做互相关运算时,若横向相邻元素相同,输出为0;否则输出为非0。

K = tf.constant([[1,-1]], dtype=tf.float32)

c. 将输入X和设计的卷积核K进行互相关运算。

Y = corr2d(X, K)
Y

输出:

<tf.Variable 'Variable:0' shape=(6, 7) dtype=float32, numpy=
array([[ 0.,  1.,  0.,  0.,  0., -1.,  0.],
       [ 0.,  1.,  0.,  0.,  0., -1.,  0.],
       [ 0.,  1.,  0.,  0.,  0., -1.,  0.],
       [ 0.,  1.,  0.,  0.,  0., -1.,  0.],
       [ 0.,  1.,  0.,  0.,  0., -1.,  0.],
       [ 0.,  1.,  0.,  0.,  0., -1.,  0.]], dtype=float32)>

结论:将从白到黑的边缘和从黑到白的边缘分别检测成了1和-1,其余部分的输出全为0。


示例4:learn kernel by data

使用1.3小节中物体边缘检测的输入数据X和输出数据Y,来学习构造的核数组K,简要步骤包括:

先构造一个卷积层,将其卷积核初始化成随机数组。
之后,在每一次迭代中,使用平方误差来比较Y和卷积层的输出,然后计算梯度来更新权重。
简单起见,这里的卷积层忽略了偏差。

由于corr2d使用了对单个元素赋值([i, j]=)的操作,无法自动求梯度,因而使用tf.keras.layers提供的Conv2D类来进行实现(而非上文自行构造的Conv2D类)。


构造二维卷积层:

X = tf.reshape(X, (1,6,8,1))
Y = tf.reshape(Y, (1,6,7,1))

conv2d = tf.keras.layers.Conv2D(filters=1, kernel_size=(1,2))
Y_hat = conv2d(X)
Y_hat.shape
TensorShape([1, 6, 7, 1])

迭代10次:

for i in range(10):
    with tf.GradientTape(watch_accessed_variables=False) as tape:
        # 仅对权重w进行追踪
        tape.watch(conv2d.weights[0])
        
        Y_hat = conv2d(X)
        # 损失函数为平方误差
        l = (abs(Y_hat - Y)) ** 2
        
        grads = tape.gradient(l, conv2d.weights[0])
        
        # 元素对应相乘
        lr = 3e-2
        update = tf.multiply(lr, grads)
        
        # 更新权重w
        updated_weights = conv2d.get_weights()
        updated_weights[0] = conv2d.weights[0] - update
        conv2d.set_weights(updated_weights)  

        if (i + 1)% 2 == 0:
            print('batch %d, loss %.3f' % (i + 1, tf.reduce_sum(l)))
batch 2, loss 8.014
batch 4, loss 2.823
batch 6, loss 1.079
batch 8, loss 0.429
batch 10, loss 0.174

查看学习到的核数组(即,权重w):

tf.reshape(conv2d.get_weights()[0],(1,2))
<tf.Tensor: id=1012, shape=(1, 2), dtype=float32, numpy=array([[ 0.94999015, -1.035664  ]], dtype=float32)>

结论:结果与之前定义的核数组K较接近。



参考

《动手学深度学习》(TF2.0版)

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
二维卷积神经网络(Convolutional Neural Network, CNN)是一种常用于图像处理和计算机视觉任务的深度学习模型。下面是二维卷积神经网络的计算公式: 1. 输入数据: 假设输入数据为一个二维矩阵,通常表示为一个三维张量,形状为 [batch_size, height, width, channels],其中 batch_size 表示输入的样本数量,height 和 width 表示输入图像的高度和宽度,channels 表示输入图像的通道数。 2. 卷积操作: 卷积操作是二维卷积神经网络的核心操作,它通过滑动一个称为卷积核(或滤波器)的小矩阵在输入数据上进行计算。卷积操作的计算公式如下: ![convolution_formula](https://img-blog.csdnimg.cn/20211209153603634.png) 其中,* 表示卷积操作,i 和 j 分别表示输出特征图的位置,k 和 l 分别表示卷积核的位置,h 和 w 分别表示卷积核的高度和宽度,C_in 和 C_out 分别表示输入和输出特征图的通道数。 3. 激活函数: 在卷积操作之后,通常会对输出特征图应用激活函数,以引入非线性变换。常用的激活函数包括ReLU、Sigmoid、Tanh等。 4. 池化操作: 池化操作用于减小特征图的尺寸,并提取出主要特征。常用的池化操作有最大池化和平均池化。池化操作的计算公式如下: ![pooling_formula](https://img-blog.csdnimg.cn/20211209153603635.png) 其中,⨆ 表示池化操作,i 和 j 分别表示输出特征图的位置,k 和 l 分别表示池化窗口的位置,h 和 w 分别表示池化窗口的高度和宽度。 以上是二维卷积神经网络的计算公式。如果你还有其他问题,请继续提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值