Data Validation & Testing

Data Validation in CI/CD

5 min read

English Content

Why Data Validation Matters in ML

In traditional software, bugs come from code. In ML systems, bugs can come from code, model architecture, or data. Data issues are often the most insidious because they can silently degrade model performance without raising obvious errors.

Common data issues in production ML:

  • Schema drift (new columns, changed types)
  • Distribution shift (feature statistics change)
  • Missing values increase unexpectedly
  • Data freshness problems (stale data)
  • Upstream data source changes
  • Encoding/format inconsistencies

The Cost of Bad Data

Issue Impact
Schema change Pipeline crashes, training fails
Distribution shift Model accuracy degrades silently
Missing values Biased predictions, NaN errors
Stale data Predictions based on outdated patterns
Incorrect labels Model learns wrong patterns

A 2024 survey found that 73% of ML teams cite data quality as their biggest operational challenge. Data validation in CI/CD prevents these issues from reaching production.

Data Validation Strategy

Implement validation at multiple points in your pipeline:

Data Source → [Ingestion Validation] → Raw Data
                              [Schema Validation]
                               Processed Data
                           [Statistical Validation]
                                Training Data
                            [Pre-Training Checks]
                                   Model
                           [Inference Validation]
                                Predictions

Validation Types and When to Use Them

1. Schema Validation

  • Check column names, types, and structure
  • Run on every data load
  • Fast, catches obvious issues
# Simple schema validation
def validate_schema(df, expected_schema):
    """Validate DataFrame matches expected schema."""
    errors = []

    # Check columns exist
    missing_cols = set(expected_schema.keys()) - set(df.columns)
    if missing_cols:
        errors.append(f"Missing columns: {missing_cols}")

    # Check column types
    for col, expected_type in expected_schema.items():
        if col in df.columns:
            actual_type = df[col].dtype
            if not is_compatible_type(actual_type, expected_type):
                errors.append(f"Column {col}: expected {expected_type}, got {actual_type}")

    return errors

2. Statistical Validation

  • Check distributions, ranges, correlations
  • Run on data updates
  • Catches drift and anomalies
# Statistical validation
def validate_statistics(df, baseline_stats):
    """Compare current data statistics to baseline."""
    alerts = []

    for col in baseline_stats:
        current_mean = df[col].mean()
        baseline_mean = baseline_stats[col]['mean']
        baseline_std = baseline_stats[col]['std']

        # Check if mean is within 3 standard deviations
        z_score = abs(current_mean - baseline_mean) / baseline_std
        if z_score > 3:
            alerts.append(f"Column {col}: mean drift detected (z={z_score:.2f})")

    return alerts

3. Business Rule Validation

  • Domain-specific constraints
  • Critical for correctness
  • Often overlooked
# Business rule validation
def validate_business_rules(df):
    """Validate domain-specific business rules."""
    violations = []

    # Example: Age must be positive and reasonable
    if (df['age'] < 0).any() or (df['age'] > 150).any():
        violations.append("Age values out of valid range")

    # Example: Prices must be positive
    if (df['price'] <= 0).any():
        violations.append("Non-positive prices found")

    # Example: Dates must be in order
    if (df['end_date'] < df['start_date']).any():
        violations.append("End date before start date")

    return violations

CI/CD Integration Pattern

Integrate data validation as a pipeline stage:

# GitHub Actions
name: ML Pipeline with Data Validation
on:
  push:
    paths:
      - 'data/**'
      - 'src/**'

jobs:
  validate-data:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: '3.11'

      - name: Install dependencies
        run: pip install pandas great-expectations pandera

      - name: Run schema validation
        run: python scripts/validate_schema.py

      - name: Run statistical validation
        run: python scripts/validate_statistics.py

      - name: Run business rules
        run: python scripts/validate_rules.py

  train:
    needs: validate-data
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: python scripts/train.py

Validation Gate Strategies

Blocking Gates (Hard Fails)

  • Schema violations
  • Critical missing values
  • Security/PII violations

Warning Gates (Soft Fails)

  • Statistical drift within threshold
  • Minor data quality issues
  • Performance below target but acceptable
# Implementing soft and hard gates
validate-data:
  runs-on: ubuntu-latest
  steps:
    - name: Hard validation (must pass)
      run: |
        python scripts/validate_schema.py
        python scripts/validate_critical.py

    - name: Soft validation (warn only)
      continue-on-error: true
      run: python scripts/validate_statistics.py

    - name: Check if warnings should block
      run: |
        if [ -f "validation_warnings.txt" ]; then
          echo "::warning::Data validation warnings detected"
          cat validation_warnings.txt
        fi

Key Takeaways

Validation Type When to Run Failure Action
Schema Every data load Block pipeline
Statistical Data updates Warn or block
Business rules Before training Block pipeline
Freshness Scheduled Alert team

المحتوى العربي

لماذا التحقق من البيانات مهم في ML

في البرمجيات التقليدية، الأخطاء تأتي من الكود. في أنظمة ML، الأخطاء يمكن أن تأتي من الكود أو بنية النموذج أو البيانات. مشاكل البيانات غالباً الأكثر خبثاً لأنها يمكن أن تُدهور أداء النموذج بصمت دون إثارة أخطاء واضحة.

مشاكل البيانات الشائعة في إنتاج ML:

  • انجراف المخطط (أعمدة جديدة، أنواع متغيرة)
  • تحول التوزيع (إحصائيات الميزات تتغير)
  • زيادة غير متوقعة في القيم المفقودة
  • مشاكل حداثة البيانات (بيانات قديمة)
  • تغييرات مصدر البيانات الأعلى
  • عدم اتساق الترميز/التنسيق

تكلفة البيانات السيئة

المشكلة التأثير
تغيير المخطط تعطل Pipeline، فشل التدريب
تحول التوزيع تدهور دقة النموذج بصمت
القيم المفقودة تنبؤات منحازة، أخطاء NaN
البيانات القديمة تنبؤات مبنية على أنماط قديمة
تسميات غير صحيحة النموذج يتعلم أنماط خاطئة

وجد استطلاع 2024 أن 73% من فرق ML يذكرون جودة البيانات كأكبر تحدي تشغيلي لهم. التحقق من البيانات في CI/CD يمنع هذه المشاكل من الوصول للإنتاج.

استراتيجية التحقق من البيانات

نفّذ التحقق في نقاط متعددة في خط الأنابيب:

مصدر البيانات → [التحقق من الاستيعاب] → البيانات الخام
                              [التحقق من المخطط]
                               البيانات المعالجة
                           [التحقق الإحصائي]
                                بيانات التدريب
                            [فحوصات ما قبل التدريب]
                                   النموذج
                           [التحقق من الاستدلال]
                                التنبؤات

أنواع التحقق ومتى تستخدمها

1. التحقق من المخطط

  • فحص أسماء الأعمدة والأنواع والهيكل
  • تشغيل عند كل تحميل بيانات
  • سريع، يلتقط المشاكل الواضحة
# التحقق البسيط من المخطط
def validate_schema(df, expected_schema):
    """التحقق من تطابق DataFrame مع المخطط المتوقع."""
    errors = []

    # فحص وجود الأعمدة
    missing_cols = set(expected_schema.keys()) - set(df.columns)
    if missing_cols:
        errors.append(f"Missing columns: {missing_cols}")

    # فحص أنواع الأعمدة
    for col, expected_type in expected_schema.items():
        if col in df.columns:
            actual_type = df[col].dtype
            if not is_compatible_type(actual_type, expected_type):
                errors.append(f"Column {col}: expected {expected_type}, got {actual_type}")

    return errors

2. التحقق الإحصائي

  • فحص التوزيعات والنطاقات والارتباطات
  • تشغيل عند تحديثات البيانات
  • يلتقط الانجراف والشذوذ
# التحقق الإحصائي
def validate_statistics(df, baseline_stats):
    """مقارنة إحصائيات البيانات الحالية مع خط الأساس."""
    alerts = []

    for col in baseline_stats:
        current_mean = df[col].mean()
        baseline_mean = baseline_stats[col]['mean']
        baseline_std = baseline_stats[col]['std']

        # فحص إذا كان المتوسط ضمن 3 انحرافات معيارية
        z_score = abs(current_mean - baseline_mean) / baseline_std
        if z_score > 3:
            alerts.append(f"Column {col}: mean drift detected (z={z_score:.2f})")

    return alerts

3. التحقق من قواعد العمل

  • قيود خاصة بالمجال
  • حرجة للصحة
  • غالباً يتم تجاهلها
# التحقق من قواعد العمل
def validate_business_rules(df):
    """التحقق من قواعد العمل الخاصة بالمجال."""
    violations = []

    # مثال: العمر يجب أن يكون موجب ومعقول
    if (df['age'] < 0).any() or (df['age'] > 150).any():
        violations.append("Age values out of valid range")

    # مثال: الأسعار يجب أن تكون موجبة
    if (df['price'] <= 0).any():
        violations.append("Non-positive prices found")

    # مثال: التواريخ يجب أن تكون مرتبة
    if (df['end_date'] < df['start_date']).any():
        violations.append("End date before start date")

    return violations

نمط تكامل CI/CD

دمج التحقق من البيانات كمرحلة في خط الأنابيب:

# GitHub Actions
name: ML Pipeline with Data Validation
on:
  push:
    paths:
      - 'data/**'
      - 'src/**'

jobs:
  validate-data:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: '3.11'

      - name: Install dependencies
        run: pip install pandas great-expectations pandera

      - name: Run schema validation
        run: python scripts/validate_schema.py

      - name: Run statistical validation
        run: python scripts/validate_statistics.py

      - name: Run business rules
        run: python scripts/validate_rules.py

  train:
    needs: validate-data
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: python scripts/train.py

استراتيجيات بوابات التحقق

البوابات الحاجبة (فشل صعب)

  • انتهاكات المخطط
  • قيم مفقودة حرجة
  • انتهاكات الأمان/PII

بوابات التحذير (فشل لين)

  • انجراف إحصائي ضمن العتبة
  • مشاكل جودة بيانات طفيفة
  • أداء أقل من الهدف لكن مقبول
# تنفيذ البوابات اللينة والصعبة
validate-data:
  runs-on: ubuntu-latest
  steps:
    - name: Hard validation (must pass)
      run: |
        python scripts/validate_schema.py
        python scripts/validate_critical.py

    - name: Soft validation (warn only)
      continue-on-error: true
      run: python scripts/validate_statistics.py

    - name: Check if warnings should block
      run: |
        if [ -f "validation_warnings.txt" ]; then
          echo "::warning::Data validation warnings detected"
          cat validation_warnings.txt
        fi

النقاط الرئيسية

نوع التحقق متى يُشغّل إجراء الفشل
المخطط كل تحميل بيانات حجب pipeline
الإحصائي تحديثات البيانات تحذير أو حجب
قواعد العمل قبل التدريب حجب pipeline
الحداثة مجدول تنبيه الفريق

Quiz

Module 4: Data Validation & Testing

Take Quiz