YOLOv10-1.1部分代码阅读笔记-tuner.py
tuner.py
ultralytics\engine\tuner.py
目录
tuner.py
1.所需的库和模块
2.class Tuner:
1.所需的库和模块
# Ultralytics YOLO 🚀, AGPL-3.0 license# 此模块提供用于对象检测、实例分割、图像分类、姿势估计和多对象跟踪的 Ultralytics YOLO 模型的超参数调整功能。
# 超参数调整是系统地搜索产生最佳模型性能的最佳超参数集的过程。这在 YOLO 等深度学习模型中尤为重要,因为超参数的微小变化可能会导致模型准确性和效率的显著差异。
# 示例:
# 在 COCO8 上,在 imgsz=640 和 epochs=30 处调整 YOLOv8n 的超参数,进行 300 次调整迭代。
# from ultralytics import YOLO# model = YOLO('yolov8n.pt')
# model.tune(data='coco8.yaml', epochs=10, iterations=300, optimizer='AdamW', plots=False, save=False, val=False)
"""
This 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:
# 这段代码定义了一个名为 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__ ,用于设置超参数调优的基本配置和环境。# 这行代码定义了 Tuner 类的初始化方法 __init__ ,接受两个参数。# 1.args :默认配置,类型可以是字典、 SimpleNamespace 或其他支持的配置格式。默认值为 DEFAULT_CFG ,可能是预定义的默认配置。# 2._callbacks :回调函数,用于扩展功能,如记录日志或执行额外操作。默认值为 None 。def __init__(self, args=DEFAULT_CFG, _callbacks=None):# 使用配置初始化调谐器。"""Initialize the Tuner with configurations.Args:args (dict, optional): Configuration for hyperparameter evolution."""# 这段代码初始化了一个名为 self.space 的属性,用于定义超参数的搜索空间。它尝试从 args 中提取键为 "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 。这是优化器的初始学习率,通常用于控制模型训练的收敛速度。"lr0": (1e-5, 1e-1), # initial learning rate (i.e. SGD=1E-2, Adam=1E-3)# 定义了最终学习率因子 lrf 的范围,从 0.0001 到 0.1 。这是 OneCycleLR 调度器中最终学习率的因子,用于调整学习率的衰减。"lrf": (0.0001, 0.1), # final OneCycleLR learning rate (lr0 * lrf)# 定义了动量参数 momentum 的范围,从 0.7 到 0.98 ,并设置增益为 0.3 。动量参数用于加速梯度下降的收敛,减少震荡。"momentum": (0.7, 0.98, 0.3), # SGD momentum/Adam beta1# 定义了权重衰减参数 weight_decay 的范围,从 0.0 到 0.001 。权重衰减用于正则化,防止模型过拟合。"weight_decay": (0.0, 0.001), # optimizer weight decay 5e-4# 定义了预热阶段的轮数 warmup_epochs 的范围,从 0.0 到 5.0 。预热阶段用于逐渐增加学习率,避免初始阶段的梯度爆炸。"warmup_epochs": (0.0, 5.0), # warmup epochs (fractions ok)# 定义了预热阶段的初始动量 warmup_momentum 的范围,从 0.0 到 0.95 。"warmup_momentum": (0.0, 0.95), # warmup initial momentum# 定义了框损失权重 box 的范围,从 1.0 到 20.0 。框损失权重用于调整目标检测任务中框的损失。"box": (1.0, 20.0), # box loss gain# 定义了分类损失权重 cls 的范围,从 0.2 到 4.0 。分类损失权重用于调整分类任务中的损失。"cls": (0.2, 4.0), # cls loss gain (scale with pixels)# 定义了 分布焦点损失权重 dfl 的范围,从 0.4 到 6.0 。"dfl": (0.4, 6.0), # dfl loss gain# 定义了 HSV 色调增强的范围,从 0.0 到 0.1 。HSV 色调增强用于数据增强,通过调整图像的色调来增加数据多样性。"hsv_h": (0.0, 0.1), # image HSV-Hue augmentation (fraction)# 定义了 HSV 饱和度增强的范围,从 0.0 到 0.9 。"hsv_s": (0.0, 0.9), # image HSV-Saturation augmentation (fraction)# 定义了 HSV 亮度增强的范围,从 0.0 到 0.9 。"hsv_v": (0.0, 0.9), # image HSV-Value augmentation (fraction)# 定义了图像旋转角度的范围,从 0.0 到 45.0 度。"degrees": (0.0, 45.0), # image rotation (+/- deg)# 定义了图像平移的范围,从 0.0 到 0.9 (以图像尺寸的分数表示)。"translate": (0.0, 0.9), # image translation (+/- fraction)# 定义了图像缩放的范围,从 0.0 到 0.95 。"scale": (0.0, 0.95), # image scale (+/- gain)# 定义了图像剪切角度的范围,从 0.0 到 10.0 度。"shear": (0.0, 10.0), # image shear (+/- deg)# 定义了图像透视变换的范围,从 0.0 到 0.001 。"perspective": (0.0, 0.001), # image perspective (+/- fraction), range 0-0.001# 定义了图像上下翻转的概率范围,从 0.0 到 1.0 。"flipud": (0.0, 1.0), # image flip up-down (probability)# 定义了图像左右翻转的概率范围,从 0.0 到 1.0 。"fliplr": (0.0, 1.0), # image flip left-right (probability)# 定义了图像通道顺序为 BGR 的概率范围,从 0.0 到 1.0 。"bgr": (0.0, 1.0), # image channel bgr (probability)# 定义了 Mosaic 数据增强的概率范围,从 0.0 到 1.0 。"mosaic": (0.0, 1.0), # image mixup (probability)# 定义了 Mixup 数据增强的概率范围,从 0.0 到 1.0 。"mixup": (0.0, 1.0), # image mixup (probability)# 定义了 Copy-Paste 数据增强的概率范围,从 0.0 到 1.0 。"copy_paste": (0.0, 1.0), # segment copy-paste (probability)}# 这段代码是 Tuner 类初始化方法的一部分,主要负责设置调优器的基本配置、保存路径和日志信息。# 这段代码调用 get_cfg 函数,将传入的 args 参数(可能是一个字典或其他配置格式)处理为一个统一的配置对象。# def get_cfg(cfg: Union[str, Path, Dict, SimpleNamespace] = DEFAULT_CFG_DICT, overrides: Dict = None):# -> 用于处理和返回一个配置对象。它支持从多种输入类型(如字符串、路径、字典或 SimpleNamespace )加载配置,并允许用户通过覆盖( overrides )来修改默认配置。将最终的配置字典转换为 IterableSimpleNamespace 对象并返回。# -> return IterableSimpleNamespace(**cfg)self.args = get_cfg(overrides=args)# 调用 get_save_dir 函数,根 据配置对象 self.args 和指定的名称 "tune" ,生成一个 保存调优结果的目录路径 。该路径将用于存储调优过程中的中间结果和最终输出。# def get_save_dir(args, name=None): -> 根据训练、验证或预测的参数返回一个保存目录( save_dir )。返回生成的保存目录路径,确保返回值是一个 Path 对象。 -> return Path(save_dir)self.tune_dir = get_save_dir(self.args, name="tune")# 定义了 调优结果的保存路径 ,文件名为 "tune_results.csv" 。该文件将用于记录每次调优迭代的超参数和性能指标。self.tune_csv = self.tune_dir / "tune_results.csv"# 设置回调函数,如果传入了 _callbacks 参数,则直接使用该参数。 如果未传入 _callbacks ,则调用 callbacks.get_default_callbacks() 获取默认的回调函数。回调函数通常用于扩展功能,例如在调优过程中记录日志、保存中间结果或执行其他自定义操作。self.callbacks = _callbacks or callbacks.get_default_callbacks()# 定义了一个 日志前缀 self.prefix ,用于在日志输出中标识调优器的相关信息。 colorstr 函数的作用是为字符串添加颜色(为了在终端中更醒目地显示)。self.prefix = colorstr("Tuner: ")# 调用 callbacks.add_integration_callbacks 方法,将当前调优器实例 self 添加到回调函数中。这是为了在调优过程中调用与外部系统(如日志记录工具、监控系统等)集成的回调。callbacks.add_integration_callbacks(self)# 使用 LOGGER.info 记录初始化信息。LOGGER.info(f"{self.prefix}Initialized Tuner instance with 'tune_dir={self.tune_dir}'\n" # {self.prefix}使用“tune_dir={self.tune_dir}。f"{self.prefix}💡 Learn about tuning at https://docs.ultralytics.com/guides/hyperparameter-tuning" # {self.prefix}💡 初始化 Tuner 实例,了解有关调整的信息,请访问 https://docs.ultralytics.com/guides/hyperparameter-tuning。)# 这段代码的主要功能是完成 Tuner 类的初始化,配置处理:通过 get_cfg 函数将输入的配置参数标准化为统一的配置对象。保存路径设置:生成保存调优结果的目录和文件路径。回调函数初始化:设置回调函数,用于扩展调优器的功能。日志记录:记录调优器的初始化信息,并提供学习资源的链接。这种设计使得调优器的初始化过程清晰且灵活,同时为后续的调优操作提供了必要的配置和路径支持。# 这段代码定义了 Tuner 类的 _mutate 方法,用于生成新的超参数组合。该方法基于遗传算法的思想,通过选择、突变和约束操作来探索超参数空间。# 定义了 _mutate 方法,接受以下参数 :# 1.parent :选择父代的方式,可以是 "single" (单个父代)或 "weighted" (加权组合)。# 2.n :考虑的父代数量,默认为 5。# 3.mutation :突变概率,默认为 0.8。# 4.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."""# 检查是否已经存在保存调优结果的 CSV 文件( self.tune_csv )。如果存在,说明已经有历史调优结果,可以基于这些结果进行选择和突变。if self.tune_csv.exists(): # if CSV file exists: select best hyps and mutate# Select parent(s)# 从 CSV 文件中加载历史调优结果。 np.loadtxt 用于读取 CSV 文件,跳过第一行(通常是表头),并将数据加载为 NumPy 数组。x = np.loadtxt(self.tune_csv, ndmin=2, delimiter=",", skiprows=1)# 提取 第一列 作为 性能指标 ( fitness ),用于评估每组超参数的性能。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# 计算权重,用于加权选择。权重基于性能指标的差异,确保权重之和大于零。w = x[:, 0] - x[:, 0].min() + 1e-6 # weights (sum > 0)# 如果选择方式为 "single" 或只有一组历史结果,则选择单个父代。if parent == "single" or len(x) == 1:# x = x[random.randint(0, n - 1)] # random selection# random.choices(population, weights=None, cum_weights=None, k=1)# random.choices 是 Python 标准库 random 模块中的一个函数,它用于从给定的序列中随机选择元素,可以有放回地选择多次,也可以指定每个元素被选择的概率。# population :一个序列,表示可供选择的元素集合。# weights :(可选)一个与 population 中元素数量相同的序列,表示每个元素被选择的相对概率。# cum_weights :(可选)一个与 population 中元素数量相同的序列,表示累积概率。这在创建加权随机选择时非常有用,其中每个元素的选择概率取决于前面所有元素的累积概率。# k :(可选)一个整数,表示需要选择的元素数量。# 返回值 :# 返回一个列表,包含从 population 中随机选择的 k 个元素。# 功能 :# random.choices 函数允许你从 population 中选择多个元素,可以是有放回的选择。如果提供了 weights 或 cum_weights ,则选择会根据这些权重进行加权,使得某些元素有更高的概率被选中。# 注意事项 :# 如果同时提供了 weights 和 cum_weights , random.choices 将使用 weights 而忽略 cum_weights 。# k 的值可以大于 population 的长度,这意味着可能会选择重复的元素。# 如果没有提供 weights 或 cum_weights ,则所有元素被选择的概率相等。# 从历史结果中加权选择一个父代。权重基于性能指标的差异,性能越高的结果被选中的概率越大。x = x[random.choices(range(n), weights=w)[0]] # weighted selection# 如果选择方式为 "weighted" ,则基于权重对多组父代进行加权组合。elif parent == "weighted":# 计算加权组合的父代。通过将每组父代的超参数乘以权重并求和,得到新的父代。x = (x * w.reshape(n, 1)).sum(0) / w.sum() # weighted combination# Mutate# 初始化随机数生成器。r = np.random # method# 设置随机数生成器的种子,基于当前时间戳。r.seed(int(time.time()))# 提取每个超参数的 增益值 (如果定义了增益)。增益用于控制突变的强度。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)# 循环直到至少有一个超参数发生变化,避免生成重复的超参数组合。while all(v == 1): # mutate until a change occurs (prevent duplicates)# 对父代的超参数进行突变。使用随机数生成器生成突变值。突变值基于正态分布,乘以增益和标准差。确保突变后的值在合理范围内(通过 clip 方法)。v = (g * (r.random(ng) < mutation) * r.randn(ng) * r.random() * sigma + 1).clip(0.3, 3.0)# 将突变后的超参数值存储到字典中。每个超参数值是父代值乘以突变因子。hyp = {k: float(x[i + 1] * v[i]) for i, k in enumerate(self.space.keys())}# 如果不存在历史调优结果,则直接使用默认配置作为初始超参数。else:# 从默认配置中提取超参数值。hyp = {k: getattr(self.args, k) for k in self.space.keys()}# Constrain to limits# 遍历超参数空间。for k, v in self.space.items():# 确保超参数值不低于最小值。hyp[k] = max(hyp[k], v[0]) # lower limit# 确保超参数值不高于最大值。hyp[k] = min(hyp[k], v[1]) # upper limit# 将超参数值四舍五入到小数点后 5 位。hyp[k] = round(hyp[k], 5) # significant digits# 返回突变后的超参数字典。return hyp# _mutate 方法实现了基于遗传算法的超参数突变过程,选择父代:从历史调优结果中选择性能最高的父代,支持单个选择或加权组合。突变:对父代的超参数进行随机扰动,基于正态分布生成突变值,并控制突变强度。约束:确保突变后的超参数值在预定义的范围内。返回结果:返回突变后的超参数字典。这种方法结合了历史调优结果和随机性,能够在超参数空间中高效地探索新的组合,从而找到更优的超参数配置。# 这段代码定义了 Tuner 类的 __call__ 方法,用于执行超参数调优过程。它通过多次迭代,每次生成一组新的超参数,训练模型,并记录结果,最终选择性能最佳的超参数组合。# 定义了 __call__ 方法,允许 Tuner 实例像函数一样被调用。参数包括 :# 1.model :模型对象(可选)。# 2.iterations :调优迭代次数,默认为 10。# 3.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."""# 记录调优开始的时间,用于后续计算总耗时。t0 = time.time()# 初始化变量,用于存储 最佳模型的保存路径 和 性能指标 。best_save_dir, best_metrics = None, None# 创建保存模型权重的目录( self.tune_dir/weights ),确保目录存在。(self.tune_dir / "weights").mkdir(parents=True, exist_ok=True)# 开始调优迭代,循环次数由 iterations 参数决定。for i in range(iterations):# Mutate hyperparameters# 调用 _mutate 方法生成一组新的超参数。mutated_hyp = self._mutate()# 记录当前迭代的信息,包括迭代编号和使用的超参数。LOGGER.info(f"{self.prefix}Starting iteration {i + 1}/{iterations} with hyperparameters: {mutated_hyp}") # {self.prefix} 使用超参数开始迭代 {i + 1}/{iterations}:{mutated_hyp} 。# 初始化一个空字典,用于 存储当前迭代的性能指标 。metrics = {}# 将默认配置和突变后的超参数合并为训练参数。train_args = {**vars(self.args), **mutated_hyp}# 根据训练参数生成保存当前迭代结果的目录。save_dir = get_save_dir(get_cfg(train_args))# 定义保存权重的路径。weights_dir = save_dir / "weights"# 开始一个 try 块,尝试执行训练过程。try:# Train YOLO model with mutated hyperparameters (run in subprocess to avoid dataloader hang)# 构造训练命令,包括模型训练的参数。cmd = ["yolo", "train", *(f"{k}={v}" for k, v in train_args.items())]# 通过子进程运行训练命令,避免因数据加载器阻塞主线程。 check=True 确保命令执行失败时抛出异常。# 这行代码使用了 Python 的 subprocess 模块来运行一个外部命令,并捕获其返回码( returncode )。# subprocess.run :subprocess.run 是 Python 标准库 subprocess 模块中的一个函数,用于运行外部命令。它接受以下参数 :# cmd :要运行的命令,通常是一个字符串或字符串列表。如果是字符串列表,每个元素代表命令的一个参数。# check :一个布尔值,指定是否在命令失败时抛出异常。如果 check=True ,当命令的返回码非零时,会抛出 subprocess.CalledProcessError 异常。# cmd 参数 : cmd 是一个列表,表示要运行的命令及其参数。例如: cmd = ["yolo", "train", "lr0=0.01", "epochs=50"] 这表示运行 yolo train lr0=0.01 epochs=50 命令。# .returncode : subprocess.run 返回一个 CompletedProcess 对象,其中包含以下属性。returncode 命令的返回码。返回码为 0 表示命令成功执行,非 0 表示失败。 stdout 和 stderr,标准输出和标准错误的内容(如果捕获了)。# 在这行代码中, .returncode 用于 获取命令的返回码 ,并将其赋值给 return_code 变量。# 这行代码的作用是。使用 subprocess.run 运行外部命令 cmd 。如果命令失败(返回码非 0),抛出异常。如果命令成功,获取返回码并将其存储到 return_code 变量中。这种用法非常适合在 Python 中运行外部工具或脚本,并根据返回码判断命令是否成功执行。return_code = subprocess.run(cmd, check=True).returncode# 确定检查点文件的路径,优先选择 best.pt ,如果不存在则选择 last.pt 。# 这行代码的作用是确定检查点文件(checkpoint file)的路径,通常用于加载模型训练过程中保存的最佳或最后一个权重文件。代码通过检查文件是否存在来动态选择文件路径。# weights_dir : weights_dir 是一个路径对象(可能是 pathlib.Path 类型),表示保存模型权重的目录。例如: weights_dir = Path("/path/to/weights") 。# weights_dir / "best.pt" :通过 weights_dir / "best.pt" 构造了一个路径对象,表示目录下名为 best.pt 的文件。 / 是 pathlib.Path 的路径拼接操作符。# .exists() :调用 .exists() 方法检查 best.pt 文件是否存在。如果文件存在,返回 True ;否则返回 False 。# "best.pt" if (weights_dir / "best.pt").exists() else "last.pt" :这是一个三元表达式,用于动态选择文件名。如果 best.pt 文件存在,则选择 "best.pt" 。 如果 best.pt 文件不存在,则选择 "last.pt" 。# 最终路径 :最终, ckpt_file 是一个路径对象,表示最终选择的检查点文件路径。它可能是 : weights_dir / "best.pt" (如果 best.pt 存在), weights_dir / "last.pt" (如果 best.pt 不存在)。# 这行代码的作用是动态选择模型权重文件。优先选择 best.pt 文件(如果存在),因为它通常表示训练过程中性能最佳的模型权重。如果 best.pt 文件不存在,则退回到 last.pt 文件,它表示训练过程中的最后一个模型权重。这种设计确保了代码的灵活性和健壮性,能够在不同情况下正确加载模型权重。ckpt_file = weights_dir / ("best.pt" if (weights_dir / "best.pt").exists() else "last.pt")# 从检查点文件中加载训练指标。# torch.load : torch.load 是 PyTorch 提供的函数,用于加载保存在文件中的对象(如模型权重、训练指标等)。它支持加载 .pt 或 .pth 格式的文件。 ckpt_file :文件路径,表示要加载的检查点文件。它应该是一个字符串或 Path 对象。 torch.load 返回加载的对象。加载的内容取决于保存时的内容。例如,如果保存的是模型权重,返回值将是一个字典,键是模型参数的名称,值是对应的张量。# ckpt_file :ckpt_file 是一个路径对象(可能是 pathlib.Path 或字符串),表示检查点文件的路径。例如: ckpt_file = Path("/path/to/weights/best.pt") 。# torch.load(ckpt_file) :调用 torch.load 加载检查点文件的内容。假设文件中保存了多个对象(如模型权重、训练指标等),加载后返回一个字典或其他数据结构。# ["train_metrics"] :从加载的内容中提取键为 "train_metrics" 的值。这假设检查点文件中保存了一个字典,且字典中包含键 "train_metrics" 。# train_metrics :通常是一个字典,包含训练过程中记录的性能指标,例如:# {# "fitness": 0.85,# "loss": 0.12,# "accuracy": 0.95,# ...# }# 这行代码的作用是。使用 torch.load 加载检查点文件的内容。提取键为 "train_metrics" 的值,通常是一个包含训练指标的字典。这种设计使得代码能够快速加载和访问训练过程中记录的性能指标,方便后续分析和调优。metrics = torch.load(ckpt_file)["train_metrics"]# 确保训练过程成功完成。assert return_code == 0, "training failed" # 训练失败。# 捕获训练过程中可能出现的异常。except Exception as e:# 记录训练失败的警告信息。LOGGER.warning(f"WARNING ❌️ training failure for hyperparameter tuning iteration {i + 1}\n{e}") # 警告❌️超参数调整迭代 {i + 1}\n{e} 训练失败。# Save results and mutated_hyp to CSV# 从性能指标中提取 fitness 值,如果没有则默认为 0.0。fitness = metrics.get("fitness", 0.0)# 构造一行日志,包含当前迭代的 fitness 值和超参数。# 这行代码的作用是构造一个 日志行 ( log_row ),用于记录当前迭代的 性能指标 ( fitness )和突变后的 超参数 ( mutated_hyp )。这些数据将被写入日志文件或 CSV 文件中,便于后续分析和可视化。# [round(fitness, 5)] :这部分代码将当前迭代的性能指标( fitness )四舍五入到小数点后 5 位,并将其作为列表的第一个元素。 fitness 是一个浮点数,表示当前超参数组合的性能(例如,模型的准确率或损失值)。# [mutated_hyp[k] for k in self.space.keys()] :这部分代码是一个列表推导式,用于从突变后的超参数字典( mutated_hyp )中提取所有超参数的值,并按 self.space 中定义的顺序排列。# self.space.keys() :获取超参数空间中所有超参数的键(名称)。# mutated_hyp[k] :从突变后的超参数字典中提取每个超参数的值。# + 操作符 : + 操作符用于将两个列表拼接在一起。因此, log_row 是一个列表,包含 四舍五入后的 fitness 值。 按顺序排列的突变后超参数值。# 这行代码的作用是构造一个日志行,包含以下内容。性能指标:当前迭代的 fitness 值,四舍五入到小数点后 5 位。超参数值:突变后的超参数值,按 self.space 中定义的顺序排列。这种设计使得每次迭代的结果可以被整齐地记录到文件中,便于后续分析和可视化超参数调优过程。log_row = [round(fitness, 5)] + [mutated_hyp[k] for k in self.space.keys()]# 如果 CSV 文件不存在,则构造表头。headers = "" if self.tune_csv.exists() else (",".join(["fitness"] + list(self.space.keys())) + "\n")# 将当前迭代的结果写入 CSV 文件。with open(self.tune_csv, "a") as f:f.write(headers + ",".join(map(str, log_row)) + "\n")# Get best results# 从 CSV 文件加载所有迭代的结果。x = np.loadtxt(self.tune_csv, ndmin=2, delimiter=",", skiprows=1)# 提取所有迭代的 fitness 值。fitness = x[:, 0] # first column# 找到最佳 fitness 值对应的迭代索引。best_idx = fitness.argmax()# 判断当前迭代是否为最佳迭代。best_is_current = best_idx == i# 如果当前迭代是最佳迭代,则执行以下操作:if best_is_current:# 更新最佳保存路径和性能指标。best_save_dir = save_dirbest_metrics = {k: round(v, 5) for k, v in metrics.items()}# 将当前迭代的权重文件复制到调优目录,以便后续使用。for ckpt in weights_dir.glob("*.pt"):shutil.copy2(ckpt, self.tune_dir / "weights")# 如果当前迭代不是最佳迭代且启用了清理功能,则执行以下操作:elif cleanup:# 删除当前迭代的权重目录,以节省存储空间。shutil.rmtree(ckpt_file.parent) # remove iteration weights/ dir to reduce storage space# Plot tune results# 绘制调优结果的图表,可视化超参数调优过程。# def plot_tune_results(csv_file="tune_results.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)。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.info("\n" + header)# 提取最佳迭代的超参数值。data = {k: float(x[best_idx, i + 1]) for i, k in enumerate(self.space.keys())}# 将最佳超参数保存为 YAML 文件。# def yaml_save(file="data.yaml", data=None, header=""): -> 用于将数据以YAML格式保存到文件中。yaml_save(self.tune_dir / "best_hyperparameters.yaml",data=data,# def remove_colorstr(input_string): -> 用于从输入字符串中移除 ANSI 转义序列(通常用于控制终端颜色和格式)。使用 re.sub 方法将匹配到的 ANSI 转义序列替换为空字符串(即移除这些序列),并返回处理后的字符串。 -> return ansi_escape.sub("", input_string)header=remove_colorstr(header.replace(self.prefix, "# ")) + "\n",)# 打印最佳超参数。# def yaml_print(yaml_file: Union[str, Path, dict]) -> None: -> 用于加载并打印 YAML 文件或字典的内容。它支持从文件路径加载 YAML 文件,或者直接打印传入的字典内容。yaml_print(self.tune_dir / "best_hyperparameters.yaml")# __call__ 方法实现了完整的超参数调优流程。迭代调优:通过多次迭代,每次生成一组新的超参数并训练模型。结果记录:将每次迭代的结果保存到 CSV 文件中,便于后续分析。最佳结果选择:根据性能指标选择最佳的超参数组合,并保存相关结果。清理功能:删除非最佳迭代的权重文件,节省存储空间。可视化:绘制调优结果的图表,帮助用户直观地理解调优过程。这种设计使得超参数调优过程高效且自动化,能够快速找到最优的超参数组合,提升模型性能。
# Tuner 类实现了一个自动化的超参数调优框架,适用于优化机器学习模型的性能。它的主要特点包括,遗传算法:通过突变和选择机制探索超参数空间。灵活的配置:支持自定义超参数范围和突变参数。结果记录:将每次迭代的结果保存到 CSV 文件中,并绘制调优结果图表。最佳模型保存:保存最佳模型和超参数到文件中,便于后续使用。这种设计非常适合在大规模超参数搜索中找到最优配置,尤其是在复杂的机器学习任务中。
相关文章:
YOLOv10-1.1部分代码阅读笔记-tuner.py
tuner.py ultralytics\engine\tuner.py 目录 tuner.py 1.所需的库和模块 2.class Tuner: 1.所需的库和模块 # Ultralytics YOLO 🚀, AGPL-3.0 license# 此模块提供用于对象检测、实例分割、图像分类、姿势估计和多对象跟踪的 Ultralytics YOLO 模型的超参数调…...
【数据结构】二分查找
🚩 WRITE IN FRONT 🚩 🔎 介绍:"謓泽"正在路上朝着"攻城狮"方向"前进四" 🔎🏅 荣誉:2021|2022年度博客之星物联网与嵌入式开发TOP5|TOP4、2021|2222年获评…...
iOS-支付相关
支付宝支付 #import <AlipaySDK/AlipaySDK.h> //orderStrAliPay为服务端传的订单信息 //fromScheme为应用配置的schemeUrl标识,用户支付包支付成功后跳转会本应用内 //callback回调需要在- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url 中调…...
ubuntu16.04 VSCode下cmake+clang+lldb调试c++
VSCode下cmakeclanglldb调试c Ubuntu16.04 安装OpenCV4.5.4 文章目录 VSCode下cmakeclanglldb调试c1.安装clangclangdcmake2、打开VSCode,安装扩展插件3、编译4、Debug4.1 创建launch.json。4.2 配置setting.json 5. vscode安装配置clang-format插件5.1 Linux系统安…...
学Python的人…
学Python的人… 一、Python能干什么? 1.爬虫:前几年,深度学习还没发展起来的时候,书店里Python就和爬虫挂钩,因为Python写爬虫确实方便。 2.数据分析:Python有各种的数据分析库可以方便使用࿰…...
GDB相比IDE有什么优点
GDB(GNU Debugger)相比于集成开发环境(IDE)具有一些独特的优点,主要体现在其灵活性、可定制性和低级控制能力。具体来说,GDB有以下几个优点: 1. 轻量级且无依赖 GDB是一个命令行工具,不依赖于任何复杂的图形界面或大型库,这使得它非常适合在资源受限的环境中使用,比…...
Docker 镜像加速的配置
解决拉取镜像报错:Error response from daemon: Get "https://registry-1.docker.io/v2/": net/http: request canceled while 在使用 Docker 过程中,拉取镜像的速度常常会受到网络状况的影响,尤其是在国内网络环境下,…...
分布式多卡训练(DDP)踩坑
多卡训练最近在跑yolov10版本的RT-DETR,用来进行目标检测。 单卡训练语句(正常运行): python main.py多卡训练语句: 需要通过torch.distributed.launch来启动,一般是单节点,其中CUDA_VISIBLE…...
MFC程序设计(一)MFC入门
本MFC教程使用VS2022实现 MFC基本概念 微软基础类库(英语:Microsoft Foundation Classes,简称MFC)是一个微软公司提供的类库(class libraries),以C类的形式封装了Windows API,并且…...
swift Actor并发处理
preconcurrency 使用 /*在 Swift 5.5 引入并发模型后,编译器会对潜在的数据竞争和不安全的并发代码发出警告或错误。然而,某些旧代码或第三方库可能尚未完全适配这些新规则。preconcurrency 提供了一种临时解决方案,允许你在不修改代码的情况…...
网络编程 | UDP套接字通信及编程实现经验教程
1、UDP基础 传输层主要应用的协议模型有两种,一种是TCP协议,另外一种则是UDP协议。在上一篇博客文章中,已经对TCP协议及如何编程实现进行了详细的梳理讲解,在本文中,主要讲解与TCP一样广泛使用了另一种协议:…...
Hadoop•搭建完全分布式集群
听说这里是目录哦 一、安装Hadoop🥕二、配置Hadoop系统环境变量🥮三、验证Hadoop系统环境变量是否配置成功🧁四、修改Hadoop配置文件🍭五、分发Hadoop安装目录🧋六、分发系统环境变量文件🍨七、格式化HDFS文…...
代码中使用 Iterable<T> 作为方法参数的解释
/*** 根据课程 id 集合查询课程简单信息* param ids id 集合* return 课程简单信息的列表*/ GetMapping("/courses/simpleInfo/list") List<CourseSimpleInfoDTO> getSimpleInfoList(RequestParam("ids") Iterable<Long> ids); 一、代码解释&…...
web前端1--基础
(时隔数月我又来写笔记啦~) 1、下载vscode 1、官网下载:Visual Studio Code - Code Editing. Redefined 2、步骤: 1、点击同意 一直下一步 勾一个创建桌面快捷方式 在一直下一步 2、在桌面新建文件夹 拖到vscode图标上 打开v…...
关于opensips的帮助命令的解释
opensips -help以下是 opensips 命令及其选项的中文解释(基于 3.6.0-dev 版本): 命令用法 opensips -l 地址 [-l 地址 ...] [选项]选项说明 选项功能-f 文件指定配置文件(默认为 /usr/local//etc/opensips/opensips.cfg&#x…...
你还在用idea吗
从VIM、Emacs,到eclipse、Jetbrains, 再到VSCode,过去的三十年时间,出现了这三代IDE产品。现在属于AI的时代来了,最新一代的产品像Cursor、Windsurf,就在昨天,字节跳动发布了最新的IDE,就叫Trae…...
安装wxFormBuilder
1. 网址:GitHub - wxFormBuilder/wxFormBuilder: A wxWidgets GUI Builder 2. 安装MSYS2 MSYS2可以在GitHub的内容中找到,这个版本是32位64位的 3. 在程序中打开MINGW64 shell 4. 在MSYS2 MINGW64 shell中输入 pacman -Syu pacman -S ${MINGW_PACKAGE…...
【大数据2025】Hadoop 万字讲解
文章目录 一、大数据通识大数据诞生背景与基本概念大数据技术定义与特征大数据生态架构概述数据存储数据计算与易用性框架分布式协调服务和任务调度组件数仓架构流处理架构 二、HDFSHDFS 原理总结一、系统架构二、存储机制三、数据写入流程四、心跳机制与集群管理 安全模式&…...
HTML语言的计算机基础
HTML语言的计算机基础 引言 在当今信息技术迅猛发展的时代,网页设计和开发已成为计算机科学中不可或缺的一部分。而HTML(超文本标记语言)作为构建网页的基础语言,承载着网页上所有内容的结构,帮助开发者创建和展示信…...
Cannot resolve symbol ‘XXX‘ Maven 依赖问题的解决过程
一、问题描述 在使用 Maven 管理项目依赖时,遇到了一个棘手的问题。具体表现为:在 pom.xml 文件中导入了所需的依赖,并且在 IDE 中导入语句没有显示为红色(表示 IDE 没有提示依赖缺失),但是在实际使用这些依…...
Swift语言的函数实现
Swift语言函数实现详解 引言 Swift是一种强类型、泛型编程的现代编程语言,广泛应用于iOS和macOS开发。函数是Swift编程中的基本构建块之一,通过函数可以将代码进行模块化,实现重用性和可读性。本篇文章将系统地介绍Swift中的函数࿰…...
除了基本的事件绑定,鸿蒙的ArkUI
鸿蒙操作系统(HarmonyOS)是由华为技术有限公司开发的分布式操作系统,旨在为多种智能设备提供一个统一的操作平台。它不仅适用于智能手机,还适用于平板电脑、智能手表、智能电视等物联网设备。为了使开发者能够更加便捷地创建跨设备…...
数据分析及应用:经营分析中的综合指标解析与应用
目录 1. 市场份额(Market Share) 2. 客户获取成本(Customer Acquisition Cost, CAC) 3. 客户生命周期价值(Customer Lifetime Value, CLV) 4. 客户留存率(Customer Retention Rate, CRR) 5. 净推荐值(Net Promoter Score, NPS) 6. 转化率(Conversion Rate) …...
Mac开启任何来源安装配置环境变量
目录 开启任何来源配置环境变量退出保存时如果没有权限修改文件权限拓展——.bash_profile和.zshrc 开启任何来源 sudo spctl --master-disable#打开软件时提示文件损坏 sudo xattr -r -d com.apple.quarantine 进入访达应用程序拖拽应用到终端配置环境变量 cd ~ vi ~/.bash…...
UI自动化设计模式--POM
在自动化测试中,Page Object Model(POM)设计方式是一种常用的设计模式,它将页面元素和操作封装成独立的类,提高了测试代码的可读性、可维护性和可复用性。以下是关于POM设计方式的详细介绍: 基本概念 POM…...
(三)线性代数之二阶和三阶行列式详解
在前端开发中,尤其是在WebGL、图形渲染、或是与地图、模型计算相关的应用场景里,行列式的概念常常在计算变换矩阵、进行坐标变换或进行图形学算法时被使用。理解二阶和三阶行列式对于理解矩阵运算、旋转、平移等操作至关重要。下面,我将结合具…...
postman接口测试工具详解
一、前言 Postman是一款广泛使用的API测试工具,适用于开发人员和测试人员。它提供了直观的用户界面,能够方便地进行API请求、响应验证、自动化测试等操作。本文将详细介绍Postman的功能和用法,帮助用户高效地进行API测试。 二、Postman的主…...
Golang 中强大的重试机制,解决瞬态错误
文章精选推荐 1 JetBrains Ai assistant 编程工具让你的工作效率翻倍 2 Extra Icons:JetBrains IDE的图标增强神器 3 IDEA插件推荐-SequenceDiagram,自动生成时序图 4 BashSupport Pro 这个ides插件主要是用来干嘛的 ? 5 IDEA必装的插件&…...
【C语言系列】深入理解指针(2)
一、数组名的理解 上一篇文章中我们写过一个这样的代码: int arr[10] {1,2,3,4,5,6,7,8,9,10}; int *p &arr[0];这里使用&arr[0] 的方式拿到了数组第⼀个元素的地址,但是其实数组名本来就是地址,而且是数组首元素的地址ÿ…...
【网络原理】万字详解 HTTP 协议
🥰🥰🥰来都来了,不妨点个关注叭! 👉博客主页:欢迎各位大佬!👈 文章目录 1. HTTP 前置知识1.1 HTTP 是什么1.2 HTPP 协议应用场景1.3 HTTP 协议工作过程 2. HTTP 协议格式2.1 fiddler…...
WIFI连接与通信
ESP32-S3 支持 2.4 GHz 的 Wi-Fi 4(802.11n)标准,提供高达 150 Mbps 的数据传输速率。它支持 STA(Station)模式、AP(Access Point)模式和 Wi-Fi 直连(Wi-Fi Direct)模式&…...
Elixir语言的数据库编程
Elixir语言的数据库编程 介绍 Elixir是一种基于Erlang虚拟机(BEAM)的函数式编程语言,特别适用于构建可扩展和可维护的系统。它结合了Erlang的卓越并发特性和Ruby的易用性,因此在Web开发和实时应用中越来越受到欢迎。伴随着Elixi…...
python中Mako用法
Mako 是一个轻量级的 Python 模板库,它以其高效的代码生成和灵活的表达能力著称,常用于 Web 开发和静态文件生成。以下是对 Mako 的核心 API介绍。 1. 安装 Mako 首先安装 Mako: pip install mako2. 基本用法 Mako 的核心在于 Template 类…...
SMS4J - 一个聚合各种短信API商的工具
众所周知,在我们日常的项目开发中,短信验证码发送是一个必不可少的环节。 特别是如今手机互联网时代,基本所有东西都跟手机强绑定,所有的安全验证都离不开验证码这一环节。 所以对于一个系统来说,发送短信验证码成为…...
BEVFusion论文阅读
1. 简介 融合激光雷达和相机的信息已经变成了3D目标检测的一个标准,当前的方法依赖于激光雷达传感器的点云作为查询,以利用图像空间的特征。然而,人们发现,这种基本假设使得当前的融合框架无法在发生 LiDAR 故障时做出任何预测&a…...
【总结盘点类】2024,一场关于海量数据治理以及合理建模的系列写作
目录 1.今年的创作路线 2.先说第一条线 2.1.由日志引出的海量文本数据存储和分析问题 2.2.监控以及监控的可视化 2.3.数据量级再往上走牵扯出了大数据 2.4.由大数据牵扯出的JAVA线程高级内容 3.第二条线,也是2025要继续的主线 1.今年的创作路线 今年的写作内…...
【25考研】考清华的软件工程专业的研究生需要准备什么?
清华软件复试竞争一样很激烈!建议同学认真复习! 关于项目的注意事项先来一些总结: 千万别照抄开源项目 开源项目是一个很好的参考,但直接搬过来就没啥意义啦。我们可以根据开源项目学习它的技术架构和关键点,然后结…...
网络编程-UDP套接字
文章目录 UDP/TCP协议简介两种协议的联系与区别Socket是什么 UDP的SocketAPIDatagramSocketDatagramPacket 使用UDP模拟通信服务器端客户端测试 完整测试代码 UDP/TCP协议简介 两种协议的联系与区别 TCP和UDP其实是传输层的两个协议的内容, 差别非常大, 对于我们的Java来说, …...
EXCEL的一些用法记录
按某个分隔符进行拆分多列 【数据】- 【分列】 多列调整成多行 复制 - 粘贴 - 选择【转置】 部分内容替换 SUBSTITUTE()函数 ,固定内容 加“”...
不使用 JS 纯 CSS 获取屏幕宽高
前言 在现代前端开发中,获取屏幕的宽度和高度通常依赖于 JavaScript。然而现代 CSS 也可以获取到屏幕的宽高,通过自定义属性(CSS Variables)和一些数学函数来实现这一目标。本文将详细解析如何使用 CSS 的 property 规则和一些数…...
Node.js 完全教程:从入门到精通
Node.js 完全教程:从入门到精通 Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境,允许开发者在服务器端使用 JavaScript。它的非阻塞 I/O 和事件驱动架构使得 Node.js 非常适合于构建高性能的网络应用。本文将详细介绍 Node.js 的安装、基本语…...
可替代CentOS 7的Linux操作系统选型
可替代CentOS 7的其他Linux操作系统选型 一、背景介绍二、主流操作系统调研2.1 企业级产品:Red Hat Enterprise Linux/CentOS Stream2.1.1 Red Hat Enterprise Linux2.1.2 CentOS Stream2.2 其他发行版:Debian/Ubuntu2.3 开源产品:AlmaLinux / RockyLinux2.3.1 AlmaLinux2.3…...
【ESP32】ESP32连接JY61P并通过WIFI发送给电脑
前言 手头上有个ESP32,发现有wifi功能,希望连接JY61P并通过WIFI把姿态数据发送给电脑 1.采用Arduino IDE编译器;需要安装ESP32的开发板管理器; 2.电脑接受数据是基于python的; 1. ESP32 连接手机WIFI #include <…...
【JSqlParser】Java使用JSqlParser解析SQL语句总结
简述 Java解析SQL语句有很多工具都可以做到,比如Mybatis、Druid、目前用来用去最全面的仍然是Jsqlparser,它是一个Github上的开源项目,JSqlParser是一个用于解析SQL语句的Java库,它可以帮助开发者分析和操作SQL语句的结构。无论是…...
TCP断开通信前的四次挥手(为啥不是三次?)
1.四次握手的过程 客户端A发送 FIN(终止连接请求) A:我要断开连接了(FIN)。A进入FIN_WAIT_1状态,表示请求断开,等待对方确认。 服务器B回复 ACK(确认断开请求,但还未准备…...
解决用 rm 报bash: /usr/bin/rm: Argument list too long错
但目录里面文件过多用 rm 报bash: /usr/bin/rm: Argument list too long错时怎么办: 看看以下操作记录 rootmcu:/# cd /tmp rootmcu:/tmp# rm -f /tmp/chunk* bash: /usr/bin/rm: Argument list too long rootmcu:/tmp# rm -rf /tmp/chunk* bash: /usr/bin/rm: Arg…...
AI News(1/21/2025):OpenAI 安全疏忽:ChatGPT漏洞引发DDoS风险/OpenAI 代理工具即将发布
1、OpenAI 的安全疏忽:ChatGPT API 漏洞引发DDoS风险 德国安全研究员 Benjamin Flesch 发现了一个严重的安全漏洞:攻击者可以通过向 ChatGPT API 发送一个 HTTP 请求,利用 ChatGPT 的爬虫对目标网站发起 DDoS 攻击。该漏洞源于 OpenAI 在处理…...
从零到上线:Node.js 项目的完整部署流程(包含 Docker 和 CICD)
从零到上线:Node.js 项目的完整部署流程(包含 Docker 和 CI/CD) 目录 项目初始化:构建一个简单的 Node.js 应用设置 Docker 环境:容器化你的应用配置 CI/CD:自动化构建与部署上线前的最后检查:…...
哈希桶(开散列)
文章目录 前言实现插入put方法实现get方法实现泛型类哈希桶 前言 哈希桶用来解决哈希冲突,牺牲空间换取时间。 通过数组和链表来实现哈希桶 public class Node{public int key;public int value;public Node next;public Node(int key,int value){this.keykey;this…...
DEBERTA:具有解耦注意力机制的解码增强型BERT
摘要 近年来,预训练神经语言模型的进展显著提升了许多自然语言处理(NLP)任务的性能。本文提出了一种新的模型架构DeBERTa(具有解耦注意力机制的解码增强型BERT),通过两种新技术改进了BERT和RoBERTa模型。第…...