11 мин чтения
9 сентября 2020 г.
Здесь, на Kaggle, мы рады продемонстрировать работу наших грандмастеров. Этот пост написал Владимир Игловиков, и он полон советов, которые, как он жалеет, никто не дал ему, когда он был активен на Kaggle. Оригинал поста можно найти в блоге Ternaus Blog.
Нажмите Enter или кликните, чтобы просмотреть изображение в полном размере
Введение
Я участвовал в соревнованиях по машинному обучению (ML) на Kaggle и других платформах, чтобы «накачать мышцы» в машинном обучении. Я занимал 19-е место в мировом рейтинге и получил титул Kaggle Grandmaster.
Каждый вызов в области ML заканчивался новыми знаниями, кодом и весами моделей.
Мне нравилось узнавать новое, но я игнорировал ценность, которую могли бы принести старые ML-пайплайны. Код оставался в приватных репозиториях GitHub. Веса были разбросаны по всему жесткому диску. В конце концов, всё это удалялось.
Эта ситуация характерна не только для Kaggle. Та же история и в академической среде. Студент обучает модель, пишет статью. После того как её принимают на конференцию, пайплайны забрасываются, артефакты обучения удаляются, и студент идет дальше.
В этой статье речь пойдет о небольших шагах, которые можно предпринять после завершения каждого ML-вызова.
Эти шаги помогут:
- Улучшить технические знания.
- Создать личный бренд.
- Улучшить карьерные возможности.
- Сделать мир лучше :)
В качестве примера я буду использовать репозиторий https://github.com/ternaus/retinaface
Он не был частью соревнования на Kaggle, но был создан, чтобы проиллюстрировать эту историю.
I. +5 мин: Выложите код в публичный репозиторий GitHub
Скорее всего, код уже есть на GitHub, но в приватном репозитории.
Что вы потеряете, если сделаете его публичным?
Бывают ситуации, когда приватное должно оставаться приватным, но в случае с вашим пет-проектом, решением для Kaggle или научной статьей это может быть не так.
Самое распространенное препятствие, которое я видел: люди полагают, что весь публичный код должен быть идеальным и что их будут осуждать, если это не так.
На самом деле, всем всё равно. Просто сделайте это. Выложите как есть, без какой-либо полировки.
Публикация кода — это важный психологический шаг. Выпуск неидеального кода — это уверенный, смелый поступок.
К тому же, все последующие шаги основываются на этом.
Пример: https://github.com/ternaus/retinaface
II. +20 мин: Улучшите читаемость
Вы можете улучшить читаемость своего кода на Python, добавив форматировщики синтаксиса и линтеры.
Это несложно и не отнимает много времени. Линтеры и форматировщики не превратят плохой код в хороший, но читаемость повысится. Относитесь к исправлению синтаксиса как к базовой гигиене. Это как чистить зубы, только для кода.
Я написал пост в блоге на эту тему под названием «Девять простых шагов для более красивого кода на Python». Не стесняйтесь ознакомиться.
Шаг 1: конфигурационные файлы
Добавьте эти файлы в корень вашего репозитория.
- setup.cfg — конфигурация для flake8 и mypy.
- pyproject.toml — конфигурация для black.
Шаг 2: зависимости
Установите необходимые библиотеки с помощью
Шаг 3: black
Существует 100500 способов форматирования кода. Форматировщики, такие как black или yapf, изменяют код, чтобы он соответствовал заранее определенному набору правил.
Проще читать кодовую базу, у которой есть определенные стандарты. Когда вы часами работаете над кодом и вам нужно переключаться между разными стилями программирования, это истощает «энергию силы воли» — не нужно делать это без веской причины.
Запуск
переформатирует все файлы Python в соответствии с набором правил black.
Шаг 4: flake8
Запуск
не изменит код, но проверит его на наличие синтаксических ошибок и выведет их на экран.
Исправьте их.
Шаг 5: mypy
В Python нет обязательной статической типизации, но рекомендуется добавлять типы к аргументам функций и возвращаемым значениям.
Например:
Вам следует добавить типизацию в код.
- Это облегчает чтение кода.
- Вы можете использовать пакет mypy для проверки согласованности аргументов и типов функций.
После обновления кода запустите mypy для всего репозитория:
Если mypy нашел проблемы — исправьте их.
Шаг 6: pre-commit hook
Постоянно запускать flake8, black, mypy вручную — утомительно.
Существует инструмент под названием pre-commit hook, который решает эту проблему.
Чтобы включить его, скопируйте этот файл в свой репозиторий: .pre-commit-config.yaml.
Вам нужно установить пакет pre-commit на свой компьютер с помощью:
И инициализировать его:
Теперь всё готово.
С этого момента при каждом коммите будет запускаться набор проверок, и коммит не пройдет, если что-то не так.
Главное отличие от ручного запуска black, flake8, mypy заключается в том, что он не просит вас исправить проблемы, а заставляет это сделать. Следовательно, не тратится «энергия силы воли».
Шаг 7: Github Actions
Вы добавили проверки в pre-commit hook и запускаете их локально. Но вам нужна вторая линия обороны. Вам нужно, чтобы GitHub запускал эти проверки при каждом pull request.
Способ сделать это — добавить файл .github/workflows/ci.yaml в репозиторий.
Там есть строки:
которые говорят GitHub, что проверять.
Я также рекомендую отказаться от практики отправки кода напрямую в ветку master.
Создайте новую ветку, измените код, сделайте коммит, отправьте на Github, создайте pull request и слейте его в master.
Это стандарт в индустрии, но он крайне редко встречается в академической среде и среди участников Kaggle.
Если вы не знакомы с этими инструментами, может потребоваться более 20 минут, чтобы добавить их и исправить ошибки и предупреждения.
Запомните это время. В следующем проекте добавьте эти проверки в первом коммите, когда код еще не написан. С этого момента каждый маленький коммит будет проверяться, и вам нужно будет исправлять максимум пару строк кода каждый раз: крошечные накладные расходы, отличная привычка.
Я также рекомендую прочитать книгу «Атомные привычки: Как приобрести хорошие привычки и избавиться от плохих». В ней рассказывается о небольших изменениях в поведении, которые повышают продуктивность и качество вашей жизни.
III. +20 мин: Создайте хороший readme
Хороший readme служит двум целям:
- Для себя: вы предполагаете, что никогда не будете использовать этот код, но «никогда не говори никогда». Вы будете, и вы не вспомните, что здесь происходило. Readme поможет вам.
- Для других: Readme — это инструмент продаж. Если люди не могут понять цель репозитория и какие проблемы он решает, они не будут его использовать. Вся проделанная вами работа не окажет положительного влияния на других.
Для репозиториев по машинному обучению минимум — это:
- Изображение, которое показывает, в чем заключалась задача и как вы её решили. Никаких слов не должно требоваться. Скорее всего, после работы над проблемой в течение нескольких недель у вас есть 100500 картинок. Они просто не являются частью Readme. Исправьте это.
- Где разместить данные.
- Как начать обучение.
- Как выполнить инференс.
Если вам нужно написать 100500 слов, чтобы описать, как запустить обучение или инференс, это тревожный сигнал. Вам нужно отрефакторить код и сделать его более удобным для пользователя. Люди часто спрашивают: как стать лучшим программистом? Это упражнение, которое помогает. Вам придется переписать свой код. Попробуйте взглянуть на свой Readme глазами другого человека.
Это также отличное упражнение, которое поможет выработать привычку смотреть на продукт с точки зрения пользователя.
Известная фраза: «Клиенты на первом месте».
Известная фраза: «Клиенты на первом месте».
Пример: Для retinaface я написал обертку над моделью, которая скрывает детали постобработки.
Постобработка — это довольно сложная задача, но она не представляет ценности для тех, кому она не нужна => у пользователей должна быть возможность ее скрыть.
Файл Readme, созданный на этом этапе, будет повторно использован позже, когда мы будем создавать библиотеку.
IV. +20 мин. Упростите использование вашей обученной модели
Я полагаю, вы пишете
для загрузки предобученных весов в модель.
Это работает, и шаги понятны, но для этого требуются веса на диске и знание того, где они находятся. Более элегантное решение — использовать функцию torch.utils.model_zoo.load_url в torchvision и аналогичные в TensorFlow или Keras.
Мы можем сделать следующее:
Если веса отсутствуют на диске, они загружаются из интернета и кэшируются на диске. Модель инициализируется, и веса загружаются.
Это удобно для пользователя, и именно это вы видите в библиотеках torchvision и timm.
Шаг 1: разместите веса предобученной модели
Это было самым большим препятствием для меня. Куда можно поместить веса модели, если вы не хотите связываться с AWS или GCP?
По-видимому, есть отличное решение, я бы сказал, лазейка. Вы можете добавить веса в релизы на GitHub.
Нажмите Enter или кликните, чтобы просмотреть изображение в полном размере
Лимит составляет 2 ГБ на файл, чего достаточно для большинства моделей глубокого обучения.
Шаг 2: напишите функцию, которая инициализирует модель и загружает веса
В моем случае:
Эта функциональность будет использована, когда мы будем создавать Colab Notebook и WebApp.
V. +20 мин. Создайте библиотеку
На этом этапе вы снижаете порог входа для использования вашей модели. Цель состоит в том, чтобы выполнять предсказания без
Шаг 1: добавьте необходимые зависимости в requirements.txt
Вы можете использовать
или обновить его вручную.
Шаг 2: измените структуру файлов репозитория
Создайте «основную папку», в моем случае она называется «retinaface», так же, как и репозиторий.
- Переместите туда весь важный код.
- Не перемещайте туда вспомогательные изображения, Readme, ноутбуки или тесты.
Делать это вручную и обновлять все импорты было бы утомительно. PyCharm или аналогичная IDE сделают это за вас.
Это распространенный способ структурирования кода в репозиториях.
Надеюсь, в будущем вы будете следовать этому шаблону с самого начала. Если вы хотите что-то более структурированное, ознакомьтесь с пакетом Cookie Cutter.
Шаг 3: добавьте файл конфигурации
- Добавьте setup.py в корень папки с содержимым, аналогичным setup.py
- Добавьте версию для пакета. В моем случае я добавил ее в файл init «основной» папки.
Шаг 4: создайте учетную запись на PyPI
Если у вас нет учетной записи на PyPI, самое время ее создать.
Шаг 5: соберите библиотеку и загрузите ее на PyPI
Вот и все. Ваш репозиторий стал библиотекой, и каждый сможет установить ее с помощью:
Если вы проверите страницу пакета на PyPI, вы увидите, что он использует Readme, который у вас есть в репозитории, для представления проекта.
Мы будем использовать функциональность этого шага для Google Colab и для веб-приложения.
VI. +20 мин. Создайте блокнот Google Colab
Хорошей практикой является добавление блокнота Jupyter в репозиторий, чтобы показать, как инициализировать модель и выполнить инференс. Пример.
Мы можем сделать лучше.
Мы включили «модную» инициализацию модели и магию pip install на предыдущих двух шагах. Давайте воспользуемся этим.
Мы можем создать блокнот Google Colab.
Теперь единственное, что нужно кому-то, чтобы поиграть с вашей моделью, — это браузер! Больше людей смогут ее протестировать.
Пример.
Не забудьте добавить ссылку на блокнот в ваш readme и обновить версию на PyPi.
VII. +20 мин. Создайте WebApp
Многие специалисты по анализу данных полагают, что создание веб-приложения — это сложная процедура, требующая специальных знаний.
Это предположение верно: веб-приложение для сложного проекта требует навыков, которых у специалистов по анализу данных может не быть.
Создать простое веб-приложение, демонстрирующее модель, легко.
Я создал отдельный репозиторий на GitHub для веб-приложения. Тем не менее, вы можете сделать это в своем репозитории с моделью.
Запись в блоге, описывающая детали: Как развернуть Streamlit на Heroku
Шаг 1: Добавьте код для приложения
Код
Менее 40 строк.
Шаг 2: добавьте файлы конфигурации
Вам нужно будет добавить файлы:
- setup.sh — вы можете использовать этот файл без изменений.
- Procfile — вам нужно будет изменить путь к файлу с приложением.
Шаг 3: добавьте requirements.txt
Шаг 4: зарегистрируйтесь на herokuapp
Шаг 5: отправьте код
Вы в эфире. Ознакомьтесь с примером на https://retinaface.herokuapp.com/
VIII. +4 часа: Напишите пост в блог
Многие люди недооценивают свою работу. Они полагают, что если они знают, как что-то сделать, то это знают все. Это не так.
Что для одного мусор, для другого — сокровище.
Что для одного мусор, для другого — сокровище.
Ваша статья поможет другим людям и улучшит ваши карьерные возможности.
Я работаю в Lyft, Level5, и применяю методы глубокого обучения к задачам беспилотного вождения. До Lyft я работал в агентстве по взысканию долгов TrueAccord. Вы можете прочитать о моем поиске работы в посте блога: «Смена карьеры на автономные транспортные средства».
Одной из причин, по которой я смог совершить этот карьерный сдвиг, является то, что я делился своими знаниями в постах блогов и на митапах. Это привлекло внимание рекрутеров и менеджеров по найму.
Сработало для меня — сработает и для вас.
Для машинного обучения я бы порекомендовал написать текст, который охватывает:
- В чем заключалась проблема?
- Как вы ее решили?
Если вы дочитали до этого момента и нашли эту статью полезной, вы можете сказать «Спасибо!», написав пост в блоге об одной из проблем машинного обучения, с которой вы столкнулись, и о том, как вы ее решили.
Пример:
- Задача: IEEE’s Signal Processing Society — Идентификация модели камеры
- Пост в блоге: Судебное глубокое обучение: Соревнование Kaggle по идентификации модели камеры
