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
- 计算梯度并执行权重更新
- 对于训练样本 i
- 随机洗牌训练集中的样本
正则化
作为解决过拟合的一种方法,我们可以通过正则化项为逻辑回归模型增加额外的偏差。通过 L2 正则化项,我们通过惩罚较大的权重系数来降低模型的复杂度
为了应用正则化,我们只需将正则化项添加到我们为逻辑回归定义的成本函数中,以收缩权重
单个权重的更新规则
同步权重更新
其中
有关正则化的更多信息,请参阅 广义线性模型的正则化。
参考文献
- Bishop, Christopher M. Pattern recognition and machine learning. Springer, 2006. pp. 203-213
示例 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
预测类别标签
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
示例 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
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
: floatL2 正则化的正则化参数。如果 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)。