12
votes

Routine numpue pour calculer des matrices de matrice?

Je suis intéressé à utiliser numpy pour calculer tous les mineurs d'une matrice carrée donnée. Y a-t-il une façon slick d'utiliser un tableau pour faire cela? J'imaginais que l'on peut faire pivoter les colonnes, supprimer la dernière colonne, faites pivoter les lignes de la matrice résultante et supprimez la dernière ligne, mais je n'ai rien trouvé dans la documentation numpy qui l'indique est possible.

(Q: Pourquoi cela? A: J'ai une séquence longue {m_n} de matrices assez volumineuses, environ 1 000 000 10 000 x 10 000 matrices, et je veux calculer le déterminant de chaque matrice. Chaque matrice est obtenue à partir de son prédécesseur. en changeant un seul coefficient. Cela va être beaucoup plus rapide de calculer le déterminant de la première matrice dans la séquence, puis calculez la différence det (m_ {n + 1}) - Det (m_n), qui est le produit. du coefficient changé et de son mineur.)


0 commentaires

4 Réponses :


26
votes
first array:     second array:
[[0 0 0],        [[0, 1, 3],
 [2 2 2],         [0, 1, 3],
 [3 3 3]]         [0, 1, 3]]

3 commentaires

Nappe. Je vais l'accepter dès que je découvre pourquoi cela fonctionne. Merci!


Pas de soucis; heureux que ce soit utile.


Pour ajouter les appels de la plage () dans Python 3, vous devez d'abord envelopper une liste d'une liste, par exemple, Liste (plage (i)) + liste (plage (i + 1, arr.fshape [0] )))



3
votes

Si vous ne changez qu'un élément d'une matrice à la fois, vous êtes probablement mieux à l'aide de Formulas de type Sherman-Morrison, ( wiki ): De cette façon, vous avez la complexité de n ^ 2 au lieu de n ^ 3.


0 commentaires

3
votes

La réponse fournie par Unutbu est déjà géniale et d'optimiser l'algorithme @ ev-BR répondait à un voyage intéressant.

Ma réponse ci-dessous à la question est juste de la rendre plus explicite de l'intention . P>

import numpy as np

arr = np.random.normal(0,1,(4,4))



def matrix_minor(arr, i, j):
    return np.delete(np.delete(arr,i,axis=0), j, axis=1)

# tests
arr

matrix_minor(arr, 0, 0)

matrix_minor(arr, 0, 1)


0 commentaires

2
votes

Je pensais à ce problème exact l'autre jour et je faisais quelques essais d'essais et de performances pour cette affaire, je vais donc partager ce que j'ai trouvé.

Ajout aux solutions fournies par Pauldong et Unutbu , je suis venu avec deux solutions supplémentaires. Un ( minor_mask () ) utilise une indexation de matrices numpues basée sur des masques de fantaisie et de l'autre, ( minor_fortran () ) est une solution que je suis arrivée en jouant avec de bon OL 'FORTRAN et légèrement modifié pour compiler avec NUMBA. Mettre toutes les solutions ensemble et effectuer des points de repère:

le code exemple xxx

test de performance

sur ma machine (i5 9600k , 32 Go de RAM, OpenSUse Leap 15.2, Python 3.8.9, Numpy 1.20.3, Numba 0.53.1, IPYKernel 5.5.5), je reçois les résultats suivants pour les petites et grandes matrices à l'aide du code suivant: < PRE> XXX

Calculer

Donc, ensemble, nous constatons que l'approche basée sur la liste de @unutbu effectue pire les deux cas de test, suivi de l'approche @Pauldongs (bien que IMHO étant la solution la plus propre de toutes les solutions).
L'approche d'indexation fantaisie semble fonctionner de manière cohérente pour les petites et grandes matrices, dépassée uniquement par la solution compilée pour les petites matrices. J'anticipe l'approche de masque pour être inefficace pour de très grandes matrices, car nous devons stocker le masque booléen en mémoire pour faire le masquage, mais je n'ai effectué aucun profilage de mémoire ici.

Je sais que la comparaison N'est pas sur un pied d'égalité lorsque l'inclusion de la solution de Numba, mais je dirais que cela est néanmoins pertinent pour le nombre de chiffres avec Python.


0 commentaires