目录
1.关于理论:
2.Ghost模块
2.1关于计算量
2.2.复杂度分析【内存和计算量的收益】
2.3 关于GhostNet结构【配合代码使用】:
2.3.1 pytorch中:
2.3.2 darknet的cfg文件具体分析:
3.GhostNet-yolo
论文链接:https://arxiv.org/abs/1911.11907
作者解读:https://zhuanlan.zhihu.com/p/109325275
开源代码tensorflow:https://github.com/huawei-noah/ghostnet
开源代码:pytorch : https://github.com/iamhankai/ghostnet.pytorch/blob/master/ghost_net.py
开源代码:darknet:https://github.com/AlexeyAB/darknet/files/3997987/ghostnet.cfg.txt【cfg文件】
https://github.com/AlexeyAB/darknet/issues/4418【darknet版本】
在作者专栏里讲得很清楚了,一般情况下,深度神经网络提取的特征通常会包含大量的冗余特征图,这样能够保证对输入的数据有详细的特征理解。论文里给出了一个示例,在ResNet-50网络中的特征可视化图,并标出了三对相似的特征图(6个特征)。作者认为可以不直接通过卷积生成这些特征(6个),而是可以通过一定的变换来生成所需要的特征(先生成3个特征,再通过一定的变换生成剩下三个特征,concat后就是之前需要的3对特征图)。因此可以说其中一个特征图是另一个的“幻影”(Ghost)。
所以可以知道,本文最重要的部分是,提出了并非所有特征图都要用卷积操作来得到,“幻影”特征图可以用更廉价的操作来生成。【就是文章中最关键的Ghost 模块】
由图可以得到我们在前面说的内容,原有的深度神经网络如a)结构,直接通过卷积生成一组特征图(含有一些相似的特征图);Ghost结构如b)结构,先通过卷积生成其中一部分特征图A,再将A做一些简单的线性运算生成A’,将A concat A’后生成最终需要的一组特征图。
作者说,这样的操作能够在保持相似识别性能的同时降低通用卷积层的计算成本,并且GhostNet可以超越MobileNetV3等先进的高效深度模型,在移动设备上进行快速推断。
(不愿意手打公式,直接截图作者的解析了,QAQ)
作者利用综上的操作能够减少生成特征时的相应计算量。
(不愿意手打公式,直接截图作者的解析了,QAQ)
在代码实现中,第二个变换是用depthwise conv实现的,然后将两个过程生成的feature map concat后得到完整的feature map。
class GhostModule(nn.Module):
def __init__(self, inp, oup, kernel_size=1, ratio=2, dw_size=3, stride=1, relu=True):
super(GhostModule, self).__init__()
self.oup = oup
init_channels = math.ceil(oup / ratio)
new_channels = init_channels*(ratio-1)
self.primary_conv = nn.Sequential(
nn.Conv2d(inp, init_channels, kernel_size, stride, kernel_size//2, bias=False),
nn.BatchNorm2d(init_channels),
nn.ReLU(inplace=True) if relu else nn.Sequential(),
)
self.cheap_operation = nn.Sequential(
nn.Conv2d(init_channels, new_channels, dw_size, 1, dw_size//2, groups=init_channels, bias=False),
nn.BatchNorm2d(new_channels),
nn.ReLU(inplace=True) if relu else nn.Sequential(),
)
def forward(self, x):
x1 = self.primary_conv(x)
x2 = self.cheap_operation(x1)
out = torch.cat([x1,x2], dim=1)
return out[:,:self.oup,:,:]
上面代码应该很好理解,根据上述代码可以画出简单地GhostNet的结构:
【一小部分分析,就是举个例子,怕自己忘记】
[convolutional]
batch_normalize=1
filters=16
size=3
stride=2
pad=1
activation=relu
[convolutional]
batch_normalize=1
filters=8
size=1
stride=1
pad=1
activation=relu
[convolutional]
batch_normalize=1
filters=8
groups=8
size=3
stride=1
pad=1
activation=relu
[route]
layers = -1, -2
[convolutional]
batch_normalize=1
filters=8
size=1
stride=1
pad=1
activation=relu
[convolutional]
batch_normalize=1
filters=8
groups=8
size=3
stride=1
pad=1
activation=linear
[route]
layers = -1, -2
[shortcut]
from = -7
activation = linear
配图理解:
[convolutional]
batch_normalize=1
filters=16
size=1
stride=1
pad=1
activation=relu
[convolutional]
batch_normalize=1
filters=64
groups=16
size=5
stride=1
pad=1
activation=relu
[route]
layers = -1, -2
# stride = 2
[convolutional]
batch_normalize=1
filters=80
groups=80
size=5
stride=2
pad=1
activation=linear
# shortcut
[convolutional]
batch_normalize=1
filters=40
size=1
stride=1
pad=1
activation=linear
[route]
layers = -2
#squeeze-n-excitation
[avgpool]
# squeeze ratio r=4
[convolutional]
filters=16
size=1
stride=1
activation=relu
# excitation
[convolutional]
filters=80
size=1
stride=1
activation=logistic
# multiply channels
[scale_channels]
from=-4
[convolutional]
batch_normalize=1
filters=8
size=1
stride=1
pad=1
activation=relu
[convolutional]
batch_normalize=1
filters=32
groups=8
size=5
stride=1
pad=1
activation=linear
[route]
layers = -1, -2
[shortcut]
from = -9
activation = linear
配图理解:
训练到一半,测试了单张图片的效果,还行,能跑。
cfg文件:https://github.com/hualuluu/ghost-yolo
单张效果: