全国免费咨询:

13245491521

VR图标白色 VR图标黑色
X

中高端软件定制开发服务商

与我们取得联系

13245491521     13245491521

2020-10-06_如何使用机器学习检测欺诈?

您的位置:首页 >> 新闻 >> 行业资讯

如何使用机器学习检测欺诈? 作者 | Kurtis Pykes 译者 | Sambodhi 策划 & 编辑 | 刘燕 在现实世界中,欺诈检测是一个非常普遍且具有挑战性的问题。 本文最初发表于 Towards Data Science 博客,经原作者 Kurtis Pykes 授权,InfoQ 中文站翻译并分享。 机器学习是人工智能的一个子集,它赋予了系统从经验中自动学习和改进的能力,无需进行显式编程。如此说来,我们(人类)已经可以向计算机提供大量的数据集,让计算机学习模式,这样它在面对一个或多个新实例时,能够学习如何作出决定——当我发现这一见解时,我立即知道世界即将发生改变。 报告 显示,欺诈行为给全球经济造成了 3.89 万亿英镑的损失,在过去十年里损失上升了 56%。 ——Crowe UK 作为欺诈行为的受害者,我萌生了防止这种情况再次发生在我(以及其他任何人)身上的想法,这促使我开始思考一个与我所习惯的完全不同的领域。 欺诈检测问题 在机器学习术语中,诸如欺诈检测之类的问题,可以被归类为分类问题,其目标是预测离散标签 0 或 1,其中,0 通常表示交易是非欺诈性的,1 表示交易似乎是欺诈性的。 因此,这个问题要求从业人员构建足够智能的模型,以便能够在给定各种用户交易数据的情况下,正确地检测出欺诈性和非欺诈性的交易。为了保护用户隐私,这些交易数据通常都经过匿名化处理。 由于完全依赖基于规则的系统并不是最有效的策略,因此,机器学习已成为许多金融机构用来解决这一类问题的方法。 这个问题(欺诈检测)之所以如此具有挑战性,是因为当我们在现实世界对其进行建模时,发生的大多数交易都是真实的交易,只有很小一部分是欺诈行为。这意味着我们要处理数据不平衡的问题:我写的文章《过采样和欠采样》(Oversampling and Undersampling)就是处理这一类问题的一种方法。然而,对于这篇文章,我们的主要重点将是开始我们的机器学习框架来检测欺诈行为——如果你不熟悉构建自己的框架,那你可能需要在阅读本文之前,先阅读这篇文章《构建机器学习项目》(Structuring Machine Learning Projects)。 数 据 这些数据是由 IEEE 计算智能协会(IEEE Computational Intelligence Society,IEEE-CIS)的研究人员整理出来的,用于预测欺诈性在线交易概率的任务,以二进制目标isFraud来表示。 注:数据部分是从 Kaggle 竞赛数据部分复制而来。 数据分成两个文件identity和transaction,这两个文件由TransactionID连接。但并非所有交易都有相应的身份信息。 类别特征——交易(Transaction) ProductCD card1-card6 addr1、addr2 P_emaildomain R_emaildomain M1-M9 类别特征——身份信息(Identity) DeviceType DeviceInfo id_12-id_38 TransactionDT特征是给定引用日期时间(不是实际时间戳)开始的时间间隔(timedelta)。 你可以从比赛主持人的这篇文章《数据描述(详情及讨论)》(Data Description (Details and Discussion))中了解更多有关数据的信息。 文件 train_{transaction, identity}.csv——训练集 test_{transaction, identity}.csv——测试集(你必须预测这些观察值的isFraud值) sample_submission.csv——正确格式的样本提交文件 构建框架 在处理任何机器学习任务时,第一步是建立一个可靠的 交叉验证 策略。 注:该框架背后的总体思路来自于 Abhishek Thakur。 ——GitHub 当面对不平衡的数据问题时,通常采用的方法是使用StratifiedKFold,它以这样一种方式随机地分割数据,以保持相同的类分布。 我实现了 create folds,作为preprocessing.py的一部分。 import config import numpy as np import pandas as pd from sklearn.model_selection import StratifiedKFold def read_all_data(): train_transactions = pd.read_csv(config.TRAIN_TRANSACTIONS) train_identity = pd.read_csv(config.TRAIN_IDENTITY) test_transactions = pd.read_csv(config.TEST_TRANSACTIONS) test_identity = pd.read_csv(config.TEST_IDENTITY) return train_transactions, train_identity, test_transactions, test_identity def merge_data(df1, df2): # merge dataframe on the index merged_df = df1.merge(df2, how="left", on="TransactionID") return merged_df def create_folds(df): # create a new column df["kfold"] = -1 # shuffle data df = df.sample(frac=1, random_state=42).reset_index(drop=True) # initialize kfold skf = StratifiedKFold(n_splits=5, shuffle=False) for fold, (train_idx, val_idx) in enumerate(skf.split(X=df, y=df.isFraud.values)): print(len(train_idx), len(val_idx)) df.loc[val_idx, 'kfold'] = fold df.to_csv(config.DATA_DIR + "train_folds.csv", index=False) if __name__ == "__main__": train_transactions, train_identity, test_transactions, test_identity = read_all_data() merged_test = merge_data(test_transactions, test_identity) merged_train = merge_data(train_transactions, train_identity) del train_transactions, train_identity, test_transactions, test_identity # renaming test id columns for col in merged_test.columns: if "id" in col: merged_test.rename(columns={col : col.replace("-", "_")}, inplace=True) merged_test.to_csv(config.DATA_DIR + "test_df.csv", index=False) create_folds(merged_train) 这段代码合并了来自训练集和测试集的身份信息和交易数据,然后重命名了merded_test数据中的列名,因为 id 列使用的是“-”而不是“_”,这将导致稍后检查以确保测试中的列名完全相同时出现问题。接下来,我们在训练数据中添加一个名为kfold的列名,并根据它所在的 fold 设置索引,然后保存到 CSV 文件中。 你可能已经注意到,我们导入config并将其作为通向各种交易的路径。所有的config都是另一个脚本的变量,这样我们就不必在不同的脚本重复调用这些变量了。 # Directory Paths DATA_DIR = "../input/" MODEL_OUTPUT = "../models" # Training data TRAINING_DATA = DATA_DIR + "train_folds.csv" TRAIN_TRANSACTIONS = DATA_DIR + "train_transaction.csv" TRAIN_IDENTITY = DATA_DIR + "train_identity.csv" # Test data TEST_DATA = DATA_DIR + "test_df.csv" TEST_TRANSACTIONS = DATA_DIR + "test_transaction.csv" TEST_IDENTITY = DATA_DIR + "test_identity.csv" # Categorical Features CATEGORICAL_FEATURES = [ "ProductCD", "card1", "card2", "card3", "card4", "card5", "card6", "addr1", "addr2", "P_emaildomain", "R_emaildomain", "M1", "M2", "M3", "M4", "M5", "M6", "M7", "M8", "M9", "DeviceType", "DeviceInfo", "id_12", "id_13", "id_14", "id_15", "id_16", "id_17", "id_18", "id_19", "id_20", "id_21", "id_22", "id_23", "id_24", "id_25", "id_26", "id_27", "id_28", "id_29", "id_30", "id_31", "id_32", "id_33", "id_34", "id_35", "id_36", "id_37", "id_38" ] 在处理机器学习问题时,以允许快速迭代的方式快速构建管道是非常重要的,因此我们将构建的下一个脚本是model_dispatcher.py,我们将其称为分类器,而train.py是我们的训练模型的脚本。 让我们从model_dispatcher.py开始。 from sklearn import linear_model, ensemble models = {"logistic_regression": linear_model.LogisticRegression(verbose=True, max_iter=1000, random_state=10), "random_forest": ensemble.RandomForestClassifier(verbose=True, n_estimators=100, criterion="gini")} 在这里,我们简单地导入了一个逻辑回归和随机森林,并创建了一个字典,这样我们就可以通过运行逻辑回归模型models["logistic_regression"]来将算法调用到我们的训练脚本中。 训练脚本如下所示: import os import config import model_dispatcher import joblib import argparse import pandas as pd from sklearn import preprocessing from sklearn import metrics def pipe(fold:int, model:str): df = pd.read_csv(config.TRAINING_DATA) df_test = pd.read_csv(config.TEST_DATA) X_train = df[df["kfold"] != fold].reset_index(drop=True) X_valid = df[df["kfold"] == fold].reset_index(drop=True) y_train = X_train.isFraud.values y_valid = X_valid.isFraud.values X_train = X_train.drop(["isFraud", "kfold"], axis=1) X_valid = X_valid.drop(["isFraud", "kfold"], axis=1) X_valid = X_valid[X_train.columns] label_encoders = {} for c in config.CATEGORICAL_FEATURES: lbl = preprocessing.LabelEncoder() X_train.loc[:, c] = X_train.loc[:, c].astype(str).fillna("NONE") X_valid.loc[:, c] = X_valid.loc[:, c].astype(str).fillna("NONE") df_test.loc[:, c] = df_test.loc[:, c].astype(str).fillna("NONE") lbl.fit(X_train[c].values.tolist() + X_valid[c].values.tolist() + df_test[c].values.tolist()) X_train.loc[:, c] = lbl.transform(X_train[c].values.tolist()) X_valid.loc[:, c] = lbl.transform(X_valid[c].values.tolist()) label_encoders[c] = lbl # data is ready to train clf = model_dispatcher.models[model] clf.fit(X_train.fillna(0), y_train) preds = clf.predict_proba(X_valid.fillna(0))[:, 1] print(metrics.roc_auc_score(y_valid, preds)) joblib.dump(label_encoders, f"{config.MODEL_OUTPUT}/{model}_{fold}_label_encoder.pkl") joblib.dump(clf, f"{config.MODEL_OUTPUT}/{model}_{fold}.pkl") joblib.dump(X_train.columns, f"{config.MODEL_OUTPUT}/{model}_{fold}_columns.pkl") if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument( "--fold", type=int ) parser.add_argument( "--model", type=str ) args = parser.parse_args() pipe( fold=args.fold, model=args.model ) 我希望你能读懂代码,但如果看不明白的话,我来总结一下这段代码所发生的的事情:将训练数据设置为列kfold中的值,并且与我们通过的 fold 相同的值就是测试集。然后,我们对分类变量进行标签编码,并用 0 填充所有缺失值,最后将数据训练到逻辑回归模型上。 我们得到当前的 fold 的预测,并打印出 ROC_AUC。 注:从目前的情况看,代码本身并不会运行,因此我们必须在运行每个 Fold 时,传递 fold 和 model 的值。 让我们看看逻辑回归模型的输出。 ### Logistic Regression # Fold 0 ROC_AUC_SCORE: 0.7446056326560758 # Fold 1 ROC_AUC_SCORE: 0.7476247589462117 # Fold 2 ROC_AUC_SCORE: 0.7395710927094167 # Fold 3 ROC_AUC_SCORE: 0.7365641912867861 # Fold 4 ROC_AUC_SCORE: 0.7115696956435416 这些都是相当不错的结果,但让我们使用更强大的随机森林模型,看看是否还可以改善。 ### Random Forest # Fold 0 ROC_AUC_SCORE: 0.9280242455299264 # Fold 1 ROC_AUC_SCORE: 0.9281600723876517 # Fold 2 ROC_AUC_SCORE: 0.9265254015330469 # Fold 3 ROC_AUC_SCORE: 0.9224746067992484 # Fold 4 ROC_AUC_SCORE: 0.9196977372298685 很明显,随机森林模型产生了更好的结果。让我们在 Kaggle 上进行后期提交,看看我们在排行榜上的位置。这是最重要的部分——要做到这一点,我们必须运行inference.py。 import os import pandas as pd import numpy as np import config import model_dispatcher from sklearn import preprocessing from sklearn import metrics import joblib def predict(test_data_path:str , model_name:str, model_path:str): df = pd.read_csv(test_data_path) test_idx = df["TransactionID"].values predictions = None for FOLD in range(5): df = pd.read_csv(test_data_path) encoders = joblib.load(os.path.join(model_path, f"{model_name}_{FOLD}_label_encoder.pkl")) cols = joblib.load(os.path.join(model_path, f"{model_name}_{FOLD}_columns.pkl")) for c in encoders: lbl = encoders[c] df.loc[:, c] = df.loc[:, c].astype(str).fillna("NONE") df.loc[:, c] = lbl.transform(df[c].values.tolist()) clf = joblib.load(os.path.join(model_path, f"{model_name}_{FOLD}.pkl")) df = df[cols] preds = clf.predict_proba(df.fillna(0))[:, 1] if FOLD == 0: predictions = preds else: predictions += preds predictions /= 5 sub = pd.DataFrame(np.column_stack((test_idx, predictions)), columns=["TransactionID", "isFraud"]) return sub if __name__ == "__main__": submission = predict(test_data_path=config.TEST_DATA, model_name="random_forest", model_path=f"{config.MODEL_OUTPUT}/") submission.loc[:, "TransactionID"] = submission.loc[:, "TransactionID"].astype(int) submission.to_csv(f"{config.DATA_DIR}/rf_submission.csv", index=False) 注:提交给 Kaggle 的过程并不在本文讨论的范畴,因此我将直接在排行榜上列出模型的得分以及它是如何做到的。 考虑到这个分数可以转换成 Kaggle 的私人排行榜(因为它是公共排行榜上的分数),我们在 Kaggle 的私人排行榜上排名为 3875/6351(前 61%)。虽然从 Kaggle 的角度来看,这个得分看起来并不咋样,但在现实世界的场景中,我们可能会根据任务的情况来解决这个分数。 但是,这个项目的目标并非提出最好的模型,而是创建我们自己的 API,我们将在后面的文章中讨论这个问题。 为了构建快速迭代的快速管道,我们拥有的代码是可以的,但是如果我们想部署这个模型的话,就必须做大量的清理工作,这样我们才能遵循 软件工程最佳实践。 总 结 在现实世界中,欺诈检测是一个非常普遍且具有挑战性的问题,提高正确率对于防止在顾客在商店进行真正的交易时信用卡被拒的尴尬非常重要。我们已经构建了一种非常简单的方法,使用分类变量的标签编码,用 0 填充所有缺失值,并使用随机森林,没有任何调整或方法来处理数据的不平衡性,但我们的模型仍然得到了很高的分数。为了改进模型,我们可能要先从随机森林模型中寻找重要的特征,放弃不那么重要的特征,或者我们可以使用其他更为强大的模型,比如 Light Gradient Boosting Machine 和神经网络。 注:在编写这个脚本时,模块并不是最好的,但它的格式允许我进行快速迭代。在以后的工作中,我计划将这个模型作为 API 部署到云服务器上。 作者介绍: Kurtis Pykes,痴迷于数据科学、人工智能和商业技术应用。 原文链接: https://towardsdatascience.com/using-machine-learning-to-detect-fraud-f204910389cf 你也「在看」吗??? 阅读原文

上一篇:2018-12-06_深入理解Kafka Connect:转换器和序列化 下一篇:2021-08-16_「转」BERT模型为什么这么强 | 文末赠书

TAG标签:

17
网站开发网络凭借多年的网站建设经验,坚持以“帮助中小企业实现网络营销化”为宗旨,累计为4000多家客户提供品质建站服务,得到了客户的一致好评。如果您有网站建设网站改版域名注册主机空间手机网站建设网站备案等方面的需求...
请立即点击咨询我们或拨打咨询热线:13245491521 13245491521 ,我们会详细为你一一解答你心中的疑难。
项目经理在线

相关阅读 更多>>

猜您喜欢更多>>

我们已经准备好了,你呢?
2022我们与您携手共赢,为您的企业营销保驾护航!

不达标就退款

高性价比建站

免费网站代备案

1对1原创设计服务

7×24小时售后支持

 

全国免费咨询:

13245491521

业务咨询:13245491521 / 13245491521

节假值班:13245491521()

联系地址:

Copyright © 2019-2025      ICP备案:沪ICP备19027192号-6 法律顾问:律师XXX支持

在线
客服

技术在线服务时间:9:00-20:00

在网站开发,您对接的直接是技术员,而非客服传话!

电话
咨询

13245491521
7*24小时客服热线

13245491521
项目经理手机

微信
咨询

加微信获取报价