facenet 人脸识别原理理解(三)

article/2025/9/30 13:29:46

在前两篇文章已经介绍了facenet人脸识别代码的使用和具体操作,但相关的原理还是没有说,这篇文章进行简单的讲解一下。

1. 原理

在人脸识别中,当我们需要加在图片数据库入新的一张人脸图片时,是怎么做到识别的呢,难道要我们重新修改网络最后的输出函数softmax,添加一个输出,然后再重新训练整个网络?这是不现实的吧!

那我们要怎么做呢?更多的做法是采用欧氏距离D来衡量这两张图片的差距,进行判别是否属于同一个人。如果两张人脸图片越相似,空间距离D越小;差别越大,则空间距离D越大。 

我们要设置一个阈值τ,距离小于τ时属于同一个人脸,距离大于τ时就判断为不同的人脸。

2. 网络结构

下面我从facenet的网络结构说起。

 

从网络中可以看到Batch之后是Deep architeture(Inception ResNet v1),再到L2范数,然后就是嵌入层(embedding),最后就是三元组损失了。

L2:在L2范数前要进行归一化,要不然数值太大了!

EMBEDDING: 嵌入层,是一种映射关系,从一种特征空间映射到另外一种特征空间。

Triplet Loss:三元组损失。三元组由Anchor(A), Negative(N), Positive(P)这三个组成,从字面意思我们就可以猜想,我们想让Anchor和Positive尽量的靠近(Positive意味这同一个人),Anchor和Negative尽量的远离(Negative表示不同的人)。

 

但我们在训练之前,会有 Anchor和Negative离得近,Anchor和Positive离得远的情况,如左边的图片一样。经过学习之后转变为右边我们想要的效果:Anchor与Negative离得远,与Positive离得近。

 

3. Triplet Loss损失函数

我们想让它小于等f(A)到f(P)之间的距离小于f(A)到f(P)的距离,或者说是比较它们的范数的平方,得到下式子。

其中a是一个常数,防止把所有的东西都学成 0,如果f总是输出 0,即 0-0 < 0,这种情况。同时a代表着间隔距离,它拉大了 Anchor 和 Positive 图片对和 Anchor 与 Negative 图片对之间的差距。看代码中常默认为0.2

总的损失函数:

左边为同类距离 ,右边为不同的类之间的距离。使用梯度下降法优化的过程就是让类内距离不断下降,类间距离不断提升,这样损失函数才能不断地缩小。但为了防止loss小于0,通过代码里面我们可以看到会和0比较一下。

def triplet_loss(anchor, positive, negative, alpha):"""Calculate the triplet loss according to the FaceNet paperArgs:anchor: the embeddings for the anchor images.positive: the embeddings for the positive images.negative: the embeddings for the negative images.Returns:the triplet loss according to the FaceNet paper as a float tensor."""with tf.variable_scope('triplet_loss'):pos_dist = tf.reduce_sum(tf.square(tf.subtract(anchor, positive)), 1)neg_dist = tf.reduce_sum(tf.square(tf.subtract(anchor, negative)), 1)basic_loss = tf.add(tf.subtract(pos_dist,neg_dist), alpha)loss = tf.reduce_mean(tf.maximum(basic_loss, 0.0), 0)return loss
  • center_loss损失函数

关于损失函数,除了上面的triplet_loss函数外,其实facenet.py文件里面代码还有一个center_loss损失函数,这是Deep Face 使用的方法。它会在某一个类中找到一个center,让这类所有样本的特征到中心的距离最短,让同一类别更加紧凑一些。

def center_loss(features, label, alfa, nrof_classes):"""Center loss based on the paper "A Discriminative Feature Learning Approach for Deep Face Recognition"(http://ydwen.github.io/papers/WenECCV16.pdf)"""nrof_features = features.get_shape()[1]centers = tf.get_variable('centers', [nrof_classes, nrof_features], dtype=tf.float32,initializer=tf.constant_initializer(0), trainable=False)label = tf.reshape(label, [-1])centers_batch = tf.gather(centers, label)diff = (1 - alfa) * (centers_batch - features)centers = tf.scatter_sub(centers, label, diff)with tf.control_dependencies([centers]):loss = tf.reduce_mean(tf.square(features - centers_batch))return loss, centers

 

4. Training 训练

4.1 Triplet Selection

关于如何选择这些三元组来形成训练集,随机地选择A、 P和N,遵守A和P是同一个人,而A和N是不同的人这一原则。有个问题就是:如果随机的选择它们,那么这个约束条件(d(A, P) + a ≤ d(A, N))很容易达到,因为随机选择的图片,A和N比A和P差别很大的概率很大。这样网络就很难学到东西,稳健性就很差了。引用吴恩达老师Deep learning 课程中的一段话:

那我们要做的就是尽可能选择难训练的三元组A、P和N。难训练的三元组就是,你的A、P和N的选择使得d(A, P)很接近d(A, N),即d(A, P) ≈ d(A, N),这样你的学习算法会竭尽全力使右边这个式子变大(d(A, N)),或者使左边这个式子(d(A, P))变小,这样左右两边至少有一个a的间隔。

 

 同样在facenet论文中我们也可以看到,我们要选择最远的相同人脸\LARGE x_{i}^{p}(hard positive)和最近的不同人脸\LARGE x_{i}^{n}(hard negative)来训练,如上图所示。 

4.2 Classifier

我们在生成 .pkl 文件的时候用到calssifier.py 文件,里面用SVM来训练一个分类器。整体流程大致是:CNN forward 输出后经L2传入Embedding层,得到embedding ouput的特征进行传给SVM classifier来训练一个分类器。然后把训练好的分类器保存为pickle文件。在执行指令读取分类器的时候加载SVM分类器模型,自己所用的测试图片数据就会SVM分类器模型中的类别做对比判断。.pkl文件保存的参数包括模型(model)和类别(class_names),我们是可以直接读出来的。

代码里面SVM有两种模式:TRAIN (用来训练SVM模型);CLASSIFY  (用来加载SVM模型)。看代码会有更好的理解:

# Run forward pass to calculate embeddingsprint('Calculating features for images')nrof_images = len(paths)nrof_batches_per_epoch = int(math.ceil(1.0*nrof_images / args.batch_size))emb_array = np.zeros((nrof_images, embedding_size))for i in range(nrof_batches_per_epoch):start_index = i*args.batch_sizeend_index = min((i+1)*args.batch_size, nrof_images)paths_batch = paths[start_index:end_index]images = facenet.load_data(paths_batch, False, False, args.image_size)feed_dict = { images_placeholder:images, phase_train_placeholder:False }emb_array[start_index:end_index,:] = sess.run(embeddings, feed_dict=feed_dict)classifier_filename_exp = os.path.expanduser(args.classifier_filename)if (args.mode=='TRAIN'):# Train classifierprint('Training classifier')model = SVC(kernel='linear', probability=True)      # use SVM classifiermodel.fit(emb_array, labels)# Create a list of class namesclass_names = [ cls.name.replace('_', ' ') for cls in dataset]# Saving classifier modelwith open(classifier_filename_exp, 'wb') as outfile:pickle.dump((model, class_names), outfile)print('Saved classifier model to file "%s"' % classifier_filename_exp)elif (args.mode=='CLASSIFY'):# Classify imagesprint('Testing classifier')with open(classifier_filename_exp, 'rb') as infile:(model, class_names) = pickle.load(infile)print('Loaded classifier model from file "%s"' % classifier_filename_exp)predictions = model.predict_proba(emb_array)best_class_indices = np.argmax(predictions, axis=1)best_class_probabilities = predictions[np.arange(len(best_class_indices)), best_class_indices]for i in range(len(best_class_indices)):print('%4d  %s: %.3f' % (i, class_names[best_class_indices[i]], best_class_probabilities[i]))accuracy = np.mean(np.equal(best_class_indices, labels))print('Accuracy: %.3f' % accuracy)

 

关于对facenet代码的理解,网上已经有一些比较详细的讲解了,可以读这篇博客:FaceNet源码解读2:史上最全的FaceNet源码使用方法和讲解(二)。

而人脸识别的各种在应用方面还存在各种问题,随之而来的是新算法的出现,了解更改前沿技术可以看这篇文章,个人觉得还是不错的:格灵深瞳:人脸识别最新进展以及工业级大规模人脸识别实践探讨

 

上篇文章:facenet 人脸识别库的搭建和使用方法(二)


参考资料:

https://blog.csdn.net/fire_light_/article/details/79592804


http://chatgpt.dhexx.cn/article/BDAkNP5q.shtml

相关文章

人脸识别mtcnn原理

人脸检测&#xff0c;也就是在图片中找到人脸的位置。输入是一张可能含有人脸的图片&#xff0c;输出是人脸位置的矩形框。 人脸对齐。原始图片中人脸的姿态、位置可能有较大的区别&#xff0c;为了之后统一处理&#xff0c;要把人脸“摆正”。为此&#xff0c;需要检测人脸中…

dlib中的人脸识别原理

这里讨论的是人脸识别&#xff0c;不是人脸检测 dlib中是先检测都人脸&#xff0c;然后把人脸通过Resnet生成一个128维的向量&#xff0c;Resnet有几种不同深度的结构(图片来自https://raw.githubusercontent.com/raghakot/keras-resnet/master/images/architecture.png) dlib…

计算机识别人脸原理,深入浅出人脸识别原理

编辑推荐: 本文主要介绍了人脸识别流程,如何提取面部训练数据进行识别以及人脸检测和人脸识别,它们应用场景有哪些,希望对您的学习又所帮助。 本文来自于csdn,由火龙果软件Alice编辑、推荐。 前不久Iphone X发布,革命性的取消了TouchID(指纹识别),而添加了更酷的 FaceID(…

基于html5鼠标悬停图片动画展示效果

分享一款基于html5鼠标悬停图片动画展示效果。里面包含两款不同效果的html5图片展示效果。效果图如下&#xff1a; 在线预览 源码下载 实现的代码。 html代码&#xff1a; <div class"wrap" id"wrap"><div style"float: left; padding-top…

组件分享之后端组件——一个简单且高度可扩展的分布式文件系统seaweedfs

组件分享之后端组件——一个简单且高度可扩展的分布式文件系统seaweedfs 背景 近期正在探索前端、后端、系统端各类常用组件与工具&#xff0c;对其一些常见的组件进行再次整理一下&#xff0c;形成标准化组件专题&#xff0c;后续该专题将包含各类语言中的一些常用组件。欢迎大…

代理神器Charles4.2.8的破解

打开Charles&#xff0c;点击工具栏的Help&#xff0c;选择Register Charles&#xff0c;在两栏里分别输入即可。 Registered Name: https://zhile.io License Key: 48891cf209c6d32bf4

TLS加密套件

出于兴趣爱好&#xff0c;决定开发TLS1.2-1.3的一个库。为此阅读了TLS相关的若干RFC文档&#xff0c;以及查阅了多篇相关博客文章。最终有以下发现&#xff1a; 1. TLS定义了几百个加密套件(参考https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml)&#x…

sshd服务及防暴力破解 附赠防暴力破解脚本

利用yum源安装sshd服务客户端安装&#xff1a;openssh-clients.x86_64 服务端安装&#xff1a;openssh-server.x86_64Openssh和sshd有区别吗&#xff1f; 两个是不同的概念&#xff0c;软件包名称叫openshh 开机的服务叫sshd[rootserver1 ~]# rpm -ql openssh ###查看安装的…

The server selected protocol version TLS10 is not accepted by client preferences [TLS12]

最近在部署项目的时候遇到一个问题&#xff0c;卡了整整一天时间&#xff0c;所以感觉有必要po个解决方法出来给有需要的朋友参考一下。 问题描述&#xff1a;Caused by: javax.net.ssl.SSLHandshakeException: The server selected protocol version TLS10 is not accepted b…

TLS 1.3 协议详解

TLS 1.3 握手流程详解 我的TLS实现&#xff08;支持TLS1.3和国密SSL&#xff09;&#xff0c;大家可以学习参考&#xff1a;https://github.com/mrpre/atls/ 如果觉得有用&#xff0c;请打赏N元&#xff1a;http://39.98.242.44 需要的背景知识&#xff1a; &#xff08;1&am…

服务攻防-协议漏洞-FTPRDPSSHRsyncProFTPDlibsshOpenssh-Hydra工具使用口令猜解未授权访问

目录 一、导图 二、口令猜解-Hydra-FTP&RDP&SSH 1、协议介绍 2、Hydra工具介绍 3、实例演示 三、配置不当-未授权访问-Rsync 文件备份 1、Rsync介绍 2、漏洞成因——配置不当 3、实例演示 四、协议漏洞-应用软件-FTP&ProFTPD搭建 1、引入 2、ProFTPD介…

提示:The server selected protocol version TLS10 is not accepted by client preferences [TLS13, TLS12]

JMeter连接SQLservice数据库。 1、测试计划添加sqljdbc41.jar 2、添加数据库配置 3、添加请求 3、按着上面的配置&#xff0c;执行&#xff0c;然后报错误了。 提示“Cannot create PoolableConnectionFactory (The driver could not establish a secure connection to SQL S…

SSH暴力破解

ssh暴力破解解决方案 https://www.cnblogs.com/walkingzq/p/8191900.html 最近在使用腾讯云服务器的过程中&#xff0c;被比特币黑客黑了一次服务器&#xff08;如下图所示&#xff09;。 图1 比特币勒索信息 继而认识到网络安全的重要性。在重新安装系统之后&#xff0c;发现…

SSL/TLS Cipher Suites

Cipher Suite 一个加密算法套件&#xff08;CipherSuite&#xff09;是一个四件套&#xff0c;由各类基础的加密算法组成&#xff0c;主要包含了四类&#xff1a; 1&#xff09;Key Exchange 密钥交换算法&#xff1b; 2&#xff09;Authentication 身份认证算法&#xff1b…

The server selected protocol version TLS10 is not accepted by client preferences [TLS13, TLS12]

springboot启动时报错 com.microsoft.sqlserver.jdbc.SQLServerException: 驱动程序无法通过使用安全套接字层(SSL)加密与 SQL Server 建立安全连接。错误:“The server selected protocol version TLS10 is not accepted by client prefer ences [TLS13, TLS12]”。 原因&…

centos7 SSH防暴力破解五种方法

什么是暴力破解&#xff0c;简单来说就是对一个服务器进行无数次尝试登陆&#xff0c;并用不同的密码进行登陆直到可以登陆成功。暴力破解的基本步骤可以分为以下几步&#xff1a; 找到对应的linux服务器 Ip地址扫描端口号&#xff1a;22 nmap扫描端口开始暴力破解 : 一般root…

Linux云服务器防止暴力破解(三道SSH安全策略)

前言 新购入的服务器&#xff0c;往往用户名默认为root&#xff0c;ssh默认开放22端口&#xff0c;且配置SSH服务时往往同时允许密码和公钥二重登录。然而&#xff0c;许多非法服务器运行着暴力破解程序&#xff0c;通过访问用户名root的22默认端口&#xff0c;暴力获取获取您的…

kali Linux 工具 BurpSuite-暴力破解

关于渗透的实验&#xff0c;我们大多数能在kali的工具集找到&#xff0c;其中关于抓包工具BurpSuite的使用&#xff0c;我做一个比较简单的实验————————暴力破解—————————— 暴力破解&#xff0c;顾名思义&#xff0c;就是我们把密码一个个尝试&#xff0c;只…

拒绝ssh远程暴力破解-以centos7及centos8为例

一、centos8 参考&#xff1a; 如何在CentOS 8上安装和配置Fail2ban - A5互联 - 博客园 (cnblogs.com)https://www.cnblogs.com/a5idc/p/13650056.html上面这一个讲的比较详细&#xff1a;要点摘录如下 默认的Fail2ban安装中带有两个配置文件&#xff0c;/etc/fail2ban/jail…

SSHD 服务防止暴力破解

SSHD 服务防止暴力破解 目录 1、 配置安全的 SSHD 服务&#xff08;方法一&#xff09; 2、通过开源的防护软件来防护安全&#xff08;方法二&#xff09; 1、配置安全的 SSHD 服务 1.1、 服务器安全策略 密码足够复杂&#xff1a; 密码的长度要大于 8 位不大于 20 位。密…