文章目錄
在神經網絡或機器學習的線性層(Linear Layer / Fully Connected Layer)中,經常會見到兩種形式的公式:
- 數學文獻或傳統線性代數寫法: y = W x + b \displaystyle y = W\,x + b y=Wx+b
- 一些深度學習代碼中寫法: y = x W T + b \displaystyle y = x\,W^T + b y=xWT+b
初次接觸時,很多人會覺得兩者“方向”不太一樣,不知該如何對照理解;再加上矩陣維度 ( in_features , out_features ) (\text{in\_features},\, \text{out\_features}) (in_features,out_features) 和 ( out_features , in_features ) (\text{out\_features},\, \text{in\_features}) (out_features,in_features) 的各種寫法常常讓人疑惑不已。本文將從數學角度和編程實現角度剖析它們的關系,并結合實際示例指出一些常見的坑與需要特別留意的下標對應問題。
1. 數學角度: y = W x + b \displaystyle y = W\,x + b y=Wx+b
在線性代數中,如果我們假設輸入 x x x 是一個列向量,通常會寫作 x ∈ R ( in_features ) \displaystyle x\in\mathbb{R}^{(\text{in\_features})} x∈R(in_features)(或者在更嚴格的矩陣形狀記法下寫作 ( in_features , 1 ) (\text{in\_features},\,1) (in_features,1))。那么一個最常見的全連接層可以表示為:
y = W x + b , y = W\,x + b, y=Wx+b,
其中:
- W W W 是一個大小為 ( out_features , in_features ) \bigl(\text{out\_features},\,\text{in\_features}\bigr) (out_features,in_features) 的矩陣;
- b b b 是一個 out_features \text{out\_features} out_features-維的偏置向量(形狀 ( out_features , 1 ) (\text{out\_features},\,1) (out_features,1));
- y y y 則是輸出向量,大小為 out_features \text{out\_features} out_features。
示例
假設 in_features = 3 \text{in\_features}=3 in_features=3, out_features = 2 \text{out\_features}=2 out_features=2。那么:
W ∈ R 2 × 3 , x ∈ R 3 × 1 , b ∈ R 2 × 1 . W \in \mathbb{R}^{2\times 3},\quad x \in \mathbb{R}^{3\times 1},\quad b \in \mathbb{R}^{2\times 1}. W∈R2×3,x∈R3×1,b∈R2×1.
矩陣寫開來就是:
W = [ w 11 w 12 w 13 w 21 w 22 w 23 ] , x = [ x 1 x 2 x 3 ] , b = [ b 1 b 2 ] . W = \begin{bmatrix} w_{11} & w_{12} & w_{13} \\[5pt] w_{21} & w_{22} & w_{23} \end{bmatrix},\quad x = \begin{bmatrix} x_{1}\\ x_{2}\\ x_{3} \end{bmatrix},\quad b = \begin{bmatrix} b_{1}\\ b_{2} \end{bmatrix}. W=[w11?w21??w12?w22??w13?w23??],x= ?x1?x2?x3?? ?,b=[b1?b2??].
那么線性變換結果 W x + b Wx + b Wx+b 可以展開為:
W x + b = [ w 11 x 1 + w 12 x 2 + w 13 x 3 w 21 x 1 + w 22 x 2 + w 23 x 3 ] + [ b 1 b 2 ] = [ w 11 x 1 + w 12 x 2 + w 13 x 3 + b 1 w 21 x 1 + w 22 x 2 + w 23 x 3 + b 2 ] . \begin{aligned} Wx + b &= \begin{bmatrix} w_{11}x_1 + w_{12}x_2 + w_{13}x_3 \\ w_{21}x_1 + w_{22}x_2 + w_{23}x_3 \end{bmatrix} + \begin{bmatrix} b_1 \\ b_2 \end{bmatrix} \\ &= \begin{bmatrix} w_{11}x_1 + w_{12}x_2 + w_{13}x_3 + b_1 \\ w_{21}x_1 + w_{22}x_2 + w_{23}x_3 + b_2 \end{bmatrix}. \end{aligned} Wx+b?=[w11?x1?+w12?x2?+w13?x3?w21?x1?+w22?x2?+w23?x3??]+[b1?b2??]=[w11?x1?+w12?x2?+w13?x3?+b1?w21?x1?+w22?x2?+w23?x3?+b2??].?
這就是最傳統、在數學文獻或線性代數課程中最常見的表示方法。
2. 編程實現角度: y = x W T + b \displaystyle y = x\,W^T + b y=xWT+b
在實際的深度學習代碼(例如 PyTorch、TensorFlow)中,經常看到的卻是下面這種寫法:
y = x @ W.T + b
注意這里 W.shape
通常被定義為 ( out_features , in_features ) (\text{out\_features},\, \text{in\_features}) (out_features,in_features),而 x.shape
在批量處理時則是 ( batch_size , in_features ) (\text{batch\_size},\, \text{in\_features}) (batch_size,in_features)。于是 (x @ W.T)
的結果是 ( batch_size , out_features ) (\text{batch\_size},\, \text{out\_features}) (batch_size,out_features)。
為什么會出現轉置?
因為在數學里我們通常把 x x x 當作“列向量”放在右邊,于是公式變成 y = W x + b y = Wx + b y=Wx+b。
但在編程里,尤其是處理批量輸入時,x
常寫成“行向量”的形式 ( batch_size , in_features ) (\text{batch\_size},\, \text{in\_features}) (batch_size,in_features),這就造成了在進行矩陣乘法時,需要將 W
(大小 ( out_features , in_features ) (\text{out\_features},\, \text{in\_features}) (out_features,in_features))轉置成 ( in_features , out_features ) (\text{in\_features},\, \text{out\_features}) (in_features,out_features),才能滿足「行×列」的匹配關系。
從結果上來看,
( batch_size , in_features ) × ( in_features , out_features ) = ( batch_size , out_features ) . (\text{batch\_size}, \text{in\_features}) \times (\text{in\_features}, \text{out\_features}) = (\text{batch\_size}, \text{out\_features}). (batch_size,in_features)×(in_features,out_features)=(batch_size,out_features).
所以,在代碼里就寫成 x @ W.T
,再加上偏置 b
(通常會廣播到 batch_size \text{batch\_size} batch_size 那個維度)。
本質上這和數學公式里 y = W x + b y = W\,x + b y=Wx+b 并無沖突,只是一個“列向量”和“行向量”的轉置關系。只要搞清楚最終你想讓輸出 y y y 的 shape 是多少,就能明白在代碼里為什么要寫 .T
。
3. 常見錯誤與易混點解析
有些教程或文檔,會不小心寫成:“如果我們有一個形狀為 ( in_features , out_features ) (\text{in\_features},\text{out\_features}) (in_features,out_features) 的權重矩陣 W W W……”——然后又要做 W x Wx Wx,想得到一個 out_features \text{out\_features} out_features-維的結果。但按照線性代數的常規寫法,行數必須和輸出維度匹配、列數必須和輸入維度匹配。所以 正確 的說法應該是
W ∈ R ( out_features ) × ( in_features ) . W\in\mathbb{R}^{(\text{out\_features}) \times (\text{in\_features})}. W∈R(out_features)×(in_features).
否則從矩陣乘法次序來看就對不上。
但這又可能讓人迷惑:為什么深度學習框架 torch.nn.Linear(in_features, out_features)
卻給出 weight.shape == (out_features, in_features)
? 其實正是同一個道理,它和上面“數學文獻里”用到的 W W W 形狀完全一致。
4. 小結
-
從數學角度:
最傳統的記號是
y = W x + b , W ∈ R ( out_features ) × ( in_features ) , x ∈ R ( in_features ) , y ∈ R ( out_features ) . y = W\,x + b, \quad W \in \mathbb{R}^{(\text{out\_features})\times(\text{in\_features})},\, x \in \mathbb{R}^{(\text{in\_features})},\, y \in \mathbb{R}^{(\text{out\_features})}. y=Wx+b,W∈R(out_features)×(in_features),x∈R(in_features),y∈R(out_features). -
從深度學習代碼角度:
- 由于批量數據常被視為行向量,每一行代表一個樣本特征,因此形狀通常是 ( batch_size , in_features ) (\text{batch\_size},\, \text{in\_features}) (batch_size,in_features)。
- 對應的權重
W
定義為 ( out_features , in_features ) (\text{out\_features},\, \text{in\_features}) (out_features,in_features)。為了完成行乘以列的矩陣運算,需要對W
做轉置:y = x @ W.T + b
- 得到的
y.shape
即 ( batch_size , out_features ) (\text{batch\_size},\, \text{out\_features}) (batch_size,out_features)。
-
避免踩坑:
- 寫公式時,仔細確認 in_features \text{in\_features} in_features、 out_features \text{out\_features} out_features 的位置以及矩陣行列順序。
- 編程實踐中理解“為什么要
.T
”非常重要:那只是為了匹配「行×列」的矩陣乘法規則,本質上還是和 y = W x + b y = Wx + b y=Wx+b 相同。
通過理解并區分“列向量”與“行向量”的不同慣例,避免因為矩陣維度或轉置不當而導致莫名其妙的錯誤或 bug。
參考鏈接
- PyTorch 文檔:
torch.nn.Linear
- 深度學習中的矩陣運算初步 —— batch_size 與矩陣乘法
- 常見線性代數符號:行向量與列向量