Мы заметили, что смешанное использование причудливой индексации и нарезки настолько запутанно и недокументировано для многомерных массивов, например:
In [114]: x = np.arange(720).reshape((2,3,4,5,6))
In [115]: x[:,:,:,0,[0,1,2,4,5]].shape
Out[115]: (2, 3, 4, 5)
In [116]: x[:,:,0,:,[0,1,2,4,5]].shape
Out[116]: (5, 2, 3, 5)
Я прочитал об использовании причудливого индексирования на https://numpy.org/doc/stable/user/basics.indexing.html и могу это понять x[:,0,:,[1,2]] = [x[:,0,:,1], x[:,0,:,2]]
. Однако я не могу понять, почему результат для приведенных выше Input [115]
и Input [116]
различается по первому измерению. Может ли кто-нибудь указать, где задокументированы такие правила вещания?
Спасибо!
Я пытался найти документацию для причудливой индексации, а также публиковать проблемы в репозитории numpy на Github.
В операции индексирования есть две части: подпространство, определяемое базовой индексацией (исключая целые числа), и подпространство из расширенной части индексации. Следует различать два случая комбинации индексов:
- Расширенные индексы разделены срезом, многоточием или новой осью. Например, x[обр1, :, обр2].
- Все расширенные индексы расположены рядом друг с другом. Например, x[..., arr1, arr2, :], но не x[arr1, :, 1], поскольку 1 в этом отношении является расширенным индексом.
В первом случае измерения, полученные в результате операции расширенного индексирования, идут первыми в результирующем массиве, а измерения подпространства — после них. Во втором случае измерения из операций расширенного индексирования вставляются в результирующий массив в том же месте, что и в исходном массиве (последняя логика заставляет простое расширенное индексирование вести себя точно так же, как нарезку).
Из https://numpy.org/doc/stable/user/basics.indexing.html#combining-advanced-and-basic-indexing
В вашем первом примере есть расширенная индексация в четвертом и пятом измерении (расширенная индексация в двух измерениях «рядом друг с другом»). Во втором примере есть операция нарезки (базовая индексация), разделяющая две расширенные индексации.
Спасибо за указание на документацию. Кстати, вы знаете, почему numpy приводит к такому нелогичному поведению? Я пробовал Pytorch, и он ведет себя по-другому (но его легко понять) с Numpy.
Документация по смешанному расширенному и базовому уровню является новой, так как в последний раз я пытался ответить на этот вопрос. В прошлом просто говорилось, что из-за двусмысленности размеры Алисы помещаются последними.
«потому что в подпространстве индексации нет однозначного места для перетаскивания, поэтому оно прикрепляется к началу. Всегда можно использовать .transpose() для перемещения подпространства в любое место». Очевидно, в процессе есть двусмысленность, но я не могу ее найти.
@ rochard4u, неоднозначность становится более очевидной, когда срез разделяет массивы расширенного индексирования.
Некоторое дополнительное понимание того, почему существует двусмысленность:
В последнем случае в вопросе 3-я и 5-я оси индексируются и, таким образом, исчезают из нового массива. Где-то нужно добавить новую ось (с формой, равной трансляции индексов). Если бы я был пустым и мне нужно было бы вставить массив формы (5,)
в массив с «формой» (2, 3, -, 5, -)
, поместил бы я его вместо первого отсутствующего измерения? Или второй?
Именно потому, что срез разделяет два расширенных индекса, numpy не может заменить последовательный набор осей и, следовательно, не знает, вставлять ли новую ось до или после разделяющих срезов. В результате новая ось вставляется спереди:
(5, 2, 3, 5)
^ ^^^^^^^--- old dimensions
|
new dimension
Только в первом случае, когда все исчезающие оси являются смежными («форма» (2, 3, 4, -, -)
), новые оси могут быть однозначно вставлены в конце.
Примечание. За кулисами numpy всегда вставляет новые оси в начале. Он просто (в основном для удобства, я полагаю) перемещает массив для перемещения новых осей на место, когда это однозначно.
Также интересно Numpy Enhancement Proposal 21
Спасибо за объяснение двусмысленности здесь.
Из-за улучшений в документации мы должны сопротивляться попыткам пометить этот вопрос как дубликат.