问题
前面教程我们已经讲了 怎么样求解 y = Q *X 的过程 。
过拟合 和欠拟合
但是当数据量较小的时候 会遇到 这样的问题: 过拟合 和欠拟合
奇异矩阵问题
这个矩阵当没有 逆矩阵的时候怎么样求解。
局部加权
局部加权线性回归是普通线性回归的一个改进,普通的线性回归努力寻找一个使得全局代价函数最小的模型。这个模型对于整体来说是最好的,但对于局部点来说,可能不是最好的。比如图一是线性回归得到的模型,相对于图二来说,明显不够完美,图三虽然最完美但是存在过拟合风险。那么,如何用线性回归得到一个局部更准确(可能非线性模型拟合更好)的结果呢?这时,局部加权线性回归出现了。
过拟合
线太依赖训练数据了,完全贴着数据走 如图三
在训练集(training set)上表现好,但是在测试集上效果差,也就是说在已知的数据集合中非常好,但是在添加一些新的数据进来训练效果就会差很多,造成这样的原因是考虑影响因素太多,超出自变量的维度过于多了
欠拟合
如上图二 模型拟合不够,在训练集(training set)上表现效果差,没有充分的利用数据,预测的准确度低。预测值和实际值偏差过大 。
局部加权
如图 下图红线 太直 欠拟合 。 我们可以在每一个 预测点 适当的增加 一个权重 也就是稍微变弯曲,也就是去接近图中的 那条弯曲线。给每一个点 都加上一个权重。
这个权重 我们怎么取呢 ?
通常 我们用的是 高斯核函数 。
它的图像如下 :
x是待测点,r控制了权值变化的速率,r越大,图像越瘦,离x越远权值下降越快
我们发现这个图像很像高斯分布,越靠近x,权值越大
k 的取值 也就是 公式中的 r 取值 得到的图像。
公式:
这个公式 推导过程就不赘述了 ,网上也有很多 。
Y = Q * X Q 求解如下:
W 取上述的高斯核函数。
python 实践:
def loaddataSet(filename):
numfeat = len(open(filename).readline().split('\t'))-1
dataMat = [];labelsVec = []
file = open(filename)
for line in file.readlines():
lineArr = []
curLine = line.strip().split('\t')
for i in range(numfeat):
lineArr.append(float(curLine[i]))
dataMat.append(lineArr)
labelsVec.append(float(curLine[-1]))
return dataMat,labelsVec
#局部加权
def lwlr(testPoint,xArr,yArr,k = 1.0):
xMat = mat(xArr);yMat = mat(yArr).T
m = shape(xMat)[0]
weights = mat(eye(m))
print("weights.shape=",weights.shape,yMat.shape)
# 求解 权重 W
for i in range(m):
diffMat = testPoint - xMat[i,:]
weights[i,i] = exp(diffMat * diffMat.T/(-2.0*k**2))
xTWx = xMat.T * (weights*xMat)
if linalg.det(xTWx)==0.0:
print('this matrix is singular,cannot do inverse\n')
return
#求解 Q
sigma = xTWx.I * (xMat.T * (weights * yMat))
#print("sigma==",sigma.shape)
return testPoint * sigma
def lwlrTest(testArr,xArr,yArr,k = 1.0):
m = shape(testArr)[0]
yHat = zeros(m)
print("m==",m)
for i in range(m):
yHat[i] = lwlr(testArr[i],xArr,yArr,k)
return yHat
def PlotLine1(testArr,xArr,yArr,k = 1.0):
xMat = mat(xArr)
yMat = mat(yArr)
print(xMat.shape,yMat.shape)
yHat = lwlrTest(testArr,xArr,yArr,k)
srtInd = xMat[:,1].argsort(0)
xsort = xMat[srtInd][:,0,:]
ax = plt.subplot(111)
ax.scatter(xMat[:,1].flatten().A[0],yMat.T[:,0].flatten().A[0],s = 2,c = 'red')
ax.plot(xsort[:,1],yHat[srtInd])
plt.show()
def Testlwlr():
x,y=loaddataSet("./ex0.txt")
print("xMat==",x.__sizeof__())
x1,y1=loaddataSet("./ex1.txt")
PlotLine1(x,x,y,0.05)
上述的 需要的txt 在git 上下载
岭回归
矩阵的知识
奇异矩阵:
若矩阵A相应的行列式D=0,称A为奇异矩阵,否则称为非奇异矩阵.
矩阵 的秩:
定义1:用初等行变换将矩阵A化为阶梯形矩阵, 则矩阵中非零行的个数就定义为这个矩阵的秩, 记为r(A),根据这个定义, 矩阵的秩可以通过初等行变换求得。需要注意的是, 矩阵的阶梯形并不是唯一的, 但是阶梯形中非零行的个数总是一致的
初等变换 和矩阵的秩 概念查看
结论:
对 ,
若R(A)=n,称A为满秩矩阵(可逆矩阵,非奇异矩阵);
若R(A)<n,称A为降秩矩阵(不可逆矩阵,奇异矩阵)。
满秩矩阵是一个很重要的概念, 它是判断一个矩阵是否可逆的充分必要条件。
当 矩阵 M(n*n) 不是满秩矩阵的时候 就会 出现 为 0 的情况 。 也就是 这样的情况
为了 避免出现这种情况 我们给 他加上一个单位矩阵 乘上一个系数 。
最后:
那么 就变成了一个 满秩矩阵 不会出现为 0 的情况 。
所以 Q 的求解 方程 就可以变成如下 : 推导过程网上也很多 。
python 实现
#coding=utf-8
from numpy import *
import numpy as np
import matplotlib.pyplot as plt
filename='./ex0.txt' #文件目录
def loaddataSet(filename):
numfeat = len(open(filename).readline().split('\t'))-1
dataMat = [];labelsVec = []
file = open(filename)
for line in file.readlines():
lineArr = []
curLine = line.strip().split('\t')
for i in range(numfeat):
lineArr.append(float(curLine[i]))
dataMat.append(lineArr)
labelsVec.append(float(curLine[-1]))
return dataMat,labelsVec
def RidgeRegress(xMat ,yMat,lam=0.2):
xTx = xMat.T *xMat
print("xTx shape==",xTx.shape)
denom=xTx + eye(shape(xMat)[1])*lam
print("denom==", denom.shape)
if linalg.det(denom) == 0.0:
print (" this matrix is singular cannot do inverse")
return
ws = denom.I *(xMat.T *yMat)
print("ws shape==",ws.shape)
return ws
def RidgeTest(xArr,yArr):
xMat = mat(xArr)
yMat = mat(yArr).T
yMen = mean(yMat,0)
#yMat= yMat - yMen
xMean = mean(xMat,0)
#xMat =(xMat - xMean)
print("xMat==",xMat)
number =200
wMat = zeros( (number,shape(xMat)[1]) )
print("wMat=33=",wMat.shape)
for i in range(number):
ws = RidgeRegress(xMat,yMat, exp(i-15) )
wMat[i,:] = ws.T
return wMat
def TestRidge():
x,y= loaddataSet(filename)
wMat = RidgeTest(x,y)
print("wMat==",wMat.shape)
PlotLine(x,wMat)
TestRidge()