InquirerSara Duterte says to avail all remedies amid grave threats rapsPunchWhy AI cannot replace actors — FilmmakerDaily MaverickESCAPE: How a humble Soweto parkrun cultivates joy and community in a neglected parkThe Jerusalem PostIsrael warned of potential Hamas kidnapping operation years before Oct. 7, IDF col. claims - reportCNN TürkOpenAI ve Samsung arasındaki yakınlaşmaRTP DesportoJames Rodríguez regressa ao futebol colombianoBollywood HungamaBipasha Basu seeks Tukaram Mundhe’s help after she finds worms in protein powder: “You are our only hope”Inquirer EntertainmentAi-Ai delas Alas says ‘not affected’ by ex Gerald Sibayan’s new marriageוואלהצה"ל ושב"כ: חיסלנו את מפקד חטיבת חאן יונס בזרוע הצבאית של חמאסWirtualna PolskaWojna o Trybunał. Czarzasty odmawia Nawrockiemu i żąda ślubowania BerkaDaily MailMy husband will leave our home to his two children, can I carry on living here if he dies first?ColliderOnly 10 Anime Series From the 1990s Are True Masterpieces
The Daily Newsstand · Free, Always
Friday, September 11, 2026

Галлюцинации VLM в zero-shot детекции: ложные тревоги о дыме и решение на уровне промпта

Translate

Ранняя детекция дыма и огня — частая и ценная задача уличной видеоаналитики. Камера может заметить возгорание раньше, чем люди на улице или оператор. Обучать отдельную модель детекции — это датасет, разметка и время, а возгорания в кадре выглядят слишком по-разному, чтобы быстро покрыть все случаи. Поэтому, когда сценариев детекции в рабочих проектах стало слишком много, я решила попробовать короткий путь, попросить VLM (языковую модель, умеющую работать с изображениями) найти дым текстовым промптом в zero-shot режиме, то есть вообще без обучения под задачу.

Первой моделью взяла Qwen3.5-9B — VLM среднего размера, порядка 9 млрд параметров. Схема простая: на вход — кадр и промпт «найди дым, верни bbox», на выходе — JSON с координатами. Детектор настраивается текстовым описанием, в этом всё преимущество подхода.

На тестовых видео с уличных и панорамных камер с реальным дымом система работала хорошо. А вот проверка на заведомо чистых видео (обычные дворы с парковкой, газоном, деревьями, людьми, магазинами) закончилась неожиданно: ложные сработки на 70 % кадров, на отдельных видео до 96 %.

В статье разбираю, почему это произошло, какие известные приёмы промпт-инжиниринга не помогли и как проблема решилась изменением одного промпта: доля ложных тревог на проблемных камерах снизилась с 70 % кадров до нуля, FPR (доля ложных срабатываний на негативных кадрах) на независимом бенчмарке — с 10.6 % до 0.6 % при recall выше 80 %.

Основной вывод экспериментов: задача детекции складывается из двух решений — «есть ли объект» и «где он», и их объединение в один шаг ответа VLM и один формат вывода может вызывать ложные срабатывания, когда объекта в кадре нет.

Тестовые данные

Коротко о том, на чём всё измерялось. Наборов два:

  • Негативная выборка — видео с реальных уличных камер, в основном дворы, порядка двух тысяч кадров. Отсутствие дыма и огня на них проверено вручную, поэтому каждое срабатывание на этом наборе — ложное. Именно на нём измерены все «70 % ложных» и весь перебор промптов. Кадры внутри одного видео сильно коррелированы, поэтому дальше мы смотрим не только на долю кадров, но и на число уникальных объектов, вызвавших срабатывания.

  • Размеченный бенчмарк — тысячи изображений с ручной разметкой, подобранных под наш домен: позитивы (дальний дым и огонь над лесом и полем, пожары зданий и автомобилей, задымление на улицах) и негативы со сходными сценами. На нём считались итоговые recall, precision и FPR. Варианты промпта подбирались на негативной выборке и отдельном небольшом размеченном наборе с настоящим дымом, не пересекающемся с бенчмарком. Сам бенчмарк использовался только для итоговой оценки. Данные не академические, а ориентированные на реальные условия эксплуатации.

Доля ложных здесь и далее считается по кадрам: это доля негативных кадров, на которых модель вернула хотя бы одну детекцию. Все замеры — жадная генерация (temperature 0) без constrained decoding: формат ответа задавался только текстом промпта, схема декодеру не навязывалась.

Исходный промпт и его поведение на негативных данных

Начальный промпт был типичным для zero-shot детекции:

Detect uncontrolled outdoor fire or wildfire smoke. Ignore chimney/exhaust
smoke, steam, fog, clouds, rain, snow, lens glare.
...
Output ONLY JSON in markdown code block:
[{"bbox_2d":[x1,y1,x2,y2],"label":"smoke"|"fire","confidence":0.0-1.0}]
If nothing matches: `[]`

Пустой ответ [] в промпте был формально разрешён. Однако на чистых кадрах модель почти никогда этой опцией не пользовалась.

Чем же она отвечала вместо этого? Проанализировав ложные срабатывания, я обнаружила, что все они сводятся к ~50 уникальным стабильно присутствующим в кадре объектам:

Объект

Доля всех ложных срабатываний

автомобили на дороге или парковке

~40 %

круглые красные и жёлтые знаки, листовки

~10 %

деревья и газон

~10 %

светлые предметы, размытые участки

остальное

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

Кадр без дыма и огня с уличной камеры (открытый датасет AAU RainSnow, CC BY 4.0; боксы здесь и далее — реальные ответы той же конфигурации Qwen3.5): одношаговый промпт уверенно отмечает «fire» на красном сигнале светофора. Ответ модели:

[{ "bbox_2d": [585, 256, 620, 301], "label": "fire", "confidence": 0.95 }]

Модель умеет сказать «дыма нет» — но всё равно рисует бокс

Самое интересное оказалось в сырых ответах. В 21 % ложных детекций модель возвращала бокс с confidence: 0.0 и одновременно поясняла текстом, что дыма на кадре нет. Ответ противоречит сам себе: одна его часть утверждает «объекта нет», другая содержит координаты объекта. Это показывает, что как минимум часть ошибок связана не с неспособностью распознать пустой кадр, а с рассогласованием частей генерируемого ответа. В наших наблюдениях, начав объектную ветку ответа с [{"bbox_2d":, модель почти никогда не возвращалась к пустому результату — формально разрешённый [] так и оставался номинальной опцией.

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

[{ "bbox_2d": [582, 592, 784, 749], "label": "smoke", "confidence": 0.0 }]

Как я выяснила впоследствии, в различных публикациях этот эффект уже описан для текстовых LLM: модель честна в свободном тексте, но в структурированном ответе уходит в «объектную» ветку вместо пустого списка, а антигаллюцинационные инструкции промпта часто перестают действовать при включении жёсткой схемы вывода. Получается, что мы воспроизвели этот эффект на vision-задаче, где его цена — поток ложных тревог о дыме.

Почему постобработки оказалось недостаточно

Попытки отфильтровать ложные срабатывания постобработкой не помогли:

  • порог по confidence — шкала вырождена: модель выдаёт практически только три значения: 0.9 (около 68 % ложных боксов), 0.0 (21 %) и 0.95 (11 %), отсечь нулевые можно, но это снимает лишь пятую часть тревог, остальные приходят с 0.9–0.95, поскольку confidence здесь — число, которое генерирует сама модель, а не калиброванная вероятность;

  • подтверждение по нескольким кадрам — неприменимо: это не одиночные случайные срабатывания, а устойчивые — один и тот же статичный объект даёт детекцию десятками кадров подряд;

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

Известные приёмы, которые не помогли в нашей задаче

Можно ли уменьшить ложные срабатывания только промптом? Я проверила стандартные приёмы на выборке из этих 50 уникальных случаев и размеченном наборе с настоящим дымом. В других задачах приёмы из таблицы действительно работают. Здесь — нет, и по различным причинам:

Приём

Ложные

Recall

Наблюдение в нашем эксперименте

Расширенный список исключений: «не отмечай автомобили, знаки, туман…» (negative prompting)

66 % кадров

1.00

перечисление не закрывает открытый мир, всегда находится объект вне списка. Вдобавок появились ложные срабатывания нового характера, модель начала отмечать именно те объекты, которые ей перечислили в запретах. Поведение похоже на эффект «розового слона» (ironic rebound): упоминание объекта повышает его заметность, даже если упомянут он под отрицанием.

Режим рассуждений (thinking)

0

0.40

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

Обязательное обоснование каждой детекции

64 %

1.00

эффект обратный ожидаемому — подробнее ниже

Обобщённая формулировка без перечней объектов

0

0.80

ложные уходят, но вместе со списками промпт теряет и подсказку, как выглядит «нетипичный» дым, поэтому recall дальнего дыма природных пожаров проседает с 0.97 до 0.60: отказ от явных критериев убирает часть информации, которая помогала распознавать слабые позитивные примеры

Почему не помогло обоснование

Приём rationale generation или self-explanation существует не случайно: это родственник chain-of-thought, и в задачах рассуждения он действительно повышает качество, ведь модель, вынужденная аргументировать, чаще замечает собственные ошибки. Именно поэтому его широко применяют в классификации текстов, оценке качества и LLM-judge-схемах.

Но чтобы влиять на решение, рассуждение должно генерироваться до ответа. В нашем формате объяснение идёт после координат, а в авторегрессионной генерации всё, что идёт после, не может изменить уже сгенерированное. Получается post-hoc-рационализация: модель сначала фиксирует детекцию, затем подбирает к ней аргументацию. Хуже того, требование объяснить детекцию уже предполагает, что объект найден: доля ложных на контрольной выборке осталась почти той же, 64 % против 78 % у исходного промпта. Обоснование не работает как фильтр.

Рабочее решение: разделить классификацию и локализацию

Перебрав варианты, я нашла рабочий двухэтапный промпт (presence-запрос перед локализацией), оба этапа которого выполняются в одном запросе:

Step 1 — decide, in one short line: does this frame contain burning flames or a plume of smoke? ... answering that there is nothing is
the normal, expected outcome.

<критерии: чем отличается пламя от красных объектов, дым — от тумана и теней...>

Step 2 — answer with JSON, on the last line:
- nothing burning and no smoke plume -> []
- otherwise -> [{"bbox_2d":[...],"label":"smoke"|"fire",...}]

Три ключевых элемента промпта:

  1. Свободный текст до JSON. Первой строкой модель решает бинарную задачу классификации в той форме, в которой она способна дать отрицательный ответ, то есть в свободном тексте. Это явный промежуточный шаг решения — одна строка, а не развёрнутые рассуждения thinking-режима, которые, как видно из таблицы выше, существенно снижают recall для нашей задачи.

  2. Явное разрешение ответить «ничего нет». В промпте прямо сказано: отсутствие объекта — нормальный, ожидаемый ответ. В контрольном эксперименте без шага решения recall снижается с 0.85 до 0.70.

  3. Структурированный ответ — последней строкой. Как бонус, поскольку такой формат легко парсить: JSON извлекается из последней непустой строки ответа. Рассуждение из первого шага при этом анализировать не нужно, мы сохраняем его в лог, и модель фактически сама документирует каждое своё решение, что в дальнейшем заметно упрощает отладку.

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

Промпт

Recall

Precision

FPR

Проблемные камеры, доля ложных

Одношаговый

0.855

0.847

0.106

70 % кадров

Двухэтапный

0.803

0.989

0.006

0

Что важно: recall самого сложного подкласса, дальнего дыма природных пожаров, не изменился (0.97). Общий recall стал немного ниже. Ложные тревоги ушли практически полностью при почти прежней чувствительности, поэтому этот приём вошёл в наш итоговый рабочий промпт.

Настоящий дым модель по-прежнему находит уверенно (кадр из открытого датасета D-Fire).

Цена решения. В токенах она небольшая: первый шаг — это одна короткая строка, порядка 20–40 дополнительных выходных токенов на кадр. Входная часть, а у нас это изображение из тысячи визуальных токенов плюс текст промпта, не меняется. На нашей конфигурации (vLLM, одна GPU класса RTX 4090) это выливается в +0.1 с латентности на кадр: в среднем 1.52 с против 1.41 с.

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

Один и тот же кадр: слева одношаговый промпт даёт ложный бокс «smoke 0.95» на том же светофоре, справа двухэтапный промпт детекций не даёт. Вот как выглядят реальные ответы двухэтапного промпта в трёх типовых ситуациях:

Чистый кадр:

This frame shows a wet urban street scene with parked cars, traffic
lights, and road markings. There are no visible flames, glowing embers,
or irregular bright patches. The sky is overcast but clear of any rising
smoke plumes. No smoke is emanating from vehicles, buildings, or the
ground. All objects have sharp edges and normal colors consistent with
a rainy day.

[]

Кадр с настоящим дымом:

Yes, there is a plume of smoke rising from the hillside in the distance.

[{"bbox_2d": [573, 143, 692, 286], "label": "smoke"}]

Сложный негатив (есть объекты, которые могут ассоциироваться с дымом):

The frame shows a clear sky with no visible flames or smoke plumes; the
pale area on the right is consistent with atmospheric haze or distant
cloud cover, not a rising smoke column.

[]

Параллель с другими VLM

Оставался вопрос: это особенность поведения одной модели или свойство самого одношагового bbox-формата? Я повторила эксперименты на VLM других архитектур — например, SenseNova-Vision-7B-MoT, которая поддерживает генерацию координат bounding box и для которой опубликованы метрики детекции на COCO и RefCOCO.

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

Тот же тест по остальным доступным открытым VLM класса 7–9B дал неоднородную картину: у одних моделей эффект воспроизвёлся, у других нет, а некоторые с zero-shot детекцией не справились вовсе. Каждой модели давали один и тот же одношаговый промпт и одну и ту же подвыборку из 375 негативных кадров, плюс 100 размеченных позитивов для контроля чувствительности.

Эффект воспроизвёлся ещё на двух моделях. MiMo-VL-7B повела себя как SenseNova: детекция на каждом из 375 чистых кадров при отличном зрении (99/100 позитивов), причём каждый вынужденный бокс шёл с confidence: 0.0 и меткой other: модель сигналит об отсутствии находки единственным доступным ей способом, но отказаться от координат не может. Наш парсер считает тревогой любой возвращённый бокс: другого машиночитаемого сигнала одношаговый ответ просто не даёт, так что часть проблемы здесь — интерпретация ответа, и внутри одношагового формата она неустранима. У Idefics3-8B форма умеренная: ложные срабатывания на 28 % чистых кадров (105 из 375) при 94/100 позитивов.

На подвыборке доля ложных немного отличается от полного прогона, поэтому у Qwen3.5 здесь 78 %, а не 70 % из начала статьи.

Модель

Формат ответа

FPR на негативах

SenseNova 7B (MoT)

одношаговый bbox

100 %

MiMo-VL-7B

одношаговый bbox

100 %

Qwen3.5-9B

одношаговый bbox

78 %

Idefics3-8B

одношаговый bbox

28 %

Qwen3.5-9B

двухэтапный промпт

0 %

MiMo-VL-7B

двухэтапный промпт

0 %

Idefics3-8B

двухэтапный промпт

0.5 %

Двухэтапный промпт снижает долю ложных срабатываний и у этих моделей. У Idefics3 она падает с 28 % до 0.5 % (2 кадра из 375), причём позитивов модель находит даже больше (96 против 94 из 100). У MiMo-VL ложные срабатывания исчезают полностью, со 100 % до нуля, но здесь цена заметнее: позитивов остаётся 70 из 100 против 99. То есть сам приём переносится между архитектурами, а вот баланс «ложные — чувствительность» у каждой модели свой, и его нужно проверять на своих данных.

Часть моделей с zero-shot детекцией не справилась вовсе: Phi-4-multimodal и Qwen2-VL-7B в нашей конфигурации не выдавали пригодных координат и отвечали пустым списком даже на кадрах с настоящим огнём, а LLaVA-OneVision и GLM-4.1V не давали ложных срабатываний только ценой чувствительности, пропуская больше половины позитивов.

Там, где детекция действительно работает — recall и precision на рабочем уровне, как у Qwen3-VL-8B, Qwen2.5-VL-7B или InternVL3-8B, — ложных срабатываний в одношаговом формате изначально мало. У модели MiniCPM-V-4.5 единичные ложные были, и перевод на двухэтапный промпт убрал их полностью, не задев recall, что тоже плюс.

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

Вывод и границы применимости

Мы проверили схему на нескольких своих задачах. Помимо детекции дыма, мы опробовали её на контроле перекрытия обзора камеры, к примеру ветками и посторонними объектами перед объективом. С тем же двухэтапным форматом на нашей выборке ложных срабатываний не осталось (FPR 0.21 → 0.00) при неизменном recall, то есть схему можно закладывать как шаблон и для других бинарных задач видеоаналитики.

При этом важно понимать ограничения выводов:

  • Модели. Всё измерено на открытых моделях масштаба 7–9B. Более мощные модели могут лучше справляться и с совмещённым форматом, однако исследования систематических галлюцинаций (например, DASH) показывают, что ложноположительные ответы об отсутствующих объектах встречаются и у сильных VLM.

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

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

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

Что ещё известно о галлюцинациях VLM

  • POPE — классический бенчмарк object hallucination в LVLM, построенный на вопросе «есть ли объект на изображении?». Наш первый шаг двухэтапного промпта — по сути такой же presence-запрос перед локализацией.

  • DASH — показывает, что галлюцинации VLM бывают систематическими: авторы находят кластеры реальных изображений, на которых модели стабильно «видят» отсутствующие объекты. Наши 50 повторяющихся объектов — картина того же рода.

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

Из практических материалов о том же эффекте на текстовых LLM: A Language Model Can Be Honest in Prose and Still Fabricate in JSON и JSON Mode Won’t Save You.

View the original on Хабр

KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.