Triển khai SVD tăng dần trong MATLAB


8

Có thư viện / hộp công cụ nào triển khai SVD gia tăng trong MATLAB không. Tôi đã thực hiện bài viết này , nó nhanh nhưng không hoạt động tốt. Tôi đã thử điều này nhưng trong đó cũng có lỗi lan truyền nhanh (trong khi cập nhật 5-10 điểm thì lỗi cao).

Câu trả lời:


8

Đúng. Christopher Baker đã triển khai phương pháp SVD gia tăng của mình trong gói MATLAB có tên IncPACK ( được lưu trữ trên GitHub, trong dự án imtsl ). Nó thực hiện các phương pháp được mô tả trong luận án thạc sĩ của mình . Một cuộc thảo luận ngắn gọn về lý do tại sao thuật toán của Brand có xu hướng tích lũy lỗi có thể được tìm thấy trong một bài báo năm 2012 của Baker, et al . Một phương pháp liên quan của Chahlaoui, et al thảo luận về các giới hạn lỗi trên không gian con số ít bên trái và các giá trị số ít.

Tôi đã đề cập những điểm này trong các ý kiến về câu trả lời của Stephen, nhưng nó mang lặp đi lặp lại rằng phương pháp của cả hai Baker và bởi quy mô Chahlaoui như cho một cắt ngắn rank- SVD của một bởi ma trận . Đối với các xấp xỉ thứ hạng thấp, thuật ngữ chiếm ưu thế và, tùy thuộc vào biến thể thuật toán, có hằng số dẫn đầu thường nằm trong khoảng từ 8 đến 12.Ôi(mnk+nk3)kmnmnk

Giống như câu trả lời của Stephen, thuật toán của Chahlaoui bắt đầu bằng nhân tố QR. Câu trả lời của Stephen sẽ có tác dụng tính toán các vectơ số đơn bên trái, nhưng một SVD dày đặc của ma trận sẽ có độ phức tạp siêu tuyến tính trong và trước khi cắt (nó sẽ là ), có thể sẽ làm giảm hiệu quả, nhưng có thể sẽ làm giảm hiệu quả, nhưng chính xác hơnRmnÔi(mn2)

Để biết giá trị của nó, tôi đã tự mình thực hiện thuật toán của Brand và nó hơi nhạy cảm với dung sai sản phẩm bên trong được sử dụng để cắt giảm thứ hạng. Tôi chưa sử dụng gói của Baker, nhưng tôi tin rằng nó sẽ tốt hơn, vì các ước tính lỗi tồn tại cho thuật toán của Baker (hoặc liên quan chặt chẽ) và không phải là thuật toán của Brand và vì dung sai cắt giảm thứ hạng cho thuật toán của Baker là trên các giá trị đơn lẻ, không phải bên trong các sản phẩm.


Tôi đã kiểm tra gói IncPACK, mặc dù nó có chức năng seqkl_update nhưng nó không giống như chấp nhận bất kỳ tham số nào cho các hàng và cột mới. Cũng từ bản tóm tắt trên giấy (có thể không chính xác, tôi phải đọc tất cả) có vẻ như đó là một cách tiếp cận đa cấp mà họ gọi nó là gia tăng.
pj

Baker thảo luận về cả hai cách tiếp cận đơn và đa. Các seqklchức năng có vẻ như là chức năng chính, và có các tùy chọn cho đèo duy nhất và nhiều. Một lượt đi được đưa ra bởi seqkl_stdpass, cuộc gọi nào seqkl_update, vì vậy bạn có thể muốn sử dụng seqklcho một hệ số ban đầu, theo sau là các cuộc gọi để seqkl_updatecập nhật cột.
Geoff Oxberry

Vâng, cho đến bây giờ những gì tôi tìm thấy là nó chỉ cập nhật cột, dữ liệu mới Ai được lưu trữ trong U (1: m, o: op) là nhận xét từ tệp seqkl_update. Nhưng những gì về cập nhật hàng?
pj

@pj Từ những gì tôi đã đọc, hầu hết các tài liệu tập trung vào cập nhật cột. Nếu có thể, thay vào đó, bạn có thể tính toán SVD của chuyển vị của ma trận; tuy nhiên, tôi nhận ra rằng việc chuyển đổi dữ liệu của bạn có thể không phải là một lựa chọn. Tôi đoán rằng thuật toán có thể được thể hiện lại dưới dạng cập nhật hàng, nhưng điều đó có thể đòi hỏi một chút công việc.
Geoff Oxberry

Hai liên kết đầu tiên đã chết.
Joel Sjögren

4

Một phương pháp để tính toán svd của ma trận Xlà yếu tố đầu tiên X=QRsử dụng phân tách QR (để ổn định, sử dụng xoay vòng, vì vậy đây là [Q,R,E] = qr(X,0)trong Matlab), sau đó tính toán svd của R. Nếu ma trận rất hình chữ nhật, thì tính toán đắt nhất là hệ số QR.

Do đó, nếu bạn tăng ma trận của mình Xbằng một hàng hoặc cột khác (đây là ý của bạn, phải không?), Bạn chỉ có thể cập nhật hệ số QR với qrinsertchức năng của Matlab , sau đó thực hiện lại phép tính SVD R.

Nếu bạn có một ma trận vuông lớn, phương pháp này sẽ không hữu ích, vì việc thực hiện lại SVD Rsẽ tốn thời gian.


Điều này chỉ nhanh đối với một svd cấp thấp, phải không?
dranxo 30/03/2015

@Stephen Có, đó là những gì tôi muốn, thêm một cột và một hàng (đó là thêm một điểm dữ liệu cho tôi). Tôi nghĩ rằng các phương pháp mà tôi đã thử cũng làm QR ban đầu và sau đó cập nhật. Mối quan tâm chính của tôi là lỗi. Những gì tôi đã nhận thấy là svd cho các điểm cũ không nên thay đổi nhiều, sau 5-6 cập nhật gia tăng bị lỗi với lỗi rất lớn, tương tự như vậy với các điểm mới.
pj

RXk

@GeoffOxberry, đó là những gì tôi đã nói: nếu bạn có một ma trận vuông, điều này không hiệu quả. Tôi đề cập đến nó bởi vì bạn thường có một ma trận gầy / béo và thuật toán này có thể được triển khai một cách tầm thường bằng cách sử dụng các hàm hiện có trong Matlab
Stephen

@dranxo, tốt, nếu bạn rất hình chữ nhật, nó tương đối nhanh. Nó không nhanh như một SVD gia tăng thực sự, nhưng nếu bạn rất hình chữ nhật, chi phí của SVD bên trong là không đáng kể và bạn có thể cân bằng điều này với việc dễ dàng thực hiện
Stephen

4

Đây là một phương pháp có thể xử lý các bổ sung cột: http://pcc.byu.edu/resource.html . Tôi đã cập nhật nó để xử lý các bổ sung hàng:

function [Up1,Sp,Vp1] = addblock_svd_update2( Uarg, Sarg, Varg, Aarg, force_orth )

  U = Varg;
  V = Uarg;
  S = Sarg;
  A = Aarg';

  current_rank = size( U, 2 );
  m = U' * A;
  p = A - U*m;
  P = orth( p );
  P = [ P zeros(size(P,1), size(p,2)-size(P,2)) ];
  Ra = P' * p;
  z = zeros( size(m) );
  K = [ S m ; z' Ra ];
  [tUp,tSp,tVp] = svds( K, current_rank );
  Sp = tSp;
  Up = [ U P ] * tUp;
  Vp = V * tVp( 1:current_rank, : );
  Vp = [ Vp ; tVp( current_rank+1:size(tVp,1), : ) ];
  if ( force_orth )
    [UQ,UR] = qr( Up, 0 );
    [VQ,VR] = qr( Vp, 0 );
    [tUp,tSp,tVp] = svds( UR * Sp * VR', current_rank );
    Up = UQ * tUp;
    Vp = VQ * tVp;
    Sp = tSp;
  end;

  Up1 = Vp;
  Vp1 = Up;

return;

Kiểm tra nó với

X = [[ 2.180116   2.493767  -0.047867;
       -1.562426  2.292670   0.139761;
       0.919099  -0.887082  -1.197149;
       0.333190  -0.632542  -0.013330]];

A = [1 1 1];
X2 = [X; A];
[U,S,V] = svds(X);

[Up,Sp,Vp] = addblock_svd_update2(U, S, V, A, true);

Up
Sp
Vp

[U2,S2,V2] = svds(X2);
U2
S2
V2

Bạn sẽ thấy kết quả U, S, V ở cả hai bên là như nhau.

Cũng là phiên bản Python,

import numpy as np
import scipy.linalg as lin

def  addblock_svd_update( Uarg, Sarg, Varg, Aarg, force_orth = False):
  U = Varg
  V = Uarg
  S = np.eye(len(Sarg),len(Sarg))*Sarg
  A = Aarg.T

  current_rank = U.shape[1]
  m = np.dot(U.T,A)
  p = A - np.dot(U,m)
  P = lin.orth(p)
  Ra = np.dot(P.T,p)
  z = np.zeros(m.shape)
  K = np.vstack(( np.hstack((S,m)), np.hstack((z.T,Ra)) ))
  tUp,tSp,tVp = lin.svd(K);
  tUp = tUp[:,:current_rank]
  tSp = np.diag(tSp[:current_rank])
  tVp = tVp[:,:current_rank]
  Sp = tSp
  Up = np.dot(np.hstack((U,P)),tUp)
  Vp = np.dot(V,tVp[:current_rank,:])
  Vp = np.vstack((Vp, tVp[current_rank:tVp.shape[0], :]))

  if force_orth:
    UQ,UR = lin.qr(Up,mode='economic')
    VQ,VR = lin.qr(Vp,mode='economic')
    tUp,tSp,tVp = lin.svd( np.dot(np.dot(UR,Sp),VR.T));
    tSp = np.diag(tSp)
    Up = np.dot(UQ,tUp)
    Vp = np.dot(VQ,tVp)
    Sp = tSp;

  Up1 = Vp;
  Vp1 = Up;

  return Up1,Sp,Vp1

2

Một thay thế cho SVD tăng dần là HAPOD phân rã trực giao gần đúng theo thứ bậc , trong đó có thể tìm thấy một triển khai trên github: http://git.io/hapod . HAPOD có giới hạn lỗi nghiêm ngặt và trường hợp đặc biệt là một biến thể gia tăng.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.