TR-KVKK Classifier v2
Türkçe metinlerde KVKK (Kişisel Verilerin Korunması Kanunu) kapsamındaki kişisel veri kategorilerini tespit eden BPE tabanlı Transformer modelidir.
EĞİTİM VE AKADEMİK AMAÇLIDIR
*** !!! STILL under development. Weights are updating regularly !!! ***
v1'den Farkları
| v1 | v2 | |
|---|---|---|
| Tokenizer | Karakter bazlı | BPE (16.000 vocab) |
| Pre-training | Yok | Wikipedia Türkçe MLM |
| Bağlam | Zayıf | Güçlü |
| "Hastanın X yetmezliği" | Kaçırabilir | Yakalar |
Model Mimarisi
Türkçe Wikipedia üzerinde MLM ile ön eğitim yapılmış, ardından KVKK veri seti ile fine-tune edilmiş BPE tabanlı Transformer modelidir (BPEViT).
| Parametre | Değer |
|---|---|
| Mimari | BPEViT (Transformer Encoder) |
| Tokenizer | ByteLevel BPE |
| Vocab boyutu | 16.000 |
embed_dim |
256 |
n_layers |
8 |
n_heads |
8 |
max_len |
128 token |
num_classes |
6 |
| Pre-training | MLM — Türkçe Wikipedia |
Kategoriler
| Label | Kategori | Açıklama |
|---|---|---|
| 0 | negatif |
Kişisel veri içermeyen metinler |
| 1 | tc_kimlik |
TC kimlik numarası |
| 2 | saglik |
Sağlık ve tıbbi veriler |
| 3 | finans |
IBAN, banka ve finansal bilgiler |
| 4 | iletisim |
Telefon, e-posta, adres |
| 5 | biyometrik |
Parmak izi, yüz tanıma ve benzeri |
Kullanım
import torch
import torch.nn as nn
import json
from tokenizers import ByteLevelBPETokenizer
from safetensors.torch import load_file
from huggingface_hub import hf_hub_download
class BPEViT(nn.Module):
def __init__(self, vocab_size, embed_dim, max_len, n_heads, n_layers, num_classes=None):
super().__init__()
self.embed = nn.Embedding(vocab_size, embed_dim, padding_idx=0)
self.cls_token = nn.Parameter(torch.zeros(1, 1, embed_dim))
self.pos_embed = nn.Parameter(torch.zeros(1, max_len + 1, embed_dim))
nn.init.trunc_normal_(self.cls_token, std=0.02)
nn.init.trunc_normal_(self.pos_embed, std=0.02)
encoder_layer = nn.TransformerEncoderLayer(
d_model=embed_dim, nhead=n_heads,
dim_feedforward=embed_dim * 4,
batch_first=True, dropout=0.1, activation='gelu'
)
self.transformer = nn.TransformerEncoder(encoder_layer, num_layers=n_layers)
if num_classes:
self.classifier = nn.Sequential(
nn.Linear(embed_dim, embed_dim // 2),
nn.GELU(),
nn.Dropout(0.1),
nn.Linear(embed_dim // 2, num_classes),
)
def forward(self, input_ids):
b, seq_len = input_ids.shape
pad_mask = (input_ids == 0)
cls_mask = torch.zeros((b, 1), dtype=torch.bool, device=input_ids.device)
full_mask = torch.cat((cls_mask, pad_mask), dim=1)
x = self.embed(input_ids)
cls_tok = self.cls_token.expand(b, -1, -1)
x = torch.cat((cls_tok, x), dim=1)
x = x + self.pos_embed[:, :seq_len + 1, :]
x = self.transformer(x, src_key_padding_mask=full_mask)
return self.classifier(x[:, 0])
# Model yükle
REPO_ID = "orkungedik/tr-kvkk-classifier-v2"
model_path = hf_hub_download(REPO_ID, "model.safetensors")
config_path = hf_hub_download(REPO_ID, "config.json")
vocab_path = hf_hub_download(REPO_ID, "tokenizer/vocab.json")
merges_path = hf_hub_download(REPO_ID, "tokenizer/merges.txt")
with open(config_path) as f:
config = json.load(f)
tokenizer = ByteLevelBPETokenizer(vocab_path, merges_path)
tokenizer.enable_padding(pad_id=0, length=config["max_len"])
tokenizer.enable_truncation(max_length=config["max_len"])
model = BPEViT(**{k: config[k] for k in
["vocab_size", "embed_dim", "max_len", "n_heads", "n_layers", "num_classes"]})
model.load_state_dict(load_file(model_path), strict=False)
model.eval()
# Tahmin
def predict(text: str) -> dict:
ids = tokenizer.encode(text).ids
with torch.no_grad():
logits = model(torch.tensor([ids]))
probs = torch.softmax(logits, dim=-1)[0].tolist()
top = probs.index(max(probs))
return {"label": config["label_names"][top], "confidence": round(probs[top], 4)}
print(predict("Hastanın böbrek yetmezliği bulunmaktadır."))
# → {"label": "saglik", "confidence": 0.97}
Büyük Dokümanlar
Model 128 token ile sınırlıdır. Daha uzun metinler için chunk + majority vote kullanın:
from collections import Counter
def predict_document(text: str, overlap: int = 20) -> dict:
step = config["max_len"] - overlap
tokens = tokenizer.encode(text).ids
chunks = [tokens[i:i+config["max_len"]] for i in range(0, len(tokens), step)]
chunks = [c for c in chunks if any(t != 0 for t in c)]
predictions = []
with torch.no_grad():
for chunk in chunks:
padded = chunk + [0] * (config["max_len"] - len(chunk))
logits = model(torch.tensor([padded]))
probs = torch.softmax(logits, dim=-1)[0].tolist()
predictions.append(config["label_names"][probs.index(max(probs))])
vote = Counter(predictions).most_common(1)[0][0]
return {"label": vote, "chunk_count": len(predictions)}
Eğitim
| Detay | Değer |
|---|---|
| Pre-training verisi | Türkçe Wikipedia (~1M cümle) |
| Pre-training görevi | Masked Language Modeling (MLM, %15) |
| Fine-tune verisi | orkungedik/tr-kvkk |
| Fine-tune veri boyutu | ~65.000 örnek |
| Split | %80 train / %10 val / %10 test |
| Pre-train epoch | 10 |
| Fine-tune epoch | 20 |
| Batch size | 64 (pre-train: 128) |
| Optimizer | AdamW |
| Pre-train LR | 1e-4 |
| Fine-tune LR | 3e-5 (5. epoch'tan itibaren tüm katmanlar) |
| Scheduler | CosineAnnealingLR |
Değerlendirme Sonuçları
Test seti üzerinde elde edilen metrikler (n=8.348):
| Kategori | Precision | Recall | F1 | Support |
|---|---|---|---|---|
| negatif | 0.99 | 0.98 | 0.98 | 5.417 |
| tc_kimlik | 0.97 | 0.99 | 0.98 | 526 |
| saglik | 0.91 | 0.93 | 0.92 | 826 |
| finans | 1.00 | 1.00 | 1.00 | 527 |
| iletisim | 0.99 | 1.00 | 1.00 | 526 |
| biyometrik | 0.93 | 0.98 | 0.95 | 526 |
| accuracy | 0.98 | 8.348 | ||
| macro avg | 0.97 | 0.98 | 0.97 | 8.348 |
| weighted avg | 0.98 | 0.98 | 0.98 | 8.348 |
Sınırlılıklar
- Veri seti sentetik olarak üretilmiştir; uzun format belgeler (aydınlatma metni, sözleşme) için performans düşebilir.
- Model tek kategori döndürür; birden fazla kategori içeren metinler için chunking + dağılım analizi önerilir.
- Maksimum 128 BPE token işleyebilir, daha uzun metinler için chunking gerekir.
- Yalnızca Türkçe metinler için değerlendirilmiştir.
Demo
- Downloads last month
- 267
Space using orkungedik/tr-kvkk-classifier-v2 1
Evaluation results
- accuracy on orkungedik/tr-kvkkself-reported0.980
- f1 on orkungedik/tr-kvkkself-reported0.980