Source code for doatools.estimation.source_number
import numpy as np
from math import log
[docs]def ld_stat(l, n_sources, n_snapshots):
"""Computes the sufficient statistic for source number detection in MDL/AIC.
Args:
l (~numpy.ndarray): A 1D vector of the eigenvalues of the covariance
matrix in ascending order.
n_sources (int): Number of sources.
n_snapshots (int): Number of snapshots.
References:
[1] H. L. Van Trees, Optimum array processing. New York: Wiley, 2002.
"""
if l.ndim != 1:
raise ValueError('A 1D numpy vector expected.')
n_sensors = l.size
diff = n_sensors - n_sources
l = l[:diff]
return n_snapshots * diff * log(np.sum(l) / diff / (np.prod(l)**(1./diff)))
[docs]def aic(x, n_snapshots):
"""Detects source numbers using AIC.
Args:
x (~numpy.ndarray): A 1D vector of the eigenvalues of the covariance
matrix in ascending order, or the covariance matrix itself.
n_snapshots (int): Number of snapshots.
Notes:
AIC is inconsistent, and tends to asymptotically overestimate the
number of sources. However, it tends to give a higher probability of a
correct decision.
References:
[1] H. L. Van Trees, Optimum array processing. New York: Wiley, 2002.
"""
if x.ndim > 1:
x = np.linalg.eigvalsh(x)
n_sensors = x.size
ld = np.zeros((n_sensors, 1))
for i in range(n_sensors):
ld[i] = ld_stat(x, i, n_snapshots) + i * (2 * n_sensors - i)
return np.argmin(ld)
[docs]def mdl(x, n_snapshots):
"""Detects source number using MDL.
Args:
x (~numpy.ndarray): A 1D vector of the eigenvalues of the covariance
matrix in ascending order, or the covariance matrix itself.
n_snapshots (int): Number of snapshots.
Notes:
MDL is consistent.
References:
[1] H. L. Van Trees, Optimum array processing. New York: Wiley, 2002.
"""
if x.ndim > 1:
x = np.linalg.eigvalsh(x)
n_sensors = x.size
ld = np.zeros((n_sensors, 1))
for i in range(n_sensors):
ld[i] = ld_stat(x, i, n_snapshots) + 0.5 * (i * (2 * n_sensors - i) + 1) * log(n_snapshots)
return np.argmin(ld)
[docs]def sorte(x):
r"""Detects source number using SORTE.
Arg:
x: (~numpy.ndarray): A 1D vector of the eigenvalues of the covariance
matrix in ascending order, or the covariance matrix itself.
Refereces:
[1] Z. He, A. Cichocke, S. Xie, and K. Choi, "Detecting the number of
clusters in n-way probabilistic clustering," IEEE Trans. Pattern
Anal. Mach. Intell., vol. 32, pp. 2006-2021, Nov. 2010.
"""
if x.ndim > 1:
x = np.linalg.eigvalsh(x)
# SORTE requires descending order.
x = x[::-1]
n = x.size
if n < 4:
raise ValueError('At least four eigenvalues required.')
diffs = x[:-1] - x[1:]
sigmas = [np.var(diffs[k:]) for k in range(n - 1)]
s = np.zeros((n - 2,))
for k in range(n - 2):
if np.abs(sigmas[k]) < np.finfo(np.float_).eps:
s[k] = np.inf
else:
s[k] = sigmas[k + 1] / sigmas[k]
return np.argmin(s[:-1]) + 1