6

FloatingPointError: invalid value encountered in subtractテストコードの一部で遭遇しています。コード自体に変更を加えることなく例外が発生し始めたため、理解するのに非常に苦労しています。

私の質問:invalid value encountered in subtract例外の原因は何ですか?python + numpyのインストールが異なると、動作が異なるのはなぜですか?

詳細:

このMWEは:を発生させませFloatingPointError

>>> import numpy as np
>>> np.__version__
 '1.6.1'
>>> x = np.arange(5,dtype='float64')
>>> y = np.ones(5,dtype='float64')
>>> x[2]=np.nan
>>> x-y
# array([ -1.,   0.,  nan,   2.,   3.])

ただし、コードの奥深くで2つのnp.float64 ndarrayオブジェクトを減算すると、浮動小数点の例外が発生します。例外の原因となる配列には、かなり巨大で小さな数値(1e307や1e-307など)といくつかnanのsが含まれていますが、これらの数値を組み合わせて自分で例外テストを行うことはしていません。

さらに厄介なことに、numpy、matplotlib、python、scipyの多くのバージョンでまったく同じコードを実行するJenkinsテストの大きなグリッドがあり、これらのどれもこの例外を発生させません。私はこの時点で迷子になっています-バグがあるかどうか、またはバグがある場合は、それを追跡する方法がわかりません。

病的に興味がある場合は、問題のコードはpyspeckitであり、テストはの20行目で失敗していtest_hr2421.pyます。

編集:フォローアップ-この小さなスニペット:np.seterr(invalid='raise')インポートしていたモジュール、具体的にはpymcで呼び出されていたため、プルリクエストによってこの変更が行われなくなったと思います。

4

1 に答える 1

3

Numpyには、浮動小数点エラーの処理方法に関して構成可能な動作があります。デフォルトでは、アンダーフローエラーは無視されますが、他のエラーは警告をトリガーします。カテゴリごとに、ユーザーはこの動作をで変更できますnumpy.seterr。これらの設定はグローバルです—ここには名前名はありません。したがって、ライブラリが呼び出すと、再度呼び出されるnumpy.seterr(all='raise')までプログラム全体に影響します。numpy.seterr

これが実際に問題の原因であることを確認できます

print(numpy.seterr())

次のような出力が必要です

{'divide': 'warn', 'over': 'warn', 'under': 'ignore', 'invalid': 'warn'}

これらのカテゴリの一部に値raise、特にキーがある'invalid'場合、それは観察している動作を説明します。

numpy.seterr(invalid='warn')、またはを呼び出すことで、この例外を抑制することができますinvalid='ignore'。発生する可能性のあるエラーの完全なリストについては、のドキュメントをお読みくださいnumpy.seterr

コンテキストマネージャーを使用して、動作を一時的に変更することもできます。

In [12]: x = np.arange(-5, 5,dtype='float64')

In [13]: with np.errstate(divide="raise"):
    print(1/x)
   ....:     
---------------------------------------------------------------------------
FloatingPointError                        Traceback (most recent call last)
<ipython-input-13-881589fdcb7a> in <module>()
      1 with np.errstate(divide="raise"):
----> 2     print(1/x)
      3 

FloatingPointError: divide by zero encountered in true_divide

In [14]: with np.errstate(divide="warn"):
    print(1/x)
   ....:     
/home/users/gholl/venv/stable-3.5/bin/ipython3:2: RuntimeWarning: divide by zero encountered in true_divide
  
[-0.2        -0.25       -0.33333333 -0.5        -1.                 inf
  1.          0.5         0.33333333  0.25      ]

In [15]: with np.errstate(divide="ignore"):
    print(1/x)
   ....:     
[-0.2        -0.25       -0.33333333 -0.5        -1.                 inf
  1.          0.5         0.33333333  0.25      ]

私はコード全体をwith np.errstate(all="raise")ブロック内にラップする傾向があり、問題がバグを隠していないことが確実な場合は、特定の条件を無視してコンテキストマネージャーを使用しますが、通常はそうです。

状態を永続的に変更するライブラリが実際にあった場合、メンテナに問題を提起するか、プルリクエストを送信します。これは、実際にはコンテキストマネージャを使用する必要があるため、設定の変更はコードのブロックにのみ適用され、プログラムの残りの部分。

于 2014-08-22T19:58:19.500 に答える