YOLOv2源码分析--reorg layer

文章全部YOLOv2源码分析

reorg layer中最关键的代码如下

void reorg_cpu(float *x, int w, int h, int c, int batch, int stride, int forward, float *out)
{
    int b,i,j,k;
    int out_c = c/(stride*stride);

    for(b = 0; b < batch; ++b){
        for(k = 0; k < c; ++k){
            for(j = 0; j < h; ++j){
                for(i = 0; i < w; ++i){
                    int in_index  = i + w*(j + h*(k + c*b));
                    int c2 = k % out_c;
                    int offset = k / out_c;
                    int w2 = i*stride + offset % stride;
                    int h2 = j*stride + offset / stride;
                    int out_index = w2 + w*stride*(h2 + h*stride*(c2 + out_c*b));
                    if(forward) out[out_index] = x[in_index];
                    else out[in_index] = x[out_index];
                }
            }
        }
    }
}

这一部分表述为数学公式就是

  • i n _ i n d e x = W 1 + W ∗ s t r i d e ∗ ( H 1 + H ∗ ( C 1 + C ∗ B ) ) in\_index=W_1+W*stride*(H_1+H*(C_1+C*B)) in_index=W1+Wstride(H1+H(C1+CB))

  • C 2 = C 1 % C o u t C_2=C_1\%C_{out} C2=C1%Cout

  • o f f s e t = C 1 / C o u t offset = C_1/C_{out} offset=C1/Cout

  • W 2 = W 1 ∗ s t r i d e + o f f s e t % s t r i d e W_2=W_1*stride+offset\%stride W2=W1stride+offset%stride

  • H 2 = H 1 ∗ s t r i d e + o f f s e t / s t r i d e H_2=H_1*stride+offset/stride H2=H1stride+offset/stride

  • o u t _ i n d e x = W 2 + W ∗ s t r i d e ∗ ( H 2 + H ∗ s t r i d e ∗ ( C 2 + C o u t ∗ B ) ) out\_index = W_2+W*stride*(H_2+H*stride*(C_2+C_{out}*B)) out_index=W2+Wstride(H2+Hstride(C2+CoutB))

对于前向传播,想要表达的意思就是下面这个图

那么我们知道,矩阵运算可以更加简洁的表示上面的代码中的循环,我这里给出pytorch下的代码示例

B,C,H,W = input.size()
input = input.view(B, C, H/stride, stride, W/stride, stride).transpose(3,4).contiguous()
input = input.view(B, C, H/stride*W/stride, stride*stride).transpose(2,3).contiguous()
input = input.view(B, C, stride*stride, H/stride, W/stride).transpose(1,2).contiguous()
input = input.view(B, stride*stride*C, H/stride, W/stride)

非常简洁的就解决了上述的问题,但是简洁背后的数学原理你要明白。

首先我先说一下这里的参数含义:

  • B:batch
  • C:通道数目
  • H:高
  • W:宽

按照论文中的做法,我们这里stride取2

input = input.view(B, C, H/stride, stride, W/stride, stride).transpose(3,4).contiguous()

这里的view函数的意义,我么可以理解为“看成”

这个式子想要表达的含义如下图:

input = input.view(B, C, H/stride*W/stride, stride*stride).transpose(2,3).contiguous()

这个式子想要表达的含义如下图:

从第一个式子到第二个式子的过程我们可以抽象为

input = input.view(B, C, stride*stride, H/stride, W/stride).transpose(1,2).contiguous()

这个式子想要表达的含义如下图:

最后抽象为

觉得不错,点个赞吧b( ̄▽ ̄)d

由于本人水平有限,文中有不对之处,希望大家指出,谢谢_!

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值