Aula 15 – Scikit-Learn – Reconhecimento facial – Código

Aula 15 – Scikit-Learn – Reconhecimento facial – Código

Voltar para página principal do blog

Todas as aulas desse curso

Aula 14              Aula 16

Script dessa aula:

Download do script da aula

Documentação oficial do Sklearn:

https://scikit-learn.org/stable/

Scikit-Learn - Reconhecimento facial - Código

Scikit-Learn – Reconhecimento facial – Código

Se gostarem do conteúdo dêem um joinha 👍 na página do Código Fluente no
Facebook

Link do código fluente no Pinterest

Meus links de afiliados:

Hostinger

Digital Ocean

One.com

Essa aula é baseada no trabalho apresentado no:

Labeled Faces in the Wild: A Database for Studying Face Recognition in Unconstrained Environments Gary B. Huang,Manu Ramesh, Tamara Berg, and Erik Learned-Miller

Para o download da base LFW é só clicar nesse link abaixo:

https://scikit-learn.org/stable/auto_examples/applications/plot_face_recognition.html

Ou da fonte original

http://vis-www.cs.umass.edu/lfw/

Código completo

Esse código é praticamente o mesmo do scikit, as mudanças foram:

  • Os comentários mais detalhados e em português

  • Foi adicionado um docstring

  • Nos prints foi utilizada a formatação mais atual do python 3, o novo mecanismo de formatação de sequência de caracteres conhecido como Literal String Interpolation ou mais comumente como sequências de caracteres F (devido ao caractere f que precede a string). A ideia por trás das strings f é simplificar a interpolação de strings.


"""
================================
Faces recognition example using eigenfaces and SVMs
================================

An example showing how the scikit-learn can be used to faces recognition with eigenfaces and SVMs

================================
================================

================================
Exemplo de reconhecimento de faces usando autofaces e SVMs
================================

Exemplo mostrando como o scikit-learn pode ser usado para reconhecimento de faces com autofaces e SVMs
"""
from time import time
import logging
import matplotlib.pyplot as plt

from sklearn.model_selection import train_test_split
from sklearn.model_selection import GridSearchCV
from sklearn.datasets import fetch_lfw_people
from sklearn.metrics import classification_report
from sklearn.metrics import confusion_matrix
from sklearn.decomposition import PCA
from sklearn.svm import SVC

print(__doc__)

# O logging exibe o progresso da execução no stdout
# adicionando as informações de data e hora
logging.basicConfig(level=logging.INFO, format='%(asctime)s %(message)s')

# #############################################################################
# Download dos dados, se ainda não estiver em disco e carregue-a como uma matriz numpy
lfw_people = fetch_lfw_people(min_faces_per_person=70, resize=0.4)

# Inspeciona as matrizes de imagens para encontrar os formatos das imagens( para plotagem )
n_samples, h, w = lfw_people.images.shape

# para aprendizado de máquina, usamos 2 dados diretamente( esse modelo ignora
# informações relativas a posição do pixel )
X = lfw_people.data
n_features = X.shape[1]

# A rótulo( label ) a prever é o ID da pessoa
y = lfw_people.target
target_names = lfw_people.target_names
n_classes = target_names.shape[0]

print("Total dataset size:")
print(f"n_samples: {n_samples}")
print(f"n_features: {n_features}")
print(f"n_classes: {n_classes}")

# #############################################################################
# Divide a base em um conjunto de treinamento e um conjunto de teste usando k fold
# 25% da base para o conjunto de teste os 75% restantes para o treino
# random_state é para inicializar o gerador interno de números aleatórios
# Definir random_state com um valor fixo garantirá que a mesma sequência de números 
# aleatórios seja gerada cada vez que você executar o código
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.25, random_state=42)

# #############################################################################
# Computa o principal component analysis - PCA (eigenfaces) na base de faces 
# ( tratado como dataset não rotulado ): extração não supervisionada / redução de dimensionalidade
n_components = 150
print(f"Extracting the top {n_components} eigenfaces from {X_train.shape[0]} faces")
# t0 guarda o tempo zero, para cálculo do tempo de execução do PCA
# O cálculo é feito no time() - t0 do print da linha 81
t0 = time()
pca = PCA(n_components=n_components, svd_solver='randomized',
          whiten=True).fit(X_train)
print("done in {0:.3f}s".format(time() - t0))

eigenfaces = pca.components_.reshape((n_components, h, w))

print("Projecting the input data on the eigenfaces orthonormal basis")
t0 = time()
X_train_pca = pca.transform(X_train)
X_test_pca = pca.transform(X_test)
print("done in {0:.3f}s".format(time() - t0))

# #############################################################################
# Treinando um modelo de classificação SVM

print("Fitting the classifier to the training set")
t0 = time()
param_grid = {'C': [1e3, 5e3, 1e4, 5e4, 1e5],
              'gamma': [0.0001, 0.0005, 0.001, 0.005, 0.01, 0.1], }
clf = GridSearchCV(SVC(kernel='rbf', class_weight='balanced'), param_grid)
clf = clf.fit(X_train_pca, y_train)
print("done in {0:.3f}s".format(time() - t0))
print("Best estimator found by grid search:")
print(clf.best_estimator_)

# #############################################################################
# Avaliação quantitativa da qualidade do modelo sobre o conjunto de testes

print("Predicting people's names on the test set")
t0 = time()
y_pred = clf.predict(X_test_pca)
print("done in {0:.3f}s".format(time() - t0))

print(classification_report(y_test, y_pred, target_names=target_names))
print(confusion_matrix(y_test, y_pred, labels=range(n_classes)))

# #############################################################################
# Avaliação qualitativa das previsões usando matplotlib

def plot_gallery(images, titles, h, w, n_row=3, n_col=4):
    """Helper function to plot a gallery of portraits"""
    plt.figure(figsize=(1.8 * n_col, 2.4 * n_row))
    plt.subplots_adjust(bottom=0, left=.01, right=.99, top=.90, hspace=.35)
    for i in range(n_row * n_col):
        plt.subplot(n_row, n_col, i + 1)
        plt.imshow(images[i].reshape((h, w)), cmap=plt.cm.gray)
        plt.title(titles[i], size=12)
        plt.xticks(())
        plt.yticks(())

# Plota o resultado da previsão em uma parte do conjunto de testes
def title(y_pred, y_test, target_names, i):
    pred_name = target_names[y_pred[i]].rsplit(' ', 1)[-1]
    true_name = target_names[y_test[i]].rsplit(' ', 1)[-1]
    return f'predicted: {pred_name}\ntrue:      {true_name}'

prediction_titles = [title(y_pred, y_test, target_names, i)
                     for i in range(y_pred.shape[0])]

plot_gallery(X_test, prediction_titles, h, w)

# plota a galeria das autofaces mais significativas

eigenface_titles = [f"eigenface {i}" for i in range(eigenfaces.shape[0])]
plot_gallery(eigenfaces, eigenface_titles, h, w)

plt.show()

Visão geral do código.

Qualquer função, classe ou módulo que comece com uma string literal tem um __doc__ não vazio.

Ela é a string de documentação da função, classe ou módulo.

Se estiver vazia será definido como None.

Ao fazer o download do exemplo de um script Scikit, em geral, você verá que ele começa com uma string do tipo:


"""
================================
Faces recognition example using eigenfaces and SVMs
================================
An example showing how the scikit-learn can be used to faces recognition with eigenfaces and SVM
================================
================================
Exemplo de reconhecimento de faces usando autofaces e SVMs
================================
Exemplo mostrando como o scikit-learn pode ser usado para reconhecimento de faces com autofaces e SVMs
"""

O print (__ doc__) simplesmente reutiliza essa string de documentação para mostrar no seu terminal, toda vez que você executar o script.

Logging

O Logging é uma ferramenta muito útil.

Ele ajuda a desenvolver uma melhor compreensão do fluxo de um programa e descobrir cenários nos quais você nem imaginou durante o desenvolvimento.

Os logs fornecem aos desenvolvedores um conjunto extra de olhos que estão constantemente observando o fluxo pelo qual um aplicativo passa.

Podem armazenar informações, como qual usuário ou IP acessou o aplicativo.

Se ocorrer um erro, pode fornecer mais informações do que um rastreamento de pilha, informando qual era o estado do programa antes de chegar à linha de código em que ocorreu o erro.

Enfim, essencial.

A linha logging.basicConfig(level=logging.INFO, format=’%(asctime)s %(message)s’) exibe o progresso da execução em logs no stdout.

Carga dos dados

Quando os dados são carregados, em lfw_people ele só pega pessoas que tem mais de 69 imagens diferentes (min_faces_per_person) na base, e com o resize é informada a proporção de 0.4 usada para redimensionar a imagem de cada rosto.

Depois com lfw_people.images.shape pegamos a largura(w), altura(h) e quantidade de samples(n_samples).

Com: X = lfw_people.data a parte dos dados é atribuído ao X.

Em n_features = X.shape[1] pegamos o número de características de cada imagem, que será reduzida logo mais na frente, no PCA.

No y = lfw_people.target a parte target, ou seja, as classificações, são atribuidas a y.

Já em target_names = lfw_people.target_names pegamos as pessoas mais representadas no LFW.

Resultados esperados para as 7 pessoas mais representadas no conjunto de dados:

[‘Ariel Sharon’, ‘Colin Powell’, ‘Donald Rumsfeld’, ‘George W Bush’,’Gerhard Schroeder’, ‘Hugo Chavez’, ‘Tony Blair’]

Divisão da base para treino e teste

A base é dividida em um conjunto de treinamento e um conjunto de teste usando k fold.

25% da base para o conjunto de teste os 75% restantes para o treino.

O random_state é para inicializar o gerador interno de números aleatórios.

Definir random_state com um valor fixo garantirá que a mesma sequência de números aleatórios seja gerada cada vez que você executar o código.

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=42)

Hiper-parâmetros são parâmetros que não são aprendidos diretamente nos estimadores.

No scikit-learn, eles são passados como argumentos para o construtor das classes dos estimadores.

Exemplos típicos incluem C, kernel e gama para o Support Vector Classifier, alfa para Lasso, etc.

É possível e recomendado procurar no espaço de hiper-parâmetros a melhor pontuação da validação cruzada.

Qualquer parâmetro fornecido ao construir um estimador pode ser otimizado dessa forma.

Especificamente, para encontrar os nomes e os valores atuais de todos os parâmetros para um determinado estimador, use:


estimator.get_params()

Redução de dimensionalidade

Computa o principal component analysis – PCA (eigenfaces) na base de faces, tratado como dataset não rotulado, a extração é não supervisionada nessa redução de dimensionalidade

A redução de dimensionalidade linear usa a Decomposição de Valor Singular dos dados para projetá-los em um espaço dimensional inferior.

Os dados de entrada são centralizados, mas não redimensionados para cada feature antes de aplicar o SVD (Singular Value Decomposition).

Ele usa a implementação LAPACK (LAPACK Linear Algebra PACKage) do SVD completo ou de um SVD truncado randomizado pelo método de Halko et al. 2009, dependendo da forma dos dados de entrada e do número de componentes a serem extraídos.

Cálculo de tempo

Em cada etapa, na redução de dimensionalidade, na fase de treinamento, etc. é utilizado o módulo time para calcular o tempo gasto nessas etapas.


#Tempo inicial
t0 = time()
...
processo que se quer medir o tempo
...
#imprime o tempo gasto
print("done in {0:.3f}s".format(time() - t0))

O processo de redução de dimensionalidade PCA, tenta ao mesmo tempo, preservar a maior parte da variação nas imagens.

A classe PCA usada com o parâmetro opcional svd_solver=’randomized’ é muito útil nesse caso: como vamos eliminar a maioria dos vetores singulares, é muito mais eficiente limitar o cálculo a uma estimativa aproximada dos vetores singulares que manteremos para realmente executar a transformação.

Whitening é uma importante etapa de pré-processamento para muitos algoritmos.

Ele remove ainda mais a correlação linear entre os recursos com ‘whiten = True‘.

O whiten = True escala os componentes principais pelos valores próprios equivalentes, de modo que as variações tenham a mesma unidade.

Às vezes, isso é usado na análise de imagens para aprimorar as bordas de uma imagem em relação a outros recursos.

Em termos de distância euclidiana, esperamos que o clareamento(whitening) torne as imagens da mesma classe e, portanto, compartilhe um conjunto de arestas semelhantes mais próximas umas das outras, devido ao fato de ignorar algumas diferenças como brilho por exemplo.

A linha: eigenfaces = pca.components_.reshape((n_components, h, w)), projeta os dados de entrada na base ortonormal de autofaces.

As linhas:


t0 = time()
X_train_pca = pca.transform(X_train)
X_test_pca = pca.transform(X_test)
print("done in {0:.3f}s".format(time() - t0))

Atribui a X_train_pca  a base de treino já com as dimensões reduzidas pelo processo do PCA do passo anterior.

A mesma coisa para a base de teste e o print em seguida, mostra o tempo gasto nesse processo.

Ficamos por aqui!

Na próxima a gente continua a analisar o código, vamos ver a parte de treinamento.

Obs. Eu disse no vídeo que na aula 16 a gente iria ver a parte de treinamento e avaliação, mas, achei melhor dividir as partes do código em aulas distintas, para um melhor detalhamento nas explicações. 😉

Voltar para página principal do blog

Todas as aulas desse curso

Aula 14              Aula 16

Link do meu Github com o script dessa aula:

Download do script da aula

Se gostarem do conteúdo dêem um joinha 👍 na página do Código Fluente no
Facebook

Link do código fluente no Pinterest

Novamente deixo meus link de afiliados:

Hostinger

Digital Ocean

One.com

Obrigado, até a próxima e bons estudos. 😉

About The Author
-

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>