Привет! Меня зовут Mashkka Тихонова. Я - Senior Data Scientist, а еще я активно преподаю все, что связано с ML, DS и DL - помогаю людям начать свой путь в Data Science!
За годы преподавания у меня накопилось много советов для тех, кто только-только начинает свой путь в DS. Этими советами я всегда делюсь со студентами, а теперь решила собрать их в одном посте, написанном по мотивам моей серии постов в tg .
Советы эти совсем простые (уровня не заваливай горизонт на фото, когда фоткаешь пейзаж), но очень часто именно про такие базовые вещи на первых этапах забывают рассказать.В свое время я сама наступала на эти грабли, так как мне их никто не рассказал. Буду рада, если помогу вам этих ошибок избежать!
Замечение: и не заваливайте горизонт без нужды на фото, пожалуйста, сделать его ровным - это всего пара секунд!
Самый важный навык, который первым делом должен освоить любой DS - это гуглить!
Ищешь ответ на вопрос? - Гугли, а только потом спроси!
Не работает код? - Гугли!
Выбираешь алгоритм? - Гуглить!
Нужен пример кода? - Гугли!
Не знаешь, как правильно закодить? - Гугли!
Нужны статьи по теме? - Гугли!
и т. д. и т. п.
Гугл, конечно, знает не все, но ооооочень многое. И прежде, чем бежать с вопросами к коллегам, знакомым, преподавателям - загуглите. Скорее всего вы найдете ответ.
И помните не забывайте золотые правила Гуглежа:⬇
Гуглить только в Гугле, лучше на ванильном Google.com. Никакого поиска в Яндексе, Mail или Bing, если вы ищите что-то по Data Science. Не хочу обидеть другие поисковики, я сама люблю поиск Яндекса, но для целей Data Science - это Google и только он.
Гуглить только на английском: не пытайтесь что-то искать на русском языке - это боль. Даже если не знаете английский, лучше перевести ваш запрос на английский и загуглить так.
Гуглить по ключевым словам: при формулировке запроса старайтесь выделить ключевые слова (на английском) и загуглить именно их. Вероятность найти то, что вы ищите, намного выше, чем когда вы формулируете предложение целиком.
Если у вас в коде есть какая-то случайность (случайное разбиение на train и test, случайная инициализация и т. д.), то лучше эту случайность зафиксировать. Для этого у всех методов обычно есть специальные параметры типа ransdom_state
, seed
, random_seed
и т.п.
Согласитесь, обидно: перезапустил ноутбук и скор упал или вообще все сломалось? Поэтому старайтесь, чтобы ваш код работал детерминировано и всегда выдавал один и тот же результат.
Всем рассказываю страшилку про своего стажера. Он долго-долго обучал нейросеть, а когда я попросила его оценить качество и прогнать модель на тесте, он с ужасом понял, что забыл зафиксировать random_state
при разбиении на train и test, а код с разбиением заглушил. Странная ситуация: есть модель, есть данные, а оценить ее нельзя - непонятно, какие данные использовались при обучении и на чем её тестировать. Пришлось переобучать.
train_X, test_X, train_Y, test_Y = train_test_split(X, Y,
test_size=0.2,
random_state=42)
Итог: random_state = 42
наше все!
Не надо бояться страшных логов ошибок. Часто в них содержится та самая информация, которая поможет понять, что не так в коде.
Единого "правила чтения" логов нет, у каждого здесь свой "авторский" подход. Я обычно вначале смотрю, на какой строчке все сломалось, а потом прокручиваю в самый конец - в последней строчке как правило содержится ключевая информация, что не так. Если этого оказалось недостаточно, то начинаю читать логи снизу вверх, постепенно раскручивая ошибку из недр Python вверх как спираль. А еще чаще гуглю (в Google! по правилу 1) самую последнюю строчку ошибки и в большинстве случаев на Stack Overflow нахожу ответ.
Кстати, у sklearn очень хорошие подсказки в логах, которые зачастую напрямую говорят, что не так и как это исправить.
Например:
На картинке sklearn прямо пишет о том, что в наших обучающих данных содержится всего один признак или пример надо попросту сделать train_X.reshape
А дальше просто смотрим на размерность X_train
и обнаруживаем, что да, в данных действительно всего один признак:
Значит, по совету sklearn из логов надо написать так:
model.fit(train_X.reshape(-1, 1), train_Y)
Или пример чуть посложнее:
При попытке зафитить GridSearch на ирисах Фишера (задача классификации на 3 класса), оценивая качество с помощью F1:
clf = GridSearchCV(svc, parameters, scoring = 'f1')
clf.fit(iris.data, iris.target)
sklearn подскажет нам, что необходимо указать тип агрегации, среди прочего выдав в логах вот такую подсказку:
ValueError: Target is multiclass but average='binary'. Please choose another average setting, one of [None, 'micro', 'macro', 'weighted'].
нам остается просто последовать его совету и поменять scoring = 'f1'
на scoring = 'f1_micro'
:
clf = GridSearchCV(svc, parameters, scoring = 'f1_micro')
clf.fit(iris.data, iris.target)
Как часто бывает, что код не работает и не понятно почему. Или еще хуже, работает неверно и в переменных оказывается записано что-то непонятное совсем с потолка.
Например, такое нередко случается, если вы пытаетесь разом совместить всю предобработку данных вместе с обучением модели и запихиваете все это в одну ячейку кода, оборачивая в ColumnTransformer, Pipeline, и GridSearchCV.
В этом случае дебаг вам в помощь! И если вы пока еще не освоили базовые логгеры и такую удобную штуку как VS Code (а я очень рекомендую вам это сделать и как можно скорее), то самое простое - это понаставить побольше принтов - print
(можно прямо после каждой строчки кода), чтобы отследить что оказалось в каждой переменной на каждом шагу. Чаще всего это помогает найти ту самую строчку, где все пошло не так.
А еще можно разбить одну ячейку с кодом на несколько (чем детальнее, тем лучше), выводя в конце каждой клетки значения переменных и проверяя их корректность.
Что касается ColumnTransformer
и Pipeline
, то на этапе первично написания кода, я обычно обхожусь без них, так как они очень усложняют дебаг. А оборачиваю в них все уже в конце, после первичной отладки кода. Но тут уже вкусовой вопрос.
Замечание: еще раз подчеркну, что специально сейчас не касаюсь сейчас всяких логгеров и прочих более продвинутых фишек откладки кода, а говорю про самый упрощенный дебаг на уровне принтов. Такой дебаг доступен всем, даже самым-самым начинающим DS, которые работают в GoogleColab. Если хотите начинать трушно, я только за!
Никогда, никогда, никогда не обучайте модель на тесте! То, что модель ни в каком виде не должна видеть тест на этапе обучения вы должны запомнить как 2 X 2 = 4.* Показать (или дать подглядеть) модели тест - это все равно, что прорешать со школьником его вариант ЕГЭ в классе, а потом радоваться, что он получил высокий балл. Это, конечно, здорово, но к реальным знаниям, то есть качеству модели, этот результат на таком утекшем тесте отношения не будет иметь.
*В примере 2 X 2 = 4 я предполагаю, что мы находимся в кольце целых чисел со стандартной операцией умножения.
Но если с обучением модели и тестом все ясно, на то он и тест, то с обучением трансформаций типа StandardScaler
или CountVectorizer
и т. п. есть еще один нюанс. Метод fit_transform
для них можно вызывать только от обучающих данных (то есть от train
), а для теста всегда используем лишь transform
:
X_train_scaled = scaler.fit_trasnform(X_train)
(Эту строчку сделать зачеркнутой!) X_test_scaled = scaler.fit_trasnform(X_test)
X_test_scaled = scaler.trasnform(X_test)
Строчка X_test_scaled = scaler.fit_trasnform(X_test)
может полностью испортить ваш эксперимент, ведь обучение на тесте приведет к тому, что на обучающей и тестовых выборках данные будут отмасштабированы по-разному, а значения train и test не будут биться между собой.
Пример:
Допустим у нас есть набор данных x_train = [0, 10, 20], x_test = [0, 5, 10]
, к которому мы хотим применить минимаксное преобразование (это преобразование приводит данные в диапазон [0-1]).
Отталкиваясь от значений в x_train,
получаем вот такое соответствие:
0 => 0
5 => 0.25
10 => 0.5
20 => 1
В итоге получаем, что X_train_scaled = [0, 0.5, 1], X_test_scaled = [0, 0.25, 0.5]
.
Но стоит руке дрогнуть и случайно написать: X_test_scaled = scaler.fit_trasnform(X_test)
и, о ужас, соответствие на тесте изменится и для теста мы получим вот такую вещь:
0 => 0
5 => 0.5
10 => 1
и в итоге получим X_train_scaled = [0, 0.5, 1]
, X_test_scaled = [0, 0.5, 1]
, что полностью собьет с толку вашу модель.
Не самая частая, но очень неприятная ошибка: загрузил пакет или функцию, а потом нечаянно назвал переменную тем же именем. Как итог, тщетно пытаешься применить эту функцию, получая странный error, в котором непонятно ничего. Обычно выглядит это как-то так:
TypeError: 'ResultSet' object is not callable.
Как это связано с функцией/пакетом? НепАнЯтнА! А загулить такое по названию метода не получается никак... Тяжело...
Помню, одна студентка парсила данные и импортировала BeautifulSoup
- библиотеку для работы с html-документами по именем soup:
from bs4 import BeautifulSoup as soup
Потом в совершенно другой ячейке написала:
soup = soup(html, 'html.parser')
print(soup.prettify()[:2000])
А потом долго недоумевала, почему при первом запуске все окей, но если перезапустить ячейку, то все ломается и что не так.
А дело было в том, что после выполнения soup = soup(html, 'html.parser')
, имя soup
превращается в обычную переменную. Вот такие дела....
Заповедь эта немного шуточная и написана под вдохновением одного из подкастов Андрея Себранта, а ее название говорит само за себя, к нему и добавить-то нечего. Разве что прочитайте все ответы на вопрос и найдите тот, который действительно даёт правильный ответ!
Как же приятно запустить код на выходные/поставить обучаться большую модель, а потом в понедельник обнаружить, что вычисления посчитались почти до конца, но в последний момент код упал. Например, на выходные перезапустили сервер, когда ваш прогресс был уже 99%!
Или при парсинге огромного сайта после тысячной страницы вас забанили по API, а ваш код упал.
Подобных случаев, увы, в практике любого DS-ника не избежать. Но от них можно хотя бы частично обезопасить себя, если делать промежуточные чекпоинты модели, сохранять раз в несколько итераций обработанные данные и логгировать прогресс. Тогда вам не придется перезапускать все с нуля, и вы сможете частично восстановить результат.
Совет, казалось бы, очевидный, но почему-то очень часто многие забывают про него. Но помните, поленившись написать пару строк кода с сохранением, вы всегда рискуете потом об этом пожалеть!
Регулярные выражения - очень мощный и удобной инструмент для работы с текстами. Они позволяют эффективно искать/заменять в текстах фрагменты, удовлетворяющие определенному шаблону. С помощью регулярок можно действительно решить кучу разных задач, связанных с поиском по тексту, но не стоит недооценивать их коварство.
Ведь не зря говорят, когда некоторые люди сталкиваются с проблемой, думают «Я знаю, я решу её с помощью регулярных выражений.» Теперь у них две проблемы ©
У регулярок обожают вылезать крайние случаи, в которых они работают неправильно (спецсимволы, выражения, не удовлетворяющее шаблону в конце/начале строки и т. п.). А потом начинается бег по кругу: вы пытаетесь учесть крайний случай и регулярка начинает неправильно работать в другом месте и т. д. и т. п. Как итог, она разрастается до монструозных размеров, и вообще становится непонятно, когда она работает, а когда нет.
Надеюсь, я вам не слишком напугала. Не стоит боятся регулярок, они действительно удобные, но с ними надо всегда быть аккуратными, вот и все!
Если вы не знаете, как правильно, то Google, как вы знаете, знает все. Поэтому, в любой непонятной ситуации, по заповеди 1, мы гуглим. Но что делать, если у вас есть два варианта, оба правильные, но вы не знаете какой из них лучше взять?
Встав перед таким выбором настоящий Data Scientist проведет эксперимент: попробует оба варианта и выберете тот, который окажется в данной ситуации лучше (например, на валидации).
Студенты часто спрашивают: "Мария, вот у меня есть какой-то там датасет (который я лично никогда и в глаза не видела) и какая-то там задача (о которой я пока имею очень смутное представление только с их слов), как мне лучше всего заполнить пропуски в данных, медианой или средним? А какой метод снижения размерности выбрать?"
На подобные вопросы я всегда отвечаю так: "Сравните и выберете то, что даст лучший результат! Только эксперимент даст вам ответ, что будет лучше в вашем конкретном случае!"
Warning: только не переборщите с количеством вариантов, особенно при переборе гиперпараметров методом GridSearchCV
. Помните, с ростом количества перебираемых фичей, количество вариантов возрастает мультипликативно, то есть в разы. Поэтому всегда прикидывайте, сколько вариантов у вас получится и сколько вы готовы ждать результат.
Итого: в любой непонятной ситуации - гугли, а в любой неоднозначной - проводи эксперимент!
Заключение:
Буду рада, если эти советы помогут вам избежать самых типичных ошибок на пути начинающего Data Scientist. А возможно, если вы уже опытный DS-ник, они вас позабавят и вы с улыбкой вспомните, как сами через это прошли. А еще обязательно прочитайте мои вредные советы Айтишнику!
Также приглашаю всех посетить открытый урок для новичков в ML на тему «Первичный анализ данных с Pandas», который пройдет я проведу уже сегодня. На встрече обсудим, зачем нужен первичный анализ данных в машинном обучении, какие существуют инструменты для первичного анализа данных в Python, как визуализировать данные и какая преобработка данных нужна в ML. Запись на урок доступна по ссылке ниже. А для тех, кто не успеет зарегистрироваться, по этой же ссылке будет доступна запись урока.
Могу вас увереть, заповедь 7 точно не аксиома, довольно часто бывают нужные вещи прямо в вопросе...
Конечно! Заповеди - это советы, ни в коем случае не аксиомы! Вопросы тоже, безусловно, стоит читать.
Извините, не удержался. DS это Data Scientology? Ну кругом это. На ютубе, любой ролик включает рекламу DS. "Что бы собрать эту табуретку пришлось перелапатить кучу данных в google, лучше всего это умеют делать дейта сайнтолоджисты, получить сертификат DS можно у любой бабушки торгующей семечками". Только в России такое, больше особо нигде и не слышно. Отчего так?
Следующая хайповая тема для тех кто хочет получать много денег и называть себя айтишником, предыдущие темы нейронщики на питоне и тестировщики.
P.S. минуса в карму не делают автоматически корпоративный блог лучше и ума не добавляют тоже.
DS - это Data Science, профессия тех, кто занимается машинным обучением и, в том числе например, обучением нейросетей. К Data Scientology не имеет отношения)
Спасибо, интересно! Добавлю что гугля по ключевым словам, их надо менять в зависимости от того что выпадает в результате запроса. Т.е. нужный результат не вышел, но вышли похожие запросы или тексты с тем же смыслом, тогда нужно пробовать брать слова из них.
Да, хороший поинт, согласна!
со стековерфлоу код надо не копировать, а понять и написать свой
но понимание этого приходит с опытом
Фотка к статье топ)
*надеюсь не заминусуют мой и без того маленький рейтинг*
fowrard и backward это про теорию DL. Я бы начала с просмотра вот этого афигенного курса по DL https://github.com/hse-ds/iad-deep-learning
Ой, не туда ответила, это был ответ к другому комментарию. А за комплимент спасибо)
Я как раз набираюсь опыта в данной сфере, но не совсем понятны задачи связанные с forward pass и backward pass, не знаете ли вы какие-нибудь источники где можно узнать как работать с задачами связанными с вышеупомянутыми процессами?
fowrard и backward это про теорию DL. Я бы начала с просмотра вот этого афигенного курса по DL https://github.com/hse-ds/iad-deep-learning
Помнится есть кубок «Яндекса» — соревнование по скоростному поиску в Интернете. А тут на Аглицком и в Гугле.