人脸质量评估

数据准备

数据标注

利用2015年的一篇人脸图像质量评估论文Face Image Quality Assessment Based on Learning to Rank提供的工具对数据图像数据集进行标注,人脸图像可以利用MTCNN 进行预处理,这里将人脸上下扩展了1/2,左右扩展了1/3,不进行对齐(不改变人脸的偏转角,因为这也属于图像质量评估的一个考察因素),该工具输出的值为0-100的整数值,此处将其归一化为[0,1]之间的实数值

数据存储

在做回归问题时,特别是标签为浮点数时,最好不要使用lmdb数据格式,原始的caffe中lmdb好像对float支持不太友好,可以通过修改源码,参考链接:如何将float类型的特征数据存入lmdb,但是此处可以换一个办法,利用hdf5存储,具体细节就不多讲了,但是有一个点要注意就是在读取数据的时候,

caffe.io_load_image:以RGB存储,[0-1]
matplotlib.image.imread:以RGB存储,[0,255]
cv2.imread:以BGR存储,[0,255]

所以要主要在训练模型和测试的时候要保持一致,减不减MeanValue,还有要不要归一化到[0,1]区间或者[0,255]区间

模型训练

首先这是一个质量分数回归问题,所以一个思路就是训练一个端到端的网络,首先是一个basemodel,这里采用resnet比较合适,将最后一层的输出直接改为1,为了使模型收敛的更快,可以现在FR任务上预训练一个模型,然后再在回归任务上进行finetune,这样做有一个好处,就是之前NormFace论文还是哪篇论文中提到了图像质量越好,提取到的特征模长越大,所以这个预训练应该还是有所帮助的。最后一个全连接层输出为1,然后以EuclideanLoss作为损失函数,进行训练,以SGD作为优化算法,最后训练得到了一个比较好的模型。

几点反思和记录

  • 对于标签为浮点数的数据集,最好用h5存储,存储时一定要注意数据存储的格式要一致

  • 之前采用VGG作为basemodel,然后最后全连接层输出为1,接sigmoid,然后用EuclideanLoss作为监督信号,但是输出全部是0.5左右,本来以为是sigmoid的问题,因为当输入非常大或者非常小的时候,神经元的梯度是接近于0的,这一点特性不太好,其实只要最后一个全连接层接损失函数就好,只要迭代次数够多,最终全连接层的输出会慢慢收敛的,所以没必要硬加一个约束,可能还会起到不好的效果。但是VGG16的效果并不好,无论训练多久,其输出一直在0.5附近,经过分析,应该是发生了梯度弥散,可以加BatchNorm层,于是自己设计了一个浅层的模型做实验,发现最后的结果也非常好,和经过预训练的resnet18效果差不多,但是模型小多了,这说明可能这个简单的回归任务,只要参数和数据适配,训练参数设置合理,网络结构没有太大差别。

    Q图片2019022319503

  • 至于优化算法,有地方说caffe的SGD不太适合作为回归任务的优化算法,但是之前训练一直不收敛,是由于数据存储的问题,改用adam之后也没有太大差,所以SGD还是可以作为回归的优化算法的
  • BatchNorm是个好东西