目录
一、卷积层
卷积可以看作是输入和卷积核之间的内积运算,是两个实值函数之间的一种数学运算。在卷积运算中,通常使用卷积核将输入数据进行卷积运算得到输出作为特征映射,每个卷积核可获得一个特征映射。针对二维图像使用2x2的卷积核,步长为1的运算过程如 图1-1 所示。
图 1-1 二维卷积运算过程示意图
图1-1 是一个二维卷积运算的示例,可以发现,卷积操作将周围几个像素的取值经过计算得到一个像素值。
使用卷积运算在图像识别、图像分割、图像重建等应用中有三个好处,即卷积稀疏连接、参数共享、等变表示,正是这些好处让卷积神经网络在图像处理算法中脱颖而出。
在卷积神经网络中,通过输入卷积核来进行卷积操作,使输入单元(图像或特征映射)和输出单元(特征映射)之间的连接是稀疏的,这样能够减少需要训练参数的数量,从而加快网络的计算速度。
卷积操作的参数共享特点,主要体现在模型中同一组参数可以被多个函数或操作共同使用。在卷积神经网络中,针对不同的输入会利用同样的卷积核来获得相应的输出。这种参数共享的特点是只需要训练一个参数集,而不需对每个位置学习一个参数集合。由于卷积核尺寸可以远远小于输入尺寸,即减少需要学习的参数的数量,并且针对每个卷积层可以使用多个卷积核获取输入的特征映射,对数据(尤其是图像)具有很强的特征提取和表示能力,并且在卷积运算之后,使得卷积神经网络结构对输入的图像具有平移不变的性质。
在 PyTorch 中针对卷积操作的对象和使用的场景不同,有一维卷积、二维卷积、三维卷积与转置卷积(可以简单理解为卷积操作的逆操作),但它们的使用方法比较相似,都可以从 torch . nn 模块中调用,需要用的类如 表1-2 所示。
层对应的类 | 功能作用 |
---|---|
torch.nn.Conv1d ( ) | 针对输入信号上应用1D卷积 |
torch.nn.Conv2d ( ) | 针对输入信号上应用2D卷积 |
torch.nn.Conv3d ( ) | 针对输入信号上应用3D卷积 |
torch.nn.ConvTranspose1d ( ) | 在输入信号上应用1D转置卷积 |
torch.nn.ConvTranspose2d ( ) | 在输入信号上应用2D转置卷积 |
torch.nn.ConvTranspose3d ( ) | 在输入信号上应用3D转置卷积 |
下面以 torch.nn.Conv2d ( ) 为例,介绍卷积在图像上的使用方法,调用方式为:
torch.nn.Conv2d(in_channels, out_channels, kernel_size,stride=1,padding=0,dilation=1,groups=1,bias=True)
参数说明:
① in_channels:(整数)输入图像的通道数;
② out_channels:(整数)经过卷积运算后,输出特征映射的数量;
③ kernel_size:(整数或者数组)卷积核的大小;
④ stride:(整数或者数组,正数)卷积的步长,默认为1;
⑤ padding:(整数或者数组,正数)在输入两边进行0填充的数量,默认为0;
⑥ dilation:(整数或者数组,正数)卷积核元素之间的步幅,该参数可调整空洞卷积的空洞大小,默认为1;
⑦ groups:(整数,正数)从输入通道到输出通道的阻塞连接数;
⑧ bias:(布尔值,正数)如果 bias = True,则添加偏置,默认为True;
torch.nn.Conv2d ( ) 输入的张量为(N,Cin,Hin,Win),输出的张量为(N,Cout,Hout,Wout)。
其中:
下面通过一个实例,展示图像经过二维卷积后的效果。先导入相关的包和模块,并且使用PIL包读取图像数据,使用 matplotlib 包来可视化图像和卷积后的结果,示例程序如下:
'''使用一张图片展示经过卷积后的图像效果'''
import torch
import numpy as np
import torch.nn as nn
import matplotlib.pyplot as plt
from PIL import Image
#读取图像→转化为灰度图片→转化为Numpy数组
image = Image.open(r'C:\Users\lenovo\Pictures\image.png')
gray = np.array(image.convert("L"),dtype = np.float32)
#可视化图片
plt.figure(figsize = (6,6))
plt.imshow(gray, cmap = plt.cm.gray)
plt.axis("off")
plt.show()
图 1-3 原始图片 图 1-4 灰度图片
经过上述操作后,得到一个 512×512 的数组,在使用 PyTorch 进行卷积操作之前,需要将其转化为 1×1×512×512 的张量。
#将数组装换为张量
imh,imw = gray.shape
Gray = torch.from_numpy(gray.reshape((1,1,imh, imw)))
print('Gray.shape: \n',Gray.shape)
#运行结果
Gray.shape:
torch.Size([1, 1, 512, 512])
卷积时需要将图像转化为四维来表示[ batch , channel , h , w ]。在对图像进行卷积操作后,获得两个特征映射。第一个特征映射使用图像轮廓提取卷积核获取,第二个特征映射使用的卷积核为随机数,卷积核大小为 5x5,对图像的边缘不使用0填充,所以卷积后输出特征映射的尺寸为508x508。使用下面的程序进行卷积运算,并对卷积后的两个特征映射进行可视化:
#对灰度图像进行卷积提取图像轮廓
kersize = 5 #定义边缘检测卷积核,并将维度处理为 1×1×5×5
ker = torch.ones(kersize,kersize,dtype = torch.float32)*-1
ker[2,2] = 24
ker = ker.reshape((1,1,kersize,kersize))
#进行卷积操作
conv2d = nn.Conv2d(1, 2,(kersize,kersize),bias=True)
#设置卷积时使用的核,第一个核使用边缘检测核
conv2d.weight.data[0] = ker
#对灰度图像进行卷积操作
imconv2dout = conv2d(Gray)
#对卷积后的输出进行维度压缩
Imconv2dout = imconv2dout.data.squeeze()
print('卷积后尺寸: \n',Imconv2dout.shape)
#可视化卷积后的图像
plt.figure(figsize = (12,6))
plt.subplot(1,2,1)
plt.imshow(Imconv2dout[0], cmap = plt.cm.gray)
plt.axis('off')
plt.subplot(1,2,2)
plt.imshow(Imconv2dout[1],cmap = plt.cm.gray)
plt.axis('off')
plt.show()
#输出结果
卷积后尺寸:
torch.Size([2, 508, 508])
(a) (b)
图 1-5 卷积后的两个特征映射可视化
从 图 1-5 (a)可以看到,使用的边缘特征提取卷积核很好地提取出了图像的边缘信息。而右边的图像使用的卷积核为随机数,得到的卷积结果与原始图像很相似。
二、池化层
1.示意图
图 2-1 池化层示意图
2.常用的池化操作
在 PyTorch 中,提供了多种池化的类,分别是最大值池化( MaxPool )、最大值池化的逆过程( MaxUnPool )、平均值池化( AvgPool )与自适应池化( AdaptiveMaxPool 、 AdaptiveAvgPool )等。并且均提供了一维、二维和三维的池化操作。具体的池化类和功能如表2-2所示。
层对应的类 | 功能 |
---|---|
torch.nn.MaxPool1d ( ) | 针对输入信号上应用1D最大值池化 |
torch.nn.MaxPool2d ( ) | 针对输入信号上应用2D最大值池化 |
torch.nn.MaxPool3d ( ) | 针对输入信号上应用3D最大值池化 |
torch.nn.MaxUnPool1d ( ) | 1D最大值池化的部分逆运算 |
torch.nn.MaxUnPool2d ( ) | 2D最大值池化的部分逆运算 |
torch.nn.MaxUnPool3d ( ) | 3D最大值池化的部分逆运算 |
torch.nn.AvgPool1d ( ) | 针对输入信号上应用1D平均值池化 |
torch.nn.AvgPool2d ( ) | 针对输入信号上应用2D平均值池化 |
torch.nn.AvgPool3d ( ) | 针对输入信号上应用3D平均值池化 |
torch.nn.AdaptiveMaxPool1d ( ) | 针对输入信号上应用1D自适应最大值池化 |
torch.nn.AdaptiveMaxPool2d ( ) | 针对输入信号上应用2D自适应最大值池化 |
torch.nn.AdaptiveMaxPool3d ( ) | 针对输入信号上应用3D自适应最大值池化 |
torch.nn.AdaptiveAvgPool1d ( ) | 针对输入信号上应用1D自适应平均值池化 |
torch.nn.AdaptiveAvgPool2d ( ) | 针对输入信号上应用2D自适应平均值池化 |
torch.nn.AdaptiveAvgPool3d ( ) | 针对输入信号上应用3D自适应平均值池化 |
3.函数原型
对于 torch.nn.MaxPool2d ( ) 池化操作相关参数的应用,其使用方法如下:
torch.nn.MaxPool2d(kernel_size,stride=None,padding=0,dilation=1,return_indices=False,ceil_mode=False)
参数说明:
① kernel_size:(整数或数组)最大值池化的窗口大小;
② stride:(整数或数组,正数)最大值池化窗口移动的步长,默认值是 kernel_size;
③ padding:(整数或数组,正数)输入的每一条补充 0 的层数;
④ dilation:(整数或数组,正数)一个控制窗口中元素步幅的参数;
⑤ return_indices:如果为 True ,则会返回输出最大值的索引,这样会更加便于之后的torch.nn.MaxUnPool2d ( ) 操作。
⑥ ceil_mode:如果等于 True ,计算输出信号大小的时候,会使用向上取整,默认是向下取整。
torch.nn.MaxPool2d ( ) 输入的张量为(N,Cin,Hin,Win),输出的张量为(N,Cout,Hout,Wout)。
其中:
4.实例展示
下面以 图2-1 卷积后的结果为例,对其进行最大值池化、平均值池化与自适应平均值池化。
(1)最大值池化
首先使用 nn.MaxPool2d ( ) 函数,对卷积后的输出进行最大值池化,并对其进行可视化,程序如下:
#对卷积后的结果进行最大值池化
maxpool2 = nn.MaxPool2d(2,stride=2)
pool2_out = maxpool2(imconv2dout)
pool2_out_im = pool2_out.squeeze()
print('pool2_out.shape: \n',pool2_out.shape)
通过上面程序发现,原始 508x508 的特征映射在经过窗口为 2x2 ,步长为 2 的最大值池化后,尺寸变化为 254×254 的特征映射。将两个特征映射进行可视化,得到如 图2-2 所示的图像。
#可视化最大值池化后的结果
plt.figure(figsize=(12,6))
plt.subplot(1,2,1)
plt.imshow(pool2_out_im[0].data, cmap=plt.cm.gray)
plt.axis('off')
plt.subplot(1,2,2)
plt.imshow(pool2_out_im[1].data, cmap=plt.cm.gray)
plt.axis('off')
( a ) ( b )
图 2-2 最大值池化后的结果图像
(2)平均值池化
接下来使用 nn.AvgPool2d ( ) 函数,对卷积后的输出进行平均值池化,并对其进行可视化,程序如下:
#对卷积后的结果进行平均值池化
avgpool2 = nn.AvgPool2d(2,stride=2)
pool2_out = avgpool2(imconv2dout)
pool2_out_im = pool2_out.squeeze()
print('pool2_out.shape: \n',pool2_out.shape)
#可视化平均值池化后的结果
plt.figure(figsize=(12,6))
plt.subplot(1,2,1)
plt.imshow(pool2_out_im[0].data, cmap=plt.cm.gray)
plt.axis('off')
plt.subplot(1,2,2)
plt.imshow(pool2_out_im[1].data, cmap=plt.cm.gray)
plt.axis('off')
plt.show()
#运行结果
pool2_out.shape:
torch.Size([1, 2, 254, 254])
( a ) ( b )
图 2-3 平均值池化后的结果图像
(3)自适应平均值池化
再使用 nn .AdaptiveAvgPool2d ( ) 函数,对卷积后的输出进行自适应平均值池化并可视化。在使用该函数时,可以使用 output _ size 参数指定输出特征映射的尺寸。程序如下:
#对卷积后的结果进行自适应平均值池化
AdaAvgpool2 = nn.AdaptiveAvgPool2d(output_size = (100,100))
pool2_out = AdaAvgpool2(imconv2dout)
pool2_out_im = pool2_out.squeeze ()
print('pool2_out.shape: \n',pool2_out.shape)
#可视化自适应平均值池化后的结果
plt.figure ( figsize =(12,6))
plt.subplot (1,2,1)
plt.imshow (pool2_out_im[0].data , cmap = plt.cm.gray )
plt.axis('off')
plt.subplot (1,2,2)
plt.imshow (pool2_out_im[1].data , cmap = plt.cm.gray )
plt.axis('off')
plt.show ()
#运行结果
pool2_out.shape:
torch.Size([1, 2, 100, 100])
( a ) ( b )
图 2-4 自适应平均值池化后的结果图像
最新动态,请关注微信公众号:回不去的明天