4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

機械学習でフルマラソンのゴールタイムを予測~③:Pythonでデータ可視化してみた~

Last updated at Posted at 2020-03-15

##概要
前回からの続きです。
【機械学習でフルマラソンのゴールタイムを予測】と題して、ランニングの練習時のデータからフルマラソン(42.195㎞)を走った場合のゴールタイムを予測するために、データ収集からモデル作成・予測までの一連の流れを書いていきます。

前回記事(機械学習でフルマラソンのゴールタイムを予測~②:Garminで学習データを作成してみた~)では、学習データを作成するために、不要な項目の削除と必要なデータの追加を行う手順について記載しました。

今回は作成した学習データを使ってフルマラソンのゴールタイムを予測する予測モデルを作成する前に、データを可視化して全体の傾向を見ていくところについて記載していきます。
Excelで簡単にできるものも含まれますが、同じことをPythonでやるとしたらどうやってコードを書けばいいのか知る機会として頂ければ幸いです。
cat-984097_1920.jpg
pixtabayより

##学習データの中身
ランニング時の距離やペースに影響を与えると考えられる14個の項目を特徴量とする学習データを作成しています。

  1. 練習日付(yyyy/mm/dd HH:MM:ss) 項目名:Practice Time
  2. 距離(㎞) 項目名:Distance
  3. タイム(HH:MM:ss) 項目名:Time
  4. 平均心拍数(bpm) 項目名:Average heart rate
  5. 最大心拍数(bpm) 項目名:Max heart rate
  6. 有酸素TE 項目名:Aerobic TE
  7. 平均ピッチ(歩/分) 項目名:Average pitch
  8. 1㎞あたりの平均ペース(HH:MM:ss/㎞) 項目名:Average pace
  9. 1㎞あたりの最高ペース(HH:MM:ss/㎞) 項目名:Max pace
  10. 平均歩幅(cm/歩) 項目名:Average stride
  11. 走り始めの気温(℃) 項目名:temperature
  12. 走り始めの風速(m/秒) 項目名:Wind speed
  13. その週の就業時間(h/週) 項目名:Work
  14. その週の1日あたりの平均睡眠時間(HH:MM:ss/日) 項目名:Average sleep time

1レコード分のサンプルデータ

Practice Time Distance Time Average heart rate Max heart rate Aerobic TE Average pitch Average pace Max pace Average stride temperature Wind speed Work Average sleep time
2020/2/23 16:18:00 8.19 0:59:35 161 180 3.6 176 00:07:16 00:06:11 0.78 7.9 9 44.5 6:12:00

##1か月ごとの走行距離

まずはデータを可視化する上で必要になりそうなものをインポートしておきます。
とりあえずこのくらいあれば事足りるかと思います。

RunnningDataVisualization.ipynb
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.dates as mdates
import seaborn as sns

1か月ごとの走行距離のグラフ描画は以下のコードでできます。

RunnningDataVisualization.ipynb
df = pd.read_csv(r'Activities.csv', index_col=["PracticeTime"],parse_dates=True) 
#"PracticeTime"を日付型として読み込むために、インデックスの指定を引数index_colで行い、
#parse_datesにTrueを指定し、index_colで指定した項目を日付型のインデックスとする

#グラフを描画
df_m = df.resample(rule="M").sum()
df_m_graph = df_m['Distance']
df_m_graph.plot.bar()

#グラフの表示形式をいろいろ設定
plt.title("Distance per month", fontsize = 22) #グラフにタイトル名をつける
plt.grid(True) #グラフに目盛り線をつける
plt.xlabel("month", fontsize = 15)  #グラフの横軸にラベルをつける
plt.ylabel("km", fontsize = 15)  #グラフの縦軸にラベルをつける
plt.yticks( np.arange(0, 60, 5) ) #グラフのサイズを調整する

<実行結果>
キャプチャ.JPG

こうやって見ると、夏の暑い時期にいかに練習できていないかがよくわかりますw

##散布図~ペースとピッチの関係性~

次に、1㎞あたりのペースとピッチに相関があるのか調べるため、散布図を書いていきます。
一般的に考えると、ペースが落ちればピッチ(1分間あたりの歩数)も減少していきそうですが、実際のところどうなのでしょうか。

RunnningDataVisualization.ipynb
df = df.sort_values("Average pace") #ペースを速い順に並べ替える
plt.scatter(df['Average pace'], df['Average pitch'],s=40 ,marker="*", linewidths="4", edgecolors="orange") #散布図を描画

plt.title("Scatter plot of pace and pitch", fontsize = 22)
plt.ylabel('Average pitch', fontsize = 15)
plt.xlabel('Average pace', fontsize = 15)
plt.grid(True)
plt.xticks(rotation=90)
plt.figure(figsize=(50, 4))

<実行結果>
キャプチャ.JPG

ペースが速いか遅いかにかかわらず、ピッチはその時によってばらばらであることが分かります。

##散布図~ペースとストライドの関係性~
それでは次に、ペースとストライドの関係性はどうでしょうか。
ペースが落ちれば、ストライド(1歩あたりの歩幅)も減少していきそうです。

RunnningDataVisualization.ipynb
df = df.sort_values("Average pace")
plt.scatter(df['Average pace'], df['Average stride'],s=40 ,marker="*", linewidths="4", edgecolors="blue")
plt.title("Scatter plot of pace and stride", fontsize = 22)
plt.ylabel('Average stride', fontsize = 15)
plt.xlabel('Average pace', fontsize = 15)
plt.grid(True)
plt.xticks(rotation=90)
plt.figure(figsize=(10, 10),dpi=200)
plt.show()

<実行結果>
キャプチャ.JPG

さきほどのペースとピッチの散布図と違い、こちらは点の集まりが何となく右下がりになっていることが分かります。
つまり、ペースが下がれば下がるほど、ストライドは最大25㎝ほど小さくなっているということが読み取れます。

距離をたくさん走っていくと、必ずペースががくっと落ちる瞬間が訪れますが、原因の1つはこれだったのか!とPythonで可視化したことで納得することができます。←

##特徴量同士の相関係数

最後に、各特徴量同士の相関係数を出してみます。
Garminで記録されているデータに加えて自分で学習データに追加した4つの特徴量(気温、風速、週単位での就業時間、平均睡眠時間)の中に、走行距離や心拍数などとの相関の強い特徴量が現れれば、それはペースや走行距離に何かしらの影響を与えていると考えられます。

今回は時刻データの相関係数の出し方が分からなかったので、数値データの特徴量間の相関係数のみ算出しています。

相関係数を算出するにあたり、csv読み込み時に文字列として読み込まれてしまった平均心拍数と最大心拍数の値を文字列から数値に型変換しておきます。

RunnningDataVisualization.ipynb

#型変換
df['Average heart rate'] = df['Average heart rate'].fillna(0).astype(np.int64)
df['Max heart rate'] = df['Max heart rate'].fillna(0).astype(np.int64)

#相関係数を可視化
df_corr = df.corr()
print(df_corr) #特徴量同士の相関係数を一覧で表示
fig = plt.subplots(figsize=(8, 8)) #分かりやすく可視化
sns.heatmap(df_corr, annot=True,fmt='.2f',cmap='Blues',square=True)

<実行結果>
キャプチャ.JPG
キャプチャ.JPG

注目した3つの特徴量(気温、風速、週単位での就業時間)では、他の特徴量との相関係数の絶対値が0.5を超えるものがありません。
つまり、これら3つの特徴量はさほど走行距離やペースに影響しないということが分かります。

まあ、考えてみれば暑すぎる日や寒すぎる日、風の強い日はそもそもランニングの練習をしませんし、その週の就業時間が多ければ体力的な疲労が少なからず溜まることになるので、これまたランニングの練習はしないという選択をすることになります。
というわけで、この結果もまたまた納得のいく結果です。

残念ながら、相関係数を算出しただけでは走行距離やペースに影響を与える特徴量を見つけることはできませんでしたが、このようにいろいろとデータを見ながら可視化してみることで、走る時の自分の傾向や、練習の仕方について振り返る良い機会になります。

次回はいよいよ予測モデルを作成し、予測処理を回していきます。

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?