张量流中的多变量正态偏差的CDF

时间:2016-08-23 17:08:05

标签: python tensorflow cdf

我可以从here运行此示例:

mu = [1, 2, 3.]
diag_stdev = [4, 5, 6.]
dist = tf.contrib.distributions.MultivariateNormalDiag(mu, diag_stdev)
dist.pdf([-1., 0, 1])

但是当我用最后一行代替dist.cdf([-1., 0, 1])时,我得到一个未实现的错误:

NotImplementedError: log_cdf is not implemented

至少暂时有人建议解决方法吗?

1 个答案:

答案 0 :(得分:1)

根据herehere中的解决方案,我实施了以下解决方案:

import tensorflow as tf
import numpy as np
from scipy.stats import mvn

def py_func(func, inp, Tout, stateful=True, name=None, grad=None):

    # Need to generate a unique name to avoid duplicates:
    rnd_name = 'PyFuncGrad' + str(np.random.randint(0, 1E+10))

    tf.RegisterGradient(rnd_name)(grad)
    g = tf.get_default_graph()
    with g.gradient_override_map({"PyFunc": rnd_name}):
        return tf.py_func(func, inp, Tout, stateful=stateful, name=name)

def np_cdf(mean, diag_sigma, value, name=None):
  low = np.array([-30, -30])
  cdf = list()
  for variables in zip(value, mean, diag_sigma):
    S = np.diag(variables[2])
    p, _ = mvn.mvnun(low,variables[0],variables[1],S)
    cdf.append(p)

  cdfs = np.asarray(cdf, dtype=np.float32).reshape([-1,1])
  return cdfs

def cdf_gradient(op, grad): 
  mu = op.inputs[0]
  diag_sigma = op.inputs[1]
  value = op.inputs[2]
  dist = tf.contrib.distributions.MultivariateNormalDiag(mu, diag_sigma)
  pdf = dist.pdf(value)
  dc_dv = tf.inv(diag_sigma) * pdf
  dc_dm = -1 * dc_dv
  dc_ds = tf.div(value-mu,tf.square(diag_sigma)+1e-6) * pdf
  return grad * dc_dm, grad * dc_ds, grad * dc_dv

def tf_cdf(mean, diag_sigma, value, name=None):

    with tf.name_scope(name, "MyCDF", [mean, diag_sigma, value]) as name:
        cdf = py_func(np_cdf,
                        [mean, diag_sigma, value],
                        [tf.float32],
                        name=name,
                        grad=cdf_gradient)  # <-- here's the call to the gradient
        return cdf[0]