Quais são as diferenças entre matrizes numpy e matrizes? Qual devo usar?

345

Quais são as vantagens e desvantagens de cada um?

Pelo que vi, qualquer um pode funcionar como um substituto para o outro, se necessário, então devo me preocupar em usar os dois ou devo seguir apenas um deles?

O estilo do programa influenciará minha escolha? Estou fazendo um aprendizado de máquina usando o numpy, portanto existem muitas matrizes, mas também muitos vetores (matrizes).

leve
fonte
3
Não tenho informações suficientes para justificar uma resposta, mas pelo que posso dizer a principal diferença é a implementação da multiplicação. Uma matriz realiza multiplicação de matriz / tensor, enquanto uma matriz faz multiplicação por elementos.
Mike Axiak
5
O Python 3.5 adicionou o operador infix @ para multiplicação de matrizes (PEP 465) e o NumPy 1.10 adicionou suporte para ele. Portanto, se você estiver usando o Python 3.5+ e o NumPy 1.10+, basta escrever em A @ Bvez de A.dot(B), onde Ae Bsão 2D ndarrays. Isso remove a principal vantagem de usar em matrixvez de plain ndarrays, IMHO.
MiniQuark 29/02

Respostas:

396

Numpy matrizes são estritamente 2-dimensional, enquanto numpy matrizes (ndarrays) são N-dimensional. Objetos de matriz são uma subclasse de ndarray, portanto eles herdam todos os atributos e métodos de ndarrays.

A principal vantagem das matrizes numpy é que elas fornecem uma notação conveniente para multiplicação de matrizes: se a e b são matrizes, então a*bé o seu produto de matriz.

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]]

Por outro lado, a partir do Python 3.5, o NumPy suporta a multiplicação de matrizes infix usando o @operador, para que você possa obter a mesma conveniência da multiplicação de matrizes com ndarrays no 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]]

Os objetos da matriz e os ndarrays precisam .Tretornar a transposição, mas os objetos da matriz também têm .Hpara a transposição do conjugado e .Ipara o inverso.

Por outro lado, matrizes numpy obedecem consistentemente à regra de que operações são aplicadas em elementos (exceto para o novo @operador). Assim, se ae bsão matrizes numpy, então a*ba matriz é formada pela multiplicação dos componentes por elementos:

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

Para obter o resultado da multiplicação de matrizes, use np.dot(ou @em Python> = 3.5, como mostrado acima):

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

O **operador também se comporta de maneira diferente:

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

Como aé uma matriz, a**2retorna o produto da matriz a*a. Como cé um ndarray, c**2retorna um ndarray com cada componente quadrado ao elemento.

Existem outras diferenças técnicas entre os objetos da matriz e os ndarrays (relacionados à np.ravelseleção de itens e comportamento de sequência).

A principal vantagem de matrizes numpy é que elas são mais gerais que matrizes bidimensionais . O que acontece quando você deseja uma matriz tridimensional? Então você precisa usar um ndarray, não um objeto de matriz. Assim, aprender a usar objetos de matriz é mais trabalhoso - você precisa aprender operações de objetos de matriz e operações de matriz.

Escrever um programa que mescla matrizes e matrizes dificulta sua vida, porque você precisa acompanhar o tipo de objeto que suas variáveis ​​são, para que a multiplicação não retorne algo que você não espera.

Por outro lado, se você se ater apenas aos ndarrays, poderá fazer tudo o que os objetos da matriz podem fazer e muito mais, exceto com funções / notações ligeiramente diferentes.

Se você está disposto a desistir do apelo visual da notação de produto da matriz NumPy (que pode ser alcançada com a mesma elegância com ndarrays em Python> = 3.5), acho que as matrizes NumPy são definitivamente o caminho a percorrer.

PS. Claro, você realmente não tem que escolher um em detrimento do outro, uma vez np.asmatrixe np.asarraypermitem converter um para o outro (desde que a matriz é 2-dimensional).


Há uma sinopse das diferenças entre NumPy arraysvs NumPy matrixes aqui .

unutbu
fonte
7
Para aqueles perguntando, mat**npara uma matriz pode ser inelegantly aplicado a uma matriz comreduce(np.dot, [arr]*n)
askewchan
6
Ou apenasnp.linalg.matrix_power(mat, n)
Eric
Gostaria de saber se as matrizes seriam mais rápidas ... você pensaria que elas precisam executar menos verificações que o ndarray.
PascalVKooten
11
Na verdade, os testes de timeit mostram operações ndarray como np.dot(array2, array2)as mais rápidas matrix1*matrix2. Isso faz sentido porque matrixé uma subclasse de ndarray que substitui métodos especiais como __mul__. matrix.__mul__chamadasnp.dot . Portanto, há reutilização de código aqui. Em vez de executar menos verificações, o uso matrix*matrixrequer uma chamada de função extra. Portanto, a vantagem de usar matrixé puramente sintática, e não melhor desempenho.
Unutbu
4 * 1 + 3 * 3 dando-lhe 13 quando você fez np.dot (c, d) is not este chamado realmente um produto cruzado em matemática
PirateApp
92

Scipy.org recomenda que você use matrizes:

* 'matriz' ou 'matriz'? Qual devo usar? - Resposta curta

Use matrizes.

  • Eles são o tipo padrão de vetor / matriz / tensor de numpy. Muitas funções numpy retornam matrizes, não matrizes.

  • Há uma distinção clara entre operações entre elementos e operações de álgebra linear.

  • Você pode ter vetores padrão ou vetores de linha / coluna, se desejar.

A única desvantagem de usar o tipo de matriz é que você precisará usar em dotvez de *multiplicar (reduzir) dois tensores (produto escalar, multiplicação de vetores de matrizes etc.).

atomh33ls
fonte
11
Mesmo que a resposta aceita forneça mais informações, a resposta real é realmente manter-se ndarray. O principal argumento para o uso matrixseria se o seu código fosse pesado em álgebra linear e pareceria menos claro com todas as chamadas para a dotfunção. Mas esse argumento desaparecerá no futuro, agora que o operador @ é aceito para uso com multiplicação de matrizes, consulte PEP 465 . Isso precisará do Python 3.5 e da versão mais recente do Numpy. A classe de matriz pode estar obsoleto no futuro distante, então é melhor usar ndarray para novo código ...
Bas Swinckels
6
Essa página graciosamente esquece sobre scipy.sparsematrizes. Se você usar matrizes densas e esparsas no seu código, será muito mais fácil manter isso matrix.
precisa saber é o seguinte
3
Na minha opinião, a principal desvantagem das matrizes é que a divisão de colunas retorna matrizes planas que podem ser confusas e matematicamente não são realmente boas. Isso também leva à importante desvantagem de que matrizes numpy não podem ser tratadas da mesma maneira que matrizes scipy.sparse, enquanto matrizes numpy basicamente podem ser trocadas livremente por matrizes esparsas. É um absurdo nesse contexto que o scipy recomenda o uso de matrizes e, em seguida, não fornece matrizes esparsas compatíveis.
Controlado por rádio
29

Apenas para adicionar um caso à lista de unutbu.

Uma das maiores diferenças práticas para mim de ndarrays numpy em comparação com matrizes numpy ou linguagens de matriz como o matlab, é que a dimensão não é preservada nas operações de redução. As matrizes são sempre 2d, enquanto a média de uma matriz, por exemplo, tem uma dimensão a menos.

Por exemplo, rebaixar linhas de uma matriz ou matriz:

com matriz

>>> 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]])

com matriz

>>> 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]])

Eu também acho que misturar matrizes e matrizes dá origem a muitas horas de depuração "felizes". No entanto, as matrizes scipy.sparse são sempre matrizes em termos de operadores como multiplicação.

Josef
fonte