向量、矩陣和張量的導數
[著] Erik Learned-Miller
本文翻譯自 Vector, Matrix, and Tensor Derivatives
本人英語水平有限,文章中有翻譯不到位的地方請熱心指出並改正!
本文的目的是幫助學習向量(vectors)、矩陣(matrices)和更高階張量(tensors)的導數,關於向量、矩陣和高階張量求導。
1 簡化,簡化,簡化
關於對數組求導的許多困惑都來自於想要一次性做太多的事情。這些“事情”包括一次性同時對多個組成部分的公式進行求導,在求和符號前面求導和應用鏈式求導法則。通過做這些事情的同時,我們更有可能犯錯,至少在我們有經驗之前是這樣的。
1.1 擴展符號到顯式求和方程式的每個部分
為了簡化一個給定的計算,對於輸出的單個標量元素(a single scalar element)除了標量變量(scalar variables)寫出顯示公式通常是非常有用的。一旦對於輸出的單個標量元素根據其它標量值有一個顯式的公式,然后就可以使用微積分計算,這比同時嘗試做所有的矩陣數學、求和和求導工作要簡單得多。
Example. 假如我們有一個由一個 \(C\) 行 \(D\) 列的矩陣 \(W\) 乘以一個長度為 \(D\) 的列向量 \(\vec{x}\) 得到的長度為 \(C\) 的列向量 \(\vec{y}\) :
假如我們對 \(\vec{y}\) 關於 \(\vec{x}\) 的導數感興趣。這個導數的完整表征需要 \(\vec{y}\) 的每一個分量關於 \(\vec{x}\) 的每一個分量的(偏)導數,在這個例子中,將包含 \(C\times D\) 個值,因為 \(\vec{y}\) 中有 \(C\) 個分量,在 \(x\) 中有 \(D\) 個分量。
讓我們開始計算其中的一個,對於 \(\vec{y}\) 的第 \(3\) 個分量關於關於 \(\vec{x}\) 的第 \(7\) 個分量;即我們想要計算:
這只是一個標量關於另一個標量的導數。
要做的第一件事就是寫出對於計算 \(\vec{y}_3\) 的公式,然后我們就可以對其求導。從矩陣-向量相乘的定義,\(\vec{y}_3\) 的值通過 \(W\) 的第 \(3\) 行和向量 \(\vec{x}\) 的點積計算得到:
此時,我們將原先的矩陣方程(公式 \((1)\) )簡化為一個標量方程。這使得計算想要的導數更加容易。
1.2 移除求和符號
因為直接計算公式 \((2)\) 的導數是可以的,人們經常犯的錯誤就是當微分表達式中包含求和符號(\(\sum\))或是連乘符號(\(\prod\))。當我們開始計算時,寫出來不包含任何求和符號確保做的每一步都是正確的有時候是非常有用的。使用 \(1\) 作為第一個索引,我們有:
當然,我們明確地包括了含有 \(\vec{x}_7\) 這一項,因為這就是我們在此的不同之處。此時,我們可以看到對於 \(y_3\) 僅依賴在 \(\vec{x}_7\) 之上的表達式只有 \(W_{3,7}\vec{x}_7\) 這一個項。因為在累加中沒有其它項包括 \(\vec{x}_7\) 即它們關於 \(\vec{x}_7\) 的導數都是 \(0\) 。因此,我們有:
通過關注在 \(\vec{y}\) 的一個分量和 \(\vec{x}\) 的一個分量,我們盡可能地簡化計算。在未來,當你感到困惑時,嘗試減少一個問題最基本的設置可以幫助你查看哪里出錯。
1.2.1 完善導數:雅可比(Jacobian)矩陣
回想我們的原始目標是計算 \(\vec{y}\) 每一個分量關於 \(\vec{x}\) 的每一個分量的導數,並且我們注意到其中會有 \(C\times D\) 個。它們可以寫成如下形式的一個矩陣:
在這個特別的例子中,這個矩陣被稱為雅可比矩陣(Jacobian matrix),但是這個術語對於我們的目的不重要。
注意對於如下方程:
\(\vec{y}_3\) 關於 \(\vec{x}_7\) 的部分簡單地由 \(W_{3,7}\) 給出。如果你做相同的處理方式到其它部分上,你將會發現,對於所有的 \(i\) 和 \(j\) :
這意味着偏導數的矩陣是
當然,這就是 \(W\) 本身。
因此,做完這些所有工作后,我們可以得出結論
我們有
2 行向量而不是列向量
在使用不同的神經網絡包時要密切關注權重(weight)矩陣和數據矩陣等的排列方式是很重要的。舉個例子,如果一個數據矩陣 \(X\) 包含許多不同的向量,每一個向量表示一個輸入,矩陣 \(X\) 的一行或是一列哪一個是數據向量?
在第一章節的例子中,我們使用的向量 \(\vec{x}\) 是一個列向量。但是,當 \(\vec{x}\) 是一個行向量時你也應該有能力使用同樣的基礎想法。
2.1 Example 2
令 \(\vec{y}\) 的長度為 \(C\) 的行向量(row vector)是由另一個長度為 \(D\) 的行向量 \(\vec{x}\) 與 \(D\) 行 \(C\) 列的矩陣 \(W\) 相乘得到。
重要地是,盡管 \(\vec{y}\) 和 \(\vec{x}\) 依舊有着相同數量的成分,\(W\) 的形狀(shape)是我們之前使用的 \(W\) 的形狀的轉置(transpose)。尤其是,因為我們現在使用 \(\vec{x}\) 左乘,然而,之前的 \(\vec{x}\) 是在右邊的,\(W\) 對於矩陣代數必須是轉置的才行得通。
在這個例子,你將會看到,通過寫出
得到
注意到 \(W\) 的索引是與第一個例子是相反的。但是,當我們組成所有的雅可比矩陣,我們仍然可以看到此例中也是
3 高於兩維的處理
讓我們來考慮另一個密切相關的問題,計算
在這個例子中,\(\vec{y}\) 變量沿着一個坐標變化而 \(W\) 變量沿着兩個坐標變化。因此,全部的導數最自然地包含在三維數組中。我們避免術語“三維矩陣(three-dimensional matrix)”,因為如何做定義在三維數組上的矩陣相乘和其它矩陣運算是不清晰的。
三維數組的處理,找到一種輸出排列它們的方法可能會變得更加麻煩。相反,我們應該簡單地定義我們的結果為可以適用於所需三維數組的任意一個元素結果的公式。
讓我們再次計算在 \(\vec{y}\) 上的一個分量的標量導數,比如 \(\vec{y}_3\) 和 \(W\) 的一個成分,比如是 \(W_{7,8}\) 。讓我們從相同的基本設置開始,其中我們根據其它標量分量寫下一個 \(\vec{y}_3\) 的等式。現在,我們想要一個根據其它標量值表示 \(\vec{y}_3\) 的等式,並且顯示出 \(W_{7,8}\) 在它的計算中扮演的角色。
但是,我們可以看到,\(W_{7,8}\) 在 \(\vec{y}_3\) 的計算中是沒有作用(no role)的,因為:
換句話說,即:
但是,\(\vec{y}_3\) 關於 \(W\) 的第 \(3\) 列元素的偏導數將一定不為 \(0\) 。舉個例子,\(\vec{y}_3\) 關於 \(W_{2,3}\) 的導數如下給出:
其可以通過公式 \((8)\) 簡單地看出。
總的來說,當 \(\vec{y}\) 的分量的索引等於 \(W\) 的第二個索引,導數就將非零,同時對於其它情況就為零。我們可以寫出:
但是其它三維數組的元素將會是 \(0\) 。如果我們令 \(F\) 表示 \(\vec{y}\) 關於 \(W\) 的導數的三維數組,其中:
則
對於 \(F\) 的其它元素都為零。
最后,如果我們定義一個新的二維(two-dimensional)數組 \(G\) 為:
我們可以看到我們需要關於 \(F\) 的所有信息都被存放到 \(G\) 中,並且 \(F\) 有用的(non-trivial)部分實際上是二維的,而不是三維的。
在高效的神經網絡實現中,將導數數組中重要的部分以一個緊湊的方式表示出是至關重要的。
4 多個數據點
重復之前的一些例子是很好的練習,並且使用 \(\vec{x}\) 的多個例子,堆疊在一起形成一個矩陣 \(X\) 。讓我們假設每一個單獨的 \(\vec{x}\) 是一個長度為 \(D\) 的行向量,\(X\) 是一個 \(N\) 行 \(D\) 列的二維數組。作為我們的上一個例子,\(W\) 將會是一個 \(D\) 行 \(C\) 列的矩陣。\(Y\) 由下給出:
也是一個 \(N\) 行 \(C\) 列的矩陣。因此,\(Y\) 的每一行將給出與輸入 \(X\) 的相應行的相關聯的行向量。
堅持我們寫出一個對於給定的輸出成分的表達式的技術,我們有:
我們立即可以從這個等式中看到導數:
除了 \(a=c\) 的情況,它們都為零。這也就是因為每一個 \(Y\) 的分量僅僅通過 \(X\) 的相應的行計算得到,\(Y\) 和 \(X\) 的不同行之間分量的導數都為零。
此外,我們可以看到:
這完全不取決於上面我們正在比較的 \(X\) 和 \(Y\) 的行。
實際上,矩陣 \(W\) 保持所有的這些部分,我們只需要記住根據公式 \((10)\) 索引到其中來獲得我們想要的具體的偏導數。
如果我們令 \(Y_{i,:}\) 為 \(Y\) 的第 \(i\) 行,令 \(X_{i,:}\) 為 \(X\) 的第 \(i\) 行,我們就可以看到:
這是一個我們之前由公式 \((7)\) 得到的結果的簡單的歸納。
鏈式法則與向量和矩陣的結合
現在我們已經解決了幾個基礎的例子,讓我們結合這些思想到一個鏈式法則(chain rule)的例子上。同樣,假設 \(\vec{y}\) 和 \(\vec{x}\) 都是列向量,讓我們從這個等式開始:
並且嘗試計算 \(\vec{y}\) 關於 \(\vec{x}\) 的導數。我們應該簡單地觀察兩個矩陣 \(V\) 和 \(W\) 的乘積不過是另一個矩陣,記作 \(U\) ,因此
但是,我們想要通過使用鏈式法則的處理得到中間結果的定義,以便我們可以看到在這種情況下鏈式法則如何應用到非標量導數上。
讓我們定義中間結果:
然后我們有:
然后我們使用鏈式法則寫出:
為了確保我們准確地知道這是什么意思,讓我們一次分析一個分量的老方法,以 \(\vec{y}\) 的一個分量和 \(\vec{x}\) 的一個分量開始:
但是我們應該如何准確地解釋右邊的乘積?鏈式法則的思想是以 \(\vec{y}_i\) 關於每一個標量(each scalar)中間變量的變化乘以(multiply)每一個標量中間變量關於 \(\vec{x}_j\) 的變化。尤其如果 \(\vec{m}\) 由 \(M\) 個分量組成,然后我們寫出:
回想我們之前關於一個向量關於一個向量的導數的結果:
就是 \(V_{i,k}\) 並且:
就是 \(W_{k,j}\) 。所以我們可以寫出:
其就是對 \(VW\) 的分量表達式,就是我們原先對這個問題的答案。
總結一下,我們可以在向量和矩陣導數的背景下使用鏈式法則:
- 明確說明中間結果和用於表示它們的變量
- 表示最終導數各個分量的鏈式法則
- 對鏈式法則表達式內的中間結果上適當求和
