Двуязычный бенчмарк деидентификации для транскриптов психотерапии.
CONFIDE · github.com/glebis/confide · автор Gleb Kalinin и контрибьюторы CONFIDE · опубликовано для исследований и обучения под лицензией репозитория. Транскрипты терапии синтетические/вымышленные — никаких реальных данных пациентов; единственный реальнотекстовый срез (RU-real / JayGuard) — это внешние, анонимизированные, неклинические публичные данные.
Сайт проекта, объяснение простым языком и как поучаствовать: confide.salient.community.
Слой-детектор на базе LLM (ollama) & локальный атакующий: Qwen2.5-3B-Instruct (qwen2.5:3b) через Ollama, температура 0. Детерминированные слои: Natasha (NER для русского), двуязычный regex-слой и OpenAI Privacy Filter (английский).
TL;DR — мы проверяем, насколько хорошо автоматические инструменты приватности скрывают личные данные в транскриптах психотерапевтических сессий (на русском и английском) и какая комбинация инструментов оправдывает свои вычисления.
Как это читать: ★ отмечает рекомендуемый дефолтный стек · столбцы показывают покрытие (больше — лучше) · пустой столбец означает, что эта комбинация не запускалась для данного языка · у каждой таблицы есть ключ с расшифровкой сокращений.
Деидентификация — это не один инструмент, а стек детекторов, и честный вопрос в том, какой слой окупает сжигаемый им CPU. Этот бенчмарк составляет слои-детекторы через объединение спанов на транскриптах психотерапии на русском и английском, оценивает каждую комбинацию так, как это делают опубликованные работы по деидентификации — с приоритетом полноты, на уровне сущностей, прямые против квази — и ставит более острый вопрос, чем “насколько хорош инструмент”: что способна отловить только LLM и что всё ещё утекает после маскирования?
Три типа PII — age 0%, medication 4%, profession 2% — близки к нулю при детерминированных слоях (Natasha NER + regex). Добавление локального слоя qwen поднимает их полноту на уровне упоминаний, но у медикаментов и профессии полнота на уровне сущностей по-прежнему очень низка, потому что должно быть замаскировано каждое упоминание. При этом 31% квази-идентификаторов всё ещё выживают в дефолтном стеке. Маскирование прямых идентификаторов необходимо, но недостаточно.
Именно слой LLM поднимает возраст, медикамент и профессию выше детерминированного базового уровня.
Полнота на уровне упоминаний по категориям для RU (нестрогое перекрытие), 1076 эталонных (gold) упоминаний: детерминированный (natasha+regex) против +qwen.
Структурированные прямые идентификаторы (email, телефон, ID полиса) и имена/организации/локации достигают 0.9–1.0 за счёт regex + Natasha. Даты теперь тоже отлавливаются — правило regex для числовых дат было добавлено после того, как бенчмарк выявил этот пробел.
Квази-идентификаторы, требующие знаний о мире — название препарата, род занятий, прописанный словами возраст — невидимы для паттерн- и NER-слоёв; LLM — единственный слой, который поднимает их полноту на уровне упоминаний.
Оговорка: это полнота на уровне упоминаний. На уровне сущностей (замаскированы все упоминания) медикаменты и профессия остаются на 0 даже с qwen — это более высокая планка.
Столбцы показывают полноту покрытия; ★ — это предлагаемый дефолтный стек, который жертвует небольшой полнотой ради значительного выигрыша в скорости/точности — не всегда самый высокий столбец.
Полнота покрытия по комбинациям на отображённых датасетах. Отсутствующий столбец означает, что комбинация не запускалась на этом языке (см. примечание), а не нулевую оценку. ★ = предлагаемый дефолтный стек; см. таблицу для F2/точности.
Русский язык использует только стек с приоритетом локального исполнения — Natasha + regex + qwen2.5:3b. Три детектора по замыслу работают только с английским, поэтому у любой комбинации с ними нет столбца RU: Presidio (его RU зависит от spaCy-NER и слаб — оставлен без оценки, а не искажён), Philter (набор правил для английских клинических записей) и OpenAI Privacy Filter (английский классификатор токенов). Это решение о границах охвата, а не измеренный сбой на RU.
RU: предлагаемый дефолтный стек natasha+regex+ollama ★ достигает полноты покрытия 88%. Строка OPF-на-RU опущена, пока кэш её детектора не будет перегенерирован для текущего корпуса из 30 документов.
EN-synth: OPF — это основа для имён/адресов (English’s Natasha, англоязычный аналог). Дефолтный opf+regex+ollama ★; opf+regex чуть опережает его по F2.
RU-real (JayGuard): на внешнем реальном русском тексте локальный стек достигает высокого покрытия — реальнотекстовый якорь для в остальном синтетического RU-корпуса (только PERSON/LOCATION).
| combo | cov R↑ | cov F2↑ | ent R↑ | direct↑ | quasi↑ | preds |
|---|---|---|---|---|---|---|
| regex | 0.071 | 0.086 | 0.398 | 0.407 | 0.390 | 85 |
| natasha | 0.775 | 0.752 | 0.301 | 0.370 | 0.237 | 1151 |
| ollama·qwen2.5:3b | 0.293 | 0.329 | 0.230 | 0.185 | 0.271 | 421 |
| natasha+regex | 0.846 | 0.807 | 0.699 | 0.778 | 0.627 | 1236 |
| natasha+ollama·qwen2.5:3b | 0.825 | 0.774 | 0.487 | 0.537 | 0.441 | 1333 |
| regex+ollama·qwen2.5:3b | 0.342 | 0.379 | 0.469 | 0.463 | 0.475 | 480 |
| natasha+regex+ollama·qwen2.5:3b ★ | 0.875 | 0.811 | 0.726 | 0.815 | 0.644 | 1392 |
| natasha+regex+gemma3 ◇ | 0.954 | 0.366 | 0.850 | 0.907 | 0.797 | 9093 |
| natasha+regex+gliner ◇ | 0.980 | 0.412 | 0.885 | 0.889 | 0.881 | 7927 |
◇ — экспериментальная замена в ★-стеке (LLM Gemma или NER-слой GLiNER): отдельный кэш детектора, не продвинутый дефолт (проверки дисперсии и продвижения не пройдены; см. раздел «Сравнение моделей»).
RU-real (срез JayGuard) — 60 док., 77 эталонных упоминаний (внешний, анонимизированный, реальный, но неклинический русский текст — Apache-2.0; только PERSON/LOCATION, эталон получен машинно, без человеческой адъюдикации)
| combo | cov R↑ | cov F2↑ | ent R↑ | direct↑ | quasi↑ | preds |
|---|---|---|---|---|---|---|
| regex | 0.000 | 0.000 | 0.000 | 0.000 | 0.000 | 13 |
| natasha | 0.403 | 0.418 | 0.403 | 0.358 | 0.700 | 63 |
| ollama·qwen2.5:3b | 0.610 | 0.547 | 0.610 | 0.657 | 0.300 | 160 |
| natasha+regex | 0.403 | 0.404 | 0.403 | 0.358 | 0.700 | 76 |
| natasha+ollama·qwen2.5:3b | 0.792 | 0.674 | 0.792 | 0.791 | 0.800 | 180 |
| regex+ollama·qwen2.5:3b | 0.610 | 0.547 | 0.610 | 0.657 | 0.300 | 160 |
| natasha+regex+ollama·qwen2.5:3b ★ | 0.792 | 0.674 | 0.792 | 0.791 | 0.800 | 180 |
| natasha+regex+gemma3 ◇ | 0.961 | 0.772 | 0.961 | 0.970 | 0.900 | 201 |
| natasha+regex+gemma4-12b-mlx ◇ | 1.000 | 0.830 | 1.000 | 1.000 | 1.000 | 172 |
◇ — экспериментальная замена в ★-стеке (LLM Gemma или NER-слой GLiNER): отдельный кэш детектора, не продвинутый дефолт (проверки дисперсии и продвижения не пройдены; см. раздел «Сравнение моделей»).
EN-synth — 32 док., 46 эталонных (gold) упоминаний (нет уровня сущностей / деления на прямые-квази: англоязычные наборы не содержат поэлементной аннотации entity_id, поэтому оценивается только покрытие на уровне упоминаний)
| combo | cov R↑ | cov F2↑ | preds |
|---|---|---|---|
| regex | 0.370 | 0.419 | 19 |
| opf | 0.783 | 0.818 | 38 |
| ollama·qwen2.5:3b | 0.500 | 0.525 | 49 |
| opf+regex | 0.913 | 0.921 | 46 |
| opf+ollama·qwen2.5:3b | 0.848 | 0.815 | 58 |
| regex+ollama·qwen2.5:3b | 0.761 | 0.743 | 59 |
| opf+regex+ollama·qwen2.5:3b ★ | 0.978 | 0.910 | 66 |
| natasha+regex+ollama·qwen2.5:3b | 0.783 | 0.758 | 61 |
| presidio | 0.913 | 0.907 | 51 |
| philter | 0.783 | 0.799 | 47 |
| presidio+regex+ollama·qwen2.5:3b | 0.935 | 0.880 | 66 |
| opf+regex+gemma3 ◇ | 1.000 | 0.945 | 62 |
| opf+regex+gemma4-12b-mlx ◇ | 1.000 | 0.976 | 54 |
| opf+regex+gemma4-26b·cloud ◇ | 1.000 | 0.984 | 52 |
| opf+regex+gliner ◇ | 0.957 | 0.800 | 91 |
◇ — экспериментальная замена в ★-стеке (LLM Gemma или NER-слой GLiNER): отдельный кэш детектора, не продвинутый дефолт (проверки дисперсии и продвижения не пройдены; см. раздел «Сравнение моделей»).
На проверке сложных форм полный стек отлавливает 19/20 состязательных идентификаторов — единственная утечка — это русское имя в латинской транслитерации.
| combo | cov R↑ | cov F2↑ | ent R↑ | direct↑ | quasi↑ | preds |
|---|---|---|---|---|---|---|
| regex | 0.400 | 0.455 | 0.400 | 0.471 | 0.000 | 8 |
| natasha | 0.350 | 0.389 | 0.350 | 0.353 | 0.333 | 10 |
| ollama·qwen2.5:3b | 0.650 | 0.663 | 0.650 | 0.588 | 1.000 | 25 |
| natasha+regex | 0.750 | 0.765 | 0.750 | 0.824 | 0.333 | 18 |
| natasha+regex+ollama·qwen2.5:3b ★ | 0.950 | 0.887 | 0.950 | 0.941 | 1.000 | 30 |
| natasha+regex+gemma3 ◇ | 1.000 | 0.917 | 1.000 | 1.000 | 1.000 | 32 |
| natasha+regex+gemma4-12b-mlx ◇ | 1.000 | 0.948 | 1.000 | 1.000 | 1.000 | 28 |
| natasha+regex+gemma4-26b·cloud ◇ | 1.000 | 0.943 | 1.000 | 1.000 | 1.000 | 26 |
| natasha+regex+gliner ◇ | 1.000 | 0.826 | 1.000 | 1.000 | 1.000 | 41 |
◇ — экспериментальная замена в ★-стеке (LLM Gemma или NER-слой GLiNER): отдельный кэш детектора, не продвинутый дефолт (проверки дисперсии и продвижения не пройдены; см. раздел «Сравнение моделей»).
16 фрагментов, 20 эталонных (gold) форм: отчества, транслитерация, уменьшительные формы, никнеймы VK/Telegram, СНИЛС/ИНН/паспортные идентификаторы, сокращённые адреса и переключение кодов (code-switching).
Regex отлавливает структурированные идентификаторы и никнеймы; Natasha + qwen2.5:3b восстанавливают отчества, уменьшительные формы и переключение кодов (code-switching). Единственная остаточная утечка — это “Sergey Volkov”, русское имя в латинской транслитерации: Natasha работает только с кириллицей, у regex нет правила для имён, а qwen его пропустил. Это аргумент в пользу добавления английского/латинского NER (OPF), когда ожидается транслитерация.
Экспериментальная замена модели показывает, что Gemma превосходит базовую Qwen на каждом полном коротком срезе; локальная Gemma4 сильнее всего на русских наборах, а облачная HF Gemma4 лидирует на английском стеке и стабильна на 5 репликах. GLiNER-multi — локальный zero-shot NER-слой — представлен на тех же условиях. ★-дефолты не меняются, пока не пройдены проверки дисперсии и продвижения.
| dataset | model | cov R↑ | cov F2↑ | ent R | preds |
|---|---|---|---|---|---|
| RU-synth long | Qwen2.5-3B | 0.875 | 0.802 | 0.726 | 1392 |
| RU-synth long | Gemma3 | 0.954 | 0.362 | 0.850 | 9093 |
| RU-synth long | GLiNER-multi PII (zero-shot NER) | 0.980 | 0.407 | 0.885 | 7927 |
| RU-adv | Qwen2.5-3B | 0.950 | 0.887 | 0.950 | 30 |
| RU-adv | Gemma3 | 1.000 | 0.917 | 1.000 | 32 |
| RU-adv | Gemma4 12B-MLX | 1.000 | 0.948 | 1.000 | 28 |
| RU-adv | Gemma4 26B-A4B (HF cloud) | 1.000 | 0.943 | 1.000 | 26 |
| RU-adv | GLiNER-multi PII (zero-shot NER) | 1.000 | 0.826 | 1.000 | 41 |
| RU-real | Qwen2.5-3B | 0.792 | 0.614 | 0.792 | 180 |
| RU-real | Gemma3 | 0.961 | 0.730 | 0.961 | 201 |
| RU-real | Gemma4 12B-MLX | 1.000 | 0.820 | 1.000 | 172 |
| EN-synth | Qwen2.5-3B | 0.978 | 0.870 | — | 66 |
| EN-synth | Gemma3 | 1.000 | 0.904 | — | 62 |
| EN-synth | Gemma4 12B-MLX | 1.000 | 0.955 | — | 54 |
| EN-synth | Gemma4 26B-A4B (HF cloud) | 1.000 | 0.962 | — | 52 |
| EN-synth | GLiNER-multi PII (zero-shot NER) | 0.957 | 0.782 | — | 91 |
Строки — оценки стеков из отдельных кэшей детекторов, сгенерированные score_llm_experiment.py. Облачные строки использовали только синтетический текст. Chunking Gemma3 на длинном RU-срезе включён как компромисс полноты и шума, а не как продвинутый дефолт; отсутствующие строки опущены, а не засчитаны как ноль.
Прямые идентификаторы достигают полноты на уровне сущностей 0.81; квази-идентификаторы остаются ниже — 0.64.
Полнота на уровне сущностей для RU (сущность защищена, только если замаскированы все упоминания) по классам идентификаторов.
Прямые (имя, телефон, email, полис): замаскированы с полнотой на уровне сущностей 0.81 в дефолтном стеке.
Квази (возраст, профессия, город, работодатель, медикамент, дата): LLM помогает, но потолок остаётся низким — именно эти атрибуты в совокупности реидентифицируют человека.
31% квази-идентификаторов выживают в дефолтном стеке (оба клиента); избыточное маскирование стоит 20% от объёма маскирования.
Метод — по образцу литературы о реидентификации / атаках вывода (inference) (Staab et al.; RAT-Bench; Tau-Eval). Сущность выживает, если хотя бы одно из её упоминаний осталось незамаскированным.
Локальный атакующий на базе 3B qwen восстановил 2 of 10 проверенных атрибутов из замаскированного текста (например, медикамент, поскольку его полнота на уровне сущностей равна 0). Слабый атакующий — это нижняя оценка: литература об атаках вывода (inference) (Staab et al.) сообщает о гораздо более высоких показателях реидентификации для передовых моделей.
Вывод: маскирование прямых идентификаторов — это базовый минимум; выживаемость квази-идентификаторов — полезный фильтр для проверки перед отправкой сессии на облачный анализ.
Слабый локальный атакующий восстанавливает 1/10 атрибутов (top-3); при этом 91% клинического сигнала переживает маскирование.
Метод — атака вывода (inference) top-k с фиксированным, заявленным бюджетом (qwen2.5:3b, temp 0.4, top-3 догадки на атрибут, только замаскированный текст) + сохранение нижестоящей задачи (повторный запуск извлечения когнитивных искажений на замаскированном vs. оригинальном тексте). Согласовано со Staab et al. / RAT-Bench (приватность) и Tau-Eval (полезность с учётом задачи).
То же маскирование, что снижает успех атакующего, может стереть клиническое содержание. Здесь это не так: дефолтный стек сохраняет ~91% сигнала искажений и 99.5% не-PII текста, в то время как слабый атакующий не восстанавливает ничего в top-3.
Оговорка: этот атакующий — нижняя оценка: квази-идентификаторы по-прежнему выживают в тексте (полнота на уровне сущностей для медикаментов равна 0), поэтому передовой атакующий показал бы более высокий результат. Остаточный риск для клиента B остаётся СРЕДНИМ.
Готовые деидентификаторы могут не уступать стеку по покрытию, но сильно отстают по типозависимому micro-F1.
EN-synth: полнота F2 (с весом полноты, главное) против micro-F1 с учётом типа для стека CONFIDE ★ и устоявшихся базовых решений.
Полнота F2 (оранжевый) спрашивает лишь “замаскировали ли мы спан вообще”. Тип. micro-F1 (зелёный) требует ещё и правильную метку — то, что на самом деле нужно политике маскирования.
На EN-synth Presidio чуть опережает стек по полноте F2 (за счёт широкого распознавателя DATE_TIME), но его F1 по типам гораздо ниже; Philter даёт высокое покрытие, но почти всё помечает как нетипизированное OTHER, поэтому его F1 по типам непригодна к использованию.
Главное: типовая система — это не система, настроенная под терапию; единственное покрытие, которое добавляет базовая модель, — это относительные/разговорные даты.
Метрики обнаружения измеряют то, что мы ловим; регуляторов же волнует то, что выживает. В проекции на названные риски дефолтный RU-стек оказывается на уровне RED — это обусловлено наличием 9 релевантных остаточных сущности прямых идентификаторов (ключ реидентификации, оставленный в тексте). Ещё 1 — это прописанные словами цифровые идентификаторы, по замыслу выходящие за рамки regex-слоя и описанные отдельно.
Все датасеты, бок о бок
| датасет | tier | direct res | special res | HIPAA | worst doc | inf rate | link AUC |
|---|---|---|---|---|---|---|---|
| RU | RED | 9 | 6 | 4/6 | 70% | 20% | 0.46 |
| EN-synth | AMBER | 0 | 0 | 6/7 | 0% | 20% | 0.46 |
Уровень остаточного риска по каждому языку под ★-дефолтным стеком этого языка. RU получает RED (прямые идентификаторы утекают по строгому критерию сущностей TAB); EN получает AMBER (утечки прямых ID нет, но ненулевой вывод / неполное покрытие HIPAA). Полнота на худшем документе для EN — 0%, потому что при крошечном эталоне один документ с PII может быть полностью пропущен — это шум малой выборки, а не системный сбой EN. Подробности по RU — ниже.
Триада реидентификации WP29 (Art-29 WP 05/2014) — идентифицируемость раскладывается на выделение (singling out) (остаточная квази-поверхность через оценку по доле популяции с оговорками — НЕ k-анонимность корпуса, N крошечный), связываемость (linkability) (попарная связываемость сессий, ROC AUC 0.46 — площадь под ROC-кривой: 1.0 = идеально связываемо, 0.50 = не лучше случайного угадывания, что и есть безопасное направление), и вывод (inference) (атака восстановления атрибутов извлекает 20%). Покрытие HIPAA — это контрольный список «в духе» Safe-Harbor, а не юридическое заключение (AGE — н/п; структурные ID схлопнуты).
RED = любой релевантный прямой идентификатор утекает на уровне сущностей (одно незамаскированное упоминание — это ключ). AMBER = остаток особой категории, ненулевой вывод (inference) или связываемость (linkability) выше случайной. GREEN = всё чисто.
Что утекает: не имена целиком, а конкретные варианты — словоизменённые/притяжательные/отчественные формы (Артёмом, Натальин, Денису), фамилии со строчной буквы, звательные формы, латинская транслитерация (Timur) и коллизии имени с обычным словом (Вера, Роман). Полнота на уровне упоминаний это скрывает; строгая планка сущностей TAB (один промах ⇒ не защищено) выявляет это.
Оценка выделения (singling out) иллюстративна (метод на основе доли популяции с оговорками, а не k-анонимность корпуса) — это не гарантия невозможности идентификации.
Каждый детектор запускается один раз на датасет; комбинации — это объединения спанов из кэша, слитые по интервалам в развёрнутую маску редактирования перед оценкой. В заголовке отчёта — полнота покрытия (нестрогое перекрытие), приватностно-критичный показатель; полнота-взвешенный F2 и точность приведены в таблице лидеров. Также сообщаются типозависимый micro/macro-F1 (i2b2) и полнота на уровне сущностей (TAB; замаскированы все упоминания). Числа даны на уровне упоминаний, если не указано иное. Эталон для RU локализован из двух PII-инвентарей «ключа ответов» и проверен вручную (восстановление заложенного сигнала, не независимо размеченный эталон); набор EN — это курируемый синтетический срез, а единственный реальнотекстовый якорь — внешний срез RU-real (JayGuard). Преимущественно синтетические данные — никаких реальных пациентов. Малое N: считайте показатели по типам ориентировочными.
CONFIDE-Bench опирается на перечисленную ниже литературу по деидентификации, реидентификации и документированию. Каждая работа, упомянутая или использованная в этом отчёте, указана здесь со ссылкой на её каноническую страницу (DOI / arXiv / HuggingFace / GitHub). Мы указываем только то, что отчёт действительно использует; включение не означает одобрения со стороны их авторов.
philter-lite — это форк Sirona Medical. github.com/SironaMedical/philter-lite · PyPIopenai/privacy-filter. Модель классификации токенов PII под лицензией Apache-2.0 (используется как основа для имён/адресов в EN). В карточке модели указано, что это вспомогательный инструмент маскирования / минимизации данных, а не гарантия анонимизации или соответствия требованиям. huggingface.co/openai/privacy-filter