首頁>技術>

> Photo by Rob Schreckhise on Unsplash

如果您的ML演算法效果不佳,如何發現問題

我們花了很多時間來開發機器學習演算法。但是在部署後,如果該演算法效能不佳,那將令人沮喪。問題是,如果演算法無法按預期工作,下一步應該怎麼做。什麼地方出了錯?訓練資料的數量是否足夠?我們使用了正確的功能嗎?我們是否應該繼續收集更多資料?我們可以,但是那是非常耗時且昂貴的。我們應該新增更多功能嗎?那也可能很昂貴。

往哪個方向走?

如果您的機器學習演算法無法正常工作,下一步該怎麼做?有幾種選擇:

· 獲取更多的訓練資料非常耗時。甚至可能需要數月的時間才能獲得更多的研究資料。

· 獲得更多的訓練特徵。也可能需要很多時間。但是,如果新增一些多項式特徵可以工作,那就太酷了。

· 選擇較小的一組訓練特徵。

· 增加正則項

· 減少正則項。

那麼,接下來您應該嘗試哪一個呢?開始嘗試任何操作都不是一個好主意。因為您可能最終會花太多時間在無用的事情上。您需要先發現問題,然後採取相應措施。學習曲線有助於輕鬆檢測問題,從而節省大量時間。

學習曲線對於確定如何提高演算法效能非常有用。確定演算法是否遭受偏差或擬合不足,方差或擬合過度,或兩者兼而有之,這很有用。

學習曲線的工作原理

學習曲線是成本函式的圖。在同一圖中,訓練資料的成本函式和交叉驗證資料的成本函式為演算法提供了重要的見解。提醒一下,這是成本函式的公式:

換句話說,它是預測輸出減去原始輸出的平方除以訓練資料數量的兩倍。要繪製學習曲線,我們需要將這些成本函式繪製為訓練資料數量(m)的函式。代替使用所有訓練資料,我們將僅使用訓練資料的較小子集來訓練資料。

看看下面的圖片:

這是概念

如果我們使用太少的資料來訓練資料,則該演算法將完全適合訓練資料,並且成本函式將返回0。

在上面的圖片中清楚地表明,當我們僅使用一個,兩個或三個資料演算法來訓練資料時,就可以很好地瞭解到很少的資料,並且訓練成本為零或接近於零。但是,這種型別的演算法無法在其他資料上很好地執行。

當您嘗試使交叉驗證資料適合此演算法時,在交叉驗證資料上執行效果很差的可能性很高。因此,交叉驗證資料的成本函式將返回非常高的值。

另一方面,當我們將需要越來越多的資料來訓練演算法時,它將不再完全適合訓練資料。因此,培訓成本將變得更高。

同時,由於該演算法針對大量資料進行訓練,因此在交叉驗證資料上的效能會更好,並且交叉驗證資料的成本函式將返回較低的值。這是如何建立學習曲線的方法。

開發學習演算法

我將演示如何逐步繪製學習曲線。為了繪製學習曲線,我們首先需要機器學習演算法。為簡單起見,我將使用線性迴歸演算法。首先,我們開發一個線性迴歸演算法。

首先,匯入包和資料集。我在這裡使用的資料集取材於安德魯·伍(Andrew Ng)的Coursera機器學習課程。在此資料集中,X值和y值在Excel檔案中的單獨工作表中進行組織。

提醒一下,X是我們將用來開發和訓練機器學習演算法的功能。y是我們需要預測的輸出特徵。

交叉驗證資料的X和y值也被組織在同一Excel檔案中的其他兩個工作表中。我在本文結尾處提供了到資料集的連結。請隨時下載資料集並進行練習。

%matplotlib inlineimport pandas as pdimport numpy as npimport matplotlib.pyplot as pltfile = pd.ExcelFile('dataset.xlsx')df = pd.read_excel(file, 'Xval', header=None)df.head()

以相同的方式,匯入訓練集的y值:

y = pd.read_excel(file, 'yval', header=None)y.head()

讓我們快速開發線性迴歸演算法。

定義假設

線性迴歸使用非常基本的線性方程式進行我們在學校學習的預測。公式如下:

Y = C + BX

對於機器學習,我們使用不同的術語。

在這裡," h"是假設或預測值,theta0和theta1是係數,X是輸入特徵。

在這裡,我們已經有了X。我們必須計算" h",並且期望它與y的值匹配。因為我們的目標是能夠預測y的值。

Theta0和theta1在開始時是隨機初始化的。我們將透過迭代不斷完善theta0和theta1的值。

在每次迭代中,我們將使用成本函式和梯度公式來計算成本以更新theta值

成本函式和梯度下降

成本函式為我們提供了有關我們的預測值與原始輸出特徵有何不同的想法。在這裡,我們的輸出特徵為y,預測輸出為" h"。因此,成本函式將告訴我們" h"與" y"的偏離量。我們希望成本函式值儘可能低。

這是成本函式的公式:

在成本函式最小之前,我們將不斷淘汰演算法。在每次迭代中,我們使用梯度下降來更新theta值。

要更新theta值,我們將從先前的theta值中減去梯度下降。當我們對其進行編碼時,它將更加清晰。

此處,m是訓練資料的數量,而alpha是學習率。

開發線性迴歸演算法

使用上述公式開發假設和成本函式。

m = len(df)def hypothesis(theta, X):    return theta[0] + theta[1]*Xdef cost_calc(theta, X, y):    return (1/2*m) * np.sum((hypothesis(theta, X) - y)**2)

現在,我們將定義梯度下降以最佳化引數theta0和theta1。在每次迭代中,我們將更新theta值並跟蹤成本函式和theta值。

最後,它將返回每個迭代theta值中的成本列表。程式碼很簡單。請在這裡檢查。

def gradient_descent(theta, X, y, epoch, alpha):    cost = []    theta_hist = []    i = 0    while i < epoch:        hx = hypothesis(theta, X)        theta[0] -= alpha*(sum(hx-y)/m)        theta[1] -= (alpha * np.sum((hx - y) * X))/m        cost.append(cost_calc(theta, X, y))        i += 1    return theta, cost

完成了線性迴歸演算法。我們需要一種預測輸出的方法。在預測方法中,我們將使用來自梯度下降函式和假設函式的最終theta進行預測。

def predict(theta, X, y, epoch, alpha):    theta, cost = gradient_descent(theta, X, y, epoch, alpha)    return hypothesis(theta, X), cost, theta

現在,將引數初始化為零,並使用預測函式預測輸出變數。

theta = [0,0]y_predict, cost, theta = predict(theta, df[0], y[0], 1400, 0.001)

更新的θ值是:[10.724868115832654,0.3294833798797125]

現在,在同一圖中繪製df或X的預測輸出(h)和原始輸出(y)。

plt.figure()plt.scatter(df, y)plt.scatter(df, y_predict)

看來演算法運作良好。預測的輸出線從中間位置開始。

是時候建立學習曲線了!!!

畫出學習曲線

現在,我們可以畫出學習曲線。首先,讓我們為我們的交叉驗證資料集匯入X和y值。如前所述,我們將它們組織在單獨的Excel工作表中。

file = pd.ExcelFile('dataset.xlsx')cross_val = pd.read_excel(file, 'X', header=None)cross_val.head()
cross_y = pd.read_excel(file, 'y', header=None)cross_y.head()

為此,我想稍微修改一下gradient_descent函式。

在之前的gradient_descent函式中,我們計算了每次迭代的成本。我這樣做是因為這是傳統機器學習演算法開發中的一種很好的做法。

但是對於學習曲線,我們不需要每次迭代的成本。因此,為了節省執行時間,我將在每個時期中排除計算成本函式。我們將僅返回更新的引數。

def grad_descent(theta, X, y, epoch, alpha):    i = 0    while i < epoch:        hx = hypothesis(theta, X)        theta[0] -= alpha*(sum(hx-y)/m)        theta[1] -= (alpha * np.sum((hx - y) * X))/m        i += 1    return theta

如前所述,要開發學習曲線,我們需要使用訓練資料的不同子集來訓練學習演算法。

在我們的訓練資料集中,我們有21個數據。我將僅使用一個數據,然後使用兩個資料,然後使用三個資料一直到21個數據來訓練演算法。

因此,我們將在21個訓練資料子集上對演算法進行21次訓練。我們還將跟蹤每個訓練資料子集的成本函式。請仔細看一下程式碼,它將更加清晰。

j_tr = []theta_list = []for i in range(0, len(df)):    theta = [0,0]    theta_list.append(grad_descent(theta, df[0][:i], y[0][:i], 1400, 0.001))    j_tr.append(cost_calc(theta, df[0][:i], y[0][:i]))theta_list

以下是每個訓練資料子集的訓練引數:

這是每個訓練子集的費用:

檢視每個子集的成本。當訓練資料僅為1或2時,成本為零或幾乎為零。隨著我們不斷增加培訓資料,成本也上升了,這是預期的。

現在,對訓練資料的所有子集使用上面的引數來計算交叉驗證資料的成本:

j_val = []for i in theta_list:      j_val.append(cost_calc(i, cross_val[0], cross_y[0]))j_val

剛開始時,成本確實很高,因為訓練引數來自太少的訓練資料。但是隨著引數的增加和更多訓練資料的改進,交叉驗證錯誤不斷下降。

讓我們在同一圖中繪製訓練誤差和交叉驗證誤差:

%matplotlib inlineimport matplotlib.pyplot as pltplt.figure()plt.scatter(range(0, 21), j_tr)plt.scatter(range(0, 21), j_val)

這是我們的學習曲線。

從學習曲線中得出決策

上面的學習曲線看起來不錯。它以我們預期的方式流動。最初,訓練誤差太小,驗證誤差太高。

慢慢地,它們彼此完全重疊。太完美了!但是在現實生活中,這種情況並不經常發生。

我們可能會發現學習曲線如下所示:

訓練誤差和驗證誤差之間是否存在重大差異,表明存在高方差問題。也可以稱為過度擬合問題。

獲取更多的訓練資料或選擇較小的功能集或同時使用這兩種功能都可以解決此問題。

如果傾斜曲線看起來像這樣,則意味著開始時訓練誤差太小而驗證誤差太高。緩慢地,訓練誤差變高而驗證誤差變低。但在某種程度上,它們變得平行。您可以從圖片中看到一點,即使有了更多訓練資料,交叉驗證錯誤也不再減少。

在這種情況下,獲取更多訓練資料將不會改善機器學習演算法。

修正學習演算法

假設我們正在執行線性迴歸。但是該演算法無法正常工作。

該怎麼辦?

首先,畫出一個學習曲線,如我在此處演示的。

· 如果檢測到高方差問題,請根據要素的重要性選擇一組較小的要素。如果有幫助,可以節省一些時間。如果不是,請嘗試獲取更多訓練資料。

· 如果您從學習曲線中發現高偏差問題,那麼您已經知道獲得附加功能是一種可能的解決方案。您甚至可以嘗試新增一些多項式特徵。大量時間可以幫助您節省大量時間。

· 如果您要使用正則化項lambda實現演算法,請在該演算法遇到高偏差的情況下嘗試降低lambda,並在該演算法遇到高方差問題的情況下嘗試增加lambda。

在神經網路的情況下,我們也可能遇到這種偏差或方差問題。

對於高偏差或欠擬合問題,我們需要增加神經元的數量或隱藏層的數量。為了解決高方差或過度擬合的問題,我們應該減少神經元的數量或隱藏層的數量。我們甚至可以使用不同數量的神經元繪製學習曲線。

12
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • wxPython提供了哪些模組用於Python應用開發