日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

机器学习入门(09)— 偏导数、梯度概念、梯度下降法理论和实现

發布時間:2023/11/27 生活经验 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 机器学习入门(09)— 偏导数、梯度概念、梯度下降法理论和实现 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1. 偏導數概念

對于式 4-6 而言

式(4.6)有兩個變量,求導數時有必要區分對哪個變量求導數,即對 x0x1 兩個變量中的哪一個求導數。另外,我們把這里討論的有多個變量的函數的導數稱為偏導數。用數學式表示的話,可以寫成

2. 梯度概念

當一起計算 x0x1 的偏導數。比如,我們來考慮求 x0 = 3, x1 = 4 時 (x0, x1) 的偏導數

像這樣的由全部變量的偏導數匯總而成的向量稱為梯度(gradient)。對 式(4.6) 求導的的代碼如下所示

import numpy as npdef numerical_gradient(f, x):h = 1e-4    # 0.0001grad = np.zeros_like(x)for idx in range(x.size):tmp_val = x[idx]x[idx] = float(tmp_val) + hfxh1 = f(x)     # f(x+h)x[idx] = tmp_val - hfxh2 = f(x)     # f(x-h)grad[idx] = (fxh1 - fxh2) / (2*h)x[idx] = tmp_val    # 還原值return graddef function(x):return np.sum(x ** 2)if __name__ == "__main__":numerical_gradient(function, np.array([3.0, 4.0]))  # [6. 8.]numerical_gradient(function, np.array([0.0, 2.0]))  # [0. 4.]

np.zeros_like(x) 會生成一個形狀和 x 相同、所有元素都為 0 的數組。

梯度圖形化顯示代碼:

import numpy as np
import matplotlib.pylab as plt
from mpl_toolkits.mplot3d import Axes3Ddef _numerical_gradient_no_batch(f, x):h = 1e-4 # 0.0001grad = np.zeros_like(x)for idx in range(x.size):tmp_val = x[idx]x[idx] = float(tmp_val) + hfxh1 = f(x) # f(x+h)x[idx] = tmp_val - h fxh2 = f(x) # f(x-h)grad[idx] = (fxh1 - fxh2) / (2*h)x[idx] = tmp_val # 還原值return graddef numerical_gradient(f, X):if X.ndim == 1:return _numerical_gradient_no_batch(f, X)else:grad = np.zeros_like(X)for idx, x in enumerate(X):grad[idx] = _numerical_gradient_no_batch(f, x)return graddef function_2(x):if x.ndim == 1:return np.sum(x**2)else:return np.sum(x**2, axis=1)def tangent_line(f, x):d = numerical_gradient(f, x)print(d)y = f(x) - d*xreturn lambda t: d*t + yif __name__ == '__main__':x0 = np.arange(-2, 2.5, 0.25)x1 = np.arange(-2, 2.5, 0.25)X, Y = np.meshgrid(x0, x1)X = X.flatten()Y = Y.flatten()grad = numerical_gradient(function_2, np.array([X, Y]) )plt.figure()# plt.quiver(X, Y, -grad[0], -grad[1],  angles="xy",color="#666666")#,headwidth=10,scale=40,color="#444444")plt.quiver(X, Y, -grad[0], -grad[1], angles="xy",headwidth=5,scale=30,color="#666666")plt.xlim([-2, 2])plt.ylim([-2, 2])plt.xlabel('x0')plt.ylabel('x1')plt.grid()plt.legend()plt.draw()plt.show()

顯示結果:

梯度圖像指向函數 f(x0,x1) 的“最低處”(最小值),就像指南針一樣,所有的箭頭都指向同一點。其次,我們發現離“最低處”越遠,箭頭越大。

梯度會指向各點處的函數值降低的方向。更嚴格地講,梯度指示的方向是各點處的函數值減小最多的方向。因此,無法保證梯度所指的方向就是函數的最小值或者真正應該前進的方向。實際上,在復雜的函數中,梯度指示的方向基本上都不是函數值最小處。

3. 梯度法

雖然梯度的方向并不一定指向最小值,但沿著它的方向能夠最大限度地減小函數的值。因此,在尋找函數的最小值(或者盡可能小的值)的位置的任務中,要以梯度的信息為線索,決定前進的方向。

函數的取值從當前位置沿著梯度方向前進一定距離,然后在新的地方重新求梯度,再沿著新梯度方向前進,如此反復,不斷地沿梯度方向前進。像這樣,通過不斷地沿梯度方向前進,逐漸減小函數值的過程就是梯度法(gradient method)。

梯度法是解決機器學習中最優化問題的常用方法,特別是在神經網絡的學習中經常被使用。

根據目的是尋找最小值還是最大值,梯度法的叫法有所不同。嚴格地講,尋找最小值的梯度法稱為梯度下降法(gradient descent method),尋找最大值的梯度法稱為梯度上升法(gradient ascent method)。但是通過反轉損失函數的符號,求最小值的問題和求最大值的問題會變成相同的問題,因此“下降”還是“上升”的差異本質上并不重要。

一般來說,神經網絡(深度學習)中,梯度法主要是指梯度下降法。

用數學式來表示梯度法,如式(4.7)所示。

式(4.7)的 η 表示更新量,在神經網絡的學習中,稱為學習率(learningrate)。學習率決定在一次學習中,應該學習多少,以及在多大程度上更新參數。

式(4.7)是表示更新一次的式子,這個步驟會反復執行。也就是說,每一步都按式(4.7)更新變量的值,通過反復執行此步驟,逐漸減小函數值。

學習率需要事先確定為某個值,比如0.01 或0.001。一般而言,這個值過大或過小,都無法抵達一個“好的位置”。在神經網絡的學習中,一般會一邊改變學習率的值,一邊確認學習是否正確進行了。

用代碼實現梯度下降法:

import numpy as npdef numerical_gradient(f, x):h = 1e-4    # 0.0001grad = np.zeros_like(x)for idx in range(x.size):tmp_val = x[idx]x[idx] = float(tmp_val) + hfxh1 = f(x)     # f(x+h)x[idx] = tmp_val - hfxh2 = f(x)     # f(x-h)grad[idx] = (fxh1 - fxh2) / (2*h)x[idx] = tmp_val    # 還原值return graddef function(x):return np.sum(x ** 2)def gradient_descent(f, init_x, lr=0.01, step_num=100):x = init_xfor i in range(step_num):grad = numerical_gradient(f, x)x -= lr * gradreturn xif __name__ == "__main__":init_x = np.array([-3.0, 4.0])print(gradient_descent(function, init_x=init_x, lr=0.1, step_num=100))

輸出結果:

[-6.11110793e-10  8.14814391e-10]

這里,設初始值為(-3.0, 4.0),開始使用梯度法尋找最小值。最終的結果是(-6.1e-10, 8.1e-10),非常接近(0,0)。實際上,真的最小值就是(0,0),所以說通過梯度法我們基本得到了正確結果。

對于梯度下降函數

def gradient_descent(f, init_x, lr=0.01, step_num=100):
  • f 是要進行最優化的函數;
  • init_x 是初始值,lr 是學習率 learningrate
  • step_num 是梯度法的重復次數;
  • numerical_gradient(f,x) 會求函數的梯度,用該梯度乘以學習率得到的值進行更新操作,由 step_num 指定重復的次數。

下圖表示梯度更新的過程

下面再來看看學習率過大或者過小的例子

  1. 學習率過大 lr=10.0
init_x = np.array([-3.0, 4.0])
print(gradient_descent(function, init_x=init_x, lr=10.0, step_num=100))

輸出結果是

[-2.58983747e+13 -1.29524862e+12]
  1. 學習率過小 lr=10.0
init_x = np.array([-3.0, 4.0])
print(gradient_descent(function, init_x=init_x, lr=1e-10, step_num=100))

輸出結果:

[-2.99999994  3.99999992]

實驗結果表明,學習率過大的話,會發散成一個很大的值;反過來,學習率過小的話,基本上沒怎么更新就結束了。

也就是說,設定合適的學習率是一個很重要的問題。

像學習率這樣的參數稱為超參數。這是一種和神經網絡的參數(權重和偏置)性質不同的參數。相對于神經網絡的權重參數是通過訓練數據和學習算法自動獲得的,學習率這樣的超參數則是人工設定的。一般來說,超參數需要嘗試多個值,以便找到一種可以使學習順利進行的設定。

參考:《深度學習入門:基于Python的理論與實現》

總結

以上是生活随笔為你收集整理的机器学习入门(09)— 偏导数、梯度概念、梯度下降法理论和实现的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。