Add files using upload-large-folder tool
Browse files- LTA_openwebtext_dualt/logs/owt_dirichlet_len1024_Cv_to_2v_gumbel_sde_watch_fast/infer_0004000_gpu2.log +12 -0
- LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/models/deformable_detr/__init__.py +31 -0
- LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/models/deformable_detr/configuration_deformable_detr.py +148 -0
- LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/models/deformable_detr/image_processing_deformable_detr.py +709 -0
- LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/models/deformable_detr/image_processing_pil_deformable_detr.py +738 -0
- LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/models/deformable_detr/modeling_deformable_detr.py +1711 -0
- LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/models/dpt/__init__.py +29 -0
- LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/models/dpt/configuration_dpt.py +158 -0
- LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/models/dpt/image_processing_pil_dpt.py +312 -0
- LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/utils/__init__.py +339 -0
- LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/utils/backbone_utils.py +19 -0
- LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/utils/chat_parsing_utils.py +305 -0
- LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/utils/dummy_detectron2_objects.py +11 -0
- LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/utils/dummy_music_objects.py +16 -0
- LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/utils/hp_naming.py +162 -0
- LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/utils/loading_report.py +280 -0
- LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/utils/logging.py +441 -0
- LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/utils/network_logging.py +485 -0
- LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/utils/peft_utils.py +117 -0
- LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/utils/versions.py +116 -0
LTA_openwebtext_dualt/logs/owt_dirichlet_len1024_Cv_to_2v_gumbel_sde_watch_fast/infer_0004000_gpu2.log
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[load] runs/lta_owt_dirichlet_len1024_Cv_to_2v_gbs512_4gpu_abspos_specialloss16_save1k_gumbelwatch_20260525_v2/step_0004000.pt
|
| 2 |
+
[ckpt] step=4000
|
| 3 |
+
[sde] generated 8/128
|
| 4 |
+
[sde] generated 16/128
|
| 5 |
+
[sde] generated 24/128
|
| 6 |
+
[sde] generated 32/128
|
| 7 |
+
[sde] generated 40/128
|
| 8 |
+
[sde] generated 48/128
|
| 9 |
+
[sde] generated 56/128
|
| 10 |
+
[sde] generated 64/128
|
| 11 |
+
[sde] generated 72/128
|
| 12 |
+
[sde] generated 80/128
|
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/models/deformable_detr/__init__.py
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2022 The HuggingFace Team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
from typing import TYPE_CHECKING
|
| 17 |
+
|
| 18 |
+
from ...utils import _LazyModule
|
| 19 |
+
from ...utils.import_utils import define_import_structure
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
if TYPE_CHECKING:
|
| 23 |
+
from .configuration_deformable_detr import *
|
| 24 |
+
from .image_processing_deformable_detr import *
|
| 25 |
+
from .image_processing_pil_deformable_detr import *
|
| 26 |
+
from .modeling_deformable_detr import *
|
| 27 |
+
else:
|
| 28 |
+
import sys
|
| 29 |
+
|
| 30 |
+
_file = globals()["__file__"]
|
| 31 |
+
sys.modules[__name__] = _LazyModule(__name__, _file, define_import_structure(_file), module_spec=__spec__)
|
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/models/deformable_detr/configuration_deformable_detr.py
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2022 SenseTime and The HuggingFace Inc. team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
"""Deformable DETR model configuration"""
|
| 15 |
+
|
| 16 |
+
from huggingface_hub.dataclasses import strict
|
| 17 |
+
|
| 18 |
+
from ...backbone_utils import consolidate_backbone_kwargs_to_config
|
| 19 |
+
from ...configuration_utils import PreTrainedConfig
|
| 20 |
+
from ...utils import auto_docstring
|
| 21 |
+
from ..auto import AutoConfig
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
@auto_docstring(checkpoint="SenseTime/deformable-detr")
|
| 25 |
+
@strict
|
| 26 |
+
class DeformableDetrConfig(PreTrainedConfig):
|
| 27 |
+
r"""
|
| 28 |
+
num_queries (`int`, *optional*, defaults to 300):
|
| 29 |
+
Number of object queries, i.e. detection slots. This is the maximal number of objects
|
| 30 |
+
[`DeformableDetrModel`] can detect in a single image. In case `two_stage` is set to `True`, we use
|
| 31 |
+
`two_stage_num_proposals` instead.
|
| 32 |
+
return_intermediate (`bool`, *optional*, defaults to True):
|
| 33 |
+
Whether to return the intermediate state or not
|
| 34 |
+
position_embedding_type (`str`, *optional*, defaults to `"sine"`):
|
| 35 |
+
Type of position embeddings to be used on top of the image features. One of `"sine"` or `"learned"`.
|
| 36 |
+
dilation (`bool`, *optional*, defaults to `False`):
|
| 37 |
+
Whether to replace stride with dilation in the last convolutional block (DC5). Only supported when
|
| 38 |
+
`use_timm_backbone` = `True`.
|
| 39 |
+
num_feature_levels (`int`, *optional*, defaults to 4):
|
| 40 |
+
The number of input feature levels.
|
| 41 |
+
encoder_n_points (`int`, *optional*, defaults to 4):
|
| 42 |
+
The number of sampled keys in each feature level for each attention head in the encoder.
|
| 43 |
+
decoder_n_points (`int`, *optional*, defaults to 4):
|
| 44 |
+
The number of sampled keys in each feature level for each attention head in the decoder.
|
| 45 |
+
two_stage (`bool`, *optional*, defaults to `False`):
|
| 46 |
+
Whether to apply a two-stage deformable DETR, where the region proposals are also generated by a variant of
|
| 47 |
+
Deformable DETR, which are further fed into the decoder for iterative bounding box refinement.
|
| 48 |
+
two_stage_num_proposals (`int`, *optional*, defaults to 300):
|
| 49 |
+
The number of region proposals to be generated, in case `two_stage` is set to `True`.
|
| 50 |
+
with_box_refine (`bool`, *optional*, defaults to `False`):
|
| 51 |
+
Whether to apply iterative bounding box refinement, where each decoder layer refines the bounding boxes
|
| 52 |
+
based on the predictions from the previous layer.
|
| 53 |
+
disable_custom_kernels (`bool`, *optional*, defaults to `False`):
|
| 54 |
+
Disable the use of custom CUDA and CPU kernels. This option is necessary for the ONNX export, as custom
|
| 55 |
+
kernels are not supported by PyTorch ONNX export.
|
| 56 |
+
|
| 57 |
+
Examples:
|
| 58 |
+
|
| 59 |
+
```python
|
| 60 |
+
>>> from transformers import DeformableDetrConfig, DeformableDetrModel
|
| 61 |
+
|
| 62 |
+
>>> # Initializing a Deformable DETR SenseTime/deformable-detr style configuration
|
| 63 |
+
>>> configuration = DeformableDetrConfig()
|
| 64 |
+
|
| 65 |
+
>>> # Initializing a model (with random weights) from the SenseTime/deformable-detr style configuration
|
| 66 |
+
>>> model = DeformableDetrModel(configuration)
|
| 67 |
+
|
| 68 |
+
>>> # Accessing the model configuration
|
| 69 |
+
>>> configuration = model.config
|
| 70 |
+
```"""
|
| 71 |
+
|
| 72 |
+
model_type = "deformable_detr"
|
| 73 |
+
sub_configs = {"backbone_config": AutoConfig}
|
| 74 |
+
attribute_map = {
|
| 75 |
+
"hidden_size": "d_model",
|
| 76 |
+
"num_attention_heads": "encoder_attention_heads",
|
| 77 |
+
}
|
| 78 |
+
|
| 79 |
+
backbone_config: dict | PreTrainedConfig | None = None
|
| 80 |
+
num_channels: int = 3
|
| 81 |
+
num_queries: int = 300
|
| 82 |
+
max_position_embeddings: int = 1024
|
| 83 |
+
encoder_layers: int = 6
|
| 84 |
+
encoder_ffn_dim: int = 1024
|
| 85 |
+
encoder_attention_heads: int = 8
|
| 86 |
+
decoder_layers: int = 6
|
| 87 |
+
decoder_ffn_dim: int = 1024
|
| 88 |
+
decoder_attention_heads: int = 8
|
| 89 |
+
encoder_layerdrop: float | int = 0.0
|
| 90 |
+
is_encoder_decoder: bool = True
|
| 91 |
+
activation_function: str = "relu"
|
| 92 |
+
d_model: int = 256
|
| 93 |
+
dropout: float | int = 0.1
|
| 94 |
+
attention_dropout: float | int = 0.0
|
| 95 |
+
activation_dropout: float | int = 0.0
|
| 96 |
+
init_std: float = 0.02
|
| 97 |
+
init_xavier_std: float = 1.0
|
| 98 |
+
return_intermediate: bool = True
|
| 99 |
+
auxiliary_loss: bool = False
|
| 100 |
+
position_embedding_type: str = "sine"
|
| 101 |
+
dilation: bool = False
|
| 102 |
+
num_feature_levels: int = 4
|
| 103 |
+
encoder_n_points: int = 4
|
| 104 |
+
decoder_n_points: int = 4
|
| 105 |
+
two_stage: bool = False
|
| 106 |
+
two_stage_num_proposals: int = 300
|
| 107 |
+
with_box_refine: bool = False
|
| 108 |
+
class_cost: int = 1
|
| 109 |
+
bbox_cost: int = 5
|
| 110 |
+
giou_cost: int = 2
|
| 111 |
+
mask_loss_coefficient: int = 1
|
| 112 |
+
dice_loss_coefficient: int = 1
|
| 113 |
+
bbox_loss_coefficient: int = 5
|
| 114 |
+
giou_loss_coefficient: int = 2
|
| 115 |
+
eos_coefficient: float = 0.1
|
| 116 |
+
focal_alpha: float = 0.25
|
| 117 |
+
disable_custom_kernels: bool = False
|
| 118 |
+
tie_word_embeddings: bool = True
|
| 119 |
+
|
| 120 |
+
def __post_init__(self, **kwargs):
|
| 121 |
+
# Init timm backbone with hardcoded values for BC
|
| 122 |
+
timm_default_kwargs = {
|
| 123 |
+
"num_channels": 3,
|
| 124 |
+
"features_only": True,
|
| 125 |
+
"use_pretrained_backbone": False,
|
| 126 |
+
"out_indices": [2, 3, 4] if self.num_feature_levels > 1 else [4],
|
| 127 |
+
}
|
| 128 |
+
if self.dilation:
|
| 129 |
+
timm_default_kwargs["output_stride"] = 16
|
| 130 |
+
|
| 131 |
+
self.backbone_config, kwargs = consolidate_backbone_kwargs_to_config(
|
| 132 |
+
backbone_config=self.backbone_config,
|
| 133 |
+
default_backbone="resnet50",
|
| 134 |
+
default_config_type="resnet50",
|
| 135 |
+
default_config_kwargs={"out_features": ["stage4"]},
|
| 136 |
+
timm_default_kwargs=timm_default_kwargs,
|
| 137 |
+
**kwargs,
|
| 138 |
+
)
|
| 139 |
+
|
| 140 |
+
super().__post_init__(**kwargs)
|
| 141 |
+
|
| 142 |
+
def validate_architecture(self):
|
| 143 |
+
"""Part of `@strict`-powered validation. Validates the architecture of the config."""
|
| 144 |
+
if self.two_stage is True and self.with_box_refine is False:
|
| 145 |
+
raise ValueError("If two_stage is True, with_box_refine must be True.")
|
| 146 |
+
|
| 147 |
+
|
| 148 |
+
__all__ = ["DeformableDetrConfig"]
|
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/models/deformable_detr/image_processing_deformable_detr.py
ADDED
|
@@ -0,0 +1,709 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
|
| 2 |
+
# This file was automatically generated from src/transformers/models/deformable_detr/modular_deformable_detr.py.
|
| 3 |
+
# Do NOT edit this file manually as any edits will be overwritten by the generation of
|
| 4 |
+
# the file from the modular. If any change should be done, please apply the change to the
|
| 5 |
+
# modular_deformable_detr.py file directly. One of our CI enforces this.
|
| 6 |
+
# 🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
|
| 7 |
+
# Copyright 2022 SenseTime and The HuggingFace Inc. team. All rights reserved.
|
| 8 |
+
#
|
| 9 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 10 |
+
# you may not use this file except in compliance with the License.
|
| 11 |
+
# You may obtain a copy of the License at
|
| 12 |
+
#
|
| 13 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 14 |
+
#
|
| 15 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 16 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 17 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 18 |
+
# See the License for the specific language governing permissions and
|
| 19 |
+
# limitations under the License.
|
| 20 |
+
|
| 21 |
+
import pathlib
|
| 22 |
+
from typing import Any, Optional
|
| 23 |
+
|
| 24 |
+
import torch
|
| 25 |
+
from torchvision.io import read_image
|
| 26 |
+
from torchvision.transforms.v2 import functional as tvF
|
| 27 |
+
|
| 28 |
+
from ...image_processing_backends import TorchvisionBackend
|
| 29 |
+
from ...image_processing_utils import BatchFeature, get_size_dict
|
| 30 |
+
from ...image_transforms import (
|
| 31 |
+
center_to_corners_format,
|
| 32 |
+
corners_to_center_format,
|
| 33 |
+
get_size_with_aspect_ratio,
|
| 34 |
+
safe_squeeze,
|
| 35 |
+
)
|
| 36 |
+
from ...image_utils import (
|
| 37 |
+
IMAGENET_DEFAULT_MEAN,
|
| 38 |
+
IMAGENET_DEFAULT_STD,
|
| 39 |
+
AnnotationFormat,
|
| 40 |
+
AnnotationType,
|
| 41 |
+
ChannelDimension,
|
| 42 |
+
ImageInput,
|
| 43 |
+
PILImageResampling,
|
| 44 |
+
SizeDict,
|
| 45 |
+
get_image_size,
|
| 46 |
+
get_image_size_for_max_height_width,
|
| 47 |
+
get_max_height_width,
|
| 48 |
+
validate_annotations,
|
| 49 |
+
)
|
| 50 |
+
from ...processing_utils import ImagesKwargs, Unpack
|
| 51 |
+
from ...utils import TensorType, auto_docstring
|
| 52 |
+
|
| 53 |
+
|
| 54 |
+
class DeformableDetrImageProcessorKwargs(ImagesKwargs, total=False):
|
| 55 |
+
r"""
|
| 56 |
+
format (`str`, *optional*, defaults to `AnnotationFormat.COCO_DETECTION`):
|
| 57 |
+
Data format of the annotations. One of "coco_detection" or "coco_panoptic".
|
| 58 |
+
do_convert_annotations (`bool`, *optional*, defaults to `True`):
|
| 59 |
+
Controls whether to convert the annotations to the format expected by the DEFORMABLE_DETR model. Converts the
|
| 60 |
+
bounding boxes to the format `(center_x, center_y, width, height)` and in the range `[0, 1]`.
|
| 61 |
+
Can be overridden by the `do_convert_annotations` parameter in the `preprocess` method.
|
| 62 |
+
"""
|
| 63 |
+
|
| 64 |
+
format: str | AnnotationFormat
|
| 65 |
+
do_convert_annotations: bool
|
| 66 |
+
|
| 67 |
+
|
| 68 |
+
SUPPORTED_ANNOTATION_FORMATS = (AnnotationFormat.COCO_DETECTION, AnnotationFormat.COCO_PANOPTIC)
|
| 69 |
+
|
| 70 |
+
|
| 71 |
+
# inspired by https://github.com/facebookresearch/deformable_detr/blob/master/datasets/coco.py#L33
|
| 72 |
+
def convert_coco_poly_to_mask(segmentations, height: int, width: int, device: torch.device) -> torch.Tensor:
|
| 73 |
+
"""
|
| 74 |
+
Convert a COCO polygon annotation to a mask.
|
| 75 |
+
|
| 76 |
+
Args:
|
| 77 |
+
segmentations (`list[list[float]]`):
|
| 78 |
+
List of polygons, each polygon represented by a list of x-y coordinates.
|
| 79 |
+
height (`int`):
|
| 80 |
+
Height of the mask.
|
| 81 |
+
width (`int`):
|
| 82 |
+
Width of the mask.
|
| 83 |
+
"""
|
| 84 |
+
try:
|
| 85 |
+
from pycocotools import mask as coco_mask
|
| 86 |
+
except ImportError:
|
| 87 |
+
raise ImportError("Pycocotools is not installed in your environment.")
|
| 88 |
+
|
| 89 |
+
masks = []
|
| 90 |
+
for polygons in segmentations:
|
| 91 |
+
rles = coco_mask.frPyObjects(polygons, height, width)
|
| 92 |
+
mask = coco_mask.decode(rles)
|
| 93 |
+
if len(mask.shape) < 3:
|
| 94 |
+
mask = mask[..., None]
|
| 95 |
+
mask = torch.as_tensor(mask, dtype=torch.uint8, device=device)
|
| 96 |
+
mask = torch.any(mask, axis=2)
|
| 97 |
+
masks.append(mask)
|
| 98 |
+
if masks:
|
| 99 |
+
masks = torch.stack(masks, axis=0)
|
| 100 |
+
else:
|
| 101 |
+
masks = torch.zeros((0, height, width), dtype=torch.uint8, device=device)
|
| 102 |
+
|
| 103 |
+
return masks
|
| 104 |
+
|
| 105 |
+
|
| 106 |
+
# inspired by https://github.com/facebookresearch/deformable_detr/blob/master/datasets/coco.py#L50
|
| 107 |
+
def prepare_coco_detection_annotation(
|
| 108 |
+
image,
|
| 109 |
+
target,
|
| 110 |
+
return_segmentation_masks: bool = False,
|
| 111 |
+
input_data_format: ChannelDimension | str | None = None,
|
| 112 |
+
):
|
| 113 |
+
"""
|
| 114 |
+
Convert the target in COCO format into the format expected by DEFORMABLE_DETR.
|
| 115 |
+
"""
|
| 116 |
+
image_height, image_width = image.size()[-2:]
|
| 117 |
+
|
| 118 |
+
image_id = target["image_id"]
|
| 119 |
+
image_id = torch.as_tensor([image_id], dtype=torch.int64, device=image.device)
|
| 120 |
+
|
| 121 |
+
# Get all COCO annotations for the given image.
|
| 122 |
+
annotations = target["annotations"]
|
| 123 |
+
classes = []
|
| 124 |
+
area = []
|
| 125 |
+
boxes = []
|
| 126 |
+
keypoints = []
|
| 127 |
+
for obj in annotations:
|
| 128 |
+
if "iscrowd" not in obj or obj["iscrowd"] == 0:
|
| 129 |
+
classes.append(obj["category_id"])
|
| 130 |
+
area.append(obj["area"])
|
| 131 |
+
boxes.append(obj["bbox"])
|
| 132 |
+
if "keypoints" in obj:
|
| 133 |
+
keypoints.append(obj["keypoints"])
|
| 134 |
+
|
| 135 |
+
classes = torch.as_tensor(classes, dtype=torch.int64, device=image.device)
|
| 136 |
+
area = torch.as_tensor(area, dtype=torch.float32, device=image.device)
|
| 137 |
+
iscrowd = torch.zeros_like(classes, dtype=torch.int64, device=image.device)
|
| 138 |
+
# guard against no boxes via resizing
|
| 139 |
+
boxes = torch.as_tensor(boxes, dtype=torch.float32, device=image.device).reshape(-1, 4)
|
| 140 |
+
boxes[:, 2:] += boxes[:, :2]
|
| 141 |
+
boxes[:, 0::2] = boxes[:, 0::2].clip(min=0, max=image_width)
|
| 142 |
+
boxes[:, 1::2] = boxes[:, 1::2].clip(min=0, max=image_height)
|
| 143 |
+
|
| 144 |
+
keep = (boxes[:, 3] > boxes[:, 1]) & (boxes[:, 2] > boxes[:, 0])
|
| 145 |
+
|
| 146 |
+
new_target = {
|
| 147 |
+
"image_id": image_id,
|
| 148 |
+
"class_labels": classes[keep],
|
| 149 |
+
"boxes": boxes[keep],
|
| 150 |
+
"area": area[keep],
|
| 151 |
+
"iscrowd": iscrowd[keep],
|
| 152 |
+
"orig_size": torch.as_tensor([int(image_height), int(image_width)], dtype=torch.int64, device=image.device),
|
| 153 |
+
}
|
| 154 |
+
|
| 155 |
+
if keypoints:
|
| 156 |
+
keypoints = torch.as_tensor(keypoints, dtype=torch.float32, device=image.device)
|
| 157 |
+
# Apply the keep mask here to filter the relevant annotations
|
| 158 |
+
keypoints = keypoints[keep]
|
| 159 |
+
num_keypoints = keypoints.shape[0]
|
| 160 |
+
keypoints = keypoints.reshape((-1, 3)) if num_keypoints else keypoints
|
| 161 |
+
new_target["keypoints"] = keypoints
|
| 162 |
+
|
| 163 |
+
if return_segmentation_masks:
|
| 164 |
+
segmentation_masks = [obj["segmentation"] for obj in annotations]
|
| 165 |
+
masks = convert_coco_poly_to_mask(segmentation_masks, image_height, image_width, device=image.device)
|
| 166 |
+
new_target["masks"] = masks[keep]
|
| 167 |
+
|
| 168 |
+
return new_target
|
| 169 |
+
|
| 170 |
+
|
| 171 |
+
def masks_to_boxes(masks: torch.Tensor) -> torch.Tensor:
|
| 172 |
+
"""
|
| 173 |
+
Compute the bounding boxes around the provided panoptic segmentation masks.
|
| 174 |
+
|
| 175 |
+
Args:
|
| 176 |
+
masks: masks in format `[number_masks, height, width]` where N is the number of masks
|
| 177 |
+
|
| 178 |
+
Returns:
|
| 179 |
+
boxes: bounding boxes in format `[number_masks, 4]` in xyxy format
|
| 180 |
+
"""
|
| 181 |
+
if masks.numel() == 0:
|
| 182 |
+
return torch.zeros((0, 4), device=masks.device)
|
| 183 |
+
|
| 184 |
+
h, w = masks.shape[-2:]
|
| 185 |
+
y = torch.arange(0, h, dtype=torch.float32, device=masks.device)
|
| 186 |
+
x = torch.arange(0, w, dtype=torch.float32, device=masks.device)
|
| 187 |
+
# see https://github.com/pytorch/pytorch/issues/50276
|
| 188 |
+
y, x = torch.meshgrid(y, x, indexing="ij")
|
| 189 |
+
|
| 190 |
+
x_mask = masks * torch.unsqueeze(x, 0)
|
| 191 |
+
x_max = x_mask.view(x_mask.shape[0], -1).max(-1)[0]
|
| 192 |
+
x_min = (
|
| 193 |
+
torch.where(masks, x.unsqueeze(0), torch.tensor(1e8, device=masks.device)).view(masks.shape[0], -1).min(-1)[0]
|
| 194 |
+
)
|
| 195 |
+
|
| 196 |
+
y_mask = masks * torch.unsqueeze(y, 0)
|
| 197 |
+
y_max = y_mask.view(y_mask.shape[0], -1).max(-1)[0]
|
| 198 |
+
y_min = (
|
| 199 |
+
torch.where(masks, y.unsqueeze(0), torch.tensor(1e8, device=masks.device)).view(masks.shape[0], -1).min(-1)[0]
|
| 200 |
+
)
|
| 201 |
+
|
| 202 |
+
return torch.stack([x_min, y_min, x_max, y_max], 1)
|
| 203 |
+
|
| 204 |
+
|
| 205 |
+
# 2 functions below adapted from https://github.com/cocodataset/panopticapi/blob/master/panopticapi/utils.py
|
| 206 |
+
# Copyright (c) 2018, Alexander Kirillov
|
| 207 |
+
# All rights reserved.
|
| 208 |
+
def rgb_to_id(color):
|
| 209 |
+
"""
|
| 210 |
+
Converts RGB color to unique ID.
|
| 211 |
+
"""
|
| 212 |
+
if isinstance(color, torch.Tensor) and len(color.shape) == 3:
|
| 213 |
+
if color.dtype == torch.uint8:
|
| 214 |
+
color = color.to(torch.int32)
|
| 215 |
+
return color[:, :, 0] + 256 * color[:, :, 1] + 256 * 256 * color[:, :, 2]
|
| 216 |
+
return int(color[0] + 256 * color[1] + 256 * 256 * color[2])
|
| 217 |
+
|
| 218 |
+
|
| 219 |
+
def prepare_coco_panoptic_annotation(
|
| 220 |
+
image: torch.Tensor,
|
| 221 |
+
target: dict,
|
| 222 |
+
masks_path: str | pathlib.Path,
|
| 223 |
+
return_masks: bool = True,
|
| 224 |
+
input_data_format: ChannelDimension | str = None,
|
| 225 |
+
) -> dict:
|
| 226 |
+
"""
|
| 227 |
+
Prepare a coco panoptic annotation for DEFORMABLE_DETR.
|
| 228 |
+
"""
|
| 229 |
+
image_height, image_width = get_image_size(image, channel_dim=input_data_format)
|
| 230 |
+
annotation_path = pathlib.Path(masks_path) / target["file_name"]
|
| 231 |
+
|
| 232 |
+
new_target = {}
|
| 233 |
+
new_target["image_id"] = torch.as_tensor(
|
| 234 |
+
[target["image_id"] if "image_id" in target else target["id"]], dtype=torch.int64, device=image.device
|
| 235 |
+
)
|
| 236 |
+
new_target["size"] = torch.as_tensor([image_height, image_width], dtype=torch.int64, device=image.device)
|
| 237 |
+
new_target["orig_size"] = torch.as_tensor([image_height, image_width], dtype=torch.int64, device=image.device)
|
| 238 |
+
|
| 239 |
+
if "segments_info" in target:
|
| 240 |
+
masks = read_image(annotation_path).permute(1, 2, 0).to(dtype=torch.int32, device=image.device)
|
| 241 |
+
masks = rgb_to_id(masks)
|
| 242 |
+
|
| 243 |
+
ids = torch.as_tensor([segment_info["id"] for segment_info in target["segments_info"]], device=image.device)
|
| 244 |
+
masks = masks == ids[:, None, None]
|
| 245 |
+
masks = masks.to(torch.bool)
|
| 246 |
+
if return_masks:
|
| 247 |
+
new_target["masks"] = masks
|
| 248 |
+
new_target["boxes"] = masks_to_boxes(masks)
|
| 249 |
+
new_target["class_labels"] = torch.as_tensor(
|
| 250 |
+
[segment_info["category_id"] for segment_info in target["segments_info"]],
|
| 251 |
+
dtype=torch.int64,
|
| 252 |
+
device=image.device,
|
| 253 |
+
)
|
| 254 |
+
new_target["iscrowd"] = torch.as_tensor(
|
| 255 |
+
[segment_info["iscrowd"] for segment_info in target["segments_info"]],
|
| 256 |
+
dtype=torch.int64,
|
| 257 |
+
device=image.device,
|
| 258 |
+
)
|
| 259 |
+
new_target["area"] = torch.as_tensor(
|
| 260 |
+
[segment_info["area"] for segment_info in target["segments_info"]],
|
| 261 |
+
dtype=torch.float32,
|
| 262 |
+
device=image.device,
|
| 263 |
+
)
|
| 264 |
+
|
| 265 |
+
return new_target
|
| 266 |
+
|
| 267 |
+
|
| 268 |
+
@auto_docstring
|
| 269 |
+
class DeformableDetrImageProcessor(TorchvisionBackend):
|
| 270 |
+
valid_kwargs = DeformableDetrImageProcessorKwargs
|
| 271 |
+
resample = PILImageResampling.BILINEAR
|
| 272 |
+
image_mean = IMAGENET_DEFAULT_MEAN
|
| 273 |
+
image_std = IMAGENET_DEFAULT_STD
|
| 274 |
+
format = AnnotationFormat.COCO_DETECTION
|
| 275 |
+
do_resize = True
|
| 276 |
+
do_rescale = True
|
| 277 |
+
do_normalize = True
|
| 278 |
+
do_pad = True
|
| 279 |
+
size = {"shortest_edge": 800, "longest_edge": 1333}
|
| 280 |
+
default_to_square = False
|
| 281 |
+
model_input_names = ["pixel_values", "pixel_mask"]
|
| 282 |
+
|
| 283 |
+
def __init__(self, **kwargs: Unpack[DeformableDetrImageProcessorKwargs]) -> None:
|
| 284 |
+
kwargs.setdefault("do_pad", kwargs.pop("pad_and_return_pixel_mask", self.do_pad))
|
| 285 |
+
|
| 286 |
+
size = kwargs.pop("size", None)
|
| 287 |
+
max_size = None if size is None else kwargs.pop("max_size", 1333)
|
| 288 |
+
size = size if size is not None else {"shortest_edge": 800, "longest_edge": 1333}
|
| 289 |
+
# Convert size dict for backwards compat with max_size parameter
|
| 290 |
+
kwargs["size"] = get_size_dict(size, max_size=max_size, default_to_square=False)
|
| 291 |
+
|
| 292 |
+
# Backwards compatibility
|
| 293 |
+
do_convert_annotations = kwargs.get("do_convert_annotations")
|
| 294 |
+
do_normalize = kwargs.get("do_normalize")
|
| 295 |
+
if do_convert_annotations is None and getattr(self, "do_convert_annotations", None) is None:
|
| 296 |
+
self.do_convert_annotations = do_normalize if do_normalize is not None else self.do_normalize
|
| 297 |
+
|
| 298 |
+
super().__init__(**kwargs)
|
| 299 |
+
|
| 300 |
+
def prepare_annotation(
|
| 301 |
+
self,
|
| 302 |
+
image: torch.Tensor,
|
| 303 |
+
target: dict,
|
| 304 |
+
format: AnnotationFormat | None = None,
|
| 305 |
+
return_segmentation_masks: bool | None = None,
|
| 306 |
+
masks_path: str | pathlib.Path | None = None,
|
| 307 |
+
input_data_format: str | ChannelDimension | None = None,
|
| 308 |
+
) -> dict:
|
| 309 |
+
"""
|
| 310 |
+
Prepare an annotation for feeding into DEFORMABLE_DETR model.
|
| 311 |
+
"""
|
| 312 |
+
format = format if format is not None else self.format
|
| 313 |
+
|
| 314 |
+
if format == AnnotationFormat.COCO_DETECTION:
|
| 315 |
+
return_segmentation_masks = False if return_segmentation_masks is None else return_segmentation_masks
|
| 316 |
+
target = prepare_coco_detection_annotation(
|
| 317 |
+
image, target, return_segmentation_masks, input_data_format=input_data_format
|
| 318 |
+
)
|
| 319 |
+
elif format == AnnotationFormat.COCO_PANOPTIC:
|
| 320 |
+
return_segmentation_masks = True if return_segmentation_masks is None else return_segmentation_masks
|
| 321 |
+
target = prepare_coco_panoptic_annotation(
|
| 322 |
+
image,
|
| 323 |
+
target,
|
| 324 |
+
masks_path=masks_path,
|
| 325 |
+
return_masks=return_segmentation_masks,
|
| 326 |
+
input_data_format=input_data_format,
|
| 327 |
+
)
|
| 328 |
+
else:
|
| 329 |
+
raise ValueError(f"Format {format} is not supported.")
|
| 330 |
+
return target
|
| 331 |
+
|
| 332 |
+
def resize(
|
| 333 |
+
self,
|
| 334 |
+
image: torch.Tensor,
|
| 335 |
+
size: SizeDict,
|
| 336 |
+
resample: Optional["PILImageResampling | tvF.InterpolationMode | int"] = None,
|
| 337 |
+
**kwargs,
|
| 338 |
+
) -> torch.Tensor:
|
| 339 |
+
"""
|
| 340 |
+
Resize the image to the given size. Size can be `min_size` (scalar) or `(height, width)` tuple. If size is an
|
| 341 |
+
int, smaller edge of the image will be matched to this number.
|
| 342 |
+
|
| 343 |
+
Args:
|
| 344 |
+
image (`torch.Tensor`):
|
| 345 |
+
Image to resize.
|
| 346 |
+
size (`SizeDict`):
|
| 347 |
+
Size of the image's `(height, width)` dimensions after resizing. Available options are:
|
| 348 |
+
- `{"height": int, "width": int}`: The image will be resized to the exact size `(height, width)`.
|
| 349 |
+
Do NOT keep the aspect ratio.
|
| 350 |
+
- `{"shortest_edge": int, "longest_edge": int}`: The image will be resized to a maximum size respecting
|
| 351 |
+
the aspect ratio and keeping the shortest edge less or equal to `shortest_edge` and the longest edge
|
| 352 |
+
less or equal to `longest_edge`.
|
| 353 |
+
- `{"max_height": int, "max_width": int}`: The image will be resized to the maximum size respecting the
|
| 354 |
+
aspect ratio and keeping the height less or equal to `max_height` and the width less or equal to
|
| 355 |
+
`max_width`.
|
| 356 |
+
resample (`PILImageResampling | tvF.InterpolationMode | int`, *optional*, defaults to `PILImageResampling.BILINEAR`):
|
| 357 |
+
Resampling filter to use if resizing the image.
|
| 358 |
+
"""
|
| 359 |
+
if size.shortest_edge and size.longest_edge:
|
| 360 |
+
# Resize the image so that the shortest edge or the longest edge is of the given size
|
| 361 |
+
# while maintaining the aspect ratio of the original image.
|
| 362 |
+
new_size = get_size_with_aspect_ratio(image.shape[-2:], size.shortest_edge, size.longest_edge)
|
| 363 |
+
elif size.max_height and size.max_width:
|
| 364 |
+
new_size = get_image_size_for_max_height_width(image.shape[-2:], size.max_height, size.max_width)
|
| 365 |
+
elif size.height and size.width:
|
| 366 |
+
new_size = (size.height, size.width)
|
| 367 |
+
else:
|
| 368 |
+
raise ValueError(
|
| 369 |
+
f"Size must contain 'height' and 'width' keys or 'shortest_edge' and 'longest_edge' keys. Got {size}."
|
| 370 |
+
)
|
| 371 |
+
|
| 372 |
+
image = super().resize(
|
| 373 |
+
image, size=SizeDict(height=new_size[0], width=new_size[1]), resample=resample, **kwargs
|
| 374 |
+
)
|
| 375 |
+
return image
|
| 376 |
+
|
| 377 |
+
def resize_annotation(
|
| 378 |
+
self,
|
| 379 |
+
annotation: dict[str, Any],
|
| 380 |
+
orig_size: tuple[int, int],
|
| 381 |
+
target_size: tuple[int, int],
|
| 382 |
+
threshold: float = 0.5,
|
| 383 |
+
resample: Optional["PILImageResampling | tvF.InterpolationMode | int"] = PILImageResampling.NEAREST,
|
| 384 |
+
):
|
| 385 |
+
"""
|
| 386 |
+
Resizes an annotation to a target size.
|
| 387 |
+
|
| 388 |
+
Args:
|
| 389 |
+
annotation (`dict[str, Any]`):
|
| 390 |
+
The annotation dictionary.
|
| 391 |
+
orig_size (`tuple[int, int]`):
|
| 392 |
+
The original size of the input image.
|
| 393 |
+
target_size (`tuple[int, int]`):
|
| 394 |
+
The target size of the image, as returned by the preprocessing `resize` step.
|
| 395 |
+
threshold (`float`, *optional*, defaults to 0.5):
|
| 396 |
+
The threshold used to binarize the segmentation masks.
|
| 397 |
+
resample (`PILImageResampling | tvF.InterpolationMode | int`, defaults to `tvF.InterpolationMode.NEAREST_EXACT`):
|
| 398 |
+
The resampling filter to use when resizing the masks.
|
| 399 |
+
"""
|
| 400 |
+
ratio_height, ratio_width = [target / orig for target, orig in zip(target_size, orig_size)]
|
| 401 |
+
|
| 402 |
+
new_annotation = {}
|
| 403 |
+
new_annotation["size"] = target_size
|
| 404 |
+
|
| 405 |
+
for key, value in annotation.items():
|
| 406 |
+
if key == "boxes":
|
| 407 |
+
boxes = value
|
| 408 |
+
scaled_boxes = boxes * torch.as_tensor(
|
| 409 |
+
[ratio_width, ratio_height, ratio_width, ratio_height], dtype=torch.float32, device=boxes.device
|
| 410 |
+
)
|
| 411 |
+
new_annotation["boxes"] = scaled_boxes
|
| 412 |
+
elif key == "area":
|
| 413 |
+
area = value
|
| 414 |
+
scaled_area = area * (ratio_width * ratio_height)
|
| 415 |
+
new_annotation["area"] = scaled_area
|
| 416 |
+
elif key == "masks":
|
| 417 |
+
masks = value[:, None]
|
| 418 |
+
masks = [
|
| 419 |
+
super(DeformableDetrImageProcessor, self).resize(
|
| 420 |
+
mask, size=SizeDict(height=target_size[0], width=target_size[1]), resample=resample
|
| 421 |
+
)
|
| 422 |
+
for mask in masks
|
| 423 |
+
]
|
| 424 |
+
masks = torch.stack(masks).to(torch.float32)
|
| 425 |
+
masks = masks[:, 0] > threshold
|
| 426 |
+
new_annotation["masks"] = masks
|
| 427 |
+
elif key == "size":
|
| 428 |
+
new_annotation["size"] = target_size
|
| 429 |
+
else:
|
| 430 |
+
new_annotation[key] = value
|
| 431 |
+
|
| 432 |
+
return new_annotation
|
| 433 |
+
|
| 434 |
+
def normalize_annotation(self, annotation: dict, image_size: tuple[int, int]) -> dict:
|
| 435 |
+
image_height, image_width = image_size
|
| 436 |
+
norm_annotation = {}
|
| 437 |
+
for key, value in annotation.items():
|
| 438 |
+
if key == "boxes":
|
| 439 |
+
boxes = value
|
| 440 |
+
boxes = corners_to_center_format(boxes)
|
| 441 |
+
boxes /= torch.as_tensor(
|
| 442 |
+
[image_width, image_height, image_width, image_height], dtype=torch.float32, device=boxes.device
|
| 443 |
+
)
|
| 444 |
+
norm_annotation[key] = boxes
|
| 445 |
+
else:
|
| 446 |
+
norm_annotation[key] = value
|
| 447 |
+
return norm_annotation
|
| 448 |
+
|
| 449 |
+
def _update_annotation_for_padded_image(
|
| 450 |
+
self,
|
| 451 |
+
annotation: dict,
|
| 452 |
+
input_image_size: tuple[int, int],
|
| 453 |
+
output_image_size: tuple[int, int],
|
| 454 |
+
padding,
|
| 455 |
+
update_bboxes,
|
| 456 |
+
) -> dict:
|
| 457 |
+
"""
|
| 458 |
+
Update the annotation for a padded image.
|
| 459 |
+
"""
|
| 460 |
+
new_annotation = {}
|
| 461 |
+
new_annotation["size"] = output_image_size
|
| 462 |
+
ratio_height, ratio_width = (input / output for output, input in zip(output_image_size, input_image_size))
|
| 463 |
+
|
| 464 |
+
for key, value in annotation.items():
|
| 465 |
+
if key == "masks":
|
| 466 |
+
masks = value
|
| 467 |
+
masks = tvF.pad(
|
| 468 |
+
masks,
|
| 469 |
+
padding,
|
| 470 |
+
fill=0,
|
| 471 |
+
)
|
| 472 |
+
masks = safe_squeeze(masks, 1)
|
| 473 |
+
new_annotation["masks"] = masks
|
| 474 |
+
elif key == "boxes" and update_bboxes:
|
| 475 |
+
boxes = value
|
| 476 |
+
boxes *= torch.as_tensor([ratio_width, ratio_height, ratio_width, ratio_height], device=boxes.device)
|
| 477 |
+
new_annotation["boxes"] = boxes
|
| 478 |
+
elif key == "size":
|
| 479 |
+
new_annotation["size"] = output_image_size
|
| 480 |
+
else:
|
| 481 |
+
new_annotation[key] = value
|
| 482 |
+
return new_annotation
|
| 483 |
+
|
| 484 |
+
def pad(
|
| 485 |
+
self,
|
| 486 |
+
image: torch.Tensor,
|
| 487 |
+
padded_size: tuple[int, int],
|
| 488 |
+
annotation: dict[str, Any] | None = None,
|
| 489 |
+
update_bboxes: bool = True,
|
| 490 |
+
fill: int = 0,
|
| 491 |
+
):
|
| 492 |
+
original_size = image.size()[-2:]
|
| 493 |
+
padding_bottom = padded_size[0] - original_size[0]
|
| 494 |
+
padding_right = padded_size[1] - original_size[1]
|
| 495 |
+
if padding_bottom < 0 or padding_right < 0:
|
| 496 |
+
raise ValueError(
|
| 497 |
+
f"Padding dimensions are negative. Please make sure that the padded size is larger than the "
|
| 498 |
+
f"original size. Got padded size: {padded_size}, original size: {original_size}."
|
| 499 |
+
)
|
| 500 |
+
if original_size != padded_size:
|
| 501 |
+
padding = [0, 0, padding_right, padding_bottom]
|
| 502 |
+
image = tvF.pad(image, padding, fill=fill)
|
| 503 |
+
if annotation is not None:
|
| 504 |
+
annotation = self._update_annotation_for_padded_image(
|
| 505 |
+
annotation, original_size, padded_size, padding, update_bboxes
|
| 506 |
+
)
|
| 507 |
+
|
| 508 |
+
# Make a pixel mask for the image, where 1 indicates a valid pixel and 0 indicates padding.
|
| 509 |
+
pixel_mask = torch.zeros(padded_size, dtype=torch.int64, device=image.device)
|
| 510 |
+
pixel_mask[: original_size[0], : original_size[1]] = 1
|
| 511 |
+
|
| 512 |
+
return image, pixel_mask, annotation
|
| 513 |
+
|
| 514 |
+
@auto_docstring
|
| 515 |
+
def preprocess(
|
| 516 |
+
self,
|
| 517 |
+
images: ImageInput,
|
| 518 |
+
annotations: AnnotationType | list[AnnotationType] | None = None,
|
| 519 |
+
return_segmentation_masks: bool | None = None,
|
| 520 |
+
masks_path: str | pathlib.Path | None = None,
|
| 521 |
+
**kwargs: Unpack[DeformableDetrImageProcessorKwargs],
|
| 522 |
+
) -> BatchFeature:
|
| 523 |
+
r"""
|
| 524 |
+
annotations (`AnnotationType` or `list[AnnotationType]`, *optional*):
|
| 525 |
+
Annotations to transform according to the padding that is applied to the images.
|
| 526 |
+
return_segmentation_masks (`bool`, *optional*, defaults to `self.return_segmentation_masks`):
|
| 527 |
+
Whether to return segmentation masks.
|
| 528 |
+
masks_path (`str` or `pathlib.Path`, *optional*):
|
| 529 |
+
Path to the directory containing the segmentation masks.
|
| 530 |
+
"""
|
| 531 |
+
return super().preprocess(images, annotations, return_segmentation_masks, masks_path, **kwargs)
|
| 532 |
+
|
| 533 |
+
def _preprocess(
|
| 534 |
+
self,
|
| 535 |
+
images: list["torch.Tensor"],
|
| 536 |
+
annotations: AnnotationType | list[AnnotationType] | None,
|
| 537 |
+
return_segmentation_masks: bool,
|
| 538 |
+
masks_path: str | pathlib.Path | None,
|
| 539 |
+
do_resize: bool,
|
| 540 |
+
size: SizeDict,
|
| 541 |
+
resample: "PILImageResampling | tvF.InterpolationMode | int | None",
|
| 542 |
+
do_rescale: bool,
|
| 543 |
+
rescale_factor: float,
|
| 544 |
+
do_normalize: bool,
|
| 545 |
+
do_convert_annotations: bool,
|
| 546 |
+
image_mean: float | list[float] | None,
|
| 547 |
+
image_std: float | list[float] | None,
|
| 548 |
+
do_pad: bool,
|
| 549 |
+
pad_size: SizeDict | None,
|
| 550 |
+
format: str | AnnotationFormat | None,
|
| 551 |
+
return_tensors: str | TensorType | None,
|
| 552 |
+
**kwargs,
|
| 553 |
+
) -> BatchFeature:
|
| 554 |
+
"""
|
| 555 |
+
Preprocess an image or a batch of images so that it can be used by the model.
|
| 556 |
+
"""
|
| 557 |
+
if annotations is not None and isinstance(annotations, dict):
|
| 558 |
+
annotations = [annotations]
|
| 559 |
+
|
| 560 |
+
if annotations is not None and len(images) != len(annotations):
|
| 561 |
+
raise ValueError(
|
| 562 |
+
f"The number of images ({len(images)}) and annotations ({len(annotations)}) do not match."
|
| 563 |
+
)
|
| 564 |
+
|
| 565 |
+
format = AnnotationFormat(format)
|
| 566 |
+
if annotations is not None:
|
| 567 |
+
validate_annotations(format, SUPPORTED_ANNOTATION_FORMATS, annotations)
|
| 568 |
+
|
| 569 |
+
if (
|
| 570 |
+
masks_path is not None
|
| 571 |
+
and format == AnnotationFormat.COCO_PANOPTIC
|
| 572 |
+
and not isinstance(masks_path, (pathlib.Path, str))
|
| 573 |
+
):
|
| 574 |
+
raise ValueError(
|
| 575 |
+
"The path to the directory containing the mask PNG files should be provided as a"
|
| 576 |
+
f" `pathlib.Path` or string object, but is {type(masks_path)} instead."
|
| 577 |
+
)
|
| 578 |
+
|
| 579 |
+
data = {}
|
| 580 |
+
|
| 581 |
+
processed_images = []
|
| 582 |
+
processed_annotations = []
|
| 583 |
+
pixel_masks = [] # Initialize pixel_masks here
|
| 584 |
+
for image, annotation in zip(images, annotations if annotations is not None else [None] * len(images)):
|
| 585 |
+
# prepare (COCO annotations as a list of Dict -> DEFORMABLE_DETR target as a single Dict per image)
|
| 586 |
+
if annotations is not None:
|
| 587 |
+
annotation = self.prepare_annotation(
|
| 588 |
+
image,
|
| 589 |
+
annotation,
|
| 590 |
+
format,
|
| 591 |
+
return_segmentation_masks=return_segmentation_masks,
|
| 592 |
+
masks_path=masks_path,
|
| 593 |
+
input_data_format=ChannelDimension.FIRST,
|
| 594 |
+
)
|
| 595 |
+
|
| 596 |
+
if do_resize:
|
| 597 |
+
resized_image = self.resize(image, size=size, resample=resample)
|
| 598 |
+
if annotations is not None:
|
| 599 |
+
annotation = self.resize_annotation(
|
| 600 |
+
annotation,
|
| 601 |
+
orig_size=image.size()[-2:],
|
| 602 |
+
target_size=resized_image.size()[-2:],
|
| 603 |
+
)
|
| 604 |
+
image = resized_image
|
| 605 |
+
# Fused rescale and normalize
|
| 606 |
+
image = self.rescale_and_normalize(image, do_rescale, rescale_factor, do_normalize, image_mean, image_std)
|
| 607 |
+
if do_convert_annotations and annotations is not None:
|
| 608 |
+
annotation = self.normalize_annotation(annotation, get_image_size(image, ChannelDimension.FIRST))
|
| 609 |
+
|
| 610 |
+
processed_images.append(image)
|
| 611 |
+
processed_annotations.append(annotation)
|
| 612 |
+
images = processed_images
|
| 613 |
+
annotations = processed_annotations if annotations is not None else None
|
| 614 |
+
|
| 615 |
+
if do_pad:
|
| 616 |
+
# depends on all resized image shapes so we need another loop
|
| 617 |
+
if pad_size is not None:
|
| 618 |
+
padded_size = (pad_size.height, pad_size.width)
|
| 619 |
+
else:
|
| 620 |
+
padded_size = get_max_height_width(images)
|
| 621 |
+
|
| 622 |
+
padded_images = []
|
| 623 |
+
padded_annotations = []
|
| 624 |
+
for image, annotation in zip(images, annotations if annotations is not None else [None] * len(images)):
|
| 625 |
+
# Pads images and returns their mask: {'pixel_values': ..., 'pixel_mask': ...}
|
| 626 |
+
if padded_size == image.size()[-2:]:
|
| 627 |
+
padded_images.append(image)
|
| 628 |
+
pixel_masks.append(torch.ones(padded_size, dtype=torch.int64, device=image.device))
|
| 629 |
+
padded_annotations.append(annotation)
|
| 630 |
+
continue
|
| 631 |
+
image, pixel_mask, annotation = self.pad(
|
| 632 |
+
image, padded_size, annotation=annotation, update_bboxes=do_convert_annotations
|
| 633 |
+
)
|
| 634 |
+
padded_images.append(image)
|
| 635 |
+
padded_annotations.append(annotation)
|
| 636 |
+
pixel_masks.append(pixel_mask)
|
| 637 |
+
images = padded_images
|
| 638 |
+
annotations = padded_annotations if annotations is not None else None
|
| 639 |
+
data.update({"pixel_mask": torch.stack(pixel_masks, dim=0)})
|
| 640 |
+
|
| 641 |
+
data.update({"pixel_values": torch.stack(images, dim=0)})
|
| 642 |
+
encoded_inputs = BatchFeature(data, tensor_type=return_tensors)
|
| 643 |
+
if annotations is not None:
|
| 644 |
+
encoded_inputs["labels"] = [
|
| 645 |
+
BatchFeature(annotation, tensor_type=return_tensors) for annotation in annotations
|
| 646 |
+
]
|
| 647 |
+
return encoded_inputs
|
| 648 |
+
|
| 649 |
+
def post_process_object_detection(
|
| 650 |
+
self, outputs, threshold: float = 0.5, target_sizes: TensorType | list[tuple] = None, top_k: int = 100
|
| 651 |
+
):
|
| 652 |
+
"""
|
| 653 |
+
Converts the raw output of [`DeformableDetrForObjectDetection`] into final bounding boxes in (top_left_x,
|
| 654 |
+
top_left_y, bottom_right_x, bottom_right_y) format. Only supports PyTorch.
|
| 655 |
+
|
| 656 |
+
Args:
|
| 657 |
+
outputs ([`DetrObjectDetectionOutput`]):
|
| 658 |
+
Raw outputs of the model.
|
| 659 |
+
threshold (`float`, *optional*):
|
| 660 |
+
Score threshold to keep object detection predictions.
|
| 661 |
+
target_sizes (`torch.Tensor` or `list[tuple[int, int]]`, *optional*):
|
| 662 |
+
Tensor of shape `(batch_size, 2)` or list of tuples (`tuple[int, int]`) containing the target size
|
| 663 |
+
(height, width) of each image in the batch. If left to None, predictions will not be resized.
|
| 664 |
+
top_k (`int`, *optional*, defaults to 100):
|
| 665 |
+
Keep only top k bounding boxes before filtering by thresholding.
|
| 666 |
+
|
| 667 |
+
Returns:
|
| 668 |
+
`list[Dict]`: A list of dictionaries, each dictionary containing the scores, labels and boxes for an image
|
| 669 |
+
in the batch as predicted by the model.
|
| 670 |
+
"""
|
| 671 |
+
out_logits, out_bbox = outputs.logits, outputs.pred_boxes
|
| 672 |
+
|
| 673 |
+
if target_sizes is not None:
|
| 674 |
+
if len(out_logits) != len(target_sizes):
|
| 675 |
+
raise ValueError(
|
| 676 |
+
"Make sure that you pass in as many target sizes as the batch dimension of the logits"
|
| 677 |
+
)
|
| 678 |
+
|
| 679 |
+
prob = out_logits.sigmoid()
|
| 680 |
+
prob = prob.view(out_logits.shape[0], -1)
|
| 681 |
+
k_value = min(top_k, prob.size(1))
|
| 682 |
+
topk_values, topk_indexes = torch.topk(prob, k_value, dim=1)
|
| 683 |
+
scores = topk_values
|
| 684 |
+
topk_boxes = torch.div(topk_indexes, out_logits.shape[2], rounding_mode="floor")
|
| 685 |
+
labels = topk_indexes % out_logits.shape[2]
|
| 686 |
+
boxes = center_to_corners_format(out_bbox)
|
| 687 |
+
boxes = torch.gather(boxes, 1, topk_boxes.unsqueeze(-1).repeat(1, 1, 4))
|
| 688 |
+
|
| 689 |
+
# and from relative [0, 1] to absolute [0, height] coordinates
|
| 690 |
+
if target_sizes is not None:
|
| 691 |
+
if isinstance(target_sizes, list):
|
| 692 |
+
img_h = torch.Tensor([i[0] for i in target_sizes])
|
| 693 |
+
img_w = torch.Tensor([i[1] for i in target_sizes])
|
| 694 |
+
else:
|
| 695 |
+
img_h, img_w = target_sizes.unbind(1)
|
| 696 |
+
scale_fct = torch.stack([img_w, img_h, img_w, img_h], dim=1).to(boxes.device)
|
| 697 |
+
boxes = boxes * scale_fct[:, None, :]
|
| 698 |
+
|
| 699 |
+
results = []
|
| 700 |
+
for s, l, b in zip(scores, labels, boxes):
|
| 701 |
+
score = s[s > threshold]
|
| 702 |
+
label = l[s > threshold]
|
| 703 |
+
box = b[s > threshold]
|
| 704 |
+
results.append({"scores": score, "labels": label, "boxes": box})
|
| 705 |
+
|
| 706 |
+
return results
|
| 707 |
+
|
| 708 |
+
|
| 709 |
+
__all__ = ["DeformableDetrImageProcessor"]
|
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/models/deformable_detr/image_processing_pil_deformable_detr.py
ADDED
|
@@ -0,0 +1,738 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
|
| 2 |
+
# This file was automatically generated from src/transformers/models/deformable_detr/modular_deformable_detr.py.
|
| 3 |
+
# Do NOT edit this file manually as any edits will be overwritten by the generation of
|
| 4 |
+
# the file from the modular. If any change should be done, please apply the change to the
|
| 5 |
+
# modular_deformable_detr.py file directly. One of our CI enforces this.
|
| 6 |
+
# 🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
|
| 7 |
+
# Copyright 2022 SenseTime and The HuggingFace Inc. team. All rights reserved.
|
| 8 |
+
#
|
| 9 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 10 |
+
# you may not use this file except in compliance with the License.
|
| 11 |
+
# You may obtain a copy of the License at
|
| 12 |
+
#
|
| 13 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 14 |
+
#
|
| 15 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 16 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 17 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 18 |
+
# See the License for the specific language governing permissions and
|
| 19 |
+
# limitations under the License.
|
| 20 |
+
import pathlib
|
| 21 |
+
from typing import Any, Optional
|
| 22 |
+
|
| 23 |
+
import numpy as np
|
| 24 |
+
|
| 25 |
+
from ...image_processing_backends import PilBackend
|
| 26 |
+
from ...image_processing_utils import BatchFeature
|
| 27 |
+
from ...image_transforms import (
|
| 28 |
+
PaddingMode,
|
| 29 |
+
center_to_corners_format,
|
| 30 |
+
corners_to_center_format,
|
| 31 |
+
get_size_with_aspect_ratio,
|
| 32 |
+
pad,
|
| 33 |
+
resize,
|
| 34 |
+
safe_squeeze,
|
| 35 |
+
)
|
| 36 |
+
from ...image_utils import (
|
| 37 |
+
IMAGENET_DEFAULT_MEAN,
|
| 38 |
+
IMAGENET_DEFAULT_STD,
|
| 39 |
+
AnnotationFormat,
|
| 40 |
+
AnnotationType,
|
| 41 |
+
ChannelDimension,
|
| 42 |
+
ImageInput,
|
| 43 |
+
PILImageResampling,
|
| 44 |
+
SizeDict,
|
| 45 |
+
get_image_size,
|
| 46 |
+
get_image_size_for_max_height_width,
|
| 47 |
+
get_max_height_width,
|
| 48 |
+
validate_annotations,
|
| 49 |
+
)
|
| 50 |
+
from ...processing_utils import ImagesKwargs, Unpack
|
| 51 |
+
from ...utils import TensorType, auto_docstring, is_torch_available, is_vision_available
|
| 52 |
+
from ...utils.import_utils import requires, requires_backends
|
| 53 |
+
|
| 54 |
+
|
| 55 |
+
if is_vision_available():
|
| 56 |
+
import PIL.Image
|
| 57 |
+
if is_torch_available():
|
| 58 |
+
import torch
|
| 59 |
+
|
| 60 |
+
SUPPORTED_ANNOTATION_FORMATS = (AnnotationFormat.COCO_DETECTION, AnnotationFormat.COCO_PANOPTIC)
|
| 61 |
+
|
| 62 |
+
|
| 63 |
+
class DeformableDetrImageProcessorKwargs(ImagesKwargs, total=False):
|
| 64 |
+
r"""
|
| 65 |
+
format (`str`, *optional*, defaults to `AnnotationFormat.COCO_DETECTION`):
|
| 66 |
+
Data format of the annotations. One of "coco_detection" or "coco_panoptic".
|
| 67 |
+
do_convert_annotations (`bool`, *optional*, defaults to `True`):
|
| 68 |
+
Controls whether to convert the annotations to the format expected by the DEFORMABLE_DETR model. Converts the
|
| 69 |
+
bounding boxes to the format `(center_x, center_y, width, height)` and in the range `[0, 1]`.
|
| 70 |
+
Can be overridden by the `do_convert_annotations` parameter in the `preprocess` method.
|
| 71 |
+
"""
|
| 72 |
+
|
| 73 |
+
format: str | AnnotationFormat
|
| 74 |
+
do_convert_annotations: bool
|
| 75 |
+
|
| 76 |
+
|
| 77 |
+
# inspired by https://github.com/facebookresearch/deformable_detr/blob/master/datasets/coco.py#L33
|
| 78 |
+
def convert_coco_poly_to_mask(segmentations, height: int, width: int) -> np.ndarray:
|
| 79 |
+
"""
|
| 80 |
+
Convert a COCO polygon annotation to a mask.
|
| 81 |
+
|
| 82 |
+
Args:
|
| 83 |
+
segmentations (`list[list[float]]`):
|
| 84 |
+
List of polygons, each polygon represented by a list of x-y coordinates.
|
| 85 |
+
height (`int`):
|
| 86 |
+
Height of the mask.
|
| 87 |
+
width (`int`):
|
| 88 |
+
Width of the mask.
|
| 89 |
+
"""
|
| 90 |
+
try:
|
| 91 |
+
from pycocotools import mask as coco_mask
|
| 92 |
+
except ImportError:
|
| 93 |
+
raise ImportError("Pycocotools is not installed in your environment.")
|
| 94 |
+
|
| 95 |
+
masks = []
|
| 96 |
+
for polygons in segmentations:
|
| 97 |
+
rles = coco_mask.frPyObjects(polygons, height, width)
|
| 98 |
+
mask = coco_mask.decode(rles)
|
| 99 |
+
if len(mask.shape) < 3:
|
| 100 |
+
mask = mask[..., None]
|
| 101 |
+
mask = np.asarray(mask, dtype=np.uint8)
|
| 102 |
+
mask = np.any(mask, axis=2)
|
| 103 |
+
masks.append(mask)
|
| 104 |
+
if masks:
|
| 105 |
+
masks = np.stack(masks, axis=0)
|
| 106 |
+
else:
|
| 107 |
+
masks = np.zeros((0, height, width), dtype=np.uint8)
|
| 108 |
+
|
| 109 |
+
return masks
|
| 110 |
+
|
| 111 |
+
|
| 112 |
+
# inspired by https://github.com/facebookresearch/deformable_detr/blob/master/datasets/coco.py#L50
|
| 113 |
+
def prepare_coco_detection_annotation(
|
| 114 |
+
image,
|
| 115 |
+
target,
|
| 116 |
+
return_segmentation_masks: bool = False,
|
| 117 |
+
input_data_format: ChannelDimension | str | None = None,
|
| 118 |
+
):
|
| 119 |
+
"""
|
| 120 |
+
Convert the target in COCO format into the format expected by DEFORMABLE_DETR.
|
| 121 |
+
"""
|
| 122 |
+
image_height, image_width = get_image_size(image, channel_dim=input_data_format)
|
| 123 |
+
|
| 124 |
+
image_id = target["image_id"]
|
| 125 |
+
image_id = np.asarray([image_id], dtype=np.int64)
|
| 126 |
+
|
| 127 |
+
# Get all COCO annotations for the given image.
|
| 128 |
+
annotations = target["annotations"]
|
| 129 |
+
annotations = [obj for obj in annotations if "iscrowd" not in obj or obj["iscrowd"] == 0]
|
| 130 |
+
|
| 131 |
+
classes = [obj["category_id"] for obj in annotations]
|
| 132 |
+
classes = np.asarray(classes, dtype=np.int64)
|
| 133 |
+
|
| 134 |
+
# for conversion to coco api
|
| 135 |
+
area = np.asarray([obj["area"] for obj in annotations], dtype=np.float32)
|
| 136 |
+
iscrowd = np.asarray([obj.get("iscrowd", 0) for obj in annotations], dtype=np.int64)
|
| 137 |
+
|
| 138 |
+
boxes = [obj["bbox"] for obj in annotations]
|
| 139 |
+
# guard against no boxes via resizing
|
| 140 |
+
boxes = np.asarray(boxes, dtype=np.float32).reshape(-1, 4)
|
| 141 |
+
boxes[:, 2:] += boxes[:, :2]
|
| 142 |
+
boxes[:, 0::2] = boxes[:, 0::2].clip(min=0, max=image_width)
|
| 143 |
+
boxes[:, 1::2] = boxes[:, 1::2].clip(min=0, max=image_height)
|
| 144 |
+
|
| 145 |
+
keep = (boxes[:, 3] > boxes[:, 1]) & (boxes[:, 2] > boxes[:, 0])
|
| 146 |
+
|
| 147 |
+
new_target = {}
|
| 148 |
+
new_target["image_id"] = image_id
|
| 149 |
+
new_target["class_labels"] = classes[keep]
|
| 150 |
+
new_target["boxes"] = boxes[keep]
|
| 151 |
+
new_target["area"] = area[keep]
|
| 152 |
+
new_target["iscrowd"] = iscrowd[keep]
|
| 153 |
+
new_target["orig_size"] = np.asarray([int(image_height), int(image_width)], dtype=np.int64)
|
| 154 |
+
|
| 155 |
+
if annotations and "keypoints" in annotations[0]:
|
| 156 |
+
keypoints = [obj["keypoints"] for obj in annotations]
|
| 157 |
+
# Converting the filtered keypoints list to a numpy array
|
| 158 |
+
keypoints = np.asarray(keypoints, dtype=np.float32)
|
| 159 |
+
# Apply the keep mask here to filter the relevant annotations
|
| 160 |
+
keypoints = keypoints[keep]
|
| 161 |
+
num_keypoints = keypoints.shape[0]
|
| 162 |
+
keypoints = keypoints.reshape((-1, 3)) if num_keypoints else keypoints
|
| 163 |
+
new_target["keypoints"] = keypoints
|
| 164 |
+
|
| 165 |
+
if return_segmentation_masks:
|
| 166 |
+
segmentation_masks = [obj["segmentation"] for obj in annotations]
|
| 167 |
+
masks = convert_coco_poly_to_mask(segmentation_masks, image_height, image_width)
|
| 168 |
+
new_target["masks"] = masks[keep]
|
| 169 |
+
|
| 170 |
+
return new_target
|
| 171 |
+
|
| 172 |
+
|
| 173 |
+
def masks_to_boxes(masks: np.ndarray) -> np.ndarray:
|
| 174 |
+
"""
|
| 175 |
+
Compute the bounding boxes around the provided panoptic segmentation masks.
|
| 176 |
+
|
| 177 |
+
Args:
|
| 178 |
+
masks: masks in format `[number_masks, height, width]` where N is the number of masks
|
| 179 |
+
|
| 180 |
+
Returns:
|
| 181 |
+
boxes: bounding boxes in format `[number_masks, 4]` in xyxy format
|
| 182 |
+
"""
|
| 183 |
+
if masks.size == 0:
|
| 184 |
+
return np.zeros((0, 4))
|
| 185 |
+
|
| 186 |
+
h, w = masks.shape[-2:]
|
| 187 |
+
y = np.arange(0, h, dtype=np.float32)
|
| 188 |
+
x = np.arange(0, w, dtype=np.float32)
|
| 189 |
+
# see https://github.com/pytorch/pytorch/issues/50276
|
| 190 |
+
y, x = np.meshgrid(y, x, indexing="ij")
|
| 191 |
+
|
| 192 |
+
x_mask = masks * np.expand_dims(x, axis=0)
|
| 193 |
+
x_max = x_mask.reshape(x_mask.shape[0], -1).max(-1)
|
| 194 |
+
x = np.ma.array(x_mask, mask=~(np.array(masks, dtype=bool)))
|
| 195 |
+
x_min = x.filled(fill_value=1e8)
|
| 196 |
+
x_min = x_min.reshape(x_min.shape[0], -1).min(-1)
|
| 197 |
+
|
| 198 |
+
y_mask = masks * np.expand_dims(y, axis=0)
|
| 199 |
+
y_max = y_mask.reshape(x_mask.shape[0], -1).max(-1)
|
| 200 |
+
y = np.ma.array(y_mask, mask=~(np.array(masks, dtype=bool)))
|
| 201 |
+
y_min = y.filled(fill_value=1e8)
|
| 202 |
+
y_min = y_min.reshape(y_min.shape[0], -1).min(-1)
|
| 203 |
+
|
| 204 |
+
return np.stack([x_min, y_min, x_max, y_max], 1)
|
| 205 |
+
|
| 206 |
+
|
| 207 |
+
# 2 functions below adapted from https://github.com/cocodataset/panopticapi/blob/master/panopticapi/utils.py
|
| 208 |
+
# Copyright (c) 2018, Alexander Kirillov
|
| 209 |
+
# All rights reserved.
|
| 210 |
+
def rgb_to_id(color):
|
| 211 |
+
"""
|
| 212 |
+
Converts RGB color to unique ID.
|
| 213 |
+
"""
|
| 214 |
+
if isinstance(color, np.ndarray) and len(color.shape) == 3:
|
| 215 |
+
if color.dtype == np.uint8:
|
| 216 |
+
color = color.astype(np.int32)
|
| 217 |
+
return color[:, :, 0] + 256 * color[:, :, 1] + 256 * 256 * color[:, :, 2]
|
| 218 |
+
return int(color[0] + 256 * color[1] + 256 * 256 * color[2])
|
| 219 |
+
|
| 220 |
+
|
| 221 |
+
def prepare_coco_panoptic_annotation(
|
| 222 |
+
image: np.ndarray,
|
| 223 |
+
target: dict,
|
| 224 |
+
masks_path: str | pathlib.Path,
|
| 225 |
+
return_masks: bool = True,
|
| 226 |
+
input_data_format: ChannelDimension | str = None,
|
| 227 |
+
) -> dict:
|
| 228 |
+
"""
|
| 229 |
+
Prepare a coco panoptic annotation for DEFORMABLE_DETR.
|
| 230 |
+
"""
|
| 231 |
+
image_height, image_width = get_image_size(image, channel_dim=input_data_format)
|
| 232 |
+
annotation_path = pathlib.Path(masks_path) / target["file_name"]
|
| 233 |
+
|
| 234 |
+
new_target = {}
|
| 235 |
+
new_target["image_id"] = np.asarray([target["image_id"] if "image_id" in target else target["id"]], dtype=np.int64)
|
| 236 |
+
new_target["size"] = np.asarray([image_height, image_width], dtype=np.int64)
|
| 237 |
+
new_target["orig_size"] = np.asarray([image_height, image_width], dtype=np.int64)
|
| 238 |
+
|
| 239 |
+
if "segments_info" in target:
|
| 240 |
+
masks = np.asarray(PIL.Image.open(annotation_path), dtype=np.uint32)
|
| 241 |
+
masks = rgb_to_id(masks)
|
| 242 |
+
|
| 243 |
+
ids = np.array([segment_info["id"] for segment_info in target["segments_info"]])
|
| 244 |
+
masks = masks == ids[:, None, None]
|
| 245 |
+
masks = masks.astype(np.uint8)
|
| 246 |
+
if return_masks:
|
| 247 |
+
new_target["masks"] = masks
|
| 248 |
+
new_target["boxes"] = masks_to_boxes(masks)
|
| 249 |
+
new_target["class_labels"] = np.array(
|
| 250 |
+
[segment_info["category_id"] for segment_info in target["segments_info"]], dtype=np.int64
|
| 251 |
+
)
|
| 252 |
+
new_target["iscrowd"] = np.asarray(
|
| 253 |
+
[segment_info["iscrowd"] for segment_info in target["segments_info"]], dtype=np.int64
|
| 254 |
+
)
|
| 255 |
+
new_target["area"] = np.asarray(
|
| 256 |
+
[segment_info["area"] for segment_info in target["segments_info"]], dtype=np.float32
|
| 257 |
+
)
|
| 258 |
+
|
| 259 |
+
return new_target
|
| 260 |
+
|
| 261 |
+
|
| 262 |
+
@auto_docstring
|
| 263 |
+
class DeformableDetrImageProcessorPil(PilBackend):
|
| 264 |
+
resample = PILImageResampling.BILINEAR
|
| 265 |
+
image_mean = IMAGENET_DEFAULT_MEAN
|
| 266 |
+
image_std = IMAGENET_DEFAULT_STD
|
| 267 |
+
format = AnnotationFormat.COCO_DETECTION
|
| 268 |
+
do_resize = True
|
| 269 |
+
do_rescale = True
|
| 270 |
+
do_normalize = True
|
| 271 |
+
do_pad = True
|
| 272 |
+
size = {"shortest_edge": 800, "longest_edge": 1333}
|
| 273 |
+
default_to_square = False
|
| 274 |
+
model_input_names = ["pixel_values", "pixel_mask"]
|
| 275 |
+
valid_kwargs = DeformableDetrImageProcessorKwargs
|
| 276 |
+
|
| 277 |
+
def __init__(self, **kwargs: Unpack[DeformableDetrImageProcessorKwargs]) -> None:
|
| 278 |
+
kwargs.setdefault("do_pad", kwargs.pop("pad_and_return_pixel_mask", self.do_pad))
|
| 279 |
+
|
| 280 |
+
size = kwargs.pop("size", None)
|
| 281 |
+
max_size = None if size is None else kwargs.pop("max_size", 1333)
|
| 282 |
+
size = size if size is not None else {"shortest_edge": 800, "longest_edge": 1333}
|
| 283 |
+
# Convert size dict for backwards compat with max_size parameter
|
| 284 |
+
if size is not None:
|
| 285 |
+
from ...image_processing_utils import get_size_dict
|
| 286 |
+
|
| 287 |
+
kwargs["size"] = get_size_dict(size, max_size=max_size, default_to_square=False)
|
| 288 |
+
|
| 289 |
+
# Backwards compatibility
|
| 290 |
+
do_convert_annotations = kwargs.get("do_convert_annotations")
|
| 291 |
+
do_normalize = kwargs.get("do_normalize")
|
| 292 |
+
if do_convert_annotations is None and getattr(self, "do_convert_annotations", None) is None:
|
| 293 |
+
self.do_convert_annotations = do_normalize if do_normalize is not None else self.do_normalize
|
| 294 |
+
|
| 295 |
+
super().__init__(**kwargs)
|
| 296 |
+
|
| 297 |
+
def prepare_annotation(
|
| 298 |
+
self,
|
| 299 |
+
image: np.ndarray,
|
| 300 |
+
target: dict,
|
| 301 |
+
format: AnnotationFormat | None = None,
|
| 302 |
+
return_segmentation_masks: bool | None = None,
|
| 303 |
+
masks_path: str | pathlib.Path | None = None,
|
| 304 |
+
input_data_format: str | ChannelDimension | None = None,
|
| 305 |
+
) -> dict:
|
| 306 |
+
"""
|
| 307 |
+
Prepare an annotation for feeding into DEFORMABLE_DETR model.
|
| 308 |
+
"""
|
| 309 |
+
format = format if format is not None else self.format
|
| 310 |
+
|
| 311 |
+
if format == AnnotationFormat.COCO_DETECTION:
|
| 312 |
+
return_segmentation_masks = False if return_segmentation_masks is None else return_segmentation_masks
|
| 313 |
+
target = prepare_coco_detection_annotation(
|
| 314 |
+
image, target, return_segmentation_masks, input_data_format=input_data_format
|
| 315 |
+
)
|
| 316 |
+
elif format == AnnotationFormat.COCO_PANOPTIC:
|
| 317 |
+
return_segmentation_masks = True if return_segmentation_masks is None else return_segmentation_masks
|
| 318 |
+
target = prepare_coco_panoptic_annotation(
|
| 319 |
+
image,
|
| 320 |
+
target,
|
| 321 |
+
masks_path=masks_path,
|
| 322 |
+
return_masks=return_segmentation_masks,
|
| 323 |
+
input_data_format=input_data_format,
|
| 324 |
+
)
|
| 325 |
+
else:
|
| 326 |
+
raise ValueError(f"Format {format} is not supported.")
|
| 327 |
+
return target
|
| 328 |
+
|
| 329 |
+
def resize(
|
| 330 |
+
self,
|
| 331 |
+
image: np.ndarray,
|
| 332 |
+
size: SizeDict,
|
| 333 |
+
resample: Optional["PILImageResampling"] = None,
|
| 334 |
+
**kwargs,
|
| 335 |
+
) -> np.ndarray:
|
| 336 |
+
"""
|
| 337 |
+
Resize the image to the given size. Size can be `min_size` (scalar) or `(height, width)` tuple. If size is an
|
| 338 |
+
int, smaller edge of the image will be matched to this number.
|
| 339 |
+
|
| 340 |
+
Args:
|
| 341 |
+
image (`np.ndarray`):
|
| 342 |
+
Image to resize.
|
| 343 |
+
size (`SizeDict`):
|
| 344 |
+
Size of the image's `(height, width)` dimensions after resizing. Available options are:
|
| 345 |
+
- `{"height": int, "width": int}`: The image will be resized to the exact size `(height, width)`.
|
| 346 |
+
Do NOT keep the aspect ratio.
|
| 347 |
+
- `{"shortest_edge": int, "longest_edge": int}`: The image will be resized to a maximum size respecting
|
| 348 |
+
the aspect ratio and keeping the shortest edge less or equal to `shortest_edge` and the longest edge
|
| 349 |
+
less or equal to `longest_edge`.
|
| 350 |
+
- `{"max_height": int, "max_width": int}`: The image will be resized to the maximum size respecting the
|
| 351 |
+
aspect ratio and keeping the height less or equal to `max_height` and the width less or equal to
|
| 352 |
+
`max_width`.
|
| 353 |
+
resample (`PILImageResampling`, *optional*, defaults to `PILImageResampling.BILINEAR`):
|
| 354 |
+
Resampling filter to use if resizing the image.
|
| 355 |
+
"""
|
| 356 |
+
resample = resample if resample is not None else self.resample
|
| 357 |
+
|
| 358 |
+
if size.shortest_edge and size.longest_edge:
|
| 359 |
+
# Resize the image so that the shortest edge or the longest edge is of the given size
|
| 360 |
+
# while maintaining the aspect ratio of the original image.
|
| 361 |
+
new_size = get_size_with_aspect_ratio(
|
| 362 |
+
image.shape[-2:],
|
| 363 |
+
size.shortest_edge,
|
| 364 |
+
size.longest_edge or size.shortest_edge,
|
| 365 |
+
)
|
| 366 |
+
elif size.max_height and size.max_width:
|
| 367 |
+
new_size = get_image_size_for_max_height_width(image.shape[-2:], size.max_height, size.max_width)
|
| 368 |
+
elif size.height and size.width:
|
| 369 |
+
new_size = (size.height, size.width)
|
| 370 |
+
else:
|
| 371 |
+
raise ValueError(
|
| 372 |
+
f"Size must contain 'height' and 'width' keys or 'shortest_edge' and 'longest_edge' keys. Got {size}."
|
| 373 |
+
)
|
| 374 |
+
|
| 375 |
+
image = super().resize(
|
| 376 |
+
image,
|
| 377 |
+
size=SizeDict(height=new_size[0], width=new_size[1]),
|
| 378 |
+
resample=resample,
|
| 379 |
+
**kwargs,
|
| 380 |
+
)
|
| 381 |
+
return image
|
| 382 |
+
|
| 383 |
+
def resize_annotation(
|
| 384 |
+
self,
|
| 385 |
+
annotation: dict[str, Any],
|
| 386 |
+
orig_size: tuple[int, int],
|
| 387 |
+
target_size: tuple[int, int],
|
| 388 |
+
threshold: float = 0.5,
|
| 389 |
+
resample: Optional["PILImageResampling"] = PILImageResampling.NEAREST,
|
| 390 |
+
):
|
| 391 |
+
"""
|
| 392 |
+
Resizes an annotation to a target size.
|
| 393 |
+
|
| 394 |
+
Args:
|
| 395 |
+
annotation (`dict[str, Any]`):
|
| 396 |
+
The annotation dictionary.
|
| 397 |
+
orig_size (`tuple[int, int]`):
|
| 398 |
+
The original size of the input image.
|
| 399 |
+
target_size (`tuple[int, int]`):
|
| 400 |
+
The target size of the image, as returned by the preprocessing `resize` step.
|
| 401 |
+
threshold (`float`, *optional*, defaults to 0.5):
|
| 402 |
+
The threshold used to binarize the segmentation masks.
|
| 403 |
+
resample (`PILImageResampling`, defaults to `PILImageResampling.NEAREST`):
|
| 404 |
+
The resampling filter to use when resizing the masks.
|
| 405 |
+
"""
|
| 406 |
+
ratios = tuple(float(s) / float(s_orig) for s, s_orig in zip(target_size, orig_size))
|
| 407 |
+
ratio_height, ratio_width = ratios
|
| 408 |
+
|
| 409 |
+
new_annotation = {}
|
| 410 |
+
new_annotation["size"] = target_size
|
| 411 |
+
|
| 412 |
+
for key, value in annotation.items():
|
| 413 |
+
if key == "boxes":
|
| 414 |
+
boxes = value
|
| 415 |
+
scaled_boxes = boxes * np.asarray(
|
| 416 |
+
[ratio_width, ratio_height, ratio_width, ratio_height], dtype=np.float32
|
| 417 |
+
)
|
| 418 |
+
new_annotation["boxes"] = scaled_boxes
|
| 419 |
+
elif key == "area":
|
| 420 |
+
area = value
|
| 421 |
+
scaled_area = area * (ratio_width * ratio_height)
|
| 422 |
+
new_annotation["area"] = scaled_area
|
| 423 |
+
elif key == "masks":
|
| 424 |
+
masks = value[:, None]
|
| 425 |
+
masks = np.array([resize(mask, target_size, resample=resample) for mask in masks])
|
| 426 |
+
masks = masks.astype(np.float32)
|
| 427 |
+
masks = masks[:, 0] > threshold
|
| 428 |
+
new_annotation["masks"] = masks
|
| 429 |
+
elif key == "size":
|
| 430 |
+
new_annotation["size"] = target_size
|
| 431 |
+
else:
|
| 432 |
+
new_annotation[key] = value
|
| 433 |
+
|
| 434 |
+
return new_annotation
|
| 435 |
+
|
| 436 |
+
def normalize_annotation(self, annotation: dict, image_size: tuple[int, int]) -> dict:
|
| 437 |
+
image_height, image_width = image_size
|
| 438 |
+
norm_annotation = {}
|
| 439 |
+
for key, value in annotation.items():
|
| 440 |
+
if key == "boxes":
|
| 441 |
+
boxes = value
|
| 442 |
+
boxes = corners_to_center_format(boxes)
|
| 443 |
+
boxes /= np.asarray([image_width, image_height, image_width, image_height], dtype=np.float32)
|
| 444 |
+
norm_annotation[key] = boxes
|
| 445 |
+
else:
|
| 446 |
+
norm_annotation[key] = value
|
| 447 |
+
return norm_annotation
|
| 448 |
+
|
| 449 |
+
def _update_annotation_for_padded_image(
|
| 450 |
+
self,
|
| 451 |
+
annotation: dict,
|
| 452 |
+
input_image_size: tuple[int, int],
|
| 453 |
+
output_image_size: tuple[int, int],
|
| 454 |
+
padding,
|
| 455 |
+
update_bboxes,
|
| 456 |
+
) -> dict:
|
| 457 |
+
"""
|
| 458 |
+
Update the annotation for a padded image.
|
| 459 |
+
"""
|
| 460 |
+
new_annotation = {}
|
| 461 |
+
new_annotation["size"] = output_image_size
|
| 462 |
+
ratio_height, ratio_width = (input / output for output, input in zip(output_image_size, input_image_size))
|
| 463 |
+
|
| 464 |
+
for key, value in annotation.items():
|
| 465 |
+
if key == "masks":
|
| 466 |
+
masks = value
|
| 467 |
+
masks = pad(
|
| 468 |
+
masks,
|
| 469 |
+
padding,
|
| 470 |
+
mode=PaddingMode.CONSTANT,
|
| 471 |
+
constant_values=0,
|
| 472 |
+
input_data_format=ChannelDimension.FIRST,
|
| 473 |
+
)
|
| 474 |
+
masks = safe_squeeze(masks, 1)
|
| 475 |
+
new_annotation["masks"] = masks
|
| 476 |
+
elif key == "boxes" and update_bboxes:
|
| 477 |
+
boxes = value
|
| 478 |
+
boxes *= np.asarray(
|
| 479 |
+
[
|
| 480 |
+
input_image_size[1] / output_image_size[1],
|
| 481 |
+
input_image_size[0] / output_image_size[0],
|
| 482 |
+
input_image_size[1] / output_image_size[1],
|
| 483 |
+
input_image_size[0] / output_image_size[0],
|
| 484 |
+
]
|
| 485 |
+
)
|
| 486 |
+
new_annotation["boxes"] = boxes
|
| 487 |
+
elif key == "size":
|
| 488 |
+
new_annotation["size"] = output_image_size
|
| 489 |
+
else:
|
| 490 |
+
new_annotation[key] = value
|
| 491 |
+
return new_annotation
|
| 492 |
+
|
| 493 |
+
def pad(
|
| 494 |
+
self,
|
| 495 |
+
image: np.ndarray,
|
| 496 |
+
padded_size: tuple[int, int],
|
| 497 |
+
annotation: dict[str, Any] | None = None,
|
| 498 |
+
update_bboxes: bool = True,
|
| 499 |
+
fill: int = 0,
|
| 500 |
+
):
|
| 501 |
+
input_height, input_width = get_image_size(image, channel_dim=ChannelDimension.FIRST)
|
| 502 |
+
output_height, output_width = padded_size
|
| 503 |
+
padding_bottom = output_height - input_height
|
| 504 |
+
padding_right = output_width - input_width
|
| 505 |
+
if padding_bottom < 0 or padding_right < 0:
|
| 506 |
+
raise ValueError(
|
| 507 |
+
f"Padding dimensions are negative. Please make sure that the padded size is larger than the "
|
| 508 |
+
f"original size. Got padded size: {padded_size}, original size: {(input_height, input_width)}."
|
| 509 |
+
)
|
| 510 |
+
if (input_height, input_width) != padded_size:
|
| 511 |
+
padding = ((0, padding_bottom), (0, padding_right))
|
| 512 |
+
image = pad(
|
| 513 |
+
image,
|
| 514 |
+
padding,
|
| 515 |
+
mode=PaddingMode.CONSTANT,
|
| 516 |
+
constant_values=fill,
|
| 517 |
+
data_format=ChannelDimension.FIRST,
|
| 518 |
+
input_data_format=ChannelDimension.FIRST,
|
| 519 |
+
)
|
| 520 |
+
if annotation is not None:
|
| 521 |
+
annotation = self._update_annotation_for_padded_image(
|
| 522 |
+
annotation, (input_height, input_width), (output_height, output_width), padding, update_bboxes
|
| 523 |
+
)
|
| 524 |
+
|
| 525 |
+
# Make a pixel mask for the image, where 1 indicates a valid pixel and 0 indicates padding.
|
| 526 |
+
pixel_mask = np.zeros(padded_size, dtype=np.int64)
|
| 527 |
+
pixel_mask[:input_height, :input_width] = 1
|
| 528 |
+
|
| 529 |
+
return image, pixel_mask, annotation
|
| 530 |
+
|
| 531 |
+
@auto_docstring
|
| 532 |
+
def preprocess(
|
| 533 |
+
self,
|
| 534 |
+
images: ImageInput,
|
| 535 |
+
annotations: AnnotationType | list[AnnotationType] | None = None,
|
| 536 |
+
return_segmentation_masks: bool | None = None,
|
| 537 |
+
masks_path: str | pathlib.Path | None = None,
|
| 538 |
+
**kwargs: Unpack[DeformableDetrImageProcessorKwargs],
|
| 539 |
+
) -> BatchFeature:
|
| 540 |
+
r"""
|
| 541 |
+
annotations (`AnnotationType` or `list[AnnotationType]`, *optional*):
|
| 542 |
+
Annotations to transform according to the padding that is applied to the images.
|
| 543 |
+
return_segmentation_masks (`bool`, *optional*, defaults to `self.return_segmentation_masks`):
|
| 544 |
+
Whether to return segmentation masks.
|
| 545 |
+
masks_path (`str` or `pathlib.Path`, *optional*):
|
| 546 |
+
Path to the directory containing the segmentation masks.
|
| 547 |
+
"""
|
| 548 |
+
return super().preprocess(images, annotations, return_segmentation_masks, masks_path, **kwargs)
|
| 549 |
+
|
| 550 |
+
def _preprocess(
|
| 551 |
+
self,
|
| 552 |
+
images: list[np.ndarray],
|
| 553 |
+
annotations: AnnotationType | list[AnnotationType] | None,
|
| 554 |
+
return_segmentation_masks: bool,
|
| 555 |
+
masks_path: str | pathlib.Path | None,
|
| 556 |
+
do_resize: bool,
|
| 557 |
+
size: SizeDict,
|
| 558 |
+
resample: "PILImageResampling | None",
|
| 559 |
+
do_rescale: bool,
|
| 560 |
+
rescale_factor: float,
|
| 561 |
+
do_normalize: bool,
|
| 562 |
+
do_convert_annotations: bool,
|
| 563 |
+
image_mean: float | list[float] | None,
|
| 564 |
+
image_std: float | list[float] | None,
|
| 565 |
+
do_pad: bool,
|
| 566 |
+
pad_size: SizeDict | None,
|
| 567 |
+
format: str | AnnotationFormat | None,
|
| 568 |
+
return_tensors: str | TensorType | None,
|
| 569 |
+
**kwargs,
|
| 570 |
+
) -> BatchFeature:
|
| 571 |
+
"""
|
| 572 |
+
Preprocess an image or a batch of images so that it can be used by the model.
|
| 573 |
+
"""
|
| 574 |
+
if annotations is not None and isinstance(annotations, dict):
|
| 575 |
+
annotations = [annotations]
|
| 576 |
+
|
| 577 |
+
if annotations is not None and len(images) != len(annotations):
|
| 578 |
+
raise ValueError(
|
| 579 |
+
f"The number of images ({len(images)}) and annotations ({len(annotations)}) do not match."
|
| 580 |
+
)
|
| 581 |
+
|
| 582 |
+
format = AnnotationFormat(format)
|
| 583 |
+
if annotations is not None:
|
| 584 |
+
validate_annotations(format, SUPPORTED_ANNOTATION_FORMATS, annotations)
|
| 585 |
+
|
| 586 |
+
if (
|
| 587 |
+
masks_path is not None
|
| 588 |
+
and format == AnnotationFormat.COCO_PANOPTIC
|
| 589 |
+
and not isinstance(masks_path, (pathlib.Path, str))
|
| 590 |
+
):
|
| 591 |
+
raise ValueError(
|
| 592 |
+
"The path to the directory containing the mask PNG files should be provided as a"
|
| 593 |
+
f" `pathlib.Path` or string object, but is {type(masks_path)} instead."
|
| 594 |
+
)
|
| 595 |
+
|
| 596 |
+
data = {}
|
| 597 |
+
|
| 598 |
+
# Import torch if needed for tensor conversion
|
| 599 |
+
if return_tensors == "pt":
|
| 600 |
+
if not is_torch_available():
|
| 601 |
+
raise ImportError("PyTorch is required for tensor conversion.")
|
| 602 |
+
|
| 603 |
+
processed_images = []
|
| 604 |
+
processed_annotations = []
|
| 605 |
+
pixel_masks = [] # Initialize pixel_masks here
|
| 606 |
+
for image, annotation in zip(images, annotations if annotations is not None else [None] * len(images)):
|
| 607 |
+
# prepare (COCO annotations as a list of Dict -> DEFORMABLE_DETR target as a single Dict per image)
|
| 608 |
+
if annotations is not None:
|
| 609 |
+
annotation = self.prepare_annotation(
|
| 610 |
+
image,
|
| 611 |
+
annotation,
|
| 612 |
+
format,
|
| 613 |
+
return_segmentation_masks=return_segmentation_masks,
|
| 614 |
+
masks_path=masks_path,
|
| 615 |
+
input_data_format=ChannelDimension.FIRST,
|
| 616 |
+
)
|
| 617 |
+
|
| 618 |
+
if do_resize:
|
| 619 |
+
resized_image = self.resize(image, size=size, resample=resample)
|
| 620 |
+
if annotations is not None:
|
| 621 |
+
annotation = self.resize_annotation(
|
| 622 |
+
annotation,
|
| 623 |
+
orig_size=get_image_size(image, channel_dim=ChannelDimension.FIRST),
|
| 624 |
+
target_size=get_image_size(resized_image, channel_dim=ChannelDimension.FIRST),
|
| 625 |
+
)
|
| 626 |
+
image = resized_image
|
| 627 |
+
|
| 628 |
+
if do_rescale:
|
| 629 |
+
image = self.rescale(image, rescale_factor)
|
| 630 |
+
if do_normalize:
|
| 631 |
+
image = self.normalize(image, image_mean, image_std)
|
| 632 |
+
|
| 633 |
+
if do_convert_annotations and annotations is not None:
|
| 634 |
+
annotation = self.normalize_annotation(annotation, get_image_size(image, ChannelDimension.FIRST))
|
| 635 |
+
|
| 636 |
+
processed_images.append(image)
|
| 637 |
+
processed_annotations.append(annotation)
|
| 638 |
+
images = processed_images
|
| 639 |
+
annotations = processed_annotations if annotations is not None else None
|
| 640 |
+
|
| 641 |
+
if do_pad:
|
| 642 |
+
# depends on all resized image shapes so we need another loop
|
| 643 |
+
if pad_size is not None:
|
| 644 |
+
padded_size = (pad_size.height, pad_size.width)
|
| 645 |
+
else:
|
| 646 |
+
padded_size = get_max_height_width(images, input_data_format=ChannelDimension.FIRST)
|
| 647 |
+
|
| 648 |
+
padded_images = []
|
| 649 |
+
padded_annotations = []
|
| 650 |
+
for image, annotation in zip(images, annotations if annotations is not None else [None] * len(images)):
|
| 651 |
+
# Pads images and returns their mask: {'pixel_values': ..., 'pixel_mask': ...}
|
| 652 |
+
image_height, image_width = get_image_size(image, channel_dim=ChannelDimension.FIRST)
|
| 653 |
+
if padded_size == (image_height, image_width):
|
| 654 |
+
padded_images.append(image)
|
| 655 |
+
pixel_masks.append(np.ones(padded_size, dtype=np.int64))
|
| 656 |
+
padded_annotations.append(annotation)
|
| 657 |
+
continue
|
| 658 |
+
image, pixel_mask, annotation = self.pad(
|
| 659 |
+
image, padded_size, annotation=annotation, update_bboxes=do_convert_annotations
|
| 660 |
+
)
|
| 661 |
+
padded_images.append(image)
|
| 662 |
+
padded_annotations.append(annotation)
|
| 663 |
+
pixel_masks.append(pixel_mask)
|
| 664 |
+
images = padded_images
|
| 665 |
+
annotations = padded_annotations if annotations is not None else None
|
| 666 |
+
data.update({"pixel_mask": pixel_masks})
|
| 667 |
+
|
| 668 |
+
data.update({"pixel_values": images})
|
| 669 |
+
encoded_inputs = BatchFeature(data, tensor_type=return_tensors)
|
| 670 |
+
if annotations is not None:
|
| 671 |
+
encoded_inputs["labels"] = [
|
| 672 |
+
BatchFeature(annotation, tensor_type=return_tensors) for annotation in annotations
|
| 673 |
+
]
|
| 674 |
+
return encoded_inputs
|
| 675 |
+
|
| 676 |
+
@requires(backends=("torch",))
|
| 677 |
+
def post_process_object_detection(
|
| 678 |
+
self, outputs, threshold: float = 0.5, target_sizes: TensorType | list[tuple] = None, top_k: int = 100
|
| 679 |
+
):
|
| 680 |
+
"""
|
| 681 |
+
Converts the raw output of [`DeformableDetrForObjectDetection`] into final bounding boxes in (top_left_x,
|
| 682 |
+
top_left_y, bottom_right_x, bottom_right_y) format. Only supports PyTorch.
|
| 683 |
+
|
| 684 |
+
Args:
|
| 685 |
+
outputs ([`DetrObjectDetectionOutput`]):
|
| 686 |
+
Raw outputs of the model.
|
| 687 |
+
threshold (`float`, *optional*):
|
| 688 |
+
Score threshold to keep object detection predictions.
|
| 689 |
+
target_sizes (`torch.Tensor` or `list[tuple[int, int]]`, *optional*):
|
| 690 |
+
Tensor of shape `(batch_size, 2)` or list of tuples (`tuple[int, int]`) containing the target size
|
| 691 |
+
(height, width) of each image in the batch. If left to None, predictions will not be resized.
|
| 692 |
+
top_k (`int`, *optional*, defaults to 100):
|
| 693 |
+
Keep only top k bounding boxes before filtering by thresholding.
|
| 694 |
+
|
| 695 |
+
Returns:
|
| 696 |
+
`list[Dict]`: A list of dictionaries, each dictionary containing the scores, labels and boxes for an image
|
| 697 |
+
in the batch as predicted by the model.
|
| 698 |
+
"""
|
| 699 |
+
requires_backends(self, ["torch"])
|
| 700 |
+
out_logits, out_bbox = outputs.logits, outputs.pred_boxes
|
| 701 |
+
|
| 702 |
+
if target_sizes is not None:
|
| 703 |
+
if len(out_logits) != len(target_sizes):
|
| 704 |
+
raise ValueError(
|
| 705 |
+
"Make sure that you pass in as many target sizes as the batch dimension of the logits"
|
| 706 |
+
)
|
| 707 |
+
|
| 708 |
+
prob = out_logits.sigmoid()
|
| 709 |
+
prob = prob.view(out_logits.shape[0], -1)
|
| 710 |
+
k_value = min(top_k, prob.size(1))
|
| 711 |
+
topk_values, topk_indexes = torch.topk(prob, k_value, dim=1)
|
| 712 |
+
scores = topk_values
|
| 713 |
+
topk_boxes = torch.div(topk_indexes, out_logits.shape[2], rounding_mode="floor")
|
| 714 |
+
labels = topk_indexes % out_logits.shape[2]
|
| 715 |
+
boxes = center_to_corners_format(out_bbox)
|
| 716 |
+
boxes = torch.gather(boxes, 1, topk_boxes.unsqueeze(-1).repeat(1, 1, 4))
|
| 717 |
+
|
| 718 |
+
# and from relative [0, 1] to absolute [0, height] coordinates
|
| 719 |
+
if target_sizes is not None:
|
| 720 |
+
if isinstance(target_sizes, list):
|
| 721 |
+
img_h = torch.Tensor([i[0] for i in target_sizes])
|
| 722 |
+
img_w = torch.Tensor([i[1] for i in target_sizes])
|
| 723 |
+
else:
|
| 724 |
+
img_h, img_w = target_sizes.unbind(1)
|
| 725 |
+
scale_fct = torch.stack([img_w, img_h, img_w, img_h], dim=1).to(boxes.device)
|
| 726 |
+
boxes = boxes * scale_fct[:, None, :]
|
| 727 |
+
|
| 728 |
+
results = []
|
| 729 |
+
for s, l, b in zip(scores, labels, boxes):
|
| 730 |
+
score = s[s > threshold]
|
| 731 |
+
label = l[s > threshold]
|
| 732 |
+
box = b[s > threshold]
|
| 733 |
+
results.append({"scores": score, "labels": label, "boxes": box})
|
| 734 |
+
|
| 735 |
+
return results
|
| 736 |
+
|
| 737 |
+
|
| 738 |
+
__all__ = ["DeformableDetrImageProcessorPil"]
|
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/models/deformable_detr/modeling_deformable_detr.py
ADDED
|
@@ -0,0 +1,1711 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
|
| 2 |
+
# This file was automatically generated from src/transformers/models/deformable_detr/modular_deformable_detr.py.
|
| 3 |
+
# Do NOT edit this file manually as any edits will be overwritten by the generation of
|
| 4 |
+
# the file from the modular. If any change should be done, please apply the change to the
|
| 5 |
+
# modular_deformable_detr.py file directly. One of our CI enforces this.
|
| 6 |
+
# 🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
|
| 7 |
+
# Copyright 2022 SenseTime and The HuggingFace Inc. team. All rights reserved.
|
| 8 |
+
#
|
| 9 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 10 |
+
# you may not use this file except in compliance with the License.
|
| 11 |
+
# You may obtain a copy of the License at
|
| 12 |
+
#
|
| 13 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 14 |
+
#
|
| 15 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 16 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 17 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 18 |
+
# See the License for the specific language governing permissions and
|
| 19 |
+
# limitations under the License.
|
| 20 |
+
import math
|
| 21 |
+
import warnings
|
| 22 |
+
from collections.abc import Callable
|
| 23 |
+
from dataclasses import dataclass
|
| 24 |
+
|
| 25 |
+
import torch
|
| 26 |
+
import torch.nn as nn
|
| 27 |
+
import torch.nn.functional as F
|
| 28 |
+
from torch import Tensor
|
| 29 |
+
|
| 30 |
+
from ... import initialization as init
|
| 31 |
+
from ...activations import ACT2FN
|
| 32 |
+
from ...backbone_utils import load_backbone
|
| 33 |
+
from ...integrations import use_kernel_forward_from_hub
|
| 34 |
+
from ...modeling_layers import GradientCheckpointingLayer
|
| 35 |
+
from ...modeling_outputs import BaseModelOutput, BaseModelOutputWithCrossAttentions
|
| 36 |
+
from ...modeling_utils import ALL_ATTENTION_FUNCTIONS, PreTrainedModel
|
| 37 |
+
from ...processing_utils import Unpack
|
| 38 |
+
from ...pytorch_utils import compile_compatible_method_lru_cache
|
| 39 |
+
from ...utils import ModelOutput, TransformersKwargs, auto_docstring, torch_compilable_check
|
| 40 |
+
from ...utils.generic import can_return_tuple, merge_with_config_defaults
|
| 41 |
+
from ...utils.output_capturing import OutputRecorder, capture_outputs
|
| 42 |
+
from .configuration_deformable_detr import DeformableDetrConfig
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
@auto_docstring(
|
| 46 |
+
custom_intro="""
|
| 47 |
+
Base class for outputs of the DEFORMABLE_DETR decoder. This class adds one attribute to BaseModelOutputWithCrossAttentions,
|
| 48 |
+
namely an optional stack of intermediate decoder activations, i.e. the output of each decoder layer, each of them
|
| 49 |
+
gone through a layernorm. This is useful when training the model with auxiliary decoding losses.
|
| 50 |
+
"""
|
| 51 |
+
)
|
| 52 |
+
@dataclass
|
| 53 |
+
class DeformableDetrDecoderOutput(BaseModelOutputWithCrossAttentions):
|
| 54 |
+
r"""
|
| 55 |
+
cross_attentions (`tuple(torch.FloatTensor)`, *optional*, returned when `output_attentions=True` and `config.add_cross_attention=True` is passed or when `config.output_attentions=True`):
|
| 56 |
+
Tuple of `torch.FloatTensor` (one for each layer) of shape `(batch_size, num_heads, sequence_length,
|
| 57 |
+
sequence_length)`. Attentions weights of the decoder's cross-attention layer, after the attention softmax,
|
| 58 |
+
used to compute the weighted average in the cross-attention heads.
|
| 59 |
+
intermediate_hidden_states (`torch.FloatTensor` of shape `(config.decoder_layers, batch_size, num_queries, hidden_size)`, *optional*, returned when `config.auxiliary_loss=True`):
|
| 60 |
+
Intermediate decoder activations, i.e. the output of each decoder layer, each of them gone through a
|
| 61 |
+
layernorm.
|
| 62 |
+
intermediate_reference_points (`torch.FloatTensor` of shape `(batch_size, config.decoder_layers, sequence_length, hidden_size)`):
|
| 63 |
+
Stacked intermediate reference points (reference points of each layer of the decoder).
|
| 64 |
+
"""
|
| 65 |
+
|
| 66 |
+
intermediate_hidden_states: torch.FloatTensor | None = None
|
| 67 |
+
|
| 68 |
+
intermediate_reference_points: torch.FloatTensor | None = None
|
| 69 |
+
|
| 70 |
+
|
| 71 |
+
@auto_docstring(
|
| 72 |
+
custom_intro="""
|
| 73 |
+
Base class for outputs of the Deformable DETR encoder-decoder model.
|
| 74 |
+
"""
|
| 75 |
+
)
|
| 76 |
+
@dataclass
|
| 77 |
+
class DeformableDetrModelOutput(ModelOutput):
|
| 78 |
+
r"""
|
| 79 |
+
init_reference_points (`torch.FloatTensor` of shape `(batch_size, num_queries, 4)`):
|
| 80 |
+
Initial reference points sent through the Transformer decoder.
|
| 81 |
+
last_hidden_state (`torch.FloatTensor` of shape `(batch_size, num_queries, hidden_size)`):
|
| 82 |
+
Sequence of hidden-states at the output of the last layer of the decoder of the model.
|
| 83 |
+
intermediate_hidden_states (`torch.FloatTensor` of shape `(batch_size, config.decoder_layers, num_queries, hidden_size)`):
|
| 84 |
+
Stacked intermediate hidden states (output of each layer of the decoder).
|
| 85 |
+
intermediate_reference_points (`torch.FloatTensor` of shape `(batch_size, config.decoder_layers, num_queries, 4)`):
|
| 86 |
+
Stacked intermediate reference points (reference points of each layer of the decoder).
|
| 87 |
+
enc_outputs_class (`torch.FloatTensor` of shape `(batch_size, sequence_length, config.num_labels)`, *optional*, returned when `config.with_box_refine=True` and `config.two_stage=True`):
|
| 88 |
+
Predicted bounding boxes scores where the top `config.two_stage_num_proposals` scoring bounding boxes are
|
| 89 |
+
picked as region proposals in the first stage. Output of bounding box binary classification (i.e.
|
| 90 |
+
foreground and background).
|
| 91 |
+
enc_outputs_coord_logits (`torch.FloatTensor` of shape `(batch_size, sequence_length, 4)`, *optional*, returned when `config.with_box_refine=True` and `config.two_stage=True`):
|
| 92 |
+
Logits of predicted bounding boxes coordinates in the first stage.
|
| 93 |
+
"""
|
| 94 |
+
|
| 95 |
+
init_reference_points: torch.FloatTensor | None = None
|
| 96 |
+
last_hidden_state: torch.FloatTensor | None = None
|
| 97 |
+
intermediate_hidden_states: torch.FloatTensor | None = None
|
| 98 |
+
intermediate_reference_points: torch.FloatTensor | None = None
|
| 99 |
+
decoder_hidden_states: tuple[torch.FloatTensor] | None = None
|
| 100 |
+
decoder_attentions: tuple[torch.FloatTensor] | None = None
|
| 101 |
+
cross_attentions: tuple[torch.FloatTensor] | None = None
|
| 102 |
+
encoder_last_hidden_state: torch.FloatTensor | None = None
|
| 103 |
+
encoder_hidden_states: tuple[torch.FloatTensor] | None = None
|
| 104 |
+
encoder_attentions: tuple[torch.FloatTensor] | None = None
|
| 105 |
+
enc_outputs_class: torch.FloatTensor | None = None
|
| 106 |
+
enc_outputs_coord_logits: torch.FloatTensor | None = None
|
| 107 |
+
|
| 108 |
+
|
| 109 |
+
@auto_docstring(
|
| 110 |
+
custom_intro="""
|
| 111 |
+
Output type of [`DeformableDetrForObjectDetection`].
|
| 112 |
+
"""
|
| 113 |
+
)
|
| 114 |
+
@dataclass
|
| 115 |
+
class DeformableDetrObjectDetectionOutput(ModelOutput):
|
| 116 |
+
r"""
|
| 117 |
+
loss (`torch.FloatTensor` of shape `(1,)`, *optional*, returned when `labels` are provided)):
|
| 118 |
+
Total loss as a linear combination of a negative log-likehood (cross-entropy) for class prediction and a
|
| 119 |
+
bounding box loss. The latter is defined as a linear combination of the L1 loss and the generalized
|
| 120 |
+
scale-invariant IoU loss.
|
| 121 |
+
loss_dict (`Dict`, *optional*):
|
| 122 |
+
A dictionary containing the individual losses. Useful for logging.
|
| 123 |
+
logits (`torch.FloatTensor` of shape `(batch_size, num_queries, num_classes + 1)`):
|
| 124 |
+
Classification logits (including no-object) for all queries.
|
| 125 |
+
pred_boxes (`torch.FloatTensor` of shape `(batch_size, num_queries, 4)`):
|
| 126 |
+
Normalized boxes coordinates for all queries, represented as (center_x, center_y, width, height). These
|
| 127 |
+
values are normalized in [0, 1], relative to the size of each individual image in the batch (disregarding
|
| 128 |
+
possible padding). You can use [`~DeformableDetrProcessor.post_process_object_detection`] to retrieve the
|
| 129 |
+
unnormalized bounding boxes.
|
| 130 |
+
auxiliary_outputs (`list[Dict]`, *optional*):
|
| 131 |
+
Optional, only returned when auxiliary losses are activated (i.e. `config.auxiliary_loss` is set to `True`)
|
| 132 |
+
and labels are provided. It is a list of dictionaries containing the two above keys (`logits` and
|
| 133 |
+
`pred_boxes`) for each decoder layer.
|
| 134 |
+
last_hidden_state (`torch.FloatTensor` of shape `(batch_size, num_queries, hidden_size)`, *optional*):
|
| 135 |
+
Sequence of hidden-states at the output of the last layer of the decoder of the model.
|
| 136 |
+
init_reference_points (`torch.FloatTensor` of shape `(batch_size, num_queries, 4)`):
|
| 137 |
+
Initial reference points sent through the Transformer decoder.
|
| 138 |
+
intermediate_hidden_states (`torch.FloatTensor` of shape `(batch_size, config.decoder_layers, num_queries, hidden_size)`):
|
| 139 |
+
Stacked intermediate hidden states (output of each layer of the decoder).
|
| 140 |
+
intermediate_reference_points (`torch.FloatTensor` of shape `(batch_size, config.decoder_layers, num_queries, 4)`):
|
| 141 |
+
Stacked intermediate reference points (reference points of each layer of the decoder).
|
| 142 |
+
enc_outputs_class (`torch.FloatTensor` of shape `(batch_size, sequence_length, config.num_labels)`, *optional*, returned when `config.with_box_refine=True` and `config.two_stage=True`):
|
| 143 |
+
Predicted bounding boxes scores where the top `config.two_stage_num_proposals` scoring bounding boxes are
|
| 144 |
+
picked as region proposals in the first stage. Output of bounding box binary classification (i.e.
|
| 145 |
+
foreground and background).
|
| 146 |
+
enc_outputs_coord_logits (`torch.FloatTensor` of shape `(batch_size, sequence_length, 4)`, *optional*, returned when `config.with_box_refine=True` and `config.two_stage=True`):
|
| 147 |
+
Logits of predicted bounding boxes coordinates in the first stage.
|
| 148 |
+
"""
|
| 149 |
+
|
| 150 |
+
loss: torch.FloatTensor | None = None
|
| 151 |
+
loss_dict: dict | None = None
|
| 152 |
+
logits: torch.FloatTensor | None = None
|
| 153 |
+
pred_boxes: torch.FloatTensor | None = None
|
| 154 |
+
auxiliary_outputs: list[dict] | None = None
|
| 155 |
+
last_hidden_state: torch.FloatTensor | None = None
|
| 156 |
+
decoder_hidden_states: tuple[torch.FloatTensor] | None = None
|
| 157 |
+
decoder_attentions: tuple[torch.FloatTensor] | None = None
|
| 158 |
+
cross_attentions: tuple[torch.FloatTensor] | None = None
|
| 159 |
+
encoder_last_hidden_state: torch.FloatTensor | None = None
|
| 160 |
+
encoder_hidden_states: tuple[torch.FloatTensor] | None = None
|
| 161 |
+
encoder_attentions: tuple[torch.FloatTensor] | None = None
|
| 162 |
+
|
| 163 |
+
init_reference_points: torch.FloatTensor | None = None
|
| 164 |
+
intermediate_hidden_states: torch.FloatTensor | None = None
|
| 165 |
+
intermediate_reference_points: torch.FloatTensor | None = None
|
| 166 |
+
enc_outputs_class: torch.FloatTensor | None = None
|
| 167 |
+
enc_outputs_coord_logits: torch.FloatTensor | None = None
|
| 168 |
+
|
| 169 |
+
|
| 170 |
+
@use_kernel_forward_from_hub("MultiScaleDeformableAttention")
|
| 171 |
+
class MultiScaleDeformableAttention(nn.Module):
|
| 172 |
+
def forward(
|
| 173 |
+
self,
|
| 174 |
+
value: Tensor,
|
| 175 |
+
value_spatial_shapes: Tensor,
|
| 176 |
+
value_spatial_shapes_list: list[tuple],
|
| 177 |
+
level_start_index: Tensor,
|
| 178 |
+
sampling_locations: Tensor,
|
| 179 |
+
attention_weights: Tensor,
|
| 180 |
+
im2col_step: int,
|
| 181 |
+
):
|
| 182 |
+
batch_size, _, num_heads, hidden_dim = value.shape
|
| 183 |
+
_, num_queries, num_heads, num_levels, num_points, _ = sampling_locations.shape
|
| 184 |
+
value_list = value.split([height * width for height, width in value_spatial_shapes_list], dim=1)
|
| 185 |
+
sampling_grids = 2 * sampling_locations - 1
|
| 186 |
+
sampling_value_list = []
|
| 187 |
+
for level_id, (height, width) in enumerate(value_spatial_shapes_list):
|
| 188 |
+
# batch_size, height*width, num_heads, hidden_dim
|
| 189 |
+
# -> batch_size, height*width, num_heads*hidden_dim
|
| 190 |
+
# -> batch_size, num_heads*hidden_dim, height*width
|
| 191 |
+
# -> batch_size*num_heads, hidden_dim, height, width
|
| 192 |
+
value_l_ = (
|
| 193 |
+
value_list[level_id]
|
| 194 |
+
.flatten(2)
|
| 195 |
+
.transpose(1, 2)
|
| 196 |
+
.reshape(batch_size * num_heads, hidden_dim, height, width)
|
| 197 |
+
)
|
| 198 |
+
# batch_size, num_queries, num_heads, num_points, 2
|
| 199 |
+
# -> batch_size, num_heads, num_queries, num_points, 2
|
| 200 |
+
# -> batch_size*num_heads, num_queries, num_points, 2
|
| 201 |
+
sampling_grid_l_ = sampling_grids[:, :, :, level_id].transpose(1, 2).flatten(0, 1)
|
| 202 |
+
# batch_size*num_heads, hidden_dim, num_queries, num_points
|
| 203 |
+
sampling_value_l_ = nn.functional.grid_sample(
|
| 204 |
+
value_l_,
|
| 205 |
+
sampling_grid_l_,
|
| 206 |
+
mode="bilinear",
|
| 207 |
+
padding_mode="zeros",
|
| 208 |
+
align_corners=False,
|
| 209 |
+
)
|
| 210 |
+
sampling_value_list.append(sampling_value_l_)
|
| 211 |
+
# (batch_size, num_queries, num_heads, num_levels, num_points)
|
| 212 |
+
# -> (batch_size, num_heads, num_queries, num_levels, num_points)
|
| 213 |
+
# -> (batch_size, num_heads, 1, num_queries, num_levels*num_points)
|
| 214 |
+
attention_weights = attention_weights.transpose(1, 2).reshape(
|
| 215 |
+
batch_size * num_heads, 1, num_queries, num_levels * num_points
|
| 216 |
+
)
|
| 217 |
+
output = (
|
| 218 |
+
(torch.stack(sampling_value_list, dim=-2).flatten(-2) * attention_weights)
|
| 219 |
+
.sum(-1)
|
| 220 |
+
.view(batch_size, num_heads * hidden_dim, num_queries)
|
| 221 |
+
)
|
| 222 |
+
return output.transpose(1, 2).contiguous()
|
| 223 |
+
|
| 224 |
+
|
| 225 |
+
class DeformableDetrFrozenBatchNorm2d(nn.Module):
|
| 226 |
+
"""
|
| 227 |
+
BatchNorm2d where the batch statistics and the affine parameters are fixed.
|
| 228 |
+
|
| 229 |
+
Copy-paste from torchvision.misc.ops with added eps before rqsrt, without which any other models than
|
| 230 |
+
torchvision.models.resnet[18,34,50,101] produce nans.
|
| 231 |
+
"""
|
| 232 |
+
|
| 233 |
+
def __init__(self, n):
|
| 234 |
+
super().__init__()
|
| 235 |
+
self.register_buffer("weight", torch.ones(n))
|
| 236 |
+
self.register_buffer("bias", torch.zeros(n))
|
| 237 |
+
self.register_buffer("running_mean", torch.zeros(n))
|
| 238 |
+
self.register_buffer("running_var", torch.ones(n))
|
| 239 |
+
|
| 240 |
+
def _load_from_state_dict(
|
| 241 |
+
self, state_dict, prefix, local_metadata, strict, missing_keys, unexpected_keys, error_msgs
|
| 242 |
+
):
|
| 243 |
+
num_batches_tracked_key = prefix + "num_batches_tracked"
|
| 244 |
+
if num_batches_tracked_key in state_dict:
|
| 245 |
+
del state_dict[num_batches_tracked_key]
|
| 246 |
+
|
| 247 |
+
super()._load_from_state_dict(
|
| 248 |
+
state_dict, prefix, local_metadata, strict, missing_keys, unexpected_keys, error_msgs
|
| 249 |
+
)
|
| 250 |
+
|
| 251 |
+
def forward(self, x):
|
| 252 |
+
# move reshapes to the beginning
|
| 253 |
+
# to make it user-friendly
|
| 254 |
+
weight = self.weight.reshape(1, -1, 1, 1)
|
| 255 |
+
bias = self.bias.reshape(1, -1, 1, 1)
|
| 256 |
+
running_var = self.running_var.reshape(1, -1, 1, 1)
|
| 257 |
+
running_mean = self.running_mean.reshape(1, -1, 1, 1)
|
| 258 |
+
epsilon = 1e-5
|
| 259 |
+
scale = weight * (running_var + epsilon).rsqrt()
|
| 260 |
+
bias = bias - running_mean * scale
|
| 261 |
+
return x * scale + bias
|
| 262 |
+
|
| 263 |
+
|
| 264 |
+
def replace_batch_norm(model):
|
| 265 |
+
r"""
|
| 266 |
+
Recursively replace all `torch.nn.BatchNorm2d` with `DeformableDetrFrozenBatchNorm2d`.
|
| 267 |
+
|
| 268 |
+
Args:
|
| 269 |
+
model (torch.nn.Module):
|
| 270 |
+
input model
|
| 271 |
+
"""
|
| 272 |
+
for name, module in model.named_children():
|
| 273 |
+
if isinstance(module, nn.BatchNorm2d):
|
| 274 |
+
new_module = DeformableDetrFrozenBatchNorm2d(module.num_features)
|
| 275 |
+
|
| 276 |
+
if module.weight.device != torch.device("meta"):
|
| 277 |
+
new_module.weight.copy_(module.weight)
|
| 278 |
+
new_module.bias.copy_(module.bias)
|
| 279 |
+
new_module.running_mean.copy_(module.running_mean)
|
| 280 |
+
new_module.running_var.copy_(module.running_var)
|
| 281 |
+
|
| 282 |
+
model._modules[name] = new_module
|
| 283 |
+
|
| 284 |
+
if len(list(module.children())) > 0:
|
| 285 |
+
replace_batch_norm(module)
|
| 286 |
+
|
| 287 |
+
|
| 288 |
+
class DeformableDetrConvEncoder(nn.Module):
|
| 289 |
+
"""
|
| 290 |
+
Convolutional backbone, using either the AutoBackbone API or one from the timm library.
|
| 291 |
+
|
| 292 |
+
nn.BatchNorm2d layers are replaced by DeformableDetrFrozenBatchNorm2d as defined above.
|
| 293 |
+
|
| 294 |
+
"""
|
| 295 |
+
|
| 296 |
+
def __init__(self, config):
|
| 297 |
+
super().__init__()
|
| 298 |
+
|
| 299 |
+
self.config = config
|
| 300 |
+
|
| 301 |
+
backbone = load_backbone(config)
|
| 302 |
+
self.intermediate_channel_sizes = backbone.channels
|
| 303 |
+
|
| 304 |
+
# replace batch norm by frozen batch norm
|
| 305 |
+
with torch.no_grad():
|
| 306 |
+
replace_batch_norm(backbone)
|
| 307 |
+
|
| 308 |
+
# We used to load with timm library directly instead of the AutoBackbone API
|
| 309 |
+
# so we need to unwrap the `backbone._backbone` module to load weights without mismatch
|
| 310 |
+
is_timm_model = False
|
| 311 |
+
if hasattr(backbone, "_backbone"):
|
| 312 |
+
backbone = backbone._backbone
|
| 313 |
+
is_timm_model = True
|
| 314 |
+
self.model = backbone
|
| 315 |
+
|
| 316 |
+
backbone_model_type = config.backbone_config.model_type
|
| 317 |
+
if "resnet" in backbone_model_type:
|
| 318 |
+
for name, parameter in self.model.named_parameters():
|
| 319 |
+
if is_timm_model:
|
| 320 |
+
if "layer2" not in name and "layer3" not in name and "layer4" not in name:
|
| 321 |
+
parameter.requires_grad_(False)
|
| 322 |
+
else:
|
| 323 |
+
if "stage.1" not in name and "stage.2" not in name and "stage.3" not in name:
|
| 324 |
+
parameter.requires_grad_(False)
|
| 325 |
+
|
| 326 |
+
def forward(self, pixel_values: torch.Tensor, pixel_mask: torch.Tensor):
|
| 327 |
+
# send pixel_values through the model to get list of feature maps
|
| 328 |
+
features = self.model(pixel_values)
|
| 329 |
+
if isinstance(features, dict):
|
| 330 |
+
features = features.feature_maps
|
| 331 |
+
|
| 332 |
+
out = []
|
| 333 |
+
for feature_map in features:
|
| 334 |
+
# downsample pixel_mask to match shape of corresponding feature_map
|
| 335 |
+
mask = nn.functional.interpolate(pixel_mask[None].float(), size=feature_map.shape[-2:]).to(torch.bool)[0]
|
| 336 |
+
out.append((feature_map, mask))
|
| 337 |
+
return out
|
| 338 |
+
|
| 339 |
+
|
| 340 |
+
class DeformableDetrSinePositionEmbedding(nn.Module):
|
| 341 |
+
"""
|
| 342 |
+
This is a more standard version of the position embedding, very similar to the one used by the Attention is all you
|
| 343 |
+
need paper, generalized to work on images.
|
| 344 |
+
"""
|
| 345 |
+
|
| 346 |
+
def __init__(
|
| 347 |
+
self,
|
| 348 |
+
num_position_features: int = 64,
|
| 349 |
+
temperature: int = 10000,
|
| 350 |
+
normalize: bool = False,
|
| 351 |
+
scale: float | None = None,
|
| 352 |
+
):
|
| 353 |
+
super().__init__()
|
| 354 |
+
if scale is not None and normalize is False:
|
| 355 |
+
raise ValueError("normalize should be True if scale is passed")
|
| 356 |
+
self.num_position_features = num_position_features
|
| 357 |
+
self.temperature = temperature
|
| 358 |
+
self.normalize = normalize
|
| 359 |
+
self.scale = 2 * math.pi if scale is None else scale
|
| 360 |
+
|
| 361 |
+
@staticmethod
|
| 362 |
+
@compile_compatible_method_lru_cache(maxsize=1)
|
| 363 |
+
def build_sine_position_embedding(
|
| 364 |
+
shape: torch.Size,
|
| 365 |
+
device: torch.device | str,
|
| 366 |
+
dtype: torch.dtype,
|
| 367 |
+
num_position_features: int,
|
| 368 |
+
normalize: bool = False,
|
| 369 |
+
scale: float | None = None,
|
| 370 |
+
temperature: int = 10000,
|
| 371 |
+
mask: torch.Tensor | None = None,
|
| 372 |
+
) -> torch.Tensor:
|
| 373 |
+
if mask is None:
|
| 374 |
+
mask = torch.ones((shape[0], shape[2], shape[3]), device=device, dtype=torch.bool)
|
| 375 |
+
y_embed = mask.cumsum(1, dtype=dtype)
|
| 376 |
+
x_embed = mask.cumsum(2, dtype=dtype)
|
| 377 |
+
if normalize:
|
| 378 |
+
eps = 1e-6
|
| 379 |
+
y_embed = (y_embed - 0.5) / (y_embed[:, -1:, :] + eps) * scale
|
| 380 |
+
x_embed = (x_embed - 0.5) / (x_embed[:, :, -1:] + eps) * scale
|
| 381 |
+
|
| 382 |
+
dim_t = torch.arange(num_position_features, dtype=torch.int64, device=device).to(dtype)
|
| 383 |
+
dim_t = temperature ** (2 * torch.div(dim_t, 2, rounding_mode="floor") / num_position_features)
|
| 384 |
+
|
| 385 |
+
pos_x = x_embed[:, :, :, None] / dim_t
|
| 386 |
+
pos_y = y_embed[:, :, :, None] / dim_t
|
| 387 |
+
pos_x = torch.stack((pos_x[:, :, :, 0::2].sin(), pos_x[:, :, :, 1::2].cos()), dim=4).flatten(3)
|
| 388 |
+
pos_y = torch.stack((pos_y[:, :, :, 0::2].sin(), pos_y[:, :, :, 1::2].cos()), dim=4).flatten(3)
|
| 389 |
+
pos = torch.cat((pos_y, pos_x), dim=3).permute(0, 3, 1, 2)
|
| 390 |
+
return pos
|
| 391 |
+
|
| 392 |
+
def forward(
|
| 393 |
+
self,
|
| 394 |
+
shape: torch.Size,
|
| 395 |
+
device: torch.device | str,
|
| 396 |
+
dtype: torch.dtype,
|
| 397 |
+
mask: torch.Tensor | None = None,
|
| 398 |
+
) -> torch.Tensor:
|
| 399 |
+
return self.build_sine_position_embedding(
|
| 400 |
+
shape, device, dtype, self.num_position_features, self.normalize, self.scale, self.temperature, mask
|
| 401 |
+
)
|
| 402 |
+
|
| 403 |
+
|
| 404 |
+
class DeformableDetrLearnedPositionEmbedding(nn.Module):
|
| 405 |
+
"""
|
| 406 |
+
This module learns positional embeddings up to a fixed maximum size.
|
| 407 |
+
"""
|
| 408 |
+
|
| 409 |
+
def __init__(self, embedding_dim=256):
|
| 410 |
+
super().__init__()
|
| 411 |
+
self.row_embeddings = nn.Embedding(50, embedding_dim)
|
| 412 |
+
self.column_embeddings = nn.Embedding(50, embedding_dim)
|
| 413 |
+
|
| 414 |
+
@compile_compatible_method_lru_cache(maxsize=1)
|
| 415 |
+
def forward(
|
| 416 |
+
self,
|
| 417 |
+
shape: torch.Size,
|
| 418 |
+
device: torch.device | str,
|
| 419 |
+
dtype: torch.dtype,
|
| 420 |
+
mask: torch.Tensor | None = None,
|
| 421 |
+
):
|
| 422 |
+
height, width = shape[-2:]
|
| 423 |
+
width_values = torch.arange(width, device=device)
|
| 424 |
+
height_values = torch.arange(height, device=device)
|
| 425 |
+
x_emb = self.column_embeddings(width_values)
|
| 426 |
+
y_emb = self.row_embeddings(height_values)
|
| 427 |
+
pos = torch.cat([x_emb.unsqueeze(0).repeat(height, 1, 1), y_emb.unsqueeze(1).repeat(1, width, 1)], dim=-1)
|
| 428 |
+
pos = pos.permute(2, 0, 1)
|
| 429 |
+
pos = pos.unsqueeze(0)
|
| 430 |
+
pos = pos.repeat(shape[0], 1, 1, 1)
|
| 431 |
+
return pos
|
| 432 |
+
|
| 433 |
+
|
| 434 |
+
def eager_attention_forward(
|
| 435 |
+
module: nn.Module,
|
| 436 |
+
query: torch.Tensor,
|
| 437 |
+
key: torch.Tensor,
|
| 438 |
+
value: torch.Tensor,
|
| 439 |
+
attention_mask: torch.Tensor | None,
|
| 440 |
+
scaling: float | None = None,
|
| 441 |
+
dropout: float = 0.0,
|
| 442 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 443 |
+
):
|
| 444 |
+
if scaling is None:
|
| 445 |
+
scaling = query.size(-1) ** -0.5
|
| 446 |
+
|
| 447 |
+
# Take the dot product between "query" and "key" to get the raw attention scores.
|
| 448 |
+
attn_weights = torch.matmul(query, key.transpose(2, 3)) * scaling
|
| 449 |
+
|
| 450 |
+
if attention_mask is not None:
|
| 451 |
+
attn_weights = attn_weights + attention_mask
|
| 452 |
+
|
| 453 |
+
attn_weights = nn.functional.softmax(attn_weights, dim=-1)
|
| 454 |
+
attn_weights = nn.functional.dropout(attn_weights, p=dropout, training=module.training)
|
| 455 |
+
|
| 456 |
+
attn_output = torch.matmul(attn_weights, value)
|
| 457 |
+
attn_output = attn_output.transpose(1, 2).contiguous()
|
| 458 |
+
|
| 459 |
+
return attn_output, attn_weights
|
| 460 |
+
|
| 461 |
+
|
| 462 |
+
class DeformableDetrSelfAttention(nn.Module):
|
| 463 |
+
"""
|
| 464 |
+
Multi-headed self-attention from 'Attention Is All You Need' paper.
|
| 465 |
+
|
| 466 |
+
In DEFORMABLE_DETR, position embeddings are added to both queries and keys (but not values) in self-attention.
|
| 467 |
+
"""
|
| 468 |
+
|
| 469 |
+
def __init__(
|
| 470 |
+
self,
|
| 471 |
+
config: DeformableDetrConfig,
|
| 472 |
+
hidden_size: int,
|
| 473 |
+
num_attention_heads: int,
|
| 474 |
+
dropout: float = 0.0,
|
| 475 |
+
bias: bool = True,
|
| 476 |
+
):
|
| 477 |
+
super().__init__()
|
| 478 |
+
self.config = config
|
| 479 |
+
self.head_dim = hidden_size // num_attention_heads
|
| 480 |
+
self.scaling = self.head_dim**-0.5
|
| 481 |
+
self.attention_dropout = dropout
|
| 482 |
+
self.is_causal = False
|
| 483 |
+
|
| 484 |
+
self.k_proj = nn.Linear(hidden_size, hidden_size, bias=bias)
|
| 485 |
+
self.v_proj = nn.Linear(hidden_size, hidden_size, bias=bias)
|
| 486 |
+
self.q_proj = nn.Linear(hidden_size, hidden_size, bias=bias)
|
| 487 |
+
self.o_proj = nn.Linear(hidden_size, hidden_size, bias=bias)
|
| 488 |
+
|
| 489 |
+
def forward(
|
| 490 |
+
self,
|
| 491 |
+
hidden_states: torch.Tensor,
|
| 492 |
+
attention_mask: torch.Tensor | None = None,
|
| 493 |
+
position_embeddings: torch.Tensor | None = None,
|
| 494 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 495 |
+
) -> tuple[torch.Tensor, torch.Tensor]:
|
| 496 |
+
"""
|
| 497 |
+
Position embeddings are added to both queries and keys (but not values).
|
| 498 |
+
"""
|
| 499 |
+
input_shape = hidden_states.shape[:-1]
|
| 500 |
+
hidden_shape = (*input_shape, -1, self.head_dim)
|
| 501 |
+
|
| 502 |
+
query_key_input = hidden_states + position_embeddings if position_embeddings is not None else hidden_states
|
| 503 |
+
|
| 504 |
+
query_states = self.q_proj(query_key_input).view(hidden_shape).transpose(1, 2)
|
| 505 |
+
key_states = self.k_proj(query_key_input).view(hidden_shape).transpose(1, 2)
|
| 506 |
+
value_states = self.v_proj(hidden_states).view(hidden_shape).transpose(1, 2)
|
| 507 |
+
|
| 508 |
+
attention_interface: Callable = ALL_ATTENTION_FUNCTIONS.get_interface(
|
| 509 |
+
self.config._attn_implementation, eager_attention_forward
|
| 510 |
+
)
|
| 511 |
+
|
| 512 |
+
attn_output, attn_weights = attention_interface(
|
| 513 |
+
self,
|
| 514 |
+
query_states,
|
| 515 |
+
key_states,
|
| 516 |
+
value_states,
|
| 517 |
+
attention_mask,
|
| 518 |
+
dropout=0.0 if not self.training else self.attention_dropout,
|
| 519 |
+
scaling=self.scaling,
|
| 520 |
+
**kwargs,
|
| 521 |
+
)
|
| 522 |
+
|
| 523 |
+
attn_output = attn_output.reshape(*input_shape, -1).contiguous()
|
| 524 |
+
attn_output = self.o_proj(attn_output)
|
| 525 |
+
return attn_output, attn_weights
|
| 526 |
+
|
| 527 |
+
|
| 528 |
+
class DeformableDetrMultiscaleDeformableAttention(nn.Module):
|
| 529 |
+
"""
|
| 530 |
+
Multiscale deformable attention as proposed in Deformable DETR.
|
| 531 |
+
"""
|
| 532 |
+
|
| 533 |
+
def __init__(self, config: DeformableDetrConfig, num_heads: int, n_points: int):
|
| 534 |
+
super().__init__()
|
| 535 |
+
|
| 536 |
+
self.attn = MultiScaleDeformableAttention()
|
| 537 |
+
|
| 538 |
+
if config.d_model % num_heads != 0:
|
| 539 |
+
raise ValueError(
|
| 540 |
+
f"embed_dim (d_model) must be divisible by num_heads, but got {config.d_model} and {num_heads}"
|
| 541 |
+
)
|
| 542 |
+
dim_per_head = config.d_model // num_heads
|
| 543 |
+
# check if dim_per_head is power of 2
|
| 544 |
+
if not ((dim_per_head & (dim_per_head - 1) == 0) and dim_per_head != 0):
|
| 545 |
+
warnings.warn(
|
| 546 |
+
"You'd better set embed_dim (d_model) in DeformableDetrMultiscaleDeformableAttention to make the"
|
| 547 |
+
" dimension of each attention head a power of 2 which is more efficient in the authors' CUDA"
|
| 548 |
+
" implementation."
|
| 549 |
+
)
|
| 550 |
+
|
| 551 |
+
self.im2col_step = 64
|
| 552 |
+
|
| 553 |
+
self.d_model = config.d_model
|
| 554 |
+
self.n_levels = config.num_feature_levels
|
| 555 |
+
self.n_heads = num_heads
|
| 556 |
+
self.n_points = n_points
|
| 557 |
+
|
| 558 |
+
self.sampling_offsets = nn.Linear(config.d_model, num_heads * self.n_levels * n_points * 2)
|
| 559 |
+
self.attention_weights = nn.Linear(config.d_model, num_heads * self.n_levels * n_points)
|
| 560 |
+
self.value_proj = nn.Linear(config.d_model, config.d_model)
|
| 561 |
+
self.output_proj = nn.Linear(config.d_model, config.d_model)
|
| 562 |
+
|
| 563 |
+
self.disable_custom_kernels = config.disable_custom_kernels
|
| 564 |
+
|
| 565 |
+
def forward(
|
| 566 |
+
self,
|
| 567 |
+
hidden_states: torch.Tensor,
|
| 568 |
+
attention_mask: torch.Tensor | None = None,
|
| 569 |
+
encoder_hidden_states=None,
|
| 570 |
+
encoder_attention_mask=None,
|
| 571 |
+
position_embeddings: torch.Tensor | None = None,
|
| 572 |
+
reference_points=None,
|
| 573 |
+
spatial_shapes=None,
|
| 574 |
+
spatial_shapes_list=None,
|
| 575 |
+
level_start_index=None,
|
| 576 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 577 |
+
) -> tuple[torch.Tensor, torch.Tensor]:
|
| 578 |
+
# add position embeddings to the hidden states before projecting to queries and keys
|
| 579 |
+
if position_embeddings is not None:
|
| 580 |
+
hidden_states = hidden_states + position_embeddings
|
| 581 |
+
|
| 582 |
+
batch_size, num_queries, _ = hidden_states.shape
|
| 583 |
+
batch_size, sequence_length, _ = encoder_hidden_states.shape
|
| 584 |
+
total_elements = sum(height * width for height, width in spatial_shapes_list)
|
| 585 |
+
torch_compilable_check(
|
| 586 |
+
total_elements == sequence_length,
|
| 587 |
+
"Make sure to align the spatial shapes with the sequence length of the encoder hidden states",
|
| 588 |
+
)
|
| 589 |
+
|
| 590 |
+
value = self.value_proj(encoder_hidden_states)
|
| 591 |
+
if attention_mask is not None:
|
| 592 |
+
# we invert the attention_mask
|
| 593 |
+
value = value.masked_fill(~attention_mask[..., None], float(0))
|
| 594 |
+
value = value.view(batch_size, sequence_length, self.n_heads, self.d_model // self.n_heads)
|
| 595 |
+
sampling_offsets = self.sampling_offsets(hidden_states).view(
|
| 596 |
+
batch_size, num_queries, self.n_heads, self.n_levels, self.n_points, 2
|
| 597 |
+
)
|
| 598 |
+
attention_weights = self.attention_weights(hidden_states).view(
|
| 599 |
+
batch_size, num_queries, self.n_heads, self.n_levels * self.n_points
|
| 600 |
+
)
|
| 601 |
+
attention_weights = F.softmax(attention_weights, -1).view(
|
| 602 |
+
batch_size, num_queries, self.n_heads, self.n_levels, self.n_points
|
| 603 |
+
)
|
| 604 |
+
# batch_size, num_queries, n_heads, n_levels, n_points, 2
|
| 605 |
+
num_coordinates = reference_points.shape[-1]
|
| 606 |
+
if num_coordinates == 2:
|
| 607 |
+
offset_normalizer = torch.stack([spatial_shapes[..., 1], spatial_shapes[..., 0]], -1)
|
| 608 |
+
sampling_locations = (
|
| 609 |
+
reference_points[:, :, None, :, None, :]
|
| 610 |
+
+ sampling_offsets / offset_normalizer[None, None, None, :, None, :]
|
| 611 |
+
)
|
| 612 |
+
elif num_coordinates == 4:
|
| 613 |
+
sampling_locations = (
|
| 614 |
+
reference_points[:, :, None, :, None, :2]
|
| 615 |
+
+ sampling_offsets / self.n_points * reference_points[:, :, None, :, None, 2:] * 0.5
|
| 616 |
+
)
|
| 617 |
+
else:
|
| 618 |
+
raise ValueError(f"Last dim of reference_points must be 2 or 4, but got {reference_points.shape[-1]}")
|
| 619 |
+
|
| 620 |
+
output = self.attn(
|
| 621 |
+
value,
|
| 622 |
+
spatial_shapes,
|
| 623 |
+
spatial_shapes_list,
|
| 624 |
+
level_start_index,
|
| 625 |
+
sampling_locations,
|
| 626 |
+
attention_weights,
|
| 627 |
+
self.im2col_step,
|
| 628 |
+
)
|
| 629 |
+
|
| 630 |
+
output = self.output_proj(output)
|
| 631 |
+
|
| 632 |
+
return output, attention_weights
|
| 633 |
+
|
| 634 |
+
|
| 635 |
+
class DeformableDetrMLP(nn.Module):
|
| 636 |
+
def __init__(self, config: DeformableDetrConfig, hidden_size: int, intermediate_size: int):
|
| 637 |
+
super().__init__()
|
| 638 |
+
self.fc1 = nn.Linear(hidden_size, intermediate_size)
|
| 639 |
+
self.fc2 = nn.Linear(intermediate_size, hidden_size)
|
| 640 |
+
self.activation_fn = ACT2FN[config.activation_function]
|
| 641 |
+
self.activation_dropout = config.activation_dropout
|
| 642 |
+
self.dropout = config.dropout
|
| 643 |
+
|
| 644 |
+
def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
|
| 645 |
+
hidden_states = self.activation_fn(self.fc1(hidden_states))
|
| 646 |
+
hidden_states = nn.functional.dropout(hidden_states, p=self.activation_dropout, training=self.training)
|
| 647 |
+
hidden_states = self.fc2(hidden_states)
|
| 648 |
+
hidden_states = nn.functional.dropout(hidden_states, p=self.dropout, training=self.training)
|
| 649 |
+
return hidden_states
|
| 650 |
+
|
| 651 |
+
|
| 652 |
+
class DeformableDetrEncoderLayer(GradientCheckpointingLayer):
|
| 653 |
+
def __init__(self, config: DeformableDetrConfig):
|
| 654 |
+
super().__init__()
|
| 655 |
+
self.hidden_size = config.d_model
|
| 656 |
+
self.self_attn = DeformableDetrMultiscaleDeformableAttention(
|
| 657 |
+
config,
|
| 658 |
+
num_heads=config.encoder_attention_heads,
|
| 659 |
+
n_points=config.encoder_n_points,
|
| 660 |
+
)
|
| 661 |
+
self.self_attn_layer_norm = nn.LayerNorm(self.hidden_size)
|
| 662 |
+
self.dropout = config.dropout
|
| 663 |
+
self.mlp = DeformableDetrMLP(config, self.hidden_size, config.encoder_ffn_dim)
|
| 664 |
+
self.final_layer_norm = nn.LayerNorm(self.hidden_size)
|
| 665 |
+
|
| 666 |
+
def forward(
|
| 667 |
+
self,
|
| 668 |
+
hidden_states: torch.Tensor,
|
| 669 |
+
attention_mask: torch.Tensor,
|
| 670 |
+
spatial_position_embeddings: torch.Tensor | None = None,
|
| 671 |
+
reference_points=None,
|
| 672 |
+
spatial_shapes=None,
|
| 673 |
+
spatial_shapes_list=None,
|
| 674 |
+
level_start_index=None,
|
| 675 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 676 |
+
) -> torch.Tensor:
|
| 677 |
+
"""
|
| 678 |
+
Args:
|
| 679 |
+
hidden_states (`torch.FloatTensor` of shape `(batch_size, sequence_length, hidden_size)`):
|
| 680 |
+
Input to the layer.
|
| 681 |
+
attention_mask (`torch.FloatTensor` of shape `(batch_size, sequence_length)`):
|
| 682 |
+
Attention mask.
|
| 683 |
+
position_embeddings (`torch.FloatTensor`, *optional*):
|
| 684 |
+
Position embeddings, to be added to `hidden_states`.
|
| 685 |
+
reference_points (`torch.FloatTensor`, *optional*):
|
| 686 |
+
Reference points.
|
| 687 |
+
spatial_shapes (`torch.LongTensor`, *optional*):
|
| 688 |
+
Spatial shapes of the backbone feature maps.
|
| 689 |
+
level_start_index (`torch.LongTensor`, *optional*):
|
| 690 |
+
Level start index.
|
| 691 |
+
"""
|
| 692 |
+
residual = hidden_states
|
| 693 |
+
hidden_states, _ = self.self_attn(
|
| 694 |
+
hidden_states=hidden_states,
|
| 695 |
+
attention_mask=attention_mask,
|
| 696 |
+
encoder_hidden_states=hidden_states,
|
| 697 |
+
encoder_attention_mask=attention_mask,
|
| 698 |
+
position_embeddings=spatial_position_embeddings,
|
| 699 |
+
reference_points=reference_points,
|
| 700 |
+
spatial_shapes=spatial_shapes,
|
| 701 |
+
spatial_shapes_list=spatial_shapes_list,
|
| 702 |
+
level_start_index=level_start_index,
|
| 703 |
+
)
|
| 704 |
+
|
| 705 |
+
hidden_states = nn.functional.dropout(hidden_states, p=self.dropout, training=self.training)
|
| 706 |
+
hidden_states = residual + hidden_states
|
| 707 |
+
hidden_states = self.self_attn_layer_norm(hidden_states)
|
| 708 |
+
|
| 709 |
+
residual = hidden_states
|
| 710 |
+
hidden_states = self.mlp(hidden_states)
|
| 711 |
+
hidden_states = residual + hidden_states
|
| 712 |
+
hidden_states = self.final_layer_norm(hidden_states)
|
| 713 |
+
|
| 714 |
+
if self.training:
|
| 715 |
+
if not torch.isfinite(hidden_states).all():
|
| 716 |
+
clamp_value = torch.finfo(hidden_states.dtype).max - 1000
|
| 717 |
+
hidden_states = torch.clamp(hidden_states, min=-clamp_value, max=clamp_value)
|
| 718 |
+
|
| 719 |
+
return hidden_states
|
| 720 |
+
|
| 721 |
+
|
| 722 |
+
class DeformableDetrDecoderLayer(GradientCheckpointingLayer):
|
| 723 |
+
def __init__(self, config: DeformableDetrConfig):
|
| 724 |
+
super().__init__()
|
| 725 |
+
self.hidden_size = config.d_model
|
| 726 |
+
|
| 727 |
+
self.self_attn = DeformableDetrSelfAttention(
|
| 728 |
+
config=config,
|
| 729 |
+
hidden_size=self.hidden_size,
|
| 730 |
+
num_attention_heads=config.decoder_attention_heads,
|
| 731 |
+
dropout=config.attention_dropout,
|
| 732 |
+
)
|
| 733 |
+
self.dropout = config.dropout
|
| 734 |
+
|
| 735 |
+
self.self_attn_layer_norm = nn.LayerNorm(self.hidden_size)
|
| 736 |
+
self.encoder_attn = DeformableDetrMultiscaleDeformableAttention(
|
| 737 |
+
config,
|
| 738 |
+
num_heads=config.decoder_attention_heads,
|
| 739 |
+
n_points=config.decoder_n_points,
|
| 740 |
+
)
|
| 741 |
+
self.encoder_attn_layer_norm = nn.LayerNorm(self.hidden_size)
|
| 742 |
+
self.mlp = DeformableDetrMLP(config, self.hidden_size, config.decoder_ffn_dim)
|
| 743 |
+
self.final_layer_norm = nn.LayerNorm(self.hidden_size)
|
| 744 |
+
|
| 745 |
+
def forward(
|
| 746 |
+
self,
|
| 747 |
+
hidden_states: torch.Tensor,
|
| 748 |
+
object_queries_position_embeddings: torch.Tensor | None = None,
|
| 749 |
+
reference_points=None,
|
| 750 |
+
spatial_shapes=None,
|
| 751 |
+
spatial_shapes_list=None,
|
| 752 |
+
level_start_index=None,
|
| 753 |
+
encoder_hidden_states: torch.Tensor | None = None,
|
| 754 |
+
encoder_attention_mask: torch.Tensor | None = None,
|
| 755 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 756 |
+
) -> torch.Tensor:
|
| 757 |
+
"""
|
| 758 |
+
Args:
|
| 759 |
+
hidden_states (`torch.FloatTensor`):
|
| 760 |
+
Input to the layer of shape `(seq_len, batch, embed_dim)`.
|
| 761 |
+
position_embeddings (`torch.FloatTensor`, *optional*):
|
| 762 |
+
Position embeddings that are added to the queries and keys in the self-attention layer.
|
| 763 |
+
reference_points (`torch.FloatTensor`, *optional*):
|
| 764 |
+
Reference points.
|
| 765 |
+
spatial_shapes (`torch.LongTensor`, *optional*):
|
| 766 |
+
Spatial shapes.
|
| 767 |
+
level_start_index (`torch.LongTensor`, *optional*):
|
| 768 |
+
Level start index.
|
| 769 |
+
encoder_hidden_states (`torch.FloatTensor`):
|
| 770 |
+
cross attention input to the layer of shape `(seq_len, batch, embed_dim)`
|
| 771 |
+
encoder_attention_mask (`torch.FloatTensor`): encoder attention mask of size
|
| 772 |
+
`(batch, 1, target_len, source_len)` where padding elements are indicated by very large negative
|
| 773 |
+
values.
|
| 774 |
+
"""
|
| 775 |
+
residual = hidden_states
|
| 776 |
+
|
| 777 |
+
# Self Attention
|
| 778 |
+
hidden_states, _ = self.self_attn(
|
| 779 |
+
hidden_states=hidden_states,
|
| 780 |
+
position_embeddings=object_queries_position_embeddings,
|
| 781 |
+
**kwargs,
|
| 782 |
+
)
|
| 783 |
+
|
| 784 |
+
hidden_states = nn.functional.dropout(hidden_states, p=self.dropout, training=self.training)
|
| 785 |
+
hidden_states = residual + hidden_states
|
| 786 |
+
hidden_states = self.self_attn_layer_norm(hidden_states)
|
| 787 |
+
|
| 788 |
+
residual = hidden_states
|
| 789 |
+
|
| 790 |
+
# Cross-Attention
|
| 791 |
+
hidden_states, _ = self.encoder_attn(
|
| 792 |
+
hidden_states=hidden_states,
|
| 793 |
+
attention_mask=encoder_attention_mask,
|
| 794 |
+
encoder_hidden_states=encoder_hidden_states,
|
| 795 |
+
encoder_attention_mask=encoder_attention_mask,
|
| 796 |
+
position_embeddings=object_queries_position_embeddings,
|
| 797 |
+
reference_points=reference_points,
|
| 798 |
+
spatial_shapes=spatial_shapes,
|
| 799 |
+
spatial_shapes_list=spatial_shapes_list,
|
| 800 |
+
level_start_index=level_start_index,
|
| 801 |
+
)
|
| 802 |
+
|
| 803 |
+
hidden_states = nn.functional.dropout(hidden_states, p=self.dropout, training=self.training)
|
| 804 |
+
hidden_states = residual + hidden_states
|
| 805 |
+
|
| 806 |
+
hidden_states = self.encoder_attn_layer_norm(hidden_states)
|
| 807 |
+
|
| 808 |
+
# Fully Connected
|
| 809 |
+
residual = hidden_states
|
| 810 |
+
hidden_states = self.mlp(hidden_states)
|
| 811 |
+
hidden_states = residual + hidden_states
|
| 812 |
+
hidden_states = self.final_layer_norm(hidden_states)
|
| 813 |
+
|
| 814 |
+
return hidden_states
|
| 815 |
+
|
| 816 |
+
|
| 817 |
+
@auto_docstring
|
| 818 |
+
class DeformableDetrPreTrainedModel(PreTrainedModel):
|
| 819 |
+
config: DeformableDetrConfig
|
| 820 |
+
base_model_prefix = "model"
|
| 821 |
+
main_input_name = "pixel_values"
|
| 822 |
+
input_modalities = ("image",)
|
| 823 |
+
supports_gradient_checkpointing = True
|
| 824 |
+
_no_split_modules = [
|
| 825 |
+
r"DeformableDetrConvEncoder",
|
| 826 |
+
r"DeformableDetrEncoderLayer",
|
| 827 |
+
r"DeformableDetrDecoderLayer",
|
| 828 |
+
]
|
| 829 |
+
_supports_sdpa = True
|
| 830 |
+
_supports_flash_attn = True
|
| 831 |
+
_supports_attention_backend = True
|
| 832 |
+
_supports_flex_attn = True
|
| 833 |
+
_keys_to_ignore_on_load_unexpected = [
|
| 834 |
+
r"detr\.model\.backbone\.model\.layer\d+\.0\.downsample\.1\.num_batches_tracked"
|
| 835 |
+
]
|
| 836 |
+
|
| 837 |
+
@torch.no_grad()
|
| 838 |
+
def _init_weights(self, module):
|
| 839 |
+
std = self.config.init_std
|
| 840 |
+
|
| 841 |
+
if isinstance(module, DeformableDetrLearnedPositionEmbedding):
|
| 842 |
+
init.uniform_(module.row_embeddings.weight)
|
| 843 |
+
init.uniform_(module.column_embeddings.weight)
|
| 844 |
+
elif isinstance(module, DeformableDetrMultiscaleDeformableAttention):
|
| 845 |
+
init.constant_(module.sampling_offsets.weight, 0.0)
|
| 846 |
+
default_dtype = torch.get_default_dtype()
|
| 847 |
+
thetas = torch.arange(module.n_heads, dtype=torch.int64).to(default_dtype) * (
|
| 848 |
+
2.0 * math.pi / module.n_heads
|
| 849 |
+
)
|
| 850 |
+
grid_init = torch.stack([thetas.cos(), thetas.sin()], -1)
|
| 851 |
+
grid_init = (
|
| 852 |
+
(grid_init / grid_init.abs().max(-1, keepdim=True)[0])
|
| 853 |
+
.view(module.n_heads, 1, 1, 2)
|
| 854 |
+
.repeat(1, module.n_levels, module.n_points, 1)
|
| 855 |
+
)
|
| 856 |
+
for i in range(module.n_points):
|
| 857 |
+
grid_init[:, :, i, :] *= i + 1
|
| 858 |
+
|
| 859 |
+
init.copy_(module.sampling_offsets.bias, grid_init.view(-1))
|
| 860 |
+
init.constant_(module.attention_weights.weight, 0.0)
|
| 861 |
+
init.constant_(module.attention_weights.bias, 0.0)
|
| 862 |
+
init.xavier_uniform_(module.value_proj.weight)
|
| 863 |
+
init.constant_(module.value_proj.bias, 0.0)
|
| 864 |
+
init.xavier_uniform_(module.output_proj.weight)
|
| 865 |
+
init.constant_(module.output_proj.bias, 0.0)
|
| 866 |
+
elif isinstance(module, (nn.Linear, nn.Conv2d)):
|
| 867 |
+
init.normal_(module.weight, mean=0.0, std=std)
|
| 868 |
+
if module.bias is not None:
|
| 869 |
+
init.zeros_(module.bias)
|
| 870 |
+
elif isinstance(module, nn.Embedding):
|
| 871 |
+
init.normal_(module.weight, mean=0.0, std=std)
|
| 872 |
+
# Here we need the check explicitly, as we slice the weight in the `zeros_` call, so it looses the flag
|
| 873 |
+
if module.padding_idx is not None and not getattr(module.weight, "_is_hf_initialized", False):
|
| 874 |
+
init.zeros_(module.weight[module.padding_idx])
|
| 875 |
+
if hasattr(module, "reference_points") and not self.config.two_stage:
|
| 876 |
+
init.xavier_uniform_(module.reference_points.weight, gain=1.0)
|
| 877 |
+
init.constant_(module.reference_points.bias, 0.0)
|
| 878 |
+
if hasattr(module, "level_embed"):
|
| 879 |
+
init.normal_(module.level_embed)
|
| 880 |
+
|
| 881 |
+
|
| 882 |
+
class DeformableDetrEncoder(DeformableDetrPreTrainedModel):
|
| 883 |
+
"""
|
| 884 |
+
Transformer encoder consisting of *config.encoder_layers* deformable attention layers. Each layer is a
|
| 885 |
+
[`DeformableDetrEncoderLayer`].
|
| 886 |
+
|
| 887 |
+
The encoder updates the flattened multi-scale feature maps through multiple deformable attention layers.
|
| 888 |
+
|
| 889 |
+
Args:
|
| 890 |
+
config: DeformableDetrConfig
|
| 891 |
+
"""
|
| 892 |
+
|
| 893 |
+
_can_record_outputs = {
|
| 894 |
+
"hidden_states": DeformableDetrEncoderLayer,
|
| 895 |
+
"attentions": OutputRecorder(DeformableDetrMultiscaleDeformableAttention, layer_name="self_attn", index=1),
|
| 896 |
+
}
|
| 897 |
+
|
| 898 |
+
def __init__(self, config: DeformableDetrConfig):
|
| 899 |
+
super().__init__(config)
|
| 900 |
+
|
| 901 |
+
self.dropout = config.dropout
|
| 902 |
+
self.layers = nn.ModuleList([DeformableDetrEncoderLayer(config) for _ in range(config.encoder_layers)])
|
| 903 |
+
|
| 904 |
+
# Initialize weights and apply final processing
|
| 905 |
+
self.post_init()
|
| 906 |
+
|
| 907 |
+
@merge_with_config_defaults
|
| 908 |
+
@capture_outputs
|
| 909 |
+
def forward(
|
| 910 |
+
self,
|
| 911 |
+
inputs_embeds=None,
|
| 912 |
+
attention_mask=None,
|
| 913 |
+
spatial_position_embeddings=None,
|
| 914 |
+
spatial_shapes=None,
|
| 915 |
+
spatial_shapes_list=None,
|
| 916 |
+
level_start_index=None,
|
| 917 |
+
valid_ratios=None,
|
| 918 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 919 |
+
) -> BaseModelOutput:
|
| 920 |
+
r"""
|
| 921 |
+
Args:
|
| 922 |
+
inputs_embeds (`torch.FloatTensor` of shape `(batch_size, sequence_length, hidden_size)`):
|
| 923 |
+
Flattened feature map (output of the backbone + projection layer) that is passed to the encoder.
|
| 924 |
+
attention_mask (`torch.Tensor` of shape `(batch_size, sequence_length)`, *optional*):
|
| 925 |
+
Mask to avoid performing attention on padding pixel features. Mask values selected in `[0, 1]`:
|
| 926 |
+
- 1 for pixel features that are real (i.e. **not masked**),
|
| 927 |
+
- 0 for pixel features that are padding (i.e. **masked**).
|
| 928 |
+
[What are attention masks?](../glossary#attention-mask)
|
| 929 |
+
spatial_position_embeddings (`torch.FloatTensor` of shape `(batch_size, sequence_length, hidden_size)`):
|
| 930 |
+
Spatial position embeddings (2D positional encodings) that are added to the queries and keys in each self-attention layer.
|
| 931 |
+
spatial_shapes (`torch.LongTensor` of shape `(num_feature_levels, 2)`):
|
| 932 |
+
Spatial shapes of each feature map.
|
| 933 |
+
level_start_index (`torch.LongTensor` of shape `(num_feature_levels)`):
|
| 934 |
+
Starting index of each feature map.
|
| 935 |
+
valid_ratios (`torch.FloatTensor` of shape `(batch_size, num_feature_levels, 2)`):
|
| 936 |
+
Ratio of valid area in each feature level.
|
| 937 |
+
"""
|
| 938 |
+
hidden_states = inputs_embeds
|
| 939 |
+
hidden_states = nn.functional.dropout(hidden_states, p=self.dropout, training=self.training)
|
| 940 |
+
|
| 941 |
+
spatial_shapes_tuple = tuple(spatial_shapes_list)
|
| 942 |
+
reference_points = self.get_reference_points(spatial_shapes_tuple, valid_ratios, device=inputs_embeds.device)
|
| 943 |
+
|
| 944 |
+
for encoder_layer in self.layers:
|
| 945 |
+
hidden_states = encoder_layer(
|
| 946 |
+
hidden_states,
|
| 947 |
+
attention_mask,
|
| 948 |
+
spatial_position_embeddings=spatial_position_embeddings,
|
| 949 |
+
reference_points=reference_points,
|
| 950 |
+
spatial_shapes=spatial_shapes,
|
| 951 |
+
spatial_shapes_list=spatial_shapes_list,
|
| 952 |
+
level_start_index=level_start_index,
|
| 953 |
+
**kwargs,
|
| 954 |
+
)
|
| 955 |
+
|
| 956 |
+
return BaseModelOutput(last_hidden_state=hidden_states)
|
| 957 |
+
|
| 958 |
+
@staticmethod
|
| 959 |
+
def get_reference_points(spatial_shapes_list, valid_ratios, device):
|
| 960 |
+
"""
|
| 961 |
+
Get reference points for each feature map. Used in decoder.
|
| 962 |
+
|
| 963 |
+
Args:
|
| 964 |
+
spatial_shapes_list (`list[tuple[int, int]]`):
|
| 965 |
+
Spatial shapes of each feature map.
|
| 966 |
+
valid_ratios (`torch.FloatTensor` of shape `(batch_size, num_feature_levels, 2)`):
|
| 967 |
+
Valid ratios of each feature map.
|
| 968 |
+
device (`torch.device`):
|
| 969 |
+
Device on which to create the tensors.
|
| 970 |
+
Returns:
|
| 971 |
+
`torch.FloatTensor` of shape `(batch_size, num_queries, num_feature_levels, 2)`
|
| 972 |
+
"""
|
| 973 |
+
reference_points_list = []
|
| 974 |
+
for level, (height, width) in enumerate(spatial_shapes_list):
|
| 975 |
+
ref_y, ref_x = torch.meshgrid(
|
| 976 |
+
torch.linspace(0.5, height - 0.5, height, dtype=valid_ratios.dtype, device=device),
|
| 977 |
+
torch.linspace(0.5, width - 0.5, width, dtype=valid_ratios.dtype, device=device),
|
| 978 |
+
indexing="ij",
|
| 979 |
+
)
|
| 980 |
+
# TODO: valid_ratios could be useless here. check https://github.com/fundamentalvision/Deformable-DETR/issues/36
|
| 981 |
+
ref_y = ref_y.reshape(-1)[None] / (valid_ratios[:, None, level, 1] * height)
|
| 982 |
+
ref_x = ref_x.reshape(-1)[None] / (valid_ratios[:, None, level, 0] * width)
|
| 983 |
+
ref = torch.stack((ref_x, ref_y), -1)
|
| 984 |
+
reference_points_list.append(ref)
|
| 985 |
+
reference_points = torch.cat(reference_points_list, 1)
|
| 986 |
+
reference_points = reference_points[:, :, None] * valid_ratios[:, None]
|
| 987 |
+
return reference_points
|
| 988 |
+
|
| 989 |
+
|
| 990 |
+
def inverse_sigmoid(x, eps=1e-5):
|
| 991 |
+
x = x.clamp(min=0, max=1)
|
| 992 |
+
x1 = x.clamp(min=eps)
|
| 993 |
+
x2 = (1 - x).clamp(min=eps)
|
| 994 |
+
return torch.log(x1 / x2)
|
| 995 |
+
|
| 996 |
+
|
| 997 |
+
class DeformableDetrDecoder(DeformableDetrPreTrainedModel):
|
| 998 |
+
"""
|
| 999 |
+
Transformer decoder consisting of *config.decoder_layers* layers. Each layer is a [`DeformableDetrDecoderLayer`].
|
| 1000 |
+
|
| 1001 |
+
The decoder updates the query embeddings through multiple self-attention and cross-attention layers.
|
| 1002 |
+
|
| 1003 |
+
Some tweaks for Deformable DETR:
|
| 1004 |
+
|
| 1005 |
+
- `position_embeddings`, `reference_points`, `spatial_shapes` and `valid_ratios` are added to the forward pass.
|
| 1006 |
+
- it also returns a stack of intermediate outputs and reference points from all decoding layers.
|
| 1007 |
+
|
| 1008 |
+
Args:
|
| 1009 |
+
config: DeformableDetrConfig
|
| 1010 |
+
"""
|
| 1011 |
+
|
| 1012 |
+
_can_record_outputs = {
|
| 1013 |
+
"hidden_states": DeformableDetrDecoderLayer,
|
| 1014 |
+
"attentions": OutputRecorder(DeformableDetrSelfAttention, layer_name="self_attn", index=1),
|
| 1015 |
+
"cross_attentions": OutputRecorder(
|
| 1016 |
+
DeformableDetrMultiscaleDeformableAttention, layer_name="encoder_attn", index=1
|
| 1017 |
+
),
|
| 1018 |
+
}
|
| 1019 |
+
|
| 1020 |
+
def __init__(self, config: DeformableDetrConfig):
|
| 1021 |
+
super().__init__(config)
|
| 1022 |
+
|
| 1023 |
+
self.dropout = config.dropout
|
| 1024 |
+
self.layers = nn.ModuleList([DeformableDetrDecoderLayer(config) for _ in range(config.decoder_layers)])
|
| 1025 |
+
|
| 1026 |
+
# hack implementation for iterative bounding box refinement and two-stage Deformable DETR
|
| 1027 |
+
self.bbox_embed = None
|
| 1028 |
+
self.class_embed = None
|
| 1029 |
+
|
| 1030 |
+
# Initialize weights and apply final processing
|
| 1031 |
+
self.post_init()
|
| 1032 |
+
|
| 1033 |
+
@merge_with_config_defaults
|
| 1034 |
+
@capture_outputs
|
| 1035 |
+
def forward(
|
| 1036 |
+
self,
|
| 1037 |
+
inputs_embeds=None,
|
| 1038 |
+
encoder_hidden_states=None,
|
| 1039 |
+
encoder_attention_mask=None,
|
| 1040 |
+
object_queries_position_embeddings=None,
|
| 1041 |
+
reference_points=None,
|
| 1042 |
+
spatial_shapes=None,
|
| 1043 |
+
spatial_shapes_list=None,
|
| 1044 |
+
level_start_index=None,
|
| 1045 |
+
valid_ratios=None,
|
| 1046 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 1047 |
+
):
|
| 1048 |
+
r"""
|
| 1049 |
+
Args:
|
| 1050 |
+
inputs_embeds (`torch.FloatTensor` of shape `(batch_size, num_queries, hidden_size)`):
|
| 1051 |
+
The query embeddings that are passed into the decoder.
|
| 1052 |
+
encoder_hidden_states (`torch.FloatTensor` of shape `(batch_size, sequence_length, hidden_size)`, *optional*):
|
| 1053 |
+
Sequence of hidden-states at the output of the last layer of the encoder. Used in the cross-attention
|
| 1054 |
+
of the decoder.
|
| 1055 |
+
encoder_attention_mask (`torch.LongTensor` of shape `(batch_size, sequence_length)`, *optional*):
|
| 1056 |
+
Mask to avoid performing cross-attention on padding pixel_values of the encoder. Mask values selected
|
| 1057 |
+
in `[0, 1]`:
|
| 1058 |
+
- 1 for pixels that are real (i.e. **not masked**),
|
| 1059 |
+
- 0 for pixels that are padding (i.e. **masked**).
|
| 1060 |
+
object_queries_position_embeddings (`torch.FloatTensor` of shape `(batch_size, num_queries, hidden_size)`, *optional*):
|
| 1061 |
+
Position embeddings for the object query slots that are added to the queries and keys in each self-attention layer.
|
| 1062 |
+
reference_points (`torch.FloatTensor` of shape `(batch_size, num_queries, 4)` is `as_two_stage` else `(batch_size, num_queries, 2)` or , *optional*):
|
| 1063 |
+
Reference point in range `[0, 1]`, top-left (0,0), bottom-right (1, 1), including padding area.
|
| 1064 |
+
spatial_shapes (`torch.FloatTensor` of shape `(num_feature_levels, 2)`):
|
| 1065 |
+
Spatial shapes of the feature maps.
|
| 1066 |
+
level_start_index (`torch.LongTensor` of shape `(num_feature_levels)`, *optional*):
|
| 1067 |
+
Indexes for the start of each feature level. In range `[0, sequence_length]`.
|
| 1068 |
+
valid_ratios (`torch.FloatTensor` of shape `(batch_size, num_feature_levels, 2)`, *optional*):
|
| 1069 |
+
Ratio of valid area in each feature level.
|
| 1070 |
+
|
| 1071 |
+
"""
|
| 1072 |
+
if inputs_embeds is not None:
|
| 1073 |
+
hidden_states = inputs_embeds
|
| 1074 |
+
|
| 1075 |
+
# decoder layers
|
| 1076 |
+
intermediate = ()
|
| 1077 |
+
intermediate_reference_points = ()
|
| 1078 |
+
|
| 1079 |
+
for idx, decoder_layer in enumerate(self.layers):
|
| 1080 |
+
num_coordinates = reference_points.shape[-1]
|
| 1081 |
+
if num_coordinates == 4:
|
| 1082 |
+
reference_points_input = (
|
| 1083 |
+
reference_points[:, :, None] * torch.cat([valid_ratios, valid_ratios], -1)[:, None]
|
| 1084 |
+
)
|
| 1085 |
+
elif reference_points.shape[-1] == 2:
|
| 1086 |
+
reference_points_input = reference_points[:, :, None] * valid_ratios[:, None]
|
| 1087 |
+
else:
|
| 1088 |
+
raise ValueError("Reference points' last dimension must be of size 2")
|
| 1089 |
+
|
| 1090 |
+
hidden_states = decoder_layer(
|
| 1091 |
+
hidden_states,
|
| 1092 |
+
object_queries_position_embeddings,
|
| 1093 |
+
reference_points_input,
|
| 1094 |
+
spatial_shapes,
|
| 1095 |
+
spatial_shapes_list,
|
| 1096 |
+
level_start_index,
|
| 1097 |
+
encoder_hidden_states, # as a positional argument for gradient checkpointing
|
| 1098 |
+
encoder_attention_mask,
|
| 1099 |
+
**kwargs,
|
| 1100 |
+
)
|
| 1101 |
+
|
| 1102 |
+
# hack implementation for iterative bounding box refinement
|
| 1103 |
+
if self.bbox_embed is not None:
|
| 1104 |
+
tmp = self.bbox_embed[idx](hidden_states)
|
| 1105 |
+
num_coordinates = reference_points.shape[-1]
|
| 1106 |
+
if num_coordinates == 4:
|
| 1107 |
+
new_reference_points = tmp + inverse_sigmoid(reference_points)
|
| 1108 |
+
new_reference_points = new_reference_points.sigmoid()
|
| 1109 |
+
elif num_coordinates == 2:
|
| 1110 |
+
new_reference_points = tmp
|
| 1111 |
+
new_reference_points[..., :2] = tmp[..., :2] + inverse_sigmoid(reference_points)
|
| 1112 |
+
new_reference_points = new_reference_points.sigmoid()
|
| 1113 |
+
else:
|
| 1114 |
+
raise ValueError(
|
| 1115 |
+
f"Last dim of reference_points must be 2 or 4, but got {reference_points.shape[-1]}"
|
| 1116 |
+
)
|
| 1117 |
+
reference_points = new_reference_points.detach()
|
| 1118 |
+
|
| 1119 |
+
intermediate += (hidden_states,)
|
| 1120 |
+
intermediate_reference_points += (reference_points,)
|
| 1121 |
+
|
| 1122 |
+
# Keep batch_size as first dimension
|
| 1123 |
+
intermediate = torch.stack(intermediate, dim=1)
|
| 1124 |
+
intermediate_reference_points = torch.stack(intermediate_reference_points, dim=1)
|
| 1125 |
+
|
| 1126 |
+
return DeformableDetrDecoderOutput(
|
| 1127 |
+
last_hidden_state=hidden_states,
|
| 1128 |
+
intermediate_hidden_states=intermediate,
|
| 1129 |
+
intermediate_reference_points=intermediate_reference_points,
|
| 1130 |
+
)
|
| 1131 |
+
|
| 1132 |
+
|
| 1133 |
+
@auto_docstring(
|
| 1134 |
+
custom_intro="""
|
| 1135 |
+
The bare Deformable DETR Model (consisting of a backbone and encoder-decoder Transformer) outputting raw
|
| 1136 |
+
hidden-states without any specific head on top.
|
| 1137 |
+
"""
|
| 1138 |
+
)
|
| 1139 |
+
class DeformableDetrModel(DeformableDetrPreTrainedModel):
|
| 1140 |
+
def __init__(self, config: DeformableDetrConfig):
|
| 1141 |
+
super().__init__(config)
|
| 1142 |
+
|
| 1143 |
+
# Create backbone
|
| 1144 |
+
self.backbone = DeformableDetrConvEncoder(config)
|
| 1145 |
+
|
| 1146 |
+
# Create positional encoding
|
| 1147 |
+
if config.position_embedding_type == "sine":
|
| 1148 |
+
self.position_embedding = DeformableDetrSinePositionEmbedding(config.d_model // 2, normalize=True)
|
| 1149 |
+
elif config.position_embedding_type == "learned":
|
| 1150 |
+
self.position_embedding = DeformableDetrLearnedPositionEmbedding(config.d_model // 2)
|
| 1151 |
+
else:
|
| 1152 |
+
raise ValueError(f"Not supported {config.position_embedding_type}")
|
| 1153 |
+
|
| 1154 |
+
# Create input projection layers
|
| 1155 |
+
if config.num_feature_levels > 1:
|
| 1156 |
+
num_backbone_outs = len(self.backbone.intermediate_channel_sizes)
|
| 1157 |
+
input_proj_list = []
|
| 1158 |
+
for _ in range(num_backbone_outs):
|
| 1159 |
+
in_channels = self.backbone.intermediate_channel_sizes[_]
|
| 1160 |
+
input_proj_list.append(
|
| 1161 |
+
nn.Sequential(
|
| 1162 |
+
nn.Conv2d(in_channels, config.d_model, kernel_size=1),
|
| 1163 |
+
nn.GroupNorm(32, config.d_model),
|
| 1164 |
+
)
|
| 1165 |
+
)
|
| 1166 |
+
for _ in range(config.num_feature_levels - num_backbone_outs):
|
| 1167 |
+
input_proj_list.append(
|
| 1168 |
+
nn.Sequential(
|
| 1169 |
+
nn.Conv2d(
|
| 1170 |
+
in_channels,
|
| 1171 |
+
config.d_model,
|
| 1172 |
+
kernel_size=3,
|
| 1173 |
+
stride=2,
|
| 1174 |
+
padding=1,
|
| 1175 |
+
),
|
| 1176 |
+
nn.GroupNorm(32, config.d_model),
|
| 1177 |
+
)
|
| 1178 |
+
)
|
| 1179 |
+
in_channels = config.d_model
|
| 1180 |
+
self.input_proj = nn.ModuleList(input_proj_list)
|
| 1181 |
+
else:
|
| 1182 |
+
self.input_proj = nn.ModuleList(
|
| 1183 |
+
[
|
| 1184 |
+
nn.Sequential(
|
| 1185 |
+
nn.Conv2d(
|
| 1186 |
+
self.backbone.intermediate_channel_sizes[-1],
|
| 1187 |
+
config.d_model,
|
| 1188 |
+
kernel_size=1,
|
| 1189 |
+
),
|
| 1190 |
+
nn.GroupNorm(32, config.d_model),
|
| 1191 |
+
)
|
| 1192 |
+
]
|
| 1193 |
+
)
|
| 1194 |
+
|
| 1195 |
+
if not config.two_stage:
|
| 1196 |
+
self.query_position_embeddings = nn.Embedding(config.num_queries, config.d_model * 2)
|
| 1197 |
+
|
| 1198 |
+
self.encoder = DeformableDetrEncoder(config)
|
| 1199 |
+
self.decoder = DeformableDetrDecoder(config)
|
| 1200 |
+
|
| 1201 |
+
self.level_embed = nn.Parameter(torch.Tensor(config.num_feature_levels, config.d_model))
|
| 1202 |
+
|
| 1203 |
+
if config.two_stage:
|
| 1204 |
+
self.enc_output = nn.Linear(config.d_model, config.d_model)
|
| 1205 |
+
self.enc_output_norm = nn.LayerNorm(config.d_model)
|
| 1206 |
+
self.pos_trans = nn.Linear(config.d_model * 2, config.d_model * 2)
|
| 1207 |
+
self.pos_trans_norm = nn.LayerNorm(config.d_model * 2)
|
| 1208 |
+
else:
|
| 1209 |
+
self.reference_points = nn.Linear(config.d_model, 2)
|
| 1210 |
+
|
| 1211 |
+
self.post_init()
|
| 1212 |
+
|
| 1213 |
+
def freeze_backbone(self):
|
| 1214 |
+
for name, param in self.backbone.model.named_parameters():
|
| 1215 |
+
param.requires_grad_(False)
|
| 1216 |
+
|
| 1217 |
+
def unfreeze_backbone(self):
|
| 1218 |
+
for name, param in self.backbone.model.named_parameters():
|
| 1219 |
+
param.requires_grad_(True)
|
| 1220 |
+
|
| 1221 |
+
def get_valid_ratio(self, mask, dtype=torch.float32):
|
| 1222 |
+
"""Get the valid ratio of all feature maps."""
|
| 1223 |
+
|
| 1224 |
+
_, height, width = mask.shape
|
| 1225 |
+
valid_height = torch.sum(mask[:, :, 0], 1)
|
| 1226 |
+
valid_width = torch.sum(mask[:, 0, :], 1)
|
| 1227 |
+
valid_ratio_height = valid_height.to(dtype) / height
|
| 1228 |
+
valid_ratio_width = valid_width.to(dtype) / width
|
| 1229 |
+
valid_ratio = torch.stack([valid_ratio_width, valid_ratio_height], -1)
|
| 1230 |
+
return valid_ratio
|
| 1231 |
+
|
| 1232 |
+
def get_proposal_pos_embed(self, proposals):
|
| 1233 |
+
"""Get the position embedding of the proposals."""
|
| 1234 |
+
|
| 1235 |
+
num_pos_feats = self.config.d_model // 2
|
| 1236 |
+
temperature = 10000
|
| 1237 |
+
scale = 2 * math.pi
|
| 1238 |
+
|
| 1239 |
+
# Compute position embeddings in float32 to avoid overflow with large temperature values in fp16
|
| 1240 |
+
proposals_dtype = proposals.dtype
|
| 1241 |
+
dim_t = torch.arange(num_pos_feats, dtype=torch.float32, device=proposals.device)
|
| 1242 |
+
dim_t = temperature ** (2 * torch.div(dim_t, 2, rounding_mode="floor") / num_pos_feats)
|
| 1243 |
+
# batch_size, num_queries, 4
|
| 1244 |
+
proposals = proposals.sigmoid().to(torch.float32) * scale
|
| 1245 |
+
# batch_size, num_queries, 4, 128
|
| 1246 |
+
pos = proposals[:, :, :, None] / dim_t
|
| 1247 |
+
# batch_size, num_queries, 4, 64, 2 -> batch_size, num_queries, 512
|
| 1248 |
+
pos = torch.stack((pos[:, :, :, 0::2].sin(), pos[:, :, :, 1::2].cos()), dim=4).flatten(2)
|
| 1249 |
+
# Convert back to target dtype after all computations are done
|
| 1250 |
+
return pos.to(proposals_dtype)
|
| 1251 |
+
|
| 1252 |
+
def gen_encoder_output_proposals(self, enc_output, padding_mask, spatial_shapes):
|
| 1253 |
+
"""Generate the encoder output proposals from encoded enc_output.
|
| 1254 |
+
|
| 1255 |
+
Args:
|
| 1256 |
+
enc_output (Tensor[batch_size, sequence_length, hidden_size]): Output of the encoder.
|
| 1257 |
+
padding_mask (Tensor[batch_size, sequence_length]): Padding mask for `enc_output`.
|
| 1258 |
+
spatial_shapes (list[tuple[int, int]]): Spatial shapes of the feature maps.
|
| 1259 |
+
|
| 1260 |
+
Returns:
|
| 1261 |
+
`tuple(torch.FloatTensor)`: A tuple of feature map and bbox prediction.
|
| 1262 |
+
- object_query (Tensor[batch_size, sequence_length, hidden_size]): Object query features. Later used to
|
| 1263 |
+
directly predict a bounding box. (without the need of a decoder)
|
| 1264 |
+
- output_proposals (Tensor[batch_size, sequence_length, 4]): Normalized proposals, after an inverse
|
| 1265 |
+
sigmoid.
|
| 1266 |
+
"""
|
| 1267 |
+
batch_size = enc_output.shape[0]
|
| 1268 |
+
proposals = []
|
| 1269 |
+
_cur = 0
|
| 1270 |
+
for level, (height, width) in enumerate(spatial_shapes):
|
| 1271 |
+
mask_flatten_ = padding_mask[:, _cur : (_cur + height * width)].view(batch_size, height, width, 1)
|
| 1272 |
+
valid_height = torch.sum(~mask_flatten_[:, :, 0, 0], 1)
|
| 1273 |
+
valid_width = torch.sum(~mask_flatten_[:, 0, :, 0], 1)
|
| 1274 |
+
|
| 1275 |
+
grid_y, grid_x = torch.meshgrid(
|
| 1276 |
+
torch.linspace(
|
| 1277 |
+
0,
|
| 1278 |
+
height - 1,
|
| 1279 |
+
height,
|
| 1280 |
+
dtype=enc_output.dtype,
|
| 1281 |
+
device=enc_output.device,
|
| 1282 |
+
),
|
| 1283 |
+
torch.linspace(
|
| 1284 |
+
0,
|
| 1285 |
+
width - 1,
|
| 1286 |
+
width,
|
| 1287 |
+
dtype=enc_output.dtype,
|
| 1288 |
+
device=enc_output.device,
|
| 1289 |
+
),
|
| 1290 |
+
indexing="ij",
|
| 1291 |
+
)
|
| 1292 |
+
grid = torch.cat([grid_x.unsqueeze(-1), grid_y.unsqueeze(-1)], -1)
|
| 1293 |
+
|
| 1294 |
+
scale = torch.cat([valid_width.unsqueeze(-1), valid_height.unsqueeze(-1)], 1).view(batch_size, 1, 1, 2)
|
| 1295 |
+
grid = (grid.unsqueeze(0).expand(batch_size, -1, -1, -1) + 0.5) / scale
|
| 1296 |
+
width_height = torch.ones_like(grid) * 0.05 * (2.0**level)
|
| 1297 |
+
proposal = torch.cat((grid, width_height), -1).view(batch_size, -1, 4)
|
| 1298 |
+
proposals.append(proposal)
|
| 1299 |
+
_cur += height * width
|
| 1300 |
+
output_proposals = torch.cat(proposals, 1)
|
| 1301 |
+
output_proposals_valid = ((output_proposals > 0.01) & (output_proposals < 0.99)).all(-1, keepdim=True)
|
| 1302 |
+
output_proposals = torch.log(output_proposals / (1 - output_proposals)) # inverse sigmoid
|
| 1303 |
+
output_proposals = output_proposals.masked_fill(padding_mask.unsqueeze(-1), float("inf"))
|
| 1304 |
+
output_proposals = output_proposals.masked_fill(~output_proposals_valid, float("inf"))
|
| 1305 |
+
|
| 1306 |
+
# assign each pixel as an object query
|
| 1307 |
+
object_query = enc_output
|
| 1308 |
+
object_query = object_query.masked_fill(padding_mask.unsqueeze(-1), float(0))
|
| 1309 |
+
object_query = object_query.masked_fill(~output_proposals_valid, float(0))
|
| 1310 |
+
object_query = self.enc_output_norm(self.enc_output(object_query))
|
| 1311 |
+
return object_query, output_proposals
|
| 1312 |
+
|
| 1313 |
+
@auto_docstring
|
| 1314 |
+
@can_return_tuple
|
| 1315 |
+
def forward(
|
| 1316 |
+
self,
|
| 1317 |
+
pixel_values: torch.FloatTensor,
|
| 1318 |
+
pixel_mask: torch.LongTensor | None = None,
|
| 1319 |
+
decoder_attention_mask: torch.FloatTensor | None = None,
|
| 1320 |
+
encoder_outputs: torch.FloatTensor | None = None,
|
| 1321 |
+
inputs_embeds: torch.FloatTensor | None = None,
|
| 1322 |
+
decoder_inputs_embeds: torch.FloatTensor | None = None,
|
| 1323 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 1324 |
+
) -> tuple[torch.FloatTensor] | DeformableDetrModelOutput:
|
| 1325 |
+
r"""
|
| 1326 |
+
decoder_attention_mask (`torch.FloatTensor` of shape `(batch_size, num_queries)`, *optional*):
|
| 1327 |
+
Not used by default. Can be used to mask object queries.
|
| 1328 |
+
inputs_embeds (`torch.FloatTensor` of shape `(batch_size, sequence_length, hidden_size)`, *optional*):
|
| 1329 |
+
Optionally, instead of passing the flattened feature map (output of the backbone + projection layer), you
|
| 1330 |
+
can choose to directly pass a flattened representation of an image.
|
| 1331 |
+
decoder_inputs_embeds (`torch.FloatTensor` of shape `(batch_size, num_queries, hidden_size)`, *optional*):
|
| 1332 |
+
Optionally, instead of initializing the queries with a tensor of zeros, you can choose to directly pass an
|
| 1333 |
+
embedded representation.
|
| 1334 |
+
|
| 1335 |
+
Examples:
|
| 1336 |
+
|
| 1337 |
+
```python
|
| 1338 |
+
>>> from transformers import AutoImageProcessor, DeformableDetrModel
|
| 1339 |
+
>>> from PIL import Image
|
| 1340 |
+
>>> import httpx
|
| 1341 |
+
>>> from io import BytesIO
|
| 1342 |
+
|
| 1343 |
+
>>> url = "http://images.cocodataset.org/val2017/000000039769.jpg"
|
| 1344 |
+
>>> with httpx.stream("GET", url) as response:
|
| 1345 |
+
... image = Image.open(BytesIO(response.read()))
|
| 1346 |
+
|
| 1347 |
+
>>> image_processor = AutoImageProcessor.from_pretrained("SenseTime/deformable-detr")
|
| 1348 |
+
>>> model = DeformableDetrModel.from_pretrained("SenseTime/deformable-detr")
|
| 1349 |
+
|
| 1350 |
+
>>> inputs = image_processor(images=image, return_tensors="pt")
|
| 1351 |
+
|
| 1352 |
+
>>> outputs = model(**inputs)
|
| 1353 |
+
|
| 1354 |
+
>>> last_hidden_states = outputs.last_hidden_state
|
| 1355 |
+
>>> list(last_hidden_states.shape)
|
| 1356 |
+
[1, 300, 256]
|
| 1357 |
+
```"""
|
| 1358 |
+
batch_size, num_channels, height, width = pixel_values.shape
|
| 1359 |
+
device = pixel_values.device
|
| 1360 |
+
|
| 1361 |
+
if pixel_mask is None:
|
| 1362 |
+
pixel_mask = torch.ones(((batch_size, height, width)), dtype=torch.long, device=device)
|
| 1363 |
+
|
| 1364 |
+
# Extract multi-scale feature maps of same resolution `config.d_model` (cf Figure 4 in paper)
|
| 1365 |
+
# First, sent pixel_values + pixel_mask through Backbone to obtain the features
|
| 1366 |
+
# which is a list of tuples
|
| 1367 |
+
features = self.backbone(pixel_values, pixel_mask)
|
| 1368 |
+
|
| 1369 |
+
# Then, apply 1x1 convolution to reduce the channel dimension to d_model (256 by default)
|
| 1370 |
+
sources = []
|
| 1371 |
+
masks = []
|
| 1372 |
+
position_embeddings_list = []
|
| 1373 |
+
for level, (source, mask) in enumerate(features):
|
| 1374 |
+
sources.append(self.input_proj[level](source))
|
| 1375 |
+
masks.append(mask)
|
| 1376 |
+
if mask is None:
|
| 1377 |
+
raise ValueError("No attention mask was provided")
|
| 1378 |
+
# Generate position embeddings for this feature level
|
| 1379 |
+
pos = self.position_embedding(shape=source.shape, device=device, dtype=pixel_values.dtype, mask=mask).to(
|
| 1380 |
+
source.dtype
|
| 1381 |
+
)
|
| 1382 |
+
position_embeddings_list.append(pos)
|
| 1383 |
+
|
| 1384 |
+
# Lowest resolution feature maps are obtained via 3x3 stride 2 convolutions on the final stage
|
| 1385 |
+
if self.config.num_feature_levels > len(sources):
|
| 1386 |
+
_len_sources = len(sources)
|
| 1387 |
+
for level in range(_len_sources, self.config.num_feature_levels):
|
| 1388 |
+
if level == _len_sources:
|
| 1389 |
+
source = self.input_proj[level](features[-1][0])
|
| 1390 |
+
else:
|
| 1391 |
+
source = self.input_proj[level](sources[-1])
|
| 1392 |
+
mask = nn.functional.interpolate(pixel_mask[None].to(pixel_values.dtype), size=source.shape[-2:]).to(
|
| 1393 |
+
torch.bool
|
| 1394 |
+
)[0]
|
| 1395 |
+
pos_l = self.position_embedding(
|
| 1396 |
+
shape=source.shape, device=device, dtype=pixel_values.dtype, mask=mask
|
| 1397 |
+
).to(source.dtype)
|
| 1398 |
+
sources.append(source)
|
| 1399 |
+
masks.append(mask)
|
| 1400 |
+
position_embeddings_list.append(pos_l)
|
| 1401 |
+
|
| 1402 |
+
# Create queries
|
| 1403 |
+
query_embeds = None
|
| 1404 |
+
if not self.config.two_stage:
|
| 1405 |
+
query_embeds = self.query_position_embeddings.weight
|
| 1406 |
+
|
| 1407 |
+
# Prepare encoder inputs (by flattening)
|
| 1408 |
+
source_flatten = []
|
| 1409 |
+
mask_flatten = []
|
| 1410 |
+
lvl_pos_embed_flatten = []
|
| 1411 |
+
spatial_shapes_list = []
|
| 1412 |
+
for level, (source, mask, pos_embed) in enumerate(zip(sources, masks, position_embeddings_list)):
|
| 1413 |
+
batch_size, num_channels, height, width = source.shape
|
| 1414 |
+
spatial_shape = (height, width)
|
| 1415 |
+
spatial_shapes_list.append(spatial_shape)
|
| 1416 |
+
source = source.flatten(2).transpose(1, 2)
|
| 1417 |
+
pos_embed = pos_embed.flatten(2).transpose(1, 2)
|
| 1418 |
+
mask = mask.flatten(1)
|
| 1419 |
+
lvl_pos_embed = pos_embed + self.level_embed[level].view(1, 1, -1)
|
| 1420 |
+
lvl_pos_embed_flatten.append(lvl_pos_embed)
|
| 1421 |
+
source_flatten.append(source)
|
| 1422 |
+
mask_flatten.append(mask)
|
| 1423 |
+
source_flatten = torch.cat(source_flatten, 1)
|
| 1424 |
+
mask_flatten = torch.cat(mask_flatten, 1)
|
| 1425 |
+
lvl_pos_embed_flatten = torch.cat(lvl_pos_embed_flatten, 1)
|
| 1426 |
+
spatial_shapes = torch.as_tensor(spatial_shapes_list, dtype=torch.long, device=source_flatten.device)
|
| 1427 |
+
level_start_index = torch.cat((spatial_shapes.new_zeros((1,)), spatial_shapes.prod(1).cumsum(0)[:-1]))
|
| 1428 |
+
valid_ratios = torch.stack([self.get_valid_ratio(m, dtype=source_flatten.dtype) for m in masks], 1)
|
| 1429 |
+
|
| 1430 |
+
# Fourth, sent source_flatten + mask_flatten + lvl_pos_embed_flatten (backbone + proj layer output) through encoder
|
| 1431 |
+
# Also provide spatial_shapes, level_start_index and valid_ratios
|
| 1432 |
+
if encoder_outputs is None:
|
| 1433 |
+
encoder_outputs = self.encoder(
|
| 1434 |
+
inputs_embeds=source_flatten,
|
| 1435 |
+
attention_mask=mask_flatten,
|
| 1436 |
+
spatial_position_embeddings=lvl_pos_embed_flatten,
|
| 1437 |
+
spatial_shapes=spatial_shapes,
|
| 1438 |
+
spatial_shapes_list=spatial_shapes_list,
|
| 1439 |
+
level_start_index=level_start_index,
|
| 1440 |
+
valid_ratios=valid_ratios,
|
| 1441 |
+
**kwargs,
|
| 1442 |
+
)
|
| 1443 |
+
|
| 1444 |
+
# Fifth, prepare decoder inputs
|
| 1445 |
+
batch_size, _, num_channels = encoder_outputs[0].shape
|
| 1446 |
+
enc_outputs_class = None
|
| 1447 |
+
enc_outputs_coord_logits = None
|
| 1448 |
+
if self.config.two_stage:
|
| 1449 |
+
object_query_embedding, output_proposals = self.gen_encoder_output_proposals(
|
| 1450 |
+
encoder_outputs[0], ~mask_flatten, spatial_shapes_list
|
| 1451 |
+
)
|
| 1452 |
+
|
| 1453 |
+
# hack implementation for two-stage Deformable DETR
|
| 1454 |
+
# apply a detection head to each pixel (A.4 in paper)
|
| 1455 |
+
# linear projection for bounding box binary classification (i.e. foreground and background)
|
| 1456 |
+
enc_outputs_class = self.decoder.class_embed[-1](object_query_embedding)
|
| 1457 |
+
# 3-layer FFN to predict bounding boxes coordinates (bbox regression branch)
|
| 1458 |
+
delta_bbox = self.decoder.bbox_embed[-1](object_query_embedding)
|
| 1459 |
+
enc_outputs_coord_logits = delta_bbox + output_proposals
|
| 1460 |
+
|
| 1461 |
+
# only keep top scoring `config.two_stage_num_proposals` proposals
|
| 1462 |
+
topk = self.config.two_stage_num_proposals
|
| 1463 |
+
topk_proposals = torch.topk(enc_outputs_class[..., 0], topk, dim=1)[1]
|
| 1464 |
+
topk_coords_logits = torch.gather(
|
| 1465 |
+
enc_outputs_coord_logits,
|
| 1466 |
+
1,
|
| 1467 |
+
topk_proposals.unsqueeze(-1).repeat(1, 1, 4),
|
| 1468 |
+
)
|
| 1469 |
+
|
| 1470 |
+
topk_coords_logits = topk_coords_logits.detach()
|
| 1471 |
+
reference_points = topk_coords_logits.sigmoid()
|
| 1472 |
+
init_reference_points = reference_points
|
| 1473 |
+
pos_trans_out = self.pos_trans_norm(self.pos_trans(self.get_proposal_pos_embed(topk_coords_logits)))
|
| 1474 |
+
query_embed, target = torch.split(pos_trans_out, num_channels, dim=2)
|
| 1475 |
+
else:
|
| 1476 |
+
query_embed, target = torch.split(query_embeds, num_channels, dim=1)
|
| 1477 |
+
query_embed = query_embed.unsqueeze(0).expand(batch_size, -1, -1)
|
| 1478 |
+
target = target.unsqueeze(0).expand(batch_size, -1, -1)
|
| 1479 |
+
reference_points = self.reference_points(query_embed).sigmoid()
|
| 1480 |
+
init_reference_points = reference_points
|
| 1481 |
+
|
| 1482 |
+
decoder_outputs = self.decoder(
|
| 1483 |
+
inputs_embeds=target,
|
| 1484 |
+
object_queries_position_embeddings=query_embed,
|
| 1485 |
+
encoder_hidden_states=encoder_outputs[0],
|
| 1486 |
+
encoder_attention_mask=mask_flatten,
|
| 1487 |
+
reference_points=reference_points,
|
| 1488 |
+
spatial_shapes=spatial_shapes,
|
| 1489 |
+
spatial_shapes_list=spatial_shapes_list,
|
| 1490 |
+
level_start_index=level_start_index,
|
| 1491 |
+
valid_ratios=valid_ratios,
|
| 1492 |
+
**kwargs,
|
| 1493 |
+
)
|
| 1494 |
+
|
| 1495 |
+
return DeformableDetrModelOutput(
|
| 1496 |
+
init_reference_points=init_reference_points,
|
| 1497 |
+
last_hidden_state=decoder_outputs.last_hidden_state,
|
| 1498 |
+
intermediate_hidden_states=decoder_outputs.intermediate_hidden_states,
|
| 1499 |
+
intermediate_reference_points=decoder_outputs.intermediate_reference_points,
|
| 1500 |
+
decoder_hidden_states=decoder_outputs.hidden_states,
|
| 1501 |
+
decoder_attentions=decoder_outputs.attentions,
|
| 1502 |
+
cross_attentions=decoder_outputs.cross_attentions,
|
| 1503 |
+
encoder_last_hidden_state=encoder_outputs.last_hidden_state,
|
| 1504 |
+
encoder_hidden_states=encoder_outputs.hidden_states,
|
| 1505 |
+
encoder_attentions=encoder_outputs.attentions,
|
| 1506 |
+
enc_outputs_class=enc_outputs_class,
|
| 1507 |
+
enc_outputs_coord_logits=enc_outputs_coord_logits,
|
| 1508 |
+
)
|
| 1509 |
+
|
| 1510 |
+
|
| 1511 |
+
class DeformableDetrMLPPredictionHead(nn.Module):
|
| 1512 |
+
"""
|
| 1513 |
+
Very simple multi-layer perceptron (MLP, also called FFN), used to predict the normalized center coordinates,
|
| 1514 |
+
height and width of a bounding box w.r.t. an image.
|
| 1515 |
+
|
| 1516 |
+
"""
|
| 1517 |
+
|
| 1518 |
+
def __init__(self, input_dim, hidden_dim, output_dim, num_layers):
|
| 1519 |
+
super().__init__()
|
| 1520 |
+
self.num_layers = num_layers
|
| 1521 |
+
h = [hidden_dim] * (num_layers - 1)
|
| 1522 |
+
self.layers = nn.ModuleList(nn.Linear(n, k) for n, k in zip([input_dim] + h, h + [output_dim]))
|
| 1523 |
+
|
| 1524 |
+
def forward(self, x):
|
| 1525 |
+
for i, layer in enumerate(self.layers):
|
| 1526 |
+
x = nn.functional.relu(layer(x)) if i < self.num_layers - 1 else layer(x)
|
| 1527 |
+
return x
|
| 1528 |
+
|
| 1529 |
+
|
| 1530 |
+
@auto_docstring(
|
| 1531 |
+
custom_intro="""
|
| 1532 |
+
Deformable DETR Model (consisting of a backbone and encoder-decoder Transformer) with object detection heads on
|
| 1533 |
+
top, for tasks such as COCO detection.
|
| 1534 |
+
"""
|
| 1535 |
+
)
|
| 1536 |
+
class DeformableDetrForObjectDetection(DeformableDetrPreTrainedModel):
|
| 1537 |
+
# When using clones, all layers > 0 will be clones, but layer 0 *is* required
|
| 1538 |
+
# We can't initialize the model on meta device as some weights are modified during the initialization
|
| 1539 |
+
_no_split_modules = None
|
| 1540 |
+
_tied_weights_keys = {
|
| 1541 |
+
r"bbox_embed.(?![0])\d+": "bbox_embed.0",
|
| 1542 |
+
r"class_embed.(?![0])\d+": "class_embed.0",
|
| 1543 |
+
}
|
| 1544 |
+
|
| 1545 |
+
def __init__(self, config: DeformableDetrConfig):
|
| 1546 |
+
super().__init__(config)
|
| 1547 |
+
# Deformable DETR encoder-decoder model
|
| 1548 |
+
self.model = DeformableDetrModel(config)
|
| 1549 |
+
# Detection heads on top
|
| 1550 |
+
# if two-stage, the last class_embed and bbox_embed is for region proposal generation
|
| 1551 |
+
num_pred = (config.decoder_layers + 1) if config.two_stage else config.decoder_layers
|
| 1552 |
+
self.class_embed = nn.ModuleList([nn.Linear(config.d_model, config.num_labels) for _ in range(num_pred)])
|
| 1553 |
+
self.bbox_embed = nn.ModuleList(
|
| 1554 |
+
[
|
| 1555 |
+
DeformableDetrMLPPredictionHead(
|
| 1556 |
+
input_dim=config.d_model,
|
| 1557 |
+
hidden_dim=config.d_model,
|
| 1558 |
+
output_dim=4,
|
| 1559 |
+
num_layers=3,
|
| 1560 |
+
)
|
| 1561 |
+
for _ in range(num_pred)
|
| 1562 |
+
]
|
| 1563 |
+
)
|
| 1564 |
+
# Convert to instance attribute before modifying
|
| 1565 |
+
self._tied_weights_keys = self._tied_weights_keys.copy()
|
| 1566 |
+
if config.with_box_refine:
|
| 1567 |
+
self.model.decoder.bbox_embed = self.bbox_embed
|
| 1568 |
+
self._tied_weights_keys["bbox_embed"] = "model.decoder.bbox_embed"
|
| 1569 |
+
if config.two_stage:
|
| 1570 |
+
self.model.decoder.class_embed = self.class_embed
|
| 1571 |
+
self._tied_weights_keys["class_embed"] = "model.decoder.class_embed"
|
| 1572 |
+
self.post_init()
|
| 1573 |
+
|
| 1574 |
+
@auto_docstring
|
| 1575 |
+
@can_return_tuple
|
| 1576 |
+
def forward(
|
| 1577 |
+
self,
|
| 1578 |
+
pixel_values: torch.FloatTensor,
|
| 1579 |
+
pixel_mask: torch.LongTensor | None = None,
|
| 1580 |
+
decoder_attention_mask: torch.FloatTensor | None = None,
|
| 1581 |
+
encoder_outputs: torch.FloatTensor | None = None,
|
| 1582 |
+
inputs_embeds: torch.FloatTensor | None = None,
|
| 1583 |
+
decoder_inputs_embeds: torch.FloatTensor | None = None,
|
| 1584 |
+
labels: list[dict] | None = None,
|
| 1585 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 1586 |
+
) -> tuple[torch.FloatTensor] | DeformableDetrObjectDetectionOutput:
|
| 1587 |
+
r"""
|
| 1588 |
+
decoder_attention_mask (`torch.FloatTensor` of shape `(batch_size, num_queries)`, *optional*):
|
| 1589 |
+
Not used by default. Can be used to mask object queries.
|
| 1590 |
+
inputs_embeds (`torch.FloatTensor` of shape `(batch_size, sequence_length, hidden_size)`, *optional*):
|
| 1591 |
+
Optionally, instead of passing the flattened feature map (output of the backbone + projection layer), you
|
| 1592 |
+
can choose to directly pass a flattened representation of an image.
|
| 1593 |
+
decoder_inputs_embeds (`torch.FloatTensor` of shape `(batch_size, num_queries, hidden_size)`, *optional*):
|
| 1594 |
+
Optionally, instead of initializing the queries with a tensor of zeros, you can choose to directly pass an
|
| 1595 |
+
embedded representation.
|
| 1596 |
+
labels (`list[Dict]` of len `(batch_size,)`, *optional*):
|
| 1597 |
+
Labels for computing the bipartite matching loss. List of dicts, each dictionary containing at least the
|
| 1598 |
+
following 2 keys: 'class_labels' and 'boxes' (the class labels and bounding boxes of an image in the batch
|
| 1599 |
+
respectively). The class labels themselves should be a `torch.LongTensor` of len `(number of bounding boxes
|
| 1600 |
+
in the image,)` and the boxes a `torch.FloatTensor` of shape `(number of bounding boxes in the image, 4)`.
|
| 1601 |
+
|
| 1602 |
+
Examples:
|
| 1603 |
+
|
| 1604 |
+
```python
|
| 1605 |
+
>>> from transformers import AutoImageProcessor, DeformableDetrForObjectDetection
|
| 1606 |
+
>>> from PIL import Image
|
| 1607 |
+
>>> import httpx
|
| 1608 |
+
>>> from io imoprt BytesIO
|
| 1609 |
+
|
| 1610 |
+
>>> url = "http://images.cocodataset.org/val2017/000000039769.jpg"
|
| 1611 |
+
>>> with httpx.stream("GET", url) as response:
|
| 1612 |
+
... image = Image.open(BytesIO(response.read()))
|
| 1613 |
+
|
| 1614 |
+
>>> image_processor = AutoImageProcessor.from_pretrained("SenseTime/deformable-detr")
|
| 1615 |
+
>>> model = DeformableDetrForObjectDetection.from_pretrained("SenseTime/deformable-detr")
|
| 1616 |
+
|
| 1617 |
+
>>> inputs = image_processor(images=image, return_tensors="pt")
|
| 1618 |
+
>>> outputs = model(**inputs)
|
| 1619 |
+
|
| 1620 |
+
>>> # convert outputs (bounding boxes and class logits) to Pascal VOC format (xmin, ymin, xmax, ymax)
|
| 1621 |
+
>>> target_sizes = torch.tensor([image.size[::-1]])
|
| 1622 |
+
>>> results = image_processor.post_process_object_detection(outputs, threshold=0.5, target_sizes=target_sizes)[
|
| 1623 |
+
... 0
|
| 1624 |
+
... ]
|
| 1625 |
+
>>> for score, label, box in zip(results["scores"], results["labels"], results["boxes"]):
|
| 1626 |
+
... box = [round(i, 2) for i in box.tolist()]
|
| 1627 |
+
... print(
|
| 1628 |
+
... f"Detected {model.config.id2label[label.item()]} with confidence "
|
| 1629 |
+
... f"{round(score.item(), 3)} at location {box}"
|
| 1630 |
+
... )
|
| 1631 |
+
Detected cat with confidence 0.8 at location [16.5, 52.84, 318.25, 470.78]
|
| 1632 |
+
Detected cat with confidence 0.789 at location [342.19, 24.3, 640.02, 372.25]
|
| 1633 |
+
Detected remote with confidence 0.633 at location [40.79, 72.78, 176.76, 117.25]
|
| 1634 |
+
```"""
|
| 1635 |
+
# First, sent images through DETR base model to obtain encoder + decoder outputs
|
| 1636 |
+
outputs = self.model(
|
| 1637 |
+
pixel_values,
|
| 1638 |
+
pixel_mask=pixel_mask,
|
| 1639 |
+
decoder_attention_mask=decoder_attention_mask,
|
| 1640 |
+
encoder_outputs=encoder_outputs,
|
| 1641 |
+
inputs_embeds=inputs_embeds,
|
| 1642 |
+
decoder_inputs_embeds=decoder_inputs_embeds,
|
| 1643 |
+
**kwargs,
|
| 1644 |
+
)
|
| 1645 |
+
|
| 1646 |
+
hidden_states = outputs.intermediate_hidden_states
|
| 1647 |
+
init_reference = outputs.init_reference_points
|
| 1648 |
+
inter_references = outputs.intermediate_reference_points
|
| 1649 |
+
|
| 1650 |
+
# class logits + predicted bounding boxes
|
| 1651 |
+
outputs_classes = []
|
| 1652 |
+
outputs_coords = []
|
| 1653 |
+
|
| 1654 |
+
for level in range(hidden_states.shape[1]):
|
| 1655 |
+
if level == 0:
|
| 1656 |
+
reference = init_reference
|
| 1657 |
+
else:
|
| 1658 |
+
reference = inter_references[:, level - 1]
|
| 1659 |
+
reference = inverse_sigmoid(reference)
|
| 1660 |
+
outputs_class = self.class_embed[level](hidden_states[:, level])
|
| 1661 |
+
delta_bbox = self.bbox_embed[level](hidden_states[:, level])
|
| 1662 |
+
if reference.shape[-1] == 4:
|
| 1663 |
+
outputs_coord_logits = delta_bbox + reference
|
| 1664 |
+
elif reference.shape[-1] == 2:
|
| 1665 |
+
delta_bbox[..., :2] += reference
|
| 1666 |
+
outputs_coord_logits = delta_bbox
|
| 1667 |
+
else:
|
| 1668 |
+
raise ValueError(f"reference.shape[-1] should be 4 or 2, but got {reference.shape[-1]}")
|
| 1669 |
+
outputs_coord = outputs_coord_logits.sigmoid()
|
| 1670 |
+
outputs_classes.append(outputs_class)
|
| 1671 |
+
outputs_coords.append(outputs_coord)
|
| 1672 |
+
outputs_class = torch.stack(outputs_classes)
|
| 1673 |
+
outputs_coord = torch.stack(outputs_coords)
|
| 1674 |
+
|
| 1675 |
+
logits = outputs_class[-1]
|
| 1676 |
+
pred_boxes = outputs_coord[-1]
|
| 1677 |
+
|
| 1678 |
+
loss, loss_dict, auxiliary_outputs = None, None, None
|
| 1679 |
+
if labels is not None:
|
| 1680 |
+
loss, loss_dict, auxiliary_outputs = self.loss_function(
|
| 1681 |
+
logits,
|
| 1682 |
+
labels,
|
| 1683 |
+
self.device,
|
| 1684 |
+
pred_boxes,
|
| 1685 |
+
self.config,
|
| 1686 |
+
outputs_class,
|
| 1687 |
+
outputs_coord,
|
| 1688 |
+
)
|
| 1689 |
+
|
| 1690 |
+
return DeformableDetrObjectDetectionOutput(
|
| 1691 |
+
loss=loss,
|
| 1692 |
+
loss_dict=loss_dict,
|
| 1693 |
+
logits=logits,
|
| 1694 |
+
pred_boxes=pred_boxes,
|
| 1695 |
+
auxiliary_outputs=auxiliary_outputs,
|
| 1696 |
+
last_hidden_state=outputs.last_hidden_state,
|
| 1697 |
+
decoder_hidden_states=outputs.decoder_hidden_states,
|
| 1698 |
+
decoder_attentions=outputs.decoder_attentions,
|
| 1699 |
+
cross_attentions=outputs.cross_attentions,
|
| 1700 |
+
encoder_last_hidden_state=outputs.encoder_last_hidden_state,
|
| 1701 |
+
encoder_hidden_states=outputs.encoder_hidden_states,
|
| 1702 |
+
encoder_attentions=outputs.encoder_attentions,
|
| 1703 |
+
intermediate_hidden_states=outputs.intermediate_hidden_states,
|
| 1704 |
+
intermediate_reference_points=outputs.intermediate_reference_points,
|
| 1705 |
+
init_reference_points=outputs.init_reference_points,
|
| 1706 |
+
enc_outputs_class=outputs.enc_outputs_class,
|
| 1707 |
+
enc_outputs_coord_logits=outputs.enc_outputs_coord_logits,
|
| 1708 |
+
)
|
| 1709 |
+
|
| 1710 |
+
|
| 1711 |
+
__all__ = ["DeformableDetrForObjectDetection", "DeformableDetrModel", "DeformableDetrPreTrainedModel"]
|
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/models/dpt/__init__.py
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2024 The HuggingFace Team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
from typing import TYPE_CHECKING
|
| 15 |
+
|
| 16 |
+
from ...utils import _LazyModule
|
| 17 |
+
from ...utils.import_utils import define_import_structure
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
if TYPE_CHECKING:
|
| 21 |
+
from .configuration_dpt import *
|
| 22 |
+
from .image_processing_dpt import *
|
| 23 |
+
from .image_processing_pil_dpt import *
|
| 24 |
+
from .modeling_dpt import *
|
| 25 |
+
else:
|
| 26 |
+
import sys
|
| 27 |
+
|
| 28 |
+
_file = globals()["__file__"]
|
| 29 |
+
sys.modules[__name__] = _LazyModule(__name__, _file, define_import_structure(_file), module_spec=__spec__)
|
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/models/dpt/configuration_dpt.py
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2022 The HuggingFace Inc. team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
"""DPT model configuration"""
|
| 15 |
+
|
| 16 |
+
from huggingface_hub.dataclasses import strict
|
| 17 |
+
|
| 18 |
+
from ...backbone_utils import consolidate_backbone_kwargs_to_config
|
| 19 |
+
from ...configuration_utils import PreTrainedConfig
|
| 20 |
+
from ...utils import auto_docstring
|
| 21 |
+
from ..auto.configuration_auto import AutoConfig
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
@auto_docstring(checkpoint="Intel/dpt-large")
|
| 25 |
+
@strict
|
| 26 |
+
class DPTConfig(PreTrainedConfig):
|
| 27 |
+
r"""
|
| 28 |
+
is_hybrid (`bool`, *optional*, defaults to `False`):
|
| 29 |
+
Whether to use a hybrid backbone. Useful in the context of loading DPT-Hybrid models.
|
| 30 |
+
backbone_out_indices (`list[int]`, *optional*, defaults to `[2, 5, 8, 11]`):
|
| 31 |
+
Indices of the intermediate hidden states to use from backbone.
|
| 32 |
+
readout_type (`str`, *optional*, defaults to `"project"`):
|
| 33 |
+
The readout type to use when processing the readout token (CLS token) of the intermediate hidden states of
|
| 34 |
+
the ViT backbone. Can be one of [`"ignore"`, `"add"`, `"project"`].
|
| 35 |
+
- "ignore" simply ignores the CLS token.
|
| 36 |
+
- "add" passes the information from the CLS token to all other tokens by adding the representations.
|
| 37 |
+
- "project" passes information to the other tokens by concatenating the readout to all other tokens before
|
| 38 |
+
projecting the
|
| 39 |
+
representation to the original feature dimension D using a linear layer followed by a GELU non-linearity.
|
| 40 |
+
reassemble_factors (`list[int]`, *optional*, defaults to `[4, 2, 1, 0.5]`):
|
| 41 |
+
The up/downsampling factors of the reassemble layers.
|
| 42 |
+
neck_hidden_sizes (`list[str]`, *optional*, defaults to `[96, 192, 384, 768]`):
|
| 43 |
+
The hidden sizes to project to for the feature maps of the backbone.
|
| 44 |
+
fusion_hidden_size (`int`, *optional*, defaults to 256):
|
| 45 |
+
The number of channels before fusion.
|
| 46 |
+
head_in_index (`int`, *optional*, defaults to -1):
|
| 47 |
+
The index of the features to use in the heads.
|
| 48 |
+
use_batch_norm_in_fusion_residual (`bool`, *optional*, defaults to `False`):
|
| 49 |
+
Whether to use batch normalization in the pre-activate residual units of the fusion blocks.
|
| 50 |
+
use_bias_in_fusion_residual (`bool`, *optional*, defaults to `True`):
|
| 51 |
+
Whether to use bias in the pre-activate residual units of the fusion blocks.
|
| 52 |
+
add_projection (`bool`, *optional*, defaults to `False`):
|
| 53 |
+
Whether to add a projection layer before the depth estimation head.
|
| 54 |
+
use_auxiliary_head (`bool`, *optional*, defaults to `True`):
|
| 55 |
+
Whether to use an auxiliary head during training.
|
| 56 |
+
auxiliary_loss_weight (`float`, *optional*, defaults to 0.4):
|
| 57 |
+
Weight of the cross-entropy loss of the auxiliary head.
|
| 58 |
+
semantic_classifier_dropout (`float`, *optional*, defaults to 0.1):
|
| 59 |
+
The dropout ratio for the semantic classification head.
|
| 60 |
+
backbone_featmap_shape (`list[int]`, *optional*, defaults to `[1, 1024, 24, 24]`):
|
| 61 |
+
Used only for the `hybrid` embedding type. The shape of the feature maps of the backbone.
|
| 62 |
+
neck_ignore_stages (`list[int]`, *optional*, defaults to `[0, 1]`):
|
| 63 |
+
Used only for the `hybrid` embedding type. The stages of the readout layers to ignore.
|
| 64 |
+
pooler_output_size (`int`, *optional*):
|
| 65 |
+
Dimensionality of the pooler layer. If None, defaults to `hidden_size`.
|
| 66 |
+
pooler_act (`str`, *optional*, defaults to `"tanh"`):
|
| 67 |
+
The activation function to be used by the pooler.
|
| 68 |
+
|
| 69 |
+
Example:
|
| 70 |
+
|
| 71 |
+
```python
|
| 72 |
+
>>> from transformers import DPTModel, DPTConfig
|
| 73 |
+
|
| 74 |
+
>>> # Initializing a DPT dpt-large style configuration
|
| 75 |
+
>>> configuration = DPTConfig()
|
| 76 |
+
|
| 77 |
+
>>> # Initializing a model from the dpt-large style configuration
|
| 78 |
+
>>> model = DPTModel(configuration)
|
| 79 |
+
|
| 80 |
+
>>> # Accessing the model configuration
|
| 81 |
+
>>> configuration = model.config
|
| 82 |
+
```"""
|
| 83 |
+
|
| 84 |
+
model_type = "dpt"
|
| 85 |
+
sub_configs = {"backbone_config": AutoConfig}
|
| 86 |
+
|
| 87 |
+
# NOTE: some values are typed as `None` on purpose
|
| 88 |
+
# DPT creates one of: backbone or the general model only
|
| 89 |
+
# so official checkpoint saved them as `None`
|
| 90 |
+
hidden_size: int = 768
|
| 91 |
+
num_hidden_layers: None | int = 12
|
| 92 |
+
num_attention_heads: int | None = 12
|
| 93 |
+
intermediate_size: int | None = 3072
|
| 94 |
+
hidden_act: str = "gelu"
|
| 95 |
+
hidden_dropout_prob: float | int | None = 0.0
|
| 96 |
+
attention_probs_dropout_prob: float | int | None = 0.0
|
| 97 |
+
initializer_range: float = 0.02
|
| 98 |
+
layer_norm_eps: float | None = 1e-12
|
| 99 |
+
image_size: int | list[int] | tuple[int, int] | None = 384
|
| 100 |
+
patch_size: int | list[int] | tuple[int, int] | None = 16
|
| 101 |
+
num_channels: int | None = 3
|
| 102 |
+
is_hybrid: bool = False
|
| 103 |
+
qkv_bias: bool | None = True
|
| 104 |
+
backbone_out_indices: list[int] | tuple[int, ...] | None = (2, 5, 8, 11)
|
| 105 |
+
readout_type: str = "project"
|
| 106 |
+
reassemble_factors: list[int | float] | tuple[int | float, ...] = (4, 2, 1, 0.5)
|
| 107 |
+
neck_hidden_sizes: list[int] | tuple[int, ...] = (96, 192, 384, 768)
|
| 108 |
+
fusion_hidden_size: int = 256
|
| 109 |
+
head_in_index: int = -1
|
| 110 |
+
use_batch_norm_in_fusion_residual: bool | None = False
|
| 111 |
+
use_bias_in_fusion_residual: bool | None = None
|
| 112 |
+
add_projection: bool = False
|
| 113 |
+
use_auxiliary_head: bool | None = True
|
| 114 |
+
auxiliary_loss_weight: float = 0.4
|
| 115 |
+
semantic_loss_ignore_index: int = 255
|
| 116 |
+
semantic_classifier_dropout: float | int = 0.1
|
| 117 |
+
backbone_featmap_shape: list[int] | tuple[int, ...] | None = (1, 1024, 24, 24)
|
| 118 |
+
neck_ignore_stages: list[int] | tuple[int, ...] = (0, 1)
|
| 119 |
+
backbone_config: dict | PreTrainedConfig | None = None
|
| 120 |
+
pooler_output_size: int | None = None
|
| 121 |
+
pooler_act: str = "tanh"
|
| 122 |
+
|
| 123 |
+
def __post_init__(self, **kwargs):
|
| 124 |
+
if self.readout_type not in ["ignore", "add", "project"]:
|
| 125 |
+
raise ValueError("Readout_type must be one of ['ignore', 'add', 'project']")
|
| 126 |
+
|
| 127 |
+
if self.is_hybrid:
|
| 128 |
+
if isinstance(self.backbone_config, dict):
|
| 129 |
+
self.backbone_config.setdefault("model_type", "bit")
|
| 130 |
+
|
| 131 |
+
self.backbone_config, kwargs = consolidate_backbone_kwargs_to_config(
|
| 132 |
+
backbone_config=self.backbone_config,
|
| 133 |
+
default_config_type="bit",
|
| 134 |
+
default_config_kwargs={
|
| 135 |
+
"global_padding": "same",
|
| 136 |
+
"layer_type": "bottleneck",
|
| 137 |
+
"depths": [3, 4, 9],
|
| 138 |
+
"out_features": ["stage1", "stage2", "stage3"],
|
| 139 |
+
"embedding_dynamic_padding": True,
|
| 140 |
+
},
|
| 141 |
+
**kwargs,
|
| 142 |
+
)
|
| 143 |
+
if self.readout_type != "project":
|
| 144 |
+
raise ValueError("Readout type must be 'project' when using `DPT-hybrid` mode.")
|
| 145 |
+
elif kwargs.get("backbone") is not None or self.backbone_config is not None:
|
| 146 |
+
self.backbone_config, kwargs = consolidate_backbone_kwargs_to_config(
|
| 147 |
+
backbone_config=self.backbone_config,
|
| 148 |
+
**kwargs,
|
| 149 |
+
)
|
| 150 |
+
self.backbone_out_indices = None
|
| 151 |
+
|
| 152 |
+
self.backbone_featmap_shape = self.backbone_featmap_shape if self.is_hybrid else None
|
| 153 |
+
self.neck_ignore_stages = self.neck_ignore_stages if self.is_hybrid else []
|
| 154 |
+
self.pooler_output_size = self.pooler_output_size if self.pooler_output_size else self.hidden_size
|
| 155 |
+
super().__post_init__(**kwargs)
|
| 156 |
+
|
| 157 |
+
|
| 158 |
+
__all__ = ["DPTConfig"]
|
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/models/dpt/image_processing_pil_dpt.py
ADDED
|
@@ -0,0 +1,312 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2024 The HuggingFace Inc. team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
"""Image processor class for DPT."""
|
| 15 |
+
|
| 16 |
+
import math
|
| 17 |
+
from collections.abc import Iterable
|
| 18 |
+
from typing import TYPE_CHECKING
|
| 19 |
+
|
| 20 |
+
import numpy as np
|
| 21 |
+
|
| 22 |
+
from ...image_processing_backends import PilBackend
|
| 23 |
+
from ...image_processing_utils import BatchFeature
|
| 24 |
+
from ...image_transforms import pad as np_pad
|
| 25 |
+
from ...image_utils import (
|
| 26 |
+
IMAGENET_STANDARD_MEAN,
|
| 27 |
+
IMAGENET_STANDARD_STD,
|
| 28 |
+
ChannelDimension,
|
| 29 |
+
ImageInput,
|
| 30 |
+
PILImageResampling,
|
| 31 |
+
SizeDict,
|
| 32 |
+
)
|
| 33 |
+
from ...processing_utils import ImagesKwargs, Unpack
|
| 34 |
+
from ...utils import TensorType, auto_docstring, logging
|
| 35 |
+
from ...utils.import_utils import requires
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
if TYPE_CHECKING:
|
| 39 |
+
from ...modeling_outputs import DepthEstimatorOutput
|
| 40 |
+
|
| 41 |
+
logger = logging.get_logger(__name__)
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
# Adapted from transformers.models.dpt.image_processing_dpt.DPTImageProcessorKwargs
|
| 45 |
+
class DPTImageProcessorKwargs(ImagesKwargs, total=False):
|
| 46 |
+
r"""
|
| 47 |
+
ensure_multiple_of (`int`, *optional*, defaults to 1):
|
| 48 |
+
If `do_resize` is `True`, the image is resized to a size that is a multiple of this value. Can be overridden
|
| 49 |
+
by `ensure_multiple_of` in `preprocess`.
|
| 50 |
+
keep_aspect_ratio (`bool`, *optional*, defaults to `False`):
|
| 51 |
+
If `True`, the image is resized to the largest possible size such that the aspect ratio is preserved. Can
|
| 52 |
+
be overridden by `keep_aspect_ratio` in `preprocess`.
|
| 53 |
+
do_reduce_labels (`bool`, *optional*, defaults to `self.do_reduce_labels`):
|
| 54 |
+
Whether or not to reduce all label values of segmentation maps by 1. Usually used for datasets where 0
|
| 55 |
+
is used for background, and background itself is not included in all classes of a dataset (e.g.
|
| 56 |
+
ADE20k). The background label will be replaced by 255.
|
| 57 |
+
"""
|
| 58 |
+
|
| 59 |
+
ensure_multiple_of: int
|
| 60 |
+
size_divisor: int
|
| 61 |
+
keep_aspect_ratio: bool
|
| 62 |
+
do_reduce_labels: bool
|
| 63 |
+
|
| 64 |
+
|
| 65 |
+
# Adapted from transformers.models.dpt.image_processing_dpt.get_resize_output_image_size
|
| 66 |
+
def get_resize_output_image_size(
|
| 67 |
+
input_image: np.ndarray,
|
| 68 |
+
output_size: int | Iterable[int],
|
| 69 |
+
keep_aspect_ratio: bool,
|
| 70 |
+
multiple: int,
|
| 71 |
+
) -> SizeDict:
|
| 72 |
+
def constrain_to_multiple_of(val, multiple, min_val=0, max_val=None):
|
| 73 |
+
x = round(val / multiple) * multiple
|
| 74 |
+
|
| 75 |
+
if max_val is not None and x > max_val:
|
| 76 |
+
x = math.floor(val / multiple) * multiple
|
| 77 |
+
|
| 78 |
+
if x < min_val:
|
| 79 |
+
x = math.ceil(val / multiple) * multiple
|
| 80 |
+
|
| 81 |
+
return x
|
| 82 |
+
|
| 83 |
+
input_height, input_width = input_image.shape[-2:]
|
| 84 |
+
output_height, output_width = output_size
|
| 85 |
+
|
| 86 |
+
# determine new height and width
|
| 87 |
+
scale_height = output_height / input_height
|
| 88 |
+
scale_width = output_width / input_width
|
| 89 |
+
|
| 90 |
+
if keep_aspect_ratio:
|
| 91 |
+
# scale as little as possible
|
| 92 |
+
if abs(1 - scale_width) < abs(1 - scale_height):
|
| 93 |
+
# fit width
|
| 94 |
+
scale_height = scale_width
|
| 95 |
+
else:
|
| 96 |
+
# fit height
|
| 97 |
+
scale_width = scale_height
|
| 98 |
+
|
| 99 |
+
new_height = constrain_to_multiple_of(scale_height * input_height, multiple=multiple)
|
| 100 |
+
new_width = constrain_to_multiple_of(scale_width * input_width, multiple=multiple)
|
| 101 |
+
|
| 102 |
+
return SizeDict(height=new_height, width=new_width)
|
| 103 |
+
|
| 104 |
+
|
| 105 |
+
@auto_docstring
|
| 106 |
+
class DPTImageProcessorPil(PilBackend):
|
| 107 |
+
"""PIL backend for DPT with custom resize and pad."""
|
| 108 |
+
|
| 109 |
+
valid_kwargs = DPTImageProcessorKwargs
|
| 110 |
+
|
| 111 |
+
resample = PILImageResampling.BICUBIC
|
| 112 |
+
image_mean = IMAGENET_STANDARD_MEAN
|
| 113 |
+
image_std = IMAGENET_STANDARD_STD
|
| 114 |
+
size = {"height": 384, "width": 384}
|
| 115 |
+
default_to_square = True
|
| 116 |
+
do_resize = True
|
| 117 |
+
do_rescale = True
|
| 118 |
+
do_normalize = True
|
| 119 |
+
do_pad = False
|
| 120 |
+
rescale_factor = 1 / 255
|
| 121 |
+
ensure_multiple_of = 1
|
| 122 |
+
keep_aspect_ratio = False
|
| 123 |
+
|
| 124 |
+
def __init__(self, **kwargs: Unpack[DPTImageProcessorKwargs]):
|
| 125 |
+
super().__init__(**kwargs)
|
| 126 |
+
|
| 127 |
+
@auto_docstring
|
| 128 |
+
def preprocess(
|
| 129 |
+
self,
|
| 130 |
+
images: ImageInput,
|
| 131 |
+
segmentation_maps: ImageInput | None = None,
|
| 132 |
+
**kwargs: Unpack[DPTImageProcessorKwargs],
|
| 133 |
+
) -> BatchFeature:
|
| 134 |
+
r"""
|
| 135 |
+
segmentation_maps (`ImageInput`, *optional*):
|
| 136 |
+
The segmentation maps to preprocess.
|
| 137 |
+
"""
|
| 138 |
+
return super().preprocess(images, segmentation_maps, **kwargs)
|
| 139 |
+
|
| 140 |
+
def _preprocess_image_like_inputs(
|
| 141 |
+
self,
|
| 142 |
+
images: ImageInput,
|
| 143 |
+
segmentation_maps: ImageInput | None,
|
| 144 |
+
do_convert_rgb: bool,
|
| 145 |
+
input_data_format: ChannelDimension,
|
| 146 |
+
return_tensors: str | TensorType | None,
|
| 147 |
+
device: str | None = None,
|
| 148 |
+
**kwargs,
|
| 149 |
+
) -> BatchFeature:
|
| 150 |
+
"""Handle extra inputs beyond images."""
|
| 151 |
+
images = self._prepare_image_like_inputs(
|
| 152 |
+
images=images, do_convert_rgb=do_convert_rgb, input_data_format=input_data_format, device=device
|
| 153 |
+
)
|
| 154 |
+
images_kwargs = kwargs.copy()
|
| 155 |
+
images_kwargs["do_reduce_labels"] = False
|
| 156 |
+
data = {}
|
| 157 |
+
data["pixel_values"] = self._preprocess(images, **images_kwargs)
|
| 158 |
+
|
| 159 |
+
if segmentation_maps is not None:
|
| 160 |
+
processed_segmentation_maps = self._prepare_image_like_inputs(
|
| 161 |
+
images=segmentation_maps,
|
| 162 |
+
expected_ndims=2,
|
| 163 |
+
do_convert_rgb=False,
|
| 164 |
+
input_data_format=ChannelDimension.FIRST,
|
| 165 |
+
)
|
| 166 |
+
|
| 167 |
+
segmentation_maps_kwargs = kwargs.copy()
|
| 168 |
+
segmentation_maps_kwargs.update({"do_normalize": False, "do_rescale": False})
|
| 169 |
+
processed_segmentation_maps = self._preprocess(
|
| 170 |
+
images=processed_segmentation_maps, **segmentation_maps_kwargs
|
| 171 |
+
)
|
| 172 |
+
|
| 173 |
+
processed_segmentation_maps = [
|
| 174 |
+
processed_segmentation_map.squeeze(0).astype(np.int64)
|
| 175 |
+
for processed_segmentation_map in processed_segmentation_maps
|
| 176 |
+
]
|
| 177 |
+
data["labels"] = processed_segmentation_maps
|
| 178 |
+
|
| 179 |
+
return BatchFeature(data=data, tensor_type=return_tensors)
|
| 180 |
+
|
| 181 |
+
def reduce_label(self, image: np.ndarray) -> np.ndarray:
|
| 182 |
+
"""Reduce label values by 1, replacing 0 with 255."""
|
| 183 |
+
image[image == 0] = 255
|
| 184 |
+
image = image - 1
|
| 185 |
+
image[image == 254] = 255
|
| 186 |
+
return image
|
| 187 |
+
|
| 188 |
+
def resize(
|
| 189 |
+
self,
|
| 190 |
+
image: np.ndarray,
|
| 191 |
+
size: SizeDict,
|
| 192 |
+
resample: PILImageResampling | None,
|
| 193 |
+
ensure_multiple_of: int = 1,
|
| 194 |
+
keep_aspect_ratio: bool = False,
|
| 195 |
+
**kwargs,
|
| 196 |
+
) -> np.ndarray:
|
| 197 |
+
"""Resize with aspect ratio and multiple constraints."""
|
| 198 |
+
if size.height is None or size.width is None:
|
| 199 |
+
raise ValueError(f"Size must contain 'height' and 'width' keys. Got {size.keys()}")
|
| 200 |
+
output_size = get_resize_output_image_size(
|
| 201 |
+
image,
|
| 202 |
+
output_size=(size.height, size.width),
|
| 203 |
+
keep_aspect_ratio=keep_aspect_ratio,
|
| 204 |
+
multiple=ensure_multiple_of,
|
| 205 |
+
)
|
| 206 |
+
return super().resize(image, output_size, resample, **kwargs)
|
| 207 |
+
|
| 208 |
+
def pad_image(self, image: np.ndarray, size_divisor: int = 1, **kwargs) -> np.ndarray:
|
| 209 |
+
"""Center pad image to be a multiple of size_divisor."""
|
| 210 |
+
|
| 211 |
+
def _get_pad(size, size_divisor):
|
| 212 |
+
new_size = math.ceil(size / size_divisor) * size_divisor
|
| 213 |
+
pad_size = new_size - size
|
| 214 |
+
pad_size_left = pad_size // 2
|
| 215 |
+
pad_size_right = pad_size - pad_size_left
|
| 216 |
+
return pad_size_left, pad_size_right
|
| 217 |
+
|
| 218 |
+
height, width = image.shape[-2:]
|
| 219 |
+
pad_size_left, pad_size_right = _get_pad(height, size_divisor)
|
| 220 |
+
pad_size_top, pad_size_bottom = _get_pad(width, size_divisor)
|
| 221 |
+
return np_pad(
|
| 222 |
+
image,
|
| 223 |
+
padding=((pad_size_left, pad_size_right), (pad_size_top, pad_size_bottom)),
|
| 224 |
+
data_format=ChannelDimension.FIRST,
|
| 225 |
+
input_data_format=ChannelDimension.FIRST,
|
| 226 |
+
)
|
| 227 |
+
|
| 228 |
+
def _preprocess(
|
| 229 |
+
self,
|
| 230 |
+
images: list[np.ndarray],
|
| 231 |
+
do_resize: bool,
|
| 232 |
+
size: SizeDict,
|
| 233 |
+
resample: PILImageResampling | None,
|
| 234 |
+
do_rescale: bool,
|
| 235 |
+
rescale_factor: float,
|
| 236 |
+
do_normalize: bool,
|
| 237 |
+
image_mean: float | list[float] | None,
|
| 238 |
+
image_std: float | list[float] | None,
|
| 239 |
+
do_pad: bool | None,
|
| 240 |
+
do_reduce_labels: bool,
|
| 241 |
+
keep_aspect_ratio: bool,
|
| 242 |
+
ensure_multiple_of: int,
|
| 243 |
+
size_divisor: int | None = None,
|
| 244 |
+
**kwargs,
|
| 245 |
+
) -> np.ndarray:
|
| 246 |
+
"""Custom preprocessing for DPT."""
|
| 247 |
+
processed_images = []
|
| 248 |
+
for image in images:
|
| 249 |
+
if do_reduce_labels:
|
| 250 |
+
image = self.reduce_label(image)
|
| 251 |
+
if do_resize:
|
| 252 |
+
image = self.resize(
|
| 253 |
+
image, size, resample, ensure_multiple_of=ensure_multiple_of, keep_aspect_ratio=keep_aspect_ratio
|
| 254 |
+
)
|
| 255 |
+
if do_rescale:
|
| 256 |
+
image = self.rescale(image, rescale_factor)
|
| 257 |
+
if do_normalize:
|
| 258 |
+
image = self.normalize(image, image_mean, image_std)
|
| 259 |
+
if do_pad and size_divisor is not None:
|
| 260 |
+
image = self.pad_image(image, size_divisor)
|
| 261 |
+
processed_images.append(image)
|
| 262 |
+
return processed_images
|
| 263 |
+
|
| 264 |
+
@requires(backends=("torch",))
|
| 265 |
+
def post_process_semantic_segmentation(self, outputs, target_sizes: list[tuple] | None = None):
|
| 266 |
+
"""Converts the output of [`DPTForSemanticSegmentation`] into semantic segmentation maps."""
|
| 267 |
+
import torch
|
| 268 |
+
|
| 269 |
+
logits = outputs.logits
|
| 270 |
+
if target_sizes is not None:
|
| 271 |
+
if len(logits) != len(target_sizes):
|
| 272 |
+
raise ValueError(
|
| 273 |
+
"Make sure that you pass in as many target sizes as the batch dimension of the logits"
|
| 274 |
+
)
|
| 275 |
+
if isinstance(target_sizes, torch.Tensor):
|
| 276 |
+
target_sizes = target_sizes.numpy()
|
| 277 |
+
semantic_segmentation = []
|
| 278 |
+
for idx in range(len(logits)):
|
| 279 |
+
resized_logits = torch.nn.functional.interpolate(
|
| 280 |
+
logits[idx].unsqueeze(dim=0), size=target_sizes[idx], mode="bilinear", align_corners=False
|
| 281 |
+
)
|
| 282 |
+
semantic_map = resized_logits[0].argmax(dim=0)
|
| 283 |
+
semantic_segmentation.append(semantic_map)
|
| 284 |
+
else:
|
| 285 |
+
semantic_segmentation = logits.argmax(dim=1)
|
| 286 |
+
semantic_segmentation = [semantic_segmentation[i] for i in range(semantic_segmentation.shape[0])]
|
| 287 |
+
return semantic_segmentation
|
| 288 |
+
|
| 289 |
+
@requires(backends=("torch",))
|
| 290 |
+
def post_process_depth_estimation(
|
| 291 |
+
self, outputs: "DepthEstimatorOutput", target_sizes: TensorType | list[tuple[int, int]] | None = None
|
| 292 |
+
) -> list[dict[str, TensorType]]:
|
| 293 |
+
"""Converts the raw output of [`DepthEstimatorOutput`] into final depth predictions."""
|
| 294 |
+
import torch
|
| 295 |
+
|
| 296 |
+
predicted_depth = outputs.predicted_depth
|
| 297 |
+
if (target_sizes is not None) and (len(predicted_depth) != len(target_sizes)):
|
| 298 |
+
raise ValueError(
|
| 299 |
+
"Make sure that you pass in as many target sizes as the batch dimension of the predicted depth"
|
| 300 |
+
)
|
| 301 |
+
results = []
|
| 302 |
+
target_sizes = [None] * len(predicted_depth) if target_sizes is None else target_sizes
|
| 303 |
+
for depth, target_size in zip(predicted_depth, target_sizes):
|
| 304 |
+
if target_size is not None:
|
| 305 |
+
depth = torch.nn.functional.interpolate(
|
| 306 |
+
depth.unsqueeze(0).unsqueeze(1), size=target_size, mode="bicubic", align_corners=False
|
| 307 |
+
).squeeze()
|
| 308 |
+
results.append({"predicted_depth": depth})
|
| 309 |
+
return results
|
| 310 |
+
|
| 311 |
+
|
| 312 |
+
__all__ = ["DPTImageProcessorPil"]
|
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/utils/__init__.py
ADDED
|
@@ -0,0 +1,339 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python
|
| 2 |
+
|
| 3 |
+
# Copyright 2021 The HuggingFace Inc. team. All rights reserved.
|
| 4 |
+
#
|
| 5 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 6 |
+
# you may not use this file except in compliance with the License.
|
| 7 |
+
# You may obtain a copy of the License at
|
| 8 |
+
#
|
| 9 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 10 |
+
#
|
| 11 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 12 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 13 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 14 |
+
# See the License for the specific language governing permissions and
|
| 15 |
+
# limitations under the License.
|
| 16 |
+
|
| 17 |
+
from functools import lru_cache
|
| 18 |
+
|
| 19 |
+
from packaging import version
|
| 20 |
+
|
| 21 |
+
from .. import __version__
|
| 22 |
+
from .auto_docstring import (
|
| 23 |
+
ClassAttrs,
|
| 24 |
+
ClassDocstring,
|
| 25 |
+
ImageProcessorArgs,
|
| 26 |
+
ModelArgs,
|
| 27 |
+
ModelOutputArgs,
|
| 28 |
+
auto_class_docstring,
|
| 29 |
+
auto_docstring,
|
| 30 |
+
get_args_doc_from_source,
|
| 31 |
+
parse_docstring,
|
| 32 |
+
set_min_indent,
|
| 33 |
+
)
|
| 34 |
+
from .chat_template_utils import DocstringParsingException, TypeHintParsingException, get_json_schema
|
| 35 |
+
from .constants import IMAGENET_DEFAULT_MEAN, IMAGENET_DEFAULT_STD, IMAGENET_STANDARD_MEAN, IMAGENET_STANDARD_STD
|
| 36 |
+
from .doc import (
|
| 37 |
+
add_code_sample_docstrings,
|
| 38 |
+
add_end_docstrings,
|
| 39 |
+
add_start_docstrings,
|
| 40 |
+
add_start_docstrings_to_model_forward,
|
| 41 |
+
copy_func,
|
| 42 |
+
replace_return_docstrings,
|
| 43 |
+
)
|
| 44 |
+
from .generic import (
|
| 45 |
+
ContextManagers,
|
| 46 |
+
ExplicitEnum,
|
| 47 |
+
ModelOutput,
|
| 48 |
+
PaddingStrategy,
|
| 49 |
+
TensorType,
|
| 50 |
+
TransformersKwargs,
|
| 51 |
+
_is_tensor_or_array_like,
|
| 52 |
+
can_return_loss,
|
| 53 |
+
can_return_tuple,
|
| 54 |
+
expand_dims,
|
| 55 |
+
filter_out_non_signature_kwargs,
|
| 56 |
+
find_labels,
|
| 57 |
+
flatten_dict,
|
| 58 |
+
is_numpy_array,
|
| 59 |
+
is_tensor,
|
| 60 |
+
is_timm_config_dict,
|
| 61 |
+
is_timm_local_checkpoint,
|
| 62 |
+
is_torch_device,
|
| 63 |
+
is_torch_dtype,
|
| 64 |
+
is_torch_tensor,
|
| 65 |
+
reshape,
|
| 66 |
+
safe_load_json_file,
|
| 67 |
+
squeeze,
|
| 68 |
+
strtobool,
|
| 69 |
+
tensor_size,
|
| 70 |
+
to_numpy,
|
| 71 |
+
to_py_obj,
|
| 72 |
+
torch_float,
|
| 73 |
+
torch_int,
|
| 74 |
+
transpose,
|
| 75 |
+
)
|
| 76 |
+
from .hub import (
|
| 77 |
+
CHAT_TEMPLATE_DIR,
|
| 78 |
+
CHAT_TEMPLATE_FILE,
|
| 79 |
+
CLOUDFRONT_DISTRIB_PREFIX,
|
| 80 |
+
HF_MODULES_CACHE,
|
| 81 |
+
LEGACY_PROCESSOR_CHAT_TEMPLATE_FILE,
|
| 82 |
+
S3_BUCKET_PREFIX,
|
| 83 |
+
TRANSFORMERS_DYNAMIC_MODULE_NAME,
|
| 84 |
+
EntryNotFoundError,
|
| 85 |
+
PushInProgress,
|
| 86 |
+
PushToHubMixin,
|
| 87 |
+
RepositoryNotFoundError,
|
| 88 |
+
RevisionNotFoundError,
|
| 89 |
+
cached_file,
|
| 90 |
+
define_sagemaker_information,
|
| 91 |
+
extract_commit_hash,
|
| 92 |
+
has_file,
|
| 93 |
+
http_user_agent,
|
| 94 |
+
list_repo_templates,
|
| 95 |
+
try_to_load_from_cache,
|
| 96 |
+
)
|
| 97 |
+
from .import_utils import (
|
| 98 |
+
ACCELERATE_MIN_VERSION,
|
| 99 |
+
BITSANDBYTES_MIN_VERSION,
|
| 100 |
+
ENV_VARS_TRUE_AND_AUTO_VALUES,
|
| 101 |
+
ENV_VARS_TRUE_VALUES,
|
| 102 |
+
GGUF_MIN_VERSION,
|
| 103 |
+
TRITON_MIN_VERSION,
|
| 104 |
+
XLA_FSDPV2_MIN_VERSION,
|
| 105 |
+
DummyObject,
|
| 106 |
+
OptionalDependencyNotAvailable,
|
| 107 |
+
_LazyModule,
|
| 108 |
+
check_torch_load_is_safe,
|
| 109 |
+
direct_transformers_import,
|
| 110 |
+
enable_tf32,
|
| 111 |
+
get_torch_version,
|
| 112 |
+
is_accelerate_available,
|
| 113 |
+
is_apex_available,
|
| 114 |
+
is_apollo_torch_available,
|
| 115 |
+
is_aqlm_available,
|
| 116 |
+
is_auto_round_available,
|
| 117 |
+
is_av_available,
|
| 118 |
+
is_bitsandbytes_available,
|
| 119 |
+
is_bs4_available,
|
| 120 |
+
is_causal_conv1d_available,
|
| 121 |
+
is_coloredlogs_available,
|
| 122 |
+
is_compressed_tensors_available,
|
| 123 |
+
is_cuda_platform,
|
| 124 |
+
is_cv2_available,
|
| 125 |
+
is_cython_available,
|
| 126 |
+
is_datasets_available,
|
| 127 |
+
is_decord_available,
|
| 128 |
+
is_detectron2_available,
|
| 129 |
+
is_env_variable_false,
|
| 130 |
+
is_env_variable_true,
|
| 131 |
+
is_essentia_available,
|
| 132 |
+
is_faiss_available,
|
| 133 |
+
is_fbgemm_gpu_available,
|
| 134 |
+
is_flash_attn_2_available,
|
| 135 |
+
is_flash_attn_3_available,
|
| 136 |
+
is_flash_attn_4_available,
|
| 137 |
+
is_flash_attn_greater_or_equal,
|
| 138 |
+
is_flash_attn_greater_or_equal_2_10,
|
| 139 |
+
is_flash_linear_attention_available,
|
| 140 |
+
is_flute_available,
|
| 141 |
+
is_fouroversix_available,
|
| 142 |
+
is_fp_quant_available,
|
| 143 |
+
is_fsdp_available,
|
| 144 |
+
is_g2p_en_available,
|
| 145 |
+
is_galore_torch_available,
|
| 146 |
+
is_gguf_available,
|
| 147 |
+
is_gptqmodel_available,
|
| 148 |
+
is_grokadamw_available,
|
| 149 |
+
is_grouped_mm_available,
|
| 150 |
+
is_habana_gaudi1,
|
| 151 |
+
is_hadamard_available,
|
| 152 |
+
is_hqq_available,
|
| 153 |
+
is_huggingface_hub_greater_or_equal,
|
| 154 |
+
is_in_notebook,
|
| 155 |
+
is_ipython_available,
|
| 156 |
+
is_jinja_available,
|
| 157 |
+
is_jmespath_available,
|
| 158 |
+
is_jumanpp_available,
|
| 159 |
+
is_kenlm_available,
|
| 160 |
+
is_kernels_available,
|
| 161 |
+
is_levenshtein_available,
|
| 162 |
+
is_libcst_available,
|
| 163 |
+
is_librosa_available,
|
| 164 |
+
is_liger_kernel_available,
|
| 165 |
+
is_llm_awq_available,
|
| 166 |
+
is_lomo_available,
|
| 167 |
+
is_matplotlib_available,
|
| 168 |
+
is_mistral_common_available,
|
| 169 |
+
is_mlx_available,
|
| 170 |
+
is_multipart_available,
|
| 171 |
+
is_natten_available,
|
| 172 |
+
is_ninja_available,
|
| 173 |
+
is_nltk_available,
|
| 174 |
+
is_num2words_available,
|
| 175 |
+
is_numba_available,
|
| 176 |
+
is_onnx_available,
|
| 177 |
+
is_openai_available,
|
| 178 |
+
is_optimum_available,
|
| 179 |
+
is_optimum_quanto_available,
|
| 180 |
+
is_pandas_available,
|
| 181 |
+
is_peft_available,
|
| 182 |
+
is_phonemizer_available,
|
| 183 |
+
is_pretty_midi_available,
|
| 184 |
+
is_protobuf_available,
|
| 185 |
+
is_psutil_available,
|
| 186 |
+
is_py3nvml_available,
|
| 187 |
+
is_pyctcdecode_available,
|
| 188 |
+
is_pytesseract_available,
|
| 189 |
+
is_pytest_available,
|
| 190 |
+
is_pytest_order_available,
|
| 191 |
+
is_pytorch_quantization_available,
|
| 192 |
+
is_quanto_greater,
|
| 193 |
+
is_quark_available,
|
| 194 |
+
is_qutlass_available,
|
| 195 |
+
is_rich_available,
|
| 196 |
+
is_rjieba_available,
|
| 197 |
+
is_rocm_platform,
|
| 198 |
+
is_sacremoses_available,
|
| 199 |
+
is_sagemaker_dp_enabled,
|
| 200 |
+
is_sagemaker_mp_enabled,
|
| 201 |
+
is_schedulefree_available,
|
| 202 |
+
is_scipy_available,
|
| 203 |
+
is_sentencepiece_available,
|
| 204 |
+
is_seqio_available,
|
| 205 |
+
is_serve_available,
|
| 206 |
+
is_sinq_available,
|
| 207 |
+
is_sklearn_available,
|
| 208 |
+
is_soundfile_available,
|
| 209 |
+
is_spacy_available,
|
| 210 |
+
is_speech_available,
|
| 211 |
+
is_spqr_available,
|
| 212 |
+
is_sudachi_available,
|
| 213 |
+
is_sudachi_projection_available,
|
| 214 |
+
is_tiktoken_available,
|
| 215 |
+
is_timm_available,
|
| 216 |
+
is_tokenizers_available,
|
| 217 |
+
is_torch_accelerator_available,
|
| 218 |
+
is_torch_available,
|
| 219 |
+
is_torch_bf16_available_on_device,
|
| 220 |
+
is_torch_bf16_gpu_available,
|
| 221 |
+
is_torch_cuda_available,
|
| 222 |
+
is_torch_deterministic,
|
| 223 |
+
is_torch_flex_attn_available,
|
| 224 |
+
is_torch_fp16_available_on_device,
|
| 225 |
+
is_torch_fx_proxy,
|
| 226 |
+
is_torch_greater_or_equal,
|
| 227 |
+
is_torch_hpu_available,
|
| 228 |
+
is_torch_mlu_available,
|
| 229 |
+
is_torch_mps_available,
|
| 230 |
+
is_torch_musa_available,
|
| 231 |
+
is_torch_neuron_available,
|
| 232 |
+
is_torch_neuroncore_available,
|
| 233 |
+
is_torch_npu_available,
|
| 234 |
+
is_torch_optimi_available,
|
| 235 |
+
is_torch_tensorrt_fx_available,
|
| 236 |
+
is_torch_tf32_available,
|
| 237 |
+
is_torch_tpu_available,
|
| 238 |
+
is_torch_xla_available,
|
| 239 |
+
is_torch_xpu_available,
|
| 240 |
+
is_torchao_available,
|
| 241 |
+
is_torchaudio_available,
|
| 242 |
+
is_torchcodec_available,
|
| 243 |
+
is_torchdistx_available,
|
| 244 |
+
is_torchdynamo_compiling,
|
| 245 |
+
is_torchdynamo_exporting,
|
| 246 |
+
is_torchvision_available,
|
| 247 |
+
is_torchvision_v2_available,
|
| 248 |
+
is_tracing,
|
| 249 |
+
is_training_run_on_sagemaker,
|
| 250 |
+
is_triton_available,
|
| 251 |
+
is_uroman_available,
|
| 252 |
+
is_vision_available,
|
| 253 |
+
is_vptq_available,
|
| 254 |
+
is_xlstm_available,
|
| 255 |
+
is_yt_dlp_available,
|
| 256 |
+
requires_backends,
|
| 257 |
+
torch_compilable_check,
|
| 258 |
+
torch_only_method,
|
| 259 |
+
)
|
| 260 |
+
from .kernel_config import KernelConfig
|
| 261 |
+
from .peft_utils import (
|
| 262 |
+
ADAPTER_CONFIG_NAME,
|
| 263 |
+
ADAPTER_SAFE_WEIGHTS_NAME,
|
| 264 |
+
ADAPTER_WEIGHTS_NAME,
|
| 265 |
+
check_peft_version,
|
| 266 |
+
find_adapter_config_file,
|
| 267 |
+
)
|
| 268 |
+
|
| 269 |
+
|
| 270 |
+
WEIGHTS_NAME = "pytorch_model.bin"
|
| 271 |
+
WEIGHTS_INDEX_NAME = "pytorch_model.bin.index.json"
|
| 272 |
+
SAFE_WEIGHTS_NAME = "model.safetensors"
|
| 273 |
+
SAFE_WEIGHTS_INDEX_NAME = "model.safetensors.index.json"
|
| 274 |
+
CONFIG_NAME = "config.json"
|
| 275 |
+
FEATURE_EXTRACTOR_NAME = "preprocessor_config.json"
|
| 276 |
+
IMAGE_PROCESSOR_NAME = "preprocessor_config.json"
|
| 277 |
+
VIDEO_PROCESSOR_NAME = "video_preprocessor_config.json"
|
| 278 |
+
AUDIO_TOKENIZER_NAME = "audio_tokenizer_config.json"
|
| 279 |
+
PROCESSOR_NAME = "processor_config.json"
|
| 280 |
+
GENERATION_CONFIG_NAME = "generation_config.json"
|
| 281 |
+
MODEL_CARD_NAME = "modelcard.json"
|
| 282 |
+
|
| 283 |
+
|
| 284 |
+
SENTENCEPIECE_UNDERLINE = "▁"
|
| 285 |
+
SPIECE_UNDERLINE = SENTENCEPIECE_UNDERLINE # Kept for backward compatibility
|
| 286 |
+
|
| 287 |
+
MULTIPLE_CHOICE_DUMMY_INPUTS = [
|
| 288 |
+
[[0, 1, 0, 1], [1, 0, 0, 1]]
|
| 289 |
+
] * 2 # Needs to have 0s and 1s only since XLM uses it for langs too.
|
| 290 |
+
DUMMY_INPUTS = [[7, 6, 0, 0, 1], [1, 2, 3, 0, 0], [0, 0, 0, 4, 5]]
|
| 291 |
+
DUMMY_MASK = [[1, 1, 1, 1, 1], [1, 1, 1, 0, 0], [0, 0, 0, 1, 1]]
|
| 292 |
+
|
| 293 |
+
|
| 294 |
+
def check_min_version(min_version):
|
| 295 |
+
if version.parse(__version__) < version.parse(min_version):
|
| 296 |
+
if "dev" in min_version:
|
| 297 |
+
error_message = (
|
| 298 |
+
"This example requires a source install from HuggingFace Transformers (see "
|
| 299 |
+
"`https://huggingface.co/docs/transformers/installation#install-from-source`),"
|
| 300 |
+
)
|
| 301 |
+
else:
|
| 302 |
+
error_message = f"This example requires a minimum version of {min_version},"
|
| 303 |
+
error_message += f" but the version found is {__version__}.\n"
|
| 304 |
+
raise ImportError(
|
| 305 |
+
error_message
|
| 306 |
+
+ "Check out https://github.com/huggingface/transformers/tree/main/examples#important-note for the examples corresponding to other "
|
| 307 |
+
"versions of HuggingFace Transformers."
|
| 308 |
+
)
|
| 309 |
+
|
| 310 |
+
|
| 311 |
+
@lru_cache
|
| 312 |
+
def get_available_devices() -> frozenset[str]:
|
| 313 |
+
"""
|
| 314 |
+
Returns a frozenset of devices available for the current PyTorch installation.
|
| 315 |
+
"""
|
| 316 |
+
devices = {"cpu"} # `cpu` is always supported as a device in PyTorch
|
| 317 |
+
|
| 318 |
+
if is_torch_cuda_available():
|
| 319 |
+
devices.add("cuda")
|
| 320 |
+
|
| 321 |
+
if is_torch_mps_available():
|
| 322 |
+
devices.add("mps")
|
| 323 |
+
|
| 324 |
+
if is_torch_xpu_available():
|
| 325 |
+
devices.add("xpu")
|
| 326 |
+
|
| 327 |
+
if is_torch_npu_available():
|
| 328 |
+
devices.add("npu")
|
| 329 |
+
|
| 330 |
+
if is_torch_hpu_available():
|
| 331 |
+
devices.add("hpu")
|
| 332 |
+
|
| 333 |
+
if is_torch_mlu_available():
|
| 334 |
+
devices.add("mlu")
|
| 335 |
+
|
| 336 |
+
if is_torch_musa_available():
|
| 337 |
+
devices.add("musa")
|
| 338 |
+
|
| 339 |
+
return frozenset(devices)
|
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/utils/backbone_utils.py
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import warnings
|
| 2 |
+
|
| 3 |
+
from ..backbone_utils import BackboneConfigMixin, BackboneMixin
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
class BackboneConfigMixin(BackboneConfigMixin):
|
| 7 |
+
warnings.warn(
|
| 8 |
+
"Importing `BackboneConfigMixin` from `utils/backbone_utils.py` is deprecated and will be removed in "
|
| 9 |
+
"Transformers v5.10. Import as `from transformers.backbone_utils import BackboneConfigMixin` instead.",
|
| 10 |
+
FutureWarning,
|
| 11 |
+
)
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
class BackboneMixin(BackboneMixin):
|
| 15 |
+
warnings.warn(
|
| 16 |
+
"Importing `BackboneMixin` from `utils/backbone_utils.py` is deprecated and will be removed in "
|
| 17 |
+
"Transformers v5.10. Import as `from transformers.backbone_utils import BackboneMixin` instead.",
|
| 18 |
+
FutureWarning,
|
| 19 |
+
)
|
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/utils/chat_parsing_utils.py
ADDED
|
@@ -0,0 +1,305 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2026 The HuggingFace Team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
|
| 15 |
+
from __future__ import annotations
|
| 16 |
+
|
| 17 |
+
import json
|
| 18 |
+
import re
|
| 19 |
+
|
| 20 |
+
from transformers.utils import is_jmespath_available
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
if is_jmespath_available():
|
| 24 |
+
import jmespath
|
| 25 |
+
else:
|
| 26 |
+
jmespath = None
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
def _gemma4_json_to_json(text: str) -> str:
|
| 30 |
+
"""Convert Gemma4 tool call format (unquoted keys, ``<|"|>`` string delimiters) to valid JSON."""
|
| 31 |
+
strings = []
|
| 32 |
+
|
| 33 |
+
def _capture(m):
|
| 34 |
+
strings.append(m.group(1))
|
| 35 |
+
return f"\x00{len(strings) - 1}\x00"
|
| 36 |
+
|
| 37 |
+
# Grab the inside of gemma-quotes and store them for later
|
| 38 |
+
text = re.sub(r'<\|"\|>(.*?)<\|"\|>', _capture, text, flags=re.DOTALL)
|
| 39 |
+
# Add quotes to the bare keys elsewhere
|
| 40 |
+
text = re.sub(r"(?<=[{,])(\w+):", r'"\1":', text)
|
| 41 |
+
|
| 42 |
+
# Put the inside of the quotes back afterwards
|
| 43 |
+
for i, s in enumerate(strings):
|
| 44 |
+
text = text.replace(f"\x00{i}\x00", json.dumps(s))
|
| 45 |
+
|
| 46 |
+
return text
|
| 47 |
+
|
| 48 |
+
|
| 49 |
+
def _parse_re_match(node_match: re.Match) -> dict | str:
|
| 50 |
+
# If the regex has named groups, return a dict of those groups
|
| 51 |
+
if node_match.groupdict():
|
| 52 |
+
return {key: val for key, val in node_match.groupdict().items() if val is not None}
|
| 53 |
+
# Otherwise the regex must have exactly one unnamed group, and we return that
|
| 54 |
+
else:
|
| 55 |
+
groups = list(node_match.groups())
|
| 56 |
+
if len(groups) > 1:
|
| 57 |
+
raise ValueError(f"Regex has multiple unnamed groups!\nGroups: {groups}\n")
|
| 58 |
+
elif len(groups) == 0:
|
| 59 |
+
raise ValueError(f"Regex has no capture groups:\n\n{node_match.group(0)}")
|
| 60 |
+
return groups[0]
|
| 61 |
+
|
| 62 |
+
|
| 63 |
+
def recursive_parse(
|
| 64 |
+
node_content: str | list | dict,
|
| 65 |
+
node_schema: dict,
|
| 66 |
+
):
|
| 67 |
+
"""
|
| 68 |
+
This function takes content and a JSON schema which includes
|
| 69 |
+
regex extractors, and recursively parses the content. The output
|
| 70 |
+
should be a data structure matching the schema.
|
| 71 |
+
|
| 72 |
+
Args:
|
| 73 |
+
node_content: The content corresponding to this node. Usually a string, but can be something else
|
| 74 |
+
if the parent node has multiple capture groups or named groups. In that case,
|
| 75 |
+
we generally pass the capture groups straight through to the children of this node
|
| 76 |
+
and don't do any parsing at this level.
|
| 77 |
+
node_schema: The schema node controlling the parsing.
|
| 78 |
+
|
| 79 |
+
Returns:
|
| 80 |
+
The parsed data structure for the current node.
|
| 81 |
+
"""
|
| 82 |
+
|
| 83 |
+
# If the schema has a const, we just return that value and do absolutely nothing else
|
| 84 |
+
if "const" in node_schema:
|
| 85 |
+
return node_schema["const"]
|
| 86 |
+
|
| 87 |
+
# If the node content is None, we return None. EZ.
|
| 88 |
+
if node_content is None:
|
| 89 |
+
return None
|
| 90 |
+
|
| 91 |
+
# If not, we have to do a little parsing. First, set some vars and do basic validation
|
| 92 |
+
node_type = node_schema.get("type")
|
| 93 |
+
has_regex = (
|
| 94 |
+
"x-regex" in node_schema
|
| 95 |
+
or "x-regex-iterator" in node_schema
|
| 96 |
+
or "x-regex-key-value" in node_schema
|
| 97 |
+
or "x-regex-substitutions" in node_schema
|
| 98 |
+
)
|
| 99 |
+
if has_regex and not isinstance(node_content, str):
|
| 100 |
+
raise TypeError(
|
| 101 |
+
"Schema node got a non-string input, but has a regex for parsing or substitution.\n"
|
| 102 |
+
f"Input: {node_content}\n"
|
| 103 |
+
f"Schema: {node_schema}"
|
| 104 |
+
)
|
| 105 |
+
|
| 106 |
+
node_subs = node_schema.get("x-regex-substitutions", [])
|
| 107 |
+
for node_sub in node_subs:
|
| 108 |
+
node_content = re.sub(node_sub[0], node_sub[1], node_content, flags=re.DOTALL)
|
| 109 |
+
node_regex = node_schema.get("x-regex")
|
| 110 |
+
node_regex_iterator = node_schema.get("x-regex-iterator")
|
| 111 |
+
node_regex_to_dict = node_schema.get("x-regex-key-value")
|
| 112 |
+
if node_regex is not None:
|
| 113 |
+
node_match = re.search(node_regex, node_content, flags=re.DOTALL)
|
| 114 |
+
if not node_match:
|
| 115 |
+
return None
|
| 116 |
+
node_content = _parse_re_match(node_match)
|
| 117 |
+
if node_regex_iterator is not None:
|
| 118 |
+
if node_type != "array":
|
| 119 |
+
raise TypeError(f"Schema node with type {node_type} cannot use x-regex-iterator.\nSchema: {node_schema}")
|
| 120 |
+
# Note that this can be applied after a standard node-regex search
|
| 121 |
+
node_content = [
|
| 122 |
+
_parse_re_match(node_match)
|
| 123 |
+
for node_match in re.finditer(node_regex_iterator, node_content, flags=re.DOTALL)
|
| 124 |
+
]
|
| 125 |
+
if not node_content:
|
| 126 |
+
return None
|
| 127 |
+
if node_regex_to_dict is not None:
|
| 128 |
+
if node_type != "object":
|
| 129 |
+
raise TypeError(f"Schema node with type {node_type} cannot use x-regex-key-value.\nSchema: {node_schema}")
|
| 130 |
+
# Note that this can be applied after a standard node-regex search
|
| 131 |
+
output_content = {}
|
| 132 |
+
for node_match in re.finditer(node_regex_to_dict, node_content, flags=re.DOTALL):
|
| 133 |
+
match_groups = _parse_re_match(node_match)
|
| 134 |
+
if not isinstance(match_groups, dict) or "key" not in match_groups or "value" not in match_groups:
|
| 135 |
+
raise ValueError(
|
| 136 |
+
f"Regex for x-regex-key-value must have named groups 'key' and 'value'.\n"
|
| 137 |
+
f"Match groups: {match_groups}\n"
|
| 138 |
+
f"Schema: {node_schema}"
|
| 139 |
+
)
|
| 140 |
+
output_content[match_groups["key"]] = match_groups["value"]
|
| 141 |
+
node_content = output_content
|
| 142 |
+
if not node_content:
|
| 143 |
+
return None
|
| 144 |
+
|
| 145 |
+
# Next, if the node has a parser, apply it. We do this after regexes so that the regex can extract
|
| 146 |
+
# a substring to parse, if needed.
|
| 147 |
+
if "x-parser" in node_schema:
|
| 148 |
+
parser = node_schema["x-parser"]
|
| 149 |
+
if parser == "gemma4-tool-call":
|
| 150 |
+
if not isinstance(node_content, str):
|
| 151 |
+
raise TypeError(
|
| 152 |
+
f"Node has Gemma4 tool call parser but got non-string input: {node_content}\nSchema: {node_schema}"
|
| 153 |
+
)
|
| 154 |
+
node_content = _gemma4_json_to_json(node_content)
|
| 155 |
+
parser = "json" # fall through to the JSON parser below - don't add an elif!
|
| 156 |
+
if parser == "json":
|
| 157 |
+
if not isinstance(node_content, str):
|
| 158 |
+
raise TypeError(
|
| 159 |
+
f"Node has JSON parser but got non-string input: {node_content}\nSchema: {node_schema}"
|
| 160 |
+
)
|
| 161 |
+
parser_args = node_schema.get("x-parser-args", {})
|
| 162 |
+
transform = parser_args.get("transform")
|
| 163 |
+
allow_non_json = parser_args.get("allow_non_json", False)
|
| 164 |
+
try:
|
| 165 |
+
parsed_json = json.loads(node_content)
|
| 166 |
+
except json.JSONDecodeError as e:
|
| 167 |
+
if allow_non_json:
|
| 168 |
+
parsed_json = node_content
|
| 169 |
+
else:
|
| 170 |
+
raise ValueError(
|
| 171 |
+
f"Node has JSON parser but could not parse its contents as JSON. You can use the `allow_non_json` parser arg for nodes which may contain JSON or string content.\n\nContent: {node_content}\n\nError: {e}"
|
| 172 |
+
)
|
| 173 |
+
if transform is not None:
|
| 174 |
+
if jmespath is None:
|
| 175 |
+
raise ImportError(
|
| 176 |
+
"Chat response schema includes a jmespath transformation, but jmespath is not installed. You can install it with `pip install jmespath`."
|
| 177 |
+
)
|
| 178 |
+
parsed_json = jmespath.search(parser_args["transform"], parsed_json)
|
| 179 |
+
node_content = parsed_json
|
| 180 |
+
else:
|
| 181 |
+
raise ValueError(f"Unknown parser {parser} for schema node: {node_schema}")
|
| 182 |
+
|
| 183 |
+
# Finally, handle parsed content based on schema type and recurse if required
|
| 184 |
+
if node_type == "object":
|
| 185 |
+
parsed_schema = {}
|
| 186 |
+
if isinstance(node_content, str):
|
| 187 |
+
# This means we don't have a regex at this level, so all of our child nodes need to parse the whole
|
| 188 |
+
# string themselves to extract their value.
|
| 189 |
+
if "properties" not in node_schema:
|
| 190 |
+
raise ValueError(
|
| 191 |
+
f"Object node received string content but has no regex or parser to handle it.\n"
|
| 192 |
+
f"Content: {node_content}\n"
|
| 193 |
+
f"Schema: {node_schema}"
|
| 194 |
+
)
|
| 195 |
+
for key, child_node in node_schema["properties"].items():
|
| 196 |
+
child_node_content = recursive_parse(node_content, node_schema["properties"][key])
|
| 197 |
+
if child_node_content is not None:
|
| 198 |
+
parsed_schema[key] = child_node_content
|
| 199 |
+
elif isinstance(node_content, dict):
|
| 200 |
+
for key, child_node in node_schema.get("properties", {}).items():
|
| 201 |
+
if "const" in child_node:
|
| 202 |
+
parsed_schema[key] = child_node["const"]
|
| 203 |
+
elif key in node_content:
|
| 204 |
+
parsed_schema[key] = recursive_parse(node_content[key], child_node)
|
| 205 |
+
elif "default" in child_node:
|
| 206 |
+
parsed_schema[key] = child_node["default"]
|
| 207 |
+
additional_schema = node_schema.get("additionalProperties", True)
|
| 208 |
+
# We want to check only for False values; {} is "falsy" but should pass through
|
| 209 |
+
if additional_schema is not False:
|
| 210 |
+
additional_schema = additional_schema if isinstance(additional_schema, dict) else {}
|
| 211 |
+
for key, value in node_content.items():
|
| 212 |
+
if key not in node_schema.get("properties", {}):
|
| 213 |
+
parsed_schema[key] = recursive_parse(value, additional_schema)
|
| 214 |
+
else:
|
| 215 |
+
raise TypeError(f"Expected a dict or str for schema node with type object, got {node_content}")
|
| 216 |
+
required = node_schema.get("required", [])
|
| 217 |
+
missing = [key for key in required if key not in parsed_schema]
|
| 218 |
+
if missing:
|
| 219 |
+
input_preview = repr(node_content[:500]) if isinstance(node_content, str) else repr(node_content)
|
| 220 |
+
raise ValueError(
|
| 221 |
+
f"Required fields {missing} are missing from parsed output.\n"
|
| 222 |
+
f"Parsed: {parsed_schema}\n"
|
| 223 |
+
f"Input: {input_preview}"
|
| 224 |
+
)
|
| 225 |
+
return parsed_schema
|
| 226 |
+
elif node_type == "array":
|
| 227 |
+
if not node_content:
|
| 228 |
+
return []
|
| 229 |
+
parsed_schema = []
|
| 230 |
+
if "items" in node_schema:
|
| 231 |
+
if not isinstance(node_content, list):
|
| 232 |
+
raise TypeError(f"Expected a list or regex for schema node with type array, got {node_content}")
|
| 233 |
+
for item in node_content:
|
| 234 |
+
parsed_schema.append(recursive_parse(item, node_schema["items"]))
|
| 235 |
+
return parsed_schema
|
| 236 |
+
elif "prefixItems" in node_schema:
|
| 237 |
+
if not isinstance(node_content, list):
|
| 238 |
+
if len(node_schema["prefixItems"]) == 1:
|
| 239 |
+
# If there's only one prefix item, this is a single item array, we can just wrap the string
|
| 240 |
+
node_content = [node_content]
|
| 241 |
+
else:
|
| 242 |
+
raise TypeError(f"Expected a list or regex for schema node with type array, got {node_content}")
|
| 243 |
+
if len(node_content) != len(node_schema["prefixItems"]):
|
| 244 |
+
raise ValueError(
|
| 245 |
+
f"Array node has {len(node_content)} items, but schema only has "
|
| 246 |
+
f"{len(node_schema['prefixItems'])} prefixItems defined.\n"
|
| 247 |
+
f"Content: {node_content}\n"
|
| 248 |
+
f"Schema: {node_schema}"
|
| 249 |
+
)
|
| 250 |
+
for item, item_schema in zip(node_content, node_schema["prefixItems"]):
|
| 251 |
+
parsed_schema.append(recursive_parse(item, item_schema))
|
| 252 |
+
return parsed_schema
|
| 253 |
+
else:
|
| 254 |
+
raise ValueError(f"Array node has no items or prefixItems schema defined.\nSchema: {node_schema}")
|
| 255 |
+
elif node_type in ("string", "integer", "number", "boolean"):
|
| 256 |
+
if node_type == "integer":
|
| 257 |
+
if isinstance(node_content, int):
|
| 258 |
+
return node_content
|
| 259 |
+
if not isinstance(node_content, str):
|
| 260 |
+
raise TypeError(
|
| 261 |
+
f"Expected a string or int for schema node with type integer, got {type(node_content).__name__}: {node_content}"
|
| 262 |
+
)
|
| 263 |
+
try:
|
| 264 |
+
return int(node_content)
|
| 265 |
+
except ValueError:
|
| 266 |
+
raise ValueError(
|
| 267 |
+
f"Schema node has type 'integer', but the parsed string content is not a valid integer: {node_content!r}"
|
| 268 |
+
)
|
| 269 |
+
elif node_type == "number":
|
| 270 |
+
if isinstance(node_content, (int, float)):
|
| 271 |
+
return float(node_content)
|
| 272 |
+
if not isinstance(node_content, str):
|
| 273 |
+
raise TypeError(
|
| 274 |
+
f"Expected a string or number for schema node with type number, got {type(node_content).__name__}: {node_content}"
|
| 275 |
+
)
|
| 276 |
+
try:
|
| 277 |
+
return float(node_content)
|
| 278 |
+
except ValueError:
|
| 279 |
+
raise ValueError(
|
| 280 |
+
f"Schema node has type 'number', but the parsed string content is not a valid number: {node_content!r}"
|
| 281 |
+
)
|
| 282 |
+
elif node_type == "boolean":
|
| 283 |
+
if isinstance(node_content, bool):
|
| 284 |
+
return node_content
|
| 285 |
+
if not isinstance(node_content, str):
|
| 286 |
+
raise TypeError(
|
| 287 |
+
f"Expected a string or bool for schema node with type boolean, got {type(node_content).__name__}: {node_content}"
|
| 288 |
+
)
|
| 289 |
+
if node_content.lower() in ("true", "1"):
|
| 290 |
+
return True
|
| 291 |
+
elif node_content.lower() in ("false", "0"):
|
| 292 |
+
return False
|
| 293 |
+
else:
|
| 294 |
+
raise ValueError(f"Invalid boolean value: {node_content}")
|
| 295 |
+
else:
|
| 296 |
+
# String type
|
| 297 |
+
if not isinstance(node_content, str):
|
| 298 |
+
raise TypeError(
|
| 299 |
+
f"Expected a string for schema node with type string, got {type(node_content).__name__}: {node_content}"
|
| 300 |
+
)
|
| 301 |
+
return node_content
|
| 302 |
+
elif node_type is None or node_type == "any":
|
| 303 |
+
return node_content # Don't touch it
|
| 304 |
+
else:
|
| 305 |
+
raise TypeError(f"Unsupported schema type {node_type} for node: {node_content}")
|
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/utils/dummy_detectron2_objects.py
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# This file is autogenerated by the command `make fix-copies`, do not edit.
|
| 2 |
+
from ..utils import requires_backends
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
class LayoutLMv2Model:
|
| 6 |
+
def __init__(self, *args, **kwargs):
|
| 7 |
+
requires_backends(self, ["detectron2"])
|
| 8 |
+
|
| 9 |
+
@classmethod
|
| 10 |
+
def from_pretrained(cls, *args, **kwargs):
|
| 11 |
+
requires_backends(cls, ["detectron2"])
|
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/utils/dummy_music_objects.py
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# This file is autogenerated by the command `make fix-copies`, do not edit.
|
| 2 |
+
from ..utils import DummyObject, requires_backends
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
class Pop2PianoFeatureExtractor(metaclass=DummyObject):
|
| 6 |
+
_backends = ["music"]
|
| 7 |
+
|
| 8 |
+
def __init__(self, *args, **kwargs):
|
| 9 |
+
requires_backends(self, ["music"])
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
class Pop2PianoTokenizer(metaclass=DummyObject):
|
| 13 |
+
_backends = ["music"]
|
| 14 |
+
|
| 15 |
+
def __init__(self, *args, **kwargs):
|
| 16 |
+
requires_backends(self, ["music"])
|
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/utils/hp_naming.py
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2020 The HuggingFace Team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
|
| 15 |
+
import copy
|
| 16 |
+
import re
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
class TrialShortNamer:
|
| 20 |
+
PREFIX = "hp"
|
| 21 |
+
DEFAULTS = {}
|
| 22 |
+
NAMING_INFO = None
|
| 23 |
+
|
| 24 |
+
@classmethod
|
| 25 |
+
def set_defaults(cls, prefix, defaults):
|
| 26 |
+
cls.PREFIX = prefix
|
| 27 |
+
cls.DEFAULTS = defaults
|
| 28 |
+
cls.build_naming_info()
|
| 29 |
+
|
| 30 |
+
@staticmethod
|
| 31 |
+
def shortname_for_word(info, word):
|
| 32 |
+
if len(word) == 0:
|
| 33 |
+
return ""
|
| 34 |
+
short_word = None
|
| 35 |
+
if any(char.isdigit() for char in word):
|
| 36 |
+
raise Exception(f"Parameters should not contain numbers: '{word}' contains a number")
|
| 37 |
+
if word in info["short_word"]:
|
| 38 |
+
return info["short_word"][word]
|
| 39 |
+
for prefix_len in range(1, len(word) + 1):
|
| 40 |
+
prefix = word[:prefix_len]
|
| 41 |
+
if prefix in info["reverse_short_word"]:
|
| 42 |
+
continue
|
| 43 |
+
else:
|
| 44 |
+
short_word = prefix
|
| 45 |
+
break
|
| 46 |
+
|
| 47 |
+
if short_word is None:
|
| 48 |
+
# Paranoid fallback
|
| 49 |
+
def int_to_alphabetic(integer):
|
| 50 |
+
s = ""
|
| 51 |
+
while integer != 0:
|
| 52 |
+
s = chr(ord("A") + integer % 10) + s
|
| 53 |
+
integer //= 10
|
| 54 |
+
return s
|
| 55 |
+
|
| 56 |
+
i = 0
|
| 57 |
+
while True:
|
| 58 |
+
sword = word + "#" + int_to_alphabetic(i)
|
| 59 |
+
if sword in info["reverse_short_word"]:
|
| 60 |
+
continue
|
| 61 |
+
else:
|
| 62 |
+
short_word = sword
|
| 63 |
+
break
|
| 64 |
+
|
| 65 |
+
info["short_word"][word] = short_word
|
| 66 |
+
info["reverse_short_word"][short_word] = word
|
| 67 |
+
return short_word
|
| 68 |
+
|
| 69 |
+
@staticmethod
|
| 70 |
+
def shortname_for_key(info, param_name):
|
| 71 |
+
words = param_name.split("_")
|
| 72 |
+
|
| 73 |
+
shortname_parts = [TrialShortNamer.shortname_for_word(info, word) for word in words]
|
| 74 |
+
|
| 75 |
+
# We try to create a separatorless short name, but if there is a collision we have to fallback
|
| 76 |
+
# to a separated short name
|
| 77 |
+
separators = ["", "_"]
|
| 78 |
+
|
| 79 |
+
for separator in separators:
|
| 80 |
+
shortname = separator.join(shortname_parts)
|
| 81 |
+
if shortname not in info["reverse_short_param"]:
|
| 82 |
+
info["short_param"][param_name] = shortname
|
| 83 |
+
info["reverse_short_param"][shortname] = param_name
|
| 84 |
+
return shortname
|
| 85 |
+
|
| 86 |
+
return param_name
|
| 87 |
+
|
| 88 |
+
@staticmethod
|
| 89 |
+
def add_new_param_name(info, param_name):
|
| 90 |
+
short_name = TrialShortNamer.shortname_for_key(info, param_name)
|
| 91 |
+
info["short_param"][param_name] = short_name
|
| 92 |
+
info["reverse_short_param"][short_name] = param_name
|
| 93 |
+
|
| 94 |
+
@classmethod
|
| 95 |
+
def build_naming_info(cls):
|
| 96 |
+
if cls.NAMING_INFO is not None:
|
| 97 |
+
return
|
| 98 |
+
|
| 99 |
+
info = {
|
| 100 |
+
"short_word": {},
|
| 101 |
+
"reverse_short_word": {},
|
| 102 |
+
"short_param": {},
|
| 103 |
+
"reverse_short_param": {},
|
| 104 |
+
}
|
| 105 |
+
|
| 106 |
+
field_keys = list(cls.DEFAULTS.keys())
|
| 107 |
+
|
| 108 |
+
for k in field_keys:
|
| 109 |
+
cls.add_new_param_name(info, k)
|
| 110 |
+
|
| 111 |
+
cls.NAMING_INFO = info
|
| 112 |
+
|
| 113 |
+
@classmethod
|
| 114 |
+
def shortname(cls, params):
|
| 115 |
+
cls.build_naming_info()
|
| 116 |
+
assert cls.PREFIX is not None
|
| 117 |
+
name = [copy.copy(cls.PREFIX)]
|
| 118 |
+
|
| 119 |
+
for k, v in params.items():
|
| 120 |
+
if k not in cls.DEFAULTS:
|
| 121 |
+
raise Exception(f"You should provide a default value for the param name {k} with value {v}")
|
| 122 |
+
if v == cls.DEFAULTS[k]:
|
| 123 |
+
# The default value is not added to the name
|
| 124 |
+
continue
|
| 125 |
+
|
| 126 |
+
key = cls.NAMING_INFO["short_param"][k]
|
| 127 |
+
|
| 128 |
+
if isinstance(v, bool):
|
| 129 |
+
v = 1 if v else 0
|
| 130 |
+
|
| 131 |
+
sep = "" if isinstance(v, (int, float)) else "-"
|
| 132 |
+
e = f"{key}{sep}{v}"
|
| 133 |
+
name.append(e)
|
| 134 |
+
|
| 135 |
+
return "_".join(name)
|
| 136 |
+
|
| 137 |
+
@classmethod
|
| 138 |
+
def parse_repr(cls, repr):
|
| 139 |
+
repr = repr[len(cls.PREFIX) + 1 :]
|
| 140 |
+
if repr == "":
|
| 141 |
+
values = []
|
| 142 |
+
else:
|
| 143 |
+
values = repr.split("_")
|
| 144 |
+
|
| 145 |
+
parameters = {}
|
| 146 |
+
|
| 147 |
+
for value in values:
|
| 148 |
+
if "-" in value:
|
| 149 |
+
p_k, p_v = value.split("-")
|
| 150 |
+
else:
|
| 151 |
+
p_k = re.sub("[0-9.]", "", value)
|
| 152 |
+
p_v = float(re.sub("[^0-9.]", "", value))
|
| 153 |
+
|
| 154 |
+
key = cls.NAMING_INFO["reverse_short_param"][p_k]
|
| 155 |
+
|
| 156 |
+
parameters[key] = p_v
|
| 157 |
+
|
| 158 |
+
for k in cls.DEFAULTS:
|
| 159 |
+
if k not in parameters:
|
| 160 |
+
parameters[k] = cls.DEFAULTS[k]
|
| 161 |
+
|
| 162 |
+
return parameters
|
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/utils/loading_report.py
ADDED
|
@@ -0,0 +1,280 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2025 The HuggingFace Inc. team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
import logging
|
| 15 |
+
import re
|
| 16 |
+
import shutil
|
| 17 |
+
import sys
|
| 18 |
+
from collections import OrderedDict, defaultdict
|
| 19 |
+
from dataclasses import dataclass
|
| 20 |
+
from typing import Any
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
_DIGIT_RX = re.compile(r"(?<=\.)(\d+)(?=\.|$)") # numbers between dots or at the end
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
def _pattern_of(key: str) -> str:
|
| 27 |
+
"""Replace every dot-delimited integer with '*' to get the structure."""
|
| 28 |
+
return _DIGIT_RX.sub("*", key)
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
def _fmt_indices(values: list[int], cutoff=10) -> str:
|
| 32 |
+
"""Format a list of ints as single number, {a, ..., b}, or first...last."""
|
| 33 |
+
if len(values) == 1:
|
| 34 |
+
return str(values[0])
|
| 35 |
+
values = sorted(values)
|
| 36 |
+
if len(values) > cutoff:
|
| 37 |
+
return f"{values[0]}...{values[-1]}"
|
| 38 |
+
return ", ".join(map(str, values))
|
| 39 |
+
|
| 40 |
+
|
| 41 |
+
def update_key_name(mapping: dict[str, Any]) -> dict[str, Any]:
|
| 42 |
+
"""
|
| 43 |
+
Merge keys like 'layers.0.x', 'layers.1.x' into 'layers.{0, 1}.x'
|
| 44 |
+
BUT only merge together keys that have the exact same value.
|
| 45 |
+
Returns a new dict {merged_key: value}.
|
| 46 |
+
"""
|
| 47 |
+
# (pattern, value) -> list[set[int]] (per-star index values)
|
| 48 |
+
not_mapping = False
|
| 49 |
+
if not isinstance(mapping, dict):
|
| 50 |
+
mapping = {k: k for k in mapping}
|
| 51 |
+
not_mapping = True
|
| 52 |
+
|
| 53 |
+
bucket: dict[str, list[set[int] | Any]] = defaultdict(list)
|
| 54 |
+
for key, val in mapping.items():
|
| 55 |
+
digs = _DIGIT_RX.findall(key)
|
| 56 |
+
patt = _pattern_of(key)
|
| 57 |
+
for i, d in enumerate(digs):
|
| 58 |
+
if len(bucket[patt]) <= i:
|
| 59 |
+
bucket[patt].append(set())
|
| 60 |
+
bucket[patt][i].add(int(d))
|
| 61 |
+
bucket[patt].append(val)
|
| 62 |
+
|
| 63 |
+
out_items = {}
|
| 64 |
+
for patt, values in bucket.items():
|
| 65 |
+
sets, val = values[:-1], values[-1]
|
| 66 |
+
parts = patt.split("*") # stars are between parts
|
| 67 |
+
final = parts[0]
|
| 68 |
+
for i in range(1, len(parts)):
|
| 69 |
+
if i - 1 < len(sets) and sets[i - 1]:
|
| 70 |
+
insert = _fmt_indices(sorted(sets[i - 1]))
|
| 71 |
+
if len(sets[i - 1]) > 1:
|
| 72 |
+
final += "{" + insert + "}"
|
| 73 |
+
else:
|
| 74 |
+
final += insert
|
| 75 |
+
else:
|
| 76 |
+
final += "*"
|
| 77 |
+
final += parts[i]
|
| 78 |
+
|
| 79 |
+
out_items[final] = val
|
| 80 |
+
out = OrderedDict(out_items)
|
| 81 |
+
if not_mapping:
|
| 82 |
+
return out.keys()
|
| 83 |
+
return out
|
| 84 |
+
|
| 85 |
+
|
| 86 |
+
_ansi_re = re.compile(r"\x1b\[[0-9;]*m")
|
| 87 |
+
|
| 88 |
+
|
| 89 |
+
def _strip_ansi(s: str) -> str:
|
| 90 |
+
return _ansi_re.sub("", str(s))
|
| 91 |
+
|
| 92 |
+
|
| 93 |
+
def _pad(text, width):
|
| 94 |
+
t = str(text)
|
| 95 |
+
pad = max(0, width - len(_strip_ansi(t)))
|
| 96 |
+
return t + " " * pad
|
| 97 |
+
|
| 98 |
+
|
| 99 |
+
def _make_table(rows, headers):
|
| 100 |
+
# compute display widths while ignoring ANSI codes
|
| 101 |
+
cols = list(zip(*([headers] + rows))) if rows else [headers]
|
| 102 |
+
widths = [max(len(_strip_ansi(x)) for x in col) for col in cols]
|
| 103 |
+
header_line = " | ".join(_pad(h, w) for h, w in zip(headers, widths))
|
| 104 |
+
sep_line = "-+-".join("-" * w for w in widths)
|
| 105 |
+
body = [" | ".join(_pad(c, w) for c, w in zip(r, widths)) for r in rows]
|
| 106 |
+
return "\n".join([header_line, sep_line] + body)
|
| 107 |
+
|
| 108 |
+
|
| 109 |
+
PALETTE = {
|
| 110 |
+
"reset": "[0m",
|
| 111 |
+
"red": "[31m",
|
| 112 |
+
"yellow": "[33m",
|
| 113 |
+
"orange": "[38;5;208m",
|
| 114 |
+
"purple": "[35m",
|
| 115 |
+
"bold": "[1m",
|
| 116 |
+
"italic": "[3m",
|
| 117 |
+
"dim": "[2m",
|
| 118 |
+
}
|
| 119 |
+
|
| 120 |
+
|
| 121 |
+
def _style(s, color):
|
| 122 |
+
"""Return color/style-formatted input `s` if `sys.stdout` is interactive, e.g. connected to a terminal."""
|
| 123 |
+
if sys.stdout.isatty():
|
| 124 |
+
return f"{PALETTE[color]}{s}{PALETTE['reset']}"
|
| 125 |
+
else:
|
| 126 |
+
return s
|
| 127 |
+
|
| 128 |
+
|
| 129 |
+
def _get_terminal_width(default=80):
|
| 130 |
+
try:
|
| 131 |
+
return shutil.get_terminal_size().columns
|
| 132 |
+
except Exception:
|
| 133 |
+
return default
|
| 134 |
+
|
| 135 |
+
|
| 136 |
+
@dataclass
|
| 137 |
+
class LoadStateDictInfo:
|
| 138 |
+
"""
|
| 139 |
+
Mutable container for state-dict loading results and diagnostics. Each entry in this structure is mutable,
|
| 140 |
+
and will usually be mutated in-place during the loading pipeline.
|
| 141 |
+
|
| 142 |
+
Attributes:
|
| 143 |
+
missing_keys (`set[str]`):
|
| 144 |
+
Keys that are missing from the loaded checkpoints but expected in the model's architecture.
|
| 145 |
+
unexpected_keys (`set[str]`):
|
| 146 |
+
Keys that are found in the checkpoints, but not expected in the model's architecture.
|
| 147 |
+
mismatched_keys (`set[tuple[str, tuple[int], tuple[int]]]`):
|
| 148 |
+
Keys that are found in the checkpoints and are expected in the model's architecture, but with a different shape.
|
| 149 |
+
error_msgs ( `list[str]`):
|
| 150 |
+
Some potential error messages.
|
| 151 |
+
conversion_errors (`dict[str, str]`):
|
| 152 |
+
Errors happening during the on-the-fly weight conversion process.
|
| 153 |
+
"""
|
| 154 |
+
|
| 155 |
+
missing_keys: set[str]
|
| 156 |
+
unexpected_keys: set[str]
|
| 157 |
+
mismatched_keys: set[tuple[str, tuple[int], tuple[int]]]
|
| 158 |
+
error_msgs: list[str]
|
| 159 |
+
conversion_errors: dict[str, str]
|
| 160 |
+
|
| 161 |
+
def missing_and_mismatched(self):
|
| 162 |
+
"""Return all effective missing keys, including `missing` and `mismatched` keys."""
|
| 163 |
+
return self.missing_keys | {k[0] for k in self.mismatched_keys}
|
| 164 |
+
|
| 165 |
+
def to_dict(self):
|
| 166 |
+
# Does not include the `conversion_errors` to be coherent with legacy reporting in the tests
|
| 167 |
+
return {
|
| 168 |
+
"missing_keys": self.missing_keys,
|
| 169 |
+
"unexpected_keys": self.unexpected_keys,
|
| 170 |
+
"mismatched_keys": self.mismatched_keys,
|
| 171 |
+
"error_msgs": self.error_msgs,
|
| 172 |
+
}
|
| 173 |
+
|
| 174 |
+
def create_loading_report(self) -> str | None:
|
| 175 |
+
"""Generate the minimal table of a loading report."""
|
| 176 |
+
term_w = _get_terminal_width()
|
| 177 |
+
|
| 178 |
+
rows = []
|
| 179 |
+
tips = "\n\nNotes:"
|
| 180 |
+
if self.unexpected_keys:
|
| 181 |
+
tips += f"\n- {_style('UNEXPECTED:', 'orange')}\t" + _style(
|
| 182 |
+
"can be ignored when loading from different task/architecture; not ok if you expect identical arch.",
|
| 183 |
+
"italic",
|
| 184 |
+
)
|
| 185 |
+
for k in update_key_name(self.unexpected_keys):
|
| 186 |
+
status = _style("UNEXPECTED", "orange")
|
| 187 |
+
rows.append([k, status, "", ""])
|
| 188 |
+
|
| 189 |
+
if self.missing_keys:
|
| 190 |
+
tips += f"\n- {_style('MISSING:', 'red')}\t" + _style(
|
| 191 |
+
"those params were newly initialized because missing from the checkpoint. Consider training on your downstream task.",
|
| 192 |
+
"italic",
|
| 193 |
+
)
|
| 194 |
+
for k in update_key_name(self.missing_keys):
|
| 195 |
+
status = _style("MISSING", "red")
|
| 196 |
+
rows.append([k, status, ""])
|
| 197 |
+
|
| 198 |
+
if self.mismatched_keys:
|
| 199 |
+
tips += f"\n- {_style('MISMATCH:', 'yellow')}\t" + _style(
|
| 200 |
+
"ckpt weights were loaded, but they did not match the original empty weight shapes.", "italic"
|
| 201 |
+
)
|
| 202 |
+
iterator = {a: (b, c) for a, b, c in self.mismatched_keys}
|
| 203 |
+
for key, (shape_ckpt, shape_model) in update_key_name(iterator).items():
|
| 204 |
+
status = _style("MISMATCH", "yellow")
|
| 205 |
+
data = [
|
| 206 |
+
key,
|
| 207 |
+
status,
|
| 208 |
+
f"Reinit due to size mismatch - ckpt: {str(shape_ckpt)} vs model:{str(shape_model)}",
|
| 209 |
+
]
|
| 210 |
+
rows.append(data)
|
| 211 |
+
|
| 212 |
+
if self.conversion_errors:
|
| 213 |
+
tips += f"\n- {_style('CONVERSION:', 'purple')}\t" + _style(
|
| 214 |
+
"originate from the conversion scheme", "italic"
|
| 215 |
+
)
|
| 216 |
+
for k, v in update_key_name(self.conversion_errors).items():
|
| 217 |
+
status = _style("CONVERSION", "purple")
|
| 218 |
+
_details = f"\n\n{v}\n\n"
|
| 219 |
+
rows.append([k, status, _details])
|
| 220 |
+
|
| 221 |
+
# If nothing is wrong, return None
|
| 222 |
+
if len(rows) == 0:
|
| 223 |
+
return None
|
| 224 |
+
|
| 225 |
+
headers = ["Key", "Status"]
|
| 226 |
+
if term_w > 200:
|
| 227 |
+
headers += ["Details"]
|
| 228 |
+
else:
|
| 229 |
+
headers += ["", ""]
|
| 230 |
+
table = _make_table(rows, headers=headers)
|
| 231 |
+
report = table + tips
|
| 232 |
+
|
| 233 |
+
return report
|
| 234 |
+
|
| 235 |
+
|
| 236 |
+
def log_state_dict_report(
|
| 237 |
+
model,
|
| 238 |
+
pretrained_model_name_or_path: str,
|
| 239 |
+
ignore_mismatched_sizes: bool,
|
| 240 |
+
loading_info: LoadStateDictInfo,
|
| 241 |
+
logger: logging.Logger | None = None,
|
| 242 |
+
):
|
| 243 |
+
"""
|
| 244 |
+
Log a readable report about state_dict loading issues.
|
| 245 |
+
|
| 246 |
+
This version is terminal-size aware: for very small terminals it falls back to a compact
|
| 247 |
+
Key | Status view so output doesn't wrap badly.
|
| 248 |
+
"""
|
| 249 |
+
if logger is None:
|
| 250 |
+
logger = logging.getLogger(__name__)
|
| 251 |
+
|
| 252 |
+
# Re-raise errors early if needed
|
| 253 |
+
if loading_info.error_msgs:
|
| 254 |
+
error_msg = "\n\t".join(loading_info.error_msgs)
|
| 255 |
+
if "size mismatch" in error_msg:
|
| 256 |
+
error_msg += (
|
| 257 |
+
"\n\tYou may consider adding `ignore_mismatched_sizes=True` to `from_pretrained(...)` if appropriate."
|
| 258 |
+
)
|
| 259 |
+
raise RuntimeError(f"Error(s) in loading state_dict for {model.__class__.__name__}:\n\t{error_msg}")
|
| 260 |
+
|
| 261 |
+
# Create the report table
|
| 262 |
+
report = loading_info.create_loading_report()
|
| 263 |
+
if report is None:
|
| 264 |
+
return
|
| 265 |
+
|
| 266 |
+
prelude = f"{PALETTE['bold']}{model.__class__.__name__} LOAD REPORT{PALETTE['reset']} from: {pretrained_model_name_or_path}\n"
|
| 267 |
+
|
| 268 |
+
# Log the report as warning
|
| 269 |
+
logger.warning(prelude + report)
|
| 270 |
+
|
| 271 |
+
# Re-raise in those case, after the report
|
| 272 |
+
if loading_info.conversion_errors:
|
| 273 |
+
raise RuntimeError(
|
| 274 |
+
"We encountered some issues during automatic conversion of the weights. For details look at the `CONVERSION` entries of "
|
| 275 |
+
"the above report!"
|
| 276 |
+
)
|
| 277 |
+
if not ignore_mismatched_sizes and loading_info.mismatched_keys:
|
| 278 |
+
raise RuntimeError(
|
| 279 |
+
"You set `ignore_mismatched_sizes` to `False`, thus raising an error. For details look at the above report!"
|
| 280 |
+
)
|
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/utils/logging.py
ADDED
|
@@ -0,0 +1,441 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2020 Optuna, Hugging Face
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
"""Logging utilities."""
|
| 15 |
+
|
| 16 |
+
import functools
|
| 17 |
+
import logging
|
| 18 |
+
import os
|
| 19 |
+
import sys
|
| 20 |
+
import threading
|
| 21 |
+
from collections.abc import Callable
|
| 22 |
+
from logging import (
|
| 23 |
+
CRITICAL, # NOQA
|
| 24 |
+
DEBUG,
|
| 25 |
+
ERROR,
|
| 26 |
+
FATAL, # NOQA
|
| 27 |
+
INFO,
|
| 28 |
+
NOTSET, # NOQA
|
| 29 |
+
WARN, # NOQA
|
| 30 |
+
WARNING,
|
| 31 |
+
)
|
| 32 |
+
from logging import captureWarnings as _captureWarnings
|
| 33 |
+
from typing import Any
|
| 34 |
+
|
| 35 |
+
import huggingface_hub.utils as hf_hub_utils
|
| 36 |
+
from tqdm import auto as tqdm_lib
|
| 37 |
+
|
| 38 |
+
from .._typing import TransformersLogger
|
| 39 |
+
|
| 40 |
+
|
| 41 |
+
_lock = threading.Lock()
|
| 42 |
+
_default_handler: logging.Handler | None = None
|
| 43 |
+
|
| 44 |
+
log_levels = {
|
| 45 |
+
"detail": logging.DEBUG, # will also print filename and line number
|
| 46 |
+
"debug": logging.DEBUG,
|
| 47 |
+
"info": logging.INFO,
|
| 48 |
+
"warning": logging.WARNING,
|
| 49 |
+
"error": logging.ERROR,
|
| 50 |
+
"critical": logging.CRITICAL,
|
| 51 |
+
}
|
| 52 |
+
|
| 53 |
+
_default_log_level = logging.WARNING
|
| 54 |
+
|
| 55 |
+
_tqdm_active = not hf_hub_utils.are_progress_bars_disabled()
|
| 56 |
+
_tqdm_hook: Callable[[Callable[..., Any], tuple[Any, ...], dict[str, Any]], Any] | None = None
|
| 57 |
+
|
| 58 |
+
|
| 59 |
+
def _get_default_logging_level():
|
| 60 |
+
"""
|
| 61 |
+
If TRANSFORMERS_VERBOSITY env var is set to one of the valid choices return that as the new default level. If it is
|
| 62 |
+
not - fall back to `_default_log_level`
|
| 63 |
+
"""
|
| 64 |
+
env_level_str = os.getenv("TRANSFORMERS_VERBOSITY", None)
|
| 65 |
+
if env_level_str:
|
| 66 |
+
if env_level_str in log_levels:
|
| 67 |
+
return log_levels[env_level_str]
|
| 68 |
+
else:
|
| 69 |
+
logging.getLogger().warning(
|
| 70 |
+
f"Unknown option TRANSFORMERS_VERBOSITY={env_level_str}, "
|
| 71 |
+
f"has to be one of: {', '.join(log_levels.keys())}"
|
| 72 |
+
)
|
| 73 |
+
return _default_log_level
|
| 74 |
+
|
| 75 |
+
|
| 76 |
+
def _get_library_name() -> str:
|
| 77 |
+
return __name__.split(".")[0]
|
| 78 |
+
|
| 79 |
+
|
| 80 |
+
def _get_library_root_logger() -> logging.Logger:
|
| 81 |
+
return logging.getLogger(_get_library_name())
|
| 82 |
+
|
| 83 |
+
|
| 84 |
+
def _configure_library_root_logger() -> None:
|
| 85 |
+
global _default_handler
|
| 86 |
+
|
| 87 |
+
with _lock:
|
| 88 |
+
if _default_handler:
|
| 89 |
+
# This library has already configured the library root logger.
|
| 90 |
+
return
|
| 91 |
+
_default_handler = logging.StreamHandler() # Set sys.stderr as stream.
|
| 92 |
+
# set defaults based on https://github.com/pyinstaller/pyinstaller/issues/7334#issuecomment-1357447176
|
| 93 |
+
if sys.stderr is None:
|
| 94 |
+
sys.stderr = open(os.devnull, "w")
|
| 95 |
+
|
| 96 |
+
_default_handler.flush = sys.stderr.flush
|
| 97 |
+
|
| 98 |
+
# Apply our default configuration to the library root logger.
|
| 99 |
+
library_root_logger = _get_library_root_logger()
|
| 100 |
+
library_root_logger.addHandler(_default_handler)
|
| 101 |
+
library_root_logger.setLevel(_get_default_logging_level())
|
| 102 |
+
# Always show lib when logging in non-verbose mode. Note, other libs
|
| 103 |
+
# use `transformers.logger` directly, so we check `lib_name` to be safe
|
| 104 |
+
lib_name = _get_library_name()
|
| 105 |
+
logging_format = f"[{lib_name}] %(message)s"
|
| 106 |
+
|
| 107 |
+
# if logging level is debug, we add pathname and lineno to formatter for easy debugging
|
| 108 |
+
if os.getenv("TRANSFORMERS_VERBOSITY", None) == "detail":
|
| 109 |
+
logging_format = "%(levelname)s [%(name)s:%(lineno)s] %(asctime)s %(message)s"
|
| 110 |
+
|
| 111 |
+
formatter = logging.Formatter(logging_format)
|
| 112 |
+
_default_handler.setFormatter(formatter)
|
| 113 |
+
|
| 114 |
+
ci = os.getenv("CI")
|
| 115 |
+
is_ci = ci is not None and ci.upper() in {"1", "ON", "YES", "TRUE"}
|
| 116 |
+
library_root_logger.propagate = is_ci
|
| 117 |
+
|
| 118 |
+
|
| 119 |
+
def _reset_library_root_logger() -> None:
|
| 120 |
+
global _default_handler
|
| 121 |
+
|
| 122 |
+
with _lock:
|
| 123 |
+
if not _default_handler:
|
| 124 |
+
return
|
| 125 |
+
|
| 126 |
+
library_root_logger = _get_library_root_logger()
|
| 127 |
+
library_root_logger.removeHandler(_default_handler)
|
| 128 |
+
library_root_logger.setLevel(logging.NOTSET)
|
| 129 |
+
_default_handler = None
|
| 130 |
+
|
| 131 |
+
|
| 132 |
+
def get_log_levels_dict():
|
| 133 |
+
return log_levels
|
| 134 |
+
|
| 135 |
+
|
| 136 |
+
def captureWarnings(capture):
|
| 137 |
+
"""
|
| 138 |
+
Calls the `captureWarnings` method from the logging library to enable management of the warnings emitted by the
|
| 139 |
+
`warnings` library.
|
| 140 |
+
|
| 141 |
+
Read more about this method here:
|
| 142 |
+
https://docs.python.org/3/library/logging.html#integration-with-the-warnings-module
|
| 143 |
+
|
| 144 |
+
All warnings will be logged through the `py.warnings` logger.
|
| 145 |
+
|
| 146 |
+
Careful: this method also adds a handler to this logger if it does not already have one, and updates the logging
|
| 147 |
+
level of that logger to the library's root logger.
|
| 148 |
+
"""
|
| 149 |
+
logger = get_logger("py.warnings")
|
| 150 |
+
|
| 151 |
+
if not logger.handlers:
|
| 152 |
+
logger.addHandler(_default_handler)
|
| 153 |
+
|
| 154 |
+
logger.setLevel(_get_library_root_logger().level)
|
| 155 |
+
|
| 156 |
+
_captureWarnings(capture)
|
| 157 |
+
|
| 158 |
+
|
| 159 |
+
def get_logger(name: str | None = None) -> TransformersLogger:
|
| 160 |
+
"""
|
| 161 |
+
Return a logger with the specified name.
|
| 162 |
+
|
| 163 |
+
This function is not supposed to be directly accessed unless you are writing a custom transformers module.
|
| 164 |
+
"""
|
| 165 |
+
|
| 166 |
+
if name is None:
|
| 167 |
+
name = _get_library_name()
|
| 168 |
+
|
| 169 |
+
_configure_library_root_logger()
|
| 170 |
+
return logging.getLogger(name)
|
| 171 |
+
|
| 172 |
+
|
| 173 |
+
def get_verbosity() -> int:
|
| 174 |
+
"""
|
| 175 |
+
Return the current level for the 🤗 Transformers's root logger as an int.
|
| 176 |
+
|
| 177 |
+
Returns:
|
| 178 |
+
`int`: The logging level.
|
| 179 |
+
|
| 180 |
+
<Tip>
|
| 181 |
+
|
| 182 |
+
🤗 Transformers has following logging levels:
|
| 183 |
+
|
| 184 |
+
- 50: `transformers.logging.CRITICAL` or `transformers.logging.FATAL`
|
| 185 |
+
- 40: `transformers.logging.ERROR`
|
| 186 |
+
- 30: `transformers.logging.WARNING` or `transformers.logging.WARN`
|
| 187 |
+
- 20: `transformers.logging.INFO`
|
| 188 |
+
- 10: `transformers.logging.DEBUG`
|
| 189 |
+
|
| 190 |
+
</Tip>"""
|
| 191 |
+
|
| 192 |
+
_configure_library_root_logger()
|
| 193 |
+
return _get_library_root_logger().getEffectiveLevel()
|
| 194 |
+
|
| 195 |
+
|
| 196 |
+
def set_verbosity(verbosity: int) -> None:
|
| 197 |
+
"""
|
| 198 |
+
Set the verbosity level for the 🤗 Transformers's root logger.
|
| 199 |
+
|
| 200 |
+
Args:
|
| 201 |
+
verbosity (`int`):
|
| 202 |
+
Logging level, e.g., one of:
|
| 203 |
+
|
| 204 |
+
- `transformers.logging.CRITICAL` or `transformers.logging.FATAL`
|
| 205 |
+
- `transformers.logging.ERROR`
|
| 206 |
+
- `transformers.logging.WARNING` or `transformers.logging.WARN`
|
| 207 |
+
- `transformers.logging.INFO`
|
| 208 |
+
- `transformers.logging.DEBUG`
|
| 209 |
+
"""
|
| 210 |
+
|
| 211 |
+
_configure_library_root_logger()
|
| 212 |
+
_get_library_root_logger().setLevel(verbosity)
|
| 213 |
+
|
| 214 |
+
|
| 215 |
+
def set_verbosity_info():
|
| 216 |
+
"""Set the verbosity to the `INFO` level."""
|
| 217 |
+
return set_verbosity(INFO)
|
| 218 |
+
|
| 219 |
+
|
| 220 |
+
def set_verbosity_warning():
|
| 221 |
+
"""Set the verbosity to the `WARNING` level."""
|
| 222 |
+
return set_verbosity(WARNING)
|
| 223 |
+
|
| 224 |
+
|
| 225 |
+
def set_verbosity_debug():
|
| 226 |
+
"""Set the verbosity to the `DEBUG` level."""
|
| 227 |
+
return set_verbosity(DEBUG)
|
| 228 |
+
|
| 229 |
+
|
| 230 |
+
def set_verbosity_error():
|
| 231 |
+
"""Set the verbosity to the `ERROR` level."""
|
| 232 |
+
return set_verbosity(ERROR)
|
| 233 |
+
|
| 234 |
+
|
| 235 |
+
def disable_default_handler() -> None:
|
| 236 |
+
"""Disable the default handler of the HuggingFace Transformers's root logger."""
|
| 237 |
+
|
| 238 |
+
_configure_library_root_logger()
|
| 239 |
+
|
| 240 |
+
assert _default_handler is not None
|
| 241 |
+
_get_library_root_logger().removeHandler(_default_handler)
|
| 242 |
+
|
| 243 |
+
|
| 244 |
+
def enable_default_handler() -> None:
|
| 245 |
+
"""Enable the default handler of the HuggingFace Transformers's root logger."""
|
| 246 |
+
|
| 247 |
+
_configure_library_root_logger()
|
| 248 |
+
|
| 249 |
+
assert _default_handler is not None
|
| 250 |
+
_get_library_root_logger().addHandler(_default_handler)
|
| 251 |
+
|
| 252 |
+
|
| 253 |
+
def add_handler(handler: logging.Handler) -> None:
|
| 254 |
+
"""adds a handler to the HuggingFace Transformers's root logger."""
|
| 255 |
+
|
| 256 |
+
_configure_library_root_logger()
|
| 257 |
+
|
| 258 |
+
assert handler is not None
|
| 259 |
+
_get_library_root_logger().addHandler(handler)
|
| 260 |
+
|
| 261 |
+
|
| 262 |
+
def remove_handler(handler: logging.Handler) -> None:
|
| 263 |
+
"""removes given handler from the HuggingFace Transformers's root logger."""
|
| 264 |
+
|
| 265 |
+
_configure_library_root_logger()
|
| 266 |
+
|
| 267 |
+
assert handler is not None and handler not in _get_library_root_logger().handlers
|
| 268 |
+
_get_library_root_logger().removeHandler(handler)
|
| 269 |
+
|
| 270 |
+
|
| 271 |
+
def disable_propagation() -> None:
|
| 272 |
+
"""
|
| 273 |
+
Disable propagation of the library log outputs. Note that log propagation is disabled by default.
|
| 274 |
+
"""
|
| 275 |
+
|
| 276 |
+
_configure_library_root_logger()
|
| 277 |
+
_get_library_root_logger().propagate = False
|
| 278 |
+
|
| 279 |
+
|
| 280 |
+
def enable_propagation() -> None:
|
| 281 |
+
"""
|
| 282 |
+
Enable propagation of the library log outputs. Please disable the HuggingFace Transformers's default handler to
|
| 283 |
+
prevent double logging if the root logger has been configured.
|
| 284 |
+
"""
|
| 285 |
+
|
| 286 |
+
_configure_library_root_logger()
|
| 287 |
+
_get_library_root_logger().propagate = True
|
| 288 |
+
|
| 289 |
+
|
| 290 |
+
def enable_explicit_format() -> None:
|
| 291 |
+
"""
|
| 292 |
+
Enable explicit formatting for every HuggingFace Transformers's logger. The explicit formatter is as follows:
|
| 293 |
+
```
|
| 294 |
+
[LEVELNAME|FILENAME|LINE NUMBER] TIME >> MESSAGE
|
| 295 |
+
```
|
| 296 |
+
All handlers currently bound to the root logger are affected by this method.
|
| 297 |
+
"""
|
| 298 |
+
handlers = _get_library_root_logger().handlers
|
| 299 |
+
|
| 300 |
+
for handler in handlers:
|
| 301 |
+
formatter = logging.Formatter("[%(levelname)s|%(filename)s:%(lineno)s] %(asctime)s >> %(message)s")
|
| 302 |
+
handler.setFormatter(formatter)
|
| 303 |
+
|
| 304 |
+
|
| 305 |
+
def reset_format() -> None:
|
| 306 |
+
"""
|
| 307 |
+
Resets the formatting for HuggingFace Transformers's loggers.
|
| 308 |
+
|
| 309 |
+
All handlers currently bound to the root logger are affected by this method.
|
| 310 |
+
"""
|
| 311 |
+
handlers = _get_library_root_logger().handlers
|
| 312 |
+
|
| 313 |
+
for handler in handlers:
|
| 314 |
+
handler.setFormatter(None)
|
| 315 |
+
|
| 316 |
+
|
| 317 |
+
def warning_advice(self, *args, **kwargs):
|
| 318 |
+
"""
|
| 319 |
+
This method is identical to `logger.warning()`, but if env var TRANSFORMERS_NO_ADVISORY_WARNINGS=1 is set, this
|
| 320 |
+
warning will not be printed
|
| 321 |
+
"""
|
| 322 |
+
no_advisory_warnings = os.getenv("TRANSFORMERS_NO_ADVISORY_WARNINGS")
|
| 323 |
+
if no_advisory_warnings:
|
| 324 |
+
return
|
| 325 |
+
self.warning(*args, **kwargs)
|
| 326 |
+
|
| 327 |
+
|
| 328 |
+
logging.Logger.warning_advice = warning_advice # type: ignore[unresolved-attribute]
|
| 329 |
+
|
| 330 |
+
|
| 331 |
+
@functools.lru_cache(None)
|
| 332 |
+
def warning_once(self, *args, **kwargs):
|
| 333 |
+
"""
|
| 334 |
+
This method is identical to `logger.warning()`, but will emit the warning with the same message only once
|
| 335 |
+
|
| 336 |
+
Note: The cache is for the function arguments, so 2 different callers using the same arguments will hit the cache.
|
| 337 |
+
The assumption here is that all warning messages are unique across the code. If they aren't then need to switch to
|
| 338 |
+
another type of cache that includes the caller frame information in the hashing function.
|
| 339 |
+
"""
|
| 340 |
+
self.warning(*args, **kwargs)
|
| 341 |
+
|
| 342 |
+
|
| 343 |
+
logging.Logger.warning_once = warning_once # type: ignore[unresolved-attribute]
|
| 344 |
+
|
| 345 |
+
|
| 346 |
+
@functools.lru_cache(None)
|
| 347 |
+
def info_once(self, *args, **kwargs):
|
| 348 |
+
"""
|
| 349 |
+
This method is identical to `logger.info()`, but will emit the info with the same message only once
|
| 350 |
+
|
| 351 |
+
Note: The cache is for the function arguments, so 2 different callers using the same arguments will hit the cache.
|
| 352 |
+
The assumption here is that all warning messages are unique across the code. If they aren't then need to switch to
|
| 353 |
+
another type of cache that includes the caller frame information in the hashing function.
|
| 354 |
+
"""
|
| 355 |
+
self.info(*args, **kwargs)
|
| 356 |
+
|
| 357 |
+
|
| 358 |
+
logging.Logger.info_once = info_once # type: ignore[unresolved-attribute]
|
| 359 |
+
|
| 360 |
+
|
| 361 |
+
class EmptyTqdm:
|
| 362 |
+
"""Dummy tqdm which doesn't do anything."""
|
| 363 |
+
|
| 364 |
+
def __init__(self, *args, **kwargs): # pylint: disable=unused-argument
|
| 365 |
+
self._iterator = args[0] if args else None
|
| 366 |
+
|
| 367 |
+
def __iter__(self):
|
| 368 |
+
return iter(self._iterator)
|
| 369 |
+
|
| 370 |
+
def __getattr__(self, _):
|
| 371 |
+
"""Return empty function."""
|
| 372 |
+
|
| 373 |
+
def empty_fn(*args, **kwargs): # pylint: disable=unused-argument
|
| 374 |
+
return
|
| 375 |
+
|
| 376 |
+
return empty_fn
|
| 377 |
+
|
| 378 |
+
def __enter__(self):
|
| 379 |
+
return self
|
| 380 |
+
|
| 381 |
+
def __exit__(self, type_, value, traceback):
|
| 382 |
+
return
|
| 383 |
+
|
| 384 |
+
|
| 385 |
+
class _tqdm_cls:
|
| 386 |
+
def __call__(self, *args, **kwargs):
|
| 387 |
+
factory = tqdm_lib.tqdm if _tqdm_active else EmptyTqdm
|
| 388 |
+
if _tqdm_hook is not None:
|
| 389 |
+
return _tqdm_hook(factory, args, kwargs)
|
| 390 |
+
return factory(*args, **kwargs)
|
| 391 |
+
|
| 392 |
+
def set_lock(self, *args, **kwargs):
|
| 393 |
+
self._lock = None
|
| 394 |
+
if _tqdm_active:
|
| 395 |
+
return tqdm_lib.tqdm.set_lock(*args, **kwargs)
|
| 396 |
+
|
| 397 |
+
def get_lock(self):
|
| 398 |
+
if _tqdm_active:
|
| 399 |
+
return tqdm_lib.tqdm.get_lock()
|
| 400 |
+
|
| 401 |
+
|
| 402 |
+
tqdm = _tqdm_cls()
|
| 403 |
+
|
| 404 |
+
|
| 405 |
+
def is_progress_bar_enabled() -> bool:
|
| 406 |
+
"""Return a boolean indicating whether tqdm progress bars are enabled."""
|
| 407 |
+
return bool(_tqdm_active)
|
| 408 |
+
|
| 409 |
+
|
| 410 |
+
def enable_progress_bar():
|
| 411 |
+
"""Enable tqdm progress bar."""
|
| 412 |
+
global _tqdm_active
|
| 413 |
+
_tqdm_active = True
|
| 414 |
+
hf_hub_utils.enable_progress_bars()
|
| 415 |
+
|
| 416 |
+
|
| 417 |
+
def disable_progress_bar():
|
| 418 |
+
"""Disable tqdm progress bar."""
|
| 419 |
+
global _tqdm_active
|
| 420 |
+
_tqdm_active = False
|
| 421 |
+
hf_hub_utils.disable_progress_bars()
|
| 422 |
+
|
| 423 |
+
|
| 424 |
+
def set_tqdm_hook(hook: Callable[[Callable[..., Any], tuple[Any, ...], dict[str, Any]], Any] | None):
|
| 425 |
+
"""
|
| 426 |
+
Set a hook that customizes tqdm creation.
|
| 427 |
+
|
| 428 |
+
The hook is called with the tqdm factory to use (either `tqdm.auto.tqdm` or an empty shim), along with the
|
| 429 |
+
positional and keyword arguments that would have been passed to tqdm. The hook should return an object compatible
|
| 430 |
+
with tqdm (i.e. implementing the methods your code relies on, such as `update`, `close`, context manager methods,
|
| 431 |
+
etc.).
|
| 432 |
+
|
| 433 |
+
Passing `None` clears the hook.
|
| 434 |
+
|
| 435 |
+
Returns:
|
| 436 |
+
The previous hook, which can be restored later.
|
| 437 |
+
"""
|
| 438 |
+
global _tqdm_hook
|
| 439 |
+
previous_hook = _tqdm_hook
|
| 440 |
+
_tqdm_hook = hook
|
| 441 |
+
return previous_hook
|
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/utils/network_logging.py
ADDED
|
@@ -0,0 +1,485 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2026 The HuggingFace Team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
|
| 15 |
+
from __future__ import annotations
|
| 16 |
+
|
| 17 |
+
import inspect
|
| 18 |
+
import json
|
| 19 |
+
import os
|
| 20 |
+
import threading
|
| 21 |
+
import time
|
| 22 |
+
from collections import defaultdict
|
| 23 |
+
from functools import wraps
|
| 24 |
+
from pathlib import Path
|
| 25 |
+
from typing import Any
|
| 26 |
+
|
| 27 |
+
import httpx
|
| 28 |
+
|
| 29 |
+
from .generic import strtobool
|
| 30 |
+
|
| 31 |
+
|
| 32 |
+
class _NetworkRequestTrace:
|
| 33 |
+
def __init__(self, request: httpx.Request):
|
| 34 |
+
self.request = request
|
| 35 |
+
self.started_at = time.perf_counter()
|
| 36 |
+
self.phase_started_at = {}
|
| 37 |
+
self.phases_ms = defaultdict(float)
|
| 38 |
+
|
| 39 |
+
def trace(self, name: str, info: dict[str, Any]) -> None:
|
| 40 |
+
parts = name.rsplit(".", 2)
|
| 41 |
+
if len(parts) != 3:
|
| 42 |
+
return
|
| 43 |
+
|
| 44 |
+
_, phase, state = parts
|
| 45 |
+
now = time.perf_counter()
|
| 46 |
+
if state == "started":
|
| 47 |
+
self.phase_started_at[phase] = now
|
| 48 |
+
elif state in {"complete", "failed"}:
|
| 49 |
+
phase_started_at = self.phase_started_at.pop(phase, None)
|
| 50 |
+
if phase_started_at is not None:
|
| 51 |
+
self.phases_ms[phase] += (now - phase_started_at) * 1000
|
| 52 |
+
|
| 53 |
+
def build_record(
|
| 54 |
+
self,
|
| 55 |
+
*,
|
| 56 |
+
response: httpx.Response | None = None,
|
| 57 |
+
error: BaseException | None = None,
|
| 58 |
+
stream: bool = False,
|
| 59 |
+
) -> dict[str, Any]:
|
| 60 |
+
total_ms = (time.perf_counter() - self.started_at) * 1000
|
| 61 |
+
url = self.request.url
|
| 62 |
+
host = url.host or ""
|
| 63 |
+
port = url.port
|
| 64 |
+
default_port = {"http": 80, "https": 443}.get(url.scheme)
|
| 65 |
+
host_display = host if port in (None, default_port) else f"{host}:{port}"
|
| 66 |
+
|
| 67 |
+
http_version = None
|
| 68 |
+
status_code = None
|
| 69 |
+
bytes_downloaded = None
|
| 70 |
+
response_complete = False
|
| 71 |
+
if response is not None:
|
| 72 |
+
status_code = response.status_code
|
| 73 |
+
response_complete = response.is_closed
|
| 74 |
+
raw_http_version = response.extensions.get("http_version")
|
| 75 |
+
if isinstance(raw_http_version, bytes):
|
| 76 |
+
http_version = raw_http_version.decode("ascii", errors="replace")
|
| 77 |
+
elif raw_http_version is not None:
|
| 78 |
+
http_version = str(raw_http_version)
|
| 79 |
+
|
| 80 |
+
if response_complete:
|
| 81 |
+
try:
|
| 82 |
+
bytes_downloaded = len(response.content)
|
| 83 |
+
except httpx.ResponseNotRead:
|
| 84 |
+
pass
|
| 85 |
+
|
| 86 |
+
return {
|
| 87 |
+
"method": self.request.method,
|
| 88 |
+
"scheme": url.scheme,
|
| 89 |
+
"host": host,
|
| 90 |
+
"host_display": host_display,
|
| 91 |
+
"port": port,
|
| 92 |
+
"path": url.path,
|
| 93 |
+
"has_query": bool(url.query),
|
| 94 |
+
"url": f"{url.scheme}://{host_display}{url.path}{'?...' if url.query else ''}",
|
| 95 |
+
"request_id": self.request.headers.get("x-amzn-trace-id") or self.request.headers.get("x-request-id"),
|
| 96 |
+
"status_code": status_code,
|
| 97 |
+
"http_version": http_version,
|
| 98 |
+
"bytes_downloaded": bytes_downloaded,
|
| 99 |
+
"total_ms": total_ms,
|
| 100 |
+
"stream": stream,
|
| 101 |
+
"response_complete": response_complete,
|
| 102 |
+
"phases_ms": dict(sorted(self.phases_ms.items())),
|
| 103 |
+
"error": None if error is None else f"{type(error).__name__}: {error}",
|
| 104 |
+
}
|
| 105 |
+
|
| 106 |
+
|
| 107 |
+
class _NetworkDebugProfiler:
|
| 108 |
+
def __init__(self):
|
| 109 |
+
self._records = []
|
| 110 |
+
self._lock = threading.Lock()
|
| 111 |
+
self._enabled = False
|
| 112 |
+
self._output_path = None
|
| 113 |
+
self._original_client_send = None
|
| 114 |
+
self._original_async_client_send = None
|
| 115 |
+
self._shared_dir = None
|
| 116 |
+
|
| 117 |
+
@property
|
| 118 |
+
def enabled(self) -> bool:
|
| 119 |
+
return self._enabled
|
| 120 |
+
|
| 121 |
+
def clear(self) -> None:
|
| 122 |
+
with self._lock:
|
| 123 |
+
self._records = []
|
| 124 |
+
|
| 125 |
+
def enable(self, output_path: str | os.PathLike | None = None) -> None:
|
| 126 |
+
if self._enabled:
|
| 127 |
+
self._output_path = None if output_path is None else os.fspath(output_path)
|
| 128 |
+
self.clear()
|
| 129 |
+
return
|
| 130 |
+
|
| 131 |
+
self._output_path = None if output_path is None else os.fspath(output_path)
|
| 132 |
+
self.clear()
|
| 133 |
+
|
| 134 |
+
profiler = self
|
| 135 |
+
self._original_client_send = httpx.Client.send
|
| 136 |
+
self._original_async_client_send = httpx.AsyncClient.send
|
| 137 |
+
|
| 138 |
+
@wraps(self._original_client_send)
|
| 139 |
+
def patched_client_send(client, request, *args, **kwargs):
|
| 140 |
+
return profiler._send_with_trace(profiler._original_client_send, client, request, *args, **kwargs)
|
| 141 |
+
|
| 142 |
+
@wraps(self._original_async_client_send)
|
| 143 |
+
async def patched_async_client_send(client, request, *args, **kwargs):
|
| 144 |
+
return await profiler._async_send_with_trace(
|
| 145 |
+
profiler._original_async_client_send, client, request, *args, **kwargs
|
| 146 |
+
)
|
| 147 |
+
|
| 148 |
+
httpx.Client.send = patched_client_send
|
| 149 |
+
httpx.AsyncClient.send = patched_async_client_send
|
| 150 |
+
self._enabled = True
|
| 151 |
+
|
| 152 |
+
def setup_shared_dir(self) -> str | None:
|
| 153 |
+
"""Create a shared temp directory for xdist workers to dump records into."""
|
| 154 |
+
if self._shared_dir is None:
|
| 155 |
+
import tempfile
|
| 156 |
+
|
| 157 |
+
self._shared_dir = tempfile.mkdtemp(prefix="network_debug_")
|
| 158 |
+
return self._shared_dir
|
| 159 |
+
|
| 160 |
+
def set_shared_dir(self, shared_dir: str) -> None:
|
| 161 |
+
"""Set the shared directory (called in xdist workers)."""
|
| 162 |
+
self._shared_dir = shared_dir
|
| 163 |
+
|
| 164 |
+
def dump_worker_records(self, worker_id: str | None = None) -> None:
|
| 165 |
+
"""Write this process's records to a file in the shared directory (called in workers)."""
|
| 166 |
+
if not self._shared_dir or not self._records:
|
| 167 |
+
return
|
| 168 |
+
worker_id = worker_id or f"pid{os.getpid()}"
|
| 169 |
+
dump_path = os.path.join(self._shared_dir, f"records_{worker_id}.json")
|
| 170 |
+
with self._lock:
|
| 171 |
+
records = [{**record, "phases_ms": dict(record["phases_ms"])} for record in self._records]
|
| 172 |
+
Path(dump_path).write_text(json.dumps(records), encoding="utf-8")
|
| 173 |
+
|
| 174 |
+
def load_worker_records(self) -> None:
|
| 175 |
+
"""Load all worker record files from the shared directory (called in controller)."""
|
| 176 |
+
if not self._shared_dir or not os.path.isdir(self._shared_dir):
|
| 177 |
+
return
|
| 178 |
+
import glob as glob_module
|
| 179 |
+
|
| 180 |
+
for record_file in glob_module.glob(os.path.join(self._shared_dir, "records_*.json")):
|
| 181 |
+
try:
|
| 182 |
+
records = json.loads(Path(record_file).read_text(encoding="utf-8"))
|
| 183 |
+
with self._lock:
|
| 184 |
+
for record in records:
|
| 185 |
+
record["phases_ms"] = defaultdict(float, record.get("phases_ms", {}))
|
| 186 |
+
self._records.append(record)
|
| 187 |
+
except (OSError, json.JSONDecodeError):
|
| 188 |
+
pass
|
| 189 |
+
|
| 190 |
+
def cleanup_shared_dir(self) -> None:
|
| 191 |
+
"""Remove the shared temp directory."""
|
| 192 |
+
if self._shared_dir and os.path.isdir(self._shared_dir):
|
| 193 |
+
import shutil
|
| 194 |
+
|
| 195 |
+
shutil.rmtree(self._shared_dir, ignore_errors=True)
|
| 196 |
+
self._shared_dir = None
|
| 197 |
+
|
| 198 |
+
def disable(self) -> None:
|
| 199 |
+
if not self._enabled:
|
| 200 |
+
return
|
| 201 |
+
|
| 202 |
+
httpx.Client.send = self._original_client_send
|
| 203 |
+
httpx.AsyncClient.send = self._original_async_client_send
|
| 204 |
+
self._enabled = False
|
| 205 |
+
self._original_client_send = None
|
| 206 |
+
self._original_async_client_send = None
|
| 207 |
+
self._output_path = None
|
| 208 |
+
self.clear()
|
| 209 |
+
|
| 210 |
+
def _append_record(self, record: dict[str, Any]) -> None:
|
| 211 |
+
with self._lock:
|
| 212 |
+
self._records.append(record)
|
| 213 |
+
|
| 214 |
+
def _wrap_trace_callback(self, request: httpx.Request, trace: _NetworkRequestTrace):
|
| 215 |
+
existing_trace = request.extensions.get("trace")
|
| 216 |
+
|
| 217 |
+
def wrapped_trace(name: str, info: dict[str, Any]) -> Any:
|
| 218 |
+
trace.trace(name, info)
|
| 219 |
+
if existing_trace is not None:
|
| 220 |
+
return existing_trace(name, info)
|
| 221 |
+
return None
|
| 222 |
+
|
| 223 |
+
return wrapped_trace
|
| 224 |
+
|
| 225 |
+
async def _awrap_trace_callback(self, request: httpx.Request, trace: _NetworkRequestTrace):
|
| 226 |
+
existing_trace = request.extensions.get("trace")
|
| 227 |
+
|
| 228 |
+
async def wrapped_trace(name: str, info: dict[str, Any]) -> Any:
|
| 229 |
+
trace.trace(name, info)
|
| 230 |
+
if existing_trace is not None:
|
| 231 |
+
result = existing_trace(name, info)
|
| 232 |
+
if inspect.isawaitable(result):
|
| 233 |
+
return await result
|
| 234 |
+
return result
|
| 235 |
+
return None
|
| 236 |
+
|
| 237 |
+
return wrapped_trace
|
| 238 |
+
|
| 239 |
+
def _send_with_trace(self, original_send, client, request: httpx.Request, *args, **kwargs):
|
| 240 |
+
trace = _NetworkRequestTrace(request)
|
| 241 |
+
request.extensions = dict(request.extensions)
|
| 242 |
+
request.extensions["trace"] = self._wrap_trace_callback(request, trace)
|
| 243 |
+
|
| 244 |
+
try:
|
| 245 |
+
response = original_send(client, request, *args, **kwargs)
|
| 246 |
+
except Exception as error:
|
| 247 |
+
self._append_record(trace.build_record(error=error, stream=kwargs.get("stream", False)))
|
| 248 |
+
raise
|
| 249 |
+
|
| 250 |
+
self._append_record(trace.build_record(response=response, stream=kwargs.get("stream", False)))
|
| 251 |
+
return response
|
| 252 |
+
|
| 253 |
+
async def _async_send_with_trace(self, original_send, client, request: httpx.Request, *args, **kwargs):
|
| 254 |
+
trace = _NetworkRequestTrace(request)
|
| 255 |
+
request.extensions = dict(request.extensions)
|
| 256 |
+
request.extensions["trace"] = await self._awrap_trace_callback(request, trace)
|
| 257 |
+
|
| 258 |
+
try:
|
| 259 |
+
response = await original_send(client, request, *args, **kwargs)
|
| 260 |
+
except Exception as error:
|
| 261 |
+
self._append_record(trace.build_record(error=error, stream=kwargs.get("stream", False)))
|
| 262 |
+
raise
|
| 263 |
+
|
| 264 |
+
self._append_record(trace.build_record(response=response, stream=kwargs.get("stream", False)))
|
| 265 |
+
return response
|
| 266 |
+
|
| 267 |
+
def build_report(self) -> dict[str, Any]:
|
| 268 |
+
with self._lock:
|
| 269 |
+
records = [
|
| 270 |
+
{
|
| 271 |
+
**record,
|
| 272 |
+
"phases_ms": dict(record["phases_ms"]),
|
| 273 |
+
}
|
| 274 |
+
for record in self._records
|
| 275 |
+
]
|
| 276 |
+
|
| 277 |
+
phase_totals_ms = defaultdict(float)
|
| 278 |
+
route_totals = {}
|
| 279 |
+
for record in records:
|
| 280 |
+
for phase, duration_ms in record["phases_ms"].items():
|
| 281 |
+
phase_totals_ms[phase] += duration_ms
|
| 282 |
+
|
| 283 |
+
route_key = (record["method"], record["host_display"], record["path"])
|
| 284 |
+
route_total = route_totals.setdefault(
|
| 285 |
+
route_key,
|
| 286 |
+
{
|
| 287 |
+
"method": record["method"],
|
| 288 |
+
"host_display": record["host_display"],
|
| 289 |
+
"path": record["path"],
|
| 290 |
+
"count": 0,
|
| 291 |
+
"failures": 0,
|
| 292 |
+
"total_ms": 0.0,
|
| 293 |
+
"phase_totals_ms": defaultdict(float),
|
| 294 |
+
},
|
| 295 |
+
)
|
| 296 |
+
route_total["count"] += 1
|
| 297 |
+
route_total["total_ms"] += record["total_ms"]
|
| 298 |
+
route_total["failures"] += int(record["error"] is not None)
|
| 299 |
+
for phase, duration_ms in record["phases_ms"].items():
|
| 300 |
+
route_total["phase_totals_ms"][phase] += duration_ms
|
| 301 |
+
|
| 302 |
+
routes = []
|
| 303 |
+
for route_total in route_totals.values():
|
| 304 |
+
route_total["avg_ms"] = route_total["total_ms"] / route_total["count"]
|
| 305 |
+
route_total["phase_totals_ms"] = dict(sorted(route_total["phase_totals_ms"].items()))
|
| 306 |
+
routes.append(route_total)
|
| 307 |
+
|
| 308 |
+
routes.sort(key=lambda route: route["total_ms"], reverse=True)
|
| 309 |
+
total_time_ms = sum(record["total_ms"] for record in records)
|
| 310 |
+
return {
|
| 311 |
+
"enabled": self._enabled,
|
| 312 |
+
"output_path": self._output_path,
|
| 313 |
+
"total_requests": len(records),
|
| 314 |
+
"failed_requests": sum(int(record["error"] is not None) for record in records),
|
| 315 |
+
"total_time_ms": total_time_ms,
|
| 316 |
+
"phase_totals_ms": dict(sorted(phase_totals_ms.items())),
|
| 317 |
+
"requests": records,
|
| 318 |
+
"routes": routes,
|
| 319 |
+
}
|
| 320 |
+
|
| 321 |
+
def maybe_write_report(self) -> str | None:
|
| 322 |
+
if self._output_path is None:
|
| 323 |
+
return None
|
| 324 |
+
|
| 325 |
+
report_path = Path(self._output_path)
|
| 326 |
+
report_path.parent.mkdir(parents=True, exist_ok=True)
|
| 327 |
+
report_path.write_text(json.dumps(self.build_report(), indent=2, sort_keys=True), encoding="utf-8")
|
| 328 |
+
return str(report_path)
|
| 329 |
+
|
| 330 |
+
|
| 331 |
+
_NETWORK_DEBUG_PROFILER = _NetworkDebugProfiler()
|
| 332 |
+
|
| 333 |
+
|
| 334 |
+
_DEFAULT_REPORT_PATH = "network_debug_report.json"
|
| 335 |
+
|
| 336 |
+
|
| 337 |
+
def _parse_network_debug_env() -> tuple[bool, str]:
|
| 338 |
+
enabled_raw = os.environ.get("NETWORK_DEBUG_REPORT", "").strip()
|
| 339 |
+
try:
|
| 340 |
+
enabled = bool(strtobool(enabled_raw)) if enabled_raw else False
|
| 341 |
+
except ValueError:
|
| 342 |
+
enabled = False
|
| 343 |
+
|
| 344 |
+
output_path = os.environ.get("NETWORK_DEBUG_REPORT_PATH", "").strip() or _DEFAULT_REPORT_PATH
|
| 345 |
+
return enabled, output_path
|
| 346 |
+
|
| 347 |
+
|
| 348 |
+
def _enable_network_debug_report(output_path: str | os.PathLike | None = None) -> None:
|
| 349 |
+
_NETWORK_DEBUG_PROFILER.enable(output_path=output_path)
|
| 350 |
+
|
| 351 |
+
|
| 352 |
+
def _disable_network_debug_report() -> None:
|
| 353 |
+
_NETWORK_DEBUG_PROFILER.disable()
|
| 354 |
+
|
| 355 |
+
|
| 356 |
+
def _clear_network_debug_report() -> None:
|
| 357 |
+
_NETWORK_DEBUG_PROFILER.clear()
|
| 358 |
+
|
| 359 |
+
|
| 360 |
+
def _get_network_debug_report() -> dict[str, Any]:
|
| 361 |
+
return _NETWORK_DEBUG_PROFILER.build_report()
|
| 362 |
+
|
| 363 |
+
|
| 364 |
+
def _enable_network_debug_report_from_env() -> bool:
|
| 365 |
+
enabled, output_path = _parse_network_debug_env()
|
| 366 |
+
if not enabled:
|
| 367 |
+
return False
|
| 368 |
+
|
| 369 |
+
_enable_network_debug_report(output_path=output_path)
|
| 370 |
+
return True
|
| 371 |
+
|
| 372 |
+
|
| 373 |
+
def _format_network_debug_report(max_requests: int = 20, max_routes: int = 10) -> str:
|
| 374 |
+
report = _get_network_debug_report()
|
| 375 |
+
if report["total_requests"] == 0:
|
| 376 |
+
return "Network debug report: no httpx requests captured."
|
| 377 |
+
|
| 378 |
+
lines = [
|
| 379 |
+
"Network debug report",
|
| 380 |
+
f"Requests captured: {report['total_requests']}",
|
| 381 |
+
f"Failed requests: {report['failed_requests']}",
|
| 382 |
+
f"Cumulative request time: {report['total_time_ms']:.1f} ms",
|
| 383 |
+
]
|
| 384 |
+
|
| 385 |
+
if report["phase_totals_ms"]:
|
| 386 |
+
phase_summary = ", ".join(
|
| 387 |
+
f"{phase}={duration_ms:.1f} ms"
|
| 388 |
+
for phase, duration_ms in sorted(report["phase_totals_ms"].items(), key=lambda item: item[1], reverse=True)
|
| 389 |
+
)
|
| 390 |
+
lines.append(f"Phase totals: {phase_summary}")
|
| 391 |
+
|
| 392 |
+
lines.append("")
|
| 393 |
+
lines.append("Slowest requests:")
|
| 394 |
+
for idx, record in enumerate(
|
| 395 |
+
sorted(report["requests"], key=lambda request: request["total_ms"], reverse=True)[:max_requests],
|
| 396 |
+
start=1,
|
| 397 |
+
):
|
| 398 |
+
status = record["error"] or f"status={record['status_code']}"
|
| 399 |
+
phase_bits = []
|
| 400 |
+
for phase in ("connect_tcp", "start_tls", "receive_response_headers", "receive_response_body"):
|
| 401 |
+
duration_ms = record["phases_ms"].get(phase)
|
| 402 |
+
if duration_ms is not None:
|
| 403 |
+
phase_bits.append(f"{phase}={duration_ms:.1f} ms")
|
| 404 |
+
phase_suffix = f" ({', '.join(phase_bits)})" if phase_bits else ""
|
| 405 |
+
incomplete_suffix = " incomplete" if record["stream"] and not record["response_complete"] else ""
|
| 406 |
+
lines.append(
|
| 407 |
+
f"{idx:>2}. {record['method']} {record['url']} {record['total_ms']:.1f} ms {status}{incomplete_suffix}{phase_suffix}"
|
| 408 |
+
)
|
| 409 |
+
|
| 410 |
+
lines.append("")
|
| 411 |
+
lines.append("Slowest routes:")
|
| 412 |
+
for idx, route in enumerate(report["routes"][:max_routes], start=1):
|
| 413 |
+
lines.append(
|
| 414 |
+
f"{idx:>2}. {route['method']} {route['host_display']}{route['path']} count={route['count']} "
|
| 415 |
+
f"total={route['total_ms']:.1f} ms avg={route['avg_ms']:.1f} ms failures={route['failures']}"
|
| 416 |
+
)
|
| 417 |
+
|
| 418 |
+
return "\n".join(lines)
|
| 419 |
+
|
| 420 |
+
|
| 421 |
+
class NetworkDebugPlugin:
|
| 422 |
+
"""Pytest plugin that handles all network debug orchestration including xdist coordination."""
|
| 423 |
+
|
| 424 |
+
def pytest_configure(self, config):
|
| 425 |
+
_enable_network_debug_report_from_env()
|
| 426 |
+
if not _NETWORK_DEBUG_PROFILER.enabled:
|
| 427 |
+
return
|
| 428 |
+
|
| 429 |
+
# xdist controller: create shared dir for workers to dump network records
|
| 430 |
+
if not hasattr(config, "workerinput"):
|
| 431 |
+
shared_dir = _NETWORK_DEBUG_PROFILER.setup_shared_dir()
|
| 432 |
+
if shared_dir:
|
| 433 |
+
config._network_debug_shared_dir = shared_dir
|
| 434 |
+
else:
|
| 435 |
+
# xdist worker: receive shared dir from controller
|
| 436 |
+
shared_dir = config.workerinput.get("network_debug_shared_dir")
|
| 437 |
+
if shared_dir:
|
| 438 |
+
_NETWORK_DEBUG_PROFILER.set_shared_dir(shared_dir)
|
| 439 |
+
|
| 440 |
+
def pytest_configure_node(self, node):
|
| 441 |
+
"""xdist hook: called on the controller to configure each worker node."""
|
| 442 |
+
shared_dir = getattr(node.config, "_network_debug_shared_dir", None)
|
| 443 |
+
if shared_dir:
|
| 444 |
+
node.workerinput["network_debug_shared_dir"] = shared_dir
|
| 445 |
+
|
| 446 |
+
def pytest_sessionfinish(self, session, exitstatus):
|
| 447 |
+
# xdist worker: dump network debug records for the controller to aggregate
|
| 448 |
+
if hasattr(session.config, "workerinput"):
|
| 449 |
+
worker_id = session.config.workerinput.get("workerid", f"pid{os.getpid()}")
|
| 450 |
+
_NETWORK_DEBUG_PROFILER.dump_worker_records(worker_id=worker_id)
|
| 451 |
+
|
| 452 |
+
def pytest_terminal_summary(self, terminalreporter):
|
| 453 |
+
if not _NETWORK_DEBUG_PROFILER.enabled:
|
| 454 |
+
return
|
| 455 |
+
|
| 456 |
+
# Skip report generation in xdist worker processes; only the controller should aggregate and report.
|
| 457 |
+
if hasattr(terminalreporter.config, "workerinput"):
|
| 458 |
+
return
|
| 459 |
+
|
| 460 |
+
# Aggregate worker records if running under xdist.
|
| 461 |
+
_NETWORK_DEBUG_PROFILER.load_worker_records()
|
| 462 |
+
|
| 463 |
+
report_path = None
|
| 464 |
+
try:
|
| 465 |
+
report_path = _NETWORK_DEBUG_PROFILER.maybe_write_report()
|
| 466 |
+
except OSError as error:
|
| 467 |
+
report_path = f"Failed to write JSON report: {error}"
|
| 468 |
+
|
| 469 |
+
terminalreporter.section("Network debug", sep="=")
|
| 470 |
+
for line in _format_network_debug_report().splitlines():
|
| 471 |
+
terminalreporter.write_line(line)
|
| 472 |
+
if report_path is not None:
|
| 473 |
+
terminalreporter.write_line(f"JSON report: {report_path}")
|
| 474 |
+
|
| 475 |
+
_NETWORK_DEBUG_PROFILER.cleanup_shared_dir()
|
| 476 |
+
|
| 477 |
+
|
| 478 |
+
def register_network_debug_plugin(config) -> None:
|
| 479 |
+
"""Register the network debug pytest plugin. Single entry point for conftest.py."""
|
| 480 |
+
config.pluginmanager.register(NetworkDebugPlugin(), "network_debug")
|
| 481 |
+
|
| 482 |
+
|
| 483 |
+
__all__ = [
|
| 484 |
+
"register_network_debug_plugin",
|
| 485 |
+
]
|
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/utils/peft_utils.py
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2023 The HuggingFace Team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
import importlib
|
| 15 |
+
import importlib.metadata
|
| 16 |
+
import os
|
| 17 |
+
|
| 18 |
+
from packaging import version
|
| 19 |
+
|
| 20 |
+
from .hub import cached_file
|
| 21 |
+
from .import_utils import is_peft_available
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
ADAPTER_CONFIG_NAME = "adapter_config.json"
|
| 25 |
+
ADAPTER_WEIGHTS_NAME = "adapter_model.bin"
|
| 26 |
+
ADAPTER_SAFE_WEIGHTS_NAME = "adapter_model.safetensors"
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
def find_adapter_config_file(
|
| 30 |
+
model_id: str,
|
| 31 |
+
cache_dir: str | os.PathLike | None = None,
|
| 32 |
+
force_download: bool = False,
|
| 33 |
+
proxies: dict[str, str] | None = None,
|
| 34 |
+
token: bool | str | None = None,
|
| 35 |
+
revision: str | None = None,
|
| 36 |
+
local_files_only: bool = False,
|
| 37 |
+
subfolder: str = "",
|
| 38 |
+
_commit_hash: str | None = None,
|
| 39 |
+
) -> str | None:
|
| 40 |
+
r"""
|
| 41 |
+
Simply checks if the model stored on the Hub or locally is an adapter model or not, return the path of the adapter
|
| 42 |
+
config file if it is, None otherwise.
|
| 43 |
+
|
| 44 |
+
Args:
|
| 45 |
+
model_id (`str`):
|
| 46 |
+
The identifier of the model to look for, can be either a local path or an id to the repository on the Hub.
|
| 47 |
+
cache_dir (`str` or `os.PathLike`, *optional*):
|
| 48 |
+
Path to a directory in which a downloaded pretrained model configuration should be cached if the standard
|
| 49 |
+
cache should not be used.
|
| 50 |
+
force_download (`bool`, *optional*, defaults to `False`):
|
| 51 |
+
Whether or not to force to (re-)download the configuration files and override the cached versions if they
|
| 52 |
+
exist.
|
| 53 |
+
proxies (`dict[str, str]`, *optional*):
|
| 54 |
+
A dictionary of proxy servers to use by protocol or endpoint, e.g., `{'http': 'foo.bar:3128',
|
| 55 |
+
'http://hostname': 'foo.bar:4012'}.` The proxies are used on each request.
|
| 56 |
+
token (`str` or *bool*, *optional*):
|
| 57 |
+
The token to use as HTTP bearer authorization for remote files. If `True`, will use the token generated
|
| 58 |
+
when running `hf auth login` (stored in `~/.huggingface`).
|
| 59 |
+
revision (`str`, *optional*, defaults to `"main"`):
|
| 60 |
+
The specific model version to use. It can be a branch name, a tag name, or a commit id, since we use a
|
| 61 |
+
git-based system for storing models and other artifacts on huggingface.co, so `revision` can be any
|
| 62 |
+
identifier allowed by git.
|
| 63 |
+
|
| 64 |
+
<Tip>
|
| 65 |
+
|
| 66 |
+
To test a pull request you made on the Hub, you can pass `revision="refs/pr/<pr_number>".
|
| 67 |
+
|
| 68 |
+
</Tip>
|
| 69 |
+
|
| 70 |
+
local_files_only (`bool`, *optional*, defaults to `False`):
|
| 71 |
+
If `True`, will only try to load the tokenizer configuration from local files.
|
| 72 |
+
subfolder (`str`, *optional*, defaults to `""`):
|
| 73 |
+
In case the relevant files are located inside a subfolder of the model repo on huggingface.co, you can
|
| 74 |
+
specify the folder name here.
|
| 75 |
+
"""
|
| 76 |
+
adapter_cached_filename = None
|
| 77 |
+
if model_id is None:
|
| 78 |
+
return None
|
| 79 |
+
elif os.path.isdir(model_id):
|
| 80 |
+
list_remote_files = os.listdir(model_id)
|
| 81 |
+
if ADAPTER_CONFIG_NAME in list_remote_files:
|
| 82 |
+
adapter_cached_filename = os.path.join(model_id, ADAPTER_CONFIG_NAME)
|
| 83 |
+
else:
|
| 84 |
+
adapter_cached_filename = cached_file(
|
| 85 |
+
model_id,
|
| 86 |
+
ADAPTER_CONFIG_NAME,
|
| 87 |
+
cache_dir=cache_dir,
|
| 88 |
+
force_download=force_download,
|
| 89 |
+
proxies=proxies,
|
| 90 |
+
token=token,
|
| 91 |
+
revision=revision,
|
| 92 |
+
local_files_only=local_files_only,
|
| 93 |
+
subfolder=subfolder,
|
| 94 |
+
_commit_hash=_commit_hash,
|
| 95 |
+
_raise_exceptions_for_gated_repo=False,
|
| 96 |
+
_raise_exceptions_for_missing_entries=False,
|
| 97 |
+
_raise_exceptions_for_connection_errors=False,
|
| 98 |
+
)
|
| 99 |
+
|
| 100 |
+
return adapter_cached_filename
|
| 101 |
+
|
| 102 |
+
|
| 103 |
+
def check_peft_version(min_version: str) -> None:
|
| 104 |
+
r"""
|
| 105 |
+
Checks if the version of PEFT is compatible.
|
| 106 |
+
|
| 107 |
+
Args:
|
| 108 |
+
version (`str`):
|
| 109 |
+
The version of PEFT to check against.
|
| 110 |
+
"""
|
| 111 |
+
if not is_peft_available():
|
| 112 |
+
raise ValueError("PEFT is not installed. Please install it with `pip install peft`")
|
| 113 |
+
|
| 114 |
+
is_peft_version_compatible = version.parse(importlib.metadata.version("peft")) >= version.parse(min_version)
|
| 115 |
+
|
| 116 |
+
if not is_peft_version_compatible:
|
| 117 |
+
raise ValueError(f"The version of PEFT you are using is not compatible, please use a version >= {min_version}")
|
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/utils/versions.py
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2020 The HuggingFace Team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
"""
|
| 15 |
+
Utilities for working with package versions
|
| 16 |
+
"""
|
| 17 |
+
|
| 18 |
+
import importlib.metadata
|
| 19 |
+
import operator
|
| 20 |
+
import re
|
| 21 |
+
import sys
|
| 22 |
+
|
| 23 |
+
from packaging import version
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
ops = {
|
| 27 |
+
"<": operator.lt,
|
| 28 |
+
"<=": operator.le,
|
| 29 |
+
"==": operator.eq,
|
| 30 |
+
"!=": operator.ne,
|
| 31 |
+
">=": operator.ge,
|
| 32 |
+
">": operator.gt,
|
| 33 |
+
}
|
| 34 |
+
|
| 35 |
+
|
| 36 |
+
def _compare_versions(op, got_ver, want_ver, requirement, pkg, hint):
|
| 37 |
+
if got_ver is None or want_ver is None:
|
| 38 |
+
raise ValueError(
|
| 39 |
+
f"Unable to compare versions for {requirement}: need={want_ver} found={got_ver}. This is unusual. Consider"
|
| 40 |
+
f" reinstalling {pkg}."
|
| 41 |
+
)
|
| 42 |
+
if not ops[op](version.parse(got_ver), version.parse(want_ver)):
|
| 43 |
+
raise ImportError(
|
| 44 |
+
f"{requirement} is required for a normal functioning of this module, but found {pkg}=={got_ver}.{hint}"
|
| 45 |
+
)
|
| 46 |
+
|
| 47 |
+
|
| 48 |
+
def require_version(requirement: str, hint: str | None = None) -> None:
|
| 49 |
+
"""
|
| 50 |
+
Perform a runtime check of the dependency versions, using the exact same syntax used by pip.
|
| 51 |
+
|
| 52 |
+
The installed module version comes from the *site-packages* dir via *importlib.metadata*.
|
| 53 |
+
|
| 54 |
+
Args:
|
| 55 |
+
requirement (`str`): pip style definition, e.g., "tokenizers==0.9.4", "tqdm>=4.27", "numpy"
|
| 56 |
+
hint (`str`, *optional*): what suggestion to print in case of requirements not being met
|
| 57 |
+
|
| 58 |
+
Example:
|
| 59 |
+
|
| 60 |
+
```python
|
| 61 |
+
require_version("pandas>1.1.2")
|
| 62 |
+
require_version("numpy>1.18.5", "this is important to have for whatever reason")
|
| 63 |
+
```"""
|
| 64 |
+
|
| 65 |
+
hint = f"\n{hint}" if hint is not None else ""
|
| 66 |
+
|
| 67 |
+
# non-versioned check
|
| 68 |
+
if re.match(r"^[\w_\-\d]+$", requirement):
|
| 69 |
+
pkg, op, want_ver = requirement, None, None
|
| 70 |
+
else:
|
| 71 |
+
match = re.findall(r"^([^!=<>\s]+)([\s!=<>]{1,2}.+)", requirement)
|
| 72 |
+
if not match:
|
| 73 |
+
raise ValueError(
|
| 74 |
+
"requirement needs to be in the pip package format, .e.g., package_a==1.23, or package_b>=1.23, but"
|
| 75 |
+
f" got {requirement}"
|
| 76 |
+
)
|
| 77 |
+
pkg, want_full = match[0]
|
| 78 |
+
want_range = want_full.split(",") # there could be multiple requirements
|
| 79 |
+
wanted = {}
|
| 80 |
+
for w in want_range:
|
| 81 |
+
match = re.findall(r"^([\s!=<>]{1,2})(.+)", w)
|
| 82 |
+
if not match:
|
| 83 |
+
raise ValueError(
|
| 84 |
+
"requirement needs to be in the pip package format, .e.g., package_a==1.23, or package_b>=1.23,"
|
| 85 |
+
f" but got {requirement}"
|
| 86 |
+
)
|
| 87 |
+
op, want_ver = match[0]
|
| 88 |
+
wanted[op] = want_ver
|
| 89 |
+
if op not in ops:
|
| 90 |
+
raise ValueError(f"{requirement}: need one of {list(ops.keys())}, but got {op}")
|
| 91 |
+
|
| 92 |
+
# special case
|
| 93 |
+
if pkg == "python":
|
| 94 |
+
got_ver = ".".join([str(x) for x in sys.version_info[:3]])
|
| 95 |
+
for op, want_ver in wanted.items():
|
| 96 |
+
_compare_versions(op, got_ver, want_ver, requirement, pkg, hint)
|
| 97 |
+
return
|
| 98 |
+
|
| 99 |
+
# check if any version is installed
|
| 100 |
+
try:
|
| 101 |
+
got_ver = importlib.metadata.version(pkg)
|
| 102 |
+
except importlib.metadata.PackageNotFoundError:
|
| 103 |
+
raise importlib.metadata.PackageNotFoundError(
|
| 104 |
+
f"The '{requirement}' distribution was not found and is required by this application. {hint}"
|
| 105 |
+
)
|
| 106 |
+
|
| 107 |
+
# check that the right version is installed if version number or a range was provided
|
| 108 |
+
if want_ver is not None:
|
| 109 |
+
for op, want_ver in wanted.items():
|
| 110 |
+
_compare_versions(op, got_ver, want_ver, requirement, pkg, hint)
|
| 111 |
+
|
| 112 |
+
|
| 113 |
+
def require_version_core(requirement):
|
| 114 |
+
"""require_version wrapper which emits a core-specific hint on failure"""
|
| 115 |
+
hint = "Try: `pip install transformers -U` or `pip install -e '.[dev]'` if you're working with git main"
|
| 116 |
+
return require_version(requirement, hint)
|