Каковы различия между массивами numpy и матрицами? Какой из них я должен использовать? - PullRequest
304 голосов
/ 11 ноября 2010

Каковы преимущества и недостатки каждого?

Из того, что я видел, либо один может работать в качестве замены другого, если это необходимо, поэтому стоит ли мне пользоваться обоими или мне следует придерживаться только одного из них?

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

Ответы [ 4 ]

359 голосов
/ 11 ноября 2010

Матрицы Numpy строго двумерны, а массивы Numpy (ndarrays) N-мерный. Матричные объекты являются подклассом ndarray, поэтому они наследуют все атрибуты и методы ndarrays.

Основным преимуществом матриц-матриц является то, что они обеспечивают удобную запись для умножения матриц: если a и b являются матрицами, то a * b является их матрицей продукт.

import numpy as np

a=np.mat('4 3; 2 1')
b=np.mat('1 2; 3 4')
print(a)
# [[4 3]
#  [2 1]]
print(b)
# [[1 2]
#  [3 4]]
print(a*b)
# [[13 20]
#  [ 5  8]]

С другой стороны, начиная с Python 3.5, NumPy поддерживает умножение матриц инфиксов с помощью оператора @, поэтому вы можете добиться такого же удобства умножения матриц с помощью ndarrays в Python> = 3.5.

import numpy as np

a=np.array([[4, 3], [2, 1]])
b=np.array([[1, 2], [3, 4]])
print(a@b)
# [[13 20]
#  [ 5  8]]

И матричные объекты, и ndarrays имеют .T для возврата транспонирования, но матрица объекты также имеют .H для сопряженного транспонирования и .I для обратного.

Напротив, массивы numpy всегда соблюдают правило, согласно которому операции применяется поэлементно (кроме нового оператора @). Таким образом, если a и b являются массивами numpy, то a*b является массивом формируется умножением компонентов поэлементно:

c=np.array([[4, 3], [2, 1]])
d=np.array([[1, 2], [3, 4]])
print(c*d)
# [[4 6]
#  [6 4]]

Чтобы получить результат умножения матриц, вы используете np.dot (или @ в Python> = 3.5, как показано выше):

print(np.dot(c,d))
# [[13 20]
#  [ 5  8]]

Оператор ** также ведет себя по-разному:

print(a**2)
# [[22 15]
#  [10  7]]
print(c**2)
# [[16  9]
#  [ 4  1]]

Поскольку a является матрицей, a**2 возвращает матричное произведение a*a. Поскольку c является ndarray, c**2 возвращает ndarray с каждым компонентом в квадрате поэлементно.

Существуют и другие технические различия между матричными объектами и ndarrays. (относящийся к np.ravel, выбору элементов и поведению последовательности).

Главное преимущество массивов numpy в том, что они более общие, чем 2-мерные матрицы. Что происходит, когда вы хотите 3-мерный массив? затем Вы должны использовать ndarray, а не матричный объект. Таким образом, научиться использовать матрицу объекты - это больше работы - вы должны изучить операции с матричными объектами и Операции ndarray.

Написание программы, которая использует и матрицы, и массивы, делает вашу жизнь трудной потому что вы должны отслеживать, какой тип объекта ваши переменные, чтобы умножение возвращает то, чего вы не ожидаете.

Напротив, если вы придерживаетесь только ndarrays, то вы можете делать все матричные объекты могут делать и многое другое, кроме как с немного отличающимися функции / нотации.

Если вы готовы отказаться от визуальной привлекательности матричного продукта NumPy нотации (что может быть достигнуто почти так же элегантно с ndarrays в Python> = 3.5), тогда я думаю, что массивы NumPy, безусловно, путь.

PS. Конечно, вам действительно не нужно выбирать одно за счет другого, поскольку np.asmatrix и np.asarray позволяют преобразовывать одно в другое (как пока массив является двумерным).


Существует краткий обзор различий между NumPy arrays против NumPy matrix es здесь .

83 голосов
/ 14 марта 2013

Scipy.org рекомендует использовать массивы:

* 'массив' или 'матрица'?Какой я должен использовать?- Краткий ответ

Используйте массивы.

  • Это стандартный вектор / матрица / тензорный тип numpy.Многие числовые функции возвращают массивы, а не матрицы.

  • Существует четкое различие между поэлементными операциями и операциями линейной алгебры.

  • Вы можетеиметь стандартные векторы или векторы строк / столбцов, если хотите.

Единственным недостатком использования типа массива является то, что вам придется использовать dot вместо * для умножения (уменьшить) два тензора (скалярное произведение, умножение матрицы на вектор и т. д.).

28 голосов
/ 11 ноября 2010

Просто чтобы добавить один случай в список unutbu.

Одно из самых больших практических отличий для меня от numpy ndarrays по сравнению с numpy матрицами или матричными языками, такими как matlab, заключается в том, что измерение не сохраняется в операциях сокращения. Матрицы всегда 2d, в то время как среднее значение массива, например, имеет на одно измерение меньше.

Например, унизить строки матрицы или массива:

с матрицей

>>> m = np.mat([[1,2],[2,3]])
>>> m
matrix([[1, 2],
        [2, 3]])
>>> mm = m.mean(1)
>>> mm
matrix([[ 1.5],
        [ 2.5]])
>>> mm.shape
(2, 1)
>>> m - mm
matrix([[-0.5,  0.5],
        [-0.5,  0.5]])

с массивом

>>> a = np.array([[1,2],[2,3]])
>>> a
array([[1, 2],
       [2, 3]])
>>> am = a.mean(1)
>>> am.shape
(2,)
>>> am
array([ 1.5,  2.5])
>>> a - am #wrong
array([[-0.5, -0.5],
       [ 0.5,  0.5]])
>>> a - am[:, np.newaxis]  #right
array([[-0.5,  0.5],
       [-0.5,  0.5]])

Я также думаю, что смешивание массивов и матриц порождает много «счастливых» часов отладки. Однако матрицы scipy.sparse всегда являются матрицами в терминах таких операторов, как умножение.

18 голосов
/ 26 января 2016

Как уже упоминали другие, возможно, главное преимущество matrix состояло в том, что он предоставлял удобную запись для умножения матриц.

Однако, в Python 3.5, наконец, есть специальный инфиксный оператор для матрицыумножение : @.

В последних версиях NumPy его можно использовать с ndarray s:

A = numpy.ones((1, 3))
B = numpy.ones((3, 3))
A @ B

Так что в настоящее время, даже больше, когда вы сомневаетесь, выследует придерживаться ndarray.

...