The provided code is a TensorFlow-based implementation of a Convolutional Neural Network (CNN) using the Keras API for binary classification on the breast cancer dataset. The dataset is loaded using scikit-learn's datasets module, and relevant preprocessing steps, such as standardization and train-test split, are performed. The CNN model consists of convolutional layers with batch normalization and dropout for regularization. The model is compiled using the Adam optimizer and binary crossentropy loss function. Training is executed with 35 epochs, and the learning curve, displaying accuracy and loss over epochs for both training and validation sets, is visualized. The code also includes comments explaining key components and imports, enhancing readability and providing insights into the purpose of each section.
# Importing necessary libraries and modules
import tensorflow as tf # TensorFlow and Keras: Deep learning libraries for building and training neural networks
from tensorflow.keras import Sequential
from tensorflow.keras.layers import Conv1D, MaxPool1D, Flatten, Dense, Dropout, BatchNormalization
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.regularizers import l2 # Importing L2 regularization
from tensorflow.keras.callbacks import LearningRateScheduler # Importing learning rate scheduler
from sklearn import datasets # Provides built-in datasets, including the breast cancer dataset used in this example
from sklearn.model_selection import train_test_split # Provides functions for splitting the dataset into training and testing sets
from sklearn.preprocessing import StandardScaler # Used for standardizing the data
import numpy as np #Library for numerical operations, essential for data manipulation
import pandas as pd # Data manipulation and analysis library
import matplotlib.pyplot as plt #Plotting library for visualizing the learning curve
# Load breast cancer dataset
cancerData = datasets.load_breast_cancer()
# Creating a DataFrame with the dataset features
X = pd.DataFrame(data=cancerData.data, columns=cancerData.feature_names)
X.head() # Display the first few rows of the DataFrame
mean radius | mean texture | mean perimeter | mean area | mean smoothness | mean compactness | mean concavity | mean concave points | mean symmetry | mean fractal dimension | ... | worst radius | worst texture | worst perimeter | worst area | worst smoothness | worst compactness | worst concavity | worst concave points | worst symmetry | worst fractal dimension | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 17.99 | 10.38 | 122.80 | 1001.0 | 0.11840 | 0.27760 | 0.3001 | 0.14710 | 0.2419 | 0.07871 | ... | 25.38 | 17.33 | 184.60 | 2019.0 | 0.1622 | 0.6656 | 0.7119 | 0.2654 | 0.4601 | 0.11890 |
1 | 20.57 | 17.77 | 132.90 | 1326.0 | 0.08474 | 0.07864 | 0.0869 | 0.07017 | 0.1812 | 0.05667 | ... | 24.99 | 23.41 | 158.80 | 1956.0 | 0.1238 | 0.1866 | 0.2416 | 0.1860 | 0.2750 | 0.08902 |
2 | 19.69 | 21.25 | 130.00 | 1203.0 | 0.10960 | 0.15990 | 0.1974 | 0.12790 | 0.2069 | 0.05999 | ... | 23.57 | 25.53 | 152.50 | 1709.0 | 0.1444 | 0.4245 | 0.4504 | 0.2430 | 0.3613 | 0.08758 |
3 | 11.42 | 20.38 | 77.58 | 386.1 | 0.14250 | 0.28390 | 0.2414 | 0.10520 | 0.2597 | 0.09744 | ... | 14.91 | 26.50 | 98.87 | 567.7 | 0.2098 | 0.8663 | 0.6869 | 0.2575 | 0.6638 | 0.17300 |
4 | 20.29 | 14.34 | 135.10 | 1297.0 | 0.10030 | 0.13280 | 0.1980 | 0.10430 | 0.1809 | 0.05883 | ... | 22.54 | 16.67 | 152.20 | 1575.0 | 0.1374 | 0.2050 | 0.4000 | 0.1625 | 0.2364 | 0.07678 |
5 rows × 30 columns
# Extracting target variable
y = cancerData.target
# Checking the instancences of the input data
X.shape
(569, 30)
# Splitting the data into training into 90% and testing into 10% of the dataframe
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.1, stratify=y)
# Checking the shape of the training data
X_train.shape
(512, 30)
# Checking the shape of the testing data
y_test.shape
(57,)
# Standardizing the input features using StandardScaler
# Uses a standard normal curve by converting values into z-scores
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train) # Fit and transform training data
X_test = scaler.transform(X_test) # Transform testing data
# Reshape the data for Conv1D
X_train = X_train.reshape(X_train.shape[0], X_train.shape[1], 1)
X_test = X_test.reshape(X_test.shape[0], X_test.shape[1], 1)
# Creating a Sequential model
model = Sequential() # Initialize a Sequential model
# Convolutional layer with 64 filters and kernel size of 3
model.add(Conv1D(filters=64, kernel_size=3, activation='relu', input_shape=(X_train.shape[1], 1)))
model.add(BatchNormalization())
model.add(Dropout(0.5)) # Introducing dropout for regularization
# Second convolutional layer with 128 filters and kernel size of 3
model.add(Conv1D(filters=128, kernel_size=3, activation='relu'))
model.add(BatchNormalization())
model.add(Dropout(0.5)) # More dropout for regularization
# Flatten layer to transition from convolutional layers to dense layers
model.add(Flatten())
# Dense layer with 128 units and ReLU activation, also using L2 regularization
model.add(Dense(128, activation='relu', kernel_regularizer=l2(0.01)))
model.add(Dropout(0.5)) # Adding dropout for regularization
# Output layer with sigmoid activation for binary classification
model.add(Dense(1, activation='sigmoid'))
model.summary()
Model: "sequential_7" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= conv1d_14 (Conv1D) (None, 28, 64) 256 batch_normalization_14 (Ba (None, 28, 64) 256 tchNormalization) dropout_21 (Dropout) (None, 28, 64) 0 conv1d_15 (Conv1D) (None, 26, 128) 24704 batch_normalization_15 (Ba (None, 26, 128) 512 tchNormalization) dropout_22 (Dropout) (None, 26, 128) 0 flatten_7 (Flatten) (None, 3328) 0 dense_14 (Dense) (None, 128) 426112 dropout_23 (Dropout) (None, 128) 0 dense_15 (Dense) (None, 1) 129 ================================================================= Total params: 451969 (1.72 MB) Trainable params: 451585 (1.72 MB) Non-trainable params: 384 (1.50 KB) _________________________________________________________________
# Compile the model with a learning rate scheduler
def lr_schedule(epoch):
lr = 0.001
if epoch > 10:
lr *= 0.1
return lr
# Compiling the model with Adam optimizer, binary crossentropy loss, and accuracy metric
model.compile(optimizer=Adam(learning_rate=0.0001), loss='binary_crossentropy', metrics=['accuracy'])
# Train the model with a learning rate scheduler
history = model.fit(X_train, y_train, epochs=50, verbose=1, validation_data=(X_test, y_test),
callbacks=[LearningRateScheduler(lr_schedule)])
Epoch 1/50 16/16 [==============================] - 4s 62ms/step - loss: 2.6382 - accuracy: 0.9082 - val_loss: 2.4845 - val_accuracy: 0.9649 - lr: 0.0010 Epoch 2/50 16/16 [==============================] - 1s 65ms/step - loss: 2.1447 - accuracy: 0.9688 - val_loss: 2.1248 - val_accuracy: 0.9123 - lr: 0.0010 Epoch 3/50 16/16 [==============================] - 1s 46ms/step - loss: 1.8180 - accuracy: 0.9648 - val_loss: 1.8367 - val_accuracy: 0.9649 - lr: 0.0010 Epoch 4/50 16/16 [==============================] - 1s 46ms/step - loss: 1.5839 - accuracy: 0.9688 - val_loss: 1.6499 - val_accuracy: 0.8947 - lr: 0.0010 Epoch 5/50 16/16 [==============================] - 1s 47ms/step - loss: 1.4389 - accuracy: 0.9570 - val_loss: 1.5141 - val_accuracy: 0.8772 - lr: 0.0010 Epoch 6/50 16/16 [==============================] - 1s 59ms/step - loss: 1.2709 - accuracy: 0.9707 - val_loss: 1.3991 - val_accuracy: 0.8421 - lr: 0.0010 Epoch 7/50 16/16 [==============================] - 1s 57ms/step - loss: 1.1312 - accuracy: 0.9746 - val_loss: 1.2268 - val_accuracy: 0.8947 - lr: 0.0010 Epoch 8/50 16/16 [==============================] - 1s 42ms/step - loss: 1.0214 - accuracy: 0.9668 - val_loss: 1.2144 - val_accuracy: 0.8246 - lr: 0.0010 Epoch 9/50 16/16 [==============================] - 1s 46ms/step - loss: 0.9408 - accuracy: 0.9746 - val_loss: 1.1128 - val_accuracy: 0.8421 - lr: 0.0010 Epoch 10/50 16/16 [==============================] - 1s 55ms/step - loss: 0.8461 - accuracy: 0.9766 - val_loss: 0.9505 - val_accuracy: 0.8947 - lr: 0.0010 Epoch 11/50 16/16 [==============================] - 1s 51ms/step - loss: 0.7670 - accuracy: 0.9766 - val_loss: 1.0036 - val_accuracy: 0.8246 - lr: 0.0010 Epoch 12/50 16/16 [==============================] - 1s 44ms/step - loss: 0.7158 - accuracy: 0.9785 - val_loss: 0.9662 - val_accuracy: 0.8596 - lr: 1.0000e-04 Epoch 13/50 16/16 [==============================] - 1s 53ms/step - loss: 0.6902 - accuracy: 0.9863 - val_loss: 0.9336 - val_accuracy: 0.8596 - lr: 1.0000e-04 Epoch 14/50 16/16 [==============================] - 1s 55ms/step - loss: 0.7135 - accuracy: 0.9727 - val_loss: 0.8947 - val_accuracy: 0.8772 - lr: 1.0000e-04 Epoch 15/50 16/16 [==============================] - 1s 48ms/step - loss: 0.6836 - accuracy: 0.9844 - val_loss: 0.8618 - val_accuracy: 0.8772 - lr: 1.0000e-04 Epoch 16/50 16/16 [==============================] - 1s 52ms/step - loss: 0.6840 - accuracy: 0.9844 - val_loss: 0.8237 - val_accuracy: 0.8772 - lr: 1.0000e-04 Epoch 17/50 16/16 [==============================] - 1s 43ms/step - loss: 0.6724 - accuracy: 0.9805 - val_loss: 0.7803 - val_accuracy: 0.8947 - lr: 1.0000e-04 Epoch 18/50 16/16 [==============================] - 1s 52ms/step - loss: 0.6589 - accuracy: 0.9805 - val_loss: 0.7549 - val_accuracy: 0.8947 - lr: 1.0000e-04 Epoch 19/50 16/16 [==============================] - 1s 53ms/step - loss: 0.6417 - accuracy: 0.9805 - val_loss: 0.7254 - val_accuracy: 0.9298 - lr: 1.0000e-04 Epoch 20/50 16/16 [==============================] - 1s 35ms/step - loss: 0.6427 - accuracy: 0.9766 - val_loss: 0.7021 - val_accuracy: 0.9474 - lr: 1.0000e-04 Epoch 21/50 16/16 [==============================] - 1s 32ms/step - loss: 0.6546 - accuracy: 0.9746 - val_loss: 0.6762 - val_accuracy: 0.9474 - lr: 1.0000e-04 Epoch 22/50 16/16 [==============================] - 1s 36ms/step - loss: 0.6383 - accuracy: 0.9746 - val_loss: 0.6535 - val_accuracy: 0.9474 - lr: 1.0000e-04 Epoch 23/50 16/16 [==============================] - 1s 32ms/step - loss: 0.6054 - accuracy: 0.9805 - val_loss: 0.6330 - val_accuracy: 0.9649 - lr: 1.0000e-04 Epoch 24/50 16/16 [==============================] - 1s 48ms/step - loss: 0.5852 - accuracy: 0.9902 - val_loss: 0.6200 - val_accuracy: 0.9825 - lr: 1.0000e-04 Epoch 25/50 16/16 [==============================] - 1s 40ms/step - loss: 0.6092 - accuracy: 0.9805 - val_loss: 0.5997 - val_accuracy: 0.9825 - lr: 1.0000e-04 Epoch 26/50 16/16 [==============================] - 1s 51ms/step - loss: 0.5948 - accuracy: 0.9785 - val_loss: 0.5858 - val_accuracy: 0.9825 - lr: 1.0000e-04 Epoch 27/50 16/16 [==============================] - 1s 49ms/step - loss: 0.5631 - accuracy: 0.9824 - val_loss: 0.5727 - val_accuracy: 0.9825 - lr: 1.0000e-04 Epoch 28/50 16/16 [==============================] - 1s 50ms/step - loss: 0.5787 - accuracy: 0.9766 - val_loss: 0.5597 - val_accuracy: 0.9825 - lr: 1.0000e-04 Epoch 29/50 16/16 [==============================] - 1s 43ms/step - loss: 0.5372 - accuracy: 0.9941 - val_loss: 0.5517 - val_accuracy: 0.9825 - lr: 1.0000e-04 Epoch 30/50 16/16 [==============================] - 1s 53ms/step - loss: 0.5423 - accuracy: 0.9844 - val_loss: 0.5399 - val_accuracy: 1.0000 - lr: 1.0000e-04 Epoch 31/50 16/16 [==============================] - 1s 49ms/step - loss: 0.5619 - accuracy: 0.9824 - val_loss: 0.5316 - val_accuracy: 1.0000 - lr: 1.0000e-04 Epoch 32/50 16/16 [==============================] - 1s 47ms/step - loss: 0.5295 - accuracy: 0.9863 - val_loss: 0.5217 - val_accuracy: 1.0000 - lr: 1.0000e-04 Epoch 33/50 16/16 [==============================] - 1s 43ms/step - loss: 0.5348 - accuracy: 0.9824 - val_loss: 0.5202 - val_accuracy: 0.9825 - lr: 1.0000e-04 Epoch 34/50 16/16 [==============================] - 1s 49ms/step - loss: 0.5145 - accuracy: 0.9902 - val_loss: 0.5155 - val_accuracy: 0.9649 - lr: 1.0000e-04 Epoch 35/50 16/16 [==============================] - 1s 56ms/step - loss: 0.5173 - accuracy: 0.9785 - val_loss: 0.5227 - val_accuracy: 0.9825 - lr: 1.0000e-04 Epoch 36/50 16/16 [==============================] - 1s 59ms/step - loss: 0.4906 - accuracy: 0.9863 - val_loss: 0.5017 - val_accuracy: 0.9825 - lr: 1.0000e-04 Epoch 37/50 16/16 [==============================] - 1s 51ms/step - loss: 0.4858 - accuracy: 0.9805 - val_loss: 0.4822 - val_accuracy: 0.9825 - lr: 1.0000e-04 Epoch 38/50 16/16 [==============================] - 1s 67ms/step - loss: 0.4765 - accuracy: 0.9863 - val_loss: 0.4712 - val_accuracy: 0.9825 - lr: 1.0000e-04 Epoch 39/50 16/16 [==============================] - 1s 47ms/step - loss: 0.4716 - accuracy: 0.9844 - val_loss: 0.4629 - val_accuracy: 0.9825 - lr: 1.0000e-04 Epoch 40/50 16/16 [==============================] - 1s 40ms/step - loss: 0.4804 - accuracy: 0.9785 - val_loss: 0.4543 - val_accuracy: 0.9825 - lr: 1.0000e-04 Epoch 41/50 16/16 [==============================] - 1s 51ms/step - loss: 0.4550 - accuracy: 0.9883 - val_loss: 0.4504 - val_accuracy: 0.9825 - lr: 1.0000e-04 Epoch 42/50 16/16 [==============================] - 1s 60ms/step - loss: 0.4448 - accuracy: 0.9883 - val_loss: 0.4441 - val_accuracy: 0.9825 - lr: 1.0000e-04 Epoch 43/50 16/16 [==============================] - 1s 49ms/step - loss: 0.4432 - accuracy: 0.9805 - val_loss: 0.4347 - val_accuracy: 0.9825 - lr: 1.0000e-04 Epoch 44/50 16/16 [==============================] - 1s 54ms/step - loss: 0.4302 - accuracy: 0.9941 - val_loss: 0.4277 - val_accuracy: 0.9825 - lr: 1.0000e-04 Epoch 45/50 16/16 [==============================] - 1s 39ms/step - loss: 0.4365 - accuracy: 0.9785 - val_loss: 0.4159 - val_accuracy: 0.9825 - lr: 1.0000e-04 Epoch 46/50 16/16 [==============================] - 1s 45ms/step - loss: 0.4161 - accuracy: 0.9883 - val_loss: 0.4096 - val_accuracy: 0.9825 - lr: 1.0000e-04 Epoch 47/50 16/16 [==============================] - 1s 55ms/step - loss: 0.4107 - accuracy: 0.9863 - val_loss: 0.4015 - val_accuracy: 0.9825 - lr: 1.0000e-04 Epoch 48/50 16/16 [==============================] - 1s 49ms/step - loss: 0.4062 - accuracy: 0.9902 - val_loss: 0.3956 - val_accuracy: 0.9825 - lr: 1.0000e-04 Epoch 49/50 16/16 [==============================] - 1s 45ms/step - loss: 0.3956 - accuracy: 0.9844 - val_loss: 0.3916 - val_accuracy: 0.9825 - lr: 1.0000e-04 Epoch 50/50 16/16 [==============================] - 1s 44ms/step - loss: 0.3911 - accuracy: 0.9883 - val_loss: 0.3836 - val_accuracy: 0.9825 - lr: 1.0000e-04
# Plot the learning curve
def plot_learning_curve(history, epochs):
epoch_range = range(1, epochs + 1)
# Plotting the accuracy curve for training and validation data
plt.plot(epoch_range, history.history['accuracy'])
plt.plot(epoch_range, history.history['val_accuracy'])
plt.title('Model Accuracy')
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.legend(['Train', 'Validation'], loc='upper left')
plt.ylim(0, 1.1)
plt.show()
# Plotting the loss curve for training and validation data
plt.plot(epoch_range, history.history['loss'])
plt.plot(epoch_range, history.history['val_loss'])
plt.title('Model Loss')
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.legend(['Train', 'Validation'], loc='upper left')
plt.show()
# Plotting the learning curves using the defined function
plot_learning_curve(history, 50)