Capsule Network
Capsule Network最大的特色在于vector in vector out & 动态路由算法。
vector in vector out
所谓vector in vector out指的是将原先使用标量表示的神经元变为使用向量表示的神经元。这也即是所谓的“Capsule”,“vector in vector out”或者“胶囊”所要表达的意思。按照Hinton的理解,每一个胶囊表示一个属性,而胶囊的向量则表示该特征的某些“含义”。比如,之前我们使用标量表示有没有羽毛,现在我们使用向量来表示,不仅表示有没有,还表示了有什么颜色,什么材料的特征。也就是说将神经元从标量改为向量后,在特征提取时,对单个特征的表达更为丰富了。
这有些像NLP中的词向量,之前使用的是one hot表示一个词,只能表示有没有该词而已,引入了word2vec不但表示有没有,而且能够表示该词的“意思”,表意更加丰富了。
部分人叫“Capsule Network胶囊网络”为“张量网络”
层层抽象,层层分类
上图展示了特征\(u_1\)的连接,目前从上一层传来的特征\(u_1\)假设表示羽毛,下一层抽取得到的\(v_1,v_2,v_3,v_4\)分别表示猫、狗、兔、鸟4个种类。可以很容易想到softmax:
\[
(p_{1|1},p_{2|1},p_{3|1},p_{4|1})=\frac{1}{Z_1}(e^{u_1^T v_1},e^{u_1^T v_2},e^{u_1^T v_3},e^{u_1^T v_4}),\quad Z_1=\sum_{i=0}^4e^{u_1^T v_i}
\]
我们一般选择最大的那个概率就行了,但是单靠这一个特征是不够的,我们需要综合各个特征,可以把上面的softmax对各个特征都做一遍,获得\((p_{1|2},p_{2|2},p_{3|2},p_{4|2}),(p_{1|3},p_{2|3},p_{3|3},p_{4|3})...(p_{1|5},p_{2|5},p_{3|5},p_{4|5})\)。这时就需要融合这些特征,很容易想到“加权和”对于特征\(u_i\),获得的特征分布为\((p_{1|i},p_{2|i},p_{3|i},p_{4|i})\),加权和就是:\(\sum_i u_ip_{j|i}(j=1,2,3,4)\)。对于希望获得向上一层的特征\(v_j\),这里paper中使用了一种squash函数处理后,就变成了向上一层的特征\(v_j\),也即:
\[
v_j=squash(\sum_i p_{j|i}u_i)=squash(\sum_i\frac{e^{u_i^T v_j}}{Z_i}u_i)
\]
所谓squash函数就是Capsule Network中的激活函数,和ReLU, tanh, sigmoid函数作用类似,原文中的函数如下:
\[
squash(x)=\frac{||x||^2}{1+||x||^2}\frac{x}{||x||}
\]
后半部分\(\frac{x}{||x||}\)就是将向量模变为1,前半部分\(\frac{||x||^2}{1+||x||^2}\)是一个缩减函数,函数值始终小于1。在\(||x||\)近于0时有放大作用,\(||x||\)越大,越没有影响。关于前半部分\(\frac{||x||^2}{1+||x||^2}\),将模长压缩至0~1有很多方法,比如\(tan||x||,1-e^{-||x||}\),是不是\(\frac{||x||^2}{1+||x||^2}\)这种压缩方式最好;如果在中间层,这个压缩处理是否有必要,由于有动态路由在里面,即使去掉squash函数也具有非线性;另外分母上的常数1哪来的?可不可以尝试其他常数实验效果,这会是一个超参数吗
动态路由
注意到:
\[
v_j=squash(\sum_i p_{j|i}u_i)=squash(\sum_i\frac{e^{u_i^T v_j}}{Z_i}u_i)
\]
为了求\(v_j\)需要求softmax,而为了求softmax又需要知道\(v_j\),似乎陷入了鸡生蛋,蛋生鸡的问题,这就是动态路由(Dynamic Routing)要解决的问题,它能够“自主更新”参数,从而达到Hinton放弃梯度下降的目标。看一个NLP的例子,考虑一个向量\((x_1,x_2,...,x_n)\),现在希望将n个向量整合成一个向量\(x\)(encoder)。简化下情况,仅仅使用原来向量的线性组合,也就是:
\[
x=\sum_{i=1}^n \lambda_ix_i
\]
这里的\(\lambda_i\)相当于衡量了\(x\)与\(x_i\)的相似度,衡量了\(x_i\)在最终的\(x\)中的重要程度,这也是一个鸡生蛋,蛋生鸡的问题,解决方法就是迭代。定义一个基于softmax的相似度指标,然后“加权和”:
\[
x=\sum_{i=1}^n\frac{e^{x^Tx_i}}{Z}x_i
\]
一开始,我们将\(x\)初始化为各个\(x_i\)的均值,然后将\(x\)带入右侧,左侧得到一个新的\(x\),然后再将其带入右侧,如此反复,一般迭代有限次即可收敛。为了得到得到各个\(v_j\),一开始先将它们初始化为\(u_i\)的均值,然后带入softmax迭代求解即可。事实上,输出是输入的聚类结果,而聚类通常都需要迭代算法,这个迭代算法即是“动态路由”。至于这个动态路由的细节,其实是不固定的,取决于聚类的算法。在Dynamic Routing Between Capsules. NIPS 2017 一文中,路由算法为:
\[
\begin{aligned}
&动态路由算法version1\\
\\
&初始化b_{ij}=0 \\
&迭代r次:\\
&\qquad c_i \gets softmax(b_i);\\
&\qquad s_j\gets\sum_ic_{ij}u_i;\\
&\qquad v_j\gets squash(s_j);\\
&\qquad b_{ij}\gets b_{ij}+u_i^Tv_j
\end{aligned}
\]
这里的\(c_{ij}\)即是前文中的\(p_{j|i}\)。这里有人认为原文中的\(b_{ij}\gets b_{ij}+u_i^Tv_j\)有误,应为\(b_{ij}\gets u_i^Tv_j\)。没有看懂什么意思,不作评价。
补充下聚类算法K-Means的伪代码:
\[
\begin{aligned}
输入:&样本集D=\{x_1,x_2,...,x_m\};\\
&聚类簇数k.\\
过程:\\
&从D中随机选择k个样本作为初始均值向量\{\mu_1,\mu_2,...,\mu_k\}\\
&repeat\\
&\quad 令C_i=\phi(1\leq i \leq k)\\
&\quad for\ j=1,2,...,m\ do\\
&\qquad 计算样本x_j 与各个均值向量\mu_i(1\leq i\leq k)的距离:d_{ij}=||x_j-\mu_i||_2;\\
&\qquad 根据距离最近的均值向量确定x_j的簇标记:\lambda_j=argmax_{i\in\{1,2,...,k\}}d_{ij};\\
&\qquad 将样本x_j划入相应的簇:C_{\lambda_j}=C_{\lambda_j}\cup\{x_j\};\\
&\quad end\ for\\
&\quad for\ j=1,2,...,k\ do\\
&\qquad 计算新的均值向量:\mu_{i}'=\frac{1}{|C_i|}\sum_{x\in C_i}x;\\
&\qquad 更新均值向量:\mu_i\gets\mu_{i}'\\
& until\ 当前所有均值向量均不再更新
\end{aligned}
\]
类比下,这里的\(x_1,x_2,...,x_m\)可以看作是上一层传来的特征\(u_i\);而获得的聚类中心,即均值向量\(\mu_i\)可以看作是这层抽取得到的特征\(v_j\)。按照这个算法,\(v_j\)能够迭代的算出来,那就真的抛弃反向传播了,但事实上\(v_j\)是作为输入\(u_i\)的某种聚类中心出现的,如果如此,各个\(v_j\)就都一样了。上面类比的K-Means算法获得聚类中心是需要一个参数“聚类簇数k”,这在动态路由中是没有的,类似的,神经元需要从多个角度看输入,从而得到不同的聚类中心。可以想象一个立方体,从正面获得一个中心点,从侧面又获得一个,从上面的面又可以获得一个中心点。为了实现“多角度看特征”,可以在上一层胶囊传入下一层之前,乘上一个矩阵做变换,这种变换就是所谓的仿射变换,它给神经元看特征提供了“观察角度”,这个矩阵现在还是需要反向传播训练得到的。那么,
\[
v_j=squash(\sum_i p_{j|i}u_i)=squash(\sum_i\frac{e^{u_i^T v_j}}{Z_i}u_i)
\]
就要变为:
\[
v_j=squash(\sum_i\frac{e^{\hat{u_{j|i}}^Tv_j}}{Z_i}\hat{u_{j|i}}),\ 其中\hat{u_{j|i}}=W_{ji}u_i
\]
这里的\(W_{ji}\)是待训练的矩阵,这里的乘法是矩阵乘法,矩阵乘向量,因此,Capsule Network变成了:完整的动态路由算法(Dynamic Routing Between Capsules. NIPS 2017中的动态路由):
\[
\begin{aligned}
&动态路由算法version2\\
\\
&初始化b_{ij}=0 \\
&迭代r次:\\
&\qquad c_i \gets softmax(b_i);\\
&\qquad s_j\gets\sum_ic_{ij}\hat{u_{j|i}};\\
&\qquad v_j\gets squash(s_j);\\
&\qquad b_{ij}\gets b_{ij}+u_i^Tv_j
\end{aligned}
\]
就是\(s_j\gets\sum_ic_{ij}u_i\)变为了\(s_j\gets\sum_ic_{ij}\hat{u_{j|i}}\),新出来的\(\hat{u_{j|i}}\)由\(\hat{u_{j|i}}=W_{ji}u_i\)求得。这样的Capsule层相当于普通神经网络中的全连接层。
进一步的,我们希望上一层的胶囊乘的“观察角度矩阵”\(W\)能够对上一层所有胶囊共享,就是变成这样:
这就是权值共享版的Capsule Network,所谓共享版,是指对于上一层传来的胶囊\(u_i\)使用的变换矩阵是公用的,即\(W_{ji}\equiv W_j\)。这样计算上面的\(\hat{u_{j|i}}\)就变成了\(\hat{u_{j|i}}=W_{j}u_i\)。
可以看到,Capsule Network由于需要\(W\)做仿射变换,而\(W\)是通过反向传播获得的,因此Capsule Network还是存在反向传播的。
总结
Capsule Network将底层神经元由标量表示变为向量表示,这个向量表示就是“胶囊”。基于此,部分人认为“张量网络”更为通俗易懂。
Capsule Network与传统神经网络的对比:
- Capsule Network的输入输出都是向量了,而非传统网络的标量。
- 上一层传入后,Capsule Network需要做一下仿射变换(Affine Transformation),提供不同的观察角度,而传统神经网络并没有这回事。
- Capsule Network的非线性激活使用的是squash函数,而传统的神经网络是ReLU, tanh, sigmoid等。
原文中的动态路由伪代码:
对应的简图:
实验上,Dynamic Routing Between Capsules. NIPS 2017 验证了利用capsule作为神经元表示能个获得特征更为丰富的语义,比如能够捕获到笔触粗细,数字旋转等信息。Capsule Network在该文4.1中显示能够去噪,而且表明Capsule Network能给出误判的原因。Capsule Network还能有效地对重叠数字分割。
实现
以广泛传播的CapsNet-Tensorflow,使用MNIST数据集,手写数字识别为例。整个网络分为两个卷积层(包括普通的卷积层Conv1和Capsule版的卷积层PrimaryCaps)和一个全连接层(Capsule版的全连接层DigitCaps)
Conv1 layer
Input size kernel size conv stride Channel padding size activation pooling 28x28x1 9x9 1x1 256 [0,0,0,0] ReLU No \[[None,28,28,1] -> [None,20,20,256]\]
参数数量:9x9x256+256=20992
备注:
\[
输出神经元个数=(输入神经元个数-卷积核大小+2*补零个数)/步长+1\\
20=(28-9+2*0)/1+1
\]PrimaryCaps layer
Input size | kernel size | conv stride | Channels | non-linearity func | routing |
---|---|---|---|---|---|
20x20x256 | 9x9 | 2x2 | 32 | squash | No |
\[
[None,20,20,256]\rightarrow [None,6,6,32](8个卷积层并行)\rightarrow \left\{\begin{matrix}
[None,6,6,1,32]\\
[None,6,6,1,32]\\
...\\
[None,6,6,1,32]
\end{matrix}\right.\rightarrow [None,6,6,8,32]
\]
参数数量:9x9x256x32x8+8x32=5,308,672
相当于8个卷积层并行卷积,每次从各个卷积层拿出一个通道拼合出来,这就能得到了8维的向量,也就是标量变胶囊了。[None,6,6,8,32]的axis=0是batch_size;axis=1和axis=2是feature map的大小;axis=3是胶囊的维度,传统的神经网络这一维是没有的,或者可以认为是1;axis=4是通道数。代码实现:
DigitCaps layer
相当于全连接层,上一层6x6x32个capsule进,10个capsule出(表示0~9数字的概率)
输入:上一层PrimaryCaps输出的6x6x32个capsule,每个capsule维度为[8,1]
输出:10个capsule,维度为[16,1]。输出既然是向量而非传统的一个个标量,这里使用的是模长表示0~9数字的概率。为什么使用模长,回忆上文中求\(s_j\)(没有使用squash激活的\(v_j\))时,\(s_j\leftarrow \sum_i c_{ij}\hat{u_{j|i}}\),这里\(c_{ij}\)是softmax得到的概率,表示底层capsule在高层capsule中的重要程度,到了最后一层,就可以理解为哪个capsule是概率最大的输出。所有的capsule都是经过了spuash将模规范化到0~1之间的,只有\(c_{ij}\)越大,向量模才能越大。这里就是有人所说的神经元“竞争激活”的概念,\(c_{ij}\)越大,神经元就被激活。
\[
[None,1152,8,1]\rightarrow[None,10,16,1]
\]
参数数量:1152x10个\(W_{ij}\): 1152x10x(8x16)=1,474,560
1152x10个\(c_{ij}/b_{ij}\): 1152x10x1=11,520
改进的方向
- squash 函数,存在的必要存疑,以及对该函数本身的改进
- 动态路由,现在实际上是给了一个框,这个“路由”实际上是一个聚类,现在已经有了用EM做动态路由了,这是可以试试的坑
- 现有动态路由中有个\(b_{ij}\gets b_{ij}+u_i^Tv_j\),有个哥们推导了一番,说这东西应该改为\(b_{ij}\gets u_i^Tv_j\),这样使得迭代轮数不是超参数,而是变成迭代轮数越大越好
- 神经元原先是一个标量,现在用向量表示,可不可以用矩阵,n维张量表示?
Connect
Email: cncmn@sina.cn
GitHub: cnlinxi@github
后记
花了一周多理解Capsule Network,并且动手照着别人的Capsule Network代码理解、默写出来。今天写完算是完成了一件事情。本文大多是拾人牙慧,但是也夹带了自己的一些私货,感谢这些博主和开源代码贡献者。
Capsule Network的更多相关文章
- 深度学习课程笔记(十一)初探 Capsule Network
深度学习课程笔记(十一)初探 Capsule Network 2018-02-01 15:58:52 一.先列出几个不错的 reference: 1. https://medium.com/ai% ...
- capsule network——CNN仅仅考虑了“有没有”的问题,没有考虑feature map的结构关系。这个结构关系包括位置,角度等。Capsule layer的输出也跟feature map的max-pooling输出不同,capsule layer的输出是一个向量,这个向量包含了位置,大小,角度等信息,这是feature map仅能输出一个值所不具备的;训练比较慢
capsule network--<Dynamic Routing Between Capsules> from:https://zhuanlan.zhihu.com/p/31491520 ...
- 语义分割:使用关系图辅助图像分割-Capsule Network、IceNet
文章:欲取代CNN的Capsule Network究竟是什么来头?它能为AI界带来革命性转折么? 文章:用于分类.检测和分割的移动网络 MobileNetV2 网络 文章:后RCNN时代的物体检测及分 ...
- 深度学习课程笔记(十二) Matrix Capsule
深度学习课程笔记(十二) Matrix Capsule with EM Routing 2018-02-02 21:21:09 Paper: https://openreview.net/pdf ...
- 【论文笔记】Dynamic Routing Between Capsules
Dynamic Routing Between Capsules 2018-09-16 20:18:30 Paper:https://arxiv.org/pdf/1710.09829.pdf%20 P ...
- 论文笔记:Variational Capsules for Image Analysis and Synthesis
Variational Capsules for Image Analysis and Synthesis 2018-07-16 16:54:36 Paper: https://arxiv.org/ ...
- 小样本学习(few-shot learning)在文本分类中的应用
1,概述 目前有效的文本分类方法都是建立在具有大量的标签数据下的有监督学习,例如常见的textcnn,textrnn等,但是在很多场景下的文本分类是无法提供这么多训练数据的,比如对话场景下的意图识别, ...
- 用CapsNets做电能质量扰动分类(2019-08-05)
当下最热神经网络为CNN,2017年10月,深度学习之父Hinton发表<胶囊间的动态路由>(Capsule Networks),最近谷歌正式开源了Hinton胶囊理论代码,提出的胶囊神经 ...
- 深度学习之父低调开源 CapsNet,欲取代 CNN
“卷积神经网络(CNN)的时代已经过去了!” ——Geoffrey Hinton 酝酿许久,深度学习之父Geoffrey Hinton在10月份发表了备受瞩目的Capsule Networks(Cap ...
随机推荐
- 【9309】求Y=X1/3
Time Limit: 1 second Memory Limit: 2 MB 问题描述 求Y=X1/3次方的值.X由键盘输入(x不等于0,在整型范围内).利用下列迭代公式计算: yn + 1=2/3 ...
- C++ 类包含关系Demo 笔记
is-a关系 类包含关系 构造 拷贝构造函数 重载福值运营商 析构函数 动态内存分配和释放 new delete操作 static 数据成员 好友功能 重载输入>>输出<<操 ...
- CSS布局--左侧自适应母元素高度
平常项目中经常会遇到有左侧导航菜单的高度不固定,需要与母元素或右侧元素等高的情况,以前就自以为是的使用js来设置,不仅不方便还会出现各种bug,后来就突然想到了一个好方法.有可能这方法已经被其他人用烂 ...
- Android官方教程翻译(6)——添加ActionBar
The action bar allows you to add buttons for the most important action items relating to the app's c ...
- C#中的反射总结
= 导航 顶部 什么是反射 为什么要使用反射 C#反射相关的命名空间 通过反射创建类型的实例 通过反射调用类的方法 查看类中成员 查看类的构造函数 查看类中属性 查看类中字段 反射实现的接口 ...
- WPF动态创建Image的显示问题
原文:WPF动态创建Image的显示问题 最近学习WPF,看到一篇教程讲解如何动态创建Image控件,自己练手时候无论如何也显示不出图片.刚开始以为是图片的路径有问题,可后来将图片的路径设为相对路径或 ...
- 你不从地址栏中增加曝光量所需的数据库ID方法
<p><span style="font-size: 18px;"></span></p> 当你想隐藏数据库id时,你能够使用 Ha ...
- WolframAlpha 的使用
WolframAlpha 1. 求解复杂方程组 a+b=−4ab+c=2ac=1 直接点开网站,在输入框中输入,a+b=-4;ab+c=2;ac=1;(逗号分割开来),
- C# WPF 左侧菜单右侧内容布局效果实现
原文:C# WPF 左侧菜单右侧内容布局效果实现 我们要做的效果是这样的,左侧是可折叠的菜单栏,右侧是内容区域,点击左侧的菜单项右侧内容区域则相应地切换. wpf实现的话,我的办法是用一个tabcon ...
- WPF中取得预定义颜色
原文:WPF中取得预定义颜色 使用XAML代码取得.net预定义颜色:<Page xmlns="http://schemas.microsoft.com/winfx/2006/x ...