全连接神经网络:分类与回归示例

分类

创建测试数据

python 复制代码
import random
import torch
import torch.utils.data

def get_rectangle():
    """
    随机得到矩形的宽和高,值域0-1之间的小数,
    判断这是否是一个"胖"的矩形
    :return:
    """
    width = random.random()
    height = random.random()
    fat = int(width >= height)
    return width, height, fat
width, height, fat=get_rectangle()
print(width, height, fat)

定义数据集(torch.utils.data.Dataset)

定义数据集一般是创建一个class继承torch.utils.data.Dataset,在这个class里面要定义三个函数,分别是init、len、getitem。init一般用于数据集的初始化,预处理等操作;len函数要输出这个数据集有多少条数据,按理来说我们这个测试数据是动态生成的,理论上来说有无穷多条,但在这样还是要给pytorch一个明确的数量;getitem函数是要根据序号i来获取一条数据。

python 复制代码
class Dataset(torch.utils.data.Dataset):
    #正常应该在这里执行数据的加载,处理等工作
    def __init__(self):
        pass
    #定义数据的条数
    def __len__(self):
        return 500
    #根据序号i,获取一条数据
    def __getitem__(self, i):
        #获取一个矩形的数据
        width, height, fat = get_rectangle()
        #定义宽高为x,定义是否胖为y
        x = torch.FloatTensor([width, height])
        y = fat
        return x, y
dataset = Dataset()

print(len(dataset), dataset[0])

500 (tensor([0.0132, 0.6463]), 0)

这里我们查看了dataset的数量,并查看了第0条数据。

数据遍历工具loader

这个loader是一个数据的加载器,我们把数据集传给dataset,并每八条数据为一个批次,然后我们打乱数据集当中的顺序,先前我们定义了500条数据,并非是8的整数倍,drop_last不足时直接丢弃。

python 复制代码
loader = torch.utils.data.DataLoader(dataset=dataset,
                                     batch_size=8,
                                     shuffle=True,
                                     drop_last=True)
print(len(loader), next(iter(loader)))

62 [tensor([[0.4461, 0.1130],

0.6130, 0.8681\], \[0.5334, 0.5767\], \[0.9663, 0.4436\], \[0.6687, 0.5886\], \[0.5669, 0.7870\], \[0.9415, 0.3396\], \[0.2015, 0.5745\]\]), tensor(\[1, 0, 0, 1, 1, 0, 1, 0\])

定义神经网络模型

定义的方法也是创建class继承torch.nn.module,一般在这个class下有两个函数分别是init和forward,分别是用于模型初始化和神经网络的计算过程,先来看初始化部分,这里调用了一个sequential这样一个类,用于把多层神经网络给组合在一起,也就是前后串连的关系,算完一层再算完下一层

python 复制代码
#全连接神经网络
class Model(torch.nn.Module):

    #模型初始化部分
    def __init__(self):
        super().__init__()
        #定义神经网络结构
        self.fc = torch.nn.Sequential(
            torch.nn.Linear(in_features=2, out_features=32),
            torch.nn.ReLU(),
            torch.nn.Linear(in_features=32, out_features=32),
            torch.nn.ReLU(),
            torch.nn.Linear(in_features=32, out_features=2),
            torch.nn.Softmax(dim=1),
        )

    #定义神经网络计算过程
    def forward(self, x):
        return self.fc(x)
model = Model()
print(model(torch.randn(8,2)).shape)

输入层是两个维度输入,分别就是宽和高,输出是32维的向量,激活函数ReLU将所有的负数归零,中间层就是32x32密集的网络,从这层可以很好的抽取数据当中的特征,输出还是一个Linear,输入是32维的向量,输出是两维的向量,符合我们二分类的条件,最后一层假如了softmax,这层的功能是让两个神经元输出为1,因为我们是一个二分类问题,希望其相加的结果为1。

训练模型

在训练模型部分,首先来初始化一个优化器,代码中使用的是Adam,learning rate为1e-4。因为是分类这里使用的celoss,然后我们调用train函数,对全量的数据遍历100轮,从loader中取到一批批的数据,然后我们把x放到模型中去计算,将模型计算的结果与真实的y进行求误差,也就是调用的loss函数,如果模型计算的结果根y是完全相同的情况下,它的loss应当是0,但一般是不可能的。有了loss再算梯度,调整模型当中的参数,调整完后使梯度归零,所有的pytorch都会经过这里的三个步骤。

python 复制代码
def train():
    #优化器,根据梯度调整模型参数
    optimizer = torch.optim.Adam(model.parameters(), lr=1e-4)
    
    #计算loss的函数
    loss_fun = torch.nn.CrossEntropyLoss()
    
    #让model进入train模式,开启dropout等功能
    model.train()

    #全量数据遍历100轮
    for epoch in range(100):
        
        #按批次遍历loader中的数据
        for i, (x, y) in enumerate(loader):
            
            #模型计算
            out = model(x)
            
            #根据计算结果和y的差,计算loss,在计算结果完全正确的情况下,loss为0
            loss = loss_fun(out, y)

            #根据loss计算模型的梯度
            loss.backward()
            
            #根据梯度调整模型的参数
            optimizer.step()
            
            #梯度归零,准备下一轮的计算
            optimizer.zero_grad()

        if epoch % 20 == 0:
            #计算正确率
            acc = (out.argmax(dim=1) == y).sum().item() / len(y)
            print(epoch, loss.item(), acc)
            
    #保存模型到磁盘
    torch.save(model, 'model/3.model')

关于使用哪一个工具类来计算loss,一般来说回归采用MSEloss,分类使用CEloss。

测试

代码中添加了一个注解,意思是在这个函数中不需要计算模型的梯度,因为在这个函数中执行的是测试,而非执行训练,所以不需要更新参数,所以也就不需要计算模型的梯度。首先要将训练好的模型给它加载进来。让模型进入测试模式,这样可以关闭模型当中的一些dropout之类的功能。从loader中获取一批数据,然后计算模型的正确率。

python 复制代码
#测试
#注释的表明不计算模型梯度,节省计算资源
@torch.no_grad()
def test():
    
    #从磁盘加载模型
    model = torch.load('model/3.model')

    #模型进入测试模式,关闭dropout等功能
    model.eval()

    #获取一批数据
    x, y = next(iter(loader))

    #模型计算结果
    out = model(x).argmax(dim=1)

    print(out, y)
    print(out == y)

回归

创建测试数据

python 复制代码
#生成矩形数据的函数
def get_rectangle():
    import random

    #随机得到矩形的宽和高,值域0-1之间的小数
    width = random.random()
    height = random.random()

    #计算面积
    s = width * height

    return width, height, s

定义数据集

在这里初始化不需要进行任何操作,数据的条数理论上有无穷多条,但在pytorch中还是要明确指出,每次生成一条数据,将类型转为tensor。

python 复制代码
import torch


#定义数据集
class Dataset(torch.utils.data.Dataset):

    #正常应该在这里执行数据的加载,处理等工作
    def __init__(self):
        pass

    #定义数据的条数
    def __len__(self):
        return 500

    #根据序号i,获取一条数据
    def __getitem__(self, i):
        #获取一个矩形的数据
        width, height, s = get_rectangle()

        #定义宽高为x,定义面积为y
        x = torch.FloatTensor([width, height])
        y = torch.FloatTensor([s])

        return x, y


dataset = Dataset()

print(len(dataset), dataset[0])

数据遍历工具loader

python 复制代码
#数据集加载器,每8条数据为一个批次,打乱顺序,不足8条时丢弃尾数
loader = torch.utils.data.DataLoader(dataset=dataset,
                                     batch_size=8,
                                     shuffle=True,
                                     drop_last=True)

print(len(loader), next(iter(loader)))

loader的定义与上面的分类相同。

定义神经网络模型

python 复制代码
class Model(torch.nn.Module):

    #模型初始化部分
    def __init__(self):
        super().__init__()

        #定义神经网络结构
        self.fc = torch.nn.Sequential(
            torch.nn.Linear(in_features=2, out_features=32),
            torch.nn.ReLU(),
            torch.nn.Linear(in_features=32, out_features=32),
            torch.nn.ReLU(),
            torch.nn.Linear(in_features=32, out_features=1),
        )

    #定义神经网络计算过程
    def forward(self, x):
        return self.fc(x)


model = Model()

print(model(torch.randn(8, 2)).shape)

与上一个任务不一样的是,最后一层网络它是一个全连接神经网络,并且输出值为一个神经元

训练模型

python 复制代码
def train():
    #优化器,根据梯度调整模型参数
    optimizer = torch.optim.Adam(model.parameters(), lr=1e-4)

    #计算loss的函数
    loss_fun = torch.nn.MSELoss()

    #让model进入train模式,开启dropout等功能
    model.train()

    #全量数据遍历100轮
    for epoch in range(100):

        #按批次遍历loader中的数据
        for i, (x, y) in enumerate(loader):

            #模型计算
            out = model(x)

            #根据计算结果和y的差,计算loss,在计算结果完全正确的情况下,loss为0
            loss = loss_fun(out, y)

            #根据loss计算模型的梯度
            loss.backward()

            #根据梯度调整模型的参数
            optimizer.step()

            #梯度归零,准备下一轮的计算
            optimizer.zero_grad()

        if epoch % 20 == 0:
            print(epoch, loss.item())
            
    #保存模型到磁盘
    torch.save(model, 'model/4.model')

测试

python 复制代码
#测试
#注释的表明不计算模型梯度,节省计算资源
@torch.no_grad()
def test():
    
    #从磁盘加载模型
    model = torch.load('model/4.model')

    #模型进入测试模式,关闭dropout等功能
    model.eval()

    #获取一批数据
    x, y = next(iter(loader))

    #模型计算结果
    out = model(x)

    print(torch.cat([out, y], dim=1))

将刚刚训练好的模型从磁盘上加载进来,获取一批数据,让模型进行计算,并查看模型的一个计算结果是否与真实的y之间是否接近。

相关推荐
科技社12 分钟前
咪咕互娱亮相数字中国峰会:“精品游戏+轻量终端”组合,打开数字娱乐新想象
人工智能
数智化精益手记局1 小时前
拆解物料管理erp系统的核心功能,看物料管理erp系统如何解决库存积压与缺料难题
大数据·网络·人工智能·安全·信息可视化·精益工程
Flying pigs~~1 小时前
RAG 完整面试指南:原理、优化、幻觉解决方案
人工智能·prompt·rag·智能体·检索增强生成·rag优化
博.闻广见1 小时前
AI_概率统计-2.常见分布
人工智能·机器学习
企业架构师老王1 小时前
2026制造业安全生产隐患识别AI方案:从主流产品对比看企业级AI Agent的非侵入式落地路径
人工智能·安全·ai
Aleeeeex2 小时前
RAG 那点事:从 8 份企业文档到能用的问答系统,全过程拆给你看
人工智能·python·ai编程
冬奇Lab2 小时前
一天一个开源项目(第87篇):Tank-OS —— Red Hat 工程师用一个周末,把 AI Agent 塞进了一个可启动的 Linux 镜像
人工智能·开源·资讯
小糖学代码2 小时前
LLM系列:2.pytorch入门:8.神经网络的损失函数(criterion)
人工智能·深度学习·神经网络
Jmayday2 小时前
Pytorch:RNN理论基础
pytorch·rnn·深度学习
Captaincc2 小时前
转发-中央网信办部署开展“清朗·整治AI应用乱象”专项行动
人工智能·vibecoding