飞道的博客

预测美味鲍鱼的年龄(利用回归预测数值型数据)

332人阅读  评论(0)

写在前面: 我是「虐猫人薛定谔i」,一个不满足于现状,有梦想,有追求的00后
\quad
本博客主要记录和分享自己毕生所学的知识,欢迎关注,第一时间获取更新。
\quad
不忘初心,方得始终。
\quad

❤❤❤❤❤❤❤❤❤❤

数据介绍

该数据集来自UCI,记录了鲍鱼(一种介壳类水生动物)的年龄。鲍鱼的年龄可以通过鲍鱼壳的层数推算得到。

数据加载

def loadDataSet(fileName):
	numFeat = len(open(fileName).readline().split('\t')) -1
	dataMat = []
	labelMat = []
	fr = open(fileName)
	for line in fr.readlines():
		lineArr = []
		curline = line.strip().split('\t')
		for i in range(numFeat):
			lineArr.append(float(curline[i]))
		dataMat.append(lineArr)
		labelMat.append(float(curline[-1]))
	return dataMat, labelMat

简单的线性回归

def standRegres(xArr, yArr):
	xMat = np.mat(xArr)
	yMat = np.mat(yArr).T
	xTx = xMat.T * xMat
	if np.linalg.det(xTx) == 0.0:
		print("This matrix is singular, cannot do inverse")
		return
	ws = xTx.I * (xMat.T*yMat)
	return ws



def main():
	abX, abY = loadDataSet('./res/abalone.txt')
	ws = standRegres(abX[0:99], abY[0:99])
	yHat = np.mat(abX[100:199]) * ws
	print(rssError(abY[100:199], yHat.T.A))
	# yHat01 = lwlrTest(abX[0:99], abX[0:99], abY[0:99], 0.1)
	# yHat1 = lwlrTest(abX[0:99], abX[0:99], abY[0:99], 1)
	# yHat10 = lwlrTest(abX[0:99], abX[0:99], abY[0:99], 10)
	# print(rssError(abY[0:99], yHat01.T))
	# print(rssError(abY[0:99], yHat1.T))
	# print(rssError(abY[0:99], yHat10.T))

局部加权线性回归

def rssError(yArr, yHatArr):
	"""
	计算预测误差
	"""
	return ((yArr - yHatArr)**2).sum()


def lwlr(testPoint, xArr, yArr, k=1.0):
	xMat = np.mat(xArr)
	yMat = np.mat(yArr).T
	m = np.shape(xMat)[0]
	weights = np.mat(np.eye((m)))
	for j in range(m):
		diffMat = testPoint - xMat[j, :]
		weights[j, j] = np.exp(diffMat * diffMat.T / (-2.0*k**2))
	xTx = xMat.T * (weights * xMat)
	if np.linalg.det(xTx) == 0.0:
		print("This matrix is singular, cannot do inverse")
		return
	ws = xTx.I * (xMat.T * (weights * yMat))
	return testPoint * ws


def lwlrTest(testArr, xArr, yArr, k=1.0):
	m = np.shape(testArr)[0]
	yHat = np.zeros(m)
	for i in range(m):
		yHat[i] = lwlr(testArr[i], xArr, yArr, k)
	return yHat

def main():
	abX, abY = loadDataSet('./res/abalone.txt')
	yHat01 = lwlrTest(abX[0:99], abX[0:99], abY[0:99], 0.1)
	yHat1 = lwlrTest(abX[0:99], abX[0:99], abY[0:99], 1)
	yHat10 = lwlrTest(abX[0:99], abX[0:99], abY[0:99], 10)
	print(rssError(abY[0:99], yHat01.T))
	print(rssError(abY[0:99], yHat1.T))
	print(rssError(abY[0:99], yHat10.T))


可以看到,使用较小的核将得到较低的误差。下面我们来看看其在新数据集上的表现:

	yHat01 = lwlrTest(abX[100:199],abX[0:99], abY[0:99], 0.1)
	print(rssError(abY[100:199], yHat01.T))
	yHat1 = lwlrTest(abX[100:199], abX[0:99], abY[0:99], 1)
	print(rssError(abY[100:199], yHat1.T))
	yHat10 = lwlrTest(abX[100:199], abX[0:99], abY[0:99], 10)
	print(rssError(abY[100:199], yHat10.T))


从上面的结果,我们可以看到核大小等于10时的测试误差最小,但是它在训练集上的误差却是最大的。

岭回归

岭回归最先用来处理特征数多于样本数的情况,现在也用于在估计中加入偏差,从而得到更好的估计

def ridgeRegres(xMat, yMat, lam=0.2):
	xTx = xMat.T*xMat
	denom = xTx + np.eye(np.shape(xMat)[1]) * lam
	if np.linalg.det(denom) == 0.0:
		print("This matrix is singular, cannot do inverse")
		return
	ws = denom.T * (xMat.T * yMat)
	return ws

def rigdeTest(xArr, yArr):
	xMat = np.mat(xArr)
	yMat = np.mat(yArr).T
	yMean = np.mean(yMat, 0)
	yMat = yMat - yMean
	xMeans = np.mean(xMat, 0)
	xVar = np.var(xMat, 0)
	xMat = (xMat - xMeans)/xVar
	numTestPts = 30
	wMat = np.zeros((numTestPts, np.shape(xMat)[1]))
	for i in range(numTestPts):
		ws = ridgeRegres(xMat, yMat, np.exp(i-10))
		wMat[i, :] = ws.T
	return wMat

前向逐步回归

前向逐步回归属于贪心算法,即每一步都尽可能减少误差。一开始,所有权重都设为1,然后每一步所做的决策是对某个权重增加或减少一个很小的值。

def regularize(xMat):
	inMat = xMat.copy()
	inMeans = np.mean(inMat, 0)
	inVar = np.var(inMat, 0)
	inMat = (inMat - inMeans)/inVar
	return inMat

def stageWise(xArr, yArr, eps=0.01, numIt=100):
	xMat = np.mat(xArr)
	yMat = np.mat(yArr).T
	yMean = np.mean(yMat, 0)
	yMat = yMat - yMean
	xMat = regularize(xMat)
	m, n = np.shape(xMat)
	returnMat = np.zeros((numIt, n))
	ws = np.zeros((n, 1))
	wsTest = ws.copy()
	wsMax = ws.copy()
	for i in range(numIt):
		print(ws.T)
		lowestError = np.inf
		for j in range(n):
			for sign in [-1, 1]:
				wsTest = ws.copy()
				wsTest[j] += eps*sign
				yTest = xMat * wsTest
				rssE = rssError(yMat.A, yTest.A)
				if rssE < lowestError:
					lowestError = rssE
					wsMax = wsTest
		ws = wsMax.copy()
		returnMat[i, :] = ws.T
	return returnMat


改变步长和步数

stageWise(abX, abY, 0.001, 5000)

逐步线性回归算法的主要优点是可以帮助人们理解现有的模型并做出改进。当构建了一个模型后,可以运行该算法找出重要的特征,这样就可以及时停止对那些不重要特征的收集。如果用于测试,该算法每100次迭代后就可以构建出一个模型,可以使用类似于10折交叉验证的方法比较这些模型,最终选择使误差最小的模型。


转载:https://blog.csdn.net/Deep___Learning/article/details/105718103
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场