Узкое место, представленное в yolov8, объединено с c2f, заменяя все c2f в магистральной сети.
layers | parameters | GFLOPs | kb | |
---|---|---|---|---|
YOLOv8s | 168 | 11125971 | 28.4 | 21991 |
YOLOv8_C2f_GhostBottleneckV2s | 279 | 2553539 | 6.8 | 5250 |
YOLOv8_C2f_GhostBottlenecks | 267 | 2553539 | 6.8 | 5248 |
YOLOv8_C2f_g_ghostBottlenecks | 195 | 2581091 | 6.9 | 5283 |
бумага: https://arxiv.org/pdf/1911.11907.pdf
Аннотация: Из-за ограничений памяти и вычислительных ресурсов сложно развернуть сверточную нейронную сеть CNN у производителей встраиваемых устройств. Развертывание сверточных нейронных сетей (CNN) на встроенных устройствах затруднено из-за ограниченности памяти и вычислительных ресурсов. Избыточность в картах признаков является важной характеристикой успешных нейронных сетей, но она редко изучается при проектировании архитектуры нейронных сетей. Модуль Ghost для создания большего количества карт объектов из дешевых операций. На основе набора карт внутренних признаков применение ряда линейных преобразований с небольшими затратами для создания множества карт призрачных признаков может полностью раскрыть информацию о внутренних признаках. Предлагаемый модуль Ghost можно использовать в качестве компонента plug-and-play для простой модернизации существующих сверточных нейронных сетей, а узкое место Ghost предназначено для объединения модулей Ghost и последующего легкого создания облегченной сети GhostNet.
В картах признаков, извлеченных с помощью основных глубоких нейронных сетей, богатая и даже избыточная информация обычно обеспечивает полное понимание входных данных. Например, на рисунке 1 показаны некоторые карты объектов входного изображения, сгенерированные ResNet-50, и существует множество похожих пар карт объектов, которые похожи друг на друга.
представил новый Ghost модуль для создания большего количества функций с использованием меньшего количества параметров.Конкретно,Общий сверточный слой в глубокой нейронной сети разделен на две части. Первая часть предполагает обычные свертки,Но их общее количество будет строго контролироваться. Учитывая внутреннюю карту признаков первой части,Затем применяется серия простых линейных операций для создания дополнительных карт объектов. без изменения размера выходной карты объектов,По сравнению с обычными сверточными нейронными сетями,этот Ghost Общее количество параметров и вычислительная сложность, необходимые для модуля, уменьшены.
на основе Ghost модуль, устанавливающий эффективную нейронную архитектуру, а именно GhostNet。首先替换基准神经架构中的原始卷积层以证明 Ghost Затем проверяется достоверность модуля. GhostNets Превосходство по нескольким эталонным наборам данных по зрению.
Используя преимущества модуля Ghost, специально для небольших моделей вводится Ghost Bottlenck, как показано на рисунке 3. Узкое место призрака похоже на базовый остаточный блок в ResNet, который объединяет несколько сверточных слоев и ярлыков. Узкое место «призрака» в основном состоит из сложенных друг на друга модулей-призраков. Первый модуль-призрак действует как уровень расширения для увеличения количества каналов. Коэффициентом расширения становится соотношение количества выходных каналов к количеству входных каналов. Второй призрачный модуль уменьшает количество каналов, чтобы они соответствовали ярлыкам, и тогда ярлыки располагаются между входом и выходом двух призрачных модулей. BN и ReLu применяются после каждого слоя, а ReLU не используется после второго модуля-призрака.
Экспериментальные результаты показывают, что предлагаемый модуль Ghost может снизить вычислительные затраты на общие сверточные слои, сохраняя при этом аналогичную производительность распознавания, а GhostNets может превзойти эффективные глубокие модели SOTA для решения различных задач, такие как MobileNetV3 для быстрого вывода на мобильных устройствах.
Основной код:
class GhostNet(nn.Module):
def __init__(self, cfgs, num_classes=1000, width=1.0, dropout=0.2):
super(GhostNet, self).__init__()
# setting of inverted residual blocks
self.cfgs = cfgs
self.dropout = dropout
# building first layer
output_channel = _make_divisible(16 * width, 4)
self.conv_stem = nn.Conv2d(3, output_channel, 3, 2, 1, bias=False)
self.bn1 = nn.BatchNorm2d(output_channel)
self.act1 = nn.ReLU(inplace=True)
input_channel = output_channel
# building inverted residual blocks
stages = []
block = GhostBottleneck
for cfg in self.cfgs:
layers = []
for k, exp_size, c, se_ratio, s in cfg:
output_channel = _make_divisible(c * width, 4)
hidden_channel = _make_divisible(exp_size * width, 4)
layers.append(block(input_channel, hidden_channel, output_channel, k, s,
se_ratio=se_ratio))
input_channel = output_channel
stages.append(nn.Sequential(*layers))
output_channel = _make_divisible(exp_size * width, 4)
stages.append(nn.Sequential(ConvBnAct(input_channel, output_channel, 1)))
input_channel = output_channel
self.blocks = nn.Sequential(*stages)
# building last several layers
output_channel = 1280
self.global_pool = nn.AdaptiveAvgPool2d((1, 1))
self.conv_head = nn.Conv2d(input_channel, output_channel, 1, 1, 0, bias=True)
self.act2 = nn.ReLU(inplace=True)
self.classifier = nn.Linear(output_channel, num_classes)
self.channel = [i.size(-1) for i in self.forward(torch.randn(1, 3, 640, 640))]
def forward(self, x):
x = self.conv_stem(x)
x = self.bn1(x)
x = self.act1(x)
x = self.blocks(x)
x = self.global_pool(x)
x = self.conv_head(x)
x = self.act2(x)
x = x.view(x.size(0), -1)
if self.dropout > 0.:
x = F.dropout(x, p=self.dropout, training=self.training)
x = self.classifier(x)
return x
def ghostnet(**kwargs):
"""
Constructs a GhostNet model
"""
cfgs = [
# k, t, c, SE, s
# stage1
[[3, 16, 16, 0, 1]],
# stage2
[[3, 48, 24, 0, 2]],
[[3, 72, 24, 0, 1]],
# stage3
[[5, 72, 40, 0.25, 2]],
[[5, 120, 40, 0.25, 1]],
# stage4
[[3, 240, 80, 0, 2]],
[[3, 200, 80, 0, 1],
[3, 184, 80, 0, 1],
[3, 184, 80, 0, 1],
[3, 480, 112, 0.25, 1],
[3, 672, 112, 0.25, 1]
],
# stage5
[[5, 672, 160, 0.25, 2]],
[[5, 960, 160, 0, 1],
[5, 960, 160, 0.25, 1],
[5, 960, 160, 0, 1],
[5, 960, 160, 0.25, 1]
]
]
return GhostNet(cfgs, **kwargs)