Breast Cancer Prediction with ML
Building Your First Model in ⏱ 30 Minutes
Disclaimer: This article is for academic study only and not for clinical use. The model discussed here is introductory and requires further refinement.
📚 Background
This article is primarily for researchers interested in integrating AI and machine learning into their research. It provides a step-by-step guide, taking you from zero to a basic understanding of machine learning techniques using an approachable and practical method.
🤔 Why Machine Learning?
In healthcare and medical research, we often need models that can help predict outcomes, such as diagnosing breast cancer, predicting adverse drug events, or evaluating treatment responses. Traditionally, statistical methods have been used effectively for correlations and predictions. However, when datasets involve multiple dimensions and complex interactions, traditional methods become limited. This complexity is precisely where machine learning excels.
Traditionally, statistical methods have been used effectively for correlations and predictions. However, when datasets involve multiple dimensions and complex interactions, traditional methods become limited. This complexity is precisely where machine learning excels.
🧠 What’s the Problem We’re Solving?
When beginning your machine learning journey, defining a clear problem statement is critical. Here, our goal is simple: to predict if a breast cancer tumor is malignant or benign. This makes it a binary classification problem — one of the most common and fundamental machine learning tasks.
🚀 Why Choose XGBoost?
We recommend using XGBoost (Extreme Gradient Boosting) for this task due to its excellent balance between accuracy and speed. XGBoost works by creating multiple simple models (decision trees) sequentially, with each new tree learning from the mistakes of the previous ones. Think of it as having a team of smart decision-makers collaborating to achieve a more accurate result.
Other methods you could explore include Logistic Regression, Random Forest, and Deep Learning. However, XGBoost often provides superior performance, making it ideal for beginners.
🛠️ Step-by-Step Guide to Building Your ML Model
Step 1 — Obtain Source Data📥
Download the dataset from Breast Cancer Wisconsin Diagnostic Data.
Get Samuel Chan’s stories in your inbox
Join Medium for free to get updates from this writer.
Clean, quality data is crucial — “garbage in, garbage out.” Fortunately, this dataset is already cleaned, which saves significant effort in feature engineering, a process that can often take up most of your time (>90%).
Step 2 — Setup the ML Environment 💻
The simplest environment to get started quickly is Google Colab, a free Python environment:
Step 3 — Load Required Libraries 📚
In Google Colab, most essential libraries are pre-installed, saving you time.
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.metrics import roc_curve, auc, precision_recall_curve, f1_score, confusion_matrix
import xgboost as xgb
from xgboost import XGBClassifier, plot_treeIf you use another Python environment, run the following command:
pip install numpy pandas matplotlib scikit-learn xgboostStep 4 — Upload & Load Data 📂
Drag and drop the wdbc.data file into the Colab sidebar, then load it into a Pandas DataFrame—a powerful tool for data manipulation in Python.
# Define the column names as provided from dataset URL
header = [
"ID", "Diagnosis",
"radius1", "texture1", "perimeter1", "area1", "smoothness1", "compactness1", "concavity1", "concave_points1", "symmetry1", "fractal_dimension1",
"radius2", "texture2", "perimeter2", "area2", "smoothness2", "compactness2", "concavity2", "concave_points2", "symmetry2", "fractal_dimension2",
"radius3", "texture3", "perimeter3", "area3", "smoothness3", "compactness3", "concavity3", "concave_points3", "symmetry3", "fractal_dimension3"
]
# Read the dataset without headers and assign the column names
df = pd.read_csv("wdbc.data", header=None, names=header)Step 5 — Visualize Your Data 📈
Understanding data distribution is crucial. Check if your data is balanced (similar numbers of benign and malignant cases). An imbalanced dataset might require additional preprocessing.
# Calculate the counts of unique Diagnosis values
diagnosis_counts = df["Diagnosis"].value_counts()
# Plot the bar chart
plt.figure(figsize=(8, 6))
diagnosis_counts.plot(kind='bar', color=['skyblue', 'salmon'])
plt.title("Distribution of Diagnosis")
plt.xlabel("Diagnosis")
plt.ylabel("Count")
plt.xticks(rotation=0) # Keeps the labels horizontal
plt.show()Step 6 — Data Preprocessing 🧹
- Drop unnecessary fields.
- Map your prediction target from
B(Benign) →0andM(Malignant) →1. - Separate your dataset into features (
X) and target (y).
# --------------------------------------------------
# Preprocess the Data
# --------------------------------------------------
# 'ID' is a unique identifier so we drop it.
df = df.drop(columns=["ID"])
# Convert Diagnosis to binary numeric: B -> 0, M -> 1.
df['Diagnosis'] = df['Diagnosis'].map({'B': 0, 'M': 1})
# Define features X (all columns except Diagnosis) and target y (Diagnosis).
X = df.drop(columns=["Diagnosis"])
y = df["Diagnosis"]Step 7 — Split Your Dataset and Run Training 🧩
- Split data into 70% training and 30% testing using a random split.
- !!! Important: For time-series data, do not use random splits; instead, use chronological splits.
- Train your model quickly using XGBClassifier’s
.fit()function.
# --------------------------------------------------
# Split Data: 70% Training and 30% Testing
# --------------------------------------------------
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
# --------------------------------------------------
# Train XGBoost Classifier
# --------------------------------------------------
model = XGBClassifier(use_label_encoder=False, eval_metric='logloss', random_state=42)
model.fit(X_train, y_train)Step 8 — Generate Predictions 🔮
- Use
.predict()on your test set to evaluate your model's performance.
# --------------------------------------------------
# Generate Predictions and Metrics
# --------------------------------------------------
# Get predicted probabilities for the positive class.
y_proba = model.predict_proba(X_test)[:, 1]
# Get predicted class labels.
y_pred = model.predict(X_test)Step 9 — Evaluate with Confusion Matrix 📊
The confusion matrix reveals true positives, true negatives, false positives, and false negatives, helping you understand your model’s accuracy.
# -------------------------------
# Plot Confusion Matrix
# -------------------------------
cm = confusion_matrix(y_test, y_pred)
plt.figure(figsize=(6, 6))
plt.imshow(cm, interpolation='nearest', cmap=plt.cm.Blues)
plt.title('Confusion Matrix')
plt.colorbar()
tick_marks = np.arange(2)
plt.xticks(tick_marks, ['B (0)', 'M (1)'], rotation=45)
plt.yticks(tick_marks, ['B (0)', 'M (1)'])
thresh = cm.max() / 2.
for i in range(cm.shape[0]):
for j in range(cm.shape[1]):
plt.text(j, i, format(cm[i, j], 'd'),
horizontalalignment="center",
color="white" if cm[i, j] > thresh else "black")
plt.ylabel('True Label')
plt.xlabel('Predicted Label')
plt.tight_layout()
plt.show()From our results:
- Correct Predictions = 105 (TP) + 61 (TN)
- Incorrect Predictions = 3 (FP) + 2 (FN)
Accuracy: 97% 🎯 (You shall be happy if your Real-world initial accuracy above 70%)
Step 10 — Additional Model Evaluation 📉
Accuracy alone can be misleading — it doesn’t always tell the whole story, especially when dealing with imbalanced datasets. That’s why it’s essential to explore other evaluation metrics to better understand your model’s performance.
- ROC Curve (Receiver Operating Characteristic): This curve plots the True Positive Rate (Sensitivity) against the False Positive Rate (1 — Specificity). The closer the curve is to the top-left corner, the better the model is at distinguishing between classes. The Area Under the Curve (AUC) gives you an aggregate measure of performance — 1.0 means perfect, 0.5 means no better than random guessing.
# -----------------------
# Plot ROC Curve
# -----------------------
fpr, tpr, _ = roc_curve(y_test, y_proba)
roc_auc = auc(fpr, tpr)
plt.figure()
plt.plot(fpr, tpr, color='blue', lw=2, label=f'ROC curve (AUC = {roc_auc:.2f})')
plt.plot([0, 1], [0, 1], color='red', lw=2, linestyle='--')
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('Receiver Operating Characteristic (ROC) Curve')
plt.legend(loc="lower right")
plt.grid(alpha=0.3)
plt.show()- Precision-Recall (PR) Curve: Especially useful for imbalanced datasets, the PR curve plots Precision (how many selected items are relevant) against Recall (how many relevant items are selected). A high area under this curve indicates a model with both high precision and high recall.
# -------------------------------
# Plot Precision-Recall (PR) Curve
# -------------------------------
precision, recall, _ = precision_recall_curve(y_test, y_proba)
plt.figure()
plt.plot(recall, precision, color='green', lw=2)
plt.xlabel('Recall')
plt.ylabel('Precision')
plt.title('Precision-Recall (PR) Curve')
plt.grid(alpha=0.3)
plt.show()- F1 Score vs. Probability Threshold: The F1 Score is the harmonic mean of Precision and Recall. Plotting this score across various probability thresholds helps you determine the best cutoff point for classification that balances both metrics.
# -------------------------------
# Plot F1 Score vs. Probability Threshold
# -------------------------------
thresholds = np.linspace(0, 1, 100)
f1_scores = []
for thresh in thresholds:
y_thresh = (y_proba >= thresh).astype(int)
score = f1_score(y_test, y_thresh)
f1_scores.append(score)
plt.figure()
plt.plot(thresholds, f1_scores, lw=2, label='F1 Score')
plt.xlabel('Probability Threshold')
plt.ylabel('F1 Score')
plt.title('F1 Score vs. Probability Threshold')
plt.legend()
plt.grid(alpha=0.3)
plt.show()These plots allow you to go beyond raw accuracy and make more informed decisions about model tuning and deployment.
Step 11 — Feature Importance 🔍
Identify crucial features to improve your model further. Remove less influential features and experiment with new ones to enhance your predictions.
# -------------------------------
# Plot Feature Importance
# -------------------------------
importances = model.feature_importances_
features = X.columns
# Create a DataFrame for plotting
feature_importance_df = pd.DataFrame({
'Feature': features,
'Importance': importances
}).sort_values(by='Importance', ascending=True)
plt.figure(figsize=(10, 12))
plt.barh(feature_importance_df['Feature'], feature_importance_df['Importance'], color='skyblue')
plt.xlabel('Feature Importance')
plt.title('XGBoost Feature Importance')
plt.tight_layout()
plt.show()Step 12 — Tree Visualization 🌳
Visualizing decision trees helps in understanding how the model makes decisions, enhancing transparency.
# -------------------------------
# Plot the Tree Map (First Tree)
# -------------------------------
# Create a figure and an axis with desired size and resolution.
fig, ax = plt.subplots(figsize=(20, 20), dpi=300)
# Plot the first tree from the XGBoost model on the axis.
# The 'rankdir' parameter arranges the tree from left-to-right.
plot_tree(model, num_trees=0, rankdir='LR', ax=ax)
# Optionally, set a title with a larger font for clarity.
ax.set_title("XGBoost Tree Visualization (Tree 0)", fontsize=16)
# Display the plot.
plt.show()This will produce a large tree diagram that illustrates the structure of the decision-making process in the model.
Here’s what to look for:
- Nodes: Each internal node (shown as a box with a condition like
radius_mean < 17.5) represents a decision rule based on one feature. The model uses these conditions to split the data step-by-step. - Edges: Arrows show the path data follows based on whether the condition at a node is true or false.
- Leaves: These are the terminal nodes of the tree (usually shown as rectangles without further splits). Each leaf contains a value which corresponds to the final score or output for that path through the tree. In classification, this score contributes to the decision of which class to predict.
🎓 Conclusion
This guide aimed to provide a practical introduction to training and evaluating your first prediction model (From 0 to 1). You now have the foundational knowledge to explore machine learning further 😀
If you need help or consultation, feel free to contact us at 📧 info@nouvellebiotech.com for a free session to discuss your specific use cases.
Thanks for reading! ☺️✨










