当前位置: 首页 > news >正文

YOLOv8-ultralytics-8.2.103部分代码阅读笔记-tuner.py

tuner.py

ultralytics\engine\tuner.py

目录

tuner.py

1.所需的库和模块

2.class Tuner: 


1.所需的库和模块

# Ultralytics YOLO 🚀, AGPL-3.0 license# 模块提供用于对象检测、实例分割、图像分类、姿势估计和多对象跟踪的 Ultralytics YOLO 模型的超参数调整功能。
# 超参数调整是系统地搜索产生最佳模型性能的最佳超参数集的过程。这在 YOLO 等深度学习模型中尤为重要,因为超参数的微小变化可能会导致模型准确性和效率的显著差异。
"""
Module provides functionalities for hyperparameter tuning of the Ultralytics YOLO models for object detection, instance
segmentation, image classification, pose estimation, and multi-object tracking.Hyperparameter tuning is the process of systematically searching for the optimal set of hyperparameters
that yield the best model performance. This is particularly crucial in deep learning models like YOLO,
where small changes in hyperparameters can lead to significant differences in model accuracy and efficiency.Example:Tune hyperparameters for YOLOv8n on COCO8 at imgsz=640 and epochs=30 for 300 tuning iterations.```pythonfrom ultralytics import YOLOmodel = YOLO("yolov8n.pt")model.tune(data="coco8.yaml", epochs=10, iterations=300, optimizer="AdamW", plots=False, save=False, val=False)```
"""import random
import shutil
import subprocess
import timeimport numpy as np
import torchfrom ultralytics.cfg import get_cfg, get_save_dir
from ultralytics.utils import DEFAULT_CFG, LOGGER, callbacks, colorstr, remove_colorstr, yaml_print, yaml_save
from ultralytics.utils.plotting import plot_tune_results

2.class Tuner: 

# 这段代码是一个Python类的实现,名为 Tuner 。这个类是用于机器学习或深度学习中的超参数调整(tuning)。
# 定义了一个名为 Tuner 的类。
class Tuner:# 负责 YOLO 模型超参数调整的类。# 该类通过根据搜索空间对 YOLO 模型超参数进行变异并重新训练模型以评估其性能,在给定的迭代次数内演化 YOLO 模型超参数。# 方法:# _mutate(hyp: dict) -> dict :在 `self.space` 中指定的界限内变异给定的超参数。# __call__() :在多次迭代中执行超参数演化。"""Class responsible for hyperparameter tuning of YOLO models.The class evolves YOLO model hyperparameters over a given number of iterationsby mutating them according to the search space and retraining the model to evaluate their performance.Attributes:space (dict): Hyperparameter search space containing bounds and scaling factors for mutation.tune_dir (Path): Directory where evolution logs and results will be saved.tune_csv (Path): Path to the CSV file where evolution logs are saved.Methods:_mutate(hyp: dict) -> dict:Mutates the given hyperparameters within the bounds specified in `self.space`.__call__():Executes the hyperparameter evolution across multiple iterations.Example:Tune hyperparameters for YOLOv8n on COCO8 at imgsz=640 and epochs=30 for 300 tuning iterations.```pythonfrom ultralytics import YOLOmodel = YOLO("yolov8n.pt")model.tune(data="coco8.yaml", epochs=10, iterations=300, optimizer="AdamW", plots=False, save=False, val=False)```Tune with custom search space.```pythonfrom ultralytics import YOLOmodel = YOLO("yolov8n.pt")model.tune(space={key1: val1, key2: val2})  # custom search space dictionary```"""# 这段代码是 Tuner 类的构造函数( __init__ ),它初始化类的实例。# 这是构造函数的定义,它接受两个参数。# 1.args :这是一个具有默认值的参数。 args 代表一个字典,用于存储配置信息。如果调用 Tuner 类时没有提供 args 参数,那么它将使用 DEFAULT_CFG 作为默认值。# 2._callbacks :这是一个可选参数,其默认值为 None 。 _callbacks 用于传递一个回调函数列表或回调对象,这些回调将在调优过程中的特定点被调用。如果调用 Tuner 类时没有提供 _callbacks 参数,那么它将保持为 None ,后续可能会使用默认的回调函数。def __init__(self, args=DEFAULT_CFG, _callbacks=None):# 使用配置初始化调谐器。"""Initialize the Tuner with configurations.Args:args (dict, optional): Configuration for hyperparameter evolution."""# 这行代码尝试从 args 字典中移除并返回键为 "space" 的值,如果 "space" 不存在,则使用默认的字典。 self.space 是一个字典,包含了各种超参数的搜索空间,每个键对应一个元组,元组中包含了超参数的最小值、最大值和(可选的)增益值。self.space = args.pop("space", None) or {  # key: (min, max, gain(optional))# 超参数列表。# 'optimizer': tune.choice(['SGD', 'Adam', 'AdamW', 'NAdam', 'RAdam', 'RMSProp']),# 初始学习率的范围。"lr0": (1e-5, 1e-1),  # initial learning rate (i.e. SGD=1E-2, Adam=1E-3)# 最终OneCycleLR学习率的范围( lr0 乘以 lrf )。"lrf": (0.0001, 0.1),  # final OneCycleLR learning rate (lr0 * lrf)# SGD动量/Adam beta1的范围和增益。"momentum": (0.7, 0.98, 0.3),  # SGD momentum/Adam beta1# 优化器权重衰减的范围。"weight_decay": (0.0, 0.001),  # optimizer weight decay 5e-4# 预热周期的范围(可以是分数)。"warmup_epochs": (0.0, 5.0),  # warmup epochs (fractions ok)# 预热初始动量的范围。"warmup_momentum": (0.0, 0.95),  # warmup initial momentum# "box" 、 "cls" 、 "dfl" :不同损失函数的增益范围。"box": (1.0, 20.0),  # box loss gain"cls": (0.2, 4.0),  # cls loss gain (scale with pixels)"dfl": (0.4, 6.0),  # dfl loss gain# hsv_h" 、 "hsv_s" 、 "hsv_v" :HSV色彩空间中Hue、Saturation、Value的增强范围。"hsv_h": (0.0, 0.1),  # image HSV-Hue augmentation (fraction)"hsv_s": (0.0, 0.9),  # image HSV-Saturation augmentation (fraction)"hsv_v": (0.0, 0.9),  # image HSV-Value augmentation (fraction)# 图像旋转的范围。"degrees": (0.0, 45.0),  # image rotation (+/- deg)# 图像平移的范围。"translate": (0.0, 0.9),  # image translation (+/- fraction)# 图像缩放的范围。"scale": (0.0, 0.95),  # image scale (+/- gain)# 图像剪切的范围。"shear": (0.0, 10.0),  # image shear (+/- deg)# 图像透视变换的范围。"perspective": (0.0, 0.001),  # image perspective (+/- fraction), range 0-0.001# "flipud" 、 "fliplr" :图像上下翻转和左右翻转的概率。"flipud": (0.0, 1.0),  # image flip up-down (probability)"fliplr": (0.0, 1.0),  # image flip left-right (probability)# 图像通道BGR交换的概率。"bgr": (0.0, 1.0),  # image channel bgr (probability)# "mosaic" 、 "mixup" :图像混合(mosaic和mixup)的概率。"mosaic": (0.0, 1.0),  # image mixup (probability)"mixup": (0.0, 1.0),  # image mixup (probability)# 图像复制粘贴的概率。"copy_paste": (0.0, 1.0),  # segment copy-paste (probability)}# 这行代码调用 get_cfg 函数,传入 args 作为参数,并把返回的配置赋值给 self.args 。# def get_cfg(cfg: Union[str, Path, Dict, SimpleNamespace] = DEFAULT_CFG_DICT, overrides: Dict = None):# -> 从一个配置源(可以是字符串、路径、字典或 SimpleNamespace 对象)获取配置,并允许通过 overrides 字典来覆盖默认配置。返回一个 IterableSimpleNamespace 对象,它是一个可迭代的命名空间对象,其属性由 cfg 字典中的键值对初始化。# -> return IterableSimpleNamespace(**cfg)self.args = get_cfg(overrides=args)# 这行代码调用 get_save_dir 函数,传入 self.args 和 name="tune" 作为参数,并把返回的目录路径赋值给 self.tune_dir 。# def get_save_dir(args, name=None): -> 获取或创建一个用于保存特定数据(如模型权重、日志等)的目录路径。返回保存目录的路径。返回一个 Path 对象,表示保存目录的路径。 -> return Path(save_dir)self.tune_dir = get_save_dir(self.args, name="tune")# 这行代码将 self.tune_dir 与 "tune_results.csv" 拼接,得到 self.tune_csv 的路径,用于存储调优结果。self.tune_csv = self.tune_dir / "tune_results.csv"# 这行代码将 _callbacks 赋值给 self.callbacks ,如果 _callbacks 为 None ,则调用 callbacks.get_default_callbacks() 获取默认的回调函数列表。# def get_default_callbacks():# -> 返回默认的回调函数列表。返回一个 defaultdict 对象,它使用 list 作为默认工厂函数,这意味着如果访问的键不存在,将会创建一个空列表作为该键的值。# -> return defaultdict(list, deepcopy(default_callbacks))self.callbacks = _callbacks or callbacks.get_default_callbacks()# 这行代码将 "Tuner: " 字符串通过 colorstr 函数处理后赋值给 self.prefix , colorstr 函数用于给字符串添加颜色的。# def colorstr(*input):# -> 函数通过遍历 args 中的每个元素(颜色或样式),从 colors 字典中获取对应的ANSI转义序列,并将其与传入的 string 字符串连接起来。最后,它还会添加一个 colors["end"] 序列,用于重置终端的颜色和样式到默认状态。# -> return "".join(colors[x] for x in args) + f"{string}" + colors["end"]self.prefix = colorstr("Tuner: ")# 回调函数是一种以函数对象作为参数并在完成某个特定任务后调用的函数。在编程中,回调函数是一种常用的设计模式,它允许程序在某个事件或条件触发时执行额外的代码。这种模式增强了代码的灵活性和模块化,因为它允许用户或开发者在不修改现有代码的情况下,插入自定义的行为。# 回调函数的特点 :# 参数传递 :回调函数作为参数传递给另一个函数。# 延迟执行 :回调函数不是立即执行的,而是在特定事件发生时由其他代码调用。# 事件处理 :常用于事件驱动编程,例如用户界面事件(如按钮点击)或系统事件(如文件读写完成)。# 异步操作 :在异步编程中,回调函数用于处理操作完成后的结果或错误。# 回调函数的使用场景 :# 事件监听 :在GUI编程中,回调函数用于响应用户的输入或操作。# 异步编程 :在Node.js或Python的异步IO操作中,回调函数用于处理异步操作的结果。# 测试和断言 :在单元测试中,回调函数可以用于验证异步操作的结果。# 插件和扩展 :在支持插件的软件中,回调函数允许插件介入主程序的执行流程。# 装饰器 :在装饰器模式中,回调函数用于在执行主要逻辑前后添加额外的行为。# 这行代码调用 callbacks.add_integration_callbacks 函数,传入 self 作为参数,用于添加集成回调。# def add_integration_callbacks(instance): -> 向一个实例添加集成的回调函数。这些回调函数通常用于训练过程中的不同阶段,例如记录训练日志、跟踪实验进度等。callbacks.add_integration_callbacks(self)# 这行代码使用 LOGGER 对象的 info 方法记录一条信息日志,包含了初始化 Tuner 实例的信息和一些提示信息。LOGGER.info(f"{self.prefix}Initialized Tuner instance with 'tune_dir={self.tune_dir}'\n"    # {self.prefix}使用“tune_dir={self.tune_dir}”初始化 Tuner 实例。f"{self.prefix}💡 Learn about tuning at https://docs.ultralytics.com/guides/hyperparameter-tuning"    # {self.prefix}💡 了解有关调整的信息,请访问 https://docs.ultralytics.com/guides/hyperparameter-tuning。)# 这个构造函数的主要作用是初始化 Tuner 类的实例,设置超参数搜索空间、配置、调优结果存储路径、回调函数,并记录日志。# 这段代码定义了一个名为 _mutate 的方法,它是 Tuner 类的一部分。这个方法用于生成一个新的超参数组合,通过变异(mutate)已有的超参数。# 参数定义。# 1.self :指向类实例本身的引用。# 2.parent="single" :选择父代的策略,可以是"single"(单个最佳)或"weighted"(加权组合)。# 3.n=5 :考虑用于生成新超参数组合的前n个最佳结果的数量。# 4.mutation=0.8 :变异的概率,即每个超参数有多大几率被变异。# 5.sigma=0.2 :变异的强度,控制随机扰动的幅度。def _mutate(self, parent="single", n=5, mutation=0.8, sigma=0.2):# 根据 `self.space` 中指定的边界和缩放因子对超参数进行变异。"""Mutates the hyperparameters based on bounds and scaling factors specified in `self.space`.Args:parent (str): Parent selection method: 'single' or 'weighted'.n (int): Number of parents to consider.mutation (float): Probability of a parameter mutation in any given iteration.sigma (float): Standard deviation for Gaussian random number generator.Returns:(dict): A dictionary containing mutated hyperparameters."""# 这段代码是 _mutate 方法中处理CSV文件存在时的逻辑部分。它的目的是从已有的调优结果中选择最佳的超参数组合(父代),然后基于这些父代进行变异以生成新的超参数组合。# 检查CSV文件是否存在。检查 self.tune_csv 路径指向的CSV文件是否存在。if self.tune_csv.exists():  # if CSV file exists: select best hyps and mutate# Select parent(s)# 加载数据。使用 numpy 的 loadtxt 函数加载CSV文件中的数据, ndmin=2 确保结果至少是二维数组, delimiter="," 指定了CSV的分隔符, skiprows=1 跳过第一行(通常是标题行)。x = np.loadtxt(self.tune_csv, ndmin=2, delimiter=",", skiprows=1)# 提取适应度值。  提取第一列的值,假设这一列包含了适应度评分。fitness = x[:, 0]  # first column# 确定考虑的结果数量。 确保 n 参数不超过已有结果的数量。n = min(n, len(x))  # number of previous results to consider# 选择最佳结果。 对适应度值进行降序排序,并选择前 n 个最佳结果。x = x[np.argsort(-fitness)][:n]  # top n mutations# 计算权重。计算每个结果的权重,确保权重和大于0, 1e-6 是为了防止除以0的情况。w = x[:, 0] - x[:, 0].min() + 1e-6  # weights (sum > 0)# 选择父代。# 如果 parent 参数为"single"或者结果数量为1,使用加权随机选择一个父代。if parent == "single" or len(x) == 1:# x = x[random.randint(0, n - 1)]  # random selection# 使用 random.choices 函数根据权重 w 从 n 个结果中随机选择一个。x = x[random.choices(range(n), weights=w)[0]]  # weighted selection# 如果 parent 参数为"weighted",则计算加权组合作为父代。elif parent == "weighted":# 计算所有结果的加权平均值,其中 w.reshape(n, 1) 将权重转换为列向量,以便与结果矩阵 x 进行点乘。x = (x * w.reshape(n, 1)).sum(0) / w.sum()  # weighted combination# 这段代码的目的是从一个已有的调优结果集合中,根据适应度评分选择最佳的超参数组合,并根据选择策略(单个最佳或加权组合)来确定父代,以便后续进行变异操作。# 这段代码是 _mutate 方法中负责变异操作的部分。它生成一个新的超参数组合,通过随机扰动已有的超参数(父代)。# Mutate# 设置随机数生成器。将 np.random 模块赋值给变量 r ,用于后续的随机数生成。r = np.random  # method# 设置随机数生成器的种子,确保每次运行代码时生成的随机数序列不同,这里使用当前时间的整数部分作为种子。r.seed(int(time.time()))# 计算增益值。# 这行代码遍历 self.space 字典,如果某个超参数的元组长度为3,则取第三个元素作为增益值;否则,默认增益值为1.0。g = np.array([v[2] if len(v) == 3 else 1.0 for k, v in self.space.items()])  # gains 0-1# 初始化变异向量。# 获取超参数空间的大小。ng = len(self.space)# 初始化一个全为1的向量,用于存储每个超参数的变异倍数。v = np.ones(ng)# 变异操作。# 循环直到 v 中至少有一个元素不等于1,以确保至少有一个超参数发生了变异,防止生成与父代完全相同的超参数组合。while all(v == 1):  # mutate until a change occurs (prevent duplicates)# 这行代码执行实际的变异操作 :# r.random(ng) < mutation 生成一个随机数数组,小于 mutation 参数值的位置将被标记为True,表示该位置的超参数将被变异。# r.randn(ng) 生成一个标准正态分布的随机数数组,用于控制变异的方向。# r.random() * sigma 生成一个随机数,用于控制变异的幅度, sigma 参数控制变异的强度。# g * ... + 1 将上述结果与增益值相乘并加1,确保变异后的值至少为1。# .clip(0.3, 3.0) 将结果限制在0.3到3.0的范围内,防止变异后的值过大或过小。v = (g * (r.random(ng) < mutation) * r.randn(ng) * r.random() * sigma + 1).clip(0.3, 3.0)# 生成新的超参数组合。# 这行代码根据变异后的倍数 v 和父代的超参数值 x 生成新的超参数组合。这里 x[i + 1] 是因为 x 数组的第一列是适应度值,所以超参数值从第二列开始。hyp = {k: float(x[i + 1] * v[i]) for i, k in enumerate(self.space.keys())}# 默认超参数组合。# 如果 self.tune_csv 文件不存在,即没有之前的调优结果,那么 hyp 将直接从 self.args 中获取默认的超参数值。else:hyp = {k: getattr(self.args, k) for k in self.space.keys()}# 这段代码实现了超参数的变异过程,通过随机扰动和增益调整来探索新的超参数组合,以期找到性能更优的模型配置。# Constrain to limits# 这段代码是 _mutate 方法中对生成的新超参数组合进行约束处理的部分。它确保每个超参数的值都在预定义的范围内,并且将值四舍五入到指定的有效数字。# 遍历超参数空间。这行代码遍历 self.space 字典中的每一项, k 是超参数的名称, v 是对应的元组,包含超参数的最小值、最大值和(可选的)增益值。for k, v in self.space.items():# 应用下界约束。这行代码确保 hyp 字典中对应超参数 k 的值不小于 v 元组中的第一个元素,即超参数的最小值。hyp[k] = max(hyp[k], v[0])  # lower limit# 应用上界约束。这行代码确保 hyp 字典中对应超参数 k 的值不大于 v 元组中的第二个元素,即超参数的最大值。hyp[k] = min(hyp[k], v[1])  # upper limit# 四舍五入到指定有效数字。这行代码将 hyp 字典中对应超参数 k 的值四舍五入到5位有效数字。hyp[k] = round(hyp[k], 5)  # significant digits# 返回处理后的超参数组合。这行代码返回经过约束处理和四舍五入的新超参数组合。return hyp# 这段代码的目的是确保新生成的超参数组合在合理的范围内,并且数值表示上是精确的。通过这种方式,可以避免生成无效的超参数值,同时保持数值的简洁性和可读性。# 这个方法是超参数调优过程中的关键步骤,通过变异和选择机制探索新的超参数组合,以期找到性能更优的模型配置。# 这段代码定义了 Tuner 类的特殊方法 __call__ ,它允许类的实例像函数一样被调用。这个方法执行模型的训练和超参数调优的过程。# 参数定义。# 1.self :指向类实例本身的引用。# 2.model=None :模型参数,可以传递模型实例,但在这段代码中没有使用。# 3.iterations=10 :调优过程中要进行的训练迭代次数。# 4.cleanup=True :是否在每次迭代后清理权重文件,以节省存储空间。def __call__(self, model=None, iterations=10, cleanup=True):# 调用 Tuner 实例时执行超参数演化过程。# 此方法遍历迭代次数,在每次迭代中执行以下步骤:# 1. 加载现有超参数或初始化新超参数。# 2. 使用 `mutate` 方法变异超参数。# 3. 使用变异超参数训练 YOLO 模型。# 4. 将适应度得分和变异超参数记录到 CSV 文件中。# 注意:# 该方法利用 `self.tune_csv` Path 对象读取和记录超参数和适应度得分。确保在 Tuner 实例中正确设置此路径。"""Executes the hyperparameter evolution process when the Tuner instance is called.This method iterates through the number of iterations, performing the following steps in each iteration:1. Load the existing hyperparameters or initialize new ones.2. Mutate the hyperparameters using the `mutate` method.3. Train a YOLO model with the mutated hyperparameters.4. Log the fitness score and mutated hyperparameters to a CSV file.Args:model (Model): A pre-initialized YOLO model to be used for training.iterations (int): The number of generations to run the evolution for.cleanup (bool): Whether to delete iteration weights to reduce storage space used during tuning.Note:The method utilizes the `self.tune_csv` Path object to read and log hyperparameters and fitness scores.Ensure this path is set correctly in the Tuner instance."""# 这段代码是  __call__  方法的一部分,它负责初始化调优过程,并在每次迭代中变异超参数、训练模型,并保存相关的目录和权重文件。# 初始化计时器。记录调优过程开始的时间。t0 = time.time()# 初始化最佳结果变量。初始化变量以存储 最佳模型保存目录 和 最佳度量指标 。best_save_dir, best_metrics = None, None# 创建权重目录。在 self.tune_dir 路径下创建一个名为 weights 的目录,用于存储每次迭代生成的模型权重。 parents=True 表示如果父目录不存在则创建, exist_ok=True 表示如果目录已存在则不抛出异常。(self.tune_dir / "weights").mkdir(parents=True, exist_ok=True)# 迭代调优。循环进行指定次数的迭代, iterations 是方法的一个参数,表示要进行多少次调优迭代。for i in range(iterations):# Mutate hyperparameters# 变异超参数。调用 _mutate 方法生成新的超参数组合。mutated_hyp = self._mutate()# 记录当前迭代的超参数。使用 LOGGER 记录 当前迭代的编号 和 使用的超参数组合 。LOGGER.info(f"{self.prefix}Starting iteration {i + 1}/{iterations} with hyperparameters: {mutated_hyp}")    # {self.prefix} 使用超参数开始迭代 {i + 1}/{iterations}:{mutated_hyp}。# 准备训练参数。# 初始化一个空字典,用于存储本次迭代的度量指标。metrics = {}# vars(object)# vars() 函数在 Python 中用于获取对象的属性字典。这个字典包含了对象的大部分属性,但不包括方法和其他一些特殊的属性。对于用户自定义的对象, vars() 返回的字典包含了对象的 __dict__ 属性,这是一个包含对象所有属性的字典。# 参数说明 :# object :要获取属性字典的对象。# 返回值 :# 返回指定对象的属性字典。# 注意事项 :# vars() 对于内置类型(如 int 、 float 、 list 等)返回的是一个包含魔术方法和特殊属性的字典,这些属性通常是不可访问的。# 对于自定义对象, vars() 返回的是对象的 __dict__ 属性,如果对象没有定义 __dict__ ,则可能返回一个空字典或者抛出 TypeError 。# 在 Python 3 中, vars() 也可以用于获取内置函数的全局变量字典。# vars() 函数是一个内置函数,通常用于调试和访问对象的内部状态,但在处理复杂对象时应该谨慎使用,因为直接修改对象的属性可能会导致不可预测的行为。# 将原始参数 self.args 和变异后的超参数 mutated_hyp 合并,形成完整的训练参数。train_args = {**vars(self.args), **mutated_hyp}# 调用 get_cfg 函数获取训练配置,并使用 get_save_dir 函数获取本次迭代的保存目录。# def get_save_dir(args, name=None): -> 获取或创建一个用于保存特定数据(如模型权重、日志等)的目录路径。返回保存目录的路径。返回一个 Path 对象,表示保存目录的路径。 -> return Path(save_dir)# def get_cfg(cfg: Union[str, Path, Dict, SimpleNamespace] = DEFAULT_CFG_DICT, overrides: Dict = None):# -> 从一个配置源(可以是字符串、路径、字典或 SimpleNamespace 对象)获取配置,并允许通过 overrides 字典来覆盖默认配置。返回一个 IterableSimpleNamespace 对象,它是一个可迭代的命名空间对象,其属性由 cfg 字典中的键值对初始化。# -> return IterableSimpleNamespace(**cfg)save_dir = get_save_dir(get_cfg(train_args))# 在本次迭代的保存目录下创建一个 weights 子目录,用于存储本次迭代的模型权重文件。weights_dir = save_dir / "weights"# 这段代码为每次迭代的模型训练和超参数调优做准备,包括创建必要的目录、生成新的超参数组合、记录日志以及准备训练参数。接下来的步骤将包括实际的训练模型、保存结果和选择最佳模型。# 这段代码是 __call__ 方法中负责训练模型的部分,它使用变异后的超参数来训练YOLO模型,并处理可能出现的异常。try:# Train YOLO model with mutated hyperparameters (run in subprocess to avoid dataloader hang)# 构建训练命令。构建一个包含 yolo train 命令和超参数的训练命令列表。这里使用列表推导式将 train_args 字典中的每个键值对转换为 key=value 格式的字符串,并展开到命令列表中。cmd = ["yolo", "train", *(f"{k}={v}" for k, v in train_args.items())]# 在子进程中运行训练命令。使用  subprocess.run 在子进程中执行训练命令。 check=True 参数表示如果命令执行失败(即返回码非0),则抛出异常。 returncode 属性存储命令的返回码。return_code = subprocess.run(cmd, check=True).returncode# 确定检查点文件。确定要加载的检查点文件。如果存在 best.pt 文件,则使用它;否则,使用 last.pt 文件。ckpt_file = weights_dir / ("best.pt" if (weights_dir / "best.pt").exists() else "last.pt")# 加载训练度量指标。使用PyTorch的 torch.load 函数加载检查点文件,并获取其中的 train_metrics 字典,该字典包含本次训练的度量指标。metrics = torch.load(ckpt_file)["train_metrics"]# 断言训练成功。断言命令的返回码为0,即训练成功。如果训练失败,将抛出异常。assert return_code == 0, "training failed"    # 训练失败。# 异常处理。# 捕获训练过程中的任何异常。except Exception as e:# 如果发生异常,使用 LOGGER 记录警告信息,包括迭代编号和异常信息。LOGGER.warning(f"WARNING ❌️ training failure for hyperparameter tuning iteration {i + 1}\n{e}")    # 警告❌️超参数调整迭代 {i + 1}\n{e} 训练失败。# 这段代码确保了即使训练过程中出现异常,也能被捕获并记录下来,同时避免了数据加载器挂起的问题,这是通过在子进程中运行训练命令实现的。如果训练失败,它还会清理并记录相关的错误信息,以便进一步分析和调试。# 数据加载器挂起是指在使用数据加载器(如PyTorch中的 DataLoader )进行数据加载和预处理时,程序出现停滞或无响应的状态。这种情况可能由多种原因引起,以下是一些常见的原因 :# 多线程/多进程问题 :# 如果 DataLoader 的 num_workers 参数设置不当,可能会导致数据加载器创建过多的子进程,从而消耗过多内存或导致资源竞争,使得数据加载器无法继续执行。# 资源限制 :# 系统资源不足,如CPU、内存或磁盘I/O能力不足,可能导致数据加载器无法及时读取或处理数据。# 数据问题 :# 数据集中可能包含损坏或格式不正确的数据,导致数据加载器在处理时卡住。# 数据预处理步骤可能存在错误或异常,如数据类型不匹配、维度错误等。# I/O瓶颈 :# 数据存储介质(如硬盘)的读写速度慢,或者网络延迟(如果数据存储在远程服务器上),可能导致数据加载器等待数据读取。# Python对象的Copy-On-Write(COW)机制 :# 在多进程环境中,Python的某些对象可能会触发COW机制,导致不必要的内存拷贝,增加内存消耗和延迟。# 系统负载过高 :# 系统可能因为运行了过多的任务或服务,导致负载过高,使得数据加载器无法获得足够的资源来执行。# 死锁或竞态条件 :# 在多线程或多进程环境中,不当的资源共享可能导致死锁或竞态条件,使得数据加载器无法继续执行。# 解决数据加载器挂起问题的常用方法包括 :# 调整 num_workers 参数 :# num_workers 参数控制着 DataLoader 创建的子进程数量。如果设置过大,可能会导致内存消耗过快,引起内存溢出;如果设置过小,可能会导致CPU无法及时向GPU提供数据。通常,这个值应该根据机器的CPU核心数和内存容量来合理设置。# 优化数据预处理 :# 确保数据预处理步骤没有错误或异常,比如对图像进行变换时使用了正确的参数。优化数据预处理流程可以减少内存占用和提高数据加载效率。# 检查数据集完整性 :# 确保数据集中没有损坏的文件、错误的路径或标签。在加载数据前,可以先对数据进行检查和清理,确保数据的完整性和正确性。# 使用 pin_memory :# 将 DataLoader 中的 pin_memory 参数设置为 True ,这可以加速数据从CPU到GPU的传输,但要求数据类型为tensors、maps或包含tensor的可迭代对象。# 避免使用Python内置的可变类型对象 :# 在多进程环境中,Python内置的可变类型对象(如list、dict)可能会触发copy-on-write机制,导致不必要的内存拷贝。可以使用non-refcounted对象(如pandas, numpy, pyarrow, torch tensor)来避免。# 管理共享资源 :# 使用 multiprocessing.Manager 来管理共享资源,如列表和字典,以避免多进程中的数据竞争问题。# 检查系统资源限制 :# 确保系统有足够的资源供 DataLoader 使用,如内存和磁盘空间。如果系统资源不足,可能会导致工作进程无法正常运行。# 错误日志分析 :# 当 DataLoader 工作进程退出时,通常会在错误日志中打印出具体的异常信息。查看错误日志是定位问题的关键。# 避免竞态条件和死锁 :# 在并发编程中,使用互斥机制(如锁)来确保共享资源在同一时间只被一个线程访问,避免不必要的共享,减少竞态条件和死锁的发生。# 减小 batch_size :# 降低每次迭代所需要的内存,通过减小 batch_size 来减少内存压力。# 数据加载器异常处理 :# 在迭代过程中添加异常处理逻辑,捕获如“StopIteration”等异常,并在异常发生时采取适当的操作。# 合理分配资源 :# 合理地分配和释放资源,避免资源的浪费和过度竞争。# 通过上述方法,可以有效地解决数据加载器挂起的问题,提高数据加载的效率和稳定性。# Save results and mutated_hyp to CSV# 这段代码负责将每次迭代的结果和变异后的超参数组合保存到CSV文件中。# 计算适应度值。从 metrics 字典中获取 fitness 键对应的值,如果不存在则默认为0.0。适应度值是评估模型性能的一个指标。fitness = metrics.get("fitness", 0.0)# 构建日志行。创建一个列表 log_row ,首先包含四舍五入到5位小数的适应度值,然后追加变异后的超参数值。这里使用列表推导式从 mutated_hyp 字典中获取每个超参数的值。log_row = [round(fitness, 5)] + [mutated_hyp[k] for k in self.space.keys()]# 检查文件是否存在并写入表头。# 检查 self.tune_csv 路径指向的CSV文件是否存在。如果不存在,则创建一个包含列名的字符串 headers ,列名包括 fitness 和 self.space 中的所有超参数名称,列名之间用逗号分隔,并在末尾添加换行符。headers = "" if self.tune_csv.exists() else (",".join(["fitness"] + list(self.space.keys())) + "\n")# 写入CSV文件。# 以追加模式( "a" )打开CSV文件,如果文件不存在则创建。with open(self.tune_csv, "a") as f:# map(function, iterable, ...)# Python中的 map() 函数是一个内置函数,用于将一个函数应用于一个可迭代对象(如列表、元组等)的每个元素,并返回一个新的迭代器。# 参数 :# function :一个函数,它将被应用于 iterable 中的每个元素。# iterable :一个或多个可迭代对象,其元素将被传递给 function 。# 返回值 :# map() 函数返回一个迭代器,该迭代器生成将 function 应用于 iterable 中每个元素后的结果。# map() 也可以接受多个可迭代对象,并将函数应用于对应元素。# 将 headers 和 log_row 列表转换为字符串后用逗号分隔,然后写入文件。 map(str, log_row) 确保列表中的所有元素都被转换为字符串格式,以便写入CSV文件。# map(str, log_row) 是一个Python表达式,它使用内置的 map 函数将 log_row 列表中的每个元素转换为字符串类型。# map(str, log_row) 会对 log_row 列表中的每个元素应用 str 函数,即将列表中的每个元素(可能是整数、浮点数或其他类型)转换为字符串。这样做是为了确保所有的数据都能被正确地写入CSV文件,因为CSV文件中的数据通常以文本格式存储。f.write(headers + ",".join(map(str, log_row)) + "\n")# 这段代码确保了每次迭代的结果都被记录和保存,便于后续分析和比较不同超参数组合的性能。如果CSV文件是新创建的,它还会包含列名作为文件的首行。# Get best results# 这段代码是 __call__ 方法中用于获取最佳调优结果的部分。它从CSV文件中加载所有迭代的结果,找到具有最佳适应度值的迭代,并根据条件保存最佳模型的权重文件。# 加载CSV文件中的数据。使用NumPy的 loadtxt 函数加载CSV文件中的数据。 ndmin=2 确保结果至少是二维数组, delimiter="," 指定了CSV的分隔符, skiprows=1 跳过第一行(通常是标题行)。x = np.loadtxt(self.tune_csv, ndmin=2, delimiter=",", skiprows=1)# 提取适应度值。提取第一列的值,假设这一列包含了适应度评分。fitness = x[:, 0]  # first column# 找到最佳适应度值的索引。使用NumPy的 argmax 函数找到适应度值最大的索引,即最佳迭代。best_idx = fitness.argmax()# 检查最佳迭代是否是当前迭代。如果最佳迭代的索引等于当前迭代的索引 i ,则 best_is_current 为 True 。best_is_current = best_idx == i# 保存最佳模型。# 如果当前迭代是最佳迭代( best_is_current 为True),则执行以下操作。if best_is_current:# 保存最佳模型的保存目录。best_save_dir = save_dir# 将最佳度量指标四舍五入到5位小数,并保存。best_metrics = {k: round(v, 5) for k, v in metrics.items()}# 将当前迭代的权重文件复制到  self.tune_dir / "weights"  目录下。for ckpt in weights_dir.glob("*.pt"):shutil.copy2(ckpt, self.tune_dir / "weights")# 清理权重目录。# 如果当前迭代不是最佳迭代,并且 cleanup 参数为True,则执行以下操作。elif cleanup:# 删除当前迭代的权重目录,以减少存储空间的使用。 ignore_errors=True 参数表示如果目录不存在或删除过程中出现错误,则忽略这些错误。shutil.rmtree(weights_dir, ignore_errors=True)  # remove iteration weights/ dir to reduce storage space# 这段代码确保了在调优过程中,只有最佳模型的权重文件被保存,而其他迭代的权重文件在迭代结束后被清理,从而节省存储空间。同时,它还记录了最佳迭代的度量指标和保存目录,以便后续分析和模型部署。# 这段代码是 __call__ 方法中用于绘制调优结果图表、保存和打印调优结果的部分。# Plot tune results# 绘制调优结果图表。调用 plot_tune_results 函数,传入 self.tune_csv 作为参数,该函数负责读取CSV文件并绘制调优结果的图表。plot_tune_results(self.tune_csv)# Save and print tune results# 构建日志头部信息。# 构建一个包含调优过程信息的字符串,包括 当前迭代次数 、 总迭代次数 、 已耗时 、 结果保存位置 、 最佳适应度值 、 最佳适应度指标 、 最佳模型保存位置 和 最佳超参数的信息 。header = (f'{self.prefix}{i + 1}/{iterations} iterations complete ✅ ({time.time() - t0:.2f}s)\n'    # '{self.prefix}{i + 1}/{iterations} 次迭代完成✅ ({time.time() - t0:.2f}s)。# def colorstr(*input):# -> 函数通过遍历 args 中的每个元素(颜色或样式),从 colors 字典中获取对应的ANSI转义序列,并将其与传入的 string 字符串连接起来。最后,它还会添加一个 colors["end"] 序列,用于重置终端的颜色和样式到默认状态。# -> return "".join(colors[x] for x in args) + f"{string}" + colors["end"]f'{self.prefix}Results saved to {colorstr("bold", self.tune_dir)}\n'    # {self.prefix}结果保存至 {colorstr("bold", self.tune_dir)}。f'{self.prefix}Best fitness={fitness[best_idx]} observed at iteration {best_idx + 1}\n'    # {self.prefix}在迭代 {best_idx + 1} 时观察到的最佳适应度 = {fitness[best_idx]}。f'{self.prefix}Best fitness metrics are {best_metrics}\n'    # {self.prefix}最佳适应度指标为 {best_metrics}。f'{self.prefix}Best fitness model is {best_save_dir}\n'    # {self.prefix}最佳适应度模型为 {best_save_dir}。f'{self.prefix}Best fitness hyperparameters are printed below.\n'    # {self.prefix}最佳适应度超参数打印如下。)# 记录日志。使用 LOGGER 记录构建的头部信息。LOGGER.info("\n" + header)# 保存最佳超参数。从加载的数据 x 中提取最佳适应度值对应的超参数值,并构建一个字典 data 。data = {k: float(x[best_idx, i + 1]) for i, k in enumerate(self.space.keys())}# 保存最佳超参数到YAML文件。# 调用 yaml_save 函数,将最佳超参数和头部信息保存到YAML文件中。 remove_colorstr 函数用于移除字符串中的颜色代码, header.replace(self.prefix, "# ") 用于替换日志头部中的前缀。# def yaml_save(file="data.yaml", data=None, header=""): -> 将 Python 数据结构保存为 YAML 格式的文件。yaml_save(self.tune_dir / "best_hyperparameters.yaml",data=data,# def remove_colorstr(input_string):# -> 从输入字符串中移除所有的 ANSI 转义序列,这些序列通常用于在终端中设置文本颜色和样式。将 input_string 中所有匹配的 ANSI 转义序列替换为空字符串(即移除它们)。# -> return ansi_escape.sub("", input_string)header=remove_colorstr(header.replace(self.prefix, "# ")) + "\n",)# 打印YAML文件内容。调用 yaml_print 函数,打印YAML文件的内容,以便用户查看最佳超参数。# def yaml_print(yaml_file: Union[str, Path, dict]) -> None: -> 是打印 YAML 文件的内容。yaml_print(self.tune_dir / "best_hyperparameters.yaml")# 这段代码确保了调优过程中的关键信息被记录下来,并且最佳超参数被保存和打印出来,方便用户分析和进一步使用。 yaml_save 和 yaml_print 函数是自定义的,用于处理YAML文件的保存和打印。# 这个方法实现了一个完整的超参数调优流程,包括变异、训练、结果记录和最佳结果的选择。通过这种方式,可以系统地探索超参数空间,以找到最佳的模型配置。

相关文章:

YOLOv8-ultralytics-8.2.103部分代码阅读笔记-tuner.py

tuner.py ultralytics\engine\tuner.py 目录 tuner.py 1.所需的库和模块 2.class Tuner: 1.所需的库和模块 # Ultralytics YOLO &#x1f680;, AGPL-3.0 license# 模块提供用于对象检测、实例分割、图像分类、姿势估计和多对象跟踪的 Ultralytics YOLO 模型的超参数调整…...

【数据结构】堆的概念、结构、模拟实现以及应用

本篇我们来介绍一下数据结构中的堆。 1.堆的概念及结构 1&#xff09;堆是一颗完全二叉树。 2&#xff09;堆又分为大堆和小堆&#xff0c;大堆就是树里面任何一个父节点都大于子节点&#xff0c;所以根节点是最大值&#xff1b;小堆就是树里面任何一个父节点都小于子节点&am…...

推送(push)项目到gitlab

文章目录 1、git init1.1、在当前目录中显示隐藏文件&#xff1a;1.2、查看已有的远程仓库1.3、确保你的本地机器已经生成了 SSH 密钥&#xff1a;1.4、将生成的公钥文件&#xff08;通常位于 ~/.ssh/id_rsa.pub&#xff09;复制到 GitLab 的 SSH 设置中&#xff1a;1.5、测试 …...

springboot/ssm宠物商城网站系统Java代码web项目宠物用品购物论坛源码

springboot/ssm宠物商城网站系统Java代码web项目宠物用品购物论坛源码 基于springboot(可改ssm)htmlvue项目 开发语言&#xff1a;Java 框架&#xff1a;springboot/可改ssm vue JDK版本&#xff1a;JDK1.8&#xff08;或11&#xff09; 服务器&#xff1a;tomcat 数据库&…...

前端基础的讲解-JS(22)

什么是JSON&#xff1f; 1.json 是一种轻量级的数据交换格式 简单来说&#xff1a;json 就是一种在各个编程语言中流通的数据格式&#xff0c;负责不同编程语言中的数据传递和交互。 类似于&#xff1a; 国际通用语言 - 英语 中国 56 个民族不同地区的通用语言 - 普通话 …...

zerotier实现内网穿透(访问内网服务器)

moo 内网穿透工具 实用工具&#xff1a;zerotier 目录 内网穿透工具 Windows下zerotier安装 ubuntu系统下的zerotier安装 使用moon加速 Windows下zerotier安装 有了网络之后&#xff0c;会给你一个网络id&#xff0c;这个网络id是非常重要的&#xff0c;其它设备要加入…...

python语言中怎么调用不同级文件夹中数据文件

python语言中怎么调用文件夹中数据文件 python 怎么调用同一级文件夹中数据1. **读取同一级文件夹中的数据文件&#xff08;如 .txt, .csv, .json 等&#xff09;**示例&#xff1a; 2. **导入同一级文件夹中的 Python 模块**3. **使用相对路径导入模块**4. **使用 os.path 或 …...

spring事务源码解析

1 引入 在企业级应用开发中&#xff0c;事务管理 是确保数据一致性和完整性的重要手段。而在 Spring 框架中&#xff0c;事务管理提供了高度抽象和灵活的实现&#xff0c;开发者只需通过简单的注解或配置即可轻松实现复杂的事务逻辑。然而&#xff0c;Spring 事务背后的实现机…...

【每日刷题】Day165

【每日刷题】Day165 &#x1f955;个人主页&#xff1a;开敲&#x1f349; &#x1f525;所属专栏&#xff1a;每日刷题&#x1f34d; &#x1f33c;文章目录&#x1f33c; 1. LCR 092. 将字符串翻转到单调递增 - 力扣&#xff08;LeetCode&#xff09; 2. 424. 替换后的最长…...

基于51单片机的智能公交车报站系统GPS定位语音播报智能安全检测人数统计

功能描述 1.LCD12864可显示当前年月日&#xff0c;星期&#xff0c;时间&#xff0c; 当前站名&#xff0c;经纬度&#xff0c;是否连接GPS&#xff0c;自动/手动模式&#xff0c; 2.自带GPS定位&#xff0c;可实时显示经纬度&#xff1b; 3.通过DS1302时钟芯片&#xff0c;获…...

计算机网络安全 —— 实体鉴别与生成大随机数

一、实体鉴别# ​ 实体鉴别&#xff08;经常简称为鉴别&#xff09;就是一方验证另一方身份的技术。一个实体可以是人、客户/服务器进程等。这里仅讨论如何鉴别通信对端 实体的身份&#xff0c;即验证正在通信的对方确实是所认为的通信实体&#xff0c;而不是其他的假冒者。进…...

Vue3+Pinia 状态管理持久化

一、Pinia 简介 &#x1f396;️Pinia 起始于 2019 年 11 月左右的一次实验&#xff0c;其目的是设计一个拥有组合式 API 的 Vue 状态管理库。Vue3VitePinia 新三剑客逐渐替代了Vue2WebpackVuex 了&#xff0c;性能啥的各方面吊打。 1.1 什么是状态管理&#xff1f; &#x1f…...

开源项目:轻型图像分割 unet_lite

DataBall 助力快速掌握数据集的信息和使用方式&#xff0c;会员享有 百种数据集&#xff0c;持续增加中。 需要更多数据资源和技术解决方案&#xff0c;知识星球&#xff1a; “DataBall - X 数据球(free)” -------------------------------------------------------------…...

C# 向上取整多种实现方法

1.使用 Math.Ceiling 方法&#xff1a; 在 C# 中&#xff0c;可以利用 System.Math 类下的 Math.Ceiling 方法来实现向上取整。它接受一个 double 或 decimal 类型的参数&#xff0c;并返回大于或等于该参数的最小整数&#xff08;以 double 或 decimal 类型表示&#xff09;。…...

Linux 权限及管理

目录 一、Linux权限 1、概念 2、超级用户和普通用户的相关操作 a. 添加用户&#xff0c;删除用户 b. 超级用户和普通用户的切换 c. sduo提权以及白名单设置 二、Linux权限管理 1、文件访问者的分类 2、文件访问类型和权限 a. 文件类型 b. 基本权限 3、文件权限值…...

【JVM】JVM基础教程(一)

目录 初识JVM JVM是什么&#xff1f; JVM的功能 解释、即时编译和运行 内存管理 常见的JVM JVM虚拟机规范 HotSpot的发展历程 JVM的组成 字节码文件详解 应用场景 以正确姿势打开字节码文件 ​编辑字节码文件的组成 基本信息 Magic魔数 主副版本号 常量池 接口…...

企业国内外网络互联方案全解析

面对国内市场日益饱和的现状&#xff0c;企业纷纷将目光投向海外&#xff0c;而实现国内外网络的高效互联&#xff0c;则成为支撑其跨国业务顺利运行的关键。本文将为您详细介绍几种实现国内外网络互联的有效策略&#xff0c;助您轻松应对全球化挑战。 有些企业选择使用虚拟专用…...

【优选算法 位运算】位运算算法入门详解:位运算小专题

判定字符是否唯一 题目解析 算法原理 解法一 &#xff1a;哈希数组 从前往后扫描字符串&#xff0c;把扫描到的字符先进行判断&#xff0c;如果对应的 val 0 &#xff0c;则放入哈希表中&#xff0c;否则返回 false&#xff0c;知道扫描完整个字符&#xff1b;时间…...

大文件分块上传后端服务器

一、背景&#xff1a; 后台系统需要上传大文件、大视频等数据&#xff0c;耗时过长&#xff0c;接口等待超时&#xff0c;故需优化通过前端多线程分片方式进行文件上传&#xff0c;显著提升上传速度。 二、流程&#xff1a; 前端逻辑&#xff1a; 前端使用分片技术&#xff…...

perl Window安装教程

perl Window安装教程 下载地址 https://platform.activestate.com/tangxing806/ActivePerl-5.28/distributions 运行state-remote-installer.exe 按下图截图步骤 检查perl版本 参考文献&#xff1a; perl安装教程...

Scrcpy投影之后为什么声音在电脑端显示?

关于安卓设备和电脑端扬声器优先级 在使用安卓设备与电脑进行某些连接操作&#xff08;比如通过 adb 相关工具交互时&#xff09;&#xff0c;确实存在音频输出的优先级选择情况。通常情况下&#xff0c;可能默认音频会输出到电脑端&#xff08;比如通过投屏等相关操作连接后&…...

2025年山东省职业院校技能大赛“信息安全管理与评估”(山东省) 任务书

2025年山东省职业院校技能大赛“信息安全管理与评估”(山东省 任务书 模块一网络平台搭建与设备安全防护任务1&#xff1a;网络平台搭建 &#xff08;50分&#xff09;任务2&#xff1a;网络安全设备配置与防护&#xff08;250分&#xff09; 模块二网络安全事件响应、数字取证…...

java+ssm+mysql收纳培训网

项目介绍&#xff1a; 使用javassmmysql开发的收纳视频培训网&#xff0c;系统包含超级管理员&#xff0c;系统管理员、培训师、用户角色&#xff0c;功能如下&#xff1a; 超级管理员&#xff1a;管理员管理&#xff1b;用户管理&#xff08;培训师、用户&#xff09;&#…...

多表查询-概述内连接外连接子查询

一.数据准备&#xff1a; 1.部门表&#xff1a; 代码&#xff1a; -- 部门管理 create table tb_dept (id int unsigned primary key auto_increment comment 主键ID,name varchar(10) not null unique comment 部门名称,create_time datetime not null c…...

H5游戏出海如何获得更多增长机会?

海外H5小游戏的崛起给了国内众多中小厂商出海发展的机会&#xff0c;开发者如何在海外市场获得更多的增长机会&#xff1f;#APP出海# H5游戏如何在海外获得核心用户&#xff1f; HTML5游戏的开发与运营者们首先可以利用量多质高的HTML5游戏&#xff0c;维持海外用户粘性&…...

element plus的表单校验,明明输入内容了,但提示红字还是会显示着

下拉框的不隐藏&#xff0c;可能是 trigger为blur的原因&#xff0c;改为change即可 const rules reactive({name: [{ required: true, message: "请输入名称", trigger: "blur" }],price: [{ required: true, message: "请输入价格", trigger…...

MobaXterm Sessions 批量录入导入,会话批量添加,解决导入配置中文乱码

一、创建表格 创建 Excel 表格&#xff0c;将服务器信息写入表格 二、写入文件 新建 list.txt 文件将表格中的服务器信息复制粘贴进去 三、修改脚本 这是你需要修改的变量&#xff0c;其他变量不需要动 # 登录用户 ssh_userroot # 目录名称 folder_name资源池四、执行脚本 …...

Vue项目中的权限控制实践与方案详解

在现代前端开发中&#xff0c;权限控制是一个不可或缺的重要环节。一个完善的权限控制系统不仅能够保护应用的安全性&#xff0c;还能为不同角色的用户提供更好的使用体验。让我们深入探讨Vue项目中权限控制的实现方案和最佳实践。 权限控制本质上是对用户操作的一种限制&…...

C++11新特性之线程std::thread

C std::thread的定义和功能 std::thread是C11引入的标准库类&#xff0c;用于创建和管理线程。通过std::thread&#xff0c;程序可以并发执行多个任务&#xff0c;从而提高效率。 功能与作用&#xff1a; 创建线程&#xff1a;可以启动一个线程执行某个函数或任务。管理线程…...

西门子S7-200 SMART PLC在钢铁行业中的应用

西门子S7-200 SMART PLC在钢铁行业中的应用&#xff0c;主要得益于其强大的功能、简易的编程方式以及卓越的稳定性&#xff0c;这些特点使得它能够在钢铁行业的自动化控制中发挥重要作用。 以下是对西门子S7-200 SMART PLC在钢铁行业中应用的详细分析&#xff1a; 一、钢铁行业…...

Amazon SageMaker 和 Amazon Bedrock 有什么区别

Amazon SageMaker 和 Amazon Bedrock 有什么区别 文章目录 Amazon SageMaker 和 Amazon Bedrock 有什么区别1.服务定位和主要功能区别Amazon SageMakerAmazon Bedrock 2. 适用场景Amazon SageMakerAmazon Bedrock 3. 用户群体Amazon SageMakerAmazon Bedrock 4. 开发和部署流程…...

自动驾驶数据集的应用与思考

数据作为新型生产要素&#xff0c;是数字化、网络化、智能化的基础&#xff0c;是互联网时代的“石油”“煤炭”&#xff0c;掌握数据对于企业而言是能够持续生存和发展的不竭动力&#xff0c;对于需要大量数据训练自动驾驶系统的企业而言更是如此。 而随着激光雷达、毫米波雷…...

Python 中的 threading 模块和 multiprocessing 模块有何区别?

在Python编程中&#xff0c;threading 和 multiprocessing 模块都提供了并行处理的能力&#xff0c;但它们实现的方式以及适用的场景是不同的。 下面将详细解释两者的区别&#xff0c;并给出一些日常开发中的使用建议。 Threading&#xff08;线程&#xff09; threading 模…...

网络安全之常见风险端口(Common Risk Ports for Network Security)

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 本人主要分享计算机核心技…...

思科模拟器路由器的基本配置

一、实验目的 了解路由器的作用掌握路由器的基本配置方法 3、掌握路由器模块的使用和互连方式 二、实验环境 2811路由器一台&#xff0c;计算机两台&#xff0c;Console配置线一根&#xff0c;网线若干&#xff1b;本实验拓扑图如图8-1所示&#xff1b;计算机IP地址规划如表8-…...

使用ssh免密登录实现自动化部署rsync+nfs+lsync(脚本)

单机一键部署sshrsyncnfslsync 执行准备 主机信息 主机角色外网IP内网IP主机名nfs、lsync10.0.0.31176.16.1.31nfs客户端10.0.0.7176.16.1.7web01rsync、nfs10.0.0.41172.16.1.41backup 秘钥信息 #web01可以免密连接nfs和backup [rootweb01 ~]# ssh-keygen [rootweb01 ~]#…...

第425场周赛:最小正和子数组、重排子字符串以形成目标字符串、最小数组和、移除边之后的权重最大和

Q1、[简单] 最小正和子数组 1、题目描述 给你一个整数数组 nums 和 两个 整数 l 和 r。你的任务是找到一个长度在 l 和 r 之间&#xff08;包含&#xff09;且和大于 0 的 子数组 的 最小 和。 返回满足条件的子数组的 最小 和。如果不存在这样的子数组&#xff0c;则返回 -…...

常见矩阵分析法(BCG、GE、IE、SPACE、TOWS、优先、战略优先级、安索夫、风险矩阵):如何通过系统化方法助力战略决策与数据驱动决策

在快速变化的商业环境中&#xff0c;企业决策者面临着诸多复杂的选择与挑战。矩阵分析法作为战略分析的重要工具&#xff0c;能够系统化地分析企业的内外部环境&#xff0c;帮助管理层做出更加科学、合理的决策。本文将全面解析常见的矩阵分析法&#xff0c;并探讨它们在数据驱…...

沐风老师3DMAX摄相机阵列插件使用方法

3DMAX摄相机阵列插件&#xff0c;从网格对象或样条线的顶点法线快速创建摄相机阵列。该插件从网格的顶点或样条线的节点获取每个摄影机的位置和方向。 3DMAX摄相机阵列插件支持目前3dMax主流的物理相机、标准相机、VRay物理相机。 【版本要求】 3dMax 2015及更高版本 【安装方…...

踩坑日记-win电脑怎么登录虚拟机上部署的phpmyadmin?

前请提要 电脑win11&#xff0c;安装centOS7虚拟机&#xff0c;部署了linux 安装了docker和一些镜像容器&#xff0c;准备开发项目 访问 phpMyAdmin 时无法打开页面 访问 http://0.0.0.0:8899/ 时&#xff0c;提示无法访问此页面。0.0.0.0 表示 Docker 容器将监听宿主机上的…...

手写观察者模式

本人是JavaScript开发者&#xff0c;以下的示例也是以Javascript举例来说明的。 一、概念 当对象间存在一对多的关系时&#xff0c;使用观察者模式。当被观察的对象发生变化时&#xff0c;其所有的观察者都会收到通知并进行相应的操作。 二、具体例子 比如说&#xff0c;学…...

20.LMAX-DDD的极致性能架构

学习视频来源&#xff1a;DDD独家秘籍视频合集 https://space.bilibili.com/24690212/channel/collectiondetail?sid1940048&ctype0 文章目录 历史起源架构目标架构要素 时序对比传统时序事件溯源时序LMAX时序 单线程非阻塞异步IO&#xff08;reactor&#xff09;多线程单…...

axios的引入和基本使用

一、axios的引入 使用 pnpm add axios 二、使用axios 三、axios的使用方法补充 axios除了直接使用它实例上的方法&#xff0c;还可以通过配置的方式进行使用axios({})&#xff0c;传入一个对象&#xff0c;这个对象可以有如下属性&#xff1a; url&#xff08;字符串&#…...

14--VulnHub 靶机系列之Gear_Of_War#1

靶机下载地址&#xff1a; https://download.vulnhub.com/gearsofwar/Gear_Of_War%231.ova kali机(VMware)两张网卡&#xff1a; 第一张网卡使用VM0(桥接模式)-桥接到VirtualBox Host-Only Ethernet Adapter 第二张网卡使用NAT模式--用于访问网络 信息收集 kali机eth0的I…...

Python + OpenCV 系列:图像阈值处理

文章目录 引言 1. 阈值处理的基本概念2. OpenCV 中的阈值处理3. 常见的阈值类型3.1 二值化阈值3.2 反向二值化阈值3.3 截断阈值3.4 平滑阈值 4. 自适应阈值5. Otsu’s 阈值法6. 阈值处理的应用场景7. 总结 引言 图像阈值处理是计算机视觉和图像处理中一种非常基础而重要的技术…...

el-thee懒加载删除某条数据 ,el-thee懒加载重置,el-thee刷新某个节点

一、懒加载的tree已经全部展开&#xff0c;外部点击删除的时候不需要重新展开点击获取下一层数据 <template> <el-treeref"tree":data"treeData":props"defaultProps"render-after-expandhighlight-currentlazy:expand-on-click-node&q…...

如何在 JavaScript 中设置定时器?

在 JavaScript 中&#xff0c;设置定时器通常使用两个内置的函数&#xff1a;setTimeout() 和 setInterval()。它们允许你在指定的时间延迟后执行某个函数或者以某个间隔反复执行某个函数。下面&#xff0c;我将结合实际项目代码示例讲解如何使用它们。 1. setTimeout() — 延…...

LDR6500:音频双C支持,数字与模拟的完美结合

在当今数字化快速发展的时代&#xff0c;音频设备的兼容性和性能成为了用户关注的重点。LDR6500&#xff0c;作为乐得瑞科技精心研发的USB Power Delivery&#xff08;PD&#xff09;协议芯片&#xff0c;凭借其卓越的性能和广泛的应用兼容性&#xff0c;为音频设备领域带来了新…...

小型项目的数据库适合选用ClickHouse吗?

我们与MySQL比较。 MySQL 1. 传统的业务系统 用户管理订单处理产品信息企业基础数据 2. 特点 行存储&#xff0c;适合频繁的增删改事务支持完善小规模数据查询性能好数据一致性保证生态系统成熟&#xff0c;运维简单 ClickHouse 1. 数据分析场景 日志分析用户行为分析实…...

MySQL--》如何在SQL中巧妙运用函数与约束,优化数据处理与验证?

目录 函数使用 字符串函数 数值函数 日期函数 流程函数 约束 函数使用 函数是指一段可以直接被另一段程序调用的程序或代码&#xff0c;在mysql当中有许多常见的内置函数&#xff0c;接下来开始对这些内置函数及其作用进行简单的讲解和使用&#xff1a; 字符串函数 my…...