<p>numpy.isclose против math.isclose</p>

Созданный на 5 дек. 2017  ·  78Комментарии  ·  Источник: 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)

Обратите внимание, что уравнение Numpy не является симметричным и коррелирует параметры atol и rtol , оба они плохие (IMO).

Вот ситуация, когда Numpy «неправильно» помечает два числа как равные:

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

Вот еще одна проблема симметрии этого случая:

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

Математическая версия Python выглядит пуленепробиваемой, стоит ли Numpy начать ее использовать? Есть ли преимущества использования версии Numpy?

57 - Close?

Самый полезный комментарий

@njsmith : спасибо, что

Немного истории: когда я предложил isclose для stdlib, мы определенно рассматривали numpy как предшествующий уровень техники. Если бы это был только я, я, возможно, использовал бы совместимый подход ради хорошей совместимости :-).

Но остальная часть сообщества считала более важным делать то, что «правильно» для Python, поэтому последовало долгое обсуждение ... Я попытался уловить большую часть момента в PEP, если вы хотите посмотреть.

Вот ссылка на numpy:

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

Вы можете видеть, что были высказаны те же соображения, что и в этом обсуждении.

В итоге были выделены три ключевых момента:

1) симметричный подход не вызовет удивления.

2) абсолютный допуск по умолчанию, вероятно, должен быть равен нулю, чтобы не делать никаких предположений о порядке величины аргументов.

3) разница между «слабым» и «сильным» тестами не имела значения при использовании с небольшими допусками, как и предполагаемый вариант использования.

В конце концов, я думаю, мы пришли к «лучшему» решению для math.isclose.

Но достаточно ли «лучше», чтобы нарушить обратную совместимость? Я так не думаю.

К сожалению, в большую часть numpy (и python) было добавлено много функций, потому что они были полезны, но без большого текущего обсуждения этих вещей, поэтому у нас есть много неоптимальных проектов. Это ожидается (и необходимо) для молодой библиотеки, и теперь нам просто нужно жить с этим.

@njsmith прав - я думаю, что очень немногие применения np.isclose () имеют допуски, установленные строгим анализом ошибок FP, а скорее методом проб ошибок с самим np.isclose ().

Однако я думаю, что более серьезной проблемой является значение по умолчанию atol - оно предполагает, что ваши аргументы имеют порядок 1, что может быть ОЧЕНЬ неправильным предположением, и поскольку это часто приводит к прохождению тестов, которые не должны , пользователи могут не заметить.

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

ай!

и да, причиной этого является atol :

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

Так что, вероятно, это хорошая идея - проложить путь вперед.

Мне нравится идея аргумента ключевого слова - кажется намного более простой, чем пытаться возиться с __future__ и т.п.

И тогда мы могли бы решить, хотим ли мы начать выдавать предупреждения об устаревании и в конечном итоге изменить многие версии по умолчанию ниже по течению ...

Все 78 Комментарий

Слишком поздно что-либо менять имхо.

Это одна из наиболее широко используемых функций в numpy (через assert_allclose ). Единственный путь для этого - выбрать другое имя.

Признаюсь, текущая реализация выглядит ошибкой. Обратите внимание, что использование max(abs(a), abs(b)) вместо abs(b) не нарушит никаких существующих тестов, оно просто ослабит условие в случае, если abs(a) > abs(b) .

По крайней мере, для этого нужно предупреждение в строке документации, что оно не соответствует встроенной

Как насчет добавления этого?

from numpy.__future__ import isclose

Кстати, это может быть идеей для управления версиями случайных чисел ...

Для пояснения, импорт на самом деле не будет import isclose, но включит новую семантику. Это было бы вычерпано в модуль.

Идея состоит в том, что мы можем позволить людям использовать правильную функцию, и в то же время нам не нужно нарушать какой-либо существующий код.

, импорт фактически не будет импортировать isclose, но включит новую семантику

Я не думаю, что это не импорт возможно. Просто выберите более длинное имя, например mathlike_ufunc s, которое также может охватывать remainder .

Обратите внимание, что from __future__ import print_function действительно создает print_function global

На самом деле, стиль импорта from __future__ import * может здесь не подходить - в python он влияет на _syntax_ на уровне файла, и сделать что-то подобное в numpy будет сложно

Исключения итератора не были изменением синтаксиса. Нам просто нужен небольшой модуль C для проверки пространства имен вызывающего модуля. Мы даже можем кэшировать модули, чтобы замедлить только время импорта, и только тривиально.

Вы правы - и true_division , очевидно, аналогичен isclose.

На самом деле это хороший способ избежать проблем в # 9444 в качестве альтернативы использованию операторов with для управления устаревшими функциями.

Давайте CC @ ChrisBarker-NOAA как создатель math.isclose .

ИМО, это довольно незначительная проблема. Обычно atol и rtol выбираются путем возни с ними, пока тесты не пройдут, и цель состоит в том, чтобы отловить ошибки, которые на порядок превышают допуски. Возможно, имеет смысл ослабить часть rtol как предложил @charris , но я действительно не думаю, что стоит использовать уловки самоанализа стека для этой крошечной настройки. И у нас все еще будет проблема, заключающаяся в том, что isclose часто вызывается косвенно такими вещами, как assert_allclose или различными сторонними помощниками по тестированию.

Я спросил в StackOverflow об использовании импорта стиля __future__ : https://stackoverflow.com/questions/29905278/using-future-style-imports-for-module-specific-features-in-python

TL; DR: это возможно, но непросто.

Самоанализ стека предназначен не только для этого, но и предлагается в качестве общей политики для изменения возвращаемых значений функций. Возникает вопрос: а в принципе это надо менять? Я действительно думаю, что если ответ положительный, период устаревания должен составлять как минимум несколько лет, учитывая широкое распространение. Python никогда не включал предыдущий модуль, но это один из вариантов, чтобы попытаться улучшить стабильность API, если есть спрос.

Другой метод - просто добавить это как параметр isclose(...,symmetric=True) или assert_allclose(symmetric=True) где по умолчанию будет False , текущая ситуация.

Я согласен с тем, что это небольшая проблема, когда вы не вкладываете смысл в значения rtol и atol , а просто настраиваете их для прохождения модульных тестов, как упоминалось @njsmith.

Однако иногда вы хотите сказать, что ошибка находится, например, в пределах 1% ( rtol=0.01 ).
В этом случае наихудшая ошибка измерения rtol составляет 100% ( rtol * abs(b) приближается к atol , затем atol + rtol * abs(b) ~= 2 * rtol * abs(b) ).

Это означает, что некоторые значения могут проходить с ошибкой ~ 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

Реализация идеи @charris сделает этот конкретный случай немного хуже, так как это еще больше ослабит сравнение, но все же того стоит, поскольку избавляется от проблемы симметрии и действительно имеет обратную совместимость.

ИМО, было бы лучше, если бы Numpy использовал функцию Math, но я понимаю, что изменение может быть слишком разрушительным и, возможно, неважным для большинства пользователей. Было бы полезно сделать возможность переключения между ядром isclose .

@njsmith : спасибо, что

Немного истории: когда я предложил isclose для stdlib, мы определенно рассматривали numpy как предшествующий уровень техники. Если бы это был только я, я, возможно, использовал бы совместимый подход ради хорошей совместимости :-).

Но остальная часть сообщества считала более важным делать то, что «правильно» для Python, поэтому последовало долгое обсуждение ... Я попытался уловить большую часть момента в PEP, если вы хотите посмотреть.

Вот ссылка на numpy:

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

Вы можете видеть, что были высказаны те же соображения, что и в этом обсуждении.

В итоге были выделены три ключевых момента:

1) симметричный подход не вызовет удивления.

2) абсолютный допуск по умолчанию, вероятно, должен быть равен нулю, чтобы не делать никаких предположений о порядке величины аргументов.

3) разница между «слабым» и «сильным» тестами не имела значения при использовании с небольшими допусками, как и предполагаемый вариант использования.

В конце концов, я думаю, мы пришли к «лучшему» решению для math.isclose.

Но достаточно ли «лучше», чтобы нарушить обратную совместимость? Я так не думаю.

К сожалению, в большую часть numpy (и python) было добавлено много функций, потому что они были полезны, но без большого текущего обсуждения этих вещей, поэтому у нас есть много неоптимальных проектов. Это ожидается (и необходимо) для молодой библиотеки, и теперь нам просто нужно жить с этим.

@njsmith прав - я думаю, что очень немногие применения np.isclose () имеют допуски, установленные строгим анализом ошибок FP, а скорее методом проб ошибок с самим np.isclose ().

Однако я думаю, что более серьезной проблемой является значение по умолчанию atol - оно предполагает, что ваши аргументы имеют порядок 1, что может быть ОЧЕНЬ неправильным предположением, и поскольку это часто приводит к прохождению тестов, которые не должны , пользователи могут не заметить.

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

ай!

и да, причиной этого является atol :

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

Так что, вероятно, это хорошая идея - проложить путь вперед.

Мне нравится идея аргумента ключевого слова - кажется намного более простой, чем пытаться возиться с __future__ и т.п.

И тогда мы могли бы решить, хотим ли мы начать выдавать предупреждения об устаревании и в конечном итоге изменить многие версии по умолчанию ниже по течению ...

Я хочу предложить предложение @bashtage :

"" "
Другой способ - просто добавить это как параметр isclose (..., symric = True) или assert_allclose (symric = True), где по умолчанию будет False, текущая ситуация.
"" "

Я думаю, что это лучший вариант, чем новое имя функции, и он может привести к будущему устареванию и изменению значения по умолчанию (или нет).

Я думаю, что в дополнение к (сильному) симметричному тесту atol умолчанию также должно быть равно нулю.

Учитывая это, возможно, нам нужно лучшее имя для параметра, чем symmetric , хотя это неплохо ...

О, и было бы неплохо убедиться, что isclose() не вызывается где-либо еще в numpy, кроме assert allclose() .

Самый простой способ сделать это - поставить предупреждение об устаревании и
затем удалите его перед объединением. Мы могли бы просто пойти дальше и поставить
предупреждение об устаревании, в котором говорится изменить существующий код на
симметричный = Ложь; нет причин говорить, что по умолчанию должно быть
изменится в ближайшее время, даже если есть предупреждение.

Нужно ли нам добавить его и в assert_allclose , или мы просто внесем изменения без уведомления? Заставить людей обновлять каждый из своих тестов, чтобы отключить предупреждение, на самом деле ничем не отличается от того, чтобы заставить их обновлять свои тесты, чтобы исправить снижение допуска.

@xoviat @ eric-wieser не может быть никаких обратно несовместимых изменений в assert_allclose или предупреждения об устаревании от него, это слишком разрушительно. Если мне не хватает места, где вы хотите разместить предупреждение об устаревании?

Боюсь, это все еще звучит как боль для бесконечно малых
выгода для меня.

Ненулевое значение atol по умолчанию - не случайность. Нужно получить
разумное поведение по умолчанию для любого теста, в котором ожидаемый результат включает
точные нули.

Никаких изменений в assert_allclose не требуется, так как он будет обновлен до
внутренне использовать старое поведение.

ИМО тихие изменения мерзки! Предупреждение об устаревании только для того, чтобы
в конечном итоге людям не нужно вводить флаг в интерактивной подсказке, чтобы
получить новое поведение, не более

ИМО тихие изменения мерзки!

Согласовано. Однако никаких изменений быть не должно. Предупреждения об устаревании в широко используемых функциях также вынуждают пользователей (по крайней мере, тех, кто действительно выполняет обслуживание) вносить изменения.

Как насчет исправления проблемы несимметрии, как предложил atol != 0.0 .

Мы не сможем решить эту проблему, не сообщив людям об изменении
поведение. Единственный способ, которым я знаю, как это сделать, - это предупреждение.

Что действительно было бы неплохо, так это инструмент автоматического рефакторинга для вставки флагов
в старый код. Тогда "обслуживание" будет просто запускать скрипт на вашем
код; 5 минут работы.

Извините, это можно исправить, просто установив новый флаг.

Как насчет исправления проблемы несимметрии, как предложил

Это предложение (https://github.com/numpy/numpy/issues/10161#issuecomment-349384830) кажется возможным.

Мы не можем решить эту проблему, не сообщая людям об изменении поведения.

Мы этого не исправляем. Это вопрос стоимости / выгоды любого изменения, который только что обсуждается в вопросе семантического управления версиями. Это определенно тот случай, когда мы не будем вносить какие-либо изменения или выдавать какие-либо предупреждения из широко используемой функции тестирования. Обратите внимание, что текущее поведение не является ошибкой (хотя, возможно, это неоптимальный выбор).

Для ясности, я предлагал изменить isclose, но не assert_allclose.
Судя по источникам, это изменение будет на треть разрушительным.
Однако польза все же, вероятно, слишком мала. Я никого не думаю
возражает против добавления флага, верно?

Я не думаю, что кто-то возражает против добавления флага, верно?

Не уверен, зависит от деталей. Предложение @charris может не требовать флага, и любой флаг, который вводит это, немного сомнителен для массивов:

In [1]: import math

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

Я против добавления флагов без конкретных мотивов и вариантов использования. Полезная лакмусовая бумажка: если бы начинающий разработчик спросил вас, почему существует этот флаг, как бы вы объяснили?

как бы вы объяснили?

  1. Используйте флаг symmetric=True если хотите векторизовать вызовы math.isclose
  2. Это должен был быть флаг, чтобы мы не нарушили существующий код.

Я больше ищу ситуации, когда решается какая-то реальная проблема.

Наверное, единственная актуальная проблема, которую здесь решают, - сделать новичков
подумайте больше о точности с плавающей запятой. Я имею в виду пример @rgommers
кажется, это было бы неправильно, но что, если вы имеете дело с очень маленькими
числа? IMO реализация math.isclose лучше, но я даже не
думаю, что есть консенсус по этому поводу. К сожалению, на самом деле нет
универсальное решение для определения того, являются ли числа «близкими». Но
основываясь на ответах других (которые не являются неправильными!), я действительно не
любые изменения в API в будущем. Я думаю, единственное, что нужно сделать, это
возможно обновление документации тогда (известные последние слова, учитывая, что я
ранее думал, что флаг будет в порядке)?

Конечно, примечание, сравнивающее с math.isclose и документирующее, как получить идентичное векторное поведение, установив rtol и atol, если хотите, было бы нормально.

Кроме того, если я правильно понимаю, @charris предложил решение, позволяющее
близок к тому, чтобы быть менее терпимым, чем сейчас, что не сломает
никаких тестов. Я все еще думаю, что было бы неплохо выдать предупреждение (
предупреждение должно быть выпущено один раз), если есть ситуация, когда isclose
Считайте числа «близкими», когда раньше не были. Это многолучше, чем просто молча менять поведение функции и не позволять
любой знает об этом, когда это их касается.

Я думаю, что здесь необходимы некоторые пояснения по поводу того, что мы обсуждаем. Есть две вещи, которые отличают math.isclose :

  • Другое значение по умолчанию для atol
  • Другое определение rtol

Я не думаю, что мы можем что-то сделать с первой проблемой, кроме как задокументировать ее как отличную от `math.isclose.

Вторую проблему, я думаю, лучше всего решить, добавив аргумент symmetric который по умолчанию равен False . Теперь мы можем написать в наших документах _ " np.isclose(x, y, symmetric=True, atol=0) - это векторизованная версия math.isclose(x, y) " _, которую, как мне кажется, мы пытаемся решить.

Отсюда у нас есть три варианта:

  1. Задокументируйте лишний аргумент и больше ничего не делайте
  2. Устарел вызов isclose без аргумента, заставляя пользователей писать isclose(..., symmetric=False) чтобы получить старое поведение без предупреждения (и аналогично для allclose ). Я подозреваю, что это не повредит слишком большому количеству кода, но результат будет менее читаемым без большого выигрыша. assert_close будет изменен на внутренний вызов isclose(..., symmetric=False) , поэтому пользователи не будут затронуты
  3. То же, что и выше, но также требует аргумента symmetric для assert_close . Это будет массовый отток клиентов
  4. Тихо измените поведение

Я считаю, что вариант 1 не вызывает возражений, но остальные не кажутся вещами, заслуживающими нарушения.

Изменить: 2 может быть приемлемым, если предупреждение выдается только в том случае, если поведение изменится, что будет намного менее шумным.

@ eric-wieser Есть третье отличие: способ совмещения atol и rtol . ( math.isclose использует max , numpy.isclose использует + ). Это означает, что если atol или rtol не равны нулю, не существует общего способа сделать вызов math.isclose вызову numpy.isclose .

Я все еще не думаю, что для этого стоит добавлять какие-либо видимые пользователю API.

Я был за второй вариант. Я по- прежнему за этот вариант, с
дополнительное условие, что numpy предоставит автоматизированный
инструмент рефакторинга (добавлен в entry_points), который вы можете просто запустить на своем
существующие проекты, чтобы исправить их. Судя по тому, что говорили другие, это звучит как
этот вариант не понравится другим.

Я не поддерживаю и никогда не поддерживаю ни третий, ни четвертый варианты. В
кроме того, я не сторонник изменения поведения функции до предупреждения
был выпущен как минимум для четырех основных выпусков.

Предполагая, что другие не согласны с вариантом два (который у них есть), я бы
в пользу первого варианта. Но другие (особенно @njsmith) не поддерживают
любого из вариантов, которые вы здесь указали. По крайней мере, так мне кажется.

@njsmith Это неверно; вы можете изменить поведение функции с помощью флага.

Я складываю это третье различие в формуляр _ "rtol is different" _

"" "
Я больше ищу ситуации, когда решается какая-то реальная проблема.
"" "
Я поставлю доллары на пончики (что я сделаю, потому что я понятия не имею, что это значит ...), что есть тесты, которые проходят, но не должны, потому что atol делает тест гораздо менее чувствительным, чем должно быть.

Кажется, с текущей реализацией есть три "проблемы":

1) это не симметрично

  • Я думаю, что это плохо, но на самом деле не имеет большого значения, и почти не имеет значения, когда значения действительно близки :-) Я _think_, это буквально не имеет значения, если rtol <1e-8 (по крайней мере, если atol равно 0,0)

2) атол влияет на результат, даже если он не сравнивается с нулем (что неизбежно) - но он эффективно изменяет допуск примерно в два раза - или даже больше, если атол большой, что может быть при работе с большим порядком значения величины.

3) atol ненулевое значение по умолчанию - я действительно думаю, что это самая большая проблема (особенно с текущим алгоритмом добавления обоих), так как это может очень легко привести к прохождению тестов, которые не должны - и слишком часто мы немного поленился - мы пишем тест с допуском по умолчанию, и если он проходит, мы думаем, что закончили. (когда я понял, как это работает, я вернулся к коду y и ДЕЙСТВИТЕЛЬНО нашел пару таких - упс!

Кто-то в этой ветке сказал что-то о том, что "что-то будет ломать, если:

isclose (1e-200, 0,0)

по умолчанию вернул False. Я не согласен - да, это было бы удивительно, но это заставило бы пользователя задуматься о том, что происходит, тогда как текущая реализация приводит (например):

В [8]: np.isclose (1e-20, 1e-10)
Out [8]: Верно

действительно? один на ДЕСЯТЬ ПОРЯДОВ МАГНИТУДЫ больше другого, и он возвращается Верно ????

Я хочу сказать, что ненулевое значение atol дает, возможно, менее удивительные результаты в обычном случае сравнения с нулем, но НАМНОГО более опасные и неправильные результаты при работе с небольшими числами (small на самом деле означает что-то меньшее на порядок величины 1.

И если вы работаете с большими числами, скажем больше 1e8, то атол по умолчанию также не подходит.

И в сочетании с (2) это означает, что атол по умолчанию также может неожиданным образом испортить тесты относительной устойчивости.

Итак: нет, это не ошибка, и он не "сломан", но довольно неоптимален, поэтому было бы неплохо найти путь к лучшей реализации.

Мне понравился подход флага, но я думаю, что передумал - проблема в том, что если мы не откажемся от него и не изменим флаг по умолчанию в какой-то момент, у нас просто будет почти каждый, использующий «старый» алгоритм почти навсегда. И было много хороших аргументов, почему мы, вероятно, не можем отказаться от него.

Так что, возможно, потребуется новая функция с новым именем. Мы могли бы добавить в документацию, поощряющую людей использовать новую, и _могут_ добавить предупреждения в какой-то момент, когда люди будут использовать новую, но мы никогда не сломаем чей-либо код.

У кого-нибудь есть идея хорошего имени для новой функции ????

Может, np.math.isclose и друзья? Я не знаю.

Это решает проблему np.remainder , а также позволяет легко векторизовать код с помощью from numpy import math

Так что я был бы +1 на модуле np.math

Вводить новые функции, поведение которых лишь немного отличается от поведения других функций, которые работали подобным образом в течение десятилетия, в общем, очень плохая идея. В этом случае действительно не так много проблем, которые нельзя адекватно решить с помощью документации. Итак, -1 для новой функции. И определенно -1 в совершенно новом подмодуле.

действительно? один на ДЕСЯТЬ ПОРЯДОВ МАГНИТУДЫ больше другого, и он возвращается Верно ????

Истинно ли ваше ожидание или нет, полностью зависит от контекста. Если это для чисел, полученных из непрерывного распределения на [0, 1), тогда да, вы, вероятно, ожидаете True. Пользователь действительно должен понимать абсолютные / относительные допуски и то, что на самом деле делает функция, и для этого нужны документы.

symmetric_isclose() немного затянуто, но не оскорбительно для моих глаз.: bikeshed: emoji>

10 декабря 2017 г. в 20:09 Ральф Гоммерс [email protected] написал:

Представляем новые функции, поведение которых лишь немного отличается от других
функции, которые работали так в течение десяти лет, в целом очень плохие
идея.

Мне это тоже не нравится - но взламывать код людей с изменением хуже.
У вас есть идея, кроме простой не делать numpy лучше?

В этом случае действительно не так много проблем, которые нельзя было бы адекватно решить.
решается с помощью документации.

Я не согласен - значения по умолчанию очень важны.

И я не думаю, что есть способ отрегулировать параметры, чтобы дать вам
симметричное сравнение.

И определенно -1 в совершенно новом подмодуле.

Я тоже. Если в математическом модуле есть другие вещи без numpy
эквиваленты, которые были бы полезны, их можно было бы добавить в пространство имен numpy
как и все остальное.

действительно? один на ДЕСЯТЬ ПОРЯДОВ МАГНИТУДЫ больше другого, и он возвращается
Правда????

Истинно ли ваше ожидание или нет, полностью зависит от контекста.

Именно поэтому «разумного» дефолта для атола НЕТ.

Если это для чисел, полученных из непрерывного распределения на [0, 1)
тогда да, вы, вероятно, ожидаете True.

Но isclose рекламируется как относительное сравнение - и здесь
относительность полностью стирается из абсолютного сравнения,
без того, чтобы пользователь думал об этом.

В этом вся моя точка зрения - значение по умолчанию подходит ТОЛЬКО, если вы ожидаете
значения должны быть порядка 1. Обычный случай, конечно, но не
универсальный.

Это сводится к тому, что хуже - ложноотрицательный или ложноположительный.
А в обычном случае тестирования ложное срабатывание намного хуже.

(т.е. прохождение теста, которого не должно быть)

Пользователь действительно должен понимать абсолютные / относительные допуски и
функция действительно делает,

Безусловно, но функция также должна иметь разумные значения по умолчанию и
надежный алгоритм, который легко понять.

Я стремлюсь улучшить документацию и оставить функцию в покое. Отсутствие симметрии можно объяснить следующим образом: «isclose (a, b) означает, что a близко к b, но из-за разной абсолютной точности с плавающей запятой не всегда бывает так, что b близко к a. При тестировании b должен быть ожидаемым результатом, а должен быть фактическим результатом ". Обратите внимание, что это имеет смысл для тестирования, случай симметричной функции на самом деле немного сложнее обосновать. Относительная ошибка, включая деление, не является симметричным.

Мне это тоже не нравится - но взламывать код людей с изменением хуже. У вас есть идея, кроме простой не делать numpy лучше?

Вы уже высказываете здесь ценностное суждение о том, что добавление новой функции лучше, чем ее отсутствие. Это не имхо. Три варианта:

  1. Критическое изменение - неприемлемо, можете перестать обсуждать.
  2. Просто добавляю лучшие документы
  3. Добавление функции

2 в целом лучший выбор, чем 3, следовательно, это то, что делает numpy «лучше». Вы также игнорируете, что эта штука atol / rtol не ограничивается одной функцией, так что что дальше - новый и немного «лучший» assert_allclose ? Это делает аргументы в пользу использования только документов еще более очевидными.

Это довольно серьезный дефект, в основном код, проверяющий ваш код, содержит ошибки ... не очень хорошо. Вы бы отправили на Луну что-нибудь, что проверено с помощью numpy.isclose и атола по умолчанию? Я бы подумал дважды ... и поэтому нам нужно выделить эти подводные камни в документации.
Добавление функции псевдонима просто загромождает кодовую базу, если это не принудительно для пользователей (не происходит).

Я согласен с тем, что проблема симметрии незначительна, но мы все равно должны это исправить. Если его оставить, это может отвлечь пользователей от реальных ловушек.

@rgommers написал:
"" "
Вы уже высказываете здесь ценностное суждение о том, что добавление новой функции лучше, чем ее отсутствие. Это не имхо.
"" "
Что ж, я потратил МНОГО времени на размышления и дискуссии о math.isclose , и мы начали с рассмотрения, среди прочего, реализации numpy. так что да, я ДЕЙСТВИТЕЛЬНО думаю, что этот подход лучше. И после этого обсуждения я подумал, что это в значительной степени консенсус.

И получение лучшего алгоритма / интерфейса в numpy делает его лучше, да.

Возможно, вы имеете в виду, что наличие в numpy и старой, и новой, более совершенной функции НЕ лучше, чем просто оставить там старую (возможно, лучше документированную) функцию. Конечно, это абсолютно верный момент, но я пытался провести это обсуждение и предыдущий комментарий о том, что «введение новых функций, поведение которых лишь немного отличается от поведения других функций, которые работали таким образом в течение десятилетия, в общем, очень плохая идея». казалось, что обсуждение прекратилось - я хочу сказать, что если новый способ «достаточно лучше», то это того стоит. Что у нас явно нет консенсуса, так это то, является ли этот конкретный вариант «достаточно лучше», а не «лучше» ли он.

И, кстати, я лично не убедил себя, что это стоит изменений, но я действительно хочу провести обсуждение.

Ключевым здесь является пара предположений с моей стороны. Не знаю, верны ли они, но:

1) np.isclose () больше всего используется для тестирования - достаточно ли близки ваши ответы к ожидаемым? - это через np.assert_all_close, или, более прямо, в тестах pytest, или ....

2) Большинство людей в большинстве случаев не делают ничего вроде тщательного анализа ошибок с плавающей запятой, чтобы определить, насколько хорошими будут ответы. Скорее они пробуют значение, и если оно не удается, они смотрят на результаты и решают, действительно ли это ошибка, или им нужно скорректировать допуски теста.

  • это означает, что не имеет большого значения, будут ли объединены atol и rtol и будет ли тест симметричным.

3) многие люди, большую часть времени, начинают процесс в (2) с допусками по умолчанию и пытаются изменить допуск только в случае неудачного теста.

  • ЭТО означает, что иметь атол по умолчанию довольно опасно - пройти тесты, которые не должны, - это действительно плохо.

4) Люди не читают документы (за пределами начального этапа «как я назову это») - по крайней мере, до тех пор, пока они не обнаружат сбивающее с толку поведение, а затем они могут войти и попытаться понять, как что-то действительно работает, чтобы устранить путаницу. . Но посмотрите (3) - если тест не завершился неудачно, они не знают, что нужно смотреть в документации, чтобы понять, почему.

Все это приводит меня к выводу, что numpy будет «лучше» с более похожим на math.isclose тестом близости FP.

И почему лучше документы отличная идея, но недостаточно.

Возможно, я совершенно ошибаюсь, и большинство людей внимательно читают документацию и большую часть времени тщательно выбирают как rtol, так и atol для своей проблемы, но я знаю, что я, ни полдюжины человек в моей команде, не делали этого, пока я не стал осведомлены об этих проблемах.

: bikeshed: (черт возьми, это не сработало - никаких классных смайлов)

может быть relatively_close или rel_close ?

Дополнительная "забавная" морщинка: assert_allclose действительно использует atol = 0 с помощью
по умолчанию. Есть еще одна целая ветка, где обсуждают, можем ли мы исправить
это несоответствие. (На моем телефоне так сложно его найти.)

11 декабря 2017 г. в 14:58 «Крис Баркер» [email protected] написал:

@rgommers https://github.com/rgommers написал:
"" "
Вы уже выносите здесь оценочное суждение о том, что добавляете новую функцию
лучше, чем никакой новой функции. Это не имхо.
"" "
Ну, я потратил МНОГО времени на размышления и споры о
math.isclose, и мы начали с рассмотрения реализации numpy
среди прочего. так что да, я ДЕЙСТВИТЕЛЬНО думаю, что этот подход лучше. И я думал
Судя по этому обсуждению, это был в значительной степени консенсус.

И получение лучшего алгоритма / интерфейса в numpy делает его лучше, да.

Возможно, вы имеете в виду, что и старое, и новое, лучшее, функционируют в
numpy НЕ лучше, чем просто оставить старый (возможно, лучше
задокументировано). Конечно, это совершенно верно, но я был
пытаясь провести это обсуждение, и предыдущий комментарий, что «Введение
новые функции, поведение которых лишь немного отличается от других функций
которые работали так в течение десяти лет, в общем, очень плохая идея "
похоже, закрыл обсуждение - я считаю, что если новый способ
"достаточно лучше", чем оно того стоит. Чего у нас явно нет
консенсус в том, является ли этот конкретный вариант «достаточно лучше», а не
будь то «лучше».

И, кстати, лично я не убедил себя, что стоит
изменить, но я хочу обсудить.

Ключевым здесь является пара предположений с моей стороны. Я не знаю что мы можем
знать наверняка, верны ли они, но:

1.

Наибольшее использование np.isclose () для тестирования - ваши ответы
достаточно близко к тому, что вы ожидаете? - это через np.assert_all_close или
более конкретно, в тестах pytest или ....
2.

Большинство людей в большинстве случаев не делают ничего похожего на строгие
анализ ошибок с плавающей запятой, чтобы определить, насколько хороши ответы
ожидается. Скорее они пробуют значение, и если это не удается, они смотрят на
результатов и решите, действительно ли это ошибка, или нужно отрегулировать
переносимость теста.

  • это означает, что не так уж важно, атол и
    rtol и симметричен ли тест.

  • многие люди в большинстве случаев начинают процесс в (2) с
    допуски по умолчанию, и старайтесь отрегулировать допуск только в том случае, если тест не прошел.

  • ЭТО означает, что иметь атол по умолчанию довольно опасно - тесты
    прохождение того, что не должно быть, действительно плохая вещь.

  • Люди не читают документы (помимо начального "как мне это назвать"
    stage) - по крайней мере, пока они не обнаружат сбивающего с толку поведения, а затем они
    может войти и попытаться понять, как что-то действительно работает, чтобы прояснить
    путаница. Но см. (3) - если тест не провалился, они не знают
    посмотрите документацию, чтобы понять почему.

Все это приводит меня к выводу, что numpy было бы "лучше" с
подробнее math.isclose-like тест близости FP.

И почему лучше документы отличная идея, но недостаточно.

Может быть, я совершенно не прав, и большинство людей внимательно читают документы и
в большинстве случаев тщательно выбирайте как rtol, так и atol для их проблемы -
но я знаю, что ни я, ни полдюжины человек в моей команде не делали этого, пока я
стало известно об этих проблемах.

: bikeshed: (черт возьми, это не сработало - никаких классных смайлов)

может быть relative_close или rel_close?

-
Вы получаете это, потому что вас упомянули.
Ответьте на это письмо напрямую, просмотрите его на GitHub
https://github.com/numpy/numpy/issues/10161#issuecomment-350886540 или отключить звук
нить
https://github.com/notifications/unsubscribe-auth/AAlOaNquy47fsOkvBlxcSa-Mxyhgdimlks5s_bORgaJpZM4Q2J-P
.

Вы имеете в виду № 3183?

assert_allclose фактически использует atol = 0 по умолчанию.

Интересно - от этого мне становится легче.

Это возвращает смутные воспоминания о прошлых обсуждениях различий между ними - было ли это единственным?

Привет,
В моих библиотеках thermo, fluids и ht широко используется assert_allclose numpy, поэтому я поделюсь некоторыми мыслями, поскольку это связано. Этот поток заставляет поведенческую разницу казаться очень тревожной, и немного похоже на то, что люди должны ожидать найти ошибки в своем коде из-за отсутствия симметрии и / или разницы в сочетании atol и rtol, а также atol по умолчанию (отсутствует в assert_allclose , Я знаю). Итак, я хотел посмотреть, есть ли в моих библиотеках какие-либо ошибки, и взломал очень грубую реализацию assert_allclose, которую я затем временно изменил свои тесты, чтобы использовать вместо этого.

Я думаю, что мое использование assert_allclose является репрезентативным - я сравниваю индивидуально выбранные значения и провожу тесты, в которых я нечетко и параметрически вызываю assert_allclose для результата функций. Я сравниваю целые числа и числа с плавающей запятой всех видов. Я относительно мало думал о выборе rtol или atol, только изредка добавлял atol или менял rtol на менее строгие значения по умолчанию. Библиотеки вызывают assert_allclose 13159, 1178 и 4243 раз соответственно.

Итак, я внес изменения и провел свои тесты. Я очень рад сообщить, что не обнаружил новых ошибок или сбоев при тестировании ; Единственные сбои тестов, которые я смог обнаружить, были связаны с моей реализацией assert_allclose.

Я знаю, что есть и другие, кому повезло меньше, и они столкнутся с проблемой, если что-нибудь в assert_allclose или isclose изменится. Мне лично было бы удобнее писать тесты, если бы у меня был режим assert_allclose, который воспроизводил бы поведение math.allclose, будь то другая функция или флаг symmetric . Но я знаю, что это большая работа для кого-то, и еще не было и пиара. Я рад, что смог хоть раз проверить свой код на наличие этой ошибки!

4880 - это тот, о котором я думал.

11 декабря 2017 г. в 17:01 Натаниэль Дж. Смит [email protected]
написал:

4880 https://github.com/numpy/numpy/pull/4880 - это тот, о котором я думал

оф.

Спасибо, обратите внимание, что пример statsmodel хорошо отражает мою точку зрения о
по умолчанию atol - все, кроме 0.0, опасно.

Означает ли тот факт, что это происходит каждые пару лет, что мы должны
наконец что-нибудь с этим сделать?

Может быть. Это небольшая бородавка, но иногда эти мелкие неприятности добавляют
со временем.

И хотя я рад, что assert_allclose имеет значение atol по умолчанию равным нулю
(подтверждая мою точку зрения, что это приемлемый вариант, даже если вы не
согласен, это лучший вариант) многие из нас - и все чаще - не
используя unittest, и, следовательно, может использовать np.all_close непосредственно в тестах.

И да, Ральф, если мы внесем изменения, мы захотим изменить все три
тесно связанные функции :-(. Но это дает нам возможность сделать их
более последовательный, бонус?

Хотя переход py2-3 прошел не очень хорошо, есть кое-что, что нужно
сказал, что в какой-то момент у вас есть версия «можно убирать бородавки» :-)

Есть еще один вариант, чтобы фактически переместить is_close в (действительно лучшую) математическую версию atol=0 : измените значение по умолчанию на None и попробуйте с atol=0 ; если все True просто вернутся; если какой-то False , попробуйте еще раз со стандартным atol и если результаты изменятся, выдайте предупреждение об устаревании (и верните "старый" результат).

К сожалению, нельзя одновременно выполнять и симметрию, и атол, поскольку они идут в разных направлениях (т. Е. Всегда приходилось выполнять оба случая, что кажется немного сложным). Но мне не нравится значение по умолчанию atol гораздо больше, чем отсутствие симметрии ...

Я не сторонник изменения каких-либо функций, если нет функции, которая
вы можете использовать старое поведение. Кроме того, должен быть
автоматический инструмент рефакторинга для внесения этого изменения, если это сделано. Однако это не так
даже на столе сейчас.

Переход py3k - это не то, что мы когда-либо хотели бы иметь снова, и это
не образец для подражания. Сведение чисток в один большой выпуск - не лучший вариант.
подход ИМО.

Хотя переход на py2-3 прошел не очень хорошо, есть кое-что, что нужно сказать о том, что в какой-то момент появилась версия «можно убирать бородавки» :-)

Просто чтобы ответить на эту общую идею, что специальные номера версий могут сделать критические изменения ОК: общее правило состоит в том, что можно очистить бородавки, если есть четкий план перехода, который избегает неприемлемых уровней боли, и преимущества достаточны, чтобы оправдать расходы. Ключевым моментом здесь является то, что суждение должно быть основано на влиянии на пользователей, а не на том, «следовали ли мы правилам». (Если хотите, мы - консеквенциалисты , а не деонтологи .) Итак, единственная причина объявить конкретную версию «это та, которая ломает вещи», - это существенно упрощает работу пользователей. ИМО, преимущества объединения критических изменений вместе, как правило, незначительны, если они вообще существуют - сломанный код - это неработающий код - и даже если они существуют, очень редко они собираются склонить анализ затрат / выгод с «нет» на « да".

atol ненулевое значение по умолчанию - я на самом деле думаю, что это самая большая проблема (особенно с текущим алгоритмом добавления обоих), так как это может очень легко привести к прохождению тестов, которые не должны - и слишком часто мы немного ленивый - мы пишем тест с допуском по умолчанию, и если он проходит, мы думаем, что закончили. (когда я понял, как это работает, я вернулся к коду y и ДЕЙСТВИТЕЛЬНО нашел пару таких - упс!

Обратите внимание, что пример statsmodel хорошо отражает мою точку зрения по поводу значения по умолчанию для atol - все, кроме 0.0, опасно. [...] многие из нас - и все чаще - не используют unittest, и поэтому могут использовать np.all_close непосредственно в тестах.

«Мы должны взломать код пользователя, чтобы повысить согласованность с каким-либо другим пакетом» не очень хорошо оценивается по шкале затрат / выгод. «Есть противоречия внутри NumPy, которые не просто заблуждение, но толк таким образом , что непосредственно приводит к немым ошибкам в пользовательском коде, и мы можем зафиксировать , что» путь более убедительные. Я сам еще не сформировал своего мнения, но если вы хотите добиться здесь прогресса, то я буду настаивать на этом.

Записка:

«» «Я относительно мало думал о выборе rtol или атола,
только редко добавляя атол
-нип-

$ call assert_allclose 13159, 1178 и 4243 раз соответственно.

-нип-

Никаких новых ошибок или провалов тестов не обнаружил ;

«» »

Хорошие новости, хотя я отмечаю, что assert_allclose имеет значение atol по умолчанию равным нулю. И
вот почему :-)

@njsmith написал:

«Мы должны взломать код пользователя, чтобы повысить согласованность с каким-либо другим пакетом»

Я не думаю, что кто-то в этой ветке защищает это - я уверен, что нет. Единственная согласованность, которую кто-либо защищает, - это согласованность между связанными функциями numpy.

«Внутри numpy есть несоответствия, которые не только сбивают с толку, но и сбивают с толку, что напрямую приводит к тихим ошибкам в пользовательском коде, и мы можем это исправить»

Я, по крайней мере, защищаю ЭТО. И я думаю, что большинство других.

Проблема в том, что мы не можем исправить это без:

Нарушение обратной совместимости, что я не думаю, что кто-то думает, что это достаточно серьезно, даже с циклом устаревания.

Или же

Создание нового флага или функции.

Я думаю, что новая функция будет более чистым способом сделать это. Старый код может оставаться неизменным столько, сколько он хочет, новый код может использовать новые функции, а поиск и замена (или несколько вызовов импорта) могут упростить переключение по одному файлу за раз.

(Я полагаю, вы могли бы даже обезьяну исправить numpy в своем тестовом коде ....)

У нас уже есть:

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

Я не думаю, что добавление дополнительных опций в этот список на самом деле будет иметь большое значение для реальных пользователей.

Что ж, я потратил много времени на размышления и дискуссии о math.isclose, и мы начали с рассмотрения реализации numpy среди других. так что да, я ДЕЙСТВИТЕЛЬНО думаю, что этот подход лучше.

Я тоже, и я был одним из основных разработчиков numpy.testing - это вряд ли новая проблема. Настаивать с заглавными буквами на своей правоте еще не значит.

Возможно, вы имеете в виду, что наличие в numpy и старой, и новой, более совершенной функции НЕ лучше, чем просто оставить там старую (возможно, лучше документированную) функцию. Конечно, это абсолютно верный момент, но я пытался обсудить это,

Действительно, должно быть ясно, что я имел в виду именно это.

«Представление новых функций, поведение которых лишь немного отличается от других функций, которые работали таким образом в течение десяти лет, в общем, очень плохая идея», казалось, закрыл обсуждение

Нет, это указывает на реальную проблему с добавлением новых функций, которые слишком часто игнорируются или не имеют достаточного веса. В этом случае многим разработчикам ядра это кажется довольно ясным - похоже, вы получаете заключение, что этот корабль отплыл от @njsmith , @pv , @charris и меня.

Заранее прошу прощения за перефразирование, но assert_allclose - правильное поведение (или, по крайней мере, достаточно близко к нему). Однако isclose может доставить людям неприятности, потому что предполагает абсолютную терпимость, как отмечали другие. Я рассматриваю возможность отправить PR, чтобы поставить большую красную рамку на странице документации np.isclose чтобы предупредить людей об этом поведении. Как это звучит?

Заранее прошу прощения за то, что перефразирую это, но assert_allclose - это
правильное поведение (или хотя бы достаточно близкое к нему). Однако isclose может получить
люди попадают в неприятности, потому что это предполагает абсолютную терпимость, как и другие
принято к сведению. Я подумываю отправить PR, чтобы поставить большую красную рамку на
np.isclose страница документации, чтобы предупредить людей об этом поведении. Как
этот звук?

+1

Есть мнение, что документы должны быть лучше.

Благодаря,

-CHB

-
Вы получаете это, потому что вас упомянули.
Ответьте на это письмо напрямую, просмотрите его на GitHub
https://github.com/numpy/numpy/issues/10161#issuecomment-351182296 или отключить звук
нить
https://github.com/notifications/unsubscribe-auth/AA38YDw4sdhRWYmeeyr4met1RCwWsjMQks5s_uBmgaJpZM4Q2J-P
.

Я поддерживаю улучшение документации, но думаю, что предлагаемое изменение не так полезно, как могло бы быть.

.. предупреждение :: Значение по умолчанию atol не подходит для чисел, которые
намного меньше единицы.

Во-первых, это предупреждение даже не соответствует действительности. Значение по умолчанию atol _ подходит, когда вы хотите рассматривать числа меньше 1e-8 как равные нулю. Это невозможно с относительным допуском, поэтому существует абсолютный допуск. И наоборот, значение по умолчанию atol _не подходит, если вы хотите рассматривать числа меньше 1e-8 как значимые. Не будем считать, что всех под одну гребенку.

Поэтому @xoviat , с глубочайшим уважением, я категорически возражаю против вашего субъективного утверждения:

... assert_allclose _это правильное поведение (или, по крайней мере, достаточно близко к нему).

Я думаю, что проблема с текущими документами заключается в том, что они очень хорошо описывают _ what_ atol , но не описывают _why_ это там, и поэтому пользователи могут не понять, когда изменить значение по умолчанию .

Я предлагаю что-то вроде:

"Установка небольшого ненулевого значения atol позволяет рассматривать числа, очень близкие к нулю, как фактически равные нулю. Следовательно, значение по умолчанию atol может не подходить для вашего использования. case. Выберите atol , чтобы числа больше atol считались вами значимыми (отличными от нуля), а числа меньше atol рассматривались вами как незначительные. (то же, что и ноль) ".

Наконец, я бы добавил то же примечание к строкам документации isclose и allclose .

Это мое предложение. Возьми это или оставь.
Ура.

Пожалуйста, оставьте отзыв о ПР. В частности, ваше предложение IMO слишком многословно.

Извините всех, если я был слишком раздражающим - я действительно не думал, что есть консенсус.

@xoviat : спасибо за работу над документами.

Поскольку это будет повторяться снова, я собираюсь (вероятно) положить конец этой дискуссии с помощью мини-версии нэпа, предназначенной для отклонения - резюмируйте предложения и причины отклонения. Для протокола - поскольку предыдущие выпуски как бы прекратились.

Извините за то, что поднял проблему py2 / 3 - вопрос о том, следует ли / как убирать бородавки в numpy, - это обсуждение для другого места и времени.

Проблема с isclose()

Этот вопрос (и другие ссылки) является результатом наблюдений, numpy.isclose() и друзья используют менее чем оптимальный алгоритм, имеет спорное значение по умолчанию для Атол, и различная связанная с ней функция имеет различные значения по умолчанию. В целом это приводит к путанице для пользователей и, в худшем случае, к ложноположительным тестам, когда пользователи не задумываются об установке значения atol .

В частности, реализация в stdlib: math.isclose() предоставляет другой и, возможно, лучший алгоритм и значения по умолчанию: это симметричный тест, он не смешивает rtol и atol, а значение atol по умолчанию равно 0,0.

Практически все согласны с тем, что ситуация не идеальна, но нет единого мнения о том, что это достаточно плохо, чтобы что-то с этим поделать.

Рассмотрены варианты:

Изменение алгоритмов и / или значений по умолчанию:

Повсеместно отвергнуты из-за проблем с обратной совместимостью, даже с периодом устаревания и предупреждениями - эти функции широко используются в тестах, поэтому это, по крайней мере, будет большим раздражением.

Добавление дополнительного параметра с флагом для выбора другого алгоритма

Это не нарушит существующий код, но останется навсегда с уродливым и запутанным API.

Добавление директивы __future__ - type

TL; DR: это возможно, но непросто. Похоже, никто не хотел этого добиваться.

Создание еще одной функции

Казалось, что это единственный вариант, который получил хоть какую-то поддержку, но не был поддержан основными разработчиками, участвовавшими в обсуждении.

Самый простой способ «исправить» это - добавить np.rel_close() [или другое имя] с новым алгоритмом и значениями по умолчанию, вероятно, теми, которые используются в math.isclose . Новая функция будет задокументирована как «рекомендованная» для использования в будущем коде. В будущем можно было бы добавить предупреждения об устаревании к старому, но, похоже, никто не думал, что этот шум того стоит.

Для замены можно создать инструмент рефакторинга - но кто это сделает для этого?

Это, вероятно, приведет к появлению двух очень похожих функций в обозримом будущем, и «введение новых функций, поведение которых лишь немного отличается от других функций, которые работали таким образом в течение десятилетия, в общем, очень плохая идея».

Заключение:

Это не стоит того из-за небольшого выигрыша, но есть лучшие документы, и это делается здесь: # 10214

У меня остался один вопрос:

@njsmith написал:

"" "
У нас уже есть:

allclose
assert_allclose
assert_almost_equal
assert_approx_equal
assert_array_almost_equal
assert_array_almost_equal_nulp
assert_array_max_ulp

Я не думаю, что добавление дополнительных опций в этот список на самом деле будет иметь большое значение для реальных пользователей.
"" "

Вы имеете в виду, что добавление нового было бы хорошей идеей?

Также отмечу:

большинство из них являются утверждениями, а увеличение числа утверждений - побочным эффектом архитектуры unittest.

Поскольку многие из нас переходят на другие архитектуры тестирования (например, pytest), необходимость в утверждениях отпадает.

Итак, что делать с numpy.testing - это отдельный вопрос от того, что делать с ядром numpy.

Поскольку многие из нас переходят на другие архитектуры тестирования (например, pytest), необходимость в утверждениях отпадает.

Собственно, это опасно само по себе. Тесты могут быть изменены с assert_allclose(...) на assert np.allclose(...) , и они будут незаметно становиться менее строгими, что плохо.

Я все еще использую assert_allclose в среде pytest, потому что это дает полезное сообщение об ошибке:

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

против использования 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

Возможно, это удастся исправить, реализовав pytest_assertrepr_compare , но я не уверен, как применить это к вызовам функций, и не могу понять, где pytest даже вызывает его.

@ eric-wieser: написал:

«На самом деле, это опасность сама по себе. Тесты могут быть изменены с assert_allclose (...) на assert np.allclose (...), и они будут незаметно стать менее строгими, что плохо».

В точности моя точка зрения - это "плохая идея" предполагать, что каждый будет использовать утверждения для тестирования и, следовательно, не беспокоиться о том, подходят ли значения по умолчанию isclose () и allclose () для тестирования - в идеале мир они непременно должны быть.

Вы имеете в виду, что добавление нового было бы хорошей идеей?

Нет, я имел в виду, что, учитывая, что у нас уже есть целый зверинец немного разных способов выражения почти одинаковых тестов, к сожалению, большинство пользователей не заметят или не поймут еще одно дополнение.

Также отмечу:
большинство из них являются утверждениями, а увеличение числа утверждений - побочным эффектом архитектуры unittest.
Поскольку многие из нас переходят на другие архитектуры тестирования (например, pytest), необходимость в утверждениях отпадает.

Они были написаны как утверждения, но AFAICT, каждая из этих функций фактически кодирует другое определение «почти равно». (Я думаю. Некоторые различия настолько неясны, что я не могу сказать, настоящие они или нет.)

Изменение алгоритмов и / или значений по умолчанию:
Повсеместно отвергнуты из-за проблем с обратной совместимостью, даже с периодом устаревания и предупреждениями - эти функции широко используются в тестах, поэтому это, по крайней мере, будет большим раздражением.

Я бы не стал так говорить. Для меня это единственный подход, который потенциально может иметь преимущества, достаточные для оправдания затрат. Я не говорю, что будут , и не могу говорить от имени других основных разработчиков; Я бы хотел увидеть некоторые данные, а без данных ошибаться в сторону консерватизма кажется правильным выбором. Но если бы кто-то произвел данные, я бы хотя бы посмотрел на них :-).

Например, если бы кто-то появился и сказал: «Я попробовал предложенное мной изменение в 3 больших проектах, и это привело к 12 лишним сбоям из 10 000 тестов, и из этих 12 8 из них были настоящими тихими ошибками, которые были скрыты старыми плохие значения по умолчанию "... это было бы довольно убедительно. Тем более, что это тот случай, когда у нас есть техническая возможность делать узконаправленные предупреждения. Я предполагаю, что реальные цифры будут не столь благоприятными, но пока кто-нибудь не проверит, кто знает.

В пн, 18 декабря 2017 г., в 15:57, Натаниэль Дж. Смит <
[email protected]> написал:

Нет, я имел в виду, что у нас уже есть целый зверинец
немного разные способы выражения почти одинаковых тестов, к сожалению
большинство пользователей не заметят или не поймут еще одно дополнение.

Что ж, есть одно большое различие - каждый из них был добавлен, потому что
что-то другое , и из-за капризов с плавающей запятой эти
различия могут быть важны.

Новая функция относительной близости будет делать то же самое, но
делать это лучше". И цель - рекомендовать использовать новый
вместо старого (и, возможно, со временем отказаться от старого).

Честно говоря, я не уверен, аргумент ли это за или против идеи,
хотя.

Например, если бы кто-то пришел и сказал: "Я попробовал предложенное изменение на 3 больших

проектов, и это привело к 12 лишним сбоям из 10 000 тестов, и те
12, 8 из них были настоящими тихими ошибками, которые были скрыты старыми плохими
defaults "... это было бы довольно убедительно. Тем более, что это
случай, когда у нас есть техническая возможность делать узконаправленные предупреждения.
Я предполагаю, что реальные цифры не будут столь благоприятными, но пока
кто-то проверяет, кто знает.

хм, в моей кодовой базе около 1500 тестов - не 10 000, но я дам это
выстрел. По крайней мере, я могу найти ошибку или плохой тест или два. Или получить больше
заверение!

Всем привет,

Хотел вмешаться, когда коллега столкнулся с этой проблемой.

_Отказ от ответственности: я не особо задумывался над логикой, прежде чем крикнуть «огонь в зале» и перебросить это через забор. Если я сделал из него досадный хеш-код, будьте добры, пожалуйста.

Для меня все это очень похоже на классическую проблему «курица и яйцо» в архитектуре / дизайне - семантика против реализации. Не все ошибки существуют в коде, иногда они существуют в семантике. Это не сильно отличается (если вообще) от безупречно реализованного алгоритма только для того, чтобы обнаружить, что алгоритм ошибочен - ошибка не в коде, а в алгоритме, но в любом случае это все еще ошибка. По сути, это обсуждение звучит как классическая шутка «это не ошибка, а особенность». Конечно, «выбор» - это просто так, но IMHO это обычно означает конец логического обоснования - если семантика выбрана как есть, как она реализована, то пусть будет так, реализация в порядке, конец обсуждения.

Итак, какова «желаемая» и / или «ожидаемая» семантика isclose() . Обдумывая это, я остаюсь неумолимо сходящимся с семантикой, определяемой пользователем, то есть пользователь должен иметь возможность определять семантику определение «закрыть».

По умолчанию

Что касается значений по умолчанию, это в конечном итоге не нарушает никакой семантики. Однако плохой выбор опасен. Если ненулевое значение по умолчанию было выбрано _only_, чтобы обеспечить разумное поведение при abs(a - b) == 0 то это определенно звучит как неправильный soln. Это конкретное состояние было бы лучше иметь особый регистр, поскольку оно семантически имеет особый регистр. В определении термина «закрыть» нет «места для маневра», когда разница равна нулю, это самоопределяющийся краеугольный камень, т.е. они не _close_, они _exact_ - где «close» - это относительное отклонение от точного . (_Примечание: _Особое условие корпуса может (или не может) повлиять на производительность.)

+ против max

Смешивание или «затенение» rel_tol и a_tol из-за реализации с использованием суммы, а не max _does_ нарушает семантику вышеуказанной функции. Пользовательское определение термина «закрыть» связано нетривиальным образом, поскольку оно искажает и, следовательно, нарушает семантику «относительного» и «абсолютного». Принимая во внимание только указанную выше семантику, этот аспект _ является_ ошибкой. Я нахожу @gasparka открывающий пример - неопровержимый аргумент в пользу этого.

Коммутативность (т.е. симметрия)

На самом деле здесь всего два оператора: - в a-b и <= в |a-b| <= f(a, b, atol, rtol) . В то время как вычитание является антикоммутативным, |a - b| нет, оно коммутативно по определению. Однако одного этого может быть недостаточно, чтобы указать коммутатив f(a, b, atol, rtol) . Однако здесь есть сильный и слабый аргумент.

  • Слабым является простейшее - инкапсуляция разделения функций или их отсутствие - в то время как арифметически коммутативность |a - b| может не обеспечивать коммутативность f(a, b, atol, rtol) , программно f(a, b, atol, rtol) на самом деле не так. вопрос но isClose(a, b, atol, rtol) . Здесь вычисление |a - b| выполняется внутри функции, т.е. isClose() := |a-b| <= f(a, b, atol, rtol) . Поскольку это внутреннее значение, и a и b передаются, для того, чтобы |a-b| был коммутативным, также должен быть isClose() . В противном случае коммутативность |a-b| теряет всякий смысл.
  • Сильный аргумент: операция сравнения не является строгой, то есть это <= not < , поэтому для части сравнения сравнения вы должны выполнить |a-b| = f(a, b, atol, rtol) что подразумевает f(a, b, atol, rtol) _должен быть коммутативным (я так думаю?). Невыполнение этого требования означает, что либо указанное выше равенство _ никогда_ истинно (нет значений a & b которые удовлетворяют этому), либо строгое неравенство < имеет на самом деле было семантически определено, верно?

Что вы делаете (или не делаете) в отношении всего или чего-либо из этого - это совершенно отдельный вопрос.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги

Смежные вопросы

kevinzhai80 picture kevinzhai80  ·  4Комментарии

dcsaba89 picture dcsaba89  ·  3Комментарии

Levstyle picture Levstyle  ·  3Комментарии

inducer picture inducer  ·  3Комментарии

manuels picture manuels  ·  3Комментарии