其中,是輸入數據,是第個卷積核。

池化層(Pooling Layer):

池化層用于減少特征圖的尺寸,降低模型復雜度并防止過擬合。常用的池化方法包括最大池化(Max Pooling)和平均池化(Average Pooling)。最大池化公式如下:

激活函數(Activation Function):

常用的激活函數是ReLU(Rectified Linear Unit),它通過將負值設為0來引入非線性:

全連接層(Fully Connected Layer):

全連接層將卷積和池化層提取的特征映射到類別標簽空間,通常用在網絡的最后幾層。公式如下:

其中,和是權重和偏置,是激活函數。

實際項目

數據集

我們將使用 CIFAR-10 數據集,它包含 10 個類別的 60,000 張彩色圖像,每個類別有 6,000 張圖像。

將下載的?cifar-10-python.tar.gz?文件解壓到你的項目目錄中的?./data/cifar-10-batches-py/?目錄。

mkdir -p ./data/cifar-10-batches-py
tar -xzvf cifar-10-python.tar.gz -C ./data/cifar-10-batches-py

大家注意,PyTorch 會自動檢測本地文件并使用數據,不會從網上下載。

import torch
import torchvision
import torchvision.transforms as transforms

# 數據預處理和加載
transform = transforms.Compose([
transforms.RandomHorizontalFlip(),
transforms.RandomCrop(32, padding=4),
transforms.ToTensor(),
transforms.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010))
])

train_dataset = torchvision.datasets.CIFAR10(root='./data', train=True, download=False, transform=transform)
train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=100, shuffle=True)

test_dataset = torchvision.datasets.CIFAR10(root='./data', train=False, download=False, transform=transform)
test_loader = torch.utils.data.DataLoader(test_dataset, batch_size=100, shuffle=False)

模型構建

構建一個具有兩個卷積層、兩個池化層、一個全連接層的CNN模型

import torch.nn as nn
import torch.optim as optim

class CNN(nn.Module):
def __init__(self):
super(CNN, self).__init__()
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.pool = nn.MaxPool2d(kernel_size=2, stride=2)
self.fc1 = nn.Linear(64 * 8 * 8, 512)
self.fc2 = nn.Linear(512, 10)

def forward(self, x):
x = torch.relu(self.conv1(x))
x = self.pool(x)
x = torch.relu(self.conv2(x))
x = self.pool(x)
x = x.view(-1, 64 * 8 * 8)
x = torch.relu(self.fc1(x))
x = self.fc2(x)
return x

model = CNN()

損失函數和優化器

使用交叉熵損失(Cross-Entropy Loss)和 Adam 優化器(Adam Optimizer):

import torch.optim as optim

criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)

訓練模型

訓練模型時,我們會記錄損失和準確率:

# 訓練模型
num_epochs = 10
for epoch in range(num_epochs):
running_loss = 0.0
for images, labels in train_loader:
optimizer.zero_grad()
outputs = model(images)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
running_loss += loss.item()

print(f"Epoch [{epoch+1}/{num_epochs}], Loss: {running_loss/len(train_loader)}")

# 在測試集上評估模型
model.eval()
correct = 0
total = 0
with torch.no_grad():
for images, labels in test_loader:
outputs = model(images)
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
print(f"Accuracy of the model on the test images: {100 * correct / total}%")
model.train()

繪制損失和準確率曲線

我們可以使用 Matplotlib 繪制訓練損失和準確率隨時間的變化曲線。

import matplotlib.pyplot as plt

# 假設 train_lossestest_accuracies 存儲了每個 epoch 的損失和準確率 train_losses = [0.5, 0.4, 0.35, 0.3, 0.25, 0.2, 0.15, 0.1, 0.05, 0.02] test_accuracies = [60, 65, 70, 75, 80, 85, 88, 90, 92, 95] # 繪制損失曲線 plt.figure(figsize=(12, 4)) plt.subplot(1, 2, 1) plt.plot(range(num_epochs), train_losses, label='Training Loss') plt.xlabel('Epochs') plt.ylabel('Loss') plt.title('Training Loss over Epochs') plt.legend() # 繪制準確率曲線 plt.subplot(1, 2, 2) plt.plot(range(num_epochs), test_accuracies, label='Test Accuracy') plt.xlabel('Epochs') plt.ylabel('Accuracy (%)') plt.title('Test Accuracy over Epochs') plt.legend() plt.tight_layout() plt.show()

可視化卷積核和特征圖

可視化卷積核和特征圖有助于理解CNN如何提取和利用特征。

import numpy as np

# 可視化第一個卷積層的卷積核
def visualize_filters(layer):
filters = layer.weight.data.clone()
filters = filters - filters.min()
filters = filters / filters.max()
filter_img = torchvision.utils.make_grid(filters, nrow=8, padding=1)
return filter_img.permute(1, 2, 0).cpu().numpy()

conv1_filters = visualize_filters(model.conv1)
plt.imshow(conv1_filters)
plt.title('Conv1 Filters')
plt.show()
# 可視化卷積層的特征圖
def visualize_feature_maps(images, model):
with torch.no_grad():
x = torch.relu(model.conv1(images))
feature_maps = x[0, :8] # 可視化前8個特征圖
feature_maps = torchvision.utils.make_grid(feature_maps.unsqueeze(1), nrow=8, padding=1)
return feature_maps.permute(1, 2, 0).cpu().numpy()

sample_image, _ = next(iter(train_loader))
feature_maps = visualize_feature_maps(sample_image, model)
plt.imshow(feature_maps)
plt.title('Feature Maps after Conv1')
plt.show()

最后

整個項目通過PyTorch框架構建了一個簡單的卷積神經網絡模型,用于CIFAR-10數據集的圖像分類任務。

從最初,我們詳細講解了CNN的理論背景,包括卷積層、池化層、激活函數和全連接層的工作原理,并給大家提供了完整的代碼實現和模型訓練過程。最后,我們通過可視化訓練過程中的損失、準確率以及卷積核和特征圖,進一步揭示了CNN如何處理和學習圖像數據。

本文章轉載微信公眾號@深夜努力寫Python

上一篇:

講透一個強大算法模型,K-means Clustering !!

下一篇:

講透一個強大算法模型,Ridge回歸!!
#你可能也喜歡這些API文章!

我們有何不同?

API服務商零注冊

多API并行試用

數據驅動選型,提升決策效率

查看全部API→
??

熱門場景實測,選對API

#AI文本生成大模型API

對比大模型API的內容創意新穎性、情感共鳴力、商業轉化潛力

25個渠道
一鍵對比試用API 限時免費

#AI深度推理大模型API

對比大模型API的邏輯推理準確性、分析深度、可視化建議合理性

10個渠道
一鍵對比試用API 限時免費