創(chuàng)建卷積神經(jīng)網(wǎng)絡(luò)(CNN),很多初學(xué)者不太熟悉,今兒咱們來大概說說,給一個(gè)完整的案例進(jìn)行說明。
CNN 用于圖像分類、目標(biāo)檢測、圖像生成等任務(wù)。它的關(guān)鍵思想是通過卷積層和池化層來自動(dòng)提取圖像的特征,并通過全連接層進(jìn)行分類。
原理
1.卷積層(Convolutional Layer):
卷積層使用卷積操作從輸入圖像中提取特征。卷積操作涉及一個(gè)可學(xué)習(xí)的卷積核(filter/kernel),該核在輸入圖像上滑動(dòng),并計(jì)算滑動(dòng)窗口下的點(diǎn)積。這有助于提取局部特征,使網(wǎng)絡(luò)對平移不變性更強(qiáng)。
公式:
其中,x是輸入,w是卷積核,b是偏置。
2.池化層(Pooling Layer):
池化層用于減小數(shù)據(jù)的空間維度,減少計(jì)算量,并提取最顯著的特征。最大池化是常用的一種方式,在每個(gè)窗口中選擇最大的值。
公式(最大池化):
3.全連接層(Fully Connected Layer):
全連接層用于將卷積和池化層提取的特征映射到輸出類別。它連接到前一層的所有神經(jīng)元。
實(shí)戰(zhàn)步驟和詳解
1.步驟
- 導(dǎo)入必要的庫和模塊。
- 定義網(wǎng)絡(luò)結(jié)構(gòu):使用nn.Module定義一個(gè)繼承自它的自定義神經(jīng)網(wǎng)絡(luò)類,定義卷積層、激活函數(shù)、池化層和全連接層。
- 定義損失函數(shù)和優(yōu)化器。
- 加載和預(yù)處理數(shù)據(jù)。
- 訓(xùn)練網(wǎng)絡(luò):使用訓(xùn)練數(shù)據(jù)迭代訓(xùn)練網(wǎng)絡(luò)參數(shù)。
- 測試網(wǎng)絡(luò):使用測試數(shù)據(jù)評估模型性能。
2.代碼實(shí)現(xiàn)
import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms
# 定義卷積神經(jīng)網(wǎng)絡(luò)類
class SimpleCNN(nn.Module):
def __init__(self):
super(SimpleCNN, self).__init__()
# 卷積層1
self.conv1 = nn.Conv2d(in_channels=1, out_channels=16, kernel_size=3, stride=1, padding=1)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2)
# 卷積層2
self.conv2 = nn.Conv2d(in_channels=16, out_channels=32, kernel_size=3, stride=1, padding=1)
# 全連接層
self.fc1 = nn.Linear(32 * 7 * 7, 10) # 輸入大小根據(jù)數(shù)據(jù)調(diào)整
def forward(self, x):
x = self.conv1(x)
x = self.relu(x)
x = self.pool(x)
x = self.conv2(x)
x = self.relu(x)
x = self.pool(x)
x = x.view(-1, 32 * 7 * 7)
x = self.fc1(x)
return x
# 定義損失函數(shù)和優(yōu)化器
net = SimpleCNN()
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam.NET.parameters(), lr=0.001)
# 加載和預(yù)處理數(shù)據(jù)
transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.5,), (0.5,))])
trAIn_dataset = datasets.MNIST(root='./data', train=True, download=True, transform=transform)
train_loader = torch.utils.data.DataLoader(dataset=train_dataset, batch_size=64, shuffle=True)
# 訓(xùn)練網(wǎng)絡(luò)
num_epochs = 5
for epoch in range(num_epochs):
for i, (images, labels) in enumerate(train_loader):
optimizer.zero_grad()
outputs = net(images)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
if (i+1) % 100 == 0:
print(f'Epoch [{epoch+1}/{num_epochs}], Step [{i+1}/{len(train_loader)}], Loss: {loss.item()}')
# 測試網(wǎng)絡(luò)
net.eval()
with torch.no_grad():
correct = 0
total = 0
for images, labels in test_loader:
outputs = net(images)
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
accuracy = correct / total
print('Accuracy on the test set: {}%'.format(100 * accuracy))
這個(gè)示例展示了一個(gè)簡單的CNN模型,使用MNIST數(shù)據(jù)集進(jìn)行訓(xùn)練和測試。
接下來,咱們添加可視化步驟,更直觀地了解模型的性能和訓(xùn)練過程。
可視化
1.導(dǎo)入matplotlib
import matplotlib.pyplot as plt
2.在訓(xùn)練過程中記錄損失和準(zhǔn)確率:
在訓(xùn)練循環(huán)中,記錄每個(gè)epoch的損失和準(zhǔn)確率。
# 在訓(xùn)練循環(huán)中添加以下代碼
train_loss_list = []
accuracy_list = []
for epoch in range(num_epochs):
running_loss = 0.0
correct = 0
total = 0
for i, (images, labels) in enumerate(train_loader):
optimizer.zero_grad()
outputs = net(images)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
running_loss += loss.item()
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
if (i+1) % 100 == 0:
print(f'Epoch [{epoch+1}/{num_epochs}], Step [{i+1}/{len(train_loader)}], Loss: {loss.item()}')
epoch_loss = running_loss / len(train_loader)
accuracy = correct / total
train_loss_list.Append(epoch_loss)
accuracy_list.append(accuracy)
3.可視化損失和準(zhǔn)確率:
# 在訓(xùn)練循環(huán)后,添加以下代碼
plt.figure(figsize=(12, 4))
# 可視化損失
plt.subplot(1, 2, 1)
plt.plot(range(1, num_epochs + 1), train_loss_list, label='Training Loss')
plt.title('Training Loss')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()
# 可視化準(zhǔn)確率
plt.subplot(1, 2, 2)
plt.plot(range(1, num_epochs + 1), accuracy_list, label='Accuracy')
plt.title('Accuracy')
plt.xlabel('Epochs')
plt.ylabel('Accuracy')
plt.legend()
plt.tight_layout()
plt.show()
這樣,咱們就可以在訓(xùn)練過程結(jié)束后看到訓(xùn)練損失和準(zhǔn)確率的變化。
導(dǎo)入代碼后,大家可以根據(jù)需要調(diào)整可視化的內(nèi)容和格式。