[关闭]
@richey 2016-04-15T12:16:25.000000Z 字数 6556 阅读 1478

机器学习笔记1-回归问题

机器学习 回归 梯度下降


1 线性回归(Linear Regression)

1.1 线性回归入门示例

先看个例子,比如,想用面积和卧室个数来预测房屋的价格
训练集如下:
beIZFr.png-11.7kB
首先,我们假设为线性模型,那么hypotheses定义为


其中表示面积和#bedrooms(卧室)两个特征(feature)
那么对于线性模型,更为通用的写法为

其中把看成向量,并且,就可以表示成最后那种,两个向量相乘的形式。

线性回归的目的,就是通过训练集找出使得误差最小的一组参数(称为学习),为了可以量化误差,定义代价函数(cost function)

比较好理解,就是训练集中所有样本点,真实值和预测值之间的误差的平方和,其中1/2是为了后面计算方便,求导时会消掉,所以我们目的就是找到使得最小,这就是最小二乘法(最小平方),很容易理解。
richey批注:这里的m代表m个训练样本,每个样本有n个特征(的纬度)。

291925279255104.jpg-22kB

1.2 梯度下降法(gradient descent)

为了求解这个最优化问题,即找到使得最小,可以有很多方法。
先介绍梯度下降法 ,这是一种迭代方法,先随意选取初始,比如,然后不断的以梯度的方向修正,最终使收敛到最小。
当然梯度下降找到的最优是局部最优,也就是说选取不同的初值,可能会找到不同的局部最优点,但是对于最小二乘的代价函数模型,比较简单只有一个最优点,所以局部最优即全局最优。
对于某个参数的梯度,其实就是对该参数求导的结果,所以对于某个参数每次调整的公式如下:


此处:=为赋值运算
称为“学习率”(learning rate),代表下降幅度,步长,小会导致收敛慢,大会导致错过最优点,所以公式含义就是,每次在梯度方向下降一步。
下面继续推导,假设训练集里面只有一个样本点,那么梯度推导为:



richey注解: 是特征的纬度,注意到上式是对求偏导,因此第3个式子中只有,其他项对的偏导数为零。

1.2.1 批梯度下降法

就是求导过程,但是实际训练集中会有m个样本点,所以最终递推公式为:
重复迭代以下直至收敛{



因为 中有多个参数,所以每次迭代对于每个参数都需要进行梯度下降,直到收敛到最小值,这个方法称为批梯度下降(batch gradient descent),理由是每次计算梯度都需要遍历所有的样本点,这是因为梯度的导数,而是需要考虑所有样本的误差和。
批梯度下降方法的问题就是当样本点很大的时候,基本就没法算了(每次迭代都遍历样本空间一遍)。

1.2.2 随机梯度下降法

所以提出一种stochastic gradient descent(随机梯度下降),想法很简单,即每次只考虑一个样本点,而不是所有样本点,那么公式就变为:

Loop{
for i in m,{


{
}
其实意思就是,每次迭代只是考虑让该样本点的趋向最小,而不管其他的样本点,这样算法会很快,但是收敛的过程会比较曲折,适合用于较大训练集的场景。
梯度下降法的缺点:

1.3 最小二乘法(LMS)

其推导过程的思路:
推导得出的矩阵表达式,梯度为零时的取得最小值。


相当于通过求解矩阵方程得到的解析解。

1.4 加权线性回归

首先考虑下图中的几种曲线拟合情况:
302140093624493.jpg-24.1kB
最左边的图使用线性拟合,但是可以看到数据点并不完全在一条直线上,因而拟合的效果并不好。如果我们加入项,得到,如中间图所示,该二次曲线可以更好的拟合数据点。
我们继续加入更高次项,可以得到最右边图所示的拟合曲线,可以完美地拟合数据点,最右边的图中曲线为5阶多项式,可是我们都很清醒地知道这个曲线过于完美了,对于新来的数据可能预测效果并不会那么好。
对于最左边的曲线,我们称之为欠拟合--过小的特征集合使得模型过于简单不能很好地表达数据的结构,最右边的曲线我们称之为过拟合--过大的特征集合使得模型过于复杂。
  正如上述例子表明,在学习过程中,特征的选择对于最终学习到的模型的性能有很大影响,于是选择用哪个特征,每个特征的重要性如何就产生了加权的线性回归。在传统的线性回归中,学习过程如下:

  1. Fit to minimaize
  2. Output:

richey注解:以上求和将m个样本同等看待

而加权线性回归学习过程如下:
1. Fit to minimaize
2. Output:
  二者的区别就在于对不同的样本赋予了不同的非负值权重,权重越大,对于代价函数的影响越大。一般选取的权重计算公式为:

其中,x是要预测的特征,表示离x越近的样本权重越大,越远的影响越小。
总结一下:加权线性回归LWR算法是一种non-parametric(非参数)学习算法,而线性回归则是一种parametric(参数)学习算法。
所谓参数学习算法它有固定的明确的参数,参数一旦确定,就不会改变了,我们不需要在保留训练集中的训练样本。
而非参数学习算法,每进行一次预测,就需要重新学习一组,是变化的,所以需要一直保留训练样本。也就是说,当训练集的容量较大时,非参数学习算法需要占用更多的存储空间,计算速度也较慢。有得必有失,效果好当然要牺牲一些其他的东西。

1.5 代码实现

1.5.1 使用scikit-learn库

1.5.1.1 最小二乘法

1.5.2 不使用库

  1. from numpy import *
  2. import matplotlib.pyplot as plt
  3. def loadDataSet(filename):
  4. numFeat = len(open(filename).readline().split('\t'))-1
  5. dataMat = []
  6. labelMat = []
  7. fr = open(filename)
  8. for line in fr.readlines():
  9. lineArr = []
  10. curLine = line.strip('\n').split('\t')
  11. for i in range(numFeat):
  12. lineArr.append(float(curLine[i]))
  13. dataMat.append(lineArr)
  14. labelMat.append(float(curLine[-1]))
  15. return dataMat, labelMat
  16. def standMaReg(xArr, yArr):
  17. xMat = mat(xArr)
  18. yMat = mat(yArr).T
  19. xTx = xMat.T*xMat
  20. if linalg.det(xTx)==0.0:
  21. print 'This matrix is singular, connot do inverse'
  22. return
  23. ws = xTx.I*(xMat.T*yMat)
  24. return ws
  25. def standBaGradReg(xArr, yArr, alpha=0.001, iter_num=15):
  26. xMat = mat(xArr)
  27. yMat = mat(yArr).T
  28. m,n=shape(xMat)
  29. weights = mat(ones((n,1)))
  30. for i in range(iter_num):
  31. yPredict = mat(xMat*weights)
  32. tmp=mat(zeros((n,1)))
  33. for j in range(n):
  34. tmp[j,:] += alpha*sum(multiply((yMat-yPredict),xMat[:,j]))
  35. weights = weights + tmp
  36. return weights
  37. def lwlr(testPoint, xArr, yArr, k=1.0):
  38. xMat = mat(xArr)
  39. yMat = mat(yArr).T
  40. m = shape(xMat)[0]
  41. weights = mat(eye((m)))
  42. for j in range(m):
  43. diffMat = testPoint - xMat[j,:]
  44. weights[j,j] = exp(diffMat*diffMat.T/(-2.0*k**2))
  45. xTx = xMat.T*(weights*xMat)
  46. if linalg.det(xTx) == 0.0:
  47. print "This matrix is singular, cannot do inverse"
  48. return
  49. ws = xTx.I*(xMat.T*(weights*yMat))
  50. return testPoint*ws
  51. def lwlrTest(testArr, xArr, yArr, k=1.0):
  52. m = shape(testArr)[0]
  53. yPre = zeros(m)
  54. for i in range(m):
  55. yPre[i] = lwlr(testArr[i], xArr, yArr, k)
  56. return yPre
  57. def ridgeRegres(xMat, yMat, lam=0.2):
  58. xTx = xMat.T*xMat
  59. denom = xTx + eye(shape(xMat)[1])*lam
  60. if linalg.det(denom) == 0.0:
  61. print "This matrix is singular, cannot do inverse"
  62. ws = denom.I*(xMat.T*yMat)
  63. return ws
  64. def ridgeTest(xArr, yArr, numIter=30):
  65. xMat = mat(xArr)
  66. yMat = mat(yArr).T
  67. yMean = mean(yMat,0)
  68. yMat = yMat - yMean
  69. xMeans = mean(xMat, 0)
  70. xVar = var(xMat, 0)
  71. xMat = (xMat - xMeans)/xVar
  72. wMat = zeros((numIter,shape(xMat)[1]))
  73. lamList = []
  74. for i in range(numIter):
  75. lamList.append(exp(i-10))
  76. ws = ridgeRegres(xMat, yMat, exp(i-10))
  77. wMat[i,:]=ws.T
  78. return wMat, lamList
  79. def plotReg(weights, xArr, yArr, xIndex=0):
  80. xMat = mat(xArr)
  81. yMat = mat(yArr)
  82. fig = plt.figure()
  83. ax = fig.add_subplot(111)
  84. ax.scatter(xMat[:,xIndex].flatten().A[0], yMat.T[:,0].flatten().A[0])
  85. yPredict = xMat*weights
  86. ax.plot(xMat[:,xIndex], yPredict)
  87. plt.show()
  88. xArr, yArr = loadDataSet("ex0.txt")
  89. ws1 = standMaReg(xArr, yArr)
  90. print "ws1", ws1
  91. plotReg(ws1, xArr, yArr, 1)
  92. ws2 = standBaGradReg(xArr, yArr, 0.001, 1000)
  93. print "ws2", ws2
  94. yPre = lwlrTest(xArr, xArr, yArr, 0.01)
  95. xMat = mat(xArr)
  96. srtInde = xMat[:,1].argsort(0)
  97. xSort = xMat[srtInde][:,0,:]
  98. fig = plt.figure()
  99. ax = fig.add_subplot(111)
  100. ax.plot(xSort[:,1], yPre[srtInde])
  101. ax.scatter(xMat[:,1].flatten().A[0], mat(yArr).T.flatten().A[0], s=2, c='red')
  102. plt.show()
  103. abX, abY = loadDataSet('abalone.txt')
  104. weights, lam = ridgeTest(abX, abY)
  105. plt.plot(weights)
  106. plt.show()

2 逻辑回归

3 Softmax回归

1 http://www.cnblogs.com/fxjwind/p/3626173.html?utm_source=tuicool&utm_medium=referral
2 http://blog.csdn.net/moodytong/article/details/10041547
3 http://www.cnblogs.com/fanyabo/p/4060498.html

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注