open_oura 是一个面向 Oura Ring(Gen 3/4/5)的 Rust 工具包,本项目用线性校准方法,从一份 Oura 账户的 Trends 导出 CSV 中,反推出 0–100 分制 Sleep Score、Readiness Score 与 Activity Score 的组合权重与子分数曲线,并能在本地无云环境实时复算你的睡眠分数。整个过程不需要阅读反编译代码,只要一条回归。
为什么 Oura 的分数可以离线复现?
一个关键发现:Oura 的三个 0–100 分数不是在云端算的。它们由手机里的原生ecore引擎(libappecore.so)在本地计算后上传,云端只负责存储与同步。这意味着只要拿到分数公式,就可以完全离线复算(见 docs/algorithms/README.md)。
但权重表无法直接从反编译产物中干净读出,于是项目采用了更稳妥的路径——校准(calibration):
Trends 导出 CSV 里,每一天同时包含「最终分数」和「各贡献因子子分数」,这正是回归分析需要的成对样本。
整体思路分两层:
| 层 | 内容 | 拟合方法 |
|---|---|---|
| 第一层:组合权重 | 最终分 =round(Σ wᵢ·子分ᵢ / 100),权重和为 100 | 无截距 OLS 线性回归 |
| 第二层:贡献因子曲线 | 每个子分 = fᵢ(原始指标) | 单调用 isotonic 回归,非单调用分箱经验曲线,多输入用线性拟合 |
准备数据:导出 Oura Trends CSV
线性校准对样本量有要求,建议300 天以上的完整导出(项目验证用了 336–348 天):
- 登录 Oura 网页账户 → 设置 → 数据导出,选择 Trends 趋势导出;
- 得到的 CSV 放到仓库的
local/trends.csv,或直接用--csv参数指定路径; - 安装依赖:
python3 -m venv .venv && .venv/bin/pip install -r requirements.txt如果需要拉取代码,克隆地址为https://gitcode.com/gh_mirrors/op/open_oura。
第一步:线性回归恢复组合权重
运行权重恢复脚本 tools/fit_scores.py:
python tools/fit_scores.py local/trends.csv它把每个最终分数对它的贡献因子子分数做无截距回归(np.linalg.lstsq),回归系数和 ≈1.0 恰好证实了「加权平均」的结构。实测结果:
| 分数 | R² | 最大误差 | 结论 |
|---|---|---|---|
| Sleep Score | 0.9987 | 0.8 分 | ✅ 几乎精确 |
| Readiness Score | 0.969 | 12.6 分 | ◐ 线性 + 少量非线性 |
| Activity Score | 0.904 | 11 分 | ◐ 分段组合,线性近似 |
恢复出的睡眠分数权重:Total Sleep 35%、Restfulness 15%、其余 5 项(Efficiency / REM / Deep / Latency / Timing)各 10%。完整的三张权重表见 docs/algorithms/score-weights.md。
第二步:拟合子分数曲线,端到端复现睡眠分
权重只是第一层——Trends 里的子分数本身也是原始指标(睡眠时长、HRV、温度偏差等)的确定性函数。tools/fit_sleep_score.py 为每个贡献因子挑选合适的曲线类型:
- 单调指标(总睡眠时长、效率、REM、深睡)→isotonic 回归(Pool-Adjacent-Violators 算法),留出集 R² 达 0.98–1.00;
- 非单调指标(入睡潜伏期)→ 分箱经验曲线,它实际上是一条U 型曲线:太短和太长都被扣分;
- 多输入指标(Restfulness、Sleep Timing)→ 线性拟合,其中睡眠时相是一个昼夜节律峰值曲线,中点落在 ~03:00 时得分最高,另叠加 7 天节律稳定性项。
留出 20% 天数的端到端验证结果:
Sleep Score 端到端 R²=0.964,RMSE 1.38,84% 的天数误差不超过 ±1 分,94% 不超过 ±3 分。
残差集中在两个贡献因子上:Restfulness(15% 权重,真实输入是 Oura 内部基于运动信号的 restful 时段计数,CSV 中只有聚合值)和 Sleep Timing 的个人节律理想点。这是数据粒度墙,不是方法问题。
三项分数总览与「基线墙」
tools/fit_scores_all.py 把同一套方法扩展到全部三个分数,并为基线相对型贡献因子(HRV Balance、Resting HR、Sleep/Activity Balance)构造「今日值 vs 近 14 天均值」的滞后特征:
| 分数 | ceiling(权重×真实子分) | achieved(权重×我方子分) | 差距原因 |
|---|---|---|---|
| Sleep | 0.998 | 0.969 | 两个微观输入缺失 |
| Readiness | 0.941 | 0.49 | ~50% 权重依赖 14 天个人基线轨迹 |
| Activity | 0.838 | 0.06 | 24% 权重绑定个性化每日目标,训练量是多日累积 |
结论很清晰:权重全部恢复正确(ceiling 证明),端到端差距几乎全部来自需要「累积历史」的贡献因子,而非缺失的逻辑。
校准一次,持久本地:实时评分流程
校准只做一次,结果持久化,运行时不再依赖 CSV:
# 一次性校准:trends 导出 → local/score_params.json python tools/calibrate_scores.py --csv local/trends.csv # 每晚:原始事件 → 每日摘要 + 滚动基线(写入 oura.db 的 daily_summary) python tools/build_daily.py # 实时评分(无需云端) python tools/score_sleep.py # 或 oura sleep-score python tools/score_readiness.py # 或 oura readiness-score- tools/calibrate_scores.py 只保留「戒指可推导」的驱动列(
LIVE_DRIVERS),把权重 + 每条曲线序列化为local/score_params.json(个人校准文件,gitignore 在本地); - tools/score_sleep.py 用 SleepNet 生成睡眠图,再走「曲线 → 子分 → 加权求和」三步,例如最近一晚 471 分钟睡眠、91% 效率 →Sleep Score 82;
- tools/score_readiness.py 从
daily_summary读数;历史不足 14 天时会自动标注「⚠ baselines still maturing — provisional」,基线成熟后 Readiness 就和 Sleep 一样实时可用。
管道细节见 docs/algorithms/daily-summaries-and-baselines.md。
新手常见坑与排查清单 📋
| 现象 | 原因 | 处理 |
|---|---|---|
| 提示找不到 CSV | 未导出或路径不对 | 放到local/trends.csv或传--csv |
| 拟合样本太少 | 导出天数不足、有缺失行 | 用 300+ 天的完整导出,脚本会跳过不完整行 |
| 列名对不上 | Oura 官方列名自带拼写错误Sleep Timin Score | 保持 CSV 原样,不要「修正」表头 |
| Readiness 偏低不稳 | 基线冷启动(<14 天) | 每晚同步 + 重跑build_daily.py,等基线成熟 |
| 想换更长导出 | 校准是个人生理参数 | 重新运行calibrate_scores.py覆盖即可 |
小结:这条路径能走多远
- 权重层:三个分数全部恢复,Sleep R²=0.9987 近乎位级精确;
- 曲线层:Sleep 端到端 R²=0.969、84% 天数 ±1 分内,日常使用完全够用;
- 实时层:Sleep 今日即可实时复算,Readiness 在 14 天基线成熟后同样实时,Activity 因个性化目标与多日训练量仍属「权重已解、暂不实时」。
对新手来说,最大的收获是方法论:当公式读不出来时,用真实数据回归出它——一份 Trends 导出 + 两条回归命令,就能得到你专属的 0–100 分模型。
延伸阅读
- 权重与曲线全表:docs/algorithms/score-weights.md
- 算法移植状态总览:docs/algorithms/README.md
- 每日摘要与基线机制:docs/algorithms/daily-summaries-and-baselines.md
- Rust 客户端入口:crates/README.md
【免费下载链接】open_oura
A Rust toolkit for the Oura Ring (Gen 3/4/5): reverse-engineered BLE protocol, event decoders, and reimplemented>项目地址:https://gitcode.com/gh_mirrors/op/open_oura
相关推荐
AISystem 开源课程:五大模块走通 AI 系统全栈,从芯片到推理引擎
AISystem 开源课程:五大模块走通 AI 系统全栈,从芯片到推理引擎 AISystem 是一个开源的 AI 系统课程,围绕 AI 芯片、AI 编译器、AI
人工智能教程文档深度学习模型编译推理引擎OpenStrap Edge分析引擎揭秘:1Hz心率数据如何变成睡眠分期、HRV与恢复度评分
OpenStrap Edge分析引擎揭秘:1Hz心率数据如何变成睡眠分期、HRV与恢复度评分 OpenStrap Edge 是一款本地优先的健康穿戴 App(无
期权定价模型校准终极指南:用gs-quant实现市场数据拟合优度评估
期权定价模型校准终极指南:用gs quant实现市场数据拟合优度评估 在金融市场中,期权定价模型校准是连接理论与实践的关键桥梁。本文将带你探索如何使用gs qu
金融科技