从0到1实现基于Tornado和Tensorflow的人脸年龄性别识别2.docx

上传人:b****6 文档编号:5618194 上传时间:2022-12-29 格式:DOCX 页数:11 大小:22.22KB
下载 相关 举报
从0到1实现基于Tornado和Tensorflow的人脸年龄性别识别2.docx_第1页
第1页 / 共11页
从0到1实现基于Tornado和Tensorflow的人脸年龄性别识别2.docx_第2页
第2页 / 共11页
从0到1实现基于Tornado和Tensorflow的人脸年龄性别识别2.docx_第3页
第3页 / 共11页
从0到1实现基于Tornado和Tensorflow的人脸年龄性别识别2.docx_第4页
第4页 / 共11页
从0到1实现基于Tornado和Tensorflow的人脸年龄性别识别2.docx_第5页
第5页 / 共11页
点击查看更多>>
下载资源
资源描述

从0到1实现基于Tornado和Tensorflow的人脸年龄性别识别2.docx

《从0到1实现基于Tornado和Tensorflow的人脸年龄性别识别2.docx》由会员分享,可在线阅读,更多相关《从0到1实现基于Tornado和Tensorflow的人脸年龄性别识别2.docx(11页珍藏版)》请在冰豆网上搜索。

从0到1实现基于Tornado和Tensorflow的人脸年龄性别识别2.docx

从0到1实现基于Tornado和Tensorflow的人脸年龄性别识别2

从0到1实现基于Tornado和Tensorflow的人脸、年龄、性别识别

(2)

网址:

年龄识别模型的训练过程

defmain(argv=None):

###一个图中包含有一个名称范围的堆栈,在使用name_scope(...)之后,将压(push)新名称进栈中,

#并在下文中使用该名称

withtf.Graph().as_default():

##这句比较重要选择模型

model_fn=select_model(FLAGS.model_type)

##假设这里选的是默认的,这里我们发现其实作者是实现了inceptionv3、levi_hassner_bn两种模型

##Openthemetadatafileandfigureoutnlabels,andsizeofepoch

##年龄模型的年龄段labes分别是['(0,2)','(4,6)','(8,12)','(15,20)','(25,32)','(38,43)','(48,53)','(60,100)']应该是8个标签12345678910

可以看到,select_model选择了模型,我们以deflevi_hassner(nlabels,images,pkeep,is_training):

为例子,

这个模型的命名是因为GilLeviandTalHassner,AgeandGenderClassificationusing

ConvolutionalNeuralNetworks,IEEEWorkshoponAnalysisandModelingof

FacesandGestures(AMFG),attheIEEEConf.onComputerVisionand

PatternRecognition(CVPR),Boston,June2015这篇文章。

模型的实现源代码

weight_decay=0.0005

weights_regularizer=tf.contrib.layers.l2_regularizer(weight_decay)

withtf.variable_scope("LeviHassner","LeviHassner",[images])asscope:

withtf.contrib.slim.arg_scope(

[convolution2d,fully_connected],

weights_regularizer=weights_regularizer,

biases_initializer=tf.constant_initializer(1.),

weights_initializer=tf.random_normal_initializer(stddev=0.005),

trainable=True):

withtf.contrib.slim.arg_scope(

[convolution2d],

weights_initializer=tf.random_normal_initializer(stddev=0.01)):

conv1=convolution2d(images,96,[7,7],[4,4],padding='VALID',biases_initializer=tf.constant_initializer(0.),scope='conv1')

pool1=max_pool2d(conv1,3,2,padding='VALID',scope='pool1')

norm1=tf.nn.local_response_normalization(pool1,5,alpha=0.0001,beta=0.75,name='norm1')

conv2=convolution2d(norm1,256,[5,5],[1,1],padding='SAME',scope='conv2')

pool2=max_pool2d(conv2,3,2,padding='VALID',scope='pool2')

norm2=tf.nn.local_response_normalization(pool2,5,alpha=0.0001,beta=0.75,name='norm2')

conv3=convolution2d(norm2,384,[3,3],[1,1],biases_initializer=tf.constant_initializer(0.),padding='SAME',scope='conv3')

pool3=max_pool2d(conv3,3,2,padding='VALID',scope='pool3')

flat=tf.reshape(pool3,[-1,384*6*6],name='reshape')

full1=fully_connected(flat,512,scope='full1')

drop1=tf.nn.dropout(full1,pkeep,name='drop1')

full2=fully_connected(drop1,512,scope='full2')

drop2=tf.nn.dropout(full2,pkeep,name='drop2')12345678910111213141516171819202122232425261234567891011121314151617181920212223242526

这是典型的卷积神经网络用于分类的模型结构

L2范数

其中weights_regularizer=tf.contrib.layers.l2_regularizer(weight_decay)

l2_regularizer是L2范数的意思,在《线性代数》《矩阵论中》,我们还了解到有L1范数,那么更受宠幸的规则化范数是L2范数:

||W||2。

它也不逊于L1范数,它有两个美称,在回归里面,有人把有它的回归叫“岭回归”(Ridge

Regression),有人也叫它“权值衰减weightdecay”。

它的强大功效是改善机器学习里面一个非常重要的问题:

过拟合。

至于过拟合是什么,上面也解释了,就是模型训练时候的误差很小,但在测试的时候误差很大,也就是我们的模型复杂到可以拟合到我们的所有训练样本了,但在实际预测新的样本的时候,糟糕的一塌糊涂。

通俗的讲就是应试能力很强,实际应用能力很差。

下面这幅图可以看到过拟合大概是什么状况,绿色线

在上面的图像中有两个不同的类,分别由蓝色和红色圆圈表示。

绿线是过度拟合的分类器。

它完全遵循训练数据,同时也严重依赖于训练数据,并且可能在处理未知数据时比代表正则化模型的黑线表现更差。

因此,我们的正则化目标是得到一个简单的模型,不附带任何不必要的复杂。

我们选择L2-正则化来实现这一点,L2正则化将网络中所有权重的平方和加到损失函数。

如果模型使用大权重,则对应重罚分,并且如果模型使用小权重,则小罚分。

这就是为什么我们在定义权重时使用了regularizer参数,并为它分配了一个l2_regularizer。

这告诉了TensorFlow要跟踪l2_regularizer这个变量的L2正则化项(并通过参数reg_constant对它们进行加权)。

所有正则化项被添加到一个损失函数可以访问的集合——tf.GraphKeys.REGULARIZATION_LOSSES。

将所有正则化损失的总和与先前计算的交叉熵相加,以得到我们的模型的总损失。

理解是:

限制了参数很小,实际上就限制了多项式某些分量的影响很小,这样就相当于减少参数个数,过拟合状况就会被降低。

下面走到withtf.variable_scope(“LeviHassner”,“LeviHassner”,[images])asscope:

可以看到有不少scope,那么它是什么呢?

Tensorflow为了更好的管理变量,提供了variablescope机制,具体参考TensorFlow官方这篇文章

https:

//www.tensorflow.org/programmers_guide/variable_scope

后面又来了个比较复杂的东西tf.contrib.slim,这是什么鬼,看看官方的解释:

TF-Slimisalightweightlibraryfordefining,trainingandevaluating

complexmodelsinTensorFlow.Componentsoftf-slimcanbefreelymixed

withnativetensorflow,aswellasotherframeworks,suchas

tf.contrib.learn.

我们用到的是arg_scope

arg_scope:

providesanewscopenamedarg_scopethatallowsauserto

definedefaultargumentsforspecificoperationswithinthatscope.

卷积神经网络

卷积神经网络(CNN)由输入层、卷积层、激活函数、池化层、全连接层组成,即INPUT-CONV-RELU-POOL-FC

下面终于来到网络层了啊!

来看代码

conv1=convolution2d(images,96,[7,7],[4,4],padding='VALID',biases_initializer=tf.constant_initializer(0.),scope='conv1')

pool1=max_pool2d(conv1,3,2,padding='VALID',scope='pool1')

conv2=convolution2d(pool1,256,[5,5],[1,1],padding='SAME',scope='conv2')

pool2=max_pool2d(conv2,3,2,padding='VALID',scope='pool2')

conv3=convolution2d(pool2,384,[3,3],[1,1],padding='SAME',biases_initializer=tf.constant_initializer(0.),scope='conv3')

pool3=max_pool2d(conv3,3,2,padding='VALID',scope='pool3')

#canusetf.contrib.layer.flatten

flat=tf.reshape(pool3,[-1,384*6*6],name='reshape')

full1=fully_connected(flat,512,scope='full1')

drop1=tf.nn.dropout(full1,pkeep,name='drop1')

full2=fully_connected(drop1,512,scope='full2')

drop2=tf.nn.dropout(full2,pkeep,name='drop2')123456789101112123456789101112

卷积层

卷积层:

用它来进行特征提取,如下:

关于卷积的图解如下:

输入图像和filter的对应位置元素相乘再求和,最后再加上b,得到特征图。

如图中所示,filter

w0的第一层深度和输入图像的蓝色方框中对应元素相乘再求和得到0,其他两个深度得到2,0,则有0+2+0+1=3即图中右边特征图的第一个元素3.,卷积过后输入图像的蓝色方框再滑动,stride=2,如下:

如上图,完成卷积,得到一个3*3*1的特征图;在这里还要注意一点,即zeropad项,即为图像加上一个边界,边界元素均为0.(对原输入无影响)一般有

F=3=>zeropadwith1

F=5=>zeropadwith2

F=7=>zeropadwith3,边界宽度是一个经验值,加上zeropad这一项是为了使输入图像和卷积后的特征图具有相同的维度,如:

输入为5*5*3,filter为3*3*3,在zeropad为1,则加上zeropad后的输入图像为7*7*3,则卷积后的特征图大小为5*5*1((7-3)/1+1),与输入图像一样;

卷积层还有一个特性就是“权值共享”原则。

如下图:

如没有这个原则,则特征图由10个32*32*1的特征图组成,即每个特征图上有1024个神经元,每个神经元对应输入图像上一块5*5*3的区域,即一个神经元和输入图像的这块区域有75个连接,即75个权值参数,则共有75*1024*10=768000个权值参数,这是非常复杂的,因此卷积神经网络引入“权值”共享原则,即一个特征图上每个神经元对应的75个权值参数被每个神经元共享,这样则只需75*10=750个权值参数,而每个特征图的阈值也共享,即需要10个阈值,则总共需要750+10=760个参数。

而关于特征图的大小计算方法具体如下:

第一层是个卷积层convolution2d(images,96,[7,7],[4,4],padding=’VALID’,

biases_initializer=tf.constant_initializer(0.),scope=’conv1’),

tf.contrib.layers.convolution2d(*args,**kwargs)

通过pycharm跟到tensorflow源码,实际是调用了下面这个函数

defconvolution(inputs,

num_outputs,

kernel_size,

stride=1,

padding=’SAME’,

data_format=None,

rate=1,

activation_fn=nn.relu,

normalizer_fn=None,

normalizer_params=None,

weights_initializer=initializers.xavier_initializer(),

weights_regularizer=None,

biases_initializer=init_ops.zeros_initializer(),

biases_regularizer=None,

reuse=None,

variables_collections=None,

outputs_collections=None,

trainable=True,

scope=None):

Returns:

atensorrepresentingtheoutputoftheoperation.

有点难以理解是吧,还是稍微再回顾一下卷积吧!

这个函数很强大,1到3维的卷积都支持。

(这里暂时只用2维)

·inputs:

输入变量,是一个N+2维的Tensor

类型要求是一个Tensor,而我们一般训练的数据都是常量(比如mnist,load以后得到是Python的数据类型,不是tf的),所以需要把用tf的方法做一下转换,比如tf.reshape

为什么是N+2维呢,比如图像,除了宽度和高度,实际上还有样本数量和通道数量(如RGB3通道),所以多了2维。

inputs的格式,由date_format这个参数来觉得,比如2维,有NHWC和NCHW两种。

N是样本数量,H高度,W宽度,C通道数。

·num_outputs:

卷积filter的数量,或者说提取的特征数量,比如5,10

·kernel_size:

卷积核的大小,是N个参数的list,比如二维图像,可以时候[10,10],如果参数值相同,用一个整数来·表示也可以;

·stride:

卷积步长,同样是N个参数的序列,或者都相等的话,用一个整数来表示,默认是1.

·padding:

字符串格式,默认SAME,可选’VALID’。

(我也不知道效果差异怎么样,具体的滤波过程,看下面的图)

·data_format:

字符串,指定inputs的格式

一维数据:

”NWC”(default)and“NCW”

二维数据:

”NHWC”(default)and“NCHW”

三维数据:

”NDHWC”

也就是,不指定的话,通道数都是最后一个参数。

·rate:

asequenceofNpositiveintegersspecifyingthedilationrate

tousefora’trousconvolution.Canbeasingleintegertospecifythe

samevalueforallspatialdimensions.(暂时没看到其作用)

·activation_fn:

激活函数,默认relu

·normalizer_fn:

normalizationfunctiontouseinsteadofbiases.(没用过,不知道起作用)

·normalizer_params:

normalizationfunctionparameters.

·weights_initializer:

这不用说了,有默认值,估计用默认的就可以了。

·weights_regularizer:

Optionalregularizerfortheweights.(防止过拟合)

·biases_initializer:

有默认值,一般也就不用指定。

·biases_regularizer:

·reuse:

whetherornotthelayeranditsvariablesshouldbereused.To

beabletoreusethelayerscope·mustbegiven.

应该都需要reuse吧,所以这个参数默认为True更好,现在是None。

·variables_collections:

怎么用暂时不太明白,但应该不用指定也可以;

·outputs_collections:

同上;

·trainable:

IfTruealsoaddvariablestothegraphcollection

GraphKeys.TRAINABLE_VARIABLES,默认是True。

(这个是不是说在fit的时候需要设为True,evaluate和predict的时候为false?

·scope:

也即是variable_scope,如果用多个卷积层的话,需要设置这个参数,以便把每一次的weight和bias区别出来。

了解更多关于layer的函数说明,访问tensorflow官方网站

https:

//www.tensorflow.org/api_guides/python/contrib.layers

池化层

池化层:

对输入的特征图进行压缩,一方面使特征图变小,简化网络计算复杂度;一方面进行特征压缩,提取主要特征

池化操作一般有两种,一种是AvyPooling,一种是maxPooling,如下:

同样地采用一个2*2的filter,maxpooling是在每一个区域中寻找最大值,这里的stride=2,最终在原特征图中提取主要特征得到右图。

(Avypooling现在不怎么用了,方法是对每一个2*2的区域元素求和,再除以4,得到主要特征),而一般的filter取2*2,最大取3*3,stride取2,压缩为原来的1/4.

注意:

这里的pooling操作是特征图缩小,有可能影响网络的准确度,因此可以通过增加特征图的深度来弥补(这里的深度变为原来的2倍)。

可以用tf.contrib.layers.max_pool2d或者tf.contrib.layers.avg_pool2d

max_pool2d(inputs,kernel_size,stride=2,padding=’VALID’,data_format=DATA_FORMAT_NHWC,outputs_collections=None,scope=None)

inputs:

就是卷积的输出了;

kernel_size:

是不是叫pool_size更贴切。

[kernel_height,kernel_width]或者是一个整数;

stride:

[stride_height,stride_width],不过文档上说目前这两个值必须一样

padding:

这里默认是VALID,和卷积默认不一样

data_format:

注意和卷积用的一样哦;

outputs_collections:

scope:

pooling的时候没有参数,需要scope吗?

reshape

flat=tf.reshape(pool3,[-1,384*6*6],name=’reshape’)

-1,就是缺省值,就是先以你们合适,到时总数除以你们几个的乘积,我该是几就是几。

Reshapeoutputtofitfullyconnectedlayerinput

全连接层

连接所有的特征,将输出值送给分类器(如softmax分类器)。

其实是神经网络中的隐含层。

dropout

drop2=tf.nn.dropout(full2,pkeep,name=’drop2’)

这里的keep_prob是保留概率,即我们要保留的RELU的结果所占比例,tensorflow建议的语法是,让它作为一个placeholder,在run时传入。

大概的意思如下图所示:

dropout一般用在全连接的部分,卷积部分不会用到dropout,输出曾也不会使用dropout,适用范围[输入,输出)

上面只是说了深度学习的网络层,下面讲一下训练方法:

训练方法

logits=model_fn(md['nlabels'],images,1-FLAGS.pdrop,True)

total_loss=loss(logits

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > PPT模板 > 商务科技

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1