๊ฐ์ ์ ์์ ์ฝ๋ https://colab.research.google.com/drive/13r94i6Fh4oYf-eJRSi7S_y_cen5NYkBm#scrollTo=OTsW-Wwi-X81
transformers: ์ฌ์ ํ๋ จ๋ ๋ชจ๋ธ(BERT, GPT-2 ๋ฑ)๊ณผ ํ ํฌ๋์ด์ (Tokenizer)๋ฅผ ์ ๊ณตํฉ๋๋ค.datasets: ๋ชจ๋ธ ํ์ต ๋ฐ ํ๊ฐ์ ํ์ํ ๋ค์ํ ๋ฐ์ดํฐ์
์ ์ฝ๊ฒ ๋ถ๋ฌ์ฌ ์ ์๊ฒ ํด์ค๋๋ค.!pip install transformers datasets
Hugging Face ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ ํน์ ์์ ์ ์ํํ๋ ๊ณผ์ ์ ํฌ๊ฒ ์ธ ๋จ๊ณ๋ก ๋๋ ์ ์์ต๋๋ค.
distilbert-base-uncased-finetuned-sst-2-english ๋ชจ๋ธ์ ์ฌ์ฉํฉ๋๋ค.AutoTokenizer**๋ฅผ ์ฌ์ฉํ๋ฉด, ํน์ ๋ชจ๋ธ ์ด๋ฆ(from_pretrained)๋ง ์ง์ ํด์ฃผ๋ฉด ํด๋น ๋ชจ๋ธ์ ๋ง๋ ํ ํฌ๋์ด์ ๋ฅผ ์๋์ผ๋ก ๋ถ๋ฌ์ ๋งค์ฐ ํธ๋ฆฌํฉ๋๋ค.AutoModelForSequenceClassification ๊ณผ ๊ฐ์ ํด๋์ค๋ฅผ ์ฌ์ฉํ์ฌ, ์ง์ ๋ ์ด๋ฆ์ ์ฌ์ ํ๋ จ๋ ๋ชจ๋ธ์ ๊ฐ๋จํ๊ฒ ๋ก๋ํ ์ ์์ต๋๋ค.from transformers import AutoTokenizer, AutoModelForSequenceClassification
checkpoint = "distilbert-base-uncased-finetuned-sst-2-english"
tokenizer = AutoTokenizer.from_pretrained(checkpoint)
model = AutoModelForSequenceClassification.from_pretrained(checkpoint)
argmax**๋ฅผ ํตํด ์ต์ข
์์ธก ๊ฒฐ๊ณผ๋ฅผ ํ์ธํ ์ ์์ต๋๋ค.import torch
raw_inputs = [
"I've been waiting for a HuggingFace course my whole life.",
"I hate this so much!",
]
# ํ ํฌ๋์ด์ ๋ก ๋ฌธ์ฅ ํ ํฐํ
inputs = tokenizer(raw_inputs, padding=True, truncation=True, return_tensors="pt")
# ๋ชจ๋ธ์ ์
๋ ฅ ์ ๋ฌํ์ฌ ์์ธก ์ํ
outputs = model(**inputs)
logits = outputs.logits
# ๊ฒฐ๊ณผ๋ฅผ ํ๋ฅ ๋ก ๋ณํ
predictions = torch.nn.functional.softmax(logits, dim=-1)
print(predictions)
# ๊ฐ์ฅ ๋์ ํ๋ฅ ์ ๊ฐ์ง ํด๋์ค(label) ํ์ธ
predicted_labels = torch.argmax(predictions, dim=1)
print(predicted_labels)
# label id๋ฅผ ์ค์ ์ด๋ฆ์ผ๋ก ๋ณํ
print([model.config.id2label[label_id] for label_id in predicted_labels.tolist()])
ํ ํฌ๋์ด์ ๋ ๋ชจ๋ธ์ ์ ๋ ฅ์ ์ ์ฒ๋ฆฌํ๋ ํต์ฌ์ ์ธ ์์์ ๋๋ค.
input_ids)**๋ก ๋งคํํฉ๋๋ค.attention_mask)**๋ฅผ ์์ฑํฉ๋๋ค.[CLS])์ด๋ ๋([SEP])์ ์๋ฆฌ๋ ํน์ ํ ํฐ์ ์ถ๊ฐํฉ๋๋ค.AutoTokenizer์ ์ฅ์ AutoTokenizer๋ from_pretrained()์ ๋ชจ๋ธ ์ด๋ฆ๋ง ์ ๋ฌํ๋ฉด, ํด๋น ๋ชจ๋ธ์ ๋ง๋ ํ ํฌ๋์ด์ ๋ฅผ ์๋์ผ๋ก ์ฐพ์ ๋ก๋ํด์ฃผ๋ฏ๋ก ์ค์๋ฅผ ์ค์ด๊ณ ํธ์์ฑ์ ๋์ฌ์ค๋๋ค.input_ids์ attention_mask๊ฐ ํฌํจ๋ ๋์
๋๋ฆฌ๋ฅผ ๋ฐํํฉ๋๋ค.return_tensors='pt': ๊ฒฐ๊ณผ๋ฅผ PyTorch ํ
์ ํํ๋ก ๋ฐํํฉ๋๋ค.padding=True: ๋ฐฐ์น(batch) ๋ด์์ ๋ฌธ์ฅ ๊ธธ์ด๋ฅผ ๋ง์ถ๊ธฐ ์ํด ๊ฐ์ฅ ๊ธด ๋ฌธ์ฅ์ ๊ธฐ์ค์ผ๋ก ๋๋จธ์ง ๋ฌธ์ฅ ๋ค์ ํจ๋ฉ ํ ํฐ์ ์ถ๊ฐํฉ๋๋ค.truncation=True: ๋ชจ๋ธ์ด ์ฒ๋ฆฌํ ์ ์๋ ์ต๋ ๊ธธ์ด๋ฅผ ์ด๊ณผํ๋ ๋ฌธ์ฅ์ ์๋ผ๋
๋๋ค.batch_decode ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ฉด, ๋ชจ๋ธ์ ์
๋ ฅ(input_ids)์ ๋ค์ ์๋์ ๋ฌธ์์ด๋ก ๋ณต์ํ ์ ์์ต๋๋ค. skip_special_tokens=True ์ต์
์ผ๋ก ํน์ ํ ํฐ์ ์ ์ธํ๊ณ ๋ณผ ์ ์์ต๋๋ค.# ํ ํฐํ ๊ณผ์ ํ์ธ
sequence = "Hugging Face Transformers is great!"
tokenized_output = tokenizer(sequence)
print(tokenized_output)
# {'input_ids': [101, 10372, 12111, 22558, 2003, 2307, 999, 102], 'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1]}
# input_ids๋ฅผ ๋ค์ ํ ํฐ์ผ๋ก ๋ณํ
tokens = tokenizer.convert_ids_to_tokens(tokenized_output['input_ids'])
print(tokens)
# ['[CLS]', 'hugging', 'face', 'transformers', 'is', 'great', '!', '[SEP]']
# ๋์ฝ๋ฉ
decoded_string = tokenizer.decode(tokenized_output['input_ids'], skip_special_tokens=True)
print(decoded_string)
# Hugging Face Transformers is great!
AutoModel์ ์ฅ์ AutoTokenizer์ ๋ง์ฐฌ๊ฐ์ง๋ก, AutoModel ํด๋์ค๋ฅผ ์ฌ์ฉํ๋ฉด ํน์ ์์
์ ๋ง๋ ๋ชจ๋ธ ์ํคํ
์ฒ๋ฅผ ์๋์ผ๋ก ๋ถ๋ฌ์ฌ ์ ์์ด ํธ๋ฆฌํฉ๋๋ค.AutoModelForSequenceClassification์ ๋ฌธ์ฅ ๋ถ๋ฅ ์์
์ ๋ง๋ ์ธ์ฝ๋ ๋ชจ๋ธ์ ํค๋(head)๊ฐ ์ถ๊ฐ๋ ํํ๋ก ๋ชจ๋ธ์ ๋ก๋ํฉ๋๋ค.** (dictionary unpacking) ๋ฌธ๋ฒ์ ์ฌ์ฉํ์ฌ model(**model_inputs)์ ๊ฐ์ด ๊ฐ๊ฒฐํ๊ฒ ๋ชจ๋ธ์ ์ ๋ฌํ ์ ์์ต๋๋ค.labels๋ฅผ ํจ๊ป ์ ๋ฌํ๋ฉด, ๋ชจ๋ธ์ด ์๋์ผ๋ก **์์ค(loss)**์ ๊ณ์ฐํ์ฌ ์ถ๋ ฅ์ ํฌํจ์์ผ ์ค๋๋ค. ์ด๋ PyTorch์ ํ์ต ๋ฃจํ๋ฅผ ๋งค์ฐ ๊ฐ๋จํ๊ฒ ๋ง๋ค์ด์ค๋๋ค.loss.backward()๋ฅผ ํธ์ถํ์ฌ ์ญ์ ํ๋ฅผ ์ํํ๊ณ ๋ชจ๋ธ์ ๊ฐ์ค์น๋ฅผ ์
๋ฐ์ดํธํ ์ ์์ต๋๋ค.# labels๋ฅผ ํจ๊ป ์ ๋ฌํ์ฌ loss ์๋ ๊ณ์ฐํ๊ธฐ
inputs = tokenizer(raw_inputs, padding=True, truncation=True, return_tensors="pt")
labels = torch.tensor([1, 0]) # Positive, Negative
outputs = model(**inputs, labels=labels)
print(f"Logits: {outputs.logits}")
print(f"Loss: {outputs.loss}") # loss๊ฐ ํจ๊ป ์ถ๋ ฅ๋จ
# loss๋ฅผ ์ด์ฉํ ์ญ์ ํ
loss = outputs.loss
loss.backward()
output_attentions=True, output_hidden_states=True ์ธ์๋ฅผ ์ค์ ํ๋ฉด, ๋ชจ๋ธ์ ๊ฐ ๋ ์ด์ด์์ ๊ณ์ฐ๋ **์ดํ
์
๊ฐ์ค์น(attention weights)**์ **์๋ ์ํ(hidden states)**๋ฅผ ์ถ๋ ฅ์ผ๋ก ์ป์ ์ ์์ต๋๋ค.# ์ดํ
์
๊ฐ์ค์น์ ์๋ ์ํ ์ถ๋ ฅํ๋๋ก ๋ชจ๋ธ ๋ก๋
model = AutoModelForSequenceClassification.from_pretrained(
checkpoint,
output_attentions=True,
output_hidden_states=True,
)
# ๋ชจ๋ธ ์คํ
outputs = model(**inputs)
# ์ถ๋ ฅ ํ์ธ (๋งค์ฐ ํฐ ํ
์๋ค์ด๋ฏ๋ก shape๋ง ํ์ธ)
print(f"์ฒซ ๋ฒ์งธ ์๋ ์ํ์ shape: {outputs.hidden_states[0].shape}")
print(f"์ฒซ ๋ฒ์งธ ์ดํ
์
๊ฐ์ค์น์ shape: {outputs.attentions[0].shape}")
์ฌ์ ํ๋ จ๋ ๋ชจ๋ธ์ ํน์ ์์ ๊ณผ ๋ฐ์ดํฐ์ ์ ๋ง๊ฒ ์ถ๊ฐ๋ก ํ์ต์ํค๋ ๊ณผ์ ์ ํ์ธํ๋์ด๋ผ๊ณ ํฉ๋๋ค. ๊ฐ์์์๋ IMDb ์ํ ๋ฆฌ๋ทฐ ๋ฐ์ดํฐ์ ์ ์ด์ฉํ ๊ฐ์ฑ ๋ถ์์ ์์๋ก ์ค๋ช ํฉ๋๋ค.
datasets ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ load_dataset ํจ์๋ก IMDb ๋ฐ์ดํฐ์
์ ์ฝ๊ฒ ๋ถ๋ฌ์ต๋๋ค.map ํจ์์ ํ ํฌ๋์ด์ ๋ฅผ ์ฌ์ฉํ์ฌ ์ ์ฒด ๋ฐ์ดํฐ์
์ ํ ๋ฒ์ ํ ํฐํํฉ๋๋ค. ์ด๋ batched=True ์ต์
์ ์ฌ์ฉํ๋ฉด ์ฒ๋ฆฌ ์๋๊ฐ ํฅ์๋ฉ๋๋ค.label ์ปฌ๋ผ์ ์ด๋ฆ์ labels๋ก ๋ณ๊ฒฝํฉ๋๋ค.set_format('torch')๋ฅผ ํตํด ๋ฐ์ดํฐ์
์ PyTorch ํ
์ ํ์์ผ๋ก ๋ณํํฉ๋๋ค.torch.utils.data.DataLoader๋ฅผ ์ฌ์ฉํ์ฌ ํ๋ จ ๋ฐ ๊ฒ์ฆ์ฉ ๋ฐ์ดํฐ ๋ก๋๋ฅผ ์์ฑํฉ๋๋ค.from datasets import load_dataset
# 1. ๋ฐ์ดํฐ์
๋ก๋ (GLUE ๋ฒค์น๋งํฌ์ MRPC ๋ฐ์ดํฐ์
์์)
raw_datasets = load_dataset("glue", "mrpc")
# 2. ํ ํฐํ ํจ์ ์ ์
def tokenize_function(examples):
return tokenizer(examples["sentence1"], examples["sentence2"], truncation=True)
# 3. map ํจ์๋ก ์ ์ฒด ๋ฐ์ดํฐ์
์ ํ ํฐํ ์ ์ฉ
tokenized_datasets = raw_datasets.map(tokenize_function, batched=True)
AdamW)์ ํ์ต๋ฅ ์ค์ผ์ค๋ฌ(get_scheduler)๋ฅผ transformers ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ ์ง์ ๊ฐ์ ธ์ ์ค์ ํฉ๋๋ค.Trainer ํด๋์ค ํ์ฉTrainer API๋ฅผ ์ ๊ณตํฉ๋๋ค.TrainingArguments: ํ์ต๋ฅ , ๋ฐฐ์น ํฌ๊ธฐ, ์ํญ ์, ๋ก๊ทธ ์ ์ฅ ๊ฒฝ๋ก ๋ฑ ํ์ต์ ํ์ํ ๋ชจ๋ ์ค์ ์ ์ ์ํ๋ ํด๋์ค์
๋๋ค.Trainer: ๋ชจ๋ธ, ํ์ต ์ค์ , ๋ฐ์ดํฐ์
, ํ ํฌ๋์ด์ , ๊ทธ๋ฆฌ๊ณ ์ฑ๋ฅ ํ๊ฐ ํจ์(compute_metrics)๋ฅผ ์ธ์๋ก ๋ฐ์ ํ์ต์ ๋ชจ๋ ๊ณผ์ ์ ์๋์ผ๋ก ๊ด๋ฆฌํฉ๋๋ค.trainer.train(): ์ด ํ ์ค์ ์ฝ๋๋ก ํ์ธํ๋์ ์์ํ ์ ์์ต๋๋ค.trainer.predict(): ํ์ต๋ ๋ชจ๋ธ์ ์ฌ์ฉํ์ฌ ์์ธก์ ์ํํฉ๋๋ค.EarlyStoppingCallback๊ณผ ๊ฐ์ ์ฝ๋ฐฑ์ ์ถ๊ฐํ์ฌ, ๊ฒ์ฆ ์ฑ๋ฅ์ด ๋ ์ด์ ๊ฐ์ ๋์ง ์์ ๋ ํ์ต์ ์กฐ๊ธฐ ์ข
๋ฃํ๋ ๋ฑ์ ๋ถ๊ฐ ๊ธฐ๋ฅ์ ์ฝ๊ฒ ๊ตฌํํ ์ ์์ต๋๋ค.from transformers import TrainingArguments, Trainer
# 1. ํ์ต์ ํ์ํ ์ธ์(argument)๋ค์ ์ ์
training_args = TrainingArguments(
output_dir="my_awesome_model", # ๊ฒฐ๊ณผ๋ฌผ์ด ์ ์ฅ๋ ๋๋ ํ ๋ฆฌ
evaluation_strategy="epoch", # ๋งค epoch ๋ง๋ค ํ๊ฐ ์งํ
num_train_epochs=3, # ์ด ํ์ต epoch
per_device_train_batch_size=16, # training์ฉ batch size
per_device_eval_batch_size=16, # evaluation์ฉ batch size
)
# 2. Trainer ๊ฐ์ฒด ์์ฑ
trainer = Trainer(
model,
training_args,
train_dataset=tokenized_datasets["train"],
eval_dataset=tokenized_datasets["validation"],
tokenizer=tokenizer,
)
# 3. ํ์ต ์์
trainer.train()
Trainer๋ ํ์ต ๊ณผ์ ์์ ์ค์ ๋ ๊ฒฝ๋ก์ ๋ชจ๋ธ์ ์ฒดํฌํฌ์ธํธ(checkpoint)๋ฅผ ์๋์ผ๋ก ์ ์ฅํฉ๋๋ค.AutoModel.from_pretrained()์ ์ด ์ฒดํฌํฌ์ธํธ ๊ฒฝ๋ก๋ฅผ ์ ๋ฌํ๋ฉด, ํ์ธํ๋๋ ๋ชจ๋ธ์ ๋์ค์ ๋ค์ ๋ถ๋ฌ์ ์ฌ์ฉํ ์ ์์ต๋๋ค.# ํ์ต์ด ์๋ฃ๋ ๋ชจ๋ธ์ ์ ์ฅ
trainer.save_model("my_final_model")
# ์ ์ฅ๋ ๋ชจ๋ธ์ ๋ค์ ๋ก๋ํ๊ธฐ
from transformers import AutoModelForSequenceClassification
loaded_model = AutoModelForSequenceClassification.from_pretrained("my_final_model")