Numpy: バグ:numpy.percentileの出力が並べ替えられない

作成日 2019年10月12日  ·  16コメント  ·  ソース: numpy/numpy

numpy.percentileの出力は常にソートされるとは限りません

コード例の再現:

import numpy as np
q = np.arange(0, 1, 0.01) * 100
percentile = np.percentile(np.array([0, 1, 1, 2, 2, 3, 3 , 4, 5, 5, 1, 1, 9, 9 ,9, 8, 8, 7]) * 0.1, q)
equals_sorted = np.sort(percentile) == percentile
print(equals_sorted)
assert equals_sorted.all()

エラーメッセージ:

[True True True True True True True True True True True True True
True True True True True True True True True True True True True
True True True True True True True True True True True True True
True True True True True True True True True True True True True
True True True True True True True True True True True True True
True True True True True True True True True True True True True
True True True True True True True True True True True True True
True True True True True False False True True True True False
真真真偽]
AssertionErrorトレースバック(最後の最後の呼び出し)

1 q = np.percentile(np.array([0、1、1、2、2、3、3、4、5、5、1、1、9、9、9、8、8、7])* 0.1、np.arange(0、1、0.01)* 100)
2 equals_sorted = np.sort(q)== q
----> 3 assert equals_sorted.all()

AssertionError:

Numpy / Pythonのバージョン情報:

1.17.2 3.6.8(v3.6.8:3c6b436a57、2018年12月24日、02:04:31)
[GCC4.2.1互換性のあるAppleLLVM 6.0(clang-600.0.57)]

00 - Bug numpy.lib good first issue

最も参考になるコメント

ねえ、@ eric-wieserによって提供されたstackexchangeの回答の1つに更新があり、優れた代替補間が行われたようです。
スレッドには単調性の証明が含まれており、提案された修正は、言及されたすべての問題に対処しているようです。
これが問題に意味がある場合、私はこれを最初のコミットとして実装するか、他の誰かがそれを試すことができます。
20191209_020250

全てのコメント16件

なぜそれがソートされると期待するのですか? パーセンタイルは要素ごとです-出力は入力の順序です。

こんにちは !
確かに、パーセンタイルはエルメネットの観点からです- q考慮すると、
np.arange(0, 1, 0.01) * 100
qがソートされているため、出力がソートされることを期待しています。

単一のULP内にいくつかの数値エラーがあり、同じ出力値を持つ異なる入力で異なります。 それについてやるべきことがあるとは思えません。

わずかに減少した失敗のケース:

In [40]: np.percentile(np.array([0, 1, 1, 2, 2, 3, 3 , 4, 5, 5, 1, 1, 9, 9 ,9, 8, 8, 7]) * 0.1, [89, 90, 95, 96, 98, 99])
Out[40]: array([0.9, 0.9, 0.9, 0.9, 0.9, 0.9])

In [41]: np.diff(_)
Out[41]:
array([-1.11022302e-16,  2.22044605e-16, -1.11022302e-16,  1.11022302e-16,
       -1.11022302e-16])

ここでは、diffを介してソートされていないことを示しています。

おそらくこれについて私たちにできることがあると思います。 これは、 lerp操作(基本的にadd(v_below*weights_below, v_above*weights_above) )を実行するこれらの行の安定性に帰着すると思います。

https://github.com/numpy/numpy/blob/b9fa88eec62e34e906689408096beb2450830d9a/numpy/lib/function_base.py#L3907 -L3908

https://github.com/numpy/numpy/blob/b9fa88eec62e34e906689408096beb2450830d9a/numpy/lib/function_base.py#L3928 -L3929

https://github.com/numpy/numpy/blob/b9fa88eec62e34e906689408096beb2450830d9a/numpy/lib/function_base.py#L3939 -L3942

浮動小数点値を線形補間する場合には、多くのトレードオフが必要ですが、ここでは「正しい」選択があると思われます。私たちはそれを行っていません。

ここにいくつかのより多くの背景: https

ええ、私は同意します、それが厳密に単調になるように操作を再編成することで+1します(数値的に)。 それも悪くないか、少なくともほぼ同じ精度であるなら良いでしょう。 ここでは、いくつかの追加の操作/速度について本当に心配する必要はないと確信しています。

編集:良い創刊号としてマークされています。 しかしその後、これはおそらくPythonコード内でのかなり簡単な再編成です。

私はこの問題に取り組むことに興味があります。 私は失敗したケースのいくつかを見ていて、それらがすべて同じ数の間で線形補間を含んでいることに気づきました。 つまり、Ericの例では、彼がリストしたすべてのパーセンタイルは2つの9の間にあります。 したがって、それらの間の線形補間は正確に9でなければならないと思いますか? 同じ2つの数値を線形補間する問題を修正すると、このバグで提示された問題に対処し、パフォーマンスに目立った影響を与えることはないようです。 ただし、線形補間が常に単調になるようにしたい場合は、それを行うことができますが、パフォーマンスが低下すると思われる区分的関数が必要になります。

@ ngonzo95これを実現するには、補間の算術を別の方法で綴る方法が必要です。つまり、計算に使用される式を変更/再配置します(数学的には同一ですが、数値的に単調性が保証されます)。 区分的計算は必要ありません。

区分的計算は必要ありません。

lerp要件によって異なります。 私たちが気にするかもしれないし、気にしないかもしれないいくつか:

  • 単調( (lerp(a, b, t1) - lerp(a, b, t0)) * (b - a) * (t1 - t0) >= 0
  • 有界( a <= lerp(a, b, t) <= b
  • 対称( lerp(a, b, t) == lerp(b, a, 1-t)

0 <= t <= 1

ああ、わかりました。区分的に必要になるとは思っていませんでしたが、これの本質を十分に理解していないと思います。

さらに詳しく調べてみると、関数a +(ba)* tには、単調(上記の定義)と一貫性(lerp(a、a、t)= a)の両方の特性があることがわかりました。 機能要件にはこれで十分だと思います。 この関数の主な欠点の1つは、lerp(a、b、1)!= bであるようです。 ただし、重みの計算方法により、0 <= t <1が保証されると思います。

この関数の主な欠点の1つは、lerp(a、b、1)!= bであるようです。 ただし、重みの計算方法により、0 <= t <1が保証されると思います。

残念ながら、その定式化ではlerp(a, b. 1-eps) > b)が可能であることに注意してください。

オープンソースは初めてです。
私の良い最初の問題としてこれを解決したかった。 どうすれば貢献できますか? 前提条件はありますか?

私は失敗したケースのいくつかを見ていて、それらがすべて同じ数の間で線形補間を含んでいることに気づきました

scikit-learnで、最近この問題に遭遇しました: https

qは厳密に増加すると予想されるため、 np.maximum.accumulate適用して配列を並べ替えることができます。 ただし、NumPyで問題を直接解決できれば、これは素晴らしいことです。 良い修正をするために掘り下げることができる場所はありますか?

@glemaitre :numpyの関連するすべての行は、上記の私のコメントにリンクされています、 https: //github.com/numpy/numpy/issues/14685#issuecomment -541467915

ねえ、@ eric-wieserによって提供されたstackexchangeの回答の1つに更新があり、優れた代替補間が行われたようです。
スレッドには単調性の証明が含まれており、提案された修正は、言及されたすべての問題に対処しているようです。
これが問題に意味がある場合、私はこれを最初のコミットとして実装するか、他の誰かがそれを試すことができます。
20191209_020250

quantile() lerpには別の問題があることに注意してください。inf値が正しく処理されません。#12282を参照してください。

このページは役に立ちましたか?
0 / 5 - 0 評価