Numpy рутина для вычислительной матрицы несовершеннолетних? - PullRequest
11 голосов
/ 04 октября 2010

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

(В: Зачем это? A: У меня есть длинная последовательность {M_n} довольно больших матриц, примерно 1 000 000 10 000 x 10 000 матриц, и я хочу вычислить определитель каждой матрицы. Каждая матрица получена из своего предшественника изменяя только один коэффициент. Будет намного быстрее вычислить определитель первой матрицы в последовательности, а затем вычислить разницу det (M_ {n + 1}) - det (M_n), которая является произведением измененного коэффициента и его минор.)

Ответы [ 3 ]

24 голосов
/ 04 октября 2010
In [34]: arr=np.random.random((4,4))

In [35]: arr
Out[35]: 
array([[ 0.00750932,  0.47917318,  0.39813503,  0.11755234],
       [ 0.30330724,  0.67527229,  0.71626247,  0.22526589],
       [ 0.5821906 ,  0.2060713 ,  0.50149411,  0.0328739 ],
       [ 0.42066294,  0.88529916,  0.09179092,  0.39389844]])

Это дает младший из arr с удалением 1-й строки и 2-го столбца:

In [36]: arr[np.array([0,2,3])[:,np.newaxis],np.array([0,1,3])]
Out[36]: 
array([[ 0.00750932,  0.47917318,  0.11755234],
       [ 0.5821906 ,  0.2060713 ,  0.0328739 ],
       [ 0.42066294,  0.88529916,  0.39389844]])

Итак, вы можете использовать что-то вроде этого:

def minor(arr,i,j):
    # ith row, jth column removed
    return arr[np.array(list(range(i))+list(range(i+1,arr.shape[0])))[:,np.newaxis],
               np.array(list(range(j))+list(range(j+1,arr.shape[1])))]

Относительно того, как это работает:

Обратите внимание на форму индексных массивов:

In [37]: np.array([0,2,3])[:,np.newaxis].shape
Out[37]: (3, 1)

In [38]: np.array([0,1,3]).shape
Out[38]: (3,)

Использование [:,np.newaxis] было просто для придания первому массиву формы (3,1).

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

Inв этом случае форма второго массива (3,) накачивается до (1,3).Но (3,1) и (1,3) не совпадают, поэтому (3,1) накачано до (3,3) и (1,3) накачано до (3,3).

Ах, наконец, два массива numpy имеют (после трансляции) одинаковую форму (3,3).

Numpy принимает arr[<array of shape (3,3)>, <array of shape (3,3)>] и возвращает массив формы (что неудивительно)) (3,3).

(i, j) -й элемент возвращаемого массива будет

arr[(i,j)-th element of first array, (i,j)-th element of second array]

, где первый и второй массивы выглядят (концептуально) так:

first array:     second array:
[[0 0 0],        [[0, 1, 3],
 [2 2 2],         [0, 1, 3],
 [3 3 3]]         [0, 1, 3]]
3 голосов
/ 18 октября 2018

Ответ от unutbu уже великолепен, и для оптимизации алгоритма ответ @ ev-br поставил меня в интересное путешествие.

Мой ответ на вопрос, приведенный ниже, просто для того, чтобы сделать его более понятным для намерения.

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)
3 голосов
/ 10 мая 2013

Если вы изменяете только один элемент матрицы за раз, вам, вероятно, лучше использовать формулы типа Шермана-Моррисона ( wiki ): таким образом, у вас сложность N ^ 2 вместо N ^ 3.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...