PyTorch基础5——自定义损失函数

该博客介绍了如何在PyTorch中自定义交叉熵损失函数并应用于神经网络训练。首先,定义了一个名为MyEntropyLoss的自定义损失函数,实现了交叉熵损失的计算。接着,加载了MNIST数据集,定义了一个简单的卷积神经网络,并使用自定义的损失函数和Adam优化器进行训练。在训练过程中,每20个epoch打印一次损失值。最后,博客提到了模型验证和权重保存的步骤,但未给出具体实现。
摘要由CSDN通过智能技术生成

自定义损失函数

自定义损失函数与自定义网络类似。需要继承nn.Module类,然后重写forward方法即可

# 自定义损失函数,交叉熵损失函数
class MyEntropyLoss(nn.Module):

    def forward(self,output,target):
        batch_size_ = output.size()[0] # 获得batch_size
        num_class = output[0].size()[0] #获得类别数量
        label_one_hot = functional.one_hot(target, num_classes=num_class) #转换为独热吗

        loss = (output-label_one_hot)**2/num_class #计算交叉熵损失
        return torch.sum(loss)/batch_size_ #计算平均损失值
import torch
from torch import nn
from torchvision import datasets, transforms #导入Mnist数据集
from torch.nn import functional

BATCH_SIZE = 20



# step1.加载数据
# 预先定义对每张图片进行变换规则
transforms = transforms.Compose([
                  transforms.ToTensor(), #转换为张量结构
                  transforms.Normalize((0.1037,), (0.3081,)) #对数据进行标准化
              ])
# 获取数据集
train_dataset = datasets.MNIST('data', train = True, download = True,transform = transforms )
# 将数据导入迭代器DataLoader之中, shuffle表示是否要将数据打乱
train_loader = torch.utils.data.DataLoader(train_dataset,batch_size = BATCH_SIZE, shuffle = True)



# step2.定义网络结构
# 定义一个网络
class Model(nn.Module):
    def __init__(self,class_num,input_channel=3):
        super(Model, self).__init__()
        self.conv1 = nn.Conv2d(in_channels=input_channel, out_channels=32, kernel_size=3) #卷积
        self.pool = nn.MaxPool2d(kernel_size=2, stride=2) # 池化
        self.conv2 = nn.Conv2d(in_channels=32, out_channels=64, kernel_size=5) #卷积
        self.dropout = nn.Dropout2d(p=0.1) # dropout
        self.adaptive_pool = nn.AdaptiveMaxPool2d((1, 1)) #全局池化
        self.flatten = nn.Flatten()
        self.linear1 = nn.Linear(64, 32) #线性层
        self.relu = nn.ReLU()
        self.linear2 = nn.Linear(32, class_num) #最终分了多少个类
        self.sigmoid = nn.Sigmoid()

    def forward(self, x):
        x = self.conv1(x)
        x = self.pool(x)
        x = self.conv2(x)
        x = self.pool(x)
        x = self.dropout(x)
        x = self.adaptive_pool(x)
        x = self.flatten(x)
        x = self.linear1(x)
        x = self.relu(x)
        x = self.linear2(x)
        y = self.sigmoid(x)
        return y
# 只识别10个,且输入通道为1
net = Model(class_num=10,input_channel=1)
# print(net)



# 自定义损失函数,交叉熵损失函数
class MyEntropyLoss(nn.Module):

    def forward(self,output,target):
        batch_size_ = output.size()[0]
        num_class = output[0].size()[0] #获得类别数量
        label_one_hot = functional.one_hot(target, num_classes=num_class) #转换为独热吗

        loss = (output-label_one_hot)**2/num_class
        return torch.sum(loss)/batch_size_

# step3.定义损失函数,梯度下降算法
# 定义损失函数
# loss_func = nn.CrossEntropyLoss()
loss_func = MyEntropyLoss()


# 定义梯度下降的优化器Adam
optimizer = torch.optim.Adam(params=net.parameters(),lr = 0.01)

for params in net.parameters():
    params.requires_grad = True

# 训练100个epoch
for epoch_num in range(100):

    for i,(each_data,each_label) in enumerate(train_loader):

        # 梯度清零,这一步必须要操作,因为不操作则会保留上一次训练的信息
        optimizer.zero_grad()

        # each_data # 获取数据
        # each_label # 获取标签

        # step4.进行前向传播,获取预测值
        pred = net(each_data) # 预测的结果

        # step5.计算损失函数,反向传播,进行梯度下降,将之前的梯度清空
        loss = loss_func(pred,each_label) # 计算损失值
        loss.backward() # 反向传播,求梯度
        optimizer.step() # 进行梯度下降

        if i%20 ==0:
            print(f"Epoch:{epoch_num} {i} , loss:{loss.item()}")

    # step6.验证结果的准确率
    # 训练完成之后进行验证。
    # ....


    # step7.保存模型权重
    # 保存权重,权重文件是一个字典
    params_dict = net.state_dict()
    torch.save(params_dict,"net.pth")

  • 0
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值