[Numpy] Évitez d'avertir de 0 division

J'étais désemparé lors de l'écriture du programme moi-même, donc je vais l'écrire sous forme de mémo. Si vous connaissez une meilleure solution, veuillez la signaler.

※environnement

0 division de numpy

J'obtiens un ZeroDivisionError lorsque je fais une division 0 normale en Python.

python


try:
    divided = 1 / 0
except ZeroDivisionError as e:
    print(f'ZeroDivisionError: {e}')

# -> ZeroDivisionError: division by zero

D'un autre côté, si vous divisez par 0 avec numpy, RuntimeWarning se produira, mais le résultat sera affiché sans arrêter le traitement.

python


import numpy as np

divided = 1 / np.array(0)
print(devided)
# -> inf
# -> RuntimeWarning: divide by zero encountered in true_divide

Le résultat du calcul de "1 / np.array (0)" est l'objet "numpy.inf" qui représente l'infini avec numpy. Cela donne un avertissement, mais cela n'arrête pas le processus, donc cela semble à mi-chemin. Il appartient peut-être à l'utilisateur de dire: "Je peux le calculer, mais je vais vous donner un avertissement. Je vous laisse le soin". Alors, réfléchissons à ce qu'il faut faire lorsque vous souhaitez arrêter le processus et lorsque vous autorisez le processus et ignorez l'avertissement.

Utilisez warnings.simplefilter

Vous pouvez utiliser warnings.simplefilter pour faire de RuntimeWarning une exception ou l'ignorer.

python


import warnings
import numpy as np
warnings.simplefilter('error', category=RuntimeWarning)  #Définir l'avertissement d'exécution comme exception

a = np.array(0)  #Variables qui ne devraient pas contenir 0
divided = 1 / a
print(divided)

# -> RuntimeWarning: divide by zero encountered in true_divide
# divided = 1 /Le traitement s'arrête à a et imprimer(divided)N'est pas exécuté

python


import warnings
import numpy as np
warnings.simplefilter('ignore', category=RuntimeWarning)  #Définir l'avertissement d'exécution pour ignorer

a = np.array(0)  #Variables pouvant contenir 0
divided = 1 / a
print(divided)

# -> inf
#Aucun avertissement n'est émis et le traitement se poursuit

Cependant, à ce moment, le contrôle est appliqué à RuntimeWarning autre que la division 0, il y a donc un risque que le bogue ne puisse pas être capturé, surtout s'il est ignoré. Alors je pense à une autre méthode

Utilisez numpy.seteer

(En réponse au commentaire, j'ai ajouté numpy.seteer.) Vous pouvez utiliser numpy.seteer pour définir un contrôle plus fin de Avertissement.

python


import numpy as np
np.seterr(divide='ignore')  #Ignorer uniquement l'avertissement d'exécution de la division 0

a = np.array(0)
divided = 1 / a
print(divided)

# -> inf

Vous pouvez maintenant ajouter un contrôle uniquement à la division 0. La complexité de "l'importation" des avertissements "a également été éliminée. Cependant, dans ce cas, ce contrôle s'applique à tout le code source. Si possible, je veux minimiser l'étendue du contrôle. Vous pouvez changer de contrôle en écrivant numpy.seterr avant et après la division, mais envisagez une description plus intelligente.

Utilisez numpy.errstate

(C'est également la partie ajoutée des commentaires signalés)

En utilisant numpy.errstate, le contrôle par le gestionnaire de contexte est possible.

python


import numpy as np

a = np.array(0) 
with np.errstate(divide='ignore'):  #Appliquer le contrôle uniquement dans la portée
    divided = 1 / a
print(divided)
# -> inf

divided = 1 / a  #L'avertissement d'exécution se produit car il est hors de portée de la négligence
# -> RuntimeWarning: divide by zero encountered in true_divide

Cela réduira la portée des changements de contrôle et complètera les bogues causés par des divisions (non autorisées) ailleurs.

Dans l'exemple, nous avons considéré la division des nombres dans un souci de clarté, mais vous pouvez également contrôler la division du tableau.

python


import numpy as np

a = np.array([1, 2, 0]) 
with np.errstate(divide='ignore'):  #Appliquer le contrôle uniquement dans la portée
    divided = 1 / a
print(divided)
# -> [1.  0.5 inf]

Si vous voulez diviser un nombre, vous pouvez simplement écrire une instruction if, mais c'est difficile pour un tableau, donc je pense que cette méthode de contrôle sera utile.

prime

Au début, je ne connaissais pas «numpy.errstate» et j'ai pensé à l'écrire comme suit.

python


import numpy as np

a = np.array([1, 2, 0])
divided = np.full(len(a), np.inf)  #Tous les éléments sont np.Faire un tableau d'inf
nonzero_indices = np.where(a != 0)[0]  #Un tableau d'index avec des éléments non nuls d'un
divided[nonzero_indices] = 1 / a[nonzero_indices]  # nonzero_Réécrire uniquement les éléments du tableau en division

print(divided)
# -> [1.  0.5 inf]

Je voulais éviter l'avertissement de seulement 0 division, mais cela semble redondant. Je veux pouvoir me souvenir et utiliser des méthodes utiles comme numpy.errstate.

Recommended Posts

[Numpy] Évitez d'avertir de 0 division
Évitez l'avertissement [valeur non valide rencontrée dans true_divide] lorsqu'il est divisé par zéro