回归分析及实际案例:预测鲍鱼年龄

简介: 回归分析及实际案例:预测鲍鱼年龄

上一篇文章:线性回归(Linear regression)算法

引入:

7f80f09b7ac42f009c348f7262318a11_watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hlZGEz,size_16,color_FFFFFF,t_70.png

1、线性回归:

算法的优点:

结果易于理解,计算不复杂

缺点:对非线性数据拟合不好

目标:平方误差和最小

fc4ba693bd1bfbf96a0b7b7f9d1a5b3e_20200128170315120.png

求解(对参数w求导等于0)的回归系数:

f3f3336b2e0f6c91eef01d412137e484_20200128170243263.png

模型预测:

image.png

"""
函数说明:标准回归
Parameters:
    xArr - 特征矩阵
    yArr -响应值
Returns:
     ws- 回归系数
Author:
    heda3
Blog:
    https://blog.csdn.net/heda3
Modify:
    2020-01-10
"""   
def standRegres(xArr,yArr):
    xMat = mat(xArr); yMat = mat(yArr).T
    xTx = xMat.T*xMat#计算xTx
    if linalg.det(xTx) == 0.0:#判断行列式是否为0
        print("This matrix is singular, cannot do inverse")
        return
    ws = xTx.I * (xMat.T*yMat)#计算回归系数
    return ws

注意行列式不为零才可以计算逆矩阵

#加载测试数据

from numpy import *
def loadDataSet(fileName):      #general function to parse tab -delimited floats
    numFeat = len(open(fileName).readline().split('\t')) - 1 #get number of fields 
    dataMat = []; labelMat = []
    fr = open(fileName)
    for line in fr.readlines():
        lineArr =[]
        curLine = line.strip().split('\t')
        for i in range(numFeat):
            lineArr.append(float(curLine[i]))
        dataMat.append(lineArr)
        labelMat.append(float(curLine[-1]))
    return dataMat,labelMat

数据描述:

特征:2,响应:数值型

使用线性回归预测数据并绘制散点图+计算模型的效果(相关系数计算)

 ##测试线性回归
 xArr,yArr=loadDataSet('ex0.txt')
 xArr[0:2]
 ws=standRegres(xArr,yArr)#计算回归系数
 xMat=mat(xArr)
 yMat=mat(yArr)
 #绘散点图
 import matplotlib.pyplot as plt
 fig=plt.figure()
 ax=fig.add_subplot(111)
 ax.scatter(xMat[:,1].flatten().A[0],yMat.T[:,0].flatten().A[0])#.A转变为数组
 xCopy=xMat.copy()
 xCopy.sort(0)#维度,行排序
 yHat=xCopy*ws
 ax.plot(xCopy[:,1],yHat)
 plt.show
 #求预测值和真实值的相关系数
 yHat1=xMat*ws
 corrcoef(yHat1.T,yMat)

89626b66b83e5b6e1070eb1abb2e392c_watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hlZGEz,size_16,color_FFFFFF,t_70.png

2、局部加权线性回归

Locally Weighted Linear Regression, LWLR

线性回归存在的问题是:出现欠拟合

解决方法:在估计中引入偏差,从而降低预测的均方误差

也即是通过在每一小段进行拟合,以逼近真实的数据

局部加权线性回归相比普通线性回归的问题是:每次必须在整个数据集上运行,也即是必须要保存所有的训练数据

思路:在待预测点附近的每个点赋予一定的权重

求解的回归系数:

6cc262fa8c3042f83f0b8bfe8c026a7d_2020012817234256.png

对比线性回归:

f3f3336b2e0f6c91eef01d412137e484_20200128170243263.png

其中的W矩阵用于给每个数据点赋予权重

权重W的选择,通过使用不同的核:

例如高斯核

85e63da4dca97a1aa7992834ae380294_20200128172552899.png

需要调节的参数:一个 k

#对单点估计

"""
函数说明:局部加权线性回归
Parameters:
    testPoint x空间的任意一点
    xArr - 特征矩阵
    yArr -响应值
    k 和权重有关,当k越小则使用的越少的局部数据集进行训练,k=1相当于标准线性回归
Returns:
    某个点的预测结果  testPoint * ws - 
Author:
    heda3
Blog:
    https://blog.csdn.net/heda3
Modify:
    2020-01-10
"""   
def lwlr(testPoint,xArr,yArr,k=1.0):
    xMat = mat(xArr); yMat = mat(yArr).T
    m = shape(xMat)[0]
    weights = mat(eye((m)))#定义一个权值矩阵
    for j in range(m):                      #next 2 lines create weights matrix
        diffMat = testPoint - xMat[j,:]     #x-x[i]
        weights[j,j] = exp(diffMat*diffMat.T/(-2.0*k**2))
    xTx = xMat.T * (weights * xMat)
    if linalg.det(xTx) == 0.0:
        print("This matrix is singular, cannot do inverse")
        return
    ws = xTx.I * (xMat.T * (weights * yMat))#计算回归系数
    return testPoint * ws

#对多点(数据集)估计

"""
函数说明:为数据集中的每个点调用lwlr
Parameters:
    testArr 测试的数据集
    xArr - 特征矩阵
    yArr -响应值
    k
Returns:
     testPoint * ws - 
Author:
    heda3
Blog:
    https://blog.csdn.net/heda3
Modify:
    2020-01-10
"""  
def lwlrTest(testArr,xArr,yArr,k=1.0):  #loops over all the data points and applies lwlr to each one
    m = shape(testArr)[0]
    yHat = zeros(m)
    for i in range(m):
        yHat[i] = lwlr(testArr[i],xArr,yArr,k)#要使用之前的数据集参与预测
    return yHat

对数据进行预测+绘制散点图

 ##测试局部加权线性回归
 xArr,yArr=loadDataSet('ex0.txt')
 #对单点估计
 yArr[0]
 lwlr(xArr[0],xArr,yArr,1.0)
 lwlr(xArr[0],xArr,yArr,0.001)
 #数据集中所有点的估计
 yHat=lwlrTest(xArr,xArr,yArr,0.01)
 #绘制散点图
 xMat=mat(xArr)
 srtInd=xMat[:,1].argsort(0)
 xSort=xMat[srtInd][:,0,:] #等价于xMat[srtInd.flatten().A[0]]
 import matplotlib.pyplot as plt
 fig=plt.figure()
 ax=fig.add_subplot(111)
 ax.plot(xSort[:,1],yHat[srtInd])#拟合曲线
 ax.scatter(xMat[:,1].flatten().A[0],mat(yArr).T.flatten().A[0],s=2,c='red')#.A转变为数组
 plt.show()

设置参数k值为0.01

79edb3402a5ac6a5e682ea26522efe16_watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hlZGEz,size_16,color_FFFFFF,t_70.png

问题:

数据的特征比样本点多时,计算矩阵的(XTX)的逆出错,也即是输入数据(特征)矩阵不是满秩的矩阵

或者是数据特征之间是高度相关时也不能计算

如何减少特征数,如何减少不重要的特征?

解决方法:缩减系数

1)岭回归

2)lasso

3)LAR

4)PCA回归

5)子集选择

1)岭回归

的基础上加使得矩阵非奇异,从而能对求逆

求解的回归系数:

image.png

选择的参数:    可通过交叉验证确定

注意:数据需要先标准化处理(X-mean)/var

"""
函数说明:岭回归
Parameters:
    xMat- 数据的特征 假设有n 样本个数有m
    yMat- 响应值
    lam-- 调节的参数
Returns:
     ws-- 计算出的回归系数
Author:
    heda3
Blog:
    https://blog.csdn.net/heda3
Modify:
    2020-01-10
"""  
def ridgeRegres(xMat,yMat,lam=0.2):
    xTx = xMat.T*xMat#2*2   n*n
    denom = xTx + eye(shape(xMat)[1])*lam#n*n
    if linalg.det(denom) == 0.0:
        print("This matrix is singular, cannot do inverse")
        return
    ws = denom.I * (xMat.T*yMat)
    return ws
"""
函数说明:岭回归参数lambda调节
Parameters:
    xArr- 特征矩阵
    yArr- 响应值
Returns:
    wMat - 返回一组w(维数和特征数对应)系数
Author:
    heda3
Blog:
    https://blog.csdn.net/heda3
Modify:
    2020-01-10
"""  
def ridgeTest(xArr,yArr):
    xMat = mat(xArr); yMat=mat(yArr).T
    #数据标准化处理
    yMean = mean(yMat,0)
    yMat = yMat - yMean     #to eliminate X0 take mean off of Y
    #regularize X's
    xMeans = mean(xMat,0)   #calc mean then subtract it off
    xVar = var(xMat,0)      #calc variance of Xi then divide by it
    xMat = (xMat - xMeans)/xVar
    numTestPts = 30#设置lambda参数迭代次数
    wMat = zeros((numTestPts,shape(xMat)[1]))#30*2的矩阵
    for i in range(numTestPts):
        ws = ridgeRegres(xMat,yMat,exp(i-10))
        wMat[i,:]=ws.T
    return wMat

2)lasso

对回归系数的约束:

7fafc4ead8bcf92dcc2768d052edcaad_20200128205117962.png

3)前向逐步回归

每一步都尽可能的减少误差,通过设置初始权重为1,每一步所做的决策是对某个权重增加或减少一个很小的值

算法步骤:

782f54c602aa924d39cbcfdf8034f64c_20200128205547319.png

通过多次迭代后得到趋于稳定的回归参数!

可调节的参数:步长和迭代次数

"""
函数说明:前向逐步线性回归
Parameters:
    xArr- 特征矩阵
    yArr- 响应值
    eps=0.01  每次迭代需要调整的步长
    numIt=100 迭代次数
Returns:
    returnMat - 返回一组w(维数和特征数对应)系数
Author:
    heda3
Blog:
    https://blog.csdn.net/heda3
Modify:
    2020-01-11
"""  
def stageWise(xArr,yArr,eps=0.01,numIt=100):
    xMat = mat(xArr); yMat=mat(yArr).T
    #数据的标准化
    yMean = mean(yMat,0)
    yMat = yMat - yMean     #can also regularize ys but will get smaller coef
    xMat = regularize(xMat)
    m,n=shape(xMat)
    returnMat = zeros((numIt,n)) #testing code remove
    ws = zeros((n,1)); wsTest = ws.copy(); wsMax = ws.copy()
    for i in range(numIt):
        print(ws.T)
        lowestError = inf; #一开始的误差设置很大
        for j in range(n):#n个特征也即是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()#迭代numIt次找到最小误差的回归系数
        returnMat[i,:]=ws.T
    return returnMat

案例1:预测鲍鱼年龄

问题出发点是:鲍鱼的年龄是通过贝壳的年轮计数确定,此方法耗时费力,如何依据其它的一些参数来推测鲍鱼的年龄?

数据集来源:UCI Machine Learning Repository: Abalone Data Set

b698b6826e5c9b547b4795674077d676_20200128213718247.png

数据集的描述:

上述的数据集给出的8个特征属性


Name / Data Type / Measurement Unit / Description

-----------------------------

Sex / nominal / -- / M, F, and I (infant)

Length / continuous / mm / Longest shell measurement

Diameter / continuous / mm / perpendicular to length

Height / continuous / mm / with meat in shell

Whole weight / continuous / grams / whole abalone

Shucked weight / continuous / grams / weight of meat

Viscera weight / continuous / grams / gut weight (after bleeding)

Shell weight / continuous / grams / after being dried

80d1338160a3c61c965668d408b2704d_20200128214000389.png

响应值:

构建模型预测

1)使用标准线性回归模型预测鲍鱼年龄

 ##使用标准线性回归模型
 ws=standRegres(abX[0:99],abY[0:99])
 yHat=mat(abX[100:199])*ws
 rssError(abY[100:199],yHat.T.A)

新数据上表现平方误差=518.6

2)使用局部线性加权线性回归模型预测鲍鱼年龄

 ##使用局部加权线性回归
 abX,abY=loadDataSet('abalone.txt')
 yHat01=lwlrTest(abX[0:99],abX[0:99],abY[0:99],0.1)
 yHat1=lwlrTest(abX[0:99],abX[0:99],abY[0:99],1)
 yHat10=lwlrTest(abX[0:99],abX[0:99],abY[0:99],10)
 #平方误差和
 rssError(abY[0:99],yHat01.T)
 rssError(abY[0:99],yHat1.T)
 rssError(abY[0:99],yHat10.T)
 #测试集表现
 yHat01=lwlrTest(abX[100:199],abX[100:199],abY[100:199],0.1)
 yHat1=lwlrTest(abX[100:199],abX[100:199],abY[100:199],1)
 yHat10=lwlrTest(abX[100:199],abX[100:199],abY[100:199],10)
 x1=rssError(abY[100:199],yHat01.T)
 print(x1)
 x2=rssError(abY[100:199],yHat1.T)
 print(x2)
 x3=rssError(abY[100:199],yHat10.T)
 print(x3)

在不同的参数k下的效果,以及在训练集和测试集上的表现:

平方误差结果:

训练集下:

82e3d81ff80d74238aa9d1c522648419_20200128215640861.png

测试集下:

b2a96aa342849c46f6306957c7431b15_20200128215724558.png

在未知数据上比较效果才可以很好的选择模型,10折交叉验证

3)岭回归模型预测鲍鱼年龄

 ##使用岭回归
 abX,abY=loadDataSet('abalone.txt')
 ridgeWeights=ridgeTest(abX,abY)#得到不同lambda下计算出的回归系数
 #绘制回归系数
 import matplotlib.pyplot as plt
 fig=plt.figure()
 ax=fig.add_subplot(111)
 ax.plot(ridgeWeights)
 plt.show()

横坐标为lambda值,y轴为各回归系数

b3bac597cd1469c9dc36ddbe09599ea1_watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hlZGEz,size_16,color_FFFFFF,t_70.png

通过上图看看出哪些变量对结果的预测具有影响力

为定量找到最佳参数值lambda,需要进行交叉验证获得误差最小的lambda

使用10折交叉验证计算得出最佳的岭回归系数,参与预测新的数据

在岭回归中要求数据要标准化再参与计算,那么在训练完成后新的数据如何进行预测?这个新的数据怎么利用训练的数据进行标准化?

解决方法是:利用在训练数据中得出的回归参数,通过变换实现变相的在新数据预测时的标准化

新的数据一般预测过程:

数据标准化:XT=(XTest-mean(XTrain))/Var(XTrain)

预测:Ytest=XT*Ws+mean(YTrain)

将上述的公式变换:

Ytest=((XTest-mean(XTrain))/Var(XTrain))*Ws+mean(YTrain)

设UnReg=Ws/Var(XTrain)

constantTerm=-mean(XTrain)*Ws/Var(XTrain)+mean(YTrain)

则Ytest=XTest*UnReg+constantTerm(现在的新变换后的预测过程)

###交叉验证--岭回归
ridgeWs,ridgeunReg,ridgeConstantTerm=crossValidation(abX[0:99],abY[0:99],10)#目的是找出最佳的岭回归系数
##测试均方误差
####和标准线性回归的比较
xMat=mat(abX[100:199])
yMat=mat(abY[100:199]).T
ridgeyHat=xMat*ridgeunReg.T+ridgeConstantTerm#岭回归预测
rssError(abY[100:199],ridgeyHat.T.A)#误差计算

换种写法:

###交叉验证--岭回归
ridgeWs,ridgeunReg,ridgeConstantTerm=crossValidation(abX[0:99],abY[0:99],10)#目的是找出最佳的岭回归系数
##测试均方误差
####和标准线性回归的比较
xMat=mat(abX[100:199])
yMat=mat(abY[100:199])
ridgeyHat=xMat*ridgeunReg.T+ridgeConstantTerm#岭回归预测
rssError(yMat.A,ridgeyHat.T.A)#误差计算
xxx=yMat.A
yyy=ridgeyHat.T.A
"""
函数说明:交叉验证测试岭回归
Parameters:
    xArr - 特征
    yArr - 标签
    numVal=10 - 交叉验证的次数
Returns: 
    bestWeights 最佳的岭回归参数
    为了和标准线性回归比较
    unReg,constantTerm 数据标准化还原后的特征参数和常量参数
Author:
    heda3
Blog:
    https://blog.csdn.net/heda3
Modify:
    2020-01-28
""" 
def crossValidation(xArr,yArr,numVal=10):
    m = len(yArr)#样本点个数                           
    indexList = list(range(m))
    errorMat = zeros((numVal,30))#create error mat 30columns numVal rows
    for i in range(numVal):#交叉验证
        trainX=[]; trainY=[]
        testX = []; testY = []
        random.shuffle(indexList)#随机打乱样本索引
        #训练集和测试集的划分 90%训练  10%测试
        for j in range(m):#create training set based on first 90% of values in indexList
            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 = ridgeTest(trainX,trainY)    #30*特征数 get 30 weight vectors from ridge
        #30组回归系数
        for k in range(30):#loop over all of the ridge estimates
            matTestX = mat(testX); matTrainX=mat(trainX)
            meanTrain = mean(matTrainX,0)
            varTrain = var(matTrainX,0)
            matTestX = (matTestX-meanTrain)/varTrain #regularize test with training params
            yEst = matTestX * mat(wMat[k,:]).T + mean(trainY)#test ridge results and store
            errorMat[i,k]=rssError(yEst.T.A,array(testY))
            #print errorMat[i,k]
    #计算所有这些误差值的均值
    meanErrors = mean(errorMat,0)#errorMat为 10*30   30个岭回归参数  10次交叉验证  按照把轴向数据求平均  得到每列数据的平均值,也即是10折交叉验证的平均   calc avg performance of the different ridge weight vectors
    minMean = float(min(meanErrors))#哪个岭回归参数下的误差最小
    bestWeights = wMat[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 = mat(xArr); yMat=mat(yArr).T
    meanX = mean(xMat,0); varX = var(xMat,0)
    unReg = bestWeights/varX
    print("the best model from Ridge Regression is:\n",unReg)
    #标准化后数据还原
    constantTerm=-1*sum(multiply(meanX,unReg)) + mean(yMat)
    print("with constant term: ",constantTerm)
    return bestWeights,unReg,constantTerm

平方误差结果:

4)前向逐步回归模型预测鲍鱼年龄

 ##使用逐步回归
 xArr,yArr=loadDataSet('abalone.txt')
 returnMat1=stageWise(xArr,yArr,0.01,200)#出现来回震荡情况,原因是步长太大?原因是系数已经饱和需要调小系数
 #对比更小的步长
 returnMat2=stageWise(xArr,yArr,0.001,200)
 #绘制回归系数
 import matplotlib.pyplot as plt
 fig=plt.figure()
 ax=fig.add_subplot(111)
 ax.plot(returnMat2)
 plt.show()

参数:步长和迭代次数

24197cd9f28047ac9d8b3dc76df6e6a5_watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hlZGEz,size_16,color_FFFFFF,t_70.png基于上图可以较好的发现重要特征

定量的选择模型参数:使用类似交叉验证方法

实验结果:

##数据训练
returnMat2=stageWise(xArr,yArr,0.001,5000)
###预测
####数据标准化
xMat = mat(xArr); yMat=mat(yArr).T
xMean=mean(xMat,0)
VarX=var(xMat,0)
yMean = mean(yMat,0)
Xtest=(mat(xArr[100:199])-xMean)/VarX#标准化后的测试数据
yMat=mat(yArr[100:199])#实际标签数据
Ytest=Xtest*mat(returnMat2[4999,:]).T+yMean
rssError(yMat.A,Ytest.T.A)#.A转变为数组

均方误差:

参考:

《机器学习实战》

目录
相关文章
|
5月前
|
机器学习/深度学习 数据采集 数据可视化
数据分享|用加性多元线性回归、随机森林、弹性网络模型预测鲍鱼年龄和可视化(下)
数据分享|用加性多元线性回归、随机森林、弹性网络模型预测鲍鱼年龄和可视化
|
5月前
|
机器学习/深度学习 数据可视化 数据挖掘
数据分享|用加性多元线性回归、随机森林、弹性网络模型预测鲍鱼年龄和可视化(中)
数据分享|用加性多元线性回归、随机森林、弹性网络模型预测鲍鱼年龄和可视化
数据分享|用加性多元线性回归、随机森林、弹性网络模型预测鲍鱼年龄和可视化(中)
|
5月前
|
机器学习/深度学习 数据采集 数据可视化
数据分享|用加性多元线性回归、随机森林、弹性网络模型预测鲍鱼年龄和可视化(上)
数据分享|用加性多元线性回归、随机森林、弹性网络模型预测鲍鱼年龄和可视化
|
5月前
|
存储 数据可视化 文件存储
多变量(多元)多项式曲线回归线性模型分析母亲吸烟对新生婴儿体重影响可视化
多变量(多元)多项式曲线回归线性模型分析母亲吸烟对新生婴儿体重影响可视化
|
5月前
|
机器学习/深度学习 数据采集 数据可视化
R语言用加性多元线性回归、随机森林、弹性网络模型预测鲍鱼年龄和可视化
R语言用加性多元线性回归、随机森林、弹性网络模型预测鲍鱼年龄和可视化
|
5月前
|
数据可视化
多变量(多元)多项式曲线回归线性模型分析母亲吸烟对新生婴儿体重影响可视化-2
多变量(多元)多项式曲线回归线性模型分析母亲吸烟对新生婴儿体重影响可视化
|
5月前
|
机器学习/深度学习 数据可视化 数据挖掘
用加性多元线性回归、随机森林、弹性网络模型预测鲍鱼年龄和可视化(三)
用加性多元线性回归、随机森林、弹性网络模型预测鲍鱼年龄和可视化
|
5月前
|
机器学习/深度学习 数据可视化 Shell
用加性多元线性回归、随机森林、弹性网络模型预测鲍鱼年龄和可视化(二)
用加性多元线性回归、随机森林、弹性网络模型预测鲍鱼年龄和可视化
|
5月前
|
机器学习/深度学习 数据采集 数据可视化
用加性多元线性回归、随机森林、弹性网络模型预测鲍鱼年龄和可视化(四)
用加性多元线性回归、随机森林、弹性网络模型预测鲍鱼年龄和可视化
|
5月前
|
存储 数据可视化 文件存储
数据分享|多变量多元多项式曲线回归线性模型分析母亲吸烟对新生婴儿体重影响可视化
数据分享|多变量多元多项式曲线回归线性模型分析母亲吸烟对新生婴儿体重影响可视化
下一篇
无影云桌面