Tensorboard可视化:基于LeNet5进行面部表情分类
日期:2021.09.20   来源:湖南检信智能
检信ALLEMOTION

Tensorboard可视化:基于LeNet5进行面部表情分类    

                            

无标题.jpg

面部表情分类

    面部表情是面部肌肉的一个或多个动作或状态的结果。这些运动表达了个体对观察者的情绪状态。面部表情是非语言交际的一种形式。它是表达人类之间的社会信息的主要手段,不过也发生在大多数其他哺乳动物和其他一些动物物种中。人类的面部表情至少有21种,除了常见的高兴、吃惊、悲伤、愤怒、厌恶和恐惧6种,还有惊喜(高兴+吃惊)、悲愤(悲伤+愤怒)等15种可被区分的复合表情。 

    面部表情识别技术主要的应用领域包括人机交互、智能控制、安全、医疗、通信等领域。

网络架构

    LeNet-5出自论文Gradient-Based Learning Applied to Document Recognition,是一种用于手写体字符识别的非常高效的卷积神经网络。LeNet5的网络架构如下:

    但是因为我们要做的是面部表情分类,而且CK+数据集样本大小是48*48,因此需要对LeNet5网络进行微调。网络架构如下:

image.png

    网络结构如下:

layer.jpg

计算图如下:

graph.jpg

代码实现

预处理

    数据集加载,并进行预处理,同时将测试集的前225张样本拼接成15张*15张的大图片,用于Tensorboard可视化。

%matplotlib inline
import matplotlib.pyplot as plt
import os
import cv2
import numpy as np
from tensorflow import name_scope as namespace
from tensorflow.contrib.tensorboard.plugins import projector
 
NUM_PIC_SHOW=225
base_filedir='D:/CV/datasets/facial_exp/CK+'
 
dict_str2int={'anger':0,'contempt':1,'disgust':2,'fear':3,'happy':4,'sadness':5,'surprise':6}
 
labels=[]
data=[]
 
#读取图片并将其保存至data
for expdir in os.listdir(base_filedir):
    base_expdir=os.path.join(base_filedir,expdir)
    for name in os.listdir(base_expdir):
        labels.append(dict_str2int[expdir])
        path=os.path.join(base_expdir,name)
        path=path.replace('\\','/') #将\替换为/
        img = cv2.imread(path,0)
        data.append(img)
 
data=np.array(data)
labels=np.array(labels)
 
#将data打乱
permutation = np.random.permutation(data.shape[0])
data = data[permutation,:,:]
labels = labels[permutation]
 
#取前225个图片拼成一张大图片,用于tensorboard可视化
img_set=data[:NUM_PIC_SHOW]#前225的数据用于显示
label_set=labels[:NUM_PIC_SHOW]
big_pic=None
index=0
for row in range(15):
    row_vector=img_set[index]
    index+=1
    for col in range(1,15):
        img=img_set[index]
        row_vector=np.hstack([row_vector,img])
        index+=1
    if(row==0):
        big_pic=row_vector
    else:
        big_pic=np.vstack([big_pic,row_vector])
 
plt.imshow(big_pic, cmap='gray')
plt.show()
 
#写入大图片
cv2.imwrite("D:/Jupyter/TensorflowLearning/facial_expression_cnn_projector/data/faces.png",big_pic)
 
#转换数据格式和形状
data=data.reshape(-1,48*48).astype('float32')/255.0
labels=labels.astype('float32')
 
#0.3的比例测试
scale=0.3
test_data=data[:int(scale*data.shape[0])]
test_labels=labels[:int(scale*data.shape[0])]
train_data=data[int(scale*data.shape[0]):]
train_labels=labels[int(scale*data.shape[0]):]
 
print(train_data.shape)
print(train_labels.shape)
print(test_data.shape)
print(test_labels.shape)
 
#将标签one-hot
train_labels_onehot=np.zeros((train_labels.shape[0],7))
test_labels_onehot=np.zeros((test_labels.shape[0],7))
 
for i,label in enumerate(train_labels):
    train_labels_onehot[i,int(label)]=1
for i,label in enumerate(test_labels):
    test_labels_onehot[i,int(label)]=1
 
print(train_labels_onehot.shape)
print(test_labels_onehot.shape)
2.定义前向网络

import tensorflow as tf
 
IMAGE_SIZE=48 #图片大小
NUM_CHANNELS=1 #图片通道
CONV1_SIZE=5 
CONV1_KERNEL_NUM=32
CONV2_SIZE=5
CONV2_KERNEL_NUM=64
FC_SIZE=512 #隐层大小
OUTPUT_NODE=7 #输出大小
 
#参数概要,用于tensorboard实时查看训练过程
def variable_summaries(var):
    with namespace('summaries'):
        mean=tf.reduce_mean(var)
        tf.summary.scalar('mean',mean) #平均值
        with namespace('stddev'):
            stddev=tf.sqrt(tf.reduce_mean(tf.square(var-mean)))
        tf.summary.scalar('stddev',stddev) #标准差
        tf.summary.scalar('max',tf.reduce_max(var))#最大值
        tf.summary.scalar('min',tf.reduce_min(var))#最小值
        tf.summary.histogram('histogram',var)#直方图
 
#获取权重
def get_weight(shape,regularizer,name=None):
    w=tf.Variable(tf.truncated_normal(shape,stddev=0.1),name=name)
    #variable_summaries(w)
    if(regularizer!=None):
        tf.add_to_collection('losses',tf.contrib.layers.l2_regularizer(regularizer)(w))
    return w
 
#获取偏置
def get_bias(shape,name=None):
    b=tf.Variable(tf.zeros(shape),name=name)
    #variable_summaries(b)
    return b
    
#定义前向网络
def forward(x,train,regularizer):
    with tf.name_scope('layer'):
        #把输入reshape
        with namespace('reshape_input'):
            x_reshaped=tf.reshape(x,[-1,IMAGE_SIZE,IMAGE_SIZE,NUM_CHANNELS])
        with tf.name_scope('conv1'):
            #定义两个卷积层
            conv1_w=get_weight([CONV1_SIZE,CONV1_SIZE,NUM_CHANNELS,CONV1_KERNEL_NUM],regularizer=regularizer,name='conv1_w')
            conv1_b=get_bias([CONV1_KERNEL_NUM],name='conv1_b')
            conv1=tf.nn.conv2d(x_reshaped,conv1_w,strides=[1,1,1,1],padding='SAME')
            relu1=tf.nn.relu(tf.nn.bias_add(conv1,conv1_b))
            pool1=tf.nn.max_pool(relu1,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')
            
        with tf.name_scope('conv2'):
            conv2_w=get_weight([CONV2_SIZE,CONV2_SIZE,CONV1_KERNEL_NUM,CONV2_KERNEL_NUM],regularizer=regularizer,name='conv2_w')
            conv2_b=get_bias([CONV2_KERNEL_NUM],name='conv2_b')
            conv2=tf.nn.conv2d(pool1,conv2_w,strides=[1,1,1,1],padding='SAME')
            relu2=tf.nn.relu(tf.nn.bias_add(conv2,conv2_b)) #对卷机后的输出添加偏置,并通过relu完成非线性激活
            pool2=tf.nn.max_pool(relu2,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')
            
        with tf.name_scope('flatten'):
            #定义reshape层
            pool_shape=pool2.get_shape().as_list() #获得张量的维度并转换为列表
            nodes=pool_shape[1]*pool_shape[2]*pool_shape[3] #[0]为batch值,[1][2][3]分别为长宽和深度
            #print(type(pool2))
            reshaped=tf.reshape(pool2,[-1,nodes])
        
        with tf.name_scope('fc1'):
            #定义两层全连接层
            fc1_w=get_weight([nodes,FC_SIZE],regularizer,name='fc1_w')
            fc1_b=get_bias([FC_SIZE],name='fc1_b')
            fc1=tf.nn.relu(tf.matmul(reshaped,fc1_w)+fc1_b)
            if(train):
                fc1=tf.nn.dropout(fc1,0.5)
    
        with tf.name_scope('fc2'):
            fc2_w=get_weight([FC_SIZE,OUTPUT_NODE],regularizer,name='fc2_w')
            fc2_b=get_bias([OUTPUT_NODE],name='fc2_b')
            y=tf.matmul(fc1,fc2_w)+fc2_b
    return y
3.定义反向传播 ,可视化设置,并进行训练,

BATCH_SIZE=100 #每次样本数
LEARNING_RATE_BASE=0.005 #基本学习率
LEARNING_RATE_DECAY=0.99 #学习率衰减率
REGULARIZER=0.0001 #正则化系数
STEPS=2500 #训练次数
MOVING_AVERAGE_DECAY=0.99 #滑动平均衰减系数
 
SAVE_PATH='.\\facial_expression_cnn_projector\\' #参数保存路径
data_len=train_data.shape[0]
 
#将拼接为big_pic的测试样本保存至标量,用于训练过程可视化
pic_stack=tf.stack(test_data[:NUM_PIC_SHOW]) #stack拼接图片张量
embedding=tf.Variable(pic_stack,trainable=False,name='embedding')
 
if(tf.gfile.Exists(os.path.join(SAVE_PATH,'projector'))==False):
    tf.gfile.MkDir(os.path.join(SAVE_PATH,'projector'))
 
#创建metadata文件,存放可视化图片的label
if(tf.gfile.Exists(os.path.join(SAVE_PATH,'projector','metadata.tsv'))==True):
    tf.gfile.DeleteRecursively(os.path.join(SAVE_PATH,'projector'))
    tf.gfile.MkDir(os.path.join(SAVE_PATH,'projector'))
#将可视化图片的标签写入
with open(os.path.join(SAVE_PATH,'projector','metadata.tsv'),'w') as f:
    for i in range(NUM_PIC_SHOW):
        f.write(str(label_set[i])+'\n')
 
with tf.Session() as sess:
    with tf.name_scope('input'):
        #x=tf.placeholder(tf.float32,[BATCH_SIZE,IMAGE_SIZE,IMAGE_SIZE,NUM_CHANNELS],name='x_input')
        x=tf.placeholder(tf.float32,[None,IMAGE_SIZE*IMAGE_SIZE*NUM_CHANNELS],name='x_input')
        y_=tf.placeholder(tf.float32,[None,OUTPUT_NODE],name='y_input')
    
    #reshape可视化图片
    with namespace('input_reshape'):
        image_shaped_input=tf.reshape(x,[-1,IMAGE_SIZE,IMAGE_SIZE,1]) #把输入reshape
        tf.summary.image('input',image_shaped_input,7) #添加到tensorboard中显示
    
    y=forward(x,True,REGULARIZER)
    
    global_step=tf.Variable(0,trainable=False)
    with namespace('loss'):
        #softmax并计算交叉熵
        ce=tf.nn.sparse_softmax_cross_entropy_with_logits(logits=y,labels=tf.argmax(y_,1))
        cem=tf.reduce_mean(ce) #求每个样本的交叉熵
        loss=cem+tf.add_n(tf.get_collection('losses'))
        tf.summary.scalar('loss',loss) #loss只有一个值,就直接输出
    
    learning_rate=tf.train.exponential_decay(
        LEARNING_RATE_BASE,
        global_step,
        data_len/BATCH_SIZE,
        LEARNING_RATE_DECAY,
        staircase=True
    )
    with namespace('train'):
        train_step=tf.train.GradientDescentOptimizer(learning_rate).minimize(loss,global_step=global_step)
        ema=tf.train.ExponentialMovingAverage(MOVING_AVERAGE_DECAY,global_step)
        ema_op=ema.apply(tf.trainable_variables())
    
    with namespace('accuracy'):
        correct_prediction=tf.equal(tf.argmax(y,1),tf.argmax(y_,1))
        accuracy=tf.reduce_mean(tf.cast(correct_prediction,tf.float32))
        tf.summary.scalar('accuracy',accuracy)
    
    with tf.control_dependencies([train_step,ema_op]):
        train_op=tf.no_op(name='train')
    
    init_op=tf.global_variables_initializer()
    sess.run(init_op)
    
    #合并所有的summary
    merged=tf.summary.merge_all()
    #写入图结构
    writer=tf.summary.FileWriter(os.path.join(SAVE_PATH,'projector'),sess.graph)
    saver=tf.train.Saver() #保存网络的模型
    #配置可视化
    config=projector.ProjectorConfig() #tensorboard配置对象
    embed=config.embeddings.add() #增加一项
    embed.tensor_name=embedding.name #指定可视化的变量
    embed.metadata_path='D:/Jupyter/TensorflowLearning/facial_expression_cnn_projector/projector/metadata.tsv' #路径
    embed.sprite.image_path='D:/Jupyter/TensorflowLearning/facial_expression_cnn_projector/data/faces.png' 
    embed.sprite.single_image_dim.extend([IMAGE_SIZE,IMAGE_SIZE])#可视化图片大小
    projector.visualize_embeddings(writer,config)
    #断点续训
    #ckpt=tf.train.get_checkpoint_state(MODEL_SAVE_PATH)
    #if(ckpt and ckpt.model_checkpoint_path):
    #    saver.restore(sess,ckpt.model_checkpoint_path)
    for i in range(STEPS):
        run_option=tf.RunOptions(trace_level=tf.RunOptions.FULL_TRACE)
        run_metadata=tf.RunMetadata()
        start=(i*BATCH_SIZE)%(data_len-BATCH_SIZE)
        end=start+BATCH_SIZE
        summary,_,loss_value,step=sess.run([merged,train_op,loss,global_step],
                                           feed_dict={x:train_data[start:end],y_:train_labels_onehot[start:end]},
                                           options=run_option,
                                           run_metadata=run_metadata)
        writer.add_run_metadata(run_metadata,'step%03d'%i)
        writer.add_summary(summary,i)#写summary和i到文件
        if(i%100==0):
            acc=sess.run(accuracy,feed_dict={x:test_data,y_:test_labels_onehot})
            print('%d %g'%(step,loss_value))
            print('acc:%f'%(acc))
            saver.save(sess,os.path.join(SAVE_PATH,'projector','model'),global_step=global_step)
    writer.close()

可视化训练过程

acc_loss.jpg

    执行上面的代码,打开tensorboard,可以看到训练精度和交叉熵损失如下:

    由于只有六百多的训练样本,故得到曲线抖动很大,训练精度大概在百分之八九十多浮动,测试精度在百分之七八十浮动,可见精度不高。下面使用Tensorboard将训练过程可视化(图片是用Power Point录频 然后用迅雷应用截取gif得到的):

   

————————————————
版权声明:本文为CSDN博主「陈建驱」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。


相关推荐
  • 检信智能圆满完成第84届中国教育装备展示会的参展工作
    检信智能圆满完成第84届中国教育装备展示会的参展工作 第84届中国教育装备展示会于2024年10月25日至27日在昆明滇池国际会展中心举办,本次展示会全面展示了科技创新成果在学前教育、基础教育、职业教育、特殊教育和高等教育领域的应用,包括实验室设备、信息化设备及教学软件、功能/学科教室设备,AI心理测评、音体美设备等,涵盖教育领域各个应用场景。参展的国家级高新技术企业有255家,占参展企业总数的33%。 检信ALLEMOTION 多维度心理情绪测评系统依托机器红外视觉识别技术采集人脸视频数据,结合心理计算大模型及深度学习神经网络架构,预测筛查学生心理健康预警及建立学生心理健康档案管理系统。通过本次展会与广大客户群体深入交流学习,获得了很多用户意见及认同,对我们检信品牌AI心理情绪识别具有很大的价值与作用。 湖南检信智能科技有限公司成立于2016年,是一家专注于语音情绪识别,人脸表情识别,面筛情绪识别,眼动情绪识别等核心自主知识产权技术开发的人工智能型企业,并结合湘雅医学院心理专家团队心理情绪分类模型,首创检信 Allemotion OS心理情绪开发平台, 应用开发有多维度AI心理测评系统、岗前安全评测系统和心理意图分析系统等主导产品。 检信智能聚焦于心理情绪技术的开发与应用,经过8年的企业创新发展历程,累计申请国家发明专利17项,2019年获得武器装备质量管理体系认证,2021年获得国防科大国科平台优秀创新奖,2022年非接触式无创伤心理情绪监测核心技术荣获国家科技部发明创新创业成果二等奖,2023年荣获国家高新技术企业。
    2024-10-31
  • 中国心理学会心理测量专业委员会2024年学术年会第一轮通知
    中国心理学会心理测量专业委员会2024年学术年会第一轮通知心理测量专委会中国心理学会2024年10月21日 09:01北京在人工智能时代,心理测量与测验领域历经了显著的变革和发展。人工智能技术(如机器学习、大数据分析等)已经被广泛用于心理测量指标的开发、心理测验工具的研制及优化。人工智能在心理测量与测验领域的应用,不仅提高了心理测量与测验的准确性和效率,还为心理测量与测验的创新和转型提供了新的可能性。中国心理学会心理测量专业委员会2024年学术年会定于2024年12月13日至12月15日在贵州省贵阳市召开。本次学术年会的主题为“人工智能时代的心理测量与测验”,会议将重点探讨人工智能时代下心理测量与测验的新趋势、新动向和新发展。大会将邀请心理学、教育学、统计学、计算机科学等领域的专家做大会主旨报告,系统介绍心理测量与测验的前沿方法、技术及应用成果。热忱欢迎各位学界同仁和研究生前来参会。一会议主题人工智能时代的心理测量与测验二会议组织机构主办单位:中国心理学会心理测量专业委员会、贵州师范大学承办单位:贵州师范大学心理学院协办单位:凯里学院、贵州省社会心理学学会顾问:车宏生、余嘉元、戴海琦大会主席:赵守盈学术委员会:张敏强(主任)、甘怡群(副主任)、董圣鸿、傅根跃、王力、黎坚、曾平飞、涂东波、骆方组织委员会:方平(主任)、徐建平(副主任)、罗峥、卞冉、陈海平、程超、杜林致、李英武、李中权、彭恒利、孙健敏、董长江、王蕾、肖玮、谢晶、闫巩固、张颖执行委员会:罗禹(主任)、陈维、罗杰、程刚、曾练平、高旭亮、刘国庆、赵鹏娟、许爽、裴子钊、姚成奎三会议时间、地点和日程安排1.会议时间:2024年12月13日至12月15日。13日全天报到,14-15日正式会议。2.会议地点:贵州省贵安新区花溪大学城贵州师范大学东校区。3.会议日程:日程安排简表见附件,具体日程在第二轮通知中公布。四论文投稿本次年会设主旨报告、分组报告、研究生论坛等环节,欢迎国内外专家学者、同学及各界人士踊跃投稿。1.投稿截止日期:2024年11月30日。2.投稿提交方式:会议摘要请发送至邮箱psychometric2024@163.com。提交时邮件主题及投稿文档请命名为“×××(第一作者姓名)参加心理测量专业委员会2024年学术会议摘要”。3.摘要写作格式要求如下:(1)语言为中文或英文,中文用宋体小四号字,1.5倍行距;英文用Time New Roman 字体小四号字,不超过800字。1.5倍行距。(2)论文摘要内容要求包括论文题目、作者姓名、作者单位全称、电子邮箱地址、联系电话、摘要全文(其中,关键词3~6个,之间用逗号分开)。五会议注册缴费1.会议注册费标准:参会代表1000元,中国心理学会在册普通会员800元,在读全日制学生(凭学生证)500元,中国心理学会在册学生会员400元。2.本次会议由中国心理学会收费并开具发票,具体缴纳方式在第二轮通知中公布。3.参会代表在会议期间的交通费和住宿费均自理。六参展单位邀请诚邀相关学术界与产业界人士参加本次会议,热忱欢迎相关企业和研发机构参会,共同推动心理测量与测验的研究及应用发展。请有意参展的单位于12月6日前发送邮件至psychoassessment@163.com或联系罗老师(电话:18786670954),邮件主题“心理测量与测验年会参展”,请附单位基本情况介绍、相关业务说明等。七会务组联系方式陈维(贵州师范大学),15285959353罗杰(贵州师范大学),18786670954罗峥(专委会秘书处),13661135915中国心理学会心理测量专业委员会贵州师范大学2024年10月21日
    2024-10-21
  • 中国心理学会眼动心理研究专业委员会2024年学术年会第一轮通知
    中国心理学会眼动心理研究专业委员会2024年学术年会第一轮通知眼动心理专委会中国心理学会2024年10月20日 09:02北京中国心理学会眼动心理研究专业委员会2024年学术年会拟于2024年12月21日-22日在河南新乡举行。本次会议由中国心理学会眼动心理研究专业委员会主办,由河南师范大学教育学部承办,河南省心理学会、河南大学心理学院、信阳师范大学教育科学学院心理学系协办。诚挚邀请眼动研究相关领域的科研工作者及社会各界人士参加本次大会。一、会议主题数智时代眼动追踪助力教育强国建设二、会议组织机构主办单位:中国心理学会眼动心理研究专业委员会承办单位:河南师范大学教育学部协办单位:河南省心理学会、河南大学心理学院、信阳师范大学教育科学学院心理学系主 席:白学军(中国心理学会眼动心理研究专业委员会主任)副主席:陈庆荣(中国心理学会眼动心理研究专业委员会副主任)马国杰(中国心理学会眼动心理研究专业委员会副主任)闫国利(中国心理学会眼动心理研究专业委员会副主任)秘 书:张慢慢学术委员会(按姓氏拼音排序):陈黎静、陈栩茜、陈中廷、崔磊、丁锦红、高晓雷、高笑、高在峰、谷璜、顾俊娟、韩海宾、侯友、胡笑羽、贾磊、贾宁、江新、姜英杰、康廷虎、李兴珊、梁菲菲、梁竹苑、林楠、刘萍萍、鹿士义、彭微微、屈青青、申薇、隋雪、谭滢滢、仝文、王福兴、王敬欣、魏玲、闻素霞、吴岩、熊建萍、杨海波、杨锦绵、药盼盼、臧传丽、张锦坤、张慢慢、张运红、周钧毅、周蕾会议筹备组:罗红艳(组长)、陈勇(组长)、苗学杰、康淑霞、肖广军、衡书鹏、刘小先、全金梁、张晓阳、熊建萍、孙文梅、张振、张炀、张利会、党清秀、李双双、张瑞、李云云等三、会议时间、地点及日程安排1.会议时间:2024年12月21日至12月22日2.会议地点:河南师范大学(河南省新乡市建设东路46号)3.主要日程:12月20日,全天报到。12月21-22日,开幕式、大会报告、分组报告、闭幕式。四、会议征稿1.征文主题本次会议征文涉及借助眼动技术开展的相关研究,主题涵盖但不限于眼动控制机制、语言加工、场景知觉、社会发展、跨文化研究、特殊群体发展、人因工程、广告/消费心理、驾驶行为和运动心理等。邀请国内外专家学者分享最新的研究成果,共同研讨如何采用眼动追踪技术进行理论与行为研究。2.投稿要求本次会议将设主题报告、分组报告等学术交流环节,欢迎专家学者、老师、同学及各界人士踊跃投稿。会议摘要以电子文稿形式提交,具体写作格式要求如下:(1)会议摘要语言为中文或英文,以Microsoft Word编辑。中文用宋体5号字,不超过800字。英文用Times New Roman字体5号字,不超过800字。单倍行距。(2)摘要内容要求包括:摘要题目、作者姓名、作者通讯地址(含单位全称、院系部门、所在城市、邮政编码)、电子邮箱地址、联系电话、摘要全文(其中,关键词3至6个,之间用逗号分开)。扫描下方二维码查看摘要格式。请将论文摘要电子word文档发至会务组专用邮箱hnupsycho@126.com。邮件主题及投稿文档命名为“×××(第一作者姓名)参加眼动专委会2024学术会议摘要”等字样。投稿截止日期:2024年12月10日。3.欢迎专家学者组织会前/会后工作坊,有意组织工作坊的老师请与会务组联系商议。五、会务事项1.参会人员欢迎中国心理学会眼动心理研究专业委员会委员、中国心理学会其他分支机构的专家学者、高等院校和研究机构的教师、研究生以及社会各界人士等参会。2.注册缴费(1)会议注册费标准:中国心理学会在册普通会员1000元,非中国心理学会会员1200元,中国心理学会在册学生会员500元,在读全日制学生(凭学生证)600元。(2)本次会议由中国心理学会收费并开具发票,缴费方式详见第二轮通知。(3)参会者会议期间的往返交通费和住宿费自理。六、会务组联系方式联系人:刘小先(河南师范大学),13569853542张振(河南师范大学),17737355922张炀(河南师范大学),17537417138联系邮箱:hnupsycho@126.com中国心理学会眼动心理研究专业委员会2024年10月20日
    2024-10-21