Pull to refresh

Определение пола по ФИО – когда точность действительно важна

Reading time 7 min
Views 43K
Некоторое время назад меня заинтересовала задача определения пола человека по его ФИО. В тот момент я работал в области медицинского страхования, где эта проблема была действительно актуальна – расходы на одного застрахованного, а значит и тарифы, по которым людей принимали на страхование, в зависимости от пола клиента, могли отличаться в несколько раз. Большая часть договоров – корпоративные, застрахованные являются сотрудниками работодателя.

Мы никогда не видели большинство из них в глаза, все, что мы имели – списки застрахованных, где пол иногда был указан (с большим количеством ошибок), но чаще – не указан вообще. Большинство компаний имеют свою специфику работы и профессиональные традиции, в силу чего, в их коллективах преобладают люди одного пола. Даже небольшая ошибка могла сделать потенциально прибыльный договор убыточным (или наоборот, но на такое, по странному стечению обстоятельств, случалось с нашими клиентами гораздо реже). В целом, при объеме портфеля договоров в несколько миллиардов, и характерном количестве ошибок около процента, цена корректного определения пола по ФИО была в районе нескольких десятков миллионов.

В рунете тема определения пола по ФИО поднималась уже неоднократно, но, в большинстве случаев, все сводилось к рекомендации внимательно смотреть на окончание отчества («вич»/«вна») или использовать какие-то подобные найденные вручную закономерности. К сожалению, в моей ситуации этот метод не подходил – среди застрахованных было много, действительно много, иностранцев. Правильное написание их отчества не содержало никаких признаков искомого окончания (а в некоторых случаях отсутствовало и само отчество).

Поэтому для решения задачи я решил использовать статистический подход – по существующей базе клиентов определять к какому полу обычно принадлежат люди с искомыми фамилией, именем и отчеством и, по этим данным, относить новых застрахованных к тому или иному классу. Если часть ФИО принадлежала преимущественно мужчинам – я начислял +1 балл, если женщинам – минус один балл, если было примерно поровну – начислялось 0 баллов. Результат по всем трем частям складывался и, если сумма была больше или равна +2, пол определялся как мужской; меньше или равен -2 – как женский; в противном случае считалось что пол определить не удалось и нужно рассчитывать его другими методами.

Как ни странно, подобный, очень простой алгоритм, позволил добиться потрясающей точности – на выборке в несколько сотен тысяч человек (при базе для обучения в полтора миллиона) было допущено всего 6 ошибок (которые будут описаны ниже и каждую из которых, вполне вероятно, живой человек тоже совершил бы).

Некоторые подробности предварительной подготовки обучающей выборки:

  • Все ФИО должны содержать в своем составе либо только кириллицу, либо только латиницу;
  • Допустимы только буквы, пробелы, дефисы и символ одинарной кавычки. Все остальные символы должны быть либо удалены либо заменены на близкие им. Между дефисом и близкими к нему буквами должны отсутствовать пробелы;
  • Все буквы должны быть в одном регистре (или все должны иметь первую букву – заглавную, остальные – строчные);
  • Между частями ФИО должны быть только одинарные пробелы, с краев ФИО не должно быть лишних пробелов;
  • Деление строки с ФИО на три части осуществляется по первому и второму пробелу. Если части всего две – отчество равно null, если больше трех – отчество это все, что после второго пробела.

Поскольку всю логику я писал на PL/SQL, то выкладывать целиком пакет с реализацией алгоритма я не буду – он очень завязан на внутреннюю структуру базы и особенности хранения данных, однако я хотел бы упомянуть несколько особенностей:

Поскольку каждый раз, когда требуется определить пол человека, пробегаться по таблице контрагентов со всеми записями долго, то агрегированную информацию о частотах появления определенной части ФИО в хранимых данных я разместил во вспомогательной таблице. Выглядит это как четверка параметров – [часть ФИО – тип (Ф, И или О)– пол – число записей в базе]. Статистика обновляется еженедельно, автоматически.

Для определения того, какое соотношение мужчин и женщин для одной части ФИО считать достаточным основанием для причисления его к тому или иному полу, я использовал следующую функцию:

-- по числу мужчин (первый параметр) и женщин (второй параметр) определяет пол
-- +1 - мужчина
--  0 - не известно
-- -1 - женщина
function get_sex_by_cnt (mcnt number, fcnt number) return number
is
begin
  if mcnt=fcnt then return 0; end if; -- очевидная неопределенность
  if mcnt<=2 and fcnt<=2 then return 0; end if; -- слишком мало информации для анализа
  if mcnt>=3 and fcnt=0 then return 1; end if; -- обработка нулей номер 1
  if mcnt=0 and fcnt>=3 then return -1; end if;  --обработка нулей номер 2
  if mcnt/fcnt>0.5 and mcnt/fcnt<2 then  return 0; end if; -- перевес одного пола не решающий
  if mcnt>fcnt then return 1; end if;  -- ну и наконец. очевидно мужчина
  if mcnt<fcnt then return -1; end if; -- очевидно женщина
end;  --  get_sex_by_cnt

Если по ФИО определить пол не удалось (суммарное значение оценок находится в диапазоне [-1;1]), то, в большинстве случаев, можно пренебречь фамилией и использовать только ИО – с тем же критерием корректности работы (+2 – мужчина, -2 – женщина, иначе – пол не определен). Это помогает обойти ситуации, когда неизменяемая фамилия вроде «Тимошенко» ошибочно приписывается одному полу, а имя и отчество принадлежат противоположному.

Ошибки алгоритма. Я обнаружил три ситуаций, когда алгоритм может выдать некорректный результат:

  1. Азиаты. В китайском языке отсутствуют формальные признаки позволяющие отнести имя к определенному полу. Вероятно, сказанное относится и к некоторым другим языкам (как минимум, могу предположить это про тайский, вьетнамский и корейский) Т.е. по ФИО определить пол невозможно в принципе. Данная причина ответственна за 3 обнаруженных ошибки работы функции из 6. В среднем, число мужчин и женщин с азиатскими именами оказалось равно, однако некоторые (в основном редкие имена и фамилии) принадлежали преимущественно одному полу. Какого-то простого решения кроме дальнейшего набора статистики трудно предложить, однако это не решит проблему полностью. Трудное, но относительно надежное решение — можно написать функцию определяющую – является имя азиатским или нет (я еще не сделал этого, но, судя по моей беседе с коллегой-переводчиком, это возможно) и для всех азиатов возвращать 0 вне зависимости от собранной статистики.
  2. Инициалы. В некоторых случаях ФИО заносится в базу в виде «Иванов И И». Отдельные буквы воспринимаются функцией как имя и отчество, они участвуют в общей статистике и влияют на принятие решения о поле человека. При занесении в базу нового человека с ФИО вроде «Ковальчук О И» могут возникнуть расхождения реального пола с вычисленным. Эта причина ответственна за одну ошибку из обнаруженных шести. Бороться с такими ошибками можно, например, присваивая однобуквенным фамилиям именам и отчествам нулевой пол вне зависимости от собранной статистики.
  3. Имена, которые значительно чаще использует один пол, чем другой или практика применения которых отличается в разных странах. Две ошибки из обнаруженных шести. Пример (я немного исказил реальные имена, на которых возникла ошибка, чтобы не разглашать персональные данные): Мохамад Сулейман Фархонда (женщина) и Саша Александр Джеферсон (женщина, гражданка США). Я не знаю, возможно ли подобные случаи исправить алгоритмически, поэтому просто добавил эти имена в таблицу исключений.

Как искались ошибки работы функции: был установлен запрет на занесение в базу компании новых застрахованных с полом отличным от определенного функцией. В случае возникновения подобной ошибки, сотрудники компании связывались с организацией предоставившей списки застрахованных и уточняли у нее реальный пол человека. Таким образом, все случаи расхождения реальных и расчетных данных обрабатывались в ручном режиме. Общее количество людей прошедших подобную проверку – около 250 тыс.

К сожалению, данный метод не является серебряной пулей, он просто лучше всех других, которые я встречал. Я тестировал метод на нескольких базах данных в разных компаниях. К минусам можно отнести то, что для части людей из-за недостаточной статистики определить пол по ФИО нельзя: на базе в 1,5 млн человек таких людей чуть больше 1%, на базе в 300 тыс человек таких около 3%, на базе в 6 млн человек не удалось определить пол для 0,8%. У меня есть предположение, что процент людей, для которых пол не может быть определен, обратно пропорционален корню из размера обучающей выборки, но никакого объяснения — почему именно так происходит, у меня нет. Конечно, процент людей, для которых пол может быть определен можно увеличить (и даже довести почти до 100%) установив более мягкие условия на то, когда человеку можно присвоить какой-либо пол, но для задач, с которыми я работал, была важнее точность, чем 100%-ное отнесение к одному из двух классов.

Другой недостаток, которому подвержен данный метод – плохая работа с опечатками. Несмотря на то, что некоторые из них довольно стандартны (имя «Олга» встречается чаще, чем, например, вполне правильное «Октябрина»), для большинства опечаток статистика будет отсутствовать => определить пол по такому имени будет не всегда возможно. К сожалению, обратное утверждение (если искомое имя еще ни разу не встречалось в базе, значит оно написано не правильно) не верно – людей с уникальными именами не меньше, чем опечаток в именах обычных людей.

Как и у любого инструмента, у этого есть особенности, о которых не задумываешься при создании.

  1. Набранная статистика позволяет искать имена написанные с ошибками определенного типа. Если одна часть ФИО согласно набранной статистике имеет один пол, а другая – другой, вероятно имеет место опечатка. Пример – «Иванов Наталья Сергеевна». В данном случае, наиболее вероятно, что допущена опечатка в фамилии – забыта буква «а» в конце.
  2. Если большая часть данных в обучащей выборке будет представлена преимущественно в одном формате (Ф-И-О), то опираясь на собранные данные появляется возможность искать ФИО написанные в другом порядке (например, И-O-Ф) – просто на основе того к какой части ФИО обычно принадлежит искомая часть. Это может иметь значение, если компания проводит рассылки в духе «Уважаемый Олег Константинович!».
  3. В тех случаях, которые я наблюдал на практике, процент ошибок в обучающей выборке не влияет ни на точность прогноза, ни на количество имен, которые не удалось отнести к тому или иному классу. В одном из случаев, с которым я имел дело, процент ошибок определения пола в обучающей выборке был около 4%, после их исправления и повторного сбора статистики количество имен для которых не удалось определить ФИО, изменилось меньше чем на 1%.


UPD 1
В комментариях было предложено много необычных имен, я проверил — как они будут определяться предложенным выше алгоритмом. По ссылке – предложенные имена и их вариации с оценками пола по фамилии, имени и отчеству.
UPD 2
Ниже было высказано предположение, что определение пола по ФИО является типичной задачей классификации. Я нашел у себя данные по 500 тыс человек для каждого из которых известны последние буквы фамилии (ssecondname), имени (sname) и отчества (sthirdname), цифры 3, 2 и 1 означают сколько последних символов от этой части ФИО было использовано. К сожалению, другой подобной выборки у меня нет, как и возможности сделать ее с другим набором признаков для исследования.
Также я построил на этих данных дерево решений:
Не усеченное (а значит, и, неизбежно, переобученное): h1analysis.ru/analysis/download/89
Усеченное таким образом, чтобы удалить все ветви содержащие менее 10 человек: h1analysis.ru/analysis/download/90
Качество классификации я не проверял. Усечений методами вроде 30/70 тоже не делал.
Tags:
Hubs:
+26
Comments 57
Comments Comments 57

Articles