深层神经网络实现--step by step 入门TensorFlow(二)

时间:2021-08-23 20:02:15

深层神经网络实现–step by step 入门TensorFlow(二)

标签:tensorflow


我们将采用Jupyter notebook交互式编程的方式,通过一步步代码的讲解,学习Tensorflow 编程。推荐使用Jupyter notebook作为开发环境按照文中的代码step by step 的学习。

文章列表:
Tensorflow基础知识与神经网络构建–step by step 入门TensorFlow(一)
深层神经网络实现–step by step 入门TensorFlow(二)
MNIST 数字识别和数据持久化–step by step 入门TensorFlow(三)

损失函数

神经网络模型的效果和优化目标是通过损失函数来定义的
如果用一个向量作为分类结果(比如[0,0,0,1,0]识别为第4类),那如何判断输出向量与期望的向量有多接近呢?
交叉熵是最常用的评判标准之一,它刻画了两个概率分布之间的距离。而softmax()函数可以把把输出变为概率分布。
下面是交叉熵的实现,交叉熵与回归一起可以tf.nn.softmax_cross_entropy_with_logits().
其中tf.clip_by_value的展示

import tensorflow as tf
# cross_entropy = -tf.reduce_mean(y_ * tf.log(tf.clip_by_value(y, 1e-10,1.0)))
#tf.nn.softmax_cross_entropy_with_logits(y,y_)
v = tf.constant([[1.0,2.0,3.0], [4.0,5.0,6.0]])

print(tf.clip_by_value(v,2.5,4.5).eval())
[[ 2.5  2.5  3. ]
[ 4. 4.5 4.5]]

求平均的tf.reduce_mean()函数使用方法

with tf.Session() as sess:
print(tf.reduce_mean(v).eval())
3.5

我们也可以自定义损失函数。tf.greater(v1,v2)遍历向量做大小判断,大于为true,tf.select()根据条件选择取那个队列中的元素。

import tensorflow as tf

v1 = tf.constant([2,3,8,9])
v2 = tf.constant([5,6,7,8])
with tf.Session() as sess:
a = tf.where(tf.greater(v1,v2),v1,v2) # window下select()不能用,用where()代替
print(a.eval())
[5 6 8 9]

神经网络优化算法

神经网络的优化主要使用反向传播算法和梯度下降算法。梯度下降主要用于优化单个参数的取值,而反向传播给出一个高效的方式在所有参赛上使用梯度下降算法。
由于梯度随机算法需要算出所有数据的梯度,非常耗时间,为了加快训练可使用随机梯度下降算法。而随机梯度下降算法每次随机选取一个数据算梯度,该梯度可能无法代表总体梯度,因此,我们一般采用批数据训练计算梯度的方法,而同一批训练的数据,被称为一个batch。

在使用梯度下降算法时是要设置学习率的,学习率太大会使参数在最优值旁边摇摆,太小会降低优化速率。
而tf.train.exponential_decay()函数可以实现指数衰减学习率,其中global为当前步数,decay——step为跑完1个epoch所需轮数


decayed_learning_rate = learning_rate * decay_rate ^ (global_step / decay_step)


调用方法
global_step = tf.Variable(0)
learning_rate = tf.train.exponential_decay(0.1,global_step,100,0.96,staircase=True)
learning_step = tf.train.GradientDescentOptimizer(learing_rate).minimize(…myloss..,global_step=global_step)

为了避免过拟合,经常会进行正则化,正则化的思想就是在损失函数中刻画模型复杂度的指标,即优化的是优化的是 J(theta)lambdaR(w) ,R(W)代表此时的模型复杂度,由L1或L2正则化求得,任一种正则化都是为了限制权重大小,使模型不能任意你好训练集中的噪音。

下面代码给出通过集合计算一个5层神经网络带L2正正则化的损失函数的计算方法

import tensorflow as tf
from numpy.random import RandomState

# 获取一层神经网络的权重,并将这个权重的L2正则化损失加入名称为losses的集合中
def get_weight(shape, lambda_):
var = tf.Variable(tf.random_normal(shape),dtype=tf.float32)
tf.add_to_collection("losses", tf.contrib.layers.l2_regularizer(lambda_)(var))
return var
# 输入
x = tf.placeholder(tf.float32, shape=[None, 2], name='x_input')
y_ = tf.placeholder(tf.float32, shape=[None, 1], name='y_output')
batch_size = 8
#网络构造
layer_dim = [2, 10, 10, 10, 1]
n_layers = len(layer_dim)
cur_layer = x
# 当前层节点数
in_dim = layer_dim[0]

# 通过循环生成5层全连接网络
for i in range(1, n_layers):
out_dim = layer_dim[i] #后一层节点数
weight = get_weight([in_dim,out_dim],0.001)
bias = tf.Variable(tf.constant(0.1,shape=[out_dim]))
cur_layer = tf.nn.relu(tf.matmul(cur_layer,weight) + bias)
in_dim = out_dim

# 计算均方差损失函数
mse_loss = tf.reduce_mean(tf.square(y_ - cur_layer))
# 将均方差损失函数加入损失集合
tf.add_to_collection("losses",mse_loss)
# 将损失函数的值加起来得最后最后损失函数
loss = tf.add_n(tf.get_collection("losses"))

global_step = tf.Variable(0)
learning_rate = tf.train.exponential_decay(0.1,global_step,25,0.96,staircase=True)
learning_step = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss,global_step=global_step)

ram = RandomState(1)
dataset_size = 200
X = ram.rand(dataset_size, 2) # 随机生成X
Y = [[int(x1+x2<1)] for (x1, x2) in X] # x1+x2小于1的为正样本

init_op = tf.global_variables_initializer() # 初始化所有全局变量
with tf.Session() as sess:
sess.run(init_op)
#print(sess.run(w2))
steps = 1000
for i in range(steps):
start = batch_size * i % dataset_size
#print(start)
end = min(batch_size + start, dataset_size)
#print(X[start:end])
sess.run(learning_step, feed_dict={x:X[start:end], y_:Y[start:end]})
global_step += 1
if i%100==0:
total_loss = sess.run(loss, feed_dict={x:X, y_: Y})
print("after %d step entroy is %g" % (i, total_loss))




after 0 step entroy is 0.564732
after 100 step entroy is 0.562875
after 200 step entroy is 0.561324
after 300 step entroy is 0.560026
after 400 step entroy is 0.558938
after 500 step entroy is 0.558023
after 600 step entroy is 0.557253
after 700 step entroy is 0.556604
after 800 step entroy is 0.556057
after 900 step entroy is 0.555594

使用滑动平均模型可以提高模型在测试集上的表现

import tensorflow as tf
v1 = tf.Variable(0,dtype=float32)
step = tf.Variable(0,trainable=False) #控制迭代轮数
# 定义滑动平均类
ema = tf.train.ExponentialMovingAverage(O.99,step)
# 滑动平均操作
maintain_averages_op = ema.apply([v1])