ai

PYTORCH大法

学习之路

Posted by pic4xiu on September 20, 2021

环境搭建

Windows 端

有了 anaconda 使得我们的环境搭建变得十分简单,有两种方案,一种是使用 conda 的方式创建一个专门给 pytorch 的库,还可以直接在 pip 下全局安装 pytorch 。我使用的第二种,因为使用第一种每次要想使用 pytorch 的话还得重新使用 activate 的方式进入 pytorch。

跟着李沐大大的安装配置指南,光速完成

线性模型

import numpy as np
import matplotlib.pyplot as plt
x_data = [1.0, 2.0, 3.0]
y_data = [2.0, 4.0, 6.0]

def forward(x):
    return x*w
#线性关系

def loss(x, y):
#损失函数
    y_pred = forward(x)
    return (y_pred - y) * (y_pred - y)

w_list = []
mse_list = []

#遍历找w
for w in np.arange(0.0, 4.1, 0.1):
    print('w=', w)
    l_sum=0
    for x_val,y_val in zip(x_data,y_data):
        y_pred_val = forward(x_val)
        loss_val = loss(x_val,y_val)
        l_sum+=loss_val
        print('\t',x_val,y_val,y_pred_val,loss_val)
    print('MSE=',l_sum/3)
    w_list.append(w)
    mse_list.append(l_sum/3)

plt.plot(w_list,mse_list)
plt.ylabel('loss')
plt.xlabel('w')
plt.show()

这是一个十分简单的数学模型,参数 b 甚至考虑,当然可以加上,但是算出来肯定也是 0。

梯度下降算法

import numpy as np
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)
        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)
        return grad/len(xs)
epoch_list = []
cost_list = []
print('Predict(before traning)',4,forward(4))
#遍历找w
for epoch in range(500):
   cost_val=cost(x_data,y_data)
   grad_val=gradient(x_data,y_data)
   w-=0.01*grad_val
   print('Eopch:',epoch,'w=',w,'cost=',cost_val)
   epoch_list.append(epoch)
   cost_list.append(cost_val)
print('Predict(after traning)',4,forward(4))

plt.plot(epoch_list,cost_list)
plt.ylabel('cost_val')
plt.xlabel('epoch')
plt.show()

梯度下降算法,取了个均值平均损失,但是其实挺菜的,如果存在鞍点的话,这种下降方式所算的导数就为 0 了, w 无法迭代更新。这时候随机梯度下降就出现了。

import numpy as np
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(xs, ys):
    y_pred = forward(x)
    return (y_pred - y) ** 2

def gradient(xs, ys):
    return 2* x * (x * w - y)

epoch_list = []
loss_list = []
print('Predict(before traning)',4,forward(4))
#遍历找w
for epoch in range(50):
    for x, y in zip(x_data, y_data):
        grad=gradient(x,y)
        w-=0.01*grad
        print('\tgrad:',x,y,grad)
        l=loss(x,y)
        epoch_list.append(epoch)
        loss_list.append(l)
    print('progress:',epoch,'w=',w,'loss=',l)

print('Predict(after traning)',4,forward(4))

plt.plot(epoch_list,loss_list)
plt.ylabel('loss_list')
plt.xlabel('epoch')
plt.show()

这个迭代速度超级快,而且极其不平滑。这个算法优点就是能够通过部分噪点的小影响来度过一个鞍点。

反向传播

import torch
x_data = [1.0, 2.0, 3.0]
y_data = [2.0, 4.0, 6.0]

w=torch.Tensor([1.0])
w.requires_grad=True

def forward(x):
    return x*w
#线性关系

def loss(x, y):
    y_pred = forward(x)
    return (y_pred - y) ** 2

epoch_list = []
cost_list = []
print('Predict(before traning)',4,forward(4).item())
#遍历找w
for epoch in range(500):
    for x, y in zip(x_data, y_data):
        l=loss(x,y)
        l.backward()
        print('\tgrad:',x,y,w.grad.item())
        w.data=w.data-0.01*w.grad.data
        w.grad.data.zero_()
    print('progress:',epoch,l.item())
print('Predict(after traning)',4,forward(4).item())