• Stars
    star
    109
  • Rank 319,077 (Top 7 %)
  • Language
    Go
  • License
    BSD 2-Clause "Sim...
  • Created almost 3 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Genetic algorithm for unsupervised machine learning in Go.

go.dev reference Go Report Card codecov License

μ8

Simple unsupervised machine learning package using Go 1.18 generics.

User information

μ8 (mu8) uses a simple genetic algorithm implementation to optimize a objective function. It allows optimizing floating point numbers, integers and anything else that can implement the 3 method Gene interface

The genetic algorithm implementation is currently ~150 lines long and is contained in population.go. It consists of the following steps:

  1. Natural selection. Best individual conserved (population champion)
  2. Mate.
  3. Mutate babies.
  4. Rinse and repeat.

The file mu8.go contains Genome and Gene interface definitions. Users should implement Genome interface and use Gene implementations from genes package.

There is an Islands Model Genetic Algorithm (IMGA) implementation in islands.go using the Islands type that makes use of a parallel optimization algorithm to make use of multi-core machines.

μ8 examples

Basic usage example

Everything starts with the mu8.Genome type on the user side. We define a type that implements it using a helper type genes.ContrainedFloat from the genes package. All this genes type does is save us the trouble of writing our own mu8.Gene implementation.

type mygenome struct {
	genoma []genes.ConstrainedFloat
}

func (g *mygenome) GetGene(i int) mu8.Gene { return &g.genoma[i] }
func (g *mygenome) Len() int               { return len(g.genoma) }

// Simulate simply adds the genes. We'd expect the genes to reach the max values of the constraint.
func (g *mygenome) Simulate() (fitness float64) {
	for i := range g.genoma {
		fitness += g.genoma[i].Value()
	}
    // fitness must ALWAYS be greater than zero for succesful simulation.
	return math.Max(0, fitness/float64(g.Len()))
}

We're almost ready to optimize our implementation to maximize it's fitness, which would simply be the addition of all it's genes.

Let's write the function that initializes a blank-slate mygenome

func newGenome(n int) *mygenome {
	return &mygenome{genoma: make([]genes.ConstrainedFloat, n)}
}

The function above may be confusing... what is the constraint on the number? By default genes.ConstrainedFloat uses the range [0, 1].

const Nindividuals = 100
individuals := make([]*mygenome, Nindividuals)
for i := 0; i < Nindividuals; i++ {
	genome := newGenome(genomelen)
	// This spices up the initial population so fitnesses are not all zero.
	mu8.Mutate(genome, src, .1)
	individuals[i] = genome
}

pop := genetic.NewPopulation(individuals, rand.NewSource(1), func() *mygenome {
		return newGenome(3)
})

const Ngeneration = 100
ctx := context.Background()
for i := 0; i < Ngenerations; i++ {
		err := pop.Advance(ctx)
		if err != nil {
			panic(err.Error())
		}
		err = pop.Selection(0.5, 1)
		if err != nil {
			panic(err.Error())
		}
}
fmt.Printf("champ fitness=%.3f\n", pop.ChampionFitness())

The final fitness should be close to 1.0 if the algorithm did it's job. For the code see mu8_test.go

Rocket stage optimization example

See rocket for a demonstration on rocket stage optimization. Below is the output of said program

champHeight:117.967km
champHeight:136.748km
champHeight:140.633km
champHeight:141.873km
champHeight:141.873km
champHeight:141.873km
champHeight:142.883km
champHeight:143.292km
champHeight:143.292km
champHeight:143.292km
champHeight:143.292km
our champion: 
Stage 0: coast=281.2s, propMass=0.0kg, Δm=99.35kg/s, totalMass=200.0
Stage 1: coast=0.0s, propMass=1.6kg, Δm=0.01kg/s, totalMass=21.6

Gradient "ascent" example

src := rand.NewSource(1)
const (
	genomelen      = 6
	gradMultiplier = 10.0
	epochs         = 6
)
// Create new individual and mutate it randomly.
individual := newGenome(genomelen)
rng := rand.New(src)
for i := 0; i < genomelen; i++ {
	individual.GetGene(i).Mutate(rng)
}
// Prepare for gradient descent.
grads := make([]float64, genomelen)
ctx := context.Background()
// Champion will harbor our best individual.
champion := newGenome(genomelen)
for epoch := 0; epoch < epochs; epoch++ {
	// We calculate the gradients of the individual passing a nil
	// newIndividual callback since the GenomeGrad type we implemented
	// does not require blank-slate initialization.
	err := mu8.Gradient(ctx, grads, individual, nil)
	if err != nil {
		panic(err)
	}
	// Apply gradients.
	for i := 0; i < individual.Len(); i++ {
		gene := individual.GetGeneGrad(i)
		grad := grads[i]
		gene.SetValue(gene.Value() + grad*gradMultiplier)
	}
	mu8.CloneGrad(champion, individual)
	fmt.Printf("fitness=%f with grads=%f\n", individual.Simulate(ctx), grads)
}

Contributing

Contributions very welcome! I myself have no idea what I'm doing so I welcome issues on any matter :)

Pull requests also welcome but please submit an issue first on what you'd like to change. I promise I'll answer as fast as I can.

Please take a look at the TODO's in the project: Ctrl+F TODO

References

Inspired by CodeBullets amazing video on the subject.

Logo work

Gopher rendition by Juliette Whittingslow.
Gopher design authored by Renée French is licensed by the Creative Commons Attribution 3.0 licensed.

More Repositories

1

gopherlings

📘️ Learn Go by fixing tiny incorrect programs
Go
632
star
2

cyw43439

Driver for the Wifi+bluetooth integrated circuit on the pico.
Go
112
star
3

sdf

A Go library for signed distance function shape generation. Read as 3D printing shape design.
Go
92
star
4

gitaligned

Find out where you fall on the Open-Source Character Alignment Chart
Go
74
star
5

natiu-mqtt

A dead-simple, extensible MQTT implementation well suited for embedded systems.
Go
58
star
6

go-maquina

Small finite-state machine library for Go
Go
41
star
7

peasocket

little websocket implementation
Go
34
star
8

go-presentx

golang's present tool but with code syntax highlighting
CSS
33
star
9

rebed

Recreates directory and files from embedded filesystem using Go 1.16 embed.FS type.
Go
23
star
10

godesim

ODE system solver made simple. For IVPs (initial value problems).
Go
21
star
11

exif

Dead simple exchangeable image file format tools for Go optimized for large image files using lazy loading.
Go
18
star
12

tiny-ahrsim

TinyGo attitude estimation simulation applet.
Go
17
star
13

threejs-golang-example

THREE.js example of rotating cube using gopherjs bindings. 160 lines of Go code.
JavaScript
14
star
14

sdf3ui

Browser based 3D model visualizer for use with soypat/sdf package.
Go
12
star
15

glgl

OpenGL bindings for Go that are in the goldilocks level of abstraction zone.
Go
12
star
16

three

syscall/js bindings for three.js in-browser 3D graphics.
Go
10
star
17

neurus

Neural network minimal working example in Go fit for teaching.
Go
10
star
18

ether-swtch

Low level Ethernet stack marshaller/unmarshaller for use in tiny places.
Go
8
star
19

natiu-wsocket

MQTT websocket implementation using natiu-mqtt.
Go
6
star
20

lap

linear algebra package. like gonum/mat, but small. lets say gonum-lite
Go
5
star
21

goldmark-latex

A LaTeX renderer for Goldmark. Produce .tex files from markdown.
Go
5
star
22

ieeeztreme14

IEEExtreme 14.0 solved problems for team finally_cflat
Go
4
star
23

go-play3d

3D math playground for Go.
Go
4
star
24

sv

idiomatic go http server
Go
3
star
25

gwasm

Common utilities I find myself rewriting too often across Go WASM projects.
Go
3
star
26

peamodbus

Fault tolerant, TCP modbus implementation in Go that just works. Apt for embedded systems.
Go
3
star
27

tinygo-arduino-examples

Compilation of LCD screen, ADC, and output examples.
Go
2
star
28

go-canard

Go port of libcanard. WIP.
Go
2
star
29

decimate

csv file decimator/downsampler for reducing number of points of a curve or signal.
Go
2
star
30

manigold

3D Mesh creation, manipulation and optimization library.
Go
2
star
31

go-mod-tricks

go.mod file and `go mod` command tricks to make using modules a breeze.
2
star
32

mdc

Material Design Components for use with Vecty in the most minimalistic fashion.
Go
2
star
33

plot3

3D line plots in pure Go
Go
2
star
34

whittileaks

Hardcore class notes for mechanical engineering.
TeX
2
star
35

decaffeinator

An effort to relieve the establishment of caffeine.
Go
1
star
36

piaa

Industrial extension board for Raspberry Pi Pico (W). RS485, EMI insulated digital input/output pins.
1
star
37

so

MWE tutorial of .so dynamic linking in C and Go.
C
1
star
38

tiny-sproto

A simple Point-to-Point Protocol implementation written in Go.
Go
1
star
39

wchart

syscall/js bindings for Chart.js
Go
1
star
40

novatex

Guía del LaTeX para principiantes
TeX
1
star
41

go-fem

Go packages for finite element analysis/methods.
Go
1
star
42

net

Temporary repo for minimal net package from go std lib for use with tinygo until v0.18.0 released
Go
1
star
43

fea-two

Elementos Finitos II @ ITBA
MATLAB
1
star
44

combinatrix

Combinar horarios para ITBA """dinamicamente"""
Go
1
star
45

go-qap

CERN's quality assurance plan (QAP) to solve the document naming convention problem.
Go
1
star
46

shaders

Wai- wha? Shaders? Like GPU stuff? Yeah, gpu stuff.
Go
1
star
47

vecty-examples

Basic usage of Vecty framework examples.
Go
1
star
48

go-proy

Proyectos para practicar golang
Go
1
star
49

seqs

seqs: the hottest, most idiomatic TCP implementation on the internet.
Go
1
star