{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\n# Concentration Prior Type Analysis of Variation Bayesian Gaussian Mixture\n\nThis example plots the ellipsoids obtained from a toy dataset (mixture of three\nGaussians) fitted by the ``BayesianGaussianMixture`` class models with a\nDirichlet distribution prior\n(``weight_concentration_prior_type='dirichlet_distribution'``) and a Dirichlet\nprocess prior (``weight_concentration_prior_type='dirichlet_process'``). On\neach figure, we plot the results for three different values of the weight\nconcentration prior.\n\nThe ``BayesianGaussianMixture`` class can adapt its number of mixture\ncomponents automatically. The parameter ``weight_concentration_prior`` has a\ndirect link with the resulting number of components with non-zero weights.\nSpecifying a low value for the concentration prior will make the model put most\nof the weight on few components set the remaining components weights very close\nto zero. High values of the concentration prior will allow a larger number of\ncomponents to be active in the mixture.\n\nThe Dirichlet process prior allows to define an infinite number of components\nand automatically selects the correct number of components: it activates a\ncomponent only if it is necessary.\n\nOn the contrary the classical finite mixture model with a Dirichlet\ndistribution prior will favor more uniformly weighted components and therefore\ntends to divide natural clusters into unnecessary sub-components.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "# Authors: The scikit-learn developers\n# SPDX-License-Identifier: BSD-3-Clause\n\nimport matplotlib as mpl\nimport matplotlib.gridspec as gridspec\nimport matplotlib.pyplot as plt\nimport numpy as np\n\nfrom sklearn.mixture import BayesianGaussianMixture\n\n\ndef plot_ellipses(ax, weights, means, covars):\n    for n in range(means.shape[0]):\n        eig_vals, eig_vecs = np.linalg.eigh(covars[n])\n        unit_eig_vec = eig_vecs[0] / np.linalg.norm(eig_vecs[0])\n        angle = np.arctan2(unit_eig_vec[1], unit_eig_vec[0])\n        # Ellipse needs degrees\n        angle = 180 * angle / np.pi\n        # eigenvector normalization\n        eig_vals = 2 * np.sqrt(2) * np.sqrt(eig_vals)\n        ell = mpl.patches.Ellipse(\n            means[n], eig_vals[0], eig_vals[1], angle=180 + angle, edgecolor=\"black\"\n        )\n        ell.set_clip_box(ax.bbox)\n        ell.set_alpha(weights[n])\n        ell.set_facecolor(\"#56B4E9\")\n        ax.add_artist(ell)\n\n\ndef plot_results(ax1, ax2, estimator, X, y, title, plot_title=False):\n    ax1.set_title(title)\n    ax1.scatter(X[:, 0], X[:, 1], s=5, marker=\"o\", color=colors[y], alpha=0.8)\n    ax1.set_xlim(-2.0, 2.0)\n    ax1.set_ylim(-3.0, 3.0)\n    ax1.set_xticks(())\n    ax1.set_yticks(())\n    plot_ellipses(ax1, estimator.weights_, estimator.means_, estimator.covariances_)\n\n    ax2.get_xaxis().set_tick_params(direction=\"out\")\n    ax2.yaxis.grid(True, alpha=0.7)\n    for k, w in enumerate(estimator.weights_):\n        ax2.bar(\n            k,\n            w,\n            width=0.9,\n            color=\"#56B4E9\",\n            zorder=3,\n            align=\"center\",\n            edgecolor=\"black\",\n        )\n        ax2.text(k, w + 0.007, \"%.1f%%\" % (w * 100.0), horizontalalignment=\"center\")\n    ax2.set_xlim(-0.6, 2 * n_components - 0.4)\n    ax2.set_ylim(0.0, 1.1)\n    ax2.tick_params(axis=\"y\", which=\"both\", left=False, right=False, labelleft=False)\n    ax2.tick_params(axis=\"x\", which=\"both\", top=False)\n\n    if plot_title:\n        ax1.set_ylabel(\"Estimated Mixtures\")\n        ax2.set_ylabel(\"Weight of each component\")\n\n\n# Parameters of the dataset\nrandom_state, n_components, n_features = 2, 3, 2\ncolors = np.array([\"#0072B2\", \"#F0E442\", \"#D55E00\"])\n\ncovars = np.array(\n    [[[0.7, 0.0], [0.0, 0.1]], [[0.5, 0.0], [0.0, 0.1]], [[0.5, 0.0], [0.0, 0.1]]]\n)\nsamples = np.array([200, 500, 200])\nmeans = np.array([[0.0, -0.70], [0.0, 0.0], [0.0, 0.70]])\n\n# mean_precision_prior= 0.8 to minimize the influence of the prior\nestimators = [\n    (\n        \"Finite mixture with a Dirichlet distribution\\n\" r\"prior and $\\gamma_0=$\",\n        BayesianGaussianMixture(\n            weight_concentration_prior_type=\"dirichlet_distribution\",\n            n_components=2 * n_components,\n            reg_covar=0,\n            init_params=\"random\",\n            max_iter=1500,\n            mean_precision_prior=0.8,\n            random_state=random_state,\n        ),\n        [0.001, 1, 1000],\n    ),\n    (\n        \"Infinite mixture with a Dirichlet process\\n\" r\"prior and $\\gamma_0=$\",\n        BayesianGaussianMixture(\n            weight_concentration_prior_type=\"dirichlet_process\",\n            n_components=2 * n_components,\n            reg_covar=0,\n            init_params=\"random\",\n            max_iter=1500,\n            mean_precision_prior=0.8,\n            random_state=random_state,\n        ),\n        [1, 1000, 100000],\n    ),\n]\n\n# Generate data\nrng = np.random.RandomState(random_state)\nX = np.vstack(\n    [\n        rng.multivariate_normal(means[j], covars[j], samples[j])\n        for j in range(n_components)\n    ]\n)\ny = np.concatenate([np.full(samples[j], j, dtype=int) for j in range(n_components)])\n\n# Plot results in two different figures\nfor title, estimator, concentrations_prior in estimators:\n    plt.figure(figsize=(4.7 * 3, 8))\n    plt.subplots_adjust(\n        bottom=0.04, top=0.90, hspace=0.05, wspace=0.05, left=0.03, right=0.99\n    )\n\n    gs = gridspec.GridSpec(3, len(concentrations_prior))\n    for k, concentration in enumerate(concentrations_prior):\n        estimator.weight_concentration_prior = concentration\n        estimator.fit(X)\n        plot_results(\n            plt.subplot(gs[0:2, k]),\n            plt.subplot(gs[2, k]),\n            estimator,\n            X,\n            y,\n            r\"%s$%.1e$\" % (title, concentration),\n            plot_title=k == 0,\n        )\n\nplt.show()"
      ]
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.11.14"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}