チュートリアル: チャーン予測モデルを作成、評価、スコア付けする
このチュートリアルでは、Microsoft Fabric の Synapse Data Science ワークフローのエンド ツー エンドの例について説明します。 このシナリオでは、銀行の顧客が離反するかどうかを予測するモデルを構築します。 チャーン レートまたは解約率には、銀行の顧客が銀行との取引を終了するレートが含まれます。
このチュートリアルに含まれる手順は次のとおりです:
- カスタム ライブラリをインストールする
- データの読み込み
- 探索的データ分析を通じてデータを理解して処理し、Fabric Data Wrangler 機能の使用方法を示します
- Scikit-Learn、LightGBM、MLflow を使って機械学習モデルをトレーニングし、MLflow および Fabric 自動ログ機能を使用して実験を追跡します
- 最終的な機械学習モデルを評価して保存する
- Power BI の視覚化を使用してモデルのパフォーマンスを表示します
前提条件
Microsoft Fabric サブスクリプションを取得します。 または、無料の Microsoft Fabric 試用版にサインアップします。
Microsoft Fabric にサインインします。
ホーム ページの左側にある環境スイッチャーを使って、Synapse Data Science 環境に切り替えます。
- 必要に応じて、「Microsoft Fabric でレイクハウスを作成する」の説明に 従って、Microsoft Fabric レイクハウスを作成します。
ノートブックで作業を進めます
ノートブックでこれらの後続のオプションのうちのいずれかを選択できます
- Data Science 環境のビルトイン ノートブックを開いて実行します
- GitHub から Data Science 環境にノートブックをアップロードする
ビルトインのノートブックを開きます
例の [顧客離反] のノートブックは、このチュートリアルに付属しています。
チュートリアルのビルトインのサンプル ノートブックを Synapse Data Science 環境で開くには:
Synapse Data Science のホーム ページに移動します。
[サンプルの使用] を選択してください。
対応するサンプルを選択してください。
- サンプルが Python チュートリアル用の場合は、既定の [エンド ツー エンド ワークフロー (Python)] タブから。
- サンプルが R チュートリアル用の場合は、[エンド ツー エンド ワークフロー (R)] タブから。
- サンプルがクイック チュートリアル用の場合は、[クイック チュートリアル] タブから。
コードの実行を開始する前に、[レイクハウスをノートブックにアタッチします]。
GitHub からノートブックをインポートします
[AIsample - Bank Customer Churn.ipynb] ノートブックは、このチュートリアルに付属しています。
このチュートリアルが付属するノートブックを開く場合は、「データ サイエンス チュートリアル用にシステムを準備する」内の指示に従い、ノートブックを、お使いのワークスペースにインポートします。
このページからコードをコピーして貼り付ける場合は、[新しいノートブックを作成する] ことができます。
コードの実行を開始する前に、必ずレイクハウスをノートブックにアタッチしてください。
手順 1: カスタム ライブラリをインストールする
機械学習モデルの開発またはアドホックなデータ分析には、Apache Spark セッション用のカスタム ライブラリをすばやくインストールすることが必要な場合があります。 ライブラリをインストールするには、2 つのオプションがあります。
- ノートブックのインライン インストール機能 (
%pip
または%conda
) を使って、現在のノートブックにのみライブラリをインストールします - または、Fabric 環境を作成し、パブリック ソースからライブラリをインストールするか、あるいはカスタム ライブラリをそこにアップロードすると、ワークスペース管理者はその環境をワークスペースの既定としてアタッチできます。 その後、環境内のすべてのライブラリが、ワークスペース内のすべてのノートブックと Spark ジョブ定義で使用できるようになります。 環境の詳細については、「Microsoft Fabric で環境を作成、構成、および使用する」を参照してください。
このチュートリアルでは、%pip install
を使用して、ノートブックに imblearn
ライブラリをインストールします。
Note
PySpark カーネルは、%pip install
の実行後に再起動します。 他のセルを実行する前に必要なライブラリをインストールします。
# Use pip to install libraries
%pip install imblearn
手順 2: データを読み込む
churn.csvのデータセットには、10,000 人の顧客のチャーン状態と、次を含む 14 個の属性が含まれています:
- クレジット スコア
- 地理的な場所 (ドイツ、フランス、スペイン)
- 性別 (男性、女性)
- Age
- 加入期間 (その人がその銀行の顧客であった年数)
- 口座残高
- 推定給与
- 銀行を通じて顧客が購入した商品の数
- クレジット カードの状況 (顧客がクレジット カードを所有しているかどうか)
- アクティブ メンバーの状況 (銀行のアクティブな顧客であるかどうか)
このデータセットには、行番号、顧客 ID、顧客の姓の列が含まれます。 これらの列の値は、銀行を解約するという顧客の判断に影響を与えるべきではありません。
その顧客にとっての解約を定義するイベントとは、顧客の銀行口座の閉鎖です。 データセットの Exited
列は、顧客の放棄を意味します。 これらの属性に関するコンテキストがほとんどないため、データセットに関する背景情報を必要としません。 これらの属性が Exited
状態にどのように影響するかを理解することを望んでいます。
その 10,000 人の顧客のうち、銀行を解約した顧客は 2037 人 (約 20%) に過ぎません。 そのクラスの不均衡の比率により、合成データを生成することをお勧めします。 混同行列の精度は、不均衡な分類に関連しない可能性があります。 精度再現率曲線 (AUPRC) の下の領域を使用して精度を測定したい場合があります。
- この表に、
churn.csv
データのプレビューを示します。
CustomerID | 姓 | CreditScore | 地理的な場所 | Gender | Age | 在職期間 | 残高 | NumOfProducts | HasCrCard | IsActiveMember | EstimatedSalary | 退職済 |
---|---|---|---|---|---|---|---|---|---|---|---|---|
15634602 | Hargrave | 619 | フランス | 女性 | 42 | 2 | 0.00 | 1 | 1 | 1 | 101348.88 | 1 |
15647311 | Hill | 608 | スペイン | 女性 | 41 | 1 | 83807.86 | 1 | 0 | 1 | 112542.58 | 0 |
データセットをダウンロードしてレイクハウスにアップロードする
さまざまなデータセットでこのノートブックを使用できるように、これらのパラメーターを定義します:
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
このコードは、公開されているバージョンのデータセットをダウンロードし、Fabric レイクハウスに格納します:
重要
実行する前に、ノートブックに [レイクハウスを追加する]。 間違ってインストールすると、エラーが発生します。
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.")
ノートブックの実行にかかる時間の記録を開始します:
# Record the notebook running time
import time
ts = time.time()
レイクハウスから生データを読み取る
レイクハウスの [ファイル] セクションから生データを読み取り、異なる日付要素ごとに列を追加します。 パーティション分割されたデルタ テーブルの作成では、この情報が使用されます。
df = (
spark.read.option("header", True)
.option("inferSchema", True)
.csv("Files/churn/raw/churn.csv")
.cache()
)
データセットから pandas データフレームを作成する
このコードは、処理と視覚化を容易にするために、spark DataFrame を pandas DataFrame に変換します:
df = df.toPandas()
手順 3: 探索的データ分析を実行する
生データを表示する
display
を使用して生データを探索し、一部の基本的な統計の実行およびグラフ ビューの表示を行います。 まず、データの視覚化に必要なライブラリ (例 seaborn) をインポートする必要があります。 Seaborn は Python データ視覚化ライブラリであり、データフレームと配列でビジュアルを構築するための高度なインターフェイスを提供します。
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)
Data Wrangler を使って最初のデータ クリーニングを実行する
ノートブックから直接 Data Wrangler を起動して、pandas DataFrameを探索して変換します。 ノートブック リボンの [データ] タブで、Data Wrangler ドロップダウン プロンプトを使用して、編集に使用できるアクティブな Pandas DataFrames を参照します。 Data Wrangler で開くデータフレームを選びます。
Note
ノートブック カーネルがビジー状態の間は、Data Wrangler を開くことができません。 Data Wrangler を起動する前に、セルの実行を完了する必要があります。 Data Wrangler の詳細について確認してください。
Data Wrangler が起動したら、次の図に示すように、表示されるデータ パネルの説明的な概要が生成されます。 この概要には、DataFrame の分析コード、欠損値などに関する情報が含まれています。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())
属性を決定する
このコードは、カテゴリ、数値、ターゲットの属性を決定します:
# 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)
5 つの数値の概要を表示します
ボックス プロットを使用して 5 つの数値の概要を表示する
- 最小スコア
- 第 1 四分位数
- 中央値 (median)
- 3 番目の四分位数
- 最大スコア
数値属性の場合。
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])
解約した顧客と解約していない顧客の分布を表示する
カテゴリ属性全体にわたる、解約した顧客対解約していない顧客の分布を表示します:
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)
数値属性の分布を表示します
ヒストグラムを使用して数値属性の頻度分布を表示します:
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()
特徴エンジニアリングを実行する
この特徴エンジニアリングにより、現在の属性に基づいて新しい属性を生成します:
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])
Data Wrangler を使用してワンホット エンコードを実行する
前に説明したように、Data Wrangler を起動するのと同じ手順で、Data Wrangler を使用してワンホット エンコードを実行します。 このセルには、コピーされた、ワンホット エンコード用に生成されたスクリプトが表示されます:
df_clean = pd.get_dummies(df_clean, columns=['Geography', 'Gender'])
デルタ テーブルを作成して 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}")
探索的データ分析からの観測の概要
- ほとんどの顧客はフランス出身です。 スペインは、フランスとドイツに比べてチャーン レートが最も低い。
- ほとんどの顧客はクレジット カードを持っています
- 一部の顧客は 60 歳以上で、クレジット スコアが 400 未満です。 ただし、その顧客を外れ値と見なすことはできません
- 銀行の商品を 2 つ以上持っている顧客はごくわずかです
- 非アクティブな顧客の解約率が高くなります
- 性別と加入期間年数 は、銀行口座を閉じるという顧客の決定には影響を与えません
手順 4: モデルのトレーニングと追跡を実行します
データを配置したので、モデルを定義できるようになりました。 このノートブックでは、ランダム フォレストと LightGBM のモデルを適用します。
scikit-learn ライブラリと LightGBM ライブラリを使用して、数行のコードでモデルを実装します。 さらに、MLfLow と Fabric の自動ログ記録を使用して実験を追跡します。
このコード サンプルでは、レイクハウスからデルタ テーブルを読み込みます。 レイクハウスをソースとして使用する他のデルタ テーブルを使用できます。
SEED = 12345
df_clean = spark.read.format("delta").load("Tables/df_clean").toPandas()
MLflow を使用することでモデルの追跡とログ記録のための実験を生成します
このセクションでは、実験を生成する方法を示し、モデルとトレーニングのパラメーターとスコア付けメトリックを指定します。 さらに、後で使用するために、モデルをトレーニングし、ログに記録し、トレーニング済みのモデルを保存する方法も示します。
import mlflow
# Set up the experiment name
EXPERIMENT_NAME = "sample-bank-churn-experiment" # MLflow experiment name
自動ログ記録は、モデルがトレーニングされている際、機械学習モデルの入力パラメータ、出力メトリック、出力項目の両方を自動的にキャプチャします。 その後、この情報はワークスペースに記録され、そこでは MLflow API またはワークスペース内の対応する実験によりアクセスおよび視覚化できます。
完了すると、実験はこちらの画像のようになります:
それぞれの名前が付いたすべての実験がログに記録され、そのパラメーターとパフォーマンス メトリックを追跡できます。 自動ログ機能の詳細については、「Microsoft Fabric での自動ログ記録」を参照してください。
実験と自動ログ機能の仕様を設定する
mlflow.set_experiment(EXPERIMENT_NAME) # Use a date stamp to append to the experiment
mlflow.autolog(exclusive=False)
scikit-learn と 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
トレーニング用およびテスト用のデータセットを準備する
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)
SMOTE をトレーニング データに適用します
不均衡な分類には、モデルが決定境界を効果的に学習するには、少数派クラスの例が少なすぎるために、問題があります。 これに対処するために、Synthetic Minority Oversampling Technique (SMOTE) は、少数派クラスの新しいサンプルを合成するために最も広く使用されている技術です。 手順 1 でインストールした imblearn
ライブラリを使用して SMOTE にアクセスします。
SMOTE をトレーニング データセットにのみ適用します。 元のデータに対するモデルのパフォーマンスの有効な近似を得るには、テスト データセットをその元の不均衡な分布のままにしておく必要があります。 この実験は、運用環境の状況を表します。
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)
詳細については、「SMOTE」および「ランダム オーバーサンプリングから SMOTE と ADASYN へ」を参照してください。 不均衡な学習 Web サイトは、これらのリソースをホストします。
モデルのトレーニング
4 つの特徴量を持つ最大深度が 4 のランダム フォレストを使用してモデルをトレーニングします:
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])
6 つの特徴量を持つ最大深度が 8 のランダム フォレストを使用してモデルをトレーニングします:
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])
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])
モデルのパフォーマンスを追跡するための実験アーティファクトを確認します
実験の実行は、実験アーティファクトに自動的に保存されます。 ワークスペースでそのアーティファクトを見つけることができます。 アーティファクト名は、実験の設定に使用される名前に基づいています。 トレーニングされたすべてのモデル、それらの実行、パフォーマンス メトリック、およびモデル パラメーターが実験ページのログに記録されます。
実験を表示するには:
- 左側のパネルで、ワークスペースを選択します。
- 実験名 (この場合は、sample-bank-churn-experiment) を見つけて選択します。
手順 5: 最終的な機械学習モデルを評価して保存する
保存した実験をワークスペースから開き、最適なモデルを選択して保存します:
# 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")
テスト データセット上で保存されたモデルのパフォーマンスを評価します
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
混同行列を使用して、真陽性、真陰性、偽陽性、偽陰性を表示します
分類の精度を評価するために、混同行列をプロットするスクリプトを作成します。 「不正検出サンプル」に示されているように、SynapseML ツールを使用して混同行列をプロットすることもできます。
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')
最大深度が 4 で、4 つの特徴量を持つランダム フォレスト分類子の混同行列を作成します:
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()
最大深度が 8 で、6 つの特徴量を持つランダム フォレスト分類子の混同行列を作成します:
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()
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()
Power BI の結果を保存する
デルタ フレームをレイクハウスに保存して、モデル予測結果を 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}")
手順 6: Power BI で視覚化にアクセスする
Power BI で保存したテーブルにアクセスします:
- 左側で、[OneLake データ ハブ] を選択します
- このノートブックに追加したレイクハウスを選択します
- [このレイクハウスを開く] セクションで、[開く] を選択します
- リボンで、[新しいセマンティック モデル] を選択します。 [
df_pred_results
] を選択してから、[続行] を選択して、予測にリンクされた新しい Power BI セマンティック モデルを作成します - セマンティック モデルのページの上部にあるツールから [新しいレポート] を選択して Power BI レポートの作成ページを開きます
次のスクリーンショットは、視覚化の例をいくつか示しています。 データ パネルには、デルタ テーブルとテーブルから選択する列が表示されます。 適切なカテゴリ (x) と値 (y) 軸を選択すると、テーブル列の合計や平均などのフィルターと関数を選択できます。
Note
このスクリーンショットでは、図示した例は、Power BI で保存された予測結果の分析を説明します:
ただし、実際の顧客離反のユース ケースの場合、プラットフォーム ユーザーは、特定分野の専門知識と、どのようなものを会社とビジネス分析チームがメトリックとして標準化しているかに基づいて、作成する視覚化のより徹底的な一連の要求を行う必要がある場合があります。
Power BI レポートでは、2 つ以上の銀行の商品を使用している顧客のチャーン率が高いことが示されています。 ただし、2 つ以上の商品を持っていた顧客はほとんどいませんでした。 (左下のパネルのプロットを参照。)銀行はより多くのデータを収集する必要がありますが、商品数の多さと相関関係のある他の特徴量も調査する必要があります。
ドイツの銀行の顧客は、フランスとスペインの顧客に比べて解約率が高いです。 (右下のパネルのプロットを参照してください)。 レポートの結果に基づいて、顧客の退会を促した要因の調査が役立つ可能性があります。
中高年の顧客が増えています (25 歳から 45 歳)。 45 歳から 60 歳の顧客は、より多く退会する傾向があります。
最後に、クレジット スコアが低い顧客は、他の金融機関のために銀行を解約する可能性が最も高くなります。 銀行は、クレジット スコアと口座残高が低い顧客がその銀行と契約し続けるよう促す方法を調査する必要があります。
# Determine the entire runtime
print(f"Full run cost {int(time.time() - ts)} seconds.")