使用DEAP库运行遗传编程代码时出现语法无效错误的求助
导入必要模块、定义算子、创建Fitness与Individual后,编写了如下评估函数与toolbox注册代码:
# Define the fitness function for evaluating candidate kernels def evaluate_kernel(individual): # Compile the kernel expression as a callable function kernel_func = gp.compile(individual, pset) # Train an SVM with the kernel function and compute its accuracy on the validation set svm = SVC(kernel=kernel_func) svm.fit(X_train, y_train) accuracy = svm.score(X_val, y_val) return accuracy, toolbox = base.Toolbox() toolbox.register("expr", gp.genHalfAndHalf, pset=pset, min_=1, max_=3) toolbox.register("individual", tools.initIterate, creator.Individual, toolbox.expr) toolbox.register("population", tools.initRepeat, list, toolbox.individual) toolbox.register("evaluate", evaluate_kernel) toolbox.register("mate", gp.cxOnePoint) toolbox.register("mutate", gp.mutUniform, pset=pset) toolbox.register("select", tools.selTournament, tournsize=3) # Define main function def main(): import numpy pop = toolbox.population(n=50) hof = tools.HallOfFame(1) stats = tools.Statistics(lambda ind: ind.fitness.values) stats.register("avg", numpy.mean) stats.register("min", numpy.min) stats.register("max", numpy.max) pop, logbook = algorithms.eaSimple(pop, toolbox, cxpb=0.5, mutpb=0.2, ngen=10, stats=stats, halloffame=hof, verbose=True) return pop, logbook, hof # Calling main function if __name__ == "__main__": pop, log, hof = main() print("Best individual is: %s\nwith fitness: %s" % (hof[0], hof[0].fitness)) print(pop)
运行时出现如下语法错误:
File "/usr/local/lib/python3.9/dist-packages/IPython/core/interactiveshell.py", line 3553, in run_code exec(code_obj, self.user_global_ns, self.user_ns) File "<ipython-input-26-9a5248fbca23>", line 2, in <cell line: 1> pop=main() 1 frames File "/usr/local/lib/python3.9/dist-packages/deap/algorithms.py", line 151, in eaSimple for ind, fit in zip(invalid_ind, fitnesses): File "<ipython-input-21-421003e68116>", line 4, in evaluate_kernel kernel_func = gp.compile(individual, pset) File "/usr/local/lib/python3.9/dist-packages/deap/gp.py", line 480, in compile return eval(code, pset.context, {}) File "<string>", line 1 lambda ARG0: [<deap.gp.Primitive object at 0x7ffa7a7cb540>, <deap.gp.Primitive object at 0x7ffa7a7cb900>, <deap.gp.Terminal object at 0x7ffa7b3aaa00>, <deap.gp.Terminal object at 0x7ffa7b3aaa00>] ^ SyntaxError: invalid syntax
这个错误的核心原因是你的Primitive(基元)没有正确定义可解析的字符串表示,导致gp.compile生成了无效的Python代码——从错误信息看,编译后的代码直接输出了Primitive对象的内存表示,而非合法的函数表达式。
要修复这个问题,需检查并修正pset(PrimitiveSet)的定义,确保所有基元都具备合法的字符串标识:
规范Primitive的定义
所有自定义Primitive必须指定一个可被Python解析的名称,示例如下:# 错误示例:未指定合法名称 pset.addPrimitive(my_custom_kernel, 2) # 正确示例:指定名称为合法Python标识符 pset.addPrimitive(my_custom_kernel, 2, name="custom_kernel")这里的
name参数会作为函数名出现在编译后的代码中,必须是有效的变量/函数名(不能包含空格、特殊字符)。确保Terminal(终端)的合法性
若使用自定义Terminal,同样要保证其字符串表示是合法的Python语法(如常数、变量名):# 添加常数终端,指定合法名称 pset.addTerminal(1.0, name="C1") # 重命名默认输入变量,提升可读性 pset.renameArguments(ARG0="x", ARG1="y")验证pset的正确性
在编译前可先打印个体的字符串表示,确认其为合法Python表达式:ind = toolbox.individual() print(str(ind)) # 正常输出应为类似"custom_kernel(x, C1)"的合法表达式若输出包含
<deap.gp.Primitive object...>这类内容,说明Primitive的定义存在问题,必须修正。额外注意SVM Kernel的要求
SVM的自定义kernel函数需接收两个样本矩阵(形状为(n_samples1, n_features)和(n_samples2, n_features)),并返回一个(n_samples1, n_samples2)的核矩阵。确保Primitive组合后的函数符合该要求,否则即使编译通过,后续SVM训练仍会报错。
完整的pset定义示例:
from deap import gp import numpy as np # 创建PrimitiveSet,指定输入变量数量 pset = gp.PrimitiveSet("MAIN", 2) # 重命名默认输入变量 pset.renameArguments(ARG0="x", ARG1="y") # 定义基础核函数 def linear_kernel(x, y): return x @ y.T def rbf_kernel(x, y): return np.exp(-0.1 * np.linalg.norm(x - y, axis=1)**2) # 添加Primitive并指定合法名称 pset.addPrimitive(linear_kernel, 2, name="linear") pset.addPrimitive(rbf_kernel, 2, name="rbf") # 添加常数终端 pset.addTerminal(0.1, name="gamma")
按上述方式定义后,gp.compile生成的代码会是合法的lambda表达式,不会再出现语法错误。
内容的提问来源于stack exchange,提问作者Shreya Swarnaker

