关于房间传感器监测数据集的探索
- 开源代码
- 2025-08-25 18:45:02

1,背景描述
在建筑物中,供暖、通风和空调系统的能源消耗占据了很大比例。根据居住情况以需求为导向优化这些系统的使用,是一种提升能效的方法。 本数据集包含了某一房间 4 天内多个异构传感器测量的数据信息,如二氧化碳、温度、照明、声音和运动数据信息。基于这些数据,可以利用机器学习模型来预测估计房间内的居住者人数。
2,数据说明 字段说明Date日期,格式为日-月-年(DD-MM-YYYY)Time时间,格式为小时:分钟:秒(HH:MM:SS)Temperature温度,单位为摄氏度(°C)Light光照强度,单位为勒克斯(Lux)Sound声音电压,从放大器输出读取并由ADC(模数转换器)测量,单位为伏特(V)CO2二氧化碳浓度,单位为ppm(每百万份)CO2 Slope在滑动窗口中获取的CO2值的斜率PIR被动红外传感器的二进制值,表示是否检测到运动Room_Occupancy_Count房间占用计数(目标值),真实情况下的房间占用人数(Target)S1-S7 代表不同的传感器序号 3,数据来源.semanticscholar.org/paper/Machine-Learning-Based-Occupancy-Estimation-Using-Singh-Jain/e631ea26f0fd88541f42b4e049d63d6b52d6d3ac .kaggle /datasets/ruchikakumbhar/room-occupancy-estimation
4,问题描述二分类分析 回归分析 时间序列分析 特征重要性分析
5,数据读取与预处理 import pandas as pd file_path = '/home/mw/input/02072495/room occupancy.csv' data = pd.read_csv(file_path) data.head() data.shape data.info() data.isnull().sum() # 查看重复值 data.duplicated().sum() # 描述性统计 data.describe() # 合并日期和时间为单一的时间戳列 data['Datetime'] = pd.to_datetime(data['Date'] + ' ' + data['Time'], format='%d-%m-%Y %H:%M:%S') data.drop(['Date', 'Time'], axis=1, inplace=True) from scipy.stats import spearmanr import numpy as np import matplotlib.pyplot as plt import seaborn as sns def plot_spearmanr(data, features, title, wide, height): # 计算Spearman相关矩阵和p值矩阵 spearman_corr_matrix = data[features].corr(method='spearman') pvals = data[features].corr(method=lambda x, y: spearmanr(x, y)[1]) - np.eye(len(data[features].columns)) # 将p值转换为星号 def convert_pvalue_to_asterisks(pvalue): if pvalue <= 0.001: return "***" elif pvalue <= 0.01: return "**" elif pvalue <= 0.05: return "*" return "" # 应用转换函数 pval_star = pvals.applymap(convert_pvalue_to_asterisks) # 转换为numpy类型 corr_star_annot = pval_star.to_numpy() # 定制 labels corr_labels = spearman_corr_matrix.to_numpy() p_labels = corr_star_annot shape = corr_labels.shape # 合并 labels labels = (np.asarray(["{0:.2f}\n{1}".format(data, p) for data, p in zip(corr_labels.flatten(), p_labels.flatten())])).reshape(shape) # 绘制热力图 fig, ax = plt.subplots(figsize=(height, wide), dpi=100, facecolor="w") sns.heatmap(spearman_corr_matrix, annot=labels, fmt='', cmap='coolwarm', vmin=-1, vmax=1, annot_kws={"size":10, "fontweight":"bold"}, linecolor="k", linewidths=.2, cbar_kws={"aspect":13}, ax=ax) ax.tick_params(bottom=False, labelbottom=True, labeltop=False, left=False, pad=1, labelsize=12) ax.yaxis.set_tick_params(labelrotation=0) # 自定义 colorbar 标签格式 cbar = ax.collections[0].colorbar cbar.ax.tick_params(direction="in", width=.5, labelsize=10) cbar.set_ticks([-1, -0.5, 0, 0.5, 1]) cbar.set_ticklabels(["-1.00", "-0.50", "0.00", "0.50", "1.00"]) cbar.outline.set_visible(True) cbar.outline.set_linewidth(.5) plt.title(title) plt.show() #删除不是float的类型 features = data.drop(['Datetime'],axis=1).columns.tolist() plot_spearmanr(data, features, 'Spearman correlation coefficient heat map between variables', 10, 13)温度 (Temp) 相关性:
S1_Temp, S2_Temp, S3_Temp, S4_Temp 四个传感器的温度数据之间的相关性非常高(大部分在0.80以上),这表明这些特征之间有冗余。因此,可以考虑将它们合成一个新的特征,例如它们的均值或最大值,以减少冗余并保留有用的信息。 特别是S1_Temp和S2_Temp与目标变量(Room_Occupancy_Count)有比较强的正相关(接近0.6),所以温度可以作为一个重要特征保留。 光照强度 (Light):
光照数据(S1_Light, S2_Light, S3_Light, S4_Light)与目标变量的相关性较强(约0.7-0.8),而这些传感器的光照数据之间的相关性也很高。因此,类似温度,我们可以将它们合成一个特征,如光照的平均值或最大值。 声音电压 (Sound):
S1_Sound, S2_Sound, S3_Sound, S4_Sound 的相关性比较弱(大多数都小于0.5),它们与目标变量的相关性也较弱。你可以考虑将声音电压的均值作为一个新特征,但这可能不是最重要的特征,取决于你对声音与占用人数之间的关系是否重视。 二氧化碳浓度 (CO2) 和二氧化碳斜率 (CO2_Slope):
S5_CO2与目标变量的相关性较强(约0.65),且它和S5_C02_Slope的相关性也比较强。这两个特征很可能提供了关于房间占用人数的重要信息,建议保持这两个特征,或将S5_CO2和S5_CO2_Slope的加权平均作为一个新特征。 运动 (PIR):
S6_PIR 和 S7_PIR 的相关性较强(接近0.6),且这两个特征与目标变量有较强的正相关性(接近0.6)。运动检测器与房间占用人数的相关性表明,运动数据应该是非常重要的特征。
# 计算不同传感器的温度均值 data['Temp_Avg'] = data[['S1_Temp', 'S2_Temp', 'S3_Temp', 'S4_Temp']].mean(axis=1) # 计算不同传感器的光照强度均值 data['Light_Avg'] = data[['S1_Light', 'S2_Light', 'S3_Light', 'S4_Light']].mean(axis=1) # 计算不同传感器的声音电压均值 data['Sound_Avg'] = data[['S1_Sound', 'S2_Sound', 'S3_Sound', 'S4_Sound']].mean(axis=1) from sklearn.model_selection import train_test_split from sklearn.linear_model import LogisticRegression from sklearn.metrics import accuracy_score, confusion_matrix # 分别训练两个模型,选择效果更好的那个 X = data[['Temp_Avg', 'Light_Avg', 'Sound_Avg', 'S5_CO2', 'S5_CO2_Slope']] # 用第一个传感器的数据 y1 = data['S6_PIR'] X_train, X_test, y_train, y_test = train_test_split(X, y1, test_size=0.2, random_state=42) model1 = LogisticRegression() model1.fit(X_train, y_train) y_pred1 = model1.predict(X_test) print(f"Accuracy for Sensor 1: {accuracy_score(y_test, y_pred1)}") # 用第二个传感器的数据 y2 = data['S7_PIR'] X_train, X_test, y_train, y_test = train_test_split(X, y2, test_size=0.2, random_state=42) model2 = LogisticRegression() model2.fit(X_train, y_train) y_pred2 = model2.predict(X_test) print(f"Accuracy for Sensor 2: {accuracy_score(y_test, y_pred2)}") data.drop(['S1_Light', 'S2_Light','S3_Light','S4_Light','S1_Temp','S2_Temp','S3_Temp','S4_Temp','S1_Sound','S2_Sound','S3_Sound','S4_Sound','S6_PIR'], axis=1, inplace=True) data.head()直接选择均值作为特征后续分析的理论基础,这样子可以去除冗余信息,保留关键信息,简化一下特征空间。
# 将时间特征提取为独立列 data['Year'] = data['Datetime'].dt.year data['Month'] = data['Datetime'].dt.month data['Day'] = data['Datetime'].dt.day data['Hour'] = data['Datetime'].dt.hour data['Minute'] = data['Datetime'].dt.minute import matplotlib.pyplot as plt import seaborn as sns # 设置绘图风格 sns.set(style="whitegrid") # 创建一个大图来显示不同特征与房间占用人数的关系 plt.figure(figsize=(14, 10)) # 温度与房间占用人数的关系 plt.subplot(3, 2, 1) sns.boxplot(x='Room_Occupancy_Count', y='Temp_Avg', data=data, palette="coolwarm", linewidth=2.5, fliersize=8, notch=True) plt.title('Room Occupancy Count vs Temperature', fontsize=16, weight='bold') plt.xlabel('Room Occupancy Count', fontsize=14) plt.ylabel('Temperature (°C)', fontsize=14) plt.grid(True, linestyle='--', alpha=0.5) # 光照与房间占用人数的关系 plt.subplot(3, 2, 2) sns.boxplot(x='Room_Occupancy_Count', y='Light_Avg', data=data, palette="viridis", linewidth=2.5, fliersize=8, notch=True) plt.title('Room Occupancy Count vs Light', fontsize=16, weight='bold') plt.xlabel('Room Occupancy Count', fontsize=14) plt.ylabel('Light (Lux)', fontsize=14) plt.grid(True, linestyle='--', alpha=0.5) # CO2浓度与房间占用人数的关系 plt.subplot(3, 2, 3) sns.boxplot(x='Room_Occupancy_Count', y='S5_CO2', data=data, palette="magma", linewidth=2.5, fliersize=8, notch=True) plt.title('Room Occupancy Count vs CO2', fontsize=16, weight='bold') plt.xlabel('Room Occupancy Count', fontsize=14) plt.ylabel('CO2 Concentration (ppm)', fontsize=14) plt.grid(True, linestyle='--', alpha=0.5) # 声音电压与房间占用人数的关系 plt.subplot(3, 2, 4) sns.boxplot(x='Room_Occupancy_Count', y='Sound_Avg', data=data, palette="cubehelix", linewidth=2.5, fliersize=8, notch=True) plt.title('Room Occupancy Count vs Sound', fontsize=16, weight='bold') plt.xlabel('Room Occupancy Count', fontsize=14) plt.ylabel('Sound (dB)', fontsize=14) plt.grid(True, linestyle='--', alpha=0.5) # CO2 Slope与房间占用人数的关系 plt.subplot2grid((3, 2), (2, 0), colspan=2) sns.boxplot(x='Room_Occupancy_Count', y='S5_CO2_Slope', data=data, palette="cividis", linewidth=2.5, fliersize=8, notch=True) plt.title('Room Occupancy Count vs CO2 Slope', fontsize=16, weight='bold') plt.xlabel('Room Occupancy Count', fontsize=14) plt.ylabel('CO2 Slope', fontsize=14) plt.grid(True, linestyle='--', alpha=0.5) # 调整布局,避免标签重叠 plt.tight_layout() # 添加透明背景颜色以增强现代感 plt.gcf().patch.set_facecolor('whitesmoke') # 展示图形 plt.show() 温度(Temperature)与房间占用人数(Room Occupancy Count)的关系 分布差异:图中显示不同房间占用人数(0-3人)与温度的分布情况。我们可以看到随着房间占用人数增加,温度的分布范围变化较大。这表明房间温度可能与占用人数之间存在一定的关系,可能是因为房间内有更多人时,温度会有较高的波动。 异常值:房间占用人数为0时,温度存在一些较低的异常值,可能是由于无人的房间在早晨或晚间出现低温。光照(Light)与房间占用人数的关系 明显的波动:随着房间占用人数的增加,光照强度的变化非常显著。特别是房间占用人数为3时,光照强度的分布幅度很大,这可能反映了房间内活动多、光照变化大。 异常值:在房间占用人数较低时,光照强度值相对较小,这可能代表着房间的光源较弱,或是较长时间的低光环境。二氧化碳浓度(CO2)与房间占用人数的关系 CO2浓度与人数关系:可以看到,当房间内有更多人时,CO2浓度显著增加,这符合实际情况——人类活动产生二氧化碳,人数越多,CO2浓度越高。 分布差异:在房间占用人数为0时,CO2浓度较低,而随着人数的增加,CO2浓度呈现显著的上升趋势。声音电压(Sound)与房间占用人数的关系 较高的人数会导致较大的波动:当房间占用人数为3时,声音电压的分布范围相对较大,可能是因为人数多的房间噪音更高。 异常值:较低占用人数时,声音电压相对较小且存在少量的异常值,可能说明空房间或少人时,噪音较低。CO2斜率(CO2 Slope)与房间占用人数的关系 与占用人数的正相关:CO2斜率与占用人数呈现出一定的正相关关系。较高的斜率值可能意味着房间内有更多人的时候,CO2浓度变化较为剧烈。 对后续分析的启示: 特征关系:温度、光照、CO2浓度和声音电压等特征与房间占用人数之间存在明显的关系,这些特征可以作为有用的预测因子。 特征选择:通过这些图形可以初步判断哪些特征具有较大区分度,可能有助于进行特征选择。例如,CO2浓度和温度可能对房间占用人数的预测有较强的影响。 异常值分析:图中的异常值可能代表特殊情况,比如空房间或临时高光照和高噪音环境。这些异常值可能需要在建模时处理,确保它们不会影响模型的准确性。 6,二分类分析 # 为房间占用创建一个二进制列 data['Occupancy'] = data['Room_Occupancy_Count'].apply(lambda x: 'someone' if x > 0 else 'unmanned') # 绘制房间占用率的分布图 plt.figure(figsize=(10, 6)) sns.countplot(data['Occupancy'], palette="viridis") plt.title('Room occupancy distribution') plt.xlabel('occupancy') plt.ylabel('quantity') plt.show()从上面的条形图中可以看出,房间内“无人”的时间段比“有人”的时间段要多。
from sklearn.model_selection import train_test_split from sklearn.linear_model import LogisticRegression from sklearn.metrics import accuracy_score, confusion_matrix # 将数据分为训练集和测试集 X = data[['Temp_Avg', 'Light_Avg', 'Sound_Avg', 'S5_CO2', 'S5_CO2_Slope']] # 特征列 y = data['S7_PIR'] # 目标变量:是否检测到运动(0或1) X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) # 建立Logistic Regression模型 model = LogisticRegression() model.fit(X_train, y_train) # 预测并评估模型 y_pred = model.predict(X_test) print(f"Accuracy: {accuracy_score(y_test, y_pred)}") print(f"Confusion Matrix:\n{confusion_matrix(y_test, y_pred)}")精度为92.65%,意味着大多数情况下模型能够正确判断是否有运动,从而帮助优化空调和供暖系统的运行,减少不必要的能源浪费。
from sklearn.metrics import roc_curve, auc # 计算ROC曲线的FPR和TPR fpr, tpr, thresholds = roc_curve(y_test, model.predict_proba(X_test)[:, 1]) # 计算AUC roc_auc = auc(fpr, tpr) # 绘制ROC曲线 plt.figure(figsize=(10, 8)) # 增加图像尺寸以便更好地展示 plt.plot(fpr, tpr, color='darkorange', lw=2, label=f'ROC Curve (AUC = {roc_auc:.2f})') plt.plot([0, 1], [0, 1], color='gray', linestyle='--', lw=2) # 随机分类器线,使用更粗的线条 # 设置标题和标签,调整字体大小 plt.title('Receiver Operating Characteristic (ROC) Curve', fontsize=18, weight='bold') plt.xlabel('False Positive Rate', fontsize=14) plt.ylabel('True Positive Rate', fontsize=14) # 设置图例,调整位置和字体 plt.legend(loc='lower right', fontsize=12, frameon=False) # 添加网格线 plt.grid(True, linestyle='--', alpha=0.7, linewidth=0.7) # 展示图像 plt.tight_layout() # 确保所有标签都能正常显示 plt.show() 7,时间序列分析 import matplotlib.pyplot as plt import seaborn as sns # 设置更花哨的样式 sns.set(style="whitegrid", palette="muted") # 创建一个大画布,包含多个子图 plt.figure(figsize=(14, 10)) # 温度变化趋势 plt.subplot(3, 2, 1) sns.lineplot(x='Datetime', y='Temp_Avg', data=data, linewidth=2, color='blue') plt.title('Temperature Over Time') plt.xlabel('Time') plt.ylabel('Temperature (°C)') # 光照强度变化趋势 plt.subplot(3, 2, 2) sns.lineplot(x='Datetime', y='Light_Avg', data=data, linewidth=2, color='orange') plt.title('Light Intensity Over Time') plt.xlabel('Time') plt.ylabel('Light (Lux)') # 声音电压变化趋势 plt.subplot(3, 2, 3) sns.lineplot(x='Datetime', y='Sound_Avg', data=data, linewidth=2, color='green') plt.title('Sound Voltage Over Time') plt.xlabel('Time') plt.ylabel('Sound (V)') # CO2浓度变化趋势 plt.subplot(3, 2, 4) sns.lineplot(x='Datetime', y='S5_CO2', data=data, linewidth=2, color='red') plt.title('CO2 Concentration Over Time') plt.xlabel('Time') plt.ylabel('CO2 (ppm)') # 使用subplot2grid来让最后一个图横跨两列 plt.subplot2grid((3, 2), (2, 0), colspan=2) # 在第3行占用两列 sns.lineplot(x='Datetime', y='S5_CO2_Slope', data=data, linewidth=2, color='purple') plt.title('CO2 Slope Over Time') plt.xlabel('Time') plt.ylabel('CO2 Slope') # 调整布局,避免重叠 plt.tight_layout() plt.show()温度(Temperature):图中显示了温度在某些时段内的剧烈波动,尤其是在2017年12月25日到2018年1月初,之后温度趋于平稳。这个波动可能表示设备故障或者传感器数据采集错误,值得进一步检查。
光照(Light Intensity):光照强度同样出现了显著的波动,且在某些时段光照值急剧增加,可能是房间内发生了大规模的活动,或者设备传感器报告了不正常的光照值。
声音(Sound Voltage):声音电压的波动较为剧烈,尤其在2017年12月25日到1月初期间,声音电压急剧上升。这可能表示房间内的噪音水平发生了剧烈变化,或者存在设备故障。
二氧化碳浓度(CO2):CO2浓度也显示出了剧烈的波动,尤其是在某些时段内(如12月25日),CO2浓度大幅上升。这可能是由于房间内有较多人活动导致的,或者传感器数据异常。
CO2斜率(CO2 Slope):CO2斜率图表呈现了不规则的波动,显示在某些时刻的变化速率较大。这与CO2浓度的剧烈波动相对应,可能是由于房间内人数变化或通风系统的波动。
可视化发现大量缺失值 由于在整个时间段的占比较大,用各类填充缺失值的算法显然是不切实际的,接下来我们截取一天看看各个指标数据
# 过滤2017年12月25日的数据 specific_day = data[data['Datetime'].dt.date == pd.to_datetime('2017-12-25').date()] specific_day.set_index('Datetime', inplace=True) # 提取五个特征 temperature = specific_day['Temp_Avg'] light = specific_day['Light_Avg'] sound = specific_day['Sound_Avg'] co2 = specific_day['S5_CO2'] co2_slope = specific_day['S5_CO2_Slope'] # 设置花哨的样式 sns.set(style="whitegrid", palette="muted") # 创建画布,大小为16x12,调整子图布局 plt.figure(figsize=(16, 12)) # 绘制温度随时间的变化,设置不同的颜色 plt.subplot(3, 2, 1) sns.lineplot(x=specific_day.index, y=temperature, color='royalblue', linewidth=3, linestyle='-', alpha=0.8) plt.title('Temperature Over 24 Hours', fontsize=18, weight='bold', color='darkblue') plt.xlabel('Time', fontsize=14, weight='bold', color='darkgreen') plt.ylabel('Temperature (°C)', fontsize=14, weight='bold', color='darkgreen') plt.xticks(rotation=45, fontsize=12, color='darkred') plt.yticks(fontsize=12, color='darkred') plt.grid(True, linestyle='--', alpha=0.5) # 绘制光照强度随时间的变化,使用不同颜色 plt.subplot(3, 2, 2) sns.lineplot(x=specific_day.index, y=light, linewidth=3, color='orange', alpha=0.8) plt.title('Light Intensity Over 24 Hours', fontsize=18, weight='bold', color='orange') plt.xlabel('Time', fontsize=14, weight='bold', color='darkgreen') plt.ylabel('Light (Lux)', fontsize=14, weight='bold', color='darkgreen') plt.xticks(rotation=45, fontsize=12, color='darkred') plt.yticks(fontsize=12, color='darkred') plt.grid(True, linestyle='--', alpha=0.5) # 绘制声音电压随时间的变化,使用不同颜色 plt.subplot(3, 2, 3) sns.lineplot(x=specific_day.index, y=sound, linewidth=3, color='green', alpha=0.8) plt.title('Sound Voltage Over 24 Hours', fontsize=18, weight='bold', color='green') plt.xlabel('Time', fontsize=14, weight='bold', color='darkgreen') plt.ylabel('Sound (V)', fontsize=14, weight='bold', color='darkgreen') plt.xticks(rotation=45, fontsize=12, color='darkred') plt.yticks(fontsize=12, color='darkred') plt.grid(True, linestyle='--', alpha=0.5) # 绘制CO2浓度随时间的变化,使用不同颜色 plt.subplot(3, 2, 4) sns.lineplot(x=specific_day.index, y=co2, linewidth=3, color='red', alpha=0.8) plt.title('CO2 Concentration Over 24 Hours', fontsize=18, weight='bold', color='red') plt.xlabel('Time', fontsize=14, weight='bold', color='darkgreen') plt.ylabel('CO2 (ppm)', fontsize=14, weight='bold', color='darkgreen') plt.xticks(rotation=45, fontsize=12, color='darkred') plt.yticks(fontsize=12, color='darkred') plt.grid(True, linestyle='--', alpha=0.5) # 绘制CO2斜率随时间的变化,使用不同颜色 plt.subplot(3, 2, (5, 6)) # 合并(3,2,5) + (3,2,6) sns.lineplot(x=specific_day.index, y=co2_slope, linewidth=3, color='purple', alpha=0.8) plt.title('CO2 Slope Over 24 Hours', fontsize=18, weight='bold', color='purple') plt.xlabel('Time', fontsize=14, weight='bold', color='darkgreen') plt.ylabel('CO2 Slope', fontsize=14, weight='bold', color='darkgreen') plt.xticks(rotation=45, fontsize=12, color='darkred') plt.yticks(fontsize=12, color='darkred') plt.grid(True, linestyle='--', alpha=0.5) # 调整布局,避免重叠 plt.tight_layout() # 显示图表 plt.show()温度(Temperature) 波动性:温度在12月25日的24小时内有显著的变化。温度在白天时间(大约12:00到15:00之间)上升,并在夜间(大约18:00之后)逐渐下降。 这种波动可能是由于环境因素(如外部温度变化)或房间内的活动导致的(例如暖气、空调的使用)。 信息:温度的变化有规律,且与其他特征(如光照)可能有较强的相关性。光照强度(Light Intensity) 强烈波动:光照强度在12月25日的24小时内呈现明显的波动,尤其是在白天(大约12:00到15:00),光照强度达到峰值。 随着太阳的升起和落下,光照强度发生了显著的变化。夜间,光照强度几乎降到0。 信息:光照强度与温度变化有直接关系,尤其是在室内可能与窗户的自然光照或人工照明系统相关。声音电压(Sound Voltage) 噪音波动:声音电压在24小时内波动非常剧烈,特别是某些时段(如12:25、16:25、18:25等)有较大的峰值。 这些波动可能与房间内的人流量、设备操作或其他活动相关。声音的快速变化可能是由于物体的运动、环境噪声等因素。 信息:声音变化的剧烈波动可能暗示房间内有较多的活动,或者传感器有时会出现过度灵敏的现象。CO2浓度(CO2 Concentration) CO2浓度的稳定性:CO2浓度几乎保持稳定,除了一些短暂的突发波动(特别是在12月25日的某些时段,如12:16和12:19等)。这些波动可能与房间内人员活动的增加相关(如人数增多或空气流通问题)。 信息:CO2浓度较为平稳,但在某些时刻可能反映了房间内的活动变化。CO2斜率(CO2 Slope) 斜率变化:CO2斜率的变化非常剧烈,尤其是在12:00到12:05和12:18到12:20之间的急剧波动。这可能反映了CO2浓度变化的速度,进而反映了房间内人员活动的变化。 信息:CO2斜率的剧烈变化可能与房间内的人员流动、活动以及设备的开启关闭等因素密切相关。 总结: 规律性与异常波动:温度、光照和CO2浓度在白天和夜晚呈现出较为规律的变化,但声音和CO2斜率则有更多的短期波动,提示房间内可能有很多间歇性的活动。 活动与环境关系:声音、CO2浓度和CO2斜率的波动表明房间内可能有较多的活动,特别是在人流和活动频繁的时段(如白天)。光照和温度则可能受到外部环境或空调/取暖设备的影响。 8,随机森林–房屋占用分析 from sklearn.ensemble import RandomForestClassifier from sklearn.metrics import accuracy_score # 使用房间占用人数(作为类别)进行分类预测 X = data[['Temp_Avg', 'Light_Avg', 'Sound_Avg', 'S5_CO2', 'S5_CO2_Slope','S7_PIR']] # 特征列 y = data['Room_Occupancy_Count'] # 目标:房间占用人数(分类) # 将数据分为训练集和测试集 from sklearn.model_selection import train_test_split X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) # 随机森林分类模型 rf_classifier = RandomForestClassifier(n_estimators=100, random_state=42) rf_classifier.fit(X_train, y_train) # 预测并评估 y_pred = rf_classifier.predict(X_test) print(f"Accuracy: {accuracy_score(y_test, y_pred)}") # 计算训练集准确率 train_accuracy = accuracy_score(y_train, rf_classifier.predict(X_train)) test_accuracy = accuracy_score(y_test, y_pred) print(f"Training Accuracy: {train_accuracy}") print(f"Test Accuracy: {test_accuracy}") from sklearn.model_selection import cross_val_score # 使用交叉验证评估模型 cv_scores = cross_val_score(rf_classifier, X, y, cv=5) # 5折交叉验证 print(f"Cross-validation scores: {cv_scores}") print(f"Mean cross-validation score: {cv_scores.mean()}")
观察发现随机森林模型准确率0.99,我们通过观察训练集、测试集又进行了交叉检验都发现模型准确率在0.96以上,说明没有过拟合。
import matplotlib.pyplot as plt import seaborn as sns import pandas as pd from sklearn.ensemble import RandomForestClassifier # 选择特征和目标变量 X = data[['Temp_Avg', 'Light_Avg', 'Sound_Avg', 'S5_CO2', 'S5_CO2_Slope','S7_PIR']] y = data['Room_Occupancy_Count'] # 使用随机森林进行训练 rf_classifier = RandomForestClassifier(n_estimators=100, random_state=42) rf_classifier.fit(X, y) # 获取特征重要性 feature_importances = rf_classifier.feature_importances_ # 将特征和重要性组合成数据框 feature_importance_df = pd.DataFrame({ 'Feature': X.columns, 'Importance': feature_importances }) # 按重要性排序 feature_importance_df = feature_importance_df.sort_values(by='Importance', ascending=False) # 绘制特征重要性图 plt.figure(figsize=(12, 8)) sns.set(style="whitegrid") # 使用 barplot 绘制特征重要性 ax = sns.barplot(x='Importance', y='Feature', data=feature_importance_df, palette='coolwarm', ci=None, linewidth=2.5) # 为条形添加阴影 for p in ax.patches: p.set_edgecolor('gray') p.set_linewidth(1.5) p.set_alpha(0.9) # Slight transparency for the bars # 在条形图上显示每个特征的重要性所占的比例 total_importance = feature_importance_df['Importance'].sum() for p in ax.patches: width = p.get_width() # 获取条形的宽度,即特征的重要性 percentage = (width / total_importance) * 100 # 计算所占比例 ax.text(width + 0.005, p.get_y() + p.get_height() / 2, f'{percentage:.2f}%', ha='left', va='center', fontsize=12, color='black', fontweight='bold') # 添加标题和标签 plt.title('Feature Importance (Random Forest)', fontsize=18, fontweight='bold', color='darkblue') plt.xlabel('Importance', fontsize=14, fontweight='bold', color='darkgreen') plt.ylabel('Feature', fontsize=14, fontweight='bold', color='darkgreen') # 调整轴标签大小 plt.xticks(fontsize=12, color='darkred') plt.yticks(fontsize=12, color='darkred') # 显示网格 plt.grid(True, linestyle='--', alpha=0.7) # 调整布局 plt.tight_layout() # 展示图形 plt.show() 光照(Light_Avg)是最重要的特征 从图中可以看到,光照(Light_Avg)的特征重要性最高,达到 42.69%。这意味着光照强度是房间占用人数预测中最关键的特征之一。 这表明光照强度与房间内活动密切相关,可能是因为光照变化与房间内是否有人有直接关系。比如,房间有人时光照可能会发生较大变化,而空房间的光照相对较为稳定。CO2斜率(S5_CO2_Slope)也有较高的重要性 CO2斜率(S5_CO2_Slope)的特征重要性为 18.76%,排名第二。 CO2浓度的变化(即斜率)可能与房间占用人数之间有较强的关系。由于人员活动会产生二氧化碳,随着房间内人员数量的增加,CO2的变化速度可能更为显著,因此 CO2 斜率成为了一个重要特征。声音(Sound_Avg)也有一定影响 声音电压(Sound_Avg)的特征重要性为 16.34%,排名第三。 声音强度与房间占用人数相关性较强,特别是当房间内人数增加时,噪声通常会增大。因此,声音作为一个特征,能够在一定程度上反映房间是否有人。温度(Temp_Avg)的重要性较低 温度(Temp_Avg)的特征重要性为 12.18%,在所有特征中排名第四。 尽管温度变化可能反映房间内的活动,但由于温度受多种因素影响(如外部气候条件、空调设置等),它可能没有像光照或CO2那样强烈地与房间占用人数相关。因此,它的特征重要性较低。PIR检测运动的特征重要性最低 PIR传感器(S7_PIR)的特征重要性为 2.63%,是所有特征中最低的。 PIR传感器只是简单地检测到运动,它并不能提供房间内人数的准确数字。虽然PIR在一定程度上可以反映房间内是否有活动,但它并不是一个强有力的指示器,尤其是在其他特征(如光照、CO2、声音等)能更好地反映房间占用情况的情况下。 由于PIR无法直接告诉我们房间内有多少人,它的贡献在模型中的比重较小。 9,总结上述的分析可能会有不好或者不精准的地方,希望各位读者朋友们帮忙指出。
在我阅读完数据来源中的论文时发现,上述的分析方法和逻辑跟原始研究背景和问题敲定有很大偏差,(这里我只能苦笑了),以下是原数据论文阅读理解
9.1 问题定义与研究背景 核心问题:通过非侵入式传感器数据准确估计房间内人数,优化HVAC系统能源效率。研究动机:传统方法依赖侵入式设备(如摄像头、WiFi)存在隐私问题,且现有研究多集中于占用检测(是否有人),而非具体人数估计。 9.2 实验设计与数据采集 传感器部署: 采用星型网络配置,部署7个异构传感器节点(S1-S7),包含CO₂、温度、光照、声音、PIR(被动红外)传感器。节点分工: S1-S4(桌面节点):温度、光照、声音。S5(中央节点):CO₂。S6-S7(天花板节点):PIR,用于运动检测。 数据采集: 采样周期为30秒,持续4天,覆盖不同占用场景。人工记录人员进出时间作为真实标签(0-3人)。 9.3 数据预处理与特征工程 特征提取: CO₂斜率:通过滑动窗口(25个时间点)的线性回归计算CO₂浓度变化率,捕捉人数动态变化的影响。窗口选择依据:通过试错法优化分类准确率确定窗口大小。 9.4 模型选择与训练 机器学习模型: 监督学习: LDA/QDA:基于多元高斯分布的线性/二次分类器,假设不同类别的协方差矩阵相同(LDA)或不同(QDA)。SVM:支持向量机(线性核与RBF核),通过超平面划分多类数据(采用“一对多”策略)。随机森林(RF):集成决策树,通过投票机制提升鲁棒性。 无监督学习: PCA:主成分分析,用于降维后评估模型性能。 评估指标: 准确率、F1分数(宏平均,解决类别不平衡问题)、混淆矩阵。10折交叉验证(非打乱数据,因时间序列特性)。 9.5 实验分析与结果 同质传感器融合: 单一传感器类型(如仅CO₂或光照)表现有限,光照传感器因人工操作依赖性高(如开关灯)易产生误判。 异质传感器融合: 逐步融合多传感器数据(温度+CO₂斜率→加入声音→加入PIR→最终加入光照),性能逐步提升。最佳模型:SVM-RBF(所有16个特征),准确率98.4%,F1分数0.953。 降维实验: 通过PCA将特征从12维(不含光照)降至4维,仍保持92%准确率,验证特征间强相关性。 9.6 局限性 实验场景较小(6m×4.6m),未验证大规模场景适用性。光照传感器依赖人工操作,实际应用中需结合自动化控制。而对于我们上述的分析,我是将各个传感器进行了特征选择分析的,这也是最大的失误导致满盘皆错,自己还有许多不足之后也会慢慢弥补。
注意
# 若需要完整数据集以及代码请点击以下链接 mbd.pub/o/bread/aJWTmJpt关于房间传感器监测数据集的探索由讯客互联开源代码栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“关于房间传感器监测数据集的探索”
上一篇
[DeepSeek]二、大模型