AI Sparkup

최신 AI 쉽게 깊게 따라잡기⚡

Scikit-LLM 튜토리얼 – scikit-learn 파이프라인에 텍스트 요약 통합하기

scikit-llm은 LLM 기반 텍스트 처리를 기존 머신러닝 파이프라인에 직접 연결하는 라이브러리다. 이 튜토리얼은 HuggingFace의 무료 요약 모델을 sklearn 호환 트랜스포머로 래핑하고, 텍스트 요약→TF-IDF 벡터화→감성 분류기로 이어지는 엔드투엔드 파이프라인을 구성하는 방법을 다룬다.

왜 요약을 파이프라인에 넣나

대용량 텍스트를 TF-IDF로 직접 벡터화하면 차원이 폭발적으로 늘어난다. 요약 단계를 앞에 두면 긴 텍스트를 짧은 핵심 문장으로 압축한 뒤 벡터화·분류하므로 차원 감소 + 노이즈 제거 효과를 동시에 얻는다.

설치

pip install scikit-llm
pip install transformers==4.37.2  # HuggingFace 모델 로드에 필요

scikit-LLM은 기본적으로 OpenAI 모델을 사용한다. 비용이 부담된다면 HuggingFace 무료 모델(sshleifer/distilbart-cnn-12-6)을 사용할 수 있다.

1단계: HuggingFace 요약 트랜스포머 구현

HuggingFace 모델이 sklearn 파이프라인에서 동작하려면 BaseEstimator·TransformerMixin을 상속해야 한다.

from sklearn.base import BaseEstimator, TransformerMixin
from transformers import pipeline
import torch

class HuggingFaceSummarizer(BaseEstimator, TransformerMixin):
    def __init__(self, model_name="sshleifer/distilbart-cnn-12-6",
                 max_length=40, min_length=10):
        self.model_name = model_name
        self.max_length = max_length
        self.min_length = min_length
        self.summarizer = None
        self.device = 0 if torch.cuda.is_available() else -1

    def fit(self, X, y=None):
        # 프리트레인드 모델을 메모리에 로드
        if self.summarizer is None:
            self.summarizer = pipeline(
                "summarization", model=self.model_name, device=self.device
            )
        return self

    def transform(self, X):
        if self.summarizer is None:
            self.summarizer = pipeline(
                "summarization", model=self.model_name, device=self.device
            )
        results = self.summarizer(
            X,
            max_length=self.max_length,
            min_length=self.min_length,
            truncation=True
        )
        return [res['summary_text'] for res in results]

fit()은 모델을 로드하고, transform()은 텍스트 배열을 받아 요약 문자열 배열을 반환한다.

2단계: 샘플 데이터 준비

X_long_texts = [
    "3주째 이 청소기를 쓰고 있습니다. 처음엔 부속품 사용법을 잘 몰라 헤맸고 설명서도 불명확했습니다. 하지만 전동 브러시 작동법을 익힌 뒤부터 반려동물 털을 깔끔하게 제거할 수 있었습니다. 전반적으로 괜찮은 제품이지만 계단을 오를 때 좀 무겁습니다.",
    "배송이 나흘이나 지연돼 매우 답답했습니다. 주말 여행에 필요해서 주문했는데 겨우 도착한 배낭은 지퍼가 첫 사용에서 바로 걸렸습니다. 원단도 얇고 품질이 형편없어서 전액 환불을 요청할 예정입니다.",
]
y_labels = ["positive", "negative"]

3단계: 파이프라인 구성 및 학습

from sklearn.pipeline import Pipeline
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model import LogisticRegression

# 파이프라인 정의
# 변수명을 'classification_pipeline'으로 지정해 transformers.pipeline과 충돌 방지
classification_pipeline = Pipeline([
    ('summarizer', HuggingFaceSummarizer(max_length=30, min_length=10)),
    ('vectorizer', TfidfVectorizer()),  # 요약된 텍스트를 수치 벡터로 변환
    ('classifier', LogisticRegression()),
])

# 파이프라인 학습 (모델 다운로드 → 요약 → 벡터화 → 분류기 학습)
classification_pipeline.fit(X_long_texts, y_labels)
print("파이프라인 학습 완료!")

Pipeline.fit()을 호출하면 세 단계가 순서대로 실행된다:

  1. HuggingFaceSummarizer: 긴 텍스트를 GPU/CPU로 요약
  2. TfidfVectorizer: 요약 텍스트를 수치 벡터로 변환
  3. LogisticRegression: 분류기 학습

요약 결과 확인

summarizer = HuggingFaceSummarizer(max_length=30, min_length=10)
summarizer.fit(X_long_texts)
summaries = summarizer.transform(X_long_texts)

for original, summary in zip(X_long_texts, summaries):
    print(f"[원문] {original[:60]}...")
    print(f"[요약] {summary}\n")

출력 예시:

[요약] Overall, it's a solid machine, though a bit heavy to carry. At first, I struggled with the attachments.
[요약] The delivery was delayed by four days. The zipper snagged immediately. The fabric feels cheap and flimsy.

무료 경량 모델이므로 GPT-5.5나 Gemini 수준의 품질은 아니지만, 실전 데이터셋에서 더 강력한 모델로 교체하면 품질이 크게 향상된다.

활용 확장

  • 감성 분류 → 지원 티켓 자동 라우팅: 긴 고객 문의를 요약 후 담당팀으로 분류
  • 뉴스 아카이브 처리: 수천 건의 기사를 요약 후 주제별 분류
  • GridSearchCVmax_length, min_length, 분류기 파라미터를 함께 튜닝 가능

참고 자료



AI Sparkup 구독하기

최신 게시물 요약과 더 심층적인 정보를 이메일로 받아 보세요! (무료)