Tyler Covariance Estimator¶

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.

In [1]:
# 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

Comparison between Tyler and Standard Sample Covariance Estimators in the presence of Outliers¶

In [2]:
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)
Out[2]:
Text(0.5, 1.0, 'Tyler Covariance Contour')

Comparison between Tyler and Standard Sample Covariance Estimators with fat-tailed distribution¶

In [3]:
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)
Out[3]:
<matplotlib.legend.Legend at 0x7f5aef705050>