1、capsule 网络
Hinton团队在2017年 发表 Dynamic Routing Between Capsules 一文。
capsule是使用向量来表示参数的一组神经元,或者说是特征.文中,capsule是为了改善CNN而提出。更高层的capsule代表了更大局域的图片。capsule network 没有像 CNN 池化层那样丢失信息。
对于CNN而言,两张图片是类似的,因为它们包含相似的部件,这是胶囊网络希望解决的事情。
Reddit上有 Geoffrey Hitton关于pooling的看法。
胶囊网络解决方案:
较为底层的特征(手、眼睛、嘴巴等)将只被传送到与之匹配的高层。如果,底层特征包含的是类似于眼睛或者嘴巴的特征,它将传递到“面部”的高层,如果底层特征包含的是类似手指、手掌等特征,它将传递到“手”的高层。
实现对空间信息进行编码同时也计算物体的存在概率。这可以用向量来表示,向量的模表示特征存在的概率,向量的方向表示特征的姿态信息。
2、模型
2.1 特征聚类
特征聚类是对输入的特征(每个特征都使用向量表示,而不是标量)进行聚类。聚类评价方式有欧氏距离,但是 capsule网络使用内积方式。(使用内积的理由是,考量一个特征和其他特征的关系,欧氏距离每次只能是一个特征和另外一个特征的关系)。
2.2 特征显著性
特征显著性是,表示特征的强弱,因为特征是向量,这里使用向量除了其本身的范数,然后乘于一个与范数相关的非线性函数。
使用输出向量的长度代表这个capsule的存在概率。 并且使用squashing函数(类似激活函数)使得向量的长度在 0~1。
输出向量的压缩:
vj=∥sj∥21+∥sj∥2sj∥sj∥\mathbf{v}_{j}=\frac{\left\|\mathbf{s}_{j}\right\|^{2}}{1+\left\|\mathbf{s}_{j}\right\|^{2}} \frac{\mathbf{s}_{j}}{\left\|\mathbf{s}_{j}\right\|}vj=1+∥sj∥2∥sj∥2∥sj∥sj
2.3动态路由
值得注意的是,capsule网络不使用梯度下降的方式,也就是公式中不包含 argmax,而是使用迭代法来进行求解,一般来说,迭代次数K
越多,精度越高,同时,会面临梯度消失问题。迭代次数少,那么,就造成精度不够。实际中,K
选取1,后面会解释。
2.4 变换矩阵
变换矩阵可以解决,capsule网络提取的信息局限于类中心向量信息,以及为迭代提供更好的特征初始化(如果初始化都一样,迭代就无法收敛了)。
三种包含变换矩阵的capsule网络(左上,没有初始化矩阵;右上,包含初始化矩阵,以及变换阵共享;下,变换矩阵权重不共享,矩阵数目是len(u)*len(v)
.)
2.5算法
以下是动态路由算法。
v
是输出的胶囊; u
是输入的胶囊,不断更新输出的胶囊。
3、实现
参考 苏神开源的capsule 网络。
def squash(x, axis=-1):s_squared_norm = K.sum(K.square(x), axis, keepdims=True)scale = K.sqrt(s_squared_norm + K.epsilon())return x / scaleclass Capsule(Layer):def __init__(self, num_capsule, dim_capsule, routings = 3, kernel_size= (9,1),share_weights = True, activation = 'default', **kwargs):super(Capsule, self).__init__(*kwargs)self.num_capsule = num_capsuleself.dim_capsule = dim_capsuleself.routings = routingsself.kernel_size = kernel_sizeself.share_weights = share_weightsif activation == 'default':self.activation = squashelse:self.activation = Activation(activation)def build(self, input_shape):super(Capsule, self).build(input_shape)input_dim_capsule = input_shape[-1]if self.share_weights:self.W = self.add_weight(name = 'capsule_kernel', shape = (1, input_dim_capsule, self.num_capsule *self.dim_capsule),initializer = 'glorot_uniform', trainable = True)else:input_num_capsules = input_shape[-2]self.W = self.add_weight(name = 'capsule_kernel', shape =(input_num_capsule,input_dim_capsule, self.num_capsule * self.dim_capsule),initializer = 'glorot_uniform', trainable = True)def call(self, u_vecs):if self.share_weights:u_hat_vecs = K.conv1d(u_vecs, self.W)else: u_hat_vecs = K.local_conv1d(u_vecs, self.W, [1], [1])batch_size = K.shape(u_vecs)[0]input_num_capsule = K.shape(u_vecs)[1]u_hat_vecs =K.reshape(u_hat_vecs, (batch_size, input_num_capsule, self.num_capsule,self.dim_capsule))u_hat_vecs = K.permute_dimensions(u_hat_vecs, (0, 2, 1, 3))b = K.zeros_like(u_hat_vecs[:, :, :, 0])for i in range(self.routings):b = K.permute_dimensions(b, (0, 2, 1))c = K.softmax(b)c = K.permute_dimensions(c, (0,2,1))b = K.permute_dimensions(b, (0, 2, 1))outputs = self.activation(K.batch_dot(c, u_hat_vecs, [2, 2]))if i < self.routings -1:b = K.batch_dot(outputs, u_hat_vecs, [2,3])return outputs def compute_output_shape(self, input_shape):return (None, self.num_capsule, self.dim_capsule)
调用
input_image = Input(shape=(None, None, 1))
input_image1 = Reshape((-1, 52))(input_image)
print(input_image1.shape)
capsule = Capsule(10, 52, 3, True)(input_image1)
print(capsule.shape)
output_shape=(num_classes,))(capsule)
capsule = Flatten()(capsule)x = Dropout(0.2)(Activation(activation="relu")(BatchNormalization()(Dense(220)(capsule))))output = Dense(num_classes, activation="softmax")(x)
print(output.shape)model = Model(inputs=input_image, outputs=output)
model.compile(loss= 'categorical_crossentropy',optimizer='adam',metrics=['accuracy'])model.summary()
4 感想
胶囊网络是一种用一个向量表示一个特征,并称作为胶囊,希望输入胶囊能聚成几类,每类用一个输出胶囊表示。为了实现聚类,使用内积来衡量每个输出胶囊和各个输入胶囊的相似度,并且这个过程使用迭代的方式来完成,也称作动态路由算法。
capsule 抛弃了卷积和池化的观念,引入 聚类的概念。 一些博文说到, capsule具有更好的表示输入数据的结构的性能。
细节:输入胶囊经过一个变换矩阵,得到更加丰富表示,防止输入胶囊只能学习到输入胶囊的中心向量。
Q1:为什么使用迭代方法,而不是梯度下降法?
输出是输入的聚类,而聚类通常都需要迭代算法。引入的变换阵还是需要梯度下降法来完成。
Q2:为什么使用变换阵,好处?
丰富学习输入胶囊信息,防止只学习到所有输入胶囊的中心向量。
输入向量与权重矩阵的矩阵乘法。这编码了图像中低级特征和高级特征之间非常重要的空间关系。
Q3:为什么使用胶囊网络,好处?
基于聚类思想来代替池化完成特征整合的方案,特征表达能力更加强大。
Q4:既然胶囊网络是想把比较相近的特征放到同一层,那么,胶囊网络设计时是否也是由多层网络组成?看到开源的代码都只有两层网络,一层输入层,一层输入层,这样是不是代表所有相关的特征都提取到最后那一层?
应该是高层的一个胶囊,代表它那类的特征信息。
问题:
虽然,CapsNet在简单的数据集MNIST上表现出了很好的性能,但是在更复杂的数据集如ImageNet、CIFAR-10上,却没有这种表现。这是因为在图像中发现的信息过多会使胶囊脱落。
————
参考:
- Hinton论文 dynamic-routing-between-capsules;
- Hinton 论文2 MATRIX CAPSULES WITH EM ROUTING;
- J. hui Blog;
- 苏神blog 揭开迷雾,来一顿美味的Capsule盛宴;
- 苏神blog2;
- 苏神blog3;
- Kaggle Capsule;
- 机器之心 如何理解和使用胶囊网络;