機器學(xué)習(xí)原來如此有趣!全世界最簡單的機器學(xué)習(xí)入門指南
這篇文章的目標(biāo)是讓所有人都能看懂,所以文章中將會有很多的概括,但是誰在意呢?如果這篇文章能引起一部分人對機器學(xué)習(xí)的興趣,那我的使命就達成了。
機器學(xué)習(xí)是什么?
機器學(xué)習(xí)是一種概念:不需要寫任何與問題有關(guān)的特定代碼,泛型算法(Generic Algorithms)就能告訴你一些關(guān)于你數(shù)據(jù)的有趣結(jié)論。不用編碼,你將數(shù)據(jù)輸入泛型算法當(dāng)中,它就會在數(shù)據(jù)的基礎(chǔ)上建立出它自己的邏輯。
例如,有一種算法叫做分類算法。它可以將數(shù)據(jù)放進不同的分組。用于識別手寫數(shù)字的分類算法也可以用于區(qū)分垃圾郵件和非垃圾郵件,且不需要改變?nèi)魏未a。算法是同一個,但是輸入了不同的訓(xùn)練數(shù)據(jù),所以得出不同的分類邏輯。
機器學(xué)習(xí)算法是個黑盒,它可以重復(fù)使用于很多不同的分類問題。
機器學(xué)習(xí)是覆蓋許多種泛型算法的涵蓋性術(shù)語。
兩種類型的機器算法
你可以將機器學(xué)習(xí)算法分成兩大類別:監(jiān)督式學(xué)習(xí)(supervised Learning)和非監(jiān)督式學(xué)習(xí)(unsupervised Learning)。要區(qū)分兩者很簡單,但也非常重要。
監(jiān)督式學(xué)習(xí)
假設(shè)你是一名房地產(chǎn)經(jīng)紀(jì)人,你的生意蒸蒸日上,因此你雇了一批新員工來幫忙。但是問題來了——雖然你可以一眼估算出房子的價格,但新員工卻不像你這樣經(jīng)驗豐富,他們不知道如何給房子估價。
為了幫助你的新員工(也許就是為了給自己放個假嘻嘻),你決定寫一個可以根據(jù)房屋大小、地段以及同類房屋成交價等因素來評估一間房屋的價格的小軟件。
近三個月來,每當(dāng)你的城市里有人賣了房子,你都記錄了下面的細節(jié)——臥室數(shù)量、房屋大小、地段等等。但最重要的是,你寫下了最終的成交價:
這就是我們的「訓(xùn)練數(shù)據(jù)」。
使用這些訓(xùn)練數(shù)據(jù),我們要來編寫一個能夠估算該地區(qū)其他房屋價值的程序:
我們希望使用這些訓(xùn)練數(shù)據(jù)來預(yù)測其他房屋的價格。
這就是監(jiān)督式學(xué)習(xí)。你已經(jīng)知道了每一棟房屋的售價,換句話說,你已經(jīng)知道了問題的答案,并且可以反向找出解題的邏輯。
為了編寫你的軟件,你將包含每一套房產(chǎn)的訓(xùn)練數(shù)據(jù)輸入到你的機器學(xué)習(xí)算法當(dāng)中去。算法會嘗試找出需要做哪些數(shù)學(xué)運算來得出價格。
這就好像是你已經(jīng)知道了數(shù)學(xué)測試題的答案,但是算式中的運算符號都被擦去了:![]()
天啊!一個陰險的學(xué)生擦去了參考答案上的算術(shù)符號!
你能從這張圖里看出來測驗中的數(shù)學(xué)題是怎樣的嗎?你知道自己應(yīng)該對左邊的數(shù)字「做些什么」,才能得到右邊的答案。
在監(jiān)督式學(xué)習(xí)中,你讓計算機為你算出這種關(guān)系。而一旦你知道了解決這類特定問題所需要的數(shù)學(xué)方法后,你就可以解答其它同類問題了!
非監(jiān)督式學(xué)習(xí)
讓我們回到房地產(chǎn)經(jīng)紀(jì)人的例子。如果你不知道每棟房子的售價怎么辦?即使你所知道的僅僅是每棟房屋的大小、位置等信息,你也可以搞出一些很酷炫的花樣來。這就是我們所說的非監(jiān)督式學(xué)習(xí)。
即使你并不是在嘗試預(yù)測未知的數(shù)據(jù)(如價格),你也可以運用機器學(xué)習(xí)做一些有意思的事。
這就有點像有人給你一張紙,上面寫了一列數(shù)字,然后說:「我不太清楚這些數(shù)字有什么意義,但也許你能找出些規(guī)律或是把它們分類什么的——祝你好運!」
所以該怎么處理這些數(shù)據(jù)呢?首先,你可以用個算法自動從數(shù)據(jù)中劃分出不同的細分市場。也許你會發(fā)現(xiàn),當(dāng)?shù)卮髮W(xué)附近的購房者特喜歡戶型小、臥室多的房子,而郊區(qū)的購房者偏好三臥室的大戶型。了解這些不同消費者的喜好可以直接幫助你的營銷。
你還可以做件很酷炫的事,就是自動找出非同尋常的房屋。這些與眾不同的房產(chǎn)也許是奢華的豪宅,而你可以將最優(yōu)秀的銷售人員集中在這些地區(qū),因為他們的傭金更高。
在接下來的內(nèi)容中我們主要討論監(jiān)督式學(xué)習(xí),但這并不是因為非監(jiān)督式學(xué)習(xí)比較沒用或是無趣。實際上,隨著算法的改良,非監(jiān)督式學(xué)習(xí)正變得越來越重要,因為即使不將數(shù)據(jù)和正確答案聯(lián)系在一起,它也可以被使用。[2]
太酷炫了,但是估算房價真能被看作「學(xué)習(xí)」嗎?
作為人類的一員,你的大腦可以應(yīng)付絕大多數(shù)情況,并且在沒有任何明確指令時也能夠?qū)W習(xí)如何處理這些情況。如果你做房地產(chǎn)經(jīng)紀(jì)人時間足夠長,你對于房產(chǎn)的合適定價、房屋的最佳營銷方式以及客戶會感興趣類型等等都會有一種本能般的「感覺」。強人工智能研究的目標(biāo)就是要計算機復(fù)制這種能力。
但是目前的機器學(xué)習(xí)算法還沒有那么強大——它們只能在非常特定的、有限的問題上有效。也許在這種情況下,「學(xué)習(xí)」更貼切的定義是「在少量樣本數(shù)據(jù)的基礎(chǔ)上找出一個公式來解決特定的問題」。
但是「機器在少量樣本數(shù)據(jù)的基礎(chǔ)上找出一個公式來解決特定的問題」不是個好名字。所以最后我們用「機器學(xué)習(xí)」取而代之。
當(dāng)然了,如果你是在 50 年后的未來讀的這篇文章,而我們?nèi)祟愐惨呀?jīng)得出了強人工智能的算法的話,那這篇文章看起來就像個老古董了。那樣的話,就別讀了,去讓你的機器傭人給你做份三明治吧,未來的人類。
讓我們愉快地寫代碼吧!
所以,你打算怎么寫上面例子中評估房價的程序呢?在往下看之前先思考一下吧。
如果對機器學(xué)習(xí)一無所知,你很有可能會嘗試寫出一些基本規(guī)則來評估房價,如下:
def estimate_house_sales_price(num_of_bedrooms, sqft, neighborhood):
price = 0
# 在我這地方,每平方英尺房屋均價是 200 美元
price_per_sqft = 200
if
neighborhood == "hipsterton":
#
但是有些地段房價會貴一點
price_per_sqft = 400
elif neighborhood == "skid row":
#
有些地段房價便宜點
price_per_sqft = 100
# 我們先按面積大小估計房屋價格基準(zhǔn)
price = price_per_sqft * sqft
# 現(xiàn)在根據(jù)臥室數(shù)量微調(diào)價格
if
num_of_bedrooms == 0:
#
工作室類型的公寓比較便宜
price = price?—?20000
else:
#
臥室數(shù)量越多,通常房價越貴
price
= price + (num_of_bedrooms * 1000)
return price
假如你像這樣瞎忙幾個小時,最后也許會得到一些像模像樣的東西。但是你的程序永不會完美,而且當(dāng)價格變化時很難維護。
如果能讓計算機找出實現(xiàn)上述函數(shù)功能的辦法,豈不更好?只要返回的房價數(shù)字正確,誰會在乎函數(shù)具體干了些什么呢?
def
estimate_house_sales_price(num_of_bedrooms, sqft, neighborhood):
price = <計算機,請幫我算點數(shù)學(xué)題>
return price
考慮這個問題的一種角度是將價格看作一碗美味的湯,而湯的原材料就是臥室數(shù)量、面積和地段。如果你能算出每種原材料對最終的價格有多大影響,也許就能得到各種原材料混合形成最終價格的具體比例。
這樣可以將你最初的程序(全是令人抓狂的 if else 語句)簡化成類似如下的樣子:
def estimate_house_sales_price(num_of_bedrooms, sqft, neighborhood):
price = 0
# 一小撮這個
price += num_of_bedrooms * .841231951398213
# 一大撮那個
price += sqft * 1231.1231231
# 或許再加一把這個
price += neighborhood * 2.3242341421
# 最后,再多加一點點鹽
price += 201.23432095
return price
注意那些用粗體標(biāo)注的神奇數(shù)字——.841231951398213, 1231.1231231, 2.3242341421, 和201.23432095。它們稱為權(quán)重(weight)。如果我們能找出對每棟房子都適用的完美權(quán)重,我們的函數(shù)就能預(yù)測所有的房價!
一種找出最佳權(quán)重的笨辦法如下所示:
第一步:
首先,將每個權(quán)重都設(shè)為 1.0:
def estimate_house_sales_price(num_of_bedrooms, sqft, neighborhood):
price = 0
# 一小撮這個
price += num_of_bedrooms * 1.0
# 一大撮那個
price += sqft * 1.0
# 或許再加一把這個
price += neighborhood * 1.0
# 最后,再多加一點點鹽
price += 1.0
return price
第二步:
將你知道的每棟房產(chǎn)的數(shù)據(jù)代入函數(shù)進行運算,檢驗估算值與正確價格的偏離程度:
用你的程序來預(yù)測每棟房屋的價格。
比如說,如果第一套房產(chǎn)實際成交價為 25 萬美元,你的函數(shù)估價為 17.8 萬美元,這一套房產(chǎn)你就差了 7.2 萬。
現(xiàn)在,將你的數(shù)據(jù)集中的每套房產(chǎn)估價偏離值平方后求和。假設(shè)你的數(shù)據(jù)集中交易了 500 套房產(chǎn),估價偏離值平方求和總計為 86,123,373 美元。這個數(shù)字就是你的函數(shù)現(xiàn)在的「錯誤」程度。
現(xiàn)在,將總和除以 500,得到每套房產(chǎn)的估價偏差的平均值。將這個平均誤差值稱為你函數(shù)的代價(cost)。
如果你能通過調(diào)整權(quán)重,使得這個代價變?yōu)?0,你的函數(shù)就完美了。它意味著,根據(jù)輸入的數(shù)據(jù),你的程序?qū)γ恳还P房產(chǎn)交易的估價都是分毫不差。所以這就是我們的目標(biāo)——通過嘗試不同的權(quán)重值,使代價盡可能的低。
第三步:
通過嘗試所有可能的權(quán)重值組合,不斷重復(fù)第二步。哪一個權(quán)重組合的代價最接近于 0,你就使用哪個。當(dāng)你找到了合適的權(quán)重值,你就解決了問題!
興奮的時刻到了!
挺簡單的,對吧?想一想剛才你做了些什么。你拿到了一些數(shù)據(jù),將它們輸入至三個泛型的、簡單的步驟中,最后你得到了一個可以對你所在區(qū)域任何房屋進行估價的函數(shù)。房價網(wǎng)站們,你們要小心了!
但是下面的一些事實可能會讓你更興奮:
1. 過去 40 年來,很多領(lǐng)域(如語言學(xué)、翻譯學(xué))的研究表明,這種「攪拌數(shù)字湯」(我編的詞)的泛型學(xué)習(xí)算法已經(jīng)超過了那些真人嘗試明確規(guī)則的方法。機器學(xué)習(xí)的「笨」辦法終于打敗了人類專家。
2. 你最后寫出的程序是很笨的,它甚至不知道什么是「面積」和「臥室數(shù)量」。它知道的只是攪拌,改變數(shù)字來得到正確的答案。
3. 你可能會對「為何一組特殊的權(quán)重值會有效」一無所知。你只是寫出了一個你實際上并不理解卻能證明有效的函數(shù)。
4. 試想,如果你的預(yù)測函數(shù)輸入的參數(shù)不是「面積」和「臥室數(shù)量」,而是一列數(shù)字,每個數(shù)字代表了你車頂安裝的攝像頭捕捉的畫面中的一個像素。然后,假設(shè)預(yù)測的輸出不是「價格」而是「方向盤轉(zhuǎn)動角度」,這樣你就得到了一個程序可以自動操縱你的汽車了!
太瘋狂了,對吧?
第三步里「嘗試每個數(shù)字」是怎么一回事?
好吧,當(dāng)然你不可能試遍所有權(quán)重組合來找到效果最好的組合。直到世界毀滅你也算不完,因為這數(shù)字和組合無窮無盡。
為了避免這種情況,數(shù)學(xué)家們找到了很多種聰明的辦法來快速找到優(yōu)秀的權(quán)重值。下面是一種:
首先,寫出一個簡單的等式表示上面的第二步:
這就是你的代價函數(shù)(Cost Function)。
現(xiàn)在讓我們,使用機器學(xué)習(xí)數(shù)學(xué)術(shù)語(現(xiàn)在暫時你可以忽略它們),重新改寫同樣的這一等式:
θ 表示當(dāng)前的權(quán)重值。 J(θ) 表示「當(dāng)前權(quán)重的代價」。
這個等式表示,在當(dāng)前權(quán)重值下,我們估價程序的偏離程度。
如果我們?yōu)檫@個等式中所有臥室數(shù)和面積的可能權(quán)重值作圖的話,我們會得到類似下圖的圖表:
圖中,藍色的最低點就是代價最低的地方——在這里我們的程序偏離最小。最高點們意味著偏離最大。所以,如果我們能找到一組權(quán)重值讓我們到達圖中的最低點,我們就得到了答案!
因此,我們需要做的只是調(diào)整我們的權(quán)重,使得我們在圖上朝著最低點「走下坡路」。如果我們不斷微調(diào)權(quán)重,一直向最低點移動,那么我們最終不用嘗試太多權(quán)重就可以到達那里。
如果你還記得一點微積分的話,你也許記得如果你對一個函數(shù)求導(dǎo),它會告訴你函數(shù)任意一點切線的斜率。換句話說,對于圖上任意給定的一點,求導(dǎo)能告訴我們哪條是下坡路。我們可以利用這個知識不斷走向最低點。
所以,如果我們對代價函數(shù)關(guān)于每一個權(quán)重求偏導(dǎo),那么我們就可以從每一個權(quán)重中減去該值。這樣可以讓我們更加接近山底。一直這樣做,最終我們將到達底部,得到權(quán)重的最優(yōu)值。(讀不懂?不用擔(dān)心,繼續(xù)往下讀)。
這種為函數(shù)找出最佳權(quán)重的方法叫做批量梯度下降(Batch Gradient Descent)。如果你對細節(jié)感興趣,不要害怕,可以看看這個詳細說明。
當(dāng)你使用一個機器學(xué)習(xí)算法庫來解決實際問題時,這些都已經(jīng)為你準(zhǔn)備好了。但清楚背后的原理依然是有用的。
還有什么是本篇文章略過的內(nèi)容?
上面我描述的三步算法被稱為多元線性回歸(multivariate linear regression)。你在估算一個能夠擬合所有房價數(shù)據(jù)點的直線表達式。然后,你再根據(jù)房子可能在你的直線上出現(xiàn)的位置,利用這個等式來估算你從未見過的房屋的價格。這是一個十分強大的想法,你可以用它來解決「實際」問題。
但是,盡管我展示給你的這種方法可能在簡單的情況下有效,它卻不能應(yīng)用于所有情況。原因之一,就是因為房價不會是簡簡單單一條連續(xù)的直線。
不過幸運的是,有很多辦法來處理這種情況。有許多機器學(xué)習(xí)算法可以處理非線性數(shù)據(jù)(如神經(jīng)網(wǎng)絡(luò)或帶核函數(shù)的支持向量機)。除此之外,靈活使用線性回歸也能擬合更復(fù)雜的線條。在所有的情況下,尋找最優(yōu)權(quán)重這一基本思路依然適用。
另外,我忽略了過擬合(overfitting)的概念。得到一組能完美預(yù)測原始數(shù)據(jù)集中房價的權(quán)重組很簡單,但用這組權(quán)重組來預(yù)測原始數(shù)據(jù)集之外的任何新房屋其實都不怎么準(zhǔn)確。這也是有許多解決辦法的(如正則化以及使用交叉驗證的數(shù)據(jù)集)。學(xué)習(xí)如何應(yīng)對這一問題,是學(xué)習(xí)如何成功應(yīng)用機器學(xué)習(xí)技術(shù)的重點之一。
換言之,盡管基本概念非常簡單,要通過機器學(xué)習(xí)得到有用的結(jié)果還是需要一些技巧和經(jīng)驗的。但是,這是每個開發(fā)者都能學(xué)會的技巧。
機器學(xué)習(xí)是魔法嗎?
一旦你開始明白,用機器學(xué)習(xí)技術(shù)解決那些看似困難問題(如字跡識別)有多便利時,你就會有一種,只要有足夠的數(shù)據(jù),你就能夠用機器學(xué)習(xí)解決任何問題的感覺。只需要輸入數(shù)據(jù),計算機就能神奇地找出擬合數(shù)據(jù)的等式!
但是有一點很重要,你要記住,只有在你擁有的數(shù)據(jù)對于解決實際問題有效的時候,機器學(xué)習(xí)才能適用。
例如,如果你建立了一個根據(jù)每套房屋內(nèi)盆栽種類的數(shù)量來預(yù)測房價的模型,那它永遠都不會有效果。因為盆栽種類的數(shù)量和房價之間沒有任何的關(guān)系。所以,無論你多賣力地嘗試,計算機永遠也推導(dǎo)不出兩者之間的關(guān)系。
你只能模擬實際存在的關(guān)系。
所以請記住,如果一個問題人類專家不能手動用數(shù)據(jù)解決,計算機可能也不能解決。然而,對于那些人類能夠解決的問題,如果計算機能夠更快地解決,那豈不美哉?
怎樣學(xué)到更多機器學(xué)習(xí)的知識
我認為,目前機器學(xué)習(xí)的最大問題是它主要活躍于學(xué)術(shù)界和商業(yè)研究組織中。對于只想大體了解一下,而不打算成為專家的人們來說,簡單易懂的資料不多。但是這種情況每天正在改善。
via medium.com


浙公網(wǎng)安備 33010602011771號