23.06.15
DEVOTEE를 활성화 시키면
지금 작성한 커뮤니티 글에 대해 1개의 댓글을 달아줍니다.
버튼을 누르면 글 수정 시 ChatGPT가 작성한 댓글이 수정됩니다.
| 컨텐츠 유형 | 제목 | 저장일 | 삭제 |
|---|
본인인증 로그인에 실패하였습니다.
회원이 아니시거나 본인인증 등록이
완료되지 않은 사용자입니다.
안녕하세요, Devocean Openlab에 참여하게 된 Juan입니다.
이번 4회차 모임에서는 지난주 회의를 통해 도출된 개인화 스팸 문자 필터링 On-Device LLM 프로젝트를 본격적으로 추진하기 위해,
데이터 전처리 파이프라인 검토와 학습 프레임워크 구축을 중심으로 진행하였습니다.
아래와 같은 파이프라인으로 이번 스팸 문자 On-Device LLM을 구축하게 되었습니다.
스팸 문자 데이터는 스마트 치안 빅데이터 플랫폼을 통해 2025년 최신 스팸 문자 약 39.5만 건(395k) 을 확보했습니다.
확보된 데이터는 모델 과적합 방지를 위해 먼저 중복 제거 단계를 거쳤으며, 이후 커리큘럼 학습(Curriculum Learning) 기반의 샘플링을 적용해 전처리를 진행했습니다.
최종적으로는 해당 데이터셋을 기반으로, Gemini API를 활용한 Off-Policy Knowledge Distillation을 수행하여 학습용 데이터셋을 구축했습니다.
SimHash는 텍스트를 토큰화한 뒤 각 토큰의 해시값을 생성하고, 이 해시값들의 해밍 거리(Hamming Distance) 를 기준으로 문서 유사도를 판별합니다.
해밍 거리는 같은 길이의 두 비트열에서 서로 다른 위치의 개수를 의미합니다.
# 해밍거리 예시
A = 10101100
B = 10111101
→ 해밍 거리 = 2이번 스팸 문자의 경우에는 대체로 짧고 일부 단어에 대한 변형만을 수행하여, 기본적으로 설정하는 3~5 사이의 임계값으로 해밍거리를 설정하여 중복제거를 수행하였습니다.
위 과정을 거쳐서 약 200,000 만건의 데이터셋에 대한 중복을 제거하였고, 금융, 법, 광고 등 다양한 분야로 이루어진 10,000건의 스팸 문자 데이터셋으로 구성하였습니다.
데이터의 난이도에 따라 샘플링을 달리하는 Curriculum Learning 방식을 채택하였습니다.
각 스팸 문장은 복잡도를 1~5점으로 레이블링하여 데이터셋을 구성하였으며, 쉬운 문제부터 점진적으로 어려운 문제를 학습하도록 설계했습니다.
Curriculum Learning은 모델이 다양한 패턴을 안정적으로 학습하게 하고, Loss가 안정적으로 0에 수렴할 수 있도록 돕는 장점이 있습니다.
이를 통해 금융, 광고 등 기존 스팸 유형뿐 아니라, 최근 급증하고 있는 재난지원금 관련 스팸 문자와 같은 새로운 유형에도 보다 유연하게 대응할 수 있도록 하였습니다.
라벨링 과정에서는 Gemini API의 Structured Output 기능을 활용하여, 각 데이터의 복잡도를 1~5점 사이로 자동 라벨링하여 일관된 기준으로 데이터셋을 구축하였습니다.
from google import genai
import enum
class DataComplexity(Enum):
LOW = 1
MEDIUM = 2
HIGH = 3
VERY_HIGH = 4
EXTREMELY_HIGH = 5
client = genai.Client()
response = client.models.generate_content(
model='gemini-2.5-flash-lite',
contents='모델의 prompt에 대한 문제의 복잡도를 계산해주세요.',
config={
'response_mime_type': 'text/x.enum',
'response_schema': DataComplexity,
},
)
print(response.text)마지막으로, 구축된 데이터셋을 기반으로 Off-Policy Knowledge Distillation을 수행하였습니다.
단순히 스팸 여부만 판단하는 것이 아니라, 해당 문자가 왜 스팸으로 분류되었는지에 대한 설명 가능한 근거(Explainability) 를 함께 제공하도록 설계했습니다.
예를 들어, 개인정보 요구(주민등록번호, 비밀번호 등)나 금융상품 홍보, 불법 사이트 유도와 같은 패턴별 사유를 명시함으로써 사용자가 결과를 더욱 신뢰할 수 있도록 하였습니다.
이 과정에서 Gemini API를 활용하여 모델이 생성한 분류 결과에 대해 사람이 이해할 수 있는 자연어 근거를 함께 출력하도록 증류하였으며,
이는 단순한 분류 모델을 넘어 투명하고 설명 가능한 AI 시스템으로 발전하는 데 중요한 역할을 합니다.
본 프로젝트의 기반 모델로는 Gemma 3 (4B-IT)을 채택하였습니다.
Gemma 3는 Global Attention과 Local Attention을 결합한 구조를 채택하고 있습니다.
일부 구간은 Sliding Window Attention을 활용하여 긴 시퀀스 입력을 효율적으로 처리할 수 있습니다.
나머지 구간은 Local Attention을 적용하여 단어 간의 세밀한 관계를 학습할 수 있도록 설계되었습니다.
학습 프레임워크로는 Axolotl을 활용하였으며, SK DEVOCEAN alankim님의 기술 블로그 글을 참고하여 Gemma 3 모델 학습 환경을 구성하였습니다.
base_model: google/gemma-3-4b-it
load_in_4bit: true
ddp_find_unused_parameters: true
datasets:
- path: yahma/alpaca-cleaned
type: alpaca
val_set_size: 0.01
output_dir: ./outputs/gemma3
adapter: qlora
lora_model_dir:
sequence_len: 512
sample_packing: true
lora_r: 32
lora_alpha: 16
lora_dropout: 0.05
lora_target_modules: 'model.language_model.layers.[\d]+.(mlp|cross_attn|self_attn).(up|down|gate|q|k|v|o)_proj'
wandb_project: skitty-spam_filering
wandb_entity:
wandb_watch:
wandb_name:
wandb_log_model:
gradient_accumulation_steps: 4
micro_batch_size: 2
num_epochs: 5
optimizer: adamw_bnb_8bit
lr_scheduler: cosine
learning_rate: 0.0002
bf16: true
fp16:
tf32: true
gradient_checkpointing: true
gradient_checkpointing_kwargs:
use_reentrant: false
logging_steps: 100
flash_attention: true
eager_attention: true
warmup_ratio: 0.1
evals_per_epoch: 1
saves_per_epoch: 1
weight_decay: 0.0
fsdp:
- full_shard
- auto_wrap
fsdp_config:
fsdp_version: 2
fsdp_offload_params: false
fsdp_cpu_ram_efficient_loading: true
fsdp_auto_wrap_policy: TRANSFORMER_BASED_WRAP
fsdp_transformer_layer_cls_to_wrap: GemmaDecoderLayer
fsdp_state_dict_type: FULL_STATE_DICT
fsdp_sharding_strategy: FULL_SHARD
fsdp_reshard_after_forward: true
fsdp_activation_checkpointing: true 이번 4회차 모임에서는 데이터 전처리 파이프라인과 학습을 위한 yaml 스크립트를 설계하였습니다.
다음 단계에서는 학습을 마친 모델을 대상으로 Pruning과 Quantization을 진행하여, 실제 On-Device 환경에 적합한 경량 모델로 발전시켜 나갈 계획입니다.
DEVOTEE를 활성화 시키면
지금 작성한 댓글에 AI가 댓글을 달아줍니다.