Анализ качества сна с машинным обучением, Python и SQL

Автор оригинала: Sara Robinson
  • Перевод

Последние примерно 2 месяца я ношу кольцо Oura, чтобы получать информацию о моём сне и о том, сколько я прошла шагов за день. Приложение считывает сон, разбитый на фазы (лёгкий, глубокий, быстрый), и даёт вам другие показатели, такие как частота сердечных сокращений, температура тела и частота дыхания. И для такого ботаника, как я, радостно было обнаружить, что у Oura есть API экспорта данных, чтобы я смогла лучше проанализировать их. Я загрузила данные в BigQuery и воспользовалась функцией CORR() (она потрясающая!), чтобы увидеть, какие показатели коррелируют с улучшением качества сна, а также визуализировала некоторые данные в Data Studio. Если у вас мало времени, переходите к разделу «Заключение», чтобы прочитать о том, что я узнала.

Дисклеймер: я не врач. Как раз наоборот: я ипохондрик, которому нравится писать на Python и SQL.



Получение данных из Oura в BigQuery


Я написала скрипт на Python, чтобы получить все мои текущие данные из Oura и записать их в файл JSON с разделителями новой строки (один из форматов файлов, который принимает BigQuery). Затем скрипт загружает файл в таблицу BigQuery. Я хочу написать скрипт, который запускается каждый день и добавляет самые свежие данные в мой набор данных BigQuery, но пока достаточно единоразового экспорта. Если вы пользуетесь Oura, для запуска скрипта потребуется получить токен доступа из консоли разработчика Oura. Вот мой код, который получает данные и записывает их в локальный файл:

import requests
import json

summaries = ['sleep', 'activity', 'readiness']

for data_type in summaries:
	url = 'https://api.ouraring.com/v1/' + data_type + '?start=2019-03-21'
	access_token = 'your_oura_access_token'

	result = requests.get(url,
		headers={'Content-Type':'application/json',
				'Authorization': 'Bearer {}'.format(access_token)})
	json_data = json.loads(result.content)
	with open(data_type + '.json', 'w') as jsonfile:
		for j in json_data[i]:
			json.dump(j, jsonfile)
			jsonfile.write('\n')

После выполнения этого скрипта у нас будет 3 файла JSON для каждого типа данных, которые предоставляет Oura: сон, активность и то, что они называют «готовностью» [к чему-либо; но это не бодрость; бодрость – cheerfulness], то есть того, что Oura вычисляет на основе качества вашего сна и уровня активности. Затем нужно импортировать библиотеку BigQuery и указать ссылку на набор данных:

from google.cloud import bigquery
client = bigquery.Client()
dataset_ref = client.dataset('your_dataset_name')

Теперь мы можем записать каждый файл в новую таблицу BigQuery следующим образом:

with open(filename, 'rb') as sourcefile:
	table_ref = dataset_ref.table(data_type)
	job_config = bigquery.LoadJobConfig()
	job_config.source_format = bigquery.SourceFormat.NEWLINE_DELIMITED_JSON
	job_config.autodetect = True

	job = client.load_table_from_file(
		sourcefile,
		table_ref,
		location="US",
		job_config=job_config
	)

	job.result()
	print('Job complete', job.output_rows)

Моя таблица сна теперь в BQ. Вот скриншот данных:


Поиск корреляций


А теперь самое интересное! Я хотела выяснить, какие факторы коррелировали с общим временем сна и с его качеством (количеством быстрых и глубоких фаз сна). Функция BigQuery CORR() идеально подходит, чтобы это сделать. Она использует коэффициент корреляции Пирсона: вы передаёте функции два параметра, и она возвращает число от -1 до 1, сигнализирующее о силе корреляции. 0 – корреляции между двумя значениями нет, -1 означает обратную корреляцию: когда первое значение растёт, второе падает), а 1 указывает на идеальную положительную корреляцию.

Вы никогда не увидите значений -1 или 1 в реальных данных, поэтому всё, что превышает |0,5|, сигнализирует о средней и сильной корреляции, а всё, что находится в пределах от |0,3| до |0.5|, сообщает о небольшой корреляции.

Обратите внимание, что многие из этих корреляций специфичны для меня. Моя подруга (моя ровесница) поделилась со мной своими данными Oura, и многие из её сильных корреляций отличались от моих. Каждый уникален!

Во-первых, какие показатели имели наиболее положительную или отрицательную корреляцию в моих данных? Давайте посмотрим, как частота пульса в состоянии покоя влияет на процент быстрого сна:

SELECT
  CORR(hr_average, rem / total)
FROM
  `gcp-project.bq-dataset.sleep`

Этот код вернёт значение корреляции -0,45, оно означает отрицательную среднюю корреляцию. Это имеет смысл – по мере того, как у меня увеличивается частота пульса, процент быстрых фаз сна, через которые я прохожу, снижается. Но что влияет на частоту пульса в состоянии покоя? Давайте посмотрим на температуру тела. Oura предоставляет данные об отклонении температуры тела, то есть о том, насколько ваша текущая температура отличается от средней температуры:

SELECT
  CORR(hr_average, temperature_trend_deviation)
FROM
  `gcp-project.bq-dataset.sleep`

Корреляция здесь 0,67 – очень сильная. Чем выше температура моего тела, тем выше частота пульса. Но как насчёт того, что я могу контролировать напрямую, например времени, когда я ложусь спать?

SELECT
  CORR(hr_average, EXTRACT(hour from bedtime_start))
FROM
  `gcp-project.bq-dataset.sleep`

Это соотношение составляет 0,59. Значит, как правило, чем раньше я ложусь спать, тем ниже частота пульса в состоянии покоя в течение ночи и тем больше у меня фаза быстрого сна! Быстрый сон восстанавливает ваш мозг и улучшает память, а глубокий сон помогает восстановить ваше тело. К сожалению, я не смогла найти сильной корреляции между этими факторами и процентом глубокого сна, который у меня зафиксирован. Это всё ещёе загадка для меня, хотя я читала, что полезно сократить время перед экранами до сна (по иронии судьбы я читала это на своём телефоне перед сном).

А что насчёт тренировок?


Я немного фанатик тренировок (на самом деле больше, чем немного), и, поскольку я тренируюсь почти каждый день, у меня недостаточно данных, чтобы сравнить влияние ежедневных тренировок и их отсутствия на сон. Но я обнаружила небольшую корреляцию между объёмом активности и процентом глубокого сна, который у меня был недавно. Для этого потребовался более сложный запрос JOIN для таблиц активности и сна. И мне нужно было выполнить DATE_SUB() в операторе ON из-за того, что Oura так возвращает данные:

SELECT corr(deep / total, high + medium + low) FROM (
  SELECT high, medium, low, a.summary_date
  FROM `gcp-project.oura.activity` activity
  JOIN (
	SELECT deep, total, summary_date FROM `gcp-project.oura.sleep`
  ) sleep
  ON activity.summary_date = date_sub(sleep.summary_date, interval 1 day)
 )

И я получила 0,32. Значение указывает на то, что дни, когда я активнее, слегка коррелируют с ночами, когда сон глубже.

О программном обеспечении и предубеждениях


Помимо множества интересных показателей, Oura также даёт различные оценки, которые вычисляет на основе своих данных с помощью собственных алгоритмов. Каждый день вы получаете 100 баллов за свой сон, активность и готовность. Температура тела – это один из показателей, которые используются, чтобы рассчитать показатели сна и готовности. Через пару недель использования приложения я заметила довольно сильную обратную корреляцию между температурой тела и этими показателями. Проблема здесь в том, что у большинства женщин температура тела немного повышается раз в месяц, и это нормальное явление для женщины. Сообщения в приложении довольно ясно показывают, что повышенная температура тела является симптомом того, что что-то не так:

Господи, я проспала 9 часов!

Очевидно, что температура тела повышается, когда вы больны, и, может быть, довольно трудно отличить эти процессы друг от друга, но сообщения здесь – тонкий пример того, как гендерные предубеждения закрадываются в программное обеспечение. Предполагается, что мужчины – значение по умолчанию, а поведение женщин – отклонение от этого значения. Я очень надеюсь, что команда Oura исправит эту оплошность, изменив алгоритм с учётом пола и возраста либо просто изменив сообщения, чтобы прояснить, что повышенная температура тела – это не всегда плохо.

Тем не менее я нахожу представленные приложением необработанные данные полезными и, честно говоря, увлекательными, поэтому буду продолжать носить это кольцо!

Визуализация данных о сне в Data Studio


Вернёмся к интересной части: визуализируем некоторые данные, чтобы лучше понять корреляции, которые я обнаружила. BigQuery отлично интегрируется с Data Studio, которой я могу воспользоваться, чтобы создать интересные графики временных рядов с наложением различных показателей. Когда я создаю новый отчёт в Data Studio, мне нужно выбрать BigQuery в качестве источника данных, а затем выбрать Custom Query:


Когда я введу свой запрос, я смогу использовать любой из столбцов этого запроса в своих диаграммах. Поскольку я не собираюсь отображать значения CORR, запрос нужно немного изменить:

SELECT 
	start_hr_utc, temperature_deviation, rem / total as rem_pct, deep / total as deep_pct, light / total as light_pct, low + medium + high as total_activity, steps, inactive, hr_lowest, hr_average, activity.summary_date
FROM `gcp-project.oura.activity` activity
JOIN (
  SELECT bedtime_start, extract (hour from bedtime_start) as start_hr_utc, temperature_deviation, rem, deep, light, summary_date, hr_lowest, hr_average FROM `gcp-project.oura.sleep`
) sleep
ON activity.summary_date = date_sub(sleep.summary_date, interval 1 day)

А вот моя диаграмма зависимости времени, когда начался отход ко сну, от процента быстрого сна:


За некоторыми исключениями, мой процент быстрого сна обычно увеличивается, когда я ложусь спать раньше. Как видно из следующего графика, частота пульса и фаза быстрого сна также имеют относительно сильную обратную связь:


Другой показатель, возвращаемый из API Oura, – bedtime_sleep_delta. Это разница в секундах между временем отхода ко сну нынешней и предыдущей ночью. Я вижу, что резкая смена времени отхода ко сну от ночи к ночи немного уменьшила мой процент глубокого сна:


Я надеюсь, что, продолжая собирать данные, я смогу выявить больше корреляций.

Заключение


Что я узнала, кроме навязчивого анализа данных о моём здоровье? Резюмирую:

  • Повышенная температура тела обычно коррелирует с учащённым пульсом в состоянии покоя и частотой дыхания.
  • Ранний отход ко сну почти всегда улучшает фазу быстрого сна.
  • Ложиться спать в определённое время тоже хорошо.
  • Тренировки хорошо влияют на фазу глубокого сна.
  • Помните о предвзятости при создании технологий для разнообразной аудитории. 
  • Конечно, люди – не роботы, и я не могу ложиться спать в 9 вечера каждую ночь, но всё же считаю данные очень полезными.

Эти данные сложно использовать для машинного обучения, поскольку, даже если я соберу годовой отчет, в наборе данных будет только 365 строк. Однако я думаю, что у машинного обучения есть много возможностей для работы с данными о состоянии здоровья в целом. Хотите научиться использовать машинное обучение — приходите учиться, а промокод HABR, дающий 10 % дополнительно к скидке на баннере, вам в этом поможет.



image



SkillFactory
Школа Computer Science. Скидка 10% по коду HABR

Комментарии 8

    +3
    Извините мне мою душность, но графики становятся понятнее, если у них есть оси, желательно подписанные.
      0
      Не нашел сколько заряд держит кольцо. Видать сутки или двое. Кто то купил себе очередной головняк)
        0
        Заряда хватает примерно дней на 6, сам производитель заявляет, что заряда хватает до 1 недели.
        +1
        Перед тем, как строить графики и анализировать фазы сна, было бы неплохо ознакомиться с исследованиями на тему того, возможно ли вообще определять фазу сна при помощи данных инструментов.
        Например, исследование 19 года, посвященное популярным фитнес-браслетам.
        Overall, we revealed that these devices have an alarmingly low accuracy in scoring sleep in three categories (wake, light sleep, and deep sleep) with the overall agreement ranging between 46.34% for the SC application and 53.02% for the wrist-worn MB.

        То есть погрешность в определении фазы сна составляет больше 50%, то есть браслет выдает случайные данные.

        Возможно, ситуация минимально меняется, в случае если мы добавляем показания температуры, но насколько я могу судить, для сколько-нибудь достоверного определения фазы сна необходимо как минимум ЭЭГ.
          0

          Немного оффтоп, но все же — не попадалась ли информация о том, почему фаза быстрого сна (яркие и запоминающиеся сновидения) наступает уже через 25-30 минут после засыпания? Если судить по большинству литературы, то можно было бы ожидать 60-90 минут.

            0

            Некоторые поделки ещё и давление меряют;)

            0
            Браслеты-кольца — это детская игрушка, не более. Мусор на входе — мусор на выходе. Говорю это как человек, дважды проходивший полисомнографию на weinmann somnolab.
              0
              Было бы интересно поисследовать осознанные сновидения и фазовые переходы…

              Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

              Самое читаемое