Как вычесть каждый элемент матрицы из каждой соответствующей строки другой матрицы

A = [1 2 3; 7 6 5]
B = [3 7];
A-B = [1-3 2-3 3-3; 7-7 6-7 5-7];
ans =[-2 -1 0; 0 -1 -2]

Это операция, которую я хочу сделать. Как я мог сделать это с помощью матричных функций, отличных от итерационных решений?


person erogol    schedule 15.11.2012    source источник
comment
кто-то опубликует решение очень быстро, но проверьте repmat (mathworks.com/help /matlab/ref/repmat.html) тем временем. Очень полезная функция.   -  person Dan Becker    schedule 15.11.2012


Ответы (3)


Удобнее всего это сделать с помощью bsxfun, который автоматически расширяет массивы, чтобы они соответствовали размеру (поэтому вам не нужно использовать repmat). Обратите внимание, что мне нужно транспонировать B, чтобы это был массив 2 на 1.

A = [1 2 3; 7 6 5]
B = [3 7];

result = bsxfun(@minus,A,B')

result =

-2    -1     0
 0    -1    -2
person Jonas    schedule 15.11.2012

Я думаю, что ответ Джонаса - лучший. Но для справки, вот решение с использованием явного repmat:

A = [1 2 3; 7 6 5];
B = [3 7];

sz = size(A);
C = A - repmat(B', [1 sz(2:end)]);

Мало того, что ответ Джонаса проще, он на самом деле быстрее в 2 раза для больших матриц на моей машине.

Также интересно отметить, что в случае, когда A представляет собой массив n-d, оба эти решения делают что-то вполне разумное. Матрица C будет иметь следующее свойство:

C(k,:,...,:) == A(k,:,...,:) - B(k)

На самом деле ответ Йонаса будет выполняться и, скорее всего, делать то, что вы хотите, в случае, когда B равно m-d, если начальные размеры A и B' имеют одинаковый размер. Вы можете изменить решение repmat, чтобы имитировать это... и в этот момент вы начинаете заново реализовывать bsxfun!

person Dan Becker    schedule 15.11.2012
comment
Возможно, вы уже видели это, но @Jonas дал отличный ответ на мой вопрос именно по теме решений типа bsxfun против repmat. - person Colin T Bowers; 16.11.2012

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

ie:

A =         | 1 2 3 |
            | 7 6 5 |

B =         | 3 7 |

Нет смысла вычитать матрицу 1х2 из матрицы 2х3.

Однако, если вы умножите B на некоторую промежуточную матрицу, чтобы получить в результате матрицу 2x3, это сработает, т.е.:

B' * Y =    | 3 3 3 |
            | 7 7 7 |

eg:

B' =        diag(B)
   =        | 3 0 |
            | 0 7 |


B' * Y =    | 3 3 3 |
            | 7 7 7 |

Y =         | 1 1 1 |
            | 1 1 1 |

Следовательно, A-B'*Y дает действительное, неитеративное решение.

A-(B'*Y) =      | 1 2 3 |  -  | 3 3 3 |
                | 7 6 5 |     | 7 7 7 |

         = A - (diag(B) * Y )

Единственный «обман» здесь — использование функции diag(), которая преобразует вектор в строго диагональную матрицу. Существует способ вручную разложить набор операций умножения матриц/векторов, чтобы вручную воссоздать функцию diag(), но это будет больше работы, чем мое решение выше.

Удачи!

person Cloud    schedule 15.11.2012
comment
Догберта, он прямо сказал, что хочет вычесть каждый элемент матрицы из соответствующей строки другой матрицы. Это кажется мне четко определенным, если вы говорите о вычитании одномерной матрицы из двумерной матрицы, что, по-видимому, он и имел в виду. - person Dan Becker; 15.11.2012
comment
На мой взгляд, решение, которое я выбрал, было наиболее математическим по своей природе, а не программным (то есть: что-то, что можно было бы проще выразить в виде набора формул, а не набора процедур и операторов if/else). Я думаю, что это было справедливое приближение, потому что родитель этого вопроса не уточнил, что было бы, если бы B была матрицей 2x2 вместо 1x2. Кроме того, поскольку он / она упомянул об использовании матричных функций, я предполагаю, что целью было использование матричной алгебры, а не алгоритмов :) - person Cloud; 15.11.2012