Математика Дата саентиста
@workakkk - админ @data_analysis_ml - ds https://gosuslugi.ru/snet/67b55bb01a1c5a6fb6ecc946
Ko'proq ko'rsatish📈 Telegram kanali Математика Дата саентиста analitikasi
Математика Дата саентиста (@data_math) Rus til segmentidagi kanali faol ishtirokchi. Hozirda hamjamiyat 14 427 obunachidan iborat bo'lib, Texnologiyalar & Aralashmalar toifasida 8 862-o'rinni va Rossiya mintaqasida 45 023-o'rinni egallagan.
📊 Auditoriya ko‘rsatkichlari va dinamika
невідомо sanasidan buyon loyiha tez o‘sib, 14 427 obunachiga ega bo‘ldi.
11 Noyabr, 2026 dagi oxirgi ma’lumotlarga ko‘ra kanal barqaror faollikka ega. Oxirgi 30 kunda obunachilar soni 170 ga, so‘nggi 24 soatda esa 5 ga o‘zgardi va umumiy qamrov yuqori darajada qolmoqda.
- Tasdiqlash holati: Tasdiqlanmagan
- Jalb etish (ER): Auditoriya o‘rtacha 12.78% darajada jalb etiladi. Nashrdan keyingi dastlabki 24 soatda kontent odatda umumiy obunachilar sonining 6.09% ini tashkil etuvchi reaksiyalarni to‘playdi.
- Post qamrovi: Har bir post o‘rtacha 1 844 marta ko‘riladi; birinchi sutkada odatda 878 ta ko‘rish yig‘iladi.
- Reaksiyalar va o‘zaro ta’sir: Auditoriya faol: har bir postga o‘rtacha 18 ta reaksiya keladi.
- Tematik yo‘nalishlar: Kontent llm, программирование, параметр, визуализация, stepik kabi asosiy mavzularga jamlangan.
📝 Tavsif va kontent siyosati
Muallif resursni shaxsiy fikrni ifoda etish maydoni sifatida ta’riflaydi:
“@workakkk - админ
@data_analysis_ml - ds
https://gosuslugi.ru/snet/67b55bb01a1c5a6fb6ecc946”
Yuqori yangilanish chastotasi (oxirgi ma’lumot 12 Noyabr, 2026 da olingan) sababli kanal doimo dolzarb va katta qamrovli bo‘lib qoladi. Analitika auditoriya kontent bilan faol hamkorlik qilishini, uni Texnologiyalar & Aralashmalar toifasidagi muhim ta’sir nuqtasiga aylantirishini ko‘rsatadi.
import pandas as pd
import numpy as np
np.random.seed(42)
days = pd.date_range("2023-01-01", periods=10, freq="D")
true_temp = np.sin(np.linspace(0, 3 * np.pi, 240)) * 10 + 20
bias_per_day = np.random.uniform(-2, 2, size=len(days))
df = pd.DataFrame({
"datetime": pd.date_range("2023-01-01", periods=240, freq="H"),
})
df["day"] = df["datetime"].dt.date
df["true_temp"] = true_temp
df["bias"] = df["day"].map(dict(zip(days.date, bias_per_day)))
df["measured_temp"] = df["true_temp"] + df["bias"] + np.random.normal(0, 0.5, size=240)
🔍 Разбор: как оценить смещение
Идея: температура в течение дня плавно колеблется, но bias в этот день одинаков для всех точек. Если мы "сгладим" значения (например, скользящим средним), то можем аппроксимировать общий тренд — и вычесть его, получив оценку bias.
🔧 Способ: вычтем сглаженный тренд, затем усредним остатки по дню:
```python
# Сглаживаем тренд
df["trend"] = df["measured_temp"].rolling(window=12, center=True, min_periods=1).mean()
# Остатки (приближение к bias)
df["residual"] = df["measured_temp"] - df["trend"]
# Оценка bias как среднее отклонение внутри дня
bias_est = df.groupby("day")["residual"].mean()
df["estimated_bias"] = df["day"].map(bias_est)
# Восстановим температуру: measured - bias
df["restored_temp"] = df["measured_temp"] - df["estimated_bias"]
```
📊 Результаты
Оценим ошибку восстановления:
```python
from sklearn.metrics import mean_squared_error
rmse = mean_squared_error(df["true_temp"], df["restored_temp"], squared=False)
print(f"RMSE восстановления: {rmse:.4f}")
```
> ✅ Обычно RMSE ≈ 0.5–0.7 — это близко к стандартному отклонению шума, значит bias устранён успешно!
💡 Вывод
✔️ Простая техника — сглаживание + усреднение отклонений — позволяет оценить дневные смещения
✔️ Без знания "истинной" температуры можно получить довольно точную реконструкцию
✔️ Это напоминает реальные задачи очистки данных от сенсорных сдвигов или ошибок калибровки
📈 Отличный пример практики Data Science с уклоном в математику, временные ряды и обработку шумов!List[float], представляющий одномерное распределение (например, значения метрики или зарплаты).
Нужно определить: существует ли индекс, на котором можно разделить массив на две части так, чтобы стандартное отклонение слева и справа отличалось не более чем на ε (например, 0.1).
Формат:
def has_balanced_std_split(data: list[float], epsilon: float = 0.1) -> bool:
...
Пример:
data = [1.0, 2.0, 3.0, 4.0, 5.0]
# Разделение после 2 → [1.0, 2.0], [3.0, 4.0, 5.0]
# std слева ≈ 0.5, справа ≈ 0.816 → разница = 0.316 > 0.1 → не подходит
🔍 Подсказка
Используй statistics.stdev() или numpy.std(ddof=1) (с выборочной коррекцией).
Но не забывай, что длина подмассива должна быть как минимум 2.
---
✅ Пример реализации:
```python
import statistics
def has_balanced_std_split(data: list[float], epsilon: float = 0.1) -> bool:
n = len(data)
if n < 4:
return False # Нужны хотя бы 2 элемента в каждой части
for i in range(2, n - 1):
left = data[:i]
right = data[i:]
if len(left) < 2 or len(right) < 2:
continue
std_left = statistics.stdev(left)
std_right = statistics.stdev(right)
if abs(std_left - std_right) <= epsilon:
return True
return False
```
📌 Пример использования:
```python
data = [10, 12, 11, 20, 21, 19]
print(has_balanced_std_split(data, epsilon=0.5)) # True или False в зависимости от разбивки
```
🎯 Что проверяет задача:
• понимание **дисперсии и стандартного отклонения**
• знание **статистических библиотек Python**
• работа с ограничениями на длину срезов
• мышление в духе «разделяй и анализируй»
| user_id | group | conversion_rate |
|---------|--------|-----------------|
| 1001 | A | 0 |
| 1002 | A | 1 |
| 1003 | B | 0 |
| 1004 | B | 1 |
| ... | ... | ... |
По результатам A/B теста кажется, что разницы между группами нет. Вы проверили chi-squared test и Mann-Whitney — тоже ничего.
🧩 Однако ваш коллега утверждает, что в данных явно зарыта сильная зависимость, которую можно выявить, если «включить голову».
---
🔍 Вопрос:
Какой скрытый фактор мог полностью «маскировать» эффект от теста и как его можно вычислить, даже если он отсутствует в таблице напрямую?
💡 Подсказка: данные собирались в течение 30 дней, но колонка с датой/временем была потеряна при сохранении. Однако user_id — это не случайное число.
🎯 Что нужно сделать:
1. 🧠 Предположить, что user_id содержит зашумлённую информацию о времени регистрации (например, ID выдаются монотонно)
2. 🧮 Смоделировать зависимость результата от user_id и проверить, не является ли тест несбалансированным по времени
3. 📈 Построить метрику на основе сгруппированных окон по user_id и визуализировать смещение между группами A и B
🎯 Ключевая идея решения:
Хотя колонка с датой была потеряна, можно сделать разумное предположение:
🔸 `user_id` назначается **монотонно**, т.е. пользователи с меньшими ID пришли раньше.
Если эксперимент длился 30 дней, а пользователи приходили неравномерно, то:
- группа A могла доминировать в начале
- группа B — в конце
📉 А что, если в эти периоды поведение пользователей менялось? Например, была акция, баг, праздник?
🔍 **Решение: как восстановить эффект**
1. 🟤 Добавим к данным колонку `bucket = user_id // 100`, чтобы разбить пользователей на условные "временные окна"
2. 🟤 Для каждого `bucket` считаем среднюю `conversion_rate` отдельно по группам A и B
3. 🟤 Строим график `conversion_A - conversion_B` по bucket
Если кривая скачет — тест **несбалансирован по времени** и глобальное сравнение групп вводит в заблуждение.p.
- У вас есть N исторических наблюдений: x1, x2, ..., xN, где каждое xi равно 0 или 1.
Вопросы:
1. Построить оценку вероятности успеха p и доверительный интервал на уровне 95%.
2. Рассчитать, сколько экспериментов нужно запустить, чтобы вероятность выхода в прибыль была выше 95%, учитывая:
- стоимость одного запуска C;
- прибыль от одного успешного эксперимента R.
---
▪️ Подсказки:
- Для оценки p используйте биномиальную модель.
- Для доверительного интервала:
- Можно использовать нормальное приближение (если выборка большая),
- Или Wilson-интервал для аккуратности.
---
▪️ Что оценивается:
- Правильная работа с вероятностями и доверием.
- Способность адекватно аппроксимировать биномиальные распределения.
- Чистота и практичность вычислений.
---
▪️ Разбор возможного решения:
▪️ 1. Оценка вероятности успеха:
# p_hat - оценка вероятности успеха
p_hat = sum(xi_list) / N
где xi_list — список из 0 и 1 (результаты экспериментов).
▪️ 2. Доверительный интервал через нормальное приближение:
import math
z = 1.96 # для 95% доверия
std_error = math.sqrt(p_hat * (1 - p_hat) / N)
lower_bound = p_hat - z * std_error
upper_bound = p_hat + z * std_error
▪️ 3. Wilson-интервал (более аккуратный):
z = 1.96 # для 95% доверия
center = (p_hat + z**2 / (2 * N)) / (1 + z**2 / N)
margin = (z * math.sqrt((p_hat * (1 - p_hat) / N) + (z**2 / (4 * N**2)))) / (1 + z**2 / N)
lower_bound = center - margin
upper_bound = center + margin
---
▪️ 4. Прибыльность эксперимента:
Формула прибыли при n экспериментах:
profit = successes * R - n * C
Требуется:
P(profit > 0) >= 0.95
Число успехов должно быть больше определённой границы:
min_successes = (n * C) / R
Если n велико, количество успехов приближается к нормальному распределению:
mean_successes = n * p_hat
std_successes = math.sqrt(n * p_hat * (1 - p_hat))
Для нормального приближения можно написать:
# Вероятность успешности через нормальное распределение
from scipy.stats import norm
# Вероятность, что количество успехов больше нужного
prob = 1 - norm.cdf(min_successes, loc=mean_successes, scale=std_successes)
Тогда перебором или через уравнение ищем минимальное n, чтобы prob >= 0.95.
---
▪️ Возможные подводные камни:
- Нельзя использовать нормальное приближение при малом N — нужна биномиальная модель.
- Неверное задание границ доверительного интервала может привести к неправильной стратегии запуска.
- Плохое понимание соотношения C и R приводит к ошибочным выводам об окупаемости.
---
📌Дополнительные вопросы:
- Как бы вы учли, что прибыль от успеха — случайная величина?
- Как пересчитать стратегии, если вероятность успеха зависит от времени (`p = f(t)`)?
- Как применить байесовский апдейт для оценки вероятности успеха?
---