Multiplying each element of a vector with a matrix - matlab

I have a vector v and a matrix M. I want to multiply each element of v with M and then sum all the resulting matrices.
for i=1:length(v)
lala(:,:,i) = v(i).*M;
end
sum(lala, 3)
Is it possible to do this without a for loop?

I think Danil Asotsky's answer is correct. He's exploiting the the linearity of the operation here. I just want to give another solution, using use the Kronecker tensor product, that does not dependent on this linearity property, hence still works with operation other than sum:
kvM = kron(v,M);
result = sum(reshape(kvM,[size(M) numel(v)]),3)
It's too late at my local time, and I dont feel like explaining the details of why this works, if you can't figure out from matlab help and wikipedia, then comment below and I'll explain for you.

Do you have single matrix M that don't depend from i?
In this case sum(v(i) * M) = sum(v(i)) *M.
E.g you will have expected result for code:
v_sum = sum(v);
lala_sum = v_sum * M;

Related

Why is this the correct way to do a cost function for a neural network?

So after beating my head against the wall for a few hours, I looked online for a solution to my problem, and it worked great. I just want to know what caused the issue with the way I was originally going about it.
here are some more details. The input is a 20x20px image from the MNIST datset, and there are 5000 samples, so X, or A1 is 5000x400. There are 25 nodes in the single hidden layer. The output is a one hot vector of 0-9 digits. y (not Y, which is the one hot encoding of y) is a 5000x1 vector with the value of 1-10.
Here was my original code for the cost function:
Y = zeros(m, num_labels);
for i = 1:m
Y(i, y(i)) = 1;
endfor
H = sigmoid(Theta2*[ones(1,m);sigmoid(Theta1*[ones(m, 1) X]'))
J = (1/m) * sum(sum((-Y*log(H]))' - (1-Y)*log(1-H]))')))
But then I found this:
A1 = [ones(m, 1) X];
Z2 = A1 * Theta1';
A2 = [ones(size(Z2, 1), 1) sigmoid(Z2)];
Z3 = A2*Theta2';
H = A3 = sigmoid(Z3);
J = (1/m)*sum(sum((-Y).*log(H) - (1-Y).*log(1-H), 2));
I see that this may be slightly cleaner, but what functionally causes my original code to get 304.88 and the other to get ~ 0.25? Is it the element wise multiplication?
FYI, this is the same problem as this question if you need the formal equation written out.
Thanks for any help I can get! I really want to understand where I'm going wrong
Transfer from the comments:
With a quick look, in J = (1/m) * sum(sum((-Y*log(H]))' - (1-Y)*log(1-H]))'))) there is definetely something going on with the parenthesis, but probably on how you pasted it here, not with the original code as this would throw an error when you run it. If I understand correctly and Y, H are matrices, then in your 1st version Y*log(H) is matrix multiplication while in the 2nd version Y.*log(H) is an entrywise multiplication (not matrix-multiplication, just c(i,j)=a(i,j)*b(i,j) ).
Update 1:
In regards to your question in the comment.
From the first screenshot, you represent each value yk(i) in the entry Y(i,k) of the Y matrix and each value h(x^(i))k as H(i,k). So basically, for each i,k you want to compute Y(i,k) log(H(i,k)) + (1-Y(i,k)) log(1-H(i,k)). You can do it for all the values together and store the result in matrix C. Then C = Y.*log(H) + (1-Y).*log(1-H) and each C(i,k) has the above mentioned value. This is an operation .* because you want to do the operation for each element (i,k) of each matrix (in contrast to multiplying the matrices which is totally different). Afterwards, to get the sum of all the values inside the 2D dimensional matrix C, you use the octave function sum twice: sum(sum(C)) to sum both columnwise and row-wise (or as # Irreducible suggested, just sum(C(:))).
Note there may be other errors as well.

Using spfun with two identically ordered sparse matrices

I got two sparse matrices A and B, which have identical sparsity pattern (all nonzeros are at exactly the same locations):
i = randi(1000,[50,1]);
j = randi(1000,[50,1]);
a = rand(50,1);
b = rand(50,1);
A = sparse(i,j,a,1000,1000);
B = sparse(i,j,b,1000,1000);
I would like to calculate efficiently exp(A-B) only for the nonzeros, and save it back into A.
I tried to use spfun for that task:
f = #(x,y) exp(x-y);
A = spfun(f,A,B);
but I got an error in spfun saying: "Too many input arguments."
Can anyone suggest an efficient way to calculate it?
It should be calculated many times.
Thanks!
Edit: mikkola suggested A = spfun(#f,A-B) which solves the problem, but the question remains how to do it with a function of two variables that can't be solved using the same trick. For example:
g = #(x,y) x.*cos(y);
A = spfun(#g,A,B);
You can't use
A = spfun(#exp, A-B);
because for entries where A an B are equal you will get 0 instead of 1.
To solve that, you can compute the vector of exponentials at the nonzero components, and then build a sparse matrix from that:
A = sparse(i,j,exp(nonzeros(A)-nonzeros(B))); %// if you have i, j stored
or
A(find(A)) = exp(nonzeros(A)-nonzeros(B));
Edit
According to the documentation, spfun can take only two inputs: a function and one sparse matrix.
So you cannot do directly what you want to do. The best solution is probably what has been suggested in the comments, i.e.:
res = spfun(#exp, A-B);
Best,

Error: Matrix dimensions must agree for plot

having a problem with my "new love", matlab: I wrote a function to calculate an integral using the trapz-method: `
function [L]=bogenlaenge_innen(schwingungen)
R = 1500; %Ablegeradius
OA = 1; %Amplitude
S = schwingungen; %Schwingungszahl
B = 3.175; %Tapebreite
phi = 0:2.*pi./10000:2.*pi;
BL = sqrt((R-B).^2+2.*(R-B).*OA.*sin(S.*phi)+OA.^2.*(sin(S.*phi)).^2+OA.^2.*S.^2.*(cos(S.*phi)).^2);
L = trapz(phi,BL)`
this works fine when i start it with one specific number out of the command-window. Now I want to plot the values of "L" for several S.
I did the following in a new *.m-file:
W = (0:1:1500);
T = bogenlaenge_innen(W);
plot(W,T)
And there it is:
Error using .*
Matrix dimensions must agree.
What is wrong? Is it just a dot somewhere? I am using matlab for the second day now, so please be patient.... ;) Thank you so much in advance!
PS: just ignore the german part of the code, it does not really matter :)
In your code, the arrays S and phi in the expression sin(S.*phi) should have same size or one of them should be a constant in order the code works
The error is most likely because you have made it so that the number of elements in schwingungen, i.e. W in your code, must be equal to the number of elements in phi. Since size(W) gives you a different result from size(0:2.*pi./10000:2.*pi), you get the error.
The way .* works is that is multiplies each corresponding elements of two matrices provided that they either have the same dimensions or that one of them is a scalar. So your code will work when schwingungen is a scalar, but not when it's a vector as chances are it has a different number of elements from the way you hard coded phi.
The simplest course of action (not necessarily the most Matlabesque though) for you is to loop through the different values of S:
W = (0:1:1500);
T = zeros(size(W); %Preallocate for speed)
for ii = 1:length(W)
T(ii) = bogenlaenge_innen(W(ii));
end
plot(W,T)
In your function you define phi as a vector of 10001 elements.
In this same function you do S.*phi, so if S is not the same length as phi, you will get the "dimensions must agree" error.
In your call to the function you are doing it with a vector of length 1501, so there is your error.
Regards

How to perform a checkerboard-interpolation in matlab?

I have two matrices A and B containing values for a checkerboard/chessboard-like grid of the form
AxAxAxAx...
xBxBxBxB...
AxAxAxAx...
xBxBxBxB...
...........
...........
Where x represents values not yet known which I want to (linearly) interpolate. What's the easiest way to achieve this?
First thing is probably
C = zeros(size(A)+size(B));
C(1:2:end,1:2:end) = A;
C(2:2:end,2:2:end) = B;
to obtain aforementioned matrix. Now I could loop through all remaining points and take the average of all direct neighbours, for 1) for loops in matlab are slow and 2) there's certainly a way to use interp2, though that seems to require a meshgrid-like grid. So, can this be done easier/faster?
Thanks to woodchips' answer here I found his inpaint_nans, the solution is indeed simple:
C = nan(size(A)+size(B));
C(1:2:end, 1:2:end) = A;
C(2:2:end, 2:2:end) = B;
C = inpaint_nans(C);

Vectorizing the creation of a matrix of successive powers

Let x=1:100 and N=1:10. I would like to create a matrix x^N so that the ith column contains the entries [1 i i^2 ... i^N].
I can easily do this using for loops. But is there a way to do this using vectorized code?
I'd go for:
x = 1:100;
N = 1:10;
Solution = repmat(x,[length(N)+1 1]).^repmat(([0 N])',[1 length(x)]);
Another solution (probably much more efficient):
Solution = [ones(size(x)); cumprod(repmat(x,[length(N) 1]),1)];
Or even:
Solution = bsxfun(#power,x,[0 N]');
Hope this helps.
Sounds like a Vandermonde matrix. So use vander:
A = vander(1:100);
A = A(1:10, :);
Since your matrices aren't that big, the most straight-forward way to do this would be to use MESHGRID and the element-wise power operator .^:
[x,N] = meshgrid(1:100,0:10);
x = x.^N;
This creates an 11-by-100 matrix where each column i contains [i^0; i^1; i^2; ... i^10].
Not sure if it really fits your question.
bsxfun(#power, cumsum(ones(100,10),2), cumsum(ones(100,10),1))
EDIT:
As pointed out by Adrien, my first attempt was not compliant with the OP question.
xn = 100;
N=10;
solution = [ones(1,xn); bsxfun(#power, cumsum(ones(N,xn),2), cumsum(ones(N,xn),1))];
Why not use an easy to understand for loop?
c = [1:10]'; %count to 100 for full scale problem
for i = 1:4; %loop to 10 for full scale problem
M(:,i) = c.^(i-1)
end
It takes more thinking to understand the clever vectorized versions of this code that people have shown. Mine is more of a barbarian way of doing things, but anyone reading it will understand it.
I prefer easy to understand code.
(yes, I could have pre-allocated. Not worth the lowered clarity for small cases like this.)