《深度學習入門》讀書筆記3.1:Python實現導數

導數

導數表示的是某個瞬間的變化量:

df(x)dx=limh0f(x+h)f(x)h\frac{df(x)}{dx}=\lim_{h \to0} \frac{f(x+h)-f(x)}{h}
h0h \to0怎麼表示呢?
方案一:h = 1-50

def numerical_diff(f, x):
	h = 1e-50
    return (f(x+h) - f(x)) / h
問題1:
h = 1-50這個微小值會被舍入誤差,比如python用float32類型(32位浮點數)來表示即 np.float32(1e-50)輸出爲0.0,改爲10-4就行
問題2:
我們用上述的計算出來的導數在嚴格意義上並不一致,這個差異的出現是因爲h不可能無限接近0
在這裏插入圖片描述
如圖所示,數值微分含有誤差。爲了減小這個誤差,我們可以計算函數f在(x + h)和(x − h)之間的差分。因爲這種計算方法以x爲中心,計算它左右兩邊的差分,所以也稱爲中心差分(而(x + h)和x之間的差分稱爲前向差分)。
def numerical_diff(f, x):
 h = 1e-4 # 0.0001
 return (f(x+h) - f(x-h)) / (2*h)

偏導數

偏導數和單變量的導數一樣,都是求某個地方的斜率。不過,偏導數需要將多個變量中的某一個變量定爲目標變量,並將其他變量固定爲某個值,爲了將目標變量以外的變量固定到某些特定的值上,我們定義了新函數。然後,對新定義的函數應用了之前的求數值微分的函數,得到偏導數

梯度

梯度指示的方向是各點處的函數值減小最多的方向

def numerical_gradient(f, x):
 h = 1e-4 # 0.0001
 grad = np.zeros_like(x) # 生成和x形狀相同的數組
 for idx in range(x.size):
 tmp_val = x[idx]
 # f(x+h)的計算
 x[idx] = tmp_val + h
 fxh1 = f(x)
 # f(x-h)的計算
 x[idx] = tmp_val - h
 fxh2 = f(x)
 grad[idx] = (fxh1 - fxh2) / (2*h)
 x[idx] = tmp_val # 還原值
 return grad

機器學習的主要任務是在學習時尋找最優參數。同樣地,神經網絡也必須在學習時找到最優參數(權重和偏置)。這裏所說的最優參數是指損失函數取最小值時的參數。但是,一般而言,損失函數很複雜,參數空間龐大,我們不知道它在何處能取得最小值。而通過巧妙地使用梯度來尋找函數最小值(或者儘可能小的值)的方法就是梯度法

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

此時梯度法就派上用場了。在梯度法中,函數的取值從當前位置沿着梯度方向前進一定距離,然後在新的地方重新求梯度,再沿着新梯度方向前進,如此反覆,不斷地沿梯度方向前進。像這樣,通過不斷地沿梯度方向前進,逐漸減小函數值的過程就是梯度法(gradient method)。梯度法是解決機器學習中最優化問題的常用方法,特別是在神經網絡的學習中經常被使用。

def gradient_descent(f, init_x, lr=0.01, step_num=100):
 x = init_x
 for i in range(step_num):
 	grad = numerical_gradient(f, x)
 	x -= lr * grad
 return x
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章