1. 前言

PPLCNet是百度团队结合Intel-CPU端侧推理特性而设计的轻量高性能网络PP-LCNet,所提方案在图像分类任务上取得了比ShuffleNetV2、MobileNetV2、MobileNetV3以及GhostNet更优的延迟-精度均衡。

论文提出了一种基于MKLDNN加速的轻量CPU模型PP-LCNet,它在多个任务上改善了轻量型模型的性能。

如下图所示,在图像分类任务方面,所提PP-LCNet在推理延迟-精度均衡方面大幅优于ShuffleNetV2、MobileNetV2、MobileNetV3以及GhostNet。

2. PPLCNet介绍

网络结构整体如下图所示。


1. 模块
使用了类似MobileNetV1中的深度可分离卷积作为基础,通过堆叠模块构建了一个类似MobileNetV1的BaseNet,然后组合BaseNet与某些现有技术构建了一种更强力网络PP-LCNet。
结构图如下:
左图是卷积+标准化+激活函数,右图是PPLCNet中的基础模块,我是根据源代码中画的图,源代码中是先卷积+SE模块+卷积。


def DethSepConv(x, filter,kernel_size ,stride, use_se=False):x = Conv2D(filters=x.shape[-1], kernel_size=kernel_size, strides=stride, padding='same',groups=x.shape[-1], use_bias=False)(x)x = BatchNormalization()(x)x = Activation(hard_swich)(x)if use_se:x = SE_block(x)x = Conv2D(filters=filter, kernel_size=1, strides=1, padding='same',use_bias=False)(x)x = BatchNormalization()(x)x = Activation(hard_swich)(x)return x

2. 激活函数的使用
自从卷积神经网络使用了 ReLU 激活函数后,网络性能得到了大幅度提升,近些年 ReLU 激活函数的变体也相继出现,如 Leaky-ReLU、P-ReLU、ELU 等,2017 年,谷歌大脑团队通过搜索的方式得到了 swish 激活函数,该激活函数在轻量级网络上表现优异,在 2019 年,MobileNetV3 的作者将该激活函数进一步优化为 H-Swish,该激活函数去除了指数运算,速度更快,网络精度几乎不受影响,也经过很多实验发现该激活函数在轻量级网络上有优异的表现。所以在 PP-LCNet 中,选用了该激活函数。

def hard_swich(x):return x * K.relu(x + 3.0, max_value=6.0) / 6.0

3. SE 模块
SE模块使用的激活函数ReLU和H-sigmoid。代码实现如下:

def SE_block(x_0, r = 4):channels = x_0.shape[-1]x = GlobalAveragePooling2D()(x_0)# (?, ?) -> (?, 1, 1, ?)x = x[:, None, None, :]# 用2个1x1卷积代替全连接x = Conv2D(filters=channels//r, kernel_size=1, strides=1)(x)x = Activation('relu')(x)x = Conv2D(filters=channels, kernel_size=1, strides=1)(x)x = Activation(hard_sigmoid)(x)x = Multiply()([x_0, x])return x

3. 合适的位置添加更大的卷积核
通过实验总结了一些更大的卷积核在不同位置的作用,类似 SE 模块的位置,更大的卷积核在网络的中后部作用更明显,所以在网络的后部会使用很多5x5的卷积核。
4. GAP 后使用更大的 1x1 卷积层
在 GoogLeNet 之后,GAP(Global-Average-Pooling)后往往直接接分类层,但是在轻量级网络中,这样会导致 GAP 后提取的特征没有得到进一步的融合和加工。如果在此后使用一个更大的 1x1 卷积层(等同于 FC 层),GAP 后的特征便不会直接经过分类层,而是先进行了融合,并将融合的特征进行分类。这样可以在不影响模型推理速度的同时大大提升准确率。

3. 整体代码:

参考源码:https://github.com/PaddlePaddle/PaddleClas/blob/1358e3f647e12b9ee6c5d6450291983b2d5ac382/ppcls/arch/backbone/legendary_models/pp_lcnet.py
此代码实在gpu上训练的。

import tensorflow as tf
from tensorflow.keras import backend as K
from tensorflow.keras.layers import (Layer, GlobalAveragePooling2D, Conv2D, Activation, Multiply,BatchNormalization, Dropout, Dense, Flatten, Input, Reshape
)
from tensorflow.keras.models import Model
from tensorflow.keras.activations import hard_sigmoid
import numpy as np# 保证特征层为8得倍数
def _make_divisible(v, divisor=8, min_value=None):if min_value is None:min_value = divisornew_v = max(min_value, int(v + divisor / 2) // divisor * divisor)if new_v < 0.9 * v:new_v += divisorreturn new_vdef hard_swich(x):return x * K.relu(x + 3.0, max_value=6.0) / 6.0def SE_block(x_0, r = 4):channels = x_0.shape[-1]x = GlobalAveragePooling2D()(x_0)# (?, ?) -> (?, 1, 1, ?)x = x[:, None, None, :]# 用2个1x1卷积代替全连接x = Conv2D(filters=channels//r, kernel_size=1, strides=1)(x)x = Activation('relu')(x)x = Conv2D(filters=channels, kernel_size=1, strides=1)(x)x = Activation(hard_sigmoid)(x)x = Multiply()([x_0, x])return xdef DethSepConv(x, filter,kernel_size ,stride, use_se=False):x = Conv2D(filters=x.shape[-1], kernel_size=kernel_size, strides=stride, padding='same',groups=x.shape[-1], use_bias=False)(x)x = BatchNormalization()(x)x = Activation(hard_swich)(x)if use_se:x = SE_block(x)x = Conv2D(filters=filter, kernel_size=1, strides=1, padding='same',use_bias=False)(x)x = BatchNormalization()(x)x = Activation(hard_swich)(x)return xdef PP_LCNet(inputs, classes, dropout=0.2, scale=1.0):x = Conv2D(filters=_make_divisible(16*scale), kernel_size=3, strides=2, padding='same',use_bias=False)(inputs)x = BatchNormalization()(x)x = Activation(hard_swich)(x)x = DethSepConv(x, filter=_make_divisible(_make_divisible(scale*32)), kernel_size=3, stride=1, use_se=False)print(x.shape,'1')x = DethSepConv(x, filter=_make_divisible(_make_divisible(scale*64)), kernel_size=3, stride=2, use_se=False)x = DethSepConv(x, filter=_make_divisible(_make_divisible(scale*64)), kernel_size=3, stride=1, use_se=False)print(x.shape,'2')x = DethSepConv(x, filter=_make_divisible(_make_divisible(128*scale)), kernel_size=3, stride=2, use_se=False)x = DethSepConv(x, filter=_make_divisible(_make_divisible(128*scale)), kernel_size=3, stride=1, use_se=False)print(x.shape,'3')x = DethSepConv(x, filter=_make_divisible(_make_divisible(256*scale)), kernel_size=3, stride=2, use_se=False)x = DethSepConv(x, filter=_make_divisible(_make_divisible(256*scale)), kernel_size=5, stride=1, use_se=False)x = DethSepConv(x, filter=_make_divisible(_make_divisible(256*scale)), kernel_size=5, stride=1, use_se=False)x = DethSepConv(x, filter=_make_divisible(_make_divisible(256*scale)), kernel_size=5, stride=1, use_se=False)x = DethSepConv(x, filter=_make_divisible(_make_divisible(256*scale)), kernel_size=5, stride=1, use_se=False)x = DethSepConv(x, filter=_make_divisible(_make_divisible(256*scale)), kernel_size=5, stride=1, use_se=False)print(x.shape,'4')x = DethSepConv(x, filter=_make_divisible(_make_divisible(512*scale)), kernel_size=5, stride=2, use_se=True)x = DethSepConv(x, filter=_make_divisible(_make_divisible(512*scale)), kernel_size=5, stride=1, use_se=True)print(x.shape,'5')x = GlobalAveragePooling2D()(x)shape = (1, 1, x.shape[-1])x = Reshape(shape)(x)x = Conv2D(filters=1280, kernel_size=1, strides=1,padding='valid', use_bias=False)(x)x = Activation(hard_swich)(x)x = Dropout(rate=dropout)(x)x = Flatten()(x)x = Dense(classes, activation='softmax')(x)return x
if __name__ == '__main__':inputs = Input(shape=(224,224,3))classes = 17model = Model(inputs=inputs, outputs=PP_LCNet(inputs, classes))model.summary()

tensorflow2.3实现PPLCNet——一个速度更快、准确率更高的轻量级骨干网络相关推荐

  1. FDDWNET:模型参数仅为0.8M,速度和准确率综合性能在轻量级分割网络中达到SOTA

    作者:Tom Hardy Date:2020-02-04 来源:FDDWNET:模型参数仅为0.8M,速度和准确率综合性能在轻量级分割网络中达到SOTA

  2. 我们可观测的宇宙或许仅是更高维度内的一个泡沫

    新理论提出,我们的宇宙也许位于一个正在向更高维度扩张的泡沫之中. 新浪科技讯 北京时间2月22日消息,据国外媒体报道,就像海浪最高点的泡沫一样,我们可观测的宇宙或许仅仅是一个不断向更高维度扩张的泡沫内 ...

  3. PP-LCNet 一个轻量级的CPU卷积神经网络

    论文地址:  百度飞桨https://arxiv.org/abs/2109.15099https://arxiv.org/abs/2109.15099 本文提出了一种基于MKLDNN加速策略的轻量级C ...

  4. GcExcel:比 Apache POI 速度更快、性能更高

    GrapeCity Documents for Excel(GcExcel) 是一款服务端 Java Excel 组件,产品架构轻量灵活,无需 Office 组件依赖,结合 纯前端表格控件 Sprea ...

  5. CVPR 2021 | Facebook提出FP-NAS:搜索速度更快、分类精度更高、性能更好

    作者|严志程 来源|机器之心 来自 Facebook AI 的严志程团队发表一种新的神经架构的快速搜索算法.该算法采用自适应架构概率分布熵的架构采样,能够减少采样样本达 60%,加速搜索快 1.8 倍 ...

  6. 10年老分析师:数据分析不只是一个岗位,更是一种职场必备能力

    从事数据分析十年以来,我越来越感知到数据分析的学习与成长从来都不是纸上谈兵,不是理论空谈,也不是拿工具说事,而是不断在实践中迭代理论.磨炼经验. 近十年来,我先后在零售.电商等行业工作,一直专注钻研数 ...

  7. WordPress SEO教程:让你的网站排名更高和速度更快的101个优化技巧(2019年完整指南)

    阅读其他WordPress SEO教程后,你可能已经听说过要一直保持Yoast绿灯(这几乎不起作用). 点击创建免费网站. 所以,让我们减少无关紧要的事,让我告诉你是什么让我每天有2500个访客. 这 ...

  8. 速度提升2倍,超强悍CPU级骨干网络PP-LCNet

    yolov5-pp-lcnet: GitHub - OutBreak-hui/Yolov5-PP-LCNet 分类网络的,结果还出来: https://github.com/ngnquan/PP-LC ...

  9. 速度提升2倍,超强悍CPU级骨干网络PP-LCNet出世!

    关注公众号,发现CV技术之美 算法速度优化遇到瓶颈,达不到要求?应用环境没有高性能硬件只有CPU?是不是直接戳中了各位开发者的痛点!莫慌,今天小编就来为万千开发者破局~ 这个破局点就是:针对CPU设备 ...

最新文章

  1. 关于比特币现金升级问题讨论不断升温
  2. 嵌入式 ARM 汇编编程例题(二维数组按规律求和,求两数 gcd / lcm,求数组 min / max,字符串复制,排序)
  3. 测试Servlet生命周期学习笔记
  4. 实验18:使用@Autowired注解实现根据类型实现自动装配★
  5. MyBatis代码生成器(逆向工程)MBG使用
  6. Git之深入解析如何贮藏工作分支与清理工作目录
  7. python调用摄像头人脸识别代码_利用face_recognition,dlib与OpenCV调用摄像头进行人脸识别...
  8. D3 scaleQuantize
  9. Html select、option、optgroup 标签
  10. linux系统调用劫持隐藏进程,linux 下隐藏进程的一种方法及遇到的坑
  11. git merge 回退_git+vscode进行版本控制
  12. Illustrator 教程,如何在 Illustrator 中使用绘图模式?
  13. java中double类型占几个字节_Java基本数据类型占用字节数
  14. java 权重 分配_一种按权重分配的Java算法
  15. 8个经典无线射频识别(RFID)优选方案
  16. banner图片不拉伸、全屏宽、居中显示的方法
  17. 基于OTSU最大类间方差法的ROI分割、提取图像中的形状特征--面积、周长、离心率、zernike矩
  18. 利用cftool进行函数拟合
  19. 加速度计及其飞控应用
  20. 《爱你就像爱生命》读后

热门文章

  1. 斐波那契数列java输出
  2. linux kdump保存的目录,Linux kdump
  3. Visual Studio 2019 Professional
  4. 4GLTE网络语音三大解决方案
  5. SolidWorks添加GB铝型材库要注意的问题
  6. 启动django时报错Watching for file changes with StatReloader(使用状态加载程序监视文件更改 )...
  7. Oozie的简单使用
  8. 深度系统(deepin)与win10双系统切换设置
  9. 图像处理中,对图片数据集规格大小的处理办法。
  10. 机器学习:线性回归分析女性身高与体重之间的关系