简体   繁体   中英

How to component wise multiply a vector and a matrix in MATLAB?

I wanted to compute the follow expression:

a_2 = c_k2 * (b - t_k2)

where t_k2 is a column vector of size K1 x K2 , b is of size K1 x 1 and c_k2 is a constant ( 1 x 1 ). But I have K2 of those t vectors. I know that I could just do:

t % (K1 x K2)
b % (K1 x 1)
a_k2 % (K1 x K2)
c % (K2 x 1)
for k2=1:K2
    t_k2 = t(:,k2); % K1 x 1
    c_k2 = c(k2);
    a_k2(:,k2) = c_k2 * (b - t_k2); % K1 x 1
end

but I was wondering if there was a cleaver way to write it as a single line in MATLAB (to avoid all the indexing and the looping and hopefully gain speed up). Is that possible?

My initial idea could be to replicate b into a matrix of size 'K1 x K2'. Assuming that can be done, denote that with B. Then we can compute B - t and we have each entry of (b - t_k2) . Assuming we can even do this, the only idea I have is to replicate each constant c_k into a vector of that number as in c_k_vec = [c_k, ... c_k] and then do a element wise multiplication of those matrices. It's clear that B should:

B = repmat(b, [1,K2]);

and

B - t

accomplishes part of the task...but its not clear to me how to produce the matrix where the columns are c_k_vec = [c_k, ... c_k] in one line without looping. The idea is that a vector c matches with each column B - t and we want to multiply each column of B - t by the entries in the vector x.

Maybe this isn't possible...

You pretty much answered your question (again :)). You can certainly use repmat on b to duplicate the column vector K2 times horizontally to make the dimensions consistent. However, you have a slight problem with the c matrix as the dimensions are currently incompatible if you want to achieve the computation of the output matrix vectorized.

If I understand your problem correctly, each row of your output should be multiplied by the corresponding row of c . In that case, it's simply another case of running repmat on c , but duplicate this vector K1 times .

Concretely, you can do this:

a_k2 = repmat(c.', K1, 1) .* (repmat(b, 1, K2) - t);

Take note that I had to transpose c because you said it was a K2 x 1 vector. To make sure that there are matches in size, I transposed this so that it becomes 1 x K2 , and repmat 'ing will replicate this matrix to become K1 x K2 to match with the intermediate result.

However, this looks a bit inelegant. I encourage you to take advantage of bsxfun , which does the replication under the hood:

a_k2 = bsxfun(@times, c.', bsxfun(@minus, b, t));

What will be done first is b gets replicated for as many columns as there are t , and then we will multiply this intermediate result by the right c values by replicating the c vector to match up in shape with the intermediate result. The beauty with bsxfun is that you don't need to know how many times you need to repmat something. bsxfun figures that out for you.


To show that all three statements are equivalent, let's generate some sample data, and run through your for loop, then the two pieces of code I wrote above:

%// Data setup
rng(123);
K1 = 10;
K2 = 12;

t = rand(K1, K2);
b = rand(K1, 1);
c = rand(K2, 1);

%// Your code
for k2=1:K2
    t_k2 = t(:,k2); % K1 x 1
    c_k2 = c(k2); %// Note - typo here
    a_k2(:,k2) = c_k2 * (b - t_k2); % K1 x 1
end

%// Using repmat
a_k2r = repmat(c.', K1, 1) .* (repmat(b, 1, K2) - t);

%// Using bsxfun
a_k2b = bsxfun(@times, c.', bsxfun(@minus, b, t));

a_2k is what is produced from your code and a_k2r , a_k2b are the outputs from the two pieces of code I suggested. If we display them all, we get:

>> a_k2

a_k2 =

  Columns 1 through 7

    0.1527    0.0905    0.1628    0.7042    0.2768    0.0623    0.1011
   -0.0574   -0.0840   -0.3855   -0.1957    0.0905   -0.0491   -0.1620
    0.0480   -0.0235   -0.2595   -0.1198   -0.0244   -0.0246   -0.1424
   -0.0229    0.0741   -0.0547    0.0228    0.1035   -0.0020   -0.0663
    0.1334    0.0812    0.1078    0.4122    0.0350    0.0444    0.0255
    0.4098    0.0396    0.3969    0.5813    0.7211    0.0539    0.3857
   -0.5287    0.0121   -0.0626   -0.1462   -0.2218   -0.0127   -0.2168
   -0.0881    0.0626    0.2019   -0.2849   -0.4143   -0.0093    0.1374
    0.2384    0.0444    0.3083   -0.1188    0.2827   -0.0054    0.2625
    0.0016   -0.0221   -0.1421   -0.0931   -0.2149   -0.0092   -0.0763

  Columns 8 through 12

    0.1656    0.2643    0.1098    0.0366    0.1747
   -0.1386   -0.2183   -0.4315   -0.0428   -0.0435
   -0.0685   -0.1180   -0.0347    0.0174    0.0360
   -0.0416    0.0591   -0.1329    0.0363   -0.0918
    0.1812   -0.0105    0.1691    0.0541    0.1672
    0.0796    0.0640    0.1599    0.0301    0.1280
   -0.0612   -0.0450    0.0583   -0.0550   -0.0953
    0.0829    0.2347    0.0906    0.0010    0.0127
    0.1338    0.2263    0.3101   -0.0044    0.2388
   -0.0616   -0.0017    0.0279    0.0009   -0.1763

>> a_k2b

a_k2b =

  Columns 1 through 7

    0.1527    0.0905    0.1628    0.7042    0.2768    0.0623    0.1011
   -0.0574   -0.0840   -0.3855   -0.1957    0.0905   -0.0491   -0.1620
    0.0480   -0.0235   -0.2595   -0.1198   -0.0244   -0.0246   -0.1424
   -0.0229    0.0741   -0.0547    0.0228    0.1035   -0.0020   -0.0663
    0.1334    0.0812    0.1078    0.4122    0.0350    0.0444    0.0255
    0.4098    0.0396    0.3969    0.5813    0.7211    0.0539    0.3857
   -0.5287    0.0121   -0.0626   -0.1462   -0.2218   -0.0127   -0.2168
   -0.0881    0.0626    0.2019   -0.2849   -0.4143   -0.0093    0.1374
    0.2384    0.0444    0.3083   -0.1188    0.2827   -0.0054    0.2625
    0.0016   -0.0221   -0.1421   -0.0931   -0.2149   -0.0092   -0.0763

  Columns 8 through 12

    0.1656    0.2643    0.1098    0.0366    0.1747
   -0.1386   -0.2183   -0.4315   -0.0428   -0.0435
   -0.0685   -0.1180   -0.0347    0.0174    0.0360
   -0.0416    0.0591   -0.1329    0.0363   -0.0918
    0.1812   -0.0105    0.1691    0.0541    0.1672
    0.0796    0.0640    0.1599    0.0301    0.1280
   -0.0612   -0.0450    0.0583   -0.0550   -0.0953
    0.0829    0.2347    0.0906    0.0010    0.0127
    0.1338    0.2263    0.3101   -0.0044    0.2388
   -0.0616   -0.0017    0.0279    0.0009   -0.1763

>> a_k2r

a_k2r =

  Columns 1 through 7

    0.1527    0.0905    0.1628    0.7042    0.2768    0.0623    0.1011
   -0.0574   -0.0840   -0.3855   -0.1957    0.0905   -0.0491   -0.1620
    0.0480   -0.0235   -0.2595   -0.1198   -0.0244   -0.0246   -0.1424
   -0.0229    0.0741   -0.0547    0.0228    0.1035   -0.0020   -0.0663
    0.1334    0.0812    0.1078    0.4122    0.0350    0.0444    0.0255
    0.4098    0.0396    0.3969    0.5813    0.7211    0.0539    0.3857
   -0.5287    0.0121   -0.0626   -0.1462   -0.2218   -0.0127   -0.2168
   -0.0881    0.0626    0.2019   -0.2849   -0.4143   -0.0093    0.1374
    0.2384    0.0444    0.3083   -0.1188    0.2827   -0.0054    0.2625
    0.0016   -0.0221   -0.1421   -0.0931   -0.2149   -0.0092   -0.0763

  Columns 8 through 12

    0.1656    0.2643    0.1098    0.0366    0.1747
   -0.1386   -0.2183   -0.4315   -0.0428   -0.0435
   -0.0685   -0.1180   -0.0347    0.0174    0.0360
   -0.0416    0.0591   -0.1329    0.0363   -0.0918
    0.1812   -0.0105    0.1691    0.0541    0.1672
    0.0796    0.0640    0.1599    0.0301    0.1280
   -0.0612   -0.0450    0.0583   -0.0550   -0.0953
    0.0829    0.2347    0.0906    0.0010    0.0127
    0.1338    0.2263    0.3101   -0.0044    0.2388
   -0.0616   -0.0017    0.0279    0.0009   -0.1763

... and for some bonus, let's compare the absolute difference between the original matrix (your code) and each one of these and find the maximum deviation:

>> format long g
>> max_diff1 = max(abs(a_k2(:) - a_k2r(:)))

max_diff1 =

     0

>> max_diff2 = max(abs(a_k2(:) - a_k2b(:)))

max_diff2 =

     0

As you can see, if we took an element wise subtraction between how you computed a_2k with what I produced with repmat and bsxfun , it says that the largest element in difference between the two matrices is 0.... so, we can see that there is no difference between the source and either of the alternative approaches.

我不确定c_k_vec的来源,但是通过。*可以很容易地对每个元素进行向量乘法,因此,如果您解决了(b-t_k2)部分,则将常数与。*相乘应该非常简单

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM