Sabour S, Frosst N, Hinton G E, et al. Dynamic Routing Between Capsules[C]. neural information processing systems, 2017: 3856-3866.

虽然11年就提出了capsule的概念, 但是走入人们视线的应该还是这篇文章吧. 虽然现阶段, capsule没有体现出什么优势. 不过, capsule相较于传统的CNN融入了很多先验知识, 更能够拟合人类的视觉系统(我不知), 或许有一天它会大放异彩.

主要内容

直接从这个结构图讲起吧.

  1. Input: 1 x 28 x 28 的图片 经过 9 x 9的卷积核(stride=1, padding=0, out_channels=256)作用;
  2. 256 x 20 x 20的特征图, 经过primarycaps作用(9 x 9 的卷积核(strde=2, padding=0, out_channels=256);
  3. (32 x 8) x 6 x 6的特征图, 理解为32 x 6 x 6 x 8 = 1152 x 8, 即1152个胶囊, 每个胶囊由一个8D的向量表示\(u_{i}\); (这个地方要不要squash, 大部分实现都是要的.)
  4. 接下来digitcaps中有10个caps(对应10个类别), 1152caps和10个caps一一对应, 分别用\(i, j\)表示, 前一层的caps为后一层提供输入, 输入为
\[\hat{u}_{j|i} = W_{ij}u_i,
\]

可见, 应当有1152 x 10个\(W_{ij}\in \mathbb{R}^{16\times 8}\), 其中16是输出胶囊的维度. 最后10个caps的输出为

\[s_j= \sum_{i}c_{ij}\hat{u}_{j|i}, v_j= \frac{\|s\|_j^2}{1 + \|s_j\|^2} \frac{s_j}{\|s_j\|}.
\]

其中\(c_{ij}\)是通过一个路由算法决定的, \(v_j\), 即最后的输入如此定义是出于一种直觉, 即保持原始输出(\(s\))的方向, 同时让\(v\)的长度表示一个概率(这一步称为squash).

首先初始化\(b_{ij}=0\) (这里在程序实现的时候有一个考量, 是每一次都要初始化吗, 我看大部分的实现都是如此的).



上面的Eq.3就是

\[\tag{3}
c_{ij}=\frac{\exp(b_{ij})}{\sum_{k}\exp(b_{ik})}.
\]

另外\(\hat{\mu}_{j|i} \cdot v_j=\hat{\mu}_{j|i}^Tv_j\)是一种cos相似度度量.

损失函数

损失函数采用的是margin loss:

\[\tag{4}
L_k = T_k \max(0, m^+ - \|v_k\|)^2 + \lambda (1 - T_k) \max(0, \|v_k\|-m^-)^2.
\]

\(m^+, m^-\)通常取0.9和0.1, \(\lambda\)通常取0.5.

代码

我的代码, 在sgd下可以训练(但是准确率只有98), 在adam下就死翘翘了, 所以代码肯定是有问题, 但是我实在是找不出来了, 这里有很多实现的汇总.



"""
Sabour S., Frosst N., Hinton G. Dynamic Routing Between Capsules.
Neural Information Processing Systems, pp. 3856-3866, 2017.
https://arxiv.org/pdf/1710.09829.pdf
The implement below refers to https://github.com/adambielski/CapsNet-pytorch.
""" import torch
import torch.nn as nn
import torch.nn.functional as F def squash(s):
temp = s.norm(dim=-1, keepdim=True)
return (temp / (1. + temp ** 2)) * s class PrimaryCaps(nn.Module): def __init__(
self, in_channel, out_entities,
out_dims, kernel_size, stride, padding
):
super(PrimaryCaps, self).__init__()
self.conv = nn.Conv2d(in_channel, out_entities * out_dims,
kernel_size, stride, padding)
self.out_entities = out_entities
self.out_dims = out_dims def forward(self, inputs):
conv_outs = self.conv(inputs).permute(0, 2, 3, 1).contiguous()
outs = conv_outs.view(conv_outs.size(0), -1, self.out_dims)
return squash(outs) class AgreeRouting(nn.Module): def __init__(self, in_caps, out_caps, out_dims, iterations=3):
super(AgreeRouting, self).__init__() self.in_caps = in_caps
self.out_caps = out_caps
self.out_dims = out_dims
self.iterations = iterations @staticmethod
def softmax(inputs, dim=-1):
return F.softmax(inputs, dim=dim) def forward(self, inputs):
# inputs N x in_caps x out_caps x out_dims
b = torch.zeros(inputs.size(0), self.in_caps, self.out_caps).to(inputs.device)
for r in range(self.iterations):
c = self.softmax(b) # N x in_caps x out_caps !!!!!!!!!
s = (c.unsqueeze(-1) * inputs).sum(dim=1) # N x out_caps x out_dims
v = squash(s) # N x out_caps x out_dims
b = b + (v.unsqueeze(dim=1) * inputs).sum(dim=-1)
return v class CapsLayer(nn.Module): def __init__(self, in_caps, in_dims, out_caps, out_dims, routing):
super(CapsLayer, self).__init__()
self.in_caps = in_caps
self.in_dims = in_dims
self.routing = routing
self.weights = nn.Parameter(torch.rand(in_caps, out_caps, in_dims, out_dims))
nn.init.kaiming_uniform_(self.weights) def forward(self, inputs):
# inputs: N x in_caps x in_dims
inputs = inputs.view(inputs.size(0), self.in_caps, 1, 1, self.in_dims)
u_pres = (inputs @ self.weights).squeeze() # N x in_caps x out_caps x out_dims
outs = self.routing(u_pres) # N x out_caps x out_dims return outs class CapsNet(nn.Module): def __init__(self):
super(CapsNet, self).__init__() # N x 1 x 28 x 28
self.conv = nn.Conv2d(1, 256, 9, 1, padding=0) # N x (32 * 8) x 20 x 20
self.primarycaps = PrimaryCaps(256, 32, 8, 9, 2, 0) # N x (6 x 6 x 32) x 8
routing = AgreeRouting(32 * 6 * 6, 10, 8, 3)
self.digitlayer = CapsLayer(32 * 6 * 6, 8, 10, 16, routing) def forward(self, inputs):
conv_outs = F.relu(self.conv(inputs))
pri_outs = self.primarycaps(conv_outs)
outs = self.digitlayer(pri_outs)
probs = outs.norm(dim=-1)
return probs if __name__ == "__main__": x = torch.randn(4, 1, 28 ,28)
capsnet = CapsNet()
print(capsnet(x))
def margin_loss(logits, labels, m=0.9, leverage=0.5, adverage=True):
# outs: N x num_classes x dim
# labels: N
temp1 = F.relu(m - logits) ** 2
temp2 = F.relu(logits + m - 1) ** 2
T = F.one_hot(labels.long(), logits.size(-1))
loss = (temp1 * T + leverage * temp2 * (1 - T)).sum()
if adverage:
loss = loss / logits.size(0)
# Another implement is using scatter_
# T = torch.zero(logits.size()).long()
# T.scatter_(dim=1, index=labels.view(-1, 1), 1.).cuda() if cuda()
return loss

Dynamic Routing Between Capsules的更多相关文章

  1. Hinton's paper Dynamic Routing Between Capsules 的 Tensorflow , Keras ,Pytorch实现

    Tensorflow 实现 A Tensorflow implementation of CapsNet(Capsules Net) in Hinton's paper Dynamic Routing ...

  2. 【论文笔记】Dynamic Routing Between Capsules

    Dynamic Routing Between Capsules 2018-09-16 20:18:30 Paper:https://arxiv.org/pdf/1710.09829.pdf%20 P ...

  3. Dynamic Routing Based On Redis

    Dynamic Routing Based On Redis Ngnix技术研究系列2-基于Redis实现动态路由   上篇博文我们写了个引子: Ngnix技术研究系列1-通过应用场景看Nginx的反 ...

  4. dynamic routing between captual

    对于人脑 决策树形式 对于CNN 层级与层级间的传递 人在识别物体的时候会进行坐标框架的设置 CNN无法识别,只能通过大量训练 胶囊 :一个神经元集合,有一个活动的向量,来表示物体的各类信息,向量的长 ...

  5. Paper | SkipNet: Learning Dynamic Routing in Convolutional Networks

    目录 1. 概括 2. 相关工作 3. 方法细节 门限模块的结构 训练方法 4. 总结 作者对residual network进行了改进:加入了gating network,基于上一层的激活值,得到一 ...

  6. 总结近期CNN模型的发展(一)---- ResNet [1, 2] Wide ResNet [3] ResNeXt [4] DenseNet [5] DPNet [9] NASNet [10] SENet [11] Capsules [12]

    总结近期CNN模型的发展(一) from:https://zhuanlan.zhihu.com/p/30746099 余俊 计算机视觉及深度学习   1.前言 好久没有更新专栏了,最近因为项目的原因接 ...

  7. 百年老图难倒谷歌AI,兔还是鸭?这是个问题

    上面这张图,画的是鸭子还是兔子? 自从1892年首次出现在一本德国杂志上之后,这张图就一直持续引发争议.有些人只能看到一只兔子,有些人只能看到一只鸭子,有些人两个都能看出来. 心理学家用这张图证明了一 ...

  8. 浅析 Hinton 最近提出的 Capsule 计划

    [原文]    浅析 Hinton 最近提出的 Capsule 计划     关于最新的 Hinton 的论文 Dynamic Routing Between Capsules,参见 https:// ...

  9. Hinton“深度学习之父”和“神经网络先驱”,新论文Capsule将推翻自己积累了30年的学术成果时

    Hinton“深度学习之父”和“神经网络先驱”,新论文Capsule将推翻自己积累了30年的学术成果时 在论文中,Capsule被Hinton大神定义为这样一组神经元:其活动向量所表示的是特定实体类型 ...

随机推荐

  1. org.apache.hadoop.hive.ql.metadata.HiveException: Internal Error: cannot generate all output rows for a Partition解决

    自己在路径访问明细表开发时,写的sql如下 SELECT guid, sessionid, event['url'] as page, `timestamp` as ts, row_number() ...

  2. 修改linux文件权限命令:chmod 转载至 Avril 的随笔

    Linux系统中的每个文件和目录都有访问许可权限,用它来确定谁可以通过何种方式对文件和目录进行访问和操作. 文件或目录的访问权限分为只读,只写和可执行三种.以文件为例,只读权限表示只允许读其内容,而禁 ...

  3. 转 序列化Serializable和Parcelable的区别详解

    什么是序列化,为什么要进行序列化 答:对象要进行传输(如:activity 与activity间 ,网络间 进程间等等).存储到本地就必须进行序列化 . 这种可传输的状态就是序列化. 怎么序列化??两 ...

  4. Hadoop生态圈学习-1(理论基础)

    一.大数据技术产生的背景 1. 计算机和信息技术(尤其是移动互联网)的迅猛发展和普及,行业应用系统的规模迅速扩大(用户数量和应用场景,比如facebook.淘宝.微信.银联.12306等),行业应用所 ...

  5. eclipse.ini顺序

    -vmargs需放在-Dfile.encoding=UTF-8之前,否则会出现乱码 举例: -startup plugins/org.eclipse.equinox.launcher_1.3.0.v2 ...

  6. Java 多线程的一次整理

    一天没有出过家门,实属无聊,没事瞎写写 1. 基本概念 1.1 多进程和多线程的概念 程序是由指令和数据组成,指令要运行,数据要加载,指令被 CPU 加载运行,数据被加载到内存,指令运行时可由 CPU ...

  7. SQL->Python->PySpark计算KS,AUC及PSI

    KS,AUC 和 PSI 是风控算法中最常计算的几个指标,本文记录了多种工具计算这些指标的方法. 生成本文的测试数据: import pandas as pd import numpy as np i ...

  8. 自定义 UITableViewCell 的 accessory 样式

    对于 UITableViewCell 而言,其 accessoryType属性有4种取值: UITableViewCellAccessoryNone, UITableViewCellAccessory ...

  9. 初探Windows用户态调试机制

    我们在感叹Onlydbg强大与便利的同时,是否考虑过它实现的原理呢? 作为一个技术人员知其然必知其所以然,这才是我们追求的本心. 最近在学习张银奎老师的<软件调试>,获益良多.熟悉Wind ...

  10. Kubernetes 集群无损升级实践 转至元数据结尾

    一.背景 活跃的社区和广大的用户群,使 Kubernetes 仍然保持3个月一个版本的高频发布节奏.高频的版本发布带来了更多的新功能落地和 bug 及时修复,但是线上环境业务长期运行,任何变更出错都可 ...