Main Content

Customize FIS Tuning Process

This example shows how to customize the FIS tuning process by specifying either a custom cost function or a custom optimization method.

For more information on tuning a FIS, see Tune Fuzzy Rules and Membership Function Parameters and Tune Fuzzy Trees.

Tune FIS Using Custom Cost Function

You can specify a custom cost function for tuning your fuzzy system. Doing so is useful for:

As an example, consider the FIS tree from Tune Fuzzy Trees.

Suppose you want to modify the FIS tree as shown in the following diagram, combining the FIS outputs using known mathematical operations from the training data.

Create the FIS tree, which contains three FIS objects. The outputs of the FIS tree are the outputs of the individual FIS objects.

fis1 = sugfis('Name','fis1');
fis1 = addInput(fis1,[0 10],'NumMFs',3,'MFType','gaussmf');
fis1 = addOutput(fis1,[-1 1],'NumMFs',3);

fis2 = sugfis('Name','fis2');
fis2 = addInput(fis2,[0 10],'NumMFs',3,'MFType','gaussmf');
fis2 = addOutput(fis2,[-1 1],'NumMFs',3);

fis3 = sugfis('Name','fis3');
fis3 = addInput(fis3,[0 10],'NumMFs',3,'MFType','gaussmf');
fis3 = addOutput(fis3,[0 1],'NumMFs',3);

con = ["fis1/input1" "fis2/input1";"fis2/input1" "fis3/input1"];

fisT = fistree([fis1 fis2 fis3],con);

Generate training data.

x = (0:0.1:10)';
y1 = sin(x)+cos(x);
y2 = y1./exp(x);
y = [y1;y2];

To implement the addition and multiplication operations, use a cost function. For this example, use the custom function customcostfcn, included at the end of the example. Learn a rule base using this cost function.

options = tunefisOptions('Method',"particleswarm",'OptimizationType',"learning");
options.MethodOptions.MaxIterations = 5;
rng('default')
fisTout1 = tunefis(fisT,[],@(fis)customcostfcn(fis,x,y),options);
                                 Best            Mean     Stall
Iteration     f-count            f(x)            f(x)    Iterations
    0             100           0.746            1.31        0
    1             200          0.5089           1.249        0
    2             300          0.5089           1.086        1
    3             400          0.5089           1.112        2
    4             500          0.5089           1.106        3
    5             600          0.4999           1.051        0
Optimization ended: number of iterations exceeded OPTIONS.MaxIterations.

Next, tune all the parameters of the FIS tree.

options.Method = 'patternsearch';
options.MethodOptions.MaxIterations = 25;
[in,out,rule] = getTunableSettings(fisTout1);
rng('default')
fisTout2 = tunefis(fisTout1,[in;out;rule],@(fis)customcostfcn(fis,x,y),options);
Iter     Func-count       f(x)      MeshSize     Method
    0           1       0.499882             1      
    1          13       0.499864             2     Successful Poll
    2          51       0.499727             4     Successful Poll
    3          72       0.499727             2     Refine Mesh
    4         117       0.499727             1     Refine Mesh
    5         157       0.499542             2     Successful Poll
    6         170       0.499485             4     Successful Poll
    7         191       0.499485             2     Refine Mesh
    8         217       0.499483             4     Successful Poll
    9         238       0.499483             2     Refine Mesh
   10         275       0.499483             4     Successful Poll
   11         296       0.499483             2     Refine Mesh
   12         340       0.499483             1     Refine Mesh
   13         381       0.499483             2     Successful Poll
   14         425       0.499483             1     Refine Mesh
   15         497       0.499483           0.5     Refine Mesh
   16         536       0.499394             1     Successful Poll
   17         547       0.499217             2     Successful Poll
   18         591       0.499217             1     Refine Mesh
   19         603       0.499211             2     Successful Poll
   20         630       0.498972             4     Successful Poll
   21         652       0.498972             2     Refine Mesh
   22         696       0.498972             1     Refine Mesh
   23         768       0.498972           0.5     Refine Mesh
   24         843       0.498972          0.25     Refine Mesh
   25         859       0.495584           0.5     Successful Poll
   26         869       0.494138             1     Successful Poll
Maximum number of iterations exceeded: increase options.MaxIterations.

You can add more input/output MFs and specify additional FIS tree outputs to improve the tuning performance. Using additional MF parameters and more training data for additional FIS tree outputs can further fine-tune the outputs of fis1, fis2, and fis3.

Tune FIS Using Custom Optimization Method

You can also implement your own FIS parameter optimization method using getTunableSettings, getTunableValues, and setTunableValues. This example uses these functions to tune a rule base of a fuzzy system.

Create a FIS to approximate sin(θ), where θ varies from 0 to 2π.

fisin = mamfis;

Add an input with a range of [0, 2π] and having five Gaussian MFs. Also, add an output with a range of [–1, 1] and having five Gaussian MFs.

fisin = addInput(fisin,[0 2*pi],'NumMFs',5,'MFType','gaussmf');
fisin = addOutput(fisin,[-1 1],'NumMFs',5,'MFType','gaussmf');

Add five rules.

fisin = addRule(fisin,[1 1 1 1;2 2 1 1;3 3 1 1;4 4 1 1;5 5 1 1]);
fisin.Rules
ans = 
  1x5 fisrule array with properties:

    Description
    Antecedent
    Consequent
    Weight
    Connection

  Details:
                   Description           
         ________________________________

    1    "input1==mf1 => output1=mf1 (1)"
    2    "input1==mf2 => output1=mf2 (1)"
    3    "input1==mf3 => output1=mf3 (1)"
    4    "input1==mf4 => output1=mf4 (1)"
    5    "input1==mf5 => output1=mf5 (1)"

For a faster FIS update, set DisableStructuralChecks to true.

fisin.DisableStructuralChecks = true;

Obtain the rule parameter settings.

[~,~,rule] = getTunableSettings(fisin);

Make the rule antecedents nontunable. In the rule consequents, do not allow NOT logic (negative MF indices) or empty variables (zero MF indices).

for i = 1:numel(rule)
    rule(i).Antecedent.Free = false;
    rule(i).Consequent.AllowNot = false;
    rule(i).Consequent.AllowEmpty = false;
end

Generate data for tuning.

x = (0:0.1:2*pi)';
y = sin(x);

To tune the rule parameters, use the custom function customtunefis included at the end of this example. Set the number of iterations to 2, and do not allow invalid parameter values when updating the FIS using setTunableValues.

numite = 2;
ignoreinvp = false;
fisout = customtunefis(fisin,rule,x,y,numite,ignoreinvp);
Initial cost = 1.170519
Iteration 1: Cost = 0.241121
Iteration 2: Cost = 0.241121

Display the tuned rules.

fisout.Rules
ans = 
  1x5 fisrule array with properties:

    Description
    Antecedent
    Consequent
    Weight
    Connection

  Details:
                   Description           
         ________________________________

    1    "input1==mf1 => output1=mf4 (1)"
    2    "input1==mf2 => output1=mf5 (1)"
    3    "input1==mf3 => output1=mf3 (1)"
    4    "input1==mf4 => output1=mf1 (1)"
    5    "input1==mf5 => output1=mf2 (1)"

Allow NOT logic in the rules and optimize the FIS again.

for i = 1:numel(rule)
    rule(i).Consequent.AllowNot = true;
end
fisout = customtunefis(fisin,rule,x,y,numite,ignoreinvp);
Initial cost = 1.170519
Iteration 1: Cost = 0.357052
Iteration 2: Cost = 0.241121
fisout.Rules
ans = 
  1x5 fisrule array with properties:

    Description
    Antecedent
    Consequent
    Weight
    Connection

  Details:
                   Description           
         ________________________________

    1    "input1==mf1 => output1=mf4 (1)"
    2    "input1==mf2 => output1=mf5 (1)"
    3    "input1==mf3 => output1=mf3 (1)"
    4    "input1==mf4 => output1=mf1 (1)"
    5    "input1==mf5 => output1=mf2 (1)"

Using NOT logic creates more combinations of rule parameters, resulting in more iterations to tune a FIS.

Next, reset AllowNot to false and set AllowEmpty to true. In other words, allow the absence of variables (zero output MF indices) in the consequents. Tune the FIS with the updated rule parameter settings.

for i = 1:numel(rule)
    rule(i).Consequent.AllowNot = false;
    rule(i).Consequent.AllowEmpty = true;
end

try
    fisout = customtunefis(fisin,rule,x,y,numite,ignoreinvp);
catch me
    disp("Error: "+me.message)
end
Initial cost = 1.170519
Error: Rule consequent must have at least one nonzero membership function index.

The tuning process fails since the FIS contains only one output, which must be nonzero (nonempty) in the rule consequent. To ignore invalid parameter values, specify IgnoreInvalidParameters with setTunableValues.

Set ignoreinvp to true, which specifies the IgnoreInvalidParameters value in the call to setTunableValues used in customtunefis.

ignoreinvp = true;
fisout = customtunefis(fisin,rule,x,y,numite,ignoreinvp);
Initial cost = 1.170519
Iteration 1: Cost = 0.241121
Iteration 2: Cost = 0.241121
fisout.Rules
ans = 
  1x5 fisrule array with properties:

    Description
    Antecedent
    Consequent
    Weight
    Connection

  Details:
                   Description           
         ________________________________

    1    "input1==mf1 => output1=mf4 (1)"
    2    "input1==mf2 => output1=mf5 (1)"
    3    "input1==mf3 => output1=mf3 (1)"
    4    "input1==mf4 => output1=mf1 (1)"
    5    "input1==mf5 => output1=mf2 (1)"

In this case, the tuning process bypasses the invalid values and uses only valid parameter values for optimization.

By default, tunefis ignores invalid values when updating fuzzy system parameters. You can change this behavior by setting tunefisOptions.IgnoreInvalidParameters to false.

Custom Functions

function cost = customcostfcn(fis,x,y)

tY = evalfis(fis,x);
sincosx = tY(:,1)+tY(:,2);
sincosexpx = sincosx.*tY(:,3);
actY = [sincosx;sincosexpx];
d = y(:)-actY;
cost = sqrt(mean(d.*d));

end
function fis = customtunefis(fis,rule,x,y,n,ignore)

% Show the initial cost.
cost = findcost(fis,x,y);
fprintf('Initial cost = %f\n',cost);

% Optimize the rule parameters.
numMFs = numel(fis.Outputs.MembershipFunctions);
for ite = 1:n
    for i = 1:numel(rule)
        % Get the consequent value.
        pval = getTunableValues(fis,rule(i));
        % Loop through the output MF indices to minimize the cost.
        % Use the output indices according to AllowNot and AllowEmpty.
        allowNot = rule(i).Consequent.AllowNot;
        allowEmpty = rule(i).Consequent.AllowEmpty;
        if allowNot && allowEmpty
            mfID = -numMFs:numMFs;
        elseif allowNot && ~allowEmpty
            mfID = [-numMFs:-1 1:numMFs];
        elseif ~allowNot && allowEmpty
            mfID = 0:numMFs;
        else
            mfID = 1:numMFs;
        end
        cost = 1000;
        minCostFIS = fis;
        for j = 1:length(mfID)
            % Update the consequent value.
            pval(1) = mfID(j);
            % Set the consequent value in the FIS.
            fis = setTunableValues(fis,rule(i),pval,'IgnoreInvalidParameters',ignore);
            % Evaluate cost.
            rmse = findcost(fis,x,y);
            % Update the FIS with the minimum cost.
            if rmse<cost
                cost = rmse;
                minCostFIS = fis;
            end
        end
        fis = minCostFIS;
    end
    fprintf('Iteration %d: Cost = %f\n',ite,cost);
end

end
function cost = findcost(fis,x,y)

actY = evalfis(fis,x);
d = y - actY;
cost = sqrt(mean(d.*d));

end

See Also

|

Related Topics