2010-08-09 30 views
11

Oldukça büyük (yaklaşık 50K satır) bir matrisim var ve matristeki her satır arasındaki korelasyon katsayısını yazdırmak istiyorum. Böyle Python kodunu yazdım:Korelasyon matrisini bulma

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 

ben scipy modülü (http://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.pearsonr.html) temin pearsonr fonksiyonu yararlanarak ediyorum lütfen unutmayın.

Sorum şu: Bunu yapmanın daha hızlı bir yolu var mı? Kullanabileceğim bazı matris bölme tekniği var mı?

Teşekkürler!

cevap

0

Eğer

http://docs.python.org/library/multiprocessing.html

(bu sadece olsa çok çekirdekli makinede hızlandıracaktı), 10 kümeler halinde piton çok işlemli modülü, yığın yukarı Satırlarınızı kullanmak sonuçlarınızı tampon ve daha sonra malzeme yazdırabilirsiniz

btw: Ayrıca, snippet'inizi bir işlev haline getirmeniz ve ayrıca veri birleştirme işleminin nasıl gerçekleştirileceğini de düşünmeniz gerekir. Her altişlem böyle bir liste var olan ... [startcord, stopcord, devetüyü] .. Joe kington cevabı baktıktan sonra güzel

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

Burada kastettiğiniz şeyin daha kapsamlı bir örneğini görmek isterim. – vgoklani

+0

Bence cevabım bu noktada bu sorudan çok uzaktır, ancak multiprocessiong ile ilgileniyorsanız, http://docs.python.org/library/multiprocessing.html adresine bakın. , bir işlev ve bir iş parçacığı havuzu oluşturmak ve sadece p.map (myfunc, xrange (satır)) – pyInTheSky

10

Yeni Çözüm

işe yarayabilecek, ben içine bakmaya karar verdi corrcoef() kodu ve aşağıdaki uygulamayı yapmak için ilham aldı.

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]) 

boyunca her döngü i ve satırları ı ile son satıra satır arasında Pearson katsayıları oluşturur. Çok hızlı. Sadece corrcoef()'u kullanmanın en az 1.5 katı kadardır çünkü katsayıları ve diğer birkaç şeyi gereksiz yere hesaplamamaktadır. Aynı zamanda daha hızlı olacaktır ve 50.000 satır matrisiyle bellek sorunlarını size vermeyecektir, çünkü daha sonra her bir r kümesini saklamayı veya başka bir set oluşturmadan önce bunları işlemeyi seçebilirsiniz. R'in uzun vadesini saklamaksızın, 50.000 x 10 set rasgele oluşturulmuş veriyi, yeni dizüstü bilgisayarımda bir dakikadan kısa bir süre içinde çalıştırabilmek için yukarıdaki kodu alabiliyordum.

Eski Çözüm

Birincisi, ekrana r en çıktısını tavsiye etmem. 100 satır (10 sütun) için bu, kodunuzu kullanmadan 0,301 saniye gibi bir baskı ile 19.79 saniyede bir fark yaratır. Sadece r'leri saklayın ve isterseniz daha sonra kullanın ya da en büyük r'lerden bazılarını aradığınız gibi bazı işlemleri gerçekleştirin. İkinci olarak, bazı miktarları gereksiz olarak hesaplayarak biraz tasarruf sağlayabilirsiniz. Pearson katsayısı, bir satırın kullanıldığı her zaman hesaplamak yerine önceden hesaplayabileceğiniz bazı miktarlar kullanılarak scipy cinsinden hesaplanır. Doğruca SciPy üzerinde yaklaşık 4.8x bir hızlandırması olsun

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) 

. Ayrıca, aşağıdaki kodu kullanarak bu da o yüzden çizmelerine izin de pearsonr() tarafından döndürülen p değeri (kullanmıyorsunuz kodu p-değeri maddelerini kaldırdığımda - 8.8x p-değerlerini burada bırakırsam (yüzlerce satır ile 10 sütun kullandım) aynı sonucu verdiğimi de kontrol ettim. gerçekten büyük bir gelişme, ama yardımcı olabilir.Nihayetinde, (50000) * (50001)/2 = 1,250,025,000 Pearson katsayıları (eğer doğru bir şekilde sayıyorsam) problemi ile uğraşıyorsunuz demektir. Bu çok fazla. Bu arada, her bir dizinin Pearson katsayısını kendi başına hesaplamaya gerek yoktur (1'e eşit olacaktır), ancak bu sadece 50.000 Pearson katsayısını hesaplamanızı sağlar. Yukarıdaki kodla, daha küçük veri kümelerindeki sonuçlara dayanarak verilere göre 10 sütununuz varsa, hesaplama yapmak için yaklaşık 4 1/4 saat geçmesini beklerim. Yukarıdaki kodu Cython'a veya benzer bir şeye alarak biraz iyileştirme yapabilirsiniz. Şanslıysan, düz Scipy üzerinden 10 katına çıkabileceğini umuyorum. Ayrıca, pyInTheSky tarafından önerildiği gibi, bazı çok işlem yapabilirsiniz.

6

numpy.corrcoef kullanıyor musunuz? P-değerlerini kullanmadığınız şekilde görünmek, tam istediğiniz şeyi yapmalı ve mümkün olduğunca az yaygara yapmalıdır. (Tam olarak ne kadar R'nin ne olduğunu yanlış hatırlamıyorsam, bu mümkün değil.)

Sadece rastgele verilerdeki sonuçları hızlıca kontrol ederek, yukarıdaki @Justin Peel'in koduyla aynı şeyi tekrar gönderir ve ~ 100x daha hızlı çalışır . 1000 satır ve rasgele veriler 10 sütunlu işler test Örneğin

, ...:

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() 

maksimum mutlak fark verir ~ 3.3 '-16 iki sonuç

ve zamanlar arasındaki :

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 

numpy.corrcoef istediğini sadece yapmalıyım ve bu çok hızlı.

+0

yapmak oldukça haklısınız. İlk başta "corrcoef" diye düşündüm, ama bir nedenini daha yavaş olduğunu hatırladım. Denemekten ziyade kötü anılarıma güvendiğim biraz koyunlu hissediyorum. Daha hızlıdır çünkü python döngülerini ortadan kaldırmak için matris çarpımlarını kullanır. +1 benden. –

+0

Düzeltme ile ilgili sorun, gerektiğinde yaklaşık iki kat fazla bellek kullanmasıdır. Ayrıca, katsayıların neredeyse tamamını iki kere hesaplamaktadır. Ancak, daha büyük sorun hafızasıdır ve OP hafıza problemlerinden kaçınmak için verileri kırmak zorunda kalacaktır. Esasen bir birleştirici karışıklık olacak. –

+0

@Justin Peel - True, corrcoef giriş dizisinin ek bir geçici kopyasını yaratıyor. Kullanılan bellek ile hız arasında bir değiş tokuş. Çözümün ana kısıtı bellekse ve 50.000 satırlık olması durumunda çözümünüz daha iyi olur. –

İlgili konular