बड़ी संख्या में सुविधाओं के लिए सर्वश्रेष्ठ पीसीए एल्गोरिथ्म (> 10K)?


54

मैंने पहले स्टैकऑवरफ्लो पर यह पूछा था, लेकिन ऐसा लगता है कि यह यहां अधिक उपयुक्त हो सकता है, यह देखते हुए कि इसे एसओ पर कोई जवाब नहीं मिला। यह आँकड़ों और प्रोग्रामिंग के बीच चौराहे की तरह है।

पीसीए (प्रिंसिपल कंपोनेंट एनालिसिस) करने के लिए मुझे कुछ कोड लिखना होगा। मैंने प्रसिद्ध एल्गोरिदम के माध्यम से ब्राउज़ किया है और इसे लागू किया है , जहां तक ​​मैं बता सकता हूं कि यह एनआईपीएलएस एल्गोरिथ्म के बराबर है। यह पहले 2-3 प्रमुख घटकों को खोजने के लिए अच्छी तरह से काम करता है, लेकिन फिर अभिसरण (सैकड़ों से हजारों पुनरावृत्तियों के आदेश पर) के लिए बहुत धीमा हो जाता है। यहाँ मैं क्या जरूरत के विवरण हैं:

  1. कुछ सौ के क्रम पर बड़ी संख्या में सुविधाओं (आदेश 10,000 से 20,000) और नमूना आकार के साथ काम करते समय एल्गोरिथ्म कुशल होना चाहिए।

  2. यह एक सभ्य रैखिक बीजगणित / मैट्रिक्स पुस्तकालय के बिना उचित रूप से लागू होना चाहिए, क्योंकि लक्ष्य भाषा डी है, जिसमें अभी तक कोई नहीं है, और यदि ऐसा किया भी है, तो मैं इसे परियोजना में निर्भरता के रूप में नहीं जोड़ना चाहूंगा। ।

एक साइड नोट के रूप में, एक ही डेटासेट पर आर सभी प्रिंसिपल घटकों को बहुत तेजी से ढूंढता है, लेकिन यह एकवचन मूल्य अपघटन का उपयोग करता है, जो कुछ ऐसा नहीं है जिसे मैं खुद को कोड करना चाहता हूं।


2
सार्वजनिक SVD एल्गोरिदम के भार हैं। En.wikipedia.org/wiki/… देखें । क्या आप उनमें से किसी एक का उपयोग या अनुकूलन नहीं कर सकते? इसके अलावा, आर ओपन-सोर्स है, और जीपीएल लाइसेंस के तहत, इसलिए यदि यह काम करता है तो अपने एल्गोरिथ्म को उधार क्यों नहीं लेता है?
रोब हंडमैन

@ रोब: मैं व्यावहारिक रूप से एक रेखीय बीजगणित पुस्तकालय लिखने से बचना चाहूंगा, और मैं जीपीएल के कॉपीलेफ्ट से भी बचना चाहता हूं। इसके अलावा, मैंने आर सोर्स कोड के बिट्स और टुकड़ों को पहले देखा है और यह आमतौर पर बहुत पठनीय नहीं है।
dsimcha

4
क्या मैं कुछ भूल रहा हूँ? आपके पास> 10K विशेषताएं हैं लेकिन <1K नमूने? इसका मतलब है कि पिछले 9K घटक मनमाने हैं। क्या आप पहले घटकों के सभी 1K चाहते हैं?
shabbychef

2
किसी भी घटना में, आप एसवीडी को लागू करने से बच नहीं सकते हैं, हालांकि बहुत संख्यात्मक रैखिक बीजगणित अनुसंधान के लिए धन्यवाद, अब चुनने के लिए बहुत सारे तरीके हैं, जो आपके मैट्रिक्स के बड़े / छोटे, विरल / घने होने पर निर्भर करता है, या यदि आप सिर्फ एकवचन मान चाहते हैं, या एकवचन मान और बाएँ / दाएँ एकवचन वैक्टर का पूरा सेट। IMHO को समझने के लिए एल्गोरिदम बहुत मुश्किल नहीं है।
JM

क्या आप हमें बता सकते हैं कि आप पीसीए क्यों करना चाहते हैं?
रॉबिन जिरार्ड

जवाबों:


27

मैंने रैंडमाइज्ड SVD को "Halko, N., Martinsson, PG, Shkolnisky, Y., & Tygert, M. (2010) में दिया है। बड़े डेटा सेटों के प्रमुख घटक विश्लेषण के लिए एक एल्गोरिथ्म। Arxiv preprint arXiv: 1007.5510, 0526। http://arxiv.org/abs/1007.5510 से 1 अप्रैल, 2011 को लिया गया । " यदि आप SVD को छोटा करना चाहते हैं, तो यह MATLAB में svd बदलावों की तुलना में बहुत तेजी से काम करता है। आप इसे यहां पा सकते हैं:

function [U,S,V] = fsvd(A, k, i, usePowerMethod)
% FSVD Fast Singular Value Decomposition 
% 
%   [U,S,V] = FSVD(A,k,i,usePowerMethod) computes the truncated singular
%   value decomposition of the input matrix A upto rank k using i levels of
%   Krylov method as given in [1], p. 3.
% 
%   If usePowerMethod is given as true, then only exponent i is used (i.e.
%   as power method). See [2] p.9, Randomized PCA algorithm for details.
% 
%   [1] Halko, N., Martinsson, P. G., Shkolnisky, Y., & Tygert, M. (2010).
%   An algorithm for the principal component analysis of large data sets.
%   Arxiv preprint arXiv:1007.5510, 0526. Retrieved April 1, 2011, from
%   http://arxiv.org/abs/1007.5510. 
%   
%   [2] Halko, N., Martinsson, P. G., & Tropp, J. A. (2009). Finding
%   structure with randomness: Probabilistic algorithms for constructing
%   approximate matrix decompositions. Arxiv preprint arXiv:0909.4061.
%   Retrieved April 1, 2011, from http://arxiv.org/abs/0909.4061.
% 
%   See also SVD.
% 
%   Copyright 2011 Ismail Ari, http://ismailari.com.

    if nargin < 3
        i = 1;
    end

    % Take (conjugate) transpose if necessary. It makes H smaller thus
    % leading the computations to be faster
    if size(A,1) < size(A,2)
        A = A';
        isTransposed = true;
    else
        isTransposed = false;
    end

    n = size(A,2);
    l = k + 2;

    % Form a real n×l matrix G whose entries are iid Gaussian r.v.s of zero
    % mean and unit variance
    G = randn(n,l);


    if nargin >= 4 && usePowerMethod
        % Use only the given exponent
        H = A*G;
        for j = 2:i+1
            H = A * (A'*H);
        end
    else
        % Compute the m×l matrices H^{(0)}, ..., H^{(i)}
        % Note that this is done implicitly in each iteration below.
        H = cell(1,i+1);
        H{1} = A*G;
        for j = 2:i+1
            H{j} = A * (A'*H{j-1});
        end

        % Form the m×((i+1)l) matrix H
        H = cell2mat(H);
    end

    % Using the pivoted QR-decomposiion, form a real m×((i+1)l) matrix Q
    % whose columns are orthonormal, s.t. there exists a real
    % ((i+1)l)×((i+1)l) matrix R for which H = QR.  
    % XXX: Buradaki column pivoting ile yapılmayan hali.
    [Q,~] = qr(H,0);

    % Compute the n×((i+1)l) product matrix T = A^T Q
    T = A'*Q;

    % Form an SVD of T
    [Vt, St, W] = svd(T,'econ');

    % Compute the m×((i+1)l) product matrix
    Ut = Q*W;

    % Retrieve the leftmost m×k block U of Ut, the leftmost n×k block V of
    % Vt, and the leftmost uppermost k×k block S of St. The product U S V^T
    % then approxiamtes A. 

    if isTransposed
        V = Ut(:,1:k);
        U = Vt(:,1:k);     
    else
        U = Ut(:,1:k);
        V = Vt(:,1:k);
    end
    S = St(1:k,1:k);
end

इसका परीक्षण करने के लिए, बस उसी फ़ोल्डर में एक छवि बनाएं (बस एक बड़ी मैट्रिक्स के रूप में, आप स्वयं मैट्रिक्स बना सकते हैं)

% Example code for fast SVD.

clc, clear

%% TRY ME
k = 10; % # dims
i = 2;  % # power
COMPUTE_SVD0 = true; % Comment out if you do not want to spend time with builtin SVD.

% A is the m×n matrix we want to decompose
A = im2double(rgb2gray(imread('test_image.jpg')))';

%% DO NOT MODIFY
if COMPUTE_SVD0
    tic
    % Compute SVD of A directly
    [U0, S0, V0] = svd(A,'econ');
    A0 = U0(:,1:k) * S0(1:k,1:k) * V0(:,1:k)';
    toc
    display(['SVD Error: ' num2str(compute_error(A,A0))])
    clear U0 S0 V0
end

% FSVD without power method
tic
[U1, S1, V1] = fsvd(A, k, i);
toc
A1 = U1 * S1 * V1';
display(['FSVD HYBRID Error: ' num2str(compute_error(A,A1))])
clear U1 S1 V1

% FSVD with power method
tic
[U2, S2, V2] = fsvd(A, k, i, true);
toc
A2 = U2 * S2 * V2';
display(['FSVD POWER Error: ' num2str(compute_error(A,A2))])
clear U2 S2 V2

subplot(2,2,1), imshow(A'), title('A (orig)')
if COMPUTE_SVD0, subplot(2,2,2), imshow(A0'), title('A0 (svd)'), end
subplot(2,2,3), imshow(A1'), title('A1 (fsvd hybrid)')
subplot(2,2,4), imshow(A2'), title('A2 (fsvd power)')

फास्ट एसवीडी

जब मैं इसे अपने डेस्कटॉप पर आकार 635 * 483 की छवि के लिए चलाता हूं, तो मुझे मिलता है

Elapsed time is 0.110510 seconds.
SVD Error: 0.19132
Elapsed time is 0.017286 seconds.
FSVD HYBRID Error: 0.19142
Elapsed time is 0.006496 seconds.
FSVD POWER Error: 0.19206

जैसा कि आप देख सकते हैं, निम्न मूल्यों के लिए k, यह Matlab SVD का उपयोग करने की तुलना में 10 गुना अधिक तेज है। वैसे, आपको परीक्षण फ़ंक्शन के लिए निम्नलिखित सरल फ़ंक्शन की आवश्यकता हो सकती है:

function e = compute_error(A, B)
% COMPUTE_ERROR Compute relative error between two arrays

    e = norm(A(:)-B(:)) / norm(A(:));
end

मैंने पीसीए पद्धति को नहीं जोड़ा क्योंकि यह एसवीडी का उपयोग करने के लिए सीधा है। आप उनके रिश्ते को देखने के लिए इस लिंक को देख सकते हैं।


12

आप विकल्पों में से कुछ का उपयोग करके कोशिश कर सकते हैं।

1- दंडित मैट्रिक्स विघटन । आप कुछ स्पार्सिटी प्राप्त करने के लिए यू और वी के कुछ दंड बाधाओं को लागू करते हैं। त्वरित एल्गोरिथ्म जो जीनोमिक्स डेटा पर उपयोग किया गया है

देखिये विनीत टिबशिरानी। उनके पास R-pkg भी है। "एक दंडित मैट्रिक्स अपघटन, जिसमें प्रमुख घटक और विहित सहसंबंध विश्लेषण विरल होते हैं।"

2- यादृच्छिक एसवीडी । चूंकि एसवीडी एक मास्टर एल्गोरिथ्म है, एक बहुत ही त्वरित अनुमान लगाएं वांछनीय हो सकता है, विशेष रूप से खोजपूर्ण विश्लेषण के लिए। यादृच्छिक एसवीडी का उपयोग करना, आप विशाल डेटासेट पर पीसीए कर सकते हैं।

मार्टिंसन, रोकलिन और टाइगर्ट को देखें "मैट्रिसेस के अपघटन के लिए एक यादृच्छिक एल्गोरिदम"। टाइगर्ट में पीसीए के बहुत तेज़ कार्यान्वयन के लिए कोड है।

नीचे आर में यादृच्छिक एसवीडी का एक सरल कार्यान्वयन है।

ransvd = function(A, k=10, p=5) {
  n = nrow(A)
  y = A %*% matrix(rnorm(n * (k+p)), nrow=n)
  q = qr.Q(qr(y))
  b = t(q) %*% A
  svd = svd(b)
  list(u=q %*% svd$u, d=svd$d, v=svd$v)
}

दंडित मैट्रिक्स अपघटन के लिए +1। वह पैकेज काफी अद्भुत है। मुझे शायद यह उल्लेख करना चाहिए कि यह "Witten" वर्तनी है, हालांकि, अगर लोगों को इलाज खोजने में परेशानी होती है। अंत में, ओपी ने कहा कि वे आर में कुछ भी नहीं लिखना चाहते थे, लेकिन अनिवार्य रूप से किसी भी बड़े एसवीडी पैकेज में गति के लिए सी, सी ++, या फोरट्रान बैकेंड होगा।
डेविड जे। हैरिस

4

ऐसा लगता है कि शायद आप लैंकोज़ एल्गोरिथ्म का उपयोग करना चाहते हैं । असफल होने पर, आप गोलब और वान ऋण से परामर्श करना चाह सकते हैं मैंने एक बार उनके पाठ से एक एसवीडी एल्गोरिथ्म (एसएमएल में, सभी भाषाओं में) कोडित किया और यह यथोचित रूप से अच्छी तरह से काम किया।


3

मैं सुझाव देता हूं कि कर्नेल पीसीए की कोशिश करें, जिसमें समय (स्थान की जटिलता) उदाहरणों की संख्या (एन) पर निर्भर करती है, न कि सुविधाओं (पी) की संख्या, जो मुझे लगता है कि आपकी सेटिंग (पी >> एन) में अधिक उपयुक्त होगी। कर्नेल पीसीए मूल रूप से NxN कर्नेल मैट्रिक्स (डेटा बिंदुओं के बीच समानता का मैट्रिक्स) के साथ काम करता है, बजाय PxP सहसंयोजक मैट्रिक्स जो बड़े पी के लिए सौदा करना मुश्किल हो सकता है। कर्नेल पीसीए के बारे में एक और अच्छी बात यह है कि यह गैर-रैखिक अनुमानों को सीख सकता है। यदि आप इसे एक उपयुक्त कर्नेल के साथ उपयोग करते हैं। इस पेपर को कर्नेल पीसीए पर देखें ।


2

मुझे याद आता है कि XX ^ T के बजाय X ^ TX के eigen- अपघटन की गणना करके PCA प्रदर्शन करना संभव है और फिर PC प्राप्त करने के लिए रूपांतरित होता है। हालाँकि मुझे विवरण हाथ से याद नहीं है, लेकिन यह जोलिफ़ (उत्कृष्ट) पुस्तक में है और मैं इसे तब देखूँगा जब मैं काम पर हूँ। मैं किसी भी अन्य एल्गोरिथ्म का उपयोग करने के बजाय, सी में संख्यात्मक विधियों जैसे रैखिक बीजगणित दिनचर्या का अनुवाद करूँगा।


5
अच्छा दुःख ... सहसंयोजक मैट्रिक्स का निर्माण एसवीडी के लिए सबसे अच्छा तरीका नहीं है। मैंने एक उदाहरण प्रदर्शित किया कि स्पष्ट रूप से सहसंयोजक मैट्रिक्स बनाने का गणित में एक अच्छा विचार क्यों नहीं है । ईएस: math.stackexchange.com/questions/3869/3871#3871
JM एक स्टेटिस्टिशियन नहीं है

1

फिशर एट अल द्वारा बूटस्ट्रैप विधि भी है , जिसे उच्च आयाम के कई सौ नमूनों के लिए डिज़ाइन किया गया है।

विधि का मुख्य विचार "resampling एक कम-आयाम परिवर्तन है" के रूप में तैयार किया गया है। इसलिए, यदि आपके पास उच्च-आयामी नमूनों की एक छोटी (कई सौ) संख्या है, तो आप अपने नमूनों की संख्या से अधिक प्रमुख घटक प्राप्त नहीं कर सकते। यह इस प्रकार नमूने को एक पारमार्थिक आधार के रूप में समझने के लिए समझ में आता है, इन वैक्टरों द्वारा फैलाए गए रैखिक उप-स्थान पर डेटा को प्रोजेक्ट करता है, और इस छोटे उप-क्षेत्र के भीतर पीसीए की गणना करता है। वे अधिक विवरण भी प्रदान करते हैं कि मामले से कैसे निपटें जब सभी नमूनों को मेमोरी में संग्रहीत नहीं किया जा सकता है।


0

विकिपीडिया एल्गोरिथ्म इसे उद्धृत करता है और एक समय में एक प्रमुख घटक खोजने के मामले के लिए इसके बराबर है।
dsimcha

ठीक है, मैं अब लिंक देखता हूं। यह एक काफी सरल दृष्टिकोण है, और विकिपीडिया उल्लेखों की तरह, इस मूल विचार पर अग्रिम हैं। हालांकि प्रतिबिंब पर, आप कुछ प्रकार के व्यापार-नापसंद (इस मामले में अभिसरण) से निपटने जा रहे हैं। मुझे आश्चर्य है कि अगर आप यहाँ सही सवाल पूछ रहे हैं। वहाँ वास्तव में डी के लिए linalg पुस्तकालयों के लिए कोई अच्छा बाइंडिंग हैं?
ars
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.