劉畊宏男孩女孩看過來!運動數據分析挖掘!⛵
- 2022 年 8 月 15 日
- 筆記
- FitBit, Kaggle, Python, 圖解數據分析 | 從入門到精通系列, 圖解機器學習算法 | 從入門到精通系列教程, 數據分析, 數據挖掘, 數據探索, 機器學習實戰 | 手把手教你玩轉機器學習, 特徵工程, 調參, 運動數據分析
💡 作者:韓信子@ShowMeAI
📘數據分析 ◉ 技能提升系列://www.showmeai.tech/tutorials/33
📘AI 面試題庫系列://www.showmeai.tech/tutorials/48
📘本文地址://www.showmeai.tech/article-detail/301
📢 聲明:版權所有,轉載請聯繫平台與作者並註明出處
📢 收藏ShowMeAI查看更多精彩內容
因為疫情,2年多的時間裏,大家多了很多居家的經歷,但是運動健康並不能因為居家而停止,健身隨時隨處可以進行!健身環大冒險等大熱,而前陣子的劉畊宏跳操,帶火了一大票畊宏男孩女孩,可穿戴設備市場大漲,而這些設備也記錄了大量的運動數據。
現在有非常多的運動穿戴設備,比如簡單的小米手環,到fitbit,到apple watch,而數據科學領域的從業者們,我們眾多的數據分析師和數據科學家,可以輕鬆分析健身設備上收集的數據,把數據科學和醫療保健結合起來。
在本篇內容中,ShowMeAI就基於 fitbit 手環記錄的一部分數據,講解如何進行有效的數據分析。本次使用的數據集可以在 Kaggle 平台 上免費下載。大家也可以通過ShowMeAI的網盤直接下載。
🏆 實戰數據集下載(百度網盤):公眾號『ShowMeAI研究中心』回復『實戰』,或者點擊 這裡 獲取本文 [12] 運動手環的數據分析挖掘與建模案例 『Fitabase 運動佩戴設備數據集』
⭐ ShowMeAI官方GitHub://github.com/ShowMeAI-Hub
本篇內容涉及的工具庫,大家可以參考ShowMeAI製作的工具庫速查表和教程進行學習和快速使用。
💡 數據導入
我們先導入所需工具庫,並讀取數據:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import plotly.express as px
import plotly.graph_objects as go
# 讀取數據
data = pd.read_csv('dailyActivity_merged.csv')
print(data.head())
該數據集由2016年12月3日-2016年12月5日期間通過亞馬遜Mechanical Turk進行的分佈式調查的受訪者產生。30名符合條件的Fitbit用戶同意提交個人追蹤器數據,包括身體活動、心率和睡眠監測的分鐘級輸出。個人報告可以通過輸出會話ID(A列)或時間戳(B列)進行解析。輸出結果之間的差異代表了不同類型的Fitbit追蹤器的使用和個人追蹤行為/偏好。
💡 初步分析
我們先看看這個數據集的缺失值情況:
data.isnull().sum()
我們可以通過info和describe查看數據基本信息。
data.info()
我們在數據中看到記錄時間的字段ActivityDate,我們把它轉換為時間型,以便進行後續進一步分析。
# 更改 ActivityDate 的數據類型。
data["ActivityDate"] = pd.to_datetime(data["ActivityDate"], format="%m/%d/%Y")
我們從字段名稱中可以看到,有記錄『非常活躍』、『相當活躍』、『輕度活躍』和『久坐』的時間信息,分別是VeryActiveMinutes、FairlyActiveMinutes、LightlyActiveMinutes、SedentaryMinutes,我們對所有時間做一個匯總。
data["TotalMinutes"] = data["VeryActiveMinutes"] + data["FairlyActiveMinutes"] + data["LightlyActiveMinutes"] + data["SedentaryMinutes"]
data["TotalMinutes"].sample(5)
我們通過describe函數查看一下數據集的描述性統計數據。
data.describe()
💡 EDA 探索性數據分析
數據集中的「卡路里」列記錄了每天燃燒多少卡路里,我們基於它做一點分析。
# 研究一下每日總步數和消耗的卡路里之間的聯繫。
figure = px.scatter(data_frame = data, x="Calories",
y="TotalSteps", size="VeryActiveMinutes",
trendline="ols",
title="總步數和消耗的卡路里的關係")
figure.show()
從上圖可以看出,每日熱量消耗與所採取的總步數之間存在直接關聯。 同樣的思路我們分析一下總路程和消耗卡路里的關係:
# 研究一下每日總路程和消耗的卡路里之間的聯繫。
figure = px.scatter(data_frame = data.dropna(), x="Calories",
y="TotalDistance", size="VeryActiveMinutes",
trendline="lowess", color='TotalSteps',
title="總路程和消耗的卡路里的關係")
figure.show()
上圖可以看到,總路程和卡路里之間也是正相關的關係。下面讓我們分析一下一天中的平均總活躍分鐘數。
label = ["Very Active Minutes", "Fairly Active Minutes", "Lightly Active Minutes", "Inactive Minutes"]
counts = data[["VeryActiveMinutes", "FairlyActiveMinutes", "LightlyActiveMinutes", "SedentaryMinutes"]].mean()
colors = ["gold","lightgreen", "pink", "blue"]
fig = go.Figure(data=[go.Pie(labels=label, values=counts)])
fig.update_layout(title_text="總活動時間")
fig.update_traces(hoverinfo="label+percent", textinfo="value", textfont_size=24, marker=dict(colors=colors, line=dict(color="black", width=3)))
fig.show()
一些觀察結論:
- 81.3% 的非活動分鐘數
- 15.8% 的輕度活動分鐘數
- 平均21 分鐘(1.74%)非常活躍
- 評價13 分鐘(1.11%)的相當活躍的分鐘數
下面我們展開做一點更詳細的分析,我們先抽取更細化的信息,我們添加一個新字段「Day」記錄星期幾。
data["Day"] = data["ActivityDate"].dt.day_name()
data["Day"].head()
下面我們可視化對比一下一周中每一天的『非常活躍』、『相當活躍』和『輕度活躍』的分鐘數。
fig = go.Figure()
fig.add_trace(go.Bar(
x=data["Day"],
y=data["VeryActiveMinutes"],
name="Very Active",
marker_color="purple"
))
fig.add_trace(go.Bar(
x=data["Day"],
y=data["FairlyActiveMinutes"],
name="Fairly Active",
marker_color="green"
))
fig.add_trace(go.Bar(
x=data["Day"],
y=data["LightlyActiveMinutes"],
name="Lightly Active",
marker_color="pink"
))
fig.update_layout(barmode="group", xaxis_tickangle=-45)
fig.show()
讓我們看看一周中每一天的非活動分鐘數。
day = data["Day"].value_counts()
label = day.index
counts = data["SedentaryMinutes"]
colors = ['gold','lightgreen', "pink", "blue", "skyblue", "cyan", "orange"]
fig = go.Figure(data=[go.Pie(labels=label, values=counts)])
fig.update_layout(title_text='Inactive Minutes Daily')
fig.update_traces(hoverinfo='label+percent', textinfo='value', textfont_size=30,
marker=dict(colors=colors, line=dict(color='black', width=3)))
fig.show()
從這份數據看來,星期四是大家最不活躍的一天。 下面我們來看看一周中每一天燃燒的卡路里數。
calories = data["Day"].value_counts()
label = calories.index
counts = data["Calories"]
colors = ['gold','lightgreen', "pink", "blue", "skyblue", "cyan", "orange"]
fig = go.Figure(data=[go.Pie(labels=label, values=counts)])
fig.update_layout(title_text='Calories Burned Daily')
fig.update_traces(hoverinfo='label+percent', textinfo='value', textfont_size=30, marker=dict(colors=colors, line=dict(color='black', width=3)))
fig.show()
從上圖可以看出,星期二是這份數據集中的用戶最活躍的日子之一,這一天燃燒的卡路里最多。 下面我們分析一下每日步數:
import seaborn as sns
sns.set(rc={'figure.figsize':(8,6)})
activity_by_week_day = sns.barplot(x="Day", y="TotalSteps", data=data,
order=['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'],
capsize=.2)
💡 每日消耗卡路里預估
下面我們搭建一個模型,對於每日消耗的卡路里進行建模預估。
本部分涉及到的模型知識與建模操作方法,參見ShowMeAI以下部分教程:
我們剔除ID類特徵和日期特徵,把『Calories』作為目標,把其他字段作為特徵,注意其中的『星期幾/Day』字段是類別型,我們要單獨編碼一下。
features = ['TotalSteps', 'TotalDistance', 'TrackerDistance', 'LoggedActivitiesDistance', 'VeryActiveDistance', 'ModeratelyActiveDistance', 'LightActiveDistance', 'SedentaryActiveDistance', 'VeryActiveMinutes', 'FairlyActiveMinutes', 'LightlyActiveMinutes', 'SedentaryMinutes', 'TotalMinutes', 'Day']
target = 'Calories'
# 數據切分
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(data[features], data[target], test_size=0.2, random_state=0)
# 使用lightgbm訓練
from lightgbm import LGBMRegressor
lgbm = LGBMRegressor(n_estimators=1000, learning_rate=0.05, random_state=0)
# 「星期幾」字段編碼
from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()
X_train['Day'] = le.fit_transform(X_train['Day'])
X_test['Day'] = le.transform(X_test['Day'])
# 擬合模型
lgbm.fit(X_train, y_train)
# 測試集預估
predictions = lgbm.predict(X_test)
# 計算測試集RMSE
from sklearn.metrics import mean_squared_error
rmse = np.sqrt(mean_squared_error(y_test, predictions))
print("RMSE: %f" % (rmse))
運行得到結果為RMSE: 373.128953
為了更準確地進行建模和評估,我們使用網格搜索交叉驗證進行超參數優化:
# 使用網格搜索對lightgbm模型進行超參數調優
from sklearn.model_selection import GridSearchCV
parameters = {
'learning_rate': [0.02, 0.05, 0.08, 0.1],
'max_depth': [5, 7, 10],
'feature_fraction': [0.6, 0.8, 0.9],
'subsample': [0.6, 0.8, 0.9],
'n_estimators': [100, 200, 500, 1000]}
# 網格搜索
grid_search = GridSearchCV(lgbm, parameters, cv=5, n_jobs=-1, verbose=1)
# 最佳模型
grid_search.fit(X_train, y_train)
best_lgbm = grid_search.best_estimator_
# 輸出最佳超參數
print(grid_search.best_params_)
# 測試集預估
predictions = best_lgbm.predict(X_test)
# 計算RMSE
from sklearn.metrics import mean_squared_error
rmse = np.sqrt(mean_squared_error(y_test, predictions))
print("RMSE: %f" % (rmse))
最終結果輸出
{'feature_fraction': 0.6, 'learning_rate': 0.05, 'max_depth': 5, 'n_estimators': 1000, 'subsample': 0.6}
RMSE: 352.782209
我們可以看到,調參後的模型在測試集上表現更優。最後我們輸出一下特徵重要度,看看那些因素對於卡路里消耗更加重要:
#繪製特徵重要度
import matplotlib.pyplot as plt
plt.figure(figsize=(20,10))
importance = best_lgbm.feature_importances_
feature_importance = pd.DataFrame({'feature': features, 'importance': importance})
feature_importance = feature_importance.sort_values('importance', ascending=True)
feature_importance.plot.barh(x='feature', y='importance', figsize=(20,10))
可以看到,每日總步數對結果影響最大,大家要多多抬腿多多運動!
參考資料
- 🏆 實戰數據集下載(百度網盤):公眾號『ShowMeAI研究中心』回復『實戰』,或者點擊 這裡 獲取本文 [12] 運動手環的數據分析挖掘與建模案例 『Fitabase 運動佩戴設備數據集』
- ⭐ ShowMeAI官方GitHub://github.com/ShowMeAI-Hub
- 📘數據科學工具庫速查表 | Pandas 速查表 //www.showmeai.tech/article-detail/101
- 📘 圖解數據分析:從入門到精通系列教程 //www.showmeai.tech/tutorials/33
- 📘 圖解機器學習算法:從入門到精通系列教程 //www.showmeai.tech/tutorials/34
- 📘 機器學習實戰:手把手教你玩轉機器學習系列 //www.showmeai.tech/tutorials/41


