当前位置:   article > 正文

机器学习预测实战 -- 信用卡交易欺诈数据监测(含方案和代码思路)

机器学习预测实战 -- 信用卡交易欺诈数据监测(含方案和代码思路)

目录

项目背景

目标

方案一:下采样的方法训练模型

获取数据

数据预处理

检查是否有缺失值:

查看数据类型:

查看数据分布 

方案二:smote(过采样)处理数据不平衡数据

获取数据

数据预处理

 检查是否有缺失值:

查看数据类型:

 不平衡数据处理

方法一:直接使用smote

 方法二:利用SMOTE+undersampling解决数据不平衡

分割数据集:

方法1的数据集

方法2的数据集

模型训练

准备好算法API

交叉验证的函数 

模型调优

网格搜索模型调优

计算各个指标:

集成算法

保存模型:


项目背景

一批交易数据,数据总量28万,其中正常交易数据量占比99.83%,欺诈交易数据量仅占比0.17%。

目标

训练出一个模型,能判断出交易数据是正常数据还是欺诈数据

方案一:下采样的方法训练模型

获取数据

  1. import pandas as pd
  2. import numpy as np
  3. import seaborn as sns
  4. import matplotlib.pyplot as plt
  5. import time
  6. import warnings
  7. warnings.filterwarnings('ignore')
  8. # 加载数据文件
  9. df = pd.read_csv("creditcard.csv")
  10. # 查看数据内容
  11. df.head()

上图可以看到,数据除了Amount外,都经过了标准化处理

数据预处理

检查是否有缺失值

  1. # 检查是否有空置
  2. df.isnull().sum()

 没有缺失值的情况

查看数据类型:

  1. # 查看数据类型
  2. df.dtypes

查看数据分布 

  1. # 查看Class分布
  2. labels = ['Not Fraud', 'Fraud'] # 标签
  3. size = df['Class'].value_counts() # 统计class的类别数量
  4. colors = ['lightgreen', 'orange'] # 颜色
  5. explode = [0, 0.1] # 饼图突出
  6. plt.figure(figsize=(9,9)) # 画布大小
  7. plt.pie(size, colors=colors, explode=explode, labels=labels, shadow=True, autopct='%.2f%%') # 饼图参数设置
  8. plt.axis('off') # 关闭坐标轴
  9. plt.title("Data Distribution") # 标题
  10. plt.legend() # 显示标签
  11. plt.show() # 显示

这里可以看到欺诈数据占比非常小,如果使用下采样的方法训练模型,有非常大的概率出现过拟合的现象,导致模型泛化能力差,这时候第一个方案可以停下。

方案二:smote(过采样)处理数据不平衡数据

如果不处理不平衡数据,用这些数据来训练,模型往往只会学到分辨样本多的类别,而少数类别因为学习的数据量过少,无法准确预测。

获取数据

  1. import pandas as pd
  2. import numpy as np
  3. import seaborn as sns
  4. import matplotlib.pyplot as plt
  5. import time
  6. import warnings
  7. warnings.filterwarnings('ignore')
  8. # 加载数据文件
  9. df = pd.read_csv("creditcard.csv")
  10. # 查看数据内容
  11. df.head()

上图可以看到,数据除了Amount外,都经过了标准化处理

数据预处理

对Amount进行标准化处理

  1. from sklearn.preprocessing import StandardScaler
  2. df['scaled_amount'] = StandardScaler().fit_transform(df['Amount'].values.reshape(-1,1)) # 金额归一化
  3. df['scaled_time'] = StandardScaler().fit_transform(df['Time'].values.reshape(-1,1)) # 时间归一化
  4. df.drop(['Amount', 'Time'], axis=1, inplace=True) # 删除原始的数据列

 检查是否有缺失值:

  1. # 检查是否有空置
  2. df.isnull().sum()

 没有缺失值的情况

查看数据类型:

  1. # 查看数据类型
  2. df.dtypes

 不平衡数据处理

这里我们提出一个想法,不管是对数据进行过采样还是欠采样,都是去平衡两类数据,那么我们可以尝试在用单纯的smote的同时,再创建一组数据集,对少数样本过采样,多数样本下采样,分别训练,查看效果。

方法一:直接使用smote

  1. from imblearn.over_sampling import SMOTE
  2. X_new_1, y_new_1 = SMOTE().fit_resample(X, y)
  3. # 新的类分布
  4. y_new_1.value_counts()

 方法二:利用SMOTE+undersampling解决数据不平衡

  1. from imblearn.over_sampling import SMOTE
  2. from imblearn.under_sampling import RandomUnderSampler
  3. from imblearn.pipeline import Pipeline # 管道,把要用的工具封装在一起
  4. # over
  5. over = SMOTE(sampling_strategy=0.1)
  6. # under
  7. under = RandomUnderSampler(sampling_strategy=0.5)
  8. # pipeline
  9. steps = [('o', over),('u', under)]
  10. pipeline = Pipeline(steps=steps)
  11. X_new_2, y_new_2 = pipeline.fit_resample(X, y)
  12. # 新的类分布
  13. y_new_2.value_counts()

分割数据集:

方法1的数据集

  1. from sklearn.model_selection import train_test_split
  2. X_new_1_train, X_new_1_test, y_new_1_train, y_new_1_test = train_test_split(X_new_1, y_new_1)
  3. # 数据集
  4. X_new_1_train = X_new_1_train.values
  5. X_new_1_test = X_new_1_test.values
  6. # 标签
  7. y_new_1_train = y_new_1_train.values
  8. y_new_1_test = y_new_1_test.values

方法2的数据集

  1. X_new_2_train, X_new_2_test, y_new_2_train, y_new_2_test = train_test_split(X_new_2, y_new_2)
  2. # 数据集
  3. X_new_2_train = X_new_2_train.values
  4. X_new_2_test = X_new_2_test.values
  5. # 标签
  6. y_new_2_train = y_new_2_train.values
  7. y_new_2_test = y_new_2_test.values

模型训练

因为我们处理的是一个二分类问题,这里选择的二分类中表现较好的逻辑回归,还有强大的SVM,以及各种集成算法来训练模型。利用交叉验证和网格搜索,从中选择出最优的模型和最优的参数,

准备好算法API

  1. # 简单分类器实现
  2. from sklearn.linear_model import LogisticRegression # 逻辑回归
  3. from sklearn.linear_model import SGDClassifier # 随机梯度
  4. from sklearn.svm import SVC # 支撑向量机
  5. from sklearn.ensemble import RandomForestClassifier # 随机森林
  6. from sklearn.model_selection import cross_val_score # 交叉验证计算accuracy
  7. from sklearn.model_selection import GridSearchCV # 网格搜索,获取最优参数
  8. from sklearn.model_selection import StratifiedKFold # 交叉验证
  9. from collections import Counter
  10. # 评估指标
  11. from sklearn.metrics import confusion_matrix, precision_score, recall_score, f1_score, roc_auc_score, accuracy_score, classification_report
  12. from sklearn.ensemble import BaggingClassifier, GradientBoostingClassifier # 集成学习
  13. from xgboost import XGBClassifier # 极限梯度提升树
  14. classifiers = {
  15. 'LogisticRegression':LogisticRegression(), # 逻辑回归
  16. # "SVC":SVC(), # 支撑向量机
  17. 'RFC':RandomForestClassifier(), # 随机森林
  18. 'Bagging':BaggingClassifier(), # 集成学习bagging
  19. 'SGD':SGDClassifier(), # 随机梯度
  20. 'GBC':GradientBoostingClassifier(), # 集成学习Gradient
  21. 'xgb':XGBClassifier() # 极限梯度提升树
  22. }

交叉验证的函数 

  1. def accuracy_score(X_train, y_train):
  2. for key, classifier in classifiers.items(): # 遍历每一个分类器,分别训练、计算得分
  3. classifier.fit(X_train, y_train)
  4. training_score = cross_val_score(classifier, X_train, y_train, cv=5) # 5折交叉验证
  5. print("Classifier Name : ", classifier.__class__.__name__," Training Score :", round(training_score.mean(), 2)*100,'%')

结果1

  1. # 1.1 SMOTE
  2. accuracy_score(X_new_1_train, y_new_1_train)

这里SVM算法也会消耗大量的时间,这里我把它pass掉了

 结果2

  1. # 1.2 SMOTE + under sampling
  2. accuracy_score(X_new_2_train, y_new_2_train)

 这里两种方法的结果都还不错,继续往下调优,然后我们可以看到的是,一些集成算法出现过拟合的现象,所以我们调优方向可以往降低模型复杂度这边走

模型调优

网格搜索模型调优

  1. # 网格搜索:获取最优超参数
  2. # 1 LR
  3. def LR_gs(X_train, y_train):
  4. # LR
  5. LR_param = {
  6. 'penalty':['l1', 'l2'],
  7. 'C':[0.001, 0.01, 0.1, 1, 10]
  8. }
  9. LR_gs = GridSearchCV(LogisticRegression(),param_grid=LR_param, n_jobs=-1, scoring='accuracy')
  10. LR_gs.fit(X_train, y_train)
  11. LR_estimators = LR_gs.best_estimator_ # 最优参数
  12. return LR_estimators
  13. # 2 RFC
  14. def RFC_gs(X_train, y_train):
  15. RFC_param = {
  16. 'n_estimators':[100, 150, 200], # 多少棵树
  17. 'criterion':['gini', 'entropy'], # 衡量标准
  18. 'max_depth':list(range(2,5,1)), # 树的深度
  19. }
  20. RFC_gs = GridSearchCV(RandomForestClassifier(), param_grid=RFC_param, n_jobs=-1, scoring='accuracy')
  21. RFC_gs.fit(X_train, y_train)
  22. RFC_estimators = RFC_gs.best_estimator_
  23. return RFC_estimators
  24. # 3 Bag
  25. def BAG_gs(X_train, y_train):
  26. BAG_param = {
  27. 'n_estimators':[10, 15, 20]
  28. }
  29. BAG_gs = GridSearchCV(BaggingClassifier(), param_grid=BAG_param, n_jobs=-1, scoring='accuracy')
  30. BAG_gs.fit(X_train, y_train)
  31. BAG_estimators = BAG_gs.best_estimator_
  32. return BAG_estimators
  33. # 4 SGD
  34. def SGD_gs(X_train, y_train):
  35. SGD_param = {
  36. 'penalty':['l2','l1'],
  37. 'max_iter':[1000, 1500, 2000]
  38. }
  39. SGD_gs = GridSearchCV(SGDClassifier(), param_grid=SGD_param, n_jobs=-1, scoring='accuracy')
  40. SGD_gs.fit(X_train, y_train)
  41. SGD_estimators = SGD_gs.best_estimator_
  42. return SGD_estimators
  43. # 5 xgb
  44. def XGB_gs(X_train, y_train):
  45. XGB_param = {
  46. 'n_estimators':[60,80,100,200],
  47. 'max_depth':[3,4,5,6],
  48. 'learning_rate':[0.1,0.2,0.3,0.4]
  49. }
  50. XGB_gs = GridSearchCV(XGBClassifier(), param_grid=XGB_param, n_jobs=-1, scoring='accuracy')
  51. XGB_gs.fit(X_train, y_train)
  52. XGB_estimators = XGB_gs.best_estimator_
  53. return XGB_estimators

调用上面的函数:

  1. # 采用新的数据集:X_new_1_train, y_new_1_train
  2. # 模型交叉验证、训练,获取最优超参数
  3. LR_best_estimator = LR_gs(X_new_1_train, y_new_1_train)
  4. # KNN_best_estimator = KNN_gs(X_new_1_train, y_new_1_train)
  5. # SVC_best_estimator = SVC_gs(X_new_1_train, y_new_1_train)
  6. # DT_best_estimator = DT_gs(X_new_1_train, y_new_1_train)
  7. RFC_best_estimator = RFC_gs(X_new_1_train, y_new_1_train)
  8. BAG_best_estimator = BAG_gs(X_new_1_train, y_new_1_train)
  9. SGD_best_estimator = SGD_gs(X_new_1_train, y_new_1_train)
  10. XGB_best_estimator = XGB_gs(X_new_1_train, y_new_1_train)

注:这一步在我电脑计算了三个多小时

  1. # 采用新的数据集:X_new_2_train, y_new_2_train
  2. # 模型交叉验证、训练,获取最优超参数
  3. LR_best_estimator = LR_gs(X_new_2_train, y_new_2_train)
  4. # KNN_best_estimator = KNN_gs(X_new_2_train, y_new_2_train)
  5. # SVC_best_estimator = SVC_gs(X_new_2_train, y_new_2_train)
  6. # DT_best_estimator = DT_gs(X_new_2_train, y_new_2_train)
  7. RFC_best_estimator = RFC_gs(X_new_2_train, y_new_2_train)
  8. BAG_best_estimator = BAG_gs(X_new_2_train, y_new_2_train)
  9. SGD_best_estimator = SGD_gs(X_new_2_train, y_new_2_train)
  10. XGB_best_estimator = XGB_gs(X_new_2_train, y_new_2_train)

等以上步骤都计算完成,我们就得到了网格搜索找出的最优超参数,利用得到的最优超参数,去计算准确率,精准率,召回率,f1_score,auc面积。

计算各个指标:

(这个模型我们主要是为了检测异常数据,也就是找到少数类,所以我们更看重数据查的全不全,也就是召回率和AUC指标)

  1. # 预测新的数据集:X_new_test, y_new_test
  2. from sklearn.metrics import precision_recall_fscore_support
  3. from sklearn.metrics import accuracy_score
  4. result_df = pd.DataFrame(columns=['Accuracy', 'F1-score', 'Recall', 'Precision', 'AUC_ROC'],
  5. index=['LR','RFC','Bagging','SGD','XGB'])
  6. def caculate(models, X_test, y_test):
  7. # 计算各种参数的值
  8. accuracy_results = []
  9. F1_score_results = []
  10. Recall_results = []
  11. Precision_results = []
  12. AUC_ROC_results = []
  13. for model in models:
  14. y_pred = model.predict(X_test)
  15. accuracy = accuracy_score(y_test, y_pred) # 计算准确度
  16. precision, recall, f1_score, _ = precision_recall_fscore_support(y_test, y_pred) # 计算:精确度,召回率,f1_score
  17. AUC_ROC = roc_auc_score(y_test, y_pred) # 计算ROC, AUC
  18. # 保存计算值
  19. accuracy_results.append(accuracy)
  20. F1_score_results.append(f1_score)
  21. Recall_results.append(recall)
  22. AUC_ROC_results.append(AUC_ROC)
  23. Precision_results.append(precision)
  24. return accuracy_results, F1_score_results, Recall_results, AUC_ROC_results, Precision_results

带入数据1

  1. # 将所有最优超参数的模型放在一起
  2. best_models = [LR_best_estimator, RFC_best_estimator,
  3. BAG_best_estimator, SGD_best_estimator, XGB_best_estimator]
  4. # 调用函数计算各项指标值
  5. accuracy_results, F1_score_results, Recall_results, AUC_ROC_results, Precision_results = caculate(best_models, X_new_1_test, y_new_1_test)
  6. # 将各项值放入到DataFrame中
  7. result_df['Accuracy'] = accuracy_results
  8. result_df['F1-score'] = F1_score_results
  9. result_df['Recall'] = Recall_results
  10. result_df['Precision'] = Precision_results
  11. result_df['AUC_ROC'] = AUC_ROC_results
  12. result_df # 显示计算结果

可视化:

  1. # 可视化 AUC的评分
  2. g = sns.barplot('AUC_ROC', result_df.index, data=result_df, palette='hsv', orient='h')

 

带入第二组数据:

  1. result_df_2 = pd.DataFrame(columns=['Accuracy', 'F1-score', 'Recall', 'Precision', 'AUC_ROC'],
  2. index=['LR','RFC','Bagging','SGD','XGB'])
  3. # 将所有最优超参数的模型放在一起
  4. best_models = [LR_best_estimator, RFC_best_estimator,
  5. BAG_best_estimator, SGD_best_estimator, XGB_best_estimator]
  6. # 调用函数计算各项指标值
  7. accuracy_results, F1_score_results, Recall_results, AUC_ROC_results, Precision_results = caculate(best_models, X_new_2_test, y_new_2_test)
  8. # 将各项值放入到DataFrame中
  9. result_df_2['Accuracy'] = accuracy_results
  10. result_df_2['F1-score'] = F1_score_results
  11. result_df_2['Recall'] = Recall_results
  12. result_df_2['Precision'] = Precision_results
  13. result_df_2['AUC_ROC'] = AUC_ROC_results
  14. result_df_2

 

可视化:

  1. # 可视化 AUC的评分
  2. g = sns.barplot('AUC_ROC', result_df_2.index, data=result_df_2, palette='hsv', orient='h')

       看到auc面积这里,第二组数据的结果会略微高于第一组数据,这时候我们后续可以只使用第二组数据。

到这里我们可以看到,Bagging和XGBoost都有较好的表现效果,我们选出这两个算法,对它们进行一个集成,集成为一个算法,看看能不能得到更优的效果。

集成算法

  1. # 集成学习
  2. # 根据以上AUC的结果,选择: LR 和 SVC 和 XGB 当做基模型
  3. # KNN_test = pd.Series(KNN_best_estimator.predict(X_new_1_test), name = 'KNN')
  4. Bagging_test = pd.Series(BAG_best_estimator.predict(X_new_1_test),name = 'Bagging')
  5. XGB_test = pd.Series(XGB_best_estimator.predict(X_new_1_test), name='XGB')
  6. # 把以上3个模型的预测结果集成起来
  7. ensemble_results = pd.concat([Bagging_test, XGB_test], axis=1)
  8. ensemble_results

 

集成,训练:

  1. # 将上述3个模型集成起来,当做一个模型
  2. from sklearn.ensemble import VotingClassifier
  3. voting_clf = VotingClassifier(estimators=[('BAG', BAG_best_estimator),
  4. ('XGB', XGB_best_estimator)], n_jobs=-1)
  5. # 训练
  6. voting_clf.fit(X_new_1_train, y_new_1_train)
  7. # 预测
  8. y_final_pred = voting_clf.predict(X_new_1_test)
  9. # 评估结果 : 最终集成学习预测的结果明显高于之前各个模型单独预测的结果
  10. print(classification_report(y_new_1_test, y_final_pred))

 

可以看到我们最终集成的模型预测的结果明显高于单独预测的结果,然后我们把这个超级模型保存起来:

保存模型:

  1. import pickle
  2. pickle.dump(voting_clf,open('./bag_xgb.dat','wb'))

  后续也可以绘制一下ROC曲线,这里我觉得没必要了。over!

需要源码的话可以点个赞私信我

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/371929
推荐阅读
相关标签
  

闽ICP备14008679号