R语言遗传算法:如何指定二进制染色体中1的数量
如何在R语言遗传算法中指定二进制染色体中1的数量?
我正在使用rbga函数(该问题同样适用于R语言中其他遗传算法实现方案),想知道是否可以指定二进制染色体中1的数量。
示例代码
data(iris) library(MASS) X <- as.data.frame(cbind(scale(iris[,1:4]), matrix(rnorm(36*150), 150, 36))) Y <- iris[,5] iris.evaluate <- function(indices) { print("Chromosome") print(indices) print("=================================") result = 1 if (sum(indices) > 2) { huhn <- lda(X[,indices==1], Y, CV=TRUE)$posterior result = sum(Y != dimnames(huhn)[[2]][apply(huhn, 1, function(x) which(x == max(x)))]) / length(Y) } result } monitor <- function(obj) { minEval = min(obj$evaluations); plot(obj, type="hist"); } woppa <- rbga.bin(size=40, mutationChance=0.05, zeroToOneRatio=10, evalFunc=iris.evaluate, showSettings=TRUE, verbose=TRUE)
部分染色体示例
"Chromosome" 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 "=================================" "Chromosome" 0 0 1 1 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 1 0 0 0 0 0 1 0 0 0 "=================================" "Chromosome" 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 "=================================" "Chromosome" 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 "================================="
上述染色体中1的数量(即选中的特征数)分别为5、8、5和4。
我需要遵循某论文中的技术要求,应用遗传算法后需选取特定数量的特征,因此有两个问题:
- 是否可以在遗传算法中指定解/染色体所需的特征数量?
- 是否可以在最终解/染色体上实现该需求?若可以,具体如何操作?
问题1:在遗传算法运行中指定特征数量
可以通过两种核心方式实现约束:
方法1:修改适应度评估函数,添加惩罚机制
对不符合目标特征数量的染色体施加极高惩罚,让这类染色体在选择过程中被快速淘汰。比如你需要固定选择5个特征,可以修改评估函数如下:
iris.evaluate <- function(indices) { target_k <- 5 # 你需要的固定特征数量 # 对不符合数量要求的染色体直接返回最差适应度(这里是最大错误率) if (sum(indices) != target_k) { return(1) } # 原有的评估逻辑 huhn <- lda(X[,indices==1], Y, CV=TRUE)$posterior result = sum(Y != dimnames(huhn)[[2]][apply(huhn, 1, function(x) which(x == max(x)))]) / length(Y) result }
这种方法简单直接,不需要修改遗传算法的核心逻辑,适合rbga.bin这类参数较少的实现。
方法2:自定义遗传操作(交叉/变异)
如果需要更严格的约束,可以重写交叉和变异函数,确保生成的新染色体始终满足1的数量要求:
- 交叉操作:只交换两个染色体中相同位置的0和1,或者交换固定数量的1的位置,保证交叉后1的总数不变。
- 变异操作:每次变异时,必须将一个0转为1的同时,把另一个1转为0,保持总数恒定。
不过rbga.bin本身没有开放自定义交叉、变异的参数,你可能需要切换到更灵活的遗传算法包(如GA包),或者直接修改genalg包的源码实现。
问题2:在最终解上实现特征数量约束
如果不在算法运行过程中约束,也可以在得到遗传算法的结果后进行处理:
方法1:筛选种群中符合数量要求的最优解
运行完遗传算法后,从所有迭代产生的种群个体中,筛选出1的数量符合要求的个体,再从中选择适应度最优的:
target_k <- 5 # 从种群中筛选出特征数量符合要求的个体 valid_pop <- woppa$population[apply(woppa$population, 1, sum) == target_k, ] # 对应筛选出的个体的适应度值 valid_evals <- woppa$evaluations[apply(woppa$population, 1, sum) == target_k] # 找到适应度最优的个体(这里错误率最小) if (length(valid_evals) > 0) { best_valid_idx <- which.min(valid_evals) best_valid_chromosome <- valid_pop[best_valid_idx, ] print("符合数量要求的最优染色体:") print(best_valid_chromosome) } else { print("种群中没有符合数量要求的个体,请调整算法参数或运行次数") }
方法2:调整最优解的特征数量
如果种群中没有完全符合要求的个体,可以对最优解进行微调:
- 如果最优解的1的数量多于目标值:随机去掉多余的1;
- 如果少于目标值:随机添加缺少的1。
但这种方法可能会降低解的最优性,仅适合对精度要求不高的场景。
内容的提问来源于stack exchange,提问作者vic
相关产品推荐
相关产品推荐

