
Image by Editor | Midjourney
Yellowbrick is a visualization package that extends the scikit-learn API to incorporate visual diagnostics in your machine learning workflow. It works as a diagnostic tool, helping data scientists understand model selection, hyperparameter tuning, and evaluation. By combining scikit-learn with matplotlib, Yellowbrick creates a suite of visual diagnostic tools called “visualizers” that help develop better machine learning models.
The package integrates seamlessly with:
- scikit-learn for machine learning algorithms
- matplotlib for visualization base
- numpy for numerical computations
- pandas for data manipulation
Let’s get started with setting up Yellowbrick in your Python environment.
Installation Guide
You can install Yellowbrick using pip:
pip install yellowbrick
Or using conda:
conda install -c conda-forge yellowbrick
You may be tempted to follow the guidelines presented on Yellowbrick’s Quick Start guide when installing, but if you check the current package repositories, you will see that the Yellowbrick package is now actively maintained on the conda-forge channel. I would recommend cross checking both resources if you need additional assistance for your set up.
Healthcare Provider Fraud Detection Dataset
To demonstrate some of Yellowbrick’s functionalities for classification tasks, we’ll be working with the Healthcare Provider Fraud Detection Analysis dataset from Kaggle. You can download all the files from this site and the code blocks that follow should run smoothly once these files are placed in the same working directory as your coding platform/notebook. The dataset contains information about healthcare providers, including:
- Beneficiary details (demographics, chronic conditions, etc.)
- Inpatient claims
- Outpatient claims
- Labels indicating potentially fraudulent providers
The Kaggle site has 8 files you can download, but we will be focusing our analysis on the following four main files which have matching target labels to assist our supervised learning:
- Train dataset (5,410 rows) – Contains provider IDs and fraud labels
- Train Beneficiary dataset (138,556 rows) – Patient information
- Train Inpatient dataset (40,474 rows) – Hospital admission claims
- Train Outpatient dataset (517,737 rows) – Outpatient visit claims
Now that we have our data sources identified, let’s explore how we can use Yellowbrick to help us detect fraudulent providers.
Our Classification Task
We’re tackling a binary classification problem to identify potentially fraudulent healthcare providers. Let’s first understand our target variable distribution using Yellowbrick’s ClassBalance visualizer.
# Import necessary libraries
import pandas as pd
import numpy as np
from yellowbrick.target import ClassBalance
# Load the training dataset
df_train = pd.read_csv('Train-1542865627584.csv')
df_train.head(5)
This code block shows us our first glimpse of the data, revealing a binary target variable ‘PotentialFraud’ with ‘Yes’ and ‘No’ categories:
Provider PotentialFraud 0 PRV51001 No 1 PRV51003 Yes 2 PRV51004 No 3 PRV51005 Yes 4 PRV51007 No
To better understand the class distribution:
print("\nClass Distribution:")
print(df_train["PotentialFraud"].value_counts())
Output:
Class Distribution: No 4904 Yes 506
This reveals a significant class imbalance:
- Non-fraudulent providers: 4,904 cases (90.6%)
- Potentially fraudulent providers: 506 cases (9.4%)
The ClassBalance visualizer from Yellowbrick helps us quickly visualize this with minimal code:
# Visualize class balance visualizer = ClassBalance() visualizer.fit(df_train['PotentialFraud']) visualizer.show()

Image By Author
This imbalance is typical in fraud detection scenarios, where fraudulent cases are naturally less common than legitimate ones.
Addressing Class Imbalance
A key challenge in fraud detection is handling imbalanced datasets where legitimate cases far outnumber fraudulent ones. In our healthcare dataset, with only 9.4% of providers flagged as potentially fraudulent, we need to carefully consider how this imbalance might affect our modeling efforts.
There are several strategies to address class imbalance, and Yellowbrick’s visualization capabilities can help us understand the effects of these different approaches. Let’s explore three common resampling techniques:
- Random Oversampling: Creates new samples of the minority class (fraudulent providers) by randomly duplicating existing cases until classes are balanced
- Random Undersampling: Randomly removes samples from the majority class (non-fraudulent providers) until classes are balanced
- SMOTE (Synthetic Minority Over-sampling Technique): Creates synthetic examples of the minority class based on feature space similarities between existing minority examples
Let’s visualize how each of these techniques transforms our class distribution:
import pandas as pd
import numpy as np
from yellowbrick.target import ClassBalance
from imblearn.over_sampling import RandomOverSampler, SMOTE
from imblearn.under_sampling import RandomUnderSampler
import matplotlib.pyplot as plt
# Load data
df_train = pd.read_csv('Train-1542865627584.csv')
X = pd.get_dummies(df_train['Provider']) # Convert categorical to numeric for SMOTE
y = df_train['PotentialFraud']
# Create the different sampling objects
ros = RandomOverSampler(random_state=42)
rus = RandomUnderSampler(random_state=42)
smote = SMOTE(random_state=42)
# Apply the different sampling techniques
X_ros, y_ros = ros.fit_resample(X, y)
X_rus, y_rus = rus.fit_resample(X, y)
X_smote, y_smote = smote.fit_resample(X, y)
# Create visualization
fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(15, 5))
# Random Oversampling visualization
visualizer1 = ClassBalance(ax=ax1, labels=['Non-Fraud', 'Potential Fraud'])
visualizer1.fit(y_ros)
ax1.set_title('Random Oversampling')
# Random Undersampling visualization
visualizer2 = ClassBalance(ax=ax2, labels=['Non-Fraud', 'Potential Fraud'])
visualizer2.fit(y_rus)
ax2.set_title('Random Undersampling')
# SMOTE visualization
visualizer3 = ClassBalance(ax=ax3, labels=['Non-Fraud', 'Potential Fraud'])
visualizer3.fit(y_smote)
ax3.set_title('SMOTE')
plt.tight_layout()
plt.show()

Image By Author
The visualizations above illustrate how each resampling technique affects our class distribution. Let’s analyze each resampling approach in detail:
1. Random Oversampling
- Original distribution: 4,904 non-fraud vs 506 fraud cases
- After resampling: 4,904 cases in each class
- Impact: Creates 4,398 new fraud cases by randomly duplicating existing ones
- Consideration: While this maintains all original data, repeated samples might lead to overfitting as the model sees the same fraud patterns multiple times
2. Random Undersampling
- Original distribution: 4,904 non-fraud vs 506 fraud cases
- After resampling: 506 cases in each class
- Impact: Removes 4,398 non-fraud cases to match minority class size
- Consideration: While this creates perfect balance, we lose potentially valuable information about legitimate provider behavior patterns
3. SMOTE (Synthetic Minority Over-sampling Technique)
- Original distribution: 4,904 non-fraud vs 506 fraud cases
- After resampling: 4,904 cases in each class
- Impact: Creates 4,398 new synthetic fraud cases based on feature similarities
- Consideration: Offers more diverse fraud patterns than simple oversampling, but synthetic cases might not always reflect real-world fraud scenarios
These resampling techniques provide different approaches to addressing our class imbalance challenge.
Conclusion
Yellowbrick’s seamless integration with essential data science tools like scikit-learn, pandas, and imbalanced-learn allows for efficient visual diagnostics while maintaining a clean, intuitive workflow. What sets Yellowbrick apart is its ability to combine statistical insights with clear visualizations. The ClassBalance visualizer, paired with various resampling techniques, helps us not just identify but also address class imbalance challenges through intuitive visual representations.

(this is my first time using this lib.)
X_smote, y_smote = smote.fit_resample(X, y) error:
TypeError: numpy boolean subtract, the `-` operator, is not supported, use the bitwise_xor, the `^` operator, or the logical_xor function instead.
Also of note: explicitly mentioning the need to install ‘imbalanced-learn’ will help.
Hi brian…The error message you encountered:
“`
TypeError: numpy boolean subtract, the `-` operator, is not supported, use the bitwise_xor, the `^` operator, or the logical_xor function instead.
“`
suggests that there might be an issue with the data type of `X` or `y` when using **SMOTE** from `imbalanced-learn`. This commonly occurs when:
– `y` contains boolean values (`True`/`False`) instead of integers (0,1).
– `X` has an unexpected dtype, such as a boolean array.
– There is an incompatibility between the `imbalanced-learn` and `numpy` versions.
### **Steps to Fix**
#### **1. Ensure y is Integer-Encoded**
Convert the target variable `y` to integer type explicitly before applying SMOTE:
“`python
y = y.astype(int)
“`
or, if `y` is a Pandas Series:
“`python
y = y.astype(‘int’)
“`
#### **2. Verify X and y Data Types**
Print their types to check for unexpected dtypes:
“`python
print(X.dtype, y.dtype)
“`
If `X` contains boolean values, convert them to integers:
“`python
X = X.astype(int)
“`
#### **3. Upgrade `imbalanced-learn` and Dependencies**
Ensure you have the latest compatible versions of `imbalanced-learn` and `numpy`:
“`bash
pip install –upgrade imbalanced-learn numpy
“`
#### **4. Ensure `imbalanced-learn` is Installed**
If `imbalanced-learn` is not installed, explicitly install it:
“`bash
pip install imbalanced-learn
“`
Then import and verify:
“`python
import imblearn
print(imblearn.__version__)
“`
#### **5. Use `ColumnTransformer` if Needed**
If `X` is a DataFrame with mixed types (numerical and categorical), preprocess it before using SMOTE:
“`python
from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import StandardScaler, OneHotEncoder
# Example preprocessing
preprocessor = ColumnTransformer(
transformers=[
(‘num’, StandardScaler(), numeric_features), # Scale numerical columns
(‘cat’, OneHotEncoder(handle_unknown=’ignore’), categorical_features) # Encode categorical features
]
)
X_transformed = preprocessor.fit_transform(X)
“`
Then apply SMOTE to `X_transformed` instead of `X`.
#### **6. Apply SMOTE Again**
Now retry applying SMOTE:
“`python
from imblearn.over_sampling import SMOTE
smote = SMOTE(random_state=42)
X_smote, y_smote = smote.fit_resample(X, y)
“`