Commit a28ad255 authored by Javi's avatar Javi

Adding Simple Perceptron Processing initial code

parent 697a4004
Pipeline #237 canceled with stages
File added
//The class DatasetPoint extends its functionality
class DatasetPoint extends Point {
float bias = 1.0; //The bias is always equal to 1 because of the equation of the line
int label; //The label
DatasetPoint(float x_axis_width, float y_axis_height) {
x = random(-1, 1);
y = random(-1, 1);
this.x_axis_width = x_axis_width;
this.y_axis_height = y_axis_height;
calculateMargins();
float exact_line_y = exact_function(x);
if (y > exact_line_y) {
label = 1;
} else {
label = -1;
}
}
}
\ No newline at end of file
class Perceptron {
float[] weights = new float[3];
float[] prev_weights = new float[3];
// float lr = 0.001;
float lr = 0.04;
float error;
Perceptron() {
// Start with random weights
for (int i = 0; i < weights.length; i++) {
// weights[i] = random(-1,1);
weights[i] = random(-1.0, 1.0);
}
}
//The activation function
int sign(float n) {
if (n > 0) {
return 1;
} else {
return -1;
}
}
//inputs[] -> x,y of the point and bias (always 1)
//weights[] -> initially random(-1,1)
int feedforward(float[] inputs, boolean printText) {
float sum = 0;
for ( int i = 0; i< weights.length; i++) {
sum+=inputs[i]*weights[i];
}
int output =sign(sum);
if (printText == true) {
stroke(0);
fill(0);
text("Training epoch "+epoch+" training point "+(currentDataTraining+1)+"/"+trainingDataset.length+" -> Feedforward", text_x_separation, current_text_y);
current_text_y+=text_y_separation;
text("x = "+inputs[0]+" y = "+inputs[1]+" bias = "+inputs[2], text_x_separation, current_text_y);
current_text_y+=text_y_separation;
text("w0 = "+weights[0]+" w1 = "+weights[1]+" w2 = "+ weights[2], text_x_separation, current_text_y);
current_text_y+=text_y_separation;
text("sum = (x * w0) -> ( "+inputs[0]*weights[0]+" ) + (y * w1) -> "+inputs[1]*weights[1]+" + (bias*w2) -> "+inputs[2]*weights[2]+" = "+sum, text_x_separation, current_text_y);
current_text_y+=text_y_separation;
text("sign(sum) = if (sum > 0) = 1 else = -1 -> "+output, text_x_separation, current_text_y);
current_text_y+=text_y_separation;
}
return output;
}
//Formula of the line
//weights[0]*x + weights[1]*y + weights[2]*bias (1) = 0
//Only used for the points of the line. It's not used during the training
float caulculateY(float x) {
//float m = weights[0] / weights[1];
//float b = weights[2];
//return m*x + b;
float w0 = weights[0];
float w1 = weights[1];
float w2 = weights[2];
float bias = 1;
//w0*x + w1*y + w2*bias = 0
//w1*y = -w0*x - w2*bias
//y = -w0/w1*x - w2/w1*bias
float calculated_y = - (w0/w1)*x -(w2/w1)*bias ;
return calculated_y;
}
//1. For every input, multiply that input by its weight
//2. Sum all of the weighted inputs
//3. Compute the output of the perceptron based on that sum passed through an
// activation function (the sign of the sum)
// New weight = weight + ( Error * Input * LearningRate)
boolean train(float[] inputs, int target) {
// Guess the result
int guess = feedforward(inputs, true);
stroke(0);
fill(0);
if (verbose) {
current_text_y+=text_y_separation;
text("Calculating error", text_x_separation, current_text_y);
current_text_y+=text_y_separation;
text("guessed output = "+guess+" target output = "+target, text_x_separation, current_text_y);
current_text_y+=text_y_separation;
}
// Compute the factor for changing the weight based on the error
// Error = desired output - guessed output
// Note this can only be 0, -2, or 2
// Multiply by learning constant
error = target - guess;
prev_weights[0] = weights[0];
prev_weights[1] = weights[1];
prev_weights[2] = weights[2];
// Adjust weights based on weightChange * input
for (int i = 0; i < weights.length; i++) {
weights[i] += error * inputs[i] * lr;
}
text("error = target - guess = " + error, text_x_separation, current_text_y);
current_text_y+=text_y_separation;
if ( error != 0) {
if (verbose) {
printWeightsAdjustment(inputs);
}
return true;
} else {
current_text_y+=text_y_separation;
text("Weights don't change!! Calculated points Left & Right stays the same.", text_x_separation, current_text_y);
current_text_y+=text_y_separation;
return false;
}
}
void printWeightsAdjustment(float[] inputs) {
text("Increment w0 = (error*x*lr) -> ("+error+"*"+inputs[0]+"*"+lr+") = "+ (error*inputs[0]*lr), text_x_separation, current_text_y);
current_text_y+=text_y_separation;
text("Increment w1 = (error*y*lr) -> ("+error+"*"+inputs[1]+"*"+lr+") = "+ (error*inputs[1]*lr), text_x_separation, current_text_y);
current_text_y+=text_y_separation;
text("Increment w2 = (error*bias*lr) -> ("+error+"*"+inputs[2]+"*"+lr+") = "+ (error*inputs[2]*lr), text_x_separation, current_text_y);
current_text_y+=text_y_separation;
current_text_y+=text_y_separation;
text("Adjusting weights", text_x_separation, current_text_y);
current_text_y+=text_y_separation;
text("prev w0 = "+prev_weights[0]+" new w0 = "+weights[0], text_x_separation, current_text_y);
current_text_y+=text_y_separation;
text("prev w1 = "+prev_weights[1]+" new w1 = "+weights[1], text_x_separation, current_text_y);
current_text_y+=text_y_separation;
text("prev w2 = "+prev_weights[2]+" new w2 = "+weights[2], text_x_separation, current_text_y);
current_text_y+=text_y_separation;
}
}
\ No newline at end of file
//Simple class Point
class Point {
float x;
float y;
float x_axis_width;
float y_axis_height;
float margin_x;
float margin_y;
boolean calculatedLine = false;
void show() {
if (calculatedLine == true) {
fill(255, 0, 0);
stroke(255, 0, 0);
ellipse(pixelX(), pixelY(), 8, 8);
text("("+x+","+y+")", pixelX()+10, pixelY()+10);
} else {
fill(0, 0);
stroke(0);
ellipse(pixelX(), pixelY(), 8, 8);
text("("+x+","+y+")", pixelX()+10, pixelY()+10);
}
}
Point() {
}
//Create points for representing a line -> no need of label
Point(float x_axis_width, float y_axis_height, float px, float py, boolean calculatedLine) {
x = px;
y = py;
this.x_axis_width = x_axis_width;
this.y_axis_height = y_axis_height;
this.calculatedLine=calculatedLine;
calculateMargins();
}
void calculateMargins() {
margin_x = (width-x_axis_width)/2.0;
margin_y = (height-y_axis_height)/2.0;
}
//It maps the coordinates from -1,1 into screen pixel coordinates
float pixelX() {
// float result = map(x, -1, 1, margin_x, width-margin_x);
float result = map(x, -1, 1, margin_x, width-margin_x);
return result;
}
float pixelY() {
float result = map(y, -1, 1, margin_y+y_axis_height, margin_y);
return result;
}
}
\ No newline at end of file
//The class TestingDatasetPoint extends the functionality of
//by adding methods to detect whether the point was properly classified
class TestingDatasetPoint extends DatasetPoint {
int predicted_label;
boolean successful_prediction;
float cross_size = 4;
TestingDatasetPoint(float x_axis_width, float y_axis_height) {
super(x_axis_width, y_axis_height);
}
boolean wasProperlyClassified() {
float calculated_line_y = current_function_based_on_weights(x);
if (y > calculated_line_y) {
predicted_label = 1;
} else {
predicted_label = -1;
}
if ( predicted_label == label) {
successful_prediction = true;
} else {
successful_prediction = false;
}
return successful_prediction;
}
//Draws the Testing Dataset Point.
//It displays a red x if it has been missclassified
//It displays a dot it it has been properly classified
void show(boolean currentPoint) {
if ( successful_prediction) {
fill(149, 255, 166);
if ( currentPoint == true) {
noStroke();
ellipse(pixelX(), pixelY(), 8, 8);
noFill();
stroke(149, 255, 166);
ellipse(pixelX(), pixelY(), 14, 14);
fill(0);
} else {
noStroke();
ellipse(pixelX(), pixelY(), 8, 8);
fill(0);
stroke(0);
}
} else {
stroke(255, 0, 0);
line(pixelX()-cross_size, pixelY()-cross_size, pixelX()+cross_size, pixelY()+cross_size);
line(pixelX()-cross_size, pixelY()+cross_size, pixelX()+cross_size, pixelY()-cross_size);
stroke(0);
}
}
}
\ No newline at end of file
class TrainingDatasetPoint extends DatasetPoint {
TrainingDatasetPoint(float x_axis_width, float y_axis_height) {
super(x_axis_width, y_axis_height);
//We would like to use any particular function
float lineY = exact_function(x);
if (y > lineY) {
label = 1;
} else {
label = -1;
}
}
//Draws the point on the display
void show(boolean currentPoint) {
stroke(0);
if ( label == 1) {
fill(255);
} else {
fill(0);
}
if ( currentPoint == true) {
ellipse(pixelX(), pixelY(), 8, 8);
noFill();
stroke(0);
ellipse(pixelX(), pixelY(), 14, 14);
fill(0);
text("("+x+","+y+")", pixelX()+10, pixelY()+10);
} else {
ellipse(pixelX(), pixelY(), 8, 8);
}
}
}
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment