Numpy: BUG: keluaran numpy.percentile tidak diurutkan

Dibuat pada 12 Okt 2019  ·  16Komentar  ·  Sumber: numpy/numpy

Keluaran numpy.percentile tidak selalu diurutkan

Contoh kode reproduksi:

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()

Pesan eror:

[Benar Benar Benar Benar Benar Benar Benar Benar Benar Benar Benar Benar Benar Benar
Benar Benar Benar Benar Benar Benar Benar Benar Benar Benar Benar Benar Benar Benar
Benar Benar Benar Benar Benar Benar Benar Benar Benar Benar Benar Benar Benar Benar
Benar Benar Benar Benar Benar Benar Benar Benar Benar Benar Benar Benar Benar Benar
Benar Benar Benar Benar Benar Benar Benar Benar Benar Benar Benar Benar Benar Benar
Benar Benar Benar Benar Benar Benar Benar Benar Benar Benar Benar Benar Benar Benar
Benar Benar Benar Benar Benar Benar Benar Benar Benar Benar Benar Benar Benar Benar
Benar Benar Benar Benar Benar Salah Salah Salah Benar Benar Benar Benar Benar Salah
Benar Benar Benar Salah]
AssertionError Traceback (panggilan terakhir terakhir)
di
1 q = np. Persentil (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 sama dengan_diurutkan = np.sort (q) == q
----> 3 menegaskan equals_sorted.all ()

AssertionError:

Informasi versi Numpy / Python:

1.17.2 3.6.8 (v3.6.8: 3c6b436a57, 24 Desember 2018, 02:04:31)
[GCC 4.2.1 Kompatibel dengan Apple LLVM 6.0 (clang-600.0.57)]

00 - Bug numpy.lib good first issue

Komentar yang paling membantu

Hai, sepertinya ada pembaruan untuk salah satu jawaban stackexchange yang disediakan oleh @ eric-wieser dengan interpolasi alternatif yang bagus.
Untaian tersebut menyertakan bukti monotonisitas, dan perbaikan yang diusulkan tampaknya mengatasi semua masalah yang disebutkan.
Jika ini masuk akal untuk masalah ini, saya akan bersedia menerapkan ini sebagai komitmen pertama, atau orang lain dapat mencobanya.
20191209_020250

Semua 16 komentar

Mengapa Anda mengharapkannya untuk disortir? Persentil bersifat elementwise - keluaran berada dalam urutan masukan.

Hai!
Memang, persentil adalah elmenet-bijaksana - ketika mempertimbangkan q , yang dalam kasus kami adalah
np.arange(0, 1, 0.01) * 100 .
Saya berharap hasilnya diurutkan karena q diurutkan.

Ada beberapa kesalahan numerik dalam ULP tunggal, yang berbeda untuk input berbeda dengan nilai output yang sama. Saya ragu ada yang harus dilakukan tentang itu.

Kasus kegagalan yang sedikit berkurang:

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])

di sini menunjukkan non-sort-ness melalui diff.

Saya pikir mungkin ada sesuatu yang bisa kita lakukan tentang ini. Saya pikir ini tergantung pada stabilitas baris-baris ini, yang melakukan operasi lerp (pada dasarnya 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

Ada banyak pengorbanan yang harus dilakukan saat menginterpolasi nilai floating point secara linier, tetapi saya curiga ada pilihan yang "benar" di sini, dan kami belum berhasil.

Beberapa latar belakang lainnya di sini: https://math.stackexchange.com/questions/907327/accurate-floating-point-linear-interpolation

Ya, saya setuju, +1 tentang mengatur ulang operasi sehingga sangat monotonik (secara numerik). Akan lebih baik jika juga tidak lebih buruk, atau setidaknya presisi hampir identik. Saya yakin kami benar-benar tidak perlu khawatir tentang beberapa operasi / kecepatan tambahan di sini.

EDIT: Ditandai sebagai edisi pertama yang baik. Tetapi setelah itu, ini mungkin reorganisasi yang cukup lurus ke depan dalam kode python.

Saya akan tertarik untuk membahas masalah ini. Saya melihat beberapa kasus yang gagal dan memperhatikan bahwa semuanya melibatkan interpolasi linier antara nomor yang sama. yaitu dalam contoh Eric semua persentil yang dia daftarkan terletak di antara dua angka 9. Oleh karena itu saya pikir interpolasi linier di antara mereka harus 9 tepat benar? memperbaiki masalah interpolasi linier antara dua nomor yang sama sepertinya akan menangani masalah yang disajikan dalam bug ini dan tidak menyebabkan hit yang nyata dalam kinerja. Namun, jika kita ingin memastikan bahwa interpolasi linier akan selalu monotonik, kita dapat melakukannya tetapi itu akan membutuhkan fungsi sepotong-sepotong yang menurut saya akan menurunkan kinerja.

@ ngonzo95 harus ada cara untuk mengeja aritmatika dari interpolasi yang berbeda untuk mencapai ini, yaitu mengubah / mengatur ulang rumus yang digunakan untuk perhitungan (sehingga secara matematis identik, tetapi secara numerik menjamin monotonisitas). Tidak ada perhitungan satu per satu yang diperlukan.

Tidak ada perhitungan satu per satu yang diperlukan.

Itu tergantung apa persyaratan Anda pada lerp . Beberapa yang mungkin atau mungkin tidak kita pedulikan:

  • monotonik ( (lerp(a, b, t1) - lerp(a, b, t0)) * (b - a) * (t1 - t0) >= 0 )
  • dibatasi ( a <= lerp(a, b, t) <= b )
  • simetris ( lerp(a, b, t) == lerp(b, a, 1-t) )

( 0 <= t <= 1 )

Oh oke, saya tidak berharap sedikit demi sedikit akan diperlukan, tetapi saya tidak mengetahui intrinsikaties ini dengan cukup baik.

melihat ke dalamnya lebih lanjut saya menemukan bahwa fungsi a + (ba) * t memiliki sifat monotonik (definisi disebutkan di atas) dan konsisten (lerp (a, a, t) = a). Saya yakin ini harus cukup untuk persyaratan fungsi. Tampaknya salah satu kekurangan utama dari fungsi ini adalah lerp (a, b, 1)! = B. Namun menurut saya cara kita menghitung bobot memastikan bahwa 0 <= t <1.

Tampaknya salah satu kekurangan utama dari fungsi ini adalah lerp (a, b, 1)! = B. Namun menurut saya cara kita menghitung bobot memastikan bahwa 0 <= t <1.

Perhatikan bahwa sayangnya lerp(a, b. 1-eps) > b) dimungkinkan dengan formulasi itu.

Baru di open source.
Ingin menyelesaikan ini sebagai masalah pertama saya yang baik. Bagaimana saya bisa berkontribusi? Apakah ada prasyarat?

Saya melihat beberapa kasus yang gagal dan memperhatikan bahwa semuanya melibatkan interpolasi linier antara nomor yang sama

Dalam scikit-learn, kami baru-baru ini tersandung dalam masalah ini: https://github.com/scikit-learn/scikit-learn/issues/15733

Karena kita mengharapkan q meningkat tajam, kita dapat menerapkan np.maximum.accumulate menyusun ulang larik. Namun, jika kami dapat menyelesaikan masalah di NumPy secara langsung, ini akan bagus. Adakah tempat yang bisa kita gali untuk mendapatkan perbaikan yang baik?

@glemaitre : Semua baris yang relevan di numpy ditautkan dalam komentar saya di atas, https://github.com/numpy/numpy/issues/14685#issuecomment -541467915

Hai, sepertinya ada pembaruan untuk salah satu jawaban stackexchange yang disediakan oleh @ eric-wieser dengan interpolasi alternatif yang bagus.
Untaian tersebut menyertakan bukti monotonisitas, dan perbaikan yang diusulkan tampaknya mengatasi semua masalah yang disebutkan.
Jika ini masuk akal untuk masalah ini, saya akan bersedia menerapkan ini sebagai komitmen pertama, atau orang lain dapat mencobanya.
20191209_020250

Perhatikan bahwa ada masalah lain dengan lerp di quantile() : inf nilai tidak ditangani dengan benar, lihat # 12282.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat