How do I plot linear decision boundary in matlab - matlab

plotted two different dataset
I have 2 different dataset that have different mu and sigma, and X vector such as [1.8; 1.8]. And also I know probability of each classes that P(ω1)= P(ω2) = 1/2
I want to ploting linear decision boundary between these two dataset but I don't have any idea have to do. My code is down below, here
X = [1.8; 1.8];
u1 = [1;1]; u2 = [3;3];
s1 = [1 0;0 1]; s2 = [1 0;0 1];
Pr1 = 1/2;
Pr2 = 1/2;
r = mvnrnd(u1,s1,500);
plot(r(:,1), r(:,2), '+r');
hold on
r = mvnrnd(u2,s2,500);
plot(r(:,1), r(:,2), '+b');
hold on
grid on
W1 = (u1')/(s1(1,1))^2;
W10 = (u1'*u1)/(-2*s1(1,1)) + log(Pr1);
g1 = W1'.*X + W10;
W2 = (u2')/(s2(1,1))^2;
W20 = (u2'*u2)/(-2*s2(1,1)) + log(Pr2);
g2 = W2'.*X + W20;
Is there someone who can give any idea to me please?

The trick is to calculate two points of the decision boundary you want to plot.
W1_W2 = W2 - W1; % vector from W1 to W2
W1_W2_average = (W2 + W1)/2; % point in the middle between W1 and W2
W1_W2_orthogonal = [-W1_W2(2) W1_W2(1)]; % vector orthogonal to W1_W2
points = [W1_W2_average - 2*W1_W2_orthogonal; W1_W2_average + 2*W1_W2_orthogonal]; % Two points on the line you want to plot
plot(points(:, 1), points(:, 2)); %plot the line
Note that I am not very familiar with classification problems. I might have forgotten some terms in the calculation of the decision boundary.

I solved decision problem, in detailed
First I defined parametric function with parameters x1 and x2 such as
g = #(x1,x2)
then in order to plotting decision boundary realized that g1-g2 = 0 equation such as
e = #(x1,x2) (W1*[x1;x2] + w10 - W2*[x1;x2] - w20)
ezplot(g, [-xlim xlim -ylim ylim])
and done

Related

I can not figure out why my for loop is not being taken in MATLAB

In MATLAB, I am trying to write a program that will take 3 coordinates on a graph, (x,y), use those values to solve a system of equations that will find the coefficients of a polynomial equation, y = ax^2 + bx + c, which I can then use to plot a parabola.
To test my code, I figured I could start with a polynomial, graph it, find the minimum location of the parabola, use its immediate neighbors for my other 2 locations, then run those 3 locations through my code which should spit out the coefficients of my original polynomial. But for some reason, my resulting parabola is right shifted and my values for b and c are incorrect.
Does anyone see where my issue is? I am out of ideas
clear all; close all;
x = -10:10;
%Original Polynomial
y = 6.*x.^2 + 11.*x -35;
% Find 3 Locations
[max_n, max_i] = min(y)
max_il = max_i - 1 % left neighbor of max_ni
max_nl = y(max_il) % value at max_il
max_ir = max_i + 1 % left neighbor of max_ni
max_nr = y(max_ir) % value at max_ir
% Solve for coefficients
syms a b c
equ = (a)*(max_i)^2 + (b)*(max_i) + (c) == (max_n);
equ_l = (a)*(max_il)^2 + (b)*(max_il) + (c) == (max_nl);
equ_r = (a)*(max_ir)^2 + (b)*(max_ir) + (c) == (max_nr);
sol = solve([equ, equ_l, equ_r],[a, b, c]);
Sola = sol.a
Solb = sol.b
Solc = sol.c
% New Polynomial
p = (sol.a).*(x).^2 + (sol.b).*(x) +(sol.c);
%Plot
plot(x,y); grid on; hold on;
plot(x, p);
axis([-10 10 -41 40])
[max_np, max_ip] = min(p)
legend('OG', 'New')
You are confusing the index into your array y, and the corresponding x coordinate.
x = -10:10;
y = 6.*x.^2 + 11.*x -35;
[max_n, max_i] = min(y)
Here. max_i is the index into the y array, the corresponding x coordinate would be x(max_i).
I suggest you find three data points to fit your curve to as follows:
[~, max_i] = min(y);
pts_x = x(max_i + (-1:1));
pts_y = y(max_i + (-1:1));
then use pts_x(i) and pts_y(i) as your x and y values:
syms a b c
equ = a * pts_x.^2 + b * pts_x + c == pts_y;
sol = solve(equ, [a, b, c]);

Plotting a Parametric Spline Curve Using a Periodic Spline

I want to plot a curve like this using a periodic spline:
I have the following values:
And so, I have created the following matlab code to plot this function:
%initializing values
t = [1,2,3,4,5,6,7,8,9,10,11,12,13];
tplot = [1:0.1:13];
x = [2.5,1.3,-0.25,0.0,0.25,-1.3,-2.5,-1.3,0.25,0.0,-0.25,1.3,2.5];
y = [0.0,-0.25,1.3,2.5,1.3,-0.25,0.0,0.25,-1.3,-2.5,-1.3,0.25,0.0];
[a1, b1, c1, d1] = perspline2(t,x);
[a2, b2, c2, d2] = perspline2(t,y);
for i = 1:12
xx = linspace(x(i), x(i+1), 100);
xxx = a1(i) + b1(i)*(xx-x(i)) + c1(i)*(xx-x(i)).^2 ...
+ d1(i)*(xx-x(i)).^3;
yyy = a2(i) + b2(i)*(xx-x(i)) + c2(i)*(xx-x(i)).^2 ...
+ d2(i)*(xx-x(i)).^3;
h3=plot(xxx, yyy, 'r-');
hold on
end
plot(x,y,'k.', 'MarkerSize', 30)
hold off
With perspline2() looking like this:
function [a1,b1,c1,d1] = perspline2(xnot,ynot)
x = xnot';
y = ynot';
n = length(x) - 1;
h = diff(x);
diag0 = [1; 2*(h(1:end-1)+h(2:end)); 2*h(end)];
A = spdiags([[h;0], diag0, [0;h]], [-1, 0, 1], n+1, n+1);
% Do a little surgery on the matrix:
A(1,2) = 0;
A(1,end) = -1;
A(end,1) = 2*h(1);
A(end,2) = h(1);
dy = diff(y);
rhs = 6*[0; diff(dy./h); dy(1)/h(1)-dy(end)/h(end)];
m = A \ rhs; % Solve for the slopes, S''(x_i)
% Compute the coefficients of the cubics.
a1 = y;
b1 = dy./h - h.*m(1:end-1)/2 - h.*diff(m)/6;
c1 = m/2;
d1 = diff(m)./h/6;
So basically, I know that I must use a parametric spline in order to find the correct points to plot.
I use t = [1,2,3,4,5,6,7,8,9,10,11,12,13]; as my indexes. So, I find the coefficients for the cubic spline polynomial of t vs. x and then find the coefficients for t vs. y, and then I attempt to plot them against each other using values from t in order to plot the parametric curve. However, I keep getting this curve:
I am really not sure why this is occurring.
P.S I know I can use the matlab spline function but when I do, it results in the right cusp being a bit bigger than the other cusps. I want all cusps to be equal in size and the assignment says that we must use a cubic spline.
Any help is greatly appreciated.

Plotting linear hyperplane using primal vector in Matlab

Using svmtrain and svmmodel, we're supposed to plot a hyperplane to separate two collections of data. Through the sample, I have the data:
c = [1 1; 2 1.5; 2 1;3 1.5];
N = 10; X = []; sigma = 0.2;
for i = 1:4
X = [X; sigma*randn(N,2) + repmat(c(i,:),N,1)];
end
Y = [ones(1,2*N) -ones(1,2*N)];
plot(X(1:end/2,1),X(1:end/2,2),'+')
hold all
plot(X(end/2+1:end,1),X(end/2+1:end,2),'o')
hold on
So, from my understanding, I have to use the primal vector to obtain the hyperplane as: y = w'x + b, which is the following:
model = svmtrain(Y',X,'-s 0 -t 0 -c 1')
w = model.SVs' * model.sv_coef;
b = -model.rho;
if model.Label(1) == -1
w = -w;
b = -b;
end
However, when I add
plot(w+b)
I get:
Which is not the desired hyperplane. I've played with the values as much as I can and looked up different samples of this kind, but I can't figure out how I'm supposed to use the primal and bias to produce the proper hyperplane.

Fit plane to N dimensional points in MATLAB

I have a set of N points in k dimensions as a matrix of size N X k.
How can I find the best fitting line through these points? The line will be a plane (hyerpplane) in k dimensions. It will have k coefficients and one bias term.
Existing functions like fit seem to be usable only for points in 2 or 3 dimension.
You can fit a hyperplane (or any lower dimensional affine space) to a set of D dimensional data using Principal Component Analysis. Here's an example of fitting a plane to a set of 3D data. This is explained in more detail in the MATLAB documentation but I tried to construct the simplest example I could.
% generate some random correlated data
D = 3;
mu = zeros(1,D);
sqrt_sig = randn(D);
sigma = sqrt_sig'*sqrt_sig;
% generate 50 points in a D x 50 matrix
X = mvnrnd(mu, sigma, 50)';
% perform PCA
coeff = pca(X');
% The last principal component is normal to the best fit plane and plane goes through mean of X
a = coeff(:,D);
b = -mean(X,2)'*a;
% plane defined by a'*x + b = 0
dist = abs(a'*X+b) / norm(a);
mse = mean(dist.^2)
Edit: Added example plot of results for D = 3. I take advantage of the orthogonality of the other principal components here. Ignore the code if you want it's just to demonstrate that the plane does in fact fit the data pretty well.
% plot in 3D
X0 = bsxfun(#minus,X,mean(X,2));
b1 = coeff(:,1); b2 = coeff(:,2);
y1 = b1'*X0; y2 = b2'*X0;
y1_min = min(y1); y1_max = max(y1);
y1_span = y1_max - y1_min;
y2_min = min(y2); y2_max = max(y2);
y2_span = y2_max - y2_min;
pad = 0.2;
y1_min = y1_min - pad*y1_span;
y1_max = y1_max + pad*y1_span;
y2_min = y2_min - pad*y2_span;
y2_max = y2_max + pad*y2_span;
[y1_m,y2_m] = meshgrid(linspace(y1_min,y1_max,5), linspace(y2_min,y2_max,5));
grid = bsxfun(#plus, bsxfun(#times,y1_m(:)',b1) + bsxfun(#times,y2_m(:)',b2), mean(X,2));
x = reshape(grid(1,:),size(y1_m));
y = reshape(grid(2,:),size(y1_m));
z = reshape(grid(3,:),size(y1_m));
figure(1); clf(1);
surf(x,y,z,'FaceColor','black','FaceAlpha',0.3,'EdgeAlpha',0.6);
hold on;
plot3(X(1,:),X(2,:),X(3,:),' .');
axis equal;
axis vis3d;
Edit2: When I say "principal component" I'm being a bit sloppy (or just plain wrong) with the wording. I'm actually referring to the orthogonal basis vectors that the principal components are expressed in.
Here's a simpler solution, that just uses MATLAB's \ operator. We start with defining a plane in k dimensions:
% 0 = a + x(1) * b(1) + x(2) * b(2) + ... + x(k) * 1
k = 8;
a = randn(1);
b = randn(k-1,1);
(note that we assume b(k)=1, you can always multiply the plane parameters by any value without changing the plane).
Next we generate N random points within this plane:
N = 1000;
x = rand(N,k-1);
x(:,k) = -(a + x * b);
...sorry, it's not the best way to generate random points on the plane, but it's good enough for the demonstration here. Add noise to the points:
x = x + 0.05*randn(size(x));
To find the parameters of the plane, we solve the system of equations
% a + x(1:k-1) * b == -x(k)
in the least-squares sense. a and b are the unknowns there. We can rewrite the left-hand side as [1,x(1:k-1)] * [a;b]. If we have a matrix equation M*p=v we can solve for p by writing p=M\v:
p = [ones(N,1),x(:,1:k-1)]\(-x(:,k));
disp(['ground truth: [a,b,1] = ',mat2str([a,b',1],3)]);
disp(['estimated : [a,b,1] = ',mat2str([p',1],3)]);
This gives as output:
ground truth: [a,b,1] = [-1.35 -1.44 -1.48 1.17 0.226 -0.214 0.234 -1.59 1]
estimated : [a,b,1] = [-1.41 -1.38 -1.43 1.14 0.219 -0.195 0.221 -1.54 1]
The less noise or the more points in the dataset, the smaller the error will be of course!

Plot solution of second order equation in MATLAB

Could you please help me with the following question:
I want to solve a second order equation with two unknowns and use the results to plot an ellipse.
Here is my function:
fun = #(x) [x(1) x(2)]*V*[x(1) x(2)]'-c
V is 2x2 symmetric matrix, c is a positive constant and there are two unknowns, x1 and x2.
If I solve the equation using fsolve, I notice that the solution is very sensitive to the initial values
fsolve(fun, [1 1])
Is it possible to get the solution to this equation without providing an exact starting value, but rather a range? For example, I would like to see the possible combinations for x1, x2 \in (-4,4)
Using ezplot I obtain the desired graphical output, but not the solution of the equation.
fh= #(x1,x2) [x1 x2]*V*[x1 x2]'-c;
ezplot(fh)
axis equal
Is there a way to have both?
Thanks a lot!
you can take the XData and YData from ezplot:
c = rand;
V = rand(2);
V = V + V';
fh= #(x1,x2) [x1 x2]*V*[x1 x2]'-c;
h = ezplot(fh,[-4,4,-4,4]); % plot in range
axis equal
fun = #(x) [x(1) x(2)]*V*[x(1) x(2)]'-c;
X = fsolve(fun, [1 1]); % specific solution
hold on;
plot(x(1),x(2),'or');
% possible solutions in range
x1 = h.XData;
x2 = h.YData;
or you can use vector input to fsolve:
c = rand;
V = rand(2);
V = V + V';
x1 = linspace(-4,4,100)';
fun2 = #(x2) sum(([x1 x2]*V).*[x1 x2],2)-c;
x2 = fsolve(fun2, ones(size(x1)));
% remove invalid values
tol = 1e-2;
x2(abs(fun2(x2)) > tol) = nan;
plot(x1,x2,'.b')
However, the easiest and most straight forward approach is to rearrange the ellipse matrix form in a quadratic equation form:
k = rand;
V = rand(2);
V = V + V';
a = V(1,1);
b = V(1,2);
c = V(2,2);
% rearange terms in the form of quadratic equation:
% a*x1^2 + (2*b*x2)*x1 + (c*x2^2) = k;
% a*x1^2 + (2*b*x2)*x1 + (c*x2^2 - k) = 0;
x2 = linspace(-4,4,1000);
A = a;
B = (2*b*x2);
C = (c*x2.^2 - k);
% solve regular quadratic equation
dicriminant = B.^2 - 4*A.*C;
x1_1 = (-B - sqrt(dicriminant))./(2*A);
x1_2 = (-B + sqrt(dicriminant))./(2*A);
x1_1(dicriminant < 0) = nan;
x1_2(dicriminant < 0) = nan;
% plot
plot(x1_1,x2,'.b')
hold on
plot(x1_2,x2,'.g')
hold off