从零实现机器学习算法(九) 线性回归

目录

1. 回归简介

2. 回归模型

2.1 线性回归

2.2 局部加权回归

2.3 岭回归

2.4 Lasso回归

2.5 逐步线性回归

3. 总结与分析


1. 回归简介

在客观世界中普遍存在着变量与变量之间的关系。变量之间的关系一般可以分为确定关系和不确定关系。确定关系是指变量之间的关系可以通过函数关系来表达。非确定关系即所谓的相关关系。而回归分析是研究非确定关系的方法,可以帮助我们从一个或一系列变量的值去估计另一个变量的值。

线性回归模型为

h_{\theta}\left(x\right)=\theta^{T}x

通过最小化损失函数

J\left(\theta\right)=\sum^{m}_{i=1}\left(h_{\theta}\left(x\right)^{(i)}-y^{(i)}\right)^{2}

求得最优的 \theta 。具体的方法有线性回归、局部加权回归岭回归Lasso回归逐步线性回归等

2. 回归模型

2.1 线性回归

线性回归求解 \theta 有两种方法,一种是使用梯度下降法求解,另一种是通过正规方程求解。梯度下降法前面已经介绍过了,下面介绍下正规方程的解法。

对损失函数求导

\begin{align*} \nabla_{\theta}J\left(\theta\right)& =\nabla_{\theta}\frac{1}{2}\left(X\theta-Y\right)^{T}\left(X\theta-Y\right)\\ &= \frac{1}{2}\nabla_{\theta}\left(\theta^{T}X^{T}X\theta-\theta^{T}X^{T}Y-YX\theta+Y^{T}Y\right)\\ &=\frac{1}{2}\nabla_{\theta}tr\left(\theta^{T}X^{T}X\theta-\theta^{T}X^{T}Y-YX\theta+Y^{T}Y\right)\\ &=\frac{1}{2}\nabla_{\theta}\left(tr\theta^{T}X^{T}X\theta-2trYX\theta\right)\\ &=\frac{1}{2}\nabla_{\theta}\left(X^{T}X\theta+X^{T}X\theta-2X^{T}Y\right)\\ &= X^{T}X\theta-X^{T}Y \end{align*}

令导数等于0,得

X^{T}X\theta=X^{T}Y

解得

\theta=\left(X^{T}X\right)^{-1}X^{T}Y

其中 X 为训练集, Y 为训练集标签。线性回归代码如下:

    def standardLinearRegression(self, x, y):
        if self.norm_type == "Standardization":
            x = preProcess.Standardization(x)
        else:
            x = preProcess.Normalization(x)

        xTx = np.dot(x.T, x)
        if np.linalg.det(xTx) == 0:   # calculate the Determinant of xTx
            print("Error: Singluar Matrix !")
            return
        w = np.dot(np.linalg.inv(xTx), np.dot(x.T, y))
        return w

2.2 局部加权回归

线性回归容易出现欠拟合的现象,因为它求的是具有最小均方差的无偏估计。为了解决这一问题,局部加权回归在待预测点附近的每一个点赋予一定的权重,然后在这个自己是基于最小均方差来进行普通的回归分析。对于局部加权回归来说其损失函数为

J\left(\theta\right)=\sum^{m}_{i=1}w^{(i)}\left(h_{\theta}\left(x\right)^{(i)}-y^{(i)}\right)^{2}

和线性回归类似,对损失函数求导,然后令导数为零可得

\theta=\left(X^{T}WX\right)^{-1}X^{T}WY

对于局部加权回归的权重 w 类似于支持向量机的核函数,常用的为高斯核函数

w^{(i)}=exp\left(-\frac{\left(x^{(i)}-x\right)^{T}\left(x^{(i)}-x\right)}{2\tau^{2}}\right)

局部加权回归代码:

    def LWLinearRegression(self, x, y, sample):
        if self.norm_type == "Standardization":
            x = preProcess.Standardization(x)
        else:
            x = preProcess.Normalization(x)

        sample_num = len(x)
        weights = np.eye(sample_num)
        for i in range(sample_num):
            diff = sample - x[i, :]
            weights[i, i] = np.exp(np.dot(diff, diff.T)/(-2 * self.k ** 2))
        xTx = np.dot(x.T, np.dot(weights, x))
        if np.linalg.det(xTx) == 0:
            print("Error: Singluar Matrix !")
            return
        result = np.dot(np.linalg.inv(xTx), np.dot(x.T, np.dot(weights, y)))
        return np.dot(sample.T, result)

2.3 岭回归

在做回归分析时,有时候特征维度比样本数量多,此时输入的特征矩阵不是满秩的,因此不存在其逆矩阵。为了解决这个问题,岭回归在矩阵 X^{T}X 上加上一个 \lambda I 使得矩阵非奇异。实际上,对于岭回归来说,其损失函数加上一个L2正则化项,即

J\left(\theta\right)=\sum^{m}_{i=1}\left(h_{\theta}\left(x\right)^{(i)}-y^{(i)}\right)^{2}+\lambda\left| |\theta| \right|_{2}

和线性回归类似,对损失函数求导,然后令导数为零可得

\theta=\left(X^{T}X+\lambda^{2}I\right)^{-1}X^{T}Y

岭回归代码如下:

    def ridgeRegression(self, x, y):
        if self.norm_type == "Standardization":
            x = preProcess.Standardization(x)
        else:
            x = preProcess.Normalization(x)

        feature_dim = len(x[0])
        xTx = np.dot(x.T, x)
        matrix = xTx + np.exp(feature_dim)*self.lamda
        if np.linalg.det(xTx) == 0:
            print("Error: Singluar Matrix !")
            return
        w = np.dot(np.linalg.inv(matrix), np.dot(x.T, y))
        return w

2.4 Lasso回归

Lasso与岭回归类似,Lasso回归也是在损失函数上增加正则化项。但是Lasso正价的是L1正则化项,即

J\left(\theta\right)=\sum^{m}_{i=1}\left(h_{\theta}\left(x\right)^{(i)}-y^{(i)}\right)^{2}+\lambda\left| |\theta| \right|_{1}

由于L1范数采用的是绝对值导致Lasso不是处处可导的,因此不能使用梯度下降或者牛顿法来求解。这里使用坐标下降法求得最优的 \theta 值。坐标下降法通过每次沿一个方向优化获取最小值,即

\theta^{i+1}_{j}=arg\min\limits_{\theta_{i}} J\left(\theta_{1},\theta_{2}^{(i-1)},..., \theta_{n}^{(i-1)}\right)

坐标下降法可以得到闭式解

其中

\rho_{j}=\sum_{i=1}^{m}x_{j}^{(i)}\left(y^{(i)}-\sum_{k\ne j}^{n}\theta_{k}x_{k}^{(i)}\right)\\=\sum_{i=1}^{m}x_{j}^{(i)}\left(y^{(i)}-\hat y_{pred}^{(i)}+\theta_{j}x^{(i)}_{j}\right)

\lambda 为系数。

Lasso回归代码:

 def lassoRegression(self, x, y):
        if self.norm_type == "Standardization":
            x = preProcess.Standardization(x)
        else:
            x = preProcess.Normalization(x)

        y = np.expand_dims(y, axis=1)
        sample_num, feataure_dim = np.shape(x)
        w = np.ones([feataure_dim, 1])
        for i in range(self.iterations):
            for j in range(feataure_dim):
                h = np.dot(x[:, 0:j], w[0:j]) + np.dot(x[:, j+1:], w[j+1:])
                w[j] = np.dot(x[:, j], (y - h))
                if j == 0:
                    w[j] = 0
                else:
                    w[j] = self.softThreshold(w[j])
        return w

2.5 逐步线性回归

逐步线性回归和Lasso算法类似,它采用贪心算法,每一次所做的决策是对权重增加或者减少一个很小的值。

逐步线性回归代码如下:

 def forwardstepRegression(self, x, y):
        if self.norm_type == "Standardization":
            x = preProcess.Standardization(x)
        else:
            x = preProcess.Normalization(x)

        sample_num, feature_dim = np.shape(x)
        w = np.zeros([self.iterations, feature_dim])
        best_w = np.zeros([feature_dim, 1])
        for i in range(self.iterations):
            min_error = np.inf
            for j in range(feature_dim):
                for sign in [-1, 1]:
                    temp_w = best_w
                    temp_w[j] += sign * self.learning_rate
                    y_hat = np.dot(x, temp_w)
                    error = ((y - y_hat) ** 2).sum()                # MSE
                    if error < min_error:                           # save the best parameters
                        min_error = error
                        best_w = temp_w
            w = best_w
        return w

3. 总结与分析

线性回归分析的内容还是蛮多的,其中很多方法都有相应的改进算法,这里值介绍了它们的基础算法。最后贴一下本文实现的线性回归与Sklearn检测性能的比较。

                                                       Sklearn线性回归

                                                         本文线性回归

 

发现两者运行时间差不多,但是Sklearn的回归效果要好一些,本文的到后来就飘了。

本文相关代码和数据集:https://github.com/Ryuk17/MachineLearning

参考文献:

[1] 【机器学习】一文读懂正则化与LASSO回归,Ridge回归

[2] Peter Harrington, Machine Learning IN ACTION

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值