Udostępnij za pośrednictwem


Samouczek: tworzenie, ocena i walidacja modelu przewidywania odejścia klientów

Ten samouczek przedstawia pełny przykład przepływu pracy analizy danych usługi Synapse w usłudze Microsoft Fabric. Scenariusz tworzy model, aby przewidzieć, czy klienci bankowi rezygnują, czy nie. Wskaźnik churn lub wskaźnik odpływu dotyczy tempa, w jakim klienci bankowi rezygnują z usług banku.

Samouczek obejmuje następujące kroki:

  • Instalowanie bibliotek niestandardowych
  • Ładowanie danych
  • Zrozumienie i przetwarzanie danych poprzez eksploracyjną analizę danych oraz pokazanie użycia funkcji Fabric Data Wrangler
  • Użyj bibliotek scikit-learn i LightGBM do trenowania modeli uczenia maszynowego oraz śledzenia eksperymentów za pomocą funkcji autologowania MLflow i Fabric.
  • Ocenianie i zapisywanie końcowego modelu uczenia maszynowego
  • Wyświetlanie wydajności modelu za pomocą wizualizacji usługi Power BI

Warunki wstępne

  • Pobierz subskrypcję usługi Microsoft Fabric . Możesz też utworzyć bezpłatne konto wersji próbnej usługi Microsoft Fabric.

  • Zaloguj się do usługi Microsoft Fabric.

  • Użyj przełącznika doświadczenia w lewej dolnej części strony głównej, aby przełączyć się na Fabric.

    Zrzut ekranu przedstawiający menu przełącznika trybu, pokazujące, gdzie można wybrać opcję Nauka o danych.

Śledź w zeszycie

Możesz wybrać jedną z tych opcji, aby śledzić w notesie:

  • Otwórz i uruchom wbudowany notes.
  • Prześlij swój notatnik z usługi GitHub.

Otwieranie wbudowanego notesu

W tym samouczku towarzyszy przykładowy notatnik odpływu klientów.

  1. Aby otworzyć przykładowy notatnik na potrzeby tego samouczka, postępuj zgodnie z instrukcjami w Przygotuj system do samouczków dotyczących nauki o danych.

  2. Przed rozpoczęciem uruchamiania kodu upewnij się, że dołącz magazyn typu lakehouse do notesu.

Importowanie notesu z usługi GitHub

Notes AIsample — Bank Customer Churn.ipynb towarzyszy temu samouczkowi.

Krok 1. Instalowanie bibliotek niestandardowych

W przypadku tworzenia modeli uczenia maszynowego lub analizy danych ad hoc może być konieczne szybkie zainstalowanie biblioteki niestandardowej na potrzeby sesji platformy Apache Spark. Dostępne są dwie opcje instalowania bibliotek.

  • Użyj funkcji instalacji wbudowanej w notatnik (%pip lub %conda), aby zainstalować bibliotekę wyłącznie w bieżącym notatniku.
  • Alternatywnie możesz utworzyć środowisko Fabric, zainstalować biblioteki ze źródeł publicznych lub przekazać do niego biblioteki niestandardowe, a następnie administrator obszaru roboczego może ustawić środowisko jako domyślne dla obszaru roboczego. Wszystkie biblioteki w środowisku staną się następnie dostępne do użycia w dowolnych notesach i definicjach zadań platformy Spark w obszarze roboczym. Aby uzyskać więcej informacji na temat środowisk, zobacz jak tworzyć, konfigurować i używać środowiska w usłudze Microsoft Fabric.

Na potrzeby tego samouczka użyj %pip install, aby zainstalować bibliotekę imblearn w notesie.

Notatka

Jądro PySpark jest uruchamiane ponownie po uruchomieniu %pip install. Zainstaluj wymagane biblioteki przed uruchomieniem innych komórek.

# Use pip to install libraries
%pip install imblearn

Krok 2. Ładowanie danych

Zestaw danych w churn.csv zawiera status odejścia 10 000 klientów oraz 14 atrybutów, które obejmują:

  • Ocena kredytowa
  • Lokalizacja geograficzna (Niemcy, Francja, Hiszpania)
  • Płeć (mężczyzna, kobieta)
  • Wiek
  • Kadencja (liczba lat, w których dana osoba była klientem w tym banku)
  • Saldo konta
  • Szacowane wynagrodzenie
  • Liczba produktów zakupionych przez klienta za pośrednictwem banku
  • Stan karty kredytowej (niezależnie od tego, czy klient ma kartę kredytową)
  • Stan aktywnego członka (niezależnie od tego, czy dana osoba jest aktywnym klientem banku)

Zestaw danych zawiera również kolumny: numer wiersza, identyfikator klienta i nazwisko klienta. Wartości w tych kolumnach nie powinny mieć wpływu na decyzję klienta o opuszczeniu banku.

Zdarzenie zamknięcia konta bankowego klienta definiuje utratę klienta. Kolumna Exited zestawu danych odnosi się do odejścia klienta. Ponieważ mamy niewielki kontekst dotyczący tych atrybutów, nie potrzebujemy podstawowych informacji o zestawie danych. Chcemy zrozumieć, jak te atrybuty przyczyniają się do stanu Exited.

Spośród tych 10 000 klientów tylko 2037 klientów (około 20%) opuściło bank. Ze względu na współczynnik dysproporcji klas zaleca się generowanie danych syntetycznych. Dokładność macierzy pomyłek może nie mieć znaczenia dla niezrównoważonych klasyfikacji. Możemy chcieć zmierzyć dokładność przy użyciu obszaru pod krzywą Precision-Recall (AUPRC).

  • W tej tabeli przedstawiono podgląd danych churn.csv:
Identyfikator klienta Nazwisko KredytScore Geografia Płeć Wiek Stanowisko Saldo NumOfProducts HasCrCard CzyAktywnyCzłonek Szacowana pensja Opuszczony
15634602 Hargrave 619 Francja Kobieta 42 2 0.00 1 1 1 101348.88 1
15647311 Wzgórze 608 Hiszpania Kobieta 41 1 83807.86 1 0 1 112542.58 0

Pobierz zestaw danych i prześlij do Lakehouse.

Zdefiniuj te parametry, aby można było używać tego notesu z różnymi zestawami danych:

IS_CUSTOM_DATA = False  # If TRUE, the dataset has to be uploaded manually

IS_SAMPLE = False  # If TRUE, use only SAMPLE_ROWS of data for training; otherwise, use all data
SAMPLE_ROWS = 5000  # If IS_SAMPLE is True, use only this number of rows for training

DATA_ROOT = "/lakehouse/default"
DATA_FOLDER = "Files/churn"  # Folder with data files
DATA_FILE = "churn.csv"  # Data file name

Ten kod pobiera publicznie dostępną wersję zestawu danych, a następnie przechowuje ten zestaw danych w usłudze Fabric Lakehouse:

Ważny

Dodaj lakehouse do zeszytu przed jego uruchomieniem. Niepowodzenie w tym celu spowoduje wystąpienie błędu.

import os, requests
if not IS_CUSTOM_DATA:
# With an Azure Synapse Analytics blob, this can be done in one line

# Download demo data files into the lakehouse if they don't exist
    remote_url = "https://synapseaisolutionsa.blob.core.windows.net/public/bankcustomerchurn"
    file_list = ["churn.csv"]
    download_path = "/lakehouse/default/Files/churn/raw"

    if not os.path.exists("/lakehouse/default"):
        raise FileNotFoundError(
            "Default lakehouse not found, please add a lakehouse and restart the session."
        )
    os.makedirs(download_path, exist_ok=True)
    for fname in file_list:
        if not os.path.exists(f"{download_path}/{fname}"):
            r = requests.get(f"{remote_url}/{fname}", timeout=30)
            with open(f"{download_path}/{fname}", "wb") as f:
                f.write(r.content)
    print("Downloaded demo data files into lakehouse.")

Rozpocznij rejestrowanie czasu potrzebnego do uruchomienia notesu:

# Record the notebook running time
import time

ts = time.time()

Odczyt danych surowych z lakehouse

Ten kod odczytuje nieprzetworzone dane z sekcji Files w Lakehouse i dodaje więcej kolumn dla różnych części daty. Tworzenie partycjonowanej tabeli Delta używa tych informacji.

df = (
    spark.read.option("header", True)
    .option("inferSchema", True)
    .csv("Files/churn/raw/churn.csv")
    .cache()
)

Tworzenie ramki danych pandas na podstawie zestawu danych

Ten kod konwertuje ramkę danych platformy Spark na ramkę danych biblioteki pandas, aby ułatwić przetwarzanie i wizualizację:

df = df.toPandas()

Krok 3. Wykonywanie eksploracyjnej analizy danych

Wyświetlanie danych pierwotnych

Eksploruj dane pierwotne za pomocą display, oblicz kilka podstawowych statystyk i wyświetl widoki wykresów. Najpierw należy zaimportować wymagane biblioteki do wizualizacji danych — na przykład seaborn. Seaborn to biblioteka wizualizacji danych języka Python, która udostępnia interfejs wysokiego poziomu umożliwiający tworzenie wizualizacji na ramkach danych i tablicach.

import seaborn as sns
sns.set_theme(style="whitegrid", palette="tab10", rc = {'figure.figsize':(9,6)})
import matplotlib.pyplot as plt
import matplotlib.ticker as mticker
from matplotlib import rc, rcParams
import numpy as np
import pandas as pd
import itertools
display(df, summary=True)

Wykonywanie początkowego czyszczenia danych przy użyciu narzędzia Data Wrangler

Uruchom narzędzie Data Wrangler bezpośrednio z notesu, aby eksplorować i przekształcać ramki danych biblioteki pandas. Wybierz listę rozwijaną Data Wrangler z poziomego paska narzędzi, aby przejrzeć aktywowane ramki danych pandas dostępne do edycji. Wybierz ramkę danych, którą chcesz otworzyć w narzędziu Data Wrangler.

Notatka

Nie można otworzyć Data Wrangler, gdy jądro notesu jest zajęte. Wykonanie komórki musi zakończyć się przed uruchomieniem narzędzia Data Wrangler. dowiedz się więcej o usłudze Data Wrangler.

Zrzut ekranu pokazujący, gdzie uzyskać dostęp do usługi Data Wrangler.

Po uruchomieniu narzędzia Data Wrangler zostanie wygenerowane opisowe omówienie panelu danych, jak pokazano na poniższych obrazach. Omówienie zawiera informacje o wymiarze ramki danych, brakujących wartościach itp. Za pomocą narzędzia Data Wrangler można wygenerować skrypt, aby usunąć wiersze z brakującymi wartościami, zduplikowane wiersze i kolumny o określonych nazwach. Następnie możesz skopiować skrypt do komórki. Następna komórka pokazuje skopiowany skrypt.

Zrzut ekranu przedstawiający menu Data Wrangler.

Zrzut ekranu przedstawiający brakujące dane w narzędziu Data Wrangler.

def clean_data(df):
    # Drop rows with missing data across all columns
    df.dropna(inplace=True)
    # Drop duplicate rows in columns: 'RowNumber', 'CustomerId'
    df.drop_duplicates(subset=['RowNumber', 'CustomerId'], inplace=True)
    # Drop columns: 'RowNumber', 'CustomerId', 'Surname'
    df.drop(columns=['RowNumber', 'CustomerId', 'Surname'], inplace=True)
    return df

df_clean = clean_data(df.copy())

Określanie atrybutów

Ten kod określa atrybuty kategorii, liczbowe i docelowe:

# Determine the dependent (target) attribute
dependent_variable_name = "Exited"
print(dependent_variable_name)
# Determine the categorical attributes
categorical_variables = [col for col in df_clean.columns if col in "O"
                        or df_clean[col].nunique() <=5
                        and col not in "Exited"]
print(categorical_variables)
# Determine the numerical attributes
numeric_variables = [col for col in df_clean.columns if df_clean[col].dtype != "object"
                        and df_clean[col].nunique() >5]
print(numeric_variables)

Pokaż podsumowanie z pięcioma liczbami

Użyj wykresów pól, aby wyświetlić podsumowanie z pięcioma liczbami

  • minimalny wynik
  • pierwszy kwartyl
  • mediana
  • trzeci kwartyl
  • maksymalny wynik

dla atrybutów liczbowych.

df_num_cols = df_clean[numeric_variables]
sns.set(font_scale = 0.7) 
fig, axes = plt.subplots(nrows = 2, ncols = 3, gridspec_kw =  dict(hspace=0.3), figsize = (17,8))
fig.tight_layout()
for ax,col in zip(axes.flatten(), df_num_cols.columns):
    sns.boxplot(x = df_num_cols[col], color='green', ax = ax)
# fig.suptitle('visualize and compare the distribution and central tendency of numerical attributes', color = 'k', fontsize = 12)
fig.delaxes(axes[1,2])

Zrzut ekranu przedstawiający wyświetlacz notesu z wykresem pudełkowym dla atrybutów liczbowych.

Pokaż rozmieszczenie utraconych i pozostających klientów

Pokaż dystrybucję klientów, którzy zrezygnowali, w porównaniu z tymi, którzy nie zrezygnowali, w odniesieniu do atrybutów kategorycznych.

attr_list = ['Geography', 'Gender', 'HasCrCard', 'IsActiveMember', 'NumOfProducts', 'Tenure']
fig, axarr = plt.subplots(2, 3, figsize=(15, 4))
for ind, item in enumerate (attr_list):
    sns.countplot(x = item, hue = 'Exited', data = df_clean, ax = axarr[ind%2][ind//2])
fig.subplots_adjust(hspace=0.7)

Zrzut ekranu przedstawiający notebook komputerowy z dystrybucją klientów, którzy zakończyli relację z firmą, a tych, którzy nie zakończyli.

Pokaż rozkład atrybutów liczbowych

Użyj histogramu, aby wyświetlić rozkład częstotliwości atrybutów liczbowych:

columns = df_num_cols.columns[: len(df_num_cols.columns)]
fig = plt.figure()
fig.set_size_inches(18, 8)
length = len(columns)
for i,j in itertools.zip_longest(columns, range(length)):
    plt.subplot((length // 2), 3, j+1)
    plt.subplots_adjust(wspace = 0.2, hspace = 0.5)
    df_num_cols[i].hist(bins = 20, edgecolor = 'black')
    plt.title(i)
# fig = fig.suptitle('distribution of numerical attributes', color = 'r' ,fontsize = 14)
plt.show()

Zrzut ekranu pokazujący ekran notesu z atrybutami liczbowymi.

Wykonywanie inżynierii cech

Ta inżynieria cech generuje nowe atrybuty na podstawie bieżących atrybutów:

df_clean["NewTenure"] = df_clean["Tenure"]/df_clean["Age"]
df_clean["NewCreditsScore"] = pd.qcut(df_clean['CreditScore'], 6, labels = [1, 2, 3, 4, 5, 6])
df_clean["NewAgeScore"] = pd.qcut(df_clean['Age'], 8, labels = [1, 2, 3, 4, 5, 6, 7, 8])
df_clean["NewBalanceScore"] = pd.qcut(df_clean['Balance'].rank(method="first"), 5, labels = [1, 2, 3, 4, 5])
df_clean["NewEstSalaryScore"] = pd.qcut(df_clean['EstimatedSalary'], 10, labels = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])

Używanie narzędzia Data Wrangler do wykonywania kodowania jednorazowego

Korzystając z tych samych kroków, które omówiono wcześniej do uruchomienia narzędzia Data Wrangler, wykonaj kodowanie one-hot przy użyciu tego narzędzia. W tej komórce zostanie wyświetlony skopiowany skrypt wygenerowany na potrzeby kodowania jednokrotnego:

Zrzut ekranu przedstawiający kodowanie jednorazowe w narzędziu Data Wrangler.

Zrzut ekranu przedstawiający wybór kolumn w narzędziu Data Wrangler.

df_clean = pd.get_dummies(df_clean, columns=['Geography', 'Gender'])

Utwórz tabelę delta w celu wygenerowania raportu Power BI

table_name = "df_clean"
# Create a PySpark DataFrame from pandas
sparkDF=spark.createDataFrame(df_clean) 
sparkDF.write.mode("overwrite").format("delta").save(f"Tables/{table_name}")
print(f"Spark DataFrame saved to delta table: {table_name}")

Podsumowanie obserwacji z eksploracyjnej analizy danych

  • Większość klientów pochodzi z Francji. Hiszpania ma najniższy wskaźnik zmian, w porównaniu z Francją i Niemcami.
  • Większość klientów ma karty kredytowe
  • Niektórzy klienci mają zarówno ponad 60 lat, jak i wyniki kredytowe poniżej 400. Nie można ich jednak traktować jako wartości odstające
  • Bardzo niewielu klientów ma więcej niż dwa produkty bankowe
  • Nieaktywni klienci mają wyższy współczynnik zmian
  • Płeć i czas użytkowania mają niewielki wpływ na decyzję klienta o zamknięciu konta bankowego

Krok 4: Przeprowadzanie trenowania i śledzenia modelu

Dzięki danym można teraz zdefiniować model. Zastosuj modele lasu losowego i LightGBM w tym notatniku.

Użyj bibliotek scikit-learn i LightGBM, aby zaimplementować modele z kilkoma wierszami kodu. Ponadto użyj autologowania MLflow i Fabric do śledzenia eksperymentów.

Ten przykładowy fragment kodu ładuje tabelę delta z lakehouse. Możesz użyć innych tabel różnicowych, które same korzystają z lakehouse jako źródła.

SEED = 12345
df_clean = spark.read.format("delta").load("Tables/df_clean").toPandas()

Generowanie eksperymentu na potrzeby śledzenia i rejestrowania modeli przy użyciu biblioteki MLflow

W tej sekcji przedstawiono sposób generowania eksperymentu oraz określa on parametry modelu i trenowania oraz metryki oceniania. Ponadto pokazuje, jak trenować modele, rejestrować je i zapisywać wytrenowane modele do późniejszego użycia.

import mlflow

# Set up the experiment name
EXPERIMENT_NAME = "sample-bank-churn-experiment"  # MLflow experiment name

Automatyczne rejestrowanie automatycznie przechwytuje zarówno wartości parametrów wejściowych, jak i metryki wyjściowe modelu uczenia maszynowego, ponieważ ten model jest trenowany. Te informacje są następnie rejestrowane w obszarze roboczym, gdzie interfejsy API MLflow lub odpowiedni eksperyment w obszarze roboczym mogą uzyskiwać do niego dostęp i wizualizować je.

Po zakończeniu eksperyment przypomina ten obraz:

Zrzut ekranu przedstawiający stronę eksperymentu dotyczącego odejść klientów z banku.

Wszystkie eksperymenty z odpowiednimi nazwami są rejestrowane i można śledzić ich parametry i metryki wydajności. Aby dowiedzieć się więcej na temat automatycznego rejestrowania, zobacz automatyczne rejestrowanie w usłudze Microsoft Fabric.

Ustawianie specyfikacji eksperymentu i automatycznego rejestrowania

mlflow.set_experiment(EXPERIMENT_NAME) # Use a date stamp to append to the experiment
mlflow.autolog(exclusive=False)

Importowanie biblioteki scikit-learn i lightGBM

# Import the required libraries for model training
from sklearn.model_selection import train_test_split
from lightgbm import LGBMClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score, f1_score, precision_score, confusion_matrix, recall_score, roc_auc_score, classification_report

Przygotowywanie zestawów danych trenowania i testowania

y = df_clean["Exited"]
X = df_clean.drop("Exited",axis=1)
# Train/test separation
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.20, random_state=SEED)

Stosowanie narzędzia SMOTE do danych treningowych

Niezrównoważona klasyfikacja ma problem, ponieważ ma zbyt mało przykładów klasy mniejszości, aby model mógł skutecznie nauczyć się granicy decyzyjnej. Aby to zrobić, Syntetyczna technika mniejszościowego nadpróbkowania (SMOTE) jest najczęściej stosowaną metodą do syntezowania nowych próbek dla klasy mniejszościowej. Uzyskaj dostęp do narzędzia SMOTE przy użyciu biblioteki imblearn zainstalowanej w kroku 1.

Zastosuj smOTE tylko do zestawu danych szkoleniowych. Aby uzyskać prawidłowe przybliżenie działania modelu na oryginalnych danych, należy pozostawić zestaw danych testowych w jego pierwotnej, niezrównoważonej dystrybucji. Ten eksperyment reprezentuje sytuację w środowisku produkcyjnym.

from collections import Counter
from imblearn.over_sampling import SMOTE

sm = SMOTE(random_state=SEED)
X_res, y_res = sm.fit_resample(X_train, y_train)
new_train = pd.concat([X_res, y_res], axis=1)

Aby uzyskać więcej informacji, zobacz SMOTE i Od losowego nadpróbkowania do SMOTE i ADASYN. Witryna imbalanced-learn hostuje te zasoby.

Trenowanie modelu

Użyj Random Forest do wytrenowania modelu z maksymalną głębokością czterech i czterema cechami:

mlflow.sklearn.autolog(registered_model_name='rfc1_sm')  # Register the trained model with autologging
rfc1_sm = RandomForestClassifier(max_depth=4, max_features=4, min_samples_split=3, random_state=1) # Pass hyperparameters
with mlflow.start_run(run_name="rfc1_sm") as run:
    rfc1_sm_run_id = run.info.run_id # Capture run_id for model prediction later
    print("run_id: {}; status: {}".format(rfc1_sm_run_id, run.info.status))
    # rfc1.fit(X_train,y_train) # Imbalanced training data
    rfc1_sm.fit(X_res, y_res.ravel()) # Balanced training data
    rfc1_sm.score(X_test, y_test)
    y_pred = rfc1_sm.predict(X_test)
    cr_rfc1_sm = classification_report(y_test, y_pred)
    cm_rfc1_sm = confusion_matrix(y_test, y_pred)
    roc_auc_rfc1_sm = roc_auc_score(y_res, rfc1_sm.predict_proba(X_res)[:, 1])

Użyj algorytmu Random Forest do wytrenowania modelu z maksymalną głębokością ośmiu i sześcioma cechami.

mlflow.sklearn.autolog(registered_model_name='rfc2_sm')  # Register the trained model with autologging
rfc2_sm = RandomForestClassifier(max_depth=8, max_features=6, min_samples_split=3, random_state=1) # Pass hyperparameters
with mlflow.start_run(run_name="rfc2_sm") as run:
    rfc2_sm_run_id = run.info.run_id # Capture run_id for model prediction later
    print("run_id: {}; status: {}".format(rfc2_sm_run_id, run.info.status))
    # rfc2.fit(X_train,y_train) # Imbalanced training data
    rfc2_sm.fit(X_res, y_res.ravel()) # Balanced training data
    rfc2_sm.score(X_test, y_test)
    y_pred = rfc2_sm.predict(X_test)
    cr_rfc2_sm = classification_report(y_test, y_pred)
    cm_rfc2_sm = confusion_matrix(y_test, y_pred)
    roc_auc_rfc2_sm = roc_auc_score(y_res, rfc2_sm.predict_proba(X_res)[:, 1])

Trenowanie modelu za pomocą rozwiązania LightGBM:

# lgbm_model
mlflow.lightgbm.autolog(registered_model_name='lgbm_sm')  # Register the trained model with autologging
lgbm_sm_model = LGBMClassifier(learning_rate = 0.07, 
                        max_delta_step = 2, 
                        n_estimators = 100,
                        max_depth = 10, 
                        eval_metric = "logloss", 
                        objective='binary', 
                        random_state=42)

with mlflow.start_run(run_name="lgbm_sm") as run:
    lgbm1_sm_run_id = run.info.run_id # Capture run_id for model prediction later
    # lgbm_sm_model.fit(X_train,y_train) # Imbalanced training data
    lgbm_sm_model.fit(X_res, y_res.ravel()) # Balanced training data
    y_pred = lgbm_sm_model.predict(X_test)
    accuracy = accuracy_score(y_test, y_pred)
    cr_lgbm_sm = classification_report(y_test, y_pred)
    cm_lgbm_sm = confusion_matrix(y_test, y_pred)
    roc_auc_lgbm_sm = roc_auc_score(y_res, lgbm_sm_model.predict_proba(X_res)[:, 1])

Wyświetlanie artefaktu eksperymentu w celu śledzenia wydajności modelu

Przebiegi eksperymentu są automatycznie zapisywane w dokumentacji eksperymentu. Ten artefakt można znaleźć w obszarze roboczym. Nazwa artefaktu jest oparta na nazwie użytej do ustawienia eksperymentu. Wszystkie wytrenowane modele, ich przebiegi, metryki wydajności i parametry modelu są rejestrowane na stronie eksperymentu.

Aby obejrzeć eksperymenty:

  1. Na panelu po lewej stronie wybierz swój obszar roboczy.
  2. Znajdź i wybierz nazwę eksperymentu, w tym przypadku sample-bank-churn-experiment.

Zrzut ekranu przedstawiający zarejestrowane wartości dla jednego z modeli.

Krok 5. Ocena i zapisanie końcowego modelu uczenia maszynowego

Otwórz zapisany eksperyment z obszaru roboczego, aby wybrać i zapisać najlepszy model:

# Define run_uri to fetch the model
# MLflow client: mlflow.model.url, list model
load_model_rfc1_sm = mlflow.sklearn.load_model(f"runs:/{rfc1_sm_run_id}/model")
load_model_rfc2_sm = mlflow.sklearn.load_model(f"runs:/{rfc2_sm_run_id}/model")
load_model_lgbm1_sm = mlflow.lightgbm.load_model(f"runs:/{lgbm1_sm_run_id}/model")

Ocena wydajności zapisanych modeli w zestawie danych testowych

ypred_rfc1_sm = load_model_rfc1_sm.predict(X_test) # Random forest with maximum depth of 4 and 4 features
ypred_rfc2_sm = load_model_rfc2_sm.predict(X_test) # Random forest with maximum depth of 8 and 6 features
ypred_lgbm1_sm = load_model_lgbm1_sm.predict(X_test) # LightGBM

Pokaż prawdziwie/fałszywie dodatnie/ujemne wyniki przy użyciu macierzy pomyłek

Aby ocenić dokładność klasyfikacji, utwórz skrypt, który rysuje macierz pomyłek. Macierz pomyłek można również wykreślić przy użyciu narzędzi SynapseML, jak pokazano w przykładzie wykrywania oszustw .

def plot_confusion_matrix(cm, classes,
                          normalize=False,
                          title='Confusion matrix',
                          cmap=plt.cm.Blues):
    print(cm)
    plt.figure(figsize=(4,4))
    plt.rcParams.update({'font.size': 10})
    plt.imshow(cm, interpolation='nearest', cmap=cmap)
    plt.title(title)
    plt.colorbar()
    tick_marks = np.arange(len(classes))
    plt.xticks(tick_marks, classes, rotation=45, color="blue")
    plt.yticks(tick_marks, classes, color="blue")

    fmt = '.2f' if normalize else 'd'
    thresh = cm.max() / 2.
    for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])):
        plt.text(j, i, format(cm[i, j], fmt),
                 horizontalalignment="center",
                 color="red" if cm[i, j] > thresh else "black")

    plt.tight_layout()
    plt.ylabel('True label')
    plt.xlabel('Predicted label')

Utwórz macierz pomyłek dla klasyfikatora lasu losowego o maksymalnej głębokości czterech, z czterema cechami.

cfm = confusion_matrix(y_test, y_pred=ypred_rfc1_sm)
plot_confusion_matrix(cfm, classes=['Non Churn','Churn'],
                      title='Random Forest with max depth of 4')
tn, fp, fn, tp = cfm.ravel()

Zrzut ekranu przedstawiający wyświetlacz notatnika z macierzą pomyłek dla lasu losowego z maksymalną głębokością czterech.

Utwórz macierz pomyłek dla klasyfikatora lasu losowego z maksymalną głębokością ośmiu, z sześcioma funkcjami:

cfm = confusion_matrix(y_test, y_pred=ypred_rfc2_sm)
plot_confusion_matrix(cfm, classes=['Non Churn','Churn'],
                      title='Random Forest with max depth of 8')
tn, fp, fn, tp = cfm.ravel()

Zrzut ekranu przedstawiający notes z macierzą pomyłek dla lasu losowego o maksymalnej głębokości ośmiu.

Utwórz macierz błędów dla modelu LightGBM.

cfm = confusion_matrix(y_test, y_pred=ypred_lgbm1_sm)
plot_confusion_matrix(cfm, classes=['Non Churn','Churn'],
                      title='LightGBM')
tn, fp, fn, tp = cfm.ravel()

Zrzut ekranu przedstawiający notes przedstawiający macierz pomyłek dla usługi LightGBM.

Zapisywanie wyników dla usługi Power BI

Zapisz ramkę delta do Lakehouse, aby przenieść wyniki przewidywania modelu do wizualizacji w Power BI.

df_pred = X_test.copy()
df_pred['y_test'] = y_test
df_pred['ypred_rfc1_sm'] = ypred_rfc1_sm
df_pred['ypred_rfc2_sm'] =ypred_rfc2_sm
df_pred['ypred_lgbm1_sm'] = ypred_lgbm1_sm
table_name = "df_pred_results"
sparkDF=spark.createDataFrame(df_pred)
sparkDF.write.mode("overwrite").format("delta").option("overwriteSchema", "true").save(f"Tables/{table_name}")
print(f"Spark DataFrame saved to delta table: {table_name}")

Krok 6. Uzyskiwanie dostępu do wizualizacji w usłudze Power BI

Uzyskaj dostęp do zapisanej tabeli w usłudze Power BI:

  1. Po lewej stronie wybierz pozycję OneLake.
  2. Wybierz lakehouse, który dodałeś do tego notesu.
  3. W sekcji Open this Lakehouse wybierz pozycję Otwórz.
  4. Na wstążce wybierz pozycję Nowy model semantyczny. Wybierz pozycję df_pred_results, a następnie wybierz pozycję Potwierdź, aby utworzyć nowy model semantyczny usługi Power BI połączony z przewidywaniami.
  5. Otwórz nowy model semantyczny. Możesz go znaleźć w usłudze OneLake.
  6. Wybierz pozycję Utwórz nowy raport w menu Plik z narzędzi w górnej części strony modeli semantycznych, aby otworzyć stronę autorstwa raportu Power BI.

Poniższy zrzut ekranu przedstawia przykładowe wizualizacje. Panel danych pokazuje tabele delta i kolumny do wyboru z tabeli. Po wybraniu odpowiedniej kategorii (x) i osi wartości (y) można wybrać filtry i funkcje — na przykład sumę lub średnią kolumny tabeli.

Notatka

Na tym zrzucie ekranu zilustrowany przykład opisuje analizę zapisanych wyników przewidywania w usłudze Power BI:

Zrzut ekranu przedstawiający przykład pulpitu nawigacyjnego usługi Power BI.

Jednak w przypadku rzeczywistego przypadku użycia współczynnika zmian klientów użytkownik może potrzebować bardziej szczegółowego zestawu wymagań wizualizacji do utworzenia, na podstawie wiedzy specjalistycznej oraz tego, co firma i zespół ds. analizy biznesowej i firma ustandaryzowały jako metryki.

Raport usługi Power BI pokazuje, że klienci korzystający z więcej niż dwóch produktów bankowych mają wyższy współczynnik zmian. Jednak niewielu klientów miało więcej niż dwa produkty. (Zobacz wykres w lewym dolnym panelu). Bank powinien zbierać więcej danych, ale powinien również zbadać inne funkcje, które są skorelowane z większą liczbą produktów.

Klienci bankowi w Niemczech mają wyższy współczynnik zmian w porównaniu z klientami we Francji i Hiszpanii. (Zobacz wykres w prawym dolnym panelu). Na podstawie wyników raportu badanie czynników, które zachęciły klientów do opuszczenia, może pomóc.

Istnieje więcej klientów w średnim wieku (od 25 do 45). Klienci w wieku od 45 do 60 lat mają tendencję do częstszego odchodzenia.

Na koniec klienci z niższymi ocenami kredytowymi najprawdopodobniej opuściliby bank dla innych instytucji finansowych. Bank powinien zbadać sposoby zachęcania klientów o niższych ocenach kredytowych i saldach kont, aby pozostać w banku.

# Determine the entire runtime
print(f"Full run cost {int(time.time() - ts)} seconds.")