卷积神经网络
卷积神经网络 (CNN) 是一种专门设计的神经网络,主要用于处理结构化网格数据,例如图像。CNN 利用数据的固有属性,如空间关系和局部性,来降低从高维数据中学习的复杂性和计算成本。
全连接网络面临的挑战
- 高维度: 当处理大型输入(如图像)时,全连接层在可扩展性方面遇到困难,可能导致数十亿个参数。
- 示例: 即使在降维之后,一个百万像素的图像也可能导致一个全连接层拥有大约 个参数。
CNN 的优势
- 空间不变性: CNN 对特征在输入中的位置不那么敏感,增强了鲁棒的特征识别能力。
- 参数数量减少: 通过利用空间层次结构和局部性,CNN 显著减少了所需的参数数量。
- 高效学习: CNN 的结构化方法能够有效地从较小的数据集中学习。
CNN 中的关键概念
平移不变性
- 通过卷积操作实现,该操作在整个图像上应用统一的权重,使模型能够识别物体,无论它们位于何处。
局部性原理
- CNN 在初始层专注于局部区域,这与基于图像的特征的局部性质相吻合。
分层处理
- CNN 通过层处理数据,随着数据在网络中深入,捕获越来越复杂和抽象的特征。
CNN 的数学基础
卷积
卷积操作是 CNN 的核心,涉及在整个图像上应用一个滤波器:
- : 输入图像
- : 输出特征图
- : 卷积核
- : 偏置项
通过局部性减少参数
- 将卷积限制在输入的小型局部区域内,可以显著降低参数数量,通常使用 或 的核。
扩展到多通道
现代 CNN 通过在所有通道上扩展卷积操作来处理多通道(例如,RGB 图像),从而产生多个特征图:
- : 具有多个通道的输入张量
- : 特征图的输出张量
- : 多维卷积核
实际应用和考虑事项
- 效率和归纳偏置: CNN 具有计算效率高和归纳偏置的特点,通常非常适合自然图像处理。
- 灵活性: 尽管最初是为图像数据设计的,但 CNN 的原理已被应用于其他数据类型,例如音频和文本。
图像卷积
卷积层介绍
卷积层在输入张量和核之间执行互相关操作以生成输出张量,从而优化图像数据处理。
互相关操作
该操作涉及将核在输入上滑动并计算逐元素乘积之和:
- : 输入维度
- : 核维度
示例计算
使用一个 3x3 的输入和一个 2x2 的核,操作计算如下:
使用卷积进行对象边缘检测
图像中的边缘检测可以使用特定的核来完成,这些核突出像素强度变化,这对于识别边界和纹理变化至关重要。
学习核
CNN 可以通过训练学习针对特定任务的最佳核,从而增强其执行复杂图像处理任务(如边缘检测)的能力。
填充和步长
填充
填充在输入图像周围添加额外的像素,以允许核应用于边界,从而保留输出的空间维度:
- 填充实践: 通常设置为 和 以保持输出维度与输入相似。
步长
步长控制核在输入图像上移动的步数,影响输出的分辨率和大小:
- 实际实现: 通过各种深度学习框架进行演示,说明这些概念如何应用于控制输出大小。
多输入和多输出通道
介绍
CNN 处理多个输入和输出通道,以增强多通道数据(如彩色图像)的表示和分析。
多输入通道
- 结构: 每个输入通道都有一个对应的核,使网络能够同时处理输入的多个方面。
多输出通道
- 通道扩展: CNN 增加输出通道的数量以捕获更复杂的特征,利用设计用于处理多个输入和输出通道的核。
卷积层
- 目的: 像每个像素上的全连接层一样工作,将输入通道转换为输出通道,而不考虑空间关系。
池化
池化的目的
池化层减小表示的空间大小,使网络对输入中的微小变化和位移具有不变性。
池化类型
- 最大池化: 突出最显著的特征。
- 平均池化: 平均特征,使输出平滑。
示例
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'])