将随机梯度下降算法转换为标准梯度下降

时间:2020-06-04 19:18:50

标签: python numpy neural-network linear-algebra gradient-descent

我使用NumPy线性代数编写了一小组方法来执行梯度下降。按照我的设计方式,如果在数据集中的点上update函数被迭代调用,它应该执行随机梯度下降;如果在整个数据集中被调用一次,则它应该执行标准梯度下降。

我正在尝试在Udacity的PyTorch类的第2课中转换笔记本,该类使用简单的嵌套循环执行随机梯度下降。

Udacity笔记本为found here。对于缺少的代码,建议的解决方法是found here

我使用线性代数的替代解决方案是:

def sigmoid(X): 
    return 1 / (1 + np.exp(-X))

def probability(X, weights, bias):
    return sigmoid(np.dot(X, weights) + bias)

def cross_entropy_ave(y, y_hat):
    return (-y * np.log(y_hat) - (1 - y) * np.log(1 - y_hat)).mean()

# get average gradient of cross entropy loss at all data points in X
def d_Error(X, y, weights, bias):
    y_hat = probability(X, weights, bias)
    dE_matrix =  (X.T * (y - y_hat)).T  # each row is the loss of that sample
    dEdw = np.atleast_2d(dE_matrix).mean(axis=0)
    dEdb = (y - y_hat).mean() # gives scalar
    dEdz = np.append(dEdw, dEdb)
    return dEdz

def update(X, y, weights, bias, lr):
    dEdz = d_Error(X, y, weights, bias)
    dEdw = dEdz[:-1]
    dEdb = dEdz[-1]
    weights += lr * dEdw
    bias += lr * dEdb
    return weights, bias

# implementing gradient descent:
def train(X, y, learn_rate, epochs, graph_lines=False):
    weights = np.random.normal(scale=1 / n_features**.5, size=n_features)
    bias = 0

    for e in range(epochs):
         for x, y_i in zip(X, y):
             weights, bias = update(X, y_i, weights, bias, learn_rate)

问题: 现在,如果我按样本计算梯度样本,那么我的解决方案效果很好,就像上面的代码一样,并且可以在链接的建议解决方案中找到。在样本数据集上,与建议的解决方案一样,我在100个纪元内达到了94%的准确性。

但是,我的目标是使用以下方法替换上面的train方法:

    for e in range(epochs):
        weights, bias = update(X, y, weights, bias, learn_rate)

这就是说,我使用整个数据集的平均梯度每个时期更新一次权重和偏差。有人告诉我,这在理论上应产生至少与随机梯度下降一样好的结果。但是我发现这是不正确的。对于相同的时期数和相同的学习率,我的结果令人震惊。

我的问题:我想知道我是否误解了标准梯度下降的工作原理,或者我的线性代数代码中是否有错误?

编辑:我发现,将学习速度和时代数提高一个数量级,可以给我带来很好的效果。这正常吗?

0 个答案:

没有答案