AlexNet网络结构的实现和详解

这篇具有很好参考价值的文章主要介绍了AlexNet网络结构的实现和详解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

alexnet,网络,深度学习,人工智能

AlexNet网络结构特点:

1.首次利用GPU进行网络加速训练 (GPU处理速度是CPU的20-50倍)

2.使用了ReLU激活函数,而不是传统的Sigmoid激活函数(缺点:求导麻烦、容易梯度消失)以及tanh激活函数

alexnet,网络,深度学习,人工智能

 3.使用了LRN(Local Response Normalization)局部相应归一化

4.在全连接层的前两层中使用了Dropout随机失活神经元操作,以减少过拟合

解释一下什么叫过拟合

拟合的函数完美预测训练集,但对新数据的测试集预测结果差。

过度的拟合了训练数据,而没有考虑到泛化能力

根本原因

特征维度过多,模型假设过于复杂,参数过多,训练数据过少,噪声过多

解决方法

使用Dropout的方式在网络正向传播过程中随机失活一部分神经元

alexnet,网络,深度学习,人工智能

 Dropout会在每一层中随机失活一部分神经元,可以理解为变相的减少了网络训练的参数,从而达到减少过拟合的作用

在将AlexNet网络结构之前。首先回顾一下卷积之后的矩阵尺寸大小计算公式

N = (W - F + 2P) / S + 1 

N:卷积之后的矩阵尺寸大小

W:输入图片的大小W * W

F:卷积核的大小F * F

P:padding(补0)的像素p

S:滑动的步长

第一个卷积层

alexnet,网络,深度学习,人工智能

 之所以有上下两部分,是因为有两块GPU进行并行运算

先看一下Conv1 就是框选出来的这一部分

输入图片是一个高为224 宽为224 深度为3的彩色图像

卷积核大小是11*11

所采用的步距是4

padding:[1,2]  在特征矩阵的左边加上1列0 左边加上2列0 上面加上一列0 下面加上2列0

采用卷积核的个数是2*48=96  一层有两个,一共48层

(224-11+2+1)/4 +1 =55

那么第一个卷积层输入:224*224*3

第一个卷积层输出:55*55*96(输出的深度是卷积核的个数)

第一个池化层

alexnet,网络,深度学习,人工智能

第一个池化层的输入:55*55*96

池化层池化核的尺寸:3

padding:0

步长:2

(55-3+2*0)/2+1=27

第一个池化层的输出:27*27*96   (池化操作只会改变特征矩阵的高度和宽度,不会改变深度

第二个卷积层:

alexnet,网络,深度学习,人工智能

 卷积核的个数:2*128=256(也是输出矩阵的深度)

卷积核的尺寸:5*5

padding:[2,2]

步长:1

第二个卷积层输出矩阵的尺寸:

(27-5+2+2)/1+1= 27

第二个卷积层的输入:[27,27,96]

第二个卷积层的输出:[27,27,256]

第二个池化层

alexnet,网络,深度学习,人工智能

 卷积核的尺寸:3

padding:0

stride:2

池化后的矩阵尺寸:

(27-3+2*0)/2+1=13

第二个池化层输入:[27,27,256]

第二个池化层输出:[13,13,256]

第三个卷积层:

alexnet,网络,深度学习,人工智能

 卷积核的个数:2*192=384

卷积核的尺寸:3

padding:[1,1]

stride:1

(13-3+1+1)/1+1=13

第三个卷积层输入:[13,13,256]

第三个卷积层输出:[13,13,384]

第四个卷积层

alexnet,网络,深度学习,人工智能

 卷积核的个数:2*192=384

卷积核的大小:3

padding:[1,1]

步长:1

(13-3+1+1)/1+1=13

第四个卷积层的输入:[13,13,384]

第四个卷积层的输出:[13,13,384]

第五个卷积层

alexnet,网络,深度学习,人工智能

 卷积核的个数:2*128=256

卷积核的大小:3

padding:[1,1]

步长:1

(13-3+1+1)/1+1=13

第五个卷积层的输入:[13,13,384]

第五个卷积层的输出:[13,13,256]

第三个池化层

alexnet,网络,深度学习,人工智能

 池化核的大小:3

padding:0

stride:2

(13-3+2*0)/2+1=6

第三个池化层的输入:[13,13,256]

第三个池化层的输出:[6,6,256]

最后面是三个全连接层,将Maxpool输出的进行展平,然后和三个层进行连接

总结一下这个AlexNet网络结构:
一共是五个卷积层三个全连接层

分别是:

Conv1,Maxpool1,Conv2,Maxpool2,Conv3,Conv4,Conv5,Maxpool3,Full connection1,Full connection2,Full connection3

接下来是本次训练用到的数据集,是一个花分类的数据集

alexnet,网络,深度学习,人工智能

数据集下载地址:

https://storage.googleapis.com/download.tensorflow.org/example_images/flower_photos.tgz

将下载的数据集放在这个文件夹下面,并将压缩包解压

alexnet,网络,深度学习,人工智能

 提前写好一个将数据集分为训练集和测试集的脚本,比例是9:1

下面是脚本的代码

import os
from shutil import copy, rmtree
import random


def mk_file(file_path: str):
    if os.path.exists(file_path):
        # 如果文件夹存在,则先删除原文件夹在重新创建
        rmtree(file_path)
    os.makedirs(file_path)


def main():
    # 保证随机可复现
    random.seed(0)

    # 将数据集中10%的数据划分到验证集中
    split_rate = 0.1

    # 指向你解压后的flower_photos文件夹
    cwd = os.getcwd()
    data_root = os.path.join(cwd, "flower_data")
    origin_flower_path = os.path.join(data_root, "flower_photos")
    assert os.path.exists(origin_flower_path), "path '{}' does not exist.".format(origin_flower_path)

    flower_class = [cla for cla in os.listdir(origin_flower_path)
                    if os.path.isdir(os.path.join(origin_flower_path, cla))]

    # 建立保存训练集的文件夹
    train_root = os.path.join(data_root, "train")
    mk_file(train_root)
    for cla in flower_class:
        # 建立每个类别对应的文件夹
        mk_file(os.path.join(train_root, cla))

    # 建立保存验证集的文件夹
    val_root = os.path.join(data_root, "val")
    mk_file(val_root)
    for cla in flower_class:
        # 建立每个类别对应的文件夹
        mk_file(os.path.join(val_root, cla))

    for cla in flower_class:
        cla_path = os.path.join(origin_flower_path, cla)
        images = os.listdir(cla_path)
        num = len(images)
        # 随机采样验证集的索引
        eval_index = random.sample(images, k=int(num*split_rate))
        for index, image in enumerate(images):
            if image in eval_index:
                # 将分配至验证集中的文件复制到相应目录
                image_path = os.path.join(cla_path, image)
                new_path = os.path.join(val_root, cla)
                copy(image_path, new_path)
            else:
                # 将分配至训练集中的文件复制到相应目录
                image_path = os.path.join(cla_path, image)
                new_path = os.path.join(train_root, cla)
                copy(image_path, new_path)
            print("\r[{}] processing [{}/{}]".format(cla, index+1, num), end="")  # processing bar
        print()

    print("processing done!")


if __name__ == '__main__':
    main()

把脚本文件放在这个文件夹里面

alexnet,网络,深度学习,人工智能

 就在这个页面,按住shit+鼠标右键 ,在终端中打开

 alexnet,网络,深度学习,人工智能

 输入这行代码,然后敲回车

alexnet,网络,深度学习,人工智能

完成

alexnet,网络,深度学习,人工智能 生成了训练集文件夹和测试集文件夹

alexnet,网络,深度学习,人工智能

接下来是代码详解部分

AlexNet网络结构的搭建代码详解

import torch.nn as nn
import torch


class AlexNet(nn.Module):
    def __init__(self, num_classes=1000, init_weights=False):
        super(AlexNet, self).__init__()
        self.features = nn.Sequential(#nn.Sequential能够将一系列层结构组合成一个新的结构   features用于提取图像特征的结构
            nn.Conv2d(3, 48, kernel_size=11, stride=4, padding=2),  # input[3, 224, 224]  output[48, 55, 55] 48是卷积核个数 batch channel high weight
                                                                    #padding参数解释:如果是int型,比如说1 就是上下左右都补1列0  如果传入一个tuple(元组)的话 比如传入(1,2),1代表上下方各补一行0,2代表左右两侧各补两列0
            nn.ReLU(inplace=True),#inplace这个参数可以理解为pytorch通过一种方法增加计算量,来降低内存使用容量的一种方法,可以通过这种方法在内存中载入更大的模型
            nn.MaxPool2d(kernel_size=3, stride=2),                  # output[48, 27, 27]
            nn.Conv2d(48, 128, kernel_size=5, padding=2),           # output[128, 27, 27] 没有设置stride是因为这个卷积层的步长是1,而默认的步长就是1
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=3, stride=2),                  # output[128, 13, 13]
            nn.Conv2d(128, 192, kernel_size=3, padding=1),          # output[192, 13, 13]
            nn.ReLU(inplace=True),
            nn.Conv2d(192, 192, kernel_size=3, padding=1),          # output[192, 13, 13]
            nn.ReLU(inplace=True),
            nn.Conv2d(192, 128, kernel_size=3, padding=1),          # output[128, 13, 13]
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=3, stride=2),                  # output[128, 6, 6]
        )
        self.classifier = nn.Sequential(#包含了三层全连接层 是一个分类器 
            nn.Dropout(p=0.5),#p是每一层随机失活的比例  默认是0.5
            nn.Linear(128 * 6 * 6, 2048),#第一个全连接层,全连接层的节点个数是2048个
            nn.ReLU(inplace=True),
            nn.Dropout(p=0.5),
            nn.Linear(2048, 2048),#第二个全连接层
            nn.ReLU(inplace=True),
            nn.Linear(2048, num_classes),#第三个全连接层 输入的是数据集 类别的个数,默认是1000
        )
        if init_weights:#初始化权重
            self._initialize_weights()

    def forward(self, x):#正向传播过程
        x = self.features(x)
        x = torch.flatten(x, start_dim=1)#进行一个展平处理  将传进来的变量x进行展平,从index=1 这个维度开始 也就是channel
        x = self.classifier(x)
        return x#得到网络的预测输出

    def _initialize_weights(self):
        for m in self.modules():#遍历每一层结构
            if isinstance(m, nn.Conv2d):#判断是哪一个类别
                nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')#kaiming_normal初始化权重方法
                if m.bias is not None:#如果偏置不为空的话,那么就用0去初始化
                    nn.init.constant_(m.bias, 0)
            elif isinstance(m, nn.Linear):#如果这个实例是全连接层
                nn.init.normal_(m.weight, 0, 0.01)#采用normal,也就是正态分布来给我们的权重进行赋值,正态分布的均值等于0,方差是0.01
                nn.init.constant_(m.bias, 0)#将偏置初始化为0

训练模块的代码详解

import os
import sys
import json

import torch
import torch.nn as nn
from torchvision import transforms, datasets, utils
import matplotlib.pyplot as plt
import numpy as np
import torch.optim as optim
from tqdm import tqdm

from model import AlexNet


def main():
    device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")#指定训练过程中所指定的设备 如果有GPU设备就使用第一块GPU设备,如果没有的话,就使用CPU设备
    print("using {} device.".format(device))

    data_transform = {#数据预处理函数
        "train": transforms.Compose([transforms.RandomResizedCrop(224),#随机裁剪成224*224像素大小
                                     transforms.RandomHorizontalFlip(),#在水平方向随机反转
                                     transforms.ToTensor(),#转换成一个张量
                                     transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))]),#进行一个标准化处理 output=(input-0.5)/0.5
        "val": transforms.Compose([transforms.Resize((224, 224)),  # cannot 224, must (224, 224)
                                   transforms.ToTensor(),
                                   transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])}

    data_root = os.path.abspath(os.path.join(os.getcwd(), "../.."))  # get data root path getcwd获取当前文件所在的目录  ..是返回上级目录 ../..是返回上上级目录 path.join是将两个目录连接在一起
    image_path = os.path.join(data_root, "data_set", "flower_data")  # flower data set path
    assert os.path.exists(image_path), "{} path does not exist.".format(image_path)
    train_dataset = datasets.ImageFolder(root=os.path.join(image_path, "train"),
                                         transform=data_transform["train"])
    train_num = len(train_dataset)#记录训练集有多少张图片

    # {'daisy':0, 'dandelion':1, 'roses':2, 'sunflower':3, 'tulips':4}  雏菊 蒲公英 玫瑰 向日葵 郁金香
    flower_list = train_dataset.class_to_idx#获取分类名称所对应的索引
    cla_dict = dict((val, key) for key, val in flower_list.items())#遍历分类索引的字典,然后将key value反过来 变成 0 daisy
    # write dict into json file
    json_str = json.dumps(cla_dict, indent=4) #通过json.dumps将cla这个字典转化为json模式
    with open('class_indices.json', 'w') as json_file:
        json_file.write(json_str)

    batch_size = 32

    train_loader = torch.utils.data.DataLoader(train_dataset,
                                               batch_size=batch_size, shuffle=True,
                                               num_workers=0)

    validate_dataset = datasets.ImageFolder(root=os.path.join(image_path, "val"),
                                            transform=data_transform["val"])
    val_num = len(validate_dataset)
    validate_loader = torch.utils.data.DataLoader(validate_dataset,
                                                  batch_size=batch_size, shuffle=False,
                                                  num_workers=0)

    print("using {} images for training, {} images for validation.".format(train_num,
                                                                           val_num))
    # test_data_iter = iter(validate_loader)
    # test_image, test_label = test_data_iter.next()
    
    # def imshow(img):
    #     img = img / 2 + 0.5  # unnormalize
    #     npimg = img.numpy()
    #     plt.imshow(np.transpose(npimg, (1, 2, 0)))
    #     plt.show()
    
    # print(' '.join('%5s' % cla_dict[test_label[j].item()] for j in range(4)))
    # imshow(utils.make_grid(test_image))

    net = AlexNet(num_classes=5, init_weights=True)

    net.to(device)
    loss_function = nn.CrossEntropyLoss()
    # pata = list(net.parameters())
    optimizer = optim.Adam(net.parameters(), lr=0.0002)

    epochs = 10
    save_path = './AlexNet.pth'#保存权重的路径
    best_acc = 0.0
    train_steps = len(train_loader)
    for epoch in range(epochs):
        # train
        net.train()#dropout只在训练集中使用 而不在验证集中使用
        running_loss = 0.0
        train_bar = tqdm(train_loader, file=sys.stdout)
        for step, data in enumerate(train_bar):
            images, labels = data
            optimizer.zero_grad()
            outputs = net(images.to(device))
            loss = loss_function(outputs, labels.to(device))
            loss.backward()#将损失反向传播
            optimizer.step()#更新节点参数

            # print statistics
            running_loss += loss.item()

            train_bar.desc = "train epoch[{}/{}] loss:{:.3f}".format(epoch + 1,
                                                                     epochs,
                                                                     loss)

        # validate
        net.eval()
        acc = 0.0  # accumulate accurate number / epoch
        with torch.no_grad():
            val_bar = tqdm(validate_loader, file=sys.stdout)
            for val_data in val_bar:
                val_images, val_labels = val_data
                outputs = net(val_images.to(device))
                predict_y = torch.max(outputs, dim=1)[1]
                acc += torch.eq(predict_y, val_labels.to(device)).sum().item()

        val_accurate = acc / val_num
        print('[epoch %d] train_loss: %.3f  val_accuracy: %.3f' %
              (epoch + 1, running_loss / train_steps, val_accurate))

        if val_accurate > best_acc:
            best_acc = val_accurate
            torch.save(net.state_dict(), save_path)

    print('Finished Training')


if __name__ == '__main__':
    main()

训练结果

alexnet,网络,深度学习,人工智能

预测模块的代码详解

import os
import json

import torch
from PIL import Image
from torchvision import transforms
import matplotlib.pyplot as plt

from model import AlexNet


def main():
    device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")

    data_transform = transforms.Compose(
        [transforms.Resize((224, 224)),
         transforms.ToTensor(),
         transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])

    # load image
    img_path = "../tulip.jpg"
    assert os.path.exists(img_path), "file: '{}' dose not exist.".format(img_path)
    img = Image.open(img_path)

    plt.imshow(img)
    # [N, C, H, W]
    img = data_transform(img)
    # expand batch dimension
    img = torch.unsqueeze(img, dim=0)

    # read class_indict
    json_path = './class_indices.json'
    assert os.path.exists(json_path), "file: '{}' dose not exist.".format(json_path)

    with open(json_path, "r") as f:
        class_indict = json.load(f)

    # create model
    model = AlexNet(num_classes=5).to(device)

    # load model weights
    weights_path = "./AlexNet.pth"
    assert os.path.exists(weights_path), "file: '{}' dose not exist.".format(weights_path)
    model.load_state_dict(torch.load(weights_path))

    model.eval()
    with torch.no_grad():
        # predict class
        output = torch.squeeze(model(img.to(device))).cpu()
        predict = torch.softmax(output, dim=0)
        predict_cla = torch.argmax(predict).numpy()

    print_res = "class: {}   prob: {:.3}".format(class_indict[str(predict_cla)],
                                                 predict[predict_cla].numpy())
    plt.title(print_res)
    for i in range(len(predict)):
        print("class: {:10}   prob: {:.3}".format(class_indict[str(i)],
                                                  predict[i].numpy()))
    plt.show()


if __name__ == '__main__':
    main()

 预测结果

alexnet,网络,深度学习,人工智能文章来源地址https://www.toymoban.com/news/detail-753364.html

到了这里,关于AlexNet网络结构的实现和详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 深度学习应用篇-计算机视觉-图像分类[2]:LeNet、AlexNet、VGG、GoogleNet、DarkNet模型结构、实现、模型特点详细介绍

    LeNet是最早的卷积神经网络之一 [1] ,其被提出用于识别手写数字和机器印刷字符。1998年,Yann LeCun第一次将LeNet卷积神经网络应用到图像分类上,在手写数字识别任务中取得了巨大成功。算法中阐述了图像中像素特征之间的相关性能够由参数共享的卷积操作所提取,同时使用

    2024年02月08日
    浏览(30)
  • 大数据深度学习ResNet深度残差网络详解:网络结构解读与PyTorch实现教程

    本文深入探讨了深度残差网络(ResNet)的核心概念和架构组成。我们从深度学习和梯度消失问题入手,逐一解析了残差块、初始卷积层、残差块组、全局平均池化和全连接层的作用和优点。文章还包含使用PyTorch构建和训练ResNet模型的实战部分,带有详细的代码和解释。 深度

    2024年01月18日
    浏览(36)
  • 基于AlexNet深度学习网络的智能垃圾分类系统matlab仿真

    目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 4.1、基于AlexNet深度学习网络的智能垃圾分类系统概述 4.2、基于AlexNet深度学习网络的智能垃圾分类系统主要原理 5.算法完整程序工程 matlab2022a         基于AlexNet深度学习网络的智能垃圾分类系统

    2024年02月07日
    浏览(35)
  • pytorch搭建AlexNet网络实现花分类

    使用Dropout的方式在网络正向传播过程中随机失活一部分神经元,以减少过拟合 对其中的卷积层、池化层和全连接层进行分析 1,Conv1 注意:图片中用了两块GPU并行计算,上下两组图结构一样。 输入:input_size = [224, 224, 3] 卷积层: kernels = 48 * 2 = 96 组卷积核 kernel_size = 11 paddi

    2024年02月09日
    浏览(28)
  • 深度学习图像分类实战——pytorch搭建卷积神经网络(AlexNet, LeNet, ResNet50)进行场景图像分类(详细)

    目录 1  一、实验过程 1.1  实验目的 1.2  实验简介 1.3  数据集的介绍 1.4  一、LeNet5网络模型 1.5  二、AlexNet网络模型 1.6  三、ResNet50(残差网络)网络模型  二、实验代码 导入实验所需要的库  参数配置 数据预处理 重新DataSet 加载数据转为DataLoader函数 可视化一批训练

    2024年02月05日
    浏览(48)
  • 【AI】《动手学-深度学习-PyTorch版》笔记(十八):卷积神经网络模型(LeNet、AlexNet、VGG、NiN)

    发布时间:1989年 模型目的:识别手写数字 1.3.1 相关函数原型 1)nn.Conv2d:卷积层

    2024年02月12日
    浏览(41)
  • 基于Alexnet网络实现猫狗数据集分类(Keras框架)

    程敬,女,西安工程大学电子信息学院,2022级研究生 研究方向:电子信息 电子邮件:1105719037@qq.com 陈梦丹,女,西安工程大学电子信息学院,2022级硕士研究生,张宏伟人工智能课题组 研究方向:机器视觉与人工智能 电子邮件:1169738496@qq.com LeNet于1998年提出的,是最早的神

    2024年02月08日
    浏览(33)
  • CNN经典网络模型(二):AlexNet简介及代码实现(PyTorch超详细注释版)

    一、开发背景 二、网络结构 三、模型特点 四、代码实现 1. model.py 2. train.py 3. predict.py 4. spilit_data.py 五、参考内容 AlexNet由Hinton和他的学生Alex Krizhevsky设计,模型名字来源于论文第一作者的姓名Alex。该模型以很大的优势获得了2012年ISLVRC竞赛的冠军网络,分类准确率由传统的

    2024年04月12日
    浏览(29)
  • 深度学习之图像分类识别(一):AlexNet

    本专栏介绍基于深度学习进行图像识别的经典和前沿模型,将持续更新,包括不仅限于:AlexNet, ZFNet,VGG,GoogLeNet,ResNet,DenseNet,SENet,MobileNet,ShuffleNet,EifficientNet,Vision Transformer,Swin Transformer,Visual Attention Network,ConvNeXt, MLP-Mixer,As-MLP,ConvMixer,MetaFormer 2012年,Alex

    2024年02月04日
    浏览(27)
  • AlexNet的出现推动深度学习的巨大发展

           尽管 AlexNet(2012) 的代码只比 LeNet(1998 )多出几行,但学术界花了很多年才接受深度学习这一概念,并应用其出色的实验结果。        AlexNet(由Alex Krizhevsky、Ilya Sutskever和Geoffrey Hinton共同设计)在架构上相对于早先的LeNet-5等浅层神经网络并没有显著增加代码行数

    2024年02月19日
    浏览(26)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包