Home > Mobile >  Minimize difference between indicator variables in Matlab
Minimize difference between indicator variables in Matlab

Time:01-12

I'm new to Matlab and want to write a program that chooses the value of a parameter (P) to minimize the difference between two vectors, where each vector is a variable in a dataframe. The first vector (call it A) is a predetermined vector of 1s and 0s, and the second vector (call it B) has each of its entries determined as an indicator function that depends on the value of the parameter P and other variables in the dataframe. For instance, let C be a third variable in the dataset, so

A = [1, 0, 0, 1, 0]

B = [x, y, z, u, v]

where x = 1 if (C[1] 10)^0.5 - P > (C[1])^0.5 and otherwise x = 0, and similarly, y = 1 if (C[2] 10)^0.5 - P > (C[2])^0.5 and otherwise y = 0, and so on.

I'm not really sure where to start with the code, except that it might be useful to use the fminsearch command. Any suggestions?

Edit: I changed the above by raising to a power, which is closer to the actual example that I have. I'm also providing a complete example in response to a comment: Let A be as above, and let C = [10, 1, 100, 1000, 1]. Then my goal with the Matlab code would be to choose a value of P to minimize the differences between the coordinates of the vectors A and B, where B[1] = 1 if (10 10)^0.5 - P > (10)^0.5 and otherwise B[1] = 0, and similarly B[2] = 1 if (1 10)^0.5 - P > (1)^0.5 and otherwise B[2] = 0, etc. So I want to choose P to maximize the likelihood that A[1] = B[1], A[2] = B[2], etc.

I have the following setup in Matlab, where ds is the name of my dataset:

ds.B = zeros(size(ds,1),1);     % empty vector to fill
for i = 1:size(ds,1)
if ((ds.C(i)   10)^(0.5) - P > (ds.C(i))^(0.5))
    ds.B(i) = 1;
else 
    ds.B(i) = 0;
end
end

Now I want to choose the value of P to minimize the difference between A and B. How can I do this?

CodePudding user response:

EDIT: It seems fminbnd isn't optimal, likely due to the stairstep nature of the indicator function. Here's a version which tests the midpoints of all the regions between indicator function flips, plus endpoints:

ds.A = [0; 1; 0; 0; 1]; %Changed so the new method gives better results
ds.C = [10; 1; 100; 1000; 1000]; %Changed so the new method gives better results
B = @(P)double((ds.C 10).^0.5 - P > ds.C.^0.5);

costFcn = @(P)sqrt(sum((ds.A-B(P)).^2));

% Solving the equation (C 10)^0.5 - P = C^0.5 for P, and sorting the results
BCrossingPoints = sort((ds.C 10).^0.5-ds.C.^0.5);
% Taking the average of each crossing point with its neighbors
BMidpoints = (BCrossingPoints(1:end-1) BCrossingPoints(2:end))/2;
% Appending endpoints onto the midpoints
PsToTest = [BCrossingPoints(1)-0.1; BMidpoints; BCrossingPoints(end) 0.1];
% Calculate the distance from A to B at each P to test
costResult = arrayfun(costFcn,PsToTest);
% Find the minimum cost
[~,lowestCostIndex] = min(costResult);
% Find the optimum P
optimumP = PsToTest(lowestCostIndex);

ds.B = B(optimumP);

This gives optimumP = 1.81 and B = [0 1 0 0 0].


Old answer:

If you can package your distance calculation up in a single function based on P, you can use fminbnd:

ds.A = [1, 0, 0, 1, 0];
ds.C = [10, 1, 100, 1000, 1];
B = @(P)double((ds.C 10).^0.5 - P > ds.C.^0.5);

costFcn = @(P)sqrt(sum((ds.A-B(P)).^2));

optimumP = fminbnd(costFcn,-1000,1000);

ds.B = B(optimumP);

which gives optimumP of 236.068

Rather than using an if statement, I just take the logical output of your indicator function (true or false) and convert it to a double-precision number (true becomes 1 and false becomes 0). Also rather than looping through each element, I use MATLAB's array mathematics to process all of A, B, and C at once. These two simplifications turn your above setup into two one-line functions without the need for any control flow and with the ability to take P as input.

For discussion of fminbnd vs fminsearch, see enter image description here

figure
plot(p,d2)
grid on
xlabel('p');title('d2')

enter image description here

The only degree of freedom to optimise seems to be the sign of P regardless of |P| value.

3.- f(p,x) has either no root, or just one root, depending upon p

The threshold funtion is

if f(x)>0 then B(k)==1 else B(k)==0

this is

f(p,x)=(x 10)^.5-p-x^.5

Now

(x 10).^.5-p>x.^.5 is same as (x 10).^.5-x.^.5>p

There's a range of p that keeps f(p,x)=0 without any (real) root.

For the particular case p=0 then (x 10).^.5 and x.^.5 do not intersect (until Inf reached = there's no intersection)

figure;plot(x,(x 10).^.5,x,x.^.5);grid on
[![enter image description here][3]][3]
    
y2=diff((x 10).^.5-x.^.5)
figure;plot(x(2:end),y2);
grid on;xlabel('x')
title('y2=diff((x 10).^.5-x.^.5)')
[![enter image description here][3]][3]
% 005

This means the condition f(x)>0 is always true holding all bits of B=1. With B=1 then d(A,B) turns into d(A,1), a constant.

However, for a certain value of p then there's one root and f(x)>0 is always false keeping all bits of B=0.

In this case d(A,B) the cost function turns into d(A,0) and this is A itself.

4.- P as a vector

The optimization gains in degrees of freedom if instead of P scalar, P is considered as vector.

For a given x there's a value of p that switches B(k) from 0 to 1.

Any value of p below such threshold keeps B(k)=0.

Equivalently, inverting f(x) :

g(p)=(10-p^2)^2/(4*p^2)>x

Values of x below this threshold bring B closer to A because for each element of B it's flipped to the element value of A.

Therefore, it's convenient to consider P as a vector, not a ascalar, and :

For all, or as many (as possible) elements of C to meet c(k)<(10-p^2)^2/(4*p^2) in order to get C=A or minimize d(A,C)

5.- roots of f(p,x)

syms t positive
p=[-1000:.1:1000];
zp=NaN*ones(1,numel(p));
sol=zeros(1,numel(p));
for k1=1:1:numel(p)
  p(k1)
    eq1=(t 10)^.5-p(k1)-t^.5-p(k1)==0;
    s1=solve(eq1,t);
    if ~isempty(s1) 
        zp(k1)=s1;
    end
end

nzp=~isnan(zp);
zp(nzp)

returns

 =
  
  620.0100  151.2900   64.5344   34.2225   20.2500   12.7211
 
    8.2451    5.4056    3.5260    2.2500    1.3753    0.7803
 
    0.3882    0.1488    0.0278
  • Related