🎯 Trening Modelu Churn - Deployment Ready¶

📋 Kontekst projektu¶

⚠️ UWAGA: Model churn był już szczegółowo:

  • Trenowany w projekcie 04 (churn_overfitting)
  • Optymalizowany i tuningowany w projekcie 05 (churn_model_tuning)
  • Analizowany w projekcie 06 (churn_recall_threshold)

Dlaczego trenujemy go ponownie tutaj?

  1. Przejrzystość - Projekt 07 pokazuje pełny proces deployment od A do Z
  2. Spójność - Wszystko w jednym miejscu (trening → predykcje)
  3. Samodzielność - Możesz używać tego projektu niezależnie od poprzednich
  4. Best practice - W produkcji masz pełną kontrolę nad treningiem i zapisem modelu

Ten notebook to wersja produkcyjna - prostsza, gotowa do użycia w realnym środowisku.

Krok 1: Import bibliotek¶

In [1]:
# Importujemy pandas - bibliotekę do pracy z danymi (jak Excel w Pythonie)
import pandas as pd

# Importujemy PyCaret - narzędzie AutoML do klasyfikacji
# To biblioteka która automatyzuje proces uczenia maszynowego
from pycaret.classification import *

# Importujemy json - do zapisywania ustawień modelu (threshold, itp.)
import json

print("✅ Biblioteki zaimportowane!")
✅ Biblioteki zaimportowane!

Krok 2: Wczytanie i przygotowanie danych¶

In [2]:
# Wczytujemy dane klientów z pliku CSV
# CSV = Comma Separated Values (plik tekstowy z danymi oddzielonymi przecinkami)
df = pd.read_csv('data/WA_Fn-UseC_-Telco-Customer-Churn.csv')

# Sprawdzamy ile mamy klientów i kolumn
print(f"📊 Liczba klientów: {len(df)}")
print(f"📋 Liczba kolumn: {len(df.columns)}")

# Wyświetlamy pierwsze 3 wiersze żeby zobaczyć jak wyglądają dane
print("\n🔍 Przykładowe dane:")
df.head(3)
📊 Liczba klientów: 7043
📋 Liczba kolumn: 21

🔍 Przykładowe dane:
Out[2]:
customerID gender SeniorCitizen Partner Dependents tenure PhoneService MultipleLines InternetService OnlineSecurity ... DeviceProtection TechSupport StreamingTV StreamingMovies Contract PaperlessBilling PaymentMethod MonthlyCharges TotalCharges Churn
0 7590-VHVEG Female 0 Yes No 1 No No phone service DSL No ... No No No No Month-to-month Yes Electronic check 29.85 29.85 No
1 5575-GNVDE Male 0 No No 34 Yes No DSL Yes ... Yes No No No One year No Mailed check 56.95 1889.5 No
2 3668-QPYBK Male 0 No No 2 Yes No DSL Yes ... No No No No Month-to-month Yes Mailed check 53.85 108.15 Yes

3 rows × 21 columns

In [3]:
# CZYSZCZENIE DANYCH

# 1. Usuwamy kolumnę customerID
# To tylko identyfikator klienta (jak numer PESEL) - nie pomaga w przewidywaniu
df = df.drop('customerID', axis=1)

# 2. Naprawiamy kolumnę TotalCharges (łączne opłaty)
# Niektóre wartości są tekstem " " zamiast liczb - konwertujemy na liczby
# errors='coerce' oznacza: jak nie da się zamienić na liczbę, wpisz NaN (brak danych)
df['TotalCharges'] = pd.to_numeric(df['TotalCharges'], errors='coerce')

# 3. Wypełniamy brakujące wartości zerem
# Nowi klienci (tenure=0) mają 0 historii płatności - logicznie to ma sens
df['TotalCharges'].fillna(0, inplace=True)

# 4. Sprawdzamy rozkład churn (ile klientów odchodzi vs zostaje)
print("\n📊 Rozkład Churn (czy klient odszedł):")
print(df['Churn'].value_counts())
print(f"\n💡 Procent odchodzących: {(df['Churn'] == 'Yes').sum() / len(df) * 100:.1f}%")

print("\n✅ Dane przygotowane!")
📊 Rozkład Churn (czy klient odszedł):
Churn
No     5174
Yes    1869
Name: count, dtype: int64

💡 Procent odchodzących: 26.5%

✅ Dane przygotowane!

Krok 3: Konfiguracja PyCaret (przygotowanie do treningu)¶

In [4]:
# Inicjalizujemy PyCaret - przygotowujemy środowisko do uczenia maszynowego
# To jak przygotowanie kuchni przed gotowaniem - ustawiamy wszystkie narzędzia

clf_setup = setup(
    data=df,              # Nasze dane
    target='Churn',       # Co chcemy przewidzieć (czy klient odejdzie: Yes/No)
    session_id=123,       # "Ziarnko losowości" - dla powtarzalnych wyników
    train_size=0.8,       # 80% danych do treningu, 20% do testowania
    fold=5,               # 5-fold cross-validation (dzielimy dane na 5 części)
    normalize=True,       # Normalizacja - skalowanie liczb do podobnego zakresu
    verbose=False         # Nie pokazuj szczegółów konfiguracji (mniej tekstu)
)

print("\n✅ PyCaret skonfigurowany!")
print("📊 Dane podzielone: 80% trening, 20% test")
print("🎯 Target: Churn (Yes/No)")
✅ PyCaret skonfigurowany!
📊 Dane podzielone: 80% trening, 20% test
🎯 Target: Churn (Yes/No)

Krok 4: Wybór najlepszego modelu (optymalizacja pod Recall)¶

Co to jest Recall?¶

Recall = Ile % faktycznie odchodzących klientów wykrywamy

Przykład:

  • Jest 100 klientów którzy faktycznie odejdą
  • Model wykrywa 80 z nich
  • Recall = 80%

Dlaczego optymalizujemy pod Recall?¶

W churn prediction gorsze jest przegapienie klienta, który odejdzie, niż fałszywy alarm. Najważniejsze dla nas jest przewidzenie ile będzie przypadków odejścia, dlatego metryka recall najbardziej nadaje się do tego.

In [7]:
# Porównujemy różne algorytmy uczenia maszynowego
# PyCaret automatycznie testuje ~15 różnych modeli (Gradient Boosting, Random Forest, itp.)
# sort='Recall' - wybieramy model który NAJLEPIEJ wykrywa odchodzących klientów
# n_select=1 - wybieramy tylko 1 najlepszy model

print("🔄 Porównywanie modeli...")
print("Szukamy modelu który wykryje NAJWIĘCEJ odchodzących klientów!\n")

# To może zająć 1-2 minuty - PyCaret testuje każdy model na 5-fold cross-validation
best_model = compare_models(sort='Recall', n_select=1)

print("\n✅ Najlepszy model wybrany!")
print(f"📊 Algorytm: {type(best_model).__name__}")
🔄 Porównywanie modeli...
Szukamy modelu który wykryje NAJWIĘCEJ odchodzących klientów!

✅ Najlepszy model wybrany!
📊 Algorytm: LogisticRegression

Krok 5: Zapisanie modelu do pliku¶

In [8]:
# Zapisujemy wytrenowany model do pliku
# To jak zapisanie gry - później możemy go załadować i używać bez ponownego treningu
# PyCaret automatycznie tworzy plik .pkl (pickle) - spakowany model Python

print("💾 Zapisywanie modelu...")

# save_model zapisuje model do folderu models/
save_model(best_model, 'models/churn_model')

print(f"\n✅ Model zapisany jako: models/churn_model.pkl")
print("📦 Plik zawiera: wytrenowany model + preprocessing pipeline")
💾 Zapisywanie modelu...
Transformation Pipeline and Model Successfully Saved

✅ Model zapisany jako: models/churn_model.pkl
📦 Plik zawiera: wytrenowany model + preprocessing pipeline

Krok 6: Zapisanie metadanych (ustawień modelu)¶

Co to są metadata?¶

Metadata = "dane o danych" - informacje opisujące nasz model

Po co zapisujemy metadata?¶

  1. Dokumentacja - Pamiętamy jak model był trenowany (threshold, optymalizacja)
  2. Reprodukowalność - Ktoś inny może zrozumieć ustawienia modelu
  3. Konsystencja - Predykcje używają tych samych ustawień co trening
  4. Wersjonowanie - Wiemy kiedy model był trenowany, jakie miał parametry

Co daje nam to w produkcji?¶

  • ✅ Skrypt predict.py automatycznie odczyta threshold z metadata
  • ✅ Nie trzeba pamiętać jakie były ustawienia
  • ✅ Łatwa zmiana threshold bez zmiany kodu (tylko edycja JSON)
  • ✅ Historia modelu - możesz mieć wiele wersji z różnymi metadata
In [9]:
# METADATA = informacje o modelu (nie sam model, ale jego "instrukcja obsługi")
# Zapisujemy: threshold, pod co optymalizowany, dlaczego takie ustawienia

metadata = {
    "threshold": 0.5,                          # Próg decyzyjny: >= 0.5 = "klient odejdzie"
    "optimized_for": "recall",                 # Model zoptymalizowany pod Recall
    "business_reason": "false negatives are costly",  # Dlaczego? Bo przegapienie klienta odchodzącego = strata pieniędzy
    "model_type": type(best_model).__name__,  # Jaki algorytm użyty (np. GradientBoostingClassifier)
    "train_date": pd.Timestamp.now().strftime("%Y-%m-%d %H:%M:%S")  # Kiedy wytrenowany
}

# Zapisujemy metadata do pliku JSON
# JSON = prosty format tekstowy do przechowywania danych (jak słownik Python)
with open('models/metadata.json', 'w', encoding='utf-8') as f:
    json.dump(metadata, f, indent=2, ensure_ascii=False)

print("💾 Zapisano metadata.json")
print("\n📋 Zawartość:")
print(json.dumps(metadata, indent=2, ensure_ascii=False))

print("\n✅ Model i metadata gotowe do użycia!")
💾 Zapisano metadata.json

📋 Zawartość:
{
  "threshold": 0.5,
  "optimized_for": "recall",
  "business_reason": "false negatives are costly",
  "model_type": "LogisticRegression",
  "train_date": "2026-01-07 20:26:39"
}

✅ Model i metadata gotowe do użycia!

🎉 Podsumowanie¶

Co zrobiliśmy?¶

  1. ✅ Wczytaliśmy i oczyściliśmy dane (7,043 klientów)
  2. ✅ Skonfigurowaliśmy PyCaret (80/20 train/test split)
  3. ✅ Wybraliśmy najlepszy model pod kątem Recall
  4. ✅ Zapisaliśmy model do pliku models/churn_model.pkl
  5. ✅ Zapisaliśmy ustawienia do models/metadata.json

Co dalej?¶

Teraz możemy użyć zapisanego modelu w notebooku predict.ipynb do:

  • Przewidywania churn dla nowych klientów
  • Stosowania threshold do podjęcia decyzji
  • Wdrożenia modelu w produkcji

💡 Kluczowe pliki:¶

  • models/churn_model.pkl - wytrenowany model
  • models/metadata.json - ustawienia (threshold, optymalizacja)

Model jest gotowy do deployment! 🚀