Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
Following is a part of a code I am writing in matlab, here I want to carry out the following simple mathematical operation [A][X]=[B], where [X] is unknown. In my case I have length of k around 1600000. So all I want is to get the values for g1,g2 and g3 for each element on the array. I have tried the following
k31 = omega3./(d)
k32 = omega3_2./(d)
A = [2,1,5;-2,-1,-5];
X = [g1;g2;g3];
for ii = 1:length(k31)
B = [k31(ii); k32(ii)];
X = pinv(A).*B;
end
display(g1,g2,g3)
I am using pseudo-inverse so basically I can get a solution for each X and I have made some edit there....and x is unknown, MATHEMATICALLY it can be done, but am not able to code it
Also how do I plot the values of g1 g2 g3 with x and y as follows scatter(x(1:end-1), y(1:end-1), 5, g1); scatter(x(1:end-1), y(1:end-1), 5, g2) and scatter(x(1:end-1), y(1:end-1), 5, g3)
I have to make a few assumptions here, so bear with me.
I suspect you want to do this:
k31 = omega3./(d)
k32 = omega3_2./(d)
A = [2,1,5;-2,-1,-5];
X = cell(length(k31),1);
for ii = 1:length(k31)
X{ii} = A\[k31(ii); k32(ii)];
end
which uses the backslash operator instead of inv or pinv. Type help slash to get more information.
The backslash operator will usually be much faster and more accurate than inv or pinv. It is also a lot more flexible -- your case is underdetermined (you are 1 equation short of being able to solve explicitly), in which case the backslash operator will find you a least-squares solution.
Note how I save all results in a cell-array X. This means that the nth solution will be accessible via
X{n} % == [g1(n) g2(n) g3(n)]
In my opinion you are better off creating a pseudo inverse from the singular value decomposition. Moore-Penrose pseudo inverse will work, but I think it gives some weird results sometimes. The least squares can be unstable, especially since the rank of your example matrix is not full.
Also; don't calculate the inverse for every iteration!
Here is an example, where rank-deficiency of A is taken care of:
A = [2,1,5;-2,-1,-5];
% pseudo inverse of A
[m,n] = size(A);
% get SVD
[U,S,V] = svd(A);
% check rank
r = rank(S);
SR = S(1:r,1:r);
% make complete if rank is not full
SRc = [SR^-1 zeros(r,m-r);zeros(n-r,r) zeros(n-r,m-r)];
% create inverse
A_inv = V*SRc*U.';
X=[];
for i = 1:1600
% this actually takes most of the time
k31 = rand(1000, 1);
k32 = rand(1000, 1);
B = [k31';k32'];
% X is overwritten on every loop...
X = [X A_inv*B];
end
N_xy = 1000;
x = rand(N_xy,1);
y = rand(N_xy,1);
g1 = X(1,1:N_xy);
figure(1), clf
scatter(x,y,5,g1)
I didn't plot all 1600000 points since that can't be what you want
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I am working on pedestrian step detection (acceleration data), I want to calculate statistical features from my filtered signal. I have already calculated some and now i want to calculate correlation coefficients .
My data is of 1x37205 double. I calculated features using for loop with moving window size=2samples and 50% overlap of previous window. Below I am attaching the code I tried with to calculate corrcoef.
Now i want to check if it is the right way to calculate and also want to save the out put. I am unable to understand well that how to save all corrcoef's. Could some one guide me or provide any code help in matlab or how i can save?
%%Here M is mean and V is variance i already calculated from filtered data
for i=window:length(M)-window
C = corrcoef(M(i-window/2:i+window/2),V(i-window/2:i+window/2))
end
Looking at the corrcoef documentation you can see that the output is a 2x2 matrix.
The easiest way then to save all the coefficients would be to initialize your matrix C outside of the loop and then just assign values at each iteration.
Perhaps something like
C = zeros(2, 2, length(window:lenght(M)-window));
for i = window:length(M) - window
C(:, :, i) = corrcoef(M(i-window/2:i+window/2),V(i-window/2:i+window/2));
end
Even better, you can also see that the output of the corrcoef function is structured like this:
[1, c1;
c2, 1];
where c1 and c2 are the actual coefficients.
So you could also do:
C = zeros(length(window:lenght(M)-window), 2);
for i = window:length(M) - window
temp = corrcoef(M(i-window/2:i+window/2),V(i-window/2:i+window/2));
C(i, 1) = temp(1, 2); % "c1"
C(i, 2) = temp(2, 1); % "c2"
end
EDIT TO ANSWER TO COMMENT
To implement a sliding window with any size and with any overlap, you might want to change the indexing:
wdwSize = 2;
overlap = 0.5;
C = zeros(length(1:wdwSize*overlap:length(A)-wdwSize*overlap), 2);
for i = 1:wdwSize*overlap:length(A)-wdwSize*overlap
window = i:i+wdwSize - 1;
temp = corrcoef(M(window), V(window));
C(i, 1) = temp(1, 2); % "c1"
C(i, 2) = temp(2, 1); % "c2"
end
In your case wdwSize*overlap is an integer, but you might want to be careful for a general combination of window size and overlap.
According to the documentation, this function reurns a matrix.
If the only problem is literally "how to save this data", you can store it in a cell array.
numSamples = length(M)-window;
result = cell(1, numSamples);
for i=window:numSamples
result{i-window+1} = corrcoef(M(i-window/2:i+window/2),V(i-window/2:i+window/2))
end
Remember that you can retrieve data from the cell array just as you would do with a list, but instead of using "result(i)" you need to use "result{i}".
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
(edited, i have changed the code) Well i have compound equations that i need to solve in matlab and find the result.
I have tried different techniques but have failed.
the equations are:
u(j-1)-2(u(j))+u(j+1)= -4*h^2*pi^2 * sin(2*pi*xj)
where
n=100
j=1 to n
xj=jh
h=1/n
u(0)==u(n)==0
I need to solve the equation and plot the results. so that i can compare the results with
the exact solution.
This is the code i have written so far...
function c= prob1()
n=100;
c=(0); % variable to store all results
u = linspace(1,n-1);
for k=3:90
jay=k;
h=1/k;
syms xj
eqn6 = u(jay-1) -2*u(jay)+u(jay+1)==-4*(h^2)*(pi^2)*sin(2*pi*xj);
A = solve(eqn6, xj); % solving the equation with xj as unknown
if(~(A==0))
c=vertcat(c,A); % just filtering out the results with 0 output
end
end
end
Now i GET answers in A like this " (625*asin(1/9877545463176224))/3927 ".
which i cannot plot.
Setting up the system of equations Au = b is done by translation the math into MATLAB language as follows:
n = 100;
h = 1/n;
j = 0:n; % include zero for the boundary condition
xj = j*h;
% set up right hand side
b = (-4*h^2*pi^2*sin(2*pi*xj))';
% overwrite the first and last value of b with the right hand side of the boundary conditions:
b([1 end]) = 0;
% This is the interesting part:
% set up A: 1*u(j-1) -2*u(j) + 1*u(j+1) and include the boundary conditions
main = [1; -2*ones(n-1,1); 1];
upper = [0; ones(n-1,1)];
lower = [ones(n-1,1); 0];
A = gallery('tridiag', lower, main, upper);
If you dont see why this works, I would suggest to write out the equations for at least j = 0, n/2 and n based on A and b, and to compare them with your equations.
Now, we are ready to solve the system. The system is small so I use the backslash operator (which is a direct method), but you could also pick iterative methods like bicgstab, gmres, qmr:
u = A\b;
Plot the resulting u:
plot(xj,u)
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
for X = 0: 0.00001 : 100;
M=(((sqrt(2*X)-(1/3))^2)*(2*X-1));
N=(( 10.99743/sqrt(X)-(23/30))^2)*(( 53.75263/X)-1);
if M == N
Y=X;
end
end
this code is for an equation with two sides M&N,,, it must be solved using try and error or Matlab Numerical
why this code is false?
Your problem is (as nkjt points out) with comparing floating point values with ==.
FYI: If your objective is to find for which X, M == N, then you could do it much simpler using for instance fzero:
f = #(X) (((sqrt(2.*X)-(1/3))^2)*(2.*X-1))- ...
(( 10.99743./sqrt(X)-(23/30))^2)*(( 53.75263./X)-1);
y = fsolve(f,1)
y = 6.0304
This gives:
M - N = -1.3743e-05
Which is quite close to zero (as close as you will get).
If you absolutely want try and fail, see if you can decipher this (based on the idea of nkjt):
step = 1;
X = 1:step:100
M=(((sqrt(2*X)-(1/3)).^2).*(2*X-1));
N=(( 10.99743./sqrt(X)-(23/30)).^2).*(( 53.75263./X)-1);
[Y, idx] = min(abs(N-M))
err = 1e-10; % Arbitrary tolerance > 1e-14 (typically)
it = 0;
while Y > err && it < 10
step = step / 10;
it = it + 1;
X = X(idx) + (-step*10:step:step*10);
M=(((sqrt(2*X)-(1/3)).^2).*(2*X-1));
N=(( 10.99743./sqrt(X)-(23/30)).^2).*(( 53.75263./X)-1);
[Y, idx] = min(abs(N-M))
end
The perils of floating point comparison could be one factor. When comparing two floating point numbers, you should not use == but check if the difference between them is less than some tolerance (can use eps or something else, depending on your requirements).
Rather than looping at very small steps across your entire range of possible values, you can vectorise, start with a coarser range of X values and get a much better idea of where your solution probably lies, for example:
X = 0:1:100
M=(((sqrt(2*X)-(1/3)).^2).*(2*X-1));
N=(( 10.99743./sqrt(X)-(23/30)).^2).*(( 53.75263./X)-1);
Y = abs(M-N);
plot(X,Y);
Then find the minimum difference between M and N, reduce your step size and range, and continue until you get to a value for X for which the value of abs(M-N) is below your tolerance (required accuracy of your solution).
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
i want to find the value of C such that standard deviation of A-B*C is minimum using matlab (A & B are vectors) where as C would be a scalar. Any ideas ?
This isn't a programming problem, it's a math problem. You want to find c such that
Var(A - c * B)
is minimized. But
Var(A - c*B) = Var(A) - 2 * c * Cov(A,B) + c^2 * Var(B)
Differentiating and setting to zero
-2 * Cov(A,B) + 2 * c * Var(B) = 0
which implies
c = Cov(A,B) / Var(B)
You can achieve this in Matlab with
M = cov(A, B); # Now M = [varA, covAB; covAB, varB]
covAB = M(1,2);
varB = M(2,2);
c = covAB / varB;
Following #EitanT's advice, try:
Ctry = 1.5; % define trial parameter first
Copt = fminsearch(#(x) sum((A-B*x).^2),Ctry)
edit
Note that in the above I assumed you wanted to minimize the vector norm, but following commentaries it is evident that you want to minimize the std dev of samples in array (A-B*x), in which case try
Ctry = 1.5; % define trial parameter first
Copt = fminsearch(#(x) var(A-B*x),Ctry)
If you are performing columnwise substraction of vector B from A, you can do as follows:
A=rand(900,100); B=randn(900,1); % example
Ctry = 1.5; % define parameter first
B = repmat(B,size(A,2),1);
Copt = fminsearch(#(x) var(A(:)-B*x),Ctry)
Eopt=var(A(:)-B*Copt)
#Luis Mendo suggests
nA = numel(A);
Copt = fminsearch(#(x) sum((A(:)-B*x).^2)-sum(A(:)-B*x)^2/nA,Ctry)
This is a little faster on my system.
Also, as with all minimization problems, it helps if you have a good starting estimate.
Edit
It's worth noting that the two methods find points that differ in the second significant figure, which raises the question which is more accurate. <-- just an issue that can be fixed with optimset
I have a MATLAB routine with one rather obvious bottleneck. I've profiled the function, with the result that 2/3 of the computing time is used in the function levels:
The function levels takes a matrix of floats and splits each column into nLevels buckets, returning a matrix of the same size as the input, with each entry replaced by the number of the bucket it falls into.
To do this I use the quantile function to get the bucket limits, and a loop to assign the entries to buckets. Here's my implementation:
function [Y q] = levels(X,nLevels)
% "Assign each of the elements of X to an integer-valued level"
p = linspace(0, 1.0, nLevels+1);
q = quantile(X,p);
if isvector(q)
q=transpose(q);
end
Y = zeros(size(X));
for i = 1:nLevels
% "The variables g and l indicate the entries that are respectively greater than
% or less than the relevant bucket limits. The line Y(g & l) = i is assigning the
% value i to any element that falls in this bucket."
if i ~= nLevels % "The default; doesnt include upper bound"
g = bsxfun(#ge,X,q(i,:));
l = bsxfun(#lt,X,q(i+1,:));
else % "For the final level we include the upper bound"
g = bsxfun(#ge,X,q(i,:));
l = bsxfun(#le,X,q(i+1,:));
end
Y(g & l) = i;
end
Is there anything I can do to speed this up? Can the code be vectorized?
If I understand correctly, you want to know how many items fell in each bucket.
Use:
n = hist(Y,nbins)
Though I am not sure that it will help in the speedup. It is just cleaner this way.
Edit : Following the comment:
You can use the second output parameter of histc
[n,bin] = histc(...) also returns an index matrix bin. If x is a vector, n(k) = >sum(bin==k). bin is zero for out of range values. If x is an M-by-N matrix, then
How About this
function [Y q] = levels(X,nLevels)
p = linspace(0, 1.0, nLevels+1);
q = quantile(X,p);
Y = zeros(size(X));
for i = 1:numel(q)-1
Y = Y+ X>=q(i);
end
This results in the following:
>>X = [3 1 4 6 7 2];
>>[Y, q] = levels(X,2)
Y =
1 1 2 2 2 1
q =
1 3.5 7
You could also modify the logic line to ensure values are less than the start of the next bin. However, I don't think it is necessary.
I think you shoud use histc
[~,Y] = histc(X,q)
As you can see in matlab's doc:
Description
n = histc(x,edges) counts the number of values in vector x that fall
between the elements in the edges vector (which must contain
monotonically nondecreasing values). n is a length(edges) vector
containing these counts. No elements of x can be complex.
I made a couple of refinements (including one inspired by Aero Engy in another answer) that have resulted in some improvements. To test them out, I created a random matrix of a million rows and 100 columns to run the improved functions on:
>> x = randn(1000000,100);
First, I ran my unmodified code, with the following results:
Note that of the 40 seconds, around 14 of them are spent computing the quantiles - I can't expect to improve this part of the routine (I assume that Mathworks have already optimized it, though I guess that to assume makes an...)
Next, I modified the routine to the following, which should be faster and has the advantage of being fewer lines as well!
function [Y q] = levels(X,nLevels)
p = linspace(0, 1.0, nLevels+1);
q = quantile(X,p);
if isvector(q), q = transpose(q); end
Y = ones(size(X));
for i = 2:nLevels
Y = Y + bsxfun(#ge,X,q(i,:));
end
The profiling results with this code are:
So it is 15 seconds faster, which represents a 150% speedup of the portion of code that is mine, rather than MathWorks.
Finally, following a suggestion of Andrey (again in another answer) I modified the code to use the second output of the histc function, which assigns entries to bins. It doesn't treat the columns independently, so I had to loop over the columns manually, but it seems to be performing really well. Here's the code:
function [Y q] = levels(X,nLevels)
p = linspace(0,1,nLevels+1);
q = quantile(X,p);
if isvector(q), q = transpose(q); end
q(end,:) = 2 * q(end,:);
Y = zeros(size(X));
for k = 1:size(X,2)
[junk Y(:,k)] = histc(X(:,k),q(:,k));
end
And the profiling results:
We now spend only 4.3 seconds in codes outside the quantile function, which is around a 500% speedup over what I wrote originally. I've spent a bit of time writing this answer because I think it's turned into a nice example of how you can use the MATLAB profiler and StackExchange in combination to get much better performance from your code.
I'm happy with this result, although of course I'll continue to be pleased to hear other answers. At this stage the main performance increase will come from increasing the performance of the part of the code that currently calls quantile. I can't see how to do this immediately, but maybe someone else here can. Thanks again!
You can sort the columns and divide+round the inverse indexes:
function Y = levels(X,nLevels)
% "Assign each of the elements of X to an integer-valued level"
[S,IX]=sort(X);
[grid1,grid2]=ndgrid(1:size(IX,1),1:size(IX,2));
invIX=zeros(size(X));
invIX(sub2ind(size(X),IX(:),grid2(:)))=grid1;
Y=ceil(invIX/size(X,1)*nLevels);
Or you can use tiedrank:
function Y = levels(X,nLevels)
% "Assign each of the elements of X to an integer-valued level"
R=tiedrank(X);
Y=ceil(R/size(X,1)*nLevels);
Surprisingly, both these solutions are slightly slower than the quantile+histc solution.