逻辑回归以及python实现

目录

一、逻辑回归模型结构

1.1 基本概念

二、逻辑回归的算法原理

2.1 分类目标

2.2 最大似然估计

2.3 损失函数

三、算法实现


一、逻辑回归模型结构

1.1 基本概念

  • 定义与组成机器学习中的一种分类算法,它基于线性回归模型,并通过引入非线性的logistic函数(通常是Sigmoid函数)来实现分类的目的。逻辑回归是一种用于解决二分类问题的模型,它将线性回归的输出通过Sigmoid函数映射到0和1之间。这样,逻辑回归的输出就可以被解释为一个概率值,表示某个事件发生的可能性。
  • 数学表达:在线性回归的基础上,逻辑回归通过应用Sigmoid函数来限制输出值的范围。Sigmoid函数是一个典型的逻辑函数,它可以将输入的实数值压缩到(0,1)区间内,从而完成对分类结果的概率化表达。
  • Sigmoid函数:\frac{1}{1+e_{}^{-x}}\frac{1}{1+e_{}^{-x}}

二、逻辑回归的算法原理

逻辑回归利用Sigmoid函数将线性回归的输出转换为分类任务需要的(0,1)区间内的概率值。Sigmoid函数表达式为 𝑔(𝑧)=\frac{1}{1+e_{}^{-x}},其中 𝑧 是线性组合 ^{w_{}^{T}}𝑥+𝑏,𝑤 和 𝑏 分别是权重向量和偏置项。

2.1 分类目标

逻辑回归的目标是找到一组参数(权重和偏置),使得模型对数据分类的预测概率最大化地接近真实标签。

2.2 最大似然估计

基本概念:

在逻辑回归中,最大似然估计用于估计模型参数,使得模型最好地拟合观测数据。这涉及到构建一个似然函数,它是所有数据点概率密度函数的乘积,然后求解这个函数的最大值对应的参数值。

构造:

在逻辑回归中,每个样本点的输出可以被看作是一个伯努利随机变量,即0-1分布。因此,整个数据集的似然函数可以表示为所有样本点概率的乘积。具体来说,如果yi​是第i个样本的实际类别标签,p(yi​)是模型预测该样本属于该类别的概率,则似然函数𝐿(𝜃)L(θ)可以表示为𝐿(w)=\prod_{i=1}^{n}^{p(zi)_{}^{yi}}^{(1-p(zi))_{}^{1-yi}},其中zi是第i个样本的线性组合,yi是对应的类别标签(0或1)。

优化:

 最大化似然函数使用梯度下降算法来更新模型的权重。梯度下降法是一种用于优化逻辑回归模型参数的流行算法,其核心思想是利用函数的梯度(或斜率)来确定参数更新的方向。梯度指示了函数增长最快的方向,因此在优化过程中,我们沿着梯度的相反方向(下降最快的方向)调整参数,以寻找函数的最小值。

2.3 损失函数

 为了求解模型的最优参数,我们首先要找到合适的损失函数,并极小化损失函数,当损失最小时,此时的参数就是最优参数。我们首先想到的是线性回归所使用的损失函数,即均方误差:
L ( w ) =\frac{1}{2}\sum_{i=1}^{N}​ (\sigma(\boldsymbol{x}_i)-y_i)^2

但是逻辑回归处理的是分类问题,y i 不是0就是1,而不是线性回归中的连续的数,所以均方误差在这里可能是一个非凸函数,则如下图所示,图片来源于吴恩达的机器学习课程的笔记,图中的J(θ)为损失函数。这就意味着损失函数有很多局部最小值,无法确保能通过梯度下降算法找到全局最优值。

 

所以均方误差将不适用于逻辑回归模型。

  实际上,逻辑回归使用对数损失函数,其形式为

L(w)=-\frac{1}{n}\prod_{i=1}^{n}[𝑦𝑖log⁡(𝑝(z𝑖))+(1−𝑦𝑖)log⁡(1−𝑝(z𝑖))]

其中zi是第i个样本的线性组合,yi是对应的类别标签(0或1),𝑝(𝑦𝑖)=𝜎(^{w_{}^{T}}𝑥𝑖+𝑏),σ是Sigmoid函数。

三、算法实现

以下代码实现了一个简单的逻辑回归模型,用于对鸢尾花数据集进行二分类

1.导入所需的库和模块:

import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split

numpy: 常用的数据库

matplotlib:绘图使用

sklearn.datasets:导入训练需要的数据集

train_test_split:划分训练集和测试集

2.设置随机种子:

seed_value = 2024
np.random.seed(seed_value)
为了确保实验结果的可重复性,设定了一个随机种子,使得代码运行之后得到的随机结果相同。这样可以消除随带来的误差和不确定性,使得实验更加准确。

3.定义Sigmoid激活函数:

def sigmoid(z):
    return 1 / (1 + np.exp(-z))
Sigmoid函数是逻辑回归中常用的激活函数,它将输入值映射到0和1之间。

4.定义逻辑回归类:

class LogisticRegression:
    def __init__(self, learning_rate=0.003, iterations=100):
        self.learning_rate = learning_rate # 学习率
        self.iterations = iterations # 迭代次数

 定义了一个名为LogisticRegression的类,包含初始化方法,用于设置学习率和迭代次数。

5.定义fit方法

    def fit(self, X, y):
        # 初始化参数
        self.weights = np.random.randn(X.shape[1])
        self.bias = 0

        # 梯度下降
        for i in range(self.iterations):
            # 计算sigmoid函数的预测值, y_hat = w * x + b
            y_hat = sigmoid(np.dot(X, self.weights) + self.bias)

            # 计算损失函数
            loss = (-1 / len(X)) * np.sum(y * np.log(y_hat) + (1 - y) * np.log(1 - y_hat))

            # 计算梯度
            dw = (1 / len(X)) * np.dot(X.T, (y_hat - y))
            db = (1 / len(X)) * np.sum(y_hat - y)

            # 更新参数
            self.weights -= self.learning_rate * dw
            self.bias -= self.learning_rate * db

            # 打印损失函数值
            if i % 10 == 0:
                print(f"Loss after iteration {i}: {loss}")
fit方法用于训练模型,通过梯度下降法更新参数。在每次迭代中,计算损失函数和梯度,并更新权重和偏置。

6.定义predict方法

    def predict(self, X):
        y_hat = sigmoid(np.dot(X, self.weights) + self.bias)
        y_hat[y_hat >= 0.5] = 1
        y_hat[y_hat < 0.5] = 0
        return y_hat
predict方法用于预测新的数据点,将输入数据通过训练好的模型进行预测。

7.定义score方法

    def score(self, y_pred, y):
        accuracy = (y_pred == y).sum() / len(y)
        return accuracy
score方法用于计算模型的准确率。

8.导入数据并进行预处理

iris = load_iris()
X = iris.data[:, :2]
y = (iris.target != 0) * 1

从sklearn.datasets中加载鸢尾花数据集,只使用前两个特征(花瓣长度和宽度),并将目标变量转换为二分类问题(0表示非鸢尾花,1表示鸢尾花)。

9.划分训练集和测试集

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.15, random_state=seed_value)
使用train_test_split函数将数据集划分为训练集和测试集。

10.训练模型

model = LogisticRegression(learning_rate=0.03, iterations=1000)
model.fit(X_train, y_train)

11.评估模型

y_train_pred = model.predict(X_train)
y_test_pred = model.predict(X_test)

score_train = model.score(y_train_pred, y_train)
score_test = model.score(y_test_pred, y_test)

print('训练集Accuracy: ', score_train)
print('测试集Accuracy: ', score_test)
使用训练好的模型对训练集和测试集进行预测,并计算准确率。

12.可视化决策边界

x1_min, x1_max = X[:, 0].min() - 0.5, X[:, 0].max() + 0.5
x2_min, x2_max = X[:, 1].min() - 0.5, X[:, 1].max() + 0.5
xx1, xx2 = np.meshgrid(np.linspace(x1_min, x1_max, 100), np.linspace(x2_min, x2_max, 100))
Z = model.predict(np.c_[xx1.ravel(), xx2.ravel()])
Z = Z.reshape(xx1.shape)
plt.contourf(xx1, xx2, Z, cmap=plt.cm.Spectral)
plt.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.Spectral)
plt.xlabel("Sepal length")
plt.ylabel("Sepal width")
plt.show()
使用matplotlib绘制鸢尾花数据集的散点图,并在其上绘制决策边界。

完整代码:

import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split

# 设置随机种子
seed_value = 2024
np.random.seed(seed_value)

# Sigmoid激活函数
def sigmoid(z):
    return 1 / (1 + np.exp(-z))

# 定义逻辑回归算法
class LogisticRegression:
    def __init__(self, learning_rate=0.003, iterations=100):
        self.learning_rate = learning_rate # 学习率
        self.iterations = iterations # 迭代次数

    def fit(self, X, y):
        # 初始化参数
        self.weights = np.random.randn(X.shape[1])
        self.bias = 0

        # 梯度下降
        for i in range(self.iterations):
            # 计算sigmoid函数的预测值, y_hat = w * x + b
            y_hat = sigmoid(np.dot(X, self.weights) + self.bias)

            # 计算损失函数
            loss = (-1 / len(X)) * np.sum(y * np.log(y_hat) + (1 - y) * np.log(1 - y_hat))

            # 计算梯度
            dw = (1 / len(X)) * np.dot(X.T, (y_hat - y))
            db = (1 / len(X)) * np.sum(y_hat - y)

            # 更新参数
            self.weights -= self.learning_rate * dw
            self.bias -= self.learning_rate * db

            # 打印损失函数值
            if i % 10 == 0:
                print(f"Loss after iteration {i}: {loss}")

    # 预测
    def predict(self, X):
        y_hat = sigmoid(np.dot(X, self.weights) + self.bias)
        y_hat[y_hat >= 0.5] = 1
        y_hat[y_hat < 0.5] = 0
        return y_hat
    
    # 精度
    def score(self, y_pred, y):
        accuracy = (y_pred == y).sum() / len(y)
        return accuracy

# 导入数据
iris = load_iris()
X = iris.data[:, :2]
y = (iris.target != 0) * 1

# 划分训练集、测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.15, random_state=seed_value)

# 训练模型
model = LogisticRegression(learning_rate=0.03, iterations=1000)
model.fit(X_train, y_train)

# 结果
y_train_pred = model.predict(X_train)
y_test_pred = model.predict(X_test)

score_train = model.score(y_train_pred, y_train)
score_test = model.score(y_test_pred, y_test)

print('训练集Accuracy: ', score_train)
print('测试集Accuracy: ', score_test)

# 可视化决策边界
x1_min, x1_max = X[:, 0].min() - 0.5, X[:, 0].max() + 0.5
x2_min, x2_max = X[:, 1].min() - 0.5, X[:, 1].max() + 0.5
xx1, xx2 = np.meshgrid(np.linspace(x1_min, x1_max, 100), np.linspace(x2_min, x2_max, 100))
Z = model.predict(np.c_[xx1.ravel(), xx2.ravel()])
Z = Z.reshape(xx1.shape)
plt.contourf(xx1, xx2, Z, cmap=plt.cm.Spectral)
plt.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.Spectral)
plt.xlabel("Sepal length")
plt.ylabel("Sepal width")
plt.show()

运行结果:

 

 

  • 33
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值