A.X-patent-len4096-op
한국어 특허 문헌을 과학기술표준분류 188개 중분류로 자동 분류하는 다중 레이블 인코더 분류기다. 한 문서가 여러 중분류에 대응할 수 있으며(고유 문서의 약 14%가 2~10개), 17개 대분류는 예측된 각 중분류 코드의 앞 두 글자로 유도한다.
skt/A.X-Encoder-base(한국어 ModernBERT, 16k 컨텍스트)를 4,096 토큰 창에서 파인튜닝했다.
정리 test 11,244건에서 micro-F1 0.8660 — 같은 데이터·같은 레시피의 512 토큰 창 기준 런(0.8588) 대비 +0.72pt이며, 문서 단위 paired bootstrap CI95 [+0.33, +1.10]으로 시드 잡음(±0.2pt) 밖이다.
사용법
1import json
2import torch
3from huggingface_hub import hf_hub_download
4from transformers import AutoTokenizer, AutoModelForSequenceClassification
5
6REPO = "ingyoun/A.X-patent-len4096-op"
7tokenizer = AutoTokenizer.from_pretrained(REPO)
8model = AutoModelForSequenceClassification.from_pretrained(REPO).eval()
9
10# 입력은 네 필드를 공백으로 이어 붙인다(빈 필드는 건너뛴다) — 훈련과 같은 순서여야 한다.
11fields = ["invention_title", "ipc_main", "abstract", "claims"]
12doc = {
13 "invention_title": "반도체 소자의 제조 방법",
14 "ipc_main": "H01L-021/00",
15 "abstract": "...",
16 "claims": "...",
17}
18text = " ".join(str(doc[f]) for f in fields if doc[f])
19
20enc = tokenizer(text, truncation=True, max_length=4096, return_tensors="pt")
21with torch.no_grad():
22 probs = torch.sigmoid(model(**enc).logits)[0]
23
24# τ=0.5 다중 레이블 결정
25pred_ids = (probs >= 0.5).nonzero().flatten().tolist()
26mno = [model.config.id2label[i] for i in pred_ids]
27lno = sorted({m[:2] for m in mno}) # 대분류는 중분류 코드의 앞 두 글자
28print(mno, lno)
- 결정 임계값은 τ=0.5다. 아래 성능 수치는 모두 이 임계값에서 잰 값이다.
- τ=0.5에서 아무 라벨도 넘지 않는 문서가 0.83% 있다. 반드시 하나를 내야 하는 운영이라면
probs.argmax()를 대체 경로로 둔다.
config.json의 id2label이 188개 중분류 코드(EA01 … OB02)를 담는다. 같은 매핑과 중분류→대분류 대응은 label_mappings.json에도 있다.
라벨 공간
- 중분류(
Mno) 188개 — 정렬된 코드 순서가 곧 출력 열 순서다(EA01이 0번, OB02가 187번).
- 대분류(
Lno) 17개 — EA EB EC ED EE EF EG EH EI LA LB LC NB NC ND OA OB.
- 대분류를 예측하는 별도 헤드는 없다. 중분류 예측에서 유도하므로 계층 비일관성이 원천적으로 생기지 않는다. 유도된 대분류 성능은 micro-F1 0.9132 · P@1 0.9397이다.
훈련
| 항목 | 값 |
|---|
| 베이스 모델 | skt/A.X-Encoder-base |
| 최대 길이 | 4,096 토큰 |
| 손실 | Focal Loss (α=0.25, γ=2), sigmoid 다중 레이블 |
| 유효 배치 · lr | 128 · 4.8e-4 |
| 스케줄 | linear · warmup_ratio 0.1 · weight decay 0.01 |
| 에폭 | 12 (18,912 step 완주, 조기 종료 미발동) |
| 시드 | 42 |
| 모델 선택 | val micro-F1 |
4,096은 8,192 대비 잃는 것이 토큰 1.60%뿐인데 최악 시퀀스가 절반이라 마이크로 배치를 2배로 쓸 수 있는 손익 분기점이다. 훈련 문서의 토큰 길이는 평균 796 · 중앙 629 · p99 3,619이며, 4,096을 넘는 문서는 0.8%다.
데이터
AI Hub
과학기술표준분류 대응 특허 데이터를 원천으로 한다 —
https://www.aihub.or.kr. 원본 데이터의 재배포 제한 때문에 가공본은 공개하지 않으며, 전처리 절차는 아래 코드 저장소에 있다.
- 분할: train 201,616 / val 11,132 / test 11,244 문서
documentId 단위로 재분할했다. 원 배포본은 같은 문서가 train과 val 양쪽에 나타나는 누수 위험이 있어 문서 단위로 다시 나눴다.
- 입력 필드:
invention_title · ipc_main · abstract · claims를 이 순서로 공백 연결
- 라벨 충돌·중복 문서 336건을 제거한 정리본에서 훈련·평가했다(입력 문자열 동일성으로 검출한 4부류 — 라벨 충돌 89 · train 내 정확중복 199 · train-eval 누수 45 · val-test 중복 3).
성능
test 11,244건 · τ=0.5. 비교 대상은 모두 같은 문서·같은 순서에서 잰 값이다.
| 런 | micro | macro | sample | empty | P@1 |
|---|
| KoBERT (512) | 0.8500 | 0.8467 | 0.8653 | 1.17% | 0.8935 |
| A.X (512) | 0.8588 | 0.8565 | 0.8738 | 1.17% | 0.9000 |
| 이 모델 (4096) | 0.8660 | 0.8638 | 0.8835 | 0.83% | 0.9051 |
길이 구간별 micro-F1 — 창 확장의 이득이 긴 문서에서 커진다.
| 길이 구간 | n | A.X (512) | 이 모델 (4096) | Δ |
|---|
| ≤512 | 3,187 | 0.8724 | 0.8753 | +0.29pt |
| 512–1024 | 5,172 | 0.8636 | 0.8691 | +0.55pt |
| 1024–2048 | 2,336 | 0.8360 | 0.8518 | +1.58pt |
| >2048 | 549 | 0.8318 | 0.8462 | +1.44pt |
라벨 개수별 — 다중 레이블 문서가 남은 헤드룸이다.
| 구간 | n | micro | sample |
|---|
| k=1 | 9,555 | 0.8883 | 0.8997 |
| k≥2 | 1,689 | 0.8047 | 0.7921 |
한계
- 측정된 F1은 라벨 잡음만큼 하향 편향돼 있다. 확신 오류 분석에서 나온 잡음 후보가 전부 실제 잡음이라면 참 성능은 최대 +2.1pt 높다.
- 훈련 분포가 인위적으로 평탄화돼 있다 — 중분류당 1,300~2,600건으로, 실제 특허 출원 분포와 다르다. 실제 분포에서의 성능은 이 수치와 다를 수 있다.
- 원 데이터 배포처가 공개한 baseline F1 0.8249와 직접 비교하지 말 것. 그 값은 다른 test 집합에서 잰 top-1 예측의 weighted-F1이고, 그 데이터 분할에는 문서 누수 위험이 있다. 이 저장소의 수치는 누수를 제거한 자체 test에서 잰 것이라 같은 자가 아니다. 벤더 연속성을 위해 같은 방식으로 계산한 앵커 weighted-F1은 0.8251이지만, 이 역시 test가 달라 대면시킬 수 없다.
- 도면 이미지 등 비텍스트 입력은 다루지 않는다.
라이선스
Apache-2.0 — 베이스 모델 skt/A.X-Encoder-base의 라이선스를 따른다. 학습 데이터는 AI Hub 이용 약관의 적용을 받으며 이 저장소에 포함되지 않는다.
코드 저장소