2012-08-15 2 views
0

다음 함수는 가우스 커널을 계산하며 내가 작성한 커널 릿지 회귀 알고리즘의 일부입니다. 나는 실행 시간을 향상시키기 위해이 함수를 어떻게 적절하게 수정할 수 있는지 궁금했다. (즉, 두 개의 루프를 제거하자.) 어떤 아이디어?MATLAB 함수의 실행 시간 향상

function [K] = calculate_krr_gaussiankernel(Xi,Xj,S) 
    K = zeros(size(Xi,1),size(Xj,1)); 
    for Ixi = 1:size(Xi,1), 
     for Ixj = 1:size(Xj,1), 
      K(Ixi,Ixj) = exp((-norm(Xi(Ixi,:) - Xj(Ixj,:)) .^ 2) ./ (2 * (S .^ 2))); 
     end 
    end 
end 

편집 : 공식 : enter image description here

답변

3

여기에 가장 가능성이 더 빠른 버전입니다. 그러나 큰 Xi/Xj에 대한 메모리 문제가 발생할 수 있습니다. 나는, 차이 벡터에서 내가 얻을 수 있도록 입력, 모든 (I, J)에서 바꿀 :

  • bsxfun 라인 : 여기
    function K = calculate_krr_gaussiankernel(Xi, Xj, S) 
    
        %# create an array of difference between Xi(r,:) and Xj(s,:) for all r,s 
        delta = bsxfun(@minus, permute(Xi,[1 3 2]), permute(Xj,[3 1 2])); 
    
        %# calculate the squared norm 
        ssq = sum(delta.^2, 3); 
    
        %# calculate the kernel 
        K = exp(-ssq./(2*S.^2)); 
    

    무엇 내가 뭘에 대한 설명입니다 3 차원
  • ssq 줄은 단순히 제곱의 합계를 취합니다. 저는 여기서 제곱근을 취해 규범을 얻을 수는 있지만, 어쨌든, 우리가 다시 그것을 제곱 할 것이기 때문에 그 점은 없습니다.
  • 마지막 줄은 OP의 수식을 구현합니다. 여기서 ssq은 차이의 제곱의 표준입니다.
+0

@RodyOldenhuis : 설명해 주셔서 감사합니다! – Jonas

+0

@eualin : 개별 단계에 대한 설명을 추가했습니다. – Jonas

2

K가 대칭이므로 2 배의 속도 (약)를 확실히 확보 할 수 있습니다. 또한 차이 벡터의 norm을 계산 한 다음 exp()을 반복해서 호출하는 것보다 더 빠를 수있는 exp()으로 단일 호출을 수행 할 수 있습니다. 함께 쓰는 것 :

function [K] = calculate_krr_gaussiankernel(Xi,Xj,S) 
    arg = zeros(size(Xi,1),size(Xj,1)); 
    for Ixi = 1:size(Xi,1), 
     % diagonal elements can be done in outer loop: 
     arg(Ixi,Ixi) = norm(Xi(Ixi,:) - Xj(Ixi,:)); 
     for Ixj = Ixi+1:size(Xj,1), % off-diagonals done once and copied 
      arg(Ixi,Ixj) = norm(Xi(Ixi,:) - Xj(Ixj,:)); 
      arg(Ixj,Ixi) = arg(Ixi,Ixj); 
     end 
    end 
end 

K = exp((-arg.^ 2) ./ (2 * (S .^ 2)))