Active Learning для задачи предсказания победителя Dota 2. Итеративно выбирает наиболее информативные матчи для разметки, сравнивает стратегии entropy/margin/random.
Агент для умного отбора данных через Active Learning. Задача: предсказание radiant_win по признакам, доступным на момент первой крови.
В реальном сценарии: у нас есть матчи из API, но нет вратейтов героев (нужно запрашивать отдельно — это "стоимость" разметки). AL выбирает, для каких матчей важнее всего получить вратейты, чтобы быстрее улучшить модель.
В эксперименте: имитируем этот процесс — скрываем метки пула и открываем их итеративно.
| Признак | Описание |
|---|---|
radiant_avg_winrate | Средний вратейт героев Radiant |
dire_avg_winrate | Средний вратейт героев Dire |
winrate_delta | Разница вратейтов |
first_blood_time |
| Время первой крови (секунды) |
fb_advantage_enc | 1=radiant, -1=dire, 0=none |
draft_advantage_enc | 1=radiant, -1=dire, 0=balanced |
avg_rank_tier | Средний ранг (если есть) |
Таргет: radiant_win (bool → int)
Вход: data/labeled/labeled.parquet
Выход: data/active/
.venv/bin/pip install pandas scikit-learn matplotlib pyarrow
mkdir -p data/active
Спросить (или взять из пайплайна):
logreg (по умолчанию), rf, svmentropy,randomПоказать:
## Настройки Active Learning — Dota 2 Win Prediction
- Датасет: data/labeled/labeled.parquet
- Признаки: winrate_delta, first_blood_time, fb_advantage, draft_advantage, avg_rank_tier
- Таргет: radiant_win
- Seed: 50 матчей
- Итераций: 5 × 20 матчей = 150 итоговых примеров
- Модель: LogisticRegression
- Стратегии: entropy, random
Подтверждаешь? [да]:
.venv/bin/python -c "
import pandas as pd
from sklearn.model_selection import train_test_split
df = pd.read_parquet('data/labeled/labeled.parquet')
# Encode categorical
df['fb_advantage_enc'] = df['first_blood_team'].map(
{'radiant': 1, 'dire': -1, 'none': 0}
).fillna(0)
df['draft_advantage_enc'] = df['draft_advantage'].map(
{'radiant_advantage': 1, 'dire_advantage': -1, 'balanced': 0}
).fillna(0)
df['target'] = df['radiant_win'].astype(int)
features = ['radiant_avg_winrate', 'dire_avg_winrate', 'winrate_delta',
'first_blood_time', 'fb_advantage_enc', 'draft_advantage_enc']
if 'avg_rank_tier' in df.columns:
features.append('avg_rank_tier')
df_ml = df[features + ['target', 'match_id']].dropna()
print(f'ML-ready rows: {len(df_ml)}')
print(f'Features: {features}')
print(f'Class balance: {df_ml[\"target\"].mean():.3f} (radiant winrate)')
# Split
pool_df, test_df = train_test_split(df_ml, test_size=0.3, stratify=df_ml['target'], random_state=42)
pool_df.to_parquet('data/active/pool.parquet', index=False)
test_df.to_parquet('data/active/test.parquet', index=False)
seed_df = pool_df.head(50)
seed_df.to_parquet('data/active/seed.parquet', index=False)
remaining = pool_df.iloc[50:].reset_index(drop=True)
remaining.to_parquet('data/active/pool.parquet', index=False)
print(f'Seed: {len(seed_df)}, Pool: {len(remaining)}, Test: {len(test_df)}')
"
.venv/bin/python ~/.claude/skills/active-learner/scripts/al_agent.py \
--seed data/active/seed.parquet \
--pool data/active/pool.parquet \
--test data/active/test.parquet \
--output data/active/history_entropy.json \
--strategy entropy \
--model logreg \
--n-iterations 5 \
--batch-size 20 \
--target target
.venv/bin/python ~/.claude/skills/active-learner/scripts/al_agent.py \
--seed data/active/seed.parquet \
--pool data/active/pool.parquet \
--test data/active/test.parquet \
--output data/active/history_random.json \
--strategy random \
--model logreg \
--n-iterations 5 \
--batch-size 20 \
--target target
Формат history JSON:
[
{"iteration": 0, "n_labeled": 50, "accuracy": 0.58, "f1": 0.57, "strategy": "entropy"},
{"iteration": 1, "n_labeled": 70, "accuracy": 0.61, "f1": 0.60, "strategy": "entropy"},
...
]
Примечание: базовый accuracy ~0.52–0.58 ожидаем — задача сложная, данных на момент fb мало. Цель не абсолютное качество, а сравнение стратегий.
.venv/bin/python ~/.claude/skills/active-learner/scripts/visualize.py \
--histories data/active/history_entropy.json data/active/history_random.json \
--labels "Entropy (умный отбор)" "Random (случайный)" \
--output data/active/learning_curve.png \
--title "Active Learning: Dota 2 Win Prediction"
Создать data/active/REPORT.md:
# Active Learning Report — Dota 2 Win Prediction
## Задача
Предсказание победителя Dota 2 матча по признакам, доступным
на момент первой крови.
## Настройки
- Seed: 50 матчей
- Итераций: 5 × 20 матчей
- Модель: LogisticRegression
- Признаки: winrate_delta, first_blood_time, fb_advantage, draft_advantage
## Learning Curve

## Результаты
| N матчей | Entropy Acc | Random Acc | Entropy F1 | Random F1 |
| -------- | ----------- | ---------- | ---------- | --------- |
| 50 | ... | ... | ... | ... |
...
## Вывод
Стратегия entropy достигает accuracy X при Y размеченных матчах.
Random baseline достигает того же при Z матчах.
Экономия: Z - Y = N матчей (P%).
| Скрипт | Назначение |
|---|---|
al_agent.py | AL-цикл с entropy/margin/random стратегиями |
visualize.py | Learning curves для сравнения стратегий |
radiant_win=1 даёт ~52% accuracy