user
A perceptron is an algorithm used in machine-learning. It's the simplest of all neural networks, consisting of only one neuron, and is typically used for pattern recognition.

A perceptron attempts to separate input into a positive and a negative class with the aid of a linear function. The inputs are each multiplied by weights, random weights at first, and then summed. Based on the sign of the sum a decision is made.

In order for the perceptron to make the right decision, it needs to train with input for which the *correct outcome is known*, so that the weights can slowly be adjusted until they start producing the desired results.

Task

The website The Nature of Code demonstrates a perceptron by making it perform a very simple task : determine if a randomly chosen point (x, y) is above or below a line:

```
 y = mx + b

```

Implement this perceptron and display an image (or some other visualization) of the result.

See also

* Neural networks (nature of code)
* Machine Learning - Perceptrons (youtube)
assistant
**Translation of**: Go

```
# 20201116 Raku programming solution

use MagickWand;

our ( \c, \runs ) = 0.00001, 2000 ;

class Trainer { has ( @.inputs, $.answer ) is rw }

sub linear(\x) { return x*0.7 + 40 }

class Perceptron { 
   
   has ( @.weights, Trainer @.training ) is rw ;

   submethod BUILD(:n($n), :w($w), :h($h)) {
      @!weights  = [ rand*2-1 xx ^$n ];
      @!training = (^runs).map: {
          my (\x,\y) = rand*$w , rand*$h ;
          my \a      = y < linear(x) ?? 1 !! -1;
          Trainer.new: inputs => (x,y,1), answer => a 
      }
   }

   method feedForward(@inputs) { 
      die "weights and input length mismatch" if +@inputs != +self.weights;
      return ( sum( @inputs »*« self.weights ) > 0 ) ?? 1 !! -1
   }

   method train(@inputs, \desired) {
      self.weights »+«= @inputs »*» (c*(desired - self.feedForward(@inputs)))
   }

   method draw(\img) {
      for ^runs { self.train(self.training[$_].inputs, self.training[$_].answer) }
      my $y = linear(my $x = img.width) ;
      img».&{ .stroke-width(3) or .stroke('black') or .fill('none') } # C returns 
      img.draw-line(0.0, linear(0), $x, $y);
      img.stroke-width( 1 );
      for ^runs {
         my $guess = self.feedForward(self.training[$_].inputs);
         ($x, $y) = self.training[$_].inputs[0,1] »-» 4;  
         $guess > 0 ?? img.stroke( 'blue' ) !! img.stroke( 'red' ); 
         img.circle( $x, $y, $x+8, $y );
      }
   }
}

my ($w, $h) = 640, 360;
my $perc = Perceptron.new: n => 3, w => $w, h => $h;
my $o = MagickWand.new or die; 
$o.create( $w, $h, "white" );
$perc.draw($o);
$o.write('./perceptron.png') or die

```