Настройка FILE-задач
FILE — задачи, где участник загружает файл с решением. Подходит для документов, презентаций, кода и ML-соревнований с автоматической проверкой.
Типы FILE-задач
| Тип | Проверка | Результат | Применение |
|---|
| Документы | Ручная | Отложенный | Презентации, отчёты |
| Код/архивы | Ручная | Отложенный | Проекты без автопроверки |
| CSV-предсказания | Автоматическая, Python-скриптом | Обычно 5-60 секунд | Data Science соревнования |
Создание FILE-задачи
Шаг 1: Основные поля
| Поле | Описание | Обязательное |
|---|
| Название | Название задачи | ✅ |
| Условие | Что нужно загрузить (Markdown) | ✅ |
| Баллы | Максимальное количество баллов | ✅ |
| Порядок | Позиция в треке | ✅ |
Шаг 2: Настройки файла
| Параметр | Описание |
|---|
| Разрешённые форматы | Какие типы файлов принимать |
| Максимальный размер | Лимит размера файла |
| Количество файлов | Один или несколько |
Шаг 3: Тип проверки
| Тип | Описание |
|---|
| Ручная | Файл оценивает организатор или жюри |
| Автоматическая | Метрику рассчитывает ваш Python-скрипт |
Ручная проверка
Когда использовать
- Презентации и документы
- Код проектов для code review
- Творческие работы
- Материалы без формального критерия оценки
Настройка форматов
Документы:
PDF, DOC, DOCX, PPT, PPTX, ODT
Архивы:
ZIP, RAR, TAR, TAR.GZ, 7Z
Изображения:
PNG, JPG, JPEG, GIF, SVG
Код:
PY, JS, TS, JAVA, CPP, C, GO, RS
Размер файла
| Тип контента | Рекомендуемый лимит |
|---|
| Документы | 10-20 МБ |
| Презентации | 20-50 МБ |
| Архивы с кодом | 50-100 МБ |
| Изображения | 5-10 МБ |
Критерии оценки
Укажите критерии для проверяющих:
## Критерии оценки презентации (100 баллов)
### Содержание (50 баллов)
- Полнота раскрытия темы
- Актуальность информации
- Логика изложения
### Оформление (30 баллов)
- Дизайн слайдов
- Читаемость текста
- Качество визуализаций
### Техническое решение (20 баллов)
- Реализуемость идеи
- Техническая грамотность
Автоматическая проверка
Когда использовать
- ML-чемпионаты и Data Science соревнования
- Kaggle-подобные задачи
- Любые задачи, где качество решения выражается числом
Как это устроено
Готового списка метрик на платформе нет. Метрику задаёт Python-скрипт, который вы загружаете вместе с задачей: платформа запускает его на каждой отправке участника и берёт число, которое скрипт напечатал. Так можно посчитать что угодно — от accuracy до собственной формулы с бизнес-штрафами и проверкой формата сабмита.
Отдельного типа задач «ML» больше нет: автопроверка включается тумблером в FILE-задаче.
Что нужно подготовить
| Файл | Что это | Обязателен |
|---|
Скрипт проверки (.py) | Скачивает эталон и ответ участника, считает метрику, печатает JSON | ✅ |
| Публичный тест | Эталонные ответы (ground truth) для текущего зачёта. Участникам не выдаётся — файл виден только скрипту | ✅ |
| Приватный тест | Скрытый эталон для финального пересчёта | — |
Данные для участников (train.csv, test.csv, sample_submission.csv) сюда не загружаются — выложите их ссылками в условии задачи.
Включение автопроверки
- Создайте задачу типа Файл
- В разрешённых форматах оставьте
.csv, задайте лимит размера
- Включите тумблер Автоматическая проверка
- Выберите режим лучшего результата: Больше — лучше или Меньше — лучше (для RMSE, MAE, LogLoss — «меньше»)
- Загрузите скрипт проверки, публичный и — если нужен финальный пересчёт — приватный тест
Процесс проверки
1. Участник загружает файл с предсказаниями
2. Решение создаётся без балла, со статусом «на проверке»
3. Платформа выдаёт подписанные ссылки на скрипт, эталоны и ответ участника
4. Проверяющий сервис скачивает скрипт и запускает его
5. Из stdout читается JSON с баллом
6. Балл записывается в решение — участник видит результат, обычно за 5-60 секунд
Контракт скрипта проверки
Скрипт запускается так:
python scoring.py \
--public_test_url=<url> \
--public_prediction_url=<url> \
[--private_test_url=<url>] \
[--private_prediction_url=<url>]
| Аргумент | Значение | Когда передаётся |
|---|
--public_test_url | Ссылка на публичный эталон | Всегда |
--public_prediction_url | Ссылка на файл участника | Всегда |
--private_test_url | Ссылка на приватный эталон | Если загружен приватный тест |
--private_prediction_url | Зарезервирован | Сейчас не передаётся |
Аргументы — это ссылки, а не пути к файлам. Скрипт скачивает данные сам; pandas.read_csv() принимает URL напрямую.
Скрипт печатает в stdout одну строку JSON и завершается с кодом 0:
{"public_score": 73.4512, "private_score": null}
| Правило | Почему так |
|---|
| В stdout — только этот JSON | Вывод разбирается целиком, любой лишний print ломает проверку |
| Диагностика — в stderr | Она сохраняется и доступна при разборе проблем |
Код возврата 0 | При ненулевом решение получает 0 баллов и статус «ошибка» |
private_score: null | Если приватный тест не загружен |
| Объявлены все четыре аргумента | argparse завершается с ошибкой на неизвестном ключе |
Шкала балла
Значение public_score записывается в балл решения как есть, без пересчёта на баллы задачи. Если задача стоит 100 баллов, а скрипт вернул 0.87 (F1), участник получит 0.87 балла из 100 — не 87.
Приводите метрику к шкале задачи внутри скрипта:
SCALE = 100.0 # задача на 100 баллов
public_score = round(f1 * SCALE, 4) # 0.87 -> 87.0
Для метрик, где меньше — лучше, есть два рабочих варианта:
| Вариант | Что возвращает скрипт | Режим задачи |
|---|
| Отдать саму ошибку | rmse | Меньше — лучше |
| Перевести ошибку в баллы | max(0, 100 * (1 - rmse / baseline)) | Больше — лучше |
Первый честнее для лидерборда, второй нагляднее для участников.
Пример скрипта
Рабочий скелет — подставьте свою метрику в calc_score. Проверка формата сабмита здесь не лишняя: без неё лишняя строка или дубль id дадут молча неверный балл.
#!/usr/bin/env python3
"""Скоринг сабмита: сравниваем predictions с ground truth."""
import argparse
import json
import sys
import pandas as pd
from sklearn.metrics import f1_score
SCALE = 100.0 # метрика [0..1] -> баллы задачи (points = 100)
ID_COL = "id"
TARGET_COL = "prediction"
def load(url, what):
df = pd.read_csv(url)
for col in (ID_COL, TARGET_COL):
if col not in df.columns:
raise ValueError(f"{what}: нет колонки '{col}', есть {list(df.columns)}")
return df
def calc_score(test_url, prediction_url):
gt = load(test_url, "ground truth")
pred = load(prediction_url, "submission")
if pred[ID_COL].duplicated().any():
raise ValueError("в сабмите есть дубликаты id")
merged = gt.merge(pred, on=ID_COL, how="left", suffixes=("_true", "_pred"))
missing = merged[f"{TARGET_COL}_pred"].isna().sum()
if missing:
raise ValueError(f"в сабмите нет предсказаний для {missing} объектов")
print(f"объектов: {len(merged)}", file=sys.stderr) # диагностика -> только stderr
return f1_score(
merged[f"{TARGET_COL}_true"],
merged[f"{TARGET_COL}_pred"],
average="weighted",
)
def main():
parser = argparse.ArgumentParser()
parser.add_argument("--public_test_url", required=True)
parser.add_argument("--public_prediction_url", required=True)
parser.add_argument("--private_test_url", default=None)
parser.add_argument("--private_prediction_url", default=None)
args = parser.parse_args()
try:
public_score = calc_score(args.public_test_url, args.public_prediction_url)
private_score = None
if args.private_test_url:
# приватного сабмита нет - сверяем тот же файл со скрытым эталоном
prediction_url = args.private_prediction_url or args.public_prediction_url
private_score = calc_score(args.private_test_url, prediction_url)
print(json.dumps({
"public_score": round(public_score * SCALE, 4),
"private_score": round(private_score * SCALE, 4) if private_score is not None else None,
}))
except Exception as exc:
print(f"ERROR: {exc}", file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()
Замена метрики — одна строка в calc_score:
| Задача | Код | Настройки |
|---|
| Классификация | f1_score(y_true, y_pred, average="weighted") | SCALE = 100.0, больше — лучше |
| Бинарная с вероятностями | roc_auc_score(y_true, y_score) | SCALE = 100.0, больше — лучше |
| Регрессия | mean_squared_error(y_true, y_pred, squared=False) | SCALE = 1.0, меньше — лучше |
Окружение запуска
| Параметр | Значение |
|---|
| Python | 3.10, изолированный контейнер, один процесс на решение |
| Таймаут | 300 секунд, дальше процесс снимается и решение получает ошибку |
| Data / ML | pandas, numpy 1.23.5, scipy, pyarrow, scikit-learn, scikit-image, torch (CPU), transformers |
| Прочее | evaluate, bert_score, opencv-python-headless, requests, pydantic, PyYAML, tqdm |
| Сеть | Рассчитывайте только на ссылки из аргументов: доступ к внешним сервисам не гарантируется, ставить пакеты на лету нельзя |
Если нужной библиотеки нет в списке — напишите в поддержку, образ дополняется под соревнование.
Публичный и приватный зачёт
Приватный тест — это второй эталон, с которым сверяется тот же самый файл участника: отдельную приватную отправку платформа не запрашивает. Скрипт получает --private_test_url и возвращает второе число в private_score.
| Лидерборд | Настройка | Что показывает |
|---|
| Публичный | По умолчанию | Балл по публичному эталону, виден участникам сразу |
| Приватный | «Приватный балл» в настройках лидерборда | Балл по скрытому эталону, обычно открывают после дедлайна |
Направление ранжирования (по убыванию / по возрастанию) и правило зачёта (лучший результат / сумма попыток) задаются в настройках лидерборда, а режим «больше / меньше — лучше» в задаче определяет, какую из отправок участника платформа считает его лучшей.
Ограничения попыток
Для ручной проверки
| Значение | Использование |
|---|
| 1 | Финальная загрузка |
| Без ограничений | Можно обновлять файл |
Для ML-соревнований
| Тип ограничения | Описание |
|---|
| В день | Например, 5 попыток в сутки |
| Всего | Общий лимит за соревнование |
Рекомендации:
- Короткое соревнование (1-3 дня): 10-20 попыток в день
- Длинное соревнование (1-4 недели): 3-5 попыток в день
- Без ограничений: только для обучающих соревнований
Учёт результата
| Настройка | Где задаётся | Что делает |
|---|
| Больше — лучше / Меньше — лучше | В задаче, рядом с автопроверкой | Определяет, какую отправку участника считать лучшей |
| Лучший результат / Сумма попыток | В настройках лидерборда | Как сворачивать несколько отправок в итоговый балл |
| Приватный балл | В настройках лидерборда | Ранжировать по скрытому эталону вместо публичного |
Лимит попыток считается на участника, а не на команду: в командном конкурсе каждый участник расходует свои попытки.
Условие ML-задачи
Структура описания
# Название задачи
## Описание
Краткое описание бизнес-задачи и цели.
## Данные
- **train.csv** — обучающая выборка (N объектов, M признаков)
- **test.csv** — тестовая выборка (K объектов)
- **sample_submission.csv** — пример формата ответа
### Описание признаков
| Колонка | Тип | Описание |
|---------|-----|----------|
| id | int | Уникальный идентификатор |
| feature_1 | float | Описание признака 1 |
| ... | ... | ... |
| target | float | Целевая переменная (только в train) |
## Метрика
RMSE (Root Mean Square Error) — чем меньше, тем лучше.
## Формат ответа
CSV-файл с колонками `id` и `prediction`.
## Ограничения
- 5 попыток в день
- Максимальный размер файла: 10 МБ
## Baseline
RMSE = 0.45 (среднее значение target)
Чек-лист условия
Валидация файла
Что проверяет платформа
| Проверка | Действие при ошибке |
|---|
| Расширение файла | Отклонить загрузку |
| Размер файла | Отклонить загрузку |
| Лимит попыток | Отклонить отправку |
| Сроки трека и таймер задачи | Отклонить отправку |
Расширение и размер проверяются дважды — в браузере до загрузки и на сервере. Если список разрешённых форматов пуст, принимается любое расширение.
Что проверяет скрипт
Содержимое файла платформа не разбирает — это работа скрипта проверки. Заложите в него всё, что должно приводить к ошибке или нулю:
if pred[ID_COL].duplicated().any():
raise ValueError("в сабмите есть дубликаты id")
if len(pred) != len(gt):
raise ValueError(f"строк {len(pred)}, ожидалось {len(gt)}")
Текст исключения попадает в stderr и сохраняется вместе с решением, поэтому пишите сообщения так, чтобы по ним можно было ответить участнику.
Примеры задач
Презентация проекта
Название: Презентация MVP
Условие:
Загрузите презентацию вашего MVP.
**Требования:**
- Формат: PDF или PPTX
- Объём: 10-15 слайдов
- Содержание: проблема, решение, демо, бизнес-модель
**Критерии оценки:**
- Качество идеи: 40%
- Презентация решения: 30%
- Бизнес-потенциал: 30%
Настройки:
- Форматы: PDF, PPTX
- Размер: до 50 МБ
- Проверка: ручная
- Баллы: 100
ML-соревнование
Название: Предсказание оттока клиентов
Условие (Markdown в поле «Условие»):
Предскажите вероятность оттока клиентов телеком-компании.
Данные: train.csv — 5000 клиентов с историей, test.csv — 2000 клиентов для предсказания, sample_submission.csv — пример формата.
Метрика: AUC-ROC, приведённая к 100 баллам. Чем больше, тем лучше.
Формат ответа: CSV с колонками id,prediction, 2000 строк, prediction — вероятность от 0 до 1.
Baseline: AUC-ROC = 0.50 (случайное предсказание).
Настройки задачи:
- Тип: Файл
- Формат:
.csv, до 10 МБ
- Автоматическая проверка: включена
- Режим: больше — лучше
- Скрипт проверки:
scoring.py с roc_auc_score и SCALE = 100.0
- Публичный тест:
public_gt.csv с колонками id,prediction
- Попытки: 5 в день
- Баллы: 100
Статистика
Для ручной проверки
| Метрика | Описание |
|---|
| Загружено | Количество загруженных файлов |
| На проверке | Ожидают проверки |
| Проверено | Оценённые работы |
| Средний балл | Средняя оценка |
Для задач с автопроверкой
| Что доступно | Где смотреть |
|---|
| Все отправки с баллом, временем и статусом проверки | Раздел «Решения» |
| Ошибки проверки — статус «ошибка», текст из stderr скрипта сохраняется вместе с решением | Карточка решения |
| Лучшая отправка участника — по режиму «больше / меньше — лучше» | Раздел «Решения» |
| Рейтинг участников | Лидерборд по задаче или треку |
Частые ошибки
При создании
| Ошибка | Последствие |
|---|
| Нет sample_submission | Участники не знают формат |
| Нет описания колонок | Непонятно что предсказывать |
| Слишком много попыток | Переобучение на тесте |
| Нет baseline | Непонятно хороший ли результат |
При ручной проверке
| Ошибка | Решение |
|---|
| Файлы участников не открываются | Укажите конкретные форматы |
| Критерии субъективны | Опишите шкалу оценок |
| Долгая проверка | Привлеките нескольких проверяющих |
При автопроверке
| Симптом | Причина | Решение |
|---|
| Все решения получают 0 баллов | Скрипт печатает в stdout что-то кроме JSON | Диагностику — в stderr, JSON — единственный вывод |
| Баллы вида 0.87 вместо 87 | Метрика не приведена к шкале задачи | Умножить на количество баллов задачи |
| Ошибка на каждой отправке | argparse падает на непредусмотренном аргументе | Объявить все четыре аргумента |
| Задача не сохраняется | Не загружен скрипт или публичный тест | Оба файла обязательны при включённой автопроверке |
| Проверка обрывается по таймауту | Внутри скоринга тяжёлые вычисления или загрузка моделей | Скрипт должен только сравнивать файлы, без инференса |
Частые вопросы
В: Где выбрать метрику из списка (RMSE, F1, AUC)?
О: Такого списка нет. Метрика — это ваш Python-скрипт: он считает любую формулу и печатает итоговое число. Готовый шаблон — в разделе Пример скрипта.
В: Скрипт отработал, но у всех 0 баллов. Почему?
О: Скорее всего скрипт печатает в stdout что-то кроме JSON — отладочный print или warning библиотеки. Всю диагностику отправляйте в stderr.
В: Участники получают баллы вида 0.87 вместо 87. Почему?
О: Метрика не приведена к шкале задачи. Умножьте её на количество баллов задачи внутри скрипта.
В: Можно ли менять метрику после старта?
О: Технически да — достаточно перезагрузить скрипт. Но уже проверенные решения не пересчитываются, а для участников это меняет правила по ходу. Не рекомендуется.
В: Как скрыть ground truth от участников?
О: Публичный и приватный тесты загружаются отдельно и не отдаются в API задачи — скачать их участник не может. Система передаёт их только скрипту проверки.
В: Участник загрузил неверный формат. Что делать?
О: Неподходящее расширение и превышение размера платформа отклоняет сама. Всё остальное — работа скрипта: пусть он завершается с понятным сообщением в stderr.
В: Как организовать командное ML-соревнование?
О: Создайте командный конкурс — решения привязываются к команде и попадают в командный лидерборд. Учтите, что лимит попыток считается на участника, а не на команду.
Связанные статьи