import tensorflow as tf from tensorflow.keras import layers, models, callbacks from tensorflow.keras.preprocessing.image import ImageDataGenerator import numpy as np import matplotlib.pyplot as plt import datetime import os import zipfile from google.colab import files from sklearn.metrics import classification_report, confusion_matrix import seaborn as sns from sklearn.utils import class_weight print("TensorFlow version:", tf.__version__) uploaded = files.upload() zip_filename = list(uploaded.keys())[0] extract_path = 'dataset' with zipfile.ZipFile(zip_filename, 'r') as zip_ref: zip_ref.extractall(extract_path) print("\nExtracted files:") !ls {extract_path} print("\nTrain folder contents:") !ls {extract_path}/train IMG_SIZE = (150, 150) BATCH_SIZE = 32 train_datagen = ImageDataGenerator( rescale=1./255, rotation_range=40, width_shift_range=0.3, height_shift_range=0.3, shear_range=0.3, zoom_range=0.3, horizontal_flip=True, vertical_flip=True, brightness_range=[0.8, 1.2], validation_split=0.2, fill_mode='nearest' ) train_generator = train_datagen.flow_from_directory( os.path.join(extract_path, 'train'), target_size=IMG_SIZE, batch_size=BATCH_SIZE, class_mode='binary', subset='training', shuffle=True ) validation_generator = train_datagen.flow_from_directory( os.path.join(extract_path, 'train'), target_size=IMG_SIZE, batch_size=BATCH_SIZE, class_mode='binary', subset='validation', shuffle=True ) class_weights = class_weight.compute_class_weight( 'balanced', classes=np.unique(train_generator.classes), y=train_generator.classes ) class_weights = dict(enumerate(class_weights)) class_names = list(train_generator.class_indices.keys()) print("\nDetected classes:", class_names) print("Training samples:", train_generator.samples) print("Validation samples:", validation_generator.samples) print("Class weights:", class_weights) def build_enhanced_model(input_shape): model = models.Sequential([ layers.Conv2D(64, (3,3), activation='relu', padding='same', input_shape=input_shape), layers.BatchNormalization(), layers.Conv2D(64, (3,3), activation='relu', padding='same'), layers.BatchNormalization(), layers.MaxPooling2D((2,2)), layers.Dropout(0.3), layers.Conv2D(128, (3,3), activation='relu', padding='same'), layers.BatchNormalization(), layers.Conv2D(128, (3,3), activation='relu', padding='same'), layers.BatchNormalization(), layers.MaxPooling2D((2,2)), layers.Dropout(0.3), layers.Conv2D(256, (3,3), activation='relu', padding='same'), layers.BatchNormalization(), layers.Conv2D(256, (3,3), activation='relu', padding='same'), layers.BatchNormalization(), layers.MaxPooling2D((2,2)), layers.Dropout(0.4), layers.Flatten(), layers.Dense(512, activation='relu'), layers.BatchNormalization(), layers.Dropout(0.5), layers.Dense(1, activation='sigmoid') ]) optimizer = tf.keras.optimizers.Adam(learning_rate=0.0001) model.compile( optimizer=optimizer, loss='binary_crossentropy', metrics=['accuracy', tf.keras.metrics.AUC(name='auc')] ) return model model = build_enhanced_model(input_shape=(IMG_SIZE[0], IMG_SIZE[1], 3)) model.summary() log_dir = "logs/fit/" + datetime.datetime.now().strftime("%Y%m%d-%H%M%S") callbacks = [ callbacks.TensorBoard(log_dir=log_dir), callbacks.ReduceLROnPlateau( monitor='val_loss', factor=0.5, patience=3, min_lr=1e-7, verbose=1 ), callbacks.ModelCheckpoint( 'best_model.keras', monitor='val_auc', mode='max', save_best_only=True, save_weights_only=False, verbose=1 ) ] print("\nStarting training for full 30 epochs...") history = model.fit( train_generator, steps_per_epoch=train_generator.samples // BATCH_SIZE, epochs=30, validation_data=validation_generator, validation_steps=validation_generator.samples // BATCH_SIZE, callbacks=callbacks, class_weight=class_weights, verbose=1 ) print("\nTraining complete. Saving final model...") model.save('final_model.keras') history_df = pd.DataFrame(history.history) history_df.to_csv('training_history.csv', index=False) plt.figure(figsize=(12, 5)) plt.subplot(1, 2, 1) plt.plot(history.history['accuracy'], label='Train Accuracy') plt.plot(history.history['val_accuracy'], label='Validation Accuracy') plt.title('Model Accuracy') plt.ylabel('Accuracy') plt.xlabel('Epoch') plt.legend() plt.subplot(1, 2, 2) plt.plot(history.history['loss'], label='Train Loss') plt.plot(history.history['val_loss'], label='Validation Loss') plt.title('Model Loss') plt.ylabel('Loss') plt.xlabel('Epoch') plt.legend() plt.show() val_preds = model.predict(validation_generator) val_preds = (val_preds > 0.5).astype(int) cm = confusion_matrix(validation_generator.classes, val_preds) plt.figure(figsize=(6, 6)) sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', xticklabels=class_names, yticklabels=class_names) plt.title('Confusion Matrix') plt.ylabel('True Label') plt.xlabel('Predicted Label') plt.show() print("\nClassification Report:") print(classification_report(validation_generator.classes, val_preds, target_names=class_names)) converter = tf.lite.TFLiteConverter.from_keras_model(model) tflite_model = converter.convert() with open('cat_dog.tflite', 'wb') as f: f.write(tflite_model) print("\nAll models saved successfully:") print("- final_model.keras (model after all epochs)") print("- best_model.keras (best validation AUC model)") print("- cat_dog.tflite (TFLite version)")