Pythonと教師なし学習でクロノタイプを発見する
PythonでK-MeansやDBSCANなどのクラスタリングを使い、生の睡眠データから「夜型」「朝型」などのクロノタイプにユーザーを分類する方法を解説
このページの内容
あなたは真夜中以降が最も活気づく「ナイトオウル」ですか、それとも明け方に最も生産的になる「アーリーバード」ですか?これらの自然な傾向はクロノタイプと呼ばれ、仕事のパフォーマンスから健康まで、私たちの人生に大きな影響を与えます。ユーザーの睡眠データからこれらのパターンを自動的に発見できるとしたらどうでしょうか?
この深掘りでは、睡眠タイミングのデータセットからユーザーのクロノタイプを解明するための完全なデータサイエンスプロジェクトをウォークスルーします。K-MeansとDBSCANという教師なしクラスタリングアルゴリズムを使用して、ユーザーが「アーリーバード」「ナイトオウル」「標準的な睡眠者」などの意味のあるグループに分類されるようにします。
前提条件: Pythonの基本的な理解と、Pandasを使用したデータ操作の経験があることが必要です。機械学習の概念に関する事前の知識があると有利ですが、厳密には必須ではありません。Python 3と、Pandas、Scikit-learn、Matplotlibライブラリがインストールされている必要があります。
これが開発者にとって重要な理由: ユーザー行動を理解することは、パーソナライズされた体験を構築するために不可欠です。健康・ウェルネスアプリにとって、クロノタイプでユーザーをセグメント化することで、最適な睡眠スケジュール、ワークアウト時間、さらには生産性ハックに関する-tailored recommendations(個人化された推奨事項)を実現できます。
注: この例はデモンストレーション用の合成/シミュレーションデータを使用しています。本番環境では、すべての睡眠データが匿名化され、HIPAA/GDPRに準拠して処理されていることを確認してください。
問題の理解
質問紙によるクロノタイプの人的特定は主観的かつ時間がかかります。教師なし機械学習は、受動的に収集された睡眠データからこれらのパターンを特定するためのデータ駆動型アプローチを提供します。主な課題は、生の睡眠タイミングを、クラスタリングアルゴリズムが類似のユーザーをグループ化するために効果的に使用できる意味のある特徴に変換することにあります。
ウェアラブルテクノロジーと健康アプリは現在、大量の睡眠データを提供します。研究者和企業は、睡眠の質とパターンに関する洞察を得るために、機械学習を使用してこのデータを分析することが増えています。自己報告情報に頼る代わりに、ユーザーの自然なグループ化を解明するために客観的な睡眠タイミングデータを使用します。
クロノタイプクラスタリングアーキテクチャ
次の図は、ユーザーのクロノタイプを発見するための教師なし学習パイプラインを示しています:
前提条件
必要なツール/ライブラリ:
- Python 3.x
- Pandas
- Scikit-learn
- Matplotlib
- Seaborn
バージョンの互換性について: このチュートリアルのコードは、Python 3.8、Pandas 1.3、Scikit-learn 1.0、Matplotlib 3.5、Seaborn 0.11を使用して記述されました。マイナーなバージョンの違いでは問題は発生しないはずです。
必要なライブラリをインストールするには、ターミナルで次のコマンドを実行してください:
pip install pandas scikit-learn matplotlib seaborn
睡眠タイミングデータの読み込みと前処理
実施内容
まず、データセットを読み込み、特徴量エンジニアリングの準備整えます。Kaggleからの合成「学生睡眠パターン」データセットを使用します。これは平日と週末の睡眠・起床時間含まれているため、分析に最適です。データをクリーンアップし、不整合的处理し、時間形式をより使いやすいものに変換します。
実装
# src/data_preprocessing.py
import pandas as pd
# Load the dataset
try:
df = pd.read_csv('student_sleep_patterns.csv')
except FileNotFoundError:
print("Please download the dataset from: https://www.kaggle.com/datasets/ssooni/student-sleep-patterns-dataset")
exit()
# Display the first few rows and basic info
print("Original DataFrame head:")
print(df.head())
print("\
DataFrame Info:")
df.info()
# For this analysis, we are interested in the sleep timing columns
sleep_timing_df = df[['Student_ID', 'Weekday_Sleep_Start', 'Weekday_Sleep_End', 'Weekend_Sleep_Start', 'Weekend_Sleep_End']].copy()
print("\
Sleep Timing DataFrame head:")
print(sleep_timing_df.head())
動作原理
CSVファイルをPandas DataFrameに読み込みます。.head()関数は構造を理解するために最初の数行を表示し、.info()はデータ型と非null値の概要を提供します。次に、クロノタイプ分析に関連する列のみを含む新しいDataFrame sleep_timing_dfを作成します。
一般的な落とし穴
- ファイルが見つからない: CSVファイルがPythonスクリプトと同じディレクトリにあることを確認するか、正しいファイルパスを指定してください。
- 一貫性のない時間形式: 実世界のデータでは、時間形式が乱雑な場合があります(例:'10:00 PM'、'22:00'、'10pm')。データセットは24時間float形式を使用しているため、物事は単純です。他の形式については、
pd.to_datetimeの使用が必要な場合があります。
クラスタリング用の睡眠特徴量の設計
実施内容
クロノタイプでユーザーをクラスタリングするには、睡眠行動を表す特徴量を作成する必要があります。これらの中で最も効果的な2つの特徴量は:
- 睡眠の中間点: 就寝時間と起床時間のちょうど中間点です。これは、人の自然な睡眠タイミングの強いつまりがあります。
- 睡眠時間: 睡眠に費やした合計時間。
平日と週末の両方で計算して、行動の違いを捉えます。
入力: 列Weekday_Sleep_Start、Weekday_Sleep_End、Weekend_Sleep_Start、Weekend_Sleep_Endを含むDataFrame
出力: 設計された特徴量Weekday_Midpoint、Weekday_Duration、Weekend_Midpoint、Weekend_Durationを含むDataFrame
実装
# src/feature_engineering.py
import numpy as np
def calculate_sleep_features(df):
"""Calculates midpoint of sleep and sleep duration."""
features_df = df.copy()
for period in ['Weekday', 'Weekend']:
start_col = f'{period}_Sleep_Start'
end_col = f'{period}_Sleep_End'
# Convert times to hours from midnight
start_time = features_df[start_col]
end_time = features_df[end_col]
# Handle overnight sleep
duration = np.where(end_time > start_time,
end_time - start_time,
(24 - start_time) + end_time)
midpoint = (start_time + duration / 2) % 24
features_df[f'{period}_Duration'] = duration
features_df[f'{period}_Midpoint'] = midpoint
return features_df
features_df = calculate_sleep_features(sleep_timing_df)
print("\
DataFrame with Engineered Features:")
print(features_df.head())
動作原理
- 「平日」と「週末」の両方で、睡眠時間を計算します。真夜中を跨いだ睡眠を考慮する必要があります。
end_timeがstart_timeより小さい場合、それはその人が翌日目が覚めたことを意味します。この場合、睡眠時間は(24 - start_time) + end_timeです。 - 睡眠の「中間点」は、睡眠時間の半分を開始時刻に加えることで計算されます。モジュロ演算子(
% 24)を使用して、中間点が24時間制の時計を巡回するようにします。
一般的な落とし穴
- 夜跨ぎの考慮漏れ: 単純な
end_time - start_timeは夜跨ぎの睡眠に対して負の睡眠時間を返します。np.where関数はこの条件付きロジックを処理するクリーンな方法です。
K-Meansアルゴリズムによるユーザーのクラスタリング
実施内容
K-Meansは、データを事前に定義された数のクラスター(k)にグループ化する人気のクラスタリングアルゴリズムです。クロノタイプ発見のの出発点として優れています。最適なクラスター数を決定するために「エルボー法」を使用し、設計された特徴量にK-Meansモデルを適合させます。
入力: 列[Weekday_Midpoint, Weekday_Duration, Weekend_Midpoint, Weekend_Duration]を含む特徴量行列X
出力: 各ユーザーのクラスター割り当て(0、1、2)はクロノタイプを表します
実装
# src/kmeans_clustering.py
from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler
import matplotlib.pyplot as plt
import seaborn as sns
# Select features for clustering
X = features_df[['Weekday_Midpoint', 'Weekday_Duration', 'Weekend_Midpoint', 'Weekend_Duration']]
# Scale the features
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# Elbow method to find the optimal k
inertia = []
K = range(1, 11)
for k in K:
kmeans = KMeans(n_clusters=k, random_state=42, n_init=10)
kmeans.fit(X_scaled)
inertia.append(kmeans.inertia_)
plt.figure(figsize=(8, 5))
plt.plot(K, inertia, 'bx-')
plt.xlabel('Number of clusters (k)')
plt.ylabel('Inertia')
plt.title('Elbow Method For Optimal k')
plt.show()
# Based on the elbow plot, let's choose k=3
k = 3
kmeans = KMeans(n_clusters=k, random_state=42, n_init=10)
features_df['KMeans_Cluster'] = kmeans.fit_predict(X_scaled)
print("\
DataFrame with K-Means Clusters:")
print(features_df.head())
# Visualize the clusters
plt.figure(figsize=(10, 6))
sns.scatterplot(data=features_df, x='Weekday_Midpoint', y='Weekend_Midpoint', hue='KMeans_Cluster', palette='viridis', s=100)
plt.title('Chronotype Clusters (K-Means)')
plt.xlabel('Weekday Sleep Midpoint')
plt.ylabel('Weekend Sleep Midpoint')
plt.legend(title='Cluster')
plt.show()
動作原理
- 特徴量スケーリング:
StandardScalerを使用して特徴量を正規化します。これはK-Meansのような距離ベースのアルゴリズムにとって重要であり、大きいスケールを持つ特徴量がクラスタリングプロセスを支配することを防ぎます。 - エルボー法: 異なる
kの値に対して慣性(最も近いクラスター中心へのサンプルの二乗距離の合計)を計算します。慣性の減少率が遅くなる「エルボー」が、最適なクラスター数を示します。このデータでは、k=3前後です。 - クラスタリングと可視化:
k=3でK-Meansモデルを適合させ、クラスターラベルをDataFrameに戻します。散布図は、平日と週末の睡眠中間点に基づいて結果のクラスターを可視化するのに役立ちます。
一般的な落とし穴
- 特徴量のスケーリング忘れ: 特徴量スケールが大きく異なる場合、歪んだクラスターが発生する可能性があります。
- エルボーの誤解: エルボーが明確でない場合があります。そんな場合は、シルエットスコアなどの他の方法を使用するか、ドメイン知識に依存して
kを選択する必要があります。
DBSCANクラスタリングによる外れ値の検出
実施内容
DBSCAN(Density-Based Spatial Clustering of Applications with Noise)は、任意の形状のクラスターを識別し、外れ値にも堅牢な別の強力なクラスタリングアルゴリズムです。K-Meansとは異なり事前にクラスター数を指定する必要はありません。これは、データに自然にどれくらいの数のグループが存在かわからない場合に非常に便利です。
入力: スケールされた特徴量行列X_scaled
出力: ノイズ/外れ値ポイントを-1で示すクラスター割り当て
実装
# src/dbscan_clustering.py
from sklearn.cluster import DBSCAN
# Using the same scaled features
dbscan = DBSCAN(eps=0.5, min_samples=5)
features_df['DBSCAN_Cluster'] = dbscan.fit_predict(X_scaled)
print("\
DataFrame with DBSCAN Clusters:")
print(features_df.head())
print("\
DBSCAN Cluster Counts:")
print(features_df['DBSCAN_Cluster'].value_counts())
# Visualize the clusters
plt.figure(figsize=(10, 6))
sns.scatterplot(data=features_df, x='Weekday_Midpoint', y='Weekend_Midpoint', hue='DBSCAN_Cluster', palette='viridis', s=100)
plt.title('Chronotype Clusters (DBSCAN)')
plt.xlabel('Weekday Sleep Midpoint')
plt.ylabel('Weekend Sleep Midpoint')
plt.legend(title='Cluster')
plt.show()
動作原理
- DBSCANパラメータ: DBSCANには2つの主要パラメータがあります:
eps(1つがもう1つの近傍と見なされるための2つのサンプル間の最大距離)とmin_samples(ポイントを中心にサンプルと見なされるために近傍内のサンプル数)。これらの調整は Tricky で、多少の実験が必要な場合があります。 - ノイズ検出: DBSCANはノイズポイントを-1としてラベル付けします。これはAnyクラスターに属さない外れ値を分離できるキーな利点です。
一般的な落とし穴
- パラメータ調整: DBSCANのパフォーマンスは
epsとmin_samplesに敏感です。Poorな選択は、すべてのポイントが1つのクラスターにあるか、すべてのポイントがノイズとしてラベル付けされる結果をもたらす可能性があります。意味のある結果を得るために異なる値で実験する必要がある場合があります。
すべてを組み合わせる
見つけたクラスターを分析して解釈しましょう。クラスターラベルでDataFrameをグループ化し、各グループの Features の平均値を見ることができます。
# src/analyze_clusters.py
# Analyze K-Means clusters
kmeans_summary = features_df.groupby('KMeans_Cluster')[['Weekday_Midpoint', 'Weekend_Midpoint', 'Weekday_Duration', 'Weekend_Duration']].mean()
print("\
K-Means Cluster Summary:")
print(kmeans_summary)
# Analyze DBSCAN clusters
dbscan_summary = features_df[features_df['DBSCAN_Cluster'] != -1].groupby('DBSCAN_Cluster')[['Weekday_Midpoint', 'Weekend_Midpoint', 'Weekday_Duration', 'Weekend_Duration']].mean()
print("\
DBSCAN Cluster Summary:")
print(dbscan_summary)
K-Meansクラスターの解釈: K-Meansサマリーの出力に基づいて、3つの異なるグループが見つかる場合があります:
- クラスター0:アーリーバード: 平日と週末の両方で中間点が低い(例:午前3〜4時頃)、常に早起きの就寝・起床を示唆しています。
- クラスター1:ナイトオウル: 平日と週末の両方で中間点が高い(例:午前6〜7時頃)、後の睡眠時間を偏好を示しています。
- クラスター2:標準的な睡眠者: 他の2つのグループの中間点、より典型的な睡眠スケジュールを表しています。
代替アプローチ
- 階層的クラスタリング: この方法はクラスターのツリーを作成し、グループがネストされている様子を可視化するのに便利です。事前に定義されたクラスター数は必要ありませんが、ツリーを「切る」場所を決定する必要があります。
- ガウス混合モデル(GMM): GMMは、データポイントが有限数のガウス分布の混合物から生成されると仮定する確率的モデルです。これは球形ではないクラスターを可能にするため、K-Meansより柔軟です。
結論
- 成果の要約: 睡眠タイミングデータからユーザーのクロノタイプを発見するためのエンドツーエンドのパイプラインを正常に構築しました。データをクリーンアップし、意味のある特徴量を設計し、K-MeansとDBSCANという2つの異なる教師なしクラスタリングアルゴリズムを適用して、ユーザーを明確なグループにセグメント化しました。
- 読者への次のステップ: この方法論を異なる行動データセットに適用してみてください。他のクラスタリングアルゴリズムを試したり、「社会的時差ぼけ」(平日と週末の睡眠パターンの違い)のような追加の特徴量を設計したりすることもできます。
- 行動への呼びかけ: コードを試して、自分のデータで何を発見できるか試してみてください!発見したことや加えた興味深い変更点を下のコメントで共有してください!
リソース
クイックリファレンス
| 側面 | 主要情報 |
|---|---|
| トピック | データサイエンス |
| 関連性 | 患者教育と認識 |
| 行動 | 医療提供者との相談 |
| 頻度 | ケアチームのおすすめに応じて |
| 証拠 | 現在の臨床ガイドラインに基づく |
よくある質問
Q: これが自分に該当するかどのようにわかりますか? A: あなたの個人的および家族の病史について医療提供者と相談し、あなたの個人のリスク要因を評価し、適切な次のステップを決定してください。
Q: 医師に何を聞くべきですか? A: 良い質問には次のようなものがあります:「私の結果の意味は何ですか?」「私のオプションは何ですか?」「どのような生活習慣の変化が役に立ちますか?」「いつフォローアップすべきですか?」
Q: 役立つ可能性のある生活習慣の変化はありますか? A: ほとんどの健康状態は、基本的な対策から恩恵を受けます:バランスの取れた栄養、定期的な身体活動(週150分以上)、質の良い睡眠(7〜9時間)、ストレス管理,以及び煙草の回避。
医療免責事項
この記事は教育目的のみを目的としており、医学的アドバイス構成しません。あなたの健康、治療、またはケアに関する決定する前に、常に資格のある医療提供者と相談してください。個人の状況は異なり、1人に適切なものが別の人に適切でない場合があります。
救急医療の状況が発生した場合は、直ちに911(または現地の緊急番号)に電話してください。