【ML实验7】人脸识别综合项目(PCA、多分类SVM)

实验代码获取 github repo
山东大学机器学习课程资源索引


实验目的在这里插入图片描述

实验环境

在这里插入图片描述

实验内容

在这里插入图片描述
在这里插入图片描述

PCA

两种方法EVD-PCA和SVD-PCA的实现、效率对比见我之前的博客一个PCA加速技巧,这里补充SVD方法的数学推导

首先,设方阵 A A A的特征值分解为 A = U Σ U T A=U\Sigma U^T A=UΣUT
对于矩阵 A A A尝试构建一种分解
A = U Σ V T A=U\Sigma V^T A=UΣVT
其中 U T U = I , V T V = I U^TU=I,V^TV=I UTU=I,VTV=I
效仿特征值分解,构造方阵 A T A A^TA ATA A A T AA^T AAT
A T A = ( U Σ V T ) T U Σ V T = V Σ U T U Σ V T = V Σ 1 2 V T A^TA=(U\Sigma V^T)^TU\Sigma V^T=V\Sigma U^TU\Sigma V^T=V\Sigma_1^2V^T ATA=(UΣVT)TUΣVT=VΣUTUΣVT=VΣ12VT
这里我们得到了方阵 A T A A^TA ATA的特征值分解!因此,对 A T A A^TA ATA进行特征值分解就可以得到 V V V.
同理, A A T = U Σ 2 2 U T AA^T=U\Sigma_2^2U^T AAT=UΣ22UT,对 A A T AA^T AAT进行特征值分解就可以得到 U U U.

下面证明对角矩阵 Σ 1 \Sigma_1 Σ1 Σ 2 \Sigma_2 Σ2中的非零值相等。
设线性方程组 A x = 0 Ax=0 Ax=0,左乘 A T A^T AT A T A x = 0 A^TAx=0 ATAx=0,因此 A x = 0 Ax=0 Ax=0的解也是 A T A x = 0 A^TAx=0 ATAx=0的解。
对于 A T A x = 0 A^TAx=0 ATAx=0,左乘 x T x^T xT x T A T A x = 0 ⟹ ( A x ) T ( A x ) = 0 ⟹ A x = 0 x^TA^TAx=0\Longrightarrow(Ax)^T(Ax)=0\Longrightarrow Ax=0 xTATAx=0(Ax)T(Ax)=0Ax=0,即反过来 A T A x = 0 A^TAx=0 ATAx=0的解也是 A x = 0 Ax=0 Ax=0的解。
综上, A x = 0 Ax=0 Ax=0 A T A x = 0 A^TAx=0 ATAx=0有相同的解空间,可得 r ( A ) = r ( A T A ) r(A)=r(A^TA) r(A)=r(ATA),又有 r ( A ) = r ( A T ) r(A)=r(A^T) r(A)=r(AT),因此
r ( A A T ) = r ( A T ) = r ( A ) = r ( A T A ) r(AA^T)=r(A^T)=r(A)=r(A^TA) r(AAT)=r(AT)=r(A)=r(ATA)
即矩阵 A T A A^TA ATA A A T AA^T AAT同秩。
x x x A T A A^TA ATA对应特征值 λ \lambda λ的特征向量,所以有 A T A x = λ x A^TAx=\lambda x ATAx=λx,两边同乘 A A A,得 A A T A x = λ A x AA^TAx=\lambda Ax AATAx=λAx A A T ( A x ) = λ ( A x ) AA^T(Ax)=\lambda (Ax) AAT(Ax)=λ(Ax),因此矩阵 A T A A^TA ATA A A T AA^T AAT的非零特征值相等。

而且可以得到特征值为奇异值的平方, λ i = σ i 2 \lambda_i=\sigma_i^2 λi=σi2.

在这里插入图片描述
利用 A A T AA^T AAT的分解构建对 A T A A^TA ATA的分解
矩阵 A A A的奇异值分解为 A = U Σ V T A=U\Sigma V^T A=UΣVT,两边乘 V V V,得到 A V = U Σ AV=U\Sigma AV=UΣ,每一列有 A v i = σ i u i Av_i=\sigma_iu_i Avi=σiui,即
u i = A v i λ i u_i=\frac{Av_i}{\sqrt{\lambda_i}} ui=λi Avi
其中, v i v_i vi λ i \lambda_i λi可由对 A T A A^TA ATA的分解得到。
反之同样可行。

多分类模型

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
code

function [corrRate, misclass] = ovoMultiClassModel(trainData, testData, classNum, K, trainNum)
    fprintf('Running one vs one multiclass model...\n');
    %% Step 1: Assign label
    testNum = 10 - trainNum;
    N = classNum * (classNum - 1) / 2;
    trainPart = cell(N, 1); 
%     testPart = cell(N, 1);
    cnt = 1;
    map = zeros(N, 2);  % 第cnt个二分类器的对抗分类类别i,j
    
    for i = 1 : (classNum - 1)
        for j = (i + 1) : classNum
            trainPart{cnt, 1} = [[trainData((i - 1) * trainNum + 1 : i * trainNum, :), ones(trainNum, 1)]; ...
                [trainData((j - 1) * trainNum + 1 : j * trainNum, :), -ones(trainNum, 1)]];
%             testPart{cnt, 1} = [[testData((i - 1) * testNum + 1 : i * testNum, :), ones(testNum, 1)]; ...
%                 [testData((j - 1) * testNum + 1 : j * testNum, :), -ones(testNum, 1)]];
            map(cnt, 1) = i; map(cnt, 2) = j;
            cnt = cnt + 1;
        end
    end
%     save('trainPart.mat', 'trainPart');
    
    %% Step 2: Train SVM
    A = zeros(N, 2 * trainNum); % ? num(alpha)=2*trainNum
    W = zeros(N, size(trainData, 2));   % N×K
    B = zeros(N, 1);
    for i = 1 : N
        SVMObj = mySVM(trainPart{i, 1}(:, (1 : K)), trainPart{i, 1}(:, K + 1), 1);
        A(i, :) = SVMObj.alpha';
        W(i, :) = SVMObj.w';
        B(i) = SVMObj.b;
    end
    
    %% Step 3: Test classifying
    % SVM函数输出值
    totalTest = size(testData, 1);
    val = zeros(totalTest, N);
    for i = 1 : N
        val(:, i) = (testData * W(i, :)')' + B(i);
        % (?×1)=((?×K)*(1×K)')'+(?×1),其中?为测试数据个数(totalTest)
    end
    % 第i类别参与(40×39/2)个二分类SVM中的39个
    part = zeros(classNum, classNum - 1);
    for i = 1 : classNum
        part(i, :) = find(map(:, 1) == i | map(:, 2) == i);
    end
    % f(x)=arg max_{s}∑_{t}f_{s,t}(x)
    %% A. 一对一SVM分类器结果
    res = zeros(totalTest, 1);
    for i = 1 : totalTest    % 对所有测试数据
        voteCnt = zeros(classNum, 1);
        for j = 1 : classNum    % 对所有可能分类
            for k = 1 : classNum - 1
                if val(i, part(j, k)) > 0 && map(part(j, k), 1) == j
                    voteCnt(j) = voteCnt(j) + 1;
                elseif val(i, part(j, k)) < 0 && map(part(j, k), 2) == j
                    voteCnt(j) = voteCnt(j) + 1;
                end
            end
        end
        [~, maxOne] = max(voteCnt);
        res(i) = maxOne;
    end
    %% B. 标准结果
    std = zeros(totalTest, 1);
    for i = 1 : classNum
        std((i - 1) * testNum + 1 : i * testNum) = i;
    end
    %% C. 对比统计
    corrSet = find(res == std);
    corrRate = length(corrSet) / totalTest;
    misclass = cell(1, 1);
    misclass{1} = [std, res];
    fprintf('one vs one multiclass done\n');
end

SVM训练器

在这里插入图片描述
code

function SVMObj = mySVM(x, y, C)
    m = size(x, 1);
    % !err:length=max(size(X)),返回数组最大维度长度
    
    options = optimset;
    options.largeScale = 'off';
    options.Display = 'off';
    
    %% A. 构建目标函数
    H = zeros(m);
    for i = 1 : m
        for j = 1 : m
            H(i, j) = y(i) * y (j) * x(i, :) * x(j, :)';
        end
    end
    f = (-1) * ones(m, 1);
    
    %% B. 构建约束
    Aeq = y';
    beq = 0;
    lb = zeros(m, 1);
    ub = zeros(m, 1);
    ub(:) = C;
    a0 = zeros(m, 1);   % 迭代初始值
    
    %% C. 利用quadprog求解器求解对偶问题
    % quadprog(H,f,A,b,Aeq,beq,lb,ub)
    [alpha, fval] = quadprog(H, f, [], [], Aeq, beq, lb, ub, a0, options);
    
    %% D. 求support vector
    alpha(find(alpha < 1e-8)) = 0;
    sv = find(alpha > 0 & alpha < C);
    w = 0;  % omega
    for i = 1 : length(sv)
        w = w + alpha(sv(i)) * y(sv(i)) * x (sv(i), :)';
    end
    num = y - x * w;
    b = sum(num(sv)) / length(sv);
    
    %% 构建返回对象SVMObj
    SVMObj.alpha = alpha;   % alpha(sv)
    SVMObj.w = w;
    SVMObj.b = b;
end

实验结果

在这里插入图片描述
在这里插入图片描述

conclusion

在这里插入图片描述

在使用OpenCV(计算机视觉库)和SVM(支持向量机)进行人脸识别时,通常需要经过以下几个步骤: 1. **数据采集**:首先,你需要收集人脸图像作为训练样本,并对每个人脸进行标记,以便于后续的特征提取。 2. **预处理**:对图片进行灰度化、缩放、归一化等操作,使得所有输入数据在相似的尺度下。 3. **人脸检测**:使用OpenCV的人脸检测算法,如Haar级联分类器,定位出图片中的人脸区域。 4. **特征提取**:从人脸区域提取关键特征,常用的是PCA(主成分分析)或者LBP(局部二值模式),也可以使用OpenCV自带的特征描述符如LBPH或EigenFace。 5. **训练**:将提取的特征和对应的标签(即人名或ID)作为输入,训练SVM模型。OpenCV的`cv2.ml.SVM`模块可以用于此目的。 6. **测试与识别**:对于新的图片,应用相同的预处理和人脸检测步骤,然后使用训练好的SVM模型对检测到的人脸进行识别,返回最匹配的人脸类别。 下面是一个简单的Python示例(注意这是简化的版本,实际应用中可能需要更复杂的错误处理和优化): ```python import cv2 from sklearn import svm # 加载训练数据和对应标签 faces = [] labels = [] # 假设已经准备好了标注好的人脸特征和名字列表 for i in range(len(labels)): img_path = "path/to/images/" + labels[i] + ".jpg" face = cv2.imread(img_path) faces.append(face) labels.append(i) # 提取特征并转化为数组 features = [face.reshape(1, -1) for face in faces] labels = np.array(labels) # 训练SVM clf = svm.SVC() clf.fit(features, labels) # 测试新图片 test_img = cv2.imread("path/to/test/image.jpg") gray_img = cv2.cvtColor(test_img, cv2.COLOR_BGR2GRAY) face_roi = detect_face(gray_img) # 自己实现的人脸检测函数 if face_roi is not None: test_feature = extract_features(face_roi) prediction = clf.predict([test_feature]) print(f"识别的人脸属于类别: {prediction[0]}") else: print("未检测到人脸") ```
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

u小鬼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值