허깅페이스의 transformers 코드를 보다가 추상메서드에 대해 정리해보려고 한다.
📌 추상 메서드란?
구체적인 구현없이 선언만 된 메서드.
추상 메서드는 상위 클래스에서 정의되지만, 하위 클래스에서 반드시 구현되어야 한다.
📌 사용 목적
특정 클래스가 가져야 할 공통 인터페이스를 정의하기 위해 사용된다.
📌 특징
본체(구현)가 없으며, 보통 pass 또는 raise NotImplementedError로 처리된다.
📌 구현 예시
transformers/src/tranformers/tokenization_utils_base.py
_encode_plus는 tokenization_utils_base에 정의된 추상 메서드이다.
_encode_plus는 PreTrainedTokenizerBase 클래스에서 선언만 되어 있고, 실제 구현은 상속받은 클래스(transformers/src/tranformers/tokenization_utils.py의 PreTrainedTokenizer )에서 이루어진다.
@add_end_docstrings(INIT_TOKENIZER_DOCSTRING)
class PreTrainedTokenizerBase(SpecialTokensMixin, PushToHubMixin):
...
def _encode_plus(
self,
text: Union[TextInput, PreTokenizedInput, EncodedInput],
text_pair: Optional[Union[TextInput, PreTokenizedInput, EncodedInput]] = None,
add_special_tokens: bool = True,
padding_strategy: PaddingStrategy = PaddingStrategy.DO_NOT_PAD,
truncation_strategy: TruncationStrategy = TruncationStrategy.DO_NOT_TRUNCATE,
max_length: Optional[int] = None,
stride: int = 0,
is_split_into_words: bool = False,
pad_to_multiple_of: Optional[int] = None,
padding_side: Optional[bool] = None,
return_tensors: Optional[Union[str, TensorType]] = None,
return_token_type_ids: Optional[bool] = None,
return_attention_mask: Optional[bool] = None,
return_overflowing_tokens: bool = False,
return_special_tokens_mask: bool = False,
return_offsets_mapping: bool = False,
return_length: bool = False,
verbose: bool = True,
split_special_tokens: bool = False,
**kwargs,
) -> BatchEncoding:
raise NotImplementedError
...
transformers/src/tranformers/tokenization_utils.py
from .tokenization_utils_base import (
...
PreTrainedTokenizerBase,
...
)
@add_end_docstrings(INIT_TOKENIZER_DOCSTRING)
class PreTrainedTokenizer(PreTrainedTokenizerBase):
...
def _encode_plus(
self,
text: Union[TextInput, PreTokenizedInput, EncodedInput],
text_pair: Optional[Union[TextInput, PreTokenizedInput, EncodedInput]] = None,
add_special_tokens: bool = True,
padding_strategy: PaddingStrategy = PaddingStrategy.DO_NOT_PAD,
truncation_strategy: TruncationStrategy = TruncationStrategy.DO_NOT_TRUNCATE,
max_length: Optional[int] = None,
stride: int = 0,
is_split_into_words: bool = False,
pad_to_multiple_of: Optional[int] = None,
padding_side: Optional[bool] = None,
return_tensors: Optional[Union[str, TensorType]] = None,
return_token_type_ids: Optional[bool] = None,
return_attention_mask: Optional[bool] = None,
return_overflowing_tokens: bool = False,
return_special_tokens_mask: bool = False,
return_offsets_mapping: bool = False,
return_length: bool = False,
verbose: bool = True,
**kwargs,
) -> BatchEncoding:
def get_input_ids(text):
if isinstance(text, str):
tokens = self.tokenize(text, **kwargs)
return self.convert_tokens_to_ids(tokens)
elif isinstance(text, (list, tuple)) and len(text) > 0 and isinstance(text[0], str):
if is_split_into_words:
tokens = list(
itertools.chain(*(self.tokenize(t, is_split_into_words=True, **kwargs) for t in text))
)
return self.convert_tokens_to_ids(tokens)
else:
return self.convert_tokens_to_ids(text)
elif isinstance(text, (list, tuple)) and len(text) > 0 and isinstance(text[0], int):
return text
else:
if is_split_into_words:
raise ValueError(
f"Input {text} is not valid. Should be a string or a list/tuple of strings when"
" `is_split_into_words=True`."
)
else:
raise ValueError(
f"Input {text} is not valid. Should be a string, a list/tuple of strings or a list/tuple of"
" integers."
)
if return_offsets_mapping:
raise NotImplementedError(
"return_offset_mapping is not available when using Python tokenizers. "
"To use this feature, change your tokenizer to one deriving from "
"transformers.PreTrainedTokenizerFast. "
"More information on available tokenizers at "
"https://github.com/huggingface/transformers/pull/2674"
)
first_ids = get_input_ids(text)
second_ids = get_input_ids(text_pair) if text_pair is not None else None
return self.prepare_for_model(
first_ids,
pair_ids=second_ids,
add_special_tokens=add_special_tokens,
padding=padding_strategy.value,
truncation=truncation_strategy.value,
max_length=max_length,
stride=stride,
pad_to_multiple_of=pad_to_multiple_of,
padding_side=padding_side,
return_tensors=return_tensors,
prepend_batch_axis=True,
return_attention_mask=return_attention_mask,
return_token_type_ids=return_token_type_ids,
return_overflowing_tokens=return_overflowing_tokens,
return_special_tokens_mask=return_special_tokens_mask,
return_length=return_length,
verbose=verbose,
)
...
_encode_plus는 텍스트를 토큰화하고 정수 ID로 변환 하며, 특수 토큰과 데이터를 추가하는 메서드로, PreTrainedTokenizerBase에서 추상 메서드로 정의된다.
이후 이 메서드는 PreTrainedTokenizer에서 구체적으로 구현되며, BERT나 GPT와 같은 모델별 토크나이저에서 필요에 따라 모델 특징에 맞게 확장된다.
추상 메서드는 공통 인터페이스를 제공하면서도 각 모델의 특화된 동작을 가능하게 한다.
📌 정리
PreTrainedTokenizerBase는 여러 모델에서 공통적으로 사용할 수 있는 인터페이스를 제공한다.
_encode_plus는 텍스트를 입력 받아 토큰화, 정수 변환, 특수 토큰 추가, 결과 반환 과정을 정의해야 하지만, 이 과정은 모델 별로 다를 수 있다.
추상 메서드를 사용하면서 각 모델에 특화된 방식으로 _encode_plus를 구현할 수 있다.
우리는 일관된 인터페이스 tokenizer(prompt)를 사용하면서도 모델별 최적화된 동작을 활용할 수 있다.
📌 출처 코드
transformers/src/transformers/tokenization_utils_base.py at main · huggingface/transformers
🤗 Transformers: State-of-the-art Machine Learning for Pytorch, TensorFlow, and JAX. - huggingface/transformers
github.com
https://github.com/huggingface/transformers/blob/main/src/transformers/tokenization_utils.py
transformers/src/transformers/tokenization_utils.py at main · huggingface/transformers
🤗 Transformers: State-of-the-art Machine Learning for Pytorch, TensorFlow, and JAX. - huggingface/transformers
github.com
'Python' 카테고리의 다른 글
| [Python] type hinting (2) | 2024.12.09 |
|---|