新建
卷积神经网络(一):基础CNN

爱学习的王一博

推荐镜像 :Basic Image:bohrium-notebook:2023-04-07
推荐机型 :c2_m4_cpu
赞 3
2
5
目录
卷积神经网络(一):基础CNN
代码
文本
在这个教程中,我们将使用 PyTorch 构建一个简单的卷积神经网络(CNN)来对手写数字(MNIST 数据集)进行分类。这个网络只有一个卷积层、一个池化层和一个全连接层,适合初学者理解 CNN 的基本原理和使用方法。
代码
文本
1. 导入必要的库
我们首先导入 PyTorch 及相关库,包括:
- torch:PyTorch 的主要模块。
- torch.nn:用于神经网络模型的定义。
- torch.optim:用于优化器的定义。
- torch.nn.functional:提供激活函数和其他操作。
- torchvision:用于加载和预处理图像数据的库。
代码
文本
[1]
import torch
import torch.nn as nn
import torch.optim as optim
import torch.nn.functional as F
from torchvision import datasets, transforms
from torch.utils.data import DataLoader
代码
文本
2. 定义数据预处理和加载
我们将下载并预处理 MNIST 数据集,并使用 DataLoader 加载训练和测试数据。MNIST 数据集包含60000张训练图像和10000张测试图像,图像是28×28像素的灰度图像。
代码
文本
[2]
# 图像预处理操作
transform = transforms.Compose([
transforms.ToTensor(), # 将图像转换为张量
transforms.Normalize((0.1307,), (0.3081,)) # 标准化图像,使其均值为0.1307,标准差为0.3081
])
# 下载并加载 MNIST 数据集
train_dataset = datasets.MNIST(root='./data', train=True, download=True, transform=transform)
test_dataset = datasets.MNIST(root='./data', train=False, download=True, transform=transform)
train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=1000, shuffle=False)
Downloading http://yann.lecun.com/exdb/mnist/train-images-idx3-ubyte.gz Failed to download (trying next): HTTP Error 403: Forbidden Downloading https://ossci-datasets.s3.amazonaws.com/mnist/train-images-idx3-ubyte.gz Downloading https://ossci-datasets.s3.amazonaws.com/mnist/train-images-idx3-ubyte.gz to ./data/MNIST/raw/train-images-idx3-ubyte.gz
Extracting ./data/MNIST/raw/train-images-idx3-ubyte.gz to ./data/MNIST/raw Downloading http://yann.lecun.com/exdb/mnist/train-labels-idx1-ubyte.gz Failed to download (trying next): HTTP Error 403: Forbidden Downloading https://ossci-datasets.s3.amazonaws.com/mnist/train-labels-idx1-ubyte.gz Downloading https://ossci-datasets.s3.amazonaws.com/mnist/train-labels-idx1-ubyte.gz to ./data/MNIST/raw/train-labels-idx1-ubyte.gz
Extracting ./data/MNIST/raw/train-labels-idx1-ubyte.gz to ./data/MNIST/raw Downloading http://yann.lecun.com/exdb/mnist/t10k-images-idx3-ubyte.gz Failed to download (trying next): HTTP Error 403: Forbidden Downloading https://ossci-datasets.s3.amazonaws.com/mnist/t10k-images-idx3-ubyte.gz Downloading https://ossci-datasets.s3.amazonaws.com/mnist/t10k-images-idx3-ubyte.gz to ./data/MNIST/raw/t10k-images-idx3-ubyte.gz
Extracting ./data/MNIST/raw/t10k-images-idx3-ubyte.gz to ./data/MNIST/raw Downloading http://yann.lecun.com/exdb/mnist/t10k-labels-idx1-ubyte.gz Failed to download (trying next): HTTP Error 403: Forbidden Downloading https://ossci-datasets.s3.amazonaws.com/mnist/t10k-labels-idx1-ubyte.gz Downloading https://ossci-datasets.s3.amazonaws.com/mnist/t10k-labels-idx1-ubyte.gz to ./data/MNIST/raw/t10k-labels-idx1-ubyte.gz
Extracting ./data/MNIST/raw/t10k-labels-idx1-ubyte.gz to ./data/MNIST/raw
代码
文本
解释:
- transforms.Compose:组合多个图像预处理操作。
- transforms.ToTensor:将 PIL 图像转换为 PyTorch 张量,并将像素值缩放到 [0, 1] 范围内。
- transforms.Normalize:对张量进行标准化,使其均值和标准差符合指定值。
- datasets.MNIST:下载并加载 MNIST 数据集。
- root:数据集保存的路径。
- train:布尔值,表示加载训练集或测试集。
- download:布尔值,表示是否下载数据集。
- transform:指定用于预处理的转换操作。
- DataLoader:用于批量加载数据集。
- batch_size:每个批次的样本数量。
- shuffle:是否随机打乱数据顺序。
代码
文本
3. 定义 CNN 模型
在这里,我们定义了一个简单的 CNN 模型。它包含一个卷积层、一个池化层和一个全连接层。
代码
文本
[3]
class SimpleCNN(nn.Module):
def __init__(self):
super(SimpleCNN, self).__init__()
# 单个卷积层
self.conv1 = nn.Conv2d(1, 32, kernel_size=3, stride=1, padding=1)
# 单个池化层(最大池化)
self.max_pool = nn.MaxPool2d(kernel_size=2, stride=2)
# 单个全连接层
self.fc1 = nn.Linear(32 * 14 * 14, 10)
def forward(self, x):
# 卷积 -> 激活 -> 最大池化
x = self.max_pool(F.relu(self.conv1(x)))
# 扁平化张量
x = x.view(-1, 32 * 14 * 14)
# 全连接层
x = self.fc1(x)
return x
# 实例化模型
model = SimpleCNN()
代码
文本
解释:
- 卷积层 (nn.Conv2d):
- in_channels:输入图像的通道数(MNIST 为灰度图,只有1个通道)。
- out_channels:输出特征图的通道数。
- kernel_size:卷积核的大小(3×3)。
- stride:步长(默认为1)。
- padding:每一侧填充的像素数(这里为1,保持输入和输出尺寸相同)。
- 最大池化层 (nn.MaxPool2d):
- kernel_size:池化核的大小(2×2)。
- stride:步长(默认为池化核大小)。
- 全连接层 (nn.Linear):
- in_features:输入特征数(这里是32个通道的特征图,大小为14×14,因此输入特征数为32×14×14)。
- out_features:输出特征数(MNIST 有10个类别,因此输出特征数为10)。
- 激活函数 (F.relu):
- ReLU(Rectified Linear Unit)是一种常用的非线性激活函数,可增加模型的非线性能力。
代码
文本
4. 定义损失函数和优化器
我们将使用交叉熵损失函数和 Adam 优化器。
代码
文本
[4]
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
代码
文本
解释:
- nn.CrossEntropyLoss:交叉熵损失函数,用于多分类问题,适合处理目标标签是一个整数类别的场景。
- optim.Adam:Adam 优化器,具有自适应学习率,可实现快速收敛。
代码
文本
5. 训练和测试模型
我们定义训练和测试函数,然后使用它们来训练模型并评估其性能。
代码
文本
[5]
# 训练函数
def train(model, device, train_loader, optimizer, criterion, epoch):
model.train() # 将模型设为训练模式
for batch_idx, (data, target) in enumerate(train_loader):
data, target = data.to(device), target.to(device) # 将数据加载到指定设备
optimizer.zero_grad() # 梯度清零
output = model(data) # 前向传播
loss = criterion(output, target) # 计算损失
loss.backward() # 反向传播计算梯度
optimizer.step() # 更新模型参数
if batch_idx % 100 == 0:
print(f'Train Epoch: {epoch} [{batch_idx * len(data)}/{len(train_loader.dataset)}]\tLoss: {loss.item():.6f}')
# 测试函数
def test(model, device, test_loader, criterion):
model.eval() # 将模型设为评估模式
test_loss = 0
correct = 0
with torch.no_grad(): # 禁用梯度计算
for data, target in test_loader:
data, target = data.to(device), target.to(device)
output = model(data)
test_loss += criterion(output, target).item() # 累加损失
pred = output.argmax(dim=1, keepdim=True) # 获取预测结果
correct += pred.eq(target.view_as(pred)).sum().item() # 统计正确预测的数量
test_loss /= len(test_loader.dataset)
accuracy = 100. * correct / len(test_loader.dataset)
print(f'\nTest set: Average loss: {test_loss:.4f}, Accuracy: {correct}/{len(test_loader.dataset)} ({accuracy:.2f}%)\n')
# 训练模型
device = torch.device("cuda" if torch.cuda.is_available() else "cpu") # 使用 GPU 或 CPU
model.to(device)
for epoch in range(1, 5):
train(model, device, train_loader, optimizer, criterion, epoch)
test(model, device, test_loader, criterion)
Train Epoch: 1 [0/60000] Loss: 2.367973 Train Epoch: 1 [6400/60000] Loss: 0.435666 Train Epoch: 1 [12800/60000] Loss: 0.204998 Train Epoch: 1 [19200/60000] Loss: 0.109017 Train Epoch: 1 [25600/60000] Loss: 0.076033 Train Epoch: 1 [32000/60000] Loss: 0.157300 Train Epoch: 1 [38400/60000] Loss: 0.236827 Train Epoch: 1 [44800/60000] Loss: 0.181299 Train Epoch: 1 [51200/60000] Loss: 0.127266 Train Epoch: 1 [57600/60000] Loss: 0.014404 Test set: Average loss: 0.0001, Accuracy: 9749/10000 (97.49%) Train Epoch: 2 [0/60000] Loss: 0.108169 Train Epoch: 2 [6400/60000] Loss: 0.045049 Train Epoch: 2 [12800/60000] Loss: 0.149957 Train Epoch: 2 [19200/60000] Loss: 0.074424 Train Epoch: 2 [25600/60000] Loss: 0.100772 Train Epoch: 2 [32000/60000] Loss: 0.030572 Train Epoch: 2 [38400/60000] Loss: 0.056176 Train Epoch: 2 [44800/60000] Loss: 0.032610 Train Epoch: 2 [51200/60000] Loss: 0.033248 Train Epoch: 2 [57600/60000] Loss: 0.016807 Test set: Average loss: 0.0001, Accuracy: 9797/10000 (97.97%) Train Epoch: 3 [0/60000] Loss: 0.022519 Train Epoch: 3 [6400/60000] Loss: 0.121023 Train Epoch: 3 [12800/60000] Loss: 0.052023 Train Epoch: 3 [19200/60000] Loss: 0.132572 Train Epoch: 3 [25600/60000] Loss: 0.032701 Train Epoch: 3 [32000/60000] Loss: 0.072095 Train Epoch: 3 [38400/60000] Loss: 0.011702 Train Epoch: 3 [44800/60000] Loss: 0.035461 Train Epoch: 3 [51200/60000] Loss: 0.068169 Train Epoch: 3 [57600/60000] Loss: 0.100575 Test set: Average loss: 0.0001, Accuracy: 9831/10000 (98.31%) Train Epoch: 4 [0/60000] Loss: 0.098319 Train Epoch: 4 [6400/60000] Loss: 0.014936 Train Epoch: 4 [12800/60000] Loss: 0.060127 Train Epoch: 4 [19200/60000] Loss: 0.040191 Train Epoch: 4 [25600/60000] Loss: 0.045497 Train Epoch: 4 [32000/60000] Loss: 0.056086 Train Epoch: 4 [38400/60000] Loss: 0.026181 Train Epoch: 4 [44800/60000] Loss: 0.180345 Train Epoch: 4 [51200/60000] Loss: 0.014562 Train Epoch: 4 [57600/60000] Loss: 0.033653 Test set: Average loss: 0.0001, Accuracy: 9800/10000 (98.00%)
代码
文本
已赞3
推荐阅读
公开
第八次作业-2301112397-杨晓龙
1900017821@pku.edu.cn

发布于 2024-04-24
公开
程于津-2301112385-第八次作业
Waytogo

发布于 2024-05-04