Похоже, что в Numpy 2 появился свой отдельный float64(nan)
, отличный от np.nan
. Теперь регрессионные тесты терпят неудачу, потому что пока
>>> np.nan is np.nan
True
у нас теперь есть
>>> np.nan is np.float64("nan")
False
(также json не может сериализовать эти новые NaN
).
Почему они внесли это изменение?
Есть ли способ автоматически преобразовать числа с плавающей запятой в обычные числа с плавающей запятой?
🤔 А знаете ли вы, что...
Python популярен в машинном обучении и искусственном интеллекте.
Существует несколько NaN (см. ниже и NaN в качестве ссылки), и Python может повторно использовать объекты или нет. Использование X is Y
в рамках модульного теста является здесь основной проблемой.
Например, np.inf - np.inf
дает np.nan
:
np.inf-np.inf
# nan
И все еще:
np.nan is (np.inf-np.inf)
# False
Если вы хотите узнать, является ли объект NaN, всегда используйте np.isnan (или эквивалент math
или pandas
), никогда не сравнивайте объекты или is
:
np.isnan((np.inf-np.inf))
# True
NaN не кодируются одним способом. Могут быть тихие NaN (неоднозначная операция) или сигнальные NaN (ошибочная операция). Кроме того, Python может повторно использовать объекты… или нет.
При запуске np.nan is np.nan
Python использует один и тот же объект для обоих. Если вы запускаете np.log(-1) is np.log(-1)
на моей машине, это создает два разных объекта, и результат False
:
np.log(-1) is np.log(-1)
# False
Чтобы дать вам более сложный пример, на моей машине np.nan
всегда выдается один и тот же объект. Тихие/сигнальные NaN всегда создают разные объекты. Последовательное создание одного типа NaN иногда приводит к повторному использованию объекта, а иногда нет:
(id(np.nan), # 135051355677520
id(np.inf-np.inf), # 135046756258928
id(float('nan')), # 135046756258928
id(np.log(-1)), # 135046756256624 # triggers warning
id(np.sqrt(-1)), # 135046756256624 # triggers warning # same as previous
id(float('nan')), # 135046756258928 # same as before
id(np.sqrt(-1)), # 135046756261584 # triggers warning # different
id(np.nan), # 135051355677520 # same as before
)
При повторном запуске все идентификаторы меняются, но по той же схеме. np.nan
остается стабильным:
(id(np.nan), # 135051355677520
id(np.inf-np.inf), # 135046756261872
id(float('nan')), # 135046756261872
id(np.log(-1)), # 135046756262736 # triggers warning
id(np.sqrt(-1)), # 135046756262736 # triggers warning # same as previous
id(float('nan')), # 135046756261872 # same as before
id(np.sqrt(-1)), # 135046756262640 # triggers warning # different
id(np.nan), # 135051355677520 # same as before
)
Короче говоря, не делайте этого. Используйте np.isnan