<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          機器學習:從零開始學習梯度下降

          共 10646字,需瀏覽 22分鐘

           ·

          2021-03-14 14:08

          作者:SETHNEHA 翻譯:王可汗 校對:陳丹



          梯度下降是一個需要理解的重要算法,因為它是機器學習和深度學習中使用的許多更先進算法的基礎(chǔ)。因此,掌握梯度下降的內(nèi)部工作原理對任何計劃進一步探索機器學習算法的人來說都是非常有益的。

          最好的學習方法是實踐,因此在本文中,我將一步步介紹梯度下降過程是如何工作的,而不使用像scikit-learn這樣的ML庫。在日常工作中,使用這些庫當然會更快、更簡潔,但在學習過程中,我發(fā)現(xiàn)手工實現(xiàn)對這個特定算法來說是非常寶貴的。

          梯度下降的目標

          梯度下降的目標是最小化模型預(yù)測與原始數(shù)據(jù)間的誤差。在本文的背景下,我們將著眼于二次多項式模型,也稱為二次方程:


          將二階多項式畫出來后, 看起來是這樣的:



          多項式回歸

          我們這里專門觀察多項式回歸, 即自變量x與因變量y之間的關(guān)系被建模為x的n階多項式。簡單地說,我們的二次多項式的系數(shù)a、b、c將被估計、評價和修改,直到我們可以將線準確地擬合到輸入的x數(shù)據(jù)上。梯度下降是這個過程中的優(yōu)化步驟,它修改和優(yōu)化這些系數(shù)的值。
           
          現(xiàn)在,我們將看看如何創(chuàng)建和繪制這樣的曲線,并建立一個初始模型來擬合這個數(shù)據(jù),然后我們將使用梯度下降來優(yōu)化和改進它。如果我們能得到一個可以準確描述數(shù)據(jù)的模型,希望它能夠準確預(yù)測另一組x值的y值。
           
          我們可以開始為二次多項式方程(????2+????+??)選擇系數(shù),并應(yīng)用到我們將嘗試建模的數(shù)據(jù):

          coeffs = [2,-5, 4]

          這將是我們希望我們的預(yù)測模型盡可能接近的真值模型的系數(shù)[5] 。接下來,我們需要一個二次多項式的評估函數(shù),在給定一組系數(shù)和給定輸入??的情況下,返回相應(yīng)的??。

          def eval_2nd_degree(coeffs, x):    """    Function to return the outputof evaluating a second degree polynomial,    given a specific x value.
          Args: coeffs: List containingthe coefficients a,b, and c for the polynomial. x: The input x value tothe polynomial.
          Returns: y: The correspondingoutput y value for the second degree polynomial.
          """ a = (coeffs[0]*(x*x)) b = coeffs[1]*x c = coeffs[2] y = a+b+c return y

          當x=3時,我們可以看看它的作用:

          coeffs = [2, -5, 4]x=3eval_2nd_degree(coeffs, x)
          7

          創(chuàng)建數(shù)據(jù)和基礎(chǔ)模型

          定義一些x數(shù)據(jù)(輸入),我們希望預(yù)測y(輸出):

          import numpy as npimport matplotlib.pyplot as plt
          hundred_xs=np.random.uniform(-10,10,100)print(hundred_xs)
          x_y_pairs = []for x in hundred_xs: y =eval_2nd_degree(coeffs, x) x_y_pairs.append((x,y))
          xs = []ys = []for a,b in x_y_pairs: xs.append(a) ys.append(b)
          plt.figure(figsize=(20,10))plt.plot(xs, ys, 'g+')plt.title('Original data')plt.show()


          這很好,但是我們可以通過讓事情變得更真實來改進它。你可以添加噪音或“抖動”的值,使他們可以類似于現(xiàn)實世界的數(shù)據(jù):

          defeval_2nd_degree_jitter(coeffs, x, j):    """    Function to return the noisy output ofevaluating a second degree polynomial,    given a specific x value. Output values canbe within [y?j,y+j].
          Args: coeffs: List containing thecoefficients a,b, and c for the polynomial. x: The input x value to the polynomial. j: Jitter parameter, to introduce noiseto output y.
          Returns: y: The corresponding jittered output yvalue for the second degree polynomial.
          """ a = (coeffs[0]*(x*x)) b = coeffs[1]*x c = coeffs[2] y = a+b+c print(y)
          interval = [y-j, y+j] interval_min = interval[0] interval_max = interval[1] print(f"Should get value in the range{interval_min} - {interval_max}") jit_val = random.random() *interval_max # Generate a randomnumber in range 0 to interval max
          while interval_min > jit_val: # While the random jittervalue is less than the interval min, jit_val = random.random() *interval_max # it is not in the rightrange. Re-roll the generator until it # give a number greater than the interval min.
          return jit_val

          測試一下:

          7Should get value in the range 3 - 116.233537936801398

          這個更新的函數(shù)將接受二階多項式的輸入和為這個輸入添加噪聲的抖動值,以給我們一個更現(xiàn)實的輸出,而不僅僅是一個完美的曲線:

          x_y_pairs = []for x in hundred_xs:    y  =eval_2nd_degree_jitter(coeffs, x, j)    x_y_pairs.append((x,y))
          xs = []ys = []for a,b in x_y_pairs: xs.append(a) ys.append(b)
          plt.figure(figsize=(20,10))plt.plot(xs, ys, 'g+')plt.title('Original data')plt.show()


          當我們建立我們的預(yù)測模型,并通過梯度下降來優(yōu)化它時,我們希望能夠得到盡可能接近這些值的結(jié)果。
           
          建模第一步:嘗試一個隨機模型

          建模的第一步是為二次多項式(??=????2+????+??)生成和存儲隨機系數(shù)。這將是我們的初始模型,它很可能不那么精確,我們的目標是改進它,直到它與數(shù)據(jù)足夠吻合。

          rand_coeffs=(random.randrange(-10,10),random.randrange(-10,10),random.randrange(-10,10))rand_coeffs
          (7, 6, 3)

          通過計算輸入值的預(yù)測輸出值來檢查這個模型的準確性:

          y_bar =eval_2nd_degree(rand_coeffs, hundred_xs)
          plt.figure(figsize=(20,10))plt.plot(xs, ys, 'g+', label ='original')plt.plot(xs, y_bar, 'ro',label='prediction')plt.title('Original data vsfirst prediction')plt.legend(loc="lowerright")plt.show()


          從上面的圖中可以明顯看出,這個帶有隨機系數(shù)的新模型并不完全符合我們的數(shù)據(jù)。為了定量描述這個模型有多不正確,我們計算了模型的均方誤差。這是實際輸出和預(yù)測輸出之差的平方和的平均值:


          def loss_mse(ys, y_bar):    """    Calculates MSE loss.
          Args: ys: training data labels y_bar: prediction labels
          Returns: Calculated MSE loss. """ return sum((ys - y_bar)*(ys - y_bar)) /len(ys)
          initial_model_loss = loss_mse(ys, y_bar)
          initial_model_loss
          47922.39790821987

          相當大的數(shù)。現(xiàn)在讓我們看看我們能否通過梯度下降優(yōu)化模型來改善這個相當高的損失值。
           
          梯度下降和損失減少

          我們希望改進我們的模型。因此,我們想要改變它的系數(shù)a, b和c,以減少誤差。因此我們需要知道每個系數(shù)是如何影響誤差的。這是通過計算損失函數(shù)對每個單獨系數(shù)的偏導數(shù)來實現(xiàn)的。

          在這個案例中,我們使用MSE作為我們的損失函數(shù)——這即是我們希望計算偏導數(shù)的函數(shù):

           
          我們模型的輸出預(yù)測如下:


          因此,損失可以重新表述為:

           
          在這個特定的例子中,我們損失函數(shù)的偏導數(shù)如下:


          • 如果你計算每個導數(shù)的值,你會得到每個系數(shù)的梯度。
          • 這些值給出了損失函數(shù)相對于每個特定系數(shù)的斜率。
          • 它們表明你應(yīng)該增加還是減少它來減少損失,以及這樣做的安全程度。
           
          給定系數(shù)??,??和??,計算的梯度????,????和????和學習率????,通常會更新系數(shù),更新的值定義如下:


          一旦您將新模型應(yīng)用到數(shù)據(jù)中,您的損失應(yīng)該會減少。
           
          減少損失

          我們需要一個梯度計算函數(shù),在給定一個二次多項式的系數(shù),以及一組輸入??和一組相應(yīng)的實際輸出??,將返回每個系數(shù)的梯度。

          defcalc_gradient_2nd_poly(rand_coeffs, hundred_xs, ys):    """    calculates the gradient for a second degreepolynomial.
          Args: coeffs: a,b and c, for a 2nd degreepolynomial [ y = ax^2 + bx + c ] inputs_x: x input datapoints outputs_y: actual y output points
          Returns: Calculated gradients for the 2nddegree polynomial, as a tuple of its parts for a,b,c respectively.
          """
          a_s = [] b_s = [] c_s = []

          y_bars = eval_2nd_degree(rand_coeffs,hundred_xs)
          for x,y,y_bar in list(zip(hundred_xs, ys,y_bars)): # take tuple of (xdatapoint, actual y label, predicted y label) x_squared = x**2 partial_a = x_squared * (y - y_bar) a_s.append(partial_a) partial_b = x * (y-y_bar) b_s.append(partial_b) partial_c = (y-y_bar) c_s.append(partial_c)
          num = [i for i in y_bars] n = len(num)
          gradient_a = (-2 / n) * sum(a_s) gradient_b = (-2 / n) * sum(b_s) gradient_c = (-2 / n) * sum(c_s) return(gradient_a, gradient_b,gradient_c) # return calculatedgradients as a a tuple of its 3 parts

          我們現(xiàn)在要:

          • 使用上面的函數(shù)來計算我們表現(xiàn)不佳的隨機模型的梯度。
          • 相應(yīng)調(diào)整模型系數(shù)。
          • 驗證模型的損失現(xiàn)在更小了——梯度下降起作用了!
           
          讓我們設(shè)定一個實驗的初始學習速率。這應(yīng)該保持在很小的范圍內(nèi),以避免錯過全局最小值,但也不能小到要花費無窮長的[8] 時間或陷入局部最小值。lr = 0.0001是一個很好的起點。

          calc_grad= calc_gradient_2nd_poly(rand_coeffs, hundred_xs, ys)
          lr =0.0001a_new= rand_coeffs[0] - lr * calc_grad[0]b_new= rand_coeffs[1] - lr * calc_grad[1]c_new= rand_coeffs[2] - lr * calc_grad[2]
          new_model_coeffs= (a_new, b_new, c_new)print(f"Newmodel coeffs: {new_model_coeffs}")print("")
          #updatewith these new coeffs:new_y_bar= eval_2nd_degree(new_model_coeffs, hundred_xs)updated_model_loss= loss_mse(ys, new_y_bar)
          print(f"Nowhave smaller model loss: {updated_model_loss} vs {original_model_loss}")
          New model coeffs: 5.290395171471687 5.903335222089396 2.9704266522693037Now have smaller model loss: 23402.14716735533 vs 47922.39790821987

          通過將訓練數(shù)據(jù)、原始隨機模型和更新后的低損失模型一起繪制出來,來可視化這個改進:

          plt.figure(figsize=(20,10))plt.plot(xs, ys, 'g+', label ='original model')plt.plot(xs, y_bar, 'ro', label= 'first prediction')plt.plot(xs, new_y_bar, 'b.',label = 'updated prediction')plt.title('Original model vs1st prediction vs updated prediction with lower loss')plt.legend(loc="lower right")plt.show()


          多輪迭代梯度下降

          我們幾乎準備好了。最后一步是在多個輪(周期或迭代)中迭代地執(zhí)行梯度下降。我們希望每一輪迭代都能看到在降低損失和更好地對原始數(shù)據(jù)進行模型擬合方面的改進。
           
          讓我們對上面的calc_gradient_2nd_poly函數(shù)進行改進,使其更適用于梯度下降迭代過程:

          defcalc_gradient_2nd_poly_for_GD(coeffs, inputs_x, outputs_y, lr):    """    calculates the gradient for a second degreepolynomial.
          Args: coeffs: a,b and c, for a 2nd degreepolynomial [ y = ax^2 + bx + c ] inputs_x: x input datapoints outputs_y: actual y output points lr: learning rate
          Returns: Calculated gradients for the 2nddegree polynomial, as a tuple of its parts for a,b,c respectively.
          """ a_s = [] b_s = [] c_s = []
          y_bars = eval_2nd_degree(coeffs, inputs_x)
          for x,y,y_bar in list(zip(inputs_x,outputs_y, y_bars)): # take tuple of(x datapoint, actual y label, predicted y label) x_squared = x**2 partial_a = x_squared * (y - y_bar) a_s.append(partial_a) partial_b = x * (y-y_bar) b_s.append(partial_b) partial_c = (y-y_bar) c_s.append(partial_c)
          num = [i for i in y_bars] n = len(num)
          gradient_a = (-2 / n) * sum(a_s) gradient_b = (-2 / n) * sum(b_s) gradient_c = (-2 / n) * sum(c_s)

          a_new = coeffs[0] - lr * gradient_a b_new = coeffs[1] - lr * gradient_b c_new = coeffs[2] - lr * gradient_c
          new_model_coeffs = (a_new, b_new, c_new)
          #update with these new coeffs: new_y_bar = eval_2nd_degree(new_model_coeffs,inputs_x)
          updated_model_loss = loss_mse(outputs_y,new_y_bar) return updated_model_loss,new_model_coeffs, new_y_bar

          這將作為gradient_descent函數(shù)的一部分被調(diào)用:

          def gradient_descent(epochs,lr):    """    Perform gradient descent for a seconddegree polynomial.
          Args: epochs: number of iterations to performof finding new coefficients and updatingt loss. lr: specified learning rate
          Returns: Tuple containing (updated_model_loss,new_model_coeffs, new_y_bar predictions, saved loss updates)
          """ losses = [] rand_coeffs_to_test = rand_coeffs for i in range(epochs): loss =calc_gradient_2nd_poly_for_GD(rand_coeffs_to_test, hundred_xs, ys, lr) rand_coeffs_to_test = loss[1] losses.append(loss[0]) print(losses) return loss[0], loss[1], loss[2],losses #(updated_model_loss,new_model_coeffs, new_y_bar, saved loss updates)

          最后,讓我們訓練1500輪,看看我們的模型是否學到了什么:

          GD = gradient_descent(1500,0.0001)
          plt.figure(figsize=(20,10))plt.plot(xs, ys, 'g+', label ='original')plt.plot(xs, GD[2], 'b.', label= 'final_prediction')plt.title('Original vs Finalprediction after Gradient Descent')plt.legend(loc="lowerright")plt.show()

           
          經(jīng)過完整的訓練后,這個訓練過的模型顯示出了巨大的改進。我們可以通過檢查它的最終預(yù)測系數(shù)a、b和c來進一步檢驗:

          print(f"FinalCoefficients predicted: {GD[1]}")print(f"OriginalCoefficients: {coeffs}")
          Final Coefficients predicted: (2.0133237089326155, -4.9936501002139275, 3.1596042252126195)Original Coefficients: [2, -5, 4]

          不太遠!這是對初始隨機模型的一大改進。通過觀察訓練時減少損失的情況,我們可以獲得更深入的見解:

          plt.figure(figsize=(20,10))plt.plot(GD[3], 'b-', label ='loss')plt.title('Loss over 1500iterations')plt.legend(loc="lowerright")plt.xlabel('Iterations')plt.ylabel('MSE')plt.show()


          我們觀察到為了得到更精確的系數(shù),模型損耗接近于零。我們還可以看到,在大約400輪之后,損失并沒有明顯的改善——絕對不需要1500輪[11] 。另一種策略是在訓練步驟中添加某種條件,當達到某個最小損失閾值時停止訓練。這將防止過度訓練和潛在的模型過擬合。
           
          我希望你喜歡這篇關(guān)于多項式回歸的梯度下降的文章。某些概念乍一看可能會讓人望而生畏,但隨著時間的推移,如果我們堅持足夠長的時間,我們會逐漸熟悉一個問題的“具體細節(jié)”。我發(fā)現(xiàn)這個練習對我來說確實是這樣的,我覺得這是一個很值得學習的經(jīng)驗。

          原文標題:
          PolynomialRegression — Gradient Descent from Scratch
          原文鏈接:
          https://towardsdatascience.com/polynomial-regression-gradient-descent-from-scratch-279db2936fe9?source=collection_home

          也可以加一下老胡的微信
          圍觀朋友圈~~~


          推薦閱讀

          (點擊標題可跳轉(zhuǎn)閱讀)

          麻省理工學院計算機課程【中文版】
          【清華大學王東老師】現(xiàn)代機器學習技術(shù)導論.pdf
          機器學習中令你事半功倍的pipeline處理機制
          機器學習避坑指南:訓練集/測試集分布一致性檢查
          機器學習深度研究:特征選擇中幾個重要的統(tǒng)計學概念

          老鐵,三連支持一下,好嗎?↓↓↓

          瀏覽 81
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  日皮视频免费观看网站 | 影音先锋男人的资源网站 | 五月天婷婷丁香在线播放 | 逼色网站亚洲 | 无码AV免费观看 |