Методы программной инженерии сегодня начали применять для создания зависимого от данных ПО (datacentric software) — систем искусственного интеллекта, машинного обучения и обработки больших данных. Использование самоуправляемых автомобилей и умных дронов, с одной стороны, и дефицит специалистов по исследованию данных, с другой, — все это признаки основанной на данных экономики, невозможной без их глубокой аналитики. Неудивительно, что по сравнению с 2014 годом только темпы найма специалистов соответствующего профиля выросли более чем вдвое [1]. Однако зависимое от данных ПО подвержено ошибкам. В случае с самоуправляемым автомобилем Uber следствием такой ошибки стала гибель человека: поздним мартовским вечером 2018 года Элейн Херцберг была сбита, став первой в мире жертвой робомобиля [2].

Хотя ошибки в аналитике данных порождают риски, специалисты по программной инженерии чаще сами пользуются методами аналитики данных, чем работают над совершенствованием методов разработки систем, зависимых от данных. Как показал анализ 285 докладов, обнародованных на Конференции по автоматизации программной инженерии, с 2016 по 2019 год (рис. 1) существенно выросла доля работ, посвященных искусственному интеллекту, машинному обучению и большим данным, причем докладов, касающихся аналитики данных, в 2019 году подготовлено больше, чем в остальные годы. Однако большая часть из них была посвящена решению традиционных задач программной инженерии: прогнозированию дефектов, поиску ошибок, обобщению документов, предоставлению рекомендаций кода, тестированию и т. д. — с помощью методов глубинного обучения, обработки естественного языка, эвристического и многоцелевого поиска, классификации и извлечения информации. И лишь 4% докладов затрагивали тему усовершенствования методов программной инженерии в применении к разработке систем аналитики данных.

Рис. 1. Рост применения аналитики данных в программной инженерии. Исследований, посвященных оптимизации методов программной инженерии систем аналитики данных, гораздо меньше, чем исследований в сфере использования аналитики данных для решения задач программной инженерии

Между тем сегодня остро назрела потребность в расширении исследований, направленных на адаптацию методов программной инженерии к требованиям разработки зависимого от данных ПО, с целью повышения производительности труда разработчиков и инженеров систем искусственного интеллекта, машинного обучения и обработки больших данных. Об этом говорят, в частности, результаты опросов, проведенных среди специалистов по исследованию данных при поддержке исследовательского подразделения Microsoft [3]. Существуют важные различия между разработкой традиционного и зависимого от данных ПО, из-за которых программисты испытывают сложности с отладкой и тестированием систем искусственного интеллекта, машинного обучения и аналитики больших данных.

Исследователи данных в командах разработки ПО

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

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

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

Строители платформ. Участники этой категории 49% времени уделяют разработке платформ для сбора данных. У них большой опыт в области распределенных систем обработки больших данных, разработке пользовательской и серверной части, использовании популярных языков программирования — Си, C++, C#. Это специалисты, участвующие в создании платформы и конвейера инженерии данных. Они часто сетуют на трудность очистки данных.

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

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

Отличия разработки традиционного ПО и систем аналитики больших данных

Рис. 2. Разработка традиционного ПО в сравнении с разработкой систем аналитики больших данных

Сравнение разработки традиционного и зависимого от данных ПО помогает прояснить сложности, связанные с последним (рис. 2). Как правило, исследователи данных разрабатывают аналитические приложения и тестируют их на ограниченных выборках, используя локальные компьютеры. Затем приложение проверяют на выборке гораздо большего объема на специализированном кластере, и в этом случае выполнение может занять несколько часов. Если происходит аварийное завершение задачи или выдаются неверные либо сомнительные результаты, процесс отладки повторяется сначала. Перечислим основные особенности, из-за которых разработка зависимого от данных ПО является более трудной:

1. Данные имеют огромный объем, размещены удаленно и распределены.

2. Сложности с созданием тестов. Аналитические приложения нередко начинают писать, не видя всего объема оригинальных входных данных, которые обычно размещают на сервисах хранения наподобие Amazon S3. Поскольку код пишется на основе пробной выборки (фрагмента оригинальных данных), подготовить тестовый набор для всего объема непросто.

3. Сложно задавать условия отказов, в том числе из-за неполноты тестов.

4. Системные стеки сложны и недостаточно прозрачны, так как применяемые в разработке зависимого от данных ПО распределенные системы и фреймворки машинного обучения состоят из множества сложных компонентов, отвечающих за планирование задач, управление кластерами, разделение данных, выполнение задач, обеспечение отказоустойчивости, управление выбросами и т. д.

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

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

Отладка и тестирование систем аналитики больших данных

На протяжении пяти лет в Калифорнийском университете Лос-Анджелеса идет работа по расширению и адаптации методов отладки и тестирования систем аналитики больших данных на базе Apache Spark. Опыт показал, что разработка интерактивных отладочных средств для конвейерной системы обработки больших данных требует глубокого понимания внутренней модели планирования и выполнения задач. Чтобы отслеживать происхождение данных, потребовалась переработка фреймворка параллельной обработки данных, а для повышения прозрачности процесса выполнения кода оказалось удобным воспользоваться абстрагированием.

  • BigDebug: интерактивный отладчик для систем аналитики больших данных. Для традиционной разработки существует множество удобных средств отладки, например GNU Debugger. Почему же аналогичный интерактивный инструмент так трудно было создать для Apache Spark? В частности, из-за невозможности использовать классическую реализацию точек останова: при полной остановке вычислений в конвейере параллельной обработки данных уменьшилась бы пропускная способность, и очевидно, что с помощью обычной условной точки останова пользователь не смог бы проверить сразу миллиарды записей. Отладчик BigDebug не останавливает выполнение программы, а имитирует точку останова путем восстановления состояния на момент последней контрольной точки и предоставляет состояния программы защищенным образом в режиме потока. Эффективно используя внутренние механизмы контрольных точек и планирования задач Apache Spark, создатели BigDebug смогли реализовать интерактивные возможности отладки и исправления ошибок, причем непроизводительные издержки во время работы отладчика составляют не более 34%.
  • Titian: выяснение происхождения данных для Apache Spark. Системы выяснения происхождения данных развиваются уже достаточно давно. На вход такой системы подается результат выполнения запроса, и она определяет, какие входные данные повлияли на получение этого результата, действуя по принципу, аналогичному методу динамического распространения taint-меток в средствах безопасности. Чтобы обеспечить возможность выяснения происхождения данных на уровне отдельных записей, пришлось переработать среду выполнения Apache Spark, в том числе изменить принципы хранения таблиц истории данных и реализовать механизм радикального ускорения выполнения запросов на получение входных данных.
  • BigSift: автоматизация отладки средств аналитики больших данных. На вход BigSift подаются программа и тестовый набор, после чего система автоматически находит минимальное подмножество входных данных, которые приводят к провалу теста. В BigSift применяют методику установления происхождения данных, позаимствованную из СУБД, и метод дельта-отладки. Предусмотрен ряд оптимизаций, которые позволили реализовать решение для автоматизированной отладки, работающее в 66 раз быстрее по сравнению с дельта-отладкой, при этом системе на обработку нужно на 62% меньше времени по сравнению с тем, что требуется для выполнения самой отлаживаемой задачи.
  • BigTest: тестирование систем аналитики по принципу белого ящика. Сейчас для тестирования систем аналитики данных обычно готовят выборки, но такой метод характеризуется низким покрытием кода. Еще один вариант — использовать традиционные процедуры синтеза тестов (например, символьное выполнение), однако эта методика недостаточно масштабируется для Apache Spark, объем собственного кода которой составляет порядка 700 тыс. строк.

Чтобы обеспечить автоматический синтез тестов для приложений Spark, BigTest абстрагирует операторы управления потоком данных в терминах чистой логики первого порядка. Система проводит символьное выполнение заданного пользователем кода приложения, комбинируя результат с логическими спецификациями конвейера данных. Это позволяет сгенерировать готовую выборку входных данных. При этом достаточно всего трех десятков записей, чтобы достичь такого же покрытия кода, как при тестировании на всем объеме данных. Благодаря автоматическому синтезу выборки с помощью BigTest, объем необходимых тестовых данных уменьшается на порядки, а тестирование ускоряется в 200 раз.

Направления исследований

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

Комбинированная отладка. Необходимо расширить охват отладки, начав учитывать не только ошибки в коде, но и ошибки в данных. При этом следует скомбинировать методы исправления и тех и других. В мире программной инженерии ошибками традиционно считаются дефекты кода, тогда как сообщество специалистов по СУБД рассматривает в качестве ошибок дефекты данных, обусловленные непредвиденными распределениями, функциональными зависимостями и несоответствиями в схемах. Следует объединить опыт обоих сообществ, чтобы в тандеме анализировать ошибки и в коде, и в данных. Исследователи данных создают программные системы, имея лишь смутное представление о входных данных, поэтому в коде возможны ошибки, обусловленные либо неверными предположениями, либо некорректной обработкой новых данных, отклоняющихся от доступной входной выборки.

Рассмотрим ошибку, когда используется неверный разделитель. Например, строка делится символьной последовательностью «[]» вместо «[]», что приводит к неверным результатам. Пользователь может определить эту ситуацию как ошибку в данных, но можно рассматривать ее и как ошибку программирования, допущенную из-за неверных предположений о характере данных. По сути дела, такую ошибку можно исправить и путем изменения кода, и посредством очистки данных, и обоими методами.

В сообществе программной инженерии развивают методы автоматического исправления программ, а в сообществе СУБД — средства автоматической очистки и восстановления данных. Пришло время объединить эти наработки, ввести отдельное понятие ошибок в системах аналитики данных и разобраться, как совместно исправлять ошибки в коде и данных с учетом их тесной связи.

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

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

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

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

***

Разработка зависимого от данных ПО во многих отношениях отличается от создания традиционных программ. Развитие соответствующих методов требует изучения вопросов взаимодействия ошибок в коде и данных, а также расширения охвата отладки в связи с тем, что отладка производительности так же важна для исследователей данных, как и отладка корректности. Задавать характеристики корректности работы систем эвристической, вероятностной и прогнозной аналитики заведомо трудно — нужны простые в использовании и расширении методы спецификации, охватывающие отладку и тестирование. Для решения этих задач сообществу программной инженерии предстоит работать во взаимодействии со специалистами в сфере искусственного интеллекта, машинного обучения и СУБД.

Литература

1. D. Culbertson. High demand for data science jobs. Indeed Hiring Lab, Mar. 15, 2018. URL: https://www.hiringlab.org/2018/03/15/data-science-job-postings-growing-quickly (дата обращения: 21.08.2020).

2. Wikipedia. Death of Elaine Herzberg. Apr. 4, 2020. URL: https://en.wikipedia.org/wiki/Death_of_Elaine_Herzberg (дата обращения: 21.08.2020).

3. S. Amershi et al. Software engineering for machine learning: A case study. In Proc. 2019 IEEE/ACM 41st Int. Conf. Software Engineering: Software Engineering Practice (ICSE-SEIP), May 2019. P. 291–300. doi: 10.1109/ICSE-SEIP.2019.00042.

Мирюнг Ким ( miryung@cs.ucla.edu ) — профессор, Калифорнийский университет в Лос-Анджелесе.

Miryung Kim, Software Engineering for Data Analytics. IEEE Software, July/August 2020, IEEE Computer Society. All rights reserved. Reprinted with permission.