【问题标题】:Genetic Algorithm stops mutating遗传算法停止变异
【发布时间】:2017-10-10 23:54:34
【问题描述】:

我目前正在尝试使我的遗传算法“生成”或“进化”到给定的单词。问题是,它永远不会完全达到这个词,它会停止在过高的适应度分数上,即使它应该继续变异。

举个例子:

用户输入 = “HelloWorld”
经过 500 代 = "XelgoWorfd"

而且我不知道为什么它不会继续变异。通常它应该通过随机更改字符串中的一些字符来恢复。

所以我很高兴能得到一些帮助。

这是一个基本的逐步解释:

  1. 使用完全随机的字符串创建 20 条染色体
  2. 计算与目标词相比的适应度得分。 (计算 Ascii id 差异)
  3. 将得分最高的两条染色体配对。
  4. 随机突变一些染色体(更改随机字符串字符)
  5. 杀死 90% 的弱种群并用精英染色体(当前适应度得分最高的染色体)替换它。
  6. 重复一切。

所以这里是我算法中最重要的方法:

public Chromoson[] mate(string gene) {
    Console.WriteLine("[MATING] In Progress : "+gens+" "+gene);

    int pivot = (int)Math.Round((double)gens.Length / 2) - 1;

    string child1 = this.gens.Substring(0, pivot) + gene.Substring(pivot);
    string child2 = gene.Substring(0, pivot) + this.gens.Substring(pivot);

    Chromoson[] list = new Chromoson[2];

    list[0] = new Chromoson(child1);
    list[1] = new Chromoson(child2);

    Console.WriteLine("[MATING] Pivot : "+pivot);
    Console.WriteLine("[MATING] Children : "+child1+" "+child2);

    return list;
}

public void mutate(float chance, int possiblyChanges) {
    if (random.Next(0,101) <= chance) return;

    int changes = random.Next(0, possiblyChanges + 1);
    //int index = (int) Math.Floor((double)random.Next() * this.gens.Length);

    for (int i = 0; i < changes; i++) {
        int index = random.Next(0, 13);
        StringBuilder builder = new StringBuilder(gens);
        int upOrDown = random.Next(0, 101);

        if (upOrDown <= 50 && (int)builder[index] > 0 && chars.Contains(Convert.ToChar(builder[index] - 1)))
            builder[index] = Convert.ToChar(builder[index] - 1);
        else if (upOrDown >= 50 && (int)builder[index] < 127 && chars.Contains(Convert.ToChar(builder[index] + 1)))
            builder[index] = Convert.ToChar(builder[index] + 1);
        else
            mutate(chance, possiblyChanges);

        gens = builder.ToString();
    }
    Console.WriteLine("[MUTATING] In Progress");
}

public void calculateCost(string otherGens)
{
    int total = 0;
    for (int i = 0; i < gens.Length; i++)
    {
        total += (((int)gens[i] - (int)otherGens[i]) * ((int)gens[i] - (int)otherGens[i])) * (i*i);
    }
    Console.WriteLine("[CALCULATING] Costs : " + total);
    this.cost = total;
}

【问题讨论】:

标签: c# algorithm genetic-algorithm


【解决方案1】:

在你的时间步里,有些事情已经完全消失了:

  1. 使用完全随机的字符串创建 20 条染色体。 看起来还可以。
  2. 计算与目标词相比的适应度得分。 (计算 Ascii ids 差异)。 看起来还可以。
  3. 将得分最高的两条染色体配对。 什么?你只培育了两条最适合的染色体来创造新的种群吗?这意味着您将拥有一个几乎完全相似的种群。 按比例繁殖,因此所有基因组都有机会产生后代
  4. 随机突变一些染色体(更改随机字符串字符)
  5. 杀死 90% 的弱种群并用精英染色体(当前适应度得分最高的染色体)替换它。 你杀了 90%?所以基本上,你每次迭代都保留 2 个最好的基因组,然后用第 1 步替换其他 18 个?您想要的是在第 3 步中保持 2 最适者,并通过繁殖创造其他 18 个人。
  6. 重复所有内容。

所以改变你的步骤:

初始化。初始化种群,创建 20 条随机染色体

  1. 计算每个染色体的分数
  2. 将最适合的两条染色体保存到下一个种群(也称为精英主义),通过按比例繁殖适应度来获得其他 18 个需要的个体
  3. 以一定的几率使染色体发生变异
  4. 重复

不要每轮创建随机个体。这会将您的算法变成随机搜索。

【讨论】:

  • 感谢 :D 帮助!
【解决方案2】:

您的 mutate 和 calculateCost 函数很奇怪。特别是, mutate() 看起来旨在陷入局部最小值。任何向上或向下的突变都会比精英更糟糕(它们可能是相同的,所以交叉不会改变任何东西)。使用不同的 mutate:选择一个随机索引并完全更改它。还要从 cost() 中删除 i*i。

【讨论】:

    猜你喜欢
    • 2011-06-11
    • 2012-03-27
    • 2015-03-01
    • 2015-06-08
    • 1970-01-01
    • 2012-09-23
    • 2011-03-10
    • 2014-12-21
    • 2019-02-08
    相关资源
    最近更新 更多