PCA
Redução de dimensionalidade¶
- Para o bom desempenho da tarefa de classificação é importante um conjunto suficientemente grande de atributos.
- Em muitos casos, especialmente quando se trabalha diretamente com os pixels das imagens, a informação necessária para a classificação de padrões está espalhada por praticamente todos os atributos
- No entanto, um número muito grande de atributos atrapalha o desempenho dos classificadores, num efeito conhecido como a maldição da dimensionalidade, curse of dimensionality.
- Frequentemente um número grande de atributos está associado à redundância da informação, ou seja, os valores dos tributos estão fortemente ligados entre si.
- Por exemplo, nas imagens de dígitos, pixels próximos tendem a ter tonalidades semelhantes
- Uma saída para aproveitar a maior parte da informação espalhada pelos atributos é encontrar uma transformação dos dados que use atributos o tão independentes quanto possível.
- Dessa forma, alguns atributos terão mais relevância do que outros, pois ao desfazer a interdependência, conseguimos “separar” a informação relevante da informação redundante
PCA : Principal Component Analysis¶
(Análise de Componentes Principais)
O PCA é uma transformação linear, ou seja, multiplica os vetores de atributos de entradas de N posições por uma matriz com MxN, com M ≤ N, resultando em um novo vetor de N dimensões
O elemento que se destaca é a da variância
Essa transformação é obtida por meio dos vetores de treinamento. A redução na dimensionalidade é controlada pelo parâmetro que define a porcentagem de variabilidade que será mantida nos novos dados
No Python, fazemos:
from sklearn.decomposition import PCA
medidas_pca = PCA(0.5).fit_transform(df) # Mantem 50% de variabilidade
print(medidas_pca)
print("shape original: " , df.shape, "shape PCA: " , medidas_pca.shape)
[[ -5.81469106] [ 27.45356145] [ -1.35358402] [-20.28528637]] shape original: (4, 5) shape PCA: (4, 1)
- Cada linha nessa matriz corresponde a uma vetor com N dimensões, com um significado especial, denominado de auto-vetor
- No caso dos vetores serem imagens, essas “auto-imagens” guardam características que serão usadas para identificar as imagens de teste
#Instale os pacotes e faz o download dos arquivos, se ja estiver na pasta não precisa rodar essa celula.
#!pip3 install --user python-mnist
#!pip install wget
import wget
wget.download('http://yann.lecun.com/exdb/mnist/train-images-idx3-ubyte.gz')
wget.download('http://yann.lecun.com/exdb/mnist/train-labels-idx1-ubyte.gz')
wget.download('http://yann.lecun.com/exdb/mnist/t10k-images-idx3-ubyte.gz')
wget.download('http://yann.lecun.com/exdb/mnist/t10k-labels-idx1-ubyte.gz')
't10k-labels-idx1-ubyte.gz'
1 - Gera a matriz de dados de entradas e o vetor de classes alvo para treinamento¶
Cada linha da matriz de entradas (atributos) contém os pixels da imagem.
Cada posição do array de rótulos (labels) contém a classe alvo da imgem.
No caso deste dataset, as imagens de trenamento e de teste já estão separadas, e vamos adotar a separação sugerida pelo autor da base de dados.
import time
import numpy as np
# API MNIST
from mnist import MNIST
t0 = time.time()
# Importa os dados do dieretório local
mndata = MNIST('.')
# Habilita abrir arquivos compactados
mndata.gz = True
# Carrega os dados de treinamento
entradas_treino, classes_treino = mndata.load_training()
# Carrega os dados de treinamento
entradas_teste, classes_teste = mndata.load_testing()
#Transformando em array do numpy
entradas_treino = np.array(entradas_treino)
classes_treino = np.array(classes_treino)
entradas_teste = np.array(entradas_teste)
classes_teste = np.array(classes_teste)
dados_reduzidos = False
print("Tempo para carregamento das imagens: {}s".format(time.time()-t0))
print("Dimensões da matriz dos dados de treinamento: ", entradas_treino.shape)
print("Dimensões da matriz dos dados de teste: ", entradas_teste.shape)
Tempo para carregamento das imagens: 14.753993034362793s Dimensões da matriz dos dados de treinamento: (60000, 784) Dimensões da matriz dos dados de teste: (10000, 784)
1.1 Visualizção de uma imagem¶
Neste dataset cada imagem está armazenada como uma linha da matriz de entrada.
Para visualizar a imagem que está na linha i
da matriz, temos que convertê-la novamente em uma matriz quadrada, e usar a biblioteca matplotlib
# Função que visualiza a linha lin da matriz
import matplotlib.pyplot as plt
import math
def visualiza_linha_mnist(matriz, lin):
size = int(math.sqrt(matriz.shape[1]))
img = np.reshape(matriz[lin], (size, size))
plt.imshow(img, cmap="gray")
# Visualização da linha 0
visualiza_linha_mnist(entradas_treino, 0)
plt.show()
2 - Faz a normalização e a redução da dimensionalidade com PCA¶
Instancia o modelo PCA de forma que 85% da variabilidade de dados seja mantida.
O método fit_transform(X)
treina o PCA e já traz os dados X
transformados.
Para reaproveitar o mesmo modelo PCA sem treiná-o novamente, usamos transform()
.
Uma vez que os dados de treinamento e teste já estão separados,treinamos o normalizador e o PCA com os dados de treinamento, e apenas aplicamos a transformação nos dados de teste.
from sklearn.preprocessing import StandardScaler
# PCA
from sklearn.decomposition import PCA
t0 = time.time()
normalizador = StandardScaler()
redutor_dim = PCA(0.85)
entradas_treino_norm = normalizador.fit_transform(entradas_treino)
entradas_treino_norm = redutor_dim.fit_transform(entradas_treino_norm)
entradas_teste_norm = normalizador.transform(entradas_teste)
entradas_teste_norm = redutor_dim.transform(entradas_teste_norm)
print("Tempo para o processamento (normalização + PCA) das imagens: {}s".format(time.time()-t0))
print("Novas dimensoes das matrizes de dados e classes (labels) de treinamento")
print(entradas_treino_norm.shape, entradas_teste_norm.shape)
Tempo para o processamento (normalização + PCA) das imagens: 19.009876012802124s Novas dimensoes das matrizes de dados e classes (labels) de treinamento (60000, 185) (10000, 185)
print("Dimensões da matriz dos dados de treinamento: ", entradas_treino.shape)
print("Dimensões da matriz dos dados de teste: ", entradas_teste.shape)
print(28*28)
Dimensões da matriz dos dados de treinamento: (60000, 784) Dimensões da matriz dos dados de teste: (10000, 784) 784
##Avaliação PCA
print (len(entradas_treino_norm), len(entradas_treino_norm))
print ("taxa de variancia explicada: " , len(redutor_dim.explained_variance_ratio_), redutor_dim.explained_variance_ratio_)
print ("valores de cada um dos componentes: ", len(redutor_dim.singular_values_), redutor_dim.singular_values_)
60000 60000 taxa de variancia explicada: 185 [0.05646717 0.04078272 0.0373938 0.02885115 0.02521109 0.0219427 0.01923344 0.01745799 0.01535092 0.0140172 0.01341743 0.01203742 0.0111457 0.01089924 0.01028649 0.00994487 0.00936383 0.00921046 0.00893437 0.00869913 0.00827363 0.00803417 0.00764846 0.00741772 0.00715293 0.00691847 0.00684136 0.00656675 0.00631677 0.0061292 0.00596255 0.00587716 0.00571592 0.00562307 0.00554682 0.00538418 0.00531182 0.00519606 0.00508211 0.00480006 0.00476456 0.00469139 0.00454349 0.00451346 0.00446963 0.00443383 0.00438215 0.00430382 0.00426878 0.00423647 0.00404696 0.00399447 0.00397456 0.00393821 0.00385814 0.00379043 0.00375403 0.00370776 0.00364944 0.00359301 0.00352382 0.00347794 0.00344411 0.00339868 0.00335955 0.00334886 0.00331864 0.00323026 0.00316277 0.00313244 0.00310731 0.00307243 0.00304914 0.00302717 0.00299485 0.00297761 0.00295052 0.00290438 0.00286856 0.00285678 0.00283398 0.00282627 0.00279551 0.00279305 0.00278519 0.00277455 0.00275901 0.00274227 0.00271411 0.00269263 0.00266484 0.00263581 0.00262962 0.00261034 0.00258827 0.00256176 0.00253846 0.00250447 0.00247829 0.00245034 0.00242347 0.00242064 0.00238875 0.00237455 0.00235608 0.00233053 0.0022798 0.00226174 0.00222832 0.00222442 0.00218169 0.00217257 0.00214277 0.00211938 0.00210972 0.0020733 0.00204761 0.00204368 0.00202409 0.00200462 0.00198822 0.00195216 0.00193737 0.00192103 0.00191716 0.00189802 0.00187089 0.00186536 0.0018132 0.00180005 0.00179194 0.00178973 0.0017695 0.00176158 0.00174797 0.00172985 0.00172017 0.00168727 0.00168517 0.00166842 0.00164718 0.00164575 0.00164294 0.00161486 0.0016049 0.00158912 0.0015749 0.00155918 0.00155638 0.00154666 0.00154043 0.00151605 0.00150272 0.00148761 0.00147505 0.0014682 0.00145803 0.00145568 0.00144737 0.00142895 0.00141058 0.00139939 0.00139709 0.00139533 0.00139355 0.00139225 0.00138773 0.0013834 0.00137816 0.00136845 0.00136165 0.00135822 0.00133701 0.00132905 0.00131059 0.00130293 0.00129324 0.00128241 0.00127407 0.00126822 0.00125322 0.00124045 0.00122984 0.00121618 0.00121506] valores de cada um dos componentes: 185 [1558.59475775 1324.56506425 1268.33806904 1114.08096949 1041.4321537 971.58372712 909.62781125 866.6272717 812.64796157 776.54347762 759.74854205 719.61780297 692.45059052 684.75186297 665.2254475 654.08571283 634.6905444 629.47108378 619.96491977 611.74864821 596.60000904 587.90318277 573.61706238 564.89867585 554.72424844 545.55706108 542.50833328 531.50859803 521.29389656 513.4959735 506.46720335 502.82760665 495.88178934 491.83803286 488.4917578 481.27703518 478.03201127 472.79417281 467.58152416 454.42094643 452.73755506 449.24798572 442.10962544 440.64606814 438.50160223 436.74183847 434.18923818 430.29086602 428.53573113 426.91093544 417.25324612 414.53862665 413.50407786 411.60868344 407.40275713 403.81203369 401.86842781 399.38423688 396.23108492 393.15532131 389.35177902 386.80851333 384.92303762 382.37581508 380.16791664 379.56282447 377.84621102 372.78112287 368.86630886 367.09355234 365.61819099 363.56002954 362.17963536 360.87245819 358.94092281 357.90621176 356.27402823 353.47770091 351.29123623 350.56891845 349.16718716 348.69212323 346.78936634 346.6369362 346.14874915 345.48710725 344.51781742 343.47138797 341.70285667 340.34823393 338.58759852 336.73828279 336.34220011 335.10707121 333.68749917 331.97454025 330.46102411 328.24139239 326.52136861 324.67435089 322.88936082 322.70086024 320.56858096 319.61385191 318.36887157 316.63780238 313.1725175 311.92971598 309.61609571 309.34544735 306.360028 305.71862309 303.61468514 301.95298194 301.26427292 298.6527374 296.79663011 296.51171699 295.08666108 293.66447678 292.46061956 289.79603176 288.69671405 287.47662373 287.18664393 285.74965273 283.70035923 283.28015727 279.29169961 278.27731866 277.64955632 277.47843311 275.90592833 275.28720761 274.22175433 272.7966822 272.03227791 269.41865042 269.25082545 267.90897203 266.19893845 266.08295896 265.85540571 263.57386832 262.7601788 261.46521492 260.29213116 258.9899899 258.75750421 257.94798876 257.42815671 255.38269599 254.25740548 252.97587879 251.90640352 251.32057934 250.44831234 250.24628968 249.53113324 247.93848294 246.33934447 245.36012105 245.15894614 245.00431129 244.84794458 244.73387616 244.33626317 243.95435627 243.49224383 242.63262475 242.0297457 241.72463554 239.82975985 239.11486781 237.44845681 236.75327822 235.87142391 234.8811359 234.11618726 233.57844421 232.19261652 231.00662861 230.01633731 228.73575127 228.63068847]
2.1 - Visualização das 16 primairas imagens principais¶
O PCA neste caso transforma um array (entrada ou linha da matriz) composta por um conjunto de pixels em um outro array que indica a composição da imagem em termos de "imagens principais"
plt.figure(figsize=(10,10))
plt.subplot(4,4,1)
for i in range(4):
for j in range(4):
plt.subplot(4,4,i*4+j+1)
visualiza_linha_mnist(redutor_dim.components_, i*4 + j)
plt.show()
<ipython-input-23-e7a2857a4126>:5: MatplotlibDeprecationWarning: Adding an axes using the same arguments as a previous axes currently reuses the earlier instance. In a future version, a new instance will always be created and returned. Meanwhile, this warning can be suppressed, and the future behavior ensured, by passing a unique label to each axes instance. plt.subplot(4,4,i*4+j+1)
Desafio 3¶
Agora é com você termine a implementaçao deste classificador de digitos usando o KNN. Usar as novas matrizes no treinamento, teste e avaliação do classificador
## Seu código aqui.....