news 2026/10/18 13:56:48

柔性作业车间调度与NSGA-II多目标优化:Matlab实现与实战解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
柔性作业车间调度与NSGA-II多目标优化:Matlab实现与实战解析

1. 问题拆解:柔性作业车间调度到底难在哪

做车间调度研究的同学应该都有同感——传统的作业车间调度(JSP)已经够让人头疼了,柔性作业车间调度(FJSP)更是在它基础上再添了一把火。JSP里每道工序只能在一台固定机器上加工,而FJSP放宽了这个约束,每道工序可以选择多台机器中的任意一台来加工,而且不同机器上的加工时间通常还不一样。这一下就把问题的复杂度从单纯“排顺序”升级成了“选机器 + 排顺序”的双重决策,每一道工序都要回答两个问题:在哪台机器上做、什么时候开始做。

正是这种双重决策让FJSP成为一个典型的NP-Hard组合优化问题。零件数量稍多一点、机器数量一上去,穷举法基本就告别实战了——计算量爆炸式增长,靠传统精确算法根本撑不住。工业界实际遇到的调度场景往往还有多目标需求,比如既想让最大完工时间(Makespan)最短,又想让机器总负载尽量均衡,这两个目标常常互相打架:你想让某台效率高的机器多干活缩短总工期,它的负载就上去了,别的机器闲着,均衡性就变差。这种此消彼长的关系,正是多目标优化要处理的核心矛盾。

我最早接触这个课题的时候,也想着找个现成代码跑一跑完事,结果发现网上能直接用的实现并不多。很多代码要么只处理单目标,要么算法框架写死了没法改目标函数。后来我花了不少时间把NSGA-II(非支配排序遗传算法)和FJSP做了完整结合,用Matlab写了一套可以拿来做实验、改参数、跑仿真的代码。这套代码解决的核心问题就是:在FJSP的解空间里,通过NSGA-II的进化机制,同时优化多个目标,最终输出一组互不支配的Pareto最优解集,而不是单一的解。

这个课题适合谁?一类是做生产调度、智能制造方向研究的同学,另一类是想把智能优化算法落地到实际排产场景的工程师。不管你是用来做毕业设计、写论文,还是想理解多目标进化算法的工程应用,这套思路和代码都有参考价值。

2. 多目标进化框架:NSGA-II的核心机制解析

2.1 为什么偏偏选NSGA-II

多目标优化算法不止NSGA-II一种,还有MOEA/D、SPEA2、PAES等。但NSGA-II在FJSP这个场景下可以说是“性价比”最均衡的选择。

NSGA-II的核心贡献有三块:快速非支配排序、拥挤度距离计算、精英保留策略。快速非支配排序把种群按Pareto支配关系分层,第一层就是当前种群中的非支配解集,第二层是去掉第一层后剩下的非支配解集,依此类推。这样种群就有了优先级——越靠前的层,个体越优秀。拥挤度距离则是用来衡量同一层里解的稀疏程度,距离越大说明这个解周围越空旷,越值得保留,用来维持种群多样性。

对比其他算法,NSGA-II的优势在于:参数相对少且收敛性和分布性之间的平衡做得比较好。MOEA/D需要预先设计权重向量,在目标个数变化时权重设计会很麻烦;SPEA2的环境选择策略也不错,但实现复杂度稍高。NSGA-II的算法规格几乎成了多目标进化算法的“标准范式”,论文里用它做对比实验也最有说服力。

2.2 非支配排序和拥挤度距离的计算逻辑

非支配排序的逻辑不复杂但很关键。假设种群里有N个个体,每个个体有M个目标值(比如完工时间、总负载)。个体A支配个体B,需要满足A在所有目标上都不比B差,并且至少在一个目标上严格优于B。按照这个规则把所有个体分到不同的Pareto前沿面上:第一前沿面是当前种群中不被任何个体支配的解集,然后把这些解暂时移除,在剩余个体中再找新的非支配解集,作为第二前沿面,直到所有个体都被分层。

拥挤度距离的计算思路是:对同一前沿面的个体,按每个目标值排序,边界个体的拥挤度设为无穷大,内部个体的拥挤度是相邻两个个体在各目标上的归一化距离之和。这个值越大,说明这个解在目标空间中越孤立,保留它能让解集分布更均匀。

实际代码实现里有个容易踩的坑:如果多个个体在某个目标上的值完全相等,排序时要特别注意索引对应关系,不然算出来的拥挤度会错位。我当时调试这个模块的时候,就因为这个索引问题导致种群迟迟无法收敛到均匀的Pareto前沿,花了半天才定位到问题。

2.3 锦标赛选择、交叉和变异如何协同工作

NSGA-II的选择机制是锦标赛选择(Tournament Selection),每次从种群中随机挑两个个体,优先比较前沿面等级,等级低的胜出;如果等级相同,就比较拥挤度距离,距离大的胜出。这个机制保证了种群向Pareto前沿进化的同时,不会过早丢失分布在稀疏区域的解。

交叉和变异是产生新解的主要手段。针对FJSP的特点,交叉操作不仅要处理工序顺序,还要处理机器分配,所以通常会设计两段式编码并配合相应的交叉算子——工序部分用类似POX(Precedence Operation Crossover)的方式,机器部分用均匀交叉或两点交叉。变异则分为工序变异和机器变异:工序变异随机交换两个工序的位置,必须检查交换后是否仍然满足工序先后约束;机器变异则是随机挑一道工序,从它的候选机器集中换一台机器。

这三个算子协同的效果直接决定了算法收敛速度和最终解的质量。我实测下来的经验是:交叉概率设在0.8~0.9之间,变异概率设在0.1~0.2之间,这个区间的效果最稳定。变异概率太高会破坏已经形成的优良基因组合,太低又容易陷入局部最优。

3. 柔性作业车间调度的数学建模与编码设计

3.1 决策变量与约束条件的形式化描述

FJSP的数学模型可以这样描述:有n个工件,每个工件由若干道工序组成,工序之间有先后顺序约束。有m台机器,每道工序可以在若干台候选机器上加工,且在不同机器上的加工时间不同。调度问题的目标就是确定每道工序的机器选择和开工时间,使得某些性能指标最优。

形式化地讲,决策变量包括:工序i的机器分配变量(从候选机器集中选一台)和工序i的开工时间。约束条件有三类:工序顺序约束(同一工件的前道工序完成后才能开始后道工序)、机器唯一性约束(同一台机器同一时刻只能加工一道工序)、时间连续性约束(工序一旦开始不能中断)。

这里需要注意,FJSP里还有一个“可选机器集”的概念——不是所有机器都能加工所有工序,每道工序有自己的候选机器集。这个约束直接影响了编码和初始化策略的设计,候选机器集在代码里用一个元胞数组存储,每个元素对应一道工序可选的机器编号列表。

3.2 两段式编码方案:工序排序串与机器分配串

FJSP的编码是整个算法的地基。我用的是最经典的两段式编码:一段是工序排序串(OS),一段是机器分配串(MS)。工序排序串由所有工件的工序编号组成,每个工件编号出现的次数等于该工件的工序数。解码时从左到右扫描这个串,按照每个编号第几次出现来确定当前是哪个工件的哪道工序。

机器分配串和工序排序串等长,每个位置存储对应工序选择的机器编号。需要注意:机器编号必须是该工序候选机器集中的合法机器,不能随便填一个它加工不了的机器,否则解码阶段直接报错或者产生不可行解。

举个例子,假设有3个工件,工件1有2道工序,工件2有3道工序,工件3有2道工序。那么工序排序串的总长度是7,可能的编码形如[1,2,1,3,2,3,2],其中1出现2次代表工件1的两道工序,2出现3次代表工件2的三道工序。机器分配串则对应每个位置的工序各选哪台机器。

3.3 解码策略与主动调度的生成

解码是FJSP实现的另一个关键模块。解码器需要根据工序排序串和机器分配串,结合工序约束和机器约束,推算出每道工序的最早开工时间和完工时间,最终得到整个调度方案的时间表。

这里必须区分两种解码方式:半主动调度和主动调度。半主动调度只保证工序按顺序排列,不插入空闲时间;主动调度则在不推迟其他工序的前提下,尽可能把每道工序往左压缩,利用机器上的空闲时间片。主动调度得到的Makespan通常比半主动调度更短,所以实际使用中优先采用主动解码。

主动解码的经典策略有两种:一种是“左移策略”,在满足约束的情况下把工序插入到机器最早可用的空闲区间;另一种是“全局选择策略”,按顺序逐个安排工序到最早可用的机器空闲时间段。在Matlab实现中,我采用的是基于时间线扫描的主动解码方式,维护每台机器的占用时间区间表,每次安排新工序时遍历机器的空闲区间,找到最早的可行插入点。

3.4 多目标函数构建:完工时间、机器负载与能耗

FJSP的优化目标可以根据实际需求灵活设计。最常见的三个目标是:最大完工时间(Makespan)、机器最大负载、机器总负载。这三个目标有层次关系,但又各有侧重。

最大完工时间反映了生产效率,是所有工序全部完成的时间;机器最大负载是负荷最高的那台机器的总工作时间,反映了瓶颈设备的使用情况;机器总负载是所有机器工作时间之和,反映了整体资源消耗。在绿色制造的场景下,还会加入能耗目标——不同机器加工同一道工序的能耗不同,降低总负载或优先选择低能耗机器对减少车间能耗有直接帮助。

在代码里,这三个目标通过一个目标函数计算并返回一个向量。NSGA-II对目标个数没有硬性限制,但目标越多,Pareto前沿的维度越高,解集的分布性就越难保证。我建议一般情况下用两个或三个目标就足够了,超过三个目标时,可以考虑用目标降维或者其他专门面向高维多目标优化的算法。

4. Matlab代码实现的关键细节

4.1 数据结构设计与初始化种群

Matlab写进化算法,数据结构的清晰度直接决定代码能不能顺利调通。我用的是结构体数组(struct array)来存储个体,每个个体包含两个核心字段:工序排序串(OS)、机器分配串(MS),此外还存储解码后的目标值(objectives)和被支配信息等辅助字段。

初始化种群的流程是:先随机生成工序排序串——把每个工件的工序编号填入一个数组中然后随机打乱;再生成机器分配串——遍历每道工序,从它的候选机器集中随机选一台。这一步看起来简单,但有个细节:如果初始种群完全随机,可能会让某些机器过度集中而某些机器闲置,导致初始解质量很差,拖慢收敛速度。更好的做法是初始化一部分个体时采用“机器负载均衡”启发式,在候选机器中优先选当前负载最低的机器,这样初始种群的质量会有明显提升。

4.2 交叉与变异算子的Matlab实现要点

工序排序串的交叉我用的是IPOX(Improved Precedence Operation Crossover)。思路是:将工件编号随机分成两个集合,子代1保留父代1中属于集合1的工序位置和顺序,再按父代2的顺序填入集合2的工序;子代2反过来。这个算子能很好保持工序先后可行性,实现也不复杂,核心代码逻辑大概就是几个矩阵索引操作。

% IPOX交叉核心逻辑示意 % parent1, parent2分别为两个父代的工序排序串 jobs = unique(parent1); set1 = jobs(randperm(length(jobs), round(length(jobs)/2))); set2 = setdiff(jobs, set1); % 子代1先复制parent1中属于set1的位置,再用parent2中set2的工序按序填充空位

机器分配串的交叉我采用均匀交叉,即每个位置以50%的概率从父代1或父代2中继承机器编号,但必须校验继承后机器是否在候选集中。有一种情况要特别留意:如果两台父机器都不在该工序的候选集中,就直接随机选一台候选机器。

变异算子方面,工序部分我用的是交换变异——随机选取两个位置交换工序编号,但交换后要检查每个工件的工序出现次数是否仍然正确(编号出现次数不能变)。机器部分我用了两种变异方式随机切换:一种是随机改变一台机器的编号,另一种是局部搜索式变异——找到当前负载最高的机器上的一道工序,把它换成候选集中负载更低的机器,这种变异对改善负载均衡非常有效。

4.3 Pareto前沿求解与种群更新流程

种群更新的流程遵循NSGA-II的标准逻辑:父代种群P(规模N)通过选择、交叉、变异生成子代种群Q(规模N),把P和Q合并成规模2N的种群R,对R做非支配排序,然后按前沿面等级从低到高依次填充下一代种群,直到填满N为止。在填最后一个前沿面时,如果该前沿面的个体数量超出剩余名额,就按拥挤度距离从大到小选取,保证多样性。

在Matlab代码中,这个流程对应一个主循环:每代里先对当前种群做二元锦标赛选择,得到父代配对;再做交叉和变异,生成子代;合并种群并执行环境选择。我设置的最大迭代次数一般是200~500代,种群规模100~200。代数和种群规模增大时,解的质量会提升,但计算耗时也线性增长,需要根据实验设备权衡。

一个需要特别强调的性能优化点:Matlab的循环效率偏低,非支配排序里的双层循环在大种群下会成为瓶颈。我建议在Matlab里尽量用向量化操作——比如用矩阵一次性存储所有个体的目标值,用逻辑索引代替逐元素比较,能显著提速。我实际测试过,同样的种群规模和迭代次数,向量化后耗时能减少到原来的三分之一左右。

4.4 甘特图绘制与结果可视化

算法跑完不算完,还得把调度方案可视化出来才能直观判断结果优劣。Matlab里最常用的就是甘特图。绘制甘特图的思路是:遍历机器,在时间轴上按区间绘制横条,每条对应一道工序,用不同的颜色区分不同工件。每个矩形的起始x坐标是工序的开始时间,宽度是加工时长,y坐标按机器编号分组错开。

% 甘特图绘制核心逻辑示意 for i = 1:numMachines for j = 1:numOpsOnMachine(i) rectangle('Position', [startTime(j), i-0.4, processTime(j), 0.8], ... 'FaceColor', colorMap(jobIndex, :)); end end

此外还建议绘制Pareto前沿的散点图,横轴是完工时间,纵轴是机器总负载,能直观看出解的分布范围和权衡关系。如果是三目标场景,可以用三维散点图,但Matlab三维图的可读性稍差,建议用二维投影图分三张子图展示两两关系。

5. 实验分析与典型结果解读

5.1 测试算例设计与参数配置

我采用的测试算例是某个公开基准数据集的扩展版本——来自某高校实验室的标准FJSP测试集,包含8个工件、8台机器,每个工件的工序数在2到6之间,每道工序有3到5台候选机器,加工时间在5到20之间随机分布。这个规模不算大,但足以验证算法的正确性和寻优能力,跑起来也快。

参数配置方面:种群规模设为100,迭代次数400代,交叉概率0.85,变异概率0.15。目标函数选择了最大完工时间(Makespan)和机器总负载两个目标。这个配置是我经过多轮实验确定的,既能保证收敛性又不会让计算时间过长。

5.2 收敛曲线与Pareto前沿的分析方法

收敛曲线的绘制方法是:记录每一代种群中契约个体的目标值最小值和种群平均值,画成随迭代次数变化的曲线。从曲线趋势可以判断算法是否收敛、收敛速度如何、是否存在早熟。我实测的结果是:前50代目标值下降非常快,到150代左右开始放缓,300代以后基本趋于平稳,说明400代的设置是足够的。

Pareto前沿的分析主要看两点:一是解的分布是否均匀,二是前沿是否覆盖了足够的范围。NSGA-II在拥挤度距离机制的加持下,这两点通常都有保障。我观察到的典型前沿形态是:随着完工时间增加,总负载会下降,形成一个明显的L形或反比例曲线,完美体现了两个目标之间的冲突关系。

从实际应用角度,Pareto前沿的解集给了决策者很大的灵活性。比如生产任务紧急时,可以选完工时间最短的方案,哪怕机器负载高一些;如果设备需要维护保养,就可以选总负载较低的方案,用稍微延长一点工期换取设备寿命和能耗的改善。

5.3 单目标加权与多目标Pareto决策的对比

有些场景下,用户只想要一个具体的调度方案,而不是一堆Pareto解。这时候有两种处理方式:一种是把多目标加权求和转成单目标优化,另一种是从Pareto前沿里用决策方法选一个折中解。

我对比过这两种方式的优劣:单目标加权法实现简单,但权重系数很难定,而且对权重非常敏感——权重稍微改一点,最优解可能就跳到完全不同的区域。多目标Pareto方法虽然一次要跑多个解,但跑完后可以用TOPSIS或者简单的归一化加权法从Pareto前沿中选出一个“偏好解”,这个解的鲁棒性明显更好。

在代码里,我额外写了一个从Pareto前沿中按最小曼哈顿距离挑选折中解的函数:把目标值归一化后,找离原点(理想最小值点)距离最近的一个解,作为推荐方案。这个方法不需要用户给权重,适合快速从一堆解里挑一个“相对均衡”的方案直接用。

6. 常见问题与排查技巧实录

6.1 解码后目标值为无穷大或负数

这个问题在调试初期几乎必现。最常见的原因是:机器分配串中存在不在候选机器集中的机器编号,导致解码时找不到对应的加工时间。排查方法是在解码函数入口加一个校验:遍历机器分配串的每个位置,检查机器编号是否在该工序的候选机器集中,不合法就报错。我当时的解决办法是在初始化、交叉、变异三个环节都增加了合法性校验函数,统一维护“每道工序的候选机器集合”这个元胞数组,保证任何时刻生成的个体都是合法的。

6.2 种群过早收敛,Pareto前沿分布不均

如果跑了几代之后所有个体的目标值都差不多,Pareto前沿缩成一个点,大概率是选择压力过大或者变异强度不足。可以按这几个方向调整:调低锦标赛选择的参与个体数(tournament size),从2改成1.5的实现——即随机挑3个取最优的;或者调高变异概率,尤其是机器部分的局部搜索变异,它能有效引入新的机器组合。还有一种可能性是初始种群多样性不够,建议增大初始种群里的随机比例,避免大量使用同一个启发式初始化策略。

6.3 计算耗时过长如何优化

Matlab毕竟是解释型语言,循环效率天然不如编译型语言。如果跑大规模算例特别慢,优先检查三处:非支配排序里是否有不必要的重复比较、解码器里是否反复扫描同一台机器的完整时间线、种群合并时是否有重复的个体计算。我个人的经验是:解码器是整个算法计算量最大的模块,优化它收益最大。比如可以维护“每台机器当前最晚空闲时间”这个动态数组,每次只需查找插入点而不用重新遍历整条时间线;另外将工序的候选机器信息提前预处理成数值矩阵,避免解码时反复索引元胞数组带来的性能开销。

6.4 结果不稳定,多次运行差异大

随机算法的结果本来就有波动,但如果波动太大,就要怀疑随机种子管理和初始化策略。建议在代码开头用rng固定随机种子,便于复现实验结果;同时在论文或报告中,至少要跑5到10次独立实验,取平均结果或最优结果,而不是只跑一次就下结论。我通常在实验过程中把每次运行的结果保存成.mat文件,后面分析时可以直接调用,不用重新跑一遍。

7. 基于实测经验:参数调优与后续扩展建议

7.1 参数整定的实战经验表

不同规模的问题,最优参数区间会有差异。我把实测中比较可靠的参数范围整理成一个表格,方便大家参考:

参数名称小规模算例(≤10工件)中规模算例(10~30工件)大规模算例(>30工件)
种群规模100150~200200~300
最大迭代次数200300500
交叉概率0.8~0.90.85~0.90.9
变异概率0.150.15~0.20.2
锦标赛规模22~33

这些参数是从多组对照实验里归纳出来的,不是绝对的黄金值,但作为初次实验的启动参数基本不会出大问题。关键是观察收敛曲线的形态,如果还没到迭代末期目标值就水平了,说明代数设多了;如果到末期还在明显下降,就该增加迭代次数。

7.2 向其他场景迁移的扩展方向

这套“NSGA-II + FJSP”的框架其实有很强的扩展性。如果你想做更多方向的研究或工程尝试,可以从这几个方向切入:

一是加入AGV小车调度。车间里物料运输也是影响生产效率的关键因素,把AGV的路径规划和充电约束加进模型,目标函数再增加一个“AGV总行驶时间”或者“AGV等待时间”,问题就更贴近真实智能工厂场景了。

二是引入机器故障的动态事件处理。实际车间里机器随时可能出故障,算法需要具备一定的动态响应能力——比如检测到故障后,对未开工的工序进行重调度。实现思路是:当故障事件发生时,冻结已完工的工序,保留当前种群,重新触发NSGA-II进行局部重调度。这种“预测-反应式”调度在工业界非常受欢迎。

三是用深度强化学习替代或辅助遗传算法。近几年基于指针网络的端到端调度方法很热,可以把NSGA-II生成的高质量解作为专家数据,训练一个调度策略网络,推理时直接给一个近似最优解,速度比进化算法快非常多。这两种路线各有优劣,适合不同场景下选择。

7.3 一个小技巧:如何从Pareto前沿里选出“最好”的方案

最后分享一个我在实际使用中觉得特别好用的小技巧。跑完NSGA-II之后,想把Pareto前沿里的解选一个用于实际排产,不要直接看单目标最小——那样就把多目标优化的意义抹掉了。我常用的方法是“最小距离法”:先把各目标值做归一化处理,然后找欧氏距离离理想点最近的解;如果决策者对某个目标有明确偏好,可以在归一化时给不同目标加权偏好系数,再做距离排序,选出来就是很实用的一个折中方案。

这个方法实现起来也就几行代码,但在实际项目沟通里特别有用——给现场管理人员展示时,你拿出来的是一个有明确倾向的可执行方案,而不是一堆散点,说服力强得多。而且这个选择过程独立于算法,换个指标重选就行,不需要重新跑一遍进化过程,效率高又灵活。

这套代码和完整实现,既适合用来做学术论文的实验验证,也可以改一改搬到实际排产系统里做决策支持。调度问题说到底是一个“拿时间换性能、拿负载换效率”的权衡艺术,NSGA-II的价值就是帮你在这些冲突目标之间找到一条尽量理想的均衡曲线。我跑通这套代码后最大的体会是:多目标优化并不神秘,难的是把生产约束、决策语义和进化机制严丝合缝地对应起来,希望这篇文章能帮你少踩一些我踩过的坑。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/19 8:39:43

PS5串流全攻略:局域网、远程、采集卡三方案实测

1. “AnyPS5”到底在解决什么问题PS5这台机器,买的时候很痛快,真正用起来却经常被“屏幕绑定”卡住。客厅的电视被家里人占了、出差住酒店想顺手清个日常任务、躺在床上不想开大灯、想在办公室午休时把昨晚没打完的Boss磨过去——这些场景里,…

作者头像 李华
网站建设 2026/10/19 0:52:46

单片机电容触摸按键设计实战:从原理到PCB与代码落地

简介:本资源是一份面向单片机初学者与家电维修爱好者的电容感应式触摸按键技术详解文档,聚焦STC系列单片机(如STC12C4052AD)的纯软件实现方案,解决专用芯片普及不足、维修配件难寻、原理理解模糊等实际问题。文档深入剖…

作者头像 李华
网站建设 2026/10/18 11:25:27

PS5实用优化手册:屏幕、网络、外设与存储的适配

看到“AnyPS5”这个题目,我先说个结论:它不是系统级破解,也不是什么魔改固件的黑话。我花了三周时间,把手里这台PS5从头到脚折腾了一遍,最后得出的理解是——所谓“Any”,指的是一台主机在任何日常条件不算…

作者头像 李华
网站建设 2026/10/19 8:34:53

Java日期失效判断:LocalDateTime边界、时区与ISO格式实战

做Java后端开发这些年,日期和时间的处理一直是绕不开的硬骨头。尤其是“判断某个日期是否已经失效”这类需求,做会员系统、优惠券、任务单、活动排期的时候几乎天天遇到。Java 8以后我们普遍用LocalDateTime替代了老的Date和Calendar,但真正落…

作者头像 李华
网站建设 2026/10/18 17:45:51

AI视频生产流水线:即梦+豆包+剪映三角工作流

1. 这不是“AI剪辑课”,而是一套可立即上手的AI视频生产流水线你点开这个标题,大概率是被“吊打付费”“保姆级”“从0到1”这几个词勾住的。但我想先说清楚:这30集内容里没有一集在教你怎么用“即梦”“豆包”“剪映”的按钮排布——它真正解…

作者头像 李华
网站建设 2026/10/19 7:16:43

2026-10-04 CV开源代码速览:轻量分割、小目标检测与扩散加速

计算机视觉的开源代码生态,几乎每天都在刷屏。今天这份速览对应2026年10月4日,我按自己长期养成的习惯,把当天能找到完整代码、能跑通的CV方向工作过了一遍,筛出几个真正值得点开仓库细看的方向:轻量级语义分割、小目标…

作者头像 李华