前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Geoffrey Hinton的“胶囊理论” 多语言实现代码、效果、论文解读

Geoffrey Hinton的“胶囊理论” 多语言实现代码、效果、论文解读

作者头像
用户1908973
发布2018-07-24 14:47:59
3240
发布2018-07-24 14:47:59
举报
文章被收录于专栏:CreateAMindCreateAMind

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 查看全部

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2017-11-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 CreateAMind 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档