Självstudie: Använda R för att skapa, utvärdera och bedöma en modell för bedrägeriidentifiering
I den här handledningen visas ett heltäckande exempel på ett Synapse Data Science-arbetsflöde i Microsoft Fabric. I det här scenariot skapar vi en modell för bedrägeriidentifiering i R med maskininlärningsalgoritmer som tränats på historiska data. Sedan använder vi modellen för att identifiera framtida bedrägliga transaktioner.
Den här handledningen omfattar följande steg:
- Installera anpassade bibliotek
- Läs in data
- Förstå och bearbeta data med undersökande dataanalys och visa användningen av funktionen Fabric Data Wrangler
- Träna maskininlärningsmodeller med LightGBM
- Använda maskininlärningsmodellerna för bedömning och förutsägelser
Förutsättningar
Skaffa en Microsoft Fabric-prenumeration. Eller registrera dig för en kostnadsfri Microsoft Fabric-utvärderingsversion.
Logga in på Microsoft Fabric.
Använd upplevelseväxlaren längst ned till vänster på startsidan för att växla till Fabric.
- Om det behövs skapar du ett Microsoft Fabric Lakehouse enligt beskrivningen i Skapa ett sjöhus i Microsoft Fabric.
Följ med i en anteckningsbok
Du kan välja något av följande alternativ för att följa med i en notebook:
- Öppna och kör den inbyggda notebook-filen i Synapse Data Science-upplevelsen
- Ladda upp din notebook-fil från GitHub till Synapse Data Science-upplevelsen
Öppna den inbyggda notebook-filen
Exempelexemplet Bedrägeriidentifiering notebook-fil medföljer den här självstudien.
Om du vill öppna exempelanteckningsboken för den här självstudien följer du anvisningarna i Förbereda systemet för självstudier för datavetenskap.
Se till att bifoga ett lakehouse till notebook- innan du börjar köra kod.
Importera anteckningsboken från GitHub
Den AIsample – R Fraud Detection.ipynb anteckningsboken medföljer den här handledningen.
Om du vill öppna den medföljande notebook-filen för den här självstudien, följ anvisningarna i Förbered ditt system för självstudier i datavetenskap: importera anteckningsboken till din arbetsyta.
Om du hellre kopierar och klistrar in koden från den här sidan kan du skapa en ny notebook-fil.
Se till att koppla ett lakehouse till notebooken innan du börjar köra koden.
Steg 1: Installera anpassade bibliotek
För utveckling av maskininlärningsmodeller eller ad hoc-dataanalys kan du snabbt behöva installera ett anpassat bibliotek för Apache Spark-sessionen. Du har två alternativ för att installera bibliotek.
- Använd infogade installationsresurser, till exempel
install.packages
ochdevtools::install_version
, för att endast installera i din nuvarande anteckningsbok. - Du kan också skapa en Infrastrukturmiljö, installera bibliotek från offentliga källor eller ladda upp anpassade bibliotek till den och sedan kan din arbetsyteadministratör koppla miljön som standard för arbetsytan. Alla bibliotek i miljön blir sedan tillgängliga för användning i alla anteckningsböcker och Spark-jobbdefinitioner på arbetsytan. Mer information om miljöer finns i skapa, konfigurera och använda en miljö i Microsoft Fabric.
I den här handledningen använder du install.version()
för att installera biblioteket imbalanced-learn.
# Install dependencies
devtools::install_version("bnlearn", version = "4.8")
# Install imbalance for SMOTE
devtools::install_version("imbalance", version = "1.0.2.1")
Steg 2: Läs in datan
Datamängden för bedrägeriidentifiering innehåller kreditkortstransaktioner från september 2013, som europeiska kortinnehavare gjort under loppet av två dagar. Datamängden innehåller endast numeriska funktioner på grund av en PCA-transformering (Principal Component Analysis) som tillämpas på de ursprungliga funktionerna. PCA omvandlade alla funktioner förutom Time
och Amount
. För att skydda konfidentialiteten kan vi inte tillhandahålla de ursprungliga funktionerna eller mer bakgrundsinformation om datauppsättningen.
Den här informationen beskriver datamängden:
- Funktionerna
V1
,V2
,V3
, ...,V28
är huvudkomponenterna som hämtas med PCA - Funktionen
Time
innehåller de förflutna sekunderna mellan en transaktion och den första transaktionen i datamängden - Egenskapen
Amount
är transaktionsbeloppet. Du kan använda den här funktionen för till exempel beroende, kostnadskänslig inlärning - Kolumnen
Class
är variabeln svar (mål). Den har värdet1
för bedrägeri och0
annars
Endast 492 transaktioner, av totalt 284 807 transaktioner, är bedrägliga. Datamängden är mycket obalanserad eftersom minoritetsklassen (bedräglig) endast står för cirka 0,172% av data.
Den här tabellen visar en förhandsgranskning av creditcard.csv data:
Tid | 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 | Belopp | Klass |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
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 |
Ladda ned datauppsättningen och ladda upp till lakehouse
Definiera dessa parametrar så att du kan använda den här notebook-filen med olika datauppsättningar:
IS_CUSTOM_DATA <- FALSE # If TRUE, the dataset has to be uploaded manually
IS_SAMPLE <- FALSE # If TRUE, use only 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/fraud-detection" # Folder with data files
DATA_FILE <- "creditcard.csv" # Data file name
Den här koden laddar ned en offentligt tillgänglig version av datamängden och lagrar den sedan i en Fabric lakehouse.
Viktig
Se till att lägga till en lakehouse- i anteckningsboken innan du kör den. Annars får du ett fel.
if (!IS_CUSTOM_DATA) {
# Download data files into a lakehouse if they don't exist
library(httr)
remote_url <- "https://synapseaisolutionsa.blob.core.windows.net/public/Credit_Card_Fraud_Detection"
fname <- "creditcard.csv"
download_path <- file.path(DATA_ROOT, DATA_FOLDER, "raw")
dir.create(download_path, showWarnings = FALSE, recursive = TRUE)
if (!file.exists(file.path(download_path, fname))) {
r <- GET(file.path(remote_url, fname), timeout(30))
writeBin(content(r, "raw"), file.path(download_path, fname))
}
message("Downloaded demo data files into lakehouse.")
}
Läsa rådatumdata från lakehouse
Den här koden läser rådata från avsnittet Files i lakehouse:
data_df <- read.csv(file.path(DATA_ROOT, DATA_FOLDER, "raw", DATA_FILE))
Steg 3: Utföra undersökande dataanalys
Använd kommandot display
för att visa statistik på hög nivå för datauppsättningen:
display(as.DataFrame(data_df, numPartitions = 3L))
# Print dataset basic information
message(sprintf("records read: %d", nrow(data_df)))
message("Schema:")
str(data_df)
# If IS_SAMPLE is True, use only SAMPLE_ROWS of rows for training
if (IS_SAMPLE) {
data_df = sample_n(data_df, SAMPLE_ROWS)
}
Skriv ut fördelningen av klasser i datauppsättningen:
# The distribution of classes in the dataset
message(sprintf("No Frauds %.2f%% of the dataset\n", round(sum(data_df$Class == 0)/nrow(data_df) * 100, 2)))
message(sprintf("Frauds %.2f%% of the dataset\n", round(sum(data_df$Class == 1)/nrow(data_df) * 100, 2)))
Den här klassfördelningen visar att de flesta transaktionerna är icke-bedrägliga. Därför krävs förbearbetning av data före modellträning för att undvika överanpassning.
Visa fördelningen av bedrägliga kontra icke-bedragna transaktioner
Visa fördelningen av bedrägliga kontra icke-bedrägliga transaktioner med ett diagram för att visa klassobalansen i datauppsättningen:
library(ggplot2)
ggplot(data_df, aes(x = factor(Class), fill = factor(Class))) +
geom_bar(stat = "count") +
scale_x_discrete(labels = c("no fraud", "fraud")) +
ggtitle("Class Distributions \n (0: No Fraud || 1: Fraud)") +
theme(plot.title = element_text(size = 10))
Diagrammet visar tydligt obalansen i datauppsättningen:
Visa sammanfattningen med fem nummer
Visa femtalssammanfattningen (minsta poäng, första kvartilen, median, tredje kvartilen och högsta poäng) för transaktionsbeloppet, med rutor:
library(ggplot2)
library(dplyr)
ggplot(data_df, aes(x = as.factor(Class), y = Amount, fill = as.factor(Class))) +
geom_boxplot(outlier.shape = NA) +
scale_x_discrete(labels = c("no fraud", "fraud")) +
ggtitle("Boxplot without Outliers") +
coord_cartesian(ylim = quantile(data_df$Amount, c(0.05, 0.95)))
För data med hög obalans kan det hända att lådritningar inte visar korrekta insikter. Du kan dock åtgärda problemet med Class
obalans först och sedan skapa samma diagram för mer exakta insikter.
Steg 4: Träna och utvärdera modellerna
Här tränar du en LightGBM-modell för att klassificera bedrägeritransaktionerna. Du tränar en LightGBM-modell på både den obalanserade datamängden och den balanserade datamängden. Sedan jämför du prestandan för båda modellerna.
Förbereda tränings- och testdatauppsättningar
Innan träningen delar du upp data till tränings- och testdatauppsättningarna:
# Split the dataset into training and test datasets
set.seed(42)
train_sample_ids <- base::sample(seq_len(nrow(data_df)), size = floor(0.85 * nrow(data_df)))
train_df <- data_df[train_sample_ids, ]
test_df <- data_df[-train_sample_ids, ]
Tillämpa SMOTE på träningsdatauppsättningen
Obalanserad klassificering har ett problem. Den har för få exempel på minoritetsklasser för att en modell effektivt ska kunna lära sig beslutsgränsen. SMOTE (Synthetic Minority Oversampling Technique) kan hantera detta problem. SMOTE är den mest använda metoden för att syntetisera nya exempel för minoritetsklassen. Du kan komma åt SMOTE med hjälp av det imbalance
bibliotek som du installerade i steg 1.
Använd endast SMOTE på träningsdatauppsättningen i stället för testdatauppsättningen. När du bedömer modellen med testdata behöver du en uppskattning av modellens prestanda för osedda data i produktionen. För en giltig uppskattning förlitar sig testdata på den ursprungliga obalanserade fördelningen för att representera produktionsdata så nära som möjligt.
# Apply SMOTE to the training dataset
library(imbalance)
# Print the shape of the original (imbalanced) training dataset
train_y_categ <- train_df %>% select(Class) %>% table
message(
paste0(
"Original dataset shape ",
paste(names(train_y_categ), train_y_categ, sep = ": ", collapse = ", ")
)
)
# Resample the training dataset by using SMOTE
smote_train_df <- train_df %>%
mutate(Class = factor(Class)) %>%
oversample(ratio = 0.99, method = "SMOTE", classAttr = "Class") %>%
mutate(Class = as.integer(as.character(Class)))
# Print the shape of the resampled (balanced) training dataset
smote_train_y_categ <- smote_train_df %>% select(Class) %>% table
message(
paste0(
"Resampled dataset shape ",
paste(names(smote_train_y_categ), smote_train_y_categ, sep = ": ", collapse = ", ")
)
)
Mer information om SMOTE finns i paketet 'imbalance' och resurserna Hantering av obalanserade dataset på CRAN-webbplatsen.
Träna modellen med LightGBM
Träna LightGBM-modellen med både den obalanserade datamängden och den balanserade datamängden (via SMOTE). Jämför sedan deras prestanda:
# Train LightGBM for both imbalanced and balanced datasets and define the evaluation metrics
library(lightgbm)
# Get the ID of the label column
label_col <- which(names(train_df) == "Class")
# Convert the test dataset for the model
test_mtx <- as.matrix(test_df)
test_x <- test_mtx[, -label_col]
test_y <- test_mtx[, label_col]
# Set up the parameters for training
params <- list(
objective = "binary",
learning_rate = 0.05,
first_metric_only = TRUE
)
# Train for the imbalanced dataset
message("Start training with imbalanced data:")
train_mtx <- as.matrix(train_df)
train_x <- train_mtx[, -label_col]
train_y <- train_mtx[, label_col]
train_data <- lgb.Dataset(train_x, label = train_y)
valid_data <- lgb.Dataset.create.valid(train_data, test_x, label = test_y)
model <- lgb.train(
data = train_data,
params = params,
eval = list("binary_logloss", "auc"),
valids = list(valid = valid_data),
nrounds = 300L
)
# Train for the balanced (via SMOTE) dataset
message("\n\nStart training with balanced data:")
smote_train_mtx <- as.matrix(smote_train_df)
smote_train_x <- smote_train_mtx[, -label_col]
smote_train_y <- smote_train_mtx[, label_col]
smote_train_data <- lgb.Dataset(smote_train_x, label = smote_train_y)
smote_valid_data <- lgb.Dataset.create.valid(smote_train_data, test_x, label = test_y)
smote_model <- lgb.train(
data = smote_train_data,
params = params,
eval = list("binary_logloss", "auc"),
valids = list(valid = smote_valid_data),
nrounds = 300L
)
Fastställa funktioners betydelse
Fastställa funktionsvikt för den modell som du har tränat på den obalanserade datamängden:
imp <- lgb.importance(model, percentage = TRUE)
ggplot(imp, aes(x = Frequency, y = reorder(Feature, Frequency), fill = Frequency)) +
scale_fill_gradient(low="steelblue", high="tomato") +
geom_bar(stat = "identity") +
geom_text(aes(label = sprintf("%.4f", Frequency)), hjust = -0.1) +
theme(axis.text.x = element_text(angle = 90)) +
xlim(0, max(imp$Frequency) * 1.1)
För modellen som du har tränat på den balanserade datamängden via SMOTE, beräkna funktionernas betydelse.
smote_imp <- lgb.importance(smote_model, percentage = TRUE)
ggplot(smote_imp, aes(x = Frequency, y = reorder(Feature, Frequency), fill = Frequency)) +
geom_bar(stat = "identity") +
scale_fill_gradient(low="steelblue", high="tomato") +
geom_text(aes(label = sprintf("%.4f", Frequency)), hjust = -0.1) +
theme(axis.text.x = element_text(angle = 90)) +
xlim(0, max(smote_imp$Frequency) * 1.1)
En jämförelse av dessa diagram visar tydligt att balanserade och obalanserade träningsdatauppsättningar har stora skillnader i funktionernas betydelse.
Utvärdera modellerna
Här utvärderar du de två tränade modellerna:
-
model
tränad på obalanserade rådata -
smote_model
har tränats på balanserad data
preds <- predict(model, test_mtx[, -label_col])
smote_preds <- predict(smote_model, test_mtx[, -label_col])
Utvärdera modellprestanda med en förvirringsmatris
En konfusionsmatris visar antalet
- sanna positiva identifieringar (TP)
- sanna negativa (TN)
- falska positiva (FP)
- falska negativa (FN)
som en modell producerar när den värderas med testdata. För binär klassificering returnerar modellen en 2x2
förvirringsmatris. För klassificering med flera klasser returnerar modellen en nxn
förvirringsmatris, där n
är antalet klasser.
Använd en förvirringsmatris för att sammanfatta prestanda för de tränade maskininlärningsmodellerna på testdata:
plot_cm <- function(preds, refs, title) { library(caret) cm <- confusionMatrix(factor(refs), factor(preds)) cm_table <- as.data.frame(cm$table) cm_table$Prediction <- factor(cm_table$Prediction, levels=rev(levels(cm_table$Prediction))) ggplot(cm_table, aes(Reference, Prediction, fill = Freq)) + geom_tile() + geom_text(aes(label = Freq)) + scale_fill_gradient(low = "white", high = "steelblue", trans = "log") + labs(x = "Prediction", y = "Reference", title = title) + scale_x_discrete(labels=c("0", "1")) + scale_y_discrete(labels=c("1", "0")) + coord_equal() + theme(legend.position = "none") }
Rita sammanblandningsmatrisen för modellen som tränats på den obalanserade datamängden:
# The value of the prediction indicates the probability that a transaction is fraud # Use 0.5 as the threshold for fraud/no-fraud transactions plot_cm(ifelse(preds > 0.5, 1, 0), test_df$Class, "Confusion Matrix (Imbalanced dataset)")
Rita förväxlingsmatrisen för modellen som tränats på den balanserade datamängden.
plot_cm(ifelse(smote_preds > 0.5, 1, 0), test_df$Class, "Confusion Matrix (Balanced dataset)")
Utvärdera modellprestanda med måtten AUC-ROC och AUPRC
Måttet Arean under ROC-kurvan (AUC-ROC) utvärderar förmågan hos binära klassificerare. Diagrammet AUC-ROC visualiserar kompromissen mellan den sanna positiva frekvensen (TPR) och den falska positiva frekvensen (FPR).
I vissa fall är det mer lämpligt att utvärdera klassificeraren baserat på måttet Area Under the Precision-Recall Curve (AUPRC). AUPRC-kurvan kombinerar dessa priser:
- Precisionen eller det positiva prediktiva värdet (PPV)
- Återkallandet, eller TPR
# Use the PRROC package to help calculate and plot AUC-ROC and AUPRC
install.packages("PRROC", quiet = TRUE)
library(PRROC)
Beräkna måtten AUC-ROC och AUPRC
Beräkna och rita måtten AUC-ROC och AUPRC för de två modellerna.
Obalanserad datauppsättning
Beräkna förutsägelserna:
fg <- preds[test_df$Class == 1]
bg <- preds[test_df$Class == 0]
Skriv ut området under AUC-ROC kurva:
# Compute AUC-ROC
roc <- roc.curve(scores.class0 = fg, scores.class1 = bg, curve = TRUE)
print(roc)
Rita AUC-ROC kurvan:
# Plot AUC-ROC
plot(roc)
Skriv ut AUPRC-kurvan:
# Compute AUPRC
pr <- pr.curve(scores.class0 = fg, scores.class1 = bg, curve = TRUE)
print(pr)
Plotta AUPRC-kurvan:
# Plot AUPRC
plot(pr)
Balanserad datauppsättning (via SMOTE)
Beräkna förutsägelserna:
smote_fg <- smote_preds[test_df$Class == 1]
smote_bg <- smote_preds[test_df$Class == 0]
Skriv ut AUC-ROC kurvan:
# Compute AUC-ROC
smote_roc <- roc.curve(scores.class0 = smote_fg, scores.class1 = smote_bg, curve = TRUE)
print(smote_roc)
Rita AUC-ROC kurvan:
# Plot AUC-ROC
plot(smote_roc)
Skriv ut AUPRC-kurvan:
# Compute AUPRC
smote_pr <- pr.curve(scores.class0 = smote_fg, scores.class1 = smote_bg, curve = TRUE)
print(smote_pr)
Plotta AUPRC-kurvan:
# Plot AUPRC
plot(smote_pr)
De tidigare siffrorna visar tydligt att modellen som tränats på den balanserade datamängden överträffar modellen som tränats på den obalanserade datamängden, för både AUC-ROC- och AUPRC-poäng. Det här resultatet tyder på att SMOTE effektivt förbättrar modellens prestanda när du arbetar med mycket obalanserade data.