PCA muito lento quando ambos n, p são grandes: alternativas?

9

Configuração do problema

Eu tenho pontos de dados (imagens) de alta dimensão (4096), que estou tentando visualizar em 2D. Para esse fim, estou usando t-sne de maneira semelhante ao código de exemplo a seguir de Karpathy .

A documentação do scikit-learn recomenda o uso do PCA para diminuir primeiro a dimensão dos dados:

É altamente recomendável usar outro método de redução de dimensionalidade (por exemplo, PCA para dados densos ou TruncatedSVD para dados esparsos) para reduzir o número de dimensões para uma quantidade razoável (por exemplo, 50) se o número de recursos for muito alto.

Estou usando esse código do Darks.Liu para executar o PCA em Java:

//C=X*X^t / m
DoubleMatrix covMatrix = source.mmul(source.transpose()).div(source.columns);
ComplexDoubleMatrix eigVal = Eigen.eigenvalues(covMatrix);
ComplexDoubleMatrix[] eigVectorsVal = Eigen.eigenvectors(covMatrix);
ComplexDoubleMatrix eigVectors = eigVectorsVal[0];
//Sort sigen vector from big to small by eigen values 
List<PCABean> beans = new ArrayList<PCA.PCABean>();
for (int i = 0; i < eigVectors.columns; i++) {
    beans.add(new PCABean(eigVal.get(i).real(), eigVectors.getColumn(i)));
}
Collections.sort(beans);
DoubleMatrix newVec = new DoubleMatrix(dimension, beans.get(0).vector.rows);
for (int i = 0; i < dimension; i++) {
    ComplexDoubleMatrix dm = beans.get(i).vector;
    DoubleMatrix real = dm.getReal();
    newVec.putRow(i, real);
}
return newVec.mmul(source);

Ele usa jblas para as operações de álgebra linear, que pelo que li é a opção mais rápida disponível. No entanto, calcular os autovetores e os autovalores (linhas 3,4) acaba sendo um grande gargalo (~ 10 minutos, o que é muito mais longo do que posso pagar para esta etapa).

Eu li sobre o Kernel PCA, que deveria ser bom para casos em que a dimensão é muito grande, mas seu tempo de execução é que pode ser problemático, pois também quero lidar com casos de dimensão e número. de exemplos sendo grandes.O(n3)

Na minha opinião, minhas opções são "otimizar" o PCA ou optar por outro método de redução de dimensionalidade que é inerentemente mais rápido.

Minhas perguntas

  1. Existe alguma esperança de que o PCA possa ser usado de maneira "offline"? ou seja, usando um grande conjunto de dados de imagens, execute o PCA nelas e use os principais componentes calculados para reduzir a dimensão de outros (novos!) pontos de dados?
  2. Posso acelerar o cálculo dos vetores próprios, assumindo que sei antecipadamente que só estou interessado, digamos, nos 100 principais componentes principais?
  3. Existe um método alternativo de redução de dimensionalidade que seja apropriado no meu caso (ou seja, antes de aplicar t-sne) que seja mais rápido que o PCA? Estou procurando algo que possa ser implementado facilmente em Java.
galoosh33
fonte

Respostas:

8

Pergunta 1: Digamos que você tenha observado uma matriz de dados . A partir desta você pode calcular o eigendecomposition . A questão agora é: se obtivermos novos dados provenientes da mesma população, talvez coletados em uma matriz , estará próximo da rotação ortogonal ideal de ? Esse tipo de pergunta é abordada pelo teorema de Davis-Kahan e pela teoria da perturbação da matriz em geral (se você conseguir obter uma cópia, o livro de Stewart e Sun, de 1990, é a referência padrão).XRn×p Z R m × p Z Q ZXTX=QΛQTZRm×pZQZ

Pergunta 2: você definitivamente pode acelerar as coisas se souber que só precisa dos principais vetores. No RI, use para isso; Tenho certeza de que existe um equivalente em Java, pois todos eles são invólucros de fortran.krARPACK

Pergunta 3: Eu não sei nada sobre implementações Java, mas este segmento discute a aceleração do PCA, assim como esse segmento CV. Há uma tonelada de pesquisas sobre esse tipo de coisa e existem vários métodos por aí usando coisas como aproximações de baixa classificação ou randomização.

jld
fonte
3

O código que você está usando irá inverter toda a matriz. Provavelmente já é O (p ^ 3). Você pode aproximar o resultado em O (p ^ 2), mas isso ainda será lento (mas provavelmente 100x mais rápido). Essencialmente, pegue um vetor arbitrário e faça iterações de poder. Com alta probabilidade, você obterá uma boa aproximação do primeiro vetor próprio. Em seguida, remova esse fator da matriz e repita para obter o segundo. Etc.

Mas você já tentou se as implementações rápidas do Barnes Hut tSNE no ELKI talvez funcionem apenas nos seus dados com um índice como a árvore de cobertura? Essa implementação funcionou bem quando outros falharam.

Possui QUIT - Anony-Mousse
fonte
3
O que significa "whp". apoiar?
Kodiologist 21/03
Com alta probabilidade. Veja literatura estatística.
QuIT - Anony-Mousse
2

Se seu objetivo é apenas efetuar a redução de dimensão de maneira simples e direta, você pode tentar uma técnica de mínimos quadrados alternados (ALS). Por exemplo, o Apache Spark mlibtem uma implementação ALS e acredito que oferece uma API Java. Isso deve fornecer uma matriz e uma matriz . A matriz conterá vetores de linha visualizáveis.K × p K × pn×KK×pK×p

conjecturas
fonte