2012-10-05 2 views
2

데이터에 대한 새 거리 함수를 만들려고합니다. 그러나 stats 패키지의 dist 함수와 비교할 때 내 코드의 성능은 매우 느립니다. 예를 들어, 유클리드 거리에 대한 결과를 참조하십시오내 거리 함수 최적화 R

mydist = function (x){ 

    euclidean = function (a, b){ 
    sqrt(sum((a-b)^2)) 
    } 

    distances = matrix(0, nrow=nrow(x), ncol=nrow(x)) 
    for (i in 1:nrow(x)) 
    for (j in 1:(i-1)){ # <- corrected this 
     if (j > 0){ 
     distances[i,j]=euclidean(x[i,], x[j,]) 
     distances[j,i]=distances[i,j] 
     } 
    } 

    distances 
} 


m=matrix(1:800, ncol=2) 
system.time(as.dist(mydist(m))) 
    usuário sistema decorrido 
    0.714  0.000  0.716  # <- updated values with corrected version 

system.time(dist(m)) 
    usuário sistema decorrido 
    0.004  0.000  0.002 

나는 유클리드 거리를 사용하지 않습니다. 나는 새 데이터를 개발하고 있는데, 예를 들어 프록시 패키지의 데이터와 다른 데이터를위한 통계를 사용하면 훨씬 더 복잡하다. 데이터 집합에 수 백 개의 변수와 수천 개의 예제 (선)가 있습니다. 거리를 계산하기 위해 몇 시간을 기다릴 수 없습니다.

적용을 통해 outer를 사용하여 다른 코드를 시도했습니다. 두 개의 루프보다 빠르지 만 여전히 느립니다. 아무도 제안 할 수 있습니까? 과속 일까지

+0

근본적으로 새로운 거리 측정법을 사용하지 않는 한 위키 피 디아 (Wikipedia) 주변을 스누핑하는 것이 좋습니다. R 및/또는 C에 기존 코드가있는 많은 메트릭 함수가 있습니다. 실제로 거리 함수가 시간 병목 현상입니까? 이는 데이터 세트에 적용하는 방법을 선택하기 전에 결정해야 할 사항이기도합니다. –

답변

1

의 핵심은

  • 중 하나를 당신의 거리 함수를 쉽게 벡터화 할 수있다. 이 경우 ? outer 및/또는 ? rep을 확인하십시오.
    이 접근법은 매우 빠르지 만 메모리를 소비합니다.

  • apply은 두 개의 루프를 기본적으로 하나로 줄이지 만 실제 벡터화는 대개 훨씬 빠릅니다.

  • 또는 예를 들어 인라인 C 코드, 패키지 인라인 참조.

  • 실수로 두 배의 거리를 계산해야합니다 (대칭 복사는 수행하지만 ij은 모두 1 : nrow (x) 회 반복합니다).

2

키는 전체 행렬이 아닌 각 행에서 각 행을 감산한다. 뺄셈은 열 단위로 수행되기 때문에 단순히 행렬을 조 변경하십시오.

m=matrix(1:800, ncol=2) 
system.time(a<-as.dist(mydist(m))) 
# user system elapsed 
# 1.32 0.00 1.32 

t.m<-t(m) 
system.time(x<-as.dist(apply(m,1,function(x) sqrt(colSums((x - t.m)^2))))) 
# user system elapsed 
# 0.04 0.00 0.03 

any(x!=a) # FALSE 

속도를 정말로 원한다면 C 라이브러리를 사용해야합니다.

+0

@ user1348438 : 유클리드 기능이 다른 기능에 대한 최소한의 대체품 일 뿐이라는 것을 알고 있습니까? 좀 더 명확히 해 주시겠습니까? – cbeleites