环境搭建
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())