Facial recognition systems have gained importance in studying computer vision, pattern recognition, and human-machine computer interfaces over the past few years. It is one of the tasks filled with complexities and challenges due to the possibility of variations. For example, humans’ illumination, posture, and facial expressions can be tricky to recognize quickly. Developers have suggested many approaches that they can utilize for such systems. Some of the most common approaches used for facial recognition systems are the PCA method and MLP classifier.

Facial Recognition with Python

What is PCA?

Principal component analysis, known as PCA, is a type of unsupervised learning method in Machine Learning. It is a non-parametric statistical method that helps in reducing dimensions in data sets. The developers use PCA to remove the extra number of features from data, leading to over-fitting the model. Since over-fitting causes generalization problems on examples outside the provided data set, PCA is used to remove the curse of dimensional to solve this problem.

Use of PCA in facial recognition

Performing Human facial recognition using PCA requires the generation of eigenfaces. In computer vision problems, eigenfaces are the set of eigenvectors that help facial recognition systems. Sirovich and Kirby developed this technique of using eigenvectors for developing facial recognition systems in 1987, which was later utilized by Mathew Turk and Alex Pentland to classify faces. The developers first transform the images provided for the algorithm’s training into a set of eigenfaces. They then convert the complete training data set of human images to eigenfaces by calculating standard face elements using statistical analysis. Therefore, they mostly express human images as a combination of different eigenfaces.

What is MLP?

A class of feed-forward artificial neural networks is known as Multilayer Perceptron or MLP. It includes three main types of layers of nodes. These layers are the following:

  1. Input Layer
  2. Hidden Layer
  3. Output Layer

In every layer, some neurons usually use a nonlinear activation function. This function returns true for all the layers, excluding input layer nodes. For training of such algorithms, a technique is used, which is known as the backpropagation method. Backpropagation is a technique of supervised learning and helps to differentiate the data, which is linearly inseparable. The perceptron in every layer of MLP is deeply connected. Therefore, there may be a considerable number of total parameters involved due to multiplication in different layers. Consequently, the high dimensional data sets become redundant.

Facial recognition using MLP classifier and PCA

In this tutorial, the user loads the dataset, called, Labelled faces in the wild (LFW), from the UMass website. However, although the developers can use their own labeled set, this article uses the LFW dataset to implement the facial recognition system.

Fetching the Dataset

The users can import the LFW data set from the sklearn library. The benefit of using it is that if the dataset is not available on the disk, it automatically downloads it from the internet. Moreover, they can also specify the minimum faces per person by giving the minimum number to the fetch_lfw_people() function.

from sklearn.datasets import fetch_lfw_people
lfw_dataset = fetch_lfw_people(min_faces_per_person=100)

#printing the set side by side
print("Size of data set: \n") 
samples, h, w = lfw_dataset.images.shapeprint("samples: \t %d \n" % samples)

X = lfw_dataset.data
features = X.shape[1]faces = X.shape[0]
print("features: \t %d \n" % features) 

y = lfw_dataset.target 
target_names = lfw_dataset.target_names
classes = target_names.shape[0]
print("classes: \t %d \n" % classes)

The user specifies the limit to be a hundred in the above coding example.  It means that the function should fetch the data of only those people who have equal to or more than a hundred faces. So, the function fetches the requested data as a numpy array for the developer to use later.
Note: All the images in the dataset should be of the same size to store them in a numpy array. Additionally, the images should not be so large to slow down the algorithm.

Splitting the dataset

In building a recognition system, the first step is to split the above data into testing and training data. Fortunately, the users can split the data by merely calling a function named train_test_split()and can control the splitting ratio and randomization in its arguments. The users can then store the returned data in independent testing and training variables.

from sklearn.model_selection import train_test_split
# split into a training and testing set
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.5, random_state = 0)
n_components =100

Dimension reduction using PCA

The next step is to use the PCA method to reduce the dimensionality of the data. The sklearn provides the functions to compute the PCA of any data. The user specifies the component count, which is otherwise known as the output dimensionality. In the example below, the developer is reducing the dimensionality to 100 eigenvectors. Moreover, the users can choose to whiten the data as in the below example. The whitening of the data makes it have a unit variance, which gives improved predictive accuracy.

Furthermore, the users can only apply the PCA () function on the training data and then apply the transformation to both data sets to generalize the testing data.

# PCA computation 
from sklearn.decomposition import PCA 

def pca_1 (xtrain, xtest, c):
 #whiten : bool, optional argument and by default "False."
 #Whitening removes some information from the transformed signal but improves the predictive accuracy
 
 start =time()
 n_components =100;
 print("Computing PCA.....")
 pca = PCA(n_components=n_components, whiten=True)
 pca.fit(xtrain)      #standardizing the training data to mean =0 & variance =1 

# # apply PCA transformation to training data
 X_train_pca = pca.transform(xtrain)
 X_test_pca = pca.transform(xtest)
 end = time()
 print("Time taken to compute PCA: %f sec" % ((end-start)))

Additionally, the user is calling the time () function inside the method, which is optional. It measures the starting and ending time of the function, which he uses to find the function’s time to compute PCA.

Multi-layer perceptron (MLP) classification

In the MLP method, the MLPClassifier () trains a multi-layer perceptron and fits the classifier on the data. In this classification function, the users can specify the size of hidden layers in the neural network and the batch size.  Moreover, the user can choose to give the bool argument for verbose and early stopping parameters. Verbose is an optional parameter that specifies whether the user wants the function to print progress messages to stdout or not. The early stopping argument gives it the authority that if the average accuracy does not increase significantly after a certain number of epochs, it stops training to prevent the model’s overfitting.

Secondly, it calls the predict method based on the classifier to predict the testing data. In this case, the testing data are the image faces that this method has to predict to tell which face belongs to whom.

Finally, the method calls for the classification report and the confusion matrix to show this classification’s predictive accuracy. The users can tweak the classifier parameters and compare the results to get a better classifier for their dataset.

#MLP classification
from sklearn.neural_network import MLPClassifier
from sklearn.metrics import classification_report
from sklearn.metrics import confusion_matrix 

def MLP(xtrain, xtest, ytrain, ytest):
 # train a multi-layer perceptron
 #verbose : bool, optional, default False (Whether to print progress messages to stdout)
 #batch_size :  number of samples that will be propagated through the network
 
 start =time()
 print("Fitting the classifier to the training set")
 clf = MLPClassifier(hidden_layer_sizes=(1024,), batch_size=256, verbose=False, early_stopping=True).fit(xtrain, ytrain)
 end = time()
 print("Time taken to train MLP: %f sec" % (end-start))
 start = time()
 y_pred = clf.predict(xtest)
 end = time()
 print("Time taken by MLP to predict: %f sec" % (end-start))
 print("classfication report:")
 print(classification_report(ytest, y_pred, target_names=target_names))
 print("confusion matrix:")
 print(confusion_matrix(ytest, y_pred, labels=range(classes)))

Visualization of the results

In most cases, the confusion matrices are not sufficient to help the users visualizing the results. Therefore, it is essential to plot the results gallery to evaluate the results by displaying the actual and predicted results gotten from the classification.

Importing the Matlab Plot Library

The users can visualize the results of the above methods using the Matlab plot library. The users need to import the library first, where they are importing all the essential modules. In the below example, the user is importing the pyplot as plt for ease of use in the visualization function.

import matplotlib.pyplot as plt

Note: the users can use any name in place of “plt”

Getting Titles of the Dataset

The images in the dataset are the pictures of some real-world persons with their names as the titles. In displaying the results, the users need to have those titles to display with the images to differentiate between the pictures.

The function below takes the predicted results, target results, and the target names as y_pred, y_test, and target_names in its argument. It then runs the loop on predicted results’ data and plots the predicted names on the actual names, which helps in the plot_gallery() function.

def titles(y_pred, y_test, target_names):
    for i in range(y_pred.shape[0]):
        pred_name = target_names[y_pred[i]].split(' ')[-1]
        true_name = target_names[y_test[i]].split(' ')[-1]
        yield 'predicted: {0}\ntrue: {1}'.format(pred_name, true_name)

 

Plotting Image Gallery

While writing algorithms for dataset visualization, the user can choose the number of images he wants to display on his screen while plotting the results.

In the sample code below, the plot_images() function takes the images and the titles returned from the titles() function, height, width, rows, and columns for displaying the gallery as its parameters. It first plots a figure, plots subplots inside it, and adjusts them according to the user-provided parameters. Moreover, the users can tweak the parameter’s values in the below example to suit their needs. Then, it runs a loop for columns into rows times because the number of the images that it has to display on the user’s screen depends on the number of columns and rows. Inside the loop, it reshapes the images and finally plots them with their actual and predicted titles on the user’s screen.

# Visualization of the results
def plot_images(titles, images, height, width, rows, columns):
    plt.figure(figsize=(columns * 1.5,rows * 2.5))
#adjust the image dimensions by tweaking these parameters
    plt.subplots_adjust(bottom=.90, left=.05, right=0.90, top=.02, hspace=.40)
    for i in range(columns * rows):
        plt.subplot(rows, columns, i + 1)
        plt.imshow(images[i].reshape((height, width)), cmap=plt.cm.gray)
        plt.title(titles[i], size=10)
        plt.xticks(())
        plt.yticks(())

Note: the height and width values in the function’s parameter are the low dataset’s values.

Visualizing the MLP results

The users can call the visualization function in the MLP function after obtaining the classification results, before or after calculating the confusion matrix. Below is the integration of the above functions in the MLP function:

prediction_titles = list(titles(y_pred, ytest, target_names))
plot_gallery(X_test, prediction_titles, h, w)

In the above sample code, the user stores the title function’s results in a list and passes it in the plot_images() function as one of its parameters.

 

Visualizing eigenfaces

The users can also visualize eigenfaces by calling the above plot_images() function to display the eigenfaces obtained by applying Principal Component Analysis (PCA) on the dataset.  However, the users must write a different script to get the titles for the PCA. Below is the sample code for the PCA titles:

# # Plotting eigen faces
height,width = lfw_dataset.images.shape
eigenfaces = pca.components_.reshape((n_components, height, width))
eigenface_titles = ["eigenface {0}".format(i) for i in range(eigenfaces.shape[0])]
plot_gallery(eigenfaces, eigenface_titles, height, width)

Conclusion

The amalgamation of PCA and MLP methods is one of the various strategies that the users can incorporate for facial recognition. However, as the PCA reduces the dimensionality of the images while keeping the principal features intact, it loses information that can help classify the facial features. Therefore, the users can run the algorithm with and without PCA and compare the obtained results and confusion matrices. Finally, they can choose to combine or replace the PCA and MLP with other classifiers such as SVM, ICA, LDA, and MDS for facial recognition.