5

デフォルトのnetcdfフィル値(9.96920996839e + 36)が使用されているnetcdfファイルから32ビット浮動小数点データを読み取るアプリケーションがあります。アプリの特定のポイントで、基本的なスケーリング(乗算)操作が、入力データから作成されたfloat32タイプのマスクされた配列に対して実行されます。

x = marr * scale   # or, equivalently, x = ma.multiply(marr,scale)

この操作では、「乗算でオーバーフローが発生しました」という警告がスローされます。これは、おそらく、塗りつぶしの値とスケールの積が32ビット浮動小数点の最大値を超えているためです。マスクされた配列の他の値は小さいことがわかっています。問題は、なぜnumpyが入力配列のマスクされた要素の積を計算するのかということです。確かに、これらは単に無視されるべきですよね?

たまたま、出力配列の対応する値にはまだマスクされたフラグが付けられているため、警告は黙って無視できます。しかし、これがnumpyのバグなのか、「設計どおりに機能している」のかを知ることは興味深いでしょう。

以下のコードフラグメントは、この動作を示しています。

import numpy as np
import numpy.ma as ma
arr = [9.96920996839e+36, 1.123, 2.345, 9.96920996839e+36]
marr = ma.masked_values(np.array(arr, dtype='float32'), 9.96920996839e+36)
x = marr * 128.0

予想されるように、マスクされた配列がfloat64型の場合、オーバーフロー警告は表示されません(ただし、スケール係数が十分に大きい場合は表示されます)。同様に、float32の場合に-1.0e20などの小さい塗りつぶし値を使用すると、警告は消えます。

一見すると、大きいフィル値が使用されている場合(32ビットfp値の最大値に非常に近い)、numpyはマスクされた値を識別できないように見えます。

TIA、
フィル

4

2 に答える 2

2

おそらくバグです。前の行には次のものがあります。

np.seterr(divide='ignore', invalid='ignore')

これは、0 または NaN のマスクを処理するように設計されているが、非常に大きな値ではないことを示しています。そのはず: 

np.seterr(divide='ignore', invalid='ignore', over='ignore')

大きなマスク値も処理します。

numpy.ma操作は通常、マスクされた値を含む配列内のすべての値に対して行われることに注意してください。これはおそらく、効率とブロードキャストの問題によるものです。

于 2012-09-20T10:13:50.547 に答える
2

問題は、入力配列内のマスクされた要素の積を numpy が計算するのはなぜですか? 確かに、これらは単に無視されるべきですよね?

ああ、いいえ。現在の実装では、すべての操作が配列全体に適用されてから、マスクが再適用されます。

逆効果に聞こえるかもしれませんが、他のアプローチに代わるより堅牢で非効率的な方法でした。最初は、適切なドメインにのみ操作を適用するのは素晴らしいことですが、そのドメインの計算は非常に複雑になる可能性があります ( にはいくつかの大きな問題がありましたpow)。さらに、余分なテストは、すでに哀れなパフォーマンスをクラッシュさせたでしょう。

numpy 関数がオプションの引数を受け入れる新しいメソッドが最近導入されましたがwhere、これはそれを助けることができます...しかし、欠落/無視された値のサポートを C レベルで直接導入することについての話もあります。 .

于 2012-09-20T15:21:02.817 に答える