Skip to content

Commit

Permalink
vol2: Python, more work on genetic algo
Browse files Browse the repository at this point in the history
  • Loading branch information
jeffheaton committed Aug 8, 2014
1 parent ad41001 commit 1197e96
Show file tree
Hide file tree
Showing 9 changed files with 1,071 additions and 6 deletions.
90 changes: 90 additions & 0 deletions vol2/vol2-python-examples/examples/Equilateral.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
"""
Artificial Intelligence for Humans
Volume 2: Nature-Inspired Algorithms
Python Version
http://www.aifh.org
http://www.jeffheaton.com
Code repository:
https://github.com/jeffheaton/aifh
Copyright 2014 by Jeff Heaton
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
For more information on Heaton Research copyrights, licenses
and trademarks visit:
http://www.heatonresearch.com/copyright
"""
__author__ = 'jheaton'

import math
import numpy as np
from scipy.spatial import distance


class Equilateral(object):
def __init__(self, class_count, normalized_low, normalized_high):
""" Create a lookup table that will be used for both Equilateral encoding and decoding.
"""
# Allocate a matrix to hold the lookup table.

self.encoded = np.ndarray(shape=(class_count, class_count - 1), dtype=float)

# Seed the result.
self.encoded[0][0] = -1
self.encoded[1][0] = 1.0

for k in range(2, class_count):
# scale the matrix so far
r = k
f = math.sqrt(r * r - 1.0) / r
for i in range(0, k):
for j in range(0, k - 1):
self.encoded[i][j] *= f

r = -1.0 / r
for i in range(0, k):
self.encoded[i][k - 1] = r

for i in range(0, k - 1):
self.encoded[k][i] = 0.0

self.encoded[k][k - 1] = 1.0

# Scale it.
min_eq = -1
max_eq = 1
for row in range(0, len(self.encoded)):
for col in range(0, len(self.encoded[row])):
self.encoded[row][col] = ((self.encoded[row][col] - min_eq) / (max_eq - min_eq)) \
* (normalized_high - normalized_low) + normalized_low

def encode(self, class_num):
""" Provide the equilateral encoded vector for the specified class.
"""
return self.encoded[class_num]

def decode(self, vec):
""" Match the specified vector to the class that it most closely fits.
"""
min_dist = float('inf')
result = -1

for i in range(0, len(self.encoded)):
dist = distance.euclidean(vec, self.encoded[i])
if dist < min_dist:
result = i
min_dist = dist

return result
389 changes: 389 additions & 0 deletions vol2/vol2-python-examples/examples/example_genetic_iris.py

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion vol2/vol2-python-examples/examples/example_genetic_tsp.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ def score_funct(x):
pop.score_function = score_funct
pop.goal_maximize = False

pop.train(500,10)
pop.train(pop.species[0],score_funct)

# Display results.
print("Final distance: " + str(pop.best_genome.score) )
Expand Down
39 changes: 39 additions & 0 deletions vol2/vol2-python-examples/lib/aifh/aifh_error.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
"""
Artificial Intelligence for Humans
Volume 2: Nature-Inspired Algorithms
Python Version
http://www.aifh.org
http://www.jeffheaton.com
Code repository:
https://github.com/jeffheaton/aifh
Copyright 2013 by Jeff Heaton
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
For more information on Heaton Research copyrights, licenses
and trademarks visit:
http://www.heatonresearch.com/copyright
"""
__author__ = 'jheaton'


class AIFHError(Exception):
"""An error was raised. This is used for several purposes, see individual error messages."""

def __init__(self, value):
self.value = value

def __str__(self):
return repr(self.value)
49 changes: 49 additions & 0 deletions vol2/vol2-python-examples/lib/aifh/error.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
"""
Artificial Intelligence for Humans
Volume 4: Nature-Inspired Algorithms
Python Version
http://www.aifh.org
http://www.jeffheaton.com
Code repository:
https://github.com/jeffheaton/aifh
Copyright 2014 by Jeff Heaton
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
For more information on Heaton Research copyrights, licenses
and trademarks visit:
http://www.heatonresearch.com/copyright
"""
__author__ = 'jheaton'

import numpy as np


class ErrorCalculation:
def __init__(self):
self.global_error = 0
self.count = 0

@staticmethod
def rms(actual, ideal):
return np.sqrt(np.mean((actual[:, :] - ideal[:, :]) ** 2))

@staticmethod
def sse(actual, ideal):
return np.sum((actual[:, :] - ideal[:, :]) ** 2)

@staticmethod
def mse(actual, ideal):
return np.mean((actual[:, :] - ideal[:, :]) ** 2)
41 changes: 36 additions & 5 deletions vol2/vol2-python-examples/lib/aifh/genetic.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,16 @@


class Population:
discrete = False
allow_repeats = True
species = []
goal_maximize = True
selection = None
score_function = None
best_genome = None
display_iteration = True
max_gen = 1000000
max_stagnant = 10


def better_than(self,g1,g2):
if self.goal_maximize:
Expand Down Expand Up @@ -47,23 +52,49 @@ def iteration(self):

self.species[0].members = next_generation

def train(self,max_gen,max_stagnant):
def train(self,x0,score_funct,pop_size=1000,low=1,high=-1):
generation = 1
stagnant = 0
last_best = None

while generation<=max_gen and stagnant<max_stagnant:
if not self.discrete and not self.allow_repeats:
raise("Non-discrete (continuous) problems must allow repeats, please set allow_repeats=true.")

# Do we need to generate a population?
if len(self.species[0].members) == 0:
for i in range(1,pop_size):
genome = Genome()

if self.discrete:
for j in range(0,len(x0)):
genome.genes.append(randint(low,high))
else:
for j in range(0,len(x0)):
genome.genes.append(uniform(low,high))

# Score the population
for genome in self.species[0].members:
genome.score = score_funct(genome.genes)

# Loop through training
while generation<=self.max_gen and stagnant<self.max_stagnant:
self.iteration()
print("Generaton #" + str(generation) + ", Score=" + str(self.best_genome.score) + ", stagnant=" + str(stagnant))

if self.display_iteration:
print("Generaton #" + str(generation) + ", Score=" + str(self.best_genome.score) + ", stagnant=" + str(stagnant))

generation = generation + 1

if last_best <> None and math.fabs(last_best.score-self.best_genome.score)<0.001:
if last_best != None and math.fabs(last_best.score-self.best_genome.score)<0.001:
stagnant = stagnant + 1
else:
stagnant = 0

last_best = self.best_genome

# Copy winner
for i in range(0,len(x0)-1):
x0[i] = self.best_genome.genes[i]


class Species:
Expand Down
Loading

0 comments on commit 1197e96

Please sign in to comment.