【机器学习笔记】:逻辑回归实战练习(二)

作者:xiaoyu

知乎:https://zhuanlan.zhihu.com/pypcfx

介绍:一个半路转行的数据挖掘工程师

▍前言

前几篇介绍了逻辑回归在机器学习中的重要性:5个原因告诉你:为什么在成为数据科学家之前,“逻辑回归”是第一个需要学习的

以及逻辑回归的理论和公式推导:【机器学习笔记】:从零开始学会逻辑回归(一)

继上一篇,本篇将引出一个逻辑回归的实战练习,利用逻辑回归进行二分类,通过练习你将学会:

  • 理解逻辑回归模型参数的含义
  • 使用sklearn构建逻辑回归模型
  • 可视化逻辑回归分类效果
  • 评估逻辑回归模型

▍两个变量的简单数据集

上一篇,我们已经推导出了逻辑回归参数求解的迭代公式,自己通过numpy和scipy的使用就可以很容易地实现一个逻辑回归模型。当然,sklearn库已经有了封装好了的逻辑回归类LogisticRegression,下面我们将在一个简单的数据集上使用逻辑回归实现二分类。

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.linear_model import LogisticRegression

# 导入数据集
dataset = pd.read_csv('Social_Network_Ads.csv')
X = dataset.iloc[:, [2, 3]].values
Y = dataset.iloc[:,4].values

# 将数据集分成训练集和测试集
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, Y, test_size = 0.2, random_state = 0)
y_test = pd.Series(y_test)

# 简单的预处理,特征缩放
from sklearn.preprocessing import StandardScaler
sc = StandardScaler()
X_train = sc.fit_transform(X_train)
X_test = sc.transform(X_test)

# 构建模型,预测测试集结果
classifier = LogisticRegression()
classifier.fit(X_train, y_train)
y_pred = classifier.predict(X_test)

通过上面简单的调用sklearn库的类方法我们就训练出了一个简单的逻辑回归模型,使用的都是默认参数。下面让我们看看简单的模型分类效果究竟如何。

from matplotlib.colors import ListedColormap
X_set,y_set=X_train,y_train
X1,X2=np.meshgrid(np.arange(start=X_set[:,0].min()-1, stop=X_set[:, 0].max()+1, step=0.01),
                   np.arange(start=X_set[:,1].min()-1, stop=X_set[:,1].max()+1, step=0.01))

plt.contourf(X1, X2, classifier.predict(np.array([X1.ravel(),X2.ravel()]).T).reshape(X1.shape),
             alpha = 0.75, cmap = ListedColormap(('#C65749', '#338DFF')))
plt.xlim(X1.min(),X1.max())
plt.ylim(X2.min(),X2.max())
for i,j in enumerate(np. unique(y_set)):
    plt.scatter(X_set[y_set==j,0],X_set[y_set==j,1],
                c = ListedColormap(('red', 'blue'))(i), label=j)

plt. title(' LOGISTIC(Training set)')
plt. xlabel(' Age')
plt. ylabel(' Estimated Salary')
plt. legend()
plt. show()

X_set,y_set=X_test,y_test
X1,X2=np. meshgrid(np. arange(start=X_set[:,0].min()-1, stop=X_set[:, 0].max()+1, step=0.01),
                   np. arange(start=X_set[:,1].min()-1, stop=X_set[:,1].max()+1, step=0.01))

plt.contourf(X1, X2, classifier.predict(np.array([X1.ravel(),X2.ravel()]).T).reshape(X1.shape),
             alpha = 0.75, cmap = ListedColormap(('#C65749', '#338DFF')))
plt.xlim(X1.min(),X1.max())
plt.ylim(X2.min(),X2.max())
for i,j in enumerate(np. unique(y_set)):
    plt.scatter(X_set[y_set==j,0],X_set[y_set==j,1],
                c = ListedColormap(('red', 'blue'))(i), label=j)

plt.title(' LOGISTIC(Test set)')
plt.xlabel(' Age')
plt.ylabel(' Estimated Salary')
plt.legend()
plt.show()

上图是训练集分类效果,下图是测试集的分类效果,简单总结一下上面内容:

Python语言方面:使用了meshgrid方法将二维坐标划分成了间隔非常小的矩阵细小点,然后使用了contourf方法与模型预测结果对比判断分类结果。此外,使用了scatter散点图绘制了原数据分布点作为分类前后的比对。

逻辑回归理论方面:可以明显看到,在二维坐标中,逻辑回归是以一条直线进行分类的,很好的说明了逻辑回归的本质是线性分类的。同时我们也看到,目前情况下训练集中混在蓝色点中的一些红色点是无论如何也无法正确的分类出来的,这也正是它的缺点,所以说逻辑回归的分类准确度还是相对稍低的。

▍更多变量的数据集

下面我们将要在一个数据量更大,变量更多的的数据集上进行测试。由于我们需要一个二分类的数据集,所以这里使用了“泰坦尼号生还者预测”的数据集。

https://www.kaggle.com/c/titanic/data

当然,直接使用原始数据是不行的。为了方便,数据已被我提前处理,经过了清洗、预处理、变换、筛选和衍生,可直接供模型训练。因此,我们可以直接通过sklearn构建模型,看一下sklearn中逻辑回归的参数都有哪些。

from sklearn.linear_model import LogisticRegression

classifier_default = LogisticRegression()
classifier_default

结果如下:

LogisticRegression(C=1.0,
                   class_weight=None,
                   dual=False, 
                   fit_intercept=True,
                   intercept_scaling=1, 
                   max_iter=100, 
                   multi_class='ovr',
                   n_jobs=1,
                   penalty='l2',
                   random_state=None, 
                   solver='liblinear',
                   tol=0.0001,
                   verbose=0, 
                   warm_start=False)

上面是是逻辑回归的所有参数配置,都是默认的。乍一看是有很多参数,但其实只有几个是比较关键的。下面将对逻辑回归参数进行总结分类和解释。

▍Logistic模型参数解释

正则化参数:属于该分类的参数有 C 和 penalty。

  • C:C参数与惩罚系数成反比,C值越小,则正则化效果越强,即对参数的惩罚程度越大。
  • penalty:提供我们正则化的类型,L1范数正则化和L2范数正则化(在线性回归中相当于lasso回归和岭回归),默认情况下使用L2正则化,但此参数也需要与solver类型配合使用,因为一些solver有一些限制。关于L1和L2正则化的区别和理解后续进行介绍。

优化算法参数选择 solver:优化算法有四种实现方式,分别是:liblinear,lbfgs,newton-cg,sag,下面是四种算法的介绍。

这四种算法各有一些特点,如果是L2正则化,可选的优化算法有newton-cg,lbfgs,liblinear,sag,四个均可以选择。但是如果是L1正则化,就只能选择liblinear。这是因为L1正则化的损失函数不是连续可导的,而newton-cg,lbfgs,sag这三种优化算法都需要损失函数的一阶或者二阶连续导数,liblinear并没有这个依赖。简单来说,liblinear对于L1和L2都适用,而其他三种只适用L2。

另外,sag是我们上一篇使用的梯度下降的变种随机平均梯度下降,它每次仅使用了部分样本进行梯度迭代,所以当数据量较少时不宜选用,而当数据量很大时,sag是第一选择,计算速度会加快。但是sag不能用于L1正则化,所以当你有大量的样本,又需要L1正则化的话就要自己做取舍了。要么通过对样本采样来降低样本量,要么回到L2正则化。

迭代参数:相关参数有max_iter和tol。

  • max_iter:参数求解的迭代次数,默认100。迭代次数过小会影响准确率,迭代次数过高会影响速度,一般会折中考虑。
  • tol:残差收敛条件,即迭代的连续两次之间残差小于tol就停止,默认是0.0001。

权重参数 class_weight:这个参数可以调节样本比例。一个很常见的例子是网贷违约预测中用户的好坏比,通常好用户占绝大部分,所以样本是不均衡的。除了采样方法处理外,也可以使用该参数进行调节。参数选择 balanced 则可以自动计算样本比例来达到平衡,或者也可以通过自定义比例来达到同样效果。

多分类参数 multi_class:我们上面举的例子都是默认二分类的,但逻辑回归也可以用于多分类,有 ovr 和 multinomial 两个值可以选择,默认是 ovr。ovr是one-vs-rest(OvR),而multinomial是many-vs-many(MvM)。如果是二元逻辑回归,ovr和multinomial并没有任何区别,区别主要在多元逻辑回归上。

OvR相对简单,但分类效果相对略差(这里指大多数样本分布情况,某些样本分布下OvR可能更好)。而MvM分类相对精确,但是分类速度没有OvR快。如果选择了ovr,则4种损失函数的优化方法liblinear,newton-cg, lbfgs和sag都可以选择。但是如果选择了multinomial,则只能选择newton-cg, lbfgs和sag了。

了解参数的意义后,我们可以开始尝试调节一下这些参数,通过参数调节,可以有效避免过拟合等现象,以此实现一个效果更优,更健壮的模型。

▍Logistic模型参数调试

下面我们手动调节几个参数,来感受一下这些参数是如何影响最终结果的。

# 配置调节参数
C_list = [0.0001, 1, 1000]
max_iter_list = [1, 50, 100]
classifiers = ClassifierGenerator('C', C_list)
Auc_plot(classifiers, X_test, 'C')

当然,对于不同参数的选择,我们可以通过查看ROC和AUC,以此来衡量结果。首先,我们调节C参数,分别是0.0001,1,和1000,查看这三个不同值下的ROC曲线和AUC值。如果对ROC/AUC不清楚,可以参考:【机器学习笔记】:一文让你彻底记住什么是ROC/AUC(看不懂你来找我)

上面是三个C取值在测试集数据上的评估结果,可以看到:C=0.0001的时候,AUC值为0.91,这说明模型可能出现了过拟合的现象。因为,C越小,惩罚程度越大,参数可能过度学习而无法在测试集上泛化,因此测试集上AUC值相对低。

而C的其它两个取值,1和1000,虽然二者ROC曲线稍有不同,但是AUC值都是0.92,所以就单独C参数来讲,二者皆可。

同样的,可以对比不同max_iter参数值的不同结果。

# 配置调节参数
C_list = [0.0001, 1, 1000]
max_iter_list = [1, 100]
classifiers = ClassifierGenerator('max_iter', max_iter_list)
Auc_plot(classifiers, X_test, 'max_iter')

迭代次数为1情况下AUC值0.91,偏低,而为100的时候AUC值为0.92。这说明迭代次数(max_iter=1)太低导致出现了欠拟合。

▍自动化查找最优参数

上面我们手动地调节了一些参数,但是这些参数是一起其作用的,单独调节的情况下不一定能够保证最好,最好的情况是一个完美的参数搭配或者组合。那么如何找到这样的搭配呢?除了凭借经验手动调参以外,还可以使用sklearn的一个工具。

sklearn中提供了一种自动搜索最优参数的方法:GridSearchCV,它是基于提供的参数选项,组合出各种可能,然后结合交叉验证对所有可能组合进行筛选。因此,通过使用该方法,我们就可以简单地找到相对上面单独参数调节更好的参数组合了。

还是通过上面的例子继续说明,自动调参代码如下:

from sklearn.model_selection import GridSearchCV
import warnings
warnings.filterwarnings("ignore")

# 参数设置
params = {'C':[0.0001, 1, 100, 1000],
          'max_iter':[1, 10, 100, 500],
          'class_weight':['balanced', None],
          'solver':['liblinear','sag','lbfgs','newton-cg']
         }
lr = LogisticRegression()
clf = GridSearchCV(lr, param_grid=params, cv=10)
clf.fit(X_train,y_train)

将所有参数设置考虑进去,训练数据,结果我们可以得到:

>>clf.best_params_

out:
{'C': 1, 'class_weight': None, 'max_iter': 10, 'solver': 'sag'}

上面结果就是我们基于自己提供的参数选择要找的最佳参数组合了。

▍构建最优模型

有了最优的参数后,我们将这些参数作为输入重新建立一个逻辑回归模型。代码如下:

# 根据以上绘图结果选择一个合理参数值
classifier = LogisticRegression(**clf.best_params_)
# 训练模型
classifier.fit(X_train, y_train)

# 预测测试集结果
y_pred = classifier.predict(X_test)
y_score = classifier.predict_proba(X_test)[:,1]

成功构建模型后,我们再次进行分类,并看一下最终的评估指标ROC曲线,AUC值,以及KS值:

# roc/auc计算
y_score = classifier.predict_proba(X_test)[:,1]
fpr,tpr,threshold = metrics.roc_curve(y_test, y_score)
roc_auc = metrics.auc(fpr,tpr)

# 绘制roc曲线
f,ax = plt.subplots(figsize=(8,6))
plt.stackplot(fpr, tpr, color='#338DFF', alpha = 0.5, edgecolor = 'black')
plt.plot(fpr, tpr, color='black', lw = 1.5)
plt.plot([0,1],[0,1], color = 'red', linestyle = '--', lw = 2)
plt.text(0.5,0.3,'ROC curve (area = %0.2f)' % roc_auc)
plt.xlabel('1-Specificity')
plt.ylabel('Sensitivity')
plt.show()
from ks_visual import plot_ks
# 观察ks指标,并绘制ks曲线
plot_ks(y_test = y_test, y_score = y_score, pf = 1)

可以看到,AUC值为0.92,KS值为0.75,说明分类模型的区分能力和准确度都不错。但要提醒的是:这样的好结果并不全是逻辑回归模型的功劳,而更多的是前期特征工程的贡献。只有做出好的特征,提高数据质量,才能最大程度上的提高最终效果。

参考: https://www.cnblogs.com/pinard/p/6035872.html 从零开始学习数据分析和挖掘,刘顺祥 https://github.com/MLEveryday/100-Days-Of-ML-Code

原文发布于微信公众号 - Python数据科学(Python_Spiderman)

原文发表时间:2018-11-28

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏决胜机器学习

机器学习(二十三) —— 大数据机器学习(随机梯度下降与map reduce)

机器学习(二十三)——大数据机器学习(随机梯度下降与map reduce) (原创内容,转载请注明来源,谢谢) 一、概述 1、存在问题 当样本集非常大的时候,...

39130
来自专栏数据科学学习手札

(数据科学学习手札36)tensorflow实现MLP

  我们在前面的数据科学学习手札34中也介绍过,作为最典型的神经网络,多层感知机(MLP)结构简单且规则,并且在隐层设计的足够完善时,可以拟合任意连续函数,而除...

48540
来自专栏机器之心

教程 | 无需反向传播的深度学习:DeepMind的合成梯度

选自GitHub 作者:iamtrask 机器之心编译 参与:王宇欣、Ellen Han 在这篇博文中,我们将从起点(从零开始)学习 DeepMind 最近提...

368100
来自专栏企鹅号快讯

机器学习三人行-支持向量机实践指南

关注公众号“智能算法”即可一起学习整个系列的文章。 文末查看本文代码关键字,公众号回复关键字下载代码。 其实逻辑回归算法和今天要讲的支持向量机有些类似,他们都是...

21890
来自专栏数值分析与有限元编程

雅可比矩阵(一)

物理坐标系和自然坐标系的坐标映射关系为 ? ? 咋一看,这似乎是一个线性方程组。实际上并不是,这是一个非线性方程组(不是太明显),如果是C1或者C2级就有二次项...

33090
来自专栏AI研习社

理解 YOLO 目标检测

这篇文章从它的角度解释了YOLO目标检测结构。它将不会描述网络的优缺点以及每个网络设计如何选择的原因。相反的,它关注的是网络是如何工作的。在你阅读之前,你应该对...

23030
来自专栏AI深度学习求索

弱监督语义分割算法|AE-PSL算法对抗性擦除最具有判别性区域

这是一篇有趣的弱监督语义分割算法,最有趣的在什么地方呢?它通过将图片中最重要的、最具有判别性的部分擦除了,从而来得到次判别性区域,不明白他为什么会舍弃最好的而求...

28320
来自专栏计算机视觉战队

分割算法——可以分割一切目标(各种分割总结)

周末应该是一个好好休息的时间,但是一定会有在默默努力科研的你,由于最近是开学季,很多关注的朋友一直会问“计算机视觉战队平台有基础性的内容吗?”,今天我和大家说一...

81540
来自专栏AI科技评论

干货 | 攻击AI模型之DeepFool算法

AI 科技评论按:本文为“兜哥带你学安全”系列之三,首发于AI科技评论,未经许可不得转载。

40330
来自专栏数据派THU

Python实例介绍正则化贪心森林算法(附代码)

作者:Ankit Chaoudhary 翻译:笪洁琼 校对:梁傅淇 通过本文与大家讨论一个被称为正则化的贪心森林算法。 引言 作为一名参与多个机器学习竞赛数据...

48260

扫码关注云+社区

领取腾讯云代金券