2019-03-07 06:34
Программирование в академических структурах очень любят по всякому классифицировать и систематизировать. Есть парадигмы, есть модели, есть "подходы" и т. д. В повседневном мэйнстриме на слуху императивное программирование и ООП, и немножечко функциональное.
Хорошая статья про "забытые" парадигмы (структурное, модульное, процедурное программирование), которые сегодня, на мой взгляд, наоборот актуальны как никогда! Потому что сегодня по сути везде только одна безальтернативная альтернатива -- ООП, но хорошо сделать сложную систему на ООП на самом деле куда сложнее, чем с помощью структурного или модульного подходов:
https://habr.com/ru/post/223253/
Недавно я рассказывал про дифференциальное программирование
https://vk.com/wall-152484379_1085
которое развивается в ответ на неудовлетворённую потребность невероятно быстро развивающейся области машинного обучения. И вот оказывается, что и у него тоже есть альтернативы.
Карлос Перец, автор учебника по глубокому обучению, придумал довольно интересный сервис Intuition Machine -- как быстро прикрутить AI/ML к любому виду деятельности. Мастерство тут в правильном инженерном комбинировании сверхбыстрого железа/топовых графических плат, огромных датасетов обучающих данных, подходящих алгоритмов их обработки и программных шаблонов, описывающих конкретную задачу.
В таком типовом формате Deep Learning определяется довольно прозаически: это технология программирования массивно-параллельных (massively parallel) вычислительных задач. Нюанс в том, что массивно-параллельные архитектуры (MPP) существуют не один десяток лет, я сам например в начале 90-х немного был связан с транспьютерами :) Однако Перец настаивает, что сегодня это направление становится новой парадигмой разработки, очередной революцией в программировании. Почему?
Императивное программирование и архитектуры фон Неймана подразумевают формирование последовательности достаточно простых логических конструкций (присваивания, условия, циклы), однозначно определяющих некоторый алгоритм, последовательность действий, и схему его исполнения (вычисления).
Декларативное программирование (вторая парадигма), к которому относят нередко и функциональное, подразумевает обратный подход: мы как-то формализуем решение, желаемый результат, а вот вычисление его уже становится ответственностью самой системы, и как оно будет происходить, какими шагами будет получен результат, мы не знаем. Это например языки Пролог, Planner, массово известен конечно язык запросов к базам данных SQL, и т. п. В некотором смысле и Haskell конечно тоже, да и любая система символьной математики будет декларативной.
Дифференциальное программирование, или более общо, программирование в ограничениях -- это третья парадигма, которая явилась мэйнстриму буквально в последний год усилиями ML-гуру Яна Лекуна, похоронившего Deep Learning и объявившего differential programming его полной заменой.
И вот четвёртая парадигма -- это порождающее программирование (generative programming), или рекомбинантное, как называет его Перец. Это отсылка к "генетическому" программированию, идея которого в том, что если очень долго комбинировать три императивных оператора, то какими-то градиентными спусками можно вырастить исходный текст, правильно решающий задачу :)
Порождающее программирование в целом подразумевает автоматический синтез нужной системы из доступных подсистем (кирпичиков лего) с известной функциональностью под заданные требования, и тут конечно имеются весьма серьёзные исследования. Но на практике дальше каких-то учебных сборок, или "умных" помощников в крупных системах оно не особо прорастало, пока в нынешнем десятилетии не расцвело ML.
И вот тут оказалось, что например генеративно-состязательные сети GAN точнее всего отвечают именно этой парадигме, а не декларативной, куда их традиционно относили. Нюанс в том, как мы думаем об тех же GAN -- редукционистски (аналитически, попытками сведения сложной системы к набору более простых), или же наоборот, "генеративно" (обобщающе, через синтез).
Реализовать декларативный язык гораздо сложнее, нежели императивный, потому что в дополнение к механической трансляции требуется создать и сам "движок" поиска решений, который вдобавок придётся привязывать к конкретным технологиям (недаром столько диалектов SQL существует, для каждой СУБД он свой по сути). И по этой причине метапрограммирование, несмотря на свой потенциал, развито слабо: с одной стороны, конкретные задачи удобнее всего делать на подходящем DSL, но с другой стороны, создание DSL остаётся трудоёмкой задачей, несмотря даже на неплохие инструменты, типа такого:
https://www.jetbrains.com/mps/
Дифференциальное программирование, порождающее программирование/программирование в ограничениях и рекомбинантное программирование объединяет одна черта: программисту не нужно каждый раз писать программу, решающую задачу или даже целый класс задач. Наоборот, "движок" решения уже есть, надо только правильно описать условия задачи и спецификации результата. При этом глубокое обучение позволяет решать весьма общий спектр задачек.
Генеративное программирование использует алгоритмы метаобучения, которые фиксированы, но при формировании решения не находятся на уровне когнитивного "понимания" задачи, который требуется например при реализации декларативных языков. Это так называемая компетентность без понимания, по Дэниелу Деннетту. Проще говоря, GAN способны генерировать очень реалистичные изображения котиков, но при этом они не "понимают", что делают (хотя и делают качественно, компетентно!).
Тут есть небольшой парадокс, который заключается в том, что редукционисты полагают, что у наших описательных моделей в принципе нету никаких ограничений, вопрос только в их правильной декомпозиции, правильной внутренней формализации. Однако на практике мы пока например никак не можем построить сильные модели даже простых биологических объектов. Генеративные модели -- это совсем другой подход. Они представляют собой свёртку механизмов генерации решений, однако сама эта свёртка не даёт нам никаких подсказок по поводу того, какой конкретно магией внутри неё получается правильное решение. Она обещает только устойчивый результат.
Ключевым в парадигме рекомбинантного программирования становится принцип неопределенности глубокого обучения:
Резюме в том, что по сути впервые в истории человечества удалось найти алгоритмы, с помощью которых можно автоматически "программировать" универсальные решения сложных задач реального мира.
При этом, что очень важно, эффективнее всего к этим алгоритмам относиться генеративно, как к абсолютно чёрным ящикам. Уже не требуется вручную кодить системы на миллионы строк кода — умения создать проект на тысячу императивных строк сегодня совершенно достаточно для того, чтобы с помощью ML-движков реализовывать AI/ML-проекты очень высокой сложности, причём под совершенно реальные задачи. Но потребуется небольшая дополнительная прокачка в профильной математике. Обязательно будем этим заниматься.
Но в идеале, хорошо бы конечно разобраться и с внутренней магией этого всего:)
Хорошая статья про "забытые" парадигмы (структурное, модульное, процедурное программирование), которые сегодня, на мой взгляд, наоборот актуальны как никогда! Потому что сегодня по сути везде только одна безальтернативная альтернатива -- ООП, но хорошо сделать сложную систему на ООП на самом деле куда сложнее, чем с помощью структурного или модульного подходов:
https://habr.com/ru/post/223253/
Недавно я рассказывал про дифференциальное программирование
https://vk.com/wall-152484379_1085
которое развивается в ответ на неудовлетворённую потребность невероятно быстро развивающейся области машинного обучения. И вот оказывается, что и у него тоже есть альтернативы.
Карлос Перец, автор учебника по глубокому обучению, придумал довольно интересный сервис Intuition Machine -- как быстро прикрутить AI/ML к любому виду деятельности. Мастерство тут в правильном инженерном комбинировании сверхбыстрого железа/топовых графических плат, огромных датасетов обучающих данных, подходящих алгоритмов их обработки и программных шаблонов, описывающих конкретную задачу.
В таком типовом формате Deep Learning определяется довольно прозаически: это технология программирования массивно-параллельных (massively parallel) вычислительных задач. Нюанс в том, что массивно-параллельные архитектуры (MPP) существуют не один десяток лет, я сам например в начале 90-х немного был связан с транспьютерами :) Однако Перец настаивает, что сегодня это направление становится новой парадигмой разработки, очередной революцией в программировании. Почему?
Императивное программирование и архитектуры фон Неймана подразумевают формирование последовательности достаточно простых логических конструкций (присваивания, условия, циклы), однозначно определяющих некоторый алгоритм, последовательность действий, и схему его исполнения (вычисления).
Декларативное программирование (вторая парадигма), к которому относят нередко и функциональное, подразумевает обратный подход: мы как-то формализуем решение, желаемый результат, а вот вычисление его уже становится ответственностью самой системы, и как оно будет происходить, какими шагами будет получен результат, мы не знаем. Это например языки Пролог, Planner, массово известен конечно язык запросов к базам данных SQL, и т. п. В некотором смысле и Haskell конечно тоже, да и любая система символьной математики будет декларативной.
Дифференциальное программирование, или более общо, программирование в ограничениях -- это третья парадигма, которая явилась мэйнстриму буквально в последний год усилиями ML-гуру Яна Лекуна, похоронившего Deep Learning и объявившего differential programming его полной заменой.
И вот четвёртая парадигма -- это порождающее программирование (generative programming), или рекомбинантное, как называет его Перец. Это отсылка к "генетическому" программированию, идея которого в том, что если очень долго комбинировать три императивных оператора, то какими-то градиентными спусками можно вырастить исходный текст, правильно решающий задачу :)
Порождающее программирование в целом подразумевает автоматический синтез нужной системы из доступных подсистем (кирпичиков лего) с известной функциональностью под заданные требования, и тут конечно имеются весьма серьёзные исследования. Но на практике дальше каких-то учебных сборок, или "умных" помощников в крупных системах оно не особо прорастало, пока в нынешнем десятилетии не расцвело ML.
И вот тут оказалось, что например генеративно-состязательные сети GAN точнее всего отвечают именно этой парадигме, а не декларативной, куда их традиционно относили. Нюанс в том, как мы думаем об тех же GAN -- редукционистски (аналитически, попытками сведения сложной системы к набору более простых), или же наоборот, "генеративно" (обобщающе, через синтез).
Реализовать декларативный язык гораздо сложнее, нежели императивный, потому что в дополнение к механической трансляции требуется создать и сам "движок" поиска решений, который вдобавок придётся привязывать к конкретным технологиям (недаром столько диалектов SQL существует, для каждой СУБД он свой по сути). И по этой причине метапрограммирование, несмотря на свой потенциал, развито слабо: с одной стороны, конкретные задачи удобнее всего делать на подходящем DSL, но с другой стороны, создание DSL остаётся трудоёмкой задачей, несмотря даже на неплохие инструменты, типа такого:
https://www.jetbrains.com/mps/
Дифференциальное программирование, порождающее программирование/программирование в ограничениях и рекомбинантное программирование объединяет одна черта: программисту не нужно каждый раз писать программу, решающую задачу или даже целый класс задач. Наоборот, "движок" решения уже есть, надо только правильно описать условия задачи и спецификации результата. При этом глубокое обучение позволяет решать весьма общий спектр задачек.
Генеративное программирование использует алгоритмы метаобучения, которые фиксированы, но при формировании решения не находятся на уровне когнитивного "понимания" задачи, который требуется например при реализации декларативных языков. Это так называемая компетентность без понимания, по Дэниелу Деннетту. Проще говоря, GAN способны генерировать очень реалистичные изображения котиков, но при этом они не "понимают", что делают (хотя и делают качественно, компетентно!).
Тут есть небольшой парадокс, который заключается в том, что редукционисты полагают, что у наших описательных моделей в принципе нету никаких ограничений, вопрос только в их правильной декомпозиции, правильной внутренней формализации. Однако на практике мы пока например никак не можем построить сильные модели даже простых биологических объектов. Генеративные модели -- это совсем другой подход. Они представляют собой свёртку механизмов генерации решений, однако сама эта свёртка не даёт нам никаких подсказок по поводу того, какой конкретно магией внутри неё получается правильное решение. Она обещает только устойчивый результат.
Ключевым в парадигме рекомбинантного программирования становится принцип неопределенности глубокого обучения:
чем лучше создаваемые нами нейронные сети умеют обобщать информацию, тем слабее становится их интерпретируемость, тем меньше мы понимаем, а что собственно вообще происходит, и что там у них внутри.Чем качественнее и надёжнее мы получаем результат, тем больше в модели будет избыточности и случайности. Причём самим этим механизмам, всё более запутывающим структуру модели по мере того, как она становится качественнее, стремление к обфуркации присуще естественно.
Резюме в том, что по сути впервые в истории человечества удалось найти алгоритмы, с помощью которых можно автоматически "программировать" универсальные решения сложных задач реального мира.
При этом, что очень важно, эффективнее всего к этим алгоритмам относиться генеративно, как к абсолютно чёрным ящикам. Уже не требуется вручную кодить системы на миллионы строк кода — умения создать проект на тысячу императивных строк сегодня совершенно достаточно для того, чтобы с помощью ML-движков реализовывать AI/ML-проекты очень высокой сложности, причём под совершенно реальные задачи. Но потребуется небольшая дополнительная прокачка в профильной математике. Обязательно будем этим заниматься.
Но в идеале, хорошо бы конечно разобраться и с внутренней магией этого всего:)
Источник: m.vk.com
Комментариев нет:
Отправить комментарий