У numpy.array странное поведение с оператором / =?

Sep 11 2020

Я пытаюсь нормализовать массив чисел до диапазона (0, 1], чтобы я мог использовать их в качестве весов для взвешенного random.choice (), поэтому я ввел эту строку:

# weights is a nonzero numpy.array
weights /= weights.max()

Однако Pycharm сказал, что у max()функции ( Parameter 'initial' unfilled) есть незаполненный параметр . Я пробовал это в REPL с оператором / = и с «обычным» делением ( a = a / b) и получил разные результаты для обоих и другую ошибку, чем думал Pycharm:

>>> a = numpy.array([1,2,3])
>>> a.max()
3
>>> a /= a.max()
Traceback (most recent call last):
  File "<pyshell#4>", line 1, in <module>
    a /= a.max()
TypeError: No loop matching the specified signature and casting was found for ufunc true_divide
>>> a = a/a.max()
>>> a
array([0.33333333, 0.66666667, 1.        ])

Я также понял, что для взвешенного случайного числа веса нужно суммировать до единицы, а не нормализовать к ней. Но деление его на сумму дало то же самое TypeErrorс использованием операции / = (но Pycharm думал, что это нормально):

>>> a = numpy.array([1,2,3])
>>> sum(a)
6
>>> a
array([1, 2, 3])
>>> a /= sum(a)
Traceback (most recent call last):
  File "<pyshell#13>", line 1, in <module>
    a /= sum(a)
TypeError: No loop matching the specified signature and casting was found for ufunc true_divide
>>> a = a / sum(a)
>>> a
array([0.16666667, 0.33333333, 0.5       ])

Что я здесь наткнулся? Это какая-то странная ошибка в Numpy или оператор / = имеет другое использование или что-то в этом роде? Я знаю , что они используют __truediv__и , __itruediv__но я не могу понять , почему один имеет проблему , а другие нет. Я подтвердил это поведение с помощью последней версии Numpy из pip (1.19.2 в Windows x64).

Ответы

1 Fahim Sep 11 2020 at 23:24

Это потому, что numpy заботится о типе. Когда вы применяете деление, вы меняете intна float. Но numpy не позволит вам этого сделать! Вот почему ваши ценности уже должны быть включены float. Попробуй это:

>>> a = np.array([1.0,2.0,3.0])
>>> a /= sum(a)
>>> a
array([0.16666667, 0.33333333, 0.5       ])

Но почему сработал другой? Это потому, что это не операция «на месте». Следовательно, создается новая ячейка памяти. Новая переменная, новый тип, поэтому numpy здесь все равно.