随机梯度下降收敛准则

时间:2015-03-23 23:32:10

标签: python linear-regression gradient-descent

目前我的SGD收敛标准检查MSE错误率是否在特定边界内。

def compute_mse(data, labels, weights):
    m = len(labels)
    hypothesis = np.dot(data,weights)
    sq_errors = (hypothesis - labels) ** 2
    mse = np.sum(sq_errors)/(2.0*m)
    return mse

cur_mse = 1.0
prev_mse = 100.0
m = len(labels)
while cur_mse/prev_mse < 0.99999:
    prev_mse = cur_mse

    for i in range(m):
        d = np.array(data[i])
        hypothesis = np.dot(d, weights)
        gradient = np.dot((labels[i] - hypothesis), d)/m
        weights = weights + (alpha * gradient)

    cur_mse = compute_mse(data, labels, weights)
    if cur_mse > prev_mse:
        return 

权重更新w.r.t.到训练集中的单个数据点。

使用0.001的alpha,模型应该在几次迭代中收敛但是我没有收敛。这种收敛标准是否过于严格?

1 个答案:

答案 0 :(得分:1)

我会尝试回答这个问题。首先,随机梯度下降的伪代码看起来像这样:

input: f(x), alpha, initial x (guess or random)
output: min_x f(x) # x that minimizes f(x)

while True:
    shuffle data # good practice, not completely needed
    for d in data:
        x -= alpha * grad(f(x)) # df/dx
    if <stopping criterion>:
        break

可以为要最小化的函数添加其他regularization个参数,例如l1 penalty以避免过度拟合。

回到你的问题,查看你的数据和梯度的定义,看起来你想解决一个简单的线性方程组形式:

Ax = b

产生了客观的功能:

f(x) = ||Ax - b||^2

随机梯度下降一次使用一行数据:

||A_i x - b||

其中|| o ||是欧几里德范数,_i表示行的索引。

此处Adataxweightsblabels

然后将函数的梯度计算为:

grad(f(x)) = 2 * A.T (Ax - b)

或者在随机梯度下降的情况下:

2 * A_i.T (A_i x - b)

其中.T表示转置​​。

将所有内容放回代码中......首先,我将设置合成数据:

A = np.random.randn(100, 2) # 100x2 data
x = np.random.randn(2, 1) # 2x1 weights
b = np.random.randint(0, 2, 100).reshape(100, 1) # 100x1 labels
b[b == 0] = -1 # labels in {-1, 1}

然后,定义参数:

alpha = 0.001
cur_mse = 100.
prev_mse = np.inf
it = 0
max_iter = 100
m = A.shape[0]
idx = range(m)

然后循环!

while cur_mse/prev_mse < 0.99999 and it < max_iter:
    prev_mse = cur_mse
    shuffle(idx)

    for i in idx:
        d = A[i:i+1]
        y = b[i:i+1]
        h = np.dot(d, x)
        dx = 2 * np.dot(d.T, (h - y))
        x -= (alpha * dx)

    cur_mse = np.mean((A.dot(x) - b)**2)
    if cur_mse > prev_mse:
        raise Exception("Not converging")
    it += 1

此代码几乎与您的代码相同,但增加了几个代码:

  • 基于迭代次数的另一个停止标准(如果系统不收敛或做得太慢,则避免永远循环)

  • 重新定义渐变dx(仍与您的相似)。您的符号已被反转,因此权重更新为正+,因为在我的示例中为负-(因为您在渐变中下降所以有意义)。

  • datalabels的索引编制。虽然data[i]提供了一个大小为(2,)的元组(在这种情况下为100x2数据),但使用花式索引data[i:i+1]将返回数据视图而不对其进行重新整理(例如具有形状(1, 2)),因此将允许您执行适当的矩阵乘法。

您可以根据可接受的mse错误添加第三个停止标准,即:if cur_mse < 1e-3: break

该算法具有随机数据,为我收敛20-40次迭代(取决于生成的随机数据)。

所以...假设这是你想要最小化的函数,如果这个方法对你不起作用,可能意味着你的系统未被确定(你的训练数据少于特征,这意味着{{1比...更宽广。)

希望它有所帮助!