raFTI: как сопоставлять «хаотичные» названия вин | |
Привет, я Вит Глинка, backend программист в компании Deeplace, в которой среди прочего активно работают в области winetech. Хочу презентовать нашу последнюю фичу в этой области - raFTI.v5.3 - систему полнотекстового поиска. | |
Работая с винными каталогами, довольно быстро сталкиваешься с неожиданной проблемой. Названия одних и тех же вин могут выглядеть совершенно по-разному. Например: | |
Barolo Riserva 2016 Barolo 2016 Riserva Barolo DOCG Riserva 2016 | |
Иногда различия ещё сильнее: | |
| |
В результате простая задача поиска превращается в задачу интерпретации текста. Несколько лет назад я начал экспериментировать с системой сопоставления названий вин. Постепенно она превратилась в довольно необычную систему, построенную на большом количестве эвристик и правил - raFTI.v5.3 (Relate Assemblies for Full Text Indexation). | |
Хаос названий вин | |
Названия вин часто выглядят как свободные текстовые конструкции. Они могут содержать: сорт винограда / регион / винодельню / тип вина / год / цвет / … | |
Причем порядок этих элементов может меняться. Иногда часть информации вообще отсутствует. Иногда наоборот - добавляются маркетинговые слова. В итоге разные варианты записи могут относиться к одному и тому же вину. | |
Якоря и Модификаторы | |
Некоторые термы в названии играют роль якорей, другие — модификаторов. Якоря определяют основные смысловые точки строки, а модификаторы уточняют их. | |
От групп к шаблонам | |
Сначала система использовала простые группы терминов. Например: | |
сорта винограда / регионы / винодельни / … | |
Но постепенно стало понятно, что названия вин формируются не случайно. Они обычно следуют определённым структурным шаблонам. Поэтому следующим шагом стало выделение подгрупп терминов и построение шаблонов имен. Например: | |
[Winery] [Wine name] [Color] [Type] или [Region] [Grape] [Typology] | |
Когда последовательность подгрупп в названии явно не выделена, такие шаблоны начинают играть роль якорей сопоставления. | |
Маниакальная синонимия | |
Одной из ключевых идей системы стало активное использование синонимов. Со временем эта система приобрела несколько уровней. | |
Первичная синонимия | |
На уровне токенов различными формами одного слова считаются: | |
| |
Все такие варианты получают одинаковую базовую часть индекса. | |
Вторичная синонимия | |
На этапе построения индекса формируются синонимия на уровне термов и их автоматических синонимов: | |
| |
Третичная синонимия | |
Этот уровень формируется из словарей и списков объектов: | |
| |
Четвертичная синонимия | |
Некоторые синонимы накапливаются естественным образом при обработке данных. Например, названия виноделен часто появляются вместе с названиями городов. Такие связи могут использоваться системой как дополнительная подсказка. | |
Семантические триггеры | |
Со временем стало ясно, что чрезмерная синонимия начинает создавать побочные эффекты. Для управления этим процессом был введён механизм семантических триггеров. | |
Триггер - это контекстное условие, которое разрешает или запрещает использование определённых синонимов и/или включает группу характеристик. Например: | |
| |
Со временем оказалось, что этот механизм сам по себе становится мощным инструментом описания семантики. | |
Сигнатура принятого решения | |
Чтобы понимать, почему система делает тот или иной выбор, каждое совпадение описывается компактным кодом из 11 цифр. Каждая позиция отражает вклад определённой компоненты: |
FF NGV RMC SAU | |
Компонент | Назначение |
FF | Final score |
N | Name - критерий заполенности шаблона имени |
G | Grape (сильное влияние на скор) |
V | Vineyard (сильное влияние на скор) |
R | Region (среднее влияние на скор) |
M | Modifiers for class (слабое влияние на скор) |
C | Color (сильное влияние на скор) |
S | Sparcling - CO₂ (сильное влияние на скор) |
A | Anchor - class type (сильное влияние на скор) |
U | Unical words (сильное влияние на скор) |
Значение 3 считается нейтральным / больше 3 - бонус / меньше 3 - штраф. Кроме того компоненты помеченные как (сильное влияние на скор) получают дополнительные штрафы в случае значения меньше чем 3. Влияние важной характеристики Region ослаблено, т.к. в реальных источниках данных эта характеристика сильно зашумлена ошибками и неточностями. Пример: |
(образец поиска) VIN CHATEAU VARTELY TARABOSTE ROSU SEC 0.75L |
(результаты сравнения с винами из БД) |
score | vineyard | wine name |
19 339 339 934 | Chateau Vartely | Taraboste Pinot Noir |
9 339 349 932 | Chateau Vartely | Taraboste Pur Aristocratic Rosu |
9 339 339 924 | Chateau Vartely | Taraboste Reserva Cabernet Sauvignon & Merlot |
(пояснения) Первый результат получил максимум за совпадения: винодельни + цвет + CO₂ (не отраженные характеристики в названиях берутся как значения из БД). Сорта винограда и регион не указаны в образце поиска и на результат не влияют. Совпадение уникального слова Taraboste ценится если нет лишних слов. 2-ой из БД наказан за лишние слова. 3-тий результат наказан за наличие важного (Anchor - class type) слова Reserva, которого нет в образце поиска. |
Когда человек ошибается |
(образец поиска) DIVUS Rara Neagra rosu sec 0.75l, anul 2022 |
(результаты сравнения с винами из БД) |
score | vineyard | wine name |
24 588 339 933 | Divus Winery | Rara Neagra |
12 582 369 933 | Gitana Winery | Rara Neagra Rosu Sec |
(пояснения) На первый взгляд второй вариант выглядит убедительно. Слова (Rosu Sec) в названии играют роль и характеристик и слов модификаторов при их явном указании в названии. Как характеристики они дают обоим образцам призы, как модификаторы приз получает только 2-ой образец, но он сильнее наказывается за не совпадение винодельни. (оператор выбрал 2-ой вариант, по критерию числа совпадений слов) | |
Сравнение алгоритмов матчинга | |
При тестировании raFTI результаты сопоставления сравнивались с классическим полнотекстовым поиском. В частности использовались механизмы поиска, реализованные в MySQL.FTI. Практика показала несколько характерных различий. Полнотекстовый поиск хорошо работает, когда: | |
| |
Однако в случае винных названий часто возникают проблемы: | |
| |
В таких ситуациях обычный поиск начинает возвращать большое количество нерелевантных результатов. raFTI решает эту проблему за счет: | |
| |
В результате пространство кандидатов оказывается значительно меньше, а результаты стабильнее. Многочисленные статистически значимые сравнения результатов матчинга дают следующее распределение верных ответов: |
Матчер | Результат |
MySQL.FTI | 40 % верных ответов |
raFTI.v5.3 | 96 % верных ответов |
Анти-комбинаторный эффект | |
На первый взгляд большое количество эвристик должно приводить к Combinatorial Explosion. Однако на практике наблюдается противоположный эффект. Реальные названия вин формируются внутри ограниченного набора структурных шаблонов. Поэтому дополнительные правила не расширяют пространство поиска, а наоборот помогают быстрее исключать невозможные комбинации. | |
Базовая идея raFTI | |
опирается на методологию Relate Assemblies (RA). Она включает: | |
| |
В частности используются два типа ссылочной целостности: | |
| |
Подробнее о методологии: здесь | |
В "сухом" остатке | |
В эпоху нейросетей система raFTI выглядит довольно "олдскульным" решением. Вероятно, так оно и есть. Это, однако, не мешает ей оставаться эффективным инструментом для задач, где важны прозрачность решений, управляемость знаний и предсказуемость результата. Некоторые идеи, использованные в системе, оказались заметно полезнее, чем ожидалось изначально: | |
| |
В статье описана лишь часть механизмов и принципов, лежащих в основе системы. Многие детали остались за кадром, чтобы не превращать описание в техническую документацию. Практическое применение системы продолжает выявлять новые направления развития. В частности, анализ накопленных первичных синонимов оказался полезен не только для улучшения качества распознавания, но и для обнаружения недостающих связей в предметной модели, а также для уточнения эвристик обработки редких и ошибочных форм данных. | |
Замечания, критика, альтернативные подходы или просто свежий взгляд на проблему будут особенно интересны. | |
ТЕХНОЛОГИИ МЕНЯЮТСЯ, КРИСТАЛЛИЗАЦИЯ ДАННЫХ - НЕТ | |
(помощь, переводы, графика от ChatGPT) |