{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "dd08ee41",
   "metadata": {},
   "source": [
    "# Moduł 6: Bias, leakage i drift w praktyce ML\n",
    "\n",
    "**Wersja:** uczestnika  \n",
    "**Cel:** przejść od sygnału statystycznego do diagnozy uwzględniającej rozkład, oś czasu cech i kontekst biznesowy  \n",
    "**Czas orientacyjny:** 45–55 min  \n",
    "**Dane:** customer360_reference.csv, customer360_current.csv, customer360_development_sample.csv, feature_timing.csv  \n",
    "**Artefakt końcowy:** mini-raport diagnostyczny\n",
    "\n",
    "Notebook jest częścią wspólnego case'u **Customer 360**. Dane są syntetyczne i służą wyłącznie ćwiczeniu."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f7448f7c",
   "metadata": {},
   "source": [
    "## Jak pracować\n",
    "\n",
    "1. Uruchamiaj komórki od góry do dołu.\n",
    "2. Najpierw zapisz obserwację z danych. Dopiero później formułuj hipotezę o przyczynie.\n",
    "3. W rekomendacji wskaż dowód, właściciela działania i warunek ponownej oceny.\n",
    "4. Wynik statystyczny jest sygnałem diagnostycznym. Sam nie przesądza o zatrzymaniu modelu, zmianie progu ani retrainingu."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d55542c9",
   "metadata": {},
   "source": [
    "## Granice interpretacji\n",
    "\n",
    "- KS raportuj jako statystykę D i p-value wraz z liczebnością prób; małe p-value nie określa samo skali ani działania.\n",
    "- Wysoka korelacja lub predictive power nie dowodzi leakage. Sprawdź źródło i moment dostępności.\n",
    "- Drift danych jest sygnałem zmiany rozkładu. Retraining jest decyzją po diagnozie wpływu, nie automatyczną reakcją.\n",
    "- Concept drift wymaga informacji o relacji X-y; bez dojrzałych etykiet nie należy go deklarować jako potwierdzonego."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b535eb0f",
   "metadata": {},
   "source": [
    "## Reguła operacyjna laboratorium\n",
    "Selection bias, data drift i leakage wymagają innych dowodów. Różnica reprezentacji próby jest sygnałem ryzyka selection bias, KS jest sygnałem zmiany rozkładu, a leakage ocenia się przede wszystkim przez dostępność cechy względem `t0`. Żaden pojedynczy wynik nie jest automatyczną decyzją o retrainingu."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "93bc1ac0",
   "metadata": {},
   "source": [
    "## Dane wejściowe i manifest\n",
    "Dane: `customer360_reference.csv`, `customer360_current.csv`, `customer360_development_sample.csv`, `feature_timing.csv`.  \n",
    "Opis kolumn i reguł laboratoryjnych: `manifests/M06_data_manifest.csv` w paczce zbiorczej albo `data_manifest.csv` w paczce modułowej."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7094b7f2",
   "metadata": {
    "tags": [
     "setup"
    ]
   },
   "outputs": [],
   "source": [
    "from pathlib import Path\n",
    "import sys\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "\n",
    "DATA_DIR = Path('data')\n",
    "if not DATA_DIR.exists():\n",
    "    DATA_DIR = Path('..') / 'data'\n",
    "assert DATA_DIR.exists(), 'Nie znaleziono katalogu data. Uruchom notebook z katalogu paczki lub zachowaj strukturę ZIP.'\n",
    "print('Python:', sys.version.split()[0])\n",
    "print('pandas:', pd.__version__)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fa29caf8",
   "metadata": {},
   "source": [
    "## 1. Profil reference vs current\n",
    "\n",
    "Porównaj liczebność, braki i podstawowe statystyki wieku oraz dochodu."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "96f68247",
   "metadata": {
    "tags": [
     "exercise"
    ]
   },
   "outputs": [],
   "source": [
    "ref=pd.read_csv(DATA_DIR/'customer360_reference.csv')\n",
    "cur=pd.read_csv(DATA_DIR/'customer360_current.csv')\n",
    "# TODO: profile"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f01650ce",
   "metadata": {},
   "source": [
    "## 2. Audyt ryzyka selection bias\n",
    "\n",
    "Porównaj populację referencyjną z próbką `customer360_development_sample.csv`, która w syntetycznym case powstała z nierównym prawdopodobieństwem włączenia rekordów z różnych kanałów. Policz udziały `channel` i różnice udziałów.\n",
    "\n",
    "To jest **test reprezentatywności próby**, a nie pełny audyt fairness ani dowód dyskryminacji. Nie stosuj uniwersalnego progu „biasu”; wskaż segmenty nad- i niedoreprezentowane oraz możliwy mechanizm selekcji."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "165958e8",
   "metadata": {},
   "outputs": [],
   "source": [
    "dev=pd.read_csv(DATA_DIR/'customer360_development_sample.csv')\n",
    "selection_check=pd.DataFrame(columns=['reference_share','development_share','pp_diff','representation_ratio'])\n",
    "# TODO: porównaj udziały channel w ref i dev.\n",
    "display(selection_check)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f4323800",
   "metadata": {},
   "source": [
    "## 3. Test KS dla data drift\n",
    "\n",
    "Wykonaj KS dla `age` pomiędzy `reference` i `current`. Zapisz statystykę D, p-value i liczebności. Małe p-value nie określa automatycznie skali wpływu ani działania."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "42a3b374",
   "metadata": {
    "tags": [
     "exercise"
    ]
   },
   "outputs": [],
   "source": [
    "from scipy.stats import ks_2samp\n",
    "# TODO: ks_age"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b63eebbf",
   "metadata": {},
   "source": [
    "## 4. Audyt osi czasu cech i ryzyka leakage\n",
    "\n",
    "Wczytaj `feature_timing.csv` i wskaż cechy dostępne dopiero po `t0`. Wysoka korelacja nie jest dowodem leakage; w tym ćwiczeniu głównym dowodem ryzyka jest moment dostępności cechy względem decyzji."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c6e1eca2",
   "metadata": {
    "tags": [
     "exercise"
    ]
   },
   "outputs": [],
   "source": [
    "timing=pd.read_csv(DATA_DIR/'feature_timing.csv')\n",
    "# TODO: suspicious"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d927ecbc",
   "metadata": {},
   "source": [
    "## 5. Mini-raport\n",
    "\n",
    "Oddziel trzy różne klasy obserwacji:\n",
    "- reprezentatywność próby development,\n",
    "- zmianę rozkładu reference→current,\n",
    "- dostępność cechy względem `t0`.\n",
    "\n",
    "Dla każdej zapisz hipotezę, potrzebny dowód i możliwe działanie."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "def4c7eb",
   "metadata": {
    "tags": [
     "exercise"
    ]
   },
   "outputs": [],
   "source": [
    "report=pd.DataFrame(columns=['risk_class','observation','hypothesis','evidence_needed','possible_action'])\n",
    "# TODO: dodaj osobne wiersze dla selection bias risk, data drift i leakage risk.\n",
    "display(report)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "925118a2",
   "metadata": {},
   "source": [
    "## Zadanie rozszerzające\n",
    "\n",
    "Porównaj wyniki modelu lub metrykę DQ pomiędzy kanałami, ale nie interpretuj różnicy jako dowodu niesprawiedliwości bez zdefiniowania grup, celu, procesu selekcji i kryterium oceny."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f82255d7",
   "metadata": {},
   "source": [
    "## Kryteria akceptacji ćwiczenia\n",
    "- porównujesz strukturę kanałów próby development z populacją referencyjną i opisujesz ryzyko selection bias\n",
    "- KS raportujesz jako D, p-value oraz liczebności, bez automatycznej decyzji\n",
    "- cechy dostępne po t0 są oznaczone jako ryzyko point-in-time/leakage i wymagają weryfikacji pipeline’u\n",
    "\n",
    "Przed oddaniem wykonaj **Restart Kernel and Run All**. Notebook nie powinien zależeć od ręcznie ustawionego stanu poprzednich komórek."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d09123fc",
   "metadata": {},
   "source": [
    "## Co oddajesz\n",
    "\n",
    "Zachowaj tabelę lub wykres będący wynikiem ćwiczenia oraz krótki komentarz: **obserwacja → hipoteza → potrzebny dowód → rekomendacja / dalszy krok**. Jeżeli nie da się rozstrzygnąć przyczyny na podstawie danych z notebooka, oznacz ją jako hipotezę i wskaż brakujący artefakt."
   ]
  }
 ],
 "metadata": {
  "course": {
   "generated": "2026-08-28",
   "module": 6,
   "variant": "participant"
  },
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "name": "python",
   "version": "3.x"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
