机器学习第五章:逻辑回归

一、引言

        在了解逻辑回归之前,要先认识到什么是回归问题,什么又是分类问题!

1.1 回归问题和分类问题的区别

        他们都是监督学习中的两大类问题,主要区别在于输出变量的类型预测目标的不同。

  • 回归问题的输出变量是连续性变量,而分类问题的输出变量则是离散型变量
  • 回归问题的目的是为了预测或者估计一个数值,如房价、股票价格等等;而分类问题则是将获得的输入数据划分为不同的类别,如判断邮件是否为垃圾邮件、识别图片中的对象等等。
  • 回归问题和分类问题是监督学习中的两大类问题,它们的主要区别在于输出变量的类型和预测目标的不同。

        逻辑回归是一种广泛应用于分类问题的机器学习算法,特别是在二分类问题中。尽管它的名字包含“回归”,但它实际上是一种分类方法,用于估计一个实例属于某个特定类别的概率。

1.2 逻辑回归与线性回归的区别

  • 线性回归:用于预测一个连续的数值,例如房价或体重。它通过建立一个线性模型来预测输出值,模型形式通常是 y = \omega x + b,其中 y 是预测值,x 是输入特征,\omega是权重,b 是偏差。

  • 逻辑回归:用于分类问题,预测概率(通常是二分类中的正类概率)。它通过使用Sigmoid函数将线性回归的输出映射到0和1之间,模型形式通常为

       p = Sigmoid((\omega x + b))

其中 p 是预测的概率,\omega是权重,b 是偏差。

二、 逻辑回归算法原理

2.1 Sigmoid函数

公式:\sigma \left ( z \right )= \frac{1}{1+e^{-z}}

自变量为任意实数,值域为[0,1]。

 下图给出了Sigmod 函数在不同坐标尺度下的两条曲线图。当 x 为 0 时,Sigmoid 函数值为 0.5 。随着x的增大,对应的Sigmoid值将逼近于 1 ; 而随着 x 的减小,Sigmoid 值将逼近于 0 。如果横坐标刻度足够大(如图5-1所示 ),Sigmoid 函数看起来很像一个阶跃函数。

        为了实现Logistic回归分类器,我们可以在每个特征上都乘以一个回归系数,然后把所有的结果值相加,将这个总和代入Sigmoid函数中,进而得到一个范围在0~1之间的数值。任何大于0.5的数据被分入1类,小于0.5即被归入0类。所以,Logistic回归也可以被看成所示一种概率估计。

        在具体的逻辑回归问题时,z通常是输入变量的线性组合,可以表示为z = \omega _{1}x_{1}+\omega _{2}x_{2}+...+\omega _{n}x_{n} + b 。其中,\omega _{i}是模型的权重(系数),x_{i}是输入变量的值。

2.2 基于最优化方法的最佳系数确定

        训练模型的过程中,通过最大化似然函数来估计模型的权重。似然函数是一个关于模型参数的函数,表示给定模型中样本的Galvan。在逻辑回归中,似然函数可以表示为

L(\omega ) = \prod_{i=1}^{n}g(z_{i})^{y_{i}}(1-g(z_{i}))^{1-y_{i}}

        其中,z_{i}是第i个样本的特征线性组合, y_{i}是对应的类别标签(0或1,此处指二分类问题)。

        为了最大化似然函数,下面将会用梯度下降算法来更新模型的权重。梯度下降算法是通过反复迭代来最小化损失函数,直到找到最优解。

        梯度下降算法的基本思想是:选择一个初始参数值,然后逐步调整这些参数,以减少损失函数的值。每次调整的幅度由损失函数相对于参数的梯度(即导数)和学习率(learning rate)的参数决定。梯度指向损失函数增长最快的方向,因此沿着梯度的反方向调整参数将会减少损失函数的值。

        损失函数通常是使用对数损失函数(log loss)来衡量模型的性能。对数损失函数可以表示为:

J\left ( \omega \right ) = - \frac{1}{n}\sum_{i=1}^{n}\left ( y_{i}\log g(z_{i})+(1-y_{i})\log (1-g(z_{i})) \right )

         其中,z_{i}是第i个样本的线性组合,y_{i}是对应样本的类别标签。

        最后,根据上述确定好的最佳系数来训练模型。训练模型后,我们可以使用模型来预测新样本的类别标签,预测类别标签的方法是,将新样本的特征向量代入Sigmoid函数,计算出该样本点的概率,如果概率大于0.5,则预测为正例(类别1);反之,则预测为负例(类别0)。

三、LogisticRegression算法实现

3.1 导入库包

对于逻辑回归来说,我们主要引入的库有:

  1. NumPy:用于进行数值计算,包括矩阵运算、数组操作等。用到的包有:numpy

  2. Pandas:用于数据处理,如读取数据、数据清洗、数据预处理等。用到的包有:pandas

  3. scikit-learn:提供了一个广泛的机器学习算法集合,包括逻辑回归。用到的包是:sklearn.datasets,用于导入训练需要的数据集。

  4. Matplotlib :用于数据可视化,可以帮助理解数据和模型性能。用到的包是:matplotlib

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

3.2 Sigmoid函数

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

3.3 创建逻辑回归模型

3.3.1 初始化参数

        对于逻辑回归使用的公式为z = \omega _{1}x_{1}+\omega _{2}x_{2}+...+\omega _{n}x_{n} + b,该算法的核心就是得到最佳系数\omega,为此我们定义两个参数,分别为权重\omega和偏值b

# 初始化模型参数
self.weights = np.random.randn(X.shape[1])
self.bias = 0
3.3.2 正向传播

我们现在是用逻辑回归处理鸢尾花数据集的二分类问题,因此我们希望可以得到对应样本点的概率,则将计算结果送到Sigmoid函数中得到对应概率值,公式如下所示:

p = sigmoid(y) = sigmoid(\omega*x+b) = \frac{1}{1+\exp ^{\omega*x+b}}

# 计算sigmoid函数的预测值  y_hat = w * x + b
y_hat = sigmoid(np.dot(X, self.weights) + self.bias)
3.3.3 损失函数

        损失函数(Loss Function)是机器学习中的关键概念,用于量化模型预测值与真实值之间的不一致程度。在训练过程中,损失函数的目的是指导模型如何调整参数以减少这种不一致性,从而提高模型的预测准确性。对于二分类问题,我们通常使用二元交叉熵损失(Binary Cross-Entropy)

        我们这里使用损失函数(Loss Function)来不断优化最佳系数。在每次迭代中,模型通过计算损失函数来确定当前参数下的预测误差。然后,通过梯度下降优化算法,根据损失函数的梯度来调整模型参数,以减少损失值。损失函数的公式上面有提到是:

J\left ( \omega \right ) = - \frac{1}{n}\sum_{i=1}^{n}\left ( y_{i}\log g(z_{i})+(1-y_{i})\log (1-g(z_{i})) \right )

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

我们先通过正向传播计算模型的预测值和损失函数的值。然后,再通过反向传播来计算损失函数相对于每个权重参数的导数,以便于参数的更新。我们使用梯度下降算法来更新权重参数,使损失函数最小化。

# 计算梯度
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
3.3.5 模型预测

对于逻辑回归,为了得到对应样本的类别,我们需要将最后计算出的概率二值化。如果大于0.5,将其转化为类别1,小于0.5则转化为类别0。并在模型训练后,用准确率来评估模型。

# 预测
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

3.3.6 LogisticRegression模型(完整代码)

# 逻辑回归算法
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# 逻辑回归算法
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

3.4 数据集预处理

3.4.1 获取数据集

        为了训练模型,我们使用的数据是从Python库中自带的鸢尾花数据集中获取的。

        鸢尾花数据集(Iris dataset)是一个非常著名的多类分类问题数据集。它包含150个样本,分为三个类,每个类50个样本。每个样本包含四个特征:花萼长度(sepal length)、花萼宽度(sepal width)、花瓣长度(petal length)和花瓣宽度(petal width),这些特征的单位是厘米。三个类分别是山鸢尾(Iris setosa)、变色鸢尾(Iris versicolor)和维吉尼亚鸢尾(Iris virginica)。

        因为我们这里要用逻辑回归算法处理二分类问题,而鸢尾花数据集有三个类别,因此要对数据集进行处理:将类别1归为1类,类别2和类别3归为0类。

# 导入鸢尾花数据集
iris = load_iris()
# 提取前两个特征(花萼长度和花萼宽度)作为特征集X
X = iris.data[:, :2]
# 将目标类别转换为 类别0 或 类别1 的二分类问题
y = (iris.target != 0) * 1

 

3.4.2 划分数据集

        这里我们将获取的数据集划分为训练集和测试集,用于训练和测试创建的LogisticRegression模型。

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

3.5 模型训练和评估

# 训练模型
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)

3.6 可视化决策边界

        为了更直观的感受逻辑回归对于二分类问题的处理,我们利用matplotlib包编写可视化决策边界的代码。通过结果可视化的方式,来加深我们的理解。

# 可视化决策边界
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)
# 指定字体为Microsoft YaHei
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
# 正常显示负号
# plt.rcParams['axes.unicode_minus'] = False
plt.contourf(xx1, xx2, Z, cmap=plt.cm.Spectral)
plt.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.Spectral)
plt.xlabel("花萼长度")
plt.ylabel("花萼宽度")
plt.title("逻辑回归 鸢尾花数据集")
plt.show()

3.7 代码结果展示

        对于创建的逻辑回归模型,我们已经通过鸢尾花数据集进行了模型训练并进行逻辑回归的处理,接下来我们就通过可视化决策边界来看看逻辑回归模型分类的效果,决策边界可视化图如下所示:

 

         该模型的准确率评估指标结果如下所示:

 

 

 

 

 

 

 

 

  • 27
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值