неподдерживаемые типы операндов для *: 'numpy.ndarray' и 'numpy.float64'

давний читатель, начинающий писатель.

Я искал в Google и переполнении стека, но не смог найти общий ответ на этот вопрос.

Я получаю сообщение об ошибке «неподдерживаемый тип операнда для *: 'numpy.ndarray' и 'numpy.float64'» в python 2.7.3 с использованием numpy 1.6.2.

Ошибка возникает из-за умножения массива numpy и numpy float, но это происходит не каждый раз.

Например:

x = np.tan(1) # numpy.float64
y = np.array([0,1,2,3]) # numpy.ndarray
np.multiply(x,y) # works no problem

Or

x = np.tan(np.abs(np.multiply(-31,41)))  # numpy.float64
y = np.square(np.add(np.divide(np.zeros(100),42),(-27)**40)) # numpy.ndarray
np.multiply(x,y) # works no problem

Оба работают

Теперь о проблемных детях:

np.multiply(np.square(np.add(np.divide(np.zeros(100),42),-27)**40)),
np.tan(np.abs(np.multiply(-31,41))))

или, с x, определенным, как указано выше:

np.multiply(np.square(np.add(np.divide(np.zeros(100),42),(-27)**40)),x)

оба выдают ошибку: NotImplemented

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

Почему это происходит? Как я могу исправить это в общем смысле?

Большое спасибо! Джейсон


person Jason    schedule 18.01.2013    source источник
comment
Я думаю, вы обнаружили ошибку в коде, вы можете сообщить об этом тупым людям. Для протокола: если a равно np.ndarray, а x равно np.float64, то работают и x * a, и a * x[...], но ни один из a * x, a + x, a / x или a - x не работает. Трудно понять, почему, если метод __mul__ из a не может с этим справиться, __rmul__ из x не вызывается, так как он, кажется, знает, как обращаться с этим случаем...   -  person Jaime    schedule 19.01.2013
comment
Большое спасибо, что проверили это для меня. Я постараюсь сообщить об этом как о проблеме в numpy. Как вы думаете, есть ли способ обойти это?   -  person Jason    schedule 19.01.2013
comment
Если вы замените x на x[...], это сработает, но это неприятный хак...   -  person Jaime    schedule 19.01.2013
comment
К сожалению, это не будет простым способом предотвратить ошибки в моем коде, так как эти функции генерируются случайным образом DEAP (отличная структура генетического программирования, с которой я работаю).   -  person Jason    schedule 19.01.2013
comment
Проблема зарегистрирована по адресу: github.com/numpy/numpy/issues/2930.   -  person Jason    schedule 19.01.2013
comment
Смешивание чисел с плавающей запятой с длинными целыми числами, как правило, является плохой идеей. (-27.)**47 должен решить вашу проблему... Вы можете использовать арифметику произвольной точности, но в numpy нет поддержки, см. этот ответ   -  person Stefano M    schedule 19.01.2013
comment
Уже получил ответ! Проблема исправлена ​​в numpy 1.7 (который скоро будет выпущен) /numpy/issues/2930#issuecomment-12445232   -  person Jason    schedule 19.01.2013


Ответы (2)


Я подозреваю, что проблема здесь в том, что NumPy не может хранить значения Python long в своих массивах. Как только вы пытаетесь это сделать, он переключает тип данных массива на object. Затем арифметические операции над массивом становятся более сложными, потому что NumPy больше не может выполнять арифметические операции самостоятельно.

>>> np.array(27**40)
array(1797010299914431210413179829509605039731475627537851106401L, dtype=object)
>>> np.array(27**40) * np.tan(1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for *: 'numpy.ndarray' and 'numpy.float64'

Как ни странно, иногда срабатывает перестановка порядка аргументов:

>>> np.tan(1) * np.array(27**40)
2.7986777223711575e+57

Во втором случае тип результата — это Python float, а не массив NumPy.

Исправление состоит в том, чтобы избежать создания значений long в массивах NumPy и вместо этого использовать floats:

>>> np.array(27.0**40)
array(1.797010299914431e+57)
>>> np.array(27.0**40) * np.tan(1)
2.7986777223711575e+57
>>> np.multiply(np.square(np.add(np.divide(np.zeros(10),42),(-27.0)**40)),np.tan(1))
array([  5.02925269e+114,   5.02925269e+114,   5.02925269e+114,
         5.02925269e+114,   5.02925269e+114,   5.02925269e+114,
         5.02925269e+114,   5.02925269e+114,   5.02925269e+114,
         5.02925269e+114])

Если вы получите сообщение об ошибке, похожее на будущее, первое, что нужно сделать, это проверить dtype умножаемого массива. Содержит ли он значения NumPy или объекты Python?

person Luke Woodward    schedule 18.01.2013
comment
Хороший звонок! Моя переменная массива (y = np.square(np.add(np.divide(np.zeros(100),42),(-27)**40)) как определено выше в моем вопросе) имеет тип "объект" ( y.dtype) К сожалению, я не уверен, что смогу заставить его быть поплавком, учитывая, что он начинается как поплавок, а где-то по пути приводит себя к длинному. - person Jason; 19.01.2013
comment
Проблема в операции с (-27)**40. NumPy не может напрямую обрабатывать Python long. Однако вы можете использовать np.array для преобразования массива NumPy в другой массив другого типа. Например, np.array(np.array(27**40), dtype=np.float64) вернет массив типа float64. - person Luke Woodward; 19.01.2013
comment
Да, я смог найти, где в моем коде генерировались целые числа 27 и 40, и преобразовать их в числа с плавающей запятой. Для записи np.arange генерирует int32. Большинство функций numpy работают с числами с плавающей запятой, включая np.ones и np.zeros. - person Jason; 19.01.2013

Это викторина? Не понимаю, почему вопрос так запутан... Все сводится к этому простому факту.

Дано

>>> x = 10**100
>>> type(x)
<type 'long'>
>>> y = np.float64(1)

у нас есть

>>> y.__mul__(x)
1e+100
>>> y.__rmul__(x)
NotImplemented

Это ошибка (или особенность, я не знаю), поскольку она должна быть y.__mul__(x) == y.__rmul__(x) (по крайней мере, для этих конкретных значений x и y).

Python long не умеет обрабатывать умножение с помощью numpy.float64 (но это правильно.)

>>> x.__mul__(y)
NotImplemented
>>> x.__rmul__(y)
NotImplemented

Таким образом, y*x оценивается как y.__mul__(x) и дает ожидаемый результат. Напротив, x*y сначала пробуется как x.__mul__(y) (не реализовано, хорошо), а затем как y.__rmul__(x) (не реализовано, но ошибка.).

Как уже было сказано, мы можем иметь nd.arrays произвольных объектов, и все становится ясно.

Изменить

Эта ошибка была исправлена ​​(вероятно, в numpy версии 1.7):

>>> np.version.version
'1.13.1'
>>> x = 10**100
>>> y = np.float64(1)
>>> x.__mul__(y)
NotImplemented
>>> x.__rmul__(y)
NotImplemented
>>> y.__mul__(x)
1e+100
>>> y.__rmul__(x)
1e+100
>>> x*y
1e+100
>>> y*x
1e+100
person Stefano M    schedule 18.01.2013
comment
@ Worthy7 Понятия не имею, почему мой ответ был отклонен: ИМХО, он указывает на ошибку numpy, ответственную за неожиданное поведение, что подтверждается github.com/numpy/numpy/issues/2930#issuecomment-12445232 (и нет, я не написал свой ответ после прочтения этой проблемы с numpy.) - person Stefano M; 14.08.2017