Почему массивы 0d в Numpy не считаются скалярными?

StackOverflow https://stackoverflow.com/questions/773030

  •  12-09-2019
  •  | 
  •  

Вопрос

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

>>> foo = numpy.array(1.11111111111, numpy.float64)
>>> numpy.ndim(foo)
0
>>> numpy.isscalar(foo)
False
>>> foo.item()
1.11111111111
Это было полезно?

Решение

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

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

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

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

Решение разработчика 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, но это не меняет того факта, что многие новые коммутаторы глубоко сбиты с толку этим.У некоторых есть отчетливые воспоминания о том, как они боролись с таким поведением и в конечном итоге проявили настойчивость, в то время как у других, зашедших слишком далеко, обычно остается какой-то глубокий бесформенный душевный шрам, который часто преследует их в самых невинных снах.Это безобразная ситуация для всех.

Другие советы

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top