Хорошо продуманный процесс структурирования проектов машинного обучения поможет быстро создавать новые репозитории GitHub и с самого начала ориентироваться на элегантную программную архитектуру. Команда VK Cloud перевела статью о том, как организовать файлы в проектах машинного обучения, используя VS Code. Шаблон для создания проектов машинного обучения можно скачать на GitHub.
Примечание
Чтобы создать новый проект машинного обучения из шаблона GitHub, перейдите в репозиторий GitHub и нажмите кнопку «Use this template». Репозитории для шаблонов GitHub — очень удобная вещь: в них я и другие пользователи могут генерировать новые репозитории с такой же структурой, ветвями и файлами, как в шаблоне.
На следующей странице открываются настройки проекта, например имя репозитория и настройки конфиденциальности:
Создав репозиторий, нажмите “Actions” в верхнем меню и немного подождите:
Если появилась зеленая галочка, то проект готов — можно писать код!
Дальше я расскажу, почему к проекту добавлен тот или иной файл и как был создан шаблон GitHub.
Основные файлы
Для начала давайте рассмотрим основные файлы проекта, созданного на базе шаблона:
.gitignore
Из файла .gitignore GitHub черпает информацию о том, какие файлы нужно игнорировать во время коммита проекта в репозиторий GitHub. Если вы создаете новый репозиторий с нуля, можно указать предварительно настроенный файл .gitignore. Я просто выбрала предварительно настроенный файл Python и добавила сгенерированный файл в шаблон:
Файл длинный, так что я покажу только первые строки:
https://github.com/bstollnitz/ml-template/blob/main/.gitignore
lines (105 sloc) 1.76 KB
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
...
LICENSE
Файл LICENSE дает понять, под какой лицензией распространяется код из этого репозитория. Эту настройку тоже можно указать в момент создания репозитория:
Я обычно выбираю лицензию MIT, потому что она позволяет использовать опубликованный код в коммерческих целях. Насколько я знаю, это принципиальный вопрос для разработчиков из крупных компаний с многочисленными процессами, поэтому очень важно выбрать правильную лицензию для кода. Это ключевой фактор, который в одном случае защитит интеллектуальную собственность вашей компании от конкурентов, а в другом — позволит поучаствовать в общественно важном Open-Source-проекте или помочь в создании коммерческого продукта.
README.md
Файл README.md содержит информацию о коде из этого репозитория. Я решила оставить этот файл пустым, но не удалять из шаблона. Когда я буду использовать шаблон для создания другого проекта, он напомнит, что в него надо добавить информацию. Как и два других файла, этот можно создать, просто поставив нужную галочку в момент создания репозитория:
environment.yml
В качестве диспетчера среды для Python я использую Miniconda. Поскольку во всех моих проектах есть файл environment.yml, в котором содержатся все пакеты, необходимые для исполнения кода, имеет смысл добавить этот файл в шаблон. Я включила в него несколько пакетов, которые активно использую практически в каждом проекте машинного обучения: Python, PyTorch, Yapf и Pylint — в следующем разделе я подробно остановлюсь на последних двух.
https://github.com/bstollnitz/ml-template/blob/main/environment.yml
name: <GITHUB_REPOSITORY>
channels:
- anaconda
- pytorch
- conda-forge
dependencies:
- python==3.10.4
- pytorch==1.11.0
- yapf==0.31.0
- pylint==2.12.2
На момент написания статьи это актуальные версии. Когда в следующий раз я буду обновлять пакеты до нового набора совместимых версий, обновление будет происходить в этом шаблоне. Поскольку он будет использоваться во всех будущих проектах, в каждом из них окажутся обновленные версии.
В проекте, созданном из шаблона, у файла environment.yml имя среды conda совпадает с именем репозитория. Раньше на его месте был токен
<GITHUB_REPOSITORY>
, который я добавила в шаблон GitHub. Я вернусь к этому позже, когда буду объяснять, как создавался шаблон.Чтобы установить и активировать среду conda, можно использовать следующие команды:
conda env create environment.yml
conda activate <name of your environment>
Подробнее с распространенными командами conda можно ознакомиться в документации.
Анализ кода и автоматическое форматирование
Когда пишешь код на Python в VS Code, многое зависит от анализатора кода и инструмента форматирования. Типичный анализатор кода на Python анализирует исходный программный код, проверяет, соответствует ли он официальному стайл-гайду PEP8 для Python, и выводит предупреждения в случае ошибок. Стайл-гайд PEP8 содержит рекомендации по отступам, максимальной длине строки и соглашениям об именовании переменных. Мне нравится анализатор кода Pylint, потому что в дополнение к проверке на соответствие стилю PEP8 он проверяет код и на ошибки — например, может определить, что я использовала модуль, но не импортировала его. На момент написания статьи Pylint остается самым популярным анализатором кода на Python.
Типичная утилита форматирования кода на Python выполняет автоформатирование в соответствии со стандартом PEP8. Представьте, что строка кода длиннее, чем это рекомендовано в PEP8. Тогда анализатор выдаст предупреждение, но не исправит проблему за вас. Здесь пригодится инструмент форматирования: он автоматически делит код на строки. Мне нравится YAPF, написанный Google: он и проверяет, соответствует ли код требованиям PEP8, и «причесывает» его. В приведенном примере YAPF не просто поделит код на строки с учетом рекомендованной максимальной длины, он сделает это так, чтобы код было легко читать.
Конфигурация для Pylint обычно задается в файле .pylintrc. Мой файл соответствует требованиям стайл-гайда Google для Python. Его можно загрузить с той же страницы. Еще до появления анализатора кода я уже использовала в работе этот стайл-гайд, но теперь преимуществ стало еще больше.
Если по какой-то причине мне не нужно то или иное правило, я просто отключаю соответствующие настройки одним из двух способов:
На весь проект. Добавляю его в раздел disable в файле .pylintrc. Например:
https://github.com/bstollnitz/ml-template/blob/main/.pylintrc
disable=abstract-method,
...
zip-builtin-not-iterating,
Только для конкретного экземпляра. Добавляю комментарий сразу над строкой с предупреждением анализатора. Например:
https://github.com/bstollnitz/sindy/blob/main/sindy/lorenz-pysindy/src/2_fit.py
<i># pylint: disable=unused-import</i>
from pysindy.differentiation import FiniteDifference, SINDyDerivative
Конфигурирование YAPF выполняется в файле .style.yapf. Вот содержание этого файла в шаблоне GitHub:
https://github.com/bstollnitz/ml-template/blob/main/.style.yapf
[style]
based_on_style = google
В разделе «Стиль форматирования» документации YAPF есть список из четырех основных поддерживаемых стилей: pep8, google, yapf и facebook. Я выбрала стиль Google, потому что он подразумевает соблюдение требований стайл-гайда Google для Python — удобно, когда анализатор и инструмент форматирования кода ориентируются на один и тот же стайл-гайд. В документации YAPF содержится подробная информация о том, как настроить работу YAPF.
Анализатор и инструмент форматирования кода можно включать вручную из командной строки. Но лучше всего настроить редактор так, чтобы он запускал их автоматически.
Настройка VS Code
VS Code поддерживает множество настроек, для которых в нем существуют разные локации. Эффективность работы зависит от того, насколько удачную локацию вы выберете. Когда я добавляю настройки в VS Code, то каждый раз выбираю один из трех вариантов:
-
.devcontainer/devcontainer.json. GitHub Codespaces — это облачная среда разработки, запускающая код в контейнере. Мне очень нравится эта новая функция GitHub; если вы ею еще не пользуетесь, рекомендую обязательно попробовать. В этот файл я добавляю настройки, которые нужны для работы с конкретным проектом в GitHub codespace. Например, здесь удобно указывать заданный по умолчанию путь к интерпретатору Python для Codespace.
-
.vscode/settings.json. В этот файл я добавляю настройки для конкретного проекта — вне зависимости от того, запускаю ли я проект на локальном ПК или в codespace. Именно здесь я указываю настройки анализатора и инструмента форматирования кода, что мы вскоре увидим.
-
Пользовательские настройки VS Code в Settings Sync. Если мне нужно применить определенную настройку ко всем проектам на разных устройствах, я добавляю ее в настройки VS Code и включаю Settings Sync.
В другой статье я подробно объясняю, как настраиваю GitHub Codespaces. Здесь же я расскажу о двух других локациях для настроек.
Давайте посмотрим на .vscode/settings.json. В этом файле я задаю настройки анализатора и инструмента форматирования кода для каждого проекта, потому что иногда их нужно менять. Хранение настроек в каждом проекте гарантирует, что мои коллеги будут работать с теми же настройками, сохранив единообразное форматирование кода. Я не рекомендую включать эти настройки в файл devcontainer.json, потому что обычно всем нужно, чтобы среда разработки была одинаковой и на локальном компьютере, и в Codespaces. Вот содержание моего файла .vscode/settings.json в шаблоне GitHub:
https://github.com/bstollnitz/ml-template/blob/main/.vscode/settings.json
{
«python.linting.pylintEnabled": true,
«python.formatting.provider": «yapf",
"editor.rulers": [
80
],
"editor.formatOnSave": true,
}
В первых двух строках указаны настройки для анализатора кода (Pylint) и инструмента форматирования (YAPF). В третьей строке содержится инструкция, согласно которой VS Code отображает тонкую вертикальную линию на позиции 80, поскольку PEP8 рекомендует максимальную длину строки в 79 символов. Это помогает мне визуально представить, где будет перенос кода на следующую строку. В четвертой строке содержится инструкция к VS Code запускать YAPF каждый раз, как я сохраняю код. Это очень удобно! Можно писать код, не задумываясь, как он выглядит: достаточно просто нажать Ctrl + S, чтобы форматировать его как надо.
Теперь давайте поговорим о пользовательских настройках VS Code. Чтобы изменить их, нажмите иконку в виде шестеренки в нижнем левом углу окна VS Code и выберите «Settings»:
В открывшемся редакторе настроек можно найти любые настройки VS Code. По умолчанию любые изменения, сделанные в этом редакторе, применяются к VS Code на компьютере, за которым вы сейчас работаете. Чтобы обеспечить единообразие настроек на локальном компьютере, в Codespaces и на остальных устройствах, на которых вы используете VS Code, я рекомендую включить “Settings Sync”. Так все ваши настройки окажутся связаны с учетной записью GitHub или Microsoft и будут синхронизироваться каждый раз, когда вы открываете VS Code в этом аккаунте. Чтобы включить “Settings Sync”, снова щелкните по шестеренке в окне VS Code и выберите “Turn on Settings Sync…”:
В редакторе откроется диалог, в котором можно выбрать, какие именно настройки следует синхронизировать. Я обычно ставлю все галочки:
Потом нужно нажать кнопку «Sign in & Turn on», выбрать учетную запись GitHub или Microsoft, и начнется синхронизация настроек. Если окажется, что настройки на разных устройствах противоречат друг другу, нужно выбрать, какой набор считать главным. Настройки отображаются не только в редакторе, их можно посмотреть и в формате JSON, перейдя в «Command Palette» и выбрав «Preferences: Open Settings (JSON)». Мне нравится использовать вкладку «Settings» для просмотра всех доступных настроек и файл JSON, чтобы быстро просмотреть все настройки, в которые я вносила изменения.
Мои пользовательские настройки VS Code не ограничены только проектами машинного обучения — они применяются к каждому проекту! Например, именно здесь я задаю цветовую схему пользовательского интерфейса VS Code (
"workbench.colorTheme": "Default Dark+"
) и даю VS Code указание показывать мне по-разному расставленные пробелы при сравнении двух файлов ("diffEditor.ignoreTrimWhitespace": false
).Я давняя поклонница «Settings Sync», потому что таким образом можно переустановить код Visual Studio и сразу же начать работать в знакомой среде. Но в Codespaces это важно как никогда. Благодаря ей работать в облачной среде так же комфортно, как и в локальной.
Шаблон GitHub
Создавать шаблоны GitHub на базе проекта просто: перейдите в «Settings» проекта и поставьте галочку в поле «Template repository»:
Подробнее можно прочитать об этом в документации.
В шаблонах GitHub содержатся GitHub Actions, которые позволяют задавать пользовательские настройки для проектов, так или иначе генерируемых на базе шаблона. Рабочий процесс GitHub Action определяется в файле YAML и в общем виде состоит из события-триггера и последовательности действий в GitHub, которая выполняется, когда запускается событие. Шаблон GitHub, о котором я рассказываю в этой статье, содержит рабочий процесс GitHub Action, запускающийся, когда из шаблона создается новый проект, и переименовывающий директорию среды conda и исходного кода по имени репозитория.
https://github.com/bstollnitz/ml-template/blob/main/.github/workflows/initial_setup.yml
# This GitHub Action workflow runs when a new repository is created from this
# template repo.
name: Initial Setup
on:
push:
branches:
- main
env:
REPO_NAME: ${{ github.event.repository.name }}
jobs:
initial_setup:
runs-on: ubuntu-latest
if: ${{ github.event.created }}
steps:
# GitHub Action marketplace: https://github.com/marketplace/actions/checkout
- name: Checkout
uses: actions/checkout@v3
# GitHub Action marketplace: https://github.com/marketplace/actions/find-and-replace
- name: Replace token with repository name
uses: jacobtomlinson/gha-find-replace@v2
with:
find: "<GITHUB_REPOSITORY>"
replace: ${{ env.REPO_NAME }}
exclude: "{.git,.github}/**"
- name: Rename source code directory to repository name
run: mv ml-template $REPO_NAME
# GitHub Action marketplace: https://github.com/marketplace/actions/git-auto-commit
- name: Commit all changes
uses: stefanzweifel/git-auto-commit-action@v4
with:
commit_message: Initial repo setup
commit_options: "--no-verify --signoff"
Рабочие процессы GitHub Action всегда добавляются в директорию .github/workflows. В нашем рабочем процессе четыре раздела: имя, событие-триггер, раздел для переменных среды и раздел с заданиями, содержащий действия, которые мы хотим запускать.
Нам нужно, чтобы рабочий процесс запустился в первый раз, когда мы выполняем push файлов в проект, созданный из этого шаблона. Для этого нужно указать, что событие-триггер — это push в главную ветвь. Потом дорабатываем процесс с помощью оператора
if
, согласно которому нам нужен первый push, создающий проект. Оператор if
получает доступ к контексту GitHub, в котором содержится информация о выполнении рабочего процесса. Затем он получает свойство события — в данном случае событие push — и возвращает все полезные данные о его веб-перехватчике. И наконец доходит до Created key веб-перехватчика, что является истинным для первого push репозитория.После запуска события нужно переименовать папку ml-template (в которой содержится исходный код) и среду conda по имени репозитория. Для этого нужно последовательно выполнить четыре шага в задании:
- Действие Checkout, которое проверяет код в новом репозитории, созданном из шаблона.
- Заменить все экземпляры токена
<GITHUB_REPOSITORY>
на имя репозитория с помощью действия jacobtomlinson/gha-find-replace. В нашем сценарии есть только один экземпляр токена — это имя среды conda в файле environment.yml.
- Переименовать template по имени репозитория. Именно в эту папку вы будете добавлять исходный код.
- Commit всех изменений в репозитории с помощью действия stefanzweifel/git-auto-commit-action.
Почему я решила использовать именно эти действия? Я нашла их (все, кроме команды переименования) на маркетплейсе GitHub Action. Очень удобно! Не нужно заново изобретать колесо!
Если вы создаете репозиторий из шаблона, проверьте директорию, созданную на корневом уровне: ее имя должно соответствовать имени, выбранному для репозитория. Аналогично и для имени среды conda, которое можно найти в файле environment.yml. Вы заметите, что в репозиторий добавился файл YAML с рабочим процессом из действий. На этом этапе при необходимости можно удалить всю директорию .github/workflows.
Команда VK Cloud развивает ML Platform. Она помогает построить процесс работы с ML-моделями от дизайна до деплоя, контролировать качество экспериментов и моделей. Новым пользователям даем бонус 3000 рублей на тестирование.