Conv1d一维卷积(unfold)

前言

        这次我们来搓一个一维卷积,用到的方法是滑动窗口。

功能

        基础功能,未实现扩张(dilation)卷积和分组(groups)卷积。

原理

        对于每个(out_channel)卷积核,它的各个(in_channel)卷积核需要与输入x的各个(in_channel)通道对应做卷积:kernel与对应的输入x的切片(x[:,:,i * self.stride: i * self.stride + self.ker_size])相乘再相加。

        相乘指的是:比如1×3的kernel和1×3的kernel对应元素相乘

        相加指的是:完成上述相乘之后相加,得到一个标量,然后各个(in_channel)通道的标量再相加,得到一个标量。

unfold函数

        unfold是处理二维卷积的一个函数,这里我们把一维数据(batch_size,in_channel,in_length)当作二维数据(batch_size,in_channel,1,in_length)处理,这样卷积核的大小就是(1,kernel_size),步长就是(1, stride)。unfold之后的形状变成(batch_size,in_channel * ker_size,out_length)。

广播机制

        在做乘法时,卷积核的形状变成(out_channel,in_channel * ker_size),样本x的形状是(batch_size,in_channel * ker_size,out_length)。

        根据广播机制,这两个矩阵有一个维度相同都是in_channel * ker_size,二者可以相乘。且卷积核新增2个轴变为(1,out_channel,in_channel * ker_size,1)、样本x新增1个轴变为(batch_size,1,in_channel * ker_size,out_length)。

        在第三个维度对应元素相乘再相加,得到一个标量也就是降维,所以可以得到形状为(batch_size,out_channel,out_length)。

代码

class Conv1d(nn.Module):
    def __init__(self, in_channels:int, out_channels:int, kernel_size:int=3, 
                 stride:int=1, padding:int=0, bias:bool=True) -> None:
        super(Conv1d, self).__init__()
        self.stride = stride
        self.pad = padding
        self.ker_size = kernel_size        
        self.out_ch = out_channels
        self.kernel = nn.Parameter(nn.init.xavier_normal_(pt.randn(out_channels, in_channels, kernel_size)))
        self.bias = None
        if bias:
            self.bias = nn.Parameter(pt.zeros(out_channels))

    def forward(self, x):    
        # x:(batch_size, in_channel, in_len)
        # out_len = (x.shape[2] + 2*self.pad - self.ker_size)//self.stride + 1
        x = nn.functional.pad(x, (self.pad, self.pad), "constant", 0)
        
        # (batch_size, in_ch, 1, in_len) -> (batch_size, in_ch*ker_size, out_len)
        x_unfold = nn.functional.unfold(x[:,:,None,:], 
                                        kernel_size=(1, self.ker_size), stride=(1, self.stride))
        out = self.kernel.view(self.out_ch, -1).matmul(x_unfold)
                 
        if self.bias is not None:
            out += self.bias[None,:,None]
 
        return out

结语

        有问题欢迎在评论区讨论!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Burger~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值