創造を続け、成長を加速させましょう!「ナゲッツデイリーニュープラン・6月アップデートチャレンジ」に参加した初日です。クリックしてイベントの詳細をご覧ください。
序文
簡単にまとめてみましょう。最近レビューもレビューしています。今学期の学習成果を見て、まとめて強化していきましょう。一連のメモはまだ整理中です。自分でレビューする時間はもちろん、深層学習の内容は、主にその週のYOLOについてであり、来週は私自身のクラスのものです。
このブログ投稿も約2日間作成されました。V1〜V3の論文を注意深く見ました。開発の観点から、V1からV3への変更は非常に大きいため、V4とV5は読んでいません。 V5はもっとありますそれはニューラルネットワークの構造に最適化されています。そして今日の私たちの仕事は、YOLOV5のバックボーンをどのように再現するかです。
どんなに良い理論でも実践する必要があり、理解と反省を深めることができます。次に、YOLOを使ってもっとクールなことをする必要があるので、このレベルは克服できないレベルです。
このブログ投稿は、探索用のYOLOV5.5バージョンに基づいています〜スペースの問題を考慮して、複製のために2つのブログ投稿に分割されます。
ネットワーク構造
始める前に、yolov5全体のネットワーク構造を見てみましょう。これは完全なニューラルネットワーク構造であり、 netron.app /を介して生成できますが、この図を直接使用することはありません。実際には多くの繰り返しがあります。、この図を使用して
リファレンスデザイン
実際の写真はわかりにくいので、知乎の兄である江大白の写真を参考にしましょう。
次に、各モジュールの説明を開始します。(現在のバージョンは実際には入力batch_size x 3 x 640 x 640の画像であることに注意してください)実際の画像はこの参照図面と同じではありません。実際、特定の画像は上記の画像に基づいています。だいたい長いですが、何であれ、投稿します。
フォーカスモジュール
始める前に何かに気づいた
このことはこのようなことをします、コード
class Focus(nn.Module):
# Focus wh information into c-space
def __init__(self, c1, c2, k=1, s=1, p=None, g=1, act=True): # ch_in, ch_out, kernel, stride, padding, groups
super(Focus, self).__init__()
self.conv = Conv(c1 * 4, c2, k, s, p, g, act) # 这里输入通道变成了4倍
def forward(self, x): # x(b,c,w,h) -> y(b,4c,w/2,h/2)
return self.conv(torch.cat([x[..., ::2, ::2], x[..., 1::2, ::2], x[..., ::2, 1::2], x[..., 1::2, 1::2]], 1))
复制代码
原始的3 x 640 × 640 的图像输入Focus结构,采用切片操作,先变成12 x 320 × 320的特征图 这里代码里面是将一张图片切成4份,每一份有原来的3个通道,所以 这里是c1*4。并且你应该注意到了这个第一个CONV的W的大小是64 x 32 x3 x3 这个也很好解释,一张图片本来是 .3 x 640 x 640 卷积核大小 3 x 3 按道理如果输出一个通道的话 那么 就是 3 x 3 x 3 此时输出32个通道就是 32 x 3 x 3 x 3 但是你有4份就是12个所以就是 32 x 12 x 3 x 3。 具体的推导可以看这张图
接下来就是我们的其他模块
Conv 卷积模块
这个在YOLOV5里面为了放置各种训练问题,它做了不少优化,首先是一开始的训练的时候有数据增强的处理,然后就是在卷积的时候,有归一化的处理,防止参数差距很大带来的干扰。
class Conv(nn.Module):
def __init__(self,c1,c2,k=1,s=1,p=None,g=1,act=True):
super(Conv,self).__init__()
self.conv = nn.Conv2d(c1, c2, k, s, autopad(k, p), groups=g, bias=False)
self.bn = nn.BatchNorm2d(c2)
self.act = nn.SiLU() if act is True else (act if isinstance(act, nn.Module) else nn.Identity())
def forward(self, x):
return self.act(self.bn(self.conv(x)))
def forward_fuse(self, x):
return self.act(self.conv(x))
复制代码
这里注意的是这个Sigmoid 是这个玩意和RULE其实很像,但是人家<0 有负值 这里的话多一嘴,其实这个卷积核和我们线性权重是类似的,只不过人家做到是矩阵微分,没那么神秘。
然后这里对应的图中应该是CBL模块,不过在咱们这里是Conv。
残差模块
这个对应的其实就是这个模块了CSP1_x 模块
在我们当前版本是这样的
class Bottleneck(nn.Module):
# Standard bottleneck
def __init__(self, c1, c2, shortcut=True, g=1, e=0.5): # ch_in, ch_out, shortcut, groups, expansion
super(Bottleneck, self).__init__()
c_ = int(c2 * e) # hidden channels
self.cv1 = Conv(c1, c_, 1, 1)
self.cv2 = Conv(c_, c2, 3, 1, g=g)
self.add = shortcut and c1 == c2
def forward(self, x):
return x + self.cv2(self.cv1(x)) if self.add else self.cv2(self.cv1(x))
复制代码
C3 模块
这个模块是这个样子的,和残差有点像,但是人家不是相加,而是扩充。 它是保留了一部分,然后进入残差,最后做一个融合。
class C3(nn.Module):
# CSP Bottleneck with 3 convolutions
def __init__(self, c1, c2, n=1, shortcut=True, g=1, e=0.5): # ch_in, ch_out, number, shortcut, groups, expansion
super(C3, self).__init__()
c_ = int(c2 * e) # hidden channels
self.cv1 = Conv(c1, c_, 1, 1)
self.cv2 = Conv(c1, c_, 1, 1)
self.cv3 = Conv(2 * c_, c2, 1) # act=FReLU(c2)
self.m = nn.Sequential(*[Bottleneck(c_, c_, shortcut, g, e=1.0) for _ in range(n)])
# self.m = nn.Sequential(*[CrossConv(c_, c_, 3, 1, g, 1.0, shortcut) for _ in range(n)])
def forward(self, x):
return self.cv3(torch.cat((self.m(self.cv1(x)), self.cv2(x)), dim=1))
复制代码
这个“砍”一半是通过卷积实现的,通过把通道砍到原来的0.5倍实现了留下一半,然后通过残差模块self.m(cv1) 实现卷积部分,然后在通过cat合并。
基本上我们实际的网络架构图里面有的东西就有了,当然这里面其实还有很多门道,你仔细看common文件里面就知道,这些东西的话需要结合论文来说,我这里不好说,为了这个玩意儿我至少看了5,6篇论文,还要整理。
V3バージョンで提案されている7x713x1326x26 gradセルは、ここにあるものです(もちろん、ここではそれほど小さくはありません)。 これは、JiangDabai氏の写真に似ています。
その後、繰り返し続けます。
lxsmの違い
ここに来たので、yolov5の背後にある接尾辞の意味について話しましょう。
実際、このyolov5xx.yamlを開くと、これがわかります。
この違い。
実際、これら2つのパラメーターは、ネットワークの深さと幅を表します。たとえば、width_multipleはここでは0.5です。
出力を制御する方法は?単純。
畳み込みによって出力されるチャネル数のサイズにwidth_mulitpleを掛けると、実際には深度が制御されます。たとえば、元々設定されていた128チャネルを出力しますが、0.5を掛けて出力が64になるため、幅は狭くなります。 。深さもとてもシンプルです。CSP1_Xを覚えていますか?
Zaijiang Dabai氏の写真は、繰り返される残差がいくつかあることを示しています。標準設定はCSP1_3(モジュールがあると仮定)だと思います。3x0.3は1の整数なので、私のCSP1_3は実際にはあります。残差が1つだけであるなど、深さが低下します。設定がすべて1.0であるため、最も標準的なのはyolov5l.ptです。