TOP
class="layout-aside-left paging-number">
본문 바로가기
[파이썬 Projects]/<파이썬 Gen AI, LLM>

[LLM] 허깅페이스 라이브러리 사용법 익히기

by 기록자_Recordian 2024. 12. 27.
728x90
반응형
허깅페이스
 

[AI 플랫폼] 허깅페이스: AI와 머신러닝의 새로운 지평

허깅페이스란? 허깅페이스(Hugging Face)는 자연어 처리(NLP)와 머신러닝(ML) 커뮤니티에서 가장 혁신적이고 중요한 플랫폼 중 하나로 자리 잡고 있다. 허깅페이스는 주로 Transformer 모델을 중심으로

puppy-foot-it.tistory.com


허깅페이스 모델 활용하기

 

허깅페이스 트랜스포머 라이브러리를 사용하면 허깅페이스 모델 허브의 모델을 쉽게 불러와 사용할 수 있다. 허깅페이스에서는 모델을 바디와 헤드로 구분하는데, 모델의 바디만 불러올 수도 있고, 헤드와 함께 불러올 수도 있다.

  • 바디 : 헤드를 제외한 모델의 부분
  • 헤드 : 모델의 마지막 층으로 Task에 특화되어 작업에 맞는 층으로 된 부분

여기서는 klue/roberta 라는 모델을 불러와서 실습해보도록 한다.

출처: SELECT STAR

★ KLUE (출처: SELECT STAR)
클루(KLUE)는 한국어 언어모델의 공정한 평가를 위한 목적으로 8개 종류(뉴스 헤드라인 분류, 문장 유사도 비교, 자연어 추론, 개체명 인식, 관계 추출, 형태소 및 의존 구문 분석, 기계 독해 이해, 대화 상태 추적)의 한국어 자연어 이해 문제가 포함된 데이터 집합체이다. 영한 번역문이 아닌 일상생활에서 실사용되는 한국어 원문으로만 제작돼 한국어의 정확한 이해와 추론 능력을 평가할 수 있으며, 특히 다양한 한국어 언어모델이 동일한 평가선상에서 정확하게 비교될 수 있는 평가기준과 토대가 된다는 점에서 앞으로 한국어 자연어처리 분야의 발전을 앞당길 것으로 기대된다.
# 모델 아이디로 모델 불러오기
from transformers import AutoModel
model_id = 'klue/roberta-base'
model = AutoModel.from_pretrained(model_id)
  • AutoModel: 모델의 바디를 불러오는 클래스. from_pretrained() 메서드에서 인자로 받는 model_id에 맞춰 적절한 클래스를 가져온다.
  • model_id가 허깅페이스 모델 허브의 저장소 경로인 경우 모델 허브에서 모델을 다운로드하고, 로컬 경로인 경우 지정한 로컬 경로에서 모델을 불러온다.
  • klue/roberta-base: RoBERTa 모델을 한국어로 학습한 모델이며, RoBERTa는 구글의 BERT를 개선한 모델이다.

[BERT]

 

[NLP 모델] BERT(Bidirectional Encoder Representations from Transformers)란?

BERT(Bidirectional Encoder Representations from Transformers)는 자연어 처리(NLP) 분야에서 혁신적인 도구로 자리 잡은 모델이다. BERT는 2018년 구글이 발표한 모델로, NLP 작업에서 인간 수준의 성능을 구현하는

puppy-foot-it.tistory.com

 

허깅페이스 모델을 저장할 때 config.json 파일이 함께 저장되는데, 해당 설정 파일에는

  • 모델의 종류(model_type)
  • 설정 파라미터(num_attention_heads, num_hidden_layers 등)
  • 어휘 사전 크기(vocab_size)
  • 토크나이저 클래스(tokenizer_class) 등

이 저장된다. AutoModel과 AutoTokenizer 클래스는 config.json 파일을 참고해 적절한 모델과 토크나이저를 불러온다.

AutoModel 클래스가 저장소의 모델이 어떤 계열의 모델인지 알 수 있는 것은 이 때문이다.

from transformers import AutoConfig

# Hugging Face의 klue/roberta-base 모델의 설정을 불러옵니다
model_name = "klue/roberta-base"
config = AutoConfig.from_pretrained(model_name)

# config.json 내용을 출력합니다
print(config.to_json_string())

 

이번에는 텍스트 분류 헤드가 붙은 모델을 불러와 본다.

# 분류 헤드가 포함된 모델 불러오기
from transformers import AutoModelForSequenceClassification
model_id = 'SamLowe/roberta-base-go_emotions'
classification_model = AutoModelForSequenceClassification.from_pretrained(model_id)

▶ 이를 실행하면 모델 허브의 SamLowe/roberta-base-go_emotions 저장소에서 텍스트 분류 모델을 내려받아 classification_model 변수에 저장한다.

AutoModelForSequenceClassification 클래스는 텍스트 시퀀스 분류를 위한 헤드가 포함된 모델을 불러올 때 사용하는 클래스다.

★SamLowe/roberta-base-go_emotions
다중 레이블 분류를 위해 go_emotions 데이터세트를 사용하여 roberta-base 에서 학습된 모델이다.
go_emotions는 Reddit 데이터를 기반으로 하며 28개의 레이블이 있습니다. 이는 하나 또는 여러 개의 레이블이 주어진 입력 텍스트에 적용될 수 있는 다중 레이블 데이터 세트이므로 이 모델은 주어진 입력 텍스트에 대해 28개의 '확률' 부동 소수점 출력이 있는 다중 레이블 분류 모델이다.
이 모델은 입력 문장이 어떤 감성을 나타내는지 분류하는데, 예를 들어 입력 문장에 감탄, 즐거움, 화 등과 같은 감정이 포함돼 있는지를 분류한다.

 

분류 헤드가 어떤 감정을 어떻게 분류하는지 알기 위해서는 역시 저장소의 config.json 파일에서 확인할 수 있다.

SamLowe/roberta-base-go_emotions config.json 일부 내용

 

이번에는 텍스트 분류를 위한 아키턱체에 모델 바디만 불러와 본다.

AutoModelForSequenceClassification 클래스를 사용해 모델 바디 부분의 파라미터만 있는 klue/roberta-base 저장소의 모델을 불러온다.

# 분류 헤드가 랜덤으로 초기화된 모델 불러오기
from transformers import AutoModelForSequenceClassification
model_id = 'klue/roberta-base'
classification_model = AutoModelForSequenceClassification.from_pretrained(model_id)

위 코드를 실행하면 하단의 경고가 발생한다.

Some weights of RobertaForSequenceClassification were not initialized from the model checkpoint at klue/roberta-base and are newly initialized: ['classifier.dense.bias', 'classifier.dense.weight', 'classifier.out_proj.bias', 'classifier.out_proj.weight'] You should probably TRAIN this model on a down-stream task to be able to use it for predictions and inference.
▶ RobertaForSequenceClassification의 일부 가중치는 klue/roberta-base의 모델 체크포인트에서 초기화되지 않았으며, 새로 초기화되었습니다: ['classifier.dense.bias', 'classifier.dense.weight', 'classifier.out_proj.bias', 'classifier.out_proj.weight'] 이 모델을 예측 및 추론에 사용할 수 있도록 다운스트림 작업에서 훈련시켜야 할 것입니다.

 

위 의미는 바디 부분은 klue/roberta-base 모델에서 가져왔지만 분류 헤드는 랜덤으로 초기화된 상태이므로, 현재 상태에서는 분류 헤드가 학습되지 않았기 때문에 의미 있는 분류를 하지 못한다. 그렇기 때문에 그대로 사용해서는 안 되고 추가 학습 이후에 사용하라는 것이다.

 

분류 헤드를 학습해 분류 모델을 만들기 위해 한국어 데이터를 불러와 기사를 적절한 카테고리로 분류하는 모델을 만들어 본다.


토크나이저 활용하기

 

토크나이저는 텍스트를 토큰 단위로 나누고 각 토큰을 대응하는 토큰 아이디로 변환한다. 필요한 경우 특수 토큰을 추가하는 역할도 한다. 토크나이저 역시 학습 데이터를 통해 아휘 사전을 구축하기 때문에 일반적으로 모델과 함께 저장하며, 허깅페이스 모델 저장소 아이디를 통해 불러올 수 있다. 허깅페이스 허브에서 모델과 토크나이저를 불러오는 경우 동일한 모델 아이디로 맞춰야 한다.

# 토크나이저 불러오기
from transformers import AutoTokenizer
model_id = 'klue/roberta-base'
tokenizer = AutoTokenizer.from_pretrained(model_id)

 

# 토크나이저 사용하기
#1
tokenized = tokenizer("토크나이저는 텍스트를 토큰 단위로 나눈다")
print(tokenized)

#2
print(tokenizer.convert_ids_to_tokens(tokenized['input_ids']))

#3
print(tokenizer.decode(tokenized['input_ids']))

#4
print(tokenizer.decode(tokenized['input_ids'], skip_special_tokens=True))

#1 토크나이저에 텍스트를 입력하면

  • 토큰 아이디의 리스트인 input_ids
  • 토큰이 실제 텍스트인지 아니면 길이를 맞추기 위해 추가한 패딩 인지 알려주는 attention_mask
  • 토큰이 속한 문장의 아이디를 알려주는 token_type_ids

를 반환한다.

#2 input_ids는 토큰화했을 때 각 토큰이 토크나이저 사전의 몇 번째 항목인지를 나타낸다. input_ids의 첫 번째 항목은 0이고 두 번째 항목은 9157인데, 각각 [CLS]와 '토크'에 대응되는 것을 확인할 수 있다.

#3 attention_mask가 1이면 패딩이 아닌 실제 토큰임을 의미한다. token_type_ids가 0이면 일반적으로 첫 번째 문장임을 의미한다. 토큰 아이디를 다시 텍스트로 돌리고 싶다면 토크나이저 decode 메서드를 사용하면 된다.

#4 decode 메서드 사용 시, 만약 특수 토큰을 제외하고 싶다면 skip_special_tokens 인자를 True로 설정하면 된다.

 

토크나이저는 한 번에 여러 문장을 처리할 수도 있다.

# 토크나이저에 여러 문장 넣기
tokenizer(['첫 번째 문장', '두 번째 문장'])

▶ 출력 결과를 확인해 보면 input_ids, token_type_ids, attention_mask 모두 각 문장을 토큰화해 2개의 리스트를 반환한 것을 확인할 수 있다.

 

예를 들어 2개의 문장이 서로 원인과 결과 관계인지 학습시키는 경우처럼, 한 번에 2개의 문장을 넣어야 할 경우, 두 문장을 한 번에 모델에 입력해야 한다. 이때 2개의 문장이 하나의 데이터라는 것을 표시하기 위해 한 번 더 리스트로 감싸준다.

# 하나의 데이터에 여러 문장이 들어가는 경우
tokenizer([['첫 번째 문장', '두 번째 문장']])

▶ 출력 결과를 확인해 보면 하나의 결과만 반환하는 것을 확인할 수 있다.

 

[ batch_decode() ]

토크나이저의 batch_decode() 메서드를 사용하면 input_ids 부분의 토큰 아이디를 문자열로 복원할 수 있다.

기본적으로 토큰화를 하면 [CLS] 토큰으로 문장을 시작하고 [SEP] 으로 문장을 끝내는데, 2개의 문장을 한 번에 토큰화하면 [SEP]으로 두 문장을 구분한다.

# 토큰 아이디를 문자열로 복원1
first_tokenized_result = tokenizer(['첫 번째 문장', '두 번째 문장'])['input_ids']
tokenizer.batch_decode(first_tokenized_result)

# 토큰 아이디를 문자열로 복원2
second_tokenized_result = tokenizer([['첫 번째 문장', '두 번째 문장']])['input_ids']
tokenizer.batch_decode(second_tokenized_result)

 

[token_type_ids]

토큰화 결과 중 token_type_ids는 문장을 구분하는 역할을 한다. BERT는 학습할 때 2개의 문장이 서로 이어지는지 맞추는 NSP(Next Sentence Prediction) 작업을 활용하는데, 이를 위해 문장을 구분하는 코튼 타입 아이디를 만들었다.

# BERT 토크나이저와 RoBERTa 토크나이저
#1
bert_tokenizer = AutoTokenizer.from_pretrained('klue/bert-base')
print('bert_tokenizer:', bert_tokenizer([['첫 번째 문장', '두 번째 문장']]))

#2
roberta_tokenizer = AutoTokenizer.from_pretrained('klue/roberta-base')
print('roberta_tokenizer:', roberta_tokenizer([['첫 번째 문장', '두 번째 문장']]))

#3
en_roberta_tokenizer = AutoTokenizer.from_pretrained('roberta-base')
print('en_roberta_tokenizer:', en_roberta_tokenizer([['first sentence', 'second sentence']]))

  • #1 BERT 모델의 토크나이저를 불러오면 문장에 따라 토큰 타입 아이디를 구분한다. 이 모드에서 klue/bert-base 토크나이저를 사용하는 경우 첫 번째 문장의 토큰 타입 아이디는 0, 두 번째 토큰 타입 아이디는 1이다.
  • #2 klue/roberta-base 토크나이저를 사용하는 경우 token_type_ids가 모두 0인 것을 볼 수 있는데, RoBERTa 계열 모델의 경우 NSP 작업을 학습 과정에서 제거했기 때문에 문장 토큰 구분이 필요 없다.
  • #3 영어 버전의 원본 roberta-base 토크나이저로 영어 문장을  토큰화하면 결과에 token_type_ids 항목 자체가 없는 것을 확인할 수 있다.

[attention_mask]

attention_mask는 해당 토큰이 패딩 토큰인지 실제 데이터인지에 대한 정보를 담고 있다.

  • 패딩: 모델에 입력하는 토큰 아이디의 길이를 맞추기 위해 추가하는 특수 토큰. 토크나이저의 padding 인자에 'longest'를 입력하면 입력한 문장 중 가장 긴 문장에 맞춰 패딩 토큰을 추가한다.
# attention_mask 확인
tokenizer(['첫 번째 문장은 짧다', '두 번째 문장은 첫 번째 문장보다 길다'], padding='longest')

▶ 더 긴 문장에 맞춰 패딩 토큰을 추가하여 input_ids에서 첫 번째 문장에 패딩 토큰(패딩 아이디=1)이 6개 추가된 것을 확인할 수 있고 attention_mask에는 패딩 토큰을 나타내는 숫자 0이 6개 붙은 것을 확인할 수 있다.


데이터셋 활용하기

 

dataset 라이브러리를 사용하면 허깅페이스 허브의 데이터셋을 코드로 불러올 수 있다.

다음은 KLUE 데이터셋의 서브셋 중 하나인 MRC 데이터셋을 내려받는 코드이다.

# 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')

▶ load_dataset 함수는 데이터셋을 불러오는 함수로, 데이터셋의 이름인 klue와 서브셋 이름인 mrc를 해당 함수에 인자로 전달해서 MRC 데이터셋을 내려받는다. 만약 유형이 train인 데이터만 받고 싶다면 load_dataset() 함수에 split='train' 인자를 입력하면 된다.

klue_mrc_dataset

▶ 데이터셋에는 학습(train)과 검증(validation) 유형의 데이터가 각각 17554, 5841개 있으며 제목(title), 내용(context), 질문(question)과 정답(answer) 등의 칼럼이 있다.

 

만약 로컬에 있는 파일이나 파이썬 객체를 받아 데이터셋으로 사용하고 싶다면 아래와 같이 입력하면 된다.

# 로컬의 데이터 활용하기
from datasets import load_dataset
# 로컬의 csv 데이터 파일 활용
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)

다음 내용

 


[출처]

LLM을 활용한 실전 어플리케이션 개발

https://velog.io/@redqueen12

https://open.selectstar.ai/ko/klue

허깅페이스 홈페이지

728x90
반응형