text_plain_output_1.png
from sklearn.model_selection import train_test_split

from tensorflow.keras import layers

from tensorflow.keras.preprocessing.image import ImageDataGenerator

import glob

import numpy as np

import pandas as pd

import pickle

import tensorflow as tf

import tensorflow.keras.backend as K

breast_img = glob.glob('/kaggle/input/breast-histopathology-images/IDC_regular_ps50_idx5/**/*.png', recursive=True)
data = pd.read_csv('/kaggle/input/selected-images/selected_images.csv')

train_data, val_data = train_test_split(data, test_size=0.3, random_state=42)
val_data, test_data = train_test_split(val_data, test_size=0.5, random_state=42)
datagen = ImageDataGenerator(rescale=1.0 / 255)
target_size = (50, 50)
batch_size = 32
train_generator = datagen.flow_from_dataframe(dataframe=train_data, x_col='path', y_col='label', target_size=target_size, batch_size=batch_size, class_mode='raw')
val_generator = datagen.flow_from_dataframe(dataframe=val_data, x_col='path', y_col='label', target_size=target_size, batch_size=batch_size, class_mode='raw')
test_generator = datagen.flow_from_dataframe(dataframe=test_data, x_col='path', y_col='label', target_size=target_size, batch_size=batch_size, class_mode='raw')

A, B = np.unique(train_generator.labels, return_counts=True)
n = len(train_generator.labels)
cls_weights = {i: (n - j) / n for i, j in zip(A, B)}

def f1_score(y_true, y_pred):
    true_positives = K.sum(K.round(K.clip(y_true * y_pred, 0, 1)))
    possible_positives = K.sum(K.round(K.clip(y_true, 0, 1)))
    predicted_positives = K.sum(K.round(K.clip(y_pred, 0, 1)))
    precision = true_positives / (predicted_positives + K.epsilon())
    recall = true_positives / (possible_positives + K.epsilon())
    f1_val = 2 * (precision * recall) / (precision + recall + K.epsilon())
    return f1_val

def train_best_model(units, learning_rate):
    model = tf.keras.Sequential()
    model.add(layers.Conv2D(units, (3, 3), activation='relu', input_shape=(50, 50, 3)))
    model.add(layers.BatchNormalization())
    model.add(layers.MaxPooling2D((2, 2)))
    model.add(layers.Conv2D(units * 2, (3, 3), activation='relu'))
    model.add(layers.BatchNormalization())
    model.add(layers.MaxPooling2D((2, 2)))
    model.add(layers.Conv2D(units * 4, (3, 3), activation='relu'))
    model.add(layers.BatchNormalization())
    model.add(layers.MaxPooling2D((2, 2)))
    model.add(layers.Flatten())
    model.add(layers.Dense(units * 2, activation='relu'))
    model.add(layers.BatchNormalization())
    model.add(layers.Dropout(0.5))
    model.add(layers.Dense(1, activation='sigmoid'))
    model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=learning_rate), loss='binary_crossentropy', metrics=[tf.keras.metrics.Precision(), tf.keras.metrics.Recall(), f1_score])
    history = model.fit(train_generator, validation_data=val_generator, epochs=300, callbacks=tf.keras.callbacks.EarlyStopping(patience=5, min_delta=0.001, monitor='val_loss'), class_weight=cls_weights)
    test_results = model.evaluate(test_generator)
    return (model, history, test_results)

model.save('cnn_model.h5')
with open('cnn_model_history.pkl', 'wb') as file:
    pickle.dump(history.history, file)
with open('cnn_test_results.pkl', 'wb') as file:
    pickle.dump(test_results, file)

total_parameters = model.count_params()
mult_adds_total = 0
for layer in model.layers:
    if isinstance(layer, tf.keras.layers.Conv2D):
        height, width, channels_in = layer.input_shape[1:]
        _, _, channels_out = layer.output_shape[1:]
        kernel_height, kernel_width = layer.kernel_size
        mult_adds = height * width * channels_in * channels_out * kernel_height * kernel_width
        mult_adds_total += mult_adds
print('Total parameters:', total_parameters)
print('Total number of multipy-accumulates:', mult_adds_total)