Ван И, научный сотрудник Ant Group

Не так давно проект Сюй Шивэя Go+ набрал популярность на Hacker News, о чем можно судить по репортажу по этой ссылке. Я заинтересовался этим проектом и стал участником. Недавно Сюй Шивэй и сообщество начали прямую трансляцию и попросили меня поделиться причинами, по которым я следую Go+. Я завершил эту статью, основываясь на комментариях на экране во время прямой трансляции и рекомендациях моих друзей Хун Миншэна (владелец среды выполнения TensorFlow) и Ван Ю (Шен Диаомо).

Дополнение Python с помощью Go+

Я работаю над распределенными системами глубокого обучения уже 13 лет. После того, как Сюй Вэй попросил меня взять на себя его первоначальный проект PaddlePaddle в 2016 году, мой личный опыт использования Python в промышленных системах позволил мне больше узнать об ограничениях Python. На данный момент Go+ является самым надежным компенсационным решением.

Я хочу, чтобы Go+ смог полностью догнать Python и преодолеть его недостатки. Кроме того, доступен проект, подобный NumPy (назовем его пока numgo+), который поддерживает тензорные операции и отвечает требованиям науки о данных. Кроме того, базовая библиотека глубокого обучения, похожая на PyTorch (назовем ее сейчас GoTorch), построена на основе numgo+. Более того, если это возможно, Go+ становится языком интерфейса для компиляторов глубокого обучения.

Я работаю в Ant Group и отвечаю за SQLFlow, компилятор SQL с открытым исходным кодом, который переводит программы SQL, поддерживающие ИИ с расширениями синтаксиса, в программы Python. Мои коллеги сказали, что «если экосистема Go+ станет зрелой, они будут рады использовать SQLFlow для разработки программ Go+».

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

Преимущества Python

Python имеет гибкий синтаксис и объединяет удобные функции многих других языков. Как и C++, Python допускает перегрузку операторов. Авторы NumPy перегружают арифметические операторы для тензорных операций. Как и в Lisp, функция eval Python рекурсивно реализует интерпретатор Python, который может объяснять и выполнять выражения Python, так что программы Python могут создаваться самостоятельно.

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

Ограничения Python

Преимущества Python также вызывают некоторые ограничения. Для себя я испытал следующие болевые точки.

Сложно гарантировать качество кода

Гибкий синтаксис означает, что программа может быть написана несколькими способами. В современной разработке программного обеспечения люди сотрудничают друг с другом, а не работают независимо друг от друга. Несколько возможных методов написания могут легко вызвать ссору во время проверки кода, поскольку не существует объективного стандарта выбора. Эта проблема характерна для многих других языков, таких как Java. Чтобы решить эту проблему, сообщество определяет некоторые шаблоны проектирования. Перед тем, как программисты разрабатывают программы, они сначала проверяют, доступен ли шаблон проектирования. Поэтому Java-программисты должны изучать не только синтаксис Java, но и шаблоны проектирования. Это справедливо и для языка C++. Одним из решений предыдущей проблемы является стиль кода, определенный Google. Этот стиль кода определяет синтаксис, который можно использовать или нет. Согласно объяснению Роба Пайка, выбор разрешенного синтаксиса является первоначальным замыслом дизайна Go. Python слишком гибок, поэтому стиль его кода нельзя определить так же, как в C++. PEP8 может только указывать требования к набору текста и почти не ограничивает выбор синтаксиса. Python также не может определять шаблоны, потому что шаблонов слишком много.

Для обеспечения гибкости Python использует динамические типы данных. Чтобы определить возвращаемое значение функции Python, мы должны внимательно прочитать ее код. Python также имеет расширения синтаксиса, требующие от программистов указания типов входных и выходных данных. Однако не так много людей используют расширения, потому что, в конце концов, они используют Python из-за его гибкости. Если гибкость ограничена, они обратятся к другим статическим языкам. Из-за гибкости сложно понять длинные функции Python. Тем не менее, программисты Python используют Python, чтобы полностью раскрыть свои сильные стороны, и им все равно, понимают ли другие функции Python, которые они пишут. Кроме того, они отказываются улучшать детализацию функций Python.

Несмотря на это, вы также можете найти элегантно написанный код Python, такой как Google Tangent. Это небольшой проект всего с двумя авторами. Он имеет четкую структуру кода. Каждая функция в основном содержит не более 10 строк кода, и код такой же длины, как и аннотация. Поэтому его легко понять. Однако это противоречит впечатлению многих пользователей Python. Когда я отвечал за проект PaddlePaddle, я настроил CI для вызова различных инструментов для проверки исходного кода в дополнение к изучению и обобщению шаблонов Python. Однако эти инструменты недостаточно интеллектуальны, чтобы автоматически аннотировать код или разделять длинные определения функций.

Трудно оптимизировать эффективность вычислений

Python обладает богатым синтаксисом и высокой гибкостью. Поэтому сложно написать интерпретатор и сложно оптимизировать производительность. Напротив, язык Go имеет простой синтаксис, лучшую выразительность, чем C, и меньше ключевых слов, чем C. Эта простота упрощает оптимизацию производительности программ Go. Через несколько лет после публикации Go уровень оптимизации производительности кода компилятора Go быстро приблизился к уровню оптимизации GCC для программ на C++. Как и Python, C++ имеет богатый синтаксис, поэтому сложно разрабатывать функции оптимизации производительности кода для компилятора.

Некоторые люди пытались заменить интерпретатор Python компилятором Python, чтобы оптимизировать производительность перед выполнением программы. Однако синтаксис Python более гибкий, чем синтаксис C++. Поэтому практически невозможно написать компилятор, полностью поддерживающий стандартный синтаксис Python. В результате эти попытки вскоре прекратились. В настоящее время распространенным решением является использование интерпретатора для оптимизации времени выполнения (JIT-компиляции). Это решение проще, чем использование компилятора, благодаря информации времени выполнения.

В области искусственного интеллекта обучение моделей глубокого обучения требует больших вычислительных ресурсов. Решение, основанное на графовом режиме TensorFlow, выглядит следующим образом: программы Python, написанные программистами, не обучаются во время выполнения. Вместо этого процесс обучения экспортируется в виде структуры данных, называемой вычислительным графом, а затем передается в среду выполнения TenosrFlow для выполнения. Если эффективность выполнения TensorFlow во время выполнения гарантирована, эффективность интерпретатора Python становится незначительной.

Режим графа TensorFlow создан из лучших побуждений, но он также излишен. Исходные программы, различные уровни промежуточных представлений (IR) и двоичный код были выражениями для описания вычислительного процесса. Вычислительный граф, предоставленный проектом TensorFlow в первые годы, является повторяющимся и непрофессиональным. На графе сложно выразить if-else, цикл и определения и вызовы функций, не говоря уже о расширенных структурах потока управления, таких как замыкание, сопрограмма и многопоточность. Непрофессиональный дизайн компилятора, сделанный инженерами ИИ, смущает автора LLVM Криса Латтенера. Поэтому он пытается заменить Python на Swift для TensorFlow в качестве языка интерфейса и заменить вычислительный граф TensorFlow многоуровневым промежуточным представлением (MLIR). Для получения дополнительной информации посетите https://www.tensorflow.org/mlir/dialects.

Попытки преодолеть ограничения Python

Когда я отвечал за проект PaddlePaddle, я вместе со своим коллегой Чен Си попытался создать самоходную лодку, чтобы проверить возможности Paddle Fluid. Для этого мы написали метод имитации обучения с помощью Fluid, позволяющий лодке обучаться навыкам вождения людей-водителей. Для получения дополнительной информации см. блоги серии на https://zhuanlan.zhihu.com/p/38395601. В этой попытке, если мы возьмем MacBook Pro с программами Python, он будет потреблять много энергии. С другой стороны, встроенные устройства не подходят для запуска обученных программ Python. Если мы загрузим данные на сервер для обучения после остановки лодки, лодка будет слишком медленно учиться у людей-водителей.

Поэтому другой сотрудник, Ян Ян, написал Paddle Tape, который использовал C++ для реализации автоматического дифференцирования PyTorch (autodiff). В сочетании с несколькими базовыми вычислительными блоками (операторами) Paddle Fluid, написанными на C++, лента становится полной системой глубокого обучения C++ и не имеет никакого отношения к Python.

В начале 2019 года мой друг Хун Миншэн отвечал за проект Swift для TensorFlow в Google. Это была еще одна попытка убрать Python из инфраструктуры ИИ. В то время он попросил меня поделиться историей о Paddle Tape и самоуправляемой лодке с командой Криса Латтенера. Для просмотра отредактированных слайдов перейдите по этой ссылке.

Я отвечаю за ElasticDL в Ant Group, которая представляет собой распределенную систему обучения глубокому обучению с открытым исходным кодом. Во время реализации этой системы я пытался вызвать режим графа TensorFlow, режим нетерпеливого выполнения, PyTorch и Swift для TensorFlow. Кроме того, меня вдохновили концепции дизайна Swift для TensorFlow и стратегия процветания экосистемы Python.

Go+ и наука о данных

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

До появления Go+ некоторые люди пытались использовать Go для обработки данных и для реализации библиотек тензорных операций, таких как gonum. Однако эти реализации нелегко использовать в качестве программ Python для NumPy. Это связано с тем, что типы данных должны быть указаны для констант Go, но не должны указываться для констант Python. Для сравнения примеров вы можете посетить https://github.com/qiniu/goplus/issues/307.

Когда вы используете Go для определения константы типа ndarray, код выглядит примерно так:

x := numgo.NdArray( 
     [][]float64{
      {1.0, 2.0, 3.0},
      {1.0, 2.0, 3.0}})

Однако, когда вы используете Python для той же цели, код выглядит примерно так:

x = numpy.ndarray(
    [[1.0, 2.0, 3.0],
     [1.0, 2.0, 3.0]])

С введением Go+ для автоматического определения типов данных код становится следующим, почти таким же, как в Python.

x := numgo.NdArray(
    [[1.0, 2.0, 3.0],
     [1.0, 2.0, 3.0]])

Кроме того, Сюй Шивэй добавляет комментарий, объясняющий, что Go+ готов поддерживать синтаксис определения тензора MATLAB. Благодаря этой функции программа становится проще.

x := numgo.NdArray(
     [1.0, 2.0, 3.0; 
      1.0, 2.0, 3.0])

Сегодня в Go+ сделано много подобных и удобных улучшений синтаксиса. Эти расширения синтаксиса могут значительно упростить программирование для обработки данных. Для получения дополнительной информации посетите https://github.com/qiniu/goplus/tree/master/tutorial

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

Поддержка повторного использования экосистемы Go — это сильная сторона языка Go+. В процессе разработки Go было накоплено множество базовых технологий научных вычислений, например, инкапсуляция типов данных Go, реализующих тензоры. Также доступны эффективные реализации Go для вычисления этих типов данных. Отчасти это связано с тем, что программы Go могут легко вызывать программы C и C++, включая проверенные базовые библиотеки, такие как LAPACK, в области научных вычислений и библиотеку интерфейса CUDA графических процессоров NVIDIA. Эти базовые библиотеки C и C++ также являются основой экосистемы обработки данных Python. Поэтому эта статья называется «Go+ может эффективно преодолеть недостатки Python».

Компиляторы Go+ и глубокого обучения

В предыдущих разделах мы упоминали технологии глубокого обучения. Глубокое обучение — еще одна область, в которой широко используется Python. Это, естественно, связано с наукой о данных. Например, тензорная структура данных PyTorch и TensorFlow такая же, как ndarray NumPy. В области глубокого обучения компиляторы являются последним основным направлением исследований.

Большинство разработчиков в сообществе Go являются разработчиками серверных систем. Во время прямой трансляции некоторые зрители разместили на экране комментарии о том, что они не инженеры ИИ и не следят за ИИ. Если они так думали, то это безответственное отношение к своей работе.

Граница между серверной системой и системой ИИ становится все более размытой. Серверная система предназначена для интернет-сервисов. Однако вся интернет-экономика построена на замене людей бессонными серверами для обслуживания населения, и в основе этой логики лежит ИИ.

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

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

Основная проблема системы глубокого обучения заключается в авторазнице, которая определяется математическими характеристиками алгоритма SGD. Алгоритм SGD попеременно выполняет прямой и обратный проходы для извлечения параметров модели из обучающих данных. Модель плюс параметры составляют знание. Когда исследователи модели определяют модель, они одновременно описывают прямой проход. Однако вручную описать обратный проход сложно. Следовательно, требуется программа для автоматического вычитания обратного прохода из прямого прохода. Этот автоматический вывод называется autodiff.

В настоящее время доступны две политики автодиффа. Первая политика — это деривация во время выполнения. Он также известен как подход на основе динамической сети и ленты. Независимо от сложности прямого прохода, например, он может включать в себя if-else, цикл, определения и вызовы функций и даже сопрограмму и многопоточность, основная идея этой политики заключается в записи основных операций (операторов), выполняемых последовательно в лента. Затем обратный проход заключается в отслеживании записей на ленте и последовательном вызове производного оператора (оператора градиента) для каждой операции. Эту политику используют PyTorch, нетерпеливое выполнение TensorFlow и Paddle Tape. Эта политика имеет мало отношения к компилятору, но относится к JIT-компиляции.

Другая политика заключается в вычете обратного прохода перед запуском. Для этого требуется специальный компилятор autodiff. Эта политика используется в графическом режиме TensorFlow, Caffe/Caffe2, Paddle Fluid, Google Tangent, Julia и Swift для TensorFlow. Компилятор обычно переводит исходные программы, описанные на исходном языке, в целевые программы, описанные на целевом языке. Однако режим графа TensorFlow, Caffe/Caffe2 и Paddle Fluid не представляют исходный язык и просят пользователей вызывать библиотеку Python для описания прямого прохода. Google Tangent, Julia и Swift для TensorFlow просят пользователей использовать языки Python, Julia и Swift соответственно для определения функций, описания прямого прохода и преобразования функций прямого прохода в функции обратного прохода.

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

Две политики автоматического сравнения во время компиляции и во время выполнения подходят для Go+ и не влияют на повторное использование Go+ существующих технологий. Подобно базовым библиотекам, таким как LAPACK, повторно используемым в области науки о данных, базовые операторы и операторы градиента также должны повторно использоваться в области глубокого обучения.

Во время выполнения проще использовать ленту для реализации политики автоматического сравнения. Ян Ян разработал Paddle Tape за неделю. Однако политика autodiff во время компиляции сложна. Более 20 разработчиков Paddle Fluid потратили несколько месяцев на реализацию политик autodiff для определений и вызовов if-else, цикла и функций на основе работы TensorFlow Yuan Yu, которая описана в https://arxiv.org/pdf/ 1805.01772.pdf

Эти попытки напоминают нам о важности повторного использования основных технологий сообщества. Например, мы можем заменить вычислительный граф на MLIR для описания сложных потоков управления. Вычислительный граф никогда не сможет описать горутину и выборку. Мы можем использовать Tensor Virtual Machine (TVM) в качестве серверной части компилятора и использовать технологии глубокого обучения для оптимизации программ глубокого обучения. Результатом всех этих технологий являются вызовы основных операторов. С этой точки зрения операторы, накопленные в предыдущей экосистеме глубокого обучения, аналогичны встроенным функциям. Хун Миншэн также неоднократно подчеркивал это, редактируя эту статью.

Мы надеемся, что в ближайшем будущем Go+ можно будет использовать в качестве интерфейса для глубокого обучения, такого как Python, Julia и Swift, для повторного использования базовых IR, серверной части компилятора и основных операторов.

Резюме

На мой взгляд, основной стратегией будущих проектов Go+ является поддержание простого синтаксиса Go и правильное добавление гибкости, но не слишком гибкой, как Python или C++.

Кроме того, в сотрудничестве с сообществом разрабатываются исследовательские проекты, такие как numgo+ и GoTorch. Обогащение технической экосистемы — стратегическое направление сообщества. Кроме того, Go+ используется в качестве языка интерфейса компиляторов глубокого обучения для повторного использования базовых вычислительных технологий глубокого обучения, накопленных сообществом за многие годы.

Наконец, я хотел бы поблагодарить следующих людей за помощь в доработке этой статьи: Сюй Шивэй, основных участников Go+ Чай Шушан и Чен Донгпо, отличного участника сообщества Go Аста Се и основного участника сообщества ONNX Чжан Кэ.

Вы можете принять участие в обсуждении любого содержания этой статьи.

об авторе

Ван И — исследователь в Ant Group и владелец проектов SQLFlow и ElasticDL с открытым исходным кодом. Он пишет код с 10 лет. Однажды он использовал сварную печатную плату, чтобы расширить «китайский образовательный компьютер» и превратить старомодную стиральную машину Weili с двумя баками в автоматическую стиральную машину. Он разработал свою первую компьютерную игру, используя языки ассемблера Apple BASIC и 6502. В старшей школе он самостоятельно изучил все компьютерные курсы для обычного бакалавра компьютерных специальностей, принял участие в Национальном экзамене по компьютерному рейтингу (NCRE) и получил сертификаты «программист», «старший программист» и «системный аналитик». Он занимается инфраструктурой искусственного интеллекта (ИИ) в течение 13 лет, работал в нескольких ведущих мировых интернет-компаниях и начал бизнес в Силиконовой долине США и Пекине Китая.

Оригинальный источник: