2016-07-14 4 views
1

Ich benutze die BFGS-Methode, geben Sie die negative Log-Wahrscheinlichkeit von meinem quadrierten exponentiellen/RBF-Kernel, sowie der Gradient (Jacobi) davon. Das Weglassen des Gradienten, funktioniert es erste Differenzen mit feinen - aber diescipy.optimize.minimize Jacobische Funktion verursacht 'Wert Fehler: Der Wahrheitswert eines Arrays mit mehr als einem Element ist mehrdeutig'

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all() 

Fehler kommt einmal bis ich versuche, und die Steigung der NLL zu verwenden. Beachten Sie auch, dass, während mein Quellcode in der Funktion SE_der (Gradient/Jacobi) unten .any() oder .all() im Ergebnis nicht verwendet, habe ich auch beide versucht, nur um genau den gleichen Fehler zu bekommen.

Die vorhergehende Spur ist:

Traceback (most recent call last): 
File "loaddata.py", line 107, in <module> 
gp.fit(X, y) 
File "/home/justinting/programming/bhm/ML/gp.py", line 33, in fit 
res = minimize(self.SE_NLL, gp_hp_guess, method='bfgs', jac=True) 
File "/usr/lib/python3.5/site-packages/scipy/optimize/_minimize.py", line 441, in minimize 
return _minimize_bfgs(fun, x0, args, jac, callback, **options) 
File "/usr/lib/python3.5/site-packages/scipy/optimize/optimize.py", line 865, in _minimize_bfgs 
old_fval, old_old_fval) 
File "/usr/lib/python3.5/site-packages/scipy/optimize/optimize.py", line 706, in _line_search_wolfe12 
old_fval, old_old_fval) 
File "/usr/lib/python3.5/site-packages/scipy/optimize/linesearch.py", line 282, in line_search_wolfe2 
phi, derphi, old_fval, old_old_fval, derphi0, c1, c2, amax) 
File "/usr/lib/python3.5/site-packages/scipy/optimize/linesearch.py", line 379, in scalar_search_wolfe2 
if (phi_a1 > phi0 + c1 * alpha1 * derphi0) or \ 

Der entsprechende Code ist wie folgt:

gp_hp_guess = [1.0] * 3 # initial guess 
res = minimize(self.SE_NLL, gp_hp_guess, method='bfgs', jac=self.SE_der) 

# other stuff 

def SE_der(self, args): 

    [f_err, l_scale, n_err] = args 
    L = self.L_create(f_err, l_scale, n_err) 
    alpha = linalg.solve(L.T, (linalg.solve(L, self.y))) # save for use with derivative func 
    aaT = alpha.dot(alpha.T) 
    K_inv = np.linalg.inv(L.T).dot(np.linalg.inv(L)) 
    # self.K_inv = np.linalg.inv(self.L.T).dot(np.linalg.inv(self.L)) 
    dK_dtheta = np.gradient(self.K_se(self.X, self.X, f_err, l_scale))[0] 
    der = 0.5 * np.matrix.trace((aaT - K_inv).dot(dK_dtheta)) 
    return -der 

def SE_NLL(self, args): 

    [f_err, l_scale, n_err] = args 
    L = self.L_create(f_err, l_scale, n_err) 

    alpha = linalg.solve(L.T, (linalg.solve(L, self.y))) # save for use with derivative func 
    nll = (
     0.5 * self.y.T.dot(alpha) + 
     np.matrix.trace(L) + # sum of diagonal 
     L.shape[0]/2 * math.log(2*math.pi) 
      ) 
    return nll 

Ich habe den Quellcode der Helferfunktionen ausgelassen wie die NLL funktioniert gut, wenn der Gradient Funktion wird nicht verwendet und sie teilen die gleichen Hilfsfunktionen.

Beim Aufruf der SE_der-Funktion übergeben direkt die optimierten Parameter nach der Tatsache (und nicht tatsächlich mit dem Gradienten in der Optimierung), gibt es eine einzelne Zahl wie erwartet (oder zumindest denke ich, dass das ist, was erwartet wird), so Ich kann das Problem nicht erkennen.

Ist dieser Fehler ein Missverständnis meinerseits was Scipy in seiner Jacobi-Funktion oder etwas anderes erwartet? Ich habe versucht, durch den Python-Quellcode zu graben, aber der eigentliche Funktionsaufruf, der sich mit den Funktionen beschäftigt, ist hinter Funktionen verborgen, die nicht im Python-Code auf Github zu sein scheinen - ich bin mir nicht sicher, ob sie sich in privaten/C++ - Repos befinden irgendwo anders.

+1

Warum denken Sie, dass SE_der eine einzelne Zahl zurückgeben sollte? Der Gradient ist ein Vektor mit so vielen Komponenten, wie es Variablen gibt (von denen ich drei sehe: f_err, l_scale, n_err.) –

+0

Danke @Bookend. Ich würde dies als die akzeptierte Antwort markieren, wenn es ein Post wäre, wie es für mich bestätigt hat, dass ich die Ableitung der logarithmischen Wahrscheinlichkeit in Rasmussens und Williams Buch falsch interpretiere, die die Ableitung als einen einzelnen Wert hat (daher die matrix.trace) . – mediantis

Antwort

1

Schauen Sie sich die Seitenleiste an. Sehen Sie alle diese SO Fragen über das gleiche ValueError?

Während die Umstände variieren, ist dies in fast jedem Fall das Ergebnis der Verwendung eines booleschen Arrays in einem Python-Kontext, das einen skalaren booleschen Wert erwartet.

Ein einfaches Beispiel ist

In [236]: if np.arange(10)>5:print('yes') 
--------------------------------------------------------------------------- 
ValueError        Traceback (most recent call last) 
<ipython-input-236-633002262b65> in <module>() 
----> 1 if np.arange(10)>5:print('yes') 

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all() 

np.arange(10)>5 einen booleschen Array erzeugt, np.array([False, False, ...]).

Die Kombination boolescher Ausdrücke kann dies auch erzeugen. np.arange(10)>5 | np.arange(10)<2 produziert dies, (np.arange(10)>5) | (np.arange(10)<2) nicht - wegen der Präsidentschaft der logischen Operatoren. Die Verwendung von and anstelle von | ist in diesem Zusammenhang hoffnungslos.

Ich sehe mir Ihren Code genauer an, aber vielleicht hilft Ihnen das in der Zwischenzeit, das Problem selbst zu finden.

==================

aus dem Fehlerstapel:

if (phi_a1 > phi0 + c1 * alpha1 * derphi0) or \ 

der Code an dieser Stelle (phi_a1 > phi0 + c1 * alpha1 * derphi0) erwartet (und was auch immer die folgen or) ein Skalar zu sein. Vermutlich ist eine dieser Variablen ein Array mit mehreren Werten. Zugegeben, dies geschieht weit unten im aufrufenden Stack, so dass es schwierig wird, diese Werte zurück zu Ihrem Code zu verfolgen.

Drucke, die sich auf den variablen Typ und die Form konzentrieren, könnten am nützlichsten sein. Manchmal läuft der Code bei diesen iterativen Solvern für eine Schleife gut, und dann ändert sich eine Variable in ein Array, und sie erstickt bei der nächsten Schleife.

==================

Warum verwenden Sie np.matrix.trace? In meinen Tests produziert das 2d Einzelelement np.matrix. Es ist nicht offensichtlich, dass es diesen ValueError erzeugen würde, aber es ist immer noch verdächtig.

+0

Es ist in der Tat die falsche Form, die das Problem verursacht, also werde ich dies als einzige Antwort hier akzeptieren. Ich habe in der von mir implementierten Gleichung etwas falsch interpretiert, das die Ableitung über die Zielfunktion als Einzelwert hat, also muss ich das noch einmal untersuchen. – mediantis

Verwandte Themen