在人工智能中,有没有一些简单和/或非常直观的例子,可以说明如何在模拟中实现基因组?
基本上,我想要一个简单的流程(不是教程,而是具有总结性质的东西),详细说明如何实现一个基因组,该基因组会改变模拟中“个体”的特征。
这些基因不应该是类似以下的东西:
- 质量
- 力量
- 长度
- 等等…
相反,它们应该是定义上述内容的东西,将基因组从模拟居民的实际特征中抽象出来。
我说的够清楚了吗?
无论如何,如果你尝试过任何更好的方法,并且以类似于这些有性游泳者的形式实现了进化,那么请务必发布它! 灵感越多越好 🙂
回答:
如果你自己实现“个体”,那么任何对象都可以充当你的基因组。
特征
进一步简化此操作的一种方法是将你的特征转换为枚举。 这样,你可以通过从父母那里选择特征来简单地重组父母的基因,并通过随机选择特征的其中一个枚举值来突变基因。
一旦这个方法可行,你就可以使用值范围来获得更细微的差别,但使用枚举可以帮助我一开始保持清晰。
适应度
然后,要赋予这些特征意义,你需要一个描述性能的适应度函数。 特征之间的关系由你决定,因此你可以用任何有意义的方式来描述它。 这只是提供了一种比较两个基因组的一致方法。
模拟
然后,要运行模拟,只需从几个父母开始,并生成一堆孩子来相互竞争。 这当然可以自动化,但为了清楚起见,这里有一个明确的例子。
Java 示例
import java.util.PriorityQueue;class Genome implements Comparable<Genome> { public enum Mass { LIGHT(1), AVERAGE(2), HEAVY(3); final Integer value; Mass(Integer value) { this.value = value; } } public enum Strength { WEAK(1), AVERAGE(2), STRONG(3); final Integer value; Strength(Integer value) { this.value = value; } } public enum Length { SHORT(1), AVERAGE(2), LONG(3); final Integer value; Length(Integer value) { this.value = value; } } private final Mass mass; private final Strength strength; private final Length length; public Genome(Mass mass, Strength strength, Length length) { this.mass = mass; this.strength = strength; this.length = length; } private Integer fitness() { return strength.value * length.value - mass.value * mass.value; } @Override public int compareTo(Genome that) { // notice the fitter is less in precedence if(this.fitness() > that.fitness()) return -1; else if(this.fitness() < that.fitness()) return 1; else // this.fitness() == that.fitness() return 0; } public static Genome recombine(Genome... parents) { if(parents.length < 1) return null; // Select parents randomly and then characteristics from them Mass mass = parents[(int)(Math.random() * parents.length)].mass; Strength strength = parents[(int)(Math.random() * parents.length)].strength; Length length = parents[(int)(Math.random() * parents.length)].length;; return new Genome(mass, strength, length); } public static Genome mutate(Genome parent) { // Select characteristics randomly Mass mass = Mass.values()[(int)(Math.random() * Mass.values().length)]; Strength strength = Strength.values()[(int)(Math.random() * Strength.values().length)]; Length length = Length.values()[(int)(Math.random() * Length.values().length)]; return new Genome(mass, strength, length); } public static void main() { PriorityQueue<Genome> population = new PriorityQueue<Genome>(); Genome parent1 = new Genome(Mass.LIGHT, Strength.STRONG, Length.SHORT); Genome parent2 = new Genome(Mass.AVERAGE, Strength.AVERAGE, Length.AVERAGE); Genome parent3 = new Genome(Mass.HEAVY, Strength.WEAK, Length.LONG); population.add(parent1); population.add(parent2); population.add(parent3); Genome child1 = Genome.recombine(parent1, parent2); Genome child2 = Genome.recombine(parent1, parent2); Genome child3 = Genome.recombine(parent1, parent3); Genome child4 = Genome.recombine(parent1, parent3); Genome child5 = Genome.recombine(parent2, parent3); Genome child6 = Genome.recombine(parent2, parent3); Genome child7 = Genome.recombine(parent1, parent2, parent3); Genome child8 = Genome.recombine(parent1, parent2, parent3); Genome child9 = Genome.recombine(parent1, parent2, parent3); child1 = Genome.mutate(child1); child2 = Genome.mutate(child2); child4 = Genome.mutate(child4); child8 = Genome.mutate(child8); population.add(child1); population.add(child2); population.add(child3); population.add(child4); population.add(child5); population.add(child6); population.add(child7); population.add(child8); population.add(child9); // and the winner is... Genome fittest = population.peek(); }}
编码
因为听起来你想要将特征编码成一个序列,其中一些特征在序列中是显式的,而另一些特征是从这些显式特征中派生的。
你可以通过将你的值范围(如上面的枚举)编码成一个整数来实现,其中块代表你的显式特征。
例如,如果你有两个显式特征,每个特征有四个可能的值,你可以将该集合编码为一个整数,形式为 00XX + XX00。 例如,0111 可能对应于质量 01 和长度 11。 这样做可以让你通过更改序列本身的位来进行突变。
Java 示例
import java.util.PriorityQueue;class Genome implements Comparable<Genome> { private final Integer sequence; private static final Integer bitmaskChunk = 3; // ...0011 private static final Integer shiftMass = 0; // ...00XX private static final Integer shiftLength = 2; // ...XX00 private static final Integer shiftModulus = 4; // ...0000 private Integer getMass() { return (sequence >>> shiftMass) & bitmaskChunk; } private Integer getLength() { return (sequence >>> shiftLength) & bitmaskChunk; } public Integer getStrength() { return getMass() * getLength(); } public Genome(Integer sequence) { this.sequence = sequence % (1 << Genome.shiftModulus); } private Integer fitness() { // Some performance measure return getStrength() * getLength() - getMass() * getMass(); } @Override public int compareTo(Genome that) { // notice the fitter is less in precedence if(this.fitness() > that.fitness()) return -1; else if(this.fitness() < that.fitness()) return 1; else // this.fitness() == that.fitness() return 0; } public static Genome recombine(Genome... parents) { if(parents.length < 1) return null; Integer sequence = 0; // Select parents randomly and then characteristics from them sequence += parents[(int)(Math.random() * parents.length)].getMass() << Genome.shiftMass; sequence += parents[(int)(Math.random() * parents.length)].getLength() << Genome.shiftLength; return new Genome(sequence); } public static Genome mutate(Genome parent) { Integer sequence = parent.sequence; // Randomly change sequence in some way sequence *= (int)(Math.random() * (1 << Genome.shiftModulus)); return new Genome(sequence); } public static void main() { PriorityQueue<Genome> population = new PriorityQueue<Genome>(); Genome parent1 = new Genome((int)(Math.random() * (1 << Genome.shiftModulus))); Genome parent2 = new Genome((int)(Math.random() * (1 << Genome.shiftModulus))); Genome parent3 = new Genome((int)(Math.random() * (1 << Genome.shiftModulus))); population.add(parent1); population.add(parent2); population.add(parent3); Genome child1 = Genome.recombine(parent1, parent2); Genome child2 = Genome.recombine(parent1, parent2); Genome child3 = Genome.recombine(parent1, parent3); Genome child4 = Genome.recombine(parent1, parent3); Genome child5 = Genome.recombine(parent2, parent3); Genome child6 = Genome.recombine(parent2, parent3); Genome child7 = Genome.recombine(parent1, parent2, parent3); Genome child8 = Genome.recombine(parent1, parent2, parent3); Genome child9 = Genome.recombine(parent1, parent2, parent3); child1 = Genome.mutate(child1); child2 = Genome.mutate(child2); child4 = Genome.mutate(child4); child8 = Genome.mutate(child8); population.add(child1); population.add(child2); population.add(child3); population.add(child4); population.add(child5); population.add(child6); population.add(child7); population.add(child8); population.add(child9); // and the winner is... Genome fittest = population.peek(); }}
我希望这就是你在寻找的东西。祝你好运。