Python 如何将遗传编程算法训练到可变描述符序列上?
我目前正在尝试设计一种遗传编程算法,该算法分析字符序列,并为这些字符指定一个值。下面,我制作了一个示例集。每一行代表一个数据点。经过训练的值是实值的。 例子: 对于单词Python 如何将遗传编程算法训练到可变描述符序列上?,python,genetic-programming,Python,Genetic Programming,我目前正在尝试设计一种遗传编程算法,该算法分析字符序列,并为这些字符指定一个值。下面,我制作了一个示例集。每一行代表一个数据点。经过训练的值是实值的。 例子: 对于单词ABCDE算法应返回1.0 示例数据集: ABCDE:1 ABCDEF:10 ABCDEGH:3 ABCDELKA:50 AASD:3 数据集可以是所需的最大数据集,因为这一切都是虚构的。让我们假设GP应该理解的规则并不太复杂,并且它可以由数据来解释 当给定输入序列时,我希望该算法能够近似计算数据集中的值。我现在的问题是,每个序列
ABCDE
算法应返回1.0
示例数据集:
ABCDE:1
ABCDEF:10
ABCDEGH:3
ABCDELKA:50
AASD:3
数据集可以是所需的最大数据集,因为这一切都是虚构的。让我们假设GP应该理解的规则并不太复杂,并且它可以由数据来解释
当给定输入序列时,我希望该算法能够近似计算数据集中的值。我现在的问题是,每个序列可以由不同数量的字符组成。如果可能的话,我不想自己写一些花哨的描述词
如何训练我的GP(最好使用tinyGP
或python)来构建此模型?
因为这里有这么多的讨论——一张图表上写着千言万语:
我想做的就是把一个数据点放到一个函数中。然后我得到一个值,这是我的结果。不幸的是,我不知道这个函数,我只是有一个数据集,其中有一些示例(可能1000个示例只是一个示例)。现在,我使用遗传编程算法来找到一种能够将数据点转换为结果的算法。这是我的模型。在本例中,我遇到的问题是数据点的长度不同。对于设置的长度,我可以只指定字符串中的每个字符作为输入参数。但是,如果我有不同数量的输入参数,我就不知所措了
免责声明:在我的研究中,我已经多次遇到这个问题,但我们永远都无法找到一个解决方案(比如使用窗口、描述符等)。我想使用GP,因为我喜欢这项技术,并且想尝试一下,但在Uni期间,我们也用ANN等进行了尝试,但没有效果可变输入大小的问题仍然存在。传统的遗传编程不适合可变长度输入 我突然想到,这个问题中预设了某种评价模式 例如,考虑将可变长度输入编码为单个任意精度值,例如,对于10个符号的字母表:
ABCD = 1234; ABCDEF = 123456
或
然而,如果这种编码对于问题域来说不是自然的,那么很难发展出一个能够很好地处理这种输入的程序
您还可以假设,这个问题可以用遗传衍生的有限状态机来充分表示:
F(F(F(F(init(), A), B), C), D) = 1234
这是一个独立于基因编程的研究领域,谷歌搜索,阅读研究论文,也许你能找到一个能满足你需求的软件包
同样,你的问题也可以用另一种变换来表示,例如bigram的频率——这种变换是有限长度的:
# bigrams
# ABCDE => 1
"AA": 0
"AB": 0.25
"AC": 0
"AD": 0
"AE": 0
"BA": 0
"BC": 0.25
"BD": 0
#... up to end of alphabet ...
(0, 0.25, 0, 0, 0, 0, 0.25, 0, ...., 0, ...) => 1 # ABCDE
(0, 0.20, 0, 0, 0, 0, 0.20, 0, ...., 0.20, ...) => 10 # ABCDEF
# input length N^2
# trigrams
(0, 0.33, 0, 0, ..., 0, ...) => 1 # ABCDE
(0, 0.25, 0, 0, ..., 0.25, ...) => 10 # ABCDEF
# input length N^3
二元图、三元图等都是出人意料的好预测器:
- 捕获马尔可夫信息(“ab”与“ac”)
- 捕获相对位置(“ab”和“bc”与“ed”和“bc”)
- 捕捉非线性语义(“abab”!=“ab”*2)
- 抗混乱输入(“购买新垃圾邮件”vs“购买新垃圾邮件”)
10000+10000 = 20000
1000+100000 = 101000
在这种情况下,您需要注册机之类的设备:
init: tmp = 0; res = 0
"0": tmp *= 10
"1": tmp *= 10; tmp += 1
"+": res += tmp; tmp = 0
end: res += tmp
由于没有适应度函数,因此需要将遗传算法视为分类器。所以你需要想出一种方法来评估一条染色体。正如其他人所建议的,这是一个纯粹的分类问题,而不是优化问题,但是,如果您仍然想继续遗传算法,这里有一些步骤来尝试初始方法: 您将需要:
alphabet = "ABCDE"
chromosome1 = [1, 2, 3, 4, 5]
chromosome2 = [1, 1, 2, 1, 0]
alphabet = ["AB", "AC", "AD", "AE", "BC", "BD", "BE", "CD", "CE", "DE"]
chromosome = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
alphabet = ["ABC", "ABD", "ABE"...]
chromosome = as above, a value for each combination
BIGRAM
alphabet = "ABCDE"
chromosome1 = [1, 2, 3, 4, 5]
chromosome2 = [1, 1, 2, 1, 0]
alphabet = ["AB", "AC", "AD", "AE", "BC", "BD", "BE", "CD", "CE", "DE"]
chromosome = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
alphabet = ["ABC", "ABD", "ABE"...]
chromosome = as above, a value for each combination
三角图
alphabet = "ABCDE"
chromosome1 = [1, 2, 3, 4, 5]
chromosome2 = [1, 1, 2, 1, 0]
alphabet = ["AB", "AC", "AD", "AE", "BC", "BD", "BE", "CD", "CE", "DE"]
chromosome = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
alphabet = ["ABC", "ABD", "ABE"...]
chromosome = as above, a value for each combination
二,。
解码染色体以评估单个输入
染色体代表字母表中每个元素的整数值。所以,如果你想知道一个有染色体的输入值(可变长度字符串),你需要尝试一些求值函数,最简单的是每个字母值的总和
alphabet = "ABC"
chromosome = [1, 2, 1]
input = "ABBBC"
# acc = accumulated value
value = reduce(lambda acc, x: acc + chromosme[alphabet.index(x)], input, 0)
# Will return ABBBC = 1+2+2+2+1 = 8
三,。
健身功能
你的适应度函数只是一个简单的误差函数。你可以使用简单的误差和,平方误差。。。单代的简单评估函数:
def fitnessFunction(inputs, results, alphabet, chromosome):
error = 0
for i in range(len(inputs)):
value = reduce(lambda acc, x: acc + chromosome[alphabet.index(x)], inputs[i], 0)
diff = abs(results[i] - value)
error += diff # or diff**2 if you want squared error
return error
# A simple call -> INPUTS, EXPECTED RESULTS, ALPHABET, CURRENT CHROMOSOME
fitnessFunction(["ABC", "ABB", "ABBC"], [1,2,3], "ABC", [1, 1, 0])
# returned error will be:
# A+B+C = 1 + 1 + 0 -- expected value = 1 --> error += 1
# A+B+B = 1 + 1 + 1 -- expected value = 2 --> error += 1
# A+B+C = 1 + 1 + 1 + 0 -- expected value = 3 --> error += 0
# This chromosome has error of 2
现在,使用任何交叉和变异算子