2016-10-10 2 views
3

나는 크 리그 팅 알고리즘을 코딩했는데 아주 느리다. 특히, 당신이 나는 단점의 코드 조각을 벡터화 수있는 방법에 대한 아이디어가하는 일은 아래 기능 :Vectorise 파이썬 코드

import time 
import numpy as np 

B = np.zeros((200, 6)) 
P = np.zeros((len(B), len(B))) 

def cons(): 
    time1=time.time() 
    for i in range(len(B)): 
    for j in range(len(B)): 
     P[i,j] = corr(B[i], B[j]) 
    time2=time.time() 
    return time2-time1 

def corr(x,x_i): 
    return np.exp(-np.sum(np.abs(np.array(x) - np.array(x_i))))  

time_av = 0. 
for i in range(30): 
    time_av+=cons() 
print "Average=", time_av/100. 

편집 : 보너스 질문 나는 경우 방송 솔루션에 어떻게됩니까

  1. 원하는 corr(B[i], C[j]) C가 B보다 동일한 치수
  2. p- 표준 명령이 배열 인 경우 scipy 솔루션은 어떻게됩니까?

    p=np.array([1.,2.,1.,2.,1.,2.]) 
    def corr(x, x_i): 
        return np.exp(-np.sum(np.abs(np.array(x) - np.array(x_i))**p)) 
    

    2.의 경우 P = np.exp(-cdist(B, C,'minkowski', p))을 시도했지만 scipy는 스칼라를 기대하고 있습니다.

+1

@TobySpeight CR * only *는 작업 코드를 허용하지만 모든 성능 향상 질문은 주제와 관련이 없다고 생각합니다. [이것도 여기에 있습니다.] (http://meta.codereview.stackexchange.com/a/5778). –

+0

게시 된 솔루션을 크게 수정해야하는 세부 정보를 추가하지 마십시오. 대신, 새로운 세부 사항이 포함 된 새로운 질문을 게시하고 필요할 경우 게시하십시오. 이 질문에 연결. – Divakar

답변

4

문제가 매우 단순 해 보입니다. B의 행의 각 쌍 위해 당신은 마지막 하나를 따라 합산, 세 번째 차원을

P[i,j] = np.exp(-np.sum(np.abs(B[i,:] - B[j,:]))) 

당신은 배열 방송을 활용할 수를 계산하고 소개 할 :

P2 = np.exp(-np.sum(np.abs(B[:,None,:] - B),axis=-1)) 

아이디어는 모양을 변경하는 것입니다 첫 번째 발생은 B이고 모양은 (N,1,M)이고 두 번째는 B이고 모양은 (N,M)입니다. 어레이 방송으로 후자 (1,N,M) 등가이므로

B[:,None,:] - B 

형상 (N,N,M)이다. 마지막 색인을 합산하면 찾고있는 (N,N)- 형상 상관 관계 배열이됩니다. 불필요하게이의 Symmetrix 행렬의 낮은 삼각 절반을 계산하지 않고 (동등 또는, scipy.spatial.distance.pdistscipy.spatial.distance.squareform의 조합)


당신이 scipy를 사용한다면, 당신은 scipy.spatial.distance.cdist를 사용하여이 작업을 수행 할 수있을 것이라는 점을주의. 간단한 해결책 댓글이 방법 @Divakar의 제안을 사용 :

from scipy.spatial.distance import cdist 
P3 = 1/np.exp(cdist(B, B, 'minkowski',1)) 

cdist 정확히 차이 좌표의 절대 값의 합인 1 규범의 민코프 스키 거리를 계산한다.

+1

그래서'1/np.exp (pdist (B, 'minkowski', 1))'또는''1/np.exp (cdist (B, B, 'minkowski', 1) . – Divakar

+0

@Divakar 예, OP가 scipy를 사용하지 않는 것 같기 때문에 나는 너무 노골적이되고 싶지 않았습니다. 그래서 추가 수입이 과도 할 수도 있습니다. 하지만 어쨌든 그것을 추가 할 것이다 :) 또한,'cdist'에 대한 감사, 나는 그것의 존재를 알지 못했다. –

+1

아주 완전한 답변, 감사합니다. @ AndrasDeak 실제로, 나는 scipy를 사용하는 것을 피하고 싶지만 cdist 함수는 매우 흥미롭게 보입니다.여러분은 하위 삼각 행렬이 무의미하게 계산된다는 사실을 지적합니다. 실제로 코드에서 실제로 i + 1부터 시작하는 두 번째 루프가 있습니다. '범위가 j 인 경우 (i + 1, len (B))', 임의의 경우 첫 번째 솔루션으로이를 달성하려면? – Jean