机器学习笔记——线性回归及其两种常用的优化方法

     作者:奶糖猫

     来源:奶糖猫

何为回归

回归的目的是预测数值型的目标值,最直接的办法是依据输入写出一个目标值的计算公式,比如要计算一个男生可以找到女朋友的概率:

财产 长相 身高

这意味着要综合财产、长相、身高三个因素来判断概率,其中财产也是最重要的因素。

这个式子就可以被称作回归方程,其中0.4和0.3也被称作回归系数,一般来说回归系数都是未知的,我们通过输入数据求得回归系数的过程就是回归,得到回归系数之后,就可以通过公式得到最后的预测值。

这里给出的例子属于线性回归,而回归还有另一种较为复杂的形式——非线性回归,本文只介绍线性回归的相关知识。

线性回归

回归系数推导

线性回归(LR)可分为简单一元线性回归和多元线性回归,也就是我们平时接触的一次线性方程和多次线性方程,二者的主要区别也就是未知项的个数,为了便于理解,这里主要利用一元线性回归为例。

一元线性方程的公式应该是非常熟悉的:

如果将输入数据都存放在矩阵X中,而回归系数都存放在向量 中,这样就可以得到矩阵形式的表达式:

现在的问题是如何找到 ,我们已经知道了如何度量一个分类器的性能,而回归模型的性能通常使用度量方法是“均方误差”,我们可以利用这个公式找到误差最小时的 ,这里的误差是指预测值与真实值之间的差值。

均方误差的表示形式如下:

可以将其转化为矩阵形式:

求导得出下面式子,并令其等于0:

最后解出 如下:

可以看到这里涉及到了对矩阵求逆,所以这个公式只有在可逆矩阵中才适用,就是说只有 为满秩矩阵时,上述等式才成立。矩阵中非零行的个数定义为这个矩阵的秩, 记为R(A),对于矩阵 ,若R(A)=n,则称A为满秩矩阵。

线性拟合

现在有上图这样一个数据集,按照上文所提及的方法计算出最佳拟合直线的回归系数,就可以获得这个数据集的回归曲线。这部分代码如下:

def standRegres(xMat,yMat):
    # 根据公式计算回归系数
    xTx = xMat.T * xMat
    if np.linalg.det(xTx) == 0.0:
        print("矩阵为奇异矩阵,不能求逆")
        return
    ws = xTx.I * (xMat.T*yMat)
    return ws
def plotRegression():
    xMat, yMat = loadDataSet('regression_data.txt')
    ws = standRegres(xMat, yMat) #计算回归系数
    xCopy = xMat.copy() #拷贝一个xMat矩阵
    xCopy.sort(0) # 对xCopy排序,方便绘图
    yHat = xCopy * ws # 计算对应的y值
    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.plot(xCopy[:, 1], yHat, c = 'red') # 绘制回归曲线
    plt.scatter(xMat.A[:,1],yMat.A,c = 'b',s = 10) # 绘制数据集的样本
    plt.show()

这里省略了加载数据集函数,第一个函数standRegres用来计算回归系数,先将x和y以矩阵形式传入,然后计算 ,接下来这个操作可能会比较陌生,因为上文说过了只有可逆矩阵才能求逆,这里linalg.det()方法可以计算矩阵的行列式,在行列式非零情况下,计算回归系数ws并返回。

第二个函数是绘制函数,在第一个函数计算出的回归系数基础上绘制回归曲线,最后绘制图像如下:

几乎任一数据集都可以用上述方法建立一个模型,那么这些模型的好坏程度如何评断呢?“相关系数”就可以计算预测值序列和真实值序列的匹配程度,Numpy中corrcoef方法就刚好可以计算出两个序列的相关性。


上图中主对角线上的1代表自己与自己完全匹配,而次对角线则代表预测值和真实值间的相关性,相关性并不能完全决定模型的好坏,因为相关性过高可能导致过拟合的现象。

局部加权线性回归

上面拟合的回归曲线难免有些粗糙,而且会有一些欠拟合的现象,比如波浪处到直线的距离还是有点远,这很难取得最好的预测效果,而局部加权线性回归(LWLR)通过在估计值中引入一些偏差,从而降低预测的均方误差。

这种方法的基本思想就是给待预测点附近的每个点赋予一定的权重,将这些权重用一个新的矩阵W存储,表现形式如下:

加权模型也会认为样本点之间距离越近,越有可能符合同一个线性模型,所以对于当前预测样本点 来说,离它越近的样本点 将会被赋予更大的权重,利用高斯核就可实现这种机制:

通过这种方式构建了一个只含对角元素的权重矩阵W,上述公式中只包含了一个需要调节的参数k,它决定了对附近的点赋予多大权重。

实际上当k值越大,参与训练的样本点也就越多;反之k值越小,只会有很少的局部点会参与训练。相应的k值过大可能就会出现欠拟合现象,k值过小可能就会出现过拟合现象,所以,k值的选择决定了模型的好坏。

具体代码如下:

def LWLR(testMat,xMat, yMat,k = 1.0):
    m = xMat.shape[0]
    n = testMat.shape[0]
    weights = np.mat(np.eye(m)) # 创建一个单位对角矩阵
    yHat = np.zeros(n) # 创建一个用来存预测值的矩阵
    for i in range(n):
        for j in range(m): # 遍历,根据公式求权重
            diffMat = testMat[i] - xMat[j]
            weights[j, j] = np.exp(diffMat * diffMat.T / (-2.0 * k ** 2))
        xTx = xMat.T * (weights * xMat)
        if np.linalg.det(xTx) == 0.0:
            print("矩阵为奇异矩阵,不能求逆")
            return
        ws = xTx.I * (xMat.T * (weights * yMat))
        yHat[i]=testMat[i]*ws # 求出预测值
    return yHat

这里先初始化了一个权重矩阵weights,形式是主对角线上都为1,其他位置都为0。接着遍历数据集,计算每个样本点对应的权重值,当样本点与待预测点距离越来越远时,权重将会衰减,而k控制衰减的速度。

这里需要注意的是testMat正是xMat本身,因为实际上每个样本的权重是数据集内的样本点之间相互计算得出的,用testMat命名只是方便区分而已,最后可绘制出不同k值对应的回归曲线如下:   

可以看到当k=1.0时和普通的回归曲线没有什么差别;当k=0.01时回归直线拟合的就比较不错了;当k=0.002时回归曲线开始出现棱角,证明曲线的部分受其附近样本点影响很大,导致了过拟合的现象。

随着拟合变准确的同时,该模型也付出了相应的代价,即增加了计算量,因为在对每个点预测的同时都要使用整个数据集,下面将会介绍可以解决该问题的方法。

岭回归

现实生活中 往往不是满秩矩阵,例如在数据集中可能遇到非常多的特征,其数目甚至超过了样本个数,导致X的列数多于行数,此时 显然不满秩,为了解决这个问题,就引入了岭回归(ridge regression)的概念。

岭回归的思想非常简单,就是通过引入一个矩阵 ,并且将这个单位矩阵和 相加,从而将 转化成一个可逆矩阵,进而可以对 求逆,在这种情况下回归系数表达式就可以写成:

这里 是一个单位矩阵,即主对角线上元素为1,其余元素都为0。 称为惩罚项,它的作用就是减少不重要的参数,这个技术被称作缩减,很明显缩减后能取得更好的预测结果。

在使用岭回归和缩减技术之前,需要对特征做标准化处理,这部分我们曾在KNN中也使用过,它的目的就是让每个特征具有相同的重要性,这部分代码如下:

yMean = np.mean(yMat, axis = 0) # 求真实y均值
yMat = yMat - yMean # 真实y值减去均值
xMeans = np.mean(xMat, axis = 0)# 求x均值
xVar = np.var(xMat, axis = 0) #求方差
xMat = (xMat - xMeans) / xVar # 实现标准化

代码的剩余部分和局部加权回归相似,所以就不再展示了,为了方便我们所用数据集还是上文提及的,这里最好使用特征数比样本数多的数据集,但我们只为展示得出的结论,如下:    

这张图绘制了回归系数与 的关系,当 非常小时,得到的系数是和最初线性回归一致的;当 达到一定值时,系数全部缩减成0;所以在中间部分的某值将会取得最好的预测结果。

这里有一条恒为0的蓝色线是因为我们开始时设定了一个特征全为1,所以 对这个特征是没有影响的。若想找到最佳的参数值还需要进行交叉验证,即多次调整参数寻求最优,并且根据每个特征对应系数的大小,也能判断出这个特征对预测结果影响的大小。

缩减方法除了岭回归之外还有lasso、LAR、PCA回归以及子集选择等,这些方法都可以提高预测精准率,感兴趣的伙伴可以自己了解一下。

总结

普通线性回归虽然可以拟合回归曲线,但是过于粗糙,有欠拟合的现象,通过局部加权回归可以得到更好的预测结果,但调参k是关键,k过小可能会出现过拟合的现象。针对现实任务中总出现的不可逆矩阵,缩减技术中的岭回归可以很好的解决该问题,它的主要思想就是通过消除多余的特征降低预测误差。

End

◆ ◆ ◆  ◆ ◆

长按二维码关注我们


数据森麟公众号的交流群已经建立,许多小伙伴已经加入其中,感谢大家的支持。大家可以在群里交流关于数据分析&数据挖掘的相关内容,还没有加入的小伙伴可以扫描下方管理员二维码,进群前一定要关注公众号奥,关注后让管理员帮忙拉进群,期待大家的加入。

管理员二维码:

猜你喜欢

 笑死人不偿命的知乎沙雕问题排行榜

 用Python扒出B站那些“惊为天人”的阿婆主!

 全球股市跳水大战,谁最坑爹!

 华农兄弟、徐大Sao&李子柒?谁才是B站美食区的最强王者?

 你相信逛B站也能学编程

  • 1
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
线性回归是一种常见的机器学习算法,它用于预测一个连续的因变量(或称为响应变量)Y,与一个或多个自变量(或称为预测变量)X 相关的值。在线性回归中,我们假设因变量与自变量之间存在线性关系,并通过最小化残差平方和来拟合数据。 一般来说,我们采用梯度下降法(Gradient Descent)来优化线性回归模型的参数,使得残差平方和最小化。梯度下降法是一种基于迭代的优化方法,它通过不断调整参数使得目标函数不断逼近最小值。具体来说,梯度下降法的步骤如下: 1. 初始化模型参数,如权重向量 w 和偏置 b。 2. 计算目标函数 J(w,b) 的梯度,即对每个参数求偏导数。 3. 更新模型参数,即按照梯度的反方向调整参数,使得目标函数下降。 4. 重复步骤 2 和 3,直到达到设定的停止条件。 在梯度下降法中,更新参数的公式为: w := w - α * ∂J(w,b)/∂w b := b - α * ∂J(w,b)/∂b 其中,α 表示学习率,用来控制每次更新参数的步长。学习率过大会导致震荡,学习率过小会导致收敛速度缓慢。 对于线性回归问题,我们可以采用批量梯度下降法(Batch Gradient Descent)来更新参数。具体来说,批量梯度下降法每次使用全部的样本来计算梯度,然后更新参数。这样做的好处是可以保证每次更新的方向是整体最优的,但是计算量较大,不适合大规模数据集。 除了批量梯度下降法,还有随机梯度下降法(Stochastic Gradient Descent)和小批量梯度下降法(Mini-batch Gradient Descent)。随机梯度下降法每次只使用一个样本来计算梯度和更新参数,计算量较小,但是更新方向不一定最优。小批量梯度下降法每次使用一部分样本来计算梯度和更新参数,权衡了计算量和更新方向的优劣。 在实际应用中,我们可以根据数据集的大小和计算资源的限制来选择合适的梯度下降法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值