<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/">
  <channel>
    <language>ru</language>
    <title>Рекомендательные системы</title>
    <description>Рекомендательные системы — это алгоритмы, использующие данные о поведении пользователей и их предпочтениях для того, чтобы предложить наиболее релевантные продукты, контент или услуги. Они широко применяются в таких областях, как онлайн-магазины, стриминговые сервисы, социальные сети и другие платформы, помогая улучшить пользовательский опыт и увеличить конверсии.</description>
    <link>https://tproger.ru/tag/recommendation-system</link>
    <atom:link href="https://tproger.ru/tag/recommendation-system/feed" rel="self" type="application/rss+xml"/>
    <lastBuildDate>Sat, 03 Oct 2026 22:54:56 GMT</lastBuildDate>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>12</sy:updateFrequency>
    <image>
      <title>Рекомендательные системы</title>
      <link>https://tproger.ru</link>
      <url>https://tproger.ru/apple-touch-icon.png</url>
    </image>
    <item>
      <title>Как устроены рекомендации с LLM: холодный старт, RAG и zero-shot ранжирование</title>
      <link>https://tproger.ru/articles/kak-ustroeny-rekomendacii-s-llm-holodnyj-start-rag-i-zero-shot</link>
      <comments>https://tproger.ru/articles/kak-ustroeny-rekomendacii-s-llm-holodnyj-start-rag-i-zero-shot?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Валерия Турчак]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/kak-ustroeny-rekomendacii-s-llm-holodnyj-start-rag-i-zero-shot</guid>
      <description><![CDATA[<p>Как LLM меняют рекомендательные системы: холодный старт, семантический поиск, RAG, zero-shot ранжирование и новые метрики качества.

</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/kak-ustroeny-rekomendacii-s-llm-holodnyj-start-rag-i-zero-shot">Как устроены рекомендации с LLM: холодный старт, RAG и zero-shot ранжирование</a>»</p>]]></description>
      <category><![CDATA[Инструменты]]></category>
      <category><![CDATA[Аналитика]]></category>
      <category><![CDATA[Рекомендательные системы]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Mon, 08 Jun 2026 07:48:53 GMT</pubDate>
      <content:encoded><![CDATA[<p>Мы поговорили с экспертом, чтобы узнать, как сейчас работают рекомендательные системы с LLM и почему мы так долго сидим в соцсетях. Этот опыт можно применить для своих проектов, потому что масштабы будут только наращиваться, а базу знать нужно уже сейчас. <br /></p><p>Архитектура рекомендательных систем долгое время строилась исключительно вокруг матричной факторизации и коллаборативной фильтрации. Традиционный подход опирался на анализ поведенческих паттернов и историю совместных действий: если пользователи часто кликали на одни и те же товары, алгоритм считал их векторы интересов похожими. При этом система оперировала лишь числовыми идентификаторами (ID) и оставалась невосприимчивой к внутренним свойствам самого контента.</p><p>Сейчас индустрия переходит к семантическому профилированию. Большие языковые модели (LLM) позволяют архитектуре понимать контент на уровне смыслов, извлекая данные из текстовых описаний, отзывов и характеристик. Если раньше для рекомендаций нужен был массив данных о покупках, то теперь логика меняется.</p><p>Допустим, клиент выбирает большую 4-местную кемпинговую палатку (Фактор А) и одновременно добавляет в корзину два детских спальных мешка (Фактор Б). LLM не просто ищет товары с тегом «кемпинг» . Она сопоставляет эти данные со своими знаниями о мире и делает логический вывод (Вывод В): планируется семейный выезд на природу с маленькими детьми. На основе этого синтеза система рекомендует не банальный фонарик, а мощный фумигатор повышенной безопасности для закрытых тентов или портативный подогреватель детского питания, работающий от прикуривателя.</p><h2>Где потолок?</h2><p>За последние десять лет двухступенчатый конвейер retrieval-ranking  стал стандартом индустрии рекомендаций: сначала быстрый алгоритм генерирует сотни кандидатов из каталога, а затем тяжелая модель ранжирует этот шорт-лист, предсказывая вероятность клика. Этот подход работает отлично, но имеет пределы. Команды разработки постоянно сталкиваются с тремя фундаментальными проблемами:</p><ol><li>Холодный старт. Стандартные подходы полностью зависят от активности аудитории. При загрузке в онлайн-кинотеатр нового фильма алгоритмы чистой коллаборативной фильтрации сталкиваются с проблемой «нулевого вектора»  (отсутствием строки или столбца взаимодействий в матрице). Система не может рассчитать близость нового объекта к интересам пользователей, из-за чего новинки могут неделями оставаться мертвым грузом на дне каталога.</li><li>Проблема «усредненного товара». В классических системах и покупатель, и товар — это лишь векторы в пространстве. Когда пользователь вводит сложный запрос (например, «мощный игровой ноутбук, который не перегревается и выглядит строго для офиса»), классический алгоритм пытается найти точку где-то посередине между мощностью и дизайном. В итоге вектор запроса смещается в зону универсальных домашних ноутбуков, которые не тянут игры и выглядят дешево. В этом случае система усредняет координаты, теряя специфические требования. LLM же не усредняет, а рассуждает: она видит каждое условие как отдельный логический фильтр и ищет товар, который удовлетворяет всем критериям одновременно.</li><li>Гибкость без переписывания кода. В традиционной архитектуре признаки товара жестко заданы инженерами (цена, бренд, категория). Если бизнес хочет внедрить новый критерий, например «экологичность материалов», начинается долгий процесс: нужно нанять людей для разметки тысяч товаров, изменить структуру базы данных и переобучить модель. Это занимает месяцы. В LLM-архитектуре этот признак уже существует бесплатно. Модель может извлечь информацию об экологичности напрямую из описаний или отзывов в момент запроса. Не нужно менять код или переучивать систему, достаточно просто попросить модель учитывать этот параметр.</li></ol><h2>Уровни интеграции LLM: архитектура LLMERS</h2><p>Интеграция LLM в рекомендательные системы требует разделения контуров вычислений. Важно разделять архитектуры: если классические трансформеры в RecSys (например, модели класса BERT4Rec) оптимизированы под обработку последовательностей action_id и ID товаров, то большие генеративные языковые модели работают с сырым текстом и смыслами. Если заставить тяжелую авторегрессионную LLM обрабатывать каждый клик пользователя в реальном времени, серверная инфраструктура рухнет из-за огромных задержек ответа (latency).</p><p>Ключевые паттерны интеграции (на примере e-commerce):</p><ul><li>Обогащение данных и генерация качественного контента в офлайне. Базовый холодный старт на основе текстовых описаний или картинок успешно решался и до эпохи LLM. Сила LLM в другом — она толерантна к качеству входных данных и умеет доставать сложные скрытые интенты. Если у нового товара скудное, хаотичное описание от поставщика и одна размытая фотография, старые модели выдадут бесполезный вектор. LLM же способна достроить контекст: исправить текст, вытащить неявные характеристики и, главное, сгенерировать портрет целевой аудитории. Полученный чистый, обогащенный текстовый профиль затем передается стандартным контентным моделям. Система понимает реальную ценность новинки до первого клика, даже если исходная карточка товара была заполнена ужасно.</li></ul><ul><li>Семантическое индексирование. Вместо случайных числовых ID языковая модель присваивает товарам смысловые хэши. Все палатки для кемпинга одной категории будут иметь схожие префиксы кода, что помогает графовым сетям улавливать близость объектов без опоры на историю чужих покупок.</li></ul><ul><li>Контрастивное обучение. Модели анализируют паттерны поведения на разных слоях: от многолетних привычек до короткой текущей сессии. Затем алгоритмы квантования сжимают эти знания в компактные векторы профилей, радикально снижая объем данных, поступающих в продакшен.</li></ul><ul><li>Дистилляция знаний. Тяжелая модель (учитель) размечает тысячи сложных сценариев выбора в офлайне, логически аргументируя связи. На этих идеальных данных тренируют легковесную нейросеть (ученика). В онлайне работает только быстрый ученик, отдавая ответы за миллисекунды, но сохраняя смысловую точность большой системы.</li></ul><ul><li>Zero-shot ранжирование. На самом последнем этапе шорт-лист из 20 релевантных кандидатов передается в промпт для LLM, которая пересортирует их с учетом последних действий пользователя. Это дает высочайшую точность смыслов, но применяется точечно из-за высоких задержек.</li></ul><h2>Защита от галлюцинаций: мощь паттернов RAG</h2><p>При внедрении разговорных рекомендаций — формате, где пользователь не просто получает список вариантов, а взаимодействует с системой в диалоге — вылезает главная уязвимость генеративных моделей. Они могут выдумать идеальный по характеристикам, но не существующий в базе товар. Вывод таких "галлюцинаций" в интерфейс снижает лояльность аудитории и ведет к ее оттоку.</p><p>Для жесткого контроля трансформеров инженеры применяют пайплайны Retrieval-Augmented Generation (RAG). Механизм работает в три этапа:</p><ol><li>Семантический поиск. База данных (векторное хранилище) отбирает топ реальных продуктов из каталога на основе текущего запроса клиента.</li><li>Формирование контекста. Система автоматически собирает системный промпт, оборачивая в него строгие факты (точные артикулы, цены, характеристики) о найденных товарах.</li><li>Аналитическая генерация. LLM выдает финальный результат или текстовую консультацию строго в рамках переданного узкого списка товаров, теряя возможность выдумать что-то новое.</li></ol><p>Дальнейшее развитие безопасности — Graph RAG, где агент сверяет персональную историю с глобальным математическим графом знаний. Это дает нейросети четкую картину связей каталога, исключая любые слепые догадки.</p><h2>Шаг к агентным системам будущего</h2><p>Мы наблюдаем важнейший эволюционный переход: статические алгоритмы уступают место агентным рекомендательным системам (Agentic Workflows). Классическая модель просто получает данные и отдает результат. Агент же способен вести диалог, логически рассуждать и вызывать сторонние инструменты по API.</p><p>Рассмотрим пример с выбором экипировки. Если пользователь вводит нестандартный запрос, например, «палатка для выезда с детьми в Карелию на выходные», то обычная матричная система просто выдаст витрину популярных моделей из категории «Туризм», проигнорировав нюансы.</p><p>LLM-агент работает иначе: он превращает строку поиска во вдумчивого аналитика. Используя метод пошагового рассуждения (Chain-of-Thought), нейросеть перед выдачей результата формирует скрытый внутренний логический монолог:</p><ul><li>Анализ аудитории. В запросе указаны дети. Значит, в приоритете повышенная защита от насекомых, плотное дно и хорошая вентиляция.</li></ul><ul><li>Анализ формата. Задача — поход на выходные. Это классический кемпинг, куда, скорее всего, поедут на машине. Следовательно, вес палатки не критичен и можно пожертвовать легкостью ради большого тамбура и высокого потолка.</li></ul><ul><li>Анализ локации. В Карелии высокая влажность и вероятность дождей. Требуется двухслойная конструкция с высоким показателем водонепроницаемости тента (от 4000 мм в.ст.).</li></ul><ul><li>Формирование фильтров. Ищем: кемпинговая палатка, 3-4 места, двухслойная, водостойкая, с москитными сетками.</li></ul><p>Только после завершения этой скрытой цепочки умозаключений система обращается к базе данных каталога и выводит на экран идеально подходящие товары. Более того, агент может сразу сгенерировать короткое объяснение для пользователя: «Эта модель весит чуть больше аналогов, зато у нее есть большой тамбур, можно переждать карельский дождь».</p><p>Исследователи уже тестируют многоагентные среды, где агент пользователя (хранящий вкусы клиента) и агент контента (знающий характеристики товаров) общаются в фоне, торгуясь за место конкретного продукта в ленте. Пока это требует огромных вычислительных бюджетов и тестируется в закрытых лабораториях, но тренд очевиден.</p><h3>Персонализация и миф одного запроса</h3><p>Раньше продуктовые команды и разработчики ожидали, что LLM станет универсальным решением для персонализации. На практике языковые модели блестяще перекрывают слепые зоны на старте сессии, с ходу понимая интент пользователя и удерживая его в приложении. Но когда история действий накапливается, лидерство в точности снова возвращается к классическим алгоритмам.</p><p>Способность к обобщению творит чудеса, и модель делает разумную догадку по паре слов. Однако глубокая персонализация требует времени и накопления истории реакций. В первые часы нейросеть работает как спасательный круг, не давая платформе выглядеть глупой. Она генерирует релевантную витрину, резко повышая удержание новичков. Но когда история кликов набирает вес, лидерство в точности снова перехватывают легкие классические модели. Языковые движки просто блестяще закрывают слепую зону на старте.</p><h3>Новые метрики: почему точности мало</h3><p>Традиционно качество измеряли метриками конверсии (CTR, Conversion Rate) и угадывания конкретного клика (Hit Rate). Но семантический подход требует перехода к концепции Beyond Accuracy. Оптимизация только под вероятность клика приводит к информационному пузырю и система может назойливо предлагать детективы целый месяц после одной покупки.</p><p>Новые классы метрик эффективно лечат эту болезнь:</p><ul><li>Контролируемая серендипность. Оценивает внезапные приятные сюрпризы. Если любителю детективов предложить аудиокнигу про историю джаза (похожую по нуарной атмосфере), он будет искренне доволен. Классика не смогла бы проложить такой маршрут.</li><li>Внутрисписочное сходство (разнообразие). Оценивает способность собрать подборку из фильмов абсолютно разных жанров, каждый из которых при этом точно попадает во вкус зрителя.</li><li>Объяснимость рекомендаций. Способность нейросети генерировать короткие тексты-подсказки (например, «Я советую вам этот курс, так как вы недавно искали статьи по Python»). Это повышает прозрачность и снижает барьер недоверия.</li><li>Калибровка. Жесткая проверка честности системы. Выдача обязана соответствовать реальным долговременным интересам пользователя, не скатываясь в дешевый кликбейт.</li><li>Покрытие каталога. Показывает глубину поиска. Семантический векторный движок обязан эффективно поднимать хорошие товары из самого длинного «хвоста» базы.</li></ul><h2>Инженерные барьеры и безопасность данных</h2><p>Внедрение умных технологий всегда несет риски. Команды разработки регулярно решают сложнейшие инфраструктурные ребусы:</p><ol><li>Время задержки сервера (Latency). Пользователь ждет результат миллисекунды, а гигантские трансформеры думают секундами. Инженерам приходится агрессивно кешировать результаты, батчить запросы и выносить максимум расчетов в офлайн-процессы.</li><li>Приватность и дообучение. Логи пользователей нельзя отправлять во внешнее облако. Приходится разворачивать локальные открытые модели внутри закрытого контура компании. Для экономии ресурсов видеокарт применяют методы адаптеров (PEFT): базовые веса замораживаются, и тренируются только крошечные слои, что позволяет быстро адаптировать нейросеть под специфику магазина.</li><li>Проблема выравнивания (Alignment). Базово LLM учится просто предсказывать следующее слово. Но продуктовой команде нужно растить бизнес-метрики (например, время удержания в приложении). С помощью обучения с подкреплением (RLHF) поведение модели подстраивают под реальные бизнес-цели компании.</li></ol><h2>Если на практике: мультимодальная языковая модель</h2><p>Пример такого технического внедрения — мультимодальная языковая модель (MMLM) команды AI VK. Она сравнивает контент по смыслу и тематике, объясняет комментарии, описывает интересы пользователя к конкретным сценам и учитывает эмоциональный тон материалов. Нейросеть обучена более чем на трех миллионах русскоязычных материалов и может анализировать видео, изображения, тексты и аудио. С ней рекомендательные алгоритмы быстрее показывают новый контент в продуктах VK без необходимости получения первых пользовательских реакций.</p><h3>Чек-лист: когда стоит внедрять технологию</h3><p>Решение о трансформации должно иметь четкий финансовый расчет. Оцените ваш продукт перед внедрением LLM.</p><p>Дайте зеленый свет экспериментам, если:</p><ul><li>Ваш продукт содержит огромное количество сложного текста или медиа (маркетплейсы, образовательные площадки).</li><li>У вас постоянный огромный поток новых товаров (семантика блестяще решит проблему холодного старта).</li><li>Продукт находится в нише сложного выбора (покупка электроники, бронирование туров).</li><li>Есть острая потребность объяснять логику рекомендаций пользователю живым языком.</li></ul><p>Включите красный свет, если:</p><ul><li>Сценарии потребления просты и рутинны (заказ бумажных полотенец, покупка кабеля по известному артикулу).</li><li>Намерение пользователя прозрачно и не требует глубокого анализа.</li><li>У вас жесткие аппаратные ограничения на обработку онлайн-запросов (вы просто сожжете бюджет на аренду GPU без выгоды для бизнеса).</li></ul>]]></content:encoded>
    </item>
    <item>
      <title>В *Instagram появилась настройка алгоритма рекомендаций. Как и где ее найти</title>
      <link>https://tproger.ru/news/v--instagram-poyavilas-nastrojka-algoritma-rekomendacij--kak-i-gde-ee-najti</link>
      <comments>https://tproger.ru/news/v--instagram-poyavilas-nastrojka-algoritma-rekomendacij--kak-i-gde-ee-najti?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Булат Яббаров]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/news/v--instagram-poyavilas-nastrojka-algoritma-rekomendacij--kak-i-gde-ee-najti</guid>
      <description><![CDATA[<p>В Instagram появилась настройка алгоритма рекомендаций: пользователи могут выбрать темы для Reels и управлять тем, что видят</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/news/v--instagram-poyavilas-nastrojka-algoritma-rekomendacij--kak-i-gde-ee-najti">В *Instagram появилась настройка алгоритма рекомендаций. Как и где ее найти</a>»</p>]]></description>
      <category><![CDATA[Искусственный интеллект]]></category>
      <category><![CDATA[Социальные сети]]></category>
      <category><![CDATA[Рекомендательные системы]]></category>
      <category><![CDATA[Новости]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Wed, 14 Jan 2026 08:10:03 GMT</pubDate>
      <content:encoded><![CDATA[<p>*Meta начала постепенно открывать «черный ящик» алгоритмов в *Instagram.</p><p>В соцсети появилась новая функция <b>Your Algorithm</b>, которая позволяет напрямую указать, какой контент вы хотите видеть чаще, а какой — реже.</p><p>Полного ручного управления лентой пока нет. Но это все еще самый заметный шаг *Instagram в сторону пользовательского контроля за рекомендациями.</p><p>Функцию тестировали несколько месяцев. О ее появлении еще осенью прошлого года говорил глава *Instagram Адам Моссери. Теперь настройка начала распространяться на пользователей в разных странах.</p><h2>С чего все начинается: Reels</h2><p>На первом этапе Your Algorithm работает только с <b>Reels</b>. Именно короткие видео стали основной точкой входа для алгоритмических рекомендаций, поэтому *Instagram и начал с них.</p><p>Чтобы открыть настройки, нужно:</p><ul><li>открыть любое видео в Reels;</li><li>нажать на новую кнопку с иконкой линий и сердечек;</li><li>перейти в раздел Your Algorithm.</li></ul><figure><img src="https://media.tproger.ru/user-uploads/111041/2026-01-14/ec19e959-9ce0-4721-8df6-34053862fd32.jpeg" alt="" /></figure><p>Внутри интерфейс максимально простой. *Instagram показывает темы, которые вы сейчас активно смотрите и предлагает выбрать, что вы хотите видеть больше и меньше. Темы подбираются автоматически и кратко описываются ИИ.</p><h2>Можно добавить свои темы</h2><p>Если предложенных вариантов недостаточно, темы можно ввести вручную через кнопку <b>Add</b>. Это полезно, если вы хотите сместить ленту в сторону конкретных интересов. Например, меньше лайфстайла и больше профессионального контента.</p><p>Выбранные темы отображаются прямо в интерфейсе Reels — внизу экрана, над именем пользователя. Это скорее индикатор для вас, чем кнопка управления, но он показывает, что настройки действительно применяются.</p><h2>Что будет дальше</h2><p>*Meta заявляет, что выбранные темы со временем начнут влиять не только на Reels, но и на основную ленту и вкладку <b>Explore</b>. Сейчас эффект ограничен, но логика алгоритма постепенно станет единой для всего *Instagram.</p><p>Функция пока доступна лишь на английском языке, но географически распространяется широко — почти во всех регионах, где работает *Instagram.</p><p><i>*Компания Meta и ее продукты признаны экстремистскими, их деятельность запрещена на территории РФ</i></p>]]></content:encoded>
    </item>
    <item>
      <title>Создание простой поисковой системы, которая действительно работает</title>
      <link>https://tproger.ru/articles/sozdanie-prostoj-poiskovoj-sistemy--kotoraya-dejstvitelno-rabotaet</link>
      <comments>https://tproger.ru/articles/sozdanie-prostoj-poiskovoj-sistemy--kotoraya-dejstvitelno-rabotaet?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Иван]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/sozdanie-prostoj-poiskovoj-sistemy--kotoraya-dejstvitelno-rabotaet</guid>
      <description><![CDATA[<p>Создайте свою собственную поисковую систему на PHP без внешних сервисов. Используйте токенизацию, веса и реляционные базы данных для точного и быстрого поиска по тексту. Полное руководство по реализации, индексированию и поиску.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/sozdanie-prostoj-poiskovoj-sistemy--kotoraya-dejstvitelno-rabotaet">Создание простой поисковой системы, которая действительно работает</a>»</p>]]></description>
      <category><![CDATA[Инструменты]]></category>
      <category><![CDATA[SQL]]></category>
      <category><![CDATA[Базы данных]]></category>
      <category><![CDATA[Рекомендательные системы]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Fri, 21 Nov 2025 09:12:42 GMT</pubDate>
      <content:encoded><![CDATA[<h2>Зачем строить свой собственный?</h2><p>Зачем вообще делать что-то своё?</p><p>Я знаю, что вы можете подумать: «Почему бы просто не использовать Elasticsearch?» или «А что насчёт Algolia?» Это вполне рабочие решения, но у них есть нюансы. Нужно разбираться с их API, поддерживать инфраструктуру под них и учитывать все тонкости их работы.</p><p>Но иногда хочется чего-то более простого — такого, что:</p><ul><li>работает прямо с вашей текущей базой данных;</li><li>не требует сторонних сервисов;</li><li>легко понять и отладить;</li><li>действительно выдаёт релевантные результаты.</li></ul><p>Поэтому я и сделал свою систему поиска — такую, которая использует вашу существующую БД, вписывается в архитектуру проекта и даёт полный контроль над тем, как она работает.</p><h2>Основная идея</h2><p>Концепция проста: разбить текст на токены, сохранить их, а затем при поиске сопоставлять токены запроса с токенами в индексе.</p><p>Процесс выглядит так:</p><ul><li>Индексация. Когда вы добавляете или обновляете данные, система разбивает текст на токены (слова, префиксы, n-граммы) и сохраняет их вместе с весами.</li><li>Поиск. Когда пользователь вводит запрос, он проходит такую же токенизацию. Затем система ищет совпадающие токены и подбирает подходящие документы.</li><li>Оценка. Сохранённые веса используются для расчёта итоговой релевантности.</li></ul><p>Вся суть — в том, как выполняется токенизация и как рассчитываются веса. Сейчас я покажу, что именно имеется в виду.</p><h2>Строительный блок 1: схема базы данных</h2><p>Для начала нам нужны всего две таблицы: index_tokens и index_entries.</p><h2>index_tokens</h2><p>В этой таблице хранятся все уникальные токены вместе с их весами, полученными от разных токенизаторов.</p><p>Важно: один и тот же токен может встречаться несколько раз с разными весами — по одному для каждого токенизатора.</p><figure><img src="https://media.tproger.ru/user-uploads/134517/2025-11-19/9429ca06-ac31-48ea-857e-70fab73c92e8.png" alt="" /></figure><h2>Почему так?</h2><p>Потому что разные токенизаторы создают один и тот же токен, но с разным весом.</p><p>Например, токен parser:</p><ul><li>WordTokenizer → вес 20</li><li>PrefixTokenizer → вес 5</li></ul><p>Чтобы итоговый механизм оценки релевантности работал правильно, нужны отдельные записи.</p><p>Ограничение уникальности в этой таблице — (name, weight).</p><p>То есть имя токена может повторяться, но вес — нет.</p><h2>index_entries</h2><p>Эта таблица связывает:</p><ul><li>токен</li><li>документ</li><li>конкретное поле документа</li></ul><p>…и хранит итоговый вес, который нужен для процедуры ранжирования.</p><h2>Структура таблицы index_entries</h2><figure><img src="https://media.tproger.ru/user-uploads/134517/2025-11-19/3cd82554-37a8-4530-90a6-173ef6613753.png" alt="" /></figure><h2>Что такое weight?</h2><p>Это итоговый вычисленный вес токена для конкретного поля конкретного документа.</p><p>Формула:</p><p>Он уже включает всё, что понадобится позже при начислении очков.</p><h2>Какие индексы добавляем?</h2><p>Чтобы поиск работал быстро:</p><ul><li>(document_type, document_id) — для быстрого получения документов</li><li>token_id — чтобы быстро находить все документы по токену</li><li>(document_type, field_id) — для поиска по конкретному полю</li><li>weight — для фильтрации по весам</li></ul><h2>Почему именно такая схема?</h2><p>Потому что она:</p><ul><li>простая</li><li>эффективно ложится на реляционные БД</li><li>использует сильные стороны SQL</li><li>позволяет масштабировать алгоритм без усложнений</li></ul><h2>Блок 2: токенизация</h2><h2>Что такое токенизация?</h2><p>Это процесс разбивки текста на более мелкие части — токены, удобные для поиска.</p><p>Например, слово «parser» можно разбить разными способами:</p><ul><li>Как одно целое: ["parser"]</li><li>На префиксы: ["par", "pars", "parse", "parser"]</li><li>На n-граммы (последовательности символов): ["par", "ars", "rse", "ser"]</li></ul><h2>Зачем несколько токенизаторов?</h2><p>Разные задачи требуют разных подходов к поиску:</p><ul><li>Один токенизатор для точных совпадений</li><li>Другой — для частичных совпадений</li><li>Третий — для учёта опечаток</li></ul><p>Каждый из них играет свою роль в итоговом ранжировании.</p><h2>Общий интерфейс токенизатора</h2><p>Все токенизаторы реализуют простой интерфейс:</p><p>Простой и расширяемый контракт.</p><h2>Токенизатор слов (WordTokenizer)</h2><p>Разбивает текст на отдельные слова. Слово «parser» превращается в</p><p>Этот метод отлично подходит для точных совпадений.</p><p>Вес: 20 — высокий, для точных совпадений.</p><h2>Префиксный токенизатор (PrefixTokenizer)</h2><p>Создаёт префиксы слов, например:</p><p>→</p><p>(минимальная длина префикса — 4).</p><p>Это полезно для поиска по частям слова и автодополнения.</p><p>Вес: 5 — средний, для частичных совпадений.</p><p>Зачем минимальная длина?</p><p>Чтобы избежать слишком большого количества коротких токенов — префиксы короче 4 символов обычно слишком распространены и малоэффективны.</p><h2>Токенизатор n-грамм (NGramsTokenizer)</h2><p>Создаёт последовательности символов фиксированной длины (обычно 3).</p><p>Например,</p><p>→</p><p>.</p><p>Это помогает улавливать опечатки и частичные совпадения.</p><p>Вес: 1 — низкий, но улавливает редкие случаи и опечатки.</p><p>Почему длина 3?</p><p>Это компромисс между слишком большим количеством совпадений и пропущенными вариантами из-за опечаток.</p><h2>Блок 3: Система весов</h2><p>В нашей системе есть три уровня весов, которые работают вместе, чтобы определить важность каждого токена при поиске:</p><ol><li>Вес поля — например, заголовок, основное содержание или ключевые слова. Разные части документа могут иметь разный приоритет.</li><li>Вес токенизатора — каждый тип токенизатора (слово, префикс, n-грамма) имеет свой вес. Эти веса хранятся в таблице index_tokens.</li><li>Вес документа — итоговый вес для конкретного токена в конкретном документе. Хранится в index_entries и рассчитывается по формуле:</li></ol><h2>Как рассчитывается итоговый вес?</h2><p>Во время индексации для каждого токена мы считаем вес так:</p><p>Например:</p><ul><li>Вес поля заголовка: 10</li><li>Вес токенизатора слов: 20</li><li>Длина токена «parser»: 6</li></ul><p>Тогда итоговый вес:</p><h2>Почему используется ceil(sqrt())?</h2><ul><li>Более длинные токены обычно более специфичны и важны — например, «parser» конкретнее, чем «par».</li><li>Но мы не хотим, чтобы очень длинные токены имели слишком большой вес — 100-символьный токен не должен давать вес в 100 раз больше, чем короткий.</li><li>Функция квадратного корня даёт убывающую доходность — вес растёт с длиной, но не линейно.</li><li>ceil() округляет результат вверх, чтобы сохранить веса целыми числами.</li></ul><h2>Настройка весов под свои задачи</h2><p>Вы можете гибко настраивать веса под свои нужды:</p><ul><li>Увеличить вес поля — например, если заголовки для вас важнее всего.</li><li>Изменить вес токенизатора — повысить для точных совпадений (слов), понизить для менее важных (n-граммы).</li><li>Изменить формулу для длины токена — вместо ceil(sqrt()) можно использовать логарифм или линейную функцию, чтобы по-другому влиять на вес длинных токенов.</li></ul><p>Таким образом, вы можете точно контролировать, какие части текста и какие типы совпадений важнее при поиске, и подстроить систему под свои требования.</p><h2>Блок 4: Служба индексирования</h2><p>Служба индексирования отвечает за обработку документов и сохранение всех их токенов в базе данных для последующего быстрого поиска.</p><h2>Интерфейс для документов</h2><p>Чтобы документ мог индексироваться, он должен реализовать интерфейс</p><p>с тремя методами:</p><ul><li>getDocumentId() — возвращает уникальный идентификатор документа.</li><li>getDocumentType() — возвращает тип документа (например, статья, пост, комментарий).</li><li>getIndexableFields() — возвращает поля документа, которые нужно индексировать, вместе с их весами.</li></ul><p>Пример реализации для статьи:</p><h2>Когда индексируем?</h2><ul><li>При создании или обновлении документа (например, через события).</li><li>По командам в консоли — например, app:index-document или app:reindex-documents.</li><li>Через задачи cron для массовой переиндексации.</li></ul><h2>Как работает индексирование — шаг за шагом</h2><ol><li>Получаем данные документа: его тип, ID и поля с весами.</li><li>Удаляем старый индекс для этого документа. Это важно, чтобы избежать дублирования данных.</li><li>Для каждого поля запускаем все токенизаторы, которые разбивают текст на токены.</li><li>Для каждого токена:Находим или создаём его в таблице токенов (чтобы не хранить одинаковые токены несколько раз).Рассчитываем итоговый вес по формуле:вес_поля × вес_токенизатора × ceil(квадратный_корень_из_длины_токена) Добавляем информацию в пакет для массовой вставки.Вставляем все новые записи в базу данных одним запросом — так быстрее и эффективнее.</li><li>Находим или создаём его в таблице токенов (чтобы не хранить одинаковые токены несколько раз).</li><li>Рассчитываем итоговый вес по формуле:вес_поля × вес_токенизатора × ceil(квадратный_корень_из_длины_токена) Добавляем информацию в пакет для массовой вставки.Вставляем все новые записи в базу данных одним запросом — так быстрее и эффективнее.</li></ol><h2>Зачем искать или создавать токены?</h2><p>Токены — это общие элементы для всех документов. Если токен уже есть, используем его повторно, чтобы не хранить дубли и сэкономить место и время.</p><ol><li>Ключевые моментыСтарый индекс удаляется перед созданием нового — это упрощает обновление.Используется пакетная вставка для производительности.Токены ищутся или создаются, чтобы избежать дубликатов.Итоговый вес считается динамически при индексации.</li><li>Ключевые моментыСтарый индекс удаляется перед созданием нового — это упрощает обновление.Используется пакетная вставка для производительности.Токены ищутся или создаются, чтобы избежать дубликатов.Итоговый вес считается динамически при индексации.</li><li>Старый индекс удаляется перед созданием нового — это упрощает обновление.</li><li>Используется пакетная вставка для производительности.</li><li>Токены ищутся или создаются, чтобы избежать дубликатов.</li><li>Итоговый вес считается динамически при индексации.</li></ol><h2>Блок 5: Служба поиска</h2><p>Поисковый сервис принимает строку запроса, разбивает её на токены, ищет эти токены в индексах и возвращает список документов, отсортированных по релевантности.</p><h2>Как это работает — шаг за шагом</h2><ol><li>Токенизация запроса</li></ol><p>Запрос разбивается на токены с помощью того же набора токенизаторов, который использовался при индексации документов. Это важно, чтобы поиск и индексирование были синхронизированы.</p><p>Пример:</p><ul><li>Индексация создала токены: par, pars, parse, parser (префиксный токенизатор).</li><li>Поиск тоже использует префиксный и обычный токенизатор — так мы найдём не только точное слово parser, но и все его варианты.</li></ul><p>Если запрос пустой (нет токенов), возвращаем пустой результат.</p><ol><li>Уникальные токены</li></ol><p>Из всех токенов берём только уникальные значения, чтобы не искать одинаковые токены по несколько раз.</p><ol><li>Сортировка токенов</li></ol><p>Токены сортируются по длине — сначала самые длинные. Это важно, потому что более длинные токены — более конкретные и дают более точные совпадения.</p><ol><li>Ограничение количества токенов</li></ol><p>Если пользователь отправит очень длинный запрос, мы ограничиваем число токенов (например, максимум 300), чтобы избежать нагрузок на систему.</p><ol><li>Выполнение поискового SQL-запроса</li></ol><p>Далее строится и выполняется оптимизированный SQL-запрос, который:</p><ul><li>Ищет документы, где встречаются эти токены.</li><li>Считает оценку релевантности для каждого документа.</li><li>Сортирует результаты по убыванию оценки.</li><li>Возвращает ограниченное число результатов (например, топ-10).</li></ul><h2>Как считается оценка релевантности?</h2><p>Оценка складывается из нескольких факторов:</p><ul><li>Базовый балл — сумма весов всех найденных токенов в документе.</li><li>Разнообразие токенов — документы с большим количеством разных токенов получают бонус (логарифмическая шкала, чтобы не давать слишком большой перевес).</li><li>Качество совпадений — чем выше средний вес токенов, тем лучше (например, совпадение в заголовке важнее, чем в теле текста).</li><li>Штраф за длину документа — чтобы длинные документы не имели слишком большое преимущество.</li></ul><p>В итоге оценка нормализуется на максимальное значение, чтобы можно было сравнивать разные поисковые запросы.</p><h2>Почему нужен подзапрос с весом токенов?</h2><p>В подзапросе проверяется, что документ содержит хотя бы один токен с весом выше порогового. Это исключает из результатов документы, которые совпадают только по «шумным» токенам с очень маленьким весом (например, незначительным n-граммам), что улучшает качество поиска.</p><h2>Пример возвращаемого результата</h2><p>Поиск возвращает список таких объектов — ID документа и его релевантность.</p><h2>Как получить сами документы?</h2><p>Мы берём ID из результатов поиска, и через репозиторий загружаем реальные объекты документов, сохраняя порядок релевантности.</p><p>Репозиторий гарантирует, что документы вернутся в том же порядке, что и результаты поиска (используется SQL-функция</p><h2>Итог</h2><p>В результате вы получаете мощную и гибкую поисковую систему, которая:</p><ul><li>Быстро находит релевантные документы через индексы в базе данных.</li><li>Обрабатывает опечатки и частичные совпадения с помощью n-грамм и префиксных токенизаторов.</li><li>Придаёт больше веса точным совпадениям (например, полным словам).</li><li>Работает без внешних сервисов — только с базой данных.</li><li>Легко отлаживается и настраивается за счёт прозрачного SQL и гибких весов.</li></ul><h2>Расширение системы</h2><h2>Добавление нового токенизатора</h2><p>Чтобы добавить новый способ разбиения текста на токены (например, стемминг, лемматизацию, синонимы и т.д.), нужно:</p><ul><li>Реализовать интерфейс TokenizerInterface, например:</li></ul><p>Зарегистрировать этот токенизатор в конфигурации сервиса — и он автоматически будет использоваться и для индексации, и для поиска.</p><h2>Добавление нового типа документа</h2><p>Чтобы индексировать новый тип документов (например, комментарии, статьи, профили), реализуйте интерфейс:</p><h2>Изменение весов и формул</h2><ul><li>Вес токенизаторов и полей легко настраивается через конфигурацию.</li><li>Формулы подсчёта релевантности находятся в SQL-запросе — вы можете его изменить, чтобы подстроить оценивание под свои задачи.</li></ul><h2>Заключение</h2><ul><li>Это простая и понятная поисковая система — нет сложных «черных ящиков» и магии.</li><li>Она легко контролируется, настраивается и отлаживается.</li><li>Подходит для большинства приложений, где не нужна гигантская инфраструктура типа Elasticsearch.</li><li>Главное — вы полностью управляете системой, понимаете каждый её шаг и можете улучшать её под свои нужды.</li></ul><p>Берите и делайте под себя — это ваш поиск, и он должен работать так, как вам нужно.</p>]]></content:encoded>
    </item>
    <item>
      <title>Как нейросети меняют систему рекомендаций</title>
      <link>https://tproger.ru/articles/kak-nejroseti-menyayut-sistemu-rekomendacij</link>
      <comments>https://tproger.ru/articles/kak-nejroseti-menyayut-sistemu-rekomendacij?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Татьяна Жукова]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/kak-nejroseti-menyayut-sistemu-rekomendacij</guid>
      <description><![CDATA[<p>Нейросети кардинально меняют рекомендательные системы — теперь они анализируют не отдельные действия, а целостный портрет человека. Разбираем революцию персонализации с экспертом AI VK.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/kak-nejroseti-menyayut-sistemu-rekomendacij">Как нейросети меняют систему рекомендаций</a>»</p>]]></description>
      <category><![CDATA[Работа]]></category>
      <category><![CDATA[Боты]]></category>
      <category><![CDATA[YouTube]]></category>
      <category><![CDATA[5g]]></category>
      <category><![CDATA[TikTok]]></category>
      <category><![CDATA[Vue]]></category>
      <category><![CDATA[Смартфоны]]></category>
      <category><![CDATA[Рекомендательные системы]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Thu, 14 Aug 2025 14:00:03 GMT</pubDate>
      <content:encoded><![CDATA[<p>Рекомендательные системы в цифровых платформах долгое время развивались обособленно, решая узкие задачи без общего представления о пользователе. Одна модель анализировала контент, другая — поведение, третья — занималась ранжированием. Такой подход не позволял системе до конца понять, что именно интересно человеку. Сегодня всё меняется: нейросети объединяют эти элементы в единую архитектуру, формируя целостную модель интересов. Вместе с руководителем рекомендаций в AI VK Андреем Зимовновым разбираемся, как новые подходы вытесняют старые и делают рекомендации по-настоящему персонализированными.</p><h2>Почему старые модели больше не работают</h2><p>Долгие годы рекомендательные системы состояли из десятков моделей, которые решали свои узкие задачи. На финальном этапе часто использовался градиентный бустинг — метод, при котором несколько слабых моделей, например, поведенческая (лайки и просмотры) и контентная (теги и описания), объединяются в одну, более точную и устойчивую. Такой подход плохо понимал контекст и динамику интересов пользователя. Например, если человек внезапно переключался с футбольных обзоров на кулинарные видео, система не могла быстро подстроиться. Сегодня это решается переходом к нейросетевым архитектурам, которые видят картину целиком.</p><h2>Как данные превращаются в рекомендации</h2><p>Современные системы кодируют и контент, и действия пользователей в эмбеддинги — векторы чисел, отражающие интересы и характеристики.</p><ul><li>Пользовательские эмбеддинги строятся по лайкам, просмотрам, времени активности, подпискам.</li><li>Контент кодируется по заголовкам, описаниям, тегам, обложкам, звуку и даже тону комментариев.</li></ul><p><b>Главная задача эмбеддингов — отобрать подходящий контент из миллионов вариантов.</b></p><ol><li>Всё начинается с отбора кандидатов. При помощи поиска ближайших соседей ANN (approximate nearest neighbor search), реализованного через FAISS или аналоги, за миллисекунды находятся тысячи кандидатов, которые хотя бы примерно соответствуют интересам пользователя.</li><li>После этого идёт этап предранжирования. Из тысячи кандидатов нужно выбрать пару сотен наиболее перспективных. Здесь уже работают алгоритмы градиентного бустинга, например, CatBoost или другие, выбор зависит от инфраструктуры. Они учитывают дополнительные признаки: насколько свежа публикация, насколько популярен автор, как часто пользователь взаимодействовал с похожим контентом.</li><li>Затем наступает финальное ранжирование. Применяются глубокие нейросети, включая  нейросетевые версии коллаборативной фильтрации, которые учитывают интересы похожих пользователей. Они прогнозируют, что пользователь будет делать дальше: досмотрит ли видео, поставит ли лайк или репостнёт. Здесь каждому кандидату уделяется особое внимание, ведь нужно выдать самые релевантные.</li></ol><p>Всё это работает на единой DataPlatform, которая собирает сигналы от пользователей и обучает модели. В VK для этого есть единая Discovery-платформа, которая собирает клики, лайки, поисковые запросы и обновляет эмбеддинги.</p><figure><img src="https://media.tproger.ru/user-uploads/102593/2025-08-13/b8cb46e1-666e-48a6-9f8a-49f0c9760b85.jpg" alt="" /></figure><h2>Нейросетевой зоопарк: что стоит под капотом</h2><p>В финальном ранжировании работает целая экосистема нейросетей. Это и многослойные перцептроны (MLP), и более сложные — сверточные (CNN), рекуррентные (RNN) и трансформеры.</p><h3>1. Трансформеры и большие языковые модели (LLM)</h3><p>Трансформеры — это тип нейросети, который умеет обрабатывать данные как последовательности. Возьмём предложение из трёх слов: «я ем Кафку». Трансформер не просто распознаёт значения отдельных слов — «я», «ем», «Кафку» — но и улавливает общий смысл фразы.</p><p>С помощью механизма self-attention он находит связи между элементами и понимает контекст. Это позволяет строить контекстные эмбеддинги — векторные представления, которые учитывают не только содержание, но и значение слов в конкретной ситуации. Так модель понимает, что в фразе «я ем Кафку» речь идёт о еде, а не о литературе.</p><p>В рекомендациях трансформеры анализируют действия пользователя как последовательность. Например, модель SASRec (Self-Attentive Sequential Recommendation), которая используется в VK, предсказывает, что может заинтересовать человека дальше, и уже даёт прирост точности на 2,5–3%.</p><p>Сильная сторона трансформеров — в умении распознавать связи между действиями пользователя, а не просто фиксировать каждое событие. Если человек будет стабильно взаимодействовать с определённым контентом, модель «поймёт», что это не случайность, и придаст этому интересу больший вес. При этом случайные действия, вроде одного нерелевантного клика, не исказят общую картину — механизм self-attention помогает отличать устойчивые паттерны от шумовых всплесков.</p><p>Трансформеры активно применяются в ранжировании, но изначально разрабатывались как универсальные архитектуры для работы с последовательностями.  А вот LLM, например, T5 или GPT, обучены на текстах. Они более гибкие: их можно настраивать также через текст и встраивать в диалог. Но они пока медленнее, требуют больше ресурсов и уступают в производительности на больших потоках.</p><h3>2. Мультимодальные модели</h3><p>Прорывной подход в рекомендательных системах. Они обрабатывают сразу несколько форматов: текст, изображения, звук. Всё это кодируется в векторы и сводится в общее пространство — часто тоже с помощью трансформеров. Так система понимает не только ключевые слова, но и смысл контента в разных форматах. По такому принципу работает Zelda — семейство моделей и фреймворк, лежащий в основе рекомендаций VK.</p><p>Раньше всё сводилось к матрице «пользователь × объект», где система пыталась предсказать оценки. Это работало, пока человек смотрел однотипный контент. Если пользователь смотрит обзоры гаджетов, то старая модель начинает искать похожие видео — с теми же тегами. Но если видео не помечено как «техника», система может его пропустить. Когда интересы меняются, алгоритм не понимает, почему пользователь внезапно увлёкся музыкой или историей.</p><p>Мультимодальные модели считывают сам контент: текст, видео, изображение — и ищут то, что объединяет их по смыслу. Это позволяет точнее угадывать неожиданные интересы, подстраиваться под смену вкусов и работать с новым, нестандартным контентом, который раньше выпадал из поля зрения.</p><h3>3. Диффузионные модели</h3><p>Диффузионные модели восстанавливают «чистые» предпочтения пользователя, убирая шум вроде случайных кликов и скипов. Например, вы смотрите обзоры смартфонов и случайно кликаете на видео про косметику с маркетплейса. Вы быстро переключили обратно на видео про смартфоны, и нейросеть понимает, что произошло, и не рекомендует видео про косметику.</p><p>Диффузионные модели особенно полезны при работе с разреженными и шумными данными — например, для новых пользователей. Такие модели, как DiffRec, показывают до 10% прироста точности на сложных датасетах и постепенно начинают конкурировать с трансформерами.</p><figure><img src="https://media.tproger.ru/user-uploads/102593/2025-08-13/e8814674-8971-4448-abae-af159dd57e78.jpg" alt="" /></figure><h2>Система рекомендаций продолжит меняться</h2><p>Следующим этапом в развитии нейросетевых методов может стать переход к сквозным (end-to-end) архитектурам, когда одна большая нейросеть берёт на себя все функции сразу. Некоторые платформы, например, TikTok и YouTube, уже частично внедряют end-to-end пайплайны. Это снижает ошибки на промежуточных этапах и учитывает цели платформы — вовлечение и удержание.</p>]]></content:encoded>
    </item>
    <item>
      <title>Векторные базы данных: простым языком про устройство и принцип работы</title>
      <link>https://tproger.ru/articles/vektornye-bazy-dannyh--prostym-yazykom-pro-ustrojstvo-i-princip-raboty</link>
      <comments>https://tproger.ru/articles/vektornye-bazy-dannyh--prostym-yazykom-pro-ustrojstvo-i-princip-raboty?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Ekaterina Davidova]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/vektornye-bazy-dannyh--prostym-yazykom-pro-ustrojstvo-i-princip-raboty</guid>
      <description><![CDATA[<p>Пройдём путь от простого вектора до целой рекомендательной системы, пробежимся по основным фишкам и внутреннему устройству. Поймём, а где вообще использовать этот инструмент и посмотрим на векторные базы данных в деле.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/vektornye-bazy-dannyh--prostym-yazykom-pro-ustrojstvo-i-princip-raboty">Векторные базы данных: простым языком про устройство и принцип работы</a>»</p>]]></description>
      <category><![CDATA[Базы данных]]></category>
      <category><![CDATA[Машинное обучение]]></category>
      <category><![CDATA[Рекомендательные системы]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Fri, 13 Dec 2024 14:00:03 GMT</pubDate>
      <content:encoded><![CDATA[<p>Только изучили один инструмент, как сразу же появились новые? Придется разбираться! В статье мы рассмотрим новый тип баз данных, который отлично подходит для ML задач. Пройдём путь от простого вектора до целой рекомендательной системы, пробежимся по основным фишкам и внутреннему устройству. Поймём, а где вообще использовать этот инструмент и посмотрим на векторные базы данных в деле.</p><p>Меня зовут Мозганов Николай и я бэкенд-разработчик в Точке. До недавнего времени я разрабатывал социальную сеть для предпринимателей, которая помогает находить полезные бизнес знакомства. Давайте возьмем этот сервис в качестве примера, чтобы плавно погрузиться в проблему, решаемую векторными базами данных.</p><h2>Кратко про ML и векторизацию</h2><p>Итак, мы разрабатываем сервис, в котором пользователи заполняют свои интересы, указывают экспертизу и пожелания по встрече, а мы должны подобрать интересного собеседника. На вход мы получаем тексты с информацией о пользователях, а на выходе должны выдать пары рекомендаций. По сути мы делаем умную рекомендательную систему и наша задача сводится к нахождению максимально похожих экспертиз одних клиентов и запросов других клиентов.</p><p>Например, Вася хочет пообщаться с опытными предпринимателями, а дизайнер Петя планирует выходить на маркетплейсы и ищет человека с такой экспертизой. Подходят ли они друг другу? Эта задача не так проста, как может показаться на первый взгляд. Давайте вместе попробуем ее решить.</p><p><b>Решение в лоб</b></p><p>Очевидной идеей кажется простое разбиение пользовательских текстов на слова (токены). В качестве рекомендаций будем выдавать тех людей, у которых совпало наибольшее количество слов: общие слова будут звучать в тексте, а значит людям интересны одни и те же темы. Чем больше совпадений, тем лучше! Можно наливать кофе)</p><p>Но такая рекомендательная система получится не очень умной, поскольку она не учитывает общий контекст запроса, синонимы и какие-то опечатки.</p><figure><img src="https://media.tproger.ru/user-uploads/108715/2024-12-12/ff931f47-9857-4840-8fd0-766807ed0601.png" alt="" /></figure><p>Задачу решать все-таки надо, придется обратиться за помощью к ML’щикам. Они предлагают хранить не обычные тексты, а числовые представления или по простому вектора, чтобы их понимали программы. Оказывается, практически любые объекты можно превращать в вектор: слова, предложения, картинки или даже звуки. Такой процесс называется векторизацией.</p><p>Превратить объект в вектор — это задача машинного обучения. Есть разные подходы и уже обученные модели, которые на вход получают объекты, а на выходе дают вектор. Например, Bag of Words, TF-IDF, Word2Vec и другие. Для простоты понимания можно воспринимать этот процесс как некоторую математическую магию.</p><figure><img src="https://media.tproger.ru/user-uploads/108715/2024-12-12/fe3df1a5-48cc-4741-a88a-70ed2f861d60.png" alt="" /></figure><p>МЛщики, конечно, могут много всего интересного придумать, но бэкендерам надо разбираться, как это все хранить в памяти, поэтому вспомнить, что такое вектор все-таки придется. Нам же нужно с ними работать!</p><p><b>Назад в школу</b></p><p>Вектор — это элемент векторного пространства со своими свойствами и операциями.</p><figure><img src="https://media.tproger.ru/user-uploads/108715/2024-12-12/55c6addb-e9a6-4a0e-bad7-10d776a6ec1a.png" alt="" /></figure><p>У каждого вектора есть координаты и бла бла бла. Не очень понятно, как это использовать на практике.</p><p>На самом деле вектор — это просто массив чисел, а массивы мы уже умеем обрабатывать и хранить в памяти. Самое главное свойство для нашей задачи заключается в том, что между 2-мя векторами можно искать расстояние. Интуитивно это означает, что примерно похожие друг на друга вектора, находятся на близком расстоянии. По сути математические метрики и формулы описывают наше интуитивное представление.</p><p>Примеры метрик:</p><p>1) <b>Евклидово расстояние (L2-норма)</b>. Расстояние в обычном его понимании.</p><p>Формула:</p><figure><img src="https://media.tproger.ru/user-uploads/108715/2024-12-12/8d8b3af9-f28d-41a3-95ad-2090f24c40d6.png" alt="" /></figure><p>Пример: есть два вектора</p><figure><img src="https://media.tproger.ru/user-uploads/108715/2024-12-12/7bc3cd75-e48a-4903-a3b9-c462fcbd668f.png" alt="" /></figure><p>Евклидово расстояние между ними:</p><figure><img src="https://media.tproger.ru/user-uploads/108715/2024-12-12/2b0eefd9-0c1a-4642-8fb0-7bd4280fcb10.png" alt="" /></figure><p>2) <b>Манхэттенское расстояние (L1-норма)</b></p><p>Формула:</p><figure><img src="https://media.tproger.ru/user-uploads/108715/2024-12-12/40fa85a6-37ad-4708-a083-fa75de08d3b4.png" alt="" /></figure><p>Пример: для тех же векторов манхэттенское расстояние</p><figure><img src="https://media.tproger.ru/user-uploads/108715/2024-12-12/993fbc4f-83b0-43fc-a11c-d5eea8bc6a4c.png" alt="" /></figure><p>3) <b>Косинусное сходство.</b> Технически это не истинная метрика расстояния, а мера сходства.</p><p>Формула для косинусного сходства:</p><figure><img src="https://media.tproger.ru/user-uploads/108715/2024-12-12/93513140-23d0-4ccd-babb-b861907a4ea4.png" alt="" /></figure><p>Здесь</p><figure><img src="https://media.tproger.ru/user-uploads/108715/2024-12-12/fe32b738-54aa-4f30-829d-4a7112643363.png" alt="" /></figure><p>Для нахождения расстояния используем:</p><figure><img src="https://media.tproger.ru/user-uploads/108715/2024-12-12/2c4a9ec5-c9c7-4327-a99c-7878a195a47b.png" alt="" /></figure><p>Пример:</p><figure><img src="https://media.tproger.ru/user-uploads/108715/2024-12-12/f205b9ad-8998-4b84-80fd-e31c110dbb58.png" alt="" /></figure><p>Косинусное расстояние будет:</p><figure><img src="https://media.tproger.ru/user-uploads/108715/2024-12-12/f98d5744-e86c-4de8-8252-c7aeaebc5151.png" alt="" /></figure><p>Такое маленькое расстояние указывает на то, что векторы весьма похожи.</p><p><b>Продвинутое решение</b></p><p>На такой математической идее и работает наш сервис: Мы превращаем описание пользователей в различные вектора, между которыми можно искать расстояние, а по полученным расстояниям делаем сортировку и выдаем рекомендации.</p><p>У этого решения есть принципиальные проблемы:</p><ul><li>Во-первых, оно долго работает.</li><li>Во-вторых, мы выгружаем всю таблицу с векторами в память нашего приложения, чтобы вычислить расстояния и отсортировать их.</li></ul><p>Эти проблемы хочется как-то решить и тут на помощь приходят они…</p><h2>Векторные базы данных</h2><p>Оказывается, есть векторные базы данных (ВБД). Это <b>NoSQL</b> решения, которые предназначены для хранения, индексирования и <b>поиска похожих векторов</b>.</p><p>Следовательно, с их помощью можно строить:</p><ul><li>Различные рекомендательные системы. Например, рекомендовать похожие товары в интернет магазине на основе свойств исходных товаров.</li><li>Поисковые системы — искать наиболее похожие разделы по смысловой нагрузке текста.</li><li>Делать различный анализ изображений и видео. Например, искать похожие картинки или находить оригинал изображения.</li></ul><p><b>Устройство</b></p><p>По существу, от базы данных требуется две операции: сохранять данные и читать информацию, записанную ранее. Давайте рассмотрим как работают эти процессы в векторных базах:</p><p><b>Запись</b></p><ol><li>На вход backend-приложения поступает какой-то объект (пусть это будет текст, как в нашем сервисе)</li><li>Этот объект нужно превратить в вектор при помощи обученного векторизатора.</li><li>Полученный вектор и метаданные исходного объекта можно сохранить на диск.</li></ol><figure><img src="https://media.tproger.ru/user-uploads/108715/2024-12-12/24da2247-7852-4ffc-b07e-e8c8f909f365.png" alt="" /></figure><p><b>Чтение</b></p><ol><li>К нам приходит приложение с новым объектом и запросом сделать для него рекомендацию.</li><li>Нужно проделать весь процесс обработки: векторизовать объект запроса той же моделью, получить вектор той же размерности.</li><li>Уже по сгенерированному вектору можно найти другой, наиболее близкий вектор. На этом этапе можно сделать предварительную фильтрацию по метаданным (Например, искать соседей только с длинной текста больше n).</li></ol><p>Поиск наиболее подходящих соседей может работать долго, ведь нужно просмотреть все записи на диске. Решением этой проблемы, как и в большинстве баз данных, является индексация. Мы чуть замедлим запись, но чтение будет работать сильно быстрее. Для этого могут использоваться разные алгоритмы индексации, подробнее к которым вернемся дальше.</p><figure><img src="https://media.tproger.ru/user-uploads/108715/2024-12-12/06559b32-e8b1-47cb-a1a0-a4d3d3509a45.png" alt="" /></figure><p>Функционал одних баз данных заканчиваются только хранением, индексацией и чтением, а другие могут включать в себя готовый набор векторизаторов, чтобы не нужно было писать и обучать свои. Набор возможностей из коробки зависит от конкретной базы данных.</p><figure><img src="https://media.tproger.ru/user-uploads/108715/2024-12-12/ad4ad2b5-e756-497e-b589-1d34049b0f1c.png" alt="" /></figure><p><b>Индексирование</b></p><p>Индексирование уже упоминалось, но не пояснялось, как именно оно работает. ВБД используют комбинацию различных алгоритмов и структур данных, которые участвуют в поиске приближенного ближайшего соседа. Запрос схожих векторов предоставляет приблизительные результаты, поэтому мы можем балансировать между точностью и скоростью: чем точнее хотим получить результат, тем медленнее будет работать запрос и наоборот.</p><p>Ускорить поиск можно несколькими способами: либо уменьшить размерность векторов, либо сузить область поиска. Рассмотрим парочку алгоритмов индексирования, попытаемся понять в чем заключается идея и почему поиск становится быстрее.</p><p><b>Уменьшение размерности, при помощи случайной проекции</b></p><p>По длинным векторам искать долго, давайте их «укоротим». Нужно уменьшить размерность векторов, сохранив свойство схожести. Это можно сделать согласно лемме Джонсона-Линденштрауса, которая утверждает, что небольшой набор точек в пространстве большой размерности может быть вложен в пространство гораздо меньшей размерности таким образом, что расстояния между точками почти сохраняются.</p><p>Для реализации придется сгенерировать матрицу случайной проекции, на которую будем скалярно умножать входные вектора. На выходе получаем вектора меньшей размерности, которые сохраняют свойство подобия. Мы жертвуем некоторым количеством информации, поэтому точность уменьшается, но скорость увеличивается, т.к. размер векторов становиться сильно меньше.</p><figure><img src="https://media.tproger.ru/user-uploads/108715/2024-12-12/cf1d0931-74b6-4d2e-9919-2aaf8dac5996.png" alt="" /><figcaption>Источник: https://www.pinecone.io/learn/vector-database/</figcaption></figure><p>Размер матрицы можно задавать таким, чтобы конечный результат нас устраивал, т.е. конечный размер векторов был оптимальным для поиска).</p><p>В момент запроса похожести для нового вектора, мы должны использовать ту же матрицу, чтобы спроецировать вектор запроса в пространство более низкой размерности. И уже в этом пространстве делать поиск ближайших соседей.</p><p><b>Хэширование с учетом местоположения</b></p><p>Locality-sensitive hashing (LSH) — это метод индексации, который чем-то похож на устройство обычной хэш мапы. Идея заключается в следующем: отобразим вектора в бакеты похожести, используя набор функций хеширования. Проще всего рассмотреть на примере:</p><figure><img src="https://media.tproger.ru/user-uploads/108715/2024-12-12/846893c7-6646-48da-939e-513b91ed2b67.png" alt="" /></figure><p>Зеленый вектор отображается в зеленый сегмент 1-го бакета, а синий вектор — в синий сегмент 2-го бакета.</p><p>Хэш функция определяет, в какой из бакетов попадёт вектор. По своей сути она позволяет нам группировать похожие вектора в одни и те же бакеты.</p><p>Соответственно, чтобы найти ближайших соседей для вектора запроса, нужно определить его бакет при помощи функции хэширования. Выполнить поиск можно среди данного бакета, не рассматривая другие, предварительно неблизкие, вектора. Этот метод намного быстрее, чем поиск по всему набору данных, потому что в каждом бакете гораздо меньше векторов, чем во всем пространстве.</p><p>Так же стоит упомянуть, что качество данного метода зависит от свойств выбранной функции хэширования точно так же, как и в устройстве обычной хэш мапы.</p><p><b>Иерархический навигационный маленький мир</b></p><p>Hierarchical Navigable Small World (HNSW) — на первый взгляд сложный и непонятный алгоритм, который требует построения графа поиска, однако он очень важен и полезен, поскольку используется практически во всех современных ВБД, обеспечивая хорошую точность и скорость.</p><p>На самом деле идея довольно просто объясняется при помощи LEGO человечков.</p><figure><img src="https://media.tproger.ru/user-uploads/108715/2024-12-12/76f51c72-ade5-4bf0-a49d-ce71a47e29c5.png" alt="" /></figure><p>Представим, что наши вектора обозначают персонажей из фильма «Звездные войны».</p><ol><li>Сгруппируем вектора в узлы (случайно или с помощью алгоритмов кластеризации). Объединим Йоду, Люка, и принцессу Лею в узел светлой стороны (зеленый узел). Героев темной стороны объединим в красный узел, а роботов и клонов — в 3й узел будущего графа. Получилось 3 узла: зеленый, красный и оранжевый.</li><li>Проанализируем вектор каждого узла и нарисуем серое ребро между двумя узлами, если они содержат в себе похожие вектора (т.е. расстояние между векторами меньше некоторой заданной константы). Например, Люк Скайуокер очень похож на своего отца Энакина Скайуокера, поэтому эти узлы мы можем связать ребром. Точно так же с роботом R2D2. Его хозяином был Энакин, поэтому они чем-то похожи. Соответственно, эти узлы так же свяжем ребром. <b>Таким образом, мы построим граф поиска, в котором каждый узел имеет связь с другими наиболее похожими узлами.</b></li><li>Когда к нам приходит запрос, мы можем использовать этот граф для навигации, посещая только те узлы, которые содержат вектора, наиболее близкие к вектору запроса. Например, мы хотим выдать рекомендацию для Люка Скайвокера, но Йоду и Принцессу Лею мы ему уже рекомендовали, поэтому они нам не подходят. Мы пройдемся по ребру и найдем новую рекомендацию — его отца, Энакина Скайвокера.</li></ol><p>Мы рассмотрели ключевые идеи индексации в векторных базах данных, но далеко не все. На практике устройство намного сложнее, ведь нужно учитывать множество краевых случаев. Однако, цель этой статьи — ознакомить с ключевыми идеями, чтобы появилось примерное понимание работы.</p><h2>Пробуем на практике</h2><p>Вернемся к нашей задаче по рекомендации собеседников. Выберем конкретную базу данных и сравним ее с нашим решением, которое основано на подсчете расстояния между векторами.</p><p>Для проведения экспериментов, я руководствовался следующими критериями: хотелось взять OpenSource базу данных, которую можно было бы легко развернуть у себя, а наличие встроенных векторизаторов было весомым плюсом, поскольку я занимаюсь бэкендом и не претендую на экспертность в машинном обучении. На практике это означает, что не придется заморачиваться с преобразованием текстов в вектора и совмещением интерфейсов нашего решения и ВБД.</p><figure><img src="https://media.tproger.ru/user-uploads/108715/2024-12-12/1edf1c49-c1f9-4d3a-9b8b-115a969034b5.png" alt="" /></figure><p>В таблице представлены самые популярные векторные базы данных (или расширения существующих БД, см. pgvector). Ранжирование по производительности и потреблению памяти представлено по местам. Это сделано так, потому что на разных датасетах базы данных ведут себя по-разному: где-то выигрывает одна, где-то другая, поэтому приводить конкретные цифры было бы не совсем честно. Если усреднять, то можно упорядочить их по местам, как представлено в табличке. С подробными результатами бенчмарков можно ознакомиться на <a href="https://ann-benchmarks.com/">https://ann-benchmarks.com/</a>.</p><p>Именно для бенчмарка быстрее и проще всего было взять БД с готовым векторизатором, чтобы не писать кучу кода для совместимости. После сортировки по популярности и производительности мой выбор пал на векторную базу данных Weaviate, вдобавок к которой идет неплохая документация.</p><p><b>Бенчмарки</b></p><p>Настало время провести замеры. Оба решения были запущены локально в docker контейнерах, а замеры производились с помощью <a href="https://docs.docker.com/reference/cli/docker/container/stats/">docker container stats</a>.</p><p>Рассмотрим график используемой памяти от количества векторов.</p><p>По горизонтальной оси отложены тысячи векторов (т.е. шкала от 100 векторов до полумиллиона), а по вертикальной оси — используемая память в МБ.</p><figure><img src="https://media.tproger.ru/user-uploads/108715/2024-12-12/6b277aff-17e7-4766-8e71-2456e6b75465.png" alt="" /></figure><p>Как мы видим наше решение занимает больше памяти во всех тестах, хотя разница незначительна. Ради такого результата не стоило бы и переезжать.</p><p>Память — это хорошо, но больше интересует скорость работы. Попробуем выдать 1 рекомендацию для нашего пользователя и посмотрим на затраченное время:</p><figure><img src="https://media.tproger.ru/user-uploads/108715/2024-12-12/bdace4c5-f33d-41f8-98bc-1a04f90b7a93.png" alt="" /></figure><p>Тут картина уже сильно меняется. Откровенно говоря, наше решение работает непростительно долго на больших объемах: Для выдачи всего 1 рекомендации тратится 77 секунд. И как видно из графика при росте объемов эта цифра будет только расти, а вот векторная база данных работает практически за константное время, с учетом погрешности. Чтобы лучше заметить разницу, посмотрим на эти же данные на логарифмической шкале:</p><figure><img src="https://media.tproger.ru/user-uploads/108715/2024-12-12/f4864a9d-f81e-45ec-86a6-d92660e6afe8.png" alt="" /></figure><p>Таким образом, использование векторной базы данных в нашем случае сильно ускорит выдачу одной рекомендации для пользователя. Т.е. рекомендации можно будет делать даже в режиме реального времени! Вдобавок, сэкономим пару мегабайт памяти.</p><p>У использования готовых инструментов есть еще одно большое преимущество: алгоритмы и структуры данных уже написаны за нас, поэтому нам не нужно реализовывать их повторно, исправлять баги и поддерживать собственное решение.</p><p>Всего-то достаточно развернуть векторную базу данных и сделать пару служебных запросов. Благодаря этому количество кода нашего приложения сильно снижается, освобождается время на кофе).</p><h2>Итоги</h2><p>Векторные базы данных предназначены для оптимальной работы с векторами. Они по-умному хранят и индексируют эту структуру данных, соответственно делают быстрый поиск по ней. Самая главная фишка — нахождение похожих векторов.</p><p>А еще некоторые базы данных поставляют готовый модуль векторизации, поэтому не нужно глубоко погружаться в машинное обучение, чтобы использовать этот инструмент в своих небольших проектах.</p><p>Важно понимать, что это не серебряная пуля. У каждого решения есть свои плюсы и минусы, точно так же и с векторными базами данных.</p><ol><li>Это NoSQL решение, поэтому нет строгой транзакционности (не выполняются требования ACID). С другой стороны, такой вид БД хорошо горизонтально масштабируется, но сделать это правильно не так просто, из чего вытекают следующие пункты:</li><li>Нужно разбираться с индексированием, шардированием (партиционированием) и другими неочевидными вещами.</li><li>Нужно поддерживать всю необходимую инфраструктуру, следить за ее работоспособностью.</li><li>Изучать новый инструмент и погружать в него всю команду. Это может быть весомым минусом, особенно если сроки ограничены.</li><li>Не все работает из коробки: Например, для нашей задачи ВБД не умеют каждый раз выдавать новые рекомендации, хотя это и можно реализовать при помощи аналога курсоров. В общем, все равно придется делать доработки.</li></ol><p>В заключение, хотелось бы сказать, что векторные базы данных — интересный инструмент для своих проектов, который однозначно стоит попробовать. Его использование позволяет сильно сократить время на разработку, ведь не нужно заниматься написанием собственного решения, его поддержкой и исправлением ошибок. ВБД ускоряют время поиска и чуть более оптимально используют память. С другой стороны, это не волшебное решение всех проблем: нужно поддерживать необходимую инфраструктуру, обновлять и мониторить ее, поэтому выбор всегда остается за вами. Выбирайте с умом!</p>]]></content:encoded>
    </item>
    <item>
      <title>Рекомендательные системы и реализация Content-based системы</title>
      <link>https://tproger.ru/articles/rekomendatelnye-sistemy-i-realizaciya-content-based-sistemy</link>
      <comments>https://tproger.ru/articles/rekomendatelnye-sistemy-i-realizaciya-content-based-sistemy?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Алина Т]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/rekomendatelnye-sistemy-i-realizaciya-content-based-sistemy</guid>
      <description><![CDATA[<p>Введение в рекомендательные системы: идеи, типы, метрики, преимущества и недостатки. Реализация content based системы для аниме</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/rekomendatelnye-sistemy-i-realizaciya-content-based-sistemy">Рекомендательные системы и реализация Content-based системы</a>»</p>]]></description>
      <category><![CDATA[Анализ данных]]></category>
      <category><![CDATA[Рекомендательные системы]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Mon, 23 Sep 2024 14:30:03 GMT</pubDate>
      <content:encoded><![CDATA[<p>Небольшое введение в рекомендательные системы: основные идеи, типы, метрики и как они работают.</p><p>Данную статью я условно разделю на 3 части: общая теория по рекомендательным системам, работа с данными, для которых будем строить систему и реализация системы.</p><h2>Теория (самый страшный зверь)</h2><p><b>Рекомендательная система</b> — это система, которая пытается предсказать или отфильтровать предпочтения в соответствии с выбором пользователя. Рекомендательные системы используются в различных областях, включая фильмы, музыку, новости, книги, исследовательские статьи, поисковые запросы, социальные теги и продукты в целом.</p><h3>Метрика</h3><p>Чаще всего для оценки расстояния используют косинусное сходство (Cosine Similarity).</p><p>Представление данных в форме вектора имеет ещё одно полезное свойство. Мы можем измерить близость двух векторов или угол между ними. Чем угол меньше, тем они ближе.</p><figure><img src="https://media.tproger.ru/user-uploads/106087/2024-09-20/988719a6-3e3f-4e91-a5ee-21543c1e8113.png" alt="" /><figcaption>Косинусное расстояние</figcaption></figure><h4>TF-IDF</h4><p>– применяется для анализа значимости слова в документе, который является частью большой коллекции документов либо корпуса. С помощью этой статической меры можем составить вектор, с которыми работают рекомендательные системы.</p><p>TF — это частота слова в тексте – количество раз, когда слово появляется в документе, деленное на общее количество слов в документе (каждый документ имеет свою частоту терминов). Обратная частота данных IDF — это логарифм обратной частоты распространенности слова в корпусе. Распространенностью называется отношение числа текстов, в которых встретилось искомое слово, к общему числу текстов в корпусе.</p><p>Обратная частота данных определяет вес редких слов во всех документах корпуса.</p><figure><img src="https://media.tproger.ru/user-uploads/106087/2024-09-20/f9c5ac07-bef8-4610-b039-30b9628e3243.png" alt="" /><figcaption>Визуализация работы TF-IDF</figcaption></figure><p>Scikit-Learn предоставляет преобразователь под названием TfidfVectorizer в модуле feature_extraction.text для векторизации с оценками TF-IDF.</p><h3>Проблемы</h3><ul><li>Холодный запуск</li></ul><p>Эта проблема возникает, когда в систему добавляются новые пользователи или новые элементы, новый элемент не может быть рекомендован пользователям изначально, когда он вводится в систему рекомендаций без какой-либо оценки или обзоров, и, следовательно, трудно предсказать выбор или интерес пользователя.</p><ul><li>Разреженность</li></ul><p>Это происходит много раз, когда большинство пользователей не дают оценок или отзывов о товарах, которые они приобрели, и, следовательно, модель оценки становится очень разреженной, что может привести к проблемам разреженности данных, это уменьшает возможности найти набор пользователей с похожими оценками или интерес.</p><ul><li>Конфиденциальность</li></ul><p>Как правило, человеку необходимо передать свою личную информацию в систему рекомендаций для получения более полезных услуг, но это вызывает проблемы с конфиденциальностью и безопасностью данных, многие пользователи не решаются передавать свои личные данные в системы рекомендаций. которые страдают от проблем с конфиденциальностью данных.</p><figure><img src="https://media.tproger.ru/user-uploads/106087/2024-09-20/285ccfed-6750-432c-a50e-049b235cd8db.png" alt="" /><figcaption>Проблемы рекомендательных систем</figcaption></figure><h2>Типы рекомендательных систем</h2><figure><img src="https://media.tproger.ru/user-uploads/106087/2024-09-20/6369bbb2-e2c3-40c3-aeb0-23a6ee9e9f3b.png" alt="" /><figcaption>Типы рекомендательных систем</figcaption></figure><h3>Popularity-based</h3><p>Наиболее простая система выдает рекомендации на основе популярности (popularity-based recommender systems). Чем выше средний рейтинг фильма, купленного товара или статьи, тем вероятнее, что система будет рекомендовать именно их.</p><figure><img src="https://media.tproger.ru/user-uploads/106087/2024-09-20/26dda6af-41ad-48e9-b476-a479ee73d288.png" alt="" /><figcaption>Сводка по popularity-based системам</figcaption></figure><h3>Сontent-based filtering</h3><p>Вторым типом рекомендательных систем является, так называемая, фильтрация на основе содержания (content-based filtering). В данном случае алгоритм рекомендует товары или услуги, схожие с теми, которые пользователь приобретал ранее. Например, если вы посмотрели фильм «Матрица» с Киану Ривзом, то в дальнейшем система будет рекомендовать вам научную фантастику, а также другие фильмы с участием этого актера.</p><figure><img src="https://media.tproger.ru/user-uploads/106087/2024-09-20/b7e0f036-2076-430d-8c31-894e1325f6e6.png" alt="" /><figcaption>Сводка по content-based системам</figcaption></figure><h3>Collaborative filtering</h3><p>Третий тип — коллаборативная система (collaborative filtering). Она основывается на сопоставлении пользователей и товаров (или услуг, новостей и т.д.). Математически и графически в данном случае мы работаем с матрицами предпочтений (user-item matrix).</p><figure><img src="https://media.tproger.ru/user-uploads/106087/2024-09-20/cd0d48e9-660c-4226-98b3-b9576c749915.png" alt="" /><figcaption>Сводка по collaborative системам</figcaption></figure><p>Основная предпосылка таких систем заключается в том, что предыдущих данных пользователей должно быть достаточно для создания прогноза. То есть нам не нужно ничего, кроме исторических данных, пользовательского ввода, текущих трендовых данных и так далее. Он считается одной из очень умных рекомендательных систем, которые работают на сходстве между разными пользователями, а также на товары, которые широко используются в качестве веб-сайтов электронной коммерции, а также веб-сайтов онлайн-фильмов. Он проверяет вкус похожих пользователей и дает рекомендации.</p><p>Сходство не ограничивается вкусом пользователя, более того, может учитываться сходство между различными предметами. Система будет давать более эффективные рекомендации, если у нас будет большой объем информации о пользователях и товарах.</p><figure><img src="https://media.tproger.ru/user-uploads/106087/2024-09-20/8eeff0c6-e41d-4ea6-b1bc-d24dec21501f.png" alt="" /><figcaption>Отличие collaborative  фильтрации от content-based</figcaption></figure><p>Что такое User-item matrix?</p><p>Матрица полезности показывает предпочтения пользователя в отношении определенных элементов. В данных, полученных от пользователя, мы должны найти некоторую связь между элементами, которые нравятся пользователю, и теми, которые ему не нравятся, для этого мы используем матрицу полезности. В нем мы присваиваем определенное значение каждой паре пользователь-элемент, это значение известно как степень предпочтения. Затем мы рисуем матрицу пользователя с соответствующими элементами, чтобы определить его отношения предпочтений.</p><figure><img src="https://media.tproger.ru/user-uploads/106087/2024-09-20/00f96901-5282-43c0-8afd-7d1ff4930727.png" alt="" /><figcaption>Алгоритм работы матрицы предпочтений</figcaption></figure><p>В совместной фильтрации используются два подхода:</p><h4>а)  Совместная фильтрация ближайших соседей на основе пользователей (user-based)</h4><p>Коллаборативные системы, основанные на пользователях (user-based), находят близких по предпочтениям пользователей и рекомендуют одному из них то, что уже попробовал другой.</p><p>User Profile:</p><p>В профиле пользователя мы создаем векторы, описывающие предпочтения пользователя. При создании профиля пользователя мы используем матрицу полезности, которая описывает отношения между пользователем и элементом. С помощью этой информации лучшая оценка, которую мы можем сделать относительно того, какой элемент нравится пользователю, — это некоторая агрегация профилей этих элементов.</p><figure><img src="https://media.tproger.ru/user-uploads/106087/2024-09-20/23506a47-4642-4cb8-b667-4c453d33bd0a.png" alt="" /><figcaption>Сводка по совместной фильтрации на основе пользователя</figcaption></figure><h4>b)  Совместная фильтрация ближайших соседей на основе элементов (item-based)</h4><p>Системы, основанные на предмете рекомендации (item-based), сравнивают непосредственно близость товаров или услуг. Причем что отличает эту систему, сходство определяется на основе предпочтений всех пользователей, которые оставили свои оценки.</p><p>Item Profile:</p><p>В Content-Based Recommender мы должны создать профиль для каждого элемента, который будет представлять важные характеристики этого элемента.</p><p>Например, если мы делаем фильм как объект, то его актеры, режиссер, год выпуска и жанр являются наиболее значимыми характеристиками фильма. Мы также можем добавить его рейтинг из IMDB (база данных фильмов в Интернете) в профиле товара.</p><figure><img src="https://media.tproger.ru/user-uploads/106087/2024-09-20/4dc7f1a9-ae3e-4f0d-94a7-ed57f7b2e272.png" alt="" /><figcaption>Сводка по совместной фильтрации на основе элементов</figcaption></figure><p>На этом мы закончим с ознакомлением с системами и перейдем к самому интересному — коду.</p><h2>Немного о данных</h2><p>Датасет я создала свой собственный, содержащий в себе данные об аниме (японской анимации) с сайта MyAnimeList(MAL). Очевидно, ниже приведенный код может быть использован для других наборов данных.</p><figure><img src="https://media.tproger.ru/user-uploads/106087/2024-09-20/c3b6ab0a-4eb7-49de-97c8-b55d59437e52.png" alt="" /><figcaption>Структура датасета</figcaption></figure><p>Проведем небольшой анализ данных, чтобы иметь общее представление с чем же все таки работаем.</p><p>Посмотрим, какие жанры и теги чаще всего встречаются.</p><figure><img src="https://media.tproger.ru/user-uploads/106087/2024-09-20/8c8dd06b-2373-47e7-ba31-43105dcb1286.png" alt="" /><figcaption>Наиболее часто встречаемые теги и жанры в датасете</figcaption></figure><p>Самые популярные жанры – школа, научная фантастика, экшен, комедия и романтика. Самый популярный тег – суперсилы.</p><figure><img src="https://media.tproger.ru/user-uploads/106087/2024-09-20/57b9ab27-381d-4a26-90c8-f1e2b1989246.png" alt="" /><figcaption>Распределение рейтинга по демографическим группам</figcaption></figure><p>Чаще всего высокие оценки у сененов (аниме, рассчитанные на юношей до 18-ти лет), но в целом результаты почти одинаковые.</p><figure><img src="https://media.tproger.ru/user-uploads/106087/2024-09-20/79932762-0e3a-4856-802e-b40c308886cd.png" alt="" /><figcaption>Распределение рейтинга по возрастным ограничениям</figcaption></figure><p>Высокие оценки имеют аниме с рейтингами R-17 и PG-13, то есть большинство аниме рассчитано на подростков от 13 до 17 лет.</p><figure><img src="https://media.tproger.ru/user-uploads/106087/2024-09-20/fa5d509e-147f-46b0-ac50-62b900c0cd6a.png" alt="" /><figcaption>Распределение аниме по возрастному ограничению и демографии</figcaption></figure><p>Аниме для детей имеют возрастной рейтинг для всех или для детей (до 13). Сёдзе (произведение для девушек до 18 лет) чаще всего имеет рейтинг для детей. Чем выше возрастное ограничение, тем увеличивается процент содержания сененов и сейненов (произведение для юношей до 18 и старше соответственно)</p><p>Выделим релевантные параметры для рекомендаций.</p><figure><img src="https://media.tproger.ru/user-uploads/106087/2024-09-20/c5573ece-579b-4cbb-a350-b5f0313cab9a.png" alt="" /><figcaption>Параметры для каждого элемента</figcaption></figure><h2>Рекомендательная система (Content Based)</h2><p>Для меры сходства (Cosine similarity) выберем linear kernel (ядра являются мерами сходства, т.е. s(a, b) &gt; s(a, c), если объекты a и b считаются “более похожими”, чем объекты a и c), так как это быстрее.</p><p>Теперь у нас есть матрица парного косинусного сходства (cosine similarity) для всех фильмов в нашем наборе данных. Следующим шагом будет написание функции, которая возвращает 30 наиболее похожих фильмов на основе оценки косинусного сходства.</p><p>Наконец, проверим, как работает наша модель</p><p>Теперь сравним полученный список рекомендаций с рекомендациями на популярных сайтах (на примере аниме “Vinland Saga”)</p><figure><img src="https://media.tproger.ru/user-uploads/106087/2024-09-20/9f5554a1-f506-40d0-a76a-a40a9d9e0fe5.png" alt="" /><figcaption>Рекомендации к аниме Vinland Saga</figcaption></figure><p>Самый популярный сайт на западе (MAL): Shingeki no Kyojin, Dororo, Kenpuu Denki Berserk, 91 Days, Golden Kamuy, Kingdom, Arslan Senki, Shingeki no Kyojin: The Final Season, Mushoku Tensei, Youjo Senki… – совпадает более чем на 70% с полученными результатами. Некоторые произведения не вошли, так как у них не были заполнены некоторые параметры или они вышли раньше 2000-х. Сайт, где рекомендации основываются полностью на отзывах пользователей (AnimePlanet): Shingeki no Kyojin, Berserk, Dororo, One Piece, Arslan Senki, Shoukoku no Altair, Akatsuki no Yona, Shingeki no Kyojin 3, Jormungand, Kingdom, Shigurui, Golden Kamuy 2, 91 Days, Kiseijuu… – похожие результаты как и выше. Можно сделать вывод, что система рекомендаций довольно хорошо работает – она показывает результаты, наиболее похожие на введенное аниме.</p><p>Одна из особенностей построенной системы рекомендаций заключается в том, что она рекомендует фильмы независимо от рейтингов и популярности.</p><p>Поэтому добавим механизм, где также учитывается рейтинг рекомендуемых произведений. То есть будем советовать не только наиболее похожие по тегам и жанрам, но и по популярности.</p><figure><img src="https://media.tproger.ru/user-uploads/106087/2024-09-20/2c2874d8-2a82-463e-85a7-3928ed65c4e8.png" alt="" /><figcaption>Усовершенствованная система рекомендаций</figcaption></figure><p>По сути объединили две системы, основанные на контенте: одна принимала на вход демографический параметр и возрастный рейтинг, а другая – метаданные, такие как студия, жанр и темы для составления прогнозов. А также разработали простой фильтр, чтобы отдать предпочтение фильмам с высоким рейтингом.</p><h2>Источники</h2><p>Посмотреть полную реализацию кода:</p>]]></content:encoded>
    </item>
  </channel>
</rss>