Transformers
pipeline()
모델 inference를 위해 사용
from transformers import pipeline pipe = pipeline("text-classification") pipe("This restaurant is awesome") # [{'label': 'POSITIVE', 'score': 0.9998743534088135}]
from transformers로 Github(🐈⬛) transformer에서 함수를 불러올 수 있다:
불러오는 함수의 경우, __init__.py를 확인하면 알 수 있는데, 아래 사진처럼 pipeline이 from .pipelines import pipeline이라 적혀있음을 확인가능하다.
위 좌측사진에서 확인할 수 있듯, pipelines폴더에 pipeline함수를 불러오는것을 확인할 수 있으며,
실제로 해당 폴더에 들어가보면 우측처럼 pipeline함수가 정의되고, 이 형태는 transformers.pipeline docs내용과 일치함을 확인가능하다.
Auto Classes
from_pretrained() Method로 추론이 가능하며, AutoClasses는 이런 작업을 수행, 사전훈련된 AutoConfig, AutoModel, AutoTokenizer중 하나를 자동으로 생성가능하다:
ex)from transformers import AutoConfig, AutoModel model = AutoModel.from_pretrained("google-bert/bert-base-cased")
∙ AutoConfig
generic Cofiguration클래스로 from_pretrained()라는 클래스메서드 라이브러리 설정클래스 중 하나로 인스턴스화된다.
이 클래스는 '__init__()'을 사용해 직접 인스턴스할 수 없다!!위 사진을 보면, transformers/src파일을 따고 들어간 결과, 최종적으로 from_pretrained()함수를 찾을 수 있었다.
해당 깃헙코드(가장 우측사진)를 보면, __init__()함수에 대해 raise EnvironmentError가 걸려있음이 확인가능하다.config = AutoConfig.from_pretrained("bert-base-uncased") print(config) # BertConfig { # "_name_or_path": "bert-base-uncased", # "architectures": [ # "BertForMaskedLM" # ], # "attention_probs_dropout_prob": 0.1, # "classifier_dropout": null, # "gradient_checkpointing": false, # "hidden_act": "gelu", # "hidden_dropout_prob": 0.1, # "hidden_size": 768, # "initializer_range": 0.02, # "intermediate_size": 3072, # "layer_norm_eps": 1e-12, # "max_position_embeddings": 512, # "model_type": "bert", # "num_attention_heads": 12, # "num_hidden_layers": 12, # "pad_token_id": 0, # "position_embedding_type": "absolute", # "transformers_version": "4.41.2", # "type_vocab_size": 2, # "use_cache": true, # "vocab_size": 30522 # }
위 코드를 보면, Config는 모델 학습을 위한 json파일로 되어있음을 확인가능하다.
batch_size, learning_rate, weight_decay 등 train에 필요한 것들과
tokenizer의 특수토큰들을 미리 설정하는 등 설정관련 내용이 들어있다.
또한, save_pretrained()를 이용하면 모델의 checkpoint화 함께 저장된다!
그렇기에, 만약 설정을 변경하고 싶거나 Model Proposal등의 상황에서는 config파일을 직접 불러와야한다!
∙ AutoTokenizer, (blobs, refs, snapshots)
generic Tokenizer클래스로 AutoTokenizer.from_pretrained()라는 클래스메서드.
생성 시, 라이브러리 토크나이저클래스 중 하나로 인스턴스화된다.
참고)https://chan4im.tistory.com/#%E2%88%99input-ids
이 클래스는 '__init__()'을 사용해 직접 인스턴스할 수 없다!!위 사진을 보면, transformers/src파일을 따고 들어간 결과, 최종적으로 from_pretrained()함수를 찾을 수 있었다.
해당 깃헙코드(가장 우측사진)를 보면, __init__()함수에 대해 raise EnvironmentError가 걸려있음이 확인가능하다.from transformers import AutoTokenizer # Download vocabulary from huggingface.co and cache. tokenizer = AutoTokenizer.from_pretrained("google-bert/bert-base-uncased") # If vocabulary files are in a directory # (e.g. tokenizer was saved using *save_pretrained('./test/saved_model/')*) tokenizer = AutoTokenizer.from_pretrained("./test/bert_saved_model/") # Download vocabulary from huggingface.co and define model-specific arguments tokenizer = AutoTokenizer.from_pretrained("FacebookAI/roberta-base", add_prefix_space=True) tokenizer # BertTokenizerFast(name_or_path='google-bert/bert-base-uncased', vocab_size=30522, model_max_length=512, is_fast=True, padding_side='right', truncation_side='right', special_tokens={'unk_token': '[UNK]', 'sep_token': '[SEP]', 'pad_token': '[PAD]', 'cls_token': '[CLS]', 'mask_token': '[MASK]'}, clean_up_tokenization_spaces=True), added_tokens_decoder={ # 0: AddedToken("[PAD]", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True), # 100: AddedToken("[UNK]", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True), # 101: AddedToken("[CLS]", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True), # 102: AddedToken("[SEP]", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True), # 103: AddedToken("[MASK]", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True), # }
그런데 한가지 궁금하지 않은가?
tokenizer = AutoTokenizer.from_pretrained("google-bert/bert-base-uncased")
위 코드를 작성후 실행하면 콘솔창에 왜 아래와 같은 화면이 나오는 것일까?????
미리 설명:
tokenizer_config.json에는 token에 대한 설정들이,
config.json에는 모델관련 설정이,
vocab.txt는 subword들이 들어있고,
tokenizer.json은 config된 값들에 대해 나열한 것이다.
본인의 경우, 아래와 같이 cache_dir에 지정을 하면, 해당 디렉토리에 hub라는 파일이 생기며, 그안에 모델관련 파일이 생긴다.parser.add_argument('--cache_dir', default="/data/huggingface_models")
타고 들어가다 보면 총 3가지 폴더가 나온다: blobs, refs, snapshots
blobs: 해시값으로 나타나져 있음을 확인가능하다. 해당파일에는 아래와 같은 파일이 존재한다:
Config클래스관련파일, Model관련 클래스파일들, tokenizer설정관련 json파일, weight관련 파일들 등등 아래 사진과 같이 많은 파일들이 코드화되어 들어있다:
refs: 단순히 main이라는 파일만 존재한다:해당 파일에는 snapshots안에 있는 디렉토리의 이름과 동일한 이름이 적혀있다.
snapshots: 바로 이곳에!! tokenizer_config.json, config.json, vocab.txt, tokenizer.json파일이 있음을 확인할 수 있다!!!
그런데 뭔가 이상하지 않은가??
위의 blobs에 나와있는 사진의 코드와 snapshots의 코드가 모두 일치한다는 사실!!그렇다! 즉, blobs는 snapshots 내용을 해시값형태로 저장한 것이었다!!!
사실 이짓한다음에 구글에 치니까 바로 있긴했었다..(https://huggingface.co/docs/huggingface_hub/v0.16.3/en/guides/manage-cache)
허깅페이스 설명 요약:Refs refs 폴더는 주어진 참조의 최신 리비전을 나타내는 파일을 포함합니다. 예를 들어, 이전에 리포지토리의 메인 브랜치에서 파일을 가져온 경우, refs 폴더에는 main이라는 파일이 있으며, 현재 헤드의 커밋 식별자를 포함합니다.
만약 최신 커밋이 aaaaaa라는 식별자를 가지고 있다면, 해당 파일은 aaaaaa를 포함할 것입니다.
동일한 브랜치가 새로운 커밋 bbbbbb로 업데이트된 경우, 해당 참조에서 파일을 다시 다운로드하면 refs/main 파일이 bbbbbb로 업데이트됩니다.
Blobs blobs 폴더는 실제로 다운로드된 파일을 포함합니다. 각 파일의 이름은 해당 파일의 해시입니다.
Snapshots snapshots 폴더는 위의 blobs에서 언급한 파일에 대한 심볼릭 링크를 포함합니다. 자체적으로 알려진 각 리비전에 대해 여러 폴더로 구성됩니다.
cf) 또한 cache는 아래와 같은 tree구조를 가짐:[ 96] . └── [ 160] models--julien-c--EsperBERTo-small ├── [ 160] blobs │ ├── [321M] 403450e234d65943a7dcf7e05a771ce3c92faa84dd07db4ac20f592037a1e4bd │ ├── [ 398] 7cb18dc9bafbfcf74629a4b760af1b160957a83e │ └── [1.4K] d7edf6bd2a681fb0175f7735299831ee1b22b812 ├── [ 96] refs │ └── [ 40] main └── [ 128] snapshots ├── [ 128] 2439f60ef33a0d46d85da5001d52aeda5b00ce9f │ ├── [ 52] README.md -> ../../blobs/d7edf6bd2a681fb0175f7735299831ee1b22b812 │ └── [ 76] pytorch_model.bin -> ../../blobs/403450e234d65943a7dcf7e05a771ce3c92faa84dd07db4ac20f592037a1e4bd └── [ 128] bbc77c8132af1cc5cf678da3f1ddf2de43606d48 ├── [ 52] README.md -> ../../blobs/7cb18dc9bafbfcf74629a4b760af1b160957a83e └── [ 76] pytorch_model.bin -> ../../blobs/403450e234d65943a7dcf7e05a771ce3c92faa84dd07db4ac20f592037a1e4bd
∙ AutoModel
당연히 위와 같이, 아래사진처럼 찾아갈 수 있다.
먼저 AutoModel.from_config함수를 살펴보자.
from transformers import AutoConfig, AutoModel # Download configuration from huggingface.co and cache. config = AutoConfig.from_pretrained("google-bert/bert-base-cased") model = AutoModel.from_config(config) @classmethod def from_config(cls, config, **kwargs): trust_remote_code = kwargs.pop("trust_remote_code", None) has_remote_code = hasattr(config, "auto_map") and cls.__name__ in config.auto_map has_local_code = type(config) in cls._model_mapping.keys() trust_remote_code = resolve_trust_remote_code( trust_remote_code, config._name_or_path, has_local_code, has_remote_code ) if has_remote_code and trust_remote_code: class_ref = config.auto_map[cls.__name__] if "--" in class_ref: repo_id, class_ref = class_ref.split("--") else: repo_id = config.name_or_path model_class = get_class_from_dynamic_module(class_ref, repo_id, **kwargs) if os.path.isdir(config._name_or_path): model_class.register_for_auto_class(cls.__name__) else: cls.register(config.__class__, model_class, exist_ok=True) _ = kwargs.pop("code_revision", None) return model_class._from_config(config, **kwargs) elif type(config) in cls._model_mapping.keys(): model_class = _get_model_class(config, cls._model_mapping) return model_class._from_config(config, **kwargs) raise ValueError( f"Unrecognized configuration class {config.__class__} for this kind of AutoModel: {cls.__name__}.\n" f"Model type should be one of {', '.join(c.__name__ for c in cls._model_mapping.keys())}."
Data Collator
Data Collator
일련의 sample list를 "single training mini-batch"의 Tensor형태로 묶어줌.
Default Data Collator이는 아래처럼 train_dataset이 data_collator를 이용해 mini-batch로 묶여 모델로 들어가 학습하는데 도움이 된다.
trainer = Trainer( model=model, train_dataset=train_dataset, eval_dataset=eval_dataset, data_collator=data_collator,
batch["input_ids"] , batch["labels"] ?
다만, 위와 달리 대부분의 Data Collator함수를 보면 아래와 같은 코드의 형태를 띠는데, 여기서 input_ids와 label이라는 조금 생소한 단어가 있다:
class MyDataCollator: def __init__(self, processor): self.processor = processor def __call__(self, examples): texts = [] images = [] for example in examples: image, question, answer = example messages = [{"role": "user", "content": question}, {"role": "assistant", "content": answer}] # <-- 여기까지 잘 들어가는것 확인완료. text = self.processor.tokenizer.apply_chat_template(messages, add_generation_prompt=False) texts.append(text) images.append(image) batch = self.processor(text=text, images=image, return_tensors="pt", padding=True) labels = batch["input_ids"].clone() if self.processor.tokenizer.pad_token_id is not None: labels[labels == self.processor.tokenizer.pad_token_id] = -100 batch["labels"] = labels return batch data_collator = MyDataCollator(processor)
과연 batch["input_ids"]와 batch["labels"]가 뭘까?
전술했던 data_collator는 아래와 같은 형식을 띠는데, 여기서도 보면 inputs와 labels가 있는 것을 볼 수 있다.
모든 모델은 다르지만, 다른모델과 유사한점을 공유한다
= 대부분의 모델은 동일한 입력을 사용한다!
∙Input IDs
Input ID는 모델에 입력으로 전달되는 "유일한 필수 매개변수"인 경우가 많다.
Input ID는 token_index로, 사용할 sequence(문장)를 구성하는 token의 숫자표현이다.
각 tokenizer는 다르게 작동하지만 "기본 메커니즘은 동일"하다.
ex)from transformers import BertTokenizer tokenizer = BertTokenizer.from_pretrained("bert-base-cased") sequence = "A Titan RTX has 24GB of VRAM"
tokenizer는 sequence(문장)를 tokenizer vocab에 있는 Token으로 분할한다:tokenized_sequence = tokenizer.tokenize(sequence)
token은 word나 subword 둘중 하나이다:print(tokenized_sequence) # 출력: ['A', 'Titan', 'R', '##T', '##X', 'has', '24', '##GB', 'of', 'V', '##RA', '##M'] # 예를 들어, "VRAM"은 모델 어휘에 없어서 "V", "RA" 및 "M"으로 분할됨. # 이러한 토큰이 별도의 단어가 아니라 동일한 단어의 일부임을 나타내기 위해서는? # --> "RA"와 "M" 앞에 이중해시(##) 접두사가 추가됩 inputs = tokenizer(sequence)
이를 통해 token은 모델이 이해가능한 ID로 변환될 수 있다.
이때, 모델내부에서 작동하기 위해서는 input_ids를 key로, ID값을 value로 하는 "딕셔너리"형태로 반환해야한다:encoded_sequence = inputs["input_ids"] print(encoded_sequence) # 출력: [101, 138, 18696, 155, 1942, 3190, 1144, 1572, 13745, 1104, 159, 9664, 2107, 102]
또한, 모델에 따라서 자동으로 "special token"을 추가하는데,
여기에는 모델이 가끔 사용하는 "special IDs"가 추가된다.decoded_sequence = tokenizer.decode(encoded_sequence) print(decoded_sequence) # 출력: [CLS] A Titan RTX has 24GB of VRAM [SEP]
∙Attention Mask
Attention Mask는 Sequence를 batch로 묶을 때 사용하는 Optional한 인수로
"모델이 어떤 token을 주목하고 하지 말아야 하는지"를 나타낸다.
ex)
위를 보면, encoding된 길이가 다르기 때문에 "동일한 Tensor로 묶을 수가 없다."from transformers import BertTokenizer tokenizer = BertTokenizer.from_pretrained("bert-base-cased") sequence_a = "This is a short sequence." sequence_b = "This is a rather long sequence. It is at least longer than the sequence A." encoded_sequence_a = tokenizer(sequence_a)["input_ids"] encoded_sequence_b = tokenizer(sequence_b)["input_ids"] len(encoded_sequence_a), len(encoded_sequence_b) # 출력: (8, 19)
--> padding이나 truncation이 필요함.
attention_mask는 tokenizer가 반환하는 dictionary의 "attention_mask" key에 존재한다.padded_sequences = tokenizer([sequence_a, sequence_b], padding=True) padded_sequences["input_ids"] # 출력: [[101, 1188, 1110, 170, 1603, 4954, 119, 102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [101, 1188, 1110, 170, 1897, 1263, 4954, 119, 1135, 1110, 1120, 1655, 2039, 1190, 1103, 4954, 138, 119, 102]] padded_sequences["attention_mask"] # 출력: [[1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]]
∙Token Types IDs
어떤 모델의 목적은 classification이나 QA이다.
이런 모델은 2개의 "다른 목적을 단일 input_ids"항목으로 결합해야한다.
= [CLS], [SEP] 등의 특수토큰을 이용해 수행됨.
ex)
위의 예제에서 tokenizer를 이용해 2개의 sequence가 2개의 인수로 전달되어 자동으로 위와같은 문장을 생성하는 것을 볼 수 있다.# [CLS] SEQUENCE_A [SEP] SEQUENCE_B [SEP] from transformers import BertTokenizer tokenizer = BertTokenizer.from_pretrained("bert-base-cased") sequence_a = "HuggingFace is based in NYC" sequence_b = "Where is HuggingFace based?" encoded_dict = tokenizer(sequence_a, sequence_b) decoded = tokenizer.decode(encoded_dict["input_ids"]) print(decoded) # 출력: [CLS] HuggingFace is based in NYC [SEP] Where is HuggingFace based? [SEP]
이는 seq이후에 나오는 seq의 시작위치를 알기에는 좋다.
다만, 다른 모델은 token_types_ids도 사용하며, token_type_ids로 이 MASK를 반환한다.
encoded_dict['token_type_ids'] # 출력: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1]
질문에 사용되는 context는 모두 0으로,
질문에 해당되는 sequence는 모두 1로 설정된 것을 확인할 수 있다.
∙Position IDs
RNN: 각 토큰의 위치가 내장.
Transformer: 각 토큰의 위치를 인식 ❌
∴ position_ids는 모델이 각 토큰의 위치를 list에서 식별하는 데 사용되는 optional 매개변수.모델에 position_ids가 전달되지 않으면, ID는 자동으로 Absolute positional embeddings으로 생성:
Absolute positional embeddings은 [0, config.max_position_embeddings - 1] 범위에서 선택.
일부 모델은 sinusoidal position embeddings이나 relative position embeddings과 같은 다른 유형의 positional embedding을 사용.
∙Labels
Labels는 모델이 자체적으로 손실을 계산하도록 전달될 수 있는 Optional인수이다.
즉, Labels는 모델의 예상 예측값이어야 한다: 표준 손실을 사용하여 예측값과 예상값(레이블) 간의 손실을 계산.
이때, Labels는 Model Head에 따라 다르다:
- AutoModelForSequenceClassification: 모델은 (batch_size)차원텐서를 기대하며, batch의 각 값은 전체 시퀀스의 예상 label에 해당.
- AutoModelForTokenClassification: 모델은 (batch_size, seq_length)차원텐서를 기대하며, 각 값은 개별 토큰의 예상 label에 해당
- AutoModelForMaskedLM: 모델은 (batch_size, seq_length)차원텐서를 기대하며, 각 값은 개별 토큰의 예상 레이블에 해당: label은 마스킹된 token_ids이며, 나머지는 무시할 값(보통 -100).
- AutoModelForConditionalGeneration: 모델은 (batch_size, tgt_seq_length)차원텐서를 기대하며, 각 값은 각 입력 시퀀스와 연관된 목표 시퀀스를 나타냅니다. 훈련 중에는 BART와 T5가 적절한 디코더 입력 ID와 디코더 어텐션 마스크를 내부적으로 만들기에 보통 제공할 필요X. 이는 Encoder-Decoder 프레임워크를 사용하는 모델에는 적용되지 않음. 각 모델의 문서를 참조하여 각 특정 모델의 레이블에 대한 자세한 정보를 확인하세요.
기본 모델(BertModel 등)은 Labels를 받아들이지 못하는데, 이러한 모델은 기본 트랜스포머 모델로서 단순히 특징들만 출력한다.
∙ Decoder input IDs
이 입력은 인코더-디코더 모델에 특화되어 있으며, 디코더에 입력될 입력 ID를 포함합니다.
이러한 입력은 번역 또는 요약과 같은 시퀀스-투-시퀀스 작업에 사용되며, 보통 각 모델에 특정한 방식으로 구성됩니다.대부분의 인코더-디코더 모델(BART, T5)은 레이블에서 디코더 입력 ID를 자체적으로 생성합니다.
이러한 모델에서는 레이블을 전달하는 것이 훈련을 처리하는 선호 방법입니다.
시퀀스-투-시퀀스 훈련을 위한 이러한 입력 ID를 처리하는 방법을 확인하려면 각 모델의 문서를 참조하세요.
∙Feed Forward Chunking
트랜스포머의 각 잔차 어텐션 블록에서 셀프 어텐션 레이어는 보통 2개의 피드 포워드 레이어 다음에 위치합니다.
피드 포워드 레이어의 중간 임베딩 크기는 종종 모델의 숨겨진 크기보다 큽니다(예: bert-base-uncased).크기 [batch_size, sequence_length]의 입력에 대해 중간 피드 포워드 임베딩을 저장하는 데 필요한 메모리 [batch_size, sequence_length, config.intermediate_size]는 메모리 사용량의 큰 부분을 차지할 수 있습니다.
Reformer: The Efficient Transformer의 저자들은 계산이 sequence_length 차원과 독립적이므로 두 피드 포워드 레이어의 출력 임베딩 [batch_size, config.hidden_size]_0, ..., [batch_size, config.hidden_size]_n을 개별적으로 계산하고 n = sequence_length와 함께 [batch_size, sequence_length, config.hidden_size]로 결합하는 것이 수학적으로 동일하다는 것을 발견했습니다.
이는 메모리 사용량을 줄이는 대신 계산 시간을 증가시키는 거래를 하지만, 수학적으로 동일한 결과를 얻을 수 있습니다.apply_chunking_to_forward() 함수를 사용하는 모델의 경우, chunk_size는 병렬로 계산되는 출력 임베딩의 수를 정의하며, 메모리와 시간 복잡성 간의 거래를 정의합니다. chunk_size가 0으로 설정되면 피드 포워드 청킹은 수행되지 않습니다.
Optimization
AdamW
흔히들 아묻따 Adam만 사용해라! 라는 격언이 있을정도로 만능 optimizer같지만,
CV일부 Task에서는 SGD가 더 나은 성능을 보이는 경우가 상당히 존재한다.
AdamW논문에서는 L2 Regularization과 Weight Decay관점에서 SGD에 비해 Adam이 일반화 능력이 떨어지는 이유를 설명한다.
L2 Regularization: weight가 비정상적으로 커짐을 방지. (weight값이 커지면 손실함수도 커지게 됨.)
= weight가 너무 커지지 않는 선에서 기존 손실함수를 최소로 만들어주는 weight를 모델이 학습.
weight decay: weight update 시, 이전 weight크기를 일정비율 감소시켜 overfitting방지.
SGD: L2 = weight_decay
Adam: L2 ≠ weight_decay (adaptive learning rate를 사용하기 때문에 SGD와는 다른 weight update식을 사용함.)
∴ 즉, L2 Regularization이 포함된 손실함수로 Adam최적화 시, 일반화 효과를 덜 보게 된다. (decay rate가 더 작아지게됨.)
저자는 L2 regularzation에 의한 weight decay 효과 뿐만 아니라 weight 업데이트 식에 직접적으로 weight decay 텀을 추가하여 이 문제를 해결한다. L2 regularization과 분리된 weight decay라고 하여 decoupled weight decay라고 말하는 것이다.
SGDW와 AdamW의 알고리즘:
지금까지 설명하지 않았던 𝜂가 있는데, 이는 매 weight 업데이트마다 learning rate를 일정 비율 감소시켜주는 learning rate schedule 상수를 의미한다.
초록색으로 표시된 부분이 없다면 L2 regularization을 포함한 손실함수에 SGD와 Adam을 적용한 것과 똑같다.
하지만 초록색 부분을 직접적으로 weight 업데이트 식에 추가시켜 weight decay 효과를 볼 수 있게 만들었다.
optimizer = AdamW(model.parameters(),lr=1e-3, eps=(1e-30, 1e-3),weight_decay=0.0,)
cf) model.parameters()는 weight와 bias를 돌려줌.
이제 github 코드를 통해 위의 수식에 대해 살펴보도록 하자:
cf) optimizer의 state_dict()의 형태는 아래와 같다:class AdamW(Optimizer): """ Implements Adam algorithm with weight decay fix as introduced in [Decoupled Weight Decay Regularization](https://arxiv.org/abs/1711.05101). Parameters: params (`Iterable[nn.parameter.Parameter]`): Iterable of parameters to optimize or dictionaries defining parameter groups. lr (`float`, *optional*, defaults to 0.001): The learning rate to use. betas (`Tuple[float,float]`, *optional*, defaults to `(0.9, 0.999)`): Adam's betas parameters (b1, b2). eps (`float`, *optional*, defaults to 1e-06): Adam's epsilon for numerical stability. weight_decay (`float`, *optional*, defaults to 0.0): Decoupled weight decay to apply. correct_bias (`bool`, *optional*, defaults to `True`): Whether or not to correct bias in Adam (for instance, in Bert TF repository they use `False`). no_deprecation_warning (`bool`, *optional*, defaults to `False`): A flag used to disable the deprecation warning (set to `True` to disable the warning). """ def __init__( self, params: Iterable[nn.parameter.Parameter], lr: float = 1e-3, betas: Tuple[float, float] = (0.9, 0.999), eps: float = 1e-6, weight_decay: float = 0.0, correct_bias: bool = True, no_deprecation_warning: bool = False, ): if not no_deprecation_warning: warnings.warn( "This implementation of AdamW is deprecated and will be removed in a future version. Use the PyTorch" " implementation torch.optim.AdamW instead, or set `no_deprecation_warning=True` to disable this" " warning", FutureWarning, ) require_version("torch>=1.5.0") # add_ with alpha if lr < 0.0: raise ValueError(f"Invalid learning rate: {lr} - should be >= 0.0") if not 0.0 <= betas[0] < 1.0: raise ValueError(f"Invalid beta parameter: {betas[0]} - should be in [0.0, 1.0)") if not 0.0 <= betas[1] < 1.0: raise ValueError(f"Invalid beta parameter: {betas[1]} - should be in [0.0, 1.0)") if not 0.0 <= eps: raise ValueError(f"Invalid epsilon value: {eps} - should be >= 0.0") defaults = {"lr": lr, "betas": betas, "eps": eps, "weight_decay": weight_decay, "correct_bias": correct_bias} super().__init__(params, defaults) @torch.no_grad() def step(self, closure: Callable = None): """ Performs a single optimization step. Arguments: closure (`Callable`, *optional*): A closure that reevaluates the model and returns the loss. """ loss = None if closure is not None: loss = closure() for group in self.param_groups: for p in group["params"]: if p.grad is None: continue grad = p.grad if grad.is_sparse: raise RuntimeError("Adam does not support sparse gradients, please consider SparseAdam instead") state = self.state[p] # State initialization if len(state) == 0: state["step"] = 0 # Exponential moving average of gradient values state["exp_avg"] = torch.zeros_like(p) # Exponential moving average of squared gradient values state["exp_avg_sq"] = torch.zeros_like(p) exp_avg, exp_avg_sq = state["exp_avg"], state["exp_avg_sq"] beta1, beta2 = group["betas"] state["step"] += 1 # Decay the first and second moment running average coefficient # In-place operations to update the averages at the same time exp_avg.mul_(beta1).add_(grad, alpha=(1.0 - beta1)) exp_avg_sq.mul_(beta2).addcmul_(grad, grad, value=1.0 - beta2) denom = exp_avg_sq.sqrt().add_(group["eps"]) step_size = group["lr"] if group["correct_bias"]: # No bias correction for Bert bias_correction1 = 1.0 - beta1 ** state["step"] bias_correction2 = 1.0 - beta2 ** state["step"] step_size = step_size * math.sqrt(bias_correction2) / bias_correction1 p.addcdiv_(exp_avg, denom, value=-step_size) # Just adding the square of the weights to the loss function is *not* # the correct way of using L2 regularization/weight decay with Adam, # since that will interact with the m and v parameters in strange ways. # # Instead we want to decay the weights in a manner that doesn't interact # with the m/v parameters. This is equivalent to adding the square # of the weights to the loss with plain (non-momentum) SGD. # Add weight decay at the end (fixed version) if group["weight_decay"] > 0.0: p.add_(p, alpha=(-group["lr"] * group["weight_decay"])) return loss
이를 통해 살펴보면, Optimizer라는 클래스로부터 AdamW는 상속을 받은 이후,{ 'state': { 0: {'momentum_buffer': tensor(...), ...}, 1: {'momentum_buffer': tensor(...), ...}, 2: {'momentum_buffer': tensor(...), ...}, 3: {'momentum_buffer': tensor(...), ...} }, 'param_groups': [ { 'lr': 0.01, 'weight_decay': 0, ... 'params': [0] }, { 'lr': 0.001, 'weight_decay': 0.5, ... 'params': [1, 2, 3] } ] }
위의 state_dict형태를 보면 알 수 있듯, if len(state) == 0이라는 뜻은 state가 시작을 하나도 하지 않았음을 의미한다.
exp_avg는 m을, exp_avg_sq는 vt를 의미하며 p.addcdiv_와 if group["weight_decay"]쪽에서 최종 parameter에 대한 update가 됨을 확인할 수 있다.
LR-Schedules &. Learning rate Annealing
LR Schedule: 미리 정해진 스케줄대로 lr을 바꿔가며 사용.
훈련 도중 learning rate를 증가시켜주는게 차이점!
warmup restart로 그림처럼 local minimum에서 빠져나올 기회를 제공한다.
LR Annealing: lr schedule과 혼용되어 사용되나 iteration에 따라 monotonic하게 감소하는것을 의미.
직관적으로는 처음에는 높은 learning rate로 좋은 수렴 지점을 빡세게 찾고,
마지막에는 낮은 learning rate로 수렴 지점에 정밀하게 안착할 수 있게 만들어주는 역할을 한다.
Model Outputs
ModelOutput
모든 모델은 ModelOutput의 subclass의 instance출력을 갖는다.
outputs객체는 필히 loss와 logits를 갖기에 (outputs.loss, outputs.logits) 튜플을 반환한다.from transformers import BertTokenizer, BertForSequenceClassification import torch tokenizer = BertTokenizer.from_pretrained("google-bert/bert-base-uncased") model = BertForSequenceClassification.from_pretrained("google-bert/bert-base-uncased") inputs = tokenizer("Hello, my dog is cute", return_tensors="pt") labels = torch.tensor([1]).unsqueeze(0) # 배치 크기 1 outputs = model(**inputs, labels=labels) # SequenceClassifierOutput(loss=tensor(0.4267, grad_fn=<NllLossBackward0>), # logits=tensor([[-0.0658, 0.5650]], grad_fn=<AddmmBackward0>), # hidden_states=None, attentions=None)
Cf)
CuasalLM의 경우:
loss: Language modeling loss (for next-token prediction).
logits: Prediction scores of the LM_Head (scores for each vocabulary token before SoftMax)
= raw prediction values and are not bounded to a specific range
transformers output word를 위해선 : project linearly->apply softmax 단계를 거침.
이때, LM_Head는 pre-training이 아닌, Fine-Tuning에서 사용됨.
LM_Head란, 모델의 출력 hidden_state를 받아 prediction을 수행하는 것을 의미.
ex) BERT
from transformers import BertModel, BertTokenizer, BertForMaskedLM import torch tokenizer = BertTokenizer.from_pretrained("bert-base-uncased") model = BertForMaskedLM.from_pretrained("bert-base-uncased") inputs = tokenizer("The capital of France is [MASK].", return_tensors="pt") outputs = model(**inputs) logits = outputs.logits print(f'logits: {logits}') # `torch.FloatTensor` of shape `(batch_size, sequence_length, vocab_size) # [MASK] 토큰에 대한 예측 결과를 확인합니다. masked_index = (inputs.input_ids == tokenizer.mask_token_id).nonzero(as_tuple=True)[1] print(f'masked_index: {masked_index}') # `torch.LongTensor` of shape `(1,) MASK_token = logits[0, masked_index] # batch의 첫문장에서 MASK token을 가져옴. print(f'MASK_Token: {MASK_token}') predicted_token_id = MASK_token.argmax(axis=-1) # 주어진 차원에서 가장 큰 값의 index를 반환. = 모델이 해당위치에서 얘측한 단어의 token_id print(f'predicted_token_id: {predicted_token_id}') predicted_token = tokenizer.decode(predicted_token_id) print(predicted_token) # paris 출력 # logits: tensor([[[ -6.4346, -6.4063, -6.4097, ..., -5.7691, -5.6326, -3.7883], # [-14.0119, -14.7240, -14.2120, ..., -11.6976, -10.7304, -12.7618], # [ -9.6561, -10.3125, -9.7459, ..., -8.7782, -6.6036, -12.6596], # ..., # [ -3.7861, -3.8572, -3.5644, ..., -2.5593, -3.1093, -4.3820], # [-11.6598, -11.4274, -11.9267, ..., -9.8772, -10.2103, -4.7594], # [-11.7267, -11.7509, -11.8040, ..., -10.5943, -10.9407, -7.5151]]], # grad_fn=<ViewBackward0>) # masked_index: tensor([6]) # MASK_Token: tensor([[-3.7861, -3.8572, -3.5644, ..., -2.5593, -3.1093, -4.3820]], # grad_fn=<IndexBackward0>) # predicted_token_id: tensor([3000]) # paris
cf) 참고로 argmax가 반환한 index는 vocabulary의 Index임을 아래를 통해 확인할 수 있다.for word, idx in list(vocab.items())[:5]: # 어휘의 처음 10개 항목 출력 print(f"{word}: {idx}") for word, idx in list(vocab.items())[2990:3010]: # 어휘의 처음 10개 항목 출력 print(f"{word}: {idx}") # [PAD]: 0 # [unused0]: 1 # [unused1]: 2 # [unused2]: 3 # [unused3]: 4 # jack: 2990 # fall: 2991 # raised: 2992 # itself: 2993 # stay: 2994 # true: 2995 # studio: 2996 # 1988: 2997 # sports: 2998 # replaced: 2999 # paris: 3000 # systems: 3001 # saint: 3002 # leader: 3003 # theatre: 3004 # whose: 3005 # market: 3006 # capital: 3007 # parents: 3008 # spanish: 3009
Trainer
Trainer
Trainer클래스는 🤗 Transformers 모델에 최적화되어 있다
= 모델이 항상 tuple(= 첫요소로 loss반환) , ModelOutput의 subclass를 반환해야함을 의미
= labels인자가 제공되면 Loss를 계산할 수 있음.
Trainer는 TrainingArguments로 필요인자를 전달해주면, 사용자가 직접 train_loop작성할 필요없이 학습을 시작할 수 있다.
또한, TRL 라이브러리의 SFTTrainer의 경우, 이 Trainer클래스를 감싸고 있으며, LoRA, Quantizing과 DeepSpeed 등의 기능을 통해 어떤 모델 크기에도 효율적인 확장이 가능하다.
먼저, 시작에 앞서 분산환경을 위해서는 Accelerate라이브러리를 설치해야한다!
pip install accelerate pip install accelerate --upgrade
Basic Usage
"hugㅇㅇㄹㄴ
Checkpoints
"hugㅇㅇㄹㄴ
Customizing
"hugㅇㅇㄹㄴ
Callbacks & Logging
"hugㅇㅇㄹㄴ
Accelerate & Trainer
"hugㅇㅇㄹㄴ
TrainingArguments
참고)
output_dir (str): 모델 예측과 체크포인트가 작성될 출력 디렉토리입니다. eval_strategy (str 또는 [~trainer_utils.IntervalStrategy], optional, 기본값은 "no"): 훈련 중 채택할 평가 전략을 나타냅니다. 가능한 값은 다음과 같습니다: • "no": 훈련 중 평가를 하지 않습니다. • "steps": eval_steps마다 평가를 수행하고 기록합니다. • "epoch": 각 에포크가 끝날 때마다 평가를 수행합니다. per_device_train_batch_size (int, optional, 기본값은 8): 훈련 시 GPU/XPU/TPU/MPS/NPU 코어/CPU당 배치 크기입니다. per_device_eval_batch_size (int, optional, 기본값은 8): 평가 시 GPU/XPU/TPU/MPS/NPU 코어/CPU당 배치 크기입니다. gradient_accumulation_steps (int, optional, 기본값은 1): 역전파/업데이트를 수행하기 전에 그래디언트를 누적할 업데이트 단계 수입니다. eval_accumulation_steps (int, optional): 결과를 CPU로 이동시키기 전에 출력 텐서를 누적할 예측 단계 수입니다. 설정하지 않으면 전체 예측이 GPU/NPU/TPU에서 누적된 후 CPU로 이동됩니다(더 빠르지만 더 많은 메모리가 필요합니다). learning_rate (float, optional, 기본값은 5e-5): [AdamW] 옵티마이저의 초기 학습률입니다. weight_decay (float, optional, 기본값은 0): [AdamW] 옵티마이저에서 모든 레이어에(바이어스 및 LayerNorm 가중치는 제외) 적용할 가중치 감쇠입니다. max_grad_norm (float, optional, 기본값은 1.0): 최대 그래디언트 노름(그래디언트 클리핑을 위한)입니다. num_train_epochs(float, optional, 기본값은 3.0): 수행할 총 훈련 에포크 수입니다(정수가 아닌 경우 마지막 에포크의 백분율을 수행한 후 훈련을 중지합니다). max_steps (int, optional, 기본값은 -1): 양의 정수로 설정된 경우, 수행할 총 훈련 단계 수입니다. num_train_epochs를 무시합니다. 유한한 데이터 세트의 경우, max_steps에 도달할 때까지 데이터 세트를 반복합니다. eval_steps (int 또는 float, optional): eval_strategy="steps"인 경우 두 평가 사이의 업데이트 단계 수입니다. 설정되지 않은 경우, logging_steps와 동일한 값으로 기본 설정됩니다. 정수 또는 [0,1) 범위의 부동 소수점 수여야 합니다. 1보다 작으면 전체 훈련 단계의 비율로 해석됩니다. lr_scheduler_type (str 또는 [SchedulerType], optional, 기본값은 "linear"): 사용할 스케줄러 유형입니다. 모든 가능한 값은 [SchedulerType]의 문서를 참조하세요. lr_scheduler_kwargs ('dict', optional, 기본값은 {}): lr_scheduler에 대한 추가 인수입니다. 각 스케줄러의 문서를 참조하여 가능한 값을 확인하세요. warmup_ratio (float, optional, 기본값은 0.0): 0에서 learning_rate로의 선형 웜업에 사용되는 총 훈련 단계의 비율입니다. warmup_steps (int, optional, 기본값은 0): 0에서 learning_rate로의 선형 웜업에 사용되는 단계 수입니다. warmup_ratio의 영향을 무시합니다. logging_dir (str, optional): TensorBoard 로그 디렉토리입니다. 기본값은 output_dir/runs/CURRENT_DATETIME_HOSTNAME입니다. logging_strategy (str 또는 [~trainer_utils.IntervalStrategy], optional, 기본값은 "steps"): 훈련 중 채택할 로깅 전략을 나타냅니다. 가능한 값은 다음과 같습니다: • "no": 훈련 중 로깅을 하지 않습니다. • "epoch": 각 에포크가 끝날 때마다 로깅을 합니다. • "steps": logging_steps마다 로깅을 합니다. logging_first_step (bool, optional, 기본값은 False): 첫 번째 global_step을 로깅할지 여부를 나타냅니다. logging_steps (int 또는 float, optional, 기본값은 500): logging_strategy="steps"인 경우 두 로그 사이의 업데이트 단계 수입니다. 정수 또는 [0,1) 범위의 부동 소수점 수여야 합니다. 1보다 작으면 전체 훈련 단계의 비율로 해석됩니다. run_name (str, optional, 기본값은 output_dir): 실행에 대한 설명자입니다. 일반적으로 wandb 및 mlflow 로깅에 사용됩니다. 지정되지 않은 경우 output_dir과 동일합니다. save_strategy (str 또는 [~trainer_utils.IntervalStrategy], optional, 기본값은 "steps"): 훈련 중 체크포인트를 저장할 전략을 나타냅니다. 가능한 값은 다음과 같습니다: • "no": 훈련 중 저장하지 않습니다. • "epoch": 각 에포크가 끝날 때마다 저장합니다. • "steps": save_steps마다 저장합니다. "epoch" 또는 "steps"가 선택된 경우, 항상 훈련이 끝날 때 저장이 수행됩니다. save_total_limit (int, optional): 값이 전달되면 체크포인트의 총 수를 제한합니다. output_dir에 있는 오래된 체크포인트를 삭제합니다. load_best_model_at_end가 활성화되면 metric_for_best_model에 따라 "최고" 체크포인트는 항상 가장 최근의 체크포인트와 함께 유지됩니다. 예를 들어, save_total_limit=5 및 load_best_model_at_end인 경우, 마지막 네 개의 체크포인트는 항상 최고 모델과 함께 유지됩니다. save_total_limit=1 및 load_best_model_at_end인 경우, 마지막 체크포인트와 최고 체크포인트가 서로 다르면 두 개의 체크포인트가 저장될 수 있습니다. save_safetensors (bool, optional, 기본값은 True): state_dict를 저장하고 로드할 때 기본 torch.load 및 torch.save 대신 safetensors를 사용합니다. save_on_each_node (bool, optional, 기본값은 False): 멀티노드 분산 훈련을 수행할 때, 모델과 체크포인트를 각 노드에 저장할지 여부를 나타냅니다. 기본적으로 메인 노드에만 저장됩니다. seed (int, optional, 기본값은 42): 훈련 시작 시 설정될 랜덤 시드입니다. 실행 간 일관성을 보장하려면 모델에 무작위로 초기화된 매개변수가 있는 경우 [~Trainer.model_init] 함수를 사용하여 모델을 인스턴스화하세요. data_seed (int, optional): 데이터 샘플러에 사용할 랜덤 시드입니다. 설정되지 않은 경우 데이터 샘플링을 위한 Random sampler는 seed와 동일한 시드를 사용합니다. 이 값을 사용하면 모델 시드와는 독립적으로 데이터 샘플링의 일관성을 보장할 수 있습니다. bf16 (bool, optional, 기본값은 False): 32비트 훈련 대신 bf16 16비트(혼합) 정밀도 훈련을 사용할지 여부를 나타냅니다. Ampere 이상 NVIDIA 아키텍처 또는 CPU(사용_cpu) 또는 Ascend NPU를 사용해야 합니다. 이는 실험적 API이며 변경될 수 있습니다. fp16 (bool, optional, 기본값은 False): 32비트 훈련 대신 fp16 16비트(혼합) 정밀도 훈련을 사용할지 여부를 나타냅니다. half_precision_backend (str, optional, 기본값은 "auto"): 혼합 정밀도 훈련을 위한 백엔드입니다. "auto", "apex", "cpu_amp" 중 하나여야 합니다. "auto"는 감지된 PyTorch 버전에 따라 CPU/CUDA AMP 또는 APEX를 사용하며, 다른 선택지는 요청된 백엔드를 강제로 사용합니다. bf16_full_eval (bool, optional, 기본값은 False): 32비트 대신 전체 bfloat16 평가를 사용할지 여부를 나타냅니다. 이는 더 빠르고 메모리를 절약하지만 메트릭 값에 악영향을 줄 수 있습니다. 이는 실험적 API이며 변경될 수 있습니다. fp16_full_eval (bool, optional, 기본값은 False): 32비트 대신 전체 float16 평가를 사용할지 여부를 나타냅니다. 이는 더 빠르고 메모리를 절약하지만 메트릭 값에 악영향을 줄 수 있습니다. tf32 (bool, optional): Ampere 및 최신 GPU 아키텍처에서 사용할 TF32 모드를 활성화할지 여부를 나타냅니다. 기본값은 torch.backends.cuda.matmul.allow_tf32의 기본값에 따릅니다. 자세한 내용은 TF32 문서를 참조하세요. 이는 실험적 API이며 변경될 수 있습니다. local_rank (int, optional, 기본값은 -1): 분산 훈련 중 프로세스의 순위를 나타냅니다. ddp_backend (str, optional): 분산 훈련에 사용할 백엔드를 나타냅니다. "nccl", "mpi", "ccl", "gloo", "hccl" 중 하나여야 합니다. dataloader_drop_last (bool, optional, 기본값은 False): 데이터 세트의 길이가 배치 크기로 나누어떨어지지 않는 경우 마지막 불완전한 배치를 삭제할지 여부를 나타냅니다. dataloader_num_workers (int, optional, 기본값은 0): 데이터 로딩에 사용할 하위 프로세스 수입니다(PyTorch 전용). 0은 데이터가 메인 프로세스에서 로드됨을 의미합니다. remove_unused_columns (bool, optional, 기본값은 True): 모델의 forward 메서드에서 사용되지 않는 열을 자동으로 제거할지 여부를 나타냅니다. label_names (List[str], optional): input dictionary에서 label에 해당하는 키의 목록입니다. 기본값은 모델이 사용하는 레이블 인수의 목록입니다. load_best_model_at_end (bool, optional, 기본값은 False): 훈련이 끝날 때 최상의 모델을 로드할지 여부를 나타냅니다. 이 옵션이 활성화되면, 최상의 체크포인트가 항상 저장됩니다. 자세한 내용은 save_total_limit를 참조하세요. <Tip> When set to `True`, the parameters `save_strategy` needs to be the same as `eval_strategy`, and in the case it is "steps", `save_steps` must be a round multiple of `eval_steps`. </Tip> metric_for_best_model (str, optional): load_best_model_at_end와 함께 사용하여 두 모델을 비교할 메트릭을 지정합니다. 평가에서 반환된 메트릭 이름이어야 합니다. 지정되지 않은 경우 기본값은 "loss"이며, load_best_model_at_end=True인 경우 eval_loss를 사용합니다. 이 값을 설정하면 greater_is_better의 기본값은 True가 됩니다. 메트릭이 낮을수록 좋다면 False로 설정하세요. greater_is_better (bool, optional): load_best_model_at_end 및 metric_for_best_model과 함께 사용하여 더 나은 모델이 더 높은 메트릭을 가져야 하는지 여부를 지정합니다. 기본값은 다음과 같습니다: • metric_for_best_model이 "loss"로 끝나지 않는 값으로 설정된 경우 True입니다. • metric_for_best_model이 설정되지 않았거나 "loss"로 끝나는 값으로 설정된 경우 False입니다. fsdp (bool, str 또는 [~trainer_utils.FSDPOption]의 목록, optional, 기본값은 ''): PyTorch 분산 병렬 훈련을 사용합니다(분산 훈련 전용). fsdp_config (str 또는 dict, optional): fsdp(Pytorch 분산 병렬 훈련)와 함께 사용할 설정입니다. 값은 fsdp json 구성 파일의 위치(e.g., fsdp_config.json) 또는 이미 로드된 json 파일(dict)일 수 있습니다. deepspeed (str 또는 dict, optional): Deepspeed를 사용합니다. 이는 실험적 기능이며 API가 변경될 수 있습니다. 값은 DeepSpeed json 구성 파일의 위치(e.g., ds_config.json) 또는 이미 로드된 json 파일(dict)일 수 있습니다. accelerator_config (str, dict, 또는 AcceleratorConfig, optional): 내부 Accelerator 구현과 함께 사용할 설정입니다. 값은 accelerator json 구성 파일의 위치(e.g., accelerator_config.json), 이미 로드된 json 파일(dict), 또는 [~trainer_pt_utils.AcceleratorConfig]의 인스턴스일 수 있습니다. label_smoothing_factor (float, optional, 기본값은 0.0): 사용할 레이블 스무딩 팩터입니다. 0은 label_smoothing을 사용하지 않음을 의미, 다른 값은 원핫 인코딩된 레이블을 변경합니다. optim (str 또는 [training_args.OptimizerNames], optional, 기본값은 "adamw_torch"): 사용할 옵티마이저를 나타냅니다. adamw_hf, adamw_torch, adamw_torch_fused, adamw_apex_fused, adamw_anyprecision, adafactor 중에서 선택할 수 있습니다. optim_args (str, optional): AnyPrecisionAdamW에 제공되는 선택적 인수입니다. group_by_length (bool, optional, 기본값은 False): 훈련 데이터 세트에서 대략 같은 길이의 샘플을 그룹화할지 여부를 나타냅니다(패딩을 최소화하고 효율성을 높이기 위해). 동적 패딩을 적용할 때만 유용합니다. report_to (str 또는 List[str], optional, 기본값은 "all"): 결과와 로그를 보고할 통합 목록입니다. 지원되는 플랫폼은 "azure_ml", "clearml", "codecarbon", "comet_ml", "dagshub", "dvclive", "flyte", "mlflow", "neptune", "tensorboard", "wandb"입니다. "all"은 설치된 모든 통합에 보고하며, "none"은 통합에 보고하지 않습니다. ddp_find_unused_parameters (bool, optional): 분산 훈련을 사용할 때, DistributedDataParallel에 전달되는 find_unused_parameters 플래그의 값을 나타냅니다. 기본값은 그래디언트 체크포인팅을 사용하는 경우 False, 그렇지 않은 경우 True입니다. ddp_bucket_cap_mb (int, optional): 분산 훈련을 사용할 때, DistributedDataParallel에 전달되는 bucket_cap_mb 플래그의 값을 나타냅니다. ddp_broadcast_buffers (bool, optional): 분산 훈련을 사용할 때, DistributedDataParallel에 전달되는 broadcast_buffers 플래그의 값을 나타냅니다. 기본값은 그래디언트 체크포인팅을 사용하는 경우 False, 그렇지 않은 경우 True입니다. dataloader_persistent_workers (bool, optional, 기본값은 False): True로 설정하면 데이터 로더는 데이터 세트가 한 번 소비된 후에도 작업자 프로세스를 종료하지 않습니다. 이는 작업자 데이터 세트 인스턴스를 유지할 수 있습니다. 훈련 속도를 높일 수 있지만 RAM 사용량이 증가합니다. 기본값은 False입니다. push_to_hub (bool, optional, 기본값은 False): 모델이 저장될 때마다 모델을 허브로 푸시할지 여부를 나타냅니다. 이 옵션이 활성화되면 output_dir은 git 디렉토리가 되어 저장이 트리거될 때마다 콘텐츠가 푸시됩니다(save_strategy에 따라 다름). [~Trainer.save_model]을 호출하면 푸시가 트리거됩니다. resume_from_checkpoint (str, optional): 모델에 유효한 체크포인트가 있는 폴더의 경로입니다. 이 인수는 직접적으로 [Trainer]에서 사용되지 않으며, 대신 훈련/평가 스크립트에서 사용됩니다. 자세한 내용은 예제 스크립트를 참조하세요. hub_model_id (str, optional): 로컬 output_dir과 동기화할 저장소의 이름입니다. 단순한 모델 ID일 수 있으며, 이 경우 모델은 네임스페이스에 푸시됩니다. 그렇지 않으면 전체 저장소 이름이어야 합니다(e.g., "user_name/model"). 기본값은 user_name/output_dir_name입니다. 기본값은 output_dir의 이름입니다. hub_strategy (str 또는 [~trainer_utils.HubStrategy], optional, 기본값은 "every_save"): 허브로 푸시할 범위와 시점을 정의합니다. 가능한 값은 다음과 같습니다: • "end": 모델, 구성, 토크나이저(전달된 경우), 모델 카드 초안을 푸시합니다. • "every_save": 모델, 구성, 토크나이저(전달된 경우), 모델 카드 초안을 저장할 때마다 푸시합니다. 푸시는 비동기적으로 수행되며, 저장이 매우 빈번한 경우 이전 푸시가 완료되면 새로운 푸시가 시도됩니다. 훈련이 끝날 때 최종 모델로 마지막 푸시가 수행됩니다. • "checkpoint": "every_save"와 유사하지만 최신 체크포인트도 last-checkpoint라는 하위 폴더에 푸시하여 trainer.train(resume_from_checkpoint="last-checkpoint")으로 훈련을 쉽게 재개할 수 있습니다. • "all_checkpoints": "checkpoint"와 유사하지만 최종 저장소에서 나타나는 대로 모든 체크포인트를 푸시합니다(따라서 최종 저장소에는 폴더마다 하나의 체크포인트 폴더가 있습니다). hub_token (str, optional): 모델을 허브로 푸시할 때 사용할 토큰입니다. 기본값은 huggingface-cli login으로 얻은 캐시 폴더의 토큰입니다. hub_private_repo (bool, optional, 기본값은 False): True로 설정하면 허브 저장소가 비공개로 설정됩니다. hub_always_push (bool, optional, 기본값은 False): True가 아닌 경우, 이전 푸시가 완료되지 않으면 체크포인트 푸시를 건너뜁니다. gradient_checkpointing (bool, optional, 기본값은 False): 메모리를 절약하기 위해 그래디언트 체크포인팅을 사용할지 여부를 나타냅니다. 역전파 속도가 느려집니다. auto_find_batch_size (bool, optional, 기본값은 False): 메모리에 맞는 배치 크기를 자동으로 찾아 CUDA 메모리 부족 오류를 피할지 여부를 나타냅니다. accelerate가 설치되어 있어야 합니다(pip install accelerate). ray_scope (str, optional, 기본값은 "last"): Ray를 사용한 하이퍼파라미터 검색 시 사용할 범위입니다. 기본값은 "last"입니다. Ray는 모든 시도의 마지막 체크포인트를 사용하여 비교하고 최상의 체크포인트를 선택합니다. 다른 옵션도 있습니다. 자세한 내용은 Ray 문서를 참조하세요. ddp_timeout (int, optional, 기본값은 1800): torch.distributed.init_process_group 호출의 타임아웃입니다. 분산 실행 시 GPU 소켓 타임아웃을 피하기 위해 사용됩니다. 자세한 내용은 PyTorch 문서를 참조하세요. torch_compile (bool, optional, 기본값은 False): PyTorch 2.0 torch.compile을 사용하여 모델을 컴파일할지 여부를 나타냅니다. 이는 torch.compile API에 대한 기본값을 사용합니다. torch_compile_backend 및 torch_compile_mode 인수를 사용하여 기본값을 사용자 지정할 수 있지만, 모든 값이 작동할 것이라고 보장하지 않습니다. 이 플래그와 전체 컴파일 API는 실험적이며 향후 릴리스에서 변경될 수 있습니다. torch_compile_backend (str, optional): torch.compile에서 사용할 백엔드입니다. 값을 설정하면 torch_compile이 True로 설정됩니다. 가능한 값은 PyTorch 문서를 참조하세요. 이는 실험적이며 향후 릴리스에서 변경될 수 있습니다. torch_compile_mode (str, optional): torch.compile에서 사용할 모드입니다. 값을 설정하면 torch_compile이 True로 설정됩니다. 가능한 값은 PyTorch 문서를 참조하세요. 이는 실험적이며 향후 릴리스에서 변경될 수 있습니다. split_batches (bool, optional): 분산 훈련 중 데이터 로더가 생성하는 배치를 장치에 분할할지 여부를 나타냅니다. True로 설정하면 사용된 실제 배치 크기는 모든 종류의 분산 프로세스에서 동일하지만, 사용 중인 프로세스 수의 정수 배여야 합니다.
DeepSpeed
trust_remote_code=True
중국모델에서 흔히보이는 trust_remote_code=True 설정, 과연 이건 뭘까?
이는 "huggingface/transformers"에 Model Architecture가 아직 추가되지 않은경우:
"huggingface repo 'internlm/internlm-chat-7b'에서 모델 코드를 다운로드하고, 가중치와 함께 실행한다"는 의미이다.from transformers import AutoTokenizer, AutoModel model = AutoModel.from_pretrained("internlm/internlm-chat-7b", trust_remote_code=True, device='cuda')
만약 이 값이 False라면, 라이브러리는 huggingface/transformers에 내장된 모델 아키텍처를 사용하고 가중치만 다운로드하는것을 의미한다.
rue
중국모델에서 흔히ollator함수를 보면 아래와 같은 코드의 형태를 띠는데, 여기서 input_ids와 label이라는 조금 생소한 단
'HuggingFace🤗' 카테고리의 다른 글
[Data Preprocessing] - Data Collator (1) | 2024.07.14 |
---|---|
QLoRA 실습 & Trainer vs SFTTrainer (0) | 2024.07.12 |
[QLoRA] & [PEFT] & deepspeed, DDP (0) | 2024.07.09 |