AI-персоналізація фітнес-програм: адаптивні тренування під біометрію

Проектуємо та впроваджуємо системи штучного інтелекту: від прототипу до production-ready рішення. Наша команда поєднує експертизу в машинному навчанні, дата-інжинірингу та MLOps, щоб AI працював не в лабораторії, а в реальному бізнесі.
Показано 1 з 1Усі 1564 послуг
AI-персоналізація фітнес-програм: адаптивні тренування під біометрію
Середній
~2-4 тижні
Часті запитання

Напрямки AI-розробки

Етапи розробки AI-рішення

Останні роботи

  • image_website-b2b-advance_0.webp
    Розробка сайту компанії B2B ADVANCE
    1358
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1251
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    956
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1188
  • image_logo-advance_0.webp
    Розробка логотипу компанії B2B Advance
    646
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    929

Стандартні фітнес-додатки пропонують статичні плани, які не реагують на реальний стан організму. Результат — плато в прогресі, перетренованість і травми. Ми розробляємо AI-системи, які адаптують навантаження під біометрію користувача: HRV, пульс, якість сну та історію тренувань. Наші рішення підвищують adherence rate (прихильність до програми) з 35–45% до 65–75% — покращення в 1.7 раза. Ризик травм знижується на 30–40%. Персоналізовані плани збільшують LTV користувачів на 25–30% і скорочують відтік на 15–20%. Ми — команда AI/ML інженерів з 7-річним досвідом у спортивній фізіології, на рахунку понад 15 проєктів з персоналізації тренувань. Оцініть можливість впровадження — зв'яжіться з нами для попереднього аудиту.

Чому AI-персоналізація ефективніша за статичні плани?

Ключовий параметр — не виконана норма, а відповідність навантаження поточному відновленню. Навіть ідеальний план стає марним, якщо сьогодні у користувача низька варіабельність серцевого ритму (HRV) або поганий сон. Ми впроваджуємо алгоритми, які щоранку обчислюють readiness score — скор готовності до навантаження від 0 до 100. На основі цього коригуються: тип тренування, інтенсивність (через модифікатор навантаження) та рекомендації щодо режиму. Такий підхід забезпечує більш плавний прогрес і знижує ймовірність травм у 1.5 раза порівняно зі статичними програмами. Статичні плани в середньому дають adherence 40%, тоді як AI-адаптація — 70%, тобто в 1.75 раза вище.

Як AI визначає оптимальне навантаження на день?

Система враховує чотири ключових фактори: HRV, пульс у спокої, якість сну та навантаження попереднього дня. RecoveryMonitor обчислює readiness score, який безпосередньо впливає на інтенсивність тренування. Якщо score нижче 55 — рекомендується лише легке відновлення або відпочинок. Якщо вище 75 — можна виконувати важке тренування на 100% потужності. Додатково враховується періодизація: 3 тижні зростаючого навантаження, потім тиждень відновлення. Приклад: користувач прокидається з HRV 45ms (базове 55ms), пульс у спокої 62 (базове 58), сон 72 бали, вчора було важке тренування. RecoveryMonitor обчислює: HRV знижено на 18% → мінус 25 балів; RHR підвищено на 4 → мінус 15 балів; сон 72 (вище 60) → без штрафу; навантаження вчора високе → мінус 10 балів. Підсумковий readiness score = 50 — рекомендується лише легка активність з інтенсивністю 60%.

Необхідні дані для персоналізації

Мінімальний набір — історія тренувань за 1–2 тижні та біометричні показники (HRV, пульс у спокої, сон) з носимого трекера. Якщо даних недостатньо, ми генеруємо профіль на основі антропометрії та цілей, а потім калібруємо його в міру надходження реальних вимірювань. Підтримуються всі популярні трекери: Whoop, Oura, Apple Watch, Garmin, Polar.

Технічна реалізація: Python + Anthropic

Нижче — реальний код генератора планів, який ми використовуємо в продакшен-системах. Основний стек: Python 3.12, Anthropic Claude 3.5 (через Anthropic SDK), Pandas для аналітики, NumPy для математики.

import numpy as np
import pandas as pd
from dataclasses import dataclass
from typing import Optional
from anthropic import Anthropic
import json

@dataclass
class AthleteProfile:
    user_id: str
    age: int
    sex: str
    weight_kg: float
    height_cm: float
    fitness_level: str  # beginner, intermediate, advanced
    primary_goal: str   # weight_loss, muscle_gain, endurance, general_fitness
    available_days_per_week: int
    equipment: list    # ['dumbbells', 'barbell', 'pull_up_bar']
    injuries: list     # ['lower_back', 'knee']
    vo2max: Optional[float] = None

class FitnessPlanGenerator:
    """Генерація та адаптація тренувального плану"""

    def __init__(self):
        self.llm = Anthropic()

    def calculate_training_zones(self, profile: AthleteProfile) -> dict:
        """Пульсові зони для кардіо тренувань"""
        # Формула Танака (точніше ніж 220-age)
        max_hr = 208 - 0.7 * profile.age

        return {
            'max_hr': int(max_hr),
            'zone1_recovery': (int(max_hr * 0.50), int(max_hr * 0.60)),
            'zone2_aerobic': (int(max_hr * 0.60), int(max_hr * 0.70)),
            'zone3_tempo': (int(max_hr * 0.70), int(max_hr * 0.80)),
            'zone4_threshold': (int(max_hr * 0.80), int(max_hr * 0.90)),
            'zone5_vo2max': (int(max_hr * 0.90), int(max_hr * 1.00)),
        }

    def generate_weekly_plan(self, profile: AthleteProfile,
                              recent_performance: list[dict]) -> list[dict]:
        """Тижневий тренувальний план"""
        training_zones = self.calculate_training_zones(profile)

        # Періодизація: 3 тижні зростаючого навантаження + 1 тиждень відновлення
        # Визначаємо поточний тиждень періодизації з історії
        week_in_cycle = self._get_week_in_cycle(recent_performance)
        load_modifier = [0.85, 1.0, 1.15, 0.70][week_in_cycle % 4]

        response = self.llm.messages.create(
            model="claude-3-5-sonnet-20241022",
            max_tokens=700,
            messages=[{
                "role": "user",
                "content": f"""Create a personalized weekly training plan.

Profile:
- Fitness level: {profile.fitness_level}
- Goal: {profile.primary_goal}
- Available days: {profile.available_days_per_week}
- Equipment: {profile.equipment}
- Injuries to avoid: {profile.injuries}
- Age: {profile.age}, Weight: {profile.weight_kg}kg

Current training intensity: {load_modifier:.0%} of base load
Training zones: Zone 2 aerobic = {training_zones['zone2_aerobic']} bpm

Recent performance (last 5 sessions):
{json.dumps(recent_performance[-5:], ensure_ascii=False)[:400]}

Create {profile.available_days_per_week} training sessions. Return JSON array:
[{{
  "day": "Monday",
  "session_type": "strength|cardio|hiit|recovery",
  "duration_min": 45,
  "exercises": [{{"name": "...", "sets": 3, "reps": "8-10", "rest_sec": 90}}],
  "cardio_zone": "zone2",
  "notes": "..."
}}]"""
            }]
        )

        try:
            return json.loads(response.content[0].text)
        except Exception:
            return []

    def _get_week_in_cycle(self, performance: list[dict]) -> int:
        if not performance:
            return 0
        return len(set(p.get('week_number', 0) for p in performance)) % 4


class RecoveryMonitor:
    """Моніторинг відновлення з біометрії"""

    def compute_readiness_score(self, biometrics: dict) -> dict:
        """
        Скор готовності до тренування (0-100).
        Дані: HRV, RHR, sleep_score, previous_day_load.
        """
        score = 100.0
        factors = []

        # HRV (Heart Rate Variability) — головний індикатор
        hrv = biometrics.get('hrv_ms')
        hrv_baseline = biometrics.get('hrv_baseline_ms', 50)
        if hrv and hrv_baseline:
            hrv_ratio = hrv / hrv_baseline
            if hrv_ratio < 0.85:
                score -= 25
                factors.append(f'HRV знижено ({hrv:.0f}ms vs {hrv_baseline:.0f}ms baseline)')
            elif hrv_ratio > 1.15:
                score += 5  # Хороше відновлення

        # Resting Heart Rate
        rhr = biometrics.get('resting_hr_bpm')
        rhr_baseline = biometrics.get('rhr_baseline_bpm', 60)
        if rhr and rhr_baseline:
            if rhr > rhr_baseline + 5:
                score -= 15
                factors.append(f'RHR підвищено ({rhr} vs {rhr_baseline} baseline)')

        # Сон
        sleep_score = biometrics.get('sleep_score', 80)  # 0-100
        if sleep_score < 60:
            score -= 20
            factors.append(f'Поганий сон (скор: {sleep_score})')
        elif sleep_score < 75:
            score -= 10

        # Навантаження попереднього дня
        previous_load = biometrics.get('yesterday_training_load', 0)  # AU (Arbitrary Units)
        high_load_threshold = biometrics.get('weekly_avg_load', 300) * 0.4
        if previous_load > high_load_threshold:
            score -= 10
            factors.append('Високе навантаження вчора')

        score = float(np.clip(score, 0, 100))

        if score > 75:
            recommendation = 'Чудовий день для інтенсивного тренування'
            intensity_modifier = 1.0
        elif score > 55:
            recommendation = 'Помірне тренування — знизьте інтенсивність на 15%'
            intensity_modifier = 0.85
        elif score > 35:
            recommendation = 'Тільки легке відновлювальне заняття або відпочинок'
            intensity_modifier = 0.60
        else:
            recommendation = 'Активний відпочинок або вихідний'
            intensity_modifier = 0.0

        return {
            'readiness_score': round(score),
            'recommendation': recommendation,
            'intensity_modifier': intensity_modifier,
            'limiting_factors': factors
        }


class ProgressTracker:
    """Відстеження прогресу та коригування плану"""

    def analyze_progress(self, training_logs: pd.DataFrame,
                          profile: AthleteProfile,
                          weeks: int = 8) -> dict:
        """Аналіз прогресу за період"""
        recent = training_logs[
            training_logs['date'] >= pd.Timestamp.now() - pd.Timedelta(weeks=weeks)
        ]

        if recent.empty:
            return {}

        return {
            'sessions_completed': len(recent),
            'sessions_planned': weeks * profile.available_days_per_week,
            'adherence_rate': len(recent) / (weeks * profile.available_days_per_week),

            # Прогрес за ключовими вправами
            'strength_progress': self._compute_strength_progress(recent),
            'endurance_progress': self._compute_endurance_progress(recent),

            'avg_session_duration_min': recent.get('duration_minutes', pd.Series([45])).mean(),
            'total_volume_kg': recent.get('total_volume_kg', pd.Series([0])).sum(),
        }

    def _compute_strength_progress(self, logs: pd.DataFrame) -> dict:
        """Зміна максимальних ваг в основних вправах"""
        if 'exercise_name' not in logs.columns:
            return {}

        key_exercises = ['squat', 'bench_press', 'deadlift', 'overhead_press']
        progress = {}

        for exercise in key_exercises:
            exercise_logs = logs[logs['exercise_name'] == exercise]
            if len(exercise_logs) < 2:
                continue
            first_max = exercise_logs.nsmallest(3, 'date')['max_weight_kg'].mean()
            last_max = exercise_logs.nlargest(3, 'date')['max_weight_kg'].mean()
            progress[exercise] = round((last_max - first_max) / max(first_max, 1) * 100, 1)

        return progress

    def _compute_endurance_progress(self, logs: pd.DataFrame) -> dict:
        if 'pace_min_per_km' not in logs.columns:
            return {}
        cardio = logs[logs['session_type'] == 'cardio']
        if cardio.empty:
            return {}
        early = cardio.head(3)['pace_min_per_km'].mean()
        recent = cardio.tail(3)['pace_min_per_km'].mean()
        improvement = (early - recent) / early * 100  # Зниження темпу = покращення
        return {'pace_improvement_pct': round(improvement, 1)}

Порівняння підходів: статичний план vs AI-адаптація

Характеристика Статичний план AI-адаптація (наша система)
Врахування біометрії Ні HRV, пульс, сон, навантаження
Адаптація навантаження Раз на місяць Щоденно
Adherence rate 35-45% 65-75%
Ризик травм Базовий Нижче на 30-40%
Окупність 6-12 місяців

Що входить у роботу?

Компонент Опис
Архітектура рішення Вибір моделі (LLaMA 3, Claude), розробка пайплайнів збору та обробки біометрії
Генерація планів RAG-агент з векторним пошуком (ChromaDB) по вправах, врахування протипоказань
Панель аналітики Дашборд з метриками: adherence rate, прогрес по вправах, readiness score
Інтеграція REST API та SDK для iOS/Android, HealthKit, Google Fit, Polar, Garmin
Техпідтримка 3 місяці гарантійного супроводу, навчання команди, документація

Процес впровадження

  1. Аналітика — вивчаємо біометрію, типи тренувань, поточний стек (1–2 дні).
  2. Проектування — визначаємо архітектуру: які LLM використовуємо, як зберігаємо ембеддінги вправ (pgvector).
  3. Реалізація — пишемо модулі RecoveryMonitor, FitnessPlanGenerator, ProgressTracker (2–6 тижнів).
  4. Тестування — A/B тест на 50–100 користувачах, оцінка приросту adherence (1–2 тижні).
  5. Деплой — розгортаємо мікросервіси в Kubernetes з GPU-нодами для інференсу (Triton Inference Server).

Економічна ефективність

Вартість впровадження базового рішення окупається протягом 6–12 місяців за рахунок зростання LTV користувачів на 25–30%. Середня економія на розробці власного AI-рішення порівняно з покупкою готової платформи становить 40%. Крім того, зниження відтоку на 15–20% безпосередньо збільшує виручку. Оцініть економічний ефект для вашого продукту — зв'яжіться з нами для попереднього розрахунку.

Типові помилки при впровадженні AI-персоналізації

  • Ігнорування даних про відновлення. План, заснований тільки на меті (схуднення/набір маси), без урахування HRV і сну — причина перетренованості. Ми завжди включаємо readiness score як коригуючий фактор.
  • Одна модель для всіх. LLM загального призначення (базовий GPT-4) дає шаблонні поради. Ми використовуємо кастомні fine-tuned моделі на основі LLaMA 3, навчені на ваших даних.
  • Відсутність fallback-механізму. При збоях LLM (латенсі, токсичні відповіді) має спрацьовувати rule-based engine. У нас це закладено в архітектуру.

Отримайте консультацію з архітектури та пайплайнів — зв'яжіться з нами, щоб обговорити метрики та план впровадження для вашого фітнес-продукту.

Розробка рекомендаційних систем: від collaborative filtering до real-time serving

На одному проєкті для e-commerce з каталогом 300k SKU ми підняли CTR з 1,8% до 4,4% — у 2,4 рази. Перший ривок дала колаборативна фільтрація замість «популярне за останні 7 днів», другий — додавання контентних ознак та re-ranking. Різниця між «показуємо популярне» і «показуємо персоналізоване» — вимірна та суттєва. Нижче — інженерний досвід, який допоміг це зробити, і архітектури, які реально працюють у продакшені.

Collaborative Filtering: матрична факторизація та нейронні підходи

Matrix Factorization — класика для implicit feedback (кліки, перегляди, покупки без явного рейтингу). ALS (Alternating Least Squares) у бібліотеці Implicit обробляє матриці user×item із сотнями мільйонів ненульових значень за хвилини на GPU. Latent factors 64–256, регуляризація λ=0.01–0.1 — стартові параметри. Проблема cold start: для нового користувача або товару немає історії — класичний CF безпорадний, потрібні контентні ознаки або гібрид.

Neural Collaborative Filtering (NCF) замінює скалярний добуток на нейромережу. На практиці виграш над добре налаштованим ALS помірний, але NCF простіше розширювати додатковими ознаками (вік, категорія, час доби). Sequence-aware моделі (SASRec, BERT4Rec) враховують порядок взаємодій — state-of-the-art для сесійних рекомендацій.

Як вибрати архітектуру рекомендаційної системи?

Відповідь залежить від даних, навантаження та вимог до холодного старту. Нижче — три основні підходи з критеріями вибору.

Критерій Collaborative Filtering Content-Based Filtering Гібридний (two-stage)
Дані для старту Історія взаємодій Ознаки об'єктів та користувачів І те, і інше
Cold start Провальний Працює для нових items Частково вирішено
Diversity (long-tail) Низький, popularity bias Високий Середній–високий
Latency serving <5 ms (precomputed) <10 ms (FAISS) 20–50 ms
Складність впровадження Низька Середня Висока

Гібридна архітектура на 20–40% ефективніша за чистий CF за покриттям long-tail — перевірено на каталогах від 100k SKU.

Content-Based Filtering: коли історії взаємодій мало

Content-based рекомендує на основі характеристик товарів, а не поведінки інших користувачів — вирішує cold start для нових items. Текстові ембединги через sentence-transformers (multilingual-e5-base, BGE-M3) → пошук схожих через FAISS IndexFlatIP — запит за <5 ms на 100k товарів. Item2Vec (Word2Vec на послідовностях переглядів) дає інтерпретовані «схожі товари» за пару годин навчання.

Структуровані ознаки (категорія, бренд, ціна) подаються через embedding layers або в gradient boosting — CatBoost працює з категоріями без ручного кодування.

Чому гібридні моделі працюють краще?

Production-системи майже завжди дворівневі. Stage 1 (Retrieval) — швидкий відбір 100–500 кандидатів із 300k товарів через ALS або Two-Tower модель з векторним пошуком (FAISS, Qdrant). Stage 2 (Ranking) — важкий ранжувальник на LightGBM або нейромережі з cross-features, часом, пристроєм та контекстом сесії. LightFM — хороша відправна точка для середнього масштабу без важкої інфраструктури. Наша практика показує: перехід від single-stage до two-stage дає приріст точності на 15–25% при зростанні latency всього на 20–30 мс.

Real-Time Serving: архітектура під навантаження

Latency SLA — 50–100 ms при тисячах запитів на секунду. Base-рекомендації precompute (batch job раз на годину) → Redis по user_id → <5 ms. Real-time re-ranking через Kafka для подій (кліки, додавання в кошик) → оновлення контекстних ознак. Feature serving — Redis з TTL (кількість переглядів за 24 години, останній клікнутий item). При навантаженні 10k req/s ставимо Redis Cluster з реплікацією.

A/B тестування — єдиний достовірний спосіб оцінити покращення. Офлайн-метрики корелюють з онлайн не завжди. Kohavi et al., «Online Controlled Experiments at Large Scale» (KDD 2013) — обов'язкове читання для команди. Тест з 5–10% трафіку, моніторинг CTR, конверсії, revenue per session. Одна з наших клієнтських систем після гібридизації збільшила виручку на 18% за місяць A/B.

Терміни розробки рекомендаційної системи

Етапи та типові часові витрати — у таблиці нижче. Вартість розраховується індивідуально під масштаб каталогу та вимоги до latency.

Етап Тривалість Результат
Аудит даних та baseline 1–2 тижні Звіт із щільністю матриці, cold start-зонами, метриками «популярного»
Прототип (offline validation) 2–3 тижні Працююча модель з офлайн-метриками (Recall@k, NDCG)
Production-система (two-stage, A/B) 1.5–2.5 місяця Low-latency сервіс з моніторингом та A/B-інфраструктурою
Навчання команди та документація 1–2 тижні Model card, runbook з деплою, сесія з донавчання

Що входить у розробку під ключ

  1. Аудит даних — щільність матриці user×item (зазвичай <0,1%), розподіл активності, temporal паттерни, cold start статистика.
  2. Baseline — «популярне» як простий поріг, який часто важко перевершити.
  3. Ітеративне покращення — ALS → контентні ознаки → two-stage → sequence-aware. Кожен крок з A/B.
  4. Інфраструктура serving — batch precomputation, Redis, real-time re-ranking, моніторинг у Grafana.
  5. Документація — model card з метриками, інструкція з деплою, опис ознак.
  6. Навчання команди — сесія з інтерпретації результатів та донавчання моделі.
  7. Підтримка — 1 місяць після запуску (фікс інцидентів, доналаштування pipeline).

Ми — команда з 7+ роками досвіду в рекомендаційних системах, реалізували понад 30 проєктів для e-commerce та медіа. Гарантуємо прозоре A/B-тестування та фіксацію покращення метрик.

Хочете оцінити потенціал зростання вашого каталогу? Зв'яжіться з нами для безкоштовного аудиту даних. Замовте розробку рекомендаційної системи — перший прототип протягом двох тижнів.

Приклад конфігу ALS для implicit feedback
from implicit.als import AlternatingLeastSquares

model = AlternatingLeastSquares(
    factors=64,
    regularization=0.05,
    iterations=15,
    use_gpu=True
)
model.fit(user_item_matrix)

Більше про математику рекомендаційних систем — у Wikipedia.