Умная кормушка: Machine Learning, Raspberry Pi, Telegram, немножко магии обучения + инструкция по сборке |
||
МЕНЮ Искусственный интеллект Поиск Регистрация на сайте Помощь проекту ТЕМЫ Новости ИИ Искусственный интеллект Разработка ИИГолосовой помощник Городские сумасшедшие ИИ в медицине ИИ проекты Искусственные нейросети Слежка за людьми Угроза ИИ ИИ теория Внедрение ИИКомпьютерные науки Машинное обуч. (Ошибки) Машинное обучение Машинный перевод Реализация ИИ Реализация нейросетей Создание беспилотных авто Трезво про ИИ Философия ИИ Big data Работа разума и сознаниеМодель мозгаРобототехника, БПЛАТрансгуманизмОбработка текстаТеория эволюцииДополненная реальностьЖелезоКиберугрозыНаучный мирИТ индустрияРазработка ПОТеория информацииМатематикаЦифровая экономика
Генетические алгоритмы Капсульные нейросети Основы нейронных сетей Распознавание лиц Распознавание образов Распознавание речи Техническое зрение Чат-боты Авторизация |
2017-02-27 10:18 Всё началось с того, что жена захотела повесить кормушку для птиц. Идея мне понравилась, но сразу захотелось оптимизировать. Световой день зимой короткий — сидеть днём и смотреть на кормушку времени нет. Значит нужно больше Computer Vision!
Идея была простой: прилетает птичка — вжуууух — она оказывается на телефоне. Осталось придумать как это сделать и реализовать. В статье:
Все исходники открыты + описан полный порядок развёртывания получившейся конструкции. Если честно, то я не был уверен, что всё получиться + сильно был не уверен в итоговой архитектуре. По ходу работы она достаточно сильно менялась. Поэтому на Хабре пишу после того как есть уже готовая версия. Перипетии развития можно отследить на GitHub и в блоге, где я делал небольшие отчёты походу (ссылки в конце статьи). Идея «Хочу птичек распознавать» может иметь десятки реализаций. В начале работы мне хотелось, чтобы система автоматически обнаруживала прилетающих к кормушке птичек, определяла что это за птички, выбирала лучшую фотографию, выкладывала куда-нибудь + вела статистику посещаемости. Не всё отсюда получилось сделать. Комплектуха
Инфраструктура Кусок моей домашней сети, который ответственен за проект имеет следующую конфигурацию: Rpi+камера висят около окна. Я провёл много экспериментов для того чтобы найти удобное крепление и хороший вид:В результате воткнул в подставку для ножей. Она мобильна, можно набирать базу с разных ракурсов. Не сказать, что жене эта затея понравилась, но я уверяю, что это временное решение: Картинки получаются такими: Качество с вебки не ахти какое. Но, в принципе, понятно происходящее. Вернёмся к архитектуре. В Rpi воткнут WiFi модуль, который подключен в роутеру. Фотографии сохраняются на сетевой диск (WD MyBook live). Для набора базы это необходимое условие (флешки на RPi на много не хватит). При использовании, конечно, можно отключать. Но мне удобно. Сам Rpi висит без монитора. Его управление, программирование и настройка сейчас делается с основного компа по SSH. В начале что-то настраивал воткнув в монитор, но это не обязательно. Сбор базы Хорошо собранная база — это куда сложнее, чем правильный выбор нейронной сети. Использование битой разметки или не репрезентативных данных может ухудшить качество системы куда больше, чем использование VGG вместо ResNet.Сбор базы — это масса ручного, пусть даже неквалифицированного труда. Специально для разметки больших баз есть сервисы Яндекс.Толока и Amazon Mechanical Turk. От их использования я воздержусь: размечу всё вручную сам, тут недолго. Хотя, может, имело бы смысл и туда загнать, потренироваться в использовании. Естественно, хочется автоматизировать такой процесс. Для этого рассмотрим, что мы хотим. Что есть база в нашей ситуации:
По сути, происходит событие «прилёт птицы». По этому событию мы должны определить, что это за птица прилетела и сделать хороший кадр. Проще всего сделать тривиальный «детектор движения» и набрать весь его выход. Детектор движения сделаем самым простым способом: Код на несколько строчек:
Результат работы детектора Детектор срабатывал на любую шевелёнку. На её начало и на её окончание. В результате работы детектора в течении недели была набрана база примерно в 2000 кадров. Можно считать, что птицы там в каждом втором кадре => приблизительно 1000 изображений птичек + 1000 изображений не птичек. Учитывая, что точка обзора двигается не сильно – можно предположить, что базы плюс минус достаточно.Разметка базы Для разметки я написал простенькую программу на питоне. Снизу, ссылки на исходники. Огромное спасибо моей жене за помощь в разметке! Два часа убитого времени:) И ещё пару часов потратил я сам. Для каждой картинки размечалось два признака:
Итого, имеем для каждой картинки вектор из двух величин. Ну, например, тут: Явно качество нулевое (0), а сидит – большая синица (2). Всего по базе получилось примерно половина кадров с птицами, половина пустая. При этом синиц-Лазоревок было всего 3-5% от базы. Да, набрать большую базу от них – сложно. И да, обучиться по этим 3-5% (~40 картинок) – нереально. В итоге пришлось обучать только по обычным синицам. И надеяться что рано или поздно база лазоревок наберётся сильно больше. Расширение базы Сейчас я перескочу через этап, чтобы сохранить неразрывность повествования. Про сеть, выбор сети и её обучение будет рассказано следующем разделе. Там всё более-менее обучилось, кроме лазоревок. По базе процент точности распознавания кадра был где-то 95%. Когда я говорю, что машинное обучение в конкурсах и в реальности – это две не имеющих отношения друг к другу вещи – на меня смотрят как на психа. Задачи на машинное обучение на конкурсах – вопрос оптимизации сеток и поиска лазеек. В редком случае – создания новой архитектуры. Задачи машинного обучения в реальности – вопрос создания базы. Набора, разметки, автоматизации дальнейшего переобучения.Задача с кормушкой мне понравилась во многом из-за этого. Она с одной стороны очень простая – делается практически мгновенно. А с другой стороны – очень показательная. 90% задач тут – это не имеющая отношения к конкурсам тягомотина. База, которую мы набрали выше — крайне мала для задач такого вида и не оптимальна. Она не предполагает «стабильности». Всего 4-5 позиций камеры. Одна погода за окном. Но она помогает создать алгоритм «первого этапа». Который поможет набрать хорошую базу. Модифицируем детектор, который я описал выше:
Как набор базы!? А что же мы раньше делали? Раньше мы набирали обычную базу. А теперь – мы набираем базу ошибок. За одно утро сетка выдала более 500 ситуаций распознанных как синицы: Но позвольте! Может ваша сетка не работает? Может вы перепутали каналы, когда передавали изображение к от камеры к сетке? К сожалению, нет. Это судьба всех сеток обученных на малом объёме данных (особенно у простых сетей). В тренировочном сете было всего 6-9 позиций камеры различных. Мало засветок. Мало посторонних шумов. А когда сетка видит что-то совершенно новое – она может выкинуть неверный результат. Но это не страшно. Ведь мы прикрутили сбор базы. Всего 300-400 пустых кадров в нашу базу – и ситуация улучшается. Вместо 500 ложных тревог за утро их уже ноль. Только вот что-то и птичек продетектировалось всего 2/3 от их общего числа. Вот этих не распознало: Для их сбора и стоит «else» в коде выше. Просмотреть базу срабатываний детектора движения за весь день и выбрать 2-3 пропуска просто. Для этих картинок у меня заняло времени — секунд двадцать. Реальное внедрение системы – это постоянный рабочий процесс, где сетку приходится подкручивать каждые несколько дней. А иногда и внедрять дополнительные механизмы: Решение задачи на практике – это построение такой схемы, со всеми процессами дообучения, переобучения, сбора и оптимизации сбора. Придумать и выстроить модель — это сильно больше сил, чем обучить хорошую модельку. Зачастую приходится использовать древние алгоритмы: SIFT, SURF. А иногда брать обученную сетку, но совсем из другой задачи. Например детектор лиц. Это всё? База готова? Система работает? Конечно нет. За окном лежит мягкий, белый и пушистый снег. Но он становиться жестким и обледеневшим. Наступает весна. В последние два дня опять попёрли ложняки: Солнышко светит не оттуда. Снег подтаял. Капель застучала. Хорошая база для такой задачи — это весна + зима + лето + осень. По всем птицам, по разным видам за окном, по разной погоде. Я уже писал длинную-длинную статью тут про то как собирать базы. Мне кажется, что для такой задачки требуется база хотя бы в 2-3 тысячи кадров по каждой птице в разных условиях. Пока такого нет. Генерация базы Базу можно дополнять автоматическим образом, генерируя искажения. Это значительно увеличивает стабильность. Я делал не все возможные приращения. Можно сделать больше и поднять качество. Что я делал:
А это можно было бы добавить:
Если честно, то полноценно вводить все эти искажения не стал. Времени нужно больше. А всё равно качество базы не переплюнуть. Это не Kaggle, чтобы бороться за доли процента. Настройка и запуск сети Установка Один из главных вопросов, которые мне хотелось понять для себя — возможность запуска ML-фреймворков для CV на простых устройствах. Например на Raspberry Pi. Слава богу, что кто-то подумал об этом за меня. На ГитХабе есть полезный репозиторий почти без инструкций.На RPi B+ Caffe и всё необходимое для него можно собрать и установить где-то за день (самому нужно подходить раз в час и пихать очередную команду). На RPi3 как я понимаю можно сильно быстрее (за 2-3 часа должен справиться). Чтобы не захламлять статью кучей Linux-команд — просто скидываю ссылку сюда, где я всех их описал. Caffe собирается! Работает! Изначально я думал использовать какую-то простенькую сеточку, например CaffeNet, или даже VGG16. Но автор порта Caffe под RPi настоятельно советовал использовать SqueezeNet. Я попробовал — и мне понравилось. Быстрая, достаточно мало памяти занимает. Точность, конечно, не уровня ResNet. Первая попытка развернуть сеть не очень удалась. Сеть съела 500 МБ оперативной памяти из моих 400 свободных. Достаточно быстро понял, что основная проблема была в выходном слое. Он был от ImageNet на 1000 выводов. Мне было нужно всего десяток выходных нейронов. Это уменьшило размер сети сразу до 150 метров. Сетка сама по себе очень интересная. По точности она сопоставима с AlexNet. При этом в 50 раз быстрее, по заявлениям авторов. Сама сетка реализует следующие принципы:
Итого. Есть локальный компонент: А есть глобальный, созданный из этих локальных: Идеи хорошие. На RPi3 судя по всему даёт реальное время (чую, что 10-15 fps должно быть). На моём RPi B+ это дало 1.5-2 кадра в секунду. Что ж, на большее, я, если честно, и не рассчитывал. Авторы порта под Caffe использовали сетку через C++, чтобы повысить производительность. Но я перетащил в Питон. На нём сильно быстрее разрабатывать. Обучение сети Во-первых, как я сказал выше, пришлось поменять последний полносвязный слой:
Я заменил его на два выхода. На одном выходе — наличие птицы + её тип. На втором — качество. Итоговая скорость работы на RPi B+ у такой штуки ~ 2-3 секунды на кадр + его предобработку (почистить код от конвертаций лишних, обучить в формате в котором OpenCV напрямую данные принимает – будет 1.5-2 секунды). В реальности, обучения слоя на «качество» – это та ещё морока. Я использовал три подхода (да, можно подходить корректно и брать специальные слои потерь. Но лень:
Оставил — последний. Он единственный который хоть как-то работал. С птицами по базе всё хорошо. 88%-90% правильного отнесения в класс. При этом, естественно, 100% потеря всех лазоревок. После того как я добрал базу — качество улучшилось. Ещё чуть-чуть улучшилось за счёт приращений из базы (описывал выше). Вывод информации, Telegram Переходим к последней миле. Нужно доставить картинки пользователю. Было несколько вариантов:
Почитав про Telegram и убедившись что всё там не так уж с страшно, плюс есть некоторые загадочные «каналы» — решил использовать именно его. Приступать боялся. Казалось, что придётся удолбать день-два на задачу. Наконец собрался с духом прочитать документацию про фронт работ. Выделил час вечером. А потом я был приятно удивлён. Несказанно приятно удивлён. Этого часа мне практически хватило, чтобы написать и подключить всё что я задумал. Нет, я конечно вру. Потратил 2 часа. А потом ещё полтора чтобы прикрутить ненужную свистелку. Настолько оно всё просто/удобно/безбажно работает. По сути сделать бота:
Как я понял, очень желательна обработка команд /start и /help. Если я когда-то буду делать умный дом — то чую, что без этой штуки не обойдётся. Что умеет бот. Ссылка на бота будет ниже:
Бот совмещён с распознаванием. Его текст — в исходниках. Файл capture.py. Ссылка на бота и на канал с выводом бота — ниже, в подвале статьи. А вот так выглядит режим спама: Как развивать У меня есть несколько дальнейших идей, как улучшать и что делать дальше:
Есть более глобальные планы. В идеале на следующую зиму хотел бы сделать кормушку, которая была бы полностью автономна. Чтобы её повесить на даче и управлять из города. Но для этого нужно решить ряд проблем. Во-первых, найти адекватного провайдера и сделать систему которая бы не выжирала безумно много трафика. Во-вторых, сделать дозатор корма, которым можно было бы удалённо управлять. В-третьих, сделать адекватную сборку всего этого чуда в единый кулёчек. Бюджет времени Очень много из упомянутого я делал в параллельно с другими задачами. Так что оценка может смещаться. Если захотите сделать себе такое же — часть пути помогут срезать мои исходники, но очень много придётся повторять.
Реально это всё дело растянулось недели на три-четыре. Мне кажется, что при наличии исходников и нового RPi — можно сделать раза в 2-3 быстрее. Исходники Выкладываю ссылки то, как всё это выглядит в запущенном виде. Ссылки на все свои исходники в процессе. А так же ссылки на все используемые фреймворки/гайды/форумыКак затестить Есть несколько ограничений:
Надеюсь, вас напугал. Вот ссылка на бота — @WindowFeeder_bot А вот ещё раз канал — t.me/win_feed Source code Репозиторий проекта.Тут — программы для разметки базы. Под винду и под убунту (почему-то OpenCV по разному воспринимает коды клавиатуры, было лень запариваться). Тут — пример обучения сети. На мой взгляд очень полезный для Caffe. Когда я что-то обучаю сам, то зачастую получается какая-то похожая программка такого типа. Это — основной код. Тут реализован: детектор движения, бот Telegram, нейронная сетка для распознавания. Тут база фотографий. Для большинства фотографий есть текстовый файл. В нём две цифры. Первая — тип птицы. Вторая — качество снимка (актуально только когда птица есть). Так же есть картинки без текстовичков. Там всегда нет птицы. Часть базы я взял из VOC2012, чтобы создать подвыборку с изображениями совсем не относящимися к теме. Так что увидите кошечек или собачек — не удивляйтесь. Если наберёте свою базу, то добавка моей должна повысить стабильность. Инструкции, полезные команды, и.т.д. Достаточно большой объём подробностей по настройке RPi я срезал в этой статье. В своём блоге я чуть более подробно рассказывал про некоторый этапы настройки. Плюс тут я отрезал часть идей которые не получили продолжения — там они есть. Всего 4 заметки по теме: 1, 2, 3, 4.Версия Caffe под Raspberry Pi утащена отсюда. Там почти нет описания по установке. Можно читать в моём блоге, можно пробовать по наиболее близкому гайду действовать (пропуская кусок с hdf5). Гайд по запуску OpenCV на RPi. Полезная инструкция по созданию бота в Телеграмме. А вообще, большую часть сэмплов про него я брал отсюда. Хороший репозиторий (API под Python). З.Ю. Если вдруг кто-то хочет чтобы у него птички распознавались, есть RPI, но нет развернутого компа, чтобы обучить сетку на своих данных — присылайте базу, размеченную в указанном формате. Переобучу с добавлением своей, выложу в общий доступ.З.Ю.Ю. Очень боялся, что сегодня никто из птичек не прилетит и будет обломно. Выложил статью — и пусто. Но одна всё же уже прилетела, порадовала. Может будут ещё.Источник: habrahabr.ru Комментарии: |
|