# Face Recognization 資工四 410711225 連昱婷 ## :memo:方法及步驟 1. 依據資料庫的影像格式,設計一個讀取pgm影像檔的函式。 1. 每張人臉影像均為92x112=10304的灰階影像,讀取後請將其轉為10304x1的向量,即成為一個樣本。 1. 資料庫共含有400張影像(40人,每人10張),訓練時請只用200張(每人取5張)。 1. 利用PCA計算此200張影像的轉換矩陣,設法將維度從10304降至10, 20, 30, 40, 50維 1. 以這些較低維度的樣本訓練出你所學過的任何分類器來進行辨識。 1. 比較不同維度的辨識率,並統計出混淆矩陣。 1. 以降維後的樣本,繼續利用FLD(LDA)找出另一轉換矩陣,利用此矩陣轉換降維後的樣本(毋需降維只須轉換)為有較佳的類別分離度之新樣本。 1. 以前述之辨識器再度評量辨識率以及統計混淆矩陣。 ### 混淆矩陣 Confusion Matrix 混淆矩陣常是用來評估模型好壞的方法,判定一個分類模型的表現好壞,混淆矩陣的各項指標會被拿來參考: * TP(True Positive): 正確預測成功的正樣本 * TN(True Negative): 正確預測成功的負樣本 * FP(False Positive): 錯誤預測成正樣本(實為負樣本) * FN(False Negative): 錯誤預測成負樣本(沒能預測出來的正樣本) 此作業為使用Logistic Regression分類器撰寫 ## :memo:程式碼 ```python= import numpy as np import os, glob, random, cv2 from sklearn.linear_model import LogisticRegression import matplotlib.pyplot as plt from sklearn.metrics import confusion_matrix from sklearn.decomposition import PCA from sklearn.discriminant_analysis import LinearDiscriminantAnalysis as LDA #讀取圖像 def load(folder='./att_faces'): trainData = [] testData = [] yTrain = [] yTest = [] for k in range(40): folder2 = os.path.join(folder, 's%d' % (k + 1)) data = [cv2.imread(d, 0) for d in glob.glob(os.path.join(folder2, '*.pgm'))] sample = random.sample(range(10), 5) #隨機選擇5張圖片訓練 trainData.extend([data[i].ravel() for i in range(10) if i in sample]) testData.extend([data[i].ravel() for i in range(10) if i not in sample]) yTest.extend([k] * (10 - 5)) yTrain.extend([k] * 5) return np.array(trainData), np.array(yTrain), np.array(testData), np.array(yTest) #作圖畫出混淆矩陣 def plotmatrix(name, dimension, confusion_mat): plt.imshow(confusion_mat, interpolation='nearest', cmap=plt.cm.gray) plt.title('{} Dimension {}'.format(name, dimension)) plt.colorbar() tick_marks = np.arange(4) plt.xticks(tick_marks, tick_marks) plt.yticks(tick_marks, tick_marks) plt.ylabel('Real label') plt.xlabel('Predict label') plt.show() #使用Logistic Regression分類器 def classifer(name, dimension, xTrain, xTest, yTrain, yTest): model = LogisticRegression(max_iter=1000) #在測試時報錯內容為上限過小,因此將值擴大至1000 model.fit(np.array(xTrain), np.float32(yTrain)) yPredict = model.predict(np.float32(xTest)) print('%d: 維度%d %s : LSR識別率: %.3f%%' % (dimension/10, dimension,name, (yPredict == np.array(yTest)).mean() * 100)) return yTest.tolist(), yPredict def main(dimension): xTrain_, yTrain, xTest_, yTest = load() #PCA pca = PCA(n_components=dimension) pca.fit(xTrain_, yTrain) xTrain = pca.transform(xTrain_) xTest = pca.transform(xTest_) result, ans = classifer("PCA", dimension, xTrain, xTest, yTrain, yTest) confusion_mat = confusion_matrix(ans, result) plotmatrix("PCA", dimension, confusion_mat) #LDA lda = LDA() xTrain = lda.fit_transform(xTrain, yTrain) xTest = lda.transform(xTest) result, ans = classifer("LDA", dimension, xTrain, xTest, yTrain, yTest) confusion_mat = confusion_matrix(ans, result) plotmatrix("LDA", dimension, confusion_mat) if __name__ == '__main__': for i in range(10,51,10): main(i) ``` ## :memo:執行成果 ![](https://i.imgur.com/eCLWrLf.png) ![](https://i.imgur.com/GbKiEU1.png) ![](https://i.imgur.com/kHs9xc7.png) ![](https://i.imgur.com/cvwBbnu.png) ![](https://i.imgur.com/S9of0Ex.png) ![](https://i.imgur.com/dMeOmCs.png) ![](https://i.imgur.com/F9xcqog.png) ![](https://i.imgur.com/B295xzc.png) ![](https://i.imgur.com/Dp024Hs.png) ![](https://i.imgur.com/oBa27ra.png) ![](https://i.imgur.com/pV0Rp6w.png) ## :memo:結果討論 這份作業我使用的是在機器學習所學到的Logistic Regression作為分類器 使用Logistic Regression作為分類器的選擇是因為: 1. 邏輯回歸對線性關係的擬合效果好 2. 邏輯回歸計算快(優於SVM和iForest) 3. 可以獲得A類跟B類的機率 4. 實務上Logistic Regression執行速度非常快 由上圖顯示擬合效果和辨識率都不錯 根據維度的慢慢提升,LDA版本的表現慢慢高於PCA的表現 不過我想對於實際的應用上可能比較不切實際 因為特徵不多若資料量更龐大時辨識率可能會大幅降低