としましょう。c = a + b
ですが、a
とb
はndarray
です。その形状は必ずしも同じではありません。つまり、general broadcasting rulesに続く2つの配列である可能性があります。numpyでのブロードキャスト追加の微分を計算するためのもっとpythonicな方法?
私はいくつかの出力dl/dc
の派生語を持っています。dl/da
を計算したいと思います。 a
とb
が同じ形状の場合、dl/da = dl/db = dl/dc
です。しかし、私はa.shape == (3,)
とb.shape == (2,3)
のように、このようないくつかの追加があるかもしれないので、c[i][j] = a[j] + b[i][j]
。つまり、dl/da[j] = sum_i c[i][j]
を意味します。一般に、dl/da
は、a
でブロードキャストされたすべての軸上のdl/dc
の合計です。
a
と
b
のチェーンルール誘導体を計算するために、私は次の関数を書いたが、私はそれが非常にニシキヘビはないと感じ、そしておそらくより効率的に行うことができます:私は実際に終わった
def addition_derivatives(x, y, d):
flip = False
if x.ndim < y.ndim: # x should have higher ndim
flip = True
x, y = y, x
S = x.shape # shape of array with higher ndim
s = y.shape # shape of array with lower ndim
# figure out which axes will be broadcast in which arrays
n = len(S)
# impute missing ones in the shape of the smaller array as per:
# https://docs.scipy.org/doc/numpy/user/basics.broadcasting.html#general-broadcasting-rules
s = tuple(1 if i < len(S) - len(s) else s[i - (len(S) - len(s))] for i in range(n))
axis_x = []
axis_y = []
for i in range(n):
assert s[i] == S[i] or s[i] == 1 or S[i] == 1
if S[i] == 1 and s[i] != 1:
axis_x.append(i)
if s[i] == 1 and S[i] != 1:
axis_y.append(i)
axis_x, axis_y = map(tuple, (axis_x, axis_y))
# compute the derivatives
dx = np.sum(d, axis=axis_x).reshape(x.shape)
dy = np.sum(d, axis=axis_y).reshape(y.shape)
if flip:
dx, dy = dy, dx
return dx, dy