Проект решает задачу безразметочной кластеризации временных сенсорных данных: каждой строке исходного датасета присваивается метка типа физической активности (activityID) на основе паттернов движения, зафиксированных тремя IMU-модулями (hand, chest, ankle).
Основной артефакт — Jupyter Notebook solved.ipynb с полным пайплайном: EDA, feature engineering, сравнение моделей и формирование файла submission.csv для отправки на Kaggle.
- Вход: последовательные измерения аксelerometра, гироскопа, magnetometer, orientation и температуры с трёх точек тела.
- Выход: CSV с колонками
IndexиactivityIDдля всех 534 601 строк. - Особенность: активность определяется не одним измерением, а локальным временным паттерном, поэтому кластеризация выполняется на окнах из 64 строк, после чего метки переносятся обратно на исходные строки.
clustering_ml/
├── solved.ipynb # основной ноутбук с решением
├── Physical_Activity_Monitoring_unlabeled.csv # исходные данные (не в git, см. ниже)
├── submission.csv # итоговая разметка
├── image.png # скриншот результата на Kaggle
├── pyproject.toml # зависимости проекта
├── uv.lock # lock-файл uv
└── README.md
| Параметр | Значение |
|---|---|
| Файл | Physical_Activity_Monitoring_unlabeled.csv |
| Строк | 534 601 |
| Столбцов | 53 (+ технический Index после загрузки) |
| Участники | 8 (subject_id от 1 до 8) |
| Сенсоры | hand, chest, ankle (acc ±16g/±6g, gyro, magne, orientation, temperature) |
Файл не включён в репозиторий (230+ MB, лимит GitHub — 100 MB). Скачайте его с Kaggle и положите в корень проекта, либо подключите датасет в Kaggle Notebook — ноутбук ищет файл локально и в /kaggle/input.
flowchart LR
A[CSV 534k строк] --> B[Feature engineering]
B --> C[Интерполяция пропусков]
C --> D[Окна 64 строки]
D --> E[RobustScaler + PCA]
E --> F[MiniBatchKMeans k=12]
F --> G[Сглаживание сегментов]
G --> H[submission.csv]
- Предобработка: сортировка по времени, интерполяция пропусков внутри
subject_id, обработка±inf. - Feature engineering: 3D-нормы acc/gyro/magne/orientation, временные разности, rolling mean/std (окна 16 и 64), протокольные признаки (позиция в записи, номер сессии).
- Оконная агрегация: 8 374 окна × 1 171 признак (mean, std, min, max, median).
- Масштабирование:
VarianceThreshold→RobustScaler→PCA(32 компоненты, 95.7% дисперсии) +StandardScalerдля временных признаков. - Кластеризация:
MiniBatchKMeans,n_clusters=12. - Постобработка: сглаживание одиночных коротких сегментов, перенос меток на строки, перенумерация в
activityID1–10.
На подвыборке 3 000 окон сравнивались:
| Алгоритм | Silhouette (k=12) | Примечание |
|---|---|---|
| KMeans | 0.292 | лучший silhouette среди partition-моделей |
| MiniBatchKMeans | 0.254 | финальная модель — масштабируется на все окна |
| Agglomerative (average) | 0.519 | высокий silhouette, но O(n²) по памяти |
| DBSCAN | до 0.905 | до 99.3% точек помечены как шум |
| GaussianMixture | 0.191 | наихудший результат на subsample |
Метрики финальной модели (8 374 окна, sample 5 000):
- Silhouette: 0.270
- Calinski–Harabasz: 6538
- Davies–Bouldin: 1.241
Задаются в начале solved.ipynb:
| Параметр | Значение | Назначение |
|---|---|---|
EXPECTED_N_CLUSTERS |
12 | число кластеров модели |
WINDOW_SIZE |
64 | размер временного окна (строк) |
PCA_N_COMPONENTS |
32 | число PCA-компонент |
TIME_FEATURE_WEIGHT |
1.5 | вес протокольных признаков |
MIN_SEGMENT_WINDOWS |
2 | порог сглаживания коротких сегментов |
RANDOM_STATE |
42 | воспроизводимость |
Требуется Python ≥ 3.12.10.
# установка uv: https://docs.astral.sh/uv/
uv sync
uv pip install ipykernel jupyter # для запуска ноутбука
uv run jupyter notebook solved.ipynbpython -m venv .venv
.venv\Scripts\activate # Windows
# source .venv/bin/activate # Linux / macOS
pip install -e .
pip install ipykernel jupyter
jupyter notebook solved.ipynbЗапустите все ячейки ноутбука сверху вниз. В конце будет создан или перезаписан submission.csv.
Index,activityID
0,1
1,2
...Index— порядковый номер строки в исходном CSV (0 … 534 600).activityID— метка кластера, целое число от 1 до 10.
Файл submission.csv отправлен на соревнование Kaggle. Лучший результат:
| Показатель | Значение |
|---|---|
| Score | 0.69634 |
| Место в leaderboard | 16 |
| Участник | Ryabov Alexandr |
| Число отправок | 13 |
- В обучающих данных нет ground-truth меток — качество оценивается только внутренними метриками и на Kaggle leaderboard.
- Модель обучается с k = 12, но после постобработки в submission остаётся 10 устойчивых кластеров (singleton-сегменты сглаживаются).
- «Спокойные» кластеры схожи по сырым нормам acc; разделение опирается на оконные rolling-статистики и PCA-признаки.
- Колонка пульсометра в текущем CSV отсутствует, хотя упоминается в описании задачи.
- pandas ≥ 3.0
- scikit-learn ≥ 1.8
- matplotlib ≥ 3.10
- seaborn ≥ 0.13
Полный список — в pyproject.toml.
