百度松果飞浆大作业--图像分类

一、问题背景        

        基于Caltech数据集的图像分类,Caltech101包含101个目标类+背景类,每种类别大约40到800个图像,训练集总计7999图像。本次试题需要图片为输入,通过课程学习的分类方法(支持向量机、深度神经网络、卷积神经网络等)从中识别该图像属于哪一个类别。

二、代码实现

2.1数据预处理

2.1.1解压数据集

!unzip /home/aistudio/data/data146107/dataset.zip -d /home/aistudio/data

2.1.2导入所需的包

# 导入需要的包
import paddle
import os 
import numpy as np
from PIL import Image
import matplotlib.pyplot as plt
import sys
import pickle
from paddle.vision.transforms import ToTensor
import paddle.nn.functional as F
print("本教程基于Paddle的版本号为:"+paddle.__version__)
# 本方案基于paddlepaddle2.2.2实现

2.1.3划分好数据集

from sklearn.utils import shuffle

total_list = []

# 打开 train.txt 文件并读取内容
f = open('/home/aistudio/data/dataset/train.txt', 'r', encoding='utf-8')
total_list = f.readlines()
f.close()

# 随机打乱数据
total_list = shuffle(total_list, random_state=100)

# 确定训练集和验证集的长度
train_len = int(0.85 * 7999)

# 划分训练集和验证集
train_list = total_list[:train_len]
val_list = total_list[train_len:]

# 打开 train1.txt 和 val.txt 文件用于写入
f1 = open('/home/aistudio/data/dataset/train1.txt', 'w', encoding='utf-8')
f2 = open('/home/aistudio/data/dataset/val.txt', 'w', encoding='utf-8')

# 将训练集写入 train1.txt 文件
for line in train_list:
    f1.write(line)

# 将验证集写入 val.txt 文件
for line in val_list:
    f2.write(line)

# 关闭文件
f1.close()
f2.close()

2.1.4提取标签label

# 打开 label.txt 文件用于写入
f3 = open('/home/aistudio/data/dataset/label.txt', 'w', encoding='utf-8')

# 打开 class.txt 文件用于读取
f = open('/home/aistudio/data/dataset/class.txt', 'r', encoding='utf-8')

# 逐行读取 class.txt 文件内容
for line in f.readlines():
    # 去除每行两端的空白符并按制表符 '\t' 分割字符串,获取标签名称和标签ID
    label_name, label_id = line.strip().split('\t')
    
    # 将标签名称写入 label.txt 文件,并在每个标签后添加换行符
    f3.write(label_name + '\n')
    
# 关闭 label.txt 文件
f3.close()

 2.1.5安装paddlex(最新版)

!pip install paddlex

2.1.6数据增强

from paddlex import transforms as T

# 训练集数据变换列表
train_transforms = T.Compose([
    T.RandomHorizontalFlip(),  # 随机水平翻转
    T.RandomVerticalFlip(),    # 随机垂直翻转
    T.MixupImage(alpha=1.5, beta=1.5, mixup_epoch=-1),  # Mixup增强,alpha和beta调整混合强度,mixup_epoch设置为-1表示在所有训练时期都应用Mixup
    T.RandomBlur(prob=0.1),    # 以0.1的概率对图像进行随机模糊处理
    T.RandomDistort(),         # 随机扭曲图像
    T.Normalize(),             # 图像归一化处理
    T.Resize(224)              # 调整图像大小为224x224像素
])

# 评估集数据变换列表
eval_transforms = T.Compose([
    T.Normalize(),  # 图像归一化处理
    T.Resize(224)   # 调整图像大小为224x224像素
])

        如果这一步发生报错请将pyarrow包降版本为0.17.0版本或更高一点点的版本。0.17.0版本测试是可以通过的。

2.1.7构建数据集

import paddlex as pdx

# 创建训练集
train_dataset = pdx.datasets.ImageNet(
    data_dir='/home/aistudio/data/dataset/images/',  # 数据集存储路径
    file_list='/home/aistudio/data/dataset/train1.txt',  # 训练集文件列表路径
    label_list='/home/aistudio/data/dataset/label.txt',  # 标签文件路径
    transforms=train_transforms,  # 训练集数据变换方式
    shuffle=True  # 是否对数据进行随机打乱
)

# 创建验证集
eval_dataset = pdx.datasets.ImageNet(
    data_dir='/home/aistudio/data/dataset/images/',  # 数据集存储路径
    file_list='/home/aistudio/data/dataset/val.txt',  # 验证集文件列表路径
    label_list='/home/aistudio/data/dataset/label.txt',  # 标签文件路径
    transforms=eval_transforms  # 验证集数据变换方式
)

# 创建总数据集(包含训练集和验证集)
total_dataset = pdx.datasets.ImageNet(
    data_dir='/home/aistudio/data/dataset/images/',  # 数据集存储路径
    file_list='/home/aistudio/data/dataset/train.txt',  # 总数据集文件列表路径
    label_list='/home/aistudio/data/dataset/label.txt',  # 标签文件路径
    transforms=train_transforms,  # 总数据集数据变换方式
    shuffle=True  # 是否对数据进行随机打乱
)

2.2模型训练

2.2.1设置超参数并训练

num_classes = len(train_dataset.labels)  # 获取数据集的类别数量,用于模型的输出类别数

# 使用 PaddleX 提供的 ResNet101_vd_ssld 模型,传入类别数作为参数
model = pdx.cls.ResNet101_vd_ssld(num_classes=num_classes)

# 对模型进行训练
model.train(num_epochs=50,  # 训练的轮数
            train_dataset=train_dataset,  # 训练集数据
            train_batch_size=64,  # 训练时的批量大小
            eval_dataset=eval_dataset,  # 验证集数据
            lr_decay_epochs=[10, 20, 30],  # 学习率衰减的时期
            save_dir='output/resnet101_ssld',  # 模型和日志保存的路径
            label_smoothing=True,  # 是否使用标签平滑(减少过拟合)
            use_vdl=True)  # 是否使用可视化工具进行训练过程的监控和记录

2.2.2测试验证集效果

model = pdx.load_model('output/resnet101_ssld//best_model') # 导入效果最好的模型
model.evaluate(eval_dataset, batch_size=1, return_details=True) # 验证集结果

2.2.3测试全部数据集

# 对模型进行更多轮次的训练(总共 15 轮)
model.train(num_epochs=15,  # 训练的轮数
            train_dataset=total_dataset,  # 使用全部数据集进行训练
            train_batch_size=64,  # 训练时的批量大小
            eval_dataset=eval_dataset,  # 验证集数据
            lr_decay_epochs=[4, 6, 8],  # 学习率衰减的时期
            save_dir='output/resnet101_ssld1',  # 模型和日志保存的路径
            label_smoothing=True,  # 是否使用标签平滑(减少过拟合)
            use_vdl=True)  # 是否使用可视化工具进行训练过程的监控和记录

2.2.4预测测试集

# 导入最佳模型以进行预测
model = pdx.load_model('output/resnet101_ssld/best_model')  # 加载第一次训练最佳模型
#model = pdx.load_model('output/resnet101_ssld1/best_model')  # 加载第二次训练最佳模型

test_path = "/home/aistudio/data/dataset/images/"  # 测试集图片路径
test_files = []

# 读取测试集文件列表
f = open('/home/aistudio/data/dataset/test.txt', 'r', encoding='utf-8')
for line in f.readlines():
    test_files.append(test_path + line.strip())  # 将测试集文件路径添加到列表中
f.close()

# 使用模型进行预测
result = model.predict(img_file=test_files, transforms=eval_transforms)  # 对测试集图片进行预测

print("Predict Result:\n", result)  # 打印预测结果

2.3.5将结果写入result.txt文件

f = open('/home/aistudio/result.txt', 'w', encoding='utf-8')  # 打开文件用于写入预测结果
k = 0

# 遍历预测结果并写入文件
for d in result:
    img_name = test_files[k].split('/')[-1]  # 获取图片文件名
    f.write(img_name + '\t' + str(d[0]['category_id']) + '\n')  # 写入图片名和对应的预测类别ID
    k += 1

f.close()  # 关闭文件

三、项目地址

github:百度松果飞浆大作业--图像分类

paddlepaddle:百度松果飞浆大作业--图像分类

猜你喜欢

转载自blog.csdn.net/w2563216521/article/details/134604654