2016-04-28 10 views
2

Ich verwende Python Scikit-Learn Paket PCA zu implementieren .Ich ist immer MatheMathe Domain-Fehler beim PCA mit

domain error : 
C:\Users\Akshenndra\Anaconda2\lib\site-packages\sklearn\decomposition\pca.pyc in _assess_dimension_(spectrum, rank, n_samples, n_features) 
    78   for j in range(i + 1, len(spectrum)): 
    79    pa += log((spectrum[i] - spectrum[j]) * 
---> 80      (1./spectrum_[j] - 1./spectrum_[i])) + log(n_samples) 
    81 
    82  ll = pu + pl + pv + pp - pa/2. - rank * log(n_samples)/2. 

ValueError: math domain error 

Ich weiß schon, dass Mathematik Domain Fehler verursacht, wenn wir Logarithmus einer negativen Zahl nehmen, aber ich verstehe hier nicht, wie kann es eine negative Zahl innerhalb des Logarithmus geben? weil dieser Code für andere Datensätze gut funktioniert. vielleicht hängt das mit dem zusammen, was auf der Website von sci-kitlearn geschrieben wird - "Diese Implementierung verwendet die scipy.linalg-Implementierung der Singulärwertzerlegung. Sie funktioniert nur für dichte Arrays und ist nicht skalierbar für große dimensionale Daten." große Zahl von 0 Werten)

+0

können Sie eine minimale erstellen Beispiel reproduziert diesen Fehler mit Zufallsdaten? – eickenberg

+0

Ich habe das gleiche Problem - nimmt Protokoll (0) – user48956

Antwort

0

Ich weiß nicht, ob ich richtig bin oder nicht, aber ich finde wirklich einen Weg, es zu lösen.

ich einige Fehlerinformationen nur drucken (Der Wert von spectrum_ [i] und spectrum_ [j]), und ich finde:

manchmal, sie gleich sind !!!

(Vielleicht nicht gleichen sie sind, aber sie sind zu nah, ich denke)

so, hier

pa += log((spectrum[i] - spectrum[j]) * 
        (1./spectrum_[j] - 1./spectrum_[i])) + log(n_samples) 

es meldet Fehler, wenn calculate log (0).

Mein Weg, es zu lösen, ist eine sehr kleine Zahl 1e-99-0, hinzufügen, damit es log werden (0 + 1e-99)

so können Sie ändern, es nur zu:

  pa += log((spectrum[i] - spectrum[j]) * 
        (1./spectrum_[j] - 1./spectrum_[i]) + 1e-99) + log(n_samples) 
1

Ich denke, Sie sollten stattdessen 1 hinzufügen, wie the numpy log1p description page. Da log (p + 1) = 0, wenn p = 0 (während log (e-99) = -99), und als das Zitat in der Verbindung

für reellwertige Eingangs ist log1p auch genaue für x so klein, dass 1 + x == 1 in Gleitkommaoperationen Genauigkeit

Der Code kann wie folgt modifiziert werden, um zu machen, was Sie mehr vernünftig zu lösen versuchen:

for i in range(rank): 
    for j in range(i + 1, len(spectrum)): 
     pa += log((spectrum[i] - spectrum[j]) * 
     (1./spectrum_[j] - 1./spectrum_[i]) + 1) + log(n_samples + 1) 
    ll = pu + pl + pv + pp - pa/2. - rank * log(n_samples + 1)/2