求助:用Julia Evolutionary.jl实现差分进化优化MLP遇阻
问题:使用Evolutionary.jl通过差分进化(DE)进化MLP种群失败
问题背景
本人是Julia新手,指定差分进化(DE)算法及多层感知器(MLP)初始种群后,尝试用DE进化MLP种群,但使用Evolutionary.jl包时持续失败。未找到Julia中DE进化MLP的相关示例,不清楚代码复用方式,请求技术帮助。
现有代码
1. 加载数据集
begin features = Iris.features(); slabels = Iris.labels(); classes = unique(slabels) # 数据集中的唯一类别 nclasses = length(classes) # 类别数量 d, n = size(features) # 数据集维度与样本量 end
2. 定义MLP模型
model = Chain(Dense(d, 15, relu), Dense(15, nclasses))
3. 重写initial_population生成MLP种群
begin import Evolutionary.initial_population function initial_population(method::M, individual::Chain; rng::Random.AbstractRNG=Random.default_rng(), kwargs...) where {M<:Evolutionary.AbstractOptimizer} θ, re = Flux.destructure(individual); [re(randn(rng, length(θ))) for i in 1:Evolutionary.population_size(method)] end end
4. 定义DE算法参数
algo2 = DE( populationSize=150, F=0.9, n=1, K=0.5*(1.9), selection = rouletteinv ) popu = initial_population(algo2, model)
5. optimize()函数调用问题
尝试多种optimize()调用方式均报错,不确定是否必须传入约束条件,也不清楚BoxConstraints上下界设置方法,用Nonconstraint也失败,示例代码如下:
cnst = BoxConstraints([0.5, 0.5], [2.0, 2.0]) res2 = Evolutionary.optimize(fitness,cnst,algo2,popu,opts)
已实现的辅助函数
交叉操作函数uniform_mlp
用于将MLP解构为向量、执行交叉后重构为新MLP:
function uniform_mlp(m1::T, m2::T; rng::Random.AbstractRNG=Random.default_rng()) where {T <: Chain} θ1, re1 = Flux.destructure(m1); θ2, re2 = Flux.destructure(m2); c1, c2 = UX(θ1,θ2; rng=rng) return re1(c1), re2(c2) end
变异操作函数gaussian_mlp
function gaussian_mlp(σ::Real = 1.0) vop = gaussian(σ) function mutation(recombinant::T; rng::Random.AbstractRNG=Random.default_rng()) where{T <: Chain} θ, re = Flux.destructure(recombinant) return re(convert(Vector{Float32}, vop(θ; rng=rng))) end return mutation end
核心问题点
- 不清楚
Evolutionary.optimize()的正确调用方式,是否必须传入约束条件? - 若需约束,
BoxConstraints的上下界应如何匹配MLP参数维度? - 如何让DE算法正确适配MLP个体的交叉、变异操作?
解决思路
约束条件的正确设置
- 若无约束需求,直接使用
Evolutionary.NoConstraints()而非错误的Nonconstraint。 - 若使用
BoxConstraints,上下界向量长度必须与MLP解构后的参数向量长度一致。可通过length(Flux.destructure(model)[1])获取参数总数,再生成对应长度的上下界数组(例如统一设为-10到10)。
- 若无约束需求,直接使用
适配DE算法的个体操作
- Evolutionary.jl的DE算法默认针对数值向量,而你使用的是
Chain类型个体,需重写DE的变异、交叉操作适配MLP:# 重写变异方法 import Evolutionary.mutate! function Evolutionary.mutate!(method::DE, target::Chain, pop::Vector{Chain}, rng::Random.AbstractRNG) mutate_op = gaussian_mlp(0.5) return mutate_op(target) end # 重写交叉方法 import Evolutionary.crossover! function Evolutionary.crossover!(method::DE, target::Chain, mutant::Chain, rng::Random.AbstractRNG) child, _ = uniform_mlp(target, mutant; rng=rng) return child end
- Evolutionary.jl的DE算法默认针对数值向量,而你使用的是
optimize()的正确调用- 正确调用格式示例:
opts = Evolutionary.Options(iterations=100, show_trace=true) res2 = Evolutionary.optimize(fitness, Evolutionary.NoConstraints(), algo2, popu, opts) - 注意
fitness函数必须接受Chain类型参数,返回标量适应度值(如分类误差的倒数或负误差)。
- 正确调用格式示例:
参数类型一致性检查
- 变异函数中把参数转为
Float32,但初始种群由randn生成Float64类型,建议统一类型(比如初始种群用randn(Float32, ...)),避免类型不稳定导致的错误。
- 变异函数中把参数转为
内容的提问来源于stack exchange,提问作者Meimei_Huang
相关产品推荐
相关产品推荐

