AlexNet的出现,引发人工技能的浪潮.
尽管后续出现vgg, Google系列,ResNet,DenseNet等等更深更优秀的网络,但对AlexNet有着特殊的情怀.
AlexNet的网络结构
摘自 学习笔记:大话经典模型AlexNet、VGGNet、GoogLeNet、ResNet
Pytorch代码
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
""" * * *** * * * *
@File :AlexNet.py * * * * * * *
@Date :5/9/20 * * * ** * *
@Require :pytorch ***** * ** * *
@Author :hjxu * * * ** * *
* * * * * * * *
* * *** * * *****
@Funtion : AlexNet 定义
"""
import torch
import torch.nn as nn
import torchvision
class AlexNet(nn.Module):
def __init__(self, num_classes=1000):
super(AlexNet, self).__init__()
self.feature_extraction = nn.Sequential(
nn.Conv2d(in_channels=3, out_channels=96, kernel_size=11, stride=4, padding=2, bias=False),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=3, stride=2, padding=0),
nn.Conv2d(in_channels=96, out_channels=192, kernel_size=5, stride=1, padding=2, bias=False),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=3, stride=2, padding=0),
nn.Conv2d(in_channels=192, out_channels=384, kernel_size=3, stride=1, padding=1, bias=False),
nn.ReLU(inplace=True),
nn.Conv2d(in_channels=384, out_channels=256, kernel_size=3, stride=1, padding=1, bias=False),
nn.ReLU(inplace=True),
nn.Conv2d(in_channels=256, out_channels=256, kernel_size=3, stride=1, padding=1, bias=False),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=3, stride=2, padding=0),
)
self.classifier = nn.Sequential(
nn.Dropout(p=0.5),
nn.Linear(in_features=256*6*6, out_features=4096),
nn.ReLU(inplace=True),
nn.Dropout(p=0.5),
nn.Linear(in_features=4096, out_features=4096),
nn.ReLU(inplace=True),
nn.Linear(in_features=4096, out_features=num_classes),
)
def forward(self,x):
x = self.feature_extraction(x)
x = x.view(x.size(0), 256*6*6)
x = self.classifier(x)
return x
if __name__ == '__main__':
# net = torchvision.models.AlexNet()
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
net = AlexNet()
from torchsummary import summary
print(summary(net, (3, 224, 224), device="cpu"))
print("############################################")
print(net)
input = torch.randn(8, 3, 224, 224)
out = net(input)
print(out.shape)
50轮迭代,准确率0.98
训练脚本如下:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
""" * * *** * * * *
@File :train.py * * * * * * *
@Date : * * * ** * *
@Require : ***** * ** * *
@Author :hjxu * * * ** * *
* * * * * * * *
* * *** * * *****
@Funtion : 训练脚本
"""
from __future__ import print_function, division
import numpy as np
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torch.autograd import Variable
from torch.utils.data import Dataset
from torchvision import transforms, datasets, models
from CnnNet import AlexNet
from DataLoader import DogCatDataSet
# 配置参数
random_state = 1
torch.manual_seed(random_state) # 设置随机数种子,确保结果可重复
torch.cuda.manual_seed(random_state)
torch.cuda.manual_seed_all(random_state)
np.random.seed(random_state)
# random.seed(random_state)
epochs = 70 # 训练次数
batch_size = 32 # 批处理大小
num_workers = 4 # 多线程的数目
use_gpu = torch.cuda.is_available()
# 对加载的图像作归一化处理, 并裁剪为[224x224x3]大小的图像
data_transform = transforms.Compose([
transforms.Resize(256),
transforms.CenterCrop(224),
transforms.ToTensor(),
])
train_dataset = DogCatDataSet(img_dir="./data/train", transform=data_transform)
train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=batch_size, shuffle=True, num_workers=4)
test_dataset = DogCatDataSet(img_dir="./data/validation", transform=data_transform)
test_loader = torch.utils.data.DataLoader(train_dataset, batch_size=batch_size, shuffle=True, num_workers=4)
# 加载resnet18 模型,
# net = SimpleCNN.MobileNetV1()
# net = models.MobileNetV2(num_classes=2)
net = AlexNet.AlexNet(num_classes=2)
# num_ftrs = net.fc.in_features
# net.fc = nn.Linear(num_ftrs, 2) # 更新resnet18模型的fc模型,
if use_gpu:
net = net.cuda()
print(net)
'''
Net (
(conv1): Conv2d(3, 6, kernel_size=(5, 5), stride=(1, 1))
(maxpool): MaxPool2d (size=(2, 2), stride=(2, 2), dilation=(1, 1))
(conv2): Conv2d(6, 16, kernel_size=(5, 5), stride=(1, 1))
(fc1): Linear (44944 -> 2048)
(fc2): Linear (2048 -> 512)
(fc3): Linear (512 -> 2)
)
'''
# 定义loss和optimizer
cirterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)
# 开始训练
net.train()
for epoch in range(epochs):
if((epoch + 1) % 20 == 0):
for param_group in optimizer.param_groups:
lr = param_group['lr']
param_group['lr'] = lr * 0.1
running_loss = 0.0
train_correct = 0
train_total = 0
for i, data in enumerate(train_loader, 0):
inputs, train_labels = data
if use_gpu:
inputs, labels = Variable(inputs.cuda()), Variable(train_labels.cuda())
else:
inputs, labels = Variable(inputs), Variable(train_labels)
# inputs, labels = Variable(inputs), Variable(train_labels)
optimizer.zero_grad()
outputs = net(inputs)
_, train_predicted = torch.max(outputs.data, 1)
# import pdb
# pdb.set_trace()
train_correct += (train_predicted == labels.data).sum()
loss = cirterion(outputs, labels)
loss.backward()
optimizer.step()
running_loss += loss.item()
print("epoch: ", epoch, " loss: ", loss.item())
train_total += train_labels.size(0)
print('train %d epoch loss: %.3f acc: %.3f ' % (
epoch + 1, running_loss / train_total * batch_size, 100 * train_correct / train_total))
# 模型测试
correct = 0
test_loss = 0.0
test_total = 0
test_total = 0
net.eval()
for data in test_loader:
images, labels = data
if use_gpu:
images, labels = Variable(images.cuda()), Variable(labels.cuda())
else:
images, labels = Variable(images), Variable(labels)
outputs = net(images)
_, predicted = torch.max(outputs.data, 1)
loss = cirterion(outputs, labels)
test_loss += loss.item()
test_total += labels.size(0)
correct += (predicted == labels.data).sum()
print('test %d epoch loss: %.3f acc: %.3f ' % (epoch + 1, test_loss / test_total * batch_size, 100 * correct / test_total))
torch.save(net, "./model/AlexNet.pth")