经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 大数据/云/AI » 人工智能基础 » 查看文章
AlexNet论文解读
来源:cnblogs  作者:南风丶丶  时间:2024/6/12 16:20:56  对本文有异议

前言

作为深度学习的开山之作AlexNet,确实给后来的研究者们很大的启发,使用神经网络来做具体的任务,如分类任务、回归(预测)任务等,尽管AlexNet在今天看来已经有很多神经网络超越了它,但是它依然是重要的。AlexNet的作者Alex Krizhevsky首次在两块GTX 580 GPU上做神经网络,并且在2012年ImageNet竞赛中取得了冠军,这是一件非常有意义的事情,为后来深度学习的兴起奠定了重要基础,包括现在的显卡公司NVIDIA的市值超越苹果,都有深度学习的一份功劳。

  下面讲解一下AlexNet的网络结构和论文复现。实验为使用AlexNet网络做猫狗分类任务;实验经过了模型搭建,训练,测试以及结果分析。

1.网络结构

AlexNet的网络一共有8层,前5层是卷积层,剩下3层是全连接层,具体如下所示:

第一层:卷积层1,输入为 224 × 224 × 3 的图像,卷积核的数量为96,论文中两片GPU分别计算48个核; 卷积核的大小为 11 × 11 × 3;stride = 4, stride表示的是步长, pad = 0, 表示不扩充边缘;卷积后的图形大小为:wide = (224 + 2 * padding - kernel_size) / stride + 1 = 54,height = (224 + 2 * padding - kernel_size) / stride + 1 = 54,dimention = 96,然后进行 (Local Response Normalized), 后面跟着池化pool_size = (3, 3), stride = 2, pad = 0 最终获得第一层卷积的feature map;

第二层:卷积层2, 输入为上一层卷积的feature map, 卷积的个数为256个,论文中的两个GPU分别有128个卷积核。卷积核的大小为:5 × 5 × 48;pad = 2, stride = 1; 然后做 LRN,最后 max_pooling, pool_size = (3, 3), stride = 2;

第三层:卷积3, 输入为第二层的输出,卷积核个数为384,kernel_size = (3 × 3 × 128),padding = 1,第三层没有做LRN和Pool;

第四层:卷积4, 输入为第三层的输出,卷积核个数为384,kernel_size = (3 × 3 × 192),padding = 1,和第三层一样,没有LRN和Pool;

第五层:卷积5, 输入为第四层的输出,卷积核个数为256,kernel_size = (3 × 3 × 192),padding = 1。然后直接进行max_pooling, pool_size = (3, 3), stride = 2;

第6,7,8层是全连接层,每一层的神经元的个数为4096,最终输出softmax为1000,因为上面介绍过,ImageNet这个比赛的分类个数为1000。全连接层中使用了Relu和Dropout。

2.数据集

数据集为猫狗的图片,其中猫的图片12500张,狗的图片12500张;训练数据集猫12300张,狗12300张,验证集猫100张,狗100张,测试集猫100张,狗100张;数据集链接:https://pan.baidu.com/s/11UHodPIHRDwHiRoae_fqtQ 提取码:d0fa;下图为训练集示意图:

3.数据集分类

将数据集中的猫和狗分别放在train_0和train_1中:

  1. import os
  2. import re
  3. import shutil
  4. origin_path = '/workspace/src/how-to-read-paper/dataset/train'
  5. target_path_0 = '/workspace/src/how-to-read-paper/dataset/train_0/0'
  6. target_path_1 = '/workspace/src/how-to-read-paper/dataset/train_0/1'
  7. os.makedirs(target_path_0, exist_ok=True)
  8. os.makedirs(target_path_1, exist_ok=True)
  9. file_list = os.listdir(origin_path)
  10. for i in range(len(file_list)):
  11. old_path = os.path.join(origin_path, file_list[i])
  12. result = re.findall(r'\w+', file_list[i])[0]
  13. if result == 'cat':
  14. shutil.move(old_path, target_path_0)
  15. else:
  16. shutil.move(old_path, target_path_1)

4.模型搭建

进行模型搭建和数据导入:

  1. import torch
  2. import os
  3. from torch import nn
  4. from torch.nn import functional as F
  5. from torch.autograd import Variable
  6. import matplotlib.pyplot as plt
  7. from torchvision.datasets import ImageFolder
  8. import torch.optim as optim
  9. import torch.utils.data
  10. from PIL import Image
  11. import torchvision.transforms as transforms
  12. # 超参数设置
  13. DEVICE = torch.device('cuda'if torch.cuda.is_available() else 'cpu')
  14. EPOCH = 100
  15. BATCH_SIZE = 256
  16. # 卷积层和全连接层、前向传播
  17. class AlexNet(nn.Module):
  18. def __init__(self, num_classes=2):
  19. super(AlexNet, self).__init__()
  20. # 卷积层
  21. self.features = nn.Sequential(
  22. nn.Conv2d(3, 48, kernel_size=11),
  23. nn.ReLU(inplace=True),
  24. nn.MaxPool2d(kernel_size=3, stride=2),
  25. nn.Conv2d(48, 128, kernel_size=5, padding=2),
  26. nn.ReLU(inplace=True),
  27. nn.MaxPool2d(kernel_size=3, stride=2),
  28. nn.Conv2d(128, 192, kernel_size=3, stride=1, padding=1),
  29. nn.ReLU(inplace=True),
  30. nn.Conv2d(192, 192, kernel_size=3, stride=1, padding=1),
  31. nn.ReLU(inplace=True),
  32. nn.Conv2d(192, 128, kernel_size=3, stride=1, padding=1),
  33. nn.ReLU(inplace=True),
  34. nn.MaxPool2d(kernel_size=3, stride=2),
  35. )
  36. # 全连接层
  37. self.classifier = nn.Sequential(
  38. nn.Linear(6*6*128, 2048),
  39. nn.ReLU(inplace=True),
  40. nn.Dropout(0.5),
  41. nn.Linear(2048, 2048),
  42. nn.ReLU(inplace=True),
  43. nn.Dropout(),
  44. nn.Linear(2048, num_classes),
  45. )
  46. # 前向传播
  47. def forward(self, x):
  48. x = self.features(x)
  49. x = torch.flatten(x, start_dim=1)
  50. x = self.classifier(x)
  51. return x
  52. # 训练集、测试集、验证集的导入
  53. # 归一化处理
  54. normalize = transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
  55. # 训练集
  56. path_1 = '/workspace/src/how-to-read-paper/dataset/train_0'
  57. trans_1 = transforms.Compose([
  58. transforms.Resize((65, 65)),
  59. transforms.ToTensor(),
  60. normalize,
  61. ])
  62. # 数据集
  63. train_set = ImageFolder(root=path_1, transform=trans_1)
  64. # 数据加载器
  65. train_loader = torch.utils.data.DataLoader(train_set, batch_size=BATCH_SIZE, shuffle=True, num_workers=0)
  66. # 测试集
  67. path_2 = '/workspace/src/how-to-read-paper/dataset/test'
  68. trans_2 = transforms.Compose([
  69. transforms.Resize((65, 65)),
  70. transforms.ToTensor(),
  71. normalize,
  72. ])
  73. test_data = ImageFolder(root=path_2, transform=trans_2)
  74. test_loader = torch.utils.data.DataLoader(test_data, batch_size=BATCH_SIZE, shuffle=True, num_workers=0)
  75. # 验证集
  76. path_3 = '/workspace/src/how-to-read-paper/dataset/valid'
  77. trans_3 = transforms.Compose([
  78. transforms.Resize((65, 65)),
  79. transforms.ToTensor(),
  80. normalize,
  81. ])
  82. valid_data = ImageFolder(root=path_3, transform=trans_3)
  83. valid_loader = torch.utils.data.DataLoader(valid_data, batch_size=BATCH_SIZE, shuffle=True, num_workers=0)

5.训练

进行模型训练:

  1. # 定义模型
  2. model = AlexNet().to(DEVICE)
  3. # 优化器的选择
  4. optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9, weight_decay=0.0005)
  5. def train_model(model, device, train_loader, optimizer, epoch):
  6. train_loss = 0
  7. model.train()
  8. for batch_index, (data, label) in enumerate(train_loader):
  9. data, label = data.to(device), label.to(device)
  10. optimizer.zero_grad()
  11. output = model(data)
  12. loss = F.cross_entropy(output, label)
  13. loss.backward()
  14. optimizer.step()
  15. if batch_index % 300 == 0:
  16. train_loss = loss.item()
  17. print('Train Epoch:{}\ttrain loss:{:.6f}'.format(epoch, loss.item()))
  18. return train_loss
  19. def test_model(model, device, test_loader):
  20. model.eval()
  21. correct = 0.0
  22. test_loss = 0.0
  23. # 不需要梯度的记录
  24. with torch.no_grad():
  25. for data, label in test_loader:
  26. data, label = data.to(device), label.to(device)
  27. output = model(data)
  28. test_loss += F.cross_entropy(output, label).item()
  29. pred = output.argmax(dim=1)
  30. correct += pred.eq(label.view_as(pred)).sum().item()
  31. test_loss /= len(test_loader.dataset)
  32. print('Test_average_loss:{:.4f}, Accuracy:{:3f}\n'.format(test_loss, 100*correct/len(test_loader.dataset)))
  33. acc = 100*correct / len(test_loader.dataset)
  34. return test_loss, acc
  35. # 开始训练?
  36. list = []
  37. Train_Loss_list = []
  38. Valid_Loss_list = []
  39. Valid_Accuracy_list = []
  40. for epoch in range(1, EPOCH+1):
  41. # 训练集训练
  42. train_loss = train_model(model, DEVICE, train_loader, optimizer, epoch)
  43. Train_Loss_list.append(train_loss)
  44. torch.save(model, r'/workspace/src/how-to-read-paper/model/model%s.pth' % epoch)
  45. # 验证集进行验证
  46. test_loss, acc = test_model(model, DEVICE, valid_loader)
  47. Valid_Loss_list.append(test_loss)
  48. Valid_Accuracy_list.append(acc)
  49. list.append(test_loss)

6.测试

进行模型测试:

  1. # 验证集的test_loss
  2. min_num = min(list)
  3. min_index = list.index(min_num)
  4. print('model%s' % (min_index+1))
  5. print('验证集最高准确率:')
  6. print('{}'.format(Valid_Accuracy_list[min_index]))
  7. # 取最好的进入测试集进行测试
  8. model = torch.load('/workspace/src/how-to-read-paper/model/model%s.pth' % (min_index+1))
  9. model.eval()
  10. accuracy = test_model(model, DEVICE, test_loader)
  11. print('测试集准确率')
  12. print('{}%'.format(accuracy))

7.实验结果分析

下图为epoch为50和100的loss和acc的折线图,其中使用最优的模型epoch=50时测试集的loss=0.00132, acc=89.0%;其中使用最优的模型epoch=100时测试集的loss=0.00203, acc=91.5%;从实验结果可以看出epoch=20时模型train已经很好了,那么想要train一个更好的模型有方法吗?答案肯定是有的,比如说做一下数据增强、使用正则化项、噪声注入等,这些大家都可以尝试一下。

注:本实验代码地址

 

 

原文链接:https://www.cnblogs.com/xinjieli/p/18009468

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号