假设我想计算一个标量值函数关于某些参数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
变成一个大小不等的张量列表时(例如,当模型是一个深层神经网络时),这个操作可能非常麻烦。在
似乎有两种方法可以解决这个问题:
将params
展平为1D张量,称为flat_params
:
因此tf.hessians(loss, flat_params)
自然返回一个2x2矩阵。然而,正如Why does Tensorflow Reshape tf.reshape() break the flow of gradients?中所述tf.梯度(但也适用于黑森tf),tensorflow无法在图中看到params
和{tf.hessians(loss, flat_params)
将引发错误,因为渐变将被视为None
。
在https://afqueiruga.github.io/tensorflow/2017/12/28/hessian-mnist.html中,代码的作者走另一条路,首先创建flat参数并将其部分重塑为self.params
。sian矩阵(hesm)的形状得到了预期的结果。然而,在我看来,当您有一个复杂的模型时,这将是一个麻烦的使用,并且如果您通过内置函数(如tf.layers.dense
,…)创建模型,则不可能应用。
当tf.hessians
是任意形状的张量列表时,没有直接的方法从tf.hessians
得到Hessian矩阵(如本例中的2x2矩阵)吗?如果不是,如何自动地对tf.hessians
的输出张量进行整形?在
结果是(根据TensorFlow r1.13)如果len(xs)>1,那么黑森tf(ys,xs)返回只对应于完整Hessian矩阵的块对角子矩阵的张量。本文的全部内容和解决方案https://arxiv.org/pdf/1905.05559,代码位于https://github.com/gknilsen/pyhessian
相关问题 更多 >
编程相关推荐