Categorical Naive Bayes on a Real Dataset Practice Problem
This data science coding problem helps you practice Naive Bayes, categorical naive bayes on a real dataset, and implementation skills. Read the problem statement, write your solution, and strengthen your understanding of Naive Bayes.
- Problem ID: 196
- Problem key: 196-categorical-naive-bayes-on-a-real-dataset
- URL: https://datacrack.app/solve/196-categorical-naive-bayes-on-a-real-dataset
- Difficulty: medium
- Topic: Naive Bayes
- Module: Supervised Learning
Problem Statement
# 🧩 Categorical Naive Bayes on a Real Dataset
---
### 🎯 Goal
Train and evaluate sklearn's `CategoricalNB` on the Iris dataset using the same categorical Naive Bayes ideas from the previous problems.
---
### 📖 Introduction
All earlier Naive Bayes problems used categorical feature values such as `red`, `blue`, `small`, and `large`.
So this real-dataset problem should use a categorical Naive Bayes model too.
The Iris dataset has real-valued measurements:
- sepal length
- sepal width
- petal length
- petal width
`CategoricalNB` expects categorical inputs, not raw continuous measurements. To keep the problem connected to what we learned, we first convert each numeric feature into bins such as low, medium, and high.
Then the model can learn categorical likelihoods from those bins:
$$
P(feature\_bin\mid class)
$$
This problem does **not** use `GaussianNB`, because Gaussian Naive Bayes assumes continuous features follow a bell-shaped distribution inside each class. That is a different Naive Bayes variant and has not been taught in this sequence.
---
### 💻 Task
Implement `categorical_naive_bayes_on_iris(test_size=0.3, random_state=0)`.
Your function should:
- Load the Iris dataset.
- Split it into train and test sets using `stratify=y`.
- Convert numeric features into 3 ordinal bins using `KBinsDiscretizer(n_bins=3, encode="ordinal", strategy="quantile")`.
- Fit the discretizer only on `X_train`. This means it learns the bin boundaries, such as what counts as low, medium, and high, from the training data only.
- Use the fitted discretizer to transform both `X_train` and `X_test`. This means the test data follows the same binning rules learned from the training data.
- Train sklearn's `CategoricalNB` on the binned training data.
- Predict the binned test data.
- Return train size, test size, accuracy, the first five predicted class names, and all class names.
Round accuracy to 6 decimals.
---
### 📥 Input / 📤 Output
**Input:** `test_size` and `random_state`.
**Output:**
```python
{
"train_size": ...,
"test_size": ...,
"accuracy": ...,
"first_five_predictions": [...],
"classes": [...]
}
```
---
### 🧩 Starter Code
```python
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.naive_bayes import CategoricalNB
from sklearn.preprocessing import KBinsDiscretizer
from sklearn.metrics import accuracy_score
def categorical_naive_bayes_on_iris(test_size=0.3, random_state=0):
# Your code here
pass
```
---
### 💡 Example
```python
categorical_naive_bayes_on_iris(test_size=0.3, random_state=0)
```
Expected output:
```python
{
"train_size": 105,
"test_size": 45,
"accuracy": 0.977778,
"first_five_predictions": ["virginica", "virginica", "setosa", "setosa", "versicolor"],
"classes": ["setosa", "versicolor", "virginica"]
}
```
---
### ⚠️ Common Mistakes
- Using `GaussianNB` even though this sequence taught categorical Naive Bayes.
- Fitting the binning step on the test set separately.
- Forgetting to transform the test data with the training discretizer.
- Returning numeric class IDs instead of class names.
- Splitting without `stratify=y`, which can change class balance.