What Does an Alarm Tell Us?
An alarm may catch most faulty sensors and still be wrong surprisingly often. We need to know how common faults are before deciding what an alarm means.
13 sections · 4 questions · 2 coding challenges
The arrow keys move between sections too.
Working Back From What We Observed
BOTIE
Our alarm example is invented and uses a simpler finite table. Its useful connection to that history is the direction of reasoning. We observe the alarm, then update how plausible each possible cause is. We must account for both how well a cause explains the alarm and how common that cause was to begin with.
The Alarm Works. Why Are So Many Checks Unnecessary?
Botie has a warning light that usually turns on when a greenhouse sensor is faulty. That sounds useful. But when he checks the sensors that triggered it, many are working normally. Has the warning light stopped working?
Before answering, we need to ask two different questions. How often does a faulty sensor trigger the light? And, among sensors that trigger the light, how many are faulty? Those questions describe different groups. Let's follow the sensors through both groups before reaching for a formula.
Fault prevalence and alarm rates are supplied illustrative probabilities.
Step 1 of 4
Start with all the sensors
Suppose exactly 10 of these 1,000 sensors are faulty. The other 990 work. These counts describe our invented report, not an estimated industry fault rate.
Step 2 of 4
Follow the alarms from both groups
Nine faulty sensors trigger the alarm. So do 99 working sensors. A small fraction of a large group can contribute many alarms.
| Actual condition | Sensors | Alarmed | Did not alarm |
|---|---|---|---|
| Faulty | 10 | 9 | 1 |
| Working | 990 | 99 | 891 |
Faulty
- Sensors
- 10
- Alarmed
- 9
- Did not alarm
- 1
Working
- Sensors
- 990
- Alarmed
- 99
- Did not alarm
- 891
Step 3 of 4
Now look only at the alarm group
Botie's question concerns the 108 alarms. Only nine of them came from faulty sensors. The group in the denominator has changed.
All alarms = 9 + 99 = 108 Faulty among alarms = 9 / 108 ≈ 0.0833 Alarms among faulty sensors = 9 / 10 = 0.9
Step 4 of 4
The same alarm can mean more when faults are common
Keep the detection and false-alarm rates fixed, but imagine a population with more faulty sensors. A larger share of the alarms now comes from real faults. The alarm's meaning depends on the starting population as well as the detector.
| Population | Faults | Alarms from faults | Alarms from working sensors | Fault share among alarms |
|---|---|---|---|---|
| Faults are rare | 10 | 9 | 99 | About 8.3% |
| Faults are more common | 100 | 90 | 90 | 50% |
Faults are rare
- Faults
- 10
- Alarms from faults
- 9
- Alarms from working sensors
- 99
- Fault share among alarms
- About 8.3%
Faults are more common
- Faults
- 100
- Alarms from faults
- 90
- Alarms from working sensors
- 90
- Fault share among alarms
- 50%
The alarm changes the group whose proportions we need
Weighting accounts for how common each cause is and how likely it is to produce the alarm. Dividing by the total changes the reference group to alarms.
Among the alarms, how many came from faults?
An alarm can come from a faulty sensor or a working one. Change how common faults are while keeping the alarm rates fixed and see how the explanation of an alarm changes.
BOTIE
Faulty and working shares after the alarm
- 00.0833
- 10.9167
Follow the operations
1. Faulty and working priors
- 00.01
- 10.99
2. Alarm rates given each cause
- 00.9
- 10.1
3. Weight evidence by prior
- 00.009
- 10.099
4. Add a list
0.108
5. Divide
- 00.0833
- 10.9167
6. Result
- 00.0833
- 10.9167
These invented rates are known inputs. This calculation neither estimates their uncertainty nor decides whether an inspection is worth its cost.
1. Say Which Group We Are Talking About
A probability needs a reference group. In this report, the fault rate describes all sensors. The alarm rate among faulty sensors describes only the faulty ones. Once we are told that a sensor raised an alarm, our reference group becomes the sensors that raised alarms.
Conditioning means restricting our attention using information we know. The vertical bar in a conditional probability reads as 'given'. Its position matters.
P(alarm | faulty) = 9 / 10 = 0.9
P(faulty | alarm) = 9 / 108 ≈ 0.0833Both statements can be true at the same time. Catching most faults does not establish that most alarms are faults.
2. Count Every Way the Alarm Could Happen
An alarm can come from either a faulty sensor or a working one. We need both contributions. If we count only the faulty sensors that triggered, we have a numerator but no complete denominator.
The fault rate before reading the alarm is the prior probability. The alarm rate within each group tells us how compatible the alarm is with that group.
P(faulty and alarm) = 0.01 × 0.9 = 0.009
P(working and alarm) = 0.99 × 0.1 = 0.099
P(alarm) = 0.009 + 0.099 = 0.108These are shares of all sensors. They become expected counts if we multiply by a proposed population size; expected counts need not be whole numbers.
3. Turn the Contributions Into an Updated Probability
To find the faulty share of the alarm group, divide its contribution by the total alarm contribution. This is the posterior probability, meaning the probability after incorporating this observation.
Bayes' rule writes the same bookkeeping for named events. The denominator accounts for all the ways the observed evidence can occur.
P(faulty | alarm)
= P(alarm | faulty) × P(faulty) / P(alarm)
= 0.009 / 0.108
≈ 0.0833This updates a probability. Choosing whether to send a technician is another question, involving the cost of a missed fault and an unnecessary visit.
4. Change the Starting Population
Now move the same warning system to sensors with a much higher fault rate. Even if its behaviour within the faulty and working groups stays the same, an alarm can become more convincing.
That is why we should not carry a positive predictive value from one population to another without checking the assumptions. The new population might also change the alarm's behaviour within each group.
New prior: P(faulty) = 0.2
Faulty alarm contribution = 0.2 × 0.9 = 0.18
Working alarm contribution = 0.8 × 0.1 = 0.08
Updated faulty probability = 0.18 / 0.26 ≈ 0.6923The hardware did not improve in this calculation. We changed how common each possible cause was.
5. Keep the Assumptions Visible
Our two causes cover every sensor and do not overlap. Their prior probabilities must therefore sum to one. The alarm rates are conditional on those causes; they do not have to sum to one.
An event assigned zero probability by every cause cannot be used in this calculation because there is no alarm group to condition on. Repeating the update with another alarm also needs a model of dependence: two copies of the same report are not two independent pieces of evidence.
Botie's workshop asks you to form the contributions and normalise them. It leaves the final inspection decision to a later lesson.
Calculate both updated shares
Keep the two possible causes in the same order in both arrays.
import numpy as np
prior = np.array([0.01, 0.99])
alarm_rate = np.array([0.9, 0.1])
joint = prior * alarm_rate
posterior = joint / joint.sum()
print(np.round(posterior, 4).tolist())[0.0833, 0.9167]The first entry concerns faulty sensors. The second concerns working sensors. They now describe the alarm group.
6. Follow People through the Groups Before Dividing
A warning system can catch most faults while producing many false alarms. To see why, start with a population rather than a percentage. Separate faulty sensors from working sensors, then ask how many in each group trigger the light.
Only after counting those two routes should we restrict attention to the sensors whose lights are on. The denominator has changed from all sensors, or all faulty sensors, to all alarms. That change of group is the reason the two conditional probabilities differ.
1,000 sensors: 10 faulty, 990 working
80% of faulty sensors trigger: 8 alarms
10% of working sensors trigger: 99 alarms
Faulty among alarms = 8 / (8 + 99) ≈ 0.07487. Carry the Same Test into a Different Population
Now suppose Botie checks a batch that may have been damaged in transit. Faults are more common in this batch. Even with the same sensitivity and false-alarm rate, the warning light now means something different: a larger share of the alarms can come from faulty sensors.
So, before using a probability attached to a test result, we need to know which population it describes. A result from ordinary deliveries may not apply to this damaged batch.
Change only the starting failure rate
The two entries represent ordinary stock and a damaged shipment.
import numpy as np
prior = np.array([0.01, 0.20])
sensitivity, false_alarm = 0.8, 0.1
alarm_fault = prior * sensitivity
alarm_working = (1 - prior) * false_alarm
print(np.round(alarm_fault / (alarm_fault + alarm_working), 4).tolist())[0.0748, 0.6667]The mechanism of the warning light did not improve. The evidence began from a different proportion of faulty sensors.
Check yourself
Questions on Parts 1 to 7
Question 1 of 4
Which denominator answers 'What share of alarms came from faulty sensors?'
Use the information below.
Faulty sensors: 10; working sensors: 990.
Alarms from faulty sensors: 9; alarms from working sensors: 99.Try it with Botie
Build with Botie
Write and run Python