バーンアウト検知器の作り方:PythonとScikit-learnでGitコミットパターンを分析する
開発者向けメンタルヘルスガイド。GitHub API、Pandas、Scikit-learnを使ってコミット履歴を分析し、潜在的なバーンアウトに関連するパターンを特定する機械学習モデルを構築する方法を学びます。
このページの内容
開発者の私たちにとって、人生はGitの履歴に刻まれています。コミット一つ一つが問題を解決した物語、機能を構築した物語、バグを修正した物語を語っています。しかし、もしこれらの同じコミットが別の物語−−私たちの幸福についての物語−−を語ることができるとしたらどうでしょうか?テクノロジー業界では、燃え尽き症候群は遍在する問題です。「喜べないコミット」−−コードはプッシュしているが達成感がない−−は現実の現象です。
このチュートリアルは、メンタルヘルスに対する独自の、開発者中心のアプローチを取ります。GitHubのコミット履歴を使用して、燃え尽き症候群のリスクを示唆する可能性のあるパターンを特定するPythonスクリプトを構築します。コミット頻度、コミットメッセージの長さ、コードをプッシュする時間帯などのデータを分析することで、「通常」の状態を学習し、潜在的な逸脱をフラグ付けするモデルを作成できます。
前提条件:
- Python 3.7以上がインストールされていること。
pipを使ったパッケージインストールを含むPythonの知識。- いくつかのコミット履歴を持つGitHubアカウント。
- Pandasと機械学習の概念の基本的な理解があると有益ですが、必須ではありません。
なぜこれが開発者にとって重要なのか:
これは完璧な燃え尽き症候群予測器を作るということではありません。毎日使っているツールを使って自己認識を育むということです。自分のデータにレンズを向けることで、仕事と生活のバランスやメンタルヘルスについて重要な問いかけを始めることができます。
問題の理解
開発者の燃え尽き症候群は多くの場合、-gradual-gradualなプロセスです。意識的に認識されるずっと前から、作業パターンの変化として現れることがあります。Gitデータにおける潜在的な指標としては:
- 深夜のコミット: 通常の勤務時間外にコミットが急に増えること。
- 不安定なコミット頻度: 激しい活動期と音信不通期が大きく変動すること。
- 短くて情報のないコミットメッセージ: 没頭していない、または急いでいる潜在的な兆候。
- コミット量の減少: 必ずしも悪いわけではありませんが、顕著な減少は motivation不足を示唆している可能性があります。
これを分類問題として扱います。過去のデータにラベルを付ける(例えば、自分の記憶に基づいて「通常」と「燃え尽き」期間を分類)し、各associated関連するパターンを認識するように機械学習モデルを訓練します。
前提条件
まず、環境を設定しましょう。GitHub APIを使用するために、GitHubパーソナルアクセストークンが必要です。
-
GitHubパーソナルアクセストークンを生成する:
- GitHub Settings > Developer settings > Personal access tokensにアクセスします。
- 「Generate new token」をクリックします。
- 説明的な名前をつけます(例:「Burnout Detector」)。
- 「Scopes」で
repoスコープを選択します。これによりリポジトリへの読み取りアクセスが付与されます。 - 「Generate token」をクリックし、どこか安全な場所にコピーします。もう一度見ることはできません。
-
Pythonライブラリをインストールする:
bash pip install requests pandas scikit-learn matplotlib seaborn
ステップ1:コミット履歴の取得
何をしているのか
requestsライブラリを使用してGitHub APIに接続し、特定のリポジトリのコミット履歴を取得します。
実装
新しいPythonファイルburnout_detector.pyを作成します。
# burnout_detector.py
import requests
import pandas as pd
import os
# --- Configuration ---
GITHUB_TOKEN = os.environ.get('GITHUB_TOKEN') # Best practice to use environment variables
REPO_OWNER = 'your-github-username'
REPO_NAME = 'your-repo-name'
# ---------------------
def fetch_all_commits(owner, repo, token):
"""Fetches all commits for a given repository."""
commits = []
page = 1
per_page = 100
headers = {'Authorization': f'token {token}'}
while True:
url = f'https://api.github.com/repos/{owner}/{repo}/commits?page={page}&per_page={per_page}'
response = requests.get(url, headers=headers)
if response.status_code != 200:
print(f"Error: {response.status_code}")
print(response.json())
break
data = response.json()
if not data:
break
commits.extend(data)
page += 1
return commits
# --- Main execution ---
if __name__ == '__main__':
if not GITHUB_TOKEN:
raise ValueError("Please set the GITHUB_TOKEN environment variable.")
print(f"Fetching commits for {REPO_OWNER}/{REPO_NAME}...")
all_commits = fetch_all_commits(REPO_OWNER, REPO_NAME, GITHUB_TOKEN)
print(f"Found {len(all_commits)} commits.")
# Convert to DataFrame for easier manipulation
df = pd.json_normalize(all_commits)
print(df.head())
実行する前に:
'your-github-username'と'your-repo-name'を自分の情報に置き換えてください。- セキュリティのために
GITHUB_TOKENを環境変数として設定します:- Mac/Linux:
export GITHUB_TOKEN='your_token_here' - Windows:
set GITHUB_TOKEN='your_token_here'
- Mac/Linux:
スクリプトを実行します:python burnout_detector.py
動作の仕組み
GitHub Commits APIエンドポイントにページ分けされたGETリクエストを送ります。while Trueループは、APIが空のリストを返すまでコミットのページを取得し続けます。次にpandas.json_normalizeを使用して、ネストされたJSONレスポンスをDataFrame(データ分析に理想的なテーブル形式の構造)に平坦化します。
ステップ2:Pandasによる特徴量エンジニアリング
何をしているのか
「特徴量エンジニアリング」とは、生データから機械学習モデル用の意味のある入力変数(特徴量)を作成するプロセスです。Pandasを使用して、燃え尽き症候群と相関する可能性のある特徴量を作成します。
実装
スクリプトに以下の関数を追加します:
# ... (keep the previous code)
def create_features(df):
"""Engineers features from the raw commit data."""
# Select and rename relevant columns
df = df[['sha', 'commit.author.date', 'commit.message']].rename(columns={
'commit.author.date': 'timestamp',
'commit.message': 'message'
})
# Convert timestamp to datetime objects and set as index
df['timestamp'] = pd.to_datetime(df['timestamp'])
df = df.set_index('timestamp')
# Feature 1: Hour of the day
df['hour'] = df.index.hour
# Feature 2: Day of the week (0=Monday, 6=Sunday)
df['day_of_week'] = df.index.dayofweek
# Feature 3: Commit message length
df['message_length'] = df['message'].apply(len)
# Feature 4: Commits per day
commits_per_day = df.resample('D').size().rename('commits_on_day')
df = df.join(commits_per_day, on=df.index.date)
return df
# --- Main execution ---
if __name__ == '__main__':
# ... (fetching code remains the same)
df_raw = pd.json_normalize(all_commits)
if df_raw.empty:
print("No commits found.")
else:
df_features = create_features(df_raw.copy())
print("\
--- Features ---")
print(df_features.head())
動作の仕組み
- タイムスタンプ変換:
timestamp列を適切なdatetime形式に変換し、time-based操作を実行できるようにします。 - 時間ベースの特徴量: datetimeインデックスから直接
hourとday_of_weekを抽出します。これにより、一貫した深夜労働や週末勤務のようなパターンを発見できます。 - メッセージの長さ: 各コミットメッセージの長さを計算します。
- リサンプリング:
resample('D').size()は強力なPandas時系列関数です。コミットを日次(D)でグループ化し、各グループで何個発生したかをカウントし、日次コミット頻度を提供します。次に、この情報をjoinしてメインのDataFrameに戻します。
ステップ3:データへのラベル付け(人的要素)
何をしているのか
これは最も主観的だが最も重要な部分です。「目標変数」−−モデルにどの期間が「燃え尽き」を表し、どの期間が「通常」を表すかを示すラベル−−を作成する必要があります。燃え尽き症候群の外部測定値がないので、過去のプロジェクトの記憶に基づいて独自のラベルを作成する必要があります。
実装
これはあなた独有的なものになります。目標は、記憶しているストレスや燃え尽き症候群に至った期間を1として、通常期間を0として、新しい列is_burnoutを作成することです。
# ... (keep previous code)
def label_data(df):
"""Labels data based on known periods of burnout."""
df['is_burnout'] = 0 # Default to 'normal'
# --- !!! THIS IS THE PART YOU MUST CUSTOMIZE !!! ---
# Example: Labeling a specific date range as a 'burnout' period
burnout_start = '2023-10-01'
burnout_end = '2023-10-31'
df.loc[burnout_start:burnout_end, 'is_burnout'] = 1
# Example: Labeling another stressful period
# burnout_start_2 = '2024-03-15'
# burnout_end_2 = '2024-04-05'
# df.loc[burnout_start_2:burnout_end_2, 'is_burnout'] = 1
return df
# --- Main execution ---
if __name__ == '__main__':
# ...
else:
df_features = create_features(df_raw.copy())
df_labeled = label_data(df_features.copy())
print("\
--- Labeled Data ---")
# Check the distribution of your labels
print(df_labeled['is_burnout'].value_counts())
# Display some of the labeled data
print(df_labeled[df_labeled['is_burnout'] == 1].head())
動作の仕組み
特に消耗した特定のプロジェクトや締め切りを振り返ってください。.locによるdate-rangeスライシングを使用して、これらの期間にis_burnout列に1を割り当てます。正直に!モデルの品質はラベルの品質に完全に依存します。
よくある落とし穴: 0と1の間に合理的なバランスをとるよう心がけてください。燃え尽き症候群としてラベル付けした日が少数しかない場合、モデルは学習に苦労します。
ステップ4:分類モデルの訓練
何をしているのか
ここからは機械学習です!scikit-learnを使用してRandomForestClassifierを訓練します。このモデルは決定木の「アンサンブル」であり、堅牢でありながら複雑なパターンを見つけるのに優れています。
実装
# ... (add imports at the top)
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score, classification_report, confusion_matrix
import seaborn as sns
import matplotlib.pyplot as plt
# ... (add new function)
def train_model(df):
"""Trains a model to predict burnout based on commit features."""
# Define features (X) and target (y)
features = ['hour', 'day_of_week', 'message_length', 'commits_on_day']
X = df[features]
y = df['is_burnout']
# Split data into training and testing sets
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.3, random_state=42, stratify=y
)
# Initialize and train the Random Forest Classifier
model = RandomForestClassifier(n_estimators=100, random_state=42, class_weight='balanced')
model.fit(X_train, y_train)
# Make predictions on the test set
y_pred = model.predict(X_test)
# Evaluate the model
print("\
--- Model Evaluation ---")
print(f"Accuracy: {accuracy_score(y_test, y_pred):.2f}")
print("\
Classification Report:")
print(classification_report(y_test, y_pred))
# Visualize feature importances
feature_imp = pd.Series(model.feature_importances_, index=features).sort_values(ascending=False)
plt.figure(figsize=(10, 6))
sns.barplot(x=feature_imp, y=feature_imp.index)
plt.xlabel('Feature Importance Score')
plt.ylabel('Features')
plt.title("Visualizing Important Features")
plt.show()
return model
# --- Main execution ---
if __name__ == '__main__':
# ...
else:
df_features = create_features(df_raw.copy())
df_labeled = label_data(df_features.copy())
if df_labeled['is_burnout'].sum() > 0:
train_model(df_labeled)
else:
print("\
Skipping model training: No data labeled as 'burnout'.")
動作の仕組み
- データの分割: ラベル付きデータをトレーニングセット(70%)とテストセット(30%)に分割します。モデルはトレーニングセットから学習し、続いてテストセット(実世界の性能を測定)で評価されます。
- 訓練:
model.fit(X_train, y_train)が魔法が起こる場所です。Random Forestアルゴリズムは、トレーニングデータの特徴量を分析して、「通常」と「燃え尽き」のコミットを最もよく区別するパターンを見つけます。class_weight='balanced'は、モデルに少数クラス(通常は「燃え尽き」クラス)に注意を向けるように指示し、不均衡データセットに重要です。 - 評価: 分類レポートを使用して、モデルの性能を確認します。
- 特徴量の重要度: プロットは、モデルが最も予測的だと判断した特徴量を示します。これは非常に洞察に満ちています!
hourとcommits_on_dayがあなたの個人データで最も強い指標であることがわかるかもしれません。
代替アプローチ
- ロジスティック回帰: よりシンプルで解釈しやすいモデル。比較するための良いベースラインになります。
sklearn.linear_modelからLogisticRegressionとRandomForestClassifierを入れ替えられます。 - 時系列異常検知: 分類ではなく異常検知問題として扱うことができ、「通常」の行動をモデル化し、显著な逸脱をフラグ付けします。
- センチメント分析: コミットメッセージのテキストを分析して、時間経過に伴うセンチメントの変化を検出します。コミットメッセージの肯定的なセンチメントは、より健全な職場環境とcorrelation相関があります。
結論
デジタルフットプリントを活用して自己認識と精神的幸福を推進するツールを正常に構築しました。以下のことを学びました:
- Pythonを使用してGitHub APIからデータを取得する方法。
- Pandasを使用した時系列データの特徴量エンジニアリング。
- 教師あり機械学習タスクのためのデータへのラベル付け。
- Scikit-learnでの分類モデルの訓練と評価。
このプロジェクトは起点です。 реальная реальная力は、自分の生活和作業パターンに適応することから生まれます。特徴量の重要度チャートを使用して、自分の個人的なトリガーと習慣を理解してください。忘れないでください。目標は完璧なアラームシステムを作成することではなく、メンタルヘルスに集中帮助你保持警惕ためのデータに基づいた鏡を構築することです。
次のステップ:
- すべてのリポジトリのコミットを分析する。
- このスクリプトを自動的に実行するようにデプロイする(例:週1回)して、サマリーを送る。
- コミット間の時間間隔や変更されたファイル数など、異なる特徴量を試す。
参考資料
- GitHub API Documentation: https://docs.github.com/en/rest/commits/commits
- Pandas Time Series / Date functionality: https://pandas.pydata.org/pandas-docs/stable/user_guide/timeseries.html
- Scikit-learn
RandomForestClassifier: https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.RandomForestClassifier.html
クイックリファレンス
| 側面 | 主要情報 |
|---|---|
| トピック | 開発 |
| 関連性 | 患者教育と認識 |
| アクション | 医療提供者との議論 |
| 頻度 | ケアチームのおすすめに応じて |
| エビデンス | 現在の臨床ガイドラインに基づく |
よくある質問
Q: これが自分に該当するどうかはどうすればわかりますか? A: 医療提供者と一緒に個人的な病歴と家族歴について話し、あなたのリスク因子を評価し、適切な次のステップを決定してください。
Q: 医師に何を尋ねるべきですか? A: 良い質問には次のようなものがあります:「私の結果は何を意味しますか?」「私のオプションは何ですか?」「どのようなライフスタイルの変更が役に立ちますか?」「いつフォローアップすべきですか?」
Q: 帮助するためのライフスタイルの変更はありますか? A: ほとんどの健康状態は、基本的な対策から benefits利益を得ます:バランスの取れた栄養、定期的な運動(週150分以上)、質のよい睡眠(7〜9時間)、ストレス管理、タバコの回避。
医学的免責事項
この記事は教育的目的のみを目的としており、医学的 advice助言を構成しません,健康、治療、またはケアに関する決定を行う前に、常に資格のある医療提供者にご相談ください。個人の状況は異なり、ある人適切なことが別の人にとって適切ではない場合があります。
救急車を要する emergencies急病の場合は、直ちに911(または地元の emergency number緊急番号)に連絡してください。