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

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

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

從這一章開始就要講第二個核心結構 神經網路(NN)的實現了。這一部分是個有點大的坑,我會盡我所能地一一說明。在這一章裡面,我們會說明如何把整個神經網路的結構搭建起來

援引之前用過的一張圖:

可以看到,如果不去管介面怎麼寫的話,因為我們已經處理好了 Layer,所以我們還需要處理的東西其實有一個:

  • 處理綠箭頭的部分!!!

在我們現在準備實現的樸素結構裡面,綠箭頭的部分只有兩個東西:權重 偏置量

所以我們就來實現它們~

在貼出代碼前,需要先說明一下接下來代碼裡面的 shape 是個什麼東西。事實上,它記錄了上一層神經元個數與該層神經元個數。具體而言,有:

  • shape[0] 是上一層神經元個數
  • shape[1] 是該層神經元個數

從而 shape 這個變數起到了承上啟下重要作用,請觀眾老爺們把它的定義牢記於心 ( σ"ω")σ

接下來是具體實現(這裡用到了一些 tensorflow 的函數,可以暫時先用著)(喂):

  1. 根據 shape 獲得初始權重

    def _get_w(self, shape): initial = tf.truncated_normal(shape, stddev=0.1) return tf.Variable(initial, name="w")

  2. 根據 shape 獲得初始偏置量

    def _get_b(self, shape): initial = tf.constant(0.1, shape=shape) return tf.Variable(initial, name="b")

我們再來想一想,在搭建一個網路時,操作順序是什麼?

還是上面那張圖,可以看到搭建順序應該是:加入一個 Layer → 加入綠箭頭 → 加入一個 Layer → 加入綠箭頭 → ……

所以我們接下來要做的只有兩個:加入 Layer 加入綠箭頭(這個人廢話怎麼這麼多)

先講怎麼加入綠箭頭、因為加入 Layer 的過程中會用到這一步。相信觀眾老爺們已經或多或少有些感覺了,這裡就直接貼出代碼:

def _add_weight(self, shape): w_shape = shape b_shape = shape[1], self._tf_weights.append(self._get_w(w_shape)) self._tf_bias.append(self._get_b(b_shape))

因為很重要所以再提一下(這人好啰嗦):shape[0] 是上一層神經元個數而 shape[1] 是該層神經元個數。這也是為什麼偏置量的形狀是 shape[1]

可能觀眾老爺們注意到了,代碼中出現了沒見過的 self._tf_weights 和 self._tf_bias。相信大家也都猜到了:這兩個列表就是存著所有權重和偏置量的列表,可謂是整個結構的核心之一

再講怎麼加入 Layer。不考慮介面的話,加入 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] self._layers.append(layer) self._add_weight((self._current_dimension, _next)) self._current_dimension = _next

解釋一下代碼的邏輯:

  • 如果是第一次加入 Layer 的話,創建一個含有該 Layer 的列表(self._layers),同時用一個變數(self._current_dimension)把 Layer 的 shape[1] 記錄下來(當我們第一次加入 Layer 時,shape[0] 代表著輸入數據的維度,shape[1] 代表著第一層神經元的個數)
  • 如果不是第一次加入的話,由於沒有考慮介面設計,我們需要作這樣的約定:

    • 從第二次加入 Layer 開始,Layer 的 shape 變數都是長度為 1 的元組,其唯一的元素記錄的就是該 Layer 中神經元的個數

      比如說,如果我想設計一個含有一層隱藏層、24 個神經元的結構,我就要這樣做:

      nn.add(ReLU((x.shape[1], 24)))nn.add(CrossEntorpy((y.shape[1], )))

      這裡面出現的 CrossEntropy 是損失函數層(CostLayer),目前暫時沒有講到、不過它也繼承了 Layer,目前來說可以簡單地把它看成一個普通的 Layer

    在該約定下,上面代碼的邏輯就比較清晰了;為簡潔,我就不再贅述(其實還是懶)(喂

那麼稍微總結一下:

  1. 樸素的網路結構只需要重複做兩件事:加入 Layer 和加入綠箭頭。其中,綠箭頭的本質是層與層之間的關聯,它根據 shape 生成相應的權重和偏置量
  2. 一般來說,shape 記錄的是上一層的神經元個數和這一層神經元個數(否則它記錄的會是這一層神經元的個數),它起到了重要的承上啟下的作用

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

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

(猛戳我進入附加章節 ( σ"ω")σ )


推薦閱讀:

《機器學習實戰》學習總結(五)——Logistic回歸
R & Python-機器學習演算法速查表
【小林的OpenCV基礎課 4】滑動條什麼的
用 Python 實現常用演算法和數據結構

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