PyTorch之F.pad的使用与报错记录

F.pad的使用与报错记录

原始文档:https://www.yuque.com/lart/ugkv9f/iftd9v

函数原型

函数文档:https://pytorch.org/docs/1.12/generated/torch.nn.functional.pad.html#torch-nn-functional-pad

torch.nn.functional.pad(input, pad, mode='constant', value=None) → Tensor

Padding格式

  • 1D-tensor:(p_left, p_right)
  • 2D-tensor:(p_left, p_right, p_top, p_bottom)
  • 3D-tensor:(p_left, p_right, p_top, p_bottom, p_front, p_back)

四种模式

这一函数用于实现对高维tensor的形状补齐操作。PyTorch本身提供了四种padding模式:

  • constant:使用指定的常数value补齐指定的维度。对于数据012,使用0补齐,结果可以为0001200
  • reflect:使用tensor自身的值按照“反射”的方式补齐指定的维度。对于数据012,结果可以为2101210
  • replicate:使用tensor自身边界值补齐指定的维度。对于数据012,结果可以为0001222
  • circular:使用tensor自身的值按照“循环”的方式补齐指定的维度。对于数据012,结果可以为1201201

需要注意的是,文档强调了这一点:

Constant padding is implemented for arbitrary dimensions.
Replicate and reflection padding are implemented for padding the last 3 dimensions of a 4D or 5D input tensor, the last 2 dimensions of a 3D or 4D input tensor, or the last dimension of a 2D or 3D input tensor.

这四种模式使用输出展示会更便于理解一些,下面是一个例子:

import torch
import torch.nn.functional as F

pad = [2, 2, 2, 2]
x = torch.arange(9, dtype=torch.float32).reshape(1, 1, 3, 3)

print("x")
print(x)

print("F.pad(x, pad=pad, mode='constant', value=0)")
print(F.pad(x, pad=pad, mode='constant', value=0))

print("F.pad(x, pad=pad, mode='replicate')")
print(F.pad(x, pad=pad, mode='replicate'))

print("F.pad(x, pad=pad, mode='reflect')")
print(F.pad(x, pad=pad, mode='reflect'))

print("F.pad(x, pad=pad, mode='circular')")
print(F.pad(x, pad=pad, mode='circular'))

对应的输出为:

x
tensor([[[[0., 1., 2.],
          [3., 4., 5.],
          [6., 7., 8.]]]])
F.pad(x, pad=pad, mode='constant', value=0)
tensor([[[[0., 0., 0., 0., 0., 0., 0.],
          [0., 0., 0., 0., 0., 0., 0.],
          [0., 0., 0., 1., 2., 0., 0.],
          [0., 0., 3., 4., 5., 0., 0.],
          [0., 0., 6., 7., 8., 0., 0.],
          [0., 0., 0., 0., 0., 0., 0.],
          [0., 0., 0., 0., 0., 0., 0.]]]])
F.pad(x, pad=pad, mode='replicate')
tensor([[[[0., 0., 0., 1., 2., 2., 2.],
          [0., 0., 0., 1., 2., 2., 2.],
          [0., 0., 0., 1., 2., 2., 2.],
          [3., 3., 3., 4., 5., 5., 5.],
          [6., 6., 6., 7., 8., 8., 8.],
          [6., 6., 6., 7., 8., 8., 8.],
          [6., 6., 6., 7., 8., 8., 8.]]]])
F.pad(x, pad=pad, mode='reflect')
tensor([[[[8., 7., 6., 7., 8., 7., 6.],
          [5., 4., 3., 4., 5., 4., 3.],
          [2., 1., 0., 1., 2., 1., 0.],
          [5., 4., 3., 4., 5., 4., 3.],
          [8., 7., 6., 7., 8., 7., 6.],
          [5., 4., 3., 4., 5., 4., 3.],
          [2., 1., 0., 1., 2., 1., 0.]]]])
F.pad(x, pad=pad, mode='circular')
tensor([[[[4., 5., 3., 4., 5., 3., 4.],
          [7., 8., 6., 7., 8., 6., 7.],
          [1., 2., 0., 1., 2., 0., 1.],
          [4., 5., 3., 4., 5., 3., 4.],
          [7., 8., 6., 7., 8., 6., 7.],
          [1., 2., 0., 1., 2., 0., 1.],
          [4., 5., 3., 4., 5., 3., 4.]]]])

可能会遇到的报错

常见的错误主要是因为padding的数量超过了对应模式的要求。

对于constantreplicate对于padding并没有限制。

但是另外两种模式replicatecircular就有要求了。

RuntimeError: Argument #4: Padding size should be less than the corresponding input dimension, but got: padding (3, 3) at dimension 3 of input 4

这发生在reflect模式中,padding的数量必须小于对应维度的大小。

import torch
import torch.nn.functional as F

pad = [3, 3, 3, 3]
x = torch.arange(9, dtype=torch.float32).reshape(1, 1, 3, 3)

print("F.pad(x, pad=pad, mode='reflect')")
print(F.pad(x, pad=pad, mode='reflect'))

"""
F.pad(x, pad=pad, mode='reflect')
Traceback (most recent call last):
  File "e:/Coding/PythonTools/TorchPadding/main.py", line 20, in <module>
    print(F.pad(x, pad=pad, mode='reflect'))
  File "D:\Programming\Python\envs\pt1102\lib\site-packages\torch\nn\functional.py", line 4189, in _pad
    return torch._C._nn.reflection_pad2d(input, pad)
RuntimeError: Argument #4: Padding size should be less than the corresponding input dimension, but got: padding (3, 3) at 
dimension 3 of input 4
"""

这一错误仔细思考一下其实也可以理解,因为对于序列012,如果在右侧reflect padding 3位,对于前两位可以直观的获得即为10,但是第三位如何获取就属于未明确定义的问题了。为了解决这个问题,则需要自定义一种规则。

如果我们定义reflect按照三角波的形状周期重复,则扩展后的序列可以设计为:...20121+012+101210...
此时我们则可以直接使用多次reflect padding来等价实现:

x = torch.arange(9, dtype=torch.float32).reshape(1, 1, 3, 3)
print("F.pad(x, pad=pad, mode='reflect')")

# this `pad` will raise an error
# pad = [3, 3, 3, 3]
# print("pad=", pad)
# print(F.pad(x, pad=pad, mode='reflect'))

# let's use a indirect method to imitate `pad = [3, 3, 3, 3]`
pad = [2, 2, 2, 2]
x = F.pad(x, pad=pad, mode='reflect')
pad = [1, 1, 1, 1]
x = F.pad(x, pad=pad, mode='reflect')
print(x)

此时输出:

F.pad(x, pad=pad, mode='reflect')
tensor([[[[4., 5., 4., 3., 4., 5., 4., 3., 4.],
          [7., 8., 7., 6., 7., 8., 7., 6., 7.],
          [4., 5., 4., 3., 4., 5., 4., 3., 4.],
          [1., 2., 1., 0., 1., 2., 1., 0., 1.],
          [4., 5., 4., 3., 4., 5., 4., 3., 4.],
          [7., 8., 7., 6., 7., 8., 7., 6., 7.],
          [4., 5., 4., 3., 4., 5., 4., 3., 4.],
          [1., 2., 1., 0., 1., 2., 1., 0., 1.],
          [4., 5., 4., 3., 4., 5., 4., 3., 4.]]]])

当然还有一个更一般的实现,这里实际上还存在优化的空间,不过作为参考而言已经足够:

import torch
import torch.nn.functional as F

def infinite_reflect_padding(x: torch.Tensor, pad: tuple) -> torch.Tensor:
    """Padding with reflect mode that breaks the limit.

    Args:
        x (torch.Tensor): Input tensor.
        pad (tuple): Padding tuple: left, right, top, bottom

    Returns:
        torch.Tensor: Padded tensor.
    """
    B, C, H, W = x.shape
    assert len(pad) == 4
    if W == 1:
        # must not pad the tensor.
        if not (pad[0] == 0 and pad[1] == 0):
            raise ValueError(pad)
    if H == 1:
        # must not pad the tensor.
        if not (pad[2] == 0 and pad[3] == 0):
            raise ValueError(pad)
    base_pad = [W-1, W-1, H-1, H-1]

    first_padding = []
    other_padding = []
    for p, base_p in zip(pad, base_pad):
        if p <= base_p:
            first_padding.append(p)
            other_padding.append([0, 0])
        else:
            first_padding.append(base_p)
            other_padding.append(divmod(p, base_p))

    x = F.pad(x, pad=first_padding, mode='reflect')
    for i, (quotient, remainder) in enumerate(other_padding):
        pad_template = [0, 0, 0, 0]
        for _ in range(quotient):
            pad_template[i] = base_pad[i]
            x = F.pad(x, pad=pad_template, mode='reflect')
        pad_template[i] = remainder
        x = F.pad(x, pad=pad_template, mode='reflect')
    return x


# let's use a indirect method to imitate it
x = torch.arange(12, dtype=torch.float32).reshape(1, 1, 3, 4)
print("F.pad(x, pad=pad, mode='reflect')")
x = infinite_reflect_padding(x, pad=(2, 3, 5, 4))
print(x)

输出:

F.pad(x, pad=pad, mode='reflect')
tensor([[[[ 6.,  5.,  4.,  5.,  6.,  7.,  6.,  5.,  4.],
          [10.,  9.,  8.,  9., 10., 11., 10.,  9.,  8.],
          [ 6.,  5.,  4.,  5.,  6.,  7.,  6.,  5.,  4.],
          [ 2.,  1.,  0.,  1.,  2.,  3.,  2.,  1.,  0.],
          [ 6.,  5.,  4.,  5.,  6.,  7.,  6.,  5.,  4.],
          [10.,  9.,  8.,  9., 10., 11., 10.,  9.,  8.],
          [ 6.,  5.,  4.,  5.,  6.,  7.,  6.,  5.,  4.],
          [ 2.,  1.,  0.,  1.,  2.,  3.,  2.,  1.,  0.],
          [ 6.,  5.,  4.,  5.,  6.,  7.,  6.,  5.,  4.],
          [10.,  9.,  8.,  9., 10., 11., 10.,  9.,  8.],
          [ 6.,  5.,  4.,  5.,  6.,  7.,  6.,  5.,  4.],
          [ 2.,  1.,  0.,  1.,  2.,  3.,  2.,  1.,  0.],
          [ 6.,  5.,  4.,  5.,  6.,  7.,  6.,  5.,  4.],
          [10.,  9.,  8.,  9., 10., 11., 10.,  9.,  8.],
          [ 6.,  5.,  4.,  5.,  6.,  7.,  6.,  5.,  4.],
          [ 2.,  1.,  0.,  1.,  2.,  3.,  2.,  1.,  0.]]]])

AssertionError: Padding value causes wrapping around more than once.

这发生在circular模式中,padding的数量不得超出原始tensor对应维度的大小。

import torch
import torch.nn.functional as F

pad = [4, 4, 4, 4]
x = torch.arange(9, dtype=torch.float32).reshape(1, 1, 3, 3)

print("F.pad(x, pad=pad, mode='circular')")
print(F.pad(x, pad=pad, mode='circular'))

"""
F.pad(x, pad=pad, mode='circular')
Traceback (most recent call last):
  File "e:/Coding/PythonTools/TorchPadding/main.py", line 17, in <module>
    print(F.pad(x, pad=pad, mode='circular'))
  File "D:\Programming\Python\envs\pt1102\lib\site-packages\torch\nn\functional.py", line 4193, in _pad
    return _pad_circular(input, pad)
  File "D:\Programming\Python\envs\pt1102\lib\site-packages\torch\nn\functional.py", line 4585, in _pad_circular
    assert padding[-(idx * 2 + 1)] <= size, "Padding value causes wrapping around more than once."
AssertionError: Padding value causes wrapping around more than once.
"""
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
### 回答1: pytorch_model.bin是PyTorch模型的二进制文件,可以通过以下步骤使用: 1. 导入PyTorch库 ```python import torch ``` 2. 加载模型 ```python model = torch.load('pytorch_model.bin') ``` 3. 使用模型进行推理 ```python output = model(input) ``` 其中,input是输入数据,output是模型的输出结果。 需要注意的是,pytorch_model.bin文件必须与模型的代码文件在同一目录下,否则需要指定文件路径。另外,如果模型是在GPU上训练的,需要使用torch.load函数的map_location参数将模型加载到CPU上。 ```python model = torch.load('pytorch_model.bin', map_location=torch.device('cpu')) ``` ### 回答2: pytorch_model.bin是PyTorch模型的二进制文件,包含了训练好的模型权重参数。使用pytorch_model.bin可以重载一个已经训练好的模型,然后可以继续训练,或者使用它进行发现、推理、评估等操作。 在使用pytorch_model.bin之前,需要准备好一个PyTorch模型。这个模型可以是在PyTorch中编写的代码,也可以是通过其他代码库或工具(如ONNX)导出的模型。接下来,我们将介绍如何将pytorch_model.bin应用到一个PyTorch模型。 1. 导入PyTorch库和模型 首先,需要导入PyTorch库和创建模型的Python代码。以下代码展示了如何导入一个预训练的ResNet-50模型: ``` import torch import torchvision.models as models model = models.resnet50(pretrained=True) ``` 在这个例子中,我们首先导入了PyTorch库,然后使用torchvision包中的models模块来加载ResNet-50模型。我们将预训练的模型权重设置为True,这将下载pytorch_model.bin文件,包含了预训练的模型权重。模型现在已经被加载到内存中了。 2. 保存/加载模型权重 接下来,我们需要保存预训练的模型权重。通常情况下,如果您在使用PyTorch进行新的训练,在每个训练周期后,您都应该保存模型权重。这可以通过以下代码完成: ``` torch.save(model.state_dict(), 'resnet50_weights.pth') ``` 这个代码将模型权重保存到名为resnet50_weights.pth的文件中。后续需要使用它进行推理或继续训练时,可以使用以下代码来加载pytorch_model.bin模型权重。 ``` model.load_state_dict(torch.load('resnet50_weights.pth')) ``` 这个代码将预训练的模型权重从resnet50_weights.pth文件中加载,并将它们赋值给ResNet-50模型。模型现在包含了从预训练模型中学得的权重。 3. 推理、预测和评估 现在,您已经成功加载了预训练的模型,可以使用它进行推理、预测或评估。这可以使用PyTorch的前向传递函数来完成。以下是一个使用ResNet-50进行图像分类的例子: ``` import numpy as np from PIL import Image import torchvision.transforms as transforms # Load image img = Image.open('test_image.jpg') # Preprocess image for ResNet-50 preprocess = transforms.Compose([ transforms.Resize(256), transforms.CenterCrop(224), transforms.ToTensor(), transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) ]) img_tensor = preprocess(img) img_tensor = img_tensor.unsqueeze(0) # Predict image label using ResNet-50 model.eval() with torch.no_grad(): output = model(img_tensor) probabilities = torch.nn.functional.softmax(output[0], dim=0) predicted_class_idx = np.argmax(probabilities.cpu().numpy()) # Print predicted class print('Predicted class: ', predicted_class_idx) ``` 在这个例子中,我们首先加载了一个图片,然后使用transforms对图片进行预处理(ResNet-50期望的处理方式,用于训练数据)。接下来,我们使用模型的evaluate()方法,运行前向传递函数和softmax函数,得出最可能的输出标签。模型现在已经使用pytorch_model.bin重载完毕,图片也被妥善预处理。 以上就是pytorch_model.bin的使用方法。总体而言,pytorch_model.bin允许我们重载训练好的模型,然后对新的数据进行推理、发现和评估。当然,这需要您前先在PyTorch中编写或导入一个好的模型。 ### 回答3: PyTorch是一个常用的深度学习框架,用于构建和训练各种神经网络模型。其中,pytorch_model.bin是PyTorch保存模型权重的二进制文件,它包含了训练好的模型的所有参数值。如何使用pytorch_model.bin文件呢?下面将给出详细的解释。 1. 加载模型 首先,我们需要加载保存的模型,这可以通过以下代码实现: ```python import torch from transformers import BertModel, BertConfig # 加载模型的配置文件 config = BertConfig.from_pretrained('bert-base-chinese', output_attentions=False, output_hidden_states=True) # 加载模型参数 model = BertModel.from_pretrained('bert-base-chinese', config=config) ``` 上述代码中,我们首先加载了bert-base-chinese预训练模型的配置文件,即BertConfig。然后,通过BertModel.from_pretrained()方法加载预训练模型的所有参数。这里,我们将参数保存在本地文件夹中,并使用from_pretrained()方法来加载这个文件夹。 2. 加载pytorch_model.bin文件 接下来,我们可以使用torch.load()方法来加载pytorch_model.bin文件: ```python # 加载pytorch_model.bin文件 model.load_state_dict(torch.load('pytorch_model.bin'), strict=False) ``` 这里,我们使用了load_state_dict()方法来加载pytorch_model.bin文件中保存的模型权重。需要注意的是,strict参数默认为True,表示只加载与模型结构完全匹配的参数,如果文件中存在一些未知的键,则会报错。因此,我们将strict设置为False,在加载模型时忽略不存在的键。 3. 预测 最后,我们可以使用已加载的模型来进行预测: ```python # 输入需要预测的数据 inputs = { 'input_ids': torch.tensor(input_ids).unsqueeze(0), 'attention_mask': torch.tensor(attention_mask).unsqueeze(0), 'token_type_ids': torch.tensor(token_type_ids).unsqueeze(0), } # 预测结果 outputs = model(**inputs) ``` 这里,我们需要将输入数据转换为PyTorch张量格式,并使用model()方法进行预测。预测结果将保存在outputs变量中,我们可以根据需要进行进一步处理。 总之,pytorch_model.bin文件是PyTorch保存模型权重的二进制文件,如果要使用这个文件,我们需要先加载模型配置文件,并使用from_pretrained()方法加载预训练模型的所有参数;然后,使用load_state_dict()方法加载pytorch_model.bin文件中保存的模型权重;最后,使用加载的模型进行预测。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值