Beispiel #1
0
 def __post_init__(self):
     D = self.mean.shape[-1]
     c = np.reshape(self.covariance, (-1, ))
     pc = _compute_precision_cholesky(c, 'diag')
     self.precision_cholesky = np.reshape(pc, self.covariance.shape)
     self.log_det_precision_cholesky = _compute_log_det_cholesky(
         pc, 'spherical', D)
Beispiel #2
0
 def __post_init__(self):
     D = self.mean.shape[-1]
     c = np.reshape(self.covariance, (-1, D, D))
     pc = _compute_precision_cholesky(c, 'full')
     self.precision_cholesky = np.reshape(pc, self.covariance.shape)
     self.log_det_precision_cholesky = np.reshape(
         _compute_log_det_cholesky(pc, 'full', D),
         self.covariance.shape[:-2])
Beispiel #3
0
def _estimate_log_gaussian_prob(X, means, precisions_chol, covariance_type):
    """Estimate the log Gaussian probability.

    Parameters
    ----------
    X : array-like, shape (n_samples, n_features)

    means : array-like, shape (n_components, n_features)

    precisions_chol : array-like
        Cholesky decompositions of the precision matrices.
        'full' : shape of (n_components, n_features, n_features)
        'tied' : shape of (n_features, n_features)
        'diag' : shape of (n_components, n_features)
        'spherical' : shape of (n_components,)

    covariance_type : {'full', 'tied', 'diag', 'spherical'}

    Returns
    -------
    log_prob : array, shape (n_samples, n_components)
    """
    n_samples, n_features = X.shape
    n_components, _ = means.shape
    # det(precision_chol) is half of det(precision)
    log_det = _compute_log_det_cholesky(precisions_chol, covariance_type,
                                        n_features)

    if covariance_type == 'full':
        log_prob = np.empty((n_samples, n_components))
        for k, (mu, prec_chol) in enumerate(zip(means, precisions_chol)):
            y = np.dot(X, prec_chol) - np.dot(mu, prec_chol)
            #print(y.shape)
            #print(np.argmax(np.square(y), axis=1))
            square_y = np.square(y)
            weighted_square_y = square_y
            #print(y.shape[1]-1)
            #print(square_y[0:2,:])
            weighted_square_y[:, -1] *= y.shape[1] - 1
            #print(weighted_square_y[0:2, :])
            log_prob[:, k] = np.sum(weighted_square_y, axis=1)

    return -.5 * (n_features * np.log(2 * np.pi) + log_prob) + log_det
def test_compute_log_det_cholesky():
    n_features = 2
    rand_data = RandomData(np.random.RandomState(0))

    for covar_type in COVARIANCE_TYPE:
        covariance = rand_data.covariances[covar_type]

        if covar_type == 'full':
            predected_det = np.array([linalg.det(cov) for cov in covariance])
        elif covar_type == 'tied':
            predected_det = linalg.det(covariance)
        elif covar_type == 'diag':
            predected_det = np.array([np.prod(cov) for cov in covariance])
        elif covar_type == 'spherical':
            predected_det = covariance ** n_features

        # We compute the cholesky decomposition of the covariance matrix
        expected_det = _compute_log_det_cholesky(_compute_precision_cholesky(
            covariance, covar_type), covar_type, n_features=n_features)
        assert_array_almost_equal(expected_det, - .5 * np.log(predected_det))
Beispiel #5
0
def test_compute_log_det_cholesky():
    n_features = 2
    rand_data = RandomData(np.random.RandomState(0))

    for covar_type in COVARIANCE_TYPE:
        covariance = rand_data.covariances[covar_type]

        if covar_type == 'full':
            predected_det = np.array([linalg.det(cov) for cov in covariance])
        elif covar_type == 'tied':
            predected_det = linalg.det(covariance)
        elif covar_type == 'diag':
            predected_det = np.array([np.prod(cov) for cov in covariance])
        elif covar_type == 'spherical':
            predected_det = covariance ** n_features

        # We compute the cholesky decomposition of the covariance matrix
        expected_det = _compute_log_det_cholesky(_compute_precision_cholesky(
            covariance, covar_type), covar_type, n_features=n_features)
        assert_array_almost_equal(expected_det, - .5 * np.log(predected_det))
Beispiel #6
0
def convert_sklearn_gaussian_mixture(scope, operator, container):
    """
    Converter for *GaussianMixture*,
    *BayesianGaussianMixture*.
    Parameters which change the prediction function:

    * *covariance_type*
    """
    X = operator.inputs[0]
    out = operator.outputs
    op = operator.raw_operator
    n_features = X.type.shape[1]
    n_components = op.means_.shape[0]

    # All comments come from scikit-learn code and tells
    # which functions is being onnxified.
    # def _estimate_weighted_log_prob(self, X):
    # self._estimate_log_prob(X) + self._estimate_log_weights()
    log_weights = np.log(op.weights_)  # self._estimate_log_weights()

    # self._estimate_log_prob(X)
    log_det = _compute_log_det_cholesky(op.precisions_cholesky_,
                                        op.covariance_type, n_features)

    if op.covariance_type == 'full':
        # shape(op.means_) = (n_components, n_features)
        # shape(op.precisions_cholesky_) =
        #   (n_components, n_features, n_features)

        # log_prob = np.empty((n_samples, n_components))
        # for k, (mu, prec_chol) in enumerate(zip(means, precisions_chol)):
        #     y = np.dot(X, prec_chol) - np.dot(mu, prec_chol)
        #     log_prob[:, k] = np.sum(np.square(y), axis=1)

        ys = []
        for c in range(n_components):
            prec_chol = op.precisions_cholesky_[c, :, :]
            cst = -np.dot(op.means_[c, :], prec_chol)
            y = OnnxGemm(X, prec_chol, cst, alpha=1., beta=1.)
            y2s = OnnxReduceSumSquare(y, axes=[1])
            ys.append(y2s)
        log_prob = OnnxConcat(*ys, axis=1)

    elif op.covariance_type == 'tied':
        # shape(op.means_) = (n_components, n_features)
        # shape(op.precisions_cholesky_) =
        #   (n_features, n_features)

        # log_prob = np.empty((n_samples, n_components))
        # for k, mu in enumerate(means):
        #     y = np.dot(X, precisions_chol) - np.dot(mu, precisions_chol)
        #     log_prob[:, k] = np.sum(np.square(y), axis=1)

        precisions_chol = op.precisions_cholesky_
        ys = []
        for f in range(n_components):
            cst = -np.dot(op.means_[f, :], precisions_chol)
            y = OnnxGemm(X, precisions_chol, cst, alpha=1., beta=1.)
            y2s = OnnxReduceSumSquare(y, axes=[1])
            ys.append(y2s)
        log_prob = OnnxConcat(*ys, axis=1)

    elif op.covariance_type == 'diag':
        # shape(op.means_) = (n_components, n_features)
        # shape(op.precisions_cholesky_) =
        #   (n_components, n_features)

        # precisions = precisions_chol ** 2
        # log_prob = (np.sum((means ** 2 * precisions), 1) -
        #             2. * np.dot(X, (means * precisions).T) +
        #             np.dot(X ** 2, precisions.T))

        precisions = op.precisions_cholesky_**2
        mp = np.sum((op.means_**2 * precisions), 1)
        zeros = np.zeros((n_components, ))
        xmp = OnnxGemm(X, (op.means_ * precisions).T,
                       zeros,
                       alpha=-2.,
                       beta=0.)
        term = OnnxGemm(OnnxMul(X, X), precisions.T, zeros, alpha=1., beta=0.)
        log_prob = OnnxAdd(OnnxAdd(mp, xmp), term)

    elif op.covariance_type == 'spherical':
        # shape(op.means_) = (n_components, n_features)
        # shape(op.precisions_cholesky_) = (n_components, )

        # precisions = precisions_chol ** 2
        # log_prob = (np.sum(means ** 2, 1) * precisions -
        #             2 * np.dot(X, means.T * precisions) +
        #             np.outer(row_norms(X, squared=True), precisions))

        zeros = np.zeros((n_components, ))
        precisions = op.precisions_cholesky_**2
        normX = OnnxReduceSumSquare(X, axes=[1])
        outer = OnnxGemm(normX,
                         precisions[np.newaxis, :],
                         zeros,
                         alpha=1.,
                         beta=1.)
        xmp = OnnxGemm(X, (op.means_.T * precisions),
                       zeros,
                       alpha=-2.,
                       beta=0.)
        mp = np.sum(op.means_**2, 1) * precisions
        log_prob = OnnxAdd(mp, OnnxAdd(xmp, outer))
    else:
        raise RuntimeError("Unknown op.covariance_type='{}'. Upgrade "
                           "to a mroe recent version of skearn-onnx "
                           "or raise an issue.".format(op.covariance_type))

    # -.5 * (cst + log_prob) + log_det
    cst = np.array([n_features * np.log(2 * np.pi)])
    add = OnnxAdd(cst, log_prob)
    mul = OnnxMul(add, np.array([-0.5]))
    if isinstance(log_det, float):
        log_det = np.array([log_det])
    weighted_log_prob = OnnxAdd(OnnxAdd(mul, log_det), log_weights)

    # labels
    labels = OnnxArgMax(weighted_log_prob, axis=1, output_names=out[:1])

    # def _estimate_log_prob_resp():
    # np.exp(log_resp)
    # weighted_log_prob = self._estimate_weighted_log_prob(X)
    # log_prob_norm = logsumexp(weighted_log_prob, axis=1)
    # with np.errstate(under='ignore'):
    #    log_resp = weighted_log_prob - log_prob_norm[:, np.newaxis]

    log_prob_norm = OnnxReduceLogSumExp(weighted_log_prob, axes=[1])
    log_resp = OnnxSub(weighted_log_prob, log_prob_norm)

    # probabilities
    probs = OnnxExp(log_resp, output_names=out[1:])

    # final
    labels.add_to(scope, container)
    probs.add_to(scope, container)