機器學習(一)——機器學習概述和線性迴歸
文章目錄
機器學習基本概念
什麼是機器學習
在討論機器學習(Machine Learning)之前,首先我們先回顧一下人是怎麼樣進行學習的:當一個人碰到一個問題時,他會根據自己以往的履歷和經驗,針對該問題得到一個解決方案,並從這個問題的結果中,再次吸取教訓和經驗,不斷完善自己。
機器學習其實就是模仿這樣的一個過程,讓機器“學會”人類學習的過程。換句話說,就是讓計算機能在各種各樣的“經歷”(在計算機中,指的就是數據)中“總結”出一套解決方案,並在碰見新案例時,能夠做出判斷。
機器學習和傳統編程的區別
1959年,Arthur Samuel給出了機器學習的一個非正式定義,原文如下:
Machine learning: Field of study that gives computers the ability to learn without being explicitly programed.
翻譯一下,機器學習是研究如何在不被精確編程的情況下賦予計算機學習能力的一個領域。事實上,這也是機器學習與傳統編程的區別:機器學習通過由人給機器制定一套學習方案,對於不同的問題、不同的數據可以使用類似的一套學習方案得到適用於特定情況的解決方案;而傳統編程只能對特定的問題制定特定的方案,而對於其他問題,這一套方案就束手無策。
舉個栗子,比如我們現在要讓計算機學會辨別一朵花是梅花還是向日葵。傳統編程是這樣的:首先觀察梅花和向日葵:
可以發現,梅花和向日葵在顏色和花盤大小上存在明顯差異,於是就有了以下的解決方案:
機器學習則不同,它只指定這兩種花在顏色和花盤大小上可能存在差異,而讓機器自己去通過學習來制定分類兩種花的評判標準。
可以看出,傳統編程確定的解決方案只適用於分類這兩種花的情況,但機器學習確定的是一種學習方法,任何在顏色和花盤大小上有差異的兩種花朵都可以使用相同的學習理論,來形成自己的解決方案。
這只是一個很簡單的例子,但是在很多領域,例如開發會下圍棋的機器人、人臉識別器等,傳統編程很難實現一個特定的方案。這時,你仍然能使用機器學習算法,來讓機器去學習,去得到一個解決方案。
機器學習的分類
機器學習大體上可以分爲兩類:監督學習(Supervised Learning)和非監督學習(Unsupervised Learning),分類的指標是學習的數據是否有標註,也可以理解爲是否有一個“正確答案”。舉個栗子,我們要對一批馬進行分類,如果我們按顏色分類,那麼我們會給每一匹馬打上標註:這匹馬是棕色的,這匹馬是白色的——每一匹馬都有一個明確的顏色,也就是標註,這就是監督學習。如果我們按大小分類,我們只有每一匹馬的身高、體重等數據,我們並沒有一個標準,不能直接給它定性,但我們可以通過把相似身高、體重的馬歸結在一起,再來進行一些判斷,這種在學習時沒有“正確答案”的學習就是非監督學習。
另外,根據你的標註是離散的(例如馬的顏色)或是連續的(例如房屋的價格),我們可以把監督學習再細分爲分類問題和迴歸問題。同樣地,非監督學習也可以細分爲聚類和關聯問題,這在以後會依次講到。
*
線性迴歸
問題描述
接下來我們以機器學習中最簡單的線性迴歸爲例來說明機器學習的一般過程。
有這樣一個問題:你是一名房地產大亨,目前你想要轉讓一幢面積爲的別墅,你想要知道你的別墅大概能賣多少錢,於是你去搜集了本市的別墅價格以及別墅的面積。從這堆數據中,你如何才能得到你別墅大致的價格呢?
數據分析
首先,我們將收集到的別墅價格和麪積畫成散點圖。
我們可以大致地看出,別墅的價格和麪積點近似地沿一條直線排列,於是我們想到,我們是否可以用一條直線去近似地擬合這一些點,然後根據這條直線,計算出面積爲時的價格呢?
確定好模型後,很快你就會發現:沒有任何一條直線能完美地通過所有的點,這時,你只能做出一定的讓步:允許你的模型產生誤差,但要儘可能地把誤差限制到最小。這就涉及到了機器學習中一個非常重要的概念:損失函數(Loss Function)。
損失函數
搭建模型的目的:使預測價格和實際價格儘可能接近。
設實際價格爲,預測價格爲,實際價格和預測價格之間的差距就構成了一種損失函數:
但絕對值函數並不是一個處處可導的函數,於是我們重新定義一個數學上容易處理的損失函數:
根據該損失函數,我們接着就可以對模型進行訓練了。
數學推導
接下來一部分,我們將對如何確定最優參數進行數學上的推導,對這部分不感興趣的童鞋可以直接跳過。
在大多數機器學習問題中,我們都很難直接得出確定最優參數的公式,需要利用一些優化方法(如梯度下降法)來得到近似最優解。但線性迴歸是個例外,類似線性迴歸的這種簡單模型求導方便,我們可以直接得出參數的解析解,下面就對線性迴歸參數的解析解進行數學上的推導。
我們考慮更一般的情況:設我們要預測的因變量爲,自變量爲到,它們的係數分別爲到,用向量來表示,分別記作、。那麼損失函數可以表示爲:
爲了方便起見,我們將也併入中,並在中加入一個元素1。對求偏導數,並令它們都等於0:
設按行排列成一個矩陣,構成列向量,對上式兩邊約去後移項,寫成矩陣形式爲:
這便是數學上著名的正規方程組。最後在等式兩邊乘上(假設逆矩陣存在),我們便可以得到參數的最優解析解:
編程實現
安裝並導入必要的包
我們利用Python和支持矩陣運算的numpy來實現線性迴歸。關於安裝numpy,我們只需要使用快捷鍵win+R打開運行窗口,輸入cmd,然後在命令行窗口輸入如下代碼:pip install numpy
等待安裝完成後,在程序中導入numpy。
# -*- coding: UTF-8 -*-
import numpy as np
編寫線性迴歸類
對於機器學習模型而言,我們一般把一個模型當作一個類來處理,並且類中要有兩個特定函數:fit函數和predict函數,分別對應訓練模型和預測結果。同樣的我們將線性迴歸模型定義成一個LinearRegression類,並編寫它的fit函數和predict函數。
# -*- coding: UTF-8 -*-
import numpy as np
"""
利用numpy實現線性迴歸
注:本代碼中的異常名可能不太符合邏輯
"""
class LinearRegression:
# 構造函數
def __init__(self, fit_intercept=True):
# 自變量的數量
self.n_features = 0
# 是否考慮截距項(不考慮則截距爲0)
self.fit_intercept = fit_intercept
# 係數數組
self.coef_ = np.array([])
# 截距數組
if self.fit_intercept:
self.intercept = 0
# 訓練模型
def fit(self, X, Y, axis=0):
# 把輸入數據全部轉化成按行排列
if len(X.shape) == 1:
if axis == 0:
x = np.array([X])
elif axis == 1:
x = X.reshape(-1, 1)
else:
raise IndexError
else:
if axis == 0:
x = np.copy(X)
elif axis == 1:
x = X.transpose()
else:
raise IndexError
y = Y.reshape(-1, 1)
self.n_features = x.shape[1]
n_sample = x.shape[0]
# 是否有截距項決定是否要拼接一列全爲0的矩陣元素
if self.fit_intercept:
x = np.hstack((np.ones([n_sample, 1]), x))
# 計算參數
arg = np.dot(np.dot(np.linalg.inv(np.dot(x.transpose(), x)), x.transpose()), y)
if self.fit_intercept:
self.coef_ = arg[1:]
self.intercept = arg[0]
else:
self.coef_ = arg
# 預測數據
def predict(self, X, axis=0):
if len(X.shape) == 1:
if axis == 0:
x = np.array([X])
else:
x = X.reshape(-1, 1)
else:
if axis == 0:
x = np.copy(X)
elif axis == 1:
x = X.transpose()
else:
raise IndexError
if x.shape[1] != self.n_features:
raise IndexError
if self.fit_intercept:
x = np.hstack((np.ones([x.shape[0], 1]), x))
if len(x.shape) == 1:
x = np.array([x])
arg = np.hstack((np.array([self.intercept]), self.coef_)).reshape(-1, 1)
y = np.dot(x, arg)
else:
if len(x.shape) == 1:
x = np.array([x])
y = np.dot(x, self.coef_.reshape(-1, 1))
return y
解決問題,做出預測
使用我們已經寫好的類,我們可以很方便地將數據輸入,建立線性迴歸模型,進行訓練,做出預測並進行可視化。
# -*- coding: UTF-8 -*-
"""
測試代碼
"""
import numpy as np
from LinearRegression import LinearRegression
import matplotlib.pyplot as plt
import matplotlib
if __name__ == "__main__":
size = np.array([232.0, 249.0, 333.0, 212.3, 286.0, 199.2, 205.3])
prize = np.array([4370, 4880, 7660, 4000, 6000, 3550, 3800])
# 訓練模型
model = LinearRegression()
model.fit(size, prize, axis=1)
# 做出預測
yPred = model.predict(np.array([281.0]), axis=1)
print(yPred[0])
# 將結果可視化
matplotlib.rcParams['font.sans-serif'] = ['SimHei']
plt.scatter(size, prize)
plt.xlabel(u'面積($m^2$)')
plt.ylabel(u'價格(萬元)')
x = np.linspace(180, 350, 1000)
y = model.predict(x,axis=1)
plt.plot(x, y, c='r')
plt.show()
最後我們得到面積爲的別墅的價格大約爲5964.46萬元。
小結
這篇博文主要介紹了機器學習的基本概念,並以線性迴歸爲例介紹了機器學習的三大要素:模型函數、損失函數、優化算法。在下一篇博文中,我將對線性迴歸進行更深層次的討論。