纯Python实现卷积运算,无需使用Numpy

任意批量大小,但输出通道为1。

from typing import List

# 互相关计算
def crossCorrelation(x: List[List[int]], conv_kernel: List[List[int]]):
    res = 0
    for k in range(len(x)):
        for i in range(len(x[0])):
            for j in range(len(x[0][0])):
                res += conv_kernel[k][i][j] * x[k][i][j]
    return res


def conv2d(image: List[List[List[List[int]]]], conv_kernel: List[List[List[int]]], kernel_size=3, stride=2, pad=1):
    # b, c, h, w
    b, c, h, w = len(image), len(image[0]), len(image[0][0]), len(image[0][0][0])
    c_c, c_h, c_w = len(conv_kernel), len(conv_kernel[0]), len(conv_kernel[0][0])
    assert c == c_c
    # 计算输出特征图大小
    out_h = (h - kernel_size + 2 * pad) // stride + 1
    out_w = (w - kernel_size + 2 * pad) // stride + 1
    # 计算padding后的输入
    if pad > 0:
        pad_x = [[[[0] * (w + 2 * pad) for _ in range(h + 2 * pad)] for __ in range(c)] for ___ in range(b)]
        for bb in range(b):
            for cc in range(c):
                for i in range(pad, h + pad):
                    for j in range(pad, w + pad):
                        pad_x[bb][cc][i][j] = image[bb][cc][i - pad][j - pad]

    # 构建特征图 b h w
    out = [[[0] * out_w for _ in range(out_h)] for __ in range(b)]
    # 滑动窗口实现卷积运算
    for i in range(out_h):
        for j in range(out_w):
            # 生成在高度和宽度与卷积核同样大小的输入
            roi_x = [[[[0] * kernel_size for ___ in range(kernel_size)] for __ in range(c)] for _ in range(b)]
            for bb in range(b):
                for cc in range(c):
                    row = 0
                    for hh in range(i * stride, i * stride + kernel_size):
                        col = 0
                        for ww in range(j * stride, j * stride + kernel_size):
                            roi_x[bb][cc][row][col] = pad_x[bb][cc][hh][ww]
                            col += 1
                        row += 1
            # 在批量维度上执行互相关运算,输出通道为1
            for bb in range(len(roi_x)):
                out[bb][i][j] = crossCorrelation(roi_x[bb], conv_kernel)
    return out

测试代码

image = [[[[w + h * 3 + c * 3 for w in range(3)] for h in range(3)] for c in range(3)]]
conv_kernel = [[[1] * 3 for h in range(3)] for c in range(3)]
print(image)
print(conv_kernel)
print(conv2d(image, conv_kernel, stride=1))

如果想要多个输出通道,可以遍历函数conv2d,传入不同的卷积核。

# for conv_kernel in conv_kernels:
#     conv2d(image, conv_kernel, stride=1)

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值