机器学习【二】————逻辑回归

本文介绍了逻辑回归的基本概念和与线性回归的区别,通过实例展示了如何使用逻辑回归解决分类问题。在二分类任务中,逻辑回归利用Sigmoid函数处理线性回归输出,适应0/1问题。通过增加数据量对比,说明逻辑回归在处理分类问题上的优势。同时,通过两个实例,分别演示了一阶和二阶逻辑回归在预测学生考试通过情况和芯片好坏检测中的应用,强调了在不同场景下选择合适模型的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


不会用LaTeX太痛苦啦QAQ,有时间一定要好好练习一下。4月了,各种事情都多了起来,希望自己能保持学习的热情,保持竞赛的热情

逻辑回归简介

一、逻辑回归的定义

简单来说, 逻辑回归(Logistic Regression)是一种用于解决二分类(0 or 1)问题的机器学习方法,用于估计某种事物的可能性。比如某用户购买某商品的可能性,某病人患有某种疾病的可能性,以及某广告被用户点击的可能性等。 注意,这里用的是“可能性”,而非数学上的“概率”,logisitc回归的结果并非数学定义中的概率值,不可以直接当做概率值来用。该结果往往用于和其他特征值加权求和,而非直接相乘。

二、逻辑回归与线性回归的关系

逻辑回归(Logistic Regression)与线性回归(Linear Regression)都是一种广义线性模型(generalized linear model)。逻辑回归假设因变量 y 服从伯努利分布,而线性回归假设因变量 y 服从高斯分布。 因此与线性回归有很多相同之处,去除Sigmoid映射函数的话,逻辑回归算法就是一个线性回归。可以说,逻辑回归是以线性回归为理论支持的,但是逻辑回归通过Sigmoid函数引入了非线性因素,因此可以轻松处理0/1分类问题。

下面通过实际例子来说明二者的区别

  • 分类任务:根据余额判断小明是否会去看电影

在这里插入图片描述

1.使用线性回归

这里我们建立一个基础框架
在这里插入图片描述
y=0时为负样本,则不去看电影
y=1时为正样本,则去看电影
对数据进行训练,很容易能得出一个线性方程(线性运算可看这里:线性方程求法)
在这里插入图片描述
对于这组数据我们进行如下总结
在这里插入图片描述
总结后发现,欸!好像预测的数据很准确耶,基本都预测对了。别激动,我们尝试增大数据量看看。

在这里插入图片描述
可以看出,当数据量增大后,直线的截距变小,预测开始出现错误,这时我们需要一个更准确的方法来处理数据。这时对于这类0/1的二分法就可以使用逻辑回归

2. 逻辑回归

在这里插入图片描述
我们再用大的数据进行预测,如余额为-10和100时代入计算
在这里插入图片描述
可以看出即使数据变的很大,但预测结果依旧比较准确,这就是在0/1分类问题上逻辑回归的优势之处
当然,分类任务也会有更复杂的情况,这里我们将e^(-x)中的x换成g(x),而g(x)可以根据你需要的决策边界选择方程,如下图:

  • 直线方程

在这里插入图片描述

  • 曲线方程
    在这里插入图片描述
    当然后面也还可以有x3等等形成更高维度的预测。
    对于线性回归方程,我们求解最小化损失函数J:
    在这里插入图片描述
    但对于逻辑回归函数而言,分类,标签,预测结果都是离散数据,使用上面的损失函数无法求取极小值点。对于逻辑回归有另外的最小化损失函数J:
    在这里插入图片描述

三、实例一

学生各有2门考试成绩,通过数据训练,并预测学生exam1=75,exam2=60时是否能通过考试。比较一阶和二阶边界曲线的准确度
在这里插入图片描述

  • 代码内容:
import pandas as pd
import numpy as np
data = pd.read_csv('exam_data.csv')         #读取数据
data.head()

from matplotlib import pyplot as plt
figl = plt.figure()
mask = data.loc[:,'Pass'] == 1
plt.scatter(data.loc[:,'Exam1'][mask],data.loc[:,'Exam2'][mask])
plt.scatter(data.loc[:,'Exam1'][~mask],data.loc[:,'Exam2'][~mask],marker = '^')
plt.title('Exam1-Exma2')
plt.xlabel('Exam1')
plt.ylabel('Exam2')
plt.show()                                  #画出原数据散点图

X = data.drop(['Pass'],axis=1)
y = data.loc[:,'Pass']
y.head()
X.head()

from sklearn.linear_model import LogisticRegression
LR = LogisticRegression()                   #建立逻辑回归模型
LR.fit(X,y)
y_predict = LR.predict(X)
from sklearn.metrics import accuracy_score
accuracy = accuracy_score(y,y_predict)         #看准确度
print(accuracy)

y_test = LR.predict([[75,60]])              #预测新数据
print(y_test)
print('Passed' if y_test == 1 else 'falsed')

theta0 = LR.intercept_
theta1, theta2 = LR.coef_[0][0],LR.coef_[0][1]
X1 = data.loc[:,'Exam1']
X2 = data.loc[:,'Exam2']
X1.head()
X2_new = -(theta0+theta1*X1)/theta2     #求出x1和x2的边界曲线
print(X2_new)

fig4 = plt.figure()
plt.scatter(data.loc[:,'Exam1'][mask],data.loc[:,'Exam2'][mask])
plt.scatter(data.loc[:,'Exam1'][~mask],data.loc[:,'Exam2'][~mask])     #原数据散点图
plt.plot(X1,X2_new)										#画出边界曲线
plt.title('Exam1-Exam2')
plt.xlabel('Exam1')
plt.ylabel('Exam2')
plt.show()
  • 代码解析:
    提示:对于建立模型以及读取数据等已在上一篇文章解释过了,这里主要解析逻辑回归函数的求解
figl = plt.figure()
mask = data.loc[:,'Pass'] == 1
plt.scatter(data.loc[:,'Exam1'][mask],data.loc[:,'Exam2'][mask])
plt.scatter(data.loc[:,'Exam1'][~mask],data.loc[:,'Exam2'][~mask],marker = '^')
plt.title('Exam1-Exma2')
plt.xlabel('Exam1')
plt.ylabel('Exam2')
plt.show()                                  #画出原数据散点图

这里先画出原数据图,mask是检索Pass这一行的值,其作用是用来区分通过考试和不通过考试的数据,下面两个plt.scatter函数里,第一个函数用[mask],意味只画出mask==1的数据,也就是Pass = 1的情况。而第二个[~mask]是只画出 ~mask=1的数据,也就是Pass=0的情况

在这里插入图片描述

theta0 = LR.intercept_
theta1, theta2 = LR.coef_[0][0],LR.coef_[0][1]
X1 = data.loc[:,'Exam1']
X2 = data.loc[:,'Exam2']
X1.head()
X2_new = -(theta0+theta1*X1)/theta2     #求出x1和x2的边界曲线
print(X2_new)

我们先求解一阶方程,上面提及一阶方程为g(x)=θ0+θ1X1+θ2X2。当我们建立了Logistic Regression模型后,我们可以读取训练出来的方程系数,intercept_是截距,也就是θ0。coef_[][]则是θ1,θ2…。最后求解出边界曲线。
在这里插入图片描述
很容易看出有一些数据的分类还是不精确,这时我们可以建立二阶方程来提高准确度。

data = pd.read_csv('exam_data.csv')
data.head()
X1 = data.loc[:,'Exam1']
X2 = data.loc[:,'Exam2']
y = data.loc[:,'Pass']
X1_2 = X1*X1
X2_2 = X2*X2
X1_X2 = X1*X2
X_new = {'X1':X1, 'X2':X2, 'X1_2':X1_2, 'X2_2':X2_2, 'X1_X2':X1_X2}
X_new = pd.DataFrame(X_new)
print(X_new)

建立了二阶方程,则要引入θ3和θ4,二阶方程的求解可以用求根公式。这里要特别注意一下对x1进行排序,因为这是二阶方程,如果是一阶方程是一条直线,对先后顺序没那么讲究,因为怎么都是连出一条直线。但二阶不一样,二阶是一条曲线,如果不先排序计算,可能出现先算出x大的数据,再算x小的数据,又算x大的数据,来来回回连线会导致线特别乱。只需要排序好一个,另一个是根据排序好的计算出的。

  • 不排序结果
    在这里插入图片描述
theta0 = LR2.intercept_
theta1, theta2, theta3, theta4, theta5 = LR2.coef_[0][0],LR2.coef_[0][1],LR2.coef_[0][2],LR2.coef_[0][3],LR2.coef_[0][4]
X1_new = X1.sort_values()     #对x1进行排序
print(X1,X1_new)

a = theta4
b = theta5*X1_new+theta2
c = theta0 + theta1*X1_new + theta3*X1_new*X1_new
X2_new_boundary = (-b+np.sqrt(b*b-4*a*c))/(2*a)     #求根公式

mask=y==1
fig5 = plt.figure()
passed = plt.scatter(data.loc[:,'Exam1'][mask],data.loc[:,'Exam2'][mask])
failed = plt.scatter(data.loc[:,'Exam1'][~mask],data.loc[:,'Exam2'][~mask])
plt.plot(X1_new,X2_new_boundary)   #画出边界曲线
plt.title('Exam1-Exam2')
plt.xlabel('Exam1')
plt.ylabel('Exam2')
plt.legend((passed,failed),('passed','failed'))
plt.plot(X1_new,X2_new_boundary,'r-')
plt.show()

在这里插入图片描述

四、实例二

基于数据检测芯片的好坏,建立二阶逻辑回归模型

代码如下:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

data = pd.read_csv('chip_test.csv')  #读取数据
data.head()                 
X1 = data.loc[:,'test1']
X2 = data.loc[:,'test2']
y = data.loc[:,'pass']
X1_2 = X1*X1
X2_2 = X2*X2
X1_X2 = X1*X2
X_new = {'X1':X1, 'X2':X2, 'X1_2':X1_2, 'X2_2':X2_2, 'X1_X2':X1_X2}
X_new = pd.DataFrame(X_new)
print(X_new)

from sklearn.linear_model import LogisticRegression
LR2 = LogisticRegression()          #建立逻辑回归模型
LR2.fit(X_new,y)
X1_new = X1.sort_values()

X2_boundary1 = []
X2_boundary2 = []
X2_boundary3 = []
X2_boundary4 = []

def f(x):
    theta0 = LR2.intercept_
    theta1,theta2,theta3,theta4,theta5 = LR2.coef_[0][0],LR2.coef_[0][1],LR2.coef_[0][2],LR2.coef_[0][3],LR2.coef_[0][4]
    a = theta4
    b = theta5*x+theta2
    c = theta0 + theta1*x + theta3*x*x
    X2_new_boundary = (-b+np.sqrt(b*b-4*a*c))/(2*a)
    X2_new_boundary2 = (-b-np.sqrt(b*b-4*a*c))/(2*a)
    return X2_new_boundary,X2_new_boundary2

# X1_range = [-1+x/10000 for x in range(0,20000)]     #扩大x的范围
# X1_range = np.array(X1_range)

for x in X1_new:
    X2_boundary1.append(f(x)[0])
    X2_boundary2.append(f(x)[1])
# for x in X1_range:
    
#     X2_boundary3.append(f(x)[0])
#     X2_boundary4.append(f(x)[1])
mask = y == 1

fig5 = plt.figure()           #画非完整曲线
passed = plt.scatter(data.loc[:,'test1'][mask], data.loc[:,'test2'][mask])
failed = plt.scatter(data.loc[:,'test1'][~mask], data.loc[:,'test2'][~mask])
plt.title('test1-test2')
plt.xlabel('test1')
plt.ylabel('test2')
plt.legend((passed,failed),('passed','failed'))
plt.plot(X1_new,X2_boundary1)
plt.plot(X1_new,X2_boundary2)

# fig4 = plt.figure()         #画完整曲线
# passed = plt.scatter(data.loc[:,'test1'][mask], data.loc[:,'test2'][mask])
# failed = plt.scatter(data.loc[:,'test1'][~mask], data.loc[:,'test2'][~mask])
# plt.title('test1-test2')
# plt.xlabel('test1')
# plt.ylabel('test2')
# plt.legend((passed,failed),('passed','failed'))
# plt.plot(X1_range,X2_boundary3)
# plt.plot(X1_range,X2_boundary4)
  • 代码解析:
    首先我们可以把数据分类后展示到散点图看看
data = pd.read_csv('chip_test.csv')  #读取数据
data.head()  
...
...
passed = plt.scatter(data.loc[:,'test1'][mask], data.loc[:,'test2'][mask])
failed = plt.scatter(data.loc[:,'test1'][~mask], data.loc[:,'test2'][~mask])
...

在这里插入图片描述
可以看出这次的分类类似一个圆形,立即想到要用二阶方程。
于是我们边开始定义二阶方程和系数

data = pd.read_csv('chip_test.csv')  #读取数据
data.head()                 
X1 = data.loc[:,'test1']
X2 = data.loc[:,'test2']
y = data.loc[:,'pass']
X1_2 = X1*X1
X2_2 = X2*X2
X1_X2 = X1*X2
X_new = {'X1':X1, 'X2':X2, 'X1_2':X1_2, 'X2_2':X2_2, 'X1_X2':X1_X2}
X_new = pd.DataFrame(X_new)

将定义好的系数使用DataFrame合并数据

  • pd.DataFrame(X_new)
    在这里插入图片描述
    定义一个函数,对数据依次进行计算求解,每一组数据使用求根公式都会算出2个根,对应到图上就是上下两个边界
def f(x):
    theta0 = LR2.intercept_
    theta1,theta2,theta3,theta4,theta5 = LR2.coef_[0][0],LR2.coef_[0][1],LR2.coef_[0][2],LR2.coef_[0][3],LR2.coef_[0][4]
    a = theta4
    b = theta5*x+theta2
    c = theta0 + theta1*x + theta3*x*x
    X2_new_boundary = (-b+np.sqrt(b*b-4*a*c))/(2*a)
    X2_new_boundary2 = (-b-np.sqrt(b*b-4*a*c))/(2*a)
    return X2_new_boundary,X2_new_boundary2

将数据依次送入求解

for x in X1_new:
    X2_boundary1.append(f(x)[0])
    X2_boundary2.append(f(x)[1])

求解完成后,画出曲线和散点图
在这里插入图片描述
可以看出数据大致分好类了,但是图像的左右两边有缺口,这是x的数据量比较小的缘故,为了补上缺口,我们可以将x的数据量加大。

X1_range = [-1+x/10000 for x in range(0,20000)]     #扩大x的范围
X1_range = np.array(X1_range)

之后与上边一样进行求根计算,画图。即可以得到完整图像。
在这里插入图片描述


总结

逻辑回归相比于线性回归有很多相似之处,也是机器学习的重要基础之一,文章是我学习以后的小总结,作为机器学习的小白文章中或有错误的地方,如果大佬看见了还希望可以指出,有什么问题都可以在评论区留言或私信,大家一起进步!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值