1 各种代码实现列表
2 其中一个的实现效果
3 知乎作者分析
1
https://github.com/XifengGuo/CapsNet-Keras
Other Implementations
- TensorFlow:
- CapsNet-Tensorflow: Very good implementation. I referred to this repository in my code.
- CapsNet-tensorflow
- tf_CapsNet_simple
- PyTorch:
- CapsNet-PyTorch
- capsnet.pytorch
- CapsNet
- MXNet:
- CapsNet_Mxnet
- Lasagne (Theano):
- CapsNet-Lasagne
- Chainer:
- dynamic_routing_between_capsules
2
https://github.com/naturomics/CapsNet-Tensorflow
3 https://www.zhihu.com/question/67287444/answers/created
作者:云梦居客 链接:https://www.zhihu.com/question/67287444/answer/251460831 来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
花了几个小时看完原文,当天下午就把这个model的tensorflow版实现搭了个框架,先来安利一波再作答,欢迎关注我的github。另外,个人认为
@SIY.Z
同学已经很详细的解释了routing部分的算法,我就简单补充下我对原文中第4节CapsNet的理解,若理解有误欢迎指出。
这个model不算最后的reconstruction部分的话,总共就三层。
其中第一层不值得多说,就是一个常规的conv layer,得到一个20x20x256的输出。按照原文的意思,这层的主要作用就是先在图像pixel上做一次局部特征检测,然后才送给capsule。至于为何不从第一层就开始使用capsule提取特征?当然,MNIST是灰度图,每个pixel是一个标量,每个pixel看作低层capsule的输出u_i的话,就不符合capsule输入输出都是vector的要求(不考虑标量是长度为1的vector这个情况,那将退化成现在的CNN模式),但如果把这点作为第一层使用常规conv层的理由,我认为并不充分,我们完全可以使用3 channel的图像数据集来做experiment,达到capsule输入为vector的要求。既然这样,那又是为什么这么设计这层呢,是capsule不具备常规的convolution局部特征检测的能力还是别的原因呢?这是我的一个小疑问,读了原文后我并未从中得到相关的解答,有待进一步实验解决这个疑问。
而第二层(PrimaryCaps)才是真正开始使用capsule的层,但这层跟它的低一层,也就是上面说的conv layer之间,却并未使用routing算法。按照我的理解,这层才是真正为了做routing而准备的。我们先来看下,如果在第一层的输出上做常规的32 channel, 9x9 kernel size和strides 2的CNN,结果是怎么样的呢?事实上我们将得到一个6x6x32的输出,或者说是6x6x1x32的输出(这个1不是随便加的,下面有作用),如图(1):
<img src="https://pic1.zhimg.com/50/v2-453c37d87f48141addd22555ed9dcfac_hd.jpg" data-rawwidth="615" data-rawheight="253" class="origin_image zh-lightbox-thumb" width="615" data-original="https://pic1.zhimg.com/v2-453c37d87f48141addd22555ed9dcfac_r.jpg">
图 (1)
将这个图与原文的Figure 2对比可以看出,原本convolution每次的计算输出是一个scalar value,现在到了PrimaryCaps这里成了一个长度为8的vector,也就是从6x6x1x32到了6x6x8x32(这里1就起作用了,从1到8的转变,也就是从标量向矢量的变化)。这是怎么做到的呢?按照我的理解,其实可以看作第二层在第一层的输出上用8个不同的conv2d层做了共8次32 channel, 9x9 kernel size和strides 2的卷积(每个conv2d分别一次),如下图(2)所示,每次都得到一个6x6x1x32的输出,共8个,再把这些输出在6x6x1x32的第三个纬度上concatenate, 就得到了第二层最终的输出:6x6x8x32大小的高维矩阵,也就对应上了论文里的Figure 2。
<img src="https://pic4.zhimg.com/50/v2-a402c9d94e36bc6bdcf8a6fbe06f78b3_hd.jpg" data-rawwidth="832" data-rawheight="627" class="origin_image zh-lightbox-thumb" width="832" data-original="https://pic4.zhimg.com/v2-a402c9d94e36bc6bdcf8a6fbe06f78b3_r.jpg">
图 (2)
这么理解下来,我们可以发现,primaryCaps层就是多个常规卷积层的叠堆,换句话,就是把8个conv2d封装在一起,然后形成一种新的neural unit,hinton称之为capsule,在这层这种neural unit可以输出8x1的vector,接着第三层我们就能看到输出的是16x1的vector。就说明了这种neural unit的输出可以根据需要设计verctor的输出维度。
——这里我要提一下,有位同学提出,这里的输出[6, 6] grid相互之间是共享权重的,然后又提到6x6x32=1152,这好像没有共享权重啊,我想这位同学是误读了,请大家要仔细阅读,这里在解释的是conv1 和 primaryCaps层之间的变化,按照我上面这个思路,6x6 grid之间是权重共享的,提到1152是在后面primaryCaps和digitCaps层之间的计算了。请大家注意辨别。
此外,第二层的卷积操作除了可以看作是多个常规的卷积叠堆后的效果外,还有一点是跟传统的卷积过程是不一样的,那就是对每个长度为8的vector做了文中的Eq. 1的向量单位化和缩放操作(存疑的地方:capsule内部每次的卷积只做加权求和,但不做非线性的activation非线性转换,还是加权求和后也做ReLU这类non-linearity activation呢,读了多次论文似乎没提到),公式如下,其他楼层有这个公式的解读:
<img src="https://pic4.zhimg.com/50/v2-c4da295bce77eeacb0d81caa0e1f1c7f_hd.jpg" data-rawwidth="231" data-rawheight="81" class="content_image" width="231">
Eq. 1
到了这里,第二层的计算也就完了。第三层(DigitCaps)在第二层的输出之上就开始使用了 routing 算法。这一层依然可以跟传统的网络做比较,可以看作一个全连接层,这在原文里也有提到:
<img src="https://pic1.zhimg.com/50/v2-66edbc5890111cad186cc05a1ed15bf4_hd.jpg" data-caption="" data-rawwidth="681" data-rawheight="83" class="origin_image zh-lightbox-thumb" width="681" data-original="https://pic1.zhimg.com/v2-66edbc5890111cad186cc05a1ed15bf4_r.jpg">
文中第4节的第一段第二行就说了,这个Net就是两个卷积层加第三层的fully connected layer,说明Hinton大大也是认为这个就相当于capsule版的全连接层。怎么理解呢?上图:
<img src="https://pic1.zhimg.com/50/v2-17e05dec0b0a07f80091291b4e21bcbc_hd.jpg" data-rawwidth="505" data-rawheight="259" class="origin_image zh-lightbox-thumb" width="505" data-original="https://pic1.zhimg.com/v2-17e05dec0b0a07f80091291b4e21bcbc_r.jpg">
图 (3)
请你先把第二层的6x6x8x32输出看作上图左边的样子,也就是每个长度为8x1的vector就是一个点,一个向量点!这里说的一个点在文中就是指u_i。而第三层的输出也可以看作是由10个神经元输出的10个点,每个点同样是向量点,其中向量的维度为16x1,在文中就是指v_j。所以第二层向第三层共输入32x6x6=1152个点,即 i 取值为0到32x6x6=1152, 而 j 取值为从0到10, 其中第三层的每个神经元代表一类数字(0-9)出现的可能性。那么就好理解了,传统的一个神经元就是对输出做加权求和然后非线性激活,现在就不是这样了,而是每个神经元(capsule)内部使用routing算法。至于这个routing算法起到了什么作用呢?结合他人的观点后,我认为这个routing确实有几分类似于 attention的机制,但它跟attention的差别就是,routing是低层neural unit选择高层neural unit,而attention是高层的选择低层的。
阅读原文访问
https://www.zhihu.com/question/67287444/answers/created 查看全部