1.開場先扔個段子

在網際網路廣告營銷中,經常會有這樣的對話:
問:你們的人群標籤是什麼樣的?
答:我們是專門為您訂製的look-alike標籤!
問:好吧,你們的定向演算法能不能說明一下?
答:我們用的是deep learning技術!

一般來說,話題到此,廣告主會因為自己理論知識的匱乏而羞愧得無地自容。唯一的辦法就是先透過投放廣告的方式先學習起來。
——劉鵬《廣告技術公司十大裝逼姿勢》

deep learning、DNN、BP神經網路等這些高逼格的詞,真的很能嚇唬人,但真正的內容什麼,很多人卻解釋得不多,要麼說得太晦澀,要麼說得太神叨。其實,就我們的粗淺瞭解,神經網路、深度學習啥的,入門還是很容易的。如果去除外面浮誇的包裝,它們的理論基礎也相當直白。當然這並不是說神經網路不難,它們真正難的地方是在實踐方面,但這也是有方法可處理的。為了淺顯易懂地給大家解釋這個過程,我們開設了“手把手入門神經網路系列”
在本篇文章中,我們依然少用公式多畫圖,只用初等數學的知識解釋一下神經網路。

2.神經網路有什麼牛逼之處?

機器學習演算法這麼多,為什麼神經網路這麼牛逼?
為了解釋這個問題,我們呈現了神經網路在分類問題上優於邏輯迴歸的地方——它幾乎可以實現任意複雜的分類邊界,無誤差地實現訓練集上的分類。
然而,這是有代價的:由於其強大的擬合能力,極容易產生過擬合。為了降低過擬合,我們介紹了一種降低過擬合的思路。
在這個過程中,我們儘量解釋神經網路每一步操作對應的現實意義和最終目的。可是,神經網路的可解釋性往往是個非常大的難題。為此,我們採用了最易於理解的“交集”(邏輯與)、“並集”(邏輯或)神經網路,希望能幫助大家進行啟發式理解。
但是,神經網路的問題並沒有解決完。之後,我們引出了用神經網路的一些典型問題,我們將在接下來的系列文章對其進行深入探討。

3.從邏輯迴歸到神經網路

神經網路主要應用場景之一是分類,我們之前博文中提到的邏輯迴歸也是解決分類問題的一類機器學習演算法,有趣的是,實際上兩者有著很緊密的關係,而邏輯迴歸作為幫助我們理解神經網路的切入口也是極好的,所以我們先從邏輯迴歸開始。看過本我們前文《機器學習系列(2)_用初等數學解讀邏輯迴歸》的讀者盆友應該會有個印象,邏輯迴歸可以理解成將空間中的點經過一系列幾何變換求解損失函式而進行分類的過程,具體過程如圖:
邏輯迴歸
具體分析一下我們所求的“引數” 的幾何意義,(θ1,θ2)就是圖中法向量p的方向,θ0 對應著法向量p的起點距離座標系原點的偏移。在神經網路中,向量(θ1,θ2)也叫做權重,常用w表示;θ0就叫做偏移,常用b表示。
而上面的邏輯迴歸過程,用神經元的表達方式如下,這就是傳說中的“感知器”:
感知器
其中,z=θ0+θ1X1+θ2X2a=g(z)=11+ezg(z)叫做激勵函式
邏輯迴歸的激勵函式自然就是sigmoid函式,輸出值a對應著輸入樣本點x(X1,X2)在法向量p所指向的那部分空間的概率。本文為了相容邏輯迴歸,只考慮sigmoid函式作為激勵函式的情況,而且這也是工業界最常見的情況。其他激勵函式的選擇將會在後面系列文章繼續介紹。
補充說明一下,以上只是為了表示清晰而這樣畫神經網路。在一般的神經網路畫法中,激勵函式的操作節點會與輸出節點寫成同一個節點,如下圖:
感知器二
好了,到此為止,神經網路相對於邏輯迴歸沒有提供任何新的知識,就是換了個花樣來表示
但神經網路這樣表示有個重大的作用:它方便我們以此為基礎做邏輯迴歸的多層組合巢狀——比如對同樣的輸入x(X1,X2)可以同時做n個邏輯迴歸,產生n個輸出結果,這就是傳說中的“單層感知器”或者叫“無隱層神經網路”。示意圖如下:
無隱層感知器
你還可以對n個邏輯迴歸的n個輸出再做m個邏輯迴歸,這就是傳說中的“單隱層神經網路”。示意圖如下:
單隱層感知器
如果你願意,可以繼續做下去,子子孫孫無窮匱也:
多隱層
最左邊的層叫做輸入層,最右邊的層叫做輸出層,二者之間的所有層叫做隱藏層。
如果層數比較少,就是傳說中的SNN(shallow nerual network) “淺層神經網路”;如果層數比較多,就是傳說中的DNN(Deep Neural Networks) “深度神經網路”。對“淺層神經網路”的建模叫做“淺層學習”,那麼對於“深度神經網路”……“深度學習”!
恭喜你已經會搶答了!
到目前為止,我們沒有運用任何更多的數學知識,就已經收穫了一大批裝逼術語。
如果你願意,把上面的所有情況叫做“邏輯迴歸的邏輯迴歸的邏輯迴歸的邏輯……”,我也覺得蠻好哈。(喘不過氣來了……)

4.雙隱層神經網路徹底實現複雜分類

我們之前已經探討過,邏輯迴歸的比較擅長解決線性可分的問題。對於非線性可分的問題,邏輯迴歸有一種運用複雜對映函式的思路,但這種思路只做了一次(非線性的)幾何變換,就得到了線性可分的情形。可參考下圖:
幾何變換非線性
神經網路的視角則給我們提供了另一種思路,可以連續做幾次的幾何變換,每次變換都是一些極簡單的邏輯迴歸,最終達到線性可分情形。看起來似乎很不錯哦。比如下面這個貌似很簡單的問題,我們怎麼找出他的分離邊界?
異或
發現無論怎麼用一條直線切都不行。那麼兩條直線行不行?
異或二
這麼看確實是可以的,我們只需要把兩個”半平面”取交集就可以找到一個楔形區域的非線性分離邊界了,而且並不是唯一的解。因此我們發現如果允許對同一個輸入做多種不同的邏輯迴歸,再對這些結果取交集,就可以解決很大一部分非線性可分問題。
那麼,對於取交集怎麼用邏輯迴歸表達?我們考慮兩個輸入的情況,每一個輸入是樣本點x(X1,X2)屬於某一個”半平面”的概率,取交集意味著該樣本點屬於兩個”半平面”的概率均接近於1,可以用一條直線將其區分開來。
可見,對於交集運算,通過選取合適的權重和偏移,就可以得到一個線性的分離邊界。這也就是所謂用神經元實現“邏輯與”運算,這是神經網路的一個常見應用:
邏輯與

以上過程如果用神經網路來展現的話,可以設計成一個單隱層神經網路,每層的節點數依次為:3、3、1,如下如圖:
單隱層神經網路
解釋下每一層的作用:
1. 第一層是輸入層,對應著每一個輸入的二維樣本點x(X1,X2)的2個輸座標和1個輔助偏移的常量“1”,總共3個節點。
2. 第二層是第一層的輸出層,每個節點對應著輸入樣本點屬於某個”半平面”的概率,該”半平面”的正向法向量就對應著輸入層(輸入樣本點座標)到該節點的權重w和偏移b。為了定位中間這2個X點,我們圍繞它們上下切2刀,用2個”半平面”相交產生的楔形開放凸域定位這2個X點,所以這一層對應著總共產生了的2個”半平面”,有2個節點。第二層同時也是第三層的輸入層,要考慮再加上求第三層節點時要用的1個輔助偏移的常量節點“1”,第二層總共有2+1=3個節點。
3. 第三層是第二層也是整體的輸出層,輸出節點對應著輸入樣本點屬於楔形開放凸域的概率,也就是與這2個X點屬於同一類的概率。
但是這種方法有侷限,這些直線分割的”半平面”取的交集都有個特點,用專業的說法“都是凸域的”——其邊界任意兩點的連線都在域內。如下圖各個色塊,每一個色塊都是一個凸域。
凸域
單獨一個凸域的表現能力可能不是很強,無法構造一些非凸域的奇怪的形狀。於是我們考慮是不是把n個凸域並在一起,這樣就可以組成任意非凸域的奇葩的形狀了:如上圖所有彩色色塊拼起來的區域。那對應於神經元是怎麼一個操作?……再加一層,取他們的並集
恭喜你又會搶答了。
而取並集就意味著該樣本點屬於兩個”半平面”的概率至少有一個接近於1,也可以用一條直線將其區分開來。
可見,對於並集運算,通過選取合適的權重和偏移,也可以得到一個線性的分離邊界。這就是所謂用神經元實現“邏輯或”運算,這也是神經網路的一個常見應用:
邏輯或

我們用一下這張圖總結上面所說的內容,一圖勝千言唉:
神經網路表達全圖
數學家們經過嚴格的數學證明,雙隱層神經網路能夠解決任意複雜的分類問題

5.以三分類問題為例演示神經網路的統一解法

對於一切分類問題我們都可以有一個統一的方法,只需要兩層隱藏層。以下面這個3分類問題為例:
三分類
我們通過取”半平面”、取交集生成精確包含每一個樣本點的凸域(所以凸域的個數與訓練集的樣本的個數相等),再對同類的樣本點的區域取並集,這樣無論多複雜的分離介面我們可以考慮進去。於是,我們設計雙隱層神經網路結構如下,每一層的節點數依次為:3、25、7、3:
網路結構
解釋下每一層的作用:
1. 第一層是輸入層,對應著每一個輸入的二維樣本點x(X1,X2)的2個輸座標和1個輔助偏移的常量“1”,總共3個節點。
2. 第二層是第一層的輸出層,每個節點對應著輸入樣本點屬於某個”半平面”的概率,該”半平面”的正向法向量就對應著輸入層(輸入樣本點座標)到該節點的權重w和偏移b。為了精確定位總共這6個點,我們圍繞每個點附近平行於座標軸切4刀,用四個”半平面”相交產生的方形封閉凸域精確包裹定位該點,所以這一層對應著總共產生了的4*6=24個”半平面”,有24個節點。第二層同時也是第三層的輸入層,要考慮再加上求第三層節點時要用的1個輔助偏移的常量節點“1”,第二層總共有24+1=25個節點。
3. 第三層是第二層的輸出層,每個節點對應著輸入樣本點屬於第二層區分出來的某4個”半平面”取交集形成的某個方形封閉凸域的概率,故總共需要24/4=6個節點。因為採用我們的劃分方式,只需要四個”半平面”就可以精確包裹某一個樣本點了,我們認為其他的”半平面”貢獻的權重應該為0,就只畫了生成該凸域的四個”半平面”給予的權重對應的連線,其他連線不畫。第三層同時也是第四層的輸入層,要考慮再加上求第四層節點時要用的1個輔助偏移的常量節點“1”,第三層總共有6+1=7個節點。
4. 第四層是第三層的輸出層,每個節點對應著輸入樣本點屬於某一類點所在的所有區域的概率。為找到該類的區分割槽域,對第三層屬於同一類點的2個凸域的2個節點取並集,故總共需要6/2=3個節點。(同樣,我們不畫其他類的凸域貢獻的權重的連線
小結一下就是先取”半平面”再取交集最後取並集
如果看文字太累,請看下圖。只可惜圖太小,省略了很多節點,請見諒。如果覺得還是有些問題,歡迎在評論區中參與討論哈。
神經網路全圖

6.一種降低過擬合的方法

我們的確有了一個統一的解法。但估計很多同學看到還沒看完就開始吐槽了:“總共也就6個樣本,尼瑪用了32個隱藏節點,訓練111個(24*3+6*5+3*3)引數,這過擬合也太過分了吧!”
的確如此,這個過擬合弄得我們也不忍直視。如果我們多增加幾個樣本,就會發現上面訓練出來的模型不夠用了。
過擬合

通過這個反面教材我們發現,神經網路是特別容易過擬合的。而如何降低過擬合就是神經網路領域中一個非常重要的主題,後面會有專文討論。本例只是簡單應用其中一個方法——就是降低神經網路的層數和節點數。
我們仔細觀察樣本點的分佈,發現每兩個類別都可以有一條直線直接將它們分開,這是所謂的one-vs-one的情況,用三條直線就可以完全將這些類別區分開來
三線分離

相應的,我們只需要求出每兩個類別的分離直線,找出每個類別所屬的兩個半平面,對它們求一個交集就夠了。神經網路結構如下:
三線分類

解釋下每一層的作用:
1. 第一層是輸入層,對應著每一個輸入的二維樣本點x(X1,X2)的2個輸座標和1個輔助偏移的常量“1”,總共3個節點。
2. 第二層是第一層的輸出層,每個節點對應著輸入樣本點屬於某個”半平面”的概率,該”半平面”的正向法向量就對應著輸入層(輸入樣本點座標)到該節點的權重w和偏移b。因為3個”半平面”足以定位每一個型別的區域,所以這一層有3個節點。第二層同時也是第三層的輸入層,要考慮再加上求第三層節點時要用的1個輔助偏移的常量節點“1”,第二層總共有3+1=4個節點。
3. 第三層是第二層的輸出層,每個節點對應著輸入樣本點屬於第二層區分出來的某2個”半平面”取交集形成的某個開放凸域的概率。我們同樣認為其他的”半平面”貢獻的權重應該為0,就只畫了生成該凸域的2個”半平面”給予的權重對應的連線,其他連線不畫。只是這裡與上面例子的情況有一點小小的不同,因為一個分離直線可以區分出兩個“半平面”,兩個“半平面”都被我們的利用起來做交集求凸域,故每個第二層的節點都引出了兩條權重的連線到第三層。而這取交集的結果足以定位每一個型別的區域,因此第三層也就是總體的輸出層。故第三層總共需要3個節點。
在這裡,我們只用了1個隱藏層4個節點就完成了分類任務,能夠識別的樣本還比之前多。效果是很明顯的。
從以上推導我們可以得出一個啟發式的經驗:通過適當減少神經元的層數和節點個數,可以極大地提高計算效率,降低過擬合的程度。我們會在另一篇文章中有更加全面系統的論述。

7.然而,問題真的解決了嗎?

其實並沒有。

  • 我們憑什麼知道上面改進的模型還有沒有過擬合

    其實我們並不知道。因此我們需要更加科學客觀的方法進行評估模型

  • 降低神經網路過擬合的方式有哪些?

  • 我們憑什麼知道我們的節點數隱藏層個數的選擇是合適的?

    我們剛才只是直接是畫出了分界線和相應的神經元組合。問題是,很多時候你並不知道樣本真實的分佈,並不知道需要多少層、多少個節點、之間的連結方式怎樣。

  • 我們怎麼求出這些(超)引數呢?

  • 假設我們已經知道了節點數和隱藏層數,我們怎麼求這些神經元的權重偏移呢?

  • 最常用的最優化的方法是梯度下降法。求梯度就要求偏導數,但是你怎麼求每一個權重和偏移的偏導數呢?

  • 假設我們已經知道了傳說中的BP演算法,也就是反向傳播演算法來求偏導數。但是對於稍微深一點的神經網路,這種方法可能會求出一些很奇葩的偏導數,跟真實的偏導數完全不一樣,導致整個模型崩潰。那麼我們怎麼處理、怎麼預防這樣的事情發生呢?

  • 為什麼神經網路這麼難以訓練?

  • 除掉邏輯迴歸型別對應的sigmoid激勵函式神經元,還有很多其他的激勵函式,我們對不同的問題,怎麼選擇合適的激勵函式

  • 神經網路還有其他的表示形式和可能性嗎?

  • 怎樣選擇不同的神經網路型別去解決不同的問題?
    …….

  • 其實,本文舉例中將後幾層的神經網路直接解釋成做交集、並集的“與”、“或”邏輯運算,這些技術很早就出現了,神經網路依然只是對它們的包裝,並不能顯示神經網路有多強大。神經網路的獨特特點是它能夠自動調整到合適的權重,不拘泥於交集、並集等邏輯運算對權重的限制。而神經網路真正的威力,是它幾乎可以擬合一切函式。它為什麼這麼牛?怎麼解釋神經網路的擬合特性呢?能不能形象地解釋一下?也將是我們下一步需要探討的問題。
    ……
    可見,神經網路深度學習有很多問題還沒有解決。我們會在接下來的文章中一一與大家探討。
    但是這麼多問題從哪入手?其實,我們覺得,直接給大家一個栗子,解決一個真實的問題,可能更容易理解。所以下一篇文章我們將給大家演示怎麼用神經網路計算解決問題,並做進一步的啟發式探討。而且,我們將會發碼——讓大家之間在自己的電腦上執行python程式碼——來進行手寫數字的識別。你們猜猜程式碼有多短?只有74行!

8.附:本系列文章的邏輯體系圖

邏輯體系