AutoImageProcessor代码分析
以下是对 AutoImageProcessor
类的整理,按照类属性、类方法、静态方法、实例属性和实例方法分类,并对每个方法的功能进行了描述。
类属性
无显式定义的类属性。
全局方法
IMAGE_PROCESSOR_MAPPING_NAMES
1. 遍历 IMAGE_PROCESSOR_MAPPING_NAMES
字典
for model_type, image_processors in IMAGE_PROCESSOR_MAPPING_NAMES.items():
- 目的:遍历所有模型类型及其对应的图像处理器类名。
- 变量说明:
model_type
:模型的类型字符串,例如'vit'
、'bert'
等。image_processors
:一个元组,包含慢速和(可选)快速图像处理器类名,例如('ViTImageProcessor', 'ViTImageProcessorFast')
。
2. 解包图像处理器类名
slow_image_processor_class, *fast_image_processor_class = image_processors
- 目的:拆分图像处理器类名,分别获取慢速和快速版本的类名。
- 解释:
slow_image_processor_class
:慢速图像处理器类名,必定存在(即image_processors
的第一个元素)。fast_image_processor_class
:列表,包含剩余的快速图像处理器类名(可能为空,如果没有快速版本)。
3. 检查视觉库(如 PIL)是否可用
if not is_vision_available():
slow_image_processor_class = None
- 目的:如果视觉库不可用,则无法使用慢速图像处理器,将其类名设为
None
。 - 函数:
is_vision_available()
:检查 PIL(或其他必要视觉库)是否可用。
- 结果:
- 如果 PIL 不可用,
slow_image_processor_class
被设为None
。
- 如果 PIL 不可用,
4. 检查快速图像处理器的可用性
if not fast_image_processor_class or fast_image_processor_class[0] is None or not is_torchvision_available():
fast_image_processor_class = None
else:
fast_image_processor_class = fast_image_processor_class[0]
- 目的:根据条件确定是否可以使用快速图像处理器,并适当设置其类名。
- 解释:
- 条件判断内容:
not fast_image_processor_class
:没有提供快速图像处理器类名。fast_image_processor_class[0] is None
:快速图像处理器类名为None
。not is_torchvision_available()
:torchvision
库不可用。
- 如果以上任何一个条件为真,表示无法使用快速图像处理器,将
fast_image_processor_class
设为None
。 - 否则,获取实际的快速图像处理器类名(列表的第一个元素)。
- 条件判断内容:
5. 更新 IMAGE_PROCESSOR_MAPPING_NAMES
字典
IMAGE_PROCESSOR_MAPPING_NAMES[model_type] = (slow_image_processor_class, fast_image_processor_class)
- 目的:将当前模型类型的图像处理器类名更新为根据可用性调整后的结果。
- 结果:
IMAGE_PROCESSOR_MAPPING_NAMES
中,每个model_type
的值变为一个包含可能为None
的慢速和快速图像处理器类名的元组。
总结
这段代码的核心作用是:
-
动态调整可用的图像处理器类名:根据环境中安装的库(如 PIL、torchvision),将不可用的图像处理器类名设为
None
。 -
确保后续实例化安全:在使用图像处理器时,如果某个版本(慢速或快速)不可用,程序不会尝试加载,从而避免运行时错误。
IMAGE_PROCESSOR_MAPPING
1. 创建懒加载的映射 IMAGE_PROCESSOR_MAPPING
IMAGE_PROCESSOR_MAPPING = _LazyAutoMapping(CONFIG_MAPPING_NAMES, IMAGE_PROCESSOR_MAPPING_NAMES)
- 目的:创建一个懒加载的映射,将模型配置类映射到对应的图像处理器类。
- 解释:
_LazyAutoMapping
:一个用于延迟加载的映射类,只有在实际使用时才会加载对应的模块或类。CONFIG_MAPPING_NAMES
:模型配置名称映射,用于将模型类型映射到配置类。IMAGE_PROCESSOR_MAPPING_NAMES
:之前更新的图像处理器类名映射。
总结
这段代码的核心作用是:
- 映射模型配置到图像处理器:最终生成的
IMAGE_PROCESSOR_MAPPING
映射,用于在程序中根据模型配置自动找到适当的图像处理器类。
get_image_processor_class_from_name
函数功能概述
def get_image_processor_class_from_name(class_name: str):
...
函数 get_image_processor_class_from_name
的作用是根据提供的类名字符串 class_name
,返回对应的图像处理器类对象。它在预定义的映射和可用的模块中查找类名,尝试导入相应的模块并获取类对象。如果未找到类名,且可能是由于依赖库缺失导致的,则在主 transformers
模块中查找,以返回一个适当的占位符类,从而在实例化时提供有用的错误信息。
1. 特殊处理 BaseImageProcessorFast
if class_name == "BaseImageProcessorFast":
return BaseImageProcessorFast
- 目的:如果传入的类名是
"BaseImageProcessorFast"
,直接返回BaseImageProcessorFast
类对象。 - 解释:这是一个特殊情况处理,避免在后续过程中不必要的查找。
2. 在 IMAGE_PROCESSOR_MAPPING_NAMES
中查找类名
for module_name, extractors in IMAGE_PROCESSOR_MAPPING_NAMES.items():
if class_name in extractors:
module_name = model_type_to_module_name(module_name)
module = importlib.import_module(f".{module_name}", "transformers.models")
try:
return getattr(module, class_name)
except AttributeError:
continue
- 目的:遍历
IMAGE_PROCESSOR_MAPPING_NAMES
字典,查找是否有匹配的类名。 - 步骤:
- 遍历:
module_name
:模型类型的名称,例如'vit'
。extractors
:与模型类型关联的图像处理器类名元组,包含慢速和快速版本的类名。
- 检查:如果
class_name
在extractors
中,表示找到了对应的图像处理器类。 - 转换模块名称:
- 使用
model_type_to_module_name
函数将module_name
转换为符合模块导入的名称格式。
- 使用
- 导入模块:
- 使用
importlib.import_module
动态导入模块,模块路径为transformers.models.{module_name}
。
- 使用
- 获取类对象:
- 使用
getattr
从模块中获取类对象。 - 如果成功,返回类对象。
- 如果发生
AttributeError
,表示类未在模块中定义,继续下一次循环。
- 使用
- 遍历:
3. 在额外注册的内容中查找类名
for _, extractors in IMAGE_PROCESSOR_MAPPING._extra_content.items():
for extractor in extractors:
if getattr(extractor, "__name__", None) == class_name:
return extractor
- 目的:检查在运行时动态注册的额外内容中,是否存在匹配的类名。
- 解释:
- 遍历
IMAGE_PROCESSOR_MAPPING
的_extra_content
,这是在运行时通过register
方法添加的额外映射。 - 对于每个
extractor
,检查其__name__
属性是否与class_name
匹配。 - 如果找到匹配的类,返回类对象。
- 遍历
4. 处理可能缺少的依赖
main_module = importlib.import_module("transformers")
if hasattr(main_module, class_name):
return getattr(main_module, class_name)
- 目的:如果在以上步骤未找到类名,且可能是由于依赖库缺失导致的,则在主
transformers
模块中查找。 - 解释:
- 导入主模块
transformers
。 - 使用
hasattr
检查主模块中是否存在名为class_name
的属性。 - 如果存在,使用
getattr
获取并返回类对象。
- 导入主模块
- 原因:当某些依赖库(如 PIL、torchvision 等)缺失时,相关的图像处理器类会被定义为占位符类(通常在主模块中),在实例化时会抛出友好的错误信息,提示用户安装缺失的依赖。
5. 返回 None
表示未找到类
return None
- 目的:如果所有查找都未能找到匹配的类名,返回
None
。 - 解释:调用该函数的代码应当处理
None
的返回值,可能会抛出异常或采取其他措施。
函数工作流程总结
-
特殊情况处理:如果类名是
"BaseImageProcessorFast"
,直接返回对应的类对象。 -
在预定义映射中查找:遍历
IMAGE_PROCESSOR_MAPPING_NAMES
,尝试导入对应的模块并获取类对象。 -
在动态注册的内容中查找:检查在运行时注册的额外内容中是否存在匹配的类。
-
处理缺失依赖的情况:在主
transformers
模块中查找,如果类存在,返回占位符类。 -
未找到类:如果以上步骤均未找到匹配的类名,返回
None
。
函数调用示例
-
示例 1:类名在预定义映射中
- 调用
get_image_processor_class_from_name("ViTImageProcessor")
。 - 在
IMAGE_PROCESSOR_MAPPING_NAMES
中找到对应的模型类型'vit'
。 - 导入模块
transformers.models.vit
。 - 获取并返回
ViTImageProcessor
类。
- 调用
-
示例 2:类名在动态注册的内容中
- 假设用户通过
AutoImageProcessor.register
方法注册了自定义的图像处理器。 - 调用
get_image_processor_class_from_name("CustomImageProcessor")
。 - 在
_extra_content
中找到并返回CustomImageProcessor
类。
- 假设用户通过
-
示例 3:缺少依赖库导致类无法导入
- 调用
get_image_processor_class_from_name("SomeImageProcessor")
。 - 由于缺少依赖,模块导入失败或类未定义。
- 在主
transformers
模块中查找,返回占位符类。 - 当实例化该占位符类时,提示用户安装缺失的依赖库。
- 调用
类方法
方法名称 | 类型 | 功能说明 |
---|---|---|
from_pretrained | 类方法 | 根据预训练模型的名称或路径,自动加载对应的图像处理器配置,并实例化相应的图像处理器类。该方法会解析配置文件,确定使用哪个具体的图像处理器类,并根据需要下载和加载模型的配置和参数。 |
方法签名
@classmethod
@replace_list_option_in_docstrings(IMAGE_PROCESSOR_MAPPING_NAMES)
def from_pretrained(cls, pretrained_model_name_or_path, *inputs, **kwargs):
@classmethod
:该方法是一个类方法,意味着它不需要实例化类就可以被调用,第一个参数是类本身cls
。@replace_list_option_in_docstrings(IMAGE_PROCESSOR_MAPPING_NAMES)
:这是一个装饰器,用于在文档字符串中替换图像处理器映射名称的列表选项,方便生成更完整的文档。- 参数:
pretrained_model_name_or_path
:预训练模型的名称或路径。*inputs
:可变位置参数,供子类扩展使用。**kwargs
:可变关键字参数,用于传递其他配置项。
方法功能概述
from_pretrained
方法的主要功能是:
- 根据给定的预训练模型名称或路径,加载对应的图像处理器配置文件。
- 解析配置,确定要实例化的具体图像处理器类。
- 根据用户指定或默认的选项,决定是否使用快速版本的图像处理器(如果可用)。
- 处理远程代码加载(如果配置在远程仓库中且被允许)。
- 最终实例化并返回合适的图像处理器对象。
1. 处理过时参数和准备工作
use_auth_token = kwargs.pop("use_auth_token", None)
if use_auth_token is not None:
warnings.warn(
"The `use_auth_token` argument is deprecated and will be removed in v5 of Transformers. Please use `token` instead.",
FutureWarning,
)
if kwargs.get("token", None) is not None:
raise ValueError(
"`token` and `use_auth_token` are both specified. Please set only the argument `token`."
)
kwargs["token"] = use_auth_token
- 目的:处理过时的参数
use_auth_token
,并引导用户使用新的参数token
。 - 解释:
- 如果用户在
kwargs
中传递了use_auth_token
,则发出警告,提示该参数已弃用,应该使用token
。 - 如果同时传递了
token
和use_auth_token
,则抛出错误,要求用户只使用token
。 - 最终,将
use_auth_token
的值赋给kwargs["token"]
。
- 如果用户在
config = kwargs.pop("config", None)
use_fast = kwargs.pop("use_fast", None)
trust_remote_code = kwargs.pop("trust_remote_code", None)
kwargs["_from_auto"] = True
- 目的:从关键字参数中提取配置项,为后续处理做准备。
- 解释:
config
:用户可能传递的模型配置对象,如果没有则为None
。use_fast
:决定是否使用快速版本的图像处理器的布尔值,默认值为None
,后续会根据情况设置。trust_remote_code
:是否信任并允许从远程仓库加载自定义代码。kwargs["_from_auto"] = True
:在关键字参数中添加标记,指示该调用是通过AutoImageProcessor
进行的。
2. 确定图像处理器配置文件名
if "image_processor_filename" in kwargs:
image_processor_filename = kwargs.pop("image_processor_filename")
elif is_timm_local_checkpoint(pretrained_model_name_or_path):
image_processor_filename = CONFIG_NAME
else:
image_processor_filename = IMAGE_PROCESSOR_NAME
- 目的:确定要加载的图像处理器配置文件的文件名。
- 解释:
- 如果用户在
kwargs
中指定了image_processor_filename
,则使用用户指定的文件名。 - 如果预训练模型是一个本地的
timm
检查点,则使用CONFIG_NAME
(通常为'config.json'
)。
- 否则,使用默认的IMAGE_PROCESSOR_NAME
(通常为'preprocessor_config.json'
)。
- 如果用户在
3. 加载图像处理器配置
try:
# 主路径,适用于所有 Transformers 模型和本地 TimmWrapper 检查点
config_dict, _ = ImageProcessingMixin.get_image_processor_dict(
pretrained_model_name_or_path, image_processor_filename=image_processor_filename, **kwargs
)
except Exception as initial_exception:
# 回退路径,适用于 Hub 上的 TimmWrapper 检查点
try:
config_dict, _ = ImageProcessingMixin.get_image_processor_dict(
pretrained_model_name_or_path, image_processor_filename=CONFIG_NAME, **kwargs
)
except Exception:
raise initial_exception
# 如果加载的不是 timm 配置字典,则抛出初始异常
if not is_timm_config_dict(config_dict):
raise initial_exception
- 目的:尝试加载图像处理器的配置字典。
- 解释:
- 首先尝试使用确定的
image_processor_filename
来加载配置,ImageProcessingMixin.get_image_processor_dict。 - 如果发生异常(如文件不存在),则可能是因为模型是一个
timm
模型,需要使用'config.json'
来加载。 - 如果两次尝试都失败,或者加载的配置不是
timm
配置,则抛出最初的异常。
- 首先尝试使用确定的
4. 解析图像处理器类型和自动映射
image_processor_type = config_dict.get("image_processor_type", None)
image_processor_auto_map = None
if "AutoImageProcessor" in config_dict.get("auto_map", {}):
image_processor_auto_map = config_dict["auto_map"]["AutoImageProcessor"]
- 目的:从配置字典中提取图像处理器类型和自动映射信息。
- 解释:
image_processor_type
:尝试获取image_processor_type
,这通常是图像处理器类的名称。image_processor_auto_map
:如果配置中存在auto_map
,并且其中包含AutoImageProcessor
,则获取对应的映射信息。
5. 兼容旧的特征提取器配置
if image_processor_type is None and image_processor_auto_map is None:
feature_extractor_class = config_dict.pop("feature_extractor_type", None)
if feature_extractor_class is not None:
image_processor_type = feature_extractor_class.replace("FeatureExtractor", "ImageProcessor")
if "AutoFeatureExtractor" in config_dict.get("auto_map", {}):
feature_extractor_auto_map = config_dict["auto_map"]["AutoFeatureExtractor"]
image_processor_auto_map = feature_extractor_auto_map.replace("FeatureExtractor", "ImageProcessor")
- 目的:处理旧版本的配置,其中使用了
FeatureExtractor
而不是ImageProcessor
。 - 解释:
- 如果没有获取到
image_processor_type
和image_processor_auto_map
,则尝试从旧的feature_extractor_type
中获取。 - 将
FeatureExtractor
替换为ImageProcessor
,以获取新的类型名称。
- 如果没有获取到
6. 从模型配置中获取图像处理器类型
if image_processor_type is None and image_processor_auto_map is None:
if not isinstance(config, PretrainedConfig):
config = AutoConfig.from_pretrained(
pretrained_model_name_or_path,
trust_remote_code=trust_remote_code,
**kwargs,
)
image_processor_type = getattr(config, "image_processor_type", None)
if hasattr(config, "auto_map") and "AutoImageProcessor" in config.auto_map:
image_processor_auto_map = config.auto_map["AutoImageProcessor"]
- 目的:如果在图像处理器配置中未找到类型信息,则尝试从模型的配置中获取。
- 解释:
- 如果
config
不是PretrainedConfig
的实例,则使用AutoConfig.from_pretrained
加载模型配置。 - 尝试从模型配置中获取
image_processor_type
。 - 检查模型配置中是否存在
auto_map
,并获取AutoImageProcessor
的映射信息。
- 如果
7. 确定是否使用快速版本的图像处理器并获取相应的类
image_processor_class = None
if image_processor_type is not None:
if use_fast is None:
use_fast = image_processor_type.endswith("Fast")
if not use_fast:
logger.warning_once(
"Using a slow image processor as `use_fast` is unset and a slow processor was saved with this model. "
"`use_fast=True` will be the default behavior in v4.48, even if the model was saved with a slow processor. "
"This will result in minor differences in outputs. You'll still be able to use a slow processor with `use_fast=False`."
)
if use_fast and not is_torchvision_available():
logger.warning_once(
"Using `use_fast=True` but `torchvision` is not available. Falling back to the slow image processor."
)
use_fast = False
if use_fast:
if not image_processor_type.endswith("Fast"):
image_processor_type += "Fast"
for _, image_processors in IMAGE_PROCESSOR_MAPPING_NAMES.items():
if image_processor_type in image_processors:
break
else:
image_processor_type = image_processor_type[:-4]
use_fast = False
logger.warning_once(
"`use_fast` is set to `True` but the image processor class does not have a fast version. "
" Falling back to the slow version."
)
image_processor_class = get_image_processor_class_from_name(image_processor_type)
else:
image_processor_type = (
image_processor_type[:-4] if image_processor_type.endswith("Fast") else image_processor_type
)
image_processor_class = get_image_processor_class_from_name(image_processor_type)
- 目的:根据
use_fast
选项和可用性,决定使用快速或慢速版本的图像处理器,并获取对应的类。 - 解释:
- 如果
use_fast
未设置,则根据image_processor_type
是否以'Fast'
结尾来推断。 - 如果需要使用快速版本,但
torchvision
不可用,则警告并退回使用慢速版本。 - 如果使用快速版本且类型名称未以
'Fast'
结尾,则添加'Fast'
。 - 检查调整后的
image_processor_type
是否在已知的映射中,如果不存在,则回退到慢速版本。 - 使用
get_image_processor_class_from_name
函数,根据类型名称获取对应的图像处理器类。
- 如果
8. 处理远程代码加载和实例化图像处理器
has_remote_code = image_processor_auto_map is not None
has_local_code = image_processor_class is not None or type(config) in IMAGE_PROCESSOR_MAPPING
trust_remote_code = resolve_trust_remote_code(
trust_remote_code, pretrained_model_name_or_path, has_local_code, has_remote_code
)
if image_processor_auto_map is not None and not isinstance(image_processor_auto_map, tuple):
image_processor_auto_map = (image_processor_auto_map, None)
if has_remote_code and trust_remote_code:
if not use_fast and image_processor_auto_map[1] is not None:
_warning_fast_image_processor_available(image_processor_auto_map[1])
if use_fast and image_processor_auto_map[1] is not None:
class_ref = image_processor_auto_map[1]
else:
class_ref = image_processor_auto_map[0]
image_processor_class = get_class_from_dynamic_module(class_ref, pretrained_model_name_or_path, **kwargs)
_ = kwargs.pop("code_revision", None)
if os.path.isdir(pretrained_model_name_or_path):
image_processor_class.register_for_auto_class()
return image_processor_class.from_dict(config_dict, **kwargs)
elif image_processor_class is not None:
return image_processor_class.from_dict(config_dict, **kwargs)
- 目的:处理是否需要从远程加载自定义的图像处理器类,并实例化图像处理器对象。
- 解释:
- 判断是否存在远程代码(
has_remote_code
)和本地代码(has_local_code
)。 - 使用
resolve_trust_remote_code
函数,确定是否信任远程代码(trust_remote_code
)。 - 如果存在远程代码且被信任:
- 根据
use_fast
以及可用性,选择快速或慢速版本的类引用class_ref
。 - 使用
get_class_from_dynamic_module
函数,从远程模块中获取类定义。 - 如果模型路径是本地目录,则注册该类以供自动类使用。
- 使用
from_dict
方法,根据配置字典实例化图像处理器对象并返回。
- 如果存在本地图像处理器类,则直接使用配置字典实例化并返回。
- 根据
- 判断是否存在远程代码(
9. 使用默认映射尝试获取图像处理器类
elif type(config) in IMAGE_PROCESSOR_MAPPING:
image_processor_tuple = IMAGE_PROCESSOR_MAPPING[type(config)]
image_processor_class_py, image_processor_class_fast = image_processor_tuple
if not use_fast and image_processor_class_fast is not None:
_warning_fast_image_processor_available(image_processor_class_fast)
if image_processor_class_fast and (use_fast or image_processor_class_py is None):
return image_processor_class_fast.from_pretrained(pretrained_model_name_or_path, *inputs, **kwargs)
else:
if image_processor_class_py is not None:
return image_processor_class_py.from_pretrained(pretrained_model_name_or_path, *inputs, **kwargs)
else:
raise ValueError(
"This image processor cannot be instantiated. Please make sure you have `Pillow` installed."
)
- 目的:如果上述方法都未能成功,则使用预定义的映射
IMAGE_PROCESSOR_MAPPING
尝试获取图像处理器类。 - 解释:
- 检查模型配置的类型是否在
IMAGE_PROCESSOR_MAPPING
中。 - 根据
use_fast
和可用性,选择快速或慢速版本的类,并使用from_pretrained
方法实例化。
- 检查模型配置的类型是否在
10. 抛出异常
raise ValueError(
f"Unrecognized image processor in {pretrained_model_name_or_path}. Should have a "
f"`image_processor_type` key in its {IMAGE_PROCESSOR_NAME} of {CONFIG_NAME}, or one of the following "
f"`model_type` keys in its {CONFIG_NAME}: {', '.join(c for c in IMAGE_PROCESSOR_MAPPING_NAMES.keys())}"
)
- 目的:如果所有方法都失败,无法识别或实例化图像处理器,则抛出异常。
- 解释:
- 提示用户未能识别给定模型的图像处理器类型。
- 建议检查模型的配置文件中是否包含
image_processor_type
,并列出了支持的模型类型。
静态方法
方法名称 | 类型 | 功能说明 |
---|---|---|
register | 静态方法 | 注册新的模型配置类和对应的图像处理器类,以扩展 AutoImageProcessor 的支持范围。通过此方法,用户可以添加自定义的模型和图像处理器,使其能够被 AutoImageProcessor 自动识别和加载。 |
实例方法
方法名称 | 类型 | 功能说明 |
---|---|---|
__init__ | 实例方法 | 初始化方法,被设计为抛出异常。提示用户不应直接实例化 AutoImageProcessor 类,而应该使用 from_pretrained 类方法来实例化具体的图像处理器。 |
实例属性
由于 AutoImageProcessor
类的 __init__
方法被设计为抛出异常,因此不能直接实例化该类,因此不存在实例属性。
end
好的,以下是对函数 get_image_processor_class_from_name
的解释。