FaceNet: A Unified Embedding for Face Recognition and Clustering 阅读笔记

简介

该论文试图去解决人脸识别的课题,人脸识别有三个研究方向,分别为

  1. 验证(verification),用于判断两个图像是否为同一个人
  2. 识别(recognition),用于识别一个图像是哪个人
  3. 聚类(clustering),在一系列图片中,找到一个经常出现的人

通常的人脸识别算法流程是这样的——

与之相反,论文提出的模型,以直接生产特征向量为目标,也就是说,特征向量不再作为一个中间信息,而是一个模型实实在在优化的目标。论文中的这种损失函数称为Triplet Loss。

模型

我们希望构造函数f(x),将图片x映射到特征空间\mathbb{R}^d,使得所有相同身份的人脸拥有较小的欧几里得距离,反之不同人脸的距离较大。在Triplet Loss的构造中,为了满足尺度的恒定,还额外规定f(x)位于单位球体上,即|f(x)| = 1

模型希望相同人脸特征距离近,不同人脸特征距离远,量化到数学公式上就是

|f(x_i^a)-f(x_i^p)|^2 + \alpha < |f(x_i^a)-f(x_i^n)|^2

其中x_i^a为基准图片(anchor),x_i^p为同一身份的不同图片(positive),x_i^n为不同身份的不同图片(negative). 而\alpha被称为TripletLoss的边缘距离(margin)

由于算力的原因,不能计算出所有可能的x_i^ax_i^px_i^n组合,即所有Triplet。因此,选择有代表性的Triplet是非常有必要的。一种非常暴力的做法是,找到上述不等式中前半部分的最大值以及后半部分的最小值,即argmax|f(x_i^a)-f(x_i^p)|^2argmin|f(x_i^a)-f(x_i^n)|^2,他们的组合一定是优化的瓶颈部分。我们将他们作为Hard Triplet,单纯优化他们就可以较快收敛。

由于图片画质以及误标记等原因,全局的argmax和argmin表现并不好,不过将其改成mini-batch内部的argmax与argmin就好了。

从零开始编写并托管WordPress插件:NoBaidu抵制百度插件

最近被一篇称为《搜索引擎百度已死》的文章被刷屏了,笔者本身就非常不喜欢百度,趁放寒假没有事情干,琢磨这在自己的网站上写一个插件。当访问者从百度进入网站,则在页面顶部显示一段用户自定义的阻止标语。顺便搞清楚Wordpress插件的原理。

上图就是NoBaidu的一个截图,本文按照我的编写顺序,分为——

  • 如何编写一个Wordpress插件
  • 如何将编好的插件托管到云端

另外,插件的源代码在我的github中开源,读者可以对照理解。

如何编写一个wordpress插件

编写Wordpress插件的教程网上很多,我就不重新造轮子了,我自己是在 如何开发一个WordPress如何开发一个WordPress插件 这篇文章中学到的,其核心要义就是钩子函数——

在Wordpress渲染一个页面的时候,在很多关键位置设置钩子(比如页面渲染开头,渲染器启动后等位置),而插件可以自定义的在任何钩子上挂载自己的函数,这样当页面渲染到了指定位置时,插件可以做一些自己的事情。

比如下面代码就可以在robots.txt渲染时,运行 $this->robots_txt_edit 指定的插件处理模块。

而以NoBaidu插件为例,我们需要支持如下逻辑——

  • 当普通用户访问时,检查用户的请求头的REFERER域是不是baidu域名下的URL
  • 当用户来自百度时,注册一个钩子函数,在页面渲染开始时,加入一个固定在页面顶部的,包含了自定义文字的HTML元素。
  • 当请求robots.txt时,返回禁止Baidu爬虫的robots文字

除此之外,还需要一些额外的代码,来保证我们的插件可以正常使用

  • 在用户是管理员的时候,生成插件设置页面,在其中可以设置显示的自定义抵制文字,用户选择是否组织百度爬虫,以及抵制文字是显示在顶端还是页面中部等等…
  • 编写插件安装、卸载时的逻辑,保证安装时初始化配置信息,卸载时删除配置信息,做到无残留

上述的逻辑,都集中到了下面的代码中,该代码使用一个类包裹了所有的函数(其作用类似于C++中的Namespace,用于最小化命名冲突)

看懂了上面的代码,是不是觉得Wordpress编写插件非常简单? 上述代码中引用的其他php代码,大家可以在我的github中自行查阅。

将自己写好的插件托管到wordpress云端

WordPress官网的Plugin目录最低端,有一个Add Your Plugin分区,这个分区详细介绍了该如何将你的Wordpress插件托管至wordpress.org,一般来说,读完上述的文章,你就已经能够自主把自己的插件丢到云端了。不过我准备从自己的经历出发,来大致讲一讲流程。

WordPress.org自己维护了一个svn仓库,最终会获得自己插件的专属仓库,你可以使用svn提供的版本控制,自行升级、修订等等。而想要获得自己插件的svn仓库,你就需要把自己的插件的最初版提交给官方审核。提交入口在这里。这里写几个提交的注意事项吧——

  • 最重要的是要知道php没有命名空间之说,所以一切全局变量都应该防止冲突。一个比较取巧的做法就是像上文一样,将你自己的程序包裹在一个class里面,而class以自己的插件名称命名。(我就因为配置的class命名为MySettingClass被官方打回来了)
  • 不要有额外的文件,之前写插件的时候,把网上别人插件的代码拷贝到了自己的目录,本来只是想照着抄一抄,结果忘删了,这个也被审核人发现了。
  • README.txt按照官方的标准格式写。

网站上面说的是7个工作日,结果我第一天晚上提交了初版的zip包,第二天早上就收到了审核者的邮件。按照要求修改了一些类名,并删除了无关文件后,我直接把zip包附在了回复中,第三天早上就拿到了通过的消息,并且获得了svn仓库的访问权限。开源社区真的非常强大👍

第一次要求修改的邮件
成功通过审核

接下来就是上传仓库了,如果读者会使用git的话,就别自己去学svn了,照着官方指南走一遍,就完全学会了。和git的pull, add, commit, push, tag如出一辙。

当你的first commit上传到远程仓库,并且readme.txt没有什么问题的话,你应该是可以立即在插件商店中搜索到自己写的插件的。

到这里我们在wordpress上面第一个插件就做好啦!

如果你觉得本文有用的话,欢迎到我的github仓库Star或Contribute~

让我们一起抵制Baidu吧~

参考文章

  • 【一个前人的代码】:http://ju.outofmemory.cn/entry/222836
  • 【如何开发Wordpress插件】:https://www.wpdaxue.com/writing_a_plugin.html
  • 【官方文档】:https://wordpress.org/plugins/developers/

Identity-Aware Convolutional Neural Network for Facial Expression Recognition 阅读笔记

这篇论文核心目标是提高人脸表情识别的精度。经典的表情识别算法,会将表情图片映射到特征空间(feature space)中的特征向量,而两个特征向量的欧几里得距离来衡量两个表情的相似度。

作者发现常规模型容易将“同一个人(indentity)”的特征向量放在一起而非“同一个表情(expression)”。这个问题表现在模型训练的时候,模型容易“偷偷”记录下训练数据中人物的面貌,并基于此进行判断。倘若随便换一个测试集,模型的准确度就有非常大的下降。(比如模型会记录下某黑人胖子A的吃惊的表情特征,但是之后测试集中,倘若是一个黑人瘦子B吃惊的表情,那么模型就不怎么容易判别出来了)

如下图,现有的模型的特征向量如图(a)所示依赖于人物,而作者的模型能挖掘和人物无关的表情特征,反映到特征空间中如图(b)所示。

文章提出的模型称为identity-aware convolutional neural network (IACNN) ,其核心思想是学习与表情有关(expression-related)的特征,并在同时,故意学习一个和人物有关(identity-related)的特征,后者虽然不利于网络的实际识别,但是却有利于让前者变得与身份无关(identity-invariant).

同时,该文章提出了一种距离的计算法则,能够让相似的表情的特征向量相距较近,而不相似的表情的特征向量相距较远。(不过这个计算法则感觉并不算亮点或是创新)

首先定义欧几里得距离作为接下来的距离公式——

D(f^E(I_1), f^E(I_2)) = |f^E(I_1), f^E(I_2)|^2

下面是一个自定义的损失函数公式——

L^{exp}_{Contrastive} = \frac{z_i^E}{2} * D(f^E(I_{i, 1}), f^E(I_{i,2})) + \frac{1-z_i^E}{2} * max(0, \alpha^E - D(f^E(I_{i, 1}), f^E(I_{i,2})))

这个公式看着很长,实际上非常简单,当两个图片属于同一个表情(exp),那么z_i=1 ,优化损失函数倾向于让他们的特征向量靠近;而倘若不属于同一个表情,z_i=0,优化损失函数倾向于让他们至少有\alpha^E的距离。这个损失函数可以用于训练提取表情特征的网络f^E(x)。顺便一提f^E是一个基于CNN的网络。

与上面相似,我们也可以创造一个L^{ID}_{Contrastive}专门用来训练提取身份特征的网络F^{ID}

L^{ID}_{Contrastive} = \frac{z_i^E}{2} * D(f^{ID}(I_{i, 1}), f^{ID}(I_{i,2})) + \frac{1-z_i^{ID}}{2} * max(0, \alpha^{ID} - D(f^{ID}(I_{i, 1}), f^{ID}(I_{i,2})))

通过上述的网络f^{ID}f^E,我们对于一个图片能够生成表情相关的特征FC_{exp}和身份相关特征FC_{ID},令他们的组合特征为FC_{feat}.

使用FC_{feat}进行预测,得到损失函数L^1_{softmax}L^2_{softmax}(1和2分别是两张图片),使用FC_{exp}进行预测,得到L^{exp1}_{softmax}L^{exp2}_{softmax}

最终损失函数如下

L = \lambda_1 L^{ID}_{Contrastive} + \lambda_2 L^{Exp}_{Contrastive} + \lambda_3 L^1_{softmax}+ \lambda_4 L^2_{softmax}+ \lambda_5 L^{exp1}_{softmax}+ \lambda_6 L^{exp2}_{softmax}

可以发现,优化损失函数L,身份特征相关的信息倾向于聚集在FC_{ID}中,从而使FC_{Exp}的信息是纯粹的面部无关信息。那么最后测试集上,单纯使用FC_{Exp}进行预测,就不会存在模型对于训练集人物过于依赖的问题了。