当前位置: 首页 > news >正文

四、CV_GoogLeNet

四、GoogLeNet

GoogLeNet在加深度的同时做了结构上的创新,引入了一个叫做Inception的结构来代替之前的卷积加激活的经典组件。

1.Inception块

GoogLeNet中的基础卷积块叫做Inception块,其结构较为复杂

Inception块里有4条并行的线路,前三条线路使用窗口大小分别是1 ×\times× 1、3 ×\times× 3、5 ×\times× 5的卷积层来抽取不同空间尺寸下的信息,其中中间2个线路会对输入先做1 ×\times× 1卷积来减少输入通道数,以降低模型复杂度。第4条线路则使用3 ×\times× 3最大池化层,后接1 ×\times× 1卷积层来改变通道数。4条线路都使用了合适的填充来使输入与输出的高宽一致。最后我们将每条线路的输出在通道维上连结,并向后进行传播

(1)1 ×\times× 1卷积

它和其他卷积核的唯一区别是 没有考虑在特征图局部信息之间的关系

1 ×\times× 1卷积的作用

  • 实现跨通道的交互和信息整合
  • 卷积核通道数的降维(通道数减少)和升维,减少网络参数

在tf.keras中实现Inception模块,各个卷积层卷积核的个数通过参数来控制

# 定义Inception模块
class Inception(tf.keras.layers.Layer):def __init__(self, c1, c2, c3, c4):super().__init__()#线路1self.p1_1 = tf.keras.layers.Conv2D(c1, kernel_size = 1, activation = 'relu', padding = 'same')# 线路2self.p2_1 = tf.keras.layers.Conv2D(c2[0], kernel_size = 1, activation = 'relu', padding = 'same')self.p2_2 = tf.keras.layers.Conv2D(c1[1], kernel_size = 3, activation = 'relu', padding = 'same')# 线路3self.p3_1 = tf.keras.layers.Conv2D(c3[0], kernel_size = 1, activation = 'relu', padding = 'same')self.p3_1 = tf.keras.layers.Conv2D(c3[1], kernel_size = 5, activation = 'relu', padding = 'same')# 线路4self.p4_1 = tf.keras.layers.MaxPool2D(pool_size = 3, padding = 'same', strides = 1)self.p3_1 = tf.keras.layers.Conv2D(c4, kernel_size = 1, activation = 'relu', padding = 'same')# 完成前向传播过程def call(self, x):p1 = self.p1_1(x)p2 = self.p2_2(self.p2_1(x))p3 = self.p3_2(self.p3_1(x))p4 = self.p4_2(self.p4_1(x))# 在通道维上concat输出outputs = tf.concat([p1, p2, p3, p4], axis = -1)return outputs

指定通道数,对Inception模块进行实例化

Inception(64, (96, 128), (16, 32), 32) # 每个卷积层的卷积核数

2.GoogLeNet模型

GoogLeNet主要由Inception块构成

整个网络架构分为五个模块(B1, B2, B3, B4, B5 ),每个模块之间使用步幅为2的3×\times×3最大池化层来减小输出高宽

(1)B1模块

第一模块使用了一个64通道的7 ×\times× 7卷积层

# 定义模型的输入
inputs = tf.keras.Input(shape = (224, 224, 3), name = 'input')x = tf.keras.layers.Conv2D(64, kernel_size = 7, strides = 2, padding = 'same', activation = 'relu')(inputs)x = tf.keras.layers.MaxPool2D(pool_size = 3, strides = 2, padding = 'same')(x)

(2)B2模块

第二个模块使用2个卷积层:首先是64通道的1 ×\times× 1卷积层,然后是将通道增大3倍的3 ×\times× 3卷积层

# B2模块x = tf.keras.layers.Conv2D(64, kernel_size = 1, padding = 'same', activation = 'relu')(x)
x = tf.keras.layers.Conv2D(192, kernel_size = 3, padding = 'same', activation = 'relu')(x)
x = tf.keras.layers.MaxPool2D(pool_size = 3, padding = 'same', strides = 2)(x)

(3)B3模块

第三个模块串联2个完整的Inception块。第一个Inception块的通道数是64+128+32+32=25664+128+32+32=25664+128+32+32=256,第二个Inception块输出通道数增至128+192+96+64=480128+192+96+64=480128+192+96+64=480

# B3模块x = Inception(64, (96, 128), (16, 32), 32)(x)
x = Inception(128, (128, 192), (32, 96), 64)(x)
x = tf.keras.layers.MaxPool2D(pool_size = 3, strides = 2, padding = 'same')(x)

(4)B4模块

第四模块更加复杂,它串联了5个Inception模块,其输出通道数分别是

192+208+48+64=512192+208+48+64=512192+208+48+64=512

160+224+64+64=512160+224+64+64=512160+224+64+64=512

128+256+64+64=512128+256+64+64=512128+256+64+64=512

112+288+64+64=528112+288+64+64=528112+288+64+64=528

26+320+128+128=83226+320+128+128=83226+320+128+128=832

并且增加了辅助分类器(放在第一个Inception后面和最后一个Inception前面),根据实验发现网络的中间层具有很强的识别能力,为了利用中间层抽象的特征,在某些中间层中添加含有多层的分类器,如下图所示:

辅助分类器实现:
def aux_classifier(x, filter_size):# x是输入数据,filter_size:卷积层卷积核个数,全连接层神经元个数# 池化层x = tf.keras.layers.AveragePooling2D(pool_size = 5, strides = 3, padding = 'same')(x)# 1x1卷积层x = tf.keras.layers.Conv2D(filters = filter_size[0], kernel_size = 1, strides = 1, padding = 'valid', activation = 'relu')(x)# 展平x = tf.keras.layers.Flatten()(x)# 全连接层x = tf.keras.layers.Dense(units = filter_size[1], activation = 'relu')(x)# Softmax输出层x = tf.keras.layers.Dense(units = 10, activation = 'softmax')(x)return x
B4模块实现
# B4模块#Inception
x = Inception(192, (96, 208), (16, 48), 64)(x)
# 辅助输出1
aux_output_1 = aux_classifier(x, [128, 1024])
# Inception
x = Inception(160, (112, 224), (24, 64), 64)(x)
# Inception
x = Inception(128, (128, 256), (24, 64), 64)(x)
# Inception
x = Inception(112, (144, 288), (32, 64), 64)(x)
# 辅助输出2
aux_output_2 = aux_classifier(x, [128, 1024])
# Inception
x = Inception(256, (160, 320), (32, 128), 128)(x)
# 最大池化
x = tf.keras.layers.MaxPool2D(pool_size = 3, strides = 2, padding = 'same')(x)

(5)B5模块

它串联了2个Inception模块,其输出通道数分别是

256+320+128+128=832256+320+128+128=832256+320+128+128=832

384+384+128+128=1024384+384+128+128=1024384+384+128+128=1024

后面紧跟输出层,该模块使用全局平均池化层(GPA)来将每个通道的高和宽变成1。最后输出变成二维数组后接 输出个数为标签类别数 的全连接层。

全局平均池化层(GPA)

用来替代全连接层,将特征图每一通道中所有像素值相加后求平均,得到就是GPA的结果,再将其送入后续网络中进行计算

实现过程:

# B5模块
# Inception
x = Inception(256, (160, 320), (32, 128), 128)(x)
# Inception
x = Inception(384, (192, 384), (48, 128), 128)(x)
# GPA
x = tf.keras.layers.GlobalAvgPool2D()(x)
# 输出层
main_outputs = tf.keras.layers.Dense(10, activation = 'softmax')(x)

(6)最终

构建GooLeNet模型并通过summary来看下模型的结构:

# 使用Model来创建模型,指明输入和输出
model = tf.keras.Model(inputs = inputs, outputs = [main_outputs, aux_output_1, aux_output_2])
model.summary()

3.手写数字识别

(1)数据读取

import numpy as np
from tensorflow.keras.datasets import mnist(train_images, train_labels), (test_images, test_labels) = mnist.load_data()# N H W C
train_images = np.reshape(train_images, (train_images.shape[0], train_images.shape[1], train_images.shape[2], 1))test_images = np.reshape(test_images, (test_images.shape[0], test_images.shape[1], test_images.shape[2], 1))
# 定义两个方法随机抽取部分样本演示def get_train(size):index = np.random.randint(0, np.shape(train_images)[0], size)resize_images = tf.image.resize_with_pad(train_images[index], 224, 224, )return resize_images.numpy(), train_labels[index]def get_test(size):index = np.random.randint(0, np.shape(test_images)[0], size)resize_images = tf.image.resize_with_pad(test_images[index], 224, 224, )return resize_images.numpy(), test_labels[index]
# 获取训练样本和测试样本
train_image, train_label = get_train(256)
test_image, test_label = get_test(128)

(2)模型编译

  • 有三个输出,需指定权重
# 优化器,损失函数,评价指标
model.compile(optimizer = tf.keras.optimizers.SGD(learning_rate = 0.01),loss = tf.keras.losses.sparse_categorical_crossentropy,metrics = ['accuracy'],loss_weights = [1, 0.3, 0.3])

(3)模型训练

model.fit(train_images, train_labels, batch_size = 128, epochs = 3, verbose = 1, validation_split = 0.1)

(4)模型评估

model.evaluate(test_images, test_labels, verbose = 1)

4.延伸版本

(1)InceptionV2

在InceptionV2中将大卷积核拆分为小卷积核,将V1中的5 ×\times× 5卷积用两个3 ×\times× 3的卷积代替,从而增加网络的深度,减少了参数

(2)InceptionV3

将n ×\times× n卷积分割为1 ×\times× n和n ×\times× 1两个卷积,例如,一个3 ×\times× 3的卷积首先执行一个1 ×\times× 3的卷积,然后执行一个3 ×\times× 1的卷积,这种方法的参数量和计算量均降低

http://www.dtcms.com/a/285618.html

相关文章:

  • 代码训练营DAY35 第九章 动态规划part03
  • 【收集电脑信息】collect_info.sh
  • 【NLP舆情分析】基于python微博舆情分析可视化系统(flask+pandas+echarts) 视频教程 - 基于jieba实现词频统计
  • Kubernetes Pod深度理解
  • 【数据可视化-67】基于pyecharts的航空安全深度剖析:坠毁航班数据集可视化分析
  • 【问题解决】npm包下载速度慢
  • 【AI大模型学习路线】第三阶段之RAG与LangChain——第十八章(基于RAGAS的RAG的评估)RAG中的评估思路?
  • 把握流程节点,明确信息传递
  • C专题5:函数进阶和递归
  • 最小生成树算法详解
  • 2025外卖江湖:巨头争霸,谁主沉浮?
  • 洞见AI时代数据底座的思考——YashanDB亮相2025可信数据库发展大会
  • NIO网络通信基础
  • AndroidX中ComponentActivity与原生 Activity 的区别
  • 关于字符编辑器vi、vim版本的安装过程及其常用命令:
  • 从抓包GitHub Copilot认证请求,认识OAuth 2.0技术
  • web3 区块链技术与用
  • 基于深度学习的语音识别:从音频信号到文本转录
  • 开源的大语言模型(LLM)应用开发平台Dify
  • 如何用Python并发下载?深入解析concurrent.futures 与期物机制
  • 服务攻防-Java组件安全FastJson高版本JNDI不出网C3P0编码绕WAF写入文件CI链
  • ARM64高速缓存,内存属性及MAIR配置
  • 预测导管原位癌浸润性复发的深度学习:利用组织病理学图像和临床特征
  • Nand2Tetris(计算机系统要素)学习笔记 Project 3
  • sqli(1-8)
  • ASP.NET Core Web API 内存缓存(IMemoryCache)入门指南
  • Pytorch下载Mnist手写数据识别训练数据集的代码详解
  • PyTorch新手实操 安装
  • 填坑 | React Context原理
  • SpringMVC + Tomcat10