我使用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)
这就是说,我使用整个数据集的平均梯度每个时期更新一次权重和偏差。有人告诉我,这在理论上应产生至少与随机梯度下降一样好的结果。但是我发现这是不正确的。对于相同的时期数和相同的学习率,我的结果令人震惊。
我的问题:我想知道我是否误解了标准梯度下降的工作原理,或者我的线性代数代码中是否有错误?
编辑:我发现,将学习速度和时代数提高一个数量级,可以给我带来很好的效果。这正常吗?