h = x @ W1 # x:(N,3) W1:(3,4) h:(N,4)
a = tanh(h) # a:(N,4)
y = a @ W2 # W2:(4,2) y:(N,2)
loss = ... # 假设 dy 已知,形状 (N,2)
试着推出:dW1, da, dh, dW2:
dy: shape: (N, 2);
dW2: shape: (4,2);
da: (N,4).注意:a和形状要和da的形状一样;
正确的凑法——目标是 da (N,4):
手上有 dy (N,2) 和 W2 (4,2)
da 要 (N, 4), N 是要在前的 → dy 打头(它的 N 在前)
要消掉 2、得到 4 → 所以要把 W2 转置成 (2,4) 接后面
(N,2) @ (2,4) = (N,4)
dh: a和h的shape一样,a:(N,4),h:(N,4), dh=(1-a**2)*da;
dW1: (3,4)
====== 加上bias的测试:
y = a @ W2 + b2 # b2 shape: (2,)
已知 dy (N,2),求 db2。提示:用"广播的反向要 sum 回去"那条规则,想想 b2 前向被复制了几份、在哪个维度?
a shape: (N,4);
W2 shape: (4,2);
因为a @ W2 = (N,2), b2 shape: (2,),被广播成(N,2)加上去,相当于复制了N份。
反向时b2收到的形状是(N,2),但db2必须是(2,) (因为b2的形状必须和db2一样),所以把多出来的维度sum掉:
db2 = dy.sum(0) # 把dim=0(N那维)加掉,变回(2,)。
====== 分叉相加的测试:
y = x * 7,dy/dx = 7。因为每当x增加1,y就会增加7;
y = x - 100,dy/dx = 1。
y = x * 3 + 10,dy/dx = 3。
常数对导数没有影响。