Каждый иногда встречается с НЕинтересными для него задачами, но необходимыми к выполнению. Для некоторых это кропотливые и нудные задачи, для некоторых, задачи, требующие смелых решений. Бывает просто лень, хотя это тоже сложное чувство, которое можно разложить на составляющие и анализировать отдельно. Но о лени поговорим как-нибудь в другой раз.
Меня вгоняет в чувство безнадежности задачи, которые не четко формализованы, или которые поставлены нечетко: «Сделай то, не знаю что».
Например, прилетела мне задача:
Есть временной ряд и есть «ощущение», что если разметить его «определенным» образом, то можно обучить модель с «хорошим» качеством. И такая разметка и сама модель будет нести «некий» физический смысл, а сам подход будет работать на «других» данных.
Вот всё что в кавычках — это неопределенные или слабо определенные параметры. Какое-то уравнение с огромным числом переменных, в котором даже «равенство» не определено.
Вы можете сказать «бывает, чё ныть». Садись, декомпозируй и решай.
И так-то оно так, но тут вступает в игру индивидуальный контекст. Он, конечно, на то и индивидуальный, но я попробую вас в него погрузить.
Мой контекст:
Неимоверное количество задач в бэклоге. Задачи есть всегда. За последние 5 лет не было момента, когда был бы пустой бэклог.
Непонятно как декомпозировать данную задачу. Это как будто ты пытаешься дрессировать теорию хаоса. Когда параметры как-будто независимы, но на деле всё взаимосвязано. Меняешь один параметр, меняются все остальные. Тут нужно решать задачу комплексно.
Я терпеть не могу рутинные задачи (вроде разметки), то есть где нужно делать, а не думать. Такие, знаете, где ты можешь включить два-три фильма на фоне и делать задачу. Моментально начинаю закипать. Мозг должен работать.
Кто так и не погрузился в контекст (или кому это чуждо), приведу пример из детства, который знаком каждому.
Пример из детства
Вы ребенок лет 12-ти. У вас выходной день от школы, и вы вышли гулять с друзьями — играть в футбол. Вышли играть в полдень. Сыграли матч — выиграли. Ещё один — проиграли, снова выиграли и снова проиграли. И вот отрыв уже в 3 очка, появляется азарт оторваться на 4 очка. Снова выигрыши и проигрыши, и снова азарт внутри вас всё кричит "Хочу разрыв в 5 очков". Снова выигрыши и проигрыши, и тут вроде появился шанс обыграть эту дурацкую команду соперников наконец с разрывом в 5 очков...
И именно в этот момент, вы слышите, как из окна вас зовет мать. Настойчиво. Очень настойчиво. Кричит уже не первый раз, так как вы наконец смогли услышать её. И что кричит? Конечно "Пора домой, уже поздно..."
Вы ей кричите, в возбуждении, мол, мам, игра горит, очень и очень нужно выиграть с разрывом в 5 очков. В ответ слышите «Ты и так весь день играешь. И так уже большой разрыв и вообще ты молодец. Но пора домой! Точка!»
Ну вот и как объяснить матери все свои чувства, весь тот азарт, который в вас полыхает?
Мой подход (как я подхожу к разрешению таких ситуаций)
Чтобы не размусоливать, попробовал сразу формализовать подход. Тут отмечу, что данная схема не касается коротких задач. Про них я отдельно отпишу, но хотелось бы сфокусироваться на проблеме мотивации делать более тяжелые и трудоемкие задачи.

Итак, начинается всё с верхнего правого блока. Чтобы применять подход, нужно осознать что произошел именно этот кейс. Что именно ЭТА задача заставляет прокрастинировать. А это не так просто:
Долгое время может казаться, что ты игнорируешь её, потому что действительно есть другие важные дела.
Утром не хочется на неё тратить время, а вечером нет сил, чтобы погружаться в неё.
Невозможно уместить эту задачу в свободное окно, поэтому ты ждешь большое свободное окно, чтобы за раз разобраться с задачей (ха-ха, самое подлое).
И таких причин может быть много, а спасти может следующее:
Дедлайн.
Опыт детекции этого цикла. Что ты находишь не причины, а отмазки, чтобы её не делать.
В целом, и та и другая причины норм, вот только если пришел дедлайн, то мой подход менее действенен (просто времени на креатив и наслаждения не останется).

Вот у вас есть ещё определенное время до дедлайна, и вы пришли в блок «тяги». Зачем это делать? А как вы по другому поймете, какой процесс или ощущение нужно перекрыть?
Например, не хочется дизайнить страницу, почему? Не потому что вам вообще ничего не нравится, а потому что заказчик хочет странный шрифт на этой странице, который непонятно как выбрать. И вам нужно придумать как забавно и интересно закрыть именно этот пункт, чтобы остальное пошло.

Блок «зажигалка». Вообще можно и без него, если можно с «тягой» по другому разобраться, но у меня без этого блока не выходит обычно. Нужна конфетка, а иногда большая конфетка, чтобы сдвинуть противную задачу. Важный момент, вам нужна будет хоть какая-то корреляция между «зажигалкой» и вашей задачей, иначе к задаче вы так и не приступите, а просто снова отвлечетесь.
Например, «тяга» — это написание документации. А «зажигалкой» может быть тестирование нового инструмента для рисования блок-схем. Я в свое время так и полюбил рисовать блок схемы для документации и презентаций, тестируя excalidraw.
И в конце генерируете идеи, которые максимизируют «зажигалки» и минимизируют «тяги». По итогу я составляю таблицу (тут просто обобщенный пример, ниже будет пример с моим случаем, где я прокомментирую цифры).
Идея | Корреляция с задачей | Корреляция с зажигалками (максимизируем) | Насколько это решение — тяга (минимизируем) | ||
Зажигалка 1 | Зажигалка 2 | Тяга 1 | Тяга 2 | ||
Идея 1 | 9/10 | 5/10 | 9/10 | 1/10 | 1/10 |
Идея 2 | 6/10 | 8/10 | 8/10 | 6/10 | 6/10 |
Самое сложное, понять на что ориентироваться (много цифр). У меня следующий приоритет выбора:
Как сильно зажигает.
Корреляция с задачей.
Закрытие тяг.
Обычно, как только сделал таблицу и разобрал «тяги» и «зажигалки», то уже понимаешь, что будешь делать. Табличка же нужна, чтобы случайно не начать делать то, что не имеет корреляцию с задачей.
Применение подхода к моей задаче
Тут коротко постараюсь. Сначала напомню мою задачу: есть временной ряд и есть «ощущение», что если разметить его «определенным» способом, то можно обучить модель с «хорошим» качеством. И такая разметка и сама модель будет нести «некий» физический смысл, а сам подход будет работать на «других» данных.
Мои «тяги»:
Скучно. Рутинная работа, вроде переразметки, уничтожает меня. Эту тягу нужно обязательно закрыть.
Неопределенно. Нужен четкий pipeline, чтобы в процессе реализации не размусоливать о смысле происходящего, а итеративно выполнять шаги для финального анализа.
Долго. Хочется закрыть задачу максимально быстро.
Мои «зажигалки»:
Писать код. Редко получается кодить, скучаю по коддингу.
Новая технология или библиотека. Очень люблю пробовать новые технологии.
Ну и идеи, которые удалось придумать:
Разметить ручками, прям прописать
if 1.5 < tsne_1 < 3.5 and 0 < tsne_2 < 5
, то это класс «аномалия» и т. д..Написать алгоритм для разметки. Например, как таргет мы просто берем 10 точек до аварии. Или на t-SNE измеряем дистанцию, и берем ближайшие 10 точек к аварии.
Найти тулзу на просторах интернета, некий интерактивный редактор для разметки.
Разработать графический интерактивный разметчик самому.
Идея | Корреляция с задачей | Корреляция с зажигалками (максимизируем) | Насколько это решение — тяга (минимизируем) | |||
Писать код | Что-то новое | Скучно | Неопределенно | Долго | ||
Разметка ручками | 10 | 0 | 0 | 10 | 10 | 7 |
Авто алгоритм разметки | 10 | 3 | 3 | 9 | 7 | 5 |
Поиск готового решения разметки | 8 | 3 | 10 | 6 | ? | ? |
Написать визуальный разметчик | 7 | 10 | 10 | 3 | 0 | 5 |
В первую очередь я думал о корреляции с «зажигалками». Для меня это очень важно, чтобы я горел чем-то, когда решаю задачу. Корреляция с задачей — если решение больше 0.5, то норм. Внутреннее состояние важнее. Ну и в конце, лучше бы чтобы это закрывало «тяги». Хотя обычно «тяги» обратны «зажигалкам», и если там хорошо, то и в «тягах» будут хорошие цифры.
Я ставил «?» - где невозможно оценить. Чем больше вопросов для решения, тем сомнительнее его выбор.
Написание визуального разметчика
Мы с командой часто в работе используем для визуализации plotly. Его основной плюс — это интерактивность. Есть инструментальная панель, через которую ты можешь скейлить график, а также при наведении на точки можно посмотреть их мета-информацию. И я подумал, что есть большая вероятность добавить «колбэки» где-то рядом.

Запрос в поисковике «plotly callback», первая ссылка ведет на эту страницу. Для создания интерфейса и callbacks они используют dash библиотеку.
Если лень тыкать, фрагмент кода в спойлере
app = Dash(__name__) # поднимает веб-сервер на Flask
app.layout = html.Div([
dcc.Graph(id='graph-with-slider'), # элемент для графика
dcc.Slider(id='year-slider', ...) # элемент управления
])
@callback(
Output('graph-with-slider', 'figure'), # обновить график
Input('year-slider', 'value') # стриггерить функцию после изменения
)
def update_figure(selected_year):
fig = px.scatter(...)
return fig
То есть можно настроить вызов определенной функции после изменения определенного инпута. Функция обновляет также атрибуты указанных элементов после завершения.
У меня пока нет инпута, но у меня есть график. В начале я хотел прям рисовать (о да, там можно даже рисовать). Но потом увидел замечательную функцию выделения (box select или lasso select). Поэтому следующий запрос в гугл был «dask plotly select event», который дал мне эту страницу. Событие «selectedData» триггерится, когда пользователь выделяет область на графике. Но что ещё потряснее, в колбэк передается «selected_data» - те фигуры, которые попали в выделенную область.
Осталось последнее — набор элементов управления. Тут сразу буду крепить конечные интерфейсы. Начнем с загрузки данных:

Файл загружается в *.csv формате, либо выбирается из списка ранее загруженных. Все загруженные файлы складываются в папку data/input (или какую вы в .env пропишете). Можно исключить столбцы, если они мешают вашей картинке (в моем случае, это столбец «date»). После выбора таргета начинается визуализация:

Визуализация производится путем разложения исходных (слегка предобработанных) данных на две компоненты. Пока добавил один метод, мне его хватило. Логика разметки следующая:
Вводите новое значение таргета в поле «Input label value for selected».
Выбираете на графике инструмент «Box select» или «Lasso select».
Выделяете точки, для которых хотите изменить значения таргета.
Вуаля — значения таргетов изменено, а снизу показывается, сколько значений было изменено.
Выглядит это вот так:

И напоследок оставлю ссылку на репо.
Как итог
Я закрыл задачу.
Эта штука позволила быстро переразмечать и тестировать много гипотез, и на одной из итераций получились нужные результаты.
Само собой подход не уникальный, но в моем случае он стабильно работает, хотя сначала придется побороться с собой. Что я полюбил за последние 2 года, и что я сделал, с помощью этого подхода:
Писать документацию по ГОСТу (нашел нужные зажигалки).
Рисовать блок-диаграммы (нашел любимый визуализатор).
Формализовать и подробно декомпозировать задачи не кодя (тут долго искал мотивации, но в итоге вышло).
Решил задачу, про которую написана статья.