[PYTHON] 상관 행렬 찾기
PYTHON상관 행렬 찾기
상당히 큰 행 (약 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 모듈 (http://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.pearsonr.html)에서 제공하는 pearsonr 함수를 사용하고 있습니다.
내 질문은 : 이것을하는 더 빠른 방법이 있습니까? 사용할 수있는 일부 매트릭스 파티션 기술이 있습니까?
감사!
해결법
-
==============================
1.새로운 솔루션
새로운 솔루션
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 배 이상 빠릅니다. 왜냐하면 계수 및 다른 몇 가지 사항을 중복 계산하지 않기 때문입니다. 또한 더 빠를 것이며 50,000 행 행렬에 대한 메모리 문제를주지 않을 것입니다. 그 이유는 각각의 r 세트를 저장하거나 다른 세트를 생성하기 전에이를 처리 할 수 있기 때문입니다. r의 장기간의 데이터를 저장하지 않고, 꽤 새로운 노트북에서 분당 50,000 x 10 세트의 무작위로 생성 된 데이터에서 위의 코드를 실행할 수있었습니다.
구식 솔루션
첫째, 저는 r을 화면에 인쇄하는 것을 권장하지 않습니다. 100 행 (10 열)의 경우 인쇄시 19.79 초와 코드를 사용하지 않은 경우 0.301 초 사이의 차이입니다. 그냥 r을 저장하고 나중에 원하면 사용하거나, 가장 큰 r을 찾는 것처럼 진행하면서 처리하십시오.
둘째, 일부 수량을 중복 계산하지 않아도 비용을 절약 할 수 있습니다. Pearson 계수는 행이 사용될 때마다 계산하지 않고 미리 계산할 수있는 일부 수량을 사용하여 scipy에서 계산됩니다. 또한 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.8x (수백 개의 열이있는 10 개의 열을 사용했습니다). 나는 또한 그것이 동일한 결과를주는 것을 확인했다. 이것은 큰 개선이 아니지만 도움이 될 수 있습니다.
궁극적으로, 계산중인 문제 (50000) * (50001) / 2 = 1,250,025,000 피어슨 계수 (정확하게 계산하면). 그게 많이 있습니다. 그런데 실제로는 각 행의 Pearson 계수를 계산할 필요가 없습니다 (1과 같음). 그러나 피어슨 계수를 계산하면 5 만원을 절약 할 수 있습니다. 위의 코드를 사용하면 소규모 데이터 세트의 결과를 기반으로 데이터에 10 개의 열이있는 경우 계산을 수행하는 데 약 4 시간이 걸릴 것으로 예상됩니다.
위의 코드를 Cython 또는 유사한 것으로 가져 가면 약간의 향상을 얻을 수 있습니다. 운이 좋다면 곧장 Scipy보다 10 배 향상 될 것으로 기대합니다. 또한 pyInTheSky에서 제안한 것처럼 멀티 프로세싱을 할 수 있습니다.
-
==============================
2.numpy.corrcoef를 사용해 보셨습니까? 어떻게하면 p 값을 사용하지 않는지 알 수 있으므로 원하는대로 정확하게 수행 할 수 있습니다. (피어슨의 R이 정확히 무엇인지 정확하게 기억하지 않는 한, 이것은 가능합니다.)
numpy.corrcoef를 사용해 보셨습니까? 어떻게하면 p 값을 사용하지 않는지 알 수 있으므로 원하는대로 정확하게 수행 할 수 있습니다. (피어슨의 R이 정확히 무엇인지 정확하게 기억하지 않는 한, 이것은 가능합니다.)
무작위 데이터의 결과를 신속하게 확인하기 만하면 위의 @Justin Peel 코드와 똑같은 것을 반환하고 ~ 100x 빠릅니다.
예를 들어, 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
numpy.corrcoef는 사용자가 원하는 것을 수행해야하며 훨씬 빠릅니다.
-
==============================
3.당신은 파이썬 다중 프로세스 모듈을 사용할 수 있습니다, 10 세트로 행을 청크, 결과를 버퍼링하고 물건을 출력 (이것은 멀티 코어 기계에서만 속도를 높일 것입니다)
당신은 파이썬 다중 프로세스 모듈을 사용할 수 있습니다, 10 세트로 행을 청크, 결과를 버퍼링하고 물건을 출력 (이것은 멀티 코어 기계에서만 속도를 높일 것입니다)
http://docs.python.org/library/multiprocessing.html
btw : 스 니펫을 함수로 변환하고 데이터 재구성을 수행하는 방법도 고려해야합니다. 각각의 하위 프로세스에 이런 목록이 있습니다 ... [startcord, stopcord, buff] .. 잘 작동 할 수 있습니다.
def myfunc(thelist): for i in xrange(thelist[0]:thelist[1]): .... thelist[2] = result
from https://stackoverflow.com/questions/3437513/finding-the-correlation-matrix by cc-by-sa and MIT license
'PYTHON' 카테고리의 다른 글
[PYTHON] 파이썬에서 목록을 순회하면서 요소를 제거하십시오 [duplicate] (0) | 2018.11.10 |
---|---|
[PYTHON] 파이썬 로깅 모듈에서 줄 바꿈을 억제하십시오. (0) | 2018.11.09 |
[PYTHON] Paramiko : NAT 라우터 주변의 포트 포워딩 (0) | 2018.11.09 |
[PYTHON] SciPy의 지수 곡선 피팅 (0) | 2018.11.09 |
[PYTHON] 동일한 키에 대해 여러 값을 유지하면서 파일을 구성하는 방법은 무엇입니까? (0) | 2018.11.09 |