编程语言
首页 > 编程语言> > 遗传算法-无序可变长度染色体-交叉策略?

遗传算法-无序可变长度染色体-交叉策略?

作者:互联网

我正在研究遗传算法.染色体无序-意味着它们在一个成员中出现的顺序不会影响该成员的得分.染色体的数目也不固定.一个成员可能有1条染色体,另一成员可能有100条以上.

我正在使用Python工作,并且染色体存储在列表中.下面是该结构的简化示例:

member = [{"key1":"value","key2":"value"},{"key1":"value","key2":"value"},{"key1":"value","key2":"value"}]

两个示例成员(简化)可能是:

member1 = [{"a":1.5,"b":2.334563},{"a":769.0003413,"b":0.00023}]
member2 = [{"a":7,"b":432.993246927},{"a":99,"b":532.234},{"a":21,"b":712.2},{"a":432,"b":999.9999},{"a":932,"b":12}]

在应用程序中重复出现乱序的染色体是可以的:

member3 = [{"a":1,"b":1},{"a":2,"b":2},{"a":2,"b":2},{"a":1,"b":1}]

会员

成员中的每个染色体都是一个数学函数,它以Unix epoc时间戳为输入并输出一个值.这使我可以随时使用该成员的函数获得“价值”.染色体中的关键点始终相同-但是在初始播种值从0到100的范围内会随机生成这些值,最多可保留100个小数位.

评分标准

我正在根据SQL数据库中的实时序列数据对功能进行分级.时间序列数据每1到3秒不断更新为新值.当我对此数据进行选择时,我选择epoc值大于当前epoc的位置-5秒并按降序排序,并将输出限制为1行.我获得了实际的epoc值,这是我评分的依据之一.

我取所有点(epoc:value对),并使用它们进行评分,为成员函数提供epoc,获取成员的值,然后从实际值中减去该值-并取其绝对值.

它看起来像这样:

total = 0
for chromosome in member[chromosomes]:
    for epoc in epocs:
        thisValue = Calc(epoc,chromosome)
        total = total + abs(thisValue - getRealValue(epoc))

函数Calc获取染色体和epoc值并输出一个浮点数.

零是一个完美的分数.分数越高,成员越差.我平均所有成员的得分,并删除低于平均水平的得分.

我尝试根据数据库中的一组静态数据进行分级,并且尝试根据过去24小时进行动态分级-这意味着随着时间的流逝,过去24小时始终是不同的.我还尝试了过去4个小时,过去1个小时和过去3天.

变异系统

我将突变率设置为2%,但我以较高的百分比进行了测试,但结果却更差.只有孩子有可能被突变,而不是现有人口(想保留精英).当选择一个孩子进行突变时,其染色体中的值会随机移位(随机地进行加法或减法)0到1之间的小数点(最多100个小数位).这对孩子的价值观产生了最小的改变-因为非常小的改变会极大地改变染色体功能的输出.

我的问题

我现在使用的交叉方法会导致过早收敛.

我尝试过的跨界策略

我尝试过从每个父母那里随机抽取随机染色体.我尝试过第一位父母的前半部分和第二位父母的后半部分.
到目前为止,我已经尝试了以下方法:

# Number of chromosomes from parent 1.
parent1chromosomes = randomNumber(0,len(parent1['chromosomes']))

# Number of chromosomes from parent 2.
parent2chromosomes = randomNumber(0,len(parent2['chromosomes']))

child = {}
child['chromosomes'] = []

# Get parent 1 chromosomes into child.
for i in range(0,parent1chromosomes):
    child['chromosomes'].append(random.choice(parent1['chromosomes']))

# Get parent 2 chromosomes into child.
for i in range(0,parent2chromosomes):
    child['chromosomes'].append(random.choice(parent2['chromosomes']))

注意:randomNumber是一个函数,它返回指定范围之间的随机整数.

两种尝试都会导致早期收敛.我要解决的问题非常复杂-到目前为止,我已经尝试了从10,000到1,000,000的人口规模.

表现范例

这是最近一次跑步的屏幕截图.我正在映射最佳分数(最低分数)和平均分数.在这张照片中,它绘制了五个不同人群的最佳成绩和平均值.这5个总体分别是10,000个成员,使用的是3秒钟的真实数据采样,并动态地对真实数据的最后一小时进行评分-这就是为什么最好的情况变得更糟的原因-因为对真实数据进行评分的方式发生了变化使最好的成员变得更糟.最好的分数减少了数千,这根本不准确.人口较少导致更快的早期收敛.

enter image description here

我的问题

还有什么其他方法可以更好地处理与可变长度成员发生的交叉,其中染色体的顺序无关紧要,重复的染色体也无关紧要?

解决方法:

而不是:

for i in range(0,parent1chromosomes):
    child['chromosomes'].append(random.choice(parent1['chromosomes']))

也许:

child['chromosomes'].extend(random.sample(parent1['chromosomes'], parent1chromosomes))

这意味着,如果您从一个父母那里获得了两条重复的染色体,或者从父母双方那里得到了一条拷贝,那么您只能获得重复的染色体.

标签:genetic-programming,genetic-algorithm,python,algorithm
来源: https://codeday.me/bug/20191025/1928068.html