背景と目的
建物におけるHVAC(暖房・換気・空調)システムのエネルギー消費は全体の大きな割合を占める。居住状況に応じた需要駆動型の制御により、省エネが可能となる。本稿では、複数の非接触型センサーから得られたデータを用いて、室内の滞在人数を推定する手法について検討する。対象データセットは、4日間にわたり収集された温度、照度、音圧、CO₂濃度、動き検出などの時系列情報であり、機械学習モデルによる人数推定が主眼となる。
データ構成
| フィールド | 説明 |
|---|---|
| Date | 日付(DD-MM-YYYY形式) |
| Time | 時刻(HH:MM:SS形式) |
| Temperature | 気温(°C) |
| Light | 照度(Lux) |
| Sound | 音圧(V、ADC測定値) |
| CO2 | 二酸化炭素濃度(ppm) |
| CO2_Slope | スライドウィンドウ内のCO₂変化率(勾配) |
| PIR | 赤外線センサーによる動き検出(0/1) |
| Room_Occupancy_Count | 実測滞在人数(ターゲット変数) |
| S1–S7 | 異なる位置に設置されたセンサーノード |
前処理と特徴統合
まず、日付と時刻を結合してDatetime列を作成し、タイムスタンプとして扱う。
import pandas as pd
df = pd.read_csv('room_occupancy.csv')
df['Datetime'] = pd.to_datetime(df['Date'] + ' ' + df['Time'], format='%d-%m-%Y %H:%M:%S')
df.drop(['Date', 'Time'], axis=1, inplace=True)
同種のセンサー(S1–S4)から得られる温度、照度、音圧については、ノイズ低減と冗長性除去のため、平均値を新たな特徴量として抽出。
df['Avg_Temp'] = df[['S1_Temp', 'S2_Temp', 'S3_Temp', 'S4_Temp']].mean(axis=1)
df['Avg_Light'] = df[['S1_Light', 'S2_Light', 'S3_Light', 'S4_Light']].mean(axis=1)
df['Avg_Sound'] = df[['S1_Sound', 'S2_Sound', 'S3_Sound', 'S4_Sound']].mean(axis=1)
さらに、時間情報を分解して季節性や時間帯の影響を考慮可能にする。
df['Hour'] = df['Datetime'].dt.hour
df['Minute'] = df['Datetime'].dt.minute
相関分析と可視化
スピアマン順位相関係数を用いて、各特徴量間の関係を評価。特に、Avg_LightとRoom_Occupancy_Countには強い正の相関が見られ、人がいるときに照明が点灯される傾向があることを示唆している。また、S5_CO2とCO2_Slopeも高い相関を持ち、CO₂濃度の変化速度が滞在人数の変動と関連している可能性を示す。
分類モデルの構築
滞在人数を多値分類問題として捉え、ランダムフォレスト分類器を適用。
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
features = ['Avg_Temp', 'Avg_Light', 'Avg_Sound', 'S5_CO2', 'CO2_Slope', 'S7_PIR']
X = df[features]
y = df['Room_Occupancy_Count']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
rf_model = RandomForestClassifier(n_estimators=100, random_state=42)
rf_model.fit(X_train, y_train)
preds = rf_model.predict(X_test)
print(f"テスト精度: {accuracy_score(y_test, preds):.4f}")
結果として、約98%以上の精度が得られ、交差検証でも安定した性能を確認。過学習の兆候は見られない。
特徴量の重要度評価
訓練済みモデルから特徴量の重要度を抽出し、棒グラフで可視化。
import matplotlib.pyplot as plt
import seaborn as sns
importance_df = pd.DataFrame({
'Feature': features,
'Importance': rf_model.feature_importances_
}).sort_values('Importance', ascending=False)
plt.figure(figsize=(10, 6))
sns.barplot(data=importance_df, x='Importance', y='Feature', palette='Blues_d')
plt.title('Random Forestによる特徴量の重要度')
plt.xlabel('重要度')
plt.ylabel('特徴量')
plt.show()
- Avg_Light: 最も寄与が大きく、約42%の重要度。人がいると照明が点くという行動パターンが強く反映されている。
- CO2_Slope: 第二位。CO₂濃度の急激な変化が人数増加と相関。
- Avg_Sound: 音の大きさも活動の指標として有効。
- S7_PIR: 動き検出は他の特徴に比べて重要度が低い。単なる動きの有無では人数推定に限界があるため。
時系列的傾向の把握
特定の日(例:2017-12-25)のデータを抽出し、24時間の変動をプロット。
day_data = df[df['Datetime'].dt.date == pd.to_datetime('2017-12-25').date()]
fig, axes = plt.subplots(5, 1, figsize=(14, 10), sharex=True)
day_data.set_index('Datetime')[['Avg_Temp']].plot(ax=axes[0], title='温度')
day_data.set_index('Datetime')[['Avg_Light']].plot(ax=axes[1], title='照度')
day_data.set_index('Datetime')[['Avg_Sound']].plot(ax=axes[2], title='音圧')
day_data.set_index('Datetime')[['S5_CO2']].plot(ax=axes[3], title='CO2濃度')
day_data.set_index('Datetime')[['CO2_Slope']].plot(ax=axes[4], title='CO2変化率')
plt.tight_layout()
plt.show()
昼間の活動時間帯(10:00–18:00)に照度、音圧、CO₂濃度が上昇しており、人的活動との整合性が確認できる。
考察と今後の課題
本分析では、異種センサーの融合により高精度な人数推定が可能であることが示された。特に、照度とCO₂の変化率が強力な予測因子となった。ただし、以下の点に注意が必要:
- 実験環境は小規模な部屋に限定されており、大空間への一般化にはさらなる検証が必要。
- 照明の操作が手動に依存する場合、ユーザー行動の違いによりバイアスが生じる可能性がある。
- 時系列の自己相関を考慮したモデル(LSTMなど)の導入により、さらに精度向上が期待できる。
非侵入かつプライバシーに配慮した監視手法として、スマートビルディングへの応用が見込まれる。