Dynamic routing between capsules

1. Capsule介紹

Sabour, Sara, Nicholas Frosst, and Geoffrey E. Hinton. "Dynamic routing between capsules." Advances in neural information processing systems. 2017.

Capsule特色是“vector in vector out”,取代了以往的“scaler in scaler out”,也就是神經(jīng)元的輸入輸出都變成了向量,從而算是對神經(jīng)網(wǎng)絡(luò)理論的一次革命。

然而在目前的深度學(xué)習(xí)中,從來不缺乏“vector in vector out”的案例,因此顯然這不能算是Capsule的革命。比如在NLP中,一個詞向量序列的輸入模型,這個詞向量序列再經(jīng)過RNN/CNN/Attention的編碼,輸出一個新序列,不也是“vector in vector out”嗎?

Capsule的革命在于:它提出了一種新的“vector in vector out”的傳遞方案,并且這種方案在很大程度上是可解釋的。

深度學(xué)習(xí)(神經(jīng)網(wǎng)絡(luò))為什么有效:神經(jīng)網(wǎng)絡(luò)通過層層疊加完成了對輸入的層層抽象,這個過程某種程度上模擬了人的層次分類做法,從而完成對最終目標(biāo)的輸出,并且具有比較好的泛化能力。的確,神經(jīng)網(wǎng)絡(luò)應(yīng)該是這樣做的,然而它并不能告訴我們它確確實(shí)實(shí)是這樣做的,這就是神經(jīng)網(wǎng)絡(luò)的難解釋性,也就是很多人會將深度學(xué)習(xí)視為黑箱的原因之一。

下面介紹Capsule是怎么突破這一點(diǎn)的。

2. CapsNet模型

CapsNet: 兩個卷積層(Conv 1, PrimaryCaps),一個全連接層(DigitCaps)

在這里插入圖片描述

2.1 Conv1層

常規(guī)的卷積層, 起像素級局部特征檢測作用

在這里插入圖片描述

2.2 PrimaryCaps層

生成最低級卷積8D膠囊層(無路由)

膠囊:其實(shí),只要把一個向量當(dāng)作一個整體來看,它就是一個“膠囊”。可以這樣理解:神經(jīng)元就是標(biāo)量,膠囊就是向量。Hinton的理解是:每一個膠囊表示一個屬性,而膠囊的向量則表示這個屬性的“標(biāo)架”。也就是說,我們以前只是用一個標(biāo)量表示有沒有這個特征(比如有沒有羽毛),現(xiàn)在我們用一個向量來表示,不僅僅表示有沒有,還表示“有什么樣的”(比如有什么顏色、什么紋理的羽毛),如果這樣理解,就是說在對單個特征的表達(dá)上更豐富了。

簡單的講,PrimaryCaps層要輸出一些8D的向量,每個向量代表一些比較低級的特征,向量的各個位置的值代表該特征的屬性

PrimaryCaps層: 計算過程具有多種理解方式,其中之一為,8個并行的常規(guī)卷積層的疊堆

PrimaryCaps層的第一種理解方式

8個并行的常規(guī)卷積層:


在這里插入圖片描述

卷積操作2參數(shù):


在這里插入圖片描述

對Conv1層的輸出進(jìn)行8次卷積操作2所示的卷積操作:
在這里插入圖片描述

然后對8個并行常規(guī)卷積層疊堆(對每個卷積層的各個通道在第四個維度上進(jìn)行合并):

8個[6,6,1,32]卷積層合并示意圖如下:


在這里插入圖片描述

得到疊堆后的結(jié)果:[None,6,6,8,32]
然后展開為[None,6x6x32,8,1]=[None,1152,8,1],這樣我們就得到了1152個初始膠囊,每個膠囊是一個緯度為[8,1]的向量,并代表某一特征

PrimaryCaps層的第二種理解方式

  • 32個通道之間的卷積核是獨(dú)立的(9x9大小)
  • 8個并行卷積層之間的參數(shù)也是獨(dú)立的

Rightarrow 即共有8x32個大小為9x9的相互獨(dú)立的卷積核,可看作8x32個通道的常規(guī)卷積和
則可以用下面的操作得到和第一種理解方式相同的結(jié)果

在這里插入圖片描述

輸出:

注意:雖然計算方式上與常規(guī)卷積層無差異,但意義上卻已經(jīng)大不相同!將達(dá)到8x1capsule的特征封裝的效果

PrimaryCaps輸出輸出1152個8D的膠囊后,使用了一個Squash函數(shù)做非線性變換,那么,為什么要設(shè)計這個函數(shù)呢?這個函數(shù)的原理是啥

2.3 Squash函數(shù)

為什么要設(shè)計squash函數(shù):

因為論文希望Capsule能有一個性質(zhì):膠囊的模長能夠代表這個特征的概率,即特征的“顯著程度”, 模長越大,這個特征越顯著,而我們又希望有一個有界的指標(biāo)來對這個“顯著程度”進(jìn)行衡量,所以就只能對這個模長進(jìn)行壓縮了

squash函數(shù)的原理:

squash(x) = \frac{||x||^2}{1+||x||^2} \frac{x}{||x||}

  • \frac{x}{||x||}: 將x的模長變?yōu)?
  • \frac{||x||^2}{1+||x||^2}: 起縮放x的模長的作用,x模長越大,\frac{||x||^2}{1+||x||^2}越趨近于1,||x||=0時,\frac{||x||^2}{1+||x||^2}=0

y=squash(x)的效果為:x的模長越大,y的模長越趨近于1

PrimaryCaps輸出的1152個8D的膠囊經(jīng)過squash函數(shù)后非線性變換后,都具有了膠囊的模長能夠代表這個特征的概率的特性,這些新的膠囊接著作為DigitCaps層的輸入。

2.4 DigitCaps層

由于該層解釋起來比較復(fù)雜,所以先從簡單例子開始,慢慢推出該層的流程及原理。

capsule示意

capsule示意圖:

在這里插入圖片描述

如上圖所示,底層的膠囊和高層的膠囊構(gòu)成一些連接關(guān)系那么,這些膠囊要怎么運(yùn)算,才能體現(xiàn)出“層層抽象”、“層層分類”的特性呢?讓我們先看其中一部分連接:

在這里插入圖片描述

u,v都是膠囊,圖上只展示了的連接。這也就是說,目前已經(jīng)有了這個特征(假設(shè)是羽毛),那么我想知道它屬于上層特征(假設(shè)分別代表了雞、鴨、魚、狗)中的哪一個。分類問題我們顯然已經(jīng)是很熟悉了,不就是內(nèi)積后softmax嗎?于是單靠這個特征,我們推導(dǎo)出它是屬于雞、鴨、魚、狗的概率分別是:

(p_{1|1},p_{2|1},p_{3|1},p_{4|1})=\frac{1}{Z_1} (e^{<u_1,v_1>},e^{<u_1,v_2>},e^{<u_1,v_3>},e^{<u_1,v_4>})

我們期望p_{1|1},p_{2|1}會明顯大于p_{3|1},p_{4|1}(雞鴨有羽毛,魚狗沒羽毛)不過,單靠這個特征還不夠,我們還需要綜合各個特征,于是可以把上述操作對各個u_i都做一遍,繼而得到
(p_{1|2},p_{2|2},p_{3|2},p_{4|2}), (p_{1|3},p_{2|3},p_{3|3},p_{4|3}), ...

問題是,現(xiàn)在得到這么多預(yù)測結(jié)果,究竟要選擇哪個呢?而且又不是真的要做分類,我們要的是融合這些特征,構(gòu)成更高級的特征。

于是Hinton認(rèn)為,既然u_i這個特征得到的概率分布是(p_{1|i},p_{2|i},p_{3|i},p_{4|i})那么我把這個特征切成四份,分別為(p_{1|i}u_i,p_{2|i}u_i,p_{3|i}u_i,p_{4|i}u_i), 然后把這幾個特征分別傳給v_1,v_2,v_3,v_4,最后v_1,v_2,v_3,v_4其實(shí)就是底層傳入的特征的累加

v_j=squash(p_{j|i} u_i )=squash(\sum_{i} \frac{e^{<u_i,v_j>}}{Z_i} u_i)

從上往下看,那么Capsule就是每個底層特征分別做分類,然后將分類結(jié)果整合。這時v_j應(yīng)該盡量與所有u_i都比較靠近,靠近的度量是內(nèi)積。因此,從下往上看的話,可以認(rèn)為v_j實(shí)際上就是各個u_i的某個聚類中心,而Capsule的核心思想就是輸出是輸入的某種聚類結(jié)果。

動態(tài)路由:

注意到式子v_j=squash(\sum_{i} \frac{e^{<u_i,v_j>}}{Z_i} u_i),為了求v_j需要求softmax,可是為了求softmax又需要知道v_j,這不是個雞生蛋、蛋生雞的問題了嗎?而“動態(tài)路由”正是為了解決這一問題而提出的,它能夠根據(jù)自身的特性來更新(部分)參數(shù),從而初步達(dá)到了Hinton的放棄梯度下降的目標(biāo)

下面通過幾個例子來解釋動態(tài)路由的過程:

例1:

讓我們先回到普通的神經(jīng)網(wǎng)絡(luò),大家知道,激活函數(shù)在神經(jīng)網(wǎng)絡(luò)中的地位是舉足輕重的。當(dāng)然,激活函數(shù)本身很簡單,比如一個tanh激活的全連接層。

可是,如果想用x=y+cos?y的反函數(shù)來激活呢?也就是說,得解出y=f(x),然后再用它來做激活函數(shù)。
然而x=y+cos?y的反函數(shù)是一個超越函數(shù),也就是不可能用初等函數(shù)有限地表示出來。
但我們可以通過迭代法求出y:
y_{n+1} = x - cos y_n

選擇y_0=x,代入上式迭代幾次,基本上就可以得到比較準(zhǔn)確的y了。假如迭代3次,那就是
y=x-cos?(x-cos?(x-cos?x))
可以發(fā)現(xiàn)這和動態(tài)路由的過程有點(diǎn)像

例2:

再來看一個例子,這個例子可能在NLP中有很多對應(yīng)的情景,但圖像領(lǐng)域其實(shí)也不少。考慮一個向量序列(x_1,x_2,…,x_n),我現(xiàn)在要想辦法將這n個向量整合成一個向量x(encoder),然后用這個向量來做分類:
x= \sum_{i=1}^n \lambda _i x_i
這里的λ_i相當(dāng)于衡量了x與x_i的相似度。那么,在x出現(xiàn)之前,憑什么能夠確定這個相似度呢?
解決這個問題的一個方案也是迭代。首先我們也可以定義一個基于softmax的相似度指標(biāo),然后讓

x= \sum_{i=1}^n \frac{e^{<x,x_i>}}{Z} x_i

一開始,我們一無所知,所以只好取x為各個x_i的均值,然后代入右邊就可以算出一個x,再把它代入右邊,反復(fù)迭代就行,一般迭代有限次就可以收斂,于是就可以將這個迭代過程嵌入到神經(jīng)網(wǎng)絡(luò)中了。

如果說例1跟動態(tài)路由只是神似,那么例2已經(jīng)跟動態(tài)路由是神似+形似了。

通過例1,例2,已經(jīng)可以很清晰的開始解釋動態(tài)路由過程了
為了得到各個v_j,一開始先讓它們?nèi)嫉扔趗_i的均值,然后反復(fù)迭代就好。說白了,輸出是輸入的聚類結(jié)果,而聚類通常都需要迭代算法,這個迭代算法就稱為“動態(tài)路由”。

到此,就可以寫出論文里的動態(tài)路由的算法了:


動態(tài)路由算法
初始化b_{ij}=0
迭代r次:
????c_i \leftarrow softmax(b_i)
????s_j \leftarrow \sum_i c_{ij} u_i
????v_j \leftarrow squash(s_j)
????b_{ij} \leftarrow b_{ij} + <u_i,v_j>
返回v_j


這里的c_{ij}就是前文的p_{j|i}前面已經(jīng)說了,v_j是作為輸入u_i的某種聚類中心出現(xiàn)的,而從不同角度看輸入,得到的聚類結(jié)果顯然是不一樣的。那么為了實(shí)現(xiàn)“多角度看特征”,于是可以在每個膠囊傳入下一個膠囊之前,都要先乘上一個矩陣做變換,所以式v_j=squash(\sum_{i} \frac{e^{<u_i,v_j>}}{Z_i} u_i)實(shí)際上應(yīng)該要變?yōu)?/p>

v_j=squash(\sum_{i} \frac{e^{<u_i,v_j>}}{Z_i} \hat{u} _{j|I})

\hat{u}_{j|i} = W_{ji} u_i

這里的W_{ji}是待訓(xùn)練的矩陣,這里的乘法是矩陣乘法,也就是矩陣乘以向量。所以,Capsule變成了下圖

在這里插入圖片描述

這時候就可以得到完整動態(tài)路由了:


動態(tài)路由算法
初始化b_{ij}=0
迭代r次:
????c_i \leftarrow softmax(b_i)
????s_j \leftarrow \sum_i c_{ij} \hat{u}_{j|I}
????v_j \leftarrow squash(s_j)
????b_{ij} \leftarrow b_{ij} + <u_i,v_j>
返回v_j


這樣的Capsule層,顯然相當(dāng)于普通神經(jīng)網(wǎng)絡(luò)中的全連接層。

DigitCaps層流程總結(jié)

  1. 將PrimaryCaps輸入的1152個8D的膠囊從乘W_{ji},以達(dá)到不同角度看輸入的目的,得到[None,10,1152,16,1]
  2. 對每個1152里面的16D的膠囊,通過動態(tài)路由算法聚類出一個v_j
  3. 返回[None,10,16],即輸出10個膠囊,分別對應(yīng)數(shù)字0~9,膠囊的模長代表是該數(shù)字的概率,每個膠囊內(nèi)部的值代表了該數(shù)字的某一屬性

2.5 重構(gòu)層

重構(gòu)層就比較簡單了,但是也有一些細(xì)節(jié)需要說明一下


在這里插入圖片描述

網(wǎng)絡(luò)很簡單,就是三個全連接層,其中有個masked操作,具體原理如下:
因為DigitCaps輸出[None,10,16],即每個樣本輸出10個16D的膠囊,膠囊的模長代表圖片是這個類別的概率,而每個16D的膠囊里面各個位置的值則代表了這個數(shù)字的一系列屬性,重構(gòu)是該膠囊已經(jīng)包含了大部分的信息,假設(shè)要重構(gòu)的是數(shù)字5,那么就把DigitCaps該位置的mask設(shè)置為1,其他位置為0,那么實(shí)際重構(gòu)事,就只有這個膠囊的信息參與了運(yùn)算。

2.6 損失函數(shù)Margin loss + recon loss

Margin loss函數(shù):

L_c = T_c max?(0,m^+ - ||v_c ||)^2+ \lambda (1-T_c )max?(0,||v_c||-m^- )^2

  • c:類別
  • T_c:指示函數(shù)(分類c存在為1,否則為0)
  • m^-:||v_c ||上邊界,避免假陰性,遺漏實(shí)際預(yù)測到存在的分類的情況
  • m^+:||v_c |)|下邊界,避免假陽性
  • margin loss: \sum_c L_c

重構(gòu)誤差:

  • 作用: 正則化
  • 重構(gòu)網(wǎng)絡(luò): MLP
  • 重構(gòu)誤差計算方式MSE

3. 運(yùn)行結(jié)果

3.1測試集分類結(jié)果

論文分類結(jié)果:

在這里插入圖片描述

復(fù)現(xiàn)

(routing:3,Reconstruction:yes)結(jié)果在測試集的準(zhǔn)確率平均可達(dá)99.24%以上,基本復(fù)現(xiàn)成功

3.2 單數(shù)字重構(gòu)效果

論文單數(shù)字重構(gòu)效果:

在這里插入圖片描述

復(fù)現(xiàn)單數(shù)字重構(gòu)效果:

在這里插入圖片描述

3.3 重疊數(shù)字重構(gòu)效果

論文重疊數(shù)字重構(gòu)效果:

在這里插入圖片描述

復(fù)現(xiàn)重疊數(shù)字重構(gòu)效果:

第一行為實(shí)際圖片和標(biāo)簽,第二行為預(yù)測的圖片和標(biāo)簽,第三四行是把第二行兩個圖片分開的結(jié)果


在這里插入圖片描述

4. github源碼地址

https://github.com/wangjiosw/capsule-pytorch

5. 參考文章

[1] 揭開迷霧,來一頓美味的Capsule盛宴

[2] 再來一頓賀歲宴:從K-Means到Capsule

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容