Turkish KVKK classifier

turkish-kvkk-classifier is a multi-label model that tells you which kinds of personal data a Turkish text contains. It covers 24 categories: the 14 used in VERBİS, Turkey’s data controller registry, and the 10 special categories in Article 6 of KVKK, the Turkish data protection law. It takes about 22 ms per text on a desktop CPU.

Size
110M parameters
Base model
dbmdz/bert-base-turkish-cased (BERTurk)
Labels
24, multi-label
Result
0.874 micro-F1 on 987 held-out texts
CPU speed
about 22 ms per text
Licence
MIT

What it does

Input
hastanın böbrek yetmezliği ilerlemiş, eşi 0532 111 22 33'ten ulaşılabilir
Output
kimlik, iletisim, saglik (special category: yes)
Input
böbrek yetmezliği farkındalık haftası başladı
Output
no label

A category is marked only when the text holds that kind of information about a specific person, even an unnamed one such as “the patient” or “the customer”. General information, rules, announcements and statistics get no label. In the first example a patient’s kidney failure is health data. In the second, an awareness week for kidney failure is not about anyone.

The classifier is meant to sit in front of the masking model: classify the text, pick a masking policy, then mask.

Labels

The 24 labels and their F1 on the held-out set
Label Covers F1
General categories (VERBİS)
kimlik full name, national ID number (TCKN), birth details, age, gender, nationality, marital status, ID document numbers, signature 0.97
iletisim phone, email, postal address 0.97
lokasyon the person’s location, where they are or are going, route 0.74
ozluk an employee’s personnel record: service record, payroll, leave, discipline, social security (SGK) declaration 0.84
hukuki_islem lawsuit, debt enforcement, seizure, official notification, power of attorney, formal notice, mediation 0.89
musteri_islem order, invoice, subscription, request or complaint, policy or contract transaction 0.75
fiziksel_mekan_guvenligi building entry and exit, turnstile, visitor log, security camera 0.83
islem_guvenligi IP address, log, device ID, username, password or PIN, session record 0.83
risk_yonetimi credit score, risk score, suspicious transaction, blacklist, MASAK (Turkey’s financial crimes investigation board) 0.82
finans account, IBAN, card, balance, debt, income or salary, tax number, crypto 0.85
mesleki_deneyim workplace, profession, position, diploma, certificate, reference 0.80
pazarlama shopping habits, preferences, contact consent, survey answers, cookie or segment data 0.83
gorsel_isitsel the person’s photo, voice recording, video, call recording 0.79
arac licence plate, chassis number, engine number, registration document 0.96
Special categories (KVKK Article 6)
saglik illness, diagnosis, treatment, medication, disability, blood type, pregnancy 0.92
biyometrik fingerprint, face recognition, iris or retina, voiceprint 0.88
genetik genetic test, DNA, carrier status 0.79
cinsel_hayat sexual orientation, information about sexual life 0.86
ceza_mahkumiyeti past offences, criminal record, conviction, security measure 0.84
din_felsefi_inanc religion, sect, belief, religious practice 0.93
siyasi_dusunce party membership or preference, political opinion, taking part in a protest 0.85
irk_etnik race, ethnic origin 0.82
dernek_vakif_sendika membership of an association, foundation or trade union 0.89
kilik_kiyafet headscarf, choice of religious or cultural dress 0.91

Results

There are two test sets. The main one is an independent held-out set: 1,125 texts written without looking at the training data, then labelled a second time, blind. The 987 texts where both label sets agree exactly are the gold set (87.7% exact agreement, Cohen’s kappa per label between 0.84 and 1.00). The second is a template-disjoint test of 771 examples from 333 templates that were never used in training. On the 987-text gold set, turkish-kvkk-classifier scores 0.874 micro-F1 and 0.856 macro-F1.

Scores on the two test sets
MetricHeld-out
987 texts
Disjoint test
771 examples
micro-F10.8740.895
macro-F10.8560.875
Special category present: precision0.9600.955
Special category present: recall0.8840.955
Exact match (all labels correct)0.7170.733

Micro-F1 is F1 computed over all label decisions pooled together. Macro-F1 is the unweighted mean of the per-label F1 scores.

The held-out texts and both label passes were produced with a language model and checked automatically. They were not verified line by line by a person.

Python quick start

import json, torch
from huggingface_hub import hf_hub_download
from transformers import AutoModelForSequenceClassification, AutoTokenizer

MODEL = "halilneed/turkish-kvkk-classifier"
tok = AutoTokenizer.from_pretrained(MODEL)
model = AutoModelForSequenceClassification.from_pretrained(MODEL).eval()
thresholds = json.load(open(hf_hub_download(MODEL, "thresholds.json")))
SPECIAL = {"saglik", "biyometrik", "genetik", "cinsel_hayat", "ceza_mahkumiyeti", "din_felsefi_inanc",
        "siyasi_dusunce", "irk_etnik", "dernek_vakif_sendika", "kilik_kiyafet"}

def classify(text):
    with torch.inference_mode():
        p = torch.sigmoid(model(**tok(text, return_tensors="pt", truncation=True, max_length=320)).logits)[0]
    labels = [model.config.id2label[i] for i, v in enumerate(p.tolist()) if v >= thresholds[model.config.id2label[i]]]
    return labels, bool(set(labels) & SPECIAL)

print(classify("hastanın böbrek yetmezliği ilerlemiş, eşi 0532 111 22 33'ten ulaşılabilir"))

Per-label thresholds were tuned on the dev set and ship in thresholds.json. For the special categories the threshold never goes above 0.5, which favours recall.

Measured speed: 22 ms per text at batch size one on an Intel i5-12400F with eight threads, for texts of 126 characters on average.

Training

  • Base model. dbmdz/bert-base-turkish-cased (BERTurk, 110M).
  • Method. Multi-label classification, sigmoid with binary cross-entropy, 5 epochs, learning rate 3e-5, bfloat16, up to 320 tokens.
  • Data. 36,000 synthetic examples from 3,276 templates. Most are the masking model’s templates: each PII slot maps to a category by a fixed rule, and each template is also marked for the categories its context adds. The rest are contextual sentences that contain no values. 21% of the examples are traps, texts that should get no label.
  • Split. Train, dev and test are separated by template hash.

Limitations

  • The training data is synthetic. Measure the model on your own organisation’s text before it goes into a critical pipeline.
  • The weakest labels are lokasyon (F1 0.74), musteri_islem (0.75) and gorsel_isitsel (0.79). All three are inferred from context and have no sharp boundary. genetik also scores 0.79.
  • For the question “is there special-category data here?” recall on the held-out set is 0.884, so roughly one such text in nine is missed.
  • The output is a category signal, not a legal assessment. The VERBİS inventory and KVKK compliance remain the user’s responsibility.

Türkçe KVKK kategori sınıflandırıcısı

turkish-kvkk-classifier, Türkçe bir metinde hangi kişisel veri kategorilerinin bulunduğunu belirleyen çok etiketli bir sınıflandırıcıdır: 14 VERBİS kategorisi ve KVKK md. 6’daki 10 özel nitelikli veri kategorisi. Maskeleme modelinden önce çalıştırılır: metin önce sınıflandırılır, sonuca göre maskeleme politikası seçilir, ardından metin maskelenir.

Eğitim verisine bakılmadan yazılmış 987 metinlik bağımsız sette micro-F1 0.874, macro-F1 0.856’dır. CPU’da metin başına yaklaşık 22 ms sürer. Çıktı yalnızca bir kategori tahminidir, hukuki nitelendirme değildir.