PyTorch深度学习实践——梯度下降算法

梯度下降算法代码如下:(增加绘图代码)

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值的计算完全无效,属于浪费资源。

你可能感兴趣的:(PyTorch深度学习实践,pytorch,深度学习)