feat: add KLUE NER sample viewer for scorecard capture
성적서 "1. 데이터 준비" 는 KLUE NER 을 원본 배포 형식인 인라인 태그 (`<영동고속도로:LC>`) 로 싣는데, HuggingFace datasets 판은 tokens/ner_tags 배열이라 모양이 다르다. BIO 를 엔티티 단위로 묶어 원본 형식으로 되돌린다. 전 차수 성적서 8p 첫 예시와 문자 단위로 일치함을 확인했다. 열람 전용이며 학습 경로에는 관여하지 않는다. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
10340718ca
commit
be25b6c053
104
scripts/show_klue_ner_samples.py
Normal file
104
scripts/show_klue_ner_samples.py
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
"""성능지표 #3 학습/평가 데이터 예시를 성적서 형식으로 출력한다.
|
||||||
|
|
||||||
|
전 차수 성적서(GERI `GERIR.CE.2511-02.009`) 8페이지 "1. 데이터 준비" 는 KLUE NER 을
|
||||||
|
원본 배포 형식인 인라인 태그로 싣는다.
|
||||||
|
|
||||||
|
"id": 0,
|
||||||
|
"sentence": "특히 <영동고속도로:LC> <강릉:LC> 방향 <문막휴게소:LC>에서 ..."
|
||||||
|
|
||||||
|
HuggingFace `datasets` 의 klue/ner 는 음절 토큰(`tokens`)과 BIO 태그(`ner_tags`)
|
||||||
|
배열로 들어오므로 모양이 다르다. 여기서 BIO 를 엔티티 단위로 묶어 원본 형식으로
|
||||||
|
되돌린다. 성적서에 그대로 캡처해 붙이기 위한 열람 전용 스크립트이며 학습에는
|
||||||
|
관여하지 않는다.
|
||||||
|
|
||||||
|
사용:
|
||||||
|
python scripts/show_klue_ner_samples.py # 학습셋 앞뒤 3건씩
|
||||||
|
python scripts/show_klue_ner_samples.py --split validation
|
||||||
|
python scripts/show_klue_ner_samples.py --head 5 --tail 5
|
||||||
|
python scripts/show_klue_ner_samples.py --all --out train_samples.txt
|
||||||
|
"""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
def to_inline(tokens: list[str], tags: list[str]) -> str:
|
||||||
|
"""음절 토큰 + BIO 태그 → `<표면형:태그>` 인라인 문장.
|
||||||
|
|
||||||
|
KLUE NER 의 tokens 는 공백을 포함한 음절 단위라 그대로 이어 붙이면 원문이 된다.
|
||||||
|
"""
|
||||||
|
out: list[str] = []
|
||||||
|
buf: list[str] = []
|
||||||
|
label: str | None = None
|
||||||
|
|
||||||
|
def flush() -> None:
|
||||||
|
if buf:
|
||||||
|
out.append("<%s:%s>" % ("".join(buf), label))
|
||||||
|
buf.clear()
|
||||||
|
|
||||||
|
for token, tag in zip(tokens, tags):
|
||||||
|
if tag.startswith("B-"):
|
||||||
|
flush()
|
||||||
|
label = tag[2:]
|
||||||
|
buf.append(token)
|
||||||
|
elif tag.startswith("I-") and label == tag[2:]:
|
||||||
|
buf.append(token)
|
||||||
|
else:
|
||||||
|
flush()
|
||||||
|
label = None
|
||||||
|
out.append(token)
|
||||||
|
flush()
|
||||||
|
return "".join(out)
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> int:
|
||||||
|
parser = argparse.ArgumentParser(description=__doc__)
|
||||||
|
parser.add_argument("--split", default="train", choices=("train", "validation"))
|
||||||
|
parser.add_argument("--head", type=int, default=3, help="앞에서 N건")
|
||||||
|
parser.add_argument("--tail", type=int, default=3, help="뒤에서 N건")
|
||||||
|
parser.add_argument("--all", action="store_true", help="전건 출력")
|
||||||
|
parser.add_argument("--out", help="파일로 저장 (미지정 시 표준출력)")
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
from datasets import load_dataset
|
||||||
|
|
||||||
|
ds = load_dataset("klue", "ner", split=args.split)
|
||||||
|
names = ds.features["ner_tags"].feature.names
|
||||||
|
total = len(ds)
|
||||||
|
|
||||||
|
if args.all:
|
||||||
|
indices = list(range(total))
|
||||||
|
else:
|
||||||
|
indices = list(range(min(args.head, total)))
|
||||||
|
tail_start = max(len(indices), total - args.tail)
|
||||||
|
indices += list(range(tail_start, total))
|
||||||
|
|
||||||
|
lines: list[str] = []
|
||||||
|
kind = "학습" if args.split == "train" else "평가"
|
||||||
|
lines.append("<%s 데이터 예시(총 %d 건)>" % (kind, total))
|
||||||
|
lines.append("")
|
||||||
|
|
||||||
|
previous = -1
|
||||||
|
for i in indices:
|
||||||
|
if previous >= 0 and i != previous + 1:
|
||||||
|
lines.append("...")
|
||||||
|
lines.append("")
|
||||||
|
row = ds[i]
|
||||||
|
sentence = to_inline(row["tokens"], [names[t] for t in row["ner_tags"]])
|
||||||
|
lines.append('"id": %d,' % i)
|
||||||
|
lines.append('"sentence": "%s",' % sentence)
|
||||||
|
previous = i
|
||||||
|
|
||||||
|
text = "\n".join(lines)
|
||||||
|
if args.out:
|
||||||
|
with open(args.out, "w", encoding="utf-8") as f:
|
||||||
|
f.write(text + "\n")
|
||||||
|
print("%s 에 %d건 기록 (전체 %d건)" % (args.out, len(indices), total))
|
||||||
|
else:
|
||||||
|
print(text)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
raise SystemExit(main())
|
||||||
Loading…
Reference in New Issue
Block a user