预测数值型数据:回归

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

求解回归系数的过程就是回归,,回归系数乘以输入值再讲结果加起来就得到预测值。假定回归系数存放在矩阵X中,而回归系数存放在向量w中,则预测值Y1=x1Tw给出,平方误差为(yi-xiTw)从1到m之和,用矩阵表示为(y-xw)T(y-xw),对w求导得XT(Y-Xw),欲求最值只须导数为零,所以w=(XTX)-1XTy,需要保证逆矩阵存在。

def loadDataSet(fileName):#准备数据
  numFeat=len(open(fileName).readline().split('\t'))-1
  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)#计算回归系数
  return ws

将ws与数据矩阵做内积即可得到预测值y

预测值yHat和真实值yActual用函数corrcoef来度量。

线性回归有可能出现欠拟合现象,因为它求得是具有最小均方误差的无偏估计值。

局部加权线性回归(LWLR)

给待预测点附近的每个点赋予一定的权重,,然后在这个子集上基于最小均方差来进行普通回归。与kNN一样,每次预测均需要事先选取出对应的数据子集。

w=(XTWX)-1XTWy,w是一个矩阵用来给每个点赋予权重,在此用高斯核对应的权重:w(i,i)=exp(|x(i)-x|/(-2k2)),w只含对角元素,并且点x与x(i)越接近,w(i,i)越大,k是用户指定的参数,她决定对附近点赋予多大的权重。

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):
    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):
  m=shape(testArr)[0]
  yHat=zeros(m)
  for i in range(m):
    yHat[i]=lwlr(testArr[i],xArr,yArr,k)
  return yHat

缺点:增加了计算量,因为它对每个点做出预测时都必须使用整个数据集。

岭回归

当特征比样本点还多时(n>m)求解逆矩阵会出错,所以引入岭回归,即在矩阵XTX上加一个λI从而使矩阵非奇异,进而能对XTXI求逆,I是一个m*m的单位矩阵,对角线元素全1,其他全0.则回归系数的计算公式为:(XTXI-1XTy,引入λ限制所有w之和,减少不重要的参数。

通过预测误差最小化得到λ:数据获取之后,首先抽一部分数据用于测试,剩余的作为训练集用于训练参数w,训练完毕之后再测试集上测试预测性能。通过选取不同的λ来重复上述测试过程,最终得到一个是预测误差最小的λ。

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
  xMeans=mean(xMat,0)
  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

上边是回归系数与log(λ)的关系,在λ很小的时候和先行回归一致,而在右边则全部缩减为0,在中间部分某值可以取得最好的预测效果,若要定量找到最佳参数,则需要进行交叉验证。

 

前向逐步回归

属于贪心算法,每一步都尽量减少误差。一开始,所有权重都设为1,然后每一步所做的决策是对某个权重增加或减少一个很小的值。

数据标准化,使其分布满足0均值和单位方差

在每轮迭代中:

  设置当前最小误差lowestError为正无穷

  对每个特征:

    增大或缩小:

      改变一个系数得到一个新的w

      计算新w下的误差

      如果误差Error小于当前最小误差lowestError:设置Wbest等于当前w

    将w设为新的Wbest

代码不贴了,逐步线性回归主要的优点在于它可以帮助人们理解现有的模型并作出改进。当构建了一个模型后,可以运行该算法找出重要的特征,这样就可能即使停止对哪些不太重要的特征的和收集。如果用于测试,该算法每100次迭代后就可以构建出一个模型,可以使用类似于10折交叉验证的方法比较这些模型,最终选择使误差最小的模型。

 

至于预测乐高玩具套装的价格示例我要先了解一下google API是怎么玩的。

 

 

 

 

posted on 2014-03-07 16:01  我是咖啡豆哈  阅读(726)  评论(0编辑  收藏  举报

导航