Lam1360 / YOLOv3-model-pruning

在 oxford hand 数据集上对 YOLOv3 做模型剪枝(network slimming)
MIT License
1.67k stars 431 forks source link

关于prune_utils.py中prune_model_keep_size()函数的理解 #59

Open coldlarry opened 4 years ago

coldlarry commented 4 years ago

最近正在学习这个项目,大部分代码都已经看懂了,但是看到prune_model_keep_size()函数时,有点不知所云 `def prune_model_keep_size(model, prune_idx, CBL_idx, CBLidx2mask):

pruned_model = deepcopy(model)
for idx in prune_idx:
    mask = torch.from_numpy(CBLidx2mask[idx]).cuda()
    bn_module = pruned_model.module_list[idx][1]

    bn_module.weight.data.mul_(mask)

    activation = F.leaky_relu((1 - mask) * bn_module.bias.data, 0.1)

    next_idx_list = [idx + 1]
    # 两个上采样层前的卷积层
    if idx == 79:
        next_idx_list.append(84)
    elif idx == 91:
        next_idx_list.append(96)

    for next_idx in next_idx_list:
        next_conv = pruned_model.module_list[next_idx][0]
        conv_sum = next_conv.weight.data.sum(dim=(2, 3))
        offset = conv_sum.matmul(activation.reshape(-1, 1)).reshape(-1)
        if next_idx in CBL_idx:
            next_bn = pruned_model.module_list[next_idx][1]
            next_bn.running_mean.data.sub_(offset)
        else:
            next_conv.bias.data.add_(offset)

    bn_module.bias.data.mul_(mask)

return pruned_model`

有大神能解释一下这个for next _idx in next_idx_list循环中,到底做了什么事吗?感激不尽

coldlarry commented 4 years ago

@Lam1360 @violet17

coldlarry commented 4 years ago

看到@violet17,在一个回答中提到:


剪枝的时候会先对 bias 做处理,用其后的卷积层或者 BN 层来吸收这个参数,然后再将权重赋值给 compact model, 这样做的话就能保证 pruned_model (只对 weight 置 0 的模型)和 Compact_model 对相同的输入有相同的输出

想问一下,为什么不直接将pruned_model的weights和bias全部置0,而是先将weights置0,再将bias转移到下一层?

coldlarry commented 4 years ago

我在network slimming中看不到这样的转移做法

liuyuxun12 commented 4 years ago

您好!~这个问题你解决了吗?

GeneralJing commented 3 years ago

最近看到这段代码的时候,也有点疑惑,有更好的资料解释这个吗?