2018年5月3日 星期四

Python Deep Learning 深學筆記 - 微分和揣上細值

←前一篇     後一篇→


微分(bî-hun)个觀念

微分个基礎觀念真簡單: 咱若有一个函式 y=f(x), 若是 x 變化真幼, 咱共伊標做 dx, 按呢 y 嘛綴 dx 變一點點矣, 咱共伊標做 dy, dy 親像這張圖:

y = f(x) 是一个函式, dy/dx 嘛是一个函式. in 兩的是啥物關係咧? 咱舉一个例: y = x**2, 這是真簡單个微積分, 咱先寫伊的表示:

def func_y(x):
     return x**2.0

紲落來, 欲按怎表示微分咧? 若是數學个微分理論, 愛處理連紲性(continuity) 和無限細个問題, 伊的答案號做解析 (analytic), 是完全正確--ê, 比如講: d(x**2)/dx = 2x, 就是解析. 伊佇 x = 0.5 个 dy/dx 就是 2*0.5 =1, 佇 x = 0 个 dy/dx 就是 2*0 = 0.

數值微分(Numerical differential)个觀念


若是電腦, 伊毋捌數彼款抽象思考, 數學家和電腦專家嘛發展出方法來處理微分, 彼就是數值微分(sòo-ta̍t-bî-hun). 咱用 Python 來奕看覓.

Python, 咱用一个真幼个數來逼倚, 比如講 1e-4 是 10 个負 4 次方:

def numerical_diff(f, x):
      h = 1e-4
      d =  (f(x+h) - f(x-h))/(2.0*h)
      return d

按呢共伊敆--起來:

#!/usr/bin/python3
def func_y(x):
    return x**2.0

def numerical_diff(f, x):
    h = 1e-4
    d =  (f(x+h) - f(x-h))/(2.0*h)
    return d

print(numerical_diff(func_y, 0.5))
print(numerical_diff(func_y, 0))

答案是:

0.9999999999998899
0.0

和 1 佮 0 精差是夭壽幼.  這款个方式, 號做數值微分 (numerical differentiation).

切線(tangent line) 和斜率 (slope)


佇 y=f(x), x=5 个彼點个微分, 就是彼个點个斜率 (tshiâ-lu̍t), 咱會使用彼斜率畫一條線迵過彼點, 這條線就是切線(tangent line), 咱來運行書頂的 ch04/gradient_1d.py, 伊的輸出是:

這的程式踮短短 31 逝, 就畫出一个函式佮伊的切線, 咱看伊的後半段:

def tangent_line(f, x):
    d = numerical_diff(f, x)
    print(d)
    y = f(x) - d*x
    return lambda t: d*t + y
     
x = np.arange(0.0, 20.0, 0.1)
y = function_1(x)
plt.xlabel("x")
plt.ylabel("f(x)")

tf = tangent_line(function_1, 5)
y2 = tf(x)

plt.plot(x, y)
plt.plot(x, y2)
plt.show()

函式 tagent_line(f, x) 是一个有影媠氣个寫法, 佇 4 逝就共函式 f 佇 x 點个切線函式生--出來. 伊利用一寡數學推算, 佮 lambda 這種 "生函式" 个方法.

閣紲落來就是使用 matplotlib.pylab 真勥(khiàng)个畫圖功能.

落梯法(lo̍h-thui-huat)


咱共這个函式小改一个, 親像這个程式: gradient_x2.py:

我予伊畫三條切線出來, 佇 x=5 伊的斜率是正个, x=0 伊的斜率拄拄好是 0, 佇 x=-5 伊的斜率是負个. 咱若是凊彩揣一點 x 想欲揣 f(x) 的上細值, 也就是 0 的所在, 欲按怎做咧?

咱會使那呢想: 斜率正个彼點, 咱 x 就向倒爿行. 斜率負个彼點, 咱就向正爿行, 若是伊有上細值, 伊的斜率就會那來若接近 0, 這就是上細點. 這種方法, 號做落梯法(gradient descent method).

共這个想法成做算式:

x = x - lr * df/dx

這就是逐擺 x 愛徙落去个下一步. 斜率正, df/dx > 0, 負號予 -n*df/dx 變細向倒爿. 斜率負 df/dx < 0, -n*df/dx 負負得正向正爿. n 是咱愛斟酌揀个一个數字, 傷大佮傷細攏會歹收縮. 咱用tha̍h-拄仔个 y=0.01*x**2 來做例, 參考: gradient_1_descent.py:

def gradient_descent(f, init_x, lr=0.1, step_num=10000):
    x = init_x

    for i in range(step_num):
        grad = numerical_diff(f, x)
        x -= lr * grad
    return x, f(x)


x1, y1 = gradient_descent(function_1, 10)
print(x1, y1)
x1, y1 = gradient_descent(function_1, -10)
print(x1, y1)

伊的結果是:
2.0202860902402727e-08 4.0815558864183276e-18
-2.0202860902402727e-08 4.0815558864183276e-18

雖然無仝, 毋過攏是倚 0, 彼差別幼微个程度, 會使共伊當做無差別.


沒有留言:

佇 Linux 來看GPX 檔案

最近定定有戶外活動。使用𤆬路機 (GPS) 來記錄行過的路線。普通我記錄路線,攏是用手機仔抑是專門个𤆬路機,罕得用電腦來看。 毋過,"仙人拍鼓有時錯,跤步踏差啥人無"。有一擺我無細膩,袂記得共一擺活動的路線收煞起來,閣直接開始記錄下一擺的活動,按呢共幾落...