深度学习 (十八):多输入通道和多输出通道

引入

  本节主要介绍多输入通道或者多输出通道的卷积核 [ 1 ] ^{[1]} [1]。例如彩色图像中,其在高和宽 2 2 2个维度外还有RGB 3 3 3个颜色通道,即其能够表示为一个 3 × h × w 3 \times h \times w 3×h×w的多维数组。 3 3 3所对应的维则称为通道维。html

1 多输入通道

  当输入数据含多个通道时,须要构造一个输入通道数与输入数据的通道数相同的卷积核,从而可以与含多通道的输入数据作互相关运算。
  假设输入数据的通道数为 c i c_i ci,卷积核窗口形状为 k h × k w k_h \times k_w kh×kw。当 c i = 1 c_i = 1 ci=1时,卷积核只需包含一个形状为 k h × k w k_h \times k_w kh×kw的二维数组。当 c i > 1 c_i > 1 ci>1时,则须要为每个输入通道分配一个形状为 k h × k w k_h \times k_w kh×kw的核矩阵。
  将这 c i c_i ci个矩阵在输入通道进行连结,将获得一个形状为 c i × k h × k w c_i \times k_h \times k_w ci×kh×kw的卷积核。对于每个通道,都作一次互相关运算,再将结果的二维输出按通道相加,这个过程则是多通道输入数据与多通道卷积核的二维互相关运算 (简单说就是各个通道作一次互相关运算,再把结果相加):python

import torch
import warnings
warnings.filterwarnings('ignore')


def corr2d_multi_in(x, k):
    ret_mat = corr2d(x[0, :, :], k[0, :, :])
    for i in range(1, x.shape[0]):
        ret_mat += corr2d(x[i, :, :], k[i, :, :])

    return ret_mat


def corr2d(x, k):
    """ Correlation compute with 2-dimensional matrix. """
    m, n = k.shape
    ret_mat = torch.zeros((x.shape[0] - m + 1, x.shape[1] - n + 1))
    for i in range(ret_mat.shape[0]):
        for j in range(ret_mat.shape[1]):
            ret_mat[i, j] = torch.sum(x[i: i + m, j: j + n] * k)

    return ret_mat


if __name__ == '__main__':
    temp_x = torch.reshape(torch.range(1, 18), (2, 3, 3))
    temp_k = torch.tensor([[[0, 1], [2, 3]], [[1, 2], [3, 4]]])
    print(corr2d_multi_in(temp_x, temp_k))

  输出以下:web

tensor([[152., 168.],
        [200., 216.]])

2 多通道输出

  简单来讲,假设想要获取输出通道数为 c o c_o co的输出,那么只须要输入 c o × ⋯ c_o \times \cdots co×核矩阵, ⋯ \cdots 表示多通道输入中的核矩阵形状:数组

import torch
import warnings
warnings.filterwarnings('ignore')


def corr2d_multi_in_out(x, K):
    return torch.stack([corr2d_multi_in(x, k) for k in K])


def corr2d_multi_in(x, k):
    ret_mat = corr2d(x[0, :, :], k[0, :, :])
    for i in range(1, x.shape[0]):
        ret_mat += corr2d(x[i, :, :], k[i, :, :])

    return ret_mat


def corr2d(x, k):
    """ Correlation compute with 2-dimensional matrix. """
    m, n = k.shape
    ret_mat = torch.zeros((x.shape[0] - m + 1, x.shape[1] - n + 1))
    for i in range(ret_mat.shape[0]):
        for j in range(ret_mat.shape[1]):
            ret_mat[i, j] = torch.sum(x[i: i + m, j: j + n] * k)

    return ret_mat


if __name__ == '__main__':
    temp_x = torch.reshape(torch.range(1, 18), (2, 3, 3))
    temp_k = torch.tensor([[[0, 1], [2, 3]], [[1, 2], [3, 4]]])
    temp_k = torch.stack([temp_k, temp_k + 1, temp_k + 2])
    print(corr2d_multi_in_out(temp_x, temp_k))

  输出以下:svg

tensor([[[152., 168.],
         [200., 216.]],

        [[212., 236.],
         [284., 308.]],

        [[272., 304.],
         [368., 400.]]])

3 1 × 1 1 \times 1 1×1卷积层

  当多通道卷积层的卷积窗口形状为 1 × 1 1 \times 1 1×1时,称之为 1 × 1 1 \times 1 1×1卷积层,其中的卷积运算称为 1 × 1 1 \times 1 1×1卷积。因为使用了最小窗口,其失去了识别高和宽维度上相邻元素构成的模式的功能。实际上, 1 × 1 1 \times 1 1×1卷积的主要计算发生在通道维上
  下图展现了输入通道为 2 2 2,输出通道为 1 1 1 1 × 1 1 \times 1 1×1卷积核的互相关运算。值得注意的是,输入和输出具备相同的高和宽。输出中的每一个元素来自输入中在高和宽上相应位置的元素在不一样通道之间的按权重累加。
  假设将通道维看成特征维,将高和宽维度上的元素看做数据样本,那么** 1 × 1 1 \times 1 1×1卷积层的做用与全链接层等级**。
在这里插入图片描述学习

import torch
import warnings
warnings.filterwarnings('ignore')


def corr2d_multi_in_out_1x1(x, K):
    c_i, h, w = x.shape
    c_o = K.shape[0]
    x = x.view(c_i, h * w)
    K = K.view(c_o, c_i)
    y = torch.mm(K, x)
    return y.view(c_o, h, w)


def corr2d_multi_in_out(x, K):
    return torch.stack([corr2d_multi_in(x, k) for k in K])


def corr2d_multi_in(x, k):
    ret_mat = corr2d(x[0, :, :], k[0, :, :])
    for i in range(1, x.shape[0]):
        ret_mat += corr2d(x[i, :, :], k[i, :, :])

    return ret_mat


def corr2d(x, k):
    """ Correlation compute with 2-dimensional matrix. """
    m, n = k.shape
    ret_mat = torch.zeros((x.shape[0] - m + 1, x.shape[1] - n + 1))
    for i in range(ret_mat.shape[0]):
        for j in range(ret_mat.shape[1]):
            ret_mat[i, j] = torch.sum(x[i: i + m, j: j + n] * k)

    return ret_mat


if __name__ == '__main__':
    torch.manual_seed(1)
    temp_x = torch.rand(3, 3, 3)
    temp_k = torch.rand(2, 3, 1, 1)
    print(corr2d_multi_in_out_1x1(temp_x, temp_k))
    print(corr2d_multi_in_out(temp_x, temp_k))

  输出以下:ui

tensor([[[1.3486, 0.7537, 0.5711],
         [0.7351, 0.3631, 0.8528],
         [0.5868, 1.0130, 1.0915]],

        [[1.6899, 1.3451, 1.0295],
         [1.2994, 0.6615, 1.1993],
         [0.9793, 1.4752, 1.5119]]])
tensor([[[1.3486, 0.7537, 0.5711],
         [0.7351, 0.3631, 0.8528],
         [0.5868, 1.0130, 1.0915]],

        [[1.6899, 1.3451, 1.0295],
         [1.2994, 0.6615, 1.1993],
         [0.9793, 1.4752, 1.5119]]])

参考文献
[1] 李沐、Aston Zhang等老师的这本《动手学深度学习》一书。spa

本文同步分享在 博客“因吉”(CSDN)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。.net

相关文章
相关标签/搜索