深度学习 精选笔记(13.1)卷积神经网络-LeNet模型

news2024/9/11 10:06:10

学习参考:

  • 动手学深度学习2.0
  • Deep-Learning-with-TensorFlow-book
  • pytorchlightning

①如有冒犯、请联系侵删。
②已写完的笔记文章会不定时一直修订修改(删、改、增),以达到集多方教程的精华于一文的目的。
③非常推荐上面(学习参考)的前两个教程,在网上是开源免费的,写的很棒,不管是开始学还是复习巩固都很不错的。

深度学习回顾,专栏内容来源多个书籍笔记、在线笔记、以及自己的感想、想法,佛系更新。争取内容全面而不失重点。完结时间到了也会一直更新下去,已写完的笔记文章会不定时一直修订修改(删、改、增),以达到集多方教程的精华于一文的目的。所有文章涉及的教程都会写在开头、一起学习一起进步。

1.LeNet模型结构

LeNet(LeNet-5)由两个部分组成:

  • 卷积编码器:由两个卷积层组成;
  • 全连接层密集块:由三个全连接层组成。

结构如下:
在这里插入图片描述

每个卷积块中的基本单元是一个卷积层、一个sigmoid激活函数和平均汇聚层。请注意,虽然ReLU和最大汇聚层更有效,但它们在20世纪90年代还没有出现(所以该模型就没有)。

每个卷积层使用 5×5 卷积核和一个sigmoid激活函数。些层将输入映射到多个二维特征输出,通常同时增加通道的数量。第一卷积层有6个输出通道,而第二个卷积层有16个输出通道。每个 2×2池操作(步幅2)通过空间下采样将维数减少4倍。卷积的输出形状由批量大小、通道数、高度、宽度决定。
在这里插入图片描述

为了将卷积块的输出传递给稠密块(全连接那部分),必须在小批量中展平每个样本。换言之,将这个四维输入转换成全连接层所期望的二维输入。这里的二维表示的第一个维度索引小批量中的样本,第二个维度给出每个样本的平面向量表示。LeNet的稠密块有三个全连接层,分别有120、84和10个输出。因为在执行分类任务,所以输出层的10维对应于最后输出结果的数量。

请注意,在整个卷积块中,与上一层相比,每一层特征的高度和宽度都减小了。 第一个卷积层使用2个像素的填充,来补偿 5×5
卷积核导致的特征减少。 相反,第二个卷积层没有填充,因此高度和宽度都减少了4个像素。 随着层叠的上升,通道的数量从输入时的1个,增加到第一个卷积层之后的6个,再到第二个卷积层之后的16个。 同时,每个汇聚层的高度和宽度都减半。最后,每个全连接层减少维数,最终输出一个维数与结果分类数相匹配的输出。

模型结构实现如下:(对原始模型做了一点小改动,去掉了最后一层的高斯激活。除此之外,这个网络与最初的LeNet-5一致。)

import tensorflow as tf
from d2l import tensorflow as d2l


def net():
    return tf.keras.models.Sequential([
        tf.keras.layers.Conv2D(filters=6, kernel_size=5, activation='sigmoid',
                               padding='same'),
        tf.keras.layers.AvgPool2D(pool_size=2, strides=2),
        tf.keras.layers.Conv2D(filters=16, kernel_size=5,
                               activation='sigmoid'),
        tf.keras.layers.AvgPool2D(pool_size=2, strides=2),
        tf.keras.layers.Flatten(),
        tf.keras.layers.Dense(120, activation='sigmoid'),
        tf.keras.layers.Dense(84, activation='sigmoid'),
        tf.keras.layers.Dense(10)])

将一个大小为 28×28 的单通道(黑白)图像通过LeNet。通过在每一层打印输出的形状,可以检查模型,以确保其操作与期望的结构 一致。

X = tf.random.uniform((1, 28, 28, 1))
for layer in net().layers:
    X = layer(X)
    print(layer.__class__.__name__, 'output shape: \t', X.shape)

如下,输出维度和层次变化与结构一致,说明模型没有搭建出错。

Conv2D output shape: 	 (1, 28, 28, 6)
AveragePooling2D output shape: 	 (1, 14, 14, 6)
Conv2D output shape: 	 (1, 10, 10, 16)
AveragePooling2D output shape: 	 (1, 5, 5, 16)
Flatten output shape: 	 (1, 400)
Dense output shape: 	 (1, 120)
Dense output shape: 	 (1, 84)
Dense output shape: 	 (1, 10)

2.LeNet5在Fashion-MNIST数据集上的表现

虽然卷积神经网络的参数较少,但与深度的多层感知机相比,它们的计算成本仍然很高,因为每个参数都参与更多的乘法。

batch_size = 256
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size=batch_size)

通过使用GPU,可以用它加快训练。为了使用GPU,还需要一点小改动,在进行正向和反向传播之前,需要将每一小批量数据移动到我们指定的设备(例如GPU)上。将实现多层神经网络,因此将主要使用高级API。 以下训练函数假定从高级API创建的模型作为输入,并进行相应的优化。

  • 使用在 Xavier随机初始化模型参数。
  • 使用交叉熵损失函数和小批量随机梯度下降。
class TrainCallback(tf.keras.callbacks.Callback):  #@save
    """一个以可视化的训练进展的回调"""
    def __init__(self, net, train_iter, test_iter, num_epochs, device_name):
        self.timer = d2l.Timer()
        self.animator = d2l.Animator(
            xlabel='epoch', xlim=[1, num_epochs], legend=[
                'train loss', 'train acc', 'test acc'])
        self.net = net
        self.train_iter = train_iter
        self.test_iter = test_iter
        self.num_epochs = num_epochs
        self.device_name = device_name

    def on_epoch_begin(self, epoch, logs=None):
        self.timer.start()

    def on_epoch_end(self, epoch, logs):
        self.timer.stop()
        test_acc = self.net.evaluate(
            self.test_iter, verbose=0, return_dict=True)['accuracy']
        metrics = (logs['loss'], logs['accuracy'], test_acc)
        self.animator.add(epoch + 1, metrics)
        if epoch == self.num_epochs - 1:
            batch_size = next(iter(self.train_iter))[0].shape[0]
            num_examples = batch_size * tf.data.experimental.cardinality(
                self.train_iter).numpy()
            print(f'loss {metrics[0]:.3f}, train acc {metrics[1]:.3f}, '
                  f'test acc {metrics[2]:.3f}')
            print(f'{num_examples / self.timer.avg():.1f} examples/sec on '
                  f'{str(self.device_name)}')

#@save
def train_ch6(net_fn, train_iter, test_iter, num_epochs, lr, device):
    """用GPU训练模型(在第六章定义)"""
    device_name = device._device_name
    strategy = tf.distribute.OneDeviceStrategy(device_name)
    with strategy.scope():
        optimizer = tf.keras.optimizers.SGD(learning_rate=lr)
        loss = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True)
        net = net_fn()
        net.compile(optimizer=optimizer, loss=loss, metrics=['accuracy'])
    callback = TrainCallback(net, train_iter, test_iter, num_epochs,
                             device_name)
    net.fit(train_iter, epochs=num_epochs, verbose=0, callbacks=[callback])
    return net

训练和评估LeNet-5模型:

lr, num_epochs = 0.9, 10
train_ch6(net, train_iter, test_iter, num_epochs, lr, d2l.try_gpu())

在这里插入图片描述

3. TensorFlow实现LeNet

基于 MNIST 手写数字图片数据集训练 LeNet-5 网络,并测试其最终准确度。

在 LeNet-5 的基础上进行了少许调整,使得它更容易在现代深度学习框架上实 现。首先我们将输入𝒀形状由32 × 32调整为28 × 28,然后将 2 个下采样层实现为最大池化层(降低特征图的高、宽,后续会介绍),最后利用全连接层替换掉 Gaussian connections层。

import tensorflow as tf
# 获取GPU列表
gpus = tf.config.experimental.list_physical_devices('GPU')
if gpus:
    try:
        # 设置GPU为增长式占用
        for gpu in gpus:
            tf.config.experimental.set_memory_growth(gpu, True) 
    except RuntimeError as e:
        # 打印异常
        print(e)

# LeNet-5模型

from tensorflow.keras import Sequential,layers,losses
network = Sequential([ # 网络容器
    layers.Conv2D(6,kernel_size=3,strides=1), # 第一个卷积层, 6 个 3x3 卷积核
    layers.MaxPooling2D(pool_size=2,strides=2), # 高宽各减半的池化层
    layers.ReLU(), # 激活函数
    layers.Conv2D(16,kernel_size=3,strides=1), # 第二个卷积层, 16 个 3x3 卷积核
    layers.MaxPooling2D(pool_size=2,strides=2), # 高宽各减半的池化层
    layers.ReLU(), # 激活函数
    layers.Flatten(), # 打平层,方便全连接层处理
    layers.Dense(120, activation='relu'), # 全连接层,120 个节点
    layers.Dense(84, activation='relu'), # 全连接层,84 节点
    layers.Dense(10) # 全连接层,10 个节点
])
# build 一次网络模型,给输入 X 的形状,其中 4 为随意给的 batchsize
network.build(input_shape=(4, 28, 28, 1))
# 统计网络信息
network.summary()
from tensorflow.keras import datasets

# 准备数据
(x_train, y_train), (x_test, y_test) = datasets.mnist.load_data() # 加载 MNIST 数据集
x_train = 2*tf.convert_to_tensor(x_train, dtype=tf.float32)/255.-1 # 转换为浮点张量,并缩放到-1~1
y_train = tf.convert_to_tensor(y_train, dtype=tf.int32) # 转换为整形张量
train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train))  # 构建数据集对象
train_dataset = train_dataset.batch(64).repeat(10)  # 设置批量训练的batch为32,要将训练集重复训练10遍

x_test = 2*tf.convert_to_tensor(x_test, dtype=tf.float32)/255.-1 # 转换为浮点张量,并缩放到-1~1
y_test = tf.convert_to_tensor(y_test, dtype=tf.int32) # 转换为整形张量
test_dataset = tf.data.Dataset.from_tensor_slices((x_test, y_test))  # 构建数据集对象
test_dataset = test_dataset.batch(64)  # 

# 导入误差计算,优化器模块
from tensorflow.keras import losses, optimizers,metrics

# 创建损失函数的类,在实际计算时直接调用类实例即可
criteon = losses.CategoricalCrossentropy(from_logits=True)
acc_meter = metrics.Accuracy()  # 创建准确度测量器
optimizer = optimizers.SGD(lr=0.01)  # 声明采用批量随机梯度下降方法,学习率=0.01

for step, (x, y) in enumerate(train_dataset):  # 一次输入batch组数据进行训练
    # 构建梯度记录环境
    with tf.GradientTape() as tape:
        x = tf.expand_dims(x,axis=3)#添加一个维度[64,28,28,1]
        # 前向计算,获得 10 类别的概率分布,[b, 784] => [b, 10]
        out = network(x)
        # 真实标签 one-hot 编码,[b] => [b, 10]
        y_onehot = tf.one_hot(y, depth=10)
        # 计算交叉熵损失函数,标量
        loss = criteon(y_onehot, out)
        # 自动计算梯度
        grads = tape.gradient(loss, network.trainable_variables)
        # 自动更新参数
        optimizer.apply_gradients(zip(grads, network.trainable_variables))
        acc_meter.update_state(tf.argmax(out, axis=1), y)  # 比较预测值与标签,并计算精确度
    if step % 200 == 0:  # 每200个step,打印一次结果
        print('Step', step, ': Loss is: ', float(loss), ' Accuracy: ', acc_meter.result().numpy())
        acc_meter.reset_states()  # 每一个step后准确度清零
"""
测试集评估
"""

# 记录预测正确的数量,总样本数量
correct, total = 0,0
for step, (x, y) in enumerate(test_dataset): # 遍历所有测试集样本
    # 插入通道维度,=>[b,28,28,1]
    x = tf.expand_dims(x,axis=3)
    # 前向计算,获得 10 类别的预测分布,[b, 784] => [b, 10]
    out = network(x)
#     # 真实的流程时先经过 softmax,再 argmax
#     # 但是由于 softmax 不改变元素的大小相对关系,故省去
    pred = tf.argmax(out, axis=-1)
    y = tf.cast(y, tf.int64)
#     # 统计预测正确数量
    correct += float(tf.reduce_sum(tf.cast(tf.equal(pred, y),tf.float32)))
#     # 统计预测样本总数
    total += x.shape[0]
# 计算准确率
print('test acc:', correct/total)

在数据集上面循环训练 30 个 Epoch 后,网络的训练准确度达到了 98.1%,测试准确度 也达到了 97.7%。对于非常简单的手写数字图片识别任务,古老的 LeNet-5 网络已经可以 取得很好的效果,但是稍复杂一点的任务,比如彩色动物图片识别,LeNet-5 性能就会急 剧下降。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1533573.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

HCIA复习

上面的文件里有思维导图哦~ 一、情景再现:ISP网络为学校提供了DNS服务,所以,DNS服务器驻留在ISP网络内,而不再学校网络内。DHCP服务器运行在学校网络的路由器上。 小明拿了一台电脑,通过网线,接入到校园网…

使用el-cascader组件写下拉级联多选并且具有全选功能

样式 说明: 级联选择器中加上全选的按钮, 并且保证数据响应式。 思路 因为是有全选的功能,所以不能直接使用el-cascader组件, 而是选择使用el-select组件, 在此组件内部使用el-cascader-panel级联面板全选按钮也是写在el-select组件中, 并且去监听全选按钮的状态, 根…

The Open Group开放数字标准组合|管理您的数字景观

据麻省理工学院斯隆Sloan和凯捷咨询Capgemini称,90%的首席执行官认为数字经济将影响他们的行业,但只有不到15%的首席执行官正在执行数字战略。 数字化转型对于企业在当今不断变化的市场和技术环境中持续保持竞争力至关重要。近年来,商业世界发…

‍Java OCR技术全面解析:六大解决方案比较

博主猫头虎的技术世界 🌟 欢迎来到猫头虎的博客 — 探索技术的无限可能! 专栏链接: 🔗 精选专栏: 《面试题大全》 — 面试准备的宝典!《IDEA开发秘籍》 — 提升你的IDEA技能!《100天精通鸿蒙》 …

HarmonyOS ArkTS 基础组件

目录 一、常用组件 二、文本显示(Text/Span) 2.1 创建文本 2.2 属性 2.3 添加子组件(Span) 2.4 添加事件 三、按钮(Button) 3.1 创建按钮 3.2 设置按钮类型 3.3 悬浮按钮 四、文本输入(TextInput/TextArea)…

vue-生成二维码

安装 yarn add qrcodejs2 --save npm install qrcodejs2 --save 使用 <template><div><div id"qrcodeImg"></div><!-- 创建一个div&#xff0c;并设置id --></div> </template> <script> import QRCode from q…

vue3中如何实现多个侦听器(watch)

<body> <div id"app"><input type"button" value"更改名字" click"change"> </div> <script src"vue.js"></script> <script>new Vue({el: #app,data: {food: {id: 1,name: 冰激…

C语言学习 三、运算符与表达式

3.1 运算符分类 c语言提供了13种类型的运算符&#xff0c;如下所示&#xff1a; &#xff08;1&#xff09;算术运算符&#xff08; - * / %&#xff09; &#xff08;2&#xff09;关系运算符&#xff08;> < > < !&#xff09; &#xff08;3&#xff09;逻…

Python 解析CSV文件 使用Matplotlib绘图

数据存储在CSV文件中&#xff0c;使用Matplotlib实现数据可视化。 CSV文件&#xff1a;comma-separated values&#xff0c;是在文件中存储一系列以‘&#xff0c;’分隔的值。 例如&#xff1a;"0.0","2016-01-03","1","3","20…

【Pt】新建项目时的设置

新建项目时需要在如下界面做一些设置。 一、模板与文件 模板通常选择“PBR - Metallic Roughness Alpha-blend” 文件可以选择fbx&#xff0c;abc&#xff0c;obj等格式的三维模型文件 二、项目设置 2.1 文件分辨率 指的是在软件中的预览效果&#xff0c;分辨率越高预览效果…

链动3+1模式 全新升级 解决小号和断代问题!!!

随着数字经济的蓬勃发展&#xff0c;市场竞争愈演愈烈&#xff0c;传统的商业模式显得捉襟见肘&#xff0c;难以满足企业快速发展的需求。在这种背景下&#xff0c;一种创新的商业模式——“链动31”应运而生&#xff0c;以其独特的玩法和优势&#xff0c;引领着市场发展的新方…

HEVC的编码结构

编码单元划分 CTU/CTB CTU(Coding Tree Unit)和CU组成了一个四叉树的层级结构,CTU的尺寸为64 x 64,32 x 32,16 x 16,一个CTU可以分为一个或四个CTU,对标H264的MB。 CU/CB CU/CB(Coding Unit/Coding Block),CU为亮度和色度编码单元的统称,CB特指某一个分量的的编码…

网络编程:数据库

一、作业 1> 创建一个工人信息库&#xff0c;包含工号&#xff08;主键&#xff09;、姓名、年龄、薪资。 2> 添加三条工人信息&#xff08;可以完整信息&#xff0c;也可以非完整信息&#xff09; 3> 修改某一个工人的薪资&#xff08;确定的一个&#xff09; 4> …

帅帅密码管理系统使用教程

在这个账号满天飞的大环境&#xff0c;密码太多&#xff0c;又容易遗忘&#xff0c;又不方便管理&#xff0c;存在记事本上&#xff0c;又担心泄漏。帅帅密码管理系统就是帮助你解决以上烦恼&#xff0c;用来帮助个人或团队管理众多的登陆密码&#xff0c;能够快速的查询、新增…

布隆过滤器原理介绍和典型应用案例

整理自己过去使用布隆过滤器的应用案例和理解 基本介绍 1970年由布隆提出的一种空间效率很高的概率型数据结构&#xff0c;它可以用于检索一个元素是否在一个集合中&#xff0c;由只存0或1的位数组和多个hash算法, 进行判断数据 【一定不存在或者可能存在的算法】 如果这些…

广告创意的魔力:争议与诱惑并存

《广告创意的魔力&#xff1a;争议与诱惑并存》 一、广告的创意魅力之源 广告创意是广告行业的灵魂&#xff0c;它决定着广告能否在浩瀚的信息海洋中脱颖而出&#xff0c;抓住受众的注意力。优秀的广告创意往往能够打破常规&#xff0c;用新颖、独特、有趣的手法表达广告主题…

D55125ADA A型漏电保护芯片,适用于 110V⁓220V(50/60Hz)电压,可应用于 新能源充电桩(充电枪)、智能空开(智能微断开关)等工业产品

一、应用领域 新能源充电桩&#xff08;充电枪&#xff09;、智能空开&#xff08;智能微断开关&#xff09;等工业产品&#xff0c;以及电热水器、电烤箱、电烤炉等小家电产品。 二、功能介绍 D55125ADA 是一款高性能 CMOS 漏电保护器专用电路。芯片内部包含稳压电源、放大电路…

C是用什么语言写出来的?

C是用什么语言写出来的? C语言的起源和发展是一个迭代过程&#xff1a; 1. 最初的C语言编译器的开发始于对B语言的改进。B语言是由Ken Thompson设计的&#xff0c;它是基于BCPL语言简化而来的。在开始前我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「 C语言的…

文件IO(代码案例: 文件复制, 指定目录查找文件, 指定目录查找内容)

文件复制 进行普通文件的复制 使用操作字节流的对象操作文件 // 文件复制 public class Main {public static void main(String[] args) throws IOException {// 输入两个路径, 源路径, 目的路径Scanner scanner new Scanner(System.in);System.out.println("请输入拷贝文…

鸿蒙Harmony应用开发—ArkTS-高级组件:@ohos.arkui.advanced.Chip(操作块组件)

操作块&#xff0c;用于搜索框历史记录或者邮件发送列表等场景。 说明&#xff1a; 该组件从API Version 11开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 子组件 无 Chip Chip({options:ChipOptions}) 装饰器类型&#xff1a;Builde…