top of page

Building a Comprehensive Skin Disease Dataset

  • Writer: Anie Etor-Udofia
    Anie Etor-Udofia
  • Mar 29
  • 2 min read

Introduction

Every AI model is only as good as its training data. For NOMA AI, creating a comprehensive and balanced dataset was the first critical challenge.

The goal was to include images spanning the full spectrum of skin conditions—from common acne to malignant melanoma—while ensuring the model would not become biased toward overrepresented classes.

Dataset Compilation

The “Skin Diseases and Cancer Comprehensive Dataset” was compiled on Kaggle using multiple public dermatology repositories.

The final dataset contains 12,900 images across 24 distinct classes, categorized as follows:

Malignant Classes (4)

  • Melanoma

  • Basal Cell Carcinoma

  • Squamous Cell Carcinoma

  • Actinic Keratosis (precancerous)

Benign Classes (20)

  • Acne, Eczema, Psoriasis, Rosacea, Moles

  • Seborrheic Keratoses, Lichen, Lupus

  • Vitiligo, Warts, Tinea, Candidiasis

  • Bullous, Vasculitis, Vascular Tumors

  • Drug Eruption, Infestations/Bites

  • Sun/Sunlight Damage, Benign Tumors

Normal Class (1)

  • Healthy skin tissue

The Class Imbalance Challenge

A major obstacle emerged: significant variation in class sizes.

  • Some benign classes (e.g., Eczema) had 1000+ images

  • Some malignant classes (e.g., Squamous Cell Carcinoma) had ~200 images

Without correction, the model would bias toward predicting “benign” for most cases—an unacceptable risk for a cancer screening tool.

The Solution: Computed Class Weights

To address imbalance, scikit-learn’s compute_class_weight function was used to assign weights based on class frequency:

class_counts = []
for class_name in CLASS_NAMES:
    class_path = os.path.join(dataset_path, class_name)
    num_images = len([
        f for f in os.listdir(class_path)
        if f.endswith(('.jpg', '.jpeg', '.png'))
    ])
    class_counts.append(num_images)

y_train = []
for i, count in enumerate(class_counts):
    y_train.extend([i] * count)

class_weights = compute_class_weight(
    'balanced',
    classes=np.arange(len(CLASS_NAMES)),
    y=y_train
)

class_weight_dict = {
    i: weight for i, weight in enumerate(class_weights)
}

This approach ensures the model gives greater importance to underrepresented malignant classes during training.

Data Split and Preprocessing

The dataset was split using TensorFlow’s image_dataset_from_directory:

  • 80% Training — 10,311 images

  • 20% Validation — 2,577 images

  • Random Seed: 123 (for reproducibility)

Image Preprocessing Steps

Each image was:

  • Resized to 224 × 224 pixels

  • Normalized to a [0, 1] range

  • Augmented with:

    • Random flipping

    • Rotation

    • Zoom

    • Contrast adjustments

    • Brightness variation

Why 224 × 224?

MobileNetV3 is optimized for this input size. It provides the ideal balance between:

  • Preserving diagnostic features (e.g., border irregularity, color variation)

  • Maintaining computational efficiency on edge devices like the Raspberry Pi

Key Takeaway

A balanced dataset is not just about equal numbers—it is about ensuring the model learns to detect rare but critical conditions.

By applying class weighting, malignant classes received the attention necessary for accurate detection, improving the system’s reliability as a screening tool.

Comments


bottom of page