• 卷积神经网络的常用改进


    背景

    图片类任务经常使用卷积神经网络,网络结构中经常是使用全链接作为输出层,来实现分类或者回归。

    全链接层的好处:由于其参数量级大,模型的拟合能力更强

    坏处

    ① 对于数据的尺寸要求是固定的,因此我们有时需要resize图片,导致变形或者剪切损失图片信息

    ② 模型的参数基本都集中于全链接层,因此预测时间主要被全链接占用,实时性要求高的模型会有影响

    ③ 显存占用高

    因此当我们关注实时性,可以适当牺牲准确性(卷积层复杂可以弥补准确性),并且输入数据尺寸是变化的时候,我们应该怎么做呢?

    方法

    1.去掉全链接层,使用全卷积神经网络,1*1卷积层控制输出尺寸

    2.靠近输出层的卷积层整体maxpooling,1*1卷积层控制输出尺寸

    代码

    我们以mnist作为例子:

    **全链接模型:**通过d2控制输出的tensor是1*10

    1. class DENSE_MNIST_MODEL(tf.keras.Model):
    2. def __init__(self):
    3. super(DENSE_MNIST_MODEL, self).__init__()
    4. self.conv1 = Conv2D(32, 3, activation='relu')
    5. self.flatten = Flatten()
    6. self.d1 = Dense(128, activation='relu')
    7. self.d2 = Dense(10, activation='softmax')
    8. def call(self, x):
    9. x = self.conv1(x)
    10. x = self.flatten(x)
    11. x = self.d1(x)
    12. return self.d2(x)

    模型参数:

    1. Model: "dense_mnist_model"
    2. _________________________________________________________________
    3. Layer (type) Output Shape Param #
    4. =================================================================
    5. conv2d (Conv2D) multiple 320
    6. _________________________________________________________________
    7. flatten (Flatten) multiple 0
    8. _________________________________________________________________
    9. dense (Dense) multiple 2769024
    10. _________________________________________________________________
    11. dense_1 (Dense) multiple 1290
    12. =================================================================
    13. Total params: 2,770,634
    14. Trainable params: 2,770,634
    15. Non-trainable params: 0

    输入图片是2828,经过两个maxpooling,步长是2,变成了77大小,经过77卷积,padding=valid,则只保留了channel上的特征。再经过11卷积,控制channel为10

    1. class FCN_MNIST_MODEL(tf.keras.Model):
    2. def __init__(self):
    3. super(FCN_MNIST_MODEL, self).__init__()
    4. self.conv1 = Conv2D(16, 3, 1, padding="same")
    5. self.conv2 = Conv2D(32, 3, 1, padding="same")
    6. self.conv3 = Conv2D(32, 7, 1, padding="valid")
    7. self.conv4 = Conv2D(10, 1, 1, padding="same")
    8. self.maxpool2d = MaxPool2D(2, 2, padding="valid")
    9. def call(self, inputs=(None, 28, 28, 1)):
    10. __output = self.conv1(inputs)
    11. __output = self.maxpool2d(__output)
    12. __output = self.conv2(__output)
    13. __output = self.maxpool2d(__output)
    14. __output = self.conv3(__output)
    15. __output = self.conv4(__output)
    16. shape = __output.shape
    17. __output = tf.squeeze(__output, axis=[1,2])
    18. return tf.nn.softmax(__output)

    模型参数:

    1. Model: "fcn_mnist_model"
    2. _________________________________________________________________
    3. Layer (type) Output Shape Param #
    4. =================================================================
    5. conv2d (Conv2D) multiple 160
    6. _________________________________________________________________
    7. conv2d_1 (Conv2D) multiple 4640
    8. _________________________________________________________________
    9. conv2d_2 (Conv2D) multiple 50208
    10. _________________________________________________________________
    11. conv2d_3 (Conv2D) multiple 330
    12. _________________________________________________________________
    13. max_pooling2d (MaxPooling2D) multiple 0
    14. =================================================================
    15. Total params: 55,338
    16. Trainable params: 55,338
    17. Non-trainable params: 0

    通过卷积、maxpooling、avgpooling将过程中的tensor变成11channel尺寸,再通过1*1卷积,控制channel为10。

    注意同一个batch里的数据需要是同样的尺寸,我们都会进行pad,所以常用做法是将尺度相近的图片放到同一个batch里,padding后变成同一个尺寸。

    1. class ARBITRARY_MNIST_MODEL(tf.keras.Model):
    2. def __init__(self):
    3. super(ARBITRARY_MNIST_MODEL, self).__init__()
    4. self.conv1 = Conv2D(16, 3, 1, padding="same")
    5. self.conv2 = Conv2D(32, 3, 1, padding="same")
    6. self.conv3 = Conv2D(10, 1, 1, padding="same")
    7. def call(self, inputs):
    8. __output = self.conv1(inputs)
    9. __output = self.conv2(__output)
    10. __output = tf.nn.max_pool2d(__output, __output.shape[1:3], 1, padding="VALID") # 这里也可以使用GlobalMaxPooling2D,再经过expand_dims变成四维
    11. __output = self.conv3(__output)
    12. __output = tf.squeeze(__output, axis=[1,2])
    13. return tf.nn.softmax(__output)

    模型参数:

    1. Model: "arbitrary_mnist_model"
    2. _________________________________________________________________
    3. Layer (type) Output Shape Param #
    4. =================================================================
    5. conv2d (Conv2D) multiple 160
    6. _________________________________________________________________
    7. conv2d_1 (Conv2D) multiple 4640
    8. _________________________________________________________________
    9. conv2d_2 (Conv2D) multiple 330
    10. =================================================================
    11. Total params: 5,130
    12. Trainable params: 5,130
    13. Non-trainable params: 0

    数据对比

    全链接模型(浅色的线是原始数据,深色的是平滑后的数据,周期只有10)

    损失值尾部上扬,与周期短和没有添加正则化方法有关,正则化不在本文讨论范围内。

    全卷积模型:

    可变尺寸模型:

    10个周期不够,准确度和损失还没有收敛,但是能大致看出趋势。

    模型参数量AccuracyLoss|------

    总结

    落地部署中,我们不仅关注准确度,可能更关心响应时间,因此模型不能太复杂,全卷积是一个很好的思路。

    如果我们的数据,包括图片、文本、音频等,如果尺寸变化幅度比较大,是否可以考虑将样本尺寸相近的数据放到同一个batch,网络中不使用全链接,实现动态尺度模型。

  • 相关阅读:
    vscode设置latex
    多线程与高并发(7)——从ReentrantLock到AQS源码(两万字大章,一篇理解AQS)
    (附源码课件)10款Java小游戏满足你各种需求
    Louvain算法在反作弊上的应用
    元数据管理平台对比预研 Atlas VS Datahub VS Openmetadata
    分类预测 | Matlab实现PSO-LSTM粒子群算法优化长短期记忆神经网络的数据多输入分类预测
    Spring Cloud学习笔记【分布式请求链路跟踪-Sleuth】
    2.Android高仿网易云音乐-引导界面和广告界面实现
    上周热点回顾(5.18-5.24)
    代码随想录Day60 | 739. 每日温度 | 496. 下一个更大元素
  • 原文地址:https://blog.csdn.net/cebawuyue/article/details/127426009