添加视觉处理组件
添加视觉模型需要在标准的模块化方法之上增加图像或视频处理组件。仅处理图像的模型需要图像处理器,而视频模型则需要视频处理器,两者均可通过AutoImageProcessor和AutoVideoProcessor入口点访问。
对于建模和配置步骤,请先遵循 模块化 指南。
图像处理器
当模型需要处理图像时,请创建图像处理器。torchvision 后端是默认选项,并支持 GPU 加速。如果 torchvision 不可用,则回退到 PIL。
两个图像处理器类共享相同的预处理逻辑,但使用不同的后端。它们的构造函数签名和默认值必须完全一致。AutoImageProcessor.from_pretrained() 在加载时选择后端,并在 torchvision 不可用时回退到 PIL。签名不一致会导致同一份已保存的配置在不同环境中表现出不同的行为。
torchvision
创建 image_processing_<model_name>.py,其中包含一个继承自 TorchvisionBackend 的类。如果您的处理器需要标准 [ImagesKwargs] 之外的自定义参数,请定义一个 kwargs 类。
from ...image_processing_backends import TorchvisionBackend
from ...image_utils import OPENAI_CLIP_MEAN, OPENAI_CLIP_STD, PILImageResampling
from ...processing_utils import ImagesKwargs, Unpack
from ...utils import auto_docstring
class MyModelImageProcessorKwargs(ImagesKwargs, total=False):
tile_size: int # any model-specific kwargs
@auto_docstring
class MyModelImageProcessor(TorchvisionBackend):
resample = PILImageResampling.BICUBIC
image_mean = OPENAI_CLIP_MEAN
image_std = OPENAI_CLIP_STD
size = {"shortest_edge": 224}
do_resize = True
do_rescale = True
do_normalize = True
do_convert_rgb = True
def __init__(self, **kwargs: Unpack[MyModelImageProcessorKwargs]):
super().__init__(**kwargs)PIL
创建 image_processing_pil_<model_name>.py,其中包含一个继承自 PilBackend 的类。在此处复制 kwargs 类,而不是从 torchvision 文件中导入,因为当 torchvision 未安装时导入可能会失败。添加一个 # Adapted from 注释,以便两者保持同步。对于没有自定义参数的处理器,直接使用 ImagesKwargs。
from ...image_processing_backends import PilBackend
from ...image_utils import OPENAI_CLIP_MEAN, OPENAI_CLIP_STD, PILImageResampling
from ...processing_utils import ImagesKwargs, Unpack
from ...utils import auto_docstring
# Adapted from transformers.models.my_model.image_processing_my_model.MyModelImageProcessorKwargs
class MyModelImageProcessorKwargs(ImagesKwargs, total=False):
tile_size: int # any model-specific kwargs
@auto_docstring
class MyModelImageProcessorPil(PilBackend):
resample = PILImageResampling.BICUBIC
image_mean = OPENAI_CLIP_MEAN
image_std = OPENAI_CLIP_STD
size = {"shortest_edge": 224}
do_resize = True
do_rescale = True
do_normalize = True
do_convert_rgb = True
def __init__(self, **kwargs: Unpack[MyModelImageProcessorKwargs]):
super().__init__(**kwargs)添加后处理方法
直接在处理器类中添加后处理方法。后处理方法会接收模型输出(outputs)以及特定后处理方法所需的任何其他参数。
class MyModelImageProcessor(TorchvisionBackend):
...
def post_process_my_task(self, outputs, ...):
...后处理器返回简单对象列表(list[str] 或 list[torch.Tensor])或复杂对象列表(list[MyTaskPostProcessorOutput] 或 list[dict])。后处理器的输出定义在 src/transformers/image_processing_outputs.py 中,并继承自 BatchFeature。
class MyTaskPostProcessorOutput(BatchFeature):
predictions: torch.Tensor
scores: torch.Tensor视频处理器
当模型处理视频或采样的视频帧时,添加一个视频处理器。
在模型目录中创建 video_processing_<model_name>.py。BaseVideoProcessor 继承自 TorchvisionBackend,并提供共享的解码、帧采样、调整大小、重新缩放、归一化、保存和加载行为。
类属性是默认的预处理值。用户可以在初始化时或调用时对其进行覆盖。在可能的情况下,请使用与 VideosKwargs 相同的名称,例如 size、crop_size、do_resize、do_sample_frames、num_frames 和 fps。
如果您的视频处理器需要超出标准 VideosKwargs 的自定义参数,请定义一个 kwargs 类。将其设置为 valid_kwargs,并使用它来注解 __init__,以便进行运行时验证并生成自动文档字符串。
from ...processing_utils import Unpack, VideosKwargs
from ...utils import auto_docstring
from ...video_processing_utils import BaseVideoProcessor
class MyModelVideoProcessorKwargs(VideosKwargs, total=False):
min_frames: int
max_frames: int
@auto_docstring
class MyModelVideoProcessor(BaseVideoProcessor):
size = {"shortest_edge": 224}
crop_size = {"height": 224, "width": 224}
do_resize = True
do_center_crop = True
do_normalize = True
do_sample_frames = True
num_frames = 16
model_input_names = ["pixel_values_videos"]
valid_kwargs = MyModelVideoProcessorKwargs
def __init__(self, **kwargs: Unpack[MyModelVideoProcessorKwargs]):
super().__init__(**kwargs)仅当模型需要基础均匀采样器无法表达的采样规则时,才重写 sample_frames()。例如,某些模型会强制规定帧数的最小值或最大值,或基于模型特定的约束进行采样。
如果模型的前向方法期望使用旧版输入名称,请重写 preprocess,并在调用基类实现后重命名该键。
class MyModelVideoProcessor(BaseVideoProcessor):
model_input_names = ["pixel_values"]
def preprocess(self, videos, **kwargs):
batch = super().preprocess(videos, **kwargs)
batch["pixel_values"] = batch.pop("pixel_values_videos")
return batch通过在转换脚本中实例化视频处理器并调用 save_pretrained(),将视频处理器与检查点一起保存。如果 ProcessorMixin 封装了视频处理器,则改为调用 save_pretrained()。请勿手动创建或编辑预处理配置文件。
注册类
在文件底部将新类添加到 __all__ 中,然后使用以下命令重新生成 __init__.py:
python utils/check_inits.py --fix_and_overwrite
将新类映射到模型配置,以便 Auto 类能够加载它们。生成的自动映射文件顶部包含一条警告。请勿手动编辑该文件。添加或更新模型配置后,运行:
python utils/check_auto.py --fix_and_overwrite
生成映射后,请验证模型类型是否出现在 src/transformers/models/auto/auto_mappings.py 中的相关映射里。
IMAGE_PROCESSOR_MAPPING_NAMES用于 AutoImageProcessor- AutoVideoProcessor 的
VIDEO_PROCESSOR_MAPPING_NAMES
测试
在模型测试目录中为每个视觉处理组件添加测试。使用共享的测试混入类,并提供模型特定的初始化 kwargs。图像测试通过共享的测试器自动发现处理器后端,而视频测试则显式配置其处理器类和测试夹具。
图像处理器测试
图像处理器测试位于 tests/models/<model_name>/test_image_processing_<model_name>.py。请定义一个继承自 ImageProcessingTester 的测试器,以及一个继承自 ImageProcessingTestMixin 和 unittest.TestCase 的测试类。
图像处理器测试器定义了默认测试属性,例如处理器初始化参数以及用于创建测试随机输入的参数。仅当需要与图像处理器默认值不同时,才覆盖这些参数。例如,我们通常使用较小的图像尺寸进行测试,以保持测试速度。图像处理器类会从 IMAGE_PROCESSOR_MAPPING_NAMES 中自动推断。
在测试类上设置 image_processor_tester_class。该混入会创建 self.image_processor_tester,并且已经涵盖了大多数必需的测试方法。
import unittest
from transformers.testing_utils import require_torch, require_vision
from ...test_image_processing_common import ImageProcessingTestMixin, ImageProcessingTester
class MyModelImageProcessingTester(ImageProcessingTester):
def __init__(self, **kwargs):
# Random test inputs kwargs
kwargs.setdefault("batch_size", 2) # default: 7
kwargs.setdefault("num_channels", 4) # default: 3
kwargs.setdefault("min_resolution", 20) # default: 30
kwargs.setdefault("max_resolution", 100) # default: 400
# Image processor init kwargs
kwargs.setdefault("size", {"shortest_edge": 20})
kwargs.setdefault("crop_size", {"height": 18, "width": 18})
super().__init__(**kwargs)
@require_torch
@require_vision
class MyModelImageProcessingTest(ImageProcessingTestMixin, unittest.TestCase):
image_processor_tester_class = MyModelImageProcessingTester
def test_inherits_from_mixin(self):
# Always iterate over all image processing classes
for image_processing_class in self.image_processing_classes.values():
# self.image_processor_dict contains the default processor init kwargs
# including overrides from the tester.
image_processor = image_processing_class(**self.image_processor_dict)
self.assertIsInstance(image_processor, ImageProcessingMixin)为 Mixin 无法推断的行为添加针对性测试,例如自定义调整大小规则或特定于模型的 kwargs。
后处理测试混入类位于 tests/test_image_processing_common.py 中,并叠加在 ImageProcessingTestMixin 之上。
class MyModelImageProcessingTest(ImageProcessingTestMixin, MyTaskPostProcessTestMixin, unittest.TestCase):
image_processor_tester_class = MyModelImageProcessingTester测试会自动验证您的模型是否使用了正确的 mixins。新任务的 mixins 必须添加到 tests/test_image_processing_common.py 中。
视频处理器测试
视频处理器的测试通常位于 tests/models/<model_name>/test_video_processing_<model_name>.py,并继承自 VideoProcessingTestMixin。请设置 fast_video_processing_class,定义 video_processor_dict,如果模型使用的键不是 pixel_values_videos,则需重写 input_name。
from transformers.testing_utils import require_torch, require_vision
from transformers.utils import is_torchvision_available
from ...test_video_processing_common import VideoProcessingTestMixin
@require_torch
@require_vision
class MyModelVideoProcessingTest(VideoProcessingTestMixin, unittest.TestCase):
fast_video_processing_class = MyModelVideoProcessor if is_torchvision_available() else None
input_name = "pixel_values_videos"
@property
def video_processor_dict(self):
return {"size": {"shortest_edge": 224}, "num_frames": 16}添加针对帧采样、元数据处理、解码后的视频输入、帧列表输入以及输出形状的聚焦视频测试。如果你的处理器重命名了 pixel_values_videos,请断言返回的是重命名后的键。
如果模型还包含一个封装图像或视频处理器的 ProcessorMixin,请添加 tests/models/<model_name>/test_processing_<model_name>.py 并继承自 ProcessorTesterMixin。设置 processor_class,并为那些无法在不提供参数的情况下构建的组件重写 _setup_<component>() 类方法。使用 _setup_test_attributes() 来暴露通用处理器测试所使用的占位符标记。
from ...test_processing_common import ProcessorTesterMixin
class MyModelProcessorTest(ProcessorTesterMixin, unittest.TestCase):
processor_class = MyModelProcessor
@classmethod
def _setup_image_processor(cls):
return cls._get_component_class_from_processor("image_processor")(size={"shortest_edge": 224})
@classmethod
def _setup_video_processor(cls):
return cls._get_component_class_from_processor("video_processor")(num_frames=2)
@classmethod
def _setup_test_attributes(cls, processor):
cls.image_token = getattr(processor, "image_token", "")
cls.video_token = getattr(processor, "video_token", "")