代码来源:B站up 刘二大人
1.线性模型:
实现功能:
使用线性模型 y=w*x拟合数据集。
从0.0到4.0挨个取权重w,拟合数据集。分别计算w在0.0到4.0时的损失值,这里使用的损失函数是均方误差。
代码:
import numpy as np
import matplotlib.pyplot as plt
x_data=[1.0,2.0,3.0] #dataSheet
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)**2
w_list=[] #为了画图使用,关于w和mse的图像
mse_list=[]
for w in np.arange(0.0, 4.1, 0.1): #np.arange() :从0,到4 的向量,步长为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()
知识点:就是简单的使用y = w * x这个模型,不断改变w这个参数,选择一个最符合数据集的模型。绘制的(w,mse)图可以看出,当w取2时损失为0,完美拟合数据集。
2.梯度下降
实现:
利用梯度下降算法更新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 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)
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
print('Epoch:',epoch,'w=',w,'loss=',cost_val)
print('Predict(after training)',4,forward(4))
知识点:梯度下降的权重更新公式-- 。从上面的代码可以看出,更新参数的时候与实际的loss值没有关系,知识和loss的公式有关系grad=2*x*(x*w-y)。
3.随机梯度下降:
实现功能:
上面的梯度下降算法是全部数据集计算完梯度后取平均再去更新w,SGD是一个样本计算完梯度后就去更新w。
代码:
# 随机梯度下降,
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):
y_pred = forward(x)
return (y_pred - y) ** 2
def gradient(x, y):
return 2 * x * (x * w - y)
print('predict (before training)', 4, forward(4))
for epoch in range(100):
for x, y in zip(x_data, y_data):
grad = gradient(x, y)
w -= 0.01 * grad # 及时更新,没办法并行运算,,batch
print('\tgrad:', x, y, grad)
l = loss(x, y)
print("progress:", epoch, "w=", w, "loss", l)
print('predict (after training)', 4, forward(4))
知识点:随机梯度下降(SGD)和上面的梯度下降的一个重要不同就是——SGD是一个样本进入网络后就更新一次w。这样加快了权重的收敛速度。
4.反向传播
实现功能:利用torch中的tensor自动更新权重w,不需要自己写梯度函数了。其中计算图的构建是在使用tensor计算时。在执行完loss.backward()后,释放计算图。
代码:
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 # tensor
def loss(x, y):
y_pred = forward(x)
return (y_pred - y) ** 2
print('predict (before training)', 4, forward(4).item())
for epoch in range(100):
for x, y in zip(x_data, y_data):
l = loss(x, y) # 前向,计算loss
l.backward() # 做完后计算图会释放
print('\tgrad:', x, y, w.grad.item()) # item取值,要是张量计算图一直累积
w.data -= 0.01 * w.grad.data # 不取data会是TENSOR有计算图
w.grad.data.zero_() # 计算出来的梯度不清零会累加
print("progress:", epoch, l.item())
print('predict (after training)', 4, forward(4).item())
知识点:反向传播——前向传播完成后,反向传播计算权重的梯度更新参数。代码中需要注意的是,计算图是在使用Tensor进行运算时构建,在执行完l.backward()后释放。在不需要构建计算图的地方构建了计算图不会报错,但是占据的内存会增加,直到内存爆了以后报错。
5. pytorch实现线性回归
实现:利用pytorch的损失函数和优化器更新参数和计算损失函数,构建了一个简单的y=wx+b的模型。
代码:
'''
pytorch 中的重点是构造计算图
1. 数据集
2. 神经网络模型
3. 构造损失函数和优化器
4. 训练