C# 入門深度學習:萬字長文講解微積分和梯度下降

痴者工良發表於2024-11-18

教程名稱:使用 C# 入門深度學習

作者:痴者工良

地址:

https://torch.whuanle.cn

目錄
  • 微積分
      • 極限
      • 導數
        • 求導公式
        • 乘除求導例題
        • 複合函式求導的鏈式法則
        • Sigmoid 函式的導數
        • 求最小值問題
      • 微分
      • 積分
      • 偏導數
        • 多元函式定義域
        • 多元函式的值
        • 多元函式的極限
        • 偏導數
        • 全微分
        • 偏導數求最小值
        • 拉格朗日乘數法
      • 梯度
        • 方向導數
        • 梯度
        • 梯度下降法的基本公式
        • 哈密運算元 \(\bigtriangledown\)
        • 梯度下降法求最小值的近似值

微積分

由於學習微積分需要一定的基礎知識,但是由於本教程不是數學書,所以不能一一詳細介紹基礎知識,讀者需要自行了解學習初等函式、三角函式等基礎知識。

極限

極限的符號是 \(\lim\) ,在高等數學中,主要是數列極限和函式極限,限於篇幅,本文只討論函式存在極限時的一些情況。

數學上有正無窮大( \(+\infty\) )和負無窮大( $ -\infty $ )的概念,大家都知道無窮大的意思,但是比較容易理解錯無窮小、負無窮大,無窮小指的是無限接近 0,而不是負數的無窮大。


舉個例子你就明白了,當 $ x \to + \infty$ 時, \(\frac{1}{x}\) 的值,我們都知道 x 越大, \(\frac{1}{x}\) 越小,但是不可能為 0,只能越來越接近於 0。


求解極限,一般會碰到這幾種情況,當 x 無窮大時,y 是多少。

例如下圖所示,當 x 無窮大時,y 逐漸貼近 x 軸,即 y 越來越接近,我們使用 \(y\to 0\) 表示趨近於 0 或者說接近 0。

image-20241110092447001

圖片來自《高等數學上冊》第一章第三節函式極限的定義與計算,同濟大學數學系編著。


所以:

\[\lim_{x \to \infty} f(x) = \lim_{x \to \infty} \frac{1}{x} = 0 \]

使用 C# 表示時,我們使用一個極大的數表示無窮大。

var x = torch.tensor(double.MaxValue);
var y = 1 / x;

var lim = (int)y.item<double>();
Console.WriteLine(lim);

上面使用了 y.item<double>() 將張量轉換為標量,我們也可以使用函式 y.ToScalar().ToInt32(); 轉換。


再比如下圖所示,當 x 無窮大時,y 越來越接近 \(\frac{\pi}{2}\) ,所以 :

\[\lim_{x \to \infty} \arctan x = \frac{\pi}{2} \]

image-20241110092718306

圖片來自《高等數學上冊》第一章第三節函式極限的定義與計算,同濟大學數學系編著。


上面求極限時,是當 $\lim_{x \to \infty} $ 或 $\lim_{x \to 0} $ 時的情況,在實際中更多的是給出某點,求其極限,例如:

\[\lim_{x \to x_{0}} f(x) = \lim_{x \to x_{0}} \frac{1}{x} \]


\(x=1\) 時,我們直接計算其實可以得到 y=1,極限就是 1,或者換句話來說,我們求一個函式在 \(x_{0}\) 的極限時,如果你可以直接計算出 \(y_{0}\) 的值,那麼這個值就是該點的極限。

這種函式計算極限很簡單,因為可以直接透過 \(y=f(x)\) 計算出來。


下面這道題是也是同濟大學《高等數學上冊》中的兩道題。

image-20241110095607086


當 x 解決 0 時,分子是 0,0 除以任何數都是 0,所以極限是 0?肯定不是呀。

當碰到這種 \(x\to0\) 分子或分母為 0 的情況,就不能直接計算了。這兩道題的解答過程:

image-20241110095620201


由於本文不是數學教程,因此這裡不再深入討論細節。

在高等數學中,有兩種非常重要的極限:

\[\lim_{x \to 0} \frac{\sin x}{x} = 1 ,x \in (0,\frac{\pi }{2}) \]

\[\lim_{x \to 0} (1 + x)^{\frac{1}{x}} = e \]


導數

給定一個函式,如何計算函式在某個區間上的變化率?

如圖所示,函式 \(y = x^{2}\) 在區間 \([1,3]\) 的起點 A 和 終點 B。

image-20241110102423654

那麼平均變化率就是:

\[\frac{\bigtriangleup y}{\bigtriangleup x} = \frac{9-1}{3-1} = \frac{8}{2} = 4 \]


但是當這個 \(\bigtriangleup{x}\)\(\bigtriangleup{y}\) 非常小時,事情就會變得非常複雜。如果我們要求 \(x=9\) 附近的平均變化率,則:

\[\frac{y + \bigtriangleup y}{x+ \bigtriangleup x} = \frac{9 + \bigtriangleup y}{3 + \bigtriangleup x} \]


\(\frac{\bigtriangleup y}{\bigtriangleup x}\) 非常小時,實際上反映了函式在 \(x=9\) 時的瞬時變化率。那麼這個瞬時變化率,我們可以過 A、B 點使用切線表示。

切線是輕輕接觸函式一點的一條線,由圖可知,當 x 越來越大時, \(y_{2} = x+1\)\(y_{1} = x\) 大很多,比如 \(5^2\)\(4^{2}\)\(3^{2}\) 之間的差,越來越大。

那麼切線可以反映這種變化率。如圖所示,B 點的切線角度比 A 的的切線大。

image-20241110103552859


因此,出現了一種新的函式,叫原函式的導函式,簡稱導數,導數也是一個函式,透過導數可以計算原函式任一點的瞬時變化率。

導數的表示符號有多種,例如:

\[\frac{\bigtriangleup y}{\bigtriangleup x} = f'(x) = y' = \frac{dy}{dx} = \frac{df(x)}{x}= \frac{df}{x} \]

d 是微分符號,例如 dy 是對 y 的微分,dx 是對 x 的微分。


如果要求在某點 \(x_{0}\) 的瞬時變化率,則:

\[\frac{\bigtriangleup y}{\bigtriangleup x} \big|_{x_{0}} = f'(x) \big|_{x_{0}} = y' \big|_{x_{0}} = \frac{dy}{dx} \big|_{x_{0}} = \frac{df(x)}{x} \big|_{x_{0}} = \frac{df}{x} \big|_{x_{0}} \]


讀者應該都有一定的數學基礎吧,前面兩種應該很容易理解,而後面三種也很重要,在積分和微積分的學習中,我們將會大量使用這種方式。

我們可以這樣理解:

\[dy = \bigtriangleup y \]

\[dx = \bigtriangleup x \]


在 Pytorch 中,我們可以透過微分系統進行計算,例如我們要計算 \(d(x^2) \big|_{x=3}\)

// 定義 y = x^2 函式
var func = (torch.Tensor x) => x.pow(2);

var x = torch.tensor(3.0, requires_grad: true);
var y = func(x);

// 計算導數
y.backward();

// 轉換為標量值
var grad = x.grad.ToScalar().ToDouble();
Console.WriteLine(grad);

不要搞錯,計算導數後,要使用 x 輸出導數值,而不是使用 y,因為 y 是函式結果。為什麼求導的時候不直接輸出求導結果呢?因為 Pytorch 自動求導系統是非常複雜的,計算的是偏導數,對於一元函式來說,對 x 的偏導數就是 y 的導數,在後面的偏導數和梯度時,會更多介紹這方面的知識。

另外建立 x 的張量型別時,需要新增 requires_grad: true 引數。


求導公式

下面是同濟大學《高等數學》中的一些基本求導公式。

image-20241110105635460


例如,我們求 \(y = x^2\) 的導數,使用上圖的 (2)式,得到 \(y = 2x\)


對於複合函式和複雜函式的求導會很麻煩,這裡不再贅述。對於複雜的函式,還存在高階導數,即導數的導數,二階導數公式如下:

\[f''(x) = y'' = \frac{d^2y}{dx^2} = \frac{d^2f(x)}{x^2}= \frac{d^2f}{x^2} \]


乘除求導例題

主要例題有乘法求導、商求導、指數求導幾種。

① 求下面函式的導函式。

\[f(x) = e^x \cos x \]

解:

\[\begin{align} f'(x) &= (e^x \cos{x})' \\ &= (e^x)'\cos{x} + e^x (\cos{x})' \\ &= e^x \cos{x} - e^x \sin{x} \end{align} \]


求下面函式的導數:

\[y = \frac{x+1}{\ln x} \]

解:

\[\begin{align} y' &= \frac{(x+1)'\ln{x} - (x+1)(\ln{x})}{(\ln{x})^2} \\ &= \frac{\ln{x} - (x+1)^{\frac{1}{x}}}{(\ln{x})^2} \\ &= \frac{x \ln{x} -(x+1)}{x(\ln{x})^2} \end{align} \]


複合函式求導的鏈式法則

如果 \(y=f(u)\) 在點 \(u\) 處可導,\(u=g(x)\) 在點 \(x\) 出可導,則複合函式 \(y=f[g(x)]\) 在點 \(x\) 處可導,且有:

\[\frac{dy}{dx} = \frac{dy}{du} \cdot \frac{du}{dx} \]


如果函式比較複雜,還可以推廣到有限個複合函式的情況,例如:

\[\frac{dy}{dx} = \frac{dy}{du} \cdot \frac{du}{dv} \cdot \frac{dv}{dx} \]


例題,求 \(y = e^{2x}\) 的導函式。

\(u=2x\) ,則:

\[y' = (e^u)' = e^u \cdot (u)' = e^{2x} \cdot (2x)' = 2e^{ex} \]


Sigmoid 函式的導數

經過上面的學習,我們知道由複合函式求導公式可知:

\[\big (\frac{u}{v} \big )' = \frac{u' \dot v - u \dot v'}{v^2} \]


所以對於 \(\big ( \frac{1}{f(x)} \big )'\) 此類函式的求導,可得出:

\[\big ( \frac{1}{f(x)} \big )' = - \frac{f'(x)}{f(x)^2} \]


Sigmoid 函式 \(σ(x)\) 是神經網路中最有名的啟用函式之一,其定義如下:

\[\sigma (x) = \frac{1}{1+e^{-x}} \]

image-20241114203340853


在後面學習梯度下降時,需要對 Sigmoid 函式進行求導,使用下面的公式求導會比較方便:

\[\sigma '(x) = \sigma (x)(1 - \sigma (x) ) \]


當然,你也可以使用分數的求導方法慢慢推導。

\[\begin{align} \sigma '(x) &= (\frac{1}{1+e^{-x}})' \\ &= \frac{1}{1+e^{-x}} - \frac{1}{(1+e^{-x})^2} \\ &= \frac{1}{1+e^{-x}} (1 - \frac{1}{1+e^{-x}}) \\ &= \sigma (x)(1 - \sigma (x) ) \end{align} \]


求最小值問題

函式的斜率有一個性質,當函式的斜率為 0 時,該點 a 取得極值,即 \(f'(a) = 0\) ,該點的切線平行於 x 軸。

畫出 \(y = 3x^4 - 4x^3 - 12x^2 + 32\) 的圖形如下所示,由圖可知分別在 \(x = -1\)\(0\)\(2\) 三個點存在極值,此時斜率都是 0 ,其中當 \(x = 2\) 時,函式取得最小值,該函式無最大值。

image-20241113213533007


那麼如果給定一個函式,我們如果取得這個函式的所有極值和最小最大值?這裡可以使用穿針引線法。

首先對函式進行求導並化簡。

\[\begin{align} y' &= (3x^4 - 4x^3 - 12x^2 + 32)' \\ &= 12x^3 - 12x^2 - 24x \\ &= 12x(x^2 - x - 2) \\ &= 12x(x + 1)(x - 2) \end{align} \]


由此可知,該函式在 \(x = -1,0,2\) 三點的斜率為 0,然後分別計算在這三點的值,做出如下圖所示。

image-20241113215104872


然後計算導數在區間的正負,例如當 \(x<-1\) 時,由於導數的結果是負數,所以 \(f(x)\) 遞減區間。根據導數的正負,確定 \(f(x)\) 的遞增遞減區間,然後作出新的表格。

image-20241113215631143


接下來就簡單了,根據三個點的值,在座標軸上描點,最後按照遞減區間連線,因此最小值是 0。

手畫圖不需要準確,主要是知道遞增遞減區間和極值就行。

e951f1d6da6d09477880fc13f655b23


微分

下面是同濟大學《高等數學》中的一張圖。

image-20241110110700577


由圖可知,在正方形 A 中,其面積是 \(A = (x_{0})^2\) ,而大正方形的面積是 \((x_{0}+ \bigtriangleup x)^2\) ,或者透過多個矩形面積相加得出大正方形面積為:

\[S = x_{0}^2 + 2x_{0} \bigtriangleup x + (\bigtriangleup x)^2 \]


那麼,在邊長增加了 \(\bigtriangleup x\) 的時候,面積增加了多少呢?

\[\bigtriangleup S = 2x_{0} \bigtriangleup x + (\bigtriangleup x)^2 \]


我們可以使用下面的公式來表示當 $y = f(x)$ 滿足一定關係時,其增量的表示式:

\[\bigtriangleup y = A \bigtriangleup x + O(\bigtriangleup x) \]


前面在講解導數時,我們知道 \(\bigtriangleup y =f(x + \bigtriangleup x) - f(x)\) ,所以:

\[\bigtriangleup y =f(x + \bigtriangleup x) - f(x) = A \bigtriangleup x + O(\bigtriangleup x) \]


\(\bigtriangleup x\) 非常小時,並且 \(A \not= 0\) 時,可以忽略 \(O(\bigtriangleup x)\) ,我們使用 $A \bigtriangleup x $ 近似計算 $\bigtriangleup y $ 的值,這就是微分的定義,其中 \(A = f'(x)\)

\[dy = f'(x)\bigtriangleup x \]


舉個例子,求 \(y = x^3\)\(x=1\) 時, \(\bigtriangleup x = 0.01\)\(\bigtriangleup x = 0.001\) 的增量。

上題本質就是求 \(x = 1.01\)\(x = 1\)\(\bigtriangleup y\) 以及 \(x = 1.001\)\(x = 1\)\(\bigtriangleup y\)

先求:

\[(1.01)^3 = 1.030301 \]

\[(1.001)^3 = 1.003003001 \]


所以兩個增量方便是 0.030301、0.003003001。

但是如果只需要求近似值,那麼我們使用微分方式去求,首先求出導數:

\[y' = dy = (x^3)' = 3x^2 \]


所以:

\[dy = 3x^2 \bigtriangleup x \]


所以 \(\bigtriangleup x = 0.01\) 時,有:

\[dy = 3*(1)^2 * 0.01 = 3 * 0.01 = 0.03 \]


所以 \(\bigtriangleup x = 0.001\) 時,有:

\[dy = 3*(1)^2 * 0.001 = 3 * 0.001 = 0.003 \]


所以可以這樣透過微分 dy 的方式近似計算函式的增量。

因為:

\[\bigtriangleup y = \frac{dy}{dx} \]


我們使用 dy 近似代替 \(\bigtriangleup y\) ,這就是微分的應用場景之一。


積分

前面介紹了導數,我們知道 \(y = x^3\) 的導數是 \(y = 3x^2\)

那麼反過來,我們知道一個函式 \(F(x)\) 的導數是 \(y=x^3\) ,對於冪函式,我們很容易反推出 \(\frac{1}{4} x^4\) 的導數是 \(x^3\) ,但是 \(\frac{1}{4} x^4 + 1\)\(\frac{1}{4} x^4 + 666\) 的導數都是 \(x^3\) ,所以 \(x^3\) 的原函式是不確定的,所以反推得出的積分公式,又叫不定積分,我們使用 \(C\) 來表示這個不確定的常數。


假設原函式是 F(x),導數是 \(f(x)\) ,由於常數在求導時會被消去,所以求積分時,需要出現加上這個不確定的常數,所以:

\[\int f(x)dx = F(x) + C \]


下面是同濟大學《高等數學》給出一些積分公式。

image-20241110135308642


前面介紹了微分的作用,這裡也給出導數在平面中的簡單應用場景。


如圖所示,圖中的是 \(y = x^2\) 函式的封閉區域,和 \(x=0\)\(x=2\) 兩個直線圍成了一個封閉區域,求 ABC 所圍成的封閉區域的面積。

image-20241110140743986


首先求出其原函式為 \(y = \frac{1}{3}x^3\) 。使用積分割槽間表示求解的面積:

\[\int_{1}^{2} x^2=\frac{1}{3}x^3 \big|_{1}^{2} =\frac{1}{3}2^3 - \frac{1}{3}1^3=\frac{7}{3} \]


對於上面求解的問題,使用的是積分公式,如下公式所示,∫ 表示積分符號, \(f(x)\) 表示被積函式, \(dx\) 表示積分變數增量(微分), \(a\)\(b\) 表示積分的下限和上限,即積分割槽間。

\[\int_{a}^{b} f(x) dx \]


下面再來一道簡單的題目,求 $y = 2x+3$ 和 $y = x^2$ 所圍成的面積。

image-20241110143455304


首先要求得積分割槽間,即兩者的兩個交點,由 \(x^2=2x+3\) 得:

\[x^2 - 2x -3 = 0 \]


根據十字相乘法,得:

\[(x + 1)(x - 3) = 0 \]


所以 \(x_{1} = -1\)\(x_{2} = 3\)


我們先求 \(y = 2x + 3\) 在這兩個點之間圍成的面積。

\[\int_{-1}^{3} 2x+3 = x^2+3x \big|_{-1}^{3} = (9 + 9) - (1 - 3) = 20 \]


\(y = x^2\) 在這兩個點所圍成的面積。

\[\int_{-1}^{3} x^2 = \frac{1}{3}x^3 \big|_{-1}^{3} = 9 - (-\frac{1}{3}) = 9 + \frac{1}{3} \]


所以圍成的面積是: \(20 - (9+\frac{1}{3}) = \frac{32}{3}\)


在數學上,我們可以更加方便表示這種兩個函式加減的方法,即:

\[\int_{-1}^{3} (2x+3 - x^2) = \int_{-1}^{3} (2x+3) - \int_{-1}^{3} (x^2) \]


偏導數

偏導數屬於多元函式的微分學,最常見的是求解空間問題,在初高中基本只涉及一元函式,在這裡我們引入二元函式,記作:

\[z = f(x,y) \]


在一元函式中,導數是函式沿著 x 軸的變化率,而在多元函式中由於有多個變數,不能直接計算導數,要針對某個軸方向進行求導,所以叫偏導數,接下來,我們將逐漸學習偏導數的一些基礎知識。


多元函式定義域

下面給出一個二元函式構成的圖形。

\[z=\sqrt{1-x^2-y^2} \]

image-20241110145138140


下面提個問題,怎麼求這個 \(z=\sqrt{1-x^2-y^2}\) 的定義域?

我們知道 $1 \ge x^2 + y^2 $ ,在設 \(y = 0\) 時, $1 \ge x^2 $ ,則 \(-1 \le x \le 1\) ,由於 \(1-x^2 \ge y^2\) ,所以 \(-\sqrt{1-x^2} \le y \le \sqrt{1 - x^2}\)

所以定義域:

\[-1 \le x \le 1 \\ -\sqrt{1-x^2} \le y \le \sqrt{1 - x^2} \\ z \ge 0 \]


這個函式是二元函式,求定義域還是比較簡單的,z 是 \(f(x,y)\) 的函式,我們先求出 x 的定義域,然後求出 y 定義域。推廣到 \(u=f(x,y,z)\) 三元函式,一般 x 定義域是常數,y 的定義域由 x 的函式組成,而 z 的定義域由 x、y 的函式組成。

求解空間中兩個立體圖形組成的封閉的空間體積時,就是使用定積分去求,計算定積分需要知道定義域,就是這種求法,本文不再贅述。


多元函式的值

已知函式 \(f(x,y) = \frac{xy}{x^2+y^2}\) ,求 \(f(1,2)\)

其實也很簡單,方便使用 \(x=1,y=2\) 替代進去即可:

\[f(1,2) = \frac{2}{1^2+2^2} = \frac{1}{5} \]


多元函式的極限

前面提到極限的時候,涉及到的都是一元函式,對於多元函式的極限,計算則複雜一些,我們可以使用以下公式表示二元函式在某點的極限值。

\[\lim_{_{y \longrightarrow y_{0}}^{x \longrightarrow x_{0}}} f(x,y) = A \]


求二元函式的極限,稱為二重極限。

例如求下面函式的二重極限。

\[\lim_{_{y \longrightarrow 2}^{x \longrightarrow 1}} \ln{(x+y^2)} = \ln{(1+2^2)} = \ln{5} \]


偏導數

對多元函式求導的時候,由於函式有多個未知變數,例如 $z = x^2 + y^2 $ ,由於裡面有 x、y 兩個變數,因此函式也就有兩個變化方向,求導的時候要設定是往哪個方向,例如要知道往 x 軸方向的變化率,那就是要針對 x 進行求導,求在 \(z=f(x_{0},y_{0})\) 時 x 的導數,這個就叫對 x 的偏導數。

偏導數使用符號 \(\partial\) 表示,那麼對 x 的偏導數可以記作:

\[\frac{\partial z}{\partial x} \big|_{y=y_{0}}^{x=x_{0}} \]


當然還有很多變體,Markdown 敲數學公式超級累,這裡貼個圖省事兒。

image-20241110151831018


下面給個簡單函式的偏導數,方法很簡單,當對 x 求偏導數時,把 y 當常數處理即可。

\[z = x^2 + y^2 \]

\[\frac{\partial z}{\partial x} = 2x,\frac{\partial z}{\partial y} = 2y \]


再如:

\[z = x^2 + yx + y^2 \]

\[\frac{\partial z}{\partial x} = 2x + y,\frac{\partial z}{\partial y} = 2y +x \]


前面提到積分可以求解平面中兩個函式所組成的封閉區域的面積,偏導數則可以計算空間中立體幾何和平面組成的封閉區域面積,這裡就不再深入。


全微分

設二元函式 \(z = f(x,y)\) 則其全增量公式為:

\[\bigtriangleup z =A\bigtriangleup x + B \bigtriangleup y + O(\beta) \]


那麼關於 z 的微分:

\[dz=f_{x}(x,y)dx + f_{y}(x,y)dy \]


求全微分,其實就是先求出所有偏導數,然後再進行計算。

例如求 \(z = e^{2x+3y}\) 的全微分。

389b1a036ebf0d36c4c2233c49c3556


給個例題,求函式 \(z = f(x,y) = \frac{x^2}{y}\) 在 點 \((1,-2)\) 出,當 \(\bigtriangleup x=0.02\)\(\bigtriangleup y = -0.01\) 時的全增量。


先求函式的兩個偏導數得出。

\[dz = \frac{2x}{y} \bigtriangleup x - \frac{x^2}{y^2} \bigtriangleup y \]


\(\bigtriangleup x=0.02\)\(\bigtriangleup y = -0.01\) 代入,得 \(-0.0175\)


下面是這個函式的影像。

image-20241110154210542


由微分和全微分的基礎知識可知,在數學中進行一些計算時,其精確度會有所丟失。


偏導數求最小值

在學習導數時,我們知道當 \(f'(a) = 0\) 時,該函式取得極值,推廣到多元函式中,也可以透過偏導數來求取極值。例如,對於二元函式 \(z = f(x,y)\) ,當符合下麵條件時,可以取得極值:

\[\frac{\partial z}{\partial x} = 0,\frac{\partial z}{\partial y} = 0 \]


這是因為此時 x、y 切線的斜率都是 0,這裡就不給出推理過程了,直接記住該方法即可。

如下圖是函式 \(z=x^2 + y^2\) 的影像,求當 x、y 為何值時,函式取得最小值。

image-20241114204528433

很明顯,當 x、y 都是 0 的時候,函式取得最小值,但是我們要透過數學來推到,不能只憑影像得出結論。

先求偏導數:

\[\frac{\partial z}{\partial x} = 2x \\ \frac{\partial z}{\partial y} = 2y \]


可知,當 \(x=0,y=0\) 時,兩個偏導數結果都是 0,所以 \(z=f(x,y)\) 只有在 \((0,0)\) 處有唯一的極值。

因為 \(z=x^2 + y^2 \ge 0\) ,所以可知, \(z=f(0,0)\) 時取得最小值。


當 x、y 的斜率越來越接近 0 時,可以看到曲面切線越來越光滑。

image-20241114220105658


拉格朗日乘數法

有一個二元函式 \(z=(x,y)\) ,以及附加條件 \(\varphi (x,y) = 0\) ,而拉格朗日乘數法就是用來求解這種有條件限制的多元函式極值問題。

公式如下:

\[F(x,y,\lambda) = f(x,y) + \lambda{\varphi{(x,y)}} \]


其中 $\lambda $ 是一個引數,也是我們要求解的值,求出 \(\lambda\) 後可以求得 z 的最小值。

首先將上面的公式進行偏導數求導,並且求出為 0 的條件:

\[F'_{x}(x,y,\lambda )= f'_{x}(x,y) +\lambda{\varphi{'_{x}(x,y)}} = 0 \]

\[F'_{y}(x,y,\lambda ) = f'_{y}(x,y) + \lambda{\varphi{'_{y}(x,y)}} = 0 \]

\[F'_{\lambda}(x,y,\lambda ) = \varphi{(x,y)} = 0 \]


透過上述方程求出 x、y、\(\lambda\) 之後,代入 \(f(x,y)\) 求得極值。


例題 \(a + b = 1\) ,求 \(\frac{1}{a} + \frac{4}{b}\) 的最小值。

首先,二元函式是 \(z=f(a,b) = \frac{1}{a} + \frac{4}{b}\)

約束條件 \(\varphi (a,b) = a + b - 1=0\)

所以:

\[F(a,b,\lambda) = f(a,b)+ \lambda{\varphi{(a,b)}} = \frac{1}{a} + \frac{4}{b} + \lambda{(a + b - 1)} \]


現在開始求偏導數。

\[F'_{a}(a,b,\lambda )= f'_{a}(a,b) +\lambda{\varphi{'_{a}(a,b)}} = -\frac{1}{a^2} + \lambda = 0 \qquad (1) \]

\[F'_{b}(a,b,\lambda ) = f'_{b}(a,b) + \lambda{\varphi{'_{b}(a,b)}} = -\frac{4}{b^2} + \lambda= 0 \qquad (2) \]

\[F'_{\lambda}(a,b,\lambda ) = \varphi{(a,b)} = a + b - 1= 0 \qquad (3) \]


由 (1)、(2)、(3) 解得:

image-20241114212937793


代入 \(z=f(a,b) = \frac{1}{a} + \frac{4}{b}\) ,求得 \(z_{min} = f(\frac{1}{3},\frac{2}{3}) = 9\) ,所以最小值是 9。


梯度

在本節中,我們將學習深度學習裡面重點之一的梯度下降法,梯度下降法要學習的知識比較多,本文的內容基本都是為梯度下降法做鋪墊。

百度百科:方向導數本質上研究的是函式在某點處沿某特定方向上的變化率問題,梯度反映的是空間變數變化趨勢的最大值和方向。


方向導數

前面提到導數,在一元函式中, \(y=f(x)\) ,導數是反映了其在某點的變化率,而在 \(z = f(x,y)\) 中,兩個偏導數 $\frac{\partial z}{\partial x} $ 、 \(\frac{\partial z}{\partial y}\) 則是反映函式沿著平行於 x 軸 、y 軸方向上的變化率。偏導數反映的是往某個軸方向的變化率,而方向導數則是某個方向的變化率,而不是某個軸方向。

image-20241110161833098


如上圖所示,設 \(l\) 是一條有 \(P(x,y)\) 引出來的一條射線, \(Q(x + \bigtriangleup x,y + \bigtriangleup y)\)\(l\) 上的一點,設 \(\rho\)\(P\)\(Q\) 兩點之間的距離,則:

\[\frac{\bigtriangleup z}{\rho} \]


該公式反映函式在了 \(P\)\(Q\) 兩點之間沿著 \(l\) 方向的平均變化率,如果當 \(Q\) 趨近於 \(P\) 時,極限存在,則該極限值稱為點 \(P\) 沿方向 \(l\) 的方向導數。


由於:

\[\bigtriangleup x = \rho \cos \alpha , \bigtriangleup y = \rho \cos \beta \]


所以方向導數可以表示為:

\[\begin{align} \frac{\partial z}{\partial l} &= \\ &= \frac{\partial z}{\partial x} \bigtriangleup x + \frac{\partial z}{\partial y} \bigtriangleup y \\ &= \frac{\partial z}{\partial x} \cos \alpha + \frac{\partial z}{\partial y} \cos \beta \end{align} \]


如果使用 \(i\)\(j\) 表示 x、y 上的分量,也可以表示為:

\[\frac{\partial z}{\partial l} = \frac{\partial z}{\partial x}i + \frac{\partial z}{\partial y}j \]


如果我們使用向量表示,也可以表示為:

\[(\frac{\partial z}{\partial x}, \frac{\partial z}{\partial y}) \]


梯度

梯度是指函式的值在哪個方向增長最快,後面學習的梯度下降則是相反的,是函式值下降最快的方向。


在空間中的一點,當點 \(P\) 固定時,方向 \(l\) 變化時,函式的方向導數 $\frac{\partial u}{\partial l} $ 也隨之變化,說明了對於固定的點,函式在不同方向上的變化率也有所不同。那麼對於點 \(P\) ,在什麼方向上可以使得函式的變化率達到最大?這裡需要引入梯度的概念。


下圖是一個半球。

image-20241117094156647

問,怎麼給定任意一點,怎麼最快地達到頂部?很明顯,垂直往上走,可以最快到底頂部,但是對於實際中凹凸不平的影像來說,是不能直接得出結論的,不過我們這裡可以先簡單討論。

就像上面的圖形,給定可微的二元函式 \(z = f(x,y)\) ,有一點 \((x_{0},y_{0})\) ,這個點可以往各種方向走,每個方向的方向導數都不一樣,現在假設有個方向可以讓方向導數最大,這個就是梯度 $gradf(x_{0},y_{0}) $。


如圖所示, \(A(x_{0},y_{0})\) 往 B 方向可以讓 A 最快到達頂點,也就是變化率最大。而 A 有各種方向,其中一個是往 C 走。

往 B 方向的方向導數最大,就是梯度 $gradf(x_{0},y_{0}) $ 。由圖所示,從 A 開始的任意一個方向導數,跟 $ \overrightarrow{AB}$ 都有一個夾角,因為是在空間,所以這個夾角表示起來有點麻煩,就是各個方向的餘弦值,我們也是有向量表示: \(n_{e} = (\cos \alpha ,\cos \beta)\) ,那麼方向導數、梯度的關係:

\[\frac{\partial z}{\partial l} =gradf(x_{0},y_{0}) \cdot n_{e} \]

\[\frac{\partial z}{\partial l} = \frac{\partial z}{\partial x} \cos \alpha + \frac{\partial z}{\partial y} \cos \beta = gradf(x_{0},y_{0})\cdot n_{e} \]

image-20241117094843430


如下圖所示,當 \(\alpha = 0\) 時, \(gradf(x_{0},y_{0})\)\(e_{1}\) 重合, 由於 \(\cos \alpha = 1\) ,所以方向導數也達到最大值 \(|gradf(x_{0},y_{0})|\) 。也就是,沿著梯度方向的方向導數可以達到最大值。

所以:

\[\begin{align} gradf(x_{0},y_{0}) &= \frac{\partial z}{\partial x} \cos \alpha + \frac{\partial z}{\partial y} \cos \beta \\ &= \frac{\partial z}{\partial x}i + \frac{\partial z}{\partial y}j \\ &= (\frac{\partial z}{\partial x}, \frac{\partial z}{\partial y}) \end{align} \]

image-20241110164906093


例題,求函式 \(z = \ln(x^2 + y^2)\) 的梯度。

image-20241110165653935

來源:《高等數學工本》陳兆鬥。


再來一道實際意義的題目。

image-20241110170325278

來源:《高等數學工本》陳兆鬥。


使用 C# 求解該題,得:

// 定義 u = x^2 + y^2 + z^2 函式在 (2,1,-1) 點的值
var x = torch.tensor(2.0, requires_grad: true);
var y = torch.tensor(1.0, requires_grad: true);
var z = torch.tensor(-1.0, requires_grad: true);
var u = x.pow(2) + y.pow(2) + z.pow(2);

// 求導
u.backward();

var ux = x.grad;
var uy = y.grad;
var uz = z.grad;

Console.WriteLine($"gradu(2,1,-1) = {"{"}{ux.ToScalar().ToDouble()},{uy.ToScalar().ToDouble()},{uz.ToScalar().ToDouble()} {"}"}");
gradu(2,1,-1) = {4,2,-2 }

梯度下降法的基本公式

建議讀者閱讀這篇文章,這樣很容易理解什麼是梯度下降:https://www.zhihu.com/question/434600945


前面提到,梯度是向上最快,那麼梯度下降就是向下最快,跟梯度相反就是最快咯。


梯度下降法是神經網路的武器,相信大家在瞭解深度學習時,也最常出現梯度下降的相關知識,所以本小節將講解梯度下降法的一些基礎知識。

在偏導數求最小值一節中,我們學習到最小值需要滿足以下條件:

\[\frac{\partial z}{\partial x} = 0,\frac{\partial z}{\partial y} = 0 \]


如果可以直接透過偏導數計算出梯度,那麼問題就簡單了,直接計算出最小值,都是對於實際場景要計算出來是比較可能的,尤其在神經網路裡面。所以大佬們使用另一種方法來求出最小值的近似值,叫梯度下降法。

畫出一個三維影像如圖所示:

image-20241114223740021


假如你正在最高位置,將你蒙上眼睛後,你要從最上面移動到最底的位置,每次只能移動一個格。

我們要最快下降到底部,肯定要選擇最徒的路徑,但是因為蒙著眼睛,無法跳過一個格知道後面的格的位置,所以只能先從附近的格對比後,找到最徒的格,然後再走下一步。但是不可能所有的格都走一次吧?可以先選幾個格,然後判斷哪個格最徒,接著走下一步,然後再選幾個格,再走下一步。


在前面學習梯度時,我們知道:

\[\frac{\partial z}{\partial l} = \frac{\partial z}{\partial x} \bigtriangleup x + \frac{\partial z}{\partial y} \bigtriangleup y \]


即:

\[\bigtriangleup z = \frac{\partial z}{\partial x} \bigtriangleup x + \frac{\partial z}{\partial y} \bigtriangleup y \]


如果我們把這個公式當作兩個向量的內積,可以得出:

\[\bigtriangleup z = (\frac{\partial z}{\partial x},\frac{\partial z}{\partial y}) \cdot (\bigtriangleup x,\bigtriangleup y) \]


image-20241115204555682


當以下向量方向相反時, \(\bigtriangleup z\) 取得最小值。

image-20241115205039736


讓我們回顧向量知識,當兩個向量的方向相反時,向量內積取得最小值。由於:

\[a \cdot b = |a||b| \cos \theta \]


所以向量 b 滿足:

\[b = -ka \qquad \]

(k 為正的常數)


\(b= (\bigtriangleup x,\bigtriangleup y)\)\(a= (\frac{\partial z}{\partial x},\frac{\partial z}{\partial y})\)\(k=\eta\) ,所以:

\[(\bigtriangleup x,\bigtriangleup y) = -\eta (\frac{\partial z}{\partial x},\frac{\partial z}{\partial y} ) \qquad ( \eta 為正的微小常數) \]


這個公式稱為二變數函式的梯度下降法基本公式,如果推廣到三個變數以上:

\[(\bigtriangleup x_{},\bigtriangleup x_{2},...,\bigtriangleup x_{n}) = -\eta (\frac{\partial x}{\partial x_{1}},\frac{\partial z}{\partial x_{2}},...,,\frac{\partial z}{\partial x_{n}} ) \]


前面學習方向導數和梯度的時候,我們知道沿著梯度的方向導數最大,此時梯度是 \((\frac{\partial z}{\partial x},\frac{\partial z}{\partial y})\) ,也就是向上是最徒的。

由於 \((\bigtriangleup x,\bigtriangleup y)\) 是跟梯度相反的向量,所以向下是下降最快的,所以這就是梯度下降法求使得下降最快的向量。


回顧使用偏導數求最小值 \(z=x^2 + y^2\) ,求:當 x 從 1 變成 \(1+\bigtriangleup x\) 、y 從 2 變到 \(2 + \bigtriangleup y\) 時,求出使得這個函式減小最快的向量 \((\bigtriangleup x,\bigtriangleup y)\)

首先求出偏導數:

\[\frac{\partial z}{\partial x} = 2x \\ \frac{\partial z}{\partial y} = 2y \]


根據梯度下降法的基本公式得出:

\[(\bigtriangleup x,\bigtriangleup y) = -\eta (2x,2y ) \qquad (\eta 為正的微小常數) \]

由題意當 \(x=1\)\(y=2\) 時,得出:

\[(\bigtriangleup x,\bigtriangleup y) = -\eta (2,4 ) \qquad \]

(\(\eta\) 為正的微小常數)


在本小節中,還有一個 \(\eta\) 沒有講解,它是一個非常小的正數,就像下山問題中的一個格,即移動的步長。在使用計算機進行計算時,需要確定一個合適的 \(\eta\) 值, \(\eta\) 值過小或過大都會導致一些問題,而在神經網路中, \(\eta\) 稱為學習率,沒有明確的方法求出 \(\eta\) 值,只能透過反覆實驗來尋找合適的值。


哈密運算元 \(\bigtriangledown\)

當梯度下降法推廣到多個變數時,下面的公式會顯示非常複雜:

\[(\bigtriangleup x_{},\bigtriangleup x_{2},...,\bigtriangleup x_{n}) = -\eta (\frac{\partial x}{\partial x_{1}},\frac{\partial z}{\partial x_{2}},...,\frac{\partial z}{\partial x_{n}} ) \]


所以數學上經常使用 $\bigtriangledown $ 符號簡化公式。

\[\bigtriangledown f = (\frac{\partial x}{\partial x_{1}},\frac{\partial z}{\partial x_{2}},...,\frac{\partial z}{\partial x_{n}} ) \]


替換到梯度下降法公式就是:

\[(\bigtriangleup x_{},\bigtriangleup x_{2},...,\bigtriangleup x_{n}) = -\eta \bigtriangledown f \]


梯度下降法求最小值的近似值

在學習梯度下降法的基本公式時,提到了 \(\eta\) ,那麼繼續回顧 \(z = x^2 + y^2\) 的問題,我們如果設定學習率 \(\eta = 0.1\) ,那麼根據梯度下降法,我們怎麼使用這個演算法求最小值呢?假設初始點是 \((3,2)\) ,根據梯度:

\[(\bigtriangleup x,\bigtriangleup y) = -0.1 (2x,2y ) \\ \bigtriangleup x = -0.2x \\ \bigtriangleup y = -0.2y \]


代入 \((3,2)\) ,得:

第幾次運算 當前位置 當前位置 梯度 梯度 位移向量 位移向量 函式值
i x y ∂z/∂x ∂z/∂y ∆x ∆y z
0 3.00 2.00 6.00 4.00 -0.60 -0.40 13.00

所以,點 \((3.00,2.00)\) 已經移動到 \((2.40,1.60)\) ,所以:

第幾次運算 當前位置 當前位置 梯度 梯度 位移向量 位移向量 函式值
i x y ∂z/∂x ∂z/∂y ∆x ∆y z
0 3.00 2.00 6.00 4.00 -0.60 -0.40 13.00
1 2.40 1.60

重新計算梯度等步驟,得出:

第幾次運算 當前位置 當前位置 梯度 梯度 位移向量 位移向量 函式值
i x y ∂z/∂x ∂z/∂y ∆x ∆y z
0 3.00 2.00 6.00 4.00 -0.60 -0.40 13.00
1 2.40 1.60 4.80 3.20 -0.48 -0.32 8.32

反覆執行運算,最終可以算出最小值,如果步驟越少,那麼下降的速度最快。


在 Pytorch 中,梯度下降演算法有很多種,這裡不再贅述,讀者感興趣可以參考這篇文章:https://zhuanlan.zhihu.com/p/619988672

相關文章