我想在这些简单的数据上实现梯度下降算法,但遇到了问题。如果有人能指引我正确的方向就太好了。答案应该是当x=6时得到7,但我没有得到这个结果。
X = [1, 2, 3, 4]Y = [2, 3, 4, 5]m_gradient = 0b_gradient = 0m, b = 0, 0learning_rate = 0.1N = len(Y)for p in range(100): for idx in range(len(Y)): x = X[idx] y = Y[idx] hyp = (m * x) + b m_gradient += -(2/N) * x * (y - hyp) b_gradient += -(2/N) * (y - hyp) m = m - (m_gradient * learning_rate) b = b - (b_gradient * learning_rate)print(b+m*6)
回答:
看起来你想用梯度下降法来获取线性回归的系数。增加更多的数据点,稍微降低学习率,通过观察损失函数来进行更多的训练周期,这些都有助于减少误差。
当输入规模变大时,下面的代码会产生略有偏差的结果。上述提到的方法,比如增加训练周期,会在更大范围的数字上给出正确的结果。
向量化版本
import numpy as npX = np.array([1, 2, 3, 4, 5, 6, 7])Y = np.array([2, 3, 4, 5, 6, 7, 8])w_gradient = 0b_gradient = 0w, b = 0.5, 0.5learning_rate = .01loss = 0EPOCHS = 2000N = len(Y)for i in range(EPOCHS): # 预测 Y_pred = (w * X) + b # 损失 loss = np.square(Y_pred - Y).sum() / (2.0 * N) if i % 100 == 0: print(loss) # 反向传播 grad_y_pred = (2 / N) * (Y_pred - Y) w_gradient = (grad_y_pred * X).sum() b_gradient = (grad_y_pred).sum() # 优化 w -= (w_gradient * learning_rate) b -= (b_gradient * learning_rate)print("\n\n")print("LEARNED:")print(w, b)print("\n")print("TEST:")print(np.round(b + w * (-2)))print(np.round(b + w * 0))print(np.round(b + w * 1))print(np.round(b + w * 6))print(np.round(b + w * 3000))# 预期: 30001,但得到30002。# 训练3000个周期将得到预期结果。# 对于简单演示,较少的训练数据和较小的输入范围,2000个周期已经足够print(np.round(b + w * 30000))
输出
LEARNED:1.0000349103409163 0.9998271260509328TEST:-1.01.02.07.03001.030002.0
循环版本
import numpy as npX = np.array([1, 2, 3, 4, 5, 6, 7])Y = np.array([2, 3, 4, 5, 6, 7, 8])w_gradient = 0b_gradient = 0w, b = 0.5, 0.5learning_rate = .01loss = 0EPOCHS = 2000N = len(Y)for i in range(EPOCHS): w_gradient = 0 b_gradient = 0 loss = 0 for j in range(N): # 预测 Y_pred = (w * X[j]) + b # 损失 loss += np.square(Y_pred - Y[j]) / (2.0 * N) # 反向传播 grad_y_pred = (2 / N) * (Y_pred - Y[j]) w_gradient += (grad_y_pred * X[j]) b_gradient += (grad_y_pred) # 优化 w -= (w_gradient * learning_rate) b -= (b_gradient * learning_rate) # 打印损失 if i % 100 == 0: print(loss)print("\n\n")print("LEARNED:")print(w, b)print("\n")print("TEST:")print(np.round(b + w * (-2)))print(np.round(b + w * 0))print(np.round(b + w * 1))print(np.round(b + w * 6))print(np.round(b + w * 3000))# 预期: 30001,但得到30002。# 训练3000个周期将得到预期结果。# 对于简单演示,较少的训练数据和较小的输入范围,2000个周期已经足够print(np.round(b + w * 30000))
输出
LEARNED:1.0000349103409163 0.9998271260509328TEST:-1.01.02.07.03001.030002.0