PCA na mão e no Python
PCA, ou principal component analysis é uma técnica para reduzir a dimensão de um conjunto de dados preservando, de certa forma, suas propriedades. Executar essa técnica na mão ou sem ajuda de funções prontas é um bom exercício para aprender a fundo o que está por trás desse processo. Nesse tutorial faremos um exemplo de PCA na mão, sempre conferindo as contas com Python e, depois, faremos o mesmo exemplo usando a biblioteca Scikit-learn.
Pequeno exemplo de PCA para fazer na mão
Como utilizaremos o Python para conferir nossas contas, importaremos as bibliotecas necessárias.
Os códigos serão apresentados por imagens por ser mais produtivo produzir o post dessa forma. Uma versão deste post, com código copiáveis, pode ser encontrada nesse link.
Utilizaremos as seguintes matrizes para esse trabalho:
A matriz X representa as features, enquanto y representa o target. Declararemos essas matrizes no Python:
Precisaremos das médias de cada coluna de X. Para o cálculo da média da coluna i basta fazer a seguinte conta:
com n sendo o número de linhas da matriz X. Podemos conferir as contas no Python usando a biblioteca numpy:
Nossa própria tarefa é determinar a matriz de covariância. Para isso, vamos usar uma matriz M auxiliar. Para determinar M subtraia a média da coluna i da coluna respectiva. Como no nosso exemplo todas as entradas de M estão multiplicadas por 1/3, para ficar mais elegante, colocamos 1/3 em evidência.
Para realizar a mesma conta no Python, use o código a seguir:
A matriz de covariância é de X é dada por:
onde n é o número de linhas de X.
Logo,
No Python:
Próximo passo é determinar auto-valores e auto-vetores da matriz de covariância C. Os auto-valores 𝜆 de C são raizes de
onde I é a matriz identidade.
Cada auto-valor 𝜆 tem auto-vetores associados. Apesar de auto-vetores nunca serem nulos, se incluírmos o vetor nulo no conjunto dos auto-vetores associados e chamarmos esse novo conjunto de 𝑉(𝜆), temos que 𝑉𝜆 é o conjunto solução do seguinte sistema:
Tomaremos geradores unitários de 𝑉(1) e de 𝑉(1/3), a saber, tomaremos os seguintes auto-vetores:
Essa escolha não é única e isso pode dar pequenas diferenças nos resultados finais.
No Python:
Obtemos o seguinte resultado:
Agora, ordenaremos os auto-valores do maior para o menor. Isso é necessário apenas se não tiverem ordenados dessa forma.
Nosso próximo passo é calcular o quanto cada componente (auto-vetores) estão representando (de certa forma) a variabilidade dos nossos dados. Para isso usaremos duas medidas.
A variância explicada de cada auto-valor 𝜆 é dada por:
A variância explicada acumulada de cada auto-valor 𝜆 é a sobra das variâncias explicadas de todos auto-valores até 𝜆 considerando a ordem do maior para o maior e incluindo o próprio 𝜆.
Em Python:
Vejamos de forma sumarizada que temos até o momento:
Obtemos:
Bom, isso é tudo! Considerando os dados originais como pares ordenados em ℝ², pois X possui apenas duas colunas, ao mudar da base canônica para a base composta pelos auto-vetores encontrados, teremos uma nova representação do conjunto X. Graficamente fica da seguinte forma:
Se compararmos com o original:
Vimos que os vetores foram rotacionados 45º no sentido anti-horário.
Os códigos para a criação das duas figuras acima, respectivamente, são:
e
- Os dados originais foram rotacionados por um ângulo de 45º uma vez que os auto-vetores são perpendiculares e obtidos dos eixos x e y por uma rotação de 45º no sentido anti-horário.
- Nossos dados possuiam 2 colunas, mas poderiam possuir bem mais. Além disso escolhermos 2 componentes para visualização gráfica, esse número também pode ser mais, desde que seja menor que o número de colunas.
- A ideia do PCA é diminuir a dimensão do conjunto de dados original escolhendo um número menor de componentes para projeção sobre estas.
- O processo de redução de dimensão facilita processamento e armazenamento de dados.
Fazendo com uso de biblioteca
Agora vejamos o mesmo exemplo utilizando a biblioteca Scikit-learn.
Isso é tudo, agora vejamos as informações para fins de comparação.
Obtemos:
Observe que, como a escolha dos auto-vetores não é única, o algoritmo implementado na biblioteca Scikit-learn escolheu auto-vetores diferentes dos nossos. Mas, isso não é problema, pois só houve inversão de sinal. Logo, quando fizermos a visualização gráfica da mudança de coordenada, haverá uma inversão da figura. Vejamos o código para verificar tal fato:
E o gráfico fica:
Perfeito! Mas essa técnica serve para reduzir dimensões. Como nosso exemplo é apenas para fins educacionais, é hora de aprender com exemplos reais como usar o poderoso PCA!
PCA no conjunto de dados Iris
No próximo exemplo utilizaremos PCA para reduzir o conjunto de dados Iris de 4 para 2 features. O conjunto pode ser baixado no repositório UCI. O link encontra-se nas referências.
Faremos novamente passo a passo. O código é análogo ao código usado no exemplo anterior.
Para imprimir as informações sumarizadas:
Então
Com duas componentes temos uma variância explicada cumulativa de 97%. Utilizaremos então, apenas duas componentes. Para visualizar as informações graficamente utilizamos o seguinte código:
Obtemos então
Experimente trabalhar com outros conjuntos de dados com um maior número de features.
Vejamos agora o mesmo exemplo utilizando a biblioteca Scikit-learn.
PCA no conjunto de dados Iris com biblioteca
Novamente, carregamos o conjunto de dados.
Repetimos então o processo, só que, desta vez, utilizando o PCA já pronto.
Na próxima seção veremos outra aplicação.
PCA para redução de dimensão em imagens
Outra aplicação é a redução de dimensão em imagens. Para esse exemplo, escolhemos a imagem Pássaro mineiro barulhento retirada do site Pixabay. A imagem foi transformada em escala de cinza utilizando o software GIMP.
Primeiro, carregaremos a imagem.
Observe que a matriz tem 1920 linhas e 1899 colunas. Aplicaremos, em seguida, a técnica PCA.
O número 0.99 passado como parâmetro para o métodos PCA diz que queremos um número de componentes que nos garanta 99% de variância explicada cumulativa. Observe que para isso, utilizou-se 145 componentes. Isso é uma redução imensa, uma vez que a original possuia 1899 colunas. Queremos ver, caso necessário recuperar a imagem, como essas imagens ficam com a dimensão reduzida. Para isso serão necessários duas funções auxiliares.
A primeira função reduz a imagem X mantendo var_exp de variância explicada cumulativa. Compararemos 3 valores: 0.99, 0.95 e 0.90.
A segunda função mostra o gráfico. Utilizaremos ela para comparar as imagens obtidas com a original.
Por fim, obtemos a seguinte figura: