Математика Дата саентиста
@workakkk - админ @data_analysis_ml - ds https://gosuslugi.ru/snet/67b55bb01a1c5a6fb6ecc946
إظهار المزيد📈 نظرة تحليلية على قناة تيليجرام Математика Дата саентиста
تُعد قناة Математика Дата саентиста (@data_math) في القطاع اللغوي الروسية لاعباً نشطاً. يضم المجتمع حالياً 14 427 مشتركاً، محتلاً المرتبة 8 862 في فئة التكنولوجيات والتطبيقات والمرتبة 45 023 في منطقة روسيا.
📊 مؤشرات الجمهور والحراك
منذ تأسيسه في невідомо، حقق المشروع نمواً سريعاً وجمع 14 427 مشتركاً.
بحسب آخر البيانات بتاريخ 11 نوفمبر, 2026، تحافظ القناة على نشاط مستقر. خلال آخر 30 يوماً تغيّر عدد الأعضاء بمقدار 170، وفي آخر 24 ساعة بمقدار 5، مع بقاء الوصول العام مرتفعاً.
- حالة التحقق: غير موثّقة
- معدل التفاعل (ER): يبلغ متوسط تفاعل الجمهور 12.78%. وخلال أول 24 ساعة من النشر يحصد المحتوى عادةً 6.09% من ردود الفعل نسبةً إلى إجمالي المشتركين.
- وصول المنشورات: يحصل كل منشور على متوسط 1 844 مشاهدة. وخلال اليوم الأول يجمع عادةً 878 مشاهدة.
- التفاعلات والاستجابة: يتفاعل الجمهور بانتظام؛ متوسط التفاعلات لكل منشور يبلغ 18.
- الاهتمامات الموضوعية: يركز المحتوى على مواضيع رئيسية مثل llm, программирование, параметр, визуализация, stepik.
📝 الوصف وسياسة المحتوى
يصف المؤلف القناة بأنها مساحة للتعبير عن الآراء الذاتية:
“@workakkk - админ
@data_analysis_ml - ds
https://gosuslugi.ru/snet/67b55bb01a1c5a6fb6ecc946”
بفضل وتيرة التحديث المرتفعة (أحدث البيانات بتاريخ 12 نوفمبر, 2026) تحافظ القناة على حداثتها ومستوى وصول مرتفع. وتُظهر التحليلات تفاعلاً نشطاً من الجمهور، ما يجعلها نقطة تأثير مهمة ضمن فئة التكنولوجيات والتطبيقات.
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)`)?
- Как применить байесовский апдейт для оценки вероятности успеха?
---