본문으로 건너뛰기
홈
기술
기술 전체
프로그래밍68
컴퓨터 과학63
AI48
웹 개발36
인프라33
데이터31
소프트웨어 공학18
소개
← 목록으로AI › 언어 모델 › 응용

3. 트랜스포머 모델을 다루기 위한 허깅 페이스 트랜스포머 라이브러리

목차

허깅페이스

허깅페이스(Hugging Face)는 사전 학습된 모델과 데이터셋을 공유하는 Hub, 그리고 이를 다루는 라이브러리를 제공한다. 이 글에서는 영어 리뷰 한 문장을 긍정/부정으로 분류하면서 Transformers의 핵심 구성 요소가 어디에서 쓰이는지 살펴본다.

flowchart LR
    A[리뷰 문장] --> B[토크나이저<br/>텍스트를 토큰 ID로 변환]
    B --> C[분류 모델<br/>클래스별 점수 계산]
    C --> D[후처리<br/>레이블과 점수]
    E[Hub의 모델 저장소] --> B
    E --> C
  • Hub: 모델 가중치, 설정, 토크나이저 파일, 모델 카드가 함께 있는 저장소다.
  • Transformers: 모델과 토크나이저를 불러오고 추론·학습에 사용하는 라이브러리다.
  • Datasets: 데이터셋을 불러와 분할하고 전처리하는 라이브러리다.
  • Pipeline: 전처리, 모델 실행, 후처리를 묶어 간단히 추론하는 인터페이스다.

1. Pipeline으로 먼저 결과 확인하기

아래 모델은 영어 감성 분류용이다. 한글 문장을 입력해도 실행은 될 수 있지만, 그 결과를 한국어 감성 분석 성능으로 해석하면 안 된다. 실행할 때는 모델 파일을 내려받으므로 네트워크와 저장 공간이 필요하다.

from transformers import pipeline

model_id = "distilbert/distilbert-base-uncased-finetuned-sst-2-english"
classifier = pipeline("text-classification", model=model_id)

result = classifier("The explanation is clear and useful.")
print(result)  # label과 score를 담은 결과

score는 이 모델이 출력한 클래스 점수를 후처리한 값이다. 점수가 0.9라고 해서 실제 정답 확률이 반드시 90%인 것은 아니다. 사용하려는 도메인의 검증 데이터로 정확도와 점수의 보정 상태를 확인해야 한다. 특히 영화 리뷰용 모델로 고객 문의의 위험도를 판단하면 데이터의 주제와 레이블 의미가 다르다.

2. Pipeline 내부를 나누어 보기

AutoTokenizer는 해당 모델에 맞는 토큰화 규칙을 불러오고, AutoModelForSequenceClassification은 분류 헤드가 붙은 모델 구조와 가중치를 불러온다. 둘은 같은 모델 저장소에서 가져오는 것이 기본이다. 서로 다른 토크나이저와 모델을 조합하면 토큰 ID의 뜻이 달라져 잘못된 입력이 될 수 있다.

import torch
from transformers import AutoModelForSequenceClassification, AutoTokenizer

model_id = "distilbert/distilbert-base-uncased-finetuned-sst-2-english"
tokenizer = AutoTokenizer.from_pretrained(model_id)
model = AutoModelForSequenceClassification.from_pretrained(model_id)

inputs = tokenizer(
    "The explanation is clear and useful.",
    return_tensors="pt",
    truncation=True,
)

model.eval()
with torch.no_grad():
    logits = model(**inputs).logits

class_id = logits.argmax(dim=-1).item()
print(model.config.id2label[class_id])

토크나이저가 만든 input_ids는 단어 자체가 아니라 숫자 ID의 배열이다. 모델은 각 클래스에 대한 원점수인 logits를 만들고, 마지막 코드가 가장 큰 점수의 클래스 ID를 모델 설정의 레이블로 바꾼다. pipeline은 이런 연결을 대신 처리한다. 모델이 생성형인지, 분류용인지에 따라 필요한 AutoModelFor... 클래스와 출력 해석은 달라진다.

3. 데이터셋과 모델을 함께 볼 때

학습 또는 평가에는 입력 문장만이 아니라 정답 레이블, 분할 기준, 전처리 규칙이 필요하다. Datasets는 공개 데이터셋이나 로컬 파일을 읽을 수 있다. 아래는 분할이 이미 있는 데이터셋에서 한 건의 구조를 확인하는 예다.

from datasets import load_dataset

dataset = load_dataset("cornell-movie-review-data/rotten_tomatoes")
print(dataset.keys())
print(dataset["train"][0])

train, validation, test의 역할은 앞 장의 훈련 세트와 테스트 세트에서 다룬다. 모델을 바꾸거나 임계값을 고르는 데 test를 반복 사용하면 최종 성능을 과대평가할 수 있다. 또한 공개 모델을 사용하기 전에는 모델 카드의 언어, 학습 목적, 라이선스, 제한 사항을 읽어야 한다.

4. 모델을 선택할 때 확인할 것

  1. 과제: 텍스트 분류, 토큰 분류, 임베딩, 텍스트 생성 중 어떤 출력이 필요한가?
  2. 언어와 도메인: 학습에 사용된 언어·문서 유형이 실제 입력과 비슷한가?
  3. 입력 길이: 긴 문장이 잘리는 경우 중요한 정보가 사라지지 않는가?
  4. 실행 환경: 모델 크기, 메모리, 응답 시간, 다운로드 가능 여부가 맞는가?
  5. 재현성: 모델 저장소의 리비전과 라이브러리 버전을 기록했는가?

처음에는 pipeline으로 입력과 출력을 확인하고, 토큰 처리 방식이나 배치 추론을 조정해야 할 때 토크나이저와 모델을 직접 사용하면 된다. 모델이 실행된다는 사실과 내 데이터에 적합하다는 판단은 별개의 검증 단계다.

참고: Transformers 빠른 시작, Pipeline 문서, 예제 모델 카드, Datasets 불러오기

토큰화 결과를 직접 확인하기

pipeline은 편리하지만 입력이 어디서 잘리는지 보이지 않는다. 같은 문장을 AutoTokenizer로 처리해 ID와 토큰을 살펴보면 모델 앞단의 문제가 드러난다.

tokens = tokenizer("The explanation is clear and useful.", return_tensors="pt")
print(tokens["input_ids"].shape)
print(tokenizer.convert_ids_to_tokens(tokens["input_ids"][0]))

출력의 첫 차원은 배치 크기, 둘째 차원은 토큰 수다. 원래 단어 수보다 토큰 수가 많을 수 있고, 문장 시작·끝의 특수 토큰도 포함된다. 토큰 ID는 토크나이저의 사전 번호이므로 숫자 자체가 감정 점수는 아니다. 한국어 문장을 이 영어 모델의 토크나이저에 넣으면 짧은 문장도 많은 조각으로 나뉠 수 있다. 이렇게 쪼개진 입력을 두고 모델의 분류 점수가 높게 나왔다고 해서 한국어 성능을 인정할 수 없다.

배치 입력을 한꺼번에 보낼 때는 길이가 다른 문장을 맞추기 위해 짧은 문장에 패딩을 넣는다. attention_mask는 실제 토큰과 패딩을 구분한다. 긴 입력은 모델이 허용한 길이에 맞춰 잘릴 수 있다. 예를 들어 “제품은 좋지만 환불 절차는 불편했다”에서 앞부분만 남으면 전체 평가의 의미가 바뀐다. truncation=True를 설정했으면 실제로 잘린 비율과 잘린 문장을 표본으로 확인한다.

점수에서 품질 지표까지

모델의 logits는 두 클래스에 대한 원점수다. argmax는 가장 큰 원점수의 클래스를 고르고, softmax는 원점수를 합이 1인 값으로 바꾼다. 다음 코드는 한 문장의 내부 출력을 읽는 방법이다.

probabilities = torch.softmax(logits, dim=-1)[0]
for index, probability in enumerate(probabilities):
    print(model.config.id2label[index], float(probability))

예를 들어 NEGATIVE 0.08, POSITIVE 0.92가 나왔다면 모델은 두 후보 중 긍정 쪽에 더 큰 점수를 줬다는 뜻이다. 실제 데이터의 0.92 점수 답변 100개 중 92개가 맞는지는 보정(calibration) 평가를 해야 알 수 있다. pipeline의 score를 검증 없이 고객 문의의 자동 승인 기준으로 사용하는 것은 위험하다.

시험셋에서는 전체 정확도뿐 아니라 오분류의 방향을 본다. 가상의 리뷰 100건 중 긍정 80건, 부정 20건에서 모델이 모두 긍정이라고 했다면 정확도는 80%지만 부정 리뷰를 하나도 찾지 못한다. 부정 클래스를 찾는 목적이라면 부정 재현율이 0/20 = 0%인 모델이다. 혼동 행렬로 정답 긍정→예측 부정과 정답 부정→예측 긍정을 따로 세고, 비용이 큰 오류를 기준으로 임계값을 정한다. 임계값을 시험셋에서 계속 조정하면 성능 추정이 낙관적으로 변하므로 검증셋에서 선택하고 시험셋은 마지막에 한 번 사용한다.

모델을 바꾸기 전에 고칠 수 있는 것

사용자가 “불편하지는 않았지만 다시 사고 싶지는 않다”처럼 부정 표현이 여러 번 나오는 문장에서 틀린다면 입력 문장과 레이블 정의를 먼저 확인한다. 상품 평점, 서비스 재구매 의사, 감정 극성은 서로 다른 과제일 수 있다. 모델 카드에 적힌 학습 과제와 실제 요구가 다르면 더 큰 모델을 쓰기보다 맞는 과제의 모델과 데이터를 골라야 한다. 같은 문장이 학습과 시험에 중복되는지도 확인한다. 이런 점검을 통과한 뒤에야 미세 조정이나 새 모델 도입의 효과를 비교할 수 있다.

같은 카테고리의 글