Anatoly Levenchuk (ailev) wrote,
Anatoly Levenchuk
ailev

Платформизация глубокого обучения

Архитектура -- это набор важных инженерных решений. Важные инженерные решения -- это при изменении которых придётся перепроектировать бОльшую часть проекта. Если вы поменяли в самолёте винтик с одного на другой, то изменения коснутся только этого винтика -- это не архитектурное решение. Если вы поменяли двигатель с турбореактивного на реактивный, или решили делать фюзеляж и крылья из композитных материалов, то вам придётся перепроектировать почти всё -- это архитектурное решение.

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

Архитектуры глубокого обучения (deep learning architectures, см.раздел в https://en.wikipedia.org/wiki/Deep_learning) обычно определяются как решения по выбору конкретных алгоритмов и требуемых ими структур данных, лежащие в основе обучаемой нейронной сети (в принципе, не все эти архитектуры истинно "нейронные", но про разницу "нейронных" и "ненейронных" архитектур сейчас всё меньше вспоминают). Архитектуры эти -- convolutional neural networks, deep Boltzmann machines, stacked (denoising) auto-encoders, их уже довольно много. Это "архитектуры из учебника", их предлагает "наука" -- по сути, это описания алгоритмов и их структур данных.

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

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

Задача архитектора приложения -- это обеспечить его масштабируемость, расширяемость, переносимость и т.д., все эти "требования качества" (помним, что сегодня уже неправильно говорить "нефункциональные требования" -- требования качества вполне функциональны, только их функции требуются для обеспечивающей системы, а не для использующей).

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

В принципе, сама инфраструктурная платформа тоже может быть построена на основе ещё более инфраструктурной платформы, и так во много слоёв (хотя там чаще не столько слои, сколько какой-то направленный граф использования). Каждый слой имеет интерфейс (API -- application program interface), видимый/используемый из более прикладного слоя и задействует системный интерфейс более инфраструктурного слоя (системный интерфейс он с точки зрения этого "каждого слоя", для более инфраструктурного слоя он как раз и есть API, этот "каждый слой" для него -- прикладной).

Два основных варианта предоставления платформ:
-- полный стек (full stack), когда предприятие имеет все платформы у себя -- от аппаратных платформ до всех слоёв софта
-- без стека (no stack, http://www.slideshare.net/AlbertWenger/the-no-stackstartup), когда платформа предлагается как сервис. Это важный тренд, и каждый поставщик платформы глубокого обучения стремится предоставить платформу-как-сервис вместо предоставления её как модуля в составе стека. Так, буквально только что Nervana Systems, поставщик самого быстрого на рынке софта глубокого обучения Neon (https://github.com/NervanaSystems/neon) взял $24млн. инвестиций на создание облачного сервиса глубокого обучения (http://openmarkets.cmegroup.com/10236/deep-learning-is-the-future-qa-with-naveen-rao-of-nervana-systems). Платформы-как-сервис для глубокого обучения более или менее прикладного уровня предоставляют и IBM, и Microsoft, и многие другие крупные и мелкие фирмы.

Но большинство участников рынка до сих пор ориентируется на решения полного стека, в том числе сами поставщики платформ-как-сервиса. Ставим компьютер с GPU, устанавливаем на него язык, разворачиваем десяток библиотек и фреймворков -- и работаем, разрабатываем, настраиваем, тренируем, прогоняем! Пока не нужно масштабироваться и торговать этой работой и её результатами, вопросов не возникает. Входной барьер низок: навороченный и расширяемый компьютер с GPU GTX Titan X обойдётся сегодня в сумму порядка 250тыс.рублей. Добавляйте дальше ускорители по примерно 70тыс.руб за штуку, получите совсем уже монстра. Софт бесплатный, ставь да работай.

И всё одно рынок требует всё большей и большей модульности, более и более мелкого дробления платформ, тренд "микросервисов" ведь появился совсем не случайно. "Микроплатформы" пока не говорят, но такой термин тоже вполне может появиться. А ещё платформа может быть довольно тонкой: небольшая надстройка над какой-то более базовой платформой.

Что является просто архитектурным слоём модульного софта, а что -- платформой? Неформально платформой является слой модулей с опубликованным к ним интерфейсом, которым смогут воспользоваться сторонние разработчики следующего, более прикладного слоя.

Как выглядит архитектура системы, использующей глубокое обучение, если рассмотреть её как некоторый стек платформ? Для простоты опустим пока ориентацию на бесстековость, но запомним, что эта ориентация много на что влияет: пока вы балуетесь с малыми объемами счёта и ваши машины постоянно загружены, у вас всё ОК. Как только выяснится, что объемы счёта огромны, а загрузка неравномерна, иметь застрявший в аппаратуре и тщательно развёрнутом на ней софте капитал может оказаться накладно -- и чисто экономические соображения заставят вас изменить архитектурные решения.

Архитектура DNN (deep neural network) обычно понимается как описание числа и типа слоёв и разных других гиперпараметров (параметров, которые не "выучиваются", а задаются сетьмастером/коннективистом "вручную"). Но сама настроенная сетка с заданными параметрами обычно -- не платформа, это часть архитектуры какого-то приложения, стандарт обращения к ней не публикуется (если, опять же, вы не торгуете именно этой сеткой -- и тогда публикуете её специфический API и она имеет шанс стать платформой).

В любом случае, сама глубокая нейронная сеть -- это только один из архитектурных слоёв пользовательского приложения, которое строится в свою очередь на платформах самого разного уровня. Помним, что все эти "слои" -- условность, и модули вышестоящих уровней очень любят для пущей эффективности обращаться к модулям нижележащих уровней, игнорируя правило "вассал моего вассала -- не мой вассал", чем вся идея "платформенной модульности" подрывается, зато эффективность растёт. Там компромисс на компромиссе. Вот например, NVIDIA привязывает сетьмастеров/коннективистов к своим GPU, предлагая им сразу удобный пользовательский интерфейс, скрывающий внутреннюю организацию архитектурного стека для глубокого обучения: https://developer.nvidia.com/digits

Но если вам нужно иметь полный контроль над вашей нейронной сеткой, если вы хотите достичь конкурентных преимуществ за счёт нестандартных решений именно в глубоком обучении, вам нужно собрать свой стек технологий -- свой набор типовых платформ и уникальных архитектурных слоёв, реализованных с использованием типовых платформ. Вот что там обычно бывает:

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

Сегодня используется:
-- FPGA, и никакого особого интерфейса железа к нему нет. Полная свобода оптимизации, но и невозможность накопления усилий и распределения труда. Так что пока это процветает в рамках крупных корпораций, типа как в датацентрах Microsoft, в которых поиск Bing оптимизировали при помощи нейросети на FPGA: http://geektimes.ru/post/246512/. Исследования идут полным ходом: http://cadlab.cs.ucla.edu/~cong/slides/fpga2015_chen.pdf, http://arxiv.org/abs/1507.05695, http://arxiv.org/abs/1508.01008
-- OpenCL железо (https://en.wikipedia.org/wiki/OpenCL) -- все GPU это поддерживают, но сам стандарт в глубоком обучении используется не так часто
-- CUDA железо от NVIDIA -- основной вариант для сегодняшних нейронных сетей
-- многоядерные CPU (в том числе и "истинные суперкомпьютерные архитектуры", архитектуры мейнфреймов и т.д. -- всё то, что не использует GPU). Крайне редко, например там процессоры типа Intel Knight Landing Xeon Phi с более чем 60 ядрами -- http://www.zdnet.com/article/intels-next-big-thing-knights-landing/.

2. библиотека нейросетевых примитивов для железа. Их API сейчас "стандарты де факто", поддерживаемые главным образом производителями железа.
-- можно выделить cuDNN, построенную над CUDA железом NVIDIA (https://developer.nvidia.com/cudnn). Для cuDNN уже почти вышла (уже доступен релиз-кандидат) третья версия, и реализация примитивов нейронной сети в ней стала вдвое быстрее плюс стало возможно загружать в память вдвое бОльшие модели за счёт использования очень коротких плавающих 16 бит (в нейронных сетях не требуется большой разрядности -- http://petewarden.com/2015/05/23/why-are-eight-bits-enough-for-deep-neural-networks/) -- а это всё равно, что вдвое увеличить скорость и вдвое увеличить память купленного раньше для расчётов глубоких нейронных сетей железа на базе чипов NVIDIA Maxwell и Kepler: https://developer.nvidia.com/cudnn
-- есть немножко реализаций для OpenCL, но массово это сегодня не используется, ибо NVIDIA плотно держит рынок и поддерживает OpenCL по понятным соображениям не так хорошо, как CUDA.

3. Реализация хост-языка программирования. Стандарт тут -- стандарт самого языка, но помним, что каждая IDE и каждый компилятор могут отличаться. Так, тот же Python как стандарт языка и одна из реализаций бывает также в реализации PyPy (http://pypy.org/) или Cython (http://cython.org/). У Lua как языка (стандарта языка) тоже несколько реализаций.

Cегодняшние реализации языков программирования архитектуры сети (они же -- фреймворки, они же библиотеки глубокого обучения) делаются как embedded DSL, обычно даже без своего особого синтаксиса, в рамках какого-то хост-языка программирования общего назначения. А поскольку нам нужно задать (запрограммировать!) архитектуру глубокой нейронной сети -- то есть описать число её слоёв, типы используемых ячеек, связи между слоями и т.д., то для этих целей нам потребуется как embedded DSL, так и хост-язык общего назначения.

На сегодня (кроме традиционного использования библиотек на C/C++ и множества более-менее экзотических реализаций библиотек глубокого обучения) есть два основных таких расширяемых хост-языка: Python и Lua. Я думаю, что скоро на эту арену выйдет и Julia (http://julialang.org/), в которой есть два базовых механизма расширения: метапрограммирование (по мотивам лиспа) и multiple dispatch, который обеспечивает независимое добавление операций и данных с сохранением контроля типов.

В принципе, сюда же -- к хост-языку -- я отношу и библиотеки научных вычислений: работа с матрицами, построение графиков, символьные вычисления, использование для этих операций GPU. Для Питона как хост-языка это NumPy, Theano (https://github.com/Theano/Theano) и ряд других библиотек. Для Lua это Torch, хотя его и считают больше фреймворком для глубокого обучения, но его можно рассматривать и как библиотеку научных расчётов для Lua -- он так сам себя и характеризует, http://torch.ch/.

4. Ключевой слой -- это собственно библиотека или фреймворк глубокого обучения. API (по факту это язык программирования архитектуры сети, embedded DSL -- встроенный в хост-язык предметно-специфический язык, часто даже без своего собственного синтаксиса) тут обычно публикуется, но пока обычно он ни разу не стандарт.

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

Реализация языка программирования архитектуры сети -- это и есть "нейросетевой фреймворк", сама библиотека программ. Она по понятным соображениям весьма специфична для хост-языка (например, Torch для Lua -- http://torch.ch/, различные библиотеки с использованием Theano для Питона -- https://github.com/Theano/Theano/wiki/Related-projects, Caffe для целого ряда языков http://caffe.berkeleyvision.org/, Mocha в Julia, которая по факту повторяет Caffe -- https://github.com/pluskid/Mocha.jl).

Грубо тут всё делится на три класса:
-- описание какого-то одного класса сеток (например, библиотеки глубокого обучения, построенные над Theano -- на них всех чохом обычно и ссылаются, когда говорят о Theano как фреймворке глубокого обучения).
-- универсальный просьюмерский фреймворк для создания самых разных типовых сеток "под ключ" с минимальным программированием (тот же Caffee и Mocha). В принципе, к такого сорта "просьюмерским" пакетам относят и Theano со всеми его библиотеками.
-- универсальный профессиональный фреймворк для создания нетиповых сеток и экспериментов в области нейросетевых глубоких архитектур -- пока в этой категории лидирует Torch, и совсем не случайно лидеры в глубоком обучении договорились о его совместном развитии и поддержке (http://torch.ch/whoweare.html).

Как всегда, в жизни нет счастья: желаемые хост-языки и языки программирования сети обычно не совпадают -- а всякие "обвязки" и "интерфейсы" вызовы одного языка из другого не слишком удобны в использовании. Так что если вы хотите использовать что-то типа Torch из хост-языка Julia, то вам нужно бы сначала разработать какой-нибудь фреймворк JuliaNN с аналогичным набором функций, добиться от него тех же точности и производительности, как от Torch и только потом уже наслаждаться глубокими сетками из Julia. Ну, или использовать уже имеющийся фреймворк Mocha, в котором пока не реализованы даже RNN, а есть только CNN.

5. Модель нейронной сети -- model zoo framework
Стандартом API тут мог бы быть формат, в котором распространяются модели и данные к ним (см., например, попытку спецификации такого стандарта для Caffe Model Zoo -- http://caffe.berkeleyvision.org/model_zoo.html). Хорошо, если такой формат для модели нейронной сети оговаривается -- этот уровень часто не выделяется специально.

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

В какой-то мере можно было бы говорить, что это и есть "модель предметной области, отражённая в нейронной сети", но я бы считал, что тут будет расщепление на два слоя:
5a. универсальная модель нейронной сети, "нейросетевой солвер" с минимальными настройками, "глубоконейросетевой движок"
5b. модель доступа к данным предметной области (модель данных и процедуры чтения-записи в формат для нейросетевого солвера/"глубоконейросетевого движка")

Но пока этот слой совсем, совсем не платформа -- он весьма специфичен, его интерфейсы в большинстве случаев совсем не публичны.

6. Собственно приложение, задействующее движок глубокого обучения.

Всякие утилиты и различия архитектуры обучения сети и архитектуры использования обученной сетки я пока не рассматриваю. И так уже многабукофф.

Итого: стек платформ глубокого обучения только-только появляется, платформизация идёт полным ходом. Сегодня буквально каждую неделю предлагаются новые архитектуры глубокого обучения, на рынок выходят всё новые и новые игроки, так что мы ещё много чего нового и интересного увидим в ближайшее время и в хост-языках для научных вычислений, и в платформах глубокого обучения для полного стека, и в платформах-как-сервисах для предприятий, предпочитающих не держать собственный стек.
  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your reply will be screened

  • 14 comments