from transformers import AutoTokenizer
from pprint import pprint
tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased")
text = "I love NLP with Hugging Face!"
tokens = tokenizer(text)
pprint(tokens)
# {'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
# 'input_ids': [101, 1045, 2293, 17953, 2361, 2007, 17662, 2227, 999, 102],
# 'token_type_ids': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]}
| 구분 | 설명 | 필요 이유 |
|---|---|---|
| input_ids | 텍스트를 토큰화한 뒤, 각 토큰을 정수 ID로 변환한 값 | 모델이 텍스트를 숫자로 이해할 수 있게 함 |
| attention_mask | 어떤 토큰을 실제로 처리하고, 어떤 토큰을 무시해야 하는지 지정 (1=실제 토큰, 0=패딩) | 패딩으로 인해 모델이 혼란스러워하지 않도록 하기 위해 필요 |
| token_type_ids | 문장 쌍 입력 시, 각 토큰이 첫 번째 문장인지 두 번째 문장인지 구분 (0=문장1, 1=문장2) | 두 문장이 섞여 있어도 문장 경계를 구분하도록 도와줌 |
model_id = "klue/roberta-base"
tokenizer = AutoTokenizer.from_pretrained(model_id)
tokens = tokenizer("토크나이저는 텍스트를 토큰으로 나누어요")
pprint(tokens)
# {'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
# 'input_ids': [0,
# 9157,
# 7461,
# 2190,
# 2259,
# 8509,
# 2138,
# 1793,
# 2855,
# 6233,
# 4835,
# 10283,
# 2],
# 'token_type_ids': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]}
pprint(tokenizer.convert_ids_to_tokens(tokens["input_ids"]))
# ['[CLS]',
# '토크',
# '##나이',
# '##저',
# '##는',
# '텍스트',
# '##를',
# '토',
# '##큰',
# '##으로',
# '나누',
# '##어요',
# '[SEP]']
pprint(tokenizer.decode(tokens["input_ids"]))
# '[CLS] 토크나이저는 텍스트를 토큰으로 나누어요 [SEP]'
pprint(tokenizer.decode(tokens["input_ids"], skip_special_tokens=True))
# '토크나이저는 텍스트를 토큰으로 나누어요'
from datasets import load_dataset
klue_tc_train = load_dataset("klue", "ynat", split="train")
klue_tc_eval = load_dataset("klue", "ynat", split="validation")
klue_tc_train[100]
# {'guid': 'ynat-v1_train_00100',
# 'title': '트레이드 성사한 잠실구장 두 사령탑 불펜 투수가 필요했다',
# 'label': 5,
# 'url': 'https://sports.news.naver.com/news.nhn?oid=001&aid=0010244304',
# 'date': '2018.07.31 17:54'}
klue_tc_train.features["label"].names
# ['IT과학', '경제', '사회', '생활문화', '세계', '스포츠', '정치']
klue_tc_train = klue_tc_train.remove_columns(["guid", "url", "date"])
klue_tc_eval = klue_tc_eval.remove_columns(["guid", "url", "date"])
klue_tc_label = klue_tc_train.features["label"]
def addLabels(batch):
batch["label_str"] = klue_tc_label.int2str(batch["label"]) # 숫자 입력 시 해당하는 라벨이름 반환
return batch
klue_tc_train = klue_tc_train.map(addLabels, batched=True, batch_size=1000)
klue_tc_train[100]
# {'title': '트레이드 성사한 잠실구장 두 사령탑 불펜 투수가 필요했다',
# 'label': 5,
#. 'label_str': '스포츠'}
train_dataset = klue_tc_train.train_test_split(
test_size=10_000,
shuffle=True,
seed=42
)["test"]
val_test_dataset = klue_tc_eval.train_test_split(
test_size=1_000,
shuffle=True,
seed=42
)
val_dataset = val_test_dataset["train"].train_test_split(
test_size=1_000,
shuffle=True,
seed=42
)["test"]
test_dataset = val_test_dataset["test"]
import torch
import numpy as np
from transformers import Trainer, TrainingArguments, AutoModelForSequenceClassification, AutoTokenizer
def tokenize_function(examples):
return tokenizer(examples["title"], padding="max_length", truncation=True)
model_id = "klue/roberta-base"
model = AutoModelForSequenceClassification.from_pretrained(
model_id,
num_labels=len(train_dataset.features["label"].names)
)
tokenizer = AutoTokenizer.from_pretrained(model_id)
train_dataset = train_dataset.map(tokenize_function, batched=True)
val_dataset = val_dataset.map(tokenize_function, batched=True)
test_dataset = test_dataset.map(tokenize_function, batched=True)
!mkdir results
# 모델 학습에 필요한 파라미터
training_args = TrainingArguments(
output_dir="./results",
num_train_epochs=1,
per_device_train_batch_size=8,
per_device_eval_batch_size=8,
evaluation_strategy="epoch",
learning_rate=5e-5,
push_to_hub=False,
report_to="none",
)
# 정확도 계산 함수
def compute_metrics(eval_pred):
logits, labels = eval_pred
predictions = np.argmax(logits, axis=-1)
return {"accuracy": (predictions==labels).mean()}
trainer = Trainer(
model=model,
args=training_args,
train_dataset=train_dataset,
eval_dataset=val_dataset,
tokenizer=tokenizer,
compute_metrics=compute_metrics,
)
trainer.train()
trainer.evaluate(test_dataset)
# {'eval_loss': 0.46416130661964417,
# 'eval_accuracy': 0.85,
# 'eval_runtime': 26.822,
# 'eval_samples_per_second': 37.283,
# 'eval_steps_per_second': 4.66,
# 'epoch': 1.0}
*이 글은 제로베이스 데이터 취업 스쿨의 강의 자료 일부를 발췌하여 작성되었습니다.