Simple implementation of conv2d

directly on the code

For pre-content, please refer to: simple implementation of conv1d

def myconv2d(infeat, convkernel, padding=0, stride=1):
    b, c, h, w = len(infeat), len(infeat[0]), len(infeat[0][0]), len(infeat[0][0][0])
    out_c, in_c, kh, kw = len(convkernel), len(convkernel[0]), len(convkernel[0][0]), len(convkernel[0][0][0])
    # 不使用分组卷积,c = in_c
    # 卷积核为正方形,kh = kw
    
    res = [[[[0] * (w-kw+1) for _ in range(h-kh+1)] for _ in range(out_c)] for _ in range(b)]
    # 最终输出形状:b*out_c*(h-kh+1)*(w-kw+1)
    # print(len(res), len(res[0]), len(res[0][0]), len(res[0][0][0]))
    for i in range(b):
        # 关于batch,目前只能串行完成
        
        for j in range(out_c):
            # 计算每一组的结果
            
            for m in range(c):
                for n in range(h-kh+1):
                    for g in range(w-kw+1):
                        # 计算每一个位置的值
                        
                        ans = 0
                        for k1 in range(kh):
                            for k2 in range(kw):
                                ans += infeat[i][m][n+k1][g+k2] * convkernel[j][m][k1][k2]
                        res[i][j][n][g] += ans
    return res


# 我的卷积
infeat = [[[[1,0,2,2,2], [0,0,0,0,0], [2,0,2,2,2], [1,0,0,0,0], [1,0,0,2,1]],
           [[1,0,1,0,1], [0,0,0,0,1], [0,0,2,0,0], [2,0,0,0,0], [0,0,1,0,0]],
           [[0,2,2,0,0], [0,0,0,0,1], [1,1,2,0,2], [2,0,0,0,0], [0,1,1,0,1]]]]

convkernel = [[[[1,0,0], [-1,0,0], [0,-1,1]],
               [[-1,-1,0], [-1,-1,1], [1,0,0]],
               [[1,1,0], [0,-1,1], [1,1,1]]],
              
              [[[1,-1,0], [-1,0,0], [0,1,-1]],
               [[0,1,-1], [0,0,0], [0,1,1]],
               [[0,-1,0], [1,1,-1], [-1,0,1]]]]
outfeat = myconv2d(infeat, convkernel)
print(outfeat)


# pytorch源码计算结果
from torch.nn.functional import conv2d
import torch
import numpy

infeat = torch.tensor(numpy.array(infeat))
convkernel = torch.tensor(numpy.array(convkernel))

outfeat_pytorch = conv2d(infeat, convkernel)
print(outfeat_pytorch)

The output is as follows, which is the same as the official calculation result:

[[[[8, 6, 11], [5, -4, -2], [3, 5, 4]], [[-1, -2, -2], [-4, 3, -3], [2, -4, 1]]]]
tensor([[[[ 8,  6, 11],
          [ 5, -4, -2],
          [ 3,  5,  4]],

         [[-1, -2, -2],
          [-4,  3, -3],
          [ 2, -4,  1]]]], dtype=torch.int32)

think

In pytorch, it is directly multiplied and added according to the sliding window. Unlike the traditional convolution definition (defold, shift, multiply, add), there is no defold operation

Guess you like

Origin blog.csdn.net/qq_45510888/article/details/123460943