guide to model evaluation eliminating bias
Guide to Model Evaluation: Eliminating Bias in Machine Learning Predictions
Explore our tutorial on model fairness to detect hidden biases in machine learning models. Understand the flaws of traditional evaluation metrics with the help of the Giskard library. Our guide, packed with examples and a step-by-step process, shows you how to tackle data sampling bias and master feature engineering for fairness. Learn to create domain-specific tests and debug your ML models, ensuring they are fair and reliable.
Data is one of the most invaluable assets in today's world, with a staggering 328.77 million terabytes generated daily, encompassing a diverse array of content, from videos and text to spoken words. This data, spanning personal and supplementary information about individuals, can unveil profound insights about a person's identity.
However, these data patterns often need a more crucial context for our behaviors and interpersonal interactions as human beings. When fed into machine learning algorithms, they perpetuate societal assumptions, generating predictions that raise legitimate concerns about privacy and fairness. These concerns extend to their impact on diverse groups of people across various facets of life, affecting things like how insurance costs are calculated, credit scores for different groups, and even health predictions.
Because of these concerns, it's important to make sure that machine learning models built with this data are fair and don't favor one group over another in ways that can cause long term harm.
This article will:
- Introduce unethical practices in machine learning.
- Develop a model for salary predictions to introduce classical model evaluation.
- Talk about the problems with traditional model evaluations that don't consider fairness.
- Introduce Giskard as a tool to ensure machine learning models are fair in their predictions.
Now, let's dive in!
☯ ️Machine Learning bias, and unethical practices: Ensuring AI Fairness
To understand the concept of data bias and its potential impact on individuals, let’s examine a scenario involving insurance payments.
Insurance provides financial security in unforeseen situations like accidents, but it has faced criticism globally for how insurers distribute premium payments across people in different geographical locations. When you pay premiums to an insurance company, they use various factors to calculate coverage, including age, gender, location and health status, through using ML to scale the process for calculating insurance premiums and coverages.
Since the data that insurers use contains human bias, they may carry assumptions using protected and proxy attribute correlations within the dataset without understanding the context. This can invariably lead to discrimination, potentially disadvantaging certain income or racial groups.
For instance, an insurance company may use ZIP codes as proxy variables to determine premium costs. However, these algorithms lack the understanding that ZIP codes can often be linked to socioeconomic factors like race and income.
Fairness Implication — This potentially leads to unfair and discriminatory pricing practices that may violate anti-discrimination laws wherever these algorithms are deployed. This also reduces transparency and accountability because it makes it difficult for people to understand why they are paying higher than other people from different zip codes.
This can happen in other domains like banking, hiring and salary distribution, education, etc. This means that there’s a need to evaluate ML models to understand how they make predictions and make them better by improving fairness.
🧪 Overview of classical Machine Learning model evaluation
Traditional model evaluation techniques tend to focus on assessing the overall predictive performance of a model without delving deeply into the fairness or potential biases associated with specific variables, including protected and proxy variables.
In many cases, classic model evaluation primarily emphasizes metrics such as accuracy, precision, recall, F1-score, and ROC AUC, among others, to gauge how well a model performs in making predictions. These metrics generally evaluate the model's overall effectiveness in terms of correctly classifying outcomes but may not thoroughly examine how the model treats different subgroups or the fairness of its predictions with respect to protected or proxy variables.
Table 1. Showing the difference between protected and proxy variables based on definition, examples and usage
| Protected Variables | Proxy Variables | |
|---|---|---|
| Definition | Sensitive attributes are often related to privacy and fairness, such as race, gender, age, or disability status. | Non-sensitive attributes that indirectly correlate with protected variables and may unintentionally introduce bias. |
| Example | - Race or ethnicity - Gender (Sex) - Age - Disability status |
- Zip code (correlated with race and income) - Education level (correlated with age) - Job title (correlated with gender) |
| Usage | - Used to assess and monitor fairness in machine learning models. - Protected from direct use to prevent discrimination. |
- May inadvertently introduce bias if not considered during model development. - Should be identified and addressed to ensure fairness. |
💰 Use Case: Evaluating a model trained on adult income data for salary prediction
To show how models might seem to perform well using standard evaluation methods but exhibit biases when fairness is taken into account, the adult income dataset from Kaggle is used.
This dataset is notorious for its inherent bias (just as in the insurance use case discussed earlier), particularly due to its imbalanced nature. It serves as an ideal example to underscore the critical significance of fairness, particularly in a sensitive domain like predicting salaries.
It is also a popular dataset for building a binary classifier that predicts if a person makes over $50,000 a year or not, given their demographic variation.
📚 Install Giskard and import libraries to evaluate a model
| pip install "giskard>=2.0.0b" -U |
What’s Giskard? Testing framework for model evaluation
Giskard is a testing framework created to reduce the risks associated with biases, performance issues, and errors, improving the reliability of machine learning models. With the aid of this tool, you can find hidden flaws in your machine learning models like performance bias, unrobustness, data leakage, overconfidence, stochasticity, and unethical behavior. Giskard helps you automatically scan your models for vulnerabilities and offers concise descriptions of these risks if they are present.
Load and Preprocess the dataset
Download the CSV file programmatically and proceed to preprocessing in the Google Colab coding environment.
| def load_data(): | |
| dataset_url="https://raw.githubusercontent.com/pooja2512/Adult-Census-Income/master/adult.csv" | |
| save_path="/content/drive/MyDrive/adult.csv" | |
| response=requests.get(dataset_url) | |
| with open(save_path, 'wb') as file: | |
| file.write(response.content) | |
| return pd.read_csv(save_path) | |
| adult=load_data() | |
| adult.head() |
The data used in this exercise was sourced from here. It contains some rows with missing values, poorly formatted column names, and certain columns that won't be necessary for our purposes.
After specifying the variables you can start preprocessing and preparing data for training.
| import numpy as np | |
| def preprocess_data(df): | |
| df = df.replace('?', np.NaN) | |
| df = df.dropna() | |
| df = df.drop(columns=drop_var) | |
| return df | |
| adult = preprocess_data(adult) |
Set constant variables you will need for splitting the data for simplicity and then split your data into training and testing.
| RANDOM_SEED=0 | |
| TEST_RATIO=0.2 | |
| X_train, X_test, y_train, y_test = train_test_split(adult.drop(columns=target), adult[target], test_size=TEST_RATIO, random_state=RANDOM_SEED) |
Classic Model Evaluation Pitfall #1: Addressing data sampling bias
Data sampling bias occurs when the data collected doesn't accurately represent the entire population you want to make predictions about. For the "Adult" dataset, one might assume that this is a fair representation of society, but when you take a closer look, you might find that certain racial groups are underrepresented or overrepresented.
Initiate bias mitigation: Wrap your Dataset with Giskard for ML model evaluation
Wrapping your dataset with Giskard is the first step towards preparing to scan your model for performance issues. Datasets represent a potential major source of bias for ML models. Bias mitigation can be done by carefully selecting features to train on.
| clean_df=pd.concat([X_test, y_test], axis=1) | |
| wrapped_data=Dataset(df=clean_df, target=target, name="income_data", cat_columns=cat_var) |
Classic Model Evaluation Pitfall #2: Difficulty in enabling efficient feature engineering based on fairness
Traditional model evaluations are blind when it comes to group disparities in predictions made for demographic groups. A model may achieve high accuracy while still treating certain groups unfairly. It doesn’t tell you much about the data it uses to come to that generalization.
Train the ML model
Here, the data is coded with OneHotCoder and then passed into the Pipeline method and trained with RandomForestClassifier.
| preprocessor=ColumnTransformer(transformers=[ | |
| ("num", StandardScaler(), num_var), | |
| ("cat", OneHotEncoder(handle_unknown="ignore", sparse=False), cat_var), | |
| ]) | |
| pipeline=Pipeline(steps=[ | |
| ("preprocessor", preprocessor), | |
| ("classifier", RandomForestClassifier()) | |
| ]) | |
| pipeline.fit(X_train, y_train) | |
| # Accuracy score. | |
| train_metric=pipeline.score(X_train, y_train) | |
| test_metric=pipeline.score(X_test, y_test) | |
| print(f'Train accuracy: {train_metric:.2f}') | |
| print(f'Test accuracy: {test_metric:.2f}') |
Output:
Ensure AI fairness: Wrap and Scan your model for ML model evaluation
Just like the dataset, Giskard library is used to wrap the model in order to prepare the scan.
| wrapped_model=Model( | |
| model=pipeline, | |
| model_type="classification", | |
| name="salary_cls", | |
| classification_labels=pipeline.classes_, | |
| feature_names=X_train.columns | |
| ) | |
| wrapped_predict=wrapped_model.predict(wrapped_data) | |
| wrapped_test_metric=accuracy_score(y_test, wrapped_predict.prediction) | |
| print(f'Wrapped Test accuracy: {wrapped_test_metric:.2f}') |
Generate a test suite from the Scan
The results generated from the scan can serve as building blocks to create a comprehensive test suite that incorporates domain-specific challenges and considerations, enhancing the overall testing process of your ML model.
| test_suite=results.generate_test_suite("My first test suite") | |
| test_suite.run() |
Output:
🤖 Conclusion
Through this guide, you've learned to scan your model and develop comprehensive test suites using the Giskard Python library. You’ve also seen how the Giskard Hub can prove to be the ideal debugging and model evaluation companion when training new ML models. Giskard's tools simplify and automate many tasks that are often missed when creating ML models.