闭式岭回归
Closed Form Ridge Regression
我无法理解实现多脊回归的函数的输出。对于该方法的封闭形式,我在 Python 中从头开始执行此操作。此封闭形式如下所示:
我有一个训练集 X
即 100 rows x 10 columns
和一个向量 y
即 100x1
.
我的尝试如下:
def ridgeRegression(xMatrix, yVector, lambdaRange):
wList = []
for i in range(1, lambdaRange+1):
lambVal = i
# compute the inner values (X.T X + lambda I)
xTranspose = np.transpose(x)
xTx = xTranspose @ x
lamb_I = lambVal * np.eye(xTx.shape[0])
# invert inner, e.g. (inner)**(-1)
inner_matInv = np.linalg.inv(xTx + lamb_I)
# compute outer (X.T y)
outer_xTy = np.dot(xTranspose, y)
# multiply together
w = inner_matInv @ outer_xTy
wList.append(w)
print(wList)
为了测试,我 运行 它具有前 5 个 lambda 值。
wList
变为 5 numpy.arrays
,每个长度为 10(我假设有 10 个系数)。
这是这 5 个数组中的第一个:
array([ 0.29686755, 1.48420319, 0.36388528, 0.70324668, -0.51604451,
2.39045735, 1.45295857, 2.21437745, 0.98222546, 0.86124358])
我的问题和说明:
不应该有 11 个系数,(1 个用于 y 轴截距 + 10 个斜率)?
我如何从这个计算中得到 Minimum Square Error
?
如果我想绘制这条线,接下来会发生什么?
我想我对我正在看的东西真的很困惑,因为我还在研究我的线性代数。
谢谢!
通常为了使符号更紧凑,矩阵 X
包含一列用于截距的 1,因此如果您有 p
个预测变量,则矩阵的维度为 n
通过 p+1
。有关示例,请参见 Wikipedia article on linear regression。
要计算样本内 MSE,请使用 MSE 的定义:残差平方的平均值。要计算泛化误差,您需要交叉验证。
首先,我会将您的岭回归修改为如下所示:
import numpy as np
def ridgeRegression(X, y, lambdaRange):
wList = []
# Get normal form of `X`
A = X.T @ X
# Get Identity matrix
I = np.eye(A.shape[0])
# Get right hand side
c = X.T @ y
for lambVal in range(1, lambdaRange+1):
# Set up equations Bw = c
lamb_I = lambVal * I
B = A + lamb_I
# Solve for w
w = np.linalg.solve(B,c)
wList.append(w)
return wList
请注意,我用隐式求解替换了您的 inv
计算矩阵求逆的调用。这在数值上更加稳定,尤其是对于这些类型的问题而言,这是一个重要的考虑因素。
我还采用了 A=X.T@X
计算、单位矩阵 I
生成和右侧向量 c=X.T@y
计算脱离循环——这些在循环中不会改变循环并且计算起来相对昂贵。
正如@qwr 指出的那样,X
的列数将决定您拥有的系数数。您还没有描述您的模型,因此不清楚基础域 x
是如何构造成 X
的。
传统上,人们可能会使用多项式回归,在这种情况下 X
就是 Vandermonde Matrix。在这种情况下,第一个系数将与 y 截距相关联。但是,根据您问题的上下文,您似乎对多元线性回归感兴趣。无论如何,都需要明确定义模型。完成后,返回的权重可用于进一步分析您的数据。
此外,您不应将 lambVal
视为整数。如果目的只是为了在 xTx
条件不佳时避免数值错误,它可以很小(接近 0)。
我建议您使用对数范围而不是线性范围,从 0.001 开始,如果您愿意,可以增加到 100 或更多。例如,您可以将代码更改为:
powerMin = -3
powerMax = 3
for i in range(powerMin, powerMax):
lambVal = 10**i
print(lambVal)
然后,一旦您从交叉验证中找出 lambVal
的正确顺序是什么,您就可以尝试更小的范围或线性范围。
我无法理解实现多脊回归的函数的输出。对于该方法的封闭形式,我在 Python 中从头开始执行此操作。此封闭形式如下所示:
我有一个训练集 X
即 100 rows x 10 columns
和一个向量 y
即 100x1
.
我的尝试如下:
def ridgeRegression(xMatrix, yVector, lambdaRange):
wList = []
for i in range(1, lambdaRange+1):
lambVal = i
# compute the inner values (X.T X + lambda I)
xTranspose = np.transpose(x)
xTx = xTranspose @ x
lamb_I = lambVal * np.eye(xTx.shape[0])
# invert inner, e.g. (inner)**(-1)
inner_matInv = np.linalg.inv(xTx + lamb_I)
# compute outer (X.T y)
outer_xTy = np.dot(xTranspose, y)
# multiply together
w = inner_matInv @ outer_xTy
wList.append(w)
print(wList)
为了测试,我 运行 它具有前 5 个 lambda 值。
wList
变为 5 numpy.arrays
,每个长度为 10(我假设有 10 个系数)。
这是这 5 个数组中的第一个:
array([ 0.29686755, 1.48420319, 0.36388528, 0.70324668, -0.51604451,
2.39045735, 1.45295857, 2.21437745, 0.98222546, 0.86124358])
我的问题和说明:
不应该有 11 个系数,(1 个用于 y 轴截距 + 10 个斜率)?
我如何从这个计算中得到 Minimum Square Error
?
如果我想绘制这条线,接下来会发生什么?
我想我对我正在看的东西真的很困惑,因为我还在研究我的线性代数。
谢谢!
通常为了使符号更紧凑,矩阵
X
包含一列用于截距的 1,因此如果您有p
个预测变量,则矩阵的维度为n
通过p+1
。有关示例,请参见 Wikipedia article on linear regression。要计算样本内 MSE,请使用 MSE 的定义:残差平方的平均值。要计算泛化误差,您需要交叉验证。
首先,我会将您的岭回归修改为如下所示:
import numpy as np
def ridgeRegression(X, y, lambdaRange):
wList = []
# Get normal form of `X`
A = X.T @ X
# Get Identity matrix
I = np.eye(A.shape[0])
# Get right hand side
c = X.T @ y
for lambVal in range(1, lambdaRange+1):
# Set up equations Bw = c
lamb_I = lambVal * I
B = A + lamb_I
# Solve for w
w = np.linalg.solve(B,c)
wList.append(w)
return wList
请注意,我用隐式求解替换了您的 inv
计算矩阵求逆的调用。这在数值上更加稳定,尤其是对于这些类型的问题而言,这是一个重要的考虑因素。
我还采用了 A=X.T@X
计算、单位矩阵 I
生成和右侧向量 c=X.T@y
计算脱离循环——这些在循环中不会改变循环并且计算起来相对昂贵。
正如@qwr 指出的那样,X
的列数将决定您拥有的系数数。您还没有描述您的模型,因此不清楚基础域 x
是如何构造成 X
的。
传统上,人们可能会使用多项式回归,在这种情况下 X
就是 Vandermonde Matrix。在这种情况下,第一个系数将与 y 截距相关联。但是,根据您问题的上下文,您似乎对多元线性回归感兴趣。无论如何,都需要明确定义模型。完成后,返回的权重可用于进一步分析您的数据。
此外,您不应将 lambVal
视为整数。如果目的只是为了在 xTx
条件不佳时避免数值错误,它可以很小(接近 0)。
我建议您使用对数范围而不是线性范围,从 0.001 开始,如果您愿意,可以增加到 100 或更多。例如,您可以将代码更改为:
powerMin = -3
powerMax = 3
for i in range(powerMin, powerMax):
lambVal = 10**i
print(lambVal)
然后,一旦您从交叉验证中找出 lambVal
的正确顺序是什么,您就可以尝试更小的范围或线性范围。