elevne's Study Note
Huggingface 공부 - (2: Huggingface 코드 사용해보기) 본문
Transformers, Huggingface는 NLP와 ML 프로젝트의 속도를 높이는 다양한 라이브러리와 도구를 갖춘 생태계로 빠르게 성장했다. Huggingface는 크게 Library, Hub 둘로 구성된다고 한다. Library는 코드를 제공하고, Hub는 사전훈련 모델 가중치, 데이터셋, 평가지표를 위한 Script 등을 제공한다고 한다.
전이학습은 Transformer의 성공을 견인한 주요 요소라고 한다. 사전훈련되 모델을 새로운 작업에 빠르게, 재사용하는 것이 가능해졌기 때문이다. Huggingface Hub에서는 20,000 개 이상의 무료 모델을 사용할 수 있고 Pipeline Class를 사용하여 단 한줄로 Test를 해볼 수 있다.
또, NLP task에서는 텍스트를 Token으로 분할하는 Tokenizing 단계를 거치게 되는데 Huggingfae Tokenizer은 Rust 기반의 Backend에서 매우 빠르게 Tokenizing을 진행해준다고 한다.
위에서 설명한 Huggingface API를 사용하여 간단하게 글 분류 Task를 수행해보았다. 사용한 데이터셋은 영어로 작성된 Tweet Message 모음이며 Anger, Disgust, Fear, Joy, Sadness, Surprise 여섯 개의 감정으로 글이 분류되어 있다.
from datasets import list_datasets, load_dataset
all_datasets = list_datasets()
print(len(all_datasets))
emotions = load_dataset('emotion')
print(emotions)
Huggingface datasets에서 제공하는 데이터는 총 15414 개가 있는 것을 확인할 수 있으며, emotions 객체를 print 하여 데이터셋이 어떻게 구성되어 있는지를 확인할 수 있다. 이 DatasetDict 객체는 일반 Dictionary 객체에 접근하듯이 개별 분할을 참조할 수 있다고 한다.
train_ds = emotions["train"]
print(train_ds)
print(len(train_ds))
참고) 만약 훈련에 필요한 Dataset이 Huggingface dataset에 없다면 다른 메서드를 사용해서 csv 파일 등의 데이터를 불러올 수 있다.
- csv: load_dataset("csv", data_files="~~~.csv")
- text: load_dataset("text", data_files="~~~.txt")
- json: load_dataset("json", data_files="my_file.json")
이제 Load 한 Data를 Pandas Dataframe으로 바꿔볼 수도 있다.
import pandas as pd
emotions.set_format(type="pandas")
df = emotions["train"][:]
df.head()
위 Dataframe에서는 Label이 정수 형식으로 출력되므로 features 속성으로 label을 선택해준 후 int2str() 메서드로 레이블 이름에 해당하는 새로운 열을 Dataframe에 추가해준다.
def label_int2str(row):
return emotions["train"].features["label"].int2str(row)
df["label_name"] = df["label"].apply(label_int2str)
df.head()
아래 코드로 간단하게 불러온 데이터셋의 분포를 확인해본다.
import matplotlib.pyplot as plt
df["label_name"].value_counts(ascending=True).plot()
plt.title("Classes")
plt.show()
원래 위와 같이 Label의 분포가 불균등할 때, 소수 Class를 Random하게 Oversampling, 다수 Class를 Random하게 Undersampling, 혹은 추가 데이터를 넣는 것이 필요하지만 이번 실습에서는 그냥 진행한다.
이제 emotions.reset_format()으로 원래 데이터 형태로 되돌려준 후, Tokenizing을 진행할 단계이다. Tokenizing 단계에서 어휘 사전을 크게 잡으면 신경망의 Parameter 역시 많이 필요해져 문제가 된다. 예를 들어 100만 개의 고유한 단어가 있고 해당 100만 차원의 입력 벡터를 신경망의 첫 번째 층에서 1000 차원의 벡터로 압축한다면 이는 벌써 10억 개의 가중치를 갖게 된다.... 모델 파라미터가 낭비되는 것은 피하는 것이 좋기에 어휘사전의 크기를 제한한다. 이 제한하는 일반적인 방법으로 드물게 등장하는 단어를 무시하는 방법이 있다. 예를 들어 어휘사전은 10만 차원 정도로만 구성하고 나머지 단어는 'unknown'으로 분류하여 UNK Token으로 Mapping 하는 것이다. 하지만 이러한 방법은 단어 Tokenizing 과정에서 중요한 정보를 잃게 되는데, 이 두 문제의 절충안이 바로 Subword Tokenization(부분단어 토큰화)라고 한다.
Subword Tokenization은 문자 토큰화와 단어 토큰화의 장점을 결합한 방법이라고 한다. 드물게 등장하는 단어를 더 작은 단위로 나누면 모델이 복잡한 단어나 철차 오류를 처리하기 용이하다고 한다. 다른 한 편으로는 입력 길이를 적절한 크기로 유지하기 위해 자주 등장하는 단어는 고유한 항목으로 유지하는 것이다. 이번 실습에서는 NLP 분야에서 널리 사용되는 Subword Tokenization 메서드 중 BERT, DistilBERT Tokenizer로 사용되는 WordPiece를 사용한다.
from transformers import AutoTokenizer
model_ckpt = "distilbert-base-uncased"
tokenizer = AutoTokenizer.from_pretrained(model_ckpt)
AutoTokenizer Class는 체크포인트 이름을 사용하여 모델의 설정, 사전훈련 모델의 가중치, 어휘 사전을 자동으로 추출하는 자동 클래스라고 한다.
text = "I am so sad..."
encoded_text = tokenizer(text)
print(encoded_text)
print(encoded_text.input_ids)
tokens = tokenizer.convert_ids_to_tokens(encoded_text.input_ids)
print(tokens)
print(tokenizer.convert_tokens_to_string(tokens))
전체 말뭉치를 Tokenizing 하기 위해 DatasetDict 객체의 map() 메서드를 사용할 수 있다.
def tokenize(batch):
return tokenizer(batch["text"], padding=True, truncation=True)
위 함수는 Tokenizer을 Sample Batch에 적용한다. padding=True로 지정하면 Batch에 있는 가장 긴 Sample의 크기에 맞춰 Sample을 0으로 Padding한다. truncation=True로 설정하면 Model 최대 문맥 크기에 맞춰 Sample을 잘라낸다.
emotions_encoded = emotions.map(tokenize, batched=True, batch_size=None)
map() 메서드는 말뭉치에 있는 모든 Sample에 개별적으로 작용하므로 batched=True로 설정하여 Tweet을 Batch로 Encoding 한다. batch_size=None으로 지정하면 전체 데이터셋이 하나의 배치로 Tokenize() 함수에 들어가게 되는 것이다.
Transformer 모델은 Feature Extractor로 사용하기 편하다고 한다. 훈련하는 동안 Body의 가중치는 Freeze하고 은닉 상태를 분류 모델의 특성으로 사용할 수 있는 것이다.
AutoTokenizer을 사용했던 것과 비슷하게 Model을 Load 할 때는 AutoModel Class를 사용할 수 있다.
from transformers import AutoModel
import torch
model_ckpt = "distilbert-base-uncased"
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = AutoModel.from_pretrained(model_ckpt).to(device)
Pytorch를 활용하여 위처럼 GPU 사용여부를 확인하고 Device를 지정해줄 수 있다.
이후 단계부터든 다음 시간에 진행하겠다!
'Machine Learning > NLP' 카테고리의 다른 글
Huggingface 공부 - (3-1: Huggingface 다중언어 개체명 인식) (0) | 2022.12.26 |
---|---|
Huggingface 공부 - (2-2: Huggingface 코드 사용해보기) (0) | 2022.12.15 |
Huggingface 공부 - Transformer (1: Attention Mechanism) (0) | 2022.12.11 |
KoBART 분석해보기 (2) (0) | 2022.11.26 |
KoBART 분석해보기 (1) (1) | 2022.11.24 |