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

orkungedik/tr-kvkk-demo-v2

Downloads last month
267
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Space using orkungedik/tr-kvkk-classifier-v2 1

Evaluation results