(1)用线性回归找到最佳拟合直线

线性回归的优点是结果易于理解,计算不复杂,缺点是对非线性的数据拟合不好,适用于数值型和标称型数据类型。

线性回归最重要的是找到回归系数,一旦找到回归系数,乘以输入值,再将结果全部累加在一起,就得到了预测值。(假定输入数据存放在矩阵X中,回归系数存放在向量W中,则预测结果Y = X.T*W)

找到合适的回归系数W一个最常见的方法是找出误差最小的W(误差值预测值和真实值的差值),我们一般采用平方误差:

以下代码可用来找到数据的最佳拟合直线:

1)标准回归函数和数据导入函数:

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

def standRegres(xArr,yArr):
    # 计算最佳拟合直线
    xMat = mat(xArr); yMat = mat(yArr).T
    xTx = xMat.T*xMat
    if linalg.det(xTx) == 0.0:
        # 如果行列式为0计算逆矩阵会出现错误
        print("This matrix is singular, cannot do inverse")
        return
    ws = xTx.I * (xMat.T*yMat) # .I返回逆矩阵,.T返回矩阵的转置
    return ws # ws存放的就是回归系数

导入数据集中的数据后所得到的最佳拟合直线如下图所示:

我们应该怎么判断模型的好坏呢?一种方法就是计算预测值yHat序列和真实值y序列的匹配程度(即相关系数),可以调用python中Numpy库的corrcoef()命令来计算

可以得到相关系数:

可以看到对角线上的数据是1.0,因为yMat,yHat和自己的匹配程度都是最完美的,而yHat和yMat的匹配程度大约为0.98,说明匹配程度相当不错。

(2)局部加权线性回归

线性回归有可能会出现欠拟合现象,所以引入局部加权线性回归(LWLR),该算法给待预测点附近的每一个点赋予一定的权重,LWLR算法解出回归系数W的公式为:

LWLR使用“核”来对附近的点赋予更高的权重,最常见的是高斯核,对应的权重如下:

点X与X(i)越近,w(i,i)就越大,上面公式包含一个需要用户指定的参数K决定了对附近的点赋予多大的权重,也是LWLR唯一需要考虑的参数。

LWLR代码如下:

# 给定X空间中的任意一点,计算出对应的预测值yHat
def lwlr(testPoint,xArr,yArr,k=1.0):
    # lwlr为局部加权线性回归
    # 随样本点与待预测点距离的递增,权重值将以指数级衰减
    # 输入参数K控制衰减的速度
    xMat = mat(xArr); yMat = mat(yArr).T
    m = shape(xMat)[0]
    weights = mat(eye((m)))
    '''创建对角权重矩阵weights,为每个样本点初始化了一个权重'''
    '''遍历数据集,计算每个样本点对应的权重值'''
    for j in range(m):
        diffMat = testPoint - xMat[j,:]
        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

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,所得到的结果如下图所示:

以上三张图分别为K=1.0/0.01/0.003时候的结果,可以看出K=0.01时可以挖掘出数据的潜在规律,但K=0.003时候就会出现overfitting的问题。

(3)岭回归

岭回归就是在矩阵(XT)X上加入一个λI从而使得矩阵非奇异,进而能对(XT)X+λI求逆。矩阵I是一个m维单位矩阵,λ是用户自定义的数值,此时回归系数的计算公式是:

引入λ后能够减少不重要的参数,从而更好地理解数据,有更好的预测结果。

岭回归的实现代码如下:

def ridgeRegres(xMat,yMat,lam=0.2):
    # 计算回归系数
    xTx = xMat.T*xMat
    denom = xTx + eye(shape(xMat)[1])*lam
    if linalg.det(denom) == 0.0:
        print("This matrix is singular, cannot do inverse")
        return
    ws = denom.I * (xMat.T*yMat)
    return ws

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
    # 数据标准化(减去均值再除以方差
    xMeans = mean(xMat,0)   #calc mean then subtract it off
    xVar = var(xMat,0)      # 计算方差
    xMat = (xMat - xMeans)/xVar
    numTestPts = 30
    wMat = zeros((numTestPts,shape(xMat)[1]))
    for i in range(numTestPts):
        ws = ridgeRegres(xMat,yMat,exp(i-10))
        wMat[i,:]=ws.T
    return wMat
01-10 20:27