线性回归分析应该是我们最常用的分析模型了,根据身高和体重预测年龄
1.回归分析的基本概念
§回归分析假定自变量对因变量的影响强度是始终保持不变的,如公式所示:
对于因变量的预测值可以被分解成两部分:
常量(constant):x取值为零时y的平均估计量,可以被看成是一个基线水平
回归部分:它刻画因变量Y的取值中,由因变量Y与自变量X的线性关系所决定的部分,即可以由X直接估计的部分
其中的参数和含义如下:
Ŷ:y的估计值(所估计的平均水平),表示给定自变量的取值时,根据公式算得的y的估计值;
a:常数项,表示自变量取值均为0时因变量的平均水平,即回归直线在y轴上的截距
(多数情况下没有实际意义,研究者也不关心)
b:回归系数,在多变量回归中也称偏回归系数。自变量x 改变一个单位,y估计值的改变量。即回归直线 的斜率
2.其他的一些参数和概念
残差:估计值和每一个实测值之间的差被称为残差。它刻画了因变量y除了自变量x以外的其它所有未进入 该模型,或未知但可能与y有关的随机和非随机因素共同引起的变异,即不能由x直接估计的部分
模型适用条件:§线性趋势 §独立性 §正态性 §方差齐性
如果只是探讨自变量与因变量间的关系,则后两个条件可以适当放宽
样本量 :根据经验,记录数应当在希望分析的自变量数的20倍以上为宜
偏回归系数:
相应的自变量上升一个单位时,因变量取值的变动情况,即自变量对因变量的影响程度
标化偏回归系数:量纲问题,忽略量纲之后的回归系数
决定系数:
相应的相关系数的平方,用R2表示,它反映因变量y的全部变异中能够通过回归关系被自变量解释的比例
3.分析步骤
3..1自变量与因变量的相关趋势(散点图)进行描述性分析,找出强影响点
3.2对数据的分布,分析变量的正态性,和方差齐次性的问题
3.3进行线性回归建模
3.4考虑残差之间是否独立和残差的分布是否符合正态分布
P-P图,残差分布图
4.具体实现
4.1一般求解
-----------python的实现 (1)一般求解
--------python的实现 (1)一般求解-代码
#线性回归误差平方和最小
from numpy import *
import xlrd
import xlwt
import matplotlib.pyplot as plt
#导入数据
def loadDataSet(x=r"C:\Users\mei-huang\Desktop\data2.xlsx",y=u'回归数据'):
data=xlrd.open_workbook(x) #excel的位置
try:
table = data.sheet_by_name(y) # 通过名称获取 #excel的工作表名 列名放置在第一行
except:
print("no sheet in %s named sheet1"%data)
print(table.nrows,table.ncols)
x_data=[];y_data=[];labels=[]
for n in range(1,table.nrows): #,
col = []
for c in range(table.ncols): #
# print(table.cell(n,c).value,type(table.cell(n,c).value))
x=table.cell(n,c).value
col.append(float(x))
x_data.append(col[0:-1])
y_data.append(col[-1])
for n in range(1):
for c in range(table.ncols):
labels.append(table.cell(n,c).value)
return x_data,y_data,labels
#k值求解
def standRegres(xArr,yArr):
xMat = mat(xArr); yMat = mat(yArr).T #对变量进行转置
xTx = xMat.T*xMat #进行矩阵运算
if linalg.det(xTx) == 0.0:
print ("This matrix is singular, cannot do inverse")
return
ws = xTx.I * (xMat.T*yMat)
return ws
# 返回误差平方和
def rssError(yArr,yHatArr):
yArr=array(yArr);yHatArr=array(yHatArr)
# print(yArr[0,1:10],yHatArr[0,1:10])
return ((yArr-yHatArr)**2).sum()
#加载数据
xx,yy,labels= loadDataSet()
xMat=mat(xx[0:1000])
yMat=mat(yy[0:1000])
# 对变量进行描述性统计分析 绘制三点图和直方图
fig1 = plt.figure()
fig2=plt.figure()
fig3=plt.figure()
ax3 = fig3.add_subplot(111)
ax3.hist(yMat.flatten().A[0],bins=6,stacked=True)
ax3.set_title("%s-hist" %(labels[-1]))
for n in range(xMat.shape[1]):
ax = fig1.add_subplot(2,2,n+1)
ax.scatter(xMat[:,n].flatten().A[0],yMat.flatten().A[0])
ax.set_title("%s-%splot"%(labels[n],labels[-1]))
ax2 = fig2.add_subplot(2, 2, n+1)
ax2.hist(xMat[:,n])
ax2.set_title("%s-hist" %(labels[n]))
plt.show() #显示变量的分布图和与x的关系图
# #参数求解方式1-常规求解
# #一般线性回归
# #计算回归系数和预测值
k=standRegres(xMat,yMat)
print(k.T,k.shape)
y1=xMat*k
#计算真实值和预测值的相关系数
r=corrcoef(y1.T,yMat) #0.44 比较差的相关系数
print(r)
# 返回误差平方和
print(rssError(y1.T,yMat))
fig = plt.figure()
ax = fig.add_subplot(111)
# ax.scatter(yMat.flatten().A[0], y1.flatten().A[0])
# yMat=yMat[:,0].argsort(0) #将数组的数值从小到大排序,并按照对应的索引值输出
# print(yMat)
# yMat=yMat[yMat][:,0,:]
# y1=y1[yMat][:,0,:]
# yMat.flatten().A[0].sort()
# y1.flatten().A[0].sort()
ax.plot(range(1000),yMat.flatten().A[0], mec='r', mfc='w')
ax.plot(range(1000),y1.flatten().A[0], mec='g', mfc='w')
plt.show()
#写出结果到文件
book = xlwt.Workbook(encoding='utf-8', style_compression=0)
sheet = book.add_sheet('test', cell_overwrite_ok=True)
n=0
for x in range(k.shape[0]) :
sheet.write(n, 1, k[x,0])
n+=1
book.save(r'e:\test3.csv')
4.2加权系数回归
from numpy import *
import xlrd
import xlwt
import matplotlib.pyplot as plt
#导入数据
def loadDataSet(x=r"C:\Users\mei-huang\Desktop\data2.xlsx",y=u'回归数据'):
data=xlrd.open_workbook(x) #打开文件位置
try:
table = data.sheet_by_name(y) # 打开工作簿名称
except:
print("no sheet in %s named sheet1"%data)
print(table.nrows,table.ncols) #返回数据有多少行,有多少列
x_data=[];y_data=[];labels=[] #建立三个列表存放,变量x,变量y,变量名
for n in range(1,table.nrows): #对行进行循环
col = [] #存放一行内容
for c in range(table.ncols): # #对列进行循环
# print(table.cell(n,c).value,type(table.cell(n,c).value))
x=table.cell(n,c).value #取出数值
col.append(float(x)) #添加到col中
x_data.append(col[0:-1]) #添加x变量到x列表
y_data.append(col[-1]) #添加y 到y列表
for n in range(1): #添加列名到标签列表
for c in range(table.ncols):
labels.append(table.cell(n,c).value)
return x_data,y_data,labels
# 返回误差平方和
def rssError(yArr,yHatArr):
yArr=array(yArr);yHatArr=array(yHatArr) #把传入y1,y2的数据类型变成数组
# print(yArr[0,1:10],yHatArr[0,1:10])
return ((yArr-yHatArr)**2).sum() #返回(y1-y2)的平方和)
# 参数求解方式2-局部加权线性回归(LWLR)
'''正常线性回归,把所有的点看的一样重要,权重回归对于偏离较远的数据点的影响进行调低,降低对拟合直线的影响
k=1表示正常的线性回归-所有的点都一样,我们可以调整k得到不同效果,然后用这个k值对新的数据进行拟合'''
def lwlr(testPoint,xArr,yArr,k=1.0): #(需要预测数据集合,样本数据的x变量,样本数据的y变量,衰减系数)
xMat = mat(xArr); yMat = mat(yArr).T
m = shape(xMat)[0] #样本数据的行数
weights = mat(eye((m))) #创建对角矩阵(对角线上是1,其余都是0)
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) #返回调整权重后的数值x
if linalg.det(xTx) == 0.0:
print ("This matrix is singular, cannot do inverse")
return
ws = xTx.I * (xMat.T * (weights * yMat)) #得到回归系数
# print(ws)
return testPoint * ws
def lwlrTest(testArr,xArr,yArr,k=1.0): #k=1对所有的点赋予相同的权重,等价于最小二乘法
m = shape(testArr)[0] #需要预测的数据的行数
yHat = zeros(m) #建立空数组
for i in range(m): #将预测的数据返回
yHat[i]= lwlr(testArr[i],xArr,yArr,k)
return yHat #返回预测结果
#读入数据 1 已经知道结果的数据集合
xx,yy,labels= loadDataSet()
xMat=mat(xx[0:100])
yMat=mat(yy[0:100])
#读入数据2 需要预测的数据集合
xx1,xx2,labels1= loadDataSet(x=r"C:\Users\mei-huang\Desktop\data2.xlsx",y=u'预测数据') #在excel新建工作簿,只放入x的数据
xMat2=hstack((mat(xx1),mat(xx2).T)) #把数据按照列合并
#测试不同的k值查看对已经知道结果的数据进行拟合 ,返回拟合的曲线和拟合的误差
y2=lwlrTest(xMat,xMat,yMat,0.9) #调整k等于0.9
r=corrcoef(y2.T,yMat)[0,1] #返回相关系数
dis=rssError(y2.T,yMat)# 返回误差
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(range(len(yMat.flatten().A[0])),yMat.flatten().A[0], mec='r', mfc='w')
ax.plot(range(len(mat(y2).flatten().A[0])),mat(y2).flatten().A[0], mec='g', mfc='w')
plt.annotate(u"r:%s\ndis:%s"%(r,dis),xy=(75,23.75),xytext=(80,23.7),
# arrowprops=dict(facecolor="r", headlength=1, headwidth=3, width=2)
)
plt.show()
#对新的的数据进行拟合
y3=lwlrTest(xMat2,xMat,yMat,0.9) #经过测试k=0.9的效果最理想,新数据xMat2,用k=0.9做拟合
# print(y3)
#将对新数据的预测结果写入到指定文件
book = xlwt.Workbook(encoding='utf-8', style_compression=0)
sheet = book.add_sheet('test', cell_overwrite_ok=True)
n=0
for x in range(len(y3)) :
sheet.write(n, 1, y3[x])
n+=1
book.save(r'e:\test4.csv')