import numpy as np
a = np.array([0.1, 0.2, 0.4, 0.3])
masked_a = np.ma.masked_array(a, [0, 0, 1, 1])
counter = np.zeros(len(a) + 1)
while True:
action = np.random.choice(len(a), p=masked_a)
counter[action] += 1
print(counter / counter.sum())
# [0.09931198 0.20076697 0. 0. 0.69992105]
Он не должен возвращать индекс> 3, но когда последний элемент замаскированного массива истинен, он может вернуть index = 4
Проблема также возникает в Generator.choice
в разрабатываемой версии numpy:
In [1]: import numpy as np
In [2]: np.__version__
Out[2]: '1.20.0.dev0+986e533'
In [3]: rng = np.random.default_rng()
In [4]: pm = np.ma.masked_array([0.1, 0.2, 0.4, 0.3], mask=[0, 0, 1, 1])
In [5]: rng.choice(4, p=pm, size=12)
Out[5]: array([4, 4, 4, 0, 4, 1, 4, 0, 0, 4, 4, 4])
Раньше я добавлял ярлык «ошибка», но это субъективное мнение. В numpy есть и другие функции, которые неправильно обрабатывают маскированные массивы (или, лучше сказать, «правильно», поскольку «правильность» также может быть признаком суждения), где мы не обязательно считаем это ошибкой. Возможно, это просто пример неопределенного поведения, и краткий ответ на этот вопрос - «не делайте этого!». Однако было бы лучше, если бы мы могли вызвать исключение вместо того, чтобы возвращать бессмысленные результаты.
Было бы достаточно просто добавить явную проверку замаскированного массива и вызвать ошибку, если какое-либо из значений действительно замаскировано, но это похоже на очень конкретное, специальное исправление.
Generator.choice
отправляется в __array_function__
? Если нет, то, вероятно, так и должно быть.
Если это так, то я думаю, что мы просто добавим это ко всем остальным «распадам маскированного массива, потому что мы еще не реализовали __array_function__
» ошибки.
Раньше я добавлял ярлык «ошибка», но это субъективное мнение. В numpy есть и другие функции, которые неправильно обрабатывают маскированные массивы (или, лучше сказать, «правильно», поскольку «правильность» также может быть признаком суждения), где мы не обязательно считаем это ошибкой. Возможно, это просто пример неопределенного поведения, и краткий ответ на этот вопрос - «не делайте этого!». Однако было бы лучше, если бы мы могли вызвать исключение вместо того, чтобы возвращать бессмысленные результаты.
Было бы достаточно просто добавить явную проверку замаскированного массива и вызвать ошибку, если какое-либо из значений действительно замаскировано, но это похоже на очень конкретное, специальное исправление.
Я думаю, что если он не обрабатывает его правильно, он не должен разрешать передачу замаскированного массива (должен вызывать исключение), но в основном работает правильно (он работает хорошо, за исключением некоторых случаев). это может вызвать потенциальные проблемы для производственной среды.
__array_function__
в Generator
. В то время как многие заставляют входные данные вести себя непрерывно C, вероятно, некоторые функции не всегда вызывают это достаточно строго.
Если вы добавите NPY_ARRAY_ENSUREARRAY
вы получите заполненный ndarray, игнорирующий маску. Трудно сказать, что это «правильно». В примере @WarrenWeckesser в качестве вероятностей используется pm=np.array([.1,.2,.3,.4])
.