
如何高效爬取全球新聞網站 – 整合Scrapy、Selenium與Mediastack API實現自動化新聞采集
其中,是輸入數據,是第個卷積核。
池化層(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_losses
和 test_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()
可視化卷積核和特征圖
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