終于把卷積神經(jīng)網(wǎng)絡算法搞懂了!??!
大家好,我是小寒
今天給大家介紹一個強大的算法模型,卷積神經(jīng)網(wǎng)絡算法
卷積神經(jīng)網(wǎng)絡(CNN)是一種專為處理像圖像等具有網(wǎng)格拓撲結(jié)構(gòu)的數(shù)據(jù)而設(shè)計的深度學習模型。
CNN 通過使用卷積運算來替代傳統(tǒng)神經(jīng)網(wǎng)絡的全連接層,能夠有效減少參數(shù)數(shù)量并保留空間信息,極大地提升了圖像識別、目標檢測等任務的效果。
圖片
卷積神經(jīng)網(wǎng)絡的基本構(gòu)成
卷積神經(jīng)網(wǎng)絡主要由卷積層、池化層和全連接層組成。
1.卷積層
卷積層是 CNN 的核心組成部分,用于從輸入數(shù)據(jù)中提取局部特征。
其主要運算是通過多個卷積核(filter)對輸入數(shù)據(jù)進行卷積操作,生成特征圖 (feature map)。
圖片
- 卷積核
卷積核是一個小矩陣,它在輸入數(shù)據(jù)上滑動,應用點積運算來提取特定的局部特征。
卷積核的大小和數(shù)量是可調(diào)的超參數(shù)。 - Stride(步幅)
這是卷積核在輸入數(shù)據(jù)上移動的步長。
步幅越大,特征圖的尺寸越小。
圖片
- Padding(填充)
為保持卷積后的輸出尺寸與輸入相同,通常會在輸入數(shù)據(jù)的邊緣進行零填充。
圖片
卷積層的輸出稱為特征圖(Feature Map),通過多次卷積操作,CNN 能夠逐層提取出越來越高層次的特征信息。
2.池化層
池化層的主要作用是通過下采樣來減少數(shù)據(jù)的維度,同時保留輸入的關(guān)鍵信息。
池化層通常插入在卷積層之后,用于減少計算量和參數(shù)數(shù)量,并在某種程度上減輕過擬合的風險。
常見的池化方法有最大池化和平均池化。
- 最大池化
最大池化是最常見的池化操作。它在局部窗口中選擇最大值。
例如,使用一個2x2的窗口,每次移動步長為2,對局部區(qū)域的像素值取最大值。
最大池化的目的在于保留最顯著的特征。
圖片
- 平均池化
它計算局部窗口內(nèi)所有值的平均。平均池化會平滑特征,適合于某些應用場景。
圖片
3.全連接層
在經(jīng)過若干個卷積層和池化層之后,通常會將特征圖展平成一個向量,并將其傳遞給全連接層。
全連接層與傳統(tǒng)的前饋神經(jīng)網(wǎng)絡類似,每個神經(jīng)元與上一層的所有神經(jīng)元相連。
圖片
卷積神經(jīng)網(wǎng)絡的優(yōu)勢
- 局部連接性
通過卷積操作,CNN 能夠捕捉局部的空間特征,減少參數(shù)。 - 權(quán)值共享
卷積核的權(quán)值在圖像中多個位置共享,進一步降低了參數(shù)量。 - 自動提取特征
通過逐層的卷積操作,CNN 可以自動提取從低級到高級的特征,不需要手工設(shè)計特征。
示例代碼
下面是一個使用卷積神經(jīng)網(wǎng)絡(CNN)進行圖像分類的完整示例代碼,采用 PyTorch 框架來實現(xiàn)。
import torch
import torch.nn as nn
import torch.optim as optim
import torchvision
import torchvision.transforms as transforms
# 定義 CNN 模型
class CNNModel(nn.Module):
def __init__(self):
super(CNNModel, self).__init__()
# 定義第一層卷積層,輸入通道為 3(CIFAR-10 中的彩色圖像),輸出通道為 32,卷積核大小為 3x3
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(2, 2)
# 定義全連接層,假設(shè)輸入為 64*8*8,輸出為 512
self.fc1 = nn.Linear(64 * 8 * 8, 512)
# 定義第二個全連接層,輸出為 10(CIFAR-10 有 10 個類別)
self.fc2 = nn.Linear(512, 10)
def forward(self, x):
x = self.pool(torch.relu(self.conv1(x)))
x = self.pool(torch.relu(self.conv2(x)))
x = x.view(-1, 64 * 8 * 8)
x = torch.relu(self.fc1(x))
x = self.fc2(x)
return x
# 超參數(shù)
batch_size = 64
learning_rate = 0.001
num_epochs = 10
# 數(shù)據(jù)預處理
transform = transforms.Compose([
transforms.RandomHorizontalFlip(), # 隨機水平翻轉(zhuǎn)
transforms.RandomCrop(32, padding=4), # 隨機裁剪
transforms.ToTensor(), # 轉(zhuǎn)換為張量
transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)) # 歸一化
])
# 加載 CIFAR-10 數(shù)據(jù)集
trainset = torchvision.datasets.CIFAR10(root='./data', train=True, download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=batch_size, shuffle=True)
testset = torchvision.datasets.CIFAR10(root='./data', train=False, download=True, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=batch_size, shuffle=False)
model = CNNModel()
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=learning_rate)
# 訓練模型
for epoch in range(num_epochs):
running_loss = 0.0
for i, (inputs, labels) in enumerate(trainloader, 0):
inputs, labels = inputs, labels
optimizer.zero_grad()
outputs = model(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
running_loss += loss.item()
if i % 100 == 99:
print(f'Epoch [{epoch + 1}/{num_epochs}], Step [{i + 1}], Loss: {running_loss / 100:.4f}')
running_loss = 0.0
print('Finished Training')
# 在測試集上評估模型
correct = 0
total = 0
with torch.no_grad():
for inputs, labels in testloader:
outputs = model(inputs)
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
print(f'Accuracy of the network on the 10000 test images: {100 * correct / total:.2f}%')