Функция оценки с использованием массива numpy возвращает inf и nan

У меня есть следующий массив и функция numpy:

import numpy
import scipy.special

i = numpy.linspace(0, 500, 501, dtype = int)

def func(x, n):
  return scipy.special.eval_hermite(n, x)

Я оцениваю функцию для каждого элемента в моем массиве i, используя две разные аппроксимации:

Подход 1:

hermites = func(0, i)

Подход 2:

hermites = [func(0, idx) for idx in i]

Два подхода дают два разных ответа. Они отличаются, потому что после элемента 50, подход 1 начинает возвращать inf и nan. Подход 2 также не дает правильного значения для каждого элемента i. Тем не менее, он может рассчитать больше из них. Подход 2 не работает для i >= 64.

Оба подхода дают мне ответ примерно в одно и то же время (0,7 с для len(i) = 15000, определяется с помощью timeit). Что я не понимаю, так это разные результаты. Это потому, что я научился избегать for loops в python, насколько это возможно. Похоже, на этот раз это не так.

Мне пришла в голову мысль, что это связано с памятью. Однако при оценке одного элемента, т. Е. print func(0, 64), также возвращается 0. (равно выводу подхода 2 ).

Что происходит?

7 голосов | спросил The Dude 17 +03002015-10-17T15:45:21+03:00312015bEurope/MoscowSat, 17 Oct 2015 15:45:21 +0300 2015, 15:45:21

1 ответ


0

Это ошибка в scipy, созданная время от времени удивительными правилами приведения "ufuncs" numpy. Проблема в том, что в scipy версии 0.16 и старше, когда первый аргумент eval_hermite является целочисленным массивом а второй - целочисленный скаляр, тип данных возвращаемого значения - с плавающей запятой одинарной точности (numpy.float32). Когда вторым аргументом является 64-битное значение с плавающей запятой, тип возвращаемого значения - numpy.float64. Наибольшее значение, которое может быть представлено с помощью float32, намного меньше значения float64, поэтому, когда вторым аргументом является целое число, eval_hermite переполняется до бесконечности гораздо раньше.

Например, это с scipy 0.16.0 и numpy 1.10.1:

In [26]: from scipy.special import eval_hermite

Обратите внимание, что тип возвращаемого значения: float32:

In [27]: eval_hermite([20, 50, 100, 200], 0)
Out[27]: 
array([  6.70442586e+11,             -inf,              inf,
                    inf], dtype=float32)

Если вторым аргументом является число с плавающей запятой, тип возвращаемого значения float64, и большие значения могут быть представлены:

In [28]: eval_hermite([20, 50, 100, 200], 0.0)
Out[28]: 
array([  6.70442573e+011,  -1.96078147e+039,   3.06851876e+093,
         8.45055019e+216])

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

hermites = func(0.0, i)

Эта проблема была исправлена ​​в версии для разработчиков scipy (см. https://github.com/scipy /scipy /pull /4896 ), поэтому у scipy 0.17 не должно быть этой проблемы при выпуске.

ответил Warren Weckesser 17 +03002015-10-17T16:30:01+03:00312015bEurope/MoscowSat, 17 Oct 2015 16:30:01 +0300 2015, 16:30:01

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132