Заскуль питона (Data Science)
6.24K subscribers
111 photos
15 videos
4 files
143 links
Канал про Python, Data Science, SQL и многое другое

По вопросам сотрудничества и рекламе: @m459n9

Мемы: @ds_memes

Чат: https://t.iss.one/my_it_frogs
Download Telegram
😋 Когда задачи кочуют из спринта в спринт

Всем привет! У кого в трекере задач был таск, который существовал бесконечно (по крайнем мере вам так кажется)?

Лично у меня бывало такое: открываешь задачу, а она уже третью итерацию кочует из одного спринта в другой. Казалось бы, простая штука - это сделать дашборд или сделать аналитику, а в итоге эта задача никуда не уходит. Просто существует и все...

🥺 Обычно это такие долгоиграющие задачи, которые никто не решает до конца: то заказчик сменился, то приоритеты поменялись, то внезапно нужно переделать всё под новый бизнес-процесс. Муть страшная, если вовремя не сделать ряд действий, задача превратиться в рудимент, который нужно будет бесконечно поддерживать новыми правками.

Как это выглядит на практике
1. Встречи проходят, а таска осталась на месте, никаких апдейтов не произошло.
2. Заказчик на вопрос "актуально ли?" отвечает что-то типа "ну, наверное, да…", но сам не уверен. Обычно вот тут нужно остановиться и спросить более конкретно про задачу, которую покрывает инструмент.
3. На стендапах появляется лёгкая неловкость (или часть людей в принципе не интересуются): все понимают, что задача висит, но почему - никто не знает. Было такое, что задача у смежного направления могла висеть и по 2-3 месяца, хотя по сути нужно было декомпозировать до более мелких задач и прокачивать видимость выполнения работы)
4. В голове включается голос (от тебя): "Может, со мной что-то не так?" — и начинается самокопание. Расслабься, попробуй посмотреть с холодной головой, что ты действительно сделал и почему вообще это было нужно.

😋 Что делать?
1. Декомпозировать. Разбиваю задачу на мелкие шаги. Вообще это может выглядеть вот так, если, например, задача - это собрать классный дашборд!

а) поговорить с заказчиком
б) собрать сырые данные
в) проверить метрики
г) собрать прототип
д) выкатить первую версию.
е) поддержка.

2. Фиксировать всё письменно. Заказчик сказал устно - завтра забудет. И да, спустя время это спасает, когда возвращаемся к болям, тут важно ее закрыть и все будет топчик.
3. Не бояться возвращать задачу. Если ТЗ меняется - переоткрываю и честно спрашиваю: "А что реально нужно?" Часто оказывается, что половину уже не надо или приоритеты поменялись.

В следующих постах вернемся к техническим аспектам, ну а пока все!

Ставьте мои любимые реакции 🐳🐬, делитесь постом и пишите в комментариях были ли такие ситуации у вас!
Please open Telegram to view this post
VIEW IN TELEGRAM
45🐳1964🎄21
Аналитика мемов

😏 Возможно вы уже заметили подозрительную активность с каналом @ds_memes

😐 Рад поделиться с вами своим новым проектом. Хочу сделать его максимально прозрачным и раскрыть все карты.

В чем идея?
Хотелось сделать не просто ресурс с развлекательным контентом, а порционный источник дофамина, который позволит не залипать подолгу с бесконечными скроллом ленты в поисках хорошо сработавшей рекомендации, а разово закрыть свою потребность в просмотре видео и вернуться к более важным и интересным делам.

В чем суть?
Порционно: посты будут выходить ограниченное количество раз в день (пока 3, буду тюнить в зависимости от предпочтений подписчиков) в определенные промежутки времени - до работы / во время обеда / после работы.

Тематика: контент подобран только на определенную тему IT / работа / офис 💻

Ничего лишнего: никакой тяжелой теории и смыслов - только мемы.

Если вам интересно следить за развитием такого продукта, ставьте реакции - расскажу как полностью автоматизировал процесс публикации и подбора контента. Ставьте 🐳🐬, если интересно. Ссылочку продублирую тут.

И пусть у вас всегда будет под рукой база мемов для чата с коллегами 😎
Please open Telegram to view this post
VIEW IN TELEGRAM
🐳21144
💫 Spark для аналитика (ч.2.)

Собралось много реакций на предыдущем посте про Spark, делаю еще один!
Repartition в Spark. Зачем это вообще нужно?

В pandas не задумываешься про куски данных: читаете DataFrame и сразу работаешь с ним целиком. В Spark всё иначе: данные делятся на партиции (шарды), которые обрабатываются разными воркерами. Repartition позволяет управлять тем, как и насколько равномерно эти куски разбросаны по кластеру.

Зачем?

⚖️ Баланс нагрузки на кластер. Spark работает быстрее, если данные распределены по всем воркерам более-менее равномерно. Если партиций мало, часть узлов простаивает, остальные тянут всё на себе и теряется весь смысл распределённых вычислений.

🚤 Ускоряет джойны и агрегации. Самая частая боль в Spark - это медленные джойны или группировки. Причина часто в том, что данные по ключу раскиданы неравномерно. Если сделать .repartition("key") перед джойном Spark сможет склеить нужные куски локально, а не гонять данные по всему кластеру.

📝 Экономит память и снижает риск падений приложений. Иногда Spark после фильтрации или select делает ОЧЕНЬ перекошенные партиции: на одной куча данных, на другой почти ничего. Это может привести к OutOfMemory именно на одном воркере, при том что на других куча свободной памяти. Repartition выравнивает данные и размазывает нагрузку.

🗃️ Контроль количества файлов на выходе. Когда записываешь данные в parquet/csv, Spark по дефолту делает столько файлов, сколько партиций в DataFrame.
Если хочешь один файл — обязательно делайте .repartition(1) перед записью, иначе получишь кучу маленьких частей.

📝 Как это выглядит на практике

🔗 Джойны (делаем repartition по ключу объединения таблиц, так проще собрать ключи, разбросанные по кластеру)

df_left = df_left.repartition("user_id")
df_right = df_right.repartition("user_id")
df_joined = df_left.join(df_right, on="user_id", how="inner")


✍️ Запись (в примере ниже указано то, что на выходе мы получаем один файл).

df_result.repartition(1).write.parquet("result.parquet")


☝️ Изменяем количество партиций вручную.

df = df.repartition(50)  # вручную задаём 50 партиций


Обычно количество партиций автоматически подтягивается из конфига приложения, возможно, при настройке видели параметр spark.sql.shuffle.partitions

Самое важное в этом посте, что нужно искать размен между количеством партиций и размером задач на воркеры.
1️⃣
Слишком много партиций. Куча маленьких задач, и на маленьких данных становится только хуже, по скорости проседает.
2️⃣
Слишком мало партиций. Неэффективно, Spark теряет свою распределённость, одна нода делает всю работу.


Вообще в DA / DS / ML / DE мы всегда работаем с разменом (трейд-оффами) и все упирается в задачи, которые мы решаем)

Пишем дальше про Spark или нет?
🐳 — Пишем, давай еще, очень интересно
🤝 — Давай уже про что-то другое!
Please open Telegram to view this post
VIEW IN TELEGRAM
🐳558🤝311
🔭 Пост про магистратуры

Всем привет! Сегодня хочу написать про магистратуры, которые рассматриваю, куда проходил вступительные. Сначала я думал, что будет достаточно стрессово, но как оказалось зря.

⚠️ На что я обращаю внимание

1. Онлайн-формат обучения, так как не в кайф подрываться на другой конец города (или вообще в другой город) за учебой.

2. Очная форма обучения + акредитованный вуз. Сейчас практически все онлайн-магистратуры предоставляют очный формат обучения, то есть все плюшки от него будут получены (если вы понимаете о чем я).

3. Айтишное образование. Первое мое образование (Менеджмент) не связано с айтишкой, по крайнем мере его нет в реестре специальностей на отсрочку, поэтому иду получать.

4. Возможное обучение чему-то новому. Управление AI-продуктами, ML. Постоянно чему-то учиться тоже кайф + если тут применить обязательные дедлайны (хочется еще не страдать от этого), обучение пройдет намного эффективнее.

5. Стоимость. Большинство магистратур предоставляют только платное обучение. Есть образовательные кредиты, но не хочется растягивать эту историю, учитывая, что брать его нужно на 15 лет. Конечно, можно все разом выплатить и не париться, но тоже один из факторов.

Куда я прошел вступительные испытания

💻💻💻 НИУ ВШЭ

1. Аналитика больших данных. Достаточно простенькое вступительное, очень сильно похоже на демовариант + курс на Stepik. Скидки нет, стоимость 490к в год. По модулям есть классные дисциплины с LLM / MLOps / ML для аналитики / DE / Продуктовые метрики. В общем, получается неплохой фуллстек аналитик.

2. Магистр по наукам о данных. Суммарный балл складывается из тестирования по математике, мотивационного письма, личных достижений и собеседования. Демовариант. Скидки нет, стоимость 490к в год. Тут больше упор на ML. По программе тоже зашло + процедура сама по себе не была такой сложной.

3. Искусственный интеллект. Более хардовая магистратура, есть скидки. Стоимость 520к в год. Упор на современные архитектуры, фундаментальные знания. В магистратуре нужно уделять больше времени, чем в предыдущих. В программе более детально описано. По демовариантам можно хорошо подготовиться + есть отдельные курсы на Stepik

🟢 МИФИ. Множество компаний коллабятся с этим вузом. От некоторых из них я прошел вступительные (простенькая математика + кейс), проблем с поступлением не вижу, стоимость ~400к + по наполнению у всех примерно одинаково. Есть плюсом военная кафедра. Вот пример одной из программ, хороший план.

▪️ Центральный университет. Посмотрел по программам, есть топовые преподаватели, например, Александр Дьяконов и Рома Васильев.
По вступительным: был контекст по математике и программированию.
Слышал много положительных отзывов + получил грант, по идее можно идти туда, но обучение очное в кампусе несколько раз в неделю. Ребята из ЦУ, если вы тут есть, напишите в комменты, как вам, очень интересно почитать.

😮 ИТМО. Подавался с портфолио на несколько программ по портфолио, сформировал релевантный опыт + достижения в виде участия в хакатонах, кейс-чемпионатах + выступлений. Понравилось, что есть бюджет + можно получить достаточное хорошее образование AI Talent Hub, УВБ и др. Будем отталкиваться от результатов собеседований и конкурса портфолио. Если будет еще и удаленный формат обучения — будет кайф!
Сейчас я склоняюсь к выбору МИФИ, но, возможно, мое решение поменяется. Поэтому буду рад услышать ваши за и против.

Ставьте 🐳, если пост понравился, делитесь вашим мнением

@zasql_python 👉 @ds_memes
Please open Telegram to view this post
VIEW IN TELEGRAM
🐳49🔥136
Мемы

Всем доброе утро! Сегодня суббота, а это значит, что нужно отдыхать, уделять время себе после рабочей неделе, предлагаю прислать любимые мемы про DS / IT / работу в комментарии.

😏 Если мемы будут классные, то я их выложу в @ds_memes, а пока начну эстафету в комментариях.

Следующий пост выложу про то, как устроен пайплайн публикации мемов.

🐳🐳🐳

@zasql_python
Please open Telegram to view this post
VIEW IN TELEGRAM
1😁11🐳421
😎 Крутые статьи на Хабре про A/B-тестирование от крупных компаний

A/B-тесты кажутся простыми: разделили аудиторию, сравнили метрики, сделали вывод. Но на практике можно легко допустить ошибку, которая приведёт к неправильным решениям. Собрал полезные статьи с Хабра, которые помогут разобраться в нюансах экспериментов и избежать классических фейлов и узнать что-то новое.

Топ постов от IT-компаний, в которых активно используется 🆎.

💙 Ozon

🟢Шесть причин, почему ваши A/B-тесты не работают
🟢Без А/B результат XЗ, или Как построить высоконагруженную платформу А/B-тестов

🖤 X5 Tech

🟢А/Б тесты с метрикой отношения. Дельта-метод
🟢Как проводить A/B-тестирование на 15 000 офлайн-магазинах
🟢50 оттенков линейной регрессии, или почему всё, что вы знаете об A/B тестах, помещается в одно уравнение
🟢Varioqub: за Mann-Whitney замолвите слово

🛒 Купер (ex. СберМаркет)

🟢Линеаризация: зачем и как укрощать ratio-метрики в A/B-тестах
🟢База: айсберг A/B-тестов

🌏 Авито

🟢Как устроено A/B-тестирование в Авито
🟢Как улучшить ваши A/B-тесты: лайфхаки аналитиков Авито. Часть 1
🟢Как улучшить ваши A/B-тесты: лайфхаки аналитиков Авито. Часть 2
🟢Сетап А/В-теста, который помог снизить MDE выручки в 2 раза
🟢Как мы в Авито проводим A/B-тесты CRM-рассылок

🤪 Lamoda Tech

🟢Как же мощно я провел A/B-тест, или почему не стоит сравнивать наблюдаемый аплифт с MDE

❤️ Яндекс

🟢10 мифов об A/B-тестировании: как избежать распространённых заблуждений в статистическом анализе

🏦 Т-банк

🟢Использование последовательного тестирования для уменьшения размера выборки

Ставьте 🐳, если подборка была полезной, сохраняйте к себе, чтобы не забыть! Следующую подборку сделаю по методам оценки эффекта без A/B тестирования

@zasql_python 👉 @ds_memes

Что-то забыл? Пишите в комментариях!
Please open Telegram to view this post
VIEW IN TELEGRAM
🐳6110🔥95👍42
Forwarded from Data Science Memes
Пятница, играем в русскую рулетку.

😏 @ds_memes
Please open Telegram to view this post
VIEW IN TELEGRAM
😁36🤣11😎21🤯1
Буквально 2 дня назад вышла статья Avito 🌍 по 🆎. Разбираем по шагам механику A/B-тестирования: математика, интуиция и код

Почитал, в целом могу сказать, что хорошее чтиво для разбора A/B тестов.

Обычно, я смотрю графически на то, как изменяется MDE (тут это написано в зависимости от длительности эксперимента), также смотрю и по количеству пользователей в эксперименте (10/10, 20/20 и тд), только равные группы пользователей.

🧑‍🎓 Теоретическое
def compare_mde(current_a, current_b, new_a, new_b):
return np.sqrt(1/current_a + 1/current_b) / np.sqrt(1/new_a + 1/new_b)

# здесь смотрят на то, а как изменится mde, если мы перейдем от 10/10 к 50/50 разбиению
compare_mde(0.1, 0.1, 0.5, 0.5) # ~2.236


💻 Практическое
def check_mde_reduce_from_size(grouped_dataset, current_t, current_c, new_t, new_c):
"""
Функция для сравнения MDE в текущем варианте сплитования и в новом.
Параметры:
- grouped_dataset: сгруппированный поюзерный датасет, на осоновании которого будут сравниваться MDE
- current_t: доля пользователей в тесте в текущем сетапе
- current_c: доля пользователей в контроле в текущем сетапе
- new_t: доля пользователей в тесте в новом сетапе
- new_c: доля пользователей в контроле в новом сетапе
Возвращает:
- отношение MDE_current / MDE_new
"""


grouped_dataset['group_current'] = np.random.choice(['test', 'control', '-'],
p=[current_t, current_c, 1 - current_c - current_t],
size=len(grouped_dataset))
grouped_dataset['group_new'] = np.random.choice(['test', 'control', '-'],
p=[new_t, new_c, 1 - new_t - new_c],
size=len(grouped_dataset))
metric = 'promotion_revenue'


test_curr = np.array(grouped_dataset[(grouped_dataset['group_current'] == 'test')][metric])
control_curr = np.array(grouped_dataset[(grouped_dataset['group_current'] == 'control')][metric])

test_new = np.array(grouped_dataset[(grouped_dataset['group_new'] == 'test')][metric])
control_new = np.array(grouped_dataset[(grouped_dataset['group_new'] == 'control')][metric])

MDE_current = get_relative_MDE(test_curr, control_curr, alpha=0.05, beta=0.2)
MDE_new = get_relative_MDE(test_new, control_new, alpha=0.05, beta=0.2)
return MDE_current / MDE_new


Из формулы MDE зачастую мы работаем с равными дисперсиями в выборкам, поэтому можно вынести из под корня константу в виде дисперсии и размера выборки, это вот тут.

Прикольно, что на практических сгенерированных примерах видно, что эти расчеты реально работают и можно использовать для реализации внутри компании, при дизайне / расчета A/B тестов.

Написано еще тут и про прокси-метрики, что их нужно выбирать в зависимости от каждого кейса, про оценку эффекта при переходе от обычной метрики к прокси-метрике, интерпретацию прокси-метрик

+ итоги правильной подготовки сетапа теста, где выбрали

а) сплит 50/50, а не 10/10
б) выбрали прокси-метрику, а не основную (которая обладает меньшей чувствительностью)
в) держать тест не 1, а 7 недель.

🔽 как результат, получили сокращение MDE в 9.2 раза!

Ну и дополнительно рассказали про контр-метрики, в очередной раз упомянули линеаризацию + доверительный интервал для оценки эффекта Ratio-метрик.

В целом, хорошая и ненапряжная статья, которую я вам советую прочитать, если хотите начать разбираться в A/B тестах + подметить для себя что-то новое)

Ставьте 🐳, если понравился пост, делитесь своими мыслями в комментариях.
Please open Telegram to view this post
VIEW IN TELEGRAM
🐳33🔥95
вот и думаем! Garbage in -> Garbage Out.

@zasql_python 👉 @ds_memes
Please open Telegram to view this post
VIEW IN TELEGRAM
20😁7🐳3
Шпаргалки по визуализации в Python

Всем привет! Аналитикам и другим специалистам в области анализа данных необходимо из семпла данных сделать какое-то исследование, найти закономерность в данных и презентовать это ПМ / руководству и др. Не для каждой задачи нужно строить дашборд, поскольку задача может требовать первичный анализ.

🤔 В начале не придаешь этому значения, так как таблицы для нас содержат уже достаточное количество информации + различные статистики. Но на этом этапе хочется иметь возможность визуализировать базовые или интересные штуковины, с помощью которых можно будет сгенерировать еще гипотез.

Визуализировать можно и через Matplotlib (база всех графиков в Python), Seaborn (более расширенный функционал, чем Matplotlib), Plotly (интерактивные графики).

⬇️ Ниже приведен в коде минимум, которым можно пользоваться. Это должно покрывать большое количество задач (~80%) на распределения, поведение метрики во времени. Конечно, есть и другие виды визуализации, но это базовые. Сюда еще можно отнести boxplot для визуализации.

import matplotlib.pyplot as plt
import numpy as np

# Данные
x = np.linspace(0, 10, 100) # создаём массив от 0 до 10 из 100 точек
y = np.sin(x) # вычисляем sin(x)
data = np.random.randn(1000) # 1000 случайных значений из нормального распределения

# Фигура с 2 графиками (subplots)
fig, ax = plt.subplots(1, 2, figsize=(12, 4)) # создаём фигуру с 1 строкой и 2 графиками

# Первый subplot: гистограмма
ax[0].hist(data, bins=20, color="skyblue", edgecolor="black") # рисуем гистограмму
ax[0].set_title("Гистограмма") # заголовок графика
ax[0].set_xlabel("Значения") # подпись оси X
ax[0].set_ylabel("Частота") # подпись оси Y
ax[0].grid(True) # включаем сетку

# Второй subplot: линейный график
ax[1].plot(x, y, label="sin(x)", color="red") # рисуем линию sin(x)
ax[1].set_xlim(0, 12) # ограничение по оси X
ax[1].set_ylim(-2, 2) # ограничение по оси Y
ax[1].set_xticks([0,2,4,6,8,10]) # задаём кастомные тики по X
ax[1].set_yticks([-2,-1,0,1,2]) # задаём кастомные тики по Y
ax[1].set_xlabel("Ось X") # подпись оси X
ax[1].set_ylabel("Ось Y") # подпись оси Y
ax[1].set_title("Линейный график") # заголовок графика
ax[1].legend() # выводим легенду
ax[1].grid(True) # включаем сетку


❤️ Если вдруг, вы хотите делать более красивые графики, испытывать наслаждение при их построении, а также сделать их понятнее, вэлком ниже.

1️⃣ Matplotlib [дока]

🔗 Matplotlib CheatSheet (matplotlib.org)

🔗 Гайд на Kaggle по различным визуализациям

🔗 DataCamp Matplotlib CheatSheet

2️⃣ Seaborn [дока]

🔗 DataCamp Seaborn

🔗 Вот тут очень хорошо описано + есть по другим библиотекам

3️⃣ Plotly [дока]

🔗 Plotly Express, Colab

🔗 Plotly Cheatsheet

🙊 Сам я использую matplotlib и seaborn, потому что они быстро настраиваются, но кому-то заходит и Plotly, так как он при обычной настройке может сделать красоту. Каждому свое)

Ну и конечно же, можно использовать ChatGPT, Cursor и других ребят для отрисовки графиков, смотря какую цель преследуете

Ставьте 🐳, сохраняйте к себе, чтобы не потерять, тренируйтесь и все у вас получится!
Please open Telegram to view this post
VIEW IN TELEGRAM
🐳366🔥5