Quali sono le differenze tra matrici e matrici intorpidite? Quale dovrei usare?


346

Quali sono i vantaggi e gli svantaggi di ciascuno?

Da quello che ho visto, uno può funzionare come sostituto dell'altro, se necessario, quindi dovrei preoccuparmi di usarli entrambi o dovrei attenermi a uno solo di essi?

Lo stile del programma influenzerà la mia scelta? Sto facendo un po 'di apprendimento automatico usando numpy, quindi ci sono davvero molte matrici, ma anche molti vettori (array).


3
Non ho abbastanza informazioni per giustificare una risposta, ma da quello che posso dire la differenza principale è l'implementazione della moltiplicazione. Una matrice esegue la moltiplicazione matrice / tensore, mentre una matrice eseguirà la moltiplicazione in termini di elementi.
Mike Axiak,

5
Python 3.5 ha aggiunto l'operatore infix @ per la moltiplicazione di matrici (PEP 465) e NumPy 1.10 ha aggiunto il supporto per esso. Quindi se stai usando Python 3.5+ e NumPy 1.10+, puoi semplicemente scrivere A @ Binvece di A.dot(B)dove Ae dove Bsono i 2D ndarray. Questo elimina il vantaggio principale dell'utilizzo matrixinvece di plain ndarrays, IMHO.
MiniQuark,

Risposte:



396

Le matrici numpy sono strettamente bidimensionali, mentre le matrici numpy (ndarrays) sono N-dimensionali. Gli oggetti Matrix sono una sottoclasse di ndarray, quindi ereditano tutti gli attributi e i metodi di ndarrays.

Il vantaggio principale delle matrici intorpidite è che forniscono una comoda notazione per la moltiplicazione di matrici: se aeb sono matrici, allora a*bè il loro prodotto di matrice.

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

D'altra parte, a partire da Python 3.5, NumPy supporta la moltiplicazione di matrici di infissi utilizzando l' @operatore, in modo da poter ottenere la stessa comodità di moltiplicazione di matrici con ndarrays in 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]]

Sia gli oggetti matrice che gli ndarrays devono .Trestituire la trasposizione, ma anche gli oggetti matrice hanno .Hper la trasposizione coniugata e .Iper l'inverso.

Al contrario, gli array intorpiditi rispettano costantemente la regola secondo cui le operazioni vengono applicate in termini di elementi (ad eccezione del nuovo @operatore). Pertanto, se ae bsono matrici intorpidite, allora a*bè l'array formato moltiplicando i componenti in termini di elementi:

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

Per ottenere il risultato della moltiplicazione della matrice, usi np.dot(o @in Python> = 3.5, come mostrato sopra):

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

L' **operatore si comporta anche diversamente:

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

Poiché aè una matrice, a**2restituisce il prodotto matrice a*a. Poiché cè un ndarray, c**2restituisce un ndarray con ciascun componente al quadrato dell'elemento.

Esistono altre differenze tecniche tra oggetti matrice e ndarrays (che hanno a che fare con la np.ravelselezione degli oggetti e il comportamento della sequenza).

Il vantaggio principale delle matrici insensibili è che sono più generali delle matrici bidimensionali . Cosa succede quando si desidera un array tridimensionale? Quindi devi usare un ndarray, non un oggetto matrice. Pertanto, imparare a usare gli oggetti matrice è più lavoro: devi imparare le operazioni con gli oggetti matrice e le operazioni ndarray.

Scrivere un programma che mescola matrici e matrici ti rende la vita difficile perché devi tenere traccia di quale tipo di oggetto sono le tue variabili, per evitare che la moltiplicazione restituisca qualcosa che non ti aspetti.

Al contrario, se rimani solo con ndarrays, puoi fare tutto ciò che gli oggetti matrice possono fare, e altro, tranne con funzioni / notazioni leggermente diverse.

Se sei disposto a rinunciare all'appeal visivo della notazione del prodotto a matrice NumPy (che può essere raggiunto quasi altrettanto elegantemente con ndarrays in Python> = 3.5), allora penso che gli array NumPy siano sicuramente la strada da percorrere.

PS. Naturalmente, davvero non c'è bisogno di scegliere uno a discapito dell'altro, dal momento che np.asmatrixe np.asarraypermetterà di convertire l'uno all'altro (fino a quando la matrice è 2-dimensionale).


C'è una sinossi delle differenze tra NumPy arrayse NumPy matrixes qui .


7
Per quelli che si chiedono, mat**nper una matrice può essere applicata in modo non reduce(np.dot, [arr]*n)
elegante

6
O semplicementenp.linalg.matrix_power(mat, n)
Eric,

Mi chiedo se le matrici sarebbero più veloci ... penseresti che debbano eseguire meno controlli di ndarray.
PascalVKooten,

1
In realtà, i test timeit mostrano operazioni ndarray come np.dot(array2, array2)più veloci di matrix1*matrix2. Questo ha senso perché matrixè una sottoclasse di ndarray che sostituisce metodi speciali come __mul__. matrix.__mul__chiamatenp.dot . Quindi c'è un riutilizzo del codice qui. Invece di eseguire meno controlli, l'utilizzo matrix*matrixrichiede una chiamata di funzione aggiuntiva. Quindi il vantaggio dell'uso matrixè puramente sintattico, non con prestazioni migliori.
unutbu,

4 * 1 + 3 * 3 che ti danno 13 quando hai fatto np.dot (c, d) non è in realtà questo chiamato un prodotto incrociato in matematica
PirateApp

92

Scipy.org ti consiglia di usare array:

* 'array' o 'matrix'? Quale dovrei usare? - Risposta breve

Usa array.

  • Sono il tipo standard di vettore / matrice / tensore del numpy. Molte funzioni numpy restituiscono array, non matrici.

  • Esiste una chiara distinzione tra operazioni basate sull'elemento e operazioni algebriche lineari.

  • Se lo desideri, puoi avere vettori standard o vettori di riga / colonna.

L'unico svantaggio dell'uso del tipo di array è che dovrai usare dotinvece di *moltiplicare (ridurre) due tensori (prodotto scalare, moltiplicazione di matrici ecc.).


11
Anche se la risposta accettata fornisce maggiori informazioni, la vera risposta è proprio quella di attenersi ndarray. L'argomento principale da usare matrixsarebbe se il tuo codice è pesante nell'algebra lineare e sembrerebbe meno chiaro con tutte le chiamate alla dotfunzione. Ma questo argomento scomparirà in futuro, ora che l'operatore @ è accettato per l'uso con la moltiplicazione della matrice, vedere PEP 465 . Ciò richiederà Python 3.5 e l'ultima versione di Numpy. La classe matrix potrebbe essere deprecata in un lontano futuro, quindi è meglio usare ndarray per il nuovo codice ...
Bas Swinckels

6
Quella pagina dimentica gentilmente delle scipy.sparsematrici. Se usi matrici dense e sparse nel tuo codice, è molto più facile attenersi matrix.
David Nemeskey,

3
A mio avviso, il principale svantaggio delle matrici è che la suddivisione in colonne restituisce matrici piatte che possono essere fonte di confusione e matematicamente non sono realmente valide. Questo porta anche all'importante svantaggio che le matrici intorpidite non possono essere trattate allo stesso modo delle matrici scipy.sparse mentre le matrici intorpidite possono sostanzialmente essere scambiate liberamente con matrici sparse. Un po 'assurdo in questo contesto che scipy consiglia di usare array e quindi non fornisce array sparsi compatibili.
Radio Controlled

29

Solo per aggiungere un caso all'elenco di unutbu.

Una delle maggiori differenze pratiche per me dei ndarrays intorpiditi rispetto alle matrici intorpidite o ai linguaggi delle matrici come matlab, è che la dimensione non viene mantenuta nelle operazioni di riduzione. Le matrici sono sempre 2d, mentre la media di un array, ad esempio, ha una dimensione in meno.

Ad esempio le righe di decodifica di una matrice o matrice:

con matrice

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

con matrice

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

Penso anche che la miscelazione di matrici e matrici dia origine a molte "felici" ore di debug. Tuttavia, le matrici scipy.sparse sono sempre matrici in termini di operatori come la moltiplicazione.


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.