For the linear regression, I want to generate the matrix for polynomials of n degree.
if n is 1
X=[x(:), ones(length(x),1)]
if n is 2
X=[x(:).^2 x(:) ones(length(x),1)]
...
if n is 5
X=[x(:).^5 x(:).^4 x(:).^3 x(:).^2 x(:) ones(length(x),1)]
I do not know how to code with matlab if I set n=6 and it will automatically generate the wanted X matrix. Hope you can help me.
This can be easily done with bsxfun:
X = bsxfun(#power, x(:), n:-1:0);
Or, in Matlab versions from R1016b onwards, you can use implicit expansion:
X = x(:).^(n:-1:0);
Check out the polyval function. I believe that will do what you’re looking for.
To get increasing the polynomial to increase in degree, you can increase the length of your p argument using a loop.
If you write edit polyfit you can see how MATLAB have implemented the polyfit command, which is similar to what you are trying to do. In there you will find the code
% Construct the Vandermonde matrix V = [x.^n ... x.^2 x ones(size(x))]
V(:,n+1) = ones(length(x),1,class(x));
for j = n:-1:1
V(:,j) = x.*V(:,j+1);
end
Which constructs the matrix you are interested in. The benefit of this method over the bsxfun is that you only calculate x(:).^n and then saves the intermediary results. Instead of treating all powers as seperate problems, e.g. x(:)^(n-1) as a seperate problem to x(:).^n.
Related
I've been trying to vectorize a for loop in Matlab because it bottlenecks the whole program but I have no clue about how to do it when iterating on different rows or columns of a single matrix inside of the loop. Here's the code :
// X is an n*k matrix, W is n*n
// W(i,j) stores the norm of the vector resulting from subtracting
// the j-th line of X from its i-th line.
for i = 1:n
for j = 1:n
W(i,j) = norm(X(i,:) - X(j,:))
end
end
Edit :
I chose Luis Mendo's answer as it was the most convenient for me and the one that's closer to the mathematical concept behind my algorithm, yet all three answers were correct and I'd advise to use the one that's the most convenient depending on which Matlab Toolboxes you have or the way you want to code.
I also noticed that the common point of all answers was to use a different format, for example : using an array that would store the indices, reshaping current arrays, using one more dimension...
So I think that's the right thing to explore if you have a similar problem.
Using combinatory:
% sample data
X = randi(9,5,4);
n = size(X,1);
% row index combinations
combIdx = combvec(1:n,1:n);
% difference between row combinations
D = X(combIdx(1,:),:)-X(combIdx(2,:),:);
% norm of each row
W = diag(sqrt(D*D'));
% reshape
W = reshape(W,n,[]);
Here is another solution that may be more efficient for big matrices.
For Matlab >=R2016 you can simple use
W = sqrt(sum(abs(reshape(X,n,1,k) - reshape(X,1,n,k)).^2,3))
(if your array is real-valued you can also skip the abs). For earlier versions of Matlab you need to add some repmat magic, namely:
W = sqrt(sum(abs(repmat(reshape(X,n,1,k),[1,n,1]) - repmat(reshape(X,1,n,k),[n,1,1])).^2,3));
P.S.: R2017b might make it even more convenient, at least the release notes mention a function called vecnorm that could replace the somewhat ugly sqrt(sum(abs(.).^2))) thing. But the documentation is not up yet so I don't know what exactly it will do. "
If you have the Statistics Toolbox, use pdist:
W = squareform(pdist(X));
No toolbox: good old bsxfun:
W = sqrt(sum(bsxfun(#minus, permute(X, [1 3 2]), permute(X, [3 1 2])).^2, 3));
I have the following matrix
R=(A-C)*inv(A+B-C-C')*(A-C');
where A and B are n by n matrices. I want to find n*n matrix C such that the determinant of R is minimized, SO:
C=arg min (det(R));
Is there any function in MATLAB that can handle this problem?
It seems like you are trying to find the minimum of an unconstrained multivariable function. This can probably be achieved with fminunc
fun = #(x)x(1)*exp(-(x(1)^2 + x(2)^2)) + (x(1)^2 + x(2)^2)/20;
x0 = [1,2];
[x,fval] = fminunc(fun,x0)
Note that there are no examples in the documentation where a matrix is used, this is probably because horrendous performance could be expected when trying to solve this problem for a matrix of any nontiny size. (This is not because of matlab, but because of the nature of the problem).
It is also good to realize that this method does not (cannot) guarantee an optimum, only a local optimum.
I have the following code, how will I be able to simplify it using the function as it currently runs pretty slow, assume X is 10x7 and Y is 4x7 and D is a matrix stores the correlation between each pair of vectors. If the solution is to use the xcorr2 function can someone show me how it is done?
for i = 1:4
for j = 1:10
D(j,i) = corr2(X(j,:),Y(i,:));
end
end
Use pdist2 (Statistics toolbox) with 'correlation' option. It's faster than your code (even with preallocation), and requires just one line:
D = 1-pdist2(X,Y,'correlation');
Here is how I would do it:
First of all, store/process your matrix transposed. This makes for easier use of the correlation function.
Now assuming you have matrices X and Y and want to get the correlations between combinations of columns, this is easily achieved with a single loop:
Take the first column of X
use corrcoef to determine the correlation with all columns of Y at once.
As long as there is one, take the next column of X
Alternate to this, you can check whether it helps to replace corr2 in your original code with corr, xcorr or corrcoef and see which one runs fastest.
With corrcoef you can do this without a loop, and without using a toolbox:
D = corrcoef([X', Y']);
D = D(1 : size(X, 1), end - size(Y, 1) + 1 : end);
A drawback is that more coefficients are computed than necessary.
The transpose is necessary because your matrices do not follow the Matlab convention to enumerate samples with the first index and variables with the second.
This is the equation I am trying to solve:
h = (X'*X)^-1*X'*y
where X is a matrix and y is a vector ((X'X)^-1 is the inverse of X-transpose times X). I have coded this in Matlab as:
h = (X'*X)\X'*y
which I believe is correct. The problem is that X is around 10000x10000, and trying to calculate that inverse is crashing Matlab on even the most powerful computer I can find (16 cores, 24GB RAM). Is there any way to split this up, or a library designed for doing such large inversions?
Thank you.
That looks like a pseudo inverse. Are you perhaps looking for just
h = X \ y;
I generated a random 10,000 by 10,000 matrix X and a random 10,000 by 1 vector y.
I just broke up my computation step by step. (Code shown below)
Computed the transpose and held it in matrix K
Then I computed Matrix A by multiplying K by X
Computed vector b by multiplying K by vector y
Lastly, I used the backslash operator on A and b to solve
I didn't have a problem with the computation. It took a while, but breaking up the operations into the smallest groups possible helped to prevent the computer from being overwhelmed. However, it could be the composition of the matrix that you are using (ie. Sparse, decimals, etc.).
X = randi(2000, [10000, 10000]);
y = randi(2000, 10000, 1);
K = X';
A = K*X;
b = K*y;
S = A\b;
If you have multiple machines at your disposal, and you can recast your problem into the form h = X\y as proposed by #Ben, then you could use distributed arrays. This demo shows how you can do that.
Jordan,
Your equation is exactly the definition for "Moore-Penrose Matrix Inverse".
Check: http://mathworld.wolfram.com/Moore-PenroseMatrixInverse.html
Directly using h = X \ y; should help.
Or check Matlab pinv(X)*y
I want to compute an outer product of the same vector in Matlab. A representative example would be:
x=rand(1e5,1);
sigma=x*x'-spdiags(x,0,length(x),length(x));
Is there any obvious way to speed this up? x*x' is a symmetric matrix, but have not figured out a way to help Matlab use that information to speed things up.
EDIT: There is a way to do this with loops but I cannot see the benefit yet:
for k=1:length(x)
sigma(k:length(x),k)=x(k).*x(k:length(x));
end
The above might work with a sparse array.
Have you considered using pdist with custom distance function
sigmaCompact = pdist( x(:), #(x, Y) x.*Y );
sigma = squareform(sigmaCompact);
up to the special treatment of sigma( k, k );