Views
No views yet
urchade/gliner_multi_pii-v1 をベースに、日本語の合成データでファインチューニングしました。person name — 氏名 (漢字・ひらがな・カタカナ)phone number — 電話番号 (090-XXXX-XXXX, +81-X-XXXX-XXXX, ベタ書き 11 桁など)address — 住所 (〒郵便番号、都道府県、丁目番地号、ビル名など)email address — メールアドレスdate — 日付 (西暦、令和、平成など)url — URLaccount number — 口座番号 (銀行口座、顧客番号など)secret — パスワード・API キー・認証コードなど| Label | Precision | Recall | F1 | Support |
|---|---|---|---|---|
| person name | 0.984 | 0.982 | 0.983 | 439 |
| phone number | 0.856 | 0.856 | 0.856 | 180 |
| address | 0.966 | 0.825 | 0.890 | 103 |
| email address | 0.867 | 0.837 | 0.852 | 203 |
| date | 0.947 | 0.962 | 0.955 | 131 |
| url | 0.942 | 0.802 | 0.866 | 101 |
| account number | 1.000 | 0.948 | 0.973 | 77 |
| secret | 0.963 | 0.917 | 0.939 | 84 |
| micro avg | 0.940 | 0.908 | 0.924 | 1318 |
urchade/gliner_multi_pii-v1 をそのまま日本語に適用した場合の F1 は約 0.10 で、本モデルは約 9 倍の精度改善を達成しています。pip install gliner janomewhitespace splitter は日本語の単語境界を識別できません。本モデルでは Janome 形態素解析器を使用し、さらに空白だけのトークンを除外する独自の splitter を使うことを前提に学習されています。この splitter を必ず適用してください。1from gliner import GLiNER
2from gliner.data_processing import WordsSplitter
3
4
5class JapaneseSplitterNoWS:
6 """Janome ベースの splitter。空白だけのトークンを yield しない。"""
7
8 def __init__(self):
9 self._base = WordsSplitter(splitter_type="janome")
10
11 def __call__(self, text):
12 for tok, s, e in self._base(text):
13 if tok.strip() == "":
14 continue
15 yield tok, s, e
16
17
18model = GLiNER.from_pretrained("DataSign/gliner-ja-pii-v1", max_width=25)
19model.data_processor.words_splitter = JapaneseSplitterNoWS()1labels = [
2 "person name", "phone number", "address", "email address",
3 "date", "url", "account number", "secret",
4]
5
6text = (
7 "氏名: 山田太郎\n"
8 "住所: 〒980-0021 宮城県仙台市青葉区中央1-2-3\n"
9 "電話: 022-123-4567\n"
10 "メール: yamada@example.co.jp\n"
11 "申込日: 令和8年5月15日"
12)
13
14entities = model.predict_entities(text, labels, threshold=0.5)
15for e in entities:
16 print(f"[{e['label']}] {e['text']!r} (score={e['score']:.2f})")[person name] '山田太郎' (score=1.00)
[address] '〒980-0021 宮城県仙台市青葉区中央1-2-3' (score=0.98)
[phone number] '022-123-4567' (score=1.00)
[email address] 'yamada@example.co.jp' (score=1.00)
[date] '令和8年5月15日' (score=1.00)1def chunk_text(text, splitter, chunk_size=120, overlap=20):
2 tokens = list(splitter(text))
3 chunks = []
4 i = 0
5 while i < len(tokens):
6 end = min(i + chunk_size, len(tokens))
7 chunks.append((tokens[i][1], tokens[end - 1][2],
8 text[tokens[i][1]:tokens[end - 1][2]]))
9 if end == len(tokens):
10 break
11 i = end - overlap
12 return chunks
13
14
15splitter = JapaneseSplitterNoWS()
16chunks = chunk_text(long_text, splitter)
17all_entities = []
18for char_start, _, chunk in chunks:
19 preds = model.predict_entities(chunk, labels, threshold=0.5)
20 for p in preds:
21 p["start"] += char_start
22 p["end"] += char_start
23 all_entities.append(p)ja_JP ロケール) で氏名・住所・電話・メールを生成し、テンプレートに差し込む方式で 4,000 サンプルを作成しました。テンプレートは以下を含みます:氏名: <値>, 住所:\n<値>)<氏名>様、ご依頼の件、<日付>までに対応します)姓: <姓>\n名: <名>\nメール: <email> 形式)User <name> failed to login at <date>)パスワードは <secret>、APIキーは <secret> です)諒 などの 1 文字漢字名は学習サンプルが限定的で recall が低い場合がありますurchade/gliner_multi_pii-v1 と同じ)1@misc{zaratiana2023gliner,
2 title={GLiNER: Generalist Model for Named Entity Recognition using Bidirectional Transformer},
3 author={Urchade Zaratiana and Nadi Tomeh and Pierre Holat and Thierry Charnois},
4 year={2023},
5 eprint={2311.08526},
6 archivePrefix={arXiv},
7 primaryClass={cs.CL}
8}