Udostępnij za pośrednictwem


Samouczek: tworzenie, ocenianie i ocenianie modelu przewidywania zmian

Ten samouczek przedstawia pełny przykład przepływu pracy usługi Synapse Nauka o danych w usłudze Microsoft Fabric. Scenariusz tworzy model, aby przewidzieć, czy klienci bankowi rezygnują. Stopa zmian lub stopa poniżania obejmuje stawkę, w jakiej klienci bankowi kończą swoją działalność z bankiem.

W tym samouczku opisano następujące kroki:

  • Instalowanie bibliotek niestandardowych
  • Ładowanie danych
  • Zrozumienie i przetwarzanie danych za pomocą eksploracyjnej analizy danych oraz pokazanie użycia funkcji Wrangler danych sieci szkieletowej
  • Używanie bibliotek scikit-learn i LightGBM do trenowania modeli uczenia maszynowego oraz śledzenia eksperymentów za pomocą funkcji automatycznego rejestrowania MLflow i fabric
  • Ocenianie i zapisywanie końcowego modelu uczenia maszynowego
  • Wyświetlanie wydajności modelu za pomocą wizualizacji usługi Power BI

Wymagania wstępne

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

  • Zaloguj się do usługi Microsoft Fabric.

  • Użyj przełącznika środowiska po lewej stronie głównej, aby przełączyć się na środowisko usługi Synapse Nauka o danych.

    Screenshot of the experience switcher menu, showing where to select Data Science.

Postępuj zgodnie z instrukcjami w notesie

Możesz wybrać jedną z tych opcji, które należy wykonać w notesie:

  • Otwieranie i uruchamianie wbudowanego notesu w środowisku Nauka o danych
  • Przekazywanie notesu z usługi GitHub do środowiska Nauka o danych

Otwieranie wbudowanego notesu

Przykładowy notes rezygnacji klienta jest dołączony do tego samouczka.

Aby otworzyć wbudowany notes przykładowy samouczka w środowisku usługi Synapse Nauka o danych:

  1. Przejdź do strony głównej usługi Synapse Nauka o danych.

  2. Wybierz pozycję Użyj przykładu.

  3. Wybierz odpowiedni przykład:

    • Na domyślnej karcie Kompleksowe przepływy pracy (Python), jeśli przykład dotyczy samouczka dotyczącego języka Python.
    • Na karcie Kompleksowe przepływy pracy (R), jeśli przykład dotyczy samouczka języka R.
    • Jeśli przykład jest przeznaczony do szybkiego samouczka, na karcie Szybkie samouczki .
  4. Przed rozpoczęciem uruchamiania kodu dołącz usługę Lakehouse do notesu .

Importowanie notesu z usługi GitHub

Notes AIsample — Bank Customer Churn.ipynb jest dołączony do tego samouczka.

Aby otworzyć towarzyszący notes na potrzeby tego samouczka, postępuj zgodnie z instrukcjami w temacie Przygotowywanie systemu do celów nauki o danych, aby zaimportować notes do obszaru roboczego.

Jeśli wolisz skopiować i wkleić kod z tej strony, możesz utworzyć nowy notes.

Przed rozpoczęciem uruchamiania kodu pamiętaj, aby dołączyć usługę Lakehouse do notesu .

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 wbudowanych funkcji instalacji (%pip lub %conda) notesu, aby zainstalować bibliotekę tylko w bieżącym notesie.
  • Alternatywnie możesz utworzyć środowisko sieci szkieletowej, zainstalować biblioteki ze źródeł publicznych lub przekazać do niego biblioteki niestandardowe, a następnie administrator obszaru roboczego może dołączyć ś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 tworzenie, konfigurowanie i używanie środowiska w usłudze Microsoft Fabric.

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

Uwaga

Jądro PySpark jest uruchamiane ponownie po %pip install uruchomieniu. 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 stan zmian 10 000 klientów wraz z 14 atrybutami, 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 współczynnik zmian dla tego klienta. Kolumna zestawu danych Exited odnosi się do porzucenia 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 Exited stanu.

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ą precyzji kompletności (AUPRC).

  • W tej tabeli przedstawiono podgląd churn.csv danych:
CustomerID (Identyfikator klienta) Surname KredytScore Obszar geograficzny Płeć Wiek Stały etat Saldo NumOfProducts HasCrCard IsActiveMember EstimatedSalary Odeszli
15634602 Hargrave 619 Francja Kobieta 42 2 0,00 1 1 1 101348.88 1
15647311 Hill 608 Hiszpania Kobieta 41 1 83807.86 1 0 1 112542.58 0

Pobieranie zestawu danych i przekazywanie do usługi 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żne

Dodaj magazyn lakehouse do notesu 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()

Odczytywanie danych pierwotnych z lakehouse

Ten kod odczytuje nieprzetworzone dane z sekcji Pliki lakehouse i dodaje więcej kolumn dla różnych części dat. Utworzenie partycjonowanej tabeli różnicowej 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

Zapoznaj się z danymi nieprzetworzonymi za pomocą displaymetody , 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. Na karcie Dane wstążki notesu użyj monitu rozwijanego Data Wrangler, aby przejrzeć aktywowane ramki danych pandas dostępne do edycji. Wybierz ramkę danych, którą chcesz otworzyć w narzędziu Data Wrangler.

Uwaga

Nie można otworzyć narzędzia Wrangler danych, 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.

Screenshot that shows where to access 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.

Screenshot that shows the Data Wrangler menu.

Screenshot that shows missing data in 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])

Screenshot that shows a notebook display of the box plot for numerical attributes.

Pokaż dystrybucję wycofanych i niezwiązanych klientów

Pokaż dystrybucję wycofanych i niezwiązanych klientów z atrybutami kategorii:

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)

Screenshot that shows a notebook display of the distribution of exited versus non-exited customers.

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()

Screenshot that shows a notebook display of numerical attributes.

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, aby uruchomić narzędzie Data Wrangler, zgodnie z wcześniejszym opisem, użyj narzędzia Data Wrangler, aby wykonać kodowanie jednorazowe. W tej komórce zostanie wyświetlony skopiowany skrypt wygenerowany na potrzeby kodowania jednokrotnego:

Screenshot that shows one-hot encoding in Data Wrangler.

Screenshot that shows the selection of columns in Data Wrangler.

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

Tworzenie tabeli różnicowej w celu wygenerowania raportu usługi 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 są zarówno w wieku powyżej 60 lat, jak i mają wyniki kredytowe poniżej 400 lat. Nie można ich jednak traktować jako wartości odstających
  • 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. Wykonywanie trenowania i śledzenia modelu

Dzięki danym można teraz zdefiniować model. Zastosuj losowe modele lasu i lightGBM w tym notesie.

Użyj bibliotek scikit-learn i LightGBM, aby zaimplementować modele z kilkoma wierszami kodu. Ponadto użyj funkcji automatycznego rejestrowania MLfLow i sieci szkieletowej, aby śledzić eksperymenty.

Ten przykładowy kod ładuje tabelę różnicową z lakehouse. Możesz użyć innych tabel różnicowych, które same używają 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:

Screenshot that shows the experiment page for the bank churn experiment.

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żony klasyfikacja ma problem, ponieważ ma zbyt mało przykładów klasy mniejszości dla modelu, aby skutecznie nauczyć się granicy decyzyjnej. Aby to zrobić, Syntetyczna technika oversampling Minority Oversampling Technique (SMOTE) jest najczęściej stosowaną techniką syntezowania nowych próbek dla klasy mniejszości. Uzyskaj dostęp do narzędzia SMOTE przy użyciu biblioteki zainstalowanej imblearn w kroku 1.

Zastosuj smOTE tylko do zestawu danych szkoleniowych. Aby uzyskać prawidłowe przybliżenie wydajności modelu dla oryginalnych danych pierwotnych, należy pozostawić zestaw danych testowych w pierwotnej 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 From random over-sampling to SMOTE and ADASYN (Z losowego próbkowania do SMOTE i ADASYN). Niezrównoważona witryna internetowa learn hostuje te zasoby.

Szkolenie modelu

Użyj lasu losowego, aby wytrenować model z maksymalną głębokością czterech i czterema funkcjami:

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 lasu losowego, aby wytrenować model z maksymalną głębokością ośmiu i z sześcioma funkcjami:

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 artefaktie 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 wyświetlić 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.

Screenshot that shows logged values for one of the models.

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ż wyniki prawdziwie/fałszywie dodatnie/ujemne przy użyciu macierzy pomyłek

Aby ocenić dokładność klasyfikacji, utwórz skrypt, który wykreśli macierz pomyłek. Macierz pomyłek można również wykreślić przy użyciu narzędzi SynapseML, jak pokazano w przykładzie Wykrywanie 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 z maksymalną głębokością czterech, z czterema funkcjami:

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()

Screenshot that shows a notebook display of a confusion matrix for random forest with a maximum depth of four.

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()

Screenshot that shows a notebook display of a confusion matrix for random forest with a maximum depth of eight.

Utwórz macierz pomyłek dla rozwiązania 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()

Screenshot that shows a notebook display of a confusion matrix for LightGBM.

Zapisywanie wyników dla usługi Power BI

Zapisz ramkę różnicową w usłudze Lakehouse, aby przenieść wyniki przewidywania modelu do wizualizacji usługi 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 Data Hub
  2. Wybierz magazyn lakehouse dodany do tego notesu
  3. W sekcji Otwórz tę usługę Lakehouse wybierz pozycję Otwórz
  4. Na wstążce wybierz pozycję Nowy model semantyczny. Wybierz df_pred_resultspozycję , a następnie wybierz pozycję Kontynuuj , aby utworzyć nowy model semantyczny usługi Power BI połączony z przewidywaniami
  5. Wybierz pozycję Nowy raport z narzędzi w górnej części strony modeli semantycznych, aby otworzyć stronę tworzenia raportu usługi Power BI

Poniższy zrzut ekranu przedstawia przykładowe wizualizacje. Panel danych przedstawia tabele i kolumny różnicowe do wybrania 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.

Uwaga

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

Screenshot that shows a Power BI dashboard example.

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ą większa 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 z zakresu od 45 do 60 mają tendencję do zamykania więcej.

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.")