ESEN← Back to the blog
Deep Learning

How I trained my first CNN to detect COVID-19 in chest X-rays

By Guille Ferveg· 2026· 8 min read

I had never trained a neural network for images before. This is my log of training my first CNN to distinguish normal chest X-rays from COVID-19 cases: what confused me, what finally clicked and the mistakes that taught me more than the successes.

Before starting: this is a learning exercise using a public Kaggle dataset. It is not a medical device and cannot diagnose anyone in real life. The goal was to learn deep learning, not replace a radiologist.

01 What is a CNN, and why use one for images?

The first thing I had to understand was that a standard neural network sees an image as a huge list of disconnected pixels and loses the idea of what is next to what. A CNN (convolutional neural network) solves this through convolution: a small window slides across the image looking for patterns such as edges, textures and shapes.

The image that unlocked the intuition for me was a magnifying glass moving across the X-ray and learning by itself what to inspect. Early layers detect simple things such as lines and contrasts; later layers combine them into more complex structures such as lung shapes and opacities. No one tells it what to look for; it learns from examples.

02 Preparing the data was 70% of the work

I thought the difficult part would be “the network.” That was wrong: preparing the images took most of the time. The dataset had X-rays in two folders (COVID and normal), and before training I had to:

from tensorflow.keras.preprocessing.image import ImageDataGenerator

train_datagen = ImageDataGenerator(
    rescale=1./255,        # from 0–255 to 0–1
    rotation_range=15,     # rotate up to ±15°
    zoom_range=0.1,        # 10% zoom
    horizontal_flip=True,   # horizontal flip
    validation_split=0.2
)
What I learned here: if the data is dirty or disorganized, no architecture can save the project. A model is only as good as the data it receives.

03 Building the network in blocks—it was not so mystical

Thinking of it as repeating blocks made it less intimidating. I used three convolutional blocks, each following the same recipe: a layer that searches for patterns (Conv2D), one that stabilizes (BatchNormalization), one that reduces dimensions (MaxPooling) and one that randomly deactivates neurons so the model does not memorize (Dropout).

model = models.Sequential([
    # Block 1: simple patterns
    layers.Conv2D(32, (3,3), activation='relu', padding='same'),
    layers.BatchNormalization(),
    layers.MaxPooling2D(2,2),
    layers.Dropout(0.25),
    # Blocks 2 and 3: more filters (64 and 128), more complex patterns
    # ...
    layers.Flatten(),
    layers.Dense(256, activation='relu'),
    layers.Dropout(0.5),
    layers.Dense(1, activation='sigmoid')  # 1 output: COVID or normal
])

The final layer has a single neuron with sigmoid, which returns a number between zero and one: the “probability” that the X-ray is COVID. If it is greater than 0.5, the model classifies it as COVID.

04 The specter of overfitting

The concept I struggled with most was overfitting: when the model memorizes the images instead of learning the general pattern. It performs perfectly on what it has already seen and poorly on new images. It is like a student who memorizes the answers to a practice test without understanding the subject.

I used three tools against it, and seeing them work was very satisfying:

In the end, the difference between training and validation performance stayed below 3%. That signal—similar performance on unseen data—told me that the model was genuinely learning.

05 Metrics: why accuracy is not enough

My first instinct was to look only at accuracy: the percentage of correct predictions. I reached 92.86% and felt delighted. But in a medical problem, that number can be misleading, and this became the project’s most important lesson.

Imagine that 90 out of every 100 X-rays are normal. A dishonest model that always predicts “normal” would achieve 90% accuracy while missing every COVID case. That is why other metrics matter:

The mental shift: there is no universally “good metric.” It depends on which error is more costly. Here, prioritizing recall makes sense because missing a COVID case is worse than raising a false alarm.

06 What I found most difficult—honestly

For this to be a genuine log rather than a perfect snapshot, these are the parts I found most difficult:

07 What I took away

Training my first CNN taught me that deep learning is not black magic. It is about preparing the data properly, building the network from meaningful blocks, controlling overfitting and selecting metrics according to the problem. Every step has a rationale, and once you understand it, the process becomes far less intimidating.

The next step? Trying Transfer Learning: instead of training from scratch, start with a network already trained on millions of images, such as ResNet or MobileNet, and adapt it. It is said to perform better with limited data, and I want to test that myself.

Deep LearningCNNTensorFlowKerasComputer visionLearning

Interested in machine learning?

Write to me and let’s talk—about neural networks, data or why your model refuses to converge.

Let’s talk →