Silhouette function gives me an error: element number 2 undefined in return list - function

I am trying to check the performance of k-means with the silhouette function but I am getting an error.
I am calling the function like this [out1,out2] = silhouette(normalized, idx); or [out1,out2] = silhouette(normalized, idx, 'cosine');
The definition of the function is function [si, h] = silhouette(X, clust, metric)
I expect to take a number between -1,+1 but instead of that I am getting error: element number 2 undefined in return list.
My code for the silhouette function:
function [si, h] = silhouette(X, clust, metric)
% Nan Zhou
% Code Matlab 'silhouette' into Octave function
% Sichuan University, Macquarie University
% zhnanx#gmail.com
% input parameters
% X, n-by-p data matrix
% - Rows of X correspond to points, columns correspond to coordinates.
% clust, clusters defined for X; n-by-1 vector
% metric, e.g. Euclidean, sqEuclidean, cosine
% return values
% si, silhouettte values, n-by-1 vector
% h, figure handle, waiting to be solved in the future
% algorithm reference
% - Peter J. Rousseeuw (1987)
% - Silhouettes: a Graphical Aid to the Interpretation and Validation of Cluster Analysis
% - doi:10.1016/0377-0427(87)90125-7
% check size
if (size(X, 1) != size(clust, 1))
error("First dimension of X <%d> doesn't match that of clust <%d>",...
size(X, 1), size(clust, 1));
endif
% check metric
if (! exist('metric', 'var'))
metric = 'sqEuclidean';
endif
%%%% function set
function [dist] = EuclideanDist(x, y)
dist = sqrt((x - y) * (x - y)');
endfunction
function [dist] = sqEuclideanDist(x, y)
dist = (x - y) * (x - y)';
endfunction
function [dist] = cosineDist(x, y)
cosineValue = dot(x,y)/(norm(x,2)*norm(y,2));
dist = 1 - cosineValue;
endfunction
%%% end function set
% calculating
si = zeros(size(X, 1), 1);
%h
%calculate values of si one by one
for iii = 1:length(si)
%%% distance of iii to all others
iii2all = zeros(size(X, 1), 1);
for jjj = 1:size(X, 1)
switch (metric)
case 'Euclidean'
iii2all(jjj) = EuclideanDist(X(iii, :), X(jjj, :));
case 'sqEuclidean'
iii2all(jjj) = sqEuclideanDist(X(iii, :), X(jjj, :));
case 'cosine'
iii2all(jjj) = cosineDist(X(iii, :), X(jjj, :));
otherwise
error('Invalid metric.');
endswitch
endfor
%%% end distance to all
%%% allocate values to clusters
clusterIDs = unique(clust); % eg [1; 2; 3; 4]
groupedValues = {};
for jjj = 1:length(clusterIDs)
groupedValues{clusterIDs(jjj)} = [iii2all(clust == clusterIDs(jjj))];
endfor
%%% end allocation
%%% calculate a(i)
% dist of object iii to all other objects in the same cluster
a_iii = groupedValues{clust(iii)};
% average distance of iii to all other objects in the same cluster
a_i = sum(a_iii) / (size(a_iii, 1) - 1);
%disp(a_i);pause;
%%% end a(i)
%%% calculate b(i)
clusterIDs_new = clusterIDs;
% remove the cluster iii in
clusterIDs_new(find(clusterIDs_new == clust(iii))) = [];
% average distance of iii to all objects of another cluster
a_iii_2others = zeros(length(clusterIDs_new), 1);
for jjj = 1:length(clusterIDs_new)
values_another = groupedValues{clusterIDs_new(jjj)};
a_iii_2others(jjj) = mean(values_another);
endfor
b_i = min(a_iii_2others);
%disp(b_i);disp('---');pause;
%%% end b(i)
%%% calculate s(i)
si(iii) = (b_i - a_i) / max([a_i; b_i]);
%%% end s(i)
endfor
end

Related

How to plot Iterations in Julia

I coded a function picircle() that estimates pi.
Now I would like to plot this function for N values.
function Plotpi()
p = 100 # precision of π
N = 5
for i in 1:N
picircle(p)
end
end
3.2238805970149254
3.044776119402985
3.1641791044776117
3.1243781094527363
3.084577114427861
Now I am not sure how to plot the function, I tried plot(PP()) but it didn't work
Here I defined picircle:
function picircle(n)
n = n
L = 2n+1
x = range(-1, 1, length=L)
y = rand(L)
center = (0,0)
radius = 1
n_in_circle = 0
for i in 1:L
if norm((x[i], y[i]) .- center) < radius
n_in_circle += 1
end
end
println(4 * n_in_circle / L)
end
Your problem is that your functions don't actually return anything:
julia> x = Plotpi()
3.263681592039801
3.0646766169154227
2.845771144278607
3.18407960199005
3.044776119402985
julia> x
julia> typeof(x)
Nothing
The numbers you see are just printed to the REPL, and print doesn't return any value:
julia> x = print(5)
5
julia> typeof(x)
Nothing
So you probably just want to change your function so that it returns what you want to plot:
julia> function picircle(n)
n = n
L = 2n+1
x = range(-1, 1, length=L)
y = rand(L)
center = (0,0)
radius = 1
n_in_circle = 0
for i in 1:L
if norm((x[i], y[i]) .- center) < radius
n_in_circle += 1
end
end
4 * n_in_circle / L
end
Then:
julia> x = picircle(100)
3.263681592039801
julia> x
3.263681592039801
So now the value of the function is actually returned (rather than just printed to the console). You don't really need a separate function if you just want to do this multiple times and plot the results, a comprehension will do. Here's an example comparing the variability of the estimate with 100 draws vs 50 draws:
julia> using Plots
julia> histogram([picircle(100) for _ ∈ 1:1_000], label = "100 draws", alpha = 0.5)
julia> histogram!([picircle(20) for _ ∈ 1:1_000], label = "20 draws", alpha = 0.5)

Simulating waves in disc or circle form

I am getting an error when I run this code while selecting disc view or circle view option for wave simulation. The code and error are attached. I think there is some problem in this part of code typically in fzero function. Any help would be great.
Code:
function z = bjzeros(n,k)
% BJZEROS Zeros of the Bessel function.
% z = bjzeros(n,k) is the first k zeros of besselj(n,x)
% delta must be chosen so that the linear search can take
% steps as large as possible
delta = .99*pi;
Jsubn = inline('besselj(n,x)''x','n');
a = n+1;
fa = besselj(n,a);
z = zeros(1,k);
j = 0;
while j < k
b = a + delta;
fb = besselj(n,b);
if sign(fb) ~= sign(fa)
j = j+1;
z(j) = fzerotx(Jsubn,[a b],n);
end
a = b;
fa = fb;
end
Error:
Undefined function 'fzerotx' for input arguments of type 'inline'.
Error in waves>bjzeros (line 292)
z(j) = fzerotx(Jsubn,[a b],n);
Error in waves (line 137)
mu = [bjzeros(0,2) bjzeros(1,2)];
Function Declarations and Syntax
The fzerotx() function may not be declared. You can follow the file structure below to create the required M-files/functions in the same directory. Another small error may be caused by a missing comma, I got rid of the error by changing the line:
Jsubn = inline('besselj(n,x)''x','n');
to
Jsubn = inline('besselj(n,x)','x','n');
File 1: Main File/Function Call → [main.m]
mu = [bjzeros(0,2) bjzeros(1,2)];
File 2: bjzeros() Function → [bjzeros.m]
function z = bjzeros(n,k)
% BJZEROS Zeros of the Bessel function.
% z = bjzeros(n,k) is the first k zeros of besselj(n,x)
% delta must be chosen so that the linear search can take
% steps as large as possible
delta = .99*pi;
Jsubn = inline('besselj(n,x)','x','n');
a = n+1;
fa = besselj(n,a);
z = zeros(1,k);
j = 0;
while j < k
b = a + delta;
fb = besselj(n,b);
if sign(fb) ~= sign(fa)
j = j+1;
z(j) = fzerotx(Jsubn,[a b],n);
end
a = b;
fa = fb;
end
end
File 3: fzerotx() Function → [fzerotx.m]
Function Reference: MATLAB: Textbook version of FZERO
function b = fzerotx(F,ab,varargin)
%FZEROTX Textbook version of FZERO.
% x = fzerotx(F,[a,b]) tries to find a zero of F(x) between a and b.
% F(a) and F(b) must have opposite signs. fzerotx returns one
% end point of a small subinterval of [a,b] where F changes sign.
% Arguments beyond the first two, fzerotx(F,[a,b],p1,p2,...),
% are passed on, F(x,p1,p2,..).
%
% Examples:
% fzerotx(#sin,[1,4])
% F = #(x) sin(x); fzerotx(F,[1,4])
% Copyright 2014 Cleve Moler
% Copyright 2014 The MathWorks, Inc.
% Initialize.
a = ab(1);
b = ab(2);
fa = F(a,varargin{:});
fb = F(b,varargin{:});
if sign(fa) == sign(fb)
error('Function must change sign on the interval')
end
c = a;
fc = fa;
d = b - c;
e = d;
% Main loop, exit from middle of the loop
while fb ~= 0
% The three current points, a, b, and c, satisfy:
% f(x) changes sign between a and b.
% abs(f(b)) <= abs(f(a)).
% c = previous b, so c might = a.
% The next point is chosen from
% Bisection point, (a+b)/2.
% Secant point determined by b and c.
% Inverse quadratic interpolation point determined
% by a, b, and c if they are distinct.
if sign(fa) == sign(fb)
a = c; fa = fc;
d = b - c; e = d;
end
if abs(fa) < abs(fb)
c = b; b = a; a = c;
fc = fb; fb = fa; fa = fc;
end
% Convergence test and possible exit
m = 0.5*(a - b);
tol = 2.0*eps*max(abs(b),1.0);
if (abs(m) <= tol) | (fb == 0.0)
break
end
% Choose bisection or interpolation
if (abs(e) < tol) | (abs(fc) <= abs(fb))
% Bisection
d = m;
e = m;
else
% Interpolation
s = fb/fc;
if (a == c)
% Linear interpolation (secant)
p = 2.0*m*s;
q = 1.0 - s;
else
% Inverse quadratic interpolation
q = fc/fa;
r = fb/fa;
p = s*(2.0*m*q*(q - r) - (b - c)*(r - 1.0));
q = (q - 1.0)*(r - 1.0)*(s - 1.0);
end;
if p > 0, q = -q; else p = -p; end;
% Is interpolated point acceptable
if (2.0*p < 3.0*m*q - abs(tol*q)) & (p < abs(0.5*e*q))
e = d;
d = p/q;
else
d = m;
e = m;
end;
end
% Next point
c = b;
fc = fb;
if abs(d) > tol
b = b + d;
else
b = b - sign(b-a)*tol;
end
fb = F(b,varargin{:});
end
Ran using MATLAB R2019b

Implementing Euler's Method in GNU Octave

I am reading "Numerical Methods for Engineers" by Chapra and Canale. In it, they've provided pseudocode for the implementation of Euler's method (for solving ordinary differential equations). Here is the pseucode:
Pseucode for implementing Euler's method
I tried implementing this code in GNU Octave, but depending on the input values, I am getting one of two errors:
The program doesn't give any output at all. I have to press 'Ctrl + C' in order to break execution.
The program gives this message:
error: 'ynew' undefined near line 5 column 21
error: called from
Integrator at line 5 column 9
main at line 18 column 7
I would be very grateful if you could get this program to work for me. I am actually an amateur in GNU Octave. Thank you.
Edit 1: Here is my code. For main.m:
%prompt user
y = input('Initial value of y:');
xi = input('Initial value of x:');
xf = input('Final value of x:');
dx = input('Step size:');
xout = input('Output interval:');
x = xi;
m = 0;
xpm = x;
ypm = y;
while(1)
xend = x + xout;
if xend > xf
xend = xf;
h = dx;
Integrator(x,y,h,xend);
m = m + 1;
xpm = x;
ypm = y;
if x >= xf
break;
endif
endif
end
For Integrator.m:
function Integrator(x,y,h,xend)
while(1)
if xend - x < h
h = xend - x;
Euler(x,y,h,ynew);
y = ynew;
if x >= xend
break;
endif
endif
end
endfunction
For Euler.m:
function Euler(x,y,h,ynew)
Derivs(x,y,dydx);
ynew = y + dydx * h;
x = x + h;
endfunction
For Derivs.m:
function Derivs(x,y,dydx)
dydx = -2 * x^3 + 12 * x^2 - 20 * x + 8.5;
endfunction
Edit 2: I shoud mention that the differential equation which Chapra and Canale have given as an example is:
y'(x) = -2 * x^3 + 12 * x^2 - 20 * x + 8.5
That is why the 'Derivs.m' script shows dydx to be this particular polynomial.
Here is my final code. It has four different M-files:
main.m
%prompt the user
y = input('Initial value of y:');
x = input('Initial value of x:');
xf = input('Final value of x:');
dx = input('Step size:');
xout = dx;
%boring calculations
m = 1;
xp = [x];
yp = [y];
while x < xf
[x,y] = Integrator(x,y,dx,min(xf, x+xout));
m = m+1;
xp(m) = x;
yp(m) = y;
end
%plot the final result
plot(xp,yp);
title('Solution using Euler Method');
ylabel('Dependent variable (y)');
xlabel('Independent variable (x)');
grid on;
Integrator.m
%This function takes in 4 inputs (x,y,h,xend) and returns 2 outputs [x,y]
function [x,y] = Integrator(x,y,h,xend)
while x < xend
h = min(h, xend-x);
[x,y] = Euler(x,y,h);
end
endfunction
Euler.m
%This function takes in 3 inputs (x,y,h) and returns 2 outputs [x,ynew]
function [x,ynew] = Euler(x,y,h)
dydx = Derivs(x,y);
ynew = y + dydx * h;
x = x + h;
endfunction
Derivs.m
%This function takes in 2 inputs (x,y) and returns 1 output [dydx]
function [dydx] = Derivs(x,y)
dydx = -2 * x^3 + 12 * x^2 - 20 * x + 8.5;
endfunction
Your functions should look like
function [x, y] = Integrator(x,y,h,xend)
while x < xend
h = min(h, xend-x)
[x,y] = Euler(x,y,h);
end%while
end%function
as an example. Depending on what you want to do with the result, your main loop might need to collect all the results from the single steps. One variant for that is
m = 1;
xp = [x];
yp = [y];
while x < xf
[x,y] = Integrator(x,y,dx,min(xf, x+xout));
m = m+1;
xp(m) = x;
yp(m) = y;
end%while

multi-sensors fusion using Kalman filter

I need to use the Kalman filter to fuse multi-sensors positions for gaussian measurement (for example 4 positions as the input of the filter and 1 position as output). It is possible to help me with some examples or tutorials because all the examples I found are related to the estimation of the positions?
OPTION 1
Weighted Avarage
In this case you don't need to implement a real Kalman Filter. You just can use the signal variances to calculate the weights and then calculate the weighted avarage of the inputs. The weights can be found as an inverse of the variances.
So if you have two signals S1 and S2 with variances V1 and V2, then the fused result would be
A fusion example can be seen on the next plot.
I simulated two signals. The variance of the second signal changes over the time. As long as it's smaller than the variance of the first signal the fused result is close to the second signal. It is not the case when the variance of the second signal is too high.
OPTION 2
Kalman Filter with Multiple Update Steps
The classical Kalman Filter uses prediction and update steps in a loop:
prediction
update
prediction
update
...
In your case you have 4 independent measurements, so you can use those readings after each other in separate update steps:
prediction
update 1
update 2
update 3
update 4
prediction
update 1
...
A very nice point is that the order of those updates does not matter! You can use updates 1,2,3,4 or 3,2,4,1. In both cases you should get the same fused output.
Compared to the first option you have following pros:
You have a variance propogation
You have the system noise matrix Q,
so you can control the smoothness of the fused output
Here is my matlab code:
function [] = main()
% time step
dt = 0.01;
t=(0:dt:2)';
n = numel(t);
%ground truth
signal = sin(t)+t;
% state matrix
X = zeros(2,1);
% covariance matrix
P = zeros(2,2);
% kalman filter output through the whole time
X_arr = zeros(n, 2);
% system noise
Q = [0.04 0;
0 1];
% transition matrix
F = [1 dt;
0 1];
% observation matrix
H = [1 0];
% variance of signal 1
s1_var = 0.08*ones(size(t));
s1 = generate_signal(signal, s1_var);
% variance of signal 2
s2_var = 0.01*(cos(8*t)+10*t);
s2 = generate_signal(signal, s2_var);
% variance of signal 3
s3_var = 0.02*(sin(2*t)+2);
s3 = generate_signal(signal, s3_var);
% variance of signal 4
s4_var = 0.06*ones(size(t));
s4 = generate_signal(signal, s4_var);
% fusion
for i = 1:n
if (i == 1)
[X, P] = init_kalman(X, s1(i, 1)); % initialize the state using the 1st sensor
else
[X, P] = prediction(X, P, Q, F);
[X, P] = update(X, P, s1(i, 1), s1(i, 2), H);
[X, P] = update(X, P, s2(i, 1), s2(i, 2), H);
[X, P] = update(X, P, s3(i, 1), s3(i, 2), H);
[X, P] = update(X, P, s4(i, 1), s4(i, 2), H);
end
X_arr(i, :) = X;
end
plot(t, signal, 'LineWidth', 4);
hold on;
plot(t, s1(:, 1), '--', 'LineWidth', 1);
plot(t, s2(:, 1), '--', 'LineWidth', 1);
plot(t, s3(:, 1), '--', 'LineWidth', 1);
plot(t, s4(:, 1), '--', 'LineWidth', 1);
plot(t, X_arr(:, 1), 'LineWidth', 4);
hold off;
grid on;
legend('Ground Truth', 'Sensor Input 1', 'Sensor Input 2', 'Sensor Input 3', 'Sensor Input 4', 'Fused Output');
end
function [s] = generate_signal(signal, var)
noise = randn(size(signal)).*sqrt(var);
s(:, 1) = signal + noise;
s(:, 2) = var;
end
function [X, P] = init_kalman(X, y)
X(1,1) = y;
X(2,1) = 0;
P = [100 0;
0 300];
end
function [X, P] = prediction(X, P, Q, F)
X = F*X;
P = F*P*F' + Q;
end
function [X, P] = update(X, P, y, R, H)
Inn = y - H*X;
S = H*P*H' + R;
K = P*H'/S;
X = X + K*Inn;
P = P - K*H*P;
end
And here is the result:

Storing cost history in a vector

I wrote following code for gradientDescent in Octave in .m file as follows:
function [theta, J_history] = gradientDescent(X, y, theta, alpha, num_iters)
% Test values:
X = [1 5; 1 2; 1 4; 1 5];
y = [1 6 4 2]';
theta = [0 0]';
alpha = 0.01;
num_iters = 1000;
% Initialize some useful values:
m = length(y); % number of training examples
J_history = zeros(num_iters, 1);
for iter = 1:num_iters
x = X(:,2);
h = theta(1) + (theta(2)*x);
theta_zero = theta(1) - alpha * (1/m) * sum(h-y);
theta_one = theta(2) - alpha * (1/m) * sum((h - y) .* x);
theta = [theta_zero; theta_one];
% ============================================================
% Save the cost J in every iteration
J_history(iter) = computeCost(X, y, theta); % History of J
end
disp(min(J_history));
end
% Code for computeCost function is as follows:
function J = computeCost(X, y, theta)
data =
6.1101 17.5920
5.5277 9.1302
8.5186 13.6620
7.0032 11.8540
5.8598 6.8233
8.3829 11.8860
7.4764 4.3483
8.5781 12.0000
6.4862 6.5987
m = length(y);
J = 0;
X = data(:, 1);
y = data(:, 2);
predictions = X*theta'; % predictions of hypothesis on examples
sqrErrors = (predictions - y).^2; % squared errors
J = 1/(2*m) * sum(sqrErrors);
end
When I run this from octave workspace I get the following error:
Error: A(I) = X: X must have the same size as I
error: called from
gradientDescent at line 55 column 21
I tried many things but unsuccessfully and mentors never replied properly.
Can you please tell me where I may be making a mistake.
Thanks in advance.
Bharat.