Вычислить внешнее произведение массивов с произвольными размерами

У меня есть два массива A,B, и я хочу взять внешний продукт в их последнем измерении, например. result[:,i,j]=A[:,i]*B[:,j], когда A,B двумерны.

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

В моей конкретной задаче A,B - это срезы из большего трехмерного массива Z. Иногда это может быть вызвано с помощью целочисленных индексов A=Z[:,1,:], B=Z[:,2,:], а в других случаях - срезов A=Z[:,1:3,:],B=Z[:,4:6,:]. Поскольку scipy «сжимает» одноэлементные размеры, я не знаю, какими будут мои входные данные.

Массив-внешний-продукт, который я пытаюсь определить, должен удовлетворять

array_outer_product( Y[a,b,:], Z[i,j,:] ) == scipy.outer( Y[a,b,:], Z[i,j,:] )
array_outer_product( Y[a:a+N,b,:], Z[i:i+N,j,:])[n,:,:] == scipy.outer( Y[a+n,b,:], Z[i+n,j,:] ) 
array_outer_product( Y[a:a+N,b:b+M,:], Z[i:i+N, j:j+M,:] )[n,m,:,:]==scipy.outer( Y[a+n,b+m,:] , Z[i+n,j+m,:] )

для любых массивов ранга 3 Y,Z и целых чисел a,b,...i,j,k...n,N,...

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


person Dave    schedule 23.07.2012    source источник
comment
Можете ли вы опубликовать пример ввода и вывода?   -  person user545424    schedule 24.07.2012
comment
Вы смотрели numpy.multiply.outer? Я думаю, что это то, что он делает (но я не читал этот пост так внимательно).   -  person David    schedule 13.07.2015


Ответы (3)


Возможно, вам повезет с einsum:

http://docs.scipy.org/doc/numpy/reference/generated/numpy.einsum.html

person Nicolas Barbey    schedule 24.07.2012
comment
Я не знал об этой функции. Выглядит очень полезно. Спасибо. - person Michelle Lynn Gill; 24.07.2012
comment
Я бы попробовал это, если бы использовал numpy ›1.6.0 (я не) - person Dave; 25.07.2012

Обнаружив использование многоточия в массивах numpy / scipy, я в конечном итоге реализовал его как рекурсивную функцию:

def array_outer_product(A, B, result=None):
    ''' Compute the outer-product in the final two dimensions of the given arrays.
    If the result array is provided, the results are written into it.
    '''
    assert(A.shape[:-1] == B.shape[:-1])
    if result is None:
        result=scipy.zeros(A.shape+B.shape[-1:], dtype=A.dtype)
    if A.ndim==1:
        result[:,:]=scipy.outer(A, B)
    else:
        for idx in xrange(A.shape[0]):
            array_outer_product(A[idx,...], B[idx,...], result[idx,...])
    return result
person Dave    schedule 01.08.2012

Предполагая, что я правильно вас понял, пару недель назад я столкнулся с аналогичной проблемой в своем исследовании. Я понял, что продукт Кронекера - это просто внешний продукт, сохраняющий размерность. Таким образом, вы могли сделать что-то вроде этого:

import numpy as np

# Generate some data
a = np.random.random((3,2,4))
b = np.random.random((2,5))

# Now compute the Kronecker delta function
c = np.kron(a,b)

# Check the shape
np.prod(c.shape) == np.prod(a.shape)*np.prod(b.shape)

Я не уверен, какую форму вы хотите получить в конце, но вы можете использовать нарезку массива в сочетании с np.rollaxis, np.reshape, np.ravel (и т. Д.), Чтобы перемещать вещи по своему усмотрению. Я предполагаю, что недостатком этого является то, что он выполняет некоторые дополнительные вычисления. Это может иметь значение, а может и не иметь значения, в зависимости от ваших ограничений.

person Michelle Lynn Gill    schedule 24.07.2012