tensorflow2.3实现PPLCNet——一个速度更快、准确率更高的轻量级骨干网络
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——一个速度更快、准确率更高的轻量级骨干网络相关推荐
- FDDWNET:模型参数仅为0.8M,速度和准确率综合性能在轻量级分割网络中达到SOTA
作者:Tom Hardy Date:2020-02-04 来源:FDDWNET:模型参数仅为0.8M,速度和准确率综合性能在轻量级分割网络中达到SOTA
- 我们可观测的宇宙或许仅是更高维度内的一个泡沫
新理论提出,我们的宇宙也许位于一个正在向更高维度扩张的泡沫之中. 新浪科技讯 北京时间2月22日消息,据国外媒体报道,就像海浪最高点的泡沫一样,我们可观测的宇宙或许仅仅是一个不断向更高维度扩张的泡沫内 ...
- PP-LCNet 一个轻量级的CPU卷积神经网络
论文地址: 百度飞桨https://arxiv.org/abs/2109.15099https://arxiv.org/abs/2109.15099 本文提出了一种基于MKLDNN加速策略的轻量级C ...
- GcExcel:比 Apache POI 速度更快、性能更高
GrapeCity Documents for Excel(GcExcel) 是一款服务端 Java Excel 组件,产品架构轻量灵活,无需 Office 组件依赖,结合 纯前端表格控件 Sprea ...
- CVPR 2021 | Facebook提出FP-NAS:搜索速度更快、分类精度更高、性能更好
作者|严志程 来源|机器之心 来自 Facebook AI 的严志程团队发表一种新的神经架构的快速搜索算法.该算法采用自适应架构概率分布熵的架构采样,能够减少采样样本达 60%,加速搜索快 1.8 倍 ...
- 10年老分析师:数据分析不只是一个岗位,更是一种职场必备能力
从事数据分析十年以来,我越来越感知到数据分析的学习与成长从来都不是纸上谈兵,不是理论空谈,也不是拿工具说事,而是不断在实践中迭代理论.磨炼经验. 近十年来,我先后在零售.电商等行业工作,一直专注钻研数 ...
- WordPress SEO教程:让你的网站排名更高和速度更快的101个优化技巧(2019年完整指南)
阅读其他WordPress SEO教程后,你可能已经听说过要一直保持Yoast绿灯(这几乎不起作用). 点击创建免费网站. 所以,让我们减少无关紧要的事,让我告诉你是什么让我每天有2500个访客. 这 ...
- 速度提升2倍,超强悍CPU级骨干网络PP-LCNet
yolov5-pp-lcnet: GitHub - OutBreak-hui/Yolov5-PP-LCNet 分类网络的,结果还出来: https://github.com/ngnquan/PP-LC ...
- 速度提升2倍,超强悍CPU级骨干网络PP-LCNet出世!
关注公众号,发现CV技术之美 算法速度优化遇到瓶颈,达不到要求?应用环境没有高性能硬件只有CPU?是不是直接戳中了各位开发者的痛点!莫慌,今天小编就来为万千开发者破局~ 这个破局点就是:针对CPU设备 ...
最新文章
- 关于比特币现金升级问题讨论不断升温
- 嵌入式 ARM 汇编编程例题(二维数组按规律求和,求两数 gcd / lcm,求数组 min / max,字符串复制,排序)
- 测试Servlet生命周期学习笔记
- 实验18:使用@Autowired注解实现根据类型实现自动装配★
- MyBatis代码生成器(逆向工程)MBG使用
- Git之深入解析如何贮藏工作分支与清理工作目录
- python调用摄像头人脸识别代码_利用face_recognition,dlib与OpenCV调用摄像头进行人脸识别...
- D3 scaleQuantize
- Html select、option、optgroup 标签
- linux系统调用劫持隐藏进程,linux 下隐藏进程的一种方法及遇到的坑
- git merge 回退_git+vscode进行版本控制
- Illustrator 教程,如何在 Illustrator 中使用绘图模式?
- java中double类型占几个字节_Java基本数据类型占用字节数
- java 权重 分配_一种按权重分配的Java算法
- 8个经典无线射频识别(RFID)优选方案
- banner图片不拉伸、全屏宽、居中显示的方法
- 基于OTSU最大类间方差法的ROI分割、提取图像中的形状特征--面积、周长、离心率、zernike矩
- 利用cftool进行函数拟合
- 加速度计及其飞控应用
- 《爱你就像爱生命》读后
热门文章
- 斐波那契数列java输出
- linux kdump保存的目录,Linux kdump
- Visual Studio 2019 Professional
- 4GLTE网络语音三大解决方案
- SolidWorks添加GB铝型材库要注意的问题
- 启动django时报错Watching for file changes with StatReloader(使用状态加载程序监视文件更改 )...
- Oozie的简单使用
- 深度系统(deepin)与win10双系统切换设置
- 图像处理中,对图片数据集规格大小的处理办法。
- 机器学习:线性回归分析女性身高与体重之间的关系