I have a vector for which I need to calculate a threshold to convert it to a binary vector (above threshold=1, below=0). The values of the vector are either close to zero or far from it. So if plotted the vector, values either lie near X-axis or shoot up high(so there is a clear difference between the values). Each time, the values in the vector change so I need to calculate the threshold dynamically. There is no limit on max or min values that the vector can take. I know that otsu's method is used for grayscale images but since the range values for my vector is varying, I think I cannot use it. Is there any standard way to calculate threshold for my case? If not, are there any good workarounds?
I suggest you specify the percentage of values that will become 1, and use the corresponding percentile value as the threshold (computed with prctile function from the Statistics Toolbox):
x = [3 45 0.1 0.4 10 5 6 1.2];
p = 70; %// percent of values that should become 1
threshold = prctile(x,p);
x_quant = x>=threshold;
This approach makes the threshold automatically adapt to your values. Since your data are unbounded, using percentiles may be better than using averages, because with the average a single large value can deviate your threshold more than desired.
In the example,
x_quant =
0 1 0 0 1 0 0 0
if the limits dont differ in a single vector and the 0 and 1 values are nearly equal in probability, why dont you simply use the mean of the vector as a threshold?
>> X=[6 .5 .9 3 .4 .6 7]
X =
6.0000 0.5000 0.9000 3.0000 0.4000 0.6000 7.0000
>> X>=mean(X)
ans =
1 0 0 1 0 0 1
if the probability is different for ones and zeros you might want to multiply the mean in the comparison to fit again. note that this is a very simplistic aproach, which can surly be improved to better fit your problem
Related
I am new to MATLAB's environment and no matter how much I have struggled it just seems that I cannot get the concept of how to construct a ML algorithm for a multivariate Bernoulli.
I have a dataset of N variables (x1,x2,...,xN) and each variable is a vector of D dimensions (Dx1), with a parameter vector in the form p=(p1,p2,...,pD) . So the Bernoulli distribution should have the form:
Pr(X|p)=Πp(d)^x(nd)*(1-p(d))^(1-x(nd))
The code that I created uses MATLAB's mle function:
for n=1:D
prob(n)=mle(dataset(:,n),'distribution', 'bernoulli');
end
which gives me a D vector of estimated probabilities from the dataset.
But, what I am really interested in is how to implement the ML on a step-by-step MATLAB process and not just use the mle.
Thank you very much.
phat for a Bernoulli distribution is proportion of successes to the number of trials. If you'd like to do it manually, you can just count the number of successes (either 1 or 0) in each of your vectors then divide it by the length of the vector. Here's a quick way assuming 1's are successes stored vertically in the matrix.
bern_mat = [0 0 1 0 1 1; 1 1 0 1 0 0 ; 1 0 1 0 1 1]; % 3x6 matrix of 1's and 0's
phat = sum(bern_mat,1)/size(bern_mat,1); % sum across the first dim then divide by size of first dim.
I have 3 matrices (55000x3 double) and want to compare them.
I'm taking the arithmetic mean of the value of each position and want to provide in addition an indicator how the three matrices correlate.
The values in one position of the matrices are for example:
Matrix1 pos(1:1): 3.679
Matrix2 pos(1:1): 3.721
Matrix3 pos(1:1): 3.554
As I cannot just give the standard deviation for each value because it would be to much information I'm looking for a way to give a meaningful statement for the correlation without having to much information.
What's the best way to do this?
I think you want the correlation coefficient. You can reshape each of your matrices into a vector (using (:)), and then compute the correlation coefficient for each pair of vectors (originally matrices) using corrcoef.
For example, let:
Matrix1 = [ 1 2; 3 4; 5 6 ];
Matrix2 = -2*[ 1 2; 3 4; 5 6 ];
Matrix3 = [ 1.1 2.3; 3.4 4.1; 4.9 6.3 ];
Then
C = corrcoef([Matrix1(:) Matrix2(:) Matrix3(:)]);
gives
C =
1.0000 -1.0000 0.9952
-1.0000 1.0000 -0.9952
0.9952 -0.9952 1.0000
This tells you that, in this case,
Each of the three matrices is totally correlated with itself (C(1,1), C(2,2) and C(3,3) equal 1). This is obvious.
Matrices 1 and 2 have correlation coefficient C(1,2) equal to -1. This was expected, because matrix 2 is a negative multiple of matrix 1.
Matrices 1 and 3 are highly correlated (C(1,3) is 0.9952). This is because matrix 3 was defined as matrix 1 with some random "noise".
Matrices 2 and 3 are also highly correlated but with negative sign (C(2,3) is -0.9952), as should be clear from the above.
Have you tried representing your data using boxplot?
boxplot(([data(:,1); data(:,2); data(:,3)])');
I'm trying to do an algorithm in Matlab to try to calculate a received power in dBm of a logarithmic model of a wireless telecommunication system..
My algorithm calculate the received power for a number of distances in km that the user specified in the input and stores it in a vector
vector_distances = { 1, 5, 10, 50, 75 }
vector_Prx = { 131.5266 145.5060 151.5266 165.5060 169.0278 }
The thing is that I almost have everything that I need, but for graphics purposes I need to plot a graph in where on the x axys I have my vector of receiver power but on the y axys I want to show the same received power but with the most complete logarithmic model (the one that have also the noise - with Log-normal distribution on the formula - but for this thing in particular for every distance in my vector I need to choose 50 numbers with 0.5 distance between them (like a matrix) and then for every new point in the same distance calculate the logarithmic model to later plot in the same graph the two functions, one with the model with no noise (a straight line) and one with the noise.. like this picture
!http://imgur.com/gLSrKor
My question is, is there a way to choose 50 numbers with 0.5 distance between them for an existing number?
I know for example, if you have a vector
EDU>> m = zeros(1,5)
m =
0 0 0 0 0
EDU>> v = 5 %this is the starter distance%
v =
5
EDU>> m(1) = 5
m =
5 0 0 0 0
% I want to create a vector with 5 numbers with 0.5 distance between them %
EDU>> for i=2:5
m(i) = m(i-1) + 0.5
end
EDU>> m
m =
5.0000 5.5000 6.0000 6.5000 7.0000
But I have two problems, the firs one is, could this be more simplex? I am new on Matlab..and the other one, could I create a vector like this (with the initial number in the center)
EDU>> m
m =
4.0000 4.5000 **5.0000** 5.5000 6.0000
Sorry for my english, and thank you so much for helping me
In MATLAB, if you want to create a vector from a number n to a number m, you use the format
A = 5:10;
% A = [5,6,7,8,9,10]
You can also specify the step of the vector by including a third argument between the other two, like so:
A = 5:0.5:10;
% A = [5,5.5,6,6.5,7,7.5,8,8.5,9,9.5,10]
You can also use this to count backwards:
A = 10:-1:5
% A = [10,9,8,7,6,5]
This is my attempt to simulate the water surface. It works fine when I use the surf() function. But when I change it to bar3(), this error occurs: "Matrix dimensions must agree, not rendering mesh". Can some one please tell me how to fix this? Here's my code:
n=60;
i = 2:n-1;
j = 2:n-1;
H = ones(n,n);
Dropx=30; %x and y coordinate of the droplet
Dropy=30;
width=20;
r=width/2;
dt=0.1;
dx=0.3;
%%% add droplet to the surface %%%
[x,y] = ndgrid(-1.5:(2/(width/1.5-1)):1);
D = 8*exp(-5*(x.^2+y.^2));
w = size(D,1);
i2 = (Dropx-r):w+(Dropx-r)-1;
j2 = (Dropy-r):w+(Dropy-r)-1;
H(i2,j2) = H(i2,j2) + D;
oldH=H;
newH=H;
h=surf(newH); % cannot change this to bar3
axis([1 n 1 n -2 8]);
k=0.2; %damping constant
c=2; %wave speed
while 1==1
newH(i,j)=H(i,j)+(1-k*dt)*(H(i,j)-oldH(i,j))-...
dt^2*c^2/dx^2*((4*H(i,j)-H(i+1,j)-H(i-1,j)-H(i,j+1)-H(i,j-1))...
+0.4*(4*H(i,j)-H(i+1,j+1)-H(i+1,j-1)-H(i-1,j+1)-H(i-1,j-1)));
set(h,'Zdata', newH(i,j));
oldH=H;
H=newH;
pause(0.05);
end
The problem, as stated by David, is that bar3 transforms the original data matrix into a special ZData. This new one is a cell array of patches, of length n (60 in your code), each of them is an array of size [n*6,4]. So you cannot assign directly your new matrix to ZData.
There is one solution, besides recreating the plot each time. Basically, it modifies directly ZData. You can directly modify element by element Zdata. For that, try the following code instead of calling set(h,'Zdata', newH(i,j));:
for ih=j
set(h(ih), 'ZData', kron(newH(i,ih),[nan 0 0 nan;0,1,1,0;0,1,1,0;nan 0 0 nan;nan 0 0 nan;nan nan nan nan]));
end
h is the handle of the plot; in the case of bar3, its length is n, the first dimension of your matrix. So, for each bar column, you set the ZData according to its format. Each element V of the matrix is transformed to this matrix:
NaN 0 0 NaN
0 V V 0
0 V V 0
NaN 0 0 NaN
NaN 0 0 NaN
NaN NaN NaN NaN
So, in order to build the complete ZData of each column, you call the function kron with the column of the updated matrix and with this atomic matrix.
This is not very fast; on my computer, the display lags time to time, but it is faster than recreating the bar plot each time. Using surf is more faster because there is less patches to draw.
The problem lies in the way you handle the plotting.
h=bar3(newH);
plots the data and stores handles to patch graphic objects in h. When you write the following :
set(h,'Zdata', newH(i,j));
you assume that the handle 'Zdata' is a 60x60 array, which is not the case for bar3. Just write
output = get(h,'Zdata')
to see that. It requires a bit more data handling to do it this way but that seems tedious.
I propose an easy solution to this, simply replotting at every timestep :
oldH=H;
newH=H;
h=bar3(newH);
axis([1 n 1 n -2 8]);
k=0.2; %damping constant
c=2; %wave speed
while 1==1
newH(i,j)=H(i,j)+(1-k*dt)*(H(i,j)-oldH(i,j))-...
dt^2*c^2/dx^2*((4*H(i,j)-H(i+1,j)-H(i-1,j)-H(i,j+1)-H(i,j-1))...
+0.4*(4*H(i,j)-H(i+1,j+1)-H(i+1,j-1)-H(i-1,j+1)-H(i-1,j-1)));
h=bar3(newH);
axis([1 n 1 n -2 8]);
oldH=H;
H=newH;
pause(0.05);
end
I am new to Matlab and I think this is a very basic question..
I have two arrays:
tst
ans =
0 0 0.2500 0.2500 0 0 0 0
prp
ans =
0 0 0 0.5333 0.0333 0.0333 0.1667 0.0667
I want to plot the averages between those two on the same plot (as a line). What is the best way to do it?
I usually do something like:
# Plot figure
plot(...);
# Calculate the average
avg = mean(tst);
# Add a line to the figure
line(xlim(), [avg avg]);
And repeat for prp. You can style the lines however you want according to the linespec documentation.
Note that you should do this at the end of anything that would change the xlimits (holding and plotting something else, etc.) as it depends on xlim().
Edit
I may have misunderstood your question. The above code will plot a horizontal line at the average of the points in the array tst.
If instead you want a line plot whose points are the average of the two arrays, you want something like:
# Calculate average between arrays
avg = mean([tst;prp]);
# Plot all 3 lines at once
plot([tst;prp;avg]');