走近数据算法——逻辑回归(Logistic Regression)

特别声明:本文仅学习交流,感兴趣的朋友可以留言互相讨论。


  • 文章简介
    本文是在学习过程中通过自己对模型的理解及复盘整理,并不对代码逻辑进行讲解,文中外链资料都是在学习过程中觉得比较容易理解的资料,可以作为参考,本来不想写那么长的,越写发现越写不完......
    数据来源:Kaggle下载 creditcard.csv 信用卡欺诈数据,数据做过脱敏处理,可自行下载。
  • 模型介绍
    一元线性回归是一种很容易理解的模型,就相当于 y = f(x) = ax + b,表明自变量x与因变量y的关系。那么x0,x1,x2,会生成y0,y1,y2其实(x0,y0)、(x1,y1)就是分布在二维向量间的多个点,我们可以拟合一个线性方程:y =β0 +β1*x1 +β2*x2 +β3*x3 +...+βn*xn并通过最小二乘法估计各个β系数的值。
    (点我跳转到 最小二乘法通俗解释 相关资料)

    那么到底什么是逻辑回归?
    这里又要讲到一个Sigmoid函数,Logistic回归算法基于Sigmoid函数,或者说Sigmoid就是逻辑回归函数。下图个人觉得非常好理解,g(z)函数就是Sigmoid函数,它将线性拟合h(x)函数作为参数z带入公式,线性方程我们知道他的x,y可以是±∞,那么通过Sigmoid函数之后可以将y的值域范围压缩到(0,1),注意这是开区间,它仅无限接近0和1,这结果其实就是最后二分类的概率值,一般默认概率大于等于0.5则默认为1,小于0.5则为0,阀值可以设置。

    用一句话来说就是:逻辑回归假设数据服从伯努利分布,通过极大化似然函数的方法,运用梯度下降来求解参数得出分类概率,通过阈值过滤来达到将数据二分类的目的。
    (伯努利分布又称二项分布,是无数个独立试验的正样例成功次数的概率分布,详细点我跳转到相关资料)
    (点我跳转到 最大似然法通俗解释 相关资料)
  • 数据观察
    先看样本数据 source_data.head(3)
    字段名都被做过特殊处理,Class为最后的标识(Label)看到所有的特征(Feature)都在(1,-1)间,但Amount的数值波动范围较大,机器学习中其实就等于转化为数学问题,数据按大小来界定权重,Amount大重要程度大,所以在这需要对Amount进行数据标准
  • 数据标准化(Normalization)
    常用的2个标准化方法 : Z-ScoreMin_Max 这两种标准化方法不光在机器学习中有用,平时多维数据简单归一拉到一个水平线上加权制定系数也是常用到这两个方法。

    1、Min_Max 标准化将原始数据线性化的方法转换到[0,1]的范围,归一化公式如下:

    2、Z-Score 归一化方法将原始数据集归一化为均值为0、方差1的数据集,那么它的阈值范围自然为[-1,1]归一化公式如下:
# 1、StandardScaler就是z-score方法  
# 2、MaxMinScaler就是min_max方法
from sklearn.preprocessing import StandardScaler 
source_data['New_Amount'] =  StandardScaler().fit_transform(source_data['Amount'].values.reshape(-1,1))
# StandardScaler参数只接受矩阵
data = source_data.drop(columns=['Amount','Time'])
  • 独热编码(One-Hot Encoding)
    是不是已经各种术语弄得快放弃了? 画了一张图,可能不是很严谨但我觉得很好理解


    就是把离散变量作为fature,对应fature以1作为标识,这个编码转化过程就是One-Hot Encoding,还有一种编码叫LabelEncoder就是将公司名变成类别值

  • 样本重采样(Resample)

# 检查正负样本label差异
pd.value_counts(source_data['Class'])


样本重采样是对样本Label数量不均衡处理,这里可以有2种处理方式:欠采样(代表算法:EasyEnsemble)过采样(代表算法:SMOTE) ,两种方法概念其实很简单。

1、欠采样:即去除一些反例使得正反例数目接近,再进行学习。由于丢弃很多反例,会使得训练集远小于初始训练集,所以有可能导致欠拟合。

2、过采样:增加一些正例使得正反例数目接近,然后再学习。需要注意的是不能只是对初始正例样本重复采样,否则导致严重的过拟合,SMOTE算法中用用到了另一种机器学习的算法KNN(K邻近取样算法)

from imblearn.over_sampling import SMOTE
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import confusion_matrix

# 数据集中正反lable相差悬殊,需进行重采样
# 重采样常用方法有2种,1、欠采样 代表算法:EasyEnsemble 2、过采样 代表算法:SMOTE

# 先对数据进行切分
labels = data['Class']
features = data.drop(columns=['Class'])

x_train, x_test, y_train , y_test = train_test_split(features,
                                                    labels,
                                                    test_size = 0.3,
                                                    random_state = 0)

# 这里进行SMOTE过采样的方法
over_sample = SMOTE(random_state=0)
os_x_train , os_y_train = over_sample.fit_sample(x_train ,y_train)
os_x_train = pd.DataFrame(os_x_train)
os_y_train = pd.DataFrame(os_y_train)
  • 交叉验证(Cross - Validation)
    用来验证分类器的性能一种统计分析方法,基本思想是把在某种意义下将原始数据(dataset)进行分组,一部分做为训练集(train set),另一部分做为验证集(validation set),首先用训练集对分类器进行训练,在利用验证集来测试训练得到的模型(model)
  • 损失函数(Loss Function)
    看到一个比较容易理解的说法如下:


    我们假设直线的方程为Y=a0+a1X(a为常数系数)。假设a0=10 a1=3 那么Y=10+3X

    上面的案例它的绝对损失函数求和计算求得为:6,这个函数就称为损失函数(loss function),或者叫代价函数(cost function),我们希望我们预测的公式与实际值差值越小越好,所以就定义了一种衡量模型好坏的方式。

    公式Y-实际Y的绝对值,数学表达式:

    为后续数学计算方便,我们通常使用平方损失函数代替绝对损失函数,公式Y-实际Y的平方,数学表达式:

    还有在下面讲到正则化的部分,损失函数 = 误差部分(loss term) + 正则化部分(regularization term)

  • 正则化惩罚
    常用正则范数:L1正则L2正则
    1、L2正则化惩罚项(λ为惩罚力度权重):
    loss = loss + 1/2w² ,w为明显波动情况,通过过W去判断模型最终loss值,越低模型效果越好
    2、L1正则化惩罚项 (λ为惩罚力度权重):
    loss = loss + |w| ,w为明显波动情况,通过过W去判断模型最终loss值,越低模型效果越好
    加入正则化的目的:防止过拟合约束(限制)要优化的参数

  • 混淆矩阵(Confusion Matrix)
    首先它长这样,就一个多维矩阵,呵呵!!统计学就术语可以让我们从放弃到崩溃。我们从混淆矩阵的4个基础指标中可以衍生出各类评估指标,模型好坏都靠这些指标进行评估。

    感觉很多资料讲的不够通俗,个人理解给大家翻译一下,我们先把正例和反例替换成比较通俗的"买"和"不买":
    真正例(True Positive,TP):真实情况是"买",预测结果也是"买",TP表示正例预测成功次数。
    假正例(False Positive,FP):真实情况是"不买",预测结果也是"买",FP表示负例预测错误次数。
    假负例(False Negative,FN):真实情况是"买",预测结果也是"不买",FN表示正例预测错误次数。
    真负例(True Negative,TN):真实情况是"不买",预测结果也是"不买",TN表示负例预测成功次数。


    现在明白了吧,其实很简单,再来看下常用的衍生指标的意思。
    模型精度(Accuracy):Accuracy = (TP + TN) / (TP + FP + TN + FN)
    一般情况下,模型的精度越高,说明模型的效果越好。
    准确率,又称查准率(Precision,P):Precision = TP / (TP + FP)
    一般情况下,查准率越高,说明模型的效果越好。
    召回率,又称查全率(Recall,R):Recall = TP / (TP + FN)
    一般情况下,Recall越高,说明有更多的正类样本被模型预测正确,模型的效果越好。
    F1值(F1-Score):F1 Score = P*R/2(P+R),其中P和R分别为 precision 和 recall
    一般情况下,F1-Score越高,说明模型的效果越好。


    那么我们再来看几个图形指标
    真阳性率(True Positive Rate,TPR ):TPR = TP / (TP+FN)
    等于Recall,一般情况下,TPR 越高,说明有更多的正类样本被模型预测正确,模型的效果越好。
    假阳性率(False Positive Rate,FPR ):FPR= FP / (FP+TN)​
    一般情况下,FPR 越低,说明有更多的负类样本被模型预测正确,模型的效果越好。

    ROC(Receiver Operating Characteristic):ROC曲线的纵坐标为 TPR,横坐标为 FPR
    AUC(Area Under Curve):ROC曲线下的面积,很明显,AUC 的结果不会超过 1,通常 ROC 曲线都在 y = x 这条直线上面,所以,AUC 的值一般在 0.5 ~ 1 之间,面积越大模型效果越好。

    以上都是很重要的模型评估的常用指标,代码如下
from sklearn.metrics import roc_curve, auc
# y = np.array([1,1,2,2])
# pred = np.array([0.1, 0.4, 0.35, 0.8])
fpr, tpr, thresholds = roc_curve(y, pred, pos_label=1)
fpr      # array([ 0. ,  0.5,  0.5,  1. ])
tpr      # array([ 0.5,  0.5,  1. ,  1. ])
thresholds      #array([ 0.8 ,  0.4 ,  0.35,  0.1 ])
auc(fpr, tpr)

那么这张图我们现在就相当好理解了吧。


以下两个链接对混淆矩阵及涉及到的指标讲述的非常明白易懂,还不清楚的可以点开看阅读。
混淆矩阵及评估指标相关扩展资料1,外链
混淆矩阵及评估指标相关扩展资料2,外链

  • 混淆矩阵图例
    为了美观,做了混淆举证图例展示,其实如果平时完全可以,用上面普通矩阵形式进行观察
import itertools
def plot_confusion_matrix(cm, 
                          classes,
                          normalize=False,
                          title='Confusion matrix',
                          cmap=plt.cm.Blues):
    """
    This function prints and plots the confusion matrix.
    Normalization can be applied by setting `normalize=True`.
    """
    if normalize:
        cm = cm.astype('float') / cm.sum(axis=1)[:, np.newaxis]
#         print("Normalized confusion matrix")
    else:
        pass
#         print('Confusion matrix, without normalization')

    im = plt.imshow(cm, interpolation='nearest', cmap=cmap, vmax = cm.max() / 3.)
    plt.title(title,fontsize = 16)
    plt.colorbar(im,shrink=0.63,pad=0.05) 
    tick_marks = np.arange(len(classes))
    plt.xticks(tick_marks, classes, rotation=0,fontsize = 14)
    plt.yticks(tick_marks, classes,fontsize = 14,rotation=90)

#     fmt = '.2f' if normalize else 'd'
    thresh = cm.max() / 2.
    for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])):
        plt.text(j, i, format(cm[i, j]),
                 horizontalalignment="center",
                 fontsize = 16,
                 color="white" if cm[i, j] > thresh else "black")

    plt.tight_layout()
#     plt.ylabel('True label',fontsize = 14)
#     plt.xlabel('Predicted label',fontsize = 14)

# 模型评估标准 re_call = TP/(TP+NF)
plt.figure(figsize=(12,6)) 

for i,t in enumerate(range(3,9),start=1):
    thresholds = t / 10
    y_proba = lr.predict_proba(x_test.values)[:,1] > thresholds
    plt.subplot(2,3,i)
    matrix = confusion_matrix(y_test, y_proba)
    plot_confusion_matrix(matrix, classes=['Label_0','Label_1'],title = 'Thresholds > %s' % thresholds)
#     print(classification_report(y_test, y_proba))
  • 模型评估(Model Evaluation)
    模型评估常用的包括了上面提到的交叉验证损失函数正则化惩罚混淆矩阵FPRTPR(也可以称为recall)ROCAUCF1-Score
    下面不仅做了一次5层的交叉验证,还用了用了L1惩罚项,不断用惩罚系数去调整模型的精确度,确认惩罚系数,从结果图中可以看到,模型精确度不断在提升。
# 交叉验证准备,切分数据集
def kfold_result_info(x,y,n=5):
    os_x_train = x
    os_x_train = y
    # K-fold交叉验证
    kfold = KFold(len(os_y_train),n_folds= n ,shuffle=False,random_state=0)
    for num in range(5):
    #   c_param 为参数λ惩罚力度权重,代入不断尝试,构造参数
        c_param = 0.01 * 10 ** num
        print('Regularization L1 Param %s :' %(c_param))
        recall_list = []
        
        for i ,val_idx in enumerate(kfold, start=1):
    #       建立逻辑回归测试模型
            lr = LogisticRegression(C = c_param, penalty='l1')
            lr.fit(os_x_train.iloc[val_idx[0],:], os_y_train.iloc[val_idx[0],:].values.ravel())
            os_pre_result = lr.predict(os_x_train.iloc[val_idx[1],:].values)
            # 模型评估标准 re_call = TP/(TP+NF)
            re_call = recall_score(os_y_train.iloc[val_idx[1],:].values,os_pre_result)
            recall_list.append(re_call)
            
            print('\t Cross-val ReCall_Score: %s' % re_call)
        
        mean_score = np.mean(recall_list)
        print('\nRound%s Mean Score : %s' % (num + 1, mean_score))
        print('\n-----------------------------------------------')

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容