nn.Unfold 批量切片、F.conv2d 指定卷积核二维卷积操作、nn.Conv2d卷积层

nn.Unfold 批量切片、F.conv2d 指定卷积核二维卷积操作、nn.Conv2d卷积层


文章目录

  • nn.Unfold 批量切片、F.conv2d 指定卷积核二维卷积操作、nn.Conv2d卷积层
  • 前言
  • 1、nn.Unfold 批量切片
  • 2、F.conv2d 指定卷积核二维卷积操作
    • 3、nn.Conv2d卷积层


前言

这是我最近遇到的一个问题,对图片每个像素点进行遍历,并且对每个像素点所在的33区域进行数据计算,最开始我是用for来写的,因为for循环是一个框一个框的遍历计算,速度很慢,电脑计算量也没有上去。为了解决这个问题,我百度了很多次,摸索出了以下方法,用nn.Unfold 批量切片,再用矩阵计算所对应的33区域,最后用F.conv2d 指定卷积核二维卷积进行数据整合。大致思路就是这样。


1、nn.Unfold 批量切片

参数说明:
kernel_size:滑块大小
dilation:控制滑动过程中所跨越元素的个数
padding:填充
stride:步长

unfold = nn.Unfold(kernel_size=(3, 3), dilation=1, padding=0, stride=(1, 1))
inp_unf = unfold(input)

平时我们经常会用到for循环进行切片操作,选取数组一定区域的数据。比如需要对一张图片遍历每个像素点所在的3*3区域,用for循环的来依次切片速度会很慢。通过nn.Unfold函数可以把所需要遍历的区域的数值提取出来放到一个新的数组里。举例如下:

import torch
import torch.nn as nn
# inp大小 [1, 1, 5, 6]
inp = torch.tensor([[[[1.0, 2, 3, 4, 5, 6],
                      [7, 8, 9, 10, 11, 12],
                      [13, 14, 15, 16, 17, 18],
                      [19, 20, 21, 22, 23, 24],
                      [25, 26, 27, 28, 29, 30],
                      ]]])
# 实例化 3*3滑块依次遍历inp,一共有12个3*3的框
unfold = nn.Unfold(kernel_size=(3, 3), dilation=1, padding=0, stride=(1, 1))
inp_unf = unfold(inp)
print('inp=',inp.shape,inp)
print('inp_unf=',inp_unf.shape,inp_unf)

inp= torch.Size([1, 1, 5, 6])
tensor([[[[ 1., 2., 3., 4., 5., 6.],
[ 7., 8., 9., 10., 11., 12.],
[13., 14., 15., 16., 17., 18.],
[19., 20., 21., 22., 23., 24.],
[25., 26., 27., 28., 29., 30.]]]])
inp_unf= torch.Size([1, 9, 12])
每一竖排代表一个3*3区域的框, 一共12个
tensor([[[ 1., 2., 3., 4., 7., 8., 9., 10., 13., 14., 15., 16.],
[ 2., 3., 4., 5., 8., 9., 10., 11., 14., 15., 16., 17.],
[ 3., 4., 5., 6., 9., 10., 11., 12., 15., 16., 17., 18.],
[ 7., 8., 9., 10., 13., 14., 15., 16., 19., 20., 21., 22.],
[ 8., 9., 10., 11., 14., 15., 16., 17., 20., 21., 22., 23.],
[ 9., 10., 11., 12., 15., 16., 17., 18., 21., 22., 23., 24.],
[13., 14., 15., 16., 19., 20., 21., 22., 25., 26., 27., 28.],
[14., 15., 16., 17., 20., 21., 22., 23., 26., 27., 28., 29.],
[15., 16., 17., 18., 21., 22., 23., 24., 27., 28., 29., 30.]]])

举例2

import torch
inputs = torch.randn(1, 2, 8, 8)
unfold = torch.nn.Unfold(kernel_size=(2, 2), stride=1)
patches = unfold(inputs)
print(inputs.size())
print(patches.size())

2、F.conv2d 指定卷积核二维卷积操作

nn.Unfold 函数可以把数据批量切片,对每一个小块进行数据处理,我们可以通过矩阵计算的形式批量计算。也有可能会用到下面指定卷积核的卷积。

import torch
from torch.nn import functional as F

"""手动定义卷积核(weight)和偏置"""
w = torch.rand(16, 3, 5, 5)  # 16种3通道的5乘5卷积核
b = torch.rand(16)  # 和卷积核种类数保持一致(不同通道共用一个bias)

"""定义输入样本"""
x = torch.randn(1, 3, 28, 28)  # 1张3通道的28乘28的图像

"""2D卷积得到输出"""
out = F.conv2d(x, w, b, stride=1, padding=1)  # 步长为1,外加1圈padding
print(out.shape)

out = F.conv2d(x, w, b, stride=2, padding=2)  # 步长为2,外加2圈padding
print(out.shape)

torch.Size([1, 16, 26, 26])
torch.Size([1, 16, 14, 14])

3、nn.Conv2d卷积层

import torch
from torch import nn

"""要输入的原始图像"""
x = torch.rand(1, 1, 28, 28)

"""2维的卷积层,用于图片的卷积"""
# 输入图像的通道数=1(灰度图像),卷积核的种类数=3
# 卷积核的shape是3乘3的,扫描步长为1,padding为0
layer = nn.Conv2d(1, 3, kernel_size=3, stride=1, padding=0)
out = layer(x)
print(out.shape)  # torch.Size([1, 3, 26, 26])

# 这次使用padding为1.所以原始图像上下左右都加了一层0
layer = nn.Conv2d(1, 3, kernel_size=3, stride=1, padding=1)
print(layer.forward(x).shape)  # torch.Size([1, 3, 28, 28])

# stride设置为2,也就是每次移动2格子(向上或者向右)
layer = nn.Conv2d(1, 3, kernel_size=3, stride=2, padding=1)
# 相当于每次跳1个像素地扫描,输出的Feature Map直接小了一半
print(layer.forward(x).shape)  # torch.Size([1, 3, 14, 14])
# 查看一下卷积层的权重(即卷积核)信息和偏置信息:
print(layer.weight)
print(layer.bias)

你可能感兴趣的:(基础学习,python,深度学习,pytorch)