Skip to content

知识点卡片:逻辑回归

基本信息

属性内容
知识点逻辑回归 (Logistic Regression)
掌握程度★★★★★
学习优先级P0
预估时间8小时
面试频率★★★★★

核心原理

逻辑回归是二分类的线性模型:

模型:P(y=1|x) = σ(w^T x + b) = 1 / (1 + exp(-w^T x - b))

损失函数 (Binary Cross Entropy):
L = -[y log(p) + (1-y) log(1-p)]

梯度(简洁形式!):
∂L/∂w = X^T (σ(Xw) - y) / n

为什么是Sigmoid?

python
"""
对数几率(log-odds)模型:
log(P(y=1) / P(y=0)) = w^T x + b

解出 P(y=1):
P(y=1) = 1 / (1 + exp(-w^T x - b)) = sigmoid(w^T x + b)

所以sigmoid不是随意选的——它来自对数几率的线性模型。
"""

从零实现

python
import numpy as np

class LogisticRegression:
    def __init__(self, lr=0.01, n_iters=1000, penalty='l2', C=1.0):
        self.lr = lr
        self.n_iters = n_iters
        self.penalty = penalty
        self.C = C  # 正则化强度的倒数

    def sigmoid(self, z):
        # 数值稳定版本
        z = np.clip(z, -500, 500)
        return 1 / (1 + np.exp(-z))

    def fit(self, X, y):
        n, d = X.shape
        self.w = np.random.randn(d) * 0.01
        self.b = 0.0

        for _ in range(self.n_iters):
            # 预测
            z = X @ self.w + self.b
            pred = self.sigmoid(z)

            # 梯度
            error = pred - y
            dw = (1/n) * X.T @ error
            db = (1/n) * error.sum()

            # 正则化梯度
            if self.penalty == 'l2':
                dw += (1 / (self.C * n)) * self.w
            elif self.penalty == 'l1':
                dw += (1 / (self.C * n)) * np.sign(self.w)

            # 更新
            self.w -= self.lr * dw
            self.b -= self.lr * db

    def predict_proba(self, X):
        return self.sigmoid(X @ self.w + self.b)

    def predict(self, X, threshold=0.5):
        return (self.predict_proba(X) >= threshold).astype(int)

sklearn实现

python
from sklearn.linear_model import LogisticRegression

# 注意:sklearn中C是正则化强度的倒数
# C越大 → 正则化越弱
model = LogisticRegression(
    penalty='l2',      # 'l1', 'l2', 'elasticnet', None
    C=1.0,             # 正则化系数倒数
    max_iter=1000,
    solver='lbfgs',    # 小数据用lbfgs,大数据用saga
    multi_class='auto'
)
model.fit(X_train, y_train)

# 获取概率(不只是分类)
probs = model.predict_proba(X_test)  # (n, 2)
# probs[:, 0] = P(y=0), probs[:, 1] = P(y=1)

多分类扩展

python
# One-vs-Rest:训练K个二分类器
# Multinomial:softmax回归(等同于神经网络的softmax层)

from sklearn.linear_model import LogisticRegression

# OvR(默认)
model_ovr = LogisticRegression(multi_class='ovr')
model_ovr.fit(X, y)

# Multinomial(等同于softmax回归)
model_multi = LogisticRegression(multi_class='multinomial', solver='lbfgs')
model_multi.fit(X, y)

面试高频问题

Q1: 逻辑回归和线性回归的区别?

方面线性回归逻辑回归
任务回归分类
输出实数[0,1]概率
损失函数MSEBCE
梯度X^T(Xw-y)X^T(σ(Xw)-y)
决策边界线性决策边界

Q2: 推导逻辑回归的梯度

p = σ(z), z = Xw

L = -[y log p + (1-y) log(1-p)]

∂p/∂z = p(1-p)(sigmoid性质)

∂L/∂z = -[y * (1/p) * p(1-p) + (1-y) * (-1/(1-p)) * p(1-p)]
       = -[y(1-p) - (1-y)p]
       = -[y - yp - p + yp]
       = p - y

∂L/∂w = X^T ∂L/∂z / n = X^T(p - y) / n

Q3: 逻辑回归为什么叫"回归"却做分类?

: 因为它在做一个回归——对对数几率 log(p/(1-p)) 做线性回归。输出通过sigmoid转换成概率,再用阈值变成分类结果。从根本上讲,它是用回归的思想解分类问题。


相关知识点