image

Пока TensorFlow активно завоевывает мир, воюет за аудиторию с такими крупными игроками рынка машинного обучения и глубоких нейронных сетей как Keras, Theano и Caffe, другие менее грандиозные проекты тем временем партизанят, пытаясь занять хоть какую-нибудь нишу. Про один из таких проектов я как раз и хотел сегодня рассказать ввиду полного отсутствия информации о нем на Хабрахабре. Итак, tiny-dnn — это полностью автономная C++11 реализация глубинного обучения, созданная для применения в условиях ограниченных вычислительных ресурсов, встроенных систем или IoT. Подробности под катом.

Что же предлагают нам разработчики


  1. Скорость даже без GPU. Достигается засчет TBB и векторизации SSE/AVX. 98.8 процентов точности на MNIST за 13 минут обучения
  2. Портируемость. Об этом далее
  3. Возможность импортировать модели Caffe. Но понадобится protobuf
  4. Предсказуемая производительность. Простая многопоточная модель + отсутствие GC (стоило ли им это писать, ведь библиотека для C++ программистов)

В целом, ничего революционного, но и упрекнуть особо не за что. Предлагается все делать на C++ и довольно прямолинейно. Есть возможность сохранения и загрузки модели в файл и из файла (опять же без зависимостей). Полный список см. в ссылке на GitHub.

Установка и сборка


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

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

Опыт использования в MS Visual Studio


После вызова «cmake .» сгенерируется *.sln файл для MS Visual Studio 2015 (Community Edition вполне подходит). В этом солюшене два проекта, собственно сама библиотека и тесты. ТУда можно просто добавить свой проект, а для начала использования библиотеки прописать:

#include "tiny_dnn/tiny_dnn.h"

но при этом следует не забыть добавить в «Include directories» каталог с tiny-dnn. Также в моем случае возникла проблема сборки, а именно:

error C4996: 'std::copy::_Unchecked_iterators::_Deprecate': Call to 'std::copy' with parameters that may be unsafe - this call relies on the caller to check that the passed values are correct. To disable this warning, use -D_SCL_SECURE_NO_WARNINGS. See documentation on how to use Visual C++ 'Checked Iterators'

для решения потребовалось добавить define _SCL_SECURE_NO_WARNINGS в параметрах проекта (C/C++ -> Preprocessor).

Пример использования


На странице можно найти примеры, но они про затертый до дыр MNIST, для него нужны данные, функции разбора (которые на самом деле встроеные в библиотеку) и т.д. Лично мне хотелось банального «Hello, world» в мире нейросетей — реализации xor. Гугление не дало быстрых результатов, что вылилось в желание сделать самому и поделиться в статье. Вот что получилось:


#include "tiny_dnn/tiny_dnn.h"

using namespace tiny_dnn;
using namespace tiny_dnn::activation;
network<sequential> construct_mlp() 
{
    //auto mynet = make_mlp<tan_h>({ 2, 8, 2 });
    auto mynet = make_mlp<relu>({ 2, 8, 2 });
    assert(mynet.in_data_size() == 2);
    assert(mynet.out_data_size() == 2);
    return mynet;
}

int main(int argc, char** argv)
{
    auto net = construct_mlp();

    std::vector<label_t> train_labels {0, 1, 1, 0};
    std::vector<vec_t> train_numbers{ {0, 0}, {0, 1}, {1, 0}, {1, 1} };

    adagrad optimizer; // use gradient_descent?
    net.train<mse>(optimizer, train_numbers, train_labels, 4, 1000); // batch size 4, 1000 epochs

    for (auto& tn : train_numbers)
    {
        auto res_label = net.predict_label(tn);
        auto res = net.predict(tn);
        std::cout << "In: (" << tn[0] << "," << tn[1] << ") Prediction: " << res_label << std::endl;
    }
    std::cin.get();
    return 0;
}

Первые впечатления


Они спорные. С одной стороны все очень просто и гарантированно везде заведется, с другой стороны на банальном XOR'е сеть как-то долго сходится, например за 100 эпох на выходе получаются правильные, но крайне неуверенные результаты вроде 0.15, за 1000 эпох что-то вроде 0.8. Кажется, аналогичная модель на tensorflow сходится быстрее, но это неточно :)

Далее, сам демо-проект собирается дольше, чем хотелось бы. Похоже, это из-за подхода с хидерами. Возможно в более крупном проекте даже заметно не будет, в маленьком проекте с одним C++ файлом очень даже. Кстати, возможно на помощь придется решение от MS с т.н. precompiled headers…

То, как в библиотеке предлагается использовать синтаксис и фичи C++11, как ни странно, порадовало — я не так много программирую на «голом» C++ (чаще Qt), но тестовый пример дался с первой попытки. Кстати замечания к нему приветствуются.

> Ссылка на GitHub
> Ссылка на полезную презентацию
Поделиться с друзьями
-->

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


  1. Randl
    13.01.2017 19:26
    +5

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


    1. erwins22
      13.01.2017 20:23

      Сделайте поддержку AMD GPU и к вам потянуться те кто на нем.
      TensofFlow — только NVIDIA/


      1. Randl
        13.01.2017 20:45

        У Tensorflow есть экспериментальная поддержка OpenCL (по крайней мере, когда я его последний раз компилировал, он меня спрашивал нужна ли поддержка OpenCL).
        У нас OpenCL в планах одновременно с CUDA.


    1. QtRoS
      13.01.2017 20:34

      О, какой удачный случай. Что-набудь скажете про пример с XOR, выглядит сносно? Имеет смысл в примеры библиотеки заливать?


      1. Randl
        13.01.2017 20:44

        На первый взгляд прилично. Думаю лучше открыть PR и там уже пример рассмотрят всесторонне.


  1. barkalov
    13.01.2017 19:49
    +1

    Небольшое уточнение по вступрительному параграфу:

    Пока TensorFlow активно завоевывает мир, воюет за аудиторию с такими крупными игроками рынка машинного обучения и глубоких нейронных сетей как Keras, Theano и Caffe
    TensorFlow не «воюет» с Keras, а является одним из его backend'ов (наряду с Theano). Другими словами, Keras работает на TensofFlow.


    1. QtRoS
      13.01.2017 20:57

      Это как посмотреть. Не уверен, что авторы TensorFlow будут рады тому, что на слуху будет Keras, а не TF, даже если первый работает поверх второго. Все же за популярность и применение в качестве стандарта де-факто по-моему борьба есть.


      1. BelBES
        14.01.2017 12:14

        Особенно в свете того, что Theano как бекенд Keras'а на данный момент надирает TF по скорости)


    1. QtRoS
      16.01.2017 22:23

      А, нет, будут :)
      Google chooses Keras


  1. Alert123
    13.01.2017 20:24

    А какие у этой библиотеки способы использования?
    Я вот ищу что нибудь чтобы для фиксированной базы из тысяч цветных иллюстраций очень быстро определять соответвие по изображению с камеры (или узнать что совпадений нет).
    Для этих целей подойдет?


    1. QtRoS
      13.01.2017 20:30

      Краткий ответ: да, при правильном использовании.
      Длинный ответ: эта библиотека лишь одна из многих. Для проверки Вашей гипотезы я бы лично порекомендовал воспользоваться более простыми фреймворками (притом не обязательно сразу используя глубинное обучение, зависит от данных), например sklearn. Если взлетит и Вы сами найдете для себя решение, то уже тогда только стоит начинать думать о том, как же внедрить решение в условиях ваших ограничений по ресурсам, железу, фреймворку, языку. Но для проведения такой проверки Вам понадобится «понять» данные, продумать их представление и т.д., вполне себе стандартная работа специалиста по ML. Вызвать одну функцию и получить профит как например с QR-кодами вряд ли получится.


  1. ErmIg
    14.01.2017 19:12
    +1

    Начал использовать tiny_dnn, когда он еще назывался tiny_ cnn. Повелся на простоту интеграции в проект. На редкость тормознутое творение. Стал разбираться в причинах — авторы так увлеклись распараллеливанием алгоритмов и асинхронным их исполнением, что дошли до маразма. Апофеозом было копирование 10 чисел, путем распараллеливания на 8 потоков! Естественно, что из-за потерь на синхронизацию производительность была ниже плинтуса. Убрал лишнее распараллеливание, добавил где надо SIMD оптимизации — вроде стало работать более менее быстро. Только по итогу от исходного проекта практически ничего не осталось. В итоге в конце концов свой велосипед написал. В последней версии они переписали очень многое — стало гораздо лучше в плане производительности, но все равно свой велосипед в разы опережает.


    1. Randl
      14.01.2017 23:19
      +1

      А почему бы не открыть PR или хотя бы issue по тормозящим моментам?


      1. ErmIg
        16.01.2017 09:05
        +1

        Тут есть ряд моментов. Сам мой велосипед Само мое решение находится в открытом доступе:

        https://github.com/ermig1979/Simd/blob/master/src/Simd/SimdNeural.hpp

        Стоит отметить, что решение менее универсально, чем оригинальный tiny_cnn и тем более tiny_dnn. Кроме того оно завязано на библиотеку Simd. А это противоречит основной концепции tiny_dnn — все в заголовочных файлах и желательно без сторонних зависимостей. Потому просто сделать pull request будет довольно затруднительно.

        Хотя я наверное был бы рад помочь.


    1. QtRoS
      14.01.2017 23:44

      Да, присоединюсь к Randl — если можете сделать мир библиотеку лучше, то почему бы не поделиться? Я уверен, что с Вами будут рады обсудить идеи.


  1. VioletGiraffe
    15.01.2017 00:04
    +3

    Интересно! Спасибо за статью. С такой простотой использования, ещё и на С++, мне захотелось всё-таки разобраться, как этими сетями польоваться на практике :)


    1. BelBES
      15.01.2017 00:26

      Caffe еще проще, и деплоить можно в C++ код.
      Правда за счет im2col, без напильника в embedded особо не влезешь.


      1. VioletGiraffe
        15.01.2017 00:34
        +1

        Embedded мне не интересно, только десктоп. Библиотека, которая просто подключается и работает без возни со сборкой и т. д. — это огромный плюс.


        1. BelBES
          15.01.2017 14:56

          Caffe собирается из CMake'а, т.ч. там никаких проблем нету (список зависимостей устанавливается одной командной apt-get install)...


          1. VioletGiraffe
            15.01.2017 15:12

            Windows :)


  1. Smorodov
    15.01.2017 23:24

    Ветка Caffe для виндоус есть: здесь.


  1. eiennohito
    20.01.2017 18:36

    Увы, не для текста. Рекуррентных сетей вообще нет (и похоже не предвидится).

    На текст специализируются похоже только https://github.com/clab/dynet да https://github.com/pfnet/chainer