使用tensorflow实现神经网络

1 神经网络简介

一句话概括tensorflow对神经网络的实现方式:用张量表示数据,用计算图搭建神经网络,用会话执行计算图,优化线上的权重(参数)得到模型,并使用该模型进行预测

使用神经网络解决分类问题的主要步骤:

1. 提取特征向量作为输入
2. 定义神经网络结构,得到输出
3. 通过训练数据调整参数取值,这是训练神经网络的过程
4. 使用神经网络进行预测

2 前向传播算法简介

神经网络的结构就是不同神经元之间的连接结构。
全连接的神经网络是指相邻两层之间的任意两个节点之间都有连接。和卷积层、LSTM结构不同,前向传播结果需要三部分信息:输入,连接结构和输出。
实现前向传播过程的TF程序:

a = tf.matmul(x, w1)
y = tf.matmul(a, w2)

tf.matmul实现了矩阵乘法的功能。

3 神经网络参数与TF变量

TF中,变量(tf.Variable)的作用是保存和更新神经网络中的参数,需要指定初始值,一般是使用随机初始值。 在TF中声明一个2×3矩阵的方法

weights = tf.variable(tf.random_normal([2,3], stddev=2))

上面的代码生成一个2×3矩阵,矩阵中元素是均值为0,标准差为2的随机数,tf.random_normal函数可以通过参数mean来指定均值,没指定时默认为0。

TF随机数生成函数

函数名称 随机数分布 主要参数
tf.random_nomal 正态分布 均值、标准差、取值类型
tf.truncated_normal 正态分布,但如果随机出来的值偏离平均值超过2个标准差,那么这个数将会被重新随机 均值、标准差、取值类型
tf.random_uniform 平均分布 最小、最大取值,取值类型
tf.random_gamma Gamma分布 形状参数alpha、尺度参数beta、取值类型

TF随机数生成函数

函数名称 功能 样例
tf.zeros 产生全0的数组 tf.zeros([2,3], int32)->[[0,0,0],[0,0,0]]
tf.ones 产生全1的数组 tf.ones([2,3], int32)->[[1,1,1],[1,1,1]]
tf.fill 产生一个全部为给定数字的数组 tf.fill([2,3], 9)->[[9,9,9],[9,9,9]]
tf.constant 产生一个给定值的敞亮 tf.constant([1,2,3])->[1,2,3]

神经网络中偏置bias通常使用常数来设置初始值:
biases = tf.Variable(tf.zeros([3]))
TF也支持用其他变量的初始值来初始化新变量:

w2=tf.Variable(weights.initialized_value())
w3=tf.Variable(weights.initialized_value()*2.0)

w2被初始化为weights的值,w3是weights的两倍。
TF中,一个变量被使用之前,这个变量的初始化过程需要被明确调用。
以下样例介绍通过变量实现神经网络的参数并向前传播的过程。

import tensorflow as tf
#声明w1、w2两个变量,并通过seed参数设定了随机种子,这样可以保证每次运行的结果相同
w1 = tf.Variable(tf.random_normal([2, 3], seddev=1, seed=1))
w2 = tf.Variable(tf.random_normal([3, 1], seddev=1, seed=1))
#暂时将输入的特征向量定义为一个常量。注意这里x是一个1*2矩阵。
x = tf.constant([[0.7, 0.9]])
#通过前面描述的前向传播算法获得神经网络输出
a = tf.matmul(x, w1)
b = tf.matmul(a, w2)

#-------------------------

sess = tf.Session()
#这里不能通过sess.run(y)获取y的取值,因为w1,w2都还没有运行初始化过程。下面进行初始化
sess.run(w1.initializer)
sess.run(w2.initializer)
#输出[[3.95757794]]
print(sess.run(y))
sess.close()

由分割线隔开的第一部分定义了计算图中的所有计算但是没有真正运行。
第二部分声明一个会话并通过会话计算结果。但在计算y之前需要通过初始化给变量赋值。为了解决单个调用麻烦的问题,下面实现初始化所有变量。

init_op = tf.initialize_all_variables()#这个函数要被弃用了,建议用最新的:tf.global_variables_initializer()
sess.run(init_op)

 

4使用TF训练神经网络模型

使用监督学习的思想是,在已知答案的标注数据集上,模型给出的预测结果要尽量接近真实的答案。通过调整神经网络中的参数对训练数据的进行拟合,可以使得模型对未知样本提供预测能力。

神经网络优化算法中最常用的是反向传播算法。其实现了一个迭代的过程。每次迭代的开始首先选取一部分训练数据,称为一个batch,其会通过向前传播算法得到模型的预测结果。训练数据有正确答案标注因此会得到差距。基于差距通过反向传播算法更新参数取值。

一个batch的数据可以用常量,但是如果每轮迭代都用常量计算图会很大。为解决,TF提供了placeholder机制用于提供数据,其定义了一个位置,其中规定数据在运行时制定。类型指定后不可改变,维度信息可以推导,因此不一定给出。下面给出实例代码:

import tensorflow as tf
#声明w1、w2两个变量,并通过seed参数设定了随机种子,这样可以保证每次运行的结果相同
w1 = tf.Variable(tf.random_normal([2, 3], seddev=1, seed=1))
w2 = tf.Variable(tf.random_normal([3, 1], seddev=1, seed=1))
#定义placeholder作为输入数据存放的地方,维度不一定定义,但如果维度确定,给出将降低出错几率
x = tf.placeholder(tf.float32, shape=(3, 2), name="input")
a = tf.matmul(x, w1)
b = tf.matmul(a, w2)

#-------------------------

sess = tf.Session()
init_op = tf.initialize_all_variables()
sess.run(init_op)

#下面一行将报错
print(sess.run(y))

'''输出
[[3.95757794]
 [1.15376544]
 [3.16749191]]
'''
print(sess.run(y, feed_dict={x: [[0.7, 0.9],[0.1, 0.4], [0.5, 0.8]]}))
sess.close()

下面代码定义了一个简单的损失函数并通过TF定义了反向传播的算法。

#定义损失函数来刻画预测值与真实值的差距
cross_entropy = -tf.reduce_mean(
    y_ * tf.log(tf.clip_by_value(y, 1e-10, 1.0)))
#定义学习率
learning_rate = 0.001
#定义反向传播算法来优化参数
train_step = tf.train.AdamOptimizer(learning_rate).minimize(cross_entropy)

cross_entropy定义了交叉熵,train_step定义了优化方法。
常用优化方法:
tf.train.GradientDescentOptimizer
tf.train.AdamOptimizer
tf.train.MomentumOptimizer
定义完反向传播算法后通过运行sess.run(train_step)就可以对所有在GraphKeys.TRAINABLE_VARIABLES集合中的变量进行优化使当前batch下损失函数更小。

发表评论

邮箱地址不会被公开。 必填项已用*标注