Пять ключевых выводов, которые я сделал во время решения задачи по программированию, и как они применимы к анализу данных.
Делиться

В этом году я впервые принял участие в Advent of Code — серии ежедневных задач по программированию, публикуемых в течение декабря. Ежедневные задачи обычно содержат две головоломки, основанные на схожей проблеме. Хотя эти задачи и проблемы не похожи на типичные рабочие процессы в области анализа данных, я понял, что многие привычки, способы мышления и подходы к решению проблем, которые они поощряют, на удивление хорошо применимы к работе с данными. В этой статье я размышляю о пяти уроках, которые я извлек из участия в Advent of Code в этом году, и о том, как они применимы к анализу данных.
Для меня Advent of Code стал скорее контролируемой практикой, позволяющей повторить основы и отточить навыки программирования. Вы сосредотачиваетесь на главном, поскольку отсутствуют отвлекающие факторы, с которыми вы сталкиваетесь в повседневной работе: нет совещаний, меняющихся требований, общения с заинтересованными сторонами или накладных расходов на координацию. Вместо этого у вас есть простая и бинарная обратная связь: ваш ответ либо правильный, либо нет. Нет «почти правильного», нет способа объяснить результат и нет способа продать свое решение. В то же время у вас есть свобода и гибкость в выборе любого подхода, который вы считаете подходящим, если вы сможете прийти к правильному решению.
Работа в таких условиях была довольно сложной, но очень ценной, поскольку она также выявляла привычки. Учитывая, что места для двусмысленности практически нет, и нельзя скрывать свои ошибки, любые недостатки в работе сразу же обнаруживались. Со временем я также понял, что большинство моих неудач были связаны не столько с синтаксисом, выбором алгоритма или реализацией кода, сколько с тем, как я подходил к решению проблем до того, как начинал писать код. Ниже я поделюсь своими главными выводами из этого опыта.

Урок 1: Набросайте решение — подумайте, прежде чем писать код.
Одна из закономерностей, часто проявлявшихся во время Advent of Code, заключалась в моей склонности сразу переходить к реализации. Столкнувшись с новой проблемой, я обычно испытывал искушение немедленно начать кодирование и попытаться как можно быстрее найти решение. Как ни парадоксально, такой подход часто приводил к прямо противоположному результату. Например, я писал глубоко вложенный код для обработки граничных случаев, что увеличивало время выполнения кода, не понимая, что существует гораздо более простое решение.
В итоге мне помогло то, что перед началом работы с кодом я сделал шаг назад. Вместо этого я начал с того, что записал требования, входные данные и ограничения. Процесс записи помог мне обрести ясность и структуру, которых мне не хватало, когда я сразу же приступил к написанию кода. Кроме того, обдумывание возможных подходов, составление приблизительного плана решения или работа над псевдокодом помогли еще больше формализовать необходимую логику. После этого реализация кода стала намного проще.
Этот опыт применим и к науке о данных, поскольку многие проблемы могут быть сложными из-за нечетких целей, плохо сформулированных задач или недостаточно хорошо известных заранее ограничений и требований. Определение желаемых результатов и обоснование решения до начала написания кода позволяет избежать напрасных усилий. Работа в обратном направлении от намеченного результата, а не в прямом направлении от предпочтительной технологии, помогает сосредоточиться на фактической цели, которую необходимо достичь.
Урок 2: Проверка входных данных – Знайте свои данные
Даже после применения такого подхода, как предварительное планирование решений и определение желаемого результата, возникла еще одна повторяющаяся проблема: входные данные. Некоторые из моих ошибок не были связаны с некорректным кодом, а с предположениями о данных, которые не подтвердились на практике. В одном случае я предположил, что данные имеют определенные минимальные и максимальные границы, что оказалось неверным и привело к неправильному решению. В конце концов, код может быть правильным сам по себе, но полностью выйти из строя при работе с данными, для которых он изначально не был предназначен.
Это еще раз показало, почему проверка входных данных так важна. Часто мое решение не требовало полной переработки, достаточных небольших корректировок, таких как введение дополнительных условий или проверок границ, было достаточно для получения правильного и надежного решения. Кроме того, первоначальное исследование данных может дать представление о масштабе данных и указать, какие подходы являются осуществимыми. При работе с большими диапазонами, экстремальными значениями или высокой мощностью множества очень вероятно, что методы перебора, вложенные циклы или комбинаторные подходы быстро достигнут предела.
Естественно, это в равной степени важно и в проектах по анализу данных, где предположения о данных (явные или неявные) могут привести к серьезным проблемам, если их не проверить. Раннее исследование данных — жизненно важный шаг для предотвращения распространения проблем на последующие этапы, где их будет гораздо сложнее исправить. Главный вывод заключается не в том, чтобы полностью избегать предположений о данных, а в том, чтобы сделать их явными, задокументировать и проверить на ранних этапах процесса.
Урок 3: Быстрое итеративное совершенствование – прогресс важнее совершенства.
Головоломки в Advent of Code обычно делятся на две части. Вторая часть часто основывается на первой, но вводит новое ограничение, сложность или неожиданный поворот, например, увеличение размера задачи. Увеличение сложности часто делает недействительным первоначальное решение первой части. Тем не менее, это не означает, что решение первой части бесполезно, поскольку оно обеспечивает ценную отправную точку.
Наличие такой рабочей базовой модели помогает прояснить, как проявляется проблема, как ее можно решить и чего уже достигает предложенное решение. Далее, улучшения можно вносить более структурированным образом, поскольку известно, какие предположения больше не выполняются и какие части необходимо изменить для достижения успешного решения. Таким образом, доработка конкретного базового решения намного проще, чем разработка абстрактного «идеального» решения с самого начала.
В книге «Advent of Code» вторая часть появляется только после решения первой, что делает бессмысленными попытки найти решение, подходящее для обеих частей. Такая структура отражает распространенное на практике ограничение, поскольку обычно заранее неизвестны все требования. Попытка предугадать все возможные расширения, которые могут потребоваться, не только в значительной степени умозрительна, но и неэффективна.
В науке о данных можно наблюдать схожие принципы. По мере изменения требований, развития источников данных и уточнения потребностей и запросов заинтересованных сторон, проекты и решения также должны развиваться. Поэтому начинать с простых решений и итеративно совершенствовать их на основе реальной обратной связи гораздо эффективнее, чем пытаться с самого начала создать полностью универсальную систему. Такое «идеальное» решение редко бывает найдено на начальном этапе, и именно итерации позволяют решениям сходиться к чему-то полезному.
Урок 4: Проектирование в масштабе – Знайте пределы возможностей
Хотя итерационный подход предполагает начало с простых решений, в книге «Advent of Code» также неоднократно подчеркивается важность понимания масштаба и того, как он влияет на используемый подход. Во многих головоломках вторая часть не просто добавляет логическую сложность, но и значительно увеличивает размер задачи. Таким образом, решение с экспоненциальной или факториальной сложностью может быть достаточным для первой части, но становится непрактичным, когда размер задачи увеличивается во второй части.
Даже при использовании простого базового решения крайне важно иметь приблизительное представление о том, как оно будет масштабироваться. Вложенные циклы, перебор всех возможных комбинаций или исчерпывающий поиск всех возможных вариантов указывают на то, что решение перестанет работать так эффективно по мере роста размера задачи. Поэтому знание (приблизительной) точки отказа облегчает оценку необходимости и сроков переписывания решения.
Это не противоречит идее избегания преждевременной оптимизации. Скорее, это указывает на то, что следует понимать компромиссы, на которые приходится идти при выборе решения, не прибегая к немедленному внедрению наиболее эффективного или масштабируемого подхода. Проектирование с учетом масштабируемости означает понимание масштабируемости и сложности, а не необходимость слепой оптимизации с самого начала.
Здесь также проводится параллель с наукой о данных: решения могут хорошо работать на выборочных данных или ограниченных наборах данных, но склонны к сбоям при работе с данными «производственного уровня». Осознание этих узких мест, распознавание вероятных ограничений и учет альтернативных подходов делают такие системы более устойчивыми. Знание того, где решение может перестать работать, может предотвратить дорогостоящие перепроектирования и переписывания в дальнейшем, даже если они не будут внедрены немедленно.
Урок 5: Будьте последовательны – импульс важнее мотивации
Один из менее очевидных выводов, сделанных после участия в Advent of Code, был связан не столько с решением проблем, сколько с «наличием возможности участвовать». Решение головоломки каждый день кажется выполнимым в теории, но на практике оказывается сложной задачей, особенно когда это сочетается с усталостью, ограниченным временем или снижением мотивации, особенно после целого рабочего дня. Поэтому надежда на волшебное возвращение мотивации оказалась нежизнеспособной стратегией.
Реальный прогресс достигался благодаря ежедневной работе над проблемами, а не случайным всплескам вдохновения. Повторение укрепляло способы мышления и умение разбирать проблемы, что, в свою очередь, создавало импульс. Как только этот импульс был набран, прогресс начал накапливаться, и последовательность стала важнее интенсивности.
Развитие навыков в области анализа данных редко происходит за счет разовых проектов или изолированных глубоких исследований. Вместо этого оно является результатом многократной практики, внимательного анализа данных, разработки решений, итеративного совершенствования моделей и отладки предположений, проводимых последовательно в течение длительного времени. Полагаться только на мотивацию нецелесообразно, но наличие фиксированных рутинных действий делает процесс устойчивым. Книга «Появление кода» наглядно демонстрирует это различие: в то время как мотивация колеблется, постоянство накапливается. Такая ежедневная структура помогла превратить решение задач из стремления в привычку.

Заключительные мысли
Оглядываясь назад, я понимаю, что настоящая ценность участия в Advent of Code заключалась не в решении отдельных задач или изучении новых приемов программирования, а в выявлении моих привычек. Это показало, где я склонен спешить с решениями, где я склонен к излишнему усложнению и где замедление темпа и шаг назад сэкономили бы мне много времени. Сами по себе задачи были лишь средством достижения цели, а настоящая ценность заключалась в полученных знаниях.
Программа Advent of Code оказалась для меня наиболее эффективной, когда я воспринимал её как целенаправленную практику, а не как соревнование. Регулярное участие, сосредоточение на ясности, а не на оригинальности, и совершенствование решений вместо погони за идеальными вариантами с самого начала оказались гораздо ценнее, чем поиск единственного решения.
Если вы еще не пробовали, я бы порекомендовал вам сделать это, либо во время мероприятия в следующем году, либо прорабатывая головоломки прошлых лет. Этот процесс быстро выявляет привычки, которые сохраняются и после решения самих головоломок. А если вам нравится решать сложные задачи, вы, скорее всего, найдете это по-настоящему увлекательным и полезным опытом.
Источник: towardsdatascience.com



























