上一篇機器學習入門系列(1)--機器學習概覽簡單介紹了機器學習的一些基本概念,包括定義、優缺點、機器學習任務的劃分等等。
接下來計劃通過幾篇文章來介紹下,一個完整的機器學習專案的實現步驟會分為幾步,最後會結合《hands-on-ml-with-sklearn-and-tf》的例子來介紹下相應程式碼的實現。
這是如何構建一個完整的機器學習專案第一篇!
這裡先給出一個完整的機器學習專案過程的主要步驟,如下所示:
- 專案概述。
- 獲取資料。
- 發現並視覺化資料,發現規律
- 為機器學習演算法準備資料。
- 選擇模型,進行訓練。
- 微調模型。
- 給出解決方案。
- 部署、監控、維護系統
第一篇文章會介紹下第一節內容,開始一個專案的時候,需要確定什麼問題,包括選擇合適的損失函式。
1. 專案概覽
1.1 劃定問題
當我們開始一個機器學習專案的時候,需要先了解兩個問題:
- **商業目標是什麼?**公司希望利用演算法或者模型收穫什麼,這決定需要採用什麼演算法和評估的效能指標?
- 當前的解決方案效果如何?
通過上述兩個問題,我們就可以開始設計系統,也就是解決方案。
但首先,有些問題也需要了解清楚:
- 監督還是無監督,或者是強化學習?
- 是分類,迴歸,還是其他型別問題?
- 採用批量學習還是需要線上學習。
1.2 選擇效能指標
選擇效能指標,通常對於模型,首先就是指模型的準確率,而在機器學習中,演算法的準確率是需要通過減少損失來提高的,這就需要選擇一個合適的損失函式來訓練模型。
一般,從學習任務型別可以將損失函式劃分為兩大類--迴歸損失和分類損失,分別對應迴歸問題和分類問題。
迴歸損失
均方誤差 / 平方誤差 / L2 誤差
均方誤差(MSE)度量的是預測值和真實值之間差的平方的均值,它只考慮誤差的平均大小,不考慮其方向。但經過平方後,對於偏離真實值較多的預測值會受到更嚴重的懲罰,並且 MSE 的數學特性很好,也就是特別易於求導,所以計算梯度也會變得更加容易。
MSE 的數學公式如下:
程式碼實現如下:
def rmse(predictions, targets):
# 真實值和預測值的誤差
differences = predictions - targets
differences_squared = differences ** 2
mean_of_differences_squared = differences_squared.mean()
# 取平方根
rmse_val = np.sqrt(mean_of_differences_squared)
return rmse_val
複製程式碼
當然上述程式碼實現的是均方根誤差(RMSE),一個簡單的測試例子如下:
y_hat = np.array([0.000, 0.166, 0.333])
y_true = np.array([0.000, 0.254, 0.998])
print("d is: " + str(["%.8f" % elem for elem in y_hat]))
print("p is: " + str(["%.8f" % elem for elem in y_true]))
rmse_val = rmse(y_hat, y_true)
print("rms error is: " + str(rmse_val))
複製程式碼
輸出結果為:
d is: ['0.00000000', '0.16600000', '0.33300000']
p is: ['0.00000000', '0.25400000', '0.99800000']
rms error is: 0.387284994115
複製程式碼
平方絕對誤差 / L1 誤差
平均絕對誤差(MAE)度量的是預測值和實際觀測值之間絕對差之和的平均值。和 MSE 一樣,這種度量方法也是在不考慮方向的情況下衡量誤差大小。但和 MSE 的不同之處在於,MAE 需要像線性規劃這樣更復雜的工具來計算梯度。此外,MAE 對異常值更加穩健,因為它不使用平方。
數學公式如下:
MAE 的程式碼實現也不難,如下所示:
def mae(predictions, targets):
differences = predictions - targets
absolute_differences = np.absolute(differences)
mean_absolute_differences = absolute_differences.mean()
return mean_absolute_differences
複製程式碼
測試樣例可以直接用剛才的 MSE 的測試程式碼,輸出結果如下:
d is: ['0.00000000', '0.16600000', '0.33300000']
p is: ['0.00000000', '0.25400000', '0.99800000']
mae error is: 0.251
複製程式碼
平均偏差誤差(mean bias error)
這個損失函式應用得比較少,在機器學習領域太不常見了,我也是第一次看到這個損失函式。它和 MAE 很相似,唯一區別就是它沒有用絕對值。因此,需要注意的是,正負誤差可以互相抵消。儘管在實際應用中沒那麼準確,但它可以確定模型是存在正偏差還是負偏差。
數學公式如下:
程式碼的實現,其實只需要在 MAE 的基礎上刪除加入絕對值的程式碼,如下所示:
def mbe(predictions, targets):
differences = predictions - targets
mean_absolute_differences = differences.mean()
return mean_absolute_differences
複製程式碼
還是利用剛剛的測試樣例,結果如下:
d is: ['0.00000000', '0.16600000', '0.33300000']
p is: ['0.00000000', '0.25400000', '0.99800000']
mbe error is: -0.251
複製程式碼
可以看到我們給的簡單測試樣例,存在一個負偏差。
分類誤差
Hinge Loss / 多分類 SVM 誤差
hinge loss 常用於最大間隔分類(maximum-margin classification),它是在一定的安全間隔內(通常是 1),正確類別的分數應高於所有錯誤類別的分數之和。最常用的就是支援向量機(SVM)。儘管不可微,但它是一個凸函式,可以採用機器學習領域中常用的凸優化器。
其數學公式如下:
公式中 sj
表示的是預測值,而 s_yi
是真實值,也可以說是正確預測的數值,而 1 表示的就是間隔 margin
,這裡我們希望通過真實值和預測值之間的差來表示兩種預測結果之間的相似關係,而 margin
是人為設定的一個安全係數,我們是希望正確分類的得分要高於錯誤預測的得分,並且是高於一個 margin
的數值,也就是s_yi
越高越好,s_j
越低越好。這樣計算得到的 Loss 會趨向於 0.
用一個簡單的例子說明,假設現在有如下三個訓練樣本,我們需要預測三個類別,下面表格中的數值就是經過演算法得到的每個類別的數值:
每一列就每張圖片每個類別的數值,我們也可以知道每一列的真實值分別是狗、貓、馬。簡單的程式碼實現如下:
def hinge_loss(predictions, label):
'''
hinge_loss = max(0, s_j - s_yi +1)
:param predictions:
:param label:
:return:
'''
result = 0.0
pred_value = predictions[label]
for i, val in enumerate(predictions):
if i == label:
continue
tmp = val - pred_value + 1
result += max(0, tmp)
return result
複製程式碼
測試例子如下:
image1 = np.array([-0.39, 1.49, 4.21])
image2 = np.array([-4.61, 3.28, 1.46])
image3 = np.array([1.03, -2.37, -2.27])
result1 = hinge_loss(image1, 0)
result2 = hinge_loss(image2, 1)
result3 = hinge_loss(image3, 2)
print('image1,hinge loss={}'.format(result1))
print('image2,hinge loss={}'.format(result2))
print('image3,hinge loss={}'.format(result3))
# 輸出結果
# image1,hinge loss=8.48
# image2,hinge loss=0.0
# image3,hinge loss=5.199999999999999
複製程式碼
這個計算過程更加形象的說明:
## 1st training example
max(0, (1.49) - (-0.39) + 1) + max(0, (4.21) - (-0.39) + 1)
max(0, 2.88) + max(0, 5.6)
2.88 + 5.6
8.48 (High loss as very wrong prediction)
## 2nd training example
max(0, (-4.61) - (3.28)+ 1) + max(0, (1.46) - (3.28)+ 1)
max(0, -6.89) + max(0, -0.82)
0 + 0
0 (Zero loss as correct prediction)
## 3rd training example
max(0, (1.03) - (-2.27)+ 1) + max(0, (-2.37) - (-2.27)+ 1)
max(0, 4.3) + max(0, 0.9)
4.3 + 0.9
5.2 (High loss as very wrong prediction)
複製程式碼
通過計算,hinge loss 數值越高,就代表預測越不準確。
交叉熵損失 / 負對數似然
交叉熵損失(cross entroy loss)是分類演算法最常用的損失函式。
數學公式:
根據公式,如果實際標籤y_i
是 1, 那麼公式只有前半部分;如果是 0, 則只有後半部分。簡單說,交叉熵是將對真實類別預測的概率的對數相乘,並且,它會重重懲罰那些置信度很高但預測錯誤的數值。
程式碼實現如下:
def cross_entropy(predictions, targets, epsilon=1e-10):
predictions = np.clip(predictions, epsilon, 1. - epsilon)
N = predictions.shape[0]
ce_loss = -np.sum(np.sum(targets * np.log(predictions + 1e-5))) / N
return ce_loss
複製程式碼
測試樣例如下:
predictions = np.array([[0.25, 0.25, 0.25, 0.25],
[0.01, 0.01, 0.01, 0.96]])
targets = np.array([[0, 0, 0, 1],
[0, 0, 0, 1]])
cross_entropy_loss = cross_entropy(predictions, targets)
print("Cross entropy loss is: " + str(cross_entropy_loss))
# 輸出結果
# Cross entropy loss is: 0.713532969914
複製程式碼
上述程式碼例子,原始碼地址:
1.3 核實假設
核實假設其實也可以說是確定你設計的系統的輸入輸出,我們的機器學習專案是需要商用的話,肯定就不只是一個演算法模型,通常還會有前端展示頁面效果,後端的服務等等,你需要和前後端的負責人進行溝通,核實介面的問題。
比如,《hands-on-ml-with-sklearn-and-tf》書中給出的例子是設計一個預測房價的系統,其輸出是房價的數值,但是如果前端需要展示的是類別,即房價是便宜、中等還是昂貴,那麼我們的系統輸出的房價就沒有意義了,這時候我們要解決的就是分類問題,而不是迴歸問題。
因此,當你在做一個機器學習專案的時候,你需要和有工作交接的同事保持良好的溝通,隨時進行交流,確認介面的問題。
小結
第一篇簡單介紹了開始一個機器學習專案,首先需要明確商業目標,已有的解決方案,設計的機器學習系統屬於什麼型別任務,並以此為基礎,選擇合適的效能指標,即損失函式。
參考:
- 《hands-on-ml-with-sklearn-and-tf》第二節
- www.jiqizhixin.com/articles/09…
- blog.csdn.net/fendegao/ar…
- blog.csdn.net/xg123321123…
歡迎關注我的微信公眾號--機器學習與計算機視覺,或者掃描下方的二維碼,大家一起交流,學習和進步!