1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
import torch
# 准备数据集
x_data = [1.0, 2.0, 3.0]
y_data = [2.0, 4.0, 6.0]
w = torch.Tensor([1.0]) # 创建权重初始值,tensor变量中只有一个值
w.requires_grad = True # 该变量需要计算梯度,默认的tensor不需要计算梯度
# 设计模型
def forward(x):
return x* w # w是个tensor,乘法*被重载了: tensor 与tensor之间的数乘,x被自动转换成tensor,所以乘法结果也是tensor,并且也会需要计算梯度。
# 计算损失
def loss(x,y):
y_pred = forward(x) # 计算预测值
return (y_pred - y) ** 2 # 每调用一次loss函数,计算图被动态地构建出来
# 训练过程
print("predict (before training)", 4, forward(4).item())
for epoch in range(100): #训练100轮
for x,y in zip(x_data, y_data): # 对应组合拼起来
# 前馈:计算每个样本的损失(随机梯度下降),是一个(标量)tensor,含有1个值,
# 如果是一个向量没法backward
l = loss(x,y)
# 反向传播:调用张量 l 的成员函数,把图上的所有梯度求出来,存到 w 中,然后计算图就被释放了,
# 下一次loss计算会创建新的计算图(因为每次计算图可能不一样)
l.backward()
print('\t grad:', x,y, w.grad.item()) #item把grad变成int/float,直接拿出它的数值(防止产生计算图)
w.data = w.data - 0.01 * w.grad.data #更新数值,成员grad也是一个tensor,tensor的乘法会建立计算图,所以要取其data再做乘法,就不会建立计算图,只是修改w的数值(并不是说以后还要对这个运算求梯度)
w.grad.data.zero_() #权重的梯度(导数)的数值清零,否则各次由.backward()计算出的梯度值会累加(有的时候需要梯度累加)
print("progress",epoch, 1.item()) #打印每轮训练的loss
print("predict (after training)", 4, forward(4).item())
|