python实现conv(卷积),dept_conv(通道卷积),batchnorm(批量归一化)的前向过程(一)

神经网络已经在各行各业都得到了普遍的应用,然而在工程落地以及一些验证过程中有必要自己实现一些常用的模块,比如卷积,池化,批量归一化等常规的神经网络模块。尽管现在都是各种调库的天下,自己在做相关工程发现了解和实现这些基本模块还是很有必要的,不仅加深自己的理解,更加容易工程落地。神经网络的基础这里就不过多介绍,直接上实现代码。
卷积实现:输入数据排布[N,chin,dim_inh,dim_inw],权重的排布[chout,chin,kernelh,kernelw],输出数据排布[N,chout,dim_outh,dim_outw],实现程序也给出了输入数据,权重,输出数据都为二维数据的情形。x:[N,chin * dim_inh * dim_inw],w:[chout,chin * kernelh * kernelw],result:[N,chout * dimouth * dimoutw]。实现示意图如下:
在这里插入图片描述

#四维实现
class predict_cnn(nn.Module):
    def __init__(self, stride=1, padding=0):
        super(predict_cnn, self).__init__()
        self.padding = padding
        self.stride = stride

    def forward(self, x, w, b):
        w = w.detach().numpy()
        b = b.detach().numpy()

        ch_im_in = w.shape[1]
        ch_im_out = w.shape[0]
        kernel = w.shape[2]

        dim_im_in_y = x.shape[2]
        dim_im_in_x = x.shape[3]

        dim_im_out_y = int((dim_im_in_y - kernel + 2 * self.padding) / self.stride) + 1
        dim_im_out_x = int((dim_im_in_x - kernel + 2 * self.padding) / self.stride) + 1
        result = np.zeros((ch_im_out, dim_im_out_y, dim_im_out_x))

        for co in range(ch_im_out):
            for oy in range(dim_im_out_y):
                for ox in range(dim_im_out_x):
                    conv_out = b[co].copy()
                    for m in range(kernel):
                        for n in range(kernel):

                            row = self.stride * oy + m - self.padding
                            col = self.stride * ox + n - self.padding

                            if row < 0 or row >= dim_im_in_y or col < 0 or col >= dim_im_in_x:
                                pass
                            else:
                                for ci in range(ch_im_in):
                                    conv_out += x[0, ci, row, col] * w[co, ci, m, n]

                    result[co][oy][ox] = conv_out

        return result

#二维实现
class predict_cnn_dim2(nn.Module):
    def __init__(self, stride=1, padding=0):
        super(predict_cnn_dim2, self).__init__()
        self.padding = padding
        self.stride = stride

    def forward(self, x, w, b):
        w = w.detach().numpy()
        b = b.detach().numpy()

        ch_im_in = w.shape[1]
        ch_im_out = w.shape[0]
        kernel = w.shape[2]

        dim_im_in_y = x.shape[2]
        dim_im_in_x = x.shape[3]

        dim_im_out_y = int((dim_im_in_y - kernel + 2 * self.padding) / self.stride) + 1
        dim_im_out_x = int((dim_im_in_x - kernel + 2 * self.padding) / self.stride) + 1
        result = np.zeros((ch_im_out, dim_im_out_y * dim_im_out_x))

        w = w.reshape(w.shape[0],-1)
        x = x.squeeze(0)
        x = x.reshape(x.shape[0],-1)

        for co in range(ch_im_out):
            for oy in range(dim_im_out_y):
                for ox in range(dim_im_out_x):
                    conv_out = b[co].copy()
                    co_idx = oy * dim_im_out_x + ox
                    for m in range(kernel):
                        for n in range(kernel):

                            row = self.stride * oy + m - self.padding
                            col = self.stride * ox + n - self.padding
                            ci_idx = row * dim_im_in_x + col

                            if row < 0 or row >= dim_im_in_y or col < 0 or col >= dim_im_in_x:
                                pass
                            else:
                                for ci in range(ch_im_in):
                                    w_idx = ci * kernel * kernel + m * kernel + n
                                    conv_out += x[ci, ci_idx] * w[co, w_idx]

                    result[co,co_idx] = conv_out

        return result

通道卷积:实现示意图如下
在这里插入图片描述
可以看到通道卷积要求输入数据的通道和输出通道数一致,权重维度:[chout,1,kernelh,kernelw],输入数据:[N,chin,dim_inh,dim_inw],输出数据:[N,chout,dim_outh,dim_outw],此时要求chin = chout,且在前向推理一般N=1。这里代码实现主要是针对前向推理,当N=1时,将输入数据的维度0,1转换一下,此时的通道卷积就等价于常规卷积,即相当于输入数据的通道chin = 1,样本N原来的通道数。具体代码实现如下:

#四维实现
class dpw_cnn(nn.Module):
    def __init__(self, stride=1, padding=0):
        super(dpw_cnn, self).__init__()
        self.padding = padding
        self.stride = stride

    def forward(self, x, w, b):
        w = w.detach().numpy()
        b = b.detach().numpy()

        ch_im_in = w.shape[1]
        ch_im_out = w.shape[0]
        kernel = w.shape[2]

        dim_im_in_y = x.shape[2]
        dim_im_in_x = x.shape[3]

        dim_im_out_y = int((dim_im_in_y - kernel + 2 * self.padding) / self.stride) + 1
        dim_im_out_x = int((dim_im_in_x - kernel + 2 * self.padding) / self.stride) + 1
        result = np.zeros((ch_im_out, dim_im_out_y, dim_im_out_x))

        for co in range(ch_im_out):
            for oy in range(dim_im_out_y):
                for ox in range(dim_im_out_x):
                    conv_out = b[co].copy()
                    for m in range(kernel):
                        for n in range(kernel):

                            row = self.stride * oy + m - self.padding
                            col = self.stride * ox + n - self.padding

                            if row < 0 or row >= dim_im_in_y or col < 0 or col >= dim_im_in_x:
                                pass
                            else:
                                for ci in range(ch_im_in):
                                    conv_out += x[0, co, row, col] * w[co, ci, m, n]

                    result[co][oy][ox] = conv_out

        return result

#二维实现
class dpw_cnn_dim2(nn.Module):
    def __init__(self, stride=1, padding=0):
        super(dpw_cnn_dim2, self).__init__()
        self.padding = padding
        self.stride = stride

    def forward(self, x, w, b):
        w = w.detach().numpy()
        b = b.detach().numpy()

        ch_im_in = w.shape[1]
        ch_im_out = w.shape[0]
        kernel = w.shape[2]

        dim_im_in_y = x.shape[2]
        dim_im_in_x = x.shape[3]

        dim_im_out_y = int((dim_im_in_y - kernel + 2 * self.padding) / self.stride) + 1
        dim_im_out_x = int((dim_im_in_x - kernel + 2 * self.padding) / self.stride) + 1
        result = np.zeros((ch_im_out, dim_im_out_y * dim_im_out_x))

        w = w.reshape(w.shape[0],-1)
        x = x.squeeze()
        x = x.reshape(x.shape[0],-1)

        for co in range(ch_im_out):
            for oy in range(dim_im_out_y):
                for ox in range(dim_im_out_x):
                    conv_out = b[co].copy()
                    co_idx = oy * dim_im_out_x + ox
                    for m in range(kernel):
                        for n in range(kernel):

                            row = self.stride * oy + m - self.padding
                            col = self.stride * ox + n - self.padding
                            ci_idx = row * dim_im_in_x + col

                            if row < 0 or row >= dim_im_in_y or col < 0 or col >= dim_im_in_x:
                                pass
                            else:
                                for ci in range(ch_im_in):
                                    w_idx = ci * kernel * kernel + m * kernel + n
                                    conv_out += x[co, ci_idx] * w[co, w_idx]

                    result[co,co_idx] = conv_out

        return result

全连接层:全连接最为直观,也很容易理解,实质就是两个矩阵相乘。实现过程如下:

class predict_fc(nn.Module):
    def __init__(self):
        super(predict_fc, self).__init__()

    def forward(self, x, w, b):
        w = w.detach().numpy()
        b = b.detach().numpy()
        # x = x.numpy()
        x = np.matmul(w, x.T).squeeze() + b

        return x

后续会进一步的讲解神经网络相关基础实现,这里只是做个铺垫,bn层在后续会讲解。希望可以帮助到大家,不当之处请指教,谢谢!
这里附上一个例子python卷积,通道卷积实现

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值