卷积神经网络(CNN)入门与实践
立即解锁
发布时间: 2025-09-01 01:19:28 阅读量: 15 订阅数: 33 AIGC 


现代计算机视觉与PyTorch
### 卷积神经网络(CNN)入门与实践
#### 卷积与池化的特性
当图像向左平移 1 个像素时,经过卷积、激活和池化操作后,图像的维度会因池化而降低,意味着更少的像素存储了原始图像的大部分信息。由于池化存储的是一个区域的信息,即使原始图像平移 1 个单位,池化图像中一个像素内的信息也不会改变,因为该区域的最大值很可能会被捕捉到。
卷积和池化还与感受野有关。以一个 100x100 的图像为例,经过两次卷积和池化操作(卷积操作有填充)后,输出图像的形状为 25x25。此时,25x25 输出中的每个单元对应原始图像中一个更大的 4x4 区域。因此,卷积和池化操作使得结果图像中的每个单元都包含了原始图像一个区域内的关键信息。
#### 实现 CNN
CNN 是计算机视觉技术的基础,了解其工作原理很重要。CNN 由卷积、池化、扁平化和最终的分类层组成。下面通过一个简单的示例,使用 PyTorch 构建 CNN 架构,并通过代码理解前向传播过程中的各种操作。
##### 步骤 1:导入相关库
```python
import torch
from torch import nn
from torch.utils.data import TensorDataset, Dataset, DataLoader
from torch.optim import SGD, Adam
device = 'cuda' if torch.cuda.is_available() else 'cpu'
from torchvision import datasets
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
```
##### 步骤 2:创建数据集
```python
X_train = torch.tensor([[[[1,2,3,4],[2,3,4,5],
[5,6,7,8],[1,3,4,5]]],
[[[-1,2,3,-4],[2,-3,4,5],
[-5,6,-7,8],[-1,-3,-4,-5]]]]).to(device).float()
X_train /= 8
y_train = torch.tensor([0,1]).to(device).float()
```
这里将输入数据集除以最大值 8,使其范围在 -1 到 +1 之间。输入数据集的形状为 (2,1,4,4),表示有两个数据点,每个数据点是 4x4 的形状,且有 1 个通道。
##### 步骤 3:定义模型架构
```python
def get_model():
model = nn.Sequential(
nn.Conv2d(1, 1, kernel_size=3),
nn.MaxPool2d(2),
nn.ReLU(),
nn.Flatten(),
nn.Linear(1, 1),
nn.Sigmoid(),
).to(device)
loss_fn = nn.BCELoss()
optimizer = Adam(model.parameters(), lr=1e-3)
return model, loss_fn, optimizer
```
在这个模型中,使用 `nn.Conv2d` 指定输入有 1 个通道,卷积后输出 1 个通道(即 1 个 3x3 的滤波器)。接着进行最大池化、ReLU 激活、扁平化,最后连接到一个输出单元,并使用 Sigmoid 激活函数。损失函数为二元交叉熵损失(`nn.BCELoss`),优化器使用 Adam,学习率为 0.001。
##### 步骤 4:总结模型架构
```python
!pip install torch_summary
from torchsummary import summary
model, loss_fn, optimizer = get_model()
summary(model, X_train);
```
各层参数情况如下:
| 层 | 参数数量 | 原因 |
| ---- | ---- | ---- |
| Conv2d | 10 | 9 个权重参数(3x3)和 1 个偏置 |
| MaxPool2d、ReLU、Flatten | 0 | 这些是在卷积层输出上执行的操作,不涉及权重或偏置 |
| Linear | 2 | 1 个权重和 1 个偏置 |
##### 步骤 5:训练模型
```python
# 定义训练批量数据的函数
def train_batch(x, y, model, opt, loss_fn):
model.train()
prediction = model(x)
batch_loss = loss_fn(prediction.squeeze(0), y)
batch_loss.backward()
optimizer.step()
optimizer.zero_grad()
return batch_loss.item()
# 定义训练数据加载器
trn_dl = DataLoader(TensorDataset(X_train, y_train))
# 训练模型 2000 个 epoch
for epoch in range(2000):
for ix, batch in enumerate(iter(trn_dl)):
x, y = batch
batch_loss = train_batch(x, y, model, optimizer, loss_fn)
```
##### 步骤 6:对第一个数据点进行前向传播
```python
model(X_train[:1])
```
输出结果为 0.1625。
#### 使用深度 CNN 进行图像分类
传统神经网络在处理平移图像时预测不准确,而 CNN 可以解决这个问题。下面以 Fashion-MNIST 数据集为例,展示 CNN 在处理平移图像时的表现。
##### 步骤 1:导入必要的包
```python
from torchvision import datasets
from torch.utils.data import Dataset, DataLoader
import torch
import torch.nn as nn
device = "cuda" if torch.cuda.is_available() else "cpu"
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
```
##### 步骤 2:定义 Fashion-MNIST 数据集类
```python
class FMNISTDataset(Dataset):
def __init__(self, x, y):
x = x.float()/255
x = x.view(-1,1,28,28)
self.x, self.y = x, y
def __getitem__(self, ix):
x, y = self.x[ix], self.y[ix]
return x.to(device), y.to(device)
def __len__(self):
return len(self.x)
```
这里将输入图像重塑为 (1,28,28) 的形状,以适应 CNN 的输入要求。
##### 步骤 3:定义 CNN 模型架构
```python
from torch.optim import SGD, Adam
def get_model():
model = nn.Sequential(
nn.Conv2d(1, 64, kernel_size=3),
nn.MaxPool2d(2),
nn.ReLU(),
nn.Conv2d(64, 128, kernel_size=3),
nn.MaxPool2d(2),
nn.ReLU(),
nn.Flatten(),
nn.Linear(3200, 256),
nn.ReLU(),
nn.Linear(256, 10)
).to(device)
loss_fn = nn.CrossEntropyLoss()
optimizer = Adam(model.parameters(), lr=1e-3)
return model, loss_fn, optimizer
```
##### 步骤 4:总结模型
```python
from torchsummary import summary
model, loss_fn, optimizer = get_model()
summary(model, torch.zeros
```
0
0
复制全文
相关推荐









