【问题标题】:tf.where causes optimiser to fail in tensorflowtf.where 导致优化器在张量流中失败
【发布时间】:2017-04-21 13:28:21
【问题描述】:

我想检查是否可以使用 tensorflow 而不是 pymc3 解决 this 问题。实验的想法是我将定义一个包含开关点的概率系统。我可以使用采样作为推理方法,但我开始想知道为什么我不能只使用梯度下降来做到这一点。

我决定在 tensorflow 中进行梯度搜索,但是当涉及 tf.where 时,似乎 tensorflow 很难执行梯度搜索。

您可以在下面找到代码。

import tensorflow as tf
import numpy as np

x1 = np.random.randn(50)+1
x2 = np.random.randn(50)*2 + 5
x_all = np.hstack([x1, x2])
len_x = len(x_all)
time_all = np.arange(1, len_x + 1)

mu1 = tf.Variable(0, name="mu1", dtype=tf.float32)
mu2 = tf.Variable(5, name = "mu2", dtype=tf.float32)
sigma1 = tf.Variable(2, name = "sigma1", dtype=tf.float32)
sigma2 = tf.Variable(2, name = "sigma2", dtype=tf.float32)
tau = tf.Variable(10, name = "tau", dtype=tf.float32)

mu = tf.where(time_all < tau,
              tf.ones(shape=(len_x,), dtype=tf.float32) * mu1,
              tf.ones(shape=(len_x,), dtype=tf.float32) * mu2)
sigma = tf.where(time_all < tau,
              tf.ones(shape=(len_x,), dtype=tf.float32) * sigma1,
              tf.ones(shape=(len_x,), dtype=tf.float32) * sigma2)

likelihood_arr = tf.log(tf.sqrt(1/(2*np.pi*tf.pow(sigma, 2)))) -tf.pow(x_all - mu, 2)/(2*tf.pow(sigma, 2))
total_likelihood = tf.reduce_sum(likelihood_arr, name="total_likelihood")

optimizer = tf.train.RMSPropOptimizer(0.01)
opt_task = optimizer.minimize(-total_likelihood)
init = tf.global_variables_initializer()

with tf.Session() as sess:
    sess.run(init)
    print("these variables should be trainable: {}".format([_.name for _ in tf.trainable_variables()]))
    for step in range(10000):
        _lik, _ = sess.run([total_likelihood, opt_task])
        if step % 1000 == 0:
            variables = {_.name:_.eval() for _ in [mu1, mu2, sigma1, sigma2, tau]}
            print("step: {}, values: {}".format(str(step).zfill(4), variables))

你会注意到 tau 参数并没有改变,即使 tensorflow 似乎知道变量并且它是梯度。关于出了什么问题的任何线索?这是可以在张量流中计算的东西还是我需要不同的模式?

【问题讨论】:

    标签: python python-3.x tensorflow


    【解决方案1】:

    tau 仅用于 condition 的参数 where: (tf.where(time_all &lt; tau, ...) ,这是一个布尔张量。由于计算梯度只对连续值有意义,因此输出相对于tau 的梯度将为零。

    即使忽略tf.where,您在表达式time_all &lt; tau 中使用了tau,它几乎处处都是常数,因此梯度为零。

    由于梯度为零,无法用梯度下降法学习tau

    根据您的问题,您可以使用加权和代替p*val1 + (1-p)*val2,而不是两个值之间的硬切换,其中p 以连续方式依赖于tau

    【讨论】:

      【解决方案2】:

      分配的解决方案是正确答案,但不包含我的问题的代码解决方案。以下 sn-p 可以;

      import tensorflow as tf
      import numpy as np
      import os
      import uuid
      
      TENSORBOARD_PATH = "/tmp/tensorboard-switchpoint"
      # tensorboard --logdir=/tmp/tensorboard-switchpoint
      
      x1 = np.random.randn(35)-1
      x2 = np.random.randn(35)*2 + 5
      x_all = np.hstack([x1, x2])
      len_x = len(x_all)
      time_all = np.arange(1, len_x + 1)
      
      mu1 = tf.Variable(0, name="mu1", dtype=tf.float32)
      mu2 = tf.Variable(0, name = "mu2", dtype=tf.float32)
      sigma1 = tf.Variable(2, name = "sigma1", dtype=tf.float32)
      sigma2 = tf.Variable(2, name = "sigma2", dtype=tf.float32)
      tau = tf.Variable(15, name = "tau", dtype=tf.float32)
      switch = 1./(1+tf.exp(tf.pow(time_all - tau, 1)))
      
      mu = switch*mu1 + (1-switch)*mu2
      sigma = switch*sigma1 + (1-switch)*sigma2
      
      likelihood_arr = tf.log(tf.sqrt(1/(2*np.pi*tf.pow(sigma, 2)))) - tf.pow(x_all - mu, 2)/(2*tf.pow(sigma, 2))
      total_likelihood = tf.reduce_sum(likelihood_arr, name="total_likelihood")
      
      optimizer = tf.train.AdamOptimizer()
      opt_task = optimizer.minimize(-total_likelihood)
      init = tf.global_variables_initializer()
      
      tf.summary.scalar("mu1", mu1)
      tf.summary.scalar("mu2", mu2)
      tf.summary.scalar("sigma1", sigma1)
      tf.summary.scalar("sigma2", sigma2)
      tf.summary.scalar("tau", tau)
      tf.summary.scalar("likelihood", total_likelihood)
      merged_summary_op = tf.summary.merge_all()
      
      with tf.Session() as sess:
          sess.run(init)
          print("these variables should be trainable: {}".format([_.name for _ in tf.trainable_variables()]))
          uniq_id = os.path.join(TENSORBOARD_PATH, "switchpoint-" + uuid.uuid1().__str__()[:4])
          summary_writer = tf.summary.FileWriter(uniq_id, graph=tf.get_default_graph())
          for step in range(40000):
              lik, opt, summary = sess.run([total_likelihood, opt_task, merged_summary_op])
              if step % 100 == 0:
                  variables = {_.name:_.eval() for _ in [total_likelihood]}
                  summary_writer.add_summary(summary, step)
                  print("i{}: {}".format(str(step).zfill(5), variables))
      

      【讨论】:

        猜你喜欢
        • 2017-01-29
        • 1970-01-01
        • 1970-01-01
        • 2018-07-20
        • 2020-11-09
        • 1970-01-01
        • 1970-01-01
        • 2011-04-20
        • 1970-01-01
        相关资源
        最近更新 更多