线性回归就是用一条直线去拟合所有的数据点,使得这些数据点拟合出来的误差最小。一般使用平方误差最小来作为标准去寻找线性回归的系数ws。用平方误差来作为标准是严格的数学证明的。
大概证明的思路是这样的,假设,其中是线性回归函数,通过线性回归获得的结果与真实值y之间的误差,我们假设c服从于(0, )的正态分布,我们可以使用极大似然估计出取得最佳的系数时,必然是取最小的平方误差,具体的证明过程感兴趣的可以自己去查找下资料,只有有概率论和线性代数的基础看懂证明应该不难。
然后在根据最小二乘法对w进行估计,最后得到最佳的w是
代码如下:
'''导入相应的库,导入数据集,数据集如下图所示'''
from numpy import *
import numpy as np
import pandas as pd
line = pd.read_table('C:/Users/ASUS/Desktop/data mining/data/line/ex0.txt',header=None)
line.head()
'''获取x和y'''
x=line.iloc[:,0:2] ####x就是上图中前两列
y=line.iloc[:,2:3] ####y就是最后一列
'''计算最佳的系数矩阵ws,ws的公式如上'''
def clc_w(x,y):
x=mat(x)
y=mat(y)
xTx=x.T*x
if linalg.det(xTx)==0.0:
print('error')
return
ws=xTx.I * (x.T*y)
return ws
ws=clc_w(x,y)
'''画出原数据的散点图和拟合直线'''
import matplotlib.pyplot as plt
fig=plt.figure()
ax=fig.add_subplot(111)
ax.scatter(x[:,1],y)
ax.plot(x[:,1],y_predict,color='r')
显然这个直线拟合的不是特别的好,容易出现欠拟合的现象。我们可以使用局部加权线性回归去给每个待预测的点赋予一定的权重,这种算法解出来的回归系数w的形式是
其中的是一个矩阵,用于给每个数据点赋予一定的权重,一般最常用的核是高斯核,其公式是
具体的代码如下:
x=line.iloc[:,0:2]
y=line.iloc[:,2:3]
'''主要添加了w(i,i)对角阵的求解,w(i,i)的计算公式图上所示,x_test是一个1*2的矩阵,为x[i,:],是x的每一行'''
def creat_ws(x_test,x,y,k):
x=mat(x)
y=mat(y)
m=shape(x)[0]
ws1=mat(eye(m))
for j in range(m):
diffMat=xtest-x[j,:]
ws1[j,j]=np.exp(diffMat*diffMat.T/(-2.0*k**2))
xTx=x.T*(ws1*x)
if linalg.det(xTx)==0.0:
print('error')
return
ws=xTx.I*(x.T*(ws1*y))
return xtest*ws
'''xtest是一个n*2的矩阵其表示为x,用于取出x的每一行给x_test。'''
def test_ws(xtest,x,y,k=0.1):
m=shape(xtest)[0]
y1=zeros(m)
for i in range(m):
y1[i]=creat_ws(xtest[i],x,y,k)
return y1
测试函数
y_last=test_ws(x,x,y,k=0.01)
s=np.array(y_last)
srtInt=x[:,1].argsort(0) ####将x按照第1列进行排序,返回下标
xa=x[srtInt][:,1] ####取出第一列,
ya=s[srtInt]
画图观察效果
import matplotlib.pyplot as plt
fig=plt.figure()
ax=fig.add_subplot(111)
ax.scatter(x[:,1],y)
ax.plot(x[:,1],y_predict,color='r')
ax.plot(xa,ya,color='y')
拟合的结果如图所示,在调节不同的k值时还会对结果有所影响,k值越小则拟合的就越越接近真实值,容易造成过拟合。具体k值哈需要自己调节。
绿色是原来的散点图,红色线性回归拟合的结果,蓝色是加权线性回归拟合的结果。显然加权线性回归可以更好地去解释点的分布,但是也要注意好k值得选取,选的小了容易造成过拟合,小了,容易欠拟合。