机器学习——SVM(支持向量机)与人脸识别

2023-11-01

    忆如完整项目/代码详见github:https://github.com/yiru1225(转载标明出处 勿白嫖 star for projects thanks)

目录

系列文章目录

一、SVM的概念与原理

1.SVM简介

2.SVM基本流程

3.SVM在多分类中的推广

二、经典SVM运用于图像识别分类

三、SVM运用于人脸识别

1.预处理

1.1 数据导入与处理

1.2 数据降维

2.人脸识别

2.1 OVO实现SVM

2.2 OVR实现SVM

3.PCA与LDA分别结合SVM在各维度、各数据集的人脸识别率及其与KNN的对比

3.1 ORL下比较SVM与KNN对于PCA和LDA的人脸识别率随维度的改变

3.2  各种方法在不同数据集下的平均人脸识别率

4.OVO与OVR实现SVM的人脸识别率比较

4.1 ORL下比较OVO与OVR实现SVM + PCA的人脸识别率随维度的改变                      

4.2 OVO与OVR实现SVM + PCA在不同数据集下的平均人脸识别率           

四、创新SVM算法设计

五、其他

1. 数据集及资源

2. 参考资料

总结


系列文章目录

本系列博客重点在机器学习的概念原理与代码实践,不包含繁琐的数学推导(有问题欢迎在评论区讨论指出,或直接私信联系我)。

代码可以全抄    大家搞懂原理与流程去复现才是有意义的!!!

第一章 机器学习——PCA(主成分分析)与人脸识别_@李忆如的博客-CSDN博客

第二章 机器学习——LDA (线性判别分析) 与人脸识别_@李忆如的博客-CSDN博客

第三章 机器学习——LR(线性回归)、LRC(线性回归分类)与人脸识别_@李忆如的博客​​​​​

第四章 机器学习——SVM(支持向量机)与人脸识别


梗概

本篇博客主要介绍SVM(支持向量机)算法,利用经典SVM实现图像识别二分类,并将SVM(OVO与OVR均实现)+ 降维方法(PCA与LDA)用于人脸识别,并将SVM与KNN进行比较,OVO与OVR进行比较(内附数据集与matlab、python代码)


一、SVM的概念与原理

1.SVM简介

支持向量机(SVM)是在分类与回归中分析数据的有监督学习模型与相关的学习算法。本质上是一种二分类模型,它的经典模型是定义在特征空间的间隔最大的线性分类器,学习策略是间隔最大化

2.SVM基本流程

SVM模型将实例表示为空间(超平面、超空间)中的点,这样映射就使得单独类别的实例被尽可能宽的明显的间隔分开。然后,将新的实例映射到同一空间,并基于它们落在间隔的哪一侧来预测所属类别。

3.SVM在多分类中的推广

由于SVM是一种二分类器,即用一条线或一个平面分开两类不同数据,一般用如下两个方法使其推广到多分类。

① OVR:对于K个类别的情况,训练K个SVM,第j个SVM用于判断任意条数据是属于类别j还是类别非j。预测的时候,具有距超空间i最大值的表示给定的数据x属于类别i。

② OVO:对于K个类别的情况,训练K*(K-1)/2个SVM,每一个SVM只用于判断任意条数据是属于K中的特定两个类别。预测的时候,使用K*(K-1)/2个SVM做K*(K-1)/2次预测,使用计票的方式决定数据被分类为哪个类别的次数最多,就认为数据x属于此类别。

Tips:SVM详细推导可见:svm原理详细推导_weixin_42001089的博客-CSDN博客_svm推导

二、经典SVM运用于图像识别分类

① 问题描述:识别图片属于森林还是房间

② 算法实现核心:使用mapminmax实现划分后的数据集归一化,利用函数fitcsvm训练归一化后训练集,通过求解二次规划与准备参数,得到a并找到支持向量,predict用刚刚训练出的模型预测,求b得到f(x)与预测类别。

③ 代码如下:

clear;
% dataset是将bedroom和forest合并;dataset = [bedroom;forset];这行代码可以实现合并
load forest.mat                  %导入要分类的数据集
load bedroom.mat
dataset = [bedroom;MITforest];
load labelset.mat                %导入分类集标签集

% 选定训练集和测试集

% 将第一类的1-5,第二类的11-15做为训练集
train_set = [dataset(1:5,:);dataset(11:15,:)];
% 相应的训练集的标签也要分离出来
train_set_labels = [lableset(1:5);lableset(11:15)];
% 将第一类的6-10,第二类的16-20,做为测试集
test_set = [dataset(6:10,:);dataset(16:20,:)];
% 相应的测试集的标签也要分离出来
test_set_labels = [lableset(6:10);lableset(16:20)];
 
% 数据预处理,将训练集和测试集归一化到[0,1]区间
 
[mtrain,ntrain] = size(train_set);
[mtest,ntest] = size(test_set);
 
test_dataset = [train_set;test_set];
% mapminmax为MATLAB自带的归一化函数
[dataset_scale,ps] = mapminmax(test_dataset',0,1);
dataset_scale = dataset_scale';
 
train_set = dataset_scale(1:mtrain,:);
test_set = dataset_scale( (mtrain+1):(mtrain+mtest),: );
 
% SVM网络训练
model = fitcsvm(train_set,train_set_labels);
 
% SVM网络预测
[predict_label] = predict(model,test_set);
%[predict_label] = model.IsSupportVector;

 
% 结果分析
 
% 测试集的实际分类和预测分类图
% 通过图可以看出只有一个测试样本是被错分的
figure;
hold on;
plot(test_set_labels,'o');
plot(predict_label,'r*');
xlabel('测试集样本','FontSize',12);
ylabel('类别标签','FontSize',12);
legend('实际测试集分类','预测测试集分类');
title('测试集的实际分类和预测分类图','FontSize',12);
grid on;

④ 识别效果如下:

 分析:分析上图可知,预测分类与实际分类均相等,预测效果很好。

三、SVM运用于人脸识别

1.预处理

1.1 数据导入与处理

利用imread批量导入人脸数据库,或直接load相应mat文件,并在导入时不断将人脸拉成一个个列向量组成reshaped_faces,并取出n%作为测试数据,剩下100-n%作为训练数据,重复此步骤,将导入数据抽象成框架,可以匹配不同数据集的导入(本实验框架适配ORL、AR、FERET数据集)。

Tips:代码可见本系列第二篇文章(LDA与人脸识别),基本一致。

1.2 数据降维

使用LDA或PCA对数据降维(具体原理与详细代码见本系列一二篇文章)

% LDA
% 算每个类的平均
k = 1; 
class_mean = zeros(dimension, people_num); 
for i=1:people_num
    % 求一列(即一个人)的均值
    temp = class_mean(:,i);
    % 遍历每个人的train_pic_num_of_each张用于训练的脸,相加算平均
    for j=1:train_pic_num_of_each
        temp = temp + train_data(:,k);
        k = k + 1;
    end
    class_mean(:,i) = temp / train_pic_num_of_each;
end

% 算类类间散度矩阵Sb
Sb = zeros(dimension, dimension);
all_mean = mean(train_data, 2); % 全部的平均
for i=1:people_num
    % 以每个人的平均脸进行计算,这里减去所有平均,中心化
    centered_data = class_mean(:,i) - all_mean;
    Sb = Sb + centered_data * centered_data';
end
Sb = Sb / people_num;

% 算类内散度矩阵Sw
Sw = zeros(dimension, dimension);
k = 1; % p表示每一张图片
for i=1:people_num % 遍历每一个人
    for j=1:train_pic_num_of_each % 遍历一个人的所有脸计算后相加
        centered_data = train_data(:,k) - class_mean(:,i);
        Sw = Sw + centered_data * centered_data';
        k = k + 1;
    end
end
Sw = Sw / (people_num * train_pic_num_of_each);

% 目标函数一:经典LDA(伪逆矩阵代替逆矩阵防止奇异值)
% target = pinv(Sw) * Sb;

% PCA
centered_face = (train_data - all_mean);
cov_matrix = centered_face * centered_face';
target = cov_matrix;

% 求特征值、特征向量
[eigen_vectors, dianogol_matrix] = eig(target);
eigen_values = diag(dianogol_matrix);

% 对特征值、特征向量进行排序
[sorted_eigen_values, index] = sort(eigen_values, 'descend'); 
eigen_vectors = eigen_vectors(:, index);
eigen_vectors = real(eigen_vectors); % 处理复数,会导致一定误差(LDA用)

2.人脸识别

实现核心流程:使用PCA/LDA先对数据进行预处理与降维,SVM使用OVO/OVR对划分好的数据集进行模型训练与测试集预测,最终记录识别率并与比较。

2.1 OVO实现SVM

%使用SVM人脸识别
    % SVM(OVO)
rate = []; %用于记录人脸识别率
for i=10:10:160
    right_num = 0;
    % 降维得到投影矩阵
    project_matrix = eigen_vectors(:,1:i);
    projected_train_data = project_matrix' * (train_data - all_mean);
    projected_test_data = project_matrix' * (test_data - all_mean);

    % SVM训练过程
           model_num = 1;
       for j = 0:1:people_num - 2
         train_img1 = projected_train_data(:,j * train_pic_num_of_each + 1 : j * train_pic_num_of_each + train_pic_num_of_each); % 取出每次SVM需要的训练集
         train_label1 = ones(1,train_pic_num_of_each)*(j + 1); % 给定训练标签
         test_img1 = projected_test_data(:,j * test_pic_num_of_each + 1 : j * test_pic_num_of_each + test_pic_num_of_each); % 取出每次SVM需要的测试集
         for z = j + 1:1:people_num - 1
         train_img2 = projected_train_data(:,z * train_pic_num_of_each + 1 : z * train_pic_num_of_each + train_pic_num_of_each); % 取出每次SVM需要的训练集
         train_label2 = ones(1,train_pic_num_of_each)*(z + 1); % 给定训练标签
         train_imgs = [train_img1,train_img2];
         train_label = [train_label1,train_label2];
         
         test_img2 = projected_test_data(:,z * test_pic_num_of_each + 1 : z * test_pic_num_of_each + test_pic_num_of_each); % 取出每次SVM需要的测试集
         test_imgs = [test_img1,test_img2];
         
          % 数据预处理,将训练集和测试集归一化到[0,1]区间 
        [mtrain,ntrain] = size(train_imgs); %m为行数,n为列数
        [mtest,ntest] = size(test_imgs);
 
        test_dataset = [train_imgs,test_imgs];
        % mapminmax为MATLAB自带的归一化函数
        [dataset_scale,ps] = mapminmax(test_dataset,0,1);
 
        train_imgs = dataset_scale(:,1:ntrain);
        test_imgs = dataset_scale( :,(ntrain+1):(ntrain+ntest) );
 
        % SVM网络训练
        train_imgs = train_imgs';
        train_label = train_label';
        expr = ['model_' num2str(model_num) ' = fitcsvm(train_imgs,train_label);']; % fitcsvm默认读取数据为按行,一张一脸为一列,需要转置
        eval(expr);
        model_num = model_num + 1;
         end
       end
       model_num = model_num - 1;
       
       % 人脸识别
       test = []; % 测试用
    for k = 1:1:test_pic_num_of_each * people_num
        test_img = projected_test_data(:,k); % 取出待识别图像
        test_real_label = fix((k - 1) / test_pic_num_of_each) + 1; % 给定待测试真实标签
        predict_labels = zeros(1,people_num); %用于OVO后续投票
      
       % SVM网络预测
       for t = 1:1:model_num
       predict_label = predict(eval(['model_' num2str(t)]),test_img');
       % test = [test,predict_label]; % 测试用
       predict_labels(1,predict_label) = predict_labels(1,predict_label) + 1;
       end
         [max_value,index] = max(predict_labels);
       if(index == test_real_label)
           right_num = right_num + 1;   
       end
    end
       
       recognition_rate = right_num / (test_pic_num_of_each * people_num); 
       rate = [rate,recognition_rate];
end    

2.2 OVR实现SVM

           % SVM(OVR)
rate = []; %用于记录人脸识别率
for i = 10:10:160
        right_num = 0;
    % 降维得到投影矩阵
    project_matrix = eigen_vectors(:,1:i);
    projected_train_data = project_matrix' * (train_data - all_mean);
    projected_test_data = project_matrix' * (test_data - all_mean);
         model_num = 1;
             % SVM训练过程(每次训练都要使用整个数据集)
         for j = 0:1:people_num - 1
         
         train_imgs = circshift(projected_train_data,-j * train_pic_num_of_each ,2); %使训练集始终在前几行
         train_label1 = ones(1,train_pic_num_of_each) * (j + 1);
         train_label2 = zeros(1,train_pic_num_of_each * (people_num - 1));
         train_label = [train_label1,train_label2];
         
         test_imgs = circshift(projected_test_data,-j * test_pic_num_of_each ,2); %使测试集始终在前几行

        % 数据预处理,将训练集和测试集归一化到[0,1]区间 
        [mtrain,ntrain] = size(train_imgs); %m为行数,n为列数
        [mtest,ntest] = size(test_imgs);
 
        test_dataset = [train_imgs,test_imgs];
        % mapminmax为MATLAB自带的归一化函数
        [dataset_scale,ps] = mapminmax(test_dataset,0,1);

        train_imgs = dataset_scale(:,1:ntrain);
        test_imgs = dataset_scale( :,(ntrain+1):(ntrain+ntest) );
 
        % SVM网络训练
        train_imgs = train_imgs';
        train_label = train_label';
        expr = ['model_' num2str(model_num) ' = fitcsvm(train_imgs,train_label);']; % fitcsvm默认读取数据为按行,一张一脸为一列,需要转置
        eval(expr);
        model_num = model_num + 1;
         end
        model_num = model_num - 1;
         % 人脸识别
       for k = 1:1:test_pic_num_of_each * people_num
        test_img = projected_test_data(:,k); % 取出待识别图像
        test_real_label = fix((k - 1) / test_pic_num_of_each) + 1; % 给定待测试真实标签
        predict_labels = zeros(1,people_num); %用于OVR预测
      
       % SVM网络预测
       for t = 1:1:model_num
       [predict_label,possibility] = predict(eval(['model_' num2str(t)]),test_img');
       if predict_label ~= 0
       predict_labels(1,predict_label) = predict_labels(1,predict_label) + possibility(1,1); 
       end
       end
         [min_value,index] = min(predict_labels); % 若一张图片被预测为多类,选择离超平面最远的作为最终预测类
       if(index == test_real_label)
           right_num = right_num + 1;   
       end
       end
       recognition_rate = right_num / (test_pic_num_of_each * people_num); 
       rate = [rate,recognition_rate];
        
end

3.PCA与LDA分别结合SVM在各维度、各数据集的人脸识别率及其与KNN的对比

运行SVM.m,比较在ORL(或其他数据集下)SVM(OVO实现为例)+降维方法与KNN+降维方法的人脸识别率随维度的变化,并在多个数据集下比较不同方法的人脸识别率,结果与分析如下:

3.1 ORL下比较SVM与KNN对于PCA和LDA的人脸识别率随维度的改变

3.2  各种方法在不同数据集下的平均人脸识别率

 Tips:数据集后为训练集与测试集的划分比

分析:分析以上两组图可知,各方法的人脸识别率与维度、数据集、参数选择均存在巨大关系,并没有某种方法组合在所有维度所有数据集下均具有优越性。

4.OVO与OVR实现SVM的人脸识别率比较

分别用OVO与OVR的思想训练SVM不同分类器并应用于人脸识别,在不同维度、不同数据集下的人脸识别率如下:

4.1 ORL下比较OVO与OVR实现SVM + PCA的人脸识别率随维度的改变                      

4.2 OVO与OVR实现SVM + PCA在不同数据集下的平均人脸识别率           

分析:分析以上两组图可知,OVR实现SVM时在低维度时识别率低于OVO实现SVM,随着维度增加,OVR的识别率逐渐稳定地优于OVO,且在实验的三个数据集中,OVR的平均识别率均高于OVO。另外,OVR训练的分类器数量少,在小数据集下效率更高,但随着数据规模增大,OVR每次训练数据过大,效率会逐渐低于OVO。 

5.方法与函数的补充

对于多分类SVM,matlab可以使用fitcecoc函数,python可以使用svm.SVC搭配fit与predict直接实现多分类SVM,而不需要多次训练二分类SVM。

四、创新SVM算法设计

① 经典SVM不足:无法处理非线性数据,对大规模训练样本难以实施。

已有改进:软间隔SVM/SVM/ CSVM

③ 创新SVM算法简述:

(1)SMO后通过对核函数的缓存可以大大增加算法效率。因为在经典SVM中,空间消耗主要在模型的训练,时间消耗主要在各种核函数与其他模型、函数的调用。

(2)对于最优化问题中f(x)的计算需要不断循环,代价很高,在此定义并缓存一个g(x)如下,让我们可以随时计算误差:

3)优化数据集划分,实现冷热数据分离。热数据在前(大于0小于Calpha值),冷数据在后(小于等于0 或者大于等于 C alpha)在后。随着迭代加深,大部分时候只需要在热数据里求解,并且热数据的大小会逐步不停的收缩,所以区分了冷热以后SVM 大部分都在针对有限的热数据迭代。

4)传入外部分类“权重”修正结果,提高识别率。用原始的 C 乘以各自分类的权重,得到 Cp Cn,然后迭代时,不同的样本根据它的 y 值符号,用不同的 C 值带入计算。

(5)同时支持稀疏和非稀疏,针对不同数据,选择合适的方式求解。

五、其他

1. 数据集及资源

本实验所用数据集:ORL5646、AR5040、FERET_80,代码框架可适用多个数据集。

常用人脸数据集如下(不要白嫖哈哈哈)

链接:https://pan.baidu.com/s/12Le0mKEquGMgh5fhNagZGw 
提取码:yrnb

SVM完整代码与二分类所需数据集:李忆如/忆如的机器学习 - Gitee.com

2. 参考资料

1.支持向量机(SVM)的推导(线性SVM、软间隔SVM、Kernel Trick) - liuyang0 - 博客园 

2.手撕SVM公式——硬间隔、软间隔、核技巧_Dominic_S的博客-CSDN博客_硬间隔

3.手写SVM算法(Matlab实现) - 知乎 (zhihu.com)

4.SVM支持向量机+实例展示_Snippers的博客-CSDN博客_svm支持向量机

5.周志华《机器学习》


总结

SVM作为经典的线性二分类器,通过”最大化间隔“为目标导向对数据进行超空间(平面)投影并划分。如今仍然在机器学习许多领域(数据分类、语言图像处理、推荐系统)有优异表现。且作为一种有监督学习方法(利用了数据的原有信息),SVM能得到较好的保留数据信息。但SVM仍存在处理高维数据大计算代价问题、不好刻画非线性问题等等,另外,SVM假设的数据属性在现实世界的问题中往往难以达到,从而影响实验结果,后续博客会分析其他算法优化或解决上述问题。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

机器学习——SVM(支持向量机)与人脸识别 的相关文章

随机推荐

  • JVM--基础--27.4--工具--MemoryAnalyzer--介绍、安装

    JVM 基础 27 4 工具 MemoryAnalyzer 介绍 安装 1 介绍 Memory Analyzer 是一个跨平台的开源工具 可以用它来分析内存问题 可以用来监控整个 Java 应用程序的状态和行为 1 1 我使用Memory
  • Java:Map转List (用stream实现)

    例子 Map
  • Swift学习之 - 访问控制权限(fileprivate,private,internal,public,open)

    先来看下小白的错误代码 import UIKit class ViewController UIViewController override func viewDidLoad super viewDidLoad text extensio
  • 批量修改文件名 最简单的实现python os

    import os def name file dir r C Users Administrator Desktop 车牌 a os listdir file dir for i in a os rename i i png i为原名 p
  • 算法训练营第二十二天(8.4)

    LeeCode77 Combinations 题目地址 力扣 题目类型 回溯 组合 不用排序 class Solution private vector
  • Acwing-877. 扩展欧几里得算法

    include
  • 国家地区语言缩写码

    国家地区语言缩写码 语言 国家 地区 语言代码 国家 地区 语言代码 简体中文 中国 zh cn 繁体中文 台湾地区 zh tw 繁体中文 香港 zh hk 英语 香港 en hk 英语 美国 en us 英语 英国 en gb 英语 全球
  • 宝塔一键配置https

    下面是宝塔的说明 注意Apache的坑 证书文件目录 大部分免费证书 指阿里 腾讯申请的 都会有以下四个文件夹 面板只需要用到nginx或apache的 其他无需理会 Nginx环境配置证书方法 证书目录只有两个文件的 进入nginx 证书
  • 【技术分享】Lombok!代码简洁神器还是代码“亚健康”元凶?

    如果您正在阅读此文 想必您对Project Lombok已经有了一段时间的了解 您是否正准备拥抱Lombok 还是正准备将如此酷炫的项目推荐给你的团队 如果您准备那么做 不妨听听我在使用Lombok一年后的一些感受 我承认 Lombok是一
  • # C++网络请求(get,post,上传图片)与QML混合编程

    C 网络请求 get post 上传图片 与QML混合编程 文章主要分两个大模块 C 模块和qml模块 包含了Qt下网络请求QNetworkAccessManager QNetworkRequest QNetworkReply类库 以及响应
  • vue中实现锚点定位平滑滚动

    下面是简单的代码 拿来即用 html 给div盒子设定单击事件和ref名 div 点击滑动到此位置 div methods getThere 通过ref名获取元素在页面中的位置并滚动至此 this el querySelector cat
  • Unity3D中打包WEBGL后读取本地文件数据+网络请求

    PS 博主在上编文章中写道webgl读取本地文件数据以及内部网络请求 在这里详细补充一下 首先上一编博主运行html之后报的错误 提示内存不足 1 首先排查一下webgl包的大小 不能超过2G 2 F12查看具体错误 在这里博主的是 a 本
  • AWS Kubernetes Ingress nginx websocket 代理

    在需要配置WebSocket的Ingress服务上增加下面注解 metadata annotations nginx org websocket services SERVICE NAME WebSocket 测试 ws test yaml
  • JSON 按key的字符先后顺序排序

    话不多说直接上方法 var sortJson function obj callback var endValue item key keyArray keyArray2 o i len endValue keyArray keyArray
  • 一元线性回归分析的残差诊断

    1973年安斯库姆 Anscombe 构造了四组数据 用这四组数据得到的经验回归方程是相同的 都是y 3 00 0 500x 决定系数都是 r2 0 667 相关系数r 0 816 这四组数据所建的回归方程是相同的 决定系数r2 F统计量也
  • uboot中printf( )函数实现分析

    1 前言 这部分涉及uboot中串口的初始化 参考博客 uboot中串口 控制台 初始化详解 2 printf 函数实现思路分析 1 uboot中的printf 函数的用法和利用C库编写C语言程序时是一样的 本身uboot中printf 函
  • linux中的/etc/hosts.allow和/etc/hosts.deny详解

    linux中的 etc hosts allow和 etc hosts deny详解 当linux主机需要允许 禁止某些ip地址 地址段访问某些资源或服务时 etc hosts allow和 etc hosts deny就派上了用场 两个文件
  • tcp_transmit_skb的发送时机梳理

    在上文数据通过网络发送的过程中 当程序调用tcp sendmsg发送数据的时候有可能当前的数据不会马上发送出去 当前在哪些场景下会触发数据的发送呢 检查mtu 创建 一个新的路径MTU 发现段 未启用路径MTU 当前路径MTU探测段的长度不
  • Andriod期末复习总结

    一 安卓项目的目录结构 AndroidManifest xml 项目清单文件 设置应用名称 图标等属性 libs 项目依赖的外部库 src Java源文件 bin 目标文件 Java字节码 class 资源打包文件 ap 和Dalvik虚拟
  • 机器学习——SVM(支持向量机)与人脸识别

    忆如完整项目 代码详见github https github com yiru1225 转载标明出处 勿白嫖 star for projects thanks 目录 系列文章目录 一 SVM的概念与原理 1 SVM简介 2 SVM基本流程