用于GPflow模型的预计算张量流张量

时间:2018-06-25 12:34:34

标签: python tensorflow gpflow

我想将一个稀疏的高斯过程模型(来自GPflow库)包含到另一个项目中。问题是我不能一次为多个输入调用预测函数,但必须顺序调用它。我已经检查了SGPR类(https://github.com/GPflow/GPflow/blob/master/gpflow/models/sgpr.py)中的预测函数predict_F,发现我可以预先进行很多预计算。因此,我制作了SGPR的子类,并编写了一种方法precompute,修改后的预测功能:

async

但是当我运行代码时,速度没有差别。我想张量流仅在调用predict_f时才执行所有表达式,但是我不知道如何显式预计算某些张量。希望tensorflow大师能够帮助我,在此先感谢!

1 个答案:

答案 0 :(得分:0)

我找到了一个愚蠢但简单的解决方案。这是SGPR类的包装器,该包装器会预先计算一些常用矩阵,然后将其用于预测。

from gpflow.models import GPModel, SGPR
from gpflow.decors import params_as_tensors, autoflow
from gpflow import settings
from gpflow.params import Parameter, DataHolder
import tensorflow as tf

class fastSGPR(SGPR, GPModel):
    def __init__(self,X_tr, Y_tr, kernel, Zp):
        gpflow.models.SGPR.__init__(self,X_tr, Y_tr, kern=kernel, Z=Zp)
        print("Model has been initialized")

    @autoflow()
    @params_as_tensors
    def precompute(self):
        print("Precomputing required tensors...")
        p_num_inducing = len(self.feature)
        p_err = self.Y - self.mean_function(self.X)
        p_Kuf = self.feature.Kuf(self.kern, self.X)
        p_Kuu = self.feature.Kuu(self.kern, jitter=settings.numerics.jitter_level)
        p_sigma = tf.sqrt(self.likelihood.variance)
        self.p_L = tf.cholesky(p_Kuu)
        p_A = tf.matrix_triangular_solve(self.p_L, p_Kuf, lower=True) / p_sigma
        p_B = tf.matmul(p_A, p_A, transpose_b=True) + tf.eye(p_num_inducing, dtype=settings.tf_float)

        self.p_LB = tf.cholesky(p_B)
        p_Aerr = tf.matmul(p_A, p_err)
        self.p_c = tf.matrix_triangular_solve(self.p_LB, p_Aerr, lower=True) / p_sigma
        print("Tensors have been precomputed")
        return self.p_L, self.p_LB, self.p_c

    @autoflow((settings.float_type, [None, None]), (settings.float_type, [None, None]), (settings.float_type, [None, None]), (settings.float_type, [None, None]))
    def predict_f(self, Xnew, L, LB, c):
        """
        Compute the mean and variance of the latent function(s) at the points
        Xnew.
        """
        return self._build_predict(Xnew, L, LB, c)

    @params_as_tensors
    def _build_predict(self, Xnew, L, LB, c, full_cov=False):
        """
        Compute the mean and variance of the latent function at some new points
        Xnew. For a derivation of the terms in here, see the associated SGPR
        notebook.
        """
        Kus = self.feature.Kuf(self.kern, Xnew)
        tmp1 = tf.matrix_triangular_solve(L, Kus, lower=True)
        tmp2 = tf.matrix_triangular_solve(LB, tmp1, lower=True)
        mean = tf.matmul(tmp2, c, transpose_a=True)

        if full_cov:
            var = self.kern.K(Xnew) + tf.matmul(tmp2, tmp2, transpose_a=True) \
                  - tf.matmul(tmp1, tmp1, transpose_a=True)
            shape = tf.stack([1, 1, tf.shape(self.Y)[1]])
            var = tf.tile(tf.expand_dims(var, 2), shape)
        else:
            var = self.kern.Kdiag(Xnew) + tf.reduce_sum(tf.square(tmp2), 0) \
                  - tf.reduce_sum(tf.square(tmp1), 0)
            shape = tf.stack([1, tf.shape(self.Y)[1]])
            var = tf.tile(tf.expand_dims(var, 1), shape)
        return mean + self.mean_function(Xnew), var

    def assign(self, params):
        params1 = dict(params)
        params1["fastSGPR/kern/variance"] = params1.pop("SGPR/kern/variance")
        params1["fastSGPR/kern/lengthscales"] = params1.pop("SGPR/kern/lengthscales")
        params1["fastSGPR/likelihood/variance"] = params1.pop("SGPR/likelihood/variance")
        params1["fastSGPR/feature/Z"] = params1.pop("SGPR/feature/Z")
        SGPR.assign(self,params1)