Ich lerne das neuronale Netzwerk und möchte eine Funktion cross_entropy
in Python schreiben. Wo ist es definiert als
dabei ist N
die Anzahl der Samples, k
ist die Anzahl der Klassen, log
ist der natürliche Logarithmus, t_i,j
ist 1, wenn die Probe i
in der Klasse j
und sonst 0
ist, und p_i,j
die vorhergesagte Wahrscheinlichkeit, in der i
ist Klasse j
. Um numerische Probleme mit dem Logarithmus zu vermeiden, schneiden Sie die Vorhersagen in den [10^{−12}, 1 − 10^{−12}]
-Bereich.
Gemäß der obigen Beschreibung habe ich die Codes aufgeschrieben, indem ich die Vorhersagen auf [epsilon, 1 − epsilon]
range klippte und dann den cross_entropy anhand der obigen Formel berechnete.
def cross_entropy(predictions, targets, epsilon=1e-12):
"""
Computes cross entropy between targets (encoded as one-hot vectors)
and predictions.
Input: predictions (N, k) ndarray
targets (N, k) ndarray
Returns: scalar
"""
predictions = np.clip(predictions, epsilon, 1. - epsilon)
ce = - np.mean(np.log(predictions) * targets)
return ce
Der folgende Code wird verwendet, um zu überprüfen, ob die Funktion cross_entropy
korrekt ist.
predictions = np.array([[0.25,0.25,0.25,0.25],
[0.01,0.01,0.01,0.96]])
targets = np.array([[0,0,0,1],
[0,0,0,1]])
ans = 0.71355817782 #Correct answer
x = cross_entropy(predictions, targets)
print(np.isclose(x,ans))
Die Ausgabe der obigen Codes ist False, dh meine Codes zum Definieren der Funktion cross_entropy
sind nicht korrekt. Dann drucke ich das Ergebnis von cross_entropy(predictions, targets)
aus. Es gab 0.178389544455
und das korrekte Ergebnis sollte ans = 0.71355817782
sein. Kann mir jemand helfen zu überprüfen, was das Problem mit meinen Codes ist?
Sie sind gar nicht so weit weg, aber denken Sie daran, dass Sie den Durchschnittswert von N Summen verwenden, wobei N = 2 (in diesem Fall). So könnte Ihr Code lesen:
def cross_entropy(predictions, targets, epsilon=1e-12):
"""
Computes cross entropy between targets (encoded as one-hot vectors)
and predictions.
Input: predictions (N, k) ndarray
targets (N, k) ndarray
Returns: scalar
"""
predictions = np.clip(predictions, epsilon, 1. - epsilon)
N = predictions.shape[0]
ce = -np.sum(targets*np.log(predictions+1e-9))/N
return ce
predictions = np.array([[0.25,0.25,0.25,0.25],
[0.01,0.01,0.01,0.96]])
targets = np.array([[0,0,0,1],
[0,0,0,1]])
ans = 0.71355817782 #Correct answer
x = cross_entropy(predictions, targets)
print(np.isclose(x,ans))
Ich denke, es ist ein bisschen klarer, wenn Sie bei np.sum()
bleiben. Außerdem habe ich 1e-9 in die np.log()
eingefügt, um die Möglichkeit zu vermeiden, dass in Ihrer Berechnung ein Log (0) angezeigt wird. Hoffe das hilft!
HINWEIS: Gemäß dem Kommentar von @ Peter ist der Versatz von 1e-9
in der Tat überflüssig, wenn Ihr Epsilon-Wert größer als 0
ist.
def cross_entropy(x, y):
""" Computes cross entropy between two distributions.
Input: x: iterabale of N non-negative values
y: iterabale of N non-negative values
Returns: scalar
"""
if np.any(x < 0) or np.any(y < 0):
raise ValueError('Negative values exist.')
# Force to proper probability mass function.
x = np.array(x, dtype=np.float)
y = np.array(y, dtype=np.float)
x /= np.sum(x)
y /= np.sum(y)
# Ignore zero 'y' elements.
mask = y > 0
x = x[mask]
y = y[mask]
ce = -np.sum(x * np.log(y))
return ce
def cross_entropy_via_scipy(x, y):
''' SEE: https://en.wikipedia.org/wiki/Cross_entropy'''
return entropy(x) + entropy(x, y)
from scipy.stats import entropy, truncnorm
x = truncnorm.rvs(0.1, 2, size=100)
y = truncnorm.rvs(0.1, 2, size=100)
print np.isclose(cross_entropy(x, y), cross_entropy_via_scipy(x, y))