В моей идее “Система из небольших специализированных моделей” было предположение, которое казалось очевидным: если поставить на разных этапах разные архитектуры, они будут ошибаться по-разному. Значит, ошибок в конечном решении станет меньше.

Вроде убедительно. Пока не нарисуешь, как именно соединены эти модели.

В первой статье я рассказывал, как использую генеративные модели для критического разбора инженерных решений. Во второй — «Активировать мало — недостаточно: почему AI-роутеру могут понадобиться альтернативные стратегии» — перешёл к вопросу о маршрутизации и сохранении нескольких вариантов действия.

Теперь пора применить тот же критический подход к собственной гипотезе.

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

Где заканчивается помощь следующего эксперта

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

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

Параллельный ансамбль устроен иначе. Несколько моделей видят один объект и отвечают на один вопрос, после чего их ответы объединяются. Там два правильных ответа иногда могут перекрыть один неправильный.

Слово «несколько» есть в обоих описаниях. Механизм исправления ошибки — только во втором, если способ объединения действительно позволяет её исправить.

Три раза по 95% — ещё не ответ

Возьмём 1000 условных объектов. Каждый из трёх узлов ошибается ровно на 50 из них. У каждого точность 95%.

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

Теперь расположим ошибки тремя способами.

Первый: узлы ошибаются на одних и тех же 50 объектах. Эти объекты теряются, остальные 950 проходят весь маршрут. Точность цепочки — 95%.

Второй: ошибки независимы. Вероятность пройти три этапа равна 0,95 × 0,95 × 0,95 = 0,857375. Получаем 85,7375%. Это вероятность в заданной модели, а не обещание ровно такого числа успехов в случайной выборке из 1000 объектов.

Третий: ошибки не пересекаются. Первый узел теряет свои 50 объектов, второй — другие 50, третий — ещё 50. До результата доходят 850 объектов. Точность цепочки — 85%.

Расположение ошибок

Точность каждого узла

Точность всей цепочки

Совпадают полностью

95%

95%

Независимы

95%

85,7375%

Не пересекаются

95%

85%

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

Если обозначить набор ошибок узла через E, то цепочка ошибается на объединении E1 ∪ E2 ∪ E3. При фиксированных размерах этих наборов важен размер их объединения. Совпадающие ошибки оставляют больше объектов, которые проходят все проверки; непересекающиеся отсекают разные объекты.

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

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

А теперь соединяем те же ошибки иначе

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

Если все ошибаются вместе, голосование ничего не исправляет: остаются те же 95%.

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

P(ошибка большинства) = 3 × 0,05² × 0,95 + 0,05³ = 0,00725
Точность большинства = 99,275%

Если наборы ошибок не пересекаются, на каждом объекте ошибается не больше одного участника. Двое остальных его перевешивают. В этой искусственной конструкции получается 100%.

Та же структура ошибок

Последовательная цепочка

Бинарное голосование большинством

Полное совпадение

95%

95%

Независимость

85,7375%

99,275%

Непересекающиеся ошибки

85%

100%

Сто процентов здесь получились из устройства примера. Мы сами запретили двум участникам ошибаться одновременно. К реальным нейросетям эта гарантия не прилагается.

Для свободного текста всё ещё сложнее: два ответа могут выражать одну ошибочную мысль разными словами, а оценщик — предпочесть убедительное объяснение правильному. Результат бинарного голосования нельзя автоматически перенести на совет языковых моделей.

Расчёт, который можно повторить

Ниже полный пример на Python без сторонних библиотек. Единица означает ошибку участника, ноль — правильный ответ. Мы перебираем восемь возможных сочетаний трёх ошибок и задаём им вероятности. Поэтому здесь нет случайной погрешности генератора и не нужен seed.

from fractions import Fraction as F
from itertools import product

p = F(1, 20)  # 5% ошибок у каждого участника
states = list(product((0, 1), repeat=3))

distributions = {
    "shared": {(0, 0, 0): 1 - p, (1, 1, 1): p},
    "independent": {
        s: p \*\* sum(s) \* (1 - p) \*\* (3 - sum(s))
        for s in states
    },
    "disjoint": {
        (0, 0, 0): 1 - 3 \* p,
        (1, 0, 0): p,
        (0, 1, 0): p,
        (0, 0, 1): p,
    },
}

expected = {
    "shared": (F(19, 20), F(19, 20)),
    "independent": (F(6859, 8000), F(7942, 8000)),
    "disjoint": (F(17, 20), F(1)),
}

for name, distribution in distributions.items():
    assert sum(distribution.values()) == 1
    assert all(weight >= 0 for weight in distribution.values())
    for i in range(3):
        assert sum(w for s, w in distribution.items() if s\[i]) == p

    chain = sum(w for s, w in distribution.items() if sum(s) == 0)
    vote = sum(w for s, w in distribution.items() if sum(s) <= 1)
    assert (chain, vote) == expected\[name]
    print(f"{name:11} chain={float(chain):.6%} vote={float(vote):.6%}")

Результат:

shared      chain=95.000000% vote=95.000000%
independent chain=85.737500% vote=99.275000%
disjoint    chain=85.000000% vote=100.000000%

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

Как теперь звучит моя гипотеза

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

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

Если такой возможности нет, обнаруженное несогласие останется красивой записью в журнале.

Согласие тоже не даёт гарантии. Все участники могут уверенно повторить одну ошибку. Поэтому проверять нужно конкретный вопрос: помогает ли несогласие выделять ошибки лучше, чем более дешёвый сигнал от одной модели, при сопоставимом бюджете?

Работы по deep ensembles дают основания исследовать ансамбли как способ оценки неопределённости. Но в них полезное разнообразие возникает и при обучении сетей одной архитектуры. Отдельно авторы Rethinking Mixture-of-Agents показывают, что объединение ответов разных LLM не всегда выигрывает у объединения нескольких ответов одной сильной модели.

Значит, разные архитектуры - один из вариантов эксперимента. Пока неизвестно, окажется ли он лучшим.

Как я предлагаю проверять это на моделях

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

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

Я бы сравнил следующие варианты:

Вариант

Как устроен

На какой вопрос отвечает

Одна модель

Сразу предсказывает конечный класс

Оправдано ли вообще усложнение?

Цепочка одной архитектуры

Отдельно обученные узлы, один маршрут

Что даёт сама иерархия?

Цепочка разных архитектур

Та же иерархия и политика маршрута

Что меняется при замене архитектур?

Ансамбль одной архитектуры на узле

Несколько инициализаций, общая политика объединения

Хватает ли разнообразия обучения?

Ансамбль разных архитектур на узле

Та же политика объединения

Даёт ли архитектурное различие дополнительную пользу?

Адаптивная проверка

Дополнительные ветви запускаются выборочно

Можно ли сохранить пользу при меньшей стоимости?

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

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

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

Что считать полезным результатом

Первая метрика — доля объектов, для которых правильно определён конечный класс. Рядом нужно показать ошибки каждого уровня и долю случаев, когда правильная ветвь вообще сохранилась среди кандидатов. Тогда будет видно, подвёл нас поиск вариантов или выбор из них.

Отдельно я бы измерял ошибки после отказа от автоматического решения. Здесь важны два числа:

Покрытие = автоматически завершённые задачи / все задачи
Риск = ошибочные автоматические решения / автоматически завершённые задачи

Если система передала человеку всё, автоматических ошибок действительно не осталось. Но при нулевом покрытии риск по этой формуле не определён, а автоматизация ничего не сделала. Поэтому варианты нужно сравнивать при одинаковом покрытии или показывать всю кривую «риск — покрытие». Такой подход используется в selective classification.

Затем идут ресурсы: средняя и высокая задержка, например 95-й процентиль, пиковая память и стоимость обработки всего набора. Несколько малых моделей могут работать по очереди, но их загрузка тоже занимает время. Слово «малые» не освобождает от измерений.

Для сравнения потребуется зафиксировать оборудование и режим выполнения. Равное число вызовов не означает равные вычисления. Полезнее показать качество при нескольких бюджетах времени или стоимости, включая все вспомогательные компоненты. В задачах маршрутизации между LLM похожую постановку обмена качества на стоимость рассматривает RouteLLM.

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

Что заставит меня отказаться от этой версии идеи

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

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

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

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

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

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

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