Tensorflow 学习笔记(六) ———— Optimizer

二 31 一月 2017 by Chan

Optimizer

本篇博客探索所用tensorflow的优化器解决最优化问题
In [1]:
import tensorflow as tf

定义目标函数, $loss = (x-3)^2$, 求goal最小时,x的值:

In [2]:
# x = tf.placeholder(tf.float32)
x = tf.Variable(tf.truncated_normal([1]), name="x")
goal = tf.pow(x-3,2, name="goal")
In [3]:
with tf.Session() as sess:
    x.initializer.run()
    print x.eval()
    print goal.eval()
[-0.15094033]
[ 9.92842579]

使用梯度下降优化器解决问题。

1. 使用minimize()

In [4]:
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.1)
train_step = optimizer.minimize(goal)
In [5]:
def train():
    with tf.Session() as sess:
        x.initializer.run()
        for i in range(10):
            print "x: ", x.eval()
            train_step.run()
            print "goal: ",goal.eval()    
train()
x:  [ 0.0178078]
goal:  [ 5.69182014]
x:  [ 0.61424625]
goal:  [ 3.64276576]
x:  [ 1.09139693]
goal:  [ 2.33137012]
x:  [ 1.47311759]
goal:  [ 1.49207664]
x:  [ 1.77849412]
goal:  [ 0.95492917]
x:  [ 2.0227952]
goal:  [ 0.61115462]
x:  [ 2.21823621]
goal:  [ 0.39113891]
x:  [ 2.37458897]
goal:  [ 0.25032887]
x:  [ 2.49967122]
goal:  [ 0.16021053]
x:  [ 2.59973693]
goal:  [ 0.10253474]

如果是最大化呢?

很简单,给目标函数套上tf.negative就可以了。不过好像写成-1 * 完全没有区别~~

In [6]:
y = tf.Variable(tf.truncated_normal([1]))
max_goal = tf.sin(y)
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.1)
# train_step = optimizer.minimize(tf.negative(max_goal))
train_step = optimizer.minimize(-1 * max_goal)
In [7]:
with tf.Session() as sess:
    y.initializer.run()
    for i in range(10):
        print "y: ", y.eval()
        train_step.run()
        print "max_goal: ",max_goal.eval()
y:  [ 0.44078666]
max_goal:  [ 0.50659275]
y:  [ 0.5312283]
max_goal:  [ 0.57895529]
y:  [ 0.61744684]
max_goal:  [ 0.64343935]
y:  [ 0.69898278]
max_goal:  [ 0.70009637]
y:  [ 0.77553248]
max_goal:  [ 0.7492556]
y:  [ 0.8469373]
max_goal:  [ 0.79144251]
y:  [ 0.91316539]
max_goal:  [ 0.82730311]
y:  [ 0.97428977]
max_goal:  [ 0.85753846]
y:  [ 1.03046536]
max_goal:  [ 0.88285518]
y:  [ 1.08190739]
max_goal:  [ 0.90393031]

2 . minimize() = compute_gradients() + apply_gradients()

拆分成计算梯度和应用梯度两个步骤。

In [8]:
# compute_gradients 返回的是:A list of (gradient, variable) pairs
gra_and_var = optimizer.compute_gradients(goal)
train_step = optimizer.apply_gradients(gra_and_var)
train()
x:  [ 0.40001234]
goal:  [ 4.32635927]
x:  [ 0.92000991]
goal:  [ 2.7688694]
x:  [ 1.33600795]
goal:  [ 1.77207625]
x:  [ 1.66880643]
goal:  [ 1.13412893]
x:  [ 1.93504512]
goal:  [ 0.72584224]
x:  [ 2.14803624]
goal:  [ 0.46453902]
x:  [ 2.31842899]
goal:  [ 0.29730505]
x:  [ 2.45474315]
goal:  [ 0.19027515]
x:  [ 2.56379461]
goal:  [ 0.12177601]
x:  [ 2.65103579]
goal:  [ 0.07793671]

3. 进一步

clip_by_global_norm:修正梯度值

用于控制梯度爆炸的问题。梯度爆炸和梯度弥散的原因一样,都是因为链式法则求导的关系,导致梯度的指数级衰减。为了避免梯度爆炸,需要对梯度进行修剪。

In [9]:
gradients, vriables = zip(*optimizer.compute_gradients(goal))
gradients, _ = tf.clip_by_global_norm(gradients, 1.25)
train_step = optimizer.apply_gradients(zip(gradients, vriables))
train()
x:  [-0.76665598]
goal:  [ 13.26165771]
x:  [-0.64165598]
goal:  [ 12.36686897]
x:  [-0.51665598]
goal:  [ 11.50333118]
x:  [-0.39165598]
goal:  [ 10.67104053]
x:  [-0.26665598]
goal:  [ 9.87000275]
x:  [-0.14165597]
goal:  [ 9.10021305]
x:  [-0.01665596]
goal:  [ 8.36167431]
x:  [ 0.10834403]
goal:  [ 7.65438461]
x:  [ 0.23334403]
goal:  [ 6.97834587]
x:  [ 0.35834405]
goal:  [ 6.33355713]

exponential_decay 加入学习率衰减:

In [10]:
# global_step 记录当前是第几个batch
global_step = tf.Variable(0)
learning_rate = tf.train.exponential_decay(
    3.0, global_step, 3, 0.3, staircase=True)
optimizer2 = tf.train.GradientDescentOptimizer(learning_rate)
gradients, vriables = zip(*optimizer2.compute_gradients(goal))
gradients, _ = tf.clip_by_global_norm(gradients, 1.25)
train_step = optimizer2.apply_gradients(zip(gradients, vriables), 
                                       global_step=global_step)
with tf.Session() as sess:
        global_step.initializer.run()
        x.initializer.run()
        for i in range(10):
            print "x: ", x.eval()
            train_step.run()
            print "goal: ",goal.eval()
x:  [-0.92852646]
goal:  [ 0.03187185]
x:  [ 2.82147312]
goal:  [ 0.79679614]
x:  [ 3.89263439]
goal:  [ 8.16453552]
x:  [ 0.14263475]
goal:  [ 3.00108886]
x:  [ 1.26763487]
goal:  [ 0.3688924]
x:  [ 2.39263487]
goal:  [ 0.23609133]
x:  [ 3.4858923]
goal:  [ 0.04995694]
x:  [ 3.2235105]
goal:  [ 0.01057091]
x:  [ 3.10281491]
goal:  [ 0.0022368]
x:  [ 3.04729486]
goal:  [ 0.00157078]