【问题标题】:Create matrix with numpy from a function in vectorized fashion?用矢量化方式从函数中创建带有 numpy 的矩阵?
【发布时间】:2020-10-13 16:29:05
【问题描述】:

假设我有两个数组xt,长度为N,我想创建一个矩阵,其中

M_i,j = t_i * t_j * func(x_i, x_j)

在这种情况下,func() 只接受x 的两个元素并返回一个标量值。

t.shape = (N, )
x.shape = (N, 2)

// expected
M.shape = (N, N)

问题是:这是否可以在不使用 numpy 以矢量化方式循环整个矩阵的情况下完成?我知道有一些方法可以通过函数填充矩阵,问题是,这里的函数参数取决于让我卡住的矩阵的索引。

【问题讨论】:

  • 这取决于func。如果func 可以广播它的参数,它应该只是M = t[:, np.newaxis] * t * func(x[:, np.newaxis], x)(或者使用M = np.einsum('i,j,ij->ij', t, t, func(x[:, np.newaxis], x)) 可能会更有效)。
  • @jdehesa 是的,我已经为我的特定功能找到了解决方案,如我的回答中所述。但我想一般情况下是做不到的..

标签: python arrays numpy vectorization


【解决方案1】:

不确定最短的方法,但有可能

> np.diag(t) @ np.fromfunction(lambda i, j: x[i] + x[j], (2, 2), dtype=int) @ np.diag(t)

array([[ 0, 15],
       [15, 50]])

函数被定义为一个简单的 lambda,用你自己的替换。 这里我用过

> t=np.array([3,5])
> x=np.array([0,1])

【讨论】:

  • 我在这里仍然有一些错误,因为在我的情况下,中间项返回一个标量。这是我的实现(func() 应该计算一个 rbf 内核):np.fromfunction(lambda i, j: np.exp((-np.linalg.norm(x[i] - x[j]) ** 2) / (2 * self.sigma ** 2)), (x.shape[0], x.shape[0]), dtype=int)
  • 您将norm 应用于标量,我认为这就是它不起作用的原因。由于您要平方,因此您甚至不需要绝对值。
  • x 的每个元素都是一个 (2, ) 数组,所以这应该仍然是正确的,因为两个元素之间的差异也是一个向量...我取向量的范数,然后对 skalar 结果求平方。
  • 好的,我在示例中使用 x 作为一维数组。
【解决方案2】:

好的,在这种特殊情况下,我能够回答我自己的问题,因为我最初采用两个输入的函数实际上只是计算它们的差异,然后使用该结果计算进一步的值。

考虑到这一点,我能够创建一个“差异矩阵”并以向量化方式使用标准 numpy 函数,如下所示(通过将我的函数分解为其组件):

原始函数(RBF内核):

def CalculateGaussKernel(self, x1minusx2):
    return np.exp((-np.linalg.norm(x1minusx2) ** 2) / (2 * self.sigma ** 2))

以向量化方式从 OP 计算公式的代码:

t_outer = np.outer(t, t)
DiffMat = x.reshape(-1, 1, 2) - x
KernelMat = np.exp(-(np.linalg.norm(DiffMat, axis=2)**2) / (2 * self.sigma**2))
K = np.multiply(t_outer, KernelMat)

如前所述,这仅由于我的特定功能的性质而起作用。 @karakfa 为一般功能提供了另一个答案,但是到目前为止我还不能让它工作。无论如何,也许他的回答更适合我的问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-30
    • 2019-10-18
    • 1970-01-01
    • 2019-05-13
    相关资源
    最近更新 更多