在本文中,我們將學習使用主成分分析(PCA)和支援向量機(SVM)來建立人臉識別模型。
首先,我們來看看PCA和SVM的介紹:
主成分分析:主成分分析(PCA)是一種機器學習演算法,廣泛應用於探索性資料分析和建立預測模型。它通常用於降維,方法是將每個資料點投影到前幾個主成分上,以獲得低維資料,同時儘可能保留資料的變化。
支援向量機支援向量機(SVM)是一種用於兩組分類問題的有監督機器學習模型。在為每個類別提供一組帶標籤的訓練資料後,它能夠對新的測試資料進行分類。
支援向量機基於最大化間隔的平面對資料進行分類,它的決策邊界是直的,是一種很好的影象分類演算法。實驗結果表明,支援向量機在經過3-4輪相關反饋後,其搜尋精度明顯高於傳統的查詢最佳化方案,對於影象分割系統也是如此,包括那些使用改進的支援向量機的系統。
人臉識別人臉是由許多畫素組成的高維資料。高維資料很難處理,也不能用二維資料的散點圖等簡單技術視覺化。
我們要做的是利用PCA對資料的高維進行降維處理,然後將其輸入到SVM分類器中對影象進行分類。
接下來進入編碼部分!
下面的程式碼示例取自關於eigenfaces的sklearn文件。我們將一步一步地檢查程式碼,以瞭解其複雜性和結果。
import pylab as plimport numpy as npfrom matplotlib import pyplot as pltfrom sklearn.model_selection import train_test_splitfrom sklearn.datasets import fetch_lfw_peoplefrom sklearn.model_selection import GridSearchCVfrom sklearn.metrics import classification_reportfrom sklearn.metrics import confusion_matrixfrom sklearn.decomposition import PCA as RandomizedPCAfrom sklearn.svm import SVC
將資料載入到Numpy陣列中接下來將資料下載到磁碟中,並使用fetch_lfw_people將其作為NumPy陣列載入sklearn.datasets。
lfw_people = fetch_lfw_people(min_faces_per_person=70, resize=0.4)
lfw資料集包括一個用於研究無約束人臉識別問題的人臉照片資料庫,其中有從網路收集的13000多張包含人臉的照片。1680名照片中的人在資料集中有兩張或兩張以上不同的照片。
影象採用灰度(畫素值=0-255)。
影象Numpy陣列接下來、尋找影象陣列圖片的形狀。我們將使用NumPy shape屬性,該屬性返回一個元組,每個索引都有對應元素的數量。
n_samples, h, w = lfw_people.images.shapenp.random.seed(42)
從變數explorer可以看到,我們有1288個樣本(圖片),高度為50px,寬度為37px(50x37=1850個特徵)。
Numpy陣列我們將使用lfw_people 的data陣列,直接儲存在X中,我們將在以後的處理中使用這些資料。
X = lfw_people.datan_features = X.shape[1]
X中的資料有1288個樣本,每個樣本有1850個特徵。
目標名稱和標籤接下來定義標籤,這些標籤是圖片所屬的人的id。
y = lfw_people.targettarget_names = lfw_people.target_namesn_classes = target_names.shape[0]
這裡,y代表目標,它是每個圖片的標籤。標籤由target_names變數進一步定義,該變數由7個要識別的人的姓名組成。
target是一個1288x1的NumPy陣列,它包含1288張圖片對應名稱的0–6值。因此,如果id 0的目標值為5,則表示“Hugo Chavez”,如target_names中所示:
因此,y是數字形式的目標,target_names是名稱中的任何目標/標籤,n_classes是儲存類數量的變數,在這個例子中有7個目標:
Ariel SharonColin PowellDonald RumsfeldGeorge W BushGerhard SchröderHugo ChavezTony Blair打印出變數:
print("Total dataset size:")print("n_samples: %d", n_samples)print("n_features: %d", n_features)print("n_classes: %d", n_classes)
所以,我們有1288個樣本(圖片),每個樣本總共有1850個特徵(50px37px)和7個類(人)。
劃分訓練集和測試集接下來,我們將使用sklearn.model_selection將資料(X-特徵和y-標籤)分為訓練資料和測試資料,其中25%用於測試,其餘75%用於訓練模型。
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=42)
以下是變數X-train、X_test、y_train和y_test:
基於PCA的降維方法現在,我們將從 sklearn.decomposition選擇PCA 以訓練模型。我們已經在第一段程式碼中匯入了PCA。
在這個例子中,訓練集X_train中總共有966個特徵,我們將使用PCA(維數縮減)將它們減少到50個:
n_components = 50pca = RandomizedPCA(n_components=n_components, whiten=True).fit(X_train)
這個過程需要不到一秒鐘的時間,這可以透過使用時間函式進行驗證(這一點暫時跳過)。
現在我們將重塑PCA元件並定義特徵臉,這是在人臉識別的計算機視覺問題中使用的一組特徵向量的名稱:
eigenfaces = pca.components_.reshape((n_components, h, w))
如截圖所示,特徵臉是一個50×50×37的Numpy陣列。前50對應於特徵的數量。
接下來,我們將使用PCA在X_train 和X_test 上的transform 函式來降低維數。
X_train_pca = pca.transform(X_train)X_test_pca = pca.transform(X_test)
從上面的截圖可以看出,透過PCA演算法,X_train和X_test的維數都被降低了。每一個都將特徵從1850個減少到50個(正如我們在演算法中定義的那樣)。
訓練SVM分類器完成了降維,我們現在就開始分類。首先將訓練SVM分類模型。
我們將使用GridSearchCV,這是一個庫函式,它是一種調整超引數的方法。它將系統地為網格中指定的演算法引數的每個組合建立和評估模型,並在最佳估計量('best_estimator_')引數網格中給出:
print("Fitting the classifier to the training set")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("Best estimator found by grid search:")print(clf.best_estimator_)
)
我們資料的最佳分類器是SVC,引數如下:
SVC(C=1000, class_weight = ‘balanced’, gamma=0.01)
預測現在在測試資料上預測這些人的名字。我們將使用從GridSearchCV中找到的分類器,它已經在訓練資料擬合。
print("Predicting the people names on the testing set")y_pred = clf.predict(X_test_pca)
分類報告和混淆矩陣
預測完成後,列印分類報告,它將顯示模型的精度、召回率、F1分數和支援分數。這使我們對分類器的行為有了更深入的瞭解。
print(classification_report(y_test, y_pred, target_names=target_names))
列印混淆矩陣:
print(confusion_matrix(y_test, y_pred, labels=range(n_classes)))
在上面的例子中,混淆矩陣列印真正例、假正例和假反例的值,並提供分類器的概述。
繪圖最後,繪製人物肖像和特徵臉!
定義兩個函式:title在測試集的一部分繪製預測結果,plot_gallery透過繪製它們來評估預測:
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 'predicted: %s\ntrue: %s' % (pred_name, true_name)def plot_gallery(images, titles, h, w, n_row=3, n_col=4): """繪製肖像庫的幫助函式""" 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(())
現在我們在測試集的一部分繪製預測結果:
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)
繪製特徵面。我們將使用在上面程式碼塊中定義的eigenfaces變數。
eigenface_titles = ["eigenface %d" % i for i in range(eigenfaces.shape[0])]plot_gallery(eigenfaces, eigenface_titles, h, w)plt.show()
最後,我們來繪製PCA+SVM模型用於人臉識別的精度:
from sklearn.metrics import accuracy_scorescore = accuracy_score(y_test, y_pred)print(score)
準確分數是0.81!雖然這並不是一個完美的分數,還有很大的改進空間,但PCA和SVM的人臉識別為我們提供了進一步強大演算法的起點!
結論本文利用PCA和SVM建立了一個人臉識別模型。主成分分析演算法被用來減少資料的維數;影象有很多畫素值!然後利用支援向量機進行分類,透過超引數調整尋找最佳估計量。我們對這些肖像進行了分類,準確度得分為0.81。