Dynamic Routing Between Capsules

摘要

这个是最近比较火的Hinton关于对之前深度神经网络的质疑性论文, 大家都知道Hinton在深度学习领域的地位,那么他为什么对dnn提出质疑,甚至于最近他的演讲论文的title 是 “What is wrong with convolutional neural nets?”。我们来看下具体是什么情况。

定义

capsule: 神经网络的一个层分成多个组,每个组包含多个神经元,他的输出是一个激活向量
激活向量:它是一个向量,它的长度(2范数)用来表示实体存在的概率,方向来表示实体的参数
激活capsule: 上一层的每个capsule通过转换矩阵来得到一个“预测向量”,预测这个capsule和下一层的capsule连接的概率,只有上一层多个capsule的预测是一致的时候,这个这个下层的capsule变为激活状态。

质疑点

论文还没有开始,我先列下Hinton对dnn的质疑点:

  • dnn能发挥的能力取决于我们对不同layer的结合,我们通常用的是全连接的方式来连接不同的layer。但是这种方式除了在计算的时候带来性能消耗外,还带来其他的负面影响。我们认为 l层是 眼睛和嘴的单元,l+1 层是脸的单元,这样的连接是有意义的。但是我们把 眼,轮子,手 连接到 脸,其实是无意义的,还加入了干扰信息。所以他们要寻找一种比纯粹全连接更加有意义的连接方式,而且这种方式更容易也更快优化。
  • dnn是用bp的形式优化的,但是相反大脑神经元的连接原理是遵从Hebbian 原则:共同激发的神经元连接在一起,Capsules 也是模仿这个假设,低级的capsule更加倾向于将自己的输出传输给某种高级的capsules,这种高级的capsules的激活的向量和低级capsule的数据的点积值比较高。
  • 标准的dnn 比如:AlexNet,ResNet,层级之间的下采样pooling连接,采用的 max操作,考虑的2x2这样的邻近像素中最大的值,这里的pooling层没有要学习的参数。一种更好的想法是让他们在更大的区域去学习怎么pool,另外一种更优的方式是一种动态的模式:对于每个可能的父capsule,它自身通过对output和一个权重矩阵进行计算得到一个“预测向量”,有了这个预测向量,这个capsule就知道和那些父capsule进行层级连接了。这个机制称为 routing-by-agreement

CapsNet 机制

CapsNet故名思意它是capsules组成的网络,一般:
第一层是正常的卷积层,卷积层之后生成一个基础的capusle层,然后开始多层的capsules组成的layers。

capsule是一组unit的组合,capsule分别接受上一层每一个capsule的输入,然后经过内部迭代计算,得出一个向量。

我们希望输向量的长度用来代表这个capsule在这个层级能代表这个entity的概率(直观的解释是,假如这个capsule所在的层是预测层,那么每个capsule代表一个类别,最长输出的那个capsule的那个类别概率最大),我们用一个非线性的挤压函数,将短的向量的长度(向量长度)接近0,将长的向量长度变的接近为1

这里保证长度代表概率的机制为,非线形函数:
vj=||sj||21+||sj||2sj||sj||

输入是 sj , 输出是 vj

代码为:

# squash function
ded squash(capsules):
    vec_squared_norm = tf.reduce_sum(tf.square(capsules), -2, keep_dims=True)
    scalar_factor = vec_squared_norm / (1 + vec_squared_norm) / tf.sqrt(vec_squared_norm + epsilon)
    vec_squashed = scalar_factor * capsules  # element-wise

详细示例及代码:

我们以手写笔识别的CNN网络为例:

这里写图片描述
首先:输入图片

Conv1:

经过一个卷积层,卷积层的filter 为:9 x 9, stride=1, 输出的通道数是256

conv1 = tf.layers.conv2d(input, 256, 9, strides=(1, 1), padding='VALID')
# output_nul=256
# kernel_size=9
# conv1 shape = [batch_size, 20, 20, 256]

PrimaryCaps:

也是一个卷积层,filter 为: 9 x 9,strip=2,输出是 32 * 8, 其中32为通道数量,8为每个capsule的神经单元数, 然后经过一个squash 函数:

# output 32 * 8
# shape [batch_size, 6, 6, 32 * 8]
capsules = tf.layers.conv2d(conv1, 32 * 8, 9, strides =(2,2), padding='VALID', activation=tf.nn.relu)
# 8 units per capsule, 1152 capsules
# shape [batch_size, 1152, 8, 1]
capsules = tf.reshape(capsules, (batch_size, -1, 8, 1))

u_i = squash(capsules)

DigitCaps:

capsule 输入输出的计算, 这是算法和机制的重点:

我们先直接贴出capsule输出迭代的算法,然后我们一步步分析:

这里写图片描述
这个示例我们只是演示了一层capsules,如果多层只要将这个过程重复即可:

我们假设上一层的capsules的输出是 ui(u1,u2,...,um)

下面我们开始这个针对下一层capsule j路由的迭代:
ui 在经过一个针对j的独立线性变换后,得到一个i 对j的预测向量,
它的长度表示i是不是目标的概率。
û j|i=Wijui
这里的 Wij 不是共享的向量,假设上一层有i个capsule,
下一层有j个capsule,那么连层连接的W的个数就有i * j个。
代码:

W = tf.get_variable('Weight', shape=(1152, 10, 8, 16), dtype=tf.float32
u_hat_ji = tf.matmul(W, u_i, transpose_a=True)

其中 1152为上一层的输出capsule i的个数,10位下一层capsules j的数量,所以该层连接的W数量是1152 * 10 个。

上面我们计算的是单个capsule i对 j的预测,我们下面需要的上一层的每一个capsule的预测进行综合。

首先我们介绍 bij
它是一个参数,代表capsule i 和下一层 capusle j是否建立连接,可以初始化为0向量,求出它我们就有了路由信息,知道该和哪个capsule进行连接了。

# capsule num i=1152
# capsule num j=10
b_IJ = tf.constant(np.zeros([batch_size, 1152, 10, 1, 1], dtype=np.float32))

下面就开始算法的迭代了

Loop Start

  • 对于上一层的一个i而言,我们计算i 到下一层各个capule的概率,也就是和它们每一个连接的可能性:
    cij=exp(bij)kexp(bik)
c_IJ = tf.nn.softmax(b_IJ, dim=2)
  • 对于下一层的一个j而言,我们得到i对j的输出预言:
    sj=icijû j|i
s_J = tf.multiply(c_IJ, u_hat)
s_J = tf.reduce_sum(s_J, axis=1, keep_dims=True)
  • 综合所有上一层capsules的预言,预言一致性选择:

vj=||sj||21+||sj||2sj||sj||

  • 对输出进行squash处理
v_J = squash(s_J)
  • 更新变量

aij=vj.û j|i
bij=bij+aij

u_produce_v = tf.matmul(u_hat, v_J, transpose_a=True)
b_IJ += u_produce_v

Loop End

预测

vj 的长度可以用来预测case j是目标的概率,
所以下一步先计算j维度的长度,然后利用softmax计算概率
代码:

self.v_length = tf.sqrt(
                        tf.reduce_sum(
                            tf.square(v_j),
                                axis=2, keep_dims=True) + epsilon)

self.softmax_v = tf.nn.softmax(self.v_length, dim=1)

Margin loss

我们按手写数字的case为例:
我们最终的目的是预测数字的分类,比如:0-9,最后一层的capsules, 假如数字是5,那么第5个capsule的示例向量应该很长,我们给个综合的Margin loss:
Lc=Tcmax(0,m+||vc||)2+λ(1Tc)max(0,||vc||m)2
这里如果capsule命中label, Tc =1,否则为0
m+=0.9 , m=0.1 , 建议的 λ=0.5
所有的loss 是这些最后一层的capsule的loss总和。

综述

下面对比下capsule机制和传统的神经单元的对比:


这里写图片描述

其他

Reconstruction as a regularization method

参考

论文:https://arxiv.org/pdf/1710.09829v1.pdf
代码:https://github.com/naturomics/CapsNet-Tensorflow
其他:https://medium.com/mlreview/deep-neural-network-capsules-137be2877d44

关注公众号:

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值