本站原创文章,转载请说明来自《老饼讲解-深度学习》www.bbbdata.com
Inception模型是一系列以Inception模块为特色的卷积神经网络,共有4个版本,第一个版本也称为GoogLeNet模型
本文讲解Inception-V1的模型结构与配置,以及展示pytorch实现Inception-V1(GoogLeNet)的具体代码
通过本文,可以了解Inception-V1、GoogLeNet模型是什么,以及如何使用GoogLeNet来实现图像类别识别
本节讲解GoogLeNet-Inception-V1的模型结构,快速了解Inception-V1是什么
什么是Inception-V1(GoogLeNet)卷积神经网络
Inception系列模型是由谷歌团队开发的一种以Inception模块为特色的卷积神经网络
Inception系列目前共有4个版本,它的第一个版本在2014年提出,并取得了ILSVRC-2014分类任务冠军
当时第一个版本致敬LeNet,取名为GoogLeNet,但有了其它版本后,现在一般称为Inception-V1模型
Inception-V1的原文提供的模型结构图如下:
由于原文的结构图比较头晕,笔者整理后的Inception-V1模型结构如下:
可以看到,GoogLeNet的整个结构由C1-C5、F6共6大层组成
👉1. C1和C2是传统的卷积层
👉2. C3-C5则是由Inception模块堆积的卷积层
👉3. F6是全连接层
总的来说,整个GoogLeNet的侧重点就在于加入了Inception模块,其它的都是继承AlexNet的思想
GoogLeNet模型辅助器说明
GoogLeNet还在模型中还添加了两个预测分支(辅助器0和辅助器1)
它们只用于训练阶段辅助模型训练浅层的模型参数,并不参与最后的模型应用
训练阶段,两个辅助器也同时进行反向传播更新浅层的权重、阈值,
但它们只作为辅助,所以它们在训练时的影响需要削弱,在更新时,只以30%作为权重、阈值的迭代量
GoogLeNet原文加入辅助器是希望浅层能尽快抓住类别特征,但后面的论文发现作用不大,渐渐一般不再使用
本节讲解GoodLeNet-Inception-V1模型的详细配置和具体的运算逻辑
Inception-V1结构与配置详述
从模型流程图可以看到,Inception-V1(GoodLeNet)是一个相对复杂的模型
它包含了并行部分,因此不能以流式直接描述它运算的流程与配置
因此,我们对其分为三部分进行描述:
👉1. Inception的配置格式与具体运算逻辑
👉2. GoodLeNet-Inception-V1模型的主流程配置
👉3. 侧头辅助器
下面我们分别描述这三部分的配置与运算过程:
一、Inception-V1模块的配置格式
Inception-V1模块的结构图如下
其中,输入通道数、每个卷积(共6个)的通道数是待定参数
不妨以下述格式作为Inception-V1模块的配置格式:
C :输入通道数
C1 :Inception内部1×1卷积层的输出通道数
C21:Inception内部3×3卷积层的输出通道数
C31:Inception内部5×5卷积层的输出通道数
C20:Inception内部3×3卷积层之前的1×1降维卷积层的输出通道数
C30:Inception内部5×5卷积层之前的1×1降维卷积层的输出通道数
C4 :Inception内部池化层之后的1×1降维卷积层的输出通道数
一个Inception-V1模块的详细运算流程如下:
Inception-V1模型的详细配置
GoodLeNetinception-V1的主流程的配置与运算流程如下:
GoogLeNet辅助器的参数与运算流程
两个辅助器的流程基本是一致的,只是输入的通道数不同,导致卷积层的输入通道不同,其它是一致的
两个辅助器的具体参数和运算流程如下
本节讲解Inception-v1(GoogLeNet)模型的代码实现与使用示例
Inception-v1(GoogLeNet)-代码实现
在pytorch中可以用googlenet来构建一个InceptionV1模型
下面我们打印出pytroch的googlenet模型结构:
from torchvision import models
model = models.googlenet(init_weights=False) # 初始化GoogLeNet模型(InceptionV1)
print('\n GoogLeNet的模块:\n',dict(model.named_children())) # 打印GoogLeNet模型结构
可以看到,Pytorch所提供的GoogLeNet模型会与原文多多少少有些小出入,其它的深度学习框架也是一样
例如,在Pytorch的GoogLeNet中,没有使用LRN局部归一化,而是使用BN批归一化
因为毕竟GoogLeNet是较早的模型,随着时间的推移,一些无效的内容在实践中就会被淘汰
因此,GoogLeNet原文中的模型结构更多是学习时作为模型基准,而在实践中应灵活变通,与时俱进
Inception-V1(GoogLeNet)-代码实现
下面展示如何训练一个Inception-V1卷积神经网络用于图片类别识别
具体代码如下:
import torchvision
import torch
from torch.utils.data import DataLoader
import numpy as np
model = torchvision.models.googlenet(num_classes=102) # 初始化模型
print('\n googlenet的模块:\n',dict(model.named_children()) )
# 训练函数
def train(dataloader,valLoader,model,epochs,goal,device):
for epoch in range(epochs):
err_num = 0 # 本次epoch评估错误的样本
eval_num = 0 # 本次epoch已评估的样本
print('-----------当前epoch:',str(epoch),'----------------')
for batch, (imgs, labels) in enumerate(dataloader):
# -----训练模型-----
x, y = imgs.to(device), labels.to(device) # 将数据发送到设备
optimizer.zero_grad() # 将优化器里的参数梯度清空
py = model(x) # 计算模型的预测值
loss=lossFun(py.logits, y) # 计算损失函数值
+0.3*lossFun(py.aux_logits1, y)
+0.3*lossFun(py.aux_logits2, y)
loss.backward() # 更新参数的梯度
optimizer.step() # 更新参数
# ----计算错误率----
idx = torch.argmax(py.logits,axis=1) # 模型的预测类别
eval_num = eval_num + len(idx) # 更新本次epoch已评估的样本
err_num = err_num +sum(y != idx) # 更新本次epoch评估错误的样本
if(batch%10==0): # 每10批打印一次结果
print('err_rate:',err_num/eval_num) # 打印错误率
# -----------验证数据误差---------------------------
model.eval() # 将模型调整为评估状态
val_acc_rate = calAcc(model,valLoader,device) # 计算验证数据集的准确率
model.train() # 将模型调整回训练状态
print("验证数据的准确率:",val_acc_rate) # 打印准确率
if((err_num/eval_num)<=goal): # 检查退出条件
break
print('训练步数',str(epoch),',最终训练误差',str(err_num/eval_num))
# 计算数据集的准确率
def calAcc(model,dataLoader,device):
py = np.empty(0) # 初始化预测结果
y = np.empty(0) # 初始化真实结果
for batch, (imgs, labels) in enumerate(dataLoader): # 逐批预测
cur_py = model(imgs.to(device)) # 计算网络的输出
cur_py = torch.argmax(cur_py,axis=1) # 将最大者作为预测结果
py = np.hstack((py,cur_py.detach().cpu().numpy())) # 记录本批预测的y
y = np.hstack((y,labels)) # 记录本批真实的y
acc_rate = sum(y==py)/len(y) # 计算测试样本的准确率
return acc_rate
# -------模型参数初始化----------------------
def init_param(model):
param_dict = dict(model.named_parameters()) # 获取模型的参数字典
for key in param_dict: # 历遍每个参数,对其初始化
param_name = key.split(".")[-1] # 获取参数的尾缀作为名称
if (param_name=='weight'): # 如果是权重
torch.nn.init.normal_(param_dict[key]) # 则正态分布初始化
elif (param_name=='bias'): # 如果是阈值
torch.nn.init.zeros_(param_dict[key]) # 则初始化为0
#-------------主流程脚本----------------------------------
#-------------------加载数据-----------------------
trainsform =torchvision.transforms.Compose([
torchvision.transforms.Resize([224, 224]),
torchvision.transforms.ToTensor(),
]
)
train_data = torchvision.datasets.Flowers102(
root = 'D:\pytorch\data' # 路径,如果路径有,就直接从路径中加载,如果没有,就联网获取
,split ='train' # 训练数据
,transform = trainsform # 转换数据
,download = True # 是否下载,选为True,就下载到root下面
,target_transform= None)
val_data = torchvision.datasets.Flowers102(
root = 'D:\pytorch\data' # 路径,如果路径有,就直接从路径中加载,如果没有,就联网获取
,split ='test' # 测试数据
,transform = trainsform # 转换数据
,download = True # 是否下载,选为True,就下载到root下面
,target_transform= None)
#-------------------模型训练--------------------------------
trainLoader = DataLoader(train_data, batch_size=30, shuffle=True) # 将数据装载到DataLoader
valLoader = DataLoader(val_data , batch_size=30) # 将验证数据装载到DataLoader
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') # 设置训练设备
init_param(model) # 初始化模型参数
model = model.to(device) # 发送到设备
lossFun = torch.nn.CrossEntropyLoss() # 定义损失函数为交叉熵损失函数
optimizer = torch.optim.SGD(model.parameters(), lr=0.01,momentum =0.9) # 初始化优化器
train(trainLoader,valLoader,model,1000,0.01,device) # 训练模型,训练100步,错误低于1%时停止训练
# -----------模型效果评估---------------------------
model.eval() # 将模型切换到评估状态(屏蔽Dropout)
train_acc_rate = calAcc(model,trainLoader,device) # 计算训练数据集的准确率
print("训练数据的准确率:",train_acc_rate) # 打印准确率
val_acc_rate = calAcc(model,valLoader,device) # 计算验证数据集的准确率
print("验证数据的准确率:",val_acc_rate)
备注:代码未亲测,仅供参考
好了,上述就是GoogLeNet-Inception-V1的模型结构的全部介绍内容了~
End