模式识别与机器学习(作业5)基于PCA–LDA的人脸识别

简介: 本次的实验是在模式识别与机器学习(作业4),PCA降维的基础上加入了线性判别分析,对维度进行了进一步的降低。

1. 导入数据

一共有40个人脸,每个人脸10张图片,8张用于训练,2张用于测试。所以训练集有320张图片,测试集有80张图片。图像的分辨率为112*92,我们将其reshape为(1,10304)。由此得到训练集(320,10304),测试集(180,10304)

#%%导入数据
import numpy as np
import cv2
import os.path as osp
import os
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import accuracy_score
#训练集路径
osp.abspath(".")
#导入训练数据
train_x,train_y = [],[]
for i in os.listdir(osp.join(osp.realpath("."),"train_1")):
    img = cv2.imread(osp.join(osp.realpath("."),"train_1",i),0)
    train_x.append(np.reshape(img,(1,-1)))
    a,_ = i.split("_")
    train_y.append(a)
test_x,test_y = [],[]
for i in os.listdir(osp.join(osp.realpath("."),"test")):
    img = cv2.imread(osp.join(osp.realpath("."),"test",i),0)
    test_x.append(np.reshape(img,(1,-1)))
    a,_ = i.split("_")
    test_y.append(a)
train_x = np.array(train_x,dtype = np.float32).squeeze(1)
train_y = np.array(train_y)
test_x = np.array(test_x,dtype = np.float32).squeeze(1)
test_y = np.array(test_y)

2. PCA降维

在训练时,最初采用的是特征值分解的方法,但是存在的问题是,因为维度较高,特征分解时间较长,并且分解后的特征向量存在虚数,不利于识别。因此,我采用了第二种方法,SVD分解的方法**(保留前80个维度)**,具体的步骤请参照李航博士《统计学习原理》第二版一书(page336),这里不再一一赘述。

class PCA:
    #定义K近邻的值必须大于1
    def __init__(self):
        self.x_train_fit = None
        self.y_train_fit = None
        self.u = None
        self.s = None
        self.vh = None
    def fit(self,x_train,y_train):
        self.x_train_fit = x_train
        self.y_train_fit = y_train
        return self
    #中心化,建立模型
    def Centralization(self,X):
        Centra = X - np.mean(self.x_train_fit,axis = 0)
        return Centra
    def model(self):
         #定义一个新矩阵
         X_ = (1/np.sqrt(len(self.Centralization(self.x_train_fit))))*self.Centralization(self.x_train_fit)
         #进行奇异值分解
         self.u, self.s, self.vh = np.linalg.svd(X_)
     #降维
    def transform(self,X,K):
        X = self.Centralization(X)
        X_dunction = (((self.vh).T[:,:K]).T).dot(X.T).T
        return X_dunction
#%%
pca = PCA()
pca.fit(train_x,train_y)
pca.model()
k=80
X_test_dunction_1 = pca.transform(test_x,k)
X_train_dunction_1 = pca.transform(train_x,k)

3. LDA降维

LDA也可以推广到了多分类的任务当中。假定存在 N NN个类,且第i ii 类示例数为m i m_im

i

我们先定义"全局散度矩阵"St=Sb+Sw=i=1m(xiμ)(xiμ)T

其中u uu是所有示例样本的均值xi为第i ii类样本的示例。

我们还要重新定义多分类任务的类内散度S w S_wS 即每个类别的散度矩阵之和:

S w = ∑ i = 1 N S w i \mathbf{S}_{w}=\sum_{i=1}^{N} \mathbf{S}_{w_{i}}



其中

S w i = ∑ x ∈ X i ( x − μ i ) ( x − μ i ) T \mathbf{S}_{w_{i}}=\sum_{\boldsymbol{x} \in X_{i}}\left(\boldsymbol{x}-\boldsymbol{\mu}_{i}\right)\left(\boldsymbol{x}-\boldsymbol{\mu}_{i}\right)^{\mathrm{T}}



由以上公式可以知道

S b = S t − S w = ∑ i = 1 N m i ( μ i − μ ) ( μ i − μ ) T

Sb=St−Sw=∑i=1Nmi(μi−μ)(μi−μ)T

Sb=St−Sw=∑i=1Nmi(μi−μ)(μi−μ)T


其中S b S_bS

b

为类间散度,m i m_im

i

表示的为类别,在本题目中有40个类别。u i u_iu

i

是同一类别下的特征均值。

一般的我们可以利用如下公式,进行求解,其中W WW就是一个投影矩阵,我们可以选取特征值最大的前K个,用于特征的降维。

S b W = λ S w W \mathbf{S}_{b} \mathbf{W}=\lambda \mathbf{S}_{w} \mathbf{W}

#%%导入数据
#%%算法的判别
#需要计算肋间方差和类内方差
import collections
#求取所用示例的均值向量(k,),k表示降维后的数据
mean_u = np.mean(X_train_dunction_1,axis = 0)
#求取类间散度矩阵,和类内散度矩阵
S_b = np.zeros((X_train_dunction_1.shape[1],X_train_dunction_1.shape[1]))
S_w = np.zeros((X_train_dunction_1.shape[1],X_train_dunction_1.shape[1]))
get_class =  collections.Counter(train_y).keys()
for classes in get_class:
    x_i = np.array([x_i for x_i,i in zip(X_train_dunction_1,train_y) if i == classes])
    mean_u_i = np.mean(x_i,axis = 0)
    #类间散度矩阵
    S_b = S_b + (mean_u_i - mean_u).reshape(-1,1).dot((mean_u_i - mean_u).reshape(1,-1))
    #类内散度矩阵,西瓜书公式3.41,3.42
    S_w = S_w + (x_i - mean_u_i).T.dot(x_i - mean_u_i)
#类间散度矩阵,西瓜书公式3.43
S_b = S_b * len(get_class)
#进行特征值分解
eig_vals, eig_vecs = np.linalg.eig(np.linalg.inv(S_w).dot(S_b))
#对特征值进行由高到低的排序
eig_vecs = np.array([eig_vecs[:,i] for i in np.argsort(-eig_vals)])
#%%求取准确度
for k in range(1,40):
    X_train_dunction_2 = X_train_dunction_1.dot(eig_vecs[:,:k])
    X_test_dunction_2 = X_test_dunction_1.dot(eig_vecs[:,:k])
    accu = 0
    for i in range(len(test_y)):
        a = [np.linalg.norm(X_test_dunction_2[i,:] - X_train_dunction_2[j,:]) for j in range(len(train_y))]
        min_dix = np.argmin(a)
        if train_y[min_dix] == test_y[i]:
            accu += 1
    print("保留前{}维的准确度为{}".format(k,accu/80))

结果

保留前1维的准确度为0.0875
保留前2维的准确度为0.425
保留前3维的准确度为0.575
保留前4维的准确度为0.7125
保留前5维的准确度为0.8
保留前6维的准确度为0.85
保留前7维的准确度为0.875
保留前8维的准确度为0.8875
保留前9维的准确度为0.875
保留前10维的准确度为0.8625
保留前11维的准确度为0.875
保留前12维的准确度为0.9125
保留前13维的准确度为0.9375
保留前14维的准确度为0.9125
保留前15维的准确度为0.9375
保留前16维的准确度为0.95
保留前17维的准确度为0.9375
保留前18维的准确度为0.9125
保留前19维的准确度为0.9625
保留前20维的准确度为0.9625
保留前21维的准确度为0.9625
保留前22维的准确度为0.9625
保留前23维的准确度为0.9625
保留前24维的准确度为0.975
保留前25维的准确度为0.975
保留前26维的准确度为0.975
保留前27维的准确度为0.9625
保留前28维的准确度为0.9625
保留前29维的准确度为0.9625
保留前30维的准确度为0.95
保留前31维的准确度为0.9625
保留前32维的准确度为0.95
保留前33维的准确度为0.9625
保留前34维的准确度为0.9625
保留前35维的准确度为0.9625
保留前36维的准确度为0.9625
保留前37维的准确度为0.95
保留前38维的准确度为0.9625
保留前39维的准确度为0.975

有测试结果得出,在本实验中保留前24维,准确度可以达到最佳。

相关文章
|
3月前
|
机器学习/深度学习 数据采集 算法
Python实现PCA降维和KNN人脸识别模型(PCA和KNeighborsClassifier算法)项目实战
Python实现PCA降维和KNN人脸识别模型(PCA和KNeighborsClassifier算法)项目实战
|
12月前
|
机器学习/深度学习 人工智能 监控
如何利用机器学习提高人脸识别准确率
如何利用机器学习提高人脸识别准确率
185 1
|
5月前
|
机器学习/深度学习 算法 API
【Paddle】PCA线性代数基础 + 领域应用:人脸识别算法(1.1w字超详细:附公式、代码)
【Paddle】PCA线性代数基础 + 领域应用:人脸识别算法(1.1w字超详细:附公式、代码)
83 0
|
机器学习/深度学习 安全 算法
机器学习引领未来:人脸识别技术的应用与挑战
当今世界,机器学习在各个领域都取得了巨大的成功和影响。其中,人脸识别技术无疑是一个备受关注的研究领域,它的广泛应用涵盖了从安全领域到娱乐产业的各个方面。本文将探讨机器学习在人脸识别方向的应用,以及这一技术的潜力和挑战。
|
机器学习/深度学习 数据采集 自然语言处理
基于机器学习的情绪识别算法matlab仿真,对比SVM,LDA以及决策树
基于机器学习的情绪识别算法matlab仿真,对比SVM,LDA以及决策树
|
5月前
|
机器学习/深度学习 算法 数据可视化
【模式识别】解锁降维奥秘:深度剖析PCA人脸识别技术
【模式识别】解锁降维奥秘:深度剖析PCA人脸识别技术
55 0
|
机器学习/深度学习 存储 算法
【机器学习实战项目】10分钟学会Python怎么用LDA线性判别模型进行分类预测(五)
【机器学习实战项目】10分钟学会Python怎么用LDA线性判别模型进行分类预测(五)
305 0
|
机器学习/深度学习
经典机器学习系列(二)【线性判别分析LDA】
经典机器学习系列(二)【线性判别分析LDA】
116 0
|
算法 生物认证 语音技术
基于ORL人脸数据库和PCA特征降维算法的人脸识别matlab仿真
基于ORL人脸数据库和PCA特征降维算法的人脸识别matlab仿真
199 0
|
机器学习/深度学习 传感器 算法
【人脸识别】基于PCA结合SVM和adaboost实现人脸识别附GUI界面
【人脸识别】基于PCA结合SVM和adaboost实现人脸识别附GUI界面
下一篇
无影云桌面