Почему 0d массивы в Numpy не считаются скалярными? - PullRequest
60 голосов
/ 21 апреля 2009

Конечно, массив 0d является скалярным, но Numpy, похоже, так не считает ... я что-то упустил или я просто неправильно понял концепцию?

>>> foo = numpy.array(1.11111111111, numpy.float64)
>>> numpy.ndim(foo)
0
>>> numpy.isscalar(foo)
False
>>> foo.item()
1.11111111111

Ответы [ 2 ]

122 голосов
/ 27 апреля 2009

Не стоит слишком об этом думать. Это в конечном итоге лучше для психического здоровья и долголетия человека.

Любопытная ситуация со скалярными типами Numpy объясняется тем, что не существует изящного и последовательного способа разложения матрицы 1x1 до скалярных типов. Хотя математически это одно и то же, они обрабатываются совершенно другим кодом.

Если вы выполняете какое-то количество научного кода, в конечном итоге вы захотите, чтобы такие вещи, как max(a), работали с матрицами всех размеров, даже скалярами. Математически, это вполне разумная вещь, чтобы ожидать. Однако для программистов это означает, что все, что представляет скаляры в Numpy, должно иметь атрибуты .shape и .ndim, так что, по крайней мере, ufuncs не должен выполнять явную проверку типов на своем входе для 21 возможных скалярных типов в Numpy.

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

Решение разработчика Numpy заключается в наследовании от скаляров ndarray и Python для своего скалярного типа, так что все скаляры также имеют .shape, .ndim, .T и т. Д. И т. Д. Матрица 1x1 все еще будет присутствовать, но ее использование не рекомендуется, если вы знаете, что будете иметь дело со скаляром. Хотя теоретически это должно работать нормально, иногда вы все равно можете увидеть некоторые места, где они пропустили валик, и уродливые внутренности открыты для всеобщего обозрения:

>>> from numpy import *
>>> a = array(1)
>>> b = int_(1)
>>> a.ndim
0
>>> b.ndim
0
>>> a[...]
array(1)
>>> a[()]
1
>>> b[...]
array(1)
>>> b[()]
1

На самом деле нет причин, по которым a[...] и a[()] должны возвращать разные вещи, но это так. Есть предложения изменить это, но похоже, что они забыли закончить работу с массивами 1x1.

Потенциально более серьезная и, возможно, неразрешимая проблема заключается в том, что скаляры Numpy неизменны. Поэтому «разбрызгивание» скаляра в ndarray, математически сопряженная операция сворачивания массива в скаляр, является реализацией PITA. На самом деле вы не можете вырастить скаляр Numpy, его нельзя по определению преобразовать в ndarray, даже если newaxis загадочно работает с ним:

>>> b[0,1,2,3] = 1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'numpy.int32' object does not support item assignment
>>> b[newaxis]
array([1])

В Matlab увеличение размера скаляра является совершенно приемлемой и бездумной операцией. В Numpy вы должны использовать jarring a = array(a) везде, где вы думаете , у вас будет возможность начать со скаляра и закончить массивом. Я понимаю, почему Numpy должен так хорошо играть с Python, но это не меняет того факта, что многие новые переключатели глубоко смущены этим. У некоторых есть явная память о борьбе с этим поведением и, в конечном итоге, о настойчивости, в то время как у других, которые слишком далеко ушли, обычно остается какой-то глубокий бесформенный психический шрам, который часто преследует их самые невинные сны. Это ужасная ситуация для всех.

5 голосов
/ 21 апреля 2009

Вы должны создать скалярный массив немного по-другому:

>>> x = numpy.float64(1.111)
>>> x
1.111
>>> numpy.isscalar(x)
True
>>> numpy.ndim(x)
0

Похоже, скаляры в numpy могут немного отличаться от того, к чему вы привыкли с чисто математической точки зрения Я полагаю, вы думаете о скалярных матрицах?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...