为了提高模型的复杂度,使用非线性函数(sigmoid,relu等)
求导,链式求导。
前馈运算
tensor介绍:
data和 grad
数据存放在tensor中:常亮,向量,矩阵,张量grad用于存放导数
创建模型,其实就是在构建于
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
w.requires_grad = True w是需要计算梯度的,自己设定
l.backward可以自动计算出梯度,可以把计算图上所有的需要梯度的地方都计算出来。
然后把梯度都存放到w中,之后计算图就会被释放(backward)出现以后,计算图就会被释放。
每一次释放都是为下一次构建图做准备。
权重更新的时候不需要进行图构建
上面这一步一定要取到数据,不然tensor进行,其实会继续建立图,因此需要取到里面的data
说白了就是做一个纯数值运算,并不需要搭建图
w.grad.item()就是拿出一个标量防止产生计算图
如果不进行控制(不释放),就会出现以下的循环图搭建
造成的后果是,不停地搭建图,如果数据量不较大的时候,就会把内存用完,程序崩掉。
因此主要到底是图的计算,还是标量的计算。
可以这样使用,使用item()进行
每一次更新完需要清零
"""
下面我根据自己的理解详细的把这段代码分析一遍
希望对学习pytorch的朋友有所帮助
"""
# 1 首先导入需要的库(torch和绘图)
import torch
import matplotlib.pyplot as plt
# 2 准备需要的数据 x_data,y_data
x_data = [1.0,2.0,3.0]
y_data = [2.0,4.0,6.0]
# 3 定义一个初始张量(权重w),注意,这个权重后面是需要进行更新设置的,因此需要计算梯度,这个需要w.requires_grad = True
w = torch.tensor([1.0])
w.requires_grad = True
# 4 定义一个前向函数,计算预测值,同时要知道,由于上面我们使用的是w,具有tensor权重的,因此在与常亮x_data做计算的时候,x_data会自动转换成tensor
def forward(x):
return x*w # w是tensor
# w是一个tensor,x不一定是一个tensor,因此需要自动转换为tensor,类似C语言中的数据类型转换
# 5 定义一个损失,采用均方差进行
def loss(x,y):
y_pred = forward(x)
return (y_pred - y)**2
# 6 定义两个空列表,为了接受计算的结果,用于可视化显示
print("predict (befor training)",4,forward(4).item())
epoch_l = []
loss_l = []
# 7 进行迭代,使用zip进行分离,然后计算损失,计算后需要使用backward进行导数计算
for epoch in range(100):
for x,y in zip(x_data,y_data):
l = loss(x,y)
l.backward()
print('\tgrad:',x,y,w.grad.item()) # 注意,这里的item是一定需要的,因为w是tensor类型,这里需要得到具体的值
w.data = w.data - 0.01*w.grad.data # 注意:更新权重也是一样的,是数值的更新
w.grad.data.zero_() # 这一步很重要,如果没有这一步,计算的w是混乱的,因为计算的时候会在上一步的基础上进行,因此需要做清零操作
print("prograss:",epoch,l.item())
# 这里就是为了把里面处理后的结果拿到,用户可视化
epoch_l.append(epoch)
loss_l.append(l.item())
print("predict (after training)",4,forward(4).item())
# 8 可视化显示(epoch和loss)
plt.plot(epoch_l,loss_l,c='r')
plt.show()