深度学习原理——卷积计算

1 卷积计算

这个就是普通的卷积计算原理,输入有3个通道,输出有2个通道,没加激活函数等。
在这里插入图片描述
如上图所示,输入有3个通道,输出有2个通道,也就是有2个卷积核(一个卷积核就是322)。对于每个卷积核,先在输入3个通道分别作卷积,再将3个通道结果加起来得到卷积输出。所以对于某个卷积层,无论输入图像有多少个通道,输出图像通道数总是等于卷积核数量!
(1)参数量就是:输入通道数卷积核的宽度卷积核的高度*输出通道数
(2)计算量:补0和不补0不一样
(3)总结:
<1>卷积核是3维的,其中一个维度是输入通道,另外两个维度是卷积核的宽度和高度;卷积核中一般不说长度,说高度。
<2>输出图像通道数总是等于卷积核数量。
参考:https://zhuanlan.zhihu.com/p/31426458
(4)卷积核的参数一般4个,
《1》卷积核大小,也就是宽,高;
《2》pad补0与否;
《3》跨度;
《4》输出通数。

(1)卷积核就是一个参与运算的二维矩阵,对应位置相乘再相加。3个参数,大小-跨度-padding边缘填充
(2)卷积运算原理,最基本的就是单通道对应一个输出通道,那就用一个二维矩阵(比如33)对输入图像进行运算,提取图像特征,原理如下图。但是单通道输入得到多通道(k个通道)输出,就需要k个滤波器,每个滤波器是就是一个二维的33矩阵,也就是每个滤波器包含一个卷积核。但是当输入是多通道(t)得到多通道(k个通道)输出,那这次卷积就包括k个滤波器,每个滤波器就是一个3维矩阵,33t,每个滤波器就包含t个卷积核。上面输出通道是k,那就得到了k个特征图,每个输出通道就是一个特征图。具体深入理解请看(多通道图像卷积过程及计算方式https://blog.csdn.net/briblue/article/details/83063170)

在这里插入图片描述

图 k 单通道卷积
在这里插入图片描述

(2)输入是一个5x5x3的矩阵,有三个通道。filter是一个3x3x3的矩阵。首先,filter中的每个卷积核(记住卷积核是3维的,不是2维的)分别应用于输入层的三个通道。执行三次卷积,产生3个3x3的通道。

然后,这三个通道相加(矩阵加法),得到一个3x3x1的单通道。这个通道就是在输入层(5x5x3矩阵)应用filter(3x3x3矩阵)的结构。
在这里插入图片描述

(3)filter和kernel之间的不同很微妙。很多时候,它们可以互换,所以这可能造成我们的混淆。那它们之间的不同在于哪里呢?一个"kernel"更倾向于是2D的权重矩阵。而’filter"则是指多个Kernel堆叠的3D结构。如果是一个2D的filter,那么两者就是一样的。但是一个3Dfilter, 在大多数深度学习的卷积中,它是包含kernel的。每个卷积核都是独一无二的,主要在于强调输入通道的不同方面。

2 卷积

在这里插入图片描述
在这里插入图片描述

3 填充

在这里插入图片描述

4 步长

在这里插入图片描述

5 多通道卷积和多卷积核

在这里插入图片描述

6 卷积参数计算

在这里插入图片描述

7 设计卷积

在这里插入图片描述

8 代码实现

在这里插入图片描述

def conv_(img, conv_filter):
    """
    卷积核计算操作
    :param img: 图片数据
    :param conv_filter: 卷积核
    :return:
    """
    # 1、获取卷积核的大小
    filter_size = conv_filter.shape[1]
    # 初始化卷积后的结果,给个较大的输出结果
    result = np.zeros((img.shape))
    # 2、对图片进行循环使用卷积操作(获取当前区域并使用过滤器进行相乘操作.)
    # (1)r和c为特征图的下表,从0到特征图输出大小
    for r in np.uint16(np.arange(filter_size/2.0, img.shape[0]-filter_size/2.0+1)):
        for c in np.uint16(np.arange(filter_size/2.0, img.shape[1]-filter_size/2.0+1)):
            # 取出过滤器大小的图片区域,从图片左上角开始
            curr_region = img[r-np.uint16(np.floor(filter_size/2.0)):r+np.uint16(np.ceil(filter_size/2.0)),
                              c-np.uint16(np.floor(filter_size/2.0)):c+np.uint16(np.ceil(filter_size/2.0))]
            # 图片当前区域与卷积核进行线性相乘
            curr_result = curr_region * conv_filter
            # 结果求和并保存,按照下表保存
            conv_sum = np.sum(curr_result)
            result[r, c] = conv_sum

    # 裁剪矩阵
    final_result = result[np.uint16(filter_size/2.0):result.shape[0]-np.uint16(filter_size/2.0),
                          np.uint16(filter_size/2.0):result.shape[1]-np.uint16(filter_size/2.0)]
    return final_result


def conv(img, conv_filter):
    """
    卷积过程实现
    :param img: 图像
    :param conv_filter: 卷积过滤器
    :return:
    """
    # 1、输入的参数大小做异常检测
    # 检查输入的图片和卷积核是否一样大小
    if len(img.shape) != len(conv_filter.shape) - 1:
        print("Error: Number of dimensions in conv filter and image do not match.")
        exit()
    # 检查输入的图片的通道数和卷积的深度一样
    if len(img.shape) > 2 or len(conv_filter.shape) > 3:
        if img.shape[-1] != conv_filter.shape[-1]:
            print("Error: Number of channels in both image and filter must match.")
            sys.exit()
    # 检查是否过滤器的长宽一样
    if conv_filter.shape[1] != conv_filter.shape[2]:
        print('Error: Filter must be a square matrix. I.e. number of rows and columns must match.')
        sys.exit()
    # 检查过滤器的维度是奇数
    if conv_filter.shape[1] % 2 == 0:
        print('Error: Filter must have an odd size. I.e. number of rows and columns must be odd.')
        sys.exit()

    # 2、初始化一个空的特征图来装入计算的结果
    feature_maps = np.zeros((img.shape[0]-conv_filter.shape[1]+1,
                                img.shape[1]-conv_filter.shape[1]+1,
                                conv_filter.shape[0]))

    # 3、图片的卷积完整操作(分别使用每一个过滤器进行过滤操作)
    for filter_num in range(conv_filter.shape[0]):
        print("Filter ", filter_num + 1)
        # 获取当前的filter参数
        curr_filter = conv_filter[filter_num, :]

        # 当前filter进行卷积核计算操作
        if len(curr_filter.shape) > 2:
            # 对图片的每个channel进行卷积运算
            conv_map = conv_(img[:, :, 0], curr_filter[:, :, 0])
            for ch_num in range(1, curr_filter.shape[-1]):
                conv_map = conv_map + conv_(img[:, :, ch_num], curr_filter[:, :, ch_num])
        else:
            # 只有一个filter的情况
            conv_map = conv_(img, curr_filter)
        feature_maps[:, :, filter_num] = conv_map
    return feature_maps

# 使用过程
# 1、定义这层有两个卷积核,每个大小3x3(例子默认对黑白图片进行计算),默认一个步长,不零填充
l1_filter = np.zeros((2,3,3))
# 初始化参数
l1_filter[0, :, :] = np.array([[[-1, 0, 1], 
                                   [-1, 0, 1], 
                                   [-1, 0, 1]]])
l1_filter[1, :, :] = np.array([[[1,   1,  1], 
                                   [0,   0,  0], 
                                   [-1, -1, -1]]])
# 卷积计算
l1_feature_map = cnn.conv(img, l1_filter)
  • 28
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

晓码bigdata

如果文章给您带来帮助,感谢打赏

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值