前言:機器學習是目前最激動人心的技術之一,你也許沒有意識到自己每天都會多次用到學習算法,每當你使用Google或百度等搜索引擎時,它總是能給出令人滿意的結果,原因就是Google或百度等公司使用的學習算法,學會了如何給網頁排序。每次你使用Facebook或蘋果的相片分類功能,它能識別出你朋友的照片,這也是機器學習。每當你閱讀郵件時,你的垃圾郵件過濾器會幫助你過濾掉大量的垃圾郵件,這也是學習算法。
那麼爲什麼機器學習現在如此流行?實際上機器學習是從AI即人工智能發展出來的一個領域。我們想建造智能機器,然後發現我們可以通過編程讓機器做一些基本的事情。比如,如何找到從A到B的最短路徑。但是大多數情況下,我們不知道如何編寫AI程序來做更有趣的事情。如網頁搜索,相片標記,反垃圾郵件,人們認識到做到這些事情唯一的方法,就是使機器自己學習如何去做。因此,機器學習是爲計算機開發的一項新功能,如今它涉及工業和基礎科學中的許多領域。例如數據挖掘,我們無法手動編寫的程序(例如無法編寫程序使直升飛機自己飛行,唯一可行的就是讓計算機自己學習駕駛直升飛機)
1. 機器學習介紹:
1.1 什麼是機器學習(Machine Learning)?
即使是在機器學習從業者中,也沒有對機器學習的統一定義,一個比較早期的定義是由Arthur Samuel在1959年給出的,他將機器學習定義爲:在沒有明確設置的情況下,使計算機具有學習能力的研究領域。這是一個不正式,也是比較陳舊的一個定義。
Samuel編寫了一個跳棋遊戲的程序,這個跳棋遊戲令人驚訝之處在於,Samuel自己並不是一個玩跳棋的高手,他所做的是使程序與自己對弈幾萬次,通過觀察哪些佈局容易贏,哪些佈局容易輸,一段時間後,跳棋遊戲程序就學到了什麼是好的佈局,什麼是不好的佈局,最終程序學會了玩跳棋,比Samuel玩得還好。
吳恩達教授在卡內基梅隆大學的一個朋友Tom Mitchell在1998年提出了一個更新的定義:計算機程序從經驗E中學習,解決某一任務T,進行某一性能度量P,通過P測定在T上的表現因經驗E而提高。對於上述的跳棋遊戲,經驗E就是程序與自己下幾萬次跳棋,任務T就是玩跳棋,性能度量P就是與新對手玩跳棋時贏的概率。
1.2 機器學習分類:
目前有各種不同類型的學習算法,最主要的兩類是監督學習(supervised learning)和無監督學習(unsupervised learning),通俗來講,監督學習就是我們會教計算機做某件事情。而在無監督學習中,我們讓計算機自己學習。
Supervised Learning:
在給出監督學習的定義前,先來看一個例子
假設你擁有下面的這些房價數據,圖表上的每一個點代表一次交易,橫座標代表交易房屋的佔地面積,縱座標代表交易房屋的價格(單位是千美元)。
現在讓你預測一個750平方英尺的房屋的交易價格可能是多少?學習算法能做到的一件事就是根據數據畫一條直線來擬合這些數據,然後根據這條直線來進行預測。但是這不是能使用的唯一的學習算法,在此例子中,可能會有一個更好的學習算法,例如用二次函數或二階多項式看起來能夠模擬得更好。
監督學習是指,我們給算法一個數據集,其中包含了正確答案,也就是說我們給它一個房價數據集,在這個數據集中的每個樣本,我們都給出正確的價格,即這個房子的實際賣價,算法的目的就是給出更多的正確答案,例如通過算法預測房價爲750平方英尺的房子的價格。用更專業的術語來定義,這個問題也被稱爲迴歸問題,迴歸問題就是指預測一個連續的值。
下面是另一種監督學習的例子:
假設你想看醫療記錄,並且設法預測乳腺癌是惡性的還是良性的,假設某人發現了一個乳腺腫瘤,即乳房上的腫塊,惡性腫瘤就是有害的且危險的,良性腫瘤就是無害的。橫軸是腫瘤的尺寸,縱軸的1代表惡性,0代表良性。機器學習的問題就是讓你根據粉色點所處的腫瘤尺寸,計算腫瘤是良性的還是惡性的概率。用更專業的術語來說,這就是一個分類問題,分類是指設法預測一個離散值。這個例子中,只有一個特徵或者說是隻有一個屬性,即通過腫瘤的大小這一個屬性來預測腫瘤是惡性的還是良性的。
在其他的機器學習問題中,可能會有多個特徵,多個屬性,例如現在假設我們不僅知道腫瘤的大小,還知道病人的年紀。以O代表良性腫瘤,用X代表惡性腫瘤。橫軸代表腫瘤的大小,縱軸代表病人的年紀。
對於這種有多個特徵的數據集,學習算法能夠做的就是在數據上畫出一條直線,設法將惡性腫瘤和良性腫瘤分開。這樣對於粉色的點,通過這種方式,你的學習算法就會認爲,這個腫瘤位於良性區域,因此這個腫瘤是良性的機率比惡性的大。
- 在分類算法中目標變量的類型通常是標稱型(如:真與假),而在迴歸算法中通常是連續型(如:1~100)。
Unsupervised Learning:
對於監督學習中的每一個樣本,我們已經被清楚地告知了什麼是所謂的正確答案,即它們是良性還是惡性,而在無監督學習中,我們所用的數據沒有任何的標籤,或者是都具有相同的標籤或者都沒有標籤,我們拿到這個數據集,但我們卻不知道要拿它來做什麼,也不知道每個數據點究竟是什麼,我們只是知道有一個這樣的數據集,例如下面這幅圖,對於給定的數據集,無監督學習算法可能判定該數據集包含兩個不同的簇,無監督學習算法可以把這些數據分成兩個不同的簇,這就是聚類算法。聚類算法被應用在很多地方,其中一個應用聚類算法的例子就是谷歌新聞,谷歌新聞所做的就是每天去網絡上,收集幾萬條甚至幾十萬條新聞,然後將它們組合成一個個新聞專題,有關同一主題的新聞被顯示在一起。
其實聚類算法和無監督學習算法也可應用到許多其他的問題,例如它在基因組學中的應用,下圖是一個DNA微陣列數據的例子,給定一組不同的個體,對於每個個體,檢測他們是否擁有某個特定的基因,也就是檢測特定基因的表達程度,這些紅,灰,綠等顏色展示了不同個體擁有特定基因的程度,然後你需要做的就是運行一個聚類算法,把不同的個體歸入不同的類也就是歸爲不同類型的人,這就是無監督學習。因爲我們只知道這裏有一堆數據,但是不知道這些數據是什麼,不知道每一個是哪一個類型,甚至不知道有哪些類型。因爲我們沒有把數據集的所謂的“正確答案”給算法,所以這就是無監督學習。
2. Linear regression with one variable(單變量線性迴歸):
2.1 Model representaion(模型表達):讓我們先來看之前那個預測住房價格的例子,假設你一個朋友有一套大小爲1250平方英尺大小的房子,他想要讓你幫他預測這個房子能賣多少錢?你可以用一條直線來擬合這組數據,根據這個模型,你可以告訴你的朋友,他的房子也許可以賣到220000美元左右。這是一個監督學習算法的例子,它之所以是監督學習,是因爲每一個例子都有一個“正確的答案”,也就是說我們知道數據集中所賣的房子的實際大小和價格,而且這也是一個迴歸問題的例子,迴歸是指預測一個具體的數值輸出,也就是房子的價格。另一種最常見的監督學習問題被稱爲分類問題,用來預測離散值的輸出,例如我們觀察腫瘤,並試圖判斷它是良性的還是惡性的。
更正式一點說,在監督學習裏,我們有一個數據集,它被稱爲一個訓練集(Training Set),以住房價格爲例,我們有一個房價的訓練集,我們的工作是從這個數據中,學習如何預測房價。
下面將定義一些符號將更有利於理解:
m:表示訓練樣本的數量,也就是訓練集中的實例數量。
x:代表輸入變量或者說是特徵。
y:代表輸出變量也就是要預測的目標變量。
(x,y):表示一個訓練樣本。
(x(i),y(i) ):代表第i個訓練樣本。(這個i是訓練集中的一個索引,指的是表格中的第i行)。
監督學習算法的工作流程:
向學習算法提供訓練集,比如說房價訓練集,學習算法的任務是輸出一個函數,通常用小寫字母h表示,h代表假設函數,在房價預測的例子中假設函數的作用是,把房子的大小作爲輸入變量,將它作爲x的值,然後輸出這個房子預測的y值,h是一個從x映射到y的函數。在這個例子中,假設函數是預測y是關於x的線性函數。hθ(x)也可以簡寫爲h(x)。
2.2 Cost funcion(代價函數):
代價函數是爲了幫助我們弄清楚如何把最有可能的直線與我們的數據相擬合。
例如我們有一個這樣的訓練集,m代表了訓練樣本的數量,假設m=47,我們的假設函數是
這些θ0和θ1我們把它們稱爲模型參數,我們需要做的就是通過選擇合適的θ0和θ1,使得誤差儘量的小。選擇不同的θ0和θ1,會得到不同的假設函數,例如可以選擇下圖中的這些θ0和θ1。
在線性迴歸中,我們有一個訓練集,我們要做的就是得出θ0和θ1這兩個參數的值,使得假設函數所表示的直線儘量地與這些數據點能夠很好的擬合,例如就像下圖中的這一條直線,那麼如何求出θ0和θ1的值來使它很好地擬合數據呢?
我們的想法是,我們需要選擇能使h(x),也就是輸入x時,我們預測的值最接近該樣本對應的y值的參數θ0和θ1。所以,在我們的訓練集中我們會得到一定數量的樣本,我們知道x表示賣出哪所房子,並且知道賣出的這所房子的實際交易價格。所以我們要儘量選擇合適的參數值,使得在訓練集中,對於給出的訓練集中的x值,我們能夠合理準確地預測y的值。接下來給出標準的定義,在線性迴歸中,我們要解決的實際上是一個最小化的問題,我們要做的就是儘量減少假設輸出與房子的真實交易價格之間的差的平方。所以我們要做的就是對所有的訓練樣本進行一個求和,將第i號對應的預測結果減去第i號房子的實際交易價格所得的差的平方相加得到一個總和,而我們希望這個總和能夠儘可能的小,也就是預測值和實際值的差的平方誤差和或者說預測價格和實際賣出價格的差的平方。爲了讓表達式的數學意義變得容易理解一點,實際上考慮的是所求誤差和的1/m,也就是我們要嘗試儘量減少平均誤差,也就是儘量減少其1/(2*m),即通常是平均誤差的一半,這只是爲了使數學意義更直白一些,因此對這個求和值的1/2求最小值,也能夠得到相同的θ0和θ1。所以代價函數可以表示爲,所以我們要做的就是對J(θ0,θ1)求最小值,這就是代價函數。代價函數也被稱作平方誤差函數,有時也被稱爲平方誤差代價函數,事實上,之所以要求出誤差的平方和,是因爲誤差平方代價函數對於大多數問題,特別是迴歸問題,都是一個合理的選擇,當然還有其他的代價函數也能很好地發揮作用,但是平方誤差代價函數可能是解決迴歸問題最常用的手段了。
爲了更好地使代價函數J可視化,使用一個簡化的假設函數h,設θ0=0,則h(x) = θ1 * x。使用簡化的代價函數便於更好的理解代價函數的概念。
下圖(左)中的紅色X代表房子實際交易價格,θ0=0時,假設函數是過原點的直線,對於每一條假設函數,它的預測值和實際值的差的平方也就是下圖(左)中藍色豎線的長度的平方。在下圖(右)做出相應的代價函數J(θ1)的圖像,顯然,當θ1=1時,J(θ1)最小。
學習算法的優化目的是找到一個最優的θ1,使得J(θ1)最小化,顯然由圖可知當θ1=1時,J(θ1)取得最小值。 我們繪製一個等高線圖,三個座標分別爲θ0和θ1和J(θ0,θ1)。如下圖所示,這是一個類似碗狀形狀的圖像,豎直高度即是J(θ0,θ1)。
也可以在二維圖中用下圖進行表示,每一個橢圓形顯示了一系列J(θ0,θ1)值相等的點,例如下圖右中的三個點,他們的J(θ0,θ1)值相等,這些同心橢圓的中心點(碗狀底部)就是最小值。
2.3 Gradient descent(梯度下降法):
梯度下降法可以最小化代價函數J。爲了簡潔起見,假設這裏只有兩個參數θ0和θ1,梯度下降的思路是先給θ0和θ1賦初值,到底需要賦什麼值其實並不重要,但通常的選擇是讓θ0設爲0,θ1也設爲0,然後不停地一點點地改變θ0和θ1來使得J(θ0,θ1)變小,直到我們找到J(θ0,θ1)的最小值或者局部最小值。
讓我們通過一些圖片來看看梯度下降法是如何工作的,假設要讓下圖這個函數值最小化。
首先對θ0和θ1賦以某個初值,也就是對應於從這個函數表面上的某個點出發,不管θ0和θ1的取值是多少,假設將它們都初始化爲0,但有時你也可以把它們初始化爲其他值。現在把這個圖像想象爲一座山,想象一下你正站在下圖所示點處。在梯度下降算法中,我們要做的就是旋轉360度,看看周圍,並問自己,如果在某個方向上走一小步,朝哪個方向走才能儘快走下山?
每次都往傾斜度最大的方向邁一小步,直到到達局部最低點,所以所走路徑大致爲下圖。
梯度下降有一個有趣的特點,對於不同的起始點,可能會得到不同的局部最優解,例如下圖。
上圖就是梯度下降算法的數學定義,這個公式有很多細節問題,首先注意這個符號“:=”,我們使用“:=”表示賦值,這是一個賦值運算符,例如a:=b,在計算機中,這意味着將b的值賦給a。而如果寫a=b,那麼這是一個真假判定,其實就是在斷言a的值等於b的值。這裏的α是學習率(learning rate),α用來控制梯度下降時,我們需要邁出多大的步子。如果α值很大,梯度下降就很迅速,也就是我們會用大步子下山。如果α值很小,我們會用小碎步下山。還有一個關於梯度下降法的細節,我們要更新θ0和θ1,當j=0和j=1時,會產生更新,實現梯度下降算法的微妙之處是,對於這個表達式,我們需要同時更新θ0和θ1,θ0更新爲θ0減去某項,θ1更新爲θ1減去某項,實現方法是計算表達式等式右邊的部分,然後同時更新θ0和θ1。事實發現,同步更新是更自然的實現方法。如果用非同步更新去實現算法,可能也會正確工作,但是這種方法並不是人們通常用的那個梯度下降算法,而是具有不同性質的其他算法。由於各種原因,這其中會表現出微小的差別。所以我們需要做的就是在梯度下降算法中實現同步更新。
接下來進一步解釋這個數學定義:
這是關於實數θ1的代價函數J(θ1),橫軸表示θ1,縱軸表示J(θ1)。第一幅圖中從θ1處開始梯度下降,梯度下降要做的就是不斷更新θ1。在微積分中這一點的導數其實就是這一點的切線,就是那條紅色的直線,這條直線的斜率爲正,也就是說它有正導數,所以θ1就更新爲θ1-α*(一個正數),α也就是學習速率永遠是一個正數,所以我們就相當於將θ1左移,使θ1變小了。我們看到這麼做是對的,因爲往左移實際上是在向最低點靠近。在第二幅圖中,用同樣的代價函數J(θ1),再作出同樣的圖像。而這次把參數初始化到左邊那個點,現在的導數項也就是這點的切線的斜率,這條切線的斜率是負的,所以這個函數有負導數,這個導數項是小於0的,所以當更新θ1時,θ1被更新爲θ1-α*(一個負數),所以實際上θ1在增大,也就是向右移動,也是在接近最低點。這就是導數項的意義。
接下來看一看學習速率α的作用:
如果α太小,就會用一個比較小的係數來更新,梯度下降可能就會很慢,就需要很多步才能到達全局最低點。
如果α太大,如圖所示,那麼梯度下降可能會越過最低點,甚至可能無法收斂或者發散。
如果θ1已經處在一個局部最優點,局部最優點的導數爲0,而在梯度下降更新過程中,θ1更新爲θ1-α*0,所以θ1將不會改變。即如果參數已經處於局部最低點,那麼梯度下降法更新其實什麼都沒做,它不會改變參數的值,它使解始終保持在局部最優點。這也解釋了,即使學習速率α保持不變,梯度下降法也可以收斂到局部最低點的原因。
我們來看一個例子:
首先在品紅色的那個點初始化θ1的值,然後用梯度下降法一步步更新,你會發現,越接近最低點,斜率越小,導數也就越小,逐漸接近於0。所以隨着梯度下降法的進行,移動的幅度會自動變得越來越小,直到最終移動幅度非常小,你會發現,已經收斂到了局部最小值,這就是梯度下降的運行方式。所以實際上沒有必要再另外減小α,這就是梯度下降算法。你可以用它來嘗試最小化任何代價函數J,而不只是線性迴歸中的代價函數J。
Gradient descent for linear regression:
現在我們將梯度下降和線性迴歸結合,得到線性迴歸的算法,它可以用直線模型來擬合數據。下圖是梯度下降法和線性迴歸模型(包括線性假設和平方差代價函數),我們要做的就是將梯度下降法應用到最小化平方差代價函數。
爲了應用梯度下降法,關鍵步驟就是求出左邊式子中的導數項。因此我們需要知道這個偏導數項是什麼,J(θ0,θ1)對θ0和θ1的偏導數如下:
那麼梯度下降算法就可以寫成下面這種形式,這就是線性迴歸算法:
這個算法也叫批量梯度下降法(batch gradient descent),就是不斷重複這個步驟,直到得到最優值。
執行梯度下降時,根據你的初始值的不同,可能會得到不同的局部最優解。
但線性迴歸的代價函數總是一個弓狀函數,術語叫做凸函數。這個函數沒有局部最優解,只有一個全局最優解。當你計算這種代價函數的梯度下降的時候,只要你使用線性迴歸,它總會收斂到全局最優,因爲沒有全局最優解之外的局部最優解。