YOLOv9-0.1部分代码阅读笔记-experimental.py

news2024/12/17 12:00:04

experimental.py

models\experimental.py

目录

experimental.py

1.所需的库和模块

2.class Sum(nn.Module): 

3.class MixConv2d(nn.Module): 

4.class Ensemble(nn.ModuleList): 

5.def attempt_load(weights, device=None, inplace=True, fuse=True): 


1.所需的库和模块

import math

import numpy as np
import torch
import torch.nn as nn

from utils.downloads import attempt_download

2.class Sum(nn.Module): 

# 这段代码定义了一个名为 Sum 的类,它是一个继承自 nn.Module 的 PyTorch 神经网络模块。这个模块的目的是将多个输入张量( x )相加,并且可以选择性地应用权重。
# 这个模块的设计灵感来源于论文 "EfficientDet: Scalable and Efficient Object Detection" 中提到的加权双向特征金字塔网络(Weighted Bi-directional Feature Pyramid Network, BiFPN)。
# 定义了一个继承自 nn.Module 的新类 Sum ,这是一个 PyTorch 神经网络模块的基类。
class Sum(nn.Module):
    # Weighted sum of 2 or more layers https://arxiv.org/abs/1911.09070    2 层或更多层的加权和 https://arxiv.org/abs/1911.09070。
    # Sum 类的构造函数,它接受两个参数。
    # 1.n :输入的数量。
    # 2.weight :一个布尔值,表示是否应用权重,默认为 False 。
    def __init__(self, n, weight=False):  # n: number of inputs
        # 调用基类的构造函数,这是 Python 中继承机制的一部分,用于确保基类被正确初始化。
        super().__init__()
        # 将传入的 weight 参数保存为类的成员变量。
        self.weight = weight  # apply weights boolean
        # 创建一个迭代器对象,用于在 forward 方法中迭代输入张量。
        self.iter = range(n - 1)  # iter object
        # 如果 weight 参数为 True ,则执行以下操作。
        if weight:
            # 创建一个可学习的参数 w ,它是一个 PyTorch 参数( nn.Parameter ),这意味着它的值可以在训练过程中被优化。参数的初始值是通过 torch.arange(1.0, n) / 2 生成的,然后取负值。 requires_grad=True 表示需要计算这些权重的梯度。
            self.w = nn.Parameter(-torch.arange(1.0, n) / 2, requires_grad=True)  # layer weights

    # 定义了 forward 方法,这是神经网络模块的前向传播方法,它接受输入张量 1.x 。
    def forward(self, x):
        # 初始化输出 y 为第一个输入张量 x[0] 。
        y = x[0]  # no weight
        # 如果 weight 为 True ,则执行以下操作。
        if self.weight:
            # 权重参数 self.w 通过 sigmoid 函数激活,然后乘以 2,以确保权重在 0 到 2 之间。
            w = torch.sigmoid(self.w) * 2
            # 迭代剩余的输入张量,并将它们与对应的权重相乘后累加到 y 。
            for i in self.iter:
                y = y + x[i + 1] * w[i]
        # 如果 weight 为 False ,则执行以下操作。
        else:
            # 迭代剩余的输入张量,并将它们直接累加到 y 。
            for i in self.iter:
                y = y + x[i + 1]
        # 返回最终的输出 y 。
        return y
# 这个模块可以用于将多个输入张量相加,并且可以选择是否对每个输入张量应用不同的权重。如果启用权重,权重将通过训练过程进行优化。

3.class MixConv2d(nn.Module): 

# 这段代码定义了一个名为 MixConv2d 的类,它是一个继承自 nn.Module 的 PyTorch 神经网络模块。这个模块实现了混合深度卷积(Mixed Depth-wise Convolution),这是一种在单个卷积操作中混合使用不同核大小的技术。
# 定义了一个名为 MixConv2d 的新类,它继承自 PyTorch 的 nn.Module 类。
class MixConv2d(nn.Module):
    # Mixed Depth-wise Conv https://arxiv.org/abs/1907.09595
    # MixConv2d 类的构造函数,它接受以下参数。
    # 1.c1 :输入通道数。
    # 2.c2 :输出通道数。
    # 3.k :一个元组,包含不同的核大小,默认为 (1, 3) 。
    # 4.s :步长,默认为 1 。
    # 5.equal_ch :一个布尔值,表示是否每个分组的通道数相等,默认为 True 。
    def __init__(self, c1, c2, k=(1, 3), s=1, equal_ch=True):  # ch_in, ch_out, kernel, stride, ch_strategy
        # 调用基类的构造函数。
        super().__init__()
        # 获取核大小的数量。
        n = len(k)  # number of convolutions
        # 如果 equal_ch 为 True ,则每个分组的通道数相等。
        if equal_ch:  # equal c_ per group
            # 生成一个从 0 到 n-1 的等间隔序列,长度为 c2 。
            i = torch.linspace(0, n - 1E-6, c2).floor()  # c2 indices
            # 计算每个分组的通道数。
            c_ = [(i == g).sum() for g in range(n)]  # intermediate channels
        # 如果 equal_ch 为 False ,则使用线性方程组求解每个分组的通道数,使得权重数量相等。
        else:  # equal weight.numel() per group
            # 创建一个列表 b ,其中包含 c2 (总的输出通道数)后面跟着 n 个零。这个列表将作为线性方程组的 b 向量。
            b = [c2] + [0] * n
            # 创建一个 n+1 行 n 列的单位矩阵 a ,然后通过 k=-1 参数将矩阵向下移动一个位置,这样可以得到一个除了第一列以外都是零的矩阵。
            a = np.eye(n + 1, n, k=-1)
            # 通过 np.roll 函数将矩阵 a 沿列方向向右移动一个位置,然后从原矩阵 a 中减去这个移动后的矩阵。这样做的结果是,除了第一列和最后一列以外,其他列的对角线上的元素会变成 -1 。
            a -= np.roll(a, 1, axis=1)
            # 将矩阵 a 中的每个元素乘以对应的核大小的平方( k 是一个包含核大小的元组)。
            a *= np.array(k) ** 2
            # 将矩阵 a 的第一行设置为全1,这是因为我们想要在第一组卷积中使用所有的输出通道。
            a[0] = 1
            # 使用 numpy 的 linalg.lstsq 函数解决线性方程组 ax = b 。 rcond=None 参数表示不对矩阵进行奇异值截断。函数返回的是方程组的解,我们取第一个返回值(即解向量),并使用 round 函数将解向量中的值四舍五入到最近的整数。这个解向量 c_ 表示每个卷积核大小对应的输出通道数。
            c_ = np.linalg.lstsq(a, b, rcond=None)[0].round()  # solve for equal weight indices, ax = b
        # 通过这种方式,我们可以确保每个卷积核大小对应的权重数量大致相等,从而在不同的卷积核大小之间平衡模型的复杂度。这种方法在设计深度学习模型时非常有用,因为它可以帮助我们更有效地利用模型的参数。

        # 创建一个模块列表,包含不同核大小的卷积层。
        self.m = nn.ModuleList([
            # groups=math.gcd(c1, int(c_)) :分组数,使用 math.gcd 函数计算输入通道数和输出通道数的最大公约数,这样可以确保每个分组的通道数是整数。
            # bias=False :不使用偏置项,因为后面会使用批量归一化层,它会包含偏置项。
            nn.Conv2d(c1, int(c_), k, s, k // 2, groups=math.gcd(c1, int(c_)), bias=False) for k, c_ in zip(k, c_)])
        # 通过这行代码,为 MixConv2d 类创建了一个包含多个具有不同核大小的卷积层的 ModuleList 。在前向传播时,每个卷积层都会对输入特征图进行卷积操作,然后将结果拼接起来,形成最终的输出特征图。这种方法可以提高模型对不同尺度特征的捕捉能力,同时保持计算效率。
        # 创建一个批量归一化层。
        self.bn = nn.BatchNorm2d(c2)
        # 创建一个激活层,SiLU(也称为Sigmoid-Weighted Linear Unit)。
        self.act = nn.SiLU()

    # 定义了前向传播的方法,它接受一个输入。
    # 1.x :这是一个张量(tensor),代表输入的特征图(feature maps)。
    def forward(self, x):
        #  [self.m] :这是一个包含多个卷积层的 ModuleList ,每个卷积层都有不同的核大小。
        # for m in self.m :这是一个循环,遍历 ModuleList 中的每个卷积层。
        # m(x) :对每个卷积层应用输入 x ,得到每个卷积层的输出。
        # torch.cat([m(x) for m in self.m], 1) :使用 torch.cat 函数将所有卷积层的输出在通道维度(维度1)上拼接起来。这样,如果每个卷积层的输出通道数不同,它们仍然可以被合并成一个单一的张量。
        # self.bn(...) :将拼接后的张量传递给批量归一化层( BatchNorm2d ),这有助于规范化数据,使其具有相同的均值和方差,从而提高模型的训练效率和性能。
        # self.act(...) :最后,将归一化后的张量传递给激活函数层(在这里是 SiLU 即 Sigmoid-Weighted Linear Unit ),这为模型引入非线性,使其能够学习更复杂的特征。
        return self.act(self.bn(torch.cat([m(x) for m in self.m], 1)))
    # forward 方法将输入 x 通过不同核大小的卷积层,然后将这些卷积层的输出在通道维度上拼接,接着进行批量归一化和激活,最终输出的结果就是模型的前向传播结果。这种方法允许模型在单个操作中利用不同尺度的局部感受野,从而提高其对不同尺度特征的捕捉能力。
# 这个 MixConv2d 模块可以根据核大小的不同,将输入通道分割成不同的组,并在每个组上应用不同大小的卷积核。这种方法可以提高模型的表达能力,同时保持计算效率。

4.class Ensemble(nn.ModuleList): 

# 这段代码定义了一个名为 Ensemble 的类,它继承自 PyTorch 的 nn.ModuleList 。这个类用于实现模型集成(ensemble),即将多个模型的预测结果结合起来以提高性能。
# 定义了一个名为 Ensemble 的新类,它继承自 PyTorch 的 nn.ModuleList 类。
class Ensemble(nn.ModuleList):
    # Ensemble of models
    #  Ensemble 类的构造函数。
    def __init__(self):
        # 调用基类的构造函数,初始化 ModuleList 。
        super().__init__()

    # 定义了 forward 方法,这是神经网络模块的前向传播方法。它接受以下参数。
    # 1.x :输入数据。
    # 2.augment :一个布尔值,表示是否应用数据增强。
    # 3.profile :一个布尔值,表示是否进行性能分析。
    # 4.visualize :一个布尔值,表示是否进行可视化。
    def forward(self, x, augment=False, profile=False, visualize=False):
        # 列表推导式,它遍历 Ensemble 中的每个模块(即每个模型),将输入 x 和其他参数传递给每个模型的 forward 方法,并收集每个模型的输出。这里每个模型的 forward 方法返回一个元组,并且只取元组的第一个元素(即预测结果)。
        y = [module(x, augment, profile, visualize)[0] for module in self]
        # y = torch.stack(y).max(0)[0]  # max ensemble
        # y = torch.stack(y).mean(0)  # mean ensemble
        # 使用 torch.cat 函数将所有模型的输出在通道维度(维度1)上拼接起来。这种集成方法通常用于非最大抑制(NMS)集成,其中不同模型的预测结果被合并,然后应用 NMS 来去除重叠的检测框。
        y = torch.cat(y, 1)  # nms ensemble
        # 返回拼接后的输出 y 和一个 None 值,表示没有额外的输出。在 PyTorch 中, None 通常用于表示没有额外的输出或信息。
        return y, None  # inference, train output
# 这个 Ensemble 类提供了一种简单的方式来集成多个模型的预测结果。通过这种方式,可以提高模型的鲁棒性和准确性,特别是在目标检测等任务中。集成方法可以根据具体任务的需求进行调整,例如使用最大值集成( max ensemble )或平均值集成( mean ensemble )。

5.def attempt_load(weights, device=None, inplace=True, fuse=True): 

# 这段代码定义了一个名为 attempt_load 的函数,它用于加载一个或多个预训练的模型权重,并创建一个模型集合( Ensemble )。这个函数处理了模型权重的加载、兼容性更新和模型融合。
# 定义了 attempt_load 函数,它接受以下参数。
# 1.weights :模型权重的路径或路径列表。
# 2.device :模型运行的设备,默认为 None 。
# 3.inplace :是否在原地修改模型参数,默认为 True 。
# 4.fuse :是否融合模型中的某些层以提高效率,默认为 True 。
def attempt_load(weights, device=None, inplace=True, fuse=True):
    # Loads an ensemble of models weights=[a,b,c] or a single model weights=[a] or weights=a
    # 从 models.yolo 模块导入 Detect 和 Model 类。
    from models.yolo import Detect, Model

    # 这段代码是 attempt_load 函数中的一部分,它负责加载一个或多个预训练模型的权重,并对每个模型进行兼容性更新,最后将它们添加到一个 Ensemble 实例中。
    # 创建一个 Ensemble 实例,这个实例将用来存储多个模型。
    model = Ensemble()
    # 遍历 weights 参数。如果 weights 是一个列表,直接遍历它;如果不是列表,将其转换为一个只包含该权重的列表,这样就可以统一处理单个权重和权重列表的情况。
    for w in weights if isinstance(weights, list) else [weights]:
        # 对于每个权重文件,首先尝试下载(如果文件不存在),然后使用 torch.load 加载权重文件。 map_location='cpu' 确保权重文件被加载到 CPU 上。
        # def attempt_download(file, repo='ultralytics/yolov5', release='v7.0'): -> 尝试从 GitHub 仓库的发布资产中下载文件,如果本地找不到该文件。返回处理后的文件路径。返回文件的路径,以字符串形式。 -> return file / return str(file)
        ckpt = torch.load(attempt_download(w), map_location='cpu')  # load
        # 从加载的权重中,尝试获取 ema (指数移动平均)键对应的模型状态,如果没有,则获取 model 键对应的状态。然后将模型状态转移到指定的 device 上,并转换为浮点数(FP32)。
        ckpt = (ckpt.get('ema') or ckpt['model']).to(device).float()  # FP32 model

        # Model compatibility updates
        # 检查加载的模型是否有 stride 属性,如果没有,则为其设置一个默认值。
        if not hasattr(ckpt, 'stride'):
            ckpt.stride = torch.tensor([32.])
        # 检查模型是否有 names 属性,并且该属性是否是列表或元组。如果是,将其转换为字典,其中索引作为键,原始列表或元组中的元素作为值。
        if hasattr(ckpt, 'names') and isinstance(ckpt.names, (list, tuple)):
            ckpt.names = dict(enumerate(ckpt.names))  # convert to dict

        # 如果 fuse 参数为 True 且模型有 fuse 方法,则调用该方法来融合模型中的某些层,然后设置模型为评估模式( eval )。如果没有 fuse 方法或 fuse 参数为 False ,则直接将模型设置为评估模式。最后,将模型添加到 Ensemble 实例中。
        model.append(ckpt.fuse().eval() if fuse and hasattr(ckpt, 'fuse') else ckpt.eval())  # model in eval mode
    # 通过这段代码,可以将多个预训练模型的权重加载并集成到一个 Ensemble 实例中,每个模型都被设置为评估模式,并且进行了必要的兼容性更新。这样的集成模型可以用于提高预测的准确性和鲁棒性。

    # 这段代码是 attempt_load 函数的另一部分,它负责对加载的模型进行模块兼容性更新,并在模型集合中只有一个模型时返回该单个模型。
    # Module compatibility updates
    # 模块兼容性更新。
    # 遍历 Ensemble 实例 model 中的所有模块。 modules() 方法返回模型中所有模块的迭代器。
    for m in model.modules():
        # 获取当前模块 m 的类型。
        t = type(m)
        # 检查模块类型是否为特定的激活函数类或自定义的 Detect 和 Model 类。如果是,执行以下操作。
        if t in (nn.Hardswish, nn.LeakyReLU, nn.ReLU, nn.ReLU6, nn.SiLU, Detect, Model):
            # 设置模块的 inplace 属性。这是为了兼容 PyTorch 1.7.0 版本,因为在新版本中,某些操作默认是原地(in-place)执行的,这可以通过设置 inplace=True 来启用。
            m.inplace = inplace  # torch 1.7.0 compatibility
            # if t is Detect and not isinstance(m.anchor_grid, list):
            #    delattr(m, 'anchor_grid')
            #    setattr(m, 'anchor_grid', [torch.zeros(1)] * m.nl)
        # 检查模块类型是否为 nn.Upsample 并且没有 recompute_scale_factor 属性。如果是,执行以下操作。
        elif t is nn.Upsample and not hasattr(m, 'recompute_scale_factor'):
            # 为模块添加 recompute_scale_factor 属性并设置为 None 。这是为了兼容 PyTorch 1.11.0 版本,因为在新版本中, Upsample 模块的行为有所变化。
            # recompute_scale_factor 属性在 PyTorch 的 nn.Upsample 模块中用于控制插值过程中缩放因子( scale_factor )的计算方式。具体来说,这个属性影响如何根据输入和输出张量的大小来计算插值时使用的缩放因子。
            m.recompute_scale_factor = None  # torch 1.11.0 compatibility

    # Return model
    # 返回模型。
    # 检查 Ensemble 实例 model 中是否只有一个模型。
    if len(model) == 1:
        # 如果只有一个模型,直接返回该模型。 model[-1] 表示 Ensemble 实例中的最后一个模型,也就是唯一的模型。
        return model[-1]
    # 这段代码确保了加载的模型与当前 PyTorch 版本的兼容性,并且提供了一种简洁的方式来处理只包含单个模型的模型集合。通过这种方式, attempt_load 函数可以灵活地处理单个模型和模型集合,同时确保模型在不同版本的 PyTorch 中都能正常工作。

    # 这段代码是 attempt_load 函数的最后一部分,它负责完成模型集合( Ensemble )的设置,并返回这个集合。
    # Return detection ensemble
    # 打印一条消息,表明已经使用提供的权重创建了一个模型集合,并显示这些权重。
    print(f'Ensemble created with {weights}\n')    # 使用 {weights} 创建的集成。
    # 遍历一个包含属性名称的元组。
    for k in 'names', 'nc', 'yaml':
        # 对于每个属性名称,使用 setattr 函数将 Ensemble 实例的对应属性设置为第一个模型( model[0] )的同名属性的值。这样做是为了确保模型集合具有与单个模型相同的属性,例如类别名称( names )、类别数量( nc )和模型配置( yaml )。
        # setattr(model, k, getattr(model[0], k)) :对于每个属性名称 k ,这行代码执行以下操作 :
        # getattr(model[0], k) :获取模型集合中第一个模型( model[0] )的属性 k 的值。
        # setattr(model, k, ...) :将这个值设置为整个模型集合对象( model )的属性 k 。
        setattr(model, k, getattr(model[0], k))
    # 计算模型集合中所有模型的最大步长( stride ),并将其设置为模型集合的 stride 属性。 torch.argmax 找到最大步长值的索引,然后通过索引访问对应的模型,并获取其 stride 属性。
    model.stride = model[torch.argmax(torch.tensor([m.stride.max() for m in model])).int()].stride  # max stride
    # 断言检查模型集合中的所有模型是否具有相同数量的类别( nc )。如果不一致,则抛出异常,并显示每个模型的类别数量。
    assert all(model[0].nc == m.nc for m in model), f'Models have different class counts: {[m.nc for m in model]}'    # 模型有不同的类别数:{[m.nc for m in model]。
    # 返回最终构建的模型集合( Ensemble )。
    return model
    # 这段代码确保了模型集合具有一致的属性,并且所有模型都具有相同数量的类别。通过设置最大步长,它还确保了模型集合可以正确地处理不同分辨率的输入。最后,它返回构建好的模型集合,这个集合可以用于推理或进一步的训练。
# 这个函数提供了一个灵活的方式来加载和集成多个模型,同时处理了模型的兼容性问题。通过这种方式,可以轻松地将多个预训练模型组合起来,以提高模型的性能和鲁棒性。

# 模型集合( Ensemble )中包含的每个模型都使用各自的 yaml 属性。当你创建一个模型集合并将多个模型添加到其中时,每个模型都保留自己的配置信息,包括 yaml 属性。
# 在 attempt_load 函数中,代码段:
# for k in 'names', 'nc', 'yaml':
#     setattr(model, k, getattr(model[0], k))
# 将模型集合中第一个模型的 yaml 属性复制到 模型集合对象 上,使得你可以通过模型集合对象访问这个属性。但这并不意味着集合中的其他模型的 yaml 属性被修改或覆盖。每个模型仍然保持自己的独立 yaml 配置。
# 如果你需要访问集合中某个特定模型的 yaml 属性,你应该直接访问那个模型实例的属性。例如:
# yaml_config_for_model = model[0].yaml  # 获取模型集合中第一个模型的 yaml 配置
# 在这里, model[0] 表示模型集合中的第一个模型,你可以通过索引来访问集合中的其他模型,并获取它们的 yaml 属性。每个模型的 yaml 属性都是独立的,反映了它们各自的配置信息。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2261045.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

爬虫逆向学习(十四):分享一下某数通用破解服务开发经验

阅前须知 这篇博客不是教大家怎么实现的,而且告知大家有这个东西,或者说一种趋势,借此分享自己大致的实现经验。具体的实现我也不好整理,毕竟是在别人的基础上缝缝补补。 前言 使用补环境方式破解过某数的同学都知道&#xff0…

知识分享第二十八天-数学篇一

组合.二项式定理.常见导数 组合 让我们通过一个具体的例子来理解组合(Combinations)的概念 假设你有一个装有5个不同颜色球的袋子:红、蓝、绿、黄和紫。你想从中随机抽取3个球, 不考虑顺序,那么你可以有多少种不同的…

Kruskal最小生成树算法正确性证明

Kruskal: 每次考虑最短一条边, 如果会形成回路则不选择该边, 如果不会形成回路则选择该边, 直到选出了n-1条边 要点: 每次都选择不会形成回路的最短边 数学归纳法 ① n<2时, 显然成立 ② 设n k时成立, 则当n k1时: 将图划分为 子图A(k) 和 B(1) ∵ n k时成立 ∴ A(k)可…

Liveweb视频汇聚平台支持WebRTC协议赋能H.265视频流畅传输

随着科技的飞速发展和网络技术的不断革新&#xff0c;视频监控已经广泛应用于社会各个领域&#xff0c;成为现代安全管理的重要组成部分。在视频监控领域&#xff0c;视频编码技术的选择尤为重要&#xff0c;它不仅关系到视频的质量&#xff0c;还直接影响到视频的传输效率和兼…

iPhone苹果相册视频怎么提取音频?

在数字时代&#xff0c;视频已成为我们记录生活、分享故事的重要方式。然而&#xff0c;有时候我们只想保留视频中的音频部分&#xff0c;比如一段动人的背景音乐或是一段珍贵的对话。那么&#xff0c;苹果相册视频怎么提取音频呢&#xff1f;本文将介绍三种简单且实用的方法&a…

【图像配准】方法总结

图像配准(Image registration)就是将不同时间、不同传感器&#xff08;成像设备&#xff09;或不同条件下&#xff08;天候、照度、摄像位置和角度等&#xff09;获取的两幅或多幅图像进行匹配、叠加的过程&#xff0c;就是找到1幅图像像素到另1幅图像像素间的空间映射关系它已…

专业140+总分400+北京理工大学826信号处理导论考研经验北理工电子信息与通信工程,真题,大纲,参考书。

考研总分400&#xff0c;专业826信号处理导论&#xff08;信号与系统和dsp&#xff09;140&#xff0c;成功上岸北理工&#xff0c;虽然已经一段时间&#xff0c;但是后劲很大&#xff0c;每每回想还是昨日事&#xff0c;群里同学多次要求分享自己的一些经验&#xff0c;感谢大…

ReactPress最佳实践—搭建导航网站实战

Github项目地址&#xff1a;https://github.com/fecommunity/easy-blog 欢迎Star。 近期&#xff0c;阮一峰在科技爱好者周刊第 325 期中推荐了一款开源工具——ReactPress&#xff0c;ReactPress一个基于 Next.js 的博客和 CMS 系统&#xff0c;可查看 demo站点。&#xff08;…

Windows 环境实战开源项目GFPGAN 教程

GFPGAN GFPGAN&#xff08;Generative Facial Prior-GAN&#xff09;是由腾讯ARC&#xff08;Applied Research Center&#xff09;开发的一种实用的真实世界人脸修复算法。它专门设计用于人脸图像的生成和优化&#xff0c;尤其在低质量人脸图像的超分辨率恢复方面表现出色。以…

链表的应用

尾删 int tail_del (linkListPtr S) { if(NULL S || empty(S)) { printf("失败\n"); return 0; } linkListPtr q S; for(int i0 ; i<S->len-1;i) { qq->next; } free(q->next); q->n…

一个小工具

院内感染监控系统 开发工具Delphi7 报表工具FastReport unit U_Ymjg;interfaceusesWindows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,Dialogs, RzButton, ExtCtrls, RzPanel, ImgList, Grids, RzGrids, StdCtrls,RzCmboBx, DB, ADODB;typeTFrm_ym…

Python:程序中如何引用环境变量

应用场景&#xff1a;具有安全性的信息&#xff08;如密钥&#xff09;&#xff0c;为方式代码提交被同时提交到公共环境&#xff08;如git&#xff09;&#xff0c;可以通过环境变量配置后&#xff0c;在代码中直接引用。 优点&#xff1a;安全、复用性强、持久化&#xff08…

电力场景绝缘子缺陷识别分割数据集labelme格式1099张3类别

数据集格式&#xff1a;labelme格式(不包含mask文件&#xff0c;仅仅包含jpg图片和对应的json文件) 图片数量(jpg文件个数)&#xff1a;1099 标注数量(json文件个数)&#xff1a;1099 标注类别数&#xff1a;3 标注类别名称:["brokenpart","brokeninsulator…

C++ -- 哈希表封装实现unordered_map 和 unordered_set

本章内容分为源码看框架讲解和结构模拟实现两部分&#xff0c;源码框架是让我们了解容器结构在设计时的思路&#xff0c;模拟实现才是重点。因此如果在看源码结构式感到疑惑&#xff0c;不妨继续往下看&#xff0c;相信一切都会慢慢了解~ 源码及框架分析 在C98 / SGI-STL30版本…

修改vscode中emmet中jsx和tsx语法中className的扩展符号从单引号到双引号 - HTML代码补全 - 单引号双引号

效果图 实现步骤 文件 > 首选项 > 设置搜索“”在settings.json中修改&#xff0c;增加 "emmet.syntaxProfiles": {"html": {"attr_quotes": "single"},"jsx": {"attr_quotes": "double","…

CSS学习记录12

CSS浮动 CSSfloat属性规定元素如何浮动 CSSclear属性规定哪些元素可以在清除的元素旁边以及在哪一侧浮动。 float属性 float属性用于定位和格式化内容&#xff0c;例如让图像向左浮动到容器的文本那里。 float属性可以设置以下值之一&#xff1a; left - 元素浮动到其容器…

IDEA搭建SpringBoot,MyBatis,Mysql工程项目

目录 一、前言 二、项目结构 三、初始化项目 四、SpringBoot项目集成Mybatis编写接口 五、代码仓库 一、前言 构建一个基于Spring Boot框架的现代化Web应用程序&#xff0c;以满足[公司/组织名称]对于[业务需求描述]的需求。通过利用Spring Boot简化企业级应用开发的优势&…

Redis应用—4.在库存里的应用

大纲 1.库存模块设计 2.库存缓存分片和渐进式同步方案 3.基于缓存分片的下单库存扣减方案 4.商品库存设置流程与异步落库的实现 6.库存入库时"缓存分片写入 渐进式写入 写入失败进行MQ补偿"的实现 7.库存扣减时"基于库存分片依次扣减 合并扣减 扣不了…

25. 深浅拷贝

一、什么是浅拷贝 只对对象的最顶层进行的拷贝称为 浅拷贝。我们可以用 copy 模块中的 copy() 方法实现浅拷贝。 import copya [11, 22, 33] b [44, 55, 66] c [a, b] d copy.copy(c)print(f"c: {c}") print(f"d: {d}") print(f"c d: {c d}&q…

【GCC】2015: draft-alvestrand-rmcat-congestion-03 机器翻译

腾讯云的一个分析,明显是看了这个论文和草案的 : 最新的是应该是这个 A Google Congestion Control Algorithm for Real-Time Communication draft-ietf-rmcat-gcc-02 下面的这个应该过期了: draft-alvestrand-rmcat-congestion-03