📌 서론
이번 글에서는 사전 학습된 모델(TinyBERT)을 허깅페이스에서 가져와서 IMDB 영화 리뷰 데이터셋으로 파인튜닝을 하고, 새로 학습된 모델을 AWS S3에 업로드하는 과정을 정리해볼것이다.
IMDB 데이터셋 로드 및 전처리
IMDB 영화 리뷰 데이터셋을 가져오자. 이 데이터셋은 영화 리뷰와 각 리뷰의 감정(sentiment)을 포함하고 있다.
## 데이터로드
import pandas as pd
data = pd.read_csv('https://raw.githubusercontent.com/laxmimerit/All-CSV-ML-Data-Files-Download/master/IMDB-Dataset.csv')
data.head()
그리고 데이터셋을 전처리하는데 필요한 라이브러리를 설치해주자
datasets 라이브러리 설치
Hugging Face의 datasets 라이브러리를 설치하는 명령이다. 이 라이브러리는 다양한 데이터셋을 쉽게 불러오고 처리할 수 있게 해준다.
!pip install datasets
다음 코드는 pandas DataFrame을 Hugging Face의 Dataset 형식으로 변환한다. 이렇게 변환함으로써 데이터를 더 쉽게 처리하고, 모델 학습에 적합한 형태로 관리할 수 있게 된다.
from datasets import Dataset
dataset = Dataset.from_pandas(data)
이렇게 처리한 데이터셋을 훈련/테스트 데이터로 나눠주고 확인해보자.
dataset = dataset.train_test_split(test_size=0.3)
dataset
DatasetDict({
train: Dataset({
features: ['review', 'sentiment'],
num_rows: 35000
})
test: Dataset({
features: ['review', 'sentiment'],
num_rows: 15000
})
})
- DatasetDict: 분할된 데이터셋을 딕셔너리 형태로 보여준다. 여기서 train과 test라는 두 개의 데이터셋이 생성되었음을 알 수 있다.
- features: 각 데이터셋의 컬럼을 의미하며, review와 sentiment 두 개의 특징을 포함하고 있다.
- num_rows: 각 데이터셋의 샘플 수를 나타낸다. 훈련 데이터셋에는 35,000개의 리뷰가 있고, 테스트 데이터셋에는 15,000개의 리뷰가 포함되어 있다.
# sentiment 의 긍/부정 갯수
data['sentiment'].value_counts()
sentiment
positive 25000
negative 25000
Name: count, dtype: int64
감정 라벨을 정수형으로 변환
다음 코드는 sentiment 라벨을 정수형(label)으로 변환하는 과정이다. BERT와 같은 머신러닝 모델은 입력 데이터로 텍스트나 카테고리 대신 숫자형 데이터를 필요로 하기 때문에, 라벨을 숫자로 매핑하여 모델이 이해할 수 있도록 변환하는 것이다.
label2id = {'negative':0, 'positive':1}
dataset = dataset.map(lambda x: {'label':label2id[x['sentiment']]})
dataset
map 함수를 사용해 sentiment 컬럼을 label 컬럼이라는 새로운 컬럼을 통해서 정수형으로 변환해줬다.
DatasetDict({
train: Dataset({
features: ['review', 'sentiment', 'label'],
num_rows: 35000
})
test: Dataset({
features: ['review', 'sentiment', 'label'],
num_rows: 15000
})
})
데이터 확인
dataset['train'][0]
{'review': "A tragically wonderful movie... brings us to a Japan that does not exist anymore. Despite Hollywood's technical expertise, I have yet to see a (hollywood) movie that can match the authenticity of the atmosphere in this small town by the river near the sea... Tom Cruise's The Last Samurai looked liked the last installment of the Lord of The Rings in trying to capture rural Old Japan.<br /><br />If you like serene but intense story lines, this is a must see film. It will be a respite from hollow flashy films much like the last 1000 blockbusters you saw. I think this is one of Kurosawa's better stories.<br /><br />Even if it's a movie about geishas and brothels and the complicated rules that govern life in such settings, it did not turn into a skin flick. The characters are full of depth and act with much intensity.",
'sentiment': 'positive',
'label': 1}
모델 불러오기
torch(PyTorch)란?
torch는 PyTorch 라이브러리로, Facebook에서 개발한 오픈소스 딥러닝 프레임워크다.
PyTorch는 tensor라는 데이터 구조를 사용하여 수학적 연산을 수행하며, 딥러닝 모델을 구축하고 학습시키는 데 매우 유용하다.
!pip install transformers torch
from transformers import AutoTokenizer
import torch
device = torch.device('cuda') if torch.cuda.is_available() else torch.device("cpu")
# Hugginc Face에서 tinybert 검색 -> huawei-noah 모델 선택
model = 'huawei-noah/TinyBERT_General_4L_312D'
tokenizer = AutoTokenizer.from_pretrained(model, use_fast=True)
tokenizer
- AutoTokenizer: AutoTokenizer는 다양한 사전 학습된 언어 모델에 맞는 토크나이저를 자동으로 불러올 수 있게 해주는 유틸리티다. 이 유틸리티는 모델 이름만 주어지면 그 모델에 맞는 토크나이저를 자동으로 찾아준다.
- torch.device(): 연산을 수행할 장치를 지정하는 역할을 한다. 딥러닝에서 연산을 가속하기 위해 GPU(CUDA)를 사용하는 것이 일반적이고 이 코드는 GPU가 사용 가능한지 확인하는 것이다. (만약 GPU가 있다면 cuda 장치를 사용하고, 없으면 cpu에서 연산을 수행한다.)
- model: 이 모델은 속도가 빠르고, 메모리 사용이 적어 파인튜닝(fine-tuning)에 적합하다.
- AutoTokenizer.from_pretrained(): 사전 학습된 모델에 맞는 토크나이저를 불러온다.
- use_fast=True: 더 빠른 토크나이저 구현을 사용하겠다는 옵션이다. 일반적으로 속도를 높이기 위해 fast tokenizer가 선호된다.
- 이 토크나이저는 나중에 텍스트 데이터를 입력받아, 모델이 처리할 수 있는 형식(숫자 벡터)으로 변환하는 역할을 한다.
review 텍스트를 토큰화
이제 리뷰 텍스트를 BERT 모델이 처리할 수 있도록 토큰화 해주는 함수를 만들어주자.
def tokenize(batch):
temp = tokenizer(batch['review'], padding=True, truncation=True, max_length=300)
return temp
- padding=True: 텍스트 데이터를 동일한 길이로 패딩 처리
- truncation=True: 맥스 토큰 갯수를 넘어가는 문장은 잘라낸다.
- max_length=300: 토큰화된 결과의 최대 길이를 300개 (300개 이상의 토큰은 자른다. 300개 이하는 패딩처리)
- batch['review']: batch는 IMDB 리뷰 데이터의 한 배치(batch)를 나타내며, 여기서 review는 리뷰 텍스트가 담긴 컬럼이다.
- batch는 여러 개의 리뷰가 포함된 데이터 묶음이다. 이를 한꺼번에 처리하는 이유는 배치(batch processing)를 통해 더 효율적으로 모델에 입력하기 위해서다.
dataset = dataset.map(tokenize, batched=True, batch_size=None)
dataset
위 코드는 각 배치에 대해 tokenize 함수가 적용돼서 리뷰 텍스트가 BERT 모델에 맞게 토큰화된다.
DatasetDict({
train: Dataset({
features: ['review', 'sentiment', 'label', 'input_ids', 'token_type_ids', 'attention_mask'],
num_rows: 35000
})
test: Dataset({
features: ['review', 'sentiment', 'label', 'input_ids', 'token_type_ids', 'attention_mask'],
num_rows: 15000
})
})
tokenize가 잘 적용됐는지 확인해보자.
dataset['train'][0]
모델 불러오기
이제 위에서 설정한 TinyBERT 모델을 감정 분석을 위한 문장 분류 모델로 불러온다. 감정 분석에서 positive와 negative 두 가지 범주로 분류를 수행할 것이다.
from transformers import AutoModelForSequenceClassification
# 숫자 레이블을 감정 상태로 매핑
id2label = {0:'negative', 1:'positive'}
# 사전 학습된 TinyBERT 모델을 감정 분석용으로 불러오기
model = AutoModelForSequenceClassification.from_pretrained(
model, # 사전 학습된 모델의 이름
num_labels=len(label2id), # 레이블 갯수(긍정/부정 총 2개)
label2id=label2id, # 레이블 문자열 데이터를 숫자로 매핑 딕셔너리
id2label=id2label
)
AutoModelForSequenceClassification은 Hugging Face에서 제공하는 텍스트 분류 모델 클래스로, 사전 학습된 BERT 기반 모델을 불러와 분류 작업에 맞게 재구성할 수 있다.
평가지표 설정
이제 모델을 평가할 라이브러리를 설치해주자.
evaluate는 모델 성능을 평가할 때 자주 사용하는 지표를 계산하는 라이브러리다. 모델이 얼마나 정확하게 예측하는지 평가할 때 자주 사용된다.
!pip install evaluate
import evaluate
import numpy as np
accuracy = evaluate.load('accuracy')
이제 위에서 만들어준 정확도를 기반으로 평가때 사용될 함수를 만들어주자.
다음 함수는 모델의 예측과 실제 레이블을 비교해서 정확도를 계산해준다.
def compute_metrics(eval_pred): # 평가지표
predctions, labels = eval_pred
predctions = np.argmax(predctions, axis=1) # 가장 높은 확률의 클래스로 변환
return accuracy.compute(predictions=predctions, references=labels) # 예측값, 실제 정답 값
모델 학습 설정
Hugging Face의 transformers 라이브러리와 PyTorch를 함께 설치하는 명령이다. PyTorch는 학습에 필요한 프레임워크이고, transformers는 사전 학습된 모델을 불러와 학습하는 데 사용된다.
!pip install 'transformers[torch]'
TrainingArguments 설정
학습을 위한 다양한 설정들을 정의해보자.
from transformers import Trainer, TrainingArguments
args = TrainingArguments(
output_dir='train_dir', # 학습 결과를 저장할 디렉토리
overwrite_output_dir=True,
num_train_epochs=3,
learning_rate=2e-5,
per_device_train_batch_size=32, # 각 디바이스당 학습 배치 크기
per_device_eval_batch_size=32, # 각 디바이스당 평가 배치 크기
eval_strategy='epoch' # 매 에포크마다 평가
)
그리고 Trainer를 설정해주자.
trainer = Trainer(
model=model,
args=args,
train_dataset=dataset['train'],
eval_dataset=dataset['test'],
compute_metrics=compute_metrics, # 평가 지표를 계산하는 함수
tokenizer=tokenizer # 텍스트를 토큰으로 변환하는 도구
)
위 변수들을 이용해서 실제로 모델을 학습시켜주자. (해당 코드는 나는 대략 두시간 걸렸다...)
trainer.train()
코드를 실행하면 모델 학습과 평가를 동시에 수행한다.
eval_strategy='epoch'로 설정되었기 때문에 매번 에포크 끝날 때마다 모델이 테스트 데이터셋에 대해 얼마나 잘 예측하는지 정확도를 계산한다.
학습이 완료되면 다음과 같이 디렉토리가 생성되고 각 폴더 안에 json 파일들도 잘 생성된 모습을 확인할 수 있다.
모델 평가/저장 및 파이프라인 생성
모델 평가
이제 학습된 모델을 평가해보자.
trainer.evaluate()
Trainer 객체에 정의된 평가 데이터셋(dataset['test'])을 사용하여 모델 성능을 평가한다.
loss가 꽤 적고 accuracy가 높은걸로 봐서 잘 학습된것같다.
이제 파인튜닝된 모델을 저장해보자
모델 저장
tinybert-sentiment-analysis 라는 이름의 폴더에 학습이 완료된 모델을 파일로 저장해보자.
trainer.save_model('tinybert-sentiment-analysis')
그럼 이렇게 폴더가 생기고 모델 가중치(pytorch_model.bin), 설정 파일(config.json), 그리고 토크나이저 설정 등이 저장된걸 확인할 수 있다.
텍스트 분류 파이프라인 생성
감정 분석을 위한 텍스트 분류 파이프라인을 설정해보자
from transformers import pipeline
classifier = pipeline('text-classification', model='tinybert-sentiment-analysis', device=device)
Hugging Face의 pipeline 함수는 다양한 자연어 처리 작업을 간편하게 수행할 수 있는 고수준 API다. 여기서는 텍스트 분류(text-classification) 작업을 위해 사용된다.
classifier는 감정 분석을 위한 텍스트 분류 모델이 되어, 입력된 텍스트를 긍정 또는 부정으로 분류할 수 있다.
모델 테스트
실제로 파이프라인이 잘 구축됐는지 확인해보자!
data = ['OMG, This movie is crazy.....!!!', 'you should never watch this movie. i wasted my time.']
classifier(data)
꽤 높은 정확도를 보이고 있다!
이렇게 파인튜닝한 모델을 AWS S3에 업로드해보자!
S3 업로드
boto3는 AWS 관련 python 라이브러리다. S3 버킷 생성/업로드, EC2 생성/삭제 등등 다양한 기능을 제공한다.
!pip install boto3
(이 다음 코드로 넘어가기 전에 aws cli 명령어를 설치해서 access key와 secret key를 설정해줘야한다!!)
S3 버킷 생성
AWS 콘솔에서 버킷을 생성할수도 있지만! boto3를 이용해서 파이썬 코드로도 생성할 수 있다.
import boto3
s3 = boto3.client('s3')
def create_s3_bucket(bucket_name):
try:
s3.create_bucket(
Bucket=bucket_name,
CreateBucketConfiguration={'LocationConstraint':'ap-northeast-2'}
)
print(f"Success to create s3 bucket Name: {bucket_name}")
except Exception as e:
print(e)
이렇게 bucket 생성 함수를 만들어주고 사용해보자.
create_s3_bucket('my-mlops')
버킷을 생성해주고 잘 생성됐는지 확인해보자.
s3.list_buckets()
위에서 정한 이름으로 잘 생성된걸 확인할 수 있다.
bucket에 모델 업로드
위에서 생성한 bucket에 파인튜닝한 모델을 업로드해보자.
import os
for root, dir, files in os.walk('tinybert-sentiment-analysis'):
print(root, dir, files, '\n')
for file_name in files:
file_path = os.path.join(root, file_name)
print(file_path)
bucket_name = 'my-mlops'
s3.upload_file(file_path, bucket_name, file_path)
- os.walk를 사용해서 폴더 구조를 유지하면서 파일을 업로드했다.
- s3.upload_file에서 key값(세번째 인자)으로 file_path를 해준 이유는 버킷에 폴더 형태로 업로드하기 위함이었다.
내 로컬파일에 있던 모델이 정상적으로 버킷에 업로드된걸 확인할 수 있다.
이렇게 허깅페이스에서 모델을 불러와서 커스텀 데이터셋으로 파인튜닝을 진행하고, 새로 학습한 모델을 S3 버킷에 업로드하는것까지 해봤다. 아마 시간이 된다면 S3 버킷에 있는 모델을 다운로드 받고 docker 기반 EC2에 배포하는것도 정리해봐야겠다.
'MLOps' 카테고리의 다른 글
Docker 기반 Airflow, MLFlow, FastAPI, Streamlit 적용한 MLOps 프로젝트 후기 (5) | 2024.10.12 |
---|---|
Docker로 mlflow 실행할때 OSError: [Errno 30] Read-only file system: '/mlflow' 에러 발생 (5) | 2024.10.09 |
Docker 환경에서 Airflow의 DAGs 테스트 (파이썬 코드, Slack Webhook, MLFlow) (3) | 2024.09.26 |
FastAPI와 Docker를 활용한 S3 모델 서빙 및 배포 방법 (5) | 2024.09.24 |
MLFlow로 머신러닝 모델 실험 관리 및 Tag로 stage 표시 (3) | 2024.09.22 |