Copied from the GitHub issue: Bayesian sensor fundamentally changed · Issue #79694 · home-assistant/core · GitHub
Apologies and efforts
Hi all and apologies for the inconvenience.
OP is right. The fundamental logic of the Bayesian sensor has indeed changed. I will explain the rationale and the methods to transition. But first I want to explain that I have put a great deal of effort into trying to make the transition as least painful as possible including the merge of 2 repair features which detect broken configs rather than silently breaking. Add repair for missing Bayesian `prob_given_false` by HarvsG · Pull Request #79303 · home-assistant/core · GitHub and Add to issue registry if user has mirrored entries for breaking in #67631 by HarvsG · Pull Request #79208 · home-assistant/core · GitHub. I hope that is what has lead you here. I made efforts to survey the community to understand how people worked around the old logic. I tried to consult the community on changes that are coming. And when I realised the breaking text was not helpful enough I tried to change it. I got a statistic professor - and likely author of the spread sheet you are using - to have a look at my changes: prob_given_false is soon req, show in examples by HarvsG · Pull Request #24276 · home-assistant/home-assistant.io · GitHub and the response was postive.
Rationale
The changes were made in essence because the previous functionality was incorrect, based on incorrect maths and those of you who do have working configs have them working despite the previous logic, not because of it. For more detail on this you can read the early discussion on the breaking PR https://github.com/home-assistant/core/pull/67631 but in short there were 2 issues. Firstly prob_given_false
had a default value of 1 - prob_given_true
this had no mathematical rationale. The second, which is most likely causing the issue you are facing, is that the logic did not update the probabilities if a sensor was not sensing the ‘to_state’, this is simply poor logic. If a motion sensor senses movement that is evidence you are home, and if it doesn’t - that is (weaker) evidence you are not home. This was pointed out in this popular community post
Fixes:
If your config looks like this - with both opposite states configured with prob_given_true
s and prob_given_false
s that sum to one then your config was essentially a ‘workaround’ implementing what this change did. So the fix is to simply remove one of them
- platform: "bayesian"
name: "internet_working"
prior: 0.99 # internet has high up time
probability_threshold: 0.95
observations:
- platform: "state"
entity_id: "binary_sensor.internet_connection_cloudflared"
prob_given_true: 0.003 # cloudflare is rarely unavailible when the internet is up
prob_given_false: 0.99 # it is highly likely that cloudflare will be unreachable when the internet is down - unless it is a dns issue
to_state: "off"
- platform: "state"
entity_id: "binary_sensor.internet_connection_cloudflared"
prob_given_true: 0.997 # cloudflare is rarely unavailible when the internet is up
prob_given_false: 0.01 # it is highly likely that cloudflare will be unreachable when the internet is down - unless it is a dns issue
to_state: "on"
- platform: "template"
prob_given_true: 0.0001
prob_given_false: 0.10
value_template: >-
{% if is_state('binary_sensor.greenpi', 'off')
and is_state('binary_sensor.wireguard', 'off') %}
true
{% else %}
false
{% endif %}
- platform: "template" # evaluates to true when both the greeni and wireguard are down
prob_given_true: 0.9999 # if the internet is working then it is very unlikely both are down
prob_given_false: 0.90 # if the internet is not working then there is 10% chance they are both unreachable
value_template: >-
{% if is_state('binary_sensor.greenpi', 'off')
and is_state('binary_sensor.wireguard', 'off') %}
false
{% else %}
true
{% endif %}
to de-duplicate
- platform: "bayesian"
name: "internet_working" # maybe sensible to switch these in seperate errors - DNS, Switch, Gl-inet
prior: 0.99 # internet has high up time
probability_threshold: 0.95 # by defualt assume the internet is up
observations:
- platform: "state"
entity_id: "binary_sensor.internet_connection_cloudflared"
prob_given_true: 0.003 # cloudflare is rarely unavailible when the internet is up
prob_given_false: 0.99 # it is highly likely that cloudflare will be unreachable when the internet is down - unless it is a dns issue
to_state: "off"
- platform: "template" # evaluates to true when both the greeni and wireguard are down
prob_given_true: 0.0001 # if the internet is working then it is very unlikely both are down
prob_given_false: 0.10 # if the internet is not working then there is 10% chance they are both unreachable
value_template: >-
{% if is_state('binary_sensor.greenpi', 'off')
and is_state('binary_sensor.wireguard', 'off') %}
true
{% else %}
false
{% endif %}
(This is important for value_template
and numeric_state
observations like the one above, otherwise the probability calculations will be duplicated. It won’t actually effect anything for state
observations - for reasons I can explain later if wanted)
If your config looks like this (only one to_state
configured per entity) then your config is essentially correct, however when you set it up you probably had to ‘tweak’ the probabilities to get the functionality you wanted rather than basing them on ‘true’ values. So your functionality will likely be different after today’s update.
- platform: "bayesian"
name: "someone home"
prior: 0.6
probability_threshold: 0.8
observations:
- platform: "state"
entity_id: "binary_sensor.hall_motion"
prob_given_true: 0.70
prob_given_false: 0.001
to_state: "on"
- platform: "state"
entity_id: "binary_sensor.kitchen_motion"
prob_given_true: 0.65
prob_given_false: 0.001
to_state: "on"
There are 2 fixes. The first, and most future-proof way is to head to the new updated documentation and re-estimate your probabilities - you will likely find that accuracy improves. There are worked examples in the documentation and in the GitHub issue linked above.
The hacky solution (not recommended) to effectively disable the new functionality but setting the other states to being uninformative
by setting the prob_given_false
== prob_given_true
. This will not work for numeric_state
and templates
- platform: "bayesian"
name: "someone home"
prior: 0.6
probability_threshold: 0.8
observations:
- platform: "state"
entity_id: "binary_sensor.hall_motion"
prob_given_true: 0.70
prob_given_false: 0.001
to_state: "on"
- platform: "state"
entity_id: "binary_sensor.hall_motion"
prob_given_true: 0.5
prob_given_false: 0.5
to_state: "off"
- platform: "state"
entity_id: "binary_sensor.kitchen_motion"
prob_given_true: 0.65
prob_given_false: 0.001
to_state: "on"
- platform: "state"
entity_id: "binary_sensor.kitchen_motion"
prob_given_true: 0.5
prob_given_false: 0.5
to_state: "off"
The hacky work around for template
observations would be to re-write the template to return None
instead in place of when it would return False
- to again induce Bayesian to ignore a negative observation as it used to.
Again - apologies for the breaking change. I hope you can appreciate have made efforts to try and reduce the pain this change brings.
If you are confused by the above then please post your config here, DM* on the community forum if you want to keep it private or send me a link to a public gist and I will fix it for you. @ikbensuper @stigvi
*ideally best to do it in public so others can learn from the changes.