<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Data Science on kenji.blog</title><link>http://kenji.blog/ru/categories/data-science/</link><description>Recent content in Data Science on kenji.blog</description><generator>Hugo -- gohugo.io</generator><language>ru</language><copyright>kenjinote</copyright><lastBuildDate>Sat, 12 Sep 2026 12:00:00 +0900</lastBuildDate><atom:link href="http://kenji.blog/ru/categories/data-science/index.xml" rel="self" type="application/rss+xml"/><item><title>Будни инженера, управляющего своим здоровьем с помощью смарт-колец (Лайфхаки для здоровья)</title><link>http://kenji.blog/ru/p/engineer-health-hacks-wearables/</link><pubDate>Sat, 12 Sep 2026 12:00:00 +0900</pubDate><guid>http://kenji.blog/ru/p/engineer-health-hacks-wearables/</guid><description>&lt;img src="http://kenji.blog/p/engineer-health-hacks-wearables/img/eyecatch.jpg" alt="Featured image of post Будни инженера, управляющего своим здоровьем с помощью смарт-колец (Лайфхаки для здоровья)" />&lt;h2 id="1-введение-на-стыке-программной-инженерии-и-биохакинга">1. Введение: На стыке программной инженерии и биохакинга
&lt;/h2>&lt;p>Современная программная инженерия — это изнурительный интеллектуальный труд, связанный с экстремальными когнитивными нагрузками и длительным сидячим образом жизни (Sedentary Lifestyle). Постоянное изучение меняющихся технологических стеков, поиск багов в сложных распределенных системах и давление дедлайнов. Чтобы преодолеть всё это, недостаточно просто полагаться на &amp;ldquo;силу воли&amp;rdquo; или &amp;ldquo;упорство&amp;rdquo;. Необходим подход, при котором вы настраиваете свое тело как аппаратное обеспечение, подобно отладке системы — то есть &amp;ldquo;биохакинг&amp;rdquo; (Biohacking).&lt;/p>
&lt;p>В прошлом мы полагались на субъективные ощущения (эвристику) вроде &amp;ldquo;сегодня я чувствую себя хорошо или плохо&amp;rdquo;, но сегодня, благодаря распространению высокопроизводительных носимых устройств, таких как Oura Ring, Apple Watch и Garmin, мы можем неинвазивно получать биометрические данные 24 часа в сутки, 365 дней в году. В этой статье объясняется, как получать биометрические данные (ВСР, ЧСС покоя, архитектура сна) и данные о производительности (метрики кодирования с помощью WakaTime и т.д.) через API, и проводить корреляционный анализ с использованием подходов науки о данных с помощью Python и Pandas. Мы также очень подробно разберем научно обоснованные лайфхаки для здоровья инженеров, такие как математические модели циркадных ритмов и оптимальное время приема кофе на основе периода полувыведения кофеина.&lt;/p>
&lt;h2 id="2-то-что-нельзя-измерить-нельзя-контролировать-оборудование-для-получения-биометрических-данных">2. То, что нельзя измерить, нельзя контролировать: Оборудование для получения биометрических данных
&lt;/h2>&lt;p>Каждый сенсор (носимое устройство) для получения биометрических данных имеет свои сильные стороны. Первым шагом в управлении здоровьем на основе данных является выбор оптимального устройства в соответствии с вашими целями.&lt;/p>
&lt;h3 id="21-oura-ring-generation-3--4">2.1 Oura Ring (Generation 3 / 4)
&lt;/h3>&lt;p>Поскольку данные собираются непосредственно с артерий пальца, оно отличается очень высокой точностью измерения частоты сердечных сокращений во время сна, вариабельности сердечного ритма (ВСР) и изменения температуры поверхности тела по сравнению с умными часами на запястье. На пальцах густая сеть капилляров, что позволяет оптическому датчику пульса (PPG: фотоплетизмография) получать данные с низким уровнем шума. Кроме того, устройство обладает богатым REST API, позволяющим легко экспортировать необработанные данные в формате JSON через OAuth2.0, что делает его самым удобным для &amp;ldquo;хакинга&amp;rdquo; устройством для инженеров.&lt;/p>
&lt;h3 id="22-apple-watch-series--ultra">2.2 Apple Watch Series / Ultra
&lt;/h3>&lt;p>Отлично подходит для отслеживания активности, измерения насыщения крови кислородом (SpO2) и электрокардиограммы (ЭКГ). Это лучшее устройство для отслеживания уровня активности в течение дня и измерения ВСР по требованию через приложения для осознанности (приложение &amp;ldquo;Дыхание&amp;rdquo;). Однако экспорт данных требует использования HealthKit, и для прямого доступа из Python и т.д. потребуется промежуточный шаг, например, экспорт в CSV через приложения iOS (такие как AutoSleep или HealthFit).&lt;/p>
&lt;h3 id="23-garmin-fenix--forerunner">2.3 Garmin (Fenix / Forerunner)
&lt;/h3>&lt;p>Помимо точности GPS-трекинга, уникальный показатель остатка энергии под названием &amp;ldquo;Body Battery&amp;rdquo; является превосходным. Он рассчитывается на основе ВСР и уровня стресса. Данные Garmin можно получить через API Garmin Connect, но поскольку существует барьер в виде корпоративного API, индивидуальным разработчикам необходимо использовать библиотеки с открытым исходным кодом или инструменты для парсинга, созданные энтузиастами.&lt;/p>
&lt;p>В этой статье основное внимание будет уделено данным с &lt;strong>Oura Ring&lt;/strong>, которое является вершиной в отслеживании сна и восстановления, и из которого чрезвычайно легко извлекать данные через API, а также данным с &lt;strong>WakaTime&lt;/strong>, который измеряет время кодирования в качестве плагина для IDE (таких как VS Code и IntelliJ).&lt;/p>
&lt;h2 id="3-базовая-теория-биометрических-данных-наука-о-данных-вср-и-чсс-покоя">3. Базовая теория биометрических данных: Наука о данных ВСР и ЧСС покоя
&lt;/h2>&lt;p>С точки зрения науки о данных &amp;ldquo;восстановление&amp;rdquo; (Recovery) определяется не просто таким показателем, как &amp;ldquo;долго спал — значит хорошо&amp;rdquo;, а двумя следующими главными метриками.&lt;/p>
&lt;h3 id="31-вср-вариабельность-сердечного-ритма-heart-rate-variability-и-моделирование-вегетативной-нервной-системы">3.1 ВСР (Вариабельность сердечного ритма: Heart Rate Variability) и моделирование вегетативной нервной системы
&lt;/h3>&lt;p>Сердце не бьется в постоянном ритме, как метроном. Например, даже если частота сердечных сокращений составляет 60 ударов в минуту, интервал между каждым ударом (интервал R-R) всегда колеблется, например, &amp;ldquo;0,92 секунды&amp;rdquo;, &amp;ldquo;1,05 секунды&amp;rdquo;, &amp;ldquo;0,98 секунды&amp;rdquo;. Количественное выражение величины этого колебания — это ВСР (вариабельность сердечного ритма).&lt;/p>
&lt;p>ВСР напрямую отражает баланс вегетативной нервной системы, то есть &amp;ldquo;симпатической нервной системы (газ)&amp;rdquo; и &amp;ldquo;парасимпатической нервной системы (тормоз)&amp;rdquo;. В состоянии стресса, переутомления или после употребления алкоголя симпатическая нервная система доминирует, биение сердца становится более равномерным, а ВСР снижается. Наоборот, в состоянии полного расслабления и восстановления доминирует парасимпатическая (блуждающий нерв) нервная система, пульс динамически колеблется в такт дыханию, и ВСР повышается.&lt;/p>
&lt;p>Существуют два подхода к расчету ВСР: во временной области (Time-domain) и в частотной области (Frequency-domain). Наиболее часто используемым в анализе во временной области и применяемым в Oura Ring и Apple Watch является &lt;strong>RMSSD (Root Mean Square of Successive Differences)&lt;/strong>. Это среднеквадратичное значение разности между последовательными межкардиоинтервалами (RR-интервалами).&lt;/p>
&lt;p>Строго математически это выражается следующим образом:&lt;/p>
$$ RMSSD = \sqrt{\frac{1}{N-1} \sum_{i=1}^{N-1} (RR_{i+1} - RR_i)^2} $$&lt;p>Где,&lt;/p>
&lt;ul>
&lt;li>$N$ — общее количество измеренных сердечных сокращений&lt;/li>
&lt;li>$RR_i$ — $i$-й RR-интервал (в миллисекундах)&lt;/li>
&lt;/ul>
&lt;p>Для инженера, если ВСР (RMSSD) при пробуждении утром значительно ниже индивидуального базового уровня (скользящее среднее за последние несколько недель), это позволяет принять решение на основе данных: &amp;ldquo;Сегодня следует избегать проектирования архитектуры с высокой когнитивной нагрузкой или деплоя в продакшен, а вместо этого посвятить день расширению тестового покрытия или написанию документации&amp;rdquo;.&lt;/p>
&lt;h3 id="32-частота-сердечных-сокращений-в-покое-чсс-покоя---rhr-resting-heart-rate-и-сигналы-восстановления">3.2 Частота сердечных сокращений в покое (ЧСС покоя - RHR: Resting Heart Rate) и сигналы восстановления
&lt;/h3>&lt;p>RHR (ЧСС покоя) — это количество ударов сердца в минуту, когда тело полностью расслаблено (обычно во время сна). После употребления алкоголя, переедания в позднее время или в качестве раннего симптома болезни (например, инфекции), когда организм тратит энергию на внутренний метаболизм или иммунную реакцию, RHR поднимается на несколько или даже более десяти ударов в минуту выше базового уровня.&lt;/p>
&lt;p>Чем ниже RHR, тем больше крови сердечная мышца может перекачать за один удар (высокий ударный объем), что указывает на высокую аэробную способность и степень восстановления после усталости. В идеале кривая RHR должна иметь форму &amp;ldquo;гамака&amp;rdquo;, достигая наименьшего значения в первой половине сна, что свидетельствует о наиболее качественном восстановлении.&lt;/p>
&lt;h2 id="4-детальный-анализ-архитектуры-сна">4. Детальный анализ архитектуры сна
&lt;/h2>&lt;p>Производительность мозга инженера определяется не только &amp;ldquo;количеством&amp;rdquo; сна, но и его &amp;ldquo;качеством&amp;rdquo;, то есть архитектурой сна (Sleep Architecture). Ночной сон обычно состоит из 4-5 циклов по 90-110 минут.&lt;/p>
&lt;h3 id="41-nrem-сон-стадии-1-2-легкий-сон--light-sleep">4.1 NREM-сон Стадии 1-2 (Легкий сон / Light Sleep)
&lt;/h3>&lt;p>Это подготовительная стадия, когда мозговые волны постепенно замедляются, и тело начинает расслабляться. Составляет около 50% всего сна. Хотя вклад в когнитивное восстановление невелик, это важный мост для перехода к следующей стадии глубокого сна.&lt;/p>
&lt;h3 id="42-nrem-сон-стадия-3-глубокий-сон--deep-sleep--slow-wave-sleep-sws">4.2 NREM-сон Стадия 3 (Глубокий сон / Deep Sleep / Slow Wave Sleep: SWS)
&lt;/h3>&lt;p>В мозговых волнах появляются дельта-волны (низкие частоты 0,5-2 Гц), это основное время для физического восстановления тела. Секретируется большое количество гормона роста, и происходит восстановление клеток. Это также необходимо для укрепления иммунной системы, и напрямую связано не только с восстановлением мышечной усталости у спортсменов, но и со снятием зрительного напряжения и восстановлением мышц шеи и плеч у инженеров. Глубокий сон обычно концентрируется в циклах первой половины сна.&lt;/p>
&lt;h3 id="43-rem-сон-быстрый-сон--rapid-eye-movement">4.3 REM-сон (Быстрый сон / Rapid Eye Movement)
&lt;/h3>&lt;p>Мозг так же активен, как и во время бодрствования, но мышцы тела парализованы. Для инженеров этот REM-сон чрезвычайно важен; он играет роль в систематизации в мозгу синтаксиса новых языков программирования или сложных концепций алгоритмов, изученных в течение дня, и их закреплении в долговременной памяти (Memory Consolidation). Нейропластичность (Neuroplasticity) повышается, и способность к творческому решению проблем (&amp;ldquo;внезапно придумал, как исправить баг, принимая душ&amp;rdquo;) также усиливается благодаря REM-сну. REM-сон имеет тенденцию удлиняться во второй половине сна (ближе к утру).&lt;/p>
&lt;p>Другими словами, &amp;ldquo;сокращение времени сна путем принудительного раннего пробуждения по будильнику&amp;rdquo; означает локальное и значительное сокращение REM-сна, связанного с закреплением памяти и креативностью, что равносильно критическому багу, который существенно снижает вашу производительность как инженера.&lt;/p>
&lt;h2 id="5-непрерывный-мониторинг-уровня-глюкозы-cgm-и-защита-от-спайков">5. Непрерывный мониторинг уровня глюкозы (CGM) и защита от спайков
&lt;/h2>&lt;p>В последние годы внедрение CGM (Continuous Glucose Monitor: устройство для непрерывного мониторинга уровня глюкозы) стало обязательным среди биохакеров. Типичными устройствами являются FreeStyle Libre и Dexcom.
При употреблении пищи (особенно углеводов и сахара) концентрация глюкозы в крови резко возрастает (спайк уровня сахара в крови), а затем резко падает (краш) из-за массовой секреции инсулина. Во время этого &amp;ldquo;краша&amp;rdquo; возникает сильная сонливость (Brain Fog) и снижение концентрации. Сонливость &amp;ldquo;проклятых 2 часов дня&amp;rdquo; после обеда, скорее всего, вызвана не только биологическими часами, но и скачком уровня сахара в крови из-за чрезмерного потребления рамена или белого риса.&lt;/p>
&lt;p>Кривую реакции уровня глюкозы в крови $G(t)$ можно приблизительно выразить с помощью следующей модели затухающих колебаний как разницу между скоростью всасывания потребленных углеводов и клиренсом под действием инсулина:&lt;/p>
$$ G(t) = G_{base} + \Delta G \cdot e^{-\alpha t} \sin(\beta t) $$&lt;p>Где,&lt;/p>
&lt;ul>
&lt;li>$G_{base}$: Уровень глюкозы натощак (базовый уровень)&lt;/li>
&lt;li>$\Delta G$: Амплитуда повышения уровня глюкозы после еды&lt;/li>
&lt;li>$\alpha$: Коэффициент затухания, основанный на чувствительности к инсулину и скорости метаболизма&lt;/li>
&lt;li>$\beta$: Частотная составляющая колебаний&lt;/li>
&lt;li>$t$: Время, прошедшее после еды&lt;/li>
&lt;/ul>
&lt;p>Чтобы поддерживать производительность инженера, важно минимизировать $\Delta G$ (амплитуду). В частности, эффективны такие лайфхаки, как &amp;ldquo;сначала есть овощи (клетчатку)&amp;rdquo;, &amp;ldquo;избегать рафинированных углеводов&amp;rdquo; и &amp;ldquo;совершать 15-минутную легкую прогулку после еды (активирует транспортер GLUT4 и поглощает глюкозу в мышцы независимо от инсулина)&amp;rdquo;.&lt;/p>
&lt;h2 id="6-проектирование-архитектуры-построение-локального-конвейера-данных">6. Проектирование архитектуры: Построение локального конвейера данных
&lt;/h2>&lt;p>Построим локальный конвейер данных для интегрированного анализа биометрических данных и данных о производительности.
Следующая диаграмма Mermaid (блок-схема) показывает процесс от получения данных из API до их визуализации на дашборде.&lt;/p>
&lt;pre class="mermaid">
flowchart TD
A[&amp;#34;Oura Ring API (Биометрия)&amp;#34;] --&amp;gt;|JSON через OAuth2| C[&amp;#34;Конвейер приема данных на Python&amp;#34;]
B[&amp;#34;WakaTime API (Время кодирования)&amp;#34;] --&amp;gt;|JSON через API Ключ| C
E[&amp;#34;SwitchBot API (Температура комнаты / CO2)&amp;#34;] --&amp;gt;|JSON через API Ключ| C
C --&amp;gt;|Извлечение и Трансформация| D[&amp;#34;Pandas DataFrame (Память)&amp;#34;]
D --&amp;gt;|Загрузка| F[&amp;#34;TimescaleDB / PostgreSQL&amp;#34;]
F --&amp;gt; G[&amp;#34;Jupyter Notebook (Ad-hoc Анализ)&amp;#34;]
F --&amp;gt; H[&amp;#34;Веб-приложение Streamlit (Ежедневный мониторинг)&amp;#34;]
&lt;/pre>
&lt;p>Благодаря этой архитектуре мы сможем автоматически ежедневно отслеживать корреляцию между нашим физическим состоянием (ввод) и производительностью кодирования (вывод).&lt;/p>
&lt;p>Давайте рассмотрим последовательность взаимодействия между системами более подробно.&lt;/p>
&lt;pre class="mermaid">
sequenceDiagram
participant U as &amp;#34;Пользователь (Инженер)&amp;#34;
participant W as &amp;#34;Плагин WakaTime (VS Code)&amp;#34;
participant O as &amp;#34;Oura Ring и API&amp;#34;
participant S as &amp;#34;Python ETL Пакет&amp;#34;
participant DB as &amp;#34;TimescaleDB&amp;#34;
U-&amp;gt;&amp;gt;W: &amp;#34;Пишет код (Набор на клавиатуре)&amp;#34;
W--&amp;gt;&amp;gt;W: &amp;#34;Логирует точный ритм кодирования&amp;#34;
U-&amp;gt;&amp;gt;O: &amp;#34;Спит (Носит кольцо)&amp;#34;
O--&amp;gt;&amp;gt;O: &amp;#34;Записывает ВСР, ЧСС покоя, Темп. и Фазы сна&amp;#34;
S-&amp;gt;&amp;gt;W: &amp;#34;GET /api/v1/users/current/summaries&amp;#34;
S-&amp;gt;&amp;gt;O: &amp;#34;GET /v2/usercollection/sleep&amp;#34;
S-&amp;gt;&amp;gt;S: &amp;#34;Очистка и слияние данных (Pandas)&amp;#34;
S-&amp;gt;&amp;gt;DB: &amp;#34;INSERT INTO daily_metrics&amp;#34;
Note over S,DB: &amp;#34;Запланировано через Cron / Airflow&amp;#34;
&lt;/pre>
&lt;h2 id="7-прием-данных-с-помощью-python-и-pandas">7. Прием данных с помощью Python и Pandas
&lt;/h2>&lt;p>Давайте посмотрим, как использовать скрипт Python для фактического получения данных из API Oura Ring и WakaTime и их интеграции в виде Pandas DataFrame. Мы создадим надежный код, который выдержит практическое применение.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;span class="lnt">48
&lt;/span>&lt;span class="lnt">49
&lt;/span>&lt;span class="lnt">50
&lt;/span>&lt;span class="lnt">51
&lt;/span>&lt;span class="lnt">52
&lt;/span>&lt;span class="lnt">53
&lt;/span>&lt;span class="lnt">54
&lt;/span>&lt;span class="lnt">55
&lt;/span>&lt;span class="lnt">56
&lt;/span>&lt;span class="lnt">57
&lt;/span>&lt;span class="lnt">58
&lt;/span>&lt;span class="lnt">59
&lt;/span>&lt;span class="lnt">60
&lt;/span>&lt;span class="lnt">61
&lt;/span>&lt;span class="lnt">62
&lt;/span>&lt;span class="lnt">63
&lt;/span>&lt;span class="lnt">64
&lt;/span>&lt;span class="lnt">65
&lt;/span>&lt;span class="lnt">66
&lt;/span>&lt;span class="lnt">67
&lt;/span>&lt;span class="lnt">68
&lt;/span>&lt;span class="lnt">69
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">requests&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">pandas&lt;/span> &lt;span class="k">as&lt;/span> &lt;span class="nn">pd&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">datetime&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">datetime&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">timedelta&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">os&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Environment Variables&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">OURA_TOKEN&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">os&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">getenv&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;OURA_ACCESS_TOKEN&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">WAKATIME_API_KEY&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">os&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">getenv&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;WAKATIME_API_KEY&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">fetch_oura_sleep_data&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">start_date&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">end_date&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">pd&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">DataFrame&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;Fetch daily sleep summary from Oura Ring API v2.&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;https://api.ouraring.com/v2/usercollection/sleep&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">params&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;start_date&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">start_date&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;end_date&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">end_date&lt;/span>&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">headers&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;Authorization&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;Bearer &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">OURA_TOKEN&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">response&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">headers&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">headers&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">params&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">params&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">response&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">raise_for_status&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="c1"># Raise exception for 4xx/5xx errors&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">response&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">json&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;data&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">[])&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="ow">not&lt;/span> &lt;span class="n">data&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">pd&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">DataFrame&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">df&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">pd&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">json_normalize&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">data&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Extract deeply nested values or select essential columns&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">df&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">df&lt;/span>&lt;span class="p">[[&lt;/span>&lt;span class="s1">&amp;#39;day&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;score&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;time_in_bed&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;total_sleep_duration&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;average_hrv&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;lowest_heart_rate&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;deep_sleep_duration&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;rem_sleep_duration&amp;#39;&lt;/span>&lt;span class="p">]]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Convert dates to datetime objects and set as index&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">df&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;day&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">pd&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">to_datetime&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">df&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;day&amp;#39;&lt;/span>&lt;span class="p">])&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">df&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">set_index&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;day&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">inplace&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">True&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">df&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">fetch_wakatime_data&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">start_date&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">end_date&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">pd&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">DataFrame&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;Fetch coding duration summaries from WakaTime API.&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;https://wakatime.com/api/v1/users/current/summaries&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">params&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;start&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">start_date&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;end&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">end_date&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;api_key&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">WAKATIME_API_KEY&lt;/span>&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">response&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">params&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">params&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">response&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">raise_for_status&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">response&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">json&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;data&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">[])&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">records&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">day_data&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">data&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">date_str&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">day_data&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;range&amp;#39;&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="s1">&amp;#39;date&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Extract total seconds spent coding&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">total_seconds&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">day_data&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;grand_total&amp;#39;&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="s1">&amp;#39;total_seconds&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">records&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">({&lt;/span>&lt;span class="s1">&amp;#39;day&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">date_str&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;coding_hours&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">total_seconds&lt;/span> &lt;span class="o">/&lt;/span> &lt;span class="mf">3600.0&lt;/span>&lt;span class="p">})&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">df&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">pd&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">DataFrame&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">records&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="ow">not&lt;/span> &lt;span class="n">df&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">empty&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">df&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;day&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">pd&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">to_datetime&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">df&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;day&amp;#39;&lt;/span>&lt;span class="p">])&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">df&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">set_index&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;day&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">inplace&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">True&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">df&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">if&lt;/span> &lt;span class="vm">__name__&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s2">&amp;#34;__main__&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Fetch data for the last 60 days&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">end&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">datetime&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">now&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">strftime&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;%Y-%m-&lt;/span>&lt;span class="si">%d&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">start&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">datetime&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">now&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">timedelta&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">days&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">60&lt;/span>&lt;span class="p">))&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">strftime&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;%Y-%m-&lt;/span>&lt;span class="si">%d&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">oura_df&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">fetch_oura_sleep_data&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">start&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">end&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">waka_df&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">fetch_wakatime_data&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">start&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">end&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Merge datasets on &amp;#39;day&amp;#39; index using inner join&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">merged_df&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">pd&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">merge&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">oura_df&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">waka_df&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">left_index&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">True&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">right_index&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">True&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">how&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;inner&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Save raw data to CSV/DB&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">merged_df&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">to_csv&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;health_productivity_raw.csv&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;Ingested &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="nb">len&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">merged_df&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> days of data.&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="8-предобработка-данных-и-разработка-признаков-feature-engineering">8. Предобработка данных и разработка признаков (Feature Engineering)
&lt;/h2>&lt;p>Опасно использовать полученные необработанные данные напрямую для анализа. Необходимо обработать пропущенные значения (Missing Values) из-за забытой зарядки устройств и сгенерировать новые значимые показатели (разработка признаков: Feature Engineering).&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">engineer_features&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">df&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">pd&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">DataFrame&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">pd&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">DataFrame&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;Apply feature engineering and cleaning to the merged dataframe.&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">df&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">df&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">copy&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 1. Handle missing values (e.g., forward fill)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">df&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">fillna&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">method&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;ffill&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">inplace&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">True&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 2. Calculate Sleep Efficiency&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Formula: (Total Sleep Time / Time in Bed) * 100&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">df&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;sleep_efficiency_pct&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">df&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;total_sleep_duration&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">/&lt;/span> &lt;span class="n">df&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;time_in_bed&amp;#39;&lt;/span>&lt;span class="p">])&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="mi">100&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 3. Calculate Sleep Stage Ratios&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">df&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;rem_ratio&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">df&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;rem_sleep_duration&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">/&lt;/span> &lt;span class="n">df&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;total_sleep_duration&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">df&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;deep_ratio&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">df&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;deep_sleep_duration&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">/&lt;/span> &lt;span class="n">df&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;total_sleep_duration&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 4. Calculate 7-day Moving Averages (Rolling Mean) to smooth out daily noise&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">df&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;hrv_7d_ma&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">df&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;average_hrv&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">rolling&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">window&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">7&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">mean&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">df&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;rhr_7d_ma&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">df&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;lowest_heart_rate&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">rolling&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">window&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">7&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">mean&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 5. Calculate daily deviation from baseline&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">df&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;hrv_deviation&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">df&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;average_hrv&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">df&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;hrv_7d_ma&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 6. Normalize targets for Machine Learning (Optional)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kn">from&lt;/span> &lt;span class="nn">sklearn.preprocessing&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">MinMaxScaler&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">scaler&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">MinMaxScaler&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">df&lt;/span>&lt;span class="p">[[&lt;/span>&lt;span class="s1">&amp;#39;hrv_scaled&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;coding_scaled&amp;#39;&lt;/span>&lt;span class="p">]]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">scaler&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">fit_transform&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">df&lt;/span>&lt;span class="p">[[&lt;/span>&lt;span class="s1">&amp;#39;average_hrv&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;coding_hours&amp;#39;&lt;/span>&lt;span class="p">]])&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Drop rows with NaN generated by rolling window&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">df&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">dropna&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">inplace&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">True&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">df&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">processed_df&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">engineer_features&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">merged_df&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="9-корреляционный-анализ-пересечение-производительности-и-показателей-здоровья">9. Корреляционный анализ: Пересечение производительности и показателей здоровья
&lt;/h2>&lt;p>На основе предварительно обработанных данных мы проанализируем взаимосвязь между показателями здоровья и производительностью кодирования. Гипотеза заключается в том, что &amp;ldquo;в дни с высокой ВСР (когда вегетативная нервная система сбалансирована и восстановлена), концентрация сохраняется дольше, время кодирования увеличивается, или можно выполнять более сложные задачи&amp;rdquo;.&lt;/p>
&lt;pre class="mermaid">
xychart-beta
title ВСР против Часов кодирования в день (Нормализовано)
x-axis [&amp;#34;Пн&amp;#34;, &amp;#34;Вт&amp;#34;, &amp;#34;Ср&amp;#34;, &amp;#34;Чт&amp;#34;, &amp;#34;Пт&amp;#34;, &amp;#34;Сб&amp;#34;, &amp;#34;Вс&amp;#34;]
y-axis &amp;#34;ВСР и Вывод кодирования&amp;#34; 10 --&amp;gt; 100
line [45, 52, 65, 75, 70, 58, 48]
bar [35, 42, 58, 65, 60, 20, 15]
&lt;/pre>
&lt;p>&lt;em>(Примечание: Линейный график показывает отклонение от нормализованного базового уровня ВСР, а гистограмма показывает время кодирования WakaTime. Можно увидеть корреляцию, при которой вывод кодирования максимизируется со среды по пятницу, когда достигается достаточное восстановление)&lt;/em>&lt;/p>
&lt;p>Мы рассчитаем коэффициент корреляции (коэффициент корреляции Пирсона $r$) с помощью Pandas и проверим статистическую значимость (p-значение) с помощью SciPy.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">scipy.stats&lt;/span> &lt;span class="k">as&lt;/span> &lt;span class="nn">stats&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Select numerical columns for correlation matrix&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">cols_of_interest&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;average_hrv&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;score&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;deep_sleep_duration&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;rem_sleep_duration&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;coding_hours&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">correlation_matrix&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">processed_df&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">cols_of_interest&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">corr&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;Correlation with Coding Hours:&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">correlation_matrix&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;coding_hours&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">sort_values&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ascending&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">False&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Calculate Pearson correlation coefficient and p-value for REM sleep and Coding Hours&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">r&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">p_value&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">stats&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">pearsonr&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">processed_df&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;rem_sleep_duration&amp;#39;&lt;/span>&lt;span class="p">],&lt;/span> &lt;span class="n">processed_df&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;coding_hours&amp;#39;&lt;/span>&lt;span class="p">])&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;REM Sleep vs Coding Hours: r = &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">r&lt;/span>&lt;span class="si">:&lt;/span>&lt;span class="s2">.3f&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">, p-value = &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">p_value&lt;/span>&lt;span class="si">:&lt;/span>&lt;span class="s2">.4f&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Во многих случаях наблюдается значимая положительная корреляция ($p &lt; 0.05$) между &lt;code>average_hrv&lt;/code> или &lt;code>rem_sleep_duration&lt;/code> и &lt;code>coding_hours&lt;/code>. В частности, в сообществе инженеров, занимающихся &amp;ldquo;количественным измерением себя&amp;rdquo; (Quantified Self), часто сообщается, что продолжительность REM-сна в предыдущую ночь сильно влияет на &amp;ldquo;время, необходимое для устранения ошибок (отладки)&amp;rdquo; и &amp;ldquo;производительность&amp;rdquo; в текущий день.&lt;/p>
&lt;h2 id="10-математическая-модель-циркадных-ритмов-и-оптимизация-когнитивных-пиков">10. Математическая модель циркадных ритмов и оптимизация когнитивных пиков
&lt;/h2>&lt;p>У людей есть биологические часы с циклом около 24 часов, называемые циркадным ритмом (Circadian Rhythm). В зависимости от этого ритма колеблются температура тела, секреция гормонов (утренний спайк кортизола и ночная секреция мелатонина) и &amp;ldquo;когнитивные способности&amp;rdquo;.&lt;/p>
&lt;p>Колебания циркадного ритма часто аппроксимируются с помощью математической модели, использующей косинусоиду (модель Cosinor), и изменения биометрических показателей можно сформулировать следующим образом:&lt;/p>
$$ y(t) = M + A \cos\left(\frac{2\pi}{24}(t - \phi)\right) + e(t) $$&lt;ul>
&lt;li>$y(t)$: Биометрический показатель в момент времени $t$ (например, температура кора тела или уровень бдительности)&lt;/li>
&lt;li>$M$: MESOR (Midline Estimating Statistic of Rhythm) - центральное значение ритма (средний уровень)&lt;/li>
&lt;li>$A$: Амплитуда (Amplitude) - величина колебаний&lt;/li>
&lt;li>$\phi$: Акрофаза (Acrophase) - фаза (время) пика&lt;/li>
&lt;li>$e(t)$: Член ошибки из-за факторов окружающей среды и т.д.&lt;/li>
&lt;/ul>
&lt;p>В контексте инженерии эта формула означает, что &amp;ldquo;время суток ($\phi$), когда производительность (уровень бдительности) достигает пика, биологически детерминировано, и в это время следует назначать задачи с наибольшей когнитивной нагрузкой (исправление сложных багов, проектирование новой архитектуры)&amp;rdquo;.&lt;/p>
&lt;p>В случае типичного утреннего хронотипа (Morning Lark) первый когнитивный пик наступает через 2-4 часа после пробуждения (например, с 9:00 до 11:00). Затем, около 14:00, наступает спад циркадного ритма (Post-lunch dip), и еще один небольшой пик приходится на вечер. Выявление вашего пикового времени ($\phi$) по уровню активности из данных носимых устройств и субъективному уровню концентрации, а затем защита этого времени с помощью &amp;ldquo;блокировки времени&amp;rdquo; в Google Календаре и т.д. — это лучший лайфхак для здоровья. Назначать бессмысленные встречи на пиковое время — все равно что выделять самое производительное ядро процессора для процесса ожидания.&lt;/p>
&lt;h2 id="11-фармакокинетика-кофеина-и-оптимальное-время-приема">11. Фармакокинетика кофеина и оптимальное время приема
&lt;/h2>&lt;p>Инженеры и кофе неразделимы, но чрезмерное употребление кофеина или употребление в позднее время блокирует аденозиновые рецепторы в мозге и разрушает &amp;ldquo;глубокий сон&amp;rdquo; (Deep Sleep) ночью. Субъективно вам может казаться, что вы спите хорошо, но посмотрев на данные Oura Ring, вы можете увидеть, что ваш пульс не падает, а доля глубокого сна резко снижается.&lt;/p>
&lt;p>Выведение кофеина из организма подчиняется кинетике первого порядка (First-order kinetics). Другими словами, концентрация в крови снижается экспоненциально.&lt;/p>
$$ C(t) = C_0 e^{-k t} $$&lt;p>Где,&lt;/p>
&lt;ul>
&lt;li>$C(t)$: Концентрация кофеина в крови по прошествии времени $t$&lt;/li>
&lt;li>$C_0$: Начальная концентрация (максимальная концентрация сразу после приема)&lt;/li>
&lt;li>$k$: Константа скорости элиминации (выведения)&lt;/li>
&lt;li>$t$: Время, прошедшее с момента приема (в часах)&lt;/li>
&lt;/ul>
&lt;p>Константа скорости элиминации $k$ выражается через период полувыведения кофеина ($t_{1/2}$) следующим образом:&lt;/p>
$$ k = \frac{\ln(2)}{t_{1/2}} $$&lt;p>Для здорового взрослого человека период полувыведения кофеина $t_{1/2}$ составляет около &lt;strong>5-6 часов&lt;/strong>, хотя это зависит от индивидуальной генетики (ген CYP1A2).
Например, предположим, что вы выпили 1 чашку капельного кофе (около 150 мг кофеина) в 15:00 ($C_0 = 150$). Если период полувыведения составляет 5,5 часов, то $k \approx 0.126$.
Рассчитав концентрацию остаточного кофеина в организме ко времени отхода ко сну в 23:00 (через 8 часов):&lt;/p>
$$ C(8) = 150 \times e^{-0.126 \times 8} = 150 \times e^{-1.008} \approx 150 \times 0.365 = 54.75 \text{ мг} $$&lt;p>Другими словами, ко времени сна в организме все еще остается 54 мг кофеина (немного больше, чем в 1 чашке эспрессо), что напрямую негативно влияет на архитектуру сна.
Вывод на основе данных, полученный из этой фармакокинетической модели, заключается в том, что &lt;strong>&amp;ldquo;для обеспечения качественного сна прием кофеина следует начинать через 90 минут после пробуждения (после того как уляжется спайк кортизола), и полностью прекращать не позднее 14:00 (за 9-10 часов до сна)&amp;rdquo;&lt;/strong>.&lt;/p>
&lt;h2 id="12-взлом-переменных-среды-lux-температура-co2">12. Взлом переменных среды (Lux, Температура, CO2)
&lt;/h2>&lt;p>Важно оптимизировать не только внутреннюю систему собственного тела, но и внешние переменные среды (Environment Variables).&lt;/p>
&lt;h3 id="121-программирование-световой-среды-lux">12.1 Программирование световой среды (Lux)
&lt;/h3>&lt;p>Самый мощный &amp;ldquo;Zeitgeber (синхронизатор: сигнал, указывающий время)&amp;rdquo; для сброса циркадных ритмов — это свет. Утром, когда около 100 000 люкс солнечного света попадает на фоторецепторные клетки сетчатки (ipRGC), секреция мелатонина прекращается, и таймер сбрасывается. И наоборот, ночью необходимо блокировать синий свет, чтобы не препятствовать секреции мелатонина. Эффективно не только снижать цветовую температуру дисплея с помощью такого программного обеспечения, как f.lux, но и управлять умным освещением (например, Philips Hue) через API, написав скрипт, который автоматически снижает освещенность и цветовую температуру в комнате после захода солнца.&lt;/p>
&lt;h3 id="122-контроль-температуры-в-спальне-и-латентность-сна-sleep-latency">12.2 Контроль температуры в спальне и латентность сна (Sleep Latency)
&lt;/h3>&lt;p>Люди засыпают при снижении температуры кора тела (Core Body Temperature). Поддерживая в спальне прохладную температуру 18-19 градусов и ложась в постель точно в момент резкого падения температуры кора тела, которая была временно повышена теплой ванной за 90 минут до сна, можно кардинально сократить латентность сна (Sleep Latency: время от момента укладывания в постель до засыпания) и максимизировать глубокий сон.&lt;/p>
&lt;h3 id="123-концентрация-co2-и-снижение-когнитивных-функций">12.3 Концентрация CO2 и снижение когнитивных функций
&lt;/h3>&lt;p>Если вы добавите API концентратора SwitchBot или метеостанции Netatmo в свой конвейер данных, вы увидите четкую отрицательную корреляцию между концентрацией углекислого газа (CO2) в помещении и производительностью.
Как показывают исследования Гарвардского университета и другие, когда концентрация CO2 превышает 1000 ppm, когнитивные функции (особенно способность принимать стратегические решения) начинают значительно снижаться, а превышение 2000 ppm вызывает серьезное падение производительности. Удаленная работа в закрытом помещении зимой незаметно снижает вашу производительность.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Pseudo-code for intelligent room ventilation using Home Assistant / SwitchBot API&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">requests&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">check_and_ventilate&lt;/span>&lt;span class="p">():&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Get current CO2 level from Netatmo/SwitchBot API&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">co2_ppm&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">get_sensor_data&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;co2_sensor_id&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">co2_ppm&lt;/span> &lt;span class="o">&amp;gt;&lt;/span> &lt;span class="mi">1000&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;Warning: CO2 level high (&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">co2_ppm&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> ppm). Cognitive decline risk.&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Trigger smart plug to turn on ventilation fan&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">turn_on_smart_plug&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;ventilation_fan_id&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Send notification to Slack/Discord&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">send_notification&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;Вентилятор включен. Уровень CO2 высокий.&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">elif&lt;/span> &lt;span class="n">co2_ppm&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="mi">600&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">turn_off_smart_plug&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;ventilation_fan_id&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Регулярно выполняя такой скрипт с помощью Cron, вы создадите автономную систему контроля среды, которая всегда поддерживает оптимальную концентрацию кислорода.&lt;/p>
&lt;h2 id="13-заключение-cicd-системы-человеческого-тела">13. Заключение: CI/CD системы человеческого тела
&lt;/h2>&lt;p>Попробуйте рассматривать собственное тело как единую сложную распределенную систему. Носимые устройства (Oura Ring) — это экспортеры метрик для мониторинга (Prometheus), скрипты Python/Pandas — это конвейер анализа логов (Logstash/Fluentd), а ежедневные изменения физического состояния и производительности — это здоровье системы, отображаемое на дашборде (Grafana/Streamlit).&lt;/p>
&lt;p>&amp;ldquo;Работа в ущерб времени сна&amp;rdquo; — это то же самое, что и форсированное добавление функций, игнорируя технический долг (Technical Debt). В краткосрочной перспективе вы можете успеть к релизу, но в долгосрочной перспективе это обязательно приведет к сбою системы (выгоранию, серьезным проблемам со здоровьем, депрессии).&lt;/p>
&lt;p>Мониторинг ВСР, проверка трендов ЧСС покоя, оптимизация архитектуры сна. И ежедневная тонкая настройка &amp;ldquo;гиперпараметров&amp;rdquo;, таких как питание, упражнения, сон и окружающая среда, с одновременным анализом корреляции с данными о производительности WakaTime. Это не что иное, как процесс &lt;strong>CI/CD (непрерывная интеграция и непрерывная доставка)&lt;/strong> для человеческого тела.&lt;/p>
&lt;p>Давайте использовать науку о данных и API для инжиниринга такого состояния здоровья, которое позволит вам достичь максимальной производительности. Ведь качество кода, который вы пишете, напрямую зависит от здоровья вашей собственной биологической системы.&lt;/p>
&lt;hr>
&lt;p>&lt;em>Отказ от ответственности (Disclaimer): Эта статья суммирует личные эксперименты автора и подходы науки о данных, и не содержит медицинских советов. Если у вас наблюдается постоянное плохое самочувствие или нарушения сна, пожалуйста, проконсультируйтесь со специализированным медицинским учреждением.&lt;/em>&lt;/p></description></item><item><title>Компромисс между конфиденциальностью и удобством: судьба персональных данных в эпоху больших данных</title><link>http://kenji.blog/ru/p/privacy-vs-convenience-big-data/</link><pubDate>Sat, 12 Sep 2026 12:00:00 +0900</pubDate><guid>http://kenji.blog/ru/p/privacy-vs-convenience-big-data/</guid><description>&lt;img src="http://kenji.blog/p/privacy-vs-convenience-big-data/img/eyecatch.jpg" alt="Featured image of post Компромисс между конфиденциальностью и удобством: судьба персональных данных в эпоху больших данных" />&lt;h1 id="компромисс-между-конфиденциальностью-и-удобством-судьба-персональных-данных-в-эпоху-больших-данных">Компромисс между конфиденциальностью и удобством: судьба персональных данных в эпоху больших данных
&lt;/h1>&lt;p>В современном цифровом обществе мы генерируем огромные объемы данных в нашей повседневной жизни. Непрерывно собираются разнообразные «большие данные», такие как данные о местоположении со смартфонов, публикации в социальных сетях, история покупок в интернет-магазинах и данные о здоровье, фиксируемые носимыми устройствами. Эти данные необходимы для развития ИИ (искусственного интеллекта) и предоставления персонализированных услуг, что делает нашу жизнь более удобной и насыщенной.&lt;/p>
&lt;p>Однако, с другой стороны, риск нарушения конфиденциальности, связанный со сбором и использованием персональных данных, стал серьезной социальной проблемой. Риски, скрывающиеся за удобством, такие как утечки данных, передача данных третьим лицам без согласия пользователей и опасения по поводу создания государства тотального контроля, достигли масштабов, которые невозможно игнорировать. В этой статье мы дадим чрезвычайно подробное техническое объяснение того, как решается эта современная дилемма — «компромисс между конфиденциальностью и удобством» — с точки зрения как технологий, так и законодательства, с учетом последних тенденций.&lt;/p>
&lt;h2 id="1-парадигма-общества-управляемого-данными-и-эволюция-архитектуры-данных">1. Парадигма общества, управляемого данными, и эволюция архитектуры данных
&lt;/h2>&lt;p>Для эффективного сбора и использования данных компании внедряют различные архитектуры данных. Произошел переход от ранее доминирующих «хранилищ данных» (Data Warehouse) к «озерам данных» (Data Lake), которые централизованно управляют всеми данными, включая неструктурированные, а в настоящее время происходит сдвиг парадигмы в сторону распределенной архитектуры — «сетки данных» (Data Mesh).&lt;/p>
&lt;h3 id="централизованное-озеро-данных-и-конвейер-анонимизации">Централизованное озеро данных и конвейер анонимизации
&lt;/h3>&lt;p>Озеро данных — это репозиторий хранилища, в котором хранятся огромные объемы необработанных данных в их исходном формате. Однако использование необработанных данных, содержащих персональные данные (PII: Personally Identifiable Information), напрямую для анализа приводит к серьезным нарушениям нормативных требований. Поэтому между озером данных и средой анализа внедряется строгий «конвейер анонимизации» (Anonymization Pipeline).&lt;/p>
&lt;p>На следующем рисунке показан процесс работы конвейера анонимизации в типичном централизованном озере данных.&lt;/p>
&lt;pre class="mermaid">
flowchart TD
A[&amp;#34;Источники данных (Веб, IoT, Мобильные)&amp;#34;] --&amp;gt;| Сбор данных | B[&amp;#34;Зона необработанных данных (Неизмененные)&amp;#34;]
B --&amp;gt;| Процесс ETL | C[&amp;#34;Конвейер анонимизации и очистки&amp;#34;]
C --&amp;gt;| Псевдонимизация / Токенизация | D[&amp;#34;Доверенная зона (k-анонимизированные)&amp;#34;]
D --&amp;gt;| Проектирование признаков | E[&amp;#34;Очищенная зона (Готово для ML)&amp;#34;]
E --&amp;gt;| Обучение модели | F[&amp;#34;Инструменты BI и модели ML&amp;#34;]
C --&amp;gt;| Журналы аудита | G[&amp;#34;Центр безопасности и соответствия требованиям&amp;#34;]
&lt;/pre>
&lt;p>В таком конвейере при поступлении данных автоматически применяются такие процессы, как хеширование, маскирование и шифрование. Однако, как будет показано ниже, простое маскирование или псевдонимизация (Pseudonymization) не могут полностью исключить риск «повторной идентификации» (Re-identification) путем сопоставления с другими источниками данных.&lt;/p>
&lt;h2 id="2-глубокое-понимание-технологий-защиты-конфиденциальности-pets">2. Глубокое понимание технологий защиты конфиденциальности (PETs)
&lt;/h2>&lt;p>Ключом к достижению баланса между конфиденциальностью и использованием данных являются «технологии повышения конфиденциальности» (Privacy-Enhancing Technologies: PETs). Здесь мы подробно объясним математические определения и техническую реализацию основных технологий PETs, которые играют чрезвычайно важную роль в современном анализе больших данных и машинном обучении.&lt;/p>
&lt;h3 id="21-k-анонимность-k-anonymity-и-ее-расширения">2.1 k-анонимность (K-Anonymity) и ее расширения
&lt;/h3>&lt;p>Предложенная Латаньей Суини и Пьеранджелой Самарати в 1998 году «k-анонимность» является основополагающей концепцией защиты конфиденциальности при публикации данных. Это означает, что любая запись в наборе данных должна быть неотличима как минимум от $k-1$ других записей.&lt;/p>
&lt;p>Атрибуты в базе данных можно разделить на три основные категории:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Идентификаторы (Explicit Identifiers)&lt;/strong>: информация, позволяющая напрямую идентифицировать человека, например, имя или идентификационный номер (обычно удаляются или шифруются).&lt;/li>
&lt;li>&lt;strong>Квази-идентификаторы (Quasi-Identifiers: QIs)&lt;/strong>: информация, которая сама по себе не может идентифицировать человека, но позволяет сделать это в комбинации, например, возраст, пол, почтовый индекс.&lt;/li>
&lt;li>&lt;strong>Конфиденциальные атрибуты (Sensitive Attributes)&lt;/strong>: информация, подлежащая защите, такая как название заболевания или годовой доход.&lt;/li>
&lt;/ol>
&lt;p>k-анонимность гарантирует, что существует как минимум $k$ одинаковых комбинаций квази-идентификаторов (класс эквивалентности: Equivalence Class). Однако k-анонимность уязвима для «атаки однородности» (Homogeneity Attack) и «атаки с использованием фоновых знаний» (Background Knowledge Attack). Например, если все $k$ человек в определенном классе эквивалентности имеют одно и то же заболевание (конфиденциальный атрибут), название заболевания будет раскрыто, даже если сохраняется k-анонимность.&lt;/p>
&lt;p>Для преодоления этой проблемы были предложены следующие расширенные модели:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>l-разнообразие (l-diversity)&lt;/strong>: гарантирует, что конфиденциальный атрибут в каждом классе эквивалентности принимает как минимум $l$ различных значений.&lt;/li>
&lt;li>&lt;strong>t-близость (t-closeness)&lt;/strong>: гарантирует, что расстояние (например, расстояние землекопа - Earth Mover&amp;rsquo;s Distance) между распределением конфиденциального атрибута в каждом классе эквивалентности и его распределением во всем наборе данных не превышает порог $t$.&lt;/li>
&lt;/ul>
&lt;h3 id="22-дифференциальная-приватность-differential-privacy-dp">2.2 Дифференциальная приватность (Differential Privacy: DP)
&lt;/h3>&lt;p>Преодолев ограничения модели k-анонимности, «дифференциальная приватность» (Differential Privacy), предложенная Синтией Дворк и ее коллегами в 2006 году, сегодня широко применяется как наиболее строгий математический стандарт конфиденциальности. Технологические гиганты, такие как Apple, Google и Microsoft, применяют эту $\epsilon$-дифференциальную приватность при сборе телеметрических и статистических данных от пользователей.&lt;/p>
&lt;h4 id="математическое-определение-дифференциальной-приватности">Математическое определение дифференциальной приватности
&lt;/h4>&lt;p>Рандомизированный алгоритм (Randomized Algorithm) $\mathcal{M}$ удовлетворяет $\epsilon$-дифференциальной приватности, если для любых двух соседних наборов данных $D$ и $D'$, отличающихся ровно на одну запись (то есть $\|D - D'\|_1 = 1$), и любого подмножества возможных результатов $S \subseteq \text{Range}(\mathcal{M})$ выполняется следующее неравенство:&lt;/p>
$$ \Pr[\mathcal{M}(D) \in S] \le e^\epsilon \Pr[\mathcal{M}(D') \in S] $$&lt;p>Здесь $\epsilon$ (бюджет приватности) — это неотрицательный параметр, контролирующий уровень защиты конфиденциальности. Чем меньше $\epsilon$, тем сильнее защита конфиденциальности, но при этом снижается полезность (утилитарность) данных.&lt;/p>
&lt;p>Кроме того, широко используется ослабленная модель — $(\epsilon, \delta)$-дифференциальная приватность, которая допускает нарушение гарантии конфиденциальности с очень малой вероятностью $\delta$.&lt;/p>
$$ \Pr[\mathcal{M}(D) \in S] \le e^\epsilon \Pr[\mathcal{M}(D') \in S] + \delta $$&lt;h4 id="механизм-лапласа-laplace-mechanism">Механизм Лапласа (Laplace Mechanism)
&lt;/h4>&lt;p>Типичным методом реализации дифференциальной приватности является «механизм Лапласа», который преднамеренно добавляет шум (случайные числа), подчиняющийся определенному распределению, к истинному результату запроса. То, сколько шума следует добавить, зависит от «глобальной чувствительности» (Global Sensitivity) $\Delta f$ функции $f$.&lt;/p>
&lt;p>Глобальная чувствительность $\Delta f$ определяется как максимальное изменение результата функции $f$ для любых соседних наборов данных $D, D'$.&lt;/p>
$$ \Delta f = \max_{D, D'} \| f(D) - f(D') \|_1 $$&lt;p>Механизм Лапласа добавляет к результату функции $f(D)$ шум $Y$, выбранный из распределения Лапласа $\text{Lap}(b)$ с параметром масштаба $b = \frac{\Delta f}{\epsilon}$.&lt;/p>
$$ \mathcal{M}(D) = f(D) + Y, \quad Y \sim \text{Lap}\left(\frac{\Delta f}{\epsilon}\right) $$&lt;p>Функция плотности вероятности распределения Лапласа имеет следующий вид:&lt;/p>
$$ p(x \mid b) = \frac{1}{2b} \exp\left( - \frac{|x|}{b} \right) $$&lt;p>Благодаря внедрению этого шума становится невозможно по результатам сделать вывод о том, присутствует ли конкретный человек в наборе данных. Компании используют DP как технологию, маскирующую сами персональные данные, сохраняя при этом полезность статистических тенденций всех данных (среднее значение, дисперсия, количество и т. д.).&lt;/p>
&lt;h3 id="23-федеративное-обучение-federated-learning-fl">2.3 Федеративное обучение (Federated Learning: FL)
&lt;/h3>&lt;p>Традиционное машинное обучение использовало централизованный подход, при котором огромные объемы данных собирались на центральном сервере, как в упомянутом ранее озере данных, для обучения модели. Однако отправка конфиденциальных данных, таких как медицинские изображения или история ввода на смартфоне, на центральный сервер сопряжена с серьезным риском для конфиденциальности.&lt;/p>
&lt;p>В связи с этим в 2016 году Google предложил «федеративное обучение» (Federated Learning). При федеративном обучении вместо перемещения самих данных вычислительный процесс для модели переносится на граничные устройства (например, смартфоны или серверы больниц), где эти данные находятся.&lt;/p>
&lt;pre class="mermaid">
flowchart TD
Server[&amp;#34;Центральный сервер агрегации&amp;#34;]
Device1[&amp;#34;Граничное устройство 1 (Смартфон)&amp;#34;]
Device2[&amp;#34;Граничное устройство 2 (Смартфон)&amp;#34;]
Device3[&amp;#34;Граничное устройство 3 (Смартфон)&amp;#34;]
Server --&amp;gt;| 1. Рассылка весов глобальной модели | Device1
Server --&amp;gt;| 1. Рассылка весов глобальной модели | Device2
Server --&amp;gt;| 1. Рассылка весов глобальной модели | Device3
Device1 --&amp;gt;| 2. Локальное обучение на приватных данных | Device1
Device2 --&amp;gt;| 2. Локальное обучение на приватных данных | Device2
Device3 --&amp;gt;| 2. Локальное обучение на приватных данных | Device3
Device1 --&amp;gt;| 3. Передача градиентов/обновлений модели | Server
Device2 --&amp;gt;| 3. Передача градиентов/обновлений модели | Server
Device3 --&amp;gt;| 3. Передача градиентов/обновлений модели | Server
Server --&amp;gt;| 4. Агрегация (FedAvg) | Server
Server --&amp;gt;| 5. Обновление глобальной модели | Server
&lt;/pre>
&lt;h4 id="алгоритм-federated-averaging-fedavg">Алгоритм Federated Averaging (FedAvg)
&lt;/h4>&lt;p>Типичным алгоритмом агрегации в федеративном обучении является FedAvg. Каждый клиент $k$ использует свой собственный набор данных $D_k$ (размером $n_k$) для локального обучения методом стохастического градиентного спуска (SGD) в течение нескольких эпох, вычисляя обновленные веса $w_{t+1}^k$.&lt;/p>
&lt;p>Центральный сервер получает веса от участвующих $K$ клиентов и обновляет веса глобальной модели $w_{t+1}$ путем их усреднения с весом, пропорциональным размеру данных. Если общее количество данных равно $n = \sum_{k=1}^K n_k$, формула обновления выглядит следующим образом:&lt;/p>
$$ w_{t+1} = \sum_{k=1}^K \frac{n_k}{n} w_{t+1}^k $$&lt;p>Благодаря этому можно создавать интеллектуальные модели ИИ, не перемещая исходные персональные данные (такие как история сообщений или фотографии) за пределы устройства. В качестве типичных примеров применения можно привести функцию прогнозирования следующего слова в Google Keyboard (Gboard), а также улучшение моделей распознавания голоса Apple FaceID и «Привет, Siri».&lt;/p>
&lt;h3 id="24-гомоморфное-шифрование-homomorphic-encryption-he">2.4 Гомоморфное шифрование (Homomorphic Encryption: HE)
&lt;/h3>&lt;p>«Волшебная» криптографическая технология, которая позволяет выполнять вычисления (такие как сложение и умножение) с данными, оставляя их в зашифрованном состоянии, — это гомоморфное шифрование. При использовании обычных методов шифрования для обработки данных их необходимо сначала расшифровать (вернуть в открытый текст), но расшифровка на облачном сервере является уязвимостью с точки зрения безопасности.&lt;/p>
&lt;p>С использованием гомоморфного шифрования реализуются следующие свойства: если функция шифрования — $E(\cdot)$, то сложение или умножение открытых текстов $m_1$ и $m_2$ становится возможным через операции над зашифрованными текстами ($\oplus$ и $\otimes$).&lt;/p>
$$ E(m_1 + m_2) = E(m_1) \oplus E(m_2) $$$$ E(m_1 \times m_2) = E(m_1) \otimes E(m_2) $$&lt;p>Гомоморфное шифрование делится на «частично гомоморфное шифрование» (Partially Homomorphic Encryption: PHE), которое позволяет выполнять только сложение или только умножение, и «полностью гомоморфное шифрование» (Fully Homomorphic Encryption: FHE), которое позволяет выполнять и сложение, и умножение бесконечное число раз. С тех пор как в 2009 году Крейг Джентри построил первую схему FHE с использованием криптографии на решетках (Lattice-based cryptography), это стало большим прорывом в криптографии.&lt;/p>
&lt;p>В настоящее время остаются проблемы, такие как вычислительные затраты и увеличение размера зашифрованного текста (накладные расходы), но ожидается, что эта технология найдет применение в безопасном анализе медицинских данных в облаке и конфиденциальных вычислениях между финансовыми учреждениями.&lt;/p>
&lt;h2 id="3-законодательство-и-тенденции-комплаенса-gdpr-против-ccpa">3. Законодательство и тенденции комплаенса: GDPR против CCPA
&lt;/h2>&lt;p>Параллельно с технологической эволюцией во всем мире также стремительно развивается правовая база. Соблюдение этих законов и нормативных актов стало обязательным условием для компаний при использовании больших данных. Давайте сравним две наиболее влиятельные нормативные базы.&lt;/p>
&lt;h3 id="общий-регламент-по-защите-данных-ес-gdpr">Общий регламент по защите данных ЕС (GDPR)
&lt;/h3>&lt;p>Вступивший в силу в мае 2018 года Общий регламент ЕС по защите данных (GDPR) признан «мировым стандартом (золотым стандартом)» в области защиты персональных данных. GDPR применяется ко всем организациям, обрабатывающим данные лиц на территории ЕС, и в случае его нарушения налагается огромный штраф в размере до 4% от мирового годового оборота или 20 миллионов евро, в зависимости от того, какая сумма больше.&lt;/p>
&lt;p>&lt;strong>Основные особенности GDPR:&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Принцип согласия (Opt-in)&lt;/strong>: Сбор и обработка данных требуют явного, свободного и предварительного согласия пользователя.&lt;/li>
&lt;li>&lt;strong>Право на забвение (Right to be Forgotten/Right to Erasure)&lt;/strong>: Пользователь имеет право требовать от компании полного удаления своих персональных данных. Данные также должны быть удалены из резервных копий озера данных, что является технически чрезвычайно сложным требованием.&lt;/li>
&lt;li>&lt;strong>Контроллер данных и процессор данных&lt;/strong>: Строго определяет ответственность того, кто определяет цели использования данных (контроллер), и того, кто обрабатывает данные в соответствии с его инструкциями (процессор).&lt;/li>
&lt;/ul>
&lt;h3 id="закон-калифорнии-о-конфиденциальности-потребителей-ccpacpra">Закон Калифорнии о конфиденциальности потребителей (CCPA/CPRA)
&lt;/h3>&lt;p>Хотя в Соединенных Штатах нет всеобъемлющего закона о конфиденциальности на федеральном уровне, Закон Калифорнии о конфиденциальности потребителей (CCPA), вступивший в силу в Калифорнии в 2020 году, служит де-факто национальным стандартом. Позже он был дополнительно усилен Законом о правах на конфиденциальность Калифорнии (CPRA).&lt;/p>
&lt;p>&lt;strong>Основные особенности CCPA:&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Принцип отказа (Opt-out)&lt;/strong>: В отличие от «предварительного согласия» GDPR, сбор данных возможен без предварительного согласия, но требуется предоставить пользователю четкую ссылку для отказа с текстом «Не продавать мою персональную информацию (Do Not Sell My Personal Information)».&lt;/li>
&lt;li>&lt;strong>Право доступа к данным&lt;/strong>: Потребители могут потребовать раскрытия конкретной информации, собранной компанией, ее категорий, источников и факта продажи третьим лицам.&lt;/li>
&lt;/ul>
&lt;p>Эти законы строго требуют от компаний реализации концепции «конфиденциальность на этапе проектирования» (Privacy by Design), то есть внедрения защиты конфиденциальности еще на этапе разработки систем и процессов.&lt;/p>
&lt;h2 id="4-проблемы-внедрения-в-экосистеме-данных">4. Проблемы внедрения в экосистеме данных
&lt;/h2>&lt;p>Давайте рассмотрим с точки зрения реализации применение технологий защиты конфиденциальности и законодательных актов в реальной среде больших данных. Например, предположим случай реализации k-анонимизации или дифференциальной приватности в озере данных с использованием Python и Pandas или PySpark.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Концептуальная реализация агрегирования данных с применением дифференциальной приватности (Python)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">numpy&lt;/span> &lt;span class="k">as&lt;/span> &lt;span class="nn">np&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">pandas&lt;/span> &lt;span class="k">as&lt;/span> &lt;span class="nn">pd&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">laplace_mechanism&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">true_value&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">sensitivity&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">epsilon&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> Функция для добавления шума Лапласа к истинному значению
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">scale&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">sensitivity&lt;/span> &lt;span class="o">/&lt;/span> &lt;span class="n">epsilon&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">noise&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">random&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">laplace&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">loc&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">scale&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">scale&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">true_value&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">noise&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">get_dp_average_salary&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">dataframe&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">epsilon&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mf">1.0&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> Вычисление средней зарплаты с гарантией дифференциальной приватности
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Фактическое вычисление&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">true_sum&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">dataframe&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;salary&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">sum&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">true_count&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">len&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">dataframe&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Применение дифференциальной приватности (на основе предположения о чувствительности)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Предположим, что колебание максимальной зарплаты является чувствительностью (более строго требуется клиппинг)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">max_salary_diff&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">100000&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Добавление шума (также возможно применение DP отдельно к сумме и количеству)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">noisy_sum&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">laplace_mechanism&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">true_sum&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">max_salary_diff&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">epsilon&lt;/span> &lt;span class="o">/&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">noisy_count&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">laplace_mechanism&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">true_count&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">epsilon&lt;/span> &lt;span class="o">/&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">noisy_sum&lt;/span> &lt;span class="o">/&lt;/span> &lt;span class="n">noisy_count&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Выполнение внутри конвейера данных&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># dp_avg_salary = get_dp_average_salary(raw_df, epsilon=0.5)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Как видно из этого фрагмента кода, сама реализация дифференциальной приватности проста и заключается в добавлении шума, но в реальной эксплуатации управление «бюджетом приватности» ($\epsilon$) становится чрезвычайно сложной задачей. При выполнении нескольких запросов к одному и тому же набору данных бюджет приватности расходуется (на основе теоремы композиции), и в конечном итоге необходимо создать механизм (Privacy Budget Management), который будет блокировать весь набор данных или отклонять запросы.&lt;/p>
&lt;h2 id="5-перспективы-на-будущее-и-этические-проблемы">5. Перспективы на будущее и этические проблемы
&lt;/h2>&lt;p>Компромисс между большими данными и конфиденциальностью не является игрой с нулевой суммой. С развитием PETs, таких как дифференциальная приватность, федеративное обучение и гомоморфное шифрование, новая парадигма использования данных — «обмен инсайтами без обмена данными» — становится реальностью.&lt;/p>
&lt;p>Кроме того, в последние годы движение за возвращение суверенитета данных (Data Sovereignty) от гигантских платформ к частным лицам ускорилось благодаря связи с концепциями «Сетки данных» (Data Mesh) и «Web3» (децентрализованной сети). Обсуждается будущее, в котором персональные данные будут храниться в персональных хранилищах данных (PDS) или кошельках данных, а сами пользователи будут контролировать разрешения на использование и монетизацию данных.&lt;/p>
&lt;p>Однако технические решения не идеальны. В федеративном обучении существует угроза «атаки отравления» (Poisoning Attack), при которой злоумышленный клиент отправляет некорректные обновления модели, чтобы испортить глобальную модель. В случае с дифференциальной приватностью также указывается на этическую проблему: данные меньшинств могут быть стерты шумом, что приводит к появлению систематической ошибки (предвзятости) в моделях ИИ.&lt;/p>
&lt;h2 id="заключение">Заключение
&lt;/h2>&lt;p>Судьба персональных данных в эпоху больших данных выходит за рамки простой технической проблемы и ставит фундаментальный вопрос о том, в каком обществе мы хотим жить. Как нам защитить человеческое достоинство и конфиденциальность, продолжая наслаждаться удобствами? К устойчивому решению можно прийти только благодаря триединству: совершенствованию правовых норм, непрерывным инновациям в технологиях защиты конфиденциальности и высокой грамотности каждого из нас, предоставляющего данные. Конфиденциальность и удобство больше не будут компромиссом, а превратятся в «обязательное требование», которое можно будет удовлетворить с помощью новейших технологий.&lt;/p></description></item></channel></rss>