I built a decision tree to classify beer styles by their flavor attributes - bitterness, sweetness, that kind of thing - and it landed at 59% accuracy. My first reaction was that I needed to fix it. After sitting with it for a while, I realized the better question was what that number was actually telling me.

Accuracy isn't the whole story

59% sounds mediocre by itself. But this was a multi-class problem across a lot of beer styles, and several of them share overlapping flavor profiles by design. The model separated IPAs and Sours well, with precision above 0.65 for both, but struggled with Lambic and Porter. That's not the model failing randomly. It's picking up on something true - those styles genuinely taste more alike than an IPA and a Porter do.

The confusion matrix told me more than the accuracy score did

Early on I was treating the accuracy score as the main result. The confusion matrix ended up being more useful. Strong values down the diagonal for the styles that are easy to tell apart, and real overlap for the ones that aren't, gave a more honest picture than one summary number could. It confirmed that flavor attributes alone can't fully separate every beer category, and that's a real limitation, not a bug.

Why this matters beyond beer

This is a pattern I keep running into outside of this project too. A model's job isn't to hit some arbitrary accuracy target - it's to be honest about what the data can and can't explain. An imperfect model that's upfront about where a domain gets genuinely ambiguous is more useful than an inflated one that quietly memorized noise in the training set.

What I'd try next

If I revisit this, I'd add features beyond taste - brewing method, ABV, regional style conventions - to help separate the harder categories. But I'd still rather report a 59% model that's honest about its limits than a 95% one that's just memorized the training set.

See the full project →