-
Notifications
You must be signed in to change notification settings - Fork 86
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
113 changed files
with
14,409 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
|
||
# Code from Chapter 10 of Machine Learning: An Algorithmic Perspective (2nd Edition) | ||
# by Stephen Marsland (http://stephenmonika.net) | ||
|
||
# You are free to use, change, or redistribute the code in any way you wish for | ||
# non-commercial purposes, but please maintain the name of the original author. | ||
# This code comes with no warranty of any kind. | ||
|
||
# Stephen Marsland, 2008, 2014 | ||
|
||
# The Population Based Incremental Learning algorithm | ||
# Comment and uncomment fitness functions as appropriate (as an import and the fitnessFunction variable) | ||
|
||
import pylab as pl | ||
import numpy as np | ||
|
||
#import fourpeaks as fF | ||
import knapsack as fF | ||
|
||
def PBIL(): | ||
pl.ion() | ||
|
||
populationSize = 100 | ||
stringLength = 20 | ||
eta = 0.005 | ||
|
||
#fitnessFunction = 'fF.fourpeaks' | ||
fitnessFunction = 'fF.knapsack' | ||
p = 0.5*np.ones(stringLength) | ||
best = np.zeros(501,dtype=float) | ||
|
||
for count in range(501): | ||
# Generate samples | ||
population = np.random.rand(populationSize,stringLength) | ||
for i in range(stringLength): | ||
population[:,i] = np.where(population[:,i]<p[i],1,0) | ||
|
||
# Evaluate fitness | ||
fitness = eval(fitnessFunction)(population) | ||
|
||
# Pick best | ||
best[count] = np.max(fitness) | ||
bestplace = np.argmax(fitness) | ||
fitness[bestplace] = 0 | ||
secondplace = np.argmax(fitness) | ||
|
||
# Update vector | ||
p = p*(1-eta) + eta*((population[bestplace,:]+population[secondplace,:])/2) | ||
|
||
if (np.mod(count,100)==0): | ||
print count, best[count] | ||
|
||
pl.plot(best,'kx-') | ||
pl.xlabel('Epochs') | ||
pl.ylabel('Fitness') | ||
pl.show() | ||
#print p | ||
|
||
PBIL() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
# Code from Chapter 10 of Machine Learning: An Algorithmic Perspective (2nd Edition) | ||
# by Stephen Marsland (http://stephenmonika.net) | ||
|
||
# You are free to use, change, or redistribute the code in any way you wish for | ||
# non-commercial purposes, but please maintain the name of the original author. | ||
# This code comes with no warranty of any kind. | ||
|
||
# Stephen Marsland, 2008, 2014 | ||
|
||
# A fitness function for the Knapsack problem | ||
import numpy as np | ||
|
||
def billsfit(pop): | ||
|
||
|
||
maxSize = 500 | ||
#sizes = np.array([193.71,60.15,89.08,88.98,15.39,238.14,68.78,107.47,119.66,183.70]) | ||
|
||
sizes = np.array([109.60,125.48,52.16,195.55,58.67,61.87,92.95,93.14,155.05,110.89,13.34,132.49,194.03,121.29,179.33,139.02,198.78,192.57,81.66,128.90]) | ||
|
||
fitness = np.sum(sizes*pop,axis=1) | ||
fitness = np.where(fitness>maxSize,500-2*(fitness-maxSize),fitness) | ||
|
||
return fitness |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
|
||
# Code from Chapter 10 of Machine Learning: An Algorithmic Perspective (2nd Edition) | ||
# by Stephen Marsland (http://stephenmonika.net) | ||
|
||
# You are free to use, change, or redistribute the code in any way you wish for | ||
# non-commercial purposes, but please maintain the name of the original author. | ||
# This code comes with no warranty of any kind. | ||
|
||
# Stephen Marsland, 2008, 2014 | ||
|
||
# An exhaustive search to solve the Knapsack problem | ||
import numpy as np | ||
|
||
def exhaustive(): | ||
maxSize = 500 | ||
sizes = np.array([109.60,125.48,52.16,195.55,58.67,61.87,92.95,93.14,155.05,110.89,13.34,132.49,194.03,121.29,179.33,139.02,198.78,192.57,81.66,128.90]) | ||
|
||
best = 0 | ||
|
||
twos = np.arange(-len(sizes),0,1) | ||
twos = 2.0**twos | ||
|
||
for i in range(2**len(sizes)-1): | ||
string = np.remainder(np.floor(i*twos),2) | ||
fitness = np.sum(string*sizes) | ||
if fitness > best and fitness<500: | ||
best = fitness | ||
bestString = string | ||
print best | ||
print bestString | ||
|
||
exhaustive() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
|
||
# Code from Chapter 10 of Machine Learning: An Algorithmic Perspective (2nd Edition) | ||
# by Stephen Marsland (http://stephenmonika.net) | ||
|
||
# You are free to use, change, or redistribute the code in any way you wish for | ||
# non-commercial purposes, but please maintain the name of the original author. | ||
# This code comes with no warranty of any kind. | ||
|
||
# Stephen Marsland, 2008, 2014 | ||
|
||
# The four peaks fitness function | ||
import numpy as np | ||
def fourpeaks(population): | ||
|
||
T = 15 | ||
start = np.zeros((np.shape(population)[0],1)) | ||
finish = np.zeros((np.shape(population)[0],1)) | ||
|
||
fitness = np.zeros((np.shape(population)[0],1)) | ||
|
||
for i in range(np.shape(population)[0]): | ||
s = np.where(population[i,:]==1) | ||
f = np.where(population[i,:]==0) | ||
if np.size(s)>0: | ||
start = s[0][0] | ||
else: | ||
start = 0 | ||
|
||
if np.size(f)>0: | ||
finish = np.shape(population)[1] - f[-1][-1] -1 | ||
else: | ||
finish = 0 | ||
|
||
if start>T and finish>T: | ||
fitness[i] = np.maximum(start,finish)+100 | ||
else: | ||
fitness[i] = np.maximum(start,finish) | ||
|
||
fitness = np.squeeze(fitness) | ||
return fitness |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,163 @@ | ||
|
||
# Code from Chapter 10 of Machine Learning: An Algorithmic Perspective (2nd Edition) | ||
# by Stephen Marsland (http://stephenmonika.net) | ||
|
||
# You are free to use, change, or redistribute the code in any way you wish for | ||
# non-commercial purposes, but please maintain the name of the original author. | ||
# This code comes with no warranty of any kind. | ||
|
||
# Stephen Marsland, 2008, 2014 | ||
|
||
|
||
# The Genetic algorithm | ||
# Comment and uncomment fitness functions as appropriate (as an import and the fitnessFunction variable) | ||
|
||
import pylab as pl | ||
import numpy as np | ||
import fourpeaks as fF | ||
|
||
class ga: | ||
|
||
def __init__(self,stringLength,fitnessFunction,nEpochs,populationSize=100,mutationProb=-1,crossover='un',nElite=4,tournament=True): | ||
""" Constructor""" | ||
self.stringLength = stringLength | ||
|
||
# Population size should be even | ||
if np.mod(populationSize,2)==0: | ||
self.populationSize = populationSize | ||
else: | ||
self.populationSize = populationSize+1 | ||
|
||
if mutationProb < 0: | ||
self.mutationProb = 1/stringLength | ||
else: | ||
self.mutationProb = mutationProb | ||
|
||
self.nEpochs = nEpochs | ||
|
||
self.fitnessFunction = fitnessFunction | ||
|
||
self.crossover = crossover | ||
self.nElite = nElite | ||
self.tournment = tournament | ||
|
||
self.population = np.random.rand(self.populationSize,self.stringLength) | ||
self.population = np.where(self.population<0.5,0,1) | ||
|
||
def runGA(self,plotfig): | ||
"""The basic loop""" | ||
pl.ion() | ||
#plotfig = pl.figure() | ||
bestfit = np.zeros(self.nEpochs) | ||
|
||
for i in range(self.nEpochs): | ||
# Compute fitness of the population | ||
fitness = eval(self.fitnessFunction)(self.population) | ||
|
||
# Pick parents -- can do in order since they are randomised | ||
newPopulation = self.fps(self.population,fitness) | ||
|
||
# Apply the genetic operators | ||
if self.crossover == 'sp': | ||
newPopulation = self.spCrossover(newPopulation) | ||
elif self.crossover == 'un': | ||
newPopulation = self.uniformCrossover(newPopulation) | ||
newPopulation = self.mutate(newPopulation) | ||
|
||
# Apply elitism and tournaments if using | ||
if self.nElite>0: | ||
newPopulation = self.elitism(self.population,newPopulation,fitness) | ||
|
||
if self.tournament: | ||
newPopulation = self.tournament(self.population,newPopulation,fitness,self.fitnessFunction) | ||
|
||
self.population = newPopulation | ||
bestfit[i] = fitness.max() | ||
|
||
if (np.mod(i,100)==0): | ||
print i, fitness.max() | ||
#pl.plot([i],[fitness.max()],'r+') | ||
pl.plot(bestfit,'kx-') | ||
#pl.show() | ||
|
||
def fps(self,population,fitness): | ||
|
||
# Scale fitness by total fitness | ||
fitness = fitness/np.sum(fitness) | ||
fitness = 10*fitness/fitness.max() | ||
|
||
# Put repeated copies of each string in according to fitness | ||
# Deal with strings with very low fitness | ||
j=0 | ||
while np.round(fitness[j])<1: | ||
j = j+1 | ||
|
||
newPopulation = np.kron(np.ones((np.round(fitness[j]),1)),population[j,:]) | ||
|
||
# Add multiple copies of strings into the newPopulation | ||
for i in range(j+1,self.populationSize): | ||
if np.round(fitness[i])>=1: | ||
newPopulation = np.concatenate((newPopulation,np.kron(np.ones((np.round(fitness[i]),1)),population[i,:])),axis=0) | ||
|
||
# Shuffle the order (note that there are still too many) | ||
indices = range(np.shape(newPopulation)[0]) | ||
np.random.shuffle(indices) | ||
newPopulation = newPopulation[indices[:self.populationSize],:] | ||
return newPopulation | ||
|
||
def spCrossover(self,population): | ||
# Single point crossover | ||
newPopulation = np.zeros(np.shape(population)) | ||
crossoverPoint = np.random.randint(0,self.stringLength,self.populationSize) | ||
for i in range(0,self.populationSize,2): | ||
newPopulation[i,:crossoverPoint[i]] = population[i,:crossoverPoint[i]] | ||
newPopulation[i+1,:crossoverPoint[i]] = population[i+1,:crossoverPoint[i]] | ||
newPopulation[i,crossoverPoint[i]:] = population[i+1,crossoverPoint[i]:] | ||
newPopulation[i+1,crossoverPoint[i]:] = population[i,crossoverPoint[i]:] | ||
return newPopulation | ||
|
||
def uniformCrossover(self,population): | ||
# Uniform crossover | ||
newPopulation = np.zeros(np.shape(population)) | ||
which = np.random.rand(self.populationSize,self.stringLength) | ||
which1 = which>=0.5 | ||
for i in range(0,self.populationSize,2): | ||
newPopulation[i,:] = population[i,:]*which1[i,:] + population[i+1,:]*(1-which1[i,:]) | ||
newPopulation[i+1,:] = population[i,:]*(1-which1[i,:]) + population[i+1,:]*which1[i,:] | ||
return newPopulation | ||
|
||
def mutate(self,population): | ||
# Mutation | ||
whereMutate = np.random.rand(np.shape(population)[0],np.shape(population)[1]) | ||
population[np.where(whereMutate < self.mutationProb)] = 1 - population[np.where(whereMutate < self.mutationProb)] | ||
return population | ||
|
||
def elitism(self,oldPopulation,population,fitness): | ||
best = np.argsort(fitness) | ||
best = np.squeeze(oldPopulation[best[-self.nElite:],:]) | ||
indices = range(np.shape(population)[0]) | ||
np.random.shuffle(indices) | ||
population = population[indices,:] | ||
population[0:self.nElite,:] = best | ||
return population | ||
|
||
def tournament(self,oldPopulation,population,fitness,fitnessFunction): | ||
newFitness = eval(self.fitnessFunction)(population) | ||
for i in range(0,np.shape(population)[0],2): | ||
f = np.concatenate((fitness[i:i+2],newFitness[i:i+2]),axis=1) | ||
indices = np.argsort(f) | ||
if indices[-1]<2 and indices[-2]<2: | ||
population[i,:] = oldPopulation[i,:] | ||
population[i+1,:] = oldPopulation[i+1,:] | ||
elif indices[-1]<2: | ||
if indices[0]>=2: | ||
population[i+indices[0]-2,:] = oldPopulation[i+indices[-1]] | ||
else: | ||
population[i+indices[1]-2,:] = oldPopulation[i+indices[-1]] | ||
elif indices[-2]<2: | ||
if indices[0]>=2: | ||
population[i+indices[0]-2,:] = oldPopulation[i+indices[-2]] | ||
else: | ||
population[i+indices[1]-2,:] = oldPopulation[i+indices[-2]] | ||
return population | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
|
||
# Code from Chapter 10 of Machine Learning: An Algorithmic Perspective (2nd Edition) | ||
# by Stephen Marsland (http://stephenmonika.net) | ||
|
||
# You are free to use, change, or redistribute the code in any way you wish for | ||
# non-commercial purposes, but please maintain the name of the original author. | ||
# This code comes with no warranty of any kind. | ||
|
||
# Stephen Marsland, 2008, 2014 | ||
|
||
# A greedy algorithm to solve the Knapsack problem | ||
import numpy as np | ||
|
||
def greedy(): | ||
maxSize = 500 | ||
sizes = np.array([109.60,125.48,52.16,195.55,58.67,61.87,92.95,93.14,155.05,110.89,13.34,132.49,194.03,121.29,179.33,139.02,198.78,192.57,81.66,128.90]) | ||
|
||
sizes.sort() | ||
newSizes = sizes[-1:0:-1] | ||
space = maxSize | ||
|
||
while len(newSizes)>0 and space>newSizes[-1]: | ||
# Pick largest item that will fit | ||
item = np.where(space>newSizes)[0][0] | ||
print newSizes[item] | ||
space = space-newSizes[item] | ||
newSizes = np.concatenate((newSizes[:item],newSizes[item+1:])) | ||
print "Size = ",maxSize-space | ||
|
||
greedy() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
|
||
# Code from Chapter 10 of Machine Learning: An Algorithmic Perspective (2nd Edition) | ||
# by Stephen Marsland (http://stephenmonika.net) | ||
|
||
# You are free to use, change, or redistribute the code in any way you wish for | ||
# non-commercial purposes, but please maintain the name of the original author. | ||
# This code comes with no warranty of any kind. | ||
|
||
# Stephen Marsland, 2008, 2014 | ||
|
||
# A fitness function for the Knapsack problem | ||
import numpy as np | ||
|
||
def knapsack(pop): | ||
maxSize = 500 | ||
#sizes = np.array([193.71,60.15,89.08,88.98,15.39,238.14,68.78,107.47,119.66,183.70]) | ||
|
||
sizes = np.array([109.60,125.48,52.16,195.55,58.67,61.87,92.95,93.14,155.05,110.89,13.34,132.49,194.03,121.29,179.33,139.02,198.78,192.57,81.66,128.90]) | ||
|
||
fitness = np.sum(sizes*pop,axis=1) | ||
fitness = np.where(fitness>maxSize,500-2*(fitness-maxSize),fitness) | ||
|
||
return fitness |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
|
||
# Code from Chapter 10 of Machine Learning: An Algorithmic Perspective (2nd Edition) | ||
# by Stephen Marsland (http://stephenmonika.net) | ||
|
||
# You are free to use, change, or redistribute the code in any way you wish for | ||
# non-commercial purposes, but please maintain the name of the original author. | ||
# This code comes with no warranty of any kind. | ||
|
||
# Stephen Marsland, 2008, 2014 | ||
|
||
# A fitness function for the onemax problem | ||
import numpy as np | ||
|
||
def onemax(pop): | ||
|
||
fitness = np.sum(pop,axis=1) | ||
|
||
return fitness |
Oops, something went wrong.