|
本教程视频直播回看:
前言:
本教学主要目的是学习如何一步一步用Keras自己编写一个模型,然后训练,一步一步最终部署到Toybrick嵌入式NPU上运行。之所以选则facenet,是因为他网络原理简单,loss函数需要手动编写(keras不提供,刚好可以学习如何训练),模型好坏可鉴别能力强,完全可以和原预训练模型进行对比,对于教学有非常好的帮助。学完后举一反三,可自行组建网络来玩。也建议有想学Keras或pyTorch的同学也可以找一个现成的论文模型,从头到尾按自己的理解写一遍代码,训练一次,部署一次。做完后你就可以毕业了。
下载地址:
Facenet源作者地址: [url=https://github.com/davidsandberg/facenet.git]https://github.com/davidsandberg/facenet.git
本教学源码:https://github.com/Jerzha/rknn_facenet.git
直播回看:http://www.yizhibo.com/l/GtN8pfmIJskQQ2kN.html
数据集:
CASIA-Webface:- http://www.cbsr.ia.ac.cn/english/CASIA-WebFace-Database.html
LFW : - http://vis-www.cs.umass.edu/lfw/#download
VGGFace:
- https://arxiv.org/abs/1710.08092v1
应用中可以用一套数据集做训练,另外一套做评估。或者一套数据集分两部分,一部分训练,一部分评估。
训练数据的预处理:
* 下载的训练数据需要先用对齐算法(官方用mtcnn做align)清洗一遍,存成对齐后的数据集存放。
* 总的来说,最终部署时候如何使用该网络,你就应该如何送训练数据
编写模型(Keras篇):
1. 参看本教学源码的models目录,我们先抽象了一个BaseModel基类(继承自tf.keras.Model),用于扩展save_pb, save_rknn等等操作。建议大家也可以这么做,不要每次遇到一个新模型都从头写一遍冗余代码。这样我们最终这个模型的使用就变得异常简单,最终使用起来类似这样:
- model = InceptionResnetV1(...) # 实例化模型
- model.compile(...) # 初始化/编译模型
- model.fit(...) # 训练模型
- model.evaluate(...) # 评估模型
- model.predict(...) # 使用该模型推理
- model.load_weights(...) # 读取权重
- model.save_weights(...) # 存储权重
- model.load(...) # 读取H5格式模型
- model.save(...) # 存储H5格式模型(配置+权重)
- model.save_pb(...) # 存储PB格式模型
- model.save_rknn(...) # 存储rknn格式模型
2. 需要注意的是,本文写的keras.model是基于函数式的调用,而非子类调用,我们利用python的子父类结构抽象了这个函数式调用过程。如果用tf/keras官方教程写成子类式调用,很多的虚函数你需要去实现,会显得非常麻烦。
3. 使用tf.kears可以非常简洁快速的构建出想要的模型,参看本教学用代码models/inception_resnet_v1.py,可以看到我复写的整个模型可读性远远超过原作者tf写的一大坨乱七八糟的代码。(这个就是Keras/pyTorch的最大优势所在)
FaceNet介绍:
1. Facenet论文并没有提出新的模型结构,只是讲了一种通过128维embedding特征向量的欧式距离来比对人脸的方法,解决了有限的分类器来区分有限人脸的情况。并提出了一种新的triplet loss思想,利用三元组的比对,来让同一个人的特征距离 + 阈值(0.2) < 不同人的特征距离 。
2. 原作者的代码上用center loss(另外一篇论文提出的)替代了triplet loss,收敛效果更好。
3. 论文代码主要是用 Inception_Resnet_v1 和v2 来构建模型,这里的inception module是google提出的一种网络结构,而Resnet是微软研究院提出的一种网络结构,这两个都是当下非常流行的网络结构,大家看我的直播或者直接看论文来了解这两个优秀的基本网络结构。
4. 而其最基础的网络结构采用的是 conv2d - batch normalization - relu ,也是当下非常流行的结构,batch normalization很好的解决了网络层数过多时候的梯度爆炸或者消失的问题,也是很值得借鉴的。
5. 需要注意的是,Facenet的输入不需要归一化处理,但是需要align对齐,原作者采用的是mtcnn来对齐,实际部署上可以考虑其他的对齐方案,例如android自带的detect face接口,他是两点对齐;或者opencv的人脸检测方案(直播演示的就是这个)。 对齐后识别的准确度更加的精确。训练时候原作者把所有的数据集图像都用mtcnn对齐抠了人脸后送入网络训练的。而用于推理时候,还把图像进行了预白化(prewhiten)处理,让不同亮度下的人脸识别更加准确。
训练 (TripletLoss):
TripletLoss 由facenet论文提出,主要思想是每次训练输入三个参数和一个阈值:
1. auchor的照片(集)
2. 和auchor照片属于同一个人的positive照片(集)
3. 和auchor照片不属于一个人的negative照片(集)
4. 阈值alpha(论文里是0.2)
训练过程:
1. 计算 auchor、positive、negative 经过网络推理后得到的各个128维embedding向量
2. 计算 auchor 和 positive 的欧式距离 pos_dist
3. 计算 auchor 和 negative 的欧式距离 neg_dist
4. 得出基础损失(集) base_loss = pos_dist - neg_dist + alpha, 如果base_loss < 0,则base_loss = 0
5. 根据送入的batch_size得出损失(集)的均值loss
所以可以看到训练的目标是让不同人的照片的距离,大于同一个人的照片距离 + alpha
我们事例代码里每次取数据时候会取3倍于batch_size的数据,前1/3是auchor图集,中1/3是positive图集,最后1/3是negative图集,
计算损失时候就可以把数组分成三部分后分别计算dist,而label变量就不会用到了。
训练(softmax + center loss):
TBD
(工作原因,比较忙,未完待续)
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
|