פיתוח מודל לזיהוי הונאות ב-Cloud AI Platform באמצעות TensorFlow Enterprise ו-BigQuery

1. סקירה כללית

בשיעור ה-Lab הזה תוטמעו באופן ישיר מערך נתונים של BigQuery ותאמנים מודל לזיהוי הונאות באמצעות TensorFlow Enterprise ב-Google Cloud AI Platform.

מה לומדים

נסביר לכם איך:

  • ניתוח נתונים ב-BigQuery
  • הטמעת נתונים באמצעות מחבר BigQuery ב-TensorFlow Enterprise
  • פיתוח מודל למידה עמוקה (Deep Learning) כדי לזהות הונאות באמצעות מערך נתונים לא מאוזן

2. ניתוח הנתונים ב-BigQuery

כדי להריץ את ה-Codelab הזה צריך פרויקט ב-Google Cloud Platform שהחיוב מופעל בו. כדי ליצור פרויקט, יש לפעול לפי ההוראות האלה.

שלב 1: גישה למערך הנתונים הציבורי של BigQuery

כדי לגשת למערכי נתונים ציבוריים של BigQuery במסוף Google Cloud, לוחצים על הקישור הזה.

בעץ המשאבים בפינה הימנית התחתונה, תוצג רשימה של מערכי הנתונים. מנווטים בין מערכי הנתונים הזמינים עד שמוצאים את הביטוי ml-datasets ובוחרים בטבלה ulb-fraud-detection שבטבלה:

d5e78261514a90ef.png

כדי לקבל מידע נוסף על מערך הנתונים, לוחצים מסביב לכל כרטיסייה:

  • בכרטיסייה Schema מתוארים סוגי הנתונים.
  • בכרטיסייה פרטים מוסבר שמדובר במערך נתונים לא מאוזן שכולל 284,407 עסקאות, שמתוכן 492 בוצעו במרמה.
  • בכרטיסייה Preview (תצוגה מקדימה) מוצגות הרשומות ממערך הנתונים.

שלב 2: שליחת שאילתה על הטבלה

כרטיסיית הפרטים מספקת לנו את המידע הבא על הנתונים:

  • זמן: מספר השניות בין העסקה הראשונה במערך הנתונים לבין הזמן של העסקה שנבחרה.
  • V1-V28 הן עמודות שעברו טרנספורמציה באמצעות שיטה להפחתת מימדים שנקראת PCA, שביצעה אנונימיזציה של הנתונים.
  • Amount הוא סכום העסקה.

נבדוק אותו לעומק על ידי לחיצה על Query Table כדי להריץ שאילתה:

581e596426a98383.png

מעדכנים את ההצהרה כדי להוסיף * כדי להציג את כל העמודות, ולוחצים על Run.

SELECT * FROM `bigquery-public-data.ml_datasets.ulb_fraud_detection` LIMIT 1000

שלב 3: ניתוח הנתונים

BigQuery מספק מספר פונקציות סטטיות. בואו נסתכל על האופן שבו הנתונים מתאימים למשתנה היעד Class.

SELECT CORR(Time,Class) as TimeCorr, CORR(V1,Class) as V1Corr, CORR(V2,Class) as V2Corr, CORR(Amount,Class) as AmountCorr FROM `bigquery-public-data.ml_datasets.ulb_fraud_detection`

e1e98a8315b62e9e.png

הקורלציה תספק טווח בין 1- (בקורלציה שלילית) ל-1 (קורלציה חיובית), כש-0 הוא בלתי תלוי.

לתשומת ליבכם: ל-V1 ול-V2 יש התאמה קלה עם משתנה היעד שלנו (בסביבות -0.1 ו-0 .1 בהתאמה).

אין התאמה רבה לזמן. מתאם קצת שלילי עשוי להצביע על כך שיש פחות עסקאות שמקורן בתרמית לאורך זמן במערך הנתונים.

לסכום יש מתאם נמוך יותר, מה שמעיד על כך שעסקאות הונאה עשויות להיות מעט יותר גבוהות בסכומים גבוהים יותר של עסקאות.

שלב 4: חישוב הערכים הממוצעים להתאמה לעומס (scaling) של תכונות

נרמול ערכי תכונות יכול לעזור לרשת נוירונים להתמזג מהר יותר. סכמה נפוצה היא למרכז ערכים סביב 0 עם סטיית תקן של 1. השאילתה הבאה תאחזר את הערכים הממוצעים. לא צריך לשמור את התוצאה, כי בהמשך יהיה לנו קטע קוד בשבילה.

ניתן לראות גם שהשאילתה כוללת משפט WHERE מעניין. בחלק הבא נתאר זאת בקטע שבו נתאר איך לפצל את הנתונים בין ערכות האימון לערכות הבדיקה.

SELECT
   AVG(Time), AVG(V1), AVG(V2), AVG(V3), AVG(V4), AVG(V5), AVG(V6), AVG(V7), AVG(V8),
   AVG(V9), AVG(V10),AVG(V11), AVG(V12), AVG(V13), AVG(V14), AVG(V15), AVG(V16),
   AVG(V17), AVG(V18), AVG(V19), AVG(V20), AVG(V21), AVG(V22), AVG(V23), AVG(V24),
   AVG(V25), AVG(V26), AVG(V27),AVG(V28), AVG(Amount)
FROM
   `bigquery-public-data.ml_datasets.ulb_fraud_detection`
WHERE
   MOD(ABS(FARM_FINGERPRINT(CONCAT(SAFE_CAST(Time AS STRING),
   SAFE_CAST(Amount AS STRING)))),10) < 8

שלב 5: פיצול הנתונים

מקובל להשתמש ב-3 מערכי נתונים כשמפתחים מודל של למידת מכונה:

  • אימון: משמש לבניית המודל באמצעות התאמה חזרתית של פרמטרים
  • תיקוף: משמש כדי להעריך אם המודל מבצע התאמת יתר על ידי אימות נתונים בלתי תלויים בתהליך האימון.
  • בדיקה: משמש אחרי שהמודל נוצר כדי להעריך את הדיוק

ב-Codelab הזה, נשתמש בפיצול/אימות/אימות/בדיקה של 80/10/10.

אנחנו נכניס כל מערך נתונים לטבלה משלו ב-BigQuery. השלב הראשון הוא יצירת "מערך נתונים" של BigQuery שהוא מאגר לטבלאות קשורות. כשהפרויקט נבחר, בוחרים באפשרות Create Dataset (יצירת מערך נתונים).

1084d9f5edbf760b.png

לאחר מכן יוצרים מערך נתונים בשם tfe_codelab שיכיל את הטבלאות של האימון, האימות והבדיקה.

e5b8646ebdf5f272.png

עכשיו נריץ 3 שאילתות לאמן, לבדיקה ולאימות, ונשמור את הנתונים במערך הנתונים החדש של tfe_codelab.

בעורך השאילתות, מריצים שאילתה כדי ליצור את נתוני האימון:

SELECT *
FROM `bigquery-public-data.ml_datasets.ulb_fraud_detection`
WHERE MOD(ABS(FARM_FINGERPRINT(CONCAT(SAFE_CAST(Time AS STRING),SAFE_CAST(Amount AS STRING)))),10) < 8

בסיום השאילתה, שומרים את התוצאות בטבלת BigQuery.

49d20c9b4b62f6a7.png

במערך הנתונים tfe_codelab שיצרתם עכשיו, נותנים לטבלה את השם ulb_fraud_detection_train ושומרים את הנתונים.

6d83cf113a0682e1.png

משפט WHERE מפצל תחילה את הנתונים על ידי חישוב גיבוב בכמה עמודות. לאחר מכן היא בוחרת שורות שבהן שארית הגיבוב כשמחלקים ב-10 היא מתחת ל-80, כך שהתוצאה שמתקבלת היא 80%.

נחזור על אותו תהליך לאימות ולבדיקה של קבוצות עם שאילתות דומות שבוחרות 10% מהנתונים, כל אחת.

אימות

SELECT *
FROM `bigquery-public-data.ml_datasets.ulb_fraud_detection`
WHERE MOD(ABS(FARM_FINGERPRINT(CONCAT(SAFE_CAST(Time AS STRING),SAFE_CAST(Amount AS STRING)))),10) = 8

שומרים את תוצאות השאילתה בטבלה בשם ulb_fraud_detection_val.

בדיקה

SELECT *
FROM `bigquery-public-data.ml_datasets.ulb_fraud_detection`
WHERE MOD(ABS(FARM_FINGERPRINT(CONCAT(SAFE_CAST(Time AS STRING),SAFE_CAST(Amount AS STRING)))),10) = 9

שומרים את תוצאות השאילתה בטבלה בשם ulb_fraud_detection_test.

3. הגדרת סביבת ה-notebook

עכשיו, אחרי שעברנו על מבוא קצר של הנתונים, נגדיר את סביבת פיתוח המודלים שלנו.

שלב 1: הפעלת ממשקי API

המחבר של BigQuery משתמש ב-BigQuery Storage API. מחפשים את BigQuery Storage API במסוף ומפעילים את ה-API אם הוא מושבת כרגע.

9895a2fd3cdf8f8c.png

שלב 2: יצירת מכונה של AI Platform Notebooks

עוברים אל הקטע 'notebooks של AI Platform' במסוף Cloud ולוחצים על New Instance. אחר כך בוחרים את סוג המכונה העדכני ביותר של TensorFlow Enterprise 1.x ללא GPU:

35301141e9fd3f44.png

משתמשים באפשרויות ברירת המחדל ואז לוחצים על יצירה. אחרי שיוצרים את המכונה, בוחרים באפשרות Open JupyterLab:

3b801f8ff3db0f2f.png

לאחר מכן יוצרים notebook מסוג Python 3 מ-JupyterLab:

58523671a252b95a.png

4. הטמעת רשומות מ-BigQuery

שלב 1: מייבאים חבילות Python

בתא הראשון של ה-notebook, מוסיפים את פעולות הייבוא הבאות ומריצים את התא. אפשר להריץ אותו על ידי לחיצה על לחצן החץ ימינה בתפריט העליון או על ידי הקשה על מקש Enter:

import tensorflow as tf
import tensorflow.keras as keras
import tensorflow.keras.layers as layers

from tensorflow_io.bigquery import BigQueryClient

import functools

tf.enable_eager_execution()

שלב 2: מגדירים קבועים

עכשיו נגדיר כמה קבועים לשימוש בפרויקט. משנים את GCP_PROJECT_ID למזהה הפרויקט בפועל שבו אתם משתמשים. עכשיו אפשר להריץ תאים חדשים בזמן שיוצרים אותם.

GCP_PROJECT_ID = '<YOUR_PROJECT_ID>'
DATASET_GCP_PROJECT_ID = GCP_PROJECT_ID # A copy of the data is saved in the user project
DATASET_ID = 'tfe_codelab'
TRAIN_TABLE_ID = 'ulb_fraud_detection_train'
VAL_TABLE_ID = 'ulb_fraud_detection_val'
TEST_TABLE_ID = 'ulb_fraud_detection_test'

FEATURES = ['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','Amount']
LABEL='Class'
DTYPES=[tf.float64] * len(FEATURES) + [tf.int64]

שלב 3: הגדרת פונקציות עזר

עכשיו נגדיר כמה פונקציות. הפונקציה read_session() קוראת נתונים מטבלה ב-BigQuery. extract_labels() היא פונקציה מסייעת להפרדת עמודת התווית מהשאר, כך שמערך הנתונים יהיה בפורמט המצופה מ-extract_labels() בהמשך.

client = BigQueryClient()

def read_session(TABLE_ID):
    return client.read_session(
        "projects/" + GCP_PROJECT_ID, DATASET_GCP_PROJECT_ID, TABLE_ID, DATASET_ID,
        FEATURES + [LABEL], DTYPES, requested_streams=2
)

def extract_labels(input_dict):
  features = dict(input_dict)
  label = tf.cast(features.pop(LABEL), tf.float64)
  return (features, label)

שלב 4: הטמעת הנתונים

לסיום, ניצור כל מערך נתונים ונדפיס את אצוות הנתונים הראשונה ממערך הנתונים לאימון. שימו לב שהגדרנו BATCH_SIZE של 32. זה פרמטר חשוב שישפיע על המהירות והדיוק של האימון.

BATCH_SIZE = 32

raw_train_data = read_session(TRAIN_TABLE_ID).parallel_read_rows().map(extract_labels).batch(BATCH_SIZE)
raw_val_data = read_session(VAL_TABLE_ID).parallel_read_rows().map(extract_labels).batch(BATCH_SIZE)
raw_test_data = read_session(TEST_TABLE_ID).parallel_read_rows().map(extract_labels).batch(BATCH_SIZE)

next(iter(raw_train_data)) # Print first batch

5. מודל build

שלב 1: מעבדים מראש את הנתונים

ניצור עמודות של תכונות לכל תכונה במערך הנתונים. במערך הנתונים הספציפי הזה, כל העמודות הן מסוג num_column אבל יש כמה סוגי עמודות אחרים (למשל categorical_column).

כמו שהסברנו קודם, אנחנו גם נוסיף את הנתונים למרכז סביב האפס כדי שהרשת תתכנס מהר יותר. חישבנו מראש את האמצעים של כל תכונה לשימוש בחישוב זה.

MEANS = [94816.7387536405, 0.0011219465482001268, -0.0021445914636999603, -0.002317402958335562,
         -0.002525792169927835, -0.002136576923287782, -3.7586818983702984, 8.135919975738768E-4,
         -0.0015535579268265718, 0.001436137140461279, -0.0012193712736681508, -4.5364970422902533E-4,
         -4.6175444671576083E-4, 9.92177789685366E-4, 0.002366229151475428, 6.710217226762278E-4,
         0.0010325807119864225, 2.557260815835395E-4, -2.0804190062322664E-4, -5.057391100818653E-4,
         -3.452114767842334E-6, 1.0145936326270006E-4, 3.839214074518535E-4, 2.2061197469126577E-4,
         -1.5601580596677608E-4, -8.235017846415852E-4, -7.298316615408554E-4, -6.898459943652376E-5,
         4.724125688297753E-5, 88.73235686453587]

def norm_data(mean, data):
  data = tf.cast(data, tf.float32) * 1/(2*mean)
  return tf.reshape(data, [-1, 1])

numeric_columns = []

for i, feature in enumerate(FEATURES):
  num_col = tf.feature_column.numeric_column(feature, normalizer_fn=functools.partial(norm_data, MEANS[i]))
  numeric_columns.append(num_col)

numeric_columns

שלב 2: בניית המודל

עכשיו אנחנו מוכנים ליצור מודל. אנחנו נזין את העמודות שיצרנו ברשת. לאחר מכן אנחנו נקמפל את המודל. אנחנו כוללים את המדד Precision/Recall AUC, ששימושי למערכי נתונים לא מאוזנים.

model = keras.Sequential([
    tf.keras.layers.DenseFeatures(numeric_columns),
    layers.Dense(64, activation='relu'),
    layers.Dense(64, activation='relu'),
    layers.Dense(1, activation='sigmoid')
])

model.compile(loss='binary_crossentropy',
              optimizer='adam',
              metrics=['accuracy', tf.keras.metrics.AUC(curve='PR')])

שלב 3: מאמנים את המודל

יש כמה שיטות לטיפול בנתונים לא מאוזנים, כולל דגימת יתר (יצירת נתונים חדשים בקבוצת מיעוט) ודגימת יתר (צמצום הנתונים בקבוצת הרוב).

למטרות של ה-codelab הזה, נשתמש בשיטה שמשקללת את האובדן בזמן סיווג שגוי של סיווג מיעוט. נציין פרמטר class_weight לאחר אימון ומשקל '1' (הונאה) גבוהה יותר, מכיוון שהיא הרבה פחות נפוצה.

נשתמש ב-3 תקופות של זמן מערכת (מעבר על הנתונים) בשיעור ה-Lab הזה כדי שהאימון יהיה מהיר יותר. בתרחיש בעולם האמיתי, נרצה להריץ את הניסוי מספיק זמן עד שתפסיק לראות עלייה ברמת הדיוק של קבוצת האימות.

CLASS_WEIGHT = {
    0: 1,
    1: 100
}
EPOCHS = 3

train_data = raw_train_data.shuffle(10000)
val_data = raw_val_data
test_data = raw_test_data

model.fit(train_data, validation_data=val_data, class_weight=CLASS_WEIGHT, epochs=EPOCHS)

שלב 4: הערכת המודל

אפשר להשתמש בפונקציה value() כדי לבדוק נתונים שהמודל מעולם לא ראה כדי לספק הערכה אובייקטיבית. לשמחתנו, השארנו את נתוני הבדיקה בדיוק בשביל זה!

model.evaluate(test_data)

שלב 5: ניתוח

בשיעור ה-Lab הזה הדגמנו איך להטמיע קבוצת נתונים גדולה מ-BigQuery ישירות במודל Keras של TensorFlow. בנוסף, עברנו על כל השלבים ליצירת מודל. לבסוף, למדנו קצת איך להתמודד עם בעיות של סיווג לא מאוזן.

אתם יכולים להמשיך לשחק עם הארכיטקטורות והגישות השונות למערך הנתונים הלא מאוזן, כדי לבדוק אם אפשר לשפר את הדיוק.

6. הסרת המשאבים

אם ברצונך להמשיך להשתמש ב-notebook הזה, מומלץ להשבית אותו כשהוא לא בשימוש. בממשק המשתמש של Notebooks במסוף Cloud, בוחרים את ה-notebook ואז לוחצים על Stop (עצירה):

57213ef2edad9257.png

כדי למחוק את כל המשאבים שיצרתם בשיעור ה-Lab הזה, תוכלו פשוט למחוק את המכונה של ה-notebook במקום לעצור אותה.

באמצעות תפריט הניווט במסוף Cloud, עוברים לקטע 'אחסון' ומוחקים את שתי הקטגוריות שיצרתם לצורך אחסון הנכסים של המודלים.