이미지 분류 유모 수준 튜토리얼 - 딥 러닝 입문 튜토리얼(모든 코드 첨부)

데이터 처리

이미지 2차 분류에는 이미지를 컴퓨터에서 인식할 수 있는 디지털 형식으로 변환해야 하는 데이터 처리가 포함됩니다. 일반적으로 사용되는 방법은 각 이미지를 다차원 배열로 변환하는 것입니다. 여기서 각 픽셀의 값은 해당 픽셀의 색상 강도를 나타냅니다. 컬러 이미지의 경우 일반적으로 3개의 채널(빨간색, 녹색, 파란색)이 있으므로 각 픽셀마다 해당 색상을 표현하기 위해 3개의 값이 필요합니다. \

이미지 분류에 대한 이미지 검색결과

from torchvision import transforms

# 定义数据预处理的操作
data_transforms = {
    'train': transforms.Compose([
        # 针对训练集的数据预处理操作
        transforms.RandomResizedCrop(224),  # 随机裁剪并调整大小为 224x224 像素
        transforms.RandomHorizontalFlip(),  # 随机水平翻转
        transforms.ToTensor(),  # 转换为张量格式
        # 对图像进行标准化,使用均值 [0.485, 0.456, 0.406] 和标准差 [0.229, 0.224, 0.225]
        transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
    ]),
    'val': transforms.Compose([
        # 针对验证集的数据预处理操作
        transforms.Resize(256),  # 调整图像大小为 256x256 像素
        transforms.CenterCrop(224),  # 中心裁剪为 224x224 像素
        transforms.ToTensor(),  # 转换为张量格式
        # 对图像进行标准化,使用均值 [0.485, 0.456, 0.406] 和标准差 [0.229, 0.224, 0.225]
        transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
    ]),
    'test': transforms.Compose([
        # 针对测试集的数据预处理操作(通常与验证集相似)
        transforms.Resize(256),  # 调整图像大小为 256x256 像素
        transforms.CenterCrop(224),  # 中心裁剪为 224x224 像素
        transforms.ToTensor(),  # 转换为张量格式
        # 对图像进行标准化,使用均值 [0.485, 0.456, 0.406] 和标准差 [0.229, 0.224, 0.225]
        transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
    ]),
}


데이터 레이아웃

이미지 이진 분류에서 데이터 세트는 일반적으로 훈련 세트와 테스트 세트로 구분됩니다. 학습 세트는 모델을 훈련하는 데 사용되고, 테스트 세트는 모델 성능을 평가하는 데 사용됩니다. 데이터 세트는 특정 비율에 따라 두 부분으로 나누어야 합니다. 일반적인 비율은 데이터 세트의 80%를 훈련에 사용하고 20%를 테스트에 사용하는 것입니다. 또한 지도 학습을 위해 데이터에 양성 또는 음성 샘플로 레이블을 지정해야 합니다.

- img (主文件夹)
    - train (训练数据子文件夹)
        - 猫 (猫类别的训练样本)
            - cat1.jpg
            - cat2.jpg
            - ...
        - 狗 (狗类别的训练样本)
            - dog1.jpg
            - dog2.jpg
            - ...
        - 兔子 (兔子类别的训练样本)
            - rabbit1.jpg
            - rabbit2.jpg
            - ...
    - val (验证数据子文件夹)
        - 猫 (猫类别的验证样本)
            - cat101.jpg
            - cat102.jpg
            - ...
        - 狗 (狗类别的验证样本)
            - dog101.jpg
            - dog102.jpg
            - ...
        - 兔子 (兔子类别的验证样本)
            - rabbit101.jpg
            - rabbit102.jpg
            - ...

기차

Keras 또는 PyTorch와 같은 딥 러닝 프레임워크를 사용하면 기존 이미지 분류 모델을 쉽게 호출하여 교육할 수 있습니다.

  1. 모델을 훈련하기 전에 모델 아키텍처, 하이퍼파라미터, 손실 함수, 옵티마이저 등을 설정해야 합니다. GPU 가속을 사용하여 훈련 시간을 단축할 수 있습니다.

  2. 훈련 과정에서는 일반적으로 더 나은 성능을 얻기 위해 모델과 하이퍼파라미터를 반복적으로 조정해야 합니다.

def train_model(model, criterion, optimizer, scheduler, num_epochs=25):
    since = time.time()

    best_model_wts = copy.deepcopy(model.state_dict())
    best_acc = 0.0

    for epoch in range(num_epochs):
        print(f'Epoch {epoch}/{num_epochs - 1}')
        print('-' * 10)

        # Each epoch has a training and validation phase
        for phase in ['train', 'val']:
            if phase == 'train':
                model.train()  # Set model to training mode
            else:
                model.eval()   # Set model to evaluate mode

            running_loss = 0.0
            running_corrects = 0

            # Iterate over data.
            for inputs, labels in dataloaders[phase]:
                inputs = inputs.to(device)
                labels = labels.to(device)

                # zero the parameter gradients
                optimizer.zero_grad()

                # forward
                # track history if only in train
                with torch.set_grad_enabled(phase == 'train'):
                    outputs = model(inputs)
                    _, preds = torch.max(outputs, 1)
                    loss = criterion(outputs, labels)

                    # backward + optimize only if in training phase
                    if phase == 'train':
                        loss.backward()
                        optimizer.step()

                # statistics
                running_loss += loss.item() * inputs.size(0)
                running_corrects += torch.sum(preds == labels.data)
            if phase == 'train':
                scheduler.step()

            epoch_loss = running_loss / dataset_sizes[phase]
            epoch_acc = running_corrects.double() / dataset_sizes[phase]

            print(f'{phase} Loss: {epoch_loss:.4f} Acc: {epoch_acc:.4f}')

            # deep copy the model
            if phase == 'val' and epoch_acc > best_acc:
                best_acc = epoch_acc
                best_model_wts = copy.deepcopy(model.state_dict())

        print()

가중치 저장

훈련이 완료된 후에는 모델의 가중치를 저장해야 합니다. 이러한 가중치에는 모델이 학습한 지식이 포함되어 있으며 나중에 추론 예측이나 지속적인 교육에 사용할 수 있습니다. 딥러닝 프레임워크에서 제공하는 API를 사용하여 모델 가중치를 하드 디스크에 저장할 수 있습니다.

model_ft = train_model(model_ft, criterion, optimizer_ft, exp_lr_scheduler,
                       num_epochs=25)
torch.save(model_ft,'model1.pth')

이미지 분류에 대한 이미지 검색결과

추론 예측

이전에 저장한 가중치를 로드하면 모델을 사용하여 추론적 예측을 할 수 있습니다. 새로운 이미지의 경우 다차원 배열로 변환하고 예측을 위해 모델에 전달해야 합니다.

이미지 분류에 대한 이미지 검색결과

예측 결과는 일반적으로 이미지가 양성 샘플에 속할 확률을 나타내는 확률 값입니다. 판단 기준을 정하기 위해 임계값(threshold)을 설정할 수 있는데, 예를 들어 확률값이 0.5보다 크면 양성 표본으로 간주한다.

import torchvision

#from model import Tudui
import torch
from PIL import Image
img_pth="qua_2.jpg"
true_label=img_pth

# 读取图像
img = Image.open(img_pth)
# 数据预处理

# 缩放
transform = torchvision.transforms.Compose([torchvision.transforms.Resize((32, 32)),
                                            torchvision.transforms.ToTensor()])
image = transform(img)
print(image.shape)

# 根据保存方式加载
model = torch.load("model.pth", map_location=torch.device('cpu'))

# 注意维度转换,单张图片
image1 = torch.reshape(image, (1, 3, 32, 32))

# 测试开关
model.eval()
# 节约性能
with torch.no_grad():
    output = model(image1)
    _, preds = torch.max(output, 1)
print(output)
# print(output.argmax(1))
# 定义类别对应字典
dist = {0: "不合格", 1: "合格"}
# 转numpy格式,列表内取第一个
#a = dist[output.argmax(1).numpy()[0]]
a = dist[preds.numpy()[0]]
# img.show()
print(a)
print("input_label:",true_label)

모든 코드

훈련 부분:



from __future__ import print_function, division

import torch
import torch.nn as nn
import torch.optim as optim
from torch.optim import lr_scheduler
import torch.backends.cudnn as cudnn
import numpy as np
import torchvision
from torchvision import datasets, models, transforms
import matplotlib.pyplot as plt
import time
import os
import copy
import pandas as pd

cudnn.benchmark = True
plt.ion()   # interactive mode


data_transforms = {
    'train': transforms.Compose([
        transforms.RandomResizedCrop(224),
        transforms.RandomHorizontalFlip(),
        transforms.ToTensor(),
        transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
    ]),
    'val': transforms.Compose([
        transforms.Resize(256),
        transforms.CenterCrop(224),
        transforms.ToTensor(),
        transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
    ]),
    'test': transforms.Compose([
        transforms.Resize(256),
        transforms.CenterCrop(224),
        transforms.ToTensor(),
        transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
    ]),
}

data_dir = 'data'#####################修改输入路径
image_datasets = {x: datasets.ImageFolder(os.path.join(data_dir, x),
                                          data_transforms[x])
                  for x in ['train', 'val', 'test']}
dataloaders = {x: torch.utils.data.DataLoader(image_datasets[x], batch_size=4,
                                             shuffle=True, num_workers=4)
              for x in ['train', 'val', 'test']}
dataset_sizes = {x: len(image_datasets[x]) for x in ['train', 'val', 'test']}
class_names = image_datasets['train'].classes



device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")

def imshow(inp, title=None):
    """Imshow for Tensor."""
    inp = inp.numpy().transpose((1, 2, 0))
    mean = np.array([0.485, 0.456, 0.406])
    std = np.array([0.229, 0.224, 0.225])
    inp = std * inp + mean
    inp = np.clip(inp, 0, 1)
    plt.imshow(inp)
    if title is not None:
        plt.title(title)
    plt.pause(0.001)  # pause a bit so that plots are updated


# Get a batch of training data
inputs, classes = next(iter(dataloaders['train']))

# Make a grid from batch
out = torchvision.utils.make_grid(inputs)

imshow(out, title=[class_names[x] for x in classes])



def train_model(model, criterion, optimizer, scheduler, num_epochs=25):
    since = time.time()

    best_model_wts = copy.deepcopy(model.state_dict())
    best_acc = 0.0

    for epoch in range(num_epochs):
        print(f'Epoch {epoch}/{num_epochs - 1}')
        print('-' * 10)

        # Each epoch has a training and validation phase
        for phase in ['train', 'val']:
            if phase == 'train':
                model.train()  # Set model to training mode
            else:
                model.eval()   # Set model to evaluate mode

            running_loss = 0.0
            running_corrects = 0

            # Iterate over data.
            for inputs, labels in dataloaders[phase]:
                inputs = inputs.to(device)
                labels = labels.to(device)

                # zero the parameter gradients
                optimizer.zero_grad()

                # forward
                # track history if only in train
                with torch.set_grad_enabled(phase == 'train'):
                    outputs = model(inputs)
                    _, preds = torch.max(outputs, 1)
                    loss = criterion(outputs, labels)

                    # backward + optimize only if in training phase
                    if phase == 'train':
                        loss.backward()
                        optimizer.step()

                # statistics
                running_loss += loss.item() * inputs.size(0)
                running_corrects += torch.sum(preds == labels.data)
            if phase == 'train':
                scheduler.step()

            epoch_loss = running_loss / dataset_sizes[phase]
            epoch_acc = running_corrects.double() / dataset_sizes[phase]

            print(f'{phase} Loss: {epoch_loss:.4f} Acc: {epoch_acc:.4f}')

            # deep copy the model
            if phase == 'val' and epoch_acc > best_acc:
                best_acc = epoch_acc
                best_model_wts = copy.deepcopy(model.state_dict())

        print()

    time_elapsed = time.time() - since
    print(f'Training complete in {time_elapsed // 60:.0f}m {time_elapsed % 60:.0f}s')
    print(f'Best val Acc: {best_acc:4f}')
    torch.save(best_model_wts,'class.pth')
    # load best model weights
    model.load_state_dict(best_model_wts)
    return model

def getFileList(path):
    for dirpath, dirnames, filenames in os.walk('.'):
    for filename in filenames:
        print(os.path.join(dirpath, filename))
    return filepath


def visualize_model(model, num_images=6):
    was_training = model.training
    model.eval()
    images_so_far = 0
    # fig = plt.figure()

    with torch.no_grad():
        for i, (inputs, labels) in enumerate(dataloaders['val']):
            inputs = inputs.to(device)
            labels = labels.to(device)

            outputs = model(inputs)
            _, preds = torch.max(outputs, 1)

            for j in range(inputs.size()[0]):
                images_so_far += 1
                ax = plt.subplot(num_images//2, 2, images_so_far)
                ax.axis('off')
                ax.set_title(f'predicted: {class_names[preds[j]]}')
                imshow(inputs.cpu().data[j])

                if images_so_far == num_images:
                    model.train(mode=was_training)
                    return
        model.train(mode=was_training)
model_ft = models.resnet18(pretrained=True)
#torch.save(model_ft,'zsl_class')
num_ftrs = model_ft.fc.in_features
# Here the size of each output sample is set to 2.
# Alternatively, it can be generalized to nn.Linear(num_ftrs, len(class_names)).
model_ft.fc = nn.Linear(num_ftrs, 2)

model_ft = model_ft.to(device)

criterion = nn.CrossEntropyLoss()

# Observe that all parameters are being optimized
optimizer_ft = optim.SGD(model_ft.parameters(), lr=0.001, momentum=0.9)

# Decay LR by a factor of 0.1 every 7 epochs
exp_lr_scheduler = lr_scheduler.StepLR(optimizer_ft, step_size=7, gamma=0.1)


model_ft = train_model(model_ft, criterion, optimizer_ft, exp_lr_scheduler,
                       num_epochs=25)
torch.save(model_ft,'model1.pth')
test_model(model_ft)
visualize_model(model_ft)

이 경로를 수정해야 합니다.

data_dir = 'data'

입력 경로 수정

가중치를 저장하는 것을 잊지 마세요

torch.save(model_ft,'model1.pth')

model.pth를 임의로 객체로 이름 지정

예측하다

from __future__ import print_function, division

import torch
import torch.nn as nn
import torch.optim as optim
from torch.optim import lr_scheduler
import torch.backends.cudnn as cudnn
import numpy as np
import torchvision
from torchvision import datasets, models, transforms
import matplotlib.pyplot as plt
import time
import os
import copy




import torchvision

#from model import Tudui
import torch
from PIL import Image
img_pth="qua_2.jpg"
true_label=img_pth

# 读取图像
img = Image.open(img_pth)
# 数据预处理

# 缩放
transform = torchvision.transforms.Compose([torchvision.transforms.Resize((32, 32)),
                                            torchvision.transforms.ToTensor()])
image = transform(img)
print(image.shape)

# 根据保存方式加载
model = torch.load("model.pth", map_location=torch.device('cpu'))

# 注意维度转换,单张图片
image1 = torch.reshape(image, (1, 3, 32, 32))

# 测试开关
model.eval()
# 节约性能
with torch.no_grad():
    output = model(image1)
    _, preds = torch.max(output, 1)
print(output)
# print(output.argmax(1))
# 定义类别对应字典
dist = {0: "不合格", 1: "合格"}
# 转numpy格式,列表内取第一个
#a = dist[output.argmax(1).numpy()[0]]
a = dist[preds.numpy()[0]]
# img.show()
print(a)
print("input_label:",true_label)

요약하다

이미지 이진 분류 작업을 수행할 때 다음 사항에 유의해야 합니다.

  1. 데이터 세트 준비:

    • 모든 이미지가 두 범주 중 하나로 올바르게 레이블이 지정된 레이블이 잘 지정된 데이터세트가 있는지 확인하세요.
    • 데이터 세트의 클래스가 균형을 이루고 있는지 확인하십시오. 즉, 각 클래스에 거의 동일한 수의 샘플이 있는지 확인하십시오.
  2. 데이터 전처리:

    • 이미지 크기 조정, 자르기, 정규화 등과 같은 적절한 데이터 전처리 작업을 수행합니다.

    • grad() 훈련에 동일한 데이터 전처리 작업을 사용합니다 :
      output = model(image1)
      _, preds = torch.max(output, 1)
      print(output)

인쇄(output.argmax(1))

카테고리 해당 사전 정의

dist = {0: "자격 없음", 1: "자격 있음"}

numpy 형식으로 변환하고 목록의 첫 번째 형식을 가져옵니다.

#a = dist[output.argmax(1).numpy()[0]]
a = dist[preds.numpy()[0]]

img.show()

print(a)
print("input_label:",true_label)


## 总结

当进行图像二分类任务时,以下是一些需要注意的要点:

1. 数据集准备:
   - 确保你有一个标注好的数据集,其中每个图像都被正确地标记为两个类别中的一个。
   - 确保数据集中的类别平衡,即每个类别中的样本数量大致相等。

2. 数据预处理:
   - 进行适当的数据预处理操作,例如调整图像大小、裁剪、归一化等。
   - 使用相同的数据预处理操作来处理训练

추천

출처blog.csdn.net/ALiLiLiYa/article/details/135249966