在Tensorflow和范围中重新分配变量

时间:2018-05-12 20:43:17

标签: python tensorflow rotational-matrices

我试图理解其中一个实现之所以有效,而另一个之所以没有。我试图在tensorflow中表示一些几何。

首先是帮助文件d_math.py

!/ usr / bin / env python3

将numpy导入为np 导入tensorflow为tf

dtype = tf.float64

def skew_symmetric(vector):
    #Creates a tensorflow matrix which is a skew-symmetric version of the input vector    
    return tf.stack([(0., -vector[2], vector[1]), (vector[2], 0., -vector[0]), (-vector[1], vector[0], 0.)], axis=0)

以下是实施1:

#!/usr/bin/env python3
import numpy as np
import tensorflow as tf
import d_math as d
import math
import time


class Joint():
    def __init__(self, axis, pos): #TODO: right now only revolute:
        axis_ = tf.Variable(axis, dtype=d.dtype)
        axis_ /= tf.linalg.norm(axis)
        theta_ = tf.Variable(0.0, dtype=d.dtype) #Always at the 0 angle config
        self.theta_ = theta_
        self.R_ = tf.cos(theta_) * tf.eye(3, dtype=d.dtype) + d.skew_symmetric(axis_) + (1. - tf.cos(theta_)) * tf.einsum('i,j->ij', axis_, axis_)



joint = Joint(np.array([1.0, 1.0, 1.0]), 0.0)
init = tf.global_variables_initializer()    

with tf.Session() as session:
    session.run(init)    
    print(joint.R_)
    print(joint.R_.eval())
    joint.theta_ = joint.theta_.assign(math.pi/4.)
    session.run(joint.theta_)
    print(joint.R_.eval())

上面的版本更新了theta,然后我得到了两个旋转矩阵的评估,一个用于theta = 0,另一个用于theta = pi / 4.

然后我尝试重构我的代码,添加一个全局会话变量,在一个单独的文件中创建,并尽可能多地隐藏在我的API中的tensorflow:

版本2:

#!/usr/bin/env python3
import numpy as np
import tensorflow as tf
import d_math as d
import math
import time
import session as s


class Joint():
    def __init__(self, axis, pos): #TODO: right now only revolute:
        axis_ = tf.Variable(axis, dtype=d.dtype)
        axis_ = axis_ / tf.linalg.norm(axis)
        theta_ = tf.Variable(0.0, dtype=d.dtype) #Always at the 0 angle config
        self.theta_ = theta_
        self.R_ = tf.cos(theta_) * tf.eye(3, dtype=d.dtype) + d.skew_symmetric(axis_) + (1. - tf.cos(theta_)) * tf.einsum('i,j->ij', axis_, axis_)

    def set_theta(self, theta):
        self.theta_.assign(theta)
        s.session.run(self.theta_)


joint = Joint(np.array([1.0, 1.0, 1.0]), 0.0)
init = tf.global_variables_initializer()    

with s.session as session:
    session.run(init)  
    print(joint.R_)
    print(joint.R_.eval())
    #joint.theta_ = joint.theta_.assign(math.pi/4.)
    joint.set_theta(math.pi/4.)
    print(joint.R_.eval())
在这里可以看到

session.py:

#!/usr/bin/env python3
import tensorflow as tf

session = tf.Session()

对于两个评估,这给出了具有θ= 0的R矩阵。

有人可以向我解释为什么实施2不起作用?

1 个答案:

答案 0 :(得分:1)

tf.assign返回更新变量的引用。根据文档:Returns: A Tensor that will hold the new value of 'ref' after the assignment has completed.

在第一个示例中,您实际上正在使用更新的参考:

joint.theta_ = joint.theta_.assign(math.pi/4.)
session.run(joint.theta_)
print(joint.R_.eval())

在第二个示例中,您未使用更新的参考:

 def set_theta(self, theta):
    not_used = self.theta_.assign(theta)
    s.session.run(self.theta_)

我最好的猜测是,如果您使用更新的参考,它应该有效:

def set_theta(self, theta):
    self.theta_ = self.theta_.assign(theta)
    s.session.run(self.theta_)

另外,不要覆盖原始张量引用是明智的,所以我会为更新的var创建一个新属性:

def set_theta(self, theta):
    self.theta_updated_ = self.theta_.assign(theta)
    s.session.run(self.theta_updated_)

# ...
print(self.theta_updated_.eval())  # <<< This should give you updated value

重要:但是,运行print(joint.R_.eval())可能仍然不会为您提供更新的值,因为操作self.R_未强制执行以取决于更新的参考self.theta_updated_和您可能必须使用tf.control_dependencies仅在更新完成后强制执行self.R_操作。例如:

with tf.control_dependencies([self.theta_updated_]):
    self.R_ = tf.cos(theta_) * # ...

最终注释:为变量分配值并不会自动告诉其他操作他们需要等到此分配完成。我发现这很难。以下是我编写的一些snippets,用于跟踪使用tf.assign时变量的行为方式。我建议您仔细阅读名为Optimizing original variables that have been updated using tf.assign的代码段。这些片段是自包含的。