本题让我们从零实现二分类逻辑回归(Logistic Regression),并用**批量梯度下降(Batch Gradient Descent)**来训练参数。
模型形式为:
y^=σ(z),z=w1x1+w2x2+b,σ(z)=1+e−z1损失函数是二分类交叉熵(Log Loss):
L=−n1i=1∑n[yilogy^i+(1−yi)log(1−y^i)]对每个参数的梯度为:
$$\frac{\partial L}{\partial w_1} = \frac{1}{n}\sum_{i=1}^{n} ( \hat{y}_i - y_i ) x_{1i},\quad \frac{\partial L}{\partial w_2} = \frac{1}{n}\sum_{i=1}^{n} ( \hat{y}_i - y_i ) x_{2i}$$∂b∂L=n1i=1∑n(y^i−yi)每一轮迭代中,用学习率 lr 做参数更新:
初始时令 w1 = w2 = b = 0.0,循环 epochs 轮。
最终返回 [w1, w2, b]。
关键点:
exp 溢出)。samples = [[x1, x2, y], ...],注意拆包时同时取出 (x1, x2, y)。初始化参数
w1 = 0.0w2 = 0.0b = 0.0n = len(samples) 为样本数定义 Sigmoid 函数(数值稳定版本)
def sigmoid(z: float) -> float:
if z >= 0:
return 1.0 / (1.0 + math.exp(-z))
else:
ez = math.exp(z)
return ez / (1.0 + ez)
这样写的好处是:
z 很大为正时,exp(-z) 非常小,不会下溢;z 很大为负时,直接算 exp(-z) 会溢出,我们改为算 exp(z) 来规避。外层循环 epochs 轮
每一轮都重新把梯度累加量置零:
dw1 = dw2 = db = 0.0
遍历所有样本,计算梯度累加
对每个样本 (x1, x2, y):
线性部分:
z = w1 * x1 + w2 * x2 + b
预测概率:
y_pred = sigmoid(z)
误差项:
diff = y_pred - y # 这是 ∂L/∂z
梯度累加:
dw1 += diff * x1
dw2 += diff * x2
db += diff
对梯度取平均
dw1 /= n
dw2 /= n
db /= n
根据学习率更新参数
w1 -= lr * dw1
w2 -= lr * dw2
b -= lr * db
重复上述步骤 epochs 次后,返回结果
return [w1, w2, b]
def sigmoid(z: float) -> float:
if z >= 0:
return 1.0 / (1.0 + math.exp(-z))
else:
ez = math.exp(z)
return ez / (1.0 + ez)
class Solution:
def logisticRegression(self, samples: List[List[float]], lr: float, epochs: int) -> List[float]:
w1 = 0.0
w2 = 0.0
b = 0.0
n = len(samples)
for _ in range(epochs):
dw1 = 0.0
dw2 = 0.0
db = 0.0
for x1, x2, y in samples:
z = w1 * x1 + w2 * x2 + b
y_pred = sigmoid(z)
diff = y_pred - y
dw1 += diff * x1
dw2 += diff * x2
db += diff
dw1 /= n
dw2 /= n
db /= n
w1 -= lr * dw1
w2 -= lr * dw2
b -= lr * db
return [w1, w2, b]
你需要实现一个二分类逻辑回归模型(Logistic Regression)。 给定 n 个样本,每个样本有二维特征 (x1,x2) 和标签 y∈{0,1},使用梯度下降训练模型,并返回最终学习到的参数:
模型形式为:
y^=σ(z)=1+e−z1,z=w1x1+w2x2+b其中 σ(⋅) 为 Sigmoid 函数。
训练目标是最小化二分类交叉熵损失(Log Loss):
L=−n1i=1∑n[yilogy^i+(1−yi)log(1−y^i)]你需要使用给定的学习率 lr 和迭代轮数 epochs,通过批量梯度下降更新参数:
对于每一轮迭代:
对所有样本计算 y^i
计算梯度:
∂w1∂L=n1i=1∑n(y^i−yi)x1i