实现鸢尾花数据集逻辑回归时sigmoid函数报power溢出错误如何解决
问题根因
- 标签取值不符合逻辑回归要求:二分类逻辑回归的正负样本标签需为
1和0,代码中错误将标签替换为1和-1,导致损失计算逻辑完全错位,参数更新方向错误,权重值快速爆炸 - 特征与标签未拆分:
trainX直接使用了包含最后一列标签的完整数据集,相当于把标签本身作为特征输入模型,初始化的权重维度为5维(鸢尾花仅4个原始特征)也正是该问题导致的 - sigmoid函数数值稳定性不足:直接计算
np.e ** (-x)时,当x为绝对值较大的负数,-x会变成极大正数,指数计算触发溢出警告 - 梯度计算公式错误且未归一化:逻辑回归的梯度计算应为
(sigmoid输出 - 真实标签) 点乘 特征矩阵 / 样本数,代码中梯度的计算顺序写反,且没有除以样本数做归一化,加上学习率设置不合理,导致权重值迭代几步就爆炸到数千的量级
修复后可运行代码
import numpy as np # 数值稳定版sigmoid实现,避免溢出 def sigmoid(x): mask = x >= 0 res = np.zeros_like(x, dtype=float) res[mask] = 1 / (1 + np.exp(-x[mask])) res[~mask] = np.exp(x[~mask]) / (1 + np.exp(x[~mask])) return res dataset = np.loadtxt("iris.data", delimiter=',', dtype=str) dataset = dataset[:100] # 标签替换为逻辑回归要求的1和0 dataset = np.where(dataset == 'Iris-setosa', 1, dataset) dataset = np.where(dataset == 'Iris-versicolor', 0, dataset) m = dataset.astype(float) np.random.shuffle(m) # 拆分特征(前4列)和标签(最后1列) X = m[:, :-1] Y = m[:, -1] # 拆分训练集和测试集 testX, testY = X[:30], Y[:30] trainX, trainY = X[30:], Y[30:] # 初始化权重和偏置 w = np.zeros(trainX.shape[1]) b = 0 lr = 0.05 epoch = 1000 # 梯度下降训练 for i in range(epoch): y_hat = sigmoid(np.dot(trainX, w) + b) # 计算梯度 dw = np.dot((y_hat - trainY), trainX) / len(trainY) db = np.sum(y_hat - trainY) / len(trainY) # 更新参数 w -= lr * dw b -= lr * db print("权重w: ", w) print("偏置b: ", b) # 测试准确率 pred = np.round(sigmoid(np.dot(testX, w) + b)) acc = np.sum(pred == testY) / len(testY) print("测试集准确率: ", acc)
效果说明
鸢尾花数据集前100个样本(山鸢尾和变色鸢尾)是完全线性可分的,修复后模型的测试集准确率可以达到100%,且不会触发溢出警告。
内容的提问来源于stack exchange,提问作者S M Sarwar
相关产品推荐
相关产品推荐

