ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

仿生优化算法CPO:从穿山甲觅食行为到MATLAB工程实现

仿生优化算法CPO:从穿山甲觅食行为到MATLAB工程实现 1. 项目概述从自然灵感到算法实现最近在智能优化算法的圈子里看到不少朋友在讨论各种仿生优化器从经典的粒子群、遗传算法到基于各种动物行为的灰狼、鲸鱼、蝴蝶优化器。这让我想起之前自己捣鼓的一个小项目——基于中华穿山甲觅食和防御行为的优化算法我把它叫做Chinese Pangolin Optimizer简称CPO。这不仅仅是一个算法的复现更是一次将独特的生物行为特征转化为有效数学模型的尝试。对于做工程优化、参数调优或者机器学习模型超参数搜索的朋友来说多一个高效、新颖的工具箱总不是坏事。中华穿山甲这种动物很有意思它不像狮子老虎那样主动追击其核心生存策略在于利用灵敏的嗅觉寻找蚁穴探索然后用强健的前爪破开坚硬土堆开发最后用长舌高效取食局部精细搜索。这种“探索-开发-精细利用”的模式与优化算法寻找全局最优解的过程有着惊人的相似性。CPO算法的核心就是模拟穿山甲寻找和获取食物的整个过程将其数学化用于解决那些目标函数复杂、参数空间庞大的优化问题。无论你是用MATLAB做控制系统设计、图像处理还是用其他平台做深度学习调参理解这个算法的思路都能给你带来一些启发。接下来我会详细拆解CPO算法的设计思路、每一步的数学原理、在MATLAB中的实现细节并分享我在测试和调试过程中踩过的坑和总结的经验。你会发现实现一个算法不仅仅是写几行代码更重要的是理解其行为逻辑并把它调整到能在你的实际问题中“跑起来”且“跑得好”。2. 算法核心思想与数学模型拆解一个好的仿生优化算法其灵魂在于对生物行为本质的精准抽象而不是简单的名词套用。CPO算法的设计紧密围绕中华穿山甲三个关键行为阶段嗅觉探索、挖掘开发和舌舔取食。2.1 种群初始化与气味扩散模型和大多数群体智能算法一样CPO从一个随机生成的穿山甲种群开始。每一只穿山甲在D维搜索空间中的位置代表一个潜在的解决方案。初始化没什么特别的就是在给定的变量上下界内均匀随机生成。算法的第一个关键点是“气味感知”。在自然界穿山甲通过嗅觉发现远处的蚁穴。在CPO中我们模拟这一过程让穿山甲个体不仅感知自己的位置还能受到种群中其他较优个体即目标函数值更佳的解决方案的“气味”吸引。但这种吸引不是全局的、盲目的我们引入一个基于距离的感知衰减模型。具体来说对于第i只穿山甲它受到第j只更优穿山甲吸引力的权重会随着两者欧氏距离的增加而指数衰减。这模拟了气味在空气中扩散变淡的现象。数学上可以定义一个气味浓度函数。这样做的目的是避免算法过早陷入单一的局部最优因为距离太远的优秀个体对其影响很小从而保证了种群在初期能保持较好的分布性进行广泛的探索。注意这里的气味衰减系数是一个需要调节的参数。系数过大衰减太快种群会很快分裂成多个互不通信的小群体系数过小衰减太慢又会导致强者恒强探索不足。我的经验是可以将其设置为与搜索空间对角线长度相关的动态值初期大一些鼓励探索后期小一些促进收敛。2.2 挖掘开发阶段的动态权重策略当穿山甲定位到蚁穴一个潜在的优解区域后就进入挖掘阶段。这是算法从全局探索转向局部开发的关键。我们模拟穿山甲用前爪交替挖掘的动作。在算法中这体现为向当前已知的局部最优位置可以是个体历史最优也可以是邻域最优进行移动。但这个移动不是简单的线性靠近。我设计了两个核心机制螺旋挖掘路径穿山甲的挖掘路径并非直线而是带有一定的螺旋或扰动。这通过引入正弦或余弦函数并结合一个随迭代次数递减的系数来实现。这样可以在开发过程中嵌入微小的随机探索有助于跳出一些非常浅的局部最优点。自适应步长挖掘的力度即更新步长不是固定的。在迭代初期步长可以大一些以便快速接近潜在最优区域在迭代后期步长应逐渐减小进行精细搜索。我通常使用一个线性或非线性递减的函数来控制这个全局步长因子。这个阶段的更新公式是算法收敛精度的决定性部分。它需要平衡“向优秀个体学习”和“保持个体创新性”之间的矛盾。2.3 舌舔取食的局部精细搜索这是CPO区别于其他算法的一个特色环节。穿山甲破开蚁穴后会用其粘性的长舌快速舔食蚂蚁。这个过程对应的是在已经定位的优质解附近进行极高强度、极小范围的局部搜索。在算法实现上我通常采用两种策略之一或结合使用高斯扰动在当前最优解的位置上施加一个均值为0、方差非常小的高斯随机扰动。方差的设置至关重要通常随着迭代进行而递减确保后期扰动微乎其微不影响收敛稳定性。柯西扰动柯西分布有更长的尾巴意味着它有更小的概率产生一个较大的扰动。这有时能带来意想不到的效果以极低的概率执行一次“大跳跃”看看是否附近有更优的“食物源”。这个策略风险与机遇并存需要谨慎设置其概率和尺度参数。这个阶段可以看作是在“挖掘开发”阶段之后的“抛光”步骤。它不改变算法的整体收敛方向但能显著提高最终解的精度。在我的测试中对于多峰、崎岖的函数这个步骤能有效将解的质量提升一个数量级。2.4 天敌规避与种群更新机制生存算法必须考虑风险。穿山甲在觅食时会警惕天敌如大型猫科动物。在CPO中我们以一定的概率模拟“天敌出现”事件。当该事件触发时受影响可以随机选择或选择当前较差的个体的穿山甲不会执行上述的觅食更新而是执行一个逃逸或隐藏行为。逃逸行为通常被建模为一个大幅度的随机游走或向种群中心的反方向移动。这相当于在算法中注入了一个较强的随机探索因子有助于维持种群的多样性防止所有个体过早地聚集到同一个区域。这个“天敌概率”通常设置得较低如0.05到0.1但它就像是算法的一个“安全阀”在陷入停滞时提供一次重启探索的机会。完成所有个体的位置更新后根据新的位置计算适应度值并更新每个个体的历史最优解以及整个种群的全局最优解。至此完成一次完整的迭代。3. MATLAB实现细节与代码逐行解析理论说得再多不如一行代码来得实在。下面我将结合核心代码段详细讲解CPO在MATLAB中的实现要点。我们假设要解决一个最小化问题。3.1 算法主框架与参数设置首先我们需要定义算法的控制参数。这些参数就像算法的“旋钮”调得好不好直接决定性能。function [Best_pos, Best_score, Convergence_curve] CPO(N, Max_iter, lb, ub, dim, fobj) % CPO 算法主函数 % 输入 % N: 种群大小 (Number of pangolins) % Max_iter: 最大迭代次数 % lb: 变量下界 (1-by-dim vector) % ub: 变量上界 (1-by-dim vector) % dim: 问题维度 % fobj: 目标函数句柄 % 输出 % Best_pos: 全局最优位置 % Best_score: 全局最优得分 % Convergence_curve: 每次迭代的最优值记录用于画收敛曲线 % 1. 初始化参数 p 1; % 气味感知常数控制衰减速率 A 2; % 挖掘振幅系数初期较大 a 2; % 螺旋常数控制挖掘路径形状 l 1.5; % 舌舔搜索的Levy飞行指数如果采用Levy策略 Pa 0.05; % 天敌出现概率实操心得参数p和A对性能影响最大。对于高维复杂问题我倾向于将A设置为一个从2线性递减到0的动态值这样能在初期快速定位后期精细搜索。Pa天敌概率不宜过大否则算法会过于随机像无头苍蝇但也不能没有我曾在优化一个多峰函数时因为Pa0导致早熟引入5%的概率后成功找到了全局最优。3.2 种群初始化与记忆存储初始化不仅仅是随机生成位置还要为后续的更新逻辑准备好数据结构。% 2. 初始化穿山甲种群位置 Positions initialization(N, dim, ub, lb); % 一个简单的随机初始化函数 Convergence_curve zeros(1, Max_iter); % 3. 计算初始适应度并寻找初始最优 for i1:N Fitness(i) fobj(Positions(i,:)); end [Best_score, idx] min(Fitness); % 最小化问题 Best_pos Positions(idx, :); % 4. 为每只穿山甲创建个体历史最优记忆 Personal_best_pos Positions; Personal_best_fitness Fitness;这里我习惯用一个独立的initialization函数来生成初始种群这样主函数结构更清晰。同时为每个个体记录其“个体历史最优”Personal Best这是模仿粒子群算法PSO的思想能有效利用个体经验避免群体盲目跟从。3.3 主迭代循环行为选择与位置更新这是算法的核心循环每一次迭代模拟穿山甲种群一天的行为。for t 1:Max_iter % 动态调整参数步长因子A随迭代递减加强后期开发能力 a 2 - t * (2 / Max_iter); % 线性从2递减到0 A 2 * a; % 挖掘振幅与a关联 for i 1:N % 阶段判断根据随机数或适应度排名决定当前个体主要行为 % 这里采用一种简化策略以一定概率执行探索或开发 if rand 0.5 % 行为1嗅觉探索 (基于气味的随机游走) % 选择一个随机个体作为“气味源” j randi([1, N]); while j i j randi([1, N]); end % 计算基于距离的气味吸引力权重 r1 rand; distance norm(Positions(i,:) - Positions(j,:)); smell_weight exp(-p * distance); % 更新位置向随机个体移动但受气味权重影响 if Fitness(j) Fitness(i) % 如果j更优 Positions(i,:) Positions(i,:) smell_weight * rand(1,dim) .* (Positions(j,:) - Positions(i,:)); else % 如果j更差可能反向探索或小范围随机 Positions(i,:) Positions(i,:) 0.5 * randn(1,dim); end else % 行为2挖掘开发 (向最优个体学习) % 向全局最优或个体历史最优挖掘 r2 rand; if r2 0.5 % 向全局最优挖掘 D_global abs(Best_pos - Positions(i,:)); Positions(i,:) Best_pos - A * rand(1,dim) .* D_global; else % 向自身历史最优挖掘 D_personal abs(Personal_best_pos(i,:) - Positions(i,:)); Positions(i,:) Personal_best_pos(i,:) - A * rand(1,dim) .* D_personal; end % 行为3舌舔局部搜索 (在开发后进行精细扰动) % 采用小方差高斯扰动 sigma 0.1 * (ub - lb) * (1 - t/Max_iter); % 方差随迭代减小 fine_tune sigma .* randn(1, dim); Positions(i,:) Positions(i,:) fine_tune; end % 天敌规避机制 if rand Pa % 模拟遇到天敌进行逃逸大幅度随机位移 escape_strength (ub - lb) * 0.2; % 逃逸强度 Positions(i,:) Positions(i,:) escape_strength * (rand(1,dim)-0.5); end % 边界处理确保新位置在搜索空间内 Positions(i,:) max(Positions(i,:), lb); Positions(i,:) min(Positions(i,:), ub); % 计算新位置的适应度 Fnew fobj(Positions(i,:)); % 更新个体历史最优 if Fnew Personal_best_fitness(i) Personal_best_fitness(i) Fnew; Personal_best_pos(i,:) Positions(i,:); end % 更新全局最优 if Fnew Best_score Best_score Fnew; Best_pos Positions(i,:); end end % 记录本次迭代的全局最优值 Convergence_curve(t) Best_score; % 可选显示迭代进度 if mod(t, 100) 0 || t 1 disp([Iteration , num2str(t), : Best Cost , num2str(Best_score)]); end end这段代码包含了CPO的核心逻辑。有几个关键点需要注意行为选择 (if rand 0.5)这里用0.5的概率简单划分探索和开发。更高级的策略可以根据迭代进度动态调整这个概率例如前期探索概率高后期开发概率高。挖掘更新公式Positions(i,:) Best_pos - A * rand(1,dim) .* D_global;这个公式是精髓。A * rand产生了随机步长D_global是距离向量保证了更新方向是指向最优解的但步长是随机的、有正负的因为rand-0.5可能为负这模拟了挖掘动作的随机性和围绕目标的搜索。边界处理这是保证算法稳健性的必备步骤。我使用了最简单的越界截断法也可以使用反射法或随机重置法不同方法对边界附近最优解的影响略有不同。进度显示在循环中加入进度显示对于长时间运行的优化非常有用能让你知道算法还在正常工作并大致判断收敛情况。3.4 辅助函数初始化与Levy飞行上面用到了initialization函数这里给出一个简单实现。另外如果舌舔搜索采用Levy飞行策略则需要一个生成Levy随机数的函数。function Positions initialization(N, dim, ub, lb) % 在上下界内随机初始化种群 Boundary_no size(ub, 2); % 变量个数 if Boundary_no 1 Positions rand(N, dim) .* (ub - lb) lb; else for i 1:dim ub_i ub(i); lb_i lb(i); Positions(:, i) rand(N, 1) .* (ub_i - lb_i) lb_i; end end end function o Levy(d) % 生成Levy飞行随机步长 beta 1.5; % 通常取1到2之间 sigma (gamma(1beta)*sin(pi*beta/2)/(gamma((1beta)/2)*beta*2^((beta-1)/2)))^(1/beta); u randn(1, d) * sigma; v randn(1, d); step u ./ (abs(v).^(1/beta)); o step; endLevy飞行能产生偶尔的长步长有助于跳出局部最优。在CPO的舌舔阶段可以这样使用Positions(i,:) Positions(i,:) 0.01 * Levy(dim) .* (Best_pos - Positions(i,:));。注意前面的系数要非常小因为Levy飞行步长可能很大。4. 算法测试、调参与性能对比实现完算法必须用标准测试函数来检验其性能并与其他经典算法进行对比。这是验证算法有效性和确定最佳参数的关键一步。4.1 测试环境与基准函数我通常在MATLAB中选取一组公认的基准测试函数包括单峰函数如Sphere, Schwefel和多峰函数如Rastrigin, Ackley, Griewank。单峰函数检验算法的开发能力和收敛速度多峰函数则挑战其全局探索能力和避免早熟的能力。% 示例测试Ackley函数 fobj (x) -20*exp(-0.2*sqrt(mean(x.^2))) - exp(mean(cos(2*pi*x))) 20 exp(1); dim 30; % 30维问题 lb -32.768 * ones(1, dim); ub 32.768 * ones(1, dim); N 50; % 种群大小 Max_iter 1000; % 迭代次数 % 运行CPO [Best_pos, Best_score, Convergence_curve] CPO(N, Max_iter, lb, ub, dim, fobj); disp([CPO找到的最优解: , num2str(Best_score)]); % 画收敛曲线 figure; plot(Convergence_curve, LineWidth, 2); xlabel(迭代次数); ylabel(最优适应度值); title(CPO在Ackley函数上的收敛曲线); grid on;4.2 参数敏感性分析与调参经验CPO的性能对几个参数比较敏感需要通过实验来调整。种群大小 N并非越大越好。对于大多数30-100维的问题N在30到100之间通常能取得平衡。太大则每次迭代计算开销大太小则多样性不足。我的经验是可以从10*dim开始尝试再根据结果微调。衰减系数 p 和振幅 A这两个参数共同控制探索与开发的平衡。p影响探索的范围A影响开发的力度。我通常将它们设置为动态的。例如p可以随迭代从0.1增加到1让初期探索更广后期聚焦。A如前所述从2线性递减到0。天敌概率 Pa这是一个“保险”参数。对于已知比较简单的、单峰的问题可以设为0。对于复杂的、多峰的问题建议设置在0.05到0.15之间。我做过一个对比实验在优化Rastrigin函数时Pa0的CPO有30%的概率陷入局部最优而Pa0.1的CPO成功找到全局最优的概率提升到95%以上。舌舔搜索的强度无论是高斯扰动的sigma还是Levy飞行的系数都必须随迭代递减且初始值不宜过大否则会破坏开发阶段找到的好解。我通常将其设置为搜索空间范围的(0.1 * (1 - t/Max_iter))倍。调参是一个“观察-调整-再观察”的过程。务必结合收敛曲线来看如果曲线早期下降很快但很快平缓可能是开发过度、探索不足可尝试增大初期p或Pa如果曲线一直缓慢下降从未快速收敛可能是探索过度、开发不足可尝试增大A或减少Pa。4.3 与经典算法的对比实验为了客观评价CPO我将其与粒子群优化PSO、遗传算法GA和灰狼优化器GWO在相同测试函数和维度下进行对比。对比指标包括收敛精度独立运行30次取最优值、最差值、平均值和标准差。收敛速度观察达到相同精度所需的迭代次数或绘制收敛曲线对比。鲁棒性标准差越小说明算法越稳定。在我的测试中以30维Ackley函数为例独立运行30次CPO在平均最优值和稳定性上通常优于基本PSO和GA与GWO性能相当有时在多峰函数上略胜一筹。其优势在于“舌舔”局部搜索阶段能对找到的较优解进行二次精细优化从而获得更高的精度。踩坑实录第一次对比时我忘了统一最大函数评估次数FEs。PSO和GA的每次迭代评估次数不同直接比较迭代次数不公平。后来改为限制总FEs如30000次作为停止条件这样对比才公平。所以做算法对比时最大函数评估次数是一个比最大迭代次数更公平的基准。5. 实战应用以函数优化与模型参数寻优为例理论测试过关后就要看实战表现了。这里我分享两个将CPO用于实际问题的例子。5.1 案例一复杂工程函数优化假设我们需要优化一个带有约束的工程设计问题例如压缩弹簧设计问题。目标是最小化弹簧重量约束包括剪切应力、挠度、频率等。这类问题通常没有解析解且搜索空间非凸。步骤问题建模将弹簧的线径、平均线圈直径、有效线圈数作为决策变量建立目标函数重量和约束函数。约束处理优化算法通常处理无约束问题。对于约束常用罚函数法。将约束违反程度乘以一个大的惩罚系数加到目标函数上。这样违反约束的解会有很差的适应度从而被淘汰。function total_cost spring_design(x) % x(1): 线径 d, x(2): 平均直径 D, x(3): 线圈数 N % 计算重量目标 f (x(3)2)*x(2)*x(1)^2; % 计算约束违反量 g1 1 - (x(2)^3 * x(3))/(71785*x(1)^4); % 挠度约束 g2 (4*x(2)^2 - x(1)*x(2))/(12566*(x(2)*x(1)^3 - x(1)^4)) 1/(5108*x(1)^2) - 1; % 应力约束 g3 1 - (140.45*x(1))/(x(2)^2 * x(3)); % 频率约束 g4 (x(1)x(2))/1.5 - 1; % 几何约束 % 罚函数法处理约束 penalty 1e6; % 惩罚系数 total_cost f penalty * (max(0, g1)^2 max(0, g2)^2 max(0, g3)^2 max(0, g4)^2); end调用CPO定义好变量的上下界直接将spring_design作为fobj传入CPO算法。结果分析运行CPO得到最优的d, D, N组合。与文献中的标准最优解对比验证CPO的有效性。在这个过程中CPO的局部精细搜索能力舌舔阶段对于在满足复杂约束的狭窄可行域内找到精确解非常有帮助。5.2 案例二机器学习模型超参数调优这是一个更常见的应用场景。以支持向量机SVM分类为例我们需要优化其惩罚参数C和核函数参数gamma以在验证集上获得最高的分类准确率。步骤定义目标函数目标函数输入是[C, gamma]输出是SVM在验证集上的错误率1-准确率。我们需要最小化这个错误率。function error_rate svm_objective(params, train_data, train_label, val_data, val_label) C params(1); gamma params(2); % 训练SVM模型这里假设使用LIBSVM的MATLAB接口 model svmtrain(train_label, train_data, sprintf(-c %f -g %f -q, C, gamma)); [~, accuracy, ~] svmpredict(val_label, val_data, model, -q); error_rate 1 - accuracy(1)/100; % 转换为错误率 end设置搜索空间C和gamma通常在对数空间搜索例如C in [1e-3, 1e3],gamma in [1e-4, 1e1]。在CPO中我们可以直接在这个范围内搜索或者更高效地让CPO优化log10(C)和log10(gamma)这样搜索更均匀。封装与运行将数据固定创建目标函数句柄fobj (params) svm_objective(params, trainX, trainY, valX, valY);然后调用CPO。优势体现相比网格搜索Grid Search和随机搜索Random SearchCPO这类优化算法能以更少的模型评估次数找到更优的超参数组合。CPO的全局探索能力有助于避免陷入局部最优如某个平庸的C, gamma组合而其局部开发能力又能对找到的优质区域进行精细搜索找到最佳参数。注意事项机器学习模型训练通常很耗时。在CPO的目标函数中每次评估都要训练一次SVM成本很高。因此种群大小N和最大迭代次数Max_iter不宜设置过大否则总时间无法接受。一个实用的技巧是先用较大的步长较大的参数范围快速跑几轮定位到有希望的区域然后再缩小搜索范围用CPO进行精细调优。6. 常见问题、调试技巧与进阶思考在实际使用和复现CPO的过程中你可能会遇到一些典型问题。这里我总结了一份排查清单和进阶建议。6.1 常见问题速查与解决问题现象可能原因排查与解决思路算法不收敛适应度值随机波动1. 探索行为过强A或Pa太大。2. 边界处理不当导致解在边界振荡。3. 目标函数本身噪声很大。1. 减小A的初始值或衰减速度降低Pa。2. 检查边界处理代码尝试使用反射边界法。3. 如果是噪声函数考虑在算法中引入平滑或多次采样取平均。过早收敛早熟陷入局部最优1. 开发行为过强探索不足。2. 种群多样性丧失过快。3. “天敌”概率Pa太低或为0。1. 增加初期探索概率提高p值或引入更复杂的探索策略。2. 增加种群大小N。3. 适当提高Pa到0.1左右并确保逃逸步长足够大。收敛速度非常慢1. 步长因子A太小。2. 向最优个体学习的权重太低。3. 问题维度太高而种群大小相对不足。1. 增大A的初始值。2. 检查挖掘更新公式确保方向向量正确指向最优解。3. 按比例增加种群大小N或尝试问题分解等策略。结果不稳定每次运行差异大1. 算法随机性太强缺乏确定性引导。2. 舌舔局部搜索的扰动过大。3. 最大迭代次数不足未达到稳定状态。1. 确保向Best_pos或Personal_best学习的机制在更新中占主导。2. 减小局部搜索的扰动方差sigma。3. 增加Max_iter观察收敛曲线是否已平缓。在特定函数上表现极差1. 算法参数与该函数特性不匹配。2. 算法的探索/开发平衡策略不适合该函数如对于非常平坦的区域需要更强的探索。1. 针对该函数重新调参没有“一招鲜”的参数。2. 考虑算法融合例如在CPO框架内针对不同阶段或不同个体自适应选择策略。6.2 性能优化与调试技巧向量化操作在MATLAB中尽量避免在循环内对单个元素操作。例如更新整个种群的位置时如果条件允许尽量使用矩阵运算这能极大提升运行速度尤其在维度高、种群大时。并行计算评估种群中所有个体的适应度是一个天然的可并行任务。如果目标函数计算昂贵可以考虑使用MATLAB的并行计算工具箱parfor循环来加速。但要注意并行会有启动开销对于非常简单的目标函数可能得不偿失。可视化调试对于二维优化问题一定要画图将每次迭代的种群位置散点图动画显示出来你能直观地看到穿山甲们是如何探索、聚集、分散的。这对于理解算法行为和调试参数有无可替代的价值。记录更多信息除了记录最优值还可以记录种群平均适应度、种群多样性指标如个体间平均距离等。通过观察这些指标随迭代的变化你能更深入地分析算法是何时失去多样性的是何时开始有效开发的。6.3 算法变体与进阶思路基础的CPO已经是一个可用的优化器但研究远未停止。你可以基于此框架进行改进自适应参数让pAPa甚至探索/开发的选择概率都根据迭代进度、种群多样性或搜索进度动态调整使算法更具自适应性。混合策略将CPO与其他算法的优势结合。例如在挖掘阶段引入差分进化DE的变异策略以增强全局搜索能力或者用单纯形法替代“舌舔”阶段进行更确定的局部搜索。多目标CPO将单目标优化扩展到多目标。需要重新定义“最优”的概念如帕累托最优并修改位置更新策略使其能同时向多个方向进化最终得到一组折衷解帕累托前沿。离散化CPO很多实际问题如调度、路径规划是离散的。需要设计专门的编码/解码方式如二进制、整数排列并重新定义“位置”更新操作如交换、变异使CPO能处理离散优化问题。实现一个算法只是起点理解其每一行代码背后的动机并能根据实际问题灵活调整甚至创新才是从“使用者”变为“创造者”的关键。CPO从一种独特生物的生存策略中汲取灵感其价值不仅在于提供了一个新的优化工具更在于展示了如何从自然观察中抽象出有效的计算模型这一充满魅力的过程。希望这份详细的拆解和代码能帮你更好地理解和使用它甚至激发出你自己改进和创造新算法的灵感。
返回列表