图像分类保姆级教程-深度学习入门教程(附全部代码)

简介: 图像分类保姆级教程-深度学习入门教程(附全部代码)

数据处理

图像二分类涉及到数据的处理,需要将图像转换为计算机可以识别的数字格式。通常使用的方法是将每个图像转换为一个多维数组,每个像素点的值代表该像素点的颜色强度。对于彩色图像,通常有三个通道(红色、绿色、蓝色),因此对于每个像素点,需要有三个值来表示它的颜色。\

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')


推理预测

通过加载之前保存的权重,可以使用模型进行推理预测。对于新的图像,需要将其转换为多维数组的形式,并传递给模型进行预测。


预测结果通常是一个概率值,表示该图像属于正样本的概率。可以设置阈值来确定判断标准,如当概率值大于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)


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. 数据预处理:
   - 进行适当的数据预处理操作,例如调整图像大小、裁剪、归一化等。
   - 使用相同的数据预处理操作来处理训练
相关文章
|
3月前
|
机器学习/深度学习 算法 定位技术
Baumer工业相机堡盟工业相机如何通过YoloV8深度学习模型实现裂缝的检测识别(C#代码UI界面版)
本项目基于YOLOv8模型与C#界面,结合Baumer工业相机,实现裂缝的高效检测识别。支持图像、视频及摄像头输入,具备高精度与实时性,适用于桥梁、路面、隧道等多种工业场景。
308 27
|
机器学习/深度学习 编解码 人工智能
人脸表情[七种表情]数据集(15500张图片已划分、已标注)|适用于YOLO系列深度学习分类检测任务【数据集分享】
本数据集包含15,500张已划分、已标注的人脸表情图像,覆盖惊讶、恐惧、厌恶、高兴、悲伤、愤怒和中性七类表情,适用于YOLO系列等深度学习模型的分类与检测任务。数据集结构清晰,分为训练集与测试集,支持多种标注格式转换,适用于人机交互、心理健康、驾驶监测等多个领域。
|
2月前
|
机器学习/深度学习 人工智能 监控
河道塑料瓶识别标准数据集 | 科研与项目必备(图片已划分、已标注)| 适用于YOLO系列深度学习分类检测任务【数据集分享】
随着城市化进程加快和塑料制品使用量增加,河道中的塑料垃圾问题日益严重。塑料瓶作为河道漂浮垃圾的主要类型,不仅破坏水体景观,还威胁水生生态系统的健康。传统的人工巡查方式效率低、成本高,难以满足实时监控与治理的需求。
|
2月前
|
机器学习/深度学习 传感器 人工智能
火灾火焰识别数据集(2200张图片已划分、已标注)|适用于YOLO系列深度学习分类检测任务【数据集分享】
在人工智能和计算机视觉的快速发展中,火灾检测与火焰识别逐渐成为智慧城市、公共安全和智能监控的重要研究方向。一个高质量的数据集往往是推动相关研究的核心基础。本文将详细介绍一个火灾火焰识别数据集,该数据集共包含 2200 张图片,并已按照 训练集(train)、验证集(val)、测试集(test) 划分,同时配有对应的标注文件,方便研究者快速上手模型训练与评估。
火灾火焰识别数据集(2200张图片已划分、已标注)|适用于YOLO系列深度学习分类检测任务【数据集分享】
|
2月前
|
机器学习/深度学习 人工智能 自动驾驶
7种交通场景数据集(千张图片已划分、已标注)|适用于YOLO系列深度学习分类检测任务【数据集分享】
在智能交通与自动驾驶技术快速发展的今天,如何高效、准确地感知道路环境已经成为研究与应用的核心问题。车辆、行人和交通信号灯作为城市交通系统的关键元素,对道路安全与交通效率具有直接影响。然而,真实道路场景往往伴随 复杂光照、遮挡、多目标混杂以及交通信号状态多样化 等挑战,使得视觉识别与检测任务难度显著增加。
|
2月前
|
机器学习/深度学习 人工智能 监控
坐姿标准好坏姿态数据集(图片已划分、已标注)|适用于YOLO系列深度学习分类检测任务【数据集分享】
坐姿标准好坏姿态数据集的发布,填补了计算机视觉领域在“细分健康行为识别”上的空白。它不仅具有研究价值,更在实际应用层面具备广阔前景。从青少年的健康教育,到办公室的智能提醒,再到驾驶员的安全监控和康复训练,本数据集都能发挥巨大的作用。
坐姿标准好坏姿态数据集(图片已划分、已标注)|适用于YOLO系列深度学习分类检测任务【数据集分享】
|
2月前
|
机器学习/深度学习 编解码 人工智能
102类农业害虫数据集(20000张图片已划分、已标注)|适用于YOLO系列深度学习分类检测任务【数据集分享】
在现代农业发展中,病虫害监测与防治 始终是保障粮食安全和提高农作物产量的关键环节。传统的害虫识别主要依赖人工观察与统计,不仅效率低下,而且容易受到主观经验、环境条件等因素的影响,导致识别准确率不足。
|
24天前
|
机器学习/深度学习 数据采集 编解码
基于深度学习分类的时相关MIMO信道的递归CSI量化(Matlab代码实现)
基于深度学习分类的时相关MIMO信道的递归CSI量化(Matlab代码实现)
|
机器学习/深度学习 人工智能 文字识别
中药材图像识别数据集(100类,9200张)|适用于YOLO系列深度学习分类检测任务
本数据集包含9200张中药材图像,覆盖100类常见中药材,适用于YOLO系列及主流深度学习模型的图像分类与目标检测任务。数据已划分为训练集(8000张)与验证集(1200张),采用标准文件夹结构和简体中文命名,适配PyTorch、TensorFlow等框架,可用于中药识别系统开发、医学辅助诊断、移动端图像识别App研发及AI科研训练,具备较强的实用性与拓展性。
563 45
|
16天前
|
机器学习/深度学习 算法 vr&ar
【深度学习】基于最小误差法的胸片分割系统(Matlab代码实现)
【深度学习】基于最小误差法的胸片分割系统(Matlab代码实现)

热门文章

最新文章