CNN for Face Alignment 深度神经网络的初次尝试
来源:互联网 发布:mac 查看php版本 编辑:程序博客网 时间:2024/06/18 00:56
在Face Alignment中,传统方法其实能够取得不错的效果。包括AAM,ASM,CLM还有之前说的基于全局显式回归的ESR,3000FPS等。
但是!传统算法在大姿态、极端表情上基本无能为力。在我的理解中,他们都是对于训练集的某些特征进行降维后记忆回归的结果(理解有错请指出)。嘻嘻,而且不去接触神经网络都要Out了!
背景
基于由俭入奢的原则,论文方面我们选取了CNN在人脸对齐方向比较前期的一篇论文CVPR _2013《Deep Convolutional Network Cascade for Facial Point Detection》
。在实现环境方面,我们选择了社区比较成熟的而且背后大佬比较牛逼的Tensorflow 1.3.0
。
去网上搜罗了一些CNN基本知识,因为卷积的Gif实在是太生动了。也很容易理解CNN卷积层中W和b的含义。
模型
我们只挑选了其中的Level1来进行实现,所以代码量也比较少。作为入门使用也是可以的。
Leve1由三个CNN网络组成[F1,EN1,NM1]。F1预测了面部五个点的位置,EN1预测其中的双眼、鼻子,NM1预测鼻子、嘴角。最后整个Leve1的输出是三个网络输出的平均值。
根据论文表格,描述了所有网络的详细结构:
我们准备实现的F1为S0结构,EN1及NM1为S1结构。在论文中,作者使用非共享卷积层。对于每一个map,分为p x q的区域。如S0的Layer1:CR(4,20,2,2),CR表示使用Abs(tanh(x))作为激活函数,卷积核大小为4x4,输出20个通道map,每个map在10x10的区域内权值共享。
但由于tensorflow并不原生支持unshare weights,所以我们直接按照标准的共享权值CNN来实现,在精度上会有一定损失。
实现细节
基于最基础的思想,利用Tensorflow中已有的Api,我们来直接实现Level 1网络。训练集及测试集均可以在论文的官网下载到。
预处理
首先,按照论文的说法,我们对原始训练集进行数据增强。对原始图像进行镜像、少量随机旋转和平移然后抽取人脸检测包围盒中的图片,将其缩放至39x39备用。相比于利用API进行后续网络的搭建,反而感觉这一步是最麻烦的。哈哈哈
搭建模型
利用Tensorflow的高级layer函数,我们可以非常方便的搭建整个网络。需要用到的api:
tf.layers.conv2d #卷积层tf.layers.max_pooling2d #最大池化层 我们这里没有像论文一样给池化层增加权值及biastf.contrib.layers.flatten #展平数据tf.layers.dense #全连接层
在选择激活函数的时候,我们选择于论文一致的 tanh 来当做激活函数。一开始我直接使用Tensorflow自带的权值初始方法,发现收敛非常慢甚至于收敛不了。经过查资料和询问朋友发现,tanh 搭配 xavier 初始化有奇效。这点我目前还没有彻底理解,留后。资料:资料
注:后来发现为手误,初始的也能收敛。
So,我们现在搭一个CNN太简单了!
def NewS0(name): with tf.name_scope('S0' + name): x = tf.placeholder(tf.float32, shape=[None, 39 , 39,1]) y = tf.placeholder(tf.float32, shape=[None, 10]) xImage = tf.reshape(x,[-1, 39, 39, 1]) Conv1 = tf.abs(tf.layers.conv2d(inputs=xImage,filters=20,kernel_size=4,strides=1,activation=tf.nn.tanh)) Pool1 = tf.layers.max_pooling2d(inputs=Conv1,pool_size=2,strides=2,padding='same') Conv2 = tf.abs(tf.layers.conv2d(inputs=Pool1,filters=40,kernel_size=3,strides=1,activation=tf.nn.tanh)) Pool2 = tf.layers.max_pooling2d(inputs=Conv2,pool_size=2,strides=2,padding='same') Conv3 = tf.abs(tf.layers.conv2d(inputs=Pool2,filters=60,kernel_size=3,strides=1,activation=tf.nn.tanh)) Pool3 = tf.layers.max_pooling2d(inputs=Conv3,pool_size=2,strides=2,padding='same') Conv4 = tf.abs(tf.layers.conv2d(inputs=Pool3,filters=80,kernel_size=2,strides=1,activation=tf.nn.tanh)) Pool3_Flat = tf.contrib.layers.flatten(Pool3) Conv4_Flat = tf.contrib.layers.flatten(Conv4) Concat = tf.concat([Pool3_Flat,Conv4_Flat],1) Fc1 = tf.layers.dense(Concat,120,activation=tf.nn.tanh) Fc2 = tf.layers.dense(Fc1,10,activation=tf.nn.tanh) Cost = tf.reduce_mean(tf.square(Fc2 - y)) / 2.0 tf.summary.scalar(name + "/Cost",Cost) Optimizer = tf.train.AdamOptimizer(1e-4).minimize(Cost) return Optimizer,Fc2,x,y,Costdef NewS1(name,isEN1): with tf.name_scope('S1' + name): x = tf.placeholder(tf.float32, shape=[None, 39,39,1]) y = tf.placeholder(tf.float32, shape=[None, 10]) xImage = tf.reshape(x,[-1, 39, 39, 1]) if isEN1: xImage = tf.slice(xImage,[0,0,0,0],[-1,31,39,1]) y_In = tf.slice(y,[0,0],[-1,6]) else: xImage = tf.slice(xImage,[0,8,0,0],[-1,31,39,1]) y_In = tf.slice(y,[0,4],[-1,6]) Conv1 = tf.abs(tf.layers.conv2d(inputs=xImage,filters=20,kernel_size=4,strides=1,activation=tf.nn.tanh)) Pool1 = tf.layers.max_pooling2d(inputs=Conv1,pool_size=2,strides=2,padding='same') Conv2 = tf.abs(tf.layers.conv2d(inputs=Pool1,filters=40,kernel_size=3,strides=1,activation=tf.nn.tanh)) Pool2 = tf.layers.max_pooling2d(inputs=Conv2,pool_size=2,strides=2,padding='same') Conv3 = tf.abs(tf.layers.conv2d(inputs=Pool2,filters=60,kernel_size=3,strides=1,activation=tf.nn.tanh)) Pool3 = tf.layers.max_pooling2d(inputs=Conv3,pool_size=2,strides=2,padding='same') Conv4 = tf.abs(tf.layers.conv2d(inputs=Pool3,filters=80,kernel_size=2,strides=1,activation=tf.nn.tanh)) Pool3_Flat = tf.contrib.layers.flatten(Pool3) Conv4_Flat = tf.contrib.layers.flatten(Conv4) Concat = tf.concat([Pool3_Flat,Conv4_Flat],1) Fc1 = tf.layers.dense(Concat,100,activation=tf.nn.tanh) Fc2 = tf.layers.dense(Fc1,6,activation=tf.nn.tanh) Cost = tf.reduce_mean(tf.square(Fc2 - y_In)) / 2.0 tf.summary.scalar(name + "/Cost",Cost) Optimizer = tf.train.AdamOptimizer(1e-4).minimize(Cost) return Optimizer,Fc2,x,y,Cost
顺便一说,我并没有使用论文中的随机梯度下降来优化参数,因为。。实在太慢了。我使用了Tensorflow中提供的优化器Adam。
最后,在测试集上的双眼间距错误率为 4%,应该说我们的网络基本已经实现了。虽然精度可能没有论文中
那么好,但也差不多啦哈哈哈哈!OK,CNN的第一次应用就算完成了。接下来去解决后续论文了。
- CNN for Face Alignment 深度神经网络的初次尝试
- CNN (深度神经网络)的本质
- CNN 深度神经网络
- Affine-Transformation Parameters Regression for Face Alignment
- 【深度学习】最新的一些开源face alignment及评价
- 深度神经网络(DNN)、卷积神经网络(CNN)、循环神经网络(RNN)(神经网络的基础知识)
- Face Alignment
- Face Alignment
- Face Alignment
- MyCat的初次尝试
- CNN卷积神经网络深度解析
- 深度学习:卷积神经网络CNN
- Face Alignment(Face Landmark)
- 卷积神经网络CNN解析-针对斯坦福的深度学习教程
- <模型汇总_1>牛逼的深度卷积神经网络CNN
- 干货 | 深度学习之卷积神经网络(CNN)的模型结构
- CNN(卷积神经网络)、RNN(循环神经网络)、DNN(深度神经网络)的内部网络结构的区别
- CNN(卷积神经网络)、RNN(循环神经网络)、DNN(深度神经网络)的内部网络结构的区别
- 洛谷 p1137 topsort正解的证明
- 12判词
- Logistic回归简介
- zoj 2112 (主席树,树状数组套线段树)
- 前端常见跨域解决方案(全)
- CNN for Face Alignment 深度神经网络的初次尝试
- 如何快速阅读——《应用篇》
- and...or的 彻底研究
- 从后台获得数据,前台实现数据加载和异步查询
- JDK9的32位版本下载
- GNU常用命令
- unity3D与Socket通信_01
- Base64编码
- Linux 自动加载驱动模块(.ko文件)