『瀚思彼岸』» 智能家居技术论坛

 找回密码
 立即注册
查看: 2836|回复: 10

[技术探讨] 一种通过贝叶斯传感器判断房间睡眠状态的方法

[复制链接]

5

主题

74

帖子

1173

积分

金牌会员

Rank: 6Rank: 6

积分
1173
金钱
1099
HASS币
0
发表于 2023-9-16 00:26:12 | 显示全部楼层 |阅读模式
本帖最后由 快刀青衣 于 2023-9-16 00:29 编辑

本贴的起源是这个帖子里的讨论,然后搜索了一下发现论坛虽然有介绍贝叶斯传感器的帖子,但是示例都比较简单或者是官方的,缺少实际应用的例子。同时又搜索了一下发现很多人跟我一样有判断卧室是否处于睡眠状态的需求,因此开一帖介绍一下我的实践,抛砖引玉。

首先,要对贝叶斯传感器有一个基本的认识,这里论坛已经有两个介绍的帖子,简介官方文档汉化,比较详细了,但是我还是强烈推荐去阅读一下官方论坛的这个帖子,对于正确理解整个传感器的工作原理非常有帮助,同时里面还给出了一个excel表格,可以通过那个表格模拟贝叶斯传感器的运行,观察概率变化,对于我们实际调试也很有用。当时就是看了这个教授的文章才真正重视起来贝叶斯传感器的使用。

在前面的基础上,介绍一下我是怎么判断卧室的睡眠情况。

首先,硬件部分。包括主卧灯、书房灯(主卧阳台改成了小书房)、台灯、主卧门窗传感器、两台电脑、主卧窗帘、主卧床的压力传感器(小米门窗改的那种)、主卧窗帘。像灯、门、电脑的开关状态和窗帘的位置都是贝叶斯的条件。其中,主卧床的压力传感器必不可少,这是避免误判的重要一环:想象一个场景,晚上八点,卧室各设备均关闭,此时除了床上没有人,整个状态已经跟晚上睡眠的时候一模一样。当然,通过人在传感器或者专设一个只检测床区域的普通人体传感器(见注1)也可以一定程度上满足要求,但压力传感器是最适合的。总而言之,一定要想办法实现床这个区域有没有人的检测,至于持续检测精确度则可以不做高的要求。

其次,生活习惯。其实大部分人关于睡眠的生活习惯是固定的,那么,具体的贝叶斯传感器设计就也要针对生活习惯来制定,这个设计包括需要哪些设备、设备具体怎么布置、各个参数怎么设置。比如,我的主卧实际上只有一个压力传感器,布置在我老婆一侧,这是因为她会坐在床上玩手机而我几乎不会,上床就一定是要睡觉了,而且我知道这个系统的运行原理,更希望HA对她是无感的。

最后,逻辑和参数。首先要明确需求的逻辑,比如对于我来说,宁愿将非睡眠状态误判为睡眠(就叫假阳性吧,下同),也不能将睡眠误判为非睡眠(就叫假阴性,下同),前者顶多是自动开灯等自动化不起作用,后者则可能造成起夜或者老婆在睡觉我推门进入的时候灯火通明,哪个更痛苦不言而喻。参数计算时,可以用过去一段时间各个设备和传感器的历史状态作为历史数据,具体的计算建议多看那个教授的帖子。
- platform: 'bayesian'
  name: '主卧睡眠'
  prior: 0.458
  probability_threshold: 0.93
  unique_id: b4755a76-31e6-11ed-a161-0242ac120002
  observations:
  - platform: 'state'
    entity_id: 'light.bedroom_light'
    prob_given_true: 0.99
    prob_given_false: 0.78
    to_state: 'off'
 - platform: 'state'
    entity_id: 'light.studyroom_light'
    prob_given_true: 0.99
    prob_given_false: 0.85
    to_state: 'off'
 - platform: 'state'
    entity_id: 'light.lamp'
    prob_given_true: 0.99
    prob_given_false: 0.95
    to_state: 'off'
 - platform: 'state'
    entity_id: 'binary_sensor.huawei_laptop'
    prob_given_true: 0.99
    prob_given_false: 0.85
    to_state: 'off'
 - platform: 'state'
    entity_id: 'binary_sensor.surface'
    prob_given_true: 0.99
    prob_given_false: 0.95
    to_state: 'off'
 - platform: 'template'
    value_template: >-
       {% if states('sensor.chinese_calendar') == 'Workday' %}
           {{ now().hour > 22 or now().hour < 8 or (now().hour > 13 and now().hour < 18) }}
       {% else %}
           {{ now().hour < 12 or (now().hour > 13 and now().hour < 18) }}
       {% endif %}
    prob_given_true: 0.9
    prob_given_false: 0.15
 - platform: 'state'
    entity_id: 'binary_sensor.bedroom_door'
    prob_given_true: 0.99
    prob_given_false: 0.57
    to_state: 'off'
 - platform: 'state'
    entity_id: 'binary_sensor.bedroom_bed_occupied'
    prob_given_true: 0.9
    prob_given_false: 0.27
    to_state: 'on'
 - platform: 'template'
    value_template: >-
       {{ states.cover.bedroom_curtain.attributes.current_position < 25 }}
    prob_given_true: 0.95
    prob_given_false: 0.35
 - platform: 'template'
    value_template: >-
       {{ is_state('person.one', 'home') or is_state('person.two', 'home')}}
    prob_given_true: 0.99
    prob_given_false: 0.5
扯了这么多,上面就是一个卧室的贝叶斯传感器实现。介绍几点,prior很好理解,像我家主卧,每天睡眠时长约11小时,那么prior就是11/24=0.458。probability_threshold的设置就比较重要,比如像这个贝叶斯传感器,在我上面说的那个场景,即除了床上没人其他状态都跟睡觉时一样的时候,得到的概率是0.92,那么probability_threshold就设置为0.93,这样,只要床压力传感器不触发,则其他条件都满足也无法触发贝叶斯传感器。下面的就都是条件了,以binary_sensor.bedroom_bed_occupied这个主卧床有人传感器条件为例说明。首先,主卧床有人传感器是根据主卧床的压力传感器生成的,主要是进行了延时,即压力传感器保持关闭15分钟(关闭可以理解为无人),主卧床有人传感器才关闭。然后查询历史数据,发现“当主卧睡觉的11小时中主卧床有人传感器打开”的时间是10小时(因为只有一个压力传感器,所以即便进行了时延,也还是会有误判的时间出现),那么prob_given_true就是10/11=0.9;而发现“当主卧没有睡觉的13小时中主卧床有人传感器打开”的时间是3.5小时(就是我老婆坐在床上玩手机但没睡觉的时间),那么prob_given_false就是3.5/13=0.27。其他的条件以此类推计算。

然后关键来了,就是不要直接用这个贝叶斯传感器决定卧室是否睡眠。因为直接使用贝叶斯传感器判断睡眠状态有一个矛盾的点,即我们不希望假阳性就需要提高probability_threshold,但提高probability_threshold又会导致假阴性出现,反过来也是如此,二者不可兼得。举例来说,如前所述,除了床上没人其他状态都跟睡觉时一样的时候,得到的概率是0.92,由于我们希望避免假阳性从而probability_threshold设置为了0.93,那就意味着,如果卧室真的处于睡眠,但由于翻身导致主卧床有人传感器关闭了,此时概率变为0.92,会立刻小于probability_threshold从而使得假阴性出现。
- id: '1693813372395'
  alias: 主卧睡眠开启
  description: ''
  trigger:
  - platform: state
    entity_id:
    - binary_sensor.zhu_wo_shui_mian
    to: 'on'
    for:
       hours: 0
       minutes: 0
       seconds: 0
  condition: []
  action:
  - service: input_select.select_option
    data:
        option: 是
    target:
       entity_id: input_select.zhu_wo_shui_mian
  mode: single

- id: '1693813751070'
  alias: 主卧睡眠关闭
  description: ''
  trigger:
  - platform: template
    value_template: '{{ states.binary_sensor.zhu_wo_shui_mian.attributes.probability < 0.85 }}'
  for:
     hours: 0
     minutes: 5
     seconds: 0
  condition: []
  action:
  - service: input_select.select_option
    data:
       option: 否
    target:
       entity_id: input_select.zhu_wo_shui_mian
  mode: single

为了解决这个矛盾,可以设置两个input_select(也可以用binary_sensor,但是input_select保留了特殊情况下手动控制的可能,更推荐)和切换他们的自动化,关闭睡眠状态必须要probability降低到一定的水平(这意味着有多个条件都不满足了,没有睡觉的概率大大增加)。当只有一个或两个条件不满足时,probability降不下来,从而睡眠状态不会关闭,起到一定的抗干扰作用,这也是前述的“持续检测精确度则可以不做高的要求”的原因。像下图红圈部分,就是我老婆先起床导致主卧床有人传感器关闭,但由于probability一直没有降到0.85以下,所以主卧的睡眠状态一直持续到了我起床破坏了其他条件之后才关闭。

2023-09-15_220321.png

由图可知,一天的运行下来,睡眠状态的自动切换是很利落的。这个方法目前有一个bug,即人睡觉起来之后立刻出去但又不离开家,卧室保持睡觉时的状态,导致概率降不下来睡眠状态无法关闭,这个bug也可以通过增加贝叶斯传感器进行多重判断解决,但这种情况在我这里出现比较少懒得弄了,后续等众筹的压力带到了通过更新一下设置可以更容易地避免。另外还有一个缺点,就是当生活方式有较大变化时(比如白班转夜班或之类的),需要重新写一些条件,除此之外对我来说算是很不错了。

注1. 前面说可以通过专设一个只检测床区域的普通人体传感器作为条件,大概是这样:一个或者几个人体传感器检测房间其他区域,一个人体传感器专门只检测床面,然后比较他们的触发时间,当只检测床区域的人体传感器最晚动作时,则认为床上有人。重点是,当房间已经处于睡眠状态时,不进行上述动作(因为米家的人体传感器更新频率比较低,避免起夜等情况导致误判,具体的就不多扯了,各位可以自行思考)。这个本来是在还没有压力传感器出来的时候在次卧做权宜之计的,也曾经准备改造硬件通过mqtt接入缩短感应时间,但有了压力传感器之后改造就搁置了。

评分

参与人数 2金钱 +22 收起 理由
隔壁的王叔叔 + 10 高手,这是高手!
relliky + 12 我来瀚思就为看你!

查看全部评分

回复

使用道具 举报

19

主题

187

帖子

1198

积分

金牌会员

Rank: 6Rank: 6

积分
1198
金钱
1011
HASS币
0
发表于 2023-9-16 00:47:22 | 显示全部楼层
太强了,进来学习!
回复

使用道具 举报

32

主题

1065

帖子

4942

积分

论坛元老

Rank: 8Rank: 8

积分
4942
金钱
3862
HASS币
90
发表于 2023-9-16 04:31:41 | 显示全部楼层
感谢!!!!!!!!!!!!!!!!!!!
我研究一下
我家全屋智能的HA设置 https://github.com/relliky/Tais_Home_Assistant_Config
回复

使用道具 举报

18

主题

266

帖子

2160

积分

论坛DIY达人

积分
2160
金钱
1889
HASS币
20
发表于 2023-9-16 08:01:56 | 显示全部楼层
感谢分享。
下面复制百度:
贝叶斯定理用来描述两个条件概率之间的关系。
例如:一座别墅在过去的 20 年里一共发生过 2 次被盗,别墅的主人有一条狗,狗平均每周晚上叫 3 次,在盗贼入侵时狗叫的概率被估计为 0.9,问题是:在狗叫的时候发生入侵的概率是多少?我们假设 A 事件为狗在晚上叫,B 为盗贼入侵,则以天为单位统计,P(A) = 3/7,P(B) = 2/(20*365) = 2/7300,P(A|B) = 0.9,按照公式很容易得出结果:P(B|A) = 0.9*(2/7300) / (3/7) = 0.00058

另一个例子,现分别有 A、B 两个容器,在容器 A 里分别有 7 个红球和 3 个白球,在容器 B 里有 1 个红球和 9 个白球,现已知从这两个容器里任意抽出了一个红球,问这个球来自容器 A 的概率是多少?
假设已经抽出红球为事件 B,选中容器 A 为事件 A,则有:P(B) = 8/20,P(A) = 1/2,P(B|A) = 7/10,按照公式,则有:P(A|B) = (7/10)*(1/2) / (8/20) = 0.875

贝叶斯公式为利用搜集到的信息对原有判断进行修正提供了有效手段。在采样之前,经济主体对各种假设有一个判断(先验概率),关于先验概率的分布,通常可根据经济主体的经验判断确定(当无任何信息时,一般假设各先验概率相同),较复杂精确的可利用包括最大熵技术或边际分布密度以及相互信息原理等方法来确定先验概率分布。
回复

使用道具 举报

51

主题

1340

帖子

5598

积分

论坛DIY达人

积分
5598
金钱
4258
HASS币
20
发表于 2023-9-16 08:34:37 | 显示全部楼层
谢谢楼主分享!看得头晕脑胀,玩个HA比小时候读书还要伤脑筋.......
回复

使用道具 举报

146

主题

2267

帖子

7004

积分

元老级技术达人

积分
7004
金钱
4732
HASS币
30
发表于 2023-9-16 11:53:51 | 显示全部楼层
应该是一种推理算法,感觉是用其他的条件,做参考推理,计算得到事件的真与假
回复

使用道具 举报

0

主题

5

帖子

75

积分

注册会员

Rank: 2

积分
75
金钱
70
HASS币
0
发表于 2023-9-16 16:58:05 | 显示全部楼层
太强了!!!!楼主是搞自动化的吗?先验概率、后验概率、全概率、贝叶斯概率这些东西都是大学本科概率论讲的东西了。而贝叶斯传感器更是涉及到模式识别、多传感器数据融合等一系列专业知识了。
回复

使用道具 举报

0

主题

22

帖子

646

积分

高级会员

Rank: 4

积分
646
金钱
624
HASS币
0
发表于 2023-9-16 21:43:23 | 显示全部楼层
贝叶斯传感器是个具体的物理硬件还是一个概念软件传感器概念?
回复

使用道具 举报

3

主题

85

帖子

1150

积分

金牌会员

Rank: 6Rank: 6

积分
1150
金钱
1065
HASS币
0
发表于 2023-9-16 22:17:55 | 显示全部楼层
感谢楼主的介绍,又打开了新世界的大门!
回复

使用道具 举报

5

主题

74

帖子

1173

积分

金牌会员

Rank: 6Rank: 6

积分
1173
金钱
1099
HASS币
0
 楼主| 发表于 2023-9-17 10:55:46 | 显示全部楼层
baduxiyang 发表于 2023-9-16 21:43
贝叶斯传感器是个具体的物理硬件还是一个概念软件传感器概念?

是HA官方提供的binary sensor,基于贝叶斯定理的
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|Hassbian

GMT+8, 2024-11-24 04:37 , Processed in 0.096338 second(s), 35 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表