跳到主要内容

卷积神经网络

卷积神经网络 (CNN) 是一种专门设计的神经网络,主要用于处理结构化网格数据,例如图像。CNN 利用数据的固有属性,如空间关系和局部性,来降低从高维数据中学习的复杂性和计算成本。

全连接网络面临的挑战

  • 高维度: 当处理大型输入(如图像)时,全连接层在可扩展性方面遇到困难,可能导致数十亿个参数。
  • 示例: 即使在降维之后,一个百万像素的图像也可能导致一个全连接层拥有大约 10910^9 个参数。

CNN 的优势

  • 空间不变性: CNN 对特征在输入中的位置不那么敏感,增强了鲁棒的特征识别能力。
  • 参数数量减少: 通过利用空间层次结构和局部性,CNN 显著减少了所需的参数数量。
  • 高效学习: CNN 的结构化方法能够有效地从较小的数据集中学习。

CNN 中的关键概念

平移不变性

  • 通过卷积操作实现,该操作在整个图像上应用统一的权重,使模型能够识别物体,无论它们位于何处。

局部性原理

  • CNN 在初始层专注于局部区域,这与基于图像的特征的局部性质相吻合。

分层处理

  • CNN 通过层处理数据,随着数据在网络中深入,捕获越来越复杂和抽象的特征。

CNN 的数学基础

卷积

卷积操作是 CNN 的核心,涉及在整个图像上应用一个滤波器:

[H]i,j=u+ab[V]a,b[X]i+a,j+b[\mathbf{H}]_{i, j} = u + \sum_a \sum_b [\mathbf{V}]_{a, b} [\mathbf{X}]_{i+a, j+b}
  • X\mathbf{X}: 输入图像
  • H\mathbf{H}: 输出特征图
  • V\mathbf{V}: 卷积核
  • uu: 偏置项

通过局部性减少参数

  • 将卷积限制在输入的小型局部区域内,可以显著降低参数数量,通常使用 3×33 \times 35×55 \times 5 的核。

扩展到多通道

现代 CNN 通过在所有通道上扩展卷积操作来处理多通道(例如,RGB 图像),从而产生多个特征图:

[H]i,j,d=a=ΔΔb=ΔΔc[V]a,b,c,d[X]i+a,j+b,c[\mathsf{H}]_{i,j,d} = \sum_{a = -\Delta}^{\Delta} \sum_{b = -\Delta}^{\Delta} \sum_c [\mathsf{V}]_{a, b, c, d} [\mathsf{X}]_{i+a, j+b, c}
  • X\mathsf{X}: 具有多个通道的输入张量
  • H\mathsf{H}: 特征图的输出张量
  • V\mathsf{V}: 多维卷积核

实际应用和考虑事项

  • 效率和归纳偏置: CNN 具有计算效率高和归纳偏置的特点,通常非常适合自然图像处理。
  • 灵活性: 尽管最初是为图像数据设计的,但 CNN 的原理已被应用于其他数据类型,例如音频和文本。

图像卷积

卷积层介绍

卷积层在输入张量和核之间执行互相关操作以生成输出张量,从而优化图像数据处理。

互相关操作

该操作涉及将核在输入上滑动并计算逐元素乘积之和:

Output=(nhkh+1)×(nwkw+1)\text{Output} = (n_h - k_h + 1) \times (n_w - k_w + 1)
  • nh,nwn_h, n_w: 输入维度
  • kh,kwk_h, k_w: 核维度

示例计算

使用一个 3x3 的输入和一个 2x2 的核,操作计算如下:

0×0+1×1+3×2+4×3=19,1×0+2×1+4×2+5×3=25,3×0+4×1+6×2+7×3=37,4×0+5×1+7×2+8×3=43.0 \times 0 + 1 \times 1 + 3 \times 2 + 4 \times 3 = 19,\\ 1 \times 0 + 2 \times 1 + 4 \times 2 + 5 \times 3 = 25,\\ 3 \times 0 + 4 \times 1 + 6 \times 2 + 7 \times 3 = 37,\\ 4 \times 0 + 5 \times 1 + 7 \times 2 + 8 \times 3 = 43.

使用卷积进行对象边缘检测

图像中的边缘检测可以使用特定的核来完成,这些核突出像素强度变化,这对于识别边界和纹理变化至关重要。

学习核

CNN 可以通过训练学习针对特定任务的最佳核,从而增强其执行复杂图像处理任务(如边缘检测)的能力。

填充和步长

填充

填充在输入图像周围添加额外的像素,以允许核应用于边界,从而保留输出的空间维度:

(nhkh+ph+1)×(nwkw+pw+1)(n_h - k_h + p_h + 1) \times (n_w - k_w + p_w + 1)
  • 填充实践: 通常设置为 ph=kh1p_h = k_h - 1pw=kw1p_w = k_w - 1 以保持输出维度与输入相似。

步长

步长控制核在输入图像上移动的步数,影响输出的分辨率和大小:

nhkh+ph+shsh×nwkw+pw+swsw\left\lfloor \frac{n_h - k_h + p_h + s_h}{s_h} \right\rfloor \times \left\lfloor \frac{n_w - k_w + p_w + s_w}{s_w} \right\rfloor
  • 实际实现: 通过各种深度学习框架进行演示,说明这些概念如何应用于控制输出大小。

多输入和多输出通道

介绍

CNN 处理多个输入和输出通道,以增强多通道数据(如彩色图像)的表示和分析。

多输入通道

  • 结构: 每个输入通道都有一个对应的核,使网络能够同时处理输入的多个方面。

多输出通道

  • 通道扩展: CNN 增加输出通道的数量以捕获更复杂的特征,利用设计用于处理多个输入和输出通道的核。

1×11 \times 1 卷积层

  • 目的: 像每个像素上的全连接层一样工作,将输入通道转换为输出通道,而不考虑空间关系。

池化

池化的目的

池化层减小表示的空间大小,使网络对输入中的微小变化和位移具有不变性。

池化类型

  • 最大池化: 突出最显著的特征。
  • 平均池化: 平均特征,使输出平滑。

示例

PyTorch

这是在 CIFAR-10 数据集上训练分类器的完整 PyTorch 代码:

import torch
import torchvision
import torchvision.transforms as transforms
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
import matplotlib.pyplot as plt
import numpy as np

# Load and normalize CIFAR10
# 加载并标准化CIFAR10
transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))
])
trainset = torchvision.datasets.CIFAR10(
root='./data', train=True, download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(
trainset, batch_size=4, shuffle=True, num_workers=2)
testset = torchvision.datasets.CIFAR10(
root='./data', train=False, download=True, transform=transform)
testloader = torch.utils.data.DataLoader(
testset, batch_size=4, shuffle=False, num_workers=2)
classes = ('plane', 'car', 'bird', 'cat', 'deer',
'dog', 'frog', 'horse', 'ship', 'truck')

# Define a Convolutional Neural Network
# 定义一个卷积神经网络
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(3, 6, 5)
self.pool = nn.MaxPool2d(2, 2)
self.conv2 = nn.Conv2d(6, 16, 5)
self.fc1 = nn.Linear(16 * 5 * 5, 120)
self.fc2 = nn.Linear(120, 84)
self.fc3 = nn.Linear(84, 10)

def forward(self, x):
x = self.pool(F.relu(self.conv1(x)))
x = self.pool(F.relu(self.conv2(x)))
x = torch.flatten(x, 1)
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x

net = Net()

# Define a Loss function and optimizer
# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)

# Train the network
# 训练网络
for epoch in range(2):
running_loss = 0.0
for i, data in enumerate(trainloader, 0):
inputs, labels = data
optimizer.zero_grad()
outputs = net(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
running_loss += loss.item()
if i % 2000 == 1999:
print(f'[{epoch + 1}, {i + 1:5d}] loss: {running_loss / 2000:.3f}')
running_loss = 0.0

print('Finished Training')
# 完成训练

# Save the trained model
# 保存训练好的模型
PATH = './cifar_net.pth'
torch.save(net.state_dict(), PATH)

# Test the network on the test data
# 在测试数据上测试网络
dataiter = iter(testloader)
images, labels = next(dataiter)
outputs = net(images)
_, predicted = torch.max(outputs, 1)
print('Predicted: ', ' '.join(f'{classes[predicted[j]]:5s}' for j in range(4)))
# 预测结果

correct = 0
total = 0
with torch.no_grad():
for data in testloader:
images, labels = data
outputs = net(images)
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels).sum().item()

print(f'Accuracy of the network on the 10000 test images: {100 * correct // total} %')
# 网络在10000张测试图像上的准确率

此代码定义了一个简单的 CNN,在 CIFAR-10 数据集上对其进行训练,并评估其性能。可能需要根据具体设置或要求进行调整。有关更详细的解释和分步说明,请参阅 PyTorch 网站上的完整教程。

Keras

import tensorflow as tf
from tensorflow.keras import layers, models

# Define a simple CNN model
# 定义一个简单的CNN模型
model = models.Sequential()
model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.Flatten())
model.add(layers.Dense(64, activation='relu'))
model.add(layers.Dense(10)) # Assuming 10 classes
# 假设有10个类别

# Compile and train the model
# 编译并训练模型
model.compile(optimizer='adam',
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
metrics=['accuracy'])

参考和有用链接