numpy是否提供了广义的内在产品?

lla*_*ram 8 python numpy

大多数面向数组的语言,如APL或J都有某种形式的广义内积,它可以像标准矩阵乘法一样,但支持任意运算来代替标准运算.例如,在J中+/ . *是标准乘法 - 然后和,但您也可以例如<./ . +获得add-then-min操作(例如,通过图形逐步更新最短路径的长度).

在慢速和仅2D的Python中,这将是这样的:

import numpy as np

def general_inner(f, g, x, y):
    return np.array([[f(g(x1, y1)) for y1 in y.T] for x1 in x])

x = np.arange(1, 5, dtype="float").reshape((2, 2))
y = np.array([[0.9], [0.1]])
assert(x.dot(y) == general_inner(np.sum, np.multiply, x, y))
Run Code Online (Sandbox Code Playgroud)

是否numpy提供任何直接支持这种模式的东西?

Die*_*Epp 4

你可以通过切片到达那里。我们可以重塑这两个参数,以便操作将被广播而不是按元素执行,然后沿不需要的轴执行归约操作。

import numpy

a = numpy.array([[1, 2, 3],
                 [4, 5, 6]])
b = numpy.array([[7, 8],
                 [9, 10],
                 [11, 12]])

# Ordinary matrix multiplication
print(a @ b)
# Matrix multiplication using broadcasting
print(numpy.sum(a[:,:,numpy.newaxis] * b[numpy.newaxis,:,:], axis=1))
# Our "generalized" version
print(numpy.min(a[:,:,numpy.newaxis] + b[numpy.newaxis,:,:], axis=1))
Run Code Online (Sandbox Code Playgroud)

我不太愿意将其称为“广义内积”,因为内积具有新版本所缺乏的特定数学结构。

其基本工作原理是,anynumpy.newaxis的长度为 1 并进行广播,因此:

a[:,:,numpy.newaxis] * b[numpy.newaxis,:,:]
Run Code Online (Sandbox Code Playgroud)

给我们:

result[i,j,k] = a[i,j] * b[j,k]
Run Code Online (Sandbox Code Playgroud)

或者如果它可以帮助你理解(我发现广播有时有点令人困惑),

aa = a[:,:,numpy.newaxis]
bb = b[numpy.newaxis,:,:]
result[i,j,k] = aa[i,j,0] * bb[0,j,k]
Run Code Online (Sandbox Code Playgroud)