共用方式為


教學課程:建立、評估和評分詐騙偵測模型

本教學課程提供 Microsoft Fabric 中 Synapse 資料科學 工作流程的端對端範例。 此案例會使用定型歷程記錄數據的機器學習演算法來建置詐騙偵測模型。 然後,它會使用模型來偵測未來的詐騙交易。

本教學課程涵蓋下列步驟:

  • 安裝自訂連結庫
  • 載入資料
  • 透過探勘數據分析來了解和處理數據
  • 使用 scikit-learn 來定型機器學習模型,並使用 MLflow 和 Fabric 自動記錄功能來追蹤實驗
  • 儲存並註冊具有最高效能的機器學習模型
  • 載入機器學習模型以進行評分和進行預測

必要條件

在筆記本中跟著

您可以選擇下列其中一個選項,以遵循筆記本:

  • 在 資料科學 體驗中開啟並執行內建筆記本
  • 將筆記本從 GitHub 上傳至 資料科學 體驗

開啟內建筆記本

此教學課程隨附詐騙偵測筆記本範例

若要在 Synapse 資料科學 體驗中開啟教學課程的內建範例筆記本:

  1. 移至 Synapse 資料科學 首頁。

  2. 選取 [ 使用範例]。

  3. 選取對應的範例:

    • 如果範例適用於 Python 教學課程,請從預設 的端對端工作流程 (Python) 索引標籤。
    • 如果範例適用於 R 教學課程,請從 [端對端工作流程] 索引標籤。
    • 如果範例適用於快速教學課程,請從 [ 快速教學 課程] 索引卷標。
  4. 開始執行程序代碼之前,請先將 Lakehouse 附加至筆記本

從 GitHub 匯入筆記本

AIsample - Fraud Detection.ipynb 筆記本會伴隨本教學課程。

若要開啟本教學課程隨附的筆記本,請遵循準備系統以進行數據科學教學課程中的指示,將筆記本匯入您的工作區。

如果您想要複製並貼上此頁面中的程式碼,您可以 建立新的筆記本

開始執行程序代碼之前,請務必將 Lakehouse 附加至筆記本

步驟 1:安裝自訂連結庫

針對機器學習模型開發或臨機操作數據分析,您可能需要快速安裝Apache Spark會話的自定義連結庫。 您有兩個選項可以安裝連結庫。

  • 使用筆記本的內嵌安裝功能 (%pip%conda) 僅在您的目前筆記本中安裝連結庫。
  • 或者,您可以建立 Fabric 環境、從公用來源安裝連結庫,或將自定義連結庫上傳至該環境,然後您的工作區系統管理員可以將環境附加為工作區的預設值。 然後,環境中的所有連結庫都可供在工作區中的任何筆記本和Spark作業定義中使用。 如需環境的詳細資訊,請參閱 在 Microsoft Fabric 中建立、設定及使用環境。

在本教學課程中,請使用 %pip install 在您的筆記本中安裝連結 imblearn 庫。

注意

執行之後 %pip install ,PySpark 核心會重新啟動。 在執行任何其他數據格之前,請先安裝所需的連結庫。

# Use pip to install imblearn
%pip install imblearn

步驟 2:載入數據

從 2013 年 9 月起,詐騙偵測數據集包含歐洲持卡人在兩天內進行的信用卡交易。 數據集只包含數值特徵,因為套用至原始特徵的主體元件分析 (PCA) 轉換。 PCA 已轉換 和Amount以外的Time所有功能。 為了保護機密性,我們無法提供數據集的原始功能或更多背景資訊。

這些詳細資料描述資料集:

  • V1V2V3... V28 功能是使用 PCA 取得的主要元件
  • 此功能 Time 包含交易與數據集中第一筆交易之間經過的秒數
  • 此功能 Amount 是交易金額。 您可以使用這項功能,例如相依、區分成本的學習
  • 數據 Class 行是回應(目標)變數。 它具有詐騙的價值 10 否則為

在總計284,807筆交易中,只有492筆交易是詐騙的。 數據集高度不平衡,因為少數(詐騙)類別只占數據的0.172%。

下表顯示creditcard.csv資料的預覽

Time V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 V11 V12 V13 V14 V15 V16 V17 V18 V19 V20 V21 V22 V23 V24 V25 V26 V27 V28 總數 類別
0 -1.3598071336738 -0.0727811733098497 2.53634673796914 1.37815522427443 -0.338320769942518 0.462387777762292 0.239598554061257 0.0986979012610507 0.363786969611213 0.0907941719789316 -0.551599533260813 -0.617800855762348 -0.991389847235408 -0.311169353699879 1.46817697209427 -0.470400525259478 0.207971241929242 0.0257905801985591 0.403992960255733 0.251412098239705 -0.018306777944153 0.277837575558899 -0.110473910188767 0.0669280749146731 0.128539358273528 -0.189114843888824 0.133558376740387 -0.0210530534538215 149.62 "0"
0 1.19185711131486 0.26615071205963 0.16648011335321 0.448154078460911 0.0600176492822243 -0.0823608088155687 -0.0788029833323113 0.0851016549148104 -0.255425128109186 -0.166974414004614 1.61272666105479 1.06523531137287 0.48909501589608 -0.143772296441519 0.635558093258208 0.463917041022171 -0.114804663102346 -0.183361270123994 -0.145783041325259 -0.0690831352230203 -0.225775248033138 -0.638671952771851 0.101288021253234 -0.339846475529127 0.167170404418143 0.125894532368176 -0.00898309914322813 0.0147241691924927 2.69 "0"

下載數據集並上傳至 Lakehouse

定義這些參數,讓您可以搭配不同的數據集使用此筆記本:

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

TARGET_COL = "Class"  # Target column name
IS_SAMPLE = False  # If True, use only <SAMPLE_ROWS> 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_FOLDER = "Files/fraud-detection/"  # Folder with data files
DATA_FILE = "creditcard.csv"  # Data file name

EXPERIMENT_NAME = "aisample-fraud"  # MLflow experiment name

此程式代碼會下載公開可用的數據集版本,然後將它儲存在 Fabric Lakehouse 中。

重要

在執行筆記本之前, 請務必將 Lakehouse 新增至筆記本。 否則,您會收到錯誤。

if not IS_CUSTOM_DATA:
    # Download data files into the lakehouse if they're not already there
    import os, requests

    remote_url = "https://synapseaisolutionsa.blob.core.windows.net/public/Credit_Card_Fraud_Detection"
    fname = "creditcard.csv"
    download_path = f"/lakehouse/default/{DATA_FOLDER}/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)
    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.")

設定 MLflow 實驗追蹤

實驗追蹤程式會為您執行的每個實驗儲存所有相關實驗相關信息。 有時候,當您執行特定實驗時,您無法取得更好的結果。 在這些情況下,您應該停止實驗並嘗試新的實驗。

Microsoft Fabric 中的 Synapse 資料科學 體驗包含自動記錄功能。 此功能可減少在定型期間自動記錄機器學習模型參數、計量和專案所需的程式代碼數量。 此功能會擴充 MLflow 自動記錄功能。 其具有 資料科學 體驗的深度整合。

透過自動記錄,您可以輕鬆地追蹤和比較不同模型和實驗的效能,而不需要手動追蹤。 如需詳細資訊,請參閱 Microsoft Fabric 中的自動記錄。

若要停用筆記本工作階段中的 Microsoft Fabric 自動記錄,請呼叫 mlflow.autolog() 並設定 disable=True

# Set up MLflow for experiment tracking
import mlflow

mlflow.set_experiment(EXPERIMENT_NAME)
mlflow.autolog(disable=True)  # Disable MLflow autologging

從 Lakehouse 讀取原始數據

此程式代碼會從 Lakehouse 讀取原始資料:

df = (
    spark.read.format("csv")
    .option("header", "true")
    .option("inferSchema", True)
    .load(f"{DATA_FOLDER}/raw/{DATA_FILE}")
    .cache()
)

步驟 3:執行探勘數據分析

在本節中,您會先探索原始數據和高階統計數據。 然後,若要轉換數據,請將數據行轉換成正確的類型,並將其從Spark DataFrame轉換成 pandas DataFrame,以方便視覺效果。 最後,您會探索並可視化數據中的類別分佈。

顯示原始數據

  1. 使用 display 命令探索原始數據,並檢視高階統計數據。 如需數據視覺效果的詳細資訊,請參閱 Microsoft Fabric 中的筆記本視覺效果。

    display(df)
    
  2. 列印資料集的一些基本資訊:

    # Print dataset basic information
    print("records read: " + str(df.count()))
    print("Schema: ")
    df.printSchema()
    

轉換資料

  1. 將資料集資料列轉換成正確的類型:

    import pyspark.sql.functions as F
    
    df_columns = df.columns
    df_columns.remove(TARGET_COL)
    
    # Ensure that TARGET_COL is the last column
    df = df.select(df_columns + [TARGET_COL]).withColumn(TARGET_COL, F.col(TARGET_COL).cast("int"))
    
    if IS_SAMPLE:
        df = df.limit(SAMPLE_ROWS)
    
  2. 將 Spark DataFrame 轉換成 pandas DataFrame,以方便視覺效果和處理:

    df_pd = df.toPandas()
    

探索數據集中的類別散發

  1. 在資料集中顯示類別分佈:

    # The distribution of classes in the dataset
    print('No Frauds', round(df_pd['Class'].value_counts()[0]/len(df_pd) * 100,2), '% of the dataset')
    print('Frauds', round(df_pd['Class'].value_counts()[1]/len(df_pd) * 100,2), '% of the dataset')
    

    此程式代碼會傳回此資料集類別散發:99.83% No Frauds 和 0.17%。 Frauds 這個類別分佈顯示大部分的交易都是非稽核的。 因此,在模型定型之前需要數據前置處理,以避免過度學習。

  2. 藉由檢視詐騙交易與非詐騙交易的分佈,使用繪圖來顯示數據集中的類別不平衡:

    import seaborn as sns
    import matplotlib.pyplot as plt
    
    colors = ["#0101DF", "#DF0101"]
    sns.countplot(x='Class', data=df_pd, palette=colors) 
    plt.title('Class Distributions \n (0: No Fraud || 1: Fraud)', fontsize=10)
    
  3. 顯示交易金額的五個數位摘要(最小值、第一分位數、中位數、第三分位數和最大分數),並包含方塊繪圖:

    fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=(12,5))
    s = sns.boxplot(ax = ax1, x="Class", y="Amount", hue="Class",data=df_pd, palette="PRGn", showfliers=True) # Remove outliers from the plot
    s = sns.boxplot(ax = ax2, x="Class", y="Amount", hue="Class",data=df_pd, palette="PRGn", showfliers=False) # Keep outliers from the plot
    plt.show()
    

    針對高度不平衡的數據,方塊繪圖可能不會顯示精確的深入解析。 不過,您可以先解決 Class 不平衡問題,然後建立相同的繪圖,以取得更精確的深入解析。

步驟 4:定型和評估模型

在這裡,您會訓練 LightGBM 模型來分類詐騙交易。 您可以在不平衡數據集和平衡數據集上訓練 LightGBM 模型。 然後,您可以比較這兩個模型的效能。

準備定型和測試數據集

在定型之前,將數據分割成定型和測試數據集:

# Split the dataset into training and testing sets
from sklearn.model_selection import train_test_split

train, test = train_test_split(df_pd, test_size=0.15)
feature_cols = [c for c in df_pd.columns.tolist() if c not in [TARGET_COL]]

將 SMOTE 套用至定型數據集

imblearn 圖書館使用綜合少數過度取樣技術(SMOTE)方法來解決不平衡分類的問題。 當少數類別的範例太少時,就會發生不平衡分類,讓模型有效地瞭解決策界限。 SMOTE 是合成少數民族類別新樣本的最廣泛使用的方法。

僅將 SMOTE 套用至定型數據集,而不是測試數據集。 當您使用測試數據為模型評分時,需要在生產環境中看不見的數據上近似模型效能。 針對有效的近似值,您的測試數據依賴原始不平衡分佈,盡可能接近生產數據。

# Apply SMOTE to the training data
import pandas as pd
from collections import Counter
from imblearn.over_sampling import SMOTE

X = train[feature_cols]
y = train[TARGET_COL]
print("Original dataset shape %s" % Counter(y))

sm = SMOTE(random_state=42)
X_res, y_res = sm.fit_resample(X, y)
print("Resampled dataset shape %s" % Counter(y_res))

new_train = pd.concat([X_res, y_res], axis=1)

如需 SMOTE 的詳細資訊,請參閱 SMOTE 方法 的 scikit-learn 參考頁面,以及 有關過度取樣 資源的 scikit-learn 使用者指南。

定型機器學習模型並執行實驗

Microsoft Fabric 中的 Apache Spark 可讓您使用巨量數據進行機器學習。 透過 Apache Spark,您可以從大量結構化、非結構化和快速行動的數據中取得寶貴的見解。

您可以使用 Microsoft Fabric 中的 Apache Spark 來定型機器學習模型:Apache Spark MLlib、SynapseML 和其他開放原始碼連結庫。 如需詳細資訊,請參閱 在 Microsoft Fabric 中定型機器學習模型。

機器學習實驗可作為所有相關機器學習執行的組織和控制主要單位。 執行會對應至模型程式代碼的單一執行。 機器學習 實驗追蹤 牽涉到管理所有實驗及其元件,例如參數、計量、模型和其他成品。

針對實驗追蹤,您可以組織特定機器學習實驗的所有必要元件。 此外,您可以使用已儲存的實驗輕鬆地重現過去的結果。 如需機器學習實驗的詳細資訊,請參閱 Microsoft Fabric 中的機器學習實驗。

  1. 若要追蹤更多計量、參數和檔案,請將 設定 exclusive=False 為更新 MLflow 自動記錄組態:

    mlflow.autolog(exclusive=False)
    
  2. 使用 LightGBM 將兩個模型定型。 一個模型會處理不平衡的數據集,另一個模型會處理平衡數據集(透過 SMOTE)。 然後比較兩個模型的效能。

    import lightgbm as lgb
    
    model = lgb.LGBMClassifier(objective="binary") # Imbalanced dataset
    smote_model = lgb.LGBMClassifier(objective="binary") # Balanced dataset
    
    # Train LightGBM for both imbalanced and balanced datasets and define the evaluation metrics
    print("Start training with imbalanced data:\n")
    with mlflow.start_run(run_name="raw_data") as raw_run:
        model = model.fit(
            train[feature_cols],
            train[TARGET_COL],
            eval_set=[(test[feature_cols], test[TARGET_COL])],
            eval_metric="auc",
            callbacks=[
                lgb.log_evaluation(10),
            ],
        )
    
    print(f"\n\nStart training with balanced data:\n")
    with mlflow.start_run(run_name="smote_data") as smote_run:
        smote_model = smote_model.fit(
            new_train[feature_cols],
            new_train[TARGET_COL],
            eval_set=[(test[feature_cols], test[TARGET_COL])],
            eval_metric="auc",
            callbacks=[
                lgb.log_evaluation(10),
            ],
        )
    

判斷定型的特徵重要性

  1. 針對您在不平衡數據集上定型的模型,判斷特徵重要性:

    with mlflow.start_run(run_id=raw_run.info.run_id):
        importance = lgb.plot_importance(
            model, title="Feature importance for imbalanced data"
        )
        importance.figure.savefig("feauture_importance.png")
        mlflow.log_figure(importance.figure, "feature_importance.png")
    
  2. 判斷您在平衡數據上定型之模型的功能重要性。 SMOTE 產生平衡的數據:

    with mlflow.start_run(run_id=smote_run.info.run_id):
        smote_importance = lgb.plot_importance(
            smote_model, title="Feature importance for balanced (via SMOTE) data"
        )
        smote_importance.figure.savefig("feauture_importance_smote.png")
        mlflow.log_figure(smote_importance.figure, "feauture_importance_smote.png")
    

若要使用不平衡數據集來定型模型,相較於以平衡數據集定型的模型,重要特徵會有顯著差異。

評估模型

在這裡,您會評估兩個定型的模型:

  • model 根據未經處理、不平衡的數據進行定型
  • smote_model 在平衡數據上定型

計算模型計量

  1. prediction_to_spark定義執行預測的函式,並將預測結果轉換成Spark DataFrame。 接著,您可以使用 SynapseML 計算預測結果的模型統計數據。

    from pyspark.sql.functions import col
    from pyspark.sql.types import IntegerType, DoubleType
    
    def prediction_to_spark(model, test):
        predictions = model.predict(test[feature_cols], num_iteration=model.best_iteration_)
        predictions = tuple(zip(test[TARGET_COL].tolist(), predictions.tolist()))
        dataColumns = [TARGET_COL, "prediction"]
        predictions = (
            spark.createDataFrame(data=predictions, schema=dataColumns)
            .withColumn(TARGET_COL, col(TARGET_COL).cast(IntegerType()))
            .withColumn("prediction", col("prediction").cast(DoubleType()))
        )
    
        return predictions
    
  2. 使用 函 prediction_to_spark 式搭配兩個模型執行預測, model 以及 smote_model

    predictions = prediction_to_spark(model, test)
    smote_predictions = prediction_to_spark(smote_model, test)
    predictions.limit(10).toPandas()
    
  3. 計算兩個模型的計量:

    from synapse.ml.train import ComputeModelStatistics
    
    metrics = ComputeModelStatistics(
        evaluationMetric="classification", labelCol=TARGET_COL, scoredLabelsCol="prediction"
    ).transform(predictions)
    
    smote_metrics = ComputeModelStatistics(
        evaluationMetric="classification", labelCol=TARGET_COL, scoredLabelsCol="prediction"
    ).transform(smote_predictions)
    display(metrics)
    

使用混淆矩陣評估模型效能

混淆矩陣會顯示的數目

  • 真肯定 (TP)
  • true negatives (TN)
  • 誤判 (FP)
  • 誤判 (FN)

當使用測試數據進行評分時,模型會產生該模型。 針對二元分類,模型會傳 2x2 回混淆矩陣。 針對多類別分類,模型會 nxn 傳回混淆矩陣,其中 n 是類別數目。

  1. 使用混淆矩陣來摘要測試數據上定型機器學習模型的效能:

    # Collect confusion matrix values
    cm = metrics.select("confusion_matrix").collect()[0][0].toArray()
    smote_cm = smote_metrics.select("confusion_matrix").collect()[0][0].toArray()
    print(cm)
    
  2. 繪製預測 smote_model 的混淆矩陣(以平衡數據定型):

    # Plot the confusion matrix
    import seaborn as sns
    
    def plot(cm):
        """
        Plot the confusion matrix.
        """
        sns.set(rc={"figure.figsize": (5, 3.5)})
        ax = sns.heatmap(cm, annot=True, fmt=".20g")
        ax.set_title("Confusion Matrix")
        ax.set_xlabel("Predicted label")
        ax.set_ylabel("True label")
        return ax
    
    with mlflow.start_run(run_id=smote_run.info.run_id):
        ax = plot(smote_cm)
        mlflow.log_figure(ax.figure, "ConfusionMatrix.png")
    
  3. 繪製預測 model 的混淆矩陣(根據原始、不平衡的數據定型):

    with mlflow.start_run(run_id=raw_run.info.run_id):
        ax = plot(cm)
        mlflow.log_figure(ax.figure, "ConfusionMatrix.png")
    

使用 AUC-ROC 和 AUPRC 量值評估模型效能

曲線接收器操作特性下的區域 (AUC-ROC) 量值會評估二元分類器的效能。 AUC-ROC 圖表會將真正率 (TPR) 與誤判率 (FPR) 之間的取捨可視化。

在某些情況下,根據精確度-召回曲線 (AUPRC) 量值下的區域來評估分類器比較合適。 AUPRC 曲線會結合這些速率:

  • 有效位數或正預測值 (PPV)
  • 召回率或 TPR

若要使用 AUC-ROC 和 AUPRC 量值來評估效能:

  1. 定義傳回 AUC-ROC 和 AUPRC 量值的函式:

    from pyspark.ml.evaluation import BinaryClassificationEvaluator
    
    def evaluate(predictions):
        """
        Evaluate the model by computing AUROC and AUPRC with the predictions.
        """
    
        # Initialize the binary evaluator
        evaluator = BinaryClassificationEvaluator(rawPredictionCol="prediction", labelCol=TARGET_COL)
    
        _evaluator = lambda metric: evaluator.setMetricName(metric).evaluate(predictions)
    
        # Calculate AUROC, baseline 0.5
        auroc = _evaluator("areaUnderROC")
        print(f"The AUROC is: {auroc:.4f}")
    
        # Calculate AUPRC, baseline positive rate (0.172% in the data)
        auprc = _evaluator("areaUnderPR")
        print(f"The AUPRC is: {auprc:.4f}")
    
        return auroc, auprc    
    
  2. 針對您針對不平衡數據定型的模型記錄 AUC-ROC 和 AUPRC 計量:

    with mlflow.start_run(run_id=raw_run.info.run_id):
        auroc, auprc = evaluate(predictions)
        mlflow.log_metrics({"AUPRC": auprc, "AUROC": auroc})
        mlflow.log_params({"Data_Enhancement": "None", "DATA_FILE": DATA_FILE})
    
  3. 針對您在平衡數據上定型的模型,記錄 AUC-ROC 和 AUPRC 計量:

    with mlflow.start_run(run_id=smote_run.info.run_id):
        auroc, auprc = evaluate(smote_predictions)
        mlflow.log_metrics({"AUPRC": auprc, "AUROC": auroc})
        mlflow.log_params({"Data_Enhancement": "SMOTE", "DATA_FILE": DATA_FILE})
    

在平衡數據上定型的模型會傳回較高的 AUC-ROC 和 AUPRC 值,而與針對不平衡數據定型的模型相比。 根據這些措施,SMOTE 在處理高度不平衡的數據時,似乎是一種有效的技術,可增強模型效能。

如下圖所示,任何實驗都會以其各自的名稱進行記錄。 您可以在工作區中追蹤實驗參數和效能計量。

Screenshot of the tracked experiment.

下圖顯示在平衡數據集上定型之模型的效能計量 (版本 2):

Screenshot of logged model performance metrics and model parameters.

您可以選取 第 1 版來查看在不平衡數據集上定型之模型的計量。 當您比較計量時,使用平衡數據集定型的模型,AUROC 會更高。 這些結果表示此模型較適合正確預測 0 類別為 0,並將類別預測 11

步驟 5:註冊模型

使用 MLflow 註冊這兩個模型:

# Register the model
registered_model_name = f"{EXPERIMENT_NAME}-lightgbm"

raw_model_uri = "runs:/{}/model".format(raw_run.info.run_id)
mlflow.register_model(raw_model_uri, registered_model_name)

smote_model_uri = "runs:/{}/model".format(smote_run.info.run_id)
mlflow.register_model(smote_model_uri, registered_model_name)

步驟 6:儲存預測結果

Microsoft Fabric 可讓使用者使用 PREDICT 可調整的函式來運作機器學習模型。 此函式支援任何計算引擎中的批次評分(或批次推斷)。

您可以直接從 Microsoft Fabric 筆記本或模型的項目頁面產生批次預測。 如需 的詳細資訊 PREDICT,請參閱 在 Microsoft Fabric 中使用 PREDICT 進行模型評分。

  1. 載入效能較佳的模型 (第 2 版)以進行批次評分,併產生預測結果:

    from synapse.ml.predict import MLFlowTransformer
    
    spark.conf.set("spark.synapse.ml.predict.enabled", "true")
    
    model = MLFlowTransformer(
        inputCols=feature_cols,
        outputCol="prediction",
        modelName=f"{EXPERIMENT_NAME}-lightgbm",
        modelVersion=2,
    )
    
    test_spark = spark.createDataFrame(data=test, schema=test.columns.to_list())
    
    batch_predictions = model.transform(test_spark)
    
  2. 將預測儲存至 Lakehouse:

    # Save the predictions to the lakehouse
    batch_predictions.write.format("delta").mode("overwrite").save(f"{DATA_FOLDER}/predictions/batch_predictions")