【深度學習之美】山重水複疑無路,最快下降問梯度(入門系列之七)

(原文於2017年6月發表於雲棲社區:https://yq.aliyun.com/articles/105339)

一年多前,吳軍博士寫了一本暢銷書《智能時代》[1]。書裏提到,在人工智能領域,有一個流派叫“鳥飛派”,亦稱之爲“模仿派”。說的是,當人們要學習飛翔的時候,最先想到的是模仿鳥一樣去飛翔。

很多年前,印度詩人泰戈爾出了本《飛鳥集》,裏面有個名句:“天空沒有留下翅膀的痕跡,但我已經飛過”。有人對此解讀爲,“人世間,很多事情雖然做過了,卻不爲人所知,但那又如何?重要的是,我已做過,並從中獲得了許多。”

兩千多年前,司馬遷在《史記•滑稽列傳》寫到:“此鳥不飛則已,一飛沖天;不鳴則已,一鳴驚人。”說的是當年楚莊王在“勢不眷我”時,選擇了“蟄伏”。蟄伏,只是一個儲勢過程,遲早有一天,蓄勢待發,“發”則達天。
這三者的情感交集,讓我聯想到出了本章的主人公傑弗裏•辛頓(Geoffrey Hinton)教授,在學術界裏,他就是這樣的一個“勵志”人物!
1986年,辛頓教授和他的小夥伴們重新設計了BP算法,以“人工神經網絡”模仿大腦工作機理,“吻”醒了沉睡多年的“人工智能”公主,一時風光無限。
但“好花不常開,好景不常在”。當風光不再時,辛頓和他的研究方向,逐漸被世人所淡忘。
這被“淡忘”的冷板凳一坐,就是30年。

但在這30年裏,辛頓又如“飛鳥”一般,即使“飛過無痕”,也從不放棄。從哪裏跌倒,就從哪裏爬起。實在不行,即使換個馬甲,也要重過一生。
玉汝於成,功不唐捐。
終於,在2006年,辛頓等人提出了“深度信念網(Deep Belief Nets,DBN)”(這實際上就是多層神經網絡的馬甲)[2]。這個“深度信念網”後期被稱爲“深度學習”。終於,辛頓再次閃耀於人工智能世界,隨後被封爲“深度學習教父”。

但細心的讀者可發現,即使辛頓等人提出了“深度信念網”,在隨後的小10年裏,這個概念亦是不溫不火地發展着(如圖1所示)。直到後期(2012年以後),隨着大數據和大計算(GPU、雲計算等)的興起,深度學習纔開始大行其道,一時間甚囂塵上。


473387ba332c29a061579c612ecdcabd36b2d99a


圖7-1 深度學習的谷歌趨勢圖

回顧起傑弗裏•辛頓過往40多年的學術生涯,可謂是顧跌宕起伏,但最終修得正果。倘若細細說起,這“牛逼”,還得從1986年吹起。

7.1 1986年的那篇神作

1986年10月,傑弗裏•辛頓還在卡內基梅隆大學任職。他和在加州大學聖迭戈分校的認知心理學家大衛·魯梅爾哈特(David Rumelhart)等人,在著名學術期刊《自然》上聯合發表題爲:“通過反向傳播算法的學習表徵(Learning Representations by Back-propagating errors)”的論文[3]。該文首次系統簡潔地闡述反向傳播算法(BP)在神經網絡模型上的應用,該算法把網絡權值糾錯的運算量,從原來的與神經元數目的平方成正比,下降到只和神經元數目本身成正比。

與此同時,當時的大背景是,在八十年代末,Intel x86系列的微處理器和內存技術的發展,讓計算機的運行速度和數據訪存速度也比二十年前高了幾個數量級。這一下(運算量下降)一上(計算速度上升),加之多層神經網絡可通過設置隱含層 (hidden layer),極大增強了數據特徵的表徵能力,從而輕易解決感知機無法實現的異或門 (XOR gate)難題,這些“天時地利人和”的大好環境,極大緩解了當年明斯基對神經網絡的責難。
於是,人工神經網絡的研究,漸漸得以復甦。


26fbe65f390940904aca829eb23e43377a97fca6


圖7-2 1986年傑弗裏•辛頓的那篇神作

值得一提的是,在文獻[3]中,傑弗裏•辛頓並不是第一作者,魯梅爾哈特纔是,而辛頓僅僅“屈居”第二(如圖7-2所示)。但爲什麼我們提起BP算法時,總是說起辛頓呢?其實原因也很簡單,主要有二:第一、魯梅爾哈特畢竟並非計算機科學領域之內的人士,我們計算機科學家,總不能找一個腦科學家去“拜碼頭”吧;第二、辛頓是這篇論文的通信作者,通常而言,通信作者纔是論文思路的核心提供者,這樣一來,即使作者排名第二,也沒有埋沒掉辛頓教授的貢獻。

同在1986年,魯梅爾哈特也和自己的小夥伴們合作發表了一篇題爲“並行分佈式處理:來自認知微結構的探索”的論文[4]。僅僅從論文題目的前半部分來看,我們很可能誤解這是一個有關“高性能計算”的文章,但從標題的後半部分可以得知,這是魯梅爾哈特等人對人類大腦研究的最新認知。魯梅爾哈特對大腦工作機理的深入觀察,極大地啓發了辛頓。辛頓靈光一現,覺得可以把這個想法遷移到“人工神經網絡”當中。於是,就有了他們神來一筆的合作。
我們知道,1986年,辛頓和魯梅爾哈特能在大名鼎鼎的《自然》期刊上發表論文,自然不是泛泛而談,它一定是解決了什麼大問題。下面我們就聊聊這個話題。

7.2 多層感知機網絡遇到的大問題

由於歷史的慣性,在第六講中提到的多層前饋網絡,有時也被稱爲多層感知機(Multilayer Perceptron,MLP)。但這個提法導致概念多少有些混淆。這是因爲,在多層前饋網絡中,神經元的內部構造已悄然發生變化,即激活函數從簡單粗暴的“階躍函數”變成了比較平滑的擠壓函數Sigmoid(如圖7-3所示)。
激活函數爲什麼要換成Sigmoid呢?其實原因並不複雜,這是因爲感知機的激活函數是階躍函數,不利於函數求導,進而求損失函數的極小值。我們知道,當分類對象是線性可分,且學習率(learning rate)η足夠小時,由感知機還堪勝任,由其構建的網絡,還可以訓練達到收斂。但分類對象不是線性可分時,感知機就有點“黔驢技窮”了。因此,通常感知機並不能推廣到一般前饋網絡中。


695665b6fab2907e89e0f5ea550082b212818350


圖 7-3 變更激活函數的前饋多層神經網絡

按照我們前面章節的說法,所謂的機器學習,簡單來說,就是找到一個好用的函數(function),從而較好地實現某個特定的功能(function)。一言蔽之,函數就是功能。而對於某個特定的前饋神經網絡,給定網絡參數(連接權值與閾值),其實就是定義了一個具備數據採集(輸入層)、加工處理(隱含層),然後輸出結果(輸出層)的函數。
如果僅僅給定一個網絡結構,其實它定義的是一個函數集合。因爲不同的網絡參數(連接權值與閾值),實現的功能“大相徑庭”。功能不同,自然函數也是不同的!

針對前饋神經網絡,我們需要實現的目的很簡單,就是想讓損失函數達到最小值,因爲只有這樣,實際輸出和預期輸出的差值才最小。那麼,如何從衆多網絡參數(神經元之間的鏈接權值和閾值)中選擇最佳的參數呢?
最簡單粗暴的方法,當然就是枚舉所有可能值了!


1d55debae62787470e13eaa4765e83e32924e177


圖7-4 暴力調參不可取

但這中暴力策略,對稍微複雜一點的網絡就不可取了!例如,用於語音識別的神經網絡,假設網絡結構有7層,每一層有1000個神經元,那麼僅一層之間的全連接權值,就達到1000×1000=1061000×1000=106個,一旦層次多了,那權值數量就海了去了!(如圖7-4所示)。故此,這種暴力調參找最優參數,既不優雅,也不高效,故實不可取!

7.3到底什麼是梯度?

爲了克服多層感知機存在的問題,人們設計了一種名爲delta(DeltaDelta)法則(delta rule)的啓發式方法,該方法可以讓目標收斂到最佳解的近似值[5]。
delta法則的核心思想在於,使用梯度下降(gradient descent)的方法找極值。具體說來,就是在假設空間中搜索可能的權值向量,並以“最佳”的姿態,來擬合訓練集合中的樣本。那麼,何謂最佳擬合呢?當然就是讓前文提到的損失函數達到最小值!

我們知道,求某個函數的極值,難免就要用到“導數”等概念。既然我們把這個系列文章定位爲入門層次,那不妨就再講細緻一點。什麼是導數呢?所謂導數,就是用來分析函數“變化率”的一種度量。針對函數中的某個特定點x0,該點的導數就是x0點的“瞬間斜率”,也即切線斜率,見公式(7.1)。

f(x0)=limΔx0ΔyΔx=limΔx0f(x0+Δx)f(x0)Δx(7.1)(7.1)f′(x0)=limΔx→0⁡ΔyΔx=limΔx→0⁡f(x0+Δx)−f(x0)Δx

如果這個斜率越大,就表明其上升趨勢越強勁。當這個斜率爲0時,就達到了這個函數的“強弩之末”,即達到了極值點。而前文提到的損失函數,如果要達到損失最小,就難免用到導數“反向指導”如何快速抵達極小值。
在單變量的實值函數中,梯度就可以簡單地理解爲只是導數,或者說對於一個線性函數而言,梯度就是線的斜率。但對於多維變量的函數,它的梯度概念就不那麼容易理解了。下面我們來談談這個概念。
在向量微積分中,標量場的梯度其實是一個向量場(vector field)。對於特定函數的某個特定點,它的梯度就表示從該點出發,該函數值增長最爲迅猛的方向(direction of greatest increase of a function)[6]。假設一個標量函數f的梯度記爲:ffgradfgradf,這裏的表示向量微分算子。那麼,在一個三維直角座標系,該函數的梯度就可以表示爲公式(7.2):

f=(fx,fy,fz)(7.2)(7.2)∇f=(∂f∂x,∂f∂y,∂f∂z)

求這個梯度值,難免要用到“偏導”的概念。說到“偏導”,這裏順便“輕拍”一下國內的翻譯。“偏導”的英文本意是“partial derivatives(局部導數)”,書本上常翻譯爲“偏導”,可能會把讀者的思路引導“偏”了。
那什麼是“局部導數”呢?對於多維變量函數而言,當求某個變量的導數(相比於全部變量,這裏只求一個變量,即爲“局部”),就是把其它變量視爲常量,然後整個函數求其導數。之後,這個過程對每個變量都“臨幸”一遍,放在向量場中,就得到了這個函數的梯度了。舉例來說,對於3變量函數f=x2+3xy+y2+z3f=x2+3xy+y2+z3,它的梯度可以這樣求得:
(1) 把yyzz視爲常量,得xx的“局部導數”:

fx=2x+3y∂f∂x=2x+3y

(2) 然後把xxzz視爲常量,得yy的“局部導數”:

fy=3x+2y∂f∂y=3x+2y

(3) 最後把xxyy視爲常量,得zz的“局部導數”:

fy=3z2∂f∂y=3z2

於是,函數ff的梯度可表示爲:

f=grad(f)=(2x+3y,3x+2y,3z2)∇f=grad(f)=(2x+3y,3x+2y,3z2)

針對某個特定點,如點A(1, 2, 3),帶入對應的值即可得到該點的梯度:

f=grad(f)=(2x+3y,3x+2y,3z2)x=1y=2z=3=(8,7,27)∇f=grad(f)=(2x+3y,3x+2y,3z2)∣x=1y=2z=3=(8,7,27)

這時,梯度可理解爲,站在向量點A(1, 2, 3),如果想讓函數f的值增長得最快,那麼它的下一個前進的方向,就是朝着向量點B(8,7,27)方向進發(如圖7-5所示)。很顯然,梯度最明顯的應用,就是快速找到多維變量函數的極(大/小)值。


fa7173766658813327198183bf5e53a187b84847


圖7-5 梯度概念的示意圖

在這裏需要說明的是,我們用“局部導數”的翻譯,僅僅是用來加深大家對“偏導”的理解,並不是想糾正大家已經約定俗成的叫法。所以爲了簡單起見,在後文我們還是將“局部導數”稱呼爲“偏導”。

7.4 到底什麼是梯度下降?

上面我們提到了梯度的概念,下面我們說說在求損失函數極小值過程中,常常提到的“梯度遞減”的概念。
我們先給出一個形象的案例。爬過山的人,可能會有這樣的體會,爬坡愈平緩(相當於斜率較小),抵達山峯(函數峯值)的過程就越緩慢,而如果不考慮爬山的重力阻力(對於計算機而言不存在這樣的阻力),山坡越陡峭(相當於斜率越大),順着這樣的山坡爬山,就越能快速抵達山峯(對於函數而言,就是愈加快速收斂到極值點)。


65e84b866c08b4c43ccdc900bb9f7a458acd3d2e


圖7-6 梯度遞減求極小值

如果我們把山峯“乾坤大挪移”,把爬山峯變成找谷底(即求極小值),這時找斜率最陡峭的坡而攀爬山峯的方法,並沒有本質變化,不過是方向相反而已。如果把登山過程中求某點的斜率稱爲“梯度(gradient)”,而找谷底的方法,就可以把它稱之爲“梯度遞減(gradient descent)”,示意圖如圖7-6所示。
依據“梯度遞減”作爲指導,走一步,算一步,一直遵循“最陡峭”的方向,探索着前進,這個過程,是不是有點像鄧公的名句“摸着石頭過河”?

這個“梯度遞減”體現出來的指導意義,就是“機器學習”中的“學習”內涵,即使在大名鼎鼎的“AlphaGo”中,“學習”這是這麼玩的!你是不是有點失望?這機器學習也太不高大上了!

但別忘了,在第一講中,我們就已經講到“學習”的本質,在於性能的提升。利用“梯度遞減”的方法,的確在很大程度上,提升了機器的性能,所以,它就是“學習”!
當然,從圖7-6中,我們也很容易看到“梯度遞減”的問題所在,那就是它很容易收斂到局部最小值。正如攀登高峯,我們會感嘆“一山還比一山高”,探尋谷底時,我們也可能發現,“一谷還比一谷低”。但是“只緣身在此山中”,當前的眼界讓我們像“螞蟻尋路”一樣,很難讓我們有全局觀,因爲我們都沒有“上帝視角”。

7.5 重溫神經網絡的損失函數

針對前饋神經網絡的設計,輸入和輸出層設計比較直觀。比如說,假如我們嘗試判斷一張手寫數字圖片上面是否寫着數字“2”。很自然地,我們可以把圖片像素的灰度值作爲網絡的輸入。如果圖片的維度是16×16,那麼我們輸入層神經元就可以設計爲256個(也就是說,輸入層是一個包括256個灰度值向量),每個神經元接受的輸入值,就是規格化的灰度值。

而輸出層的設計也很簡單,就是需要包含10神經元,輸出是數字“0~9”的分類概率(也就是說,輸出層是一個包括10個概率值的向量)。擇其大者而判之,如圖7-7所示,如果判定爲“2”的概率(比如說80%)遠遠大於其他數字,那麼整個神經網絡的最終判定,就是手寫圖片中的數字是“2”,而非其它數字。
相比於神經網絡輸入、輸出層設計的簡單直觀,它的隱含層設計,可就沒有那麼簡單了。說好聽點,它是一門藝術,依賴於“工匠”的打磨。說不好聽點,它就是一個體力活,需要不斷地“試錯”。

但通過不斷地“折騰”,研究人員還真是掌握了一些針對隱層的啓發式設計規則(如下文即將提到的BP算法),以此降低訓練網絡所花的開銷,並儘量提升網絡的性能。
那麼,怎樣纔算是提升神經網絡性能呢?這就需要用到我們前面提到的損失函數了。在第六章我們提到,所謂“損失函數”,就是一個刻畫實際輸出值和期望輸出值之間“落差”的函數。
爲了達到理想狀態,我們當然希望這種“落差”最小,也就是說,我們希望快速配置好網絡參數,從而讓這個損失函數達到極小值。這時,神經網絡的性能也就接近最優!

關於求損失函數極小值,臺灣大學李宏毅博士給出了一個通俗易懂的例子,下面我們來說說。對於識別手寫數字的神經網絡,訓練數據都是一些“0,1 2, …, 9”等數字圖像,如圖7-8所示。


c2cc9974f1c0869eca1298d03e2386257e2e737f


圖7-8 識別手寫數字的神經網絡

由於人們手寫數字的風格不同,圖像的殘缺程度不同,輸出的結果有時並不能“十全十美”,於是我們就用損失函數來衡量二者的誤差。前面我們提到,常用的損失函數是:

(Y,f(X))=12(Yf(X))2(7.3)(7.3)(Y,f(X))=12(Y−f(X))2

機器學習的任務,在很大程度上,找一個模型,擬合(fitting)或者說“適配”給定的訓練數據,然後再用這個模型預測新數據。這個模型的表現形式,具體說來,就是設計一個好用的函數,用以揭示這些訓練樣本隨自變量的變化關係。揭示擬合好壞的程度,就要用到損失函數。“損失”越小,說明擬合的效果就越好。


7f600f55091d803f5cca41d9b59c9cd814a86bc6


圖7-9 用梯度遞減,更新網絡權值

在我們訓練神經網絡時,損失函數說白了,就是有關“權值參數”的函數。爲了求損失函數的極小值,就不可避免地需要計算損失函數中每一個權值參數的偏導數,這時前文中提到的“梯度遞減”方法就派上用場了。訓練線性單元的梯度遞減算法示意圖如圖7-9所示,圖中的參數η就是“學習率”,它決定了梯度遞減搜索的步長,這個步長“過猶不及”。如果值太小,則收斂慢,如果值太大,則容易越過極值,導致網絡震盪,難以收斂。
圖7-9僅僅給出一個權值變量wiwi的梯度示意圖,而實際上,神經網絡中的參數是非常多的,因此針對損失函數LL的權值向量的梯度mathopwlimitstomathopwlimitsto可以記作:

L(w⃗ )[Lw0,Lw2,...,Lwn](7.4)(7.4)∇L(w→)≡[∂L∂w0,∂L∂w2,...,∂L∂wn]

在這裏,nablaL(mathopwlimitsto)nablaL(mathopwlimitsto)本身就是一個向量,它的多個維度分別由損失函數LL對多個權值參數wiwi求偏導所得。當梯度被解釋爲權值空間的一個向量時,它就確定了L對陡峭上升的方向。
如果需要根據圖7-9所示的公式來更新權值,我們需要一個更加實用的辦法,在每一步重複計算。幸運的是,這個過程並不複雜,通過簡易的數學推導,我們可以得到每個權值分量wiwi更加簡明的計算公式:

Lwi===wi12(Yf(X))2=12dDwi(ydyd)212dD2(ydyd)wi(ydyd)dD(ydyd)wi(ydw⃗ x⃗ d)(7.5)(7.5)∂L∂wi=∂∂wi12(Y−f(X))2=12∑d∈D∂∂wi(yd−yd′)2=12∑d∈D2(yd−yd′)∂∂wi(yd−yd′)=∑d∈D(yd−yd′)∂∂wi(yd−w→⋅x→d)

其中,xidxid表示訓練集合第dd個樣例的輸入分量xixiydyd表示第dd樣例的期望輸出值,ydyd′表示第dd樣例的實際輸出值,這二者的差值就是“損失(loss)”,也稱之爲誤差(error)。有了公式(7.5)做支撐,圖7-9所示的算法就可行之有“章法”了。
如前文所言,對於特定訓練集合,第d個樣本的預期輸出 ydyd 和實際輸出ydyd′,都是“塵埃落定”的常數,對於求權值分量wiwi 的偏導(部分導數)來說,除了作爲變量 的係數可以保留之外,其他統統都可以“看做浮雲化作零”。此外,注意到:

wTxd=w0xd0+w1xd1+...wixdi+...wnxdn(7.6)(7.6)wT⋅xd=w0xd0+w1xd1+...wixdi+...wnxdn

因此,公式(7.5)可進一步化簡爲更加簡潔的公式(7.7):

Lwi=dD(ydyd)(xid)=dD(ydyd)xid(7.7)(7.7)∂L∂wi=∑d∈D(yd−yd′)(−xid)=−∑d∈D(yd−yd′)xid

有了公式(7.7)做支撐,梯度下降的權值更新法則可用如公式(7.8)所示:

wiwiηLwi=wi+ηdD(ydyd)xid(7.8)(7.8)wi←wi−η∂L∂wi=wi+η∑d∈D(yd−yd′)xid

有了前面的知識鋪墊,我們終於可以在下一章談談誤差反向傳播(Back Propagation,BP)算法了。

7.6 小結

在本章中,我們主要講解了梯度的概念。所謂梯度,就是該函數值增長最爲迅猛的方向,然後我們介紹了梯度下降法則。
在下一章中,我們將用最爲通俗易懂的圖文並茂的方式,給你詳細解釋誤差反向傳播(BP)算法。BP算法不僅僅是作爲經典留在我們的記憶裏,而且,它還“歷久彌新”活在當下。要知道,深度信念網(也就是深度學習)之所以性能奇佳,不僅僅是因爲它有一個“無監督”的逐層預訓練(unsupervised layer-wise training),除此之外,預訓練之後的“微調(fine-tuning)”,還是需要“有監督”的BP算法作爲支撐。
由此可見,BP算法影響之深,以至於“深度學習”都離不開它!
“世上沒有白走的路,每一步都算數”。希望你能持續關注。

7.7 請你思考

通過本章的學習,請你思考如下問題:
(1)在前饋神經網絡中,隱含層設計多少層、每一層有多少神經元比較合適呢?我們可以設定一種自動確定網絡結構的方法嗎?
(2)神經網絡具有強大的特徵表徵能力,但“成也蕭何,敗也蕭何”,BP算法常常遭遇“過擬合(overfitting)”,它可能會把噪音當做有效信號,你知道有什麼策略來避免過擬合嗎?

【參考文獻】

[1] 吳軍. 智能時代. 中信出版集團. 2016.8
[2] Hinton G E, Osindero S, Teh Y W. A fast learning algorithm for deep belief nets[J]. Neural computation, 2006, 18(7): 1527-1554.
[3] Williams D, Hinton G. Learning representations by back-propagating errors[J]. Nature, 1986, 323(6088): 533-538.
[4] Rumelhart D E, McClelland J L, PDP Research Group. Parallel Distributed Processing, Volume 1 Explorations in the Microstructure of Cognition: Foundations[J]. 1986.
[5] Tom Mitchell著.曾華軍等譯. 機器學習. 機器工業出版社. 2007.4
[6] Better Explained. Vector Calculus: Understanding the Gradient

文章作者:張玉宏,著有《品味大數據》、本文節選自《深度學習之美》2018年7月電子工業出版社出版。

審校:我是主題曲哥哥。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章