首页 文章

在展平参数张量上使用tf.gradients或tf.hessians

提问于
浏览
3

假设我想计算关于某些参数W(例如前馈神经网络的权重和偏差)的标量值函数的Hessian . 如果您考虑以下代码,则实施经过培训以最小化MSE损失的二维线性模型:

import numpy as np
import tensorflow as tf

x = tf.placeholder(dtype=tf.float32, shape=[None, 2])  #inputs
t = tf.placeholder(dtype=tf.float32, shape=[None,])  #labels
W = tf.placeholder(np.eye(2), dtype=tf.float32)  #weights

preds = tf.matmul(x, W)  #linear model
loss = tf.reduce_mean(tf.square(preds-t), axis=0) #mse loss

params = tf.trainable_variables() 
hessian = tf.hessians(loss, params)

你希望 session.run(tf.hessian,feed_dict={}) 返回一个2x2矩阵(等于W) . 事实证明,因为 params 是一个2x2张量,输出是一个形状为[2,2,2,2]的张量 . 虽然我可以很容易地重新形成张量以获得我想要的矩阵,但是当 params 成为不同大小的张量列表时(例如,当模型是深度神经网络时),这个操作似乎非常麻烦 .

看来这有两种方式:

  • Flatten params 是一个名为 flat_params 的1D张量:
flat_params = tf.concat([tf.reshape(p, [-1]) for p in params])

这样 tf.hessians(loss, flat_params) 自然地返回一个2x2矩阵 . 但是如Why does Tensorflow Reshape tf.reshape() break the flow of gradients?中针对tf.gradients所述(但也适用于tf.hessians),tensorflow无法在 paramsflat_params 之间看到图形中的符号链接,并且 tf.hessians(loss, flat_params) 将引发错误,因为渐变将被视为 None .

  • https://afqueiruga.github.io/tensorflow/2017/12/28/hessian-mnist.html中,代码的作者采用另一种方式,首先创建flat参数并将其部件重新整形为 self.params . 这个技巧确实有效,可以获得具有预期形状(2x2矩阵)的粗麻布 . 但是,在我看来,当你有一个复杂的模型时,这将很麻烦,如果你通过内置函数(如 tf.layers.dense ,..)创建模型,则无法应用 .

self.params 是任意形状的张量列表时,是否没有直接的方法从 tf.hessians 获得Hessian矩阵(如本例中的2x2矩阵)?如果没有,你怎么能自动化 tf.hessians 的输出张量的整形呢?

1 回答

相关问题