低效率实现卷积操作1
卷积核尺寸最好为奇数 3*3 、5*5 ,实际应用中大部分情况下卷积核的尺寸也一般都是奇数
#定义2D卷积函数
#此处需要非常注意的是 input_2Ddata是padding后的数据,而in_size是没有padding之前的图像的大小
def conv2D(input_2Ddata,kern,in_size,out_size,stride_h=1,stride_w=1):
kernel_size_h,kernel_size_w = kern.shape[0:2]
(h1,w1)=in_size
(h2,w2)=out_size
out_2Ddata=np.zeros(shape=out_size)
for i2,i1 in zip(range(h2),range(0,h1,stride_h)):
for j2, j1 in zip(range(w2), range(0, w1, stride_w)):
window=input_2Ddata[i1:i1+kernel_size_h,j1:j1+kernel_size_w]
out_2Ddata[i2,j2]=np.sum(kern*window)
return out_2Ddata
h1=32 #输入高度
w1=48 #输入宽度
d1=12 #输入深度
input_3Ddata=np.random.randn(h1,w1,d1)
#超参数
S=2 #步长 S 最常用1 偶尔用2
F=3 #卷积核尺寸
d2=24 #输出数据深度
P=(F-1)//2
h2=(h1-F+2*P)//S+1 #计算输出尺寸的两个公式
w2=(w1-F+2*P)//S+1
padding=np.zeros(shape=(h1+2*P,w1+2*P,d1))
padding[P:-P,P:-P]=input_3Ddata
output_3Ddata=np.zeros(shape=(h2,w2,d2))
kerns=np.random.randn(d2,F,F,d1) # 卷积核的尺寸需要额外注意 4D卷积核
bias =np.random.randn(d2) #1D 偏执 每个卷积核生成的特征维增加同一个偏执--即一个数
#对d2个卷积核计算卷积 d2个卷积核代表卷积出的数据最后的维度是d2也就是d2个特征,就像RGB图像有三个特征维一样
for m in range(d2):
for k in range(d1): #数据数据的每一个维度
input_2Ddata=padding[:,:,k]
kern=kerns[m,:,:,k]
output_3Ddata[:,:,m] += conv2D(input_2Ddata,kern,in_size(h1,w1),out_size=(h2,w2),stride_h=S,stride_w=S)
output_3Ddata[:,:,m]+=bias[m]