Python · 神經網路(三*)· 網路

(這裡是最終成品的 GitHub 地址)

(這裡是本章用到的 GitHub 地址)

推薦先修章節:

Python · 神經網路(二*)· 層

Python · 神經網路(三)· 網路

由於分形這個東西是在 tensorflow 的基礎上實現的且相當麻煩、所以我就沒在我自己的結構裡面實現分形。因此,我自己實現的網路中只有一個類,某種意義上也好看一些

在講網路的實現之前,需要先提到的是:正如我們在上一章 (二*)最後提到的、Layer 是需要分成主層(Layer)附加層(SubLayer)兩種的。那麼 SubLayer 是幹嘛的呢?它可以在 Layer 的輸出的基礎上進行一些變換以得到更好的輸出

典型的 SubLayer 有 Dropout 和 Normalize。它們的定義和功效我以後有時間的話會講,現在我們只需要有這樣一個感覺:SubLayer 通常可以優化 Layer 的輸出;SubLayer 之間及 SubLayer 和其根 Layer(定義下面會說)之間的關聯不應是可更新的關聯(因為 SubLayer 更應該是一個「優化器」而不應是一個傳統意義上的神經網路中的可更新的層)

那麼 SubLayer 和 Layer 之間的結構關係就比較清楚了。具體而言,有:

  • SubLayer 是附加在 Layer 後面的
  • 一個 Layer 和若干 SubLayer 共同組成一個整體

  • SubLayer 會有一個域記錄其附加的對象(爸爸)
  • SubLayer 會有一個域記錄其根 Layer(定義為最老的爸爸)(……)

  • Layer 會有一個域記錄附加在其後的第一個 SubLayer (孩子)
  • Layer 會有一個域記錄其最年輕的孩子,不妨把它稱為最後之作(喂!)

這樣說可能有點太抽象(是肯!定!太!抽!象!好!吧!),我們畫張圖來看:

(嗯。好醜。)

知道 Layer 和 SubLayer 之間的大概關係後、就可以著手實現網路了(目前為止我們的 SubLayer 只有 CostLayer 一種,所以下面代碼實現裡面沒有出現 SubLayer)。思路和 tensorflow 版本的差不多、亦即要先實現兩個功能:

  • 加入 Layer 與 Layer 之間的關聯
  • 加入 Layer 本身

其中加入關聯這一步要比 tensorflow 版本的要簡單很多:

def _add_weight(self, shape): self._weights.append(np.random.randn(*shape)) self._bias.append(np.zeros((1, shape[1])))

加入 Layer 本身這一步則幾乎一模一樣:

def add(self, layer): if not self._layers: self._layers, self._current_dimension = [layer], layer.shape[1] self._add_weight(layer.shape) else: _next = layer.shape[0] layer.shape = (self._current_dimension, _next) self._add_layer(layer, self._current_dimension, _next)

唯一的區別在於在加入第二個 Layer 或者之後的 Layer 時,最後調用了一個 _add_layer 方法。這個方法能夠協調 Layer 和 SubLayer 之間的關係,是我們搭建網路結構的關鍵所在:

def _add_layer(self, layer, *args): _parent = self._layers[-1] _current, _next = args self._layers.append(layer) if isinstance(layer, CostLayer): _parent.child = layer self.parent = _parent self._add_weight((1, 1)) self._current_dimension = _next else: self._add_weight((_current, _next)) self._current_dimension = _next

這裡可能需要進行一些說明:

  • 當 layer 不是 CostLayer 時,做的事(else 塊里的東西)和 tensorflow 版本的一樣
  • 當 layer 是 CostLayer 時,我們只需在我們存儲權重和偏置量的列表中放一個佔位符、同時要更新一下父子關係(……)

以上就是與Python · 神經網路(三)· 層對應的、用純 Numpy 寫的結構。雖然代碼很簡單,不過涉及到的概念、理念可能有些太多,我們來整理一下:

  • 網路中有兩種層:Layer 和 SubLayer。其中 Layer 是傳統意義的 Layer, BP 演算法更新層之間的關聯時只會更新 Layer 之間的關聯
  • SubLayer 是一種「優化器」,它能優化從 Layer那裡得到的輸出。它會在前向傳導演算法中用到、但在 BP 演算法中、它會有三種行為:
    • SubLayer 之間的關聯以及 SubLayer 和根 Layer 之間的關聯不會被更新、因為它們只是佔位符
    • SubLayer 作為優化器本身可能會有一些參數,這些參數可能會被 BP 演算法更新、但影響域僅在該 SubLayer 內部(Normalize 是一個很好的栗子)
    • Layer 之間的關聯的更新是通過更新最後之作和下一層 Layer 之間關聯完成的:

      (……捂臉)

最常見的兩種 SubLayer 就是 Dropout 和 Normalize(Batch Normalization)了,如果想要知道怎麼將它們加入我們的網路的話、知道這些理念是必要的。事實上,在這個框架搭建完成後,我們完全可以嘗試使用諸如 Dropout + Normalize + Dropout 這樣的結構會發生什麼(雖然它可能非常不合理、但至少能去嘗試)。而由於演算法是用 Numpy 寫的,我們甚至可以隨便自定義 SubLayer 並嘗試它和其它 SubLayer 的組合效果。這可能對一部分觀眾老爺比較有用 ( σ"ω")σ

如果弄懂了 Layer 和 SubLayer 之間的關係、加上已經支持的(比較簡單的)自定義激活函數的話,可能就能初步應用它來擴展出屬於自己的比較複雜的神經網路模型了。如果再能夠理解這篇文章里介紹的 Optimizers 的思想,我們就能自定義梯度下降演算法、從而就可以對神經網路進行相當大的變裝了

希望觀眾老爺們能夠喜歡~

(猛戳我進入下一章!( σ"ω")σ )


推薦閱讀:

【啄米日常】3:一個不負責任的Keras介紹(下)
CTR預估[四]: Algorithm-LR Bias和Q分布
深度學習(Deep Learning)基礎概念7:搭建多層神經網路的python實現
歷史|從神經元到深度學習

TAG:Python | 机器学习 | 神经网络 |