AI Computer Institute
Expert-curated CS & AI curriculum aligned to CBSE standards. A bharath.ai initiative. About Us

Anomaly Detection: Finding the Unusual

📚 Machine Learning Applications⏱️ 24 min read🎓 Grade 9
✍️ AI Computer Institute Editorial Team Updated: August 2026 CBSE-aligned · Peer-reviewed · 24 min read
Content curated by subject matter experts with IIT/NIT backgrounds. All chapters are fact-checked against official CBSE/NCERT syllabi.

A Payment That Didn't Fit

Every time you scan a QR code to pay a chai vendor with UPI, that payment joins a river of transactions flowing through India's banking system — the UPI network alone handles billions of transactions every month, all day, every day. No human being sits there watching each one scroll past. Instead, software constantly asks a simple question about every single transaction: does this look like the millions of ordinary payments that came before it, or does it look strange? A ₹150 payment to a grocery store at 11 AM looks normal. A ₹150 payment to the same grocery store looks normal at 2 AM too, honestly. But a sudden ₹48,000 transfer from an account that has never sent more than ₹2,000 in its history, sent at 3 AM to an account it has never interacted with — that looks strange. Finding that one strange event hiding inside an ocean of normal ones is called anomaly detection, and it is one of the most useful ideas in applied machine learning. This chapter builds it from the ground up: what "unusual" even means mathematically, two different ways to catch it, and — just as important — a case where the obvious method quietly fails.

Start Small: Spot the Odd One Out

Before any formulas, look at real numbers. Ten students in a Delhi school were asked how much they spent at the canteen last week, in rupees:

230, 150, 180, 190, 200, 210, 160, 170, 220, 2400

You don't need statistics to notice something here. Nine of those numbers sit comfortably between ₹150 and ₹230 — a normal week of samosas and Frooti. The tenth number, ₹2400, is in an entirely different world. Your eye caught it instantly. The whole challenge of anomaly detection is teaching a computer to do what your eye just did, except on datasets with thousands or millions of values where "just looking" is impossible. That means we need a precise, numerical definition of "doesn't fit" — and two different ways of computing it, because as you'll see, the obvious way has a serious blind spot.

What Exactly Is an Anomaly? Three Kinds

Anomaly detection is the task of identifying data points that differ significantly from the pattern followed by the majority of the data. But "different" can show up in three distinct ways, and CBSE-level clarity means keeping them separate:

  • Point anomaly: a single value that is unusual all by itself, independent of context — like the ₹2400 canteen bill sitting among ₹150–230 bills. This is the simplest and most common type, and the one this chapter focuses on.
  • Contextual anomaly: a value that is normal in one context but unusual in another. A household's electricity bill showing 8 units of AC usage in one day is completely unremarkable in June (peak summer) but would be strange for the same household in December — the value itself doesn't change meaning, the context around it does.
  • Collective anomaly: individual values that look fine on their own, but the pattern formed by a group of them together is unusual. A single ₹1 UPI transaction is not suspicious. Twenty ₹1 transactions to twenty different accounts within ninety seconds from the same phone is a classic fraud-testing pattern — no single transaction is the anomaly; the sequence is.

Why Machines Need to Do This

This isn't a toy problem invented for textbooks. In banking, transaction-monitoring systems flag payments that deviate from a customer's normal behavior for human review — this is precisely why your bank sometimes calls you after an unusually large or oddly timed transaction. In space operations, ground control systems for satellites (ISRO's included) continuously receive telemetry — temperature readings, battery voltage, orientation angles — streaming down every few seconds; software watches for readings that drift outside the expected range, because a human operator cannot stare at hundreds of live numbers around the clock, and an early anomalous voltage reading can be the first sign of a fault before it becomes a failure. On a factory assembly line, a component whose electrical resistance test reads far outside the expected range gets automatically pulled aside for inspection, rather than shipped. In every one of these cases, the "normal" pattern is defined by data, and anomaly detection is the machinery that watches for departures from it.

Method 1 — The Z-Score: Counting "How Many Typical Wobbles Away"

The most natural way to say "this number is far from the rest" is to compare it to the average of the group, and then ask how far, measured in units of "typical spread." Let's build that idea from scratch using the canteen data.

First, the mean (average): add all ten values and divide by 10.

230 + 150 + 180 + 190 + 200 + 210 + 160 + 170 + 220 + 2400 = 4110, so mean = 4110 / 10 = ₹411.

Now here's the interesting part: notice that ₹411 isn't close to any of the nine "ordinary" spends (which cluster around ₹150–230) — it got pulled upward by the one outlier. Keep that observation in your back pocket; it becomes important very soon.

Next we need a number that describes how spread out the data typically is — the "typical wobble" away from the mean. For each value, compute its deviation (value minus mean). Some deviations are negative (below the mean), some positive (above it), and if you added them all up they would cancel to zero — which tells us nothing about spread. So we square each deviation first (squaring removes the negative sign and also punishes large deviations more than small ones), average those squares to get the variance, and then take a square root at the end to bring the units back to rupees instead of "rupees squared." That final square-rooted number is the standard deviation — loosely, "how far a typical value strays from the mean."

Worked Example: Computing the Z-Score by Hand

Here is every deviation and squared deviation for the ten canteen values, so you can verify each step yourself:

  • ₹150 → deviation −261 → squared 68,121
  • ₹160 → deviation −251 → squared 63,001
  • ₹170 → deviation −241 → squared 58,081
  • ₹180 → deviation −231 → squared 53,361
  • ₹190 → deviation −221 → squared 48,841
  • ₹200 → deviation −211 → squared 44,521
  • ₹210 → deviation −201 → squared 40,401
  • ₹220 → deviation −191 → squared 36,481
  • ₹230 → deviation −181 → squared 32,761
  • ₹2400 → deviation +1989 → squared 3,956,121

The nine "ordinary" squared deviations add up to 445,569 (check it: 68,121 + 63,001 + 58,081 + 53,361 + 48,841 + 44,521 + 40,401 + 36,481 + 32,761 = 445,569). Adding the outlier's contribution gives a grand total of 445,569 + 3,956,121 = 4,401,690. Dividing by n = 10 gives the variance: 4,401,690 / 10 = 440,169. Taking the square root: √440,169 ≈ 663.45. That's our standard deviation — on a typical week, canteen spending wobbles by roughly ₹663 around the mean (a number itself inflated by the very outlier we're hunting for).

Now we can define the z-score of any value x formally:

z = (x − mean) / standard deviation

For our suspect, ₹2400: z = (2400 − 411) / 663.45 = 1989 / 663.45 ≈ 2.998. The usual rule of thumb in anomaly detection is to flag anything with |z| greater than 3 — a value more than three "typical wobbles" from the mean is treated as unusual. Our outlier scores 2.998. That is agonizingly, almost comically, just under the line.

Coding the Z-Score Detector

Let's turn this into code and see what it actually returns:

def flag_by_zscore(data, threshold=3):
    n = len(data)
    mean = sum(data) / n
    variance = sum((x - mean) ** 2 for x in data) / n
    std = variance ** 0.5
    flagged = []
    for x in data:
        z = (x - mean) / std
        if abs(z) > threshold:
            flagged.append(x)
    return flagged

data = [230, 150, 180, 190, 200, 210, 160, 170, 220, 2400]
print(flag_by_zscore(data))
# Output: []

Tracing it line by line: mean becomes 411.0, variance becomes 440169.0, std becomes approximately 663.452. The loop computes a z-score for each of the ten values; every one of the nine ordinary values has |z| well under 1 (the largest, for ₹150, is 261/663.45 ≈ 0.393), and the outlier's z-score is ≈2.998 — which is not greater than the threshold of 3. Not a single value gets appended to flagged. The function returns an empty list. Our glaring, unmistakable-to-the-eye outlier of ₹2400 sailed straight through the z-score filter, undetected.

Wait — Why Didn't It Catch the ₹2400 Outlier?

Here's a misconception worth naming and correcting directly: many students assume "the z-score method will always catch an extreme outlier if I just look far enough out — three standard deviations should be plenty." That assumption is false, and our worked example proves it. The reason is that the mean and standard deviation used to judge the outlier are themselves computed from the same data that includes the outlier. The ₹2400 value doesn't just sit in the data passively waiting to be measured — it actively drags the mean upward (from roughly ₹190, the average of the nine ordinary values, up to ₹411) and inflates the standard deviation enormously (from what would be roughly ₹36 among just the ordinary nine, up to ₹663). By the time we measure "how far is 2400 from normal," the very definition of "normal" has already been distorted by the presence of the value we're trying to catch. This is sometimes called the masking effect: an outlier can mask its own detection by warping the statistics used to detect it.

There's actually a hard mathematical ceiling behind this, not just a coincidence. For any dataset of n values, using the same population-style standard deviation our code computes (dividing by n, not n−1), it can be proven that no single point's z-score can ever exceed √(n−1). The intuition: since all deviations from the mean must add up to exactly zero, one extremely large deviation forces the sum of all the other deviations to be its exact opposite — the outlier and the rest of the data are mathematically chained together. Working through that constraint algebraically (using an inequality called Cauchy–Schwarz, which you'll meet formally in later math) shows that a single point's deviation squared can never exceed (n−1) times the variance, which is exactly the bound z ≤ √(n−1). For our dataset, n = 10, so the theoretical ceiling is √9 = exactly 3. Our outlier scored 2.998 — it came astonishingly close to the mathematical maximum possible for ten data points, because the bound is tightest (closest to being reached) precisely when the "normal" values are all clustered near each other, which is exactly the case here. No matter how extreme we made that tenth value — ₹24,000, ₹2,400,000 — with only nine tightly clustered companions, its z-score could never cross 3. The z-score method has a structural weakness with small samples and single extreme outliers, and it's important to know that weakness rather than trust the threshold blindly.

Method 2 — The IQR: A Ruler the Outlier Can't Bend

We need a method that doesn't let the anomaly itself distort the yardstick used to catch it. The interquartile range (IQR) method does exactly that, because it's built from position in an ordered list rather than from an average that every value contributes to equally.

First, sort the data and find the median — the middle value. Then split the data into a lower half and an upper half. The median of the lower half is called the first quartile (Q1): a quarter of all values lie below it. The median of the upper half is the third quartile (Q3): three-quarters of all values lie below it. The gap between them, Q3 − Q1, is the interquartile range (IQR) — it measures the spread of the "middle bulk" of the data, deliberately ignoring the extreme ends. Finally, we draw two boundary "fences": anything below Q1 − 1.5×IQR or above Q3 + 1.5×IQR gets flagged as an outlier. The 1.5 multiplier is a widely used convention (it's also what draws the whiskers on a box-and-whisker plot).

Worked Example, Continued: Applying IQR to the Same Data

Sort the ten canteen values: 150, 160, 170, 180, 190, 200, 210, 220, 230, 2400. With n = 10 (even), the lower half is the first five values {150, 160, 170, 180, 190} and the upper half is the last five {200, 210, 220, 230, 2400}. Each half has exactly five values, so its median is simply the middle (3rd) one — no ambiguity here. Lower half's middle value: Q1 = 170. Upper half's middle value: Q3 = 220. So IQR = 220 − 170 = 50. The fences: lower fence = 170 − 1.5×50 = 170 − 75 = 95; upper fence = 220 + 1.5×50 = 220 + 75 = 295. Every one of the nine ordinary values (₹150–230) sits comfortably inside [95, 295]. Only ₹2400 sits outside it — spectacularly outside it, in fact. The IQR method catches immediately what the z-score method missed, precisely because Q1 and Q3 are computed from the ordered positions of the middle data, not from an average that ₹2400 could hijack.

Coding the IQR Detector

def median(lst):
    n = len(lst)
    mid = n // 2
    if n % 2 == 1:
        return lst[mid]
    else:
        return (lst[mid - 1] + lst[mid]) / 2

def flag_by_iqr(data):
    sorted_data = sorted(data)
    n = len(sorted_data)
    mid = n // 2
    lower_half = sorted_data[:mid]
    upper_half = sorted_data[mid:] if n % 2 == 0 else sorted_data[mid + 1:]
    q1 = median(lower_half)
    q3 = median(upper_half)
    iqr = q3 - q1
    lower_fence = q1 - 1.5 * iqr
    upper_fence = q3 + 1.5 * iqr
    flagged = [x for x in data if x < lower_fence or x > upper_fence]
    return flagged

data = [230, 150, 180, 190, 200, 210, 160, 170, 220, 2400]
print(flag_by_iqr(data))
# Output: [2400]

Tracing it: sorted_data becomes [150, 160, 170, 180, 190, 200, 210, 220, 230, 2400]. Since n = 10 is even, mid = 5, lower_half = [150, 160, 170, 180, 190], and upper_half = [200, 210, 220, 230, 2400]. Both halves have odd length 5, so median() returns each list's middle element directly: q1 = 170, q3 = 220. Then iqr = 50, lower_fence = 95.0, upper_fence = 295.0. The list comprehension checks all ten values against these fences; only 2400 exceeds 295. The function returns [2400] — the anomaly, correctly caught.

Seeing Both Methods at Once

The diagram below plots the actual canteen data (note the axis break, since ₹2400 is far beyond the cluster) and overlays both methods: the green band is the IQR "normal zone" bounded by the fences, and the orange dashed line marks the mean used by the z-score method.

Canteen Spending (Rs.), 10 students: IQR fences vs the Mean IQR "normal" zone: Rs.95 to Rs.295 scale break Rs.150 Rs.230 9 ordinary values, clustered Q1=170 Q3=220 fence=295 mean=411 (dragged outside the IQR zone!) Rs.2400 z=2.998 -> MISSED (threshold 3) IQR: 2400 > 295 -> FLAGGED

Notice the callout on the mean: it has been dragged so far by the ₹2400 outlier that it lands outside the very "normal zone" that the IQR method defines. That single visual is the whole lesson of this chapter — an average is not a neutral referee when the value being judged is also a contributor to that average.

Misconception #2 — "Anomaly" Doesn't Always Mean "Mistake"

A second misconception worth correcting: students often assume that flagging something as anomalous means the data point is wrong or an error to be deleted. Sometimes it is — a sensor glitch, a typo, a duplicated row. But often the anomaly is the most important, most genuine, most information-rich point in the whole dataset. Our ₹2400 canteen entry might well be legitimate: a student who paid for snacks for the whole class before a farewell party. In fraud detection, the flagged transaction is exactly the one investigators want to look at closely — deleting it would defeat the entire purpose. In manufacturing, an anomalous sensor reading might be the first evidence of a genuine defect worth fixing, not a number to throw away. Anomaly detection is not primarily a data-cleaning tool; it is a tool for directing human attention to the small number of cases that matter most, whatever the reason turns out to be.

Choosing a Method (and CBSE Exam Pointers)

The z-score method is simple, widely taught, and works well when the dataset is reasonably large and doesn't contain extreme single outliers that can distort the mean. The IQR method is what statisticians call a robust technique — a small number of extreme values cannot meaningfully shift Q1 or Q3, because quartiles depend only on rank/position in the sorted list, not on magnitude. For CBSE Computer Science and Informatics Practices, remember the key vocabulary precisely: mean, standard deviation, z-score and its threshold rule, median, quartile, interquartile range, and the term robust statistic for a measure resistant to outliers. In practice, real anomaly-detection systems (in banking, telecom, and industrial monitoring) often run several such checks together rather than relying on any single rule, precisely because — as you've now proven for yourself — no single method catches every case.

Check Your Understanding

Q1. In your own words, define anomaly detection, and give one original example (not from this chapter) each of a point anomaly and a contextual anomaly.

Q2. A cricket team's last 8 T20 innings have a mean score of 165 runs with a standard deviation of 18 runs. In their 9th match they score 210. Compute the z-score for this innings. Using the common threshold of 3, would it be flagged as anomalous?

Q3. A student's fitness band recorded daily steps for one week: 5000, 5200, 5400, 5600, 5800, 6000, 15000 (the last day was a school trekking trip). Find Q1, Q3, the IQR, and the upper fence. Would 15000 be flagged?

Q4. True or false: "If a data point's z-score does not exceed the threshold, it is definitely not an anomaly." Justify your answer using what you learned from the canteen example.

Answer key:

A1. Anomaly detection is the process of identifying data points that differ significantly from the pattern shown by most of the data. Sample point anomaly: a single ₹50,000 ATM withdrawal from an account that normally withdraws ₹2,000–5,000. Sample contextual anomaly: a body temperature of 37°C is completely normal at rest, but the same reading right after a student wins a 400m sprint (when a temporary rise is expected) could itself be flagged as unusually low for that context.

A2. z = (210 − 165) / 18 = 45 / 18 = 2.5. Since 2.5 is not greater than 3, this innings would not be flagged as anomalous by the standard threshold, even though it's clearly an excellent score.

A3. Sorted: 5000, 5200, 5400, 5600, 5800, 6000, 15000 (n = 7, odd, overall median = 5600). Lower half (excluding the overall median): {5000, 5200, 5400} → Q1 = 5200. Upper half: {5800, 6000, 15000} → Q3 = 6000. IQR = 6000 − 5200 = 800. Upper fence = 6000 + 1.5×800 = 7200. Since 15000 > 7200, it would be flagged — correctly, since it's a genuine anomaly (a trek day), not a data error.

A4. False. As the canteen example proved, an extreme outlier can distort the very mean and standard deviation used to compute its own z-score (the masking effect), keeping its z-score below the threshold even though it is obviously unusual. A point can fail to be flagged by the z-score method and still be a genuine anomaly — which is exactly why a second, more robust method like IQR is valuable as a cross-check.

Summary

  • Anomaly detection identifies data points that deviate significantly from the majority pattern; anomalies come in three types — point, contextual, and collective.
  • The z-score method measures how many standard deviations a value lies from the mean: z = (x − mean) / std, typically flagging |z| > 3.
  • In our worked example (mean ₹411, std ≈ ₹663.45), the outlier ₹2400 scored z ≈ 2.998 — just under the threshold — and was missed entirely, because the outlier itself inflated the mean and standard deviation used to judge it (the masking effect).
  • For any dataset of size n, no single point's z-score (using population standard deviation) can exceed √(n−1); for n = 10 that ceiling is exactly 3, explaining why our near-extreme outlier still slipped through.
  • The IQR method uses quartiles (Q1, Q3) computed from sorted position rather than from an average, making it robust to extreme outliers; it correctly flagged the same ₹2400 value that the z-score method missed.
  • An anomaly is not automatically an error — it is simply unusual, and often the most important data point to investigate, whether the cause is fraud, a fault, or a genuinely rare legitimate event.

Think About It

Think about this: How would you explain anomaly detection: finding the unusual to a friend who has never seen a computer? What real-world analogy would you use? Imagine you had to build a system using these concepts — what would be your first step? Try this: before moving on, write down three things you learned and one question you still have.

← Hyperparameter Tuning: The Art of Model OptimizationTime Series Analysis with Python →

Found this useful? Share it!

📱 WhatsApp 🐦 Twitter 💼 LinkedIn