实现岭回归:选择用于智能电网


17

我正在Python / C模块中实现Ridge回归,并且遇到了这个“小”问题。我的想法是,我想或多或少地等距采样有效自由度(例如“统计学习的要素”上第65页的图),即样本:

df(λ)=i=1pdi2di2+λ,
di2XTXdf(λmax)0df(λmin)=pλmax=ipdi2/cλmaxdi2cc=0.1λmin=0

如标题所示,那么,我需要以一定比例从到采样,以便(大概)对进行采样,例如从到间隔为 ...有没有简单的方法可以做到这一点?我曾想过使用牛顿-拉夫森方法为每个解方程,但这会增加过多的迭代,特别是当大时。有什么建议么?λλminλmaxdf(λ)0.1cpdf(λ)λp


1
此函数是一个递减凸有理函数λ0。根,尤其是在二元网格上选择时,应该很快找到。
主教

@cardinal,您可能是对的。但是,如果可能的话,我想知道是否有一些“默认”网格。例如,我试图通过执行获得网格λ=log(s)λmax/log(smax),其中,s=(1,2,...,smax),并且在一定程度的自由度下效果很好,但是作为df(λ)p,它熄灭了。这让我想知道,也许有某种整齐的方法为选择网格λ,这就是我要的。如果不存在,我也将很高兴知道(因为我知道“没有更好的方法存在”,因此可以很高兴地在代码中留下了Newton-Rapson方法)。
内斯托尔·

为了更好地了解您遇到的潜在困难,典型值和最坏情况是p什么?您关于特征值分布的先验知识吗?
主教

@cardinal,我的应用程序中典型值范围是1540,但我想使其尽可能通用。关于特征值分布,确实不多。X是在其列中包含预测变量的矩阵,这些预测变量并不总是正交的。p1540X
内斯托尔·

1
牛顿-拉夫逊通常发现根内的精度34步骤p = 40和小值d ˚F λ ; 几乎不会超过6个步骤。对于较大的值,有时最多需要30步。由于每个步骤都需要O p 计算,因此计算的总量是无关紧要的。确实,如果选择了一个好的起始值,步数似乎并不取决于p(我选择了所有d i时将使用的步数)。10-1234p=40dFλ630Øppd一世等于他们的平均值)。
ub

Answers:


19

这是一个很长的答案。因此,让我们在这里给出一个简短的版本。

  • 对于这个寻根问题,没有很好的代数解决方案,因此我们需要一个数值算法。
  • 函数具有许多不错的性质。我们可以利用它们为该问题创建牛顿方法的专门版本,并保证每个根的单调收敛。df(λ)
  • 即使R没有进行任何优化尝试的脑残代码也可以计算p = 100的大小为100的网格在几秒钟内达到 000。精心编写的代码至少可以减少2-3个数量级。p=100000C

为保证单调收敛,下面给出了两种方案。一个使用如下所示的边界,这似乎有时可以帮助保存一两个牛顿步。

示例和大小为100的自由度的统一网格。特征值是帕累托分布的,因此高度偏斜。下表列出了查找每个根的牛顿步骤数。p=100000

# Table of Newton iterations per root.
# Without using lower-bound check.
  1  3  4  5  6 
  1 28 65  5  1 
# Table with lower-bound check.
  1  2  3 
  1 14 85 

不会有此一封闭形式解,在一般情况,但也有很多结构当前可用于生产使用标准求根方法是非常有效和安全的解决方案。

在深入研究事物之前,让我们收集函数d fλ = p i = 1 d 2 i的一些性质和结果。

df(λ)=i=1pdi2di2+λ.

特性0λ的有理函数。(这是从定义显而易见。) 后果0:无一般代数解将存在用于找到根d ˚Fλ - ý = 0。这是因为存在度为p的等效多项式求根问题,因此,如果p不是非常小(即小于5),则不会存在一般解。因此,我们需要一种数值方法。dfλ
df(λ)y=0pp

属性1:函数是凸的和减小λ 0。(取导数。) 结果1(a):在这种情况下,牛顿的寻根算法将表现得非常好。让ÿ是所需的自由度,并且λ 0对应的根,即ÿ = d ˚Fλ 0。特别是,如果我们在开始时任何初始值λ 1 < λ 0(因此,d ˚Fλ 1dfλ0
yλ0y=df(λ0)λ1<λ0),则牛顿步迭代的序列 λ 1λ 2...将收敛单调的独特的解决方案 λ 0结果如图1(b) :此外,如果我们用开出 λ 1 > λ 0,则第一步骤将产生 λ 2λ 0df(λ1)>yλ1,λ2,λ0
λ1>λ0λ2λ0,从那里开始,它将根据先前的结果单调增加到解(请参见下面的警告)。直观地看,这最后的事实如下,因为如果我们开始到根权,衍生为“太”浅由于凸等第一牛顿步将带我们的地方,左侧是根。注意:由于d f通常为负λ凸,因此有充分的理由倾向于选择从所需根的左侧开始。否则,我们需要仔细检查牛顿步长是否未导致估计根的负值,这可能会使我们处于d f的非凸部分。 dfdfλdf
结果如图1(c) :一旦我们已经找到了根一些,然后从一些搜索根ÿ 2 < Ý 1,采用λ 1,使得d ˚Fλ 1= ÿ 1作为我们的初始猜测保证我们从第二个根的左边开始。因此,从那里开始,我们的收敛被保证是单调的。y1y2<y1λ1df(λ1)=y1

特性2:存在合理的界限以给出“安全”的起点。使用凸性参数和詹森不等式,我们有以下边界 结果2:这告诉我们,根 λ 0满足 d ˚Fλ 0= ÿ服从 1

p1+λpdi2df(λ)pidi2idi2+pλ.
λ0df(λ0)=y 因此,直到一个公共常数,我们将根都夹在d 2 i的谐波与算术平均值之间。
()11pidi2(pyy)λ0(1pidi2)(pyy).
di2

假设所有i的。如果不是这种情况,则结合相同保持通过考虑在正d 和更换p由正的数量d NB:由于d ˚F0 = p假设所有d > 0,则ÿ 0 p ],从那里边界总是非平凡(例如,下限是总是非负的)。di>0idipdidf(0)=pdi>0y(0,p]

这里是一个“典型”的例子的曲线图p = 400。我们已经为自由度叠加了一个大小为10的网格。这些是图中的水平线。垂直的绿线对应于)中的下限。df(λ)p=400()

Example dof plot with grid and bounds

一个算法和一些R代码示例

给定期望的自由度 in 0 p ]的网格时,一种非常有效的算法是按照降序对它们进行排序,然后使用前一个根作为该根的起点,依次找到每个根。我们可以通过检查每个根是否大于下一个根的下限来进一步优化,如果不是,则可以从下限开始下一个迭代。y1,yn(0,p]

这是中的一些示例代码R,未尝试对其进行优化。如下图所示,尽管R礼貌地说,尽管循环令人恐惧,可怕,极其缓慢,但它仍然相当快。

# Newton's step for finding solutions to regularization dof.

dof <- function(lambda, d) { sum(1/(1+lambda / (d[d>0])^2)) }
dof.prime <- function(lambda, d) { -sum(1/(d[d>0]+lambda / d[d>0])^2) }

newton.step <- function(lambda, y, d)
{ lambda - (dof(lambda,d)-y)/dof.prime(lambda,d) }

# Full Newton step; Finds the root of y = dof(lambda, d).
newton <- function(y, d, lambda = NA, tol=1e-10, smart.start=T)
{
    if( is.na(lambda) || smart.start )
        lambda <- max(ifelse(is.na(lambda),0,lambda), (sum(d>0)/y-1)/mean(1/(d[d>0])^2))
    iter <- 0
    yn   <- Inf
    while( abs(y-yn) > tol )
    {
        lambda <- max(0, newton.step(lambda, y, d)) # max = pedantically safe
        yn <- dof(lambda,d)
        iter = iter + 1
    }
    return(list(lambda=lambda, dof=y, iter=iter, err=abs(y-yn)))
}

di di2

newton.grid <- function(ygrid, d, lambda=NA, tol=1e-10, smart.start=TRUE)
{
    p <- sum(d>0)
    if( any(d < 0) || all(d==0) || any(ygrid > p) 
        || any(ygrid <= 0) || (!is.na(lambda) && lambda < 0) )
        stop("Don't try to fool me. That's not nice. Give me valid inputs, please.")
    ygrid <- sort(ygrid, decreasing=TRUE)
    out    <- data.frame()
    lambda <- NA
    for(y in ygrid)
    {
        out <- rbind(out, newton(y,d,lambda, smart.start=smart.start))
        lambda <- out$lambda[nrow(out)]
    }
    out
}

样本函数调用

set.seed(17)
p <- 100000
d <- sqrt(sort(exp(rexp(p, 10)),decr=T))
ygrid <- p*(1:100)/100
# Should take ten seconds or so.
out <- newton.grid(ygrid,d)

提出这个问题后,我可以再参考此答案。非常感谢您发布此详细分析。
2012年

了不起的答案:-),非常感谢枢机主教的建议和答案。
内斯托尔·

1

此外,还有几种方法可以有效地计算出完整的正则化路径:

  1. 全球定位系统
  2. 全球网
  3. 网络

上面是所有R软件包,因为您使用的是Python,所以scikit-learn包含ridge,套索和弹性网的实现。


1
olsR rms包中的函数可以使用数值优化来使用有效的AIC找到最佳惩罚。但是您必须提供最大的惩罚,但这并不总是那么容易。
弗兰克·哈雷尔

0

根据以下来源,可能的替代方法似乎是:

封闭式解决方案: dFλ=Ť[RXXX+λ一世p-1个X

如果您使用正态方程作为求解器或计算方差-协方差估计,则您应该已经计算了 XX+λ一世p-1个。如果您要估算各个参数的系数,则此方法最有效λ

资料来源:https : //onlinecourses.science.psu.edu/stat857/node/155

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.