交易数据异常检测—机器学习实战

[python]  view plain  copy
  1.   
GitHub: https://github.com/yjfiejd/transaction_data_Anomaly_Detection (可下载资料)
[python]  view plain  copy
  1. # coding: utf-8  
  2.   
  3. # In[2]:  
  4.   
  5.   
  6. import pandas as pd  
  7. import matplotlib.pyplot as plt  
  8. import numpy as np  
  9. import os  
  10. get_ipython().run_line_magic('matplotlib''inline')  
  11.   
  12.   
  13. # In[3]:  
  14.   
  15.   
  16. os.chdir('/Users/a1/Downloads/百度云盘/机器学习算法配套案例实战/逻辑回归-信用卡欺诈检测')  
  17.   
  18.   
  19. # In[4]:  
  20.   
  21.   
  22. data = pd.read_csv("creditcard.csv")  
  23. data.head()  
  24.   
  25.   
  26. # In[5]:  
  27.   
  28.   
  29. #data.describe  
  30.   
  31.   
  32. # In[6]:  
  33.   
  34.   
  35. #看正负样本的比例,用value_counts来统计  
  36. count_class = pd.value_counts(data['Class']).sort_index() #默认按行标升序排列  
  37. #count_class.sort_index(ascending = False) 降序排列  
  38. count_class  
  39.   
  40.   
  41. # In[7]:  
  42.   
  43.   
  44. #查看count_class的类型, 这里取了pandas中dataFrame中的一列,所以为series格式  
  45. type(count_class)  
  46.   
  47.   
  48. # In[8]:  
  49.   
  50.   
  51. #用pandas画简单的图  
  52. count_class.plot(kind='bar')  
  53. plt.title('Fraud class histogram')  
  54. plt.xlabel('Class')  
  55. plt.ylabel('Frequency')  
  56.   
  57.   
  58. # ## 数据预处理  
  59. # ### 1)正常样本的个数 与 异常样本的个数如下图, 样本数据不均衡该怎么办?  
  60. #       
  61. #     #方法一:下采样 - 如上图减少0样本的个数,让它与1样本一样的少, 看看哪种更好?  
  62. #     #方法二:过采样 - 让1号样本变多,让它与0号样本一样的多  
  63.   
  64. # ### 2)某些特征数值太大,比如这里的normAmount,保证特征之间的分布差异差不多  
  65. #     #归一化  
  66. #     #标准化  
  67.   
  68. # In[9]:  
  69.   
  70.   
  71. #预处理  
  72. from sklearn.preprocessing import StandardScaler  
  73. #data中加上一列,把原来的Amount转换为新的特征  
  74. data['normAmount'] = StandardScaler().fit_transform(data['Amount'].values.reshape(-11)) #注意reshape python3.0的用法  
  75. #删除原来的没用的特征,用drop(['',''], axis = 1) 表示列  
  76. data = data.drop(['Time','Amount'], axis = 1)  
  77. data.head()  
  78.   
  79.   
  80. # ### 1.1下采样策略 : 使得0和1的样本一样少  
  81.   
  82. # In[10]:  
  83.   
  84.   
  85. # 构造特征数据,:表示选择所有的行,x列选择中不包含‘Class’这一列label, y列中只选择包含label这一列  
  86. X = data.iloc[:, data.columns != 'Class']  
  87. Y = data.iloc[:, data.columns == 'Class']  
  88.   
  89. #统计Class=1的样本有多少,然后在让0样本数量与1样本数量一致  
  90. number_records_fraud = len(data[data.Class == 1]) #统计异常样本个数  
  91. #取所有1样本(少)索引值,再把所有的索引值组成新的array  
  92. fraud_indices = np.array(data[data.Class == 1].index)   
  93. #取所有0样本(多)的索引值  
  94. normal_indices = np.array(data[data.Class == 0].index)  
  95. #从0样本中随机取,让取出的0样本的个数等于1样本个数; np.random.choice()用法:http://blog.csdn.net/autoliuweijie/article/details/51982514  
  96. random_normal_indices = np.random.choice(normal_indices, number_records_fraud, replace = False)  
  97. #随机取出来,取得里面值的index值  
  98. random_normal_indices = np.array(random_normal_indices)  
  99.   
  100. #组合拼接,把index都存着  
  101. under_sample_indices = np.concatenate([fraud_indices, random_normal_indices])  
  102.   
  103. #利用组合号的index,从data取出数据  
  104. under_sample_data = data.iloc[under_sample_indices,:] #取出需要的列,取出所有行  
  105.   
  106. #获得列新的数据集合  
  107. X_undersample = under_sample_data.iloc[:, under_sample_data.columns != 'Class']  
  108. Y_undersample = under_sample_data.iloc[:, under_sample_data.columns == 'Class']  
  109.   
  110. #打印新的数据集合,看下正样本与负样本均衡了么  
  111. print("Percentage of normal transction:", len(under_sample_data[under_sample_data.Class == 0])/len(under_sample_data))  
  112. print("Percentage of normal transction:", len(under_sample_data[under_sample_data.Class == 1])/len(under_sample_data))  
  113. print("Total number of new dataset", len(under_sample_data))  
  114. fraud_indices #返回的是所有1样本的索引  
  115.   
  116.   
  117. # ### 交叉验证  
  118. #     #先洗牌  
  119. #     #再切分  
  120.   
  121. # In[11]:  
  122.   
  123.   
  124. from sklearn.cross_validation import train_test_split  
  125.   
  126. #对整个原始数据集切分,查看如何使用train_test_split  
  127. #http://scikit-learn.org/stable/modules/generated/sklearn.cross_validation.train_test_split.html  
  128. X_train, X_test, y_train, y_test = train_test_split(X, Y, test_size = 0.3, random_state = 0)  
  129.   
  130. print("**********我是分割线**********")  
  131. print("Number transaction train dataset:", len(X_train))  
  132. print("Number transaction test dataset:", len(X_test))  
  133. print("Total number of transaction:", len(X_train)+len(X_test))  
  134.   
  135.   
  136. # #### 这里为什么对原始数据集也进行切分? → 后续测试model时使用  
  137. #     #回答:因为下采样数据集切分,只是为了得到合适的model,真正验证时候,需要把model放到原始的测试集中,因为下采样的测试集第一小,第二分部规则不一定与原始数据集合一样  
  138.   
  139. # In[13]:  
  140.   
  141.   
  142. #对下采样的后的数据集进行切分  
  143. X_train_undersample, X_test_undersample, y_train_undersample, y_test_undersample = train_test_split(X_undersample, Y_undersample, test_size = 0.3, random_state = 0)  
  144.   
  145. print("**********我是分割线**********")  
  146. print("Number transaction train dataset:", len(X_train_undersample))  
  147. print("Number transaction test dataset:", len(X_test_undersample))  
  148. print("Total number of transaction:", len(X_train_undersample) + len(X_test_undersample))  
  149.   
  150.   
  151. # ### 建模操作- 逻辑回归模型  
  152. #     #模型评估方法,不能仅仅依靠精度,特别是样本不均衡的情况下  
  153. #     #需要用recall来制定model的评估标准  
  154. #     #Recall = TP/TP+FN  (True positive/ True positive + False nagative)  
  155.   
  156. # In[14]:  
  157.   
  158.   
  159. #导入机器学习建模库,逻辑回归; 交叉验证(几份)&结果;混淆矩阵  
  160. from sklearn.linear_model import LogisticRegression  
  161. from sklearn.cross_validation import KFold, cross_val_score  
  162. from sklearn.metrics import confusion_matrix, recall_score, classification_report  
  163.   
  164.   
  165. # In[53]:  
  166.   
  167.   
  168. #切分完数据集后,进行交叉验证  
  169. def printing_Kfold_scores(x_train_data, y_train_data):  
  170.     fold = KFold(len(y_train_data), 5, shuffle=False)  
  171.       
  172.     #正则化惩罚项,参数: 希望model浮动小,泛化能力更强,更能避免过拟合A,B,model  
  173.     #L2正则化+1/2 w平方,看谁的loss小,惩罚力度可以用λ调节  
  174.     #L1正则化,加|w|绝对值  
  175.     c_param_range = [0.010.1110100#这个就是λ  
  176.       
  177.     #可视化展示  
  178.     results_table = pd.DataFrame(index = range(len(c_param_range), 2), columns = ['C_parameter''Mean recall score'])  
  179.     results_table['C_parameter'] = c_param_range  
  180.       
  181.     j = 0  
  182.     for c_param in c_param_range:  
  183.         print("---------------------------------")  
  184.         print('C parameter:', c_param)  
  185.         print("---------------------------------")  
  186.         print('')  
  187.           
  188.         recall_accs = []  
  189.         ## enumerate 转化为枚举值,iteration:枚举编号,indices:枚举值  
  190.         #http://blog.csdn.net/churximi/article/details/51648388  
  191.         for iteration, indices in enumerate(fold, start=1):#交叉验证,每次取不同的训练集,测试集  
  192.               
  193.             #选择逻辑回归模型, 实例化模型  
  194.             lr = LogisticRegression(C = c_param, penalty = 'l1'#传进参数λ,选则l1正则化,也可以选l2  
  195.               
  196.             #进行训练fit  
  197.             lr.fit(x_train_data.iloc[indices[0], :], y_train_data.iloc[indices[0],:].values.ravel())  
  198.               
  199.             #进行预测再train里面的validation测试集中  
  200.             y_pred_undersample = lr.predict(x_train_data.iloc[indices[1],:].values)  
  201.               
  202.             #计算召回率,recall  
  203.             recall_acc = recall_score(y_train_data.iloc[indices[1],:].values, y_pred_undersample)  
  204.             recall_accs.append(recall_acc)  
  205.             print('Iteration', iteration, ':recall score = ', recall_acc)  
  206.               
  207.             #recall的平均值  
  208.         results_table.loc[j, 'Mean recall score'] = np.mean(recall_accs)  
  209.         j += 1  
  210.         print('')  
  211.         print('mean recall score', np.mean(recall_accs))  
  212.         print('')  
  213.   
  214.     #best_c = results_table.loc[results_table['Mean recall score'].idxmax()]['C_parameter']  
  215.     best_c = results_table  
  216.     best_c.dtypes.eq(object) #因为best_c中的mean recall score 值的类型为‘object’,需要转换为'float',这里找出类型为‘object’的列名,返回index  
  217.     new = best_c.columns[best_c.dtypes.eq(object)] #利用返回的列名,找出那一列,pandas.columns,  
  218.     best_c[new] = best_c[new].apply(pd.to_numeric, errors = 'coerce', axis=0#对该列进行操作,把‘object’转换为‘float’类型  
  219.     best_c  
  220.     #通过idxmax()函数取得‘Mean recall score’中值最大的行号,通过行号找到这行,然后取这行列名为‘C_parameter’的值  
  221.     best_c = results_table.loc[results_table['Mean recall score'].idxmax()]['C_parameter']  
  222.   
  223.     #如何找到值最大时候的索引值  
  224.   
  225.     #选择最合适的C参数  
  226.     # Finally, we can check which C parameter is the best amongst the chosen.  
  227.     print('*********************************************************************************')  
  228.     print('Best model to choose from cross validation is with C parameter = ', best_c)  
  229.     print('*********************************************************************************')  
  230.       
  231.     #print (best_c.dtypes)  
  232.     #print(best_c.dtypes.eq(object))  
  233.     print(new)  
  234.     #print(best_c.dtypes)  
  235.       
  236.     return best_c  
  237.   
  238.   
  239. # In[54]:  
  240.   
  241.   
  242. best_c = printing_Kfold_scores(X_train_undersample, y_train_undersample)  
  243.   
  244.   
  245. # ### 混淆矩阵  
  246. #     #里面有预测值与真实值可以求一些指标, Recall值TP/TP+FN,精度值TP+FN/TP+FN+TN+FP  
  247. #     #在下采样中,recall值可以满足要求,但是当模型用在整体数据集中容易误杀太多,精度会降低,那么如何解决呢?  
  248. #     #要不要试一试 过采样?  
  249. #     #如果我啥都不用,用原始的数据,那模型效果怎样呢?  
  250.   
  251. # In[55]:  
  252.   
  253.   
  254. #混淆矩阵  
  255. #http://scikit-learn.org/stable/auto_examples/model_selection/plot_confusion_matrix.html 官方画图实例  
  256. def plot_confusion_matrix(cm, classes,  
  257.                           title='Confusion matrix',  
  258.                           cmap=plt.cm.Blues):  
  259.     """ 
  260.     This function prints and plots the confusion matrix. 
  261.     """  
  262.     plt.imshow(cm, interpolation='nearest', cmap=cmap)  
  263.     plt.title(title)  
  264.     plt.colorbar()  
  265.     tick_marks = np.arange(len(classes))  
  266.     plt.xticks(tick_marks, classes, rotation=0)  
  267.     plt.yticks(tick_marks, classes)  
  268.   
  269.     thresh = cm.max() / 2.  
  270.     for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])):  
  271.         plt.text(j, i, cm[i, j],  
  272.                  horizontalalignment="center",  
  273.                  color="white" if cm[i, j] > thresh else "black")  
  274.   
  275.     plt.tight_layout()  
  276.     plt.ylabel('True label')  
  277.     plt.xlabel('Predicted label')  
  278.   
  279.   
  280. # In[56]:  
  281.   
  282.   
  283. import itertools  
  284. lr = LogisticRegression(C = best_c, penalty = 'l1')  
  285. lr.fit(X_train_undersample,y_train_undersample.values.ravel())  
  286. y_pred_undersample = lr.predict(X_test_undersample.values)  
  287.   
  288. # Compute confusion matrix  
  289. cnf_matrix = confusion_matrix(y_test_undersample,y_pred_undersample)  
  290. np.set_printoptions(precision=2)  
  291.   
  292. print("Recall metric in the testing dataset: ", cnf_matrix[1,1]/(cnf_matrix[1,0]+cnf_matrix[1,1]))  
  293.   
  294. # Plot non-normalized confusion matrix  
  295. class_names = [0,1]  
  296. plt.figure()  
  297. plot_confusion_matrix(cnf_matrix  
  298.                       , classes=class_names  
  299.                       , title='Confusion matrix')  
  300. plt.show()  
  301.   
  302.   
  303. # In[57]:  
  304.   
  305.   
  306. lr = LogisticRegression(C = best_c, penalty = 'l1')  
  307. lr.fit(X_train_undersample,y_train_undersample.values.ravel())  
  308. y_pred = lr.predict(X_test.values)  
  309.   
  310. # Compute confusion matrix  
  311. cnf_matrix = confusion_matrix(y_test,y_pred)  
  312. np.set_printoptions(precision=2)  
  313.   
  314. print("Recall metric in the testing dataset: ", cnf_matrix[1,1]/(cnf_matrix[1,0]+cnf_matrix[1,1]))  
  315.   
  316. # Plot non-normalized confusion matrix  
  317. class_names = [0,1]  
  318. plt.figure()  
  319. plot_confusion_matrix(cnf_matrix  
  320.                       , classes=class_names  
  321.                       , title='Confusion matrix')  
  322. plt.show()  
  323.   
  324.   
  325. # In[58]:  
  326.   
  327.   
  328. best_c = printing_Kfold_scores(X_train,y_train)  
  329.   
  330.   
  331. # In[59]:  
  332.   
  333.   
  334. lr = LogisticRegression(C = 0.01, penalty = 'l1')  
  335. lr.fit(X_train_undersample,y_train_undersample.values.ravel())  
  336. y_pred_undersample_proba = lr.predict_proba(X_test_undersample.values)  
  337.   
  338. thresholds = [0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9]  
  339.   
  340. plt.figure(figsize=(10,10))  
  341.   
  342. j = 1  
  343. for i in thresholds:  
  344.     y_test_predictions_high_recall = y_pred_undersample_proba[:,1] > i  
  345.       
  346.     plt.subplot(3,3,j)  
  347.     j += 1  
  348.       
  349.     # Compute confusion matrix  
  350.     cnf_matrix = confusion_matrix(y_test_undersample,y_test_predictions_high_recall)  
  351.     np.set_printoptions(precision=2)  
  352.   
  353.     print("Recall metric in the testing dataset: ", cnf_matrix[1,1]/(cnf_matrix[1,0]+cnf_matrix[1,1]))  
  354.   
  355.     # Plot non-normalized confusion matrix  
  356.     class_names = [0,1]  
  357.     plot_confusion_matrix(cnf_matrix  
  358.                           , classes=class_names  
  359.                           , title='Threshold >= %s'%i)   
  360.   
  361.   
  362. # In[60]:  
  363.   
  364.   
  365. import pandas as pd  
  366. from imblearn.over_sampling import SMOTE  
  367. from sklearn.ensemble import RandomForestClassifier  
  368. from sklearn.metrics import confusion_matrix  
  369. from sklearn.model_selection import train_test_split  
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值