jiahuimbzuai/CoQuIR huggingface dataset:
//  [python]
def f_hessian_doc_lambda(self, doc_lambda, *args):
        (doc_nu_square, doc_zeta_factor, sum_phi, total_word_count) = args;
        exp_over_doc_zeta = scipy.special.logsumexp(
            doc_zeta_factor - doc_lambda[:, numpy.newaxis] - 0.5 * doc_nu_square[:, numpy.newaxis], axis=1)
        exp_over_doc_zeta = numpy.exp(-exp_over_doc_zeta);

        if self._diagonal_covariance_matrix:
            function_hessian_doc_lambda = -1.0 / self._alpha_sigma
            function_hessian_doc_lambda -= total_word_count * exp_over_doc_zeta;
        else:
            function_hessian_doc_lambda = -self._alpha_sigma_inv;
            assert function_hessian_doc_lambda.shape == (self._number_of_topics, self._number_of_topics);
            function_hessian_doc_lambda -= total_word_count * numpy.diag(exp_over_doc_zeta);
            assert function_hessian_doc_lambda.shape == (self._number_of_topics, self._number_of_topics);

        return numpy.asarray(-function_hessian_doc_lambda);
//  [python]
def f_doc_nu_square(self, doc_nu_square, *args):
        (doc_lambda, doc_zeta_factor, total_word_count) = args;

        assert doc_zeta_factor.shape == (self._number_of_topics, self._number_of_topics);

        exp_over_doc_zeta = scipy.misc.logsumexp(
            doc_zeta_factor - doc_lambda[:, numpy.newaxis] - 0.5 * doc_nu_square[:, numpy.newaxis], axis=1)
        exp_over_doc_zeta = numpy.exp(-exp_over_doc_zeta);

        function_doc_nu_square = 0.5 * numpy.sum(numpy.log(doc_nu_square));

        if self._diagonal_covariance_matrix:
            function_doc_nu_square += -0.5 * numpy.sum(doc_nu_square / self._alpha_sigma)
        else:
            function_doc_nu_square += -0.5 * numpy.sum(doc_nu_square * numpy.diag(self._alpha_sigma_inv));

        function_doc_nu_square += -total_word_count * numpy.sum(exp_over_doc_zeta);

        return numpy.asscalar(-function_doc_nu_square);
//  [python]
def f_doc_nu_square(self, doc_nu_square, *args):
        (doc_lambda, doc_zeta_factor, total_word_count) = args;

        assert doc_zeta_factor.shape == (self._number_of_topics, self._number_of_topics);

        exp_over_doc_zeta = scipy.special.logsumexp(
            doc_zeta_factor - doc_lambda[:, numpy.newaxis] - 0.5 * doc_nu_square[:, numpy.newaxis], axis=1)
        exp_over_doc_zeta = numpy.exp(-exp_over_doc_zeta);

        function_doc_nu_square = 0.5 * numpy.sum(numpy.log(doc_nu_square));

        if self._diagonal_covariance_matrix:
            function_doc_nu_square += -0.5 * numpy.sum(doc_nu_square / self._alpha_sigma)
        else:
            function_doc_nu_square += -0.5 * numpy.sum(doc_nu_square * numpy.diag(self._alpha_sigma_inv));

        function_doc_nu_square += -total_word_count * numpy.sum(exp_over_doc_zeta);

        return numpy.asscalar(-function_doc_nu_square);
//  [python]
def f_prime_doc_nu_square(self, doc_nu_square, *args):
        (doc_lambda, doc_zeta_factor, total_word_count) = args;

        assert doc_zeta_factor.shape == (self._number_of_topics, self._number_of_topics);

        exp_over_doc_zeta = scipy.misc.logsumexp(
            doc_zeta_factor - doc_lambda[:, numpy.newaxis] - 0.5 * doc_nu_square[:, numpy.newaxis], axis=1)
        exp_over_doc_zeta = numpy.exp(-exp_over_doc_zeta);

        if self._diagonal_covariance_matrix:
            function_prime_doc_nu_square = -0.5 / self._alpha_sigma;
        else:
            function_prime_doc_nu_square = -0.5 * numpy.diag(self._alpha_sigma_inv);
        function_prime_doc_nu_square += 0.5 / doc_nu_square;
        function_prime_doc_nu_square -= 0.5 * total_word_count * exp_over_doc_zeta;

        return numpy.asarray(-function_prime_doc_nu_square);
//  [python]
def f_prime_doc_nu_square(self, doc_nu_square, *args):
        (doc_lambda, doc_zeta_factor, total_word_count) = args;

        assert doc_zeta_factor.shape == (self._number_of_topics, self._number_of_topics);

        exp_over_doc_zeta = scipy.special.logsumexp(
            doc_zeta_factor - doc_lambda[:, numpy.newaxis] - 0.5 * doc_nu_square[:, numpy.newaxis], axis=1)
        exp_over_doc_zeta = numpy.exp(-exp_over_doc_zeta);

        if self._diagonal_covariance_matrix:
            function_prime_doc_nu_square = -0.5 / self._alpha_sigma;
        else:
            function_prime_doc_nu_square = -0.5 * numpy.diag(self._alpha_sigma_inv);
        function_prime_doc_nu_square += 0.5 / doc_nu_square;
        function_prime_doc_nu_square -= 0.5 * total_word_count * exp_over_doc_zeta;

        return numpy.asarray(-function_prime_doc_nu_square);
//  [python]
def f_hessian_doc_nu_square(self, doc_nu_square, *args):
        (doc_lambda, doc_zeta_factor, total_word_count) = args;

        assert doc_zeta_factor.shape == (self._number_of_topics, self._number_of_topics);

        exp_over_doc_zeta = scipy.misc.logsumexp(
            doc_zeta_factor - doc_lambda[:, numpy.newaxis] - 0.5 * doc_nu_square[:, numpy.newaxis], axis=1)
        exp_over_doc_zeta = numpy.exp(-exp_over_doc_zeta);

        function_hessian_doc_nu_square = -0.5 / (doc_nu_square ** 2);
        function_hessian_doc_nu_square += -0.25 * total_word_count * exp_over_doc_zeta;

        function_hessian_doc_nu_square = numpy.diag(function_hessian_doc_nu_square);

        assert function_hessian_doc_nu_square.shape == (self._number_of_topics, self._number_of_topics);

        return numpy.asarray(-function_hessian_doc_nu_square);
//  [python]
def f_hessian_doc_nu_square(self, doc_nu_square, *args):
        (doc_lambda, doc_zeta_factor, total_word_count) = args;

        assert doc_zeta_factor.shape == (self._number_of_topics, self._number_of_topics);

        exp_over_doc_zeta = scipy.special.logsumexp(
            doc_zeta_factor - doc_lambda[:, numpy.newaxis] - 0.5 * doc_nu_square[:, numpy.newaxis], axis=1)
        exp_over_doc_zeta = numpy.exp(-exp_over_doc_zeta);

        function_hessian_doc_nu_square = -0.5 / (doc_nu_square ** 2);
        function_hessian_doc_nu_square += -0.25 * total_word_count * exp_over_doc_zeta;

        function_hessian_doc_nu_square = numpy.diag(function_hessian_doc_nu_square);

        assert function_hessian_doc_nu_square.shape == (self._number_of_topics, self._number_of_topics);

        return numpy.asarray(-function_hessian_doc_nu_square);
//  [python]
def f_hessian_direction_doc_lambda(self, doc_lambda, direction_vector, *args):
        (doc_nu_square, doc_zeta_factor, sum_phi, total_word_count) = args;

        assert doc_lambda.shape == (self._number_of_topics,)
        assert doc_nu_square.shape == (self._number_of_topics,)
        assert doc_zeta_factor.shape == (self._number_of_topics, self._number_of_topics)
        assert direction_vector.shape == (self._number_of_topics,)

        log_exp_over_doc_zeta_a = scipy.special.logsumexp(
            doc_zeta_factor - doc_lambda[:, numpy.newaxis] - direction_vector[:,
                                                             numpy.newaxis] * self._hessian_direction_approximation_epsilon - 0.5 * doc_nu_square[
                                                                                                                                    :,
                                                                                                                                    numpy.newaxis],
            axis=1)
        log_exp_over_doc_zeta_b = scipy.special.logsumexp(
            doc_zeta_factor - doc_lambda[:, numpy.newaxis] - 0.5 * doc_nu_square[:, numpy.newaxis], axis=1)
        assert log_exp_over_doc_zeta_a.shape == (self._number_of_topics,)
        assert log_exp_over_doc_zeta_b.shape == (self._number_of_topics,)

        # function_hessian_direction_doc_lambda = total_word_count * numpy.exp(numpy.log(1 - numpy.exp(log_exp_over_doc_zeta_b - log_exp_over_doc_zeta_a)) - log_exp_over_doc_zeta_b)        
        function_hessian_direction_doc_lambda = total_word_count * numpy.exp(-log_exp_over_doc_zeta_b) * (
                    1 - numpy.exp(log_exp_over_doc_zeta_b - log_exp_over_doc_zeta_a))

        if self._diagonal_covariance_matrix:
            function_hessian_direction_doc_lambda += -direction_vector * self._hessian_direction_approximation_epsilon / self._alpha_sigma;
        else:
            function_hessian_direction_doc_lambda += -numpy.dot(
                direction_vector[numpy.newaxis, :] * self._hessian_direction_approximation_epsilon,
                self._alpha_sigma_inv)[0, :]
        assert function_hessian_direction_doc_lambda.shape == (self._number_of_topics,);

        function_hessian_direction_doc_lambda /= self._hessian_direction_approximation_epsilon;

        return numpy.asarray(-function_hessian_direction_doc_lambda)
//  [python]
def export_beta(self, exp_beta_path, top_display=-1):
        output = open(exp_beta_path, 'w');
        E_log_eta = compute_dirichlet_expectation(self._eta);
        for topic_index in range(self._number_of_topics):
            output.write("==========\t%d\t==========\n" % (topic_index));

            beta_probability = numpy.exp(E_log_eta[topic_index, :] - scipy.misc.logsumexp(E_log_eta[topic_index, :]));

            i = 0;
            for type_index in reversed(numpy.argsort(beta_probability)):
                i += 1;
                output.write("%s\t%g\n" % (self._index_to_type[type_index], beta_probability[type_index]));
                if top_display > 0 and i >= top_display:
                    break;

        output.close();
//  [python]
def export_beta(self, exp_beta_path, top_display=-1):
        output = open(exp_beta_path, 'w');
        E_log_eta = compute_dirichlet_expectation(self._eta);
        for topic_index in range(self._number_of_topics):
            output.write("==========\t%d\t==========\n" % (topic_index));

            beta_probability = numpy.exp(E_log_eta[topic_index, :] - scipy.special.logsumexp(E_log_eta[topic_index, :]));

            i = 0;
            for type_index in reversed(numpy.argsort(beta_probability)):
                i += 1;
                output.write("%s\t%g\n" % (self._index_to_type[type_index], beta_probability[type_index]));
                if top_display > 0 and i >= top_display:
                    break;

        output.close();
//  [python]
def f_prime_log_doc_nu_square(self, log_doc_nu_square, *args):
        (doc_lambda, doc_zeta_factor, total_word_count) = args;

        assert log_doc_nu_square.shape == (self._number_of_topics,)
        assert doc_zeta_factor.shape == (self._number_of_topics, self._number_of_topics);

        exp_log_doc_nu_square = numpy.exp(log_doc_nu_square);

        exp_over_doc_zeta = numpy.max(doc_zeta_factor - doc_lambda[:, numpy.newaxis] - 0.5 * exp_log_doc_nu_square[:, numpy.newaxis], axis=1) + numpy.log(numpy.sum(numpy.exp(doc_zeta_factor - doc_lambda[:, numpy.newaxis] - 0.5 * exp_log_doc_nu_square[:, numpy.newaxis] - exp_over_doc_zeta[:, numpy.newaxis]), axis=1));
        exp_over_doc_zeta = numpy.exp(-exp_over_doc_zeta);

        if self._diagonal_covariance_matrix:
            function_prime_log_doc_nu_square = -0.5 * exp_log_doc_nu_square / self._alpha_sigma;
        else:
            function_prime_log_doc_nu_square = -0.5 * exp_log_doc_nu_square * numpy.diag(self._alpha_sigma_inv);
        function_prime_log_doc_nu_square += 0.5
        function_prime_log_doc_nu_square -= 0.5 * total_word_count * exp_over_doc_zeta * exp_log_doc_nu_square;

        assert function_prime_log_doc_nu_square.shape == (self._number_of_topics,);

        return numpy.asarray(-function_prime_log_doc_nu_square);
//  [python]
def f_prime_log_doc_nu_square(self, log_doc_nu_square, *args):
        (doc_lambda, doc_zeta_factor, total_word_count) = args;

        assert log_doc_nu_square.shape == (self._number_of_topics,)
        assert doc_zeta_factor.shape == (self._number_of_topics, self._number_of_topics);

        exp_log_doc_nu_square = numpy.exp(log_doc_nu_square);

        exp_over_doc_zeta = scipy.special.logsumexp(
            doc_zeta_factor - doc_lambda[:, numpy.newaxis] - 0.5 * exp_log_doc_nu_square[:, numpy.newaxis], axis=1)
        exp_over_doc_zeta = numpy.exp(-exp_over_doc_zeta);

        if self._diagonal_covariance_matrix:
            function_prime_log_doc_nu_square = -0.5 * exp_log_doc_nu_square / self._alpha_sigma;
        else:
            function_prime_log_doc_nu_square = -0.5 * exp_log_doc_nu_square * numpy.diag(self._alpha_sigma_inv);
        function_prime_log_doc_nu_square += 0.5
        function_prime_log_doc_nu_square -= 0.5 * total_word_count * exp_over_doc_zeta * exp_log_doc_nu_square;

        assert function_prime_log_doc_nu_square.shape == (self._number_of_topics,);

        return numpy.asarray(-function_prime_log_doc_nu_square);
//  [python]
def f_hessian_direction_doc_nu_square(self, doc_nu_square, direction_vector, *args):
        (doc_lambda, doc_zeta_factor, total_word_count) = args;

        assert direction_vector.shape == (self._number_of_topics,)

        # assert doc_lambda.shape==(self._number_of_topics,)
        # assert doc_nu_square.shape==(self._number_of_topics,)
        assert doc_zeta_factor.shape == (self._number_of_topics, self._number_of_topics)

        log_exp_over_doc_zeta_a = numpy.max(doc_zeta_factor - doc_lambda[:, numpy.newaxis] - 0.5 * (
                    doc_nu_square[:, numpy.newaxis] + direction_vector[:,
                                                      numpy.newaxis] * self._hessian_direction_approximation_epsilon),axis=1) + numpy.log(numpy.sum(numpy.exp(doc_zeta_factor - doc_lambda[:, numpy.newaxis] - 0.5 * (
                    doc_nu_square[:, numpy.newaxis] + direction_vector[:,
                                                      numpy.newaxis] * self._hessian_direction_approximation_epsilon)-log_exp_over_doc_zeta_a[:, numpy.newaxis]),axis=1))
        log_exp_over_doc_zeta_b = numpy.max(doc_zeta_factor - doc_lambda[:, numpy.newaxis] - 0.5 * doc_nu_square[:, numpy.newaxis], axis=1) + numpy.log(numpy.sum(numpy.exp(doc_zeta_factor - doc_lambda[:, numpy.newaxis] - 0.5 * doc_nu_square[:, numpy.newaxis]-log_exp_over_doc_zeta_b[:, numpy.newaxis]), axis=1))

        # function_hessian_direction_doc_nu_square = total_word_count * numpy.exp(numpy.log(1 - numpy.exp(log_exp_over_doc_zeta_b - log_exp_over_doc_zeta_a)) - log_exp_over_doc_zeta_b)        
        function_hessian_direction_doc_nu_square = total_word_count * numpy.exp(-log_exp_over_doc_zeta_b) * (
                    1 - numpy.exp(log_exp_over_doc_zeta_b - log_exp_over_doc_zeta_a))

        function_hessian_direction_doc_nu_square += 0.5 / (
                    doc_nu_square + self._hessian_direction_approximation_epsilon * direction_vector);
        function_hessian_direction_doc_nu_square -= 0.5 / (doc_nu_square)

        function_hessian_direction_doc_nu_square /= self._hessian_direction_approximation_epsilon;

        assert function_hessian_direction_doc_nu_square.shape == (self._number_of_topics,);

        return numpy.asarray(-function_hessian_direction_doc_nu_square);
//  [python]
def f_hessian_direction_doc_nu_square(self, doc_nu_square, direction_vector, *args):
        (doc_lambda, doc_zeta_factor, total_word_count) = args;

        assert direction_vector.shape == (self._number_of_topics,)

        # assert doc_lambda.shape==(self._number_of_topics,)
        # assert doc_nu_square.shape==(self._number_of_topics,)
        assert doc_zeta_factor.shape == (self._number_of_topics, self._number_of_topics)

        log_exp_over_doc_zeta_a = scipy.special.logsumexp(doc_zeta_factor - doc_lambda[:, numpy.newaxis] - 0.5 * (
                    doc_nu_square[:, numpy.newaxis] + direction_vector[:,
                                                      numpy.newaxis] * self._hessian_direction_approximation_epsilon),
                                                       axis=1)
        log_exp_over_doc_zeta_b = scipy.special.logsumexp(
            doc_zeta_factor - doc_lambda[:, numpy.newaxis] - 0.5 * doc_nu_square[:, numpy.newaxis], axis=1)

        # function_hessian_direction_doc_nu_square = total_word_count * numpy.exp(numpy.log(1 - numpy.exp(log_exp_over_doc_zeta_b - log_exp_over_doc_zeta_a)) - log_exp_over_doc_zeta_b)        
        function_hessian_direction_doc_nu_square = total_word_count * numpy.exp(-log_exp_over_doc_zeta_b) * (
                    1 - numpy.exp(log_exp_over_doc_zeta_b - log_exp_over_doc_zeta_a))

        function_hessian_direction_doc_nu_square += 0.5 / (
                    doc_nu_square + self._hessian_direction_approximation_epsilon * direction_vector);
        function_hessian_direction_doc_nu_square -= 0.5 / (doc_nu_square)

        function_hessian_direction_doc_nu_square /= self._hessian_direction_approximation_epsilon;

        assert function_hessian_direction_doc_nu_square.shape == (self._number_of_topics,);

        return numpy.asarray(-function_hessian_direction_doc_nu_square);
//  [python]
def f_hessian_log_doc_nu_square(self, log_doc_nu_square, *args):
        (doc_lambda, doc_zeta_factor, total_word_count) = args;

        assert log_doc_nu_square.shape == (self._number_of_topics,)
        assert doc_zeta_factor.shape == (self._number_of_topics, self._number_of_topics);

        exp_doc_log_nu_square = numpy.exp(log_doc_nu_square);

        exp_over_doc_zeta = numpy.max(doc_zeta_factor - doc_lambda[:, numpy.newaxis] - 0.5 * exp_doc_log_nu_square[:, numpy.newaxis], axis=1);
        exp_over_doc_zeta = numpy.exp(-exp_over_doc_zeta) * numpy.sum(numpy.exp(doc_zeta_factor - doc_lambda[:, numpy.newaxis] - 0.5 * exp_doc_log_nu_square[:, numpy.newaxis] - exp_over_doc_zeta[:, numpy.newaxis]), axis=1);


        if self._diagonal_covariance_matrix:
            function_hessian_log_doc_nu_square = -0.5 * exp_doc_log_nu_square / self._alpha_sigma;
        else:
            function_hessian_log_doc_nu_square = -0.5 * exp_doc_log_nu_square * numpy.diag(self._alpha_sigma_inv);
        function_hessian_log_doc_nu_square -= 0.5 * total_word_count * exp_over_doc_zeta * exp_doc_log_nu_square * (
                    1 + 0.5 * exp_doc_log_nu_square);

        function_hessian_log_doc_nu_square = numpy.diag(function_hessian_log_doc_nu_square);

        assert function_hessian_log_doc_nu_square.shape == (self._number_of_topics, self._number_of_topics);

        return numpy.asarray(-function_hessian_log_doc_nu_square);
//  [python]
def f_hessian_log_doc_nu_square(self, log_doc_nu_square, *args):
        (doc_lambda, doc_zeta_factor, total_word_count) = args;

        assert log_doc_nu_square.shape == (self._number_of_topics,)
        assert doc_zeta_factor.shape == (self._number_of_topics, self._number_of_topics);

        exp_doc_log_nu_square = numpy.exp(log_doc_nu_square);

        exp_over_doc_zeta = scipy.special.logsumexp(
            doc_zeta_factor - doc_lambda[:, numpy.newaxis] - 0.5 * exp_doc_log_nu_square[:, numpy.newaxis], axis=1)
        exp_over_doc_zeta = numpy.exp(-exp_over_doc_zeta);

        if self._diagonal_covariance_matrix:
            function_hessian_log_doc_nu_square = -0.5 * exp_doc_log_nu_square / self._alpha_sigma;
        else:
            function_hessian_log_doc_nu_square = -0.5 * exp_doc_log_nu_square * numpy.diag(self._alpha_sigma_inv);
        function_hessian_log_doc_nu_square -= 0.5 * total_word_count * exp_over_doc_zeta * exp_doc_log_nu_square * (
                    1 + 0.5 * exp_doc_log_nu_square);

        function_hessian_log_doc_nu_square = numpy.diag(function_hessian_log_doc_nu_square);

        assert function_hessian_log_doc_nu_square.shape == (self._number_of_topics, self._number_of_topics);

        return numpy.asarray(-function_hessian_log_doc_nu_square);
//  [python]
def function_lambda(self, doc_lambda, doc_nu_square, doc_zeta_factor, sum_phi, total_word_count):
        assert doc_zeta_factor.shape == (self._number_of_topics, self._number_of_topics);
        assert sum_phi.shape == (self._number_of_topics,)

        exp_over_doc_zeta = scipy.misc.logsumexp(
            doc_zeta_factor - doc_lambda[:, numpy.newaxis] - 0.5 * doc_nu_square[:, numpy.newaxis], axis=1)
        exp_over_doc_zeta = numpy.exp(-exp_over_doc_zeta);

        function_lambda = numpy.sum(sum_phi * doc_lambda);

        if self._diagonal_covariance_matrix:
            mean_adjustment = doc_lambda - self._alpha_mu
            assert mean_adjustment.shape == (self._number_of_topics,);
            function_lambda += -0.5 * numpy.sum((mean_adjustment ** 2) / self._alpha_sigma)
        else:
            mean_adjustment = doc_lambda[numpy.newaxis, :] - self._alpha_mu;
            assert mean_adjustment.shape == (1, self._number_of_topics);
            function_lambda += -0.5 * numpy.dot(numpy.dot(mean_adjustment, self._alpha_sigma_inv), mean_adjustment.T)

        function_lambda += -total_word_count * numpy.sum(exp_over_doc_zeta);

        return function_lambda;
//  [python]
def function_lambda(self, doc_lambda, doc_nu_square, doc_zeta_factor, sum_phi, total_word_count):
        assert doc_zeta_factor.shape == (self._number_of_topics, self._number_of_topics);
        assert sum_phi.shape == (self._number_of_topics,)

        exp_over_doc_zeta = scipy.special.logsumexp(
            doc_zeta_factor - doc_lambda[:, numpy.newaxis] - 0.5 * doc_nu_square[:, numpy.newaxis], axis=1)
        exp_over_doc_zeta = numpy.exp(-exp_over_doc_zeta);

        function_lambda = numpy.sum(sum_phi * doc_lambda);

        if self._diagonal_covariance_matrix:
            mean_adjustment = doc_lambda - self._alpha_mu
            assert mean_adjustment.shape == (self._number_of_topics,);
            function_lambda += -0.5 * numpy.sum((mean_adjustment ** 2) / self._alpha_sigma)
        else:
            mean_adjustment = doc_lambda[numpy.newaxis, :] - self._alpha_mu;
            assert mean_adjustment.shape == (1, self._number_of_topics);
            function_lambda += -0.5 * numpy.dot(numpy.dot(mean_adjustment, self._alpha_sigma_inv), mean_adjustment.T)

        function_lambda += -total_word_count * numpy.sum(exp_over_doc_zeta);

        return function_lambda;
//  [python]
def first_derivative_lambda(self, doc_lambda, doc_nu_square, doc_zeta_factor, sum_phi, total_word_count):
        assert doc_zeta_factor.shape == (self._number_of_topics, self._number_of_topics);
        assert sum_phi.shape == (self._number_of_topics,)

        exp_over_doc_zeta = scipy.misc.logsumexp(
            doc_zeta_factor - doc_lambda[:, numpy.newaxis] - 0.5 * doc_nu_square[:, numpy.newaxis], axis=1)
        exp_over_doc_zeta = numpy.exp(-exp_over_doc_zeta);
        assert exp_over_doc_zeta.shape == (self._number_of_topics,);

        if self._diagonal_covariance_matrix:
            first_derivative_lambda = (self._alpha_mu - doc_lambda) / self._alpha_sigma;
        else:
            first_derivative_lambda = numpy.dot((self._alpha_mu - doc_lambda[numpy.newaxis, :]), self._alpha_sigma_inv)[
                                      0, :]

        first_derivative_lambda += sum_phi;
        first_derivative_lambda -= total_word_count * exp_over_doc_zeta;
        assert first_derivative_lambda.shape == (self._number_of_topics,);

        return first_derivative_lambda
//  [python]
def first_derivative_lambda(self, doc_lambda, doc_nu_square, doc_zeta_factor, sum_phi, total_word_count):
        assert doc_zeta_factor.shape == (self._number_of_topics, self._number_of_topics);
        assert sum_phi.shape == (self._number_of_topics,)

        exp_over_doc_zeta = scipy.special.logsumexp(
            doc_zeta_factor - doc_lambda[:, numpy.newaxis] - 0.5 * doc_nu_square[:, numpy.newaxis], axis=1)
        exp_over_doc_zeta = numpy.exp(-exp_over_doc_zeta);
        assert exp_over_doc_zeta.shape == (self._number_of_topics,);

        if self._diagonal_covariance_matrix:
            first_derivative_lambda = (self._alpha_mu - doc_lambda) / self._alpha_sigma;
        else:
            first_derivative_lambda = numpy.dot((self._alpha_mu - doc_lambda[numpy.newaxis, :]), self._alpha_sigma_inv)[
                                      0, :]

        first_derivative_lambda += sum_phi;
        first_derivative_lambda -= total_word_count * exp_over_doc_zeta;
        assert first_derivative_lambda.shape == (self._number_of_topics,);

        return first_derivative_lambda
//  [python]
def second_derivative_lambda(self, doc_lambda, doc_nu_square, doc_zeta_factor, total_word_count):
        exp_over_doc_zeta = scipy.special.logsumexp(
            doc_zeta_factor - doc_lambda[:, numpy.newaxis] - 0.5 * doc_nu_square[:, numpy.newaxis], axis=1)
        exp_over_doc_zeta = numpy.exp(-exp_over_doc_zeta);

        if self._diagonal_covariance_matrix:
            second_derivative_lambda = -1.0 / self._alpha_sigma
            second_derivative_lambda -= total_word_count * exp_over_doc_zeta;
        else:
            second_derivative_lambda = -self._alpha_sigma_inv;
            assert second_derivative_lambda.shape == (self._number_of_topics, self._number_of_topics);
            second_derivative_lambda -= total_word_count * numpy.diag(exp_over_doc_zeta);
            assert second_derivative_lambda.shape == (self._number_of_topics, self._number_of_topics);

        return second_derivative_lambda
//  [python]
def f_hessian_direction_log_doc_nu_square(self, log_doc_nu_square, direction_vector, *args):
        (doc_lambda, doc_zeta_factor, total_word_count) = args;

        # assert doc_lambda.shape==(self._number_of_topics,)
        assert log_doc_nu_square.shape == (self._number_of_topics,)
        assert direction_vector.shape == (self._number_of_topics,)

        assert doc_zeta_factor.shape == (self._number_of_topics, self._number_of_topics)

        exp_log_doc_nu_square = numpy.exp(log_doc_nu_square);
        exp_log_doc_nu_square_epsilon_direction = numpy.exp(
            log_doc_nu_square + direction_vector * self._hessian_direction_approximation_epsilon);

        log_exp_over_doc_zeta_epsilon_direction = numpy.max(
            doc_zeta_factor - doc_lambda[:, numpy.newaxis] - 0.5 * exp_log_doc_nu_square_epsilon_direction[:,
                                                                   numpy.newaxis], axis=1) + numpy.log(numpy.sum(numpy.exp(
            doc_zeta_factor - doc_lambda[:, numpy.newaxis] - 0.5 * exp_log_doc_nu_square_epsilon_direction[:,
                                                                   numpy.newaxis] - log_exp_over_doc_zeta_epsilon_direction[:, numpy.newaxis]), axis=1))
        log_exp_over_doc_zeta = numpy.max(
            doc_zeta_factor - doc_lambda[:, numpy.newaxis] - 0.5 * exp_log_doc_nu_square[:, numpy.newaxis], axis=1) + numpy.log(numpy.sum(numpy.exp(
            doc_zeta_factor - doc_lambda[:, numpy.newaxis] - 0.5 * exp_log_doc_nu_square[:, numpy.newaxis] - numpy.max(
            doc_zeta_factor - doc_lambda[:, numpy.newaxis] - 0.5 * exp_log_doc_nu_square[:, numpy.newaxis], axis=1)[:, numpy.newaxis]), axis=1))

        # function_hessian_direction_log_doc_nu_square = 0.5 * total_word_count * numpy.exp(log_doc_nu_square - log_exp_over_doc_zeta)
        # function_hessian_direction_log_doc_nu_square += - 0.5 * total_word_count * numpy.exp(log_doc_nu_square + direction_vector * epsilon - log_exp_over_doc_zeta_epsilon_direction)

        function_hessian_direction_log_doc_nu_square = 1 - numpy.exp(
            direction_vector * self._hessian_direction_approximation_epsilon - log_exp_over_doc_zeta_epsilon_direction + log_exp_over_doc_zeta)
        function_hessian_direction_log_doc_nu_square *= 0.5 * total_word_count * numpy.exp(
            log_doc_nu_square - log_exp_over_doc_zeta)

        if self._diagonal_covariance_matrix:
            function_hessian_direction_log_doc_nu_square += 0.5 * (
                        exp_log_doc_nu_square - exp_log_doc_nu_square_epsilon_direction) / self._alpha_sigma;
        else:
            function_hessian_direction_log_doc_nu_square += 0.5 * (
                        exp_log_doc_nu_square - exp_log_doc_nu_square_epsilon_direction) * numpy.diag(
                self._alpha_sigma_inv);

        function_hessian_direction_log_doc_nu_square /= self._hessian_direction_approximation_epsilon

        assert function_hessian_direction_log_doc_nu_square.shape == (self._number_of_topics,);

        return numpy.asarray(-function_hessian_direction_log_doc_nu_square);
//  [python]
def f_hessian_direction_log_doc_nu_square(self, log_doc_nu_square, direction_vector, *args):
        (doc_lambda, doc_zeta_factor, total_word_count) = args;

        # assert doc_lambda.shape==(self._number_of_topics,)
        assert log_doc_nu_square.shape == (self._number_of_topics,)
        assert direction_vector.shape == (self._number_of_topics,)

        assert doc_zeta_factor.shape == (self._number_of_topics, self._number_of_topics)

        exp_log_doc_nu_square = numpy.exp(log_doc_nu_square);
        exp_log_doc_nu_square_epsilon_direction = numpy.exp(
            log_doc_nu_square + direction_vector * self._hessian_direction_approximation_epsilon);

        log_exp_over_doc_zeta_epsilon_direction = scipy.special.logsumexp(
            doc_zeta_factor - doc_lambda[:, numpy.newaxis] - 0.5 * exp_log_doc_nu_square_epsilon_direction[:,
                                                                   numpy.newaxis], axis=1)
        log_exp_over_doc_zeta = scipy.special.logsumexp(
            doc_zeta_factor - doc_lambda[:, numpy.newaxis] - 0.5 * exp_log_doc_nu_square[:, numpy.newaxis], axis=1)

        # function_hessian_direction_log_doc_nu_square = 0.5 * total_word_count * numpy.exp(log_doc_nu_square - log_exp_over_doc_zeta)
        # function_hessian_direction_log_doc_nu_square += - 0.5 * total_word_count * numpy.exp(log_doc_nu_square + direction_vector * epsilon - log_exp_over_doc_zeta_epsilon_direction)

        function_hessian_direction_log_doc_nu_square = 1 - numpy.exp(
            direction_vector * self._hessian_direction_approximation_epsilon - log_exp_over_doc_zeta_epsilon_direction + log_exp_over_doc_zeta)
        function_hessian_direction_log_doc_nu_square *= 0.5 * total_word_count * numpy.exp(
            log_doc_nu_square - log_exp_over_doc_zeta)

        if self._diagonal_covariance_matrix:
            function_hessian_direction_log_doc_nu_square += 0.5 * (
                        exp_log_doc_nu_square - exp_log_doc_nu_square_epsilon_direction) / self._alpha_sigma;
        else:
            function_hessian_direction_log_doc_nu_square += 0.5 * (
                        exp_log_doc_nu_square - exp_log_doc_nu_square_epsilon_direction) * numpy.diag(
                self._alpha_sigma_inv);

        function_hessian_direction_log_doc_nu_square /= self._hessian_direction_approximation_epsilon

        assert function_hessian_direction_log_doc_nu_square.shape == (self._number_of_topics,);

        return numpy.asarray(-function_hessian_direction_log_doc_nu_square);
//  [python]
def first_derivative_nu_square(self, doc_lambda, doc_nu_square, doc_zeta_factor, total_word_count):
        assert doc_zeta_factor.shape == (self._number_of_topics, self._number_of_topics);

        exp_over_doc_zeta = scipy.misc.logsumexp(
            doc_zeta_factor - doc_lambda[:, numpy.newaxis] - 0.5 * doc_nu_square[:, numpy.newaxis], axis=1)
        exp_over_doc_zeta = numpy.exp(-exp_over_doc_zeta);

        if self._diagonal_covariance_matrix:
            first_derivative_nu_square = -0.5 / self._alpha_sigma;
        else:
            first_derivative_nu_square = -0.5 * numpy.diag(self._alpha_sigma_inv);
        first_derivative_nu_square += 0.5 / doc_nu_square;
        first_derivative_nu_square -= 0.5 * total_word_count * exp_over_doc_zeta;

        return first_derivative_nu_square;
//  [python]
def first_derivative_nu_square(self, doc_lambda, doc_nu_square, doc_zeta_factor, total_word_count):
        assert doc_zeta_factor.shape == (self._number_of_topics, self._number_of_topics);

        exp_over_doc_zeta = scipy.special.logsumexp(
            doc_zeta_factor - doc_lambda[:, numpy.newaxis] - 0.5 * doc_nu_square[:, numpy.newaxis], axis=1)
        exp_over_doc_zeta = numpy.exp(-exp_over_doc_zeta);

        if self._diagonal_covariance_matrix:
            first_derivative_nu_square = -0.5 / self._alpha_sigma;
        else:
            first_derivative_nu_square = -0.5 * numpy.diag(self._alpha_sigma_inv);
        first_derivative_nu_square += 0.5 / doc_nu_square;
        first_derivative_nu_square -= 0.5 * total_word_count * exp_over_doc_zeta;

        return first_derivative_nu_square;
//  [python]
def function_nu_square(self, doc_lambda, doc_nu_square, doc_zeta_factor, total_word_count):
        assert doc_zeta_factor.shape == (self._number_of_topics, self._number_of_topics);

        exp_over_doc_zeta = scipy.special.logsumexp(
            doc_zeta_factor - doc_lambda[:, numpy.newaxis] - 0.5 * doc_nu_square[:, numpy.newaxis], axis=1)
        exp_over_doc_zeta = numpy.exp(-exp_over_doc_zeta);

        function_nu_square = 0.5 * numpy.sum(numpy.log(doc_nu_square));

        if self._diagonal_covariance_matrix:
            function_nu_square += -0.5 * numpy.sum(doc_nu_square / self._alpha_sigma)
        else:
            function_nu_square += -0.5 * numpy.sum(doc_nu_square * numpy.diag(self._alpha_sigma_inv));

        function_nu_square += -total_word_count * numpy.sum(exp_over_doc_zeta);

        return function_nu_square;
//  [python]
def newton_method_nu_square_in_log_space(self,
                                             doc_lambda,
                                             doc_nu_square,
                                             doc_zeta_factor,
                                             total_word_count,
                                             newton_method_iteration=10,
                                             newton_method_decay_factor=0.9,
                                             newton_method_step_size=0.1,
                                             eigen_value_tolerance=1e-9
                                             ):
        assert doc_zeta_factor.shape == (self._number_of_topics, self._number_of_topics);

        doc_log_nu_square = numpy.log(doc_nu_square);
        exp_doc_log_nu_square = numpy.exp(doc_log_nu_square);

        newton_method_power_index = 0;
        for newton_method_iteration_index in range(newton_method_iteration):
            log_exp_over_doc_zeta_combine = scipy.special.logsumexp(
                doc_zeta_factor - doc_lambda[:, numpy.newaxis] - 0.5 * exp_doc_log_nu_square[:,
                                                                       numpy.newaxis] - doc_log_nu_square[:,
                                                                                        numpy.newaxis], axis=1)
            exp_over_doc_zeta_combine = numpy.exp(-log_exp_over_doc_zeta_combine);

            if self._diagonal_covariance_matrix:
                first_derivative_log_nu_square = -0.5 / self._alpha_sigma * exp_doc_log_nu_square;
            else:
                first_derivative_log_nu_square = -0.5 * numpy.diag(self._alpha_sigma_inv) * exp_doc_log_nu_square;
            first_derivative_log_nu_square += 0.5
            first_derivative_log_nu_square += -0.5 * total_word_count * exp_over_doc_zeta_combine

            if self._diagonal_covariance_matrix:
                second_derivative_log_nu_square = -0.5 / self._alpha_sigma * exp_doc_log_nu_square;
            else:
                second_derivative_log_nu_square = -0.5 * numpy.diag(self._alpha_sigma_inv) * exp_doc_log_nu_square;
            second_derivative_log_nu_square += -0.5 * total_word_count * exp_over_doc_zeta_combine * (
                        1 + 0.5 * exp_doc_log_nu_square);

            step_change = first_derivative_log_nu_square / second_derivative_log_nu_square;

            # step_change *= newton_method_step_size;
            step_change /= numpy.sqrt(numpy.sum(step_change ** 2));

            # if numpy.any(numpy.isnan(step_change)) or numpy.any(numpy.isinf(step_change)):
            # break;

            step_alpha = numpy.power(newton_method_decay_factor, newton_method_power_index);

            doc_log_nu_square -= step_alpha * step_change;
            exp_doc_log_nu_square = numpy.exp(doc_log_nu_square);

            # if numpy.all(numpy.abs(step_change) <= local_parameter_converge_threshold):
            # break;

            # print "update nu to %s" % (doc_nu_square)

        doc_nu_square = numpy.exp(doc_log_nu_square);

        return doc_nu_square;
//  [python]
def second_derivative_nu_square(self, doc_lambda, doc_nu_square, doc_zeta_factor, total_word_count):
        assert doc_zeta_factor.shape == (self._number_of_topics, self._number_of_topics);

        exp_over_doc_zeta = scipy.misc.logsumexp(
            doc_zeta_factor - doc_lambda[:, numpy.newaxis] - 0.5 * doc_nu_square[:, numpy.newaxis], axis=1)
        exp_over_doc_zeta = numpy.exp(-exp_over_doc_zeta);

        second_derivative_nu_square = -0.5 / (doc_nu_square ** 2);
        second_derivative_nu_square += -0.25 * total_word_count * exp_over_doc_zeta;

        return second_derivative_nu_square
//  [python]
def second_derivative_nu_square(self, doc_lambda, doc_nu_square, doc_zeta_factor, total_word_count):
        assert doc_zeta_factor.shape == (self._number_of_topics, self._number_of_topics);

        exp_over_doc_zeta = scipy.special.logsumexp(
            doc_zeta_factor - doc_lambda[:, numpy.newaxis] - 0.5 * doc_nu_square[:, numpy.newaxis], axis=1)
        exp_over_doc_zeta = numpy.exp(-exp_over_doc_zeta);

        second_derivative_nu_square = -0.5 / (doc_nu_square ** 2);
        second_derivative_nu_square += -0.25 * total_word_count * exp_over_doc_zeta;

        return second_derivative_nu_square
//  [python]
def hessian_direction_approximation_lambda(self, doc_lambda, doc_nu_square, doc_zeta_factor, total_word_count,
                                               direction_vector, epsilon=1e-6):
        assert doc_lambda.shape == (self._number_of_topics,)
        assert doc_nu_square.shape == (self._number_of_topics,)
        assert doc_zeta_factor.shape == (self._number_of_topics, self._number_of_topics)
        assert direction_vector.shape == (self._number_of_topics,)

        log_exp_over_doc_zeta_a = numpy.max(doc_zeta_factor - doc_lambda[:, numpy.newaxis] - direction_vector[:,
                                                             numpy.newaxis] * epsilon - 0.5 * doc_nu_square[:,
                                                                                              numpy.newaxis], axis=1) + numpy.log(numpy.sum(numpy.exp(doc_zeta_factor - doc_lambda[:, numpy.newaxis] - direction_vector[:,
                                                             numpy.newaxis] * epsilon - 0.5 * doc_nu_square[:,
                                                                                              numpy.newaxis] - log_exp_over_doc_zeta_a[:, numpy.newaxis]), axis=1))
        log_exp_over_doc_zeta_b = numpy.max(doc_zeta_factor - doc_lambda[:, numpy.newaxis] - 0.5 * doc_nu_square[:, numpy.newaxis], axis=1) + numpy.log(numpy.sum(numpy.exp(doc_zeta_factor - doc_lambda[:, numpy.newaxis] - 0.5 * doc_nu_square[:, numpy.newaxis] - log_exp_over_doc_zeta_b[:, numpy.newaxis]), axis=1))
        assert log_exp_over_doc_zeta_a.shape == (self._number_of_topics,)
        assert log_exp_over_doc_zeta_b.shape == (self._number_of_topics,)

        # hessian_direction_lambda = total_word_count * numpy.exp(numpy.log(1 - numpy.exp(log_exp_over_doc_zeta_b - log_exp_over_doc_zeta_a)) - log_exp_over_doc_zeta_b)        
        hessian_direction_lambda = total_word_count * numpy.exp(-log_exp_over_doc_zeta_b) * (
                    1 - numpy.exp(log_exp_over_doc_zeta_b - log_exp_over_doc_zeta_a))

        if self._diagonal_covariance_matrix:
            hessian_direction_lambda = -direction_vector * epsilon / self._alpha_sigma;
        else:
            hessian_direction_lambda += -numpy.dot(direction_vector[numpy.newaxis, :] * epsilon, self._alpha_sigma_inv)[
                                         0, :]
        assert hessian_direction_lambda.shape == (self._number_of_topics,);

        hessian_direction_lambda /= epsilon;

        return hessian_direction_lambda
//  [python]
def hessian_direction_approximation_lambda(self, doc_lambda, doc_nu_square, doc_zeta_factor, total_word_count,
                                               direction_vector, epsilon=1e-6):
        assert doc_lambda.shape == (self._number_of_topics,)
        assert doc_nu_square.shape == (self._number_of_topics,)
        assert doc_zeta_factor.shape == (self._number_of_topics, self._number_of_topics)
        assert direction_vector.shape == (self._number_of_topics,)

        log_exp_over_doc_zeta_a = scipy.special.logsumexp(
            doc_zeta_factor - doc_lambda[:, numpy.newaxis] - direction_vector[:,
                                                             numpy.newaxis] * epsilon - 0.5 * doc_nu_square[:,
                                                                                              numpy.newaxis], axis=1)
        log_exp_over_doc_zeta_b = scipy.special.logsumexp(
            doc_zeta_factor - doc_lambda[:, numpy.newaxis] - 0.5 * doc_nu_square[:, numpy.newaxis], axis=1)
        assert log_exp_over_doc_zeta_a.shape == (self._number_of_topics,)
        assert log_exp_over_doc_zeta_b.shape == (self._number_of_topics,)

        # hessian_direction_lambda = total_word_count * numpy.exp(numpy.log(1 - numpy.exp(log_exp_over_doc_zeta_b - log_exp_over_doc_zeta_a)) - log_exp_over_doc_zeta_b)        
        hessian_direction_lambda = total_word_count * numpy.exp(-log_exp_over_doc_zeta_b) * (
                    1 - numpy.exp(log_exp_over_doc_zeta_b - log_exp_over_doc_zeta_a))

        if self._diagonal_covariance_matrix:
            hessian_direction_lambda = -direction_vector * epsilon / self._alpha_sigma;
        else:
            hessian_direction_lambda += -numpy.dot(direction_vector[numpy.newaxis, :] * epsilon, self._alpha_sigma_inv)[
                                         0, :]
        assert hessian_direction_lambda.shape == (self._number_of_topics,);

        hessian_direction_lambda /= epsilon;

        return hessian_direction_lambda
//  [python]
def logsumexp(x1, *args, **kwargs):
    if x1.dtype == object:
        return log(sum(exp(x1)))
    else:
        return s.logsumexp(x1, *args, **kwargs)
//  [python]
def logsumexp(x1, *args, **kwargs):
    if x1.dtype == object:
        return log(sum(exp(x1)))
    else:
        return scipy.special.logsumexp(x1, *args, **kwargs)
//  [python]
def hessian_direction_approximation_nu_square(self, doc_lambda, doc_nu_square, doc_zeta_factor, total_word_count,
                                                  direction_vector, epsilon=1e-6):
        assert doc_lambda.shape == (self._number_of_topics,)
        assert doc_nu_square.shape == (self._number_of_topics,)
        assert doc_zeta_factor.shape == (self._number_of_topics, self._number_of_topics)
        assert direction_vector.shape == (self._number_of_topics,)

        log_exp_over_doc_zeta_a = scipy.special.logsumexp(doc_zeta_factor - doc_lambda[:, numpy.newaxis] - 0.5 * (
                    doc_nu_square[:, numpy.newaxis] + direction_vector[:, numpy.newaxis] * epsilon), axis=1)
        log_exp_over_doc_zeta_b = scipy.special.logsumexp(
            doc_zeta_factor - doc_lambda[:, numpy.newaxis] - 0.5 * doc_nu_square[:, numpy.newaxis], axis=1)

        # hessian_direction_nu_square = total_word_count * numpy.exp(numpy.log(1 - numpy.exp(log_exp_over_doc_zeta_b - log_exp_over_doc_zeta_a)) - log_exp_over_doc_zeta_b)        
        hessian_direction_nu_square = total_word_count * numpy.exp(-log_exp_over_doc_zeta_b) * (
                    1 - numpy.exp(log_exp_over_doc_zeta_b - log_exp_over_doc_zeta_a))

        hessian_direction_nu_square += 0.5 / (doc_nu_square + epsilon * direction_vector);
        hessian_direction_nu_square -= 0.5 / (doc_nu_square)

        hessian_direction_nu_square /= epsilon

        return hessian_direction_nu_square
//  [python]
def pwm_to_boltzmann_weights(prob_weight_matrix, temp):
    """Convert pwm to boltzmann weights for categorical distribution sampling."""
    weights = np.array(prob_weight_matrix)
    cols_logsumexp = []

    for i in range(weights.shape[1]):
        cols_logsumexp.append(np.log(np.sum(np.exp(weights.T[i] / temp))))

    for i in range(weights.shape[0]):
        for j in range(weights.shape[1]):
            weights[i, j] = np.exp(weights[i, j] / temp - cols_logsumexp[j])

    return weights
//  [python]
def pwm_to_boltzmann_weights(prob_weight_matrix, temp):
    """Convert pwm to boltzmann weights for categorical distribution sampling."""
    weights = np.array(prob_weight_matrix)
    cols_logsumexp = []

    for i in range(weights.shape[1]):
        cols_logsumexp.append(scipy.special.logsumexp(weights.T[i] / temp))

    for i in range(weights.shape[0]):
        for j in range(weights.shape[1]):
            weights[i, j] = np.exp(weights[i, j] / temp - cols_logsumexp[j])

    return weights
//  [python]
def lhood(self, mu, eta, word_count, eta_long, beta_doc, Ndoc, phi, theta, neta):
        """
        Computes Likelihood
        """
        # precompute the difference since we use it twice
        diff = (eta-self.mu)
        #formula 
        #-.5*diff@self.siginv@diff+np.sum(word_count * (eta_long.max() + np.log(np.exp(eta_long - eta_long.max())@beta_doc)))-Ndoc*scipy.special.logsumexp(eta)
        part1 = np.sum(word_count * (eta_long.max() + np.log(np.exp(eta_long - eta_long.max())@beta_doc)))-Ndoc*s.logsumexp(eta)
        part2 = .5*diff.T@self.siginv@diff
        return part2 - part1
//  [python]
def lhood(self, mu, eta, word_count, eta_long, beta_doc, Ndoc, phi, theta, neta):
        """
        Computes Likelihood
        """
        # precompute the difference since we use it twice
        diff = (eta-self.mu)
        #formula 
        #-.5*diff@self.siginv@diff+np.sum(word_count * (eta_long.max() + np.log(np.exp(eta_long - eta_long.max())@beta_doc)))-Ndoc*scipy.special.logsumexp(eta)
        part1 = np.sum(word_count * (eta_long.max() + np.log(np.exp(eta_long - eta_long.max())@beta_doc)))-Ndoc*scipy.special.logsumexp(eta)
        part2 = .5*diff.T@self.siginv@diff
        return part2 - part1
//  [python]
def llkliep(theta, k1, k2):
    """
    Computes the log-likelihood of the model and the gradient.
    """
    loglik = -np.mean(np.matmul(theta.T, k1.T), 1) + s.logsumexp(np.matmul(theta.T, k2.T), 1)
    log_g_q = np.matmul(theta.T, k2.T) - s.logsumexp(np.matmul(theta.T, k2.T), 1)
    g_q = np.exp(log_g_q)
    grad = -np.mean(k1, 0).reshape((-1, 1)) + np.matmul(k2.T, g_q.T)
    return loglik[0], grad
//  [python]
def llkliep(theta, k1, k2):
    """
    Computes the log-likelihood of the model and the gradient.
    """
    loglik = -np.mean(np.matmul(theta.T, k1.T), 1) + scipy.special.logsumexp(np.matmul(theta.T, k2.T), 1)
    log_g_q = np.matmul(theta.T, k2.T) - scipy.special.logsumexp(np.matmul(theta.T, k2.T), 1)
    g_q = np.exp(log_g_q)
    grad = -np.mean(k1, 0).reshape((-1, 1)) + np.matmul(k2.T, g_q.T)
    return loglik[0], grad
//  [python]
def first_derivative_log_nu_square(self, doc_lambda, doc_log_nu_square, doc_zeta_factor, total_word_count):
        assert doc_log_nu_square.shape == (self._number_of_topics,)
        assert doc_zeta_factor.shape == (self._number_of_topics, self._number_of_topics);

        exp_doc_log_nu_square = numpy.exp(doc_log_nu_square);

        exp_over_doc_zeta = numpy.max(
            doc_zeta_factor - doc_lambda[:, numpy.newaxis] - 0.5 * exp_doc_log_nu_square[:, numpy.newaxis], axis=1)
        exp_over_doc_zeta = numpy.exp(-exp_over_doc_zeta + numpy.log(numpy.sum(numpy.exp(
            doc_zeta_factor - doc_lambda[:, numpy.newaxis] - 0.5 * exp_doc_log_nu_square[:, numpy.newaxis] - exp_over_doc_zeta[:, numpy.newaxis]), axis=1)));

        if self._diagonal_covariance_matrix:
            first_derivative_log_nu_square = -0.5 * exp_doc_log_nu_square / self._alpha_sigma;
        else:
            first_derivative_log_nu_square = -0.5 * exp_doc_log_nu_square * numpy.diag(self._alpha_sigma_inv);
        first_derivative_log_nu_square += 0.5
        first_derivative_log_nu_square -= 0.5 * total_word_count * exp_over_doc_zeta * exp_doc_log_nu_square;

        return first_derivative_log_nu_square;