Existe um algoritmo SVD truncado que calcula os valores singulares, um de cada vez?
Meu problema: gostaria de calcular os primeiros valores singulares (e vetores singulares) de uma matriz densa grande , mas não sei qual seria um valor apropriado de . é grande, portanto, por razões de eficiência, prefiro não avaliar o SVD completo apenas para interromper os menores SVs posteriormente.
Idealmente, haveria uma maneira de calcular os valores singulares serialmente, do maior ( ) ao menor ( ). Dessa forma, eu poderia simplesmente interromper a computação depois de calcular o ésimo valor se cair abaixo de algum limite.
Existe um algoritmo desse tipo (de preferência com uma implementação em Python)? Na minha pesquisa, apenas encontrei funções SVD truncadas que tomam k como parâmetro, forçando-o a adivinhar a priori.
fonte
Respostas:
Existem algumas opções disponíveis se você quiser uma fatoração de classificação k aproximada.
Uma fatoração aproximada da forma acima pode ser convertida em uma decomposição padrão como QR ou SVD usando técnicas padrão. Uma boa revisão está disponível no artigo de Halko, Martinsson e Tropp "Encontrando estrutura com aleatoriedade: algoritmos probabilísticos para construir decomposições aproximadas de matriz"
Em termos de software, uma interface para algoritmos de ID está disponível em scipy (scipy.linalg.interpolative) http://docs.scipy.org/doc/scipy-dev/reference/linalg.interpolative.html, que permite ao usuário especificar .ϵ
fonte
(Editado, porque eu li mal a pergunta; você já sabe que existem rotinas disponíveis para calcular os primeiros valores singulares.)k
Se você excluir a abordagem de calcular todo o SVD, os algoritmos parciais de SVD se reduzirão ao uso de métodos iterativos para resolver um problema relacionado de autovalor hermitiano. Portanto, uma estratégia que você poderia adotar seria codificar manualmente esse tipo de coisa e continuar resolvendo o maior valor singular ainda não resolvido até que você queira parar, usando algo como uma estratégia de mudança e inversão. Pode haver maneiras elegantes de fazer esse tipo de coisa em pacotes sofisticados como o SLEPc .
Outra estratégia seria a seguinte:
Se a rotina SVD esparsa calcular um SVD fino (e não consigo ver por que não faria), essa estratégia fornecerá todos os valores singulares que você deseja (além de possivelmente alguns extras), porque valores abaixo da tolerância absoluta ser tratado como zero. Nesse caso, você pode usar scipy.sparse.linalg.svds , observando que é um parâmetro opcional e que não precisa especificá-lo a priori .k
fonte