Beefy Boxes and Bandwidth Generously Provided by pair Networks
Come for the quick hacks, stay for the epiphanies.
 
PerlMonks  

RFC: A Beginners Guide to Fuzzy Rules-Based Systems

by lin0 (Curate)
on Oct 12, 2006 at 05:51 UTC ( [id://577755]=perlmeditation: print w/replies, xml ) Need Help??

Greetings Fellow Monks,

This is a 50-minutes seminar I am giving next week as a part of an Image Analysis tutorial I am teaching. In this seminar, I introduce Fuzzy Sets and the AI::FuzzyInference module to the students.

The tutorial is divided into six parts:

  1. Introduction to Image Analysis;
  2. Introduction to the Insight Toolkit (a toolkit for image processing, registration, and segmentation);
  3. Introduction to Fuzzy Sets (the first part of this seminar)
  4. Introduction to the AI::FuzzyInference module (the second part of this seminar);
  5. Design strategies for Image Analysis Applications; and
  6. Development of an Image Analysis Application.

The operating system is Linux

The students are supposed to have at least a basic knowledge of Perl.

The goal is to have the students walking out of the 50-minutes seminar knowing how to use the AI::FuzzyInference module and ready for a 1-hour seminar in which we use the module in an image analysis application.

Any comment or suggestion will be appreciated, especially with the goal of making this (either as-is or modified) into a piece suitable for the Tutorials section.

Thank you,

lin0


Updates:

Update 1:

When calling the “new” method, I am now using a “Direct Object Syntax” (my $fis = AI::FuzzyInference->new;) instead of the “Indirect Object Syntax” I was using before. Thank you to ovid for pointing that out.

Update 2:

I added some comments about what the output of the script is when you run it. Thanks to talexb for pointing that out

Update 3:

Minor gramatical mistake fixed.

From:

Fuzzy Sets are a special type of sets that are able to express the notion of partial membership (as a value in the interval [0, 1] ) of an element to a particular group.

To:

A Fuzzy Set is a special type of set that is able to express the notion of partial membership (as a value in the interval [0, 1] ) of an element to a particular group.

Thanks to runrig for pointing it out


Introduction:

A Fuzzy Set is a special type of set that is able to express the notion of partial membership (as a value in the interval [0, 1] ) of an element to a particular group. Fuzzy Sets were first proposed by Prof. Lotfi Zadeh of the University of California at Berkeley in the 1965 paper “Fuzzy Sets”. Fuzzy Sets have been successfully used in applications that range from image processing and pattern recognition to decision support systems and fuzzy control systems. For a good overview on Fuzzy Sets and related terms (Fuzzy Logic and Fuzzy Control Systems), I encourage you to have a look at the Wikipedia.

Main Operations:

The AND, OR, and NOT operators of boolean logic exist in fuzzy logic. The AND operator is used to find the intersection between two sets (it is usually defined as the minimum between two Fuzzy Sets). The OR operator is used to find the union between two sets (it is usually defined as the maximum between two Fuzzy Sets). The NOT operator is used to find the complement of a set (it is usually defined as the subtraction of a membership function from 1)

Rules-Based Systems:

Rules are usually expressed in the form:

IF variable_1 IS fuzzy_set_input_1 AND variable_2 IS fuzzy_set_input_2 THEN action IS fuzzy_set_output

the IF part is called the "antecedent" and the THEN part is called the "consequent".

In this example, the two input variables are "variable_1" and "variable_2". They have values defined as fuzzy sets. The output variable, "action", is also defined by fuzzy sets.

To make a decision based on a set of rules, a rules-based system follows these steps:

  1. All the rules that apply are invoked, using the membership functions and truth values obtained from the inputs (by a process called fuzzification), to determine the result of the antecedent.
  2. This result in turn will be mapped into a membership function and truth value controlling the output variable. This process is known as implication. Two of the more common implication functions are: clipping (the fuzzy set is clipped to a value given by the level of activation of the input variables) and scaling ( the fuzzy set is multiplied by a value given by the level of activation of the input variables).
  3. These results are combined by a process called aggregation. One common approach for the aggregation involves using the “maximum” of the implicated sets.
  4. Finally, a process known as defuzzification is used to compute a single value that is representative of the aggregated fuzzy set. A typical defuzzification approach involves computing the centroid of the aggregated fuzzy set

The AI::FuzzyInference module:

Consider a system for assigning awards to Deserving Monks, directed by a Perl script. The script has to make decisions based on the "quality" of the nodes written by the Deserving Monks and the "speed" on which the Deserving Monk answer the cry for help from other monks. Therefore, one could have input variables: "quality" and "speed" and output variable "award".

The variable "quality" in this system can be subdivided into a range of values: "bad", "ok", "good", "excellent". The variable "speed" in this system can be subdivided into a range of values: "slow", "regular", "fast", "fastest". The variable "award" in this system can be subdivided into a range of values: "minimum", "small", "good", "excellent".

Among the rules for computing the 'award', we could have:

IF “quality” IS bad AND “speed” IS slow THEN “award” IS minimum IF “quality” IS good AND “speed” IS slow THEN “award” IS small IF “quality” IS ok AND “speed” IS fast THEN “award” IS good IF “quality” IS excellent AND “speed” IS fast THEN “award” IS excellen +t

Here, we have a step by step guide to implement the corresponding Rules-Based System using the AI::FuzzyInference module:

First, we need to include the module

use AI::FuzzyInference;

Second, we need a FuzzyInference object to work with, so we create a new one

my $fis = AI::FuzzyInference->new;

Third, we define the input variables. For the input variable “quality” we have

$fis->inVar('quality', 0, 10, bad => [ 0, 1, 2, 1, 4, 0 ], ok => [ 2, 0, 4, 1, 6, 0 ], good => [ 4, 0, 6, 1, 8, 0 ], excelent => [ 6, 0, 8, 1, 10, 1 ], );

on the first line, from left to right:

  • $fis is the object identifier
  • inVar indicates that we are entering an input variable
  • 'quality' is the name of the input variable
  • 0 is the minimum acceptable value for the input variable
  • 10 is the maximum acceptable value for the input variable

on the second line, from left to right:

  • bad is a fuzzy set identifier
  • 0 is a value of the input variable
  • 1 is the membership value for an input value equal to 0
  • 2 is a value of the input variable
  • 1 is the membership value for an input value equal to 2
  • 4 is a value of the input variable
  • 0 is the membership value for an input value equal to 4

The graphical representation of fuzzy set "bad" is:

| 1.00|BBBB | B 0.50| B | B |________B________________ 0 2 4 6 8 10

Fourth, we define the output variable.

$fis->outVar('award', 0, 100, minimum => [ 0,1, 20,1, 40,0 ], small => [ 20,0, 40,1, 60,0 ], good => [ 40,0, 60,1, 80,0 ], excellent => [ 60,0, 80,1, 100,1 ], );

on the first line, from left to right:

  • $fis is the object identifier
  • outVar indicates that we are entering an output variable
  • 'award' is the name of the output variable
  • 0 is the minimum value for the output variable
  • 100 is the maximum value for the output variable

on the second line, from left to right:

  • minimum is a fuzzy set identifier
  • 0 is a value of the input variable
  • 1 is the membership value for an output value equal to 0
  • 20 is a value of the input variable
  • 1 is the membership value for an output value equal to 20
  • 40 is a value of the input variable
  • 0 is the membership value for an output value equal to 40

The graphical representation of fuzzy set "minimum" is:

| 1.00|MMMM | M 0.50| M | M |_______M_____________________ 0 20 40 60 80 100

Fifth, we add the rules

$fis->addRule( 'quality=bad & speed=slow' => 'award=minimum', 'quality=ok & speed=slow' => 'award=minimum', 'quality=good & speed=slow' => 'award=small', 'quality=excellent & speed=slow' => 'award=small',

on the first line, from left to right:

  • $fis is the object identifier
  • addRule indicates that we are entering a set of rules

on the second line, from left to right:

  • 'quality=bad & speed=slow' is the antecedent

  • 'award=minimum' is the consequent

Sixth, we compute the value of the “award” for a given set of values for the input variables.

$fis->compute( quality => $quality_of_service, speed => $speed_of_service);

Finally, to recover the value of the output variable, we use:

my $award = $fis->value('award');

If we wanted to know the values of the main operations and the main functions, we use:

$fis->operation( '&' ); #for the AND operation $fis->operation( '|' ); #for the OR operation $fis->implication(); #for the implication function $fis->aggregation(); #for the aggregation function $fis->defuzzification(); #for the defuzzification

In addition, we could select different values for the operations and the implication function by using:

$fis->operation( '&', 'difference'); $fis->operation( '|', 'sum'); $fis->implication( 'scale' );

As a final note, another tutorial for the AI::FuzzyInference module is available in [1]

[1] Ala Qumsieh, “Fuzzy Logic in Perl,” The Perl Journal, pp. 3-7, June 2003

The complete script to assign the awards to Deserving Monks is given below.

When you run the script, it will ask you first for the quality of service of the Deserving Monk (it should be a number between 0 and 10. This number represents the average quality of the nodes written by the Monk). Let's say that we think the quality of service is "ok" so we enter the value "4". Then, the script will ask you for the speed of service (it should be a number between 0 and 10. This number represents how fast the Monk replies to the requests for help). Let's say that we consider that the Monk answer "very fast" to the requests (the Monk is not the fastest but is closer to the fastest) so we enter the value "7". After you enter that value, the script will show you the value of the award (a number between 0 and 100 representing the percentage of the maximum possible award).

For this example, the award will be 60. In addition to the value of the "award", the script will also inform you of the values of "&", "|", "implication", "aggregation", and "defuzzification" it used in the computation. At the end of the script, I show you how to modify the values of "|", and "implication". This is why you also see a print out indicating the "new values of | and implication".

Enjoy it!


#!/usr/bin/perl use warnings; use strict; use AI::FuzzyInference; ############## # problem: to assign an award to a deserving Monk ############## #my $fis = new AI::FuzzyInference; # this indirect object # notation was replaced # for the direct # notation below as # suggested by ovid my $fis = AI::FuzzyInference->new; ############## # input variables: inVar # 'service' relates to the quality of the nodes written by the Monk # 'speed' relates to how fast the Monk offers a hand to a fellow # monk in need ############## $fis->inVar('quality', 0, 10, bad => [ 0, 1, 2, 1, 4, 0 ], ok => [ 2, 0, 4, 1, 6, 0 ], good => [ 4, 0, 6, 1, 8, 0 ], excellent => [ 6, 0, 8, 1,10, 1 ], ); $fis->inVar('speed', 0, 10, slow => [ 0, 1, 2, 1, 4, 0 ], regular => [ 2, 0, 4, 1, 6, 0 ], fast => [ 4, 0, 6, 1, 8, 0 ], fastest => [ 6, 0, 8, 1,10, 1 ], ); ############## # output variable: outVar # 'award' relates to the quality of the award to be given ############## $fis->outVar('award', 0, 100, minimum => [ 0,1, 20,1, 40,0 ], small => [ 20,0, 40,1, 60,0 ], good => [ 40,0, 60,1, 80,0 ], excellent => [ 60,0, 80,1, 100,1 ], ); ############## # Adding the rules: addRule ############## $fis->addRule( 'quality=bad & speed=slow' => 'award=minimum', 'quality=ok & speed=slow' => 'award=minimum', 'quality=good & speed=slow' => 'award=small', 'quality=excellent & speed=slow' => 'award=small', 'quality=bad & speed=regular' => 'award=minimum', 'quality=ok & speed=regular' => 'award=small', 'quality=good & speed=regular' => 'award=small', 'quality=excellent & speed=regular' => 'award=excellent', 'quality=bad & speed=fast' => 'award=small', 'quality=ok & speed=fast' => 'award=good', 'quality=good & speed=fast' => 'award=good', 'quality=excellent & speed=fast' => 'award=excellent', 'quality=bad & speed=fastest' => 'award=small', 'quality=ok & speed=fastest' => 'award=good', 'quality=good & speed=fastest' => 'award=excellent', 'quality=excellent & speed=fastest' => 'award=excellent', ); ############## # Requesting information from the user: # $quality_of_service, $speed_of_service ############## my ($quality_of_service, $speed_of_service); print "Please, enter the quality of service [0, 10]: "; chomp ($quality_of_service = <STDIN>); print "Please, enter the speed of service [0, 10]: "; chomp($speed_of_service = <STDIN>); ############## # computing the "award" given the "quality_of_service" # and the "speed_of_service" as entered by the user # # Note: we are using the default values for: # & (min), # | (max), # implication (clip), # aggregation (max), and # defuzzification (centroid) ############## $fis->compute( quality => $quality_of_service, speed => $speed_of_service); ############## # reading and showing the value of the 'award' ############## my $award = $fis->value('award'); print "\nAward (quality = $quality_of_service, speed = $speed_of_servi +ce) [0, 100]: $award\n\n"; ############## # showing the values of: # &, |, implication, aggregation, defuzzification ############## print "values of &, |, implication, aggregation, and defuzzification\n +"; print "& = ", $fis->operation( '&' ),"\n"; print "| = ", $fis->operation( '|' ),"\n"; print "implication = ", $fis->implication(), "\n"; print "aggregation = ", $fis->aggregation(), "\n"; print "defuzzification = ", $fis->defuzzification(), "\n\n"; ############## # modifying the values of | and implication ############## $fis->operation( '|', 'sum'); $fis->implication( 'scale' ); ############## # showing the new values of: | and implication ############## print "new values of | and implication\n"; print "| = ", $fis->operation( '|' ),"\n"; print "implication = ", $fis->implication(), "\n";

Replies are listed 'Best First'.
Re: RFC: A Beginners Guide to Fuzzy Rules-Based Systems
by Ovid (Cardinal) on Oct 12, 2006 at 09:55 UTC

    Your explanation seems clear (well, I think it's clear, given that I don't know much about this area), but I'd make a tiny, almost unrelated change:

        my $fis = new AI::FuzzyInference;

    We're trying really hard to discourage indirect object notation. That's better written as:

        my $fis = AI::FuzzyInference->new;

    Indirect object notation can lead to annoying bugs. perlobj has a good discussion of the problems in the "Indirect Object Syntax" section.

    Cheers,
    Ovid

    New address of my CGI Course.

      Hi Ovid,

      thank you very much for the comment. I just updated the node to reflect your suggestion.

      Cheers!

      lin0

      I'm sorry, but after many years of using many languages, I am not at all inclined to consider $f = Foo->new() as if it were a method on the type. I will continue to use $f = new Foo() as if it were an operator built into the language, because it feels more literate and readable.

      Even with the same sort of bugs, I don't see a lot of people clamoring for a shift to $fh->print @list syntax.

      --
      [ e d @ h a l l e y . c c ]

        I'm sorry, but after many years of using many languages, I am not at all inclined to consider $f = Foo->new() as if it were a method on the type.

        What does how other languages work have to do with how Perl works? In Perl, it's a class method. It's not a keyword.

        I will continue to use $f = new Foo() as if it were an operator built into the language, because it feels more literate and readable.

        Okay, but good luck debugging it when it fails in weird and unexpected ways.

        Even with the same sort of bugs, I don't see a lot of people clamoring for a shift to $fh->print @list syntax.

        I suspect you don't know why the indirect object notation can fail then. It's a lot more difficult to call print with filehandle and a bareword as arguments, but PBP suggests instead print {$fh} @list.

Re: RFC: A Beginners Guide to Fuzzy Rules-Based Systems
by talexb (Chancellor) on Oct 12, 2006 at 12:23 UTC

    Very interesting. A few comments: The $fis->addRule call in your code block above makes sense, but seems to be a huge blob of code that will just have to be parsed back to a (quality, speed) array of

    [ [ qw/min min small small/ ], [ qw/min small small excellent/ ], [ qw/small good good excellent/ ], [ qw/small good good excellent/ ] ]
    For clarity and teaching purposes, great. For maintainability and error prevention, not so good.

    Also, what does this produce when you run it?

    Alex / talexb / Toronto

    "Groklaw is the open-source mentality applied to legal research" ~ Linus Torvalds

      Hi Alex

      Thank you for your comments.

      About your comment on the $fis->addRule, I am not sure if I understood it. Could you, please, rephrase it? Anyway, to give you a better description of the $fis->addRule: each line in the addRule represents a hash's element with the 'quality=bad & speed=slow' being a “key” of the hash (guaranteeing uniqueness of the antecedents) and the 'award=minimum' being the “value” for the key.

      About your comment on the output of the script, I just added a description just before the code.

      Cheers!

      lin0

          About your comment on the $fis->addRule, I am not sure if I understood it. Could you, please, rephrase it?

        Your OP contained the following chunk of code:

        $fis->addRule( 'quality=bad & speed=slow' => 'award=minimum', 'quality=ok & speed=slow' => 'award=minimum', 'quality=good & speed=slow' => 'award=small', 'quality=excellent & speed=slow' => 'award=small', 'quality=bad & speed=regular' => 'award=minimum', 'quality=ok & speed=regular' => 'award=small', 'quality=good & speed=regular' => 'award=small', 'quality=excellent & speed=regular' => 'award=excellent', 'quality=bad & speed=fast' => 'award=small', 'quality=ok & speed=fast' => 'award=good', 'quality=good & speed=fast' => 'award=good', 'quality=excellent & speed=fast' => 'award=excellent', 'quality=bad & speed=fastest' => 'award=small', 'quality=ok & speed=fastest' => 'award=good', 'quality=good & speed=fastest' => 'award=excellent', 'quality=excellent & speed=fastest' => 'award=excellent', );
        and I was wondering if that could be replaced with just an array (in my original post), for prevention of errors and maintainability.

        Just a thought.

        Alex / talexb / Toronto

        "Groklaw is the open-source mentality applied to legal research" ~ Linus Torvalds

Re: RFC: A Beginners Guide to Fuzzy Rules-Based Systems
by runrig (Abbot) on Oct 12, 2006 at 20:01 UTC
    Minor grammar nit:
    s/a special type of sets/a special type of set/;

      Hi runrig,

      I made the change. Thanks for pointing it out.

      Cheers,

      lin0

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlmeditation [id://577755]
Approved by GrandFather
Front-paged by wfsp
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others taking refuge in the Monastery: (6)
As of 2024-03-28 23:32 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found