5

我想实现一个对角矩阵应用函数,它是通过d首先提供对角线,然后用x. 当然我不想创建一个实际的矩阵,因为只需要一个元素向量乘法。

现在,一些用户将提供一个对角线d的形状(k,),一些形状(k,1)。此外,x可以有形状(k,)(k,1). 我希望 apply() 方法的行为就像*for numpy 矩阵一样,因为结果具有与 input 相同的形状x

因此问题是:在 Python/Numpy 中,是否有一种非不确定的方法可以将两个 np.arraysxy形状(k,)(k,1)(以任何组合)元素相乘以使结果数组的形状为x

我做了一些实验[:,None]

x = np.empty((4,1))
y = np.empty(4)
(x * y).shape         # (4,4)  -- nope
(y * y).shape         # (4,)   -- yes
(x * y[:,None]).shape # (4, 1) -- yes
(y * y[:,None]).shape # (4,4)  -- nope

我当然可以将我的代码包装在 中if len(x.shape)==...:,但这感觉不是很pythonic。

建议?

4

2 回答 2

5

既然我理解了你的问题,我的建议就是重塑. 调用reshape返回一个视图,所以它不会产生任何大的复制成本或类似的东西。只需重新整形数组、相乘并再次整形:

>>> def shape_preserving_mult(x, y):
...     return (x.reshape((-1,)) * y.reshape((-1))).reshape(x.shape)
... 

或者更简洁地说,正如您和 rroowwllaandd 指出的那样:

>>> def shape_preserving_mult(x, y):
...     return x * y.reshape(x.shape)
... 
>>> shape_preserving_mult(x, y)
array([[ 0],
       [ 1],
       [ 4],
       [ 9],
       [16]])
>>> shape_preserving_mult(x, y.T)
array([[ 0],
       [ 1],
       [ 4],
       [ 9],
       [16]])
>>> shape_preserving_mult(x.T, y)
array([[ 0,  1,  4,  9, 16]])
>>> shape_preserving_mult(x.T, y.T)
array([[ 0,  1,  4,  9, 16]])

我之前建议的内容如下。

值得注意的是,如果你将一个 numpy 形状(1, 4)数组与一个形状数组相乘,(4,)你会得到接近你想要的东西。

>>> x = numpy.arange(5).reshape((5, 1))
>>> y = numpy.arange(5)
>>> x.shape
(5, 1)
>>> x.T.shape
(1, 5)
>>> y * x.T
array([[ 0,  1,  4,  9, 16]])

这没有 的形状a,但确实有 的形状a.T。你总是可以再次调用T结果。这也适用于形状数组(5,),因为一维数组上的转置操作不会导致任何变化。所以也许你可以这样做:

>>> def transposed_mult(x, y):
...     return (x.T * y).T
... 
>>> transposed_mult(x, y)
array([[ 0],
       [ 1],
       [ 4],
       [ 9],
       [16]])

但是,如果您传递一个 shape 数组,这当然会导致相反的问题(1, 5)

>>> transposed_mult(x.T, y)
array([[ 0,  0,  0,  0,  0],
       [ 0,  1,  2,  3,  4],
       [ 0,  2,  4,  6,  8],
       [ 0,  3,  6,  9, 12],
       [ 0,  4,  8, 12, 16]])

您在原始帖子中要求的确切内容也是如此transposed_mult,但如果您需要任何进一步的灵活性,它将无法按预期工作。事实上,您似乎需要额外的灵活性。

于 2012-04-22T13:05:39.670 回答
3

如果您可以假设xandy本质上都是一维数组,那么使用 numpy 的.flatten()数组方法:

>>> result=x.flatten()*y.flatten()

应该返回一个一维数组:

>>> result.shape
(4,)

为了保持您的形状,x您可以执行以下操作:

>>> result = x*y.reshape(x.shape)
>>> result.shape
(4,1)
于 2012-04-22T12:59:24.357 回答