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