torch= PyTorch 的 Python API 入口

torch的历史由来

利用pytorch搭建一层神经网络

python 复制代码
import torch
import torch.nn as nn

net = nn.Linear(2,1)
x = torch.tensor([[1.0,3.0]])
out = net(x)
print(out)

输出结果

每次会给不同的w,b所以每次运行输出的结果都会改变

自动求导+反向传播更新参数

python 复制代码
import torch
import torch.nn as nn
#1.数据
x = torch.tensor([[1.0],[2.0],[3.0]])
y_true = torch.tensor([[2.0],[4.0],[6.0]])
print(y_true.shape)
#2.模型 + 损失 + 优化器
model = nn.Linear(1,1,bias=False)
loss_fn = nn.MSELoss()
optimizer = torch.optim.SGD(model.parameters(),lr=0.1)
#一轮训练(前向传播 -> 求损失 -> 反向传播 -> 更新参数)
#前向传播
y_pred = model(x)
loss = loss_fn(y_pred,y_true)

#反向传播求梯度
loss.backward()

#更新权重
optimizer.step()
#清空梯度,防止累加
optimizer.zero_grad()
print("权重w:",model.weight.item())
print("loss值:",loss.item())

输出

每次执行时输出的结果都会改变

反向传播

w新 = w旧 - 学习率 * 梯度

python 复制代码
import torch

# 参数1.初始值 2.是否自动微分 3.数据类型
w = torch.tensor(10, requires_grad=True, dtype=torch.float)
print(f'w:{w}')
# 定义loss变量,表示损失函数
loss = 2 * w ** 2  # loss求导loss = 2w² ---> 求导: 4w
# 打印梯度函数类型
print(f'梯度函数类型:{type(loss.grad_fn)}')
print(loss.sum())
# 计算梯度,梯度 = 损失函数的导数,计算完毕后会记录到w.grad属性中
loss.sum().backward()  # 保证loss是1个标量
# loss.backward()
w.data = w.data - 0.01 * w.grad  # (学习率是0.01,梯度是w.grad)

# 打印最终结果
print(f"更新后的权重:{w}")

自动微分让损失越来越小

就是深度学习中最重要的让损失越来越小,预测值无限接近于真实值。

python 复制代码
import torch

# 参数1.初始值 2.是否自动微分 3.数据类型
w = torch.tensor(10, requires_grad=True, dtype=torch.float)
print(f'w:{w}')
# 定义loss变量,表示损失函数
loss = w ** 2  # loss求导loss = w² ---> 求导: 2w
# 打印梯度函数类型
print(f"开始权重初始值:{w},(0.01 * w.grad):无, loss:{loss}")
#迭代100次,求最优解
for i in range(1,101):
    #3.1正向计算(前向传播)
    loss = w**2
    #3.2 梯度清零w.grad.zero_() 默认梯度会累加
    # 至此(第一次的时候),还没有计算梯度, 所以w.grad = None,要做非空判断
    if w.grad is not None:
        w.grad.zero_()
    #3.3反向传播 损失函数的导数,计算完毕后会记录到w.grad属性中
    loss.sum().backward()

    #3.4 梯度更新 w.data = w.data - 0.01 * w.grad
    w.data = w.data - 0.01 * w.grad

    # 3.5打印本次梯度更新后权重参数结果
    print(f"第{i}次,权重初始值:{w},(0.01 * w.grad):{0.01 * w.grad}, loss:{loss}")
#打印最终结果
print(f"最终结果权重:{w},梯度:{w.grad},loss:{loss}")

输出的结果

detach()

复制代码
一个张量一旦设置了 自动微分,这个张量就不能直接转成 numpy的 ndarray对象了,需要通过 detach()函数解决.
python 复制代码
#一个张量一旦设置了 自动微分,这个张量就不能直接转成 numpy的 ndarray对象了,需要通过 detach()函数解决.
import torch

t1 = torch.tensor([10, 20], requires_grad=True, dtype=torch.float)
print(f"t1:{t1},type:{type(t1)}")

#尝试把上述张量 ---> numpy对象
n1 = t1.numpy()
print(f"n1:{n1},type:{type(n1)}")

报错

优化后输出

python 复制代码
#一个张量一旦设置了 自动微分,这个张量就不能直接转成 numpy的 ndarray对象了,需要通过 detach()函数解决.
import torch

t1 = torch.tensor([10, 20], requires_grad=True, dtype=torch.float)
print(f"t1:{t1},type:{type(t1)}")

#尝试把上述张量 ---> numpy对象
# n1 = t1.numpy()
# print(f"n1:{n1},type:{type(n1)}")

#解决办法通过detach()函数,拷贝一份张量然后转换
n1 = t1.detach().numpy()
print(f"n1:{n1},type:{type(n1)}")