我做了挺长时间智能家居方向的东西,一直觉得市面上所谓的"智能"大多名不副实——无非是App里点一下开关,设个定时,或者语音控制一下,本质还是人在操作机器,机器并没有真正理解人。直到我自己动手做了这个基于用户行为数据分析的AI实验项目,才算是摸到了一点"智能"的门槛。这套方案的核心思路很简单:不靠规则,而是让系统通过传感器采集用户在房间里的行为轨迹,用模型去学习每个人的生活习惯,再反过来自动控制灯光、空调、窗帘这些设备。今天就把我踩过的坑、调过的参数、还有整个从零搭建的思考过程完整写出来,想自己做点真·智能家居实验的,可以参考参考。
本文主要分享一套可以完整复现的实验框架,适合有嵌入式或Python基础、想尝试AIoT方向落地项目的开发者,也适合正在做毕业设计或者个人作品集的电子、计算机相关专业学生。我会从方案选型、传感器选型、数据采集、模型训练、自动化联动到问题排查全部讲清楚,里面包含我实际跑通的代码结构和具体配置,能直接省掉你大量试错的成本。
1. 实验项目的整体设计思路拆解
1.1 传统智能家居为什么不够"智能"
智能家居已经这么多年了,但大部分人的真实体验是:装了一堆智能设备,新鲜了几天,最后还是回去用手按开关。问题出在哪?传统方案本质上都是被动响应式的——用户给出明确指令(按键、App点击、语音命令),设备才执行动作。这不能算智能,只能算"可以远程控制的电器"。
真正能称为智能家居的,应该具备两个能力:主动感知和自适应决策。主动感知指的是系统能通过采集用户行为数据,判断"这个人在哪个房间""在做什么";自适应决策指的是系统根据判断结果,自动调节设备状态,并且随着用户习惯的积累不断优化调节策略。要做到这两点,光靠if-else规则是写不出来的——你不可能穷举"几点几分在客厅看电视应该开多亮的灯"这种组合,所以才需要引入行为数据分析这个环节,让模型代替人去发现规律。
1.2 方案选型:行为数据驱动 vs 规则驱动
我做实验最开始确实走了弯路。第一版用的是纯规则方案:人体传感器检测到有人,就开灯;超过5分钟没检测到动静,就关灯。听起来合理,实际用起来别扭得要命——你坐在沙发上玩手机一动不动,灯10分钟就关了,得频繁挥手臂去"唤醒";你在卧室睡觉翻了个身,传感器照样触发,灯半夜亮起来差点把我吓醒。
这些痛点让我下决心换成行为数据驱动的方案。核心思路变成了三层:
- 数据层:用多个低成本传感器持续采集用户在屋内的移动轨迹、停留时间、开关门状态、电流能耗变化,形成时间序列数据。
- 模型层:把时间序列切分成窗口,提取统计特征,用分类模型识别当前行为(睡觉、办公、看电视、做饭、离家等)。
- 控制层:把识别出的行为映射为设备联动规则,用置信度加时间平滑策略避免抖动,保证执行稳定性。
这个框架的普适性很强,因为它把"感知—理解—行动"解耦了。即使你后续换更好的传感器、换更强的模型,只需要替换对应层就行,不用推翻整个架构。
1.3 实验环境的整体架构
我实际搭建的实验环境是这样的:以一块STM32F407开发板作为主控,连接人体红外传感器、门磁传感器、电流互感器、温湿度传感器,数据通过串口传给树莓派(或者任何一台跑Python的主机),在树莓派上完成数据清洗、特征提取、行为识别,最后通过MQTT下发控制指令给智能插座和PWM调光模块。整体架构如下:
传感器采集层(STM32) ↓ 串口JSON数据 边缘数据层(树莓派 + Python) ↓ MQTT 控制执行层(智能插座 / 调光模块 / 窗帘电机)我当时选择STM32做主控,是因为它的ADC和GPIO资源丰富,采集多路传感器很方便,还能把采集到的数据先做一层滤波,减轻上位机的计算压力。但如果你手里只有树莓派或者香橙派,也可以把传感器直接接到开发板,节省一层通信开发时间。这个方案很灵活,核心不在于主控型号,而在于数据通路要打通——传感器数据必须以结构化的、带时间戳的形式进入模型,而不是零散地存日志文件。
2. 数据采集与预处理:整个系统最容易翻车的一步
2.1 传感器选型的门道
行为识别的基础是数据质量,而数据质量在你选定传感器的瞬间就决定了大半。我用过的传感器有好几种,逐个说说实际表现。
人体红外传感器(PIR):最常用,便宜,但短板也明显——只能检测"有没有人动",静止的人体检测不到。我在沙发上刷手机这一场景里,PIR数据几乎是断线的。后来我加了一个策略:PIR不单独作为判断依据,而是和电流检测配合使用,用电器的功率波动曲线作为状态兜底。
门磁传感器:装在房门和门窗上,检测开关状态。这个数据非常有价值,尤其用来判断"进出房间""起夜""外出回家"等事件,状态量简单可靠,几乎不需要清洗。强烈建议每个房间至少装一个。
电流互感器(非侵入式电流检测):这是我整个数据方案里最关键的一个传感器。它夹在房间总闸的电线上,通过检测电流波形间接判断电器开关状态,不需要拆改电路。在电视、电脑、电暖器这些大功率设备上效果非常明显——一旦电视启动,电流特征立刻跳变。这比PIR靠谱多了。
温湿度传感器(DHT22):辅助作用,用来区分"洗澡"(湿度骤升)和"正常活动",以及辅助判断睡眠时段的环境变化。
选型的一个通用原则:永远不要迷信单一传感器。行为识别本质是融合多种弱信号做判断,单一传感器数据都太片面,只有多源数据交叉验证才能获得稳定的准确率。
2.2 采样策略与数据格式设计
采样频率是第一个要定下来的参数。我实测下来的推荐值是:PIR和门磁高频采集(2~5秒一次),电流互感器中等频率(1秒一次),温湿度低频采集(30秒一次),然后用时间对齐机制把不同频率的数据统一到同一时间轴。采样频率不是越高越好——采集频率太高,数据量大而且波动噪声多,徒增清洗成本;太低,则会漏掉关键行为变化,尤其是开关电器的瞬态特征。
数据格式我走了不少弯路。一开始我用CSV裸存,时间戳格式不统一、传感器id混乱,后面做特征工程时痛苦不堪。后来统一成了JSON格式,每条数据带"sensor_id"、"timestamp"、"value"、"event_type",STM32端组装好之后通过串口发给上位机。下面是我实际使用的数据帧格式:
{ "timestamp": "2024-11-20 21:03:26", "sensor_id": "pir_livingroom", "value": 1, "event_type": "motion" }这里有一个重要的工程细节:传感器数据解析必须考虑丢包和乱序。我踩过很惨的坑——STM32串口缓冲区溢出,导致时间戳错位十几个小时,整个训练集报废,后来在解析脚本里加入"时间戳单调性校验",一旦发现乱序,直接丢弃该帧并打日志,宁可丢数据也不要错数据。
2.3 从原始状态到行为特征:特征工程怎么做
数据采集完成之后,你手里是一堆看似杂乱的状态序列,接下来就是特征工程的主场了。这也是我在琢磨"模型到底学什么"时花时间最多的地方。对于一段30分钟的时间窗口,我提取的特征分三层:
基础统计特征:运动触发次数、平均停留时长、开门次数、功率均值/方差、温湿度变化趋势。这一层描述的是"这个房间里发生了什么动静"。
时间上下文特征:当前时间段(清晨/上午/下午/深夜)、是否为工作日、距上次离家时长。这一层描述的是"当前处于什么时间场景"。通过把时间编码进去,模型才能区分"凌晨玩手机"和"夜间睡眠"这种统计特征很相似但本质不同的行为。
状态转移特征:上一行为状态、当前状态的持续时间、相邻事件的时间间隔。这一层是让模型具备"记忆"的关键,比如从"客厅活动"突然变为"卧室活动",大概率是准备睡觉了。
特征提取完之后,我做了标准化处理(StandardScaler),并且把所有特征拼成一个向量输入模型。工程上还有一个很容易被忽略的决策:滑动窗口的重叠率。我用的是30秒窗口、10秒步长,也就是说相邻窗口有20秒重叠。重叠的好处是行为切换的过渡帧能被多次采样,提升模型对边界事件的敏感度;坏处是数据量增大三倍。测试下来这个重叠率对准确率的提升很值,推荐沿用。
3. 行为识别模型的选择与训练细节
3.1 轻量模型还是深度模型
模型选择这一步,我先后尝试过好几种方案,把试错经验直接分享给你,省得重复花钱花时间。
决策树/随机森林:胜在训练快、可解释性强、嵌入式部署友好。在数据量不大的家庭场景下(我只积累了大概两周数据,两万多条窗口样本),随机森林在五个行为类别的分类上能达到89%左右的准确率,这个表现已经足够实用了。如果你没有太多标注数据,或者不想在调动GPU这些事上耗费精力,随机森林是完全够用的方案。
LSTM/GRU等序列模型:能捕捉更细粒度的时序依赖,我在实验中测试了GRU模型,准确率能提到93%左右,但代价是训练时间显著增加、模型体积大、在树莓派上推理延迟更高。在"人在房间内走动—坐下—打开电脑"这种连续动作切换的场景里,GRU确实比随机森林更顺滑,但用起来成本高了不少。
实际结论:当前实验阶段,随机森林已经能覆盖我的需求,优先考虑在线推理的低延迟,所以最终用的是随机森林 + 少量滑动窗口平滑策略的折中方案。如果你是想做学术验证或者心中有更复杂的场景需求(比如同时识别"睡眠品质""情绪状态"等高阶概念),再考虑换序列模型不迟。
给一个我训练模型时的代码结构参考,比较容易跑通:
import pandas as pd from sklearn.ensemble import RandomForestClassifier from sklearn.model_selection import train_test_split from sklearn.metrics import classification_report # 假设 features 是特征工程后的DataFrame,label 是行为标签列 X = features.drop(columns=['label']) y = features['label'] X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.2, random_state=42, stratify=y ) clf = RandomForestClassifier( n_estimators=200, max_depth=12, min_samples_leaf=2, n_jobs=-1, random_state=42 ) clf.fit(X_train, y_train) y_pred = clf.predict(X_test) print(classification_report(y_test, y_pred))这里有三个参数我调了很久,重点说一下:
max_depth=12:限制树深,防止模型过度学习个别时间段的行为噪声。试过不限制深度,训练集准确率100%,测试集直接掉到75%,过拟合非常明显。min_samples_leaf=2:保证每个叶子节点至少覆盖2个样本,提高泛化能力。数据量少的场景下这个参数很管用。n_estimators=200:不是越多越好,我测过500棵树,准确率只提升了0.2%,但推理耗时增加了接近一倍。为了在树莓派上跑实时推理,我压在了200棵。
3.2 行为类别的定义与标注策略
模型能识别什么,取决于你定义了哪些行为类别。我在实验里先定义了五个最基础的家居行为:睡眠、居家活动、工作学习、影音娱乐、离家。这几个类别基本覆盖了一天中绝大部分时间,而且区分度比较明显,模型学习起来不困难。
标注是监督学习里最耗费精力的环节,起初我天真地想全手动标注——边看时间戳边翻监控日志做标记,两周数据标下来,人真要疯了。后来我换了个半自动标注策略:用App记录 + 传感器事件自动辅助。具体做法是:手机装一个简单的打卡App,每当行为切换时手动打一个标签;然后写脚本,用门磁和PIR事件的时间点做辅助对齐,自动填充两个行为标签之间的未标注区间。这样两周的数据,实际手动标注的时间压缩到了两小时内,效率提升巨大。
3.3 从模型输出到设备控制:置信度与平滑策略
模型直接输出预测结果,拿它去控制设备是不行的,会有一个专有名词叫"决策抖动"——模型在行为边界上来回摆动,一会儿判定"居家活动",一会儿判定"影音娱乐",如果这种抖动直接映射成设备开关动作,灯就会疯狂闪烁,空调一会开一会关,体验非常糟糕。
我的解决思路是引入一个置信度阈值 + 滞回比较器:
PREDICT_THRESHOLD = 0.7 # 低于该置信度不切换状态 HYSTERESIS_COUNT = 3 # 连续3个窗口预测相同行为才切换 def decide_action(current_state, prediction_prob): max_prob = max(prediction_prob) pred_label = prediction_prob.argmax() if max_prob < PREDICT_THRESHOLD: return current_state # 置信度不足,维持现状 if pred_label != current_state and confidence_streak[pred_label] >= HYSTERESIS_COUNT: return pred_label return current_state置信度阈值设为0.7是我多次测试后的平衡点。设得太高,行为切换响应慢,比如从客厅进卧室躺下,可能要等1分钟才能触发睡眠氛围;设得太低,误判会明显增多。滞回比较器的作用更直接——要求连续3个窗口(20秒)都预测同一个行为才真正切换,这样设备的执行状态就稳定了,画面就舒服多了。
4. 自动化联动与系统掉线排查实录
4.1 行为到设备执行链路的搭建
模型识别出行为并不等于智能家居完成,还要把行为转成实际设备动作,并通过稳定可靠的链路执行下去。我的这套系统里,树莓派跑着Python程序,推理出来的行为标签通过MQTT协议发布到消息服务器,然后智能插座、调光模块、窗帘电机各自订阅自己关心的主题,收到指令就执行动作。
联动规则我写在了模型和硬件中间的一个规则引擎里,这样后续修改联动策略不需要动模型代码。举几个我实际在用的联动规则:
| 识别行为 | 执行动作 | 执行时机 |
|---|---|---|
| 睡眠 | 关闭卧室主灯、空调设为睡眠模式 | 行为持续1分钟以上 |
| 影音娱乐 | 客厅灯光调暗到30%、打开电视插座电源 | 置信度超过0.8 |
| 工作学习 | 书桌台灯亮度调到80%、关闭卧室设备 | 行为持续30秒 |
| 离家 | 关闭所有非必要插座、窗帘自动合上 | 离家状态持续5分钟 |
这套规则本身不复杂,但执行顺序上有一个重要的经验:设备动作要分级响应。比如睡眠行为触发,应该先关灯再调空调,然后是电动窗帘,最后才是那些不痛不痒的待机设备断电。如果反过来一窝蜂同时执行,瞬间功率波动会很大,而且夜里的执行噪音会影响用户入睡。
4.2 我实际踩过的几个典型问题
这个实验过程中,问题多得写不完,挑几个最有代表性的、也是最可能复现的问题说说,每个都附带排查思路。
问题一:传感器偶发误报,导致行为识别紊乱
PIR传感器非常容易被热源干扰,比如暖气片、阳光直射,甚至猫路过,都会触发误报。最初我识别准确率总上不去,排查了很久,后来通过可视化工具看数据的分布,才发现有一个区域的数据标签和实际场景严重不符——是PIR安装位置对着一面西晒墙导致的。解决方案是调整安装位置,同时后端加了一个"去抖逻辑":PIR单次触发信号持续时间低于3秒的当做无效事件,直接过滤掉。
问题二:串口通信中断,上位机数据断流
STM32和树莓派之间的串口通信,运行几天之后莫名中断。排查后发现是USB转串口模块的供电不稳导致的。给模块换了一个独立供电的USB HUB端口,之后一周测试再没断过。排查这类问题有个经验:先看物理层供电,再看波特率,最后看软件缓冲区,能省很多时间。
问题三:模型冷启动,刚装好系统时没有历史数据可用
刚开始的那一周,模型没有用户历史行为数据,处于裸奔状态。我的临时方案是:内置了一套保守的默认规则兜底(比如"检测到有人就保持当前设备状态不变"),同时不执行任何自动化动作,只默默采集数据。等攒够了三天的行为数据,才开始训练模型并切换到自动模式。这个"影子模式"设计,既保证了实验期间不影响正常生活,又让系统平稳度过了数据积累期。
问题四:树莓派卡死导致智能联动全部失效
有一阵子系统运行两三天就卡死一次,后来排查出来是树莓派的内存被频繁读写日志撑爆了。加了两道保险:一是日志切割,每天一个文件,超过50MB就清理最旧的;二是写了一个看门狗脚本,每隔15分钟检查主进程是否存活,死掉就自动重启。从那以后系统再没长时中断过。
4.3 实验效果评估
系统稳定运行一段时间之后,我做了一次集中评估。随机选取了连续7天的数据做离线回测,行为识别准确率在89%~93%之间,比预想的要好;联动规则执行成功率在95%左右,剩下的5%个别是因为传感器数据缺失导致置信度不足,系统主动放弃了执行。这个结果下,自动模式带来的设备误动作已经非常少。
还有个很有价值的副产品:通过行为数据分析,系统能发现用户的生活习惯规律。比如通过聚类分析,我发现我工作日晚上11点30分左右进入卧室的概率高达78%,系统可以在这个时间点提前开启卧室空调的睡眠预热模式,这就是一个靠规则很难想到、但数据能自然浮现的智能场景。
5. 这套实验还能往哪些方向延伸
做完整套流程之后,我最大的体会是:基于用户行为数据分析的智能家居,真正的护城河不在硬件,而在数据和模型的积累。设备谁都能买到,传感器谁都能拼,但"如何从模糊的传感器信号中理解人的意图"才是决定体验上限的关键。
如果你也想动手做,我建议按这个顺序推进:先把传感器数据通路跑通,再做简单的规则联动,积累两周数据,然后引入模型识别,最后才考虑多房间联动和远程控制。步子迈得太大,容易在调试上耗尽耐心。
如果已经完成了基础版,还有一些很值得尝试的扩展方向:用序列模型做全屋行为轨迹预测,提前预判下一个房间;把语音、摄像头视觉信息融合进来,提升行为识别的鲁棒性;或者接入语音助手,让自动化规则支持自然语言交互。我自己下一个阶段正准备做的是多设备联动场景下的能耗优化——在保持行为识别准确的前提下,把非必要设备的待机能耗压到最低,这会在后面单独写一期实验记录,到时候再来分享实际数据。
最后再分享一个小技巧:实验过程中一定要把传感器原始数据、中间特征、模型预测结果全部可视化出来。别怕麻烦,很多时候你盯着数据分布看半小时,比闷头调三天参数更有效。行为数据本身是会说话的,关键是你得先让它们呈现在你眼前。