<p>numpy.isclose vs math.isclose</p>

Dibuat pada 5 Des 2017  ·  78Komentar  ·  Sumber: numpy/numpy

numpy.isclose (https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.isclose.html):

abs(a - b) <= (atol + rtol * abs(b))

math.isclose (https://docs.python.org/3/library/math.html#math.isclose):

abs(a - b) <= max(rtol * max(abs(a), abs(b)), atol)

Perhatikan bahwa persamaan Numpy tidak simetris dan menghubungkan parameter atol dan rtol , keduanya adalah hal yang buruk (IMO).

Berikut adalah situasi di mana Numpy "salah" menandai dua angka sebagai sama:

a = 0.142253
b = 0.142219
rtol = 1e-4
atol = 2e-5

# true because atol interferes with the rtol measurement
abs(a - b) <= (atol + rtol * abs(b))
Out[24]: True

# correct result, rtol fails
abs(a - b) <= max(rtol * max(abs(a), abs(b)), atol)
Out[29]: False

Ini satu lagi, masalah simetri kasus ini:

a = 0.142253
b = 0.142219
rtol = 1e-4
atol = 1.9776e-05

# relative to b
abs(a - b) <= (atol + rtol * abs(b))
Out[73]: False

#relative to a
abs(a - b) <= (atol + rtol * abs(a))
Out[74]: True

# math one has no problems with this
abs(a - b) <= max(rtol * max(abs(a), abs(b)), atol)
Out[75]: False

Versi matematika Python tampaknya antipeluru, haruskah Numpy mulai menggunakan ini? Apakah ada keuntungan menggunakan versi Numpy?

57 - Close?

Komentar yang paling membantu

@njsmith : terima kasih sudah mengajak saya masuk.

Sedikit sejarah: ketika saya mengusulkan isclose untuk stdlib, kami pasti melihat numpy sebagai seni sebelumnya. Jika hanya saya, saya mungkin telah menggunakan pendekatan yang kompatibel, demi kompatibilitas yang baik :-).

Tetapi komunitas lainnya berpikir lebih penting untuk melakukan apa yang "benar" untuk Python, jadi diskusi panjang pun terjadi ... Saya mencoba menangkap sebagian besar poin di PEP, jika Anda ingin melihatnya.

Berikut referensi numpy:

https://www.python.org/dev/peps/pep-0485/#numpy -isclose

Anda dapat melihat bahwa poin yang sama dibuat seperti dalam diskusi ini.

Pada akhirnya, tiga poin kunci keluar:

1) pendekatan simetris akan menghasilkan kejutan terkecil.

2) toleransi absolut default mungkin harus nol, agar tidak membuat asumsi apa pun tentang urutan besarnya argumen.

3) perbedaan antara uji "lemah" dan "kuat" tidak relevan bila digunakan dengan toleransi kecil, seperti kasus penggunaan yang diharapkan.

Pada akhirnya, saya pikir kami menemukan solusi "terbaik" untuk math.isclose.

Tapi apakah itu "lebih baik" cukup untuk merusak kompatibilitas ke belakang? Saya rasa tidak.

Sayangnya, banyak numpy (dan python) memiliki banyak fitur yang ditambahkan karena berguna, tetapi tanpa banyak diskusi saat ini, hal-hal ini didapat, jadi kami memiliki banyak desain yang kurang optimal. Ini diharapkan (dan perlu) untuk perpustakaan muda, dan kita harus menerimanya sekarang.

@ njsmith benar - Saya pikir sangat sedikit penggunaan np.isclose () memiliki toleransi yang ditetapkan oleh analisis kesalahan FP yang ketat, melainkan, trial error, dengan np.isclose () itu sendiri.

Namun, saya pikir masalah yang lebih besar adalah default atol - ini mengasumsikan bahwa argumen Anda berurutan 1 - yang bisa menjadi asumsi yang SANGAT salah, dan karena itu akan sering mengakibatkan kelulusan tes yang seharusnya tidak , pengguna mungkin tidak menyadarinya.

In [85]: np.isclose(9.0e-9, 1.0e-9)
Out[85]: True

Aduh!

dan ya, itu adalah atol menyebabkan ini:

In [86]: np.isclose(9.0e-9, 1.0e-9, atol=0.0)
Out[86]: False

Jadi mungkin Ide yang Baik untuk memiliki jalan ke depan.

Saya suka ide argumen kata kunci - sepertinya jauh lebih mudah daripada mencoba mengacaukan __future__ dan sejenisnya.

Dan kami kemudian dapat memutuskan apakah kami ingin mulai mengeluarkan peringatan penghentian dan akhirnya mengubah banyak versi default di hilir ...

Semua 78 komentar

Terlambat untuk mengubah apapun imho.

Ini adalah salah satu fungsi yang paling banyak digunakan di semua numpy (melalui assert_allclose ) Satu-satunya jalur untuk ini adalah memilih nama lain.

Saya akui bahwa implementasi saat ini terlihat seperti bug. Perhatikan bahwa menggunakan max(abs(a), abs(b)) alih-alih abs(b) tidak akan merusak pengujian yang ada, itu hanya melonggarkan kondisi dalam kasus abs(a) > abs(b) .

Paling tidak, ini membutuhkan peringatan di docstring bahwa itu tidak cocok dengan bawaan

Bagaimana jika menambahkan ini?

from numpy.__future__ import isclose

Kebetulan, itu mungkin ide untuk pembuatan versi nomor acak ...

Untuk klarifikasi, impor sebenarnya tidak akan mengimpor isclose tetapi akan mengaktifkan semantik baru. Ini akan dimasukkan ke dalam modul.

Idenya adalah kita dapat mengizinkan orang untuk menggunakan fungsi yang benar dan pada saat yang sama, kita tidak perlu merusak kode yang ada.

, impor tidak akan benar-benar mengimpor isclose tetapi akan mengaktifkan semantik baru

Saya tidak berpikir membuat ini bukan impor tidak mungkin. Pilih saja nama yang lebih panjang, seperti mathlike_ufunc s, yang juga bisa mencakup remainder .

Perhatikan bahwa from __future__ import print_function sebenarnya menghasilkan print_function global

Sebenarnya, gaya impor from __future__ import * mungkin tidak sesuai di sini - di python, ini memengaruhi _syntax_ pada tingkat per file, dan melakukan sesuatu yang serupa di numpy akan menjadi rumit

Pengecualian iterator bukanlah perubahan sintaks. Kami hanya membutuhkan modul C kecil untuk memeriksa namespace dari modul pemanggil. Kami bahkan dapat menyimpan modul-modul tersebut sehingga hanya waktu impor yang diperlambat, dan hanya sepele.

Anda benar - dan true_division jelas mirip dengan isclose.

Ini sebenarnya cara yang bagus untuk menghindari masalah di # 9444, sebagai alternatif untuk menggunakan pernyataan with untuk mengelola fitur yang tidak digunakan lagi.

Mari CC @ ChrisBarker-NOAA sebagai pembuat math.isclose .

Ini adalah masalah IMO yang cukup kecil. Umumnya atol dan rtol dipilih dengan mengotak-atiknya sampai tes lulus, dan tujuannya adalah untuk menangkap kesalahan yang urutan besarnya lebih besar dari toleransi. Mungkin masuk akal untuk melonggarkan bagian rtol seperti yang disarankan @charris , tetapi menurut saya tidak ada gunanya menarik trik introspeksi tumpukan untuk perubahan kecil ini. Dan kami masih memiliki masalah bahwa isclose sering disebut secara tidak langsung oleh hal-hal seperti assert_allclose atau berbagai pembantu pengujian pihak ketiga.

Saya bertanya di StackOverflow tentang penggunaan impor gaya __future__ : https://stackoverflow.com/questions/29905278/using-future-style-imports-for-module-specific-features-in-python

TLDR: itu mungkin, tapi tidak mudah atau bersih.

Introspeksi tumpukan tidak hanya untuk ini, tetapi diusulkan sebagai kebijakan umum untuk mengubah nilai kembalian fungsi. Pertanyaannya adalah: pada prinsipnya, haruskah ini diubah? Menurut saya, jika jawabannya ya, periode penghentian penggunaan harus setidaknya beberapa tahun mengingat penggunaan yang meluas. Python tidak pernah menyertakan modul sebelumnya tetapi itu adalah salah satu opsi untuk mencoba meningkatkan stabilitas API, jika ada permintaan.

Metode lain adalah dengan menambahkan ini sebagai opsi isclose(...,symmetric=True) atau assert_allclose(symmetric=True) mana defaultnya adalah False , situasi saat ini.

Saya setuju bahwa ini adalah masalah kecil ketika Anda tidak memberi arti pada nilai rtol dan atol , cukup sesuaikan untuk lulus pengujian unit, seperti yang disebutkan oleh @njsmith.

Namun, terkadang Anda ingin mengatakan bahwa kesalahannya ada di dalam, misalnya, 1% ( rtol=0.01 ).
Dalam kasus ini kesalahan kasus terburuk tentang pengukuran rtol adalah 100% ( rtol * abs(b) mendekati atol , lalu atol + rtol * abs(b) ~= 2 * rtol * abs(b) ).

Artinya beberapa nilai bisa lewat dengan kesalahan ~ 2%:

atol = 1e-8 #default
rtol = 0.01 # 1%

b = 1e-6
a = 1.0199e-6 # ~ 2% larger comapared to b
abs(a - b) <= (atol + rtol * abs(b))
True

Menerapkan ide @charris , akan membuat kasus khusus ini sedikit lebih buruk, karena ini bahkan lebih melonggarkan perbandingan, tetapi tetap berharga karena menghilangkan masalah simetri dan memang kompatibel ke belakang.

IMO akan lebih baik jika Numpy menggunakan fungsi Matematika, tetapi saya mengerti bahwa perubahan itu mungkin terlalu mengganggu dan mungkin tidak penting bagi sebagian besar pengguna. Membuat opsi untuk mengubah antara isclose inti akan berguna.

@njsmith : terima kasih sudah mengajak saya masuk.

Sedikit sejarah: ketika saya mengusulkan isclose untuk stdlib, kami pasti melihat numpy sebagai seni sebelumnya. Jika hanya saya, saya mungkin telah menggunakan pendekatan yang kompatibel, demi kompatibilitas yang baik :-).

Tetapi komunitas lainnya berpikir lebih penting untuk melakukan apa yang "benar" untuk Python, jadi diskusi panjang pun terjadi ... Saya mencoba menangkap sebagian besar poin di PEP, jika Anda ingin melihatnya.

Berikut referensi numpy:

https://www.python.org/dev/peps/pep-0485/#numpy -isclose

Anda dapat melihat bahwa poin yang sama dibuat seperti dalam diskusi ini.

Pada akhirnya, tiga poin kunci keluar:

1) pendekatan simetris akan menghasilkan kejutan terkecil.

2) toleransi absolut default mungkin harus nol, agar tidak membuat asumsi apa pun tentang urutan besarnya argumen.

3) perbedaan antara uji "lemah" dan "kuat" tidak relevan bila digunakan dengan toleransi kecil, seperti kasus penggunaan yang diharapkan.

Pada akhirnya, saya pikir kami menemukan solusi "terbaik" untuk math.isclose.

Tapi apakah itu "lebih baik" cukup untuk merusak kompatibilitas ke belakang? Saya rasa tidak.

Sayangnya, banyak numpy (dan python) memiliki banyak fitur yang ditambahkan karena berguna, tetapi tanpa banyak diskusi saat ini, hal-hal ini didapat, jadi kami memiliki banyak desain yang kurang optimal. Ini diharapkan (dan perlu) untuk perpustakaan muda, dan kita harus menerimanya sekarang.

@ njsmith benar - Saya pikir sangat sedikit penggunaan np.isclose () memiliki toleransi yang ditetapkan oleh analisis kesalahan FP yang ketat, melainkan, trial error, dengan np.isclose () itu sendiri.

Namun, saya pikir masalah yang lebih besar adalah default atol - ini mengasumsikan bahwa argumen Anda berurutan 1 - yang bisa menjadi asumsi yang SANGAT salah, dan karena itu akan sering mengakibatkan kelulusan tes yang seharusnya tidak , pengguna mungkin tidak menyadarinya.

In [85]: np.isclose(9.0e-9, 1.0e-9)
Out[85]: True

Aduh!

dan ya, itu adalah atol menyebabkan ini:

In [86]: np.isclose(9.0e-9, 1.0e-9, atol=0.0)
Out[86]: False

Jadi mungkin Ide yang Baik untuk memiliki jalan ke depan.

Saya suka ide argumen kata kunci - sepertinya jauh lebih mudah daripada mencoba mengacaukan __future__ dan sejenisnya.

Dan kami kemudian dapat memutuskan apakah kami ingin mulai mengeluarkan peringatan penghentian dan akhirnya mengubah banyak versi default di hilir ...

Saya ingin mengusulkan saran @bashtage :

"" "
Metode lain akan menambahkan ini sebagai opsi isclose (..., simetris = True) atau assert_allclose (simetris = True) di mana defaultnya adalah False, situasi saat ini.
"" "

Saya pikir ini adalah opsi yang lebih baik daripada nama fungsi baru, dan dapat mengarah ke penghentian masa depan dan perubahan default (atau tidak).

Saya pikir selain tes simetris (kuat), atol harus default ke nol juga.

Mengingat itu, mungkin kita membutuhkan nama yang lebih baik untuk parameter daripada symmetric , meskipun tidak buruk ...

Oh - dan mungkin bagus untuk memastikan bahwa isclose() tidak dipanggil di tempat lain di numpy selain assert allclose() .

Cara termudah untuk melakukannya mungkin dengan memasukkan peringatan penghentian dan
lalu hapus sebelum menggabungkan. Kita bisa langsung saja memasang
peringatan deprecation yang mengatakan untuk mengubah kode yang ada menjadi
simetris = Salah; tidak ada alasan untuk mengatakan bahwa defaultnya perlu
berubah dalam waktu dekat bahkan jika ada peringatannya.

Apakah kita perlu menambahkannya ke assert_allclose juga, atau apakah kita hanya melakukan perubahan secara diam-diam? Membuat orang memperbarui setiap tes mereka untuk membungkam peringatan sebenarnya tidak ada bedanya dengan membuat mereka memperbarui tes mereka untuk memperbaiki pengurangan toleransi

@xoviat @ eric-wieser tidak boleh ada perubahan mundur yang tidak kompatibel ke assert_allclose atau peringatan penghentian darinya, terlalu mengganggu. Kecuali jika saya melewatkan tempat Anda ingin meletakkan peringatan penghentian?

Saya khawatir ini masih terdengar sangat menyakitkan untuk yang sangat kecil
keuntungan, bagi saya.

Memiliki atol menjadi bukan nol secara default bukanlah suatu kebetulan. Itu dibutuhkan untuk mendapatkan
perilaku default yang masuk akal untuk pengujian apa pun yang menyertakan hasil yang diharapkan
nol tepat.

Tidak ada perubahan pada assert_allclose apa pun yang diperlukan, karena akan diperbarui menjadi
internal untuk menggunakan perilaku lama.

Perubahan diam IMO itu buruk! Peringatan penghentian hanya agar
orang pada akhirnya tidak perlu mengetikkan bendera di prompt interaktif untuk
dapatkan perilaku baru, tidak lebih

Perubahan diam IMO itu buruk!

Sepakat. Namun, seharusnya tidak ada perubahan apa pun. Peringatan penghentian dalam fungsi yang banyak digunakan juga memaksa pengguna (setidaknya yang benar-benar melakukan pemeliharaan) untuk membuat perubahan.

Bagaimana dengan memperbaiki masalah non-simetri seperti yang disarankan @charris ? Ini juga akan membebaskan beberapa ruang dokumentasi, yang dapat diisi dengan peringatan tentang hal-hal buruk yang mungkin terjadi jika atol != 0.0 .

Kami tidak dapat memperbaiki masalah itu tanpa memberi tahu orang-orang tentang perubahan tersebut
tingkah laku. Satu-satunya cara saya tahu bagaimana melakukannya adalah dengan peringatan.

Apa yang benar-benar bagus adalah alat refactoring otomatis untuk menyuntikkan bendera
menjadi kode lama. Kemudian 'pemeliharaan' hanya akan menjalankan skrip di file
kode; 5 menit kerja.

Maaf, ini bisa diperbaiki, hanya dengan bendera baru.

Bagaimana dengan memperbaiki masalah non-simetri seperti yang disarankan @charris ?

Saran itu (https://github.com/numpy/numpy/issues/10161#issuecomment-349384830) tampaknya dapat dilakukan.

Kami tidak dapat memperbaiki masalah itu tanpa memberi tahu orang-orang tentang perilakunya yang berubah.

Kami tidak memperbaikinya. Ini adalah masalah biaya / manfaat dari setiap perubahan yang baru saja dibahas dalam masalah pembuatan versi semantik. Ini jelas merupakan kasus di mana kami tidak akan membuat perubahan atau mengeluarkan peringatan apa pun dari fungsi pengujian yang banyak digunakan. Perhatikan bahwa perilaku saat ini bukanlah bug (meskipun bisa dibilang pilihan yang kurang optimal).

Untuk memperjelas, saya mengusulkan perubahan ke isclose tetapi tidak assert_allclose.
Dari melihat sumber, perubahan itu akan menjadi yang ketiga sebagai mengganggu.
Namun, manfaatnya mungkin masih terlalu kecil. Saya tidak berpikir siapa pun
objek untuk menambahkan bendera, benar?

Saya tidak berpikir ada orang yang keberatan untuk menambahkan bendera, benar?

Tidak yakin, tergantung detailnya. Saran @charris mungkin tidak memerlukan flag, dan flag apapun yang memasukkan ini agak dipertanyakan untuk array:

In [1]: import math

In [2]: math.isclose(0, 1e-200)
Out[2]: False

Saya menentang menambahkan bendera tanpa motivasi konkret dan kasus penggunaan. Tes lakmus yang berguna: jika seorang pengembang pemula bertanya kepada Anda mengapa bendera ini ada, bagaimana Anda menjelaskannya?

bagaimana Anda menjelaskan?

  1. Anda menggunakan tanda symmetric=True jika ingin memvektorisasi panggilan ke math.isclose
  2. Itu harus menjadi sebuah bendera agar kami tidak merusak kode yang ada.

Saya lebih mencari situasi di mana ada beberapa masalah yang sebenarnya sedang diselesaikan.

Mungkin satu-satunya masalah sebenarnya yang diselesaikan di sini adalah membuat pemula
pikirkan lebih lanjut tentang akurasi floating-point. Maksud saya, contoh oleh @rgommers
sepertinya itu akan salah, tetapi bagaimana jika Anda berurusan dengan sangat kecil
nomor? IMO implementasi math.isclose lebih baik, tetapi saya bahkan tidak
pikir ada konsensus tentang itu. Sayangnya, sebenarnya tidak ada
solusi satu ukuran untuk semua untuk menentukan apakah angka "mendekati". Tapi
berdasarkan tanggapan dari orang lain (yang tidak salah!), saya tidak juga
perubahan apa pun pada API ke depannya. Saya kira satu-satunya tindakan yang harus diambil adalah
mungkin pembaruan dokumentasi kemudian (kata-kata terakhir yang terkenal, mengingat bahwa saya
sebelumnya mengira sebuah bendera akan baik-baik saja)?

Tentunya catatan yang dibandingkan dengan math.isclose dan mendokumentasikan bagaimana mendapatkan perilaku vektor yang identik dengan mengatur rtol dan atol, jika ada yang mau, akan baik-baik saja.

Juga, jika saya mengerti dengan benar, @charris mengusulkan solusi untuk mengizinkan
hampir menjadi kurang toleran daripada saat ini, yang tidak akan rusak
tes apa pun. Saya masih berpikir itu akan menjadi ide yang baik untuk mengeluarkan peringatan (file
peringatan harus dikeluarkan satu kali) jika ada situasi di mana akan ditutup
menganggap angka menjadi "dekat" padahal sebelumnya tidak. Itu banyaklebih baik daripada sekadar mengubah perilaku fungsi secara diam-diam dan tidak membiarkannya
ada yang tahu tentang itu ketika itu mempengaruhi mereka.

Saya pikir beberapa klarifikasi diperlukan di sini tentang apa yang kita diskusikan. Ada dua hal yang membuat math.isclose berbeda:

  • Default berbeda untuk atol
  • Definisi berbeda dari rtol

Saya tidak berpikir kita dapat melakukan apa pun tentang masalah pertama, selain mendokumentasikannya sebagai perbedaan dari `math.isclose.

Masalah kedua, menurut saya paling baik diperbaiki dengan menambahkan argumen symmetric yang defaultnya menjadi False . Sekarang kita dapat menulis di dokumen kita _ " np.isclose(x, y, symmetric=True, atol=0) adalah versi vektor dari math.isclose(x, y) " _, yang bagi saya tampaknya merupakan hal yang ingin kita selesaikan.

Dari sini, kami memiliki tiga opsi:

  1. Dokumentasikan argumen tambahan, dan jangan lakukan yang lain
  2. Hentikan pemanggilan isclose tanpa argumen, memaksa pengguna untuk menulis isclose(..., symmetric=False) untuk mendapatkan perilaku lama tanpa peringatan (dan serupa untuk allclose ). Saya menduga ini tidak akan mengenai terlalu banyak kode, tetapi hasilnya kurang dapat dibaca tanpa keuntungan besar. assert_close akan diubah untuk memanggil isclose(..., symmetric=False) internal, sehingga pengguna tidak akan terpengaruh
  3. Seperti di atas, tetapi juga membutuhkan argumen symmetric menjadi assert_close . Ini akan menjadi churn besar-besaran di hilir
  4. Ubah perilaku secara diam-diam

Dari semua ini, saya pikir opsi 1 tidak dapat diganggu, tetapi sisanya tidak terdengar seperti hal-hal yang layak untuk diganggu.

Edit: 2 mungkin dapat diterima jika peringatan hanya dibunyikan jika perilakunya berubah, yang akan jauh lebih tidak berisik.

@ eric-wieser Ada perbedaan ketiga: cara atol dan rtol digabungkan. ( math.isclose menggunakan max , numpy.isclose menggunakan + ). Ini berarti bahwa kecuali atol atau rtol adalah nol, tidak ada cara umum untuk membuat panggilan math.isclose cocok dengan panggilan numpy.isclose .

Saya masih merasa ini tidak layak untuk menambahkan API yang terlihat oleh pengguna.

Saya mendukung opsi dua. Saya masih mendukung opsi itu, dengan
Ketentuan tambahan bahwa numpy akan memberikan otomatisasi
alat refactoring (ditambahkan ke entry_points) yang bisa Anda jalankan di
proyek yang ada untuk memperbaikinya. Berdasarkan apa yang orang lain katakan, itu terdengar seperti
opsi ini tidak akan disukai oleh orang lain.

Saya tidak, dan tidak pernah menyukai salah satu dari opsi tiga atau empat. Di
Selain itu, saya tidak mendukung perubahan perilaku fungsi sampai ada peringatan
telah dipancarkan setidaknya untuk empat rilis utama.

Dengan asumsi bahwa orang lain tidak setuju dengan opsi dua (yang mereka miliki), saya akan setuju
mendukung opsi satu. Tetapi yang lain (terutama @njsmith) tidak mendukung
dari salah satu opsi yang Anda berikan di sini. Setidaknya itulah persepsi saya.

@njonk Itu tidak benar; Anda bisa mengubah perilaku fungsi dengan bendera.

Saya melipat perbedaan ketiga itu menjadi handwavey _ "rtol is different" _

"" "
Saya lebih mencari situasi di mana ada beberapa masalah yang sebenarnya sedang diselesaikan.
"" "
Saya akan bertaruh dolar untuk donat (yang akan saya lakukan karena saya tidak tahu apa artinya ..) bahwa ada tes di luar sana yang lulus yang seharusnya tidak karena atol membuat tes menjadi kurang sensitif. seharusnya.

Tampaknya ada tiga "masalah" dengan penerapan saat ini:

1) tidak simetris

  • Saya pikir itu terlalu buruk, tetapi sebenarnya bukan masalah besar, dan hampir tidak ada perbedaan ketika nilainya benar-benar dekat :-) Saya _think_ secara harfiah tidak ada perbedaan jika rtol <1e-8 (setidaknya jika atol adalah 0,0)

2) atol mempengaruhi hasil bahkan ketika tidak dibandingkan dengan nol (itu tidak dapat dihindari) - tetapi secara efektif mengubah toleransi sekitar faktor dua - atau bahkan lebih jika atol besar, yang mungkin terjadi jika bekerja dengan pesanan besar nilai besarnya.

3) atol bukan nol menjadi default - Saya sebenarnya berpikir ini adalah masalah terbesar (terutama dengan algoritma saat ini untuk menambahkan keduanya) karena dapat dengan mudah menyebabkan kelulusan tes yang seharusnya tidak - dan terlalu sering kita melakukannya agak malas - kami menulis tes dengan toleransi default, dan jika lolos, kami pikir kami sudah selesai. (ketika saya menyadari bahwa begitulah cara kerjanya, saya kembali ke kode y, dan DID menemukan beberapa dari mereka - ups!

Seseorang di utas ini mengatakan sesuatu tentang "akan ada sesuatu yang mengganggu jika:

isclose (1e-200, 0,0)

mengembalikan False secara default. Saya tidak setuju - ya, itu akan mengejutkan, tetapi itu akan memaksa pengguna untuk memikirkan apa yang sedang terjadi, sedangkan implementasi saat ini menghasilkan (misalnya):

Dalam [8]: np.isclose (1e-20, 1e-10)
Keluar [8]: Benar

Betulkah? satu adalah SEPULUH ORDER MAGNITUDE lebih besar dari yang lain dan itu kembali Benar ????

Maksud saya adalah bahwa memiliki atol bukan nol memberikan hasil yang mungkin kurang mengejutkan dalam kasus umum dibandingkan dengan nol, tetapi JAUH lebih berbahaya dan hasil yang salah ketika bekerja dengan angka kecil (kecil benar-benar kurang dari urutan besarnya 1.

Dan jika Anda bekerja dengan angka besar, katakanlah lebih besar dari 1e8, maka atol default juga tidak sesuai.

Dan ditambah dengan (2), itu berarti atol default juga dapat mengacaukan tes toleransi relatif dengan cara yang mengejutkan.

Jadi: tidak, ini bukan bug, dan tidak "rusak", tetapi cukup sub-optimal, jadi alangkah baiknya jika memiliki cara ke depan untuk implementasi yang lebih baik.

Saya memang menyukai pendekatan bendera, tetapi saya pikir saya berubah pikiran - masalahnya adalah kecuali kita menghentikannya, dan bendera default berubah di beberapa titik, kita hanya akan meminta hampir semua orang menggunakan algoritma "lama" cukup banyak selamanya. Dan ada banyak argumen bagus mengapa kami mungkin tidak bisa menolaknya.

Jadi mungkin fungsi baru, dengan nama baru sudah diatur. Kami dapat menambahkan ke dokumen yang mendorong orang untuk menggunakan yang baru, dan _mungkin_ menambahkan peringatan di beberapa titik ketika orang menggunakan yang baru, tapi kami tidak akan pernah merusak kode siapa pun.

Ada yang punya ide untuk nama yang bagus untuk fungsi baru ????

Mungkin np.math.isclose dan teman-teman? Saya tidak tahu.

Itu memecahkan np.remainder menjadi berbeda juga, dan juga memungkinkan Anda untuk dengan mudah membuat vektor kode dengan menggunakan from numpy import math

Jadi saya akan menjadi +1 pada modul np.math

Memperkenalkan fungsi baru dengan perilaku yang hanya sedikit berbeda dari fungsi lain yang telah bekerja seperti itu selama satu dekade pada umumnya adalah ide yang sangat buruk. Dalam kasus ini sebenarnya tidak banyak masalah yang tidak dapat diselesaikan dengan dokumentasi. Jadi -1 pada fungsi baru. Dan pasti -1 pada submodul baru.

Betulkah? satu adalah SEPULUH ORDER MAGNITUDE lebih besar dari yang lain dan itu kembali Benar ????

Apakah ekspektasi Anda Benar atau Salah sepenuhnya bergantung pada konteks. Jika itu untuk bilangan yang berasal dari distribusi kontinu pada [0, 1) maka ya, Anda mungkin mengharapkan True. Seorang pengguna benar-benar harus memahami toleransi absolut / relatif dan apa fungsi sebenarnya, dan untuk itulah dokumen itu.

symmetric_isclose() agak bertele-tele, tapi tidak menyinggung mata saya.: bikeshed: emoji>

Pada 10 Des 2017, pukul 20:09, Ralf Gommers [email protected] menulis:

Memperkenalkan fungsi baru dengan perilaku yang sedikit berbeda dari yang lain
fungsi yang telah bekerja seperti itu selama satu dekade secara umum sangat buruk
ide.

Saya juga tidak menyukainya - tetapi melanggar kode orang dengan perubahan lebih buruk.
Apakah Anda punya ide selain sederhana untuk tidak membuat numpy lebih baik?

Dalam hal ini sebenarnya tidak ada banyak masalah yang tidak bisa ditangani secara memadai
diselesaikan dengan dokumentasi.

Saya tidak setuju - default penting - banyak.

Dan menurut saya tidak ada cara untuk menyesuaikan parameter untuk memberi Anda a
perbandingan simetris.

Dan pasti -1 pada submodul baru.

Saya juga. Jika ada hal lain dalam modul matematika tanpa numpy
padanan yang akan berguna, mereka dapat ditambahkan ke namespace numpy
seperti yang lainnya.

Betulkah? satu adalah SEPULUH PESANAN MAGNITUDE lebih besar dari yang lain dan itu kembali
Benar????

Apakah ekspektasi Anda Benar atau Salah sepenuhnya bergantung pada konteks.

Persis - itulah mengapa TIDAK ADA default yang "masuk akal" untuk atol.

Jika itu untuk bilangan yang berasal dari distribusi kontinu di [0, 1)
maka ya, Anda mungkin mengharapkan True.

Tapi isclose diiklankan sebagai perbandingan relatif - dan di sini
kerelatifan sedang sepenuhnya dicuci menjadi perbandingan mutlak,
tanpa pengguna harus memikirkannya.

Itulah maksud saya - default HANYA sesuai jika Anda mengharapkan
nilai-nilai menjadi urutan besarnya 1. Kasus umum, tentu, tapi tidak
universal.

Ini bermuara pada yang lebih buruk - negatif palsu atau positif palsu.
Dan dalam kasus penggunaan umum pengujian, positif palsu jauh lebih buruk.

(yaitu lulus tes yang seharusnya tidak)

Seorang pengguna benar-benar harus memahami toleransi absolut / relatif dan apa a
fungsi sebenarnya,

Tentu - tetapi suatu fungsi juga harus memiliki default yang wajar dan a
algoritma yang kuat yang mudah dimengerti.

Saya cenderung meningkatkan dokumentasi dan membiarkan fungsinya sendiri. Kurangnya simetri dapat dijelaskan sebagai "isclose (a, b) berarti bahwa a mendekati b, tetapi karena presisi absolut yang bervariasi dari floating point, tidak selalu terjadi bahwa b mendekati a. Dalam pengujian, b harus merupakan hasil yang diharapkan dan a harus merupakan hasil aktual. " Perhatikan bahwa ini masuk akal untuk pengujian, case fungsi simetris sebenarnya sedikit lebih rumit untuk dibenarkan. Kesalahan relatif, yang melibatkan pembagian sebagaimana adanya, tidak simetris.

Saya juga tidak menyukainya - tetapi melanggar kode orang dengan perubahan lebih buruk. Apakah Anda punya ide selain sederhana untuk tidak membuat numpy lebih baik?

Anda sudah memberikan penilaian nilai di sini bahwa menambahkan fungsi baru Anda lebih baik daripada tidak ada fungsi baru. Ini bukan imho. Tiga opsi:

  1. Perubahan yang menghancurkan - tidak dapat diterima, Anda dapat berhenti membahasnya.
  2. Hanya menambahkan dokumen yang lebih baik
  3. Menambahkan fungsi

2 secara keseluruhan adalah pilihan yang lebih baik daripada 3, maka itulah yang membuat numpy "lebih baik". Anda juga mengabaikan bahwa hal atol / rtol ini tidak terbatas pada satu fungsi, jadi apa selanjutnya - yang baru dan sedikit "lebih baik" assert_allclose ? Hal ini membuat kasus khusus dokumen menjadi lebih jelas.

Ini adalah cacat yang cukup serius, pada dasarnya pengujian kode kode Anda disadap ... tidak bagus. Apakah Anda akan mengirim sesuatu ke bulan yang diuji dengan numpy.isclose dan default atol? Saya akan berpikir dua kali ... dan itulah mengapa kita perlu membuat perangkap ini menonjol dalam dokumentasi.
Menambahkan fungsi alias hanya akan mengacaukan basis kode kecuali jika dipaksa pada pengguna (tidak terjadi).

Saya setuju bahwa hal-hal yang simetris itu kecil, tetapi kita harus tetap memperbaikinya. Meninggalkannya dapat mengalihkan pengguna dari kesulitan yang sebenarnya.

@rgommers menulis:
"" "
Anda sudah memberikan penilaian nilai di sini bahwa menambahkan fungsi baru Anda lebih baik daripada tidak ada fungsi baru. Ini bukan imho.
"" "
Yah, saya menghabiskan BANYAK waktu untuk memikirkan, dan berdebat tentang math.isclose , dan kami memang mulai dengan melihat implementasi numpy di antara yang lain. jadi, ya, saya rasa pendekatan itu lebih baik. Dan saya berpikir dari diskusi ini bahwa itu adalah konsensus.

Dan mendapatkan algoritma / antarmuka yang lebih baik menjadi numpy membuatnya lebih baik, ya.

Mungkin maksud Anda memiliki fungsi lama dan baru, lebih baik, di numpy TIDAK lebih baik, daripada membiarkan fungsi lama (mungkin lebih baik didokumentasikan) di sana. Tentu, itu poin yang benar-benar valid, tetapi saya mencoba untuk membahasnya, dan komentar sebelumnya bahwa "Memperkenalkan fungsi baru dengan perilaku yang hanya sedikit berbeda dari fungsi lain yang telah bekerja seperti itu selama satu dekade secara umum adalah ide yang sangat buruk" sepertinya menutup diskusi - maksud saya adalah jika cara baru itu "cukup lebih baik" daripada itu akan sepadan. Yang jelas kita tidak memiliki konsensus adalah apakah opsi khusus ini "cukup lebih baik", bukan apakah "lebih baik".

Dan omong-omong, saya pribadi belum meyakinkan diri saya sendiri bahwa perubahan itu berharga, tetapi saya ingin berdiskusi.

Kuncinya di sini adalah beberapa asumsi dari pihak saya. Saya tidak tahu apakah kita dapat mengetahui dengan pasti apakah mereka benar, tetapi:

1) penggunaan terbesar np.isclose () adalah untuk pengujian - apakah jawaban Anda cukup dekat dengan yang Anda harapkan? - ini melalui np.assert_all_close, atau lebih langsung, dalam tes pytest, atau ....

2) Kebanyakan orang, sebagian besar waktu, tidak melakukan sesuatu seperti analisis kesalahan floating point yang ketat untuk menentukan seberapa baik jawaban yang diharapkan. Sebaliknya, mereka mencoba nilai, dan jika gagal mereka melihat hasilnya dan memutuskan apakah itu benar-benar sebuah kesalahan, atau jika mereka perlu menyesuaikan toleransi pengujian.

  • ini berarti tidak masalah apakah atol dan rtol digabungkan, dan apakah pengujiannya simetris.

3) banyak orang, seringkali, memulai proses dalam (2) dengan toleransi default, dan hanya melihat untuk menyesuaikan toleransi jika tes gagal.

  • INI berarti memiliki atol default cukup berbahaya - tes yang seharusnya tidak lulus adalah hal yang sangat buruk.

4) Orang tidak membaca dokumen (di luar tahap awal "bagaimana saya menyebutnya") - setidaknya sampai mereka menemukan perilaku yang membingungkan, dan kemudian mereka mungkin masuk dan mencoba memahami bagaimana sesuatu benar-benar bekerja untuk menghilangkan kebingungan . Tetapi lihat (3) - jika sebuah tes tidak gagal, mereka tidak tahu untuk pergi melihat dokumen untuk memahami mengapa.

Semua ini membawa saya pada kesimpulan bahwa numpy akan menjadi "lebih baik" dengan tes kedekatan FP seperti math.isclose-like.

Dan mengapa dokumen yang lebih baik merupakan ide yang bagus, tetapi tidak cukup.

Mungkin saya benar-benar salah, dan kebanyakan orang dengan hati-hati membaca dokumen dan memilih rtol dan atol dengan cermat untuk masalah mereka sebagian besar waktu - tetapi saya tahu saya, atau setengah lusin orang di tim saya, melakukannya sampai saya menjadi menyadari masalah ini.

: bikeshed: (sial, itu tidak berhasil - tidak ada emoji yang bagus)

mungkin relatively_close , atau rel_close ?

Kerutan "menyenangkan" tambahan: assert_allclose sebenarnya menggunakan atol = 0 oleh
default. Ada utas lain di suatu tempat yang memperdebatkan apakah kita bisa memperbaikinya
ketidakkonsistenan itu. (Di ponsel saya jadi tidak dapat menemukannya dengan mudah.)

Pada 11 Des 2017 14:58, "Chris Barker" [email protected] menulis:

@rgommers https://github.com/rgommers menulis:
"" "
Anda sudah memberikan penilaian nilai di sini yang menambahkan fungsi baru Anda
lebih baik daripada tidak ada fungsi baru. Ini bukan imho.
"" "
Yah, saya menghabiskan BANYAK waktu untuk memikirkan, dan berdebat tentang
math.isclose, dan kami memulai dengan melihat implementasi numpy
diantara yang lain. jadi, ya, saya rasa pendekatan itu lebih baik. Dan saya pikir
dari diskusi ini, itu cukup banyak konsensus.

Dan mendapatkan algoritma / antarmuka yang lebih baik menjadi numpy membuatnya lebih baik, ya.

Mungkin maksud Anda memiliki yang lama dan yang baru, lebih baik, berfungsi
numpy TIDAK lebih baik, daripada meninggalkan yang lama (mungkin lebih baik
didokumentasikan) berfungsi di sana. Tentu, itu poin yang benar-benar valid, tetapi saya benar
mencoba untuk melakukan diskusi itu, dan komentar sebelumnya yang "Memperkenalkan
fungsi baru dengan hanya sedikit perbedaan perilaku dari fungsi lainnya
yang telah bekerja seperti itu selama satu dekade secara umum adalah gagasan yang sangat buruk "
sepertinya menutup diskusi - maksud saya adalah jika cara baru adalah
"cukup lebih baik" daripada itu akan sia-sia. Apa yang jelas tidak kami miliki a
konsensus adalah apakah opsi khusus ini "cukup lebih baik", bukan
apakah itu "lebih baik".

Dan omong-omong, saya pribadi belum meyakinkan diri saya sendiri bahwa itu layak
berubah, tapi saya ingin berdiskusi.

Kuncinya di sini adalah beberapa asumsi dari pihak saya. Saya tidak tahu apakah kami bisa
pernah tahu dengan pasti apakah mereka benar, tetapi:

1.

penggunaan terbesar np.isclose () adalah untuk pengujian - apakah jawaban Anda
cukup dekat dengan apa yang Anda harapkan? - ini melalui np.assert_all_close, atau
lebih langsung, dalam tes pytest, atau ....
2.

Kebanyakan orang, sebagian besar waktu, tidak melakukan sesuatu yang terlalu ketat
analisis kesalahan floating point untuk menentukan seberapa baik jawaban tersebut
diharapkan. Sebaliknya, mereka mencoba nilai, dan jika gagal mereka melihat
hasil dan memutuskan apakah itu benar-benar kesalahan, atau jika perlu untuk menyesuaikan
toleransi pengujian.

  • ini berarti bahwa tidak terlalu penting apakah atol dan
    rtol digabung, dan apakah pengujiannya simetris.

  • banyak orang, sebagian besar waktu, memulai proses dalam (2) dengan
    toleransi default, dan hanya melihat untuk menyesuaikan toleransi jika tes gagal.

  • INI berarti memiliki atol default cukup berbahaya - tes
    melewati yang tidak seharusnya adalah hal yang sangat buruk.

  • Orang tidak membaca dokumen (di luar inisial "bagaimana saya menyebutnya"
    tahap) - setidaknya sampai mereka menemukan perilaku yang membingungkan, dan kemudian mereka
    mungkin masuk dan mencoba memahami bagaimana sesuatu benar-benar berfungsi untuk menjernihkan
    kebingungan. Tapi lihat (3) - jika sebuah tes tidak gagal, mereka tidak tahu
    lihat dokumen untuk memahami alasannya.

Semua ini membawa saya pada kesimpulan bahwa numpy akan menjadi "lebih baik" dengan a
lebih banyak tes kedekatan FP seperti math.isclose.

Dan mengapa dokumen yang lebih baik merupakan ide yang bagus, tetapi tidak cukup.

Mungkin saya benar-benar salah, dan kebanyakan orang dengan cermat membaca dokumen dan
pilih rtol dan atol dengan hati-hati untuk masalah mereka sebagian besar waktu -
tapi saya tahu saya, atau setengah lusin orang di tim saya, melakukan itu sampai saya
menyadari masalah ini.

: bikeshed: (sial, itu tidak berhasil - tidak ada emoji yang bagus)

mungkin relative_close, atau rel_close?

-
Anda menerima ini karena Anda disebutkan.
Balas email ini secara langsung, lihat di GitHub
https://github.com/numpy/numpy/issues/10161#issuecomment-350886540 , atau bisukan
utasnya
https://github.com/notifications/unsubscribe-auth/AAlOaNquy47fsOkvBlxcSa-Mxyhgdimlks5s_bORgaJpZM4Q2J-P
.

Maksud Anda # 3183?

assert_allclose sebenarnya menggunakan atol = 0 secara default.

Menarik - itu membuatku merasa lebih baik.

Ini membawa kembali ingatan kabur tentang diskusi masa lalu tentang perbedaan antara keduanya - apakah itu satu-satunya?

Hai,
Pustaka thermo, fluids, dan ht saya menggunakan banyak assert_allclose dari numpy, jadi saya berbagi beberapa pemikiran di sini karena terkait. Utas ini membuat perbedaan perilaku tampak sangat mengkhawatirkan, dan sepertinya orang akan menemukan bug dalam kode mereka karena kurangnya simetri dan / atau perbedaan dalam menggabungkan atol dan rtol serta atol default (tidak ada di assert_allclose , Aku tahu). Jadi saya ingin melihat apakah perpustakaan saya memiliki bug, dan meretas implementasi assert_allclose yang sangat kasar yang kemudian saya ubah pengujian saya untuk digunakan sementara.

Saya pikir penggunaan assert_allclose saya representatif - Saya membandingkan nilai yang dipilih secara individual, dan melakukan tes di mana saya mengaburkan hal-hal dan memanggil assert_allclose pada hasil fungsi secara parametrik. Saya membandingkan int dan float dari semua jenis besaran. Saya relatif sedikit berpikir untuk memilih rtol atau atol, hanya jarang menambahkan atol atau mengubah rtol ke default yang kurang ketat. Pustaka memanggil assert_allclose 13159, 1178, dan 4243 kali masing-masing.

Jadi saya membuat perubahan, dan saya menjalankan tes tes saya. Saya sangat senang untuk mengatakan bahwa saya tidak menemukan bug baru atau kegagalan pengujian ; satu-satunya kegagalan pengujian yang dapat saya temukan adalah dengan penerapan assert_allclose saya.

Saya tahu ada orang lain yang kurang beruntung, dan mengalami masalah jika ada yang berubah di assert_allclose atau isclose. Saya pribadi akan merasa lebih nyaman menulis tes jika saya memiliki mode assert_allclose yang mereplikasi perilaku math.allclose, apakah itu melalui fungsi lain atau symmetric flag. Tapi saya tahu itu banyak pekerjaan yang harus dilakukan seseorang dan belum ada dan PR juga. Saya senang mendapatkan kenyamanan memeriksa kode saya untuk kesalahan ini meskipun sekali!

4880 adalah salah satu yang saya pikirkan.

Pada 11 Desember 2017, pukul 17:01, Nathaniel J. Smith [email protected]
menulis:

4880 https://github.com/numpy/numpy/pull/4880 adalah yang saya pikirkan

dari.

Terima kasih, Perhatikan bahwa contoh statsmodel menjelaskan maksud saya dengan baik tentang
default atol - apa pun selain 0,0 berbahaya.

Apakah fakta bahwa ini muncul setiap beberapa tahun menunjukkan bahwa kita harus melakukannya
akhirnya melakukan sesuatu tentang itu?

Mungkin memang begitu. Ini kutil kecil, tapi terkadang gangguan kecil itu bertambah
up seiring waktu.

Dan sementara saya senang bahwa assert_allclose memiliki atol default ke nol
(mendukung pendapat saya bahwa itu adalah pilihan yang dapat diterima, bahkan jika Anda tidak melakukannya
setuju itu adalah pilihan terbaik) banyak dari kita - dan lebih banyak lagi sepanjang waktu - tidak
menggunakan unittest, dan karenanya dapat menggunakan np.all_close secara langsung dalam pengujian.

Dan ya Ralf, jika kami melakukan perubahan, kami ingin mengubah ketiganya
fungsi terkait erat :-(. Tapi itu memberi kita kesempatan untuk membuatnya
lebih konsisten, bonus?

Sementara transisi py2-3 belum berjalan dengan baik, ada sesuatu yang akan terjadi
mengatakan memiliki versi "tidak apa-apa untuk membersihkan kutil" di beberapa titik :-)

Ada pilihan lain, untuk benar-benar memindahkan is_close ke versi matematika (yang memang lebih baik) dari atol=0 : ubah default ke None , dan coba dengan atol=0 ; jika semua True hanya kembali; jika beberapa False , coba lagi dengan standar atol dan jika hasil berubah mengeluarkan peringatan penghentian (dan mengembalikan hasil "lama").

Sayangnya, seseorang tidak dapat melakukan kedua simetri dan atol pada saat yang sama, karena keduanya menuju ke arah yang berbeda (yaitu, seseorang harus selalu menjalankan kedua kasus tersebut, yang tampaknya sedikit berlebihan). Tapi saya tidak suka default atol lebih dari kurangnya simetri ...

Saya tidak mendukung mengubah fungsi apa pun kecuali ada fungsi itu
Anda dapat menggunakan yang memiliki perilaku lama. Selain itu, harus ada file
alat refactoring otomatis untuk membuat perubahan ini jika selesai. Namun itu tidak benar
bahkan di atas meja sekarang.

Transisi py3k bukanlah sesuatu yang kami ingin miliki lagi dan itu
bukan panutan. Menggulirkan pembersihan menjadi satu rilis besar bukanlah hal yang baik
mendekati IMO.

Sementara transisi py2-3 tidak berjalan dengan baik, ada sesuatu yang harus dikatakan untuk memiliki versi "tidak apa-apa untuk membersihkan kutil" di beberapa titik :-)

Hanya untuk mengatasi ide umum bahwa nomor versi khusus dapat membuat breaking perubahan OK: aturan umum adalah bahwa itu ok untuk membersihkan kutil, jika ada rencana transisi yang jelas yang menghindari tingkat yang tidak dapat diterima dari rasa sakit dan manfaat yang cukup untuk membenarkan biaya. Poin kuncinya di sini adalah bahwa penilaiannya harus dalam hal efek pada pengguna, bukan apakah kita "mengikuti aturan". (Jika Anda ingin menjadi mewah, kami adalah konsekuensialis , bukan deontologis .) Jadi, satu-satunya alasan untuk menyatakan versi tertentu menjadi "ini yang merusak barang" adalah jika membuat hal-hal secara substansial lebih mudah untuk ditangani oleh pengguna. Manfaat IMO dari menggabungkan perubahan pemecah bersama umumnya kecil jika ada sama sekali - kode yang rusak adalah kode yang rusak - dan bahkan jika ada, sangat jarang bahwa mereka akan memberi tip analisis biaya / manfaat dari "tidak" menjadi " Iya".

atol bukan nol menjadi default - Saya sebenarnya berpikir ini adalah masalah terbesar (terutama dengan algoritma saat ini untuk menambahkan keduanya) karena dapat dengan mudah menyebabkan kelulusan tes yang seharusnya tidak - dan terlalu sering kita sedikit malas - kami menulis tes dengan toleransi default, dan jika lolos, kami pikir kami sudah selesai. (ketika saya menyadari bahwa begitulah cara kerjanya, saya kembali ke kode y, dan DID menemukan beberapa dari mereka - ups!

Perhatikan bahwa contoh statsmodel menjelaskan maksud saya tentang default atol - apa pun selain 0,0 berbahaya. [...] banyak dari kita - dan lebih banyak lagi sepanjang waktu - tidak menggunakan unittest, dan karenanya dapat menggunakan np.all_close secara langsung dalam pengujian.

"Kami harus memecahkan kode pengguna untuk meningkatkan konsistensi dengan beberapa paket lain" tidak mendapat skor yang baik pada skala biaya / manfaat. "Ada ketidakkonsistenan di dalam numpy yang tidak hanya membingungkan, tetapi juga membingungkan dengan cara yang secara langsung mengarah ke bug diam dalam kode pengguna, dan kami dapat memperbaikinya" jauh lebih menarik. Saya sendiri belum membentuk opini, tetapi jika Anda ingin mendapatkan kemajuan di sini maka inilah yang akan saya dorong.

Sebuah catatan:

"" "Saya relatif sedikit berpikir untuk memilih rtol atau atol,
jarang menambahkan atol
-menggunting-

$ call assert_allclose 13159, 1178, dan 4243 kali masing-masing.

-menggunting-

Saya tidak menemukan bug baru atau kegagalan pengujian ;

"" "

Kabar baik, meskipun saya perhatikan bahwa assert_allclose memiliki atol default ke nol. Dan
ini sebabnya :-)

@njsmith menulis:

"Kita harus memecahkan kode pengguna untuk meningkatkan konsistensi dengan beberapa paket lain"

Saya tidak berpikir siapa pun di utas ini menganjurkan hal itu - saya yakin tidak. Satu-satunya konsistensi yang diadvokasi adalah konsistensi di antara fungsi numpy terkait.

"Ada ketidakkonsistenan di dalam numpy yang tidak hanya membingungkan, tetapi juga membingungkan dengan cara yang langsung mengarah ke bug diam dalam kode pengguna, dan kami dapat memperbaikinya"

ITULAH apa yang saya, setidaknya saya dukung. Dan saya pikir kebanyakan orang lain.

Masalahnya adalah kita tidak dapat memperbaikinya tanpa:

Mematahkan kompatibilitas mundur, yang menurut saya tidak ada yang menganggap ini cukup serius untuk dilakukan - bahkan dengan siklus penghentian.

Atau

Membuat bendera atau fungsi baru.

Saya pikir fungsi baru akan menjadi cara yang lebih bersih untuk melakukannya. Kode lama dapat tetap tidak berubah selama diinginkan, kode baru dapat menggunakan fungsi baru, dan pencarian dan penggantian (atau beberapa impor sebagai panggilan) dapat memudahkan untuk berpindah satu file pada satu waktu.

(Saya kira Anda bahkan bisa menambal monyet numpy di kode uji Anda ....)

Kami sudah memiliki:

  • allclose
  • assert_allclose
  • assert_almost_equal
  • assert_approx_equal
  • assert_array_almost_equal
  • assert_array_almost_equal_nulp
  • assert_array_max_ulp

Saya tidak berpikir menambahkan lebih banyak opsi ke daftar ini sebenarnya tidak akan membuat banyak perbedaan bagi pengguna nyata.

Yah, saya menghabiskan BANYAK waktu untuk memikirkan, dan berdebat tentang math.isclose, dan kami memang mulai dengan melihat implementasi numpy di antara yang lain. jadi, ya, saya rasa pendekatan itu lebih baik.

Begitu pula saya, dan saya telah menjadi salah satu pengelola utama numpy.testing - ini bukanlah masalah baru. Memaksa dengan huruf kapital bahwa Anda benar tidak membuatnya jadi demikian.

Mungkin maksud Anda memiliki fungsi lama dan baru, lebih baik, di numpy TIDAK lebih baik, daripada membiarkan fungsi lama (mungkin lebih baik didokumentasikan) di sana. Tentu, itu poin yang benar-benar valid, tapi saya mencoba untuk berdiskusi,

Memang, harus jelas bahwa itulah yang saya maksud.

"Memperkenalkan fungsi baru dengan perilaku yang hanya sedikit berbeda dari fungsi lain yang telah bekerja seperti itu selama satu dekade pada umumnya adalah ide yang sangat buruk" sepertinya menutup diskusi

Tidak, ini menunjukkan masalah nyata dengan menambahkan fungsi baru yang terlalu sering diabaikan atau tidak diberi bobot yang cukup. Dalam hal ini tampaknya cukup jelas bagi banyak pengembang inti - sepertinya Anda mendapatkan penilaian bahwa kapal ini telah berlayar dari @njsmith , @pv , @charris , dan saya.

Saya mohon maaf sebelumnya karena mengulangi ini, tetapi assert_allclose adalah perilaku yang benar (atau setidaknya cukup dekat dengannya). Namun, isclose dapat membuat orang mendapat masalah karena mengasumsikan toleransi mutlak seperti yang dicatat orang lain. Saya sedang mempertimbangkan untuk mengirimkan PR untuk meletakkan kotak merah besar pada halaman dokumentasi np.isclose untuk memperingatkan orang-orang tentang perilaku ini. Bagaimana kedengarannya?

Saya mohon maaf sebelumnya karena mengulangi hal ini, tetapi assert_allclose adalah
perilaku yang benar (atau setidaknya cukup dekat dengannya). Namun, isclose mungkin saja didapat
orang menjadi masalah karena mengasumsikan toleransi mutlak seperti yang dimiliki orang lain
dicatat. Saya sedang mempertimbangkan untuk mengirimkan PR untuk meletakkan kotak merah besar di
halaman dokumentasi np.isclose untuk memperingatkan orang-orang tentang perilaku ini. Bagaimana
suara itu?

+1

Saya ada konsensus bahwa dokumen harus lebih baik.

Terima kasih,

-CHB

-
Anda menerima ini karena Anda disebutkan.
Balas email ini secara langsung, lihat di GitHub
https://github.com/numpy/numpy/issues/10161#issuecomment-351182296 , atau nonaktifkan
utasnya
https://github.com/notifications/unsubscribe-auth/AA38YDw4sdhRWYmeeyr4met1RCwWsjMQks5s_uBmgaJpZM4Q2J-P
.

Saya mendukung peningkatan dokumentasi, tetapi menurut saya perubahan yang diusulkan tidak sebisa mungkin.

.. peringatan :: Default atol tidak sesuai untuk nomor itu
jauh lebih sedikit dari satu.

Pertama, peringatan ini bahkan tidak benar, secara umum. Default atol _is_ sesuai jika Anda ingin memperlakukan angka yang lebih kecil dari 1e-8 sama dengan nol. Ini tidak mungkin dengan toleransi relatif, itulah sebabnya ada toleransi absolut. Sebaliknya, default atol _tidak sesuai jika Anda ingin memperlakukan angka yang lebih kecil dari 1e-8 sebagai bermakna. Jangan berasumsi bahwa satu ukuran cocok untuk semua.

Oleh karena itu, @xoviat , dengan rasa hormat yang terdalam, saya sangat keberatan dengan pernyataan subjektif Anda:

... assert_allclose _is_ perilaku yang benar (atau setidaknya cukup dekat dengannya).

Saya pikir masalah dengan dokumen saat ini, adalah bahwa ia melakukan pekerjaan yang sangat baik dalam menjelaskan _what_ atol ada, tetapi tidak menjelaskan _why_ itu ada, dan oleh karena itu pengguna mungkin tidak mengerti kapan harus mengubah nilai default .

Saya mengusulkan sesuatu di sepanjang baris:

"Menetapkan nilai bukan nol kecil dari atol memungkinkan seseorang untuk memperlakukan angka yang sangat mendekati nol secara efektif sama dengan nol. Oleh karena itu, nilai default atol mungkin tidak sesuai untuk Anda gunakan kasus. Pilih atol sedemikian rupa sehingga angka yang lebih besar dari atol dianggap oleh Anda bermakna (berbeda dari nol), dan angka yang lebih kecil dari atol dianggap oleh Anda sebagai dapat diabaikan (sama dengan nol). "

Terakhir, saya akan menambahkan catatan yang sama ke docstrings isclose dan allclose .

Ini saran saya. Ambil atau tinggalkan.
Bersulang.

Silakan tinggalkan umpan balik ulasan di PR. Secara khusus, proposal Anda IMO terlalu bertele-tele.

Maaf semua jika saya terlalu menyebalkan - saya benar-benar belum berpikir ada konsensus.

@xoviat : terima kasih telah mengerjakan

Karena ini akan muncul lagi, saya akan (mungkin) mengakhiri diskusi ini dengan versi mini NEP yang dirancang untuk ditolak - meringkas proposal dan alasan penolakan. Sebagai catatan - karena masalah sebelumnya agak mereda.

Maaf telah mengemukakan masalah py2 / 3 - apakah / bagaimana membersihkan kutil di numpy adalah diskusi untuk tempat dan waktu lain.

Masalah dengan isclose()

Masalah ini (dan referensi lainnya) adalah hasil pengamatan bahwa numpy.isclose() dan teman-teman menggunakan algoritme yang kurang optimal, memiliki default yang diperdebatkan untuk atol, dan berbagai fungsi terkait memiliki default yang berbeda. Keseluruhan ini menghasilkan kebingungan bagi pengguna, dan dalam kasus terburuk, tes positif palsu ketika pengguna tidak bijaksana untuk menyetel nilai atol .

Secara khusus, implementasi di stdlib: math.isclose() , menyediakan algoritma dan default yang berbeda, dan bisa dibilang lebih baik: ini adalah tes simetris, tidak mencampur rtol dan atol, dan atol default adalah 0.0

Hampir ada konsensus bahwa situasinya tidak ideal, tetapi tidak ada konsensus bahwa itu cukup buruk untuk melakukan apa pun.

Pilihan dipertimbangkan:

Mengubah algoritma dan / atau default:

Ditolak secara universal karena masalah kompatibilitas ke belakang, bahkan dengan periode penghentian dan peringatan - fungsi ini banyak digunakan dalam pengujian, jadi setidaknya akan menjadi gangguan besar.

Menambahkan parameter ekstra dengan bendera untuk memilih algoritma yang berbeda

Ini tidak akan merusak kode yang ada, tetapi akan bertahan selamanya dengan API yang jelek dan membingungkan.

Menambahkan direktif __future__ - type

TLDR: itu mungkin, tapi tidak mudah atau bersih. Sepertinya tidak ada yang ingin mengejar ini.

Menciptakan fungsi lain

Yang satu ini tampaknya menjadi satu-satunya pilihan yang mendapatkan daya tarik, tetapi tidak didukung oleh pengembang inti yang berpartisipasi dalam diskusi.

Cara paling bersih untuk "memperbaiki" ini adalah dengan menambahkan np.rel_close() [atau nama lain] dengan algoritme dan default baru, kemungkinan besar yang digunakan di math.isclose . Fungsi baru akan didokumentasikan sebagai yang "direkomendasikan" untuk digunakan untuk kode masa depan. Dimungkinkan untuk menambahkan peringatan deprecation ke yang lama di masa depan - tetapi sepertinya tidak ada yang berpikir kebisingan akan sepadan pada saat ini.

Alat pemfaktoran ulang dapat dibuat untuk membuat penggantinya - tetapi siapa yang akan melakukannya untuk penggunaan yang satu ini?

Hal ini mungkin akan menghasilkan dua fungsi yang sangat mirip di masa mendatang, dan "Memperkenalkan fungsi baru dengan perilaku yang hanya sedikit berbeda dari fungsi lain yang telah bekerja seperti itu selama satu dekade secara umum adalah ide yang sangat buruk."

Kesimpulan:

Tidak sepadan dengan keuntungan kecil, tetapi dokumen yang lebih baik sudah diatur, dan itu dilakukan di sini: # 10214

Saya masih memiliki satu pertanyaan:

@njsmith menulis:

"" "
Kami sudah memiliki:

allclose
assert_allclose
assert_almost_equal
assert_approx_equal
assert_array_almost_equal
assert_array_almost_equal_nulp
assert_array_max_ulp

Saya tidak berpikir menambahkan lebih banyak opsi ke daftar ini sebenarnya tidak akan membuat banyak perbedaan bagi pengguna nyata.
"" "

Apakah maksud Anda menambahkan yang baru akan menjadi ide yang bagus?

Saya juga akan mencatat:

sebagian besar adalah asserts - dan proliferasi asserts adalah efek samping dari arsitektur unittest.

Karena banyak dari kita pindah ke arsitektur pengujian lain (misalnya pytest), kebutuhan akan pernyataan hilang.

Jadi apa yang dilakukan dengan numpy.testing adalah pertanyaan terpisah dari apa yang harus dilakukan dengan numpy core.

Karena banyak dari kita pindah ke arsitektur pengujian lain (misalnya pytest), kebutuhan akan pernyataan hilang.

Sebenarnya, ini sendiri merupakan bahaya. Tes dapat diubah dari assert_allclose(...) menjadi assert np.allclose(...) , dan secara diam-diam akan menjadi kurang ketat, yang merupakan hal yang buruk.

Saya masih menggunakan assert_allclose di lingkungan pytest karena memberikan pesan kegagalan yang berguna:

    def test_shs():
        a = [0.1, 0.2, 0.3, 0.4]
        b = [0.2, 0.3, 0.3, 0.4]

>       np.testing.assert_allclose(a,b)
E       AssertionError: 
E       Not equal to tolerance rtol=1e-07, atol=0
E       
E       (mismatch 50.0%)
E        x: array([ 0.1,  0.2,  0.3,  0.4])
E        y: array([ 0.2,  0.3,  0.3,  0.4])

vs menggunakan assert np.allclose()

    def test_shs():
        a = [0.1, 0.2, 0.3, 0.4]
        b = [0.2, 0.3, 0.3, 0.4]
>       assert np.allclose(a, b)
E       assert False
E        +  where False = <function allclose at 0x7f20b13c9840>([0.1, 0.2, 0.3, 0.4], [0.2, 0.3, 0.3, 0.4])
E        +    where <function allclose at 0x7f20b13c9840> = np.allclose

Mungkin mungkin untuk memperbaikinya dengan mengimplementasikan pytest_assertrepr_compare , tetapi saya tidak yakin bagaimana menerapkannya ke pemanggilan fungsi, dan tidak dapat menentukan di mana pytest bahkan memanggilnya.

@ eric-wieser: menulis:

"Sebenarnya, ini sendiri merupakan bahaya. Pengujian mungkin diubah dari assert_allclose (...) menjadi assert np.allclose (...), dan secara diam-diam akan menjadi kurang ketat, yang merupakan hal yang buruk."

Persis maksud saya - itu adalah "Ide Buruk" untuk mengasumsikan bahwa setiap orang akan menggunakan pernyataan untuk pengujian, dan dengan demikian tidak peduli dengan apakah default isclose () dan allclose () sesuai untuk pengujian - dalam ideal dunia mereka pasti seharusnya.

Apakah maksud Anda menambahkan yang baru akan menjadi ide yang bagus?

Tidak, maksud saya mengingat kami sudah memiliki banyak cara yang sedikit berbeda untuk mengekspresikan tes yang hampir sama, sayangnya sebagian besar pengguna tidak akan memperhatikan atau memahami tambahan lain.

Saya juga akan mencatat:
sebagian besar adalah asserts - dan proliferasi asserts adalah efek samping dari arsitektur unittest.
Karena banyak dari kita pindah ke arsitektur pengujian lain (misalnya pytest), kebutuhan akan pernyataan hilang.

Mereka kebetulan ditulis sebagai asserts, tetapi AFAICT masing-masing dari fungsi tersebut sebenarnya mengkodekan definisi yang berbeda dari "hampir sama". (Saya pikir. Beberapa perbedaan sangat tidak jelas sehingga saya tidak tahu apakah itu nyata atau tidak.)

Mengubah algoritma dan / atau default:
Ditolak secara universal karena masalah kompatibilitas ke belakang, bahkan dengan periode penghentian dan peringatan - fungsi ini banyak digunakan dalam pengujian, jadi setidaknya akan menjadi gangguan besar.

Saya tidak akan cukup mengatakan seperti itu. Bagi saya, ini adalah satu-satunya pendekatan yang berpotensi memiliki manfaat yang cukup untuk membenarkan biaya. Saya tidak mengatakan bahwa mereka akan melakukannya , dan saya tidak dapat berbicara untuk pengembang inti lainnya; Saya ingin melihat beberapa data, dan tanpa data, melakukan kesalahan di sisi konservatisme sepertinya pilihan yang tepat. Tetapi jika seseorang menghasilkan data, setidaknya saya akan melihatnya :-).

Seperti, jika seseorang muncul dan berkata, "Saya mencoba perubahan yang saya usulkan pada 3 proyek besar, dan itu menyebabkan 12 kegagalan tambahan dari 10.000 pengujian, dan dari 12 itu, 8 di antaranya adalah bug diam yang sebenarnya telah disembunyikan oleh yang lama. default buruk "... itu akan cukup meyakinkan. Terutama karena ini adalah kasus di mana kami memiliki kemampuan teknis untuk melakukan peringatan yang ditargetkan secara sempit. Saya menduga angka sebenarnya tidak akan terlalu menguntungkan, tetapi sampai seseorang memeriksa, siapa tahu.

Pada hari Senin, 18 Desember 2017 jam 15.57, Nathaniel J. Smith <
[email protected]> menulis:

Tidak, maksudku mengingat kita sudah memiliki seluruh kebun binatang
cara yang sedikit berbeda untuk mengekspresikan tes yang hampir sama, sayangnya
sebagian besar pengguna tidak akan melihat atau memahami tambahan lainnya.

Ada satu perbedaan besar - masing-masing ditambahkan karena memang begitu
sesuatu yang berbeda , dan dengan keanehan floating point, itu
perbedaan bisa jadi penting.

Fungsi relative-closeness yang baru pada dasarnya akan melakukan hal yang sama, tetapi
lakukan dengan lebih baik". Dan tujuannya adalah untuk merekomendasikan agar yang baru digunakan
bukannya yang lama (dan mungkin menghilangkan yang lama pada akhirnya).

Sejujurnya, saya tidak yakin apakah itu argumen yang mendukung atau menentang gagasan tersebut,
meskipun.

Seperti, jika seseorang muncul dan berkata, "Saya mencoba perubahan yang saya usulkan pada 3 besar

proyek, dan itu menyebabkan 12 kegagalan tambahan dari 10.000 pengujian, dan dari itu
12, 8 dari mereka adalah serangga diam yang sebenarnya telah disembunyikan oleh penjahat lama
defaults "... itu akan cukup meyakinkan. Terutama karena ini adalah file
kasus di mana kami memiliki kemampuan teknis untuk melakukan peringatan yang ditargetkan secara sempit.
Saya menduga angka sebenarnya tidak akan terlalu menguntungkan, tapi sampai
seseorang memeriksa, siapa tahu.

hmm, basis kode saya memiliki sekitar 1500 tes - bukan 10.000, tetapi saya akan memberikannya a
tembakan. Jika tidak ada yang lain, saya mungkin menemukan satu atau dua bug atau tes yang buruk. Atau dapatkan lebih banyak
jaminan!

Hai semua,

Ingin berpadu di sini setelah rekan kerja mengalami masalah ini.

_Penafian: Saya tidak terlalu memikirkan logika tersebut sebelum meneriakkan "api di aula" dan melemparkan ini melewati pagar. Jika saya telah membuat hash yang memalukan tentangnya, bersikaplah baik hati, cantiklah._

Bagi saya, ini semua terdengar sangat mirip dengan masalah arsitektur / desain klasik "ayam & telur" - semantik vs implementasi. Tidak semua bug ada di dalam kode, terkadang ada di dalam semantik. Ini tidak jauh berbeda (jika sama sekali) dari algoritme yang diimplementasikan dengan sempurna hanya untuk menemukan bahwa algoritme itu cacat - bug tidak ada dalam kode, ada dalam algoritme, tetapi bagaimanapun juga, itu masih bug. Pada dasarnya, diskusi ini terdengar seperti lelucon klasik “itu bukan bug, itu fitur”. Tentu saja, "pilihan" hanyalah itu, tetapi IMHO ini biasanya menandakan akhir dari alasan - jika semantik dipilih untuk apa adanya, seperti yang diterapkan, maka biarlah, implementasinya keren, akhir diskusi.

Jadi apa semantik "yang diinginkan" dan / atau "diharapkan" dari isclose() . Memikirkan hal ini, saya dibiarkan menyatu secara tak terelakkan pada semantik yang ditentukan pengguna, yaitu pengguna harus dapat mendefinisikan semantik definisi "dekat".

Default

Mengenai default, ini pada akhirnya tidak merusak semantik apa pun. Namun, pilihan yang buruk _is_ berbahaya. Jika default bukan nol adalah _only_ dipilih untuk memberikan perilaku yang wajar ketika abs(a - b) == 0 maka ini pasti terdengar seperti solusi yang salah. Keadaan khusus ini akan lebih baik menjadi cangkang khusus karena cased khusus semantik. Tidak ada "ruang gerak" dalam definisi "tutup" jika perbedaannya nol, itu adalah batu penjuru yang menentukan sendiri, yaitu mereka bukan _close_, mereka _exact_ - di mana "dekat" adalah penyimpangan relatif dari tepat . (_Catatan: _ Kondisi casing khusus mungkin (atau mungkin tidak) memengaruhi performa.)

+ vs max

Pencampuran atau "shadowing" dari rel_tol dan a_tol karena implementasi menggunakan jumlah dan bukan max _does_ merusak semantik fungsi di atas. Definisi pengguna tentang "dekat" terikat dengan cara yang tidak sepele karena merusak, dan oleh karena itu merusak, semantik "relatif" dan "mutlak". Dengan hanya mempertimbangkan semantik di atas, aspek ini _adalah bug. Saya menemukan @gasparka Contoh pembuka argumen yang tak terbantahkan tentang hal ini.

Komutatifitas (yaitu simetri)

Hanya ada dua operator di sini: - di a-b , dan <= dalam |a-b| <= f(a, b, atol, rtol) . Sementara pengurangan itu antikomutatif, |a - b| bukan, itu komutatif, menurut definisi. Namun, ini saja mungkin tidak cukup untuk menyatakan komutatif f(a, b, atol, rtol) . Namun ada argumen yang kuat dan lemah di sini.

  • Yang lemah adalah yang paling sederhana - enkapsulasi pemisahan fungsi atau kurangnya - sementara secara aritmatik komutatifitas |a - b| mungkin tidak memaksakan f(a, b, atol, rtol) , secara terprogram, f(a, b, atol, rtol) tidak benar-benar ada pertanyaan tapi isClose(a, b, atol, rtol) . Di sini komputasi |a - b| dilakukan secara internal ke fungsi yaitu isClose() := |a-b| <= f(a, b, atol, rtol) . Karena ini internal dan a dan b dilalui, untuk |a-b| menjadi komutatif isClose() juga harus. Jika tidak, komutatifitas |a-b| semuanya berarti.
  • Argumen yang kuat: Operasi perbandingan tidak ketat, yaitu <= bukan < , oleh karena itu untuk bagian persamaan dari perbandingan Anda harus memenuhi |a-b| = f(a, b, atol, rtol) yang berarti f(a, b, atol, rtol) _must_ juga bersifat komutatif (menurut saya?). Gagal melakukannya berarti persamaan di atas adalah _never_ true (tidak ada nilai a & b yang memenuhi ini) atau ketidaksetaraan yang ketat, < , memiliki sebenarnya telah didefinisikan secara semantik, bukan?

Apa yang Anda lakukan (atau tidak lakukan) tentang semua atau sebagian dari ini adalah pertanyaan yang sepenuhnya terpisah.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat