Torch框架:自动微分、组件、数据构建加载、重构线性回归

自动微分:

import torch
import numpy as np
from matplotlib import pyplot as plt

# 关闭科学计数法
# np.set_printoptions(suppress=True)
torch.set_printoptions(sci_mode=False)

# 叶子节点:
# 用户直接创建的张量,并且requires_grad=True
def test01():
    x = torch.tensor(5.0, requires_grad=True)
    y = x ** 2
    z = y.sum()
    print(x.is_leaf)
    print(y.is_leaf)
    print(z.is_leaf)
    print(y.requires_grad)
    print(z.requires_grad)

# 反向传播
def test02():
    x = torch.tensor(1.0, requires_grad=True)
    y = torch.tensor(2.0)
    z = x ** 2 + y ** 2
    # 反向传播,自动求导,计算x的梯度
    z.backward()
    # 获取x的梯度
    print(x.grad)
    print(y.grad)

# 向量反向传播,计算梯度
def test03():
    x = torch.tensor([1, 2, 3], dtype=torch.float, requires_grad=True)
    y = x ** 2
    # loss = y.sum()
    loss = y.mean()
    # 反向传播
    # y.backward(torch.tensor([1.0, 1.0, 1.0]))
    loss.backward()
    print(x.grad)

# 多标量反向传播计算梯度
def test04():
    x = torch.tensor(1.0, requires_grad=True)
    y = torch.tensor(2.0, requires_grad=True)
    z = x ** 2 + y ** 2
    z.backward()
    print(x.grad)
    print(y.grad)

# 多向量反向传播计算梯度
def test05():
    x = torch.tensor([1, 2, 3], dtype=torch.float, requires_grad=True)
    y = torch.tensor([4, 5, 6], dtype=torch.float, requires_grad=True)
    z = x * y
    loss = z.sum()
    loss.backward()
    print(x.grad)
    print(y.grad)

# 设置张量不参与梯度计算
def test06():
    x = torch.tensor(1.0, requires_grad=True)
    y = x ** 2
    print(y.requires_grad)
    # 通过with梯度上下文控制,使y不参与梯度计算(常用)
    # torch.no_grad():控制张量不参与梯度计算
    with torch.no_grad():
        y = x ** 2
        print(y.requires_grad)

    # 通过装饰器
    @torch.no_grad()
    def fn():
        y = x ** 2
        return y

    y = fn()
    print(y.requires_grad)
    # 全局控制(谨慎使用)
    torch.set_grad_enabled(False)
    y = x ** 2
    print(y.requires_grad)

# 梯度累加
def test07():
    x = torch.tensor([1, 2, 3], dtype=torch.float, requires_grad=True)
    # 循环计算梯度时,默认梯度是累加的
    for _ in range(3):
        y = x ** 2
        z = y.sum()
        z.backward()
        print(x.grad)
        # 梯度清零
        if x.grad is not None:
            x.grad.zero_()
        z.backward()
        print(x.grad)

# 求函数最小值
# 绘制曲线函数,帮助分析数据
def test08():
    x = np.linspace(-10, 10, 100)
    y = x ** 2
    plt.plot(x, y)
    plt.show()

# 通过反向传播计算最小值
def test09():
    lst = []
    # 初始化x值
    x = torch.tensor(3.0, requires_grad=True)
    # 迭代检索
    epochs = 25
    # 学习率
    lr = 0.1
    for epoch in range(epochs):
        y = x ** 2
        # 反向传播
        y.backward()
        # 梯度下降计算时,x不需要参与梯度计算
        with torch.no_grad():
            x -= lr * x.grad
        # 梯度清零
        x.grad.zero_()
        print(f"epoch: {epoch}, x:{x.item()}, y:{y.item()}")
        lst.append((x.item(), y.item()))
    x_lst = [t[0] for t in lst]
    y_lst = [t[1] for t in lst]
    plt.scatter(x=x_lst, y=y_lst)
    plt.show()

if __name__ == '__main__':
    # test01()
    # test02()
    # test03()
    # test04()
    # test05()
    # test06()
    # test07()
    # test08()
    test09()

组件:

import torch
from torch import nn, optim

# 线性层组件
def test01():
    # nn.Linear():线性层组件
    # 参数:
    # in_features:输入的特征数
    # out_features:输出的特征数
    model = nn.Linear(20, 30)
    x = torch.randn(100, 20)
    y = model(x)
    print(y.shape)

# 优化器
def test02():
    # 学习率
    lr = 0.1
    # y = x ** 2
    # 定义线性模型,w和b做了随机初始化
    model = nn.Linear(20, 10)
    # 定义损失函数
    criterion = nn.MSELoss()
    # 定义优化器,主要做梯度下降,更新模型参数
    optimizer = optim.SGD(model.parameters(), lr=lr)
    # 初始化输入数据
    x = torch.randn(100, 20)
    # 标签数据
    y = torch.randn(100, 10)
    # 预测值
    y_pred = model(x)
    # 损失函数
    loss = criterion(y_pred, y)
    # 反向传播
    loss.backwrad()
    # 梯度下降,更新模型参数
    optimizer.step()
    # 梯度清零
    optimizer.zero_grad()
    print(loss.item())
    print(model.weight)
    print(model.bias)

if __name__ == '__main__':
    # test01()
    test02()

数据构建和加载:

import torch
from torch.utils.data import Dataset, TensorDataset, DataLoader

torch.manual_seed(0)

# 自定义数据构建类
# 1.继承Dataset抽象类
# 2.必须实现__len__和__getitem__方法
class MyDataset(Dataset):
    def __init__(self, data, label):
        self.data = data
        self.label = label

    def __len__(self):
        return len(self.data)

    def __getitem__(self, index):
        data = self.data[index]
        label = self.label[index]
        return data, label

def test01():
    x = torch.randn(100, 10)
    y = torch.randn(100, 1)
    my_dataset = MyDataset(x, y)
    print(my_dataset[0])

# TensorDataset():是Dataset的一个实现类
# 可以将data和label作为参数传输给TensorDataset()生成数据集
def test02():
    x = torch.randn(100, 10)
    y = torch.randn(100, 1)
    my_dataset = TensorDataset(x, y)
    print(my_dataset[0])

# 数据加载器:DataLoader,是一个迭代器
# 参数:
# batch_size:批量加载数据,将多个样本打包成一个批量,加载器每次加载一个批量的数据
# shuffle:为True表示打乱数据顺序
def test03():
    x = torch.randn(100, 10)
    y = torch.randn(100, 1)
    my_dataset = MyDataset(x, y)
    dataloader = DataLoader(my_dataset, batch_size=4, shuffle=True)
    for data, label in dataloader:
        print(data)
        print(label)

if __name__ == '__main__':
    # test01()
    # test02()
    test03()

重构线性回归:

import torch
from torch import nn, optim
from sklearn.datasets import make_regression
import random
from torch.utils.data import Dataset, DataLoader, TensorDataset

input_features = 5

def build_data():
    noise = random.randint(1, 3)
    bias = 14.5
    x, y, coef = make_regression(
        # 样本数量
        n_samples=1000,
        # 每个样本包含的特征数量
        n_features=input_features,
        # 输出标签个数
        n_targets=1,
        # coef若为True,则返回真实系数(权重)
        coef=True,
        # 随机数种子
        random_state=42,
        # 添加噪声
        noise=noise,
        # 设置偏移值
        bias=bias
    )
    x = torch.tensor(x, dtype=torch.float)
    y = torch.tensor(y, dtype=torch.float)
    coef = torch.tensor(coef, dtype=torch.float)
    bias = torch.tensor(bias, dtype=torch.float)
    return x, y, coef, bias

def train():
    x, y, coef, bias = build_data()
    # 封装数据集
    dataset = TensorDataset(x, y)
    # 数据加载器
    dataloader = DataLoader(dataset, batch_size=16, shuffle=True)
    # 定义线性模型
    model = nn.Linear(input_features, 1)
    # 定义损失函数
    criterion = nn.MSELoss()
    # 定义优化器
    optimizer = optim.SGD(model.parameters(), lr=0.1)
    epochs = 500
    # 开始训练
    for epoch in range(epochs):
        loss_sum = 0
        for train_x, train_y in dataloader:
            # 获取预测值
            y_pred = model(train_x)
            # 损失计算
            loss = criterion(y_pred, train_y.view(-1, 1))
            # 反向传播
            loss.backward()
            # 更新参数(梯度下降)
            optimizer.step()
            # 梯度清零
            optimizer.zero_grad()
            # 损失值累加
            loss_sum += loss.item()
            # print(f"Epoch: {epoch}, Loss: {loss.item()}")
        print(f"Epoch: {epoch}, Loss: {loss_sum / len(dataloader)}")

    w = model.weight.detach()
    b = model.bias.detach().item()
    print(f"真实w: {coef}, 训练w: {w}")
    print(f"真实偏置(b): {bias}, 训练偏置: {b}")

if __name__ == '__main__':
    train()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值