从零实现梯度下降线性回归遇数值异常问题求助
修复梯度下降线性回归中的数值异常问题
问题描述
从零实现基于梯度下降的线性回归算法,在CSV数据集上测试时,运行出现以下警告:
RuntimeWarning: invalid value encountered in subtract
self.weights = self.weights - self.lr * dw
已解决语法问题,附上完整代码,需要修复该数值异常问题。
可能原因及解决方案
1. 数据存在缺失值
如果CSV数据中特征或目标列存在NaN,会导致梯度计算过程中出现无效值,最终引发权重更新时的异常。
解决方法:检查并清理缺失值
df = pd.read_csv('prices.csv') # 查看各列缺失值数量 print(df.isnull().sum()) # 删除特征列和目标列含缺失值的行 df = df.dropna(subset=[df.columns[2], df.columns[3]])
2. 特征未做标准化/归一化
若特征数值范围过大(比如房价、销售额这类量级较大的数据),梯度dw的数值会异常大,乘以学习率后更新权重时会出现数值爆炸,最终变成NaN或无穷大。
解决方法:对特征进行标准化处理
from sklearn.preprocessing import StandardScaler # 加载数据并清理后 X = df.iloc[:,2].values.reshape(-1,1) y = df.iloc[:,3].values # 标准化特征 scaler = StandardScaler() X = scaler.fit_transform(X)
3. 学习率设置过高
过大的学习率会让梯度下降的步长超出合理范围,导致权重更新后数值溢出,引发无效值警告。
解决方法:调小学习率
# 比如将学习率从0.01改为0.001,可根据数据情况进一步调整 reg = LinReg(lr=0.001, n_iters=1000)
4. MSE计算逻辑错误
当前代码中的MSE计算是均值的平方,而非正确的平方的均值,这会导致评估指标错误,需修正。
解决方法:修正MSE函数
def MSE(y_test, predictions): # 正确的MSE是平方误差的均值 return np.mean((y_test - predictions)**2)
修改后的完整代码
import numpy as np from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler import matplotlib.pyplot as plt import pandas as pd class LinReg(): def __init__(self, lr=0.001, n_iters=1000): self.lr = lr self.n_iters = n_iters self.weights = None self.bias = None 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_iters): y_pred = np.dot(X, self.weights) + self.bias dw = (1/n_samples) * np.dot(X.T, (y_pred - y)) db = (1/n_samples) * np.sum(y_pred - y) self.weights = self.weights - self.lr * dw self.bias = self.bias - self.lr * db def predict(self, X): y_pred = np.dot(X, self.weights) + self.bias return y_pred # 加载并清理数据 df = pd.read_csv('prices.csv') print(df.isnull().sum()) df = df.dropna(subset=[df.columns[2], df.columns[3]]) # 提取特征和目标变量并标准化 X = df.iloc[:,2].values.reshape(-1,1) y = df.iloc[:,3].values 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=1234) # 训练模型并预测 reg = LinReg(lr=0.001, n_iters=1000) reg.fit(X_train, y_train) predictions = reg.predict(X_test) # 计算MSE def MSE(y_test, predictions): return np.mean((y_test - predictions)**2) mse_value = MSE(y_test, predictions) print(f"MSE: {mse_value}") # 可视化结果 y_pred_line = reg.predict(X) cmap = plt.get_cmap('viridis') fig = plt.figure(figsize=(8,6)) plt.scatter(X_train, y_train, color=cmap(0.9), s=10, label='训练集') plt.scatter(X_test, y_test, color=cmap(0.5), s=10, label='测试集') plt.plot(X, y_pred_line, color='black', linewidth=2, label="回归直线") plt.legend() plt.show() print(y_pred_line)
内容的提问来源于stack exchange,提问作者user8083
相关产品推荐
相关产品推荐

