假如我們接到了一個項目:
要讓計算機能夠認知圖片中的動物是不是貓。
該怎么做?
// 如果看不懂就去補概率論、數理統計、離散數學、線性代數啊啊啊啊
顯然我們不能直接拿着一張圖問計算機,這個是不是貓。但是無數巨牛們把它變成了計算機可以理解的問題。
首先從這個問題的問法開始:
【是】 或者 【不是】貓圖。
這個問題只有兩個回答:【是】 以及 【不是】,那么這是一個只有兩種結果的問題。
即:
1、二分分類(Binary Classification)
++二分分類問題,即只輸出真(True)假(False)兩種結果的分類問題++。
我們以一張圖片作為輸入,想要輸出識別此圖片的標簽,如果是貓則輸出1,否則輸出0,並用y來表示輸出的結果。
即輸出只有兩種結果:[y = 0]或者[y = 1]。
這就是一個典型的二分分類問題。
但是作為一個抽象圖片,是無法被計算機認知的,計算機認知的是圖像對應的數據。
來看看一張圖片在計算機中是如何表示的:
它由三個獨立矩陣,分別對應紅(R)、綠(G)、藍(B)三個顏色通道。如果輸入的是一個64x64的圖片,就會有三個64x64的矩陣。上圖中,為了方便,使用了5x4的尺寸。
為了用數學的方式表示這張圖片,我們需要有一個特征向量(feature vector)x,來把這些像素值都提出來,放入其中。
為了能把這些值放入其中,我們像下面這樣定義一個特征向量x:
我們把所有的值提出,如紅色通道中的255、231等,直到列完所有紅色像素,接着是綠色的255、134、220等,把圖片中所有的RGB像素強度值都列出來。
如果圖片是64x64的,那么向量x的總維度(dimension) 就是64x64x3=12288。我們用nx來表示輸入的特征向量x的維度,有時為了簡潔也會用小寫的n來表示。
特征向量x包含了原圖片的所有RGB通道信息,這樣我們就可以用這個特征向量x來代表原圖片。
我們的問題就變成了這樣:
++輸入特征向量x,讓計算機告訴我結果y應該是什么。++
我們現在知道了,“貓圖”問題實際上就是一個二分分類問題。
在該二分分類問題中,我們的目標是訓練出一個分類器,它以圖片的特征向量x作為輸入,預測輸出的結果標簽y是1還是0,也就是預測圖片是不是貓。
那么我們應該用什么樣的方法來實現分類呢?
讓我們先來了解一種方法:
2、線性回歸(Linear Regression)
我們已知輸入特征向量x是一張圖片,我們希望識別出這是(True),或者不是(False) 一張“貓圖”,這是一個二分分類問題。
對於這個“貓圖識別”問題,我們將對輸出結果y的預測值寫作y帽,這個y帽是一個概率值,即當輸入特征x滿足條件時,對輸出結果y的預測值:
這是一個條件概率,也就是說,當輸入特征向量x(給出圖片)時,我們需要y帽能告訴我們y = 1(這個圖是“貓圖”)的概率。
那么如何來計算輸出預測值y帽呢?我們可不可以先從一些圖片中學習,到底什么樣的圖是“貓圖”,從而掌握“識別貓圖”的能力呢?
在這個貓圖例子中,我們有一些已經被標記好是否是貓圖的圖片(即結果y的值已知),我們要通過這些圖來總結“貓圖”的規律。這些圖片的集合,我們稱之為“訓練集(train set)”,因為我們要用這些圖片來訓練算法識別“貓圖”。
訓練集里每一個輸入的圖片特征向量x以及對應的輸出y所組成的(x,y)都可以看做一點,無數訓練集的圖片及其標簽就可以看做是許多(x,y)點的集合。
而我們要做的就是建立一個模型,將點的分布用一條函數線來表示出來。
這樣就可以預測其趨勢,進而對未知結果的測試集(test set) 進行預測,得出預測結果y帽,也就是得出計算機沒見過的圖片,是“貓圖”的概率。
這就是“線性回歸(Linear Regression)”的思想,線性回歸用途最多的地方就是做預測。它可以將離散的點集,擬合成一條最符合趨勢的連續函數線,從而將看似無規律的點,總結成有明確規律的函數公式(當然總結出的公式不一定完美,不過我們還有其他的辦法來評判擬合出的函數的“完美”程度)
總結一下就是:
1、我們已知訓練集圖片的特征向量x,並且已經知道了每個圖片的標簽y。
2、我們需要用這些已知的(x,y)來學習,得出是貓的圖的規律(建立模型,將離散的點擬合成連續的線)。
3、進而就能知道測試集里的圖是不是貓圖(對於一個連續的函數曲線,給出其x值就可得到對應的y值)。
那么我們可以這樣嘗試一下:
這就是一個線性回歸(Linear Regression) 的模型。其中的wT是一個與輸入圖片x的特征向量維數同為nx的向量,b是一個常數值。
實際上這個模型和這個直線方程本質上是相同的,只不過其中變量x的值不是一個實數,而是向量而已:
我們想要得出x和y的函數關系,就需要知道參數a和b的具體值。對應我們的例子來說,就是需要知道向量wT和常數b。
所以我們要做的,就是通過大量的訓練集數據,來得出最合適的wT和b來描述訓練集中x和y的函數關系。
但是這個模型並不好用,因為對於一個圖片,它要么是貓(即y為真,y = 1),要么不是貓(即y為假,y = 0),所以對於y的預測值y帽(圖片是貓圖的概率),它的取值只能在[0,1]區間內。
但是對於這個線性回歸而言,是沒有這個限制的,它可以取非常大的值,甚至可以取負值。
所以簡單的線性回歸方法,不能解決我們這個二分分類問題,它的值域不受限制。
我們希望有一個方法,它能在我們輸入x后,讓輸出的y的取值范圍只在[0,1]區間之內。
那么應該如何做呢?這里我們就需要邏輯回歸(Logistic Regression)。
3、邏輯回歸(Logistic Regression)
邏輯回歸(Logistic Regression)和線性回歸(Linear Regression)有什么不同之處?
前面提到了,線性回歸對於輸出的結果y沒有限制,因此無法用在我們這個問題上。而邏輯回歸是一個二元分類器,所謂二元分類器,即只有真(1)或者假(0)的分類器,其取值區間是[0,1],因此我們要用邏輯回歸的方法,才能得出我們需要的結果。
通過它可以將我們輸入的圖片(向量x),進行二元的分類。
因此有了以下的新方法:
y帽等於sigmoid函數作用於(wT + b)上,其中sigmoid函數等於:
這就像給線性回歸函數套了一層sigmoid函數的“殼”,sigmoid函數是一個單調函數,其圖像是這樣的:
可以看出當x趨於無限大時,函數的值趨近於1,而x趨近於負無窮時,函數的值趨近於0。
這樣我們任意給出輸入x,其輸出y帽要么是[0,1]區間內的某個值,符合我們對y帽是一個概率值的定義,要么極端情況下,y帽趨近於1(幾乎可以肯定是“貓圖”)或者趨近於0(幾乎不可能是“貓圖”),由此我們將y帽的取值很好地限制在了[0,1]區間內,得到了我們想要的數學模型。
這樣我們只需要用訓練集的數據,來得出合適的參數wT和b即可。即通過訓練集,“訓練”計算機識別貓圖。
// 果然核心內容就TM是數學-_-|||
那么這下子問題的本質我們知道了,解決問題的工具我們也有了,可是我們不知道這個邏輯回歸的方法,是不是真的很好解決了問題。
之前也說過,不論線性回歸還是邏輯回歸,都是通過訓練集(已知點集),來擬合出函數線,進而對其趨勢進行預測。既然是擬合曲線,既然是預測,那么很可能是不“完美”的,預測結果甚至可能和實際結果南轅北轍。
我們需要知道通過這個函數線,我們得出的預測值y帽到底和真實的y相差多少,從而能夠判斷出這個辦法的“完美”程度。
4、邏輯回歸的損失函數(Loss Function)、成本函數(Cost Function)
讓我們再來回顧一下邏輯回歸的公式:
為了“訓練”出合適的參數wT和b,我們需要給函數一個含有m個樣本的訓練集,來使我們的每一個(任意第i個)樣本的預測值y帽(i)都盡量與其對應的真實值y(i)相等:
可是我們如何才能知道預測值具體和真實值相差多少呢?
損失函數(loss function),或者說誤差函數(error function),就是用於衡量我們的預測值y帽和實際值y有多接近的函數。
我們經常使用方差的方法來評價誤差,比如這樣定義損失函數,對於m個樣本中的任意第i個樣本,都有:
這是正常情況下我們求方差的方法,但是通常在邏輯回歸中,大家不會這么做。
因為后面我們需要討論優化問題,這樣定義的損失函數是非凸的,它可能同時擁有多個峰(谷),計算機無法像我們人一樣從圖像上一眼看出在某區間內的最值,它需要沿着曲線尋找,這樣就容易在某一個小的峰(谷)處停下,誤以為已經到達了最值點。
因此這樣我們很難找到函數的最值從而得到全局最優解,也就找不到讓我們的邏輯回歸線最合適的參數wT和b。
我們需要定義一個不同的損失函數,它有着與誤差平方相似的作用,但是它會是一個凸函數(convex function)。它只有一個峰(谷),只要達到它在區間內的峰(谷)處,就一定是它的最值點。
在凸函數里我們很容易找到區間內的最值,這樣有利於我們后續進行優化,因此我們像下面這樣定義損失函數,對於訓練集的某一個樣本:
我們先驗證一下這個函數是不是真的能反映y帽與y的差距大小。
當y = 1時:
作為一個衡量y帽與y的差距大小的函數,如果我們希望它盡可能的小,也就是說我們希望:
盡可能大,這個對數函數是一個單調遞增函數,想讓它盡可能大,就意味着我們需要y帽盡可能大,而y帽的取值區間在[0,1]之間,因此y帽越接近於1,這個函數越小。
也就是說,當y帽 = y = 1時,這個衡量y帽與y的差距大小的函數等於零,對於y = 0時也同理。
而相反的,y帽與y的差距越大時,這個函數的值越大。實際上不僅對於0,1這樣的特殊點,對於所有的點,這個函數都有這樣的性質。
於是我們發現這個函數能夠很好的衡量y帽與y的差距,並且最重要的,它是一個凸函數,非常有利於我們后續的優化,因此我們將選用它作為我們的損失函數,這個函數在統計學上有一個名字,叫做:
對數損失函數(logarithmicloss function),或者數似然損失函數(log-likelihood loss function)。
對數損失函數是對似然函數取對數得到的一種函數,似然函數是一種關於統計模型參數的函數。給定輸出x時,關於參數θ的似然函數L(θ|x)(在數值上)等於給定參數θ后變量X的概率:L(θ|x)=P(X=x|θ)。而取對數變成對數損失函數,是為了讓其變成凸函數,方便后續優化時尋找全局最優解。
科普:幾種常見的損失函數 —— 損失函數有幾種?他們都有什么特點?
擴展:邏輯回歸為什么使用對數損失函數 —— 為什么對於伯努利分布的邏輯回歸模型,對數損失函數和似然函數是等價的?
但是這僅僅衡量了某一對預測值y帽(i)和其對應的真實值y(i) 的差距,訓練集中有很多對y帽(i)、y(i),損失函數並不能表現出樣本總體的情況。
我們需要知道樣本的全局損失,因此我們需要成本函數(cost function):
其中m是用於訓練的樣本的個數,可以看出,成本函數是對損失函數的累加平均,用於反映樣本的總體誤差,衡量了樣本總體的表現。
這是一個wT和b的二元函數,因為對於任意給定的輸入x,我們得到的預測值,y帽,只取決於我們訓練出的wT和b這兩個參數。
因此實際上評價y帽(i)的表現,就是評價我們訓練出的wT和b這兩個參數的表現,所以它是關於wT和b的函數。
經過我們訓練的邏輯回歸模型,其wT和b參數應滿足在一定條件下,令成本函數盡可能的小,這樣我們得到的模型,才能更准確的進行預測。
我們現在知道了評價每個預測值y帽(i)的損失函數,以及評價樣本總體誤差的成本函數。
他們可以用來衡量模型中wT和b參數效果的好壞。
這就像我們學會了給我們訓練出的模型打分,那么我們應該如何提高我們模型的分數呢?
為了優化我們的模型,我們需要了解:
5、梯度下降法(Gradient Descent)
回顧一下我們的成本函數:
對於樣本中的每一個預測值y帽(i),我們都把它和其對應的真實值y(i)進行了比較,進而衡量了參數wT和b的效果。
之前說了,成本函數描述了我們樣本總體的預測值與真實值的誤差大小,我們當然想要預測值越准確越好。
所以我們需要找到一組參數wT和b,使得成本函數J(wT,b)盡可能的小。
成本函數J(wT,b)是一個二元函數,在三維空間中它應該是一個曲面的形式,我們可以畫出它大概的函數圖像。
這個圖像的X軸與Y軸,分別是參數wT和b,而Z軸則是成本函數J(wT,b)的值,這樣我們就能很直觀的看出,在不同的wT和b點出,成本函數的取值大小。
得益於我們之前使用了對數損失函數,而不是簡單的方差來衡量預測值與真實值的誤差,我們得到的函數圖像是一個下凸的曲面。
它是一個凸函數,就像一個大碗,因此我們能從圖像中很輕松的找到成本函數J(wT,b)的最小值點,即圖像中的低谷處。
雖然肉眼很容易觀察到,但是我們應該用什么數學方法來准確的找到這個點呢?
這就需要梯度下降法(Grandient Descent)。
如果成本函數真的是一個大碗,那么如果我們在碗邊上放一個小球,這個小球就會沿着碗邊滾下去,最后小球一定會停在碗底,到達碗內的最低點。
梯度下降法就是這樣的思想:我們選定一個初始點,然后找到下降的最陡的方向,向着這個方向走一步,到達第二點。然后再尋找下降最陡的方向,向着這個方向走一步…… 如此循環,最終接近甚至達到函數的最值處。
讓我們先從一個簡單的一元函數開始,來看看梯度下降法具體是怎么做的。
我們假設有一個圖像是這樣的一元函數f(x):
我們選定一點(x0,f(x0))作為初始點,然后用這樣的方法到達下一個點(x1,f(x1)):
其中,x0是初始值,α是一個被稱為學習率(learning rate)或者步長的參數,它決定了我們每一步跨越的幅度,也就是決定了我們滾落到谷底處的速度。df(x0)/dx則是函數f(x)在x0處的導數值,也就是這一點處的斜率,它描述了在當前位置下,我們應該朝着哪個方向移動。
這樣我們找到了下一點的橫坐標x1,那么下一點的坐標就是(x1,f(x1))。
從這個式子中我們可以看出,當導數大於零,即點在函數單調遞增的區間上時:
這種情況下得到的x1 < x0,新的點(x1,f(x1))是在(x0,f(x0))的左側,我們向着函數下降的方向前進了一步。
而當導數小於零是,即點在函數的單調遞減區間上時,情況正好相反,(x1,f(x1))在(x0,f(x0))的右側,還是向着函數下降的方向前進了一步。
不論我們在函數曲線額哪一側,我們總向着低谷所在的方向前進。
這其中,當α越大時,x1與x0便相距越遠,我們所走的“一步”的步長就越大。
現在我們到了一個新的點(x1,f(x1)),從這個點出發,重復上面的過程:
如此循環、迭代,最終我們就能逼近函數的最低點,從而得到最優解。
但是在梯度下降法中,步長α的選擇十分關鍵,如果我們選擇的步長α很小,那么我們需要很多次迭代才能最終達到最優解,所花費的時間可能非常非常長,而如果步長α選擇的過大,很有可能出現下面的情況,“一步跨過”最優解,從而導致結果不收斂,甚至發散。
這個圖是其中一種步長α過大的情況。在點(xn,f(xn))處,通過計算我們能知道下一點(xn+1,f(xn+1))應該在這一點的左側,但是因為步長α設置的過大,我們一下子跨過了最低點,到了單調遞減區間,並且新點處f(xn+1)>f(xn),在這里我們再次計算后得知下一點(xn+2,f(xn+2))應該在(xn+1,f(xn+1))的右側,然而因為步長過大,我們又一次跨過了最低點到了(xn+2,f(xn+2)),並且f(xn+2)>f(xn+1)。這導致了一個嚴重的后果,就是在這種情況下,我們不但得不到收斂的結果從而逼近最低點,反而得到了一個發散的結果,離最優解越來越遠。
梯度下降法在越靠近最優解點處,由於梯度的降低,我們的靠近速度將越來越慢,而如果步長α選擇過小,將導致我們短時間內很難靠近最優解點。
接下來我們擴展到多維空間中,來看看對於一個凸曲面,梯度下降法是如何做的,假設我們有一個二元函數f(x,y),我們先定義叫做梯度的量:
梯度是一個向量,它的兩個分量分別是兩個變量的偏導數。其意義是在該點處,上升最快的方向。對於之前的一元函數而言,其梯度就是所在點的切線方向。
來看一個實例,比如我們假設f(x,y) = x3 + y2,那么它的梯度應該是:
假設我們現在在這個函數x = 1,y = 2處,那么該處的梯度就是:
也就是說,對於函數f(x,y) = x3 + y2,它從x = 1,y = 2處出發,沿着向量<3,4>的方向上升最快。
那么此時對於一個曲面,用梯度下降法從(x1,y1,f(x1,y1))的公式是:
其中梯度是上升最快的方向向量,因此我們需要添加負號,才是我們要求的下降方向。
對於更高維度依舊如此,只是無法簡單的從圖像表示出來,但是做法是相同的。
相對應的梯度是:
因此,假設初始點,以及初始點處的梯度是:
那么由梯度下降法,第二點的坐標就是:
不斷迭代下去,最終就能得到函數的全局最優解。
回到“貓圖識別”的例子,我們想要利用梯度下降法進行優化的,是我們的成本函數。
我們想要求得一組wT和b使得我們的成本函數最小。但是這里wT是一個向量,而非一個實數。
輸入的特征向量x也是一個nx維向量:
實際上我們的預測值可以寫成:
因此最終成本函數可以寫成:
它的梯度是:
然后我們就可以用梯度下降法求出全局最優解,從而找到最合適的參數wT以及b,達到“訓練”的效果。
小結:
在“貓圖識別”例子中,我們解決問題的過程是這樣的:
- 問題本質:二分分類
- 解決方法:邏輯回歸
- 效果評判:損失函數及成本函數
- 進行優化:梯度下降法
內容的一些符號說明
我們用一對(x,y)來表示一個單獨的樣本,x是nx維的特征向量,標簽y值為0或1。
訓練集是一個包含m個樣本的集合,我們用(x(1),y(1))來表示樣本1的輸入和輸出,(x(2),y(2))表示樣本2的輸入和輸出,以此類推。這些就表示訓練樣本集整體,m為訓練樣本個數,有時候為了強調,也寫作mtrain,因為有時候我們需要用mtest來表示測試集樣本數量。
最后,我們需要用更緊湊的符號表示訓練集。
我們用大寫X來表示一個矩陣,它由訓練集中的x1、x2這些組成,我們將x(1)放進矩陣的第一列,x(2)放進矩陣的第二列,以此類推,最后得到矩陣X,這個矩陣有m列,矩陣高度為x(m)的維數nx,在矩陣X中,我們將訓練樣本x(m)作為行向量堆疊,而不是作為列向量堆疊,是因為構建神經網絡時,這樣做會讓構建過程簡單得多。
/↑↑↑ 為什么? 答:可以使用.np函數直接運用矩陣進行計算,省去for遍歷循環,提高效率。 2018.12.12 /
由此,X是一個nx x m的矩陣。為了方便構建一個神經網絡,將標簽y(m)也放入各列中,組成一個矩陣Y。
在python實現中,X.shape()是一個方法,其作用是輸出矩陣的維度,因此X.shape = (nx,m),Y.shape = (1,m)。