我想实现一个对角矩阵应用函数,它是通过首先提供对角线 d
,然后用 x
进行一堆矩阵向量乘法而创建的。当然,我不想创建一个实际的矩阵,因为所需要的只是逐元素向量乘法。
现在,一些用户将提供形状为 (k,)
的对角线 d
,一些形状为 (k,1)
.此外,x
可以具有形状 (k,)
和 (k,1)
。我希望 apply() 方法的行为与 numpy 矩阵的 *
一样,因为结果具有与输入 x
相同的形状。
因此问题来了:在 Python/Numpy 中,是否有一种简单的方法来逐元素相乘两个形状为 ( 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。
建议?
最佳答案
既然我明白了你的问题,我的建议就是 reshape 。调用 reshape
返回一个 View ,因此它不会产生任何大的复制成本或类似的事情。简单地 reshape 数组,相乘,然后再次 reshape :
>>> def shape_preserving_mult(x, y):
... return (x.reshape((-1,)) * y.reshape((-1))).reshape(x.shape)
...
或者更简洁地说,正如您和 rroowwllaanndd 指出的那样:
>>> 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]])
我之前建议的实质内容保留在下面。
值得注意的是,如果将形状为 (1, 4)
的 numpy 数组与形状为 (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]])
但是,如果您传递形状为 (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
完全按照您在原始帖子中的要求进行操作,但如果您需要任何进一步的灵 active ,它不会按预期工作。事实上,您似乎需要额外的灵 active 。
关于python - 按元素乘以 1D-numpy 数组(形状(k,1)或(k,))并使结果具有第一个的形状,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10268061/