第一次写,新手试水。谢谢
数据导入及预处理
def loadDateSet(filename):
"""
加载数据
@param filename: 数据集(txt)
@return: dataMet:对应的数据集 labelMat:对应的分类标签,即类别标签
"""
numFeat = len(open(filename).readline().split('\t')) - 1 #解析以tab键分隔的文件中的浮点数
dataMat = []
labelMat = []
fr = open(filename)
for line in fr.readlines():
lineArr = [] #读每一行
curLine = line.strip().split('\t') #去掉一行中tab分隔的空白
for i in range(numFeat):
lineArr.append(float(curLine[i])) #将数据添加到lineArr数组中
dataMat.append(lineArr)
labelMat.append(float(curLine[-1]))
return dataMat,labelMat
一、线性回归
1.1 工作原理
① 读入数据,将数据特征x、特征标签y存储在矩阵x、y中
② 验证 xTx = xMat.T * xMat 矩阵是否可逆
③ 使用最小二乘法求得到回归系数 w 的最佳估计
1.2 求回归系数
def standRegres(xArr, yArr):
"""
线性回归
@param xArr: 输入的样本数据
@param yArr: 输入数据的类别标签,即每个样本对应的目标变量
@return: ws:回归系数(w = (x^t * x)^-1 * x^t * y)
"""
xMat = np.mat(xArr) #将xArr转换为矩阵
yMat = np.mat(yArr).T #将yArr转换为矩阵并进行转置;mat().T 代表的是对矩阵进行转置操作
xTx = xMat.T * xMat
if np.linalg.det(xTx) == 0.0: #判断xTx是否可逆,det()=0不可逆
print("This matrix is singular , cannot do inverse!")
return
ws = xTx.I * (xMat.T * yMat)
return ws
二、局部加权线性回
完整源码
import numpy as np
import matplotlib.pyplot as lib
import pandas as pan
def loadDateSet(filename):
"""
加载数据
@param filename: 数据集(txt)
@return: dataMet:对应的数据集 labelMat:对应的分类标签,即类别标签
"""
numFeat = len(open(filename).readline().split('\t')) - 1 #解析以tab键分隔的文件中的浮点数
dataMat = []
labelMat = []
fr = open(filename)
for line in fr.readlines():
lineArr = [] #读每一行
curLine = line.strip().split('\t') #去掉一行中tab分隔的空白
for i in range(numFeat):
lineArr.append(float(curLine[i])) #将数据添加到lineArr数组中
dataMat.append(lineArr)
labelMat.append(float(curLine[-1]))
return dataMat,labelMat
def standRegres(xArr, yArr):
"""
线性回归
@param xArr: 输入的样本数据
@param yArr: 输入数据的类别标签,即每个样本对应的目标变量
@return: ws:回归系数(w = (x^t * x)^-1 * x^t * y)
"""
xMat = np.mat(xArr) #将xArr转换为矩阵
yMat = np.mat(yArr).T #将yArr转换为矩阵并进行转置;mat().T 代表的是对矩阵进行转置操作
xTx = xMat.T * xMat
if np.linalg.det(xTx) == 0.0: #判断xTx是否可逆,det()=0不可逆
print("This matrix is singular , cannot do inverse!")
return
ws = xTx.I * (xMat.T * yMat)
return ws
def regression1x1():
"""
画图
一元线性回归作图(ex0.txt)
"""
xArr, yArr = loadDateSet("ex0.txt")
#xArr, yArr = loadDateSet("abalone.txt")
xMat = np.mat(xArr)
yMat = np.mat(yArr)
ws = standRegres(xArr, yArr)
fig = lib.figure()
ax = fig.add_subplot(111)
ax.scatter(xMat[:, 1].flatten().A[0], yMat.T[:, 0].flatten().A[0])
xCopy = xMat.copy()
xCopy.sort(0)
yHat = xCopy * ws
ax.plot(xCopy[:, 1], yHat)
lib.show()
def lwlr(testPoint, xArr, yArr, k=1.0):
"""
局部加权线性回归
@param testPoint: 样本点
@param k:关于赋予权重矩阵的核的一个参数,与权重的衰减速率有关
@return:testPoint * ws:数据点与具有权重的系数相乘得到的预测点
计算权重的公式:w = e^((x^((i))-x) / -2k^2)
"""
xMat = np.mat(xArr)
yMat = np.mat(yArr).T
m = np.shape(xMat)[0] #获取xMat的行数
weights = np.mat(np.eye(m)) # eye()返回一个对角线元素为1,其他元素为0的二维数组,创建权重矩阵weights,该矩阵为每个样本点初始化了一个权重
for j in range(m):
diffMat = testPoint - xMat[j,:] #计算testPoint与输入样本点之间的距离,然后下面计算出每个样本贡献误差的权值
weights[j, j] = np.exp(diffMat * diffMat.T / (-2.0 * k**2)) #k控制衰减的速度
xTx = xMat.T * (weights * xMat) #在原来的求解上对xMat加上了权重,即每行为x1乘以对应的权重
if np.linalg.det(xTx) == 0.0:
print("This matrix is singular , cannot do inverse!")
return
ws = xTx.I * xMat.T * (weights * yMat) #每行的x和y都分别乘以对应的权重
return testPoint * ws
def lwlrTest(testArr, xArr, yArr, k=1.0):
"""
测试局部加权线性回归
@param testArr: 测试所用所有的样本点
@return:yHat:预测点的估计值
"""
m = np.shape(testArr)[0] # 得到样本点的总数
yHat = np.zeros(m) # 构建一个全部都是 0 的 1 * m 的矩阵
for i in range(m): #循环利用lwlr函数计算出testArr每行向量对应的ws,算出加权预测值
yHat[i] = lwlr(testArr[i], xArr, yArr, k)
return yHat
def regression2():
"""
测试2:
局部加权线性回归作图
"""
xArr, yArr = loadDateSet("ex0.txt")
yHat = lwlrTest(xArr, xArr, yArr, 0.003)
xMat = np.mat(xArr)
yMat = np.mat(yArr)
srtInd = xMat[:, 1].argsort(0) #argsort()函数是将x中的元素从小到大排列,提取其对应的index(索引),然后输出
xSort = xMat[srtInd][:, 0, :]
fig = lib.figure()
ax = fig.add_subplot(111)
ax.plot(xSort[:, 1], yHat[srtInd])
ax.scatter(xMat[:, 1].flatten().A[0], yMat.T.flatten().A[0], s=2, c='red')
lib.show()
def rssError(yArr,yHatArr):
"""
计算预测值和实际值方差
"""
return ((yArr-yHatArr)**2).sum()
def abaloneAgeTest():
"""
预测鲍鱼的年龄
"""
abX, abY = loadDateSet("abalone.txt")
# 使用不同的核进行预测
oldyHat01 = lwlrTest(abX[0:99], abX[0:99], abY[0:99], 0.1)
oldyHat1 = lwlrTest(abX[0:99], abX[0:99], abY[0:99], 1)
oldyHat10 = lwlrTest(abX[0:99], abX[0:99], abY[0:99], 10)
# 打印出不同的核预测值与训练数据集上的真实值之间的误差大小
print("old yHat01 error Size is :", rssError(abY[0: 99], oldyHat01.T))
print("old yHat1 error Size is :", rssError(abY[0: 99], oldyHat1.T))
print("old yHat10 error Size is :", rssError(abY[0: 99], oldyHat10.T))
# 打印出 不同的核预测值 与 新数据集(测试数据集)上的真实值之间的误差大小
newsyHat01 = lwlrTest(abX[100:199], abX[0:99], abY[0: 99], 0.1)
print("new yHat01 error Size is :", rssError(abY[100: 199], newsyHat01.T))
newsyHat1 = lwlrTest(abX[100:199], abX[0:99], abY[0: 99], 1)
print("new yHat1 error Size is :", rssError(abY[100: 199], newsyHat1.T))
newsyHat10 = lwlrTest(abX[100:199], abX[0:99], abY[0:99], 10)
print("new yHat10 error Size is :", rssError(abY[100: 199], newsyHat10.T))
# 使用简单的 线性回归 进行预测,与上面的计算进行比较
standWs = standRegres(abX[0:99], abY[0: 99])
standyHat = np.mat(abX[100: 199]) * standWs
print("standRegress error Size is:", rssError(abY[100: 199], standyHat.T.A))