一、实现方式

1. 准备数据集

  • 文本数值化 -> 数值张量化
  • Dataset -> DataLoader
  • Dataset: 把x和y对应起来
  • DataLoader: 方便批量取数据

2. 构建模型

  • 使用类来构建(继承Module,实现2个方法【init, forward】)

3. 模型训练 2层循环,外层遍历轮次,内层遍历批次

4模型预测/评估 和模型训练类似,但是比模型训练简单

二、线性回归详细流程

                                                        

        

三、案例代码

import copy

import matplotlib.pyplot as plt
import torch
import torch.nn as nn
import torch.optim as optim
from sklearn.datasets import make_regression
import warnings
from torch.utils.data import DataLoader, TensorDataset

plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号

warnings.filterwarnings(action="ignore")


# 1.构造数据集
def get_dataset():
    x, y, coef = make_regression(n_samples=100, n_features=1, bias=1.5, noise=10, coef=True, random_state=22)
    x = torch.tensor(x, dtype=torch.float32)
    y = torch.tensor(y, dtype=torch.float32)
    return x, y, coef


# 2.可视化数据集
def show_dataset():
    x, y, coef = get_dataset()
    plt.scatter(x, y)
    plt.plot(x, x * coef + 1.5)
    plt.grid()
    plt.show()


# 3.构建模型
def make_model():
    # 模型
    model = nn.Linear(in_features=1, out_features=1) #当你创建nn.Linear模型时,模型内部的参数,(权重和偏置)会自动设置requires_grad=True
    # 损失函数
    loss_fn = nn.MSELoss()
    # 优化器
    optimizer = optim.SGD(params=model.parameters(), lr=0.01)
    return model, loss_fn, optimizer


# 4.模型训练
def train_model():
    # 获取数据迭代器
    x, y, coef = get_dataset()
    x1 = x
    y1 = y

    # 转换为dataset --->将x,y对应起来,dataset[0]拿到第一个x和y
    # 转换dataloader --->方便批次取数据
    dataset = TensorDataset(x, y)
    # print(x,y,dataset[0]) # dataset[0]拿到第一个x和y

    # batch_size 1或者2的指数幂,shuffle:打乱数据的顺序,模型训练必须,因为原数据可能有顺序,必须要保持公正
    dataloader = DataLoader(dataset=dataset, batch_size=8, shuffle=True)
    # 获取模型 模型三大剑
    model, loss_fn, optimizer = make_model()
    # 准备变量
    epochs = 100  # 遍历轮次
    # 以下三行代码 定义额外参数 目的可视化
    total_sample = 0
    total_loss = 0
    epoch_loss = []
    # 模型训练
    # 外层循环控制轮次
    for epoch in range(epochs):
        # 内存循环控制批次   ---> batch_size=8
        for x, y in dataloader:
        #     print(x) #tensor([[ 0.0128],[ 1.0560],[ 0.0237],[ 0.5557],[-0.4238],[ 0.5526],[-0.1650],[-0.2349]])
        #     print(y) #tensor([ -4.2455,  43.6361, -10.8484,  28.9158, -11.2937,  15.7931,  -4.0613,-18.4478]) y是1维的
        #     break
        # break
            # 模型预测
            y_pred = model(x)  # 调用模型方法,前向传播forward-->
                               # model = nn.Linear(in_features=1, out_features=1)
                               # 当你创建nn.Linear模型时,模型内部的参数,(权重和偏置)会自动设置requires_grad=True
            # 计算损失,因为y_pred:[8,1],所以需要把y也变成[8,1]的形状
            loss = loss_fn(y_pred, y.reshape(-1, 1))
            # 梯度清零
            optimizer.zero_grad()
            # 反向传播
            loss.backward()  #在循环内,loss是一个标量
            # 梯度更新
            optimizer.step()
            # 纪录数据
            total_loss += loss.item() # 取tensor中的数
            total_sample += len(y)

        # 以下两行代码是为了 可视化
        epoch_loss.append(total_loss / total_sample) # total_loss / total_sample:每8个样本中平均每个样本的损失,
                                                     # epoch_loss一共有100个数字,代表共计100轮计算出的平均损失

        # 打印日志
        print("当前轮次:", (epoch + 1), "当前平均损失:", total_loss / total_sample)

    # 绘制损失曲线
    plt.plot(range(epochs), epoch_loss) # 每个轮次的每轮平均损失(一共100个轮次)
    plt.grid()
    plt.title("损失变化曲线")
    plt.show()

    # 绘制拟合曲线
    x1 = x1.detach().numpy()
    y1 = y1.detach().numpy()
    plt.scatter(x1, y1) #真实值散点图 不能用x,y,因为for x,y in dataloader隐式赋值了
    plt.plot(x1, x1 * coef + 1.5, label='true')  #真实值线性方程
    plt.plot(x1, model.weight.detach().numpy() * x1 + model.bias.detach().numpy(), label='train') #预测值线性方程
    plt.grid()
    plt.legend() #展示图例
    plt.show()


if __name__ == '__main__':
    # show_dataset()
    # make_model()
    train_model()

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐