Недавно Facebook выпустила свой open-source-проект по распознаванию образов. Конечно же, его сразу захотелось пощупать, посмотреть, как он работает и что с его помощью можно получить. Мы решили разобраться с его установкой и опытным путём проверить, так ли легко его использовать, как об этом пишут в инструкции разработчики.
Этот проект не самый простой, поэтому возникает вопрос, зачем он нужен, если есть готовые фреймворки типа Keras, TensorFlow и Caffe, где, как говорится, «сел и поехал»? А ответ прост: нужен гибкий инструмент с возможностью расширения, с которым подружится Python. Научились мы отличать кита от чайки, но что нам это даст? IFunny серьёзно делает весёлое приложение и хочет удивлять пользователей новыми фичами, так почему бы не изучить такое богатое направление и применить?
Прочитав этот разбор, вы станете на шаг ближе к просветлению. Готовы? Тогда хватайте ручку, бумагу и приступаем!
И да, можно смело считать эту статью мануалом по установке, причём пошаговым, но можно и обращаться к ней в случае, если вылезла ошибка, а Google отводит глаза в сторону или выдаёт в поисковике несусветную чушь.
Приступая к установке
Немного не доходя до момента, когда нужно написать первый git clone для их проекта, остановимся на этапе железа и окружения.
Вроде бы всё прозрачно и красиво. Но. Начнём с железа. Проект очень и очень требовательный. Особенно к памяти, свопу и видеокарте. Изначально сборка велась на AWS-инстансе с конфигурацией:
- OS: Linux Redhat 2017.09 (EC2) → Ubuntu 16.04 LTS
- CPU: 16 x Intel® Xeon® CPU E5-2686 v4 @ 2.30GHz;
- HDD: 1 Tb;
- Swap: 16 Gb →128 Gb (!!!);
- RAM: 122 Gb (7 x 16 Gb, 1 x 10 Gb);
- Graphic adapter: GRID K520 → Tesla M60.
Лучше сразу используйте Ubuntu LTS, поскольку в нём уже есть все необходимые базовые компиляторы последних версий или же несложно обновиться до последних версий. В процессе сборки и запуска будет понятно, почему мы так резко перескочили с одной системы на другую, поменяли видеокарту и накинули своп.
Если хотите собрать всё это из любопытства, чтобы посмотреть, как это работает и поиграться, то обзаведитесь как минимум видеокартой с технологией CUDA. Без неё пытаться запуститься бесполезно. Чтобы понимать, какая видеокарта что может — вот линк на вики.
Видеокарта GRID K520 относится к CUDA capability 3.0+. С ней уже можно работать, но не так быстро как хотелось бы.
Поехали? Или постоим чуть-чуть…
Ставим пакет от Nvidia
Приступаем непосредственно к окружению. Для начала убедимся, что у нас g++ версии не ниже 4.9, иначе в самом конце нас может постигнуть фиаско. Берите самый новый, самый свежий g++, только что из репозитория. Далее ставим свеженькие драйвера от Nvidia.
sudo yum install nvidia #что-то такое, у амазона свой репозиторий
sudo yum install cuda #да, именно так, всё просто
nvcc --version #версия CUDA
Зарегистрируйтесь на http://developers.nvidia.com и скачайте cuDNN-библиотеку для вашей версии CUDA.
cd ~/
tar -xzvf cudnn-$VERSION-linux-x64-v7.tgz
Для Ubuntu 16.04 всё выглядит попроще:
sudo apt-get install nvidia-384*
sudo apt-get install nvidia-cuda-dev
sudo apt-get install nvidida-cuda-toolkit
И вот тут можно поступить по-разному. Официальный мануал требует, чтобы мы скопировали файлы в разные места. Можно согласиться с мануалом и скопировать так, как указано. Но можно поступить проще. Из cuda/include скопировать библиотеки в /usr/local/cuda/lib64
.
Установка Lua и LuaRocks
Дальше. Нам нужна Lua и LuaRocks (ещё один менеджер пакетов — мало нам, мало). Тут всё просто для обеих ОС:
curl -R -O http://www.lua.org/ftp/lua-5.3.4.tar.gz
tar zxf lua-5.3.4.tar.gz
cd lua-5.3.4
make linux test
cd ~/
wget luarocks-2.4.3.tar.gz
tar -xvf luarocks-2.4.3.tar.gz
cd luarocks-2.4.3
./configure
make build
sudo make install
cd ~/
Устанавливаем Torch7 и его зависимости
У нас уже есть luarocks-менеджер зависимостей. А теперь самое интересное: нужно поставить часть зависимостей через LuaRocks (всё не выйдет, иначе поставленное и вовсе не взлетит). Вообще, при установке именно этих зависимостей проблем возникнуть не должно, но тут есть много-много маленьких грабелек (а как же без них).
-
Torch (должен установиться Torch7).
git clone https://github.com/torch/distro.git ~/torch --recursive cd ~/torch; bash install-deps; # ./install.sh — так не надо делать, в LUAJIT21 сломано получение содержимого #файла в виде датасета TORCH_LUA_VERSION=LUA52 ./install.sh # ставим lua52 и радуемся: всё #компилируется и работает, на warning внимания не обращайте source ~/.bashrc # тогда заработает запуск torch через th и будут экспортированы #пути к библиотекам
По идее, ничто не остановит вас в этот момент, кроме ошибки с 'half'. Данная проблема решается следующим образом: сначала выполняем в консоли команду
export TORCH_NVCC_FLAGS="-D__CUDA_NO_HALF_OPERATORS__".
Затем запускаем установку заново.
-
COCO API: собирается только из исходников, но хотя бы ставится без проблем.
git clone https://github.com/cocodataset/cocoapi.git cd cocoapi luarocks make LuaAPI/rocks/coco-scm-1.rockspec
-
image: проблем нет. Ставим через luarocks:
luarocks install image
-
tds: внезапно это не пакет и вообще ставить надо lua ffi
luarocks install --server=http://luarocks.org/dev luaffi
-
cjson: по идее проблем нет, разве что пакет называется json.
luarocks install json
-
nnx: и вот тут засада. Вы ведь уже порадовались собранному фреймворку Torch? Тогда клонируем репозиторий в корень torch и ПЕРЕСОБИРАЕМ его целиком. Здесь необходимо уточнить, что сразу собрать с nnx не удастся, в его зависимостях как раз указаны пакеты COCO API, image, tds и cjson.
-
optim: проблем не найдено, ставится напрямую
luarocks install optim
. -
inn: аналогично
luarocks install inn
. - cutorch, cunn, cudnn — ставить именно в такой последовательности
luarocks install cutorch luarocks install cunn luarocks install cudnn
Вроде бы всё поставили. Но не покидает чувство что что-то забыли… Что-то важное… Так и есть. Сам проект кто клонировать будет?
cd ~/
git clone https://github.com/facebookresearch/deepmask.git
cd deepmask
Устанавливаем модели для обучения
Затянули? Молодцы. А вот теперь будет самая долгая часть. Скачиваем обучающие паки и сетки. И у нас есть два пути. Первый путь — скачать готовые модели и, не обучая сеть, сразу приступить к проверке своей картинки (тут можно смело пропускать шаг тренировки нейросети и сразу ставить зависимости дальше).
mkdir -p pretrained/deepmask;
cd pretrained/deepmask
wget https://s3.amazonaws.com/deepmask/models/deepmask/model.t7
mkdir -p pretrained/sharpmask;
cd pretrained/sharpmask
wget https://s3.amazonaws.com/deepmask/models/sharpmask/model.t7
cd ~/deepmask/
th computeProposals.lua pretrained/deepmask # run DeepMask
th computeProposals.lua pretrained/sharpmask # run SharpMask
th computeProposals.lua pretrained/sharpmask -img /path/to/image.jpg
Как уже было сказано, скачанных моделей достаточно для быстрого старта. Так можно поступить, чтобы не обучать нейросеть в течение нескольких дней, но этого мало для чего-то более серьёзного. Второй путь начинается здесь. Поэтому продолжаем.
mkdir -p pretrained
wget https://s3.amazonaws.com/deepmask/models/resnet-50.t7 # ой ой ой, 250 Мб.
mkdir -p ~/deepmask/data;
cd ~/deepmask/data
wget http://msvocds.blob.core.windows.net/annotations-1-0-3/instances_train-val2014.zip # ~158 Mb
wget http://msvocds.blob.core.windows.net/coco2014/train2014.zip # ~13 Gb >85k файлов
wget http://msvocds.blob.core.windows.net/coco2014/val2014.zip # ~6.2 Gb >40k файлов
Решаем ошибки с CUDA
Теперь у нас есть необходимые наборы для тренировки нейросети и валидации тренировки. Кажется, что есть.
th train.lua --help
....
THCudaCheck FAIL file=/home/ubuntu/torch/extra/cutorch/lib/THC/THCGeneral.c line=70 error=30 : unknown error
/home/ubuntu/torch/install/bin/lua: /home/ubuntu/torch/install/share/lua/5.2/trepl/init.lua:389: cuda runtime error (30) : unknown error at /home/ubuntu/torch/extra/cutorch/lib/THC/THCGeneral.c:70
Смотрим trace. Хм… Очень похоже на то, что не хватает установленных зависимостей: cunn, cudnn установился криво. Ладно, переустанавливаем. Но дело не в них. Let's make an investigation! Проверяем дальше. Пробуем снова установить cutorch и… Бинго! Модуль cwrap не обнаружен.
Устанавливаем, что ж ещё остаётся делать.
luarockt install cwrap
luarockt install cutorch
И тут мы снова получаем ошибку, что модуль cwrap не установлен. WTF? Не буду углубляться в механику LuaRocks, но именно пакет cwrap нельзя поставить вот так, сходу. Копаемся в помощнике и находим следующее: «в случае если пакет установлен, но по сути его нет, примените директиву --local». Пакет Шрёдингера. Вроде есть, но его нет. Ладно.
luarockt install --local wrap
И снова те же грабли. А вот это уже не смешно. Ставить всё это под sudo категорически не рекомендую. Ну вот зачем математическому пакету суперпользователь? Несколько шагов, которые помогают установить этот пакет из rockspec-файла. Проверьте пути LUA_PATH и LUA_CPATH и выполните следующие команды:
cd ~/torch
git clone https://github.com/torch/cwrap.git
cd cwrap
cmake .
cd ..
TORCH_LUA_VERSION=LUA52 ./install.sh
cd cwrap
luarocks make rocks/cwrap-scm-1.rockspec
luarocks install cutorch
luarocks install inn
luarocks install cunn
luarocks install cudnn
Обучаем нейросеть (если модели были скачаны — пропускайте этот шаг)
Справились. Пора приступать к обучению нейросети. Дальнейшие действия могут занять и несколько суток! Внимательно смотрите на те опции, с которыми запускаете тренировку и валидацию!
cd ~/deepmask
th train.lua --help
```bash
Смотрим, какие опции он нам предлагает по умолчанию. Описываю только те, которые можно менять или буду менять сам.
```bash
-nthreads # параметр очень интересный — количество потоков обработки.
#Максимальное значение равно количеству (!) ФИЗИЧЕСКИХ (!) процессоров,
#в случае с нашим инстансом амазона — 16
-batch # размер пачки для обработки. По умолчанию 32
-maxload # я оставил его как есть, поскольку мне нужно обучение на полной
#базе. По умолчанию 4000
-testmaxload # число пачек для валидации. Можно поиграть с параметром,
#но учитывайте, что это напрямую влияет на количество памяти, которое
#требуется; по умолчанию 500
-maxepoch # число эпох. По умолчанию 300 эпох. Это слишком много,
#далее станет ясно почему
Итак, приступим. Раз уж нам достался такой мощный инстанс, что же нам мешает загрузить по максимуму процессоры?
th train.lua -nthreads 16 -batch 500
Упс… А ведь Nvidia установила свои библиотеки и отмахивается от всяких vcc --version правильной инфой. Только вот библиотеки лежат в /home/ubuntu/cuda/lib64/libcudnn.so.5
. А это значит, что в самый конец файла .bashrc добавляем директиву:
export CUDNN_PATH="/home/ubuntu/cuda/lib64/libcudnn.so.5"
По идее, нас ждёт счастье, но нет. Мы снова можем наступить на грабли. Достаточно серьёзные.
В случае, если грабли найдены не были, то увидите текст, похожий на текст на скриншоте.
Либо одно из сообщений об ошибке. Сами ошибки и методы их решения подробно описаны под спойлерами.
th train.lua -nthreads 16 -batch 500
Found Environment variable CUDNN_PATH = /home/ubuntu/cuda/lib64/libcudnn.so.5-- ignore option dm
-- ignore option reload
-- ignore option datadir
nthreads 16 2
-- ignore option rundir
-- ignore option gpu
batch 500 32
| running in directory /home/ubuntu/deepmask/exps/deepmask/exp,batch=500,nthreads=16
| number of paramaters trunk: 15198016
| number of paramaters mask branch: 1608768
| number of paramaters score branch: 526337
| number of paramaters total: 17333121
convert: data//annotations/instances_train2014.json --> .t7 [please be patient]
convert: data//annotations/instances_train2014.json --> .t7 [please be patient]
convert: data//annotations/instances_train2014.json --> .t7 [please be patient]
convert: data//annotations/instances_train2014.json --> .t7 [please be patient]
convert: data//annotations/instances_train2014.json --> .t7 [please be patient]
/home/ubuntu/torch/install/bin/lua: ...e/ubuntu/torch/install/share/lua/5.2/threads/threads.lua:183: [thread 16 callback] /home/ubuntu/torch/install/share/lua/5.2/coco/CocoApi.lua:142: Expected value but found T_END at character 1
Если вас постигла такая замечательная ошибка, то нужно сделать просто серию замечательных шагов:
cd ~
rm -rf torch/
git clone https://github.com/torch/distro.git ~/torch --recursive
cd ~/torch;
bash install-deps;
TORCH_LUA_VERSION=LUA52 ./install.sh
git checkout 5961f52a65fe33efa675f71e5c19ad8de56e8dad
./clean.sh
bash install-reps
TORCH_LUA_VERSION-LUA52 ./install.sh
luarocks install cudnn
luarocks install cutorch # именно так! И не спрашивайте. Там ещё достаточно граблей
luarocks install cunn
luarocks install inn
luarocks install tds
luarocks install optim
luarocks install nnx
luarocks install image
cd ~/coco/
luarocks make LuaAPI/rocks/coco-scm-1.rockspec
Пересобрали. Доустановили. Запускаемся опять с теми же опциями и видим:
th train.lua -nthreads 16 -batch 500
-- ignore option rundir
-- ignore option dm
-- ignore option reload
-- ignore option gpu
-- ignore option datadir
nthreads 1 2
| running in directory /Users/ryan/mess/2016/34/deepmask/exps/deepmask/exp,nthreads=1
| number of paramaters trunk: 15198016
| number of paramaters mask branch: 1608768
| number of paramaters score branch: 526337
| number of paramaters total: 17333121
convert: data//annotations/instances_train2014.json --> .t7 [please be patient]
FATAL THREAD PANIC: (write) not enough memory
Поток в панике. Что делать? Тушить! Workaround на этот раз очень лайтовый. Даже не надо ничего пересобирать. Просто руками конвертируем аннотации тренировки и валидации. Ошибка чтения файлов лечится так же.
```bash
cd ~/deepmask/
th
coco = require 'coco'
coco.CocoApi("data/annotations/instances_train2014.json")
#Увидим строчки, которые ниже
#convert: data/annotations/instances_train2014.json --> .t7 [please be patient]
#converting: annotations
#converting: categories
#converting: images
#convert: building indices
#convert: complete [57.22 s]
#CocoApi
coco.CocoApi("data/annotations/instances_val2014.json")
#Увидим строчки, которые ниже
#convert: data/annotations/instances_val2014.json --> .t7 [please be patient]
#converting: annotations
#converting: categories
#converting: images
#convert: building indices
#convert: complete [26.07 s]
#CocoApi
Обучаем нейросеть
Вот теперь приготовления завершены. Все модели есть, сети есть, изображения для тренировки и валидации есть. Снова запускаем. Попробуем максимально нагрузить.
th train.lua -batch 500 -nthreads 16
Параллельно смотрим htop (не самая лучшая идея, поскольку он не покажет разделение потребляемой памяти по типу).
Мягко говоря, жарковато. Напоминаю: 16 физических процессоров, каждый по 8 ядер, с виртуализацией. И память. Неудивительно, что через несколько минут работы терминал выдал «Убито»!
Повторяем попытку, делаем условия "полегче":
th train.lua -maxepoch 2 -nthreads 4
Found Environment variable CUDNN_PATH = /home/ubuntu/cuda/lib64/libcudnn.so.5maxepoch 2 300
-- ignore option datadir
-- ignore option gpu
-- ignore option dm
nthreads 4 2
-- ignore option rundir
-- ignore option reload
| running in directory /home/ubuntu/deepmask/exps/deepmask/exp,maxepoch=2,nthreads=4
| number of paramaters trunk: 15198016
| number of paramaters mask branch: 1608768
| number of paramaters score branch: 526337
| number of paramaters total: 17333121
| start training
Ещё раз. Использованные 154 Гб памяти — это все банки RAM, часть свопа и часть виртуальной памяти. Останавливаем. Остановка через kill или Ctrl + C не критична вообще. При перезапуске обучения все старые модели затираются.
Даже на амазонской машине можно спокойно оставить скрипт работать и идти заниматься своими делами часа полтора-два.
Кстати, важная пометка: чтобы увидеть, что что-то получилось, результаты тренировки нейросети и т.д., при работе через ssh используйте screen. Внезапно пропала связь и прочее? Не беда. Переподключились к машине, ввели screen -r — и мы снова видим то, на чём вылетели.
Опция -nthreads 4
вымучена перезапусками и засеканием времени тренировки нейросети. Потому что при большей загрузке начинается конкуренция за оперативную память, а параметров у нас очень и очень много (в сумме 17 млн).
На обучающую выборку в 85К изображений. Кстати, каждый чётный шаг обучения скрипта проводит валидацию нейросети.
th train.lua -nthreads 16 -maxepoch 12
Found Environment variable CUDNN_PATH = /home/ubuntu/cuda/lib64/libcudnn.so.5-- ignore option reload
-- ignore option dm
maxepoch 12 300
-- ignore option gpu
nthreads 16 2
-- ignore option datadir
-- ignore option rundir
| running in directory /home/ubuntu/deepmask/exps/deepmask/exp,maxepoch=12,nthreads=16
| number of paramaters trunk: 15198016
| number of paramaters mask branch: 1608768
| number of paramaters score branch: 526337
| number of paramaters total: 17333121
| start training
[train] | epoch 00001 | s/batch 0.67 | loss: 0.31743
[train] | epoch 00002 | s/batch 0.67 | loss: 0.18296
[test] | epoch 00002 | IoU: mean 054.60 median 061.36 suc@.5 062.63 suc@.7 036.53 | acc 092.91 | bestmodel *
[train] | epoch 00003 | s/batch 0.67 | loss: 0.16256
[train] | epoch 00004 | s/batch 0.67 | loss: 0.15217
[test] | epoch 00004 | IoU: mean 059.10 median 065.86 suc@.5 068.97 suc@.7 043.31 | acc 093.93 | bestmodel *
[train] | epoch 00005 | s/batch 0.67 | loss: 0.14583
[train] | epoch 00006 | s/batch 0.67 | loss: 0.14183
[test] | epoch 00006 | IoU: mean 056.79 median 064.92 suc@.5 065.88 suc@.7 042.34 | acc 094.27 | bestmodel x
[train] | epoch 00007 | s/batch 0.67 | loss: 0.13739
[train] | epoch 00008 | s/batch 0.67 | loss: 0.13489
[test] | epoch 00008 | IoU: mean 059.53 median 067.17 suc@.5 069.44 suc@.7 045.33 | acc 094.69 | bestmodel *
[train] | epoch 00009 | s/batch 0.67 | loss: 0.13417
[train] | epoch 00010 | s/batch 0.67 | loss: 0.13290
[test] | epoch 00010 | IoU: mean 061.80 median 069.41 suc@.5 072.71 suc@.7 048.92 | acc 094.67 | bestmodel *
[train] | epoch 00011 | s/batch 0.67 | loss: 0.13070
[train] | epoch 00012 | s/batch 0.67 | loss: 0.12711
[test] | epoch 00012 | IoU: mean 060.16 median 067.43 suc@.5 070.71 suc@.7 046.34 | acc 094.85 | bestmodel x
Провели обучение и можно приступать к следующему этапу. На основе полученных DeepMask-моделей необходимо сгенерировать SharpMask.
th train.lua -dm ~/deepmask/exps/deepmask/exp,maxepoch=2,nthreads=4/
# необходимо точно указать путь, где лежат наши модели
Если была запущена тренировка с другими параметрами, то название папки с моделями будет иное. Но основной путь до неё тот же. Пока идёт обучение DeepMask или построение SharpMask, продолжим установку.
Ставим google-glog
С ним проблем не возникло, потому что он и правда простой и беспроблемный.
cd ~/
git clone https://github.com/google/glog.git
cd glog
./autogen.sh
./configure
make
sudo make install
Multipathnet, fbpython и целый ворох зависимостей
Теперь от нас всего-то требуется клонировать проект multipathnet, установить к нему зависимости и запустить распознавание. Кажется, я где-то уже слышал что всё «легко и просто».
cd ~/
git clone https://github.com/facebookresearch/multipathnet.git
luarocks install torchnet
luarocks install class
luarocks install fbpython
Не пытайтесь ставить fbpython через Conda или Anaconda и прочее. Как выражается Facebook в инструкции: note that this won't work with anaconda as it ships with it's own libraries which conflict with torch. Если перевести примерно и с долей юмора, то «это их собственная баржа, на ней свои заморочки и свой капитан».
Итак, кто-то опять умолчал о зависимостях.
...
-- Found Torch7 in /home/ubuntu/torch/install
-- REQUIRED_ARGS (missing: THPP_INCLUDE_DIR THPP_LIBRARIES)
-- Looking for pthread.h
...
Гуглим во все стороны, что это за переменные и почему их у нас до сих пор нет.
cd ~/
git clone https://github.com/facebook/folly.git
git clone https://github.com/facebook/fbthrift.git
git clone https://github.com/facebook/thpp
git clone https://github.com/facebookarchive/fblualib.git
# не пользуйтесь форком, форк не работает, клонируем из архива
Я считаю, это прекрасно. Ещё небольшой зоопарк. Ладно. Для тех, кто на Ubuntu:
sudo apt-get install zlib1g-dev binutils-dev libjemalloc-dev libssl-dev
sudo apt-get install libevent-dev
sudo apt-get install libsnappy-dev
sudo apt-get install libboost-all-dev libgoogle-glog-dev libgflags-dev liblz4-dev liblzma-dev libsnappy-dev
Linux:
cd ~/
git clone https://github.com/gflags/gflags.git
cd gflags
mkdir build && cd build
$ ccmake ..
- Press 'c' to configure the build system and 'e' to ignore warnings.
# Обязательно включаем SHARED_LIB
- Set CMAKE_INSTALL_PREFIX and other CMake variables and options.
# Жмём 'c' ещё раз
- Continue pressing 'c' until the option 'g' is available.
# Жмём 'g' и радуемся
- Then press 'g' to generate the configuration files for GNU Make.
cd ..
cmake -fpic -shared configure .
make
sudo make install
cd ~/
git clone https://github.com/google/glog.git
export LDFLAGS='-L/usr/local/lib'
cd glog
autoreconf -ivf
./configure
make
sudo make install
cd ~/
git clone https://github.com/google/double-conversion.git
cd double-conversion
cmake . -DBUILD_SHARED_LIBS=ON # не спрашивайте. ну не хавает
#здесь cmake по дефолту -fpic -shared
make
sudo make install
Теперь для всех:
wget https://github.com/google/googletest/archive/release-1.8.0.tar.gz &&
tar zxf release-1.8.0.tar.gz &&
rm -f release-1.8.0.tar.gz &&
cd googletest-release-1.8.0 &&
cmake configure . &&
make &&
sudo make install
cd ~/folly
cmake -fpic -shared configure ..
make (optionally -j$(proc))
sudo make install
Дальше всё идёт только для Ubuntu, посколько на RHEL было бессмысленно пытаться обновить всё окружение. На момент написания статьи дальше в RHEL продвинуться просто было невозможно, ограничение на максимальную версию пакетов для инстансов «Амазона» тому виной.
Пользователи Linux могут самостоятельно продолжить установку пакетов, но искать необходимые пакеты необходимо будет вам (ну а если в процессе наткнетесь на грабли — добро пожаловать в комментарии, с радостью помогу решить проблемы).
Ставим fbthrift
НИКОГДАне трогайте build_folly_fbthrift.sh. Иначе придётся откатиться к моменту, когда ничего нет, кроме тренировки модели.
sudo apt-get install flex bison
git clone https://github.com/no1msd/mstch.git
cd mstch
cmake .
make
sudo make install
cd ~/
git clone https://github.com/facebook/wangle.git
cd wangle/wangle
cmake .
make
sudo make install
cd ~/
git clone https://github.com/facebook/zstd.git
cd zstd
make
sudo make install
cd ~/
git clone https://github.com/krb5/krb5.git
cd krb5/src
autoreconf -ivf
./configure
make
sudo make install
cd ~/fbthrift/build
cmake -fpic -shared configure .
make
sudo make install
И теперь думаете, что счастье есть и можно устанавливать thpp. Как показала практика — нет. Упираетесь в тысячу косяков… Fbthrift! Для начала:
cd ~/fbthrift/thrift/compiler/py
sudo python setup.py install
Это установит недостающий thrift_compiler. Далее оказывается, что вообще отсутствует frontend.so. Забыли скомпилироть и положить в папку. Ну ладно (для справки: ниже строка генерации frontend.so для g++ ~v5.4).
cd ~/fbthrift/thrift/compiler/py
g++ -I /usr/include/python2.7 -I ~/fbthrift -std=c++1y -fpic -shared -o frontend.so compiler.cc -lboost_python -lpython2.7 -L/build/lib -lcompiler_base -lcompiler_ast -lboost_system -lboost_filesystem -lssl -lcrypto
sudo cp frontend.so /usr/local/lib/python2.7/dist-packages/thrift_py-0.9.0-py2.7.egg/thrift_compiler/
Если у вас чего-то не хватает, скомпилируйте сами. Такое ощущение, что дальше еще и дописывать придется за них код. И предчувствие не обмануло.
Если поймали ошибку вызова методов с неправильным количеством параметров
Вооот, теперь нас ждёт счастье. Ну почти. Добрые самаритяне из Facebook поменяли вызовы функций в torch7, но между делом забыли сделать правильный вызов в thpp. Как мило.
cd ~/thpp/thpp/detail/
nano TensorGeneric.h
Нужно поправить следующие вызовы (кэп подсказывает: после dim добавилась часть ", 0"):
static void _max(THTensor* values, THLongTensor* indices,
THTensor* t, int dim) {
return THTensor_(max)(values, indices, t, dim, 0);
}
static void _min(THTensor* values, THLongTensor* indices,
THTensor* t, int dim) {
return THTensor_(min)(values, indices, t, dim, 0);
}
static void _sum(THTensor* r, THTensor* t, int dim) {
return THTensor_(sum)(r, t, dim, 0);
}
static void _prod(THTensor* r, THTensor* t, int dim) {
return THTensor_(prod)(r, t, dim, 0);
}
Собираем пакет заново, но это ещё не всё...
cd ~/thpp/thpp
ccmake .
#Делаем опцию NO_TEST = ON, жмём 'c', потом 'g'
cmake .
make
sudo make install
Ставим fblualib
Теперь на очереди fblualib. С ним можно расправиться легко и просто. Повторюсь: ни в коем случае не пользуйтесь их скриптами, которые носят заманчивые имена install-all.sh. Накроются все ваши пляски, и придётся начинать почти с нуля.
sudo apt-get install
libedit-dev
libmatio-dev
libpython-dev
python-numpy
Поставим, вдруг упустили. Не мудрено с такой «простой» инструкцией от разработчиков. Проверили, что у нас есть numpy для ВСЕХ версий питона.
cd ~/fblualib/fblualib
cmake -fpic -shared configure .
make
sudo make install
И снова куча ошибок. А всё почему? Да потому, что кто-то не стал править вызовы функций и в rocks-пакетах. Значит, правим вызовы руками. Просто писали инструкцию для Lua версии ниже 5.2, а он уже у нас 5.2, и искать старую нужную версию нет смысла. Проще поправить вызов функций.
cd ~/fblualib/fblualib/python
luarocks make rockspec/*
Выдаст ошибку при компиляции типа «недоопределённый тип». Всё просто. В файле с ошибкой правим определение типа luaL_reg на luaL_Reg (ЗАЧЕМ меняли вызов, я не знаю!)
Файлов с ошибкой будет два. Правки должны быть сделаны на 191 и 341 строках в двух файлах, которые будут в сообщении об ошибке.
Исправили вызов — попробовали. Скомпилировалось? Можно радоваться.
В принципе, уже после данных манипуляций можно было бы просто из ~/fblualib/fblualib
ещё раз вызвать ./build.sh
, но это уже дело вкуса — руками надёжнее.
Продолжаем мучения:
cd ~/coco
luarocks make LuaAPI/rocks/coco-scm-1.rockspec
# на всякий случай обновим зависимости
sudo pip install Cython
cd PythonAPI
make
sudo make install
Запускаем построение SharpMask для обученной нейросети
По идее, мы уже достигли дна, в смысле — дошли до конца инструкции по установке. Осталась самая приятная часть. Кстати, как раз закончился процесс создания SharpMask.
th train.lua -dm exps/deepmask/exp,maxepoch=2,nthreads=4/ -maxepoch 2 -nthreads 4
Found Environment variable CUDNN_PATH = /home/ubuntu/cuda/lib64/libcudnn.so.5gSz 160 112
nthreads 4 2
-- ignore option gpu
-- ignore option reload
maxepoch 2 300
-- ignore option datadir
-- ignore option dm
hfreq 0 0.5
-- ignore option rundir
| running in directory /home/ubuntu/deepmask/exps/sharpmask/exp,gSz=160,hfreq=0,maxepoch=2,nthreads=4
| number of paramaters net h: 1090466
| number of paramaters net v: 1660050
| number of paramaters total: 2750516
| start training
[train] | epoch 00001 | s/batch 1.95 | loss: 0.16018
[train] | epoch 00002 | s/batch 1.95 | loss: 0.13267
[test] | epoch 00002 | IoU: mean 059.74 median 065.92 suc@.5 069.00 suc@.7 043.39 | bestmodel *
Вполне себе хорошие данные для дальнейшей работы с моделями. Не забывайте добавлять в LUA_PATH /home//?.lua и в .bashrc тоже. Исходя из опыта установки всего проекта и тренировки моделей, просто сделайте линки из multipathnet на deepmask/data и линки sharpmask/model.t7 и deepmask/model.t7 и не занимайтесь копированием файлов.
cd ~/deepmask
mkdir data && cd data
mkdir models && mkdir proposals
ln -s ~/deepmask/data ~/multipathnet/data
#deepMask и sharpMask — если были другие параметры обучения,
# то папки другие будут
ln -s ~/deepmask/exps/deepmask/exp,maxepoch=2,nthreads=4/model.t7 ~/deepmask/data/models/deepmask.t7
ln -s ~/deepmask/exps/sharpmask/exp,gSz=160,hfreq=0,maxepoch=2,nthreads=4/model.t7 ~/deepmask/data/models/sharpmask.t7
Если не запускается из-за ошибки в тестах
Из файла fbcoco.lua убираем следующие строки:
require 'testCoco.init'
require 'Tester_FRCNN'
Теперь точно не зависнет и не сегфолтнется.
Долгожданная проверка!
Пора запускать проверку!
th demo.lua -img data/test6.jpg
Found Environment variable CUDNN_PATH = /home/ubuntu/cuda/lib64/libcudnn.so.5nn.Sequential {
[input -> (1) -> (2) -> (3) -> (4) -> (5) -> (6) -> output]
(1): nn.ParallelTable {
input
|`-> (1): nn.Sequential {
| [input -> (1) -> (2) -> (3) -> output]
| (1): NoBackprop: nn.Sequential {
| [input -> (1) -> (2) -> (3) -> (4) -> (5) -> output]
| (1): nn.SpatialConvolution(3 -> 64, 7x7, 2,2, 3,3) without bias
| (2): inn.ConstAffine
| (3): nn.ReLU
| (4): nn.SpatialMaxPooling(3x3, 2,2, 1,1)
| (5): nn.Sequential {
| [input -> (1) -> (2) -> output]
| (1): nn.Sequential {
| [input -> (1) -> (2) -> (3) -> output]
| (1): nn.ConcatTable {
| input
| |`-> (1): nn.Sequential {
| | [input -> (1) -> (2) -> (3) -> (4) -> (5) -> output]
| | (1): nn.SpatialConvolution(64 -> 64, 3x3, 1,1, 1,1) without bias
| | (2): inn.ConstAffine
| | (3): nn.ReLU
| | (4): nn.SpatialConvolution(64 -> 64, 3x3, 1,1, 1,1) without bias
| | (5): inn.ConstAffine
| | }
| `-> (2): nn.Identity
| ... -> output
| }
| (2): nn.CAddTable
| (3): nn.ReLU
| }
| (2): nn.Sequential {
| [input -> (1) -> (2) -> (3) -> output]
| (1): nn.ConcatTable {
| input
| |`-> (1): nn.Sequential {
| | [input -> (1) -> (2) -> (3) -> (4) -> (5) -> output]
| | (1): nn.SpatialConvolution(64 -> 64, 3x3, 1,1, 1,1) without bias
| | (2): inn.ConstAffine
| | (3): nn.ReLU
| | (4): nn.SpatialConvolution(64 -> 64, 3x3, 1,1, 1,1) without bias
| | (5): inn.ConstAffine
| | }
| `-> (2): nn.Identity
| ... -> output
| }
| (2): nn.CAddTable
| (3): nn.ReLU
| }
| }
| }
| (2): nn.Sequential {
| [input -> (1) -> (2) -> output]
| (1): nn.Sequential {
| [input -> (1) -> (2) -> (3) -> output]
| (1): nn.ConcatTable {
| input
| |`-> (1): nn.Sequential {
| | [input -> (1) -> (2) -> (3) -> (4) -> (5) -> output]
| | (1): nn.SpatialConvolution(64 -> 128, 3x3, 2,2, 1,1) without bias
| | (2): inn.ConstAffine
| | (3): nn.ReLU
| | (4): nn.SpatialConvolution(128 -> 128, 3x3, 1,1, 1,1) without bias
| | (5): inn.ConstAffine
| | }
| `-> (2): nn.SpatialConvolution(64 -> 128, 1x1, 2,2) without bias
| ... -> output
| }
| (2): nn.CAddTable
| (3): nn.ReLU
| }
| (2): nn.Sequential {
| [input -> (1) -> (2) -> (3) -> output]
| (1): nn.ConcatTable {
| input
| |`-> (1): nn.Sequential {
| | [input -> (1) -> (2) -> (3) -> (4) -> (5) -> output]
| | (1): nn.SpatialConvolution(128 -> 128, 3x3, 1,1, 1,1) without bias
| | (2): inn.ConstAffine
| | (3): nn.ReLU
| | (4): nn.SpatialConvolution(128 -> 128, 3x3, 1,1, 1,1) without bias
| | (5): inn.ConstAffine
| | }
| `-> (2): nn.Identity
| ... -> output
| }
| (2): nn.CAddTable
| (3): nn.ReLU
| }
| }
| (3): nn.Sequential {
| [input -> (1) -> (2) -> output]
| (1): nn.Sequential {
| [input -> (1) -> (2) -> (3) -> output]
| (1): nn.ConcatTable {
| input
| |`-> (1): nn.Sequential {
| | [input -> (1) -> (2) -> (3) -> (4) -> (5) -> output]
| | (1): nn.SpatialConvolution(128 -> 256, 3x3, 2,2, 1,1) without bias
| | (2): inn.ConstAffine
| | (3): nn.ReLU
| | (4): nn.SpatialConvolution(256 -> 256, 3x3, 1,1, 1,1) without bias
| | (5): inn.ConstAffine
| | }
| `-> (2): nn.SpatialConvolution(128 -> 256, 1x1, 2,2) without bias
| ... -> output
| }
| (2): nn.CAddTable
| (3): nn.ReLU
| }
| (2): nn.Sequential {
| [input -> (1) -> (2) -> (3) -> output]
| (1): nn.ConcatTable {
| input
| |`-> (1): nn.Sequential {
| | [input -> (1) -> (2) -> (3) -> (4) -> (5) -> output]
| | (1): nn.SpatialConvolution(256 -> 256, 3x3, 1,1, 1,1) without bias
| | (2): inn.ConstAffine
| | (3): nn.ReLU
| | (4): nn.SpatialConvolution(256 -> 256, 3x3, 1,1, 1,1) without bias
| | (5): inn.ConstAffine
| | }
| `-> (2): nn.Identity
| ... -> output
| }
| (2): nn.CAddTable
| (3): nn.ReLU
| }
| }
| }
`-> (2): nn.Identity
... -> output
}
(2): inn.ROIPooling
(3): nn.Sequential {
[input -> (1) -> (2) -> (3) -> output]
(1): nn.Sequential {
[input -> (1) -> (2) -> output]
(1): nn.Sequential {
[input -> (1) -> (2) -> (3) -> output]
(1): nn.ConcatTable {
input
|`-> (1): nn.Sequential {
| [input -> (1) -> (2) -> (3) -> (4) -> (5) -> output]
| (1): nn.SpatialConvolution(256 -> 512, 3x3, 2,2, 1,1) without bias
| (2): inn.ConstAffine
| (3): nn.ReLU
| (4): nn.SpatialConvolution(512 -> 512, 3x3, 1,1, 1,1) without bias
| (5): inn.ConstAffine
| }
`-> (2): nn.SpatialConvolution(256 -> 512, 1x1, 2,2) without bias
... -> output
}
(2): nn.CAddTable
(3): nn.ReLU
}
(2): nn.Sequential {
[input -> (1) -> (2) -> (3) -> output]
(1): nn.ConcatTable {
input
|`-> (1): nn.Sequential {
| [input -> (1) -> (2) -> (3) -> (4) -> (5) -> output]
| (1): nn.SpatialConvolution(512 -> 512, 3x3, 1,1, 1,1) without bias
| (2): inn.ConstAffine
| (3): nn.ReLU
| (4): nn.SpatialConvolution(512 -> 512, 3x3, 1,1, 1,1) without bias
| (5): inn.ConstAffine
| }
`-> (2): nn.Identity
... -> output
}
(2): nn.CAddTable
(3): nn.ReLU
}
}
(2): nn.SpatialAveragePooling(7x7, 1,1)
(3): nn.View(512)
}
(4): nn.ConcatTable {
input
|`-> (1): nn.Linear(512 -> 81)
|`-> (2): nn.Linear(512 -> 81)
|`-> (3): nn.Linear(512 -> 81)
|`-> (4): nn.Linear(512 -> 81)
|`-> (5): nn.Linear(512 -> 81)
|`-> (6): nn.Linear(512 -> 81)
`-> (7): nn.Linear(512 -> 324)
... -> output
}
(5): nn.ModeSwitch {
input
|`-> (1): nn.ConcatTable {
| input
| |`-> (1): nn.SelectTable(4)
| `-> (2): nn.SelectTable(7)
| ... -> output
| }
`-> (2): nn.Sequential {
[input -> (1) -> (2) -> output]
(1): nn.ParallelTable {
input
|`-> (1): nn.Sequential {
| [input -> (1) -> (2) -> output]
| (1): nn.SoftMax
| (2): nn.View(1, -1, 81)
| }
|`-> (2): nn.Sequential {
| [input -> (1) -> (2) -> output]
| (1): nn.SoftMax
| (2): nn.View(1, -1, 81)
| }
|`-> (3): nn.Sequential {
| [input -> (1) -> (2) -> output]
| (1): nn.SoftMax
| (2): nn.View(1, -1, 81)
| }
|`-> (4): nn.Sequential {
| [input -> (1) -> (2) -> output]
| (1): nn.SoftMax
| (2): nn.View(1, -1, 81)
| }
|`-> (5): nn.Sequential {
| [input -> (1) -> (2) -> output]
| (1): nn.SoftMax
| (2): nn.View(1, -1, 81)
| }
|`-> (6): nn.Sequential {
| [input -> (1) -> (2) -> output]
| (1): nn.SoftMax
| (2): nn.View(1, -1, 81)
| }
`-> (7): nn.Identity
... -> output
}
(2): nn.ConcatTable {
input
|`-> (1): nn.Sequential {
| [input -> (1) -> (2) -> (3) -> output]
| (1): nn.NarrowTable
| (2): nn.JoinTable
| (3): nn.Mean
| }
`-> (2): nn.SelectTable(7)
... -> output
}
}
... -> output
}
(6): nn.ParallelTable {
input
|`-> (1): nn.Identity
`-> (2): nn.BBoxNorm
... -> output
}
}
{
1 :
{
1 : CudaTensor - size: 2x81
2 : CudaTensor - size: 2x324
}
}
{
1 :
{
1 : CudaTensor - size: 2x3x224x224
2 : CudaTensor - size: 2x5
}
}
{
1 : 0.17677669529664
2 : 0.25
3 : 0.35355339059327
4 : 0.5
5 : 0.70710678118655
6 : 1
7 : 1.4142135623731
}
0.66218614578247 17 dog
| done
Очевидно, на картинке собака! Пора подвести итоги.
Результаты бега по граблям
Вы сделали это! И стали на шаг ближе к просветлению. А если ещё и прошли по всем граблям (и даже нашли пару новых, в чём я совершенно не сомневаюсь), то, однозначно, можете зависать над землёй на высоте трёх ци и легко устанавливать все зависимости для проекта одним движением брови.
Задачка была не из лёгких, а информации в интернете было очень и очень мало, особенно по багам с несовместимостью версий.
Причина проста: весь проект по распознаванию образов был выпущен в тот момент, когда все компоненты и зависимости были рабочие и ставились прямо из репозиториев. Позже все пошли вразнос и никто не стал исправлять кривые связи, неточности языка, версионность, недостаток файлов и прочее. Но мы, как всегда, всё превозмогли и всех победили.
Вообще сам набор после нормальной сборки и приведения в рабочий вид оставил приятное впечатление, если бы не процесс приведения в чувство всей этой Санта-Барбары.
Все трудности преодолели, теперь можно немного поговорить о планах на будущее. А они у нас далекоидущие: в целях эксперимента перейти на CUDA 9.1, cuDNN 7, который обещает почти тройной прирост производительности для алгоритмов свёрточной нейронной сети и усовершенствованной свёрточной нейронной сети. Правда, это потянет за собой пересборку части пакетов (точнее, пересборку inn, cunn, cudnn, cutorch через LuaRocks и правку зависимостей).
Буду рад ответить на ваши вопросы, а если расскажете о собственных граблях, постараюсь разобраться и помочь!
Автор: Trevil