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

时间:2018-08-21 11:58:55

标签: python tensorflow deep-learning hessian-matrix

假设我要针对某些参数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展平为称为flat_params的一维张量:

    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也成立),张量流无法看到图中的paramsflat_params与{{ 1}}将引发错误,因为渐变将被视为tf.hessians(loss, flat_params)

  • https://afqueiruga.github.io/tensorflow/2017/12/28/hessian-mnist.html中,代码的编写者采用另一种方法,首先创建flat参数并将其部分重塑为None。此技巧确实有效,并且具有 expected 形状(2x2矩阵)的粗麻布效果。但是,在我看来,当您拥有复杂的模型时,这将很麻烦,并且如果通过内置函数(例如self.params等创建模型,则无法应用)。

tf.layers.dense是任意形状的张量列表时,没有直接方法可以从tf.hessians获取Hessian矩阵(在此示例中为2x2矩阵)吗?如果没有,如何自动self.params的输出张量重塑?

1 个答案:

答案 0 :(得分:1)

(根据TensorFlow r1.13)证明,如果len(xs)> 1,则tf.hessians(ys,xs)返回仅与完整Hessian矩阵的块对角线子矩阵相对应的张量。本文https://arxiv.org/pdf/1905.05559的全文和解决方案,以及https://github.com/gknilsen/pyhessian的代码