惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Stack Overflow Blog
Stack Overflow Blog
WordPress大学
WordPress大学
罗磊的独立博客
S
Secure Thoughts
Schneier on Security
Schneier on Security
博客园 - Franky
www.infosecurity-magazine.com
www.infosecurity-magazine.com
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
爱范儿
爱范儿
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Hacker News: Ask HN
Hacker News: Ask HN
PCI Perspectives
PCI Perspectives
Google DeepMind News
Google DeepMind News
S
Security Affairs
SecWiki News
SecWiki News
博客园 - 聂微东
Security Archives - TechRepublic
Security Archives - TechRepublic
Google Online Security Blog
Google Online Security Blog
H
Heimdal Security Blog
S
Security @ Cisco Blogs
Engineering at Meta
Engineering at Meta
C
CXSECURITY Database RSS Feed - CXSecurity.com
Cloudbric
Cloudbric
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
V
Visual Studio Blog
P
Proofpoint News Feed
Project Zero
Project Zero
T
Threat Research - Cisco Blogs
Webroot Blog
Webroot Blog
Blog — PlanetScale
Blog — PlanetScale
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
W
WeLiveSecurity
Last Week in AI
Last Week in AI
月光博客
月光博客
Microsoft Azure Blog
Microsoft Azure Blog
M
MIT News - Artificial intelligence
有赞技术团队
有赞技术团队
S
Securelist
GbyAI
GbyAI
Application and Cybersecurity Blog
Application and Cybersecurity Blog
C
CERT Recently Published Vulnerability Notes
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Cyberwarzone
Cyberwarzone
B
Blog RSS Feed
P
Palo Alto Networks Blog
H
Hacker News: Front Page
D
Docker
雷峰网
雷峰网
Latest news
Latest news
Microsoft Security Blog
Microsoft Security Blog

Все публикации подряд на Хабре

Ловим музу за клавиатуру: как айтишнику стать автором Что умеет Midjourney в 2026? Мой немного грустный разбор этого шикарного инструмента Никто не любит писать тесты, но ИИ может исправить это IPv8 выглядит как мечта. Поэтому почти наверняка не взлетит Производители вернули в продажу материнки с DDR3. Что происходит? Управление агентом с телефона через Telegram теперь в KodaCode От координации к лидерству: как меняется роль руководителя разработки Я сделала родителям бизнес вместо пенсии: зарабатываем 70 тысяч, мама не даёт продать В три раза быстрее приемка товара и оптимизация трудозатрат на 73%: как «РСТ-Инвент» помог Gulliver Group ИИ-шечный мир победил? О влиянии искусственного интеллекта на игропром Кремль снижает давление на Телеграмм пока Европа строит интернет по паспорту Как CEO, CTO и CIO за 8 часов собрали ИИ-директора, который умеет держать позицию под давлением Как (не) потерять домен за выходные Вместо 8 разных VPS: как я организовал практику студентам на одном сервере Почему твой Open Source проект не замечают? R&D: искусство управления неопределенностью в разработке AI-дефляция: вакансий для разработчиков больше, а рост зарплат — худший за 15 лет Мы отдали управление роботами OpenClaw. Что из этого вышло Галактический ID: система идентификации для всех форм разумной жизни Шесть основ бизнес-анализа: начинаем с вопроса «Кто в игре?» Код-ревью, в котором дело не в коде Данные переехали. Команда — нет Системной подход к сдаче OSWE в 2025 Почему комната управления реактором покрашена в цвет морской пены 4 YAML-файла вместо PySpark: как аналитикам строить пайплайны без разработчиков LLM-агент для поиска свободных доменов: автоматизируем подбор Когда, зачем и как правильно начинать новую сессию в Claude Code? Как я заставил нейросеть писать макросы для FreeCAD Анатомия ИИ‑агента для подбора персонала. От тысячи резюме к топ‑10 за минуты Опыт разработчика как экономика внимания Автономность как точка невозврата: кто будет субъектом в цифровом будущем Обучение ИИ в «диких» условиях: как рутинные действия превращаются в датасеты Как измерить LLM для задач кибербеза: обзор открытых бенчмарков Где хранить код? Сравнение GitHub, GitLab и Bitbucket Математика объясняет, почему нормальное распределение встречается повсюду Почему ваш FinOps не работает: 12 тезисов от практиков Как подписать проектную документацию УКЭП с использованием бесплатных лицензий Pilot Адаптивное администрирование Sigla Vision Я грузил уран в бочки, а потом 20 лет строил ИТ в атомной отрасли Чем позвонить с Эвереста? История и обзор спутниковой связи. Часть 2 Как языковая модель помогает контролировать качество инструктажей по охране труда в металлургии Как не передать на desktop свой IP в РКН Анатомия SAP Privileges: как устроено управление правами в macOS MoneyDev: Сказка про три главных слова Обновлённый токенизатор видео K-VAE 2.0 от Сбера Как сделать диспетчеризацию дома на 1284 квартиры почти бесплатно Как мы разогнали железную дорогу Мы дали агентам рутину. Теперь надо решить — что делать с освободившимся временем Токсичный контент, промпт-хакинг и защита ИИ — всё о Guardrails для LLM Умный город начинается с точного взгляда: как «Фалькон Тех» меняет пространство к лучшему Навайбкодил приложение для анализа графов Почему Дюну так интересно читать? Упрощаем работу с рутиной или как стать Гендальфом Белым Деконструкция Go: CPU, RAM и что там происходит. Go Assembler база. Часть 1.1 Какие профессии исчезнут из-за ИИ, а какие появятся? И что с этим делать Как мы построили IT-отдел, где хочется расти: архитектурные встречи, прозрачные метрики и книжные подарки Rufler: Делаем из Claude Code автономный рой через один YAML-конфиг Sing-box и белый список приложений Как построить надёжный обмен сообщениями в микросервисах: лучшие практики для enterprise OpenAI строит MLM-пирамиду, а McKinsey и Accenture помогают ей в этом Дом, который не построил Фишер (Часть 2) «Сверхзвуковой математик» против «Вдумчивого логиста»: битва алгоритмов 3D-упаковки Мультимодальные модели – грубый и дорогой инструмент Разговоры ничего не стоят. Код тоже Проверки физических лиц: с кого начнет ФНС Топ-10 бесплатных нейросетей для создания видео в 2026 году Первые слои кода: как наши решения сегодня определяют архитектуру ИИ на десятилетия Разработка нового статического анализатора: PVS-Studio JavaScript Поиск уязвимостей ПО: базовый минимум или роскошный максимум Почему оценка персонала не работает как инструмент управления Как мы разработали ИИ-ассистента и сократили рутину продуктовой команды на 50% Как я ушел из найма, нажарил косточек и продал на маркетплейсах на 168 млн в год Когда 1С:ERP уже внедрена, а нормального производственного плана всё ещё нет Как я сделал Claude мультимодальным, подключив к нему Qwen Omni Как приглашение на вакансию мечты превращается в атаку Infrastructure as Code: философия и лучшие практики IaC Тестируем Yandex Code Assistant на задаче, в которой нужно хранить секреты nxs-universal-chart v3.0: новое поколение универсального Helm-чарта Callback Injection: Техника, которая отправила Microsoft Defender в глухой нокаут «Все идеи на стол»: митап как способ вывести проект из тупика Сегодня я узнал нечто новое о GPU благодаря багу в своей игре Как заставить LLM ̶ ̶г̶а̶л̶л̶ю̶ ̶ эволюционировать Карта событий как фундамент аналитики: практический кейс для E-commerce Что выбрать для AI: x86, ARM или RISC-V? Дайджест железа за март Роль соматических мутаций в развитии аутоиммунных заболеваний: путь к избирательной терапии Mythos от Anthropic — тревожный сигнал для всех, а не только для банков Guardrails для LLM на Java: как приручить промпт‑инъекции и токсичные ответы Green-VLA: как мы собрали VLA-модель для реального антропоморфного робота и не потеряли обобщение Финансовая гонка вооружений: почему умные люди добровольно в ней участвуют Эра ИИ-агентов наступила: выбираем лучшего цифрового сотрудника # Практический опыт внедрения WinCC Redundancy на производственном предприятии Сделал MVP за 3 дня, а потом неделю прикручивал оплату. Оно того стоило? Физика против Маска: почему Starship V3 может оказаться ещё одной катастрофой Нефть Венесуэлы: крупнейшие запасы в мире, но не крупнейшая нефтяная держава JPA 4. Переосмысление Hibernate Почему зеркальная фотокамера Nikon D5 десятилетней давности идеально подошла для миссии «Артемида-2» Проект «Уровень-Спутник» или как мы сделали платформу для гидрологов «Замедлиться, чтобы ускориться»: почему ИИ повышает цену ошибок в требованиях и архитектуре Как с нуля поднять трафик IT-компании на 1657% при бюджете 55 тыс. и выжить Pixel-perfect Downsampling — идеальная отрисовка 50 миллионов точек без потерь
Рекомендательные системы для бизнеса — мой опыт разработчика
tkutru · 2026-04-28 · via Все публикации подряд на Хабре

Если вы видели "С этим товаром покупают…", "Попробуйте этот урок дальше" или ощущали необычную точность автоподбора треков в музыкальных сервисах - вы сталкивались с рекомендательной системой.

Но стоит ли конкретному бизнесу вообще её строить? И если да, то с чего начать, чтобы не потратить впустую месяцы инженерного времени на "чёрный ящик", который никто не понимает?

Эта статья написана мной РУКАМИ (не "ИИ") и основана на моём выступлении-вебинаре для инженеров, предпринимателей и продуктовых специалистов. Я не ML исследователь и не публичный спикер - я фулстек-разработчик, который создавал и поддерживал рекомендательные системы в разнообразных коммерческих проектах.

Целевая аудитория - все, кому интересна эта тема.

Что такое рекомендательная система и зачем она бизнесу? (одна страница моей личной демагогии)

Упрощённо, рекомендательная система - это компьютерная программа, которая предлагает подходящие товары/предметы (items) пользователям (users) на основе взаимодействий (interactions).

Компонент

Что это

Примеры

Пользователи (users)

Кто получает рекомендации

Клиенты, студенты, посетители сайта

Товары (items)

Что мы рекомендуем

Товары, уроки, видео, статьи и пр. контент

Взаимодействия (interactions)

Сигналы предпочтений

Просмотры, лайки, покупки, написание комментариев, добавления в закладки, оценки и т.п.

Сделаю небольшой шаг назад, чтобы взглянуть на "большую картину" - а собственно, в чём реальная ценность рекомендательных систем для бизнеса?

Бизнес - это создание товаров и услуг ради прибыли, за счёт добавленной ценности.

У машин два неоспоримых преимущества перед человеком: скорость и точность вычислений. Никакой голливудской магии тут нет.

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

Все разговоры про "умные алгоритмы", "нейросети, которые понимают пользователя" - маркетинговое фуфло. В классическом смысле компьютеры тупы. Они не думают, а скорее - исполняют инструкции. Написанные человеком.

Отдельная моя ремарка про цунами чатбот-ИИ-хайпа. Современные "универсальные" LLM умеют всё на поверхностном уровне, но на глубоком - почти ничего. Их работу сложно интерпретировать, тонко настроить под конкретную задачу, они ненадёжны и выдают галлюцинации с уверенным тоном. Бывают полезны в узких сценариях, но далеко не настолько, как пытаются продать. Бездумное внедрение "чёрных ящиков" без контроля ведёт к фильтр-баблам, неуместным рекомендациям и потере доверия. Топ-менеджмент часто требует воткнуть ИИ везде, не задумываясь о цене ошибки.

В отличие от этих "универсальных решений", правильно построенная рекомендательная система даёт предсказуемую пользу: скорость, точность, управляемая интерпретируемость, гибкая настройка. Вы можете понимать, почему пользователю показали конкретный товар или урок. Вы можете отладить правило, скорректировать вес, провести A/B-тест. Вы контролируете процесс.

Классический пример, работающий десятилетиями: "покупатели, которые смотрели это, также покупали..." на Amazon. Никакой нейросетевой магии - простая коллаборативная логика, посчитанная быстро и точно. Этот подход до сих пор генерирует значимую долю выручки той и аналогичных платформ.

Переходим к конкретике работы рек. систем

Представим, у вас есть онлайн-школа по изучению иностранного языка, например испанского. Студентам периодически назначаются домашние задания. Например: почитать текст/посмотреть видео/послушать подкаст, и потом дать обратную связь - оценить уместность задания.

Кратко, пример результатов работы рексистемы можно описать так:

Студенту John Doe назначается новое домашнее задание “Заказываем тапас в Барселоне”, потому что похожий на него студент Mark Smith, ранее уже выполнял это задание и дал позитивную обратную связь, оценив уместность задания в 5/5.

(примечание: мой изначальный вебинар был на английском, поэтому многие имена и примеры данных в коде тоже будут на английском, потому что мне влом было специально всё переделывать на русский)

Возникает логичный вопрос - а как мы (быстро, точно, без монструозных видеокарт и “облаков” из загнивающих вражеских стран) посчитали, что John Doe похож на Mark Smith?

Представим, результат нашего запроса к бд выглядит так:

Оффтоп вопрос для дотошного читателя: как в табличке оказался знак вопроса? Второй оффтоп вопрос для ML-щиков: что не так с этими данными? (речь про конкретный столбец)

Оффтоп вопрос для дотошного читателя: как в табличке оказался знак вопроса? Второй оффтоп вопрос для ML-щиков: что не так с этими данными? (речь про конкретный столбец)

Помимо обычных данных, мы получили "индекс похожести" (similarity score) в диапазоне [0,1], основанный на ряде правил. А именно - если по сравнению с John Doe у другого студента:

  1. Одинаковый уровень владения изучаемым языком ("B1" == "B1"), добавляем 0.5

  2. Насколько-то % совпадают теги интересов, добавляем до 0.3. Иными словами, считаем коэффициент Жаккара

  3. Совпадает родной язык (native language), добавляем 0.1

  4. Схож возраст (в пределах 5 лет), добавляем 0.1

Фактически, это алгоритм K-ближайших соседей в своей простейшей форме, эвристической и основанной на чётких рукотворных правилах.

Запрос на T-SQL выглядит так:

WITH users AS (
  SELECT 'john_doe' user_id, 'John Doe' name, 'B1' skill, 'travel,food,culture' interests, 'en' native_lang, 28 age
  UNION ALL SELECT 'mark_smith', 'Mark Smith', 'B1', 'travel,history,culture', 'en', 31
  UNION ALL SELECT 'sofia_ivanova', 'Sofia Ivanova', 'B1', 'business,travel,food', 'ru', 29
  UNION ALL SELECT 'chloe_dubois', 'Chloe Dubois', 'B2', 'food,wine,travel,culture', 'fr', 26
  UNION ALL SELECT 'anna_muller', 'Anna Müller', 'A2', 'grammar,exams', 'de', 24
  UNION ALL SELECT 'carlos_ruiz', 'Carlos Ruiz', 'B2', 'business,negotiations', 'pt', 35
),
john AS (SELECT * FROM users WHERE user_id = 'john_doe'),
user_tags AS (SELECT u.user_id, u.name, u.skill, u.native_lang, u.age, TRIM(value) tag FROM users u CROSS APPLY STRING_SPLIT(u.interests, ',')),
john_tags AS (SELECT TRIM(value) tag FROM john CROSS APPLY STRING_SPLIT(interests, ',')),
similarity_calc AS (
  SELECT u.user_id, u.name, u.skill, u.interests, u.native_lang, u.age,
         COUNT(CASE WHEN jt.tag IS NOT NULL THEN 1 END) shared_tags,
         COUNT(DISTINCT ut.tag) + (SELECT COUNT(*) FROM john_tags) - COUNT(CASE WHEN jt.tag IS NOT NULL THEN 1 END) union_tags
  FROM user_tags ut
  LEFT JOIN john_tags jt ON ut.tag = jt.tag
  JOIN users u ON u.user_id = ut.user_id
  GROUP BY u.user_id, u.name, u.skill, u.interests, u.native_lang, u.age
)
SELECT 
  name [User], skill [Skill], interests [Interests], native_lang [Native Lang], age [Age],
  CASE WHEN user_id = 'john_doe' THEN '1.00' ELSE
    RIGHT('00' + CONVERT(VARCHAR(10), CAST(ROUND(
      CASE WHEN skill = (SELECT skill FROM john) THEN 0.5 ELSE 0 END +
      CASE WHEN union_tags > 0 THEN (shared_tags * 1.0 / union_tags) * 0.3 ELSE 0 END +
      CASE WHEN native_lang = (SELECT native_lang FROM john) THEN 0.1 ELSE 0 END +
      CASE WHEN ABS(age - (SELECT age FROM john)) < 5 THEN 0.1 ELSE 0 END,
    2) AS NUMERIC(4,2)), 4), 4) END [Similarity to John]
FROM similarity_calc
ORDER BY CASE WHEN user_id = 'john_doe' THEN 0 ELSE 1 END, [Similarity to John] DESC;

Можете поковырять его, скопипастив себе или например сюда

Пока мы поработали только с "пользователями"-студентами (users), чтобы понять, как искать похожих пользователей.
Для полноценной рек. системы нам надо учесть "товары"-домашние задания (items) и "взаимодействия"-оценки от студентов выполненным домашним заданиям.

Напомню, наша рек. система должна работать по следующей логике:


Студенту John Doe назначается новое домашнее задание HW-101 “Заказываем тапас в Барселоне”, потому что похожий на него студент Mark Smith, ранее уже выполнял это задание и дал позитивную обратную связь, оценив уместность задания в 5/5.

Запрос с учетом "товаров" и "взаимодействий" будет выглядеть так:

-- Recommendation for John Doe: profile match + peer feedback
WITH users AS (
  SELECT 'john_doe' user_id, 'John Doe' name, 'B1' skill, 'travel,food,culture' interests, 'en' native_lang, 28 age  UNION ALL SELECT 'mark_smith', 'Mark Smith', 'B1', 'travel,history,culture', 'en', 31  UNION ALL SELECT 'sofia_ivanova', 'Sofia Ivanova', 'B1', 'business,travel,food', 'ru', 29
),
items AS (
  SELECT 'HW-101' item_id, 'Ordering Tapas in Barcelona' title, 'B1' skill, 'travel,food,culture' tags  UNION ALL SELECT 'HW-102', 'Spanish Business Emails', 'B2', 'business,writing'  UNION ALL SELECT 'HW-103', 'DELE A2 Grammar Drills', 'A2', 'grammar,exams'
  UNION ALL SELECT 'HW-104', 'Mexican Street Food Vlog', 'A2', 'food,travel,culture'  UNION ALL SELECT 'HW-105', 'Argentine History Podcast', 'B1', 'history,culture,travel'
),
feedback AS (
  SELECT 'mark_smith' user_id, 'HW-101' item_id, 5 rating  UNION ALL SELECT 'mark_smith', 'HW-105', 4  UNION ALL SELECT 'sofia_ivanova', 'HW-101', 5  UNION ALL SELECT 'sofia_ivanova', 'HW-102', 3  UNION ALL SELECT 'sofia_ivanova', 'HW-104', 4
),
-- Pre-aggregate peer ratings per item to avoid duplication
item_feedback AS (
  SELECT item_id, AVG(rating * 1.0) AS avg_rating
  FROM feedback
  WHERE user_id IN ('mark_smith', 'sofia_ivanova')
  GROUP BY item_id
),
john AS (
  SELECT * FROM users WHERE user_id = 'john_doe'
),
recommendations AS (
  SELECT 
    i.item_id,
    i.title,
    -- Personal relevance: skill + interest overlap + base weight
    (CASE WHEN i.skill = j.skill THEN 0.5 ELSE 0 END +
     (SELECT COUNT(*) FROM STRING_SPLIT(i.tags, ',') t 
      WHERE TRIM(t.value) IN (SELECT TRIM(value) FROM STRING_SPLIT(j.interests, ','))) * 0.3 / 3.0 +
     0.2) AS personal_score,
    ISNULL(f.avg_rating, 0) AS avg_social_rating
  FROM items i
  CROSS JOIN john j
  LEFT JOIN item_feedback f ON f.item_id = i.item_id
)
SELECT TOP 3
  item_id AS [Item ID],
  title AS [Title],
  ROUND(personal_score, 2) AS [Personal Match],
  CAST(avg_social_rating AS DECIMAL(3,1)) AS [Avg Rating from Peers],
  ROUND(personal_score + (CASE WHEN avg_social_rating >= 4 THEN 0.2 ELSE 0 END), 2) AS [Final Score]
FROM recommendations
-- Exclude items John already completed
WHERE item_id NOT IN (SELECT item_id FROM feedback WHERE user_id = 'john_doe')
-- Deterministic ordering: score first, then item ID
ORDER BY [Final Score] DESC, item_id ASC;

Опять же, можете его скопипастить и проверить здесь

Данный запрос даст следующие результаты:

Вуаля, мы построили несложную рекомендательную систему!

Двигаемся дальше - рекомендательные системы по типу "черного ящика"

Работает примерно так:

  1. Скармливаем данные (datasets)

  2. ??? магия чёрная чёрного ящика ???

  3. Получаем рекомендации

Достаточно похоже на нейросети? Концептуально - весьма.

Преимущества таких моделей в том, что они могут выявлять неочевидные паттерны и быть более эффективными на конкретных задачах. За что нередко надо расплачиваться сниженной интерпретируемостью результатов и повышенной вычислительной прожорливостью.

Однако, выбор между прозрачностью и простотой модели (как в описанной выше рек. системе) и "черноящиковостью" - это, как правило, не выбор между одним либо другим, а скорее выбор точки на диапазоне ближе к чему-то.

Условно, если двигаться от "более проразчного" к "менее прозрачному", я бы распределил рекомендательные системы как-то так:

Подход

Примеры

Прозрачность

Когда имеет смысл

Жёстко прописанные правила

"показать урок Б после урока А"

полностью объяснимо, очевидно, захардкожено

старт, мало данных, фигак-фигак и в продакшн

Эвристики

схожесть по тегам, демографии, эвристический kNN

объяснимо - как в примере выше

есть нюансы, но так же остаётся требование делать всё быстро, дёшево, понятно

Матричная факторизация

SVD, ALS

частично прозрачно, но надо приложить усилия, чтобы объяснить факторы, типа "фактор 7 связан с интересом о путешествиях"

средний масштаб (~десятки тысяч товаров), можем начинать называть себя ML-щиками!

Градиентный бустинг

LightGBM, XGBoost

можно отлаживать по фичам

когда захотелось заморочиться похитрее после факторизации

Эмбеддинги + поиск

two-tower сети + векторный поиск

не особо прозрачно, интерпретировать всё не имеет смысла

большой каталог товаров (больше чем почти у всех), и нужна скорость

Сквозные нейросети

ленты TikTok/Instagram

полностью чёрный ящик

огромные данные и команда, когда условно 1% улучшения в какой-нибудь метрике - это дополнительные десятки или сотни тысяч долларов прибыли каждый месяц

Более сложные и менее прозрачные рексистемы работают не только с большим количеством данных, но и большим типом разных взаимодействий (клики, просмотры, написание комментария, оценки, потраченное время), учитывая также контекст (устройство, с которого заходили, география, день недели) и последовательность этих действий.

Помимо прочего, такие системы нередко сочетают в себе гибридный подход, например могут использовать эмбеддинги (поиск во векторам) для быстрого нахождения "товаров-кандидатов" и дальше использовать градиентный бустинг или сквозные нейросети для ранжирования/сортировки найденных кандидатов.

Как выглядят "менее прозрачные" рекомендательные системы

Разберём вариант, как конкретно выглядит "меньшая прозрачность" рек. систем на примере матричной факторизации.

Напомню, матрица - это система это по-сути табличка, или двумерный массив.

В нашем случае, следует рассмотреть матрицу взаимодействий (user-item matrix).

HW-101

HW-102

HW-103

HW-104

HW-105

John Doe

?

?

?

?

?

Mark Smith

5

?

?

?

4

Sofia Ivanova

5

3

?

4

?

  • Строки = пользователи

  • Столбцы = товары (домашки)

  • Ячейки = оценки (или клики/время)

  • ? = пропущенные значения (студент ещё не видел задание)

Цель: предсказать "?" так, чтобы предложить пользователю уроки с максимальным значением.

В отличие от предыдущего примера с эвристическим kNN, где правила настройки весов задавались вручную, подход матричной факторизации предполагает автоматический подбор значений факторов. Это уже настоящее машинное обучение.

Вектор - это последовательность чисел (как строка, столбец, или одномерный массив).

Для каждого студента и каждого задания мы задаём вектор из k факторов. Количество факторов k устанавливается экспериментально и обычно это от 5 до 20 для относительно небольших данных (где-то до ~15 тысяч взаимодействий-interactions).

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

Тогда вычисление конкретного значения "?" для ячейки John Doe, HW-101 (первая ячейка в пред. таблице) будет выглядеть так:

//Обучение уже прошло и дало нам эти векторы из пяти скрытых факторов
$u = [0.42, -0.18, 0.61, 0.05, -0.33]; //вектор студента John Doe
$i = [0.55,  0.12, 0.48, 0.22,  0.10]; //вектор задания HW-101

//Базовые поправки (bias), которые модель выучила автоматически
$global = 3.85; //средняя оценка по всей школе
$u_bias = 0.30; //John склонен ставить оценки чуть выше среднего
$i_bias = 0.15; //HW-101 в целом нравится аудитории

//Считаем скалярное произведение: насколько векторы "смотрят в одну сторону"
$dot = 0;
for ($k = 0; $k < 5; $k++) {
    $dot += $u[$k] * $i[$k];
}

//Прогноз
$prediction = $global + $u_bias + $i_bias + $dot;

echo "Прогноз оценки John для HW-101: " . round($prediction, 2) . "/5\n";

//В итоге получим: Прогноз оценки John для HW-101: 4.78/5

Да код на PHP, что поделать... =)

Аналогично, мы можем посчитать и заполнить остальные ячейки в строке исходной таблицы, и найти домашние задания с максимальными предсказаниями. Отсортировав их, мы получим топ рекомендаций для конкретного студента.

Основная идея этого примера в том, что вектора для пользователя John Doe [0.42, -0.18, 0.61, 0.05, -0.33] и задания HW-101 [0.55, 0.12, 0.48, 0.22, 0.10] состоят из 5 факторов каждый, и каждый из этих факторов является скрытым, латентным.

Несмотря на то, что система автоматически их вычисляет прозрачным образом, она не даёт им никаких названий или объяснений.

Мы можем лишь предположить, что, к примеру, первый фактор для задания 0.55 как-то связан с едой (чем выше значение, тем больше тема еды характерна для задания), а третий фактор для студента 0.61 возможно связан с уровнем владения изучаемым языком.

Если вы представите, что пользователей у вас не три, а пять тысяч, заданий не пять, а десять тысяч, а факторов при этом штук 20, интерпретация рекомендаций может стать значительно сложнее по сравнению с предыдущим примером с эвристическим kNN, где расчёт рекомендации проходил по явным и понятным правилам.

И это один небольшой пример движения в сторону меньшей прозрачности - всегда можно пойти ещё дальше в "лес", вплоть до глубоких нейронных сетей с миллионами и миллиардами весов, где практически невозможно чётко интерпретировать значение каждого отдельного "нейрона".

Применимость рекомендательных систем для бизнеса

Применимость рек. систем может сильно варьироваться в зависимости от конкретного коммерческого проекта.
Я бы выделил следующие взаимосвязанные условия, когда рек. система может быть реально уместной:

  • Желание и возможность инвестировать в рексистему
    Рексистема не является волшебным инструментом, появляющимся "из воздуха".

    Любое решение, даже условно готовое, требует настройки, поддержки, погружения в тему. Данные надо причесывать, системы метрик - создавать и отслеживать.

    Всё это требует времени, ресурсов - больших, чем "15 минут в день".

  • Короткий цикл обратной связи
    Речь идёт о взаимодействиях (interactions) и метриках. Взаимодействия - это обратная связь от пользователей.

    Вы должны уметь довольно быстро понять, нравится, уместен ли рекомендуемый контент, или нет.

    Метрики, измеряющие эффективность и некоторые другие показатели работы рек. системы, также должны обновляться раз в какое-то не слишком долгое время. Навскидку, это должно быть что-то в пределах одной недели.

    Если между обновлениями рекомендациий, взаимодействий или метрик проходит год - у вас вряд ли будет возможность эффективно обновлять и поддерживать рек. систему.

  • Данные в правильном формате и в достаточном количестве
    Навскидку, вам нужно не менее 100 пользователей и не менее 1000 "товаров" (items), которые вы будете рекомендовать. Больше - лучше.

    Помимо прочего, данные о пользователях, товарах и контекстах должны быть оцифрованы (не быть "на бумаге" или в виде неявных знаний, устных описаний и т.п.) и иметь соответствующий формат.

    Насчёт формата - вам скорее всего придётся данные всё равно "причесывать", но есть нюансы, о некоторых из которых я напишу ниже.

  • Возможность проводить A/B и прочие тесты, и измерять изменения
    Вытекает из первого пункта про инвестиции в рексистему, но решил обозначить отдельно.

    Рексистема без метрик = непонятное нечто (мы улучшаемся или ухудшаемся со временем? в каких аспектах?).

    Невозможность сравнить две модели = невозможность выбрать оптимальную.

Типа:

Подходит

Не подходит

Интернет-магазин с историей покупок

B2B с десятком сделок в год

Видеоплатформа с метриками просмотра

Сильно зарегулированная отрасль без права на эксперименты

Образовательный сервис с трекингом прогресса

Стартап с упором на "максимизацию количества фич" и без аналитики, типа "добавим потом"

Измеримость работы рек. системы. Метрики

Основная мысль - надо не только регулярно проводить достаточно измерений, но и понимать, что и как будет измеряться.

Как было показано выше, решения в области рекомендательных систем можно написать и "руками", без библиотек, фреймворков, готовых программ и прочих сторонних/облачных продуктов. В таком случае, систему отчётов (сбора метрик) скорее всего придётся написать руками тоже.

Однако, даже если взять какое-то готовое решение, которое помимо рекомендаций будет выдавать ещё метрики, это не освобождает от необходимости иметь систему отчётов по рекоммендациям и понимать, как она работает.

А именно:

  • Надо понимать, как конкретно считаются метрики (подробнее об этом ниже)

  • Важные метрики следует дублировать на своей стороне

  • Имеет смысл дополнять готовые метрики своими собственными

  • Как бы то ни было, система метрик/отчётов должна минимально зависеть от конкретной реализации, чтобы рексистему или конкретную версию модели можно было поменять на другую, и сравнивать одно с другим через отчёты (а-ля D из SOLID)

Теперь немного про технические метрики рексистем.

Это не исчерпывающее руководство, просто примеры для понимания:

Precision@K

Если система показала пользователю K рекомендаций, какая доля из них реально оказалась ему полезна?

Скрытый текст

Это базовая метрика точности, которая отвечает на вопрос о качестве выдачи, а не о полноте охвата.

Допустим, вы разбили данные студента на обучающую и тестовую выборку, обучили модель на восьмидесяти процентах истории, а затем попросили её порекомендовать пять товаров из оставшихся двадцати процентов. Если из пяти рекомендованных товаров студент в реальности положительно оценил только два, то Precision@5 составит сорок процентов.

Метрика не учитывает порядок внутри топа и не штрафует за пропущенные релевантные товары, которые не попали в выдачу. Она показывает исключительно чистоту того, что увидит пользователь прямо сейчас.

Coverage

Какую долю всего каталога система способна рекомендовать пользователям?

Скрытый текст

Если в вашем каталоге десять тысяч товаров, а алгоритм рекомендует только пятьсот самых популярных, покрытие составляет пять процентов.

Низкое покрытие означает игнорирование длинного хвоста, что со временем снижает маржинальность и лишает новинки шансов на продвижение. Высокое покрытие говорит о том, что модель исследует весь ассортимент, но требует контроля качества, чтобы не показывать откровенный мусор.

На практике метрику считают как отношение уникальных рекомендованных товаров к общему числу доступных товаров за выбранный период. Это индикатор здоровья системы, а не точности предсказаний.

Novelty

Насколько рекомендуемые товары неочевидны или непопулярны для конкретного пользователя?

Скрытый текст

Система может выдавать идеально релевантные товары, которые пользователь и так давно знает или с которыми постоянно положительно взаимодействует (хорошо оценивает, периодически покупает и т.п.).

Новизна штрафует такие выдачи и поощряет рекомендации, находящиеся вне прямой истории взаимодействий.

Обычно метрику рассчитывают через обратную популярность товара в логарифмической шкале, умноженную на вероятность того, что пользователь ещё не сталкивался с этим объектом.

В образовательном сервисе это может быть урок по смежной теме, который студент ещё не открывал, но который логично вписывается в его траекторию. Высокая новизна без потери релевантности удерживает внимание и снижает эффект усталости от однообразия.

Diversity

Насколько сильно отличаются друг от друга товары внутри одной выдачи для одного пользователя?

Скрытый текст

Если все пять рекомендованных уроков посвящены одной грамматической теме, система имеет низкое разнообразие. Даже если каждый урок идеально подходит по уровню, пользователь быстро потеряет интерес из-за монотонности.

Разнообразие измеряют через попарное сравнение признаков товаров в выдаче, например через косинусное расстояние между их векторами или разницу категорий. В рекомендациях это работает как встроенный регулятор, который не даёт модели зацикливаться на одном кластере интересов.

Баланс между точностью и разнообразием настраивается вручную через весовые коэффициенты в финальном скоринге.

Serendipity

Способность системы рекомендовать товары, которые пользователь не искал, но неожиданно высоко оценил.

Скрытый текст

Это самая сложная для автоматизации метрика, потому что она сочетает релевантность с непредсказуемостью.

Формально её можно оценить как долю рекомендаций, которые попали в топ взаимодействий пользователя, но при этом имели низкий базовый скор популярности или не пересекались с его историей по тегам.

В реальной жизни это срабатывает, когда студент получает рекомендацию по культуре страны, а не грамматике, и вдруг понимает, что это именно то, что мотивировало его начать учить язык.

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

Recall@K

Какую долю всех потенциально релевантных товаров система успела захватить в свою выдачу размера K?

Скрытый текст

В отличие от Precision, которая смотрит на качество показанного, Recall оценивает полноту охвата.

Если у пользователя в тестовой выборке двадцать релевантных товаров, а модель в топ десять включила только четыре, метрика составит двадцать процентов. Этот показатель критичен в сценариях поиска или подбора, где пропуск важного элемента стоит дороже, чем показ лишнего (например: поиск вакансий, подбор курсов, медицинские рекомендации).

На практике Recall@K и Precision@K используют в паре, так как они находятся в обратной зависимости: расширяя выдачу, вы ловите больше нужного (растёт Recall), но неизбежно разбавляете ленту шумом (падает Precision).

NDCG@K

Оценка качества ранжирования, которая учитывает, что релевантные товары на верхних позициях важнее, чем на нижних.

Скрытый текст

Аббревиатура расшифровывается как Normalized Discounted Cumulative Gain (Нормализованный дисконтированный кумулятивный выигрыш). Звучит сложно, но идея простая: релевантный товар вверху списка ценится гораздо выше, чем тот же товар внизу.

Пользователь редко смотрит дальше 3–5 позиций. Поэтому попадание на 1-е место даёт системе максимум баллов, на 5-е - существенно меньше. Метрика буквально "дисконтирует" ценность товара с ростом его позиции в списке.

Главное преимущество NDCG перед Precision/Recall - она работает с градациями релевантности. Не кликнул/не кликнул, а открыл -> посмотрел 10 секунд -> добавил в корзину -> купил. Итоговое значение всегда от 0 до 1: единица означает идеально отсортированную выдачу, ноль - полную ерунду. Это отраслевой стандарт для поисковиков и персонализированных лент, где порядок выдачи решает всё.

Отдельно замечу, что у любого коммерческого проекта есть и "бизнесовые", маркетинговые метрики, типа: CTR, LTV, конверсия, обращения в поддержку и т.п.

И хотя между вышеперечисленными техническими метриками рексистем и "бизнесовыми" метриками проекта есть взаимосвязь, она как правило не прямая и не мгновенная.

Например, высокая доля coverage (покрытие каталога в рекоммендациях) и качественный контент могут улучшать удержание пользователя и CTR, а высокий Precision@K как правило будет повышать LTV.

Но чтобы понять это, надо продолжительное время: а.) поддерживать рексистему б.) собирать и сравнивать метрики.

Типовые ошибки при разработке рек. системы

Опять же, не исчерпывающее руководство - просто примеры. Условно, поделю на ошибки данных (почему нужен правильный формат, правильно причесывать) и ошибки на уровне продукта/архитектуры.

Начнём с типовых ошибок на уровне данных:

  • Неконсистентность
    Разные форматы дат, дубли сущностей, со временем - изменение неизменяемого. Модель начинает давать странные результаты не из-за алгоритма, а из-за мусора на входе.

    Ошибка в самой первой картинке этой статьи - использование числового age (возраста) вместо birth_year (года рождения) для нахождения пользователей, схожих по возрасту. Age меняется со временем, а birth_year - нет, из-за чего при использовании age многие пользователи будут то схожи, то не схожи в зависимости от дня в году. И т.д.

  • Игнорирование негативных сигналов
    Обучение только на кликах и покупках без учёта пропусков, скрытий, быстрых выходов и дизлайков. Без негативных примеров система не понимает, что показывать точно не надо.

  • Утечка будущего в прошлое
    В обучающую выборку попадают признаки, которые стали известны только после взаимодействия. Например, модель предсказывает клик, а в фичи уже зашито время просмотра. На тестах метрики хорошие, в продакшене - бяка.

  • Магические пропуски
    Слепая замена пустых значений нулями или средним. Для модели это создаёт искусственные закономерности. Пропуски нужно либо явно маркировать, либо обрабатывать отдельно для каждого типа признака.

  • Дрейф данных
    Поведение пользователей, популярность товаров или сезонность меняются, а веса модели остаются старыми. Метрики плавно деградируют. Решение - мониторинг распределений признаков и регулярное переобучение.

  • Отсутствие версионирования
    Невозможно понять, какая версия датасета или фичей обучила текущую модель. При падении качества или необходимости отката приходится гадать. Нужен чёткий учёт версий данных, кода и весов.

Ошибки уровня продукта и архитектуры:

  • Нейросеть или "непрозрачный" продукт на старте
    Сложная модель требует много данных, вычислительных ресурсов и экспертизы. На раннем этапе простая эвристика или базовая коллаборативная фильтрация часто работают лучше и быстрее. Сложность добавляют только когда простые методы уперлись в потолок.

  • Рекомендации только популярных товаров
    Алгоритм скатывается в выдачу бестселлеров, потому что они дают стабильный CTR. Длинный хвост и новинки игнорируются. Система выглядит рабочей, но персонализации не происходит.

  • Игнорирование холодного старта
    Новый пользователь или новый товар попадают в систему, а выдача остаётся пустой или случайной. Без отдельной стратегии (онбординг, контентные признаки, популярные категории, тематические подборки) теряется первый контакт.

  • Скорость против точности
    Попытка запускать тяжёлую модель "на лету" для каждого запроса. Пользователь ждёт, серверы перегружаются, метрики падают. Правильный подход - оффлайн генерация кандидатов и лёгкое онлайн-ранжирование или кеширование.

  • Оптимизация под неверную метрику
    Погоня за CTR или временем сессии без учёта качества приводит к кликбейту, выгоранию аудитории и оттоку. Техническая метрика должна коррелировать с бизнес-целью, а не подменять её.

  • Отсутствие фолбека при проблемах с API
    Если модель упала, сеть лагает или данные не подгрузились, пользователь видит пустой экран. Нужен жёсткий запасной вариант: популярные товары, статические подборки, последний успешный кеш. Система должна работать всегда, даже с временной деградацией качества.

Подводя итог

Рекомендательная система - не волшебная палочка и не обязательный атрибут "цифрового продукта". Это инструмент, который работает ровно настолько хорошо, насколько хорошо вы понимаете свои данные, цели пользователей и бизнес-процессы.

За всеми разговорами про нейросети, эмбеддинги и "умный ИИ" стоит простая истина: чаще всего бизнесу нужна не самая сложная модель, а самая предсказуемая, интерпретируемая и быстрая. Начинайте с малого и двигайтесь в сторону усложнения - постепенно. Не гонитесь за "чёрными ящиками", пока не упрётесь в потолок простых методов.

Если рекомендательная система понятна, надёжна и ведёт в правильную сторону, она окупит вложения многократно. Если же строить её на хайпе, неподготовленных таблицах и слепой вере в "автопилот" - получится дорого, сложно и бесполезно.

Прагматизм важнее моды, прозрачность важнее сложности, а измерения - важнее догадок.

Спасибо за внимание.

P.s.: Текст разрешается копировать только в неизменном оригинальном виде, с указанием авторства и ссылкой на оригинал.