使用自動編碼器檢測信用卡欺詐
使用自動編碼器檢測信用卡欺詐
- 來源 |願碼(ChainDesk.CN) 內容編輯
- 願碼Slogan | 連線每個程式設計師的故事
- 網站 |http://chaindesk.cn
- 願碼願景 | 打造全學科IT系統免費課程,助力小白使用者、初級工程師0成本免費系統學習、低成本進階,幫助BAT一線資深工程師成長並利用自身優勢創造睡後收入。
- 官方公眾號 | 願碼 | 願碼服務號 | 區塊鏈部落
- 免費加入願碼全思維工程師社群 | 任一公眾號回覆“願碼”兩個字獲取入群二維碼
本文閱讀時間:11min
自動編碼器是重要的生成模型型別之一,具有一些有趣的特性,可以用於檢測信用卡欺詐等應用。在本文中,我們將使用Autoencoders來檢測信用卡欺詐。
我們將使用一個新的資料集,其中包含具有匿名功能的實際信用卡交易記錄。資料集不適用於很多特徵工程。我們將不得不依靠端到端的學習方法來構建一個好的欺詐檢測器。
從資料集載入資料
像往常一樣,我們首先載入資料。時間特徵顯示了交易的絕對時間,這使得在這裡處理起來有點困難。所以我們將放棄它。
df = pd.read_csv('../input/creditcard.csv') df = df.drop('Time',axis=1)
我們將事務的X資料與事務的分類分開,並提取作為pandas資料幀基礎的numpy陣列。
X = df.drop('Class',axis=1).values y = df['Class'].values
功能縮放
現在我們需要擴充套件功能。特徵縮放使我們的模型更容易學習資料的良好表示。對於特徵縮放,我們將所有特徵縮放為介於0和1之間。這可確保資料集中沒有非常高或非常低的值。但要注意,這種方法容易受到影響結果的異常值的影響。對於每列,我們首先減去最小值,以使新的最小值變為零。然後我們除以最大值,使新的最大值變為1。通過指定axis = 0,我們執行縮放列。
X -= X.min(axis=0) X /= X.max(axis=0)
最後,我們分割了我們的資料:
from sklearn.model_selection import train_test_split X_train, X_test, y_train,y_test = train_test_split(X,y,test_size=0.1)
我們的編碼器輸入現在有29個尺寸,我們壓縮到12個尺寸,然後再恢復原始的29維輸出。
from keras.models import Model from keras.layers import Input, Dense
您會注意到我們最終使用的是sigmoid啟用函式。這是唯一可能的,因為我們將資料縮放為0到1之間的值。我們還使用編碼層的tanh啟用。這只是一種在實驗中執行良好的樣式選擇,並確保編碼值在-1和1之間。您可以根據需要使用不同的啟用功能。如果您正在處理影象或更深層次的網路,則重新啟用通常是一個不錯的選擇。如果您正在使用比我們在這裡更淺的網路,那麼tanh啟用通常很有效。
data_in = Input(shape=(29,)) encoded = Dense(12,activation='tanh')(data_in) decoded = Dense(29,activation='sigmoid')(encoded) autoencoder = Model(data_in,decoded)
我們使用均方誤差損失。這首先是一個不尋常的選擇,使用sigmoid啟用和均方誤差丟失,但它是有道理的。大多數人認為乙狀結腸啟用必須與交叉熵損失一起使用。但是交叉熵損失會使值為零或一,並且在這種情況下適用於分類任務。但在我們的信用卡示例中,大多數值約為0.5。均值誤差在處理目標不是二進位制的值時更好,但在頻譜上更好。
autoencoder.compile(optimizer='adam',loss='mean_squared_error')
訓練後,自動編碼器收斂到低損耗。
autoencoder.fit(X_train, X_train, epochs = 20, batch_size=128, validation_data=(X_test,X_test))
重建損失很低,但我們怎麼知道我們的自動編碼器是否執行良好?再次,檢查。人類非常善於視覺判斷事物,但不善於判斷抽象數字。
我們將首先進行一些預測,其中我們通過自動編碼器執行測試集的子集。
pred = autoencoder.predict(X_test[0:10])
然後我們可以繪製單個樣本。下面的程式碼生成一個重疊的條形圖,將原始交易資料與重建的交易資料進行比較。
import matplotlib.pyplot as plt
import numpy as np width = 0.8 prediction= pred[9] true_value = X_test[9] indices = np.arange(len(prediction)) fig = plt.figure(figsize=(10,7)) plt.bar(indices, prediction, width=width, color='b', label='Predicted Value') plt.bar([i+0.25*width for i in indices], true_value, width=0.5*width, color='r', alpha=0.5, label='True Value') plt.xticks(indices+width/2., ['V{}'.format(i) for i in range(len(prediction))] ) plt.legend() plt.show()
用t-SNE視覺化潛在空間
我們現在有一個神經網路,它接受信用卡交易並輸出看起來或多或少相同的信用卡交易。但這當然不是我們構建自動編碼器的原因。自動編碼器的主要優點是我們現在可以將事務編碼為較低維度的表示,該表示捕獲事務的主要元素。要建立編碼器模型,我們所要做的就是定義一個新的Keras模型,它從輸入對映到編碼狀態:
encoder = Model(data_in,encoded)
請注意,您無需再次訓練此模型。這些層保留了我們之前訓練過的自動編碼器的權重。
為了編碼我們的資料,我們現在使用編碼器模型:
enc = encoder.predict(X_test)
但是,我們如何知道這些編碼是否包含有關欺詐的任何有意義的資訊?再一次,視覺表現是關鍵。雖然我們的編碼尺寸低於輸入資料,但它們仍然具有十二個維度。人類不可能考慮12維空間,因此我們需要在較低維度的空間中繪製我們的編碼,同時仍然保留我們關心的特徵。
在我們的例子中,我們關心的特徵是接近度 。我們希望在二維圖中,在12維空間中彼此接近的點彼此接近。更確切地說,我們關心鄰域,我們希望在高維空間中彼此最接近的點在低維空間中也彼此最接近。
保留鄰居是相關的,因為我們想要找到欺詐叢集。如果我們發現欺詐性交易在我們的高維編碼中形成一個叢集,我們可以使用一個簡單的檢查來判斷一個新的交易是否屬於欺詐叢集,以便將交易標記為欺詐。
將高維資料投影到低維圖中同時保留鄰域的流行方法稱為t分佈隨機鄰域嵌入或t-SNE。
簡而言之,t-SNE旨在忠實地表示在所有點的隨機樣本中兩個點是鄰居的概率。也就是說,它試圖找到資料的低維表示,其中隨機樣本中的點具有與高維資料中相同的最接近鄰居的概率。
t-SNE演算法遵循以下步驟:
- 計算所有點之間的高斯相似度。這是通過計算點之間的歐幾里德(空間)距離然後計算該距離處的高斯曲線的值來完成的,參見圖形。來自該點的所有點的高斯相似度可以計算為:
- ' sigma '是高斯分佈的方差?我們將在稍後討論如何確定這種差異。注意,由於點i和j之間的相似性通過所有其他點之間的距離之和(表示為k)來縮放,因此i,j,pi|j之間的相似性可以與j和i之間的相似性不同,pj|i 。因此,我們平均兩個相似點以獲得我們繼續工作的最終相似性,其中n是資料點的數量。
- 隨機地將資料點定位在較低維空間中。
- 計算較低維空間中所有點之間的t-相似度 。
- 就像訓練神經網路一樣,我們將通過遵循損失函式的梯度來優化較低維空間中的資料點的位置。在這種情況下,損失函式是較高和較低維空間中相似性之間的Kullback-Leibler(KL)差異。我們將在變分自動編碼器部分詳細介紹KL分歧。現在,只需將其視為衡量兩種分佈之間差異的方法。損失函式相對於 較低維空間中的資料點i的位置yi的導數是:
- 使用梯度下降調整較低維空間中的資料點。高維資料中靠近的移動點靠近在一起,並且移動點彼此遠離更遠。
您會將此識別為具有動量的梯度下降形式,因為先前的漸變已合併到位置更新中。
使用的t分佈總是具有一個自由度。一個自由度的選擇導致更簡單的公式以及一些不錯的數值屬性,從而導致更快的計算和更有用的圖表。
具有困惑超引數的使用者可以影響高斯分佈的標準偏差。困惑可以解釋為我們期望得到的鄰居的數量。低茫然值強調區域性鄰近,而大茫然值強調全域性茫然值。在數學上,困惑可以計算為:
其中Pi是資料集中所有資料點位置的概率分佈,H(Pi)是此分佈的Shannon熵,計算公式如下:
雖然該公式的細節與使用t-SNE不是非常相關,但重要的是要知道t-SNE執行對標準偏差' sigma '的值的搜尋,以便它找到其上的熵的全域性分佈Pi。我們的資料是我們所希望的困惑。換句話說,您需要手動指定困惑,但這種困惑對資料集的意義也取決於資料集。
t-SNE的發明者Van Maarten和Hinton報告說,該演算法對於5到50之間的困惑選擇相對穩健。大多數庫中的預設值是30,這對於大多數資料集來說是一個很好的值。如果你發現你的視覺化效果不理想,那麼調整困惑度值可能是你想要做的第一件事。
對於所涉及的所有數學,使用t-SNE非常簡單。scikit-learn有一個方便的t-SNE 實現,我們可以像scikit中的任何演算法一樣使用它。我們首先匯入TSNE類。然後我們建立一個新的TSNE例項。我們定義我們想要訓練5000個時期,使用30的預設困惑和200的預設學習率。我們還指定我們希望在訓練過程中輸出。然後我們只需呼叫fit_transform,它將我們的12維編碼轉換為二維投影。
from sklearn.manifold import TSNE tsne = TSNE(verbose=1,n_iter=5000) res = tsne.fit_transform(enc)
作為警告,t-SNE非常慢,因為它需要計算所有點之間的距離。預設情況下,sklearn使用稱為Barnes Hut近似的更快版本的t-SNE,它不是那麼精確但已經快得多。
有一個更快的python實現t-SNE,可以用來代替sklearn的實現。然而,它沒有得到很好的記錄,並且具有較少的功能。
我們可以將t-SNE結果繪製為散點圖。例如,我們將通過顏色區分欺詐與非欺詐,欺詐以紅色繪製,非欺詐以藍色繪製。由於t-SNE的實際值無關緊要,我們將隱藏軸。
fig = plt.figure(figsize=(10,7)) scatter =plt.scatter(res[:,0],res[:,1],c=y_test, cmap='coolwarm', s=0.6) scatter.axes.get_xaxis().set_visible(False) scatter.axes.get_yaxis().set_visible(False)
為了便於定位,包含大多數欺詐的群集標有圓圈。您可以看到欺詐與其他交易完全分開。顯然,我們的自動編碼器已經找到了一種方法,可以在不給出標籤的情況下將欺詐與真實交易區分開來。這是一種無監督學習的形式。事實上,普通自動編碼器執行PCA的近似,這對於無監督學習很有用。在圖表中,您可以看到一些明顯與其他交易分開但不是欺詐的叢集。使用自動編碼器和無監督學習,可以以我們之前沒有考慮過的方式分離和分組我們的資料。