首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何快速存储numpy对象(矩阵)?

如何快速存储numpy对象(矩阵)?
EN

Stack Overflow用户
提问于 2017-03-25 12:06:25
回答 2查看 78关注 0票数 1

我必须存储一个numpy矩阵的列表。我尝试过两种方法:

1.创建一个list并追加如下:

代码语言:javascript
复制
ls_ws=[]
for ind in range(iterations):
    ...
    ls_ws.append(ls_w) # ls_w is a matrix of size 6,1

问题:在开始时速度快,在结束时变得非常慢。

2.创建一个零矩阵并对其进行修改:

代码语言:javascript
复制
for ind in range(iterations):
    ...
    ls_ws=np.matrix(np.zeros((6,iterations))) 

问题:,我不是很确定,但不管每次迭代的速度如何,这个速度似乎都是一样的。

奇怪的是,如果我把迭代设置为小数目,那就太快了。但是,如果我把它设为1500这样的大数,那么每次迭代(甚至是第一次迭代)都会非常慢。

第二种方法应该是快速的,但如果我将迭代设置为大量的话,则会非常慢。为什么?如何解决这个问题?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-03-25 12:20:17

我认为这里几乎有一个很好的解决方案,但是您对列和行的处理可能会影响性能:

代码语言:javascript
复制
ls_ws=np.matrix(np.zeros((6,iterations))) 
for ind in range(iterations):
    ...
    ls_ws[:,ind]=ls_w

您应该在第一个维度中迭代,而不是在最后一个维度中迭代。您可以交换维度,也可以这样做:

代码语言:javascript
复制
ls_ws=np.matrix(np.zeros((6,iterations), order='F')) 

当数组很大时,这可能会有所帮助,因为您将访问6个元素的连续块,而不是每次迭代中的零散位。

票数 5
EN

Stack Overflow用户

发布于 2017-03-25 16:22:19

附加了一个简单的列表版本:

代码语言:javascript
复制
def foo1(N):
    alist = []
    for _ in range(N):
        alist.append([1,2,3,4,5,6])
    return np.array(alist)

带N的时间尺度平滑

代码语言:javascript
复制
In [4]: timeit foo1(100)
10000 loops, best of 3: 123 µs per loop
In [5]: timeit foo1(1000)
1000 loops, best of 3: 1.23 ms per loop
In [6]: timeit foo1(10000)
100 loops, best of 3: 12.3 ms per loop
In [7]: timeit foo1(100000)
10 loops, best of 3: 129 ms per loop
In [8]: timeit foo1(1000000)
1 loop, best of 3: 1.29 s per loop
In [9]: timeit foo1(10000000)
1 loop, best of 3: 12.9 s per loop

列表追加可能会导致大列表的速度减慢。列表使用缓冲区来保存指针,加上一些增长空间。当它增长超过那个空间时,它必须得到更多。如果不能扩展“就地”,则必须请求新的空间并复制所有指针。这可以减缓非常大的列表的速度,这些列表接近于填充内存。随着时间从123移到129,我可能会看到这方面的迹象。

代码语言:javascript
复制
def foo2(N):
    out = np.zeros((N,6),int)
    for i in range(N):
        out[i,:] = [1,2,3,4,5,6]
    return out

时间也以N表示,是列表情况的两倍:

代码语言:javascript
复制
In [15]: timeit foo2(100)
1000 loops, best of 3: 242 µs per loop
In [16]: timeit foo2(1000)
100 loops, best of 3: 2.52 ms per loop
In [17]: timeit foo2(10000)
10 loops, best of 3: 24.6 ms per loop
In [18]: timeit foo2(100000)
1 loop, best of 3: 249 ms per loop
In [19]: timeit foo2(1000000)
1 loop, best of 3: 2.52 s per loop
In [20]: timeit foo2(10000000)
1 loop, best of 3: 25.2 s per loop

在最后一个维度上迭代没有时间上的区别。

代码语言:javascript
复制
def foo3(N):
    out = np.zeros((6,N),int)
    for i in range(N):
        out[:,i] = [1,2,3,4,5,6]
    return out

在一次分配/创建6个元素的同时迭代1000次是糟糕的numpy实践。如果必须迭代,最好在每次执行大型操作时循环几次。例如6循环与1000个项目数组。

如果我将迭代向下移到编译后的代码,则时间要快得多。

代码语言:javascript
复制
def foo4(N):
    out = np.zeros((N,6),int)
    out[...] = [1,2,3,4,5,6]
    return out

In [28]: timeit foo4(1000)
.... cached.
10000 loops, best of 3: 20.4 µs per loop
In [29]: timeit foo4(100000)
1000 loops, best of 3: 1.45 ms per loop

您可以讨论保存矩阵,甚至分配一个np.matrix。那么让我们看看这会产生什么效果:

代码语言:javascript
复制
def foo1m(N):
    alist = []
    for _ in range(N):
        alist.append(np.matrix([1,2,3,4,5,6]).T)
    return np.concatenate(alist, axis=1)

def foo2m(N):
    out = np.matrix(np.zeros((6,N),int))
    for i in range(N):
        out[:,i] = np.matrix([1,2,3,4,5,6]).T
    return out

In [62]: timeit foo1(1000)
1000 loops, best of 3: 1.32 ms per loop
In [63]: timeit foo1m(1000)
100 loops, best of 3: 18 ms per loop
In [64]: timeit foo2(1000)
100 loops, best of 3: 2.75 ms per loop
In [65]: timeit foo2m(1000)
10 loops, best of 3: 28.2 ms per loop

这使得每次/迭代次数增加了10倍。matrixndarray的一个子类,需要更多的处理(强制2d等)。

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

https://stackoverflow.com/questions/43016121

复制
相关文章

相似问题

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