Как структурировать проекты машинного обучения с использованием объектно-ориентированного программирования на Python?

Я заметил, что специалисты по статистике и машиностроению, как правило, не используют OOPS для проектов ML/data science при использовании Python (или других языков).

Главным образом это должно происходить из-за отсутствия понимания лучших практик разработки программного обеспечения в упс при разработке кода ML для производства. Потому что они в основном приходят из математики и статистика образования фона, чем информатика.

Дни, когда ученый ML разрабатывает специальный прототипный код, а другая команда разработчиков программного обеспечения делает его готовым к работе, в отрасли прошли.

enter image description here

Вопросы

  1. Как мы структурируем код, используя ООП для проекта ML?
  2. Должна ли каждая важная задача (из рисунка выше), такая как очистка данных, преобразование объектов, поиск по сетке, проверка модели и т.д., Быть отдельным классом? Каковы рекомендуемые методы разработки кода для ML?
  3. Любые хорошие ссылки на GitHub с хорошо написанным кодом для справки (может быть хорошо написанным решением проблемы)
  4. Должен ли каждый класс, например очистка данных, иметь функции fit(), transform(), fit_transform() для каждого процесса, такого как remove_missing(), outlier_removal()? Когда это сделано, почему scikit-learn BaseEstimator обычно наследуется?
  5. Какой должна быть структура типичного конфигурационного файла для проектов ML в производстве?

Ответ 1

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

При написании кода не должно быть никакой разницы, для чего предназначен код 1. ML - просто еще один домен, как и все остальное, и должен следовать принципам чистого кода.

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

Позвольте мне попытаться объяснить это более подробно, отвечая на некоторые из ваших вопросов:

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

4) Такие сложные иерархии наследования обычно создаются для того, чтобы реализация была расширяемой (см. "O" в SOLID). В этом случае пользователи библиотеки могут наследовать BaseEstimator, и легко увидеть, какие методы они могут переопределить и как они вписываются в существующую структуру scikit.

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

Все эти вещи должны быть объединены с предположением, насколько вероятно, что этот кусок кода будет изменен/расширен в будущем? Если вы уверены, что что-то должно быть написано в камне, не беспокойтесь о всех аспектах (например, сосредоточьтесь только на удобочитаемости) и направьте свои усилия на более важные части реализации.

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


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