Building an Artificial Neural Network for Breast Cancer Prediction

Deep learning and artificial neural networks (ANNs) have revolutionized the field of predictive modeling, enabling more accurate and insightful predictions than ever before. In this tutorial, we‘ll walk through the process of building an ANN to predict breast cancer diagnoses using a classic dataset. Whether you‘re a beginner looking to learn the fundamentals or an experienced practitioner seeking to refine your skills, this guide will provide a comprehensive overview of the key steps involved.

Understanding Artificial Neural Networks

Before diving into the implementation, let‘s briefly review what artificial neural networks are and how they work. ANNs are a type of machine learning model inspired by the structure and function of biological neural networks in the brain. They consist of interconnected nodes or "neurons" organized into layers:

  • An input layer that receives the initial data
  • One or more hidden layers that learn representations of the data
  • An output layer that makes the final predictions

Information flows through the network from the input to the output layer, with each neuron receiving weighted inputs, applying an activation function, and passing its output to the next layer. During training, the network learns the optimal weights to map inputs to the correct outputs by iteratively adjusting the weights to minimize a loss function.

The power of ANNs lies in their ability to learn complex, non-linear relationships in data without being explicitly programmed. With enough training data and computing power, ANNs can uncover intricate patterns and make highly accurate predictions. This has led to breakthroughs in computer vision, natural language processing, and other domains.

The Breast Cancer Dataset

To illustrate the process of building an ANN, we‘ll use the classic Wisconsin Breast Cancer dataset. This dataset contains features computed from digitized images of fine needle aspirate (FNA) biopsies of breast masses, along with a diagnosis of malignant (cancerous) or benign (non-cancerous). The goal is to train a model that can predict the diagnosis based on the features alone.

The dataset contains 569 instances, each with 30 features and a binary diagnosis label (M = malignant, B = benign). The features capture characteristics of the cell nuclei present in the images, such as radius, texture, perimeter, area, smoothness, and more.

This dataset is a great choice for learning ANN basics because it is relatively small and easy to work with, but still complex enough to be interesting. It‘s also a real-world problem with clear practical value – a model that can accurately detect breast cancer from biopsy images could save lives by enabling earlier diagnosis and treatment.

With that background in mind, let‘s get started building our ANN!

Step 1: Import Libraries and Load the Data

The first step is to import the necessary Python libraries. We‘ll be using Pandas for data loading and manipulation, NumPy for numerical computing, Matplotlib and Seaborn for visualization, and Scikit-learn and Keras for building and evaluating the ANN.

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import confusion_matrix, classification_report
from keras.models import Sequential
from keras.layers import Dense

Next, load the data into a Pandas DataFrame:

data = pd.read_csv(‘data.csv‘)
print(data.shape)
data.head()

We can see that the dataset has 569 rows and 33 columns, with the first column being an ID number, the last being the diagnosis label, and the rest being the 30 features. Let‘s check for any missing values:

data.isnull().sum()  

Fortunately, there are no missing values in this dataset. If there were, we would need to decide how to handle them, such as by removing rows with missing data or imputing the missing values.

Step 2: Preprocess the Data

With the data loaded, we can start preprocessing it for modeling. First, let‘s separate the features (X) and the target variable (y) we want to predict:

X = data.iloc[:, 2:-1].values
y = data.iloc[:, -1].values

Next, we need to encode the categorical diagnosis labels (M and B) as 0 and 1 to use them in the ANN:

from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()
y = le.fit_transform(y)

Then split the data into training and testing sets, using 80% for training and 20% for testing:

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

Finally, scale the feature data to have zero mean and unit variance, which helps the ANN converge faster during training:

scaler = StandardScaler()
X_train = scaler.fit_transform(X_train) 
X_test = scaler.transform(X_test)

Step 3: Define the Model Architecture

With the data prepared, we can define the architecture of our ANN using the Keras Sequential model API. We‘ll use a simple feedforward architecture with two hidden layers:

model = Sequential()
model.add(Dense(16, activation=‘relu‘, input_shape=(30,)))
model.add(Dense(8, activation=‘relu‘))
model.add(Dense(1, activation=‘sigmoid‘))

The first layer has 16 neurons and uses the ReLU activation function. It expects input of shape (30,) corresponding to our 30 input features. The second hidden layer has 8 neurons, also with ReLU activation. The output layer has a single neuron with sigmoid activation, which squashes the output to a probability between 0 and 1 that we can interpret as the likelihood of the positive class (malignant cancer).

We can visualize this architecture by calling model.summary():

_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense_5 (Dense)              (None, 16)                496       
_________________________________________________________________
dense_6 (Dense)              (None, 8)                 136       
_________________________________________________________________
dense_7 (Dense)              (None, 1)                 9         
=================================================================
Total params: 641
Trainable params: 641
Non-trainable params: 0

This shows that our model has a total of 641 parameters, all of which are trainable.

Step 4: Compile and Train the Model

With the architecture defined, we need to compile the model by specifying the loss function, optimizer, and metrics to monitor during training. Since this is a binary classification problem, we‘ll use binary cross-entropy loss and the Adam optimizer, and watch the accuracy metric:

model.compile(optimizer=‘adam‘, loss=‘binary_crossentropy‘, metrics=[‘accuracy‘])

Now we‘re ready to train! We‘ll use a batch size of 32 and train for 100 epochs, with 10% of the data reserved for validation to monitor for overfitting:

history = model.fit(X_train, y_train, 
                    batch_size=32, 
                    epochs=100,
                    validation_split=0.1)  

As the model trains, we can see the loss and accuracy metrics for each epoch print out. The training accuracy increases to close to 100%, while the validation accuracy tops out around 98%, suggesting slight overfitting. We could try to address this with techniques like regularization or simplifying the model architecture, but for now let‘s evaluate the model as is.

Step 5: Evaluate Performance

To assess the final model‘s performance, we‘ll use the held-out test set:

loss, accuracy = model.evaluate(X_test, y_test)
print(‘Test accuracy:‘, accuracy)

This shows a test set accuracy of about 97%, which is pretty good! But accuracy alone doesn‘t tell the whole story. Let‘s look at the confusion matrix:

y_pred = (model.predict(X_test) > 0.5).astype(int).squeeze()
cm = confusion_matrix(y_test, y_pred)
sns.heatmap(cm, annot=True, fmt=‘g‘)
plt.xlabel(‘Predicted‘)
plt.ylabel(‘Actual‘) 

The confusion matrix shows that out of 114 test instances, the model correctly predicted 43 malignant and 68 benign cases, but misclassified 1 malignant case as benign and 2 benign cases as malignant. In a medical context, we might be more concerned about the false negative (misclassifying cancer as benign) than the false positives.

We can get additional performance metrics from a classification report:

print(classification_report(y_test, y_pred))
              precision    recall  f1-score   support

           0       0.97      0.98      0.97        44
           1       0.99      0.97      0.98        70

    accuracy                           0.97       114
   macro avg       0.98      0.97      0.98       114
weighted avg       0.98      0.97      0.98       114

This breaks down the precision, recall, and F1 score for each class, along with overall accuracy and averages. We can see that the model performs well on both classes, with slightly higher precision than recall for the malignant (0) class and vice versa for the benign (1) class.

Finally, let‘s visualize how the model‘s loss and accuracy evolved over the training epochs:

plt.figure(figsize=(12,4))
plt.subplot(1,2,1)
plt.plot(history.history[‘loss‘], label=‘train‘)
plt.plot(history.history[‘val_loss‘], label=‘val‘)
plt.xlabel(‘Epoch‘)
plt.ylabel(‘Loss‘) 
plt.legend()

plt.subplot(1,2,2)
plt.plot(history.history[‘accuracy‘], label=‘train‘)
plt.plot(history.history[‘val_accuracy‘], label=‘val‘)  
plt.xlabel(‘Epoch‘)
plt.ylabel(‘Accuracy‘)
plt.legend()

plt.tight_layout()
plt.show()

These plots show typical learning curves, with the training loss decreasing and accuracy increasing over time, while the validation metrics level off and even start to diverge, indicating some overfitting in the later epochs.

Step 6: Make Predictions on New Data

As a final test, let‘s use the trained model to make predictions on some new, unlabeled data. Of course, in a real scenario we wouldn‘t have the true labels to compare against, but this is just for illustrative purposes.

new_data = [[13.08,15.71,85.63,520,0.1075,0.127,0.04568,0.0311,0.1967,0.06811,0.1852,0.7477,1.383,14.67,0.004097,0.01898,0.01698,0.00649,0.01678,0.002425,14.5,20.49,96.09,630.5,0.1312,0.2776,0.189,0.07283,0.3184,0.08183],
            [9.504,12.44,60.34,273.9,0.1024,0.06492,0.02956,0.02076,0.1815,0.06905,0.2773,0.9768,1.909,15.7,0.009606,0.01432,0.01985,0.01421,0.02027,0.002968,10.23,15.66,65.13,314.9,0.1324,0.1148,0.08867,0.06227,0.245,0.07773]]

new_data = scaler.transform(new_data)

preds = (model.predict(new_data) > 0.5).astype(int)
print(preds)
[[1]
 [0]]

The model predicts that the first example is benign (1) and the second is malignant (0). Of course, to have full confidence in these predictions we‘d want to validate the model‘s performance on a larger held-out test set or using cross-validation, but this gives a quick sense of how we can apply the trained model to new data.

Saving and Reusing the Model

Finally, once we‘re satisfied with the model‘s performance, we can save its architecture, weights, and the data preprocessing steps like the scaler for future use:

model.save(‘breast_cancer_model.h5‘) 
joblib.dump(scaler, ‘scaler.pkl‘)

We can later load the saved model and scaler to make predictions on new data without retraining:

loaded_model = load_model(‘breast_cancer_model.h5‘)
loaded_scaler = joblib.load(‘scaler.pkl‘) 

new_data = loaded_scaler.transform(new_data)
preds = (loaded_model.predict(new_data) > 0.5).astype(int)

This is just a simple example – in practice, you‘d want to save the model files somewhere accessible like cloud storage and build a more user-friendly inference pipeline. But the core idea is that once trained and saved, the model can be deployed and used to make predictions on new data at scale.

Conclusion and Next Steps

Congratulations – you now know how to build, train, evaluate, and use a basic artificial neural network for binary classification using the Keras API! Of course, there are many ways to extend and improve on this example, such as:

  • Experimenting with different model architectures, activation functions, and hyperparameters
  • Using techniques like regularization, dropout, and cross-validation to reduce overfitting
  • Exploring other types of models like convolutional neural networks for image data
  • Building a web app or API to expose the model for use

The field of deep learning is vast and rapidly evolving, with new architectures, use cases, and best practices emerging all the time. But the core principles and workflow you‘ve learned here provide a solid foundation for further learning and application to real-world problems.

Remember, the power of deep learning lies not just in the model itself, but in the quality and quantity of data used to train it. Always be sure to carefully inspect and preprocess your data, use appropriate train/validation/test splits, and monitor model performance to guide your iterations.

With practice and experience, you‘ll be able to harness the power of deep learning to uncover valuable insights, make accurate predictions, and build intelligent systems that can improve people‘s lives. So keep learning, stay curious, and happy coding!

How useful was this post?

Click on a star to rate it!

Average rating 0 / 5. Vote count: 0

No votes so far! Be the first to rate this post.

Similar Posts