使用自動編碼器檢測信用卡欺詐

2020-02-29     sandag

自動編碼器是重要的生成模型類型之一,具有一些有趣的特性,可以用於檢測信用卡欺詐等應用。在本文中,我們將使用Autoencoders來檢測信用卡欺詐。

我們將使用一個新的數據集,其中包含具有匿名功能的實際信用卡交易記錄。數據集不適用於很多特徵工程。我們將不得不依靠端到端的學習方法來構建一個好的欺詐檢測器。

從數據集加載數據

像往常一樣,我們首先加載數據。時間特徵顯示了交易的絕對時間,這使得在這裡處理起來有點困難。所以我們將放棄它。

df = pd.read_csv('../input/creditcard.csv')df = df.drop('Time',axis=1)

我們將事務的X數據與事務的分類分開,並提取作為pandas數據幀基礎的numpy數組。

X = df.drop('Class',axis=1).valuesy = 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_splitX_train, X_test, y_train,y_test = train_test_split(X,y,test_size=0.1)

我們的編碼器輸入現在有29個尺寸,我們壓縮到12個尺寸,然後再恢復原始的29維輸出。

from keras.models import Modelfrom 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 npwidth = 0.8prediction   = 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算法遵循以下步驟:

  1. 計算所有點之間的高斯相似度。這是通過計算點之間的歐幾里德(空間)距離然後計算該距離處的高斯曲線的值來完成的,參見圖形。來自該點的所有點的高斯相似度可以計算為:

  1. ' sigma '是高斯分布的方差?我們將在稍後討論如何確定這種差異。注意,由於點i和j之間的相似性通過所有其他點之間的距離之和(表示為k)來縮放,因此i,j,pi|j之間的相似性可以與j和i之間的相似性不同,pj|i 。因此,我們平均兩個相似點以獲得我們繼續工作的最終相似性,其中n是數據點的數量。

  1. 隨機地將數據點定位在較低維空間中。
  2. 計算較低維空間中所有點之間的 t-相似度 。

  1. 就像訓練神經網絡一樣,我們將通過遵循損失函數的梯度來優化較低維空間中的數據點的位置。在這種情況下,損失函數是較高和較低維空間中相似性之間的Kullback-Leibler(KL)差異。我們將在變分自動編碼器部分詳細介紹KL分歧。現在,只需將其視為衡量兩種分布之間差異的方法。損失函數相對於 較低維空間中的數據點i的位置yi的導數是:

  1. 使用梯度下降調整較低維空間中的數據點。高維數據中靠近的移動點靠近在一起,並且移動點彼此遠離更遠。

您會將此識別為具有動量的梯度下降形式,因為先前的漸變已合併到位置更新中。

使用的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 TSNEtsne = 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的近似,這對於無監督學習很有用。在圖表中,您可以看到一些明顯與其他交易分開但不是欺詐的集群。使用自動編碼器和無監督學習,可以以我們之前沒有考慮過的方式分離和分組我們的數據。

文章來源: https://twgreatdaily.com/zh/ovHvkHAB3uTiws8KGcr3.html