Искусственный интеллект, вызовы и риски – глазами инженера

в 10:26, , рубрики: big data, BigData, Алгоритмы, Блог компании 1С-Битрикс, машинное обучение, нейронные сети, разработка

Добрый день, коллеги. Сегодня хочется трезво посмотреть глазами инженера на так популярные сейчас искусственный интеллект и Deep learning, упорядочить, выстроить факты и выработать выигрышную стратегию – как с этим … взлететь, пролететь и не упасть кому-нибудь на голову? Потому-что, когда дело от лабораторных моделей на python/matplotlib/numpy или lua доходит до высоконагруженного production в клиентском сервисе, когда ошибка в исходных данных сводит на нет все усилия – становится не то, что весело, а даже начинается нумерологический средневековый экстаз и инженеры начинают сутки напролет танцевать, в надежде излечиться от новомодной чумы )

Искусственный интеллект, вызовы и риски – глазами инженера - 1
Танцующие инженеры, тщетно надеющиеся исцелиться

Современная разработка

Полезно для начала вспомнить, как в принципе устроена современная разработка программного обеспечения. За основу, как правило, берутся классические, хорошо изученные в «прошлом веке» алгоритмы: поиск, сортировка и т.д и т.п. Любимые всеми СУБД – хороший пример бородатых, тщательно проверенных и изученных классических алгоритмов (да простят нас Кодд и Дейт за такую попсу).

К алгоритмам добавляются согласованные сообществом инженеров (хотя нередко ни с кем не согласованные, продвинутые злой силой) – стандарты: сеть (DNS, TCP/IP), форматы файлов, сервисы операционной системы (POSIX) и т.п.

Ну и, конечно, языки. В последние годы, к сожалению, в этой области началась какая-то унылая ерундистика: добавляют-убирают автоматические геттеры и сеттеры и автоматически вводят-выводят типы (как будто это прямо так важно важно), размазывают идеи функционального программирования из «Алисы в Стране чудес» и Haskel на Scala, пытаются частично скрыть дыры С++ в Rust, создают C для гуманитариев в виде Go, в очередной раз придумывают javascript «с нуля» (ECMAScript 6) и всем сердцем продолжают верить в красоту модели акторов и забивают совершенно разные гвозди с помощью Erlang. Вся эта движуха, не без основания, подогревается идеей будущего многопоточного программирования на многоядерных процессорах и GPU, возможно в кластерах, с помощью акторов, immutable-данных, функционального ЗОЖ и неявных извращений в виде currying и рекурсивного построения бинарного дерева. Но, очевидно, близкого прорыва пока ну совсем не видно – логика столкнулась с физикой и все стало упираться в ограничение человеческого мозга, тупость компиляторов в решении более-менее интересных задач и способность людей, ну извините, ошибаться и без злого умысла плодить тонны багов. И все с новой силой звучит высказывание Эдсгера Дейкстры, что серьезное программирование – для умных, как не крути и никакие чудо-юдо технологии тут не помогут. Хотя может и правда нам помогут футуристичные квантовые компьютеры, ну надо же во что-то верить?

В общем, чтобы с языками не запутаться и код не закровоточил багами, есть известное средство – писать … «правильно». Но чтобы понять значение «правильно», нужно прочитать много книг, перелопатить сотни тысяч строк кода в режиме «завтра в 10:00 должно работать и радовать клиентов» и выпить немало чашек крепкого кофе и разбить немало клавиатур о головы коллег. Но это правило – работает. Всегда.

Искусственный интеллект, вызовы и риски – глазами инженера - 2
Мир глазами инженера

Что касается библиотек, то никто, разумеется, не пишет сейчас все с «нуля». Это глупо и дорого. Но, используя «чужие» библиотеки всегда остается риск, что их писали немного «неправильно», а повлиять на это в данный момент почти никак нельзя, а сверху еще и маслица подливают: «бери готовое, вот они взяли и у них работает». Так все, конечно, и делают и используют Linux (операционка, но, по сути, такая же «библиотека» доступа к «железу»), nginx, apache, mysql, php, стандартные библиотеки коллекций (java, c++ STL). Библиотеки, к сожалению, сильно отличаются друг от друга, как по скорости, так и по степени документированности и числу «неисправленных ошибок» — поэтому успеха достигают команды, обладающие определенным чутьем и отличающие надежные «крысиные шкурки» от хорошо пропиаренных, но мало полезных, непрозрачных и/или неадекватных при чуть нестандартной нагрузке решений.

Таким образом, теоретически и, приложив определенные усилия, практически можно создать адекватное программное обеспечение в сжатые сроки с сильно ограниченными ресурсами, используя математически проверенные алгоритмы и библиотеки достаточной, но не критичной степени испорченности, на доказавшем свою «нормальность» языке/ах программирования. Примеров успеха – не то, чтобы много много, но они есть ;-)

Искусственный интеллект, вызовы и риски – глазами инженера - 3
Примеров успехов – не то, чтобы много много, но они есть

Машинное обучение

В этой области, в основном, речь идет об обучаемых алгоритмах. Когда бизнес, скажем, накопил некую «бигдату» и хочет ее монетизировать и вытащить полезный, помогающий клиентам и/или повышающий производительность труда алгоритм. Аналитически в лоб задачу эту бывает крайне сложно или невозможно решить, требуются эксперто-годы, учет множества факторов, вызов Ктулху – и, кажется, что можно поступить проще и «наглее»: протащить глубокую нейронную сеть «мордой» по данным и тыкать ее в них то тех пор, пока ошибка станет ниже определенного уровня (помним, что обычно проверяют два типа ошибок – ошибка обучения и ошибка генерализации на тестовом наборе данных). Ходит поверье, что при наличии миллиона и более примеров – глубокая нейронка способна начать работать на уровне не хуже человека, а если примеров больше – есть надежда научить ее превосходить человека. А если примеров меньше – нейронка тоже может приносить свою посильную пользу, помогая, но не заменяя человека.

Искусственный интеллект, вызовы и риски – глазами инженера - 4
Полезная нейронка внутри R2D2

Звучит красиво и практично – вот есть данные, «большие данные»: фас, нейронка, учись и помогай человечеству. Но, как известно, дьявол скрывается в мелочах.

Порог входа в разработку и машинное обучение/Deep learning

Ни для кого не секрет, что технологии разработки делятся на категории по уровню вхождения. В самых простых и доступных технологиях людей всегда значительно больше, часто с совсем непрофильным образованием и в такой обстановке нередко создается много неправильных, недолго живущих и воюющих друг с другом библиотек – в эту нишу хорошо ложиться JavaScript и Node.js. Понятно, что если копать вглубь, то появляется множество неочевидных деталей, появляются настоящие Гуру с большой буквы – но войти в эту область в шортах и сачком для бабочек за выходные вполне реально.

Искусственный интеллект, вызовы и риски – глазами инженера - 5
Юные фронт-энд разработчики на JavaScript. Но чтобы стать мегагуру, придется долго учиться, лета точно не хватит.

В «среднюю» по уровню вхождения категорию можно отнести динамические языки программирования типа: PHP, Python, Ruby, Lua. Тут все уже намного сложнее – более развитые концепции ООП, частично реализованные возможности функционального программирования, иногда доступна примитивная многопоточность, более выражена модульность и средства создания больших программ, доступны системные функции, частично реализованы стандартные типы данных и алгоритмы. За недельку, без напряжения, разобраться и начать создавать полезный код – вполне реально, даже без профильного образования.

Искусственный интеллект, вызовы и риски – глазами инженера - 6
Динамические слаботипизированные скриптовые языки имеют небольшой порог входа. За лето можно научиться и костер разжигать, и рыбку ловить

В «высшую» по уровню вхождения категорию обычно относят хорошо зарекомендовавшие себя промышленные языки типа C++, Java, C# и уже вроде бы начавшие наступать им на пятки Scala, bash и VisualBasic (последние два — шутка). Тут уже мы встретим очень развитые промышленные инструменты управления сложностью, качественные библиотеки типовых структур данных и алгоритмов, мощные возможности по созданию доменных диалектов, огромное количество качественной документации, дополнительные развитые библиотеки для отладки, профилирования и великолепные визуальные среды разработки. Войти и работать в этой категории проще всего, имея профильное образование или большую любовь к программированию и несколько лет месяцев интенсивного опыта и хорошее знание алгоритмов и структур данных – т.к. работа ведется нередко на довольно низком уровне и знания тонкостей операционной системы, сетевых протоколов – часто тут важны.

Искусственный интеллект, вызовы и риски – глазами инженера - 7
Промышленные языки программирования требуют изнурительной подготовки и нередко не прощают ошибок

Таким образом, в принципе, начинающего разработчика от полезного инженера отделяет несколько месяцев тяжелого изнурительного труда или годы эмоционального тусения в программных проектах и вытирания доски после мозговых штурмов.

А вот с машинным обучением немного… иначе. Аналитиками часто просто рождаются. Процесс обучения напоминает изучение игры на музыкальном инструменте – 2-3 года сольфеджио, 2-3 года гаммы гонять до посинения, 3 года в оркестре, 5 лет резать трупы в морге и тонны пота. Научить человека азам математики и статистики, математическому анализу, линейной алгебре, дифференциальному исчислению, теории вероятностей – за месяцы просто невозможно, нужны годы и … и не все потянут и пройдут на следующий курс. Многие сойдут с дистанции на другие кафедры. Быть ученым – не для всех, как бы не хотелось.

Искусственный интеллект, вызовы и риски – глазами инженера - 8
Стажировка аналитиков

А может, пронесет? Все в это верят по началу: за выходные разберусь! Но к сожалению, для того, чтобы понять, как работает самая элементарная в машинном обучении «логистическая регрессия», являющаяся своего рода «hello world» в программировании, требуется хорошо понимать как минимум пару разделов высшей математики: теорию вероятности и линейную алгебру. А для понимания логики «стохастического градиентного спуска» нужно также знать хотя бы в базовом виде дифференциальное исчисление.

Сырые полу-лабораторные фреймворки

Драйва добавляет высокая влажность. Имеющиеся на рынке популярные фреймворки для Deep learning – сырые до такой степени, что утром на клавиатуре появляется самая настоящая плесень.

Искусственный интеллект, вызовы и риски – глазами инженера - 9
Популярные фреймворки для машинного обучения. Они не пропали, они просто еще очень сырые

Понятно почему. Парад «универсальных» фреймворков начался лишь в прошлом, 2015 году. Deep learning уверенно пошел вверх в третий раз только в 2006 году, после многих десятилетий неуверенности и застоя. GPU совсем недавно внезапно оказались в нужное время в нужном месте.

К сожалению, TensorFlow совсем еще медленный и странноватый в production, Torch7 страдает отсутствием нормальной документации и языком Lua, deeplearning4j пытается понравится GPU, а кандидаты типа Theano на python непонятно как эффективно эксплуатировать в production без тяжелых наркотиков. Да, ходят легенды, что обучение нейронной сети это одно, а ее эксплуатация это сооовсем другое и этим должны заниматься совсем другие люди и технологии – но реальность считает деньги и это, согласитесь, страшно неудобно, дорого и не очень разумно. Наиболее универсальным и нацеленным на решение конкретных бизнес задач в сжатые сроки на «нормальном» промышленном языке является похоже пока только deeplearning4j – но от тоже находится в фазе активного роста и созревания со всеми вытекающими.

Как выбрать архитектуру нейронной сети для решения бизнес-задачи?

Читать научные публикации на птичьем диалекте с откровенным матаном без мата могут единицы, поэтому для большинства инженеров скорее всего наиболее прикладной и полезный способ изучения возможностей архитектуры – это копание в исходниках фреймворков, в большинстве случаем на “проклятом” студенческом python и изучение многочисленных примерчиков, которых в разных фреймворках становится все больше и больше и это не может не радовать.

Поэтому общий рецепт – выберите наиболее походящую решаемой задаче архитектуру в виде примера в коде, реализуйте ее 1 в 1 в удобном для эксплуатации фреймворке, закажите молебен и может вам повезет! Что значит «может повезет»? А все очень просто. Вы столкнетесь со следующим спектром инженерных рисков:

Искусственный интеллект, вызовы и риски – глазами инженера - 10
Аналитик, ведущий разработчик и руководитель проекта готовятся к молебну «О сведении нейронки». Говорят, скоро докажут теорему о влиянии молебнов на поведение градиентного спуска в условиях многочисленных плато, седловин и локальных минимумов

1) Архитектура нейронки хорошо работает с данными исследователя, но с вашими данными может работать совсем «иначе» или работать совсем наоборот.
2) В вашем фреймворке может не оказаться всего спектра элементарных кубиков: автоматического дифференцирования, алгоритма обновления с тонкой подстройкой (updater), расширенных средств регуляризации (dropout и других), нужной функции ошибки (loss), определенной операции над данными (векторное произведение) и т.п. Вы можете заменить их аналогами, но это привнесет риски.
3) Иногда, правда редко, хочется потянуть в production Matlab или R ;-) Тут один совет – сразу к врачу.
4) Скорее всего, вам потребуется подстроить нейронную сеть под дополнительные бизнес-требования, которые появились позже и совершенно не укладываются в идеальный мир математики. Например – значительно снизить уровень ложно-позитивных срабатываний, увеличить Recall, понизить время обучения, адаптировать модель к гораздо большему набору данных, добавить и учитывать новую информацию. И тут, как правило, понадобиться очень глубоко вникать в архитектуру нейронки и крутить скрытые винтики – а крутить на удачу, это путь к срыву сроков релиза и ночным кошмарам. И без профессора можно просидеть с отверткой с растерянным выражением лица и месяц и два и полгода.

Искусственный интеллект, вызовы и риски – глазами инженера - 11
Что же делать, что крутить? Разработчик на C++ пытается понять отличие softmax от softsign

Здравствуйте тензоры!

Для инженера тензор – это просто многомерный массив, позволяющий совершать над собой различные операции и жертвоприношения. Но к работе с тензорами – нужно привыкать ;-) Первые недели даже от трехмерных тензоров голова побаливает, не говоря уже о гораздо более «глубоких» тензорах для рекуррентных и сверточных сетей. Можно убить кучу времени на эти низкоуровневые манипуляции, отладку циферок в тензорах и поиск ошибок в одном значении из 40 000. Обязательно учитывайте этот риск – тензоры только кажутся простыми.

Искусственный интеллект, вызовы и риски – глазами инженера - 12
Будьте осторожны! Попытки представить структуру 4 и более мерных тензоров приводит к агрессивному косоглазию

Особенности работы с GPU

Может быть в начале неочевидно, но обычно быстрее обучать нейронку и получать ее ответы тогда, когда все необходимые данные (тензоры) загружены в память GPU. А память этих драгоценных и так обожаемых геймерами устройств – ограничена и обычно гораздо меньше памяти сервера. Приходится городить костыли – вводить промежуточное кэширование тензоров в ОЗУ, частичную генерацию тензоров во время прохождения по набору данных (ибо все могут и не поместиться) и так далее. Поэтому – учитываем и этот немаловажный инженерный риск, влияющий на трудоемкость. Сроки можно смело умножать на 3.

Искусственный интеллект, вызовы и риски – глазами инженера - 13
Видеокарта. На ней, оказывается, можно не только играть!

Нейронная сеть в production

Допустим, вам сильно «повезло», вы хорошенько потрудились и довели лабораторный прототип до production качества, подняли веб-сервер, загружаете обученную нейронку в память сервера или сразу в память GPU и адекватно быстро отдаете ответ. Но … данные меняются и за ними нужно менять/дообучать модель. Вам необходимо постоянно следить за качеством работы нейронки, измерять ее точность и ряд других параметров, зависящих от конкретной бизнес-задачи и тщательно продумать процедуру ее обновления и до/переучивания. Поверьте, мороки тут значительно больше, чем с классической СУБД, которую нужно лишь раз в 5 лет оптимизировать и раз в 10 лет убирать паутину с материнской платы :-)

А еще ходят легенды, что нейронную сеть можно просто … дообучить и не нужно будет ее заново переучивать на всем объеме данных. На самом деле — нельзя, но всем очень очень нужно и иногда… везет. Если данных достаточно мало и нужно постараться запомнить их как можно больше (не снижая ошибку на тестовом наборе данных, разумеется) – то просто так «дообучить» не «переучивая» без риска что-то важное забыть уже не получится. Нет никакой гарантии, что стохастический градиентный спуск (SGD) запомнив новое, не забудет важное старое ;-) А если данных много (миллионы фотографий например) и требований запомнить именно этот конкретный пример нет — сработает (но молебен не помешает).

Разработчик, тестировщик и суицид

Не все осознают, что если при классическом программировании ошибки могли встретиться только либо в вашем коде, либо в сторонней библиотеке, либо по причине гормонального всплеска – то при обучении и эксплуатации нейронки все усложняется на порядки и вот почему:

1) У вас все стало плохо и неточно, потому что просто взяла и поменялась к черту информация, скрытая в исходном наборе данных
2) У вас ошибка в архитектуре нейронной сети и она проявилась только что из-за изменения исходных данных. Будьте добры, надевайте каску и изучайте градиенты и веса каждого слоя: нет ли затухания градиента, нет ли «взрыва» градиента, насколько равномерно распределяются веса и не нужно ли подкрутить регуляризацию, нет ли проблем в функции ошибки на выходе (loss), нет ли затухания потока информации/градиента в пограничных режимах сигмоидов и других специфических функциях активации и т.д. и т.п. – головная боль обеспечена надолго и всерьез и каска только для красоты.
3) Вам повезло и вы нашли ошибку в фреймворке нейронной сети … за неделю до релиза.

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

Искусственный интеллект, вызовы и риски – глазами инженера - 14
Настойка из паранойи, выдержка – 5 лет

Выводы

Мы открыто и честно обозначили ключевые факты и риски, связанные с внедрением и использованием глубоких нейронных сетей в высоконагруженных сервисах – с точки зрения инженера. Выводы – пока не делаем. Видно, что работы много, работа эта не простая, но страшно интересная и успех приходит только к профессионалам, умеющим объединять знания и людей из разных областей и владеющих вкусом к синергии. Очевидно, что нужно не просто прекрасно программировать и чувствовать систему кончиками пальцев, но и либо понимать, либо активно привлекать к подобным проектам экспертов в области математики и создавать коллегам позитивные, творческие условия – чтобы приходило побольше интересных и эффективных идей и способов их лаконичной и быстрой реализации. А иначе … придется месяцами сидеть с отверткой перед рухнувшим «Гравицапом», крутить наугад винтики, жечь спички и с завистью смотреть на блистающие в небе своей мощью и красотой искусственного интеллекта решения конкурентов. Желаю всем инженерной удачи, сходящийся нейронных сетей, уверенности, энергии и как можно меньше трудноуловимых ошибок! Ку! ;-)

Искусственный интеллект, вызовы и риски – глазами инженера - 15

Автор: 1С-Битрикс

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js