二分类问题的解决利器:逻辑回归算法详解(一)

news2025/4/17 10:30:14

文章目录

  • 🍋引言
  • 🍋逻辑回归的原理
  • 🍋逻辑回归的应用场景
  • 🍋逻辑回归的实现

🍋引言

逻辑回归是机器学习领域中一种重要的分类算法,它常用于解决二分类问题。无论是垃圾邮件过滤、疾病诊断还是客户流失预测,逻辑回归都是一个强大的工具。本文将深入探讨逻辑回归的原理、应用场景以及如何在Python中实现它。

🍋逻辑回归的原理

逻辑回归是一种广义线性模型(Generalized Linear Model,简称GLM),它的目标是根据输入特征的线性组合来预测二分类问题中的概率。具体来说,逻辑回归通过使用Sigmoid函数(又称为Logistic函数)将线性输出映射到0到1之间的概率值。Sigmoid函数的数学表达式如下:

在这里插入图片描述
其中, P ( Y = 1 ∣ X ) P(Y=1|X) P(Y=1∣X) 表示在给定输入特征X的条件下,目标变量Y等于1的概率。 β 0 , β 1 , … , β n \beta_0, \beta_1, \ldots, \beta_n β0,β1,,βn 是模型的权重参数, X 1 , X 2 , … , X n X_1, X_2, \ldots, X_n X1,X2,,Xn 是输入特征。

逻辑回归的训练目标是找到最佳的权重参数,使得模型的预测结果与实际观测值尽可能一致。这通常通过最大化似然函数或最小化对数损失函数来实现。

🍋逻辑回归的应用场景

逻辑回归在各个领域都有广泛的应用,以下是一些常见的场景:

  • 垃圾邮件检测: 逻辑回归可以根据邮件的内容和特征来预测一封邮件是否是垃圾邮件。

  • 医学诊断: 在医学领域,逻辑回归可以用于预测患者是否患有某种疾病,基于患者的临床特征和实验室检测结果。

  • 金融风险管理: 逻辑回归可用于评估客户违约的概率,帮助银行和金融机构做出信贷决策。

  • 社交网络分析: 逻辑回归可以用于社交网络中的用户行为分析,例如预测用户是否会点击广告或关注某个话题。

🍋逻辑回归的实现

这里我们准备封装一个逻辑回归的py文件,命名为LogisticRegression.py
这里我们首先需要导入需要的库

from sklearn.metrics import accuracy_score
import numpy as np

accuracy_score函数用于计算分类模型的准确率,它是一个评估分类模型性能的常用指标。准确率表示正确分类的样本数量占总样本数量的比例。在机器学习中,通常希望模型的准确率越高越好,因为它衡量了模型对数据的分类能力。

之后我们定义一个LogisticRegression类,接下来的代码,我们将写在此类中
首先是初始化函数

def __init__(self):
        """初始化LinearRegression模型"""
        self.coef_ = None  # 系数
        self.interception_ = None  # 截距
        self._theta = None

self.coef_ = None
创建了一个对象属性coef_,并将其初始化为None。coef_通常用来存储线性回归模型的系数(也称为权重),这些系数用于预测目标变量。在初始化时,这些系数还没有被计算,因此被设置为None。

self.interception_ = None
创建了一个对象属性interception_,并将其初始化为None。interception_通常用来存储线性回归模型的截距,也就是模型在特征值为零时的预测值。在初始化时,截距也还没有被计算,因此被设置为None。

self._theta = None
最后一行代码创建了一个对象属性_theta,同样初始化为None。这个属性可能用于存储模型的参数(系数和截距),但是它以一个下划线 _ 开头,这通常表示该属性是类内部使用的,不应该直接被外部访问或修改。

之后我们定义一个逻辑回归特有的函数

def sigmoid(self, t):
        return 1 / (1 + np.exp(-t))

这个函数用来计算Sigmoid函数的值。Sigmoid函数的数学表达式如下:

在这里插入图片描述

其中, t t t 是输入参数。函数使用NumPy库中的np.exp()函数计算 e e e的负t次方,然后将1除以这个结果,得到Sigmoid函数的值。Sigmoid函数的输出范围是0到1之间,当 t t t趋向于正无穷时,Sigmoid函数趋近于1,而当 t t t趋向于负无穷时,Sigmoid函数趋近于0。这使得Sigmoid函数在二分类问题中常用于将线性输出映射到概率值。

之后我们定义fit函数用于训练模型,采用的方法是批量梯度下降来最小化逻辑回归的损失函数,从而找到最优的模型参数,这里我将进行详细说明

def fit(self, x_train, y_train, eta=0.01, n_iters=1e4, epsilon=1e-8):
        """根据给定的x_train和y_train 使用梯度下降法训练LogisticRegression模型"""

        def J(theta, X_b, y):  # 计算损失函数J的值,theta是参数
            y_hat = self.sigmoid(X_b.dot(theta))
            try:
                return -np.sum(y * np.log(y_hat) + (1 - y) * np.log(1 - y_hat)) / len(
                    X_b)  # 稍微有点理解迷糊,y真实减去y预测 平方,然后除以个数
            except:
                # 返回一个float的最大值
                return float('inf')

        def dJ(theta, X_b, y):  # theta是一个向量
            y_hat = self.sigmoid(X_b.dot(theta))
            return X_b.T.dot(y_hat - y) / len(X_b)

        def gradient_descent(X_b, y, initial_theta, eta, n_iters, epsilon):  # 传入一个最大迭代次数,1万
            theta = initial_theta
            iters = 0
            while iters < n_iters:
                gradient = dJ(theta, X_b, y)
                last_theta = theta
                theta = theta - gradient * eta
                if abs(J(theta, X_b, y) - J(last_theta, X_b, y)).all() < epsilon:  # 这里应该是all还是any?  结果好像是一样,不加会报错
                    break
                iters += 1
            return theta

        X_b = np.hstack([np.ones((len(x_train), 1)), x_train])
        # 根据给定的x_train计算出X_b
        initial_theta = np.zeros(X_b.shape[1])
        # 创建出一个空的theta向量
        self._theta = gradient_descent(X_b, y_train, initial_theta, eta, n_iters, epsilon)
        self.interception_ = self._theta[0]
        self.coef_ = self._theta[1:]
        return self

def fit(self, x_train, y_train, eta=0.01, n_iters=1e4, epsilon=1e-8):
这是fit方法的定义,它接受训练数据x_train和对应的目标变量y_train作为输入,还包括三个可选参数:eta(学习率,默认为0.01)、n_iters(最大迭代次数,默认为1万)、epsilon(用于判断收敛的小量值,默认为1e-8)。

def J(theta, X_b, y):
这是一个内部函数,用于计算损失函数的值。传入参数包括模型参数theta、带有偏置项的训练数据X_b,以及目标变量y。损失函数的定义使用了逻辑回归的交叉熵损失函数。

def dJ(theta, X_b, y):
这是另一个内部函数,用于计算损失函数关于参数theta的梯度。梯度是损失函数关于参数的导数,它告诉我们在当前参数值下,损失函数增加最快的方向。这里使用了逻辑回归的梯度计算公式。

def gradient_descent(X_b, y, initial_theta, eta, n_iters, epsilon):
这是用于执行梯度下降法的内部函数。它接受训练数据X_b、目标变量y、初始参数initial_theta、学习率eta、最大迭代次数n_iters以及收敛判定值epsilon。在循环中,它计算梯度并更新参数,直到满足停止条件(收敛或达到最大迭代次数)。

X_b = np.hstack([np.ones((len(x_train), 1)), x_train])
这一行代码创建了一个新的特征矩阵X_b,通过在训练数据前面添加一列全为1的列来实现,以处理截距项。

initial_theta = np.zeros(X_b.shape[1])
这一行代码创建了一个初始的参数向量initial_theta,并将其初始化为全零向量。

self._theta = gradient_descent(X_b, y_train, initial_theta, eta, n_iters, epsilon)
这一行代码调用了gradient_descent函数,使用梯度下降法来训练模型并获得最优的参数向量self._theta。

self.interception_ = self.theta[0]
self.coef
= self.theta[1:]
这两行代码将参数向量self.theta中的第一个元素作为截距项赋值给self.interception,将其余的元素作为系数赋值给self.coef

return self
最后,fit方法返回模型对象自身,以便进行链式操作。

这里我们再定义一个随机梯度下降

def fit_sgd(self, X_train, y_train, n_iters=5, t0=5, t1=50):  # 这里的n_iters代表 整个数据看几轮,不能取10000
        assert X_train.shape[0] == y_train.shape[0]

        def dJ_sgd(theta, X_b_i, y_i):  # 计算梯度,不需要m了,因为是随机挑选出一行数据
            return X_b_i.T.dot(X_b_i.dot(theta) - y_i) * 2

        def sgd(X_b, y, initial_theta, n_iters, t0=5, t1=50):  # 随机梯度下降法
            def learning_rate(t):
                return t0 / (t + t1)

            theta = initial_theta
            m = len(X_b)
            
            for cur_iter in range(n_iters):             
                random_indexs = np.random.permutation(m)  # 随机打乱样本
                X_b_new = X_b[random_indexs]
                y_new = y[random_indexs]
               
                for i in range(m):
                    gradient = dJ_sgd(theta, X_b_new[i], y_new[i])
                    theta = theta - gradient * learning_rate(cur_iter * m + i)
            return theta

        X_b = np.hstack([np.ones((len(X_train), 1)), X_train])
        initial_theta = np.random.randn(X_b.shape[1])
        self._theta = sgd(X_b, y_train, initial_theta, n_iters, t0=5, t1=50)
        self.interception_ = self._theta[0]
        self.coef_ = self._theta[1:]
def fit_sgd(self, X_train, y_train, n_iters=5, t0=5, t1=50):

这是fit_sgd方法的定义,与之前的方法不同,它使用随机梯度下降来训练模型。接受训练数据X_train和对应的目标变量y_train,以及可选的参数:n_iters(迭代轮数,默认为5,表示整个数据集会被遍历5次)、t0 和 t1(用于计算学习率的超参数,默认分别为5和50)。

assert X_train.shape[0] == y_train.shape[0]
这一行代码用于确保训练数据X_train和目标变量y_train的样本数量一致,以避免数据维度不匹配的问题。

def dJ_sgd(theta, X_b_i, y_i):
这是一个内部函数,用于计算随机梯度下降的梯度。传入参数包括模型参数 theta、一个样本的特征向量 X_b_i,以及对应的目标变量 y_i。梯度计算使用了逻辑回归的梯度公式,但仅针对单个样本。

def sgd(X_b, y, initial_theta, n_iters, t0=5, t1=50):
这是执行随机梯度下降的内部函数。它接受特征矩阵 X_b、目标变量 y、初始参数 initial_theta、迭代轮数 n_iters,以及学习率计算的超参数 t0 和 t1。

learning_rate(t) 是一个学习率调度函数,根据当前迭代轮数 t 来计算学习率。学习率在每轮迭代中都会发生变化,起初较大,后来逐渐减小,这有助于随机梯度下降的收敛。

随机梯度下降的主要循环包括迭代整个数据集 n_iters 次。在每次迭代中,首先对样本进行随机打乱(打乱顺序),然后遍历每个样本,计算梯度并更新参数。

X_b = np.hstack([np.ones((len(X_train), 1)), X_train])
这一行代码与之前类似,将原始特征矩阵 X_train 转换为带有截距项的特征矩阵 X_b。

initial_theta = np.random.randn(X_b.shape[1])
这一行代码创建了一个随机初始化的参数向量 initial_theta,用作随机梯度下降的起点。

self._theta = sgd(X_b, y_train, initial_theta, n_iters, t0=5, t1=50)
这一行代码调用了 sgd 函数来执行随机梯度下降,训练模型,并获取最优的参数向量 self._theta。

self.interception_ = self.theta[0]
self.coef
= self.theta[1:]
这两行代码将参数向量 self.theta 中的第一个元素作为截距项赋值给 self.interception,将其余的元素作为系数赋值给 self.coef

最后我们进行预测的处理

def predict_prob(self, X_predict):
        X_b = np.hstack([np.ones((len(X_predict), 1)), X_predict])
        return self.sigmoid(X_b.dot(self._theta))

    def predict(self, X_predict):
        return np.array(self.predict_prob(X_predict) >= 0.5, dtype='int')

    def score(self, x_predict, y_test):
        y_predict = self.predict(x_predict)
        return accuracy_score(y_test, y_predict)

    def __repr__(self):
        return "LogisticRegression()"

predict_prob(self, X_predict):
这个方法用于对输入的特征数据 X_predict 进行预测,并返回预测的概率值。首先,它将输入数据 X_predict 扩展为带有截距项的特征矩阵 X_b,然后使用模型的参数 _theta 和 sigmoid 函数来计算每个样本的概率值。这个方法返回的是每个样本属于正类别的概率值,范围在0到1之间。

predict(self, X_predict):
这个方法使用 predict_prob 方法返回的概率值来进行二分类预测。它将概率值与阈值0.5进行比较,如果概率值大于等于0.5,则预测为正类别(1),否则预测为负类别(0)。返回的结果是一个包含0和1的数组,表示每个样本的预测类别。

score(self, x_predict, y_test):
这个方法用于评估模型的性能。它接受输入数据 x_predict 和对应的真实目标变量 y_test,并使用 predict 方法来进行预测。然后,它计算模型的准确率(Accuracy)分数,通过与真实标签进行比较来确定模型的预测精度。最终,这个方法返回模型的准确率作为性能评估的指标。

repr(self):
这是一个特殊方法,用于定义模型对象的字符串表示。当您创建模型对象并尝试打印它时,将返回该字符串,以便更好地描述模型。在这里,字符串表示简单地返回了 “LinearRegression()”,表示这是一个线性回归模型。


接下来我们用鸢尾花数据进行实践一下
首先还是导入库

from sklearn.datasets import load_iris
from LogisticRegression import LogisticRegression
import numpy as np

之后做一些前期数据选择,分割数据集的准备

iris = load_iris()
y = iris.target
X = iris.data[y<2,:2]
y = y[y<2]
plt.scatter(X[y==0,0],X[y==0,1])
plt.scatter(X[y==1,0],X[y==1,1])
plt.show()
X_train,X_test,y_train,y_test = train_test_split(X,y)

运行结果如下
在这里插入图片描述
之后我们进行拟合预测

log_reg = LogisticRegression()
log_reg.fit(X_train,y_train)
log_reg.score(X_test,y_test)

运行结果如下
在这里插入图片描述
之后我们创建一个用于可视化模型决策会边界的函数

def x2(clf,x1):
    return (-clf.interception_-x1*clf.coef_[0])/clf.coef_[1]

并绘制图像

x_plot = np.linspace(4,7,100)
y_plot = x2(log_reg,x_plot)
plt.plot(x_plot,y_plot,color='r')
plt.scatter(X[y==0,0],X[y==0,1])
plt.scatter(X[y==1,0],X[y==1,1])
plt.show()

plt.scatter(X[y == 0,0], X[y == 0,1]) 和 plt.scatter(X[y == 1,0], X[y == 1,1]):
这两行代码用于绘制数据点的散点图。第一行绘制了属于类别0的数据点,第二行绘制了属于类别1的数据点。这样,你可以在图中看到不同类别的数据点的分布情况。

运行结果如下
在这里插入图片描述
接下来我们用测试集来演示一下

plt.plot(x_plot,y_plot,color='r')
plt.scatter(X_test[y_test==0,0],X_test[y_test==0,1])
plt.scatter(X_test[y_test==1,0],X_test[y_test==1,1])
plt.show()

在这里插入图片描述

请添加图片描述

挑战与创造都是很痛苦的,但是很充实。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1029595.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

git安装配置教程

目录 git安装配置1. 安装git2. git 配置3.生成ssh key:4. 获取生产的密钥3. gitee或者github添加ssh-key4.git使用5. git 使用-本地仓库与远程仓库建立连接第一步&#xff1a;进入项目文件夹&#xff0c;初始化本地仓库第二步&#xff1a;建立远程仓库。 建立远程连接的小技巧 …

strcpy常见的错误

char* arr "handsome"; strcpy(arr, "pretty"); printf("%s\n", arr); 这个程序在编译器上是运行不出来的&#xff0c;因为arr是一个字符串指针&#xff0c;它的值不可以被修改&#xff0c;可以将arr改成字符数组

录屏没有声音怎么办,3个方法教你解决

随着科技的不断发展&#xff0c;人们越来越依赖电子设备进行工作和学习。在这个过程中&#xff0c;录屏已经成为了一种必要的技能。无论是手机还是电脑&#xff0c;我们都可以通过录屏来记录重要的信息。但是&#xff0c;有时候我们在录屏时会发现声音无法正常录制&#xff0c;…

前后端分离的低代码快速开发框架

低代码开发正逐渐成为企业创新的关键工具。通过提高开发效率、降低成本、增强灵活性以及满足不同用户需求&#xff0c;低代码开发使企业能够快速响应市场需求&#xff0c;提供创新解决方案。选择合适的低代码平台&#xff0c;小成本组建一个专属于你的应用。 项目简介 这是一个…

竞赛 基于深度学习的人脸识别系统

前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 基于深度学习的人脸识别系统 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学长非常推荐&#xff01; &#x1f9ff; 更多资料, 项目分享&#xff1a; https://gitee.com/dancheng-senior/…

spring security教程(一)--认证

零.简介 【1】简介 【2】登录校验流程 【3】原理&#xff08;入门的时候先了解一下就好&#xff09; 一.思路分析 二.建表 确保你已经建立好一张用户表&#xff0c;并且引入springboot&#xff0c;mybatis&#xff0c;mp,slf4j等基础依赖。 即使你有多个角色你也可以将他们的…

安装社区版本OB

获取一键安装包 https://www.oceanbase.com/softwarecenter 离线安装 [admintest001 ~]$ tar -xzf oceanbase-all-in-one-*.tar.gz [admintest001 ~]$ cd oceanbase-all-in-one/bin/ [admintest001 bin]$ ./install.sh [admintest001 bin]$ source ~/.oceanbase-all-in-one/…

【人工智能】企业如何使用 AI与人工智能的定义、研究价值、发展阶段的深刻讨论

前言 人工智能&#xff08;Artificial Intelligence&#xff09;&#xff0c;英文缩写为AI。 它是研究、开发用于模拟、延伸和扩展人的智能的理论、方法、技术及应用系统的一门新的技术科学。人工智能是新一轮科技革命和产业变革的重要驱动力量。 &#x1f4d5;作者简介&#x…

stm32学习-芯片系列/选型/开发方式

【03】STM32HAL库开发-初识STM32 | STM概念、芯片分类、命名规则、选型 | STM32原理图设计、看数据手册、最小系统的组成 、STM32IO分配_小浪宝宝的博客-CSDN博客  STM32&#xff1a;ST是意法半导体&#xff0c;M是MCU/MPU&#xff0c;32是32位。  ST累计推出了&#xff1a…

【NCRE 二级Java语言程序设计03】考试环境及考试过程概览

目录 前言一、考试环境介绍1.硬件环境2.软件环境 二、考试特别说明1.考试时间说明2.考试题型及分值 三、考试流程介绍1.登录考试系统2.考试答题界面3.答题交卷操作 总结 前言 &#x1f4dc;本专栏主要是分享自己备考全国计算机二级Java语言程序设计所学心得体会、所搜集的资料信…

CTF —— 网络安全大赛(这不比王者好玩吗?)

前言 随着大数据、人工智能的发展&#xff0c;人们步入了新的时代&#xff0c;逐渐走上科技的巅峰。 \ ⚔科技是一把双刃剑&#xff0c;网络安全不容忽视&#xff0c;人们的隐私在大数据面前暴露无遗&#xff0c;账户被盗、资金损失、网络诈骗、隐私泄露&#xff0c;种种迹象…

大数据快速入门开发环境篇:CentOS 7安装配置Hadoop大数据框架开发环境

注意&#xff1a;在开始安装之前&#xff0c;请确保您的CentOS 7系统已经正确安装和配置了Java。Hadoop需要Java来运行。 目录 一、下载与配置Hadoop框架&#xff1a;1.1、下载与环境变量设置1.2、XML配置文件Hadoop设置1.3、格式化HDFS 二、Hadoop 3.x版本中hdfs命令的问题解…

使用命令行(CMD)编译单Java文件

1.安装JDK JDK官网&#xff1a;https://www.oracle.com/java/technologies/downloads/ 选 Windows -> x64 MSI Instaler或者x64 Installer 安装成功后。 2.配置环境变量 按下Win键&#xff0c;搜索环境变量 添加JAVA_HOME系统环境变量&#xff0c;要指定类似这样的路径(…

day1_QT

day1_QT 实现登录窗口效果 实现登录窗口 #include "loginwindow.h"LoginWindow::LoginWindow(QWidget *parent): QWidget(parent) {//设置窗口标题和图标this->setWindowTitle("ChatWe");this->setWindowIcon(QIcon("D:\\learn\\QT\\day1\\wor…

RT-Thread UART设备

UART UART&#xff08;Universal Asynchronous Receiver/Trasmitter&#xff09;通用异步收发器&#xff0c;UART作为异步串口通信协议的一种&#xff0c;工作原理是将传输数据的每个字符一位接一位地传输。是在应用程序开发过程中使用频率最高的数据总线。 UART串口的特点是…

使用格式工厂转换影片的默认音轨

不少电影尤其是mkv格式的都是英国双语的音轨&#xff0c;如图&#xff1a; 一般默认的是第一个English。有需求让它默认是国语的。 一、打开格式工厂 &#xff0c;选择视频格式&#xff0c;选择添加文件&#xff0c;选择输出配置 二、找到音频流索引 对应本文实例电影的音频顺…

成集云 | 金蝶云星辰集成聚水潭ERP(金蝶云星辰主管供应链)| 解决方案

源系统成集云目标系统 方案介绍 金蝶云星辰是金蝶旗下的一款企业级SaaS管理云&#xff0c;其目标是帮助企业拓客开源、智能管理和实时决策。为了实现这一目标&#xff0c;它为企业提供了多种SaaS服务&#xff0c;包括财务云、税务云、进销存云、生产云、零售云、电商…

C++项目:仿mudou库实现高性能高并发服务器

文章目录 一、实现目标二、前置知识&#xff08;一&#xff09;HTTP服务器1.概念2.Reactor模型&#xff1a;3.分类 一、实现目标 仿muduo库One Thread One Loop式主从Reactor模型实现高并发服务器&#xff1a; 通过咱们实现的高并发服务器组件&#xff0c;可以简洁快速的完成⼀…

Hive部署,hive客户端

1、Hive部署 Hive是分布式运行的框架还是单机运行的&#xff1f; Hive是单机工具&#xff0c;只需要部署在一台服务器即可。Hive虽然是单机的&#xff0c;但是它可以提交分布式运行的MapReduce程序运行。 1.1、规划 我们知道Hive是单机工具后&#xff0c;就需要准备一台服务…

AI聊天ChatGPT系统源码卡密验证开源版

ChatGPT卡密验证版源码是一个基于PHP7.4和MySQL5.6的聊天AI源码&#xff0c;它不仅支持暗黑模式、反应速度极快&#xff0c;而且充值方面采用后台生成卡密方式&#xff0c;方便快捷&#xff0c;如果您有能力将其接入在线支付&#xff0c;即可进一步拓展充值方式&#xff0c;为更…