def jensen_shannon_multivariate(X, weights=None):
    """Calculate Jensen-Shannon divergence between several distributions.

    Parameters
    ----------
    X : array-like, shape = (n_samples, n_distributions)
        Discrete probability distributions.

    weights : array-like, shape = (n_distributions)
        Array of weights associated with the distributions. If None all
        distributions are assumed to have equal weight.

    Returns
    -------
    jensen_shannon : float
    """
    if X.ndim < 2:
        raise ValueError("X must be a 2-D array")

    X = np.asarray(X)
    n = X.shape[1]

    if weights is not None:
        weights = np.asarray(weights)

        if len(weights) != n:
            raise ValueError("Shapes of X and weights differ.")

        if weights.sum() != 1.0:
            raise ValueError("weights must sum 1.")
    else:
        weights = np.ones(n) / n

    js = entropy(np.sum(weights * X, axis=1))
    js -= np.dot(weights, [entropy(X[:, i]) for i in range(n)])

    return js
Calculate Jensen-Shannon divergence between several distributions.

    Parameters
    ----------
    X : array-like, shape = (n_samples, n_distributions)
        Discrete probability distributions.

    weights : array-like, shape = (n_distributions)
        Array of weights associated with the distributions. If None all
        distributions are assumed to have equal weight.

    Returns
    -------
    jensen_shannon : float
    
optbinning/binning/metrics.py