我正在编写一个遗传算法来寻找一个能够表达目标数值的表达式,例如,如果目标数值是10
,那么一个可能的解可以是2*5
。我遇到了整个种群变成一个相同染色体的情景,我认为这是由适应度函数引起的。
以下是一些可能的染色体,它们遵循数字和运算符在字符串中交替出现的规则,确保没有两个数字或两个运算符相邻。一个合法的字符串可以以数字或+/-
运算符开头。表达式将从左到右按原样计算(忽略算术运算的顺序):
1/2+3+5
-2+4+1+8
-7+6*2+8
+2/5-1+8 2+1*2-2
+2*7*7+3
+1/2/2/6 5/5*9*1
+3-1+1*8 3-8+7*1
选择函数(Selection()):
def selection(population): total_finesses = Decimal(0.0) # 轮盘选择法: for chromosome in population: total_finesses += chromosome .fitness # 生成随机数(旋转轮盘)。 pick = Decimal(random.uniform(0, float(total_finesses))) current = Decimal(0.0) for i, chrom in enumerate(population): current += chrom.fitness if current > pick: return population[i]
适应度函数(Fitness()):
def fitness_calculator(chromosome): current_value = get_value(chromosome) # 返回染色体的十进制值。 return Decimal(-1 * (abs(target - current_value), 5))
如您所见,适应度越接近0越好,因为我正在寻找与目标数值之间的差值最小的表达式。
我认为我的选择算法存在问题,无法在轮盘选择法中选择适应度最低的染色体。
回答:
我在计算机科学的StackExchange上回答了一个类似的问题,在这里,它以最佳方式解释了如何为您的问题找到一个好的选择方法。
然而,看起来您似乎没有实现变异,这对于维持种群的多样性是必要的;因此,您可能需要以某种方式实现它。可以在这里找到几种方法这里。
@[隐藏人名] 在您的问题评论中也提出了一些合理的观点。如果您的种群中有多个相同的解,这会造成问题,那么就不要允许这种情况发生。此外,随机选择通常不是一个好主意,常常会使评估函数失去作用。您的评估函数对种群中的解进行排名。使用它!有些方法说选择最好的解并使它们交配以使最好的解变得更好;另一些方法说选择最差的解以保持所有解都相当不错。除此之外,您还可以选择许多其他可能的选择方法。
我的最后一点是(虽然这可能不直接适用于您,但可能对最终进入此讨论的人有帮助),在研究遗传算法时,精细调整的初始种群大小往往被低估。确保您也尝试几种不同的变化。
阅读材料:
Miller, B. L., & Goldberg, D. E. (1995). Genetic algorithms, tournament selection, and the effects of noise. Complex Systems, 9(3), 193-212.
Goldberg, D. E., & Deb, K. (1991). A comparative analysis of selection schemes used in genetic algorithms. Urbana, 51, 61801-2996.
Poon, P. W., & Carter, J. N. (1995). Genetic algorithm crossover operators for ordering applications. Computers & Operations Research, 22(1), 135-147.