NSGA-II算法实战:用Python手把手教你解决多目标优化问题(附完整代码)

# NSGA-II算法实战:用Python手把手教你解决多目标优化问题(附完整代码) 多目标优化问题就像是在生活中做决策,你常常需要在多个相互冲突的目标之间寻找平衡。比如,设计一款产品,你既希望它性能卓越,又希望成本低廉,还希望开发周期短。这些目标往往无法同时达到最优,你需要找到一个“折中”的方案集合。这就是多目标优化的核心。对于开发者而言,当面对这类问题时,传统的单目标优化方法往往束手无策,而遗传算法家族中的**NSGA-II**(非支配排序遗传算法II)则提供了一套优雅且强大的解决方案。 这篇文章不是一篇理论综述,而是一份面向实践的指南。如果你已经对遗传算法有基本了解,现在需要快速上手一个能解决实际工程问题的多目标优化工具,那么你来对地方了。我们将绕过复杂的数学推导,直接切入核心:如何用Python从零开始实现NSGA-II,理解每一行代码背后的逻辑,并处理你在编码过程中可能遇到的典型问题。我们将构建一个完整的、可运行的框架,并通过对一个经典测试函数的优化,让你直观地看到算法如何一步步逼近最优解集。 ## 1. 环境准备与问题定义 在开始编码之前,我们需要明确两件事:一是搭建好编程环境,二是清晰地定义我们要解决的多目标优化问题。一个清晰的问题定义是算法成功的一半。 ### 1.1 安装必要的Python库 我们只需要最基础的几个科学计算和可视化库。建议使用`pip`进行安装。如果你使用的是Anaconda,这些库通常已经预装。 ```bash pip install numpy matplotlib ``` * `numpy`:用于高效的数组和矩阵运算,是算法中种群、目标值等数据存储和处理的基石。 * `matplotlib`:用于可视化最终的Pareto前沿,直观地展示优化结果。 ### 1.2 定义我们的第一个多目标优化问题 为了聚焦于算法实现本身,我们选择一个经典的双目标优化测试问题:**ZDT1**。这个问题定义清晰,其真实的Pareto前沿是已知的凸曲线,非常适合用来验证我们代码的正确性。 ZDT1问题的数学描述如下: - 决策变量个数 `n=30`,每个变量 `x_i` 的取值范围是 `[0, 1]`。 - 目标函数1:`f1(x) = x1` - 目标函数2:`f2(x) = g(x) * h(f1, g)` - 其中 `g(x) = 1 + 9 * (sum_{i=2}^{n} x_i) / (n-1)` - `h(f1, g) = 1 - sqrt(f1 / g)` 这个问题的特点是,`f1` 越小越好,`f2` 也越小越好,但两者相互冲突。其真实的Pareto前沿对应 `g(x)=1` 时 `f2 = 1 - sqrt(f1)` 的曲线。 > 注意:选择ZDT1而非更简单的函数,是因为它能更好地测试算法在维持解集多样性和收敛性方面的能力。许多简单的双目标函数(如原文中的示例)可能无法充分暴露算法实现中的潜在缺陷。 下面我们用Python代码来定义这个问题: ```python import numpy as np def zdt1(individual): """ 计算ZDT1问题的两个目标函数值。 参数: individual: 一个一维numpy数组,代表一个解(染色体),长度为30。 返回: 一个包含两个目标函数值的元组 (f1, f2)。 """ # 目标函数1 f1 = individual[0] # 计算g(x) g = 1.0 + 9.0 * np.sum(individual[1:]) / (len(individual) - 1) # 目标函数2 h = 1.0 - np.sqrt(f1 / g) f2 = g * h # 默认是最小化问题,我们直接返回计算值 return np.array([f1, f2]) ``` ## 2. NSGA-II核心组件实现 NSGA-II的卓越性能主要依赖于三个核心机制:**快速非支配排序**、**拥挤距离计算**和**精英保留策略**。我们将逐一实现它们,并确保代码的效率和可读性。 ### 2.1 快速非支配排序 这是NSGA-II区分解优劣的关键。其目的是将种群中的解划分为不同的“前沿层”。第一层(Front 0)是所有不被任何其他解支配的解(Pareto最优解),第二层是被第一层中至少一个解支配,但又不被其他同层或更低层解支配的解,以此类推。 **支配关系**:解A支配解B,当且仅当A在所有目标上都不比B差,并且至少在一个目标上严格比B好。 ```python def fast_non_dominated_sort(population_obj): """ 对种群进行快速非支配排序。 参数: population_obj: 一个二维numpy数组,形状为 (population_size, n_objectives), 每一行代表一个解的目标函数值向量。 返回: fronts: 一个列表的列表。fronts[0]是第一前沿层(最优)解的索引列表, fronts[1]是第二层,依此类推。 """ population_size = population_obj.shape[0] # S[p]:存储被解p支配的解的索引列表 S = [[] for _ in range(population_size)] # n[p]:支配解p的解的数量 n = np.zeros(population_size, dtype=int) # rank[p]:解p所在的前沿层数 rank = np.zeros(population_size, dtype=int) fronts = [[]] # 初始化前沿列表,先放入一个空列表用于存储第一层 # 第一轮循环:计算支配关系 for p in range(population_size): S[p] = [] n[p] = 0 for q in range(population_size): if p == q: continue # 判断p是否支配q # 条件:p在所有目标上 <= q,且至少在一个目标上 < q if np.all(population_obj[p] <= population_obj[q]) and np.any(population_obj[p] < population_obj[q]): S[p].append(q) # 判断q是否支配p elif np.all(population_obj[q] <= population_obj[p]) and np.any(population_obj[q] < population_obj[p]): n[p] += 1 if n[p] == 0: rank[p] = 0 fronts[0].append(p) # 迭代构建后续前沿层 i = 0 while fronts[i]: # 当前前沿层不为空 Q = [] # 存储下一层前沿的索引 for p in fronts[i]: for q in S[p]: n[q] -= 1 if n[q] == 0: rank[q] = i + 1 if q not in Q: # 避免重复添加 Q.append(q) i += 1 if Q: # 如果下一层有解 fronts.append(Q) else: break # 下一层为空,结束循环 return fronts ``` > 提示:在比较两个解的目标向量时,我们使用了`np.all`和`np.any`,这使得代码可以轻松扩展到两个以上的目标函数,而无需修改逻辑。 ### 2.2 拥挤距离计算 在同一前沿层内,我们需要一个度量来区分解的“好坏”,以确保选择的多样性。拥挤距离衡量的是一个解在其相邻解之间的“孤立程度”。距离越大,说明该解所在区域越稀疏,保留它对维持前沿的分布均匀性越有利。 计算步骤(针对一个前沿层): 1. 根据每个目标函数值对该层解进行排序。 2. 边界解(最大值和最小值)的拥挤距离设为无穷大(或一个很大的数)。 3. 对于中间的解,其拥挤距离是其在每个目标上相邻解的函数值差值的归一化总和。 ```python def crowding_distance_assignment(front_obj): """ 计算一个前沿层内所有解的拥挤距离。 参数: front_obj: 一个二维numpy数组,形状为 (front_size, n_objectives), 代表某个前沿层所有解的目标函数值。 返回: distances: 一个一维numpy数组,长度为front_size,代表每个解的拥挤距离。 """ front_size = front_obj.shape[0] n_obj = front_obj.shape[1] distances = np.zeros(front_size) if front_size <= 2: # 如果前沿层解的数量小于等于2,直接赋予最大距离 distances.fill(np.inf) return distances for m in range(n_obj): # 对每个目标函数分别处理 # 根据第m个目标函数值排序 order = np.argsort(front_obj[:, m]) # 边界解的距离设为无穷大 distances[order[0]] = np.inf distances[order[-1]] = np.inf # 获取该目标的最大最小值,用于归一化 f_max = front_obj[order[-1], m] f_min = front_obj[order[0], m] if f_max == f_min: continue # 避免除零错误 # 计算中间解的拥挤距离贡献 for i in range(1, front_size - 1): distances[order[i]] += (front_obj[order[i+1], m] - front_obj[order[i-1], m]) / (f_max - f_min) return distances ``` ### 2.3 选择、交叉与变异算子 遗传算法的进化动力来源于选择、交叉和变异。在NSGA-II中,选择操作是基于**二元锦标赛选择**和**拥挤比较算子**。 **拥挤比较算子 (≺_n)**:用于比较同一前沿层内两个解的优劣。 1. 优先选择前沿层序号`rank`更小的解(更优的前沿)。 2. 如果两个解在同一前沿层,则选择拥挤距离`distance`更大的解(更稀疏的区域)。 ```python def tournament_selection(population, fitness, ranks, distances, tournament_size=2): """ 基于拥挤比较算子的二元锦标赛选择。 参数: population: 种群决策变量数组。 fitness: 种群目标函数值数组。 ranks: 每个解的前沿层序号。 distances: 每个解的拥挤距离。 tournament_size: 锦标赛规模,默认为2。 返回: 被选中的父代个体的索引。 """ selected_indices = [] pop_size = len(population) for _ in range(pop_size): # 需要选择出pop_size个父代 # 随机选择 tournament_size 个候选者 candidates = np.random.choice(pop_size, tournament_size, replace=False) # 根据拥挤比较算子选择优胜者 winner = candidates[0] for candidate in candidates[1:]: if (ranks[candidate] < ranks[winner]) or \ ((ranks[candidate] == ranks[winner]) and (distances[candidate] > distances[winner])): winner = candidate selected_indices.append(winner) return selected_indices ``` 对于交叉和变异,我们采用遗传算法中常用的**模拟二进制交叉(SBX)**和**多项式变异**。它们能较好地保持解的有效性,并在实数编码问题中表现优异。 ```python def simulated_binary_crossover(parent1, parent2, eta_c=20): """ 模拟二进制交叉 (SBX)。 参数: parent1, parent2: 父代个体(一维数组)。 eta_c: 分布指数,控制子代与父代的相似度,值越大子代越接近父代。 返回: 两个子代个体。 """ u = np.random.rand(len(parent1)) beta = np.empty_like(u) mask = u <= 0.5 beta[mask] = (2 * u[mask]) ** (1.0 / (eta_c + 1)) beta[~mask] = (1.0 / (2 * (1 - u[~mask]))) ** (1.0 / (eta_c + 1)) child1 = 0.5 * ((1 + beta) * parent1 + (1 - beta) * parent2) child2 = 0.5 * ((1 - beta) * parent1 + (1 + beta) * parent2) # 确保子代在变量边界内 child1 = np.clip(child1, 0, 1) child2 = np.clip(child2, 0, 1) return child1, child2 def polynomial_mutation(individual, eta_m=20, prob_mut=1.0/30): """ 多项式变异。 参数: individual: 待变异的个体。 eta_m: 分布指数。 prob_mut: 每个基因的变异概率,通常设为 1/变量个数。 返回: 变异后的个体。 """ mutated = individual.copy() for i in range(len(individual)): if np.random.rand() < prob_mut: u = np.random.rand() delta = 0.0 if u < 0.5: delta = (2 * u) ** (1.0 / (eta_m + 1)) - 1 else: delta = 1 - (2 * (1 - u)) ** (1.0 / (eta_m + 1)) mutated[i] += delta mutated[i] = np.clip(mutated[i], 0, 1) # 确保在边界内 return mutated ``` ## 3. 算法主循环与精英保留策略 NSGA-II的核心循环遵循“生成子代 -> 合并父子代 -> 环境选择”的模式。环境选择环节是精英保留策略的体现,它从合并后的种群中选出最好的N个个体进入下一代。 ```python def nsga2_main(pop_size=100, max_gen=250, n_var=30, crossover_prob=0.9): """ NSGA-II 主算法流程。 参数: pop_size: 种群大小。 max_gen: 最大进化代数。 n_var: 决策变量个数(对应ZDT1的30)。 crossover_prob: 交叉概率。 返回: final_population: 最终种群。 final_fitness: 最终种群的目标函数值。 pareto_front: 近似Pareto前沿(第一层非支配解)。 """ # 1. 初始化种群 population = np.random.rand(pop_size, n_var) # 在[0,1]内随机生成 fitness = np.array([zdt1(ind) for ind in population]) for gen in range(max_gen): # 2. 对当前种群进行非支配排序和拥挤距离计算 fronts = fast_non_dominated_sort(fitness) all_distances = np.zeros(pop_size) # 为每一层计算拥挤距离 for front in fronts: front_fitness = fitness[front, :] front_distances = crowding_distance_assignment(front_fitness) all_distances[front] = front_distances # 为每个个体分配前沿层序号 ranks = np.zeros(pop_size, dtype=int) for idx, front in enumerate(fronts): ranks[front] = idx # 3. 选择父代(二元锦标赛) parents_indices = tournament_selection(population, fitness, ranks, all_distances) parents = population[parents_indices] # 4. 交叉和变异生成子代 offspring = [] for i in range(0, pop_size, 2): if i+1 < pop_size and np.random.rand() < crossover_prob: p1, p2 = parents[i], parents[i+1] c1, c2 = simulated_binary_crossover(p1, p2) c1 = polynomial_mutation(c1) c2 = polynomial_mutation(c2) offspring.extend([c1, c2]) else: # 如果不交叉,则直接复制父代并变异 c1 = polynomial_mutation(parents[i].copy()) c2 = polynomial_mutation(parents[i+1].copy()) if i+1 < pop_size else None offspring.append(c1) if c2 is not None: offspring.append(c2) offspring = np.array(offspring[:pop_size]) # 确保子代数量为pop_size # 5. 合并父代和子代种群 combined_population = np.vstack([population, offspring]) combined_fitness = np.array([zdt1(ind) for ind in combined_population]) # 6. 环境选择:从合并种群(2N)中选择最好的N个进入下一代 next_pop_indices = [] combined_fronts = fast_non_dominated_sort(combined_fitness) # 计算合并种群中每个解的拥挤距离 combined_distances = np.zeros(2 * pop_size) for front in combined_fronts: front_fitness = combined_fitness[front, :] front_distances = crowding_distance_assignment(front_fitness) combined_distances[front] = front_distances # 按前沿层和拥挤距离选择 for front in combined_fronts: # 如果加入当前层会超过种群大小,则按拥挤距离排序,选择距离大的 if len(next_pop_indices) + len(front) > pop_size: # 计算当前层需要选择的个数 remaining = pop_size - len(next_pop_indices) # 根据拥挤距离降序排序当前层的索引 sorted_front_indices = front[np.argsort(-combined_distances[front])] next_pop_indices.extend(sorted_front_indices[:remaining].tolist()) break else: next_pop_indices.extend(front) # 7. 形成新一代种群 population = combined_population[next_pop_indices] fitness = combined_fitness[next_pop_indices] # 可选:每50代打印一次进度 if gen % 50 == 0: first_front_fitness = fitness[combined_fronts[0]] if combined_fronts[0].size > 0 else None print(f"Generation {gen}: First front size = {len(combined_fronts[0])}") # 最终的非支配排序,获取近似Pareto前沿 final_fronts = fast_non_dominated_sort(fitness) pareto_front = fitness[final_fronts[0]] if final_fronts[0].size > 0 else None return population, fitness, pareto_front ``` ## 4. 结果可视化与性能评估 运行算法后,我们需要评估其结果。最直观的方式就是可视化近似Pareto前沿,并将其与真实前沿进行对比。 ### 4.1 可视化Pareto前沿 ```python import matplotlib.pyplot as plt def plot_pareto_front(pareto_front, true_front=None): """ 绘制近似Pareto前沿和真实前沿(如果提供)。 参数: pareto_front: 算法得到的近似前沿,形状为 (n_points, 2)。 true_front: 真实的Pareto前沿点。 """ plt.figure(figsize=(10, 6)) if pareto_front is not None: # 对近似前沿按f1排序,使连线更平滑 sorted_front = pareto_front[pareto_front[:, 0].argsort()] plt.scatter(sorted_front[:, 0], sorted_front[:, 1], c='red', s=50, label='NSGA-II Approximation', zorder=3) plt.plot(sorted_front[:, 0], sorted_front[:, 1], 'r--', alpha=0.7, linewidth=1, zorder=2) if true_front is not None: plt.plot(true_front[:, 0], true_front[:, 1], 'b-', linewidth=2, label='True Pareto Front (ZDT1)', zorder=1) plt.xlabel('Objective 1 (f1)', fontsize=12) plt.ylabel('Objective 2 (f2)', fontsize=12) plt.title('Pareto Front Comparison', fontsize=14) plt.legend() plt.grid(True, alpha=0.3) plt.tight_layout() plt.show() # 生成ZDT1的真实Pareto前沿用于对比 def generate_true_pareto_zdt1(n_points=100): f1 = np.linspace(0, 1, n_points) f2 = 1 - np.sqrt(f1) # 当g(x)=1时 return np.column_stack((f1, f2)) # 运行算法并绘图 if __name__ == "__main__": pop_size = 100 max_gen = 250 final_pop, final_fit, approx_front = nsga2_main(pop_size=pop_size, max_gen=max_gen) true_front = generate_true_pareto_zdt1() print(f"Final population size: {final_pop.shape[0]}") print(f"Approximated Pareto front size: {approx_front.shape[0] if approx_front is not None else 0}") plot_pareto_front(approx_front, true_front) ``` 运行这段代码,你应该能看到红色的散点(近似前沿)紧密地分布在蓝色的真实前沿曲线附近。这表明我们的NSGA-II实现是有效的,能够很好地收敛并保持解的多样性。 ### 4.2 常见问题与调试技巧 在实现和运行过程中,你可能会遇到一些问题。这里列出几个典型场景及其排查思路: | 问题现象 | 可能原因 | 排查与解决思路 | | :--- | :--- | :--- | | **算法不收敛**,解集远离真实前沿。 | 1. 交叉/变异概率设置不当,破坏性太强。<br>2. 选择压力太小,优秀个体无法被保留。<br>3. 种群大小或迭代次数不足。 | 1. 检查`crossover_prob`和`polynomial_mutation`中的`prob_mut`,适当调低。<br>2. 确保锦标赛选择中的拥挤比较算子逻辑正确,优先选择`rank`小的解。<br>3. 增加`pop_size`和`max_gen`。 | | **解集多样性差**,所有解挤在一起。 | 1. 拥挤距离计算有误,导致选择时无法区分同一层的解。<br>2. 变异算子未能有效探索搜索空间。 | 1. 仔细检查`crowding_distance_assignment`函数,特别是边界解的处理和归一化步骤。<br>2. 增大多项式变异的分布指数`eta_m`,或稍微提高变异概率`prob_mut`。 | | **运行速度非常慢**。 | 1. 非支配排序算法复杂度高(O(MN²))。<br>2. Python循环过多,未利用向量化。 | 1. 对于大规模问题(种群>1000,目标>3),考虑使用更高效的排序库或近似方法。<br>2. 在关键计算(如目标函数评估)中使用`numpy`向量化操作。本例中`zdt1`函数已向量化。 | | **最终前沿层解的数量远小于种群大小**。 | 环境选择逻辑可能有问题,在从合并种群选择时,只取了第一层前沿。 | 检查主循环中“环境选择”部分的代码,确保它是按前沿层逐层选取,直到填满新种群,并在最后一层根据拥挤距离筛选。 | 一个实用的调试方法是,在算法初期(如前10代)打印出种群的目标函数值、前沿层分布和拥挤距离,观察其变化是否符合预期。例如,第一层前沿的解应该具有最好的目标函数值(对于最小化问题,值更小),并且拥挤距离应该能有效区分同一层内的解。 将NSGA-II应用到你的具体问题时,关键在于**目标函数的定义**和**决策变量的编码**。确保你的目标函数计算正确且高效。对于复杂的约束条件,可能需要引入约束处理机制,如罚函数法或专门的约束支配关系。这个实现框架为你提供了一个坚实的起点,你可以在此基础上进行修改和扩展,以应对更复杂的现实世界多目标优化挑战。

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

Python内容推荐

多目标优化算法(四)NSGA3的代码(python3.6)

多目标优化算法(四)NSGA3的代码(python3.6)

它被设计用于解决多目标优化问题,这些问题通常涉及到多个相互冲突的目标函数,使得找到一个单一的最佳解变得困难。NSGA3是NSGA-II的改进版本,它引入了更精细的种群划分策略和新的选择机制来提高性能。

以python库 的形式 实现 NSGA-II算法_python_代码_下载

以python库 的形式 实现 NSGA-II算法_python_代码_下载

以 python 库的形式实现 NSGA-II 算法。该实现可用于解决多变量(多于一维)多目标优化问题。目标和维度的数量不受限制。一些关键算子被选为:二元锦标赛选择、模拟二元交叉和多项式变异。请注意,

非支配排序遗传算法(NSGA-II) 的实现,一种Python 中 的多目标优化算法_python_Jupyter _代码_下载

非支配排序遗传算法(NSGA-II) 的实现,一种Python 中 的多目标优化算法_python_Jupyter _代码_下载

**非支配排序遗传算法(NSGA-II)**NSGA-II是基于遗传算法(Genetic Algorithm)的一个改进版本,由Deb等人于2002年提出,专门用于解决多目标优化问题。

多目标优化NSGA3代码,NSGAII多目标算法,Python

多目标优化NSGA3代码,NSGAII多目标算法,Python

在多目标优化问题中,NSGA(非支配排序遗传算法)系列是常用的一种高效解决方案。

NSGAII算法的Python实现代码

NSGAII算法的Python实现代码

该代码实现了基于NSGA-II的多目标优化算法,并包含多个测试函数支持。同时涉及三维坐标点和二维数据点的处理,可用于图形绘制、数据分析及可视化。

多目标优化NSGA3代码,NSGAII多目标算法,Python源码.zip

多目标优化NSGA3代码,NSGAII多目标算法,Python源码.zip

示例问题:可能提供了一些示例多目标优化问题的定义,用于测试和演示算法的性能。通过这些代码,你可以学习如何在Python环境中应用多目标优化算法,以及如何定制和调整算法参数以适应不同的优化问题。

基于MOEAD 和 NSGA-II多目标优化算法解决柔性车间调度问题附Python代码.rar

基于MOEAD 和 NSGA-II多目标优化算法解决柔性车间调度问题附Python代码.rar

本资源包含的Python代码为研究者和工程师提供了一个实用的工具,通过MOEAD和NSGA-II算法对柔性车间调度问题进行深入研究和模拟实验。

NSGA-II算法的python实现(包含详细注释案例)

NSGA-II算法的python实现(包含详细注释案例)

总之,NSGA-II算法通过非支配排序和拥挤度策略,有效地解决了多目标优化问题,是多目标优化领域的重要工具。

基于多种遗传算法(NSGA-II,NSGA-III,C-TAEA)和模糊优化算法的实现(python)

基于多种遗传算法(NSGA-II,NSGA-III,C-TAEA)和模糊优化算法的实现(python)

标题中的“基于多种遗传算法(NSGA-II,NSGA-III,C-TAEA)和模糊优化算法的实现(python)”表明这是一个关于多目标优化问题的项目,它使用了三种不同的遗传算法变体以及模糊优化技术,并且是用

基于MOEAD 和 NSGA-II多目标优化算法解决柔性车间调度问题(Python代码实现)

基于MOEAD 和 NSGA-II多目标优化算法解决柔性车间调度问题(Python代码实现)

内容概要:本文介绍了基于MOEAD和NSGA-II两种多目标优化基于MOEAD 和 NSGA-II多目标优化算法解决柔性车间调度问题(Python代码实现)算法解决柔性车间调度问题的Python代码实

多目标优化算法或多目标优化算法的 python 库

多目标优化算法或多目标优化算法的 python 库

pyMetaheuristic是一个开源的Python库,专注于提供多种元启发式算法。该库遵循GNU通用公共许可证,不提供任何保证,用户需遵守相应条款。

NSGA3多目标优化算法python代码.zip

NSGA3多目标优化算法python代码.zip

《NSGA3多目标优化算法在Python中的实现详解》NSGA3(Non-dominated Sorting Genetic Algorithm 3)是一种高效的多目标优化算法,主要用于解决具有多个相互冲突的目标函数的优化问题

Python实现NSGA-II多目标优化算法:Jupyter Notebook代码详解与下载

Python实现NSGA-II多目标优化算法:Jupyter Notebook代码详解与下载

非支配排序遗传算法(NSGA-II)是一种广泛应用于多目标优化问题的改进遗传算法,由Deb等人于2002年提出。该算法适用于解决具有相互冲突目标函数的复杂工程与设计问题。NSGA-II的核心流程包括:

文档+程序NSGA-II多目标优化的matlab代码.zip

文档+程序NSGA-II多目标优化的matlab代码.zip

通过运行和调试这些代码,可以提升对多目标优化问题解决能力,对于科研工作者和工程师来说,是宝贵的实践素材。

nsga-ii算法

nsga-ii算法

#### 五、应用领域NSGA-II算法因其强大的解决多目标优化问题的能力,在许多领域都有着广泛的应用,包括但不限于:- **工程设计**:如机械结构优化、电子电路设计等。

某银行电气平面图纸.dwg.rar

某银行电气平面图纸.dwg.rar

某银行电气平面图纸.dwg.rar

目标检测-番茄果实病害检测数据集6998张7类标签YOLO+VOC(已增强).zip

目标检测-番茄果实病害检测数据集6998张7类标签YOLO+VOC(已增强).zip

数据集格式:VOC格式+YOLO格式 压缩包内含:3个文件夹,分别存储图片、xml、txt文件 JPEGImages文件夹中jpg图片总计:6998 Annotations文件夹中xml文件总计:6998 labels文件夹中txt文件总计:6998 标签种类数:7 标签名称:["Healthy","Rotten-Tomato","bacterial-Spot","blossomendrotrotation","cracking","spliting","sunscaled"] 每个标签的框数(注意yolo格式类别顺序不和这个对应,而以labels文件夹classes.txt为准): Healthy 框数 = 4253(健康) Rotten-Tomato 框数 = 985(腐烂) bacterial-Spot 框数 = 4190(细菌性斑点) blossomendrotrotation 框数 = 1344(花腐病) cracking 框数 = 2163(裂纹) spliting 框数 = 1930(开裂) sunscaled 框数 = 1334(日灼病) 总框数:16199 图片清晰度(分辨率:像素):清晰 图片是否增强:是 标签形状:矩形框,用于目标检测识别 重要说明:暂无 特别声明:本数据集不对训练的模型或者权重文件精度作任何保证,数据集只提供准确且合理标注

STM32F4-USB-CDC-标准库版本

STM32F4-USB-CDC-标准库版本

STM32F4 USB CDC 标准库版本+VCP官方驱动

Arial Italic.rar

Arial Italic.rar

当 CAD 缺失对应字体时,图纸文字会显示异常,出现乱码、问号。将下载好的字体文件复制到 AutoCAD 的 Fonts 文件夹中,即可恢复正常显示。

无界创意,AI赋能。AI济南超级联赛第二季 •AIGC视频创意大赛正式启动

无界创意,AI赋能。AI济南超级联赛第二季 •AIGC视频创意大赛正式启动

无界创意,AI赋能。AI济南超级联赛第二季 •AIGC视频创意大赛正式启动

最新推荐最新推荐

recommend-type

pandas DataFrame实现几列数据合并成为新的一列方法

今天小编就为大家分享一篇pandas DataFrame实现几列数据合并成为新的一列方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
recommend-type

Python学习笔记之pandas索引列、过滤、分组、求和功能示例

主要介绍了Python学习笔记之pandas索引列、过滤、分组、求和功能,结合实例形式分析了Python针对抓取保存的csv数据使用pandas进行索引列、过滤、分组、求和等操作的相关实现技巧,需要的朋友可以参考下
recommend-type

pandas 选取行和列数据的方法详解

前言 本文介绍在 pandas 中如何读取数据行列的方法。数据由行和列组成,在数据库中,一般行被称作记录 (record),列被称作字段 (field)。回顾一下我们对记录和字段的获取方式:一般情况下,字段根据名称获取,记录根据筛选条件获取。比如获取 student_id 和 studnent_name 两个字段;记录筛选,比如 sales_amount 大于 10000 的所有记录。对于熟悉 SQL 语句的人来说,就是下面的语句: select student_id, student_name from exam_scores where chinese >= 90 and math >
recommend-type

从pandas一个单元格的字符串中提取字符串方式

以titanic数据集为例。 其中name列是字符串,现在想从其中提取title作为新的一列。 例如: # create new Title column df['Title'] = df['Name'].str.extract('([A-Za-z]+)\.', expand=True) 提取其中的title作为新的一列。 以上就是对从pandas的单元格中提取字符串的认识。 这篇从pandas一个单元格的字符串中提取字符串方式就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持软件开发网。 您可能感兴趣的文章:pandas
recommend-type

pandas读取CSV文件时查看修改各列的数据类型格式

主要介绍了pandas读取CSV文件时查看修改各列的数据类型格式,本文给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
recommend-type

学生成绩管理系统C++课程设计与实践

资源摘要信息:"学生成绩信息管理系统-C++(1).doc" 1. 系统需求分析与设计 在进行学生成绩信息管理系统开发前,首先需要进行系统需求分析,这是确定系统开发目标与范围的过程。需求分析应包括数据需求和功能需求两个方面。 - 数据需求分析: - 学生成绩信息:需要收集学生的姓名、学号、课程成绩等数据。 - 数据类型和长度:明确每个数据项的数据类型(如字符串、整型等)和长度,例如学号可能是字符串类型且长度为一定值。 - 描述:详细描述每个数据项的意义,以确保系统能够准确处理。 - 功能需求分析: - 列出功能列表:用户界面应提供清晰的操作指引,列出所有可用功能。 - 查询学生成绩:系统应能通过学号或姓名查询学生的成绩信息。 - 增加学生成绩信息:允许用户添加未保存的学生成绩信息。 - 删除学生成绩信息:能够通过学号或姓名删除已经保存的成绩信息。 - 修改学生成绩信息:通过学号或姓名修改已有的成绩记录。 - 退出程序:提供安全退出程序的选项,并确保所有修改都已保存。 2. 系统设计 系统设计阶段主要完成内存数据结构设计、数据文件设计、代码设计、输入输出设计、用户界面设计和处理过程设计。 - 内存数据结构设计: - 使用链表结构组织内存中的数据,便于动态增删查改操作。 - 数据文件设计: - 选择文本文件存储数据,便于查看和编辑。 - 代码设计: - 根据功能需求,编写相应的函数和模块。 - 输入输出设计: - 设计简洁明了的输入输出提示信息和操作流程。 - 用户界面设计: - 用户界面应为字符界面,方便在命令行环境下使用。 - 处理过程设计: - 设计数据处理流程,确保每个操作都有明确的处理逻辑。 3. 系统实现与测试 实现阶段需要根据设计阶段的成果编写程序代码,并进行系统测试。 - 程序编写: - 完成系统设计中所有功能的程序代码编写。 - 系统测试: - 设计测试用例,通过测试用例上机测试系统。 - 记录测试方法和测试结果,确保系统稳定可靠。 4. 设计报告撰写 最后,根据系统开发的各个阶段,撰写详细的设计报告。 - 系统描述:包括问题说明、数据需求和功能需求。 - 系统设计:详细记录内存数据结构设计、数据文件设计、代码设计、输入/输出设计、用户界面设计、处理过程设计。 - 系统测试:包括测试用例描述、测试方法和测试结果。 - 设计特点、不足、收获和体会:反思整个开发过程,总结经验和教训。 时间安排: - 第19周(7月12日至7月16日)完成项目。 - 7月9日8:00到计算机学院实验中心(三楼)提交程序和课程设计报告。 指导教师和系主任(或责任教师)需要在文档上签名确认。 系统需求分析: - 使用表格记录系统需求分析的结果,包括数据项、数据类型、数据长度和描述。 - 分析数据项如学生成绩信息、状态器、链表节点等,确定其属性和行为。 以上就是文档中提到的学生成绩信息管理系统开发的关键知识点。开发此类系统需要熟练掌握C++编程基础,了解面向对象的程序设计思想,以及熟悉文件操作和链表等数据结构的应用。此外,良好的软件开发流程意识、测试意识和文档撰写能力也是必不可少的。
recommend-type

别再手动拖拽了!用Lumerical脚本批量创建FDTD仿真结构(附完整代码)

# 告别低效建模:Lumerical脚本自动化实战指南 在光子学仿真领域,时间就是科研生命线。当同行还在GUI界面里反复点击菜单时,你已经用脚本批量生成了20组参数化结构——这不是未来场景,而是每位FDTD用户都应该掌握的基础生产力革命。本文将彻底改变你与Lumerical的交互方式,从手动拖拽的农耕时代,跃迁到自动化建模的工业文明。 ## 1. 为何脚本建模是必然选择 2019年Nature Photonics的一项研究显示,科研工作者在仿真工具上平均浪费37%的时间在重复性操作上。对于需要参数扫描的纳米光学结构设计,这个数字可能更高。手动创建10个不同尺寸的纳米柱阵列意味着: -
recommend-type

Java邮件解析任务中,如何安全高效地提取HTML邮件内容并避免硬编码、资源泄漏和类型转换异常?

<think>我们被要求优化一段Java代码,该代码用于处理邮件(特别是来自特定发件人的构建通知邮件)。代码的主要问题包括: 1. 重复获取邮件内容:在检查MIME类型后,多次调用`msg[i].getContent()`,这可能导致性能问题或流关闭异常。 2. 类型转换问题:直接将邮件内容转换为`Multipart`而不进行类型检查,可能引发`ClassCastException`。 3. 代码结构问题:逻辑嵌套过深,可读性差,且存在重复代码(如插入邮件详情的操作在两个地方都有)。 4. 硬编码和魔法值:例如在解析HTML表格时使用了硬编码的索引(如list3.get(10)),这容易因邮件
recommend-type

RH公司应收账款管理优化策略研究

资源摘要信息:"本文针对RH公司的应收账款管理问题进行了深入研究,并提出了改进策略。文章首先分析了应收账款在企业管理中的重要性,指出其对于提高企业竞争力、扩大销售和充分利用生产能力的作用。然后,以RH公司为例,探讨了公司应收账款管理的现状,并识别出合同管理、客户信用调查等方面的不足。在此基础上,文章提出了一系列改善措施,包括完善信用政策、改进业务流程、加强信用调查和提高账款回收力度。特别强调了建立专门的应收账款回收部门和流程的重要性,并建议在实际应用过程中进行持续优化。同时,文章也意识到企业面临复杂多变的内外部环境,因此提出的策略需要根据具体情况调整和优化。 针对财务管理领域的专业学生和从业者,本文提供了一个关于应收账款管理问题的案例研究,具有实际指导意义。文章还探讨了信用管理和征信体系在应收账款管理中的作用,强调了它们对于提升企业信用风险控制和市场竞争能力的重要性。通过对比国内外企业在应收账款管理上的差异,文章总结了适合中国企业实际环境的应收账款管理方法和策略。" 根据提供的文件内容,以下是详细的知识点: 1. 应收账款管理的重要性:应收账款作为企业的一项重要资产,其有效管理关系到企业的现金流、财务健康以及市场竞争力。不良的应收账款管理会导致资金链断裂、坏账损失增加等问题,严重影响企业的正常运营和长远发展。 2. 应收账款的信用风险:在信用交易日益频繁的商业环境中,企业必须对客户信用进行评估,以便采取合理的信用政策,降低信用风险。 3. 合同管理的薄弱环节:合同是应收账款管理的法律基础,严格的合同管理能够保障企业权益,减少因合同问题导致的应收账款风险。 4. 客户信用调查:了解客户的信用状况对于预测和控制应收账款风险至关重要。企业需要建立有效的客户信用调查机制,识别和筛选信用良好的客户。 5. 应收账款回收策略:企业应建立有效的账款回收机制,包括定期的账款跟进、逾期账款的催收等。同时,建立专门的应收账款回收部门可以提升回收效率。 6. 应收账款管理流程优化:通过改进企业内部管理流程,如简化审批流程、提高工作效率等措施,能够提升应收账款的管理效率。 7. 应收账款管理策略的调整和优化:由于企业的内外部环境复杂多变,因此制定的管理策略需要根据实际情况进行动态调整和持续优化。 8. 信用管理和征信体系的作用:建立和完善企业内部信用管理体系和征信体系,有助于企业更好地控制信用风险,并在市场竞争中占据有利地位。 9. 对比国内外应收账款管理实践:通过研究国内外企业在应收账款管理上的不同做法和经验,可以借鉴先进的管理理念和方法,提升国内企业的应收账款管理水平。 综上所述,本文深入探讨了应收账款管理的多个方面,为RH公司乃至其他同类型企业提供了应收账款管理的改进方向和策略,对于财务管理专业的教育和实践都具有重要的参考价值。
recommend-type

新手别慌!用BingPi-M2开发板带你5分钟搞懂Tina Linux SDK目录结构

# 新手别慌!用BingPi-M2开发板带你5分钟搞懂Tina Linux SDK目录结构 第一次拿到BingPi-M2开发板时,面对Tina Linux SDK里密密麻麻的文件夹,我完全不知道从哪下手。就像走进一个陌生的大仓库,每个货架上都堆满了工具和零件,却找不到操作手册。这种困惑持续了整整两天,直到我意识到——理解目录结构比死记硬背每个文件更重要。 ## 1. 为什么SDK目录结构如此重要 想象你正在组装一台复杂的模型飞机。如果所有零件都混在一个箱子里,你需要花大量时间寻找每个螺丝和面板。但如果有分门别类的隔层,标注着"机身部件"、"电子设备"、"紧固件",组装效率会成倍提升。Ti