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

分类

创建测试数据

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之间是否接近。

相关推荐
wuhanwhite1 小时前
2025:OpenAI的“七十二变”?
人工智能·openai·语音识别
XianxinMao1 小时前
BitNet a4.8:通过4位激活实现1位大语言模型的高效内存推理
人工智能·语言模型·自然语言处理
一水鉴天2 小时前
智能工厂的设计软件 应用场景的一个例子:为AI聊天工具添加一个知识系统 之11 方案再探之2 项目文件(修改稿1)
人工智能
KeyPan2 小时前
【视觉SLAM:八、后端Ⅰ】
人工智能·数码相机·算法·机器学习·计算机视觉
StarCap2 小时前
【论文阅读】Reducing Activation Recomputation in Large Transformer Models
论文阅读·深度学习·transformer
好评笔记2 小时前
多模态论文笔记——Coca(副)
论文阅读·人工智能·深度学习·计算机视觉·transformer·coca·dalle2
好评笔记2 小时前
多模态论文笔记——Coca
人工智能·深度学习·计算机视觉·aigc·transformer·多模态·coca
何大春2 小时前
Quo Vadis, Anomaly Detection? LLMs and VLMs in the Spotlight 论文阅读
论文阅读·人工智能·深度学习·论文笔记
Jackilina_Stone2 小时前
【论文阅读笔记】SCI算法与代码 | 低照度图像增强 | 2022.4.21
论文阅读·人工智能·笔记·python·算法·计算机视觉
图王大胜3 小时前
模型 九屏幕分析法
人工智能·解决方案·管理·决策·战略规划·企业发展·分析方法