LogisticRegression:二元分类器

用于二元分类任务的逻辑回归类。

from mlxtend.classifier import LogisticRegression

概述

感知机 (Perceptron)'自适应线性神经元 (Adaline)' 相关,逻辑回归模型是一种用于二元分类的线性模型。然而,与 Adaline 中最小化线性成本函数(例如平方误差和 (SSE))不同,我们最小化一个 sigmoid 函数,即逻辑函数

其中定义为网络输入

网络输入反过来基于 logit 函数

这里,是给定特征时,特定样本属于类别 1 的条件概率。logit 函数接受范围 [0, 1] 内的输入,并将其转换为整个实数范围内的值。相反,逻辑函数接受整个实数范围内的输入值,并将其转换为范围 [0, 1] 内的值。换句话说,逻辑函数是 logit 函数的逆函数,它使我们能够预测某个样本属于类别 1(或类别 0)的条件概率。

模型拟合后,条件概率通过阈值函数转换为二元类别标签:

$$y = g({z}) = $$

或等效地

$$y = g({z}) = $$

目标函数 -- 对数似然

为了参数化逻辑回归模型,我们最大化似然(或最小化逻辑成本函数)。

我们将似然写为

假设训练样本相互独立。

实际上,更容易最大化这个方程的(自然)对数,这称为对数似然函数

取对数的一个优点是避免非常小的似然值导致的数值下溢(以及浮点数学的挑战)。另一个优点是我们可以更容易地获得导数,使用加法技巧将因子的乘积重写为求和项,然后我们可以使用诸如梯度上升之类的优化算法对其进行最大化。

目标函数 -- 逻辑成本函数

作为最大化对数似然的一种替代方法,我们可以定义一个成本函数需要最小化;我们将对数似然重写为

$$ J\big(\phi(z), y; \mathbf{w}\big) = $$

正如上图所示,我们对错误的预测施加越来越大的惩罚成本。

梯度下降 (GD) 和随机梯度下降 (SGD) 优化

梯度上升与对数似然

为了通过基于梯度的优化来学习逻辑回归模型的权重系数,我们计算对数似然函数关于第 j 个权重的偏导数如下

作为一个中间步骤,我们计算 sigmoid 函数的偏导数,这在后面会派上用场

现在,我们将重新代回对数似然偏导数方程,并获得如下所示的方程

现在,为了找到模型的权重,我们沿着梯度的正方向迈出一步,以最大化对数似然。此外,我们在权重更新中加入一个系数,即学习率到权重更新

请注意,梯度上升/下降中的梯度(和权重更新)是根据训练集中的所有样本计算的,这与随机梯度上升/下降不同。有关梯度下降和随机梯度下降之间差异的更多信息,请参阅相关文章 梯度下降和随机梯度下降

前一个方程显示了单个权重的权重更新。在基于梯度的优化中,所有权重系数同时更新;权重更新可以更紧凑地写为

其中

梯度下降与逻辑成本函数

在上一节中,我们推导了对数似然函数的梯度,可以通过梯度上升进行优化。类似地,我们可以获得逻辑成本函数的成本梯度并通过梯度下降最小化它,以学习逻辑回归模型。

单个权重的更新规则

同步权重更新

其中

洗牌

随机洗牌的实现方式如下

  • 对于一个或多个 epoch
    • 随机洗牌训练集中的样本
      • 对于训练样本 i
        • 计算梯度并执行权重更新

正则化

作为解决过拟合的一种方法,我们可以通过正则化项为逻辑回归模型增加额外的偏差。通过 L2 正则化项,我们通过惩罚较大的权重系数来降低模型的复杂度

为了应用正则化,我们只需将正则化项添加到我们为逻辑回归定义的成本函数中,以收缩权重

单个权重的更新规则

同步权重更新

其中

有关正则化的更多信息,请参阅 广义线性模型的正则化

参考文献

示例 1 - 梯度下降

from mlxtend.data import iris_data
from mlxtend.plotting import plot_decision_regions
from mlxtend.classifier import LogisticRegression
import matplotlib.pyplot as plt

# Loading Data

X, y = iris_data()
X = X[:, [0, 3]] # sepal length and petal width
X = X[0:100] # class 0 and class 1
y = y[0:100] # class 0 and class 1

# standardize
X[:,0] = (X[:,0] - X[:,0].mean()) / X[:,0].std()
X[:,1] = (X[:,1] - X[:,1].mean()) / X[:,1].std()

lr = LogisticRegression(eta=0.1, 
                        l2_lambda=0.0, 
                        epochs=100,
                        minibatches=1, # for Gradient Descent
                        random_seed=1,
                        print_progress=3)
lr.fit(X, y)

plot_decision_regions(X, y, clf=lr)
plt.title('Logistic Regression - Gradient Descent')
plt.show()

plt.plot(range(len(lr.cost_)), lr.cost_)
plt.xlabel('Iterations')
plt.ylabel('Cost')
plt.show()
Iteration: 100/100 | Cost 0.32 | Elapsed: 0:00:00 | ETA: 0:00:00

png

png

预测类别标签

y_pred = lr.predict(X)
print('Last 3 Class Labels: %s' % y_pred[-3:])
Last 3 Class Labels: [1 1 1]

预测类别概率

y_pred = lr.predict_proba(X)
print('Last 3 Class Labels: %s' % y_pred[-3:])
Last 3 Class Labels: [ 0.99997968  0.99339873  0.99992707]

示例 2 - 随机梯度下降

from mlxtend.data import iris_data
from mlxtend.plotting import plot_decision_regions
from mlxtend.classifier import LogisticRegression
import matplotlib.pyplot as plt

# Loading Data

X, y = iris_data()
X = X[:, [0, 3]] # sepal length and petal width
X = X[0:100] # class 0 and class 1
y = y[0:100] # class 0 and class 1

# standardize
X[:,0] = (X[:,0] - X[:,0].mean()) / X[:,0].std()
X[:,1] = (X[:,1] - X[:,1].mean()) / X[:,1].std()

lr = LogisticRegression(eta=0.5, 
                        epochs=30, 
                        l2_lambda=0.0, 
                        minibatches=len(y), # for SGD learning 
                        random_seed=1,
                        print_progress=3)
lr.fit(X, y)

plot_decision_regions(X, y, clf=lr)
plt.title('Logistic Regression - Stochastic Gradient Descent')
plt.show()

plt.plot(range(len(lr.cost_)), lr.cost_)
plt.xlabel('Iterations')
plt.ylabel('Cost')
plt.show()
Iteration: 30/30 | Cost 0.27 | Elapsed: 0:00:00 | ETA: 0:00:00

png

png

示例 3 - 带小批量的随机梯度下降

在这里,我们将 minibatches 设置为 5,这将导致批量大小为 20 个样本的小批量学习(因为 100 个 Iris 样本除以 5 个小批量等于 20)。

from mlxtend.data import iris_data
from mlxtend.plotting import plot_decision_regions
from mlxtend.classifier import LogisticRegression
import matplotlib.pyplot as plt

# Loading Data

X, y = iris_data()
X = X[:, [0, 3]] # sepal length and petal width
X = X[0:100] # class 0 and class 1
y = y[0:100] # class 0 and class 1

# standardize
X[:,0] = (X[:,0] - X[:,0].mean()) / X[:,0].std()
X[:,1] = (X[:,1] - X[:,1].mean()) / X[:,1].std()

lr = LogisticRegression(eta=0.5, 
                        epochs=30, 
                        l2_lambda=0.0, 
                        minibatches=5, # 100/5 = 20 -> minibatch-s 
                        random_seed=1,
                        print_progress=3)
lr.fit(X, y)

plot_decision_regions(X, y, clf=lr)
plt.title('Logistic Regression - Stochastic Gradient Descent')
plt.show()

plt.plot(range(len(lr.cost_)), lr.cost_)
plt.xlabel('Iterations')
plt.ylabel('Cost')
plt.show()
Iteration: 30/30 | Cost 0.25 | Elapsed: 0:00:00 | ETA: 0:00:00

png

png

API

LogisticRegression(eta=0.01, epochs=50, l2_lambda=0.0, minibatches=1, random_seed=None, print_progress=0)

逻辑回归分类器。

注意,此 Logistic Regression 实现期望二元类别标签为 {0, 1}。

参数

  • eta : float (默认值: 0.01)

    学习率 (介于 0.0 和 1.0 之间)

  • epochs : int (默认值: 50)

    遍历训练数据集的次数。在每个 epoch 之前,如果 minibatches > 1,数据集会被洗牌,以防止随机梯度下降中的周期性。

  • l2_lambda : float

    L2 正则化的正则化参数。如果 l2_lambda=0.0,则不进行正则化。

  • minibatches : int (默认值: 1)

    用于基于梯度的优化的 minibatch 数量。如果为 1:梯度下降学习 如果为 len(y):随机梯度下降 (SGD) 在线学习 如果 1 < minibatches < len(y):SGD 小批量学习

  • random_seed : int (默认值: None)

    设置用于洗牌和初始化权重的随机状态。

  • print_progress : int (默认值: 0)

    将拟合进度打印到 stderr。 0: 无输出 1: 已用 epoch 数和成本 2: 1 加已用时间 3: 2 加估计完成时间

属性

  • w_ : 2d-array, shape={n_features, 1}

    模型拟合后的权重。

  • b_ : 1d-array, shape={1,}

    模型拟合后的偏置项。

  • cost_ : list

    每个 epoch 的交叉熵成本列表(sgd 或 gd)。

示例

有关使用示例,请参阅 https://mlxtend.cn/mlxtend/user_guide/classifier/LogisticRegression/

方法


fit(X, y, init_params=True)

从训练数据中学习模型。

参数

  • X : {类数组, 稀疏矩阵}, shape = [样本数, 特征数]

    训练向量,其中 n_samples 是样本数量,n_features 是特征数量。

  • y : 类数组, shape = [样本数]

    目标值。

  • init_params : bool (默认值: True)

    在拟合之前重新初始化模型参数。设置为 False 可继续使用之前模型拟合的权重进行训练。

返回值

  • self : object

predict(X)

从 X 预测目标。

参数

  • X : {类数组, 稀疏矩阵}, shape = [样本数, 特征数]

    训练向量,其中 n_samples 是样本数量,n_features 是特征数量。

返回值

  • target_values : 类数组, shape = [样本数]

    预测的目标值。


predict_proba(X)

从网络输入预测 X 的类别概率。

参数

  • X : {类数组, 稀疏矩阵}, shape = [样本数, 特征数]

    训练向量,其中 n_samples 是样本数量,n_features 是特征数量。

返回值

  • 类别 1 概率 : float

score(X, y)

计算预测准确率

参数

  • X : {类数组, 稀疏矩阵}, shape = [样本数, 特征数]

    训练向量,其中 n_samples 是样本数量,n_features 是特征数量。

  • y : 类数组, shape = [样本数]

    目标值(真实类别标签)。

返回值

  • acc : float

    预测准确率,一个介于 0.0 和 1.0 之间的浮点数(完美得分为 1.0)。