2011-04-07 9 views
2

У меня 2 матрицы А (NXM) и В (NXD) и хочет, чтобы умножить поэлементно каждый столбец А с ряд B. Есть т столбцов в A и n 1xd векторов в B, поэтому результатом являются m nxd-матрицы. Затем я хочу суммировать (result_i, 1), чтобы получить m 1xd векторы, которые я хочу применить vertcat для получения матрицы mxd. Я делаю эти операции, используя для цикла, и он медленный, потому что n и d большие. Как я могу векторизовать это в Matlab, чтобы сделать его быстрее? Спасибо.Как векторизовать это матричное умножение в MATLAB

EDIT:
Вы все в порядке: я был смущен мой собственный вопрос. То, что я имел в виду под «умножить element-wise, каждый столбец A со строкой B» состоит в том, чтобы умножить n элементов столбца в A с соответствующими n строками B. Что я хочу сделать с одним столбцом A, является как следует (и я повторяю это для т столбцов матрицы а, то vertcat вектора C вместе, чтобы получить матрицу МКД):

column_of_A = 

    3 
    3 
    1 


B = 

    3  1  3  3 
    2  2  1  2 
    1  3  3  3 


C = sum(diag(column_of_A)*B, 1) 

    16 12 15 18 
+2

Если вы умножаете каждый столбец 'A' на каждую строку' B', то вы получаете m * n матриц, а не m. Если нет, то как вы выбираете строку из 'B' для данного столбца' A'? Дано ли это заранее? –

+0

@Itamar Katz: Я должен умножить каждый элемент из m столбцов A _elementwise_ на каждую строку B, то есть [1 2 3] '* [1 1] = [1 1; 2 2; 3 3]. – Martin08

+0

Это не умножение по элементам, а вместо этого это матричное умножение. – Jonas

ответ

6

Вы можете проголосовать за свою деятельность следующим образом. Обратите внимание, однако, что векторизация происходит за счет увеличения использования памяти, поэтому решение может оказаться неработоспособным для вас.

%# multiply nxm A with nx1xd B to create a nxmxd array 
tmp = bsxfun(@times,A,permute(B,[1 3 2])); 

%# sum and turn into mxd 
out = squeeze(sum(tmp,1)); 

Вы можете сделать все в одной строке, которая может помочь Matlab JIT компилятор, чтобы сохранить на память.

EDIT

Вот способ заменить первую строку, если у вас нет bsxfun

[n,m] = size(A); 
[n,d] = size(B); 
tmp = repmat(A,[1 1 d]) .* repmat(permute(B,[1 3 2]),[1,m,1]); 
+0

@Jonas Это, похоже, не создает матрицу 'mxd'. Это дает мне «nxd» (тот же размер, что и «B»). Это или я делаю что-то ужасно глупое (вполне возможно). – Darhuuk

+0

@ Darhuuk: О, я суммировал неправильное измерение. Спасибо за хедз-ап! – Jonas

+0

@Jonas Нет проблем :). Хороший метод, который не знал о 'bsxfun', кажется примерно в 3-10 раз быстрее, чем я предлагал на небольших матрицах, с которыми я тестирую. – Darhuuk

1

это некрасиво, но, насколько я могу судить, это работает. Я не уверен, что это будет быстрее, чем ваш цикл, хотя, плюс, у него большие издержки памяти. Во всяком случае, здесь идет:

A_3D = repmat(reshape(A, size(A, 1), 1, size(A, 2)), 1, size(B, 2)); 
B_3D = repmat(B, [ 1 1 size(A, 2)]); 
result_3D = sum(A_3D .* B_3D, 1); 
result = reshape(result_3D, size(A, 2), size(B, 2)) 

Что она делает это: сделать в 3D-матрицу размером п х 1 х м, так что один столбец в каждом индексе 3-го размера. Затем мы повторяем матрицу, чтобы получить матрицу n x d x m. Мы повторяем B и в третьем измерении. Затем мы производим кусочное умножение всех элементов и суммируем их. Полученная матрица представляет собой матрицу 1 x d x m. Мы преобразуем это в матрицу m x d.

Я почти уверен, что несколько раз меняю размеры размеров в своих объяснениях, но надеюсь, что вы получите общий смысл.

Умножение с диагональной матрицей кажется, по крайней мере, в два раза быстрее, но я не мог найти способ использовать diag, так как он хочет использовать векторную или двумерную матрицу. Я могу попробовать еще раз сегодня вечером, я считаю, что должен быть более быстрый способ :).

[Редактировать] Разбить команду по частям, чтобы хотя бы сделать ее немного читаемой.

0

Это способ, которым я хотел бы сделать это:

сумма (repmat (А, 1,4).* B)

Если вы не знаете, количество столбцов B:.

сумма (repmat (A, 1, размер (В, 2)) * B)

Смежные вопросы