Python Numpy矩阵行比较

Python Numpy矩阵行比较,python,performance,numpy,matrix,comparison,Python,Performance,Numpy,Matrix,Comparison,问题更多地集中在计算的性能上 我有两个矩阵,列数相同,行数不同。一个矩阵是“模式”,其行必须分别与其他矩阵行(所有行)进行比较,然后才能提取平均值的统计值,即模式、标准、,。。。 我有下面的矩阵,计算如下: numCols = 10 pattern = np.random.randint(0,2,size=(7,numCols)) matrix = np.random.randint(0,2,size=(5,numCols)) comp_mean = np.zeros(pattern.shap

问题更多地集中在计算的性能上

我有两个矩阵,列数相同,行数不同。一个矩阵是“模式”,其行必须分别与其他矩阵行(所有行)进行比较,然后才能提取平均值的统计值,即模式、标准、,。。。 我有下面的矩阵,计算如下:

numCols = 10
pattern = np.random.randint(0,2,size=(7,numCols))
matrix = np.random.randint(0,2,size=(5,numCols))

comp_mean = np.zeros(pattern.shape[0])
for i in range(pattern.shape[0]):
    comp_mean[i] = np.mean(np.sum(pattern[i,:] == matrix, axis=1))

print comp_mean # Output example: [ 1.6  1.   1.6  2.2  2.   2.   1.6]
这是清楚的。问题是两者的矩阵行数都要大得多(~1.000.000)。所以这个代码运行得很慢。我试图实现numpy语法,因为有时它会让我感到惊讶,因为它提高了计算时间。因此,我编写了以下代码(可能很奇怪,但它可以工作!):

但是,此代码比上一个使用“for”bucle的代码慢。因此,我想知道是否有可能加快计算速度

编辑

我已经检查了实矩阵不同方法的运行时间,结果如下:

  • Me-进近1:18.04
  • Me-进近2:303.10
  • 迪瓦卡-进近1:18.79秒
  • 迪瓦卡-进近2:65.11
  • 迪瓦卡-接近3.1:137.78
  • 迪瓦卡-进近3.2:59.59
  • 迪瓦卡-进近4:6.06
编辑(2)

以前在笔记本电脑中执行的运行。我已经在桌面上运行了代码。我避免了最坏的结果,新的运行时现在不同了:

  • Me-接近1:6.25
  • 迪瓦卡-进近1:4.01
  • 迪瓦卡-进近2:3.66秒
  • 迪瓦卡-进近4:3.12
这里可以建议使用的方法很少

方法#1

out = np.mean(np.sum(pattern[:,None,:] == matrix[None,:,:],2),1)
方法#2

mrows = matrix.shape[0]
prows = pattern.shape[0]
out = (pattern[:,None,:] == matrix[None,:,:]).reshape(prows,-1).sum(1)/mrows
方法#3

mrows = matrix.shape[0]
prows = pattern.shape[0]
out = np.einsum('ijk->i',(pattern[:,None,:] == matrix[None,:,:]).astype(int))/mrows
# OR out = np.einsum('ijk->i',(pattern[:,None,:] == matrix[None,:,:])+0)/mrows

方法#4

如果
矩阵
中的行数很大,那么最好坚持使用for循环,以避免这种情况下的巨大内存需求,这也可能导致运行时变慢。相反,我们可以在每个循环迭代中进行一些优化。下面是一个可能的优化-

mrows = matrix.shape[0]
comp_mean = np.zeros(pattern.shape[0])
for i in range(pattern.shape[0]):
    comp_mean[i] = (pattern[i,:] == matrix).sum()
comp_mean = comp_mean/mrows

你能试试这个吗:

import scipy.ndimage.measurements

comp_mean = np.zeros(pattern.shape[0])
for i in range(pattern.shape[0]):
    m = scipy.ndimage.measurements.histogram(matrix,0,1,2,pattern[i],[0,1])
    comp_mean[i] = m[0][0]+m[1][1]
comp_mean /= matrix.shape[0]

关于。

pattern有多大?@Divakar,对于公开的运行时测试,pattern number rows 100.000和matrix 1.000 rows。检查添加的方法#4?@Divakar您的上一种方法具有最佳性能。你们认为它仍然有可能更进一步,或者正如你们所说的,因为矩阵太大,所以最好还是坚持一个for循环?我将在一台内存大的机器上尝试同样的代码,以检查这是否会成为计算上的瓶颈。看看它在高端机器上的表现肯定会很有趣。对于矢量化的代码和庞大的数据量,总是会有这种争斗,特别是当操作是一种简化时。对#4进行了轻微的编辑,虽然我怀疑不会产生太大的影响。此代码的问题是,模式行只能包含0或1,这使得m[0][0]或m[1][1]不存在,并返回TypeError。我试着用下面的
comp_mean[I]=int(如果np.size(m[0])==1 else m[0][0])+int(如果np.size(m[1])==1 else m[1][1])
来更改您的行,这可能不是最优化的行,因为运行时间是250.35秒。如果您找到另一种更好的方法,请告诉我如何检查runtime.3标签。我修改了您的代码,但正如我所解释的,当其中一个标签不在您在循环中比较的模式行中时,就会出现问题,因为m[n][n]不存在,它会给出一个类型错误并停止执行。@我会尝试类似于m=scipy.ndimage.measures.histogram(矩阵,0,2,3,模式[I],[0,1,2]),然后是m[0][0]+m[1][1]+m[2]这就是我在提到我修改了你的代码时所尝试的。然而,正如我所说的,当模式中的一行没有一个标签的值时(假设一行上都是零),m[1][1]就不存在。它是空的。因此,这会导致停止执行时出现TypeError。试着用下面的矩阵来理解我的意思:
pattern=np.array([1,1,1,1,1,1,1,1,1,1,0],[1,0,0,1,1,1,0],[0,1,1,1,1,1,1,0,0])
OK,我明白了;这个想法可能不是很好。我之所以建议使用它,是因为scipy.ndimage对于一些与数组上的“标签”相关的计算非常快速,但您自己的问题似乎有点不同。。。和
np.einsum
。。。有趣+1.@rayryeng这么大的缩减操作的内存需求是最大的原因,
matrix
pattern
大得多可能是原因。@rayryeng,我同意你的看法,
np.einsum
很有趣。我甚至不知道这个函数:S@isal我发现这一页更详细:
numpy
文档非常不准确。
import scipy.ndimage.measurements

comp_mean = np.zeros(pattern.shape[0])
for i in range(pattern.shape[0]):
    m = scipy.ndimage.measurements.histogram(matrix,0,1,2,pattern[i],[0,1])
    comp_mean[i] = m[0][0]+m[1][1]
comp_mean /= matrix.shape[0]