正確かつ高速な物体検出のための受容野ブロックネット
簡単な紹介
SSDに基づいて、この効果を説明するための神経科学の予備知識の使用が強化され、前方RFBモジュールを置きます。基本的に受容野を強化するために設計された新しい構造であり、人間の網膜は遠く視線の中央に近いほど大きな受容野、ある視線の中心線、小さな現場での経験から、受容野特性を有することを示します。これに基づき、提案RFBモジュールは、人間の視覚特性をシミュレートするために使用されます。
RFBモジュール
図に示すように設定。
なぜ使用のコンボリューションは、それを空に?
受容野を改善するためにまず第一に、直感的なアイデアは、いずれかの層を深め、いずれか大きい方畳み込みカーネルを使用するか、またはコンボリューションを使用する前にプールされることです。ネットワークパラメータの層を深化することは、あまり変化します軽量なタスクを完了することはできません。多くの畳み込みカーネルパラメータもマルチになると、プールのパラメータは増加しませんが、情報損失を行います、バック層に助長されていませんが、情報転送。だからここではどちらも、中空の畳み込みを考えるのが自然ではないパラメータの量を増やすだけでなく、受容野を向上させることができます。
なぜ私はこの多分岐構造が必要なのですか?
これは、前述のように人間の視野は感覚をキャプチャするフィールド異なる受容野の中心、多分岐構造を用いる、各ブランチフィールドからの距離が異なることを特徴とする、異なる受容野の情報をキャプチャすることであり、最終的に連結することにより融合します情報の受容野は、我々は人間の視覚効果のシミュレーションを実現することができます。ここで著者はまた、説明する絵を与えました。
なぜ私はRFBの2つのバージョンが何を提案すべきか?
構造RFBは、1つのパラメータの量を減少させる、第二は、より小さな増加感情で、右の2つの分岐の1×3,3×1にRFBのCONV 3×3の構造と比較して、元のままであります野生、これまた小さな受容野をキャプチャするために、人間の視覚システムのシミュレーションインチ
ネットワークアーキテクチャ
全体的なネットワーク構造を以下に示すが、これはよく理解されています。
フロントはvgg19あり、その後、分岐予測6つの中間層、心の中で何もないより良く理解から分離します。
コードの再現性
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchsummary import summary
class RFBModule(nn.Module):
def __init__(self,out,stride = 1):
super(RFBModule,self).__init__()
self.s1 = nn.Sequential(
nn.Conv2d(out,out,kernel_size = 1),
nn.Conv2d(out,out,kernel_size=3,dilation = 1,padding = 1,stride = stride)
)
self.s2 = nn.Sequential(
nn.Conv2d(out,out,kernel_size =1),
nn.Conv2d(out,out,kernel_size=3,padding = 1),
nn.Conv2d(out,out,kernel_size=3,dilation = 3,padding = 3,stride = stride)
)
self.s3 = nn.Sequential(
nn.Conv2d(out,out,kernel_size =1),
nn.Conv2d(out,out,kernel_size = 5,padding =2),
nn.Conv2d(out,out,kernel_size=3,dilation=5,padding = 5,stride = stride)
)
self.shortcut = nn.Conv2d(out,out,kernel_size = 1,stride = stride)
self.conv1x1 = nn.Conv2d(out*3,out,kernel_size =1)
def forward(self,x):
s1 = self.s1(x)
s2 = self.s2(x)
s3 = self.s3(x)
#print(s1.size(),s2.size(),s3.size())
mix = torch.cat([s1,s2,s3],dim = 1)
mix = self.conv1x1(mix)
shortcut = self.shortcut(x)
return mix + shortcut
class RFBsModule(nn.Module):
def __init__(self,out,stride = 1):
super(RFBsModule,self).__init__()
self.s1 = nn.Sequential(
nn.Conv2d(out,out,kernel_size = 1),
nn.Conv2d(out,out,kernel_size=3,dilation = 1,padding = 1,stride = stride)
)
self.s2 = nn.Sequential(
nn.Conv2d(out,out,kernel_size =1),
nn.Conv2d(out,out,kernel_size=(1,3),padding = (0,1)),
nn.Conv2d(out,out,kernel_size=3,dilation = 3,padding = 3,stride = stride)
)
self.s3 = nn.Sequential(
nn.Conv2d(out,out,kernel_size =1),
nn.Conv2d(out,out,kernel_size = (3,1),padding =(1,0)),
nn.Conv2d(out,out,kernel_size=3,dilation=3,padding = 3,stride = stride)
)
self.s4 = nn.Sequential(
nn.Conv2d(out,out,kernel_size =1),
nn.Conv2d(out,out,kernel_size=3),
nn.Conv2d(out,out,kernel_size = 3,dilation = 5,stride = stride,padding = 6)
)
self.shortcut = nn.Conv2d(out,out,kernel_size = 1,stride = stride)
self.conv1x1 = nn.Conv2d(out*4,out,kernel_size =1)
def forward(self,x):
s1 = self.s1(x)
s2 = self.s2(x)
s3 = self.s3(x)
s4 = self.s4(x)
#print(s1.size(),s2.size(),s3.size(),s4.size())
#print(s1.size(),s2.size(),s3.size())
mix = torch.cat([s1,s2,s3,s4],dim = 1)
mix = self.conv1x1(mix)
shortcut = self.shortcut(x)
return mix + shortcut
class RFBNet(nn.Module):
def __init__(self):
super(RFBNet,self).__init__()
self.feature_1 = nn.Sequential(
nn.Conv2d(3,64,kernel_size = 3,padding = 1),
nn.ReLU(),
nn.Conv2d(64,64,kernel_size=3,padding=1),
nn.ReLU(),
nn.MaxPool2d(kernel_size = 2,stride = 2),
nn.Conv2d(64,128,kernel_size = 3,padding = 1),
nn.ReLU(),
nn.Conv2d(128,128,kernel_size=3,padding=1),
nn.ReLU(),
nn.MaxPool2d(kernel_size = 2,stride = 2),
nn.Conv2d(128,256,kernel_size = 3,padding = 1),
nn.ReLU(),
nn.Conv2d(256,256,kernel_size=3,padding=1),
nn.ReLU(),
nn.Conv2d(256,256,kernel_size=3,padding=1),
nn.ReLU(),
nn.MaxPool2d(kernel_size = 2,stride = 2),
nn.Conv2d(256,512,kernel_size = 3,padding = 1),
nn.ReLU(),
nn.Conv2d(512,512,kernel_size=3,padding=1),
nn.ReLU(),
nn.Conv2d(512,512,kernel_size=3,padding=1),
nn.ReLU(),
)
self.feature_2 = nn.Sequential(
nn.MaxPool2d(kernel_size = 2,stride = 2),
nn.Conv2d(512,512,kernel_size = 3,padding = 1),
nn.ReLU(),
nn.Conv2d(512,512,kernel_size=3,padding=1),
nn.ReLU(),
nn.Conv2d(512,512,kernel_size=3,padding=1),
nn.ReLU(),
)
self.pre = nn.Conv2d(512,64,kernel_size = 1)
self.fc = nn.Conv2d(512,64,kernel_size = 1)
self.det1 = RFBsModule(out = 64,stride = 1)
self.det2 = RFBModule(out = 64,stride = 1)
self.det3 = RFBModule(out = 64,stride = 2)
self.det4 = RFBModule(out = 64,stride = 2)
self.det5 = nn.Conv2d(64,64,kernel_size = 3)
self.det6 = nn.Conv2d(64,64,kernel_size=3)
def forward(self,x):
x = self.feature_1(x)
det1 = self.det1(self.fc(x))
x = self.feature_2(x)
x = self.pre(x)
det2 = self.det2(x)
det3 = self.det3(det2)
det4 = self.det4(det3)
det5 = self.det5(det4)
det6 = self.det6(det5)
det1 = det1.permute(0,2,3,1).contiguous().view(x.size(0),-1,64)
det2 = det2.permute(0,2,3,1).contiguous().view(x.size(0),-1,64)
det3 = det3.permute(0,2,3,1).contiguous().view(x.size(0),-1,64)
det4 = det4.permute(0,2,3,1).contiguous().view(x.size(0),-1,64)
det5 = det5.permute(0,2,3,1).contiguous().view(x.size(0),-1,64)
det6 = det6.permute(0,2,3,1).contiguous().view(x.size(0),-1,64)
return torch.cat([det1,det2,det3,det4,det5,det6],dim = 1)
if __name__ == "__main__":
net = RFBNet()
x = torch.randn(2,3,300,300)
summary(net,(3,300,300),device = "cpu")
print(net(x).size())