pytroch笔记

一 随机数生成器种子

def make_deterministic(seed):
    # https://github.com/pytorch/pytorch/issues/7068#issuecomment-487907668
    random.seed(seed)
    os.environ['PYTHONHASHSEED'] = str(seed)
    np.random.seed(seed)
    torch.manual_seed(seed)
    torch.cuda.manual_seed(seed)
    torch.cuda.manual_seed_all(seed)  # if you are using multi-GPU.
    torch.backends.cudnn.benchmark = False
    torch.backends.cudnn.deterministic = True

这段代码是在Python中,特别是使用了NumPy和PyTorch进行科学计算或深度学习时,用来设置随机数生成器种子的。这样做可以确保你的代码具有确定性,即多次运行下相同的输入将产生相同的输出,这对于确保实验的可重复性非常重要。以下是每行代码的具体解释:

  1. random.seed(seed):
  • 这行设置了Python内置的随机数生成器的种子。这影响所有使用Python内置random模块的随机数生成,使得其随机序列是可以预测的。
  1. os.environ['PYTHONHASHSEED'] = str(seed):
  • 设置环境变量PYTHONHASHSEED为特定的字符串表示的种子。这个变量控制Python 哈希(hash)的随机化。对于一些版本的Python,设置这个种子可以禁用哈希随机化,从而确保对象的哈希值在多次程序运行时是一致的。
  1. np.random.seed(seed):
  • 这行代码设置了NumPy随机数生成器的种子。NumPy广泛用于科学计算中的随机数生成,设定种子保证了NumPy操作(如随机数组生成)的确定性。
  1. torch.manual_seed(seed):
  • 这一行设置了PyTorch的随机数生成器的种子,对CPU操作影响。
  1. torch.cuda.manual_seed(seed):
  • 设置了CUDA随机数生成器的种子,只影响当前GPU。
  1. torch.cuda.manual_seed_all(seed):
  • 如果你使用多GPU,这行代码会设置所有CUDA随机数生成器的种子。
  1. torch.backends.cudnn.benchmark = False:
  • 这行代码禁用了cuDNN的自动优化器。因为自动优化器会在运行时根据计算图形选择最快的操作算法,这可能会导致程序每次运行时的行为略有不同。禁用此功能可以增加程序的确定性。
  1. torch.backends.cudnn.deterministic = True:
  • 设置这个选项后,cuDNN将仅使用确定性的卷积算法。这意味着对于固定的输入和网络,卷积的输出将在多次运行间保持一致。这对于需要重复实验结果的情况非常有用,但可能会牺牲一些性能。

总的来说,上述代码的目的是为了确保当你的代码使用随机数生成功能时,能够产生可重复的结果,这在进行科学研究和实验时非常重要。通过固定随机数种子,你可以确保每次运行代码时,即使是涉及随机选择的算法(如初始化模型权重、选择数据子集等),也能得到相同的结果。这有助于其他研究人员复制你的实验,以及在调试时跟踪问题。

二、动态加载和修改预训练模型

def get_image_encoder(name, pretrained=True):
    weights = "DEFAULT" if pretrained else None
    model = getattr(torchvision.models, name)(weights=weights)
    if name.startswith('vgg'):
        model.classifier[6] = nn.Identity()
    elif name.startswith('resnet'):
        model.fc = nn.Identity()
    elif name.startswith('vit'):
        model.heads = nn.Identity()
    elif name.startswith('convnext'):
        model.classifier[-1] = nn.Identity()
    else:
        raise ValueError(f"Unsupported image encoder: {
     name}")
    # Infer the output size of the image encoder
    with torch.inference_mode():
        out = model(torch.randn(5, 3, 224, 224))
    assert out.dim() == 2
    assert out.size(0) == 5
    image_encoder_output_dim = out.size(1)
    return model, image_encoder_output_dim

这段代码是一个Python函数的一部分,该函数用于动态加载和修改预训练的计算机视觉模型,并确定模型的输出维度。下面是代码的逐行解析:

  1. weights = "DEFAULT" if pretrained else None:
  • 这行代码是一个条件表达式,用于设置weights变量的值。如果变量pretrainedTrue,则weights被设置为字符串"DEFAULT",这意味着函数将加载有预训练权重的模型。否则,weights被设置为None,表示不使用预训练权重。
  1. model = getattr(torchvision.models, name)(weights=weights):
  • 这行代码利用getattr函数动态获取torchvision.models中名为name的模型类,并实例化该模型。如果pretrainedTrue,则使用默认的预训练权重。
  1. 接下来的几行代码根据模型的名称来修改模型的分类器部分:
  • 如果模型名称以'vgg'开头,将VGG模型的分类器的最后一层替换为nn.Identity(),这是一个占位层,其目的是不改变输入数据。
  • 如果模型名称以'resnet'开头,将ResNet模型的全连接层(fc)替换为nn.Identity()
  • 如果模型名称以'vit'开头,将Vision Transformer模型的头(heads)替换为nn.Identity()
  • 如果模型名称以'convnext'开头,将ConvNeXt模型的分类器的最后一层替换为nn.Identity()

这一步通常在你想要使用这些模型作为特征提取器时进行。通过替换最后的层,你可以获取中间层的输出,而不是最终的分类结果。

  1. else块中,如果模型名称不是上述几种模型之一,将抛出ValueError异常,指出不支持的图像编码器。
  2. with torch.inference_mode():块中:
  • 使用torch.inference_mode()上下文管理器来进行推理,这意味着在这个块中的计算不会保存梯度,从而节省内存并提高计算速度。
  • out = model(torch.randn(5, 3, 224, 224))行创建了一个形状为(5, 3, 224, 224)的随机张量,这模拟了5个具有3个颜色通道(例如RGB)和224x224像素的图像。然后通过模型进行前向传递以产生输出。
  1. 接下来的两个assert语句用于验证模型输出:
  • assert out.dim() == 2确认输出out是二维的,这通常意味着每个样本都有一个一维的输出向量。
  • assert out.size(0) == 5确保输出批次的大小为5,即输入批次中的样本数量。
  1. image_encoder_output_dim = out.size(1):
  • 这行代码获取输出向量的维度,即模型对每个输入图像生成的特征数量。
  1. 最后,函数返回修改后的模型和图像编码器的输出维度。

整体来说,这段代码用于准备和调整模型,使其适用于特征提取任务,而非最终的分类任务,并且能确定模型输出特征的维度。这在转移学习或多任务学习的上下文中是很常见的做法。

三、权重初始化

Apply Kaiming initialization to the attribute predictors

    for predictor in self.attribute_predictors:
        nn.init.kaiming_normal_(predictor.weight, nonlinearity='relu')
        nn.init.zeros_(predictor.bias)

这段代码是用Python语言编写的,具体来说是使用了PyTorch这个深度学习框架。它的目的是对一个神经网络中的属性预测器(attribute predictors)部分进行参数初始化。这里分为两步:

  1. nn.init.kaiming_normal_(predictor.weight, nonlinearity='relu'):
    这一行对每个属性预测器的权重(weight)进行Kaiming/He正态分布初始化。这种初始化方法是由Kaiming He等人提出的,特别适合配合ReLU激活函数使用的深度神经网络。它尝试保持输入和输出的方差一致,以此来避免在前向传播和反向传播时梯度消失或爆炸的问题。
  2. nn.init.zeros_(predictor.bias):
    这一行将每个属性预测器的偏置(bias)初始化为零。这是一个常见的偏置初始化方法,它简单地将所有偏置值设置为零。

综上所述,这段代码中的循环遍历了一个名为self.attribute_predictors的网络部分中的所有属性预测器,对每个预测器的权重和偏置进行了适当的初始化。这是训练深度神经网络时的一个重要步骤,因为合适的初始化可以显著提高训练的效率和最终模型的性能。

相关推荐

  1. pytroch笔记

    2024-02-22 03:32:01       33 阅读
  2. pytorch入门笔记

    2024-02-22 03:32:01       28 阅读
  3. PyTorch学习笔记(一)

    2024-02-22 03:32:01       25 阅读
  4. PyTorch学习笔记(三)

    2024-02-22 03:32:01       23 阅读
  5. PyTorch学习笔记(四)

    2024-02-22 03:32:01       21 阅读
  6. PyTorch学习笔记(六)

    2024-02-22 03:32:01       20 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-02-22 03:32:01       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-02-22 03:32:01       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-02-22 03:32:01       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-02-22 03:32:01       18 阅读

热门阅读

  1. 力扣-217. 存在重复元素

    2024-02-22 03:32:01       25 阅读
  2. Rust语言之异步写文件

    2024-02-22 03:32:01       29 阅读
  3. 炫技亮点 优雅处理数据流程 过滤器模式

    2024-02-22 03:32:01       29 阅读
  4. 类和对象 下(再谈构造函数 static成员 友元)

    2024-02-22 03:32:01       32 阅读
  5. 【Linux 内核源码分析】内存管理——Slab 分配器

    2024-02-22 03:32:01       29 阅读
  6. C++面试高频问题汇总( 一)

    2024-02-22 03:32:01       36 阅读
  7. gtowizard合租cash和锦标赛mtt

    2024-02-22 03:32:01       26 阅读
  8. 前端常见面试题

    2024-02-22 03:32:01       26 阅读
  9. Qt 基本知识

    2024-02-22 03:32:01       28 阅读
  10. webrtc 中 FIR PLI 有何区别? 分别适用于什么场景

    2024-02-22 03:32:01       32 阅读
  11. vue 学习definproperty方法

    2024-02-22 03:32:01       32 阅读
  12. Gradio学习(二)—————学习block布局

    2024-02-22 03:32:01       27 阅读