Как структурировать проекты машинного обучения с помощью GitHub и VS Code: полная инструкция с настройками и шаблонами

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!



Хорошо продуманный процесс структурирования проектов машинного обучения поможет быстро создавать новые репозитории 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, то каждый раз выбираю один из трех вариантов:

  1. .devcontainer/devcontainer.json. GitHub Codespaces — это облачная среда разработки, запускающая код в контейнере. Мне очень нравится эта новая функция GitHub; если вы ею еще не пользуетесь, рекомендую обязательно попробовать. В этот файл я добавляю настройки, которые нужны для работы с конкретным проектом в GitHub codespace. Например, здесь удобно указывать заданный по умолчанию путь к интерпретатору Python для Codespace.
  2. .vscode/settings.json. В этот файл я добавляю настройки для конкретного проекта — вне зависимости от того, запускаю ли я проект на локальном ПК или в codespace. Именно здесь я указываю настройки анализатора и инструмента форматирования кода, что мы вскоре увидим.
  3. Пользовательские настройки 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 по имени репозитория. Для этого нужно последовательно выполнить четыре шага в задании:

  1. Действие Checkout, которое проверяет код в новом репозитории, созданном из шаблона.
  2. Заменить все экземпляры токена <GITHUB_REPOSITORY> на имя репозитория с помощью действия jacobtomlinson/gha-find-replace. В нашем сценарии есть только один экземпляр токена — это имя среды conda в файле environment.yml.
  3. Переименовать template по имени репозитория. Именно в эту папку вы будете добавлять исходный код.
  4. Commit всех изменений в репозитории с помощью действия stefanzweifel/git-auto-commit-action.

Почему я решила использовать именно эти действия? Я нашла их (все, кроме команды переименования) на маркетплейсе GitHub Action. Очень удобно! Не нужно заново изобретать колесо!

Если вы создаете репозиторий из шаблона, проверьте директорию, созданную на корневом уровне: ее имя должно соответствовать имени, выбранному для репозитория. Аналогично и для имени среды conda, которое можно найти в файле environment.yml. Вы заметите, что в репозиторий добавился файл YAML с рабочим процессом из действий. На этом этапе при необходимости можно удалить всю директорию .github/workflows.

Команда VK Cloud развивает ML Platform. Она помогает построить процесс работы с ML-моделями от дизайна до деплоя, контролировать качество экспериментов и моделей. Новым пользователям даем бонус 3000 рублей на тестирование.
Источник: https://habr.com/ru/companies/vk/articles/733000/


Интересные статьи

Интересные статьи

Перед вами вторая часть из серии материалов, состоящей из двух публикаций. Здесь я предлагаю практическое руководство по архитектуре ML-проекта, освоение которого позволит вам оценить качество автомат...
Результаты выборов в государственную думу, которые проходили 17-19 сентября 2021 вызывают сомнения у многих экспертов. Независимый электоральный аналитик Сергей Шпилькин оценил количество голосов, вбр...
Меня зовут Ярослав Голубев, я работаю в JetBrains Research, в лаборатории методов машинного обучения в программной инженерии. Некоторые мои коллеги уже писали здесь о своих проектах (напр...
Сегодня я расскажу о том, как быстро собрать отказоустойчивый кластер с балансировкой нагрузки с помощью keepalived на примере DNS-серверов. Читать дальше → ...
Программист тратит многие часы на разработку некоего функционала и на то, чтобы код соответствовал передовым практическим приёмам, принятым в той или иной среде. В эти часы не должно ...