第1关:岭回归
任务描述
本关任务:编写一个能计算数组平均值和最大值的小程序。
相关知识
为了完成本关任务,你需要掌握:1.什么是岭回归,2.岭回归核心算法,3.lasso缩减。
什么是岭回归
岭回归最先用来处理特征数多于样本数的情况,现在也用于在估计中加人偏差,从而得到更好的估计。这里通过引入1来限制了所有《之和,通过引人该惩罚项,能够减少不重要的参数,这个技术在统计学中也叫做缩减(shrinkage )。 缩减方法可以去掉不重要的参数,因此能更好地理解数据。此外,与简单的线性回归相比,缩减法能取得更好的预测效果。
岭回归核心算法
lasso缩减
不难证明,在增加如下约束时,普通的最小二乘法回归会得到与岭回归的一样的公式:
上式限定了所有回归系数的平方和不能大于
。使用普通的最小二乘法回归在当两个或更多的特征相关时,可能会得出一个很大的正系数和一个很大的负系数。正是因为上述限制条件的存在,使用岭回归可以避免这个问题。 与岭回归类似,另一个缩减方法lasso也对回归系数做了限定,对应的约束条件如下:
唯一的不同点在于,这个约束条件使用绝对值取代了平方和。虽然约束形式只是稍作变化,结果却大相径庭:在
足够小的时候,一些系数会因此被迫缩减到0,这个特性可以帮助我们更好 地理解数据。这两个约束条件在公式上看起来相差无几,但细微的变化却极大地增加了计算复杂度(为了在这个新的约束条件下解出回归系数,需要使用二次规划算法)。
编程要求
根据提示,在右侧编辑器补充代码,绘制岭回归系数矩阵。
测试说明
根据所学完成右侧编程题。
from matplotlib.font_manager import FontProperties
import matplotlib.pyplot as plt
import numpy as np
# 加载数据
def loadDataSet(fileName):
"""
Parameters:
fileName - 文件名
Returns:
xArr - x数据集
yArr - y数据集
"""
numFeat = len(open(fileName).readline().split('\t')) - 1
xArr = [];
yArr = []
fr = open(fileName)
for line in fr.readlines():
lineArr = []
curLine = line.strip().split('\t')
for i in range(numFeat):
lineArr.append(float(curLine[i]))
xArr.append(lineArr)
yArr.append(float(curLine[-1]))
return xArr, yArr
# 数据标准化
def regularize(xMat, yMat):
"""
Parameters:
xMat - x数据集
yMat - y数据集
Returns:
inxMat - 标准化后的x数据集
inyMat - 标准化后的y数据集
"""
inxMat = xMat.copy() # 数据拷贝
inyMat = yMat.copy()
yMean = np.mean(yMat, 0) # 行与行操作,求均值
inyMat = yMat - yMean # 数据减去均值
inMeans = np.mean(inxMat, 0) # 行与行操作,求均值
inVar = np.var(inxMat, 0) # 行与行操作,求方差
inxMat = (inxMat - inMeans) / inVar # 数据减去均值除以方差实现标准化
return inxMat, inyMat
# 计算平方误差
def rssError(yArr, yHatArr):
"""
Parameters:
yArr - 预测值
yHatArr - 真实值
Returns:
"""
return ((yArr - yHatArr) ** 2).sum()
# 前向逐步线性回归
def stageWise(xArr, yArr, eps=0.01, numIt=100):
"""
Parameters:
xArr - x输入数据
yArr - y预测数据
eps - 每次迭代需要调整的步长
numIt - 迭代次数
Returns:
returnMat - numIt次迭代的回归系数矩阵
"""
xMat = np.mat(xArr);
yMat = np.mat(yArr).T # 数据集
xMat, yMat = regularize(xMat, yMat) # 数据标准化
m, n = np.shape(xMat)
returnMat = np.zeros((numIt, n)) # 初始化numIt次迭代的回归系数矩阵
ws = np.zeros((n, 1)) # 初始化回归系数矩阵
wsTest = ws.copy()
wsMax = ws.copy()
for i in range(numIt): # 迭代numIt次
# print(ws.T) #打印当前回归系数矩阵
lowestError = float('inf'); # 正无穷
for j in range(n): # 遍历每个特征的回归系数
for sign in [-1, 1]:
###########
请在此处填写代码
##########
ws = wsMax.copy()
returnMat[i, :] = ws.T # 记录numIt次迭代的回归系数矩阵
return returnMat
第2关:前向逐步线性回归
任务描述
本关任务:根据前向逐步线性回归方法编写一个绘制岭回归系数矩阵的程序。
相关知识
为了完成本关任务,你需要掌握:1.向前逐步回归的思想,2.前向逐步线性回归的核心算法,3.逐步线性回归算法的好处。
向前逐步回归的思想
前向逐步回归算法可以得到与lasso差不多的效果,但更加简单。它属于一种贪心算法,即每一步都尽可能减少误差。一开始,所有的权重都设为1,然后每一步所做的决策是对某个权重增加或减少一个很小的值。
该算法的伪代码如下所示: 数据标准化,使其分布满足0均值和单位方差 在每轮迭代过程中: 设置当前最小误差lowestError为正无穷 对每个特征: 增大或缩小: 改变一个系数得到一个新的w 计算新w下的误差 如果误差Error小于当前最小误差lowestError:设置Wbest等于当前的w 将w设置为新的Wbest
前向逐步线性回归的核心算法
向前逐步线性回归算法的好处
逐步线性回归算法的实际好处并不在于能绘出漂亮的图,主要的优点在于它可以帮助人们理解现有的模型并做出改进。当构建了一个模型后,可以运行该算法找出重要的特征,这样就有可能及时停止对那些不重要特征的收集。最后,如果用于测试,该算法每100次迭代后就可以构建出一个模型,可以使用类似于10折交叉验证的方法比较这些模型,最终选择使误差最小的模型。 当应用缩减方法(如逐步线性回归或岭回归) 时 ,模型也就增加了偏差(bias),与此同时却减小了模型的方差。
编程要求
根据提示,在右侧编辑器补充代码,绘制岭回归系数矩阵的程序。
测试说明
根据所学,完成右侧编程题。
from matplotlib.font_manager import FontProperties
import matplotlib.pyplot as plt
import numpy as np
# 加载数据
def loadDataSet(fileName):
"""
Parameters:
fileName - 文件名
Returns:
xArr - x数据集
yArr - y数据集
"""
numFeat = len(open(fileName).readline().split('\t')) - 1
xArr = []; yArr = []
fr = open(fileName)
for line in fr.readlines():
lineArr =[]
curLine = line.strip().split('\t')
for i in range(numFeat):
lineArr.append(float(curLine[i]))
xArr.append(lineArr)
yArr.append(float(curLine[-1]))
return xArr, yArr
# 岭回归
def ridgeRegres(xMat, yMat, lam = 0.2):
"""
Parameters:
xMat - x数据集
yMat - y数据集
lam - 缩减系数
Returns:
ws - 回归系数
"""
##########
xTx = xMat.T*xMat
denom = xTx + eye(shape(xMat)[1])*lam
if linalg.det(denmo) == 0.0:
print("This matrix is singular, cannot do inverse")
return
##########
ws = denom.I * (xMat.T * yMat)
return ws
# 岭回归测试
def ridgeTest(xArr, yArr):
"""
Parameters:
xMat - x数据集
yMat - y数据集
Returns:
wMat - 回归系数矩阵
"""
xMat = np.mat(xArr); yMat = np.mat(yArr).T
#数据标准化
yMean = np.mean(yMat, axis = 0) #行与行操作,求均值
yMat = yMat - yMean #数据减去均值
xMeans = np.mean(xMat, axis = 0) #行与行操作,求均值
xVar = np.var(xMat, axis = 0) #行与行操作,求方差
xMat = (xMat - xMeans) / xVar #数据减去均值除以方差实现标准化
numTestPts = 30 #30个不同的lambda测试
wMat = np.zeros((numTestPts, np.shape(xMat)[1])) #初始回归系数矩阵
for i in range(numTestPts): #改变lambda计算回归系数
ws = ridgeRegres(xMat, yMat, np.exp(i - 10)) #lambda以e的指数变化,最初是一个非常小的数,
wMat[i, :] = ws.T #计算回归系数矩阵
return wMat