Python中使用梯度下降的线性回归

数据挖掘 机器学习 Python 线性回归 梯度下降 执行
2022-02-27 20:07:13

我正在尝试在不使用任何内置机器库的情况下实现一个简单的多元线性回归模型。到目前为止,我已经能够获得大约的训练均方根误差,并且来自正常(封闭形式)方程的模型能够产生的训练 RMSE 。我正在寻找可以改进梯度下降算法实现的方法。下面是我的实现:2.93 2.3

我的梯度下降方法如下所示: 其中是模型参数,是训练元素的数量,是input 和是目标元素。是步长。θ=θ[(α/2N)X(XθY)]θNXYα

def gradientDescent(self):
    for i in range(self.iters):
        # T = T - (\alpha/2N) * X*(XT - Y)
        self.theta = self.theta - (self.alpha/len(self.X)) * np.sum(self.X * (self.X @ self.theta.T - self.Y), axis=0)
    return errors

我将设置为,将迭代次数设置为 1000。梯度下降在大约 700-800 次迭代(检查)时达到收敛。α0.1

我的错误函数是这样的:

def error_function(self):
        # Error function: (1/2N) * (XT - Y)^2 where T is theta
        error_values = np.power(((self.X @ self.theta.T) - self.Y), 2)
        return np.sum(error_values)/(2 * len(self.X))

我期待梯度下降的训练误差和正规方程会变得相似,但它们有一点巨大的差异。所以,我想知道我是否做错了什么。

PS我还没有标准化数据。归一化导致更低的 RMSE (~ )0.22

1个回答

这可能是由于许多不同的原因。最重要的是,您的成本函数可能会陷入局部最小值。要解决此问题,您可以使用不同的学习率或更改系数的初始化。

您的代码中可能存在更新权重或计算梯度的问题。

但是,我将这两种方法都用于简单的线性回归,并得到了相同的结果,如下所示:

import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.datasets import make_regression


# generate regression dataset
X, y = make_regression(n_samples=100, n_features=1, noise=30)



def cost_MSE(y_true, y_pred):
    '''
    Cost function
    '''
    # Shape of the dataset
    n = y_true.shape[0]
    
    # Error 
    error = y_true - y_pred
    # Cost
    mse = np.dot(error, error) / n
    return mse


def cost_derivative(X, y_true, y_pred):
    '''
    Compute the derivative of the loss function
    '''
    # Shape of the dataset
    n = y_true.shape[0]
    
    # Error 
    error = y_true - y_pred
    
    # Derivative
    der = -2 / n * np.dot(X, error)

    return der


# Lets run an example

X_new = np.concatenate((np.ones(X.shape), X), axis = 1)
learning_rate = 0.1
X_new_T = X_new.T
n_iters = 100
mse = []

#initialize the weight vector
alpha = np.array([0, np.random.rand()])

for _ in range(n_iters):
    
    # Compute the predicted y
    y_pred = np.dot(X_new, alpha)
    
    # Compute the MSE
    mse.append(cost_MSE(y, y_pred))
    
    # Compute the derivative
    der = cost_derivative(X_new_T, y, y_pred)
    
    # Update the weight
    alpha  -= learning_rate * der
alpha

对于梯度下降,系数为:

array([-3.36575322, 28.06370831])

这是封闭形式解决方案的代码:

np.dot(np.linalg.inv(np.dot(X_new_T,X_new)), np.dot(X_new_T, y))

以及闭式解的系数:

array([-3.36575322, 28.06370831])

由于系数相等,RMSE、MSE、R2 相等。