Przejdź do głównej zawartości

practise

ćwiczenia praktyczne - narzędzia ML ⭐

W tej lekcji połączysz wszystkie poznane narzędzia w praktyczny projekt. Będziesz trenować różne modele, oceniać je za pomocą różnych metryk i optymalizować hiperparametry.

zadanie główne: klasyfikacja klientów banku

Stworzysz model do przewidywania, czy klient banku wykupi produkt finansowy na podstawie jego danych demograficznych i historycznych.

krok 1: przygotowanie danych

import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier
from sklearn.svm import SVC
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score
from sklearn.metrics import confusion_matrix, classification_report
from sklearn.model_selection import GridSearchCV, cross_val_score
import matplotlib.pyplot as plt
import seaborn as sns

# Generowanie syntetycznych danych bankowych
np.random.seed(42)
n_samples = 2000

# Tworzenie cech
age = np.random.normal(45, 15, n_samples)
income = np.random.normal(50000, 20000, n_samples)
credit_score = np.random.normal(700, 100, n_samples)
years_employed = np.random.normal(8, 5, n_samples)
balance = np.random.normal(10000, 5000, n_samples)

# Tworzenie targetu (prawdopodobieństwo zakupu produktu)
purchase_prob = (age/100 + income/100000 + credit_score/1000 +
years_employed/20 + balance/50000) / 5
purchase = (purchase_prob + np.random.normal(0, 0.1, n_samples)) > 0.5

# Tworzenie DataFrame
data = pd.DataFrame({
'age': age,
'income': income,
'credit_score': credit_score,
'years_employed': years_employed,
'balance': balance,
'purchase': purchase
})

print("Rozkład klas:")
print(data['purchase'].value_counts(normalize=True))

krok 2: podział danych i skalowanie

# Podział na cechy i target
X = data.drop('purchase', axis=1)
y = data['purchase']

# Podział na zbiory treningowy i testowy
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42, stratify=y
)

# Skalowanie cech
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)

print(f"Rozmiar zbioru treningowego: {X_train.shape}")
print(f"Rozmiar zbioru testowego: {X_test.shape}")

krok 3: trenowanie różnych modeli

# Lista modeli do porównania
models = {
'Random Forest': RandomForestClassifier(random_state=42),
'Gradient Boosting': GradientBoostingClassifier(random_state=42),
'SVM': SVC(random_state=42)
}

# Słownik na wyniki
results = {}

# Trenowanie i ocena modeli
for name, model in models.items():
print(f"\nTrenowanie {name}...")

# Trenowanie
if name == 'SVM':
model.fit(X_train_scaled, y_train)
y_pred = model.predict(X_train_scaled)
y_pred_test = model.predict(X_test_scaled)
else:
model.fit(X_train, y_train)
y_pred = model.predict(X_train)
y_pred_test = model.predict(X_test)

# Obliczanie metryk
results[name] = {
'train_accuracy': accuracy_score(y_train, y_pred),
'test_accuracy': accuracy_score(y_test, y_pred_test),
'precision': precision_score(y_test, y_pred_test),
'recall': recall_score(y_test, y_pred_test),
'f1': f1_score(y_test, y_pred_test),
'predictions': y_pred_test
}

print(f"Test Accuracy: {results[name]['test_accuracy']:.3f}")
print(f"F1-Score: {results[name]['f1']:.3f}")

krok 4: analiza wyników

# Porównanie modeli
comparison_df = pd.DataFrame({
'Model': list(results.keys()),
'Test Accuracy': [results[name]['test_accuracy'] for name in results.keys()],
'Precision': [results[name]['precision'] for name in results.keys()],
'Recall': [results[name]['recall'] for name in results.keys()],
'F1-Score': [results[name]['f1'] for name in results.keys()]
})

print("\nPorównanie modeli:")
print(comparison_df.sort_values('F1-Score', ascending=False))

# Wizualizacja wyników
plt.figure(figsize=(12, 8))

# Wykres słupkowy metryk
plt.subplot(2, 2, 1)
metrics = ['Test Accuracy', 'Precision', 'Recall', 'F1-Score']
x = np.arange(len(metrics))
width = 0.25

for i, (name, color) in enumerate(zip(results.keys(), ['blue', 'orange', 'green'])):
values = [results[name][metric.lower().replace(' ', '_')] for metric in metrics]
plt.bar(x + i*width, values, width, label=name, color=color)

plt.xlabel('Metryki')
plt.ylabel('Wartość')
plt.title('Porównanie metryk dla różnych modeli')
plt.xticks(x + width, metrics)
plt.legend()
plt.ylim(0, 1)

# Macierze pomyłek
for i, (name, color) in enumerate(zip(results.keys(), ['Blues', 'Oranges', 'Greens'])):
plt.subplot(2, 2, i+2)
cm = confusion_matrix(y_test, results[name]['predictions'])
sns.heatmap(cm, annot=True, fmt='d', cmap=color)
plt.title(f'Macierz pomyłek - {name}')
plt.ylabel('Rzeczywiste')
plt.xlabel('Przewidywane')

plt.tight_layout()
plt.show()

krok 5: tuning hiperparametrów dla najlepszego modelu

# Wybierz najlepszy model na podstawie F1-Score
best_model_name = comparison_df.loc[comparison_df['F1-Score'].idxmax(), 'Model']
print(f"\nNajlepszy model: {best_model_name}")

# Tuning hiperparametrów dla Random Forest
if best_model_name == 'Random Forest':
param_grid = {
'n_estimators': [50, 100, 200],
'max_depth': [5, 10, 15, None],
'min_samples_split': [2, 5, 10],
'min_samples_leaf': [1, 2, 4]
}

grid_search = GridSearchCV(
RandomForestClassifier(random_state=42),
param_grid,
cv=5,
scoring='f1',
n_jobs=-1
)

grid_search.fit(X_train, y_train)

print(f"Najlepsze parametry: {grid_search.best_params_}")
print(f"Najlepszy F1-Score: {grid_search.best_score_:.3f}")

# Ocena na zbiorze testowym
best_model = grid_search.best_estimator_
y_pred_best = best_model.predict(X_test)

print(f"\nWyniki po tuningu:")
print(f"Test Accuracy: {accuracy_score(y_test, y_pred_best):.3f}")
print(f"F1-Score: {f1_score(y_test, y_pred_best):.3f}")

# Feature importance
feature_importance = best_model.feature_importances_
feature_names = X.columns

plt.figure(figsize=(10, 6))
plt.bar(feature_names, feature_importance)
plt.title('Feature Importance - Random Forest')
plt.xlabel('Cechy')
plt.ylabel('Importance')
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()

zadania dodatkowe

  1. Eksperymentuj z różnymi metrykami - spróbuj użyć ROC-AUC zamiast F1-Score do oceny modeli.

  2. Dodaj więcej modeli - przetestuj Logistic Regression, KNN, i Decision Trees.

  3. Analiza błędów - przeanalizuj przypadki, gdzie model popełnia błędy.

  4. Cross-validation - użyj cross-validation do bardziej rzetelnej oceny modeli.

  5. Feature engineering - stwórz nowe cechy (np. stosunek income/age) i sprawdź, czy poprawiają wyniki.

pytania do refleksji

  • Który model okazał się najlepszy i dlaczego?
  • Czy różne metryki dają różne rankingi modeli?
  • Jak można poprawić wyniki modeli?
  • Które cechy są najważniejsze dla przewidywania zakupu produktu?