Add files using upload-large-folder tool
Browse files- LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/models/encoder_decoder/__init__.py +27 -0
- LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/models/encoder_decoder/configuration_encoder_decoder.py +102 -0
- LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/models/encoder_decoder/modeling_encoder_decoder.py +471 -0
- LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/models/lw_detr/__init__.py +27 -0
- LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/models/lw_detr/configuration_lw_detr.py +226 -0
- LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/models/lw_detr/modeling_lw_detr.py +1673 -0
- LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/models/lw_detr/modular_lw_detr.py +1398 -0
- LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/models/modernbert/__init__.py +27 -0
- LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/models/patchtst/__init__.py +27 -0
- LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/models/patchtst/configuration_patchtst.py +170 -0
- LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/models/patchtst/modeling_patchtst.py +1973 -0
- LTA_openwebtext_dualt/mini_owt_logdirichlet/runs/owt_t5_elftokenized_full_len1024_C1_to_1024_pow1_d768_l12_h12_gbs512_8gpu_50ep_lr3e4_elfopt_t5embed_unfixed_stateprobadd_selfcond_ce_fast_20260531_230026/step_001000.pt +3 -0
- LTA_openwebtext_dualt/mini_owt_logdirichlet/runs/owt_t5_elftokenized_full_len1024_C1_to_1024_pow1_d768_l12_h12_gbs512_8gpu_50ep_lr3e4_elfopt_t5embed_unfixed_stateprobadd_selfcond_ce_fast_20260531_230026/step_036000.pt +3 -0
- LTA_openwebtext_dualt/mini_owt_logdirichlet/runs/owt_t5_elftokenized_full_len1024_C1_to_1024_pow1_d768_l12_h12_gbs512_8gpu_50ep_lr3e4_elfopt_t5embed_unfixed_stateprobadd_selfcond_ce_fast_20260531_230026/step_038000.pt +3 -0
- LTA_openwebtext_dualt/mini_owt_logdirichlet/runs/owt_t5_elftokenized_full_len1024_C1_to_1024_pow1_d768_l12_h12_gbs512_8gpu_50ep_lr3e4_elfopt_t5embed_unfixed_stateprobadd_selfcond_ce_fast_20260531_230026/step_100000.pt +3 -0
- LTA_openwebtext_dualt/mini_owt_logdirichlet/runs/owt_t5_elftokenized_full_len1024_C1_to_1024_pow1_d768_l12_h12_gbs512_8gpu_50ep_lr3e4_elfopt_t5embed_unfixed_stateprobadd_selfcond_ce_fast_20260531_230026/step_135000.pt +3 -0
- LTA_openwebtext_dualt/mini_owt_logdirichlet/runs/owt_t5_elftokenized_full_len1024_C1_to_1024_pow1_d768_l12_h12_gbs512_8gpu_50ep_lr3e4_elfopt_t5embed_unfixed_stateprobadd_selfcond_ce_fast_20260531_230026/step_173000.pt +3 -0
- LTA_openwebtext_dualt/mini_owt_logdirichlet/runs/owt_t5_elftokenized_full_len1024_C1_to_1024_pow1_d768_l12_h12_gbs512_8gpu_50ep_lr3e4_elfopt_t5embed_unfixed_stateprobadd_selfcond_ce_fast_20260531_230026/step_197000.pt +3 -0
- LTA_openwebtext_dualt/mini_owt_logdirichlet/runs/owt_t5_elftokenized_full_len1024_C1_to_1024_pow1_d768_l12_h12_gbs512_8gpu_50ep_lr3e4_elfopt_t5embed_unfixed_stateprobadd_selfcond_ce_fast_20260531_230026/step_203000.pt +3 -0
- LTA_openwebtext_dualt/mini_owt_logdirichlet/runs/owt_t5_elftokenized_full_len1024_C1_to_1024_pow1_d768_l12_h12_gbs512_8gpu_50ep_lr3e4_elfopt_t5embed_unfixed_stateprobadd_selfcond_ce_fast_20260531_230026/step_236000.pt +3 -0
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/models/encoder_decoder/__init__.py
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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_encoder_decoder import *
|
| 22 |
+
from .modeling_encoder_decoder import *
|
| 23 |
+
else:
|
| 24 |
+
import sys
|
| 25 |
+
|
| 26 |
+
_file = globals()["__file__"]
|
| 27 |
+
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/encoder_decoder/configuration_encoder_decoder.py
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2020 The HuggingFace Inc. team.
|
| 2 |
+
# Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
|
| 3 |
+
#
|
| 4 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 5 |
+
# you may not use this file except in compliance with the License.
|
| 6 |
+
# You may obtain a copy of the License at
|
| 7 |
+
#
|
| 8 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 9 |
+
#
|
| 10 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 11 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 12 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 13 |
+
# See the License for the specific language governing permissions and
|
| 14 |
+
# limitations under the License.
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
from huggingface_hub.dataclasses import strict
|
| 18 |
+
|
| 19 |
+
from ...configuration_utils import PreTrainedConfig
|
| 20 |
+
from ...utils import auto_docstring, logging
|
| 21 |
+
from ..auto import AutoConfig
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
logger = logging.get_logger(__name__)
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
@auto_docstring(checkpoint="")
|
| 28 |
+
@strict
|
| 29 |
+
class EncoderDecoderConfig(PreTrainedConfig):
|
| 30 |
+
r"""
|
| 31 |
+
Examples:
|
| 32 |
+
|
| 33 |
+
```python
|
| 34 |
+
>>> from transformers import BertConfig, EncoderDecoderConfig, EncoderDecoderModel
|
| 35 |
+
|
| 36 |
+
>>> # Initializing a BERT google-bert/bert-base-uncased style configuration
|
| 37 |
+
>>> config_encoder = BertConfig()
|
| 38 |
+
>>> config_decoder = BertConfig()
|
| 39 |
+
|
| 40 |
+
>>> config = EncoderDecoderConfig.from_encoder_decoder_configs(config_encoder, config_decoder)
|
| 41 |
+
|
| 42 |
+
>>> # Initializing a Bert2Bert model (with random weights) from the google-bert/bert-base-uncased style configurations
|
| 43 |
+
>>> model = EncoderDecoderModel(config=config)
|
| 44 |
+
|
| 45 |
+
>>> # Accessing the model configuration
|
| 46 |
+
>>> config_encoder = model.config.encoder
|
| 47 |
+
>>> config_decoder = model.config.decoder
|
| 48 |
+
>>> # set decoder config to causal lm
|
| 49 |
+
>>> config_decoder.is_decoder = True
|
| 50 |
+
>>> config_decoder.add_cross_attention = True
|
| 51 |
+
|
| 52 |
+
>>> # Saving the model, including its configuration
|
| 53 |
+
>>> model.save_pretrained("my-model")
|
| 54 |
+
|
| 55 |
+
>>> # loading model and config from pretrained folder
|
| 56 |
+
>>> encoder_decoder_config = EncoderDecoderConfig.from_pretrained("my-model")
|
| 57 |
+
>>> model = EncoderDecoderModel.from_pretrained("my-model", config=encoder_decoder_config)
|
| 58 |
+
```"""
|
| 59 |
+
|
| 60 |
+
model_type = "encoder-decoder"
|
| 61 |
+
sub_configs = {"encoder": AutoConfig, "decoder": AutoConfig}
|
| 62 |
+
has_no_defaults_at_init = True
|
| 63 |
+
|
| 64 |
+
pad_token_id: int | None = None
|
| 65 |
+
decoder_start_token_id: int | None = None
|
| 66 |
+
is_encoder_decoder: bool | None = True
|
| 67 |
+
|
| 68 |
+
def __post_init__(self, **kwargs):
|
| 69 |
+
if "encoder" not in kwargs or "decoder" not in kwargs:
|
| 70 |
+
raise ValueError(
|
| 71 |
+
f"A configuration of type {self.model_type} cannot be instantiated because not both `encoder` and"
|
| 72 |
+
f" `decoder` sub-configurations are passed, but only {kwargs}"
|
| 73 |
+
)
|
| 74 |
+
|
| 75 |
+
encoder_config = kwargs.pop("encoder")
|
| 76 |
+
encoder_model_type = encoder_config.pop("model_type")
|
| 77 |
+
decoder_config = kwargs.pop("decoder")
|
| 78 |
+
decoder_model_type = decoder_config.pop("model_type")
|
| 79 |
+
|
| 80 |
+
self.encoder = AutoConfig.for_model(encoder_model_type, **encoder_config)
|
| 81 |
+
self.decoder = AutoConfig.for_model(decoder_model_type, **decoder_config)
|
| 82 |
+
super().__post_init__(**kwargs)
|
| 83 |
+
|
| 84 |
+
@classmethod
|
| 85 |
+
def from_encoder_decoder_configs(
|
| 86 |
+
cls, encoder_config: PreTrainedConfig, decoder_config: PreTrainedConfig, **kwargs
|
| 87 |
+
) -> PreTrainedConfig:
|
| 88 |
+
r"""
|
| 89 |
+
Instantiate a [`EncoderDecoderConfig`] (or a derived class) from a pre-trained encoder model configuration and
|
| 90 |
+
decoder model configuration.
|
| 91 |
+
|
| 92 |
+
Returns:
|
| 93 |
+
[`EncoderDecoderConfig`]: An instance of a configuration object
|
| 94 |
+
"""
|
| 95 |
+
logger.info("Set `config.is_decoder=True` and `config.add_cross_attention=True` for decoder_config")
|
| 96 |
+
decoder_config.is_decoder = True
|
| 97 |
+
decoder_config.add_cross_attention = True
|
| 98 |
+
|
| 99 |
+
return cls(encoder=encoder_config.to_dict(), decoder=decoder_config.to_dict(), **kwargs)
|
| 100 |
+
|
| 101 |
+
|
| 102 |
+
__all__ = ["EncoderDecoderConfig"]
|
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/models/encoder_decoder/modeling_encoder_decoder.py
ADDED
|
@@ -0,0 +1,471 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2018 The HuggingFace Inc. team.
|
| 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 |
+
"""Classes to support Encoder-Decoder architectures"""
|
| 15 |
+
|
| 16 |
+
import inspect
|
| 17 |
+
import warnings
|
| 18 |
+
|
| 19 |
+
import torch
|
| 20 |
+
from torch import nn
|
| 21 |
+
from torch.nn import CrossEntropyLoss
|
| 22 |
+
|
| 23 |
+
from ...cache_utils import Cache
|
| 24 |
+
from ...configuration_utils import PreTrainedConfig
|
| 25 |
+
from ...generation import GenerationMixin
|
| 26 |
+
from ...modeling_outputs import BaseModelOutput, Seq2SeqLMOutput
|
| 27 |
+
from ...modeling_utils import PreTrainedModel
|
| 28 |
+
from ...utils import auto_docstring, logging
|
| 29 |
+
from ...utils.generic import can_return_tuple
|
| 30 |
+
from ..auto.configuration_auto import AutoConfig
|
| 31 |
+
from ..auto.modeling_auto import AutoModel, AutoModelForCausalLM
|
| 32 |
+
from .configuration_encoder_decoder import EncoderDecoderConfig
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
logger = logging.get_logger(__name__)
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
DEPRECATION_WARNING = (
|
| 39 |
+
"Version v4.12.0 introduces a better way to train encoder-decoder models by computing the loss inside the"
|
| 40 |
+
" encoder-decoder framework rather than in the decoder itself. You may observe training discrepancies if"
|
| 41 |
+
" fine-tuning a model trained with versions anterior to 4.12.0. The decoder_input_ids are now created based on the"
|
| 42 |
+
" labels, no need to pass them yourself anymore."
|
| 43 |
+
)
|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
def shift_tokens_right(input_ids: torch.Tensor, pad_token_id: int, decoder_start_token_id: int):
|
| 47 |
+
"""
|
| 48 |
+
Shift input ids one token to the right.
|
| 49 |
+
"""
|
| 50 |
+
shifted_input_ids = input_ids.new_zeros(input_ids.shape)
|
| 51 |
+
shifted_input_ids[:, 1:] = input_ids[:, :-1].clone()
|
| 52 |
+
if decoder_start_token_id is None:
|
| 53 |
+
raise ValueError("Make sure to set the decoder_start_token_id attribute of the model's configuration.")
|
| 54 |
+
shifted_input_ids[:, 0] = decoder_start_token_id
|
| 55 |
+
|
| 56 |
+
if pad_token_id is None:
|
| 57 |
+
raise ValueError("Make sure to set the pad_token_id attribute of the model's configuration.")
|
| 58 |
+
# replace possible -100 values in labels by `pad_token_id`
|
| 59 |
+
shifted_input_ids.masked_fill_(shifted_input_ids == -100, pad_token_id)
|
| 60 |
+
|
| 61 |
+
return shifted_input_ids
|
| 62 |
+
|
| 63 |
+
|
| 64 |
+
@auto_docstring
|
| 65 |
+
class EncoderDecoderModel(PreTrainedModel, GenerationMixin):
|
| 66 |
+
r"""
|
| 67 |
+
[`EncoderDecoderModel`] is a generic model class that will be instantiated as a transformer architecture with one
|
| 68 |
+
of the base model classes of the library as encoder and another one as decoder when created with the
|
| 69 |
+
:meth*~transformers.AutoModel.from_pretrained* class method for the encoder and
|
| 70 |
+
:meth*~transformers.AutoModelForCausalLM.from_pretrained* class method for the decoder.
|
| 71 |
+
"""
|
| 72 |
+
|
| 73 |
+
config: EncoderDecoderConfig
|
| 74 |
+
base_model_prefix = "encoder_decoder"
|
| 75 |
+
main_input_name = "input_ids"
|
| 76 |
+
supports_gradient_checkpointing = True
|
| 77 |
+
_supports_flash_attn = True
|
| 78 |
+
_supports_sdpa = True
|
| 79 |
+
|
| 80 |
+
def __init__(
|
| 81 |
+
self,
|
| 82 |
+
config: PreTrainedConfig | None = None,
|
| 83 |
+
encoder: PreTrainedModel | None = None,
|
| 84 |
+
decoder: PreTrainedModel | None = None,
|
| 85 |
+
):
|
| 86 |
+
r"""
|
| 87 |
+
encoder (`PreTrainedModel`, *optional*):
|
| 88 |
+
The encoder model to use.
|
| 89 |
+
decoder (`PreTrainedModel`, *optional*):
|
| 90 |
+
The decoder model to use.
|
| 91 |
+
"""
|
| 92 |
+
if config is None and (encoder is None or decoder is None):
|
| 93 |
+
raise ValueError("Either a configuration or an encoder and a decoder has to be provided.")
|
| 94 |
+
if config is None:
|
| 95 |
+
config = EncoderDecoderConfig.from_encoder_decoder_configs(encoder.config, decoder.config)
|
| 96 |
+
else:
|
| 97 |
+
if not isinstance(config, self.config_class):
|
| 98 |
+
raise ValueError(f"Config: {config} has to be of type {self.config_class}")
|
| 99 |
+
|
| 100 |
+
if getattr(config.decoder, "cross_attention_hidden_size", None) is not None:
|
| 101 |
+
if config.decoder.cross_attention_hidden_size != config.encoder.hidden_size:
|
| 102 |
+
raise ValueError(
|
| 103 |
+
"If `cross_attention_hidden_size` is specified in the decoder's configuration, it has to be equal"
|
| 104 |
+
f" to the encoder's `hidden_size`. Got {config.decoder.cross_attention_hidden_size} for"
|
| 105 |
+
f" `config.decoder.cross_attention_hidden_size` and {config.encoder.hidden_size} for"
|
| 106 |
+
" `config.encoder.hidden_size`."
|
| 107 |
+
)
|
| 108 |
+
|
| 109 |
+
# initialize with config
|
| 110 |
+
super().__init__(config)
|
| 111 |
+
|
| 112 |
+
if encoder is None:
|
| 113 |
+
from ..auto.modeling_auto import AutoModel
|
| 114 |
+
|
| 115 |
+
encoder = AutoModel.from_config(config.encoder)
|
| 116 |
+
|
| 117 |
+
if decoder is None:
|
| 118 |
+
from ..auto.modeling_auto import AutoModelForCausalLM
|
| 119 |
+
|
| 120 |
+
decoder = AutoModelForCausalLM.from_config(config.decoder)
|
| 121 |
+
|
| 122 |
+
self.encoder = encoder
|
| 123 |
+
self.decoder = decoder
|
| 124 |
+
|
| 125 |
+
if self.encoder.config.to_dict() != self.config.encoder.to_dict():
|
| 126 |
+
logger.warning(
|
| 127 |
+
f"Config of the encoder: {self.encoder.__class__} is overwritten by shared encoder config:"
|
| 128 |
+
f" {self.config.encoder}"
|
| 129 |
+
)
|
| 130 |
+
if self.decoder.config.to_dict() != self.config.decoder.to_dict():
|
| 131 |
+
logger.warning(
|
| 132 |
+
f"Config of the decoder: {self.decoder.__class__} is overwritten by shared decoder config:"
|
| 133 |
+
f" {self.config.decoder}"
|
| 134 |
+
)
|
| 135 |
+
|
| 136 |
+
# make sure that the individual model's config refers to the shared config
|
| 137 |
+
# so that the updates to the config will be synced
|
| 138 |
+
# update `_attn_implementation` because the attn is set in a deepcopied config within PreTrainedModel
|
| 139 |
+
self.config.encoder._attn_implementation = self.encoder.config._attn_implementation
|
| 140 |
+
self.config.decoder._attn_implementation = self.decoder.config._attn_implementation
|
| 141 |
+
self.encoder.config = self.config.encoder
|
| 142 |
+
self.decoder.config = self.config.decoder
|
| 143 |
+
|
| 144 |
+
# encoder outputs might need to be projected to different dimension for decoder
|
| 145 |
+
if (
|
| 146 |
+
self.encoder.config.hidden_size != self.decoder.config.hidden_size
|
| 147 |
+
and getattr(self.decoder.config, "cross_attention_hidden_size", None) is None
|
| 148 |
+
):
|
| 149 |
+
self.enc_to_dec_proj = nn.Linear(self.encoder.config.hidden_size, self.decoder.config.hidden_size)
|
| 150 |
+
|
| 151 |
+
if self.encoder.get_output_embeddings() is not None:
|
| 152 |
+
raise ValueError(
|
| 153 |
+
f"The encoder {self.encoder} should not have a LM Head. Please use a model without LM Head"
|
| 154 |
+
)
|
| 155 |
+
|
| 156 |
+
decoder_signature = set(inspect.signature(self.decoder.forward).parameters.keys())
|
| 157 |
+
if "encoder_hidden_states" not in decoder_signature:
|
| 158 |
+
raise ValueError(
|
| 159 |
+
"The selected decoder is not prepared for the encoder hidden states to be passed. Please see the "
|
| 160 |
+
"following discussion on GitHub: https://github.com/huggingface/transformers/issues/23350"
|
| 161 |
+
)
|
| 162 |
+
|
| 163 |
+
self.post_init()
|
| 164 |
+
|
| 165 |
+
@torch.no_grad()
|
| 166 |
+
def _init_weights(self, module):
|
| 167 |
+
if module in self.encoder.modules():
|
| 168 |
+
self.encoder._init_weights(module)
|
| 169 |
+
elif module in self.decoder.modules():
|
| 170 |
+
self.decoder._init_weights(module)
|
| 171 |
+
|
| 172 |
+
def get_input_embeddings(self):
|
| 173 |
+
return self.encoder.get_input_embeddings()
|
| 174 |
+
|
| 175 |
+
def get_output_embeddings(self):
|
| 176 |
+
return self.decoder.get_output_embeddings()
|
| 177 |
+
|
| 178 |
+
def set_output_embeddings(self, new_embeddings):
|
| 179 |
+
return self.decoder.set_output_embeddings(new_embeddings)
|
| 180 |
+
|
| 181 |
+
@classmethod
|
| 182 |
+
def from_encoder_decoder_pretrained(
|
| 183 |
+
cls,
|
| 184 |
+
encoder_pretrained_model_name_or_path: str | None = None,
|
| 185 |
+
decoder_pretrained_model_name_or_path: str | None = None,
|
| 186 |
+
*model_args,
|
| 187 |
+
**kwargs,
|
| 188 |
+
) -> PreTrainedModel:
|
| 189 |
+
r"""
|
| 190 |
+
Instantiate an encoder and a decoder from one or two base classes of the library from pretrained model
|
| 191 |
+
checkpoints.
|
| 192 |
+
|
| 193 |
+
|
| 194 |
+
The model is set in evaluation mode by default using `model.eval()` (Dropout modules are deactivated). To train
|
| 195 |
+
the model, you need to first set it back in training mode with `model.train()`.
|
| 196 |
+
|
| 197 |
+
Params:
|
| 198 |
+
encoder_pretrained_model_name_or_path (`str`, *optional*):
|
| 199 |
+
Information necessary to initiate the encoder. Can be either:
|
| 200 |
+
|
| 201 |
+
- A string, the *model id* of a pretrained model hosted inside a model repo on huggingface.co.
|
| 202 |
+
- A path to a *directory* containing model weights saved using
|
| 203 |
+
[`~PreTrainedModel.save_pretrained`], e.g., `./my_model_directory/`.
|
| 204 |
+
|
| 205 |
+
decoder_pretrained_model_name_or_path (`str`, *optional*, defaults to `None`):
|
| 206 |
+
Information necessary to initiate the decoder. Can be either:
|
| 207 |
+
|
| 208 |
+
- A string, the *model id* of a pretrained model hosted inside a model repo on huggingface.co.
|
| 209 |
+
- A path to a *directory* containing model weights saved using
|
| 210 |
+
[`~PreTrainedModel.save_pretrained`], e.g., `./my_model_directory/`.
|
| 211 |
+
|
| 212 |
+
model_args (remaining positional arguments, *optional*):
|
| 213 |
+
All remaining positional arguments will be passed to the underlying model's `__init__` method.
|
| 214 |
+
|
| 215 |
+
kwargs (remaining dictionary of keyword arguments, *optional*):
|
| 216 |
+
Can be used to update the configuration object (after it being loaded) and initiate the model (e.g.,
|
| 217 |
+
`output_attentions=True`).
|
| 218 |
+
|
| 219 |
+
- To update the encoder configuration, use the prefix *encoder_* for each configuration parameter.
|
| 220 |
+
- To update the decoder configuration, use the prefix *decoder_* for each configuration parameter.
|
| 221 |
+
- To update the parent model configuration, do not use a prefix for each configuration parameter.
|
| 222 |
+
|
| 223 |
+
Behaves differently depending on whether a `config` is provided or automatically loaded.
|
| 224 |
+
|
| 225 |
+
Example:
|
| 226 |
+
|
| 227 |
+
```python
|
| 228 |
+
>>> from transformers import EncoderDecoderModel
|
| 229 |
+
|
| 230 |
+
>>> # initialize a bert2bert from two pretrained BERT models. Note that the cross-attention layers will be randomly initialized
|
| 231 |
+
>>> model = EncoderDecoderModel.from_encoder_decoder_pretrained("google-bert/bert-base-uncased", "google-bert/bert-base-uncased")
|
| 232 |
+
>>> # saving model after fine-tuning
|
| 233 |
+
>>> model.save_pretrained("./bert2bert")
|
| 234 |
+
>>> # load fine-tuned model
|
| 235 |
+
>>> model = EncoderDecoderModel.from_pretrained("./bert2bert")
|
| 236 |
+
```"""
|
| 237 |
+
|
| 238 |
+
kwargs_encoder = {
|
| 239 |
+
argument[len("encoder_") :]: value for argument, value in kwargs.items() if argument.startswith("encoder_")
|
| 240 |
+
}
|
| 241 |
+
|
| 242 |
+
kwargs_decoder = {
|
| 243 |
+
argument[len("decoder_") :]: value for argument, value in kwargs.items() if argument.startswith("decoder_")
|
| 244 |
+
}
|
| 245 |
+
|
| 246 |
+
# remove encoder, decoder kwargs from kwargs
|
| 247 |
+
for key in kwargs_encoder:
|
| 248 |
+
del kwargs["encoder_" + key]
|
| 249 |
+
for key in kwargs_decoder:
|
| 250 |
+
del kwargs["decoder_" + key]
|
| 251 |
+
|
| 252 |
+
# Load and initialize the encoder and decoder
|
| 253 |
+
# The distinction between encoder and decoder at the model level is made
|
| 254 |
+
# by the value of the flag `is_decoder` that we need to set correctly.
|
| 255 |
+
encoder = kwargs_encoder.pop("model", None)
|
| 256 |
+
if encoder is None:
|
| 257 |
+
if encoder_pretrained_model_name_or_path is None:
|
| 258 |
+
raise ValueError(
|
| 259 |
+
"If `encoder_model` is not defined as an argument, a `encoder_pretrained_model_name_or_path` has "
|
| 260 |
+
"to be defined."
|
| 261 |
+
)
|
| 262 |
+
|
| 263 |
+
if "config" not in kwargs_encoder:
|
| 264 |
+
encoder_config, kwargs_encoder = AutoConfig.from_pretrained(
|
| 265 |
+
encoder_pretrained_model_name_or_path, **kwargs_encoder, return_unused_kwargs=True
|
| 266 |
+
)
|
| 267 |
+
|
| 268 |
+
if getattr(encoder_config, "is_decoder", False) or getattr(
|
| 269 |
+
encoder_config, "add_cross_attention", False
|
| 270 |
+
):
|
| 271 |
+
logger.info(
|
| 272 |
+
f"Initializing {encoder_pretrained_model_name_or_path} as a encoder model "
|
| 273 |
+
"from a decoder model. Cross-attention and causal mask are disabled."
|
| 274 |
+
)
|
| 275 |
+
encoder_config.is_decoder = False
|
| 276 |
+
encoder_config.add_cross_attention = False
|
| 277 |
+
|
| 278 |
+
kwargs_encoder["config"] = encoder_config
|
| 279 |
+
|
| 280 |
+
encoder = AutoModel.from_pretrained(encoder_pretrained_model_name_or_path, *model_args, **kwargs_encoder)
|
| 281 |
+
|
| 282 |
+
decoder = kwargs_decoder.pop("model", None)
|
| 283 |
+
if decoder is None:
|
| 284 |
+
if decoder_pretrained_model_name_or_path is None:
|
| 285 |
+
raise ValueError(
|
| 286 |
+
"If `decoder_model` is not defined as an argument, a `decoder_pretrained_model_name_or_path` has "
|
| 287 |
+
"to be defined."
|
| 288 |
+
)
|
| 289 |
+
|
| 290 |
+
if "config" not in kwargs_decoder:
|
| 291 |
+
decoder_config, kwargs_decoder = AutoConfig.from_pretrained(
|
| 292 |
+
decoder_pretrained_model_name_or_path, **kwargs_decoder, return_unused_kwargs=True
|
| 293 |
+
)
|
| 294 |
+
else:
|
| 295 |
+
decoder_config = kwargs_decoder["config"]
|
| 296 |
+
|
| 297 |
+
if (
|
| 298 |
+
getattr(decoder_config, "is_decoder", None) is False
|
| 299 |
+
or getattr(decoder_config, "add_cross_attention", None) is False
|
| 300 |
+
):
|
| 301 |
+
logger.info(
|
| 302 |
+
f"Initializing {decoder_pretrained_model_name_or_path} as a decoder model. Cross attention"
|
| 303 |
+
f" layers are added to {decoder_pretrained_model_name_or_path} and randomly initialized if"
|
| 304 |
+
f" {decoder_pretrained_model_name_or_path}'s architecture allows for cross attention layers."
|
| 305 |
+
)
|
| 306 |
+
decoder_config.is_decoder = True
|
| 307 |
+
decoder_config.add_cross_attention = True
|
| 308 |
+
|
| 309 |
+
kwargs_decoder["config"] = decoder_config
|
| 310 |
+
decoder = AutoModelForCausalLM.from_pretrained(decoder_pretrained_model_name_or_path, **kwargs_decoder)
|
| 311 |
+
|
| 312 |
+
# instantiate config with corresponding kwargs
|
| 313 |
+
config = EncoderDecoderConfig.from_encoder_decoder_configs(encoder.config, decoder.config, **kwargs)
|
| 314 |
+
return cls(encoder=encoder, decoder=decoder, config=config)
|
| 315 |
+
|
| 316 |
+
@can_return_tuple
|
| 317 |
+
@auto_docstring
|
| 318 |
+
def forward(
|
| 319 |
+
self,
|
| 320 |
+
input_ids: torch.LongTensor | None = None,
|
| 321 |
+
attention_mask: torch.FloatTensor | None = None,
|
| 322 |
+
decoder_input_ids: torch.LongTensor | None = None,
|
| 323 |
+
decoder_attention_mask: torch.BoolTensor | None = None,
|
| 324 |
+
encoder_outputs: tuple[torch.FloatTensor] | None = None,
|
| 325 |
+
past_key_values: Cache | None = None,
|
| 326 |
+
inputs_embeds: torch.FloatTensor | None = None,
|
| 327 |
+
decoder_inputs_embeds: torch.FloatTensor | None = None,
|
| 328 |
+
labels: torch.LongTensor | None = None,
|
| 329 |
+
use_cache: bool | None = None,
|
| 330 |
+
**kwargs,
|
| 331 |
+
) -> tuple | Seq2SeqLMOutput:
|
| 332 |
+
r"""
|
| 333 |
+
decoder_input_ids (`torch.LongTensor` of shape `(batch_size, target_sequence_length)`, *optional*):
|
| 334 |
+
Indices of decoder input sequence tokens in the vocabulary.
|
| 335 |
+
|
| 336 |
+
Indices can be obtained using [`PreTrainedTokenizer`]. See [`PreTrainedTokenizer.encode`] and
|
| 337 |
+
[`PreTrainedTokenizer.__call__`] for details.
|
| 338 |
+
|
| 339 |
+
[What are input IDs?](../glossary#input-ids)
|
| 340 |
+
|
| 341 |
+
If `past_key_values` is used, optionally only the last `decoder_input_ids` have to be input (see
|
| 342 |
+
`past_key_values`).
|
| 343 |
+
|
| 344 |
+
For training, `decoder_input_ids` are automatically created by the model by shifting the `labels` to the
|
| 345 |
+
right, replacing -100 by the `pad_token_id` and prepending them with the `decoder_start_token_id`.
|
| 346 |
+
decoder_attention_mask (`torch.BoolTensor` of shape `(batch_size, target_sequence_length)`, *optional*):
|
| 347 |
+
Default behavior: generate a tensor that ignores pad tokens in `decoder_input_ids`. Causal mask will also
|
| 348 |
+
be used by default.
|
| 349 |
+
decoder_inputs_embeds (`torch.FloatTensor` of shape `(batch_size, target_sequence_length, hidden_size)`, *optional*):
|
| 350 |
+
Optionally, instead of passing `decoder_input_ids` you can choose to directly pass an embedded
|
| 351 |
+
representation. This is useful if you want more control over how to convert `decoder_input_ids` indices
|
| 352 |
+
into associated vectors than the model's internal embedding lookup matrix.
|
| 353 |
+
labels (`torch.LongTensor` of shape `(batch_size, sequence_length)`, *optional*):
|
| 354 |
+
Labels for computing the masked language modeling loss for the decoder. Indices should be in `[-100, 0,
|
| 355 |
+
..., config.vocab_size]` (see `input_ids` docstring) Tokens with indices set to `-100` are ignored
|
| 356 |
+
(masked), the loss is only computed for the tokens with labels in `[0, ..., config.vocab_size]`
|
| 357 |
+
|
| 358 |
+
Examples:
|
| 359 |
+
|
| 360 |
+
```python
|
| 361 |
+
>>> from transformers import EncoderDecoderModel, BertTokenizer
|
| 362 |
+
>>> import torch
|
| 363 |
+
|
| 364 |
+
>>> tokenizer = BertTokenizer.from_pretrained("google-bert/bert-base-uncased")
|
| 365 |
+
>>> model = EncoderDecoderModel.from_encoder_decoder_pretrained(
|
| 366 |
+
... "google-bert/bert-base-uncased", "google-bert/bert-base-uncased"
|
| 367 |
+
... ) # initialize Bert2Bert from pre-trained checkpoints
|
| 368 |
+
|
| 369 |
+
>>> # training
|
| 370 |
+
>>> model.config.decoder_start_token_id = tokenizer.cls_token_id
|
| 371 |
+
>>> model.config.pad_token_id = tokenizer.pad_token_id
|
| 372 |
+
>>> model.config.vocab_size = model.config.decoder.vocab_size
|
| 373 |
+
|
| 374 |
+
>>> input_ids = tokenizer("This is a really long text", return_tensors="pt").input_ids
|
| 375 |
+
>>> labels = tokenizer("This is the corresponding summary", return_tensors="pt").input_ids
|
| 376 |
+
>>> outputs = model(input_ids=input_ids, labels=labels)
|
| 377 |
+
>>> loss, logits = outputs.loss, outputs.logits
|
| 378 |
+
|
| 379 |
+
>>> # save and load from pretrained
|
| 380 |
+
>>> model.save_pretrained("bert2bert")
|
| 381 |
+
>>> model = EncoderDecoderModel.from_pretrained("bert2bert")
|
| 382 |
+
|
| 383 |
+
>>> # generation
|
| 384 |
+
>>> generated = model.generate(input_ids)
|
| 385 |
+
```"""
|
| 386 |
+
# `record outputs` can rely on the absence of the kwarg to retrieve whether the config should be used or not
|
| 387 |
+
# Hence, we use this workaround to allow for defaults to work as expected
|
| 388 |
+
kwargs_shared = {key: kwargs[key] for key in ["output_attentions", "output_hidden_states"] if key in kwargs}
|
| 389 |
+
|
| 390 |
+
kwargs_encoder = {argument: value for argument, value in kwargs.items() if not argument.startswith("decoder_")}
|
| 391 |
+
kwargs_encoder = kwargs_encoder | kwargs_shared
|
| 392 |
+
|
| 393 |
+
kwargs_decoder = {
|
| 394 |
+
argument[len("decoder_") :]: value for argument, value in kwargs.items() if argument.startswith("decoder_")
|
| 395 |
+
}
|
| 396 |
+
if "num_items_in_batch" in kwargs_encoder:
|
| 397 |
+
kwargs_decoder["num_items_in_batch"] = kwargs_encoder.pop("num_items_in_batch", None)
|
| 398 |
+
kwargs_decoder = kwargs_decoder | kwargs_shared
|
| 399 |
+
|
| 400 |
+
if encoder_outputs is None:
|
| 401 |
+
encoder_outputs = self.encoder(
|
| 402 |
+
input_ids=input_ids,
|
| 403 |
+
attention_mask=attention_mask,
|
| 404 |
+
inputs_embeds=inputs_embeds,
|
| 405 |
+
return_dict=True,
|
| 406 |
+
**kwargs_encoder,
|
| 407 |
+
)
|
| 408 |
+
elif isinstance(encoder_outputs, tuple):
|
| 409 |
+
encoder_outputs = BaseModelOutput(*encoder_outputs)
|
| 410 |
+
|
| 411 |
+
encoder_hidden_states = encoder_outputs[0]
|
| 412 |
+
|
| 413 |
+
# optionally project encoder_hidden_states
|
| 414 |
+
if (
|
| 415 |
+
self.encoder.config.hidden_size != self.decoder.config.hidden_size
|
| 416 |
+
and getattr(self.decoder.config, "cross_attention_hidden_size", None) is None
|
| 417 |
+
):
|
| 418 |
+
encoder_hidden_states = self.enc_to_dec_proj(encoder_hidden_states)
|
| 419 |
+
|
| 420 |
+
if (labels is not None) and (decoder_input_ids is None and decoder_inputs_embeds is None):
|
| 421 |
+
decoder_input_ids = shift_tokens_right(
|
| 422 |
+
labels, self.config.pad_token_id, self.config.decoder_start_token_id
|
| 423 |
+
)
|
| 424 |
+
if decoder_attention_mask is None:
|
| 425 |
+
decoder_attention_mask = (decoder_input_ids != self.config.pad_token_id).to(decoder_input_ids.dtype)
|
| 426 |
+
|
| 427 |
+
# Decode
|
| 428 |
+
decoder_outputs = self.decoder(
|
| 429 |
+
input_ids=decoder_input_ids,
|
| 430 |
+
attention_mask=decoder_attention_mask,
|
| 431 |
+
encoder_hidden_states=encoder_hidden_states,
|
| 432 |
+
encoder_attention_mask=attention_mask,
|
| 433 |
+
inputs_embeds=decoder_inputs_embeds,
|
| 434 |
+
use_cache=use_cache,
|
| 435 |
+
past_key_values=past_key_values,
|
| 436 |
+
return_dict=True,
|
| 437 |
+
**kwargs_decoder,
|
| 438 |
+
)
|
| 439 |
+
|
| 440 |
+
# Compute loss independent from decoder (as some shift the logits inside them)
|
| 441 |
+
loss = None
|
| 442 |
+
if labels is not None:
|
| 443 |
+
warnings.warn(DEPRECATION_WARNING, FutureWarning)
|
| 444 |
+
logits = decoder_outputs.logits
|
| 445 |
+
loss_fct = CrossEntropyLoss()
|
| 446 |
+
loss = loss_fct(logits.reshape(-1, self.decoder.config.vocab_size), labels.view(-1))
|
| 447 |
+
|
| 448 |
+
return Seq2SeqLMOutput(
|
| 449 |
+
loss=loss,
|
| 450 |
+
logits=decoder_outputs.logits,
|
| 451 |
+
past_key_values=decoder_outputs.past_key_values,
|
| 452 |
+
decoder_hidden_states=decoder_outputs.hidden_states,
|
| 453 |
+
decoder_attentions=decoder_outputs.attentions,
|
| 454 |
+
cross_attentions=decoder_outputs.cross_attentions,
|
| 455 |
+
encoder_last_hidden_state=encoder_outputs.last_hidden_state,
|
| 456 |
+
encoder_hidden_states=encoder_outputs.hidden_states,
|
| 457 |
+
encoder_attentions=encoder_outputs.attentions,
|
| 458 |
+
)
|
| 459 |
+
|
| 460 |
+
def prepare_decoder_input_ids_from_labels(self, labels: torch.Tensor):
|
| 461 |
+
return shift_tokens_right(labels, self.config.pad_token_id, self.config.decoder_start_token_id)
|
| 462 |
+
|
| 463 |
+
def resize_token_embeddings(self, *args, **kwargs):
|
| 464 |
+
raise NotImplementedError(
|
| 465 |
+
"Resizing the embedding layers via the EncoderDecoderModel directly is not supported. Please use the"
|
| 466 |
+
" respective methods of the wrapped objects (model.encoder.resize_token_embeddings(...) or"
|
| 467 |
+
" model.decoder.resize_token_embeddings(...))"
|
| 468 |
+
)
|
| 469 |
+
|
| 470 |
+
|
| 471 |
+
__all__ = ["EncoderDecoderModel"]
|
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/models/lw_detr/__init__.py
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
+
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_lw_detr import *
|
| 22 |
+
from .modeling_lw_detr import *
|
| 23 |
+
else:
|
| 24 |
+
import sys
|
| 25 |
+
|
| 26 |
+
_file = globals()["__file__"]
|
| 27 |
+
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/lw_detr/configuration_lw_detr.py
ADDED
|
@@ -0,0 +1,226 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
|
| 2 |
+
# This file was automatically generated from src/transformers/models/lw_detr/modular_lw_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_lw_detr.py file directly. One of our CI enforces this.
|
| 6 |
+
# 🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
|
| 7 |
+
# Copyright 2026 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 |
+
|
| 22 |
+
from huggingface_hub.dataclasses import strict
|
| 23 |
+
|
| 24 |
+
from ...backbone_utils import BackboneConfigMixin, consolidate_backbone_kwargs_to_config
|
| 25 |
+
from ...configuration_utils import PreTrainedConfig
|
| 26 |
+
from ...utils import auto_docstring, logging
|
| 27 |
+
from ..auto import AutoConfig
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
logger = logging.get_logger(__name__)
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
@auto_docstring(checkpoint="AnnaZhang/lwdetr_small_60e_coco")
|
| 34 |
+
@strict
|
| 35 |
+
class LwDetrViTConfig(BackboneConfigMixin, PreTrainedConfig):
|
| 36 |
+
r"""
|
| 37 |
+
pretrain_image_size (`int`, *optional*, defaults to 224):
|
| 38 |
+
The size (resolution) of each image during pretraining.
|
| 39 |
+
window_block_indices (`list[int]`, *optional*, defaults to `[]`):
|
| 40 |
+
List of indices of blocks that should have window attention instead of regular global self-attention.
|
| 41 |
+
use_absolute_position_embeddings (`bool`, *optional*, defaults to `True`):
|
| 42 |
+
Whether to add absolute position embeddings to the patch embeddings.
|
| 43 |
+
cae_init_values (`float`, *optional*, defaults to 0.1):
|
| 44 |
+
Initialization value for CAE parameters when `use_cae` is enabled.
|
| 45 |
+
num_windows (`int`, *optional*, defaults to 16):
|
| 46 |
+
Number of windows for window-based attention. Must be a perfect square and the image size must be
|
| 47 |
+
divisible by the square root of this value. This enables efficient window-major feature map organization.
|
| 48 |
+
|
| 49 |
+
Example:
|
| 50 |
+
|
| 51 |
+
```python
|
| 52 |
+
>>> from transformers import LwDetrViTConfig, LwDetrViTModel
|
| 53 |
+
|
| 54 |
+
>>> # Initializing a LW-DETR ViT configuration
|
| 55 |
+
>>> configuration = LwDetrViTConfig()
|
| 56 |
+
|
| 57 |
+
>>> # Initializing a model (with random weights) from the configuration
|
| 58 |
+
>>> model = LwDetrViTModel(configuration)
|
| 59 |
+
|
| 60 |
+
>>> # Accessing the model configuration
|
| 61 |
+
>>> configuration = model.config
|
| 62 |
+
```"""
|
| 63 |
+
|
| 64 |
+
model_type = "lw_detr_vit"
|
| 65 |
+
|
| 66 |
+
hidden_size: int = 768
|
| 67 |
+
num_hidden_layers: int = 12
|
| 68 |
+
num_attention_heads: int = 12
|
| 69 |
+
mlp_ratio: int = 4
|
| 70 |
+
hidden_act: str = "gelu"
|
| 71 |
+
dropout_prob: float | int = 0.0
|
| 72 |
+
initializer_range: float = 0.02
|
| 73 |
+
layer_norm_eps: float = 1e-6
|
| 74 |
+
|
| 75 |
+
image_size: int | list[int] | tuple[int, int] = 256
|
| 76 |
+
pretrain_image_size: int | list[int] | tuple[int, int] = 224
|
| 77 |
+
patch_size: int | list[int] | tuple[int, int] = 16
|
| 78 |
+
num_channels: int = 3
|
| 79 |
+
qkv_bias: bool = True
|
| 80 |
+
window_block_indices: list[int] | tuple[int, ...] = ()
|
| 81 |
+
use_absolute_position_embeddings: bool = True
|
| 82 |
+
_out_features: list[str] | None = None
|
| 83 |
+
_out_indices: list[int] | None = None
|
| 84 |
+
cae_init_values: float = 0.1
|
| 85 |
+
num_windows: int = 16
|
| 86 |
+
|
| 87 |
+
def __post_init__(self, **kwargs):
|
| 88 |
+
self.num_windows_side = int(math.sqrt(self.num_windows))
|
| 89 |
+
self.stage_names = ["stem"] + [f"stage{idx}" for idx in range(1, self.num_hidden_layers + 1)]
|
| 90 |
+
self.set_output_features_output_indices(
|
| 91 |
+
out_indices=kwargs.pop("out_indices", None), out_features=kwargs.pop("out_features", None)
|
| 92 |
+
)
|
| 93 |
+
super().__post_init__(**kwargs)
|
| 94 |
+
|
| 95 |
+
def validate_architecture(self):
|
| 96 |
+
"""Part of `@strict`-powered validation. Validates the architecture of the config."""
|
| 97 |
+
if self.num_windows % math.sqrt(self.num_windows) != 0:
|
| 98 |
+
raise ValueError(
|
| 99 |
+
f"`num_windows` has to be a perfect square, where num_windows % math.sqrt(num_windows) != 0, but got {self.num_windows}."
|
| 100 |
+
)
|
| 101 |
+
if self.image_size / self.num_windows % math.sqrt(self.num_windows) != 0:
|
| 102 |
+
raise ValueError(
|
| 103 |
+
f"`image_size` has to be divisible by `num_windows`, where image_size / num_windows % math.sqrt(num_windows) != 0,but got {self.image_size} and {self.num_windows}."
|
| 104 |
+
)
|
| 105 |
+
|
| 106 |
+
|
| 107 |
+
@auto_docstring(checkpoint="AnnaZhang/lwdetr_small_60e_coco")
|
| 108 |
+
@strict
|
| 109 |
+
class LwDetrConfig(PreTrainedConfig):
|
| 110 |
+
r"""
|
| 111 |
+
projector_scale_factors (`list[float]`, *optional*, defaults to `[]`):
|
| 112 |
+
Scale factors for the feature pyramid network. Each scale factor determines the resolution of features
|
| 113 |
+
at different levels. Supported values are 0.5, 1.0, and 2.0.
|
| 114 |
+
hidden_expansion (`float`, *optional*, defaults to 0.5):
|
| 115 |
+
Expansion factor for hidden dimensions in the projector layers.
|
| 116 |
+
c2f_num_blocks (`int`, *optional*, defaults to 3):
|
| 117 |
+
Number of blocks in the C2F layer.
|
| 118 |
+
activation_function (`str`, *optional*, defaults to `"silu"`):
|
| 119 |
+
The non-linear activation function in the projector. Supported values are `"silu"`, `"relu"`, `"gelu"`.
|
| 120 |
+
batch_norm_eps (`float`, *optional*, defaults to 1e-05):
|
| 121 |
+
The epsilon value for batch normalization layers.
|
| 122 |
+
decoder_ffn_dim (`int`, *optional*, defaults to 2048):
|
| 123 |
+
Dimension of the "intermediate" (often named feed-forward) layer in decoder.
|
| 124 |
+
decoder_n_points (`int`, *optional*, defaults to 4):
|
| 125 |
+
The number of sampled keys in each feature level for each attention head in the decoder.
|
| 126 |
+
decoder_self_attention_heads (`int`, *optional*, defaults to 8):
|
| 127 |
+
Number of attention heads for each attention layer in the decoder self-attention.
|
| 128 |
+
decoder_cross_attention_heads (`int`, *optional*, defaults to 16):
|
| 129 |
+
Number of attention heads for each attention layer in the decoder cross-attention.
|
| 130 |
+
decoder_activation_function (`str`, *optional*, defaults to `"relu"`):
|
| 131 |
+
The non-linear activation function in the decoder. Supported values are `"relu"`, `"silu"`, `"gelu"`.
|
| 132 |
+
num_queries (`int`, *optional*, defaults to 300):
|
| 133 |
+
Number of object queries, i.e. detection slots. This is the maximal number of objects
|
| 134 |
+
[`LwDetrModel`] can detect in a single image.
|
| 135 |
+
group_detr (`int`, *optional*, defaults to 13):
|
| 136 |
+
Number of groups for Group DETR attention mechanism, which helps reduce computational complexity.
|
| 137 |
+
disable_custom_kernels (`bool`, *optional*, defaults to `True`):
|
| 138 |
+
Disable the use of custom CUDA and CPU kernels. This option is necessary for the ONNX export, as custom
|
| 139 |
+
kernels are not supported by PyTorch ONNX export.
|
| 140 |
+
class_loss_coefficient (`float`, *optional*, defaults to 1):
|
| 141 |
+
Relative weight of the classification loss in the Hungarian matching cost.
|
| 142 |
+
|
| 143 |
+
Examples:
|
| 144 |
+
|
| 145 |
+
```python
|
| 146 |
+
>>> from transformers import LwDetrConfig, LwDetrModel
|
| 147 |
+
|
| 148 |
+
>>> # Initializing a LW-DETR AnnaZhang/lwdetr_small_60e_coco style configuration
|
| 149 |
+
>>> configuration = LwDetrConfig()
|
| 150 |
+
|
| 151 |
+
>>> # Initializing a model (with random weights) from the AnnaZhang/lwdetr_small_60e_coco style configuration
|
| 152 |
+
>>> model = LwDetrModel(configuration)
|
| 153 |
+
|
| 154 |
+
>>> # Accessing the model configuration
|
| 155 |
+
>>> configuration = model.config
|
| 156 |
+
```"""
|
| 157 |
+
|
| 158 |
+
model_type = "lw_detr"
|
| 159 |
+
sub_configs = {"backbone_config": AutoConfig}
|
| 160 |
+
|
| 161 |
+
backbone_config: dict | PreTrainedConfig | None = None
|
| 162 |
+
projector_scale_factors: list[float] | tuple[float, ...] = ()
|
| 163 |
+
hidden_expansion: float = 0.5
|
| 164 |
+
c2f_num_blocks: int = 3
|
| 165 |
+
activation_function: str = "silu"
|
| 166 |
+
batch_norm_eps: float = 1e-5
|
| 167 |
+
dropout: float | int = 0.0
|
| 168 |
+
decoder_ffn_dim: int = 2048
|
| 169 |
+
decoder_n_points: int = 4
|
| 170 |
+
decoder_layers: int = 3
|
| 171 |
+
decoder_self_attention_heads: int = 8
|
| 172 |
+
decoder_cross_attention_heads: int = 16
|
| 173 |
+
decoder_activation_function: str = "relu"
|
| 174 |
+
num_queries: int = 300
|
| 175 |
+
attention_bias: bool = True
|
| 176 |
+
attention_dropout: float | int = 0.0
|
| 177 |
+
activation_dropout: float | int = 0.0
|
| 178 |
+
group_detr: int = 13
|
| 179 |
+
init_std: float = 0.02
|
| 180 |
+
disable_custom_kernels: bool = True
|
| 181 |
+
class_cost: int | float = 2
|
| 182 |
+
bbox_cost: int | float = 5
|
| 183 |
+
giou_cost: int | float = 2
|
| 184 |
+
class_loss_coefficient: int | float = 1
|
| 185 |
+
dice_loss_coefficient: int | float = 1
|
| 186 |
+
bbox_loss_coefficient: int | float = 5
|
| 187 |
+
giou_loss_coefficient: int | float = 2
|
| 188 |
+
eos_coefficient: float = 0.1
|
| 189 |
+
focal_alpha: float = 0.25
|
| 190 |
+
auxiliary_loss: bool = True
|
| 191 |
+
d_model: int = 256
|
| 192 |
+
|
| 193 |
+
def __post_init__(self, **kwargs):
|
| 194 |
+
if "mask_loss_coefficient" in kwargs:
|
| 195 |
+
logger.warning_once(
|
| 196 |
+
"The parameter `mask_loss_coefficient` was renamed to `class_loss_coefficient` in LW-DETR. "
|
| 197 |
+
"Please use `class_loss_coefficient` instead. `mask_loss_coefficient` will be removed in a future version."
|
| 198 |
+
)
|
| 199 |
+
self.class_loss_coefficient = kwargs.pop("mask_loss_coefficient")
|
| 200 |
+
|
| 201 |
+
self.backbone_config, kwargs = consolidate_backbone_kwargs_to_config(
|
| 202 |
+
backbone_config=self.backbone_config,
|
| 203 |
+
default_config_type="lw_detr_vit",
|
| 204 |
+
default_config_kwargs={
|
| 205 |
+
"image_size": 1024,
|
| 206 |
+
"hidden_size": 192,
|
| 207 |
+
"num_hidden_layers": 10,
|
| 208 |
+
"window_block_indices": [0, 1, 3, 6, 7, 9],
|
| 209 |
+
"out_indices": [2, 4, 5, 9],
|
| 210 |
+
},
|
| 211 |
+
**kwargs,
|
| 212 |
+
)
|
| 213 |
+
|
| 214 |
+
self.projector_in_channels = [self.d_model] * len(self.projector_scale_factors)
|
| 215 |
+
self.projector_out_channels = self.d_model
|
| 216 |
+
self.num_feature_levels = len(self.projector_scale_factors)
|
| 217 |
+
super().__post_init__(**kwargs)
|
| 218 |
+
|
| 219 |
+
def validate_architecture(self):
|
| 220 |
+
"""Part of `@strict`-powered validation. Validates the architecture of the config."""
|
| 221 |
+
for scale in self.projector_scale_factors:
|
| 222 |
+
if scale not in [0.5, 1.0, 2.0]:
|
| 223 |
+
raise ValueError(f"Unsupported scale factor: {scale}")
|
| 224 |
+
|
| 225 |
+
|
| 226 |
+
__all__ = ["LwDetrConfig", "LwDetrViTConfig"]
|
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/models/lw_detr/modeling_lw_detr.py
ADDED
|
@@ -0,0 +1,1673 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
|
| 2 |
+
# This file was automatically generated from src/transformers/models/lw_detr/modular_lw_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_lw_detr.py file directly. One of our CI enforces this.
|
| 6 |
+
# 🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
|
| 7 |
+
# Copyright 2026 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 collections.abc
|
| 21 |
+
import math
|
| 22 |
+
import warnings
|
| 23 |
+
from collections.abc import Callable
|
| 24 |
+
from dataclasses import dataclass
|
| 25 |
+
from typing import Any
|
| 26 |
+
|
| 27 |
+
import torch
|
| 28 |
+
import torch.nn.functional as F
|
| 29 |
+
from torch import Tensor, nn
|
| 30 |
+
|
| 31 |
+
from ... import initialization as init
|
| 32 |
+
from ...activations import ACT2CLS, ACT2FN
|
| 33 |
+
from ...backbone_utils import BackboneMixin, filter_output_hidden_states
|
| 34 |
+
from ...integrations import use_kernel_forward_from_hub
|
| 35 |
+
from ...modeling_layers import GradientCheckpointingLayer
|
| 36 |
+
from ...modeling_outputs import BackboneOutput, BaseModelOutput, BaseModelOutputWithCrossAttentions
|
| 37 |
+
from ...modeling_utils import ALL_ATTENTION_FUNCTIONS, PreTrainedModel
|
| 38 |
+
from ...processing_utils import Unpack
|
| 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_lw_detr import LwDetrConfig, LwDetrViTConfig
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
def eager_attention_forward(
|
| 46 |
+
module: nn.Module,
|
| 47 |
+
query: torch.Tensor,
|
| 48 |
+
key: torch.Tensor,
|
| 49 |
+
value: torch.Tensor,
|
| 50 |
+
attention_mask: torch.Tensor | None,
|
| 51 |
+
scaling: float,
|
| 52 |
+
dropout: float = 0.0,
|
| 53 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 54 |
+
):
|
| 55 |
+
key_states = repeat_kv(key, module.num_key_value_groups)
|
| 56 |
+
value_states = repeat_kv(value, module.num_key_value_groups)
|
| 57 |
+
|
| 58 |
+
attn_weights = torch.matmul(query, key_states.transpose(2, 3)) * scaling
|
| 59 |
+
if attention_mask is not None:
|
| 60 |
+
attn_weights = attn_weights + attention_mask
|
| 61 |
+
|
| 62 |
+
attn_weights = nn.functional.softmax(attn_weights, dim=-1, dtype=torch.float32).to(query.dtype)
|
| 63 |
+
attn_weights = nn.functional.dropout(attn_weights, p=dropout, training=module.training)
|
| 64 |
+
attn_output = torch.matmul(attn_weights, value_states)
|
| 65 |
+
attn_output = attn_output.transpose(1, 2).contiguous()
|
| 66 |
+
|
| 67 |
+
return attn_output, attn_weights
|
| 68 |
+
|
| 69 |
+
|
| 70 |
+
def repeat_kv(hidden_states: torch.Tensor, n_rep: int) -> torch.Tensor:
|
| 71 |
+
"""
|
| 72 |
+
This is the equivalent of torch.repeat_interleave(x, dim=1, repeats=n_rep). The hidden states go from (batch,
|
| 73 |
+
num_key_value_heads, seqlen, head_dim) to (batch, num_attention_heads, seqlen, head_dim)
|
| 74 |
+
"""
|
| 75 |
+
batch, num_key_value_heads, slen, head_dim = hidden_states.shape
|
| 76 |
+
if n_rep == 1:
|
| 77 |
+
return hidden_states
|
| 78 |
+
hidden_states = hidden_states[:, :, None, :, :].expand(batch, num_key_value_heads, n_rep, slen, head_dim)
|
| 79 |
+
return hidden_states.reshape(batch, num_key_value_heads * n_rep, slen, head_dim)
|
| 80 |
+
|
| 81 |
+
|
| 82 |
+
class LwDetrViTAttention(nn.Module):
|
| 83 |
+
"""LwDetr ViT attention with k_proj bias=False and dropout from config.dropout_prob."""
|
| 84 |
+
|
| 85 |
+
def __init__(self, config: LwDetrViTConfig):
|
| 86 |
+
super().__init__()
|
| 87 |
+
self.config = config
|
| 88 |
+
self.num_attention_heads = config.num_attention_heads
|
| 89 |
+
self.head_dim = getattr(config, "head_dim", config.hidden_size // config.num_attention_heads)
|
| 90 |
+
self.attention_dropout = config.dropout_prob
|
| 91 |
+
self.scaling = self.head_dim**-0.5
|
| 92 |
+
self.is_causal = False
|
| 93 |
+
|
| 94 |
+
self.q_proj = nn.Linear(config.hidden_size, config.num_attention_heads * self.head_dim, bias=config.qkv_bias)
|
| 95 |
+
self.k_proj = nn.Linear(config.hidden_size, config.num_attention_heads * self.head_dim, bias=False)
|
| 96 |
+
self.v_proj = nn.Linear(config.hidden_size, config.num_attention_heads * self.head_dim, bias=config.qkv_bias)
|
| 97 |
+
self.o_proj = nn.Linear(config.num_attention_heads * self.head_dim, config.hidden_size, bias=True)
|
| 98 |
+
self.num_key_value_groups = 1
|
| 99 |
+
|
| 100 |
+
def forward(
|
| 101 |
+
self,
|
| 102 |
+
hidden_states: torch.Tensor,
|
| 103 |
+
attention_mask: torch.Tensor | None = None,
|
| 104 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 105 |
+
) -> tuple[torch.Tensor, torch.Tensor]:
|
| 106 |
+
input_shape = hidden_states.shape[:-1]
|
| 107 |
+
hidden_shape = (*input_shape, -1, self.head_dim)
|
| 108 |
+
|
| 109 |
+
query_states = self.q_proj(hidden_states).view(hidden_shape).transpose(1, 2)
|
| 110 |
+
key_states = self.k_proj(hidden_states).view(hidden_shape).transpose(1, 2)
|
| 111 |
+
value_states = self.v_proj(hidden_states).view(hidden_shape).transpose(1, 2)
|
| 112 |
+
|
| 113 |
+
attention_interface: Callable = ALL_ATTENTION_FUNCTIONS.get_interface(
|
| 114 |
+
self.config._attn_implementation, eager_attention_forward
|
| 115 |
+
)
|
| 116 |
+
|
| 117 |
+
attn_output, attn_weights = attention_interface(
|
| 118 |
+
self,
|
| 119 |
+
query_states,
|
| 120 |
+
key_states,
|
| 121 |
+
value_states,
|
| 122 |
+
attention_mask,
|
| 123 |
+
dropout=0.0 if not self.training else self.attention_dropout,
|
| 124 |
+
scaling=self.scaling,
|
| 125 |
+
**kwargs,
|
| 126 |
+
)
|
| 127 |
+
|
| 128 |
+
attn_output = attn_output.reshape(*input_shape, -1).contiguous()
|
| 129 |
+
attn_output = self.o_proj(attn_output)
|
| 130 |
+
|
| 131 |
+
return attn_output, attn_weights
|
| 132 |
+
|
| 133 |
+
|
| 134 |
+
class LwDetrViTMlp(nn.Module):
|
| 135 |
+
def __init__(self, config, in_features: int, hidden_features: int) -> None:
|
| 136 |
+
super().__init__()
|
| 137 |
+
self.fc1 = nn.Linear(in_features, hidden_features)
|
| 138 |
+
self.act = ACT2FN[config.hidden_act]
|
| 139 |
+
self.fc2 = nn.Linear(hidden_features, in_features)
|
| 140 |
+
self.drop = nn.Dropout(config.dropout_prob)
|
| 141 |
+
|
| 142 |
+
def forward(self, x: torch.Tensor) -> torch.Tensor:
|
| 143 |
+
x = self.fc1(x)
|
| 144 |
+
x = self.act(x)
|
| 145 |
+
x = self.drop(x)
|
| 146 |
+
x = self.fc2(x)
|
| 147 |
+
x = self.drop(x)
|
| 148 |
+
|
| 149 |
+
return x
|
| 150 |
+
|
| 151 |
+
|
| 152 |
+
class LwDetrViTLayer(GradientCheckpointingLayer):
|
| 153 |
+
def __init__(
|
| 154 |
+
self,
|
| 155 |
+
config: LwDetrViTConfig,
|
| 156 |
+
layer_idx,
|
| 157 |
+
) -> None:
|
| 158 |
+
super().__init__()
|
| 159 |
+
|
| 160 |
+
dim = config.hidden_size
|
| 161 |
+
self.attention = LwDetrViTAttention(config)
|
| 162 |
+
self.intermediate = LwDetrViTMlp(config=config, in_features=dim, hidden_features=int(dim * config.mlp_ratio))
|
| 163 |
+
self.layernorm_before = nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps)
|
| 164 |
+
self.layernorm_after = nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps)
|
| 165 |
+
|
| 166 |
+
self.gamma_1 = nn.Parameter(torch.Tensor(dim), requires_grad=True)
|
| 167 |
+
self.gamma_2 = nn.Parameter(torch.Tensor(dim), requires_grad=True)
|
| 168 |
+
|
| 169 |
+
self.window = layer_idx in config.window_block_indices
|
| 170 |
+
self.num_windows = config.num_windows
|
| 171 |
+
|
| 172 |
+
def forward(
|
| 173 |
+
self,
|
| 174 |
+
hidden_states: torch.Tensor,
|
| 175 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 176 |
+
) -> torch.Tensor:
|
| 177 |
+
batch_size, seq_len, channels = hidden_states.shape
|
| 178 |
+
hidden_states_norm = self.layernorm_before(hidden_states)
|
| 179 |
+
|
| 180 |
+
if not self.window:
|
| 181 |
+
hidden_states_norm = hidden_states_norm.reshape(
|
| 182 |
+
batch_size // self.num_windows, self.num_windows * seq_len, channels
|
| 183 |
+
)
|
| 184 |
+
|
| 185 |
+
attention_output, _ = self.attention(hidden_states_norm, **kwargs)
|
| 186 |
+
attention_output = attention_output * self.gamma_1
|
| 187 |
+
|
| 188 |
+
if not self.window:
|
| 189 |
+
attention_output = attention_output.reshape(batch_size, seq_len, channels)
|
| 190 |
+
|
| 191 |
+
hidden_states = hidden_states + attention_output
|
| 192 |
+
|
| 193 |
+
layer_output = self.layernorm_after(hidden_states)
|
| 194 |
+
layer_output = self.intermediate(layer_output)
|
| 195 |
+
layer_output = layer_output * self.gamma_2
|
| 196 |
+
|
| 197 |
+
hidden_states = hidden_states + layer_output
|
| 198 |
+
|
| 199 |
+
return hidden_states
|
| 200 |
+
|
| 201 |
+
|
| 202 |
+
class LwDetrViTEmbeddings(nn.Module):
|
| 203 |
+
"""
|
| 204 |
+
This class turns `pixel_values` of shape `(batch_size, num_channels, height, width)` into the initial
|
| 205 |
+
`hidden_states` (patch embeddings) to be consumed by a Transformer.
|
| 206 |
+
"""
|
| 207 |
+
|
| 208 |
+
def __init__(self, config):
|
| 209 |
+
super().__init__()
|
| 210 |
+
image_size, patch_size = config.pretrain_image_size, config.patch_size
|
| 211 |
+
num_channels, hidden_size = config.num_channels, config.hidden_size
|
| 212 |
+
|
| 213 |
+
image_size = image_size if isinstance(image_size, collections.abc.Iterable) else (image_size, image_size)
|
| 214 |
+
patch_size = patch_size if isinstance(patch_size, collections.abc.Iterable) else (patch_size, patch_size)
|
| 215 |
+
num_patches = (image_size[1] // patch_size[1]) * (image_size[0] // patch_size[0])
|
| 216 |
+
self.image_size = image_size
|
| 217 |
+
self.patch_size = patch_size
|
| 218 |
+
self.num_channels = num_channels
|
| 219 |
+
self.num_patches = num_patches
|
| 220 |
+
|
| 221 |
+
if config.use_absolute_position_embeddings:
|
| 222 |
+
# Initialize absolute positional embedding with pretrain image size.
|
| 223 |
+
num_positions = num_patches + 1
|
| 224 |
+
self.position_embeddings = nn.Parameter(torch.zeros(1, num_positions, config.hidden_size))
|
| 225 |
+
else:
|
| 226 |
+
self.position_embeddings = None
|
| 227 |
+
|
| 228 |
+
self.projection = nn.Conv2d(num_channels, hidden_size, kernel_size=patch_size, stride=patch_size)
|
| 229 |
+
|
| 230 |
+
def get_absolute_positions(self, abs_pos_embeddings, has_cls_token, height, width):
|
| 231 |
+
"""
|
| 232 |
+
Calculate absolute positional embeddings. If needed, resize embeddings and remove cls_token dimension for the
|
| 233 |
+
original embeddings.
|
| 234 |
+
|
| 235 |
+
Args:
|
| 236 |
+
abs_pos_embeddings (`torch.Tensor`):
|
| 237 |
+
Absolute positional embeddings with (1, num_position, num_channels).
|
| 238 |
+
has_cls_token (`bool`):
|
| 239 |
+
If true, has 1 embedding in abs_pos_embeddings for cls token.
|
| 240 |
+
height (`int`):
|
| 241 |
+
Height of input image tokens.
|
| 242 |
+
width (`int`):
|
| 243 |
+
Width of input image tokens.
|
| 244 |
+
|
| 245 |
+
Returns:
|
| 246 |
+
Absolute positional embeddings after processing with shape (1, height, width, num_channels)
|
| 247 |
+
"""
|
| 248 |
+
if has_cls_token:
|
| 249 |
+
abs_pos_embeddings = abs_pos_embeddings[:, 1:]
|
| 250 |
+
num_position = abs_pos_embeddings.shape[1]
|
| 251 |
+
size = int(math.sqrt(num_position)) # This is a constant and can be recorded as such in the ONNX export.
|
| 252 |
+
if size * size != num_position:
|
| 253 |
+
raise ValueError("Absolute position embeddings must be a square number.")
|
| 254 |
+
|
| 255 |
+
if torch.jit.is_tracing() or (size != height or size != width):
|
| 256 |
+
# nn.functional.interpolate is a noop in case size == height and size == width - we need to always capture this path with jit.trace.
|
| 257 |
+
new_abs_pos_embeddings = nn.functional.interpolate(
|
| 258 |
+
abs_pos_embeddings.reshape(1, size, size, -1).permute(0, 3, 1, 2),
|
| 259 |
+
size=(height, width),
|
| 260 |
+
mode="bicubic",
|
| 261 |
+
align_corners=False,
|
| 262 |
+
)
|
| 263 |
+
|
| 264 |
+
return new_abs_pos_embeddings.permute(0, 2, 3, 1)
|
| 265 |
+
else:
|
| 266 |
+
return abs_pos_embeddings.reshape(1, height, width, -1)
|
| 267 |
+
|
| 268 |
+
def forward(self, pixel_values: torch.Tensor) -> torch.Tensor:
|
| 269 |
+
num_channels = pixel_values.shape[1]
|
| 270 |
+
if num_channels != self.num_channels:
|
| 271 |
+
raise ValueError(
|
| 272 |
+
"Make sure that the channel dimension of the pixel values match with the one set in the configuration."
|
| 273 |
+
f" Expected {self.num_channels} but got {num_channels}."
|
| 274 |
+
)
|
| 275 |
+
embeddings = self.projection(pixel_values)
|
| 276 |
+
|
| 277 |
+
if self.position_embeddings is not None:
|
| 278 |
+
# (batch_size, num_channels, height, width) -> (batch_size, height, width, num_channels)
|
| 279 |
+
embeddings = embeddings.permute(0, 2, 3, 1)
|
| 280 |
+
# add position embeddings
|
| 281 |
+
embeddings = embeddings + self.get_absolute_positions(
|
| 282 |
+
self.position_embeddings, True, embeddings.shape[1], embeddings.shape[2]
|
| 283 |
+
)
|
| 284 |
+
# (batch_size, height, width, num_channels) -> (batch_size, num_channels, height, width)
|
| 285 |
+
embeddings = embeddings.permute(0, 3, 1, 2)
|
| 286 |
+
|
| 287 |
+
return embeddings
|
| 288 |
+
|
| 289 |
+
|
| 290 |
+
@auto_docstring
|
| 291 |
+
class LwDetrViTPreTrainedModel(PreTrainedModel):
|
| 292 |
+
config: LwDetrViTConfig
|
| 293 |
+
base_model_prefix = "lw_detr_vit"
|
| 294 |
+
main_input_name = "pixel_values"
|
| 295 |
+
input_modalities = ("image",)
|
| 296 |
+
supports_gradient_checkpointing = True
|
| 297 |
+
_no_split_modules = ["LwDetrViTEmbeddings", "LwDetrViTLayer"]
|
| 298 |
+
_supports_sdpa = True
|
| 299 |
+
_supports_flash_attn = True
|
| 300 |
+
_supports_flex_attn = True
|
| 301 |
+
_supports_attention_backend = True
|
| 302 |
+
_can_record_outputs = {
|
| 303 |
+
"hidden_states": LwDetrViTLayer,
|
| 304 |
+
"attentions": LwDetrViTAttention,
|
| 305 |
+
}
|
| 306 |
+
|
| 307 |
+
@torch.no_grad()
|
| 308 |
+
def _init_weights(self, module) -> None:
|
| 309 |
+
"""Initialize the weights"""
|
| 310 |
+
if isinstance(module, (nn.Linear, nn.Conv2d)):
|
| 311 |
+
init.trunc_normal_(module.weight, mean=0.0, std=self.config.initializer_range)
|
| 312 |
+
if module.bias is not None:
|
| 313 |
+
init.zeros_(module.bias)
|
| 314 |
+
elif isinstance(module, nn.LayerNorm):
|
| 315 |
+
init.zeros_(module.bias)
|
| 316 |
+
init.ones_(module.weight)
|
| 317 |
+
elif isinstance(module, LwDetrViTEmbeddings):
|
| 318 |
+
init.trunc_normal_(module.position_embeddings, mean=0.0, std=self.config.initializer_range)
|
| 319 |
+
if isinstance(module, LwDetrViTLayer):
|
| 320 |
+
init.constant_(module.gamma_1, self.config.cae_init_values)
|
| 321 |
+
init.constant_(module.gamma_2, self.config.cae_init_values)
|
| 322 |
+
|
| 323 |
+
|
| 324 |
+
class LwDetrViTEncoder(LwDetrViTPreTrainedModel):
|
| 325 |
+
def __init__(self, config: LwDetrViTConfig):
|
| 326 |
+
super().__init__(config)
|
| 327 |
+
self.layer = nn.ModuleList([LwDetrViTLayer(config, idx) for idx in range(config.num_hidden_layers)])
|
| 328 |
+
self.post_init()
|
| 329 |
+
|
| 330 |
+
@merge_with_config_defaults
|
| 331 |
+
@capture_outputs
|
| 332 |
+
def forward(
|
| 333 |
+
self,
|
| 334 |
+
hidden_states: torch.Tensor,
|
| 335 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 336 |
+
) -> BaseModelOutput:
|
| 337 |
+
for layer_module in self.layer:
|
| 338 |
+
hidden_states = layer_module(hidden_states, **kwargs)
|
| 339 |
+
|
| 340 |
+
return BaseModelOutput(last_hidden_state=hidden_states)
|
| 341 |
+
|
| 342 |
+
|
| 343 |
+
@auto_docstring()
|
| 344 |
+
class LwDetrViTBackbone(BackboneMixin, LwDetrViTPreTrainedModel):
|
| 345 |
+
def __init__(self, config):
|
| 346 |
+
super().__init__(config)
|
| 347 |
+
|
| 348 |
+
self.embeddings = LwDetrViTEmbeddings(config)
|
| 349 |
+
self.encoder = LwDetrViTEncoder(config)
|
| 350 |
+
self.num_features = [config.hidden_size for _ in range(config.num_hidden_layers + 1)]
|
| 351 |
+
|
| 352 |
+
# initialize weights and apply final processing
|
| 353 |
+
self.post_init()
|
| 354 |
+
|
| 355 |
+
def get_input_embeddings(self) -> LwDetrViTEmbeddings:
|
| 356 |
+
return self.embeddings.projection
|
| 357 |
+
|
| 358 |
+
@can_return_tuple
|
| 359 |
+
@filter_output_hidden_states
|
| 360 |
+
@auto_docstring
|
| 361 |
+
def forward(self, pixel_values: torch.Tensor, **kwargs: Unpack[TransformersKwargs]) -> BackboneOutput:
|
| 362 |
+
r"""
|
| 363 |
+
Examples:
|
| 364 |
+
|
| 365 |
+
```python
|
| 366 |
+
>>> from transformers import LwDetrViTConfig, LwDetrViTBackbone
|
| 367 |
+
>>> import torch
|
| 368 |
+
|
| 369 |
+
>>> config = LwDetrViTConfig()
|
| 370 |
+
>>> model = LwDetrViTBackbone(config)
|
| 371 |
+
|
| 372 |
+
>>> pixel_values = torch.randn(1, 3, 224, 224)
|
| 373 |
+
|
| 374 |
+
>>> with torch.no_grad():
|
| 375 |
+
... outputs = model(pixel_values)
|
| 376 |
+
|
| 377 |
+
>>> feature_maps = outputs.feature_maps
|
| 378 |
+
>>> list(feature_maps[-1].shape)
|
| 379 |
+
[1, 768, 14, 14]
|
| 380 |
+
```"""
|
| 381 |
+
embedding_output = self.embeddings(pixel_values)
|
| 382 |
+
|
| 383 |
+
batch_size, channels, height, width = embedding_output.shape
|
| 384 |
+
# (batch_size, channels, height, width) -> (batch_size, height, width, channels)
|
| 385 |
+
hidden_states = embedding_output.permute(0, 2, 3, 1)
|
| 386 |
+
|
| 387 |
+
window_height = height // self.config.num_windows_side
|
| 388 |
+
window_width = width // self.config.num_windows_side
|
| 389 |
+
# (batch_size, height, width, channels) -> (batch_size*num_windows_side**2, window_height*window_width, channels)
|
| 390 |
+
hidden_states = (
|
| 391 |
+
hidden_states.reshape(
|
| 392 |
+
batch_size,
|
| 393 |
+
self.config.num_windows_side,
|
| 394 |
+
window_height,
|
| 395 |
+
self.config.num_windows_side,
|
| 396 |
+
window_width,
|
| 397 |
+
channels,
|
| 398 |
+
)
|
| 399 |
+
.permute(0, 1, 3, 2, 4, 5)
|
| 400 |
+
.reshape(batch_size * self.config.num_windows_side**2, window_height * window_width, channels)
|
| 401 |
+
)
|
| 402 |
+
|
| 403 |
+
kwargs["output_hidden_states"] = True # required to extract layers for the stages
|
| 404 |
+
output = self.encoder(hidden_states, **kwargs)
|
| 405 |
+
|
| 406 |
+
feature_maps = ()
|
| 407 |
+
hidden_states = output.hidden_states
|
| 408 |
+
for stage, hidden_state in zip(self.stage_names, hidden_states):
|
| 409 |
+
if stage in self.out_features:
|
| 410 |
+
hidden_state = (
|
| 411 |
+
hidden_state.reshape(
|
| 412 |
+
batch_size,
|
| 413 |
+
self.config.num_windows_side,
|
| 414 |
+
self.config.num_windows_side,
|
| 415 |
+
window_height,
|
| 416 |
+
window_width,
|
| 417 |
+
channels,
|
| 418 |
+
)
|
| 419 |
+
.permute(0, 5, 1, 3, 2, 4)
|
| 420 |
+
.reshape(batch_size, channels, height, width)
|
| 421 |
+
)
|
| 422 |
+
feature_maps += (hidden_state,)
|
| 423 |
+
|
| 424 |
+
return BackboneOutput(
|
| 425 |
+
feature_maps=feature_maps, hidden_states=output.hidden_states, attentions=output.attentions
|
| 426 |
+
)
|
| 427 |
+
|
| 428 |
+
|
| 429 |
+
class LwDetrConvNormLayer(nn.Module):
|
| 430 |
+
def __init__(
|
| 431 |
+
self,
|
| 432 |
+
config: LwDetrConfig,
|
| 433 |
+
in_channels: int,
|
| 434 |
+
out_channels: int,
|
| 435 |
+
kernel_size: int,
|
| 436 |
+
stride: int,
|
| 437 |
+
activation: str | None = None,
|
| 438 |
+
):
|
| 439 |
+
super().__init__()
|
| 440 |
+
self.conv = nn.Conv2d(
|
| 441 |
+
in_channels,
|
| 442 |
+
out_channels,
|
| 443 |
+
kernel_size,
|
| 444 |
+
stride,
|
| 445 |
+
padding=kernel_size // 2,
|
| 446 |
+
bias=False,
|
| 447 |
+
)
|
| 448 |
+
self.norm = nn.BatchNorm2d(out_channels, config.batch_norm_eps)
|
| 449 |
+
self.activation = nn.Identity() if activation is None else ACT2CLS[activation]()
|
| 450 |
+
|
| 451 |
+
def forward(self, hidden_state):
|
| 452 |
+
hidden_state = self.conv(hidden_state)
|
| 453 |
+
hidden_state = self.norm(hidden_state)
|
| 454 |
+
hidden_state = self.activation(hidden_state)
|
| 455 |
+
return hidden_state
|
| 456 |
+
|
| 457 |
+
|
| 458 |
+
class LwDetrRepVggBlock(nn.Module):
|
| 459 |
+
def __init__(self, config: LwDetrConfig):
|
| 460 |
+
super().__init__()
|
| 461 |
+
hidden_channels = int(config.d_model * config.hidden_expansion)
|
| 462 |
+
self.conv1 = LwDetrConvNormLayer(
|
| 463 |
+
config, hidden_channels, hidden_channels, 3, 1, activation=config.activation_function
|
| 464 |
+
)
|
| 465 |
+
self.conv2 = LwDetrConvNormLayer(
|
| 466 |
+
config, hidden_channels, hidden_channels, 3, 1, activation=config.activation_function
|
| 467 |
+
)
|
| 468 |
+
|
| 469 |
+
def forward(self, x: torch.Tensor) -> torch.Tensor:
|
| 470 |
+
y = self.conv1(x)
|
| 471 |
+
y = self.conv2(y)
|
| 472 |
+
return y
|
| 473 |
+
|
| 474 |
+
|
| 475 |
+
class LwDetrC2FLayer(nn.Module):
|
| 476 |
+
# Inspired by RTDetrCSPRepLayer
|
| 477 |
+
def __init__(self, config: LwDetrConfig, in_channels: int):
|
| 478 |
+
super().__init__()
|
| 479 |
+
num_blocks = config.c2f_num_blocks
|
| 480 |
+
activation = config.activation_function
|
| 481 |
+
out_channels = config.d_model
|
| 482 |
+
|
| 483 |
+
self.hidden_channels = int(out_channels * config.hidden_expansion)
|
| 484 |
+
|
| 485 |
+
conv1_out_channels = 2 * self.hidden_channels
|
| 486 |
+
self.conv1 = LwDetrConvNormLayer(config, in_channels, conv1_out_channels, 1, 1, activation=activation)
|
| 487 |
+
|
| 488 |
+
conv2_in_channels = (2 + num_blocks) * self.hidden_channels
|
| 489 |
+
self.conv2 = LwDetrConvNormLayer(config, conv2_in_channels, out_channels, 1, 1, activation=activation)
|
| 490 |
+
|
| 491 |
+
self.bottlenecks = nn.ModuleList(LwDetrRepVggBlock(config) for _ in range(num_blocks))
|
| 492 |
+
|
| 493 |
+
def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
|
| 494 |
+
hidden_states = self.conv1(hidden_states)
|
| 495 |
+
all_hidden_states = list(hidden_states.split(self.hidden_channels, 1))
|
| 496 |
+
hidden_states = all_hidden_states[-1]
|
| 497 |
+
hidden_states = hidden_states.contiguous()
|
| 498 |
+
|
| 499 |
+
for bottleneck in self.bottlenecks:
|
| 500 |
+
hidden_states = bottleneck(hidden_states)
|
| 501 |
+
all_hidden_states.append(hidden_states)
|
| 502 |
+
|
| 503 |
+
hidden_states = torch.cat(all_hidden_states, 1)
|
| 504 |
+
hidden_states = self.conv2(hidden_states)
|
| 505 |
+
return hidden_states
|
| 506 |
+
|
| 507 |
+
|
| 508 |
+
class LwDetrLayerNorm(nn.LayerNorm):
|
| 509 |
+
r"""LayerNorm that supports two data formats: channels_last (default) or channels_first.
|
| 510 |
+
The ordering of the dimensions in the inputs. channels_last corresponds to inputs with shape (batch_size, height,
|
| 511 |
+
width, channels) while channels_first corresponds to inputs with shape (batch_size, channels, height, width).
|
| 512 |
+
"""
|
| 513 |
+
|
| 514 |
+
def __init__(self, normalized_shape, *, eps=1e-6, data_format="channels_last", **kwargs):
|
| 515 |
+
super().__init__(normalized_shape, eps=eps, **kwargs)
|
| 516 |
+
if data_format not in ["channels_last", "channels_first"]:
|
| 517 |
+
raise NotImplementedError(f"Unsupported data format: {data_format}")
|
| 518 |
+
self.data_format = data_format
|
| 519 |
+
|
| 520 |
+
def forward(self, features: torch.Tensor) -> torch.Tensor:
|
| 521 |
+
"""
|
| 522 |
+
Args:
|
| 523 |
+
features: Tensor of shape (batch_size, channels, height, width) OR (batch_size, height, width, channels)
|
| 524 |
+
"""
|
| 525 |
+
if self.data_format == "channels_first":
|
| 526 |
+
features = features.permute(0, 2, 3, 1)
|
| 527 |
+
features = super().forward(features)
|
| 528 |
+
features = features.permute(0, 3, 1, 2)
|
| 529 |
+
else:
|
| 530 |
+
features = super().forward(features)
|
| 531 |
+
return features
|
| 532 |
+
|
| 533 |
+
|
| 534 |
+
class LwDetrSamplingLayer(nn.Module):
|
| 535 |
+
def __init__(self, config: LwDetrConfig, channel_size: int, scale: float):
|
| 536 |
+
super().__init__()
|
| 537 |
+
|
| 538 |
+
self.scale = scale
|
| 539 |
+
self.channel_size = channel_size
|
| 540 |
+
|
| 541 |
+
layers = []
|
| 542 |
+
if scale == 2.0:
|
| 543 |
+
if channel_size > 512:
|
| 544 |
+
layers.append(LwDetrConvNormLayer(config, channel_size, channel_size // 2, 1, 1, activation="relu"))
|
| 545 |
+
layers.append(nn.ConvTranspose2d(channel_size // 2, channel_size // 4, kernel_size=2, stride=2))
|
| 546 |
+
else:
|
| 547 |
+
layers.append(nn.ConvTranspose2d(channel_size, channel_size // 2, 2, 2))
|
| 548 |
+
elif scale == 0.5:
|
| 549 |
+
layers.append(LwDetrConvNormLayer(config, channel_size, channel_size, 3, 2, activation="relu"))
|
| 550 |
+
self.layers = nn.ModuleList(layers)
|
| 551 |
+
|
| 552 |
+
def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
|
| 553 |
+
for layer in self.layers:
|
| 554 |
+
hidden_states = layer(hidden_states)
|
| 555 |
+
return hidden_states
|
| 556 |
+
|
| 557 |
+
|
| 558 |
+
class LwDetrScaleProjector(nn.Module):
|
| 559 |
+
def __init__(self, config: LwDetrConfig, scale: float):
|
| 560 |
+
super().__init__()
|
| 561 |
+
|
| 562 |
+
intermediate_dims = [config.backbone_config.hidden_size] * len(config.backbone_config.out_indices)
|
| 563 |
+
sampling_layers = []
|
| 564 |
+
for channel_size in intermediate_dims:
|
| 565 |
+
sampling_layers.append(LwDetrSamplingLayer(config, channel_size, scale))
|
| 566 |
+
self.sampling_layers = nn.ModuleList(sampling_layers)
|
| 567 |
+
|
| 568 |
+
intermediate_dim = intermediate_dims[-1]
|
| 569 |
+
if scale == 2.0:
|
| 570 |
+
if intermediate_dim > 512:
|
| 571 |
+
intermediate_dim = intermediate_dim // 4
|
| 572 |
+
else:
|
| 573 |
+
intermediate_dim = intermediate_dim // 2
|
| 574 |
+
projector_input_dim = intermediate_dim * len(intermediate_dims)
|
| 575 |
+
|
| 576 |
+
self.projector_layer = LwDetrC2FLayer(config, projector_input_dim)
|
| 577 |
+
self.layer_norm = LwDetrLayerNorm(config.d_model, data_format="channels_first")
|
| 578 |
+
|
| 579 |
+
def forward(self, hidden_states_tuple: tuple[torch.Tensor]) -> torch.Tensor:
|
| 580 |
+
sampled_hidden_states = []
|
| 581 |
+
for sampling_layer, hidden_states in zip(self.sampling_layers, hidden_states_tuple):
|
| 582 |
+
hidden_states = sampling_layer(hidden_states)
|
| 583 |
+
sampled_hidden_states.append(hidden_states)
|
| 584 |
+
hidden_states = torch.cat(sampled_hidden_states, dim=1)
|
| 585 |
+
hidden_states = self.projector_layer(hidden_states)
|
| 586 |
+
hidden_states = self.layer_norm(hidden_states)
|
| 587 |
+
return hidden_states
|
| 588 |
+
|
| 589 |
+
|
| 590 |
+
class LwDetrMultiScaleProjector(nn.Module):
|
| 591 |
+
def __init__(self, config: LwDetrConfig):
|
| 592 |
+
super().__init__()
|
| 593 |
+
|
| 594 |
+
self.config = config
|
| 595 |
+
scale_factors = config.projector_scale_factors
|
| 596 |
+
|
| 597 |
+
self.scale_layers = nn.ModuleList([LwDetrScaleProjector(config, scale) for scale in scale_factors])
|
| 598 |
+
|
| 599 |
+
def forward(self, hidden_states: tuple[torch.Tensor]) -> list[torch.Tensor]:
|
| 600 |
+
output_hidden_states = []
|
| 601 |
+
for scale_layer in self.scale_layers:
|
| 602 |
+
output_hidden_states.append(scale_layer(hidden_states))
|
| 603 |
+
return output_hidden_states
|
| 604 |
+
|
| 605 |
+
|
| 606 |
+
class LwDetrConvEncoder(nn.Module):
|
| 607 |
+
def __init__(self, config: LwDetrConfig):
|
| 608 |
+
super().__init__()
|
| 609 |
+
self.backbone = LwDetrViTBackbone(config.backbone_config)
|
| 610 |
+
self.projector = LwDetrMultiScaleProjector(config)
|
| 611 |
+
|
| 612 |
+
def forward(self, pixel_values: torch.Tensor, pixel_mask: torch.Tensor):
|
| 613 |
+
# send pixel_values through the model to get list of feature maps
|
| 614 |
+
features = self.backbone(pixel_values).feature_maps
|
| 615 |
+
features = self.projector(features)
|
| 616 |
+
out = []
|
| 617 |
+
for feature_map in features:
|
| 618 |
+
# downsample pixel_mask to match shape of corresponding feature_map
|
| 619 |
+
mask = nn.functional.interpolate(pixel_mask[None].float(), size=feature_map.shape[-2:]).to(torch.bool)[0]
|
| 620 |
+
out.append((feature_map, mask))
|
| 621 |
+
return out
|
| 622 |
+
|
| 623 |
+
|
| 624 |
+
class LwDetrAttention(nn.Module):
|
| 625 |
+
"""LW-DETR self-attention with group-DETR training technique."""
|
| 626 |
+
|
| 627 |
+
def __init__(self, config: LwDetrConfig, layer_idx: int):
|
| 628 |
+
super().__init__()
|
| 629 |
+
self.config = config
|
| 630 |
+
self.layer_idx = layer_idx
|
| 631 |
+
self.head_dim = getattr(config, "head_dim", config.d_model // config.decoder_self_attention_heads)
|
| 632 |
+
self.scaling = self.head_dim**-0.5
|
| 633 |
+
self.attention_dropout = config.attention_dropout
|
| 634 |
+
self.is_causal = False
|
| 635 |
+
self.num_key_value_groups = 1
|
| 636 |
+
|
| 637 |
+
self.q_proj = nn.Linear(
|
| 638 |
+
config.d_model, config.decoder_self_attention_heads * self.head_dim, bias=config.attention_bias
|
| 639 |
+
)
|
| 640 |
+
self.k_proj = nn.Linear(
|
| 641 |
+
config.d_model, config.decoder_self_attention_heads * self.head_dim, bias=config.attention_bias
|
| 642 |
+
)
|
| 643 |
+
self.v_proj = nn.Linear(
|
| 644 |
+
config.d_model, config.decoder_self_attention_heads * self.head_dim, bias=config.attention_bias
|
| 645 |
+
)
|
| 646 |
+
self.o_proj = nn.Linear(
|
| 647 |
+
config.decoder_self_attention_heads * self.head_dim, config.d_model, bias=config.attention_bias
|
| 648 |
+
)
|
| 649 |
+
|
| 650 |
+
def forward(
|
| 651 |
+
self,
|
| 652 |
+
hidden_states: torch.Tensor,
|
| 653 |
+
position_embeddings: torch.Tensor | None = None,
|
| 654 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 655 |
+
) -> tuple[torch.Tensor, torch.Tensor]:
|
| 656 |
+
batch_size, seq_len, _ = hidden_states.shape
|
| 657 |
+
|
| 658 |
+
hidden_states_original = hidden_states
|
| 659 |
+
if position_embeddings is not None:
|
| 660 |
+
hidden_states = hidden_states if position_embeddings is None else hidden_states + position_embeddings
|
| 661 |
+
|
| 662 |
+
if self.training:
|
| 663 |
+
# at training, we use group detr technique to add more supervision by using multiple weight-sharing decoders at once for faster convergence
|
| 664 |
+
# at inference, we only use one decoder
|
| 665 |
+
hidden_states_original = torch.cat(
|
| 666 |
+
hidden_states_original.split(seq_len // self.config.group_detr, dim=1), dim=0
|
| 667 |
+
)
|
| 668 |
+
hidden_states = torch.cat(hidden_states.split(seq_len // self.config.group_detr, dim=1), dim=0)
|
| 669 |
+
|
| 670 |
+
attention_input_shape = hidden_states.shape[:-1]
|
| 671 |
+
hidden_shape = (*attention_input_shape, -1, self.head_dim)
|
| 672 |
+
query_states = self.q_proj(hidden_states).view(hidden_shape).transpose(1, 2)
|
| 673 |
+
key_states = self.k_proj(hidden_states).view(hidden_shape).transpose(1, 2)
|
| 674 |
+
value_states = self.v_proj(hidden_states_original).view(hidden_shape).transpose(1, 2)
|
| 675 |
+
|
| 676 |
+
attention_interface: Callable = ALL_ATTENTION_FUNCTIONS.get_interface(
|
| 677 |
+
self.config._attn_implementation, eager_attention_forward
|
| 678 |
+
)
|
| 679 |
+
|
| 680 |
+
attn_output, attn_weights = attention_interface(
|
| 681 |
+
self,
|
| 682 |
+
query_states,
|
| 683 |
+
key_states,
|
| 684 |
+
value_states,
|
| 685 |
+
attention_mask=None,
|
| 686 |
+
dropout=0.0 if not self.training else self.attention_dropout,
|
| 687 |
+
scaling=self.scaling,
|
| 688 |
+
**kwargs,
|
| 689 |
+
)
|
| 690 |
+
attn_output = attn_output.reshape(*attention_input_shape, -1).contiguous()
|
| 691 |
+
attn_output = self.o_proj(attn_output)
|
| 692 |
+
|
| 693 |
+
if self.training:
|
| 694 |
+
attn_output = torch.cat(torch.split(attn_output, batch_size, dim=0), dim=1)
|
| 695 |
+
|
| 696 |
+
return attn_output, attn_weights
|
| 697 |
+
|
| 698 |
+
|
| 699 |
+
@use_kernel_forward_from_hub("MultiScaleDeformableAttention")
|
| 700 |
+
class MultiScaleDeformableAttention(nn.Module):
|
| 701 |
+
def forward(
|
| 702 |
+
self,
|
| 703 |
+
value: Tensor,
|
| 704 |
+
value_spatial_shapes: Tensor,
|
| 705 |
+
value_spatial_shapes_list: list[tuple],
|
| 706 |
+
level_start_index: Tensor,
|
| 707 |
+
sampling_locations: Tensor,
|
| 708 |
+
attention_weights: Tensor,
|
| 709 |
+
im2col_step: int,
|
| 710 |
+
):
|
| 711 |
+
batch_size, _, num_heads, hidden_dim = value.shape
|
| 712 |
+
_, num_queries, num_heads, num_levels, num_points, _ = sampling_locations.shape
|
| 713 |
+
value_list = value.split([height * width for height, width in value_spatial_shapes_list], dim=1)
|
| 714 |
+
sampling_grids = 2 * sampling_locations - 1
|
| 715 |
+
sampling_value_list = []
|
| 716 |
+
for level_id, (height, width) in enumerate(value_spatial_shapes_list):
|
| 717 |
+
# batch_size, height*width, num_heads, hidden_dim
|
| 718 |
+
# -> batch_size, height*width, num_heads*hidden_dim
|
| 719 |
+
# -> batch_size, num_heads*hidden_dim, height*width
|
| 720 |
+
# -> batch_size*num_heads, hidden_dim, height, width
|
| 721 |
+
value_l_ = (
|
| 722 |
+
value_list[level_id]
|
| 723 |
+
.flatten(2)
|
| 724 |
+
.transpose(1, 2)
|
| 725 |
+
.reshape(batch_size * num_heads, hidden_dim, height, width)
|
| 726 |
+
)
|
| 727 |
+
# batch_size, num_queries, num_heads, num_points, 2
|
| 728 |
+
# -> batch_size, num_heads, num_queries, num_points, 2
|
| 729 |
+
# -> batch_size*num_heads, num_queries, num_points, 2
|
| 730 |
+
sampling_grid_l_ = sampling_grids[:, :, :, level_id].transpose(1, 2).flatten(0, 1)
|
| 731 |
+
# batch_size*num_heads, hidden_dim, num_queries, num_points
|
| 732 |
+
sampling_value_l_ = nn.functional.grid_sample(
|
| 733 |
+
value_l_,
|
| 734 |
+
sampling_grid_l_,
|
| 735 |
+
mode="bilinear",
|
| 736 |
+
padding_mode="zeros",
|
| 737 |
+
align_corners=False,
|
| 738 |
+
)
|
| 739 |
+
sampling_value_list.append(sampling_value_l_)
|
| 740 |
+
# (batch_size, num_queries, num_heads, num_levels, num_points)
|
| 741 |
+
# -> (batch_size, num_heads, num_queries, num_levels, num_points)
|
| 742 |
+
# -> (batch_size, num_heads, 1, num_queries, num_levels*num_points)
|
| 743 |
+
attention_weights = attention_weights.transpose(1, 2).reshape(
|
| 744 |
+
batch_size * num_heads, 1, num_queries, num_levels * num_points
|
| 745 |
+
)
|
| 746 |
+
output = (
|
| 747 |
+
(torch.stack(sampling_value_list, dim=-2).flatten(-2) * attention_weights)
|
| 748 |
+
.sum(-1)
|
| 749 |
+
.view(batch_size, num_heads * hidden_dim, num_queries)
|
| 750 |
+
)
|
| 751 |
+
return output.transpose(1, 2).contiguous()
|
| 752 |
+
|
| 753 |
+
|
| 754 |
+
class LwDetrMultiscaleDeformableAttention(nn.Module):
|
| 755 |
+
"""
|
| 756 |
+
Multiscale deformable attention as proposed in Deformable DETR.
|
| 757 |
+
"""
|
| 758 |
+
|
| 759 |
+
def __init__(self, config: LwDetrConfig, num_heads: int, n_points: int):
|
| 760 |
+
super().__init__()
|
| 761 |
+
|
| 762 |
+
self.attn = MultiScaleDeformableAttention()
|
| 763 |
+
|
| 764 |
+
if config.d_model % num_heads != 0:
|
| 765 |
+
raise ValueError(
|
| 766 |
+
f"embed_dim (d_model) must be divisible by num_heads, but got {config.d_model} and {num_heads}"
|
| 767 |
+
)
|
| 768 |
+
dim_per_head = config.d_model // num_heads
|
| 769 |
+
# check if dim_per_head is power of 2
|
| 770 |
+
if not ((dim_per_head & (dim_per_head - 1) == 0) and dim_per_head != 0):
|
| 771 |
+
warnings.warn(
|
| 772 |
+
"You'd better set embed_dim (d_model) in LwDetrMultiscaleDeformableAttention to make the"
|
| 773 |
+
" dimension of each attention head a power of 2 which is more efficient in the authors' CUDA"
|
| 774 |
+
" implementation."
|
| 775 |
+
)
|
| 776 |
+
|
| 777 |
+
self.im2col_step = 64
|
| 778 |
+
|
| 779 |
+
self.d_model = config.d_model
|
| 780 |
+
self.n_levels = config.num_feature_levels
|
| 781 |
+
self.n_heads = num_heads
|
| 782 |
+
self.n_points = n_points
|
| 783 |
+
|
| 784 |
+
self.sampling_offsets = nn.Linear(config.d_model, num_heads * self.n_levels * n_points * 2)
|
| 785 |
+
self.attention_weights = nn.Linear(config.d_model, num_heads * self.n_levels * n_points)
|
| 786 |
+
self.value_proj = nn.Linear(config.d_model, config.d_model)
|
| 787 |
+
self.output_proj = nn.Linear(config.d_model, config.d_model)
|
| 788 |
+
|
| 789 |
+
self.disable_custom_kernels = config.disable_custom_kernels
|
| 790 |
+
|
| 791 |
+
def forward(
|
| 792 |
+
self,
|
| 793 |
+
hidden_states: torch.Tensor,
|
| 794 |
+
attention_mask: torch.Tensor | None = None,
|
| 795 |
+
encoder_hidden_states=None,
|
| 796 |
+
encoder_attention_mask=None,
|
| 797 |
+
position_embeddings: torch.Tensor | None = None,
|
| 798 |
+
reference_points=None,
|
| 799 |
+
spatial_shapes=None,
|
| 800 |
+
spatial_shapes_list=None,
|
| 801 |
+
level_start_index=None,
|
| 802 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 803 |
+
) -> tuple[torch.Tensor, torch.Tensor]:
|
| 804 |
+
# add position embeddings to the hidden states before projecting to queries and keys
|
| 805 |
+
if position_embeddings is not None:
|
| 806 |
+
hidden_states = hidden_states + position_embeddings
|
| 807 |
+
|
| 808 |
+
batch_size, num_queries, _ = hidden_states.shape
|
| 809 |
+
batch_size, sequence_length, _ = encoder_hidden_states.shape
|
| 810 |
+
total_elements = sum(height * width for height, width in spatial_shapes_list)
|
| 811 |
+
torch_compilable_check(
|
| 812 |
+
total_elements == sequence_length,
|
| 813 |
+
"Make sure to align the spatial shapes with the sequence length of the encoder hidden states",
|
| 814 |
+
)
|
| 815 |
+
|
| 816 |
+
value = self.value_proj(encoder_hidden_states)
|
| 817 |
+
if attention_mask is not None:
|
| 818 |
+
# we invert the attention_mask
|
| 819 |
+
value = value.masked_fill(~attention_mask[..., None], float(0))
|
| 820 |
+
value = value.view(batch_size, sequence_length, self.n_heads, self.d_model // self.n_heads)
|
| 821 |
+
sampling_offsets = self.sampling_offsets(hidden_states).view(
|
| 822 |
+
batch_size, num_queries, self.n_heads, self.n_levels, self.n_points, 2
|
| 823 |
+
)
|
| 824 |
+
attention_weights = self.attention_weights(hidden_states).view(
|
| 825 |
+
batch_size, num_queries, self.n_heads, self.n_levels * self.n_points
|
| 826 |
+
)
|
| 827 |
+
attention_weights = F.softmax(attention_weights, -1).view(
|
| 828 |
+
batch_size, num_queries, self.n_heads, self.n_levels, self.n_points
|
| 829 |
+
)
|
| 830 |
+
# batch_size, num_queries, n_heads, n_levels, n_points, 2
|
| 831 |
+
num_coordinates = reference_points.shape[-1]
|
| 832 |
+
if num_coordinates == 2:
|
| 833 |
+
offset_normalizer = torch.stack([spatial_shapes[..., 1], spatial_shapes[..., 0]], -1)
|
| 834 |
+
sampling_locations = (
|
| 835 |
+
reference_points[:, :, None, :, None, :]
|
| 836 |
+
+ sampling_offsets / offset_normalizer[None, None, None, :, None, :]
|
| 837 |
+
)
|
| 838 |
+
elif num_coordinates == 4:
|
| 839 |
+
sampling_locations = (
|
| 840 |
+
reference_points[:, :, None, :, None, :2]
|
| 841 |
+
+ sampling_offsets / self.n_points * reference_points[:, :, None, :, None, 2:] * 0.5
|
| 842 |
+
)
|
| 843 |
+
else:
|
| 844 |
+
raise ValueError(f"Last dim of reference_points must be 2 or 4, but got {reference_points.shape[-1]}")
|
| 845 |
+
|
| 846 |
+
output = self.attn(
|
| 847 |
+
value,
|
| 848 |
+
spatial_shapes,
|
| 849 |
+
spatial_shapes_list,
|
| 850 |
+
level_start_index,
|
| 851 |
+
sampling_locations,
|
| 852 |
+
attention_weights,
|
| 853 |
+
self.im2col_step,
|
| 854 |
+
)
|
| 855 |
+
|
| 856 |
+
output = self.output_proj(output)
|
| 857 |
+
|
| 858 |
+
return output, attention_weights
|
| 859 |
+
|
| 860 |
+
|
| 861 |
+
class LwDetrMLP(nn.Module):
|
| 862 |
+
def __init__(self, config: LwDetrConfig):
|
| 863 |
+
super().__init__()
|
| 864 |
+
self.dropout = config.dropout
|
| 865 |
+
self.activation_fn = ACT2FN[config.decoder_activation_function]
|
| 866 |
+
self.fc1 = nn.Linear(config.d_model, config.decoder_ffn_dim)
|
| 867 |
+
self.fc2 = nn.Linear(config.decoder_ffn_dim, config.d_model)
|
| 868 |
+
|
| 869 |
+
def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
|
| 870 |
+
residual = hidden_states
|
| 871 |
+
hidden_states = self.fc1(hidden_states)
|
| 872 |
+
hidden_states = self.activation_fn(hidden_states)
|
| 873 |
+
hidden_states = nn.functional.dropout(hidden_states, p=self.dropout, training=self.training)
|
| 874 |
+
hidden_states = self.fc2(hidden_states)
|
| 875 |
+
hidden_states = nn.functional.dropout(hidden_states, p=self.dropout, training=self.training)
|
| 876 |
+
hidden_states = residual + hidden_states
|
| 877 |
+
return hidden_states
|
| 878 |
+
|
| 879 |
+
|
| 880 |
+
class LwDetrDecoderLayer(GradientCheckpointingLayer):
|
| 881 |
+
def __init__(self, config: LwDetrConfig, layer_idx: int):
|
| 882 |
+
nn.Module.__init__(self)
|
| 883 |
+
|
| 884 |
+
# self-attention
|
| 885 |
+
self.self_attn = LwDetrAttention(config, layer_idx=layer_idx)
|
| 886 |
+
self.dropout = config.dropout
|
| 887 |
+
self.activation_fn = ACT2FN[config.decoder_activation_function]
|
| 888 |
+
self.activation_dropout = config.activation_dropout
|
| 889 |
+
self.self_attn_layer_norm = nn.LayerNorm(config.d_model)
|
| 890 |
+
|
| 891 |
+
# cross-attention
|
| 892 |
+
self.cross_attn = LwDetrMultiscaleDeformableAttention(
|
| 893 |
+
config,
|
| 894 |
+
num_heads=config.decoder_cross_attention_heads,
|
| 895 |
+
n_points=config.decoder_n_points,
|
| 896 |
+
)
|
| 897 |
+
self.cross_attn_layer_norm = nn.LayerNorm(config.d_model)
|
| 898 |
+
|
| 899 |
+
# mlp
|
| 900 |
+
self.mlp = LwDetrMLP(config)
|
| 901 |
+
self.layer_norm = nn.LayerNorm(config.d_model)
|
| 902 |
+
|
| 903 |
+
def forward(
|
| 904 |
+
self,
|
| 905 |
+
hidden_states: torch.Tensor,
|
| 906 |
+
position_embeddings: torch.Tensor | None = None,
|
| 907 |
+
reference_points=None,
|
| 908 |
+
spatial_shapes=None,
|
| 909 |
+
spatial_shapes_list=None,
|
| 910 |
+
level_start_index=None,
|
| 911 |
+
encoder_hidden_states: torch.Tensor | None = None,
|
| 912 |
+
encoder_attention_mask: torch.Tensor | None = None,
|
| 913 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 914 |
+
):
|
| 915 |
+
self_attention_output, self_attn_weights = self.self_attn(
|
| 916 |
+
hidden_states, position_embeddings=position_embeddings, **kwargs
|
| 917 |
+
)
|
| 918 |
+
|
| 919 |
+
self_attention_output = nn.functional.dropout(self_attention_output, p=self.dropout, training=self.training)
|
| 920 |
+
hidden_states = hidden_states + self_attention_output
|
| 921 |
+
hidden_states = self.self_attn_layer_norm(hidden_states)
|
| 922 |
+
|
| 923 |
+
cross_attention_output, cross_attn_weights = self.cross_attn(
|
| 924 |
+
hidden_states=hidden_states,
|
| 925 |
+
attention_mask=encoder_attention_mask,
|
| 926 |
+
encoder_hidden_states=encoder_hidden_states,
|
| 927 |
+
encoder_attention_mask=encoder_attention_mask,
|
| 928 |
+
position_embeddings=position_embeddings,
|
| 929 |
+
reference_points=reference_points,
|
| 930 |
+
spatial_shapes=spatial_shapes,
|
| 931 |
+
spatial_shapes_list=spatial_shapes_list,
|
| 932 |
+
level_start_index=level_start_index,
|
| 933 |
+
**kwargs,
|
| 934 |
+
)
|
| 935 |
+
cross_attention_output = nn.functional.dropout(cross_attention_output, p=self.dropout, training=self.training)
|
| 936 |
+
hidden_states = hidden_states + cross_attention_output
|
| 937 |
+
hidden_states = self.cross_attn_layer_norm(hidden_states)
|
| 938 |
+
|
| 939 |
+
hidden_states = self.mlp(hidden_states)
|
| 940 |
+
hidden_states = self.layer_norm(hidden_states)
|
| 941 |
+
|
| 942 |
+
return hidden_states
|
| 943 |
+
|
| 944 |
+
|
| 945 |
+
@auto_docstring
|
| 946 |
+
class LwDetrPreTrainedModel(PreTrainedModel):
|
| 947 |
+
config: LwDetrConfig
|
| 948 |
+
base_model_prefix = "model"
|
| 949 |
+
main_input_name = "pixel_values"
|
| 950 |
+
input_modalities = ("image",)
|
| 951 |
+
_no_split_modules = [
|
| 952 |
+
r"LwDetrConvEncoder",
|
| 953 |
+
r"LwDetrDecoderLayer",
|
| 954 |
+
]
|
| 955 |
+
_supports_sdpa = True
|
| 956 |
+
_supports_flash_attn = True
|
| 957 |
+
_supports_flex_attn = True
|
| 958 |
+
_supports_attention_backend = True
|
| 959 |
+
_can_record_outputs = {
|
| 960 |
+
"attentions": [LwDetrAttention, LwDetrMultiscaleDeformableAttention],
|
| 961 |
+
"hidden_states": [LwDetrDecoderLayer],
|
| 962 |
+
}
|
| 963 |
+
|
| 964 |
+
@torch.no_grad()
|
| 965 |
+
def _init_weights(self, module):
|
| 966 |
+
super()._init_weights(module)
|
| 967 |
+
|
| 968 |
+
if isinstance(module, LwDetrMultiscaleDeformableAttention):
|
| 969 |
+
init.constant_(module.sampling_offsets.weight, 0.0)
|
| 970 |
+
thetas = torch.arange(module.n_heads, dtype=torch.int64).float() * (2.0 * math.pi / module.n_heads)
|
| 971 |
+
grid_init = torch.stack([thetas.cos(), thetas.sin()], -1)
|
| 972 |
+
grid_init = (
|
| 973 |
+
(grid_init / grid_init.abs().max(-1, keepdim=True)[0])
|
| 974 |
+
.view(module.n_heads, 1, 1, 2)
|
| 975 |
+
.repeat(1, module.n_levels, module.n_points, 1)
|
| 976 |
+
)
|
| 977 |
+
for i in range(module.n_points):
|
| 978 |
+
grid_init[:, :, i, :] *= i + 1
|
| 979 |
+
|
| 980 |
+
init.copy_(module.sampling_offsets.bias, grid_init.view(-1))
|
| 981 |
+
init.constant_(module.attention_weights.weight, 0.0)
|
| 982 |
+
init.constant_(module.attention_weights.bias, 0.0)
|
| 983 |
+
init.xavier_uniform_(module.value_proj.weight)
|
| 984 |
+
init.constant_(module.value_proj.bias, 0.0)
|
| 985 |
+
init.xavier_uniform_(module.output_proj.weight)
|
| 986 |
+
init.constant_(module.output_proj.bias, 0.0)
|
| 987 |
+
if hasattr(module, "level_embed"):
|
| 988 |
+
init.normal_(module.level_embed)
|
| 989 |
+
if hasattr(module, "refpoint_embed") and module.refpoint_embed is not None:
|
| 990 |
+
init.constant_(module.refpoint_embed.weight, 0)
|
| 991 |
+
if hasattr(module, "class_embed") and module.class_embed is not None:
|
| 992 |
+
prior_prob = 0.01
|
| 993 |
+
bias_value = -math.log((1 - prior_prob) / prior_prob)
|
| 994 |
+
init.constant_(module.class_embed.bias, bias_value)
|
| 995 |
+
if hasattr(module, "bbox_embed") and module.bbox_embed is not None:
|
| 996 |
+
init.constant_(module.bbox_embed.layers[-1].weight, 0)
|
| 997 |
+
init.constant_(module.bbox_embed.layers[-1].bias, 0)
|
| 998 |
+
|
| 999 |
+
|
| 1000 |
+
@auto_docstring(
|
| 1001 |
+
custom_intro="""
|
| 1002 |
+
Base class for outputs of the LwDetrDecoder. This class adds two attributes to
|
| 1003 |
+
BaseModelOutputWithCrossAttentions, namely:
|
| 1004 |
+
- a stacked tensor of intermediate decoder hidden states (i.e. the output of each decoder layer)
|
| 1005 |
+
- a stacked tensor of intermediate reference points.
|
| 1006 |
+
"""
|
| 1007 |
+
)
|
| 1008 |
+
@dataclass
|
| 1009 |
+
class LwDetrDecoderOutput(BaseModelOutputWithCrossAttentions):
|
| 1010 |
+
r"""
|
| 1011 |
+
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`):
|
| 1012 |
+
Tuple of `torch.FloatTensor` (one for each layer) of shape `(batch_size, num_heads, sequence_length,
|
| 1013 |
+
sequence_length)`. Attentions weights of the decoder's cross-attention layer, after the attention softmax,
|
| 1014 |
+
used to compute the weighted average in the cross-attention heads.
|
| 1015 |
+
intermediate_hidden_states (`torch.FloatTensor` of shape `(config.decoder_layers, batch_size, num_queries, hidden_size)`, *optional*, returned when `config.auxiliary_loss=True`):
|
| 1016 |
+
Intermediate decoder activations, i.e. the output of each decoder layer, each of them gone through a
|
| 1017 |
+
layernorm.
|
| 1018 |
+
intermediate_reference_points (`torch.FloatTensor` of shape `(batch_size, config.decoder_layers, sequence_length, hidden_size)`):
|
| 1019 |
+
Stacked intermediate reference points (reference points of each layer of the decoder).
|
| 1020 |
+
"""
|
| 1021 |
+
|
| 1022 |
+
intermediate_hidden_states: torch.FloatTensor | None = None
|
| 1023 |
+
|
| 1024 |
+
intermediate_reference_points: torch.FloatTensor | None = None
|
| 1025 |
+
|
| 1026 |
+
|
| 1027 |
+
def encode_sinusoidal_position_embedding(
|
| 1028 |
+
pos_tensor: torch.Tensor,
|
| 1029 |
+
num_pos_feats: int = 128,
|
| 1030 |
+
temperature: int = 10000,
|
| 1031 |
+
) -> torch.Tensor:
|
| 1032 |
+
"""Sinusoidal position embeddings from normalized anchor coordinates.
|
| 1033 |
+
|
| 1034 |
+
Each coordinate in `pos_tensor` is independently encoded with ``num_pos_feats``
|
| 1035 |
+
interleaved sin/cos components; per-coordinate embeddings are concatenated.
|
| 1036 |
+
Handles 2-D ``(x, y)`` and N-D ``(x, y, w, h)`` inputs. For 2-D+ inputs the
|
| 1037 |
+
x and y embeddings are swapped to follow the DETR ``[pos_y, pos_x, ...]`` convention.
|
| 1038 |
+
|
| 1039 |
+
Args:
|
| 1040 |
+
pos_tensor: Normalized coordinates in ``[0, 1]``, shape ``(..., n_coords)``.
|
| 1041 |
+
num_pos_feats: Embedding dimension per coordinate.
|
| 1042 |
+
temperature: Base for the frequency decay.
|
| 1043 |
+
|
| 1044 |
+
Returns:
|
| 1045 |
+
Tensor of shape ``(..., n_coords * num_pos_feats)``, same dtype as input.
|
| 1046 |
+
"""
|
| 1047 |
+
scale = 2 * math.pi
|
| 1048 |
+
dim_t = torch.arange(num_pos_feats, dtype=torch.float32, device=pos_tensor.device)
|
| 1049 |
+
dim_t = temperature ** (2 * torch.div(dim_t, 2, rounding_mode="floor") / num_pos_feats)
|
| 1050 |
+
|
| 1051 |
+
coords = pos_tensor.unbind(-1) # list of (...,) tensors
|
| 1052 |
+
embeddings = [coord[..., None] * scale / dim_t for coord in coords] # each (..., num_pos_feats)
|
| 1053 |
+
embeddings = [
|
| 1054 |
+
torch.stack((e[..., 0::2].sin(), e[..., 1::2].cos()), dim=-1).flatten(-2) for e in embeddings
|
| 1055 |
+
] # each (..., num_pos_feats)
|
| 1056 |
+
|
| 1057 |
+
if len(embeddings) >= 2:
|
| 1058 |
+
embeddings[0], embeddings[1] = embeddings[1], embeddings[0]
|
| 1059 |
+
|
| 1060 |
+
return torch.cat(embeddings, dim=-1).to(pos_tensor.dtype)
|
| 1061 |
+
|
| 1062 |
+
|
| 1063 |
+
class LwDetrDecoder(LwDetrPreTrainedModel):
|
| 1064 |
+
"""
|
| 1065 |
+
Transformer decoder consisting of *config.decoder_layers* layers. Each layer is a [`DeformableDetrDecoderLayer`].
|
| 1066 |
+
|
| 1067 |
+
The decoder updates the query embeddings through multiple self-attention and deformable cross-attention layers.
|
| 1068 |
+
|
| 1069 |
+
Some tweaks for LwDetr:
|
| 1070 |
+
|
| 1071 |
+
- it uses group detr technique at training for faster convergence.
|
| 1072 |
+
|
| 1073 |
+
Args:
|
| 1074 |
+
config: LwDetrConfig
|
| 1075 |
+
"""
|
| 1076 |
+
|
| 1077 |
+
_can_record_outputs = {
|
| 1078 |
+
"hidden_states": LwDetrDecoderLayer,
|
| 1079 |
+
"attentions": OutputRecorder(LwDetrAttention, layer_name="self_attn", index=1),
|
| 1080 |
+
"cross_attentions": OutputRecorder(LwDetrMultiscaleDeformableAttention, layer_name="cross_attn", index=1),
|
| 1081 |
+
}
|
| 1082 |
+
|
| 1083 |
+
def __init__(self, config: LwDetrConfig):
|
| 1084 |
+
super().__init__(config)
|
| 1085 |
+
self.dropout = config.dropout
|
| 1086 |
+
self.layers = nn.ModuleList([LwDetrDecoderLayer(config, i) for i in range(config.decoder_layers)])
|
| 1087 |
+
self.layernorm = nn.LayerNorm(config.d_model)
|
| 1088 |
+
|
| 1089 |
+
self.gradient_checkpointing = False
|
| 1090 |
+
|
| 1091 |
+
self.ref_point_head = LwDetrMLPPredictionHead(2 * config.d_model, config.d_model, config.d_model, num_layers=2)
|
| 1092 |
+
|
| 1093 |
+
self.post_init()
|
| 1094 |
+
|
| 1095 |
+
def get_reference(self, reference_points, valid_ratios):
|
| 1096 |
+
# batch_size, num_queries, batch_size, 4
|
| 1097 |
+
obj_center = reference_points[..., :4]
|
| 1098 |
+
|
| 1099 |
+
# batch_size, num_queries, num_levels, 4
|
| 1100 |
+
reference_points_inputs = obj_center[:, :, None] * torch.cat([valid_ratios, valid_ratios], -1)[:, None]
|
| 1101 |
+
|
| 1102 |
+
# batch_size, num_queries, d_model * 2
|
| 1103 |
+
query_sine_embed = encode_sinusoidal_position_embedding(
|
| 1104 |
+
reference_points_inputs[:, :, 0, :], num_pos_feats=self.config.d_model // 2
|
| 1105 |
+
)
|
| 1106 |
+
|
| 1107 |
+
# batch_size, num_queries, d_model
|
| 1108 |
+
query_pos = self.ref_point_head(query_sine_embed)
|
| 1109 |
+
return reference_points_inputs, query_pos
|
| 1110 |
+
|
| 1111 |
+
@merge_with_config_defaults
|
| 1112 |
+
@capture_outputs
|
| 1113 |
+
def forward(
|
| 1114 |
+
self,
|
| 1115 |
+
inputs_embeds: torch.Tensor | None = None,
|
| 1116 |
+
reference_points: torch.Tensor | None = None,
|
| 1117 |
+
spatial_shapes: torch.Tensor | None = None,
|
| 1118 |
+
spatial_shapes_list: torch.Tensor | None = None,
|
| 1119 |
+
level_start_index: torch.Tensor | None = None,
|
| 1120 |
+
valid_ratios: torch.Tensor | None = None,
|
| 1121 |
+
encoder_hidden_states: torch.Tensor | None = None,
|
| 1122 |
+
encoder_attention_mask: torch.Tensor | None = None,
|
| 1123 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 1124 |
+
):
|
| 1125 |
+
intermediate = ()
|
| 1126 |
+
intermediate_reference_points = (reference_points,)
|
| 1127 |
+
|
| 1128 |
+
if inputs_embeds is not None:
|
| 1129 |
+
hidden_states = inputs_embeds
|
| 1130 |
+
|
| 1131 |
+
reference_points_inputs, query_pos = self.get_reference(reference_points, valid_ratios)
|
| 1132 |
+
|
| 1133 |
+
for idx, decoder_layer in enumerate(self.layers):
|
| 1134 |
+
hidden_states = decoder_layer(
|
| 1135 |
+
hidden_states,
|
| 1136 |
+
encoder_hidden_states=encoder_hidden_states,
|
| 1137 |
+
encoder_attention_mask=encoder_attention_mask,
|
| 1138 |
+
position_embeddings=query_pos,
|
| 1139 |
+
reference_points=reference_points_inputs,
|
| 1140 |
+
spatial_shapes=spatial_shapes,
|
| 1141 |
+
spatial_shapes_list=spatial_shapes_list,
|
| 1142 |
+
level_start_index=level_start_index,
|
| 1143 |
+
**kwargs,
|
| 1144 |
+
)
|
| 1145 |
+
intermediate_hidden_states = self.layernorm(hidden_states)
|
| 1146 |
+
intermediate += (intermediate_hidden_states,)
|
| 1147 |
+
|
| 1148 |
+
intermediate = torch.stack(intermediate)
|
| 1149 |
+
last_hidden_state = intermediate[-1]
|
| 1150 |
+
intermediate_reference_points = torch.stack(intermediate_reference_points)
|
| 1151 |
+
|
| 1152 |
+
return LwDetrDecoderOutput(
|
| 1153 |
+
last_hidden_state=last_hidden_state,
|
| 1154 |
+
intermediate_hidden_states=intermediate,
|
| 1155 |
+
intermediate_reference_points=intermediate_reference_points,
|
| 1156 |
+
)
|
| 1157 |
+
|
| 1158 |
+
|
| 1159 |
+
@auto_docstring(
|
| 1160 |
+
custom_intro="""
|
| 1161 |
+
Base class for outputs of the LwDetr backbone-decoder model.
|
| 1162 |
+
"""
|
| 1163 |
+
)
|
| 1164 |
+
@dataclass
|
| 1165 |
+
class LwDetrModelOutput(ModelOutput):
|
| 1166 |
+
r"""
|
| 1167 |
+
init_reference_points (`torch.FloatTensor` of shape `(batch_size, num_queries, 4)`):
|
| 1168 |
+
Initial reference points sent through the Transformer decoder.
|
| 1169 |
+
intermediate_hidden_states (`torch.FloatTensor` of shape `(batch_size, config.decoder_layers, num_queries, hidden_size)`):
|
| 1170 |
+
Stacked intermediate hidden states (output of each layer of the decoder).
|
| 1171 |
+
intermediate_reference_points (`torch.FloatTensor` of shape `(batch_size, config.decoder_layers, num_queries, 4)`):
|
| 1172 |
+
Stacked intermediate reference points (reference points of each layer of the decoder).
|
| 1173 |
+
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`):
|
| 1174 |
+
Predicted bounding boxes scores where the top `config.two_stage_num_proposals` scoring bounding boxes are
|
| 1175 |
+
picked as region proposals in the first stage. Output of bounding box binary classification (i.e.
|
| 1176 |
+
foreground and background).
|
| 1177 |
+
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`):
|
| 1178 |
+
Logits of predicted bounding boxes coordinates in the first stage.
|
| 1179 |
+
"""
|
| 1180 |
+
|
| 1181 |
+
init_reference_points: torch.FloatTensor | None = None
|
| 1182 |
+
last_hidden_state: torch.FloatTensor | None = None
|
| 1183 |
+
intermediate_hidden_states: torch.FloatTensor | None = None
|
| 1184 |
+
intermediate_reference_points: torch.FloatTensor | None = None
|
| 1185 |
+
enc_outputs_class: torch.FloatTensor | None = None
|
| 1186 |
+
enc_outputs_coord_logits: torch.FloatTensor | None = None
|
| 1187 |
+
hidden_states: tuple[torch.FloatTensor, ...] | None = None
|
| 1188 |
+
attentions: tuple[torch.FloatTensor, ...] | None = None
|
| 1189 |
+
cross_attentions: tuple[torch.FloatTensor, ...] | None = None
|
| 1190 |
+
|
| 1191 |
+
|
| 1192 |
+
def refine_bboxes(reference_points, deltas):
|
| 1193 |
+
reference_points = reference_points.to(deltas.device)
|
| 1194 |
+
new_reference_points_cxcy = deltas[..., :2] * reference_points[..., 2:] + reference_points[..., :2]
|
| 1195 |
+
new_reference_points_wh = deltas[..., 2:].exp() * reference_points[..., 2:]
|
| 1196 |
+
new_reference_points = torch.cat((new_reference_points_cxcy, new_reference_points_wh), -1)
|
| 1197 |
+
return new_reference_points
|
| 1198 |
+
|
| 1199 |
+
|
| 1200 |
+
@auto_docstring(
|
| 1201 |
+
custom_intro="""
|
| 1202 |
+
The bare LW Detr Model (consisting of a backbone and decoder Transformer) outputting raw
|
| 1203 |
+
hidden-states without any specific head on top.
|
| 1204 |
+
"""
|
| 1205 |
+
)
|
| 1206 |
+
class LwDetrModel(LwDetrPreTrainedModel):
|
| 1207 |
+
def __init__(self, config: LwDetrConfig):
|
| 1208 |
+
super().__init__(config)
|
| 1209 |
+
|
| 1210 |
+
# Create backbone + positional encoding
|
| 1211 |
+
self.backbone = LwDetrConvEncoder(config)
|
| 1212 |
+
|
| 1213 |
+
self.group_detr = config.group_detr
|
| 1214 |
+
self.num_queries = config.num_queries
|
| 1215 |
+
hidden_dim = config.d_model
|
| 1216 |
+
self.reference_point_embed = nn.Embedding(self.num_queries * self.group_detr, 4)
|
| 1217 |
+
self.query_feat = nn.Embedding(self.num_queries * self.group_detr, hidden_dim)
|
| 1218 |
+
|
| 1219 |
+
self.decoder = LwDetrDecoder(config)
|
| 1220 |
+
|
| 1221 |
+
self.enc_output = nn.ModuleList([nn.Linear(hidden_dim, hidden_dim) for _ in range(self.group_detr)])
|
| 1222 |
+
self.enc_output_norm = nn.ModuleList([nn.LayerNorm(hidden_dim) for _ in range(self.group_detr)])
|
| 1223 |
+
# Should normally be None and then instantiated in the ForObjectDetection class
|
| 1224 |
+
self.enc_out_bbox_embed = nn.ModuleList(
|
| 1225 |
+
[LwDetrMLPPredictionHead(config.d_model, config.d_model, 4, num_layers=3) for _ in range(self.group_detr)]
|
| 1226 |
+
)
|
| 1227 |
+
self.enc_out_class_embed = nn.ModuleList(
|
| 1228 |
+
[nn.Linear(config.d_model, config.num_labels) for _ in range(self.group_detr)]
|
| 1229 |
+
)
|
| 1230 |
+
|
| 1231 |
+
self.post_init()
|
| 1232 |
+
|
| 1233 |
+
def freeze_backbone(self):
|
| 1234 |
+
for name, param in self.backbone.model.named_parameters():
|
| 1235 |
+
param.requires_grad_(False)
|
| 1236 |
+
|
| 1237 |
+
def unfreeze_backbone(self):
|
| 1238 |
+
for name, param in self.backbone.model.named_parameters():
|
| 1239 |
+
param.requires_grad_(True)
|
| 1240 |
+
|
| 1241 |
+
def get_valid_ratio(self, mask, dtype=torch.float32):
|
| 1242 |
+
"""Get the valid ratio of all feature maps."""
|
| 1243 |
+
|
| 1244 |
+
_, height, width = mask.shape
|
| 1245 |
+
valid_height = torch.sum(mask[:, :, 0], 1)
|
| 1246 |
+
valid_width = torch.sum(mask[:, 0, :], 1)
|
| 1247 |
+
valid_ratio_height = valid_height.to(dtype) / height
|
| 1248 |
+
valid_ratio_width = valid_width.to(dtype) / width
|
| 1249 |
+
valid_ratio = torch.stack([valid_ratio_width, valid_ratio_height], -1)
|
| 1250 |
+
return valid_ratio
|
| 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 in [0, 1] space.
|
| 1265 |
+
Invalid positions (padding or out-of-bounds) are filled with 0.
|
| 1266 |
+
- invalid_mask (Tensor[batch_size, sequence_length, 1]): Boolean mask that is True for invalid positions
|
| 1267 |
+
(padded pixels or proposals whose coordinates fall outside (0.01, 0.99)).
|
| 1268 |
+
"""
|
| 1269 |
+
batch_size = enc_output.shape[0]
|
| 1270 |
+
proposals = []
|
| 1271 |
+
_cur = 0
|
| 1272 |
+
for level, (height, width) in enumerate(spatial_shapes):
|
| 1273 |
+
mask_flatten_ = padding_mask[:, _cur : (_cur + height * width)].view(batch_size, height, width, 1)
|
| 1274 |
+
valid_height = torch.sum(~mask_flatten_[:, :, 0, 0], 1)
|
| 1275 |
+
valid_width = torch.sum(~mask_flatten_[:, 0, :, 0], 1)
|
| 1276 |
+
|
| 1277 |
+
grid_y, grid_x = torch.meshgrid(
|
| 1278 |
+
torch.linspace(
|
| 1279 |
+
0,
|
| 1280 |
+
height - 1,
|
| 1281 |
+
height,
|
| 1282 |
+
dtype=enc_output.dtype,
|
| 1283 |
+
device=enc_output.device,
|
| 1284 |
+
),
|
| 1285 |
+
torch.linspace(
|
| 1286 |
+
0,
|
| 1287 |
+
width - 1,
|
| 1288 |
+
width,
|
| 1289 |
+
dtype=enc_output.dtype,
|
| 1290 |
+
device=enc_output.device,
|
| 1291 |
+
),
|
| 1292 |
+
indexing="ij",
|
| 1293 |
+
)
|
| 1294 |
+
grid = torch.cat([grid_x.unsqueeze(-1), grid_y.unsqueeze(-1)], -1)
|
| 1295 |
+
|
| 1296 |
+
scale = torch.cat([valid_width.unsqueeze(-1), valid_height.unsqueeze(-1)], 1).view(batch_size, 1, 1, 2)
|
| 1297 |
+
grid = (grid.unsqueeze(0).expand(batch_size, -1, -1, -1) + 0.5) / scale
|
| 1298 |
+
width_height = torch.ones_like(grid) * 0.05 * (2.0**level)
|
| 1299 |
+
proposal = torch.cat((grid, width_height), -1).view(batch_size, -1, 4)
|
| 1300 |
+
proposals.append(proposal)
|
| 1301 |
+
_cur += height * width
|
| 1302 |
+
output_proposals = torch.cat(proposals, 1)
|
| 1303 |
+
output_proposals_valid = ((output_proposals > 0.01) & (output_proposals < 0.99)).all(-1, keepdim=True)
|
| 1304 |
+
invalid_mask = padding_mask.unsqueeze(-1) | ~output_proposals_valid
|
| 1305 |
+
output_proposals = output_proposals.masked_fill(invalid_mask, float(0))
|
| 1306 |
+
|
| 1307 |
+
# assign each pixel as an object query
|
| 1308 |
+
object_query = enc_output
|
| 1309 |
+
object_query = object_query.masked_fill(invalid_mask, float(0))
|
| 1310 |
+
return object_query, output_proposals, invalid_mask
|
| 1311 |
+
|
| 1312 |
+
@can_return_tuple
|
| 1313 |
+
@auto_docstring
|
| 1314 |
+
def forward(
|
| 1315 |
+
self,
|
| 1316 |
+
pixel_values: torch.FloatTensor = None,
|
| 1317 |
+
pixel_mask: torch.LongTensor | None = None,
|
| 1318 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 1319 |
+
) -> LwDetrModelOutput:
|
| 1320 |
+
r"""
|
| 1321 |
+
Examples:
|
| 1322 |
+
|
| 1323 |
+
```python
|
| 1324 |
+
>>> from transformers import AutoImageProcessor, DeformableDetrModel
|
| 1325 |
+
>>> from PIL import Image
|
| 1326 |
+
>>> import httpx
|
| 1327 |
+
>>> from io import BytesIO
|
| 1328 |
+
|
| 1329 |
+
>>> url = "http://images.cocodataset.org/val2017/000000039769.jpg"
|
| 1330 |
+
>>> with httpx.stream("GET", url) as response:
|
| 1331 |
+
... image = Image.open(BytesIO(response.read()))
|
| 1332 |
+
|
| 1333 |
+
>>> image_processor = AutoImageProcessor.from_pretrained("AnnaZhang/lwdetr_small_60e_coco")
|
| 1334 |
+
>>> model = DeformableDetrModel.from_pretrained("AnnaZhang/lwdetr_small_60e_coco")
|
| 1335 |
+
|
| 1336 |
+
>>> inputs = image_processor(images=image, return_tensors="pt")
|
| 1337 |
+
|
| 1338 |
+
>>> outputs = model(**inputs)
|
| 1339 |
+
|
| 1340 |
+
>>> last_hidden_states = outputs.last_hidden_state
|
| 1341 |
+
>>> list(last_hidden_states.shape)
|
| 1342 |
+
[1, 300, 256]
|
| 1343 |
+
```"""
|
| 1344 |
+
batch_size, num_channels, height, width = pixel_values.shape
|
| 1345 |
+
device = pixel_values.device
|
| 1346 |
+
|
| 1347 |
+
if pixel_mask is None:
|
| 1348 |
+
pixel_mask = torch.ones(((batch_size, height, width)), dtype=torch.long, device=device)
|
| 1349 |
+
|
| 1350 |
+
# Extract multi-scale feature maps of same resolution `config.d_model` (cf Figure 4 in paper)
|
| 1351 |
+
# First, sent pixel_values + pixel_mask through Backbone to obtain the features
|
| 1352 |
+
# which is a list of tuples
|
| 1353 |
+
features = self.backbone(pixel_values, pixel_mask)
|
| 1354 |
+
|
| 1355 |
+
# Then, apply 1x1 convolution to reduce the channel dimension to d_model (256 by default)
|
| 1356 |
+
sources = []
|
| 1357 |
+
masks = []
|
| 1358 |
+
for level, (source, mask) in enumerate(features):
|
| 1359 |
+
sources.append(source)
|
| 1360 |
+
masks.append(mask)
|
| 1361 |
+
if mask is None:
|
| 1362 |
+
raise ValueError("No attention mask was provided")
|
| 1363 |
+
|
| 1364 |
+
if self.training:
|
| 1365 |
+
reference_points = self.reference_point_embed.weight
|
| 1366 |
+
query_feat = self.query_feat.weight
|
| 1367 |
+
else:
|
| 1368 |
+
# only use one group in inference
|
| 1369 |
+
reference_points = self.reference_point_embed.weight[: self.num_queries]
|
| 1370 |
+
query_feat = self.query_feat.weight[: self.num_queries]
|
| 1371 |
+
|
| 1372 |
+
# Prepare encoder inputs (by flattening)
|
| 1373 |
+
source_flatten = []
|
| 1374 |
+
mask_flatten = []
|
| 1375 |
+
spatial_shapes_list = []
|
| 1376 |
+
for source, mask in zip(sources, masks):
|
| 1377 |
+
batch_size, num_channels, height, width = source.shape
|
| 1378 |
+
spatial_shape = (height, width)
|
| 1379 |
+
spatial_shapes_list.append(spatial_shape)
|
| 1380 |
+
source = source.flatten(2).transpose(1, 2)
|
| 1381 |
+
mask = mask.flatten(1)
|
| 1382 |
+
source_flatten.append(source)
|
| 1383 |
+
mask_flatten.append(mask)
|
| 1384 |
+
source_flatten = torch.cat(source_flatten, 1)
|
| 1385 |
+
mask_flatten = torch.cat(mask_flatten, 1)
|
| 1386 |
+
spatial_shapes = torch.as_tensor(spatial_shapes_list, dtype=torch.long, device=source_flatten.device)
|
| 1387 |
+
level_start_index = torch.cat((spatial_shapes.new_zeros((1,)), spatial_shapes.prod(1).cumsum(0)[:-1]))
|
| 1388 |
+
valid_ratios = torch.stack([self.get_valid_ratio(m, dtype=source_flatten.dtype) for m in masks], 1)
|
| 1389 |
+
|
| 1390 |
+
target = query_feat.unsqueeze(0).expand(batch_size, -1, -1)
|
| 1391 |
+
reference_points = reference_points.unsqueeze(0).expand(batch_size, -1, -1)
|
| 1392 |
+
|
| 1393 |
+
object_query_embedding, output_proposals, invalid_mask = self.gen_encoder_output_proposals(
|
| 1394 |
+
source_flatten, ~mask_flatten, spatial_shapes_list
|
| 1395 |
+
)
|
| 1396 |
+
|
| 1397 |
+
group_detr = self.group_detr if self.training else 1
|
| 1398 |
+
topk = self.num_queries
|
| 1399 |
+
topk_coords_logits = []
|
| 1400 |
+
topk_coords_logits_undetach = []
|
| 1401 |
+
object_query_undetach = []
|
| 1402 |
+
|
| 1403 |
+
for group_id in range(group_detr):
|
| 1404 |
+
group_object_query = self.enc_output[group_id](object_query_embedding)
|
| 1405 |
+
group_object_query = self.enc_output_norm[group_id](group_object_query)
|
| 1406 |
+
|
| 1407 |
+
group_enc_outputs_class = self.enc_out_class_embed[group_id](group_object_query)
|
| 1408 |
+
group_enc_outputs_class = group_enc_outputs_class.masked_fill(invalid_mask, float("-inf"))
|
| 1409 |
+
group_delta_bbox = self.enc_out_bbox_embed[group_id](group_object_query)
|
| 1410 |
+
group_enc_outputs_coord = refine_bboxes(output_proposals, group_delta_bbox)
|
| 1411 |
+
|
| 1412 |
+
group_topk_proposals = torch.topk(group_enc_outputs_class.max(-1)[0], topk, dim=1)[1]
|
| 1413 |
+
group_topk_coords_logits_undetach = torch.gather(
|
| 1414 |
+
group_enc_outputs_coord,
|
| 1415 |
+
1,
|
| 1416 |
+
group_topk_proposals.unsqueeze(-1).repeat(1, 1, 4),
|
| 1417 |
+
)
|
| 1418 |
+
group_topk_coords_logits = group_topk_coords_logits_undetach.detach()
|
| 1419 |
+
group_object_query_undetach = torch.gather(
|
| 1420 |
+
group_object_query, 1, group_topk_proposals.unsqueeze(-1).repeat(1, 1, self.config.d_model)
|
| 1421 |
+
)
|
| 1422 |
+
|
| 1423 |
+
topk_coords_logits.append(group_topk_coords_logits)
|
| 1424 |
+
topk_coords_logits_undetach.append(group_topk_coords_logits_undetach)
|
| 1425 |
+
object_query_undetach.append(group_object_query_undetach)
|
| 1426 |
+
|
| 1427 |
+
topk_coords_logits = torch.cat(topk_coords_logits, 1)
|
| 1428 |
+
topk_coords_logits_undetach = torch.cat(topk_coords_logits_undetach, 1)
|
| 1429 |
+
object_query_undetach = torch.cat(object_query_undetach, 1)
|
| 1430 |
+
|
| 1431 |
+
enc_outputs_class = object_query_undetach
|
| 1432 |
+
enc_outputs_coord_logits = topk_coords_logits_undetach
|
| 1433 |
+
|
| 1434 |
+
reference_points = refine_bboxes(topk_coords_logits, reference_points)
|
| 1435 |
+
|
| 1436 |
+
init_reference_points = reference_points
|
| 1437 |
+
decoder_outputs = self.decoder(
|
| 1438 |
+
inputs_embeds=target,
|
| 1439 |
+
reference_points=reference_points,
|
| 1440 |
+
spatial_shapes=spatial_shapes,
|
| 1441 |
+
spatial_shapes_list=spatial_shapes_list,
|
| 1442 |
+
level_start_index=level_start_index,
|
| 1443 |
+
valid_ratios=valid_ratios,
|
| 1444 |
+
encoder_hidden_states=source_flatten,
|
| 1445 |
+
encoder_attention_mask=mask_flatten,
|
| 1446 |
+
**kwargs,
|
| 1447 |
+
)
|
| 1448 |
+
|
| 1449 |
+
return LwDetrModelOutput(
|
| 1450 |
+
init_reference_points=init_reference_points,
|
| 1451 |
+
last_hidden_state=decoder_outputs.last_hidden_state,
|
| 1452 |
+
intermediate_hidden_states=decoder_outputs.intermediate_hidden_states,
|
| 1453 |
+
intermediate_reference_points=decoder_outputs.intermediate_reference_points,
|
| 1454 |
+
enc_outputs_class=enc_outputs_class,
|
| 1455 |
+
enc_outputs_coord_logits=enc_outputs_coord_logits,
|
| 1456 |
+
hidden_states=decoder_outputs.hidden_states,
|
| 1457 |
+
attentions=decoder_outputs.attentions,
|
| 1458 |
+
cross_attentions=decoder_outputs.cross_attentions,
|
| 1459 |
+
)
|
| 1460 |
+
|
| 1461 |
+
|
| 1462 |
+
class LwDetrMLPPredictionHead(nn.Module):
|
| 1463 |
+
"""
|
| 1464 |
+
Very simple multi-layer perceptron (MLP, also called FFN), used to predict the normalized center coordinates,
|
| 1465 |
+
height and width of a bounding box w.r.t. an image.
|
| 1466 |
+
|
| 1467 |
+
"""
|
| 1468 |
+
|
| 1469 |
+
def __init__(self, input_dim, hidden_dim, output_dim, num_layers):
|
| 1470 |
+
super().__init__()
|
| 1471 |
+
self.num_layers = num_layers
|
| 1472 |
+
h = [hidden_dim] * (num_layers - 1)
|
| 1473 |
+
self.layers = nn.ModuleList(nn.Linear(n, k) for n, k in zip([input_dim] + h, h + [output_dim]))
|
| 1474 |
+
|
| 1475 |
+
def forward(self, x):
|
| 1476 |
+
for i, layer in enumerate(self.layers):
|
| 1477 |
+
x = nn.functional.relu(layer(x)) if i < self.num_layers - 1 else layer(x)
|
| 1478 |
+
return x
|
| 1479 |
+
|
| 1480 |
+
|
| 1481 |
+
@auto_docstring(
|
| 1482 |
+
custom_intro="""
|
| 1483 |
+
Output type of [`LwDetrForObjectDetection`].
|
| 1484 |
+
"""
|
| 1485 |
+
)
|
| 1486 |
+
@dataclass
|
| 1487 |
+
class LwDetrObjectDetectionOutput(ModelOutput):
|
| 1488 |
+
r"""
|
| 1489 |
+
loss (`torch.FloatTensor` of shape `(1,)`, *optional*, returned when `labels` are provided)):
|
| 1490 |
+
Total loss as a linear combination of a negative log-likehood (cross-entropy) for class prediction and a
|
| 1491 |
+
bounding box loss. The latter is defined as a linear combination of the L1 loss and the generalized
|
| 1492 |
+
scale-invariant IoU loss.
|
| 1493 |
+
loss_dict (`Dict`, *optional*):
|
| 1494 |
+
A dictionary containing the individual losses. Useful for logging.
|
| 1495 |
+
logits (`torch.FloatTensor` of shape `(batch_size, num_queries, num_classes + 1)`):
|
| 1496 |
+
Classification logits (including no-object) for all queries.
|
| 1497 |
+
pred_boxes (`torch.FloatTensor` of shape `(batch_size, num_queries, 4)`):
|
| 1498 |
+
Normalized boxes coordinates for all queries, represented as (center_x, center_y, width, height). These
|
| 1499 |
+
values are normalized in [0, 1], relative to the size of each individual image in the batch (disregarding
|
| 1500 |
+
possible padding). You can use [`~DeformableDetrProcessor.post_process_object_detection`] to retrieve the
|
| 1501 |
+
unnormalized bounding boxes.
|
| 1502 |
+
auxiliary_outputs (`list[Dict]`, *optional*):
|
| 1503 |
+
Optional, only returned when auxiliary losses are activated (i.e. `config.auxiliary_loss` is set to `True`)
|
| 1504 |
+
and labels are provided. It is a list of dictionaries containing the two above keys (`logits` and
|
| 1505 |
+
`pred_boxes`) for each decoder layer.
|
| 1506 |
+
init_reference_points (`torch.FloatTensor` of shape `(batch_size, num_queries, 4)`):
|
| 1507 |
+
Initial reference points sent through the Transformer decoder.
|
| 1508 |
+
intermediate_hidden_states (`torch.FloatTensor` of shape `(batch_size, config.decoder_layers, num_queries, hidden_size)`):
|
| 1509 |
+
Stacked intermediate hidden states (output of each layer of the decoder).
|
| 1510 |
+
intermediate_reference_points (`torch.FloatTensor` of shape `(batch_size, config.decoder_layers, num_queries, 4)`):
|
| 1511 |
+
Stacked intermediate reference points (reference points of each layer of the decoder).
|
| 1512 |
+
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`):
|
| 1513 |
+
Predicted bounding boxes scores where the top `config.two_stage_num_proposals` scoring bounding boxes are
|
| 1514 |
+
picked as region proposals in the first stage. Output of bounding box binary classification (i.e.
|
| 1515 |
+
foreground and background).
|
| 1516 |
+
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`):
|
| 1517 |
+
Logits of predicted bounding boxes coordinates in the first stage.
|
| 1518 |
+
"""
|
| 1519 |
+
|
| 1520 |
+
loss: torch.FloatTensor | None = None
|
| 1521 |
+
loss_dict: dict | None = None
|
| 1522 |
+
logits: torch.FloatTensor | None = None
|
| 1523 |
+
pred_boxes: torch.FloatTensor | None = None
|
| 1524 |
+
auxiliary_outputs: list[dict] | None = None
|
| 1525 |
+
init_reference_points: torch.FloatTensor | None = None
|
| 1526 |
+
last_hidden_state: torch.FloatTensor | None = None
|
| 1527 |
+
intermediate_hidden_states: torch.FloatTensor | None = None
|
| 1528 |
+
intermediate_reference_points: torch.FloatTensor | None = None
|
| 1529 |
+
enc_outputs_class: Any = None
|
| 1530 |
+
enc_outputs_coord_logits: torch.FloatTensor | None = None
|
| 1531 |
+
hidden_states: tuple[torch.FloatTensor, ...] | None = None
|
| 1532 |
+
attentions: tuple[torch.FloatTensor, ...] | None = None
|
| 1533 |
+
cross_attentions: tuple[torch.FloatTensor, ...] | None = None
|
| 1534 |
+
|
| 1535 |
+
|
| 1536 |
+
@auto_docstring(
|
| 1537 |
+
custom_intro="""
|
| 1538 |
+
LW DETR Model (consisting of a backbone and decoder Transformer) with object detection heads on
|
| 1539 |
+
top, for tasks such as COCO detection.
|
| 1540 |
+
"""
|
| 1541 |
+
)
|
| 1542 |
+
class LwDetrForObjectDetection(LwDetrPreTrainedModel):
|
| 1543 |
+
# When using clones, all layers > 0 will be clones, but layer 0 *is* required
|
| 1544 |
+
# We can't initialize the model on meta device as some weights are modified during the initialization
|
| 1545 |
+
_no_split_modules = None
|
| 1546 |
+
_tied_weights_keys = None
|
| 1547 |
+
|
| 1548 |
+
def __init__(self, config: LwDetrConfig):
|
| 1549 |
+
super().__init__(config)
|
| 1550 |
+
self.model = LwDetrModel(config)
|
| 1551 |
+
self.class_embed = nn.Linear(config.d_model, config.num_labels)
|
| 1552 |
+
self.bbox_embed = LwDetrMLPPredictionHead(config.d_model, config.d_model, 4, num_layers=3)
|
| 1553 |
+
|
| 1554 |
+
self.post_init()
|
| 1555 |
+
|
| 1556 |
+
@can_return_tuple
|
| 1557 |
+
@auto_docstring
|
| 1558 |
+
def forward(
|
| 1559 |
+
self,
|
| 1560 |
+
pixel_values: torch.FloatTensor = None,
|
| 1561 |
+
pixel_mask: torch.LongTensor | None = None,
|
| 1562 |
+
labels: list[dict] | None = None,
|
| 1563 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 1564 |
+
) -> LwDetrObjectDetectionOutput:
|
| 1565 |
+
r"""
|
| 1566 |
+
labels (`list[Dict]` of len `(batch_size,)`, *optional*):
|
| 1567 |
+
Labels for computing the bipartite matching loss. List of dicts, each dictionary containing at least the
|
| 1568 |
+
following 2 keys: 'class_labels' and 'boxes' (the class labels and bounding boxes of an image in the batch
|
| 1569 |
+
respectively). The class labels themselves should be a `torch.LongTensor` of len `(number of bounding boxes
|
| 1570 |
+
in the image,)` and the boxes a `torch.FloatTensor` of shape `(number of bounding boxes in the image, 4)`.
|
| 1571 |
+
|
| 1572 |
+
Examples:
|
| 1573 |
+
|
| 1574 |
+
```python
|
| 1575 |
+
>>> from transformers import AutoImageProcessor, LwDetrForObjectDetection
|
| 1576 |
+
>>> from PIL import Image
|
| 1577 |
+
>>> import httpx
|
| 1578 |
+
>>> from io import BytesIO
|
| 1579 |
+
|
| 1580 |
+
>>> url = "http://images.cocodataset.org/val2017/000000039769.jpg"
|
| 1581 |
+
>>> with httpx.stream("GET", url) as response:
|
| 1582 |
+
... image = Image.open(BytesIO(response.read()))
|
| 1583 |
+
|
| 1584 |
+
>>> image_processor = AutoImageProcessor.from_pretrained("AnnaZhang/lwdetr_small_60e_coco")
|
| 1585 |
+
>>> model = LwDetrForObjectDetection.from_pretrained("AnnaZhang/lwdetr_small_60e_coco")
|
| 1586 |
+
|
| 1587 |
+
>>> inputs = image_processor(images=image, return_tensors="pt")
|
| 1588 |
+
>>> outputs = model(**inputs)
|
| 1589 |
+
|
| 1590 |
+
>>> # convert outputs (bounding boxes and class logits) to Pascal VOC format (xmin, ymin, xmax, ymax)
|
| 1591 |
+
>>> target_sizes = torch.tensor([image.size[::-1]])
|
| 1592 |
+
>>> results = image_processor.post_process_object_detection(outputs, threshold=0.5, target_sizes=target_sizes)[
|
| 1593 |
+
... 0
|
| 1594 |
+
... ]
|
| 1595 |
+
>>> for score, label, box in zip(results["scores"], results["labels"], results["boxes"]):
|
| 1596 |
+
... box = [round(i, 2) for i in box.tolist()]
|
| 1597 |
+
... print(
|
| 1598 |
+
... f"Detected {model.config.id2label[label.item()]} with confidence "
|
| 1599 |
+
... f"{round(score.item(), 3)} at location {box}"
|
| 1600 |
+
... )
|
| 1601 |
+
Detected cat with confidence 0.8 at location [16.5, 52.84, 318.25, 470.78]
|
| 1602 |
+
Detected cat with confidence 0.789 at location [342.19, 24.3, 640.02, 372.25]
|
| 1603 |
+
Detected remote with confidence 0.633 at location [40.79, 72.78, 176.76, 117.25]
|
| 1604 |
+
```"""
|
| 1605 |
+
outputs = self.model(
|
| 1606 |
+
pixel_values,
|
| 1607 |
+
pixel_mask=pixel_mask,
|
| 1608 |
+
**kwargs,
|
| 1609 |
+
)
|
| 1610 |
+
|
| 1611 |
+
last_hidden_states = outputs.last_hidden_state
|
| 1612 |
+
intermediate_reference_points = outputs.intermediate_reference_points
|
| 1613 |
+
enc_outputs_class_logits = outputs.enc_outputs_class
|
| 1614 |
+
enc_outputs_boxes_logits = outputs.enc_outputs_coord_logits
|
| 1615 |
+
|
| 1616 |
+
logits = self.class_embed(last_hidden_states)
|
| 1617 |
+
pred_boxes_delta = self.bbox_embed(last_hidden_states)
|
| 1618 |
+
pred_boxes = refine_bboxes(intermediate_reference_points[-1], pred_boxes_delta)
|
| 1619 |
+
|
| 1620 |
+
enc_outputs_class_logits_list = enc_outputs_class_logits.split(self.config.num_queries, dim=1)
|
| 1621 |
+
pred_class = []
|
| 1622 |
+
group_detr = self.config.group_detr if self.training else 1
|
| 1623 |
+
for group_index in range(group_detr):
|
| 1624 |
+
group_pred_class = self.model.enc_out_class_embed[group_index](enc_outputs_class_logits_list[group_index])
|
| 1625 |
+
pred_class.append(group_pred_class)
|
| 1626 |
+
enc_outputs_class_logits = torch.cat(pred_class, dim=1)
|
| 1627 |
+
|
| 1628 |
+
loss, loss_dict, auxiliary_outputs = None, None, None
|
| 1629 |
+
if labels is not None:
|
| 1630 |
+
outputs_class, outputs_coord = None, None
|
| 1631 |
+
if self.config.auxiliary_loss:
|
| 1632 |
+
intermediate_hidden_states = outputs.intermediate_hidden_states
|
| 1633 |
+
outputs_coord_delta = self.bbox_embed(intermediate_hidden_states)
|
| 1634 |
+
outputs_coord = refine_bboxes(intermediate_reference_points, outputs_coord_delta)
|
| 1635 |
+
outputs_class = self.class_embed(intermediate_hidden_states)
|
| 1636 |
+
|
| 1637 |
+
loss, loss_dict, auxiliary_outputs = self.loss_function(
|
| 1638 |
+
logits,
|
| 1639 |
+
labels,
|
| 1640 |
+
self.device,
|
| 1641 |
+
pred_boxes,
|
| 1642 |
+
self.config,
|
| 1643 |
+
outputs_class,
|
| 1644 |
+
outputs_coord,
|
| 1645 |
+
enc_outputs_class_logits,
|
| 1646 |
+
enc_outputs_boxes_logits,
|
| 1647 |
+
)
|
| 1648 |
+
|
| 1649 |
+
return LwDetrObjectDetectionOutput(
|
| 1650 |
+
loss=loss,
|
| 1651 |
+
loss_dict=loss_dict,
|
| 1652 |
+
logits=logits,
|
| 1653 |
+
pred_boxes=pred_boxes,
|
| 1654 |
+
auxiliary_outputs=auxiliary_outputs,
|
| 1655 |
+
last_hidden_state=outputs.last_hidden_state,
|
| 1656 |
+
intermediate_hidden_states=outputs.intermediate_hidden_states,
|
| 1657 |
+
intermediate_reference_points=outputs.intermediate_reference_points,
|
| 1658 |
+
init_reference_points=outputs.init_reference_points,
|
| 1659 |
+
enc_outputs_class=enc_outputs_class_logits,
|
| 1660 |
+
enc_outputs_coord_logits=enc_outputs_boxes_logits,
|
| 1661 |
+
hidden_states=outputs.hidden_states,
|
| 1662 |
+
attentions=outputs.attentions,
|
| 1663 |
+
cross_attentions=outputs.cross_attentions,
|
| 1664 |
+
)
|
| 1665 |
+
|
| 1666 |
+
|
| 1667 |
+
__all__ = [
|
| 1668 |
+
"LwDetrPreTrainedModel",
|
| 1669 |
+
"LwDetrModel",
|
| 1670 |
+
"LwDetrForObjectDetection",
|
| 1671 |
+
"LwDetrViTPreTrainedModel",
|
| 1672 |
+
"LwDetrViTBackbone",
|
| 1673 |
+
]
|
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/models/lw_detr/modular_lw_detr.py
ADDED
|
@@ -0,0 +1,1398 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2026 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 math
|
| 15 |
+
from collections.abc import Callable
|
| 16 |
+
from dataclasses import dataclass
|
| 17 |
+
from typing import Any
|
| 18 |
+
|
| 19 |
+
import torch
|
| 20 |
+
from huggingface_hub.dataclasses import strict
|
| 21 |
+
from torch import nn
|
| 22 |
+
|
| 23 |
+
from ... import initialization as init
|
| 24 |
+
from ...activations import ACT2FN
|
| 25 |
+
from ...backbone_utils import consolidate_backbone_kwargs_to_config
|
| 26 |
+
from ...configuration_utils import PreTrainedConfig
|
| 27 |
+
from ...modeling_layers import GradientCheckpointingLayer
|
| 28 |
+
from ...modeling_outputs import BackboneOutput, BaseModelOutput
|
| 29 |
+
from ...modeling_utils import ALL_ATTENTION_FUNCTIONS, PreTrainedModel
|
| 30 |
+
from ...processing_utils import Unpack
|
| 31 |
+
from ...utils import ModelOutput, TransformersKwargs, auto_docstring, logging
|
| 32 |
+
from ...utils.generic import can_return_tuple, merge_with_config_defaults
|
| 33 |
+
from ...utils.output_capturing import OutputRecorder, capture_outputs
|
| 34 |
+
from ..auto import AutoConfig
|
| 35 |
+
from ..conditional_detr.modeling_conditional_detr import encode_sinusoidal_position_embedding
|
| 36 |
+
from ..convnext.modeling_convnext import ConvNextLayerNorm
|
| 37 |
+
from ..deformable_detr.modeling_deformable_detr import (
|
| 38 |
+
DeformableDetrDecoderOutput,
|
| 39 |
+
DeformableDetrForObjectDetection,
|
| 40 |
+
DeformableDetrMLPPredictionHead,
|
| 41 |
+
DeformableDetrModel,
|
| 42 |
+
DeformableDetrMultiscaleDeformableAttention,
|
| 43 |
+
)
|
| 44 |
+
from ..llama.modeling_llama import eager_attention_forward
|
| 45 |
+
from ..rt_detr.modeling_rt_detr import RTDetrConvNormLayer
|
| 46 |
+
from ..vit.modeling_vit import ViTAttention
|
| 47 |
+
from ..vitdet.configuration_vitdet import VitDetConfig
|
| 48 |
+
from ..vitdet.modeling_vitdet import (
|
| 49 |
+
VitDetBackbone,
|
| 50 |
+
VitDetEmbeddings,
|
| 51 |
+
VitDetMlp,
|
| 52 |
+
VitDetPreTrainedModel,
|
| 53 |
+
)
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
logger = logging.get_logger(__name__)
|
| 57 |
+
|
| 58 |
+
|
| 59 |
+
@auto_docstring(checkpoint="AnnaZhang/lwdetr_small_60e_coco")
|
| 60 |
+
@strict
|
| 61 |
+
class LwDetrViTConfig(VitDetConfig):
|
| 62 |
+
r"""
|
| 63 |
+
pretrain_image_size (`int`, *optional*, defaults to 224):
|
| 64 |
+
The size (resolution) of each image during pretraining.
|
| 65 |
+
window_block_indices (`list[int]`, *optional*, defaults to `[]`):
|
| 66 |
+
List of indices of blocks that should have window attention instead of regular global self-attention.
|
| 67 |
+
use_absolute_position_embeddings (`bool`, *optional*, defaults to `True`):
|
| 68 |
+
Whether to add absolute position embeddings to the patch embeddings.
|
| 69 |
+
cae_init_values (`float`, *optional*, defaults to 0.1):
|
| 70 |
+
Initialization value for CAE parameters when `use_cae` is enabled.
|
| 71 |
+
num_windows (`int`, *optional*, defaults to 16):
|
| 72 |
+
Number of windows for window-based attention. Must be a perfect square and the image size must be
|
| 73 |
+
divisible by the square root of this value. This enables efficient window-major feature map organization.
|
| 74 |
+
|
| 75 |
+
Example:
|
| 76 |
+
|
| 77 |
+
```python
|
| 78 |
+
>>> from transformers import LwDetrViTConfig, LwDetrViTModel
|
| 79 |
+
|
| 80 |
+
>>> # Initializing a LW-DETR ViT configuration
|
| 81 |
+
>>> configuration = LwDetrViTConfig()
|
| 82 |
+
|
| 83 |
+
>>> # Initializing a model (with random weights) from the configuration
|
| 84 |
+
>>> model = LwDetrViTModel(configuration)
|
| 85 |
+
|
| 86 |
+
>>> # Accessing the model configuration
|
| 87 |
+
>>> configuration = model.config
|
| 88 |
+
```"""
|
| 89 |
+
|
| 90 |
+
model_type = "lw_detr_vit"
|
| 91 |
+
|
| 92 |
+
image_size: int | list[int] | tuple[int, int] = 256
|
| 93 |
+
cae_init_values: float = 0.1
|
| 94 |
+
num_windows: int = 16
|
| 95 |
+
|
| 96 |
+
residual_block_indices = AttributeError()
|
| 97 |
+
use_relative_position_embeddings = AttributeError()
|
| 98 |
+
window_size = AttributeError()
|
| 99 |
+
drop_path_rate = AttributeError()
|
| 100 |
+
|
| 101 |
+
def __post_init__(self, **kwargs):
|
| 102 |
+
self.num_windows_side = int(math.sqrt(self.num_windows))
|
| 103 |
+
super().__post_init__(**kwargs)
|
| 104 |
+
|
| 105 |
+
def validate_architecture(self):
|
| 106 |
+
"""Part of `@strict`-powered validation. Validates the architecture of the config."""
|
| 107 |
+
if self.num_windows % math.sqrt(self.num_windows) != 0:
|
| 108 |
+
raise ValueError(
|
| 109 |
+
f"`num_windows` has to be a perfect square, where num_windows % math.sqrt(num_windows) != 0, but got {self.num_windows}."
|
| 110 |
+
)
|
| 111 |
+
if self.image_size / self.num_windows % math.sqrt(self.num_windows) != 0:
|
| 112 |
+
raise ValueError(
|
| 113 |
+
f"`image_size` has to be divisible by `num_windows`, where image_size / num_windows % math.sqrt(num_windows) != 0,but got {self.image_size} and {self.num_windows}."
|
| 114 |
+
)
|
| 115 |
+
|
| 116 |
+
|
| 117 |
+
@auto_docstring(checkpoint="AnnaZhang/lwdetr_small_60e_coco")
|
| 118 |
+
@strict
|
| 119 |
+
class LwDetrConfig(PreTrainedConfig):
|
| 120 |
+
r"""
|
| 121 |
+
projector_scale_factors (`list[float]`, *optional*, defaults to `[]`):
|
| 122 |
+
Scale factors for the feature pyramid network. Each scale factor determines the resolution of features
|
| 123 |
+
at different levels. Supported values are 0.5, 1.0, and 2.0.
|
| 124 |
+
hidden_expansion (`float`, *optional*, defaults to 0.5):
|
| 125 |
+
Expansion factor for hidden dimensions in the projector layers.
|
| 126 |
+
c2f_num_blocks (`int`, *optional*, defaults to 3):
|
| 127 |
+
Number of blocks in the C2F layer.
|
| 128 |
+
activation_function (`str`, *optional*, defaults to `"silu"`):
|
| 129 |
+
The non-linear activation function in the projector. Supported values are `"silu"`, `"relu"`, `"gelu"`.
|
| 130 |
+
batch_norm_eps (`float`, *optional*, defaults to 1e-05):
|
| 131 |
+
The epsilon value for batch normalization layers.
|
| 132 |
+
decoder_ffn_dim (`int`, *optional*, defaults to 2048):
|
| 133 |
+
Dimension of the "intermediate" (often named feed-forward) layer in decoder.
|
| 134 |
+
decoder_n_points (`int`, *optional*, defaults to 4):
|
| 135 |
+
The number of sampled keys in each feature level for each attention head in the decoder.
|
| 136 |
+
decoder_self_attention_heads (`int`, *optional*, defaults to 8):
|
| 137 |
+
Number of attention heads for each attention layer in the decoder self-attention.
|
| 138 |
+
decoder_cross_attention_heads (`int`, *optional*, defaults to 16):
|
| 139 |
+
Number of attention heads for each attention layer in the decoder cross-attention.
|
| 140 |
+
decoder_activation_function (`str`, *optional*, defaults to `"relu"`):
|
| 141 |
+
The non-linear activation function in the decoder. Supported values are `"relu"`, `"silu"`, `"gelu"`.
|
| 142 |
+
num_queries (`int`, *optional*, defaults to 300):
|
| 143 |
+
Number of object queries, i.e. detection slots. This is the maximal number of objects
|
| 144 |
+
[`LwDetrModel`] can detect in a single image.
|
| 145 |
+
group_detr (`int`, *optional*, defaults to 13):
|
| 146 |
+
Number of groups for Group DETR attention mechanism, which helps reduce computational complexity.
|
| 147 |
+
disable_custom_kernels (`bool`, *optional*, defaults to `True`):
|
| 148 |
+
Disable the use of custom CUDA and CPU kernels. This option is necessary for the ONNX export, as custom
|
| 149 |
+
kernels are not supported by PyTorch ONNX export.
|
| 150 |
+
class_loss_coefficient (`float`, *optional*, defaults to 1):
|
| 151 |
+
Relative weight of the classification loss in the Hungarian matching cost.
|
| 152 |
+
|
| 153 |
+
Examples:
|
| 154 |
+
|
| 155 |
+
```python
|
| 156 |
+
>>> from transformers import LwDetrConfig, LwDetrModel
|
| 157 |
+
|
| 158 |
+
>>> # Initializing a LW-DETR AnnaZhang/lwdetr_small_60e_coco style configuration
|
| 159 |
+
>>> configuration = LwDetrConfig()
|
| 160 |
+
|
| 161 |
+
>>> # Initializing a model (with random weights) from the AnnaZhang/lwdetr_small_60e_coco style configuration
|
| 162 |
+
>>> model = LwDetrModel(configuration)
|
| 163 |
+
|
| 164 |
+
>>> # Accessing the model configuration
|
| 165 |
+
>>> configuration = model.config
|
| 166 |
+
```"""
|
| 167 |
+
|
| 168 |
+
model_type = "lw_detr"
|
| 169 |
+
sub_configs = {"backbone_config": AutoConfig}
|
| 170 |
+
|
| 171 |
+
backbone_config: dict | PreTrainedConfig | None = None
|
| 172 |
+
projector_scale_factors: list[float] | tuple[float, ...] = ()
|
| 173 |
+
hidden_expansion: float = 0.5
|
| 174 |
+
c2f_num_blocks: int = 3
|
| 175 |
+
activation_function: str = "silu"
|
| 176 |
+
batch_norm_eps: float = 1e-5
|
| 177 |
+
dropout: float | int = 0.0
|
| 178 |
+
decoder_ffn_dim: int = 2048
|
| 179 |
+
decoder_n_points: int = 4
|
| 180 |
+
decoder_layers: int = 3
|
| 181 |
+
decoder_self_attention_heads: int = 8
|
| 182 |
+
decoder_cross_attention_heads: int = 16
|
| 183 |
+
decoder_activation_function: str = "relu"
|
| 184 |
+
num_queries: int = 300
|
| 185 |
+
attention_bias: bool = True
|
| 186 |
+
attention_dropout: float | int = 0.0
|
| 187 |
+
activation_dropout: float | int = 0.0
|
| 188 |
+
group_detr: int = 13
|
| 189 |
+
init_std: float = 0.02
|
| 190 |
+
disable_custom_kernels: bool = True
|
| 191 |
+
class_cost: int | float = 2
|
| 192 |
+
bbox_cost: int | float = 5
|
| 193 |
+
giou_cost: int | float = 2
|
| 194 |
+
class_loss_coefficient: int | float = 1
|
| 195 |
+
dice_loss_coefficient: int | float = 1
|
| 196 |
+
bbox_loss_coefficient: int | float = 5
|
| 197 |
+
giou_loss_coefficient: int | float = 2
|
| 198 |
+
eos_coefficient: float = 0.1
|
| 199 |
+
focal_alpha: float = 0.25
|
| 200 |
+
auxiliary_loss: bool = True
|
| 201 |
+
d_model: int = 256
|
| 202 |
+
|
| 203 |
+
def __post_init__(self, **kwargs):
|
| 204 |
+
if "mask_loss_coefficient" in kwargs:
|
| 205 |
+
logger.warning_once(
|
| 206 |
+
"The parameter `mask_loss_coefficient` was renamed to `class_loss_coefficient` in LW-DETR. "
|
| 207 |
+
"Please use `class_loss_coefficient` instead. `mask_loss_coefficient` will be removed in a future version."
|
| 208 |
+
)
|
| 209 |
+
self.class_loss_coefficient = kwargs.pop("mask_loss_coefficient")
|
| 210 |
+
|
| 211 |
+
self.backbone_config, kwargs = consolidate_backbone_kwargs_to_config(
|
| 212 |
+
backbone_config=self.backbone_config,
|
| 213 |
+
default_config_type="lw_detr_vit",
|
| 214 |
+
default_config_kwargs={
|
| 215 |
+
"image_size": 1024,
|
| 216 |
+
"hidden_size": 192,
|
| 217 |
+
"num_hidden_layers": 10,
|
| 218 |
+
"window_block_indices": [0, 1, 3, 6, 7, 9],
|
| 219 |
+
"out_indices": [2, 4, 5, 9],
|
| 220 |
+
},
|
| 221 |
+
**kwargs,
|
| 222 |
+
)
|
| 223 |
+
|
| 224 |
+
self.projector_in_channels = [self.d_model] * len(self.projector_scale_factors)
|
| 225 |
+
self.projector_out_channels = self.d_model
|
| 226 |
+
self.num_feature_levels = len(self.projector_scale_factors)
|
| 227 |
+
super().__post_init__(**kwargs)
|
| 228 |
+
|
| 229 |
+
def validate_architecture(self):
|
| 230 |
+
"""Part of `@strict`-powered validation. Validates the architecture of the config."""
|
| 231 |
+
for scale in self.projector_scale_factors:
|
| 232 |
+
if scale not in [0.5, 1.0, 2.0]:
|
| 233 |
+
raise ValueError(f"Unsupported scale factor: {scale}")
|
| 234 |
+
|
| 235 |
+
|
| 236 |
+
class LwDetrViTAttention(ViTAttention):
|
| 237 |
+
"""LwDetr ViT attention with k_proj bias=False and dropout from config.dropout_prob."""
|
| 238 |
+
|
| 239 |
+
def __init__(self, config: LwDetrViTConfig):
|
| 240 |
+
super().__init__()
|
| 241 |
+
self.attention_dropout = config.dropout_prob
|
| 242 |
+
self.k_proj = nn.Linear(config.hidden_size, config.num_attention_heads * self.head_dim, bias=False)
|
| 243 |
+
self.num_key_value_groups = 1
|
| 244 |
+
|
| 245 |
+
|
| 246 |
+
class LwDetrViTMlp(VitDetMlp):
|
| 247 |
+
pass
|
| 248 |
+
|
| 249 |
+
|
| 250 |
+
class LwDetrViTLayer(GradientCheckpointingLayer):
|
| 251 |
+
def __init__(
|
| 252 |
+
self,
|
| 253 |
+
config: LwDetrViTConfig,
|
| 254 |
+
layer_idx,
|
| 255 |
+
) -> None:
|
| 256 |
+
super().__init__()
|
| 257 |
+
|
| 258 |
+
dim = config.hidden_size
|
| 259 |
+
self.attention = LwDetrViTAttention(config)
|
| 260 |
+
self.intermediate = LwDetrViTMlp(config=config, in_features=dim, hidden_features=int(dim * config.mlp_ratio))
|
| 261 |
+
self.layernorm_before = nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps)
|
| 262 |
+
self.layernorm_after = nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps)
|
| 263 |
+
|
| 264 |
+
self.gamma_1 = nn.Parameter(torch.Tensor(dim), requires_grad=True)
|
| 265 |
+
self.gamma_2 = nn.Parameter(torch.Tensor(dim), requires_grad=True)
|
| 266 |
+
|
| 267 |
+
self.window = layer_idx in config.window_block_indices
|
| 268 |
+
self.num_windows = config.num_windows
|
| 269 |
+
|
| 270 |
+
def forward(
|
| 271 |
+
self,
|
| 272 |
+
hidden_states: torch.Tensor,
|
| 273 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 274 |
+
) -> torch.Tensor:
|
| 275 |
+
batch_size, seq_len, channels = hidden_states.shape
|
| 276 |
+
hidden_states_norm = self.layernorm_before(hidden_states)
|
| 277 |
+
|
| 278 |
+
if not self.window:
|
| 279 |
+
hidden_states_norm = hidden_states_norm.reshape(
|
| 280 |
+
batch_size // self.num_windows, self.num_windows * seq_len, channels
|
| 281 |
+
)
|
| 282 |
+
|
| 283 |
+
attention_output, _ = self.attention(hidden_states_norm, **kwargs)
|
| 284 |
+
attention_output = attention_output * self.gamma_1
|
| 285 |
+
|
| 286 |
+
if not self.window:
|
| 287 |
+
attention_output = attention_output.reshape(batch_size, seq_len, channels)
|
| 288 |
+
|
| 289 |
+
hidden_states = hidden_states + attention_output
|
| 290 |
+
|
| 291 |
+
layer_output = self.layernorm_after(hidden_states)
|
| 292 |
+
layer_output = self.intermediate(layer_output)
|
| 293 |
+
layer_output = layer_output * self.gamma_2
|
| 294 |
+
|
| 295 |
+
hidden_states = hidden_states + layer_output
|
| 296 |
+
|
| 297 |
+
return hidden_states
|
| 298 |
+
|
| 299 |
+
|
| 300 |
+
class LwDetrViTEmbeddings(VitDetEmbeddings):
|
| 301 |
+
pass
|
| 302 |
+
|
| 303 |
+
|
| 304 |
+
class LwDetrViTPreTrainedModel(VitDetPreTrainedModel):
|
| 305 |
+
config: LwDetrViTConfig
|
| 306 |
+
base_model_prefix = "lw_detr_vit"
|
| 307 |
+
main_input_name = "pixel_values"
|
| 308 |
+
supports_gradient_checkpointing = True
|
| 309 |
+
_no_split_modules = ["LwDetrViTEmbeddings", "LwDetrViTLayer"]
|
| 310 |
+
_supports_sdpa = True
|
| 311 |
+
_supports_flash_attn = True
|
| 312 |
+
_supports_flex_attn = True
|
| 313 |
+
_supports_attention_backend = True
|
| 314 |
+
_can_record_outputs = {
|
| 315 |
+
"hidden_states": LwDetrViTLayer,
|
| 316 |
+
"attentions": LwDetrViTAttention,
|
| 317 |
+
}
|
| 318 |
+
|
| 319 |
+
@torch.no_grad()
|
| 320 |
+
def _init_weights(self, module) -> None:
|
| 321 |
+
if isinstance(module, (nn.Linear, nn.Conv2d)):
|
| 322 |
+
init.trunc_normal_(module.weight, mean=0.0, std=self.config.initializer_range)
|
| 323 |
+
if module.bias is not None:
|
| 324 |
+
init.zeros_(module.bias)
|
| 325 |
+
elif isinstance(module, nn.LayerNorm):
|
| 326 |
+
init.zeros_(module.bias)
|
| 327 |
+
init.ones_(module.weight)
|
| 328 |
+
elif isinstance(module, LwDetrViTEmbeddings):
|
| 329 |
+
init.trunc_normal_(module.position_embeddings, mean=0.0, std=self.config.initializer_range)
|
| 330 |
+
if isinstance(module, LwDetrViTLayer):
|
| 331 |
+
init.constant_(module.gamma_1, self.config.cae_init_values)
|
| 332 |
+
init.constant_(module.gamma_2, self.config.cae_init_values)
|
| 333 |
+
|
| 334 |
+
|
| 335 |
+
class LwDetrViTEncoder(LwDetrViTPreTrainedModel):
|
| 336 |
+
def __init__(self, config: LwDetrViTConfig):
|
| 337 |
+
super().__init__(config)
|
| 338 |
+
self.layer = nn.ModuleList([LwDetrViTLayer(config, idx) for idx in range(config.num_hidden_layers)])
|
| 339 |
+
self.post_init()
|
| 340 |
+
|
| 341 |
+
@merge_with_config_defaults
|
| 342 |
+
@capture_outputs
|
| 343 |
+
def forward(
|
| 344 |
+
self,
|
| 345 |
+
hidden_states: torch.Tensor,
|
| 346 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 347 |
+
) -> BaseModelOutput:
|
| 348 |
+
for layer_module in self.layer:
|
| 349 |
+
hidden_states = layer_module(hidden_states, **kwargs)
|
| 350 |
+
|
| 351 |
+
return BaseModelOutput(last_hidden_state=hidden_states)
|
| 352 |
+
|
| 353 |
+
|
| 354 |
+
@auto_docstring()
|
| 355 |
+
class LwDetrViTBackbone(VitDetBackbone):
|
| 356 |
+
def forward(self, pixel_values: torch.Tensor, **kwargs: Unpack[TransformersKwargs]) -> BackboneOutput:
|
| 357 |
+
r"""
|
| 358 |
+
Examples:
|
| 359 |
+
|
| 360 |
+
```python
|
| 361 |
+
>>> from transformers import LwDetrViTConfig, LwDetrViTBackbone
|
| 362 |
+
>>> import torch
|
| 363 |
+
|
| 364 |
+
>>> config = LwDetrViTConfig()
|
| 365 |
+
>>> model = LwDetrViTBackbone(config)
|
| 366 |
+
|
| 367 |
+
>>> pixel_values = torch.randn(1, 3, 224, 224)
|
| 368 |
+
|
| 369 |
+
>>> with torch.no_grad():
|
| 370 |
+
... outputs = model(pixel_values)
|
| 371 |
+
|
| 372 |
+
>>> feature_maps = outputs.feature_maps
|
| 373 |
+
>>> list(feature_maps[-1].shape)
|
| 374 |
+
[1, 768, 14, 14]
|
| 375 |
+
```"""
|
| 376 |
+
embedding_output = self.embeddings(pixel_values)
|
| 377 |
+
|
| 378 |
+
batch_size, channels, height, width = embedding_output.shape
|
| 379 |
+
# (batch_size, channels, height, width) -> (batch_size, height, width, channels)
|
| 380 |
+
hidden_states = embedding_output.permute(0, 2, 3, 1)
|
| 381 |
+
|
| 382 |
+
window_height = height // self.config.num_windows_side
|
| 383 |
+
window_width = width // self.config.num_windows_side
|
| 384 |
+
# (batch_size, height, width, channels) -> (batch_size*num_windows_side**2, window_height*window_width, channels)
|
| 385 |
+
hidden_states = (
|
| 386 |
+
hidden_states.reshape(
|
| 387 |
+
batch_size,
|
| 388 |
+
self.config.num_windows_side,
|
| 389 |
+
window_height,
|
| 390 |
+
self.config.num_windows_side,
|
| 391 |
+
window_width,
|
| 392 |
+
channels,
|
| 393 |
+
)
|
| 394 |
+
.permute(0, 1, 3, 2, 4, 5)
|
| 395 |
+
.reshape(batch_size * self.config.num_windows_side**2, window_height * window_width, channels)
|
| 396 |
+
)
|
| 397 |
+
|
| 398 |
+
kwargs["output_hidden_states"] = True # required to extract layers for the stages
|
| 399 |
+
output = self.encoder(hidden_states, **kwargs)
|
| 400 |
+
|
| 401 |
+
feature_maps = ()
|
| 402 |
+
hidden_states = output.hidden_states
|
| 403 |
+
for stage, hidden_state in zip(self.stage_names, hidden_states):
|
| 404 |
+
if stage in self.out_features:
|
| 405 |
+
hidden_state = (
|
| 406 |
+
hidden_state.reshape(
|
| 407 |
+
batch_size,
|
| 408 |
+
self.config.num_windows_side,
|
| 409 |
+
self.config.num_windows_side,
|
| 410 |
+
window_height,
|
| 411 |
+
window_width,
|
| 412 |
+
channels,
|
| 413 |
+
)
|
| 414 |
+
.permute(0, 5, 1, 3, 2, 4)
|
| 415 |
+
.reshape(batch_size, channels, height, width)
|
| 416 |
+
)
|
| 417 |
+
feature_maps += (hidden_state,)
|
| 418 |
+
|
| 419 |
+
return BackboneOutput(
|
| 420 |
+
feature_maps=feature_maps, hidden_states=output.hidden_states, attentions=output.attentions
|
| 421 |
+
)
|
| 422 |
+
|
| 423 |
+
|
| 424 |
+
class LwDetrConvNormLayer(RTDetrConvNormLayer):
|
| 425 |
+
def __init__(
|
| 426 |
+
self,
|
| 427 |
+
config: LwDetrConfig,
|
| 428 |
+
in_channels: int,
|
| 429 |
+
out_channels: int,
|
| 430 |
+
kernel_size: int,
|
| 431 |
+
stride: int,
|
| 432 |
+
activation: str | None = None,
|
| 433 |
+
):
|
| 434 |
+
super().__init__(config, in_channels, out_channels, kernel_size, stride, activation)
|
| 435 |
+
self.conv = nn.Conv2d(
|
| 436 |
+
in_channels,
|
| 437 |
+
out_channels,
|
| 438 |
+
kernel_size,
|
| 439 |
+
stride,
|
| 440 |
+
padding=kernel_size // 2,
|
| 441 |
+
bias=False,
|
| 442 |
+
)
|
| 443 |
+
|
| 444 |
+
|
| 445 |
+
class LwDetrRepVggBlock(nn.Module):
|
| 446 |
+
def __init__(self, config: LwDetrConfig):
|
| 447 |
+
super().__init__()
|
| 448 |
+
hidden_channels = int(config.d_model * config.hidden_expansion)
|
| 449 |
+
self.conv1 = LwDetrConvNormLayer(
|
| 450 |
+
config, hidden_channels, hidden_channels, 3, 1, activation=config.activation_function
|
| 451 |
+
)
|
| 452 |
+
self.conv2 = LwDetrConvNormLayer(
|
| 453 |
+
config, hidden_channels, hidden_channels, 3, 1, activation=config.activation_function
|
| 454 |
+
)
|
| 455 |
+
|
| 456 |
+
def forward(self, x: torch.Tensor) -> torch.Tensor:
|
| 457 |
+
y = self.conv1(x)
|
| 458 |
+
y = self.conv2(y)
|
| 459 |
+
return y
|
| 460 |
+
|
| 461 |
+
|
| 462 |
+
class LwDetrC2FLayer(nn.Module):
|
| 463 |
+
# Inspired by RTDetrCSPRepLayer
|
| 464 |
+
def __init__(self, config: LwDetrConfig, in_channels: int):
|
| 465 |
+
super().__init__()
|
| 466 |
+
num_blocks = config.c2f_num_blocks
|
| 467 |
+
activation = config.activation_function
|
| 468 |
+
out_channels = config.d_model
|
| 469 |
+
|
| 470 |
+
self.hidden_channels = int(out_channels * config.hidden_expansion)
|
| 471 |
+
|
| 472 |
+
conv1_out_channels = 2 * self.hidden_channels
|
| 473 |
+
self.conv1 = LwDetrConvNormLayer(config, in_channels, conv1_out_channels, 1, 1, activation=activation)
|
| 474 |
+
|
| 475 |
+
conv2_in_channels = (2 + num_blocks) * self.hidden_channels
|
| 476 |
+
self.conv2 = LwDetrConvNormLayer(config, conv2_in_channels, out_channels, 1, 1, activation=activation)
|
| 477 |
+
|
| 478 |
+
self.bottlenecks = nn.ModuleList(LwDetrRepVggBlock(config) for _ in range(num_blocks))
|
| 479 |
+
|
| 480 |
+
def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
|
| 481 |
+
hidden_states = self.conv1(hidden_states)
|
| 482 |
+
all_hidden_states = list(hidden_states.split(self.hidden_channels, 1))
|
| 483 |
+
hidden_states = all_hidden_states[-1]
|
| 484 |
+
hidden_states = hidden_states.contiguous()
|
| 485 |
+
|
| 486 |
+
for bottleneck in self.bottlenecks:
|
| 487 |
+
hidden_states = bottleneck(hidden_states)
|
| 488 |
+
all_hidden_states.append(hidden_states)
|
| 489 |
+
|
| 490 |
+
hidden_states = torch.cat(all_hidden_states, 1)
|
| 491 |
+
hidden_states = self.conv2(hidden_states)
|
| 492 |
+
return hidden_states
|
| 493 |
+
|
| 494 |
+
|
| 495 |
+
class LwDetrLayerNorm(ConvNextLayerNorm):
|
| 496 |
+
pass
|
| 497 |
+
|
| 498 |
+
|
| 499 |
+
class LwDetrSamplingLayer(nn.Module):
|
| 500 |
+
def __init__(self, config: LwDetrConfig, channel_size: int, scale: float):
|
| 501 |
+
super().__init__()
|
| 502 |
+
|
| 503 |
+
self.scale = scale
|
| 504 |
+
self.channel_size = channel_size
|
| 505 |
+
|
| 506 |
+
layers = []
|
| 507 |
+
if scale == 2.0:
|
| 508 |
+
if channel_size > 512:
|
| 509 |
+
layers.append(LwDetrConvNormLayer(config, channel_size, channel_size // 2, 1, 1, activation="relu"))
|
| 510 |
+
layers.append(nn.ConvTranspose2d(channel_size // 2, channel_size // 4, kernel_size=2, stride=2))
|
| 511 |
+
else:
|
| 512 |
+
layers.append(nn.ConvTranspose2d(channel_size, channel_size // 2, 2, 2))
|
| 513 |
+
elif scale == 0.5:
|
| 514 |
+
layers.append(LwDetrConvNormLayer(config, channel_size, channel_size, 3, 2, activation="relu"))
|
| 515 |
+
self.layers = nn.ModuleList(layers)
|
| 516 |
+
|
| 517 |
+
def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
|
| 518 |
+
for layer in self.layers:
|
| 519 |
+
hidden_states = layer(hidden_states)
|
| 520 |
+
return hidden_states
|
| 521 |
+
|
| 522 |
+
|
| 523 |
+
class LwDetrScaleProjector(nn.Module):
|
| 524 |
+
def __init__(self, config: LwDetrConfig, scale: float):
|
| 525 |
+
super().__init__()
|
| 526 |
+
|
| 527 |
+
intermediate_dims = [config.backbone_config.hidden_size] * len(config.backbone_config.out_indices)
|
| 528 |
+
sampling_layers = []
|
| 529 |
+
for channel_size in intermediate_dims:
|
| 530 |
+
sampling_layers.append(LwDetrSamplingLayer(config, channel_size, scale))
|
| 531 |
+
self.sampling_layers = nn.ModuleList(sampling_layers)
|
| 532 |
+
|
| 533 |
+
intermediate_dim = intermediate_dims[-1]
|
| 534 |
+
if scale == 2.0:
|
| 535 |
+
if intermediate_dim > 512:
|
| 536 |
+
intermediate_dim = intermediate_dim // 4
|
| 537 |
+
else:
|
| 538 |
+
intermediate_dim = intermediate_dim // 2
|
| 539 |
+
projector_input_dim = intermediate_dim * len(intermediate_dims)
|
| 540 |
+
|
| 541 |
+
self.projector_layer = LwDetrC2FLayer(config, projector_input_dim)
|
| 542 |
+
self.layer_norm = LwDetrLayerNorm(config.d_model, data_format="channels_first")
|
| 543 |
+
|
| 544 |
+
def forward(self, hidden_states_tuple: tuple[torch.Tensor]) -> torch.Tensor:
|
| 545 |
+
sampled_hidden_states = []
|
| 546 |
+
for sampling_layer, hidden_states in zip(self.sampling_layers, hidden_states_tuple):
|
| 547 |
+
hidden_states = sampling_layer(hidden_states)
|
| 548 |
+
sampled_hidden_states.append(hidden_states)
|
| 549 |
+
hidden_states = torch.cat(sampled_hidden_states, dim=1)
|
| 550 |
+
hidden_states = self.projector_layer(hidden_states)
|
| 551 |
+
hidden_states = self.layer_norm(hidden_states)
|
| 552 |
+
return hidden_states
|
| 553 |
+
|
| 554 |
+
|
| 555 |
+
class LwDetrMultiScaleProjector(nn.Module):
|
| 556 |
+
def __init__(self, config: LwDetrConfig):
|
| 557 |
+
super().__init__()
|
| 558 |
+
|
| 559 |
+
self.config = config
|
| 560 |
+
scale_factors = config.projector_scale_factors
|
| 561 |
+
|
| 562 |
+
self.scale_layers = nn.ModuleList([LwDetrScaleProjector(config, scale) for scale in scale_factors])
|
| 563 |
+
|
| 564 |
+
def forward(self, hidden_states: tuple[torch.Tensor]) -> list[torch.Tensor]:
|
| 565 |
+
output_hidden_states = []
|
| 566 |
+
for scale_layer in self.scale_layers:
|
| 567 |
+
output_hidden_states.append(scale_layer(hidden_states))
|
| 568 |
+
return output_hidden_states
|
| 569 |
+
|
| 570 |
+
|
| 571 |
+
class LwDetrConvEncoder(nn.Module):
|
| 572 |
+
def __init__(self, config: LwDetrConfig):
|
| 573 |
+
super().__init__()
|
| 574 |
+
self.backbone = LwDetrViTBackbone(config.backbone_config)
|
| 575 |
+
self.projector = LwDetrMultiScaleProjector(config)
|
| 576 |
+
|
| 577 |
+
def forward(self, pixel_values: torch.Tensor, pixel_mask: torch.Tensor):
|
| 578 |
+
# send pixel_values through the model to get list of feature maps
|
| 579 |
+
features = self.backbone(pixel_values).feature_maps
|
| 580 |
+
features = self.projector(features)
|
| 581 |
+
out = []
|
| 582 |
+
for feature_map in features:
|
| 583 |
+
# downsample pixel_mask to match shape of corresponding feature_map
|
| 584 |
+
mask = nn.functional.interpolate(pixel_mask[None].float(), size=feature_map.shape[-2:]).to(torch.bool)[0]
|
| 585 |
+
out.append((feature_map, mask))
|
| 586 |
+
return out
|
| 587 |
+
|
| 588 |
+
|
| 589 |
+
class LwDetrAttention(nn.Module):
|
| 590 |
+
"""LW-DETR self-attention with group-DETR training technique."""
|
| 591 |
+
|
| 592 |
+
def __init__(self, config: LwDetrConfig, layer_idx: int):
|
| 593 |
+
super().__init__()
|
| 594 |
+
self.config = config
|
| 595 |
+
self.layer_idx = layer_idx
|
| 596 |
+
self.head_dim = getattr(config, "head_dim", config.d_model // config.decoder_self_attention_heads)
|
| 597 |
+
self.scaling = self.head_dim**-0.5
|
| 598 |
+
self.attention_dropout = config.attention_dropout
|
| 599 |
+
self.is_causal = False
|
| 600 |
+
self.num_key_value_groups = 1
|
| 601 |
+
|
| 602 |
+
self.q_proj = nn.Linear(
|
| 603 |
+
config.d_model, config.decoder_self_attention_heads * self.head_dim, bias=config.attention_bias
|
| 604 |
+
)
|
| 605 |
+
self.k_proj = nn.Linear(
|
| 606 |
+
config.d_model, config.decoder_self_attention_heads * self.head_dim, bias=config.attention_bias
|
| 607 |
+
)
|
| 608 |
+
self.v_proj = nn.Linear(
|
| 609 |
+
config.d_model, config.decoder_self_attention_heads * self.head_dim, bias=config.attention_bias
|
| 610 |
+
)
|
| 611 |
+
self.o_proj = nn.Linear(
|
| 612 |
+
config.decoder_self_attention_heads * self.head_dim, config.d_model, bias=config.attention_bias
|
| 613 |
+
)
|
| 614 |
+
|
| 615 |
+
def forward(
|
| 616 |
+
self,
|
| 617 |
+
hidden_states: torch.Tensor,
|
| 618 |
+
position_embeddings: torch.Tensor | None = None,
|
| 619 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 620 |
+
) -> tuple[torch.Tensor, torch.Tensor]:
|
| 621 |
+
batch_size, seq_len, _ = hidden_states.shape
|
| 622 |
+
|
| 623 |
+
hidden_states_original = hidden_states
|
| 624 |
+
if position_embeddings is not None:
|
| 625 |
+
hidden_states = hidden_states if position_embeddings is None else hidden_states + position_embeddings
|
| 626 |
+
|
| 627 |
+
if self.training:
|
| 628 |
+
# at training, we use group detr technique to add more supervision by using multiple weight-sharing decoders at once for faster convergence
|
| 629 |
+
# at inference, we only use one decoder
|
| 630 |
+
hidden_states_original = torch.cat(
|
| 631 |
+
hidden_states_original.split(seq_len // self.config.group_detr, dim=1), dim=0
|
| 632 |
+
)
|
| 633 |
+
hidden_states = torch.cat(hidden_states.split(seq_len // self.config.group_detr, dim=1), dim=0)
|
| 634 |
+
|
| 635 |
+
attention_input_shape = hidden_states.shape[:-1]
|
| 636 |
+
hidden_shape = (*attention_input_shape, -1, self.head_dim)
|
| 637 |
+
query_states = self.q_proj(hidden_states).view(hidden_shape).transpose(1, 2)
|
| 638 |
+
key_states = self.k_proj(hidden_states).view(hidden_shape).transpose(1, 2)
|
| 639 |
+
value_states = self.v_proj(hidden_states_original).view(hidden_shape).transpose(1, 2)
|
| 640 |
+
|
| 641 |
+
attention_interface: Callable = ALL_ATTENTION_FUNCTIONS.get_interface(
|
| 642 |
+
self.config._attn_implementation, eager_attention_forward
|
| 643 |
+
)
|
| 644 |
+
|
| 645 |
+
attn_output, attn_weights = attention_interface(
|
| 646 |
+
self,
|
| 647 |
+
query_states,
|
| 648 |
+
key_states,
|
| 649 |
+
value_states,
|
| 650 |
+
attention_mask=None,
|
| 651 |
+
dropout=0.0 if not self.training else self.attention_dropout,
|
| 652 |
+
scaling=self.scaling,
|
| 653 |
+
**kwargs,
|
| 654 |
+
)
|
| 655 |
+
attn_output = attn_output.reshape(*attention_input_shape, -1).contiguous()
|
| 656 |
+
attn_output = self.o_proj(attn_output)
|
| 657 |
+
|
| 658 |
+
if self.training:
|
| 659 |
+
attn_output = torch.cat(torch.split(attn_output, batch_size, dim=0), dim=1)
|
| 660 |
+
|
| 661 |
+
return attn_output, attn_weights
|
| 662 |
+
|
| 663 |
+
|
| 664 |
+
class LwDetrMultiscaleDeformableAttention(DeformableDetrMultiscaleDeformableAttention):
|
| 665 |
+
pass
|
| 666 |
+
|
| 667 |
+
|
| 668 |
+
class LwDetrMLP(nn.Module):
|
| 669 |
+
def __init__(self, config: LwDetrConfig):
|
| 670 |
+
super().__init__()
|
| 671 |
+
self.dropout = config.dropout
|
| 672 |
+
self.activation_fn = ACT2FN[config.decoder_activation_function]
|
| 673 |
+
self.fc1 = nn.Linear(config.d_model, config.decoder_ffn_dim)
|
| 674 |
+
self.fc2 = nn.Linear(config.decoder_ffn_dim, config.d_model)
|
| 675 |
+
|
| 676 |
+
def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
|
| 677 |
+
residual = hidden_states
|
| 678 |
+
hidden_states = self.fc1(hidden_states)
|
| 679 |
+
hidden_states = self.activation_fn(hidden_states)
|
| 680 |
+
hidden_states = nn.functional.dropout(hidden_states, p=self.dropout, training=self.training)
|
| 681 |
+
hidden_states = self.fc2(hidden_states)
|
| 682 |
+
hidden_states = nn.functional.dropout(hidden_states, p=self.dropout, training=self.training)
|
| 683 |
+
hidden_states = residual + hidden_states
|
| 684 |
+
return hidden_states
|
| 685 |
+
|
| 686 |
+
|
| 687 |
+
class LwDetrDecoderLayer(GradientCheckpointingLayer):
|
| 688 |
+
def __init__(self, config: LwDetrConfig, layer_idx: int):
|
| 689 |
+
nn.Module.__init__(self)
|
| 690 |
+
|
| 691 |
+
# self-attention
|
| 692 |
+
self.self_attn = LwDetrAttention(config, layer_idx=layer_idx)
|
| 693 |
+
self.dropout = config.dropout
|
| 694 |
+
self.activation_fn = ACT2FN[config.decoder_activation_function]
|
| 695 |
+
self.activation_dropout = config.activation_dropout
|
| 696 |
+
self.self_attn_layer_norm = nn.LayerNorm(config.d_model)
|
| 697 |
+
|
| 698 |
+
# cross-attention
|
| 699 |
+
self.cross_attn = LwDetrMultiscaleDeformableAttention(
|
| 700 |
+
config,
|
| 701 |
+
num_heads=config.decoder_cross_attention_heads,
|
| 702 |
+
n_points=config.decoder_n_points,
|
| 703 |
+
)
|
| 704 |
+
self.cross_attn_layer_norm = nn.LayerNorm(config.d_model)
|
| 705 |
+
|
| 706 |
+
# mlp
|
| 707 |
+
self.mlp = LwDetrMLP(config)
|
| 708 |
+
self.layer_norm = nn.LayerNorm(config.d_model)
|
| 709 |
+
|
| 710 |
+
def forward(
|
| 711 |
+
self,
|
| 712 |
+
hidden_states: torch.Tensor,
|
| 713 |
+
position_embeddings: torch.Tensor | None = None,
|
| 714 |
+
reference_points=None,
|
| 715 |
+
spatial_shapes=None,
|
| 716 |
+
spatial_shapes_list=None,
|
| 717 |
+
level_start_index=None,
|
| 718 |
+
encoder_hidden_states: torch.Tensor | None = None,
|
| 719 |
+
encoder_attention_mask: torch.Tensor | None = None,
|
| 720 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 721 |
+
):
|
| 722 |
+
self_attention_output, self_attn_weights = self.self_attn(
|
| 723 |
+
hidden_states, position_embeddings=position_embeddings, **kwargs
|
| 724 |
+
)
|
| 725 |
+
|
| 726 |
+
self_attention_output = nn.functional.dropout(self_attention_output, p=self.dropout, training=self.training)
|
| 727 |
+
hidden_states = hidden_states + self_attention_output
|
| 728 |
+
hidden_states = self.self_attn_layer_norm(hidden_states)
|
| 729 |
+
|
| 730 |
+
cross_attention_output, cross_attn_weights = self.cross_attn(
|
| 731 |
+
hidden_states=hidden_states,
|
| 732 |
+
attention_mask=encoder_attention_mask,
|
| 733 |
+
encoder_hidden_states=encoder_hidden_states,
|
| 734 |
+
encoder_attention_mask=encoder_attention_mask,
|
| 735 |
+
position_embeddings=position_embeddings,
|
| 736 |
+
reference_points=reference_points,
|
| 737 |
+
spatial_shapes=spatial_shapes,
|
| 738 |
+
spatial_shapes_list=spatial_shapes_list,
|
| 739 |
+
level_start_index=level_start_index,
|
| 740 |
+
**kwargs,
|
| 741 |
+
)
|
| 742 |
+
cross_attention_output = nn.functional.dropout(cross_attention_output, p=self.dropout, training=self.training)
|
| 743 |
+
hidden_states = hidden_states + cross_attention_output
|
| 744 |
+
hidden_states = self.cross_attn_layer_norm(hidden_states)
|
| 745 |
+
|
| 746 |
+
hidden_states = self.mlp(hidden_states)
|
| 747 |
+
hidden_states = self.layer_norm(hidden_states)
|
| 748 |
+
|
| 749 |
+
return hidden_states
|
| 750 |
+
|
| 751 |
+
|
| 752 |
+
@auto_docstring
|
| 753 |
+
class LwDetrPreTrainedModel(PreTrainedModel):
|
| 754 |
+
config: LwDetrConfig
|
| 755 |
+
base_model_prefix = "model"
|
| 756 |
+
main_input_name = "pixel_values"
|
| 757 |
+
input_modalities = ("image",)
|
| 758 |
+
_no_split_modules = [
|
| 759 |
+
r"LwDetrConvEncoder",
|
| 760 |
+
r"LwDetrDecoderLayer",
|
| 761 |
+
]
|
| 762 |
+
_supports_sdpa = True
|
| 763 |
+
_supports_flash_attn = True
|
| 764 |
+
_supports_flex_attn = True
|
| 765 |
+
_supports_attention_backend = True
|
| 766 |
+
_can_record_outputs = {
|
| 767 |
+
"attentions": [LwDetrAttention, LwDetrMultiscaleDeformableAttention],
|
| 768 |
+
"hidden_states": [LwDetrDecoderLayer],
|
| 769 |
+
}
|
| 770 |
+
|
| 771 |
+
@torch.no_grad()
|
| 772 |
+
def _init_weights(self, module):
|
| 773 |
+
super()._init_weights(module)
|
| 774 |
+
|
| 775 |
+
if isinstance(module, LwDetrMultiscaleDeformableAttention):
|
| 776 |
+
init.constant_(module.sampling_offsets.weight, 0.0)
|
| 777 |
+
thetas = torch.arange(module.n_heads, dtype=torch.int64).float() * (2.0 * math.pi / module.n_heads)
|
| 778 |
+
grid_init = torch.stack([thetas.cos(), thetas.sin()], -1)
|
| 779 |
+
grid_init = (
|
| 780 |
+
(grid_init / grid_init.abs().max(-1, keepdim=True)[0])
|
| 781 |
+
.view(module.n_heads, 1, 1, 2)
|
| 782 |
+
.repeat(1, module.n_levels, module.n_points, 1)
|
| 783 |
+
)
|
| 784 |
+
for i in range(module.n_points):
|
| 785 |
+
grid_init[:, :, i, :] *= i + 1
|
| 786 |
+
|
| 787 |
+
init.copy_(module.sampling_offsets.bias, grid_init.view(-1))
|
| 788 |
+
init.constant_(module.attention_weights.weight, 0.0)
|
| 789 |
+
init.constant_(module.attention_weights.bias, 0.0)
|
| 790 |
+
init.xavier_uniform_(module.value_proj.weight)
|
| 791 |
+
init.constant_(module.value_proj.bias, 0.0)
|
| 792 |
+
init.xavier_uniform_(module.output_proj.weight)
|
| 793 |
+
init.constant_(module.output_proj.bias, 0.0)
|
| 794 |
+
if hasattr(module, "level_embed"):
|
| 795 |
+
init.normal_(module.level_embed)
|
| 796 |
+
if hasattr(module, "refpoint_embed") and module.refpoint_embed is not None:
|
| 797 |
+
init.constant_(module.refpoint_embed.weight, 0)
|
| 798 |
+
if hasattr(module, "class_embed") and module.class_embed is not None:
|
| 799 |
+
prior_prob = 0.01
|
| 800 |
+
bias_value = -math.log((1 - prior_prob) / prior_prob)
|
| 801 |
+
init.constant_(module.class_embed.bias, bias_value)
|
| 802 |
+
if hasattr(module, "bbox_embed") and module.bbox_embed is not None:
|
| 803 |
+
init.constant_(module.bbox_embed.layers[-1].weight, 0)
|
| 804 |
+
init.constant_(module.bbox_embed.layers[-1].bias, 0)
|
| 805 |
+
|
| 806 |
+
|
| 807 |
+
def refine_bboxes(reference_points, deltas):
|
| 808 |
+
reference_points = reference_points.to(deltas.device)
|
| 809 |
+
new_reference_points_cxcy = deltas[..., :2] * reference_points[..., 2:] + reference_points[..., :2]
|
| 810 |
+
new_reference_points_wh = deltas[..., 2:].exp() * reference_points[..., 2:]
|
| 811 |
+
new_reference_points = torch.cat((new_reference_points_cxcy, new_reference_points_wh), -1)
|
| 812 |
+
return new_reference_points
|
| 813 |
+
|
| 814 |
+
|
| 815 |
+
@auto_docstring(
|
| 816 |
+
custom_intro="""
|
| 817 |
+
Base class for outputs of the LwDetrDecoder. This class adds two attributes to
|
| 818 |
+
BaseModelOutputWithCrossAttentions, namely:
|
| 819 |
+
- a stacked tensor of intermediate decoder hidden states (i.e. the output of each decoder layer)
|
| 820 |
+
- a stacked tensor of intermediate reference points.
|
| 821 |
+
"""
|
| 822 |
+
)
|
| 823 |
+
@dataclass
|
| 824 |
+
class LwDetrDecoderOutput(DeformableDetrDecoderOutput):
|
| 825 |
+
pass
|
| 826 |
+
|
| 827 |
+
|
| 828 |
+
class LwDetrDecoder(LwDetrPreTrainedModel):
|
| 829 |
+
"""
|
| 830 |
+
Transformer decoder consisting of *config.decoder_layers* layers. Each layer is a [`DeformableDetrDecoderLayer`].
|
| 831 |
+
|
| 832 |
+
The decoder updates the query embeddings through multiple self-attention and deformable cross-attention layers.
|
| 833 |
+
|
| 834 |
+
Some tweaks for LwDetr:
|
| 835 |
+
|
| 836 |
+
- it uses group detr technique at training for faster convergence.
|
| 837 |
+
|
| 838 |
+
Args:
|
| 839 |
+
config: LwDetrConfig
|
| 840 |
+
"""
|
| 841 |
+
|
| 842 |
+
_can_record_outputs = {
|
| 843 |
+
"hidden_states": LwDetrDecoderLayer,
|
| 844 |
+
"attentions": OutputRecorder(LwDetrAttention, layer_name="self_attn", index=1),
|
| 845 |
+
"cross_attentions": OutputRecorder(LwDetrMultiscaleDeformableAttention, layer_name="cross_attn", index=1),
|
| 846 |
+
}
|
| 847 |
+
|
| 848 |
+
def __init__(self, config: LwDetrConfig):
|
| 849 |
+
super().__init__(config)
|
| 850 |
+
self.dropout = config.dropout
|
| 851 |
+
self.layers = nn.ModuleList([LwDetrDecoderLayer(config, i) for i in range(config.decoder_layers)])
|
| 852 |
+
self.layernorm = nn.LayerNorm(config.d_model)
|
| 853 |
+
|
| 854 |
+
self.gradient_checkpointing = False
|
| 855 |
+
|
| 856 |
+
self.ref_point_head = LwDetrMLPPredictionHead(2 * config.d_model, config.d_model, config.d_model, num_layers=2)
|
| 857 |
+
|
| 858 |
+
self.post_init()
|
| 859 |
+
|
| 860 |
+
def get_reference(self, reference_points, valid_ratios):
|
| 861 |
+
# batch_size, num_queries, batch_size, 4
|
| 862 |
+
obj_center = reference_points[..., :4]
|
| 863 |
+
|
| 864 |
+
# batch_size, num_queries, num_levels, 4
|
| 865 |
+
reference_points_inputs = obj_center[:, :, None] * torch.cat([valid_ratios, valid_ratios], -1)[:, None]
|
| 866 |
+
|
| 867 |
+
# batch_size, num_queries, d_model * 2
|
| 868 |
+
query_sine_embed = encode_sinusoidal_position_embedding(
|
| 869 |
+
reference_points_inputs[:, :, 0, :], num_pos_feats=self.config.d_model // 2
|
| 870 |
+
)
|
| 871 |
+
|
| 872 |
+
# batch_size, num_queries, d_model
|
| 873 |
+
query_pos = self.ref_point_head(query_sine_embed)
|
| 874 |
+
return reference_points_inputs, query_pos
|
| 875 |
+
|
| 876 |
+
@merge_with_config_defaults
|
| 877 |
+
@capture_outputs
|
| 878 |
+
def forward(
|
| 879 |
+
self,
|
| 880 |
+
inputs_embeds: torch.Tensor | None = None,
|
| 881 |
+
reference_points: torch.Tensor | None = None,
|
| 882 |
+
spatial_shapes: torch.Tensor | None = None,
|
| 883 |
+
spatial_shapes_list: torch.Tensor | None = None,
|
| 884 |
+
level_start_index: torch.Tensor | None = None,
|
| 885 |
+
valid_ratios: torch.Tensor | None = None,
|
| 886 |
+
encoder_hidden_states: torch.Tensor | None = None,
|
| 887 |
+
encoder_attention_mask: torch.Tensor | None = None,
|
| 888 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 889 |
+
):
|
| 890 |
+
intermediate = ()
|
| 891 |
+
intermediate_reference_points = (reference_points,)
|
| 892 |
+
|
| 893 |
+
if inputs_embeds is not None:
|
| 894 |
+
hidden_states = inputs_embeds
|
| 895 |
+
|
| 896 |
+
reference_points_inputs, query_pos = self.get_reference(reference_points, valid_ratios)
|
| 897 |
+
|
| 898 |
+
for idx, decoder_layer in enumerate(self.layers):
|
| 899 |
+
hidden_states = decoder_layer(
|
| 900 |
+
hidden_states,
|
| 901 |
+
encoder_hidden_states=encoder_hidden_states,
|
| 902 |
+
encoder_attention_mask=encoder_attention_mask,
|
| 903 |
+
position_embeddings=query_pos,
|
| 904 |
+
reference_points=reference_points_inputs,
|
| 905 |
+
spatial_shapes=spatial_shapes,
|
| 906 |
+
spatial_shapes_list=spatial_shapes_list,
|
| 907 |
+
level_start_index=level_start_index,
|
| 908 |
+
**kwargs,
|
| 909 |
+
)
|
| 910 |
+
intermediate_hidden_states = self.layernorm(hidden_states)
|
| 911 |
+
intermediate += (intermediate_hidden_states,)
|
| 912 |
+
|
| 913 |
+
intermediate = torch.stack(intermediate)
|
| 914 |
+
last_hidden_state = intermediate[-1]
|
| 915 |
+
intermediate_reference_points = torch.stack(intermediate_reference_points)
|
| 916 |
+
|
| 917 |
+
return LwDetrDecoderOutput(
|
| 918 |
+
last_hidden_state=last_hidden_state,
|
| 919 |
+
intermediate_hidden_states=intermediate,
|
| 920 |
+
intermediate_reference_points=intermediate_reference_points,
|
| 921 |
+
)
|
| 922 |
+
|
| 923 |
+
|
| 924 |
+
@auto_docstring(
|
| 925 |
+
custom_intro="""
|
| 926 |
+
Base class for outputs of the LwDetr backbone-decoder model.
|
| 927 |
+
"""
|
| 928 |
+
)
|
| 929 |
+
@dataclass
|
| 930 |
+
class LwDetrModelOutput(ModelOutput):
|
| 931 |
+
r"""
|
| 932 |
+
init_reference_points (`torch.FloatTensor` of shape `(batch_size, num_queries, 4)`):
|
| 933 |
+
Initial reference points sent through the Transformer decoder.
|
| 934 |
+
intermediate_hidden_states (`torch.FloatTensor` of shape `(batch_size, config.decoder_layers, num_queries, hidden_size)`):
|
| 935 |
+
Stacked intermediate hidden states (output of each layer of the decoder).
|
| 936 |
+
intermediate_reference_points (`torch.FloatTensor` of shape `(batch_size, config.decoder_layers, num_queries, 4)`):
|
| 937 |
+
Stacked intermediate reference points (reference points of each layer of the decoder).
|
| 938 |
+
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`):
|
| 939 |
+
Predicted bounding boxes scores where the top `config.two_stage_num_proposals` scoring bounding boxes are
|
| 940 |
+
picked as region proposals in the first stage. Output of bounding box binary classification (i.e.
|
| 941 |
+
foreground and background).
|
| 942 |
+
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`):
|
| 943 |
+
Logits of predicted bounding boxes coordinates in the first stage.
|
| 944 |
+
"""
|
| 945 |
+
|
| 946 |
+
init_reference_points: torch.FloatTensor | None = None
|
| 947 |
+
last_hidden_state: torch.FloatTensor | None = None
|
| 948 |
+
intermediate_hidden_states: torch.FloatTensor | None = None
|
| 949 |
+
intermediate_reference_points: torch.FloatTensor | None = None
|
| 950 |
+
enc_outputs_class: torch.FloatTensor | None = None
|
| 951 |
+
enc_outputs_coord_logits: torch.FloatTensor | None = None
|
| 952 |
+
hidden_states: tuple[torch.FloatTensor, ...] | None = None
|
| 953 |
+
attentions: tuple[torch.FloatTensor, ...] | None = None
|
| 954 |
+
cross_attentions: tuple[torch.FloatTensor, ...] | None = None
|
| 955 |
+
|
| 956 |
+
|
| 957 |
+
@auto_docstring(
|
| 958 |
+
custom_intro="""
|
| 959 |
+
The bare LW Detr Model (consisting of a backbone and decoder Transformer) outputting raw
|
| 960 |
+
hidden-states without any specific head on top.
|
| 961 |
+
"""
|
| 962 |
+
)
|
| 963 |
+
class LwDetrModel(DeformableDetrModel):
|
| 964 |
+
def __init__(self, config: LwDetrConfig):
|
| 965 |
+
PreTrainedModel.__init__(self, config)
|
| 966 |
+
|
| 967 |
+
# Create backbone + positional encoding
|
| 968 |
+
self.backbone = LwDetrConvEncoder(config)
|
| 969 |
+
|
| 970 |
+
self.group_detr = config.group_detr
|
| 971 |
+
self.num_queries = config.num_queries
|
| 972 |
+
hidden_dim = config.d_model
|
| 973 |
+
self.reference_point_embed = nn.Embedding(self.num_queries * self.group_detr, 4)
|
| 974 |
+
self.query_feat = nn.Embedding(self.num_queries * self.group_detr, hidden_dim)
|
| 975 |
+
|
| 976 |
+
self.decoder = LwDetrDecoder(config)
|
| 977 |
+
|
| 978 |
+
self.enc_output = nn.ModuleList([nn.Linear(hidden_dim, hidden_dim) for _ in range(self.group_detr)])
|
| 979 |
+
self.enc_output_norm = nn.ModuleList([nn.LayerNorm(hidden_dim) for _ in range(self.group_detr)])
|
| 980 |
+
# Should normally be None and then instantiated in the ForObjectDetection class
|
| 981 |
+
self.enc_out_bbox_embed = nn.ModuleList(
|
| 982 |
+
[LwDetrMLPPredictionHead(config.d_model, config.d_model, 4, num_layers=3) for _ in range(self.group_detr)]
|
| 983 |
+
)
|
| 984 |
+
self.enc_out_class_embed = nn.ModuleList(
|
| 985 |
+
[nn.Linear(config.d_model, config.num_labels) for _ in range(self.group_detr)]
|
| 986 |
+
)
|
| 987 |
+
|
| 988 |
+
self.post_init()
|
| 989 |
+
|
| 990 |
+
def gen_encoder_output_proposals(self, enc_output, padding_mask, spatial_shapes):
|
| 991 |
+
"""Generate the encoder output proposals from encoded enc_output.
|
| 992 |
+
|
| 993 |
+
Args:
|
| 994 |
+
enc_output (Tensor[batch_size, sequence_length, hidden_size]): Output of the encoder.
|
| 995 |
+
padding_mask (Tensor[batch_size, sequence_length]): Padding mask for `enc_output`.
|
| 996 |
+
spatial_shapes (list[tuple[int, int]]): Spatial shapes of the feature maps.
|
| 997 |
+
|
| 998 |
+
Returns:
|
| 999 |
+
`tuple(torch.FloatTensor)`: A tuple of feature map and bbox prediction.
|
| 1000 |
+
- object_query (Tensor[batch_size, sequence_length, hidden_size]): Object query features. Later used to
|
| 1001 |
+
directly predict a bounding box. (without the need of a decoder)
|
| 1002 |
+
- output_proposals (Tensor[batch_size, sequence_length, 4]): Normalized proposals in [0, 1] space.
|
| 1003 |
+
Invalid positions (padding or out-of-bounds) are filled with 0.
|
| 1004 |
+
- invalid_mask (Tensor[batch_size, sequence_length, 1]): Boolean mask that is True for invalid positions
|
| 1005 |
+
(padded pixels or proposals whose coordinates fall outside (0.01, 0.99)).
|
| 1006 |
+
"""
|
| 1007 |
+
batch_size = enc_output.shape[0]
|
| 1008 |
+
proposals = []
|
| 1009 |
+
_cur = 0
|
| 1010 |
+
for level, (height, width) in enumerate(spatial_shapes):
|
| 1011 |
+
mask_flatten_ = padding_mask[:, _cur : (_cur + height * width)].view(batch_size, height, width, 1)
|
| 1012 |
+
valid_height = torch.sum(~mask_flatten_[:, :, 0, 0], 1)
|
| 1013 |
+
valid_width = torch.sum(~mask_flatten_[:, 0, :, 0], 1)
|
| 1014 |
+
|
| 1015 |
+
grid_y, grid_x = torch.meshgrid(
|
| 1016 |
+
torch.linspace(
|
| 1017 |
+
0,
|
| 1018 |
+
height - 1,
|
| 1019 |
+
height,
|
| 1020 |
+
dtype=enc_output.dtype,
|
| 1021 |
+
device=enc_output.device,
|
| 1022 |
+
),
|
| 1023 |
+
torch.linspace(
|
| 1024 |
+
0,
|
| 1025 |
+
width - 1,
|
| 1026 |
+
width,
|
| 1027 |
+
dtype=enc_output.dtype,
|
| 1028 |
+
device=enc_output.device,
|
| 1029 |
+
),
|
| 1030 |
+
indexing="ij",
|
| 1031 |
+
)
|
| 1032 |
+
grid = torch.cat([grid_x.unsqueeze(-1), grid_y.unsqueeze(-1)], -1)
|
| 1033 |
+
|
| 1034 |
+
scale = torch.cat([valid_width.unsqueeze(-1), valid_height.unsqueeze(-1)], 1).view(batch_size, 1, 1, 2)
|
| 1035 |
+
grid = (grid.unsqueeze(0).expand(batch_size, -1, -1, -1) + 0.5) / scale
|
| 1036 |
+
width_height = torch.ones_like(grid) * 0.05 * (2.0**level)
|
| 1037 |
+
proposal = torch.cat((grid, width_height), -1).view(batch_size, -1, 4)
|
| 1038 |
+
proposals.append(proposal)
|
| 1039 |
+
_cur += height * width
|
| 1040 |
+
output_proposals = torch.cat(proposals, 1)
|
| 1041 |
+
output_proposals_valid = ((output_proposals > 0.01) & (output_proposals < 0.99)).all(-1, keepdim=True)
|
| 1042 |
+
invalid_mask = padding_mask.unsqueeze(-1) | ~output_proposals_valid
|
| 1043 |
+
output_proposals = output_proposals.masked_fill(invalid_mask, float(0))
|
| 1044 |
+
|
| 1045 |
+
# assign each pixel as an object query
|
| 1046 |
+
object_query = enc_output
|
| 1047 |
+
object_query = object_query.masked_fill(invalid_mask, float(0))
|
| 1048 |
+
return object_query, output_proposals, invalid_mask
|
| 1049 |
+
|
| 1050 |
+
@can_return_tuple
|
| 1051 |
+
@auto_docstring
|
| 1052 |
+
def forward(
|
| 1053 |
+
self,
|
| 1054 |
+
pixel_values: torch.FloatTensor = None,
|
| 1055 |
+
pixel_mask: torch.LongTensor | None = None,
|
| 1056 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 1057 |
+
) -> LwDetrModelOutput:
|
| 1058 |
+
r"""
|
| 1059 |
+
Examples:
|
| 1060 |
+
|
| 1061 |
+
```python
|
| 1062 |
+
>>> from transformers import AutoImageProcessor, DeformableDetrModel
|
| 1063 |
+
>>> from PIL import Image
|
| 1064 |
+
>>> import httpx
|
| 1065 |
+
>>> from io import BytesIO
|
| 1066 |
+
|
| 1067 |
+
>>> url = "http://images.cocodataset.org/val2017/000000039769.jpg"
|
| 1068 |
+
>>> with httpx.stream("GET", url) as response:
|
| 1069 |
+
... image = Image.open(BytesIO(response.read()))
|
| 1070 |
+
|
| 1071 |
+
>>> image_processor = AutoImageProcessor.from_pretrained("AnnaZhang/lwdetr_small_60e_coco")
|
| 1072 |
+
>>> model = DeformableDetrModel.from_pretrained("AnnaZhang/lwdetr_small_60e_coco")
|
| 1073 |
+
|
| 1074 |
+
>>> inputs = image_processor(images=image, return_tensors="pt")
|
| 1075 |
+
|
| 1076 |
+
>>> outputs = model(**inputs)
|
| 1077 |
+
|
| 1078 |
+
>>> last_hidden_states = outputs.last_hidden_state
|
| 1079 |
+
>>> list(last_hidden_states.shape)
|
| 1080 |
+
[1, 300, 256]
|
| 1081 |
+
```"""
|
| 1082 |
+
batch_size, num_channels, height, width = pixel_values.shape
|
| 1083 |
+
device = pixel_values.device
|
| 1084 |
+
|
| 1085 |
+
if pixel_mask is None:
|
| 1086 |
+
pixel_mask = torch.ones(((batch_size, height, width)), dtype=torch.long, device=device)
|
| 1087 |
+
|
| 1088 |
+
# Extract multi-scale feature maps of same resolution `config.d_model` (cf Figure 4 in paper)
|
| 1089 |
+
# First, sent pixel_values + pixel_mask through Backbone to obtain the features
|
| 1090 |
+
# which is a list of tuples
|
| 1091 |
+
features = self.backbone(pixel_values, pixel_mask)
|
| 1092 |
+
|
| 1093 |
+
# Then, apply 1x1 convolution to reduce the channel dimension to d_model (256 by default)
|
| 1094 |
+
sources = []
|
| 1095 |
+
masks = []
|
| 1096 |
+
for level, (source, mask) in enumerate(features):
|
| 1097 |
+
sources.append(source)
|
| 1098 |
+
masks.append(mask)
|
| 1099 |
+
if mask is None:
|
| 1100 |
+
raise ValueError("No attention mask was provided")
|
| 1101 |
+
|
| 1102 |
+
if self.training:
|
| 1103 |
+
reference_points = self.reference_point_embed.weight
|
| 1104 |
+
query_feat = self.query_feat.weight
|
| 1105 |
+
else:
|
| 1106 |
+
# only use one group in inference
|
| 1107 |
+
reference_points = self.reference_point_embed.weight[: self.num_queries]
|
| 1108 |
+
query_feat = self.query_feat.weight[: self.num_queries]
|
| 1109 |
+
|
| 1110 |
+
# Prepare encoder inputs (by flattening)
|
| 1111 |
+
source_flatten = []
|
| 1112 |
+
mask_flatten = []
|
| 1113 |
+
spatial_shapes_list = []
|
| 1114 |
+
for source, mask in zip(sources, masks):
|
| 1115 |
+
batch_size, num_channels, height, width = source.shape
|
| 1116 |
+
spatial_shape = (height, width)
|
| 1117 |
+
spatial_shapes_list.append(spatial_shape)
|
| 1118 |
+
source = source.flatten(2).transpose(1, 2)
|
| 1119 |
+
mask = mask.flatten(1)
|
| 1120 |
+
source_flatten.append(source)
|
| 1121 |
+
mask_flatten.append(mask)
|
| 1122 |
+
source_flatten = torch.cat(source_flatten, 1)
|
| 1123 |
+
mask_flatten = torch.cat(mask_flatten, 1)
|
| 1124 |
+
spatial_shapes = torch.as_tensor(spatial_shapes_list, dtype=torch.long, device=source_flatten.device)
|
| 1125 |
+
level_start_index = torch.cat((spatial_shapes.new_zeros((1,)), spatial_shapes.prod(1).cumsum(0)[:-1]))
|
| 1126 |
+
valid_ratios = torch.stack([self.get_valid_ratio(m, dtype=source_flatten.dtype) for m in masks], 1)
|
| 1127 |
+
|
| 1128 |
+
target = query_feat.unsqueeze(0).expand(batch_size, -1, -1)
|
| 1129 |
+
reference_points = reference_points.unsqueeze(0).expand(batch_size, -1, -1)
|
| 1130 |
+
|
| 1131 |
+
object_query_embedding, output_proposals, invalid_mask = self.gen_encoder_output_proposals(
|
| 1132 |
+
source_flatten, ~mask_flatten, spatial_shapes_list
|
| 1133 |
+
)
|
| 1134 |
+
|
| 1135 |
+
group_detr = self.group_detr if self.training else 1
|
| 1136 |
+
topk = self.num_queries
|
| 1137 |
+
topk_coords_logits = []
|
| 1138 |
+
topk_coords_logits_undetach = []
|
| 1139 |
+
object_query_undetach = []
|
| 1140 |
+
|
| 1141 |
+
for group_id in range(group_detr):
|
| 1142 |
+
group_object_query = self.enc_output[group_id](object_query_embedding)
|
| 1143 |
+
group_object_query = self.enc_output_norm[group_id](group_object_query)
|
| 1144 |
+
|
| 1145 |
+
group_enc_outputs_class = self.enc_out_class_embed[group_id](group_object_query)
|
| 1146 |
+
group_enc_outputs_class = group_enc_outputs_class.masked_fill(invalid_mask, float("-inf"))
|
| 1147 |
+
group_delta_bbox = self.enc_out_bbox_embed[group_id](group_object_query)
|
| 1148 |
+
group_enc_outputs_coord = refine_bboxes(output_proposals, group_delta_bbox)
|
| 1149 |
+
|
| 1150 |
+
group_topk_proposals = torch.topk(group_enc_outputs_class.max(-1)[0], topk, dim=1)[1]
|
| 1151 |
+
group_topk_coords_logits_undetach = torch.gather(
|
| 1152 |
+
group_enc_outputs_coord,
|
| 1153 |
+
1,
|
| 1154 |
+
group_topk_proposals.unsqueeze(-1).repeat(1, 1, 4),
|
| 1155 |
+
)
|
| 1156 |
+
group_topk_coords_logits = group_topk_coords_logits_undetach.detach()
|
| 1157 |
+
group_object_query_undetach = torch.gather(
|
| 1158 |
+
group_object_query, 1, group_topk_proposals.unsqueeze(-1).repeat(1, 1, self.config.d_model)
|
| 1159 |
+
)
|
| 1160 |
+
|
| 1161 |
+
topk_coords_logits.append(group_topk_coords_logits)
|
| 1162 |
+
topk_coords_logits_undetach.append(group_topk_coords_logits_undetach)
|
| 1163 |
+
object_query_undetach.append(group_object_query_undetach)
|
| 1164 |
+
|
| 1165 |
+
topk_coords_logits = torch.cat(topk_coords_logits, 1)
|
| 1166 |
+
topk_coords_logits_undetach = torch.cat(topk_coords_logits_undetach, 1)
|
| 1167 |
+
object_query_undetach = torch.cat(object_query_undetach, 1)
|
| 1168 |
+
|
| 1169 |
+
enc_outputs_class = object_query_undetach
|
| 1170 |
+
enc_outputs_coord_logits = topk_coords_logits_undetach
|
| 1171 |
+
|
| 1172 |
+
reference_points = refine_bboxes(topk_coords_logits, reference_points)
|
| 1173 |
+
|
| 1174 |
+
init_reference_points = reference_points
|
| 1175 |
+
decoder_outputs = self.decoder(
|
| 1176 |
+
inputs_embeds=target,
|
| 1177 |
+
reference_points=reference_points,
|
| 1178 |
+
spatial_shapes=spatial_shapes,
|
| 1179 |
+
spatial_shapes_list=spatial_shapes_list,
|
| 1180 |
+
level_start_index=level_start_index,
|
| 1181 |
+
valid_ratios=valid_ratios,
|
| 1182 |
+
encoder_hidden_states=source_flatten,
|
| 1183 |
+
encoder_attention_mask=mask_flatten,
|
| 1184 |
+
**kwargs,
|
| 1185 |
+
)
|
| 1186 |
+
|
| 1187 |
+
return LwDetrModelOutput(
|
| 1188 |
+
init_reference_points=init_reference_points,
|
| 1189 |
+
last_hidden_state=decoder_outputs.last_hidden_state,
|
| 1190 |
+
intermediate_hidden_states=decoder_outputs.intermediate_hidden_states,
|
| 1191 |
+
intermediate_reference_points=decoder_outputs.intermediate_reference_points,
|
| 1192 |
+
enc_outputs_class=enc_outputs_class,
|
| 1193 |
+
enc_outputs_coord_logits=enc_outputs_coord_logits,
|
| 1194 |
+
hidden_states=decoder_outputs.hidden_states,
|
| 1195 |
+
attentions=decoder_outputs.attentions,
|
| 1196 |
+
cross_attentions=decoder_outputs.cross_attentions,
|
| 1197 |
+
)
|
| 1198 |
+
|
| 1199 |
+
def get_proposal_pos_embed(self, proposals):
|
| 1200 |
+
raise NotImplementedError("get_proposal_pos_embed is not used in LwDetrForObjectDetection")
|
| 1201 |
+
|
| 1202 |
+
|
| 1203 |
+
class LwDetrMLPPredictionHead(DeformableDetrMLPPredictionHead):
|
| 1204 |
+
pass
|
| 1205 |
+
|
| 1206 |
+
|
| 1207 |
+
@auto_docstring(
|
| 1208 |
+
custom_intro="""
|
| 1209 |
+
Output type of [`LwDetrForObjectDetection`].
|
| 1210 |
+
"""
|
| 1211 |
+
)
|
| 1212 |
+
@dataclass
|
| 1213 |
+
class LwDetrObjectDetectionOutput(ModelOutput):
|
| 1214 |
+
r"""
|
| 1215 |
+
loss (`torch.FloatTensor` of shape `(1,)`, *optional*, returned when `labels` are provided)):
|
| 1216 |
+
Total loss as a linear combination of a negative log-likehood (cross-entropy) for class prediction and a
|
| 1217 |
+
bounding box loss. The latter is defined as a linear combination of the L1 loss and the generalized
|
| 1218 |
+
scale-invariant IoU loss.
|
| 1219 |
+
loss_dict (`Dict`, *optional*):
|
| 1220 |
+
A dictionary containing the individual losses. Useful for logging.
|
| 1221 |
+
logits (`torch.FloatTensor` of shape `(batch_size, num_queries, num_classes + 1)`):
|
| 1222 |
+
Classification logits (including no-object) for all queries.
|
| 1223 |
+
pred_boxes (`torch.FloatTensor` of shape `(batch_size, num_queries, 4)`):
|
| 1224 |
+
Normalized boxes coordinates for all queries, represented as (center_x, center_y, width, height). These
|
| 1225 |
+
values are normalized in [0, 1], relative to the size of each individual image in the batch (disregarding
|
| 1226 |
+
possible padding). You can use [`~DeformableDetrProcessor.post_process_object_detection`] to retrieve the
|
| 1227 |
+
unnormalized bounding boxes.
|
| 1228 |
+
auxiliary_outputs (`list[Dict]`, *optional*):
|
| 1229 |
+
Optional, only returned when auxiliary losses are activated (i.e. `config.auxiliary_loss` is set to `True`)
|
| 1230 |
+
and labels are provided. It is a list of dictionaries containing the two above keys (`logits` and
|
| 1231 |
+
`pred_boxes`) for each decoder layer.
|
| 1232 |
+
init_reference_points (`torch.FloatTensor` of shape `(batch_size, num_queries, 4)`):
|
| 1233 |
+
Initial reference points sent through the Transformer decoder.
|
| 1234 |
+
intermediate_hidden_states (`torch.FloatTensor` of shape `(batch_size, config.decoder_layers, num_queries, hidden_size)`):
|
| 1235 |
+
Stacked intermediate hidden states (output of each layer of the decoder).
|
| 1236 |
+
intermediate_reference_points (`torch.FloatTensor` of shape `(batch_size, config.decoder_layers, num_queries, 4)`):
|
| 1237 |
+
Stacked intermediate reference points (reference points of each layer of the decoder).
|
| 1238 |
+
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`):
|
| 1239 |
+
Predicted bounding boxes scores where the top `config.two_stage_num_proposals` scoring bounding boxes are
|
| 1240 |
+
picked as region proposals in the first stage. Output of bounding box binary classification (i.e.
|
| 1241 |
+
foreground and background).
|
| 1242 |
+
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`):
|
| 1243 |
+
Logits of predicted bounding boxes coordinates in the first stage.
|
| 1244 |
+
"""
|
| 1245 |
+
|
| 1246 |
+
loss: torch.FloatTensor | None = None
|
| 1247 |
+
loss_dict: dict | None = None
|
| 1248 |
+
logits: torch.FloatTensor | None = None
|
| 1249 |
+
pred_boxes: torch.FloatTensor | None = None
|
| 1250 |
+
auxiliary_outputs: list[dict] | None = None
|
| 1251 |
+
init_reference_points: torch.FloatTensor | None = None
|
| 1252 |
+
last_hidden_state: torch.FloatTensor | None = None
|
| 1253 |
+
intermediate_hidden_states: torch.FloatTensor | None = None
|
| 1254 |
+
intermediate_reference_points: torch.FloatTensor | None = None
|
| 1255 |
+
enc_outputs_class: Any = None
|
| 1256 |
+
enc_outputs_coord_logits: torch.FloatTensor | None = None
|
| 1257 |
+
hidden_states: tuple[torch.FloatTensor, ...] | None = None
|
| 1258 |
+
attentions: tuple[torch.FloatTensor, ...] | None = None
|
| 1259 |
+
cross_attentions: tuple[torch.FloatTensor, ...] | None = None
|
| 1260 |
+
|
| 1261 |
+
|
| 1262 |
+
@auto_docstring(
|
| 1263 |
+
custom_intro="""
|
| 1264 |
+
LW DETR Model (consisting of a backbone and decoder Transformer) with object detection heads on
|
| 1265 |
+
top, for tasks such as COCO detection.
|
| 1266 |
+
"""
|
| 1267 |
+
)
|
| 1268 |
+
class LwDetrForObjectDetection(DeformableDetrForObjectDetection):
|
| 1269 |
+
_tied_weights_keys = None
|
| 1270 |
+
|
| 1271 |
+
def __init__(self, config: LwDetrConfig):
|
| 1272 |
+
PreTrainedModel.__init__(self, config)
|
| 1273 |
+
self.model = LwDetrModel(config)
|
| 1274 |
+
self.class_embed = nn.Linear(config.d_model, config.num_labels)
|
| 1275 |
+
self.bbox_embed = LwDetrMLPPredictionHead(config.d_model, config.d_model, 4, num_layers=3)
|
| 1276 |
+
|
| 1277 |
+
self.post_init()
|
| 1278 |
+
|
| 1279 |
+
@can_return_tuple
|
| 1280 |
+
@auto_docstring
|
| 1281 |
+
def forward(
|
| 1282 |
+
self,
|
| 1283 |
+
pixel_values: torch.FloatTensor = None,
|
| 1284 |
+
pixel_mask: torch.LongTensor | None = None,
|
| 1285 |
+
labels: list[dict] | None = None,
|
| 1286 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 1287 |
+
) -> LwDetrObjectDetectionOutput:
|
| 1288 |
+
r"""
|
| 1289 |
+
labels (`list[Dict]` of len `(batch_size,)`, *optional*):
|
| 1290 |
+
Labels for computing the bipartite matching loss. List of dicts, each dictionary containing at least the
|
| 1291 |
+
following 2 keys: 'class_labels' and 'boxes' (the class labels and bounding boxes of an image in the batch
|
| 1292 |
+
respectively). The class labels themselves should be a `torch.LongTensor` of len `(number of bounding boxes
|
| 1293 |
+
in the image,)` and the boxes a `torch.FloatTensor` of shape `(number of bounding boxes in the image, 4)`.
|
| 1294 |
+
|
| 1295 |
+
Examples:
|
| 1296 |
+
|
| 1297 |
+
```python
|
| 1298 |
+
>>> from transformers import AutoImageProcessor, LwDetrForObjectDetection
|
| 1299 |
+
>>> from PIL import Image
|
| 1300 |
+
>>> import httpx
|
| 1301 |
+
>>> from io import BytesIO
|
| 1302 |
+
|
| 1303 |
+
>>> url = "http://images.cocodataset.org/val2017/000000039769.jpg"
|
| 1304 |
+
>>> with httpx.stream("GET", url) as response:
|
| 1305 |
+
... image = Image.open(BytesIO(response.read()))
|
| 1306 |
+
|
| 1307 |
+
>>> image_processor = AutoImageProcessor.from_pretrained("AnnaZhang/lwdetr_small_60e_coco")
|
| 1308 |
+
>>> model = LwDetrForObjectDetection.from_pretrained("AnnaZhang/lwdetr_small_60e_coco")
|
| 1309 |
+
|
| 1310 |
+
>>> inputs = image_processor(images=image, return_tensors="pt")
|
| 1311 |
+
>>> outputs = model(**inputs)
|
| 1312 |
+
|
| 1313 |
+
>>> # convert outputs (bounding boxes and class logits) to Pascal VOC format (xmin, ymin, xmax, ymax)
|
| 1314 |
+
>>> target_sizes = torch.tensor([image.size[::-1]])
|
| 1315 |
+
>>> results = image_processor.post_process_object_detection(outputs, threshold=0.5, target_sizes=target_sizes)[
|
| 1316 |
+
... 0
|
| 1317 |
+
... ]
|
| 1318 |
+
>>> for score, label, box in zip(results["scores"], results["labels"], results["boxes"]):
|
| 1319 |
+
... box = [round(i, 2) for i in box.tolist()]
|
| 1320 |
+
... print(
|
| 1321 |
+
... f"Detected {model.config.id2label[label.item()]} with confidence "
|
| 1322 |
+
... f"{round(score.item(), 3)} at location {box}"
|
| 1323 |
+
... )
|
| 1324 |
+
Detected cat with confidence 0.8 at location [16.5, 52.84, 318.25, 470.78]
|
| 1325 |
+
Detected cat with confidence 0.789 at location [342.19, 24.3, 640.02, 372.25]
|
| 1326 |
+
Detected remote with confidence 0.633 at location [40.79, 72.78, 176.76, 117.25]
|
| 1327 |
+
```"""
|
| 1328 |
+
outputs = self.model(
|
| 1329 |
+
pixel_values,
|
| 1330 |
+
pixel_mask=pixel_mask,
|
| 1331 |
+
**kwargs,
|
| 1332 |
+
)
|
| 1333 |
+
|
| 1334 |
+
last_hidden_states = outputs.last_hidden_state
|
| 1335 |
+
intermediate_reference_points = outputs.intermediate_reference_points
|
| 1336 |
+
enc_outputs_class_logits = outputs.enc_outputs_class
|
| 1337 |
+
enc_outputs_boxes_logits = outputs.enc_outputs_coord_logits
|
| 1338 |
+
|
| 1339 |
+
logits = self.class_embed(last_hidden_states)
|
| 1340 |
+
pred_boxes_delta = self.bbox_embed(last_hidden_states)
|
| 1341 |
+
pred_boxes = refine_bboxes(intermediate_reference_points[-1], pred_boxes_delta)
|
| 1342 |
+
|
| 1343 |
+
enc_outputs_class_logits_list = enc_outputs_class_logits.split(self.config.num_queries, dim=1)
|
| 1344 |
+
pred_class = []
|
| 1345 |
+
group_detr = self.config.group_detr if self.training else 1
|
| 1346 |
+
for group_index in range(group_detr):
|
| 1347 |
+
group_pred_class = self.model.enc_out_class_embed[group_index](enc_outputs_class_logits_list[group_index])
|
| 1348 |
+
pred_class.append(group_pred_class)
|
| 1349 |
+
enc_outputs_class_logits = torch.cat(pred_class, dim=1)
|
| 1350 |
+
|
| 1351 |
+
loss, loss_dict, auxiliary_outputs = None, None, None
|
| 1352 |
+
if labels is not None:
|
| 1353 |
+
outputs_class, outputs_coord = None, None
|
| 1354 |
+
if self.config.auxiliary_loss:
|
| 1355 |
+
intermediate_hidden_states = outputs.intermediate_hidden_states
|
| 1356 |
+
outputs_coord_delta = self.bbox_embed(intermediate_hidden_states)
|
| 1357 |
+
outputs_coord = refine_bboxes(intermediate_reference_points, outputs_coord_delta)
|
| 1358 |
+
outputs_class = self.class_embed(intermediate_hidden_states)
|
| 1359 |
+
|
| 1360 |
+
loss, loss_dict, auxiliary_outputs = self.loss_function(
|
| 1361 |
+
logits,
|
| 1362 |
+
labels,
|
| 1363 |
+
self.device,
|
| 1364 |
+
pred_boxes,
|
| 1365 |
+
self.config,
|
| 1366 |
+
outputs_class,
|
| 1367 |
+
outputs_coord,
|
| 1368 |
+
enc_outputs_class_logits,
|
| 1369 |
+
enc_outputs_boxes_logits,
|
| 1370 |
+
)
|
| 1371 |
+
|
| 1372 |
+
return LwDetrObjectDetectionOutput(
|
| 1373 |
+
loss=loss,
|
| 1374 |
+
loss_dict=loss_dict,
|
| 1375 |
+
logits=logits,
|
| 1376 |
+
pred_boxes=pred_boxes,
|
| 1377 |
+
auxiliary_outputs=auxiliary_outputs,
|
| 1378 |
+
last_hidden_state=outputs.last_hidden_state,
|
| 1379 |
+
intermediate_hidden_states=outputs.intermediate_hidden_states,
|
| 1380 |
+
intermediate_reference_points=outputs.intermediate_reference_points,
|
| 1381 |
+
init_reference_points=outputs.init_reference_points,
|
| 1382 |
+
enc_outputs_class=enc_outputs_class_logits,
|
| 1383 |
+
enc_outputs_coord_logits=enc_outputs_boxes_logits,
|
| 1384 |
+
hidden_states=outputs.hidden_states,
|
| 1385 |
+
attentions=outputs.attentions,
|
| 1386 |
+
cross_attentions=outputs.cross_attentions,
|
| 1387 |
+
)
|
| 1388 |
+
|
| 1389 |
+
|
| 1390 |
+
__all__ = [
|
| 1391 |
+
"LwDetrConfig",
|
| 1392 |
+
"LwDetrPreTrainedModel",
|
| 1393 |
+
"LwDetrModel",
|
| 1394 |
+
"LwDetrForObjectDetection",
|
| 1395 |
+
"LwDetrViTConfig",
|
| 1396 |
+
"LwDetrViTPreTrainedModel",
|
| 1397 |
+
"LwDetrViTBackbone",
|
| 1398 |
+
]
|
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/models/modernbert/__init__.py
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
+
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_modernbert import *
|
| 22 |
+
from .modeling_modernbert import *
|
| 23 |
+
else:
|
| 24 |
+
import sys
|
| 25 |
+
|
| 26 |
+
_file = globals()["__file__"]
|
| 27 |
+
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/patchtst/__init__.py
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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_patchtst import *
|
| 22 |
+
from .modeling_patchtst import *
|
| 23 |
+
else:
|
| 24 |
+
import sys
|
| 25 |
+
|
| 26 |
+
_file = globals()["__file__"]
|
| 27 |
+
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/patchtst/configuration_patchtst.py
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2023 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 |
+
"""PatchTST model configuration"""
|
| 15 |
+
|
| 16 |
+
from huggingface_hub.dataclasses import strict
|
| 17 |
+
|
| 18 |
+
from transformers.configuration_utils import PreTrainedConfig
|
| 19 |
+
from transformers.utils import auto_docstring
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
@auto_docstring(checkpoint="ibm-granite/granite-timeseries-patchtst")
|
| 23 |
+
@strict
|
| 24 |
+
class PatchTSTConfig(PreTrainedConfig):
|
| 25 |
+
r"""
|
| 26 |
+
context_length (`int`, *optional*, defaults to 32):
|
| 27 |
+
The context length of the input sequence.
|
| 28 |
+
distribution_output (`str`, *optional*, defaults to `"student_t"`):
|
| 29 |
+
The distribution emission head for the model when loss is "nll". Could be either "student_t", "normal" or
|
| 30 |
+
"negative_binomial".
|
| 31 |
+
loss (`str`, *optional*, defaults to `"mse"`):
|
| 32 |
+
The loss function for the model corresponding to the `distribution_output` head. For parametric
|
| 33 |
+
distributions it is the negative log likelihood ("nll") and for point estimates it is the mean squared
|
| 34 |
+
error "mse".
|
| 35 |
+
patch_length (`int`, *optional*, defaults to 1):
|
| 36 |
+
Define the patch length of the patchification process.
|
| 37 |
+
patch_stride (`int`, *optional*, defaults to 1):
|
| 38 |
+
Define the stride of the patchification process.
|
| 39 |
+
num_attention_heads (`int`, *optional*, defaults to 4):
|
| 40 |
+
Number of attention heads for each attention layer in the Transformer encoder.
|
| 41 |
+
share_embedding (`bool`, *optional*, defaults to `True`):
|
| 42 |
+
Sharing the input embedding across all channels.
|
| 43 |
+
channel_attention (`bool`, *optional*, defaults to `False`):
|
| 44 |
+
Activate channel attention block in the Transformer to allow channels to attend each other.
|
| 45 |
+
ffn_dim (`int`, *optional*, defaults to 512):
|
| 46 |
+
Dimension of the "intermediate" (often named feed-forward) layer in the Transformer encoder.
|
| 47 |
+
norm_type (`str` , *optional*, defaults to `"batchnorm"`):
|
| 48 |
+
Normalization at each Transformer layer. Can be `"batchnorm"` or `"layernorm"`.
|
| 49 |
+
norm_eps (`float`, *optional*, defaults to 1e-05):
|
| 50 |
+
A value added to the denominator for numerical stability of normalization.
|
| 51 |
+
positional_dropout (`float`, *optional*, defaults to 0.0):
|
| 52 |
+
The dropout probability in the positional embedding layer.
|
| 53 |
+
path_dropout (`float`, *optional*, defaults to 0.0):
|
| 54 |
+
The dropout path in the residual block.
|
| 55 |
+
ff_dropout (`float`, *optional*, defaults to 0.0):
|
| 56 |
+
The dropout probability used between the two layers of the feed-forward networks.
|
| 57 |
+
bias (`bool`, *optional*, defaults to `True`):
|
| 58 |
+
Whether to add bias in the feed-forward networks.
|
| 59 |
+
activation_function (`str`, *optional*, defaults to `"gelu"`):
|
| 60 |
+
The non-linear activation function (string) in the Transformer.`"gelu"` and `"relu"` are supported.
|
| 61 |
+
pre_norm (`bool`, *optional*, defaults to `True`):
|
| 62 |
+
Normalization is applied before self-attention if pre_norm is set to `True`. Otherwise, normalization is
|
| 63 |
+
applied after residual block.
|
| 64 |
+
positional_encoding_type (`str`, *optional*, defaults to `"sincos"`):
|
| 65 |
+
Positional encodings. Options `"random"` and `"sincos"` are supported.
|
| 66 |
+
use_cls_token (`bool`, *optional*, defaults to `False`):
|
| 67 |
+
Whether cls token is used.
|
| 68 |
+
init_std (`float`, *optional*, defaults to 0.02):
|
| 69 |
+
The standard deviation of the truncated normal weight initialization distribution.
|
| 70 |
+
share_projection (`bool`, *optional*, defaults to `True`):
|
| 71 |
+
Sharing the projection layer across different channels in the forecast head.
|
| 72 |
+
scaling (`Union`, *optional*, defaults to `"std"`):
|
| 73 |
+
Whether to scale the input targets via "mean" scaler, "std" scaler or no scaler if `None`. If `True`, the
|
| 74 |
+
scaler is set to "mean".
|
| 75 |
+
do_mask_input (`bool`, *optional*):
|
| 76 |
+
Apply masking during the pretraining.
|
| 77 |
+
mask_type (`str`, *optional*, defaults to `"random"`):
|
| 78 |
+
Masking type. Only `"random"` and `"forecast"` are currently supported.
|
| 79 |
+
random_mask_ratio (`float`, *optional*, defaults to 0.5):
|
| 80 |
+
Masking ratio applied to mask the input data during random pretraining.
|
| 81 |
+
num_forecast_mask_patches (`int` or `list`, *optional*, defaults to `[2]`):
|
| 82 |
+
Number of patches to be masked at the end of each batch sample. If it is an integer,
|
| 83 |
+
all the samples in the batch will have the same number of masked patches. If it is a list,
|
| 84 |
+
samples in the batch will be randomly masked by numbers defined in the list. This argument is only used
|
| 85 |
+
for forecast pretraining.
|
| 86 |
+
channel_consistent_masking (`bool`, *optional*, defaults to `False`):
|
| 87 |
+
If channel consistent masking is True, all the channels will have the same masking pattern.
|
| 88 |
+
unmasked_channel_indices (`list`, *optional*):
|
| 89 |
+
Indices of channels that are not masked during pretraining. Values in the list are number between 1 and
|
| 90 |
+
`num_input_channels`
|
| 91 |
+
mask_value (`int`, *optional*, defaults to 0):
|
| 92 |
+
Values in the masked patches will be filled by `mask_value`.
|
| 93 |
+
pooling_type (`str`, *optional*, defaults to `"mean"`):
|
| 94 |
+
Pooling of the embedding. `"mean"`, `"max"` and `None` are supported.
|
| 95 |
+
head_dropout (`float`, *optional*, defaults to 0.0):
|
| 96 |
+
The dropout probability for head.
|
| 97 |
+
prediction_length (`int`, *optional*, defaults to 24):
|
| 98 |
+
The prediction horizon that the model will output.
|
| 99 |
+
num_targets (`int`, *optional*, defaults to 1):
|
| 100 |
+
Number of targets for regression and classification tasks. For classification, it is the number of
|
| 101 |
+
classes.
|
| 102 |
+
output_range (`list`, *optional*):
|
| 103 |
+
Output range for regression task. The range of output values can be set to enforce the model to produce
|
| 104 |
+
values within a range.
|
| 105 |
+
num_parallel_samples (`int`, *optional*, defaults to 100):
|
| 106 |
+
The number of samples is generated in parallel for probabilistic prediction.
|
| 107 |
+
|
| 108 |
+
```python
|
| 109 |
+
>>> from transformers import PatchTSTConfig, PatchTSTModel
|
| 110 |
+
|
| 111 |
+
>>> # Initializing an PatchTST configuration with 12 time steps for prediction
|
| 112 |
+
>>> configuration = PatchTSTConfig(prediction_length=12)
|
| 113 |
+
|
| 114 |
+
>>> # Randomly initializing a model (with random weights) from the configuration
|
| 115 |
+
>>> model = PatchTSTModel(configuration)
|
| 116 |
+
|
| 117 |
+
>>> # Accessing the model configuration
|
| 118 |
+
>>> configuration = model.config
|
| 119 |
+
```
|
| 120 |
+
"""
|
| 121 |
+
|
| 122 |
+
model_type = "patchtst"
|
| 123 |
+
attribute_map = {
|
| 124 |
+
"hidden_size": "d_model",
|
| 125 |
+
"num_attention_heads": "num_attention_heads",
|
| 126 |
+
"num_hidden_layers": "num_hidden_layers",
|
| 127 |
+
}
|
| 128 |
+
|
| 129 |
+
num_input_channels: int = 1
|
| 130 |
+
context_length: int = 32
|
| 131 |
+
distribution_output: str = "student_t"
|
| 132 |
+
loss: str | None = "mse"
|
| 133 |
+
patch_length: int = 1
|
| 134 |
+
patch_stride: int = 1
|
| 135 |
+
num_hidden_layers: int = 3
|
| 136 |
+
d_model: int = 128
|
| 137 |
+
num_attention_heads: int = 4
|
| 138 |
+
share_embedding: bool = True
|
| 139 |
+
channel_attention: bool = False
|
| 140 |
+
ffn_dim: int = 512
|
| 141 |
+
norm_type: str = "batchnorm"
|
| 142 |
+
norm_eps: float = 1e-05
|
| 143 |
+
attention_dropout: float | int = 0.0
|
| 144 |
+
positional_dropout: float | int = 0.0
|
| 145 |
+
path_dropout: float | int = 0.0
|
| 146 |
+
ff_dropout: float | int = 0.0
|
| 147 |
+
bias: bool = True
|
| 148 |
+
activation_function: str = "gelu"
|
| 149 |
+
pre_norm: bool = True
|
| 150 |
+
positional_encoding_type: str = "sincos"
|
| 151 |
+
use_cls_token: bool = False
|
| 152 |
+
init_std: float = 0.02
|
| 153 |
+
share_projection: bool = True
|
| 154 |
+
scaling: str | bool | None = "std"
|
| 155 |
+
do_mask_input: bool | None = None
|
| 156 |
+
mask_type: str = "random"
|
| 157 |
+
random_mask_ratio: float = 0.5
|
| 158 |
+
num_forecast_mask_patches: list[int] | tuple[int, ...] | int | None = (2,)
|
| 159 |
+
channel_consistent_masking: bool | None = False
|
| 160 |
+
unmasked_channel_indices: list[int] | None = None
|
| 161 |
+
mask_value: int = 0
|
| 162 |
+
pooling_type: str | None = "mean"
|
| 163 |
+
head_dropout: float | int = 0.0
|
| 164 |
+
prediction_length: int = 24
|
| 165 |
+
num_targets: int = 1
|
| 166 |
+
output_range: list | None = None
|
| 167 |
+
num_parallel_samples: int = 100
|
| 168 |
+
|
| 169 |
+
|
| 170 |
+
__all__ = ["PatchTSTConfig"]
|
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/models/patchtst/modeling_patchtst.py
ADDED
|
@@ -0,0 +1,1973 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2023 IBM & Hugging Face. 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 |
+
"""PyTorch PatchTST model."""
|
| 15 |
+
|
| 16 |
+
import math
|
| 17 |
+
from collections.abc import Callable
|
| 18 |
+
from dataclasses import dataclass
|
| 19 |
+
|
| 20 |
+
import torch
|
| 21 |
+
from torch import nn
|
| 22 |
+
|
| 23 |
+
from ... import initialization as init
|
| 24 |
+
from ...activations import ACT2CLS
|
| 25 |
+
from ...integrations.deepspeed import is_deepspeed_zero3_enabled
|
| 26 |
+
from ...modeling_flash_attention_utils import FlashAttentionKwargs
|
| 27 |
+
from ...modeling_outputs import BaseModelOutput
|
| 28 |
+
from ...modeling_utils import ALL_ATTENTION_FUNCTIONS, PreTrainedModel
|
| 29 |
+
from ...processing_utils import Unpack
|
| 30 |
+
from ...time_series_utils import NegativeBinomialOutput, NormalOutput, StudentTOutput
|
| 31 |
+
from ...utils import ModelOutput, TransformersKwargs, auto_docstring, logging
|
| 32 |
+
from .configuration_patchtst import PatchTSTConfig
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
logger = logging.get_logger(__name__)
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
# Copied from transformers.models.bert.modeling_bert.eager_attention_forward
|
| 39 |
+
def eager_attention_forward(
|
| 40 |
+
module: nn.Module,
|
| 41 |
+
query: torch.Tensor,
|
| 42 |
+
key: torch.Tensor,
|
| 43 |
+
value: torch.Tensor,
|
| 44 |
+
attention_mask: torch.Tensor | None,
|
| 45 |
+
scaling: float | None = None,
|
| 46 |
+
dropout: float = 0.0,
|
| 47 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 48 |
+
):
|
| 49 |
+
if scaling is None:
|
| 50 |
+
scaling = query.size(-1) ** -0.5
|
| 51 |
+
|
| 52 |
+
# Take the dot product between "query" and "key" to get the raw attention scores.
|
| 53 |
+
attn_weights = torch.matmul(query, key.transpose(2, 3)) * scaling
|
| 54 |
+
|
| 55 |
+
if attention_mask is not None:
|
| 56 |
+
attn_weights = attn_weights + attention_mask
|
| 57 |
+
|
| 58 |
+
attn_weights = nn.functional.softmax(attn_weights, dim=-1)
|
| 59 |
+
attn_weights = nn.functional.dropout(attn_weights, p=dropout, training=module.training)
|
| 60 |
+
|
| 61 |
+
attn_output = torch.matmul(attn_weights, value)
|
| 62 |
+
attn_output = attn_output.transpose(1, 2).contiguous()
|
| 63 |
+
|
| 64 |
+
return attn_output, attn_weights
|
| 65 |
+
|
| 66 |
+
|
| 67 |
+
# Copied from transformers.models.wav2vec2.modeling_wav2vec2.Wav2Vec2Attention with Wav2Vec2->PatchTST
|
| 68 |
+
class PatchTSTAttention(nn.Module):
|
| 69 |
+
"""Multi-headed attention from 'Attention Is All You Need' paper"""
|
| 70 |
+
|
| 71 |
+
def __init__(
|
| 72 |
+
self,
|
| 73 |
+
embed_dim: int,
|
| 74 |
+
num_heads: int,
|
| 75 |
+
dropout: float = 0.0,
|
| 76 |
+
is_decoder: bool = False,
|
| 77 |
+
bias: bool = True,
|
| 78 |
+
is_causal: bool = False,
|
| 79 |
+
config: PatchTSTConfig | None = None,
|
| 80 |
+
):
|
| 81 |
+
super().__init__()
|
| 82 |
+
self.embed_dim = embed_dim
|
| 83 |
+
self.num_heads = num_heads
|
| 84 |
+
self.dropout = dropout
|
| 85 |
+
self.head_dim = embed_dim // num_heads
|
| 86 |
+
self.config = config
|
| 87 |
+
|
| 88 |
+
if (self.head_dim * num_heads) != self.embed_dim:
|
| 89 |
+
raise ValueError(
|
| 90 |
+
f"embed_dim must be divisible by num_heads (got `embed_dim`: {self.embed_dim}"
|
| 91 |
+
f" and `num_heads`: {num_heads})."
|
| 92 |
+
)
|
| 93 |
+
self.scaling = self.head_dim**-0.5
|
| 94 |
+
self.is_decoder = is_decoder
|
| 95 |
+
self.is_causal = is_causal
|
| 96 |
+
|
| 97 |
+
self.k_proj = nn.Linear(embed_dim, embed_dim, bias=bias)
|
| 98 |
+
self.v_proj = nn.Linear(embed_dim, embed_dim, bias=bias)
|
| 99 |
+
self.q_proj = nn.Linear(embed_dim, embed_dim, bias=bias)
|
| 100 |
+
self.out_proj = nn.Linear(embed_dim, embed_dim, bias=bias)
|
| 101 |
+
|
| 102 |
+
def forward(
|
| 103 |
+
self,
|
| 104 |
+
hidden_states: torch.Tensor,
|
| 105 |
+
key_value_states: torch.Tensor | None = None,
|
| 106 |
+
attention_mask: torch.Tensor | None = None,
|
| 107 |
+
output_attentions: bool | None = False,
|
| 108 |
+
# TODO: we need a refactor so that the different attention modules can get their specific kwargs
|
| 109 |
+
# ATM, we have mixed things encoder, decoder, and encoder-decoder attn
|
| 110 |
+
**kwargs: Unpack[FlashAttentionKwargs],
|
| 111 |
+
) -> tuple[torch.Tensor, torch.Tensor | None, tuple[torch.Tensor] | None]:
|
| 112 |
+
"""Input shape: Batch x Time x Channel"""
|
| 113 |
+
|
| 114 |
+
# if key_value_states are provided this layer is used as a cross-attention layer
|
| 115 |
+
# for the decoder
|
| 116 |
+
is_cross_attention = key_value_states is not None
|
| 117 |
+
|
| 118 |
+
# determine input shapes
|
| 119 |
+
input_shape = hidden_states.shape[:-1]
|
| 120 |
+
|
| 121 |
+
hidden_shape = (*input_shape, -1, self.head_dim)
|
| 122 |
+
|
| 123 |
+
# get query proj
|
| 124 |
+
query_states = self.q_proj(hidden_states).view(hidden_shape).transpose(1, 2)
|
| 125 |
+
|
| 126 |
+
current_states = key_value_states if is_cross_attention else hidden_states
|
| 127 |
+
kv_shape = (*current_states.shape[:-1], -1, self.head_dim)
|
| 128 |
+
key_states = self.k_proj(current_states).view(kv_shape).transpose(1, 2)
|
| 129 |
+
value_states = self.v_proj(current_states).view(kv_shape).transpose(1, 2)
|
| 130 |
+
|
| 131 |
+
attention_interface: Callable = ALL_ATTENTION_FUNCTIONS.get_interface(
|
| 132 |
+
self.config._attn_implementation, eager_attention_forward
|
| 133 |
+
)
|
| 134 |
+
|
| 135 |
+
attn_output, attn_weights = attention_interface(
|
| 136 |
+
self,
|
| 137 |
+
query_states,
|
| 138 |
+
key_states,
|
| 139 |
+
value_states,
|
| 140 |
+
attention_mask,
|
| 141 |
+
dropout=0.0 if not self.training else self.dropout,
|
| 142 |
+
scaling=self.scaling,
|
| 143 |
+
output_attentions=output_attentions,
|
| 144 |
+
**kwargs,
|
| 145 |
+
)
|
| 146 |
+
|
| 147 |
+
attn_output = attn_output.reshape(*input_shape, -1).contiguous()
|
| 148 |
+
attn_output = self.out_proj(attn_output)
|
| 149 |
+
|
| 150 |
+
return attn_output, attn_weights, None
|
| 151 |
+
|
| 152 |
+
|
| 153 |
+
class PatchTSTBatchNorm(nn.Module):
|
| 154 |
+
"""
|
| 155 |
+
Compute batch normalization over the sequence length (time) dimension.
|
| 156 |
+
"""
|
| 157 |
+
|
| 158 |
+
def __init__(self, config: PatchTSTConfig):
|
| 159 |
+
super().__init__()
|
| 160 |
+
self.batchnorm = nn.BatchNorm1d(config.d_model, eps=config.norm_eps)
|
| 161 |
+
|
| 162 |
+
def forward(self, inputs: torch.Tensor):
|
| 163 |
+
"""
|
| 164 |
+
Parameters:
|
| 165 |
+
inputs (`torch.Tensor` of shape `(batch_size, sequence_length, d_model)`):
|
| 166 |
+
input for Batch norm calculation
|
| 167 |
+
Returns:
|
| 168 |
+
`torch.Tensor` of shape `(batch_size, sequence_length, d_model)`
|
| 169 |
+
"""
|
| 170 |
+
output = inputs.transpose(1, 2) # output: (batch_size, d_model, sequence_length)
|
| 171 |
+
output = self.batchnorm(output)
|
| 172 |
+
return output.transpose(1, 2)
|
| 173 |
+
|
| 174 |
+
|
| 175 |
+
def random_masking(
|
| 176 |
+
inputs: torch.Tensor,
|
| 177 |
+
mask_ratio: float,
|
| 178 |
+
unmasked_channel_indices: list | None = None,
|
| 179 |
+
channel_consistent_masking: bool = False,
|
| 180 |
+
mask_value: int = 0,
|
| 181 |
+
):
|
| 182 |
+
"""random_masking: Mask the input considering the control variables.
|
| 183 |
+
|
| 184 |
+
Args:
|
| 185 |
+
inputs (`torch.Tensor` of shape `(batch_size, num_channels, sequence_length, num_features)`):
|
| 186 |
+
The input tensor to mask.
|
| 187 |
+
mask_ratio (`float`):
|
| 188 |
+
Masking ratio applied to mask the input data during random pretraining. It is the number between 0 and 1.
|
| 189 |
+
unmasked_channel_indices (list, *optional*):
|
| 190 |
+
Indices of channels that will not be masked.
|
| 191 |
+
channel_consistent_masking (bool, *optional*, defaults to `False`):
|
| 192 |
+
When true, masking will be same across all channels of a timeseries. Otherwise, masking positions will vary
|
| 193 |
+
across channels.
|
| 194 |
+
mask_value (int, *optional*, defaults to 0):
|
| 195 |
+
Define the value of masked patches for pretraining.
|
| 196 |
+
|
| 197 |
+
Returns:
|
| 198 |
+
`tuple(torch.Tensor)`: inputs_mask, masked input, same shape as input Tensor and mask tensor of shape [bs x c x
|
| 199 |
+
n]
|
| 200 |
+
"""
|
| 201 |
+
if mask_ratio < 0 or mask_ratio >= 1:
|
| 202 |
+
raise ValueError(f"Mask ratio {mask_ratio} has to be between 0 and 1.")
|
| 203 |
+
|
| 204 |
+
batch_size, num_channels, sequence_length, num_features = inputs.shape
|
| 205 |
+
device = inputs.device
|
| 206 |
+
|
| 207 |
+
len_keep = int(sequence_length * (1 - mask_ratio))
|
| 208 |
+
|
| 209 |
+
if channel_consistent_masking:
|
| 210 |
+
noise = torch.rand(batch_size, 1, sequence_length, device=device) # noise in [0, 1], bs x 1 x L
|
| 211 |
+
noise = noise.repeat(1, num_channels, 1) # bs x num_channels x time
|
| 212 |
+
else:
|
| 213 |
+
# noise in [0, 1], bs x num_channels x L
|
| 214 |
+
noise = torch.rand(batch_size, num_channels, sequence_length, device=device)
|
| 215 |
+
|
| 216 |
+
# mask: [bs x num_channels x num_patch]
|
| 217 |
+
mask = torch.ones(batch_size, num_channels, sequence_length, device=device)
|
| 218 |
+
mask[:, :, :len_keep] = 0
|
| 219 |
+
|
| 220 |
+
# sort noise for each sample
|
| 221 |
+
ids_shuffle = torch.argsort(noise, dim=-1) # ascend: small is keep, large is remove
|
| 222 |
+
ids_restore = torch.argsort(ids_shuffle, dim=-1) # ids_restore: [bs x num_channels x L]
|
| 223 |
+
|
| 224 |
+
mask = torch.gather(mask, dim=-1, index=ids_restore)
|
| 225 |
+
mask = mask.unsqueeze(-1).repeat(1, 1, 1, num_features) # mask: [bs x num_channels x num_patches x patch_length]
|
| 226 |
+
if unmasked_channel_indices is not None:
|
| 227 |
+
mask[:, unmasked_channel_indices, :, :] = 0
|
| 228 |
+
|
| 229 |
+
inputs_mask = inputs.masked_fill(mask.bool(), mask_value)
|
| 230 |
+
return inputs_mask, mask[..., 0]
|
| 231 |
+
|
| 232 |
+
|
| 233 |
+
def forecast_masking(
|
| 234 |
+
inputs: torch.Tensor,
|
| 235 |
+
num_forecast_mask_patches: list | int,
|
| 236 |
+
unmasked_channel_indices: list | None = None,
|
| 237 |
+
mask_value: int = 0,
|
| 238 |
+
):
|
| 239 |
+
"""Forecast masking that masks the last K patches where K is from the num_forecast_mask_patches.
|
| 240 |
+
If num_forecast_mask_patches is a list, samples in the batch will be randomly masked by numbers defined in the list.
|
| 241 |
+
|
| 242 |
+
Parameters:
|
| 243 |
+
inputs (`torch.Tensor`):
|
| 244 |
+
Input of shape `(bs, num_channels, num_patch, patch_length)`
|
| 245 |
+
num_forecast_mask_patches (`list`):
|
| 246 |
+
Number of patches to be masked at the end of each batch sample. e.g. 4 or [3, 5].
|
| 247 |
+
unmasked_channel_indices (`list`, *optional*):
|
| 248 |
+
Indices of channels that are not masked.
|
| 249 |
+
mask_value (`int`, *optional*, defaults to 0):
|
| 250 |
+
Values in the masked patches will be filled by `mask_value`.
|
| 251 |
+
|
| 252 |
+
Returns:
|
| 253 |
+
`tuple(torch.Tensor)`: inputs_mask, masked input, same shape as inputs Tensor and Mask tensor of shape `(bs,
|
| 254 |
+
num_channels , num_patch)` or `(bs, tsg1, tsg2, num_channels, num_patch)`
|
| 255 |
+
"""
|
| 256 |
+
|
| 257 |
+
if isinstance(num_forecast_mask_patches, int):
|
| 258 |
+
num_forecast_mask_patches = [num_forecast_mask_patches]
|
| 259 |
+
forecast_mask_ratios = [1 for _ in num_forecast_mask_patches]
|
| 260 |
+
|
| 261 |
+
batch_size, num_channels, sequence_length, num_features = inputs.shape
|
| 262 |
+
mask = torch.zeros(batch_size, num_channels, sequence_length, device=inputs.device)
|
| 263 |
+
|
| 264 |
+
t_list = []
|
| 265 |
+
total_length = 0
|
| 266 |
+
total_ratio = sum(forecast_mask_ratios)
|
| 267 |
+
|
| 268 |
+
for patch_length, ratio in zip(num_forecast_mask_patches, forecast_mask_ratios):
|
| 269 |
+
if patch_length <= 0 or patch_length >= sequence_length:
|
| 270 |
+
raise ValueError(
|
| 271 |
+
f"num_forecast_mask_patches {patch_length} should be greater than 0 and less than total patches."
|
| 272 |
+
)
|
| 273 |
+
temp_len = int(batch_size * ratio / total_ratio)
|
| 274 |
+
t_list.append([patch_length, ratio, temp_len])
|
| 275 |
+
total_length += temp_len
|
| 276 |
+
|
| 277 |
+
t_list = sorted(t_list, key=lambda x: x[2])
|
| 278 |
+
|
| 279 |
+
if total_length < batch_size:
|
| 280 |
+
t_list[0][2] = t_list[0][2] + (batch_size - total_length)
|
| 281 |
+
elif total_length > batch_size:
|
| 282 |
+
t_list[-1][2] = t_list[-1][2] + (total_length - batch_size)
|
| 283 |
+
|
| 284 |
+
batch1 = 0
|
| 285 |
+
for patch_len, _, temp_len in t_list:
|
| 286 |
+
batch2 = batch1 + temp_len
|
| 287 |
+
mask[batch1:batch2, :, -patch_len:] = 1
|
| 288 |
+
batch1 = batch2
|
| 289 |
+
|
| 290 |
+
perm = torch.randperm(mask.shape[0])
|
| 291 |
+
mask = mask[perm]
|
| 292 |
+
|
| 293 |
+
mask = mask.unsqueeze(-1).repeat(1, 1, 1, num_features) # mask: [bs x num_channels x num_patch x patch_len]
|
| 294 |
+
if unmasked_channel_indices is not None:
|
| 295 |
+
mask[:, unmasked_channel_indices, :, :] = 0
|
| 296 |
+
|
| 297 |
+
inputs_mask = inputs.masked_fill(mask.bool(), mask_value)
|
| 298 |
+
return inputs_mask, mask[..., 0]
|
| 299 |
+
|
| 300 |
+
|
| 301 |
+
class PatchTSTPatchify(nn.Module):
|
| 302 |
+
"""
|
| 303 |
+
A class to patchify the time series sequence into different patches
|
| 304 |
+
|
| 305 |
+
Returns:
|
| 306 |
+
`torch.Tensor` of shape `(batch_size, num_channels, num_patches, patch_length)`
|
| 307 |
+
"""
|
| 308 |
+
|
| 309 |
+
def __init__(self, config: PatchTSTConfig):
|
| 310 |
+
super().__init__()
|
| 311 |
+
|
| 312 |
+
self.sequence_length = config.context_length
|
| 313 |
+
self.patch_length = config.patch_length
|
| 314 |
+
self.patch_stride = config.patch_stride
|
| 315 |
+
|
| 316 |
+
if self.sequence_length <= self.patch_length:
|
| 317 |
+
raise ValueError(
|
| 318 |
+
f"Sequence length ({self.sequence_length}) has to be greater than the patch length ({self.patch_length})"
|
| 319 |
+
)
|
| 320 |
+
|
| 321 |
+
# get the number of patches
|
| 322 |
+
self.num_patches = (max(self.sequence_length, self.patch_length) - self.patch_length) // self.patch_stride + 1
|
| 323 |
+
new_sequence_length = self.patch_length + self.patch_stride * (self.num_patches - 1)
|
| 324 |
+
self.sequence_start = self.sequence_length - new_sequence_length
|
| 325 |
+
|
| 326 |
+
def forward(self, past_values: torch.Tensor):
|
| 327 |
+
"""
|
| 328 |
+
Parameters:
|
| 329 |
+
past_values (`torch.Tensor` of shape `(batch_size, sequence_length, num_channels)`, *required*):
|
| 330 |
+
Input for patchification
|
| 331 |
+
|
| 332 |
+
Returns:
|
| 333 |
+
`torch.Tensor` of shape `(batch_size, num_channels, num_patches, patch_length)`
|
| 334 |
+
"""
|
| 335 |
+
sequence_length = past_values.shape[-2]
|
| 336 |
+
if sequence_length != self.sequence_length:
|
| 337 |
+
raise ValueError(
|
| 338 |
+
f"Input sequence length ({sequence_length}) doesn't match model configuration ({self.sequence_length})."
|
| 339 |
+
)
|
| 340 |
+
# output: [bs x new_sequence_length x num_channels]
|
| 341 |
+
output = past_values[:, self.sequence_start :, :]
|
| 342 |
+
# output: [bs x num_patches x num_input_channels x patch_length]
|
| 343 |
+
output = output.unfold(dimension=-2, size=self.patch_length, step=self.patch_stride)
|
| 344 |
+
# output: [bs x num_input_channels x num_patches x patch_length]
|
| 345 |
+
output = output.transpose(-2, -3).contiguous()
|
| 346 |
+
return output
|
| 347 |
+
|
| 348 |
+
|
| 349 |
+
class PatchTSTMasking(nn.Module):
|
| 350 |
+
"""
|
| 351 |
+
Class to perform random or forecast masking.
|
| 352 |
+
|
| 353 |
+
Parameters:
|
| 354 |
+
config (`PatchTSTConfig`): model config
|
| 355 |
+
Returns:
|
| 356 |
+
x_mask (`torch.Tensor` of shape `(batch_size, num_channels, num_patches, patch_length)`)
|
| 357 |
+
Masked patched input
|
| 358 |
+
mask (`torch.Tensor` of shape `(batch_size, num_channels, num_patches)`)
|
| 359 |
+
Bool tensor indicating True on masked points
|
| 360 |
+
"""
|
| 361 |
+
|
| 362 |
+
def __init__(self, config: PatchTSTConfig):
|
| 363 |
+
super().__init__()
|
| 364 |
+
self.random_mask_ratio = config.random_mask_ratio
|
| 365 |
+
self.channel_consistent_masking = config.channel_consistent_masking
|
| 366 |
+
self.mask_type = config.mask_type
|
| 367 |
+
self.num_forecast_mask_patches = config.num_forecast_mask_patches
|
| 368 |
+
self.unmasked_channel_indices = config.unmasked_channel_indices
|
| 369 |
+
self.mask_value = config.mask_value
|
| 370 |
+
if self.unmasked_channel_indices is not None:
|
| 371 |
+
self.unmasked_channel_indices = sorted(self.unmasked_channel_indices)
|
| 372 |
+
|
| 373 |
+
def forward(self, patch_input: torch.Tensor):
|
| 374 |
+
"""
|
| 375 |
+
Parameters:
|
| 376 |
+
patch_input (`torch.Tensor` of shape `(batch_size, num_channels, num_patches, patch_length)`, *required*):
|
| 377 |
+
Patch input
|
| 378 |
+
|
| 379 |
+
Return:
|
| 380 |
+
masked_input (`torch.Tensor` of shape `(batch_size, num_channels, num_patches, patch_length)`)
|
| 381 |
+
Masked patched input
|
| 382 |
+
mask (`torch.Tensor` of shape `(batch_size, num_channels, num_patches)`)
|
| 383 |
+
Bool tensor indicating True on masked points
|
| 384 |
+
|
| 385 |
+
"""
|
| 386 |
+
if self.mask_type == "random":
|
| 387 |
+
masked_input, mask = random_masking(
|
| 388 |
+
inputs=patch_input,
|
| 389 |
+
mask_ratio=self.random_mask_ratio,
|
| 390 |
+
unmasked_channel_indices=self.unmasked_channel_indices,
|
| 391 |
+
channel_consistent_masking=self.channel_consistent_masking,
|
| 392 |
+
mask_value=self.mask_value,
|
| 393 |
+
)
|
| 394 |
+
elif self.mask_type == "forecast":
|
| 395 |
+
masked_input, mask = forecast_masking(
|
| 396 |
+
inputs=patch_input,
|
| 397 |
+
num_forecast_mask_patches=self.num_forecast_mask_patches,
|
| 398 |
+
unmasked_channel_indices=self.unmasked_channel_indices,
|
| 399 |
+
mask_value=self.mask_value,
|
| 400 |
+
)
|
| 401 |
+
else:
|
| 402 |
+
raise ValueError(f"Invalid mask type {self.mask_type}.")
|
| 403 |
+
|
| 404 |
+
# mask: [bs x num_input_channels x num_patch]
|
| 405 |
+
mask = mask.bool()
|
| 406 |
+
return masked_input, mask
|
| 407 |
+
|
| 408 |
+
|
| 409 |
+
class PatchTSTEncoderLayer(nn.Module):
|
| 410 |
+
"""
|
| 411 |
+
PatchTST encoder layer
|
| 412 |
+
"""
|
| 413 |
+
|
| 414 |
+
def __init__(self, config: PatchTSTConfig):
|
| 415 |
+
super().__init__()
|
| 416 |
+
|
| 417 |
+
self.channel_attention = config.channel_attention
|
| 418 |
+
|
| 419 |
+
self.self_attn = PatchTSTAttention(
|
| 420 |
+
embed_dim=config.d_model,
|
| 421 |
+
num_heads=config.num_attention_heads,
|
| 422 |
+
dropout=config.attention_dropout,
|
| 423 |
+
config=config,
|
| 424 |
+
)
|
| 425 |
+
|
| 426 |
+
# Add & Norm of the sublayer 1
|
| 427 |
+
self.dropout_path1 = nn.Dropout(config.path_dropout) if config.path_dropout > 0 else nn.Identity()
|
| 428 |
+
if config.norm_type == "batchnorm":
|
| 429 |
+
self.norm_sublayer1 = PatchTSTBatchNorm(config)
|
| 430 |
+
elif config.norm_type == "layernorm":
|
| 431 |
+
self.norm_sublayer1 = nn.LayerNorm(config.d_model, eps=config.norm_eps)
|
| 432 |
+
else:
|
| 433 |
+
raise ValueError(f"{config.norm_type} is not a supported norm layer type.")
|
| 434 |
+
|
| 435 |
+
# Add & Norm of the sublayer 2
|
| 436 |
+
if self.channel_attention:
|
| 437 |
+
self.dropout_path2 = nn.Dropout(config.path_dropout) if config.path_dropout > 0 else nn.Identity()
|
| 438 |
+
if config.norm_type == "batchnorm":
|
| 439 |
+
self.norm_sublayer2 = PatchTSTBatchNorm(config)
|
| 440 |
+
elif config.norm_type == "layernorm":
|
| 441 |
+
self.norm_sublayer2 = nn.LayerNorm(config.d_model, eps=config.norm_eps)
|
| 442 |
+
else:
|
| 443 |
+
raise ValueError(f"{config.norm_type} is not a supported norm layer type.")
|
| 444 |
+
|
| 445 |
+
# Position-wise Feed-Forward
|
| 446 |
+
self.ff = nn.Sequential(
|
| 447 |
+
nn.Linear(config.d_model, config.ffn_dim, bias=config.bias),
|
| 448 |
+
ACT2CLS[config.activation_function](),
|
| 449 |
+
nn.Dropout(config.ff_dropout) if config.ff_dropout > 0 else nn.Identity(),
|
| 450 |
+
nn.Linear(config.ffn_dim, config.d_model, bias=config.bias),
|
| 451 |
+
)
|
| 452 |
+
|
| 453 |
+
# Add & Norm of sublayer 3
|
| 454 |
+
self.dropout_path3 = nn.Dropout(config.path_dropout) if config.path_dropout > 0 else nn.Identity()
|
| 455 |
+
if config.norm_type == "batchnorm":
|
| 456 |
+
self.norm_sublayer3 = PatchTSTBatchNorm(config)
|
| 457 |
+
elif config.norm_type == "layernorm":
|
| 458 |
+
self.norm_sublayer3 = nn.LayerNorm(config.d_model, eps=config.norm_eps)
|
| 459 |
+
else:
|
| 460 |
+
raise ValueError(f"{config.norm_type} is not a supported norm layer type.")
|
| 461 |
+
|
| 462 |
+
self.pre_norm = config.pre_norm
|
| 463 |
+
|
| 464 |
+
def forward(self, hidden_state: torch.Tensor, output_attentions: bool | None = None):
|
| 465 |
+
"""
|
| 466 |
+
Parameters:
|
| 467 |
+
hidden_state (`torch.Tensor` of shape `(batch_size, num_channels, sequence_length, d_model)`, *required*):
|
| 468 |
+
Past values of the time series
|
| 469 |
+
output_attentions (`bool`, *optional*):
|
| 470 |
+
Whether or not to return the output attention of all layers
|
| 471 |
+
Return:
|
| 472 |
+
`torch.Tensor` of shape `(batch_size, num_channels, sequence_length, d_model)`
|
| 473 |
+
|
| 474 |
+
"""
|
| 475 |
+
batch_size, num_input_channels, sequence_length, d_model = hidden_state.shape
|
| 476 |
+
|
| 477 |
+
# First sublayer: attention across time
|
| 478 |
+
# hidden_states: [(bs*num_channels) x sequence_length x d_model]
|
| 479 |
+
hidden_state = hidden_state.view(batch_size * num_input_channels, sequence_length, d_model)
|
| 480 |
+
|
| 481 |
+
if self.pre_norm:
|
| 482 |
+
## Norm and Multi-Head attention and Add residual connection
|
| 483 |
+
attn_output, attn_weights, _ = self.self_attn(
|
| 484 |
+
hidden_states=self.norm_sublayer1(hidden_state), output_attentions=output_attentions
|
| 485 |
+
)
|
| 486 |
+
# Add: residual connection with residual dropout
|
| 487 |
+
hidden_state = hidden_state + self.dropout_path1(attn_output)
|
| 488 |
+
else:
|
| 489 |
+
## Multi-Head attention and Add residual connection and Norm - Standard Transformer from BERT
|
| 490 |
+
attn_output, attn_weights, _ = self.self_attn(
|
| 491 |
+
hidden_states=hidden_state, output_attentions=output_attentions
|
| 492 |
+
)
|
| 493 |
+
# hidden_states: [(bs*num_channels) x sequence_length x d_model]
|
| 494 |
+
hidden_state = self.norm_sublayer1(hidden_state + self.dropout_path1(attn_output))
|
| 495 |
+
|
| 496 |
+
# hidden_state: [bs x num_channels x sequence_length x d_model]
|
| 497 |
+
hidden_state = hidden_state.reshape(batch_size, num_input_channels, sequence_length, d_model)
|
| 498 |
+
|
| 499 |
+
# second sublayer: attention across variable at any given time
|
| 500 |
+
if self.channel_attention:
|
| 501 |
+
# hidden_state: [bs x sequence_length x num_channels x d_model]
|
| 502 |
+
hidden_state = hidden_state.transpose(2, 1).contiguous()
|
| 503 |
+
# hidden_state: [(bs*sequence_length) x num_channels x d_model]
|
| 504 |
+
hidden_state = hidden_state.view(batch_size * sequence_length, num_input_channels, d_model)
|
| 505 |
+
if self.pre_norm:
|
| 506 |
+
## Norm and Multi-Head attention and Add residual connection
|
| 507 |
+
attn_output, channel_attn_weights, _ = self.self_attn(
|
| 508 |
+
hidden_states=self.norm_sublayer2(hidden_state), output_attentions=output_attentions
|
| 509 |
+
)
|
| 510 |
+
# Add: residual connection with residual dropout
|
| 511 |
+
hidden_state = hidden_state + self.dropout_path2(attn_output)
|
| 512 |
+
else:
|
| 513 |
+
## Multi-Head attention and Add residual connection and Norm
|
| 514 |
+
attn_output, channel_attn_weights, _ = self.self_attn(
|
| 515 |
+
hidden_states=hidden_state, output_attentions=output_attentions
|
| 516 |
+
)
|
| 517 |
+
# hidden_states: [(bs*sequence_length) x num_channels x d_model]
|
| 518 |
+
hidden_state = self.norm_sublayer2(hidden_state + self.dropout_path2(attn_output))
|
| 519 |
+
|
| 520 |
+
# Reshape hidden state
|
| 521 |
+
# hidden_state: [bs x sequence_length x num_channels x d_model]
|
| 522 |
+
hidden_state = hidden_state.reshape(batch_size, sequence_length, num_input_channels, d_model)
|
| 523 |
+
# hidden_state: [bs x num_channels x sequence_length x d_model]
|
| 524 |
+
hidden_state = hidden_state.transpose(1, 2).contiguous()
|
| 525 |
+
|
| 526 |
+
# Third sublayer: mixing across hidden
|
| 527 |
+
# hidden_state: [(batch_size*num_channels) x sequence_length x d_model]
|
| 528 |
+
hidden_state = hidden_state.view(batch_size * num_input_channels, sequence_length, d_model)
|
| 529 |
+
if self.pre_norm:
|
| 530 |
+
## Norm and Position-wise Feed-Forward and Add residual connection
|
| 531 |
+
# Add: residual connection with residual dropout
|
| 532 |
+
hidden_state = hidden_state + self.dropout_path3(self.ff(self.norm_sublayer3(hidden_state)))
|
| 533 |
+
else:
|
| 534 |
+
## Position-wise Feed-Forward and Add residual connection and Norm
|
| 535 |
+
# Add: residual connection with residual dropout
|
| 536 |
+
hidden_state = self.norm_sublayer3(hidden_state + self.dropout_path3(self.ff(hidden_state)))
|
| 537 |
+
|
| 538 |
+
# [bs x num_channels x sequence_length x d_model]
|
| 539 |
+
hidden_state = hidden_state.reshape(batch_size, num_input_channels, sequence_length, d_model)
|
| 540 |
+
|
| 541 |
+
outputs = (hidden_state,)
|
| 542 |
+
if output_attentions:
|
| 543 |
+
outputs += (attn_weights, channel_attn_weights) if self.channel_attention else (attn_weights,)
|
| 544 |
+
|
| 545 |
+
return outputs
|
| 546 |
+
|
| 547 |
+
|
| 548 |
+
@auto_docstring
|
| 549 |
+
class PatchTSTPreTrainedModel(PreTrainedModel):
|
| 550 |
+
config: PatchTSTConfig
|
| 551 |
+
base_model_prefix = "model"
|
| 552 |
+
main_input_name = "past_values"
|
| 553 |
+
input_modalities = ("time",)
|
| 554 |
+
supports_gradient_checkpointing = False
|
| 555 |
+
_supports_flash_attn = True
|
| 556 |
+
_supports_sdpa = True
|
| 557 |
+
_supports_flex_attn = True
|
| 558 |
+
|
| 559 |
+
@torch.no_grad()
|
| 560 |
+
def _init_weights(self, module: nn.Module):
|
| 561 |
+
"""
|
| 562 |
+
Initialize weights
|
| 563 |
+
"""
|
| 564 |
+
if isinstance(module, PatchTSTPositionalEncoding):
|
| 565 |
+
# get the number of patches
|
| 566 |
+
num_patches = (
|
| 567 |
+
max(self.config.context_length, self.config.patch_length) - self.config.patch_length
|
| 568 |
+
) // self.config.patch_stride + 1
|
| 569 |
+
# initialize cls_token
|
| 570 |
+
if self.config.use_cls_token:
|
| 571 |
+
init.normal_(module.cls_token, std=0.02)
|
| 572 |
+
num_patches += 1
|
| 573 |
+
# initialize positional encoding
|
| 574 |
+
position_enc = module._init_pe(self.config, num_patches)
|
| 575 |
+
if is_deepspeed_zero3_enabled():
|
| 576 |
+
import deepspeed
|
| 577 |
+
|
| 578 |
+
with deepspeed.zero.GatheredParameters(module.position_enc, modifier_rank=None):
|
| 579 |
+
if module.position_enc.numel() > 0:
|
| 580 |
+
init.copy_(module.position_enc, position_enc)
|
| 581 |
+
else:
|
| 582 |
+
init.copy_(module.position_enc, position_enc)
|
| 583 |
+
elif isinstance(module, (nn.LayerNorm, nn.BatchNorm1d)):
|
| 584 |
+
init.zeros_(module.bias)
|
| 585 |
+
init.ones_(module.weight)
|
| 586 |
+
if getattr(module, "running_mean", None) is not None:
|
| 587 |
+
init.zeros_(module.running_mean)
|
| 588 |
+
init.ones_(module.running_var)
|
| 589 |
+
init.zeros_(module.num_batches_tracked)
|
| 590 |
+
elif isinstance(module, nn.Linear):
|
| 591 |
+
init.normal_(module.weight, mean=0.0, std=self.config.init_std)
|
| 592 |
+
if module.bias is not None:
|
| 593 |
+
init.zeros_(module.bias)
|
| 594 |
+
|
| 595 |
+
def _set_gradient_checkpointing(self, module, value=False):
|
| 596 |
+
if isinstance(module, (PatchTSTEncoder)):
|
| 597 |
+
module.gradient_checkpointing = value
|
| 598 |
+
|
| 599 |
+
|
| 600 |
+
class PatchTSTEmbedding(nn.Module):
|
| 601 |
+
def __init__(self, config: PatchTSTConfig):
|
| 602 |
+
super().__init__()
|
| 603 |
+
self.num_input_channels = config.num_input_channels
|
| 604 |
+
self.share_embedding = config.share_embedding
|
| 605 |
+
# Input encoding: projection of feature vectors onto a d-dim vector space
|
| 606 |
+
if self.share_embedding:
|
| 607 |
+
self.input_embedding = nn.Linear(config.patch_length, config.d_model)
|
| 608 |
+
else:
|
| 609 |
+
self.input_embedding = nn.ModuleList()
|
| 610 |
+
for _ in range(config.num_input_channels):
|
| 611 |
+
self.input_embedding.append(nn.Linear(config.patch_length, config.d_model))
|
| 612 |
+
|
| 613 |
+
def forward(self, patch_input: torch.Tensor):
|
| 614 |
+
"""
|
| 615 |
+
Parameters:
|
| 616 |
+
patch_input (`torch.Tensor` of shape `(batch_size, num_channels, num_patches, patch_length)`, *required*):
|
| 617 |
+
Patch input for embedding
|
| 618 |
+
return:
|
| 619 |
+
`torch.Tensor` of shape `(batch_size, num_channels, num_patches, d_model)`
|
| 620 |
+
"""
|
| 621 |
+
# Input encoding
|
| 622 |
+
num_input_channels = patch_input.shape[1]
|
| 623 |
+
if num_input_channels != self.num_input_channels:
|
| 624 |
+
raise ValueError(
|
| 625 |
+
f"The defined number of input channels ({self.num_input_channels}) in the config "
|
| 626 |
+
f"has to be the same as the number of channels in the batch input ({num_input_channels})"
|
| 627 |
+
)
|
| 628 |
+
if self.share_embedding:
|
| 629 |
+
embeddings = self.input_embedding(patch_input) # x: [bs x num_channels x num_patches x d_model]
|
| 630 |
+
else:
|
| 631 |
+
embeddings = [self.input_embedding[i](patch_input[:, i, :, :]) for i in range(num_input_channels)]
|
| 632 |
+
embeddings = torch.stack(embeddings, dim=1)
|
| 633 |
+
return embeddings
|
| 634 |
+
|
| 635 |
+
|
| 636 |
+
class PatchTSTPositionalEncoding(nn.Module):
|
| 637 |
+
"""
|
| 638 |
+
Class for positional encoding
|
| 639 |
+
"""
|
| 640 |
+
|
| 641 |
+
def __init__(self, config: PatchTSTConfig, num_patches: int):
|
| 642 |
+
super().__init__()
|
| 643 |
+
self.use_cls_token = config.use_cls_token
|
| 644 |
+
self.num_input_channels = config.num_input_channels
|
| 645 |
+
if config.use_cls_token:
|
| 646 |
+
# cls_token: [1 x num_input_channels x 1 x d_model]
|
| 647 |
+
self.cls_token = nn.Parameter(torch.zeros(1, 1, 1, config.d_model))
|
| 648 |
+
num_patches += 1
|
| 649 |
+
# positional encoding: [num_patches x d_model]
|
| 650 |
+
self.position_enc = self._init_pe(config, num_patches)
|
| 651 |
+
# Positional dropout
|
| 652 |
+
self.positional_dropout = (
|
| 653 |
+
nn.Dropout(config.positional_dropout) if config.positional_dropout > 0 else nn.Identity()
|
| 654 |
+
)
|
| 655 |
+
|
| 656 |
+
@staticmethod
|
| 657 |
+
def _init_pe(config: PatchTSTConfig, num_patches: int) -> nn.Parameter:
|
| 658 |
+
# Positional encoding
|
| 659 |
+
if config.positional_encoding_type == "random":
|
| 660 |
+
position_enc = nn.Parameter(torch.randn(num_patches, config.d_model), requires_grad=True)
|
| 661 |
+
elif config.positional_encoding_type == "sincos":
|
| 662 |
+
position_enc = torch.zeros(num_patches, config.d_model)
|
| 663 |
+
position = torch.arange(0, num_patches).unsqueeze(1)
|
| 664 |
+
div_term = torch.exp(torch.arange(0, config.d_model, 2) * -(math.log(10000.0) / config.d_model))
|
| 665 |
+
position_enc[:, 0::2] = torch.sin(position * div_term)
|
| 666 |
+
position_enc[:, 1::2] = torch.cos(position * div_term)
|
| 667 |
+
position_enc = position_enc - position_enc.mean()
|
| 668 |
+
position_enc = position_enc / (position_enc.std() * 10)
|
| 669 |
+
position_enc = nn.Parameter(position_enc, requires_grad=False)
|
| 670 |
+
else:
|
| 671 |
+
raise ValueError(
|
| 672 |
+
f"{config.positional_encoding_type} is not a valid positional encoder. Available types are 'random' and 'sincos'."
|
| 673 |
+
)
|
| 674 |
+
return position_enc
|
| 675 |
+
|
| 676 |
+
def forward(self, patch_input: torch.Tensor):
|
| 677 |
+
if self.use_cls_token:
|
| 678 |
+
# patch_input: [bs x num_channels x num_patches x d_model]
|
| 679 |
+
patch_input = self.positional_dropout(patch_input + self.position_enc[1:, :])
|
| 680 |
+
# append cls token where cls_token: [1 x num_channels x 1 x d_model]
|
| 681 |
+
cls_token = self.cls_token + self.position_enc[:1, :]
|
| 682 |
+
# get the same copy of cls_token for all the samples in batch: [bs x num_channels x 1 x d_model]
|
| 683 |
+
cls_tokens = cls_token.expand(patch_input.shape[0], self.num_input_channels, -1, -1)
|
| 684 |
+
# hidden_state: [bs x num_channels x (num_patches+1) x d_model]
|
| 685 |
+
hidden_state = torch.cat((cls_tokens, patch_input), dim=2)
|
| 686 |
+
else:
|
| 687 |
+
# hidden_state: [bs x num_channels x num_patches x d_model]
|
| 688 |
+
hidden_state = self.positional_dropout(patch_input + self.position_enc)
|
| 689 |
+
return hidden_state
|
| 690 |
+
|
| 691 |
+
|
| 692 |
+
class PatchTSTEncoder(PatchTSTPreTrainedModel):
|
| 693 |
+
"""
|
| 694 |
+
PatchTST Encoder
|
| 695 |
+
"""
|
| 696 |
+
|
| 697 |
+
def __init__(self, config: PatchTSTConfig, num_patches: int):
|
| 698 |
+
super().__init__(config)
|
| 699 |
+
self.gradient_checkpointing = False
|
| 700 |
+
|
| 701 |
+
# Input embedding: projection of feature vectors onto a d-dim vector space
|
| 702 |
+
self.embedder = PatchTSTEmbedding(config)
|
| 703 |
+
# Positional encoding
|
| 704 |
+
self.positional_encoder = PatchTSTPositionalEncoding(config, num_patches)
|
| 705 |
+
# Encoder
|
| 706 |
+
self.layers = nn.ModuleList([PatchTSTEncoderLayer(config) for i in range(config.num_hidden_layers)])
|
| 707 |
+
|
| 708 |
+
# Initialize weights and apply final processing
|
| 709 |
+
self.post_init()
|
| 710 |
+
|
| 711 |
+
def forward(
|
| 712 |
+
self,
|
| 713 |
+
patch_input: torch.Tensor,
|
| 714 |
+
output_hidden_states: bool | None = None,
|
| 715 |
+
output_attentions: bool | None = None,
|
| 716 |
+
**kwargs,
|
| 717 |
+
) -> BaseModelOutput:
|
| 718 |
+
"""
|
| 719 |
+
Parameters:
|
| 720 |
+
patch_input (`torch.Tensor` of shape `(batch_size, num_channels, num_patches, patch_length)`, *required*):
|
| 721 |
+
Past values of the time series
|
| 722 |
+
output_hidden_states (bool, optional): Indicates if hidden states should be outputted.
|
| 723 |
+
output_attentions (bool, optional): Indicates if attentions should be outputted.
|
| 724 |
+
|
| 725 |
+
return:
|
| 726 |
+
`BaseModelOutput`
|
| 727 |
+
"""
|
| 728 |
+
output_attentions = output_attentions if output_attentions is not None else self.config.output_attentions
|
| 729 |
+
output_hidden_states = (
|
| 730 |
+
output_hidden_states if output_hidden_states is not None else self.config.output_hidden_states
|
| 731 |
+
)
|
| 732 |
+
|
| 733 |
+
# Input embedding
|
| 734 |
+
patch_input = self.embedder(patch_input)
|
| 735 |
+
# Positional encoding
|
| 736 |
+
hidden_state = self.positional_encoder(patch_input)
|
| 737 |
+
|
| 738 |
+
encoder_states = () if output_hidden_states else None
|
| 739 |
+
all_attentions = () if output_attentions else None
|
| 740 |
+
for encoder_layer in self.layers:
|
| 741 |
+
if output_hidden_states:
|
| 742 |
+
encoder_states = encoder_states + (hidden_state,)
|
| 743 |
+
|
| 744 |
+
layer_outputs = encoder_layer(hidden_state=hidden_state, output_attentions=output_attentions)
|
| 745 |
+
# get hidden state. hidden_state shape is [bs x num_channels x num_patches x d_model]
|
| 746 |
+
# or [bs x num_channels x (num_patches+1) x d_model] if use cls_token
|
| 747 |
+
hidden_state = layer_outputs[0]
|
| 748 |
+
# append attention matrix at each layer
|
| 749 |
+
if output_attentions:
|
| 750 |
+
all_attentions = all_attentions + (layer_outputs[1],)
|
| 751 |
+
# return past_values, hidden_states
|
| 752 |
+
return BaseModelOutput(last_hidden_state=hidden_state, hidden_states=encoder_states, attentions=all_attentions)
|
| 753 |
+
|
| 754 |
+
|
| 755 |
+
@auto_docstring(
|
| 756 |
+
custom_intro="""
|
| 757 |
+
Base class for model's outputs, with potential hidden states.
|
| 758 |
+
"""
|
| 759 |
+
)
|
| 760 |
+
@dataclass
|
| 761 |
+
class PatchTSTModelOutput(ModelOutput):
|
| 762 |
+
r"""
|
| 763 |
+
last_hidden_state (`torch.FloatTensor` of shape `(batch_size, num_channels, num_patches, patch_length)`):
|
| 764 |
+
Sequence of hidden-states at the output of the last layer of the model.
|
| 765 |
+
hidden_states (`tuple(torch.FloatTensor)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):
|
| 766 |
+
Tuple of `torch.FloatTensor` (one for the output of the embeddings, if the model has an embedding layer, +
|
| 767 |
+
one for the output of each layer) of shape `(batch_size, num_channels, height, width)`. Hidden-states of
|
| 768 |
+
the model at the output of each layer plus the optional initial embedding outputs.
|
| 769 |
+
mask (`torch.FloatTensor` of shape `(batch_size, num_channels, num_patches)`, *optional*):
|
| 770 |
+
Bool masked tensor indicating which patches are masked
|
| 771 |
+
loc (`torch.FloatTensor` of shape `(batch_size, 1, num_channels)`, *optional*):
|
| 772 |
+
Mean of the input data (batch_size, sequence_length, num_channels) over the sequence_length
|
| 773 |
+
scale (`torch.FloatTensor` of shape `(batch_size, 1, num_channels)`, *optional*):
|
| 774 |
+
Std of the input data (batch_size, sequence_length, num_channels) over the sequence_length
|
| 775 |
+
patch_input (`torch.FloatTensor` of shape `(batch_size, num_channels, num_patches, patch_length)`):
|
| 776 |
+
Patched input to the Transformer
|
| 777 |
+
"""
|
| 778 |
+
|
| 779 |
+
last_hidden_state: torch.FloatTensor | None = None
|
| 780 |
+
hidden_states: tuple[torch.FloatTensor] | None = None
|
| 781 |
+
attentions: tuple[torch.FloatTensor] | None = None
|
| 782 |
+
mask: torch.FloatTensor | None = None
|
| 783 |
+
loc: torch.FloatTensor | None = None
|
| 784 |
+
scale: torch.FloatTensor | None = None
|
| 785 |
+
patch_input: torch.FloatTensor | None = None
|
| 786 |
+
|
| 787 |
+
|
| 788 |
+
@auto_docstring(
|
| 789 |
+
custom_intro="""
|
| 790 |
+
Output type of [`PatchTSTForPretraining`].
|
| 791 |
+
"""
|
| 792 |
+
)
|
| 793 |
+
@dataclass
|
| 794 |
+
class PatchTSTForPretrainingOutput(ModelOutput):
|
| 795 |
+
r"""
|
| 796 |
+
loss (*optional*, returned when `labels` is provided, `torch.FloatTensor` of shape `(1,)`):
|
| 797 |
+
MSE loss.
|
| 798 |
+
prediction_output (`torch.FloatTensor` of shape `(batch_size, sequence_length, config.vocab_size)`):
|
| 799 |
+
Prediction outputs of the time series modeling heads.
|
| 800 |
+
"""
|
| 801 |
+
|
| 802 |
+
loss: torch.FloatTensor | None = None
|
| 803 |
+
prediction_output: torch.FloatTensor | None = None
|
| 804 |
+
hidden_states: tuple[torch.FloatTensor] | None = None
|
| 805 |
+
attentions: tuple[torch.FloatTensor] | None = None
|
| 806 |
+
|
| 807 |
+
|
| 808 |
+
@auto_docstring(
|
| 809 |
+
custom_intro="""
|
| 810 |
+
Output type of [`PatchTSTForRegression`].
|
| 811 |
+
"""
|
| 812 |
+
)
|
| 813 |
+
@dataclass
|
| 814 |
+
class PatchTSTForRegressionOutput(ModelOutput):
|
| 815 |
+
r"""
|
| 816 |
+
loss (*optional*, returned when `labels` is provided, `torch.FloatTensor` of shape `(1,)`):
|
| 817 |
+
MSE loss.
|
| 818 |
+
regression_outputs (`torch.FloatTensor` of shape `(batch_size, num_targets)`):
|
| 819 |
+
Regression outputs of the time series modeling heads.
|
| 820 |
+
"""
|
| 821 |
+
|
| 822 |
+
loss: torch.FloatTensor | None = None
|
| 823 |
+
regression_outputs: torch.FloatTensor | None = None
|
| 824 |
+
hidden_states: tuple[torch.FloatTensor] | None = None
|
| 825 |
+
attentions: tuple[torch.FloatTensor] | None = None
|
| 826 |
+
|
| 827 |
+
|
| 828 |
+
@auto_docstring(
|
| 829 |
+
custom_intro="""
|
| 830 |
+
Output type of [`PatchTSTForPrediction`].
|
| 831 |
+
"""
|
| 832 |
+
)
|
| 833 |
+
@dataclass
|
| 834 |
+
class PatchTSTForPredictionOutput(ModelOutput):
|
| 835 |
+
r"""
|
| 836 |
+
loss (*optional*, returned when `labels` is provided, `torch.FloatTensor` of shape `(1,)`):
|
| 837 |
+
MSE loss.
|
| 838 |
+
prediction_outputs (`torch.FloatTensor` of shape `(batch_size, prediction_length, -1)`):
|
| 839 |
+
Prediction outputs of the time series modeling heads.
|
| 840 |
+
attentions (`tuple(torch.FloatTensor)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):
|
| 841 |
+
Tuple of `torch.FloatTensor` (one for each layer) of shape `(batch_size, num_heads, sequence_length,
|
| 842 |
+
sequence_length)`.
|
| 843 |
+
|
| 844 |
+
Attentions weights after the attention softmax, used to compute the weighted average in the self-attention
|
| 845 |
+
heads.
|
| 846 |
+
loc: (`torch.FloatTensor` of shape `(batch_size, 1, num_channels)`, *optional*)
|
| 847 |
+
Mean of the input data (batch_size, sequence_length, num_channels) over the sequence_length
|
| 848 |
+
scale: (`torch.FloatTensor` of shape `(batch_size, 1, num_channels)`, *optional*)
|
| 849 |
+
Std of the input data (batch_size, sequence_length, num_channels) over the sequence_length
|
| 850 |
+
"""
|
| 851 |
+
|
| 852 |
+
loss: torch.FloatTensor | None = None
|
| 853 |
+
prediction_outputs: torch.FloatTensor | None = None
|
| 854 |
+
hidden_states: tuple[torch.FloatTensor] | None = None
|
| 855 |
+
attentions: tuple[torch.FloatTensor] | None = None
|
| 856 |
+
loc: torch.FloatTensor | None = None
|
| 857 |
+
scale: torch.FloatTensor | None = None
|
| 858 |
+
|
| 859 |
+
|
| 860 |
+
@auto_docstring(
|
| 861 |
+
custom_intro="""
|
| 862 |
+
Output type of [`PatchTSTForClassification`].
|
| 863 |
+
"""
|
| 864 |
+
)
|
| 865 |
+
@dataclass
|
| 866 |
+
class PatchTSTForClassificationOutput(ModelOutput):
|
| 867 |
+
r"""
|
| 868 |
+
loss (*optional*, returned when `labels` is provided, `torch.FloatTensor` of shape `(1,)`):
|
| 869 |
+
Total loss as the sum of the masked language modeling loss and the next sequence prediction
|
| 870 |
+
(classification) loss.
|
| 871 |
+
prediction_logits (`torch.FloatTensor` of shape `(batch_size, num_targets)`):
|
| 872 |
+
Prediction scores of the PatchTST modeling head (scores before SoftMax).
|
| 873 |
+
"""
|
| 874 |
+
|
| 875 |
+
loss: torch.FloatTensor | None = None
|
| 876 |
+
prediction_logits: torch.FloatTensor | None = None
|
| 877 |
+
hidden_states: tuple[torch.FloatTensor] | None = None
|
| 878 |
+
attentions: tuple[torch.FloatTensor] | None = None
|
| 879 |
+
|
| 880 |
+
|
| 881 |
+
@auto_docstring(
|
| 882 |
+
custom_intro="""
|
| 883 |
+
Base class for time series model's predictions outputs that contains the sampled values from the chosen
|
| 884 |
+
distribution.
|
| 885 |
+
"""
|
| 886 |
+
)
|
| 887 |
+
@dataclass
|
| 888 |
+
class SamplePatchTSTOutput(ModelOutput):
|
| 889 |
+
r"""
|
| 890 |
+
sequences (`torch.FloatTensor` of shape `(batch_size, num_samples, prediction_length, num_targets)`):
|
| 891 |
+
Sampled values from the chosen distribution.
|
| 892 |
+
"""
|
| 893 |
+
|
| 894 |
+
sequences: torch.FloatTensor | None = None
|
| 895 |
+
|
| 896 |
+
|
| 897 |
+
# Copied from transformers.models.time_series_transformer.modeling_time_series_transformer.nll
|
| 898 |
+
def nll(input: torch.distributions.Distribution, target: torch.Tensor) -> torch.Tensor:
|
| 899 |
+
"""
|
| 900 |
+
Computes the negative log likelihood loss from input distribution with respect to target.
|
| 901 |
+
"""
|
| 902 |
+
return -input.log_prob(target)
|
| 903 |
+
|
| 904 |
+
|
| 905 |
+
# Copied from transformers.models.time_series_transformer.modeling_time_series_transformer.weighted_average
|
| 906 |
+
def weighted_average(input_tensor: torch.Tensor, weights: torch.Tensor | None = None, dim=None) -> torch.Tensor:
|
| 907 |
+
"""
|
| 908 |
+
Computes the weighted average of a given tensor across a given `dim`, masking values associated with weight zero,
|
| 909 |
+
meaning instead of `nan * 0 = nan` you will get `0 * 0 = 0`.
|
| 910 |
+
|
| 911 |
+
Args:
|
| 912 |
+
input_tensor (`torch.FloatTensor`):
|
| 913 |
+
Input tensor, of which the average must be computed.
|
| 914 |
+
weights (`torch.FloatTensor`, *optional*):
|
| 915 |
+
Weights tensor, of the same shape as `input_tensor`.
|
| 916 |
+
dim (`int`, *optional*):
|
| 917 |
+
The dim along which to average `input_tensor`.
|
| 918 |
+
|
| 919 |
+
Returns:
|
| 920 |
+
`torch.FloatTensor`: The tensor with values averaged along the specified `dim`.
|
| 921 |
+
"""
|
| 922 |
+
if weights is not None:
|
| 923 |
+
weighted_tensor = torch.where(weights != 0, input_tensor * weights, torch.zeros_like(input_tensor))
|
| 924 |
+
sum_weights = torch.clamp(weights.sum(dim=dim) if dim else weights.sum(), min=1.0)
|
| 925 |
+
return (weighted_tensor.sum(dim=dim) if dim else weighted_tensor.sum()) / sum_weights
|
| 926 |
+
else:
|
| 927 |
+
return input_tensor.mean(dim=dim)
|
| 928 |
+
|
| 929 |
+
|
| 930 |
+
# Copied from transformers.models.time_series_transformer.modeling_time_series_transformer.TimeSeriesStdScaler with TimeSeriesTransformer->PatchTST,TimeSeries->PatchTST
|
| 931 |
+
class PatchTSTStdScaler(nn.Module):
|
| 932 |
+
"""
|
| 933 |
+
Standardize features by calculating the mean and scaling along the first dimension, and then normalizes it by
|
| 934 |
+
subtracting from the mean and dividing by the standard deviation.
|
| 935 |
+
"""
|
| 936 |
+
|
| 937 |
+
def __init__(self, config: PatchTSTConfig):
|
| 938 |
+
super().__init__()
|
| 939 |
+
self.dim = config.scaling_dim if hasattr(config, "scaling_dim") else 1
|
| 940 |
+
self.keepdim = config.keepdim if hasattr(config, "keepdim") else True
|
| 941 |
+
self.minimum_scale = config.minimum_scale if hasattr(config, "minimum_scale") else 1e-5
|
| 942 |
+
|
| 943 |
+
def forward(
|
| 944 |
+
self, data: torch.Tensor, observed_indicator: torch.Tensor
|
| 945 |
+
) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor]:
|
| 946 |
+
"""
|
| 947 |
+
Parameters:
|
| 948 |
+
data (`torch.Tensor` of shape `(batch_size, sequence_length, num_input_channels)`):
|
| 949 |
+
input for Batch norm calculation
|
| 950 |
+
observed_indicator (`torch.BoolTensor` of shape `(batch_size, sequence_length, num_input_channels)`):
|
| 951 |
+
Calculating the scale on the observed indicator.
|
| 952 |
+
Returns:
|
| 953 |
+
tuple of `torch.Tensor` of shapes
|
| 954 |
+
(`(batch_size, sequence_length, num_input_channels)`,`(batch_size, 1, num_input_channels)`,
|
| 955 |
+
`(batch_size, 1, num_input_channels)`)
|
| 956 |
+
"""
|
| 957 |
+
denominator = observed_indicator.sum(self.dim, keepdim=self.keepdim)
|
| 958 |
+
denominator = denominator.clamp_min(1.0)
|
| 959 |
+
loc = (data * observed_indicator).sum(self.dim, keepdim=self.keepdim) / denominator
|
| 960 |
+
|
| 961 |
+
variance = (((data - loc) * observed_indicator) ** 2).sum(self.dim, keepdim=self.keepdim) / denominator
|
| 962 |
+
scale = torch.sqrt(variance + self.minimum_scale)
|
| 963 |
+
return (data - loc) / scale, loc, scale
|
| 964 |
+
|
| 965 |
+
|
| 966 |
+
# Copied from transformers.models.time_series_transformer.modeling_time_series_transformer.TimeSeriesMeanScaler with TimeSeriesTransformer->PatchTST,TimeSeries->PatchTST
|
| 967 |
+
class PatchTSTMeanScaler(nn.Module):
|
| 968 |
+
"""
|
| 969 |
+
Computes a scaling factor as the weighted average absolute value along the first dimension, and scales the data
|
| 970 |
+
accordingly.
|
| 971 |
+
"""
|
| 972 |
+
|
| 973 |
+
def __init__(self, config: PatchTSTConfig):
|
| 974 |
+
super().__init__()
|
| 975 |
+
self.dim = config.scaling_dim if hasattr(config, "scaling_dim") else 1
|
| 976 |
+
self.keepdim = config.keepdim if hasattr(config, "keepdim") else True
|
| 977 |
+
self.minimum_scale = config.minimum_scale if hasattr(config, "minimum_scale") else 1e-10
|
| 978 |
+
self.default_scale = config.default_scale if hasattr(config, "default_scale") else None
|
| 979 |
+
|
| 980 |
+
def forward(
|
| 981 |
+
self, data: torch.Tensor, observed_indicator: torch.Tensor
|
| 982 |
+
) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor]:
|
| 983 |
+
"""
|
| 984 |
+
Parameters:
|
| 985 |
+
data (`torch.Tensor` of shape `(batch_size, sequence_length, num_input_channels)`):
|
| 986 |
+
input for Batch norm calculation
|
| 987 |
+
observed_indicator (`torch.BoolTensor` of shape `(batch_size, sequence_length, num_input_channels)`):
|
| 988 |
+
Calculating the scale on the observed indicator.
|
| 989 |
+
Returns:
|
| 990 |
+
tuple of `torch.Tensor` of shapes
|
| 991 |
+
(`(batch_size, sequence_length, num_input_channels)`,`(batch_size, 1, num_input_channels)`,
|
| 992 |
+
`(batch_size, 1, num_input_channels)`)
|
| 993 |
+
"""
|
| 994 |
+
ts_sum = (data * observed_indicator).abs().sum(self.dim, keepdim=True)
|
| 995 |
+
num_observed = observed_indicator.sum(self.dim, keepdim=True)
|
| 996 |
+
|
| 997 |
+
scale = ts_sum / torch.clamp(num_observed, min=1)
|
| 998 |
+
|
| 999 |
+
# If `default_scale` is provided, we use it, otherwise we use the scale
|
| 1000 |
+
# of the batch.
|
| 1001 |
+
if self.default_scale is None:
|
| 1002 |
+
batch_sum = ts_sum.sum(dim=0)
|
| 1003 |
+
batch_observations = torch.clamp(num_observed.sum(0), min=1)
|
| 1004 |
+
default_scale = torch.squeeze(batch_sum / batch_observations)
|
| 1005 |
+
else:
|
| 1006 |
+
default_scale = self.default_scale * torch.ones_like(scale)
|
| 1007 |
+
|
| 1008 |
+
# apply default scale where there are no observations
|
| 1009 |
+
scale = torch.where(num_observed > 0, scale, default_scale)
|
| 1010 |
+
|
| 1011 |
+
# ensure the scale is at least `self.minimum_scale`
|
| 1012 |
+
scale = torch.clamp(scale, min=self.minimum_scale)
|
| 1013 |
+
scaled_data = data / scale
|
| 1014 |
+
|
| 1015 |
+
if not self.keepdim:
|
| 1016 |
+
scale = scale.squeeze(dim=self.dim)
|
| 1017 |
+
|
| 1018 |
+
return scaled_data, torch.zeros_like(scale), scale
|
| 1019 |
+
|
| 1020 |
+
|
| 1021 |
+
# Copied from transformers.models.time_series_transformer.modeling_time_series_transformer.TimeSeriesNOPScaler with TimeSeriesTransformer->PatchTST,TimeSeries->PatchTST
|
| 1022 |
+
class PatchTSTNOPScaler(nn.Module):
|
| 1023 |
+
"""
|
| 1024 |
+
Assigns a scaling factor equal to 1 along the first dimension, and therefore applies no scaling to the input data.
|
| 1025 |
+
"""
|
| 1026 |
+
|
| 1027 |
+
def __init__(self, config: PatchTSTConfig):
|
| 1028 |
+
super().__init__()
|
| 1029 |
+
self.dim = config.scaling_dim if hasattr(config, "scaling_dim") else 1
|
| 1030 |
+
self.keepdim = config.keepdim if hasattr(config, "keepdim") else True
|
| 1031 |
+
|
| 1032 |
+
def forward(
|
| 1033 |
+
self, data: torch.Tensor, observed_indicator: torch.Tensor | None = None
|
| 1034 |
+
) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor]:
|
| 1035 |
+
"""
|
| 1036 |
+
Parameters:
|
| 1037 |
+
data (`torch.Tensor` of shape `(batch_size, sequence_length, num_input_channels)`):
|
| 1038 |
+
input for Batch norm calculation
|
| 1039 |
+
Returns:
|
| 1040 |
+
tuple of `torch.Tensor` of shapes
|
| 1041 |
+
(`(batch_size, sequence_length, num_input_channels)`,`(batch_size, 1, num_input_channels)`,
|
| 1042 |
+
`(batch_size, 1, num_input_channels)`)
|
| 1043 |
+
"""
|
| 1044 |
+
scale = torch.ones_like(data, requires_grad=False).mean(dim=self.dim, keepdim=self.keepdim)
|
| 1045 |
+
loc = torch.zeros_like(data, requires_grad=False).mean(dim=self.dim, keepdim=self.keepdim)
|
| 1046 |
+
return data, loc, scale
|
| 1047 |
+
|
| 1048 |
+
|
| 1049 |
+
class PatchTSTScaler(nn.Module):
|
| 1050 |
+
def __init__(self, config: PatchTSTConfig):
|
| 1051 |
+
super().__init__()
|
| 1052 |
+
if config.scaling == "mean" or config.scaling is True:
|
| 1053 |
+
self.scaler = PatchTSTMeanScaler(config)
|
| 1054 |
+
elif config.scaling == "std":
|
| 1055 |
+
self.scaler = PatchTSTStdScaler(config)
|
| 1056 |
+
else:
|
| 1057 |
+
self.scaler = PatchTSTNOPScaler(config)
|
| 1058 |
+
|
| 1059 |
+
def forward(
|
| 1060 |
+
self, data: torch.Tensor, observed_indicator: torch.Tensor
|
| 1061 |
+
) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor]:
|
| 1062 |
+
"""
|
| 1063 |
+
Parameters:
|
| 1064 |
+
data (`torch.Tensor` of shape `(batch_size, sequence_length, num_input_channels)`):
|
| 1065 |
+
Input for scaler calculation
|
| 1066 |
+
observed_indicator (`torch.BoolTensor` of shape `(batch_size, sequence_length, num_input_channels)`):
|
| 1067 |
+
Calculating the scale on the observed indicator.
|
| 1068 |
+
Returns:
|
| 1069 |
+
tuple of `torch.Tensor` of shapes
|
| 1070 |
+
(`(batch_size, sequence_length, num_input_channels)`,`(batch_size, 1, num_input_channels)`,
|
| 1071 |
+
`(batch_size, 1, um_input_channels)`)
|
| 1072 |
+
"""
|
| 1073 |
+
data, loc, scale = self.scaler(data, observed_indicator)
|
| 1074 |
+
return data, loc, scale
|
| 1075 |
+
|
| 1076 |
+
|
| 1077 |
+
@auto_docstring
|
| 1078 |
+
class PatchTSTModel(PatchTSTPreTrainedModel):
|
| 1079 |
+
def __init__(self, config: PatchTSTConfig):
|
| 1080 |
+
super().__init__(config)
|
| 1081 |
+
|
| 1082 |
+
self.scaler = PatchTSTScaler(config)
|
| 1083 |
+
self.patchifier = PatchTSTPatchify(config)
|
| 1084 |
+
self.do_mask_input = config.do_mask_input
|
| 1085 |
+
# get num_patches information from PatchTSTPatchify
|
| 1086 |
+
num_patches = self.patchifier.num_patches
|
| 1087 |
+
|
| 1088 |
+
if self.do_mask_input:
|
| 1089 |
+
self.masking = PatchTSTMasking(config)
|
| 1090 |
+
else:
|
| 1091 |
+
self.masking = nn.Identity()
|
| 1092 |
+
self.encoder = PatchTSTEncoder(config, num_patches=num_patches)
|
| 1093 |
+
|
| 1094 |
+
# Initialize weights and apply final processing
|
| 1095 |
+
self.post_init()
|
| 1096 |
+
|
| 1097 |
+
def forward(
|
| 1098 |
+
self,
|
| 1099 |
+
past_values: torch.Tensor,
|
| 1100 |
+
past_observed_mask: torch.Tensor | None = None,
|
| 1101 |
+
future_values: torch.Tensor | None = None,
|
| 1102 |
+
output_hidden_states: bool | None = None,
|
| 1103 |
+
output_attentions: bool | None = None,
|
| 1104 |
+
return_dict: bool | None = None,
|
| 1105 |
+
**kwargs,
|
| 1106 |
+
) -> tuple | PatchTSTModelOutput:
|
| 1107 |
+
r"""
|
| 1108 |
+
Parameters:
|
| 1109 |
+
past_values (`torch.Tensor` of shape `(bs, sequence_length, num_input_channels)`, *required*):
|
| 1110 |
+
Input sequence to the model
|
| 1111 |
+
past_observed_mask (`torch.BoolTensor` of shape `(batch_size, sequence_length, num_input_channels)`, *optional*):
|
| 1112 |
+
Boolean mask to indicate which `past_values` were observed and which were missing. Mask values selected
|
| 1113 |
+
in `[0, 1]`:
|
| 1114 |
+
|
| 1115 |
+
- 1 for values that are **observed**,
|
| 1116 |
+
- 0 for values that are **missing** (i.e. NaNs that were replaced by zeros).
|
| 1117 |
+
future_values (`torch.BoolTensor` of shape `(batch_size, prediction_length, num_input_channels)`, *optional*):
|
| 1118 |
+
Future target values associated with the `past_values`
|
| 1119 |
+
output_hidden_states (`bool`, *optional*):
|
| 1120 |
+
Whether or not to return the hidden states of all layers
|
| 1121 |
+
output_attentions (`bool`, *optional*):
|
| 1122 |
+
Whether or not to return the output attention of all layers
|
| 1123 |
+
return_dict (`bool`, *optional*):
|
| 1124 |
+
Whether or not to return a `ModelOutput` instead of a plain tuple.
|
| 1125 |
+
|
| 1126 |
+
Returns:
|
| 1127 |
+
`PatchTSTModelOutput` or tuple of `torch.Tensor` (if `return_dict`=False or `config.return_dict`=False)
|
| 1128 |
+
|
| 1129 |
+
Examples:
|
| 1130 |
+
|
| 1131 |
+
```python
|
| 1132 |
+
>>> from huggingface_hub import hf_hub_download
|
| 1133 |
+
>>> import torch
|
| 1134 |
+
>>> from transformers import PatchTSTModel
|
| 1135 |
+
|
| 1136 |
+
>>> file = hf_hub_download(
|
| 1137 |
+
... repo_id="hf-internal-testing/etth1-hourly-batch", filename="train-batch.pt", repo_type="dataset"
|
| 1138 |
+
... )
|
| 1139 |
+
>>> batch = torch.load(file)
|
| 1140 |
+
|
| 1141 |
+
>>> model = PatchTSTModel.from_pretrained("namctin/patchtst_etth1_pretrain")
|
| 1142 |
+
|
| 1143 |
+
>>> # during training, one provides both past and future values
|
| 1144 |
+
>>> outputs = model(
|
| 1145 |
+
... past_values=batch["past_values"],
|
| 1146 |
+
... future_values=batch["future_values"],
|
| 1147 |
+
... )
|
| 1148 |
+
|
| 1149 |
+
>>> last_hidden_state = outputs.last_hidden_state
|
| 1150 |
+
```"""
|
| 1151 |
+
|
| 1152 |
+
return_dict = return_dict if return_dict is not None else self.config.return_dict
|
| 1153 |
+
output_attentions = output_attentions if output_attentions is not None else self.config.output_attentions
|
| 1154 |
+
output_hidden_states = (
|
| 1155 |
+
output_hidden_states if output_hidden_states is not None else self.config.output_hidden_states
|
| 1156 |
+
)
|
| 1157 |
+
|
| 1158 |
+
if past_observed_mask is None:
|
| 1159 |
+
past_observed_mask = torch.ones_like(past_values)
|
| 1160 |
+
|
| 1161 |
+
# x: tensor [bs x sequence_length x num_input_channels]
|
| 1162 |
+
scaled_past_values, loc, scale = self.scaler(past_values, past_observed_mask)
|
| 1163 |
+
|
| 1164 |
+
# patched_values: [bs x num_input_channels x num_patches x patch_length] for pretrain
|
| 1165 |
+
patched_values = self.patchifier(scaled_past_values)
|
| 1166 |
+
if self.do_mask_input:
|
| 1167 |
+
masked_values, mask = self.masking(patched_values)
|
| 1168 |
+
else:
|
| 1169 |
+
masked_values, mask = self.masking(patched_values), None
|
| 1170 |
+
|
| 1171 |
+
encoder_output = self.encoder(
|
| 1172 |
+
patch_input=masked_values, output_hidden_states=output_hidden_states, output_attentions=output_attentions
|
| 1173 |
+
)
|
| 1174 |
+
|
| 1175 |
+
if not return_dict:
|
| 1176 |
+
outputs = (encoder_output.last_hidden_state, encoder_output.hidden_states, encoder_output.attentions)
|
| 1177 |
+
outputs = outputs + (mask, loc, scale, patched_values)
|
| 1178 |
+
return tuple(v for v in outputs if v is not None)
|
| 1179 |
+
|
| 1180 |
+
return PatchTSTModelOutput(
|
| 1181 |
+
last_hidden_state=encoder_output.last_hidden_state,
|
| 1182 |
+
hidden_states=encoder_output.hidden_states,
|
| 1183 |
+
attentions=encoder_output.attentions,
|
| 1184 |
+
mask=mask,
|
| 1185 |
+
loc=loc,
|
| 1186 |
+
scale=scale,
|
| 1187 |
+
patch_input=patched_values,
|
| 1188 |
+
)
|
| 1189 |
+
|
| 1190 |
+
|
| 1191 |
+
class PatchTSTMaskPretrainHead(nn.Module):
|
| 1192 |
+
"""
|
| 1193 |
+
Pretraining head for mask modelling
|
| 1194 |
+
"""
|
| 1195 |
+
|
| 1196 |
+
def __init__(self, config: PatchTSTConfig):
|
| 1197 |
+
super().__init__()
|
| 1198 |
+
self.dropout = nn.Dropout(config.head_dropout) if config.head_dropout > 0 else nn.Identity()
|
| 1199 |
+
self.linear = nn.Linear(config.d_model, config.patch_length)
|
| 1200 |
+
self.use_cls_token = config.use_cls_token
|
| 1201 |
+
|
| 1202 |
+
def forward(self, embedding: torch.Tensor) -> torch.Tensor:
|
| 1203 |
+
"""
|
| 1204 |
+
Parameters:
|
| 1205 |
+
embedding (`torch.Tensor` of shape `(bs, num_channels, num_patches, d_model)` or
|
| 1206 |
+
`(bs, num_channels, num_patches+1, d_model)` if `cls_token` is set to True, *required*):
|
| 1207 |
+
Embedding from the model
|
| 1208 |
+
Returns:
|
| 1209 |
+
`torch.Tensor` of shape `(bs, num_channels, num_patches, d_model)` or
|
| 1210 |
+
`(bs, num_channels, num_patches+1, d_model)` if `cls_token` is set to True
|
| 1211 |
+
|
| 1212 |
+
"""
|
| 1213 |
+
embedding = self.linear(self.dropout(embedding)) # [bs x num_channels x num_patches x patch_length]
|
| 1214 |
+
if self.use_cls_token:
|
| 1215 |
+
embedding = embedding[:, :, 1:, :] # remove the first cls token
|
| 1216 |
+
return embedding
|
| 1217 |
+
|
| 1218 |
+
|
| 1219 |
+
@auto_docstring(
|
| 1220 |
+
custom_intro="""
|
| 1221 |
+
The PatchTST for pretrain model.
|
| 1222 |
+
"""
|
| 1223 |
+
)
|
| 1224 |
+
class PatchTSTForPretraining(PatchTSTPreTrainedModel):
|
| 1225 |
+
def __init__(self, config: PatchTSTConfig):
|
| 1226 |
+
super().__init__(config)
|
| 1227 |
+
|
| 1228 |
+
config.do_mask_input = True
|
| 1229 |
+
self.model = PatchTSTModel(config=config)
|
| 1230 |
+
self.head = PatchTSTMaskPretrainHead(config)
|
| 1231 |
+
|
| 1232 |
+
# Initialize weights and apply final processing
|
| 1233 |
+
self.post_init()
|
| 1234 |
+
|
| 1235 |
+
def forward(
|
| 1236 |
+
self,
|
| 1237 |
+
past_values: torch.Tensor,
|
| 1238 |
+
past_observed_mask: torch.Tensor | None = None,
|
| 1239 |
+
output_hidden_states: bool | None = None,
|
| 1240 |
+
output_attentions: bool | None = None,
|
| 1241 |
+
return_dict: bool | None = None,
|
| 1242 |
+
**kwargs,
|
| 1243 |
+
) -> tuple | PatchTSTForPretrainingOutput:
|
| 1244 |
+
r"""
|
| 1245 |
+
Parameters:
|
| 1246 |
+
past_values (`torch.Tensor` of shape `(bs, sequence_length, num_input_channels)`, *required*):
|
| 1247 |
+
Input sequence to the model
|
| 1248 |
+
past_observed_mask (`torch.BoolTensor` of shape `(batch_size, sequence_length, num_input_channels)`, *optional*):
|
| 1249 |
+
Boolean mask to indicate which `past_values` were observed and which were missing. Mask values selected
|
| 1250 |
+
in `[0, 1]`:
|
| 1251 |
+
|
| 1252 |
+
- 1 for values that are **observed**,
|
| 1253 |
+
- 0 for values that are **missing** (i.e. NaNs that were replaced by zeros).
|
| 1254 |
+
output_hidden_states (`bool`, *optional*):
|
| 1255 |
+
Whether or not to return the hidden states of all layers
|
| 1256 |
+
output_attentions (`bool`, *optional*):
|
| 1257 |
+
Whether or not to return the output attention of all layers
|
| 1258 |
+
return_dict (`bool`, *optional*): Whether or not to return a `ModelOutput` instead of a plain tuple.
|
| 1259 |
+
|
| 1260 |
+
Returns:
|
| 1261 |
+
`PatchTSTForPretrainingOutput` or tuple of `torch.Tensor` (if `return_dict`=False or
|
| 1262 |
+
`config.return_dict`=False)
|
| 1263 |
+
|
| 1264 |
+
Examples:
|
| 1265 |
+
|
| 1266 |
+
```python
|
| 1267 |
+
>>> from huggingface_hub import hf_hub_download
|
| 1268 |
+
>>> import torch
|
| 1269 |
+
>>> from transformers import PatchTSTConfig, PatchTSTForPretraining
|
| 1270 |
+
|
| 1271 |
+
>>> file = hf_hub_download(
|
| 1272 |
+
... repo_id="hf-internal-testing/etth1-hourly-batch", filename="train-batch.pt", repo_type="dataset"
|
| 1273 |
+
... )
|
| 1274 |
+
>>> batch = torch.load(file)
|
| 1275 |
+
|
| 1276 |
+
>>> # Config for random mask pretraining
|
| 1277 |
+
>>> config = PatchTSTConfig(
|
| 1278 |
+
... num_input_channels=7,
|
| 1279 |
+
... context_length=512,
|
| 1280 |
+
... patch_length=12,
|
| 1281 |
+
... stride=12,
|
| 1282 |
+
... mask_type='random',
|
| 1283 |
+
... random_mask_ratio=0.4,
|
| 1284 |
+
... use_cls_token=True,
|
| 1285 |
+
... )
|
| 1286 |
+
>>> # Config for forecast mask pretraining
|
| 1287 |
+
>>> config = PatchTSTConfig(
|
| 1288 |
+
... num_input_channels=7,
|
| 1289 |
+
... context_length=512,
|
| 1290 |
+
... patch_length=12,
|
| 1291 |
+
... stride=12,
|
| 1292 |
+
... mask_type='forecast',
|
| 1293 |
+
... num_forecast_mask_patches=5,
|
| 1294 |
+
... use_cls_token=True,
|
| 1295 |
+
... )
|
| 1296 |
+
>>> model = PatchTSTForPretraining(config)
|
| 1297 |
+
|
| 1298 |
+
>>> # during training, one provides both past and future values
|
| 1299 |
+
>>> outputs = model(past_values=batch["past_values"])
|
| 1300 |
+
|
| 1301 |
+
>>> loss = outputs.loss
|
| 1302 |
+
>>> loss.backward()
|
| 1303 |
+
```"""
|
| 1304 |
+
|
| 1305 |
+
return_dict = return_dict if return_dict is not None else self.config.return_dict
|
| 1306 |
+
|
| 1307 |
+
# past_values: [bs x num_channels x num_patches x d_model] or
|
| 1308 |
+
# [bs x num_channels x (num_patches+1) x d_model] if use cls_token
|
| 1309 |
+
model_output = self.model(
|
| 1310 |
+
past_values=past_values,
|
| 1311 |
+
past_observed_mask=past_observed_mask,
|
| 1312 |
+
output_hidden_states=output_hidden_states,
|
| 1313 |
+
output_attentions=output_attentions,
|
| 1314 |
+
return_dict=True,
|
| 1315 |
+
)
|
| 1316 |
+
|
| 1317 |
+
# last_hidden_state: [bs x num_channels x num_patches x patch_length] or
|
| 1318 |
+
# [bs x num_channels x (num_patches+1) x patch_length] if use cls_token
|
| 1319 |
+
x_hat = self.head(model_output.last_hidden_state)
|
| 1320 |
+
|
| 1321 |
+
# calculate masked_loss
|
| 1322 |
+
loss = nn.MSELoss(reduction="none")
|
| 1323 |
+
loss_val = loss(x_hat, model_output.patch_input)
|
| 1324 |
+
masked_loss = (loss_val.mean(dim=-1) * model_output.mask).sum() / (model_output.mask.sum() + 1e-10)
|
| 1325 |
+
|
| 1326 |
+
encoder_states = model_output.hidden_states
|
| 1327 |
+
if not return_dict:
|
| 1328 |
+
outputs = (x_hat,) + model_output[1:-4]
|
| 1329 |
+
outputs = (masked_loss,) + outputs if masked_loss is not None else outputs
|
| 1330 |
+
return outputs
|
| 1331 |
+
return PatchTSTForPretrainingOutput(
|
| 1332 |
+
loss=masked_loss, prediction_output=x_hat, hidden_states=encoder_states, attentions=model_output.attentions
|
| 1333 |
+
)
|
| 1334 |
+
|
| 1335 |
+
|
| 1336 |
+
class PatchTSTClassificationHead(nn.Module):
|
| 1337 |
+
def __init__(self, config: PatchTSTConfig):
|
| 1338 |
+
super().__init__()
|
| 1339 |
+
self.use_cls_token = config.use_cls_token
|
| 1340 |
+
self.pooling_type = config.pooling_type
|
| 1341 |
+
self.flatten = nn.Flatten(start_dim=1)
|
| 1342 |
+
self.dropout = nn.Dropout(config.head_dropout) if config.head_dropout > 0 else nn.Identity()
|
| 1343 |
+
self.linear = nn.Linear(config.num_input_channels * config.d_model, config.num_targets)
|
| 1344 |
+
|
| 1345 |
+
def forward(self, embedding: torch.Tensor):
|
| 1346 |
+
"""
|
| 1347 |
+
Parameters:
|
| 1348 |
+
embedding (`torch.Tensor` of shape `(bs, num_channels, num_patches, d_model)` or
|
| 1349 |
+
`(bs, num_channels, num_patches+1, d_model)` if `cls_token` is set to True, *required*):
|
| 1350 |
+
Embedding from the model
|
| 1351 |
+
Returns:
|
| 1352 |
+
`torch.Tensor` of shape `(bs, num_targets)`
|
| 1353 |
+
|
| 1354 |
+
"""
|
| 1355 |
+
if self.use_cls_token:
|
| 1356 |
+
# use the first output token, pooled_embedding: bs x num_channels x d_model
|
| 1357 |
+
pooled_embedding = embedding[:, :, 0, :]
|
| 1358 |
+
elif self.pooling_type == "mean":
|
| 1359 |
+
# pooled_embedding: [bs x num_channels x d_model]
|
| 1360 |
+
pooled_embedding = embedding.mean(dim=2)
|
| 1361 |
+
elif self.pooling_type == "max":
|
| 1362 |
+
# pooled_embedding: [bs x num_channels x d_model]
|
| 1363 |
+
pooled_embedding = embedding.max(dim=2).values
|
| 1364 |
+
else:
|
| 1365 |
+
raise ValueError(f"pooling operator {self.pooling_type} is not implemented yet")
|
| 1366 |
+
# pooled_embedding: bs x num_channels * d_model
|
| 1367 |
+
pooled_embedding = self.flatten(pooled_embedding)
|
| 1368 |
+
# output: bs x n_classes
|
| 1369 |
+
output = self.linear(self.dropout(pooled_embedding))
|
| 1370 |
+
return output
|
| 1371 |
+
|
| 1372 |
+
|
| 1373 |
+
@auto_docstring(
|
| 1374 |
+
custom_intro="""
|
| 1375 |
+
The PatchTST for classification model.
|
| 1376 |
+
"""
|
| 1377 |
+
)
|
| 1378 |
+
class PatchTSTForClassification(PatchTSTPreTrainedModel):
|
| 1379 |
+
def __init__(self, config: PatchTSTConfig):
|
| 1380 |
+
super().__init__(config)
|
| 1381 |
+
|
| 1382 |
+
# Turn off masking
|
| 1383 |
+
if config.do_mask_input:
|
| 1384 |
+
logger.warning("Setting `do_mask_input` parameter to False.")
|
| 1385 |
+
config.do_mask_input = False
|
| 1386 |
+
|
| 1387 |
+
self.model = PatchTSTModel(config)
|
| 1388 |
+
self.head = PatchTSTClassificationHead(config)
|
| 1389 |
+
|
| 1390 |
+
# Initialize weights and apply final processing
|
| 1391 |
+
self.post_init()
|
| 1392 |
+
|
| 1393 |
+
@auto_docstring
|
| 1394 |
+
def forward(
|
| 1395 |
+
self,
|
| 1396 |
+
past_values: torch.Tensor,
|
| 1397 |
+
target_values: torch.Tensor | None = None,
|
| 1398 |
+
past_observed_mask: bool | None = None,
|
| 1399 |
+
output_hidden_states: bool | None = None,
|
| 1400 |
+
output_attentions: bool | None = None,
|
| 1401 |
+
return_dict: bool | None = None,
|
| 1402 |
+
**kwargs,
|
| 1403 |
+
) -> tuple | PatchTSTForClassificationOutput:
|
| 1404 |
+
r"""
|
| 1405 |
+
past_values (`torch.Tensor` of shape `(bs, sequence_length, num_input_channels)`, *required*):
|
| 1406 |
+
Input sequence to the model
|
| 1407 |
+
target_values (`torch.Tensor`, *optional*):
|
| 1408 |
+
Labels associates with the `past_values`
|
| 1409 |
+
past_observed_mask (`torch.BoolTensor` of shape `(batch_size, sequence_length, num_input_channels)`, *optional*):
|
| 1410 |
+
Boolean mask to indicate which `past_values` were observed and which were missing. Mask values selected
|
| 1411 |
+
in `[0, 1]`:
|
| 1412 |
+
|
| 1413 |
+
- 1 for values that are **observed**,
|
| 1414 |
+
- 0 for values that are **missing** (i.e. NaNs that were replaced by zeros).
|
| 1415 |
+
|
| 1416 |
+
Examples:
|
| 1417 |
+
|
| 1418 |
+
```python
|
| 1419 |
+
>>> from transformers import PatchTSTConfig, PatchTSTForClassification
|
| 1420 |
+
|
| 1421 |
+
>>> # classification task with two input channel2 and 3 classes
|
| 1422 |
+
>>> config = PatchTSTConfig(
|
| 1423 |
+
... num_input_channels=2,
|
| 1424 |
+
... num_targets=3,
|
| 1425 |
+
... context_length=512,
|
| 1426 |
+
... patch_length=12,
|
| 1427 |
+
... stride=12,
|
| 1428 |
+
... use_cls_token=True,
|
| 1429 |
+
... )
|
| 1430 |
+
>>> model = PatchTSTForClassification(config=config)
|
| 1431 |
+
|
| 1432 |
+
>>> # during inference, one only provides past values
|
| 1433 |
+
>>> past_values = torch.randn(20, 512, 2)
|
| 1434 |
+
>>> outputs = model(past_values=past_values)
|
| 1435 |
+
>>> labels = outputs.prediction_logits
|
| 1436 |
+
```"""
|
| 1437 |
+
|
| 1438 |
+
return_dict = return_dict if return_dict is not None else self.config.return_dict
|
| 1439 |
+
|
| 1440 |
+
model_output = self.model(
|
| 1441 |
+
past_values=past_values,
|
| 1442 |
+
past_observed_mask=past_observed_mask,
|
| 1443 |
+
output_hidden_states=output_hidden_states,
|
| 1444 |
+
output_attentions=output_attentions,
|
| 1445 |
+
return_dict=True,
|
| 1446 |
+
)
|
| 1447 |
+
y_hat = self.head(model_output.last_hidden_state)
|
| 1448 |
+
|
| 1449 |
+
loss_val = None
|
| 1450 |
+
if target_values is not None:
|
| 1451 |
+
loss = nn.CrossEntropyLoss()
|
| 1452 |
+
loss_val = loss(y_hat, target_values)
|
| 1453 |
+
|
| 1454 |
+
if not return_dict:
|
| 1455 |
+
outputs = (y_hat,) + model_output[1:-3]
|
| 1456 |
+
outputs = (loss_val,) + outputs if loss_val is not None else outputs
|
| 1457 |
+
return outputs
|
| 1458 |
+
return PatchTSTForClassificationOutput(
|
| 1459 |
+
loss=loss_val,
|
| 1460 |
+
prediction_logits=y_hat,
|
| 1461 |
+
hidden_states=model_output.hidden_states,
|
| 1462 |
+
attentions=model_output.attentions,
|
| 1463 |
+
)
|
| 1464 |
+
|
| 1465 |
+
|
| 1466 |
+
@auto_docstring(
|
| 1467 |
+
custom_intro="""
|
| 1468 |
+
The PatchTST for regression Model.
|
| 1469 |
+
"""
|
| 1470 |
+
)
|
| 1471 |
+
class PatchTSTPredictionHead(nn.Module):
|
| 1472 |
+
def __init__(self, config: PatchTSTConfig, num_patches: int, distribution_output=None):
|
| 1473 |
+
r"""
|
| 1474 |
+
num_patches (`int`):
|
| 1475 |
+
The number of patches in the input sequence.
|
| 1476 |
+
distribution_output (`DistributionOutput`, *optional*):
|
| 1477 |
+
The distribution output layer for probabilistic forecasting. If None, a linear output layer is used.
|
| 1478 |
+
"""
|
| 1479 |
+
super().__init__()
|
| 1480 |
+
|
| 1481 |
+
self.share_projection = config.share_projection
|
| 1482 |
+
self.num_input_channels = config.num_input_channels
|
| 1483 |
+
self.use_cls_token = config.use_cls_token
|
| 1484 |
+
self.pooling_type = config.pooling_type
|
| 1485 |
+
if self.pooling_type or self.use_cls_token:
|
| 1486 |
+
head_dim = config.d_model
|
| 1487 |
+
else:
|
| 1488 |
+
head_dim = config.d_model * num_patches
|
| 1489 |
+
|
| 1490 |
+
if not self.share_projection:
|
| 1491 |
+
# if each channel has its own head
|
| 1492 |
+
self.projections = nn.ModuleList()
|
| 1493 |
+
self.dropouts = nn.ModuleList()
|
| 1494 |
+
self.flattens = nn.ModuleList()
|
| 1495 |
+
for i in range(self.num_input_channels):
|
| 1496 |
+
self.flattens.append(nn.Flatten(start_dim=2))
|
| 1497 |
+
if distribution_output is None:
|
| 1498 |
+
# use linear head
|
| 1499 |
+
self.projections.append(nn.Linear(head_dim, config.prediction_length))
|
| 1500 |
+
else:
|
| 1501 |
+
# use distribution head
|
| 1502 |
+
self.projections.append(distribution_output.get_parameter_projection(head_dim))
|
| 1503 |
+
self.dropouts.append(nn.Dropout(config.head_dropout) if config.head_dropout > 0 else nn.Identity())
|
| 1504 |
+
else:
|
| 1505 |
+
# all the channels share the same head
|
| 1506 |
+
self.flatten = nn.Flatten(start_dim=2)
|
| 1507 |
+
if distribution_output is None:
|
| 1508 |
+
# use linear head
|
| 1509 |
+
self.projection = nn.Linear(head_dim, config.prediction_length)
|
| 1510 |
+
else:
|
| 1511 |
+
# use distribution head
|
| 1512 |
+
self.projection = distribution_output.get_parameter_projection(head_dim)
|
| 1513 |
+
self.dropout = nn.Dropout(config.head_dropout) if config.head_dropout > 0 else nn.Identity()
|
| 1514 |
+
|
| 1515 |
+
def forward(self, embedding: torch.Tensor):
|
| 1516 |
+
"""
|
| 1517 |
+
Parameters:
|
| 1518 |
+
embedding (`torch.Tensor` of shape `(bs, num_channels, num_patches, d_model)` or
|
| 1519 |
+
`(bs, num_channels, num_patches+1, d_model)` if `cls_token` is set to True, *required*):
|
| 1520 |
+
Embedding from the model
|
| 1521 |
+
Returns:
|
| 1522 |
+
`torch.Tensor` of shape `(bs, forecast_len, num_channels)`
|
| 1523 |
+
|
| 1524 |
+
"""
|
| 1525 |
+
if self.use_cls_token:
|
| 1526 |
+
# pooled_embedding: [bs x num_channels x d_model]
|
| 1527 |
+
pooled_embedding = embedding[:, :, 0, :]
|
| 1528 |
+
else:
|
| 1529 |
+
if self.pooling_type == "mean":
|
| 1530 |
+
# pooled_embedding: [bs x num_channels x d_model]
|
| 1531 |
+
pooled_embedding = embedding.mean(dim=2)
|
| 1532 |
+
elif self.pooling_type == "max":
|
| 1533 |
+
# pooled_embedding: [bs x num_channels x d_model]
|
| 1534 |
+
pooled_embedding = embedding.max(dim=2).values
|
| 1535 |
+
else:
|
| 1536 |
+
# pooled_embedding: [bs x num_channels x num_patches x d_model]
|
| 1537 |
+
pooled_embedding = embedding
|
| 1538 |
+
|
| 1539 |
+
if not self.share_projection:
|
| 1540 |
+
output = []
|
| 1541 |
+
for i in range(self.num_input_channels):
|
| 1542 |
+
# pooled_embedding: [bs x (d_model * num_patches)] or [bs x d_model)]
|
| 1543 |
+
pooled_embedding = self.flattens[i](pooled_embedding[:, i, :])
|
| 1544 |
+
pooled_embedding = self.dropouts[i](pooled_embedding)
|
| 1545 |
+
# pooled_embedding: [bs x forecast_len]
|
| 1546 |
+
# or tuple ([bs x forecast_len], [bs x forecast_len]) if using distribution head
|
| 1547 |
+
pooled_embedding = self.projections[i](pooled_embedding)
|
| 1548 |
+
output.append(pooled_embedding)
|
| 1549 |
+
# output: [bs x num_channels x forecast_len]
|
| 1550 |
+
output = torch.stack(output, dim=1)
|
| 1551 |
+
else:
|
| 1552 |
+
# pooled_embedding: [bs x num_channels x (d_model * num_patches)] or [bs x num_channels x d_model)]
|
| 1553 |
+
pooled_embedding = self.flatten(pooled_embedding)
|
| 1554 |
+
pooled_embedding = self.dropout(pooled_embedding)
|
| 1555 |
+
# output: [bs x num_channels x forecast_len] or
|
| 1556 |
+
# tuple ([bs x num_channels x forecast_len], [bs x num_channels x forecast_len]) if using distribution head
|
| 1557 |
+
output = self.projection(pooled_embedding)
|
| 1558 |
+
|
| 1559 |
+
if isinstance(output, tuple):
|
| 1560 |
+
# output: ([bs x forecast_len x num_channels], [bs x forecast_len x num_channels])
|
| 1561 |
+
output = tuple(z.transpose(2, 1) for z in output)
|
| 1562 |
+
else:
|
| 1563 |
+
output = output.transpose(2, 1) # [bs x forecast_len x num_channels]
|
| 1564 |
+
return output
|
| 1565 |
+
|
| 1566 |
+
|
| 1567 |
+
@auto_docstring(
|
| 1568 |
+
custom_intro="""
|
| 1569 |
+
The PatchTST for prediction model.
|
| 1570 |
+
"""
|
| 1571 |
+
)
|
| 1572 |
+
class PatchTSTForPrediction(PatchTSTPreTrainedModel):
|
| 1573 |
+
def __init__(self, config: PatchTSTConfig):
|
| 1574 |
+
super().__init__(config)
|
| 1575 |
+
|
| 1576 |
+
# Turn off masking
|
| 1577 |
+
if config.do_mask_input:
|
| 1578 |
+
logger.warning("Setting `do_mask_input` parameter to False.")
|
| 1579 |
+
config.do_mask_input = False
|
| 1580 |
+
|
| 1581 |
+
self.model = PatchTSTModel(config)
|
| 1582 |
+
|
| 1583 |
+
if config.loss == "mse":
|
| 1584 |
+
self.distribution_output = None
|
| 1585 |
+
else:
|
| 1586 |
+
if config.distribution_output == "student_t":
|
| 1587 |
+
self.distribution_output = StudentTOutput(dim=config.prediction_length)
|
| 1588 |
+
elif config.distribution_output == "normal":
|
| 1589 |
+
self.distribution_output = NormalOutput(dim=config.prediction_length)
|
| 1590 |
+
elif config.distribution_output == "negative_binomial":
|
| 1591 |
+
self.distribution_output = NegativeBinomialOutput(dim=config.prediction_length)
|
| 1592 |
+
else:
|
| 1593 |
+
raise ValueError(f"Unknown distribution output {config.distribution_output}")
|
| 1594 |
+
|
| 1595 |
+
self.head = PatchTSTPredictionHead(
|
| 1596 |
+
config, self.model.patchifier.num_patches, distribution_output=self.distribution_output
|
| 1597 |
+
)
|
| 1598 |
+
|
| 1599 |
+
# Initialize weights and apply final processing
|
| 1600 |
+
self.post_init()
|
| 1601 |
+
|
| 1602 |
+
def forward(
|
| 1603 |
+
self,
|
| 1604 |
+
past_values: torch.Tensor,
|
| 1605 |
+
past_observed_mask: torch.Tensor | None = None,
|
| 1606 |
+
future_values: torch.Tensor | None = None,
|
| 1607 |
+
output_hidden_states: bool | None = None,
|
| 1608 |
+
output_attentions: bool | None = None,
|
| 1609 |
+
return_dict: bool | None = None,
|
| 1610 |
+
**kwargs,
|
| 1611 |
+
) -> tuple | PatchTSTForPredictionOutput:
|
| 1612 |
+
r"""
|
| 1613 |
+
Parameters:
|
| 1614 |
+
past_values (`torch.Tensor` of shape `(bs, sequence_length, num_input_channels)`, *required*):
|
| 1615 |
+
Input sequence to the model
|
| 1616 |
+
past_observed_mask (`torch.BoolTensor` of shape `(batch_size, sequence_length, num_input_channels)`, *optional*):
|
| 1617 |
+
Boolean mask to indicate which `past_values` were observed and which were missing. Mask values selected
|
| 1618 |
+
in `[0, 1]`:
|
| 1619 |
+
|
| 1620 |
+
- 1 for values that are **observed**,
|
| 1621 |
+
- 0 for values that are **missing** (i.e. NaNs that were replaced by zeros).
|
| 1622 |
+
future_values (`torch.Tensor` of shape `(bs, forecast_len, num_input_channels)`, *optional*):
|
| 1623 |
+
Future target values associated with the `past_values`
|
| 1624 |
+
output_hidden_states (`bool`, *optional*):
|
| 1625 |
+
Whether or not to return the hidden states of all layers
|
| 1626 |
+
output_attentions (`bool`, *optional*):
|
| 1627 |
+
Whether or not to return the output attention of all layers
|
| 1628 |
+
return_dict (`bool`, *optional*):
|
| 1629 |
+
Whether or not to return a `ModelOutput` instead of a plain tuple.
|
| 1630 |
+
|
| 1631 |
+
Returns:
|
| 1632 |
+
`PatchTSTForPredictionOutput` or tuple of `torch.Tensor` (if `return_dict`=False or
|
| 1633 |
+
`config.return_dict`=False)
|
| 1634 |
+
|
| 1635 |
+
Examples:
|
| 1636 |
+
|
| 1637 |
+
```python
|
| 1638 |
+
>>> from huggingface_hub import hf_hub_download
|
| 1639 |
+
>>> import torch
|
| 1640 |
+
>>> from transformers import PatchTSTConfig, PatchTSTForPrediction
|
| 1641 |
+
|
| 1642 |
+
>>> file = hf_hub_download(
|
| 1643 |
+
... repo_id="hf-internal-testing/etth1-hourly-batch", filename="train-batch.pt", repo_type="dataset"
|
| 1644 |
+
... )
|
| 1645 |
+
>>> batch = torch.load(file)
|
| 1646 |
+
|
| 1647 |
+
>>> # Prediction task with 7 input channels and prediction length is 96
|
| 1648 |
+
>>> model = PatchTSTForPrediction.from_pretrained("namctin/patchtst_etth1_forecast")
|
| 1649 |
+
|
| 1650 |
+
>>> # during training, one provides both past and future values
|
| 1651 |
+
>>> outputs = model(
|
| 1652 |
+
... past_values=batch["past_values"],
|
| 1653 |
+
... future_values=batch["future_values"],
|
| 1654 |
+
... )
|
| 1655 |
+
|
| 1656 |
+
>>> loss = outputs.loss
|
| 1657 |
+
>>> loss.backward()
|
| 1658 |
+
|
| 1659 |
+
>>> # during inference, one only provides past values, the model outputs future values
|
| 1660 |
+
>>> outputs = model(past_values=batch["past_values"])
|
| 1661 |
+
>>> prediction_outputs = outputs.prediction_outputs
|
| 1662 |
+
```"""
|
| 1663 |
+
|
| 1664 |
+
return_dict = return_dict if return_dict is not None else self.config.return_dict
|
| 1665 |
+
|
| 1666 |
+
# get model output
|
| 1667 |
+
model_output = self.model(
|
| 1668 |
+
past_values=past_values,
|
| 1669 |
+
past_observed_mask=past_observed_mask,
|
| 1670 |
+
output_hidden_states=output_hidden_states,
|
| 1671 |
+
output_attentions=output_attentions,
|
| 1672 |
+
return_dict=True,
|
| 1673 |
+
)
|
| 1674 |
+
# get output head
|
| 1675 |
+
y_hat = self.head(model_output.last_hidden_state)
|
| 1676 |
+
|
| 1677 |
+
loss_val = None
|
| 1678 |
+
|
| 1679 |
+
if self.distribution_output:
|
| 1680 |
+
y_hat_out = y_hat
|
| 1681 |
+
else:
|
| 1682 |
+
y_hat_out = y_hat * model_output.scale + model_output.loc
|
| 1683 |
+
|
| 1684 |
+
if future_values is not None:
|
| 1685 |
+
if self.distribution_output:
|
| 1686 |
+
distribution = self.distribution_output.distribution(
|
| 1687 |
+
y_hat, loc=model_output.loc, scale=model_output.scale
|
| 1688 |
+
)
|
| 1689 |
+
loss_val = nll(distribution, future_values)
|
| 1690 |
+
# take average of the loss
|
| 1691 |
+
loss_val = weighted_average(loss_val)
|
| 1692 |
+
else:
|
| 1693 |
+
loss = nn.MSELoss(reduction="mean")
|
| 1694 |
+
loss_val = loss(y_hat_out, future_values)
|
| 1695 |
+
|
| 1696 |
+
loc = model_output.loc
|
| 1697 |
+
scale = model_output.scale
|
| 1698 |
+
|
| 1699 |
+
if not return_dict:
|
| 1700 |
+
outputs = (y_hat_out,) + model_output[1:-1]
|
| 1701 |
+
outputs = (loss_val,) + outputs if loss_val is not None else outputs
|
| 1702 |
+
return outputs
|
| 1703 |
+
return PatchTSTForPredictionOutput(
|
| 1704 |
+
loss=loss_val,
|
| 1705 |
+
prediction_outputs=y_hat_out,
|
| 1706 |
+
hidden_states=model_output.hidden_states,
|
| 1707 |
+
attentions=model_output.attentions,
|
| 1708 |
+
loc=loc,
|
| 1709 |
+
scale=scale,
|
| 1710 |
+
)
|
| 1711 |
+
|
| 1712 |
+
@torch.no_grad()
|
| 1713 |
+
def generate(
|
| 1714 |
+
self,
|
| 1715 |
+
past_values: torch.Tensor,
|
| 1716 |
+
past_observed_mask: torch.Tensor | None = None,
|
| 1717 |
+
) -> SamplePatchTSTOutput:
|
| 1718 |
+
"""
|
| 1719 |
+
Generate sequences of sample predictions from a model with a probability distribution head.
|
| 1720 |
+
|
| 1721 |
+
Parameters:
|
| 1722 |
+
past_values (`torch.FloatTensor` of shape `(batch_size, sequence_length, num_input_channels)`):
|
| 1723 |
+
Past values of the time series that serves as context in order to predict the future.
|
| 1724 |
+
past_observed_mask (`torch.BoolTensor` of shape `(batch_size, sequence_length, num_input_channels)`, *optional*):
|
| 1725 |
+
Boolean mask to indicate which `past_values` were observed and which were missing. Mask values selected
|
| 1726 |
+
in `[0, 1]`:
|
| 1727 |
+
|
| 1728 |
+
- 1 for values that are **observed**,
|
| 1729 |
+
- 0 for values that are **missing** (i.e. NaNs that were replaced by zeros).
|
| 1730 |
+
|
| 1731 |
+
Return:
|
| 1732 |
+
[`SamplePatchTSTOutput`] where the outputs `sequences` tensor will have shape `(batch_size, number of
|
| 1733 |
+
samples, prediction_length, 1)` or `(batch_size, number of samples, prediction_length, num_input_channels)`
|
| 1734 |
+
for multivariate predictions.
|
| 1735 |
+
"""
|
| 1736 |
+
# get number of samples
|
| 1737 |
+
num_parallel_samples = self.config.num_parallel_samples
|
| 1738 |
+
|
| 1739 |
+
# get model output
|
| 1740 |
+
outputs = self(
|
| 1741 |
+
past_values=past_values,
|
| 1742 |
+
future_values=None,
|
| 1743 |
+
past_observed_mask=past_observed_mask,
|
| 1744 |
+
output_hidden_states=False,
|
| 1745 |
+
)
|
| 1746 |
+
if self.distribution_output:
|
| 1747 |
+
# get distribution
|
| 1748 |
+
distribution = self.distribution_output.distribution(
|
| 1749 |
+
outputs.prediction_outputs, loc=outputs.loc, scale=outputs.scale
|
| 1750 |
+
)
|
| 1751 |
+
# get samples: list of [bs x forecast_len x num_channels]
|
| 1752 |
+
samples = [distribution.sample() for _ in range(num_parallel_samples)]
|
| 1753 |
+
# samples: [bs x num_samples x forecast_len x num_channels]
|
| 1754 |
+
samples = torch.stack(samples, dim=1)
|
| 1755 |
+
else:
|
| 1756 |
+
samples = outputs.prediction_outputs.unsqueeze(1)
|
| 1757 |
+
|
| 1758 |
+
return SamplePatchTSTOutput(sequences=samples)
|
| 1759 |
+
|
| 1760 |
+
|
| 1761 |
+
class PatchTSTRegressionHead(nn.Module):
|
| 1762 |
+
"""
|
| 1763 |
+
Regression head
|
| 1764 |
+
"""
|
| 1765 |
+
|
| 1766 |
+
def __init__(self, config: PatchTSTConfig, distribution_output=None):
|
| 1767 |
+
super().__init__()
|
| 1768 |
+
self.y_range = config.output_range
|
| 1769 |
+
self.use_cls_token = config.use_cls_token
|
| 1770 |
+
self.pooling_type = config.pooling_type
|
| 1771 |
+
self.distribution_output = distribution_output
|
| 1772 |
+
|
| 1773 |
+
head_dim = config.num_input_channels * config.d_model
|
| 1774 |
+
|
| 1775 |
+
self.flatten = nn.Flatten(start_dim=1)
|
| 1776 |
+
self.dropout = nn.Dropout(config.head_dropout) if config.head_dropout > 0 else nn.Identity()
|
| 1777 |
+
|
| 1778 |
+
if distribution_output is None:
|
| 1779 |
+
self.projection = nn.Linear(head_dim, config.num_targets)
|
| 1780 |
+
else:
|
| 1781 |
+
self.projection = distribution_output.get_parameter_projection(head_dim)
|
| 1782 |
+
|
| 1783 |
+
def forward(self, embedding: torch.Tensor):
|
| 1784 |
+
"""
|
| 1785 |
+
Parameters:
|
| 1786 |
+
embedding (`torch.Tensor` of shape `(bs, num_channels, num_patches, d_model)` or
|
| 1787 |
+
`(bs, num_channels, num_patches+1, d_model)` if `cls_token` is set to True, *required*):
|
| 1788 |
+
Embedding from the model
|
| 1789 |
+
Returns:
|
| 1790 |
+
`torch.Tensor` of shape `(bs, output_dim)`
|
| 1791 |
+
|
| 1792 |
+
"""
|
| 1793 |
+
if self.use_cls_token:
|
| 1794 |
+
# use the first output token, pooled_embedding: [bs x num_channels x d_model]
|
| 1795 |
+
pooled_embedding = embedding[:, :, 0, :]
|
| 1796 |
+
elif self.pooling_type == "mean":
|
| 1797 |
+
# pooled_embedding: [bs x num_channels x d_model]
|
| 1798 |
+
pooled_embedding = embedding.mean(dim=2)
|
| 1799 |
+
elif self.pooling_type == "max":
|
| 1800 |
+
# pooled_embedding: [bs x num_channels x d_model]
|
| 1801 |
+
pooled_embedding = embedding.max(dim=2).values
|
| 1802 |
+
else:
|
| 1803 |
+
raise ValueError(f"pooling operator {self.pooling_type} is not implemented yet")
|
| 1804 |
+
# flatten the input
|
| 1805 |
+
# pooled_embedding: bs x (num_channels * d_model)
|
| 1806 |
+
pooled_embedding = self.dropout(self.flatten(pooled_embedding))
|
| 1807 |
+
# projection
|
| 1808 |
+
# output: bs x output_dim or a tuple of this shape for distribution head
|
| 1809 |
+
output = self.projection(pooled_embedding)
|
| 1810 |
+
# apply sigmoid to bound the output if required
|
| 1811 |
+
if (self.distribution_output is None) & (self.y_range is not None): # linear head
|
| 1812 |
+
output = torch.sigmoid(output) * (self.y_range[1] - self.y_range[0]) + self.y_range[0]
|
| 1813 |
+
return output
|
| 1814 |
+
|
| 1815 |
+
|
| 1816 |
+
@auto_docstring(
|
| 1817 |
+
custom_intro="""
|
| 1818 |
+
The PatchTST for regression model.
|
| 1819 |
+
"""
|
| 1820 |
+
)
|
| 1821 |
+
class PatchTSTForRegression(PatchTSTPreTrainedModel):
|
| 1822 |
+
def __init__(self, config: PatchTSTConfig):
|
| 1823 |
+
super().__init__(config)
|
| 1824 |
+
|
| 1825 |
+
# Turn off masking
|
| 1826 |
+
if config.do_mask_input:
|
| 1827 |
+
logger.warning("Setting `do_mask_input` parameter to False.")
|
| 1828 |
+
config.do_mask_input = False
|
| 1829 |
+
|
| 1830 |
+
self.model = PatchTSTModel(config)
|
| 1831 |
+
if config.loss == "mse":
|
| 1832 |
+
self.distribution_output = None
|
| 1833 |
+
else:
|
| 1834 |
+
if config.distribution_output == "student_t":
|
| 1835 |
+
self.distribution_output = StudentTOutput(dim=config.num_targets)
|
| 1836 |
+
elif config.distribution_output == "normal":
|
| 1837 |
+
self.distribution_output = NormalOutput(dim=config.num_targets)
|
| 1838 |
+
elif config.distribution_output == "negative_binomial":
|
| 1839 |
+
self.distribution_output = NegativeBinomialOutput(dim=config.num_targets)
|
| 1840 |
+
else:
|
| 1841 |
+
raise ValueError(f"Unknown distribution output {config.distribution_output}")
|
| 1842 |
+
|
| 1843 |
+
self.head = PatchTSTRegressionHead(config, self.distribution_output)
|
| 1844 |
+
|
| 1845 |
+
# Initialize weights and apply final processing
|
| 1846 |
+
self.post_init()
|
| 1847 |
+
|
| 1848 |
+
@auto_docstring
|
| 1849 |
+
def forward(
|
| 1850 |
+
self,
|
| 1851 |
+
past_values: torch.Tensor,
|
| 1852 |
+
target_values: torch.Tensor | None = None,
|
| 1853 |
+
past_observed_mask: torch.Tensor | None = None,
|
| 1854 |
+
output_hidden_states: bool | None = None,
|
| 1855 |
+
output_attentions: bool | None = None,
|
| 1856 |
+
return_dict: bool | None = None,
|
| 1857 |
+
**kwargs,
|
| 1858 |
+
) -> tuple | PatchTSTForRegressionOutput:
|
| 1859 |
+
r"""
|
| 1860 |
+
past_values (`torch.Tensor` of shape `(bs, sequence_length, num_input_channels)`, *required*):
|
| 1861 |
+
Input sequence to the model
|
| 1862 |
+
target_values (`torch.Tensor` of shape `(bs, num_input_channels)`):
|
| 1863 |
+
Target values associates with the `past_values`
|
| 1864 |
+
past_observed_mask (`torch.BoolTensor` of shape `(batch_size, sequence_length, num_input_channels)`, *optional*):
|
| 1865 |
+
Boolean mask to indicate which `past_values` were observed and which were missing. Mask values selected
|
| 1866 |
+
in `[0, 1]`:
|
| 1867 |
+
|
| 1868 |
+
- 1 for values that are **observed**,
|
| 1869 |
+
- 0 for values that are **missing** (i.e. NaNs that were replaced by zeros).
|
| 1870 |
+
Whether or not to return a `ModelOutput` instead of a plain tuple.
|
| 1871 |
+
|
| 1872 |
+
Examples:
|
| 1873 |
+
|
| 1874 |
+
```python
|
| 1875 |
+
>>> from transformers import PatchTSTConfig, PatchTSTForRegression
|
| 1876 |
+
|
| 1877 |
+
>>> # Regression task with 6 input channels and regress 2 targets
|
| 1878 |
+
>>> model = PatchTSTForRegression.from_pretrained("namctin/patchtst_etth1_regression")
|
| 1879 |
+
|
| 1880 |
+
>>> # during inference, one only provides past values, the model outputs future values
|
| 1881 |
+
>>> past_values = torch.randn(20, 512, 6)
|
| 1882 |
+
>>> outputs = model(past_values=past_values)
|
| 1883 |
+
>>> regression_outputs = outputs.regression_outputs
|
| 1884 |
+
```"""
|
| 1885 |
+
|
| 1886 |
+
return_dict = return_dict if return_dict is not None else self.config.return_dict
|
| 1887 |
+
|
| 1888 |
+
model_output = self.model(
|
| 1889 |
+
past_values=past_values,
|
| 1890 |
+
past_observed_mask=past_observed_mask,
|
| 1891 |
+
output_hidden_states=output_hidden_states,
|
| 1892 |
+
output_attentions=output_attentions,
|
| 1893 |
+
return_dict=True,
|
| 1894 |
+
)
|
| 1895 |
+
# get output head. y_hat is of shape [bs x num_targets] or tuple of this shape
|
| 1896 |
+
y_hat = self.head(model_output.last_hidden_state)
|
| 1897 |
+
|
| 1898 |
+
loss = None
|
| 1899 |
+
if target_values is not None:
|
| 1900 |
+
if self.distribution_output:
|
| 1901 |
+
distribution = self.distribution_output.distribution(y_hat)
|
| 1902 |
+
# y_hat should be a 2-tuple, each with dimension [bs, num_targets]
|
| 1903 |
+
y_hat = tuple(item.view(-1, self.config.num_targets) for item in y_hat)
|
| 1904 |
+
loss = nll(distribution, target_values)
|
| 1905 |
+
# take average of the loss
|
| 1906 |
+
loss = weighted_average(loss)
|
| 1907 |
+
else:
|
| 1908 |
+
loss = nn.MSELoss(reduction="mean")
|
| 1909 |
+
loss = loss(y_hat, target_values)
|
| 1910 |
+
|
| 1911 |
+
if not return_dict:
|
| 1912 |
+
# hidden_states, attentions, mask
|
| 1913 |
+
outputs = (y_hat,) + model_output[1:-3]
|
| 1914 |
+
outputs = (loss,) + outputs if loss is not None else outputs
|
| 1915 |
+
return outputs
|
| 1916 |
+
return PatchTSTForRegressionOutput(
|
| 1917 |
+
loss=loss,
|
| 1918 |
+
regression_outputs=y_hat,
|
| 1919 |
+
hidden_states=model_output.hidden_states,
|
| 1920 |
+
attentions=model_output.attentions,
|
| 1921 |
+
)
|
| 1922 |
+
|
| 1923 |
+
@torch.no_grad()
|
| 1924 |
+
def generate(
|
| 1925 |
+
self,
|
| 1926 |
+
past_values: torch.Tensor,
|
| 1927 |
+
past_observed_mask: torch.Tensor | None = None,
|
| 1928 |
+
) -> SamplePatchTSTOutput:
|
| 1929 |
+
"""
|
| 1930 |
+
Generate sequences of sample predictions from a model with a probability distribution head.
|
| 1931 |
+
|
| 1932 |
+
Parameters:
|
| 1933 |
+
past_values (`torch.FloatTensor` of shape `(batch_size, sequence_length, num_input_channels)`):
|
| 1934 |
+
Past values of the time series that serves as context in order to predict the future.
|
| 1935 |
+
past_observed_mask (`torch.BoolTensor` of shape `(batch_size, sequence_length, num_input_channels)`, *optional*):
|
| 1936 |
+
Boolean mask to indicate which `past_values` were observed and which were missing. Mask values selected
|
| 1937 |
+
in `[0, 1]`:
|
| 1938 |
+
|
| 1939 |
+
- 1 for values that are **observed**,
|
| 1940 |
+
- 0 for values that are **missing** (i.e. NaNs that were replaced by zeros).
|
| 1941 |
+
|
| 1942 |
+
Return:
|
| 1943 |
+
[`SamplePatchTSTOutput`] where the outputs `sequences` tensor will have shape `(batch_size, number of
|
| 1944 |
+
samples, num_targets)`.
|
| 1945 |
+
"""
|
| 1946 |
+
# get number of samples
|
| 1947 |
+
num_parallel_samples = self.config.num_parallel_samples
|
| 1948 |
+
|
| 1949 |
+
# get model output
|
| 1950 |
+
outputs = self(
|
| 1951 |
+
past_values=past_values,
|
| 1952 |
+
target_values=None,
|
| 1953 |
+
past_observed_mask=past_observed_mask,
|
| 1954 |
+
output_hidden_states=False,
|
| 1955 |
+
)
|
| 1956 |
+
|
| 1957 |
+
# get distribution
|
| 1958 |
+
distribution = self.distribution_output.distribution(outputs.regression_outputs)
|
| 1959 |
+
# get samples: list of [bs x num_targets]
|
| 1960 |
+
samples = [distribution.sample() for _ in range(num_parallel_samples)]
|
| 1961 |
+
# samples: [bs x num_samples x num_targets]
|
| 1962 |
+
samples = torch.stack(samples, dim=1).view(-1, num_parallel_samples, self.config.num_targets)
|
| 1963 |
+
return SamplePatchTSTOutput(sequences=samples)
|
| 1964 |
+
|
| 1965 |
+
|
| 1966 |
+
__all__ = [
|
| 1967 |
+
"PatchTSTModel",
|
| 1968 |
+
"PatchTSTPreTrainedModel",
|
| 1969 |
+
"PatchTSTForPrediction",
|
| 1970 |
+
"PatchTSTForPretraining",
|
| 1971 |
+
"PatchTSTForRegression",
|
| 1972 |
+
"PatchTSTForClassification",
|
| 1973 |
+
]
|
LTA_openwebtext_dualt/mini_owt_logdirichlet/runs/owt_t5_elftokenized_full_len1024_C1_to_1024_pow1_d768_l12_h12_gbs512_8gpu_50ep_lr3e4_elfopt_t5embed_unfixed_stateprobadd_selfcond_ce_fast_20260531_230026/step_001000.pt
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:1aa341eb9ed99506627f80f4b70887e720d25512825a349a73cf28fe114cd46b
|
| 3 |
+
size 515519058
|
LTA_openwebtext_dualt/mini_owt_logdirichlet/runs/owt_t5_elftokenized_full_len1024_C1_to_1024_pow1_d768_l12_h12_gbs512_8gpu_50ep_lr3e4_elfopt_t5embed_unfixed_stateprobadd_selfcond_ce_fast_20260531_230026/step_036000.pt
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:5b2d72944bb49d0bcb8bbb5f01497fe800afeaf9cc5fbd3e27d0424c7d08e861
|
| 3 |
+
size 515519058
|
LTA_openwebtext_dualt/mini_owt_logdirichlet/runs/owt_t5_elftokenized_full_len1024_C1_to_1024_pow1_d768_l12_h12_gbs512_8gpu_50ep_lr3e4_elfopt_t5embed_unfixed_stateprobadd_selfcond_ce_fast_20260531_230026/step_038000.pt
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:1ad049284a7e7301eb78966cc2be57487df86efe92e711a03e7fd48400173973
|
| 3 |
+
size 515519058
|
LTA_openwebtext_dualt/mini_owt_logdirichlet/runs/owt_t5_elftokenized_full_len1024_C1_to_1024_pow1_d768_l12_h12_gbs512_8gpu_50ep_lr3e4_elfopt_t5embed_unfixed_stateprobadd_selfcond_ce_fast_20260531_230026/step_100000.pt
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:87fdeaead6e09d7836628bbdd5a5bc626b6edc0b3c54efbd4b382a50c5cbe84f
|
| 3 |
+
size 515519058
|
LTA_openwebtext_dualt/mini_owt_logdirichlet/runs/owt_t5_elftokenized_full_len1024_C1_to_1024_pow1_d768_l12_h12_gbs512_8gpu_50ep_lr3e4_elfopt_t5embed_unfixed_stateprobadd_selfcond_ce_fast_20260531_230026/step_135000.pt
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:73471d3765f03038acf5c0c134ecdeda95b7b67556b92c8dd8ed100dae8e890d
|
| 3 |
+
size 515519058
|
LTA_openwebtext_dualt/mini_owt_logdirichlet/runs/owt_t5_elftokenized_full_len1024_C1_to_1024_pow1_d768_l12_h12_gbs512_8gpu_50ep_lr3e4_elfopt_t5embed_unfixed_stateprobadd_selfcond_ce_fast_20260531_230026/step_173000.pt
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:28fbbcc3b528281bdca696e2e9fbd0018dc9b148a534da21d52258b4114136a1
|
| 3 |
+
size 515519058
|
LTA_openwebtext_dualt/mini_owt_logdirichlet/runs/owt_t5_elftokenized_full_len1024_C1_to_1024_pow1_d768_l12_h12_gbs512_8gpu_50ep_lr3e4_elfopt_t5embed_unfixed_stateprobadd_selfcond_ce_fast_20260531_230026/step_197000.pt
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:b2eb645b31651c7e54eb2ff7e06e3c5a8533f0fb976678fee816da1107eed6d4
|
| 3 |
+
size 515519058
|
LTA_openwebtext_dualt/mini_owt_logdirichlet/runs/owt_t5_elftokenized_full_len1024_C1_to_1024_pow1_d768_l12_h12_gbs512_8gpu_50ep_lr3e4_elfopt_t5embed_unfixed_stateprobadd_selfcond_ce_fast_20260531_230026/step_203000.pt
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:565b196d1cf6ea7889eec1b25ed3c60a58e486b3b9b8b92a680bcf758b0eb158
|
| 3 |
+
size 515519058
|
LTA_openwebtext_dualt/mini_owt_logdirichlet/runs/owt_t5_elftokenized_full_len1024_C1_to_1024_pow1_d768_l12_h12_gbs512_8gpu_50ep_lr3e4_elfopt_t5embed_unfixed_stateprobadd_selfcond_ce_fast_20260531_230026/step_236000.pt
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:1a1c6f2dd3e478d9b8eedfc6e83464fc3b96fa7c58f0b4e013f9487237d42904
|
| 3 |
+
size 515519058
|