Skip to content

Instantly share code, notes, and snippets.

@ebraminio
Last active October 15, 2021 10:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ebraminio/77108bcc297adfda1d76c9cb71b34fa0 to your computer and use it in GitHub Desktop.
Save ebraminio/77108bcc297adfda1d76c9cb71b34fa0 to your computer and use it in GitHub Desktop.
// `clang a.c && time ./a.out`
// real 0m0.071s
// user 0m0.067s
// sys 0m0.002s
// `clang -O3 a.c && time ./a.out`
// real 0m0.029s
// user 0m0.025s
// sys 0m0.001s
// `gcc-6 a.c && time ./a.out`
// real 0m0.093s
// user 0m0.084s
// sys 0m0.003s
// `gcc-6 -O3 a.c && time ./a.out`
// real 0m0.032s
// user 0m0.027s
// sys 0m0.002s
#include <stdio.h>
#include <time.h>
float speed = 0.01;
const int num_weights = 3;
float weights[3];
float activate(float num) {
// turn a sum over 0 into 1, and below 0 into -1
return num > 0 ? 1 : -1;
}
float feed_forward(float inputs[]) {
float sum = 0;
// multiply inputs by weights and sum them
for (int i = 0; i < num_weights; ++i) {
sum += weights[i] * inputs[i];
}
// return the 'activated' sum
return activate(sum);
}
void train(float inputs[], float desired_output) {
float guess = feed_forward(inputs);
float err = desired_output - guess;
for (int x = 0; x < num_weights; ++x) {
weights[x] += err * inputs[x] * speed;
}
}
int g_seed;
// http://stackoverflow.com/a/3747462
int fastrand() {
g_seed = (214013 * g_seed + 2531011);
return (g_seed >> 16) & 0x7FFF;
}
float frand() {
return (float)fastrand() / 32768;
}
int main() {
// init random generator
g_seed = time(0);
for (int x = 0; x < num_weights; ++x) {
weights[x] = frand() * 2 - 1;
}
for (int x = 0; x < 1000000; ++x) {
int x_coord = frand() * 500 - 250;
int y_coord = frand() * 500 - 250;
int line_y = .5 * x_coord + 10; // line: f(x) = 0.5x + 10
float arr[3] = { x_coord, y_coord, 1 };
train(arr, y_coord > line_y ? 1 : -1);
}
float arr1[3] = { -7, 9, 1 };
printf("(-7, 9): %f\n", feed_forward(arr1));
float arr2[3] = { 3, 1, 1 };
printf("(3, 1): %f\n", feed_forward(arr2));
printf("%f, %f, %f", weights[0], weights[1], weights[2]);
}
// `time csharp perceptron.cs`:
// real 0m0.902s
// user 0m0.835s
// sys 0m0.044s
class Perceptron {
private double speed;
public double[] weights;
public Perceptron(double learnSpeed, int numWeights) {
speed = learnSpeed;
weights = new double[numWeights];
var rand = new Random();
for (var i = 0; i < numWeights; ++i) {
weights[i] = rand.NextDouble() * 2 - 1;
}
}
public double FeedForward(double[] inputs) {
var sum = .0;
// multiply inputs by weights and sum them
for (var x = 0; x < weights.Length; ++x)
sum += weights[x] * inputs[x];
// return the 'activated' sum
return Activate(sum);
}
public double Activate(double num) {
return num > 0 ? 1 : -1;
}
public void Train(double[] inputs, double desiredOutput) {
var guess = FeedForward(inputs);
var error = desiredOutput - guess;
for (var x = 0; x < weights.Length; ++x)
weights[x] += error * inputs[x] * speed;
}
}
var p = new Perceptron(0.01, 3);
var rand = new Random();
for (var x = 0; x < 1000000; ++x) {
var xCoord = rand.NextDouble() * 500 - 250;
var yCoord = rand.NextDouble() * 500 - 250;
var lineY = 0.5 * xCoord + 10; // line: f(x) = 0.5x + 10
if (yCoord > lineY) { // above the line
p.Train(new double[] { xCoord, yCoord, 1 }, 1);
} else { // below the line
p.Train(new double[] { xCoord, yCoord, 1 }, -1);
}
}
Console.WriteLine("(-7, 9): " + p.FeedForward(new double[] { -7, 9, 1 }));
Console.WriteLine("(3, 1): " + p.FeedForward(new double[] { 3, 1, 1 }));
for (var i = 0; i < p.weights.Length; ++i) {
Console.Write(p.weights[i] + ", ");
}
Console.WriteLine();
! by Calak,
! gfortran perceptron.f -Ofast -o perceptron && time ./perceptron
! Not the same machine as others,
! ./main 0.02s user 0.00s system 97% cpu 0.024 total
module Perceptron
real :: speed = 0.01, weights(3)
contains
real function activate(num)
real :: num
!turn a sum over 0 into 1, and below 0 into -1
activate = merge(1., -1., num > 0)
end function activate
real function feed_forward(inputs)
real :: inputs(:), sum
!multiply inputs by weights and sum them
sum = dot_product(weights, inputs)
!return the "activated" sum
feed_forward = activate(sum)
end function feed_forward
subroutine train(inputs, desired_output)
real :: inputs(:), desired_output, guess, err
guess = feed_forward(inputs)
err = desired_output - guess
weights = weights + err * inputs * speed
end subroutine train
end module Perceptron
program main
use Perceptron
integer :: x_coord, y_coord, line_y, g_seed
integer*8 :: x
real, dimension(3) :: arr, arr1, arr2
g_seed = time()
weights = (/ (frand() * 2 - 1, x = 1, size(weights)) /)
do x = 0, 1000000
x_coord = frand() * 500 - 250
y_coord = frand() * 500 - 250
line_y = 0.5 * x_coord + 10 !line: f(x) = 0.5x + 10
arr = (/ x_coord, y_coord, 1 /)
call train(arr, merge(1., -1., y_coord > line_y))
end do
arr1 = (/ -7, 9, 1 /)
print *, "(-7, 9): ", feed_forward(arr1)
arr2 = (/ 3, 1, 1 /)
print *, "(3, 1): ", feed_forward(arr2)
print *, weights
contains
integer function fastrand()
g_seed = 214013 * g_seed + 2531011
fastrand = and(rshift(g_seed, 16), z'7FFF')
end function fastrand
real function frand()
frand = real(fastrand()) / 32768
end function frand
end program main
package main
// `go build perceptron.go && time ./perceptron`
// real 0m0.167s
// user 0m0.157s
// sys 0m0.007s
import (
"math/rand"
"fmt"
)
var (
speed float32 = 0.01
num_weights = 3
weights [3]float32
)
func feed_forward(inputs []float32) float32 {
var sum float32
// multiply inputs by weights and sum them
for i := 0; i < num_weights; i++ {
sum += weights[i] * inputs[i]
}
// return the 'activated' sum
return activate(sum)
}
func activate(num float32) float32 {
// turn a sum over 0 into 1, and below 0 into -1
var result float32
result = -1
if num > 0 {
result = 1
}
return result
}
func train(inputs []float32, desired_output float32) {
guess := feed_forward(inputs)
err := desired_output - guess
for x := 0; x < num_weights; x++ {
weights[x] += err * inputs[x] * speed
}
}
func main() {
for x := 0; x < num_weights; x++ {
weights[x] = rand.Float32() * 2 - 1
}
for x := 0; x < 1000000; x++ {
x_coord := rand.Float32() * 500 - 250
y_coord := rand.Float32() * 500 - 250
line_y := .5 * x_coord + 10 // line: f(x) = 0.5x + 10
arr := make([]float32, 3)
arr[0] = x_coord
arr[1] = y_coord
arr[2] = 1
var expected float32
expected = -1
if y_coord > line_y {
expected = 1
}
train(arr, expected)
}
arr := make([]float32, 3)
arr[0] = -7
arr[1] = 9
arr[2] = 1
fmt.Printf("(-7, 9): %f\n", feed_forward(arr))
arr[0] = 3
arr[1] = 1
arr[2] = 1
fmt.Printf("(3, 1): %f\n", feed_forward(arr))
}
// `time node perceptron.js`
// real 0m0.199s
// user 0m0.172s
// sys 0m0.022s
function perceptron(speed, numWeights) {
var weights = [];
for (var i = 0; i < numWeights; ++i) {
weights.push(Math.random() * 2 - 1);
}
function feedForward(inputs) {
var sum = 0;
// multiply inputs by weights and sum them
for (var x = 0; x < weights.length; ++x)
sum += weights[x] * inputs[x];
// return the 'activated' sum
return activate(sum);
}
function activate(num) {
return num > 0 ? 1 : -1;
}
return {
feedForward,
activate,
weights,
train(inputs, desiredOutput) {
var guess = feedForward(inputs);
var error = desiredOutput - guess;
for (var x = 0; x < weights.length; ++x)
weights[x] += error * inputs[x] * speed;
}
}
}
function trainer() {
var p = perceptron(0.01, 3);
for (var x = 0; x < 1000000; ++x) {
var xCoord = Math.random() * 500 - 250;
var yCoord = Math.random() * 500 - 250;
var lineY = 0.5 * xCoord + 10; // line: f(x) = 0.5x + 10;
if (yCoord > lineY) { // above the line
p.train([xCoord, yCoord, 1], 1);
} else { // below the line
p.train([xCoord, yCoord, 1], -1);
}
}
return p; // return our trained perceptron
}
var p = trainer();
console.log('(-7, 9): ' + p.feedForward([-7, 9, 1]));
console.log('(3, 1): ' + p.feedForward([3, 1, 1]));
console.log(p.weights);
<?php
// `time php perceptron.php`
// real 0m5.710s
// user 0m5.635s
// sys 0m0.038s
// (hhvm is faster but I don't have it on the same setup)
function r() {
return mt_rand(0, 32767) / 32767;
}
class Perceptron {
var $speed;
var $weights;
function __construct($learn_speed, $num_weights) {
$this->speed = $learn_speed;
$this->weights = [];
for ($x = 0; $x < $num_weights; ++$x) {
$this->weights[] = r() * 2 - 1;
}
}
function getWeights() {
return $this->weights;
}
public function feed_forward($inputs) {
$sum = 0;
# multiply inputs by weights and sum them
for ($i = 0; $i < count($this->weights); ++$i) {
$sum += $this->weights[$i] * $inputs[$i];
}
# return the 'activated' sum
return $this->activate($sum);
}
function activate($num) {
# turn a sum over 0 into 1, and below 0 into -1
if ($num > 0)
return 1;
return -1;
}
function train($inputs, $desired_output) {
$guess = $this->feed_forward($inputs);
$error = $desired_output - $guess;
for ($x = 0; $x < count($this->weights); ++$x) {
$this->weights[$x] += $error * $inputs[$x] * $this->speed;
}
}
}
$p = new Perceptron(0.01, 3);
for ($x = 0; $x < 1000000; ++$x) {
$x_coord = r() * 500 - 250;
$y_coord = r() * 500 - 250;
$line_y = .5 * $x_coord + 10; # line: f(x) = 0.5x + 10;
$p->train([$x_coord, $y_coord, 1], $y_coord > $line_y
? 1 # above the line
: -1); # below the line
}
echo "(-7, 9): " . $p->feed_forward([-7, 9, 1]) . "\n";
echo "(3, 1): " . $p->feed_forward([3, 1, 1]) . "\n";
echo var_dump($p->weights);
# `time python3 perceptron.py`
# real 0m6.740s
# user 0m6.580s
# sys 0m0.044s
# `time pypy perceptron.py`
# real 0m0.593s
# user 0m0.536s
# sys 0m0.049s
import random
speed = 0.01
num_weights = 3
weights = []
def feed_forward(inputs):
sum = 0
# multiply inputs by weights and sum them
for x in range(0, len(weights)):
sum += weights[x] * inputs[x]
# return the 'activated' sum
return activate(sum)
def activate(num):
# turn a sum over 0 into 1, and below 0 into -1
if num > 0:
return 1
return -1
def train(inputs, desired_output):
guess = feed_forward(inputs)
error = desired_output - guess
for x in range(0, len(weights)):
weights[x] += error * inputs[x] * speed
for x in range(0, num_weights):
weights.append(random.random()*2-1)
for x in range(0, 1000000):
x_coord = random.random()*500-250
y_coord = random.random()*500-250
line_y = .5 * x_coord + 10 # line: f(x) = 0.5x + 10
if y_coord > line_y: # above the line
train([x_coord, y_coord, 1], 1)
else: # below the line
train([x_coord, y_coord, 1], -1)
print("(-7, 9): " + str(feed_forward([-7,9,1])))
print("(3, 1): " + str(feed_forward([3,1,1])))
print(weights)
// rustc perceptron.rs -C opt-level=3 && time ./perceptron
//
// Not the same machine as others,
// 0.03s user 0.00s system 98% cpu 0.032 total
//
// Add
// [profile.dev]
// overflow-checks = false
// to cargo while development
use std::time::{SystemTime, UNIX_EPOCH};
mod perceptron {
const SPEED: f32 = 0.01;
pub const NUM_WEIGHTS: usize = 3;
#[derive(Debug)]
pub struct Perceptron {
weights: [f32; NUM_WEIGHTS],
}
impl Perceptron {
pub fn new(mut rand: impl FnMut() -> f32) -> Perceptron {
let mut perceptron = Perceptron { weights: [0.0; 3] };
for x in 0..NUM_WEIGHTS {
perceptron.weights[x] = rand();
}
perceptron
}
fn activate(self: &Self, num: f32) -> f32 {
// turn a sum over 0 into 1, and below 0 into -1
if num > 0.0 {
1.0
} else {
-1.0
}
}
pub fn feed_forward(self: &mut Self, inputs: [f32; NUM_WEIGHTS]) -> f32 {
let mut sum = 0.0;
// multiply inputs by WEIGHTS and sum them
for i in 0..NUM_WEIGHTS {
sum += self.weights[i] * inputs[i];
}
// return the 'activated' sum
self.activate(sum)
// or just self.activate((0..NUM_WEIGHTS).map(|i| self.weights[i] * inputs[i]).sum())
}
pub fn train(self: &mut Self, inputs: [f32; NUM_WEIGHTS], desired_output: f32) {
let guess = self.feed_forward(inputs);
let err = desired_output - guess;
for x in 0..NUM_WEIGHTS {
self.weights[x] += err * inputs[x] * SPEED;
}
}
}
}
mod rand {
pub struct Rand {
seed: i32,
}
impl Rand {
pub fn new(seed: i32) -> Rand {
Rand { seed }
}
// http://stackoverflow.com/a/3747462
fn fastrand(self: &mut Self) -> i32 {
self.seed = 214013 * self.seed + 2531011;
(self.seed >> 16) & 0x7FFF
}
pub fn frand(self: &mut Self) -> f32 {
self.fastrand() as f32 / 32768.0
}
}
}
fn main() {
// init random generator
let mut rand = rand::Rand::new(
SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_secs() as i32,
);
let mut perceptron = perceptron::Perceptron::new(|| rand.frand() * 2.0 - 1.0);
for _ in 0..1000000 {
let x_coord = rand.frand() * 500.0 - 250.0;
let y_coord = rand.frand() * 500.0 - 250.0;
let line_y = x_coord / 2.0 + 10.0; // line: f(x) = 0.5x + 10
let arr = [x_coord, y_coord, 1.0];
perceptron.train(arr, if y_coord > line_y { 1.0 } else { -1.0 });
}
println!("(-7, 9): {}", perceptron.feed_forward([-7.0, 9.0, 1.0]));
println!("(3, 1): {}", perceptron.feed_forward([3.0, 1.0, 1.0]));
println!("{:?}", perceptron);
}
' by Calak
DECLARE FUNCTION activate# (num AS DOUBLE)
DECLARE FUNCTION feedForward# (inputs() AS DOUBLE)
DECLARE SUB train (inputs() AS DOUBLE, desiredOutput AS DOUBLE)
CONST speed = .01
DIM numWeights AS INTEGER: numWeights = 3
REDIM SHARED weights(numWeights - 1) AS DOUBLE
RANDOMIZE TIMER
DIM x AS LONG
FOR x = 0 TO UBOUND(weights)
weights(x) = RND * 2 - 1
NEXT x
DIM xCoord AS INTEGER, yCoord AS INTEGER, lineY AS INTEGER
DIM arr(2) AS DOUBLE, expected AS DOUBLE
FOR x = 0 TO 1000000
xCoord = RND * 500 - 250
yCoord = RND * 500 - 250
lineY = .5 * xCoord + 10 ' line: f(x) = 0.5x + 10
arr(0) = xCoord: arr(1) = yCoord: arr(2) = 1
IF yCoord > lineY THEN expected = 1 ELSE expected = -1
CALL train(arr(), expected)
NEXT x
DIM arr1(2) AS DOUBLE, arr2(2) AS DOUBLE
arr1(0) = -7: arr1(1) = 9: arr1(2) = 1
PRINT "(-7, 9): "; feedForward(arr1())
arr2(0) = 3: arr2(1) = 1: arr2(2) = 1
PRINT "(3, 1): "; feedForward(arr2())
PRINT weights(0), weights(1), weights(2)
END
FUNCTION activate# (num AS DOUBLE)
' turn a sum over 0 into 1, and below 0 into -1
IF num > 0 THEN activate = 1 ELSE activate = -1
END FUNCTION
FUNCTION feedForward# (inputs() AS DOUBLE)
DIM sum AS DOUBLE, i AS INTEGER
' multiply inputs by weights and sum them
FOR i = 0 TO UBOUND(weights)
sum = sum + weights(i) * inputs(i)
NEXT i
' return the "activated" sum
feedForward = activate(sum)
END FUNCTION
SUB train (inputs() AS DOUBLE, desiredOutput AS DOUBLE)
DIM guess AS DOUBLE, er AS DOUBLE
guess = feedForward(inputs())
er = desiredOutput - guess
DIM x AS INTEGER
FOR x = 0 TO UBOUND(weights)
weights(x) = weights(x) + er * inputs(x) * speed
NEXT x
END SUB
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment