2016-02-08 63 views
5

Mam problem z próbą użycia scipy.stats.multivariate_normal, mam nadzieję, że jedno z was może być w stanie pomóc.scipy.stats.multivariate_normal Podnoszenie `LinAlgError: pojedyncza macierz` mimo że moja macierz kowariancji jest odwracalna

mam macierz 2x2, która jest możliwe, aby znaleźć odwrotność użyciu numpy.linalg.inv(), jednak gdy próbuję użyć go jako macierzy kowariancji w multivariate_normal otrzymam LinAlgError stwierdzając, że jest to liczba pojedyncza matryca:

In [89]: cov = np.array([[3.2e5**2, 3.2e5*0.103*-0.459],[3.2e5*0.103*-0.459, 0.103**2]]) 

In [90]: np.linalg.inv(cov) 
Out[90]: 
array([[ 1.23722158e-11, 1.76430200e-05], 
     [ 1.76430200e-05, 1.19418880e+02]]) 

In [91]: multivariate_normal([0,0], cov) 
--------------------------------------------------------------------------- 
LinAlgError        Traceback (most recent call last) 
<ipython-input-91-44a6625beda5> in <module>() 
----> 1 multivariate_normal([0,0], cov) 

/mnt/ssd/Enthought_jli199/Canopy_64bit/User/lib/python2.7/site-packages/scipy/stats/_multivariate.pyc in __call__(self, mean, cov, allow_singular, seed) 
    421   return multivariate_normal_frozen(mean, cov, 
    422           allow_singular=allow_singular, 
--> 423           seed=seed) 
    424 
    425  def _logpdf(self, x, mean, prec_U, log_det_cov, rank): 

/mnt/ssd/Enthought_jli199/Canopy_64bit/User/lib/python2.7/site-packages/scipy/stats/_multivariate.pyc in __init__(self, mean, cov, allow_singular, seed) 
    591   """ 
    592   self.dim, self.mean, self.cov = _process_parameters(None, mean, cov) 
--> 593   self.cov_info = _PSD(self.cov, allow_singular=allow_singular) 
    594   self._dist = multivariate_normal_gen(seed) 
    595 

/mnt/ssd/Enthought_jli199/Canopy_64bit/User/lib/python2.7/site-packages/scipy/stats/_multivariate.pyc in __init__(self, M, cond, rcond, lower, check_finite, allow_singular) 
    217   d = s[s > eps] 
    218   if len(d) < len(s) and not allow_singular: 
--> 219    raise np.linalg.LinAlgError('singular matrix') 
    220   s_pinv = _pinv_1d(s, eps) 
    221   U = np.multiply(u, np.sqrt(s_pinv)) 

LinAlgError: singular matrix 
+2

Z jakich wersji numpy korzystasz? Z powodzeniem mogę uruchomić kod na numpy 1.10.1. Zauważ, że nawet jeśli macierz jest * technicznie * odwracalna, jest straszliwie źle skalowana. – kazemakase

+0

Witam kazemakase, to jest wersja 1.9.2. – Jonnyishman

Odpowiedz

8

Domyślnie multivariate_normal sprawdza, czy którakolwiek z wartości własnych macierzy kowariancji jest mniejsza niż wybrana tolerancja na podstawie jej typu dnspe i wielkości jej największej wartości własnej (spójrz na kod źródłowy dla scipy.stats._multivariate._PSD i scipy.stats._multivariate._eigvalsh_to_eps w celu uzyskania pełnych informacji).

Jako wspomniany powyżej @kazemakase, podczas gdy macierz kowariancji może być odwracalna zgodnie z kryteriami stosowanymi przez np.linalg.inv, jest nadal bardzo słabo uwarunkowana i nie spełnia bardziej rygorystycznych testów używanych przez multivariate_normal.

Możesz przejść allow_singular=True do multivariate_normal, aby pominąć ten test, ale ogólnie lepiej byłoby przeskalować twoje dane, aby w pierwszej kolejności nie przekazać tak źle skonstruowanej macierzy kowariancji.

+0

Witaj, ali_m, Dzięki za pomoc. Teraz widzę, że sprawdzanie odbywa się, gdy robiłem wewnątrz kodu źródłowego dla multivariate_normal. Zamierzam ujednolicić moje dane, aby uniknąć posiadania tak źle skonstruowanej macierzy kowariancji. – Jonnyishman