我们现在开始了解卷积神经网络,卷积神经网络是深度学习在计算机视觉领域的突破性成果,在计算机视觉领域,往往我们输入的图像都很大,使用全连接网络的话,计算的代价较高,图像也很难保留原有的特征,导致图像处理的准确率不高。
卷积神经网络(Convolutional Neural Networks,简称CNN)是一种特殊类型的神经网络,特别适合于处理具有网格结构的数据,如图像和视频。CNN的设计灵感来源于生物视觉系统,特别是大脑视觉皮层对视觉信息的处理方式。
关键组件:
图像是由像素点组成的,每个像素点的值范围为: [0, 255]
我们看到的彩色图一般都是多通道的图像, 所谓多通道可以理解为图像由多个不同的图像层叠加而成,最常见的RGB彩色图像由三个通道组成——红色、绿色、蓝色,每个通道都有自己的像素值(也是0到255的范围),三者的组合可以表示出数百万种不同的颜色。
我们通过一个简单的例子来使用Python的matplotlib
库来加载并显示一张图像,进而理解像素和通道的概念。
from PIL import Image
import matplotlib.pyplot as plt
# 加载图像
image_path = 'your_image_path.jpg' # 替换为你的图片路径
img_pil = Image.open(image_path)
# 使用matplotlib显示图像
plt.figure(figsize=(8, 8)) # 设置显示窗口大小
plt.imshow(img_pil) # 显示图像
# 如果是RGB图像,可以分离通道查看
if img_pil.mode == 'RGB':
r, g, b = img_pil.split()
plt.figure(figsize=(8, 8))
plt.imshow(r, cmap='Reds') # 显示红色通道
plt.figure(figsize=(8, 8))
plt.imshow(g, cmap='Greens') # 显示绿色通道
plt.figure(figsize=(8, 8))
plt.imshow(b, cmap='Blues') # 显示蓝色通道
plt.show() # 显示所有图像窗口
卷积神经网络(Convolutional Neural Network)是含有卷积层的神经网络. 卷积层的作用就是用来自动学习、提取图像的特征。CNN网络主要有三部分构成:卷积层、池化层和全连接层构成,其中卷积层负责提取图像中的局部特征;池化层用来大幅降低参数量级(降维);全连接层类似人工神经网络的部分,用来输出想要的结果。
卷积核
计算步骤:
PyTorch 卷积层 API
import torch
import torch.nn as nn
import matplotlib.pyplot as plt
# 显示图像
def show(img):
# 输入形状: (Height, Width, Channel)
plt.imshow(img)
plt.axis('off')
plt.show()
# 1. 单个多通道卷积核
def test01():
# 读取图像, 形状: (640, 640, 4)
img = plt.imread('data/彩色图片.png')
show(img)
# 构建卷积层
# 由于 out_channels 为 1, 相当于只有一个4通道卷积核
conv = nn.Conv2d(in_channels=4, out_channels=1, kernel_size=3, stride=1, padding=1)
# 输入形状: (BatchSize, Channel, Height, Width)
# mg形状: torch.Size([4, 640, 640])
img = torch.tensor(img).permute(2, 0, 1)
# img 形状: torch.Size([1, 4, 640, 640])
img = img.unsqueeze(0)
# 输入卷积层, new_img 形状: torch.Size([1, 1, 640, 640])
new_img = conv(img)
# new_img 形状: torch.Size([640, 640, 1])
new_img = new_img.squeeze(0).permute(1, 2, 0)
show(new_img.detach().numpy())
# 2. 多个多通道卷积核
def test02():
# 读取图像, 形状: (640, 640, 4)
img = plt.imread('data/彩色图片.png')
show(img)
# 构建卷积层
# 由于 out_channels 为 3, 相当于只有 3 个4通道卷积核
conv = nn.Conv2d(in_channels=4, out_channels=3, kernel_size=3, stride=1, padding=1)
# 输入形状: (BatchSize, Channel, Height, Width)
# img形状: torch.Size([3, 640, 640])
img = torch.tensor(img).permute(2, 0, 1)
# img 形状: torch.Size([1, 3, 640, 640])
img = img.unsqueeze(0)
# 输入卷积层, new_img 形状: torch.Size([1, 3, 640, 640])
new_img = conv(img)
# new_img 形状: torch.Size([640, 640, 3])
new_img = new_img.squeeze(0).permute(1, 2, 0)
# 打印三个特征图
show(new_img[:, :, 0].unsqueeze(2).detach().numpy())
show(new_img[:, :, 1].unsqueeze(2).detach().numpy())
show(new_img[:, :, 2].unsqueeze(2).detach().numpy())
池化层(Pooling Layer)在卷积神经网络(CNN)中紧随卷积层之后,其主要目的是降低特征图的空间维度,减少计算量,同时保持或提炼重要的特征信息。
最常见的池化类型有两种:
计算过程
边缘处理
与卷积层类似,池化层也可以通过添加边界填充(padding)来处理边缘,但实践中通常较少使用,因为池化的目的是降维而非保持尺寸不变。
在PyTorch中,使用池化层主要通过torch.nn
模块中的类来实现,比如nn.MaxPool2d
用于最大池化,nn.AvgPool2d
用于平均池化,以及nn.AdaptiveMaxPool2d
和nn.AdaptiveAvgPool2d
用于自适应池化。
最大池化 (Max Pooling)
import torch
import torch.nn as nn
# 创建一个最大池化层实例
max_pool = nn.MaxPool2d(kernel_size=2, stride=2) # 核大小为2x2,步长也为2
# 假设我们有一个张量作为输入,形状为(batch_size, channels, height, width)
input_tensor = torch.randn(1, 3, 32, 32) # 例如,一个批次、3个通道、32x32大小的图像
# 通过池化层传递输入张量
output_tensor = max_pool(input_tensor)
print("Output shape:", output_tensor.shape) # 输出张量的形状会根据池化核大小和步长变化
平均池化 (Average Pooling)
avg_pool = nn.AvgPool2d(kernel_size=2, stride=2) # 同样的核大小和步长设置
output_tensor_avg = avg_pool(input_tensor)
print("Average Pool Output shape:", output_tensor_avg.shape)
自适应池化 (Adaptive Pooling)
adaptive_max_pool = nn.AdaptiveMaxPool2d(output_size=(8, 8)) # 输出尺寸为8x8
output_adaptive_max = adaptive_max_pool(input_tensor)
print("Adaptive Max Pool Output shape:", output_adaptive_max.shape)
adaptive_avg_pool = nn.AdaptiveAvgPool2d(output_size=(8, 8))
output_adaptive_avg = adaptive_avg_pool(input_tensor)
print("Adaptive Avg Pool Output shape:", output_adaptive_avg.shape)