深度学习笔记7:各种类型卷积图解

普通卷积:

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

深度可分离卷积

在这里插入图片描述

在这里插入图片描述

分组卷积

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

扩张卷积

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

代码: 待更新

```python
""" 不同convlution的实现。"""
# -*- coding: utf-8 -*-

# time : 2021/5/5 10:15
# task: 
import numpy as np
import matplotlib.pyplot as plt
import time
import sys
import os
from utils import OptimizerInitializer,WeightInitializer,ActivationInitializer
from utils import  LayerBase, CrossEntropy, FullyConnected, minibatch,Softmax
from collections import OrderedDict


""" 定义一个pading计算函数,可以使输入和输出的特征图尺度大小一致"""
def caculate_paddims_same_2Dconv(X_shape, out_dim, kernel_shape, stride, dilation=1):
    """
    param :
    :param X_shape: 输入特征图的尺度
    :param out_dim: 输出特征图尺度
    :param kernel_shape: 卷积核大小
    :param stride:
    :param dilation: 空洞因子
    :return: 上下左右的pading值。
    """
    d = dilation
    fr, fc = kernel_shape
    out_r, out_c = out_dim
    nex, in_r, in_c, in_chanle = X_shape # 分表表示输入输出以及通道值。
    # 先计算 空洞卷积的空洞卷积值。
    fr_x, fc_x = fr + (fr-1)*(d-1), fc + (fc-1)*(d-1)
    # compute pad value.
    # formuler : [w + 2p - (k+(k-1)*(d-1))]/s +1 = outw
    # p = [(outw -1) * s + fr_x - w ]/2
    pr,pc =int( ((out_r -1) * stride + fr_x - in_r )/2), int( ((out_c -1) * stride + fc_x - in_c )/2)

    # 上边得到的pr,pc 可能会小一个,因为如果需要扩张的pading总数为奇数,两边分一下就成为了0.5,取整后,就舍弃了
    # 一个pad单位,所以需要进行验证和修正。
    # use pr,pc compute the outsize, and test the outsize is eq with the needed outsize.
    n_out_r, n_out_c = int((in_r+ 2 * pr - fr + stride)/stride), int((in_c+ 2 * pc - fc + stride)/stride)

    # panduan
    pr1,pr2 = pr,pr # 上下的扩张大小。
    if n_out_r == out_r -1 :# 如果相等就直接返回了,如果差1就在下边加上一个,否则报错。
        pr1,pr2 = pr, pr+1
    elif n_out_r != out_r:
        raise AssertionError  # 声明错误。

    pc1, pc2 = pc, pc  # 上下的扩张大小。
    if n_out_c == out_c - 1:  # 如果相等就直接返回了,如果差1就在下边加上一个,否则报错。
        pc1, pc2 = pc, pc + 1
    elif n_out_c != out_c:
        raise AssertionError  # 声明错误。

    return  (pr1,pr2,pc1,pc2) # 上下,左右的扩张值。


"""  对输入X 进行pading, X .shape : batchsize, h,w, num_channel"""
def Pad2D(X, pad, kernel_shape=None, stride=None, dilation=1):
    """
    函数说明:对输入X 进行pading
    :param X:  shape : bz, h,w,n_c
    :param pad: int tuple, "same", valid
    :param kernel_shape:
    :param stride:
    :param dilation:
    :return:
    """
    p = pad
    if isinstance(p, int):
        p = (pad,pad,pad,pad)

    if isinstance(p, tuple):
        X_pad = np.pad(X,
                       pad_width=((0,0), (pad[0], pad[1]), (pad[2],pad[3]),(0,0)),
                       mode="constant",
                       constant_values=0,
                       )

    # 如果pad 是字符 same,或者valid
    if pad == "same" and kernel_shape and stride is not None:
        p = caculate_paddims_same_2Dconv(X.shape, X.shape[1:3], kernel_shape, stride, dilation)
        X_pad, p = Pad2D(X,p) # 这里使用递归调用方法。

    if pad == "valid":
        p = (0,0,0,0)
        X_pad , p = Pad2D(X,p)

    return X_pad, p



""" 定义2维度卷积的非矩阵操作"""
def Conv2d(X,W, stride, pad, dilation=1):
    """
    参数说明:
    :param X: 输入,batchsize, in_rows, in_cols, in_channels.
    :param W: 权重,shape: kernel_row, kernel_col, in_channels, out_channels.
    :param stride:
    :param pad: 填充,元组,或者 same,vilad
    :param dilation: 扩张率。
    :return: 卷积的结果,shape: batchsize, out_rows, out_cols, outchannels
    """
    s, d = stride, dilation
    X_pad, p = Pad2D(X, pad, W.shape[:2], stride=s, dilation=dilation)
    pr1, pr2, pc1, pc2 = p
    print(p)
    x_samples, x_rows, x_cols, in_channels = X.shape
    fr,fc,in_channels,out_channels = W.shape
    # 先计算输出的形状:
    # 扩张情况下
    _fr, _fc = fr + (fr-1)*(d-1), fc + (fc-1)*(d-1)
    out_rows, out_cols = int((x_rows + pr1 + pr2 - _fr + s)/s) , int((x_cols + pc1 + pc2 +s - _fc)/s)
    # 然后构造输出矩阵,默认0填充,并计算各个位置的值。
    Z = np.zeros(shape=(x_samples, out_rows, out_cols, out_channels))
    # print(Z.shape)
    start_time = time.time()
    for m in range(x_samples):
        for c in range(out_channels):
            for i in range(out_rows):
                for j in range(out_cols):
                    # 以i,j 像素为中心进行卷积乘法。
                    i0, i1 = i*s, i*s + _fr  # 当前位置加上卷积核的大小。
                    j0, j1 = j*s, j*s + _fc
                    # 从xpad 中切片窗口。
                    window = X_pad[m, i0:i1:d, j0:j1:d, :] # 第m个样本: 所有输入通道,shape : k,k,inchannel.
                    Z[m,i,j,c] =np.sum( window * W[:,:,:,c])   # w[:,:,:,c] shape : k,k,inchanel.
                    # 各个通道的和,并且是个标量。
    t = time.time() - start_time
    print(f"compute timing used {t}")
    return Z


# test the conv2d :
x = np.random.random(size=(10,32,32,3)) # 3 通道的,batchsize 10, 大小为 32 32
w = np.random.random(size=(3,3,3,64)) # 输入为3通道,输出为64通道,kernel 3 3

# print(x.shape)
# print(w.shape)

conv_result = Conv2d(x,w, stride=2, pad="same", dilation=1)
print(conv_result.shape)
# (16, 17, 16, 17)
# compute timing used 4.634718894958496
# (10, 32, 32, 64)



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值