jiahuimbzuai/CoQuIR huggingface dataset:
//  [python]
def compute_oscr(self, pred_k, pred_u, labels, nclasses):
        if pred_k.shape[1] == nclasses + 1:
            x1, x2 = -1 * pred_k[:, -1], -1 * pred_u[:, -1]
            pred = np.argmax(pred_k[:, :-1], axis=1)
        else:
            x1 = self.temperature * np.log(np.sum(np.exp(pred_k / self.temperature), axis=1))
            x2 = self.temperature * np.log(np.sum(np.exp(pred_u / self.temperature), axis=1))
            # x1, x2 = np.max(pred_k, axis=1), np.max(pred_u, axis=1)
            pred = np.argmax(pred_k, axis=1)
        correct = (pred == labels)
        m_x1 = np.zeros(len(x1))
        m_x1[pred == labels] = 1
        k_target = np.concatenate((np.ones(len(x1)), np.zeros(len(x2))), axis=0)
        u_target = np.concatenate((np.zeros(len(x1)), np.ones(len(x2))), axis=0)
        predict = np.concatenate((x1, x2), axis=0)
        n = len(predict)

        # Cutoffs are of prediction values
        
        CCR = [0 for x in range(n+2)]
        FPR = [0 for x in range(n+2)] 

        auxa = np.random.random(predict.size)
        idx = np.lexsort((auxa, predict))
        # idx = predict.argsort()

        s_k_target = k_target[idx]
        s_u_target = u_target[idx]
        for k in range(n-1):
            CC = s_k_target[k+1:].sum()
            FP = s_u_target[k:].sum()

            # True	Positive Rate
            CCR[k] = float(CC) / float(len(x1))
            # False Positive Rate
            FPR[k] = float(FP) / float(len(x2))

        CCR[n] = 0.0
        FPR[n] = 0.0
        CCR[n+1] = 1.0
        FPR[n+1] = 1.0

        # Positions of ROC curve (FPR, TPR)
        ROC = sorted(zip(FPR, CCR), reverse=True)

        OSCR = 0

        # Compute AUROC Using Trapezoidal Rule
        for j in range(n+1):
            h =   ROC[j][0] - ROC[j+1][0]
            w =  (ROC[j][1] + ROC[j+1][1]) / 2.0

            OSCR = OSCR + h*w

        return OSCR, ROC
//  [python]
def compute_oscr(self, pred_k, pred_u, labels, nclasses):
        if pred_k.shape[1] == nclasses + 1:
            x1, x2 = -1 * pred_k[:, -1], -1 * pred_u[:, -1]
            pred = np.argmax(pred_k[:, :-1], axis=1)
        else:
            x1 = self.temperature * logsumexp(pred_k / self.temperature, axis=1)
            x2 = self.temperature * logsumexp(pred_u / self.temperature, axis=1)
            # x1, x2 = np.max(pred_k, axis=1), np.max(pred_u, axis=1)
            pred = np.argmax(pred_k, axis=1)
        correct = (pred == labels)
        m_x1 = np.zeros(len(x1))
        m_x1[pred == labels] = 1
        k_target = np.concatenate((np.ones(len(x1)), np.zeros(len(x2))), axis=0)
        u_target = np.concatenate((np.zeros(len(x1)), np.ones(len(x2))), axis=0)
        predict = np.concatenate((x1, x2), axis=0)
        n = len(predict)

        # Cutoffs are of prediction values
        
        CCR = [0 for x in range(n+2)]
        FPR = [0 for x in range(n+2)] 

        auxa = np.random.random(predict.size)
        idx = np.lexsort((auxa, predict))
        # idx = predict.argsort()

        s_k_target = k_target[idx]
        s_u_target = u_target[idx]
        for k in range(n-1):
            CC = s_k_target[k+1:].sum()
            FP = s_u_target[k:].sum()

            # True	Positive Rate
            CCR[k] = float(CC) / float(len(x1))
            # False Positive Rate
            FPR[k] = float(FP) / float(len(x2))

        CCR[n] = 0.0
        FPR[n] = 0.0
        CCR[n+1] = 1.0
        FPR[n+1] = 1.0

        # Positions of ROC curve (FPR, TPR)
        ROC = sorted(zip(FPR, CCR), reverse=True)

        OSCR = 0

        # Compute AUROC Using Trapezoidal Rule
        for j in range(n+1):
            h =   ROC[j][0] - ROC[j+1][0]
            w =  (ROC[j][1] + ROC[j+1][1]) / 2.0

            OSCR = OSCR + h*w

        return OSCR, ROC
//  [python]
def softmin(cost, f, g, eps, axis):
  return -eps * s.logsumexp(-center(cost, f, g) / eps, axis=axis)
//  [python]
def softmin(cost, f, g, eps, axis):
  return -eps * scipy.special.logsumexp(-center(cost, f, g) / eps, axis=axis)
//  [python]
def _resize_prediction(self, prediction, target_shape):
        if prediction.shape != target_shape:
            orig_shape = prediction.shape
            x_factor = target_shape[1] / prediction.shape[1]
            y_factor = target_shape[0] / prediction.shape[0]

            prediction = zoom(prediction, [y_factor, x_factor], order=1, mode='nearest')

            prediction -= np.log(np.sum(np.exp(prediction)))

            if prediction.shape != target_shape:
                print("compute size", self.compute_size)
                print("prediction shape", orig_shape)
                print("target shape", target_shape)
                print("x factor", x_factor)
                print("y factor", y_factor)
                raise ValueError(prediction.shape)

            assert prediction.shape == target_shape

        return prediction
//  [python]
def _resize_prediction(self, prediction, target_shape):
        if prediction.shape != target_shape:
            orig_shape = prediction.shape
            x_factor = target_shape[1] / prediction.shape[1]
            y_factor = target_shape[0] / prediction.shape[0]

            prediction = zoom(prediction, [y_factor, x_factor], order=1, mode='nearest')

            prediction -= logsumexp(prediction)

            if prediction.shape != target_shape:
                print("compute size", self.compute_size)
                print("prediction shape", orig_shape)
                print("target shape", target_shape)
                print("x factor", x_factor)
                print("y factor", y_factor)
                raise ValueError(prediction.shape)

            assert prediction.shape == target_shape

        return prediction
//  [python]
def average_predictions(log_densities, log_density_count=None, maximal_chunk_size=None, verbose=False, library='torch'):
    """ compute average log density given multiple log densities.

    specifying log_density_count allows to process generator arrays to avoid keeping all predictions in memory.
    specifying maximal_chunk_size allows to process the log densities such that not too many log densities are kept in
    memory at all (which only makes sense if log_densities is a generator), see logsumexp_iterator for more details
    """

    if maximal_chunk_size is not None and log_density_count is None:
        print("Warning: specifying maximal_chunk_size without log_density_count doesn't make sense because then the log densities have to be converted into a list and hence put in memory anyway.")

    if log_density_count is None:
        log_densities = np.array(list(log_densities))
        log_density_count = len(log_densities)

    normalization_constant = np.log(log_density_count)
    def weighted_log_densities(log_densities, normalization_constant):
        for log_density in log_densities:
            yield log_density - normalization_constant

    result = logsumexp_iterator(weighted_log_densities(log_densities, normalization_constant), log_density_count, maximal_chunk_size=maximal_chunk_size, verbose=verbose, library=library)
    result_norm = logsumexp(result)

    if not (-0.0001 < result_norm < 0.0001):
        print(f"Warning: result of averaging not well normalized (logsum={result_norm}). This could either be a problem with the averaged predictions or indicate numerical issues in averaging.")

    result -= result_norm

    return result
//  [python]
def test_softmax_correctness(check_lazy_shapes):
    mat = Tensor(3, 4).np()
    approx(B.logsumexp(mat), s.logsumexp(mat))
    for axis in [None, -1, 0, 1]:
        approx(
            B.softmax(mat, axis=axis),
            s.softmax(mat, axis=axis),
        )
//  [python]
def test_softmax_correctness(check_lazy_shapes):
    mat = Tensor(3, 4).np()
    approx(B.logsumexp(mat), scipy.special.logsumexp(mat))
    for axis in [None, -1, 0, 1]:
        approx(
            B.softmax(mat, axis=axis),
            scipy.special.softmax(mat, axis=axis),
        )
//  [python]
def _log_density(self, stimulus):
        stimulus = self.ensure_color(stimulus)

        stimulus_size = stimulus.shape[0], stimulus.shape[1]
        max_size = max(stimulus_size)
        factor = self.size / max_size

        if factor != 1.0:
            if self.verbose:
                print("Resizing with factor", factor)
            stimulus_for_parent_model = zoom(stimulus, [factor, factor, 1.0], order=1, mode='nearest')
        else:
            stimulus_for_parent_model = stimulus

        log_density = self.parent_model.log_density(stimulus_for_parent_model)

        factor_y = stimulus.shape[0] / log_density.shape[0]
        factor_x = stimulus.shape[1] / log_density.shape[1]

        if factor_y != 1.0 or factor_x != 1.0:
            if self.verbose:
                print("Wrong shape, resizing log densities", stimulus.shape, log_density.shape)
            log_density = zoom(log_density, [factor_y, factor_x], order=1, mode='nearest')
            log_density -= np.log(np.sum(np.exp(log_density)))

        assert log_density.shape[0] == stimulus.shape[0]
        assert log_density.shape[1] == stimulus.shape[1]

        return log_density
//  [python]
def _log_density(self, stimulus):
        stimulus = self.ensure_color(stimulus)

        stimulus_size = stimulus.shape[0], stimulus.shape[1]
        max_size = max(stimulus_size)
        factor = self.size / max_size

        if factor != 1.0:
            if self.verbose:
                print("Resizing with factor", factor)
            stimulus_for_parent_model = zoom(stimulus, [factor, factor, 1.0], order=1, mode='nearest')
        else:
            stimulus_for_parent_model = stimulus

        log_density = self.parent_model.log_density(stimulus_for_parent_model)

        factor_y = stimulus.shape[0] / log_density.shape[0]
        factor_x = stimulus.shape[1] / log_density.shape[1]

        if factor_y != 1.0 or factor_x != 1.0:
            if self.verbose:
                print("Wrong shape, resizing log densities", stimulus.shape, log_density.shape)
            log_density = zoom(log_density, [factor_y, factor_x], order=1, mode='nearest')
            log_density -= logsumexp(log_density)

        assert log_density.shape[0] == stimulus.shape[0]
        assert log_density.shape[1] == stimulus.shape[1]

        return log_density
//  [python]
def log_prob(self, value):
        value = np.expand_dims(value, axis=-1)
        mlog_prob = Normal(self.locs, self.scales).log_prob(value)
        if self._validate_args:
            self._validate_sample(value)
        wlog_prob = np.log(self.weights) + mlog_prob
        return scipy.misc.logsumexp(wlog_prob, axis=-1)
//  [python]
def log_prob(self, value):
        value = np.expand_dims(value, axis=-1)
        mlog_prob = Normal(self.locs, self.scales).log_prob(value)
        if self._validate_args:
            self._validate_sample(value)
        wlog_prob = np.log(self.weights) + mlog_prob
        return scipy.special.logsumexp(wlog_prob, axis=-1)
//  [python]
def test_logsumexp_correctness(check_lazy_shapes):
    mat = PositiveTensor(3, 4).np()
    approx(B.logsumexp(mat), s.logsumexp(mat))
    for axis in [None, -1, 0, 1]:
        for squeeze in [True, False]:
            approx(
                B.logsumexp(mat, axis=axis, squeeze=squeeze),
                s.logsumexp(mat, axis=axis, keepdims=not squeeze),
            )
//  [python]
def test_logsumexp_correctness(check_lazy_shapes):
    mat = PositiveTensor(3, 4).np()
    approx(B.logsumexp(mat), scipy.special.logsumexp(mat))
    for axis in [None, -1, 0, 1]:
        for squeeze in [True, False]:
            approx(
                B.logsumexp(mat, axis=axis, squeeze=squeeze),
                scipy.special.logsumexp(mat, axis=axis, keepdims=not squeeze),
            )
//  [python]
def _log_density(self, stimulus):
        stimulus_data = as_stimulus(stimulus).stimulus_data

        if self.factor != 1.0:
            if self.verbose:
                print("Resizing with factor", self.factor)
            if stimulus_data.ndim == 2:
                factors = [self.factor, self.factor]
            else:
                factors = [self.factor, self.factor, 1.0]

            stimulus_for_parent_model = zoom(stimulus_data, factors, order=1, mode='nearest')

        else:
            stimulus_for_parent_model = stimulus

        log_density = self.parent_model.log_density(stimulus_for_parent_model)

        factor_y = stimulus.shape[0] / log_density.shape[0]
        factor_x = stimulus.shape[1] / log_density.shape[1]

        if factor_y != 1.0 or factor_x != 1.0:
            if self.verbose:
                print("Wrong shape, resizing log densities", stimulus.shape, log_density.shape)
            log_density = zoom(log_density, [factor_y, factor_x], order=1, mode='nearest')
            log_density -= np.max(log_density)
            log_density -= np.log(np.sum(np.exp(log_density - np.max(log_density))))

        assert log_density.shape[0] == stimulus.shape[0]
        assert log_density.shape[1] == stimulus.shape[1]

        return log_density
//  [python]
def _log_density(self, stimulus):
        stimulus_data = as_stimulus(stimulus).stimulus_data

        if self.factor != 1.0:
            if self.verbose:
                print("Resizing with factor", self.factor)
            if stimulus_data.ndim == 2:
                factors = [self.factor, self.factor]
            else:
                factors = [self.factor, self.factor, 1.0]

            stimulus_for_parent_model = zoom(stimulus_data, factors, order=1, mode='nearest')

        else:
            stimulus_for_parent_model = stimulus

        log_density = self.parent_model.log_density(stimulus_for_parent_model)

        factor_y = stimulus.shape[0] / log_density.shape[0]
        factor_x = stimulus.shape[1] / log_density.shape[1]

        if factor_y != 1.0 or factor_x != 1.0:
            if self.verbose:
                print("Wrong shape, resizing log densities", stimulus.shape, log_density.shape)
            log_density = zoom(log_density, [factor_y, factor_x], order=1, mode='nearest')
            log_density -= logsumexp(log_density)

        assert log_density.shape[0] == stimulus.shape[0]
        assert log_density.shape[1] == stimulus.shape[1]

        return log_density
//  [python]
def logsumexpTest(config,nb):
    inputs = [] 
    outputs = [] 
    vecDim = VECDIM[nb % len(VECDIM)]
    dims=np.array([NBTESTS,vecDim])
    for _ in range(0,NBTESTS):
       v = np.random.rand(vecDim)
       v = v / np.sum(v)
       e = s.logsumexp(v)
       inputs += list(v)
       outputs.append(e)
    inputs = np.array(inputs)
    outputs = np.array(outputs)
    config.writeInput(nb, inputs,"Input")
    config.writeInputS16(nb, dims,"Dims")
    config.writeReference(nb, outputs,"RefLogSumExp")
//  [python]
def logsumexpTest(config,nb):
    inputs = [] 
    outputs = [] 
    vecDim = VECDIM[nb % len(VECDIM)]
    dims=np.array([NBTESTS,vecDim])
    for _ in range(0,NBTESTS):
       v = np.random.rand(vecDim)
       v = v / np.sum(v)
       e = scipy.special.logsumexp(v)
       inputs += list(v)
       outputs.append(e)
    inputs = np.array(inputs)
    outputs = np.array(outputs)
    config.writeInput(nb, inputs,"Input")
    config.writeInputS16(nb, dims,"Dims")
    config.writeReference(nb, outputs,"RefLogSumExp")
//  [python]
def messages_backwards(self):
        # NOTE: np.maximum calls are because the C++ code doesn't do
        # np.logaddexp(-inf,-inf) = -inf, it likes nans instead
        from pyhsmm.internals.hsmm_messages_interface import messages_backwards_log
        betal, betastarl = messages_backwards_log(
                np.maximum(self.trans_matrix,1e-50),self.aBl,np.maximum(self.aDl,-1000000),
                self.aDsl,np.empty_like(self.aBl),np.empty_like(self.aBl),
                self.right_censoring,self.trunc if self.trunc is not None else self.T)
        assert not np.isnan(betal).any()
        assert not np.isnan(betastarl).any()

        if not self.left_censoring:
            self._normalizer = s.logsumexp(np.log(self.pi_0) + betastarl[0])
        else:
            raise NotImplementedError

        return betal, betastarl
//  [python]
def messages_backwards(self):
        # NOTE: np.maximum calls are because the C++ code doesn't do
        # np.logaddexp(-inf,-inf) = -inf, it likes nans instead
        from pyhsmm.internals.hsmm_messages_interface import messages_backwards_log
        betal, betastarl = messages_backwards_log(
                np.maximum(self.trans_matrix,1e-50),self.aBl,np.maximum(self.aDl,-1000000),
                self.aDsl,np.empty_like(self.aBl),np.empty_like(self.aBl),
                self.right_censoring,self.trunc if self.trunc is not None else self.T)
        assert not np.isnan(betal).any()
        assert not np.isnan(betastarl).any()

        if not self.left_censoring:
            self._normalizer = logsumexp(np.log(self.pi_0) + betastarl[0])
        else:
            raise NotImplementedError

        return betal, betastarl
//  [python]
def aBl_einsum(self):
        if self._aBBl is None:
            sigmas = np.array([[c.sigmas for c in d.components] for d in self.obs_distns])
            Js = -1./(2*sigmas)
            mus = np.array([[c.mu for c in d.components] for d in self.obs_distns])

            # all_likes is T x Nstates x Ncomponents
            all_likes = \
                    (np.einsum('td,td,nkd->tnk',self.data,self.data,Js)
                        - np.einsum('td,nkd,nkd->tnk',self.data,2*mus,Js))
            all_likes += (mus**2*Js - 1./2*np.log(2*np.pi*sigmas)).sum(2)

            # weights is Nstates x Ncomponents
            weights = np.log(np.array([d.weights.weights for d in self.obs_distns]))
            all_likes += weights[na,...]

            # aBl is T x Nstates
            aBl = self._aBl = np.logaddexp.reduce(all_likes, axis=2)
            aBl[np.isnan(aBl).any(1)] = 0.

            aBBl = self._aBBl = np.empty((self.Tblock,self.num_states))
            for idx, (start,stop) in enumerate(self.changepoints):
                aBBl[idx] = aBl[start:stop].sum(0)

        return self._aBBl
//  [python]
def aBl_einsum(self):
        if self._aBBl is None:
            sigmas = np.array([[c.sigmas for c in d.components] for d in self.obs_distns])
            Js = -1./(2*sigmas)
            mus = np.array([[c.mu for c in d.components] for d in self.obs_distns])

            # all_likes is T x Nstates x Ncomponents
            all_likes = \
                    (np.einsum('td,td,nkd->tnk',self.data,self.data,Js)
                        - np.einsum('td,nkd,nkd->tnk',self.data,2*mus,Js))
            all_likes += (mus**2*Js - 1./2*np.log(2*np.pi*sigmas)).sum(2)

            # weights is Nstates x Ncomponents
            weights = np.log(np.array([d.weights.weights for d in self.obs_distns]))
            all_likes += weights[na,...]

            # aBl is T x Nstates
            aBl = self._aBl = logsumexp(all_likes, axis=2)
            aBl[np.isnan(aBl).any(1)] = 0.

            aBBl = self._aBBl = np.empty((self.Tblock,self.num_states))
            for idx, (start,stop) in enumerate(self.changepoints):
                aBBl[idx] = aBl[start:stop].sum(0)

        return self._aBBl
//  [python]
def hsmm_messages_backwards_log(
    trans_potentials, initial_state_potential,
    cumulative_obs_potentials, dur_potentials, dur_survival_potentials,
    betal, betastarl,
    left_censoring=False, right_censoring=True):
    errs = np.seterr(invalid='ignore') # logaddexp(-inf,-inf)

    T, _ = betal.shape

    betal[-1] = 0.
    for t in range(T-1,-1,-1):
        cB, offset = cumulative_obs_potentials(t)
        dp = dur_potentials(t)
        betastarl[t] = np.logaddexp.reduce(
            betal[t:t+cB.shape[0]] + cB + dur_potentials(t), axis=0)
        betastarl[t] -= offset
        if right_censoring:
            np.logaddexp(betastarl[t], cB[-1] - offset + dur_survival_potentials(t),
                    out=betastarl[t])
        betal[t-1] = np.logaddexp.reduce(betastarl[t] + trans_potentials(t-1), axis=1)
    betal[-1] = 0. # overwritten on last iteration

    if not left_censoring:
        normalizer = np.logaddexp.reduce(initial_state_potential + betastarl[0])
    else:
        raise NotImplementedError

    np.seterr(**errs)
    return betal, betastarl, normalizer
//  [python]
def hsmm_messages_backwards_log(
    trans_potentials, initial_state_potential,
    cumulative_obs_potentials, dur_potentials, dur_survival_potentials,
    betal, betastarl,
    left_censoring=False, right_censoring=True):
    errs = np.seterr(invalid='ignore') # logaddexp(-inf,-inf)

    T, _ = betal.shape

    betal[-1] = 0.
    for t in range(T-1,-1,-1):
        cB, offset = cumulative_obs_potentials(t)
        dp = dur_potentials(t)
        betastarl[t] = logsumexp(
            betal[t:t+cB.shape[0]] + cB + dur_potentials(t), axis=0)
        betastarl[t] -= offset
        if right_censoring:
            np.logaddexp(betastarl[t], cB[-1] - offset + dur_survival_potentials(t),
                    out=betastarl[t])
        betal[t-1] = logsumexp(betastarl[t] + trans_potentials(t-1), axis=1)
    betal[-1] = 0. # overwritten on last iteration

    if not left_censoring:
        normalizer = logsumexp(initial_state_potential + betastarl[0])
    else:
        raise NotImplementedError

    np.seterr(**errs)
    return betal, betastarl, normalizer
//  [python]
def compute_W(self):

		# Compute P(choose feature)
		# etas = log(P(choose feature) / P(choose knockoff))
		etas_cat = np.concatenate(
			[
				self.etas.reshape(self.N, self.ngroup, 1),
				np.zeros((self.N, self.ngroup, 1))
			],
			axis=2
		)
		# this equals log(P(choose feature))
		log_prob = scipy.special.log_softmax(etas_cat, axis=2)[:, :, 0]
		self.log_prob = np.log(np.sum(np.exp(log_prob - np.max(log_prob, axis=0, keepdims=True)), axis=0)) + np.max(log_prob, axis=0)
		self.W = np.exp(self.log_prob) - 0.5
		# clip numerical errors
		self.W[np.abs(self.W) < 1e-15] = 0
		return self.W
//  [python]
def compute_W(self):

		# Compute P(choose feature)
		# etas = log(P(choose feature) / P(choose knockoff))
		etas_cat = np.concatenate(
			[
				self.etas.reshape(self.N, self.ngroup, 1),
				np.zeros((self.N, self.ngroup, 1))
			],
			axis=2
		)
		# this equals log(P(choose feature))
		log_prob = scipy.special.log_softmax(etas_cat, axis=2)[:, :, 0]
		self.log_prob = scipy.special.logsumexp(log_prob, b=1/self.N, axis=0)
		self.W = np.exp(self.log_prob) - 0.5
		# clip numerical errors
		self.W[np.abs(self.W) < 1e-15] = 0
		return self.W
//  [python]
def __call__(self, y, y_logits):
        y = y.reshape(-1, 1).astype(int, copy=False)

        assert y.size == y_logits.shape[0]

        ignored_inds = (y == self.ignore_index).ravel()

        grads = scipy.special.softmax(y_logits, axis=-1)
        grads[np.arange(y.size), y.ravel()] -= 1.0
        grads[ignored_inds, :] = 0.0

        log_probs = y_logits - scipy.special.logsumexp(y_logits, axis=-1, keepdims=True)
        ce_loss = np.take_along_axis(log_probs, y, axis=-1)
        ce_loss[ignored_inds] = 0.0
        ce_loss = -float(np.sum(ce_loss))

        if self.average:
            valid_tokens_num = int(np.sum(~ignored_inds)) + 1e-7
            ce_loss /= valid_tokens_num
            grads /= valid_tokens_num

        return ce_loss, grads
//  [python]
def hsmm_messages_forwards_log(
    trans_potential, initial_state_potential,
    reverse_cumulative_obs_potentials, reverse_dur_potentials, reverse_dur_survival_potentials,
    alphal, alphastarl,
    left_censoring=False, right_censoring=True):

    T, _ = alphal.shape

    alphastarl[0] = initial_state_potential
    for t in range(T-1):
        cB = reverse_cumulative_obs_potentials(t)
        alphal[t] = np.logaddexp.reduce(
            alphastarl[t+1-cB.shape[0]:t+1] + cB + reverse_dur_potentials(t), axis=0)
        if left_censoring:
            raise NotImplementedError
        alphastarl[t+1] = np.logaddexp.reduce(
            alphal[t][:,na] + trans_potential(t), axis=0)
    t = T-1
    cB = reverse_cumulative_obs_potentials(t)
    alphal[t] = np.logaddexp.reduce(
        alphastarl[t+1-cB.shape[0]:t+1] + cB + reverse_dur_potentials(t), axis=0)

    if not right_censoring:
        normalizer = np.logaddexp.reduce(alphal[t])
    else:
        normalizer = None # TODO

    return alphal, alphastarl, normalizer
//  [python]
def hsmm_messages_forwards_log(
    trans_potential, initial_state_potential,
    reverse_cumulative_obs_potentials, reverse_dur_potentials, reverse_dur_survival_potentials,
    alphal, alphastarl,
    left_censoring=False, right_censoring=True):

    T, _ = alphal.shape

    alphastarl[0] = initial_state_potential
    for t in range(T-1):
        cB = reverse_cumulative_obs_potentials(t)
        alphal[t] = logsumexp(
            alphastarl[t+1-cB.shape[0]:t+1] + cB + reverse_dur_potentials(t), axis=0)
        if left_censoring:
            raise NotImplementedError
        alphastarl[t+1] = logsumexp(
            alphal[t][:,na] + trans_potential(t), axis=0)
    t = T-1
    cB = reverse_cumulative_obs_potentials(t)
    alphal[t] = logsumexp(
        alphastarl[t+1-cB.shape[0]:t+1] + cB + reverse_dur_potentials(t), axis=0)

    if not right_censoring:
        normalizer = logsumexp(alphal[t])
    else:
        normalizer = None # TODO

    return alphal, alphastarl, normalizer
//  [python]
def hsmm_sample_forwards_log(
    trans_potentials, initial_state_potential,
    cumulative_obs_potentials, dur_potentials, dur_survival_potentails,
    betal, betastarl,
    left_censoring=False, right_censoring=True):

    T, _ = betal.shape
    stateseq = np.empty(T,dtype=np.int32)
    durations = []

    t = 0

    if left_censoring:
        raise NotImplementedError
    else:
        nextstate_unsmoothed = initial_state_potential

    while t < T:
        ## sample the state
        nextstate_distn_log = nextstate_unsmoothed + betastarl[t]
        nextstate_distn = np.exp(nextstate_distn_log - logsumexp(nextstate_distn_log))
        assert nextstate_distn.sum() > 0
        state = sample_discrete(nextstate_distn)

        ## sample the duration
        dur_logpmf = dur_potentials(t)[:,state]
        obs, offset = cumulative_obs_potentials(t)
        obs, offset = obs[:,state], offset[state]
        durprob = np.random.random()

        dur = 0 # NOTE: always incremented at least once
        while durprob > 0 and dur < dur_logpmf.shape[0] and t+dur < T:
            p_d = np.exp(dur_logpmf[dur] + obs[dur] - offset
                    + betal[t+dur,state] - betastarl[t,state])

            assert not np.isnan(p_d)
            durprob -= p_d
            dur += 1

        stateseq[t:t+dur] = state
        durations.append(dur)

        t += dur
        nextstate_log_distn = trans_potentials(t)[state]

    return stateseq, durations
//  [python]
def compute_W(self, signs):

		# 1. Guess sign(beta)
		self.sign_guess = np.sign(
			np.sum(signs > 0, axis=0) - np.sum(signs < 0, axis=0)
		)
		nzeros = np.sum(self.sign_guess == 0)
		self.sign_guess[self.sign_guess == 0] = 1 - 2*np.random.binomial(1, 0.5, nzeros)			# Compute log(P(tildebeta) = sign_guess)
		
		# 2. Compute P(log(tildebeta) = sign_guess)
		eta_g0 = self.sign_guess == np.sign(signs)
		adj_eta = self.etas * (2*eta_g0 - 1)
		etas_cat = np.concatenate(
			[
				adj_eta.reshape(self.N, self.p, 1), 
				np.zeros((self.N, self.p, 1))
			],
			axis=2
		)
		# This equals: log(P(sgn(tildebeta) = sign guess))
		log_prob = scipy.special.log_softmax(etas_cat, axis=2)[:, :, 0]
		log_prob = np.log(np.sum(np.exp(log_prob - log_prob.max(axis=0)), axis=0)) + log_prob.max(axis=0) + np.log(1/self.N)
		self.W = np.exp(log_prob) - 0.5

		# 3. Compute sign(W)
		self.wrong_guesses = np.sign(self.tildebeta) != self.sign_guess
		self.W[self.wrong_guesses] = -1 * self.W[self.wrong_guesses]
		return self.W
//  [python]
def compute_W(self, signs):

		# 1. Guess sign(beta)
		self.sign_guess = np.sign(
			np.sum(signs > 0, axis=0) - np.sum(signs < 0, axis=0)
		)
		nzeros = np.sum(self.sign_guess == 0)
		self.sign_guess[self.sign_guess == 0] = 1 - 2*np.random.binomial(1, 0.5, nzeros)			# Compute log(P(tildebeta) = sign_guess)
		
		# 2. Compute P(log(tildebeta) = sign_guess)
		eta_g0 = self.sign_guess == np.sign(signs)
		adj_eta = self.etas * (2*eta_g0 - 1)
		etas_cat = np.concatenate(
			[
				adj_eta.reshape(self.N, self.p, 1), 
				np.zeros((self.N, self.p, 1))
			],
			axis=2
		)
		# This equals: log(P(sgn(tildebeta) = sign guess))
		log_prob = scipy.special.log_softmax(etas_cat, axis=2)[:, :, 0]
		log_prob = scipy.special.logsumexp(log_prob, b=1/self.N, axis=0)
		self.W = np.exp(log_prob) - 0.5

		# 3. Compute sign(W)
		self.wrong_guesses = np.sign(self.tildebeta) != self.sign_guess
		self.W[self.wrong_guesses] = -1 * self.W[self.wrong_guesses]
		return self.W
//  [python]
def get_logprobs_by_actions(self, contexts, actions):
    """Returns log-probabilities for each given action and context.

    Args:
      contexts: Array of contexts (n-times-d, d=data dim., n=sample size).
      actions: Actions (integers) for which probabilies are requested.
    Returns: Log-probabilities according to the policy.
    """
    v = (1.0 / self.temperature) * contexts.dot(self.parameters)
    pot = (1.0 / self.temperature) * (contexts *
                                      self.parameters[:, actions].T).sum(axis=1)
    logprob = pot - scipy.misc.logsumexp(v, axis=1)
    return logprob
//  [python]
def get_logprobs_by_actions(self, contexts, actions):
    """Returns log-probabilities for each given action and context.

    Args:
      contexts: Array of contexts (n-times-d, d=data dim., n=sample size).
      actions: Actions (integers) for which probabilies are requested.
    Returns: Log-probabilities according to the policy.
    """
    v = (1.0 / self.temperature) * contexts.dot(self.parameters)
    pot = (1.0 / self.temperature) * (contexts *
                                      self.parameters[:, actions].T).sum(axis=1)
    logprob = pot - scipy.special.logsumexp(v, axis=1)
    return logprob
//  [python]
def get_logprobs(self, contexts: np.ndarray):
    """Returns log-probabilities over actions for each given context.

    The softmax policy is defined as a probability vector
      log(exp(<W,x> / temp) / sum(exp(<W,x> / temp)))
      where temp is a temperature of a policy and
      W is a K-times-d matrix of parameters (here K is a number of actions
      and d is a context dimension) fitted by gradient ascent.

    Args:
      contexts: Array of contexts (n-times-d, d=data dim., n=sample size).
    Returns: Array of log-probabilities according to the policy (n-times-K).
    """
    v = (1.0 / self.temperature) * contexts.dot(self.parameters)
    logprob = v - np.expand_dims(np.log(np.sum(np.exp(v), axis=1)), axis=1)
    return logprob
//  [python]
def get_logprobs(self, contexts: np.ndarray):
    """Returns log-probabilities over actions for each given context.

    The softmax policy is defined as a probability vector
      log(exp(<W,x> / temp) / sum(exp(<W,x> / temp)))
      where temp is a temperature of a policy and
      W is a K-times-d matrix of parameters (here K is a number of actions
      and d is a context dimension) fitted by gradient ascent.

    Args:
      contexts: Array of contexts (n-times-d, d=data dim., n=sample size).
    Returns: Array of log-probabilities according to the policy (n-times-K).
    """
    v = (1.0 / self.temperature) * contexts.dot(self.parameters)
    logprob = v - np.expand_dims(scipy.special.logsumexp(v, axis=1), axis=1)
    return logprob
//  [python]
def _lnfoldedprob_and_blob(self, folded_par_vals, as_dict=False):
        """
        Return log of the folded probability and a blob with extra
        information. The blob is provided by the likelihood class
        (self.posterior.likelihood.get_blob), and additionally this
        method chooses a random unfolding based on the probabilities and
        appends the unfolded parameter values to the blob.
        """
        lnprobs, par_dics, metadatas = self._get_lnprobs_pardics_metadatas(
            *folded_par_vals)

        ln_folded_prob = np.log(np.sum(np.exp(lnprobs)))

        if np.isneginf(ln_folded_prob):
            i_unfold = 0
        else:
            probabilities = np.exp(lnprobs - ln_folded_prob)
            i_unfold = self._rng.choice(len(probabilities), p=probabilities)

        blob = (par_dics[i_unfold]
                | self.posterior.likelihood.get_blob(metadatas[i_unfold]))

        if as_dict:
            return ln_folded_prob, blob

        return ln_folded_prob, *blob.values()
//  [python]
def _lnfoldedprob_and_blob(self, folded_par_vals, as_dict=False):
        """
        Return log of the folded probability and a blob with extra
        information. The blob is provided by the likelihood class
        (self.posterior.likelihood.get_blob), and additionally this
        method chooses a random unfolding based on the probabilities and
        appends the unfolded parameter values to the blob.
        """
        lnprobs, par_dics, metadatas = self._get_lnprobs_pardics_metadatas(
            *folded_par_vals)

        ln_folded_prob = scipy.special.logsumexp(lnprobs)

        if np.isneginf(ln_folded_prob):
            i_unfold = 0
        else:
            probabilities = np.exp(lnprobs - ln_folded_prob)
            i_unfold = self._rng.choice(len(probabilities), p=probabilities)

        blob = (par_dics[i_unfold]
                | self.posterior.likelihood.get_blob(metadatas[i_unfold]))

        if as_dict:
            return ln_folded_prob, blob

        return ln_folded_prob, *blob.values()
//  [python]
def mce_partition_fh(env, *, R=None):
    r"""Performs the soft Bellman backup for a finite-horizon, undiscounted MDP.

    Calculates V^{soft}, Q^{soft}, and pi using recurrences (9.1), (9.2), and
    (9.3) from Ziebart (2010).

    Args:
        env (ModelBasedEnv): a tabular, known-dynamics MDP.
        R (None or np.array): a reward matrix. Defaults to env.reward_matrix.

    Returns:
        (V, Q, \pi) corresponding to the soft values, Q-values and MCE policy.
        V is a 2d array, indexed V[t,s]. Q is a 3d array, indexed Q[t,s,a].
        \pi is a 3d array, indexed \pi[t,s,a].
    """

    # shorthand
    horizon = env.horizon
    n_states = env.n_states
    n_actions = env.n_actions
    T = env.transition_matrix
    if R is None:
        R = env.reward_matrix

    # Initialization
    # indexed as V[t,s]
    V = np.full((horizon, n_states), -np.inf)
    # indexed as Q[t,s,a]
    Q = np.zeros((horizon, n_states, n_actions))
    broad_R = R[:, None]

    # Base case: final timestep
    # final Q(s,a) is just reward
    Q[horizon - 1, :, :] = broad_R
    # V(s) is always normalising constant
    V[horizon - 1, :] = np.max(Q[horizon - 1, :, :], axis=1)

    # Recursive case
    for t in reversed(range(horizon - 1)):
        next_values_s_a = T @ V[t + 1, :]
        Q[t, :, :] = broad_R + next_values_s_a
        V[t, :] = np.max(Q[t, :, :], axis=1)

    pi = np.exp(Q - V[:, :, None])

    return V, Q, pi
//  [python]
def mce_partition_fh(env, *, R=None):
    r"""Performs the soft Bellman backup for a finite-horizon, undiscounted MDP.

    Calculates V^{soft}, Q^{soft}, and pi using recurrences (9.1), (9.2), and
    (9.3) from Ziebart (2010).

    Args:
        env (ModelBasedEnv): a tabular, known-dynamics MDP.
        R (None or np.array): a reward matrix. Defaults to env.reward_matrix.

    Returns:
        (V, Q, \pi) corresponding to the soft values, Q-values and MCE policy.
        V is a 2d array, indexed V[t,s]. Q is a 3d array, indexed Q[t,s,a].
        \pi is a 3d array, indexed \pi[t,s,a].
    """

    # shorthand
    horizon = env.horizon
    n_states = env.n_states
    n_actions = env.n_actions
    T = env.transition_matrix
    if R is None:
        R = env.reward_matrix

    # Initialization
    # indexed as V[t,s]
    V = np.full((horizon, n_states), -np.inf)
    # indexed as Q[t,s,a]
    Q = np.zeros((horizon, n_states, n_actions))
    broad_R = R[:, None]

    # Base case: final timestep
    # final Q(s,a) is just reward
    Q[horizon - 1, :, :] = broad_R
    # V(s) is always normalising constant
    V[horizon - 1, :] = scipy.special.logsumexp(Q[horizon - 1, :, :], axis=1)

    # Recursive case
    for t in reversed(range(horizon - 1)):
        next_values_s_a = T @ V[t + 1, :]
        Q[t, :, :] = broad_R + next_values_s_a
        V[t, :] = scipy.special.logsumexp(Q[t, :, :], axis=1)

    pi = np.exp(Q - V[:, :, None])

    return V, Q, pi
//  [python]
def test_masked_logmeanexp(self):
    # test1: compare against numpy/scipy implementation.
    masked_scores = self.scores
    num_masked_ele = np.sum(masked_scores > 0.)
    masked_scores[masked_scores <= 0.] = -np.inf
    numpy_impl = np.float32(
        np.logaddexp.reduce(masked_scores) - np.log(num_masked_ele))
    result_0d = mi._masked_logmeanexp(self.scores, self.scores > 0, axis=None)
    self.assertAllClose(self.evaluate(result_0d), numpy_impl)

    # test2: test against results from composition of numpy functions.
    scores_2 = np.array([[2., 5., -1e-3],
                         [-1073., 4.2, -4.]], dtype=np.float32)
    result_empty_sum = mi._masked_logmeanexp(
        scores_2, scores_2 < 0., axis=None)
    numpy_result = np.log(np.mean(np.exp(scores_2[scores_2 < 0.])))
    self.assertAllClose(self.evaluate(result_empty_sum),
                        numpy_result.astype(np.float32))

    # test3: whether `axis` arg works as expected.
    result_1d = mi._masked_logmeanexp(self.scores, self.scores > 0, axis=[1,])
    self.assertEqual(result_1d.shape, [13,])
//  [python]
def test_masked_logmeanexp(self):
    # test1: compare against numpy/scipy implementation.
    masked_scores = self.scores
    num_masked_ele = np.sum(masked_scores > 0.)
    masked_scores[masked_scores <= 0.] = -np.inf
    numpy_impl = np.float32(
        scipy.special.logsumexp(masked_scores) - np.log(num_masked_ele))
    result_0d = mi._masked_logmeanexp(self.scores, self.scores > 0, axis=None)
    self.assertAllClose(self.evaluate(result_0d), numpy_impl)

    # test2: test against results from composition of numpy functions.
    scores_2 = np.array([[2., 5., -1e-3],
                         [-1073., 4.2, -4.]], dtype=np.float32)
    result_empty_sum = mi._masked_logmeanexp(
        scores_2, scores_2 < 0., axis=None)
    numpy_result = np.log(np.mean(np.exp(scores_2[scores_2 < 0.])))
    self.assertAllClose(self.evaluate(result_empty_sum),
                        numpy_result.astype(np.float32))

    # test3: whether `axis` arg works as expected.
    result_1d = mi._masked_logmeanexp(self.scores, self.scores > 0, axis=[1,])
    self.assertEqual(result_1d.shape, [13,])
//  [python]
def logsumexp(tensor, axis=0):
        return s.logsumexp(tensor, axis=axis)
//  [python]
def logsumexp(tensor, axis=0):
        return scipy.special.logsumexp(tensor, axis=axis)
//  [python]
def __call__(self, obs, info={}):
    self.belief_logits = utils.update_beliefs(self.env, self.belief_logits, obs, self.prev_act, self.obs_model, self.dynamics_model)
    act_logits = np.log(np.sum(np.exp(self.q_vals + self.belief_logits[:, np.newaxis]), axis=0))
    self.prev_act = utils.sample_from_categorical(act_logits)
    return self.prev_act
//  [python]
def __call__(self, obs, info={}):
    self.belief_logits = utils.update_beliefs(self.env, self.belief_logits, obs, self.prev_act, self.obs_model, self.dynamics_model)
    act_logits = scipy.special.logsumexp(self.q_vals + self.belief_logits[:, np.newaxis], axis=0)
    self.prev_act = utils.sample_from_categorical(act_logits)
    return self.prev_act
//  [python]
def calculate_mi_bounds_on_p(sess, vae, n_samples, m_iwae_samples, iwae_batch_size, n_repeats, tqdm_desc):
    res = []
    with tqdm(total=n_repeats * n_samples * (m_iwae_samples + 1), desc=tqdm_desc) as tqdm_t:
        mi_lower_bound_per_sample = []
        mi_upper_bound_per_sample = []

        for _ in range(n_repeats):
            for _ in range(n_samples):
                x, hvm_term, log_p_x_z = sess.run([vae._mi_p_x, vae._mi_p_hvm_term, vae._mi_p_log_p_x_z])
                tqdm_t.update(1)

                elbos = []
                m_offset = 0
                while m_offset < m_iwae_samples:
                    batch_size = min(iwae_batch_size, m_iwae_samples - m_offset)
                    m_offset += batch_size

                    elbos_subset = sess.run(vae._mi_p_elbos, feed_dict={vae._mi_p_x: x, vae.m_iwae_samples: batch_size})
                    elbos.extend(elbos_subset)

                    tqdm_t.update(batch_size)

                assert len(elbos) == m_iwae_samples
                log_p_lower_bound = np.max(elbos) + np.log(np.sum(np.exp(elbos - np.max(elbos)))) - np.log(m_iwae_samples)
                log_p_upper_bound = np.max(elbos + [hvm_term]) + np.log(np.sum(np.exp(elbos + [hvm_term] - np.max(elbos + [hvm_term])))) - np.log(m_iwae_samples + 1)

                mi_lower_bound_per_sample.append(log_p_x_z - log_p_upper_bound)
                mi_upper_bound_per_sample.append(log_p_x_z - log_p_lower_bound)

            res.append((np.mean(mi_lower_bound_per_sample), np.mean(mi_upper_bound_per_sample)))
            tqdm_t.set_description(tqdm_desc + ', cur. est.: {:.3f} <= MI <= {:.3f}'.format(*np.mean(res, axis=0)))

    return np.array(res).T
//  [python]
def calculate_mi_bounds_on_p(sess, vae, n_samples, m_iwae_samples, iwae_batch_size, n_repeats, tqdm_desc):
    res = []
    with tqdm(total=n_repeats * n_samples * (m_iwae_samples + 1), desc=tqdm_desc) as tqdm_t:
        mi_lower_bound_per_sample = []
        mi_upper_bound_per_sample = []

        for _ in range(n_repeats):
            for _ in range(n_samples):
                x, hvm_term, log_p_x_z = sess.run([vae._mi_p_x, vae._mi_p_hvm_term, vae._mi_p_log_p_x_z])
                tqdm_t.update(1)

                elbos = []
                m_offset = 0
                while m_offset < m_iwae_samples:
                    batch_size = min(iwae_batch_size, m_iwae_samples - m_offset)
                    m_offset += batch_size

                    elbos_subset = sess.run(vae._mi_p_elbos, feed_dict={vae._mi_p_x: x, vae.m_iwae_samples: batch_size})
                    elbos.extend(elbos_subset)

                    tqdm_t.update(batch_size)

                assert len(elbos) == m_iwae_samples
                log_p_lower_bound = sp.special.logsumexp(elbos) - np.log(m_iwae_samples)
                log_p_upper_bound = sp.special.logsumexp(elbos + [hvm_term]) - np.log(m_iwae_samples + 1)

                mi_lower_bound_per_sample.append(log_p_x_z - log_p_upper_bound)
                mi_upper_bound_per_sample.append(log_p_x_z - log_p_lower_bound)

            res.append((np.mean(mi_lower_bound_per_sample), np.mean(mi_upper_bound_per_sample)))
            tqdm_t.set_description(tqdm_desc + ', cur. est.: {:.3f} <= MI <= {:.3f}'.format(*np.mean(res, axis=0)))

    return np.array(res).T
//  [python]
def log_normalization_constant(self, *, all_g):
        """
        Computes normalization constant for log p(G), i.e. `Z = log(sum_G p(g))`

        Args:
            all_g: list of igraph.Graph objects

        Returns:
            float
        """
        log_prob_g_unn = np.zeros(len(all_g))
        for i, g in enumerate(tqdm.tqdm(all_g, desc='p(G) log_normalization_constant', disable=not self.verbose)):
            log_prob_g_unn[i] = self.unnormalized_log_prob(g=g)
        log_prob_sum_g = s.logsumexp(log_prob_g_unn)
        return log_prob_sum_g
//  [python]
def log_normalization_constant(self, *, all_g):
        """
        Computes normalization constant for log p(G), i.e. `Z = log(sum_G p(g))`

        Args:
            all_g: list of igraph.Graph objects

        Returns:
            float
        """
        log_prob_g_unn = np.zeros(len(all_g))
        for i, g in enumerate(tqdm.tqdm(all_g, desc='p(G) log_normalization_constant', disable=not self.verbose)):
            log_prob_g_unn[i] = self.unnormalized_log_prob(g=g)
        log_prob_sum_g = scipy.special.logsumexp(log_prob_g_unn)
        return log_prob_sum_g
//  [python]
def kfoldCrossValidationMVG(D, L):
    numberOfCorrectPredictions = 0
    for i in range(D.shape[1]):
        (DTR, LTR), (DEV, LEV) = (np.delete(D, i, 1), np.delete(L, i)), (vcol(D[:, i], 4), L[i])
        (mu0, sigma0), (mu1, sigma1), (mu2, sigma2) = computeMLestimates(DTR, LTR)
        logS = computeScoreMatrix(DEV, mu0, sigma0, mu1, sigma1, mu2, sigma2, logpdf_GAU_ND)
        priorLogProbabilities = vcol(np.array([np.log(1/3), np.log(1/3), np.log(1/3)]), 3)
        logSJoint = logS+priorLogProbabilities
        marginalLogDensities = vrow(np.max(logSJoint, axis=0) + np.log(np.sum(np.exp(logSJoint - np.max(logSJoint, axis=0)), axis=0)), 1)
        logSPost = logSJoint-marginalLogDensities
        predictedLabels = logSPost.argmax(axis=0)
        numberOfCorrectPredictions += np.array(predictedLabels == LEV).sum()
    accuracy = numberOfCorrectPredictions/L.size * 100
    errorRate = 100-accuracy
    print("Accuracy of the MVG classifier when working with log-densities and using K-fold cross validation with leave-one-out approach: %.2f %%" % (accuracy))
    print("Error rate: %.2f %%" % (errorRate))
    return
//  [python]
def kfoldCrossValidationMVG(D, L):
    # Same procedure of MVGlogdensities but with leave-one-out approach:
    # number of folds is equal to the number of samples, we iterate over all samples
    # and each time we use one of them as evaluation set and the remaining 149
    # as training set.
    # Then we compute the predicted lable and count how many times it is correct.
    numberOfCorrectPredictions = 0
    for i in range(D.shape[1]):  # i=0...149
        # Each time we need to delete the i-th column (sample) from the training set
        # while in the evaluation set we should keep only the i-th column.
        # vcol is necessary to exploit broadcasting
        (DTR, LTR), (DEV, LEV) = (np.delete(D, i, 1),
                                  np.delete(L, i)), (vcol(D[:, i], 4), L[i])
        (mu0, sigma0), (mu1, sigma1), (mu2, sigma2) = computeMLestimates(DTR, LTR)
        logS = computeScoreMatrix(DEV, mu0, sigma0, mu1,
                                  sigma1, mu2, sigma2, logpdf_GAU_ND)
        priorLogProbabilities = vcol(
            np.array([np.log(1/3), np.log(1/3), np.log(1/3)]), 3)
        logSJoint = logS+priorLogProbabilities  # 3x1
        marginalLogDensities = vrow(
            sc.special.logsumexp(logSJoint, axis=0), 1)  # 1x1
        # We need to keep it as 1x1 to exploit broadcasting
        logSPost = logSJoint-marginalLogDensities
        predictedLabels = logSPost.argmax(axis=0)
        # Add the result of prediction to the proper variable
        numberOfCorrectPredictions += np.array(predictedLabels == LEV).sum()
    # Now we can compute percentage values for accuracy and error rate.
    accuracy = numberOfCorrectPredictions/L.size * \
        100  # over all samples, that are 150
    errorRate = 100-accuracy
    print("Accuracy of the MVG classifier when working with log-densities and "
          "using K-fold cross validation with leave-one-out approach: %.2f %%" % (accuracy))
    print("Error rate: %.2f %%" % (errorRate))
    return
//  [python]
def kfoldCrossValidationNBG(D, L):
    numberOfCorrectPredictions = 0
    for i in range(D.shape[1]):
        (DTR, LTR), (DEV, LEV) = (np.delete(D, i, 1), np.delete(L, i)), (vcol(D[:, i], 4), L[i])
        (mu0, sigma0), (mu1, sigma1), (mu2, sigma2) = computeMLestimates(DTR, LTR)
        (sigma0, sigma1, sigma2) = (sigma0*np.identity(sigma0.shape[0]), sigma1*np.identity(
            sigma1.shape[0]), sigma2*np.identity(sigma2.shape[0]))
        logS = computeScoreMatrix(DEV, mu0, sigma0, mu1,
                                  sigma1, mu2, sigma2, logpdf_GAU_ND)
        priorLogProbabilities = vcol(
            np.array([np.log(1/3), np.log(1/3), np.log(1/3)]), 3)
        logSJoint = logS+priorLogProbabilities  # 3x1
        marginalLogDensities = vrow(
            np.log(np.sum(np.exp(logSJoint), axis=0)), 1)  
        logSPost = logSJoint-marginalLogDensities
        predictedLabels = logSPost.argmax(axis=0)
        numberOfCorrectPredictions += np.array(predictedLabels == LEV).sum()
    accuracy = numberOfCorrectPredictions/L.size * 100
    errorRate = 100-accuracy
    print("Accuracy of the Naive Bayes Gaussian classifier when working with log-densities and "
          "using K-fold cross validation with leave-one-out approach: %.2f %%" % (accuracy))
    print("Error rate: %.2f %%" % (errorRate))
    return