《机器学习实战》8.3 线性回归之缩减系数来'理解'数据

《机器学习实战》8.3 线性回归之缩减系数来’理解’数据

搜索微信公众号:‘AI-ming3526’或者’计算机视觉这件小事’ 获取更多人工智能、机器学习干货
csdn:https://blog.csdn.net/baidu_31657889/
github:https://github.com/aimi-cn/AILearners

本文出现的所有代码,均可在github上下载,不妨来个Star把谢谢~:Github代码地址

一、引言

本篇文章讲解线性回归的缩减方法–岭回归以及逐步线性回归。

二、岭回归

如果数据的特征比样本点还多应该怎么办?很显然,此时我们不能再使用上文的方法进行计算了,因为矩阵X不是满秩矩阵,非满秩矩阵在求逆时会出现问题。为了解决这个问题,统计学家引入岭回归(ridge regression)的概念。

2.1 什么是岭回归?

岭回归即我们所说的L2正则线性回归,在一般的线性回归最小化均方误差的基础上增加了一个参数w的L2范数的罚项,从而最小化罚项残差平方和:

在这里插入图片描述

简单说来,岭回归就是在普通线性回归的基础上引入单位矩阵。回归系数的计算公式变形如下:

在这里插入图片描述

式中,矩阵I是一个mxm的单位矩阵,加上一个λI从而使得矩阵非奇异,进而能对矩阵求逆。

岭回归最先用来处理特征数多于样本数的情况,现在也用于在估计中加入偏差,从而得到更好的估计。这里通过引入λ来限制了所有w之和,通过引入该惩罚项,能够减少不重要的参数,这个技术在统计学中也可以叫做缩减(shrinkage)。

缩减方法可以去掉不重要的参数,因此能更好地裂解数据。此外,与简单的线性回归相比,缩减法能够取得更好的预测效果。

2.2、编写代码

为了使用岭回归和缩减技术,首先需要对特征做标准化处理。因为,我们需要使每个维度特征具有相同的重要性。本文使用的标准化处理比较简单,就是将所有特征都减去各自的均值并除以方差。

创建regression02.py文件
代码很简单,处理的文件是前文中的鲍鱼的数据,只需要稍做修改,其中,λ为模型的参数。我们先绘制一个回归系数与log(λ)的曲线图,看下它们的规律,编写代码如下:

#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@File    :   regression.py
@Time    :   2019/07/01 19:02:32
@Author  :   xiao ming 
@Version :   1.0
@Contact :   xiaoming3526@gmail.com
@Desc    :   岭回归以及逐步线性回归
@github  :   https://github.com/aimi-cn/AILearners
'''

# here put the import lib
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties

'''
@description: 加载数据
@param:fileName - 文件名
@return:  xArr - x数据集
        yArr - y数据集
'''
def loadDataSet(fileName):
    numFeat = len(open(fileName).readline().split('\t')) - 1
    xArr = []; yArr = []
    fr = open(fileName)
    for line in fr.readlines():
        lineArr =[]
        curLine = line.strip().split('\t')
        for i in range(numFeat):
            lineArr.append(float(curLine[i]))
        xArr.append(lineArr)
        yArr.append(float(curLine[-1]))
    return xArr, yArr

'''
@description: 岭回归
@param: xMat - x数据集
        yMat - y数据集
        lam - 缩减系数
@return: ws - 回归系数
'''
def ridgeRegres(xMat, yMat, lam = 0.2):
    xTx = xMat.T * xMat
    denom = xTx + np.eye(np.shape(xMat)[1]) * lam
    if np.linalg.det(denom) == 0.0:
        print("矩阵为奇异矩阵,不能转置")
        return
    ws = denom.I * (xMat.T * yMat)
    return ws

'''
@description: 岭回归测试
@param:xMat - x数据集
        yMat - y数据集
@return: wMat - 回归系数矩阵
'''
def ridgeTest(xArr, yArr):
    xMat = np.mat(xArr); yMat = np.mat(yArr).T
    #数据标准化
    yMean = np.mean(yMat, axis = 0)                        #行与行操作,求均值
    yMat = yMat - yMean                                    #数据减去均值
    xMeans = np.mean(xMat, axis = 0)                    #行与行操作,求均值
    xVar = np.var(xMat, axis = 0)                        #行与行操作,求方差
    xMat = (xMat - xMeans) / xVar                        #数据减去均值除以方差实现标准化
    numTestPts = 30                                        #30个不同的lambda测试
    wMat = np.zeros((numTestPts, np.shape(xMat)[1]))    #初始回归系数矩阵
    for i in range(numTestPts):                            #改变lambda计算回归系数
        ws = ridgeRegres(xMat, yMat, np.exp(i - 10))    #lambda以e的指数变化,最初是一个非常小的数,
        wMat[i, :] = ws.T                                 #计算回归系数矩阵
    return wMat

'''
@description: 绘制岭回归系数矩阵
@param:None
@return: None
'''
def plotwMat():
    font = FontProperties(fname=r"c:\windows\fonts\simsun.ttc", size=14)
    abX, abY = loadDataSet('C:/Users/Administrator/Desktop/blog/github/AILearners/data/ml/jqxxsz/8.Regression/abalone.txt')
    redgeWeights = ridgeTest(abX, abY)
    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.plot(redgeWeights)    
    ax_title_text = ax.set_title(u'log(lambada)与回归系数的关系', FontProperties = font)
    ax_xlabel_text = ax.set_xlabel(u'log(lambada)', FontProperties = font)
    ax_ylabel_text = ax.set_ylabel(u'回归系数', FontProperties = font)
    plt.setp(ax_title_text, size = 20, weight = 'bold', color = 'red')
    plt.setp(ax_xlabel_text, size = 10, weight = 'bold', color = 'black')
    plt.setp(ax_ylabel_text, size = 10, weight = 'bold', color = 'black')
    plt.show()

if __name__ == '__main__':
    plotwMat()

运行结果如下:

在这里插入图片描述

图绘制了回归系数与log(λ)的关系。在最左边,即λ最小时,可以得到所有系数的原始值(与线性回归一致);而在右边,系数全部缩减成0;在中间部分的某个位置,将会得到最好的预测结果。想要得到最佳的λ参数,可以使用交叉验证的方式获得,文章的后面会继续讲解。

三、前向逐步线性回归

前向逐步线性回归算法属于一种贪心算法,即每一步都尽可能减少误差。我们计算回归系数,不再是通过公式计算,而是通过每次微调各个回归系数,然后计算预测误差。那个使误差最小的一组回归系数,就是我们需要的最佳回归系数。

创建regression03.py文件
前向逐步线性回归实现也很简单。当然,还是先进行数据标准化,编写代码如下:

#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@File    :   regression03.py
@Time    :   2019/07/15 20:47:44
@Author  :   xiao ming 
@Version :   1.0
@Contact :   xiaoming3526@gmail.com
@Desc    :   岭回归以及逐步线性回归
@github  :   https://github.com/aimi-cn/AILearners
'''

# here put the import lib
from matplotlib.font_manager import FontProperties
import matplotlib.pyplot as plt
import numpy as np

'''
@description: 加载数据
@param: fileName - 文件名
@return:  xArr - x数据集
        yArr - y数据集
'''
def loadDataSet(fileName):
    numFeat = len(open(fileName).readline().split('\t')) - 1
    xArr = []; yArr = []
    fr = open(fileName)
    for line in fr.readlines():
        lineArr =[]
        curLine = line.strip().split('\t')
        for i in range(numFeat):
            lineArr.append(float(curLine[i]))
        xArr.append(lineArr)
        yArr.append(float(curLine[-1]))
    return xArr, yArr

'''
@description: 数据标准化
@param: xMat - x数据集
        yMat - y数据集
@return:  inxMat - 标准化后的x数据集
        inyMat - 标准化后的y数据集
'''
def regularize(xMat, yMat):
    inxMat = xMat.copy()                                                        #数据拷贝
    inyMat = yMat.copy()
    yMean = np.mean(yMat, 0)                                                    #行与行操作,求均值
    inyMat = yMat - yMean                                                        #数据减去均值
    inMeans = np.mean(inxMat, 0)                                                   #行与行操作,求均值
    inVar = np.var(inxMat, 0)                                                     #行与行操作,求方差
    inxMat = (inxMat - inMeans) / inVar                                            #数据减去均值除以方差实现标准化
    return inxMat, inyMat

'''
@description: 计算平方误差
@param:yArr - 预测值
        yHatArr - 真实值
@return: 平方误差
'''
def rssError(yArr,yHatArr):
    return ((yArr-yHatArr)**2).sum()

'''
@description: 前向逐步线性回归
@param: xArr - x输入数据
        yArr - y预测数据
        eps - 每次迭代需要调整的步长
        numIt - 迭代次数
@return: returnMat - numIt次迭代的回归系数矩阵
'''
def stageWise(xArr, yArr, eps = 0.01, numIt = 100):
    xMat = np.mat(xArr); yMat = np.mat(yArr).T                                         #数据集
    xMat, yMat = regularize(xMat, yMat)                                                #数据标准化
    m, n = np.shape(xMat)
    returnMat = np.zeros((numIt, n))                                                #初始化numIt次迭代的回归系数矩阵
    ws = np.zeros((n, 1))                                                            #初始化回归系数矩阵
    wsTest = ws.copy()
    wsMax = ws.copy()
    for i in range(numIt):                                                            #迭代numIt次
        # print(ws.T)                                                                    #打印当前回归系数矩阵
        lowestError = float('inf');                                                 #正无穷
        for j in range(n):                                                            #遍历每个特征的回归系数
            for sign in [-1, 1]:
                wsTest = ws.copy()
                wsTest[j] += eps * sign                                                #微调回归系数
                yTest = xMat * wsTest                                                #计算预测值
                rssE = rssError(yMat.A, yTest.A)                                    #计算平方误差
                if rssE < lowestError:                                                #如果误差更小,则更新当前的最佳回归系数
                    lowestError = rssE
                    wsMax = wsTest
        ws = wsMax.copy()
        returnMat[i,:] = ws.T                                                         #记录numIt次迭代的回归系数矩阵
    return returnMat

'''
@description: 绘制岭回归系数矩阵
@param:None
@return: None
'''
def plotstageWiseMat():
    font = FontProperties(fname=r"c:\windows\fonts\simsun.ttc", size=14)
    xArr, yArr = loadDataSet('C:/Users/Administrator/Desktop/blog/github/AILearners/data/ml/jqxxsz/8.Regression/abalone.txt')
    returnMat = stageWise(xArr, yArr, 0.005, 1000)
    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.plot(returnMat)    
    ax_title_text = ax.set_title(u'前向逐步回归:迭代次数与回归系数的关系', FontProperties = font)
    ax_xlabel_text = ax.set_xlabel(u'迭代次数', FontProperties = font)
    ax_ylabel_text = ax.set_ylabel(u'回归系数', FontProperties = font)
    plt.setp(ax_title_text, size = 15, weight = 'bold', color = 'red')
    plt.setp(ax_xlabel_text, size = 10, weight = 'bold', color = 'black')
    plt.setp(ax_ylabel_text, size = 10, weight = 'bold', color = 'black')
    plt.show()

if __name__ == '__main__':
    plotstageWiseMat()

运行结果如下:

在这里插入图片描述

还是,我们打印了迭代次数与回归系数的关系曲线。可以看到,有些系数从始至终都是约为0的,这说明它们不对目标造成任何影响,也就是说这些特征很可能是不需要的。逐步线性回归算法的优点在于它可以帮助人们理解有的模型并做出改进。当构建了一个模型后,可以运行该算法找出重要的特征,这样就有可能及时停止对那些不重要特征的收集。

总结一下:

缩减方法(逐步线性回归或岭回归),就是将一些系数缩减成很小的值或者直接缩减为0。这样做,就增大了模型的偏差(减少了一些特征的权重),通过把一些特征的回归系数缩减到0,同时也就减少了模型的复杂度。消除了多余的特征之后,模型更容易理解,同时也降低了预测误差。但是当缩减过于严厉的时候,就会出现过拟合的现象,即用训练集预测结果很好,用测试集预测就糟糕很多。

AIMI-CN AI学习交流群【1015286623】 获取更多AI资料
扫码加群:
在这里插入图片描述

分享技术,乐享生活:我们的公众号‘计算机视觉这件小事’每周推送“AI”系列资讯类文章,欢迎您的关注!
在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
机器学习中,线性回归是一种常见的实战方法。线性回归的目标是通过拟合一个线性模型来预测一个连续的目标变量。在实际应用中,线性回归可以用于预测房价、销售量等连续变量。 线性回归的基本定义是通过最小化预测值与真实值之间的平方误差来拟合一个线性模型。这可以通过梯度下降算法来实现。梯度下降算法是一种迭代优化算法,通过不断调整模型参数来最小化损失函数。 在线性回归中,我们可以使用最小二乘法来计算模型参数。最小二乘法通过求解正规方程来得到模型参数的闭式解。然而,当矩阵为非满秩矩阵时,无法求逆,这时可以采用岭回归来解决这个问题。岭回归通过在矩阵的转置乘以矩阵上加上一个正则化项来使矩阵非奇异,从而能够求逆。 另一种方法是使用梯度下降算法来求解线性回归模型的参数。梯度下降算法通过不断迭代调整模型参数来最小化损失函数。在每一次迭代中,算法根据损失函数的梯度方向更新模型参数。通过不断迭代,梯度下降算法可以逐渐接近最优解。 在实际应用中,线性回归可以通过使用不同的特征工程方法来提高模型的性能。特征工程包括选择合适的特征、处理缺失值、进行特征缩放等。此外,线性回归还可以通过引入正则化项来防止过拟合问题。 总结起来,机器学习中的线性回归是一种常见的实战方法,可以通过最小化预测值与真实值之间的平方误差来拟合一个线性模型。可以使用最小二乘法或梯度下降算法来求解模型参数。在实际应用中,还可以通过特征工程和正则化来提高模型性能。 #### 引用[.reference_title] - *1* [机器学习实战(一)—— 线性回归](https://blog.csdn.net/qq_44715621/article/details/110449232)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [机器学习实战----线性回归](https://blog.csdn.net/zhangyingjie09/article/details/83018072)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [机器学习实战线性回归](https://blog.csdn.net/luoluopan/article/details/88052806)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值