xbe.at

Statistics and maths / Probability and distributions

Gaussian Mixture Model

12 min read, 15 sections

Contents
  1. Introduction to Gaussian Mixture Models
  2. Components of a Gaussian Mixture Model
  3. Expectation-Maximization Algorithm
  4. Choosing the Number of Components
  5. Gaussian Mixture Models for Clustering
  6. Gaussian Mixture Models for Anomaly Detection
  7. Gaussian Mixture Models for Density Estimation
  8. Gaussian Mixture Models for Image Segmentation
  9. Gaussian Mixture Models for Speech Recognition
  10. Gaussian Mixture Models for Handwriting Recognition
  11. Gaussian Mixture Models for Data Generation
  12. Gaussian Mixture Models for Outlier Detection
  13. Gaussian Mixture Models for Dimensionality Reduction
  14. Gaussian Mixture Models for Time Series Analysis
  15. Additional Resources

Introduction to Gaussian Mixture Models

Gaussian Mixture Models (GMMs) are powerful probabilistic models used for clustering and density estimation. They represent complex probability distributions by combining multiple Gaussian distributions. GMMs are widely used in various fields, including computer vision, speech recognition, and data analysis.

import numpy as np
import matplotlib.pyplot as plt
from sklearn.mixture import GaussianMixture

# Generate sample data
np.random.seed(42)
X = np.concatenate([
    np.random.normal(0, 1, 300),
    np.random.normal(5, 1.5, 700)
]).reshape(-1, 1)

# Fit GMM
gmm = GaussianMixture(n_components=2, random_state=42)
gmm.fit(X)

# Plot results
x = np.linspace(-5, 10, 1000).reshape(-1, 1)
y = np.exp(gmm.score_samples(x))
plt.hist(X, bins=50, density=True, alpha=0.5)
plt.plot(x, y, 'r-', label='GMM')
plt.title('Gaussian Mixture Model Example')
plt.xlabel('Value')
plt.ylabel('Density')
plt.legend()
plt.show()

Components of a Gaussian Mixture Model

A Gaussian Mixture Model consists of multiple Gaussian distributions, each characterized by its mean, covariance, and mixing coefficient. The mean determines the center of the distribution, the covariance defines its shape and orientation, and the mixing coefficient represents the relative weight of each component.

import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import multivariate_normal

def plot_gaussian(mean, cov, color):
    x, y = np.mgrid[-5:15:.01, -5:15:.01]
    pos = np.dstack((x, y))
    rv = multivariate_normal(mean, cov)
    plt.contour(x, y, rv.pdf(pos), colors=color, alpha=0.6)

# Define GMM parameters
means = [np.array([0, 0]), np.array([7, 7])]
covs = [np.array([[2, 0], [0, 2]]), np.array([[1.5, 1], [1, 1.5]])]
weights = [0.4, 0.6]

# Plot individual components and mixture
plt.figure(figsize=(10, 8))
plot_gaussian(means[0], covs[0], 'b')
plot_gaussian(means[1], covs[1], 'r')

x, y = np.mgrid[-5:15:.01, -5:15:.01]
pos = np.dstack((x, y))
z = sum(w * multivariate_normal(m, c).pdf(pos) for w, m, c in zip(weights, means, covs))
plt.contourf(x, y, z, alpha=0.3)

plt.title('Components of a Gaussian Mixture Model')
plt.xlabel('X')
plt.ylabel('Y')
plt.show()

Expectation-Maximization Algorithm

The Expectation-Maximization (EM) algorithm is used to estimate the parameters of a Gaussian Mixture Model. It iteratively refines the model parameters to maximize the likelihood of the observed data. The algorithm alternates between two steps: the Expectation step (E-step) and the Maximization step (M-step).

import numpy as np
from scipy.stats import multivariate_normal

def em_gmm(X, k, max_iters=100, tol=1e-6):
    n, d = X.shape
    
    # Initialize parameters
    means = X[np.random.choice(n, k, replace=False)]
    covs = [np.eye(d) for _ in range(k)]
    weights = np.ones(k) / k
    
    for _ in range(max_iters):
        # E-step
        resp = np.zeros((n, k))
        for j in range(k):
            resp[:, j] = weights[j] * multivariate_normal(means[j], covs[j]).pdf(X)
        resp /= resp.sum(axis=1, keepdims=True)
        
        # M-step
        N = resp.sum(axis=0)
        means_new = np.dot(resp.T, X) / N[:, np.newaxis]
        
        covs_new = []
        for j in range(k):
            diff = X - means_new[j]
            covs_new.append(np.dot(resp[:, j] * diff.T, diff) / N[j])
        
        weights_new = N / n
        
        # Check convergence
        if np.allclose(means, means_new, atol=tol) and np.allclose(weights, weights_new, atol=tol):
            break
        
        means, covs, weights = means_new, covs_new, weights_new
    
    return means, covs, weights

# Example usage
X = np.random.randn(1000, 2) * 0.5
X[:500] += np.array([2, 2])
means, covs, weights = em_gmm(X, k=2)
print("Estimated means:", means)
print("Estimated weights:", weights)

Choosing the Number of Components

Determining the optimal number of components in a Gaussian Mixture Model is crucial for accurate modeling. One common approach is to use the Bayesian Information Criterion (BIC) or Akaike Information Criterion (AIC). These criteria balance the model's likelihood with its complexity to prevent overfitting.

import numpy as np
from sklearn.mixture import GaussianMixture
import matplotlib.pyplot as plt

# Generate sample data
np.random.seed(42)
X = np.concatenate([
    np.random.normal(0, 1, 300),
    np.random.normal(5, 1.5, 700)
]).reshape(-1, 1)

# Compute BIC for different numbers of components
n_components_range = range(1, 10)
bic = []
for n_components in n_components_range:
    gmm = GaussianMixture(n_components=n_components)
    gmm.fit(X)
    bic.append(gmm.bic(X))

# Plot BIC scores
plt.plot(n_components_range, bic, marker='o')
plt.xlabel('Number of components')
plt.ylabel('BIC')
plt.title('BIC Score vs. Number of GMM Components')
plt.show()

# Find the optimal number of components
optimal_components = n_components_range[np.argmin(bic)]
print(f"Optimal number of components: {optimal_components}")

Gaussian Mixture Models for Clustering

GMMs can be used for soft clustering, where each data point has a probability of belonging to each cluster. This probabilistic approach allows for more nuanced cluster assignments compared to hard clustering methods like K-means.

import numpy as np
import matplotlib.pyplot as plt
from sklearn.mixture import GaussianMixture

# Generate sample data
np.random.seed(42)
X = np.concatenate([
    np.random.multivariate_normal([0, 0], [[1, 0], [0, 1]], 200),
    np.random.multivariate_normal([4, 4], [[1.5, 0], [0, 1.5]], 300)
])

# Fit GMM
gmm = GaussianMixture(n_components=2, random_state=42)
gmm.fit(X)

# Predict cluster probabilities
probs = gmm.predict_proba(X)

# Plot results
plt.figure(figsize=(10, 8))
plt.scatter(X[:, 0], X[:, 1], c=probs[:, 0], cmap='viridis')
plt.colorbar(label='Probability of belonging to cluster 1')
plt.title('GMM Soft Clustering')
plt.xlabel('X')
plt.ylabel('Y')
plt.show()

print("Cluster means:", gmm.means_)
print("Cluster covariances:", gmm.covariances_)

Gaussian Mixture Models for Anomaly Detection

GMMs can be used for anomaly detection by identifying data points with low likelihood under the estimated model. This approach is particularly useful when the normal data follows a complex, multi-modal distribution.

import numpy as np
import matplotlib.pyplot as plt
from sklearn.mixture import GaussianMixture

# Generate normal and anomalous data
np.random.seed(42)
normal_data = np.concatenate([
    np.random.multivariate_normal([0, 0], [[1, 0], [0, 1]], 400),
    np.random.multivariate_normal([4, 4], [[1.5, 0], [0, 1.5]], 600)
])
anomalies = np.random.uniform(low=-2, high=6, size=(50, 2))
X = np.vstack([normal_data, anomalies])

# Fit GMM
gmm = GaussianMixture(n_components=2, random_state=42)
gmm.fit(normal_data)

# Compute log-likelihood scores
scores = gmm.score_samples(X)

# Set threshold for anomaly detection
threshold = np.percentile(scores, 1)

# Plot results
plt.figure(figsize=(10, 8))
plt.scatter(X[:, 0], X[:, 1], c=scores, cmap='viridis')
plt.colorbar(label='Log-likelihood')
plt.title('GMM Anomaly Detection')
plt.xlabel('X')
plt.ylabel('Y')

# Highlight anomalies
anomalies = X[scores < threshold]
plt.scatter(anomalies[:, 0], anomalies[:, 1], color='red', s=50, marker='x', label='Anomalies')
plt.legend()
plt.show()

print(f"Number of detected anomalies: {len(anomalies)}")

Gaussian Mixture Models for Density Estimation

GMMs excel at estimating probability density functions of complex, multi-modal distributions. This makes them useful for generating new samples or computing probabilities of unseen data points.

import numpy as np
import matplotlib.pyplot as plt
from sklearn.mixture import GaussianMixture

# Generate sample data
np.random.seed(42)
X = np.concatenate([
    np.random.normal(-2, 1, 300),
    np.random.normal(2, 1.5, 700)
]).reshape(-1, 1)

# Fit GMM
gmm = GaussianMixture(n_components=2, random_state=42)
gmm.fit(X)

# Generate points for plotting
x = np.linspace(-8, 8, 1000).reshape(-1, 1)
y = np.exp(gmm.score_samples(x))

# Plot results
plt.figure(figsize=(10, 6))
plt.hist(X, bins=50, density=True, alpha=0.5, label='Data')
plt.plot(x, y, 'r-', label='GMM Density Estimation')
plt.title('Gaussian Mixture Model Density Estimation')
plt.xlabel('Value')
plt.ylabel('Density')
plt.legend()
plt.show()

# Generate new samples
new_samples = gmm.sample(1000)[0]
plt.figure(figsize=(10, 6))
plt.hist(new_samples, bins=50, density=True, alpha=0.5, label='Generated Samples')
plt.plot(x, y, 'r-', label='GMM Density Estimation')
plt.title('GMM Generated Samples')
plt.xlabel('Value')
plt.ylabel('Density')
plt.legend()
plt.show()

Gaussian Mixture Models for Image Segmentation

GMMs can be applied to image segmentation tasks by modeling pixel intensities or color distributions. This approach is particularly useful for separating different regions or objects in an image based on their color characteristics.

import numpy as np
import matplotlib.pyplot as plt
from sklearn.mixture import GaussianMixture
from skimage import io, color

# Load and preprocess image
image = io.imread('https://upload.wikimedia.org/wikipedia/commons/8/8c/Andromeda_Galaxy_560mm_FL.jpg')
image_rgb = color.rgba2rgb(image)
image_lab = color.rgb2lab(image_rgb)

# Reshape image for GMM
pixels = image_lab.reshape(-1, 3)

# Fit GMM
n_components = 5
gmm = GaussianMixture(n_components=n_components, random_state=42)
gmm.fit(pixels)

# Predict segments
segments = gmm.predict(pixels)
segmented_image = segments.reshape(image_rgb.shape[:2])

# Plot results
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(15, 7))
ax1.imshow(image_rgb)
ax1.set_title('Original Image')
ax1.axis('off')

ax2.imshow(segmented_image, cmap='viridis')
ax2.set_title('Segmented Image')
ax2.axis('off')

plt.tight_layout()
plt.show()

print(f"Number of segments: {n_components}")

Gaussian Mixture Models for Speech Recognition

In speech recognition, GMMs are often used to model the distribution of acoustic features for different phonemes or words. This allows for probabilistic classification of speech sounds based on their acoustic properties.

import numpy as np
import matplotlib.pyplot as plt
from sklearn.mixture import GaussianMixture
from scipy.io import wavfile
from scipy.signal import spectrogram

# Load audio file (replace with your own audio file)
sample_rate, audio = wavfile.read('speech_sample.wav')

# Compute spectrogram
f, t, Sxx = spectrogram(audio, fs=sample_rate, nperseg=256, noverlap=128)

# Reshape spectrogram for GMM
X = Sxx.T.reshape(-1, 1)

# Fit GMM
n_components = 3
gmm = GaussianMixture(n_components=n_components, random_state=42)
gmm.fit(X)

# Predict segments
segments = gmm.predict(X)
segmented_spectrogram = segments.reshape(Sxx.T.shape)

# Plot results
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(12, 10))

ax1.pcolormesh(t, f, Sxx, shading='gouraud')
ax1.set_title('Original Spectrogram')
ax1.set_ylabel('Frequency [Hz]')

ax2.pcolormesh(t, f, segmented_spectrogram.T, shading='gouraud', cmap='viridis')
ax2.set_title('GMM Segmented Spectrogram')
ax2.set_xlabel('Time [sec]')
ax2.set_ylabel('Frequency [Hz]')

plt.tight_layout()
plt.show()

print(f"Number of acoustic segments: {n_components}")

Gaussian Mixture Models for Handwriting Recognition

GMMs can be used in handwriting recognition systems to model the distribution of features extracted from handwritten characters. This approach allows for probabilistic classification of characters based on their shape and style characteristics.

import numpy as np
import matplotlib.pyplot as plt
from sklearn.mixture import GaussianMixture
from sklearn.datasets import load_digits

# Load digit dataset
digits = load_digits()
X = digits.data
y = digits.target

# Fit GMM for each digit
n_components = 3
gmms = []
for digit in range(10):
    X_digit = X[y == digit]
    gmm = GaussianMixture(n_components=n_components, random_state=42)
    gmm.fit(X_digit)
    gmms.append(gmm)

# Function to classify a digit
def classify_digit(image, gmms):
    scores = [gmm.score(image.reshape(1, -1)) for gmm in gmms]
    return np.argmax(scores)

# Test classification
test_index = np.random.randint(len(X))
test_image = X[test_index]
true_label = y[test_index]
predicted_label = classify_digit(test_image, gmms)

# Visualize results
plt.figure(figsize=(8, 4))
plt.subplot(121)
plt.imshow(test_image.reshape(8, 8), cmap='gray')
plt.title(f"True: {true_label}")
plt.subplot(122)
plt.imshow(test_image.reshape(8, 8), cmap='gray')
plt.title(f"Predicted: {predicted_label}")
plt.show()

Gaussian Mixture Models for Data Generation

GMMs can be used to generate synthetic data that follows the distribution of the original dataset. This is useful for data augmentation, simulation, and testing machine learning models with larger datasets.

import numpy as np
import matplotlib.pyplot as plt
from sklearn.mixture import GaussianMixture

# Generate original data
np.random.seed(42)
original_data = np.concatenate([
    np.random.normal(0, 1, (500, 2)),
    np.random.normal(3, 0.5, (500, 2))
])

# Fit GMM to original data
gmm = GaussianMixture(n_components=2, random_state=42)
gmm.fit(original_data)

# Generate synthetic data
synthetic_data, _ = gmm.sample(1000)

# Visualize results
plt.figure(figsize=(12, 5))
plt.subplot(121)
plt.scatter(original_data[:, 0], original_data[:, 1], alpha=0.5)
plt.title("Original Data")
plt.subplot(122)
plt.scatter(synthetic_data[:, 0], synthetic_data[:, 1], alpha=0.5)
plt.title("Synthetic Data")
plt.tight_layout()
plt.show()

Gaussian Mixture Models for Outlier Detection

GMMs can be used to identify outliers in datasets by computing the likelihood of each data point under the fitted model. Points with very low likelihood are considered potential outliers.

import numpy as np
import matplotlib.pyplot as plt
from sklearn.mixture import GaussianMixture

# Generate data with outliers
np.random.seed(42)
normal_data = np.random.normal(0, 1, (1000, 2))
outliers = np.random.uniform(-5, 5, (50, 2))
data = np.vstack([normal_data, outliers])

# Fit GMM
gmm = GaussianMixture(n_components=1, random_state=42)
gmm.fit(data)

# Compute log-likelihoods
log_likelihoods = gmm.score_samples(data)

# Identify outliers
threshold = np.percentile(log_likelihoods, 1)
outlier_mask = log_likelihoods < threshold

# Visualize results
plt.figure(figsize=(10, 8))
plt.scatter(data[~outlier_mask, 0], data[~outlier_mask, 1], label="Normal")
plt.scatter(data[outlier_mask, 0], data[outlier_mask, 1], color='red', label="Outliers")
plt.title("GMM Outlier Detection")
plt.legend()
plt.show()

Gaussian Mixture Models for Dimensionality Reduction

GMMs can be used for probabilistic dimensionality reduction, similar to probabilistic PCA. This allows for modeling complex, multi-modal distributions in lower-dimensional spaces while preserving uncertainty information.

import numpy as np
import matplotlib.pyplot as plt
from sklearn.mixture import GaussianMixture
from sklearn.datasets import make_moons

# Generate 2D data
X, _ = make_moons(n_samples=1000, noise=0.1, random_state=42)

# Fit GMM for dimensionality reduction
n_components = 5
gmm = GaussianMixture(n_components=n_components, covariance_type='tied', random_state=42)
gmm.fit(X)

# Transform data to 1D
X_transformed = gmm.predict_proba(X)

# Visualize results
plt.figure(figsize=(12, 5))
plt.subplot(121)
plt.scatter(X[:, 0], X[:, 1], alpha=0.5)
plt.title("Original 2D Data")
plt.subplot(122)
plt.scatter(X_transformed[:, 0], X_transformed[:, 1], alpha=0.5)
plt.title("GMM Reduced 2D Data")
plt.tight_layout()
plt.show()

Gaussian Mixture Models for Time Series Analysis

GMMs can be applied to time series data for tasks such as regime detection, anomaly detection, and forecasting. By modeling the distribution of time series features, GMMs can capture complex temporal patterns and dependencies.

import numpy as np
import matplotlib.pyplot as plt
from sklearn.mixture import GaussianMixture

# Generate synthetic time series with regime changes
np.random.seed(42)
n_samples = 1000
t = np.linspace(0, 10, n_samples)
regime1 = np.sin(2 * np.pi * t) + np.random.normal(0, 0.1, n_samples)
regime2 = 2 * np.cos(2 * np.pi * t) + np.random.normal(0, 0.1, n_samples)
time_series = np.where(t < 5, regime1, regime2)

# Prepare data for GMM
X = np.column_stack([time_series[:-1], time_series[1:]])

# Fit GMM
gmm = GaussianMixture(n_components=2, random_state=42)
gmm.fit(X)

# Predict regimes
regimes = gmm.predict(X)

# Visualize results
plt.figure(figsize=(12, 6))
plt.plot(t, time_series, alpha=0.7)
plt.scatter(t[1:], time_series[1:], c=regimes, cmap='viridis', alpha=0.5)
plt.title("Time Series with GMM-detected Regimes")
plt.xlabel("Time")
plt.ylabel("Value")
plt.colorbar(label="Regime")
plt.show()

Additional Resources

For those interested in diving deeper into Gaussian Mixture Models and their applications, here are some valuable resources:

  1. Reynolds, D. A. (2009). Gaussian Mixture Models. Encyclopedia of Biometrics, 659-663. ArXiv: https://arxiv.org/abs/1504.05916
  2. Bishop, C. M. (2006). Pattern Recognition and Machine Learning. Springer. (Chapter 9: Mixture Models and EM)
  3. Rasmussen, C. E. (2000). The Infinite Gaussian Mixture Model. Advances in Neural Information Processing Systems, 12. ArXiv: https://arxiv.org/abs/1710.03855
  4. Zivkovic, Z. (2004). Improved Adaptive Gaussian Mixture Model for Background Subtraction. Proceedings of the 17th International Conference on Pattern Recognition. ArXiv: https://arxiv.org/abs/1708.02973

These resources provide in-depth explanations of GMM theory, algorithms, and applications in various domains. They cover advanced topics such as infinite mixture models and adaptive GMMs for specific use cases.

More in Probability and distributions

  1. Limitations of Normal Distribution in Nature7 min

    The normal distribution, while widely used, is not always the best model for real-world phenomena. Many natural processes are asymmetric or involve...

  2. Exploring Conditional Probability with Python12 min

    Conditional probability is a fundamental concept in statistics that allows us to calculate the likelihood of an event occurring given that another event has...

  3. Master Probability Distributions with Python7 min

    Probability distributions are mathematical functions that describe the likelihood of different outcomes in a random event. They are fundamental to statistics...

  4. Explaining Normal Distribution in Data Science10 min

    The Normal Distribution, also known as the Gaussian distribution, is a symmetrical, bell-shaped curve that represents the probability distribution of many...

  5. Non-Normality Tests Using Python8 min

    Non-normality tests are statistical tools used to assess whether a given dataset deviates from a normal distribution. It's crucial to understand that these...

  6. Essentials of Probability and Statistics5 min

    Probability is the branch of mathematics that deals with the likelihood of events occurring. It forms the foundation for statistical analysis and...