
电商平台的欺诈检测是一个很典型的互联网风控场景。互联网业务的正常运行需要有一个强有力的欺诈检测系统做支持。一个好的欺诈检测系统必须能准确地识别欺诈交易并且能在实时交易进行过程中做出判断。
大体说来,欺诈检测可以分为异常检测和盗用检测。异常检测方法用正常交易的样本做训练得到模型来检测可能的新欺诈行为。盗用检测方法是用已经标记的正常样本和欺诈样本做训练得到识别一个新样本是欺诈或正常的可能性。
深度学习在欺诈检测领域有很多的算法应用。在本篇文章中我们用Auto-Encoder方法来对信用卡交易的样本建模并评估其效果。我们对互联网上公开的German Credit数据集进行实验。这个数据集有20个特征,包含信用历史,交易金额,职业等。German 数据集有1000 个样本。
神经网络是通过大量数据集,进行end-to-end的训练,不断提高其准确率。Auto-Encoder方法,如下图所示,通过设计encode和decode过程使输入和输出越来越接近,是一种无监督学习过程。
Auto-Encoder包括两个过程:encode和decode, 输入数据通过encode进行处理,得到code,再经过decode处理得到输出。我们控制encode的输出维数,就相当于强迫encode过程以低维参数学习高维特征。Auto-Encoder的目的是使下图中的输入x和输出x’ 越相似越好,这就需要在每次输出之后,进行误差反向传播,不断优化整个网络参数。
在本篇中我们用Keras训练一个Auto-Encoder神经网络,通过非监督的学习方法来识别信用卡交易中的异常行为。
装载数据
df = pd.read_csv("data/german_credit_data.csv")
数据探索
df.shape
(1000, 21)
1000个样本,21个特征。
LABELS = ["Normal", "Fraud"]
count_classes = pd.value_counts(df['Creditability'], sort = True)
count_classes.plot(kind = 'bar', rot=0)
plt.title("Transaction class distribution")
plt.xticks(range(2), LABELS)
plt.xlabel("Class")
plt.ylabel("Frequency")
准备数据
对Credit Amount等数值型特征通过scikit’s StandardScaler做标准化处理。对Purpose等分类型特征做one-hot encoding处理。
Code Example:
df['Credit_Amount'] = StandardScaler().fit_transform(df['Credit_Amount'].values.reshape(-1, 1))
df = pd.concat([df,pd.get_dummies(df['Purpose'], prefix='Purpose')],axis=1)
df.drop(['Purpose'],axis=1, inplace=True)
训练Auto-Encoder和训练一般的机器学习模型有不一样的地方。假设你手边有很多正常交易的样本,并且希望通过异常检测来识别新的可能的欺诈交易。那在训练Auto-Encoder时只对正常交易的样本进行训练。用训练好的模型预测测试集里样本可以对模型的表现进行评估。
RANDOM_SEED = 42
X_train, X_test = train_test_split(df, test_size=0.2, random_state=RANDOM_SEED)
X_train = X_train[X_train.Creditability == 0]
X_train = X_train.drop(['Creditability'], axis=1)
y_test = X_test['Creditability']
X_test = X_test.drop(['Creditability'], axis=1)
X_train = X_train.values
X_test = X_test.values
建立模型
我们建立有4层连接层分别是22,11,11,45个神经元的Auto-Encoder模型。前面2层是作为encoder,后面两层是作为decoder。
input_dim = X_train.shape[1]
encoding_dim = 22
input_layer = Input(shape=(input_dim, ))
encoder = Dense(encoding_dim, activation="tanh", activity_regularizer=regularizers.l1(10e-5))(input_layer)
encoder = Dense(int(encoding_dim / 2), activation="relu")(encoder)
decoder = Dense(int(encoding_dim / 2), activation='tanh')(encoder)
decoder = Dense(input_dim, activation='relu')(decoder)
autoencoder = Model(inputs=input_layer, outputs=decoder)
我们用100个Epoch,每次32个样本进入神经网络进行训练。
nb_epoch = 100
batch_size = 32
autoencoder.compile(optimizer='adam',
loss='mean_squared_error',
metrics=['accuracy'])
history = autoencoder.fit(X_train, X_train,
epochs=nb_epoch,
batch_size=batch_size,
shuffle=True,
validation_data=(X_test, X_test),
verbose=1).history
模型评估
predictions = autoencoder.predict(X_test)
mse = np.mean(np.power(X_test - predictions, 2), axis=1)
error_df = pd.DataFrame({'reconstruction_error': mse,
'true_class': y_test})
fpr, tpr, thresholds = roc_curve(error_df.true_class, error_df.reconstruction_error)
roc_auc = auc(fpr, tpr)
plt.title('Receiver Operating Characteristic')
plt.plot(fpr, tpr, label='AUC = %0.4f'% roc_auc)
plt.legend(loc='lower right')
plt.plot([0,1],[0,1],'r--')
plt.xlim([-0.001, 1])
plt.ylim([0, 1.001])
plt.ylabel('True Positive Rate')
plt.xlabel('False Positive Rate')
plt.show()
AUC = 0.5871,模型效果一般。我们检查一下训练集和测试集上的 reconstruction error曲线的走势。
plt.plot(history['loss'])
plt.plot(history['val_loss'])
plt.title('model loss')
plt.ylabel('loss')
plt.xlabel('epoch')
plt.legend(['train', 'test'], loc='upper right');
可以看出reconstruction error曲线下降幅度较小,并且没有趋向稳定收敛。可以认为是模型尚处于欠拟合。应该是用于训练的样本量较小的原因所致。
预测新样本
目前通过Auto-Encoder训练出来的模型是无法用于预测新样本的。为了能对新样本给出正常或欺诈的判断,我们需要对新样本计算出reconstruction error。
如果这个error大于某个事先设定好的阈值,我们就判断为欺诈。
error_df['reconstruction_error'].groupby(error_df['true_class']).describe()
阈值可以设定在0.2和0.24之间。如果在不知道正类负类标签的情况下,可以通过计算整体样本的reconstruction error的分位数来设定。
在本篇文章中我们通过Auto-Encoder对German Credit数据集进行无监督学习,得到了异常检测的模型示例。在实际应用中有很多需要注意的细节点,比如平衡神经网络的复杂度和训练集样本数的关系,保证模型在训练过程中能够有足够好的拟合逼近;对输入特征做更细致的预处理,包括相关性去重,去噪等操作。在深度学习中对categorical类型的变量也有比做one-hot encoding更好的处理机制。我们会在以后的文章中给出更多的示例。
12
往期精彩



