tensorflow中optimizer minimize自动训练简介和选择训练variable的方法

2023-11-04

 

本文主要介绍tensorflow的自动训练的相关细节,并把自动训练和基础公式结合起来。如有不足,还请指教。

写这个的初衷:有些教程说的比较模糊,没体现出用意和特性或应用场景。

面向对象:稍微了解点代码,又因为有限的教程讲解比较模糊而一知半解的初学者。

(更多相关内容,比如相关优化算法的分解和手动实现,EMA、BatchNormalization等用法,底部都有链接。)

 

 

正文

tensorflow提供了多种optimizer,典型梯度下降GradientDescent和Adagrad、Momentum、Nestrov、Adam等变种。

典型的学习步骤是梯度下降GradientDescent,optimizer可以自动实现这一过程,通过指定loss来串联所有相关变量形成计算图,然后通过optimizer(learning_rate).minimize(loss)实现自动梯度下降。minimize()也是两步操作的合并,后边会分解。

计算图的概念:一个变量想要被训练到,前提他在计算图中,更直白的说,要在公式或者连锁公式中,如果一个变量和loss没有任何直接以及间接关系,那就不会被训练到。

 

 

源码

train的过程其实就是修改计算图中的tf.Variable的过程,可以认为这些所有variable都是权重,为了简化,下面这个例子没引入placeholder和x,没有x和w的区分,但是变量prediction_to_train=3其实等价于:

prediction_to_train(y) = w*x,其中初始值w=3,隐藏的锁死的x=1(也就是一个固定的训练样本)。

这里loss定义的是平方差,label是1,所以训练过程就是x=1,y=1的数据,针对初始化w=3,训练w,把w变成1。

import tensorflow as tf

#define variable and error
label = tf.constant(1,dtype = tf.float32)
prediction_to_train = tf.Variable(3,dtype=tf.float32)

#define losses and train
manual_compute_loss = tf.square(prediction_to_train - label)
optimizer = tf.train.GradientDescentOptimizer(0.01)
train_step = optimizer.minimize(manual_compute_loss)

init = tf.global_variables_initializer()
with tf.Session() as sess:
    sess.run(init)
    for _ in range(100):
        print('variable is ', sess.run(prediction_to_train), ' and the loss is ',sess.run(manual_compute_loss))
        sess.run(train_step)

输出

variable is  3.0  and the loss is  4.0
variable is  2.96  and the loss is  3.8416002
variable is  2.9208  and the loss is  3.6894724
variable is  2.882384  and the loss is  3.5433698
variable is  2.8447363  and the loss is  3.403052
variable is  2.8078415  and the loss is  3.268291

。。。。。。。
。。。
variable is  2.0062745  and the loss is  1.0125883
variable is  1.986149  and the loss is  0.9724898
variable is  1.966426  and the loss is  0.9339792

。。。。
。。。

variable is  1.0000029  and the loss is  8.185452e-12
variable is  1.0000029  and the loss is  8.185452e-12
variable is  1.0000029  and the loss is  8.185452e-12
variable is  1.0000029  and the loss is  8.185452e-12
variable is  1.0000029  and the loss is  8.185452e-12

 

限定train的Variable的方法:

根据train是修改计算图中tf.Variable(默认是计算图中所有tf.Variable,可以通过var_list指定)的事实,可以使用tf.constant或者python变量的形式来规避常量被训练,这也是迁移学习要用到的技巧。

下边是一个正经的陈(train)一发的例子:

y=w1*x+w2*x+w3*x

因y=1,x=1

1=w1+w2+w3

又w3=4

-3=w1+w2

#demo2
#define variable and error
label = tf.constant(1,dtype = tf.float32)
x = tf.placeholder(dtype = tf.float32)
w1 = tf.Variable(4,dtype=tf.float32)
w2 = tf.Variable(4,dtype=tf.float32)
w3 = tf.constant(4,dtype=tf.float32)

y_predict = w1*x+w2*x+w3*x

#define losses and train
make_up_loss = tf.square(y_predict - label)
optimizer = tf.train.GradientDescentOptimizer(0.01)
train_step = optimizer.minimize(make_up_loss)

init = tf.global_variables_initializer()
with tf.Session() as sess:
    sess.run(init)
    for _ in range(100):
        w1_,w2_,w3_,loss_ = sess.run([w1,w2,w3,make_up_loss],feed_dict={x:1})
        print('variable is w1:',w1_,' w2:',w2_,' w3:',w3_, ' and the loss is ',loss_)
        sess.run(train_step,{x:1})

 因为w3是constant,成功避免了被陈(train)一发,只有w1和w2被train。

符合预期-3=w1+w2

variable is w1: -1.4999986  w2: -1.4999986  w3: 4.0  and the loss is  8.185452e-12
variable is w1: -1.4999986  w2: -1.4999986  w3: 4.0  and the loss is  8.185452e-12
variable is w1: -1.4999986  w2: -1.4999986  w3: 4.0  and the loss is  8.185452e-12
variable is w1: -1.4999986  w2: -1.4999986  w3: 4.0  and the loss is  8.185452e-12

下边是使用var_list限制只有w2被train的例子,只有w2被train,又因为那两个w初始化都是4,x=1,所以w2接近-7是正确答案。

#define variable and error
label = tf.constant(1,dtype = tf.float32)
x = tf.placeholder(dtype = tf.float32)
w1 = tf.Variable(4,dtype=tf.float32)
w2 = tf.Variable(4,dtype=tf.float32)
w3 = tf.constant(4,dtype=tf.float32)

y_predict = w1*x+w2*x+w3*x

#define losses and train
make_up_loss = tf.square(y_predict - label)
optimizer = tf.train.GradientDescentOptimizer(0.01)
train_step = optimizer.minimize(make_up_loss,var_list = w2)

init = tf.global_variables_initializer()
with tf.Session() as sess:
    sess.run(init)
    for _ in range(500):
        w1_,w2_,w3_,loss_ = sess.run([w1,w2,w3,make_up_loss],feed_dict={x:1})
        print('variable is w1:',w1_,' w2:',w2_,' w3:',w3_, ' and the loss is ',loss_)
        sess.run(train_step,{x:1})
variable is w1: 4.0  w2: -6.99948  w3: 4.0  and the loss is  2.7063857e-07
variable is w1: 4.0  w2: -6.9994903  w3: 4.0  and the loss is  2.5983377e-07
variable is w1: 4.0  w2: -6.9995003  w3: 4.0  and the loss is  2.4972542e-07
variable is w1: 4.0  w2: -6.9995103  w3: 4.0  and the loss is  2.398176e-07
variable is w1: 4.0  w2: -6.9995203  w3: 4.0  and the loss is  2.3011035e-07
variable is w1: 4.0  w2: -6.99953  w3: 4.0  and the loss is  2.2105178e-07
variable is w1: 4.0  w2: -6.9995394  w3: 4.0  and the loss is  2.1217511e-07

如果w1、w2、w3都是tf.constant呢?毫无疑问,,还,真友好~

一共两种情况:

var_list自动获取所有可训练变量,会报错告诉你找不到能train的variables:

ValueError: No variables to optimize.

用var_list指定一个constant,没有实现:

NotImplementedError: ('Trying to update a Tensor ', <tf.Tensor 'Const_1:0' shape=() dtype=float32>)

 

 

另一种获得var_list的方式——tf.getCollection

各种get_variable更实用一些,因为不一定方便通过python引用得到tensor。

#demo2.2  another way to collect var_list

label = tf.constant(1,dtype = tf.float32)
x = tf.placeholder(dtype = tf.float32)
w1 = tf.Variable(4,dtype=tf.float32)
with tf.name_scope(name='selected_variable_to_trian'):
    w2 = tf.Variable(4,dtype=tf.float32)
w3 = tf.constant(4,dtype=tf.float32)

y_predict = w1*x+w2*x+w3*x

#define losses and train
make_up_loss = (y_predict - label)**3
optimizer = tf.train.GradientDescentOptimizer(0.01)

output_vars = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES, scope='selected_variable_to_trian')
train_step = optimizer.minimize(make_up_loss,var_list = output_vars)

init = tf.global_variables_initializer()
with tf.Session() as sess:
    sess.run(init)
    for _ in range(3000):
        w1_,w2_,w3_,loss_ = sess.run([w1,w2,w3,make_up_loss],feed_dict={x:1})
        print('variable is w1:',w1_,' w2:',w2_,' w3:',w3_, ' and the loss is ',loss_)
        sess.run(train_step,{x:1})
variable is w1: 4.0  w2: -6.988893  w3: 4.0  and the loss is  1.3702081e-06
variable is w1: 4.0  w2: -6.988897  w3: 4.0  and the loss is  1.3687968e-06
variable is w1: 4.0  w2: -6.9889007  w3: 4.0  and the loss is  1.3673865e-06
variable is w1: 4.0  w2: -6.9889045  w3: 4.0  and the loss is  1.3659771e-06
variable is w1: 4.0  w2: -6.9889083  w3: 4.0  and the loss is  1.3645688e-06
variable is w1: 4.0  w2: -6.988912  w3: 4.0  and the loss is  1.3631613e-06
variable is w1: 4.0  w2: -6.988916  w3: 4.0  and the loss is  1.3617548e-06
variable is w1: 4.0  w2: -6.9889197  w3: 4.0  and the loss is  1.3603493e-06

TRAINABLE_VARIABLE=False

另一种限制variable被限制的方法,与上边的方法原理相似,都和tf.GraphKeys.TRAINABLE_VARIABLE有关,只不过前一个是从里边挑出指定scope,这个从变量定义时就决定了不往里插入这个变量。

不可训练和常量还是不同的,毕竟还能手动修改,比如滑动平均值的应用,不可训练像是专门针对optimizer的约定。

 

#demo2.4  another way to avoid variable be train

label = tf.constant(1,dtype = tf.float32)
x = tf.placeholder(dtype = tf.float32)
w1 = tf.Variable(4,dtype=tf.float32,trainable=False)
w2 = tf.Variable(4,dtype=tf.float32)
w3 = tf.constant(4,dtype=tf.float32)

y_predict = w1*x+w2*x+w3*x

#define losses and train
make_up_loss = (y_predict - label)**3
optimizer = tf.train.GradientDescentOptimizer(0.01)

output_vars = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES)
train_step = optimizer.minimize(make_up_loss,var_list = output_vars)

init = tf.global_variables_initializer()
with tf.Session() as sess:
    sess.run(init)
    for _ in range(3000):
        w1_,w2_,w3_,loss_ = sess.run([w1,w2,w3,make_up_loss],feed_dict={x:1})
        print('variable is w1:',w1_,' w2:',w2_,' w3:',w3_, ' and the loss is ',loss_)
        sess.run(train_step,{x:1})

获取所有trainable变量来train,也就等于不指定var_list直接train,是默认参数。

      var_list: Optional list or tuple of `Variable` objects to update to
        minimize `loss`.  Defaults to the list of variables collected in
        the graph under the key `GraphKeys.TRAINABLE_VARIABLES`.
#demo2.3  another way to avoid variable be train

label = tf.constant(1,dtype = tf.float32)
x = tf.placeholder(dtype = tf.float32)
#w1 = tf.Variable(4,dtype=tf.float32)
w1 = tf.Variable(4,dtype=tf.float32,trainable=False)
with tf.name_scope(name='selected_variable_to_trian'):
    w2 = tf.Variable(4,dtype=tf.float32)
w3 = tf.constant(4,dtype=tf.float32)

y_predict = w1*x+w2*x+w3*x

#define losses and train
make_up_loss = (y_predict - label)**3
optimizer = tf.train.GradientDescentOptimizer(0.01)

train_step = optimizer.minimize(make_up_loss)

init = tf.global_variables_initializer()
with tf.Session() as sess:
    sess.run(init)
    for _ in range(3000):
        w1_,w2_,w3_,loss_ = sess.run([w1,w2,w3,make_up_loss],feed_dict={x:1})
        print('variable is w1:',w1_,' w2:',w2_,' w3:',w3_, ' and the loss is ',loss_)
        sess.run(train_step,{x:1})

实际结果同上,略。

 

minimize()操作分解

其实minimize()操作也只是一个compute_gradients()和apply_gradients()的组合操作.

compute_gradients()用来计算梯度,opt.apply_gradients()用来更新参数。通过多个optimizer可以指定多个具有不同学习率的学习过程,针对不同的var_list分别进行gradient的计算和参数更新,可以用来迁移学习或者处理一些深层网络梯度更新不匹配的问题,暂不赘述。

#demo2.4  combine of ompute_gradients() and apply_gradients()

label = tf.constant(1,dtype = tf.float32)
x = tf.placeholder(dtype = tf.float32)
w1 = tf.Variable(4,dtype=tf.float32,trainable=False)
w2 = tf.Variable(4,dtype=tf.float32)
w3 = tf.Variable(4,dtype=tf.float32)

y_predict = w1*x+w2*x+w3*x

#define losses and train
make_up_loss = (y_predict - label)**3
optimizer = tf.train.GradientDescentOptimizer(0.01)

w2_gradient = optimizer.compute_gradients(loss = make_up_loss, var_list = w2)
train_step = optimizer.apply_gradients(grads_and_vars = (w2_gradient))

init = tf.global_variables_initializer()
with tf.Session() as sess:
    sess.run(init)
    for _ in range(300):
        w1_,w2_,w3_,loss_,w2_gradient_ = sess.run([w1,w2,w3,make_up_loss,w2_gradient],feed_dict={x:1})
        print('variable is w1:',w1_,' w2:',w2_,' w3:',w3_, ' and the loss is ',loss_)
        print('gradient:',w2_gradient_)
        sess.run(train_step,{x:1})

 

具体的learning rate、step、计算公式和手动梯度下降实现:

在预测中,x是关于y的变量,但是在train中,w是L的变量,x是不可能变化的。所以,知道为什么weights叫Variable了吧(强行瞎解释一发)

下面用tensorflow接口手动实现梯度下降:

为了方便写公式,下边的代码改了变量的命名,采用loss、prediction、gradient、weight、y、x等首字母表示,η表示学习率,w0、w1、w2等表示第几次迭代时w的值,不是多个变量。

loss=(y-p)^2=(y-w*x)^2=(y^2-2*y*w*x+w^2*x^2)

dl/dw = 2*w*x^2-2*y*x

代入梯度下降公式w1=w0-η*dL/dw|w=w0

w1 = w0-η*dL/dw|w=w0

w2 = w1 - η*dL/dw|w=w1

w3 = w2 - η*dL/dw|w=w2

 

初始:y=3,x=1,w=2,l=1,dl/dw=-2,η=1

更新:w=4

更新:w=2

更新:w=4

所以,本例x=1,y=3,dl/dw巧合的等于2w-2y,也就是二倍的prediction和label的差距。learning rate=1会导致w围绕正确的值来回徘徊,完全不收敛,这样写主要是方便演示计算。改小learning rate 并增加循环次数就能收敛了。

#demo4:manual gradient descent in tensorflow
#y label
y = tf.constant(3,dtype = tf.float32)
x = tf.placeholder(dtype = tf.float32)
w = tf.Variable(2,dtype=tf.float32)
#prediction
p = w*x

#define losses
l = tf.square(p - y)
g = tf.gradients(l, w)
learning_rate = tf.constant(1,dtype=tf.float32)
#learning_rate = tf.constant(0.11,dtype=tf.float32)
init = tf.global_variables_initializer()

#update
update = tf.assign(w, w - learning_rate * g[0])

with tf.Session() as sess:
    sess.run(init)
    print(sess.run([g,p,w], {x: 1}))
    for _ in range(5):
        w_,g_,l_ = sess.run([w,g,l],feed_dict={x:1})
        print('variable is w:',w_, ' g is ',g_,'  and the loss is ',l_)

        _ = sess.run(update,feed_dict={x:1})

结果:

learning rate=1

[[-2.0], 2.0, 2.0]
variable is w: 2.0  g is  [-2.0]   and the loss is  1.0
variable is w: 4.0  g is  [2.0]   and the loss is  1.0
variable is w: 2.0  g is  [-2.0]   and the loss is  1.0
variable is w: 4.0  g is  [2.0]   and the loss is  1.0
variable is w: 2.0  g is  [-2.0]   and the loss is  1.0

 效果类似下图

缩小learning rate

variable is w: 2.9964619  g is  [-0.007575512]   and the loss is  1.4347095e-05
variable is w: 2.996695  g is  [-0.0070762634]   and the loss is  1.2518376e-05
variable is w: 2.996913  g is  [-0.0066099167]   and the loss is  1.0922749e-05
variable is w: 2.9971166  g is  [-0.0061740875]   and the loss is  9.529839e-06
variable is w: 2.9973066  g is  [-0.0057668686]   and the loss is  8.314193e-06
variable is w: 2.9974842  g is  [-0.0053868294]   and the loss is  7.2544826e-06
variable is w: 2.9976501  g is  [-0.0050315857]   and the loss is  6.3292136e-06
variable is w: 2.997805  g is  [-0.004699707]   and the loss is  5.5218115e-06
variable is w: 2.9979498  g is  [-0.004389763]   and the loss is  4.8175043e-06
variable is w: 2.998085  g is  [-0.0041003227]   and the loss is  4.2031616e-06
variable is w: 2.9982114  g is  [-0.003829956]   and the loss is  3.6671408e-06
variable is w: 2.9983294  g is  [-0.0035772324]   and the loss is  3.1991478e-06

 

扩展:Momentum、Adagrad的自动和手动实现,这里嫌太长,分开了

 

源码

 

补充实操经验:

实际工程经常会使用global_step变量,作为动态学习率、EMABatch_Normalization操作的依据,在对所有可训练数据训练时,尤其ema选中所有可训练变量时,容易对global_step产生影响(本来是每一步+1,偏偏被加了个惯性,加了衰减系数),所以global_step一定要设定trainable=False。并且EMA等操作谨慎选择训练目标。

关于EMA与trainable=False,其实没有严格关系,但是通常有一定关系,EMA默认可能是获得所有可训练变量,如果给global_step设定trainable=False,就避免了被传入EMA的var_list,这也算是一个“你也不知道为什么,只是走运没出事儿”的常见案例了!!!

同样道理,BatchNormalization的average_mean和average_variance都是要设定trainable=False,都是他们单独维护的。

 

 

 

 

 
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

tensorflow中optimizer minimize自动训练简介和选择训练variable的方法 的相关文章

随机推荐

  • 【Java】Map和Set

    目录 一 搜索树 1 概念 2 操作 查找 3 操作 插入 4 操作 删除 难点 6 性能分析 二 搜索 1 概念及场景 2 模型 三 Map 的使用 1 关于Map的说明 2 关于Map Entry的说明 gt 3 Map 的常用方法说明
  • Shiro简单配置Springboot版(3)

    6 整合SpringBoot项目实战 6 0 整合思路 6 1 创建springboot项目 6 2 引入shiro依赖
  • 小雀和他的王国【牛客练习赛56 E】【Tarjan缩点+树的直径】

    题目链接 首先 如果它本身就是在环内了 那么 任意的破坏环上的任意条边 都是不会影响答案的 所以 我们可以知道 会映像答案的边只有那些桥 于是 做法就变成了Tarjan缩点 然后就变成了一棵树了 我们现在想要构成最大的环 于是任务就变成了找
  • python 查tensorflow版本_查看已安装tensorflow版本

    由于tensorflow版本不同 可能一些函数的调用也有变换 这时候可能需要查看tensorflow版本 可以在终端输入查询命令如下 python import tensorflow as tf tf version 查询tensorflo
  • Android内存优化的10条建议

    合理设置应用的minSdkVersion和targetSdkVersion 使应用可以运行在更多设备上 这可以提高内存利用效率 避免在Application和Activity的onCreate方法中做过多工作 这会占用过多内存 可以将不必要
  • Spring 定时器 No qualifying bean of type [org.springframework.scheduling.TaskScheduler] is defined

    最近项目里面 用了spring的定时任务 一直以来 项目运行的不错 定时器也能正常使用 可是 今天启动项目测试的时候 盯着启动Log看了一阵子 突然间发现 启动的Log中居然有一个异常 虽然一闪而过 但是那熟悉的异常格式还是让我浑身一颤 这
  • 启动hive报错_Power BI连接Hive数据库

    要想实现Powe BI连接Hive数据库 需要安装一个驱动进行配置 同时服务器开启hiveserver2在后台运行 1 下载ClouderaHiveODBC64 https downloads cloudera com connectors
  • windows安装mingw编译c程序

    这篇文章主要介绍在windows下安装mingw 编译c代码的详细步骤 mingw是在windows下面的gcc 有了mingw 以前在linux下面编写的c代码也能在window下面编译运行啦 1 第一步 下载mingw 下载mingw很
  • 从程序员的角度看待算法的学习与研究

    一 引言 算法的重要性和应用场景 提高效率 算法可以帮助我们设计和实现高效的解决方案 在有限的资源下 提高计算机程序或系统的执行速度和效率 解决复杂问题 算法可以提供有效的解决方案来解决各种复杂问题 例如图像处理 自然语言处理 数据分析等领
  • 微软疑断自由软件开发者“活路”,禁止在微软商店发布商业开源

    整理 彭慧中 责编 屠敏 出品 CSDN ID CSDNnews 几周前 微软更新了其应用商店的政策 增加了新的政策 将于下周开始生效 其中包括以下文字 所有定价 都不能 企图从开源或其他普遍免费的软件中获取经济利益 图源SFC 原本大家以
  • Python记3(类与对象、路径、文件、异常处理、抽象基类

    目录 1 Class 1 1 声明类 1 2 类的特殊属性 1 3 创建对象 1 4 构造函数和析构函数 1 5 类方法和静态方法 类变量与实例变量 1 6 公有 保护 私有变量 通过下划线数量和位置区分 1 7 继承 1 7 1 多继承M
  • MATLAB编程(3)——MATLAB依次运行多个脚本.m文件

    问题描述 在做算法对比实验时 经常需要依次运行多个算法的代码 每个算法的入口程序是一个脚本 m文件 当然 算法的脚本文件中又会调用算法自己的子函数 我们期望MATLAB依次运行这些对比算法的脚本 m文件 而不用等到一个算法的程序执行结束后
  • 一次诡异的linux系统重启故障

    情况描述 同事反应说oracle数据库在周末的时候宕了 排查下问题 登到服务器上发现 oracle进程已经不存在 然后ps看了下监听进程 发现也不存在 这时候就怀疑是操作系统重启了 操作系统版本信息 root card paopi log
  • cmake add_subdirectory添加父级目录及其子目录的源码

    cmake add subdirectory添加父级目录及其子目录的源码 1 目录结构 tree main CMakeLists txt main cpp thirdlib CMakeLists txt myprintf cpp mypri
  • perl:取整、四舍五入、向上取整、向下取整

    取整int 四舍五入round 向上取整POSIX ceil 向下取整就是int或者POSIX floor 其中ceil和floor 要使用库POSIX 在perl源代码里加入 usr bin perl use strict use war
  • 为什么我们需要 HTTP/3?QUIC协议成功“上位”。

    TCP 是 Internet 上使用和部署最广泛的协议之一 多年来一直被视为网络基石 随着HTTP 3正式被标准化 QUIC协议成功 上位 UDP 取代 TCP成为基础协议 TCP究竟 输 在哪里 TCP与HTTP的不解之缘 HTTP 超文
  • 获取光标,并且移动至最后

    准备一个元素 div div 调用获取光标方法 传入元素 this keepLastIndex document getElementById sendMessageInput keepLastIndex obj if window get
  • nodeJS ---包管理工具

    包管理工具 一 概念介绍 1 1 包是什么 包 英文单词是 package 代表了一组特定功能的源码集合 1 2 包管理工具 管理 包 的应用软件 可以对 包 进行 下载安装 更新 删除 上传 等操作 借助包管理工具 可以快速开发项目 提升
  • 【React】 18课 简单理解redux

    本章主要讲redux的js文件内的代码原理以及使用方法 简单理解redux是干什么的 其实redux与vuex类似 是用于redux内各组件间通讯的数据存储仓库 首先我们来看以下文件目录结构 在此之前我们需要给React项目安装redux插
  • tensorflow中optimizer minimize自动训练简介和选择训练variable的方法

    本文主要介绍tensorflow的自动训练的相关细节 并把自动训练和基础公式结合起来 如有不足 还请指教 写这个的初衷 有些教程说的比较模糊 没体现出用意和特性或应用场景 面向对象 稍微了解点代码 又因为有限的教程讲解比较模糊而一知半解的初