赞
踩
经网友提醒,yolo v2的 passthrough 层与 v5 的 focus 层很像,因为海思是支持 passthrough 层的,鉴于此,花了点时间了解了一下,提出一些浅见,抛砖引玉。另附:yolo v5 海思开发
上文我说的是,二者很像,说明它们还是有区别的,现在说说区别。
出于严谨,结合海思文档图片与 passthrough 源码来一起理解,先看看 passthrough 源码:
// 它的源码是 c++ 的,不是 python 格式 int reorg_cpu(THFloatTensor *x_tensor, int w, int h, int c, int batch, int stride, int forward, THFloatTensor *out_tensor) 3 { 4 // Grab the tensor 5 float * x = THFloatTensor_data(x_tensor); 6 float * out = THFloatTensor_data(out_tensor); 7 8 // https://github.com/pjreddie/darknet/blob/master/src/blas.c 9 int b,i,j,k; 10 int out_c = c/(stride*stride); 11 12 for(b = 0; b < batch; ++b){ //batch_size 13 14 for(k = 0; k < c; ++k){ //channel 15 16 for(j = 0; j < h; ++j){ //height 17 18 for(i = 0; i < w; ++i){ //width,可以看见passthrough 是行优先 ! 19 20 int in_index = i + w*(j + h*(k + c*b)); 21 int c2 = k % out_c; 22 int offset = k / out_c; 23 int w2 = i*stride + offset % stride; 24 int h2 = j*stride + offset / stride; 25 int out_index = w2 + w*stride*(h2 + h*stride*(c2 + out_c*b)); 26 if(forward) out[out_index] = x[in_index]; // 压缩channel 27 else out[in_index] = x[out_index]; // 扩展channel 28 } 29 } 30 } 31 } 32 33 return 1; 34 }
再结合海思的文档的图示来看,更加清晰,上图可以看见数据重新排布的顺序是 红色 -> 天蓝色 -> 淡绿(左下) -> 深绿(右下),即行优先。再结合上文第18行代码可得出,passthrough 层确实是行优先,这个先记住。
focus层没有上面的图示,只有代码,我们根据源码举个例子加强理解一下。
# 源码镇楼
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)
def forward(self, x): # x(b,c,h,w) -> y(b,4c,h/2,w/2)
return self.conv(torch.cat([x[..., ::2, ::2], x[..., 1::2, ::2], x[..., ::2, 1::2], x[..., 1::2, 1::2]], 1))
下面举例:
a = np.array(range(8)).reshape(1, 2, 2, 2)
print(a.shape)
print(a)
d = np.concatenate([a[..., ::2, ::2], a
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。