Математика Дата саентиста
@workakkk - админ @data_analysis_ml - ds https://gosuslugi.ru/snet/67b55bb01a1c5a6fb6ecc946
Больше📈 Аналитический обзор Telegram-канала Математика Дата саентиста
Канал Математика Дата саентиста (@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)`)?
- Как применить байесовский апдейт для оценки вероятности успеха?
---