机器学习实战第8章预测数值型数据:回归2

1. Shrinkage(缩减) Methods

当特征比样本点还多时(n>m),输入的数据矩阵X不是满秩矩阵,在求解(XTX)-1时会出现错误。接下来主要介绍岭回归(ridge regression)和前向逐步回归(Foward Stagewise Regression)两种方法。

1.1 岭回归(ridge regression)

简单来说,岭回归就是在矩阵XTX上加上一个从而使得矩阵非奇异,进而能进行求逆。其中矩阵I是一个单位矩阵,是一个调节参数。

岭回归的回归系数计算公式为:

岭回归最先用来处理特征数多于样本的情况,现在也用于在估计中加入偏差,来得到更好的估计。当=0时,岭回归和普通线性回归一样,当趋近于正无穷时,回归系数接近于0。可以通过交叉验证的方式得到使测试结果最好的值。

岭回归代码:

 1 # encoding: utf-8
 2 ‘‘‘
 3 @Author: shuhan Wei
 4 @File: ridgeRegression.py
 5 @Time: 2018/8/24 11:16
 6 ‘‘‘
 7 import numpy as np
 8 import matplotlib.pyplot as plt
 9
10 def loadDataSet(fileName):
11     numFeat = len(open(fileName).readline().split(‘\t‘)) - 1
12     dataMat = []; labelMat = []
13     fr = open(fileName)
14     for line in fr.readlines():
15         lineArr = []
16         curLine = line.strip().split(‘\t‘)
17         for i in range(numFeat):
18             lineArr.append(float(curLine[i]))
19         dataMat.append(lineArr)
20         labelMat.append(float(curLine[-1]))
21     return dataMat, labelMat
22
23
24 """
25     函数说明:岭回归函数 w=(XT*X+lamI)-1 * XT*y
26     Parameters:
27         xMat - x数据集
28         yMat - y数据集
29         lam - 用户自定义参数
30     Returns:
31         ws  - 回归系数
32 """
33 def ridgeRegres(xMat, yMat, lam=0.2):
34     xTx = xMat.T * xMat
35     denom = xTx + np.eye(np.shape(xMat)[1]) * lam
36     if np.linalg.det(denom) == 0.0:
37         print("The matrix is singular, cannot do inverse")
38         return
39     ws = denom.I * (xMat.T * yMat)
40     return ws
41
42
43 """
44     函数说明:测试岭回归
45     Parameter:
46         xArr - x数据集矩阵
47         yArr - y数据集矩阵
48     Returns:
49         wMat - 回归系数矩阵,30组系数
50 """
51 def ridgeTest(xArr, yArr):
52     xMat = np.mat(xArr); yMat = np.mat(yArr).T
53     #对数据进行标准化处理
54     yMean = np.mean(yMat, 0)
55     yVar = np.var(yMat,0)
56     yMat = yMat - yMean
57     xMeans = np.mean(xMat,0)    #行操作
58     xVar = np.var(xMat, 0)
59     xMat = (xMat - xMeans) / xVar
60     numTestPts = 30 # 在30个不同lambda值下
61     wMat = np.zeros((numTestPts, np.shape(xMat)[1]))  #系数矩阵
62     for i in range(numTestPts):
63         ws = ridgeRegres(xMat, yMat, np.exp(i-10))
64         wMat[i,:] = ws.T
65     return wMat
66
67 """
68     函数说明:绘制回归系数与lambda关系曲线
69 """
70 def plotLambda(ridgeWeights):
71     plt.rcParams[‘font.sans-serif‘] = [‘SimHei‘]
72     plt.rcParams[‘axes.unicode_minus‘] = False
73     fig = plt.figure()
74     ax = fig.add_subplot(111)
75     ax.plot(ridgeWeights)
76     ax_title_text = ax.set_title(u‘log(lambada)与回归系数的关系‘)
77     ax_xlabel_text = ax.set_xlabel(u‘log(lambada)‘)
78     ax_ylabel_text = ax.set_ylabel(u‘回归系数‘)
79     plt.setp(ax_title_text, size=20, weight=‘bold‘, color=‘red‘)
80     plt.setp(ax_xlabel_text, size=10, weight=‘bold‘, color=‘black‘)
81     plt.setp(ax_ylabel_text, size=10, weight=‘bold‘, color=‘black‘)
82     plt.show()
83
84
85 if __name__ == ‘__main__‘:
86     abX, abY = loadDataSet(‘abalone.txt‘)
87     ridgeWeights = ridgeTest(abX, abY)
88     plotLambda(ridgeWeights)

 1.2 前向逐步回归(Foward Stagewise Regression)

前向逐步回归算法属于一种贪心算法,即每一步都尽可能减少误差,一开始所有的权重都设置为1,然后每一步对权重增加或减少一个很小的值。

算法是伪代码如下:

 数据标准化,使其分布满足0均值和单位方差
  在每轮迭代过程中:
    设置当前最小误差lowestError为正无穷
    对每个特征:
      增大或缩小:
        改变一个系数得到一个新的W
        计算新W下的误差
        如果误差Error小于lowestError,设置wbest = 当前W
      将W设置为新的wbest

代码如下:

 1 # encoding: utf-8
 2 ‘‘‘
 3 @Author: shuhan Wei
 4 @File: stageWise.py
 5 @Time: 2018/8/24 13:10
 6 ‘‘‘
 7 import numpy as np
 8 import regression
 9 import matplotlib.pyplot as plt
10
11
12 def regularize(xMat):#regularize by columns
13     inMat = xMat.copy()
14     inMeans = np.mean(inMat,0)   #calc mean then subtract it off
15     inVar = np.var(inMat,0)      #calc variance of Xi then divide by it
16     inMat = (inMat - inMeans)/inVar
17     return inMat
18
19
20 def rssError(yArr,yHatArr): #yArr and yHatArr both need to be arrays
21     return ((yArr-yHatArr)**2).sum()
22
23
24 """
25     函数说明:向前逐步回归算法
26     Parameters:
27         xArr - x数据集
28         yArr - y数据集
29         eps - 每次迭代步长
30         numIt - 迭代次数
31     Returns:
32         系数矩阵
33 """
34 def stageWise(xArr, yArr, eps=0.01, numIt = 100):
35     xMat = np.mat(xArr)
36     yMat = np.mat(yArr).T
37     yMean = np.mean(yMat, 0)
38     yMat = yMat - yMean
39     xMat = regularize(xMat)
40     m, n = np.shape(xMat)
41     returnMat = np.zeros((numIt, n))  # testing code remove
42     ws = np.zeros((n, 1));wsTest = ws.copy();wsMax = ws.copy()
43     for i in range(numIt):  # could change this to while loop
44         print(ws.T)
45         lowestError = np.inf;   #初始化最小误差为正无穷
46         for j in range(n):  #遍历每个特征
47             for sign in [-1, 1]:
48                 wsTest = ws.copy()
49                 wsTest[j] += eps * sign
50                 yTest = xMat * wsTest
51                 rssE = rssError(yMat.A, yTest.A)
52                 if rssE < lowestError:
53                     lowestError = rssE
54                     wsMax = wsTest
55         ws = wsMax.copy()
56         returnMat[i, :] = ws.T
57     return returnMat
58
59
60 def plot(weights):
61     plt.rcParams[‘font.sans-serif‘] = [‘SimHei‘]
62     plt.rcParams[‘axes.unicode_minus‘] = False
63     fig = plt.figure()
64     ax = fig.add_subplot(111)
65     ax.plot(weights)
66     ax_title_text = ax.set_title(u‘回归系数与迭代次数的关系‘)
67     ax_xlabel_text = ax.set_xlabel(u‘迭代次数‘)
68     ax_ylabel_text = ax.set_ylabel(u‘回归系数‘)
69     plt.setp(ax_title_text, size=20, weight=‘bold‘, color=‘red‘)
70     plt.setp(ax_xlabel_text, size=10, weight=‘bold‘, color=‘black‘)
71     plt.setp(ax_ylabel_text, size=10, weight=‘bold‘, color=‘black‘)
72     plt.show()
73
74
75 if __name__ == ‘__main__‘:
76     abX, abY = regression.loadDataSet(‘abalone.txt‘)
77     weights = stageWise(abX, abY, 0.001, 5000)
78     plot(weights)

结果:

        

        中间省略

        

当迭代次数很大时,接近于普通最小二乘回归

小结:当使用缩减方法时,把一些系数的回归系数缩减到0,减少了模型的复杂度,增加了模型的偏差,同时减小了方差

权衡偏差和方差

      

1.3 实例:预测乐高玩具价格

在交叉验证中使用90%数据集作为训练数据,10%做为测试数据,通过10次迭代之后,求30个不同lambda下的误差均值,再选择最小的误差,从而获取最优回归系数。

使用岭回归时需要对x数据集进行标准化,对y数据集进行中心化。最后需要对计算的回归系数进行还原,同时截距等于

# encoding: utf-8
‘‘‘
@Author: shuhan Wei
@File: legao.py
@Time: 2018/8/24 16:16
‘‘‘
#BeautifulSoup是一个可以从HTML或XML文件中提取数据的Python库
import random

from bs4 import BeautifulSoup
import numpy as np
import regression
import ridgeRegression

def rssError(yArr,yHatArr): #yArr and yHatArr both need to be arrays
    return ((yArr-yHatArr)**2).sum()

def scrapePage(inFile, outFile, yr, numPce, origPrc):
    # 打开并读取HTML文件
    with open(inFile, encoding=‘utf-8‘) as fr:
        html = fr.read()
    fw = open(outFile, ‘a‘)  # a是追加模式
    soup = BeautifulSoup(html)
    i = 1
    currentRow = soup.findAll(‘table‘, r="%d" % i)
    while (len(currentRow) != 0):
        currentRow = soup.findAll(‘table‘, r="%d" % i)
        title = currentRow[0].findAll(‘a‘)[1].text
        lwrTitle = title.lower()
        print(lwrTitle)
        if (lwrTitle.find(‘new‘) > -1) or (lwrTitle.find(‘nisb‘) > -1):
            newFlag = 1.0   #全新
        else:
            newFlag = 0.0   #不是全新
        soldUnicde = currentRow[0].findAll(‘td‘)[3].findAll(‘span‘)
        if len(soldUnicde) == 0:
            print
            "item #%d did not sell" % i
        else:
            soldPrice = currentRow[0].findAll(‘td‘)[4]
            priceStr = soldPrice.text
            priceStr = priceStr.replace(‘$‘, ‘‘)  # strips out $
            priceStr = priceStr.replace(‘,‘, ‘‘)  # strips out ,
            if len(soldPrice) > 1:
                priceStr = priceStr.replace(‘Free shipping‘, ‘‘)  # strips out Free Shipping
            print
            "%s\t%d\t%s" % (priceStr, newFlag, title)
            fw.write("%d\t%d\t%d\t%f\t%s\n" % (yr, numPce, newFlag, origPrc, priceStr))
        i += 1
        currentRow = soup.findAll(‘table‘, r="%d" % i)
    fw.close()

def setDataCollect():
    scrapePage(‘setHtml/lego8288.html‘, ‘out.txt‘, 2006, 800, 49.99)    #2006年出品,部件数目800,原价49.99
    scrapePage(‘setHtml/lego10030.html‘, ‘out.txt‘, 2002, 3096, 269.99)
    scrapePage(‘setHtml/lego10179.html‘, ‘out.txt‘, 2007, 5195, 499.99)
    scrapePage(‘setHtml/lego10181.html‘, ‘out.txt‘, 2007, 3428, 199.99)
    scrapePage(‘setHtml/lego10189.html‘, ‘out.txt‘, 2008, 5922, 299.99)
    scrapePage(‘setHtml/lego10196.html‘, ‘out.txt‘, 2009, 3263, 249.99)

"""
    函数说明:交叉验证测试岭回归
    Parameters:
        xArr - x数据集
        yArr - y数据集
        numVal - 交叉验证的次数
"""
def crossValidation(xArr,yArr,numVal=10):
    m = len(yArr)
    indexList = list(range(m))  #生成索引列表
    errorMat = np.zeros((numVal,30))#存放误差值
    for i in range(numVal):
        trainX=[]; trainY=[]
        testX = []; testY = []
        random.shuffle(indexList)    #打乱indexList,为了下面随机选取数据
        for j in range(m):  #使用90%的数据做训练集,10%做测试集
            if j < m * 0.9:
                trainX.append(xArr[indexList[j]])
                trainY.append(yArr[indexList[j]])
            else:
                testX.append(xArr[indexList[j]])
                testY.append(yArr[indexList[j]])
        wMat = ridgeRegression.ridgeTest(trainX,trainY)    #使用岭回归获取30组回归系数
        print(wMat)
        for k in range(30):#loop over all of the ridge estimates
            matTestX = np.mat(testX); matTrainX = np.mat(trainX)
            meanTrain = np.mean(matTrainX,0)
            varTrain = np.var(matTrainX,0)
            matTestX = (matTestX-meanTrain)/varTrain #正规化测试数据
            yEst = matTestX * np.mat(wMat[k,:]).T + np.mean(trainY)#计算预测y值
            errorMat[i,k] = rssError(yEst.T.A,np.array(testY))
            #print errorMat[i,k]
    meanErrors = np.mean(errorMat,0)#calc avg performance of the different ridge weight vectors
    minMean = float(min(meanErrors))    #获取最小的误差值
    bestWeights = wMat[np.nonzero(meanErrors==minMean)]
    #can unregularize to get model
    #when we regularized we wrote Xreg = (x-meanX)/var(x)
    #we can now write in terms of x not Xreg:  x*w/var(x) - meanX/var(x) +meanY
    xMat = np.mat(xArr); yMat = np.mat(yArr).T
    meanX = np.mean(xMat,0); varX = np.var(xMat,0)
    unReg = bestWeights / varX
    print("the best model from Ridge Regression is:\n",unReg)
    print("with constant term: ",-1*np.sum(np.multiply(meanX,unReg),1) + np.mean(yMat))  #常数项

if __name__ == ‘__main__‘:
    # setDataCollect()
    lgX, lgY = regression.loadDataSet(‘out.txt‘)
    #加上X0
    lgXMat = np.mat(np.ones((np.shape(lgX)[0],np.shape(lgX)[1]+1)))
    lgXMat[:,1:5] = np.mat(lgX)
    print(lgXMat[0])
    ws = regression.standRegres(lgXMat,lgY)
    print(ws)
    print(lgXMat[0]*ws,lgY[0])
    crossValidation(lgX,lgY)

  使用最小二乘回归预测结果为:

  

  它对数据拟合得很好,但看上去却没什么道理,从公式看零部件数量越多,反而销售价更低。

  使用岭回归:

  

  

  该结果和最小二乘结果没有太大差异,我们本期望找到一个更易于理解的模型,显然没有达到预期效果。为了达到这一点,我们看一下在缩减回归中系数是如何变化的

  

  看运行结果的第一行,可以看到最大的是第4项,第二大的是第2项。因此,如果只选择一个特征来做预测的话,我们应该选择第4个特征,也就是原始加个。如果可以选择2个特征的话,应该选择第4个和第2个特征。

  这种分析方法使得我们可以挖掘大量数据的内在规律。在仅有4个特征时,该方法的效果也许并不明显;但如果有100个以上的特征,该方法就会变得十分有效:它可以指出哪个特征是关键的,而哪些特征是不重要的。

使用sklearn中的岭回归

def usesklearn():
    from sklearn import linear_model
    reg = linear_model.Ridge(alpha=.5)
    lgX, lgY = regression.loadDataSet(‘out.txt‘)
    setDataCollect(lgX, lgY)
    reg.fit(lgX, lgY)
    print("$%f%f*Year%f*NumPieces+%f*NewOrUsed+%f*original price" % (reg.intercept_, reg.coef_[0], reg.coef_[1], reg.coef_[2], reg.coef_[3],reg.coef[4]))

            

 

原文地址:https://www.cnblogs.com/weiququ/p/9537483.html

时间: 2024-10-07 02:26:06

机器学习实战第8章预测数值型数据:回归2的相关文章

机器学习实战第8章预测数值型数据:回归

1.简单的线性回归 假定输入数据存放在矩阵X中,而回归系数存放在向量W中,则对于给定的数据X1,预测结果将会是 这里的向量都默认为列向量 现在的问题是手里有一些x和对应的y数据,怎样才能找到W呢?一个常用的方法是找到使误差最小的W,这里的误差是指预测y值与真实y值之间的差值,使用该误差的简单累加将使得正差值和负差值相互抵消,所以我们采用平方误差. 平方误差可以写做: 用矩阵表示可以写成 使用上式对w进行求导: 具体可参考https://blog.csdn.net/nomadlx53/articl

机器学习——预测数值型数据:回归

线性回归 优点:结果易于理解,计算上不复杂 缺点:对非线性的数据拟合不好 适用数据类型:数值型和标称型数据 回归的目的就预测数值型的目标值.最直接的办法就是依据输入写一个目标值的计算公式.这个计算公式就是所谓的回归方程(regression equation),其中的参数就是回归系数,求这些回归系数的过程就是回归. 说道回归,一般都是指线性回归(linear regression). 一元线性回归的矩阵形式可以写成,其中 是噪声,b是回归系数(斜率) 或者 ,其中y.X.a.都是n维向量,而b是

回归:预测数值型数据

何为回归? “回归”一词是由达尔文的表兄弟Francis Galton发明的.Galton于1877年完成了第一次回归预测,目的是根据上一代豌豆种子(双亲)的尺寸来预测下一代豌豆种子(孩子)的尺寸. Galton在大量对象上应用了回归分析,甚至包括人的身高预测.他注意到,如果双亲的高高度比平均高度高,他们的子女也倾向于比平均高度高,但尚不及双亲(笔者感觉未必,Galton并未考虑物质条件的发展会带来整体身高的增加,至少笔者感觉80,90的人普遍比父母高).孩子的高度向着平均高度“回归”. 在软件

第八章:预测数值型数据:回归

本章内容□ 线性回归□ 局部加权线性回归□ 岭回归和逐步线性回归□ 预测鲍鱼年龄和玩具售价  8.1用线性回归找到最佳拟合直线

机器学习实战之第一章 机器学习基础

第1章 机器学习基础 机器学习 概述 机器学习就是把无序的数据转换成有用的信息. 获取海量的数据 从海量数据中获取有用的信息 我们会利用计算机来彰显数据背后的真实含义,这才是机器学习的意义. 机器学习 场景 例如:识别动物猫 模式识别(官方标准):人们通过大量的经验,得到结论,从而判断它就是猫. 机器学习(数据学习):人们通过阅读进行学习,观察它会叫.小眼睛.两只耳朵.四条腿.一条尾巴,得到结论,从而判断它就是猫. 深度学习(深入数据):人们通过深入了解它,发现它会'喵喵'的叫.与同类的猫科动物

预测数值型数据-回归(Regression)

===================================================================== <机器学习实战>系列博客是博主阅读<机器学习实战>这本书的笔记也包含一些其他python实现的机器学习算法 算法实现均采用python github 源码同步:https://github.com/Thinkgamer/Machine-Learning-With-Python ==================================

机器学习实战第7章——利用AdaBoost元算法提高分类性能

将不同的分类器组合起来,这种组合结果被称为集成方法或元算法(meta-algorithm). 使用集成方法时会有多种形式:(1)可以是不同算法的集成(2)可以是同一种算法在不同设置下的集成(3)数据集不同部分分配给不同分类器之后的集成,等等 接下来介绍基于同一种分类器多个不同实例的两种不同计算方法bagging和boosting 1. bagging 原理:从原始数据集选择S次后得到S个新数据集的一种技术.新数据集和原数据集的大小相等.每个数据集都是通过在原始数据集中随机选择一个样本来进行替换而

机器学习--标称型和数值型数据

在监督学习(supervised learning)的过程中,只需要给定输入样本集,机器就可以从中推演出指定目标变量的可能结果.监督学习相对比较简单,机器只需从输入数据中预测合适的模型,并从中计算出目标变量的结果. 监督学习一般使用两种类型的目标变量:标称型和数值型 标称型:标称型目标变量的结果只在有限目标集中取值,如真与假(标称型目标变量主要用于分类) 数值型:数值型目标变量则可以从无限的数值集合中取值,如0.100,42.001等 (数值型目标变量主要用于回归分析)-------------

机器学习实战之第二章 k-近邻算法

第2章 k-近邻算法 KNN 概述 k-近邻(kNN, k-NearestNeighbor)算法主要是用来进行分类的. KNN 场景 电影可以按照题材分类,那么如何区分 动作片 和 爱情片 呢? 动作片:打斗次数更多 爱情片:亲吻次数更多 基于电影中的亲吻.打斗出现的次数,使用 k-近邻算法构造程序,就可以自动划分电影的题材类型. 现在根据上面我们得到的样本集中所有电影与未知电影的距离,按照距离递增排序,可以找到 k 个距离最近的电影. 假定 k=3,则三个最靠近的电影依次是, He's Not