J'ai un grand ensemble de données de nombres à virgule flottante. Je les parcoure et évalue np.log(x)
pour chacun d’eux. Je reçois
RuntimeWarning: divide by zero encountered in log
Je voudrais contourner cela et renvoyer 0 si cette erreur se produit.
Je pense définir une nouvelle fonction:
def safe_ln(x):
#returns: ln(x) but replaces -inf with 0
l = np.log(x)
#if l = -inf:
l = 0
return l
En gros, j'ai besoin d'un moyen de vérifier que la sortie est -inf
mais je ne sais pas comment procéder. Merci de votre aide!
Puisque la log
pour x=0
est moins infinie, je voudrais simplement vérifier si la valeur d'entrée est égale à zéro et renvoyer ce que vous voulez là:
def safe_ln(x):
if x <= 0:
return 0
return math.log(x)
EDIT: small edit: vous devez vérifier toutes les valeurs inférieures ou égales à 0.
EDIT 2 : np.log
est bien sûr une fonction à calculer sur un tableau numpy. Pour les valeurs uniques, vous devez utiliser math.log
. Voici à quoi ressemble la fonction ci-dessus avec numpy:
def safe_ln(x, minval=0.0000000001):
return np.log(x.clip(min=minval))
Vous utilisez une fonction np, je peux donc sans risque supposer que vous travaillez sur un tableau numpy? Le moyen le plus efficace consiste à utiliser la fonction where au lieu d’une boucle for
myarray= np.random.randint(10,size=10)
result = np.where(myarray>0, np.log(myarray), 0)
sinon, vous pouvez simplement utiliser la fonction de journalisation, puis corriger le trou:
myarray= np.random.randint(10,size=10)
result = np.log(myarray)
result[result==-np.inf]=0
La fonction np.log retourne correctement -inf lorsqu'elle est utilisée avec une valeur de 0, alors êtes-vous sûr de vouloir renvoyer un 0? si, quelque part, vous devez revenir à la valeur d'origine, vous allez rencontrer un problème, en changeant des zéros en un ...
Tu peux le faire.
def safe_ln(x):
try:
l = np.log(x)
except ZeroDivisionError:
l = 0
return l
utiliser la gestion des exceptions:
In [27]: def safe_ln(x):
try:
return math.log(x)
except ValueError: # np.log(x) might raise some other error though
return float("-inf")
....:
In [28]: safe_ln(0)
Out[28]: -inf
In [29]: safe_ln(1)
Out[29]: 0.0
In [30]: safe_ln(-100)
Out[30]: -inf
La réponse donnée par Enrico est Nice, mais les deux solutions aboutissent à un avertissement:
RuntimeWarning: divide by zero encountered in log
En guise d'alternative, nous pouvons toujours utiliser la fonction where
mais n'exécuter le calcul principal que s'il est approprié:
# alternative implementation -- a bit more typing but avoids warnings.
loc = np.where(myarray>0)
result2 = np.zeros_like(myarray, dtype=float)
result2[loc] =np.log(myarray[loc])
# answer from Enrico...
myarray= np.random.randint(10,size=10)
result = np.where(myarray>0, np.log(myarray), 0)
# check it is giving right solution:
print(np.allclose(result, result2))
Mon cas d'utilisation était pour la division, mais le principe est clairement le même:
x = np.random.randint(10, size=10)
divisor = np.ones(10,)
divisor[3] = 0 # make one divisor invalid
y = np.zeros_like(divisor, dtype=float)
loc = np.where(divisor>0) # (or !=0 if your data could have -ve values)
y[loc] = x[loc] / divisor[loc]
vous pourriez faire:
def safe_ln(x):
#returns: ln(x) but replaces -inf with 0
try:
l = np.log(x)
except RunTimeWarning:
l = 0
return l