TensorFlow实现多层感知机及可视化训练过程中的数据记录

说明(what)

本篇博客主要有2个目的,第一,记录学习使用TensorFlow的操作流程;第二,将TensorFlow训练数据模型过程中的参数数据进行可视化记录。

具体操作(how)

实例描述

1.使用TensorFlow搭建一个3层的神经网络(输入层,隐藏层,输出层)的模型训练经典的MNIST数据集,从而来预测手写体数字。
2.训练过程中使用TensorBoard来可视化训练过程中参数数据
实例的Github代码地址

TensorFlow代码实现

Step1 导入响应的库和加载数据集

1
2
3
4
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
#以独热编码的方式加载数据集
mnist = input_data.read_data_sets('./MNIST_data/',one_hot=True)

Step2 模型相关的参数设置
将模型相关的可能会变化的参数提前设置出来,方便后面统一更改

1
2
3
4
5
6
7
8
9
10
11
in_unit = 784
h1_unit = 300

learningrate = 0.05 # 梯度下降法学习率
dropout_keep_prob = 0.75 # dropout时保留神经元的比例,神经网络不为0的参数变为原理的1/dropout_keep_prob倍

batch_size = 100 # 梯度下降法选取的batch的size
max_iter = 3000 # 迭代次数

sava_dir = '../data/' # 存放数据结果
log_dir = '../log/' # 日志目录

Step3 设置TensorFlow中的计算图

  1. TensorFlow启动session运行节点操作时,先设置好TensorFlow计算图,有利于全局把控计算图中的所有的节点操作。(TensorFlow中的计算图包括节点和边,其中节点为运算操作,而边代表数据的流动即张量,但是一些边没有数据流动表示节点运算操作之间的依赖关系;TensorFlow中的节点操作运行需要通过Session会话来启动,使用session.run()或节点操作对象调用eval()
  2. tf.placeholderTensorFlow中的占位符,作为外部数据(包括数据集和其他一些模型参数)的输入占位,当运行节点操作时候需要设置feed_dict参数来对占位符数据进行填充。
  3. 见下面NO3说明部分
  4. 在第一层隐藏层的输出后使用tf.nn.dropout再加了一层dropout
  5. 模型训练优化器选用的是AdamOptimizerloss函数是交叉熵,使用的是tf自带的tf.nn.softmax_cross_entropy_with_logits来计算真实值和预测值的交叉熵
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    tf.reset_default_graph()
    train_graph = tf.Graph()
    with train_graph.as_default():
    # step 3.1 设置算法模型中的输入,使用占位符,占用输入的数据(什么情况下使用占位符,什么情况下设置tf变量)
    train_x = tf.placeholder(dtype=tf.float32,shape=[None,in_unit],name = 'train_x')
    train_y = tf.placeholder(dtype=tf.float32,shape=[None,10],name = 'train_y')

    # step 3.2构造神经网络
    # 创建第一层隐藏层
    hidden_layer1 = nn_layer(train_x,input_dim=in_unit,output_dim=h1_unit,layer_name='hider_layer1',act=tf.nn.relu)

    #在第一层隐藏层上创建一层 dropout层 —— 随机关闭一些hidden_layer1的神经元
    with tf.name_scope('dropout'):
    dropout_prob = tf.placeholder(dtype=tf.float32, name='dropout_prob')
    tf.summary.scalar('dropout_keep_probability',dropout_prob)
    hidden_layer1_dropout = tf.nn.dropout(hidden_layer1,dropout_prob)

    #创建输出层,包括10个类别,输出层的输入是hidden_layer1_dropout,输出是[1,10]
    y = nn_layer(hidden_layer1_dropout,h1_unit,10,layer_name='out_layer',act=tf.identity)

    # step 3.3 创建损失函数
    with tf.name_scope('loss'):
    cross_entropy_diff = tf.nn.softmax_cross_entropy_with_logits(labels=train_y, logits=y)

    with tf.name_scope('total'):
    cross_entropy = tf.reduce_mean(cross_entropy_diff)
    tf.summary.scalar('loss', cross_entropy)

    # step 3.4 选择优化器训练并设计计算准确率的节点
    optimizer = tf.train.AdamOptimizer(learning_rate=learningrate)
    train_op = optimizer.minimize(cross_entropy)

    with tf.name_scope('accuracy'):
    with tf.name_scope('correct_prediction'):
    correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(train_y, 1))
    with tf.name_scope('accuracy'):
    accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
    tf.summary.scalar('accuracy', accuracy)

NO3: 其中构建单层神经网络的操作封装于函数nn_layer,返回一个Tensor对象。weight_variable函数和bias_variable函数中使用tf.Variable来初始化网络层中对应的权重w和偏置项b. 其中tf.matmul(input_tensor,weight)+bias是该层网络的所有神经元的wx+b的向量表示,表示神经元的输入—g(wx+b),其中g为激活函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
def nn_layer(input_tensor,input_dim,output_dim,layer_name,act=tf.nn.relu):
"""
建立神经网络层(一层),并返回该层网络层的输出的tensor对象
:param input_tensor:特征数据
:param input_dim:输入数据的维度大小
:param output_dim:该层神经元的个数
:param layer_name:命名空间
:param act:神经元对应的激活函数
"""
#设置命名空间
with tf.name_scope(layer_name):
#初始化权重,并记录权重变化
with tf.name_scope('weights'):
weight = weight_variable([input_dim,output_dim])
variable_summeries(weight)# 记录权重变化

with tf.name_scope('bias'):
bias = bias_variable([output_dim])
variable_summeries(bias)

with tf.name_scope('linear_compute'):
preact = tf.matmul(input_tensor,weight)+bias
tf.summary.histogram('linear',preact)

activeation = act(preact,name = 'activation')
tf.summary.histogram('activation',activeation)

return activeation
def weight_variable(shape):
"""
将每一层的神经网络的对应的权重参数w,初始化并封装到function中
"""
inita_w = tf.truncated_normal(shape,stddev=0.1)
return tf.Variable(inita_w,dtype=tf.float32)
def bias_variable(shape):
"""
将每一层的神经网络的对应的偏置项b,初始化并封装到function中
"""
inita_b = tf.constant(0.1,shape=shape)
return tf.Variable(inita_b)

Step4 启动TensorFlow Session来实现计算图中的训练操作并将相应的Summary记录到日志文件
1.初始化Session并设置Session对应的计算图,初始化TensorFlow的变量操作 tf.global_variables_initializer().run()

  1. 计算图中的节点运行方式有两种,方式一:session.run(),函数中设置好计算图中对应的节点操作,如session.run([train_op,cross_entropy,accuracy])其中train_op表示运行模型训练的操作,cross_entropy表示运行获取训练模型交叉熵的操作,accuracy表示获取模型运行的准确率操作,run函数返回的节点操作运行的对应结果。方式二,在tf.InteractiveSession初始化session情况下可以使用oper.eval()来运行操作,如train_op.eval()。该方式一次只能运行一个节点操作。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    session = tf.InteractiveSession(graph=train_graph)
    # step 4.1 合并summary并初始化所有变量
    merged = tf.summary.merge_all()
    train_writer = tf.summary.FileWriter(log_dir+'/train',graph=train_graph)
    test_writer = tf.summary.FileWriter(log_dir+'/test',graph=train_graph)

    tf.global_variables_initializer().run()

    # Step 4.2 训练模型并记录到TensorBoard
    for iter in range(max_iter):
    trainx_batch_x,train_batch_y = mnist.train.next_batch(batch_size)
    #迭代10次记录一下accuracy
    if iter % 10 == 0:
    summmary,acc,loss = session.run([merged,accuracy,cross_entropy],feed_dict={train_x:trainx_batch_x,train_y:train_batch_y,dropout_prob:1.0})
    test_writer.add_summary(summmary,iter)#写入日志
    print('loss at step %s: %s'%(iter,loss))
    print('Accuracy at step %s: %s'%(iter,acc))
    else:
    if iter % 100 == 0:
    #记录tensor运行节点的信息
    run_options = tf.RunOptions(trace_level=tf.RunOptions.FULL_TRACE)
    run_metadata = tf.RunMetadata()
    #将配置信息和记录运行信息的proto传入运行的过程,从而记录运行时每一个节点的时间、空间开销信息
    summmary,_ = session.run([merged,train_op],
    feed_dict={train_x:trainx_batch_x,train_y:train_batch_y,dropout_prob:dropout_keep_prob},
    options=run_options,
    run_metadata=run_metadata)
    #将节点运行时的信息写入日志文件
    train_writer.add_run_metadata(run_metadata,'step %d' % iter)
    train_writer.add_summary(summmary,iter)
    pass
    else:
    summmary,_ = session.run([merged,train_op],feed_dict={train_x:trainx_batch_x,train_y:train_batch_y,dropout_prob:dropout_keep_prob})
    train_writer.add_summary(summmary,iter)
    train_writer.close()
    test_writer.close()
    session.close()

TensorBoard可视化过程

TensorBoard能记录的数据类型为:
数据类型
标量:SCALARS
图片:IMAGES
音频:AUDIO
计算图:GRAPHS
数据分布图:DISTRIBUTIONS
直方图:HISTOGRAMS
嵌入向量:EMBEDDINGS
对上述数据的记录方式有:

1
2
3
4
5
6
tf.summary.audio(name, tensor)
tf.summary.scalar(name,tensor)
tf.summary.image(name, tensor)
tf.summary.histogram(name, tensor)
#其中name表示生成的节点的名称。 也将作为TensorBoard中的一个系列名称。tensor为要记录的数据。
#其中嵌入向量EMBEDDINGS的可视化,需要依赖于模型的保存,需要定义tf.train.Saver对象,再配置projector.ProjectorConfig对象。

基本可视化步骤(摘自其他博客):
1.建立一个Graph计算图,即想从该计算图中记录某些数据的信息并可视化。
代码实现中的 Step 3 中的代码 为建立计算图的过程。
train_graph = tf.Graph()
2.确定要在Graph计算图中的哪些节点放置Summary Operations以用来记录信息。
其中tf.name_scope(name)为给节点设置上下文,可以理解为节点的文件夹管理,一层包含一层的关系
Step 3设计计算图中的建立神经网络的代码:

1
2
3
4
#记录其中交叉熵的值
tf.summary.scalar('loss', cross_entropy)
#记录激活函数层的输出值
tf.summary.histogram('activation',activeation)

3.计算图中设计的Summary Operations并不会真正去执行计算记录,需要使用Session中的run去执行,或者被其他操作节点依赖执行。在TensorFlow代码实现Step中创建的Summary Operations没有被其他节点依赖,需要特地去运行Summary节点操作。Step 4 中通过代码merged = tf.summary.merge_all() 将所有的Summary Operations合并成一个节点,从而直接run该节点即可,也可以通过代码tf.summary.merge(input_list),合并指定的一些Summary Operations成一个节点再run
4.使用tf.summary.FileWriter 将运行后输出的数据都保存到本地磁盘中。
Step 4 中的代码

1
2
#graph参数为指定要获取数据信息的计算图,对应着第一步。
train_writer = tf.summary.FileWriter(log_dir+'/train',graph=train_graph)

  1. 运行整个程序,并在终端输入运行TensorBoard的指令,再打开web端查看可视化的结果
    命令:tensorboard --logdir='./ML/log/'
    tensorboard命令
    打开对应的网址 http://0.0.0.0:6006/
-------------本文结束感谢您的阅读-------------

本文标题:TensorFlow实现多层感知机及可视化训练过程中的数据记录

文章作者:ComeOnJian

发布时间:2018年03月02日 - 16:03

最后更新:2018年04月12日 - 18:04

原始链接:https://jianwenjun.xyz/2018/03/02/TensorFlow实现多层感知机及可视化训练过程中的数据记录/

许可协议: 转载请保留原文链接及作者。

显示 Gitment 评论