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


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

В рознице первым вопросом стало то, как отличить прораба от тележки. И это было ничуть не смешно.

Да, и тем, кто переживал за кота-терминатора из прошлого поста — его поймали. Детали в конце.

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

Кластеры покупателей


На входе у нас данные с камер, смотрящих вертикально вниз на кассы. Картинка с них распознаётся ПО Synesis CasRetail, и мы имеем уже не видеопоток, а данные о том, во сколько пришёл какой объект и во сколько он покинул зону действия.


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

Вот пример лога (расшифровывать не стал, и так вроде должно быть понятно):

{
      "camera" : "22f961d5-9cfc-4214-8870-65edb79fe373",
      "start" : "2016-09-11T14:28:03+03:00",
      "end" : "2016-09-11T14:29:00+03:00",
      "rules" : [
      // данные для линии  
      {
         "counter" : 12,
         "rule" : "36da29cf-7858-4bc6-9b11-55ff129aeaa7",
         "extendedStatistics" : [ "2015-02-11T14:28:04+03:00", "2015-02-11T14:28:04+03:00", "2015-02-11T14:28:12+03:00"] // (optional)
      },
      // данные для зоны 
      {
         "counter" : 0,
         "histogram":[57.61533203125003,0.0, .., 0.0,0.0], // total 256 items
         "lifetimeHistogram" : [],
         "lifetimeHistogramStep" : 60,
         "lostObjectsCounter" : 2,
         "bornObjectsCounter" : 0,
         "objectsAtEndInterval" : 12,
         "rule" : "ea473652-2f7d-49fc-bce0-e6d93e472c17"
      }
   ]
}

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

ПО обрабатывает картинку 640х480 и, кстати, для задачи подсчета покупателей больше и не нужно. Система справляется легко…. Да-да, downsample почти в 3 раза и это увеличивает скорость обработки изображения. Тут не нужно много мегапикселей, так как человек может занимать в кадре всего 30-40 пикселей.

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

  • Покупатель может прийти толпой (например, семьёй). По факту будет 3-4 человека, но реально — один чек. А данные про чек в европейской стране, и если вы не хотите ждать год… ну, вы поняли.
  • Может прийти прораб, набрать стройматериалов в 3-4 тележки и уйти. Система отфиксирует группу объектов, но покупатель будет опять же один.
  • Мать с коляской и тележкой — это 3 непонятных объекта.

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

Через несколько дней наблюдений за повадками тележек выяснилось, что они льнут к людям. И группа людей, сделавшая один чек, практически одновременно уходит из кассовой зоны. То есть задача сводилась к подсчёту кластеров объектов, выходящих за виртуальную линию кассы (на картинке — tripwire_11) — а это решается крайне просто. Кстати, линия нужна для того, чтобы корректно понимать, когда человек ушел из кассы. ведь если он вышел из зоны, то он просто мог уйти из очереди назад в зал (например, психанул, не стал ждать).

То есть система в реальном времени выдаёт статистику «два объекта ? один покупатель» и из этого показывает длину очереди. А с задержкой 1 минуту валидирует себя и уточняет, сколько покупателей было по факту на основе того, как они повели себя за кассой.

Это было суперкруто. Мы решили почти все проблемы такой системой с ошибкой в 2-5% (зависит от количества тележек, уборщиц, охранников и прочих отклонений от статистического среднего).

Сюрпризы распознавания


Итак, мы:

  • Знаем входящий поток людей за каждый день и знаем его в реальном времени.
  • Знаем длину очереди на каждой кассе.
  • Умеем делать в реальном времени уведомления о том, что надо открывать ещё кассу (где-то очередь длиннее 4-5 человек).
  • Умеем закрывать кассы, если они пустые.
  • Начинаем собирать данные для аналитики для предсказания расписания касс.

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

  • Да, есть моменты, когда нужно больше кассиров.
  • Да, есть моменты, когда магазин несёт потери из-за простаивающих касс (сотни тысяч рублей в месяц).
  • Самое весёлое — при пиках на кассах 10-18 кассы 1-3 могут быть не загружены.

Про последнее скажу особо: оказывается, люди не умеют грамотно распределяться по кассам. И вполне возможны ситуации, когда какие-то кассы простаивают, а какие-то загружены. Умелое распределение позволяет сильно сэкономить по факту, и магазин этому научился.


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

Ход проекта


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

Минимальная смена кассира из аутстаффа (внешней компании, предоставляющей кассиров) — 4 часа. Чем раньше кассир будет заказан, тем дешевле. Поэтому дальше задача сводится, во-первых, к прогнозированию (нужно знать, сколько кассиров и когда надо, алгоритм, нужно сказать, не из простых — для тех, кто в теме — это блендинг из 6 моделей от классических ARIMA до RandomForest (любителям kaggle — и без xgBoost можно точно прогнозировать). А во-вторых, к оптимизации на основе прогнозных данных, а именно — к минимизации общей стоимости персонала при соблюдении необходимого уровня сервиса и кучи технических ограничений (например, аутстафф кассира нельзя выдернуть меньше чем на полдня).

Через месяц мы решили эту задачу без учёта сезонных пиков:

  • Исторические данные по дням дают точную загрузку по часам.
  • Есть профили для каждого дня недели.
  • Есть спецпрофили для ситуаций «осадки», «праздник», «день перед выходными», «день перед 3 выходными» — это очень важные ситуации для аналитики. Дождь, например, даёт минус 18 процентов к покупателям, а день перед 3 выходными — плюс 14%.
  • Есть данные о погоде.
  • Есть корреляты с других проектов (известные графики коллег со всего мира) — там просто 3-4 замера за день, но они очень полезны иногда, когда данных нет (например, будут полезны на Новый год).
  • Мы знаем конверсию, то есть с какой вероятностью зашедший в магазин станет покупателем. Это просто множитель к выходному потоку.
  • Для людей, заходящих через кассы, мы тоже знаем примерные коэффициенты — их пришлось считать руками, но они вносят очень малую погрешность.

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

Система может учиться, и сама себя верифицировать по схеме план-факт. Плюс можно прикрутить email-уведомления, собирать статистику.

Дальше


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

А это результаты нашего теста или «шуточного» сервиса под названием «пробки в столовой». Тоже отлично работает уже пару лет. Для того, чтобы им воспользоваться, достаточно зайти в корпоративную соцсеть, где в реальном времени можно посмотреть текущую загруженность нашей офисной столовой, а также прогноз времени, необходимого для того, чтобы отстоять очередь в кассу и пообедать в зависимости от того, когда подойти. И что самое интересное – совсем недавно такую систему себе захотели внедрить два внешних заказчика. Один из них, например, как оказалось, уже 2 года безрезультатно бился с огромными очередями в столовой.





Про кота


Напомню, в прошлом посте про распознавание лиц на входе на объект фигурировал кот, наносящий убытка магазину на 50-100 тысяч рублей в месяц. Этот неутомимый охотник отметился на видеонаблюдении тенью, прыгающей сверху на самые жирные мешки с кормом и вскрывающей их в поисках тёплых сочных внутренностей. А ещё на него списывали много дорогого алкоголя.

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


Ещё проекты


Поделиться с друзьями
-->

Комментарии (42)


  1. TimsTims
    03.11.2016 10:13
    +5

    > Кот уходил от погони 4 года. Даже когда за него (живого) давали награду 5 тысяч рублей
    А мне тогда показалось, что никакого кота и небыло, а сотрудники сами хитро подворовывали, списывая на кота все расходы. И по тону прошлой статьи, показалось, что вы их раскусили со своими разработками.

    В теме очень быстро угадывается магазин OBI

    > люди не умеют грамотно распределяться по кассам
    Да, и это не зависит от магазина. В том же OBI первые к входу/выходу кассы обычно всегда с очередью(небольшой), а дальние бывают совсем пустые. То же самое бывает и в супермаркетах, и в других магазинах. А уж про неоптимальное распределение людей в метро можно отдельную статью писать))


    1. Oxoron
      03.11.2016 10:52

      А уж про неоптимальное распределение людей в метро можно отдельную статью писать))

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


      1. DrZlodberg
        03.11.2016 11:46
        +1

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


    1. mtp
      05.11.2016 04:08

      > В теме очень быстро угадывается магазин OBI

      Да, при взгляде на фотку сходу вспоминается магазин OBI, который в Химковской Меге. И стоило возиться с замыливанием и кропом? Обишные безопасники в своём репертуаре. Каждый раз, выходя с касс, вечно попадал на каких-то очень строгих и важных вахтеров, скрупулезно сверявших чек и содержимое корзины.

      Давно не был в ОБИ, стараюсь туда не заходить. Но, судя по статье, порядки в их магазинах не сильно изменились. Мне, правда, уже это не интересно, давно открыл для себя приятный Леруа Мерлен со сравнимым ассортиментом, без шмона на выходе и заметно более низкими ценами.


  1. cry_san
    03.11.2016 10:14
    +4

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

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

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


  1. cry_san
    03.11.2016 10:16
    +4

    И да, спасибо за концовку истории с котом! Теперь моя душа спокойна.


  1. LoadRunner
    03.11.2016 10:20

    дядьку Дейкстру с его историей с железнодорожными вагонами
    А что за история такая?

    И что самое интересное – совсем недавно такую систему себе захотели внедрить два внешних заказчика.
    В армии проблему загруженности столовых решили уже давно :)




  1. Oxoron
    03.11.2016 10:44

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

    Простите, не понял, речь же шла про пригородные электрички. Откуда там Европа?


    1. brahew
      03.11.2016 10:56
      +1

      Электрички — это другой проект, там надо было считать населённость вагона по данным с турникетов. Про них и перроны — было отступление. Все, что ниже – исключительно про гипермаркет.


      1. DrZlodberg
        03.11.2016 11:49
        +1

        А как, если не секрет. Электричка длинная, турникеты обычно в одном-двух местах только. И народ в ней распределяется очень неравномерно. Обычно кучкуются в вагонах, которые ближе к выходу на следующих крупных станциях. Зная маршрут можно даже в час-пик ехать сравнительно комфортно.


        1. brahew
          03.11.2016 13:22

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


  1. chieftain_yu
    03.11.2016 11:06
    +6

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


    1. dmitry_ch
      03.11.2016 13:31

      Котик из военской части, и пропажи дорогого алькоголя — чего его там научили?!


      1. RussDragon
        03.11.2016 23:16

        Насколько я понял, котик был не из воинской части, пока не встретил злых охотников =)


  1. servekon
    03.11.2016 11:14

    Чтобы более равномерно распределять потоки по кассам, нужно вешать в торговом зале информационные табло «Быстрее всего вас обслужат на кассах 1..2..3».
    И вопрос: за счет чего несут убытки от простаивающих касс?


    1. Hint
      03.11.2016 11:16

      Кассирам платить нужно


      1. servekon
        03.11.2016 11:21

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


        1. Hint
          03.11.2016 11:27

          Да, более грамотно составлять график и распределять покупателей по кассам


  1. Hint
    03.11.2016 11:16

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


    1. Firz
      03.11.2016 15:08

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


      1. Hint
        03.11.2016 15:17

        Видно, что люди уже давно стоят, а касса всё еще «свободная». Вот и интересно как они эту информацию обновляют. Если автоматически, то таких задержек по 5 минут быть не должно.


        1. webkumo
          03.11.2016 16:01

          Может там «кнопочка у кассира», которая умеет только добавиться в раздел «свободная касса», а обратно отлипать не умеет?


  1. Ryppka
    03.11.2016 11:22
    +2

    Про котика: Анатолий Борисович, перелогиньтесь!))))


  1. LoadRunner
    03.11.2016 11:34

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

    Интересно, в крупных гипермаркетах такой подход решит проблему касс? То, что он сломает мозг российским покупателям — это наверняка.


    1. Oxoron
      03.11.2016 11:39

      Слишком много касс для такого подхода. А вот в аэропортах так делают (правда, разделяют кассы на группы, вроде около 5 касс на авиакомпанию).


    1. ErshoFF
      03.11.2016 11:45
      +3

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

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


      1. DrZlodberg
        03.11.2016 11:51
        +1

        Из опыта — к сожалению достаточно одного/двух человек, чтобы развалить эту систему. Стоит кому-то забить и начать строить свою очередь, как она моментально вырастает до полноценной.


      1. LoadRunner
        03.11.2016 11:53
        +1

        Одно дело, когда коллективный разум до этого доходит и учит новых, а другое — когда всех и сразу.


    1. chieftain_yu
      03.11.2016 13:11

      Это может сработать, если линия касс — метров 10. Ну, 15.
      Если кассы протянулись на 50 — уже не вариант.

      Либо нужен внешний диспетчер, который обеспечивает наличие двух покупателей у касс — обслуживаемого и следующего (чтобы не терять время, пока следующий покупатель идет к освободившейся кассе).
      И то баговаться будет со страшной силой.


    1. iSage
      03.11.2016 16:23

      https://en.wikipedia.org/wiki/MythBusters_(2016_season)#MythBustStore

      А вообще это в шмоточных обычно так — H&M, Uniqlo, etc.
      Надо заметить, что свободную кассу не всегда можно услышать/увидеть, люди тупят и это замедляет общую очередь. Плюс время на дойти до дальней кассы, например.


      1. dmitryredkin
        03.11.2016 18:17

        В Ашанах пул касс «с одной корзиной» именно так и работает.


    1. tazepam
      09.11.2016 15:09

      Так в Ашане сделано. Одна очередь на 2 кассы. По факту очередь выглядит длинной и вставать в нее никакого желания нет.


  1. 4ebriking
    03.11.2016 12:44
    -2

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


  1. aamonster
    03.11.2016 13:27
    +3

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


  1. Andrei_ra
    03.11.2016 13:27

    Электронная очередь? Идёшь по магазину, через каждые n метров блок для выдачи квитка. Получил квиток на определеную квассу, при выдаче можно заказать минимальное желаемое время: 5, 10, 15 минут. Исходя из среднего времени обслуживания и запланированной очереди система понимает какое время установить и какую кассу выбрать. На кассе при наступлении очереди загорается на табло номер квитка, не подошёл за 15 секунд — бери новый. Часть касс могут с обычной очередью работать.

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


  1. rikert
    03.11.2016 13:56

    > картинка обрезанная и замыленная по просьбе безопасников

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


  1. vis_inet
    03.11.2016 14:25

    Скажите, а зачем закрывать кассы, если они пустые?
    Кассир куда-то уходит, ему меньше платят?
    В чём смысл этого?


    1. brahew
      03.11.2016 14:27

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


  1. ehxo
    04.11.2016 01:38
    +1

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


    1. LoadRunner
      04.11.2016 13:46

      Если кота зовут Катей, то это уже приковывает внимание.