Открытие вчерашнего вечера:
pdbpp
, т.е. pdb++ - еще один python-дебаггер с автодополнением и прочими обязательными фичами. Я обычно пользовался ipdb
, но у pdbpp
есть одна исключительно полезная фича - он заменяет дефолтный pdb
в интеграциях. Значит, можно, например, легко влезть дебаггером в падающий тест.$ cat test_me.py
def test_something():
x = 5
assert False
$ pytest --pdb
======= test session starts =======
platform linux -- Python 3.6.6, pytest-5.1.2, py-1.8.0, pluggy-0.13.0
rootdir: /home/arseny/candy-store/adhoc
plugins: cov-2.7.1
collected 1 item
test_me.py F
>>>>>>> traceback >>>>>>>
def test_something():
x = 5
> assert False
E assert False
test_me.py:3: AssertionError
>>>>>>> entering PDB >>>>>>>
>>>>>>> PDB post_mortem (IO-capturing turned off) >>>>>>>
[11] > /home/arseny/candy-store/adhoc/test_me.py(3)test_something()
-> assert False
6 frames hidden (try 'help hidden_frames')
(Pdb++) x
5
(Pdb++)
Недавно в ods.ai случилось некоторое нашествие постов (например) почти по шаблону "подскажите самую крутую нейросетку для {узкая_задача}". Там в комментариях и родилась простая и понятная псевдоформула для подобных вопросов:
Иными словами, чтобы получить крутое решение на своей непопулярной подзадаче, нужно взять state of the art в задаче на более популярном домене (например, вместо детекции рук посмотреть подходы к детекции лиц) и закидать ее хорошими данными из своего домена.
sota(task, domain) ≈ sota(task, most_popular_domain) + sota(domain_dataset)
.Иными словами, чтобы получить крутое решение на своей непопулярной подзадаче, нужно взять state of the art в задаче на более популярном домене (например, вместо детекции рук посмотреть подходы к детекции лиц) и закидать ее хорошими данными из своего домена.
siberia.slides.html
4 MB
Слайды с моего выступления на сибирском датафесте
На Data Fest Siberia несколько раз обнаружил воспроизводимый способ задавать плохие вопросы из зала. Шаблон примерно такой:
Докладчик: у нас была маленькая команда, мало данных, не хватало железа, и еще какие-то проблемы. Превозмогая невзгоды, мы из говна и палок смогли собрать такой-то пайплайн, и он заработал! 🎉 Спасибо за внимание.
Слушатель: а почему вы не использовали SuperGAN, AlphaPlus RL и еще какие-то баззворды?
Докладчик: у нас была маленькая команда, мало данных, не хватало железа, и еще какие-то проблемы. Превозмогая невзгоды, мы из говна и палок смогли собрать такой-то пайплайн, и он заработал! 🎉 Спасибо за внимание.
Слушатель: а почему вы не использовали SuperGAN, AlphaPlus RL и еще какие-то баззворды?
У меня был совершенно чудесный коллега, который обычно не читал статьи, а просматривал по диагонали, через 30 секунд восклицал "А, ну тут все понятно" и начинал имплементировать ровно то, что успевал уловить (и додумать) за это время. Эдакая платоновская пещера.
Недостающие детали он зачастую додумывал на ходу. С ключевой идеей иногда случались казусы: например, однажды он взял ее из некой схемы, проигнорировав подпись. Подпись гласила что-то вроде "а вот так делали раньше, и сейчас это давно неактуально".
Чудо случалось дальше: несмотря на вольную трактовку, результаты обычно получались хорошими, пусть часто и ортогональными статье.
Так вот, попалась мне недавно несложная, казалось бы, задача, требующая какого-то метрик лернинга. Я бегло посмотрел на реализацию какого-то тоже излишне творческого человека, совместил его идеи со своими фантазиями на тему того, как сиамские сети должны работать, и все это закодил. Результат немного предсказуем: я оверфитнулся,обосрался и заплакал.
Все закончилось хорошо: советы более опытного в метрик лернинге человека и вдумчивое чтение матчасти помогли все починить и обучить (hard example mining рулит, если что). А мораль простая: если ты почему-то думаешь, что понимаешь как что-то работает, это совсем не всегда значит, что можно (высокомерно) игнорировать написанное умными людьми.
Недостающие детали он зачастую додумывал на ходу. С ключевой идеей иногда случались казусы: например, однажды он взял ее из некой схемы, проигнорировав подпись. Подпись гласила что-то вроде "а вот так делали раньше, и сейчас это давно неактуально".
Чудо случалось дальше: несмотря на вольную трактовку, результаты обычно получались хорошими, пусть часто и ортогональными статье.
Так вот, попалась мне недавно несложная, казалось бы, задача, требующая какого-то метрик лернинга. Я бегло посмотрел на реализацию какого-то тоже излишне творческого человека, совместил его идеи со своими фантазиями на тему того, как сиамские сети должны работать, и все это закодил. Результат немного предсказуем: я оверфитнулся,
Все закончилось хорошо: советы более опытного в метрик лернинге человека и вдумчивое чтение матчасти помогли все починить и обучить (hard example mining рулит, если что). А мораль простая: если ты почему-то думаешь, что понимаешь как что-то работает, это совсем не всегда значит, что можно (высокомерно) игнорировать написанное умными людьми.
продуктовый computer vision со стороны: нужно читать свежие статьи c CVPR и ICCV и имплементировать моднейшие архитектуры
продуктовый computer vision изнутри: бля, опять инстаграм забанил все скраперы
продуктовый computer vision изнутри: бля, опять инстаграм забанил все скраперы
Видел недавно образец карго-культа с привкусом ООП.
Дано: старый плохой код, состоящий из двух функций
Задача: отрефакторить, в первую очередь сделать модульно и тестируемо.
Результат выглядел примерно так:
Дано: старый плохой код, состоящий из двух функций
process
и upload_to_s3
, примерно 500 строк в сумме. Задача: отрефакторить, в первую очередь сделать модульно и тестируемо.
Результат выглядел примерно так:
class AbstractProcessor:Monkey see, monkey do.
def __init__():
pass
@abc.abstractmethod
def process():
pass
@abc.abstractmethod
def upload_to_s3():
pass
class Processor:
def __init__():
super().__init__()
def process():
# 300 строк старого говна
def upload_to_s3():
# 200 строк старого говна
#мысли_из_душа
Придумал бесполезную метрику: соотношение yaml-кода (или где вы там храните свои конфигурации) к python-коду для одного ML эксперимента.
Если для каждого нового эксперимента нужно писать много кода и мало конфигурации, представляются такие варианты:
- эксперименты исключительно передовые (или новая задача в рамках проекта, или кардинально новый подход к ее решению);
- инфраструктура находится где-то между "оставляет желать лучшего" и "ебаный колхоз".
Такая двойственность делает метрику абсолютно бесполезной. А раз так, то это и не метрика, а просто херня какая-то.
Придумал бесполезную метрику: соотношение yaml-кода (или где вы там храните свои конфигурации) к python-коду для одного ML эксперимента.
Если для каждого нового эксперимента нужно писать много кода и мало конфигурации, представляются такие варианты:
- эксперименты исключительно передовые (или новая задача в рамках проекта, или кардинально новый подход к ее решению);
- инфраструктура находится где-то между "оставляет желать лучшего" и "ебаный колхоз".
Такая двойственность делает метрику абсолютно бесполезной. А раз так, то это и не метрика, а просто херня какая-то.
Если бы я стремился прославиться в computer vision тусовке, я бы начал с написания human-friendly обертки вокруг python-обертки вокруг OpenCV.
Понятно, что хардкорные плюсовики привыкли к нечитаемым ошибкам, но нам, нежным хипстерам, очень грустно от этих всяких
Понятно, что хардкорные плюсовики привыкли к нечитаемым ошибкам, но нам, нежным хипстерам, очень грустно от этих всяких
*** SystemError: <built-in function> returned NULL without setting an error
Я сейчас на той стадии технической (не)зрелости, что довольно много думаю об абстракциях. Точнее, о нужном и допустимом уровне абстракции для разных задач.
Если спуститься слишком низко, то для любой фигни нужно будет изобретать свой велосипед, а для него - свои колеса. В силу ограниченности наших умов, эти колеса иногда будут квадратными. Ну и количество времени, необходимое для любой задачи, ожидаемо устремится в бесконечность.
Если подняться слишком высоко, то программирование превращается в шаманство. Трижды стукни в бубен в полнолуние, переодевшись в петуха, и тогда твои тесты позеленеют, а логистическая регрессия покажет точность 146%.
Хороший пример: https://habr.com/ru/post/471282/#comment_20748088. Статья уже слегка отредактирована, потому перескажу вкратце историю (можно частично восстановить из комментариев): чувак вооружился сверхвысокоуровневой абстракцией fastai, забил на train/val/test разбиение (библиотека все сделает за него), получил близкие к идеальным результаты и начал хвастаться, как легко превзойти предыдущий state of the art.
Кажется, что опыт именно тем и полезен: со временем инженер примерно чувствует нужный уровень абстракции для задачи. Настоящие сеньоры - те, чьи абстракции протекают не сразу.
Если вы знаете, что почитать на эту тему - напишите мне (@arsenyinfo) и посоветуйте!
Если спуститься слишком низко, то для любой фигни нужно будет изобретать свой велосипед, а для него - свои колеса. В силу ограниченности наших умов, эти колеса иногда будут квадратными. Ну и количество времени, необходимое для любой задачи, ожидаемо устремится в бесконечность.
Если подняться слишком высоко, то программирование превращается в шаманство. Трижды стукни в бубен в полнолуние, переодевшись в петуха, и тогда твои тесты позеленеют, а логистическая регрессия покажет точность 146%.
Хороший пример: https://habr.com/ru/post/471282/#comment_20748088. Статья уже слегка отредактирована, потому перескажу вкратце историю (можно частично восстановить из комментариев): чувак вооружился сверхвысокоуровневой абстракцией fastai, забил на train/val/test разбиение (библиотека все сделает за него), получил близкие к идеальным результаты и начал хвастаться, как легко превзойти предыдущий state of the art.
Кажется, что опыт именно тем и полезен: со временем инженер примерно чувствует нужный уровень абстракции для задачи. Настоящие сеньоры - те, чьи абстракции протекают не сразу.
Если вы знаете, что почитать на эту тему - напишите мне (@arsenyinfo) и посоветуйте!
Классический шаблон вопроса на собеседовании: "у тебя есть неатомарный кусочек софта [примерное описание этого софта], и он работает плохо [сырое описание проблемы]. как исправить?". Например, в случае deep learning собеседования вопрос может быть сформулирован так: "у тебя есть пайплайн обучения сети, но она обучается слишком медленно. как ускорить?"
Если собеседуемый претендует на не совсем junior роль, от него ожидаются встречные вопросы. Например: что такое медленно? как это определили? почему это плохо и важно? В случае с обучением модели кто-то может иметь в виду просто некую неэффективность пайплайна в вакууме, а кто-то - несоответствие конкретным хотелкам (нужно обновлять модель ежедневно, а она тренируется три дня).
И уже после этого нужно отвечать. Слабые инженеры сразу говорят, что можно улучшить ("а давайте поменяем модель на более легкую!"), а сильные - набрасывают план, как находить слабые места и как их ранжировать ("определим, где у нас затык - для начала посмотрим утилизацию процессора, GPU и диска"). Это не всегда значит, что слабых нельзя нанимать, но наверняка какое-то время их придется кормить с ложечки и детально расписывать задачи.
Если собеседуемый претендует на не совсем junior роль, от него ожидаются встречные вопросы. Например: что такое медленно? как это определили? почему это плохо и важно? В случае с обучением модели кто-то может иметь в виду просто некую неэффективность пайплайна в вакууме, а кто-то - несоответствие конкретным хотелкам (нужно обновлять модель ежедневно, а она тренируется три дня).
И уже после этого нужно отвечать. Слабые инженеры сразу говорят, что можно улучшить ("а давайте поменяем модель на более легкую!"), а сильные - набрасывают план, как находить слабые места и как их ранжировать ("определим, где у нас затык - для начала посмотрим утилизацию процессора, GPU и диска"). Это не всегда значит, что слабых нельзя нанимать, но наверняка какое-то время их придется кормить с ложечки и детально расписывать задачи.
Хрестоматийный пример того, что иногда случается, если один человек делает машинлернинг, потом не глядя перекидывает результаты работы через стенку, чтобы кто-то другой вкрутил это в продакшен.
Дано: модель для сегментации, на выходе логиты. Человек, который должен прикрутить ее к продакшен приложению, слышал, что выход сегментации должен быть
После расследования обнаружилось, что постпроцессинг делался примерно так:
Дано: модель для сегментации, на выходе логиты. Человек, который должен прикрутить ее к продакшен приложению, слышал, что выход сегментации должен быть
[0..1]
, а значит, он должен добавить какой-то постпроцессинг.После расследования обнаружилось, что постпроцессинг делался примерно так:
std::clamp(x, 0, 1)
.Два дня боролся с утечкой памяти в доставшемся по наследству deep learning пайплайне. Оказалось, что на самом деле их две, а ведь в языках с автоматической очисткой памяти это довольно редкий зверь.
Первый лик нашелся относительно легко при помощи pympler. Дальше началось странное, потому что pympler не видел новые объекты, а память потихоньку утекала - медленно, но верно.
Для победы пришлось отбросить ковбойский подход "ща я тут дебаггером влезу, на код гляну и все быстро пойму" и перейти к divide and conquer:
- беру кусок пайплайна;
- вместо настоящего выполнения кэширую;
- смотрю, течет или нет.
После N итераций в подозреваемых остался один большой и запутанный модуль - все еще много. Смотреть глазами на графики потребления памяти стало сложно, глаз замылился. На картинке один из таких графиков, в качестве такого себе доказательства.
Пришлось добавить статистики и вместо графиков смотреть на p-value, что проще и не требует умственных усилий. Так удалось локализовать проблему до одной функции, изолировать ее и найти проблему: подвыборка из тензора по индексам оставляла неявный референс.
Мораль такая: даже если ты не разбираешься в проблеме, декомпозиция и базовая автоматизация (инструменты, склеенные скотчем) помогут.
Первый лик нашелся относительно легко при помощи pympler. Дальше началось странное, потому что pympler не видел новые объекты, а память потихоньку утекала - медленно, но верно.
Для победы пришлось отбросить ковбойский подход "ща я тут дебаггером влезу, на код гляну и все быстро пойму" и перейти к divide and conquer:
- беру кусок пайплайна;
- вместо настоящего выполнения кэширую;
- смотрю, течет или нет.
После N итераций в подозреваемых остался один большой и запутанный модуль - все еще много. Смотреть глазами на графики потребления памяти стало сложно, глаз замылился. На картинке один из таких графиков, в качестве такого себе доказательства.
Пришлось добавить статистики и вместо графиков смотреть на p-value, что проще и не требует умственных усилий. Так удалось локализовать проблему до одной функции, изолировать ее и найти проблему: подвыборка из тензора по индексам оставляла неявный референс.
Мораль такая: даже если ты не разбираешься в проблеме, декомпозиция и базовая автоматизация (инструменты, склеенные скотчем) помогут.
Полгода назад я выступал на Bulbacon и, отвечая на вопросы, сказал что-то вроде: "Через год называть себя дата сайнтистом станет зашкваром", подразумевая дурную славу некачественного кода в духе "я тут чего-то нафигачил в jupyter notebook" и намекая, что всем машинлернерам стоит учиться писать более или менее чистый код.
Тем временем в Python developers survey 2019 появился провокационный вопрос.
Тем временем в Python developers survey 2019 появился провокационный вопрос.
Обнаружил сервис для не самых умных, но не безответственных unix-пользователей.
Например, гуглите какой-то свой вопрос, видите волшебную shell команду на StackOverflow с кучей непонятных флажков. Есть соблазн просто вбить в терминал, но голос разума говорит, что надо бы хотя бы поверхностно разобраться, что это за магия.
Собственно, для этого и нужен explain shell. Пример с классическим sudo rm -rf.
Например, гуглите какой-то свой вопрос, видите волшебную shell команду на StackOverflow с кучей непонятных флажков. Есть соблазн просто вбить в терминал, но голос разума говорит, что надо бы хотя бы поверхностно разобраться, что это за магия.
Собственно, для этого и нужен explain shell. Пример с классическим sudo rm -rf.