Showing posts with label boolean and function. Show all posts
Showing posts with label boolean and function. Show all posts

Sunday, November 29, 2015

Perceptron Learning using the Delta rule - Gradient Descent - Java (Training for the boolean AND function)

The delta rule uses gradient descent to approximate the target function. It is guaranteed to converge even if the function is not linearly separable, unlike the perceptron learning rule.

We'll be training the perceptron to learn the boolean AND function. We'll use two weights w1, w2. These weights are approximated by the delta rule to fit the training examples most closely. Next we need to find the threshold value (w0) which we will use to classify the training examples accurately.

I've represented 0 with -1, 1 with 1 itself.

Code:

class Example{
    int x1, x2;
    double o;
    Example(int x1, int x2, double o){
        this.x1 = x1;
        this.x2 = x2;
        this.o = o;
    }
}

public class DeltaRulePerceptron {
    double w1, w2;
    double dw1, dw2;
    double n;
    
    DeltaRulePerceptron(){
        //Random values
        w1 = 0.1;
        w2 = 0.7;
        n = 0.05;
    }
    
    public double computeOutput(Example example){
        return example.x1 * w1 + example.x2*w2;
    }
    
    public void trainWithDelta(Example[] examples){ 
        for(int i=0;i<1000;++i){
           
//            System.out.println("Iteration #"+i);
            dw1 = 0;
            dw2 = 0;
            
            for(Example ex:examples){
                double o = computeOutput(ex);
                double t = ex.o;
//                System.out.println("o = "+o+" t = "+t); 
                
                dw1 = dw1 + n*(t-o)*ex.x1;
                dw2 = dw2 + n*(t-o)*ex.x2;
            } 
             
            w1 += dw1;
            w2 += dw2; 
        }        
    }
    
    public static void main(String[] args){
        DeltaRulePerceptron d = new DeltaRulePerceptron(); 
        
        //AND boolean function
        Example[] examples = new Example[]{
            new Example(-1, -1, -1),
            new Example(-1 , 1, -1),
            new Example( 1, -1, -1),
            new Example( 1,  1, 1)
        };
        d.trainWithDelta(examples);
        System.out.println("(AND) Trained weights : "+d.w1+" "+d.w2); 
        
        //bias
        double w0 = 0.5;
        System.out.println("w0 = "+w0);
        
        //Test
        System.out.println(d.sign(w0, d.computeOutput(examples[0])));
        System.out.println(d.sign(w0, d.computeOutput(examples[1])));
        System.out.println(d.sign(w0, d.computeOutput(examples[2])));
        System.out.println(d.sign(w0, d.computeOutput(examples[3])));
        
        
        //XOR - fails - A single layer perceptron can't represent a XOR function
        examples = new Example[]{
            new Example(-1, -1, 1),
            new Example(-1 , 1, -1),
            new Example( 1, -1, -1),
            new Example( 1,  1, 1)
        };
        d.trainWithDelta(examples);
        System.out.println("(XOR) Trained weights : "+d.w1+" "+d.w2);
        System.out.println("w0 = "+w0);
        
        System.out.println(d.sign(w0, d.computeOutput(examples[0])));
        System.out.println(d.sign(w0, d.computeOutput(examples[1])));
        System.out.println(d.sign(w0, d.computeOutput(examples[2])));
        System.out.println(d.sign(w0, d.computeOutput(examples[3])));
    }
    
    public int sign(double w0, double output){
        return output-w0>0?+1:-1;
    }
}

Output:

(AND) Trained weights : 0.49999999999999994 0.5000000000000002
w0 = 0.5
-1
-1
-1
1

(XOR) Trained weights : 0.0 5.551115123125783E-17
w0 = 0.5
-1
-1
-1
-1

Perceptron leaning to classify boolean AND function with the perceptron training rule - Java

A perceptron can be trained to classify inputs according to the AND boolean function.

You need to set the bias accurately, otherwise the learning function will never converge. The code only contains the AND function, you can modify the input for other functions accordingly.

I've represented 0 with -1, 1 with 1 itself.

class Example{
    int x1,x2;
    int o;
    
    Example(int a, int b, int c){
        x1 = a;x2 = b;o = c;
    }
}

class Perceptron {
    double w[];
    double n = 0.1;
    
    Perceptron(){
        w = new double[]{-0.1, -0.9, 0.7};
    }
    
    //Getting the perceptron's output
    int processInput(double x1, double x2){ 
        double result = 1*w[0] + x1*w[1]+x2*w[2];
        if(result>0)return 1;
        else return -1;
    }
    
    //Train using perceptron training rule
    void train(Example[] examples){
        while(true){
            int count=0;
            for(Example e:examples){ 
                int o = processInput(e.x1, e.x2);
                int t = e.o;
                
                if(o!=t)System.out.println("\n"+e.x1+" "+e.x2+" : "+o);
                if(t==o)count++;
                 
                w[1] = w[1] + n*(t-o)*e.x1;        
                w[2] = w[2] + n*(t-o)*e.x2;
                
                if(o!=t)System.out.println("New weights = "+w[1]+" "+w[2]);
            }
            if(count==4)break;
        }
        System.out.println("Perceptron training complete.");
        System.out.println("Learned weights : [w1, w2] = ["+w[1]+", "+w[2]+"]");
    }
    
    public static void main(String[] args){
        Perceptron perceptron = new Perceptron();
        
        Example[] examples = new Example[4];
        examples[0] = new Example(-1, -1, -1);
        examples[1] = new Example(-1, 1, -1);
        examples[2] = new Example(1, -1, -1);
        examples[3] = new Example(1, 1, 1);
       
        perceptron.train(examples);
    }
}

class Example{
    int x1,x2;
    int o;
    
    Example(int a, int b, int c){
        x1 = a;x2 = b;o = c;
    }
}

class Perceptron {
    double w[];
    double n = 0.1;
    
    Perceptron(){
        w = new double[]{-0.1, -0.9, 0.7};
    }
    
    //Getting the perceptron's output
    int processInput(double x1, double x2){ 
        double result = 1*w[0] + x1*w[1]+x2*w[2];
        if(result>0)return 1;
        else return -1;
    }
    
    //Train using perceptron training rule
    void train(Example[] examples){
        while(true){
            int count=0;
            for(Example e:examples){ 
                int o = processInput(e.x1, e.x2);
                int t = e.o;
                
                if(o!=t)System.out.println("\n"+e.x1+" "+e.x2+" : "+o);
                if(t==o)count++;
                 
                w[1] = w[1] + n*(t-o)*e.x1;        
                w[2] = w[2] + n*(t-o)*e.x2;
                
                if(o!=t)System.out.println("New weights = "+w[1]+" "+w[2]);
            }
            if(count==4)break;
        }
        System.out.println("Perceptron training complete.");
        System.out.println("Learned weights : [w1, w2] = ["+w[1]+", "+w[2]+"]");
    }
    
    public static void main(String[] args){
        Perceptron perceptron = new Perceptron();
        
        Example[] examples = new Example[4];
        examples[0] = new Example(-1, -1, -1);
        examples[1] = new Example(-1, 1, -1);
        examples[2] = new Example(1, -1, -1);
        examples[3] = new Example(1, 1, 1);
       
        perceptron.train(examples);
    }
}

Output:

-1 -1 : 1
New weights = -0.7 0.8999999999999999

-1 1 : 1
New weights = -0.49999999999999994 0.7

-1 1 : 1
New weights = -0.29999999999999993 0.49999999999999994

-1 1 : 1
New weights = -0.09999999999999992 0.29999999999999993

-1 1 : 1
New weights = 0.10000000000000009 0.09999999999999992
Perceptron training complete.
Learned weights : [w1, w2] = [0.10000000000000009, 0.09999999999999992]