跳到主要内容

逻辑回归与Sigmoid函数

逻辑回归(Logistic Regression)是一种常用的分类算法,尤其适用于二分类问题。它基于线性回归模型,但通过Sigmoid函数将输出映射到[0,1]区间,表示某一结果的概率。

算法原理

Sigmoid函数

Sigmoid函数(也称为逻辑函数)是逻辑回归的核心,其数学表达式为:

σ(z)=11+ez\sigma(z) = \frac{1}{1 + e^{-z}}

其中,z=θTxz = \theta^T x 是线性函数,θ\theta 是模型参数,xx 是特征向量。

Sigmoid函数的值域为(0,1),可以解释为事件发生的概率。当 zz \rightarrow \infty 时,σ(z)1\sigma(z) \rightarrow 1;当 zz \rightarrow -\infty 时,σ(z)0\sigma(z) \rightarrow 0

决策边界

在逻辑回归中,我们通常使用以下规则进行分类:

  • 如果 σ(z)0.5\sigma(z) \geq 0.5,则预测为类别1
  • 如果 σ(z)<0.5\sigma(z) < 0.5,则预测为类别0

这等价于:

  • 如果 z0z \geq 0,则预测为类别1
  • 如果 z<0z < 0,则预测为类别0

其中 z=θTxz = \theta^T x 是决策边界。

损失函数

逻辑回归使用对数似然损失函数(Log-likelihood Loss):

J(θ)=1mi=1m[y(i)log(hθ(x(i)))+(1y(i))log(1hθ(x(i)))]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)}))]

其中:

  • mm 是样本数量
  • y(i)y^{(i)} 是第i个样本的实际标签(0或1)
  • hθ(x(i))=σ(θTx(i))h_\theta(x^{(i)}) = \sigma(\theta^T x^{(i)}) 是模型预测的概率

参数优化

我们的目标是找到最优的参数 θ\theta,使损失函数 J(θ)J(\theta) 最小。常用的优化方法是梯度下降:

θj:=θjαJ(θ)θj\theta_j := \theta_j - \alpha \frac{\partial J(\theta)}{\partial \theta_j}

其中:

  • α\alpha 是学习率
  • 梯度 J(θ)θj=1mi=1m(hθ(x(i))y(i))xj(i)\frac{\partial J(\theta)}{\partial \theta_j} = \frac{1}{m} \sum_{i=1}^{m} (h_\theta(x^{(i)}) - y^{(i)}) x_j^{(i)}

代码实现

使用scikit-learn库

import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import accuracy_score, confusion_matrix, classification_report
from sklearn.datasets import load_breast_cancer

# 加载数据集(乳腺癌数据集,二分类问题)
data = load_breast_cancer()
X = data.data
y = data.target

# 数据预处理:标准化
scaler = StandardScaler()
X = scaler.fit_transform(X)

# 分割训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 创建并训练逻辑回归模型
model = LogisticRegression(C=1.0, max_iter=1000)
model.fit(X_train, y_train)

# 预测
y_pred = model.predict(X_test)
y_prob = model.predict_proba(X_test)[:, 1]

# 评估模型
accuracy = accuracy_score(y_test, y_pred)
conf_matrix = confusion_matrix(y_test, y_pred)
class_report = classification_report(y_test, y_pred)

print(f"准确率: {accuracy:.4f}")
print("混淆矩阵:")
print(conf_matrix)
print("分类报告:")
print(class_report)

# 可视化决策边界(仅使用前两个特征进行可视化)
plt.figure(figsize=(10, 6))
plt.scatter(X_test[:, 0], X_test[:, 1], c=y_test, cmap=plt.cm.Paired, edgecolors='k')
plt.title('逻辑回归决策边界')
plt.xlabel(data.feature_names[0])
plt.ylabel(data.feature_names[1])
plt.savefig('logistic_regression_decision_boundary.png')
plt.show()

# 可视化Sigmoid函数
x = np.linspace(-10, 10, 1000)
y = 1 / (1 + np.exp(-x))
plt.figure(figsize=(10, 6))
plt.plot(x, y)
plt.title('Sigmoid函数')
plt.xlabel('z')
plt.ylabel('σ(z)')
plt.grid(True)
plt.savefig('sigmoid_function.png')
plt.show()

从零实现逻辑回归

import numpy as np

class LogisticRegression:
def __init__(self, learning_rate=0.01, n_iterations=1000):
self.learning_rate = learning_rate
self.n_iterations = n_iterations
self.weights = None
self.bias = None

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

def fit(self, X, y):
"""训练逻辑回归模型"""
# 初始化参数
n_samples, n_features = X.shape
self.weights = np.zeros(n_features)
self.bias = 0

# 梯度下降优化
for _ in range(self.n_iterations):
# 线性模型
linear_model = np.dot(X, self.weights) + self.bias
# 应用sigmoid函数
y_predicted = self.sigmoid(linear_model)

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

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

def predict_probability(self, X):
"""预测样本属于正类的概率"""
linear_model = np.dot(X, self.weights) + self.bias
return self.sigmoid(linear_model)

def predict(self, X, threshold=0.5):
"""预测类别(默认阈值为0.5)"""
probabilities = self.predict_probability(X)
return [1 if p > threshold else 0 for p in probabilities]

def accuracy(self, X, y):
"""计算准确率"""
predictions = self.predict(X)
return np.mean(predictions == y)

逻辑回归与Sigmoid函数可视化

Sigmoid函数曲线

Sigmoid函数的特点是将任何实数映射到(0,1)区间,形成一条S形曲线:

逻辑回归决策边界

在二维特征空间中,逻辑回归的决策边界是一条直线(高维空间中是一个超平面):

正则化

为了防止过拟合,逻辑回归通常会加入正则化项:

L1正则化(Lasso)

J(θ)=1mi=1m[y(i)log(hθ(x(i)))+(1y(i))log(1hθ(x(i)))]+λj=1nθjJ(\theta) = -\frac{1}{m} \sum_{i=1}^{m} [y^{(i)} \log(h_\theta(x^{(i)})) + (1-y^{(i)}) \log(1-h_\theta(x^{(i)}))] + \lambda \sum_{j=1}^{n} |\theta_j|

L1正则化倾向于产生稀疏解,即许多特征的权重变为0。

L2正则化(Ridge)

J(θ)=1mi=1m[y(i)log(hθ(x(i)))+(1y(i))log(1hθ(x(i)))]+λj=1nθj2J(\theta) = -\frac{1}{m} \sum_{i=1}^{m} [y^{(i)} \log(h_\theta(x^{(i)})) + (1-y^{(i)}) \log(1-h_\theta(x^{(i)}))] + \lambda \sum_{j=1}^{n} \theta_j^2

L2正则化会使权重值更小但通常不会变为精确的0。

# scikit-learn中使用L1和L2正则化
# L1正则化
model_l1 = LogisticRegression(penalty='l1', C=1.0, solver='liblinear')

# L2正则化
model_l2 = LogisticRegression(penalty='l2', C=1.0)

# 弹性网络(Elastic Net):同时使用L1和L2正则化
model_elastic = LogisticRegression(penalty='elasticnet', C=1.0, l1_ratio=0.5, solver='saga')

其中,C是正则化强度的倒数,C越小,正则化越强。

多类分类

虽然逻辑回归本身是二分类算法,但可以扩展到多分类问题:

一对多(One-vs-Rest)

为每个类别训练一个二分类器,将该类作为正类,其他所有类作为负类。

一对一(One-vs-One)

为每对类别训练一个二分类器,总共需要 k(k1)2\frac{k(k-1)}{2} 个分类器(k是类别数量)。

from sklearn.linear_model import LogisticRegression
from sklearn.multiclass import OneVsRestClassifier, OneVsOneClassifier

# 一对多
model_ovr = OneVsRestClassifier(LogisticRegression())

# 一对一
model_ovo = OneVsOneClassifier(LogisticRegression())

逻辑回归的优缺点

优点

  • 简单易于实现和理解
  • 计算效率高,训练速度快
  • 不易过拟合,特别是在高维数据上
  • 提供良好的概率解释
  • 可以使用L1正则化进行特征选择

缺点

  • 假设特征之间是线性关系,无法学习复杂的非线性决策边界
  • 对异常值敏感
  • 要求特征之间相对独立,多重共线性会影响模型性能
  • 在类别不平衡数据上表现可能不佳

应用场景

逻辑回归广泛应用于:

  • 垃圾邮件分类
  • 疾病诊断
  • 信用评分
  • 客户流失预测
  • 广告点击率预测

小结

逻辑回归是一种简单但强大的分类算法,特别是对于线性可分的问题。它不仅可以提供分类结果,还能给出概率估计,这在许多应用场景中非常有用。虽然它不如复杂的算法(如神经网络)强大,但因其简单性、可解释性和效率,仍然是实践中的重要工具。