データサイエンティスト(仮)

元素粒子論博士。今はデータサイエンティスト(仮)。

Dynamic Routing Between Capsulesを読む

前提

この記事はDeepLearning論文紹介 Advent Calendar 2017 - Adventarの12月10日の記事です。Advent Calendarで記事を書くのは初めてですが、頑張ります。理解が足りなくて非常にわかりづらい記事になっていると思いますので、今後もちょくちょく修正が入ると思います。

読んだ論文

Hintonさんが著者に入っている、以下の論文です。
[1710.09829] Dynamic Routing Between Capsules
Deep Learning界の重鎮のアイデアということもあり、興味を持ったため、こちらの論文を読むことにしました。

概要

正直、Introductionは門外漢すぎてあまり腹落ちしていないのですが、より人間の脳に近しいと思われるネットワーク構造を考え、CNNよりも人間の認知に近いような分類器を作ろうという試みのようです。そのための一歩として、内積スカラー値の塊であった層をベクトルの塊であるcapsuleというものに置き換え、capsuleを用いたネットワークであるCapsNetを提唱している論文になります。

現在、物体認識ではCNNを用いることがスタンダードに見えますが、以下の記事のHintonの講義にあるように、欠点もあるようです。
Dynamic Routing Between Capsules | moskomule log
大きくは

  • poolingで微小変換に対する不変性を獲得する代わりに、顔→目, 鼻といった位置情報、階層構造が失われる
  • 回転などの差異を識別するために別途学習データが必要

といったものです。本論文で提唱している、capsuleを組み込んだCapsNetでは、位置や姿勢などの情報をcapsuleというベクトルの形で保持し,capsule同士が階層的な「構文木」をなすように結合の仕方(routing)を学習することで、CNNの欠点を解消できる可能性があります。

以下、CapsNetの構造、および検証結果について紹介していきます。

Capsuleの計算の入出力

capsuleのimplementationの方法にはいくつか方法があるようですが、論文ではCapsNetのアイデアのキモになる部分、capsuleの入出力とcapsule間の関係を決める方法にフォーカスして紹介しています。

squashing:capsuleの入出力

capsuleでは、capsuleの出力ベクトルの長さが対応するものの存在確率を表現するようにしています。通常のニューラルネットワークでは、活性化関数でそういった効果を表現しますが、capsuleでは以下のような「squashing」という変換でベクトルの長さを|0, 1)にして表現しているようです。
$$
\vec{v}_l = \frac{ \| \vec{s}_j \|^2}{1 + \| \vec{s}_j \|^2} \frac{\vec{s}_j}{\| \vec{s}_j \|}
$$
ここで、\vec{v}_j capsule jの出力ベクトルで、\vec{s}_j はそのcapsuleに対する入力です。

Routing:capsule間の関係性

\vec{s}_j は、前層のcapsuleとの結びつきによって決まります。前層のi番目*1capsuleの出力を\vec{u}_i, 次の層のj番目のcapsuleとの「重み行列」をW_{ij}とします*2。これらを掛け合わせたものを「prediction vector\hat{\vec{u}}_{j|i}とし、各iに対して重みつけ和をとったものが\vec{s}_j となります。
$$
\vec{s}_j = \sum _i c_{ij} \hat{\vec{u}}_{j|i}
$$
係数c_{ij}は、c_{ij}は、以下のようなsoftmaxの形をしています。
$$
c_{ij} = \frac{\text{exp}(b_{ij})}{\sum_k \text{exp}(b_{ik})}
$$
ロジットb_{ik}は以下のroutingアルゴリズムによって動的に更新されます。

f:id:tekenuko:20171210152049p:plain

「Agreement」\hat{\vec{u}}_{j|i} \cdot \vec{s}_j capsule間の類似度的な量になっていると考えられます。この量を用いてロジットを更新していくため、結びつきが強そうなcapsule間の係数c_{ij}がどんどん1に、そうでない係数は0に近づいていくような動きをするのでしょう。

ここの解釈に関して、以下のブログでこのような例えがありました。
f:id:tekenuko:20171210160729p:plain
Dynamic Routing Between Capsules | moskomule log

CapsNetのアーキテクチャ

CapsNetのアーキテクチャーは以下になります。
f:id:tekenuko:20171208113058p:plain:w800
中間層は全3層で、2層が畳み込み層、1層が全結合層です。2層目と3層目がCapsuleになっています。

  • 1層目:畳み込み層
    • channel(フィルタの数):256
    • kernel(フィルタのサイズ):9×9
    • stride(畳み込みの際にスライドさせるピクセルの間隔):1
    • 活性化関数:ReLU
    • 出力:20×20×256
  • 2層目:畳み込みCapsule(PrimaryCapsules)
    • Capsuleの数:32
    • channel(Capsuleのベクトルの成分数):8
    • kernel:9×9
    • stride:2
    • squashing
  • 3層目:全結合Capsule(DigitCaps)
    • Capsuleの数:10(クラス数10に対応)
    • Capsuleのベクトルの成分数:16

Loss関数

Margin Lossを採用。各クラスに対応するcapsuleに対し
$$
L_k = T_k \ \text{max}\left( 0, m^+ \|\vec{v}_k \| \right)^2 + \lambda \left( 1 - T_k \right) \ \text{max}\left( 0, \|\vec{v}_k \| - m^- \right)^2
$$
としています。T_k はクラスkが存在する場合は1をとり、m^+ = 0.9, \ m^- = 0.1, \lambda = 0.5ととっています。全体のLossはすべてのcapsuleのLossの和をとったものを使用します。

routingの実装について

Tensorflowで実装し、OptimizerはAdamを使用しているとのことです。パラメータはTensorflowのデフォルトを使用、学習率は指数的に落ちていくようになっているようです。

正則化による再構成

本論文では、Margin Lossに加えて、以下の構造を使った入力画像と再構成した出力による二乗誤差を新たに追加しているようです。
f:id:tekenuko:20171210162726p:plain:w500
最終層の次元が784なのは、MNISTの入力の28×28 = 784に対応しています。加える際には、0.0005を掛けてから追加しているようです。再構成した画像が入力に近くない場合は、大きな二乗誤差が出ることになるため、ネットワークが入力画像に近い画像を出せるような重みになることを期待し、またそのような重みに学習が進むことをエンカレッジしているような考えなんだと思います。

再構成できているかの図が一つ紹介されていますが、5と3が間違えやすいということはあれど、概ねよく再現されているのでしょう。
f:id:tekenuko:20171210172856p:plain:w500

実験結果

CapsNetの性能に関しては、主にMNISTとMultiMNIST(MNISTの数字を重ねたもの)を用いて伝統的なCNNとの比較を行っています。

結果のまとめは以下となります。
f:id:tekenuko:20171210164000p:plain:w500

Baselineは、畳み込み層の数は3つで、channel数がそれぞれ256, 256, 128, kernelとstrideは5×5と1に統一しています。畳み込み層のあとは328次元、192次元の全結合層で、最後にdropoutを利用した出力層、という構造になっており、Loss関数はクロスエントロピーを使用しています。OptimizerはAdamを使用しているようですが、細かいパラメータの話は記載がありません。routingの実装の際と同様、デフォルトのパラメータを使用しているのだと思います。

MNIST

CapsNetはデータ拡張やデータの回転、スケーリング、アンサンブルを用いずにテストエラー0.25%を達成しています。先行研究(アンサンブルなどを使用)の0.21%と近しい精度となっており、routingが精度向上に寄与しているのではないかと考えられます。また、CapsNetは従来のCNNと比較してパラメータ数が少なく(Baselineは35.4M個、CapsNetは再構成を除くと6.8M、含めても8.2M)、効率的な学習ができていると見ることもできそうです。

また、学習で獲得したDigitCapに関して、16次元のベクトルの要素を少しずつ動かした結果が以下になります。
f:id:tekenuko:20171210173131p:plain:w500
太さやスケールの変換を性質として持つような成分が獲得されているような振る舞いになっています。これはとても面白い性質だと思います。

Affine変換に対するロバスト

また、CapsNetが画像の変換に対してロバストかを検証するために、MNISTをアフィン変換(伸縮・回転・平行移動)をしたデータセット(affNIST)に関してテストを実施しています。以下は、affNISTの画像の例です。
f:id:tekenuko:20171210170936p:plain:w300
あらかじめCapsNetとCNN(畳み込み層+プーリング層とDropout層)でMNISTによってそれぞれ訓練データの精度を99.2~3%となるまで学習します。これらをaffNISTでテストした結果、それぞれ精度が79%, 66%となっており、CapNetのほうがよい性能を出しています。よって、従来のCNNよりもCapsNetが変換に対してロバストであると期待されます。

MultiMNIST

本論文では、MNISTの画像を重ねたもの(MultiMNIST)に関しても検証を行っています。以下は重ねたものに関して分離できているかを表す図です。
f:id:tekenuko:20171210171923p:plain:w500
R(,) が再構築をする際に使ったラベル、L(,) が正解のラベルを表しています。 白黒の画像はMultiMNISTの画像で、数字が2つ重なっています、カラフルな画像は下は再構築した画像で、R(,) のラベルを1つずつ使って再構築した画像を色違いで重ねています。重なっている場合でも概ねうまくラベル付けできるようです。

他のデータセット

CIFAR 10やsmallNORB、SVHMといったデータセットでも検証を行っています。ただし、例えばCIFAR 10では7モデルのアンサンブルによってテストエラー10.6%を達成しているなど、アンサンブルを行っています。そういった操作を行わない場合の性能が気になります。

Discussionと所感

CapsNetは、2000年代はじめの音声認識によるRNNと似たような研究段階にあるとの主張をしています。結構アナロジーがあるようです。音声認識では隠れマルコフがかつては有用な方法だったが、スケールすると非効率な点があり、再帰型のネットワークの研究が登場し、とって変わられたという歴史があるようですが*3、物体認識に関するCNNとcapsuleの関係も似たものである可能性があります。CNNは回転や平行移動はデータを水増しして学習する必要があるので、リッチな認識性能を獲得するためにはどんどん学習データを増やさなくてはいけません。一方で、capsuleは変換や重なりといった構造を少ないコストで獲得することが期待されるもので、研究が進めば物体認識でCNNにとって変わる存在になるかもしれません。正直、capsuleそのものや論文に関してきちんと理解ができていない部分があったり疑問点もありますが、将来非常に有用なものになる可能性を感じました。今後の研究の進展に期待したいと思います。

実装に関しては、早速何人かによって実装例が出ているようです。自分でも使ってみて、より理解を深めていきたいと思います。
github.com
github.com
github.com

*1:この言い方が適切かは検討が必要

*2:この重み行列に関しては、どう学習するかの記載がないのですが、おそらく誤差逆伝搬で学習するのだと思います。

*3:適当なこと言っているかもしれません。