# 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:執行成果











## :memo:結果討論
這份作業我使用的是在機器學習所學到的Logistic Regression作為分類器
使用Logistic Regression作為分類器的選擇是因為:
1. 邏輯回歸對線性關係的擬合效果好
2. 邏輯回歸計算快(優於SVM和iForest)
3. 可以獲得A類跟B類的機率
4. 實務上Logistic Regression執行速度非常快
由上圖顯示擬合效果和辨識率都不錯
根據維度的慢慢提升,LDA版本的表現慢慢高於PCA的表現
不過我想對於實際的應用上可能比較不切實際
因為特徵不多若資料量更龐大時辨識率可能會大幅降低