In this example, we will compare the Tyler covariance estimator with the standard sample covariance estimator in the presence of outliers and fat tails. This example demonstrates that the Tyler estimator is robust to outliers, while the standard sample covariance can be heavily influenced by them.
# Copyright (c) 2025 Mohammadjavad Vakili
import matplotlib.pyplot as plt
import numpy as np
from doc_utils import generate_2d_data_with_outliers, generate_2d_student_t_data, plot_2d_data, plot_covariance_contour
from heavytail.tyler import tyler_covariance
true_cov = np.array([[1, 0.5], [0.5, 1]])
data = generate_2d_data_with_outliers(cov=true_cov, n_outliers=50, n_samples=1000)
mean = np.mean(data, axis=0)
fig, ax = plt.subplots(figsize=(8, 8))
plot_2d_data(data, ax=ax)
tyler_cov = tyler_covariance(data)
sample_cov = np.cov(data, rowvar=False)
plot_covariance_contour(mean=mean, cov=true_cov, ax=ax, n_std=2., color='k', alpha=1, label='True Covariance')
plot_covariance_contour(mean=mean, cov=tyler_cov, ax=ax, n_std=2., color='C1', alpha=1, label='Tyler Covariance')
plot_covariance_contour(mean=mean, cov=sample_cov, ax=ax, n_std=2., color='C3', alpha=1, label='Sample Covariance')
plt.legend(frameon=False)
plt.title("Tyler Covariance Contour")
/home/runner/work/heavy-tail/heavy-tail/docs/doc_utils.py:115: UserWarning: Setting the 'color' property will override the edgecolor or facecolor properties. ellip = Ellipse(xy=mean, width=width, height=height, angle=theta, edgecolor="red", fc="None", lw=2, **kwargs)
Text(0.5, 1.0, 'Tyler Covariance Contour')
true_cov = np.array([[1, 0.5], [0.5, 1]])
nu = 4 # Degrees of freedom for the Student's t-distribution
data = generate_2d_student_t_data(nu=4, cov=true_cov, n_samples=1000)
mean = np.mean(data, axis=0)
fig, ax = plt.subplots(figsize=(8, 8))
plot_2d_data(data, ax=ax)
tyler_cov = tyler_covariance(data)
sample_cov = np.cov(data, rowvar=False)
plot_covariance_contour(mean=mean, cov=true_cov, ax=ax, n_std=2., color='k', alpha=1, label='True Covariance')
plot_covariance_contour(mean=mean, cov=tyler_cov, ax=ax, n_std=2., color='C1', alpha=1, label='Tyler Covariance')
plot_covariance_contour(mean=mean, cov=sample_cov, ax=ax, n_std=2., color='C3', alpha=1, label='Sample Covariance')
plt.legend(frameon=False)
<matplotlib.legend.Legend at 0x7f5aef705050>