2016-02-13 11:18:50 wjmishuai 阅读数 9933
  • 大数据:深度学习项目实战-人脸检测视频教程

    购买课程后,请扫码入学习群,获取唐宇迪老师答疑 进军深度学习佳项目实战:人脸检测项目视频培训课程,从数据的收集以及预处理开始,一步步带着大家完成整个人脸检测的项目,其中涉及了如何使用深度学习框架Caffe完成整个项目的架构,对于每一个核心步骤详细演示流程和原理解读,在完成检测代码之后进行了详细评估分析,并给出一篇顶级会议论文作为学习参考,详细分析了针对人脸检测项目的优缺点和改进策略。

    16410 人正在学习 去看看 唐宇迪
1:基于深度学习的人脸识别算法流程
(1)模型训练
x可以理解成输入图片,就是像素组成的矩阵
fw(x)理解成我们最后要拟合的回归函数,也就是最后训练出来的model。

(2)人脸匹配




2:教程大纲与导航

2019-06-20 19:39:23 xiaosongshine 阅读数 461
  • 大数据:深度学习项目实战-人脸检测视频教程

    购买课程后,请扫码入学习群,获取唐宇迪老师答疑 进军深度学习佳项目实战:人脸检测项目视频培训课程,从数据的收集以及预处理开始,一步步带着大家完成整个人脸检测的项目,其中涉及了如何使用深度学习框架Caffe完成整个项目的架构,对于每一个核心步骤详细演示流程和原理解读,在完成检测代码之后进行了详细评估分析,并给出一篇顶级会议论文作为学习参考,详细分析了针对人脸检测项目的优缺点和改进策略。

    16410 人正在学习 去看看 唐宇迪

『深度应用』深度学习人脸识别模型开发与应用流程综述


0. 概念简介

 

度量学习(Metric Learning),也称距离度量学习(Distance Metric Learning,DML) 属于机器学习的一种。其本质就是相似度的学习,也可以认为距离学习。因为在一定条件下,相似度和距离可以相互转换。比如在空间坐标的两条向量,既可以用余弦相似度的大小,也可以使用欧式距离的远近来衡量相似程度。

常见的人脸识别与声纹识别都属于度量学习。

一般的度量学习包含以下步骤:

  1. Encoder编码模型:用于把原始数据编码为特征向量(重点如何训练模型
  2. 相似度判别算法:将一对特征向量进行相似度比对(重点如何计算相似度,阈值如何设定

 

1.编码模型训练

 

通过使用大量数据集进行网络模型训练。使编码模型可以实现对原始数据提取特征向量的功能。

基于深度学习的度量学习算法中,可以分为两个流派:

  1. 网络设计派:代表孪生神经网络(Siamese network)
  2. 损失改进派:代表 xx-softmax

本文主要讲整体开发流程,具体细节请自行查阅。

通过对编码模型训练,得到了具备提取特征的encoder模型,让原始数据通过encoder模型就可以对应特征向量:

X = Encoder(row)

下面就是利用这个encoder模型,作为特征提取器,进行相似度判别。

 

2.相似度判别算法

 

在第一步(1.编码模型训练)完成后,获得了具备特征提取的编码模型,就可以利用此encoder网络进行验证系统开发。

首先要对在第一步得到的编码模型进行性能测试。步骤如下:

  1. 使用测试数据生成测试对,需要保证尽量随机取对和正负数据平衡,同一种标签为1,不同种为0
  2. 使用编码模型得到所有特征向量
  3. 根据测试对的特征向量计算相似度,可选余弦距离度/欧式距离
  4. 根据测试对的相似度与标签,设置合理阈值范围,分辨率取0.0001,遍历阈值计算 FAR(错误接受率)FRR(错误拒绝率),两者相等得到EER(等错误概率),此时的阈值也是较优阈值。(也可以使用类似方法验证准确率)

通过上述步骤就可以获得模型的识别性能和应用阈值。

如若想提高阈值的泛化能力,可以采用测试与验证的方法计算阈值:

  1.  将测试对分为10组,用来确定阈值并验证精读。
  2. 使用其中1组,同种判断错误和不同种判定错误的个数。
  3. 选择错误个数最少的那个阈值,用剩余9组,判断识别精度。
  4. 步骤2和3执行10次,将每次3获取的精度进行累加并求平均,得到最终判定精度。记录下精度最高的那次的阈值,记为最优阈值

 


References:

1.https://blog.csdn.net/fuwenyan/article/details/74943248

2016-06-04 16:39:46 shixiangyun2 阅读数 24746
  • 大数据:深度学习项目实战-人脸检测视频教程

    购买课程后,请扫码入学习群,获取唐宇迪老师答疑 进军深度学习佳项目实战:人脸检测项目视频培训课程,从数据的收集以及预处理开始,一步步带着大家完成整个人脸检测的项目,其中涉及了如何使用深度学习框架Caffe完成整个项目的架构,对于每一个核心步骤详细演示流程和原理解读,在完成检测代码之后进行了详细评估分析,并给出一篇顶级会议论文作为学习参考,详细分析了针对人脸检测项目的优缺点和改进策略。

    16410 人正在学习 去看看 唐宇迪

人脸识别介绍

人脸识别技术是一项非接触式、用户友好、非配合型的计算机视觉识别技术。随着机器学习、深度学习等技术的发展,人脸识别的应用正日趋完善和成熟。本文将介绍人脸识别技术如何用于考勤/签到系统。

本文将主要从以下几个方面阐述:

  • 平台环境需求
  • 涉及的技术点
  • 人脸识别系统流程
  • 细节设计

平台环境需求

  • 操作系统:Windows 64位
  • 第三方库:OpenCV,Caffe,boost
  • 开发语言:C++
  • 数据库:MySQL

技术点

adaboost算法和CNN用于人脸检测与定位;
随机森林算法/CNN用于人脸关键点标定;
卷积神经网络用于人脸特征提取;
MFC用于设计系统操作界面;
MySQL数据库用于管理人物-人脸特征数据库;
Caffe框架用于上述环节中CNN模型的训练;
使用Caffe的C++接口进模型行部署和使用;
使用connector C++进行MySQL数据库的连接。

系统流程

考勤系统主要包含两个操作:注册和实时识别记录。

注册是指管理员通过软件界面将需考勤人员登记入库。 这里要输入待考勤人员的信息。
实时识别记录是系统自动对来往人群进行人脸识别,并记录通行者的身份。

进行注册的流程如下:

Created with Raphaël 2.1.0开始注册?人脸检测特征提取插入数据库yes

实时识别的流程如下:

Created with Raphaël 2.1.0开始实时识别?人脸检测特征提取搜索数据库并记录身份yes

细节设计

人脸检测

使用OpenCV的人脸检测器进行人脸的初步检测,使用Caffe训练CNN网络进行人脸的二分类判定,将两部分合在一起完成人脸检测。此环节需注意根据应用场景调整参数,做到性能与召回率的平衡。

也可使用Python+OpenCV进行视频中的人脸检测,参考这篇文章

人脸关键点定位

关键点定位的目标是在确知人脸位置的基础上,精确定位面部的关键点,如下图示意:

获得面部关键点的目的是进行人脸的对齐和标准化。标准化的人脸输入可以获得更高的人脸识别精度。

人脸特征提取

人脸特征提取是根据上述标准化的人脸区域图块,提取出数字化的特征。即完成从RGB信息到数值特征的变换。此环节需要尽量使得同一个人物的不同人脸所提取到的特征尽可能相似,而不同人物的人脸所提取的特征尽可能相异。

模型的训练

人脸识别的CNN网络模型的训练采用CASIA-Webface数据库,具体训练方式参见我的这篇文章。训练模型的流程参考我的github项目

本模型在LFW评测集上达到了接近97%的准确率。具备一定的实用性。

模型的部署

部署主要考虑Caffe在Windows平台的移植,官方的Caffe对Windows系统并不支持,为了使用Caffe的C++接口,我们需要使用Windows版本的Caffe,微软出了一个版本的Caffe,参考这里。

MySQL数据库的使用

MySQL的安装和配置详见这里。
我们使用默认的3306端口,配置好账户密码后,即可创建数据表。

MFC工程的搭建

使用Visual Studio 2013创建MFC工程,设计本软件的界面。详细的配置流程参考这里。

本软件设计界面如下
界面

主要包括注册和搜索两个功能。点击注册时,按钮下方出现输入框,用于输入待考察人物的信息。

软件使用

注册,点击注册按钮,并选定需要注册的人脸。
注册
输入人物信息,并提交到数据库。
输入信息
搜索,点击搜索,界面中实时识别人物,并将识别到的信息展示在人脸上。
搜索

2019-11-24 13:42:10 weixin_42137700 阅读数 16
  • 大数据:深度学习项目实战-人脸检测视频教程

    购买课程后,请扫码入学习群,获取唐宇迪老师答疑 进军深度学习佳项目实战:人脸检测项目视频培训课程,从数据的收集以及预处理开始,一步步带着大家完成整个人脸检测的项目,其中涉及了如何使用深度学习框架Caffe完成整个项目的架构,对于每一个核心步骤详细演示流程和原理解读,在完成检测代码之后进行了详细评估分析,并给出一篇顶级会议论文作为学习参考,详细分析了针对人脸检测项目的优缺点和改进策略。

    16410 人正在学习 去看看 唐宇迪

人脸关键点检测是人脸图像中重要的基石,今天给大家介绍入门深度学习人脸关键点检测必读的文章。

作者&编辑 | 言有三

1 DCNN Cascade

听这个名字就知道是一个很早期的,使用Cascade(级连)流程来解决人脸关键点检测问题的框架,由粗到精,就是它的基本思想。

文章引用量:900+

推荐指数:✦✦✦✦✧

「每周CV论文推荐」 初学深度学习人脸关键点检测必读文章

 

[1] Sun Y, Wang X, Tang X. Deep convolutional network cascade for facial point detection[C]//Proceedings of the IEEE conference on computer vision and pattern recognition. 2013: 3476-3483.

2 TCDCN

多任务联合是在人脸算法中经常被使用的策略,TCDCN(Tasks-Constrained Deep Convolutional Network)将人脸关键点检测与性别、是否带眼镜、是否微笑及脸部的姿势这四个子任务结合起来构成一个多任务学习模型,一些子任务比如脸部姿态在后来的人脸关键点检测框架中被经常使用。

文章引用量:900+

推荐指数:✦✦✦✦✧

「每周CV论文推荐」 初学深度学习人脸关键点检测必读文章

 

[2] Zhang Z, Luo P, Loy C C, et al. Facial landmark detection by deep multi-task learning[C]//European conference on computer vision. Springer, Cham, 2014: 94-108.

3 MTCNN

MTCNN也是基于Cascade的框架,但是整体思路更加巧妙合理,并且将人脸检测和人脸关键点检测任务同时完成。

文章引用量:900+

推荐指数:✦✦✦✦✦

「每周CV论文推荐」 初学深度学习人脸关键点检测必读文章

 

[3] Joint Face Detection and Alignment using Multi-task Cascaded Convolutional Networks[K. Zhang al., 2016

4 DAN

DAN同样是一种级连网络,不过它没有采用多尺度,各阶段网络的输入则均为整张图片,逐步对姿态不断进行校正,另外加入了关键点热图(Landmark Heatmaps)作为监督,关键点热图在后面的很多任务中也被使用。

文章引用量:100+

推荐指数:✦✦✦✦✧

「每周CV论文推荐」 初学深度学习人脸关键点检测必读文章

 

[4] Kowalski M, Naruniec J, Trzcinski T. Deep alignment network: A convolutional neural network for robust face alignment[C]//Proceedings of the IEEE Conference on Computer Vision and Pattern Recognition Workshops. 2017: 88-97.

5 Boundary-Aware

人脸的边缘信息对人脸关键点检测是很有用的监督信息,Boundary-Aware算法基于边缘感知的人脸关键点检测算法,提升了算法在大侧脸、夸张表情、遮挡、模糊等极端情况下的检测精度,这也是一种很常用的监督。

文章引用量:40+

推荐指数:✦✦✦✦✧

「每周CV论文推荐」 初学深度学习人脸关键点检测必读文章

 

[5] Wu W, Qian C, Yang S, et al. Look at boundary: A boundary-aware face alignment algorithm[C]//Proceedings of the IEEE Conference on Computer Vision and Pattern Recognition. 2018: 2129-2138.

6 综述

上面就是这一周初入深度学习人脸关键点检测值得读的文章,往后我们还会推荐精度更高的,以及3D相关的人脸关键点检测算法,先打好基础吧,最后推荐个综述读读。

文章引用量:40+

推荐指数:✦✦✦✦✧

[6] Jin X, Tan X. Face alignment in-the-wild: A survey[J]. Computer Vision and Image Understanding, 2017, 162: 1-22.

2015-01-29 20:35:43 u012162613 阅读数 86868
  • 大数据:深度学习项目实战-人脸检测视频教程

    购买课程后,请扫码入学习群,获取唐宇迪老师答疑 进军深度学习佳项目实战:人脸检测项目视频培训课程,从数据的收集以及预处理开始,一步步带着大家完成整个人脸检测的项目,其中涉及了如何使用深度学习框架Caffe完成整个项目的架构,对于每一个核心步骤详细演示流程和原理解读,在完成检测代码之后进行了详细评估分析,并给出一篇顶级会议论文作为学习参考,详细分析了针对人脸检测项目的优缺点和改进策略。

    16410 人正在学习 去看看 唐宇迪

DeepLearning tutorial(5)CNN卷积神经网络应用于人脸识别(详细流程+代码实现)


@author:wepon

@blog:http://blog.csdn.net/u012162613/article/details/43277187


本文代码下载地址:我的github


本文主要讲解将CNN应用于人脸识别的流程,程序基于python+numpy+theano+PIL开发,采用类似LeNet5的CNN模型,应用于olivettifaces人脸数据库,实现人脸识别的功能,模型的误差降到了5%以下。本程序只是个人学习过程的一个toy implement,样本很小,模型随时都会过拟合。

但是,本文意在理清程序开发CNN模型的具体步骤,特别是针对图像识别,从拿到图像数据库,到实现一个针对这个图像数据库的CNN模型,我觉得本文对这些流程的实现具有参考意义。


《本文目录》

一、olivettifaces人脸数据库介绍

二、CNN的基本“构件”(LogisticRegression、HiddenLayer、LeNetConvPoolLayer)

三、组建CNN模型,设置优化算法,应用于Olivetti Faces进行人脸识别

四、训练结果以及参数设置的讨论

五、利用训练好的参数初始化模型

六、一些需要说明的


一、olivettifaces人脸数据库介绍


Olivetti Faces是纽约大学的一个比较小的人脸库,由40个人的400张图片构成,即每个人的人脸图片为10张。每张图片的灰度级为8位,每个像素的灰度大小位于0-255之间,每张图片大小为64×64。如下图,这个图片大小是1190*942,一共有20*20张人脸,故每张人脸大小是(1190/20)*(942/20)即57*47=2679:



本文所用的训练数据就是这张图片,400个样本,40个类别,乍一看样本好像比较小,用CNN效果会好吗?先别下结论,请往下看。

要运行CNN算法,这张图片必须先转化为数组(或者说矩阵),这个用到python的图像库PIL,几行代码就可以搞定,具体的方法我之前刚好写过一篇文章,也是用这张图,考虑到文章冗长,就不复制过来了,链接在此:《利用Python PIL、cPickle读取和保存图像数据库》


训练机器学习算法,我们一般将原始数据分成训练数据(training_set)、验证数据(validation_set)、测试数据(testing_set)。本程序将training_set、validation_set、testing_set分别设置为320、40、40个样本。它们的label为0~39,对应40个不同的人。这部分的代码如下:

"""
加载图像数据的函数,dataset_path即图像olivettifaces的路径
加载olivettifaces后,划分为train_data,valid_data,test_data三个数据集
函数返回train_data,valid_data,test_data以及对应的label
"""
def load_data(dataset_path):
    img = Image.open(dataset_path)
    img_ndarray = numpy.asarray(img, dtype='float64')/256
    faces=numpy.empty((400,2679))
    for row in range(20):
	   for column in range(20):
		faces[row*20+column]=numpy.ndarray.flatten(img_ndarray [row*57:(row+1)*57,column*47:(column+1)*47])

    label=numpy.empty(400)
    for i in range(40):
	label[i*10:i*10+10]=i
    label=label.astype(numpy.int)

    #分成训练集、验证集、测试集,大小如下
    train_data=numpy.empty((320,2679))
    train_label=numpy.empty(320)
    valid_data=numpy.empty((40,2679))
    valid_label=numpy.empty(40)
    test_data=numpy.empty((40,2679))
    test_label=numpy.empty(40)

    for i in range(40):
	train_data[i*8:i*8+8]=faces[i*10:i*10+8]
	train_label[i*8:i*8+8]=label[i*10:i*10+8]
	valid_data[i]=faces[i*10+8]
	valid_label[i]=label[i*10+8]
	test_data[i]=faces[i*10+9]
	test_label[i]=label[i*10+9]

    #将数据集定义成shared类型,才能将数据复制进GPU,利用GPU加速程序。
    def shared_dataset(data_x, data_y, borrow=True):
        shared_x = theano.shared(numpy.asarray(data_x,
                                               dtype=theano.config.floatX),
                                 borrow=borrow)
        shared_y = theano.shared(numpy.asarray(data_y,
                                               dtype=theano.config.floatX),
                                 borrow=borrow)
        return shared_x, T.cast(shared_y, 'int32')



    train_set_x, train_set_y = shared_dataset(train_data,train_label)
    valid_set_x, valid_set_y = shared_dataset(valid_data,valid_label)
    test_set_x, test_set_y = shared_dataset(test_data,test_label)
    rval = [(train_set_x, train_set_y), (valid_set_x, valid_set_y),
            (test_set_x, test_set_y)]
    return rval

二、CNN的基本“构件”(LogisticRegression、HiddenLayer、LeNetConvPoolLayer)


卷积神经网络(CNN)的基本结构就是输入层、卷积层(conv)、子采样层(pooling)、全连接层输出层(分类器)。  卷积层+子采样层一般都会有若干个,本程序实现的CNN模型参考LeNet5,有两个“卷积+子采样层”LeNetConvPoolLayer。全连接层相当于MLP(多层感知机)中的隐含层HiddenLayer。输出层即分类器,一般采用softmax回归(也有人直接叫逻辑回归,其实就是多类别的logistics regression),本程序也直接用LogisticRegression表示。

总结起来,要组建CNN模型,必须先定义LeNetConvPoolLayer、HiddenLayer、LogisticRegression这三种layer,这一点在我上一篇文章介绍CNN算法时讲得很详细,包括代码注解,因为太冗长,这里给出链接:《DeepLearning tutorial(4)CNN卷积神经网络原理简介+代码详解》

代码太长,就不贴具体的了,只给出框架,具体可以下载我的代码看看:

#分类器,即CNN最后一层,采用逻辑回归(softmax)
class LogisticRegression(object):
    def __init__(self, input, n_in, n_out):
        self.W = ....
        self.b = ....
        self.p_y_given_x = ...
        self.y_pred = ...
        self.params = ...
    def negative_log_likelihood(self, y):
    def errors(self, y):

#全连接层,分类器前一层
class HiddenLayer(object):
    def __init__(self, rng, input, n_in, n_out, W=None, b=None,activation=T.tanh):
        self.input = input
        self.W = ...
        self.b = ...
        lin_output = ...
        self.params = [self.W, self.b]

#卷积+采样层(conv+maxpooling)
class LeNetConvPoolLayer(object):
    def __init__(self, rng, input, filter_shape, image_shape, poolsize=(2, 2)):
        self.input = input
        self.W = ...
        self.b = ...
        # 卷积
        conv_out = ...
        # 子采样
        pooled_out =...
        self.output = ...
        self.params = [self.W, self.b]



三、组建CNN模型,设置优化算法,应用于Olivetti Faces进行人脸识别


上面定义好了CNN的几个基本“构件”,现在我们使用这些构件来组建CNN模型,本程序的CNN模型参考LeNet5,具体为:input+layer0(LeNetConvPoolLayer)+layer1(LeNetConvPoolLayer)+layer2(HiddenLayer)+layer3(LogisticRegression)


这是一个串联结构,代码也很好写,直接用第二部分定义好的各种layer去组建就行了,上一layer的输出接下一layer的输入,具体可以看看代码evaluate_olivettifaces函数中的“建立CNN模型”部分。


CNN模型组建好了,就剩下用优化算法求解了,优化算法采用批量随机梯度下降算法(MSGD),所以要先定义MSGD的一些要素,主要包括:代价函数,训练、验证、测试model、参数更新规则(即梯度下降)。这部分的代码在evaluate_olivettifaces函数中的“定义优化算法的一些基本要素”部分。


优化算法的基本要素也定义好了,接下来就要运用人脸图像数据集来训练这个模型了,训练过程有训练步数(n_epoch)的设置,每个epoch会遍历所有的训练数据(training_set),本程序中也就是320个人脸图。还有迭代次数iter,一次迭代遍历一个batch里的所有样本,具体为多少要看所设置的batch_size。关于参数的设定我在下面会讨论。这一部分的代码在evaluate_olivettifaces函数中的“训练CNN阶段”部分。

代码很长,只贴框架,具体可以下载我的代码看看:

def evaluate_olivettifaces(learning_rate=0.05, n_epochs=200,
                    dataset='olivettifaces.gif',
                    nkerns=[5, 10], batch_size=40):   

    #随机数生成器,用于初始化参数....
    #加载数据.....
    #计算各数据集的batch个数....
    #定义几个变量,x代表人脸数据,作为layer0的输入......

    ######################
    #建立CNN模型:
    #input+layer0(LeNetConvPoolLayer)+layer1(LeNetConvPoolLayer)+layer2(HiddenLayer)+layer3(LogisticRegression)
    ######################
    ...
    ....
    ......

    #########################
    # 定义优化算法的一些基本要素:代价函数,训练、验证、测试model、参数更新规则(即梯度下降)
    #########################
    ...
    ....
    ......

    #########################
    # 训练CNN阶段,寻找最优的参数。
    ########################
    ...
    .....
    .......


另外,值得一提的是,在训练CNN阶段,我们必须定时地保存模型的参数,这是在训练机器学习算法时一个经常会做的事情,这一部分的详细介绍我之前写过一篇文章《DeepLearning tutorial(2)机器学习算法在训练过程中保存参数》。简单来说,我们要保存CNN模型中layer0、layer1、layer2、layer3的参数,所以在“训练CNN阶段”这部分下面,有一句代码:

 save_params(layer0.params,layer1.params,layer2.params,layer3.params)


这个函数具体定义为:


#保存训练参数的函数
def save_params(param1,param2,param3,param4):  
        import cPickle  
        write_file = open('params.pkl', 'wb')   
        cPickle.dump(param1, write_file, -1)
        cPickle.dump(param2, write_file, -1)
        cPickle.dump(param3, write_file, -1)
        cPickle.dump(param4, write_file, -1)
        write_file.close()  


如果在其他算法中,你要保存的参数有五个六个甚至更多,那么改一下这个函数的参数就行啦。



四、训练结果以及参数设置的讨论


ok,上面基本介绍完了CNN模型的构建,以及模型的训练,我将它们的代码都放在train_CNN_olivettifaces.py这个源文件中,将Olivetti Faces这张图片跟这个代码文件放在同个目录下,运行这个文件,几分钟就可以训练完模型,并且在同个目录下得到一个params.pkl文件,这个文件保存的就是最后的模型的参数,方便你以后直接使用这个模型。

好了,现在讨论一下怎么设置参数,具体来说,程序中可以设置的参数包括:学习速率learning_rate、batch_size、n_epochs、nkerns、poolsize。下面逐一讨论调节它们时对模型的影响。

  • 调节learning_rate
学习速率learning_rate就是运用SGD算法时梯度前面的系数,非常重要,设得太大的话算法可能永远都优化不了,设得太小会使算法优化得太慢,而且可能还会掉入局部最优。可以形象地将learning_rate比喻成走路时步子的大小,想象一下要从一个U形的山谷的一边走到山谷最低点,如果步子特别大,像巨人那么大,那会直接从一边跨到另一边,然后又跨回这边,如此往复。如果太小了,可能你走着走着就掉入了某些小坑,因为山路总是凹凸不平的(局部最优),掉入这些小坑后,如果步子还是不变,就永远走不出那个坑。

好,回到本文的模型,下面是我使用时的记录,固定其他参数,调节learning_rate:
(1)kerns=[20, 50], batch_size=40,poolsize=(2,2),learning_rate=0.1时,validation-error一直是97.5%,没降下来,分析了一下,觉得应该是学习速率太大,跳过了最优。

(2)nkerns=[20, 50], batch_size=40,poolsize=(2,2),learning_rate=0.01时,训练到epoch 60多时,validation-error降到5%,test-error降到15%

(3)nkerns=[20, 50], batch_size=40,poolsize=(2,2),learning_rate=0.05时,训练到epoch 36时,validation-error降到2.5%,test-error降到5%

注意,验证集和测试集都只有40张图片,也就是说只有一两张识别错了,还是不错的,数据集再大点,误差率可以降到更小。最后我将learning_rate设置为0.05。

PS:学习速率应该自适应地减小,是有专门的一些算法的,本程序没有实现这个功能,有时间再研究一下。


  • 调节batch_size
因为我们采用minibatch SGD算法来优化,所以是一个batch一个batch地将数据输入CNN模型中,然后计算这个batch的所有样本的平均损失,即代价函数是所有样本的平均。而batch_size就是一个batch的所包含的样本数,显然batch_size将影响到模型的优化程度和速度。


回到本文的模型,首先因为我们train_dataset是320,valid_dataset和test_dataset都是40,所以batch_size最好都是40的因子,也就是能让40整除,比如40、20、10、5、2、1,否则会浪费一些样本,比如设置为30,则320/30=10,余数时20,这20个样本是没被利用的。并且,如果batch_size设置为30,则得出的validation-error和test-error只是30个样本的错误率,并不是全部40个样本的错误率。这是设置batch_size要注意的。特别是样本比较少的时候。


下面是我实验时的记录,固定其他参数,改变batch_size:
batch_size=1、2、5、10、20时,validation-error一直是97.5%,没降下来。我觉得可能是样本类别覆盖率过小,因为我们的数据是按类别排的,每个类别10个样本是连续排在一起的,batch_size等于20时其实只包含了两个类别,这样优化会很慢。

因此最后我将batch_size设为40,也就是valid_dataset和test_dataset的大小了,没办法,原始数据集样本太少了。一般我们都不会让batch_size达到valid_dataset和test_dataset的大小的。


  • 关于n_epochs

n_epochs也就是最大的训练步数,比如设为200,那训练过程最多遍历你的数据集200遍,当遍历了200遍你的dataset时,程序会停止。n_epochs就相当于一个停止程序的控制参数,并不会影响CNN模型的优化程度和速度,只是一个控制程序结束的参数。


  • nkerns=[20, 50]

20表示第一个卷积层的卷积核的个数,50表示第二个卷积层的卷积核的个数。这个我也是瞎调的,暂时没什么经验可以总结。
不过从理论上来说,卷积核的个数其实就代表了特征的个数,你提取的特征越多,可能最后分类就越准。但是,特征太多(卷积核太多),会增加参数的规模,加大了计算复杂度,而且有时候卷积核也不是越多越好,应根据具体的应用对象来确定。所以我觉得,CNN虽号称自动提取特征,免去复杂的特征工程,但是很多参数比如这里的nkerns还是需要去调节的,还是需要一些“人工”的。


下面是我的实验记录,固定batch_size=40,learning_rate=0.05,poolsize=(2,2):

(1)nkerns=[20, 50]时,训练到epoch 36时,validation-error降到2.5%,test-error降到5%

(2)nkerns=[10, 30]时,训练到epoch 46时,validation-error降到5%,test-error降到5%

(3)nkerns=[5, 10]时,训练到epoch 38时,validation-error降到5%,test-error降到7.5%


  • poolsize=(2, 2)


poolzize在本程序中是设置为(2,2),即从一个2*2的区域里maxpooling出1个像素,说白了就算4和像素保留成1个像素。本例程中人脸图像大小是57*47,对这种小图像来说,(2,2)时比较合理的。如果你用的图像比较大,可以把poolsize设的大一点。




+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++分割线+++++++++++++++++++++++++++++++++++++++++++



上面部分介绍完了CNN模型构建以及模型训练的过程,代码都在train_CNN_olivettifaces.py里面,训练完可以得到一个params.pkl文件,这个文件保存的就是最后的模型的参数,方便你以后直接使用这个模型。以后只需利用这些保存下来的参数来初始化CNN模型,就得到一个可以使用的CNN系统,将人脸图输入这个CNN系统,预测人脸图的类别。

接下来就介绍怎么使用训练好的参数的方法,这部分的代码放在use_CNN_olivettifaces.py文件中。




五、利用训练好的参数初始化模型


在train_CNN_olivettifaces.py中的LeNetConvPoolLayer、HiddenLayer、LogisticRegression是用随机数生成器去随机初始化的,我们将它们定义为可以用参数来初始化的版本,其实很简单,代码只需要做稍微的改动,只需要在LogisticRegression、HiddenLayer、LeNetConvPoolLayer这三个class的__init__()函数中加两个参数params_W,params_b,然后将params_W,params_b赋值给这三个class里的W和b:

        self.W = params_W
        self.b = params_b

params_W,params_b就是从params.pkl文件中读取来的,读取的函数:
#读取之前保存的训练参数
#layer0_params~layer3_params都是包含W和b的,layer*_params[0]是W,layer*_params[1]是b
def load_params(params_file):
    f=open(params_file,'rb')
    layer0_params=cPickle.load(f)
    layer1_params=cPickle.load(f)
    layer2_params=cPickle.load(f)
    layer3_params=cPickle.load(f)
    f.close()
    return layer0_params,layer1_params,layer2_params,layer3_params


ok,可以用参数初始化的CNN定义好了,那现在就将需要测试的人脸图输入该CNN,测试其类别。同样的,需要写一个读图像的函数load_data(),代码就不贴了。将图像数据输入,CNN的输出便是该图像的类别,这一部分的代码在use_CNN()函数中,代码很容易看懂。

这一部分还涉及到theano.function的使用,我把一些笔记记在了use_CNN_olivettifaces.py代码的最后,因为跟代码相关,结合代码来看会比较好,所以下面就不讲这部分,有兴趣的看看代码。

最后说说测试的结果,我仍然以整副olivettifaces.gif作为输入,得出其类别后,跟真正的label对比,程序输出被错分的那些图像,运行结果如下:



错了五张,我标了三张:





六、一些需要说明的


首先是本文的严谨性:在文章开头我就说这只是一个toy implement,400张图片根本不适合用DL来做。
当然我写这篇文章,只是为了总结一下这个实现流程,这一点希望对读者也有参考意义。

最后,我的代码都放在这里:github地址,可以下载

欢迎留言交流,有任何错误请不吝指出!


人脸检测深度方法

阅读数 297

没有更多推荐了,返回首页