Реализация AI-анализа качества сна по данным датчиков в мобильном приложении
Акселерометр на запястье во время сна пишет характерные паттерны для разных фаз: глубокий сон — почти полная неподвижность с периодическими микродвижениями, REM — редкие движения с нарастающим пульсом, бодрствование — явная активность. Задача модели — правильно разметить 8 часов этих данных.
Источники сырых данных
На iOS данные сна доступны через HealthKit как HKCategoryType(.sleepAnalysis). Apple Watch и сторонние трекеры (Oura, Fitbit, Garmin) записывают туда этапы сна. Но если нужны сырые данные акселерометра и GyroScope для собственной ML-классификации — HealthKit их не отдаёт в ретроспективе. Нужно фоновое приложение с CMMotionManager, пишущее данные на диск.
class NightMotionRecorder {
private let motionManager = CMMotionManager()
private var dataBuffer: [(timestamp: Date, x: Double, y: Double, z: Double)] = []
func startNightRecording() {
guard motionManager.isAccelerometerAvailable else { return }
motionManager.accelerometerUpdateInterval = 1.0 / 25.0 // 25 Hz достаточно для сна
motionManager.startAccelerometerUpdates(to: .main) { [weak self] data, error in
guard let data = data else { return }
self?.dataBuffer.append((
timestamp: Date(),
x: data.acceleration.x,
y: data.acceleration.y,
z: data.acceleration.z
))
}
}
}
25 Hz — баланс между точностью и расходом батареи. Сон не требует 100 Hz акселерометра. Background режим для CMMotionManager нужен через UIBackgroundModes: motion в Info.plist — но iOS агрессивно завершает фоновые задачи. Надёжнее: BGProcessingTask для ночной обработки данных с частичными записями.
SpO2 из HealthKit
Данные пульсоксиметрии через HKQuantityType(.oxygenSaturation). Apple Watch Series 6+ пишет SpO2 каждые 1-2 часа ночью в фоне. Падение ниже 90% — признак апноэ сна. Но Apple не пишет ночной SpO2 непрерывно (из соображений батареи), поэтому прерывистые данные нужно интерполировать осторожно.
Алгоритм классификации фаз сна
Стандартная задача — 4 класса: Wake, Light NREM, Deep NREM (N3), REM. Клинически валидный стандарт — полисомнография (PSG) с ЭЭГ. Акселерометра и ЧСС достаточно для Wake/Sleep разделения с точностью ~85%, полная 4-стадийная классификация — 60–75% agreement с PSG.
Feature engineering из акселерометра
Из сырого 25 Hz сигнала за 30-секундные эпохи вычисляем:
- Activity count — сумма абсолютных изменений вектора ускорения (Cole-Kripke алгоритм)
- ZCR (Zero Crossing Rate) — частота пересечений нуля, коррелирует с мелкой моторикой
-
ENMO (Euclidean Norm Minus One) — стандарт в актиграфии,
sqrt(x²+y²+z²) - 1g, убирает гравитацию - Angle z-axis — угол запястья, характерный для разных поз сна
Из ЧСС (если есть) добавляем:
- ЧСС в покое vs текущая ЧСС (дельта)
- HRV (RMSSD из RR-интервалов) — в REM HRV выше чем в deep sleep
Модель
Random Forest на этих фичах даёт разумную базу. Для temporal context — LSTM поверх RF-фич: RF выдаёт вектор признаков для каждой 30-сек эпохи, LSTM учитывает последовательность эпох. Это паттерн из исследований Stanford Sleep Lab.
# Feature extraction для одной эпохи (30 сек, 750 семплов при 25 Hz)
def extract_epoch_features(epoch_data):
x, y, z = epoch_data[:, 0], epoch_data[:, 1], epoch_data[:, 2]
enmo = np.maximum(np.sqrt(x**2 + y**2 + z**2) - 1, 0)
angle_z = np.arctan(z / np.sqrt(x**2 + y**2 + 1e-6)) * 180 / np.pi
return {
'enmo_mean': np.mean(enmo),
'enmo_std': np.std(enmo),
'enmo_max': np.max(enmo),
'angle_z_mean': np.mean(angle_z),
'angle_z_std': np.std(angle_z),
'activity_count': np.sum(np.abs(np.diff(enmo)))
}
Конвертация и деплой модели
Для iOS: sklearn Random Forest → coremltools.converters.sklearn.convert() → .mlmodel. LSTM слой → отдельная CoreML нейросеть. Объединяем в CoreML Pipeline. Для Android: обе модели через TFLite с делегатом NNAPI для аппаратного ускорения.
UI: интерпретация результата
Гипнограмма (график фаз сна по оси времени) — стандартный способ отображения. Дополнительно: Sleep Score как агрегатная метрика, breakdown по времени в каждой фазе, выявленные паттерны (позднее засыпание, частые пробуждения).
Рекомендации привязываем к конкретным паттернам: «Доля N3 (глубокого сна) упала с 18% до 9% за последние 5 ночей» + конкретный совет, а не «улучшите качество сна».
Процесс работы
Выбор источников данных (HealthKit vs сырой акселерометр). Разработка pipeline обработки ночных данных. Feature engineering и обучение модели классификации. Конвертация и интеграция в приложение. UI компоненты гипнограммы и рекомендаций. Тестирование точности на реальных данных с носимых устройств.
Ориентиры по срокам
Wake/Sleep детектор с актиграфией и базовым UI — 1–2 недели. Полноценный 4-стадийный классификатор с гипнограммой и персонализированными рекомендациями — 3–5 недель.







