特征脸算法

前言

特征脸算法使经典的人脸识别算法,特征脸算法使用了PCA方法。本文介绍了PCA算法和其应用特征脸算法

算法流程

特征脸算法:

  1. 设数据集D为张 的图片,则将图片展开,组成 大小的矩阵。

  2. 计算此矩阵的对均值向量 ,此为,对每个图片,计算。

  3. 计算的协方差矩阵,注意的大小为。寻找的是像素之间的关系而不是图片之间的关系

  4. 计算算的特征值与其对应的特征向量 ,找到前个特征值所对应的特征向量,组成新的矩阵。

  5. 改变基。以特征向量作为新的基做新的图片

  6. 使用KNN进行分类

算法原理

如果我们要学习一组图片的基,让,其中

那么对于所有的图片,找到一个图片近似,对以下的求最小值

其中是欧几里得平方距离

是一个在的基中的一张图片

如果要使最小,则易得是样本图片的均值(偏导)

其中 。所以 ,此式独立于

的零维呈现是一个点 的一维呈现是一条线

让是通过的一条线的方向。回使的方差达到最高

其中是任意图像

是平均图像

J_1(\{\alpha^{(1)},\alpha^{(2)},...,\alpha^{(N)}\}, \mathbf{e})=\Sigma^N_{i=0}||(\alpha^{(0)}+a^{(i)}\mathbf{e})-\alpha^{(i)}||^2=\sum\limits_i(a^{(i)})^2-2\sum\limits_i a^{(i)}\mathbf{e}^T(\alpha^{(i)}-\alpha^{(0)})+\sum\limits^N_{i=0}||\alpha^{(0)}-\alpha^{(i)}||^2_2

当求出来的偏导为0的时候,可以将用代替

那么如何决定的方向呢?

J_1(\{\alpha^{(1)},\alpha^{(2)},...,\alpha^{(N)}\}, \mathbf{e})=\sum\limits_i(a^{(i)})^2-2\sum\limits_i a^{(i)}\mathbf{e}^T(\alpha^{(i)}-\alpha^{(0)})+\sum\limits^N_{i=0}||\alpha^{(0)}-\alpha^{(i)}||^2_2\\=-\sum\limits_i [\mathbf{e}^T(\alpha^{(i)}-\alpha^{(0)})]^2+\sum\limits^N_{i=0}||\alpha^{(0)}-\alpha^{(i)}||^2_2\\=-\sum\limits_i\mathbf{e}^T(\alpha^{(i)}-\alpha^{(0)})(\alpha^{(i)}-\alpha^{(0)})^T\mathbf{e}+\sum\limits^N_{i=0}||\alpha^{(0)}-\alpha^{(i)}||^2_2

其中为的协方差矩阵

由于是常数

其中

使用拉格朗日乘子法

当的时候

所以选取前个所对应的

为什么选择最大的:

最大的使最小

最后新的基为

这种算法也被称作PCA,可以看作是一个由原来维度的向量到大小的向量的投影

代码

from sklearn.datasets import fetch_openml
import numpy as np

mnist = fetch_openml('mnist_784', cache=False)

x_train = mnist.data.astype('float32')[:2000] / 255
y_train = mnist.target.astype('int64')[:2000]

x_test = mnist.data.astype('float32')[2000:2500] /255
y_test = mnist.target.astype('int64')[2000:2500]


def zero_mean(x_train, x_test):
    x_train_mean = np.mean(x_train, axis=0)
    x_train_norm = x_train - x_train_mean
    x_test_norm = x_test - x_train_mean
    return x_train_norm, x_test_norm


def compute_basis(data, n=300):
    C = data.T @ data
    w, v = np.linalg.eig(C)
    basis_indices = np.argsort(w)[::-1][:n]
    eigenvectors = v[basis_indices]
    return eigenvectors.T


def change_basis(data_matrix, eigenvectors):
    I_eig = data_matrix @ eigenvectors
    return I_eig


def knn_predict(eig_train_x, eig_test_x, y_train, y_test, k=1):
    predictions = np.zeros_like(y_test)
    for i in range(eig_test_x.shape[0]):
        x = eig_test_x[i]
        distance_vector = np.sum((eig_train_x - x) ** 2, axis=1)
        nearest_indices = np.argsort(distance_vector)[:k]
        a = y_train[nearest_indices]
        uni, count = np.unique(a, return_counts=True)
        predictions[i] = uni[np.argmax(count)]
    return predictions


if __name__ == '__main__':
    x_train_norm, x_test_norm = zero_mean(x_train, x_test)
    eigenvectors = compute_basis(x_train_norm)
    eig_train_x = change_basis(x_train_norm, eigenvectors)
    eig_test_x = change_basis(x_test_norm, eigenvectors)

你可能感兴趣的:(特征脸算法)