The situation
An energy retailer with 900,000 residential customers runs a support desk that takes about 250 tickets a day. Someone reads each one and files it into one of twelve queues: billing, tariff changes, meter faults, new connections, moving home, payment difficulty, solar feed-in, outages, complaints, and three smaller ones. Filing by hand takes two people most of a morning, and the proposal on the table is a text classifier that reads the ticket and picks the queue.
The training data is an export of 40,000 tickets from the last four years. Each row holds the text the customer typed and the queue it ended up in. That looks like a labelled dataset, and in the loosest sense it is. Four details about how it came to exist change the picture.
- Three people did the filing. They alternated across four years, nobody ever checked anyone else’s work, and no ticket carries more than one label. There was never a written definition of any queue. Each new filer learned by watching the last one.
- The labels are lopsided. Billing holds 12,400 tickets and meter faults 11,900, which is 61 per cent of the export between them. Three queues hold fewer than 300 each. Payment difficulty, the queue that routes a customer in financial hardship to a specialist team, holds 214.
- One queue changed meaning halfway through. Billing was split into billing and tariff changes at the start of year three. The 18,000 tickets already filed were never revisited, so the same words sit under two different labels depending on when they arrived.
- Only one channel produced tickets. The web form did. Phone calls were logged in a separate system that was retired, and the interpreter line and the accessibility line have never created a ticket in this export at all.
The training budget is approved and the data science contractor starts on Monday. Nobody has yet asked whether the data supports the model.
What actually matters
Start with the four properties the AI Practitioner material asks you to recognise when it talks about the “characteristics of datasets”: inclusivity, diversity, curated data sources, and balanced datasets. They sound like the same idea said four ways. They are four separate questions with four separate answers.
Inclusivity asks whether every group the model will serve appears in the data it learns from. Not every group in the world, every group the model will be pointed at. This retailer’s classifier will read tickets from customers who ring the interpreter line, because the plan is to route those into the same twelve queues once the phone channel is connected. Those customers contributed nothing to the export. Diversity asks about the spread of situations rather than people: how many ways a problem gets described, how many seasons and tariff changes and billing cycles the data covers, how many channels and phrasings and lengths. A set of 40,000 tickets all written into one web form in one language over four calm years is narrow even where it is large. Curated data sources asks where each example came from, who produced it, and on what terms it may be used. That means provenance you can state, a licence you can point at, and a record of collection rather than an export somebody found on a share. Balanced datasets asks about the spread across the labels themselves, and it is the one this export fails most visibly at 12,400 against 214.
Then separate two defects that get discussed as though they were one. Class imbalance is about how many examples sit under each label. Label quality is about whether the label on an example is right. A perfectly balanced set with unreliable labels teaches a model the wrong answers with great confidence. A set with impeccable labels and no examples of payment difficulty produces a model that is accurate on average and useless for the customers who most need the routing to work. Three filers with no written definitions and no adjudication is a label-quality problem; 214 tickets in a queue is a balance problem. Resampling does nothing for the first and relabelling does nothing for the second.
That leads into bias and fairness, which are the words this whole area is filed under. Bias here means the model is systematically wrong in a particular direction, and a model trained on this export inherits its skew rather than inventing one. Fairness asks whether the impacts land equitably across the groups the model serves. Put them together and the effect on demographic groups becomes concrete. A classifier that has seen almost no tickets from the interpreter line will misroute those customers more often than it misroutes anyone else. The overall accuracy figure will not show it, because they are too few in the test set to move the average. The consequence is not an abstraction. A misrouted payment-difficulty ticket sits in a general queue with a five-day response while somebody’s supply is at risk.
One instinct has to be named and refused before it is acted on. Removing the attribute that identifies the group, so the model cannot see it, is fairness-through-unawareness, and it fails twice over. The model finds proxies anyway (postcode, tariff type, message length, the phrasing of a translated sentence), so the skew survives the deletion. Worse, the attribute you deleted is the one you needed in order to measure whether anything was wrong. Keep it, restrict who can read it, and use it to check the model.
Finding all of this out is cheap next to acting on it. A day of profiling and a small relabelling audit cost a fraction of a fortnight’s training run plus the rework when a model that scores well in testing routes hardship cases into the wrong queue.
What we’ll filter on
- Inclusivity: does every group the model will serve appear in the data, in enough volume to be learned from and measured on?
- Diversity: does the data cover the range of situations, phrasings, channels, and time periods the model will meet in production?
- Provenance: do we know where each example came from and whether we are permitted to train on it?
- Balance: how far apart are the largest and smallest label counts, and is the smallest one large enough to learn?
- Label quality: how often do two people who read the same example agree on its label, and has the meaning of any label changed over time?
- Measurability: after the fix, can we still slice results by the attribute we were worried about?
The landscape
The options divide into two groups: ways to find out what is in the data, and things you can do about what you find. Work the first group before spending anything on the second.
Profiling the raw export
AWS Glue DataBrew runs a visual profile over a dataset without anybody writing code: row counts, value distributions per column, missing values, duplicates, and the shape of each field. On this export it produces the twelve label counts, the tickets submitted twice, and the rows where the text field is empty. Run per year, it also makes the year-three label change visible as a distribution that shifts. AWS Glue itself is where the cleaning becomes repeatable: a job that applies the same transformations every time, with the Data Catalog holding the schema so the dataset has a definition rather than a filename.
Measuring the skew
Two measurements are worth knowing by name. Class imbalance compares the number of examples in one group with the number in another, and reported as a ratio it is the blunt instrument this export needs: 12,400 to 214 is roughly 58 to 1. Difference in proportions of labels compares the rate at which a label appears in one group against the rate in another. If tickets from one postcode band are filed to complaints twice as often as tickets from another, that difference is in the training data before any model exists, and the model will reproduce it. Both are arithmetic over the raw data and need no trained model. Amazon SageMaker Clarify shipped them as a managed pre-training bias job. That managed service moved to maintenance in June 2026, so a new build computes the same two numbers in its own data pipeline. It is a few lines of aggregation rather than a project. The definitions are what a practitioner is expected to recognise, and they outlive the service that packaged them.
Slicing by group
Subgroup analysis means splitting the data by an attribute and computing the same measure separately for each slice, instead of trusting one number over everybody. Before training it answers how many examples each group contributed. After training it answers whether accuracy is worse for one group than another, which a single overall accuracy figure will hide whenever the group is small. Amazon SageMaker Data Wrangler is the exploration surface for this: import the export, join it to the customer attributes, and look at distributions and per-slice counts before a training job is ever configured. Human audits sit alongside: a person reading a sample of tickets and the routing decisions made on them, which catches the failures nobody thought to compute.
Checking the labels
The material calls this “analyzing label quality”, in its own spelling, and the method is older than machine learning. Take a stratified sample across the twelve queues, write down what each queue actually means first, then have more than one person label the same tickets independently and measure how often they agree. Disagreement between two careful people is the ceiling on what a model can achieve, because the training data cannot be more consistent than the humans who produced it. Amazon SageMaker Ground Truth is the AWS service for running that work: a labelling job with several workers per item, automatic consolidation of their answers, and an adjudication step where contested items go to a reviewer. The workforce can be your own staff, a vendor, or Amazon Mechanical Turk. Labels you already own are still cheaper than labels you buy, and this is the case where the ones you own need checking before they are trusted.
Collecting more of what is missing
The only fix for a group that is absent is to get examples of it. For the interpreter line that means connecting the channel to the ticketing system and waiting a quarter for real tickets to accumulate. It is the slowest option on this list and the only one that closes a coverage gap, because no statistical treatment can create examples of a kind of customer who never appears.
Resampling or reweighting
For a label that is present but rare, two standard adjustments help. Resampling changes the training set: duplicate or synthesise more of the small class, or discard some of the large one, so the model sees the rare label often enough to learn it. Reweighting leaves the data alone and tells the training process that mistakes on the rare class count for more. Neither adds information; both stop the model from taking the easy route of never predicting payment difficulty at all. Both also make the training set unrepresentative on purpose, so the held-out set used for measurement has to stay at real-world proportions or the reported numbers become fiction.
Accepting the skew and writing it down
Sometimes the right answer is to train on the data you have and be explicit about what it cannot do. Amazon SageMaker Model Cards are the AWS place to record that: intended use, the data the model was trained on, how it was evaluated, per-group results, and the limitations. A documented limitation lets an operations manager decide that interpreter-line tickets keep going to a person for now. An undocumented one becomes a surprise six months later.
Buying a curated source
AWS Data Exchange is the marketplace for subscribing to third-party datasets with a licence and a stated provenance attached, delivered into your account and refreshed on a schedule. Nobody sells another retailer’s support tickets, so it does not solve this particular gap. It solves the neighbouring one. Reference data by postcode, demographic or economic, gives the subgroup analysis something to slice on. For teams building on public corpora it is also where curated data sources arrive with paperwork, rather than as a scrape whose terms nobody has read.
Deleting the attribute
Drop the language flag, the postcode, or the channel from the training data and the model cannot discriminate on it. That is fairness-through-unawareness and it does not work. Proxies remain, so the model reproduces the same skew through other columns, and the deletion removes the ability to detect it. This one appears on the list so it can be recognised and rejected, not chosen.
Evaluation
Side by side
| Response | Closes a coverage gap | Fixes a rare label | Fixes bad labels | Cost and time | Skew stays measurable |
|---|---|---|---|---|---|
| Collect more from the missing group | ✓ | ✓ | ✗ | High; a quarter or more | ✓ |
| Resample or reweight | ✗ | ✓ | ✗ | Low; a training-config change | ✓ |
| Relabel with adjudication | ✗ | ✗ | ✓ | Moderate; days of people’s time | ✓ |
| Accept and document in a Model Card | ✗ | ✗ | ✗ | Low; hours of writing | ✓ |
| Buy a curated source | ✓ where one exists | ✓ where one exists | ✗ | Subscription, plus integration | ✓ |
| Delete the attribute | ✗ | ✗ | ✗ | Low, and it makes things worse | ✗ |
Which defect you actually have
The solution
Nothing here says do not build the classifier. It says the export is two problems and a gap, and each of the three has an owner and a different fix.
Profile before anything else. A DataBrew profile over the export costs a day and settles the arguments. Run it once for the whole set and once per year, and it hands back the twelve counts, the duplicates, the empty text fields, and the year-three definition change as a step in the distribution. The 18,000 tickets filed before billing was split are a known defect after that, not a mystery. Most of them can be re-filed by rule, since a ticket mentioning a tariff switch belongs in the new queue, with the residue going to people.
Treat label quality as a separate spend and do it first. Write a one-paragraph definition of each of the twelve queues, agreed by the people who work them, before anybody labels anything. Then run a stratified sample through Ground Truth with three workers per ticket and an adjudication step for the contested ones. The output is two things: a corrected sample, and a number saying how often careful people agree. That number is the ceiling. A model trained to reproduce labels that humans agree on 71 per cent of the time will not reach 90 per cent accuracy. The accuracy figure the contractor reports means nothing until it is compared with that ceiling.
The coverage gap cannot be fixed by modelling. No amount of resampling produces a ticket from a customer who uses the interpreter line, because the export contains none. Two honest options exist. Connect the phone and interpreter channels to the ticketing system, wait a quarter, and train on data that includes them. Or scope the model to web-form tickets, say so in writing, and keep the other channels on human routing until there is data. Choosing the second and forgetting to say so is how a coverage gap becomes a customer complaint.
Balance is the cheapest of the three to address. Reweight the small classes so the model is penalised properly for missing them, and keep a held-out set at real-world proportions so the reported numbers describe production rather than the adjusted training set. For payment difficulty at 214 examples, expect a weak classifier for a while and design around it: route on confidence, and send anything the model is unsure of to a person. Under-routing a hardship case is a worse error than over-routing one, and the threshold should reflect that rather than being left at the default.
Keep the attributes you need in order to check. Language flag, channel, and postcode band stay in the evaluation data, access-controlled, because subgroup analysis needs something to slice on. Delete them and the model still discriminates through proxies while the measurement becomes impossible.
Write the Model Card at the same time as the model. Intended use, the four years and one channel the data came from, the groups it under-represents, per-queue and per-group accuracy, and the routing rule for low-confidence cases. The business question that started this was reducing two people’s morning of filing, and a card that says the model handles nine queues well, three poorly, and one channel not at all still answers that question honestly.
Worked example
The audit is 600 tickets, 50 from each queue, labelled independently by three people who have read the new definitions. That is 1,800 judgements, roughly a day and a half of two people’s time plus a reviewer, and it is the cheapest useful thing this team can buy.
Suppose the result comes back like this. All three agree on 426 of the 600 tickets, which is 71 per cent. Agreement is above 90 per cent for meter faults, outages, and new connections, where the customer’s words map onto one queue. It collapses to 46 per cent for billing against tariff changes, which is the split that happened in year three and was never applied backwards. Payment difficulty and complaints are confused with each other in a third of their cases, because a customer who cannot pay usually complains in the same sentence.
Read that as three findings rather than one score. The high-agreement queues are fit to train on now. The billing and tariff-changes boundary is a definition problem, and the fix is a rule applied to the 18,000 old tickets rather than more training data. The payment-difficulty confusion is the one with a customer at the end of it. Two hundred and fourteen examples, split across a boundary people cannot see, is not something a model will resolve on its own. That queue keeps a human in the loop and gets a collection effort behind it.
None of this required a training run. The class-imbalance ratio came out of a profile, the disagreement rate out of a day and a half of reading, and between them they changed what gets built.
What’s worth remembering
- The characteristics of datasets worth checking before training are inclusivity (every group the model will serve appears), diversity (the range of situations is covered), curated data sources (provenance and permission are known), and balanced datasets (examples are spread across the labels).
- Class imbalance and label quality are separate defects with separate fixes: resampling and reweighting address a rare label, and relabelling with adjudication addresses labels that are wrong.
- A coverage gap cannot be closed by any statistical adjustment, because no technique invents examples of a group that never appeared; collect the data or buy a curated source.
- Class imbalance and difference in proportions of labels are pre-training measurements over raw data, so a skew can be found and quantified before a model exists.
- Subgroup analysis is what makes bias visible, which is why deleting a protected attribute is fairness-through-unawareness: proxies keep the skew and the deletion removes the measurement.
- What a model can achieve is capped by how often careful people agree on the labels, so analysing label quality on a small stratified sample belongs before the training budget, not after it.