import numpy as np
import torch
def ZY_Conv(img, in_channels, out_channels, kernels, bias, stride=1, padding=0):
# 得到参数
N, C, H, W = img.shape
kc,kci,kh, kw = kernels.shape
p = padding
#四周填充
if p:
img = np.pad(img, ((0, 0), (0, 0), (p, p), (p, p)), 'constant') # padding along with all axis
#得到输出的尺寸
out_h = (H + 2 * padding - kh) // stride + 1
out_w = (W + 2 * padding - kw) // stride + 1
#卷积
outputs = np.zeros([N, out_channels, out_h, out_w])
for n in range(N):
for out_c in range(out_channels):
for in_c in range(in_channels):
for h in range(out_h):
for w in range(out_w):
for x in range(kh):
for y in range(kw):
outputs[n][out_c][h][w] += img[n][in_c][h * stride + x][w * stride + y] * kernels[out_c][in_c][x][y]
#添加偏置
if in_c == in_channels - 1:
outputs[n][out_c][:][:] += bias[out_c]
# 转化为tensor格式,内部数据为float32的形式
outputs = torch.tensor(outputs, dtype=torch.float32)
return outputs
if __name__ == '__main__':
img = np.asarray(
[[
[
[0, 1, 2, 3, 4],
[1, 2, 3, 4, 5],
[2, 3, 4, 5, 6],
[3, 4, 5, 6, 7],
[4, 5, 6, 7, 8],
],
[
[1, 2, 3, 4, 5],
[2, 3, 4, 5, 6],
[3, 4, 5, 6, 7],
[4, 5, 6, 7, 8],
[5, 6, 7, 8, 9]
],
[
[2, 3, 4, 5, 6],
[3, 4, 5, 6, 7],
[4, 5, 6, 7, 8],
[5, 6, 7, 8, 9],
[6, 7, 8, 9, 0]
],
]]
)
kernels = np.asarray(
[
[
[
[0, 0, 0],
[0, 1, 0],
[0, 0, 0]
],
[
[0, 0, 0],
[0, 1, 1],
[0, 0, 0]
],
[
[0, 0, 0],
[0, 1, 0],
[0, 0, 1]
],
],
[
[
[1, 2, -1],
[0, 1, 0],
[0, 0, 0]
],
[
[0, 0, 0],
[0, 1, 1],
[0, 0, 0]
],
[
[0, 0, 0],
[0, 1, 0],
[0, 0, 1]
],
]
]
)
bias = np.asarray(
[-0.0722, -0.1841]
)
in_channels = 3
out_channels = 2
outputs = ZY_Conv(img, in_channels, out_channels, kernels, bias, stride=2, padding=1)
print(outputs)
卷积运行结果:
与pytorch自带卷积函数对比:
from __future__ import print_function, division
import torch
import os
import numpy as np
import torch.nn as nn
from zy_conv2 import ZY_Conv
img = np.asarray(
[[
[
[0.0, 1.0, 2.0, 3.0, 4.0],
[1.0, 2.0, 3.0, 4.0, 5.0],
[2.0, 3.0, 4.0, 5.0, 6.0],
[3.0, 4.0, 5.0, 6.0, 7.0],
[4.0, 5.0, 6.0, 7.0, 8.0],
],
[
[1.0, 2.0, 3.0, 4.0, 5.0],
[2.0, 3.0, 4.0, 5.0, 6.0],
[3.0, 4.0, 5.0, 6.0, 7.0],
[4.0, 5.0, 6.0, 7.0, 8.0],
[5.0, 6.0, 7.0, 8.0, 9.0]
],
[
[2.0, 3.0, 4.0, 5.0, 6.0],
[3.0, 4.0, 5.0, 6.0, 7.0],
[4.0, 5.0, 6.0, 7.0, 8.0],
[5.0, 6.0, 7.0, 8.0, 9.0],
[6.0, 7.0, 8.0, 9.0, 0.0]
],
]]
)
#将img转化为tensor类型
img= torch.tensor(img, dtype=torch.float32)
conv= nn.Conv2d(3, 2, 3, 1, 1)#设置输入通道为3,输出通道为2,卷积核大小为2,步长为2,零填充为1
#进行卷积操作,输出卷积核和偏置及卷积结果
out=conv(img)
print("卷积核:")
print(conv.weight)
print("偏执:")
print(conv.bias)
print("pytorch自带卷积函数运行结果:")
print(out)
#提取出卷积核与偏置矩阵
kernels=conv.weight
kernals=kernels.detach().numpy()
bias=conv.bias
bias=bias.detach().numpy()
in_channels = 3
out_channels = 2
#将提取出来的卷积核与偏置矩阵代入自编的卷积函数中,对比自编函数与pytorch自带函数的结果
outputs = ZY_Conv(img, in_channels, out_channels, kernels, bias, stride=1, padding=1)
print("自编卷积函数运行结果:")
print(outputs)
对比结果: