TensorFlow学习(二)——神经网络梯度优化

笔者是一个痴迷于挖掘数据中的价值的学习人,希望在平日的工作学习中,挖掘数据的价值,找寻数据的秘密,笔者认为,数据的价值不仅仅只体现在企业中,个人也可以体会到数据的魅力,用技术力量探索行为密码,让大数据助跑每一个人,欢迎直筒们关注我的公众号,大家一起讨论数据中的那些有趣的事情。

我的公众号为:livandata

神经网络相关的内容比较复杂,笔者只能逐一的进行总结,不足之处敬请谅解,如有遗漏,也欢迎大家留言沟通,学习的过程,本省就是相学相长的过程,以下内容希望对大家有所帮助。

1、神经网络用到的知识点为:

# 选取tensor中索引对应的元素:

c = np.random.random([10, 1])

# 取出第二个、第四个元素

b = tf.nn.embedding_lookup(c, [1,3])

sess = tf.Session()

print(sess.run(b))

print(c)

a = tf.get_variable('a', shape=[5, 2])

b = tf.get_variable('b', shape=[5, 2], trainable=False)

# 获取可以训练的变量a

tvar = tf.trainable_variables()

sess = tf.InteractiveSession()

sess.run(tf.initialize_all_variables())

print(sess.run(tvar))

print(sess.run(a))

2、损失函数的计算一般会采用梯度递减的方式进行,一般在使用梯度时会有很多现成的方法,比如:train = tf.train.GradientDescentOptimizer(0.01).minimize(loss),但是在调优过程中有时存在梯度消失或梯度爆炸等情况,其原因是由于链式求导法则中存在的问题,需要对函数的梯度进行优化或者更换激活函数,来减少梯度消失和爆炸的问题,下面提供了几个梯度优化的方法,仅供参考:

# 选取tensor中索引对应的元素:

c = np.random.random([10, 1])

# 取出第二个、第四个元素

b = tf.nn.embedding_lookup(c, [1,3])

sess = tf.Session()

print(sess.run(b))

print(c)

a = tf.get_variable('a', shape=[5, 2])

b = tf.get_variable('b', shape=[5, 2], trainable=False)

# 获取可以训练的变量a

tvar = tf.trainable_variables()

sess = tf.InteractiveSession()

sess.run(tf.initialize_all_variables())

print(sess.run(tvar))

print(sess.run(a))

神经网络梯度规则:

1)梯度求导:

grad = tf.gradients(ys=b, xs=a):即对b进行求导,自变量为a

grad = tf.gradients(ys=[y1, y2], xs=[x1,x2,x3]):则相当于对y1+y2求偏导,偏导的自变量为[x1, x2, x3]

x_input = tf.placeholder(tf.float32, name='x_input')

y_input = tf.placeholder(tf.float32, name='y_input')

w = tf.Variable(2.0, name='weight')

b = tf.Variable(1.0, name='biases')

y = tf.add(tf.multiply(x_input, w), b)

gradient:梯度求导;

loss = tf.reduce_mean(tf.pow(y_input - y, 2))/(2*32)

train = tf.train.GradientDescentOptimizer(0.01).minimize(loss)

sess = tf.InteractiveSession()

sess.run(tf.initialize_all_variables())

# train为训练之后的模型

batch_xs, batch_ys = mnist.train.next_batch(100)

train.run({x:batch_xs, y:batch_ys})

print(sess.run(y, feed_dict={x_input:x_train[i], y_input:y_train[i]}))

2)加权重求导:即对xs中的每个元素的求导值加权重。

w1 = tf.get_variable('w1', shape=[1])

w2 = tf.get_variable('w2', shape=[1])

w3 = tf.get_variable('w3', shape=[1])

w4 = tf.get_variable('w4', shape=[1])

z1 = 3*w1+2*w2+w3

z2 = -1*w3+w4

# grad_ys=[[-2.0, -3.0, -4.0],[-2.0, -3.0, -4.0]]

# 原来的值是对(z1+z2)求偏导;

# 现在的值是对((-2)*z1+(-3)*z2)求偏导;

grads = tf.gradients([z1, z2], [w1, w2, w3, w4], grad_ys=[[-2.0],[-3.0]])

with tf.Session() as sess:

    tf.global_variables_initializer().run()

    print(sess.run(grads))

3)梯度阻挡:

主要是阻挡一个方向的梯度,使其不再向上传播:

w1 = tf.Variable(2.0)

w2 = tf.Variable(2.0)

a = tf.multiply(w1, 3.0)

a_stoped = tf.stop_gradient(a)

b = tf.multiply(a_stoped, w2)

# b = w1*3.0*w2

gradients = tf.gradients(b, xs=[w1, w2])

# 上面的模型是为了构建一个含有两个变量的函数式,对b求导时主要分两步:

# 第一步求w1的导数,因为在运算中针对w1方向的梯度已经停掉,所以输出none

# 第二步求w2的导数,运算中针对w2方向的梯度正常运算,所以输出正常的值;

# 可以将b函数看作是一个树状结构,stop_gradient限制了一个分枝,其他分枝不受影响;

print(gradients)

4)梯度修剪(梯度爆炸控制:由于权重的更新过于迅猛):

梯度爆炸与梯度消减的原因一样,都是因为链式法则求导的关系,导致梯度指数级衰减,为了避免梯度爆炸,需要进行梯度修剪;

tf.clip_by_global_norm(t_list, clip_norm, use_norm, name):

gradients得到的是一个梯度,有时这个梯度太大,导致梯度爆炸,因此需要进行梯度的修剪,

主要是按照clip_norm的平方和对t_list进行修剪,得到修剪后的梯度值。

原理为:

第一步:在solver中先设置一个clip_gradient;

第二步:在进行前向传播或者后向传播时,会得到每个权重的梯度diff,这时不像通常那样直接使用这些梯度进行权重更新,而是先求所有权重梯度的平方和sumsq_diff

缩放因子为:scale_factor=clip_gradient/sumsq_diff;这个scale_factor在(0,1)之间,如果权重梯度的平方和越大,则缩放因子将越小;

第三步:将所有的权重梯度乘以这个缩放因子,这时得到的梯度才是最后的梯度信息;

import tensorflow as tf 

def gradient_clip(gradients, max_gradient_norm):

    """计算的过程为:clipped_gradients=gradients/平方和(max_gradient_norm)"""

    clipped_gradients, gradient_norm = tf.clip_by_global_norm(

            gradients, max_gradient_norm)

    gradient_norm_summary = [tf.summary.scalar("grad_norm", gradient_norm)]

    gradient_norm_summary.append(

        tf.summary.scalar("clipped_gradient", tf.global_norm(clipped_gradients)))

    return clipped_gradients

w1 = tf.Variable([[3.0,2.0]]) 

params = tf.trainable_variables()

res = tf.matmul(w1, [[3.0],[1.]]) 

grads = tf.gradients(res,[w1]) 

clipped_gradients = gradient_clip(grads,2.0)

global_step = tf.Variable(0, name='global_step', trainable=False)

with tf.Session() as sess: 

    tf.global_variables_initializer().run()

    print(sess.run(res))

    print(sess.run(grads)) 

    print(sess.run(clipped_gradients))

dropout(x, keep_drop)函数:主要是防止训练过程中的过拟合,按照概率将x中的元素置为零,并将其他值放大;

x是一个张量,而keep_prod是一个(0,1)之间的值,x中的元素清零的概率相互独立,为1-keep_prod,其他的元素按照1/keep_prod重新计算概率;

a = tf.get_variable('a', shape=[2,5])

b=a

a_drop=tf.nn.dropout(a,0.8)

sess = tf.InteractiveSession()

sess.run(tf.initialize_all_variables())

print(sess.run(b))

print(sess.run(a_drop))

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值