以《简单易懂》的语言带你搞懂逻辑回归算法【附Python代码详解】机器学习系列之逻辑回归篇

以《简单易懂》的语言带你搞懂逻辑回归算法【附Python代码详解】机器学习系列之逻辑回归篇目录必看前言逻辑回归算法1概述2基本原理3sklearn实现3.1导入数据(乳腺癌数据集)3.2建模3.3绘制学习曲线3.4网格搜索-确定最优参数结束语必看前言这一篇文章,我会详细从机器学习的角度介绍逻辑回归,以及如何利用Python来实现逻辑回归以及逻辑回归的实战模拟,另外我也会教大家如何利用网格搜索找到最优参数。干货满满!逻辑回归算法1概述分类技术是机器学习和数据挖掘应用中的重要组成部分。在数据科学中,绝大多数的问题属于分类问题。解决分类的算法也有很多种。如:KNN,使距

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

大家早上好,本人姓吴,如果觉得文章写得还行的话也可以叫我吴老师。欢迎大家跟我一起走进数据分析的世界,一起学习

感兴趣的朋友可以关注我或者我的数据分析专栏,里面有许多优质的文章跟大家分享哦。


必看前言

这一篇文章,我会详细从机器学习的角度介绍逻辑回归,以及如何利用Python来实现逻辑回归以及逻辑回归的实战模拟,另外我也会教大家如何利用网格搜索找到最优参数。

干货满满!

逻辑回归算法

1 概述

分类技术是机器学习和数据挖掘应用中的重要组成部分。在数据科学中, 绝大多数的问题属于分类问题。解决分类的算法也有很多种。 如:KNN,使距离计算来实现分类;决策树,通过构建直观易懂的树来实现分类。这里我们要展开的是Logistic回归,它是一种很常见的用来解决二元分类问题的回归方法,它主要是通过寻找最优参数来正确地分类原始数据。

2 基本原理

逻辑回归(Logistic Regression,简称LR),其实是一个很有误导性的概念,虽然它的名字中带有”回归”两个字,但是它最擅长处理的却是分类问题。LR分类器适用于各项广义上的分类任务,例如:评论信息的正负情感分析(二分类)、用户点击率(二分类)、用户违约信息预测(二分类)、垃圾邮件预测(二分类)、疾病预测(二分类)、用户等级分类(多分类)等场景。我们这里主要讨论的是二分类问题。在这里插入图片描述
之前我们介绍了线性回归的算法基本原理、使用方法、在最小二乘法求最优解以及条件不满足的情况系原始算法的修正方法。但实际上,线性回归只是机器学习类算法中最简单的用特征预测标签数值的回归算法,满足线性规律的真实场景并不是很多,因此标准线性回归应用面有限。为了解决该问题,线性回归在实际应用中引入了诸多变化形式,而这些变化形式可统一规整为如下形式∶ y = g − 1 ( w T x + b ) y=g^{-1}(w^Tx+b) y=g1(wTx+b)其中 g ( ∗ ) g(*) g()为可微函数。而这类模型也被称为广义线性模型(generalized linear model),其中函数被称为联系函数((link function),现如今被广为人知的逻辑回归就是诸多广义回归算法的其中一种。在逻辑回归中,我们使用对数几率函数(Logistic function)作为 g − 1 ( ∗ ) g^{-1}(*) g1(),对数几率函数表示形式如下: y = g ( z ) = 1 1 + e − x y=g(z)=\frac {1}{1+e^{-x}} y=g(z)=1+ex1能够看出,对数几率函数是一个Sigmoid函数。Sigmoid函数是形似S的函数,对率函数是Sigmoid函数的重要代表,在感知机理论中也发挥着重大作用(在神经网络中叫做激活函数,只不过神经网络加了一些隐藏层,用于拟合非线性函数)。
在这里插入图片描述
(注意这里是开区间,一般将大于0.5的看做正分类,小于0.5看做父分类)

利用对率函数,我们可将 转化为一个 (0,1) 区间内的值,除此之外, g ( z ) g(z) g(z)还有一个很好的导数性质∶ g ′ ( z ) = g ( z ) ( 1 − g ( z ) ) g'(z)=g(z)(1-g(z)) g(z)=g(z)(1g(z))带入对率函数,得到逻辑回归表达式为: y = 1 1 + e − ( w T x + b ) y=\frac{1}{1+e^{-(w^Tx+b)}} y=1+e(wTx+b)1进一步可得: l n y 1 − y = w T x + b ln \frac{y}{1-y}=w^Tx+b ln1yy=wTx+b由于 y y y和 1- y y y的和为1,因此可将 y y y和 1- y y y视为一对正反例的可能性,即 y y y视作样本 x x x为正例的可能性,则1- y y y x x x为反例的可能性,二者比例: 1 1 − y \frac{1}{1-y} 1y1被称为 “几率”(odds),反映了样本 为正例的相对可能性。对几率取对数则得到”对数几率”(logodds,亦称logit): l n 1 1 − y ln\frac{1}{1-y} ln1y1由此看出,上式实际上是在用线性回归模型的预测结果取逼近真实标记的对数几率。因此,其对应的模型被称为”对数几率回归”(logistic regression)。需要注意的是,虽然其名字包含回归二字,但本质上是一种分类学习方法。这种方法有很多优点,例如它是直接对分类可能性进行建模,因此它不仅预测出”类别”,而且得到的是近似概率预测,这对许多需要利用概率辅助决策的任务很有用。

3 sklearn实现

对于损失函数而言,我们知道在线性回归中是通过最小二乘法来得到最小化的函数值。

那么对于逻辑回归来讲,是通过梯度下降的方式来得到最小化的损失函数,是一步步迭代求导的过程。

那接下来我们先去用sklearn来实现逻辑回归,再来讲梯度下降,这样大家才不会那么难理解明白。

3.1 导入数据(乳腺癌数据集)

import numpy as np
import pandas as pd
from sklearn.datasets import load_breast_cancer #乳腺癌数据集
import matplotlib.pyplot as plt
X =load_breast_cancer().data
Y =load_breast_cancer().target
X.shape

(569, 30)

Y

在这里插入图片描述

pd.DataFrame(X) #可以考虑标准化

在这里插入图片描述

3.2 建模

from sklearn.linear_model import LogisticRegression as LR #逻辑回归
from sklearn.model_selection import train_test_split

大家可以先看一下逻辑回归的参数有哪些:

# LR(
# penalty='l2', # l2正则化---岭回归 l1正则化---lasso 默认l2
# *,
# dual=False,
# tol=0.0001,
# C=1.0, # C越小表示惩罚力度越大,C越大惩罚力度越小
# fit_intercept=True,
# intercept_scaling=1,
# class_weight=None,
# random_state=None,
# solver='lbfgs', # 梯度下降的方式
# max_iter=100, # 梯度下降会有迭代次数
# multi_class='auto',
# verbose=0,
# warm_start=False,
# n_jobs=None,
# l1_ratio=None,
# )

我们先看这个penalty参数,那L2对应的是什么呢?

在岭回归中,对自变量系数进行平方和处理也被称作L2正则化。

岭回归和Lasso在线性回归中主要是解决共线性并且做特征选择的问题,但是在逻辑回归中它起的作用主要是通过公式对权值进行更新计算来防止过拟合。

LogisticRegression默认就带了正则化项。penalty参数可选择的值为”1″和”2″,分别对应L1的正则化和L2的正则化,默认是L2的正则化。

在调参时如果我们主要的目的只是为了解决过拟合,一般penalty选择L2正则化就够了。但是如果选择L2正则化发现还是过拟合,即预测效果差的时候,就可以考虑L1正则化。另外,如果模型的特征非常多,我们希望一些不重要的特征系数归零,从而让模型系数稀疏化的话,也可以使用L1正则化。

penalty参数的选择会影响我们损失函数优化算法的选择。即参数solver的选择,如果是L2正则化,那么4种可选的算法 (‘newton-cg’,‘Ibfgs’,‘liblinear’,‘sag’} 都可以选择。但是如果penalty是L1正则化的话,就只能选择 ‘liblinear’了。这是因为L1正则化的损失函数不是连续可导的,而 {‘newton-cg’,‘Ibfgs,‘sag’}这三种优化算法时都需要损失函数的一阶或者二阶连续导数。而 ’liblinear’ 并没有这个依赖。

而两种正则化下C的取值,都可以通过学习曲线来进行调整。

建立两个逻辑回归,L1正则化和L2正则化的差别一目了然∶

lr1 = LR(penalty='l1',solver='liblinear', #l1 正则化 #liblinear是梯度下降方法中的坐标下降法
                       C= 0.5,
                       max_iter=1000).fit(X,Y)

lr2 = LR(penalty='l2',solver='liblinear', #l2 正则化
                       C= 0.5,
                       max_iter=1000).fit(X,Y)
lr1.score(X,Y),lr2.score(X,Y)

(0.9578207381370826, 0.9560632688927944)

从得分来看区别不大。

  • L1正则化可以对特征进行筛选
lr1.coef_ # w 参数值 

在这里插入图片描述

  • 对当前的数据集来讲,使用L1,特征减少至1/3,精度还是控制96%,说明剩下的特征是比较重要的特征,可以很好体现X与Y之间的关系。
lr2.coef_ # w 参数值 

在这里插入图片描述

  • 特征越多,模型复杂度越高,更容易将噪声学习到模型中,导致过拟合(模型泛化能力下降),模型特征越少(不能太过),泛化能力越强
#对每一行进行预测
lr2.predict_proba(X)  # 0 1
#.sum(axis=1)

在这里插入图片描述
predict_proba函数之前在knn的时候就讲过啦,每一行的两个数值分别对应两个类别的概率值,相加等于1。

3.3 绘制学习曲线

我们可以通过L1正则化筛选特征,而L2正则化则是给出所有系数值,那么我们怎么判断哪种方法更好呢?

答:绘制学习曲线看一看。

# 切分数据集
Xtrain,Xtest,Ytrain,Ytest = train_test_split(X,Y,test_size=0.3,random_state=420)
#查看C在L1、L2下训练集和测试集的表现
l1 = []
l2 = []

l1test = []
l2test = []

for i in np.linspace(0.05,1,19):
    #实例化模型并训练
    lrl1 = LR(penalty='l1',solver='liblinear',C=i,max_iter=1000).fit(Xtrain,Ytrain)
    lrl2 = LR(penalty='l2',solver='liblinear',C=i,max_iter=1000).fit(Xtrain,Ytrain)
    
    # 记录训练集的分数
    l1.append(lrl1.score(Xtrain,Ytrain))
    l2.append(lrl2.score(Xtrain,Ytrain))
    
    # 记录测试集的分数
    l1test.append(lrl1.score(Xtest,Ytest))
    l2test.append(lrl2.score(Xtest,Ytest))
# 画图

graph = [l1,l2,l1test,l2test]
color = ["green","black","lightgreen","gray"]
label = ["L1","L2","L1test","L2test"] 

plt.figure(figsize=(6,6))
for i in range(len(graph)):
    plt.plot(np.linspace(0.05,1,19),graph[i],color[i],label=label[i])
plt.legend(loc=4) #图例的位置在哪⾥?4表示,右下⻆
plt.show()

在这里插入图片描述
可以看到随着C值的增大,分数逐渐增大。

而在最开始(大概0.1)的时候,L2的分数明显大概L1,但是当0.2左右时,L1测试集分数明显大于L2,这是为什么呢?

主要就是惩罚力度比较大了,模型对特征进行选取,所以对位置数据的泛化能力就强了。

而我们也可以看到当C值大概等于0.8时,L2测试集和训练集的分数最大(我们一般也是默认选择L2)。

关于最大迭代次数绘制学习曲线:

# 确定C=0.8 关于最大迭代次数绘制学习曲线
l2 = []
l2test = []

for i in range(1,201,10):
    lrl2 = LR(penalty='l2',solver='liblinear',C=0.8,max_iter=i).fit(Xtrain,Ytrain)
    
    l2.append(lrl2.score(Xtrain,Ytrain))
    l2test.append(lrl2.score(Xtest,Ytest))
    
plt.plot(range(1,201,10),l2,label='l2')
plt.plot(range(1,201,10),l2test,label='l2test')
plt.legend(loc=4)

在这里插入图片描述
可以发现我们选择差不多25次迭代效果就可以啦,多了也没用,还浪费时间。

因为我们这里的梯度算法其实就是通过一次次的迭代去计算最小的损失函数。我们看一下下面这张图:

在这里插入图片描述
其实呢,我们求解最小损失函数的过程,就像“下山”一样,一次次迭代就是从山顶不断下山的过程的。

需要注意的是,梯度下降不一定能找到全局的最优解,有可能是局部最优(但如果我们损失函数是一个凸函数的话,得到的就一定是最优解)

3.4 网格搜索-确定最优参数

我们可以利用绘制学习曲线的方法,找到最优的参数,但是这样总感觉有些许麻烦。

那么有没有一种方法,可以帮助我们一次性就找到最优的参数呢?答案是有的!

#导包
from sklearn.model_selection import GridSearchCV #网格搜索
from sklearn.preprocessing import StandardScaler #标准化
data = pd.DataFrame(X,columns= load_breast_cancer().feature_names)
data['label'] = Y
#划分数据集
Xtrain,Xtest,Ytrain,Ytest = train_test_split(X,Y,test_size=0.3,random_state=420)

#对训练集和测试集做标准化---去量纲
std = StandardScaler().fit(Xtrain)
Xtrain_ = std.transform(Xtrain)
Xtest_ = std.transform(Xtest)
#在l2范式下,判断C和solver的最优值
p = { 
   
    'C':list(np.linspace(0.05,1,19)),
    'solver':['liblinear','sag','newton-cg','lbfgs']
}

model = LR(penalty='l2',max_iter=10000)

GS = GridSearchCV(model,p,cv=5)
GS.fit(Xtrain_,Ytrain)

在这里插入图片描述

查看最大分数值:

GS.best_score_

0.9874683544303797

最大分数对应的最优参数:

GS.best_params_

{‘C’: 0.3138888888888889, ‘solver’: ‘sag’}

那么得到最优参数的话,我们就可以用这些参数建模啦。

#将最优参数重新用于实例化模型,查看训练集和测试集下的分数
model = LR(penalty='l2',
           max_iter=10000,
           C=GS.best_params_['C'],
           solver=GS.best_params_['solver'])  #sag 三种通过导数计算的方式是不能l1正则化的

训练模型:

model.fit(Xtrain_,Ytrain)

查看训练集和测试集的效果:

model.score(Xtrain_,Ytrain),model.score(Xtest_,Ytest)

(0.9874371859296482, 0.9649122807017544)

结束语

那么关于逻辑回归的介绍就到这里啦,下一篇讲啥好呢。。。

emmm,明天再看吧。

推荐关注的专栏

?‍?‍?‍? 机器学习:分享机器学习实战项目和常用模型讲解
?‍?‍?‍? 数据分析:分享数据分析实战项目和常用技能整理

机器学习系列往期回顾

❤️ 一文带你用Python玩转线性回归模型 ❤️加利福尼亚房价预测❤️回归模型评估指标介绍
? 如何搞懂机器学习中的线性回归模型?机器学习系列之线性回归基础篇
? 你真的了解分类模型评估指标都有哪些吗?【附Python代码实现】
? 一文带你用Python玩转决策树 ❤️画出决策树&各种参数详细说明❤️决策树的优缺点又有哪些?
? 开始学习机器学习时你必须要了解的模型有哪些?机器学习系列之决策树进阶篇
? 开始学习机器学习时你必须要了解的模型有哪些?机器学习系列之决策树基础篇
❤️ 以❤️简单易懂❤️的语言带你搞懂有监督学习算法【附Python代码详解】机器学习系列之KNN篇
? 开始学习机器学习之前你必须要了解的知识有哪些?机器学习系列入门篇

往期内容回顾

? 我和关注我的前1000个粉丝“合影”啦!收集前1000个粉丝进行了一系列数据分析,收获满满
? MySQL必须掌握的技能有哪些?超细长文带你掌握MySQL【建议收藏】
? Hive必须了解的技能有哪些?万字博客带你掌握Hive❤️【建议收藏】

关注我,了解更多相关知识!

CSDN@报告,今天也有好好学习

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/171745.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • vim 配置 clang-format[通俗易懂]

    vim 配置 clang-format[通俗易懂]vim配置clang-format

  • Python3.7模块之hashlib

    Python3.7模块之hashlibupdate()不支持将字符串对象引入,因为哈希在字节上工作,而不在字符上工作。所以update后面的括号里只能是字节(bytes)形式importhashlibmd=hashlib.md5()md.update(“你好”)md=md.hexdigest()print(md)出现以下错误:D:\PycharmProjects\untitled\venv\Scripts\pyt…

  • stm32 st_基于STM32

    stm32 st_基于STM32用了不少芯片,就只有51有位操作,这个特性很喜欢,赋值简单、效率又高且节省内存,不必为了一个bool去分配一个uint8.发现stm32有Bit-Banding,就试了一下,用MDK-ARM环境下的汇编代码做了一些比较。操作,清零USART1的SR寄存器的TC位:方法一://利用USART_TypeDef这个结构寻到SR的地址,再赋值USART1->SR&amp…

    2022年10月13日
  • plsqldev使用指南_plsql配置文件在哪儿

    plsqldev使用指南_plsql配置文件在哪儿plsqldev的配置plsqldev的安装需要这两个,可以在网上下载注意问题:1、Path变量中添加client的路径2、并且在plsqldev上配置这两个的路径,不需要登录,直接取消然后就可以进去这个了,然后点工具,首选项3、然后是新建目录,在这下面新建一个文件,里面写着这个文件的路径,以及数据库地址以及端口的配置4、tnsnames.ora的写法…

    2022年10月24日
  • linux中setfacl命令,Linux命令之:setfacl和getfacl

    linux中setfacl命令,Linux命令之:setfacl和getfacl命令总结之:setfacl和getfaclacl:accesscontrollist,实现灵活的权限管理除了文件的所有者,所属组合其他人,可以对更多的用户设置权限acl生效顺序:所有者、自定义用户、自定义组、其他人1、首先我们查看man帮助文档说明[root@centos7sixijie]#mansetfacl根据man文档节选出来几个我们会经常用到的功能和选项加以说明:setfacl…

  • spider crawled. red bottom shoes「建议收藏」

    Hewasamostnotoriousblasphemer,andhispoweroflanguagewassoextraordinarywhicheverybodyutilizedtod…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号