การคำนวณที่มีประสิทธิภาพของเมทริกซ์ผกผันสแควร์รูท


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ผมไม่แน่ใจว่าทั้งหมดผมเข้าใจบรรทัด มีวิธีที่มีประสิทธิภาพมากกว่าในการคำนวณเมทริกซ์ผกผันสแควร์รูทหรือไม่? การวิจัยeigenการเรียกฟังก์ชัน LAPACK


ที่จัดไว้ให้เป็นจริง( d + | d | ) / 2เท่ากับสูงสุด( d , 0 ) สิ่งนี้จะกำจัดค่าลักษณะเฉพาะเชิงลบใด ๆ ที่เมทริกซ์อาจมีได้อย่างมีประสิทธิภาพ คุณไม่จำเป็นต้องรายการทั้งหมดของเมทริกซ์- 1 / 2หรือมันจะเพียงพอที่จะสามารถที่จะคูณ- 1 / 2โดยพลเวกเตอร์x ? d(d+|d|)/2สูงสุด(d,0)A-1/2A-1/2x
Daniel Shapero

@DanielShapero ขอบคุณสำหรับความคิดเห็นของคุณ ถ้าฉันมีเมทริกซ์ PSD ฉันไม่ต้องการบรรทัดนั้น ใบสมัครของฉันต้องใช้คอมพิวเตอร์ในรูปแบบสมการกำลังสองเช่น- 1 / 2 B - 1 / 2 A-1/2BA-1/2
tchakravarty

ฉันไม่คุ้นเคยกับ R แต่ได้รับบรรทัดที่ 7 ฉันคิดว่ามันมีการทำดัชนีเชิงตรรกะเช่น Matlab ถ้าเป็นเช่นนั้นฉันขอแนะนำให้คุณเขียนบรรทัดที่ 5 d[d<0] = 0ใหม่ซึ่งมีความหมายมากกว่า
Federico Poloni

รหัสนี้ถูกต้องหรือไม่ ฉันใช้มันกับตัวอย่างง่ายๆใน matlab และพบคำตอบว่าผิด เมทริกซ์ของฉันเป็นบวกแน่นอน แต่ก็ไม่สมมาตร โปรดดูคำตอบของฉันด้านล่าง: ฉันได้โอนรหัสไปยัง matlab
roni

คำตอบ:


10

รหัสที่คุณได้โพสต์ใช้การสลายตัว eigenvalue ของเมทริกซ์สมมาตรเพื่อคำนวณ- 1 / 2 A-1/2

คำสั่ง

d = (D + เอบีเอส (ง)) / 2

A

AA

A


6
AAA=BTBBBRA

5

จากประสบการณ์ของผมวิธีโพลาร์ - นิวตันของไฮแทมทำงานได้เร็วขึ้นมาก (ดูบทที่ 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()ฟังก์ชั่นdที่จะทั้งสองmax(d,0)และd2[d==0]=0ในหนึ่งวง
ข ลองใช้งานei$valuesโดยตรง

ตัวเลือกที่ 2 - ใช้ C ++:
เขียนRcppArmadilloซ้ำฟังก์ชันทั้งหมดใน C ++ ด้วย คุณจะยังสามารถโทรหาได้จาก R

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.