Вычисление векторизованного гессиана в Tensorflow - PullRequest
0 голосов
/ 06 января 2019

Задача

Рассмотрим проблему настройки

x   : A (N, K) tensor that we want to differentiate with respect to.
f(x): A function sending x to a scalar i.e.
          f: R^(N x K) -> R

То, что я хочу найти, - это каждое наблюдение x[i,:] (размер N ось), градиент (N x K) и гессиан (N x K x K).

Градиенты

Теперь градиенты в каждом наблюдении легко найти, так как вам просто нужно найти градиент f относительно всех x значений, т.е.

df/dx[0,0]  ...  df/dx[0,K]
  .                .
  .                .
  .                .
df/dx[N,0]  ...  df/dx[N,K]

, что можно сделать просто с помощью

tf.gradients(f(x), x)

гессенцы

Теперь у меня проблема с поиском размера (N, K, K) гессенского тензора. Если я использую функцию tf.hessians наивно, т.е.

tf.hessians(f(x), x)

это находит (правильно) тензор (N, K, N, K) частичных вторых производных, даже для значений x между наблюдениями. Это всегда 0 (в моем случае), поэтому для больших значений N это может быть очень неэффективно.

Как заставить Tensorflow находить только N (K x K) матрицы Гессена с j, k записями df/(dx[i,j]dx[i,k]), для наблюдения i?

Я думаю, что может быть циклическое решение для значений 0, ..., N-1, однако N также не известен статическому графику, он только динамически определяется для новых входных данных.

Пустой код

Ниже приведен минимальный рабочий пример, иллюстрирующий проблему.

import tensorflow as tf
import numpy as np

N = 2
K = 3

# Create dummy data.
x_np = np.random.rand(N, K).astype(np.float32)

# Define Tensorflow graph.
x = tf.placeholder(tf.float32, shape=(None, K), name='x')
f = tf.reduce_sum(tf.multiply(x, x), name='f')

grad = tf.gradients(f, x, name='grad')
hess = tf.hessians(f, x, name='hess')

# Run the Tensorflow graph.
sess = tf.Session()

print("\nTensorflow gradient:")
print(sess.run(grad, feed_dict={'x:0': x_np})[0])

print("\nTensorflow Hessian:")
hess_tf = sess.run(hess, feed_dict={'x:0': x_np})[0]
print(hess_tf)

# Show how we can get the Hessian we want from `hess_tf`.
hess_np = np.empty([N, K, K])
for i in range(N):
    hess_np[i, :, :] = hess_tf[i, :, i, :]

print("\nWanted Hessian:")
print(hess_np)
...