23.06.15
DEVOTEE를 활성화 시키면
지금 작성한 커뮤니티 글에 대해 1개의 댓글을 달아줍니다.
버튼을 누르면 글 수정 시 ChatGPT가 작성한 댓글이 수정됩니다.
| 컨텐츠 유형 | 제목 | 저장일 | 삭제 |
|---|
본인인증 로그인에 실패하였습니다.
회원이 아니시거나 본인인증 등록이
완료되지 않은 사용자입니다.
다양한 트랜스포머 모델을 통일된 인터페이스로 사용할 수 있도록 지원하는 오픈소스 라이브러리
허깅페이스가 없다면 새로운 트랜스포머 모델이 공개될 때마다 어떤 인터페이스를 사용하며, 어떤 함수를 써야 하는지 일일이 다 찾아봐야 할 것
허깅페이스를 통해 우리는 사용하고자 하는 트랜스포머 모델을 불러오고, 학습시키고, 이를 통해 추론하기만 하면 된다.
!pip install transformers==4.40.1 datasets==2.19.0 huggingface_hub==0.23.0 -qqqfrom transformers import AutoTokenizer, AutoModel
text = "What is Huggingface Transformers?"
# BERT 모델 활용
bert_model = AutoModel.from_pretrained("bert-base-uncased")
bert_tokenizer = AutoTokenizer.from_pretrained('bert-base-uncased')
encoded_input = bert_tokenizer(text, return_tensors='pt')
bert_output = bert_model(**encoded_input)
# GPT-2 모델 활용
gpt_model = AutoModel.from_pretrained('gpt2')
gpt_tokenizer = AutoTokenizer.from_pretrained('gpt2')
encoded_input = gpt_tokenizer(text, return_tensors='pt')
gpt_output = gpt_model(**encoded_input)학습 모델을 탐색할 수 있는 모델 허브와 데이터셋을 가져올 수 있는 데이터셋 허브가 존재
허깅페이스 모델은 바디와 헤드로 구분되어 있다. 같은 바디를 사용하면서 헤드만 바꾸어 사용할 수도 있기 때문에 모델 활용시 각 작업에 맞게 따로 분리해서 불러온다.
#모델 아이디로 모델 불러오기
from transformers import AutoModel
model_id = 'klue/roberta-base'
model = AutoModel.from_pretrained(model_id)
#분류 헤드가 포함된 모델 불러오기
from transformers import AutoModelForSequenceClassification
model_id = 'SamLowe/roberta-base-go_emotions'
classification_model = AutoModelForSequenceClassification.from_pretrained(model_id)위 예제중 두번째는 텍스트 시퀀스 분류를 위한 헤드가 포함된 모델을 불러올때 사용하는 코드이다.
만약 여기서 model_id에 헤드가 없이 바디만 있는 모델 id를 넣는다면 warning이 뜨고 분류 헤드는 랜덤으로 초기화가 된다.
from transformers import AutoModelForSequenceClassification
model_id = 'klue/roberta-base'
classification_model = AutoModelForSequenceClassification.from_pretrained(model_id)토크나이저는 텍스트를 토큰 단위로 나누어 토큰을 id값으로 변환한다.
#토크나이저 불러오기
from transformers import AutoTokenizer
model_id = 'klue/roberta-base'
tokenizer = AutoTokenizer.from_pretrained(model_id)
#토크나이저 사용 예제
tokenized = tokenizer("토크나이저는 텍스트를 토큰 단위로 나눈다")
print(tokenized)
# {'input_ids': [0, 9157, 7461, 2190, 2259, 8509, 2138, 1793, 2855, 5385, 2200, 20950, 2],
# 'token_type_ids': [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]}
print(tokenizer.convert_ids_to_tokens(tokenized['input_ids']))
# ['[CLS]', '토크', '##나이', '##저', '##는', '텍스트', '##를', '토', '##큰', '단위', '##로', '나눈다', '[SEP]']
print(tokenizer.decode(tokenized['input_ids']))
# [CLS] 토크나이저는 텍스트를 토큰 단위로 나눈다 [SEP]
print(tokenizer.decode(tokenized['input_ids'], skip_special_tokens=True))
# 토크나이저는 텍스트를 토큰 단위로 나눈다token_type_ids는 첫번째 문장이면 0, 아니면 1을 나타내는 값이고 attention_mask값은 패딩 토큰인지 실제 토큰인지를 나타내는 값이다.
decode를 통해서 토큰단위로 나눈 문장을 다시 합칠수 있고, CLS, SEP는 문장의 시작과 끝을 나타내는 특수 토큰이다.
#토크나이저에 여러 문장이 들어가는 경우
first_tokenized_result = tokenizer(['첫 번째 문장', '두 번째 문장'])['input_ids']
tokenizer.batch_decode(first_tokenized_result)
# ['[CLS] 첫 번째 문장 [SEP]', '[CLS] 두 번째 문장 [SEP]']
second_tokenized_result = tokenizer([['첫 번째 문장', '두 번째 문장']])['input_ids']
tokenizer.batch_decode(second_tokenized_result)
# ['[CLS] 첫 번째 문장 [SEP] 두 번째 문장 [SEP]']첫번째 처럼 두 문장을 각각 list에 넣을수도 있고, 두 문장을 합쳐서 하나로 토크나이징 할 수도 있다.
##기 정의된 데이터셋 활용 (KLUE MRC)
from datasets import load_dataset
klue_mrc_dataset = load_dataset('klue', 'mrc')
# klue_mrc_dataset_only_train = load_dataset('klue', 'mrc', split='train')
##로컬 데이터 활용
from datasets import load_dataset
# 로컬의 데이터 파일을 활용
dataset = load_dataset("csv", data_files="my_file.csv")
# 파이썬 딕셔너리 활용
from datasets import Dataset
my_dict = {"a": [1, 2, 3]}
dataset = Dataset.from_dict(my_dict)
# 판다스 데이터프레임 활용
from datasets import Dataset
import pandas as pd
df = pd.DataFrame({"a": [1, 2, 3]})
dataset = Dataset.from_pandas(df)#데이터셋 다운로드
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
#불필요 컬럼 제거
klue_tc_train = klue_tc_train.remove_columns(['guid', 'url', 'date'])
klue_tc_eval = klue_tc_eval.remove_columns(['guid', 'url', 'date'])
klue_tc_train
#label_str 추가
klue_tc_label = klue_tc_train.features['label']
def make_str_label(batch):
batch['label_str'] = klue_tc_label.int2str(batch['label'])
return batch
klue_tc_train = klue_tc_train.map(make_str_label, batched=True, batch_size=1000)
klue_tc_train[0]
# {'title': '유튜브 내달 2일까지 크리에이터 지원 공간 운영', 'label': 3, 'label_str': '생활문화'}
#데이터셋 분할
train_dataset = klue_tc_train.train_test_split(test_size=10000, shuffle=True, seed=42)['test']
dataset = klue_tc_eval.train_test_split(test_size=1000, shuffle=True, seed=42)
test_dataset = dataset['test']
valid_dataset = dataset['train'].train_test_split(test_size=1000, shuffle=True, seed=42)['test']# 준비 과정
# dataset을 나누고 tokenize_function을 정의한다
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)
valid_dataset = valid_dataset.map(tokenize_function, batched=True)
test_dataset = test_dataset.map(tokenize_function, batched=True)
#학습 인자와 평가 함수 정의
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
)
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=valid_dataset,
tokenizer=tokenizer,
compute_metrics=compute_metrics,
)
trainer.train()
trainer.evaluate(test_dataset) # 정확도 0.84
#학습 모델 업로드
from huggingface_hub import login
login(token="본인의 허깅페이스 토큰 입력")
repo_id = f"본인의 아이디 입력/roberta-base-klue-ynat-classification"
trainer.push_to_hub(repo_id)# 파이프라인을 활용한 추론
from transformers import pipeline
model_id = "본인의 아이디 입력/roberta-base-klue-ynat-classification"
model_pipeline = pipeline("text-classification", model=model_id)
model_pipeline(dataset["title"][:5])
# 직접 추론
import torch
from torch.nn.functional import softmax
from transformers import AutoModelForSequenceClassification, AutoTokenizer
class CustomPipeline:
def __init__(self, model_id):
self.model = AutoModelForSequenceClassification.from_pretrained(model_id)
self.tokenizer = AutoTokenizer.from_pretrained(model_id)
self.model.eval()
def __call__(self, texts):
tokenized = self.tokenizer(texts, return_tensors="pt", padding=True, truncation=True)
with torch.no_grad():
outputs = self.model(**tokenized)
logits = outputs.logits
probabilities = softmax(logits, dim=-1)
scores, labels = torch.max(probabilities, dim=-1)
labels_str = [self.model.config.id2label[label_idx] for label_idx in labels.tolist()]
return [{"label": label, "score": score.item()} for label, score in zip(labels_str, scores)]
custom_pipeline = CustomPipeline(model_id)
custom_pipeline(dataset['title'][:5])
DEVOTEE를 활성화 시키면
지금 작성한 댓글에 AI가 댓글을 달아줍니다.