Skip to content

Instantly share code, notes, and snippets.

@adrianseeley
Created March 4, 2014 16:26
Show Gist options
  • Save adrianseeley/9349785 to your computer and use it in GitHub Desktop.
Save adrianseeley/9349785 to your computer and use it in GitHub Desktop.
GATO.WEIGHTED GENETIC FOLDER (C#) - IRIS -> 0 ERRORS
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
namespace GATO.WGF
{
class Program
{
static void Main(string[] args)
{
List<TrainingCase> TrainingCases = new List<TrainingCase>();
using (FileStream FS = File.OpenRead("iris.data"))
{
using (StreamReader SR = new StreamReader(FS))
{
while (!SR.EndOfStream)
{
String Line = SR.ReadLine();
String[] Parts = Line.Split(',');
List<double> Inputs = new List<double>();
for (int p = 0; p < Parts.Length - 1; p++)
{
Inputs.Add(Double.Parse(Parts[p]));
}
TrainingCases.Add(new TrainingCase(Inputs.ToArray(), Parts[Parts.Length - 1]));
}
}
}
WeightedGeneticFolder WGF = new WeightedGeneticFolder(NumberOfInputs: 4);
WGF.Train(
TrainingCases,
ErrorThreshold: 0,
FitnessThreshold: 2, // class count - 1
IterationThreshold: 100000,
MaximumHalfPopulation: 10,
AddGeneticFoldRate: 0.50
);
Console.WriteLine("Final Fitness: " + WGF.OptimalConfiguration.Fitness);
Console.WriteLine("Total Errors: " + WGF.OptimalConfiguration.Test(TrainingCases));
Console.ReadLine();
}
}
class WeightedGeneticFolder
{
public int NumberOfNearestNeighbours;
public WeightedGeneticFolderConfiguration OptimalConfiguration;
public WeightedGeneticFolder(int NumberOfInputs)
{
OptimalConfiguration = new WeightedGeneticFolderConfiguration(NumberOfInputs);
}
public void Train (List<TrainingCase> TrainingCases, double ErrorThreshold, double FitnessThreshold, int IterationThreshold, int MaximumHalfPopulation, double NerfRate = 1.01, double WeightPointMutationRate = 0.05, double WeightPointMutationAmount = 0.05, double AddGeneticFoldRate = 0.10, double RemovePointGeneticFoldRate = 0.05, double GeneticFoldPointMutationRate = 0.05, double GeneticFoldPointMutationAmount = 0.05)
{
OptimalConfiguration.BuildNeighbourhood(TrainingCases);
OptimalConfiguration.AssesFitness(TrainingCases);
OptimalConfiguration.Nerf = 1.0;
List<WeightedGeneticFolderConfiguration> Population = new List<WeightedGeneticFolderConfiguration>() { OptimalConfiguration };
for (int Iteration = 0; Iteration < IterationThreshold && Population[0].Errors > ErrorThreshold && Population[0].Fitness > FitnessThreshold; Iteration++)
{
StringBuilder sb = new StringBuilder();
sb.Append("Iteration: " + Iteration + " Errors: " + Population[0].Errors + " Fit: " + Population[0].Fitness + " Nerf: " + Population[0].Nerf.ToString("N4") + " G: " + Population[0].GeneticFolds.Count + " W: ");
for (int w = 0; w < Population[0].Weights.Length; w++)
{
sb.Append(Population[0].Weights[w].ToString("N4") + (w != Population[0].Weights.Length - 1 ? ", " : ""));
}
/*for (int g = 0; g < Population[0].GeneticFolds.Count; g++)
{
sb.Append(Population[0].GeneticFolds[g] + (g != Population[0].GeneticFolds.Count - 1 ? ", " : ""));
}*/
Console.WriteLine(sb);
for (int PopulationIterator = Population.Count - 1; PopulationIterator >= 0; PopulationIterator--)
{
WeightedGeneticFolderConfiguration Mutant = Population[PopulationIterator].Clone().Mutate(WeightPointMutationRate, WeightPointMutationAmount, AddGeneticFoldRate, RemovePointGeneticFoldRate, GeneticFoldPointMutationRate, GeneticFoldPointMutationAmount);
Mutant.BuildNeighbourhood(TrainingCases);
Mutant.AssesFitness(TrainingCases);
Mutant.Nerf = 1.0;
if (Mutant.Errors >= Population[PopulationIterator].Errors || Mutant.Fitness >= Population[PopulationIterator].Fitness)
{
Population[PopulationIterator].Nerf *= NerfRate;
}
Population.Add(Mutant);
}
Population.Sort((a, b) =>
{
int ret;
ret = a.Errors.CompareTo(b.Errors);
if (ret != 0) return ret;
ret = (a.Fitness * a.Nerf).CompareTo(b.Fitness * b.Nerf);
if (ret != 0) return ret;
return a.GeneticFolds.Count.CompareTo(b.GeneticFolds.Count);
});
if (Population.Count > MaximumHalfPopulation)
{
Population.RemoveRange(MaximumHalfPopulation, Population.Count - MaximumHalfPopulation);
}
}
Population.Sort((a, b) =>
{
int ret;
ret = a.Errors.CompareTo(b.Errors);
if (ret != 0) return ret;
ret = (a.Fitness).CompareTo(b.Fitness);
if (ret != 0) return ret;
return a.GeneticFolds.Count.CompareTo(b.GeneticFolds.Count);
});
OptimalConfiguration = Population[0];
}
}
class WeightedGeneticFolderConfiguration
{
public static Random R = new Random();
public double[] Weights;
public List<double> GeneticFolds;
public List<KeyValuePair<String, double>> Neighbourhood;
public int Errors;
public double Fitness;
public double Nerf;
public WeightedGeneticFolderConfiguration(int NumberOfInputs)
{
Weights = new double[NumberOfInputs];
for (int w = 0; w < Weights.Length; w++)
{
Weights[w] = 1;
}
GeneticFolds = new List<double>();
Neighbourhood = new List<KeyValuePair<string, double>>();
}
public WeightedGeneticFolderConfiguration Clone()
{
WeightedGeneticFolderConfiguration WGFC = new WeightedGeneticFolderConfiguration(Weights.Length);
Weights.CopyTo(WGFC.Weights, 0);
WGFC.GeneticFolds.AddRange(GeneticFolds.GetRange(0, GeneticFolds.Count));
WGFC.Neighbourhood.AddRange(Neighbourhood.GetRange(0, Neighbourhood.Count));
WGFC.Fitness = Fitness;
WGFC.Nerf = Nerf;
return WGFC;
}
public WeightedGeneticFolderConfiguration Mutate(double WeightPointMutationRate, double WeightPointMutationAmount, double AddGeneticFoldRate, double RemovePointGeneticFoldRate, double GeneticFoldPointMutationRate, double GeneticFoldPointMutationAmount)
{
for (int w = 0; w < Weights.Length; w++)
{
if (R.NextDouble() < WeightPointMutationRate)
{
Weights[w] += R.NextDouble() * ((Weights[w] * WeightPointMutationAmount) - (Weights[w] * -WeightPointMutationAmount)) + (Weights[w] * -WeightPointMutationAmount);
}
}
while (R.NextDouble() < AddGeneticFoldRate)
{
GeneticFolds.Add(Neighbourhood[R.Next(0, Neighbourhood.Count)].Value);
}
for (int g = GeneticFolds.Count - 1; g >= 0; g--)
{
if (R.NextDouble() < RemovePointGeneticFoldRate)
{
GeneticFolds.RemoveAt(g);
continue;
}
if (R.NextDouble() < GeneticFoldPointMutationRate)
{
GeneticFolds[g] += R.NextDouble() * ((GeneticFolds[g] * GeneticFoldPointMutationAmount) - (GeneticFolds[g] * -GeneticFoldPointMutationAmount)) + (GeneticFolds[g] * -GeneticFoldPointMutationAmount);
}
}
return this;
}
public void BuildNeighbourhood (List<TrainingCase> TrainingCases)
{
Neighbourhood = new List<KeyValuePair<string, double>>();
for (int t = 0; t < TrainingCases.Count; t++)
{
Neighbourhood.Add(new KeyValuePair<String, double>(TrainingCases[t].Class, Express(TrainingCases[t].Inputs)));
}
}
public double Express(double[] Inputs)
{
double OutputSum = 0;
for (int i = 0; i < Inputs.Length; i++)
{
OutputSum += Inputs[i] * Weights[i];
}
for (int g = 0; g < GeneticFolds.Count; g++)
{
OutputSum = Fold(GeneticFolds[g], OutputSum);
}
return OutputSum;
}
private double Fold(double GeneticFold, double OutputSum)
{
if (OutputSum > GeneticFold) return GeneticFold - (OutputSum - GeneticFold);
else return OutputSum;
}
public void AssesFitness(List<TrainingCase> TrainingCases)
{
Neighbourhood.Sort((a, b) =>
{
return a.Value.CompareTo(b.Value);
});
int Faults = 0;
String LastClass = Neighbourhood[0].Key;
for (int n = 1; n < Neighbourhood.Count; n++)
{
if (Neighbourhood[n].Key != LastClass)
{
LastClass = Neighbourhood[n].Key;
Faults++;
}
}
Fitness = Faults;
Errors = Test(TrainingCases);
}
public String Classify (double[] Inputs, int KNearestNeighbours)
{
return KNearestNeighbour(Express(Inputs), KNearestNeighbours);
}
public String KNearestNeighbour(double OutputSum, int KNearestNeighbours)
{
List<KeyValuePair<String, double>> NeighbourDistances = new List<KeyValuePair<string, double>>();
for (int n = 0; n < Neighbourhood.Count; n++)
{
NeighbourDistances.Add(new KeyValuePair<String, double> (Neighbourhood[n].Key, Math.Abs(Neighbourhood[n].Value - OutputSum)));
}
NeighbourDistances.Sort((a, b) =>
{
return a.Value.CompareTo(b.Value);
});
Dictionary<String, int> NearestNeighbours = new Dictionary<string, int>();
for (int n = 0; n < NeighbourDistances.Count && n < KNearestNeighbours; n++)
{
if (!NearestNeighbours.ContainsKey(NeighbourDistances[n].Key))
{
NearestNeighbours.Add(NeighbourDistances[n].Key, 0);
}
NearestNeighbours[NeighbourDistances[n].Key]++;
}
List<KeyValuePair<String, int>> NearestNeighboursList = NearestNeighbours.ToList();
NearestNeighboursList.Sort((a, b) =>
{
return a.Value.CompareTo(b.Value);
});
return NearestNeighboursList[0].Key;
}
public int Test(List<TrainingCase> TrainingCases)
{
int Errors = 0;
for (int t = 0; t < TrainingCases.Count; t++)
{
if (TrainingCases[t].Class != Classify(TrainingCases[t].Inputs, 3))
{
Errors++;
}
}
return Errors;
}
}
class TrainingCase
{
public double[] Inputs;
public String Class;
public TrainingCase(double[] Inputs, String Class)
{
this.Inputs = Inputs;
this.Class = Class;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment