12.02.2021       Выпуск 373 (08.02.2021 - 14.02.2021)       Статьи

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

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

Читать>>




Экспериментальная функция:

Ниже вы видите текст статьи по ссылке. По нему можно быстро понять ссылка достойна прочтения или нет

Просим обратить внимание, что текст по ссылке и здесь может не совпадать.

Последние примерно 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 % дополнительно к скидке на баннере, вам в этом поможет.







Разместим вашу рекламу

Пиши: mail@pythondigest.ru

Нашли опечатку?

Выделите фрагмент и отправьте нажатием Ctrl+Enter.

Система Orphus