普通卷积:
深度可分离卷积
分组卷积
扩张卷积
代码: 待更新
```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)