def grad_marg_likelihood(self, data):
        dL_dK = 0

        M = data["M"]
        Z = data["Z"]
        omega = data["omega"]
        kappa = data["kappa"]

        # Compute the kernel for Z_news
        Cvv  = self.kernel.K(Z, Z)
        Cvv +=  np.diag(1e-6 * np.ones(M))

        for k in xrange(self.K-1):
            sys.stdout.write(".")
            sys.stdout.flush()

            # The predictive mean and covariance are given by equations 2.22-2.24
            # of GPML by Rasmussen and Williams
            Cvvpo = Cvv + np.diag(omega[:,k])
            iCvvpo = np.linalg.inv(Cvvpo)

            # The "observations" are the effective mean of the Gaussian
            # likelihood given omega
            y = kappa[:,k] / omega[:,k] - self.mu[k]

            # Compute alpha in Eqn 5.9
            # x1 = solve_triangular(Lvvpo, y, lower=True)
            # alpha = solve_triangular(Lvvpo.T, x1, lower=False)
            alpha = iCvvpo.dot(y)

            # The gradient wrt theta is given by
            #   Tr(dL_dK * dK_dtheta)
            # = Tr(1/2 * (alpha * alpha^T - K^{-1}) * dK/dtheta)
            # where theta is a param of the kernel.
            # Here we just compute the first term, dL_dK
            dL_dK += 0.5 * (np.outer(alpha, alpha) - iCvvpo)

        return dL_dK
Compute the gradient of the marginal likelihood for a given dataset wrt K
dataset/ETHPy150Open HIPS/pgmult/pgmult/gp.py/_MultinomialGPBase.grad_marg_likelihood