В numpy
некоторые операции возврата в форме , (R, 1)
но некоторые возвращения (R,)
. Это сделает умножение матриц более утомительным, поскольку reshape
требуется явное . Например, с учетом матрицы M
, если мы хотим определить, numpy.dot(M[:,0], numpy.ones((1, R)))
где R
находится число строк (конечно, такая же проблема возникает и по столбцам). Мы получим matrices are not aligned
ошибку, поскольку M[:,0]
она в форме, (R,)
но numpy.ones((1, R))
в форме (1, R)
.
Итак, мои вопросы:
Какая разница между формой
(R, 1)
и(R,)
. Я буквально знаю, что это список чисел и список списков, где весь список содержит только число. Просто интересно, почему бы не спроектироватьnumpy
так, чтобы оно отдавало предпочтение форме,(R, 1)
а не(R,)
упрощало умножение матриц.Есть ли лучшие способы для приведенного выше примера? Без явного изменения, как это:
numpy.dot(M[:,0].reshape(R, 1), numpy.ones((1, R)))
Ответы:
1. Смысл фигур в NumPy
Вы пишете: «Я буквально знаю, что это список чисел и список списков, где весь список содержит только число», но это немного бесполезный способ думать об этом.
Лучший способ думать о массивах NumPy состоит в том, что они состоят из двух частей: буфера данных, который является просто блоком необработанных элементов, и представления. описывающего, как интерпретировать буфер данных.
Например, если мы создадим массив из 12 целых чисел:
Затем
a
состоит из буфера данных, расположенного примерно так:и представление, которое описывает, как интерпретировать данные:
Здесь форма
(12,)
означает, что массив индексируется одним индексом, который работает от 0 до 11. Концептуально, если мы помечаем этот единственный индексi
, массивa
выглядит так:Если мы изменим массив, это не изменит буфер данных. Вместо этого он создает новое представление, описывающее другой способ интерпретации данных. Так после:
массив
b
имеет тот же буфер данныхa
, что и сейчас, но теперь он индексируется двумя индексами, которые работают от 0 до 2 и от 0 до 3 соответственно. Если мы пометим два индексаi
иj
, массив будетb
выглядеть так:которое значит что:
Вы можете видеть, что второй индекс изменяется быстро, а первый - медленно. Если вы предпочитаете, чтобы это было наоборот, вы можете указать
order
параметр:что приводит к массиву, проиндексированному так:
которое значит что:
Теперь должно быть понятно, что означает для массива иметь форму с одним или несколькими размерами размера 1. После:
массив
d
индексируется двумя индексами, первый из которых работает от 0 до 11, а второй индекс всегда равен 0:так что:
Измерение длины 1 является «свободным» (в некотором смысле), поэтому ничто не мешает вам отправиться в город:
давая массив, проиндексированный так:
так что:
См. Внутреннюю документацию NumPy для более подробной информации о том, как реализованы массивы.
2. Что делать?
поскольку
numpy.reshape
просто создает новое представление, вы не должны бояться использовать его при необходимости. Это правильный инструмент для использования, когда вы хотите проиндексировать массив другим способом.Однако в длинных вычислениях обычно можно организовать массивы с «правильной» формой, в первую очередь, и таким образом минимизировать количество преобразований и транспонировок. Но, не видя фактического контекста, который привел к необходимости изменения формы, трудно сказать, что следует изменить.
Пример в вашем вопросе:
но это не реально. Во-первых, это выражение:
вычисляет результат проще. Во-вторых, есть ли что-то особенное в колонке 0? Возможно, что вам действительно нужно:
источник
newaxis
если вам нужна другая ось, например ,a[:, j, np.newaxis]
являетсяj
й столбецa
, иa[np.newaxis, i]
этоi
я строка.(R, )
случае формаndarray
представляет собой кортеж с единичными элементами, поэтому печатается Python с запятой. Без лишней запятой это было бы неоднозначно с выражением в скобках . Аndarray
с одним измерением может быть как вектор-столбец длиныR
. В этом(R, 1)
случае кортеж имеет два элемента, поэтому его можно рассматривать как вектор строк (или матрицу с 1 строкой длиныR
.Разница между
(R,)
и(1,R)
буквально в количестве индексов, которые вам нужно использовать.ones((1,R))
является двумерным массивом, который имеет только одну строкуones(R)
это вектор. Как правило, если для переменной не имеет смысла иметь более одной строки / столбца, следует использовать вектор, а не матрицу с одноэлементным измерением.Для вашего конкретного случая есть несколько вариантов:
1) Просто сделайте второй аргумент вектором. Следующее работает отлично:
2) Если вы хотите использовать матричные операции, подобные матричным, используйте класс
matrix
вместоndarray
. Все матрицы превращаются в двумерные массивы, а оператор*
выполняет умножение матриц вместо поэлементного (так что вам не нужна точка). По моему опыту, это больше проблем, чем оно того стоит, но может быть неплохо, если вы привыкли к Matlab.источник
matrix
класс. В чем проблема дляmatrix
класса BTW?matrix
том, что это только 2D, а также в том, что, поскольку он перегружает оператор '*', функции, написанные для,ndarray
могут завершиться ошибкой, если используются вmatrix
.Форма является кортежем. Если есть только 1 измерение, форма будет одним числом и пустым после запятой. Для размеров 2+ после всех запятых будет число.
источник
Для базового класса массива 2d массивы не более особенные, чем 1d или 3d. Некоторые операции сохраняют размеры, некоторые уменьшают их, другие объединяют или даже расширяют их.
Другие выражения, которые дают тот же массив
MATLAB начинал с двухмерных массивов. Более новые версии допускают больше измерений, но сохраняют нижнюю границу 2. Но вы все равно должны обратить внимание на разницу между матрицей строк и столбцом один, один с формой
(1,3)
v(3,1)
. Как часто ты писал[1,2,3].'
? Я собирался написатьrow vector
иcolumn vector
, но с этим 2d ограничением, в MATLAB нет векторов - по крайней мере, не в математическом смысле вектора как 1d.Вы смотрели
np.atleast_2d
(также версии _1d и _3d)?источник
1) Причина не предпочесть форму
(R, 1)
более(R,)
, что это излишне усложняет. Кроме того, почему предпочтительнее иметь форму(R, 1)
по умолчанию для вектора длины R вместо(1, R)
? Лучше быть простым и понятным, когда вам нужны дополнительные измерения.2) Для вашего примера вы вычисляете внешний продукт, так что вы можете сделать это без
reshape
вызова, используяnp.outer
:источник
M[:,0]
по существу получает все строки с первым элементом, поэтому имеет больше смысла иметь,(R, 1)
чем(1, R)
. 2) Это не всегда можно заменитьnp.outer
, например, точкой для матрицы в форме (1, R), затем (R, 1).matrix
объект. 2) На самом деле,np.outer
работает независимо от того , является ли форма(1, R)
,(R, 1)
или комбинации из двух.Здесь уже есть много хороших ответов. Но мне было трудно найти какой-то пример, где фигура или массив могут сломать всю программу.
Итак, вот один:
Это не удастся с ошибкой:
но если мы добавим
reshape
кa
:это работает правильно!
источник