大家好啊,我是董董灿。
昨天写了一篇关于分组卷积的文章:分组卷积的思想神了,然后有同学希望多了解下通道洗牌。
我个人感觉,通道洗牌这个算法,或者说这个思想,可以称之为小而精,并且是实际解决了大问题的经典算法。
今天就来一起看看。
1、通道洗牌的背景
分组卷积(Group Convolution)那篇文章中提到,分组卷积的好处是可以将一个大卷积在通道维度拆分成多个小卷积,来实现每个小卷积的并行计算,从而减少内存占用,提高性能。
但是分组卷积会带来一个副作用,那就是组与组之间的特征无法交互和融合,会使得整个神经网络最终的训练/推理效果不尽如人意。
怎么办呢?人们就想到了洗牌这一算法。
通道洗牌主要就是为了解决分组卷积带来的副作用,也就是组间的特征无法交互融合。
这里举一个例子说明一下这个问题。
一个年级共150人,如果你是年级主任,你肯定希望这150人的成绩都能达到最好,成绩好的帮助成绩差的,大家互相帮助,一起进步。
最理想的情况是,每个人都可以和其他人互帮互助,这样,150人中成绩最差的同学,也可以和成绩最好的同学交流,来提高自己的成绩。
但是,一个不好的现象便是,我们通常会将150人分班学习,假设150人分了3个班,每个班50人。
结果便是每个班内的同学交流很多,而班与班之间的交流却很少。
假设成绩最差的同学在3班,称他为学渣A,3班成绩最好的同学称他为学霸B,而3个班150人中的年级第一在1班,称他为学神C。
很显然,学渣A和学神C是很难在一起交流学习的,因为不在一个班。
而学渣A能够到的天花板,也就是本班的学霸B,而学霸B可能比学神A的平均成绩少20分。
这就会导致班与班之间学习发展不平衡。
一个很容易想到的解决办法就是学生走班制,让每个班的学生可以有机会去其他班上课。使3个班的平均成绩尽可能的接近。
通道洗牌就是类似于学生走班制。
在进行分组卷积之前,经过通道洗牌操作,可以把通道内的数据(150个学生)随机打乱或按一定规则打乱,然后分为三组。
记住每次计算分组卷积前都这么做,可以很有效的确保每次分到三个班的学生都是不同的,从而实现整体的信息交流。
2、如何完成洗牌
利用程序完成洗牌有很多种方法,比如随机洗牌等,但一个更简单的完成洗牌的动作便是转置。
我们假设有以下数据,用下图左侧图来表示,分组前橙色和蓝色是不在一个组里的。
经过对原始数据做转置(行与列互换)之后,可以看到每一组中都包含三种颜色的数据,也就完成了转置前不同组间的信息交流。
对于卷积的通道而言,利用转置来完成通道洗牌也很简单。
假设通道数为 c,分组卷积将通道数分为 g 组,每组 n 个特征,那么可以得到 c = g * n。
利用程序完成洗牌的逻辑便是,先将一维通道数据 reshape 成 (g, n) 的二维数据,然后转置变成 (n, g) 的数据,然后再 reshape 回一维数据,完成分组和通道洗牌操作。
伪代码如下
c = c.reshape((g, n))group_c = np.transpose(c, (1, 0))new_c = group_c.reshape((n, g))
三行代码就可以完成通道洗牌的操作,是不是很简单?
关于卷积的其他文章,感兴趣的小伙伴可以查看: