Запуск Caffe на RPi + SqueezeNet

Продолжение идеи про кормушку для синичек.

1

Фабула прошлой части: за окном стоит прозрачная кормушка. На неё смотрит камера, подключённая к Raspberri Pi. Хочу автоматическую съёмку птичек с распознаванием + с анализом того сколько. Плюс хочу чтобы кадры сохраняло, а лучшие –  мне выкладывало куда-нибудь.

Установка Caffe и разметка базы птичек внезапно прошла ударными темпами. Плюс начитал много интересной инфы. Так что решил разбить пост на две части. В текущем посте – установка Caffe на RPi + рассказы про забавную сеточку SqueezeNet. В следующем посте (будет завтра-послезавтра) – разметка базы, обучение, оптимизация архитектуры сети/сетей.

Вот очень полезный репозиторий с Caffe. Но почти без инструкций. Сказано:

if I missed any setup steps here or if you run into any issue, please let me know.

Реальность несколько посложнее. У меня был старый Raspberry Pi B+. Под ним caffe не соберётся, приходится делать апдейт GCC. Вариантов в инете масса, но 95% из них не работает. Caffe это нестандартный Debian. Правильный вариант вот:

Update /etc/apt/sources.list to have jessie wherever you’ve currently got wheezy

sudo apt-get update
sudo apt-get dist-upgrade
sudo rpi-update
reboot

По времени у меня этот апдейт занял 2-3 часа.
Главное – не забыть поменять “jessie” на “wheezy”. Это критично.
Дальше установка идёт по пути Ubuntu:

sudo apt-get update
sudo apt-get upgrade
sudo apt-get install -y build-essential cmake git pkg-config
sudo apt-get install -y libprotobuf-dev libleveldb-dev libsnappy-dev libhdf5-serial-dev protobuf-compiler
sudo apt-get install -y libatlas-base-dev 
sudo apt-get install -y --no-install-recommends libboost-all-dev
sudo apt-get install -y libgflags-dev libgoogle-glog-dev liblmdb-dev
sudo apt-get install -y python-pip

По времени где-то пол часа-час.
Теперь нужно установить OpenCV. Он ставиться тоже только с бубнами. К сожалению, я это делал года 2 назад, так что подробной инструкции проверенной сейчас дать не смогу. Но похоже было что-то на это.
Короче OpenCV сейчас ставиться так и всё:

sudo apt-get install libopencv-dev python-opencv

То что выше, это если вы хотите 3.0. Проверял на RPi3
Заканчиваем установкой BLAS, минут за 10-20:

sudo apt-get install libopenblas-dev

Дальше есть два пути.

Первый путь – запускаем “make all”.
Автор Rpi Caffe как бы намекает нам, что тут и нужно остановиться, а дальнейшие работы делать следующим образом:

On one terminal, type — sh cont_classifiy_squeezenet.sh
On another terminal, type — python python/cont_record.py

По сути, запустить один c++ процесс, который будет мониторить в папочке “/var/tmp/” появление файла, который обрабатывать и выкладывать в папочку ответ “/var/tmp/topics.csv”.
Класть файл и обрабатывать ответ – питоном.
Понятно, что это оптимальный по времени процесс. Но есть пара существенных минусов:
1) Сложнее код который придётся модифицироватьи  поддерживать, постоянно нужно рекомпилить на pi
2) Нагрузка на ssd-карточку выше из за постоянных процессов чтения-удаления

Для продакшн решения, если нужно получить прирост скорости на 20-30% – надо приводить этот вариант в порядок. А для побаловаться хочется питон. Так что нужно пройти не предусмотренное автором: поставить в pip весь комплект библиотек.

Второй путь.
Понятно, что часть библиотек из requirements.txt не нужна. А часть у меня даже не установилась. Вот список тех, которые я оставил (сильно не уверен, что все нужны):

 

Cython>=0.19.2
numpy>=1.7.1
scipy>=0.13.2
scikit-image>=0.9.3
h5py>=2.2.0
networkx>=1.8.1
nose>=1.3.0
pandas>=0.12.0
python-dateutil>=1.4,<2
protobuf>=2.5.0
python-gflags>=2.0
pyyaml>=3.10
six>=1.1.0

В первую очередь вынес всё связанное с matplotlib. Теперь можно запустить установку:

for req in $(cat requirements.txt); do pip install $req; done

Pip под арм начинает всё собирать сам с нуля. Так что это на долго. У меня ушло где-то пол дня. На моём Pi нужно запустить их с нуля.
Теперь “make all”, “make pycaffe”.
Всё, поздравляю! Ваш Caffe сбилжен:
1
Чтобы его использовать нужно прописать в терминале перед вызовом:

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/pi/Caffe/caffe-rpi/build/lib
export PYTHONPATH=$PYTHONPATH:/home/pi/Caffe/caffe-rpi/python

В принципе, всё стандарт, ничего нового.
Сходу удалось запустить скрипт:

import caffe
import numpy as np
from scipy import misc

caffe_root = '/home/pi/Caffe/caffe-rpi/'
net = caffe.Net(caffe_root+'/SqueezeNet/SqueezeNet_v1.0/deploy.prototxt', caffe_root+'/SqueezeNet/SqueezeNet_v1.0/squeezenet_v1.0.caffemodel', caffe.TEST)
image = misc.imread(caffe_root+'/examples/images/cat.jpg')
transformer = caffe.io.Transformer({'data': net.blobs['data'].data.shape})
mu = np.array([128.0, 128.0, 128.0])
transformer.set_transpose('data', (2, 0, 1))
transformer.set_mean('data', mu)
transformed_image = transformer.preprocess('data', image) 
net.blobs['data'].data[0] = transformed_image
net.forward()
print net.blobs['prob'].data[0].argmax()

Всё заработало как часы. Но.. Отъело 500 метров памяти. Учитывая, что на RPI только 350 свободных метров оперативки, остальная память ушла в swap. Распознавание длилось по 20-25 секунд. Как это лечить – расскажу завтра-послезавтра в части про настройку сетки.
А сейчас – небольшое отступление про SqueezeNet.
Авторы уверяют, что сетка, при сохранении точности AlexNet, имеет в 50 раз более хорошую производительность. Конечно,
AlexNet это не бог весть что по современным временам. Но производительность x50 внушает уважение. Что сделано:

  1. Свёртки 3*3 заменены на свёртки 1*1. Каждая такая замена в 9 раз уменьшает число параметров
  2. На вход оставшихся свёрток 3*3 пробуют подавать только маленькое число каналов
  3. Уменьшение размера делается как можно позднее, чтобы свёрточные слои имели большую площадь активации.

Эти три стратегии привели к тому, что авторы создали “fire module”:

diagramme2_fire

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

  1. Отказ от FC слоя на последнем уровне. В принципе, это достаточно модно и неплохо влияет на производительность. Для того чтобы это достичь авторы берут выход последнего свёрточного слоя, разделяют его на N частей, и усредняют каждую часть через avg-pooling по числу каналов. Эти выходы пулинга подаются на обучающие нейроны.
  2. В некоторых из версий сети авторы пробую различные пробросы боковые. Почти residual. Это увеличивает точность:
    1-QJGepE_JorGO1LlI0Qy1yA

Идеи хорошие. На RPi3 судя по всему даёт реальное время (чую, что 10-15 fps должно быть).
А что это дало на моём RPi-B+ расскажу завтра-послезавтра.

1 thought on “Запуск Caffe на RPi + SqueezeNet”

Comments are closed.