机器学习实战之线性回归

 对于对给定数据集X和对应目标值y,线性回归目的是要找到回归系数w,使用线性方程y=X^{T}*w来拟合这些数据点。

1.标准线性回归:

通常求取回归系数的做法是,求得使平方误差最下的w

平方误差:                                             \sum_{i=1}^{m}(y_{i}-x_{i}^{T})^{2}                         

解出回归系数:

                                                            \widehat{w}=(X^{T}X)^{-1}X^{T}y        

直接用此公式时需注意矩阵的求逆,需要判断矩阵行列式不为零,否则不能直接求逆。

from numpy import *
import matplotlib.pyplot as plt

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
#标准回归
def standRegres(xArr,yArr):
    X=mat(xArr)
    y=mat(yArr).T
    xTx=X.T*X
    if linalg.det(xTx)==0:#检查是否可逆
        print('This matrix is singular, cannot do inverse')
        return
    w=xTx.I*(X.T*y)
    return w

                                                                                        标准线性回归

                                                      

2.局部加权线性回归(LWLR)

线性回归的缺点是容易出现欠拟合,采用局部加权线性回归,给与每一个待预测点附近的点一定的权重,在该子集上基于最小平方误差进行回归。这种算法每次预测前需要先选出相应数据子集。对应回归系数的解为:

                                                              \widehat{w}=(X^{T}WX)^{-1}X^{T}Wy

其中W是一个矩阵,用来给每一个数据点赋予权重。类似于SVM中的核,常用的核是高斯核,介绍见下图(见《机器学习实战》P142)。

                       

#局部加权回归
def lwlr(testpoint,xArr,yArr,k=1):
    X=mat(xArr)
    y=mat(yArr).T
    m=shape(X)[0]
    weights=mat(eye(m))
    for i in range(m):
        diffMat=testpoint-X[i,:]
        weights[i,i]=exp(diffMat*diffMat.T/(-2.0*k**2))
    xTx=X.T*(weights*X)
    if linalg.det(xTx)==0:
        print('This matrix is singular, cannot do inverse')
        return
    w=xTx.I*(X.T*(weights*y))
    return testpoint*w
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

                                                                                                    k=0.05

                                                              

                                                                                                      k=0.01

                                                                

                                                                                                  k=0.005

                                                          

当K=1时,所有数据权重相同,拟合结果与标准回归相同。当k=0.01时,拟合效果较好。当k=0.005时,纳入了太多的噪声点,拟合曲线与数据点过于贴近,训练误差很小,但是会造成过拟合,对新数据的预测能力降低。

3.缩减法:

当样本特征个数n大于样本点数m时,X为非满秩矩阵,将不可逆。此时可以使用缩减法将某些不重要的特征去掉,降低模型的复杂度,

岭回归是一种常见的缩减法。简单来说就是在X^{T}X上加上\lambda I,使得矩阵不奇异,从而可以求逆。这种情况下,回归系数计算公式变为:

                                                                \widehat{w}=(X^{T}X+\lambda I)^{-1}X^{T}y

#岭回归
def ridgeRegress(xMat,yMat,lam=0.2):
    xTx=xMat.T*xMat
    denom=xTx+eye(shape(xMat)[1])*lam
    if linalg.det(denom)==0:
        print('This matrix is singular, cannot do inverse')
        return
    w=denom.I*(xMat.T*yMat)
    return w
def ridgeTest(xArr,yArr):
    xMat=mat(xArr)
    yMat=mat(yArr).T
    yMean=mean(yMat,0)
    yMat=yMat-yMean
    xMean=mean(xMat,0)
    varX=var(xMat,0)
    xMat=(xMat-xMean)/varX
    numTestPts=30
    wMat=mat(zeros((numTestPts,shape(xMat)[1])))
    for i in range(numTestPts):
        ws=ridgeRegress(xMat,yMat,lam=exp(i-10))
        wMat[i, :]=ws.T
    return wMat

计算不同i=0:29,对应\lambda=e^{i-10},\lambda以指数级变化,这样可以更容易看出在\lambda很大和很小时对回归系数的影响。如下图所示,在最左边\lambda很小时,得到原始的回归系数(与标准回归相同),在最右边,系数缩减为零。可以通过交叉验证得到合适的\lambda值。

x,y=loadDataSet('D:\python\code\machinelearninginaction\Ch08\\abalone.txt')
W=ridgeTest(x,y)
print(W)
fig=plt.figure()
ax=fig.add_subplot(111)
for i in range(8):
   ax.plot(W[:,i],label='w%s'% i)
ax.legend(loc='upper right')
plt.show()

                                                        

前项逐步线性回归:

开始对每一个权重取值为0,然后进行迭代,每次对w减小或者增大一个很小的数值,然后计算平方误差,若误差减小,则更新w值。


#归一化特征矩阵;使得每一特征相同重要
def regularize(xMat):#regularize by columns
    inMat = xMat.copy()
    inMeans = mean(inMat,0)   #calc mean then subtract it off
    inVar = var(inMat,0)      #calc variance of Xi then divide by it
    inMat = (inMat - inMeans)/inVar
    return inMat
#计算平方误差
def rssError(yArr,yHatArr): #yArr and yHatArr both need to be arrays
    return ((yArr-yHatArr)**2).sum()
#前项逐步线性规划
def stageWise(xArr,yArr,eps=0.01,numIt=500):
    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)
    ws=zeros((n,1))
    wsMax=ws.copy()
    W=mat(zeros((numIt,n)))
    for i in range(numIt):
        lowestError = 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
        W[i,:]=wsMax.T
        ws = wsMax.copy()
    return W

 下图所示为步长eps=0.005,迭代1000次,w的变化曲线。

                                                    

逐步线性回归可以帮助我们更好地认识数据特征,对模型进行改进。建立一个模型后,可以运行该算法,选择出比较重要的特征,可以对不重要的特征及时停止分析。每迭代100次便可以构建一个模型,运用交叉验证的方法选出最优参数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值