PrepBro
Профессии
PrepBro
Профессия:

Подготовка

  • Вопросы911
  • Задачи36

Аналитика

  • hh статистика
  • Анализ резюме

Практика

  • Тестовое собеседование
  • Mock-собеседование
  • Менторы

Поддержка / отзывы

Telegram админа
Профессия:

Подготовка

  • Вопросы911
  • Задачи36

Аналитика

  • hh статистика
  • Анализ резюме

Практика

  • Тестовое собеседование
  • Mock-собеседование
  • Менторы

Поддержка / отзывы

Telegram админа
Все 24 профессии
Android DeveloperData AnalystSystem Analyst1С DeveloperiOS DeveloperBusiness AnalystJava DeveloperData ScientistQA EngineerQA AutomationPHP BackendC/C++ BackendDevOps EngineerIT Project ManagerFrontend DeveloperNode.js BackendUnity DeveloperC# BackendProduct AnalystFlutter DeveloperPython DeveloperIT Product ManagerGo DeveloperData Engineer

© 2026 PrepBro. Все права защищены.

Telegram-бот

Задачи по Data Scientist

SQL: Топ-5 продуктов по выручке
1.0 Junior🔥 30💬 1

Решение

Базовый запрос: Топ-5 по выручке

SELECT 
    product_name,
    SUM(quantity * price) AS total_revenue
FROM sales
GROUP BY product_name
ORDER BY total_revenue DESC
LIMIT 5;

Объяснение:

  • SUM(quantity * price) — рассчитываем выручку как произведение количества и цены
  • GROUP BY product_name — группируем данные по названию продукта
  • ORDER BY total_revenue DESC — сортируем по выручке в убывающем порядке
  • LIMIT 5 — берём только первые 5 строк

Вариант 2: С дополнительной статистикой

Часто нужна не только выручка, но и другие метрики:

SELECT 
    product_name,
    COUNT(*) AS number_of_sales,
    SUM(quantity) AS total_quantity,
    ROUND(AVG(price), 2) AS avg_price,
    SUM(quantity * price) AS total_revenue,
    ROW_NUMBER() OVER (ORDER BY SUM(quantity * price) DESC) AS rank
FROM sales
GROUP BY product_name
ORDER BY total_revenue DESC
LIMIT 5;
Читать полностью ->
EDA: Исследовательский анализ данных
1.0 Junior🔥 26💬 1

Решение: EDA на датасете клиентов банка

1. Описательная статистика

Начинаем с базового анализа данных:

import pandas as pd
import numpy as np

# Загрузка данных
df = pd.read_csv("bank_clients.csv")

# Основная информация
print(df.info())
print(df.shape)
print(df.describe())

# Пропуски
print(df.isnull().sum())
print(df.isnull().sum() / len(df) * 100)  # % пропусков

Ключевые метрики:

  • Размер датасета (число записей, признаков)
  • Типы данных
  • Пропущенные значения
  • Базовая статистика (mean, std, min, max, quartiles)

2. Распределения признаков

import matplotlib.pyplot as plt
import seaborn as sns

# Числовые признаки
numerical_cols = df.select_dtypes(include=[np.number]).columns

fig, axes = plt.subplots(3, 3, figsize=(15, 12))
for idx, col in enumerate(numerical_cols):
    ax = axes[idx // 3, idx % 3]
    df[col].hist(bins=30, ax=ax, edgecolor="black")
    ax.set_title(f"Распределение {col}")
    ax.set_ylabel("Частота")
Читать полностью ->
SQL: Вывести название и цену для всех анализов
1.2 Junior🔥 24💬 1

SQL решение

Условие задачи

Нужно выбрать названия и цены анализов, которые продавались с 5 февраля 2020 года на протяжении всей следующей недели (5-11 февраля 2020 включительно).

SQL запрос

SELECT 
    name,
    price
FROM sales
WHERE sale_date >= "2020-02-05"
  AND sale_date <= "2020-02-11"
ORDER BY sale_date, name;

Альтернативный вариант с BETWEEN

SELECT 
    name,
    price
FROM sales
WHERE sale_date BETWEEN "2020-02-05" AND "2020-02-11"
ORDER BY sale_date, name;

Объяснение

Фильтр по датам: Условие sale_date >= "2020-02-05" AND sale_date <= "2020-02-11" отбирает все записи в диапазоне от 5 февраля (начало недели) по 11 февраля включительно (конец недели).

BETWEEN оператор: Эквивалентный способ записи более компактен и читаемый. BETWEEN включает оба граничных значения.

Выбранные столбцы: name (название анализа) и price (цена) — ровно то, что требует задача.

Читать полностью ->
Задача на доверительный интервал
1.7 Middle🔥 22💬 1

Доверительный интервал для доли: 95% CI

Условие задачи

  • Размер выборки: n = 1000
  • Количество положительных ответов: x = 520
  • Уровень доверия: 95%

Найти 95% доверительный интервал для истинной доли положительных ответов в популяции.

Решение

Шаг 1: Вычисляем выборочную долю

p̂ = x / n = 520 / 1000 = 0.52 = 52%

Шаг 2: Вычисляем стандартную ошибку (SE)

SE = sqrt(p̂ × (1 - p̂) / n)
   = sqrt(0.52 × 0.48 / 1000)
   = sqrt(0.2496 / 1000)
   = sqrt(0.0002496)
   ≈ 0.01580

Шаг 3: Определяем критическое значение

Для 95% доверительного уровня используем z-распределение (нормальное приближение):

z = 1.96  (для 95% доверия)

Шаг 4: Вычисляем границы интервала

Маржа ошибки (ME) = z × SE
                  = 1.96 × 0.01580
                  ≈ 0.0309

Нижняя граница = p̂ - ME = 0.52 - 0.0309 ≈ 0.4891
Верхняя граница = p̂ + ME = 0.52 + 0.0309 ≈ 0.5509

Ответ

95% Доверительный интервал: [0.4891, 0.5509] или [48.91%, 55.09%]

Читать полностью ->
Feature Engineering: Создание признаков
2.7 Senior🔥 20💬 1

Решение

Для предсказания оттока клиентов из транзакционных данных предлагаю 10 информативных признаков:

1. Average Transaction Amount (Средняя сумма транзакции)

df['avg_transaction_amount'] = df.groupby('customer_id')['amount'].transform('mean')

Почему информативно: Клиенты с низкими средними суммами могут быть более чувствительны к комиссиям и процентам. Высокие суммы указывают на лояльность банку (не переходят в конкурентов).

Интерпретация: avg < 100 → высокий риск оттока (75% вероятность), avg > 1000 → низкий риск (15% вероятность).

2. Transaction Frequency (Частота транзакций в месяц)

df['date'] = pd.to_datetime(df['date'])
df['year_month'] = df['date'].dt.to_period('M')

tx_per_month = df.groupby(['customer_id', 'year_month']).size().reset_index(name='count')
df['avg_monthly_transactions'] = tx_per_month.groupby('customer_id')['count'].transform('mean')
Читать полностью ->
A/B тест: Анализ результатов эксперимента
2.0 Middle🔥 20💬 1

A/B тест: Анализ результатов эксперимента

1. Расчёт конверсионных показателей

Группа A (контроль):

  • Конверсия: 320 / 10000 = 3.2%

Группа B (тест):

  • Конверсия: 380 / 10000 = 3.8%

Прирост: (380 - 320) / 320 = 18.75% относительное улучшение

2. Проверка статистической значимости (двухвыборочный z-тест)

Нулевая гипотеза H₀: Конверсии групп одинаковы (p_A = p_B) Альтернативная гипотеза H₁: Конверсии различаются (p_A ≠ p_B)

Расчёт:

  • p_A = 320 / 10000 = 0.032
  • p_B = 380 / 10000 = 0.038
  • Объединённая доля: p_pool = (320 + 380) / 20000 = 0.035
  • Стандартная ошибка: SE = √[p_pool(1-p_pool) × (1/10000 + 1/10000)] = √[0.035 × 0.965 × 0.0002] ≈ 0.00583
  • z-статистика: z = (0.038 - 0.032) / 0.00583 ≈ 1.03
  • p-value ≈ 0.303 (двусторонний)

Вывод: p-value > 0.05, различие НЕ статистически значимо на уровне 5%.

3. Доверительный интервал (95%)

Для разницы пропорций: Δp ± z₀.₀₂₅ × SE_diff

Читать полностью ->
Задача на вероятность: сумма двух костей
1.2 Junior🔥 20💬 1

Вероятность суммы при бросании двух костей

Условие задачи

Бросаем две игральные кости (d6). Найти вероятность сумм 4 и 8.

Основной принцип

Всего возможных исходов = 6 × 6 = 36

Вероятность = (Количество благоприятных исходов) / 36

Вопрос 1: Вероятность суммы = 4

Подход: перечисляем все комбинации

Чтобы получить сумму 4, нужны пары:

  • (1, 3) — первая кость = 1, вторая = 3
  • (2, 2) — первая кость = 2, вторая = 2
  • (3, 1) — первая кость = 3, вторая = 1

Всего 3 благоприятных исхода.

P(Сумма = 4) = 3 / 36 = 1 / 12 ≈ 0.0833 ≈ 8.33%

Таблица всех комбинаций для суммы 4

Кость 1Кость 2Сумма
134
224
314

Вопрос 2: Вероятность суммы = 8

Подход: перечисляем все комбинации

Чтобы получить сумму 8, нужны пары:

  • (2, 6) — 2 + 6 = 8
  • (3, 5) — 3 + 5 = 8
  • (4, 4) — 4 + 4 = 8
  • (5, 3) — 5 + 3 = 8
  • (6, 2) — 6 + 2 = 8
Читать полностью ->
Data Cleaning: Очистка датасета
2.0 Middle🔥 19💬 1

Решение

Пайплайн очистки данных на Pandas

Создам полный пайплайн с объяснением каждого шага обработки грязного датасета. Это критически важный этап, так как данные низкого качества приводят к неверным выводам.

Загрузка и инициальная диагностика

import pandas as pd
import numpy as np
from scipy import stats
import warnings
warnings.filterwarnings('ignore')

# Загрузка датасета
df = pd.read_csv('dirty_data.csv')

# Инициальная диагностика
print(f"Размер датасета: {df.shape}")
print(f"\nТипы данных:\n{df.dtypes}")
print(f"\nПропущенные значения:\n{df.isnull().sum()}")
print(f"\nПроцент пропусков:\n{df.isnull().sum() / len(df) * 100}")
print(f"\nОсновная статистика:\n{df.describe()}")

# Проверка дубликатов
print(f"\nДубликаты: {df.duplicated().sum()}")

Почему это важно: Диагностика показывает масштаб проблем и помогает выбрать оптимальные методы обработки.

Обработка типов данных

Читать полностью ->
ML System Design: Система обнаружения мошенничества
3.0 Senior🔥 19💬 1

ML System Design: Система обнаружения мошенничества

1. Признаки и данные

Основные источники данных:

  • Транзакционные данные:

    • amount (сумма)
    • merchant_category (категория магазина)
    • merchant_id
    • timestamp
    • location (география)
    • device_id
    • payment_method (карта, кошелёк, и т.д.)
  • Историческая информация пользователя:

    • Сумма транзакций в день/неделю/месяц
    • Количество транзакций в день/неделю/месяц
    • Средняя сумма транзакции
    • Стандартное отклонение сумм (волатильность)
    • Количество дней с активностью
    • Количество уникальных категорий магазинов
    • Количество уникальных географических точек
  • Гео-данные:

    • Расстояние между последовательными транзакциями
    • Время между транзакциями (должно быть достаточно для физического перемещения)
    • Скорость перемещения между точками (если >900 км/ч → мошенничество)
Читать полностью ->
Time Series: Прогнозирование продаж
2.8 Senior🔥 19💬 1

Time Series: Прогнозирование продаж

1. Анализ временного ряда (EDA)

Декомпозиция временного ряда:

import pandas as pd
from statsmodels.tsa.seasonal import seasonal_decompose

# Загрузка данных
df = pd.read_csv('sales.csv', parse_dates=['date'], index_col='date')

# Декомпозиция
decomposition = seasonal_decompose(df['sales'], model='additive', period=12)
trend = decomposition.trend
seasonal = decomposition.seasonal
residual = decomposition.resid

decomposition.plot()

Компоненты:

  • Тренд (Trend): долгосрочное движение вверх/вниз
  • Сезонность (Seasonality): повторяющиеся паттерны (месячные, годовые)
  • Остатки (Residuals): шум, нерегулярные колебания

Статистический анализ:

  • Стационарность: проверка ADF-тестом (Augmented Dickey-Fuller)
  • Если не стационарный: применить differencing
from statsmodels.tsa.stattools import adfuller
Читать полностью ->
SQL: Скользящее среднее дохода за 3 месяца
2.0 Middle🔥 19💬 1

Скользящее среднее дохода за 3 месяца

Условие задачи

Рассчитать скользящее среднее (moving average) дохода за текущий месяц и два предыдущих месяца (окно размером 3 месяца). Это позволяет сгладить сезонные колебания и увидеть тренд.

Основной SQL запрос

SELECT 
    EXTRACT(YEAR FROM date) AS year,
    EXTRACT(MONTH FROM date) AS month,
    SUM(revenue) AS monthly_revenue,
    AVG(SUM(revenue)) OVER (
        ORDER BY EXTRACT(YEAR FROM date), EXTRACT(MONTH FROM date)
        ROWS BETWEEN 2 PRECEDING AND CURRENT ROW
    ) AS moving_avg_3months
FROM transactions
GROUP BY 
    EXTRACT(YEAR FROM date),
    EXTRACT(MONTH FROM date)
ORDER BY year, month;

Пошаговое объяснение

1. Агрегирование по месяцам:

GROUP BY EXTRACT(YEAR FROM date), EXTRACT(MONTH FROM date)
SUM(revenue) AS monthly_revenue

Сначала вычисляем общий доход за каждый месяц.

Читать полностью ->
Python: Реализовать decision tree с нуля
2.8 Senior🔥 18💬 1

Решение: Decision Tree классификатор с нуля

Структура: 2 класса (Node, DecisionTree)

1. Gini Index (критерий примеси)

Gini = 1 - sum(p_i^2)
  • Минимум 0: чистый узел
  • Максимум 0.5: 50/50 класс

2. Информационный прирост

IG = Gini(parent) - (N_left/N * Gini(left) + N_right/N * Gini(right))

Выше IG → лучше разбиение.

3. Алгоритм (рекурсивный)

Базовый случай (листовой узел):

  • Достигнута max_depth
  • Меньше min_samples_split объектов
  • Чистый узел (один класс)
  • IG = 0 (нет улучшения)

Рекурсивный случай:

  1. Перебрать все признаки
  2. Для каждого признака: перебрать все пороги
  3. Вычислить IG для каждого разбиения
  4. Выбрать разбиение с максимальным IG
  5. Рекурсивно строить левое и правое поддеревья

4. Предсказание

Для каждого объекта:

  1. Начать с корня
  2. Если листовой узел → вернуть значение
  3. Если x[feature] <= threshold → идти влево
  4. Иначе → идти вправо

5. Оценка

Читать полностью ->
Product Case: Падение метрики
2.0 Middle🔥 18💬 1

Решение: Анализ падения конверсии на 15%

1. Структура анализа

Шаг 1: Подтвердить тренд (5 мин)

SELECT 
  DATE(created_at) as date,
  COUNT(DISTINCT user_id) as users,
  ROUND(100.0 * COUNT(CASE WHEN action='purchase' THEN 1 END) / COUNT(*), 2) as conv_rate
FROM events
WHERE created_at >= NOW() - INTERVAL 14 days
GROUP BY DATE(created_at)
ORDER BY date DESC;

Шаг 2: Найти где упало в воронке (10 мин)

  • Sessions → Catalog Views (% перешли)
  • Catalog → Add to Cart (% добавили)
  • Cart → Checkout (% начали оформление)
  • Checkout → Purchase (% завершили)

Если упало на Purchase → проблема с платежами. Если на Checkout → проблема с формой оформления. Если везде одинаково → проблема с трафиком.

2. Гипотезы (приоритизированные)

ВЫСОКИЙ ПРИОРИТЕТ (проверить сразу):

  1. Платежная система сбой (вероятность 40%)
    • Позвонить провайдеру платежей
    • Проверить error_rate платежей
    • Проверить статус страницу провайдера
Читать полностью ->
Python: Найти дубликаты в датасете
1.0 Junior🔥 18💬 1

Решение

Способ 1: Встроенный метод duplicated()

Самый простой и быстрый способ — использовать встроенный метод duplicated():

import pandas as pd

# Создание примера датасета
df = pd.DataFrame({
    "id": [1, 2, 3, 2, 4, 1],
    "name": ["Alice", "Bob", "Charlie", "Bob", "David", "Alice"],
    "age": [25, 30, 35, 30, 28, 25]
})

# Способ 1: Найти все дубликаты (не обозначает первое появление)
duplicates = df[df.duplicated()]
print("Дубликаты (keep=False):")
print(df[df.duplicated(keep=False)].sort_values(by="id"))

# Вариант 1a: Сохранить первое появление
duplicates_first = df[df.duplicated(keep="first")]
print("\nДубликаты (keep=first):")
print(duplicates_first)

# Вариант 1b: Сохранить последнее появление
duplicates_last = df[df.duplicated(keep="last")]
print("\nДубликаты (keep=last):")
print(duplicates_last)

Способ 2: Поиск дубликатов по конкретным столбцам

Часто нужно найти дубликаты только по определённым колонкам:

Читать полностью ->
SQL: Пользователи без заказов
1.0 Junior🔥 17💬 1

Решение: Найти пользователей без заказов

Способ 1: LEFT JOIN (стандартный и быстрый)

SELECT u.user_id, u.name, u.email
FROM users u
LEFT JOIN orders o ON u.user_id = o.user_id
WHERE o.user_id IS NULL;

Логика: LEFT JOIN соединяет таблицы, пользователи без заказов имеют NULL в полях orders. Фильтруем WHERE o.user_id IS NULL.

Производительность: O(n log n), использует индекс на orders.user_id

Преимущества:

  • Читаемо и интуитивно
  • Хорошая производительность
  • Стандарт SQL

Способ 2: NOT EXISTS (для больших таблиц)

SELECT u.user_id, u.name, u.email
FROM users u
WHERE NOT EXISTS (
  SELECT 1
  FROM orders o
  WHERE o.user_id = u.user_id
);

Логика: Для каждого пользователя проверяем, существует ли хотя бы один заказ. NOT EXISTS вернёт true если подзапрос не вернул ни одной строки.

Преимущества:

  • Очень читаемо
  • Меньше ошибок с NULL
  • Early exit при первом найденном заказе
  • Часто лучшая производительность на PostgreSQL/Oracle
Читать полностью ->
SQL: Нарастающий итог продаж по месяцам
2.0 Middle🔥 17💬 1

Нарастающий итог продаж по месяцам

Условие задачи

Рассчитать нарастающий итог (cumulative sum) количества проданных товаров по месяцам каждого года с разбивкой по группам товаров.

Основной SQL запрос

SELECT 
    EXTRACT(YEAR FROM sale_date) AS year,
    EXTRACT(MONTH FROM sale_date) AS month,
    group_name,
    SUM(quantity) AS monthly_quantity,
    SUM(SUM(quantity)) OVER (
        PARTITION BY EXTRACT(YEAR FROM sale_date), group_name
        ORDER BY EXTRACT(MONTH FROM sale_date)
    ) AS cumulative_quantity
FROM sales
GROUP BY 
    EXTRACT(YEAR FROM sale_date),
    EXTRACT(MONTH FROM sale_date),
    group_name
ORDER BY year, group_name, month;

Пошаговое объяснение

1. Выделение года и месяца:

EXTRACT(YEAR FROM sale_date) AS year,
EXTRACT(MONTH FROM sale_date) AS month

2. Агрегирование по месяцам и группам:

GROUP BY EXTRACT(YEAR FROM sale_date), EXTRACT(MONTH FROM sale_date), group_name
Читать полностью ->
SQL: Найти второго по зарплате сотрудника
1.8 Middle🔥 16💬 1

SQL: Найти второго по зарплате сотрудника

Условие

Дана таблица employees:

CREATE TABLE employees (
    id INT PRIMARY KEY,
    name VARCHAR(100),
    salary DECIMAL(10, 2),
    department_id INT
);

Нужно найти второго по зарплате сотрудника в каждом департаменте.

Решение 1: Оконная функция ROW_NUMBER()

-- Самое простое и рекомендуемое решение

WITH ranked_employees AS (
    SELECT 
        id,
        name,
        salary,
        department_id,
        ROW_NUMBER() OVER (PARTITION BY department_id ORDER BY salary DESC) AS rank
    FROM employees
)
SELECT 
    id,
    name,
    salary,
    department_id
FROM ranked_employees
WHERE rank = 2;
Читать полностью ->
Python: Реализовать линейную регрессию с нуля
2.0 Middle🔥 16💬 1

Решение

1. Аналитическое решение (Нормальное уравнение)

import numpy as np
import matplotlib.pyplot as plt
Читать полностью ->
ML System Design: Поисковая выдача
3.0 Senior🔥 15💬 1

ML System Design: Поисковая выдача (Search Ranking)

1. Архитектура: Retrieval → Ranking

Двухэтапная архитектура:

User Query
    ↓
[RETRIEVAL STAGE]  ← Быстро, низкая точность
- ElasticSearch / Solr
- BM25 ranking
- ~1000 документов

↓
[RANKING STAGE]    ← Медленнее, высокая точность
- ML модель (Learning to Rank)
- ~100 документов (top k)

↓
Final Results (10 документов)

Почему два этапа?

  • Retrieval: скорость важнее всего (нельзя проверять миллионы документов)
  • Ranking: точность важна (проверяем top-k кандидатов)

2. Feature Engineering

Query Features (зависят только от запроса):

Читать полностью ->
Python: Реализовать логистическую регрессию с нуля
1.8 Middle🔥 15💬 1

Решение

1. Sigmoid функция и Binary Cross-Entropy Loss

import numpy as np
import matplotlib.pyplot as plt
Читать полностью ->
NLP: Классификация текстов
2.4 Senior🔥 15💬 1

Решение

1. Предобработка текста

import pandas as pd
import numpy as np
import re
from nltk.corpus import stopwords
from nltk.tokenize import word_tokenize
from nltk.stem import SnowballStemmer, WordNetLemmatizer
import nltk

# Загрузить необходимые ресурсы
nltk.download('punkt')
nltk.download('stopwords')
nltk.download('wordnet')

# Загрузка данных
df = pd.read_csv('reviews.csv')
print(f"Размер датасета: {df.shape}")
print(f"\nПримеры отзывов:")
print(df['text'].head())

# === ШАГ 1: БАЗОВАЯ ОЧИСТКА ===

def preprocess_text(text):
    # Приведение к нижнему регистру
    text = text.lower()
    
    # Удаление URL
    text = re.sub(r'http\S+|www.\S+', '', text)
    
    # Удаление email
    text = re.sub(r'\S+@\S+', '', text)
    
    # Удаление специальных символов (сохраняем букву, цифру, пробел)
    text = re.sub(r'[^a-zA-Zа-яА-Я0-9\s]', '', text)
    
    # Удаление лишних пробелов
    text = re.sub(r'\s+', ' ', text).strip()
    
    return text
Читать полностью ->
SQL: Удаление дубликатов без создания новой таблицы
2.0 Middle🔥 15💬 1

Удаление дубликатов без создания новой таблицы

Условие задачи

Полные дубликаты (абсолютно идентичные строки) появились в таблице. Нужно удалить их без создания новой таблицы и без потери оригинальных данных.

Оптимальный подход: используем оконную функцию ROW_NUMBER()

Ключевая идея: присваиваем каждой строке номер в рамках группы дубликатов. Первой копии присваиваем 1, остальным — 2, 3, ... и удаляем все строки с номером > 1.

Решение 1: Используя CTE и ROW_NUMBER (РЕКОМЕНДУЕТСЯ)

WITH duplicates AS (
    SELECT 
        *,
        ROW_NUMBER() OVER (PARTITION BY col1, col2, col3, ... ORDER BY rowid) AS rn
    FROM your_table
)
DELETE FROM your_table
WHERE rowid IN (
    SELECT rowid FROM duplicates WHERE rn > 1
);

Решение 2: Если есть id столбец

DELETE FROM your_table
WHERE id NOT IN (
    SELECT MIN(id)
    FROM your_table
    GROUP BY col1, col2, col3, ...
);
Читать полностью ->
SQL: Retention пользователей по когортам
2.0 Middle🔥 14💬 1

SQL: Retention пользователей по когортам

Определения

Когорта — группа пользователей, объединённых по дате первого события (обычно месяц регистрации)

Retention — процент пользователей из когорты, вернувшихся в конкретный период

Retention по месяцам:

  • Month 0 (M0): период регистрации (100% по определению)
  • Month 1 (M1): процент, активных в месяц после регистрации
  • Month 2 (M2): процент, активных спустя 2 месяца после регистрации
  • и т.д.

SQL Решение

Шаг 1: Создание таблицы данных

CREATE TABLE user_events (
    user_id INT,
    event_date DATE,
    event_type VARCHAR(50)
);

INSERT INTO user_events VALUES
(1, '2024-01-05', 'signup'),
(1, '2024-01-15', 'purchase'),
(1, '2024-02-10', 'login'),
(2, '2024-01-10', 'signup'),
(2, '2024-01-20', 'login'),
(3, '2024-02-01', 'signup'),
(3, '2024-02-15', 'purchase'),
(3, '2024-03-05', 'login'),
(4, '2024-02-05', 'signup'),
(4, '2024-03-10', 'purchase');

Шаг 2: Полный SQL запрос

Читать полностью ->
ML: Построить рекомендательную систему
2.7 Senior🔥 14💬 1

Решение

1. Необходимые данные

Для эффективной рекомендательной системы нужны:

Базовые данные:

  • История покупок — user_id, product_id, timestamp, purchase_amount
  • Взаимодействия пользователей — просмотры, клики, добавления в корзину, оценки/лайки
  • Характеристики товаров — категория, описание, цена, теги, изображения
  • Характеристики пользователей — возраст, пол, локация, предпочтения
  • Контекст — сезонность, праздники, тренды

Метаданные:

  • Временные метки для анализа поведения
  • Информация о возвратах и жалобах
  • Данные о конкурентах (цены, наличие)

2. Подходы к рекомендациям

2.1 Collaborative Filtering (Фильтрация по сотрудничеству)

Основана на предположении: если пользователи A и B похоже покупали раньше, им понравятся одни и те же товары.

from sklearn.metrics.pairwise import cosine_similarity
import numpy as np
Читать полностью ->
Задача на точность теста (PPV)
2.3 Middle🔥 14💬 1

Положительная прогностическая ценность (PPV): диагностический тест

Условие задачи

  • Чувствительность (Sensitivity) = 99% = 0.99
  • Специфичность (Specificity) = 95% = 0.95
  • Распространённость (Prevalence) = 1% = 0.01

Тест положительный. Какова вероятность, что человек действительно болен?

Определения

Чувствительность (TPR - True Positive Rate):

P(+ | Болен) = 0.99

Вероятность положительного теста при наличии болезни.

Специфичность (TNR - True Negative Rate):

P(- | Не болен) = 0.95
Или: P(+ | Не болен) = 1 - 0.95 = 0.05

Вероятность отрицательного теста при отсутствии болезни.

Распространённость:

P(Болен) = 0.01
P(Не болен) = 0.99

Положительная прогностическая ценность (PPV)

Формула:

PPV = P(Болен | +) = P(+ | Болен) × P(Болен) / P(+)

Решение по теореме Байеса

Шаг 1: Определяем основные вероятности

P(Болен) = 0.01
P(Не болен) = 0.99
P(+ | Болен) = 0.99
P(+ | Не болен) = 0.05
Читать полностью ->
Задача на распределение Пуассона
2.0 Middle🔥 14💬 1

Распределение Пуассона: пассажиры в автобусе

Условие задачи

Поток пассажиров в автобус: λ = 3 пассажира в минуту

Найти вероятность того, что за 2 минуты зайдёт ровно 10 пассажиров.

Распределение Пуассона

Формула:

P(X = k) = (e^(-λ) × λ^k) / k!

где:
- λ (lambda) = параметр распределения (среднее количество событий)
- k = количество событий
- e ≈ 2.71828
- k! = факториал k

Шаг 1: Определяем параметр λ для нашего случая

Поток: 3 пассажира в минуту Время: 2 минуты

λ = 3 × 2 = 6 пассажиров

Поскольку события происходят независимо, параметр Пуассона пропорционален времени.

Шаг 2: Применяем формулу Пуассона

Нужна вероятность k = 10 пассажиров:

P(X = 10) = (e^(-6) × 6^10) / 10!

Шаг 3: Вычисляем компоненты

e^(-6):

e^(-6) ≈ 0.002479

6^10:

6^10 = 60,466,176

10! (факториал):

10! = 1 × 2 × 3 × 4 × 5 × 6 × 7 × 8 × 9 × 10
    = 3,628,800

Шаг 4: Финальный расчёт

Читать полностью ->
Алгоритм: Найти общих предков в дереве
1.8 Middle🔥 13💬 1

Алгоритм: Найти общих предков в дереве (LCA)

Определение и примеры

LCA (Lowest Common Ancestor) - наименьший общий предок двух узлов. Это узел, который находится на наибольшей глубине и является предком обоих узлов.

Пример дерева:
        3
       / \
      5   1
     / \
    6   2
       / \
      7   4

LCA(5, 1) = 3
LCA(5, 4) = 3
LCA(6, 2) = 5
LCA(2, 4) = 2

Решение 1: Рекурсивный поиск (DFS)

class TreeNode:
    def __init__(self, val):
        self.val = val
        self.left = None
        self.right = None
Читать полностью ->
Python: Реализовать k-means clustering
2.0 Middle🔥 13💬 1

Python: Реализовать k-means clustering

Полная реализация k-means

import numpy as np
from typing import Tuple, List
import matplotlib.pyplot as plt
Читать полностью ->
ML: Построить модель скоринга клиентов
2.7 Senior🔥 13💬 1

Решение

1. Выбор признаков для скоринга

Демографические признаки:

  • Возраст — более молодые имеют выше риск, U-образное распределение
  • Пол — может быть предиктивным в некоторых случаях
  • Город/Регион — экономическое состояние региона влияет на платежеспособность
  • Семейный статус — женатые/замужние более надёжны
  • Дети — влияет на финансовые обязательства

Финансовые признаки:

  • Доход — основной предиктор (нужна валидация)
  • Стаж работы — стабильность дохода
  • Тип занятости — постоянная/временная
  • Существующие кредиты — отношение долгов к доходу (DTI)
  • История платежей — дефолты/задержки в прошлом
  • Размер заёмки — большие суммы рискованнее
  • Срок кредита — длинные сроки = выше риск

Поведенческие признаки:

  • Кредитная история — 3-5 лет истории
  • Количество открытых счётов — диверсификация кредитов
  • Возраст первого кредита
  • Среднее использование кредитного лимита — финансовая ответственность
Читать полностью ->
Алгоритм: Найти k ближайших точек
2.0 Middle🔥 12💬 1

Решение: k ближайших точек к origin

Задача

Даны точки на 2D плоскости и начало координат (origin). Найти K ближайших точек используя heap.

Решение: Max-Heap O(n log k)

Ключевая идея:

  • Вместо вычисления евклидова расстояния можно сравнивать квадраты расстояний (избегаем sqrt)
  • Используем max-heap размером K: храним K ближайших точек
  • Для каждой точки: если расстояние меньше максимального в heap → заменяем
import heapq
from typing import List
Читать полностью ->
Задача на вероятность с картами
2.0 Middle🔥 12💬 1

Вероятность карты из первой коробки: теорема Байеса

Условие задачи

Коробка 1: 5 красных + 3 синих (всего 8 карт) Коробка 2: 4 красных + 6 синих (всего 10 карт)

Выбираем коробку случайно, достаём красную карту. Какова вероятность, что это была коробка 1?

Теорема Байеса

P(Коробка1 | Красная) = P(Красная | Коробка1) × P(Коробка1) / P(Красная)

Шаг 1: Априорные вероятности выбора коробки

P(Коробка1) = 1/2 = 0.5
P(Коробка2) = 1/2 = 0.5

Шаг 2: Вероятность вытащить красную карту из каждой коробки

Из коробки 1:

P(Красная | Коробка1) = 5/8 = 0.625

Из коробки 2:

P(Красная | Коробка2) = 4/10 = 0.4

Шаг 3: Полная вероятность вытащить красную карту

P(Красная) = P(Красная|Коробка1) × P(Коробка1) + P(Красная|Коробка2) × P(Коробка2)

P(Красная) = (5/8) × (1/2) + (4/10) × (1/2)
            = 5/16 + 4/20
            = 5/16 + 2/10
            = 0.3125 + 0.2
            = 0.5125
Читать полностью ->
Задача на вероятность с монетами
2.0 Middle🔥 12💬 1

Вероятность нечестной монеты: решение теоремой Байеса

Условие задачи

Берём 1 монету из 100 (99 честных + 1 нечестная). Подбрасываем 10 раз → 10 орлов подряд. Какова вероятность, что это нечестная монета?

Решение с использованием теоремы Байеса

Теорема Байеса:

P(A|B) = P(B|A) × P(A) / P(B)

Где:

  • A = монета нечестная
  • B = наблюдали 10 орлов подряд

Шаг 1: Определяем априорные вероятности

P(A) = P(нечестная) = 1/100 = 0.01
P(¬A) = P(честная) = 99/100 = 0.99

Шаг 2: Вероятность 10 орлов для каждого типа монеты

Если монета честная:

P(10 орлов | честная) = (1/2)^10 = 1/1024 ≈ 0.000977

Если монета нечестная:

P(10 орлов | нечестная) = 1^10 = 1

Шаг 3: Вычисляем полную вероятность наблюдаемого события

P(10 орлов) = P(10 орлов|нечестная)×P(нечестная) + P(10 орлов|честная)×P(честная)

P(10 орлов) = 1 × 0.01 + (1/1024) × 0.99
            = 0.01 + 0.000967
            = 0.010967
Читать полностью ->
Metrics Design: Метрики для e-commerce
2.8 Senior🔥 11💬 1

Решение: Metrics Design для e-commerce

1. Ключевые бизнес-метрики

North Star: Gross Merchandise Value (GMV) в месяц

Guardrail:

  • NPS > 50
  • Возврат < 10%
  • Успешность платежей > 98%
  • Uptime > 99.9%

2. Продуктовые метрики

Воронка: Sessions → Views → Cart → Checkout → Order

Метрики:

  • conversion_rate = orders / sessions
  • cart_abandonment = (cart - orders) / cart
  • avg_order_value
  • repeat_purchase_rate
  • lifetime_value

Сегментация: device, source, geo

3. Технические метрики

Performance:

  • P50 < 100ms, P95 < 500ms, P99 < 2000ms
  • Error rate < 0.1%

Availability:

  • Uptime > 99.9%
  • Cache hit > 90%
  • DB lag < 10s

4. Мониторинг

Дашборды:

  • Executive: GMV, conversion, NPS
  • Product: funnel, traffic
  • Engineering: latency, errors, cache
  • Analytics: revenue, cohorts
  • Ops: uptime, incidents

Стек: Prometheus, DataDog, ELK, Jaeger

Алерты:

  • Error > 5% → CRITICAL
  • P95 > 1000ms → HIGH
  • Conversion drop 20% → CRITICAL
Читать полностью ->
ML: Классификация изображений
2.4 Senior🔥 11💬 1

Решение

1. Выбор архитектуры нейросети

1.1 Сравнение архитектур

АрхитектураСкоростьТочностьРазмерРекомендация
MobileNet v3Отличная75%5 МБМобильные приложения
ResNet-50Хорошая80%100 МББаланс параметров
EfficientNet-B0Отличная80%30 МБЛучший выбор
ViT (Vision Transformer)Средняя85%+300 МБResearch, большие данные
DenseNet-121Средняя78%30 МБКомпактная, быстрая
Inception v3Медленная80%100 МБLegacy

Рекомендация: EfficientNet-B0 — оптимальное соотношение скорости и точности.

1.2 Архитектура сети (пример для EfficientNet)

import torch
import torch.nn as nn
from torchvision import models
from torchvision.models import EfficientNet_B0_Weights
Читать полностью ->
PyTorch: Реализовать attention mechanism
2.4 Senior🔥 9💬 1

Решение

Реализация механизма внимания в PyTorch.

1. Scaled Dot-Product Attention

import torch
import torch.nn as nn
import torch.nn.functional as F
import math
Читать полностью ->
Алгоритм: Топ-K частых элементов
1.6 Junior🔥 6💬 1

Решение: Топ-K частых элементов за O(n log k)

Задача

Найти K наиболее часто встречающихся элементов в массиве за время O(n log k) с использованием heap.

Основной подход: Min-Heap (O(n log k))

Алгоритм:

  1. Подсчитываем частоту каждого элемента с помощью Counter — O(n)
  2. Создаём мин-кучу размером K
  3. Итерируем по элементам с их частотами:
    • Если в куче меньше K элементов: добавляем текущий
    • Если куча полна и текущая частота больше минимальной в куче: заменяем минимум
  4. Результат: K элементов остаются в куче

Примеры

Анализ сложности

  • Time: O(n log k) — n для подсчёта, m log k для операций с heap (m ≤ n уникальных)
  • Space: O(n) для Counter + O(k) для heap

Альтернативные подходы

Max-Heap (O(n log n)): Меньше эффективен, но проще когда K близко к количеству уникальных элементов.

Bucket Sort (O(n)): Используем индекс = частота, получаем O(n) временно. Требует O(n) дополнительной памяти.

Практическое применение

Читать полностью ->