kiom-embedding-bge-m3: Korean Medicine Embedding Model
한의학(Korean Medicine) 도메인 특화 임베딩 모델입니다. BAAI/bge-m3를 기반으로 한의학 온톨로지 및 용어 데이터를 활용하여 LoRA 파인튜닝하였습니다.
Highlights
- MRR@10 0.9002 (3포맷 평균) — 베이스 모델(0.7285) 대비 +23.6% 향상
- 13개 SOTA 모델 대비 1위 (OpenAI, Gemini, Qwen3, E5 등 포함)
- Sim_Gap 0.5221 — 베이스 모델(0.1719) 대비 3배 향상, 정답/오답 분리 능력 대폭 개선
- 한글, 한자, 한글+한자 3가지 포맷 모두에서 최고 성능
Model Details
| 항목 | 값 |
|---|---|
| Base Model | BAAI/bge-m3 |
| Method | LoRA (PEFT) |
| LoRA Rank | 16 |
| LoRA Alpha | 32 |
| Target Modules | query, key, value |
| Output Dim | 1024 |
| Max Seq Length | 256 tokens |
| Training Data | 302,676 samples (한의학 온톨로지 10종, 3포맷) |
| Loss | MultipleNegativesRankingLoss |
| Epochs | 35 (effective, multi-epoch sweep) |
| Batch Size | 64 |
| Learning Rate | 2e-5 |
| Hard Negatives | 3 per query |
| Adapter Size | ~9MB |
Usage
Installation
pip install -U sentence-transformers peft
Inference
from sentence_transformers import SentenceTransformer
# 모델 로드
model = SentenceTransformer("kmkeum/kiom-embedding-bge-m3")
# 문장 인코딩
sentences = [
"두통(頭痛)",
"머리가 아픈 증상",
"복통(腹痛)",
]
embeddings = model.encode(sentences)
# 유사도 계산
similarities = model.similarity(embeddings, embeddings)
print(similarities)
# 두통-머리가 아픈 증상: 높은 유사도
# 두통-복통: 낮은 유사도
With PEFT (Low-level)
from transformers import AutoModel, AutoTokenizer
from peft import PeftModel
base_model = AutoModel.from_pretrained("BAAI/bge-m3")
model = PeftModel.from_pretrained(base_model, "kmkeum/kiom-embedding-bge-m3")
tokenizer = AutoTokenizer.from_pretrained("kmkeum/kiom-embedding-bge-m3")
Evaluation Results
13개 SOTA 임베딩 모델과 전체 테스트셋(25,223건 × 3포맷)으로 비교 평가하였습니다.
Average (3포맷 평균)
| Rank | Model | MRR@10 | Recall@10 | NDCG@10 | Sim_Gap |
|---|---|---|---|---|---|
| 1 | kiom-embedding-bge-m3 (Ours) | 0.9002 | 0.9952 | 0.9230 | 0.5221 |
| 2 | Octen-Embedding-8B | 0.7887 | 0.9897 | 0.8365 | 0.2352 |
| 3 | BGE-m3 (Base) | 0.7285 | 0.9757 | 0.7864 | 0.1719 |
| 4 | OpenAI text-embedding-3-large | 0.7258 | 0.9806 | 0.7859 | 0.1955 |
| 5 | Gemini Embedding | 0.8023 | 0.9890 | 0.8464 | 0.1329 |
| 6 | KaLM-Gemma3-12B | 0.7526 | 0.9847 | 0.8073 | 0.1237 |
| 7 | Qwen3-Embedding-4B | 0.7121 | 0.9815 | 0.7758 | 0.1531 |
| 8 | Qwen3-Embedding-8B | 0.7067 | 0.9831 | 0.7720 | 0.1454 |
| 9 | E5-large-instruct | 0.6930 | 0.9787 | 0.7601 | 0.0348 |
| 10 | Qwen3-Embedding-0.6B | 0.6844 | 0.9775 | 0.7535 | 0.1415 |
| 11 | NVIDIA Nemotron-8B | 0.6622 | 0.9761 | 0.7360 | 0.1024 |
| 12 | KLUE-SBERT (Huffon) | 0.5980 | 0.9697 | 0.6848 | 0.1744 |
| 13 | KLUE-SBERT | 0.5562 | 0.9647 | 0.6515 | 0.1416 |
| 14 | KoSimCSE-RoBERTa | 0.5427 | 0.9629 | 0.6405 | 0.1372 |
Both (한글+한자 병기)
| Model | MRR@10 | Recall@1 | Recall@10 | NDCG@10 | Sim_Gap |
|---|---|---|---|---|---|
| Ours | 0.9135 | 0.8747 | 0.9960 | 0.9333 | 0.5517 |
| BGE-m3 | 0.7579 | 0.6779 | 0.9776 | 0.8092 | 0.1728 |
| OpenAI | 0.7660 | 0.6759 | 0.9844 | 0.8177 | 0.2140 |
Korean (한글만)
| Model | MRR@10 | Recall@1 | Recall@10 | NDCG@10 | Sim_Gap |
|---|---|---|---|---|---|
| Ours | 0.8801 | 0.8269 | 0.9943 | 0.9075 | 0.4693 |
| BGE-m3 | 0.6648 | 0.5551 | 0.9688 | 0.7358 | 0.1490 |
| OpenAI | 0.6416 | 0.5173 | 0.9718 | 0.7191 | 0.1422 |
Chinese (한자만)
| Model | MRR@10 | Recall@1 | Recall@10 | NDCG@10 | Sim_Gap |
|---|---|---|---|---|---|
| Ours | 0.9070 | 0.8656 | 0.9954 | 0.9282 | 0.5453 |
| BGE-m3 | 0.7629 | 0.6774 | 0.9808 | 0.8142 | 0.1940 |
| OpenAI | 0.7697 | 0.6811 | 0.9856 | 0.8208 | 0.2302 |
Training Data
Overview
한국한의학연구원(KIOM)의 한의학 온톨로지 및 용어 데이터(JSON 15개 + Excel 3개)에서 10가지 유형의 positive pair를 생성하고, 온톨로지 기반 하드 네거티브를 추가한 뒤, 3가지 텍스트 포맷으로 변환하여 학습 데이터를 구축하였습니다.
Raw Data Sources
| 카테고리 | 파일 | 건수 | 주요 필드 |
|---|---|---|---|
| 동유의어 (Excel) | 동유의어.xlsx | 4,869건 | 동의어 그룹 ID, 한글명, 한자명 |
| 표준한의학용어집 (Excel) | 표준한의학용어집.xlsx | 9,074건 | 한글, 한자, 정의설명, 동의어(마침표 구분) |
| 일반인용어사전 (Excel) | 일반인용어사전.xlsx | 20,379건 | 한글, 한자, 설명 |
| 병증 (JSON × 5) | 간계/비계/신계/심계/폐계 내과학병증 | 각 ~127건 | 한글명, 한자명, 증상, 맥, 설, 치법, 처방 |
| 처방 (JSON × 5) | 간계/비계/신계/심계/폐계 내과학처방 | 각 ~425건 | 한글명, 한자명, 주치, 구성약재 |
| 참고서 (JSON × 3) | 동의방제와처방해설, 방약합편, 방제학 | 다수 | 처방과 동일 구조 |
| 약재 (JSON × 1) | 약재.json | 4,400건 | 한글명, 한자명, 성, 미, 귀경, 효능, 주치 |
| 병리 (JSON × 1) | 한방병리학.json | 393건 | 한글명, 한자명, 증후개념/분석, 주/차증상, 치법, 처방, 상용약물 |
Step 1: Positive Pair Generation (10 Types)
| # | 유형 | 소스 | 건수 | 생성 방법 |
|---|---|---|---|---|
| 1 | 동의어 쌍 | 동유의어.xlsx | 20,004 | 같은 그룹 내 모든 용어의 양방향 조합 (A↔B) |
| 2 | 표준용어 동의어 쌍 | 표준한의학용어집.xlsx | 56,650 | 주용어 + 마침표 구분 동의어 간 전체 양방향 조합 |
| 3 | 용어-정의 쌍 | 일반인용어사전.xlsx | 20,378 | 용어 → 일반인용 설명 (단방향) |
| 4 | 표준용어-정의 쌍 | 표준한의학용어집.xlsx | 9,074 | 용어 → 정의설명 (단방향) |
| 5 | 질환-증상 쌍 | 병증 JSON 5개 | 5,495 | 질환 → 개별 증상/맥/설 (이름: 설명 형태) |
| 6 | 질환-치법 쌍 | 병증 JSON 5개 | 902 | 질환 → 치법 (이름: 설명 형태) |
| 7 | 처방-주치 쌍 | 처방+참고서 JSON 8개 | 5,227 | 처방 → 주치 목록 결합 텍스트 |
| 8 | 처방-구성약재 쌍 | 처방+참고서 JSON 8개 | 5,590 | 처방 → 구성약재 리스트 (쉼표 결합) |
| 9 | 약재-효능/주치 쌍 | 약재.json | 1,706 | 약재 → 효능/주치/성미귀경 (3종 각각) |
| 10 | 병리패턴 쌍 | 한방병리학.json | 1,089 | 패턴 → 증후개념/분석/주증상/차증상/치법 (5종 각각) |
| 합계 | 126,115 |
Positive Pair 생성 예시 (클릭하여 펼치기)
유형 1 (동의어):
{"query": "자락법(刺絡法)", "pos": ["자락(刺絡)"]}
{"query": "자락(刺絡)", "pos": ["자락법(刺絡法)"]}
유형 3 (용어-정의):
{"query": "고열번갈(高熱煩渴)", "pos": ["열이 높고 갈증이 심한 증상"]}
유형 5 (질환-증상):
{"query": "열독황달(熱毒黃疸)", "pos": ["두훈목현(頭暈目眩): 머리가 어지럽고 눈앞이 아찔한 것"]}
유형 7 (처방-주치):
{"query": "청온패독음(淸瘟敗毒飮)", "pos": ["대열갈음: 열이 많이 나고 갈증이 나서 물을 많이 마시는 것. 두통여벽: 머리가 쪼개질 듯이 아픈 것. ..."]}
유형 8 (처방-구성약재):
{"query": "해독정기탕(解毒正氣湯)", "pos": ["창출(蒼朮) 7.5g, 갈근(葛根) 7.5g, ..."]}
유형 9 (약재-성미귀경):
{"query": "한채(蔊菜)", "pos": ["성: 平. 미: 苦, 辛. 귀경: 肝, 肺"]}
Step 2: Hard Negative Mining (Ontology-aware)
단순 랜덤 네거티브가 아닌, 통합 온톨로지 그래프를 구축하여 의미적으로 관련된 텍스트를 배제한 뒤 하드 네거티브를 선택합니다.
2-1. 통합 온톨로지 그래프 구축
모든 원본 데이터를 하나의 지식 그래프로 통합합니다:
Ontology Graph:
entity_texts: 엔티티 → {관련 텍스트들} (질환→증상, 처방→주치 등)
entity_links: 엔티티 → {연결된 엔티티들} (질환↔처방, 처방↔약재, 병리↔질병 등)
text_to_entities: 텍스트 → {소속 엔티티들} (역인덱스)
- 동의어 관계: 같은 그룹 내 용어 간 양방향 link
- 질환-처방 관계: 병증 데이터에서 질환↔처방 link
- 처방-약재 관계: 처방 데이터에서 처방↔구성약재 link
- 병리-질병/처방/약재 관계: 한방병리학에서 다중 link
2-2. 배제 집합(Exclusion Set) 계산
주어진 텍스트에서 2-hop 이내의 모든 관련 텍스트를 수집하여 네거티브 후보에서 제외합니다:
예: query = "간열두통(肝熱頭痛)"
→ 1-hop: 이 질환의 증상, 치법, 맥, 설 텍스트
→ 2-hop: 연결된 처방의 주치, 구성약재
→ 모두 네거티브에서 제외 (false negative 방지)
2-3. 네거티브 선택 전략 (Random 7 + Similarity 3)
각 pair에 대해 같은 type 내의 positive 텍스트 풀에서:
| 방법 | 개수 | 설명 |
|---|---|---|
| 랜덤 네거티브 | 7개 | 온톨로지 배제 후 남은 후보에서 랜덤 샘플링 |
| 유사도 기반 하드 네거티브 | 3개 | BGE-m3로 코사인 유사도 계산 → 0.4~0.6 범위에서 선택 |
| (너무 유사하면 false negative, 너무 다르면 쉬운 네거티브) |
- 유사도 범위 내 후보가 부족하면 가용한 만큼 사용 + 랜덤 보충
- 최종 네거티브: pair당 10개
Step 3: Text Format Transformation (3 Versions)
원본은 한글한자 병기 형태이며, 정규표현식으로 2가지 추가 포맷을 생성합니다:
| 포맷 | 변환 규칙 | 예시 |
|---|---|---|
| Both (병기) | 원본 그대로 | 고열번갈(高熱煩渴) |
| Korean (한글만) | \(漢字+\) 제거 |
고열번갈 |
| Chinese (한자만) | 한글(漢字) → 漢字 치환 |
高熱煩渴 |
query, pos, neg 모든 필드에 동일 변환을 적용하여 포맷별 파일을 각각 생성합니다.
Step 4: Train/Test Split
| 단계 | 설명 |
|---|---|
| 셔플 | 행 인덱스를 seed=42로 랜덤 셔플 (3포맷 동일 인덱스 유지) |
| 분할 | 80% 학습 / 20% 테스트 |
| 학습 파일 | 3포맷 합본 → unified_train.jsonl (302,676건 = 100,892 × 3) |
| 테스트 파일 | 포맷별 분리 → test_both/korean/chinese.jsonl (각 25,223건) |
| 합본 셔플 | 학습 데이터 합본 후 재셔플하여 포맷이 골고루 섞이도록 |
Final JSONL Format
{
"query": "자락법(刺絡法)",
"pos": ["자락(刺絡)"],
"neg": ["반관맥(反關脈)", "경맥(經脈)", "대추(大椎)", "합곡(合谷)", "침구(鍼灸)", "맥진(脈診)", "보법(補法)", "족삼리(足三里)", "사관혈(四關穴)", "위중(委中)"]
}
Data Scale Summary
Raw Data (18 files) → 126,115 positive pairs (10 types)
↓ Ontology-aware hard negative mining (random 7 + similarity 3 = 10/pair)
↓ 3 text format transformations (Both / Korean / Chinese)
↓ 126,115 × 3 = 378,345 total samples
↓ 80/20 train-test split
Train: 302,676 samples (3-format unified, shuffled)
Test: 25,223 × 3 formats (format-separated)
Training Environment
| 항목 | 값 |
|---|---|
| GPU | NVIDIA RTX PRO 6000 Blackwell (96GB VRAM) |
| Framework | sentence-transformers 5.2.2, PEFT 0.18.1 |
| PyTorch | 2.10.0+cu128 |
| Precision | bf16 |
Architecture
SentenceTransformer(
(0): Transformer({'max_seq_length': 256, 'do_lower_case': False, 'architecture': 'XLMRobertaModel'})
+ LoRA(r=16, alpha=32, target=['query', 'key', 'value'])
(1): Pooling({'pooling_mode_cls_token': True})
(2): Normalize()
)
Intended Use
- 한의학 용어 검색 및 의미 유사도 계산
- RAG(Retrieval-Augmented Generation) 시스템의 한의학 도메인 리트리버
- 한의학 문헌 클러스터링 및 분류
- 한의학 지식 그래프 구축 지원
Limitations
- 한의학 도메인에 특화되어 일반 도메인 성능은 베이스 모델보다 낮을 수 있음
- 최대 256 토큰까지 지원 (긴 문서는 청크 분할 필요)
- 한국어/한자 중심, 영어 의학 용어에 대한 성능은 미검증
Citation
@misc{kiom-embedding-bge-m3,
title={Korean Medicine Embedding Model based on BGE-m3},
author={Korea Institute of Oriental Medicine (KIOM)},
year={2026},
url={https://huggingface.co/kmkeum/kiom-embedding-bge-m3}
}
Acknowledgments
- Base model: BAAI/bge-m3
- Data source: 한국한의학연구원(KIOM) 한의학 온톨로지
Model tree for kmkeum/kiom-embedding-bge-m3
Base model
BAAI/bge-m3