这是记录自学的过程,目前的理论基础就是:大学高等数学+线性代数+概率论。编程基础:C/C++,python
目前的学习方法如下:理论:斯坦福Andrew NG machine learning,系列课程。代码实战:引用书籍 机器学习实战(python)。真枪实战: 研究一个案例,建模选择合适的机器学习算法,分析数据。演变:基于C/C++ 在linux下实现部分机器学习过程。将在学习中期阶段去实现。
理论推导同线性回归差不多再其基础之上乘以一个权值w。
先看看线性回归的理论推导结果:
因为后面会用python来检测这个算法,所以我们统一用矩阵公式,LWLR在其基础上乘以W得出来的的结果是:
这里省略了,LWLR的结论推导过程,感兴趣的同学可以去了解下。虽然我可能理解不够透彻,无法很顺畅的把推导过程写出来,这是件很遗憾的事,我相信后面慢慢会理解这些的。
我们先来看下我们要使用的数据的结构:
前面两列代表X1和X2,会被读到一个矩阵里面xArr。第三列代表Y,被读到yArr.第一列是作为常数用的,所以数值都是1。
先看一下对单点进行回归的主要代码:
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,:] #
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
深入分析:
这段代码主要作用是,任意给定空间一点,计算出对应的预测值yHat。
xMat = mat(xArr); yMat = mat(yArr).T 把数组变成举证此时xMat是n行两列,yMat是n行一列。
m = shape(xMat)[0] 读取xMat矩阵的行数,如果后面跟着[1]则是列数,shape保存着这样一组数据。
weights = mat(eye((m))) 创造一个m*m的单位矩阵,也即是对角权值矩阵
for j in range(m): #next 2 lines create weights matrix
diffMat = testPoint - xMat[j,:] #
weights[j,j] = exp(diffMat*diffMat.T/(-2.0*k**2))
上面是一个for循环,为了创造w这个矩阵,也就是上面所说的高斯核。先求出被测数据与已知数据的差值,因为都是1*2的矩阵,所以可以直接相减。接着diffMat*diffMat.T其实就是求|diffMat|的过程,求出来是一个值。套入高斯公式,就可以循环求出高斯核的每一个数据对应的权值。
xTx = xMat.T * (weights * xMat) xMat转置后是一个2*n的矩阵;eights*xMat 就是n*n 与n*2相乘,结果是n*2的矩阵。最后两个相乘,变成2*2的矩阵。
if linalg.det(xTx) == 0.0:
print "This matrix is singular, cannot do inverse"
return
判断刚才生成的2*2矩阵是否存在逆矩阵,也就是求他的行列值是否为零。
ws = xTx.I * (xMat.T * (weights * yMat)) 这就是求回归系数的公式套用,xTx.I 就是求逆矩阵的意思,后面也就是如上面所说。
最后返回预测的的值,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=1.0时计算后得出来的数据的图:
可以看出,K=1时导致大部分数据的权值都比较大,如同将所有数据视为等同权重,得出的最佳拟合直线和标准的回归一致,为一条直线(蓝色)。所以需要微调一下K的值,比如调成0.003的结果:
可以看出,这个时候纳入了太多的噪声数据,处于过拟合状态。再把k调成0.01时:
这个时候数据呈现出来的曲线比较很好的拟合了大多数数据点.
下面是画图的代码,原本没有提供函数形式的,手输入比较麻烦,整理成函数形式比较方便:
def plotshow(xMat,yHat,yArr):
srtInd = xMat[:,1].argsort(0)
xSort = xMat[srtInd][:,0,:]
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')
plt.show()