首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >有了Python,我如何才能最有效地从NxM矩阵元素中减去Nx1矩阵?

有了Python,我如何才能最有效地从NxM矩阵元素中减去Nx1矩阵?
EN

Stack Overflow用户
提问于 2018-08-29 07:18:06
回答 2查看 968关注 0票数 0

x是由以下所定义的3x4 Numpy矩阵:

代码语言:javascript
运行
复制
x = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12]])
In: x
Out:
array([[ 1,  2,  3,  4],
       [ 5,  6,  7,  8],
       [ 9, 10, 11, 12]])

y是由以下所定义的3x1矩阵:

代码语言:javascript
运行
复制
y = np.array([3, 6 ,9])
In: y
Out: array([3, 6, 9])

如何才能最有效地从y - x元素中减去这样的结果:

代码语言:javascript
运行
复制
array([[ 2,  1,  0, -1],
       [ 1,  0, -1, -2],
       [ 0, -1, -2, -3]])

我找到的唯一办法是:

代码语言:javascript
运行
复制
-1.0*(x.T + (-1.0*y)).T

然而,在分析时,我发现由于我多次进行上述计算,并且使用大矩阵,最后一行证明了这是我应用程序的瓶颈。因此,我问:是否有更好、更有效的方法来做到这一点?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-08-29 08:28:54

设y是由以下所定义的3x1矩阵: Y= np.array(3,6 ,9)

这不是一个3x1矩阵(这里有更多的信息):

代码语言:javascript
运行
复制
>>> y.shape
(3,)

生成一个3x1矩阵

代码语言:javascript
运行
复制
>>> y_new = np.array([[3], [6], [9]])
>>> y_new.shape
(3, 1)

或者从你现有的Y中得到:

代码语言:javascript
运行
复制
>>> y_new = y[:, np.newaxis]

一旦你有了一个3x1和一个3x4矩阵,你就可以把它们减去。

代码语言:javascript
运行
复制
>>> x - y_new
票数 1
EN

Stack Overflow用户

发布于 2018-08-29 09:28:56

正如其他人已经指出的,NumPy的广播业是您在这里的朋友。注意,由于这个广播规则,与其他面向矩阵的技术栈相比,在NumPy中使用转置操作的频率实际上要低得多(阅读: MATLAB/Octave)。

编辑的(重组)

关键是要得到一个正确的形状数组。最好的方法是使用带有额外np.newaxis/None值的切片。但是你也可以使用ndarray.reshape()

代码语言:javascript
运行
复制
import numpy as np
x = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12]])
y = np.array([3, 6 ,9]).reshape(-1, 1)  # same as: y = np.array([3, 6 ,9])[:, None]
y - x

最重要的是,正确形状的数组将允许使用numexpr,对于大型数组,它可能比NumPy更高效(如果瓶颈是该操作,那么它可能很适合您的算法):

代码语言:javascript
运行
复制
import numpy as np
import numexpr as ne

x = np.random.randint(1, 100, (3, 4))
y = np.random.randint(1, 100, (3, 1))

%timeit y - x
# The slowest run took 43.14 times longer than the fastest. This could mean that an intermediate result is being cached.
# 1000000 loops, best of 3: 879 ns per loop

%timeit ne.evaluate('y - x')
# The slowest run took 20.86 times longer than the fastest. This could mean that an intermediate result is being cached.
# 100000 loops, best of 3: 10.8 µs per loop

# not so exciting for small arrays, but for somewhat larger numbers...
x = np.random.randint(1, 100, (3000, 4000))
y = np.random.randint(1, 100, (3000, 1))

%timeit y - x
# 10 loops, best of 3: 33.1 ms per loop
%timeit ne.evaluate('y - x')
# 100 loops, best of 3: 10.7 ms per loop

# which is roughly a factor 3 faster on my machine

在这种情况下,你如何获得一个正确的账户并没有太大的不同--不管是切片还是整形--但是切片速度似乎是原来的两倍。给它加一些编号(根据评论编辑):

代码语言:javascript
运行
复制
import numpy as np

# creating the array does not depend too much as long as its size is the same

%timeit y = np.zeros((3000000))
# 838 µs ± 10.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit y = np.zeros((3000000, 1))
# 825 µs ± 12.7 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit y = np.zeros((3000, 1000))
# 827 µs ± 14.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)


# ...and reshaping / slicing is independent of the array size

x = np.zeros(3000000)
%timeit x[:, None]
# 147 ns ± 4.02 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
%timeit x.reshape(-1, 1)
# 214 ns ± 9.55 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

x = np.zeros(300)
%timeit x[:, None]
# 146 ns ± 0.659 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
%timeit x.reshape(-1, 1)
# 212 ns ± 1.56 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

不用说,%timeit基准应该是一丁点儿的。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52071644

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档