반응형
블로그 이미지
개발자로서 현장에서 일하면서 새로 접하는 기술들이나 알게된 정보 등을 정리하기 위한 블로그입니다. 운 좋게 미국에서 큰 회사들의 프로젝트에서 컬설턴트로 일하고 있어서 새로운 기술들을 접할 기회가 많이 있습니다. 미국의 IT 프로젝트에서 사용되는 툴들에 대해 많은 분들과 정보를 공유하고 싶습니다.
솔웅

최근에 올라온 글

최근에 달린 댓글

최근에 받은 트랙백

글 보관함

카테고리


반응형

https://huggingface.co/learn/nlp-course/chapter3/4?fw=pt

 

A full training - Hugging Face NLP Course

Now we’ll see how to achieve the same results as we did in the last section without using the Trainer class. Again, we assume you have done the data processing in section 2. Here is a short summary covering everything you will need: Before actually writi

huggingface.co

 

https://youtu.be/Dh9CL8fyG80?si=3CJkNCLDiNe4l80r

 

 

 

 

A full training

 

Now we’ll see how to achieve the same results as we did in the last section without using the Trainer class. Again, we assume you have done the data processing in section 2. Here is a short summary covering everything you will need:

 

이제 Trainer 클래스를 사용하지 않고 마지막 섹션에서와 동일한 결과를 얻는 방법을 살펴보겠습니다. 다시 한 번 섹션 2에서 데이터 처리를 완료했다고 가정합니다. 다음은 필요한 모든 내용을 다루는 간단한 요약입니다.

 

from datasets import load_dataset
from transformers import AutoTokenizer, DataCollatorWithPadding

# "glue" 데이터셋의 "mrpc" 태스크를 로드
raw_datasets = load_dataset("glue", "mrpc")

# BERT의 사전 훈련된 토크나이저를 불러오기
checkpoint = "bert-base-uncased"
tokenizer = AutoTokenizer.from_pretrained(checkpoint)

# 사용자 정의 토큰화 함수 정의
def tokenize_function(example):
    return tokenizer(example["sentence1"], example["sentence2"], truncation=True)

# 토큰화된 데이터셋 생성 (batched=True로 설정하여 배치 단위로 토큰화)
tokenized_datasets = raw_datasets.map(tokenize_function, batched=True)

# 데이터 콜레이터 생성 (패딩 추가)
data_collator = DataCollatorWithPadding(tokenizer=tokenizer)

 

이 코드는 Hugging Face Transformers 라이브러리를 사용하여 데이터셋을 로드하고 토큰화하는 과정을 나타냅니다. 코드를 단계별로 설명하겠습니다.

 

해석:

  1. load_dataset("glue", "mrpc"): Hugging Face의 datasets 라이브러리를 사용하여 GLUE 벤치마크의 MRPC(Microsoft Research Paraphrase Corpus) 태스크를 로드합니다.
  2. AutoTokenizer.from_pretrained(checkpoint): BERT 모델의 사전 훈련된 토크나이저를 불러옵니다. 여기서는 "bert-base-uncased"를 사용합니다.
  3. tokenize_function(example): 사용자 정의 토큰화 함수를 정의합니다. 이 함수는 입력으로 문장1(sentence1)과 문장2(sentence2)를 받아 토큰화한 결과를 반환합니다. truncation=True는 문장이 일정 길이를 초과할 경우 자르도록 설정한 것입니다.
  4. raw_datasets.map(tokenize_function, batched=True): 토큰화 함수를 사용하여 데이터셋을 토큰화합니다. batched=True로 설정하여 배치 단위로 토큰화합니다.
  5. DataCollatorWithPadding(tokenizer=tokenizer): 데이터 콜레이터를 생성합니다. 이 객체는 배치를 처리하여 패딩을 추가하고 동일한 길이로 만들어주는 역할을 합니다. 여기서는 BERT의 토크나이저를 사용하여 패딩을 추가하도록 설정했습니다.

이렇게 토큰화된 데이터셋과 데이터 콜레이터는 모델을 훈련하거나 평가할 때 사용됩니다. 데이터셋은 토큰화된 형태로 모델에 입력되고, 데이터 콜레이터는 배치를 처리하여 패딩을 추가하여 모델이 일관된 형태로 데이터를 처리할 수 있도록 도와줍니다.

 

 

Prepare for training

 

Before actually writing our training loop, we will need to define a few objects. The first ones are the dataloaders we will use to iterate over batches. But before we can define those dataloaders, we need to apply a bit of postprocessing to our tokenized_datasets, to take care of some things that the Trainer did for us automatically. Specifically, we need to:

 

실제로 훈련 루프를 작성하기 전에 몇 가지 객체를 정의해야 합니다. 첫 번째는 배치를 반복하는 데 사용할 데이터로더입니다. 하지만 이러한 데이터로더를 정의하기 전에 Trainer가 자동으로 수행한 일부 작업을 처리하기 위해 tokenized_datasets에 약간의 후처리를 적용해야 합니다. 구체적으로 다음을 수행해야 합니다.

 

  • Remove the columns corresponding to values the model does not expect (like the sentence1 and sentence2 columns).

  • 모델이 예상하지 않는 값(예: 문장1 및 문장2 열)에 해당하는 열을 제거합니다.

  • Rename the column label to labels (because the model expects the argument to be named labels).

  • 열 레이블의 이름을 labels  로 바꿉니다(모델에서는 인수 이름이 labels  로 지정될 것으로 예상하기 때문입니다).

  • Set the format of the datasets so they return PyTorch tensors instead of lists.

  • 목록 대신 PyTorch 텐서를 반환하도록 데이터 세트의 형식을 설정합니다.

Our tokenized_datasets has one method for each of those steps:

 

tokenized_datasets에는 각 단계에 대해 하나의 방법이 있습니다.

 

tokenized_datasets = tokenized_datasets.remove_columns(["sentence1", "sentence2", "idx"])
tokenized_datasets = tokenized_datasets.rename_column("label", "labels")
tokenized_datasets.set_format("torch")
tokenized_datasets["train"].column_names

 

이 코드는 Hugging Face의 datasets 라이브러리에서 사용되는 데이터셋 객체의 몇 가지 조작을 수행하는 부분입니다. 코드를 단계별로 설명하겠습니다.

 

해석:

  1. tokenized_datasets.remove_columns(["sentence1", "sentence2", "idx"]): "sentence1", "sentence2", 그리고 "idx" 열을 삭제합니다. 이 열들은 토큰화 이전에 원시 데이터셋에서 가져온 열일 것으로 예상됩니다.
  2. tokenized_datasets.rename_column("label", "labels"): "label" 열의 이름을 "labels"로 변경합니다. 일반적으로 Hugging Face Transformers 라이브러리에서 모델 훈련을 위해 사용되는 레이블 열의 이름은 "labels"입니다.
  3. tokenized_datasets.set_format("torch"): 데이터셋의 형식을 "torch"로 설정합니다. 이렇게 설정하면 PyTorch 텐서 형식으로 데이터셋이 변환됩니다.
  4. tokenized_datasets["train"].column_names: "train" 부분의 데이터셋에 있는 열의 이름들을 반환합니다. 이를 통해 현재 데이터셋에 어떤 열들이 있는지 확인할 수 있습니다.

따라서 최종적으로 "sentence1", "sentence2", "idx" 열이 삭제되고, "label"이 "labels"로 이름이 변경되며, 데이터셋의 형식이 PyTorch 텐서로 변경된 상태의 데이터셋이 만들어집니다.

 

We can then check that the result only has columns that our model will accept:

 

그런 다음 결과에 모델이 허용하는 열만 있는지 확인할 수 있습니다.

 

["attention_mask", "input_ids", "labels", "token_type_ids"]

 

 

 

Now that this is done, we can easily define our dataloaders:

 

이제 이 작업이 완료되었으므로 데이터로더를 쉽게 정의할 수 있습니다.

 

from torch.utils.data import DataLoader

# 훈련 데이터 로더 생성
train_dataloader = DataLoader(
    tokenized_datasets["train"],  # 훈련 데이터셋
    shuffle=True,                 # 에폭마다 데이터를 섞을지 여부
    batch_size=8,                 # 배치 크기
    collate_fn=data_collator      # 데이터 콜레이터 함수 (패딩 추가)
)

# 검증 데이터 로더 생성
eval_dataloader = DataLoader(
    tokenized_datasets["validation"],  # 검증 데이터셋
    batch_size=8,                       # 배치 크기
    collate_fn=data_collator            # 데이터 콜레이터 함수 (패딩 추가)
)

 

이 코드는 PyTorch의 DataLoader를 사용하여 훈련 및 검증 데이터셋에 대한 데이터 로더를 만드는 부분입니다. 코드를 단계별로 설명하겠습니다.

 

해석:

  1. DataLoader: PyTorch의 데이터 로더 클래스로, 데이터셋에서 샘플을 미니배치로 효율적으로 로드하는 데 사용됩니다.
  2. tokenized_datasets["train"] 및 tokenized_datasets["validation"]: 각각 훈련 및 검증 데이터셋을 나타냅니다.
  3. shuffle=True: 훈련 데이터셋을 에폭(epoch)마다 섞을지 여부를 나타내는 매개변수입니다. 훈련 데이터셋을 섞어 모델이 다양한 샘플을 학습하도록 도웁니다.
  4. batch_size=8: 미니배치의 크기를 나타내는 매개변수로, 각 미니배치에 포함될 샘플의 수를 결정합니다.
  5. collate_fn=data_collator: 데이터 콜레이터 함수를 지정합니다. 이 함수는 배치의 샘플을 처리하여 패딩을 추가하고 동일한 길이로 만들어주는 역할을 합니다. 여기서는 앞서 생성한 DataCollatorWithPadding 객체를 사용합니다.

이렇게 생성된 train_dataloader와 eval_dataloader는 각각 훈련 및 검증 단계에서 사용됩니다. 모델 훈련 시에는 train_dataloader를 이용하여 미니배치 단위로 데이터를 모델에 공급하고, 검증 시에는 eval_dataloader를 사용하여 검증 데이터셋에 대한 예측을 수행합니다.

 

 

To quickly check there is no mistake in the data processing, we can inspect a batch like this:

 

데이터 처리에 실수가 없는지 빠르게 확인하기 위해 다음과 같은 배치를 검사할 수 있습니다.

 

for batch in train_dataloader:
    break
{k: v.shape for k, v in batch.items()}
{'attention_mask': torch.Size([8, 65]),
 'input_ids': torch.Size([8, 65]),
 'labels': torch.Size([8]),
 'token_type_ids': torch.Size([8, 65])}

 

이 코드는 train_dataloader에서 첫 번째 미니배치를 가져와서 그 구조와 크기를 출력하는 부분입니다. 코드를 단계별로 설명하겠습니다.

 

해석:

  1. for batch in train_dataloader:: train_dataloader에서 미니배치를 순회합니다.
  2. break: 첫 번째 미니배치를 가져오고 반복문을 종료합니다. 이 부분에서는 첫 번째 미니배치만 확인합니다.
  3. {k: v.shape for k, v in batch.items()}: 미니배치의 각 텐서의 크기(shape)를 딕셔너리 형태로 출력합니다. 이 딕셔너리는 각 텐서의 키와 크기를 보여줍니다.
    • k는 텐서의 키를 나타내며, 여기서는 "input_ids," "attention_mask," "labels" 등이 될 수 있습니다.
    • v.shape는 텐서의 크기를 나타내며, 예를 들어 (배치 크기, 최대 시퀀스 길이)와 같은 형태일 것입니다.

이 코드를 실행하면 첫 번째 미니배치의 구조와 크기를 확인할 수 있습니다. 이는 데이터 처리 및 토큰화가 올바르게 이루어졌는지 확인하는 데 도움이 됩니다.

 

 

 

 

Note that the actual shapes will probably be slightly different for you since we set shuffle=True for the training dataloader and we are padding to the maximum length inside the batch.

 

훈련 데이터로더에 shuffle=True를 설정하고 배치 내부의 최대 길이까지 패딩하기 때문에 실제 모양은 약간 다를 수 있습니다.

 

Now that we’re completely finished with data preprocessing (a satisfying yet elusive goal for any ML practitioner), let’s turn to the model. We instantiate it exactly as we did in the previous section:

 

이제 데이터 전처리(ML 실무자에게는 달성하기 어려운 목표이지만 그래도 만족스러)가 완전히 완료되었으므로 모델을 살펴보겠습니다. 이전 섹션에서 했던 것과 똑같이 인스턴스화합니다.

 

from transformers import AutoModelForSequenceClassification

model = AutoModelForSequenceClassification.from_pretrained(checkpoint, num_labels=2)

 

이 코드는 Hugging Face Transformers 라이브러리를 사용하여 시퀀스 분류 모델을 로드하는 부분입니다. 코드를 단계별로 설명하겠습니다.

 

해석:

  1. from transformers import AutoModelForSequenceClassification: 시퀀스 분류 모델을 불러오기 위해 Hugging Face Transformers 라이브러리에서 AutoModelForSequenceClassification 클래스를 가져옵니다.
  2. AutoModelForSequenceClassification.from_pretrained(checkpoint, num_labels=2): 미리 훈련된 모델을 로드합니다. checkpoint는 로드하려는 모델의 이름 또는 경로를 나타냅니다. num_labels=2는 출력 레이블의 수를 나타내며, 이 경우 이진 분류를 위해 2로 설정되었습니다.

로드된 모델은 텍스트 시퀀스를 입력으로 받아 각 클래스에 대한 로짓을 출력하는 시퀀스 분류 모델입니다. 이 모델은 이미 사전 훈련된 가중치를 가지고 있으며, 특정 작업에 맞게 조정할 수 있습니다. 이러한 모델을 훈련하거나 텍스트 분류 작업에 활용할 수 있습니다.

 

To make sure that everything will go smoothly during training, we pass our batch to this model:

 

훈련 중에 모든 것이 원활하게 진행되도록 배치를 다음 모델에 전달합니다.

 

outputs = model(**batch)
print(outputs.loss, outputs.logits.shape)

 

tensor(0.5441, grad_fn=<NllLossBackward>) torch.Size([8, 2])

 

이 코드는 시퀀스 분류 모델에 입력 데이터를 주입하고, 모델의 출력인 손실 값(loss)과 로짓(logits)의 형태(shape)를 출력하는 부분입니다. 코드를 단계별로 설명하겠습니다.

 

해석:

  1. model(**batch): batch에 있는 입력 데이터를 모델에 전달합니다. batch에는 토큰화된 입력 데이터가 있으며, 모델은 이를 처리하여 예측을 수행합니다.
  2. outputs: 모델의 출력 결과를 저장한 객체입니다. 이 객체에는 여러 속성이 포함되어 있습니다.
    • outputs.loss: 모델의 출력 손실 값입니다. 이 값은 훈련 중에 사용되며, 손실을 최소화하기 위해 모델의 가중치가 업데이트됩니다.
    • outputs.logits: 모델의 출력으로, 각 클래스에 대한 로짓 값입니다. 로짓은 softmax 함수를 거친 후 확률로 변환되어 예측 클래스가 결정됩니다. logits.shape는 로짓 텐서의 크기를 나타냅니다.
  3. print(outputs.loss, outputs.logits.shape): 모델의 출력인 손실 값과 로짓 텐서의 크기를 출력합니다.

이 코드는 모델이 입력 데이터를 처리하고 그 결과를 확인하는 데 사용됩니다. 특히, 훈련할 때는 손실 값이 중요하며, 추론 및 평가 단계에서는 로짓을 통해 예측 결과를 확인할 수 있습니다.

 

 

 

All 🤗 Transformers models will return the loss when labels are provided, and we also get the logits (two for each input in our batch, so a tensor of size 8 x 2).

 

모든 🤗 Transformers 모델은 레이블이 제공되면 손실을 반환하며 로지트도 얻습니다(배치의 각 입력에 대해 2개이므로 크기가 8 x 2인 텐서).

 

We’re almost ready to write our training loop! We’re just missing two things: an optimizer and a learning rate scheduler. Since we are trying to replicate what the Trainer was doing by hand, we will use the same defaults. The optimizer used by the Trainer is AdamW, which is the same as Adam, but with a twist for weight decay regularization (see “Decoupled Weight Decay Regularization” by Ilya Loshchilov and Frank Hutter):

 

훈련 루프를 작성할 준비가 거의 다 되었습니다! 우리는 최적화 프로그램과 학습률 스케줄러라는 두 가지를 놓치고 있습니다. Trainer가 직접 수행한 작업을 복제하려고 하므로 동일한 기본값을 사용하겠습니다. Trainer에서 사용하는 최적화 프로그램은 AdamW입니다. 이는 Adam과 동일하지만 체중 감소 정규화에 대한 변형이 있습니다(Ilya Loshchilov 및 Frank Hutter의 "De커플링된 체중 감소 정규화" 참조).

 

from transformers import AdamW

# 모델의 파라미터에 AdamW 옵티마이저를 설정
optimizer = AdamW(model.parameters(), lr=5e-5)
 

이 코드는 Hugging Face Transformers 라이브러리에서 제공하는 AdamW 옵티마이저를 설정하는 부분입니다. 코드를 단계별로 설명하겠습니다.

 

해석:

  1. from transformers import AdamW: Hugging Face Transformers 라이브러리에서 AdamW 옵티마이저를 가져옵니다.
  2. optimizer = AdamW(model.parameters(), lr=5e-5): 모델의 파라미터를 가져와서 이를 AdamW 옵티마이저에 전달합니다. lr=5e-5는 학습률(learning rate)을 나타내며, 이 값은 학습 과정에서 가중치를 업데이트하는 정도를 조절합니다.

AdamW는 Adam 옵티마이저에 가중치 감쇠(weight decay)를 추가한 버전입니다. 가중치 감쇠는 모델의 가중치가 너무 커지지 않도록 제한하고, 오버피팅을 방지하는 데 도움을 줍니다.

이렇게 설정된 옵티마이저는 모델의 가중치를 업데이트할 때 사용되며, 이후에 이 옵티마이저를 통해 모델을 최적화하는 학습 과정을 진행할 수 있습니다.

 

Finally, the learning rate scheduler used by default is just a linear decay from the maximum value (5e-5) to 0. To properly define it, we need to know the number of training steps we will take, which is the number of epochs we want to run multiplied by the number of training batches (which is the length of our training dataloader). The Trainer uses three epochs by default, so we will follow that:

 

마지막으로, 기본적으로 사용되는 학습률 스케줄러는 최대값(5e-5)에서 0까지의 선형 감쇠일 뿐입니다. 이를 올바르게 정의하려면 수행할 학습 단계 수, 즉 에포크 수를 알아야 합니다. 훈련 배치 수(훈련 데이터로더의 길이)를 곱하여 실행하려고 합니다. Trainer는 기본적으로 세 가지 에포크를 사용하므로 다음을 따릅니다.

 

from transformers import get_scheduler

# 학습 에폭 수와 전체 학습 단계 수 설정
num_epochs = 3
num_training_steps = num_epochs * len(train_dataloader)

# 선형 학습률 스케줄러 설정
lr_scheduler = get_scheduler(
    "linear",
    optimizer=optimizer,
    num_warmup_steps=0,
    num_training_steps=num_training_steps,
)

# 전체 학습 단계 수 출력
print(num_training_steps)
1377

 

 

이 코드는 Hugging Face Transformers 라이브러리에서 제공하는 학습률 스케줄러를 설정하는 부분입니다. 코드를 단계별로 설명하겠습니다.

 

해석:

  1. from transformers import get_scheduler: Hugging Face Transformers 라이브러리에서 학습률 스케줄러를 가져옵니다.
  2. num_epochs = 3 및 num_training_steps = num_epochs * len(train_dataloader): 전체 학습 에폭 수와 전체 학습 단계 수를 설정합니다. 이 값들은 학습률 스케줄러 설정에 사용됩니다.
  3. lr_scheduler = get_scheduler("linear", optimizer=optimizer, num_warmup_steps=0, num_training_steps=num_training_steps): 선형 학습률 스케줄러를 설정합니다. "linear"는 선형 스케줄러를 의미하며, 학습률이 선형으로 감소하도록 만듭니다. num_warmup_steps=0은 워머핑 단계 수를 0으로 설정하며, num_training_steps는 총 학습 단계 수입니다.
  4. print(num_training_steps): 전체 학습 단계 수를 출력합니다.

이렇게 설정된 선형 학습률 스케줄러는 학습률을 일정한 비율로 감소시키면서 학습을 진행합니다. 설정된 값들은 Trainer 클래스에서 사용되는 기본값을 따르도록 설정되어 있습니다.

 

 

The training loop

 

One last thing: we will want to use the GPU if we have access to one (on a CPU, training might take several hours instead of a couple of minutes). To do this, we define a device we will put our model and our batches on:

 

마지막으로, GPU에 액세스할 수 있는 경우 GPU를 사용하고 싶을 것입니다(CPU에서는 훈련에 몇 분이 아닌 몇 시간이 걸릴 수 있습니다). 이를 위해 모델과 배치를 배치할 장치를 정의합니다.

 

import torch

# CUDA가 사용 가능한 경우 GPU를, 그렇지 않은 경우 CPU를 선택
device = torch.device("cuda") if torch.cuda.is_available() else torch.device("cpu")

# 모델을 선택한 디바이스로 이동
model.to(device)

# 선택한 디바이스 출력
device
device(type='cuda')

 

이 코드는 PyTorch를 사용하여 모델을 GPU 또는 CPU로 이동하는 부분입니다. 코드를 단계별로 설명하겠습니다.

 

해석:

  1. import torch: PyTorch 라이브러리를 가져옵니다.
  2. device = torch.device("cuda") if torch.cuda.is_available() else torch.device("cpu"): GPU(CUDA)가 사용 가능한 경우 GPU를 선택하고, 그렇지 않은 경우 CPU를 선택합니다. 이를 위해 torch.cuda.is_available() 함수를 사용하여 GPU 사용 가능 여부를 확인합니다.
  3. model.to(device): 모델을 선택한 디바이스로 이동시킵니다. 이로써 모델의 연산이 선택한 디바이스에서 수행되게 됩니다.
  4. device: 선택한 디바이스를 출력합니다. 이는 모델이 현재 어떤 디바이스에서 실행되고 있는지 확인할 수 있습니다.

이 코드는 모델을 GPU로 이동시키는데 사용되며, GPU가 없거나 사용이 불가능한 경우 CPU에서 모델을 실행하게 됩니다. GPU를 사용하면 모델의 연산이 병렬로 처리되어 훨씬 빠른 학습이 가능합니다.

 

 

CoLab에서는 GPU 사용은 안되고 CPU 를 사용해야 합니다.

 

We are now ready to train! To get some sense of when training will be finished, we add a progress bar over our number of training steps, using the tqdm library:

 

이제 훈련할 준비가 되었습니다! 훈련이 언제 완료되는지 알아보기 위해 tqdm 라이브러리를 사용하여 훈련 단계 수에 진행률 표시줄을 추가합니다.

 

from tqdm.auto import tqdm

# 훈련 단계 수만큼의 프로그레스 바 생성
progress_bar = tqdm(range(num_training_steps))

# 모델을 훈련 모드로 설정
model.train()

# 에폭 수만큼 반복
for epoch in range(num_epochs):
    # 훈련 데이터로더에서 미니배치를 가져와 반복
    for batch in train_dataloader:
        # 미니배치의 각 요소를 선택한 디바이스로 이동
        batch = {k: v.to(device) for k, v in batch.items()}
        
        # 모델에 미니배치를 전달하여 출력을 얻음
        outputs = model(**batch)
        
        # 손실 값을 얻음
        loss = outputs.loss
        
        # 역전파 수행
        loss.backward()
        
        # 옵티마이저로 모델 파라미터 업데이트
        optimizer.step()
        
        # 학습률 스케줄러를 업데이트
        lr_scheduler.step()
        
        # 기울기를 초기화하여 다음 미니배치에 대한 역전파를 위해 준비
        optimizer.zero_grad()
        
        # 프로그레스 바 업데이트
        progress_bar.update(1)

 

이 코드는 모델을 훈련하기 위한 학습 루프를 나타냅니다. 코드를 단계별로 설명하겠습니다.

 

해석:

  1. from tqdm.auto import tqdm: 훈련 과정에서 진행 상황을 시각적으로 확인하기 위해 tqdm 라이브러리에서 프로그레스 바를 사용합니다.
  2. progress_bar = tqdm(range(num_training_steps)): 전체 훈련 단계 수에 대한 프로그레스 바를 생성합니다.
  3. model.train(): 모델을 훈련 모드로 설정합니다. 이는 드롭아웃과 배치 정규화와 같은 학습 관련 기능을 활성화합니다.
  4. for epoch in range(num_epochs):: 지정된 에폭 수만큼 반복합니다.
  5. for batch in train_dataloader:: 훈련 데이터로더에서 미니배치를 가져와서 반복합니다.
  6. batch = {k: v.to(device) for k, v in batch.items()}: 미니배치의 각 요소를 선택한 디바이스로 이동시킵니다.
  7. outputs = model(**batch): 모델에 미니배치를 전달하여 모델의 출력을 얻습니다.
  8. loss = outputs.loss: 모델의 출력에서 손실 값을 얻습니다.
  9. loss.backward(): 역전파를 통해 기울기를 계산합니다.
  10. optimizer.step(): 옵티마이저를 사용하여 모델 파라미터를 업데이트합니다.
  11. lr_scheduler.step(): 학습률 스케줄러를 업데이트합니다.
  12. optimizer.zero_grad(): 모델 파라미터의 기울기를 초기화하여 다음 미니배치에 대한 역전파를 위해 준비합니다.
  13. progress_bar.update(1): 프로그레스 바를 업데이트하여 진행 상황을 시각적으로 확인합니다.

이렇게 훈련 루프를 통해 모델은 주어진 에폭 수에 대해 훈련되고, 손실이 감소하도록 파라미터가 업데이트됩니다.

 

You can see that the core of the training loop looks a lot like the one in the introduction. We didn’t ask for any reporting, so this training loop will not tell us anything about how the model fares. We need to add an evaluation loop for that.

 

훈련 루프의 핵심이 소개 부분과 매우 유사하다는 것을 알 수 있습니다. 우리는 보고를 요청하지 않았으므로 이 훈련 루프는 모델이 어떻게 진행되는지에 대해 아무 것도 알려주지 않습니다. 이를 위해 평가 루프를 추가해야 합니다.

 

The evaluation loop

 

As we did earlier, we will use a metric provided by the 🤗 Evaluate library. We’ve already seen the metric.compute() method, but metrics can actually accumulate batches for us as we go over the prediction loop with the method add_batch(). Once we have accumulated all the batches, we can get the final result with metric.compute(). Here’s how to implement all of this in an evaluation loop:

 

이전과 마찬가지로 🤗 Evaluate library 에서 제공하는 측정항목을 사용하겠습니다. 우리는 이미 metric.compute() 메소드를 보았지만 add_batch() 메소드를 사용하여 예측 루프를 진행하면서 메트릭은 실제로 배치를 누적할 수 있습니다. 모든 배치를 누적한 후에는 metric.compute()를 사용하여 최종 결과를 얻을 수 있습니다. 평가 루프에서 이 모든 것을 구현하는 방법은 다음과 같습니다.

 

import evaluate

# GLUE 메트릭을 로드
metric = evaluate.load("glue", "mrpc")

# 모델을 평가 모드로 설정
model.eval()

# 검증 데이터로더에서 미니배치를 가져와 반복
for batch in eval_dataloader:
    # 미니배치의 각 요소를 선택한 디바이스로 이동
    batch = {k: v.to(device) for k, v in batch.items()}

    # 기울기를 계산하지 않도록 설정하여 평가 수행
    with torch.no_grad():
        outputs = model(**batch)

    # 모델의 출력에서 로짓(확률 분포)을 얻음
    logits = outputs.logits

    # 로짓에서 예측 클래스를 결정
    predictions = torch.argmax(logits, dim=-1)

    # 메트릭에 현재 미니배치의 예측값과 레이블을 추가
    metric.add_batch(predictions=predictions, references=batch["labels"])

# 메트릭을 통해 최종 평가 수행
metric.compute()
{'accuracy': 0.8431372549019608, 'f1': 0.8907849829351535}

이 코드는 모델을 사용하여 검증 데이터셋에 대한 평가를 수행하는 부분입니다. 코드를 단계별로 설명하겠습니다.

 

해석:

  1. import evaluate: 평가 관련 함수들이 정의된 evaluate 모듈을 가져옵니다.
  2. metric = evaluate.load("glue", "mrpc"): GLUE 벤치마크의 MRPC(Microsoft Research Paraphrase Corpus)에 대한 메트릭을 로드합니다.
  3. model.eval(): 모델을 평가 모드로 설정합니다. 이는 드롭아웃과 배치 정규화와 같은 학습 관련 기능을 비활성화합니다.
  4. for batch in eval_dataloader:: 검증 데이터로더에서 미니배치를 가져와 반복합니다.
  5. batch = {k: v.to(device) for k, v in batch.items()}: 미니배치의 각 요소를 선택한 디바이스로 이동시킵니다.
  6. with torch.no_grad():: 기울기를 계산하지 않도록 설정하여 평가 수행을 위해 모델을 실행합니다.
  7. outputs = model(**batch): 모델에 미니배치를 전달하여 모델의 출력을 얻습니다.
  8. logits = outputs.logits: 모델의 출력에서 로짓(확률 분포)을 얻습니다.
  9. predictions = torch.argmax(logits, dim=-1): 로짓에서 예측 클래스를 결정합니다.
  10. metric.add_batch(predictions=predictions, references=batch["labels"]): 메트릭에 현재 미니배치의 예측값과 레이블을 추가합니다.
  11. metric.compute(): 메트릭을 통해 최종 평가를 수행합니다.

이를 통해 모델이 검증 데이터에 대해 얼마나 좋은 성능을 보이는지를 측정하고, GLUE 벤치마크에서 정의된 평가 메트릭을 계산합니다.

 

Again, your results will be slightly different because of the randomness in the model head initialization and the data shuffling, but they should be in the same ballpark.

 

다시 말하지만, 모델 헤드 초기화 및 데이터 셔플링의 무작위성으로 인해 결과가 약간 다르지만 동일한 기준점에 있어야 합니다.

 

✏️ Try it out! Modify the previous training loop to fine-tune your model on the SST-2 dataset.

 

✏️ 한번 사용해 보세요! 이전 훈련 루프를 수정하여 SST-2 데이터세트에서 모델을 미세 조정하세요.

 

 

Supercharge your training loop with 🤗 Accelerate

https://youtu.be/s7dy8QRgjJ0?si=tR63TKSpr0Wj3Ebn

 

 

 

TPU(Tensor Processing Unit)는 구글에서 개발한 특수한 하드웨어로, 딥러닝 작업을 가속화하기 위해 설계되었습니다. TPU는 주로 텐서플로우(TensorFlow) 딥러닝 프레임워크와 함께 사용되며, 딥러닝 모델의 학습과 추론 속도를 높이는 데 중점을 둡니다.

 

TPU의 주요 특징은 다음과 같습니다:

  1. 고성능 병렬 처리: TPU는 텐서 연산에 특화된 구조로 구성되어 있어, 행렬 곱셈 및 기타 텐서 연산을 효율적으로 수행할 수 있습니다. 이는 딥러닝 모델의 대규모 연산에 적합합니다.
  2. 낮은 전력 소모: TPU는 높은 성능에도 불구하고 상대적으로 낮은 전력을 소비합니다. 이는 에너지 효율성 면에서 우수한 성능을 제공합니다.
  3. TensorFlow와의 통합: TPU는 주로 텐서플로우와 함께 사용되며, 텐서플로우에서 제공하는 TPU 지원 기능을 활용하여 모델을 효율적으로 실행할 수 있습니다.
  4. 대규모 딥러닝 모델 지원: TPU는 대규모 딥러닝 모델의 학습에 적합하며, 대규모 데이터셋에서의 훈련 작업에 특히 유용합니다.

TPU는 클라우드 기반의 딥러닝 작업에 많이 사용되며, 구글 클라우드(Google Cloud)와 같은 클라우드 서비스 제공업체에서 TPU를 사용할 수 있는 환경을 제공하고 있습니다. TPU는 GPU와 비교하여 특정 딥러닝 워크로드에서 높은 성능을 발휘할 수 있으며, 딥러닝 연구 및 응용 분야에서 중요한 역할을 하고 있습니다.

 
 

The training loop we defined earlier works fine on a single CPU or GPU. But using the 🤗 Accelerate library, with just a few adjustments we can enable distributed training on multiple GPUs or TPUs. Starting from the creation of the training and validation dataloaders, here is what our manual training loop looks like:

이전에 정의한 훈련 루프는 단일 CPU 또는 GPU에서 잘 작동합니다. 하지만 🤗 Accelerate 라이브러리를 사용하면 몇 가지 조정만으로 여러 GPU 또는 TPU에서 분산 교육을 활성화할 수 있습니다. 교육 및 검증 데이터로더 생성부터 시작하여 수동 교육 루프는 다음과 같습니다.
 
 
from transformers import AdamW, AutoModelForSequenceClassification, get_scheduler

# 사전 훈련된 모델과 함께 시퀀스 분류 모델을 불러옴
model = AutoModelForSequenceClassification.from_pretrained(checkpoint, num_labels=2)

# AdamW 옵티마이저를 정의하고 모델의 파라미터를 전달
optimizer = AdamW(model.parameters(), lr=3e-5)

# 사용 가능한 GPU가 있다면 GPU로 모델을 이동
device = torch.device("cuda") if torch.cuda.is_available() else torch.device("cpu")
model.to(device)

# 훈련 설정: 에폭 수 및 훈련 스텝 수 설정
num_epochs = 3
num_training_steps = num_epochs * len(train_dataloader)

# 러닝 레이트 스케줄러 설정
lr_scheduler = get_scheduler(
    "linear",
    optimizer=optimizer,
    num_warmup_steps=0,
    num_training_steps=num_training_steps,
)

# tqdm을 사용하여 훈련 진행 상황을 시각적으로 표시
progress_bar = tqdm(range(num_training_steps))

# 모델을 훈련 모드로 설정
model.train()

# 에폭 수 만큼 반복
for epoch in range(num_epochs):
    # 훈련 데이터로더에서 미니배치를 가져와 반복
    for batch in train_dataloader:
        # 미니배치의 각 요소를 선택한 디바이스로 이동
        batch = {k: v.to(device) for k, v in batch.items()}

        # 모델에 미니배치를 전달하여 출력을 얻음
        outputs = model(**batch)

        # 손실을 얻고 역전파
        loss = outputs.loss
        loss.backward()

        # 옵티마이저를 사용하여 모델 파라미터 업데이트
        optimizer.step()

        # 러닝 레이트 스케줄러를 사용하여 러닝 레이트 조절
        lr_scheduler.step()

        # 기울기 초기화
        optimizer.zero_grad()

        # tqdm 업데이트
        progress_bar.update(1)

 

이 코드는 딥러닝 모델의 훈련을 위한 기본적인 스크립트를 나타냅니다. 코드를 단계별로 설명하겠습니다.

 

해석:

  1. 모델, 옵티마이저, 디바이스 설정: 사전 훈련된 모델을 불러오고, AdamW 옵티마이저를 정의하며, 사용 가능한 GPU가 있다면 GPU로 모델을 이동시킵니다.
  2. 훈련 설정: 에폭 수 및 훈련 스텝 수 설정합니다.
  3. 러닝 레이트 스케줄러 설정: 러닝 레이트 스케줄러를 설정하여 훈련 동안 러닝 레이트를 동적으로 조절합니다.
  4. tqdm을 사용한 진행 표시: tqdm은 훈련 진행 상황을 시각적으로 표시하는 도구입니다.
  5. 모델 훈련: 훈련 데이터로더에서 미니배치를 가져와 모델에 전달하고, 손실을 계산하여 역전파를 수행하며, 옵티마이저를 사용하여 모델 파라미터를 업데이트합니다. 러닝 레이트 스케줄러를 사용하여 러닝 레이트를 조절하고, tqdm을 업데이트하여 훈련 진행 상황을 표시합니다.

이러한 훈련 스크립트는 특정 모델과 데이터에 맞게 조정될 수 있으며, 주로 Hugging Face의 Transformers 라이브러리를 사용하여 딥러닝 모델을 훈련하는 일반적인 흐름을 나타냅니다.

 

And here are the changes:  변경 사항은 다음과 같습니다.

 

from accelerate import Accelerator
from transformers import AdamW, AutoModelForSequenceClassification, get_scheduler

# Accelerator 객체 생성
accelerator = Accelerator()

# AutoModelForSequenceClassification 모델 및 AdamW 옵티마이저 초기화
model = AutoModelForSequenceClassification.from_pretrained(checkpoint, num_labels=2)
optimizer = AdamW(model.parameters(), lr=3e-5)

# 훈련 및 검증 데이터로더, 모델, 옵티마이저를 Accelerator로 준비
train_dataloader, eval_dataloader, model, optimizer = accelerator.prepare(
    train_dataloader, eval_dataloader, model, optimizer
)

# 나머지 코드는 동일하게 유지됨
num_epochs = 3
num_training_steps = num_epochs * len(train_dataloader)
lr_scheduler = get_scheduler(
    "linear",
    optimizer=optimizer,
    num_warmup_steps=0,
    num_training_steps=num_training_steps
)

progress_bar = tqdm(range(num_training_steps))

model.train()
for epoch in range(num_epochs):
    for batch in train_dataloader:
        # batch = {k: v.to(device) for k, v in batch.items()}  # 이 부분 삭제
        outputs = model(**batch)
        loss = outputs.loss
        # loss.backward()  # 이 부분 변경
        accelerator.backward(loss)

        optimizer.step()
        lr_scheduler.step()
        optimizer.zero_grad()
        progress_bar.update(1)

 

이 코드는 accelerate 라이브러리를 사용하여 GPU 가속을 적용한 딥러닝 모델의 훈련 스크립트를 나타냅니다. 코드의 변경점에 대해 설명하겠습니다.

 

변경된 부분:

  1. Accelerator 사용: Accelerator 객체를 생성하고, prepare 메서드를 사용하여 훈련 데이터로더, 검증 데이터로더, 모델, 옵티마이저를 가속화합니다.
  2. Device 설정 제거: GPU 디바이스 설정 부분이 삭제되었습니다. Accelerator가 내부적으로 디바이스 관리를 수행합니다.
  3. Gradient 계산 변경: loss.backward() 대신 accelerator.backward(loss)를 사용하여 gradient 계산을 가속화합니다. Accelerator는 내부적으로 gradient 계산 및 관리를 처리합니다.

이러한 변경으로 코드는 GPU 가속을 사용하면서도 간소화되었고, 가속화 라이브러리를 통해 더욱 효율적으로 딥러닝 모델을 훈련할 수 있습니다.

 

The first line to add is the import line. The second line instantiates an Accelerator object that will look at the environment and initialize the proper distributed setup. 🤗 Accelerate handles the device placement for you, so you can remove the lines that put the model on the device (or, if you prefer, change them to use accelerator.device instead of device).

 

추가할 첫 번째 줄은 import 줄입니다. 두 번째 줄은 환경을 살펴보고 적절한 분산 설정을 초기화하는 Accelerator 개체를 인스턴스화합니다. 🤗 Accelerate가 장치 배치를 자동으로 처리하므로 장치에 모델을 배치하는 줄을 제거할 수 있습니다(또는 원하는 경우 장치 대신 accelerator.device를 사용하도록 변경).

 

Then the main bulk of the work is done in the line that sends the dataloaders, the model, and the optimizer to accelerator.prepare(). This will wrap those objects in the proper container to make sure your distributed training works as intended. The remaining changes to make are removing the line that puts the batch on the device (again, if you want to keep this you can just change it to use accelerator.device) and replacing loss.backward() with accelerator.backward(loss).

 

그런 다음 데이터로더, 모델 및 최적화 프로그램을 accelerator.prepare()로 보내는 라인에서 주요 작업이 수행됩니다. 이렇게 하면 분산 교육이 의도한 대로 작동하는지 확인하기 위해 해당 개체를 적절한 컨테이너에 래핑합니다. 나머지 변경 사항은 장치에 배치를 배치하는 줄을 제거하고(다시 말하지만 이를 유지하려면 accelerator.device를 사용하도록 변경하면 됩니다) loss.backward()를 accelerator.backward(loss)로 바꾸는 것입니다. .

 

⚠️ In order to benefit from the speed-up offered by Cloud TPUs, we recommend padding your samples to a fixed length with the `padding="max_length"` and `max_length` arguments of the tokenizer.
 
⚠️ Cloud TPU가 제공하는 속도 향상의 이점을 활용하려면 토크나이저의 `padding="max_length"` 및 `max_length` 인수를 사용하여 샘플을 고정 길이로 패딩하는 것이 좋습니다.
 

If you’d like to copy and paste it to play around, here’s what the complete training loop looks like with 🤗 Accelerate:

 

복사하여 붙여넣고 놀고 싶다면 🤗 Accelerate를 사용한 전체 훈련 루프는 다음과 같습니다.

 

from accelerate import Accelerator
from transformers import AdamW, AutoModelForSequenceClassification, get_scheduler

# Accelerator 객체 생성
accelerator = Accelerator()

# AutoModelForSequenceClassification 모델 및 AdamW 옵티마이저 초기화
model = AutoModelForSequenceClassification.from_pretrained(checkpoint, num_labels=2)
optimizer = AdamW(model.parameters(), lr=3e-5)

# 훈련 및 검증 데이터로더, 모델, 옵티마이저를 Accelerator로 준비
train_dl, eval_dl, model, optimizer = accelerator.prepare(
    train_dataloader, eval_dataloader, model, optimizer
)

# 훈련 설정: 에폭 수 및 훈련 스텝 수 설정
num_epochs = 3
num_training_steps = num_epochs * len(train_dl)

# 러닝 레이트 스케줄러 설정
lr_scheduler = get_scheduler(
    "linear",
    optimizer=optimizer,
    num_warmup_steps=0,
    num_training_steps=num_training_steps,
)

# tqdm을 사용하여 훈련 진행 상황을 시각적으로 표시
progress_bar = tqdm(range(num_training_steps))

# 모델을 훈련 모드로 설정
model.train()

# 에폭 수 만큼 반복
for epoch in range(num_epochs):
    # 훈련 데이터로더에서 미니배치를 가져와 반복
    for batch in train_dl:
        # 모델에 미니배치를 전달하여 출력을 얻음
        outputs = model(**batch)
        # 손실을 얻고 역전파
        loss = outputs.loss
        accelerator.backward(loss)

        # 옵티마이저를 사용하여 모델 파라미터 업데이트
        optimizer.step()
        # 러닝 레이트 스케줄러를 사용하여 러닝 레이트 조절
        lr_scheduler.step()
        # 기울기 초기화
        optimizer.zero_grad()
        # tqdm 업데이트
        progress_bar.update(1)

 

이 코드는 accelerate 라이브러리를 사용하여 GPU 가속을 적용한 딥러닝 모델의 훈련 스크립트를 나타냅니다. 

 

변경된 부분:

  1. Accelerator 사용: Accelerator 객체를 생성하고, prepare 메서드를 사용하여 훈련 데이터로더, 검증 데이터로더, 모델, 옵티마이저를 가속화합니다.
  2. 변수 명칭 변경: train_dl 및 eval_dl로 변수명을 변경하여 가속화된 데이터로더를 사용합니다.

나머지 코드는 이전과 동일하게 유지되며, 가속화 라이브러리를 사용하여 GPU 가속을 적용한 효율적인 딥러닝 모델 훈련을 수행합니다.

 

Putting this in a train.py script will make that script runnable on any kind of distributed setup. To try it out in your distributed setup, run the command:

 

이것을 train.py 스크립트에 넣으면 모든 종류의 분산 설정에서 해당 스크립트를 실행할 수 있습니다. 분산 설정에서 사용해 보려면 다음 명령을 실행하세요.

 

accelerate config

 

accelerate config 명령어는 accelerate 라이브러리의 환경 설정을 확인하는 명령어입니다. 이 명령어를 사용하면 현재 가속화 환경에 대한 설정 정보를 확인할 수 있습니다. 아래는 해당 명령어에 대한 설명입니다.

 

위 명령어를 실행하면, 현재 사용 중인 환경에 대한 다양한 설정이 출력됩니다. 주로 다음과 같은 정보를 확인할 수 있습니다.

  1. accelerator 설정: 현재 사용 중인 가속화 기술, 예를 들어, cuda 또는 tpu 등이 표시됩니다.
  2. num_processes 및 num_gpus 설정: 병렬 처리에 사용되는 프로세스 수와 GPU 수가 표시됩니다.
  3. fp16 설정: 16-bit 부동 소수점 사용 여부에 대한 설정이 표시됩니다.
  4. fp16_backend 설정: 16-bit 부동 소수점 연산을 처리하는 백엔드(예: apex 또는 amp)가 표시됩니다.
  5. ddp 설정: 분산 데이터 병렬 설정이 표시됩니다.

이 명령어를 사용하면 가속화 환경에 대한 자세한 설정을 확인할 수 있어, 딥러닝 모델을 효율적으로 훈련하기 위해 가속화 라이브러리를 조정하는 데 도움이 됩니다.

 

 

which will prompt you to answer a few questions and dump your answers in a configuration file used by this command:

 

그러면 몇 가지 질문에 대답하고 이 명령에서 사용하는 구성 파일에 답변을 덤프하라는 메시지가 표시됩니다.

 

accelerate launch train.py

 

accelerate launch train.py 명령어는 accelerate 라이브러리를 사용하여 딥러닝 모델을 훈련하는 스크립트인 train.py를 실행하는 명령어입니다. 이 명령어를 사용하면 가속화 환경에서 훈련을 수행할 수 있습니다. 아래는 해당 명령어에 대한 설명입니다.

 

해당 명령어를 실행하면, train.py 스크립트가 가속화 라이브러리의 환경 설정에 맞게 실행됩니다. 이때, 여러 GPU 또는 TPU 등을 활용하여 훈련을 가속화할 수 있습니다.

 

이 명령어를 사용하는 주요 이점은:

  1. 분산 훈련 지원: accelerate는 분산 훈련을 지원하며, 여러 GPU 또는 TPU에서 모델을 효율적으로 훈련할 수 있도록 도와줍니다.
  2. Mixed Precision 훈련: 16-bit 부동 소수점 연산을 사용하여 모델의 훈련 속도를 향상시킵니다.
  3. 간편한 사용: accelerate를 사용하면 분산 훈련 및 가속화 설정에 대한 복잡한 부분을 자동으로 처리하여 간편하게 활용할 수 있습니다.

따라서, accelerate launch 명령어를 사용하면 train.py를 가속화된 환경에서 간편하게 실행할 수 있습니다.

 

 

which will launch the distributed training. 분산 교육이 시작됩니다.

 

If you want to try this in a Notebook (for instance, to test it with TPUs on Colab), just paste the code in a training_function() and run a last cell with:

 

노트북에서 이 작업을 시도하려면(예: Colab의 TPU로 테스트) training_function()에 코드를 붙여넣고 다음을 사용하여 마지막 셀을 실행하세요.

 

from accelerate import notebook_launcher

notebook_launcher(training_function)

 

from accelerate import notebook_launcher와 notebook_launcher(training_function) 코드는 Jupyter Notebook 환경에서 accelerate 라이브러리를 사용하여 모델 훈련 함수(training_function)를 가속화하여 실행하는 코드입니다. 이 코드를 사용하면 Jupyter Notebook에서 간편하게 모델 훈련을 가속화할 수 있습니다.

해당 코드를 단계별로 설명하겠습니다:

 

notebook_launcher 임포트:

from accelerate import notebook_launcher

 

 

accelerate 라이브러리에서 notebook_launcher 모듈을 임포트합니다. 이 모듈은 Jupyter Notebook에서 가속화된 훈련을 지원합니다.

 

notebook_launcher 사용:

notebook_launcher(training_function)

 

  1. notebook_launcher 함수에 모델을 훈련시키는 함수(training_function)를 전달하여 사용합니다. 이 함수는 가속화된 환경에서 모델 훈련을 시작합니다. notebook_launcher는 분산 훈련 및 Mixed Precision 훈련을 처리하는 등 가속화에 필요한 설정을 자동으로 수행합니다.

이 코드를 사용하면 Jupyter Notebook에서 간편하게 training_function을 실행할 수 있으며, accelerate 라이브러리의 기능을 활용하여 가속화된 딥러닝 모델 훈련을 수행할 수 있습니다.

 

You can find more examples in the 🤗 Accelerate repo.

 

🤗 Accelerate 저장소에서 더 많은 예시를 찾아보실 수 있습니다.

 

반응형


반응형

https://huggingface.co/learn/nlp-course/chapter3/3?fw=pt

 

Fine-tuning a model with the Trainer API - Hugging Face NLP Course

🤗 Transformers provides a Trainer class to help you fine-tune any of the pretrained models it provides on your dataset. Once you’ve done all the data preprocessing work in the last section, you have just a few steps left to define the Trainer. The har

huggingface.co

 

Fine-tuning a model with the Trainer API

 

https://youtu.be/nvBXf7s7vTI?si=7V5gLAt293qhuK67

 

🤗 Transformers provides a Trainer class to help you fine-tune any of the pretrained models it provides on your dataset. Once you’ve done all the data preprocessing work in the last section, you have just a few steps left to define the Trainer. The hardest part is likely to be preparing the environment to run Trainer.train(), as it will run very slowly on a CPU. If you don’t have a GPU set up, you can get access to free GPUs or TPUs on Google Colab.

 

🤗 Transformers는 데이터세트에서 제공하는 사전 훈련된 모델을 미세 조정하는 데 도움이 되는 Trainer 클래스를 제공합니다. 마지막 섹션에서 모든 데이터 전처리 작업을 완료하고 나면 Trainer를 정의하기 위한 몇 단계만 남았습니다. 가장 어려운 부분은 Trainer.train()을 실행하기 위한 환경을 준비하는 것입니다. 왜냐하면 Trainer.train()은 CPU에서 매우 느리게 실행되기 때문입니다. GPU가 설정되어 있지 않은 경우 Google Colab에서 무료 GPU 또는 TPU에 액세스할 수 있습니다.

 

The code examples below assume you have already executed the examples in the previous section. Here is a short summary recapping what you need:

 

아래 코드 예제에서는 이전 섹션의 예제를 이미 실행했다고 가정합니다. 다음은 필요한 사항을 간략하게 요약한 것입니다.

 

from datasets import load_dataset
from transformers import AutoTokenizer, DataCollatorWithPadding

# MRPC 데이터셋 로드
raw_datasets = load_dataset("glue", "mrpc")

# BERT 모델의 체크포인트를 "bert-base-uncased"로 지정하여 토크나이저 초기화
checkpoint = "bert-base-uncased"
tokenizer = AutoTokenizer.from_pretrained(checkpoint)

# 사용자 정의 토크나이즈 함수 정의
def tokenize_function(example):
    return tokenizer(example["sentence1"], example["sentence2"], truncation=True)

# 토큰화된 데이터셋 생성
tokenized_datasets = raw_datasets.map(tokenize_function, batched=True)

# 데이터 콜레이터 초기화
data_collator = DataCollatorWithPadding(tokenizer=tokenizer)

 

이 코드는 Hugging Face Transformers 라이브러리를 사용하여 MRPC(Microsoft Research Paraphrase Corpus) 데이터셋을 로드하고, BERT 모델의 토크나이저를 초기화하며, 토큰화 함수와 데이터 콜레이터를 정의하는 예제입니다. 코드를 단계별로 설명하겠습니다.

 

해석:

  1. load_dataset("glue", "mrpc"): Hugging Face의 datasets 라이브러리를 사용하여 MRPC 데이터셋을 로드합니다.
  2. AutoTokenizer.from_pretrained(checkpoint): BERT 모델의 체크포인트를 지정하여 해당 모델에 대한 토크나이저를 초기화합니다.
  3. def tokenize_function(example): MRPC 데이터셋의 각 예시에 대한 사용자 정의 토크나이즈 함수를 정의합니다. 이 함수는 "sentence1"과 "sentence2" 필드의 문장을 토큰화합니다.
  4. raw_datasets.map(tokenize_function, batched=True): map 함수를 사용하여 데이터셋의 각 예시에 대해 토크나이즈 함수를 적용하고, 배치(batch) 단위로 토큰화된 데이터셋을 생성합니다.
  5. DataCollatorWithPadding(tokenizer=tokenizer): 데이터 콜레이터를 초기화합니다. 이 데이터 콜레이터는 패딩을 적용하여 배치의 모든 입력 시퀀스를 동일한 길이로 만들어주는 역할을 합니다.

이렇게 초기화된 토크나이저, 토큰화 함수, 데이터 콜레이터는 이후 모델 훈련 또는 추론을 위해 사용될 수 있습니다.

 

 

Training

The first step before we can define our Trainer is to define a TrainingArguments class that will contain all the hyperparameters the Trainer will use for training and evaluation. The only argument you have to provide is a directory where the trained model will be saved, as well as the checkpoints along the way. For all the rest, you can leave the defaults, which should work pretty well for a basic fine-tuning.

 

Trainer를 정의하기 전 첫 번째 단계는 Trainer가 훈련 및 평가에 사용할 모든 하이퍼파라미터를 포함는 TrainingArguments 클래스를 정의하는 것입니다. 제공해야 하는 유일한 인수는 학습된 모델이 저장될 디렉터리와 그 과정에서 체크포인트입니다. 나머지 모든 사항에 대해서는 기본값을 그대로 두면 기본 미세 조정에 매우 적합합니다.

 

from transformers import TrainingArguments

training_args = TrainingArguments("test-trainer")

 

이 코드는 Hugging Face Transformers 라이브러리를 사용하여 모델 훈련에 필요한 훈련 인자(Training Arguments)를 설정하는 예제입니다. 코드를 단계별로 설명하겠습니다.

 

해석:

  1. TrainingArguments: Hugging Face Transformers 라이브러리에서 제공하는 모델 훈련을 위한 인자를 설정하는 클래스입니다.
  2. TrainingArguments("test-trainer"): 훈련 인자 객체를 초기화합니다. 여기서 "test-trainer"는 훈련의 이름(디렉토리 이름)을 나타냅니다.

이렇게 초기화된 training_args 객체에는 모델 훈련에 필요한 다양한 설정이 포함되어 있습니다. 훈련 스크립트에서 이 인자들을 참조하여 모델 훈련을 조절할 수 있습니다. 이 예제에서는 가장 기본적인 훈련 인자만 설정되었습니다. 나중에 필요에 따라 추가적인 설정을 적용할 수 있습니다.

 

CoLab에서는 아래와 같은 에러가 남

 

 

pip install transformers[torch] 를 한 후 CoLab을 Restart 한 후 다시 실행하면 됨
 

 

 

💡 If you want to automatically upload your model to the Hub during training, pass along push_to_hub=True in the TrainingArguments. We will learn more about this in Chapter 4

 

💡 훈련 중에 모델을 허브에 자동으로 업로드하려면 TrainingArguments에 push_to_hub=True를 전달하세요. 이에 대한 자세한 내용은 4장에서 알아보겠습니다.

 

The second step is to define our model. As in the previous chapter, we will use the AutoModelForSequenceClassification class, with two labels:

 

두 번째 단계는 모델을 정의하는 것입니다. 이전 장에서와 마찬가지로 두 개의 레이블이 있는 AutoModelForSequenceClassification 클래스를 사용합니다.

 

from transformers import AutoModelForSequenceClassification

model = AutoModelForSequenceClassification.from_pretrained(checkpoint, num_labels=2)

 

이 코드는 Hugging Face Transformers 라이브러리를 사용하여 사전 훈련된 모델을 불러오거나 새로운 모델을 초기화하는 예제입니다. 코드를 단계별로 설명하겠습니다.

 

해석:

  1. AutoModelForSequenceClassification: Hugging Face Transformers 라이브러리에서 제공하는 시퀀스 분류(sequence classification) 모델을 초기화하는 클래스입니다.
  2. from_pretrained(checkpoint, num_labels=2): from_pretrained 메서드를 사용하여 사전 훈련된 모델을 불러오거나 새로운 모델을 초기화합니다. checkpoint는 모델의 체크포인트를 지정하고, num_labels=2는 모델의 출력 클래스의 개수를 나타냅니다. 이 경우에는 이진 분류를 수행하는 모델로서 출력 클래스가 2개인 경우입니다.

이 코드를 실행하면 model 변수에는 초기화된 모델이 저장되어 있습니다. 이 모델은 이진 분류를 수행할 수 있으며, 사전 훈련된 모델을 사용하여 특정 작업에 미세 조정(fine-tuning)을 할 수 있습니다.

 

 

You will notice that unlike in Chapter 2, you get a warning after instantiating this pretrained model. This is because BERT has not been pretrained on classifying pairs of sentences, so the head of the pretrained model has been discarded and a new head suitable for sequence classification has been added instead. The warnings indicate that some weights were not used (the ones corresponding to the dropped pretraining head) and that some others were randomly initialized (the ones for the new head). It concludes by encouraging you to train the model, which is exactly what we are going to do now.

 

2장과 달리 사전 훈련된 모델을 인스턴스화한 후 경고가 표시된다는 점을 알 수 있습니다. 이는 BERT가 문장 쌍을 분류하는 데 사전 학습되지 않았기 때문에 사전 학습된 모델의 헤드를 삭제하고 대신 시퀀스 분류에 적합한 새로운 헤드를 추가했기 때문입니다. 경고는 일부 가중치(삭제된 사전 훈련 헤드에 해당하는 가중치)가 사용되지 않았으며 일부 가중치(새 헤드에 대한 가중치)가 무작위로 초기화되었음을 나타냅니다. 우리가 지금 하려고 하는 것이 바로 모델 훈련을 권장하는 것으로 마무리됩니다.

 

Once we have our model, we can define a Trainer by passing it all the objects constructed up to now — the model, the training_args, the training and validation datasets, our data_collator, and our tokenizer:

 

모델이 있으면 지금까지 구성한 모든 개체(모델, training_args, 훈련 및 검증 데이터 세트, data_collator 및 토크나이저)를 전달하여 Trainer를 정의할 수 있습니다.

 

from transformers import Trainer

trainer = Trainer(
    model,
    training_args,
    train_dataset=tokenized_datasets["train"],
    eval_dataset=tokenized_datasets["validation"],
    data_collator=data_collator,
    tokenizer=tokenizer,
)

 

이 코드는 Hugging Face Transformers 라이브러리를 사용하여 모델을 훈련하기 위한 Trainer를 초기화하는 예제입니다. 코드를 단계별로 설명하겠습니다.

 

해석:

  1. Trainer: Hugging Face Transformers 라이브러리에서 제공하는 훈련을 관리하는 클래스입니다.
  2. model: 훈련에 사용될 모델 객체입니다.
  3. training_args: 앞서 설정한 모델 훈련 인자(Training Arguments) 객체입니다.
  4. train_dataset=tokenized_datasets["train"]: 훈련에 사용될 데이터셋을 지정합니다. 여기서는 토큰화된 훈련 데이터셋을 사용합니다.
  5. eval_dataset=tokenized_datasets["validation"]: 모델의 성능을 평가할 때 사용될 검증 데이터셋을 지정합니다.
  6. data_collator=data_collator: 데이터 콜레이터 객체를 지정합니다. 이 객체는 배치를 처리하여 패딩을 추가하고 동일한 길이로 만들어주는 역할을 합니다.
  7. tokenizer=tokenizer: 토크나이저 객체를 지정합니다. 이 토크나이저는 모델 입력을 토큰화하는 데 사용됩니다.

이렇게 초기화된 Trainer 객체를 사용하면 지정된 모델과 데이터셋으로 모델을 훈련하고 평가할 수 있습니다. Trainer 객체를 사용하여 모델 훈련에 관련된 다양한 작업을 수행할 수 있습니다.

 

Note that when you pass the tokenizer as we did here, the default data_collator used by the Trainer will be a DataCollatorWithPadding as defined previously, so you can skip the line data_collator=data_collator in this call. It was still important to show you this part of the processing in section 2!

 

여기에서 했던 것처럼 토크나이저를 전달하면 Trainer에서 사용하는 기본 data_collator는 이전에 정의한 대로 DataCollatorWithPadding이 되므로 이 호출에서 data_collator=data_collator 줄을 건너뛸 수 있습니다. 섹션 2에서 처리 중 이 부분을 보여주는 것이 여전히 중요했습니다!

 

To fine-tune the model on our dataset, we just have to call the train() method of our Trainer:

 

데이터 세트의 모델을 미세 조정하려면 Trainer의 train() 메서드를 호출하기만 하면 됩니다.

 

trainer.train()

 

이 코드는 Hugging Face Transformers 라이브러리의 Trainer 객체를 사용하여 모델을 훈련하는 메서드를 호출하는 예제입니다.

 

해석:

  • trainer: 앞서 초기화한 Trainer 객체입니다.
  • train(): Trainer 객체의 train 메서드를 호출합니다. 이 메서드는 모델을 실제로 훈련시키는 역할을 합니다. 메서드가 실행되면 지정된 횟수만큼 모델이 훈련되며, 각 에폭(epoch)마다 훈련 손실(training loss) 및 검증 손실(validation loss) 등의 정보가 출력됩니다.

이 코드를 실행하면 모델이 지정된 횟수만큼 데이터셋에 대해 훈련되며, 훈련 손실 및 검증 손실이 출력됩니다. Trainer 객체는 앞서 설정한 훈련 인자(Training Arguments)에 따라 훈련이 진행되며, 필요한 경우 추가적인 설정을 적용할 수 있습니다.

 

CoLab에서 train() 을 하면 두시간이 걸린다.

 

 

This will start the fine-tuning (which should take a couple of minutes on a GPU) and report the training loss every 500 steps. It won’t, however, tell you how well (or badly) your model is performing. This is because:

 

그러면 미세 조정(GPU에서는 몇 분 정도 소요)이 시작되고 500단계마다 훈련 손실이 보고됩니다. 그러나 모델의 성능이 얼마나 좋은지(또는 나쁜지) 알려주지는 않습니다. 그 이유는 아래와 같습니다.

 

  1. We didn’t tell the Trainer to evaluate during training by setting evaluation_strategy to either "steps" (evaluate every eval_steps) or "epoch" (evaluate at the end of each epoch).

    training_strategy를 "steps"(모든 eval_steps 평가) 또는 "epoch"(각 epoch 끝에서 평가)로 설정하여 훈련 중에 평가하도록 트레이너에게 지시하지 않았습니다.

  2. We didn’t provide the Trainer with a compute_metrics() function to calculate a metric during said evaluation (otherwise the evaluation would just have printed the loss, which is not a very intuitive number).

    우리는 평가 중에 메트릭을 계산하기 위해 Compute_metrics() 함수를 Trainer에 제공하지 않았습니다(그렇지 않으면 평가에서 매우 직관적인 숫자가 아닌 손실만 인쇄했을 것입니다).


Evaluation

 

Let’s see how we can build a useful compute_metrics() function and use it the next time we train. The function must take an EvalPrediction object (which is a named tuple with a predictions field and a label_ids field) and will return a dictionary mapping strings to floats (the strings being the names of the metrics returned, and the floats their values). To get some predictions from our model, we can use the Trainer.predict() command:

 

유용한 Compute_metrics() 함수를 어떻게 구축하고 다음 훈련에 사용할 수 있는지 살펴보겠습니다. 함수는 EvalPrediction 객체(예측 필드와 label_ids 필드가 있는 명명된 튜플)를 가져와야 하며 문자열을 부동 소수점(문자열은 반환된 측정항목의 이름이고 부동 소수점 값)에 매핑하는 사전을 반환합니다. 모델에서 몇 가지 예측을 얻으려면 Trainer.predict() 명령을 사용할 수 있습니다.

 

predictions = trainer.predict(tokenized_datasets["validation"])
print(predictions.predictions.shape, predictions.label_ids.shape)
(408, 2) (408,)

 

이 코드는 Hugging Face Transformers 라이브러리의 Trainer 객체를 사용하여 검증 데이터셋에 대한 예측을 수행하고, 그 결과를 출력하는 예제입니다.

 

해석:

  • trainer: 앞서 초기화한 Trainer 객체입니다.
  • predict(tokenized_datasets["validation"]): Trainer 객체의 predict 메서드를 호출하여 검증 데이터셋에 대한 예측을 수행합니다. tokenized_datasets["validation"]은 검증 데이터셋의 토큰화된 버전을 나타냅니다.
  • predictions.predictions.shape: 예측된 결과의 모양(shape)을 나타냅니다. 예측된 결과는 모델의 출력으로, 각 클래스에 대한 확률 값이 포함된 텐서입니다.
  • predictions.label_ids.shape: 실제 레이블(ground truth)의 모양(shape)을 나타냅니다. 이는 검증 데이터셋의 실제 클래스 레이블을 나타내는 텐서입니다.

결과로 출력되는 predictions.predictions.shape와 predictions.label_ids.shape은 각각 예측된 결과의 모양과 실제 레이블의 모양을 나타내므로, 모델의 성능 평가 및 분석에 활용할 수 있습니다. 이를 통해 모델이 얼마나 잘 예측했는지를 확인할 수 있습니다.

 

 

 

The output of the predict() method is another named tuple with three fields: predictions, label_ids, and metrics. The metrics field will just contain the loss on the dataset passed, as well as some time metrics (how long it took to predict, in total and on average). Once we complete our compute_metrics() function and pass it to the Trainer, that field will also contain the metrics returned by compute_metrics().

 

predict () 메서드의 출력은 predict , label_ids 및 메트릭이라는 세 가지 필드가 있는 또 다른 명명된 튜플입니다. 측정항목 필드에는 전달된 데이터 세트의 손실과 일부 시간 측정항목(전체 및 평균으로 예측하는 데 걸린 시간)만 포함됩니다. Compute_metrics() 함수를 완성하고 이를 Trainer에 전달하면 해당 필드에는 Compute_metrics()에서 반환된 측정항목도 포함됩니다.

 

As you can see, predictions is a two-dimensional array with shape 408 x 2 (408 being the number of elements in the dataset we used). Those are the logits for each element of the dataset we passed to predict() (as you saw in the previous chapter, all Transformer models return logits). To transform them into predictions that we can compare to our labels, we need to take the index with the maximum value on the second axis:

 

보시다시피 예측은 408 x 2 모양의 2차원 배열입니다(408은 우리가 사용한 데이터세트의 요소 수입니다). 이는 우리가 predict  ()에 전달한 데이터 세트의 각 요소에 대한 로짓입니다(이전 장에서 보았듯이 모든 Transformer 모델은 로짓을 반환합니다). 이를 레이블과 비교할 수 있는 predict  으로 변환하려면 두 번째 축에서 최대값을 갖는 인덱스를 가져와야 합니다.

 

import numpy as np

preds = np.argmax(predictions.predictions, axis=-1)

 

이 코드는 NumPy 라이브러리를 사용하여 모델의 예측 결과에서 각 샘플에 대한 최대값을 찾아 클래스를 선택하는 예제입니다.

 

해석:

  • predictions.predictions: 모델의 예측 결과로, 각 클래스에 대한 확률 값이 담긴 텐서입니다.
  • np.argmax(predictions.predictions, axis=-1): NumPy의 argmax 함수를 사용하여 각 샘플에 대해 가장 높은 확률 값을 가진 클래스의 인덱스를 찾습니다. axis=-1는 가장 안쪽(마지막) 차원을 기준으로 최댓값을 찾도록 지정합니다.

결과로 얻어지는 preds는 각 샘플에 대해 모델이 예측한 클래스의 인덱스를 담은 배열이 됩니다. 이를 통해 각 샘플에 대한 최종 예측 클래스를 확인할 수 있습니다. 예를 들어, 이 배열의 첫 번째 원소는 첫 번째 샘플의 예측 클래스를 나타냅니다.

 

 

We can now compare those preds to the labels. To build our compute_metric() function, we will rely on the metrics from the 🤗 Evaluate library. We can load the metrics associated with the MRPC dataset as easily as we loaded the dataset, this time with the evaluate.load() function. The object returned has a compute() method we can use to do the metric calculation:

 

이제 해당 pred를 레이블과 비교할 수 있습니다. Compute_metric() 함수를 빌드하기 위해 🤗 Evaluate 라이브러리의 메트릭을 사용합니다. 이번에는 estimate.load() 함수를 사용하여 데이터세트를 로드한 것처럼 쉽게 MRPC 데이터세트와 관련된 측정항목을 로드할 수 있습니다. 반환된 객체에는 측정항목 계산을 수행하는 데 사용할 수 있는 Compute() 메서드가 있습니다.

 

import evaluate

metric = evaluate.load("glue", "mrpc")
metric.compute(predictions=preds, references=predictions.label_ids)

 

{'accuracy': 0.8578431372549019, 'f1': 0.8996539792387542}

 

이 코드는 Hugging Face의 evaluate 모듈을 사용하여 모델의 성능 지표를 계산하는 예제입니다. 코드를 단계별로 설명하겠습니다.

 

해석:

  1. import evaluate: Hugging Face에서 제공하는 evaluate 모듈을 가져옵니다.
  2. evaluate.load("glue", "mrpc"): "glue" 데이터셋의 "mrpc" 태스크에 해당하는 성능 지표 메트릭을 로드합니다. 이 메트릭은 해당 태스크에 대한 평가 지표를 계산하는 데 사용됩니다.
  3. metric.compute(predictions=preds, references=predictions.label_ids): compute 메서드를 사용하여 모델의 예측값 (preds)과 실제 레이블 (predictions.label_ids)을 입력으로 주어 성능 지표를 계산합니다. 이 메서드는 정확도(accuracy) 및 기타 태스크별 지표를 반환할 수 있습니다.

결과로 얻어지는 값은 해당 데이터셋 및 태스크에 대한 모델의 성능을 나타내며, 필요에 따라 이를 기반으로 모델을 평가하고 비교할 수 있습니다.

 
 
 

The exact results you get may vary, as the random initialization of the model head might change the metrics it achieved. Here, we can see our model has an accuracy of 85.78% on the validation set and an F1 score of 89.97. Those are the two metrics used to evaluate results on the MRPC dataset for the GLUE benchmark. The table in the BERT paper reported an F1 score of 88.9 for the base model. That was the uncased model while we are currently using the cased model, which explains the better result.

 

모델 헤드의 무작위 초기화로 인해 얻은 측정항목이 변경될 수 있으므로 얻을 수 있는 정확한 결과는 다를 수 있습니다. 여기서 우리 모델의 검증 세트 정확도는 85.78%이고 F1 점수는 89.97임을 알 수 있습니다. 이는 GLUE 벤치마크에 대한 MRPC 데이터 세트의 결과를 평가하는 데 사용되는 두 가지 측정항목입니다. BERT 논문의 표는 기본 모델의 F1 점수가 88.9라고 보고했습니다. 우리가 현재 케이스를 씌운 모델을 사용하고 있는 동안 그것은 케이스가 없는 모델이었습니다. 이것이 더 나은 결과를 설명합니다.

 

Wrapping everything together, we get our compute_metrics() function:

 
모든 것을 하나로 묶으면 Compute_metrics() 함수를 얻게 됩니다.
 
 
def compute_metrics(eval_preds):
    metric = evaluate.load("glue", "mrpc")
    logits, labels = eval_preds
    predictions = np.argmax(logits, axis=-1)
    return metric.compute(predictions=predictions, references=labels)
 
이 코드는 모델의 평가를 위해 사용되는 사용자 정의 메트릭을 계산하는 함수를 정의한 예제입니다. 코드를 단계별로 설명하겠습니다.
 
 

해석:

  1. compute_metrics 함수 정의: 사용자가 정의한 평가 메트릭을 계산하는 함수입니다.
  2. metric = evaluate.load("glue", "mrpc"): "glue" 데이터셋의 "mrpc" 태스크에 해당하는 성능 지표 메트릭을 로드합니다.
  3. logits, labels = eval_preds: eval_preds는 평가 중에 생성된 모델의 예측값(logits)과 실제 레이블(labels)을 포함하는 튜플입니다.
  4. predictions = np.argmax(logits, axis=-1): 모델의 예측값인 logits에서 각 샘플에 대한 최대값을 가진 클래스의 인덱스를 찾아 predictions 배열에 저장합니다.
  5. return metric.compute(predictions=predictions, references=labels): 로드한 메트릭을 사용하여 예측값과 실제 레이블을 입력으로 주어 성능 지표를 계산하고 반환합니다.

이렇게 정의된 compute_metrics 함수는 모델을 평가할 때 사용되며, 평가 결과에 대한 성능 지표를 반환합니다. 사용자는 필요에 따라 이 함수를 수정하여 다양한 성능 지표를 계산할 수 있습니다.

 

And to see it used in action to report metrics at the end of each epoch, here is how we define a new Trainer with this compute_metrics() function:

 

그리고 각 에포크가 끝날 때 지표를 보고하기 위해 실제로 사용되는 것을 확인하기 위해 이 Compute_metrics() 함수를 사용하여 새 Trainer를 정의하는 방법은 다음과 같습니다.

 

training_args = TrainingArguments("test-trainer", evaluation_strategy="epoch")
model = AutoModelForSequenceClassification.from_pretrained(checkpoint, num_labels=2)

trainer = Trainer(
    model,
    training_args,
    train_dataset=tokenized_datasets["train"],
    eval_dataset=tokenized_datasets["validation"],
    data_collator=data_collator,
    tokenizer=tokenizer,
    compute_metrics=compute_metrics,
)

 

이 코드는 Hugging Face Transformers 라이브러리를 사용하여 모델 훈련을 설정하는 부분입니다. 코드를 단계별로 설명하겠습니다.

 

해석:

  1. TrainingArguments("test-trainer", evaluation_strategy="epoch"): 훈련 인자(Training Arguments) 객체를 초기화합니다. 여기서는 훈련의 이름(디렉토리 이름)을 "test-trainer"로 지정하고, evaluation_strategy="epoch"를 통해 검증을 에폭(epoch) 단위로 수행하도록 설정합니다.
  2. AutoModelForSequenceClassification.from_pretrained(checkpoint, num_labels=2): 사전 훈련된 모델을 불러오거나 새로운 모델을 초기화합니다. checkpoint는 모델의 체크포인트를 지정하고, num_labels=2는 모델의 출력 클래스의 개수를 나타냅니다. 이 경우에는 이진 분류를 수행하는 모델로서 출력 클래스가 2개인 경우입니다.
  3. Trainer(...): 훈련을 관리하는 Trainer 객체를 초기화합니다.
    • model: 훈련에 사용될 모델 객체입니다.
    • training_args: 앞서 초기화한 훈련 인자 객체입니다.
    • train_dataset=tokenized_datasets["train"]: 훈련에 사용될 데이터셋을 지정합니다. 여기서는 토큰화된 훈련 데이터셋을 사용합니다.
    • eval_dataset=tokenized_datasets["validation"]: 모델의 성능을 평가할 때 사용될 검증 데이터셋을 지정합니다.
    • data_collator=data_collator: 데이터 콜레이터 객체를 지정합니다. 이 객체는 배치를 처리하여 패딩을 추가하고 동일한 길이로 만들어주는 역할을 합니다.
    • tokenizer=tokenizer: 토크나이저 객체를 지정합니다. 이 토크나이저는 모델 입력을 토큰화하는 데 사용됩니다.
    • compute_metrics=compute_metrics: 사용자 정의 메트릭을 계산하는 함수를 지정합니다.

이렇게 초기화된 Trainer 객체를 사용하면 모델을 지정된 횟수만큼 데이터셋에 대해 훈련하고, 검증을 에폭 단위로 수행할 수 있습니다. 필요에 따라 추가적인 설정을 적용할 수 있습니다.

 

Note that we create a new TrainingArguments with its evaluation_strategy set to "epoch" and a new model — otherwise, we would just be continuing the training of the model we have already trained. To launch a new training run, we execute:

 

Evaluation_strategy가 "epoch"로 설정된 새로운 TrainingArguments와 새 모델을 생성합니다. 그렇지 않으면 이미 훈련한 모델의 훈련을 계속할 것입니다. 새로운 훈련 실행을 시작하기 위해 다음을 실행합니다.

 

trainer.train()

 

 

This time, it will report the validation loss and metrics at the end of each epoch on top of the training loss. Again, the exact accuracy/F1 score you reach might be a bit different from what we found, because of the random head initialization of the model, but it should be in the same ballpark.

 

이번에는 훈련 손실 외에 각 에포크가 끝날 때마다 검증 손실과 측정항목을 보고합니다. 다시 말하지만, 도달한 정확한 정확도/F1 점수는 모델의 무작위 헤드 초기화로 인해 우리가 찾은 것과 약간 다를 수 있지만 동일한 기준점에 있어야 합니다.

 

The Trainer will work out of the box on multiple GPUs or TPUs and provides lots of options, like mixed-precision training (use fp16 = True in your training arguments). We will go over everything it supports in Chapter 10.

 

Trainer는 여러 GPU 또는 TPU에서 즉시 작동하며 혼합 정밀도 교육과 같은 다양한 옵션을 제공합니다(교육 인수에서 fp16 = True 사용). 10장에서 지원되는 모든 내용을 살펴보겠습니다.

 

This concludes the introduction to fine-tuning using the Trainer API. An example of doing this for most common NLP tasks will be given in Chapter 7, but for now let’s look at how to do the same thing in pure PyTorch.

 

이것으로 Trainer API를 사용한 미세 조정에 대한 소개를 마칩니다. 가장 일반적인 NLP 작업에 대해 이 작업을 수행하는 예는 7장에서 제공되지만 지금은 순수한 PyTorch에서 동일한 작업을 수행하는 방법을 살펴보겠습니다.

 

✏️ Try it out! Fine-tune a model on the GLUE SST-2 dataset, using the data processing you did in section 2.

 

✏️ 한번 사용해 보세요! 섹션 2에서 수행한 데이터 처리를 사용하여 GLUE SST-2 데이터 세트에서 모델을 미세 조정합니다.

 

Summary

 

지난 단원에서는 데이터를 로드하고 미세조정 하기 위해 텍스트 데이터를 토큰화하고 정수화 하고 길이 등을 맞춰 training을 준비 했다면 이번 단원에서는 그 준비된 데이터로 실제 training을 진행하는 과정을 설명 함.

 

Training을 하기 위해서는 Huggingface의 Trainer class를 사용한다.

처음으로 TrainingArguments를 사용해 Arguments를 세팅하고 Trainer를 사용해 지금까지 준비한 모든 것을 Model에 전달하기 위한 정의를 마친다.

그 다음 train() 메소드를 실행하면 실제로 training이 이루어 진다.

training이 끝나면 validation 데이터로 predict을 한다. predict()

그리고 이 predict 한 내용을 evaluate 한다.

 

이것이 전체 training 과정 임.

 

참고로 training() 은 시간이 오래 걸리는데 이 때 더 자세한 정보가 나오도록 하기 위해 compute_metrics() 함수를 만들어 Trainer() 에 추가 했음. (compute() 메소드를 사용해서 추가 정보가 나오도록 했음)

 

def compute_metrics(eval_preds):
    metric = evaluate.load("glue", "mrpc")
    logits, labels = eval_preds
    predictions = np.argmax(logits, axis=-1)
    return metric.compute(predictions=predictions, references=labels)
training_args = TrainingArguments("test-trainer", evaluation_strategy="epoch")
model = AutoModelForSequenceClassification.from_pretrained(checkpoint, num_labels=2)

trainer = Trainer(
    model,
    training_args,
    train_dataset=tokenized_datasets["train"],
    eval_dataset=tokenized_datasets["validation"],
    data_collator=data_collator,
    tokenizer=tokenizer,
    compute_metrics=compute_metrics,
)

 

 

 

 

반응형


반응형

https://huggingface.co/learn/nlp-course/chapter3/2?fw=pt

 

Processing the data - Hugging Face NLP Course

Continuing with the example from the previous chapter, here is how we would train a sequence classifier on one batch in PyTorch: Of course, just training the model on two sentences is not going to yield very good results. To get better results, you will ne

huggingface.co

 

Processing the data

 

Continuing with the example from the previous chapter, here is how we would train a sequence classifier on one batch in PyTorch:

 

이전 장의 예를 계속해서 PyTorch의 한 배치에 대해 시퀀스 분류기를 훈련하는 방법은 다음과 같습니다.

 

import torch
from transformers import AdamW, AutoTokenizer, AutoModelForSequenceClassification

# Same as before
checkpoint = "bert-base-uncased"
tokenizer = AutoTokenizer.from_pretrained(checkpoint)
model = AutoModelForSequenceClassification.from_pretrained(checkpoint)
sequences = [
    "I've been waiting for a HuggingFace course my whole life.",
    "This course is amazing!",
]
batch = tokenizer(sequences, padding=True, truncation=True, return_tensors="pt")

# This is new
batch["labels"] = torch.tensor([1, 1])

optimizer = AdamW(model.parameters())
loss = model(**batch).loss
loss.backward()
optimizer.step()

 

이 코드는 Hugging Face Transformers 라이브러리를 사용하여 감성 분류 모델을 훈련하는 예제입니다. 코드를 단계별로 설명하겠습니다.

 

해석:

  1. 모델 및 토크나이저 초기화: BERT(Bidirectional Encoder Representations from Transformers) 모델과 토크나이저를 불러오고, 훈련에 사용할 텍스트 시퀀스를 정의합니다.
  2. 입력 배치 생성: 토크나이저를 사용하여 텍스트 시퀀스를 토큰화하고, 패딩 및 자르기를 수행하여 모델에 입력으로 전달할 수 있는 형태의 배치를 생성합니다.
  3. 라벨 추가: 훈련 데이터의 감성 분류 라벨을 나타내는 "labels" 키를 추가합니다. 이 예제에서는 각 시퀀스에 대해 1로 라벨이 지정되어 있다고 가정합니다.
  4. 옵티마이저 초기화: AdamW 옵티마이저를 초기화합니다. 이는 모델의 가중치를 업데이트할 때 사용됩니다.
  5. 손실 계산 및 역전파: 모델에 입력을 전달하여 손실을 계산하고, 역전파를 수행하여 그래디언트를 계산합니다.
  6. 모델 업데이트: 옵티마이저를 사용하여 모델의 가중치를 업데이트합니다. 이는 모델의 훈련 과정에서 경사 하강법을 이용하여 가중치를 조절하는 부분입니다.

이 코드는 BERT 모델을 사용하여 감성 분류 모델을 훈련하는 기본적인 예제를 보여줍니다.

 

 

 

Of course, just training the model on two sentences is not going to yield very good results. To get better results, you will need to prepare a bigger dataset.

 

물론 두 문장으로 모델을 훈련시키는 것만으로는 좋은 결과를 얻을 수 없습니다. 더 나은 결과를 얻으려면 더 큰 데이터 세트를 준비해야 합니다.

 

In this section we will use as an example the MRPC (Microsoft Research Paraphrase Corpus) dataset, introduced in a paper by William B. Dolan and Chris Brockett. The dataset consists of 5,801 pairs of sentences, with a label indicating if they are paraphrases or not (i.e., if both sentences mean the same thing). We’ve selected it for this chapter because it’s a small dataset, so it’s easy to experiment with training on it.

 

이 섹션에서는 William B. Dolan과 Chris Brockett의 논문에서 소개된 MRPC(Microsoft Research Paraphrase Corpus) 데이터 세트를 예로 사용합니다. 데이터세트는 5,801개의 문장 쌍으로 구성되어 있으며, 해당 문장이 의역인지 아닌지(즉, 두 문장이 모두 같은 것을 의미하는지)를 나타내는 레이블이 있습니다. 이 장에서는 데이터세트가 작기 때문에 이를 선택했습니다. 따라서 훈련을 통해 실험하기가 쉽습니다.

 

Loading a dataset from the Hub

 

https://youtu.be/_BZearw7f0w?si=DrJDFkTtQwNT0L5X

 

 

The Hub doesn’t just contain models; it also has multiple datasets in lots of different languages. You can browse the datasets here, and we recommend you try to load and process a new dataset once you have gone through this section (see the general documentation here). But for now, let’s focus on the MRPC dataset! This is one of the 10 datasets composing the GLUE benchmark, which is an academic benchmark that is used to measure the performance of ML models across 10 different text classification tasks.

 

허브에는 모델만 포함되는 것이 아닙니다. 또한 다양한 언어로 된 여러 데이터 세트가 있습니다. 여기에서 데이터세트를 찾아볼 수 있으며, 이 섹션을 완료한 후 새 데이터세트를 로드하고 처리해 보는 것이 좋습니다(여기에서 일반 문서 참조). 하지만 지금은 MRPC 데이터 세트에 집중하겠습니다! 이는 10개의 다양한 텍스트 분류 작업에 걸쳐 ML 모델의 성능을 측정하는 데 사용되는 학문적 벤치마크인 GLUE 벤치마크를 구성하는 10개의 데이터세트 중 하나입니다.

 

The 🤗 Datasets library provides a very simple command to download and cache a dataset on the Hub. We can download the MRPC dataset like this:

 

🤗 데이터 세트 라이브러리는 허브에서 데이터 세트를 다운로드하고 캐시하는 매우 간단한 명령을 제공합니다. 다음과 같이 MRPC 데이터세트를 다운로드할 수 있습니다.

 

from datasets import load_dataset

raw_datasets = load_dataset("glue", "mrpc")
raw_datasets

 

DatasetDict({
    train: Dataset({
        features: ['sentence1', 'sentence2', 'label', 'idx'],
        num_rows: 3668
    })
    validation: Dataset({
        features: ['sentence1', 'sentence2', 'label', 'idx'],
        num_rows: 408
    })
    test: Dataset({
        features: ['sentence1', 'sentence2', 'label', 'idx'],
        num_rows: 1725
    })
})

 

이 코드는 Hugging Face의 datasets 라이브러리를 사용하여 MRPC(Microsoft Research Paraphrase Corpus) 데이터셋을 로드하는 예제입니다. 코드를 단계별로 설명하겠습니다.

 

해석:

  1. load_dataset("glue", "mrpc"): Hugging Face의 datasets 라이브러리를 사용하여 GLUE(General Language Understanding Evaluation) 벤치마크의 MRPC 부분을 로드합니다. 이 부분은 두 문장이 서로 의미론적으로 동일한지 여부를 나타내는 이진 분류 데이터셋입니다.
  2. raw_datasets: 로드된 데이터셋 객체를 변수에 저장합니다. 이 데이터셋 객체에는 훈련(train), 검증(validation), 테스트(test) 등의 세트로 구분된 원시(raw) 데이터가 포함되어 있습니다.

이 코드를 실행하면 raw_datasets에 MRPC 데이터셋이 로드되어 있고, 해당 데이터셋의 구조와 예시를 확인할 수 있습니다. datasets 라이브러리는 데이터셋을 효율적으로 다루기 위한 다양한 기능을 제공하며, 이를 사용하여 데이터를 로드하고 전처리하는 과정을 단순화할 수 있습니다.

 

 

 

As you can see, we get a DatasetDict object which contains the training set, the validation set, and the test set. Each of those contains several columns (sentence1, sentence2, label, and idx) and a variable number of rows, which are the number of elements in each set (so, there are 3,668 pairs of sentences in the training set, 408 in the validation set, and 1,725 in the test set).

 

보시다시피 훈련 세트, 검증 세트 및 테스트 세트가 포함된 DatasetDict 객체를 얻습니다. 각 항목에는 여러 열(sentence1, 문장2, label 및 idx)과 각 세트의 요소 수인 가변 개수의 행이 포함되어 있습니다(따라서 훈련 세트에는 3,668개의 문장 쌍이 있고 검증 세트에서는 408, 테스트 세트에서는 1,725이 있습니다.).

 

This command downloads and caches the dataset, by default in ~/.cache/huggingface/datasets. Recall from Chapter 2 that you can customize your cache folder by setting the HF_HOME environment variable.

 

이 명령은 기본적으로 ~/.cache/huggingface/datasets에 데이터 세트를 다운로드하고 캐시합니다. HF_HOME 환경 변수를 설정하여 캐시 폴더를 사용자 정의할 수 있다는 것을 2장에서 상기하십시오.

 

We can access each pair of sentences in our raw_datasets object by indexing, like with a dictionary:

 

사전처럼 색인을 생성하여 raw_datasets 객체의 각 문장 쌍에 액세스할 수 있습니다.

 

raw_train_dataset = raw_datasets["train"]
raw_train_dataset[0]

 

{'idx': 0,
 'label': 1,
 'sentence1': 'Amrozi accused his brother , whom he called " the witness " , of deliberately distorting his evidence .',
 'sentence2': 'Referring to him as only " the witness " , Amrozi accused his brother of deliberately distorting his evidence .'}

 

이 코드는 MRPC(Microsoft Research Paraphrase Corpus) 데이터셋에서 훈련 세트(train set)를 추출하고, 해당 훈련 세트의 첫 번째 예시를 확인하는 예제입니다. 코드를 단계별로 설명하겠습니다.

 

해석:

  1. raw_datasets["train"]: MRPC 데이터셋에서 "train" 부분을 추출합니다. 이는 훈련 세트를 나타냅니다.
  2. raw_train_dataset: 추출된 훈련 세트를 변수에 저장합니다. 이 변수에는 훈련 세트의 원시(raw) 데이터가 들어 있습니다.
  3. raw_train_dataset[0]: 훈련 세트의 첫 번째 예시를 가져옵니다. 이는 두 문장과 해당 문장이 서로 의미론적으로 동일한지 여부를 나타내는 이진 레이블로 구성된 데이터 포인트입니다.

따라서 코드를 실행하면 MRPC 데이터셋의 훈련 세트에서 첫 번째 데이터 포인트를 확인할 수 있습니다. 이 데이터셋은 주로 문장의 의미론적 동일성을 평가하는 이진 분류 작업을 위해 사용됩니다.

 

 

We can see the labels are already integers, so we won’t have to do any preprocessing there. To know which integer corresponds to which label, we can inspect the features of our raw_train_dataset. This will tell us the type of each column:

 

레이블이 이미 정수라는 것을 알 수 있으므로 거기서 전처리를 수행할 필요가 없습니다. 어떤 정수가 어떤 라벨에 해당하는지 알기 위해 raw_train_dataset의 기능을 검사할 수 있습니다. 이는 각 열의 유형을 알려줍니다.

 

raw_train_dataset.features
{'sentence1': Value(dtype='string', id=None),
 'sentence2': Value(dtype='string', id=None),
 'label': ClassLabel(num_classes=2, names=['not_equivalent', 'equivalent'], names_file=None, id=None),
 'idx': Value(dtype='int32', id=None)}

 

raw_train_dataset.features는 MRPC(Microsoft Research Paraphrase Corpus) 데이터셋의 훈련 세트에 대한 특성(features)을 나타내는 부분입니다. 이것은 데이터셋의 구조와 각 데이터 포인트에 어떤 정보가 포함되어 있는지에 대한 정보를 제공합니다.

 

해석:

  • raw_train_dataset: MRPC 데이터셋에서 추출한 훈련 세트를 나타냅니다.
  • .features: 데이터셋의 각 데이터 포인트의 특성을 나타내는 속성입니다. 이는 데이터셋이 어떤 속성들을 가지고 있는지에 대한 정보를 담고 있습니다.

결과로 출력되는 정보는 데이터셋의 특성을 설명하는데 사용되는 데이터셋의 메타 정보입니다. 이 정보에는 데이터의 타입, 크기, 필드 등이 포함될 수 있습니다. 이를 통해 데이터셋의 구조를 이해하고, 필요한 정보에 쉽게 접근할 수 있게 됩니다.

 

 

Behind the scenes, label is of type ClassLabel, and the mapping of integers to label name is stored in the names folder. 0 corresponds to not_equivalent, and 1 corresponds to equivalent.

 

뒤에서 레이블은 ClassLabel 유형이며 레이블 이름에 대한 정수 매핑은 이름 폴더에 저장됩니다. 0은 not_equival에 해당하고 1은 동등에 해당합니다.

 

✏️ Try it out! Look at element 15 of the training set and element 87 of the validation set. What are their labels?

 

✏️ 한번 사용해 보세요! 훈련 세트의 요소 15와 검증 세트의 요소 87을 살펴보세요. 그들의 라벨은 무엇입니까?

 

==> The label of element 15 is 0. which means not_equivalent

 

==> The label of the element 87 is 1. which means equivalent

 

 

Preprocessing a dataset

https://youtu.be/0u3ioSwev3s?si=rry0Ov_jZduQLOes

 

 

To preprocess the dataset, we need to convert the text to numbers the model can make sense of. As you saw in the previous chapter, this is done with a tokenizer. We can feed the tokenizer one sentence or a list of sentences, so we can directly tokenize all the first sentences and all the second sentences of each pair like this:

 

데이터세트를 전처리하려면 텍스트를 모델이 이해할 수 있는 숫자로 변환해야 합니다. 이전 장에서 본 것처럼 이는 토크나이저를 사용하여 수행됩니다. 토크나이저에 한 문장 또는 문장 목록을 제공할 수 있으므로 다음과 같이 각 쌍의 모든 첫 번째 문장과 모든 두 번째 문장을 직접 토큰화할 수 있습니다.

 

from transformers import AutoTokenizer

checkpoint = "bert-base-uncased"
tokenizer = AutoTokenizer.from_pretrained(checkpoint)
tokenized_sentences_1 = tokenizer(raw_datasets["train"]["sentence1"])
tokenized_sentences_2 = tokenizer(raw_datasets["train"]["sentence2"])

 

이 코드는 Hugging Face Transformers 라이브러리를 사용하여 BERT 모델의 토크나이저를 초기화하고, MRPC(Microsoft Research Paraphrase Corpus) 데이터셋의 훈련 세트에서 각 문장을 토큰화하는 예제입니다. 코드를 단계별로 설명하겠습니다.

 

해석:

  • AutoTokenizer.from_pretrained(checkpoint): BERT 모델의 체크포인트를 로드하여 해당 모델에 대한 토크나이저를 초기화합니다.
  • raw_datasets["train"]["sentence1"] 및 raw_datasets["train"]["sentence2"]: MRPC 데이터셋의 훈련 세트에서 각 데이터 포인트의 "sentence1" 및 "sentence2" 필드에서 문장 데이터를 추출합니다.
  • tokenizer(raw_datasets["train"]["sentence1"]) 및 tokenizer(raw_datasets["train"]["sentence2"]): 각 문장을 토큰화하여 모델에 입력으로 사용할 수 있는 형태로 만듭니다. 각 문장은 토큰 ID, 어텐션 마스크, 토큰 유형 ID 등으로 이루어진 토큰화된 입력으로 변환됩니다.

따라서 코드를 실행하면 BERT 모델의 토크나이저를 사용하여 MRPC 데이터셋의 훈련 세트의 문장들이 토큰화되어 tokenized_sentences_1 및 tokenized_sentences_2 변수에 저장됩니다. 이 토큰화된 입력은 이후 모델에 입력으로 전달되어 감성 분류나 문장 유사도 등의 작업을 수행하는 데 사용될 수 있습니다.

 

However, we can’t just pass two sequences to the model and get a prediction of whether the two sentences are paraphrases or not. We need to handle the two sequences as a pair, and apply the appropriate preprocessing. Fortunately, the tokenizer can also take a pair of sequences and prepare it the way our BERT model expects:

 

그러나 단순히 두 개의 시퀀스를 모델에 전달하고 두 문장이 paraphrases  인지 아닌지에 대한 예측을 얻을 수는 없습니다. 두 시퀀스를 한 쌍으로 처리하고 적절한 전처리를 적용해야 합니다. 다행스럽게도 토크나이저는 한 쌍의 시퀀스를 가져와 BERT 모델이 예상하는 방식으로 준비할 수도 있습니다.

 

inputs = tokenizer("This is the first sentence.", "This is the second one.")
inputs

 

{ 
  'input_ids': [101, 2023, 2003, 1996, 2034, 6251, 1012, 102, 2023, 2003, 1996, 2117, 2028, 1012, 102],
  'token_type_ids': [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1],
  'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
}

 

이 코드는 Hugging Face Transformers 라이브러리를 사용하여 텍스트를 토큰화하는 예제입니다. 두 개의 문장이 주어지고, 해당 문장들이 토큰화된 입력 형식으로 변환됩니다. 코드를 단계별로 설명하겠습니다.

 

해석:

  • tokenizer: BERT 모델이나 다른 특정 모델에 해당하는 토크나이저를 초기화합니다.
  • "This is the first sentence.", "This is the second one.": 두 개의 문장이 함수에 입력됩니다.
  • inputs: 두 문장이 토크나이저에 의해 처리되어 모델에 입력으로 전달할 수 있는 형태로 변환됩니다. 결과는 딕셔너리 형태로 반환되며, 토큰 ID, 어텐션 마스크, 토큰 유형 ID 등으로 이루어진 정보를 담고 있습니다.

실제로 코드를 실행하면 inputs 변수에는 토큰화된 입력이 저장되어 있습니다. 이 토큰화된 입력은 모델에 입력으로 전달되어 문장 간의 관계를 분류하거나 다른 NLP 작업을 수행하는 데 사용될 수 있습니다.

 

 

We discussed the input_ids and attention_mask keys in Chapter 2, but we put off talking about token_type_ids. In this example, this is what tells the model which part of the input is the first sentence and which is the second sentence.

 

2장에서 input_ids 및 attention_mask 키에 대해 논의했지만 token_type_ids에 대한 논의는 미루었습니다. 이 예에서는 입력의 어느 부분이 첫 번째 문장이고 어느 부분이 두 번째 문장인지 모델에 알려줍니다.

 

✏️ Try it out! Take element 15 of the training set and tokenize the two sentences separately and as a pair. What’s the difference between the two results?

 

✏️ 한번 사용해 보세요! 훈련 세트의 요소 15를 가져와 두 문장을 개별적으로 그리고 한 쌍으로 토큰화합니다. 두 결과의 차이점은 무엇입니까?

 

 

두 문장을 따로 토큰화 하면 아래와 같이 됨

 

{'input_ids': [101, 24049, 2001, 2087, 3728, 3026, 3580, 2343, 2005, 1996, 9722, 1004, 4132, 9340, 12439, 2964, 2449, 1012, 102], 'token_type_ids': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]}

{'input_ids': [101, 3026, 3580, 2343, 4388, 24049, 1010, 3839, 2132, 1997, 1996, 9722, 1998, 4132, 9340, 12439, 2964, 3131, 1010, 2097, 2599, 1996, 2047, 9178, 1012, 102], 'token_type_ids': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]}

 

그리고 한 쌍으로 토큰화 하면 이렇게 됨.

 

{'input_ids': [101, 24049, 2001, 2087, 3728, 3026, 3580, 2343, 2005, 1996, 9722, 1004, 4132, 9340, 12439, 2964, 2449, 1012, 102, 3026, 3580, 2343, 4388, 24049, 1010, 3839, 2132, 1997, 1996, 9722, 1998, 4132, 9340, 12439, 2964, 3131, 1010, 2097, 2599, 1996, 2047, 9178, 1012, 102], 'token_type_ids': [0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1], 'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]}

 

전자는 101 이 각 문장 시작할 때 오고 후자는 101이 한번만 있음. 그리고 token_type_ids 가 전자는 모두 0인데 비해 후자는 첫번째 문장은 0이고 두번째 문장은 1 임.

 

If we decode the IDs inside input_ids back to words:

 

input_ids 내부의 ID를 다시 단어로 디코딩하면 다음과 같습니다.

 

tokenizer.convert_ids_to_tokens(inputs["input_ids"])

 

이 코드는 Hugging Face Transformers 라이브러리를 사용하여 모델 입력으로 사용되는 토큰 ID를 해당하는 토큰으로 변환하는 예제입니다. 코드를 단계별로 설명하겠습니다.

 

해석:

  • tokenizer: 이전에 초기화한 BERT 모델이나 특정 모델에 해당하는 토크나이저를 사용합니다.
  • inputs["input_ids"]: 이전 코드에서 생성한 inputs 딕셔너리에서 "input_ids" 키를 사용하여 모델에 입력으로 전달된 토큰 ID를 가져옵니다.
  • tokenizer.convert_ids_to_tokens(...): 토크나이저의 convert_ids_to_tokens 메서드를 사용하여 토큰 ID를 실제 토큰으로 변환합니다.

실제로 코드를 실행하면 inputs["input_ids"]에 해당하는 토큰 ID들이 토크나이저에 의해 실제 토큰으로 변환되어 출력됩니다. 이는 모델의 입력이 텍스트로 어떻게 표현되었는지를 확인할 수 있는 유용한 작업입니다.

 

 

we will get: 아래와 같이 결과가 나옵니다.

 

['[CLS]', 'this', 'is', 'the', 'first', 'sentence', '.', '[SEP]', 'this', 'is', 'the', 'second', 'one', '.', '[SEP]']

 

 

 

element 15에 대해 작업했던 것들을 decode 하면 아래와 같습니다.

 

 

 

 

 

So we see the model expects the inputs to be of the form [CLS] sentence1 [SEP] sentence2 [SEP] when there are two sentences. Aligning this with the token_type_ids gives us:

 

따라서 모델은 두 개의 문장이 있는 경우 입력이 [CLS] 문장1 [SEP] 문장2 [SEP] 형식이 될 것으로 예상합니다. 이것을 token_type_ids와 일치시키면 다음이 제공됩니다.

 

['[CLS]', 'this', 'is', 'the', 'first', 'sentence', '.', '[SEP]', 'this', 'is', 'the', 'second', 'one', '.', '[SEP]']
[      0,      0,    0,     0,       0,          0,   0,       0,      1,    1,     1,        1,     1,   1,       1]

 

As you can see, the parts of the input corresponding to [CLS] sentence1 [SEP] all have a token type ID of 0, while the other parts, corresponding to sentence2 [SEP], all have a token type ID of 1.

 

보시다시피, [CLS] 문장1 [SEP]에 해당하는 입력 부분은 모두 토큰 유형 ID가 0이고 문장2 [SEP]에 해당하는 다른 부분은 모두 토큰 유형 ID가 1입니다.

 

Note that if you select a different checkpoint, you won’t necessarily have the token_type_ids in your tokenized inputs (for instance, they’re not returned if you use a DistilBERT model). They are only returned when the model will know what to do with them, because it has seen them during its pretraining.

 

다른 체크포인트를 선택하는 경우 토큰화된 입력에 token_type_ids가 반드시 있을 필요는 없습니다(예를 들어 DistilBERT 모델을 사용하는 경우 반환되지 않습니다). 모델이 사전 학습 중에 이를 확인했기 때문에 모델이 이를 어떻게 해야 할지 알 때만 반환됩니다.

 

Here, BERT is pretrained with token type IDs, and on top of the masked language modeling objective we talked about in Chapter 1, it has an additional objective called next sentence prediction. The goal with this task is to model the relationship between pairs of sentences.

 

여기서 BERT는 토큰 유형 ID로 사전 학습되었으며, 1장에서 설명한 마스크된 언어 모델링 목표 외에 다음 문장 예측이라는 추가 목표가 있습니다. 이 작업의 목표는 문장 쌍 간의 관계를 모델링하는 것입니다.

 

With next sentence prediction, the model is provided pairs of sentences (with randomly masked tokens) and asked to predict whether the second sentence follows the first. To make the task non-trivial, half of the time the sentences follow each other in the original document they were extracted from, and the other half of the time the two sentences come from two different documents.

 

다음 문장 예측을 통해 모델에는 문장 쌍(무작위로 마스킹된 토큰 포함)이 제공되고 두 번째 문장이 첫 번째 문장 다음에 오는지 여부를 예측하도록 요청됩니다. 작업을 간단하게 만들기 위해 절반의 시간 동안 문장은 추출된 원본 문서에서 서로 따르고 나머지 절반의 시간은 두 문장이 두 개의 다른 문서에서 나옵니다.

 

In general, you don’t need to worry about whether or not there are token_type_ids in your tokenized inputs: as long as you use the same checkpoint for the tokenizer and the model, everything will be fine as the tokenizer knows what to provide to its model.

 

일반적으로 토큰화된 입력에 token_type_ids가 있는지 여부에 대해 걱정할 필요가 없습니다. 토크나이저와 모델에 동일한 체크포인트를 사용하는 한, 토크나이저는 모델에 무엇을 제공할지 알고 있으므로 모든 것이 잘 될 것입니다.

 

Now that we have seen how our tokenizer can deal with one pair of sentences, we can use it to tokenize our whole dataset: like in the previous chapter, we can feed the tokenizer a list of pairs of sentences by giving it the list of first sentences, then the list of second sentences. This is also compatible with the padding and truncation options we saw in Chapter 2. So, one way to preprocess the training dataset is:

 

이제 토크나이저가 한 쌍의 문장을 처리하는 방법을 살펴보았으므로 이를 사용하여 전체 데이터세트를 토큰화할 수 있습니다. 이전 장에서와 마찬가지로 토크나이저에 첫 번째 문장 목록을 제공하여 문장 쌍 목록을 제공할 수 있습니다. 그런 다음 두 번째 문장의 목록입니다. 이는 2장에서 본 패딩 및 자르기 옵션과도 호환됩니다. 따라서 교육 데이터 세트를 전처리하는 한 가지 방법은 다음과 같습니다.

 

tokenized_dataset = tokenizer(
    raw_datasets["train"]["sentence1"],
    raw_datasets["train"]["sentence2"],
    padding=True,
    truncation=True,
)

 

이 코드는 Hugging Face Transformers 라이브러리를 사용하여 MRPC(Microsoft Research Paraphrase Corpus) 데이터셋의 훈련 세트의 문장들을 토크나이저를 이용하여 일괄적으로 토큰화하는 예제입니다. 코드를 단계별로 설명하겠습니다.

 

해석:

  • tokenizer: 이전에 초기화한 BERT 모델이나 특정 모델에 해당하는 토크나이저를 사용합니다.
  • raw_datasets["train"]["sentence1"] 및 raw_datasets["train"]["sentence2"]: MRPC 데이터셋의 훈련 세트에서 각 데이터 포인트의 "sentence1" 및 "sentence2" 필드에서 문장 데이터를 추출합니다.
  • tokenizer(...): 토크나이저를 사용하여 여러 문장을 일괄적으로 토큰화합니다. padding=True 및 truncation=True는 토큰화된 입력에 대해 패딩 및 자르기를 수행하도록 지시합니다.

결과로 생성된 tokenized_dataset에는 토큰화된 입력이 저장되어 있습니다. 이 토큰화된 데이터는 모델에 입력으로 전달되어 훈련이나 추론과 같은 NLP 작업에 사용될 수 있습니다. 일반적으로 토큰화된 데이터는 토큰 ID, 어텐션 마스크, 토큰 유형 ID 등의 정보를 담고 있습니다.

 

This works well, but it has the disadvantage of returning a dictionary (with our keys, input_ids, attention_mask, and token_type_ids, and values that are lists of lists). It will also only work if you have enough RAM to store your whole dataset during the tokenization (whereas the datasets from the 🤗 Datasets library are Apache Arrow files stored on the disk, so you only keep the samples you ask for loaded in memory).

 

이는 잘 작동하지만 사전(키, input_ids, attention_mask, token_type_ids 및 목록 목록인 값 포함)을 반환해야 한다는 단점이 있습니다. 또한 토큰화 중에 전체 데이터세트를 저장할 수 있을 만큼 충분한 RAM이 있는 경우에만 작동합니다(반면 🤗 데이터세트 라이브러리의 데이터세트는 디스크에 저장된 Apache Arrow 파일이므로 요청한 샘플만 메모리에 로드하도록 유지합니다).

 

To keep the data as a dataset, we will use the Dataset.map() method. This also allows us some extra flexibility, if we need more preprocessing done than just tokenization. The map() method works by applying a function on each element of the dataset, so let’s define a function that tokenizes our inputs:

 

데이터를 데이터세트로 유지하기 위해 Dataset.map() 메서드를 사용합니다. 이는 또한 토큰화보다 더 많은 전처리가 필요한 경우 추가적인 유연성을 제공합니다. map() 메소드는 데이터 세트의 각 요소에 함수를 적용하여 작동하므로 입력을 토큰화하는 함수를 정의해 보겠습니다.

 

def tokenize_function(example):
    return tokenizer(example["sentence1"], example["sentence2"], truncation=True)

 

이 코드는 Hugging Face Transformers 라이브러리를 사용하여 MRPC(Microsoft Research Paraphrase Corpus) 데이터셋의 각 예시에 대한 사용자 정의 토크나이즈 함수를 정의하는 예제입니다. 코드를 단계별로 설명하겠습니다.

 

해석:

  • tokenize_function: 사용자가 정의한 토크나이즈 함수입니다. 이 함수는 각 데이터 포인트에 대한 토큰화를 수행합니다.
  • example: 함수의 인자로 받는 입력 예시(데이터 포인트)입니다.
  • example["sentence1"], example["sentence2"]: 입력 예시에서 "sentence1" 및 "sentence2" 필드에서 각각의 문장 데이터를 추출합니다.
  • tokenizer(..., truncation=True): 앞서 초기화한 토크나이저를 사용하여 두 문장을 토큰화합니다. truncation=True는 토큰화된 입력에 대해 자르기(truncation)를 수행하도록 지시합니다.

이 함수를 이용하면 MRPC 데이터셋의 각 예시에 대해 사용자가 원하는 방식으로 토큰화를 수행할 수 있습니다. 이러한 사용자 정의 토크나이즈 함수는 데이터셋을 처리하거나 모델에 입력을 제공하는 등의 작업에서 유용하게 사용될 수 있습니다.

 

This function takes a dictionary (like the items of our dataset) and returns a new dictionary with the keys input_ids, attention_mask, and token_type_ids. Note that it also works if the example dictionary contains several samples (each key as a list of sentences) since the tokenizer works on lists of pairs of sentences, as seen before. This will allow us to use the option batched=True in our call to map(), which will greatly speed up the tokenization. The tokenizer is backed by a tokenizer written in Rust from the 🤗 Tokenizers library. This tokenizer can be very fast, but only if we give it lots of inputs at once.

 

이 함수는 사전(데이터세트의 항목과 같은)을 가져와 input_ids, attention_mask 및 token_type_ids 키가 있는 새 사전을 반환합니다. 이전에 본 것처럼 토크나이저는 문장 쌍 목록에서 작동하므로 예제 사전에 여러 샘플(각 키가 문장 목록)이 포함되어 있는 경우에도 작동합니다. 이렇게 하면 map() 호출에서 일괄=True 옵션을 사용할 수 있어 토큰화 속도가 크게 향상됩니다. 토크나이저는 🤗 Tokenizers 라이브러리에서 Rust로 작성된 토크나이저의 지원을 받습니다. 이 토크나이저는 매우 빠르지만 한 번에 많은 입력을 제공하는 경우에만 가능합니다.

 

Note that we’ve left the padding argument out in our tokenization function for now. This is because padding all the samples to the maximum length is not efficient: it’s better to pad the samples when we’re building a batch, as then we only need to pad to the maximum length in that batch, and not the maximum length in the entire dataset. This can save a lot of time and processing power when the inputs have very variable lengths!

 

지금은 토큰화 함수에 패딩 인수를 남겨 두었습니다. 이는 모든 샘플을 최대 길이까지 채우는 것이 효율적이지 않기 때문입니다. 배치를 작성할 때 샘플을 채우는 것이 더 낫습니다. 그러면 배치의 최대 길이가 아니라 해당 배치의 최대 길이까지만 채우면 됩니다. 전체 데이터 세트. 이는 입력의 길이가 매우 다양할 때 많은 시간과 처리 능력을 절약할 수 있습니다!

 

Here is how we apply the tokenization function on all our datasets at once. We’re using batched=True in our call to map so the function is applied to multiple elements of our dataset at once, and not on each element separately. This allows for faster preprocessing.

 

모든 데이터 세트에 토큰화 기능을 한 번에 적용하는 방법은 다음과 같습니다. 우리는 map 호출에서 일괄 처리=True를 사용하여 함수가 각 요소에 개별적으로 적용되는 것이 아니라 데이터세트의 여러 요소에 동시에 적용됩니다. 이를 통해 더 빠른 전처리가 가능합니다.

 

tokenized_datasets = raw_datasets.map(tokenize_function, batched=True)
tokenized_datasets

 

이 코드는 Hugging Face Transformers 라이브러리를 사용하여 MRPC(Microsoft Research Paraphrase Corpus) 데이터셋을 토큰화하는 작업을 수행합니다. map 함수를 사용하여 사용자가 정의한 tokenize_function 함수를 데이터셋의 각 예시에 적용하고, 결과로 토큰화된 데이터셋을 얻습니다. 코드를 단계별로 설명하겠습니다.

 

해석:

  • raw_datasets: 원시 MRPC 데이터셋 객체입니다.
  • map(tokenize_function, batched=True): map 함수를 사용하여 tokenize_function을 데이터셋의 각 예시에 적용합니다. batched=True는 배치(batch) 단위로 토큰화 함수를 적용하도록 지시합니다. 이렇게 함으로써 토큰화 함수가 더 효율적으로 동작하게 됩니다.
  • tokenized_datasets: 토큰화된 결과를 저장하는 변수입니다. 이 변수에는 토큰화된 입력, 토큰 ID, 어텐션 마스크 등의 정보가 포함되어 있습니다.

따라서 코드를 실행하면 tokenized_datasets 변수에는 토큰화된 MRPC 데이터셋이 저장되게 됩니다. 이제 이 토큰화된 데이터셋을 사용하여 모델 훈련이나 추론과 같은 NLP 작업을 수행할 수 있습니다.

 

The way the 🤗 Datasets library applies this processing is by adding new fields to the datasets, one for each key in the dictionary returned by the preprocessing function:

 

🤗 데이터 세트 라이브러리가 이 처리를 적용하는 방법은 전처리 함수에서 반환된 사전의 각 키에 대해 하나씩 데이터 세트에 새 필드를 추가하는 것입니다.

 

DatasetDict({
    train: Dataset({
        features: ['attention_mask', 'idx', 'input_ids', 'label', 'sentence1', 'sentence2', 'token_type_ids'],
        num_rows: 3668
    })
    validation: Dataset({
        features: ['attention_mask', 'idx', 'input_ids', 'label', 'sentence1', 'sentence2', 'token_type_ids'],
        num_rows: 408
    })
    test: Dataset({
        features: ['attention_mask', 'idx', 'input_ids', 'label', 'sentence1', 'sentence2', 'token_type_ids'],
        num_rows: 1725
    })
})

 

 

You can even use multiprocessing when applying your preprocessing function with map() by passing along a num_proc argument. We didn’t do this here because the 🤗 Tokenizers library already uses multiple threads to tokenize our samples faster, but if you are not using a fast tokenizer backed by this library, this could speed up your preprocessing.

 

num_proc 인수를 전달하여 map()으로 전처리 함수를 적용할 때 다중 처리를 사용할 수도 있습니다. 🤗 Tokenizers 라이브러리는 이미 여러 스레드를 사용하여 샘플을 더 빠르게 토큰화하기 때문에 여기서는 이 작업을 수행하지 않았지만, 이 라이브러리에서 지원하는 빠른 토크나이저를 사용하지 않는 경우 전처리 속도가 빨라질 수 있습니다.

 

Our tokenize_function returns a dictionary with the keys input_ids, attention_mask, and token_type_ids, so those three fields are added to all splits of our dataset. Note that we could also have changed existing fields if our preprocessing function returned a new value for an existing key in the dataset to which we applied map().

 

tokenize_function은 input_ids, attention_mask 및 token_type_ids 키가 포함된 사전을 반환하므로 해당 세 필드가 데이터 세트의 모든 분할에 추가됩니다. 전처리 함수가 map()을 적용한 데이터 세트의 기존 키에 대한 새 값을 반환한 경우 기존 필드를 변경할 수도 있습니다.

 

The last thing we will need to do is pad all the examples to the length of the longest element when we batch elements together — a technique we refer to as dynamic padding.

 

마지막으로 해야 할 일은 요소를 일괄 처리할 때 가장 긴 요소의 길이에 맞춰 모든 예제를 채우는 것입니다. 이 기술을 동적 패딩이라고 합니다.

 

Dynamic padding

https://youtu.be/7q5NyFT8REg?si=Yc_qyVujnfNI--vg

 

 

The function that is responsible for putting together samples inside a batch is called a collate function. It’s an argument you can pass when you build a DataLoader, the default being a function that will just convert your samples to PyTorch tensors and concatenate them (recursively if your elements are lists, tuples, or dictionaries). This won’t be possible in our case since the inputs we have won’t all be of the same size. We have deliberately postponed the padding, to only apply it as necessary on each batch and avoid having over-long inputs with a lot of padding. This will speed up training by quite a bit, but note that if you’re training on a TPU it can cause problems — TPUs prefer fixed shapes, even when that requires extra padding.

 

배치 내에서 샘플을 모으는 function collate function 이라고 합니다. 이는 DataLoader를 빌드할 때 전달할 수 있는 인수이며, 기본값은 샘플을 PyTorch 텐서로 변환하고 연결하는 함수입니다(요소가 목록, 튜플 또는 사전인 경우 반복적으로). 우리가 가지고 있는 입력의 크기가 모두 동일하지 않기 때문에 우리의 경우에는 이것이 불가능합니다. 우리는 의도적으로 패딩을 연기하여 각 배치에 필요한 경우에만 적용하고 많은 패딩으로 인해 지나치게 긴 입력이 발생하는 것을 방지했습니다. 이렇게 하면 훈련 속도가 상당히 빨라지지만 TPU에서 훈련하는 경우 문제가 발생할 수 있습니다. TPU는 추가 패딩이 필요한 경우에도 고정된 모양을 선호합니다.

 

To do this in practice, we have to define a collate function that will apply the correct amount of padding to the items of the dataset we want to batch together. Fortunately, the 🤗 Transformers library provides us with such a function via DataCollatorWithPadding. It takes a tokenizer when you instantiate it (to know which padding token to use, and whether the model expects padding to be on the left or on the right of the inputs) and will do everything you need:

 

실제로 이를 수행하려면 일괄 처리하려는 데이터 세트 항목에 올바른 양의 패딩을 적용하는 대조 기능을 정의해야 합니다. 다행히 🤗 Transformers 라이브러리는 DataCollatorWithPadding을 통해 이러한 기능을 제공합니다. 인스턴스화할 때(사용할 패딩 토큰, 모델이 입력의 왼쪽 또는 오른쪽에 패딩을 예상하는지 여부를 파악하기 위해) 토크나이저를 사용하고 필요한 모든 작업을 수행합니다.

 

from transformers import DataCollatorWithPadding

data_collator = DataCollatorWithPadding(tokenizer=tokenizer)

 

이 코드는 Hugging Face Transformers 라이브러리를 사용하여 훈련 데이터 배치를 처리하기 위한 데이터 콜레이터(Data Collator)를 초기화하는 예제입니다. 코드를 단계별로 설명하겠습니다.

 

해석:

  • DataCollatorWithPadding: Hugging Face Transformers 라이브러리에서 제공하는 데이터 콜레이터 중 하나입니다. 이 데이터 콜레이터는 패딩(padding)을 추가하여 배치(batch)의 모든 입력 시퀀스를 동일한 길이로 만들어주는 역할을 합니다.
  • tokenizer=tokenizer: 데이터 콜레이터를 초기화할 때, 해당 데이터 콜레이터가 어떤 토크나이저를 사용할지를 지정합니다. 여기서는 이전에 초기화한 BERT 모델의 토크나이저를 사용합니다.

이렇게 초기화된 데이터 콜레이터는 훈련할 때 패딩을 적용하고 배치를 처리하는 데 사용됩니다. 토크나이저가 생성한 토큰 ID, 어텐션 마스크 등의 정보에 패딩을 추가하여 배치 내의 모든 시퀀스를 동일한 길이로 맞춰주는 역할을 합니다. 이는 모델의 효율적인 훈련을 도와줍니다.

 

To test this new toy, let’s grab a few samples from our training set that we would like to batch together. Here, we remove the columns idx, sentence1, and sentence2 as they won’t be needed and contain strings (and we can’t create tensors with strings) and have a look at the lengths of each entry in the batch:

 

이 새로운 장난감을 테스트하기 위해 훈련 세트에서 함께 배치할 샘플 몇 개를 가져옵니다. 여기에서는 필요하지 않고 문자열을 포함하는 idx, 문장1 및 문장2 열을 제거하고(문자열로 텐서를 생성할 수 없음) 배치에 있는 각 항목의 길이를 살펴봅니다.

 

samples = tokenized_datasets["train"][:8]
samples = {k: v for k, v in samples.items() if k not in ["idx", "sentence1", "sentence2"]}
[len(x) for x in samples["input_ids"]]

 

이 코드는 토큰화된 MRPC(Microsoft Research Paraphrase Corpus) 데이터셋에서 훈련 세트의 처음 8개 예시에 대한 정보를 샘플링하고, 각 샘플의 입력 시퀀스의 길이를 확인하는 예제입니다. 코드를 단계별로 설명하겠습니다.

 

해석:

  1. tokenized_datasets["train"][:8]: 토큰화된 MRPC 데이터셋의 훈련 세트에서 처음 8개의 예시를 추출합니다.
  2. {k: v for k, v in samples.items() if k not in ["idx", "sentence1", "sentence2"]}: 샘플에서 필요한 정보만을 남기고, "idx", "sentence1", "sentence2" 등의 필드를 제외한 정보를 새로운 딕셔너리로 만듭니다. 여기서는 "input_ids" 등의 토큰화된 입력 정보만을 남깁니다.
  3. [len(x) for x in samples["input_ids"]]: 샘플링된 각 예시의 "input_ids" 필드의 길이를 리스트로 반환합니다. 이는 각 입력 시퀀스의 토큰 개수를 나타냅니다.

따라서 코드를 실행하면 훈련 세트의 처음 8개 예시에 대해 각 입력 시퀀스의 토큰 개수를 확인할 수 있습니다. 이는 패딩을 고려하여 모든 시퀀스가 동일한 길이로 맞추어지는지를 확인하는 데 도움이 됩니다.

 
[50, 59, 47, 67, 59, 50, 62, 32]
 

No surprise, we get samples of varying length, from 32 to 67. Dynamic padding means the samples in this batch should all be padded to a length of 67, the maximum length inside the batch. Without dynamic padding, all of the samples would have to be padded to the maximum length in the whole dataset, or the maximum length the model can accept. Let’s double-check that our data_collator is dynamically padding the batch properly:

 

당연히 32에서 67까지 다양한 길이의 샘플을 얻습니다. 동적 패딩은 이 배치의 샘플이 모두 배치 내부의 최대 길이인 67의 길이로 패딩되어야 함을 의미합니다. 동적 패딩이 없으면 모든 샘플은 전체 데이터 세트의 최대 길이 또는 모델이 허용할 수 있는 최대 길이까지 패딩되어야 합니다. data_collator가 배치를 동적으로 적절하게 채우고 있는지 다시 확인해 보겠습니다.

 

batch = data_collator(samples)
{k: v.shape for k, v in batch.items()}

 

{'attention_mask': torch.Size([8, 67]),
 'input_ids': torch.Size([8, 67]),
 'token_type_ids': torch.Size([8, 67]),
 'labels': torch.Size([8])}

 

이 코드는 앞서 설명한 데이터 콜레이터(Data Collator)를 사용하여 샘플들(samples)을 배치(batch)로 처리하고, 처리된 배치의 각 요소의 모양(shape)을 확인하는 예제입니다. 코드를 단계별로 설명하겠습니다.

 

해석:

  1. data_collator(samples): 앞서 초기화한 데이터 콜레이터를 사용하여 샘플들을 배치로 처리합니다. 이 과정에서 패딩이 적용되어 모든 시퀀스가 동일한 길이로 맞춰집니다.
  2. {k: v.shape for k, v in batch.items()}: 처리된 배치의 각 요소에 대해 모양(shape)을 확인합니다. 딕셔너리 컴프리헨션을 사용하여 각 텐서의 이름과 모양을 딕셔너리로 정리합니다.

따라서 코드를 실행하면 처리된 배치에 대한 정보가 출력됩니다. 이는 모델에 입력으로 제공되는 배치의 각 텐서의 모양이나 차원을 확인하는 데 도움이 됩니다.

 

 

 

 

Looking good! Now that we’ve gone from raw text to batches our model can deal with, we’re ready to fine-tune it!

 

좋아 보이네! 이제 원시 텍스트에서 모델이 처리할 수 있는 배치로 전환했으므로 미세 조정할 준비가 되었습니다!

 

✏️ Try it out! Replicate the preprocessing on the GLUE SST-2 dataset. It’s a little bit different since it’s composed of single sentences instead of pairs, but the rest of what we did should look the same. For a harder challenge, try to write a preprocessing function that works on any of the GLUE tasks.

 

✏️ 한번 사용해 보세요! GLUE SST-2 데이터 세트에서 전처리를 복제합니다. 쌍이 아닌 단일 문장으로 구성되어 있기 때문에 조금 다르지만 나머지 부분은 동일하게 보일 것입니다. 더 어려운 문제를 해결하려면 모든 GLUE 작업에서 작동하는 전처리 함수를 작성해 보세요.

 

Summary

 

이 단원은 데이터를 가져와서 Fine-Tunning 이 가능하도록 Model이 처리할 수 있는 형태로 바꾸는 작업을 설명하고 있음.

입력된 텍스트를 토큰화 해서 숫자로 바꿔 줘야하고 또한 그 크기 (행렬의 크기)도 Model 이 처리할 수 있도록 같게 해 줘야 함.

이 때 padding을 너무 많이 주게 되면 (예: Max) 자원 낭비가 되고 시간도 오래 걸리므로 가장 긴 입력 sentence에 맞게 혹은 특정 길이로 맞춰 주어야 함.

이때 padding은 마지막 단계인 batch 단에서 해주고 Hugging face에서 제공하는 DataCollatorWithPadding 클래스를 사용해서 처리하면 편리함

 

 

 

 

반응형


반응형

https://huggingface.co/learn/nlp-course/chapter3/1?fw=pt

 

Introduction - Hugging Face NLP Course

2. Using 🤗 Transformers 3. Fine-tuning a pretrained model 4. Sharing models and tokenizers 5. The 🤗 Datasets library 6. The 🤗 Tokenizers library 9. Building and sharing demos new

huggingface.co

 

 

 

Introduction

 

In Chapter 2 we explored how to use tokenizers and pretrained models to make predictions. But what if you want to fine-tune a pretrained model for your own dataset? That’s the topic of this chapter! You will learn:

 

2장에서는 토크나이저와 사전 훈련된 모델을 사용하여 예측을 수행하는 방법을 살펴보았습니다. 하지만 자신의 데이터 세트에 맞게 사전 훈련된 모델을 미세 조정하려면 어떻게 해야 할까요? 이것이 이번 장의 주제입니다! 당신은 배울 것이다:

 

  • How to prepare a large dataset from the Hub
  • 허브에서 대규모 데이터세트를 준비하는 방법
  • How to use the high-level Trainer API to fine-tune a model
  • 상위 수준 Trainer API를 사용하여 모델을 미세 조정하는 방법
  • How to use a custom training loop
  • 맞춤형 훈련 루프를 사용하는 방법
  • How to leverage the 🤗 Accelerate library to easily run that custom training loop on any distributed setup
  • 🤗 Accelerate 라이브러리를 활용하여 모든 분산 설정에서 사용자 정의 훈련 루프를 쉽게 실행하는 방법

 

In order to upload your trained checkpoints to the Hugging Face Hub, you will need a huggingface.co account: create an account

 

훈련된 체크포인트를 Hugging Face Hub에 업로드하려면 Huggingface.co 계정이 필요합니다. 계정을 만드세요.

 

 

 

 

 

 

 

 

 

반응형


반응형

https://huggingface.co/learn/nlp-course/chapter2/8?fw=pt

 

End-of-chapter quiz - Hugging Face NLP Course

2. Using 🤗 Transformers 3. Fine-tuning a pretrained model 4. Sharing models and tokenizers 5. The 🤗 Datasets library 6. The 🤗 Tokenizers library 9. Building and sharing demos new

huggingface.co

 

End-of-chapter quiz

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

반응형


반응형

https://huggingface.co/learn/nlp-course/chapter2/7?fw=pt

 

Basic usage completed! - Hugging Face NLP Course

2. Using 🤗 Transformers 3. Fine-tuning a pretrained model 4. Sharing models and tokenizers 5. The 🤗 Datasets library 6. The 🤗 Tokenizers library 9. Building and sharing demos new

huggingface.co

 

Basic usage completed!

 

Great job following the course up to here! To recap, in this chapter you:

 

여기까지의 과정을 잘 따라오셨습니다! 요약하면 이 장에서는 다음을 수행합니다.

 

  • Learned the basic building blocks of a Transformer model.
  • Transformer 모델의 기본 구성 요소를 학습했습니다.
  • Learned what makes up a tokenization pipeline.
  • 토큰화 파이프라인을 구성하는 요소를 알아봤습니다.
  • Saw how to use a Transformer model in practice.
  • 실제로 Transformer 모델을 사용하는 방법을 살펴보았습니다.
  • Learned how to leverage a tokenizer to convert text to tensors that are understandable by the model.
  • 토크나이저를 활용하여 텍스트를 모델에서 이해할 수 있는 텐서로 변환하는 방법을 배웠습니다.
  • Set up a tokenizer and a model together to get from text to predictions.
  • 텍스트에서 예측을 얻으려면 토크나이저와 모델을 함께 설정하세요.
  • Learned the limitations of input IDs, and learned about attention masks.
  • 입력 ID의 제한 사항을 알아보고 주의 마스크에 대해 알아봤습니다.
  • Played around with versatile and configurable tokenizer methods.
  • 다양하고 구성 가능한 토크나이저 방법을 사용해 보았습니다.

 

 

From now on, you should be able to freely navigate the 🤗 Transformers docs: the vocabulary will sound familiar, and you’ve already seen the methods that you’ll use the majority of the time.

 

이제부터는 🤗 Transformers 문서를 자유롭게 탐색할 수 있을 것입니다. 어휘는 친숙하게 들릴 것이며 대부분의 시간에 사용하게 될 방법은 이미 살펴보셨을 것입니다.

 

 

 

반응형


반응형

https://huggingface.co/learn/nlp-course/chapter2/6?fw=pt

 

Putting it all together

 

In the last few sections, we’ve been trying our best to do most of the work by hand. We’ve explored how tokenizers work and looked at tokenization, conversion to input IDs, padding, truncation, and attention masks.

 

지난 몇 섹션에서 우리는 대부분의 작업을 수동으로 수행하기 위해 최선을 다했습니다. 우리는 토크나이저의 작동 방식을 살펴보고 토큰화, 입력 ID로의 변환, 패딩, 잘림 및  attention masks 를 살펴보았습니다.

 

However, as we saw in section 2, the 🤗 Transformers API can handle all of this for us with a high-level function that we’ll dive into here. When you call your tokenizer directly on the sentence, you get back inputs that are ready to pass through your model:

 

그러나 섹션 2에서 본 것처럼 🤗 Transformers API는 여기서 자세히 살펴볼 고급 기능을 통해 이 모든 것을 처리할 수 있습니다. 문장에서 토크나이저를 직접 호출하면 모델을 통과할 준비가 된 입력을 다시 받게 됩니다.

 

from transformers import AutoTokenizer

checkpoint = "distilbert-base-uncased-finetuned-sst-2-english"
tokenizer = AutoTokenizer.from_pretrained(checkpoint)

sequence = "I've been waiting for a HuggingFace course my whole life."

model_inputs = tokenizer(sequence)

 

이 코드는 Hugging Face Transformers 라이브러리를 사용하여 사전 훈련된 감성 분류 모델을 로드하고, 주어진 텍스트 시퀀스를 토큰화하여 모델에 입력으로 전달하기 위한 입력을 생성하는 예제입니다. 코드를 이해해보겠습니다.

 

해석:

  • AutoTokenizer.from_pretrained(checkpoint): 주어진 모델의 토크나이저를 로드합니다.
  • sequence: 감성 분류를 위한 입력 텍스트 시퀀스를 정의합니다.
  • tokenizer(sequence): 토크나이저를 사용하여 주어진 텍스트 시퀀스를 토큰화합니다. 이 토큰화된 입력은 모델에 바로 전달할 수 있는 형태로 구성됩니다.

이 코드를 실행하면 model_inputs에는 토큰 ID, 어텐션 마스크, 토큰 유형 ID 등이 포함된 딕셔너리가 생성됩니다. 이러한 토큰화된 입력은 모델에 직접 전달되어 감성 분류 또는 다른 NLP 작업을 수행하는 데 사용될 수 있습니다.

 

 

Here, the model_inputs variable contains everything that’s necessary for a model to operate well. For DistilBERT, that includes the input IDs as well as the attention mask. Other models that accept additional inputs will also have those output by the tokenizer object.

 

여기서 model_inputs 변수에는 모델이 제대로 작동하는 데 필요한 모든 것이 포함되어 있습니다. DistilBERT의 경우 여기에는 attention mask 뿐만 아니라 입력 ID도 포함됩니다. 추가 입력을 허용하는 다른 모델에도 토크나이저 개체에 의한 출력이 있습니다.

 

As we’ll see in some examples below, this method is very powerful. First, it can tokenize a single sequence:

 

아래 몇 가지 예에서 볼 수 있듯이 이 방법은 매우 강력합니다. 첫째, 단일 시퀀스를 토큰화할 수 있습니다.

 

sequence = "I've been waiting for a HuggingFace course my whole life."

model_inputs = tokenizer(sequence)

 

 

 

It also handles multiple sequences at a time, with no change in the API:

 

또한 API를 변경하지 않고 한 번에 여러 시퀀스를 처리합니다.

 

sequences = ["I've been waiting for a HuggingFace course my whole life.", "So have I!"]

model_inputs = tokenizer(sequences)

 

 

It can pad according to several objectives:

 

여러 가지 objectives 에 따라 패딩할 수 있습니다.

 

# Will pad the sequences up to the maximum sequence length
model_inputs = tokenizer(sequences, padding="longest")

# Will pad the sequences up to the model max length
# (512 for BERT or DistilBERT)
model_inputs = tokenizer(sequences, padding="max_length")

# Will pad the sequences up to the specified max length
model_inputs = tokenizer(sequences, padding="max_length", max_length=8)

 

 

It can also truncate sequences:  시퀀스를 자를 수도 있습니다.

 

sequences = ["I've been waiting for a HuggingFace course my whole life.", "So have I!"]

# Will truncate the sequences that are longer than the model max length
# (512 for BERT or DistilBERT)
model_inputs = tokenizer(sequences, truncation=True)

# Will truncate the sequences that are longer than the specified max length
model_inputs = tokenizer(sequences, max_length=8, truncation=True)

 

 

 

The tokenizer object can handle the conversion to specific framework tensors, which can then be directly sent to the model. For example, in the following code sample we are prompting the tokenizer to return tensors from the different frameworks — "pt" returns PyTorch tensors, "tf" returns TensorFlow tensors, and "np" returns NumPy arrays:

 

토크나이저 객체는 특정 프레임워크 텐서로의 변환을 처리한 후 모델로 직접 보낼 수 있습니다. 예를 들어, 다음 코드 샘플에서는 토크나이저에게 다양한 프레임워크의 텐서를 반환하도록 요청합니다. "pt"는 PyTorch 텐서를 반환하고 "tf"는 TensorFlow 텐서를 반환하며 "np"는 NumPy 배열을 반환합니다.

 

sequences = ["I've been waiting for a HuggingFace course my whole life.", "So have I!"]

# Returns PyTorch tensors
model_inputs = tokenizer(sequences, padding=True, return_tensors="pt")

# Returns TensorFlow tensors
model_inputs = tokenizer(sequences, padding=True, return_tensors="tf")

# Returns NumPy arrays
model_inputs = tokenizer(sequences, padding=True, return_tensors="np")

 

 

Special tokens

If we take a look at the input IDs returned by the tokenizer, we will see they are a tiny bit different from what we had earlier:

 

토크나이저가 반환한 입력 ID를 살펴보면 이전에 얻은 것과 약간 다른 것을 알 수 있습니다.

 

sequence = "I've been waiting for a HuggingFace course my whole life."

model_inputs = tokenizer(sequence)
print(model_inputs["input_ids"])

tokens = tokenizer.tokenize(sequence)
ids = tokenizer.convert_tokens_to_ids(tokens)
print(ids)

 

[101, 1045, 1005, 2310, 2042, 3403, 2005, 1037, 17662, 12172, 2607, 2026, 2878, 2166, 1012, 102]
[1045, 1005, 2310, 2042, 3403, 2005, 1037, 17662, 12172, 2607, 2026, 2878, 2166, 1012]

 

 

One token ID was added at the beginning, and one at the end. Let’s decode the two sequences of IDs above to see what this is about:

 

토큰 ID는 처음에 하나, 끝에 하나가 추가되었습니다. 위의 두 ID 시퀀스를 디코딩하여 이것이 무엇인지 살펴보겠습니다.

 

print(tokenizer.decode(model_inputs["input_ids"]))
print(tokenizer.decode(ids))

 

"[CLS] i've been waiting for a huggingface course my whole life. [SEP]"
"i've been waiting for a huggingface course my whole life."

 

The tokenizer added the special word [CLS] at the beginning and the special word [SEP] at the end. This is because the model was pretrained with those, so to get the same results for inference we need to add them as well. Note that some models don’t add special words, or add different ones; models may also add these special words only at the beginning, or only at the end. In any case, the tokenizer knows which ones are expected and will deal with this for you.

 

토크나이저는 시작 부분에 특수 단어 [CLS]를 추가하고 끝에 특수 단어 [SEP]를 추가했습니다. 이는 모델이 이러한 항목으로 사전 학습되었기 때문에 동일한 추론 결과를 얻으려면 해당 항목도 추가해야 하기 때문입니다. 일부 모델은 특별한 단어를 추가하지 않거나 다른 단어를 추가하지 않습니다. 모델은 이러한 특수 단어를 시작 부분에만 추가하거나 끝 부분에만 추가할 수도 있습니다. 어떤 경우든 토크나이저는 어떤 것이 예상되는지 알고 이를 처리해 줍니다.

 

Wrapping up: From tokenizer to model

Now that we’ve seen all the individual steps the tokenizer object uses when applied on texts, let’s see one final time how it can handle multiple sequences (padding!), very long sequences (truncation!), and multiple types of tensors with its main API:

 

이제 토크나이저 객체가 텍스트에 적용될 때 사용하는 모든 개별 단계를 살펴보았으므로 마지막으로 여러 시퀀스(패딩!), 매우 긴 시퀀스(잘림!), 주요 API를 갖춘 다양한 유형의 텐서: 를 처리하는 방법을 살펴보겠습니다.

import torch
from transformers import AutoTokenizer, AutoModelForSequenceClassification

checkpoint = "distilbert-base-uncased-finetuned-sst-2-english"
tokenizer = AutoTokenizer.from_pretrained(checkpoint)
model = AutoModelForSequenceClassification.from_pretrained(checkpoint)
sequences = ["I've been waiting for a HuggingFace course my whole life.", "So have I!"]

tokens = tokenizer(sequences, padding=True, truncation=True, return_tensors="pt")
output = model(**tokens)

 

 

 

 

반응형


반응형

https://huggingface.co/learn/nlp-course/chapter2/5?fw=pt

 

Handling multiple sequences - Hugging Face NLP Course

In the previous section, we explored the simplest of use cases: doing inference on a single sequence of a small length. However, some questions emerge already: Let’s see what kinds of problems these questions pose, and how we can solve them using the

huggingface.co

 

Handling multiple sequences

 

https://youtu.be/M6adb1j2jPI?si=YqCspD4kwBnCat-7

 

In the previous section, we explored the simplest of use cases: doing inference on a single sequence of a small length. However, some questions emerge already:

 

이전 섹션에서는 가장 간단한 사용 사례인 짧은 길이의 단일 시퀀스에 대해 추론을 수행하는 방법을 살펴보았습니다. 그러나 몇 가지 질문이 이미 나타났습니다.

 

  • How do we handle multiple sequences?  여러 시퀀스를 어떻게 처리합니까?
  • How do we handle multiple sequences of different lengths?  길이가 다른 여러 시퀀스를 어떻게 처리합니까?
  • Are vocabulary indices the only inputs that allow a model to work well?  모델이 잘 작동하도록 하는 유일한 입력은 vocabulary indices 입니까?
  • Is there such a thing as too long a sequence?  너무 긴 시퀀스 같은 것이 있나요?

Let’s see what kinds of problems these questions pose, and how we can solve them using the 🤗 Transformers API.

 

이러한 질문이 어떤 종류의 문제를 야기하는지, 그리고 🤗 Transformers API를 사용하여 이러한 문제를 어떻게 해결할 수 있는지 살펴보겠습니다.

 

 

Models expect a batch of inputs

 

In the previous exercise you saw how sequences get translated into lists of numbers. Let’s convert this list of numbers to a tensor and send it to the model:

 

이전 연습에서는 시퀀스가 숫자 목록으로 변환되는 방법을 살펴보았습니다. 이 숫자 목록을 텐서로 변환하여 모델에 보내겠습니다.

 

 

import torch
from transformers import AutoTokenizer, AutoModelForSequenceClassification

checkpoint = "distilbert-base-uncased-finetuned-sst-2-english"
tokenizer = AutoTokenizer.from_pretrained(checkpoint)
model = AutoModelForSequenceClassification.from_pretrained(checkpoint)

sequence = "I've been waiting for a HuggingFace course my whole life."

tokens = tokenizer.tokenize(sequence)
ids = tokenizer.convert_tokens_to_ids(tokens)
input_ids = torch.tensor(ids)
# This line will fail.
model(input_ids)

 

IndexError: Dimension out of range (expected to be in range of [-1, 0], but got 1)

 

이 코드는 Hugging Face Transformers 라이브러리를 사용하여 사전 훈련된 감성 분류 모델을 로드하고, 주어진 텍스트 시퀀스를 토큰화하여 모델에 전달하는 예제입니다. 코드를 이해해보겠습니다.

 

해석:

  • checkpoint: 사용할 모델 및 토크나이저의 이름 또는 경로를 나타냅니다. 여기서는 감성 분류 모델 "distilbert-base-uncased-finetuned-sst-2-english"를 사용합니다.
  • AutoTokenizer.from_pretrained(checkpoint): 주어진 모델의 토크나이저를 로드합니다.
  • AutoModelForSequenceClassification.from_pretrained(checkpoint): 주어진 모델을 시퀀스 분류를 위한 모델로 로드합니다.
  • sequence: 분류를 위한 입력 텍스트 시퀀스를 정의합니다.
  • tokenizer.tokenize(sequence): 입력 텍스트를 토큰화합니다.
  • tokenizer.convert_tokens_to_ids(tokens): 토큰들을 모델의 입력으로 사용할 수 있는 정수 ID로 변환합니다.
  • torch.tensor(ids): PyTorch 텐서로 변환합니다.
  • model(input_ids): 여기서 주의해야 할 부분입니다. 이 코드는 모델에 입력을 전달하는데, 일반적으로는 토큰화된 시퀀스가 아니라 정수 ID로 이루어진 텐서를 전달해야 합니다. 그러나 현재 코드에서는 토큰화된 결과를 그대로 전달하고 있습니다. 따라서 이 줄에서 에러가 발생할 것입니다.

이 코드를 수정하여 model에 올바른 입력 형식을 제공하면 모델이 텍스트를 분류하는 결과를 얻을 수 있습니다.

 

 

Oh no! Why did this fail? “We followed the steps from the pipeline in section 2.

 

이! 왜 이것이 실패했는가? “우리는 섹션 2의 파이프라인 단계를 따랐습니다.

 

The problem is that we sent a single sequence to the model, whereas 🤗 Transformers models expect multiple sentences by default. Here we tried to do everything the tokenizer did behind the scenes when we applied it to a sequence. But if you look closely, you’ll see that the tokenizer didn’t just convert the list of input IDs into a tensor, it added a dimension on top of it:

 

문제는 우리가 모델에 단일 시퀀스를 보낸 반면 🤗 Transformers 모델은 기본적으로 여러 문장을 기대한다는 것입니다. 여기서 우리는 토크나이저를 시퀀스에 적용할 때 뒤에서 토크나이저가 수행하는 모든 작업을 수행하려고 했습니다. 그러나 자세히 살펴보면 토크나이저가 입력 ID 목록을 텐서로 변환한 것이 아니라 그 위에 차원을 추가했다는 것을 알 수 있습니다.

 

tokenized_inputs = tokenizer(sequence, return_tensors="pt")
print(tokenized_inputs["input_ids"])

 

tensor([[  101,  1045,  1005,  2310,  2042,  3403,  2005,  1037, 17662, 12172,
          2607,  2026,  2878,  2166,  1012,   102]])

 

이 코드는 Hugging Face Transformers 라이브러리의 토크나이저를 사용하여 주어진 텍스트 시퀀스를 토큰화하고, 그 결과를 PyTorch 텐서로 반환하는 예제입니다. 코드를 이해해보겠습니다.

 

해석:

  • tokenizer: 사전 훈련된 모델의 토크나이저를 나타냅니다. 코드에서는 이미 로드된 토크나이저를 사용하고 있다고 가정합니다.
  • sequence: 토큰화할 텍스트 시퀀스입니다. 코드에서는 "I've been waiting for a HuggingFace course my whole life."라는 텍스트를 사용하고 있습니다.
  • tokenizer(sequence, return_tensors="pt"): 주어진 텍스트 시퀀스를 토큰화하고, 결과를 PyTorch 텐서로 반환합니다. return_tensors="pt" 인자는 결과를 PyTorch 텐서로 반환하도록 지정하는 부분입니다.
  • tokenized_inputs["input_ids"]: 토큰화된 결과 중에서 "input_ids" 키에 해당하는 값, 즉 정수로 이루어진 텐서를 출력합니다.

따라서 print(tokenized_inputs["input_ids"])는 주어진 텍스트 시퀀스를 토큰화하여 얻은 토큰 ID들을 PyTorch 텐서로 출력합니다. 이렇게 토큰화된 입력은 주로 모델에 입력으로 제공될 때 사용되며, 모델이 텍스트를 이해할 수 있는 형식으로 변환됩니다.

 

 

Let’s try again and add a new dimension:  다시 시도하고 새로운 측정기준을 추가해 보겠습니다.

 

import torch
from transformers import AutoTokenizer, AutoModelForSequenceClassification

checkpoint = "distilbert-base-uncased-finetuned-sst-2-english"
tokenizer = AutoTokenizer.from_pretrained(checkpoint)
model = AutoModelForSequenceClassification.from_pretrained(checkpoint)

sequence = "I've been waiting for a HuggingFace course my whole life."

tokens = tokenizer.tokenize(sequence)
ids = tokenizer.convert_tokens_to_ids(tokens)

input_ids = torch.tensor([ids])
print("Input IDs:", input_ids)

output = model(input_ids)
print("Logits:", output.logits)

 

We print the input IDs as well as the resulting logits — here’s the output:

 

입력 ID와 결과 로짓을 인쇄합니다. 출력은 다음과 같습니다.

 

Input IDs: [[ 1045,  1005,  2310,  2042,  3403,  2005,  1037, 17662, 12172,  2607, 2026,  2878,  2166,  1012]]
Logits: [[-2.7276,  2.8789]]

 

 

이 코드는 Hugging Face Transformers 라이브러리를 사용하여 감성 분류 모델을 로드하고, 주어진 텍스트 시퀀스를 토큰화하여 모델에 전달하며, 모델의 출력을 확인하는 예제입니다. 코드를 이해해보겠습니다.

 

해석:

  • checkpoint: 사용할 모델 및 토크나이저의 이름 또는 경로를 나타냅니다. 여기서는 감성 분류 모델 "distilbert-base-uncased-finetuned-sst-2-english"를 사용합니다.
  • AutoTokenizer.from_pretrained(checkpoint): 주어진 모델의 토크나이저를 로드합니다.
  • AutoModelForSequenceClassification.from_pretrained(checkpoint): 주어진 모델을 감성 분류를 위한 모델로 로드합니다.
  • sequence: 감성 분류를 위한 입력 텍스트 시퀀스를 정의합니다.
  • tokenizer.tokenize(sequence): 입력 텍스트를 토큰화합니다.
  • tokenizer.convert_tokens_to_ids(tokens): 토큰들을 모델의 입력으로 사용할 수 있는 정수 ID로 변환합니다.
  • torch.tensor([ids]): PyTorch 텐서로 변환합니다. 여기서는 2D 텐서를 만들기 위해 입력을 리스트로 묶었습니다.
  • model(input_ids): 모델에 입력을 전달하여 출력을 얻습니다.
  • output.logits: 모델의 출력 중 로짓(logits) 값을 확인합니다. 이 값은 감성 분류 모델이 각 클래스에 할당한 점수를 나타냅니다.

따라서 코드는 주어진 텍스트를 감성 분류 모델에 입력으로 전달하고, 모델이 예측한 클래스에 대한 로짓을 출력합니다.

 

 

 

Batching is the act of sending multiple sentences through the model, all at once. If you only have one sentence, you can just build a batch with a single sequence:

 

일괄 처리는 모델을 통해 여러 문장을 한 번에 보내는 행위입니다. 문장이 하나뿐인 경우 단일 시퀀스로 배치를 만들 수 있습니다.

 

 

batched_ids = [ids, ids]

 

 

This is a batch of two identical sequences!  이것은 두 개의 동일한 시퀀스로 구성된 배치입니다!

 

✏️ Try it out! Convert this batched_ids list into a tensor and pass it through your model. Check that you obtain the same logits as before (but twice)!

 

✏️ 한번 사용해 보세요! 이 bated_ids 목록을 텐서로 변환하고 모델을 통해 전달하세요. 이전과 동일한 로지트(단, 두 번)를 얻었는지 확인하세요!

 

 

Batching allows the model to work when you feed it multiple sentences. Using multiple sequences is just as simple as building a batch with a single sequence. There’s a second issue, though. When you’re trying to batch together two (or more) sentences, they might be of different lengths. If you’ve ever worked with tensors before, you know that they need to be of rectangular shape, so you won’t be able to convert the list of input IDs into a tensor directly. To work around this problem, we usually pad the inputs.

 

일괄 처리를 사용하면 모델에 여러 문장을 제공할 때 모델이 작동할 수 있습니다. 여러 시퀀스를 사용하는 것은 단일 시퀀스로 배치를 구축하는 것만큼 간단합니다. 하지만 두 번째 문제가 있습니다. 두 개 이상의 문장을 일괄 처리하려고 하면 길이가 다를 수 있습니다. 이전에 텐서를 사용해 본 적이 있다면 직사각형 모양이어야 하므로 입력 ID 목록을 텐서로 직접 변환할 수 없다는 것을 알고 있을 것입니다. 이 문제를 해결하기 위해 일반적으로 입력을 채웁니다.

 

Padding the inputs

The following list of lists cannot be converted to a tensor:

 

다음 list of lists 은 텐서로 변환할 수 없습니다.

 

batched_ids = [
    [200, 200, 200],
    [200, 200]
]

 

In order to work around this, we’ll use padding to make our tensors have a rectangular shape. Padding makes sure all our sentences have the same length by adding a special word called the padding token to the sentences with fewer values. For example, if you have 10 sentences with 10 words and 1 sentence with 20 words, padding will ensure all the sentences have 20 words. In our example, the resulting tensor looks like this:

 

이 문제를 해결하기 위해 패딩을 사용하여 텐서를 직사각형 모양으로 만듭니다. 패딩은 더 적은 값을 가진 문장에 패딩 토큰이라는 특수 단어를 추가하여 모든 문장의 길이를 동일하게 만듭니다. 예를 들어, 10개 단어로 구성된 10개의 문장과 20개 단어로 구성된 1개의 문장이 있는 경우 패딩을 사용하면 모든 문장이 20개 단어로 구성됩니다. 이 예에서 결과 텐서는 다음과 같습니다.

 

padding_id = 100

batched_ids = [
    [200, 200, 200],
    [200, 200, padding_id],
]

 

 

The padding token ID can be found in tokenizer.pad_token_id. Let’s use it and send our two sentences through the model individually and batched together:

 

패딩 토큰 ID는 tokenizer.pad_token_id에서 찾을 수 있습니다. 이를 사용하여 모델을 통해 두 문장을 개별적으로 일괄 전송해 보겠습니다.

 

model = AutoModelForSequenceClassification.from_pretrained(checkpoint)

sequence1_ids = [[200, 200, 200]]
sequence2_ids = [[200, 200]]
batched_ids = [
    [200, 200, 200],
    [200, 200, tokenizer.pad_token_id],
]

print(model(torch.tensor(sequence1_ids)).logits)
print(model(torch.tensor(sequence2_ids)).logits)
print(model(torch.tensor(batched_ids)).logits)
tensor([[ 1.5694, -1.3895]], grad_fn=<AddmmBackward>)
tensor([[ 0.5803, -0.4125]], grad_fn=<AddmmBackward>)
tensor([[ 1.5694, -1.3895],
        [ 1.3373, -1.2163]], grad_fn=<AddmmBackward>)

 

이 코드는 Hugging Face Transformers 라이브러리를 사용하여 감성 분류 모델을 로드하고, 서로 다른 길이의 시퀀스에 대한 예측을 수행하는 예제입니다. 코드를 이해해보겠습니다.

 

해석:

  • AutoModelForSequenceClassification.from_pretrained(checkpoint): 주어진 모델을 감성 분류를 위한 모델로 로드합니다.
  • sequence1_ids, sequence2_ids, batched_ids: 서로 다른 길이의 시퀀스를 정의합니다. sequence1_ids는 길이가 3인 시퀀스, sequence2_ids는 길이가 2인 시퀀스, batched_ids는 길이가 3 또는 2인 두 개의 시퀀스로 구성된 배치입니다. 두 번째 시퀀스의 끝 부분은 패딩 토큰으로 채워져 있습니다.
  • model(torch.tensor(sequence1_ids)).logits: 모델에 첫 번째 시퀀스를 입력으로 전달하고, 감성 분류 모델이 예측한 클래스에 대한 로짓(logits)을 출력합니다.
  • model(torch.tensor(sequence2_ids)).logits: 모델에 두 번째 시퀀스를 입력으로 전달하고, 마찬가지로 예측한 클래스에 대한 로짓을 출력합니다.
  • model(torch.tensor(batched_ids)).logits: 모델에 배치로 묶인 시퀀스를 입력으로 전달하고, 예측한 클래스에 대한 로짓을 출력합니다. 이때, 패딩된 부분은 모델에 영향을 미치지 않습니다.

따라서 코드는 서로 다른 길이의 시퀀스를 모델에 입력으로 전달하여 예측을 수행하고, 각 시퀀스에 대한 예측 클래스에 대한 로짓을 출력하는 예제입니다.

 

 

There’s something wrong with the logits in our batched predictions: the second row should be the same as the logits for the second sentence, but we’ve got completely different values!

 

일괄 예측의 로짓에 문제가 있습니다. 두 번째 행은 두 번째 문장의 로짓과 동일해야 하지만 값이 완전히 다릅니다!

 

This is because the key feature of Transformer models is attention layers that contextualize each token. These will take into account the padding tokens since they attend to all of the tokens of a sequence. To get the same result when passing individual sentences of different lengths through the model or when passing a batch with the same sentences and padding applied, we need to tell those attention layers to ignore the padding tokens. This is done by using an attention mask.

 

이는 Transformer 모델의 주요 기능이 각 토큰을 맥락화하는 attention layers 이기 때문입니다. 이는 시퀀스의 모든 토큰에 참여하므로 패딩 토큰을 고려합니다. 모델을 통해 길이가 다른 개별 문장을 전달할 때 또는 동일한 문장과 패딩이 적용된 배치를 전달할 때 동일한 결과를 얻으려면 해당 Attention 레이어에 패딩 토큰을 무시하도록 지시해야 합니다. 이는 attention mask 를 사용하여 수행됩니다.

 

Attention masks

Attention masks are tensors with the exact same shape as the input IDs tensor, filled with 0s and 1s: 1s indicate the corresponding tokens should be attended to, and 0s indicate the corresponding tokens should not be attended to (i.e., they should be ignored by the attention layers of the model).

 

어텐션 마스크는 입력 ID 텐서와 정확히 동일한 모양의 텐서이며 0과 1로 채워집니다. 1은 해당 토큰에 주의해야 함을 나타내고 0은 해당 토큰에 주의하지 않아야 함을 나타냅니다(즉, 무시해야 함). 모델의 attention layer ).

 

Let’s complete the previous example with an attention mask:

 

attention mask 를 사용하여 이전 예를 완성해 보겠습니다.

 

batched_ids = [
    [200, 200, 200],
    [200, 200, tokenizer.pad_token_id],
]

attention_mask = [
    [1, 1, 1],
    [1, 1, 0],
]

outputs = model(torch.tensor(batched_ids), attention_mask=torch.tensor(attention_mask))
print(outputs.logits)
tensor([[ 1.5694, -1.3895],
        [ 0.5803, -0.4125]], grad_fn=<AddmmBackward>)

 

이 코드는 Hugging Face Transformers 라이브러리를 사용하여 감성 분류 모델에 대해 패딩된 시퀀스를 입력으로 전달하고, attention mask를 사용하여 패딩 부분에 모델이 주의를 기울이지 않도록 하는 예제입니다. 코드를 이해해보겠습니다.

 

해석:

  • batched_ids: 두 개의 시퀀스를 담은 배치를 정의합니다. 첫 번째 시퀀스는 길이가 3이고 모든 토큰이 실제 입력에 속해 있는 것으로 가정합니다. 두 번째 시퀀스는 길이가 3이지만, 세 번째 토큰이 패딩 토큰으로 채워져 있습니다.
  • attention_mask: 각 시퀀스에 대한 어텐션 마스크를 정의합니다. 첫 번째 시퀀스는 모든 토큰에 대해 어텐션을 기울이기를 원하므로 1로 설정합니다. 두 번째 시퀀스는 마지막 토큰이 패딩되었으므로, 이를 나타내기 위해 마지막 위치에 0으로 설정합니다.
  • model(torch.tensor(batched_ids), attention_mask=torch.tensor(attention_mask)): 모델에 패딩된 시퀀스와 attention mask를 입력으로 전달합니다. attention mask는 패딩 토큰에 대한 어텐션을 조절하는 데 사용됩니다.
  • outputs.logits: 모델의 출력 중 로짓(logits) 값을 확인합니다. 이 값은 감성 분류 모델이 각 클래스에 할당한 점수를 나타냅니다.

따라서 코드는 패딩된 시퀀스를 모델에 입력으로 전달하고, attention mask를 사용하여 패딩 부분에 대한 어텐션을 제어하여 예측을 수행하고, 각 시퀀스에 대한 예측 클래스에 대한 로짓을 출력하는 예제입니다.

 

 

 

 

Now we get the same logits for the second sentence in the batch.

 

이제 배치의 두 번째 문장에 대해 동일한 로짓을 얻습니다.

 

Notice how the last value of the second sequence is a padding ID, which is a 0 value in the attention mask.

 

두 번째 시퀀스의 마지막 값이 어텐션 마스크의 0 값인 패딩 ID라는 점에 유의하세요.

 

✏️ Try it out! Apply the tokenization manually on the two sentences used in section 2 (“I’ve been waiting for a HuggingFace course my whole life.” and “I hate this so much!”). Pass them through the model and check that you get the same logits as in section 2. Now batch them together using the padding token, then create the proper attention mask. Check that you obtain the same results when going through the model!

 

✏️ 한번 사용해 보세요! 섹션 2에서 사용된 두 문장(“ I’ve been waiting for a HuggingFace course my whole life.” and “I hate this so much! ”)에 토큰화를 수동으로 적용합니다. 모델을 통해 이를 전달하고 섹션 2와 동일한 로짓을 얻는지 확인합니다. 이제 패딩 토큰을 사용하여 일괄 처리한 다음 적절한 주의 마스크를 만듭니다. 모델을 진행할 때 동일한 결과를 얻는지 확인하십시오!

 

실행 결과

 

 

"I've been waiting for a HuggingFace course my whole life." 와 "I hate this so much!" 두 문장에 대한 input_id 와 logit을 구함 
 

 

attention_mask를 사용하지 않았을 경우 두번째 문장이 다르게 나옴

 

 

attention_mask를 사용하면 batched_ids를 사용해도 두 문장 모두 logit이 같게 나옴.

 

Longer sequences

With Transformer models, there is a limit to the lengths of the sequences we can pass the models. Most models handle sequences of up to 512 or 1024 tokens, and will crash when asked to process longer sequences. There are two solutions to this problem:

 

Transformer 모델의 경우 모델을 전달할 수 있는 시퀀스의 길이에 제한이 있습니다. 대부분의 모델은 최대 512개 또는 1024개 토큰의 시퀀스를 처리하며 더 긴 시퀀스를 처리하라는 요청을 받으면 충돌이 발생합니다. 이 문제에 대한 두 가지 해결책이 있습니다.

 

  • Use a model with a longer supported sequence length.
  • 지원되는 시퀀스 길이가 더 긴 모델을 사용하세요.
  • Truncate your sequences.
  • 시퀀스를 자릅니다.

Models have different supported sequence lengths, and some specialize in handling very long sequences. Longformer is one example, and another is LED. If you’re working on a task that requires very long sequences, we recommend you take a look at those models.

 

모델마다 지원되는 시퀀스 길이가 다르며 일부 모델은 매우 긴 시퀀스를 전문적으로 처리합니다. Longformer가 한 예이고 다른 하나는 LED입니다. 매우 긴 시퀀스가 필요한 작업을 수행하는 경우 해당 모델을 살펴보는 것이 좋습니다.

 

Otherwise, we recommend you truncate your sequences by specifying the max_sequence_length parameter:

 

그렇지 않은 경우 max_sequence_length 매개변수를 지정하여 시퀀스를 자르는 것이 좋습니다.

 

sequence = sequence[:max_sequence_length]

 

 

Summary

 

여러 문장의 입력값을 받을 경우 각 tensor의 길이는 모두 같아야 한다.

이럴 경우 짧은 문장의 경우 긴 문장과 길이기 같도록 하기 위해 padding을 더해 준다.

이 때 짧은 문장에 더해진 padding이 attention 연산을 할 때 같이 계산되기 때문에 결과값 (logit)이 실제 문장과는 다르게 나온다. attention연산에서 padding 부분이 제외 되도록 하기 위해 atention_mask를 사용해야 한다.

model(torch.tensor(batched_ids), attention_mask=torch.tensor(attention_mask))

 

반응형


반응형

https://huggingface.co/learn/nlp-course/chapter2/4?fw=pt

 

Tokenizers - Hugging Face NLP Course

Tokenizers are one of the core components of the NLP pipeline. They serve one purpose: to translate text into data that can be processed by the model. Models can only process numbers, so tokenizers need to convert our text inputs to numerical data. In this

huggingface.co

 

 

 

https://youtu.be/VFp38yj8h3A?si=zeIrCE2nhR7jk2r8

 

 

Tokenizers are one of the core components of the NLP pipeline. They serve one purpose: to translate text into data that can be processed by the model. Models can only process numbers, so tokenizers need to convert our text inputs to numerical data. In this section, we’ll explore exactly what happens in the tokenization pipeline.

 

토크나이저는 NLP 파이프라인의 핵심 구성 요소 중 하나입니다. 이는 한 가지 목적, 즉 텍스트를 모델에서 처리할 수 있는 데이터로 변환하는 데 사용됩니다. 모델은 숫자만 처리할 수 있으므로 토크나이저는 텍스트 입력을 숫자 데이터로 변환해야 합니다. 이 섹션에서는 토큰화 파이프라인에서 정확히 무슨 일이 일어나는지 살펴보겠습니다.

 

In NLP tasks, the data that is generally processed is raw text. Here’s an example of such text:

 

NLP 작업에서 일반적으로 처리되는 데이터는 원시 텍스트입니다. 다음은 그러한 텍스트의 예입니다.

 

Jim Henson was a puppeteer

 

However, models can only process numbers, so we need to find a way to convert the raw text to numbers. That’s what the tokenizers do, and there are a lot of ways to go about this. The goal is to find the most meaningful representation — that is, the one that makes the most sense to the model — and, if possible, the smallest representation.

 

그러나 모델은 숫자만 처리할 수 있으므로 원시 텍스트를 숫자로 변환하는 방법을 찾아야 합니다. 이것이 바로 토크나이저가 하는 일이며, 이를 해결하는 방법은 많습니다. 목표는 가장 의미 있는 표현, 즉 모델에 가장 적합한 표현과 가능하다면 가장 작은 표현을 찾는 것입니다.

 

Let’s take a look at some examples of tokenization algorithms, and try to answer some of the questions you may have about tokenization.

 

토큰화 알고리즘의 몇 가지 예를 살펴보고 토큰화에 관해 가질 수 있는 몇 가지 질문에 답해 보겠습니다.

 

Word-based

 

https://youtu.be/nhJxYji1aho?si=aBJsxx9XrFSCPYEp

 

 

The first type of tokenizer that comes to mind is word-based. It’s generally very easy to set up and use with only a few rules, and it often yields decent results. For example, in the image below, the goal is to split the raw text into words and find a numerical representation for each of them:

 

가장 먼저 떠오르는 토크나이저 유형은 단어 기반입니다. 일반적으로 몇 가지 규칙만 있으면 설정하고 사용하기가 매우 쉽고, 종종 괜찮은 결과를 얻을 수 있습니다. 예를 들어, 아래 이미지에서 목표는 원시 텍스트를 단어로 분할하고 각 단어에 대한 숫자 표현을 찾는 것입니다.

 

 

 

There are different ways to split the text. For example, we could use whitespace to tokenize the text into words by applying Python’s split() function:

 

텍스트를 분할하는 방법에는 여러 가지가 있습니다. 예를 들어, Python의 Split() 함수를 적용하여 공백을 사용하여 텍스트를 단어로 토큰화할 수 있습니다.

 

tokenized_text = "Jim Henson was a puppeteer".split()
print(tokenized_text)

 

['Jim', 'Henson', 'was', 'a', 'puppeteer']

 

 

There are also variations of word tokenizers that have extra rules for punctuation. With this kind of tokenizer, we can end up with some pretty large “vocabularies,” where a vocabulary is defined by the total number of independent tokens that we have in our corpus.

 

구두점에 대한 추가 규칙이 있는 다양한 단어 토크나이저도 있습니다. 이런 종류의 토크나이저를 사용하면 꽤 큰 "어휘 vocabularies "를 얻을 수 있습니다. 여기서 어휘는 코퍼스에 있는 총 독립 토큰 수로 정의됩니다.

 

Each word gets assigned an ID, starting from 0 and going up to the size of the vocabulary. The model uses these IDs to identify each word.

 

각 단어에는 0부터 시작하여 어휘 크기까지 ID가 할당됩니다. 모델은 이러한 ID를 사용하여 각 단어를 식별합니다.

 

If we want to completely cover a language with a word-based tokenizer, we’ll need to have an identifier for each word in the language, which will generate a huge amount of tokens. For example, there are over 500,000 words in the English language, so to build a map from each word to an input ID we’d need to keep track of that many IDs. Furthermore, words like “dog” are represented differently from words like “dogs”, and the model will initially have no way of knowing that “dog” and “dogs” are similar: it will identify the two words as unrelated. The same applies to other similar words, like “run” and “running”, which the model will not see as being similar initially.

 

단어 기반 토크나이저로 언어를 완전히 다루려면 언어의 각 단어에 대한 식별자가 있어야 하며, 이로 인해 엄청난 양의 토큰이 생성됩니다. 예를 들어, 영어에는 500,000개 이상의 단어가 있으므로 각 단어에서 입력 ID까지의 맵을 작성하려면 많은 ID를 추적해야 합니다. 또한, " dog "와 같은 단어는 " dogs "와 같은 단어와 다르게 표현되며, 모델은 처음에는 " dog  "와 " dogs  "가 유사하다는 것을 알 수 없습니다. 즉, 두 단어를 관련 없는 것으로 식별합니다. "run" 및 "running"과 같은 다른 유사한 단어에도 동일하게 적용됩니다. 모델에서는 처음에는 유사한 것으로 간주하지 않습니다.

 

Finally, we need a custom token to represent words that are not in our vocabulary. This is known as the “unknown” token, often represented as ”[UNK]” or ””. It’s generally a bad sign if you see that the tokenizer is producing a lot of these tokens, as it wasn’t able to retrieve a sensible representation of a word and you’re losing information along the way. The goal when crafting the vocabulary is to do it in such a way that the tokenizer tokenizes as few words as possible into the unknown token.

 

마지막으로, 우리 vocabulary 에 없는 단어를 나타내기 위해서는 사용자 정의 토큰이 필요합니다. 이는 " unknown " 토큰으로 알려져 있으며 종종 "[UNK]" 또는 ""로 표시됩니다. 토크나이저가 이러한 토큰을 많이 생성하는 것을 보면 일반적으로 나쁜 징조입니다. 단어에 대한 합리적인 표현을 검색할 수 없고 그 과정에서 정보가 손실되기 때문입니다. 어휘를 만들 때 목표는 토크나이저가 가능한 한 적은 단어를 unknown  토큰으로 토큰화하는 방식으로 이를 수행하는 것입니다.

 

One way to reduce the amount of unknown tokens is to go one level deeper, using a character-based tokenizer.

 

알려지지 않은 토큰의 양을 줄이는 한 가지 방법은 문자 기반 토크나이저를 사용하여 한 단계 더 깊이 들어가는 것입니다.

 

Character-based

 

https://youtu.be/ssLq_EK2jLE?si=qpUoKBKDZyMzqICB

 

 

Character-based tokenizers split the text into characters, rather than words. This has two primary benefits:

 

문자 기반 토크나이저는 텍스트를 단어가 아닌 문자로 분할합니다. 여기에는 두 가지 주요 이점이 있습니다.

 

  • The vocabulary is much smaller.  어휘가 훨씬 작습니다.
  • There are much fewer out-of-vocabulary (unknown) tokens, since every word can be built from characters.
  • 모든 단어가 문자로 구성될 수 있으므로 어휘에서 벗어난(알 수 없는) 토큰이 훨씬 적습니다.

But here too some questions arise concerning spaces and punctuation:

 

그러나 여기서도 공백과 구두점에 관해 몇 가지 질문이 제기됩니다.

 

 

This approach isn’t perfect either. Since the representation is now based on characters rather than words, one could argue that, intuitively, it’s less meaningful: each character doesn’t mean a lot on its own, whereas that is the case with words. However, this again differs according to the language; in Chinese, for example, each character carries more information than a character in a Latin language.

 

이 접근 방식도 완벽하지는 않습니다. 이제 표현은 단어가 아닌 문자를 기반으로 하기 때문에 직관적으로 의미가 덜하다고 주장할 수 있습니다. 각 문자는 그 자체로는 큰 의미가 없지만 단어의 경우에는 그렇습니다. 그러나 이것도 언어에 따라 다릅니다. 예를 들어 중국어의 경우 각 문자는 라틴어의 문자보다 더 많은 정보를 전달합니다.

 

Another thing to consider is that we’ll end up with a very large amount of tokens to be processed by our model: whereas a word would only be a single token with a word-based tokenizer, it can easily turn into 10 or more tokens when converted into characters.

 

고려해야 할 또 다른 사항은 모델에서 처리할 토큰의 양이 매우 많아진다는 것입니다. 단어 기반 토크나이저에서는 단어가 단일 토큰일 뿐이지만, 캐릭터로 변환하면 쉽게 10개 이상의 토큰으로 바뀔 수 있습니다.

 

To get the best of both worlds, we can use a third technique that combines the two approaches: subword tokenization.

 

두 가지 장점을 모두 활용하기 위해 두 가지 접근 방식을 결합한 세 번째 기술인 하위 단어 토큰화를 사용할 수 있습니다.

 

Subword tokenization

https://youtu.be/zHvTiHr506c?si=ffMfRyqPLLUyQXuN

 

 

Subword tokenization algorithms rely on the principle that frequently used words should not be split into smaller subwords, but rare words should be decomposed into meaningful subwords.

 

하위 단어 토큰화 알고리즘은 자주 사용되는 단어를 더 작은 하위 단어로 분할해서는 안 되고, 희귀한 단어는 의미 있는 하위 단어로 분해해야 한다는 원칙에 의존합니다.

 

For instance, “annoyingly” might be considered a rare word and could be decomposed into “annoying” and “ly”. These are both likely to appear more frequently as standalone subwords, while at the same time the meaning of “annoyingly” is kept by the composite meaning of “annoying” and “ly”.

 

예를 들어, " annoyingly "는 드문 단어로 간주될 수 있으며 " annoying "과 "ly"로 분해될 수 있습니다. 이들 둘 다 독립형 하위 단어로 더 자주 나타날 가능성이 높으며, 동시에 " annoyingly "의 의미는 " annoying "과 "ly"의 복합 의미로 유지됩니다.

 

Here is an example showing how a subword tokenization algorithm would tokenize the sequence “Let’s do tokenization!“:

 

다음은 하위 단어 토큰화 알고리즘이 "Let's do tokenization!" 시퀀스를 토큰화하는 방법을 보여주는 예입니다.

 

 

These subwords end up providing a lot of semantic meaning: for instance, in the example above “tokenization” was split into “token” and “ization”, two tokens that have a semantic meaning while being space-efficient (only two tokens are needed to represent a long word). This allows us to have relatively good coverage with small vocabularies, and close to no unknown tokens.

 

이러한 하위 단어는 결국 많은 semantic meaning 를 제공하게 됩니다. 예를 들어 위의 예에서 " tokenization "는 " token "과 " ization "로 분할되었으며 space-efficient  이면서 semantic meaning 를 갖는 두 개의 토큰입니다( 긴 단어를 표현하기 위해  두 개의 토큰만 필요함).  이를 통해 우리는 작은 어휘로 상대적으로 좋은 적용 범위를 가질 수 있으며 unknown  토큰이 거의 없습니다.

 

This approach is especially useful in agglutinative languages such as Turkish, where you can form (almost) arbitrarily long complex words by stringing together subwords.

 

이 접근 방식은 하위 단어를 함께 묶어 (거의) 임의로 긴 복잡한 단어를 형성할 수 있는 터키어와 같은 교착어에서 특히 유용합니다.

 

And more!

Unsurprisingly, there are many more techniques out there. To name a few:

 

놀랍게도 이 외에도 더 많은 기술이 있습니다. 몇 가지 예를 들면 다음과 같습니다.

 

  • Byte-level BPE, as used in GPT-2.  GPT-2에서 사용되는 바이트 수준 BPE
  • WordPiece, as used in BERT.  BERT에서 사용되는 WordPiece
  • SentencePiece or Unigram, as used in several multilingual models.  여러 다국어 모델에 사용되는 SentencePiece 또는 Unigram

You should now have sufficient knowledge of how tokenizers work to get started with the API.

 

이제 API를 시작하려면 토크나이저가 어떻게 작동하는지에 대한 충분한 지식이 있어야 합니다.

 

Loading and saving

Loading and saving tokenizers is as simple as it is with models. Actually, it’s based on the same two methods: from_pretrained() and save_pretrained(). These methods will load or save the algorithm used by the tokenizer (a bit like the architecture of the model) as well as its vocabulary (a bit like the weights of the model).

 

토크나이저를 로드하고 저장하는 것은 모델과 마찬가지로 간단합니다. 실제로는 from_pretrained()와 save_pretrained()라는 동일한 두 가지 메서드를 기반으로 합니다. 이러한 방법은 토크나이저에서 사용하는 알고리즘(모델의 아키텍처와 약간 유사)과 해당 어휘(모델의 가중치와 약간 유사)를 로드하거나 저장합니다.

 

Loading the BERT tokenizer trained with the same checkpoint as BERT is done the same way as loading the model, except we use the BertTokenizer class:

 

BERT와 동일한 체크포인트로 훈련된 BERT 토크나이저를 로드하는 것은 BertTokenizer 클래스를 사용한다는 점을 제외하면 모델 로드와 동일한 방식으로 수행됩니다.

 

from transformers import BertTokenizer

tokenizer = BertTokenizer.from_pretrained("bert-base-cased")

 

Similar to AutoModel, the AutoTokenizer class will grab the proper tokenizer class in the library based on the checkpoint name, and can be used directly with any checkpoint:

 

AutoModel과 마찬가지로 AutoTokenizer 클래스는 체크포인트 이름을 기반으로 라이브러리에서 적절한 토크나이저 클래스를 가져오고 모든 체크포인트와 함께 직접 사용할 수 있습니다.

 

from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("bert-base-cased")

 

 

We can now use the tokenizer as shown in the previous section:

 

이제 이전 섹션에 표시된 대로 토크나이저를 사용할 수 있습니다.

 

tokenizer("Using a Transformer network is simple")

 

{'input_ids': [101, 7993, 170, 11303, 1200, 2443, 1110, 3014, 102],
 'token_type_ids': [0, 0, 0, 0, 0, 0, 0, 0, 0],
 'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1]}

 

해석:

  • input_ids: 텍스트를 BERT 모델이 이해할 수 있는 숫자 시퀀스로 변환한 결과입니다. 여기서는 각 토큰에 해당하는 정수 ID들의 리스트입니다.
  • token_type_ids: 문장 유형을 나타내는 부분입니다. BERT 모델이 여러 문장을 입력으로 받을 수 있기 때문에, 각 토큰이 어느 문장에 속하는지를 구분합니다. 여기서는 단일 문장이므로 모두 0으로 설정되어 있습니다.
  • attention_mask: 어텐션 마스크는 입력 토큰 중 어떤 것이 실제로 모델에 의해 주의를 기울여야 하는지를 나타냅니다. 여기서는 모든 토큰이 실제 입력에 포함되므로 모두 1로 설정되어 있습니다.

이 결과를 통해 원본 텍스트가 토큰화되어 모델의 입력 형식으로 변환된 것을 확인할 수 있습니다.

 

 

Saving a tokenizer is identical to saving a model:

 

토크나이저를 저장하는 것은 모델을 저장하는 것과 동일합니다.

 

tokenizer.save_pretrained("directory_on_my_computer")

 

 

We’ll talk more about token_type_ids in Chapter 3, and we’ll explain the attention_mask key a little later. First, let’s see how the input_ids are generated. To do this, we’ll need to look at the intermediate methods of the tokenizer.

 

token_type_ids에 대해서는 3장에서 더 자세히 설명하고 attention_mask 키에 대해서는 잠시 후에 설명하겠습니다. 먼저 input_ids가 어떻게 생성되는지 살펴보겠습니다. 이를 위해서는 토크나이저의 중간 메소드를 살펴봐야 합니다.

 

다운 받은 파일들 내용을 살펴 보겠습니다.

 

 

 

 

 

 

tokenizer.json하고 vocab.txt 는 뭔지 잘 모르겠네요.. 왜 한문이 나오는지... ;;

 

Encoding

https://youtu.be/Yffk5aydLzg?si=-pDGz1WdrfhtchwK

 

 

Translating text to numbers is known as encoding. Encoding is done in a two-step process: the tokenization, followed by the conversion to input IDs.

 

텍스트를 숫자로 변환하는 것을 인코딩이라고 합니다. 인코딩은 토큰화와 입력 ID로의 변환이라는 2단계 프로세스로 수행됩니다.

 

As we’ve seen, the first step is to split the text into words (or parts of words, punctuation symbols, etc.), usually called tokens. There are multiple rules that can govern that process, which is why we need to instantiate the tokenizer using the name of the model, to make sure we use the same rules that were used when the model was pretrained.

 

앞서 살펴본 것처럼 첫 번째 단계는 텍스트를 일반적으로 토큰이라고 하는 단어(또는 단어의 일부, 구두점 기호 등)로 분할하는 것입니다. 해당 프로세스를 제어할 수 있는 여러 규칙이 있으므로 모델 이름을 사용하여 토크나이저를 인스턴스화하여 모델이 사전 훈련될 때 사용된 것과 동일한 규칙을 사용하는지 확인해야 합니다.

 

The second step is to convert those tokens into numbers, so we can build a tensor out of them and feed them to the model. To do this, the tokenizer has a vocabulary, which is the part we download when we instantiate it with the from_pretrained() method. Again, we need to use the same vocabulary used when the model was pretrained.

 

두 번째 단계는 해당 토큰을 숫자로 변환하는 것입니다. 이를 통해 토큰으로 텐서를 구축하고 모델에 제공할 수 있습니다. 이를 위해 토크나이저에는 from_pretrained() 메서드를 사용하여 인스턴스화할 때 다운로드하는 부분인 어휘가 있습니다. 다시 말하지만, 모델이 사전 훈련될 때 사용된 것과 동일한 어휘를 사용해야 합니다.

 

To get a better understanding of the two steps, we’ll explore them separately. Note that we will use some methods that perform parts of the tokenization pipeline separately to show you the intermediate results of those steps, but in practice, you should call the tokenizer directly on your inputs (as shown in the section 2).

 

두 단계를 더 잘 이해하기 위해 두 단계를 별도로 살펴보겠습니다. 토큰화 파이프라인의 일부를 개별적으로 수행하여 해당 단계의 중간 결과를 표시하는 일부 메서드를 사용하지만 실제로는 입력에서 직접 토크나이저를 호출해야 합니다(섹션 2 참조).

 

Tokenization

The tokenization process is done by the tokenize() method of the tokenizer:

 

토큰화 프로세스는 토크나이저의 tokenize() 메소드에 의해 수행됩니다.

 

from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("bert-base-cased")

sequence = "Using a Transformer network is simple"
tokens = tokenizer.tokenize(sequence)

print(tokens)

 

The output of this method is a list of strings, or tokens:

 

이 메소드의 출력은 문자열 또는 토큰 목록입니다.

 

['Using', 'a', 'transform', '##er', 'network', 'is', 'simple']

 

This tokenizer is a subword tokenizer: it splits the words until it obtains tokens that can be represented by its vocabulary. That’s the case here with transformer, which is split into two tokens: transform and ##er.

 

이 토크나이저는 하위 단어 토크나이저입니다. 즉, 어휘로 표현될 수 있는 토큰을 얻을 때까지 단어를 분할합니다. 이는 Transform과 ##er라는 두 개의 토큰으로 분할된 Transformer의 경우입니다.

 

From tokens to input IDs

The conversion to input IDs is handled by the convert_tokens_to_ids() tokenizer method:

 

입력 ID로의 변환은 Convert_tokens_to_ids() 토크나이저 메서드에 의해 처리됩니다.

 

ids = tokenizer.convert_tokens_to_ids(tokens)

print(ids)

 

[7993, 170, 11303, 1200, 2443, 1110, 3014]

 

 

These outputs, once converted to the appropriate framework tensor, can then be used as inputs to a model as seen earlier in this chapter.

 

이러한 출력은 일단 적절한 프레임워크 텐서로 변환되면 이 장의 앞부분에서 본 것처럼 모델에 대한 입력으로 사용될 수 있습니다.

 

✏️ Try it out! Replicate the two last steps (tokenization and conversion to input IDs) on the input sentences we used in section 2 (“I’ve been waiting for a HuggingFace course my whole life.” and “I hate this so much!”). Check that you get the same input IDs we got earlier!

 

✏️ 한번 사용해 보세요! 섹션 2에서 사용한 입력 문장에 마지막 두 단계(토큰화 및 입력 ID로 변환)를 복제합니다( “I’ve been waiting for a HuggingFace course my whole life.” and “I hate this so much!” ). 이전에 얻은 것과 동일한 입력 ID를 얻었는지 확인하세요!

 

 

 

Section 2에서 같은 문장으로 얻은 input_ids

 

 

두개의 ID가 다름. 이유는 섹션 2에서는 distilbert-base-uncased-finetuned-sst-2-english 모델을 사용했고 이번 장에서는

bert-base-cased 모델을 사용했기 때문. 모델이 다르기 때문에 ids 가 다르다.
 
참고로 섹션 2에서 얻은 ids 를 이번장에서 디코딩을 하면 이렇게 나옴.
 

 

 

Decoding

Decoding is going the other way around: from vocabulary indices, we want to get a string. This can be done with the decode() method as follows:

 

디코딩은 반대 방향으로 진행됩니다. 즉, 어휘 색인에서 문자열을 얻으려고 합니다. 이는 다음과 같이 decode() 메소드를 사용하여 수행할 수 있습니다.

 

decoded_string = tokenizer.decode([7993, 170, 11303, 1200, 2443, 1110, 3014])
print(decoded_string)
'Using a Transformer network is simple'

 

 

Note that the decode method not only converts the indices back to tokens, but also groups together the tokens that were part of the same words to produce a readable sentence. This behavior will be extremely useful when we use models that predict new text (either text generated from a prompt, or for sequence-to-sequence problems like translation or summarization).

 

decode 메소드는 인덱스를 다시 토큰으로 변환할 뿐만 아니라 동일한 단어의 일부인 토큰을 함께 그룹화하여 읽을 수 있는 문장을 생성합니다. 이 동작은 새 텍스트(프롬프트에서 생성된 텍스트 또는 번역이나 요약과 같은 시퀀스 간 문제)를 예측하는 모델을 사용할 때 매우 유용합니다.

 

By now you should understand the atomic operations a tokenizer can handle: tokenization, conversion to IDs, and converting IDs back to a string. However, we’ve just scraped the tip of the iceberg. In the following section, we’ll take our approach to its limits and take a look at how to overcome them.

 

이제 토큰화, ID로 변환, ID를 다시 문자열로 변환 등 토크나이저가 처리할 수 있는 원자성 작업을 이해해야 합니다. 그러나 우리는 빙산의 일각만을 긁어낸 것에 불과합니다. 다음 섹션에서는 한계에 대한 접근 방식을 살펴보고 이를 극복하는 방법을 살펴보겠습니다.

 

Summary

 

입력값은 텍스트이고 이는 모델이 알아볼 수 있도록 숫자로 바꾸어야 한다. 입력값은 token 으로 나뉘게 되고 각 토큰마다 ID 라고 하는 숫자로 매핑된다. 이 때 ID 화 하고 또 ID를 vocablary 화 하는 것은 모델이 사용했을 때와 같은 방법으로 해야 한다.

관련된 클래스는 AutoTokenizer, BertTokenizer 등이 있다.

tokenizer.save_pretrained()로 해당 정보를 저장할 수 있다.

tokenizer.convert_tokens_to_ids(), tokenizer.decode() 등의 메소드가 있다.

 

반응형

HF-NLP-USING 🤗 TRANSFORMERS : Models

2023. 12. 25. 05:10 | Posted by 솔웅


반응형

https://huggingface.co/learn/nlp-course/chapter2/3?fw=pt

 

Models - Hugging Face NLP Course

2. Using 🤗 Transformers 3. Fine-tuning a pretrained model 4. Sharing models and tokenizers 5. The 🤗 Datasets library 6. The 🤗 Tokenizers library 9. Building and sharing demos new

huggingface.co

 

Models

 

https://youtu.be/AhChOFRegn4?si=KjVrNIfDzk7o7NKr

 

 

In this section we’ll take a closer look at creating and using a model. We’ll use the AutoModel class, which is handy when you want to instantiate any model from a checkpoint.

 

이번 섹션에서는 모델을 생성하고 사용하는 방법을 자세히 살펴보겠습니다. 체크포인트에서 모델을 인스턴스화하려는 경우 편리한 AutoModel 클래스를 사용하겠습니다.

 

The AutoModel class and all of its relatives are actually simple wrappers over the wide variety of models available in the library. It’s a clever wrapper as it can automatically guess the appropriate model architecture for your checkpoint, and then instantiates a model with this architecture.

 

AutoModel 클래스와 모든 관련 클래스는 실제로 라이브러리에서 사용할 수 있는 다양한 모델에 대한 간단한 래퍼입니다. 체크포인트에 적합한 모델 아키텍처를 자동으로 추측한 다음 이 아키텍처로 모델을 인스턴스화할 수 있으므로 영리한 래퍼입니다.

 

However, if you know the type of model you want to use, you can use the class that defines its architecture directly. Let’s take a look at how this works with a BERT model.

 

그러나 사용하려는 모델 유형을 알고 있는 경우 해당 아키텍처를 직접 정의하는 클래스를 사용할 수 있습니다. 이것이 BERT 모델에서 어떻게 작동하는지 살펴보겠습니다.

 

Creating a Transformer

The first thing we’ll need to do to initialize a BERT model is load a configuration object:

 

BERT 모델을 초기화하기 위해 가장 먼저 해야 할 일은 구성 객체를 로드하는 것입니다.

 

from transformers import BertConfig, BertModel

# Building the config
config = BertConfig()

# Building the model from the config
model = BertModel(config)

 

이 코드는 Hugging Face Transformers 라이브러리를 사용하여 BERT(Bidirectional Encoder Representations from Transformers) 모델을 구성하고 초기화하는 예제입니다. 주로 모델의 설정(configuration)과 모델 인스턴스를 생성하는 과정을 보여줍니다.

 

설명:

  1. BertConfig(): BERT 모델의 설정을 생성합니다. 이 설정은 모델의 아키텍처, 하이퍼파라미터 등을 조절하는 데 사용됩니다. 여기서는 기본 설정을 사용하고 있습니다. 필요에 따라 다양한 설정을 조절하여 모델을 사용자 정의할 수 있습니다.
  2. BertModel(config): 이전에 생성한 설정을 사용하여 BERT 모델을 빌드합니다. 이 모델은 주어진 설정에 따라 BERT의 아키텍처를 가진 인스턴스로 초기화됩니다.

이 코드는 모델 구성과 초기화의 간단한 예제를 보여주고 있습니다. 실제로는 더 많은 설정을 튜닝하고, 특정 작업에 맞게 사전 훈련된 가중치를 로드하여 모델을 사용합니다.

 

The configuration contains many attributes that are used to build the model:

 

구성에는 모델을 빌드하는 데 사용되는 많은 속성이 포함되어 있습니다.

 

print(config)
BertConfig {
  [...]
  "hidden_size": 768,
  "intermediate_size": 3072,
  "max_position_embeddings": 512,
  "num_attention_heads": 12,
  "num_hidden_layers": 12,
  [...]
}

 

해석:

  • attention_probs_dropout_prob: 어텐션 계층의 드롭아웃 확률
  • classifier_dropout: 분류기 계층의 드롭아웃 확률 (현재는 null로 설정되어 있음)
  • hidden_act: 은닉 계층에서 사용되는 활성화 함수 (여기서는 GELU)
  • hidden_dropout_prob: 은닉 계층의 드롭아웃 확률
  • hidden_size: 은닉 계층의 차원 크기
  • initializer_range: 가중치 초기화 범위
  • intermediate_size: Transformer 모델의 중간(인터미디에이트) 계층 크기
  • layer_norm_eps: 레이어 정규화의 epsilon 값
  • max_position_embeddings: 최대 위치 임베딩의 길이
  • model_type: 모델의 유형 (여기서는 "bert")
  • num_attention_heads: 어텐션 헤드의 수
  • num_hidden_layers: 은닉 계층의 총 수
  • pad_token_id: 패딩 토큰의 식별자
  • position_embedding_type: 위치 임베딩의 유형 (여기서는 "absolute")
  • transformers_version: Transformers 라이브러리의 버전
  • type_vocab_size: 타입(예: 문장 A와 문장 B)의 수
  • use_cache: 결과를 캐시에 저장하여 재사용할지 여부
  • vocab_size: 어휘 크기

이러한 설정은 모델의 아키텍처와 학습 가능한 매개변수들에 대한 중요한 정보를 담고 있습니다.

 

 

 

 

While you haven’t seen what all of these attributes do yet, you should recognize some of them: the hidden_size attribute defines the size of the hidden_states vector, and num_hidden_layers defines the number of layers the Transformer model has.

 

아직 이러한 모든 속성의 기능을 보지는 못했지만 일부 속성은 인식해야 합니다. Hidden_size 속성은 Hidden_states 벡터의 크기를 정의하고 num_hidden_layers는 Transformer 모델의 레이어 수를 정의합니다.

 

Different loading methods

Creating a model from the default configuration initializes it with random values:

 

기본 구성에서 모델을 생성하면 임의의 값으로 초기화됩니다.

 

from transformers import BertConfig, BertModel

config = BertConfig()
model = BertModel(config)

# Model is randomly initialized!

 

이 코드는 Hugging Face Transformers 라이브러리를 사용하여 BERT(Bidirectional Encoder Representations from Transformers) 모델을 랜덤으로 초기화하는 예제입니다.

 

설명:

  1. BertConfig(): BERT 모델의 설정을 생성합니다. 여기서는 기본 설정을 사용하고 있습니다.
  2. BertModel(config): 이전에 생성한 설정을 사용하여 BERT 모델을 랜덤으로 초기화합니다. 이 모델은 주어진 설정에 따라 BERT의 아키텍처를 가진 인스턴스로 초기화됩니다.
  3. # 모델은 랜덤으로 초기화됐습니다!: 주석을 통해 모델이 랜덤으로 초기화되었음을 나타냅니다. 초기화된 모델은 사전 훈련된 가중치를 가지고 있지 않으며, 훈련되지 않은 상태에서 시작됩니다.

이 코드는 가중치가 랜덤으로 초기화된 BERT 모델을 생성하는 간단한 예제입니다. 일반적으로는 랜덤으로 초기화된 모델을 사용하기보다는 사전 훈련된 모델을 로드하여 특정 작업에 맞게 조정하는 것이 더 흔합니다.

 

The model can be used in this state, but it will output gibberish; it needs to be trained first. We could train the model from scratch on the task at hand, but as you saw in Chapter 1, this would require a long time and a lot of data, and it would have a non-negligible environmental impact. To avoid unnecessary and duplicated effort, it’s imperative to be able to share and reuse models that have already been trained.

 

이 상태에서 모델을 사용할 수 있지만 횡설수설이 출력됩니다. 먼저 훈련을 받아야 합니다. 당면한 작업에 대해 처음부터 모델을 훈련할 수 있지만 1장에서 본 것처럼 이 작업에는 오랜 시간과 많은 데이터가 필요하며 환경에 미치는 영향도 무시할 수 없습니다. 불필요하고 중복된 노력을 피하려면 이미 훈련된 모델을 공유하고 재사용할 수 있는 것이 필수적입니다.

 

Loading a Transformer model that is already trained is simple — we can do this using the from_pretrained() method:

 

이미 학습된 Transformer 모델을 로드하는 것은 간단합니다. from_pretrained() 메서드를 사용하면 됩니다.

 

from transformers import BertModel

model = BertModel.from_pretrained("bert-base-cased")

 

이 코드는 Hugging Face Transformers 라이브러리를 사용하여 사전 훈련된 BERT(Bidirectional Encoder Representations from Transformers) 모델을 로드하는 예제입니다.

 

설명:

  1. from transformers import BertModel: BERT 모델을 사용하기 위해 BertModel 클래스를 가져옵니다.
  2. BertModel.from_pretrained("bert-base-cased"): "bert-base-cased"라는 사전 훈련된 BERT 모델을 로드합니다. 이 모델은 대/소문자 구분을 유지한 상태로 사전에 학습되었습니다.

로드된 모델은 이미 사전 훈련된 가중치를 가지고 있으며, 텍스트 데이터에 대한 다양한 NLP 작업에서 사용할 수 있습니다. 이 모델은 주어진 입력에 대한 표현(representation)을 추출하거나 특정 작업에 맞게 미세 조정될 수 있습니다.

사전 훈련된 모델을 사용하면 높은 수준의 언어 이해 능력을 가진 모델을 간단하게 적용할 수 있습니다.

 

 

Note :

 

Hugging Face Transformers 라이브러리를 사용하여 사전 훈련된 트랜스포머 모델을 from_pretrained 메서드를 통해 로드할 때, 주로 두 가지 주요 구성 요소가 관련됩니다.

  1. config.json: 이 파일은 모델의 구성 설정을 포함합니다. 모델 아키텍처, 하이퍼파라미터 및 모델 동작을 정의하는 기타 설정과 관련된 정보를 포함합니다. 구성 파일은 모델을 사전 훈련할 때 사용된 설정과 동일한 설정으로 모델을 올바르게 초기화하는 데 필수적입니다. JSON 파일이며 쉽게 검사하거나 수정할 수 있습니다. 이 구성은 주로 BertConfig와 같은 클래스를 사용하여 로드됩니다.
  2. model.pth 또는 model.tf (또는 유사한 이름): 이 파일은 모델의 사전 훈련된 가중치를 포함합니다. 정확한 형식 및 확장자는 프레임워크(PyTorch, TensorFlow) 및 특정 모델 아키텍처에 따라 다를 수 있습니다. 가중치 파일에는 모델이 대량의 텍스트 데이터에서 사전 훈련 중에 미세 조정된 학습 매개변수가 포함되어 있습니다. 이 파일은 모델이 사전 훈련 중에 학습한 지식과 표현을 포착하는 부분입니다.

위의 경우 model.safetensors를 로드했지만, 일반적으로 가중치가 포함된 .bin, .h5 또는 .tf와 같은 확장자를 가진 파일을 볼 수 있습니다. 파일 확장자는 프레임워크 및 모델에 따라 달라질 수 있습니다. 

from_pretrained 메서드는 config 및 사전 훈련된 가중치를 모델에 로드합니다. 모델을 로드한 후 model을 출력하면 모델 아키텍처 및 구성에 관한 정보가 표시될 수 있습니다.

만약 config.json 및 model.safetensors와 같은 특정 파일이 있다면 이러한 파일의 내용을 확인하여 실제 구조와 내용을 확인하는 것이 좋습니다.

 

pretrained model의 config

 

 

 

As you saw earlier, we could replace BertModel with the equivalent AutoModel class. We’ll do this from now on as this produces checkpoint-agnostic code; if your code works for one checkpoint, it should work seamlessly with another. This applies even if the architecture is different, as long as the checkpoint was trained for a similar task (for example, a sentiment analysis task).

 

앞에서 본 것처럼 BertModel을 동등한 AutoModel 클래스로 대체할 수 있습니다. 체크포인트에 구애받지 않는 코드가 생성되므로 지금부터 이 작업을 수행하겠습니다. 코드가 하나의 체크포인트에서 작동한다면 다른 체크포인트에서도 원활하게 작동해야 합니다. 이는 체크포인트가 유사한 작업(예: 감정 분석 작업)에 대해 훈련된 한 아키텍처가 다르더라도 적용됩니다.

 

In the code sample above we didn’t use BertConfig, and instead loaded a pretrained model via the bert-base-cased identifier. This is a model checkpoint that was trained by the authors of BERT themselves; you can find more details about it in its model card.

 

위의 코드 샘플에서는 BertConfig를 사용하지 않고 대신 bert-base-cased 식별자를 통해 사전 훈련된 모델을 로드했습니다. 이는 BERT 작성자가 직접 교육한 모델 체크포인트입니다. 모델 카드에서 자세한 내용을 확인할 수 있습니다.

 

This model is now initialized with all the weights of the checkpoint. It can be used directly for inference on the tasks it was trained on, and it can also be fine-tuned on a new task. By training with pretrained weights rather than from scratch, we can quickly achieve good results.

 

이제 이 모델은 체크포인트의 모든 가중치로 초기화됩니다. 훈련된 작업에 대한 추론을 위해 직접 사용할 수 있으며, 새로운 작업에 대해 미세 조정할 수도 있습니다. 처음부터 훈련하는 것이 아니라 미리 훈련된 가중치로 훈련하면 빠르게 좋은 결과를 얻을 수 있습니다.

 

The weights have been downloaded and cached (so future calls to the from_pretrained() method won’t re-download them) in the cache folder, which defaults to ~/.cache/huggingface/transformers. You can customize your cache folder by setting the HF_HOME environment variable.

 

가중치는 ~/.cache/huggingface/transformers의 기본값인 캐시 폴더에 다운로드 및 캐시되었습니다(향후 from_pretrained() 메서드에 대한 호출이 다시 다운로드되지 않음). HF_HOME 환경 변수를 설정하여 캐시 폴더를 사용자 정의할 수 있습니다.

 

The identifier used to load the model can be the identifier of any model on the Model Hub, as long as it is compatible with the BERT architecture. The entire list of available BERT checkpoints can be found here.

 

모델을 로드하는 데 사용되는 식별자는 BERT 아키텍처와 호환되는 한 모델 허브에 있는 모든 모델의 식별자가 될 수 있습니다. 사용 가능한 BERT 체크포인트의 전체 목록은 여기에서 확인할 수 있습니다.

 

Saving methods

Saving a model is as easy as loading one — we use the save_pretrained() method, which is analogous to the from_pretrained() method:

 

모델을 저장하는 것은 모델을 로드하는 것만큼 쉽습니다. 우리는 from_pretrained() 메서드와 유사한 save_pretrained() 메서드를 사용합니다.

 

model.save_pretrained("directory_on_my_computer")

 

이 코드는 Hugging Face Transformers 라이브러리를 사용하여 모델을 지정된 디렉토리에 저장하는 예제입니다. 코드를 간단히 설명하겠습니다.

 

설명:

  • model: 저장하려는 모델 인스턴스입니다.
  • save_pretrained("directory_on_my_computer"): 모델을 지정된 디렉토리에 저장합니다. 여기서 "directory_on_my_computer"는 모델이 저장될 로컬 디렉토리의 경로를 나타냅니다.

이 코드를 실행하면 모델의 가중치 및 구성 설정이 지정된 디렉토리에 저장됩니다. 이렇게 저장된 모델은 나중에 from_pretrained 메서드를 사용하여 다시 로드할 수 있습니다. 이는 모델을 학습한 후 향후 사용이나 배포를 위해 모델 상태를 저장하는 일반적인 방법 중 하나입니다.

 

 

This saves two files to your disk:

 

이렇게 하면 디스크에 두 개의 파일이 저장됩니다.

 

ls directory_on_my_computer

config.json pytorch_model.bin

 

If you take a look at the config.json file, you’ll recognize the attributes necessary to build the model architecture. This file also contains some metadata, such as where the checkpoint originated and what 🤗 Transformers version you were using when you last saved the checkpoint.

 

config.json 파일을 살펴보면 모델 아키텍처를 구축하는 데 필요한 속성을 인식할 수 있습니다. 이 파일에는 체크포인트가 어디서 생성되었는지, 체크포인트를 마지막으로 저장했을 때 사용한 🤗 Transformers 버전과 같은 일부 메타데이터도 포함되어 있습니다.

 

The pytorch_model.bin file is known as the state dictionary; it contains all your model’s weights. The two files go hand in hand; the configuration is necessary to know your model’s architecture, while the model weights are your model’s parameters.

 

pytorch_model.bin 파일은 상태 사전으로 알려져 있습니다. 여기에는 모델의 모든 가중치가 포함됩니다. 두 파일은 서로 밀접하게 연관되어 있습니다. 모델의 아키텍처를 알기 위해서는 구성이 필요하며, 모델 가중치는 모델의 매개변수입니다.

 

Note: 두 파일의 내용을 보면 아래와 같습니다.

 

 

이 파일들의 사이즈를 보면 이렇습니다.

 

 

config 파일은 간단한 json 포맷으로 된 텍스트 파일이기 때문에 656 바이트 밖에 안 됩니다.

그런데 가중치값이 들어 있는 model.safetensors 파일은 413 메가 바이트 정도 됩니다.

이 정도 되면 어플리케이션만 잘 만들면 onDevice 에서 돌릴 수 있지 않을까요?

지금은 입력값으로 이 가중치 값들을 가지고 결과를 만들어 내는 연산이 너무 무거워서 안되는 건가?

Using a Transformer model for inference

Now that you know how to load and save a model, let’s try using it to make some predictions. Transformer models can only process numbers — numbers that the tokenizer generates. But before we discuss tokenizers, let’s explore what inputs the model accepts.

 

이제 모델을 로드하고 저장하는 방법을 알았으니 이를 사용하여 몇 가지 예측을 해보겠습니다. Transformer  모델은 토크나이저가 생성하는 숫자만 처리할 수 있습니다. 하지만 토크나이저에 대해 논의하기 전에 모델이 어떤 입력을 받아들이는지 살펴보겠습니다.

 

Tokenizers can take care of casting the inputs to the appropriate framework’s tensors, but to help you understand what’s going on, we’ll take a quick look at what must be done before sending the inputs to the model.

 

토크나이저는 입력을 적절한 프레임워크의 텐서에 캐스팅하는 작업을 처리할 수 있지만, 무슨 일이 일어나고 있는지 이해하는 데 도움이 되도록 입력을 모델에 보내기 전에 수행해야 할 작업을 간략하게 살펴보겠습니다.

 

Let’s say we have a couple of sequences:

 

몇 가지 시퀀스가 있다고 가정해 보겠습니다.

 

sequences = ["Hello!", "Cool.", "Nice!"]

 

The tokenizer converts these to vocabulary indices which are typically called input IDs. Each sequence is now a list of numbers! The resulting output is:

 

토크나이저는 이를 일반적으로 입력 ID라고 하는 어휘 색인으로 변환합니다. 이제 각 시퀀스는 숫자 목록입니다! 결과 출력은 다음과 같습니다.

 

encoded_sequences = [
    [101, 7592, 999, 102],
    [101, 4658, 1012, 102],
    [101, 3835, 999, 102],
]

 

This is a list of encoded sequences: a list of lists. Tensors only accept rectangular shapes (think matrices). This “array” is already of rectangular shape, so converting it to a tensor is easy:

 

이것은 인코딩된 시퀀스 목록입니다. a list of lists . Tensor는 직사각형 모양(행렬을 생각해 보세요)만 허용합니다. 이 "배열"은 이미 직사각형 모양이므로 텐서로 변환하는 것은 쉽습니다.

 

import torch

model_inputs = torch.tensor(encoded_sequences)

 

Using the tensors as inputs to the model

Making use of the tensors with the model is extremely simple — we just call the model with the inputs:

 

모델과 함께 텐서를 사용하는 것은 매우 간단합니다. 입력을 사용하여 모델을 호출하기만 하면 됩니다.

 

output = model(model_inputs)

 

 

While the model accepts a lot of different arguments, only the input IDs are necessary. We’ll explain what the other arguments do and when they are required later, but first we need to take a closer look at the tokenizers that build the inputs that a Transformer model can understand.

 

모델은 다양한 인수를 허용하지만 입력 ID만 필요합니다. 다른 인수의 기능과 필요한 시기는 나중에 설명하겠지만 먼저 Transformer 모델이 이해할 수 있는 입력을 작성하는 토크나이저를 자세히 살펴봐야 합니다.

 

 

Summary

 

AutoModel이나 BertModel() 등을 사용하면 랜덤한 가중치 값이 초기화 됨

pretrained model을 사용해서 train 된 가중치를 사용하려면 from_pretrained() 메소드를 사용.

그러면 config 파일과 가중치 파일을 가져온다. save_pretrained()를 사용하면 이 두 파일을 로컬에 저장할 수 있음

 

 

반응형