梯度下降算法不会收敛

时间:2011-10-16 08:45:01

标签: c++ machine-learning linear-regression

我正在尝试为斯坦福机器学习讲座(lecture 2 at around 25:00)中解释的梯度下降算法编写一些代码。下面是我最初使用的实现,我认为它已经从讲座中正确复制了,但是当我向训练集添加大数字(>8)时,它并没有收敛。

我正在输入一个X号码,point (X,X)已添加到训练集中,所以此刻,我只是想让它收敛到y=ax+b其中a=1=theta\[1\]b=0=theta\[0\]。 训练集是数组xy,其中(x[i],y[i])是一个点。

void train()
{
    double delta;
    for (int i = 0; i < x.size(); i++)
    {
        delta = y[i]-hypothesis(x[i]);
        theta[1] += alpha*delta*x[i];
        theta[0] += alpha*delta*1;
    }
}

void C_Approx::display()
{
    std::cout<<theta[1]<<"x + "<<theta[0]<<" \t "<<"f(x)="<<hypothesis(1)<<std::endl;
}

我得到的一些结果: 我输入一个数字,它运行train()几次,然后display()

1
0.33616x + 0.33616   f(x)=0.67232
1
0.482408x + 0.482408     f(x)=0.964816
1
0.499381x + 0.499381     f(x)=0.998762
1
0.499993x + 0.499993     f(x)=0.999986
1
0.5x + 0.5   f(x)=1

它通过8之后发生分歧的一个例子:

1
0.33616x + 0.33616   f(x)=0.67232
2
0.705508x + 0.509914     f(x)=1.21542
3
0.850024x + 0.449928     f(x)=1.29995
4
0.936062x + 0.330346     f(x)=1.26641
5
0.951346x + 0.231295     f(x)=1.18264
6
0.992876x + 0.137739     f(x)=1.13062
7
0.932206x + 0.127372     f(x)=1.05958
8
1.00077x + 0.000493063   f(x)=1.00126
9
-0.689325x + -0.0714712      f(x)=-0.760797
10
4.10321e+08x + 4.365e+07     f(x)=4.53971e+08
11
1.79968e+22x + 1.61125e+21   f(x)=1.9608e+22
12
-3.9452e+41x + -3.26957e+40      f(x)=-4.27216e+41

我尝试了解决该步骤的here提出的解决方案,最终获得了类似的结果。 我做错了什么?

6 个答案:

答案 0 :(得分:9)

您的实施很好。通常,当α太大时,随机梯度下降可能会发散。您对大型数据集的处理方法是采用合理大小的随机样本,找到能够获得最佳结果的α,然后将其用于其他样本。

答案 1 :(得分:3)

我遇到了同样的问题(尽管是在Java中)因为我的学习率太大了 简而言之,我使用的是α = 0.001,我不得不将其推到0.000001以查看实际收敛情况
当然,这些值与您的数据集相关联。

答案 2 :(得分:1)

当您的成本函数增加或上下循环时,alpha的值通常太大。您使用的是哪个alpha

alpha = 0.001开始,看看是否会收敛?如果没有尝试各种alphas (0.003, 0.01, 0.03, 0.1, 0.3, 1)并找到一个快速收敛的。

缩放数据(规范化)无法帮助您只使用1个功能(theta[1]),因为规范化仅适用于2+功能(多元线性回归)。

另请注意,对于少数功能,您可以使用法线公式来获得正确的答案。

答案 3 :(得分:1)

使用回溯线搜索来保证收敛。实现起来非常简单。有关参考,请参阅Convex Optimization的Stephen Boyd。您可以为回溯线搜索选择一些标准alpha,beta值,例如0.3和0.8。

答案 4 :(得分:0)

如果我理解正确,你的训练集只在一条线的边缘有一个非零梯度?除非你从该线开始(实际上从你的一个训练点开始),否则你将找不到该线。你总是在当地最低限度。

答案 5 :(得分:0)

您的描述并不清楚您正在解决的问题。 发布到外部资源的链接也非常危险 - 您可以在stackoverflow中阻止。

在任何情况下 - 具有固定步长的渐变下降方法和(子梯度下降)(ML社区称其为学习率)不应该是必要的收敛。

P.S。 机器学习社区在收敛条件&#34;中并不感兴趣。并且&#34;收敛到什么&#34; - 他们有兴趣创造&#34;某事&#34;它通过了交叉验证,效果很好。

如果您对优化感到好奇 - 请继续查看凸优化。不幸的是,它很难找到工作,但它会在各种数学优化的事情中附加清晰的视觉。

这是源代码,它演示了简单的二次目标:

#!/usr/bin/env python
# Gradiend descend method (without stepping) is not converged for convex         
# objective

alpha = 0.1

#k = 10.0 # jumping around minimum
k = 20.0   # diverge
#k = 0.001  # algorithm converged but gap to the optimal is big

def f(x): return k*x*x
def g(x): return 2*k*x

x0 = 12
xNext = x0
i = 0
threshold = 0.01

while True:
    i += 1
    xNext = xNext + alpha*(-1)*(g(xNext))
    obj = (xNext)
    print "Iteration: %i, Iterate: %f, Objective: %f, Optimality Gap: %f" % (i, xNext, obj, obj - f(0.0))

    if (abs(g(xNext)) < threshold):
        break
    if i > 50:
        break

print "\nYou launched application with x0=%f,threshold=%f" % (x0, threshold)