행렬 제곱근 역의 효율적인 계산


15

통계에서 일반적인 문제는 대칭 양수 한정 행렬의 제곱근 역을 계산하는 것입니다. 이것을 계산하는 가장 효율적인 방법은 무엇입니까?

나는 우연히 어떤 문학 (나는 아직 읽지 않은), 일부 부수적 R 코드 여기에 내가 편의를 위해 여기에 재생됩니다,

# function to compute the inverse square root of a matrix
fnMatSqrtInverse = function(mA) {
  ei = eigen(mA)
  d = ei$values
      d = (d+abs(d))/2
      d2 = 1/sqrt(d)
      d2[d == 0] = 0
      return(ei$vectors %*% diag(d2) %*% t(ei$vectors))
}

나는 내가 그 선을 이해한다고 확신하지 못한다 d = (d+abs(d))/2. 행렬 제곱근 역을 계산하는 더 효율적인 방법이 있습니까? R eigen함수는 LAPACK을 호출합니다 .


(+||)/2최대(,0)1/21/2엑스

@DanielShapero 의견을 보내 주셔서 감사합니다. PSD 매트릭스가 있다면 그 라인이 필요하지 않습니까? 내 응용 프로그램에는 와 같은 2 차 양식이 필요합니다 . 1/21/2
tchakravarty

나는 R에 익숙하지 않지만 줄 7이 주어지면 Matlab과 같은 논리적 인덱싱이 있다고 가정합니다. 그렇다면 5 행을로 다시 작성하는 것이 좋습니다 d[d<0] = 0.
Federico Poloni

이 코드가 맞습니까? matlab의 간단한 예에서 그것을 실행하고 대답이 잘못되었다는 것을 알았습니다. 내 행렬은 양의 명확하지만 대칭은 아닙니다. 아래 답변을 참조하십시오 : 코드를 matlab으로 옮겼습니다.
roni

답변:


10

게시 한 코드는 대칭 행렬의 고유 값 분해를 사용하여 를 계산 합니다. 1/2

진술

d = (d + abs (d)) / 2

음수가 아닌 항목 만 남겨두고 d의 음수 항목을 효과적으로 가져 와서 0으로 설정합니다. 즉, 음의 고유 값 은 0 인 것처럼 처리됩니다. 이론적으로 A의 고유 값은 모두 음수가 아니어야하지만 실제로는 양의 양의 고유 값을 계산할 때 작은 음의 고유 값을 보는 것이 일반적입니다. 거의 특이한 공분산 행렬.

의 대칭 행렬 제곱근의 역수가 실제로 필요 하고 A 가 합리적으로 작다면 (1,000 x 1,000보다 크지 않음), 이것은 당신이 사용할 수있는 방법만큼이나 좋습니다.

대부분의 경우 공분산 행렬의 역의 hole 레 스키 팩터를 사용할 수 있습니다 (또는 실질적으로 공분산 행렬 자체의 hole 레 스키 팩터). Cholesky 팩터 계산은 일반적으로 밀도가 높은 행렬과 크고 작은 행렬에 대해 훨씬 더 효율적입니다 (계산 시간 및 필요한 저장 공간 모두). 따라서 Cholesky 인수 분해를 사용 것은 A 가 크고 희박 할 때 매우 바람직 합니다.


6
=아르 자형

5

필자의 경험에 따르면 Higham의 polar-Newton 방법은 훨씬 빠르게 작동합니다 ( N. Higham 의 행렬 함수 6 장 참조 ). 에서 내 짧은 노트 일차 방법으로이 방법을 비교 플롯이있다. 또한, 몇 가지 다른 행렬-제곱근 접근법에 대한 인용이 제시되지만, 대부분 극성 뉴턴 반복이 가장 잘 작동하는 것 같습니다 (고유 벡터 계산을 피함).

% compute the matrix square root; modify to compute inverse root.
function X = PolarIter(M,maxit,scal)
  fprintf('Running Polar Newton Iteration\n');
  skip = floor(maxit/10);
  I = eye(size(M));
  n=size(M,1);
  if scal
    tm = trace(M);
    M  = M / tm;
  else
    tm = 1;
  end
  nm = norm(M,'fro');

  % to compute inv(sqrt(M)) make change here
  R=chol(M+5*eps*I);

  % computes the polar decomposition of R
  U=R; k=0;
  while (k < maxit)
    k=k+1;
    % err(k) = norm((R'*U)^2-M,'fro')/nm;
    %if (mod(k,skip)==0)
    %  fprintf('%d: %E\n', k, out.err(k));
    %end

    iU=U\I;
    mu=sqrt(sqrt(norm(iU,1)/norm(U,1)*norm(iU,inf)/norm(U,inf)));
    U=0.5*(mu*U+iU'/mu);

   if (err(k) < 1e-12), break; end
  end
  X=sqrt(tm)*R'*U;
  X = 0.5*(X+X');
end

0

코드를 최적화하십시오 :

옵션 1-R 코드를 최적화하십시오
. 할 수 있습니다 apply()A와 기능 d이 의지 모두 max(d,0)d2[d==0]=0하나 개의 루프있다.
비. ei$values직접 작업 해보십시오 .

옵션 2-C ++ 사용 :로 C ++
에서 전체 함수를 다시 작성하십시오 RcppArmadillo. 여전히 R에서 전화를 걸 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.