Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/328.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.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_Algorithm_Scipy - Fatal编程技术网

Python 求相关矩阵

Python 求相关矩阵,python,algorithm,scipy,Python,Algorithm,Scipy,我有一个相当大的矩阵(大约50K行),我想打印矩阵中每一行之间的相关系数。我编写了如下Python代码: for i in xrange(rows): # rows are the number of rows in the matrix. for j in xrange(i, rows): r = scipy.stats.pearsonr(data[i,:], data[j,:]) print r 请注意,我正在使用scipy模块()提供的pea

我有一个相当大的矩阵(大约50K行),我想打印矩阵中每一行之间的相关系数。我编写了如下Python代码:

for i in xrange(rows): # rows are the number of rows in the matrix. 
    for j in xrange(i, rows):
        r = scipy.stats.pearsonr(data[i,:], data[j,:])
        print r  
请注意,我正在使用scipy模块()提供的
pearsonr
功能

我的问题是:有没有更快的方法?是否有一些矩阵划分技术,我可以使用


谢谢

您可以使用python多进程模块,将行分为10组,缓冲结果,然后打印出来(但这只会在多核机器上加快速度)

def myfunc(thelist):
    for i in xrange(thelist[0]:thelist[1]):
    ....
    thelist[2] = result

新解决方案

在看了Joe Kington的答案后,我决定研究
corrcoef()
代码,并受其启发进行以下实现

ms = data.mean(axis=1)[(slice(None,None,None),None)]
datam = data - ms
datass = np.sqrt(scipy.stats.ss(datam,axis=1))
for i in xrange(rows):
    temp = np.dot(datam[i:],datam[i].T)
    rs = temp / (datass[i:]*datass[i])
每个循环通过生成行i和行i到最后一行之间的皮尔逊系数。它非常快。它至少是单独使用
corrcoef()
的1.5倍,因为它不会冗余地计算系数和其他一些东西。它也会更快,并且不会给您带来50000行矩阵的内存问题,因为这样您可以选择存储每个r的集合,或者在生成另一个集合之前处理它们。在不存储任何r的长期数据的情况下,我能够在我全新的笔记本电脑上,在不到一分钟的时间内,在50000 x 10组随机生成的数据上运行上述代码

旧解决方案

首先,我不建议将r打印到屏幕上。对于100行(10列),打印时的时间差为19.79秒,而不使用代码时的时间差为0.301秒。如果你愿意的话,只需存储r并在以后使用它们,或者在进行过程中对它们进行一些处理,比如寻找一些最大的r

第二,您可以通过不冗余地计算某些数量来节省成本。皮尔逊系数是在scipy中使用一些可以预先计算的量来计算的,而不是每次使用一行时都进行计算。另外,您没有使用p值(p值也是由
pearsonr()
返回的),所以让我们也将其划掉。使用以下代码:

r = np.zeros((rows,rows))
ms = data.mean(axis=1)

datam = np.zeros_like(data)
for i in xrange(rows):
    datam[i] = data[i] - ms[i]
datass = scipy.stats.ss(datam,axis=1)
for i in xrange(rows):
    for j in xrange(i,rows):
        r_num = np.add.reduce(datam[i]*datam[j])
        r_den = np.sqrt(datass[i]*datass[j])
        r[i,j] = min((r_num / r_den), 1.0)
当我删除了p值的东西时,我的速度比直接的scipy代码快了大约4.8倍——如果我把p值的东西放在那里,速度是8.8倍(我使用了10列数百行)。我还检查了它是否给出了相同的结果。这不是一个很大的改进,但可能会有所帮助

最终,你会遇到这样一个问题:你正在计算(50000)*(50001)/2=1250025000皮尔逊系数(如果我计算正确的话)。这太多了。顺便说一下,真的不需要自己计算每一行的皮尔逊系数(它将等于1),但这只会节省您计算50000个Pearson系数的时间。使用上述代码,如果根据我在较小数据集上的结果,您的数据有10列,则我预计您的计算将花费大约4 1/4小时

你可以通过将上面的代码加入Cython或类似的东西来获得一些改进。如果你运气好的话,我希望你可能会比straight Scipy提高10倍。此外,正如Pyintsky所建议的,你可以进行一些多处理。

你试过仅仅使用吗?鉴于你没有使用p值,它应该可以精确地你想怎么做就怎么做,尽量不要大惊小怪。(除非我记不清皮尔逊的R是什么,这是很有可能的。)

只需快速检查随机数据的结果,它返回的结果与上面@Justin Peel的代码完全相同,运行速度快约100倍

例如,用1000行10列随机数据测试事物…:

import numpy as np
import scipy as sp
import scipy.stats

def main():
    data = np.random.random((1000, 10))
    x = corrcoef_test(data)
    y = justin_peel_test(data)
    print 'Maximum difference between the two results:', np.abs((x-y)).max()
    return data

def corrcoef_test(data):
    """Just using numpy's built-in function"""
    return np.corrcoef(data)

def justin_peel_test(data):
    """Justin Peel's suggestion above"""
    rows = data.shape[0]

    r = np.zeros((rows,rows))
    ms = data.mean(axis=1)

    datam = np.zeros_like(data)
    for i in xrange(rows):
        datam[i] = data[i] - ms[i]
    datass = sp.stats.ss(datam,axis=1)
    for i in xrange(rows):
        for j in xrange(i,rows):
            r_num = np.add.reduce(datam[i]*datam[j])
            r_den = np.sqrt(datass[i]*datass[j])
            r[i,j] = min((r_num / r_den), 1.0)
            r[j,i] = r[i,j]
    return r

data = main()
两个结果之间的最大绝对差值约为3.3e-16

和时间:

In [44]: %timeit corrcoef_test(data)
10 loops, best of 3: 71.7 ms per loop

In [45]: %timeit justin_peel_test(data)
1 loops, best of 3: 6.5 s per loop

应该做你想做的事情,而且速度更快。

你说得很对。起初我想
corrcoef
,但出于某种原因,我记得它速度较慢。我觉得有点不好意思,因为我相信我的坏内存,而不是尝试它。它更快,因为它使用矩阵乘法来消除python循环。+1em与corrcoef的区别在于,它使用的内存大约是所需内存的两倍。它几乎所有的系数都要计算两次。然而,更大的问题是内存,OP必须将数据分解以避免内存问题。它本质上会变成一个组合混乱。@Justin Peel-没错,corrcoef正在创建一个额外的温度输入数组的orary副本。这是速度和所用内存量之间的折衷。如果内存是主要约束条件,并且有50000行,那么您的解决方案会更好。事实上,我更多地考虑了它如何实际计算每个系数两次并存储它们,尽管您是对的,这也会产生额外的临时性输入的副本。我认为这(corrcoef)也许这是最好的方法,但你必须巧妙地将数据分割,然后小心地将其放回一起,才能得到所有的组合。我想看一个更全面的例子来说明你在这里的意思。我认为我的答案在这一点上与这个问题相去甚远,但如果你对多重处理感兴趣,请查看:……本质上您不需要在行中循环,而是创建一个函数和一个线程池,只需执行p.map(myfunc,xrange(rows))