二维卷积运算

字数 214阅读 783

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

import numpy as np
from copy import deepcopy

def corr2d(X, K):
    '''
    2D 卷积运算(实际是互相关)
    '''
    h, w = K.shape
    Y = np.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、核数组 K 来验证二维互相关运算的输出:

X = np.array([[7, 1, 4, 3], [3, 9, 5, 1], [5, 1, 8, 9], [7, 9, 3, 1]])
K = np.array([[7, 1], [2, 3]])

corr2d(X, K)
array([[83., 44., 44.],
       [43., 94., 79.],
       [77., 42., 74.]])

为了提高运算速度,我们可用矩阵乘法来计算卷积:

矩阵乘法来计算卷积

class Exchange:
    def exchangeTwo(self, L, i=0, j=-1):
        '''
        交换列表中的元素顺序
        '''
        L[i], L[j] = L[j], L[i]

    def loopInterchange(self, L, offset=0):
        '''
        循环列表
        '''
        n = len(L)
        assert offset < n
        for i in range(n):
            self.exchangeTwo(L, offset, i)

    def corr2d(self, X, K):
        '''
        使用矩阵乘法计算 2D 卷积
        '''
        X_ = X.flatten()
        h, w = K.shape
        A = np.zeros_like(X)
        A[:w, :h] = K
        A_ = A.flatten().tolist()
        h_ = X.shape[0] - h + 1
        w_ = X.shape[1] - w+1
        L = deepcopy(A_)
        M = []
        for i in range(w_):
            for j in range(w_):
                M.append(deepcopy(L))
                self.loopInterchange(L)
                continue
            self.loopInterchange(L)
        Y = np.dot(np.array(M), X_)
        Y_ = Y.reshape((h_, w_))
        return Y_
ex = Exchange()
ex.corr2d(X, K)
array([[83, 44, 44],
       [43, 94, 79],
       [77, 42, 74]])

这种计算方式是 caffe 的实现方式。

在频域计算卷积

公式

f * g \Leftrightarrow F \cdot G

大体是通过 FFT 转换到频域做乘法,然后再变换回去得到卷积后的结果。Torch、Theano 和 cudnn 使用的卷积计算方式。

推荐阅读更多精彩内容