(4) Acerca de la implementación de pérdidas y algunos obstáculos encontrados en el proceso de construcción de la red

Hablemos primero de la pérdida: en el código anterior, utilizamos la función de pérdida de cálculo oficial, la función de pérdida de entropía cruzada.

criterio = antorcha.nn.CrossEntropyLoss()

La función de pérdida de entropía cruzada consta principalmente de tres partes, softmax--->log---->nll_loss. Si tengo tiempo, escribiré un artículo para presentarlo. El código de implementación es el siguiente: Lo que defino es una clase, pero en realidad bastará con definir una función.

class Compute_Loss(nn.Module):
    def __init__(self):
        super(Compute_Loss, self).__init__()

    def forward(self, pred, target):
        pred = pred.to(device)
        target = target.to(device)
        log_soft = F.log_softmax(pred, dim=1)
        loss = F.nll_loss(log_soft, target)
        return loss

Algunas trampas:

1. La última capa de la red resnet18 construida antes es la capa fc completamente conectada. Agregué una capa softmax detrás de la capa fc y descubrí que la pérdida no se podía reducir. Lo verifiqué en línea y lo combiné con la composición de nn. .función de pérdida de crosentropía. Descubra:

  • La puntuación de confianza de entrada ( input) para cada clase debe ser cruda, no maximizada ni normalizada. La razón es que esta función primero ejecutará softmax en la puntuación original de la entrada, por lo que se debe garantizar que la entrada sea la puntuación original de cada categoría. Y el objetivo de entrada no puede tener la forma de codificación one_hot.

2. De la misma manera, agregué una capa Relu detrás de la capa FC, pero la pérdida tampoco se puede reducir, puede ser que los datos después de relu tengan un impacto al calcular la pérdida.

3. Al construir la red, use la capa nn.Linear () directamente en el futuro. Cuando use la GPU para entrenamiento, se informará un error que muestra que los datos están en la GPU pero el modelo no está en la GPU. aunque configuré model.to("cuda") Es inútil, por lo que debes definir nn.Linear() al definir las variables integradas de la clase y luego llamarlo hacia adelante.

Defina su propia función de pérdida. Aunque esto es una imitación de nn.crossentropy(), también puede crear su propia clase de función de pérdida para calcular la pérdida.

Código:

import torch
from torchvision import datasets, transforms, models
import os
import matplotlib.pyplot as plt
import torch.optim as optim
import torch.nn.functional as F
import numpy as np
from PIL import Image, ImageFile
from my_resnet import MainNet
import torch.nn.functional as F
import torch.nn as nn
ImageFile.LOAD_TRUNCATED_IMAGES = True
os.environ["KMP_DUPLICATE_LIB_OK"] = "TRUE"


def train():
    running_loss = 0
    for batch_idx, (data, target) in enumerate(train_data):
        data, target = data.to(device), target.to(device)
        out = net(data)
        loss = criterion(out, target)
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        running_loss += loss.item()

    return running_loss


def test():
    correct, total = 0, 0
    with torch.no_grad():
        for _, (data, target) in enumerate(val_data):
            data, target = data.to(device), target.to(device)
            out = net(data)
            out = F.softmax(out, dim=1)
            prediction = out.argmax(dim=1)
            # prediction = torch.max(out.data, dim=1)[1]
            total += target.size(0)
            correct += (prediction == target).sum().item()
        print('Accuracy on test set: (%d/%d)=%d %%' % (correct, total, 100 * correct / total))


class Compute_Loss(nn.Module):
    def __init__(self):
        super(Compute_Loss, self).__init__()

    def forward(self, pred, target):
        pred = pred.to(device)
        target = target.to(device)
        log_soft = F.log_softmax(pred, dim=1)
        loss = F.nll_loss(log_soft, target)
        return loss




if __name__ == '__main__':
    loss_list = []
    Epoches = 200
    Batch_Size = 4
    Image_Size = [256, 256]

    # 1.数据加载
    data_dir = r'D:\Code\python\完整项目放置\classify_project\multi_classification\my_dataset1'
    # 1.1 定义要对数据进行的处理
    data_transform = {x: transforms.Compose([transforms.Resize(Image_Size), transforms.ToTensor()]) for x in
                      ["train", "valid"]}
    image_datasets = {x: datasets.ImageFolder(root=os.path.join(data_dir, x), transform=data_transform[x]) for x in
                      ["train", "valid"]}
    dataloader = {x: torch.utils.data.DataLoader(dataset=image_datasets[x], batch_size=Batch_Size, shuffle=True) for x in
                  ["train", "valid"]}
    train_data, val_data = dataloader["train"], dataloader["valid"]

    index_classes = image_datasets["train"].class_to_idx
    print(index_classes)
    example_classes = image_datasets["train"].classes
    print(example_classes)

    num_classes = 3
    net = MainNet(num_classes)

    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
    net.to(device)

    # 5.定义损失函数,以及优化器
    LR = 0.0001
    criterion = Compute_Loss()
    optimizer = optim.Adam(net.parameters(), lr=LR)

    best_loss = 100
    for epoch in range(Epoches):
        loss = train()
        loss_list.append(loss)
        print("第%d轮的loss为:%5f:" % (epoch, loss))
        test()

        if loss < best_loss:
            best_loss = loss
            torch.save(net, "best1.pth")
        torch.save(net, "last1.pth")


    plt.title("Graph")
    plt.plot(range(Epoches), loss_list)
    plt.ylabel("loss")
    plt.xlabel("epoch")
    plt.show()

Supongo que te gusta

Origin blog.csdn.net/m0_48095841/article/details/125751332
Recomendado
Clasificación