--- license: mit library_name: keras pipeline_tag: image-classification tags: [cnn, image-classification, tensorflow, keras, educational, from-scratch] --- # cnn-model: small CNN image-classification demo Classroom prototype. NOT a medical device and NOT a validated pneumonia detector. ## Model This is a custom TensorFlow Sequential CNN with three `Conv2D` blocks, global-average pooling, a dense layer, dropout, and a three-class softmax output. It was trained from scratch with no pretrained weights. Classes: - `INVALID` - `NORMAL` - `PNEUMONIA` Recorded configuration: - Input: RGB image resized to `224 × 224`, producing a `(224, 224, 3)` model input - Application preprocessing: convert the image to RGB, resize it to `(224, 224)`, convert it to a NumPy array with `dtype=np.float32`, and add a batch dimension with `np.expand_dims(..., axis=0)` - Rescaling: `tf.keras.layers.Rescaling(1.0 / 255.0)` inside the model; do not rescale the application input separately - Optimizer: `tf.keras.optimizers.Adam(learning_rate=0.001)` - Loss: `tf.keras.losses.SparseCategoricalCrossentropy()` - Training metric: `accuracy` ## Training data Dataset name: **not recorded**. Dataset source: **not recorded**. The images are not included. The experiment used 12 original images: 10 `INVALID`, 1 `NORMAL`, and 1 `PNEUMONIA`. Offline augmentation expanded these into 612 images, which were then split 80/20 with seed `123` into 490 training images and 122 validation images. Training used `EarlyStopping` monitoring `val_loss` with patience 5 and `restore_best_weights=True`, plus `ReduceLROnPlateau` monitoring `val_loss`. ## Result **From saved notebook output, not re-run:** validation accuracy **1.0000** and validation loss **0.00044693** on 122 validation images. ## How to read this result Augmentation was done before the split, so augmented copies of the same original image appear in both the training and validation sets. The same validation set drove `EarlyStopping` and `ReduceLROnPlateau`. There is no held-out test set; precision, recall, F1, and a confusion matrix were not computed. The number does not show performance on new X-rays. ## How to load it The expected input is one or more RGB images resized to `224 × 224`, represented as `float32` values in the original `0–255` range. The model contains its own `1/255` rescaling layer. ```python import tensorflow as tf from huggingface_hub import hf_hub_download model_path = hf_hub_download( repo_id="faiz4320/cnn-model", filename="model.keras" ) model = tf.keras.models.load_model( model_path ) ``` For inference, convert the source image to RGB, resize it to `(224, 224)`, convert it to a NumPy `float32` array, and add a batch dimension. Do not apply another `1/255` normalization because rescaling is part of the saved model. ## Intended use and limitations - Educational demonstration only; not for medical use - Tiny independent sample: 1 original `NORMAL` image and 1 original `PNEUMONIA` image - Leakage caused by augmenting before splitting - No held-out test set - Artificial class balance created through augmentation - Dataset source not recorded ## Code https://github.com/faiz-sheikh/Chest-Xray-CNN ## Credits - TensorFlow/Keras - Streamlit