机器学习之人脸识别-使用 scikit-learn 和人工神经网络进行高效人脸识别

文章摘要

本文将介绍如何使用 Python 的 scikit-learn 库和人工神经网络(ANN)来识别人脸。我们将使用 LFW 数据集(Labeled Faces in the Wild),这是一个广泛用于人脸识别基准测试的大型人脸数据库。我们将展示如何准备数据、构建模型,并评估模型的性能。此外,我们还会探讨一些提高模型准确率的方法。

引言

人脸识别是一项关键的技术,它在安全、监控、社交网络和移动应用等多个领域都有广泛应用。随着深度学习的发展,尤其是卷积神经网络(CNN)的进步,人脸识别的准确性已经达到了非常高的水平。然而,对于初学者而言,使用传统的机器学习方法,如人工神经网络,仍然可以达到不错的效果,并且更容易理解和实现。

基本原理

多层感知器(Multilayer Perceptron, MLP)是一种人工神经网络模型,它由一系列的层组成,包括输入层、一个或多个隐藏层以及输出层。MLP中的每个层都包含多个神经元,这些神经元之间是全连接的,即每个神经元的输出都会连接到下一层的每个神经元。

下面是一个简单的数学描述,用于解释MLP的工作原理:

前向传播

假设我们有一个具有 L L L 层的MLP,其中第 l l l层有 n l n_l nl个神经元。对于输入层 l = 1 l=1 l=1,有 n 1 n_1 n1 个输入单元;对于输出层 l = L l=L l=L,有 n L n_L nL 个输出单元。每个神经元除了接受来自上一层的输入外,还会有一个偏置项 b 。

单个神经元的计算

对于第 l l l 层中的第 j j j个神经元,其计算步骤如下:

  1. 加权求和:
    z j ( l ) = ∑ i = 1 n l − 1 w i j ( l ) a i ( l − 1 ) + b j ( l ) z^{(l)}_j = \sum_{i=1}^{n_{l-1}} w^{(l)}_{ij} a^{(l-1)}_i + b^{(l)}_j zj(l)=i=1nl1wij(l)ai(l1)+bj(l)
    其中, w i j ( l ) w^{(l)}_{ij} wij(l)是第 l l l 层中第 i i i 个神经元到第 j j j 个神经元的连接权重, a i ( l − 1 ) a^{(l-1)}_i ai(l1) 是第 l − 1 l-1 l1 层中第 i i i 个神经元的激活值, b j ( l ) b^{(l)}_j bj(l) 是第 l l l 层中第 j j j个神经元的偏置项。

  2. 激活函数:
    a j ( l ) = f ( z j ( l ) ) a^{(l)}_j = f(z^{(l)}_j) aj(l)=f(zj(l))
    其中, f ( ⋅ ) f(\cdot) f() 是激活函数,常见的激活函数有 Sigmoid 函数、ReLU 函数等。

层间传递

对于第 l l l 层,其输出 a ( l ) a^{(l)} a(l) 将作为第 l + 1 l+1 l+1 层的输入。

反向传播

反向传播算法用于计算损失函数相对于每个权重和偏置的梯度,并根据这些梯度来调整权重和偏置以最小化损失函数。

损失函数

假设我们的目标是使输出尽可能接近目标值 y y y,我们可以定义一个损失函数 E E E 来衡量这种差距。常见的损失函数有均方误差(MSE)、交叉熵损失等。

梯度计算

反向传播的关键在于使用链式法则计算损失函数关于权重和偏置的梯度。从输出层开始,逐步向前计算梯度。

  1. 输出层梯度:
    δ j ( L ) = ∂ E ∂ a j ( L ) f ′ ( z j ( L ) ) \delta^{(L)}_j = \frac{\partial E}{\partial a^{(L)}_j} f'(z^{(L)}_j) δj(L)=aj(L)Ef(zj(L))

  2. 隐藏层梯度:
    δ j ( l ) = ( ∑ k = 1 n l + 1 w k j ( l + 1 ) δ k ( l + 1 ) ) f ′ ( z j ( l ) ) \delta^{(l)}_j = \left( \sum_{k=1}^{n_{l+1}} w^{(l+1)}_{kj} \delta^{(l+1)}_k \right) f'(z^{(l)}_j) δj(l)=(k=1nl+1wkj(l+1)δk(l+1))f(zj(l))

参数更新

利用梯度下降或其变种(如动量梯度下降、Adam 等)更新权重和偏置:
w i j ( l ) ← w i j ( l ) − η ∂ E ∂ w i j ( l ) w^{(l)}_{ij} \leftarrow w^{(l)}_{ij} - \eta \frac{\partial E}{\partial w^{(l)}_{ij}} wij(l)wij(l)ηwij(l)E

b j ( l ) ← b j ( l ) − η ∂ E ∂ b j ( l ) b^{(l)}_j \leftarrow b^{(l)}_j - \eta \frac{\partial E}{\partial b^{(l)}_j} bj(l)bj(l)ηbj(l)E

其中, η \eta η 是学习率,决定了参数更新的步长。

原理小结

以上就是多层感知器的基本数学原理。通过前向传播计算网络的输出,并通过反向传播来调整网络中的权重和偏置,从而使得网络能够学习数据中的模式并进行预测。这个过程通常需要大量的训练数据以及适当的超参数设置来确保良好的性能。

步骤1: 准备环境

首先,确保您的Python环境中已经安装了scikit-learn和其他必要的库。可以通过以下命令安装:

pip install scikit-learn matplotlib

步骤2: 导入库

import numpy as np
from sklearn.datasets import fetch_lfw_people
from sklearn.model_selection import train_test_split
from sklearn.neural_network import MLPClassifier
from sklearn.metrics import classification_report, confusion_matrix
import matplotlib.pyplot as plt

步骤3: 加载数据集

# 加载LFW数据集
lfw_people = fetch_lfw_people(data_home=r"D:\\AICode\\ANN\\", download_if_missing=False, min_faces_per_person=70, resize=0.4)# 获取数据集的基本信息
n_samples, h, w = lfw_people.images.shape
X = lfw_people.data
n_features = X.shape[1]
y = lfw_people.target
target_names = lfw_people.target_names
n_classes = target_names.shape[0]# 打印数据集的一些基本信息
print("Total dataset size:")
print("n_samples: %d" % n_samples)
print("n_features: %d" % n_features)
print("n_classes: %d" % n_classes)

步骤4: 可视化数据

# 定义一个辅助函数来展示图像
def plot_gallery(images, titles, h, w, n_row=3, n_col=4):"""Helper function to plot a gallery of portraits"""plt.figure(figsize=(1.8 * n_col, 2.4 * n_row))plt.subplots_adjust(bottom=0, left=.01, right=.99, top=.90, hspace=.35)for i in range(n_row * n_col):plt.subplot(n_row, n_col, i + 1)plt.imshow(images[i].reshape((h, w)), cmap=plt.cm.gray)plt.title(titles[i], size=12)plt.xticks(())plt.yticks(())# 展示一些样本
titles = ["%s" % target_names[i].split(' ')[-1] for i in lfw_people.target[:3 * 4]]
plot_gallery(lfw_people.images, titles, h, w)plt.show()

步骤5: 数据分割

# 将数据集分为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=42)

步骤6: 构建和训练模型

# 使用MLP进行人脸识别
mlp = MLPClassifier(hidden_layer_sizes=(100,), max_iter=1000, alpha=1e-4,solver='adam', verbose=10, tol=1e-4, random_state=1,learning_rate_init=.1)mlp.fit(X_train, y_train)
print("Model trained.")

步骤7: 模型评估

# 预测测试集
y_pred = mlp.predict(X_test)# 打印分类报告
print(classification_report(y_test, y_pred, target_names=target_names,zero_division=1))# 打印混淆矩阵
cm = confusion_matrix(y_test, y_pred)
print("Confusion matrix:\n%s" % cm)

步骤8: 可视化混淆矩阵

# 显示混淆矩阵
plt.imshow(cm, interpolation='nearest', cmap=plt.cm.Blues)
plt.title("Confusion matrix")
plt.colorbar()
tick_marks = np.arange(len(target_names))
plt.xticks(tick_marks, target_names, rotation=45)
plt.yticks(tick_marks, target_names)plt.tight_layout()
plt.ylabel('True label')
plt.xlabel('Predicted label')plt.show()

解析:

  1. 加载数据集:
    • 使用fetch_lfw_people函数加载LFW数据集。
    • 我们设置min_faces_per_person=70,这意味着只保留至少有70张照片的人物。
    • 图像被缩放到resize=0.4的比例,以减少计算量。
  2. 查看数据集信息:
    • n_samples表示数据集中的人脸总数。
    • n_features是每个图像的特征数量(即像素数量)。
    • n_classes是数据集中人物的数量。
  3. 可视化:
    • plot_gallery 函数用于显示一些样本图像。
    • title 函数用于生成预测和真实标签的标题。
  4. 数据分割:
    • 使用train_test_split将数据集分割成训练集和测试集。
  5. 模型训练:
    • 使用MLPClassifier创建一个多层感知器模型。
    • 设置了隐藏层的大小、迭代次数、正则化参数等。
    • 模型使用Adam优化器。
  6. 模型评估:
    • 训练完成后,使用测试集评估模型性能。
    • 输出分类报告和混淆矩阵。
  7. 混淆矩阵可视化:
    • 使用matplotlib库来可视化混淆矩阵。

结论

通过上述步骤,我们成功地使用了scikit-learn中的MLPClassifier来构建一个人脸识别模型。模型的表现可以通过分类报告和混淆矩阵来评估。虽然使用人工神经网络进行人脸识别不是最先进的方法,但对于初学者来说,这是一个很好的起点。

进阶技巧

  • 特征提取:考虑使用PCA或LDA等降维技术来减少特征的数量,这样可以加快训练速度并且有时可以提高模型性能。
  • 超参数调整:使用网格搜索或随机搜索来寻找最优的模型参数,例如隐藏层的大小、学习率等。
  • 增强数据:通过数据增强技术(如旋转、翻转等)来增加数据集的多样性,从而提高模型的泛化能力。

代码总结

以上代码展示了如何使用scikit-learn和人工神经网络来进行人脸识别。您可以根据自己的需求调整模型参数,比如增加隐藏层的数量、改变学习率等,以获得更优的结果。

如果您想要进一步提高模型的性能,可以尝试使用更复杂的方法,例如卷积神经网络(CNN),这通常会带来显著的性能提升。不过,这对于初学者来说可能较为复杂,需要一定的深度学习背景知识。

执行效果

在这里插入图片描述
在这里插入图片描述
请添加图片描述

请添加图片描述

最后的建议

  • 持续学习:机器学习是一个快速发展的领域,保持学习的态度是非常重要的。
  • 实践项目:动手实践是最好的学习方式,尝试在不同的数据集上训练模型。
  • 社区参与:加入机器学习社区,与其他开发者交流经验和心得。

通过这篇文章,我们不仅学习了如何使用scikit-learn和人工神经网络进行人脸识别,还了解了一些提高模型性能的方法。希望这篇文章对您有所帮助!

别忘了给这篇帖子点个赞👍,如果喜欢的话,也可以收藏,关注我了解更多人工智能相关案例知识哦!😉


请记得,LFW数据集较大,下载和训练可能需要一定的时间,建议将LFW数据集下载到本地,本例中是先下载到本地的。如果您在运行代码时遇到任何问题,请随时提问!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/51150.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【微软蓝屏】构建更加稳固和安全的网络环境:从“微软蓝屏”事件谈起

最近,那个让全球都头疼的“微软蓝屏”事件,简直就像是科技界的一场大地震。你说这背后的原因,竟然是一个软件更新的小失误?哎呀,这可真是让人哭笑不得。不过,笑归笑,这事儿也给我们提了个醒&…

nodejs - express 学习笔记

express 是一个基于 Node.js 平台的极简、灵活的 WEB 应用开发框架,官方网址:https://www.expressjs. com.cn/ 简单来说,express 是一个封装好的工具包,封装了很多功能,便于我们开发 WEB 应用(HTTP 服务&am…

TiDB-从0到1-sync-diff-inspector数据校验工具

TiDB从0到1系列 TiDB-从0到1-体系结构TiDB-从0到1-分布式存储TiDB-从0到1-分布式事务TiDB-从0到1-MVCCTiDB-从0到1-部署篇TiDB-从0到1-配置篇TiDB-从0到1-集群扩缩容TiDB-从0到1-数据导出导入TiDB-从0到1-BR工具 一、sync-diff-inspector工具 sync-diff-inspector是TiDB原生…

3.仓颉编程_没有switch_case需使用match_case

仓颉编程_没有switch_case需使用match_case 支持两种 match 表达式,一种是包含待匹配值的 match 表达式,另一种是不含待匹配值的 match 表达式。 含有匹配值的 match 表达式 main() {let a Hello World!//不可变量var a2 var b 77 //可变变量match(b…

指针!!C语言(第三篇)

目录 一. 二维数组传参的本质 二. 函数指针变量和函数指针数组 三. typedef关键字 四. 转移表 五. 回调函数以及qsort使用举例 一. 二维数组传参的本质 🍟首先我们先回顾一下二维数组是怎样传参的?我们需要传入数组名以及行数和列数,这…

Dhtmlx Gantt教程:创建交互式甘特图的完整指南

在现代的项目管理中,时间是一种宝贵的资源,而甘特图则是一把解锁项目进度的魔法钥匙,想象一下,您可以在一个直观而动态的时间轴上,清晰地看到项目的每一个任务如何交织在一起,如何随着时间的推移展开&#…

LangChain4j-RAG高级-检索增强器

Retrieval Augmentor 检索增强器 RetrievalAugmentor 是 RAG 管道的入口点。它负责使用从各种来源检索的相关 Content 来扩充 ChatMessage 。 可以在创建 AiService 期间指定 RetrievalAugmentor 的实例: Assistant assistant AiServices.builder(Assistant.cla…

探索大型语言模型LLama 2:原理揭秘与代码实践

一、引言 1.1 大型语言模型的重要性 大型语言模型作为人工智能领域的重要研究方向,近年来取得了显著的成果。这些模型在自然语言处理、机器翻译、对话系统、文本生成等领域展现了强大的能力,为人类带来了诸多便利。大型语言模型的出现,使得…

初识git工具~~上传代码到gitee仓库的方法

目录 1.背景~~其安装 2.gitee介绍 2.1新建仓库 2.2进行相关配置 3.拉取仓库 4.服务器操作 4.1克隆操作 4.2查看本地仓库 4.3代码拖到本地仓库 4.4关于git三板斧介绍 4.4.1add操作 4.4.2commit操作 4.4.3push操作 5.一些其他说明 5.1.ignore说明 5.2git log命令 …

视频主题Qinmei 3.0视频站源码_WordPress影视视频主题/附详细安装教程

Qinmei 3.0主题主要是将 wordpress 改造成纯 api 的站点,以便实现前后端分离的技术栈,目前的进度已经大致完成,唯一的问题就是需要安装 JWT token 插件。 功能介绍: 支持豆瓣以及 bangumi 的一键获取信息, 豆瓣 api 目前使用的是…

【Node.js基础05】包的理解与使用

一:包的理解与简介 1 什么是包 包是一个将模块、代码、以及其他资料聚合成的文件夹 2 包的分类 项目包:编写项目代码的文件夹 软件包:封装工具和方法供开发者使用 3 为什么要在软件包中编写package.json文件 记录包的清单信息 二&…

Matlab arrayfun 与 bsxfun——提高编程效率的利器!

许多人知道 MATLAB 向量化编程,少用 for 循环 可以提高代码运行效率,但关于代码紧凑化编程, arrayfun 与 bsxfun 两个重要函数却鲜有人能够用好,今天针对这两个函数举例说明其威力。 Matlab arrayfun 概述 arrayfun 是 Matlab …

力扣SQL 最后一个能进入巴士的人 自连接

Problem: 1204. 最后一个能进入巴士的人 文章目录 思路复杂度Code 思路 👨‍🏫 参考题解 复杂度 时间复杂度: O ( ∗ ) O(*) O(∗)空间复杂度: O ( ∗ ) O(*) O(∗) Code select a.person_name from queue a,queue b where a.turn > b.turn -…

[极客大挑战 2019]PHP1

打开靶机 提示有备份,可以用工具扫描,我还没有配置好环境,搜了一下其他师傅的:备份的地址在这: /www.zip 下载后得到这几个文件: index.php就是上面打开的网页,其中有一段php代码:…

谷粒商城实战笔记-72-商品服务-API-属性分组-获取分类属性分组

文章目录 一,后端接口开发Controller层修改接口接口测试 二,前端开发 这一节的内容是开发获取分类属性分组的接口。 一,后端接口开发 Controller层修改接口 修改AttrGroupController接口。 RequestMapping("/list/{catelogId}")p…

ROS getting started

文章目录 前言一、认识ROS提供的命令行工具nodestopicsservicesparametersactionsrqt_console, rqt_graph批量启动多个节点recorde and playc基础pub-sub 1.5 ROS2和fastdds1 改变订阅模式2 xml配置3 指定xml位置4 talker/listener通过发现服务器发送topic5 ros2 检视6 远程fas…

Docker容器的数据管理

转载说明:如果您喜欢这篇文章并打算转载它,请私信作者取得授权。感谢您喜爱本文,请文明转载,谢谢。 我们在使用Docker的过程中,往往需要能查看容器内应用产生的数据,或者需要把容器内的数据进行备份&#x…

信创终端操作系统上vmware的命令行操作

原文链接:信创终端操作系统上vmware的命令行操作 Hello,大家好啊!今天给大家带来一篇关于在信创终端操作系统上使用命令行操作VMware的文章。通过命令行管理VMware虚拟机可以提高效率,特别是在需要批量操作或自动化管理时。本文将…

VS2022创建C C++ GTEST工程

原因 需要对带代码进行单元测试,选择在Visual studio 中使用GTEST 框架。 实施 创建一个常规的控制台可执行程序。然后使用NUGET安装包 安装GTEST 头文件和动态库,同时安装GTEST ADAPTER。 安装可能提示找不到包源,此时需要根据提示配置一…

如何使用API快速打造健康医疗系统?

在数字医疗市场,数据是人们经常谈及的一个话题。当前,消费者医疗和健康应用收集的数据越来越多,电子健康记录的实施也创造出了大量有关病人的电子信息。 API接口在智慧医院跨网、跨机构之间的业务协同和数据共享交换中得到数据共享。支撑了医…