梯度下降算法代码如下:(增加绘图代码)
import matplotlib.pyplot as plt
x_data = [1.0, 2.0, 3.0]
y_data = [2.0, 4.0, 6.0]
w = 1.0 # 设置初始权重
def forward(x): # 定义前馈函数
return x * w
def cost(xs, ys): # 定义损失函数
cost = 0
for x, y in zip(xs, ys):
y_pred = forward(x) # 计算预测的y值
cost += (y_pred - y) ** 2 # 计算损失函数
return cost / len(xs) # 计算平均损失
def gradient(xs, ys): # 定义梯度函数
grad = 0
for x, y in zip(xs, ys):
grad += 2 * x * (x * w - y) # 对损失函数求导得到梯度,针对x和y取不同值有一个累加过程
return grad / len(xs)
epoch_list = []
cost_list = []
print('Predict (before training)', 4, forward(4))
for epoch in range(100):
cost_val = cost(x_data, y_data)
grad_val = gradient(x_data, y_data)
w -= 0.01 * grad_val # 0.01是学习率,通过这个核心算式进行迭代
print('Epoch:', epoch, 'w=', w, 'cost=', cost_val)
epoch_list.append(epoch)
cost_list.append(cost_val)
print('Predict (after training)', 4, forward(4)) # 对x=4时y的值进行预测
plt.plot(epoch_list, cost_list)
plt.ylabel('cost')
plt.xlabel('epoch')
plt.show()
随机梯度下降代码如下:
import matplotlib.pyplot as plt
x_data = [1.0, 2.0, 3.0]
y_data = [2.0, 4.0, 6.0]
w = 1.0 # 设置初始权重
def forward(x): # 定义前馈函数
return x * w
def loss(x, y): # 定义损失函数,此时不需要将x和y取所有值,故不需要循环,只需要随机取一个x和y即可
y_pred = forward(x)
return (y_pred-y)**2 # 此时不是平均损失,只是随机损失
def gradient(x, y): # 定义梯度函数
return 2*x*(x*w-y) # 此时也不是平均梯度,只是随机梯度
epoch_list = []
loss_list = []
print('Predict (before training)', 4, forward(4))
for epoch in range(100):
for x, y in zip(x_data, y_data): # x和y在范围中取值(数据多的话应该要体现随机性,现在数据太少),此处并未体现出随机,而是把每一对
l = loss(x, y) # x和y的值都取到了,此处的x和y并不是自由搭配,而是一一对应关系
grad = gradient(x, y)
w = w-0.01*grad # 核心算式,此步骤计算最后要输出的w
print("\t grad:", x, y, grad, w, l)
epoch_list.append(epoch) # 这两个语句只能放在epoch的循环中,而不能放在x,y的循环中因为若放在x,y的循环中,则epoch的值不变时,
loss_list.append(l) # l的值却在不断变化,在图像上形成很多竖直线
print("progress:", epoch, "w=", w, "loss=", l) # 此时的l和w会固定取最后一次循环中的l和w,相当于固定x=3,y=6,并不随机
plt.plot(epoch_list, loss_list)
plt.ylabel('loss')
plt.xlabel('epoch')
plt.show()
随机梯度下降法相对于梯度下降法的改进在于,不再取所有x、y值计算出的损失函数的平均值,而是随机取一组x和y计算损失函数。此方法的作用在于:数据中大多含有随机噪声,则利用这种随机噪声避免鞍点时无法继续迭代的情况。
但是此代码并不严格遵循此思想,此代码并没有体现随机性,利用zip函数把每一对x和y值都计算了一次(若是输入数据很多则计算量极大),此外,计算出的l和w每次都利用x和y循环中最后一次的结果,即固定取x=3,y=6,与随机性没有任何关系,同时造成前两对x和y值的计算完全无效,属于浪费资源。