I've always been obsessed with data. In particular health data and using it to help me tweak decisions I make in my life. Over the course of three months I tracked my daily caloric intake using MyFitnessPal whilst concurrently wearing a Whoop fitness tracker. I noticed over this period on days that when my whoop recovery score was low, I would tend to eat more food which was high in carbs and sugar. (I didn't statistically verify this..)
I figured, if I can predict my caloric intake, maybe I can prompt myself in the mornings to be more mindful of what I eat.
This project uses those two datasets to predict my daily caloric intake based on my recovery and heart rate data.
- Get my recovery data from Whoop for yesterday
- Start a sagemaker batch transform job on that data
- Read prediction and nudge me with a tip if it looks like i'll go above my ideal calories..
This project has a few dependencies and assumptions
- A Whoop membership
- A trained sagemaker model
- Your all setup up to deploy to AWS via serverless.com
- A verified email with SES
A critical assumption is that you have a sagemaker model trained on the following fields, to predict kilojoule intake.
rMSSD, resting_hr, recovery_score, n_naps, sleep_need_baseline, sleep_debt,sleep_need_strain, sleep_need_total, sleep_quality_duration, avg_hr, max_hr
This might be a bit tricky initially, but AWS actually provide an "AutoML" solution that does all the hard work for you. The guides are great and once your know how to do it, it's incredible how quickly you can get your own model trained 🧠
It's important to mention this prediction and model is quite naiive. As my habits change, its definitely going to lose its robustness. Not to mention, this is quite a narrow view on the factors influencing my eating - i'd imagine theres a lot more feature engineering and context one could build into a system like this.
Learn more about using Sagemaker AutoPilot to train your model
Note:
- Make sure your model expects csv input in the order specified above
- Sagemaker expects something like a minimum of 500 rows to train model candidates (I didn't quite have that much so did some augmentation.. cough cough copy paste... )
- Once done grab your model name, you'll need it for this system configuration
- Make a copy of
.env.example
and call it.env
- Supply it with the required configuration
Variable | Notes |
---|---|
ORG | Name of your serverless org, found here |
APP | The name you want to call your app |
SERVICE | The name you want to call your service |
REGION | AWS region |
WHOOP_EMAIL | Email used for whoop subscription |
WHOOP_PASSWORD | Password used for whoop subscription |
TIMEZONE | Prefered timezone, used to query whoop API which recognises an offset |
NOTIFICATION_ADDRESS | Verified SES address you want to send and recieve your nudge from |
MODEL_NAME | The name of your trained sagemaker model |
DATA_LAKE_BUCKET | Globally unique bucket used for data processing |
CALORIE_LIMIT | Number of calories you'd like to stay under, defaults to 10000 |
- Deploy your system via serverless
sls deploy --aws-profile your_profile
- Profit 💰
Your system will kick off at 9pm UTC time every day and email you if it thinks your going to consume more calories than you specify, enjoy!
I utilised serverless-step-functions to orchestrate my stepfunctions. A limitation of this library is that it doesn't yet support compilation of sagemaker permissions for the IAM role it produces.
As a result, i've created a fork to enable this that mindful me uses, and created a pull request which hopefully will help some other folks out.
I've also since had the opportunity to do some research since which makes me more interested in my blood sugars, than Calories In / Calories Out - stay tuned..
Our test suite runs in a pre-commit hook. Some of the tests integrate with Whoops API which requires valid auth credentials.
To avoid committing sensitive information, we have provided setEnvVars.example.js as a template. For the test suite to run successfully you will need to create a new file, .jest/setEnvVars.js
and add a valid set of Whoop credentials to the corresponding variables. This file is untracked.
If this was a more legit operation with a test user, we might defer "integration" tests that require sensitive keys to run on a build machine, use SOPs or even set up a secrets manager.
MVP is working great, but I can tidy things up a bit
- Extend configuration to accept cron config
- Decrease scope of IAM permissions
- Use stepfunctions to handle failure flows and potentially retries
- Remove left over lambdas from state machines
- Finish test coverage
- Make README more readable and intuitive