先讀懂CapsNet架構而後用TensorFlow實現,這應該是最詳細的教程了

機器之心原創
做者:蔣思源
上週 Geoffrey Hinton 等人公開了那篇 備受關注的 NIPS 論文,然後不少研究者與開發者都閱讀了該論文並做出了必定的代碼實現。機器之心在本文中將詳細解釋該論文提出的結構與過程,並藉助 GitHub 上熱烈討論的項目完成了 CapsNet 的 TensorFlow 實現,並提供了主體架構的代碼註釋。
本文是機器之心的第三個 GitHub 項目,旨在解釋 CapsNet 的網絡架構與實現。爲了解釋 CapsNet,咱們將從卷積層與卷積機制開始,從工程實踐的角度解釋卷積操做的過程與輸出,這對進一步理解 Capsule 層的處理十分有利,後面咱們將基於對 Capsule 層的理解解釋 Geoffrey Hinton 等人最近提出來的 CapsNet 架構。最後咱們會根據 naturomics 的實現進行測試與解釋。
機器之心 GitHub 項目地址:https://github.com/jiqizhixin/ML-Tutorial-Experiment

卷積層與卷積機制
這一部分主要是爲不太瞭解卷積機制具體過程的讀者準備,由於 CapsNet 的前面兩層本質上仍是傳統的卷積操做。若讀者已經瞭解基本的卷積操做,那麼能夠跳過這一章節直接閱讀 Capsule 層的結構與過程。
若要解釋卷積神經網絡,咱們先要知道爲何卷積在圖像上能比全鏈接網絡有更好的性能,如下分別展現了全鏈接網絡和卷積網絡通常的架構:
咱們知道全鏈接網絡前一層的每一個神經元(或單元)都會與後一層中每一個神經元相連,鏈接的強弱能夠經過相對應的權重控制。而全部鏈接權重就是該全鏈接神經網絡但願學到的。上圖可知卷積神經網絡也是由一層一層的神經元組織起來的,只不過全鏈接網絡相鄰兩層的神經元都有鏈接,因此能夠將相同層的神經元排列爲一列,這樣能夠方便顯示鏈接結構。而卷積網絡相連兩層之間只有部分神經元相連,爲了展現每一層神經元的維度,咱們通常會將每個卷積層的結點組織爲一個三維張量。
全鏈接網絡處理圖像最大的問題是每層之間的參數或權重太多了,主要是由於兩層間的神經元都有鏈接。若使用一個隱藏層爲 500 個單元的全鏈接網絡(784×500×10)識別 MNIST 手寫數字,那麼參數的數量爲 28×28×500+5000+510=397510 個參數,這大大限制了網絡層級的加深。
而對於卷積網絡來講,每個單元都只會和上一層部分單元相鏈接。通常每一個卷積層的單元均可以組織成一個三維張量,即矩陣沿第三個方向增長一維數據。例如 Cifar-10 數據集的輸入層就能夠組織成 32×32×3 的三維張量,其中 32×32 表明圖片的尺寸或像素數量,而 3 表明 RGB 三色通道。

卷積層
卷積層試圖將神經網絡中的每一小塊進行更加深刻的分析,從而得出抽象程度更高的特徵。通常來講經過卷積層處理的神經元結點矩陣會變得更深,即神經元的組織在第三個維度上會增長。
下圖展現了卷積核或濾波器(filter)將當前層級上的一個子結點張量轉化爲下一層神經網絡上的一個長和寬都爲 1,深度不限的結點矩陣。下圖輸入是一個 32×32×3 的張量,中間的小長方體爲卷積核,通常能夠爲 3×3 或 5×5 等,且由於要計算乘積,那麼卷積核的第三個維度必須和其處理的圖像深度(即輸入張量第三個維度 3)相等。最右邊的矩形體的深度爲 5,即前面使用了五個卷積核執行卷積操做。這五個卷積核有不一樣的權重,但每個卷積層使用一個卷積核的權重是同樣的,因此下圖五層特徵中每一層特徵都是經過一個卷積核得出來的,也就是該層共享了權重。

卷積操做
可能入門讀者對卷積的具體過程仍是不夠了解,下面咱們能夠討論卷積操做的具體過程。以下所示,該圖展現了卷積的具體操做過程。首先咱們的輸入爲 5×5×3 的張量,即 x[:, :, 0 : 3]。其次咱們有兩個 3×3 的卷積核,即 W0 和 W1,第三個維度必須和輸入張量的第三個維度相等,因此通常只用兩個維度描述一個卷積核。最後卷積操做輸出 3×3×2 的張量,其中 o[:, :, 0] 爲第一個卷積核 W0 的卷積輸出,o[:, :, 1] 爲第二個卷積核的輸出。由於輸入張量使用了 Padding,即每個通道的輸入圖像周圍加 0,且卷積核移動的步幅爲 2,則每一個卷積核輸出的維度爲 3×3(即 (7-3)/2)。
在上圖中,卷積核會與輸入張量對應相乘相加,而後再加上偏置項就等於輸出張量中對應位置的值。例如使用卷積和 W0 對輸入張量(深度爲 3 可看做圖像擁有的 RGB 三個通道)作卷積,卷積和三個層級將對應輸入張量的三個層級作乘積累計。w0[:, :, 0] 乘以 x[:, :, 0] 左上角的九個元素爲 1*0+1*0-1*0-1*0+0*0+1*1-1*0-1*0+0*1=1,同理 w0[:, :, 1] 乘以 x[:, :, 1] 左上角九個元素爲-一、w0[:, :, 2] 乘以 x[:, :, 2] 左上角九個元素爲 0,這三個值相加再加上偏置項 b0 就等於最右邊輸出張量 o[:, :, 0] 的左上角第一個元素,即 1-1+0+1=1。
隨着卷積核移動一個步長,咱們能夠計算出輸出矩陣移動一個元素的值。注意但卷積核在輸入張量上移動的時候,卷積核權重是相同的,也就是說這一層共享了相同的權重,即 o[:, :, 0] 和 o[:, :, 1] 分別共享了一組權重。這裏之因此強調權重的共享,不只由於它是卷積層核心的屬性,同時還有利於咱們在後面理解 CapsNet 的 PrimaryCaps 層。
卷積還有不少性質沒有解釋,例如最大池化選取一個濾波器內數值最大的值表明該區域的特徵以減小輸出張量的尺寸,Inception 模塊將多組卷積核並聯地對輸入張量進行處理,而後再將並聯處理獲得的多個輸出張量按序串聯地組成一個很深的輸出張量做爲 Inception 模塊的輸出等。讀者也能夠繼續閱讀機器之心關於卷積的文章進一步瞭解。最後,咱們提供了一個簡單的實現展現卷積操做的計算過程:
這一段代碼執行了卷積操做和平均池化,它的輸出以下:

Capsule 層與動態路由
這一部分主要是解釋 Capsule 層與動態路由(DynamicRouting)機制的大概原理,這一部分基於咱們對 Hinton 原論文的理解完成,並採用了知乎 SIY.Z、Debarko De 等人的觀點。文末將給出更多的參考資料,讀者可進一步閱讀以瞭解更多。
前面咱們已經知道卷積經過權重共享和局部鏈接能夠減小不少參數,此外共享卷積核權重可使圖像上的內容不受位置的影響。例如 Cifar-10 中的圖像爲 32×32×3,而由 16 個尺寸爲 5×5 的卷積核(或表述深度爲 16)所構成的卷積層,其參數共有 5*5*3*16+16=1216 個。但這這樣的卷積層單元仍是太簡單了,它們也不能表徵複雜的概念。
例如當圖像進行一些旋轉、變形或朝向不一樣的方向,那麼 CNN 自己是沒法處理這些圖片的。固然這個問題能夠在訓練中添加相同圖像的不一樣變形而獲得解決。在 CNN 中每一層都以很是細微的方式理解圖像,由於咱們卷積核的感覺野通常使用 3×3 或 5×5 等像素級的操做來理解圖像,因此卷積層老是嘗試理解局部的特徵與信息。而當咱們由前面低級特徵組合成後面複雜與抽象的特徵時,咱們極可能須要使用池化操做來減小輸出張量或特徵圖的尺寸,而這種操做實際上會丟失一些信息,好比說位置信息。
而等變映射(Equivariance)能夠幫助 CNN 理解旋轉或比例等屬性變換,並相應地調整本身,這樣圖像空間中的位置等屬性信息就不會丟失。而 Geoffrey Hinton 等人提出的 CapsNet 使用向量代替標量點,所以能獲取更多的信息。此外,咱們感受 Capsule 使用向量做爲輸入與輸出是這篇論文的亮點。

Capsule 層
在論文中,Geoffrey Hinton 介紹 Capsule 爲:「Capsule 是一組神經元,其輸入輸出向量表示特定實體類型的實例化參數(即特定物體、概念實體等出現的機率與某些屬性)。咱們使用輸入輸出向量的長度表徵實體存在的機率,向量的方向表示實例化參數(即實體的某些圖形屬性)。同一層級的 capsule 經過變換矩陣對更高級別的 capsule 的實例化參數進行預測。當多個預測一致時(本論文使用動態路由使預測一致),更高級別的 capsule 將變得活躍。」
Capsule 中的神經元的激活狀況表示了圖像中存在的特定實體的各類性質。這些性質能夠包含不少種不一樣的參數,例如姿式(位置,大小,方向)、變形、速度、反射率,色彩、紋理等等。而輸入輸出向量的長度表示了某個實體出現的機率,因此它的值必須在 0 到 1 之間。
爲了實現這種壓縮,並完成 Capsule 層級的激活功能,Hinton 等人使用了一個被稱爲「squashing」的非線性函數。該非線性函數確保短向量的長度可以縮短到幾乎等於零,而長向量的長度壓縮到接近但不超過 1 的狀況。如下是該非線性函數的表達式:

其中 v_j 爲 Capsule j 的輸出向量,s_j 爲上一層全部 Capsule 輸出到當前層 Capsule j 的向量加權和,簡單說 s_j 就爲 Capsule j 的輸入向量。該非線性函數能夠分爲兩部分,即
,前一部分是輸入向量 s_j 的縮放尺度,第二部分是輸入向量 s_j 的單位向量,該非線性函數既保留了輸入向量的方向,又將輸入向量的長度壓縮到區間 [0,1) 內。s_j 向量爲零向量時 v_j 能取到 0,而 s_j 無窮大時 v_j 無限逼近 1。該非線性函數能夠看做是對向量長度的一種壓縮和重分配,所以也能夠看做是一種輸入向量後「激活」輸出向量的方式。
那麼如上所述,Capsule 的輸入向量就至關於經典神經網絡神經元的標量輸入,而該向量的計算就至關於兩層 Capsule 間的傳播與鏈接方式。輸入向量的計算分爲兩個階段,即線性組合和 Routing,這一過程能夠用如下公式表示:
其中 u_j|i hat 爲 u_i 的線性組合,這一點能夠看做是通常全鏈接網絡前一層神經元以不一樣強弱的鏈接輸出到後一層某個神經元。只不過 Capsule 相對於通常神經網絡每一個結點都有一組神經元(以生成向量),即 u_j|i hat 表示上一層第 i 個 Capsule 的輸出向量和對應的權重向量相乘(W_ij 表示向量而不是元素)而得出的預測向量。u_j|i hat 也能夠理解爲在前一層爲第 i 個 Capsule 的狀況下鏈接到後一層第 j 個 Capsule 的強度。
在肯定 u_j|i hat 後,咱們須要使用 Routing 進行第二個階段的分配以計算輸出結點 s_j,這一過程就涉及到使用動態路由(dynamic routing)迭代地更新 c_ij。經過 Routing 就能獲取下一層 Capsule 的輸入 s_j,而後將 s_j 投入「Squashing」非線性函數後就能得出下一層 Capsule 的輸出。後面咱們會重點解釋 Routing 算法,但整個 Capsule 層及它們間傳播的過程已經完成了。
因此整個層級間的傳播與分配能夠分爲兩個部分,第一部分是下圖 u_i 與 u_j|i hat 間的線性組合,第二部分是 u_j|i hat 與 s_j 之間的 Routing 過程。若讀者對傳播過程仍然不是太明晰,那麼能夠看如下兩層 Capsule 單元間的傳播過程,該圖是根據咱們對傳播過程的理解而繪製的:
Capsule 層級結構圖

如上所示,該圖展現了 Capsule 的層級結構與動態 Routing 的過程。最下面的層級 u_i 共有兩個 Capsule 單元,該層級傳遞到下一層級 v_j 共有四個 Capsule。u_1 和 u_2 是一個向量,即含有一組神經元的 Capsule 單元,它們分別與不一樣的權重 W_ij(一樣是向量)相乘得出 u_j|i hat。例如 u_1 與 W_12 相乘得出預測向量 u_2|1 hat。隨後該預測向量和對應的「耦合係數」c_ij 相乘並傳入特定的後一層 Capsule 單元。不一樣 Capsule 單元的輸入 s_j 是全部可能傳入該單元的加權和,即全部可能傳入的預測向量與耦合係數的乘積和。隨後咱們就獲得了不一樣的輸入向量 s_j,將該輸入向量投入到「squashing」非線性函數就能得出後一層 Capsule 單元的輸出向量 v_j。而後咱們能夠利用該輸出向量 v_j 和對應預測向量 u_j|i hat 的乘積更新耦合係數 c_ij,這樣的迭代更新不須要應用反向傳播。

Dynamic Routing 算法
由於按照 Hinton 的思想,找到最好的處理路徑就等價於正確處理了圖像,因此在 Capsule 中加入 Routing 機制能夠找到一組係數 c_ij,它們能令預測向量 u_j|i hat 最符合輸出向量 v_j,即最符合輸出的輸入向量,這樣咱們就找到了最好的路徑。
按照原論文所述,c_ij 爲耦合係數(coupling coefficients),該係數由動態 Routing 過程迭代地更新與肯定。Capsule i 和後一層級全部 Capsule 間的耦合係數和爲 1,即圖四 c_11+c_12+c_13+c_14=1。此外,該耦合係數由「routing softmax」決定,且 softmax 函數中的 logits b_ij 初始化爲 0,耦合係數 c_ij 的 softmax 計算方式爲:
b_ij 依賴於兩個 Capsule 的位置與類型,但不依賴於當前的輸入圖像。咱們能夠經過測量後面層級中每個 Capsule j 的當前輸出 v_j 和 前面層級 Capsule i 的預測向量間的一致性,而後藉助該測量的一致性迭代地更新耦合係數。本論文簡單地經過內積度量這種一致性,即
,這一部分也就涉及到使用 Routing 更新耦合係數。
Routing 過程就是上圖 4 右邊表述的更新過程,咱們會計算 v_j 與 u_j|i hat 的乘積並將它與原來的 b_ij 相加而更新 b_ij,而後利用 softmax(b_ij) 更新 c_ij 而進一步修正了後一層的 Capsule 輸入 s_j。當輸出新的 v_j 後又能夠迭代地更新 c_ij,這樣咱們不須要反向傳播而直接經過計算輸入與輸出的一致性更新參數。
該 Routing 算法更具體的更新過程能夠查看如下僞代碼:
對於全部在 l 層的 Capsule i 和在 l+1 層的 Capsule j,先初始化 b_ij 等於零。而後迭代 r 次,每次先根據 b_i 計算 c_i,而後在利用 c_ij 與 u_j|i hat 計算 s_j 與 v_j。利用計算出來的 v_j 更新 b_ij 以進入下一個迭代循環更新 c_ij。該 Routing 算法十分容易收斂,基本上經過 3 次迭代就能有不錯的效果。

CapsNet 架構
Hinton 等人實現了一個簡單的 CapsNet 架構,該架構由兩個卷積層和一個全鏈接層組成,其中第一個爲通常的卷積層,第二個卷積至關於爲 Capsule 層作準備,而且該層的輸出爲向量,因此它的維度要比通常的卷積層再高一個維度。最後就是經過向量的輸入與 Routing 過程等構建出 10 個 v_j 向量,每個向量的長度都直接表示某個類別的機率。
如下是 CapsNet 的總體架構:
第一個卷積層使用了 256 個 9×9 卷積核,步幅爲 1,且使用了 ReLU 激活函數。該卷積操做應該沒有使用 Padding,輸出的張量才能是 20×20×256。此外,CapsNet 的卷積核感覺野使用的是 9×9,相比於其它 3×3 或 5×5 的要大一些,這個能是由於較大的感覺野在 CNN 層次較少的狀況下能感覺的信息越多。這兩層間的權值數量應該爲 9×9×256+256=20992。
隨後,第二個卷積層開始做爲 Capsule 層的輸入而構建相應的張量結構。咱們能夠從上圖看出第二層卷積操做後生成的張量維度爲 6×6×8×32,那麼咱們該如何理解這個張量呢?雲夢居客在知乎上給出了一個十分形象且有意思的解釋,如前面章節所述,若是咱們先考慮 32 個(32 channel)9×9 的卷積核在步幅爲 2 的狀況下作卷積,那麼實際上獲得的是傳統的 6×6×32 的張量,即等價於 6×6×1×32。
由於傳統卷積操做每次計算的輸出都是一個標量,而 PrimaryCaps 的輸出須要是一個長度爲 8 的向量,所以傳統卷積下的三維輸出張量 6×6×1×32 就須要變化爲四維輸出張量 6×6×8×32。以下所示,其實咱們能夠將第二個卷積層看做對維度爲 20×20×256 的輸入張量執行 8 次不一樣權重的 Conv2d 操做,每次 Conv2d 都執行帶 32 個 9×9 卷積核、步幅爲 2 的卷積操做。
因爲每次卷積操做都會產生一個 6×6×1×32 的張量,一共會產生 8 個相似的張量,那麼將這 8 個張量(即 Capsule 輸入向量的 8 個份量)在第三個維度上合併在一塊兒就成了 6×6×8×32。從上可知 PrimaryCaps 就至關於一個深度爲 32 的普通卷積層,只不過每一層由之前的標量值變成了長度爲 8 的向量。
此外,結合 Hinton 等人給出的 Capsule 定義,它就至關於一組常見的神經元,這些神經元封裝在一塊兒造成了新的單元。在本論文討論的 CapsNet 架構中,咱們將 8 個卷積單元封裝在一塊兒成爲了一個新的 Caosule 單元。PrimaryCaps 層的卷積計算都沒有使用 ReLU 等激活函數,它們以向量的方式預備輸入到下一層 Capsule 單元中。
PrimaryCaps 每個向量的份量層級是共享卷積權重的,即獲取 6×6 張量的卷積核權重爲相同的 9×9 個。這樣該卷積層的參數數量爲 9×9×256×8×32+8×32=5308672,其中第二部分 8×32 爲偏置項參數數量。
第三層 DigitCaps 在第二層輸出的向量基礎上進行傳播與 Routing 更新。第二層共輸出 6×6×32=1152 個向量,每個向量的維度爲 8,即第 i 層共有 1152 個 Capsule 單元。而第三層 j 有 10 個標準的 Capsule 單元,每一個 Capsule 的輸出向量有 16 個元素。前一層的 Capsule 單元數是 1152 個,那麼 w_ij 將有 1152×10 個,且每個 w_ij 的維度爲 8×16。當 u_i 與對應的 w_ij 相乘獲得預測向量後,咱們會有 1152×10 個耦合係數 c_ij,對應加權求和後會獲得 10 個 16×1 的輸入向量。將該輸入向量輸入到「squashing」非線性函數中求得最終的輸出向量 v_j,其中 v_j 的長度就表示識別爲某個類別的機率。
DigitCaps 層與 PrimaryCaps 層之間的參數包含兩類,即 W_ij 和 c_ij。全部 W_ij 的參數數量應該是 6×6×32×10×8×16=1474560,c_ij 的參數數量爲 6×6×32×10×16=184320,此外還應該有 2×1152×10=23040 個偏置項參數,不過原論文並無明確指出這些偏置項。最後小編計算出該三層 CapsNet 一共有 5537024 個參數,這並不包括後面的全鏈接重構網絡參數。(算錯了不要怪小編呦~)

損失函數與最優化
前面咱們已經瞭解 DigitCaps 層輸出向量的長度即某個類別的機率,那麼咱們該如何構建損失函數,並根據該損失函數迭代地更新整個網絡?前面咱們耦合係數 c_ij 是經過一致性 Routing 進行更新的,他並不須要根據損失函數更新,但整個網絡其它的卷積參數和 Capsule 內的 W_ij 都須要根據損失函數進行更新。通常咱們就能夠對損失函數直接使用標準的反向傳播更新這些參數,而在原論文中,做者採用了 SVM 中經常使用的 Margin loss,該損失函數的表達式爲:
其中 c 是分類類別,T_c 爲分類的指示函數(c 存在爲 1,c 不存在爲 0),m+ 爲上邊界,m- 爲下邊界。此外,v_c 的模即向量的 L2 距離。
由於實例化向量的長度來表示 Capsule 要表徵的實體是否存在,因此當且僅當圖片裏出現屬於類別 k 的手寫數字時,咱們但願類別 k 的最頂層 Capsule 的輸出向量長度很大(在本論文 CapsNet 中爲 DigitCaps 層的輸出)。爲了容許一張圖裏有多個數字,咱們對每個表徵數字 k 的 Capsule 分別給出單獨的 Margin loss。
構建完損失函數,咱們就能愉快地使用反向傳播了。

重構與表徵
重構即咱們但願利用預測的類別從新構建出該類別表明的實際圖像,例如咱們前面部分的模型預測出該圖片屬於一個類別,而後後面重構網絡會將該預測的類別信息從新構建成一張圖片。
前面咱們假設過 Capsule 的向量能夠表徵一個實例,那麼若是咱們將一個向量投入到後面的重構網絡中,它應該能重構出一個完整的圖像。所以,Hinton 等人使用額外的重構損失(reconstruction loss)來促進 DigitCaps 層對輸入數字圖片進行編碼。下圖展現了整個重構網絡的的架構:
咱們在訓練期間,除了特定的 Capsule 輸出向量,咱們須要矇住其它全部的輸出向量。而後,使用該輸出向量重構手寫數字圖像。DigitCaps 層的輸出向量被饋送至包含 3 個全鏈接層的解碼器中,並以上圖所示的方式構建。這一過程的損失函數經過計算 FC Sigmoid 層的輸出像素點與原始圖像像素點間的歐幾里德距離而構建。Hinton 等人還按 0.0005 的比例縮小重構損失,以使它不會主導訓練過程當中的 Margin loss。
Capsule 輸出向量的重構與表徵除了能提高模型的準確度之外,還能提高模型的可解釋性,由於咱們能修正須要重構向量中的某個或某些份量而觀察重構後的圖像變化狀況,這有助於咱們理解 Capsule 層的輸出結果。
以上就是本論文構建的 CapsNet 架構,固然 Hinton 還描述了不少試驗結果與發現,感興趣的讀者能夠查閱論文的後一部分。

CapsNet 的 TensorFlow 實現
如下定義構建 CapsNet 後面兩層的方法。在 CapsNet 架構中,咱們能訪問該類中的對象和方法構建 PrimaryCaps 層和 DigitCaps 層。
下面是整個 CapsNet 的架構與推斷過程代碼,咱們須要從 MNIST 抽出圖像並投入到如下定義的方法中,該批量的圖像將先經過三層 CapsNet 網絡輸出 10 個類別向量,每一個向量有 16 個元素,且每一個類別向量的長度爲輸出圖像是該類別的機率。隨後,咱們會將一個向量投入到重構網絡中構建出該向量所表明的圖像。
以上是該網絡的主體代碼,更多代碼請查看 naturomics 的 GitHub 地址,或機器之心的 GitHub 地址,咱們上傳的是帶註釋的代碼,但願能幫助初學者更加理解 CapsNet 的過程與架構。如下是上面咱們定義 CapsNet 的主體計算圖,即 TensorFlow 中的靜態計算圖:
咱們也迭代訓練了大概 3 萬多步,不過由於使用的是 CPU,因此咱們將批量大小調整爲 8 以減小單次迭代的計算壓力,如下是咱們訓練時的損失狀況,最上面是 Margin loss,下面還有重構損失和總損失:
最後放上兩張由 DigitCaps 層輸出向量重構出的對應圖像:
咱們只是初步地探索了 CapsNet,它還存在不少的可能性,例如它以向量的形式應該能獲取很是多的圖像信息,這種優點是否能在其它大型數據集或平面 3D 圖像數據集中進一步展示出非凡的表徵力?並且第二層 PrimaryCaps 的參數很是多,就像一組橫向並聯的卷積結構以產生向量(相似 Inception 模塊,但要寬地多),咱們是否能經過某種方式的共享進一步減小該層級的參數?還有當前 Routing 過程的效果至少在 MNIST 數據集中並很差,它僅僅只能展現存在這個概念,那麼咱們可否找到更加高效的 Routing 算法?此外,Capsule 是否能擴展到其餘神經網絡結構如循環或門控單元?這些可能都是咱們存在的疑惑,但向前走,時間總會給咱們答案的。

歡迎你們留言討論,本文在機器之心網站上將持續更新與修正。

參考資料
  • 原論文:Dynamic Routing Between Capsules(https://arxiv.org/abs/1710.09829)
  • 知乎討論地址:https://www.zhihu.com/question/67287444/answer/251241736
  • naturomics 實現地址(TensorFlow):https://github.com/naturomics/CapsNet-Tensorflow
  • XifengGuo 實現地址(Keras):https://github.com/XifengGuo/CapsNet-Keras
  • leftthomas 實現地址(Pytorch):https://github.com/leftthomas/CapsNet
本文爲機器之心原創,轉載請聯繫本公衆號得到受權。
相關文章
相關標籤/搜索