Python实现逻辑回归
引言
逻辑回归是一种常用的分类算法,它用于预测二分类问题。在本文中,我们将使用Python来实现逻辑回归算法,并对算法进行详细解释。逻辑回归是一种线性分类器,它使用sigmoid函数将连续的预测值转换为概率值,从而进行分类。
数据准备
在开始实现逻辑回归算法之前,我们首先需要准备我们的数据集。在这个例子中,我们将使用一个虚构的数据集,其中包含两个特征x和y,以及一个二进制的分类标签。
import numpy as np
# 创建一个虚构的数据集
x1 = np.random.randn(100, 2) + np.array([-2, 2])
x2 = np.random.randn(100, 2) + np.array([2, -2])
x = np.vstack([x1, x2])
y = np.hstack([np.zeros(100), np.ones(100)])
# 可视化数据集
import matplotlib.pyplot as plt
plt.scatter(x[:, 0], x[:, 1], c=y)
plt.xlabel('x')
plt.ylabel('y')
plt.show()
运行上述代码后,我们将得到如下图所示的散点图,其中蓝色点表示类别0,红色点表示类别1。
Sigmoid函数
逻辑回归的核心思想是使用sigmoid函数将预测值转换为概率值。Sigmoid函数定义如下:
\sigma(x) = \frac{1}{1+e^{-x}}
Sigmod函数的输入为任意实数值,输出范围在0到1之间。当输入接近正无穷大时,sigmoid函数的值接近1;当输入接近负无穷大时,sigmoid函数的值接近0。
在Python中,我们可以使用numpy
库的exp
函数来实现sigmoid函数:
def sigmoid(x):
return 1 / (1 + np.exp(-x))
损失函数
在训练逻辑回归模型时,我们需要定义一个损失函数,用于衡量预测值和真实值之间的差距。逻辑回归使用的损失函数被称为对数损失函数(log loss),定义如下:
J(\theta) = -\frac{1}{m}\sum_{i=1}^{m}[y^{(i)}\log(h_{\theta}(x^{(i)})) + (1 – y^{(i)})\log(1 – h_{\theta}(x^{(i)}))]
其中,m是训练样本的数量,h_{\theta}(x)是逻辑回归的预测函数。对于逻辑回归,预测函数定义如下:
h_{\theta}(x) = \sigma(\theta^Tx)
在上述公式中,y^{(i)}是第i个训练样本的真实标签。如果y^{(i)}=1,则第一项y^{(i)}\log(h_{\theta}(x^{(i)}))对损失函数的贡献为\log(h_{\theta}(x^{(i)}));如果y^{(i)}=0,则第二项(1 – y^{(i)})\log(1 – h_{\theta}(x^{(i)}))对损失函数的贡献为\log(1 – h_{\theta}(x^{(i)}))。我们的目标是最小化损失函数J(\theta)。
在Python中,我们可以轻松地实现对数损失函数:
def log_loss(y, h_theta_x):
epsilon = 1e-5 # 添加一个小的常数,以避免对数函数中出现无穷大或nan
return -(y * np.log(h_theta_x + epsilon) + (1 - y) * np.log(1 - h_theta_x + epsilon)).mean()
梯度下降法
为了最小化损失函数,我们需要使用梯度下降法。梯度下降法是一种迭代的优化算法,通过沿着负梯度方向更新模型参数来逐步接近最优解。
在逻辑回归中,模型参数是\theta,我们可以使用梯度下降法来不断更新\theta。
逻辑回归的梯度下降算法的更新规则如下:
\theta_j := \theta_j – \alpha\frac{\partial J(\theta)}{\partial \theta_j}
其中,\alpha是学习率,控制更新的步长。
为了使梯度下降法收敛,我们需要计算损失函数J(\theta)对参数\theta_j的偏导数\frac{\partial J(\theta)}{\partial \theta_j}。这个偏导数的计算比较复杂,但我们可以通过求解偏导数的推导过程,得到如下公式:
\frac{\partial J(\theta)}{\partial \theta_j} = \frac{1}{m}\sum_{i=1}^{m}(h_{\theta}(x^{(i)}) – y^{(i)})x_j^{(i)}
该公式表示,在梯度下降的每一次迭代中,我们需要计算每个特征的加权和(h_{\theta}(x^{(i)}) – y^{(i)})x_j^{(i)},并求平均值。
在实际实现中,我们将使用向量化的方法来加速运算:
def update_parameters(X, y, theta, h_theta_x, learning_rate):
m = X.shape[0]
gradient = np.dot(X.T, h_theta_x - y) / m
theta -= learning_rate * gradient
return theta