Python 关于矩阵的张量流梯度

Python 关于矩阵的张量流梯度,python,matrix,tensorflow,gradient-descent,reinforcement-learning,Python,Matrix,Tensorflow,Gradient Descent,Reinforcement Learning,就为了上下文,我正在尝试用Tensorflow实现一个梯度下降算法 我有一个矩阵X [ x1 x2 x3 x4 ] [ x5 x6 x7 x8 ] 我将其乘以某个特征向量Y,得到Z [ y1 ] Z = X [ y2 ] = [ z1 ] [ y3 ] [ z2 ] [ y4 ] 然后我让Z通过一个softmax函数,并获取日志。我将输出矩阵称为W 所有这些都是按如下方式实现的(添加了一点样板文件,因此可以运行) W(对应于操作\u problog

就为了上下文,我正在尝试用Tensorflow实现一个梯度下降算法

我有一个矩阵
X

[ x1 x2 x3 x4 ]
[ x5 x6 x7 x8 ]
我将其乘以某个特征向量
Y
,得到
Z

      [ y1 ]
Z = X [ y2 ]  = [ z1 ]
      [ y3 ]    [ z2 ]
      [ y4 ]
然后我让Z通过一个softmax函数,并获取日志。我将输出矩阵称为W

所有这些都是按如下方式实现的(添加了一点样板文件,因此可以运行)

W(对应于
操作\u problogs
)看起来像

[ w1 ]
[ w2 ]
我想找到关于矩阵X的
w1
的梯度,也就是说,我想计算

          [ d/dx1 w1 ]
d/dX w1 =      .
               .
          [ d/dx8 w1 ]
(最好还是看起来像一个矩阵,这样我就可以将它添加到
X
,但我真的不担心这个问题)

我希望
tf.gradients
能起到作用。我是这样计算“梯度”的

然而,当我检查
problog\u gradient
时,我得到的是

[<tf.Tensor 'foo_4/gradients/foo_4/MatMul_grad/MatMul:0' shape=(2, 4) dtype=float32>]
[]
请注意,它的形状与
X
完全相同,但实际上不应该如此。我希望得到两个渐变的列表,每个渐变对应8个元素。我怀疑我得到的是两个梯度,但每个梯度都是关于四个元素的


我对tensorflow非常陌生,因此我希望了解和解释正在发生的事情以及如何实现我想要的行为。

tf。梯度实际上是对Y进行求和,并计算Y的梯度,这就是为什么会出现这个问题

渐变需要一个标量函数,因此默认情况下,它对条目求和。这是默认行为,因为所有梯度下降算法都需要这种功能,而随机梯度下降(或其变体)是Tensorflow中的首选方法。你找不到任何更高级的算法(比如BFGS之类的),因为它们根本还没有实现(它们需要一个真正的雅可比矩阵,而雅可比矩阵也还没有实现)。不管它有什么价值,这里是我写的一个功能性雅可比实现:

def map(f, x, dtype=None, parallel_iterations=10):
    '''
    Apply f to each of the elements in x using the specified number of parallel iterations.

    Important points:
    1. By "elements in x", we mean that we will be applying f to x[0],...x[tf.shape(x)[0]-1].
    2. The output size of f(x[i]) can be arbitrary. However, if the dtype of that output
       is different than the dtype of x, then you need to specify that as an additional argument.
    '''
    if dtype is None:
        dtype = x.dtype

    n = tf.shape(x)[0]
    loop_vars = [
        tf.constant(0, n.dtype),
        tf.TensorArray(dtype, size=n),
    ]
    _, fx = tf.while_loop(
        lambda j, _: j < n,
        lambda j, result: (j + 1, result.write(j, f(x[j]))),
        loop_vars,
        parallel_iterations=parallel_iterations
    )
    return fx.stack()

def jacobian(fx, x, parallel_iterations=10):
    '''
    Given a tensor fx, which is a function of x, vectorize fx (via tf.reshape(fx, [-1])),
    and then compute the jacobian of each entry of fx with respect to x.
    Specifically, if x has shape (m,n,...,p), and fx has L entries (tf.size(fx)=L), then
    the output will be (L,m,n,...,p), where output[i] will be (m,n,...,p), with each entry denoting the
    gradient of output[i] wrt the corresponding element of x.
    '''
    return map(lambda fxi: tf.gradients(fxi, x)[0],
               tf.reshape(fx, [-1]),
               dtype=x.dtype,
               parallel_iterations=parallel_iterations)
def映射(f,x,dtype=None,parallel_迭代=10):
'''
使用指定的并行迭代次数将f应用于x中的每个元素。
要点:
1.所谓“x中的元素”,我们的意思是将f应用于x[0],…x[tf.shape(x)[0]-1]。
2.f(x[i])的输出大小可以是任意的。但是,如果该输出的数据类型
与x的数据类型不同,则需要将其指定为附加参数。
'''
如果数据类型为“无”:
dtype=x.dtype
n=tf.形状(x)[0]
循环变量=[
tf.常数(0,n.dtype),
tf.TensorArray(数据类型,大小=n),
]
_,fx=tf.while\u循环(
λj,uj
虽然此实现可以工作,但当您尝试嵌套它时,它不工作。 例如,如果您尝试使用雅可比(雅可比(…)
计算Hessian,则会出现一些奇怪的错误。这是被跟踪的。我仍然不明白这为什么会出错。我相信while循环实现或gradient实现中都存在深层次的bug,但我真的不知道

无论如何,如果你只需要一个雅可比矩阵,试试上面的代码

[<tf.Tensor 'foo_4/gradients/foo_4/MatMul_grad/MatMul:0' shape=(2, 4) dtype=float32>]
def map(f, x, dtype=None, parallel_iterations=10):
    '''
    Apply f to each of the elements in x using the specified number of parallel iterations.

    Important points:
    1. By "elements in x", we mean that we will be applying f to x[0],...x[tf.shape(x)[0]-1].
    2. The output size of f(x[i]) can be arbitrary. However, if the dtype of that output
       is different than the dtype of x, then you need to specify that as an additional argument.
    '''
    if dtype is None:
        dtype = x.dtype

    n = tf.shape(x)[0]
    loop_vars = [
        tf.constant(0, n.dtype),
        tf.TensorArray(dtype, size=n),
    ]
    _, fx = tf.while_loop(
        lambda j, _: j < n,
        lambda j, result: (j + 1, result.write(j, f(x[j]))),
        loop_vars,
        parallel_iterations=parallel_iterations
    )
    return fx.stack()

def jacobian(fx, x, parallel_iterations=10):
    '''
    Given a tensor fx, which is a function of x, vectorize fx (via tf.reshape(fx, [-1])),
    and then compute the jacobian of each entry of fx with respect to x.
    Specifically, if x has shape (m,n,...,p), and fx has L entries (tf.size(fx)=L), then
    the output will be (L,m,n,...,p), where output[i] will be (m,n,...,p), with each entry denoting the
    gradient of output[i] wrt the corresponding element of x.
    '''
    return map(lambda fxi: tf.gradients(fxi, x)[0],
               tf.reshape(fx, [-1]),
               dtype=x.dtype,
               parallel_iterations=parallel_iterations)