Кейс 2. Прогноз времени выполнения задачи разработчиком

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

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

Суть кейса

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

Мы используем следующие признаки:

  • story points задачи

  • количество затронутых файлов

  • количество строк изменений (diff)

  • опыт разработчика в месяцах

Цель – предсказать фактическое время выполнения задачи в часах.

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

circle-exclamation

Почему это сильный кейс

Во-первых, он ломает стереотип, что ML – это обязательно computer vision или NLP. Здесь чистая инженерная задача.

Во-вторых, веса модели легко интерпретируются. Можно получить ответы вида: "при прочих равных каждый дополнительный story point добавляет в среднем 1.2 часа" или "чем больше опыт разработчика, тем меньше времени уходит на задачу".

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

Реалистичный сценарий использования

Данные для такого кейса обычно берутся из внутренних систем:

  • story points – из Jira или аналогичного трекера

  • количество файлов и строк – из Git

  • опыт разработчика – из HR или внутреннего профиля

  • фактическое время – из тайм-трекера или post-factum анализа

Обучение модели делается оффлайн, например раз в неделю.

Предсказание используется либо в planning-tool, либо в tooling вокруг CI/CD (например, при анализе pull request как вспомогательная метрика для сравнения ожидаемой и фактической сложности изменений).

Важно подчеркнуть: модель не заменяет человека, а помогает скорректировать ожидания.

Формализация задачи

Каждая задача описывается вектором признаков:

x=(x1,x2,x3,x4)\mathbf{x} = (x_1, x_2, x_3, x_4)

Где:

  • x1x_1 – story points

  • x2x_2 – количество файлов

  • x3x_3 – количество строк изменений

  • x4x_4 – опыт разработчика

Модель линейной регрессии предсказывает:

y^=w1x1+w2x2+w3x3+w4x4+b\hat{y} = w_1 x_1 + w_2 x_2 + w_3 x_3 + w_4 x_4 + b

где y^\hat{y} – предсказанное время выполнения задачи в часах.

Реализация с RubixML

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

Подготовка данных

Каждая строка – одна задача из прошлого, где известно фактическое время выполнения.

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

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

Обучение модели

RubixML оптимизирует веса линейной модели с L2-регуляризацией, минимизируя функцию потерь на обучающем датасете.

Предсказание времени

Интерпретация весов

Один из главных плюсов линейной модели – возможность посмотреть на коэффициенты.

Теперь модель можно объяснить (вес – это coefficient):

  • вес при story points показывает, сколько часов в среднем добавляет один SP

  • вес при количестве файлов отражает накладные расходы на контекст

  • вес при количестве строк часто коррелирует с объёмом ручной работы

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

Такую модель уже можно обсуждать с командой и корректировать признаки осознанно.

circle-exclamation

Шум и переобучение

Этот кейс особенно хорош для разговора о качестве данных.

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

  • отвлечений

  • параллельных задач

  • сложности доменной логики

  • человеческого фактора

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

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

Выводы по кейсу

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

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

circle-info

Чтобы самостоятельно протестировать этот код, установите примеры из официального репозитория GitHubarrow-up-right или воспользуйтесь онлайн-демонстрациейarrow-up-right для его запуска.

Last updated