信用卡欺诈检测--Logistic回归算法应用

主要内容

1 数据分析和数据处理

2 数据均衡处理

  • 2.1 方案一:Undersample
  • 2.2 方案二:Oversample

3 问题记录

4 知识技能归纳


Part 1 数据分析和数据处理

此项目中数据量比较大,约有20多万条数据,需要利用python中的pandas库将数据导入,导入后数据格式为DataFrame,代码如下:

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
%matplotlib inline
#读取文件
data = pd.read_csv("creditcard.csv")
#初步查看数据的前五行
data.head()
图1-1
图1-2

代码运行之后,会展示出所有数据前五行,图1-1和图1-2分别截取数据的头尾部分,从图中可以看出,从Time列,V1-V28列,到最后两列Amount+Class, 数据集一共有31列,其中我们可以直接把time列删除,因为通常判断该条数据是否为信用卡欺诈和时间并没有关系,最后一列Class即判断此条数据是否为欺诈,class=1表示信用卡欺诈,class=0表示非信用卡欺诈。此外通过观察V1-V23列可以明显看出V1-V23列对应的数值是在-1到1之间变化,然而Amount列中的值却从0到150之间波动,为了使得后续算法使用不同列时不会因为数值的大小而导致权重分配不均匀,需要对Amount列进行处理。在此可以引入sklearn.preprocessing中的StandardScaler函数把Amount列中数值转换为区间(-1,1),具体代码如下:

from sklearn.preprocessing import StandardScaler
#添加新列normAmount,通过Amount转化而来
data['normAmount'] = StandardScaler().fit_transform(data['Amount'].reshape(-1, 1))
#对Amount进行处理之后,可以考虑把数据集中的不相关列time和Amount删除
data = data.drop(['Time','Amount'],axis=1)
data.head()


处理完Amount列之后,再来看看class列中数值分布情况,代码如下:

#先通过Pandas中value_count对data中的class列中值计数并分类
count_classes = pd.value_counts(data['Class'], sort = True).sort_index()
#通过柱状图直观展现下class列中0,1的数量分布
count_classes.plot(kind = 'bar')
#使用matplotlib绘制标题
plt.title("Fraud class histogram")
#使用matplotlib绘制X轴标题
plt.xlabel("Class")
#使用matplotlib绘制Y轴标题
plt.ylabel("Frequency")
#下图明显表示class中的0,1数据的不平衡,接着我们需要重点考虑如何解决数据不平衡的问题
图1-3

图1-3呈现的结果让人很是吃惊,初一看class=1的数量好像是0,但是实际上class=1的数据一共有492条,相对class=0的20多万条数据,在图中放在一起比较几乎可以忽略了,根本看不出效果。

很明显的一个结论是,样本中的欺诈数据和非欺诈数据分布十分的不均匀,所以在训练模型之前,我们需要对数据进行预处理,以解决数据分布的不均衡。

Part 2 数据均衡处理

通常对数据集样本做均衡处理有两个方案,一种方案是oversample,即通过一定的算法规则,以原始的数据集为依据,创造新的数据集样本,另一种方案是undersample,此方案不需要创造新的数据集,只需要对原有的数据集进行筛选,然后组合成为分布均匀的数据样本,先来实践第二种方案--undersample

2.1 Undersample

应用undersample的时候,为了保证新的数据集中class=0和class=1的数量一致,首先确认原始数据集中class=1的数量是多少,然后在class=0的数据随机选择和class=1数量相同的数据,最后把两部分数据合在一起形成新的under_sample_indices。

#区分整体数据集中的训练数据和预测结果数据
X = data.iloc[:, data.columns != 'Class']
y = data.iloc[:, data.columns == 'Class']

查看下data数据集中Class列等于1的数量

number_records_fraud = len(data[data.Class == 1])

#把对应的Class列中等于1的索引转化成为np.array类型的数组
fraud_indices = np.array(data[data.Class == 1].index)

获取data数据集中判定为非欺诈即Class列为0的索引

normal_indices = data[data.Class == 0].index

在Class=0随机选择和Class=1相同数量的索引值并且转化为np.array

random_normal_indices = np.random.choice(normal_indices, number_records_fraud,
replace = False)
random_normal_indices = np.array(random_normal_indices)

把class=0和随机选择的class=1的数据集索引粘合在一起构成新数据集的索引

under_sample_indices = np.concatenate([fraud_indices,random_normal_indices])

使用粘合在一起的undersample数据集索引,组成新的Undersample数据集

under_sample_data = data.iloc[under_sample_indices,:]

#区分undersample数据集中的训练数据和结果数据
X_undersample = under_sample_data.iloc[:, under_sample_data.columns != ‘Class’]
y_undersample = under_sample_data.iloc[:, under_sample_data.columns == ‘Class’]

看下Class=0和Class=1在数据集中的比例和整体数据的大小

print("Percentage of normal transactions: ",
len(under_sample_data[under_sample_data.Class == 0])/len(under_sample_data))
print("Percentage of fraud transactions: ",
len(under_sample_data[under_sample_data.Class == 1])/len(under_sample_data))
print("Total number of transactions in resampled data: ",
len(under_sample_data))
输出结果:
Percentage of normal transactions: 0.5
Percentage of fraud transactions: 0.5
Total number of transactions in resampled data: 984

以上就完成了under_sample_data的组合,同时区分了X_undersample和y_undersample。

来看看新生成under_sample_data中class列数据分布情况

count_classes = pd.value_counts(y_undersample[“Class”], sort = True).sort_index()
#通过柱状图直观展现下class列中0,1的数量分布
count_classes.plot(kind = ‘bar’)
#使用matplotlib绘制标题
plt.title(“Fraud class histogram”)
#使用matplotlib绘制X轴标题
plt.xlabel(“Class”)
#使用matplotlib绘制Y轴标题
plt.ylabel(“Frequency”)
图2-1

从图中能看出,通过Undersample的方式,我们保证了class中0,1数值的均匀分布,但是总体数据样本相比原来的20多万条数据,目前只有984条,接着我们可以验证下通过降低数据集数量的方式对最终算法模型的训练效果是否有影响。

引入交叉验证把数据集划分为训练集和测试集

#导入交叉验证对训练集和测试集进行划分
from sklearn.cross_validation import train_test_split

划分原始数据集,其中测试数据占30%,训练数据占70%

X_train, X_test, y_train, y_test = train_test_split(X,y,test_size = 0.3,
random_state = 0)
#查看下划分好的训练集和测试集的数量
print("Number transactions train dataset: ", len(X_train))
print("Number transactions test dataset: ", len(X_test))
print("Total number of transactions: ", len(X_train)+len(X_test))

使用同样的方法对新构造的undersample数据集进行划分

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)

print("")
print("Number transactions train dataset: ", len(X_train_undersample))
print("Number transactions test dataset: ", len(X_test_undersample))
print("Total number of transactions: ",
len(X_train_undersample)+len(X_test_undersample))

输出结果:
Number transactions train dataset: 199364
Number transactions test dataset: 85443
Total number of transactions: 284807

Number transactions train dataset: 688
Number transactions test dataset: 296
Total number of transactions: 984

导入逻辑回归算法,使用交叉验证模型,另外由于此数据集的特点,即判断为欺诈(class=1)的数据占总体的数据的比例特别小,考虑引入recall_score的验证方式,计算算法模型最终预测出的有欺诈行为的数据个数占实际总的class=1的比例的方式来验证算法最终的效果。

Recall=TP/(TP+FN)

TP : True Positive表示算法预测出是欺诈信息并且原本标记的也是欺诈信息的数据

FN:False Negative表示算法预测为非欺诈信息但实际上就是欺诈信息的数据

#导入相关机器学习库
from sklearn.linear_model import LogisticRegression
from sklearn.cross_validation import KFold, cross_val_score
from sklearn.metrics import confusion_matrix,recall_score,classification_report

LogisticRegression中有一个非常重要的参数:惩罚项C,使用不同的惩罚项C,会导致最终的算法模型的偏差效果很大,接着需要定义一个函数,用来求解相对数据集的惩罚项C,代码实现如下:

#定义一个函数,找到最佳的惩罚参数
def printing_Kfold_scores(x_train_data,y_train_data):
#将训练集分成五部分,每部分包括两段,前一段为索引80%(indices[0]),
后一段为索引20%(indices[1]),而后进行轮换。
fold = KFold(len(y_train_data),5,shuffle=False)
# 构造需要进行测试的c_param_range参数
c_param_range = [0.01,0.1,1,10,100]
#创建一个5行两列的Dataframe表格,方便后续进行平均值计算
results_table = pd.DataFrame(index = range(len(c_param_range),2), 
                              columns = ['C_parameter','Mean recall score'])
results_table['C_parameter'] = c_param_range


for c_param in c_param_range:
    print('-------------------------------------------')
    print('C parameter: ', c_param)
    print('-------------------------------------------')
    print('')

    recall_accs = []
    “”“
    以下对fold使用的enumerate函数非常关键,一方面获取之前fold通过KFold划分之后的序列
    号iteration(设置从1开始的),另一方面获取的已经自动转化为array类型的indices,
    indices一共包括两部分,一份indices[0]是总数的80%,另一份indice[1],占总数的20%,
    一共划分为五份,其中每一份的indice[0]和indices[1]数据都不一样(交替轮换),由于
    kfold保证数据是交替轮换,实现在同样的C_parameter下不同数据进行五次验证而后取均值。
    ”“”
    for iteration, indices in enumerate(fold,start=1):

        # 使用逻辑回归算法,设置对应的C参数
        lr = LogisticRegression(C = c_param, penalty = 'l1')

        #使用训练集中的indice[0]的部分进行模型的训练,然后使用indices[1]的部分进验证
        lr.fit(x_train_data.iloc[indices[0],:],
                              y_train_data.iloc[indices[0],:].values.ravel())
        #把训练好的模型应用在测试集上
        y_pred_undersample =lr.predict(x_train_data.iloc[indices[1],:].values)

        
        recall_acc = recall_score
                  (y_train_data.iloc[indices[1],:].values,y_pred_undersample)
        #把准确率结果放进recall_accs中,方便后续计算平均值,最终放进results_table中
        recall_accs.append(recall_acc)
        print('Iteration ', iteration,': recall score = ', recall_acc)

    #计算当前C参数下recall的平均值,而后保存在results_table中
    results_table.ix[j,'Mean recall score'] = np.mean(recall_accs)
    j += 1
    print('')
    print('Mean recall score ', np.mean(recall_accs))
    print('')
#返回最好的C参数值
best_c = results_table.loc[results_table['Mean recall score'].idxmax()]['C_parameter']

print('*******************************************************************')
print('Best model to choose from cross validation is with C parameter = ',best_c)                                                                      
print('*******************************************************************')
return best_c</code></pre></div><p>定义好best_c计算函数之后,接着就是应用在之前切分好的训练集上进行模型的验证</p><p>#先来求解下Undersample训练集中的best_c</p><div class="highlight"><pre><code class="language-text">#调用函数printing_kfold_scores

best_c = printing_Kfold_scores(X_train_undersample,y_train_undersample)
输出结果:

C parameter: 0.01

Iteration 1 : recall score = 0.931506849315
Iteration 2 : recall score = 0.917808219178
Iteration 3 : recall score = 1.0
Iteration 4 : recall score = 0.959459459459
Iteration 5 : recall score = 0.954545454545

Mean recall score 0.9526639965


C parameter: 0.1

Iteration 1 : recall score = 0.849315068493
Iteration 2 : recall score = 0.86301369863
Iteration 3 : recall score = 0.932203389831
Iteration 4 : recall score = 0.945945945946
Iteration 5 : recall score = 0.909090909091

Mean recall score 0.899913802398


C parameter: 1

Iteration 1 : recall score = 0.86301369863
Iteration 2 : recall score = 0.890410958904
Iteration 3 : recall score = 0.983050847458
Iteration 4 : recall score = 0.932432432432
Iteration 5 : recall score = 0.909090909091

Mean recall score 0.915599769303


C parameter: 10

Iteration 1 : recall score = 0.86301369863
Iteration 2 : recall score = 0.890410958904
Iteration 3 : recall score = 0.983050847458
Iteration 4 : recall score = 0.932432432432
Iteration 5 : recall score = 0.924242424242

Mean recall score 0.918630072333


C parameter: 100

Iteration 1 : recall score = 0.86301369863
Iteration 2 : recall score = 0.890410958904
Iteration 3 : recall score = 0.983050847458
Iteration 4 : recall score = 0.932432432432
Iteration 5 : recall score = 0.924242424242

Mean recall score 0.918630072333


Best model to choose from cross validation is with C parameter = 0.01
********************************************************************************

通过以上方式得出最好的C参数之后,接着我们可以拿过来进行模型训练和预测。

#考虑最后模型的预测效果是通过混淆矩阵来实现的,先来定义混淆矩阵绘制函数

#用来绘制混淆矩阵的函数
def plot_confusion_matrix(cm, classes,
title=‘Confusion matrix’,
cmap=plt.cm.Blues):
#设置灰度图绘制参数
plt.imshow(cm, interpolation=‘nearest’, cmap=cmap)
#绘制标题
plt.title(title)
#绘制灰度条
plt.colorbar()
#设置tick_marks的值
tick_marks = np.arange(len(classes))
#设置X轴刻度
plt.xticks(tick_marks, classes,rotation=0)
#设置Y轴刻度
plt.yticks(tick_marks, classes)
thresh = cm.max() / 2.0
print("thresh:%s"%thresh)
#通过(j,i)定位到文字内容cm[i,j]
for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])):
    plt.text(j, i, cm[i, j],
             horizontalalignment="center",
             color="white" if cm[i, j] &gt; thresh else "black")
# 紧凑显示图片,居中显示
plt.tight_layout()
#绘制Y轴标题
plt.ylabel('True label')
#绘制X轴标题
plt.xlabel('Predicted label')</code></pre></div><p>以上所有的准备好之后,激动的时刻也来了,让我们看看undersample下模型的表现。</p><div class="highlight"><pre><code class="language-text">#itertool 创建高效迭代器的Python模块

import itertools
#引入之前通过训练集交叉验证得出的最佳C参数,然后初始化模型
lr = LogisticRegression(C = best_c, penalty = ‘l1’)
#使用模型对训练集进行训练,ravel()的作用是把二维矩阵转化成一维矩阵
lr.fit(X_train_undersample,y_train_undersample.values.ravel())
y_pred_undersample = lr.predict(X_test_undersample.values)

#计算出混淆矩阵
cnf_matrix = confusion_matrix(y_test_undersample,y_pred_undersample)
np.set_printoptions(precision=2)
#根据混淆矩阵计算recall值
print("Recall metric in the testing dataset: ", cnf_matrix[1,1]/(cnf_matrix[1,0]+cnf_matrix[1,1]))

#设置好参数后,调用函数展示混淆矩阵
class_names = [0,1]

画图之前首先设置figure对象,此函数相当于设置一块自定义大小的画布,使得后面的图形输出在

这块规定了大小的画布上,其中参数figsize设置画布大小,此处使用默认大小。
plt.figure()
plot_confusion_matrix(cnf_matrix
, classes=class_names
, title=‘Confusion matrix’)
plt.show()

图2-2

上图2-2展示模型对undersample测试集的预测混淆矩阵,大概的来理解下图中的数据,左上角129(True label = 0,Predicted label=0)表示模型预测和实际情况一样,是非欺诈信息,接着旁边的20(True label = 0,Predicted label=1)表示模型预测为欺诈,但实际上是非欺诈,左下角11(True label = 1,Predicted label=0)表示模型预测为非欺诈,但是实际上为欺诈信息,旁边136(True label = 1,Predicted label=1)表示模型预测和实际情况一致,均为欺诈信息。通过混淆矩阵也可以计算出recall值为0.92517(11/11+136),模型整体的recall值效果比较好。

#看看模型在原始数据集中的效果

#调用逻辑回归算法,同样使用undersample训练集训练模型,但是这次训练好的模型应用在之前全体的
数据集中的训练集上,比较下不同效果。
lr = LogisticRegression(C = best_c, penalty = ‘l1’)
lr.fit(X_train_undersample,y_train_undersample.values.ravel())
y_pred = lr.predict(X_test.values)

Compute confusion matrix

cnf_matrix = confusion_matrix(y_test,y_pred)
np.set_printoptions(precision=2)

print("Recall metric in the testing dataset: ", cnf_matrix[1,1]/
(cnf_matrix[1,0]+cnf_matrix[1,1]))

Plot non-normalized confusion matrix

class_names = [0,1]
plt.figure()
plot_confusion_matrix(cnf_matrix
, classes=class_names
, title=‘Confusion matrix’)
plt.show()
图2-3

从上图2-3可以看出,在总体数量小的数据集上训练出的模型应用在数据量大的数据上,recall的值不会有很大的偏差,但是实际为非欺诈数据而被预测成为欺诈数据的数据量占对应数据的比例还是偏高的,在这里有一共10336条数据预测错误。

前面的best_c是根据undersample数据训练出来的,在此我们可以尝试在原始数据集上训练出对应的best_c,看下对应recall值。

best_c = printing_Kfold_scores(X_train,y_train)
输出结果:

C parameter: 0.01

Iteration 1 : recall score = 0.492537313433
Iteration 2 : recall score = 0.602739726027
Iteration 3 : recall score = 0.683333333333
Iteration 4 : recall score = 0.569230769231
Iteration 5 : recall score = 0.45

Mean recall score 0.559568228405


C parameter: 0.1

Iteration 1 : recall score = 0.567164179104
Iteration 2 : recall score = 0.616438356164
Iteration 3 : recall score = 0.683333333333
Iteration 4 : recall score = 0.584615384615
Iteration 5 : recall score = 0.525

Mean recall score 0.595310250644


C parameter: 1

Iteration 1 : recall score = 0.55223880597
Iteration 2 : recall score = 0.616438356164
Iteration 3 : recall score = 0.716666666667
Iteration 4 : recall score = 0.615384615385
Iteration 5 : recall score = 0.5625

Mean recall score 0.612645688837


C parameter: 10

Iteration 1 : recall score = 0.55223880597
Iteration 2 : recall score = 0.616438356164
Iteration 3 : recall score = 0.733333333333
Iteration 4 : recall score = 0.615384615385
Iteration 5 : recall score = 0.575

Mean recall score 0.61847902217


C parameter: 100

Iteration 1 : recall score = 0.55223880597
Iteration 2 : recall score = 0.616438356164
Iteration 3 : recall score = 0.733333333333
Iteration 4 : recall score = 0.615384615385
Iteration 5 : recall score = 0.575

Mean recall score 0.61847902217


Best model to choose from cross validation is with C parameter = 10.0
*********************************************************************************

通过以上的计算,可以很明显的看出,由于原始集的数据严重不平衡,导致最后在计算recall值的效果很差。

#通过混淆矩阵来看下原始模型训练出的best_c值最后的效果

lr = LogisticRegression(C = best_c, penalty = ‘l1’)
lr.fit(X_train,y_train.values.ravel())
y_pred_undersample = lr.predict(X_test.values)

计算混淆矩阵

cnf_matrix = confusion_matrix(y_test,y_pred_undersample)
np.set_printoptions(precision=2)

print("Recall metric in the testing dataset: ",
cnf_matrix[1,1]/(cnf_matrix[1,0]+cnf_matrix[1,1]))

绘制混淆矩阵图表

class_names = [0,1]
plt.figure()
plot_confusion_matrix(cnf_matrix, classes=class_names, title=‘Confusion matrix’)
plt.show()

图2-4

通过原始数据训练出的best_c对应的recall值效果比较差,但是实际为非欺诈,判断为欺诈的的数量占比也小了很多。

在目前默认的算法配置下,当预测为0的概率小于0.5,也就是预测为1的概率大于0.5的时候,此预测的结果就是1,相反当当预测为0的概率大于0.5,也就是预测为1的概率小于0.5的时候,此预测的结果就是0,也就是这里默认设置的阈值是0.5,接下来我们可以改变默认阈值的设置,通过混淆矩阵来看下在不同的阈值下,最终的预测结果表现,代码如下:

#通过设置不同的阈值,来看下对应的混淆矩阵呈现。
lr = LogisticRegression(C = 0.01, penalty = ‘l1’)
lr.fit(X_train_undersample,y_train_undersample.values.ravel())
#利用predict_proba可以计算出判断为0,1分别对应的概率,默认情况下,如果0对应概率大于0.5,则
即可判断为0。
y_pred_undersample_proba = lr.predict_proba(X_test_undersample.values)
#设置不同的阈值,通过不同阈值查看对应的混淆矩阵
thresholds = [0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9]

画图之前首先设置figure对象,此函数相当于设置一块自定义大小的画布,使得后面的图形输出在这块

规定了大小的画布上,其中参数figsize设置画布大小
plt.figure(figsize=(10,10))
#设置子图起点,一共是3x3的图表,每张图对应一个thresholds。
j = 1
for i in thresholds:
y_test_predictions_high_recall = y_pred_undersample_proba[:,1] > i

plt.subplot(3,3,j)
j += 1

# Compute confusion matrix
cnf_matrix = confusion_matrix(y_test_undersample,
                                             y_test_predictions_high_recall)
np.set_printoptions(precision=2)

print("Recall metric in the testing dataset: ", 
                           cnf_matrix[1,1]/(cnf_matrix[1,0]+cnf_matrix[1,1]))

# Plot non-normalized confusion matrix
class_names = [0,1]
plot_confusion_matrix(cnf_matrix , classes=class_names, 
                                                  title='Threshold &gt;= %s'%i) </code></pre></div><figure data-size="normal"><noscript><img src="https://pic2.zhimg.com/v2-57dc7e61de255feac8aa27baca0b274d_b.jpg" data-size="normal" data-rawwidth="712" data-rawheight="712" class="origin_image zh-lightbox-thumb" width="712" data-original="https://pic2.zhimg.com/v2-57dc7e61de255feac8aa27baca0b274d_r.jpg"/></noscript><img src="https://pic2.zhimg.com/80/v2-57dc7e61de255feac8aa27baca0b274d_hd.jpg" data-size="normal" data-rawwidth="712" data-rawheight="712" class="origin_image zh-lightbox-thumb lazy" width="712" data-original="https://pic2.zhimg.com/v2-57dc7e61de255feac8aa27baca0b274d_r.jpg" data-actualsrc="https://pic2.zhimg.com/v2-57dc7e61de255feac8aa27baca0b274d_b.jpg"><figcaption>图2-5</figcaption></figure><p>上图呈现的是不同阈值下的混合矩阵效果,结合可以具体的业务情况实际选择不同的threshold值。</p><p><i><b>2.2 Oversample</b></i></p><p>以上是undersample的解决方案,接着继续考虑oversample,也就是根据现有的数据创造新的数据集。</p><div class="highlight"><pre><code class="language-text">import pandas as pd

#导入此解决方案中重要的模块SMOTE用来生成oversample样本
from imblearn.over_sampling import SMOTE
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import confusion_matrix
from sklearn.model_selection import train_test_split

#读取数据,然后划分特征和结果集

credit_cards=pd.read_csv(‘creditcard.csv’)
#获取credit_cards表中列的名称
columns=credit_cards.columns
#删除最后一列,即class列
features_columns=columns.delete(len(columns)-1)
#获取除class列以外的所有特征列
features=credit_cards[features_columns]
#获取class列
labels=credit_cards[‘Class’]

#划分原始数据训练集和测试集用于oversample模型生成

features_train, features_test, labels_train, labels_test = train_test_split(features,
labels,
test_size=0.3,
random_state=0)

#利用SMOTE创造新的数据集

#初始化SMOTE 模型
oversampler=SMOTE(random_state=0)
#使用SMOTE模型,创造新的数据集
os_features,os_labels=oversampler.fit_sample(features_train,labels_train)
#切分新生成的数据集
os_features_train, os_features_test, os_labels_train, os_labels_test = train_test_split(os_features,
os_labels,
test_size=0.2,

#看看新构造的oversample数据集中0,1分布情况

os_count_classes = pd.value_counts(os_labels, sort = True).sort_index()
os_count_classes.plot(kind = ‘bar’)
plt.title(“Fraud class histogram”)
plt.xlabel(“Class”)
plt.ylabel(“Frequency”)
图2-6

从上图可以看出,现在生成的454908条数据集中,label中0,1的分布是均等的,从而有效的保证了数据的均衡分布。

#接着利用新的oversample数据集来计算惩罚项

os_features = pd.DataFrame(os_features)
os_labels = pd.DataFrame(os_labels)
best_c = printing_Kfold_scores(os_features,os_labels)
输出结果:

C parameter: 0.01

Iteration 1 : recall score = 0.890322580645
Iteration 2 : recall score = 0.894736842105
Iteration 3 : recall score = 0.968772822839
Iteration 4 : recall score = 0.957903298491
Iteration 5 : recall score = 0.958452863785

Mean recall score 0.934037681573


C parameter: 0.1

Iteration 1 : recall score = 0.890322580645
Iteration 2 : recall score = 0.894736842105
Iteration 3 : recall score = 0.970432665708
Iteration 4 : recall score = 0.958958463855
Iteration 5 : recall score = 0.960530220596

Mean recall score 0.934996154582


C parameter: 1

Iteration 1 : recall score = 0.890322580645
Iteration 2 : recall score = 0.894736842105
Iteration 3 : recall score = 0.970189222087
Iteration 4 : recall score = 0.958639715985
Iteration 5 : recall score = 0.960640133654

Mean recall score 0.934905698895


C parameter: 10

Iteration 1 : recall score = 0.890322580645
Iteration 2 : recall score = 0.894736842105
Iteration 3 : recall score = 0.970476928184
Iteration 4 : recall score = 0.959683890043
Iteration 5 : recall score = 0.960805003242

Mean recall score 0.935205048844


C parameter: 100

Iteration 1 : recall score = 0.890322580645
Iteration 2 : recall score = 0.894736842105
Iteration 3 : recall score = 0.970366271993
Iteration 4 : recall score = 0.960398324925
Iteration 5 : recall score = 0.96070608149

Mean recall score 0.935306020232


Best model to choose from cross validation is with C parameter = 100.0
*********************************************************************************

通过计算的出惩罚项c进行模型训练,然后利用混淆矩阵查看最终效果

os_features_train = pd.DataFrame(os_features_train)
os_labels_train = pd.DataFrame(os_labels_train)
#计算出best_c惩罚项之后
lr = LogisticRegression(C = best_c, penalty = ‘l1’)
lr.fit(os_features_train,os_labels_train.values.ravel())
y_pred = lr.predict(features_test.values)

计算混淆矩阵

cnf_matrix = confusion_matrix(labels_test,y_pred)
np.set_printoptions(precision=2)

print("Recall metric in the testing dataset: ", cnf_matrix[1,1]/(cnf_matrix[1,0]+cnf_matrix[1,1]))

绘制混淆矩阵图

class_names = [0,1]
plt.figure()
plot_confusion_matrix(cnf_matrix
, classes=class_names
, title=‘Confusion matrix’)
plt.show()

比较图2-7和之前的2-3可以发现,当使用oversample的方案时,recall值相对于没有发生太大的偏差,但是True label =0,Predicted label=1的数量明显减小了。

综上所述,在结合recall表现和误差值的数量,使用oversample的方案整体模型效果是比较好的。

Part 3 问题记录

  • oversample的方案中,在使用pip install imblearn 之后执行导入代码时提示出错,错误信息是sklearn当前版本0.18.1,使用imlearn需要0.19.0以上的版本,于是接着pip uninstall scikit-learn 删除当前版本的sklearn后,在pip install scikit-learn 自动安装至最新版本0.19.0。
  • 作者原始最后一段代码在我的电脑上跑不通,分析原因可能是数据集太大(oversample有四十多万条数据),系统(win7 32位)无法支持,于是我把oversample数据集进行切分(test_size=0.2),使用切分的训练集os_features_train部分进行模型的训练。

Part 4 知识技能归纳

  • 样本不均衡的解决办法,一是undersample,另外一种方法是oversample
  • 利用交叉验证的方式对数据集进行进行切分
  • 构造函数,设置不同惩罚参数进行循环验证,求取最佳参数
  • 绘制混淆矩阵,展示最终模型效果,同时考虑设置了不同的thresholds,比较不同thresholds下模型的效果

https://zhuanlan.zhihu.com/p/33173644
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值