1. 總覽
在本實驗室中,您將直接擷取 BigQuery 資料集,並在 Google Cloud AI Platform 上使用 TensorFlow Enterprise 訓練詐欺偵測模型。
課程內容
內容如下:
- 分析 BigQuery 中的資料
- 使用 TensorFlow Enterprise 中的 BigQuery 連接器擷取資料
- 使用不平衡的資料集建構深度學習模型,偵測詐欺行為
2. 在 BigQuery 中分析資料
您必須擁有已啟用計費功能的 Google Cloud Platform 專案,才能執行這項程式碼研究室。如要建立專案,請按照這裡的操作說明進行。
步驟 1:存取 BigQuery 公開資料集
按一下這個連結,即可在 Google Cloud 控制台中存取 BigQuery 公開資料集。
在左下角的「資源樹狀結構」中,您會看到資料集清單。瀏覽可用的資料集,直到找到 ml-datasets 為止,然後選取其中的 ulb-fraud-detection 表格:

點選各個分頁標籤,進一步瞭解資料集:
- 「結構定義」分頁會說明資料類型。
- 「詳細資料」分頁說明這是不平衡的資料集,內含 284,407 筆交易,其中 492 筆為詐欺交易。
- 「預覽」分頁會顯示資料集的記錄。
步驟 2:查詢表格
「詳細資料」分頁會顯示資料的下列資訊:
- 「時間」是指資料集中的第一筆交易與所選交易之間的時間差 (以秒為單位)。
- V1-V28 是透過稱為 PCA 的降維技術轉換的資料欄,可匿名化資料。
- 金額是交易金額。
按一下「查詢資料表」執行查詢,進一步瞭解:

更新陳述式,加入 * 來查看所有欄,然後按一下「執行」。
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`

相關係數的範圍為 -1 (負相關) 到 1 (正相關),0 則表示獨立。
請注意,V1 和 V2 與目標變數的相關性略有不同 (分別約為 -0.1 和 0.1)。
我們發現與「時間」的關聯性不大。如果相關性略為負向,可能表示資料集中詐欺交易的數量隨時間減少。
「金額」的相關性更低,表示交易金額越高,詐欺交易的可能性就稍微高一點。
步驟 4:計算特徵縮放的平均值
特徵值正規化有助於神經網路更快收斂。常見的方案是以 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 個資料集:
- 訓練:用於建構模型,方法是反覆調整參數
- 驗證:在訓練過程中驗證獨立資料,評估模型是否過度配適
- 測試:模型建立完成後,用來評估準確度
在本程式碼研究室中,我們會使用 80/10/10 的訓練/驗證/測試分割比例。
我們會將每個資料集放入 BigQuery 的專屬資料表中。第一步是建立 BigQuery「資料集」,也就是相關資料表的容器。選取專案後,選取「建立資料集」。

接著,建立名為 tfe_codelab 的資料集,內含訓練、驗證和測試資料表。

現在,我們要執行 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 資料表。

在您剛建立的 tfe_codelab 資料集中,將資料表命名為 ulb_fraud_detection_train,然後儲存資料。

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。

步驟 2:建立 AI Platform Notebooks 執行個體
前往 Cloud Console 的 AI Platform Notebooks 專區,然後點選「建立執行個體」。然後選取最新版的「TensorFlow 企業版 1.x」執行個體類型,且「不加入任何 GPU」:
使用預設選項,然後按一下「建立」。建立執行個體後,請選取「Open JupyterLab」:

接著,從 JupyterLab 建立 Python 3 筆記本:

4. 從 BigQuery 擷取記錄
步驟 1:匯入 Python 套件
在筆記本的第一個儲存格中,新增下列匯入內容並執行儲存格。如要執行,請按下頂端選單中的向右箭頭按鈕,或按下 Command-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 變更為您使用的實際專案 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() 是一個輔助函式,可將標籤資料欄與其餘資料欄分開,讓資料集符合稍後 keras.model_fit() 預期的格式。
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. 建構模型
步驟 1:預先處理資料
現在要為資料集中的每個特徵建立特徵資料欄。在這個特定資料集中,所有資料欄都是 numeric_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:建構模型
現在可以開始建立模型。我們會將剛建立的資料欄饋送至網路。接著編譯模型。我們納入了精確度/喚回度 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:訓練模型
處理不平衡資料的方法有很多,包括過度取樣 (在少數類別中產生新資料) 和取樣不足 (減少多數類別中的資料)。
在本程式碼研究室中,我們將使用一種技術,在錯誤分類少數類別時,過度加權損失。訓練時,我們會指定 class_weight 參數,並將「1」(詐欺) 的權重調高,因為這類事件較不常見。
在本實驗室中,我們將使用 3 個訓練週期 (資料傳遞),以加快訓練速度。在實際情境中,我們會希望執行足夠長的時間,直到驗證集的準確度不再提升為止。
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:評估模型
您可以將 evaluate() 函式套用至模型從未見過的測試資料,進行客觀評估。幸好我們已預留測試資料,專門用於這項用途!
model.evaluate(test_data)
步驟 5:探索
在本實驗室中,我們示範了如何將大型資料集從 BigQuery 直接擷取至 TensorFlow Keras 模型。我們也逐步說明瞭如何建構模型。最後,我們稍微瞭解如何處理不平衡的分類問題。
歡迎繼續嘗試不同的架構和方法,處理不平衡的資料集,看看能否提高準確度!
6. 清除
如要繼續使用這部筆電,建議在不使用時關機。在 Cloud 控制台的 Notebooks 使用者介面中,選取筆記本,然後選取「停止」:

如要刪除在本實驗室中建立的所有資源,請刪除筆記本執行個體,而非停止執行個體。
使用 Cloud 控制台的導覽選單瀏覽至「儲存空間」,然後刪除您建立的兩個 bucket,以儲存模型資產。
