PyTorch基础学习04_手动构建模型&官方模型定义组件

目录

一、手动构建模型

1、概念

2、模型构建

0.相关库函数

1.构建数据集

2.加载数据集

3.初始化参数

4.线性回归

5.损失函数

6.优化器

7.训练数据集

8.预测数据

9.调用

二、官方模型定义组件

1、模型组件

0.库函数

1.损失函数组件

2.线性回归模型组件

3.优化器方法

2、数据加载器

1.构建数据类

2.数据加载器

3、数据集加载案例

1.加载Excel数据集

2.加载图片数据集

3.加载官方数据集

4、数据增强


一、手动构建模型

1、概念

模型训练中的三个基础概念:

名词 定义
Epoch 使用训练集的全部数据对模型进行一次完整训练,被称为"一代训练"
Batch 使用训练集中的一小部分样本对模型权重进行一次反向传播的参数更新,这一小部分样本被称为"一批数据"
Iteration 使用一个Batch数据对模型进行一次参数更新的过程,被称为"一次训练"

2、模型构建

0.相关库函数
python 复制代码
import math
import torch
import random
from sklearn.datasets import make_regression
1.构建数据集
python 复制代码
def build_data():
    # 噪声设置
    noise = random.randint(1,5)
    # 样本数量
    sample = 500
    # 真实偏置
    bias = 0.5
    # 划分数据集 coef=True 表示希望函数返回生成数据的真实系数 coef即为真实系数
    x,y,coef = make_regression(n_samples=sample,n_feature=4,coef=True,noise=noise,bias=bias,random_state=666)
    # 数据转换为张量
    x = torch.tensor(x,dtype=torch.float32)
    y = torch.tensor(y,dtype=torch.float32)
    coef = torch.tensor(coef, dtype=torch.float32)

    return x,y,coef,bias
2.加载数据集

将数据集转换为迭代器,以便在训练过程中进行批量处理。

python 复制代码
def load_data(x,y):
    # 配置参数
    # 单批次数量
    batch_size = 16
    # 样本总数量
    n_samples = x.shape[0] # len(x)
    # 单轮训练的次数&向上取整
    n_batches = math.ceil(n_samples/batch_size)
    # 数据索引
    indices = list(range(n_samples))
    # 打乱索引
    random.shuffle(indices)
    # 循环从单批次中取出数据
    for i in range(0,n_batches):
        # 取出每批次对应的范围 同时做防越界处理 数量
        start = i*batch_size
        end = min((i+1)*batch_size, n_samples)
        index = indices[start:end]
        # 返回对应数据
        yield x[index],y[index]
3.初始化参数

随机初始化权重w和设置偏置b。

python 复制代码
def initialize(n_feature):
    # 根据特征数量设置权重
    # 随机数种子
    torch.manual_seed(666)
    # 随机化权重 正态分布
    w = torch.randn(n_features,require_grad=True,dtype=torch.float32)
    # 手动设置偏置
    b = torch.tensor(0.0,require_grad=True,dtype=torch.float32)
    
    return w,b
4.线性回归

设置模型函数,即进行"前向传播"。

python 复制代码
def regressor(x,w,b):
    return torch.matmul(x,w) + b # x@w + b
5.损失函数

设置为均分误差形式,即反向传播的对象。

python 复制代码
def Loss(y_pred,y_true):
    # 均方误差
    return torch.mean((y_pred - y_true)**2)
6.优化器

用在梯度更新,向梯度下降的方向更新。

python 复制代码
def optim_step(w,b,dw,db,lr):
    w.data = w.data - lr*dw.data
    b.data = b.data - lr*db.data
    return w,b
7.训练数据集
python 复制代码
def train():
    # 生成数据
    x,y,coef,bias = build_data()
    # 初始化参数
    w,b = initialize(n_features=x.shape[1])
    # 训练参数
    lr = 0.01 # 学习率
    epoch = 50 # 训练次数
    # 训练数据
    for i in range(epoch):
        total_loss = 0 # 误差总和
        count = 0 # 训练次数计数
        # 每个批次中的数据
        for batch_x,batch_y_true in load_data(x,y):
            # 预测数据
            batch_y_pred = regressor(batch_x,w,b)
            # 计算损失函数
            loss = MSE(batch_y_pred,batch_y_true) # 因为是均方误差 所以不需要讲究顺序
            total_loss += loss
            count += 1
            # 梯度清零
            if w.grad is not None:
                w.data.zero_()
            if b.grad is not None:
                b.data.zero_()
            # 反向传播 计算梯度
            loss.backward()
            # 梯度更新 得出预测权重和偏置
            w,b = optim_step(w,b,w.grad,b.grad,lr)
        print(f'epoch:{i},loss:{total_loss/count}')
    return w.data,b,coef,bias
8.预测数据
python 复制代码
def detect(x,w,b):
    return torch.matmul(x.type(torch.float32),w) + b # tensor相乘加上偏置
9.调用
python 复制代码
if __name__ == "__main__":
    w,b,coef,bias = train()
    print(f'真实系数:{coef},真实偏置:{bias}')
    print(f'预测系数:{w},预测偏置:{b}')
    # 根据手动添加的特征预测结果 这里添加了两个
    y_pred = detect(torch.tensor([[4,5,6,6],[7,8,8,9]]),w,b)
    print(f'y_pred:{y_pred}')

二、官方模型定义组件

1、模型组件

0.库函数
python 复制代码
import torch
import torch.nn as nn
import torch.optim as optim
1.损失函数组件
python 复制代码
def test01():
    """
    损失函数组件
    """
    y_true = torch.tensor([1,2,3,4,5,6],dtype=torch.float32)
    y_pred = torch.tensor([2,3,4,5,6,7],dtype=torch.float32)
    # 均分误差工具
    loss = nn.MSELoss()
    e = loss(y_true,y_pred)
    print(e)
2.线性回归模型组件
python 复制代码
def test02():
    """
    线性回归模型组件
    """
    model = nn.Linear(4,1) # w1x1+w2x2+w3x3+w4x4+b=y 隐式操作:w1 w2 w3 w4已经初始化
    # x = torch.tensor([[1,2,3,4]],dtype=torch.float32)
    # y = model(x)
    print(model.parameters())
    x1 = torch.tensor([[1,2,3,4],[1,2,3,4],[1,2,3,4]],dtype=torch.float32)
    y1 = model(x1)
    # print(y)
    print(y1)
3.优化器方法
python 复制代码
def test03():
    """
    优化器方法
    """
    # 梯度更新

    # 01 构造数据集
    input_x = torch.randint(1,10,(400,5)).type(torch.float32)
    target = torch.randint(1,10,(400,1)).type(torch.float32)
    # 02 线性层模型
    model = nn.Linear(5,1)
    # 03 优化器对象
    sgd = optim.SGD(model.parameters(),lr=0.01) # 将模型参数w传入优化器
    # 04 预测
    y_pred = model(input_x)
    # 05 损失函数
    loss_fn = nn.MSELoss()
    loss = loss_fn(y_pred,target) # 均方误差
    # print(loss)
    # 06 梯度清零
    sgd.zero_grad() # 相当于 w.grad.zero_()
    # 07 反向传播
    loss.backward() # 1 损失函数对参数的导数 2 求梯度
    # 08 梯度更新
    sgd.step()
    # 09 访问更新后的w
    print(model.weight)

2、数据加载器

1.构建数据类

在 PyTorch 中,构建自定义数据加载类通常需要继承 torch.utils.data.Dataset 并实现以下几个方法:

1、init 方法 用于初始化数据集对象:通常在这里加载数据,或者定义如何从存储中获取数据的路径和方法。

python 复制代码
    def __init__(self,data,target):
        self.data = data
        self.target = target

2、len 方法 返回样本数量:需要实现,以便 Dataloader加载器能够知道数据集的大小。

python 复制代码
    def __len__(self):
        return len(self.data)

3、getitem 方法 根据索引返回样本:将从数据集中提取一个样本,并可能对样本进行预处理或变换。如果需要进行更多的预处理或数据变换,可以在该方法中添加额外的逻辑。

python 复制代码
    def __getitem__(self,index):
        return self.data[index],self.target[index]
2.数据加载器

在训练或者验证的时候,需要用到数据加载器批量的加载样本。

和构建数据整合:

python 复制代码
import torch
import torch.nn as nn
from torch.utils.data import Dataset,DataLoader

class CustomDataSet(Dataset):
    def __init__(self,data,target):
        self.data = data
        self.target = target

    def __getitem__(self,index):

        return self.data[index],self.target[index]
    
    def __len__(self):
        return len(self.data)


if __name__ == '__main__':
    # data = CustomDataSet() -> __init__
    # len(data) -> __len__
    # data[0] -> __getitem__
    x = torch.randn(100,3)
    y = torch.randn(100,1)
    # 数据集
    data = CustomDataSet(x,y)
    count = len(data)
    print(count)
    print(data[0])

    """
    数据加载器
    """
    data_loader = DataLoader(data,batch_size=16,shuffle=True) # 小批次设置为16 shuffle=True打乱顺序
    for x,y in data_loader:
        print(x.shape,y.shape)

3、数据集加载案例

1.加载Excel数据集
python 复制代码
import torch
import pandas as pd
from torch.utils.data import Dataset,DataLoader

class my_excel_dataset(Dataset):
    def __init__(self,path):
        """
        读取excel文件, 提取特征值保存在data中, 标签值保存在target中
        """
        data_pd = pd.read_excel(path)
        # 数据处理:删除NAN的列
        data_pd.dropna(axis=1,how='all')
        # 将数据转换为DataFrame
        data_pd = pd.DataFrame(data_pd)
        # 删除原有的表头,并重命名列名为英文
        data_pd.columns = ["zubie",
                            "student_id",
                            "name",
                            "self_work",
                            "expression",
                            "ppt",
                            "answer",
                            "present",
                            "defense",
                            "comments",]
        data_pd = data_pd.drop(["zubie", "student_id", "name", "self_work", "comments"],axis=1)

        # print(data_pd.head())
        # 转换为tensor
        self.data = torch.tensor(data_pd.iloc[:,:-1].to_numpy(),dtype=torch.float32)
        self.target = torch.tensor(data_pd.iloc[:,-1].to_numpy(),dtype=torch.float32)
        
    def __len__(self):
        return len(self.data)
    def __getitem__(self,index):
        return self.data[index],self.target[index]
    


if __name__ == '__main__':
    data = my_excel_dataset('./data/21级大数据答辩成绩表.xlsx')
    data_loader = DataLoader(data,batch_size=4,shuffle=True)
    for x,y in data_loader:
        print(x,y)
2.加载图片数据集

os模块相关API:

python 复制代码
import os

"""
os模块的API
"""
def test01():
    """
    遍历当前目录
    """
    for root, dirs, files in os.walk("./data"):
        # root:当前目录路径 dirs:当前路径下所有子目录 files:当前路径下所有非目录子文件
        print(root, dirs, files,'666')

def test02():
    """
    查看文件
    """
    path = os.path.join("./data", "1.png")
    # 拼接路径 path = "./data"+"/"+"1.png"
    print(path)

def test03():
    """
    获取文件名
    """
    _,str = os.path.split("./data/animal/cat")
    print(str)

def test04():
    """
    enumrate 生成枚举下标
    """
    x=["20","hello","9999"]
    for i in range(len(x)):
        print(i,x[i])
    x=["20","hello","9999"]
    for i,el in enumerate(x):
        print(i,el)

案例:

python 复制代码
import os
import cv2
import torch
from torch.utils.data import Dataset,DataLoader

class my_image_dataset(Dataset):
    def __init__(self,path):
        self.path = path
        self.classname=[]
        self.data = []
        self.label = []
        # 遍历文件夹
        for root,dirs,files in os.walk(path):
            if root == path:
                # 通过读取文件目录创建分类名
                self.classname = dirs
                # print(dirs)
                # return
            else:
                for file in files:
                    # 单个文件的完整路径
                    file_path = os.path.join(root,file)
                    self.data.append(file_path)
                    # 该文件对应的类别
                    class_id = self.classname.index(os.path.split(root)[1])
                    self.label.append(class_id)
        
    def __len__(self):
        return len(self.data)
    def __getitem__(self,index):
        img_path = self.data[index] # x
        label = self.label[index] # y
        img = cv2.imread(img_path)
        img = cv2.resize(img,(300,300))

        img = torch.from_numpy(img)
        # HWC to CHW
        img = img.permute(2,0,1) # 维度转换
        return img, label

if __name__ == '__main__':
    data = my_image_dataset('./data/animal')
    # print(data[120])
    print(len(data))
    print(data.classname)
    train_loader = DataLoader(data, batch_size=32, shuffle=True)
    for x,y in train_loader:
        print(x) # [32,3,300,300] 单批次32张图片;3通道;300*300大小
        print(y) # [32] 32个标签
    # test04()
3.加载官方数据集

在 PyTorch 中官方提供了一些经典的数据集,如 CIFAR-10、MNIST、ImageNet 等,可以直接使用这些数据集进行训练和测试。

注意,该案例下需要联网下载官方数据集。官方地址:Datasets --- Torchvision 0.20 documentation

python 复制代码
from torchvision import datasets,transforms
from torch.utils.data import DataLoader

def test01():
    transform = transforms.Compose([
        transforms.ToTensor()
    ])
    data = datasets.MNIST(
        root='./data',
        train=True,
        download=True,
        transform=transform
    )
    for x,y in DataLoader(data,batch_size=4,shuffle=True):
        print(x.shape,y.shape)

if __name__ == '__main__':
    test01()

4、数据增强

数据增强是提高模型泛化能力(鲁棒性)的一种有效方法,尤其在图像分类、目标检测等任务中。数据增强可以模拟更多的训练样本,从而减少过拟合风险。数据增强通过torchvision.transforms模块来实现。

具体参考官方文档:Illustration of transforms --- Torchvision 0.20 documentation

相关推荐
galileo201612 分钟前
LLM与金融
人工智能
DREAM依旧28 分钟前
隐马尔科夫模型|前向算法|Viterbi 算法
人工智能
ROBOT玲玉32 分钟前
Milvus 中,FieldSchema 的 dim 参数和索引参数中的 “nlist“ 的区别
python·机器学习·numpy
GocNeverGiveUp41 分钟前
机器学习2-NumPy
人工智能·机器学习·numpy
浊酒南街1 小时前
决策树(理论知识1)
算法·决策树·机器学习
oneouto2 小时前
selenium学习笔记(二)
笔记·学习·selenium
B站计算机毕业设计超人2 小时前
计算机毕业设计PySpark+Hadoop中国城市交通分析与预测 Python交通预测 Python交通可视化 客流量预测 交通大数据 机器学习 深度学习
大数据·人工智能·爬虫·python·机器学习·课程设计·数据可视化
学术头条2 小时前
清华、智谱团队:探索 RLHF 的 scaling laws
人工智能·深度学习·算法·机器学习·语言模型·计算语言学
sealaugh322 小时前
aws(学习笔记第十九课) 使用ECS和Fargate进行容器开发
笔记·学习·aws
18号房客2 小时前
一个简单的机器学习实战例程,使用Scikit-Learn库来完成一个常见的分类任务——**鸢尾花数据集(Iris Dataset)**的分类
人工智能·深度学习·神经网络·机器学习·语言模型·自然语言处理·sklearn