结合上一篇文章,本文主要介绍如何使用TensorFlow实现上一篇文章中所介绍的神经网络模型工作过程。本文的主要侧重点是介绍如何使用TensorFlow完成程序设计与功能实现,介绍相关函数的使用方法。
1. TensorFlow实现前向传播过程:
import tensorflow as tf
# 声明w1,w2两个变量,通过seed参数设定了随机种子,保证每次运行得到的结果一样。
# tf.random_normal((2,3),stddev=1):会产生一个2x3的矩阵,矩阵中的元素是均值0,
# 标准差为2的随机数。可以通过mean指定平均值,没有指定时默认为0.
w1 = tf.Variable(tf.random_normal((2,3),stddev=1,seed=1))
w2 = tf.Variable(tf.random_normal((3,1),stddev=1,seed=1))
# 暂时将输入的特征向量定义为一个常量,此处x是一个1x2的矩阵。
# tf.constant产生一个给定值的常量,下面结果为:[0.7,0.9]
x = tf.constant([[0.7,0.9]])
# 前向传播算法可以用矩阵相乘表示,TensorFlow使用tf.matmul(x,w1)表示矩阵相乘。
# x=[x1,x2]输入;w1是第一层权重矩阵;w2是第二层权重矩阵。
a = tf.matmul(x,w1)
y = tf.matmul(a,w2)
# TesnsorFlow第二部会申明一个会话(session),通过会话计算结果。且申明和初始化分开。
sess = tf.Session()
# 先初始化,再run。由于w1,w2是变量,所以初始化这两个参数即可。
sess.run(w1.initializer)
sess.run(w2.initializer)
print(sess.run(y))
sess.close()
Tip1:
# 上述代码中的初始化使用的是w1.initializer和w2.initializer函数。当变量过多时,一个一个的初始化很
# 不方便,TensorFlow提供了以下函数,完成所有变量的初始化,这个函数自动处理变脸之间的依赖关系。
init_op = tf.global_variables_initializer()
sess.run(init_op)
2. TensorFlow定义反向传播算法:
# 使用sigmoid函数将y转换为0-1之间的数值。
# 其中,y代表预测是正样本的概率,1-y代表预测是负样本的概率。
y = tf.sigmoid(y)
# 定义损失函数来刻画预测值与真实值的差距
# “交叉熵”
cross_entropy = ....
# 学习率
learning_rate = 0.001
# 定义反向传播算法优化神经网络中的参数
train_step = tf.train.AdamOptimizer(learning_rate).minimize(corss_entropy)
# 常用三种优化方法:
tf.train.GradientDescentOptimizer
tf.train.AdamOptimizer
tf.train.MomentumOptimizer
# TensorFlow训练神经网络主要分为以下3个步骤
# 1.定义神经网络的结构和前向传播的输出结果;
# 2.定义损失函数以及选择反向传播优化的算法;
# 3.生成会话(tf.Session)并且在训练数据上反复运行反向传播优化算法。
3. TensorFlow实现深层神经网络:
# TensorFlow提供了7种不同的非线性激活函数,tf.nn.relu;tf.signoid;tf.tanh。
# 以下代码展示了如何通过TensorFlow实现加偏置项和激活函数的前向传播算法。
a = tf.nn.relu(tf.matmul(x,w1) + biases1)
y = tf.nn.relu(tf.matmul(a,w1) + biases2)
# TensorFlow实现交叉熵。
# y_代表正确结果;y代表预测结果。
# tf.clip_by_value函数可以将一个张量中的数值限制在一个范围内。
# 1.小于1e-10的等于1e-10,大于1.0的都等于1.0,处于中间的保持自己原有值;
# 2.tf.log指的是对张量中所有的元素求对数,因此log0会报错;
# 3.这里的*指的是矩阵中的元素相乘,而不是矩阵相乘【tf.matmul】。一一对应相乘即可。
cross_entropy = -tf.reduce_mean(y_ * tf.log(tf.clip_by_value)y,1e-10,1.0)
# TensorFlow实现Softmax功能。
# 由于交叉熵一般会与Softmax回归一起使用,TensorFlow对其进行封装。
# y代表了原始神经网络的输出结果,y_给出了标准答案。下面的代码输出回归之后的交叉熵。
corss_entropy = tf.nn.softmax_cross_entropy_with_logits(labels-y_,logits=y)
# TensorFlow实现均方误差损失函数。
# y代表了神经网络的输出答案,y_代表了标准答案。这里亦是对两个矩阵内部元素做减法运算。
mse = tf.reduce_mean(tf.square(y_ - y))
# 简单神经网络程序阐述“损失函数”对训练结果的影响。
import tensorflow as tf
from numpy.random import RandomState
batch_size = 8
# 输入2个节点
x = tf.placeholder(tf.float32,shape=(None,2),name='x-input')
# 回归问题一般只有一个输出节点
y_ = tf.placeholder(tf.float32,shape=(None,1),name='y-input')
# 定义一个单层的神经网络前向传播过程,简单加权和
w1 = tf.Variable(tf.random_normal([2,1]stddev=1,seed=1))
y = tf.matmul(x,w1)
# 定义预测多了和预测少了的成本
loss_less = 10
loss_more = 1
loss = tf.reduce_sum(tf.where(tf.greater(y,y_),
y - y_) * loss_more,
y_ - y) * loss_less))
train_step =tf.train.AdamOptimizer(0.001).minimize(loss)
# 通过随机数生成一个模拟数据集
rdm = RandomState(1)
dataset_size = 128
X = rdm.rand(dataset_size, 2)
# 设置回归的正确值为2个输入+1个随机量。随机量为不可预测的噪音,完全正确预测的时候最低,-0.05~0.05
Y = [[x1 + x2] + rdm.rand()/10.0-0.05] for (x1,x2) in X]
# 训练神经网络
with tf.Session() as sess:
init_op = tf.global_variables_initializer()
sess.run(init_op)
STEPS = 5000
for i in range(STEPS)
start = (i * batch_size) % dataset_size
end = min(start+batch_size,dataset_size)
sess.run(train_step,
feed_dict={x : X[start:end],y_:Y[start:end]})
print sess.run(w1)
# TensorFlow实现学习率的设置。
# exponential_decay函数会指数级别的减小学习率。
# decayde_learning_rate为衰减系数;decay_steps为衰减速度。decay_steps=总样本数/每个batch样本数
decayde_learning_rate = learning_rate * decay_rate ^ (global_step / decay_steps)
# TensorFlow实现正则化,防止过拟合。
# 代码:带L2正则化的损失函数定义。
w = tf.Variable(tf.random_normal([2,1],stddev=1,seed=1))
y = tf.matmul(x,w)
loss = tf.reduce_mean(tf.square(y_ - y))+
tf.contrib.layers.12_regularizer(lambda)(w)
# L1正则化表示函数:tf.contrib.layers.11_regularizer
4. 卷积神经网络(图像识别):
# TensorFlow实现卷积层的前向传播过程。
# tf.get_variable的方式创建过滤器的权重变量和偏置项变量。这里申明的参数变量是四维矩阵。
# 四维矩阵:前面2个维度代表过滤器尺寸;第3个维度表示当前层的深度;第4个维度表示过滤器深度。
filter_weight = tf.get_variable('weights',[5,5,3,16],
initializer-tf.truncated_normal_initializer(stddev=0.1))
# 当前矩阵上不同位置的偏置项也是共享的,总共有下一层深度个不同的偏置项。
biases = tf.get_variable('biases',[16],initializer=tf.constant_initializer(0.1))
# tf.nn.conv2d提供了一个非常方便的函数来实现卷积层前向传播的算法,一共四个参数。
# 参数1:当前层的节点矩阵。input[0,:,:,:]表示第一张图片;input[1,:,:,:]表示第二张图片。
# 参数2:提供了卷积层的权重。
# 参数3:不同维度上的步长。【虽然提供的是长度为4的数组,但第一维和第四维必然为1】
# 参数4:填充的方法。SAME=“全0填充”;VALID=“不添加”。
conv -tf.nn.conv2d(input,filter_weight,strides=[1,1,1,1],padding='SAME')
# tf.nn.bias_add提供了一个方便的函数给每个节点加上偏置项。矩阵中每个值都要加上偏置项这个值。
bias = tf.nn.bias_add(conv,biases)
# 将计算结果通过ReLU激活函数完成去线性化
actived_conv = tf.nn.relu(bias)
# TensorFlow实现最大池化层的前向传播算法。
# tf.nn.max_pool;参数ksize提供过滤器尺寸;参数strides提供步长;参数padding提供是否全0填充。
pool = tf.nn.max_pool(actived_conv,ksize=[1,3,3,1],strides=[1,2,2,1],padding='SAME')
总结:
本文主要对常用的神经网络基于TensorFlow如何实现进行了简单阐述与总结。下一篇文章笔者将对基于TensorFlow实现LeNet-5模型,Inception-v3等模型做出相应的介绍。