Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
快速python矩阵创建和迭代_Python_Performance_Python 2.7_Cpu Speed - Fatal编程技术网

快速python矩阵创建和迭代

快速python矩阵创建和迭代,python,performance,python-2.7,cpu-speed,Python,Performance,Python 2.7,Cpu Speed,我需要从权重矩阵的值开始创建一个矩阵。就创建和迭代矩阵的速度而言,哪种结构是保持矩阵的最佳结构?我在考虑列表列表或numpy 2D数组,但它们对我来说都很慢。 我需要的是: numpy array A = np.zeros((dim, dim)) for r in range(A.shape[0]): for c in range(A.shape[0]): if(r==c): A.itemset(node_degree[r]) el

我需要从权重矩阵的值开始创建一个矩阵。就创建和迭代矩阵的速度而言,哪种结构是保持矩阵的最佳结构?我在考虑列表列表或numpy 2D数组,但它们对我来说都很慢。 我需要的是:

numpy array
A = np.zeros((dim, dim))
for r in range(A.shape[0]):
    for c in range(A.shape[0]):
        if(r==c):
            A.itemset(node_degree[r])
        else:
            A.itemset(arc_weight[r,c])

其中dim也可以是20000,node_degree是一个向量,arc_weight是另一个矩阵。我用C++写的,它在0.5秒内使用了少于20秒,而其他两个在Python中使用了超过20秒。我知道Python不是C++,但是我需要尽可能快。
谢谢大家。

有一件事是,如果您已经知道列表的大小,就不应该将其添加到列表中

首先使用列表理解预先分配内存,并使用
xrange()
而不是
range()
生成
r,c
值,因为您使用的是Python<3.x(请参阅):

更好的是,您可以使用以下工具一次性构建所需:

l = [[node_degree[r] if r == c else arc_weight[r,c] 
            for c in xrange(dim)] for r in xrange(dim)]

与最初的实现相比,这应该使用更少的内存(因为使用了
xrange()
生成器),并且使用更少的时间,因为您不需要通过预先指定维度来重新分配内存。

一件事是,如果您已经知道列表的大小,则不应该将其追加到列表中

首先使用列表理解预先分配内存,并使用
xrange()
而不是
range()
生成
r,c
值,因为您使用的是Python<3.x(请参阅):

更好的是,您可以使用以下工具一次性构建所需:

l = [[node_degree[r] if r == c else arc_weight[r,c] 
            for c in xrange(dim)] for r in xrange(dim)]

与原始实现相比,这应该使用更少的内存(因为使用了
xrange()
生成器),并且由于不需要通过预先指定维度来重新分配内存,因此使用的时间应该更少。

Numpy矩阵通常更快,因为它们知道自己的维度和条目类型

在您的特定情况下,由于已经创建了arc_权重和node_度矩阵,因此可以直接从arc_权重创建矩阵,然后替换对角线:

A = np.matrix(arc_matrix)
np.fill_diagonal(A, node_degree)
另一个选项是用一个函数替换双循环,该函数将右元素置于每个位置,并从该函数创建一个矩阵:

def fill_matrix(r, c):
    return arc_weight[r,c] if r != c else node_degree[r]

A = np.fromfunction(fill_matrix, (dim, dim))
根据经验,使用numpy必须不惜一切代价避免循环。第一种方法应该更快,但您应该分析这两种方法,以查看哪些方法适合您。您还应该考虑到,您似乎在复制内存中的数据集,因此,如果数据集太大,您可能会遇到麻烦。最好的办法是直接创建矩阵,避免弧权重和节点度

编辑:列表理解和numpy矩阵创建之间的一些简单时间比较。因为我不知道你的弧权和节点度是如何定义的,所以我只做了两个随机函数。似乎
numpy.fromfunction
会抱怨函数是否有条件,所以我分两步构造矩阵

import numpy as np

def arc_weight(a,b):
    return a+b

def node_degree(a):
    return a*a

def create_as_list(N):
    return [[arc_weight(c,r) if c!=r else node_degree(c) for c in xrange(N)] for r in xrange(N)]

def create_as_numpy(N):
    A = np.fromfunction(arc_weight, (N,N))
    np.fill_diagonal(A, node_degree(np.arange(N)))
    return A
这里是
N=2000
的计时:

time A = create_as_list(2000)
CPU times: user 839 ms, sys: 16.5 ms, total: 856 ms
Wall time: 845 ms

time A = create_as_numpy(2000)
CPU times: user 83.1 ms, sys: 12.9 ms, total: 96 ms
Wall time: 95.3 ms

Numpy矩阵通常更快,因为它们知道自己的维度和条目类型

在您的特定情况下,由于已经创建了arc_权重和node_度矩阵,因此可以直接从arc_权重创建矩阵,然后替换对角线:

A = np.matrix(arc_matrix)
np.fill_diagonal(A, node_degree)
另一个选项是用一个函数替换双循环,该函数将右元素置于每个位置,并从该函数创建一个矩阵:

def fill_matrix(r, c):
    return arc_weight[r,c] if r != c else node_degree[r]

A = np.fromfunction(fill_matrix, (dim, dim))
根据经验,使用numpy必须不惜一切代价避免循环。第一种方法应该更快,但您应该分析这两种方法,以查看哪些方法适合您。您还应该考虑到,您似乎在复制内存中的数据集,因此,如果数据集太大,您可能会遇到麻烦。最好的办法是直接创建矩阵,避免弧权重和节点度

编辑:列表理解和numpy矩阵创建之间的一些简单时间比较。因为我不知道你的弧权和节点度是如何定义的,所以我只做了两个随机函数。似乎
numpy.fromfunction
会抱怨函数是否有条件,所以我分两步构造矩阵

import numpy as np

def arc_weight(a,b):
    return a+b

def node_degree(a):
    return a*a

def create_as_list(N):
    return [[arc_weight(c,r) if c!=r else node_degree(c) for c in xrange(N)] for r in xrange(N)]

def create_as_numpy(N):
    A = np.fromfunction(arc_weight, (N,N))
    np.fill_diagonal(A, node_degree(np.arange(N)))
    return A
这里是
N=2000
的计时:

time A = create_as_list(2000)
CPU times: user 839 ms, sys: 16.5 ms, total: 856 ms
Wall time: 845 ms

time A = create_as_numpy(2000)
CPU times: user 83.1 ms, sys: 12.9 ms, total: 96 ms
Wall time: 95.3 ms

复制一份
arc\u weight
并用
node\u degree
中的值填充对角线。对于20000乘20000的输出,在我的机器上大约需要1.6秒:

>>> import numpy
>>> dim = 20000
>>> arc_weight = numpy.arange(dim**2).reshape([dim, dim])
>>> node_degree = numpy.arange(dim)
>>> import timeit
>>> timeit.timeit('''
... A = arc_weight.copy()
... A.flat[::dim+1] = node_degree
... ''', '''
... from __main__ import dim, arc_weight, node_degree''',
... number=1)
1.6081738501125764

一旦你有了你的数组,尽量不要迭代它。与广播运算符和NumPy内置函数相比,Python级别的循环是一场性能灾难。

复制
arc\u weight
并用
节点度的值填充对角线。对于20000乘20000的输出,在我的机器上大约需要1.6秒:

>>> import numpy
>>> dim = 20000
>>> arc_weight = numpy.arange(dim**2).reshape([dim, dim])
>>> node_degree = numpy.arange(dim)
>>> import timeit
>>> timeit.timeit('''
... A = arc_weight.copy()
... A.flat[::dim+1] = node_degree
... ''', '''
... from __main__ import dim, arc_weight, node_degree''',
... number=1)
1.6081738501125764

一旦你有了你的数组,尽量不要迭代它。与广播运算符和NumPy内置函数相比,Python级别的循环是一场性能灾难。

稀疏矩阵在您的情况下(即大部分为零)有效吗?请尝试Cython。它应该能够达到C速度,同时还有Python接口。你也可以考虑使用DICT,其中键是行/CL。这会给你快速查找,虽然我不认为它会在创建上节省你的任何东西。如果你已经知道它的大小,你不应该追加到列表中。首先使用'l=[[0代表x范围内的x(m)]代表x范围内的x(n)]'预先分配内存。请看。稀疏矩阵在您的情况下有效吗(即大部分为零)?试试Cython。它应该能够达到C速度,同时还有Python接口。你也可以考虑使用DICT,其中键是行/CL。这会给你快速查找,虽然我不认为它会在创建上节省你的任何东西。如果你已经知道它的大小,你不应该追加到列表中。首先使用'l=[[0代表x范围内的x(m)]代表x范围内的x(n)]'预先分配内存。第二个错误是:fill_matrix()