Multiply 2D Matrix with vector to span third dimension - MATLAB - matlab

As I am trying to multiply a m x n Matrix with a p-dimensional vector, I am stumbling across some difficulties.
Trying to avoid for loops, here is what I am looking to achieve
enter code here
M = [1 2 3; p = [1;2;3]
4 5 6;
7 8 9]
I want to obtain a 3x3x3 matrix, where the slices in third dimension are simply the entries of M multiplied by the respective entry in p.
Help is much appreciated

You can use bsxfun with permute for a vectorized (no-loop) approach like so -
out = bsxfun(#times,M,permute(p(:),[3 2 1]))
You would end up with -
out(:,:,1) =
1 2 3
4 5 6
7 8 9
out(:,:,2) =
2 4 6
8 10 12
14 16 18
out(:,:,3) =
3 6 9
12 15 18
21 24 27
With matrix-multiplication -
out = permute(reshape(reshape(M.',[],1)*p(:).',[size(M) numel(p)]),[2 1 3])

Related

Matlab Matrix Vector multiplication

I am totally new to Matlab and have a simple question (not that simple for me):
I have a matrix x:
x = 1 2 3
4 5 6
7 8 9
10 11 12
and a Vector y:
y = 1 2 3
Now I would like to multiply the numbers 1 to 4 by the first element of the Vector, the numbers 5 to 8 by the second element and 9 to 12 by the last element.
CanĀ“t find a solution. Any help is highly appreciated!
Thanks Paul
If you modify your input x to set up all "groups" as columns of a new input, let's say xx, e.g. by transposing and reshaping x accordingly, you can use (element-wise) multiplication. MATLAB's implicit expansion allows such (element-wise) matrix operations. (Before MATLAB R2016b, one would need bsxfun for that.)
That would be my solution:
% Inputs
x = [1 2 3; 4 5 6; 7 8 9; 10 11 12]
y = [1 2 3]
% Transpose and reshape x to set up all "groups" as new columns
xx = reshape(x.', 4, 3)
% (Element-wise) Multiplication using implicit expansion
z = xx .* y
Output:
x =
1 2 3
4 5 6
7 8 9
10 11 12
y =
1 2 3
xx =
1 5 9
2 6 10
3 7 11
4 8 12
z =
1 10 27
2 12 30
3 14 33
4 16 36
Hope that helps!

Matlab multiply each row in matrix by different number

Say that I have a matrix:
A = [ 1 2 3 ; 4 5 6 ; 7 8 9 ; 10 11 12];
Is there a way to multiply :
row 1 by 1
row 2 by 2
row 3 by 3
and so on?
I am able to do this with for loops, however it if for an assignment where they want us to use matrices.
In the actual assignment A is filled with random number but each row which by multiplied consecutively.
Thanks, any help is much appreciated
You just need to multiply a diagonal matrix by A like so.
A = [ 1 2 3 ; 4 5 6 ; 7 8 9 ; 10 11 12];
disp(diag([1 2 3 4]) * A);
1 2 3
8 10 12
21 24 27
40 44 48
You can use bsxfun to accomplish this easily and very quickly
out = bsxfun(#times, [1 2 3 4].', A)
In newer versions of MATLAB (R2016b and newer) you can actually replace bsxfun with simply *
out = [1 2 3 4].' * A;

How to align vectors with asynchronous time stamp in matlab?

I would like to align and count vectors with different time stamps to count the corresponding bins.
Let's assume I have 3 matrix from [N,edges] = histcounts in the following structure. The first row represents the edges, so the bins. The second row represents the values. I would like to sum all values with the same bin.
A = [0 1 2 3 4 5;
5 5 6 7 8 5]
B = [1 2 3 4 5 6;
2 5 7 8 5 4]
C = [2 3 4 5 6 7 8;
1 2 6 7 4 3 2]
Now I want to sum all the same bins. My final result should be:
result = [0 1 2 3 4 5 6 7 8;
5 7 12 16 ...]
I could loop over all numbers, but I would like to have it fast.
You can use accumarray:
H = [A B C].'; %//' Concatenate the histograms and make them column vectors
V = [unique(H(:,1)) accumarray(H(:,1)+1, H(:,2))].'; %//' Find unique values and accumulate
V =
0 1 2 3 4 5 6 7 8
5 7 12 16 22 17 8 3 2
Note: The H(:,1)+1 is to force the bin values to be positive, otherwise MATLAB will complain. We still use the actual bins in the output V. To avoid this, as #Daniel says in the comments, use the third output of unique (See: https://stackoverflow.com/a/27783568/2732801):
H = [A B C].'; %//' stupid syntax highlighting :/
[U, ~, IU] = unique(H(:,1));
V = [U accumarray(IU, H(:,2))].';
If you're only doing it with 3 variables as you've shown then there likely aren't going to be any performance hits with looping it.
But if you are really averse to the looping idea, then you can do it using arrayfun.
rng = 0:8;
output = arrayfun(#(x)sum([A(2,A(1,:) == x), B(2,B(1,:) == x), C(2,C(1,:) == x)]), rng);
output = cat(1, rng, output);
output =
0 1 2 3 4 5 6 7 8
5 7 12 16 22 17 8 3 2
This can be beneficial for particularly large A, B, and C variables as there is no copying of data.

how to multiply 2D slices of two 3D matrices with each other in Matlab

I have two 3D matrices A(kl,1,r) and B(1,rs,r). kl=rs.
I need to get a new matrix C(kl,rs,r) which should have the product of column vector of A(kl,1) by the row vector of B(1,rs) for every page r without for loop
C=zeros(size(A,1),size(B,2),r);
for rr=1:size(A,3)
dummy=squeeze(A(:,:,rr))*squeeze(B(:,:,rr))';
C(:,:,rr)=dummy;
end
can anyone help with that? :)
Using bsxfun, you could do that directly in one line
out = bsxfun(#times, A, B);
Sample Inputs:
>> A
A(:,:,1) =
6
10
3
A(:,:,2) =
2
2
1
>> B
B(:,:,1) =
5 5 4
B(:,:,2) =
8 7 8
Results:
out(:,:,1) =
30 30 24
50 50 40
15 15 12
out(:,:,2) =
16 14 16
16 14 16
8 7 8

How to reshape and interleave matrix elements?

Having the values of time sequence, I would like to reshape it into a nx4 matrix [X y], for the purpose of using these values as input and output values for machine learning algorithm.
X(i) is a 1x3 input vector and y is output scalar value.
The algorithm takes as an input every 2nd sequence value (3 values) in order to predict the 4th value.
To give a practical example, let's say we have a sequence
[1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16]
The [X y] matrix should be the following:
[1 3 5 7; 2 4 6 8; 9 11 13 15; 10 12 14 16]
To get every second row I wrote the following code:
vec1 = timeSeries(1:2:end);
XyVec1 = reshape(vec1,4,[])'
similarly it could be written to get even numbers:
vec2 = timeSeries(2:2:end);
XyVec2 = reshape(vec2,5,[])'
The thing that I don't know how to do is to interleave matrix vec1 and vec2 rows to get
[vec(1,:); vec2(1,:);vec1(2,:), vec2(2,:)...]
Does anyone know how to interleave the rows of two (or more) matrices?
Try
result = zeros(size(vec1,1)+size(vec2,1),size(vec1,2));
result(1:2:end,:) = vec1;
result(2:2:end,:) = vec2;
Reuse matlab indexing facilities ot insert elements in correct rows
Sample octave mock-up: http://ideone.com/RVgmYA
There is this one-liner option
result = kron(vec1, [1;0]) + kron(vec2, [0;1]);
However, #Joel Falcou is faster. Having set the input vectors as
vec1 = rand(1000,1000);
vec2 = -rand(1000,1000);
it gives
Elapsed time is 0.007620 seconds. (indexing)
Elapsed time is 0.054607 seconds. (kron)
Good luck :) figuring out what's going on with those reshape(), permutes():
a = [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16];
reshape(permute(reshape(a,2,4,[]),[2,1,3]),4,[])'
the result
ans =
1 3 5 7
2 4 6 8
9 11 13 15
10 12 14 16
To interleave the vectors as mentioned in the end of your question you can use
reshape([vec1, vec2]', 4, [])'
for
vec1 =
1 3 5 7
9 11 13 15
vec2 =
2 4 6 8
10 12 14 16
it returns
>> reshape([vec1, vec2]', 4, [])'
ans =
1 3 5 7
2 4 6 8
9 11 13 15
10 12 14 16