You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义Logistic回归代码遇RuntimeWarning: exp溢出问题求助

问题描述

实现自定义Logistic回归代码后,模型预测结果全为0,同时出现以下警告:

RuntimeWarning: overflow encountered in exp
predictions = 1 / (1 + np.exp(-predictions))

附上的代码如下:

import numpy as np
import pandas as pd

dataset = pd.read_csv('data.csv')

dataset = (dataset - dataset.mean()) / dataset.std()

from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(dataset.iloc[:, :-1], dataset.iloc[:, -1], test_size=0.25, random_state=42)

def logisticRegression_model(X, y, learning_rate, num_epochs):
    
    weights = np.zeros(X.shape[1])
    
    for epoch in range(num_epochs):
        
        logisticRegression_update_weights(X, y, weights, learning_rate)
    
    return weights

def logisticRegression_update_weights(X, y, weights, learning_rate):
    
    gradient = logisticRegression_calculate_gradient(X, y, weights)
    
    weights += learning_rate * gradient
    
    return weights

def logisticRegression_calculate_gradient(X, y, weights):
    
    #calculating the predictions
    predictions = logisticRegression_predict(X, weights)
    
    #calculating the errors
    error = y - predictions
    
    gradient = np.dot(X.T, error)

    return gradient

def logisticRegression_predict(X, weights):
    
    predictions = np.dot(X, weights)
    
    predictions = 1 / (1 + np.exp(-predictions))
    
    return predictions

def logisticRegression_accuracy(y_true, y_pred):
    
    accuracy = np.sum(y_true == y_pred) / len(y_true)
    
    return accuracy

def logisticRegression_train(X_train, y_train, learning_rate, num_epochs):
    
    weights = logisticRegression_model(X_train, y_train, learning_rate, num_epochs)
    
    return weights

weights = logisticRegression_train(X_train, y_train, 0.1, 1000)

y_pred_train = logisticRegression_predict(X_train, weights)
y_pred_test = logisticRegression_predict(X_test, weights)

y_pred_train = (y_pred_train > 0.5).astype(int)
y_pred_test = (y_pred_test > 0.5).astype(int)

acc_train = logisticRegression_accuracy(y_train, y_pred_train)
acc_test = logisticRegression_accuracy(y_test, y_pred_test)

print('Train accuracy:', acc_train)
print('Test accuracy:', acc_test)
问题原因与修复方案

1. 权重更新未生效(核心问题)

logisticRegression_model函数中,调用logisticRegression_update_weights时未接收返回的更新后权重,导致weights始终是初始全0数组,最终预测值全为0.5,经>0.5判断后输出全0。

修复代码:

def logisticRegression_model(X, y, learning_rate, num_epochs):
    
    weights = np.zeros(X.shape[1])
    
    for epoch in range(num_epochs):
        # 接收更新后的权重
        weights = logisticRegression_update_weights(X, y, weights, learning_rate)
    
    return weights

2. 指数溢出问题

当np.dot(X, weights)结果绝对值过大时,np.exp(-predictions)会超出浮点数范围。可改用稳定版sigmoid实现:

方案一:手动处理溢出

def logisticRegression_predict(X, weights):
    predictions = np.dot(X, weights)
    # 分情况计算避免溢出
    predictions = np.where(predictions >= 0, 
                          1 / (1 + np.exp(-predictions)), 
                          np.exp(predictions) / (1 + np.exp(predictions)))
    return predictions

方案二:使用scipy内置函数(需导入from scipy.special import expit)

def logisticRegression_predict(X, weights):
    predictions = np.dot(X, weights)
    predictions = expit(predictions)
    return predictions

3. 学习率与迭代次数优化

当前学习率0.1过高,易导致权重震荡发散,建议降至0.01或0.001,并根据模型收敛情况调整迭代次数。

4. 添加偏置项

标准Logistic回归需要偏置项(截距),原代码缺失会影响拟合效果。在分割数据集后添加:

# 给训练集和测试集添加全1的偏置列
X_train = np.hstack((np.ones((X_train.shape[0], 1)), X_train))
X_test = np.hstack((np.ones((X_test.shape[0], 1)), X_test))

同时初始化权重时要包含偏置项维度:

def logisticRegression_model(X, y, learning_rate, num_epochs):
    weights = np.zeros(X.shape[1])
    ...

修复后完整代码示例

import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from scipy.special import expit

dataset = pd.read_csv('data.csv')
# 仅标准化特征,目标变量无需标准化
X = dataset.iloc[:, :-1]
y = dataset.iloc[:, -1]
X = (X - X.mean()) / X.std()

# 添加偏置项
X = np.hstack((np.ones((X.shape[0], 1)), X))

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=42)

def logisticRegression_model(X, y, learning_rate, num_epochs):
    weights = np.zeros(X.shape[1])
    for epoch in range(num_epochs):
        weights = logisticRegression_update_weights(X, y, weights, learning_rate)
    return weights

def logisticRegression_update_weights(X, y, weights, learning_rate):
    gradient = logisticRegression_calculate_gradient(X, y, weights)
    weights += learning_rate * gradient
    return weights

def logisticRegression_calculate_gradient(X, y, weights):
    predictions = logisticRegression_predict(X, weights)
    error = y - predictions
    # 按样本数归一化梯度,提升稳定性
    gradient = np.dot(X.T, error) / len(y)
    return gradient

def logisticRegression_predict(X, weights):
    predictions = np.dot(X, weights)
    predictions = expit(predictions)
    return predictions

def logisticRegression_accuracy(y_true, y_pred):
    accuracy = np.sum(y_true == y_pred) / len(y_true)
    return accuracy

def logisticRegression_train(X_train, y_train, learning_rate, num_epochs):
    weights = logisticRegression_model(X_train, y_train, learning_rate, num_epochs)
    return weights

# 调整学习率和迭代次数
weights = logisticRegression_train(X_train, y_train, 0.01, 1000)

y_pred_train = logisticRegression_predict(X_train, weights)
y_pred_test = logisticRegression_predict(X_test, weights)

y_pred_train = (y_pred_train > 0.5).astype(int)
y_pred_test = (y_pred_test > 0.5).astype(int)

acc_train = logisticRegression_accuracy(y_train, y_pred_train)
acc_test = logisticRegression_accuracy(y_test, y_pred_test)

print('Train accuracy:', acc_train)
print('Test accuracy:', acc_test)

内容的提问来源于stack exchange,提问作者Melad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 18:45:31