i-Willink
|開発者の視点|✍️ i-Willink

筋トレの疲労度を、アプリでどうモデル化したか

自社の筋トレアプリ fit-ai に「筋肉疲労スコア」を実装した記録。回復を指数関数で近似し、部位別に半減期を変え、直近7日間だけを集計する――その3つの割り切りを、開発者の立場から正直に書きます。

「今日はどの部位を鍛えるか」を、数字で答えたい。そのために自社の筋トレアプリ fit-ai へ、過去の履歴から部位ごとの疲労を 0〜100 で返す「筋肉疲労スコア」を実装しました。

でも正直に言うと、これは生理学的に正確なモデルではありません。 むしろ――正確さを、どこで諦めるか。それを決める作業でした。

fatigue_calculator という一つの計算ロジックに落とし込むまでに、 3つの割り切りを置いています。

効果を語る記事ではありません。 設計判断の記録として、開発した立場から正直に書き残します。

🎯なぜ「疲労」を数値にしたかったか

「今日は何を避けるか」に、記録アプリは答えてくれない。使い手としての、そのもどかしさが出発点でした。

筋トレを続けていると気づきます。 記録アプリはたいてい、「何をやったか」しか教えてくれません。

セット数も重量もログには残る。 なのに「じゃあ今日は何を避けるべきか」には、答えてくれない。 私自身が使い手として、ここに一番のもどかしさを感じていました。

そこで fit-ai では、過去のトレーニング履歴から部位ごとの「疲労が残っている度合い」を推定し、 0 から 100 のスコアで返すことにしました。 高ければ休ませる、低ければ鍛えてよい。ただそれだけの、単純な信号です。

難しい理論を積み上げるより、まず一つの数字にする。 そこを優先しました。

📉割り切り その1: 回復を指数関数で近似する

回復のカーブを、指数関数的な減衰で近似する。半減期ひとつで直感的に扱える割り切りを選びました。

最初の割り切りは、回復のカーブを指数関数的な減衰で表したことです。 トレーニング直後に生まれた疲労が、時間とともに一定の割合で減っていく、と仮定しました。

実際の筋損傷と修復のプロセスは、もっと複雑です。 でもアプリが扱うのは「相対的にどちらの部位が疲れているか」。 なめらかに減っていく曲線があれば、実用上はそれで足りました。

なぜ指数減衰なのか。理由はシンプルです。 パラメータが「半減期」ひとつで済み、直感的に扱えるから。

線形に減らす案も試しました。 けれど、休養が進んだ後半で回復が急に頭打ちになるのが不自然で―― 指数のほうが、実感に近い滑らかさになりました。

⏱️割り切り その2: 部位ごとに回復の半減期を変える

大きな筋群は回復が遅く、小さな筋群は早い――その順序関係を、半減期の初期値に反映させました。

次の割り切りは、回復のスピードを部位ごとに変えたことです。 大きな筋群は回復に時間がかかり、小さな筋群は比較的早く戻る。 この一般的な経験則に沿って、半減期を部位別に置きました。

実装では、脚や背中のような大筋群を長め、腕や肩のような小さめの部位を短めに。 そんな配分にしています。

運動後の筋機能の低下と回復には数十時間単位の幅があることは、筋損傷の研究でも報告されています(Exercise-Induced Muscle Damage のレビュー(PMC))。

ただ、狙いは論文値を厳密に再現することではありません。 「大筋群のほうが戻りが遅い」という順序関係を、アプリの挙動に反映させること。 数字そのものは、使いながら直していく前提の初期値です。

📅割り切り その3: 直近7日間だけを見る

指数減衰なら1週間前の疲労はほぼ無視できる。だから集計の窓を、直近7日間に絞りました。

3つ目は、集計の窓を直近7日間に区切ったことです。 理屈のうえでは、何ヶ月も前のトレーニングもわずかに影響します。

でも指数減衰なら、1週間もすれば寄与はほぼ無視できる大きさに落ちる。 それなら7日間に絞ったほうが、処理も軽く、コードも読みやすくなります。

あわせて、各エクササイズがどの部位にどれだけ効くかは、 筋電(EMG)的な関与の強さを参考にした重みで振り分けています。 ベンチプレスなら胸に多く、補助的に肩や腕にも少し、という配分です。

7日ぶんの疲労を部位ごとに重みづけして足し合わせ、最後にスコアへ正規化する。 これが fit-ai の疲労計算の骨格です。

🧭正確さより「使える割り切り」を優先した

モデルは「当たっているか」ではなく「意思決定を少し助けるか」で評価する――そう割り切りました。

この3つはいずれも、生理学的な厳密さを犠牲にして、 実装の単純さと説明のしやすさを取った判断です。

私たちは医療機器を作っているわけではありません。 次のトレーニングの助けになる目安を出したいだけ。 だからモデルは「当たっているか」ではなく、「意思決定を少し助けるか」で評価しています。

作ってみて分かったことがあります。 疲労スコアの価値は、絶対値の正しさより、日々の相対的な変化にある――そういうことでした。

昨日より脚のスコアが下がっていれば鍛えどき。 そんなふうに、自分の履歴と比べる指標として機能します。 数字を過信させないために、UI 側でも「目安」であることを繰り返し伝えるようにしました。

📝まとめ: モデルは割り切りの集合体

疲労スコアは指数減衰・部位別の半減期・7日間の累積という、3つの割り切りでできています。

筋肉疲労スコアは、この3つの割り切りでできています。 どれも「正確だから」ではなく、「そのほうが作れて、説明できて、使えるから」選びました。

個人開発に近い一人会社の規模だからこそ、完璧なモデルを目指すより、 動く目安を早く出して、自分たちで使いながら直す。 そのほうが理にかなっている、と考えています。

モデル化とは、現実のどこを捨ててよいかを決める作業でもあります。 疲労という曖昧なものを一つの数字にする過程で、 その割り切りをできるだけ正直に開示しておく。 それが、使う人への誠実さだと思っています。

あなたが何かを数値化するとき、どこを捨てますか。 一度、その割り切りを言葉にしてみてください――きっと、モデルが少し正直になります。

開発パートナーを探していますか?

AIでプロダクトを最速で形にしませんか?

最短1週間でMVPを開発。アイデアの検証から本番リリースまで、i-Willinkがフルサポートします。まずはお気軽にご相談ください。

無料で相談する

最新記事をメールで受け取る