在pytorch中的卷积操作

卷积操作:
# 1. 卷积核的输入通道数与输入数据的通道数保持一致,所以卷积核的对应通道与输入数据的对应通道进行卷积操作,以卷积核conv_i为例:
# 2. 卷积核conv_i的对应通道与输入数据对应通道 进行 对应位置元素 的乘法,即用乘法操作“*”,得到一个与卷积核形状一样的矩阵M
# 3. 将第2步中卷积结果矩阵M中的所有元素相加,得到卷积核conv_i在当前通道的卷积结果:标量su_i
# 4. 卷积核conv_i的所有通道的卷积结果su_i相加之后得到该卷积核conv_i对输入数据的最终卷积结果。

pytorch中定义的卷积核形状:

conv = nn.Conv2d(in_channels=3,out_channels=2,kernel_size=(2,2))
print(conv.weight.size())  #torch.Size([2, 3, 2, 2])

#-*- coding:utf-8 -*-
#Author LJB Create on 2021/8/27
import torch
import torch.nn as nn
import numpy as np


class Test(nn.Module):
    def __init__(self):
        super(Test,self).__init__()
        self.conv = nn.Conv2d(in_channels=3,out_channels=2,kernel_size=(2,2),padding=0,bias=False)
        conv_w = self.conv.weight
        print(conv_w.size())  #torch.Size([2, 3, 2, 2])
    def forward(self,data):
        return self.conv(data)

#自定义的“卷积”:不是真正的卷积,因为此函数的卷积操作中卷积核的大小与输入数据的H,W完全一样
#此函数为了证明一个卷积核的运算过程:
# 1. 卷积核的输入通道数与输入数据的通道数保持一致,所以卷积核的对应通道与输入数据的对应通道进行卷积操作,以卷积核conv_i为例:
# 2. 卷积核conv_i的对应通道与输入数据对应通道 进行 对应位置元素 的乘法,即用乘法操作“*”,得到一个与卷积核形状一样的矩阵M
# 3. 将第2步中卷积结果矩阵M中的所有元素相加,得到卷积核conv_i在当前通道的卷积结果:标量su_i
# 4. 卷积核conv_i的所有通道的卷积结果su_i相加之后得到该卷积核conv_i对输入数据的最终卷积结果。
def conv(data,weight):
    '''
    卷积核大小与输入数据的H,W完全一样
    :param data: 形状[batchsize,channels,H,W]
    :param weight: 形状[out_channels,in_channels,H,W],其中in_channels与data的channels保持一致进行卷积操作
    :return:
    '''
    out_channels,in_channels,H,W = weight.size()
    conv_result = []
    for d in data:
        conv_channel = []
        for out_c in range(out_channels):
            r = 0.
            for in_c in range(in_channels):
                w = weight[out_c][in_c]
                d_c = d[in_c]
                su = d_c*w  #两个形状相同的矩阵对应元素相乘,得到一个形状也完全一样的矩阵
                r += torch.sum(su)  #矩阵所有元素之和,是标量
            conv_channel.append([[r.data.item()]])
        conv_result.append(conv_channel)
    return np.array(conv_result)

if __name__=='__main__':
    #模拟输入数据 batchsize=8,channel=3,H=2,W=2
    test_data = torch.randint(0,9,(8,3,2,2)).float()

    T = Test()
    T.eval()
    with torch.no_grad():
        init_weight = torch.Tensor([[[[.1,.2],[.3,.4]],[[.5,.6],[.7,.8]],[[.9,.1],[.2,.3]]],
                                    [[[.2,.1],[.4,.3]],[[.6,.5],[.8,.7]],[[.6,.5],[.7,.8]]]])
        T.conv.weight = nn.Parameter(init_weight)  #手动初始卷积核的权重
        r = T(test_data)

    conv_res = conv(test_data,init_weight)
    print('+++ my conv:',conv_res.tolist())
    print('normal conv:',r.tolist())
    print(np.shape(conv_res))
    print(r.size())

你可能感兴趣的:(在pytorch中的卷积操作)