PaddleClas蝴蝶分类

任务描述

近年来,随着人工智能的发展,其在语音识别、自然语言处理、图像与视频分析等诸多领域取得了巨大成功。如何将人工智能技术应用到更广泛的领域成为了重要目标,本次竞赛将聚焦蝴蝶图片的细粒度图像分类,利用人工智能技术,对蝴蝶的类别、属性进行识别分类,以便相关工作者快速识别蝴蝶种类,进行科学研究,提高效率和精度。要求参赛者给出一个算法或模型,对于给定的图片,检测出图片中的蝴蝶类别和属。给定图片数据,选手据此训练模型,为每张测试数据预测出最正确的类别。

数据说明

本竞赛所用训练和测试图片均来自网络(和鲸社区)。总共有9个属,20个物种,文件genus.txt中描述了9个属名,species.txt描述了20个物种名。

数据文件包括训练集(有标注)和测试集(无标注),训练集和验证集的所有图片分别保存在Butterfly20文件夹下面的20个文件夹中,文件名即属-物种标签,测试集共有200张待分类的蝴蝶图片在test文件夹下,名称为:图片ID.jpg。

提交答案

本赛题任务是对蝴蝶图片进行物种分类,要求提交结果的格式如下:

1.每个类别的行数和测试集原始数据行数应一一对应,不可乱序。

2.输出结果应检查是否为200行数据,否则成绩无效。

3.输出结果文件命名为result.txt,一行一个物种标签(物种标号 + . +属+ _ +物种名),样例如下:

‘’’’’’

006.Graphium_agamemnon

014.Meandrusa_sciron

012.Losaria_coon

006.Graphium_agamemnon

011.Lamproptera_meges

018.Papilio_bianor

014.Meandrusa_sciron

017.Papilio_arcturus

003.Byasa_alcinous

001.Atrophaneura_horishanus

‘’’’’’

解决办法

是不是有时候你也为不会高新算法发愁,别担心,飞桨都为你实现好了,下面请看如何用飞桨解决图像分类问题。

采用端到端的PaddleClas来解决
https://github.com/PaddlePaddle/PaddleClas

PaddleClas有多好用就不讲了,大家自己体会体会。

PaddleClas

简介

飞桨图像分类套件PaddleClas是飞桨为工业界和学术界所准备的一个图像分类任务的工具集,助力使用者训练出更好的视觉模型和应用落地。

环境准备

# 克隆PaddleClas并安装依赖项,本notebook已安装
%cd work
!git clone https://gitee.com/PaddlePaddle/PaddleClas.git
%cd /home/aistudio/work/PaddleClas/ 
# !pip install --upgrade -r requirements.txt
#导入一些图像处理的包
%cd /home/aistudio
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import os, shutil, cv2, random
%matplotlib inline
/home/aistudio
!unzip -q data/data66509/Butterfly20_test.zip -d dataset
!unzip -q data/data66509/Butterfly20.zip -d dataset
!rm -rf dataset/__MACOSX/

定义数据集

# 读取label配置
%cd ~
import os
import random
import cv2
import numpy as np
import shutil
import json

with open("dataset/Butterfly20_dict.json",'r') as load_f:
    label_map = json.load(load_f)
    print(label_map)

/home/aistudio
{'0': '001.Atrophaneura_horishanus', '1': '002.Atrophaneura_varuna', '2': '003.Byasa_alcinous', '3': '004.Byasa_dasarada', '4': '005.Byasa_polyeuctes', '5': '006.Graphium_agamemnon', '6': '007.Graphium_cloanthus', '7': '008.Graphium_sarpedon', '8': '009.Iphiclides_podalirius', '9': '010.Lamproptera_curius', '10': '011.Lamproptera_meges', '11': '012.Losaria_coon', '12': '013.Meandrusa_payeni', '13': '014.Meandrusa_sciron', '14': '015.Pachliopta_aristolochiae', '15': '016.Papilio_alcmenor', '16': '017.Papilio_arcturus', '17': '018.Papilio_bianor', '18': '019.Papilio_dialis', '19': '020.Papilio_hermosanus'}
import numpy as np
from PIL import Image
from paddle.vision.transforms import functional as F


for (root , dirs, files ) in os.walk("dataset/Butterfly20", topdown=False):
    for name in files:
        abs_name=os.path.join(root, name)
        print(abs_name)
        img = Image.open(abs_name)
        rotated_img = F.rotate(img, 180)
        print(rotated_img.size)
        fake_name=os.path.join(root,"rotate_"+ name)
        print(fake_name)
        rotated_img.save(fake_name)
import numpy as np
from PIL import Image
from paddle.vision.transforms import ColorJitter



# brightness(float) - 亮度调整范围大小,会从给定参数后的均匀分布[max(0,1 - brightness), 1 + brightness]中随机选择进行实际调整,不能是负数。
# contrast(float) - 对比度调整范围大小,,会从给定参数后的均匀分布[max(0,1 - contrast), 1 + contrast]中随机选择进行实际调整,不能是负数。
# saturation(float) - 饱和度调整范围大小,,会从给定参数后的均匀分布[max(0,1 - saturation), 1 + saturation]中随机选择进行实际调整,不能是负数。
# hue(float) - 色调调整范围大小,,会从给定参数后的均匀分布[-hue, hue]中随机选择进行实际调整,参数值需要在0到0.5之间。
# keys (list[str]|tuple[str], optional) - 与 BaseTransform 定义一致。默认值: None。
# ColorJitter随机调整图像的亮度,对比度,饱和度和色调。
transform = ColorJitter(0.4, 0.4, 0.4, 0.4)

for (root , dirs, files ) in os.walk("dataset/Butterfly20", topdown=False):
    for name in files:
        abs_name=os.path.join(root, name)
        print(abs_name)
        img = Image.open(abs_name)
        rotated_img = transform(img)
        print(rotated_img.size)
        fake_name=os.path.join(root,"ColorJitter_"+ name)
        print(fake_name)
        rotated_img.save(fake_name)
# 将所有训练集的数据都写进一个列表中
# 训练集和测试集路径
data_path = "/home/aistudio/dataset"
train_folder = "Butterfly20"
test_folder = "Butterfly20_test"
data_list = []
for index in range(20):
    # print(index,label_map[str(index)])
    sub_folder=label_map[str(index)]
    abs_sub_folder=os.path.join(data_path, train_folder,sub_folder)
    sub_list=os.listdir(abs_sub_folder)
    for sub_name in sub_list:
        data_list.append(os.path.join(train_folder, sub_folder, sub_name) + ' ' + str(index) + '\n')
    print("Finished train_folder: {}".format(sub_folder))
print("Finished data_list length: {}".format(len(data_list)))

# import os
# import random
# import cv2
# import numpy as np


# 训练集和测试集路径
val_ratio = 0.1

# save file
def save_file(list, txt):
    myfile=os.path.join('dataset',txt)
    if os.path.exists(myfile):
        os.remove(myfile)
    with open(myfile, "a") as f:
        f.writelines(list)


random.shuffle(data_list)
val_number = int(val_ratio * len(data_list))
train_list = data_list[val_number:]
val_list = data_list[0:val_number]
print("full data size: {}   train_list size: {}   val_list size: {}".format(len(data_list), len(data_list)-val_number,val_number))

save_file(train_list,  'train_list.txt')
save_file(val_list,  'test_list.txt')

开始训练

# 选择GPU
%cd /home/aistudio/work/PaddleClas/
%env PYTHONPATH=$PYTHONPATH:.
%env CUDA_VISIBLE_DEVICES=0
/home/aistudio/work/PaddleClas
env: PYTHONPATH=$PYTHONPATH:.
env: CUDA_VISIBLE_DEVICES=0

模型选取

# 由于数据集划分、数据增强的随机性,可能有一些波动,在测试集上>92,最好的模型在验证集大于96应该就没问题
# 配置文件见 ./configs/EfficientNet/EfficientNetB0.yaml
!python -m paddle.distributed.launch \
    --gpus="0" \
    tools/train.py \
        -c ./configs/EfficientNet/EfficientNetB0.yaml \
    --vdl_dir='./scalar'
# 充分利用验证集,学习一些没见过的样本,用全部的训练数据微调1个epoch,去掉label smooth和一些数据增强操作.有一定随机性.
!rm -rf ./scalar_finetune/*
!python -m paddle.distributed.launch \
    --selected_gpus="0" \
    tools/train.py \
        -c ./configs/EfficientNet/EfficientNetB0_finetune.yaml \
        -o pretrained_model='./output/EfficientNetB0/best_model_train/ppcls' \
    --vdl_dir='./scalar_finetune'
You are using Paddle compiled with TensorRT, but TensorRT dynamic library is not found. Ignore this if TensorRT is not needed.
usage: launch.py [-h] [--log_dir LOG_DIR] [--nproc_per_node NPROC_PER_NODE]
                 [--gpus GPUS] [--ips IPS] [--servers SERVERS]
                 [--workers WORKERS] [--heter_workers HETER_WORKERS]
                 [--worker_num WORKER_NUM] [--server_num SERVER_NUM]
                 [--heter_worker_num HETER_WORKER_NUM] [--http_port HTTP_PORT]
                 training_script ...
launch.py: error: unrecognized arguments: --selected_gpus=0

验证\导出模型

此处修复了一些小BUG。PaddleClas的EfficientNet(网络结构位于work/PaddleClas/ppcls/modeling/architectures/efficientnet.py)在验证和导出模型的时候,缺少一个is_test=True参数,默认是False,这会让模型在验证和推理的时候也按设定的概率随机drop_connect,导致产生结果是随机的。

在./tools/export_model.py和./tools/program.py中,为EfficientNet在验证和推理创建模型的时候传入is_test=True即可。

!python -m paddle.distributed.launch \
    --gpus="0" \
    tools/eval.py \
    -o ARCHITECTURE.name="EfficientNetB0" \
    -o pretrained_model='./output/EfficientNetB0/best_model_train/ppcls'
# 导出模型
!python tools/export_model.py \
    --model='EfficientNetB0' \
    --pretrained_model='./output_finetune/EfficientNetB0/best_model_finetune/ppcls' \
    --output_path='./output_finetune/EfficientNetB0_infer'
You are using Paddle compiled with TensorRT, but TensorRT dynamic library is not found. Ignore this if TensorRT is not needed.
export model for EfficientNet

预测\推理

修改./tools/infer/predict.py ,通过for循环读取ID,生成key结果到 /home/aistudio/result_id.txt

大约1min20s

!python tools/infer/predict.py \
    -m=./output_finetune/EfficientNetB0_infer/model \
    -p=./output_finetune/EfficientNetB0_infer/params \
    -i=/home/aistudio/dataset/Butterfly20_test \
    # -i=./dataset/sgt/test/jpg \
inetune/EfficientNetB0_infer/params \
    -i=/home/aistudio/dataset/Butterfly20_test \
    # -i=./dataset/sgt/test/jpg \
    --use_gpu=1

结果处理

通过key查找value,结果保存到home/aistudio/result_id.txt

# 读取,并转换为value,
%cd /home/aistudio
import fileinput

value_list = []
for line in fileinput.input("/home/aistudio/result_id.txt"):
    value_list.append(label_map[line.strip('\n')])
print(len(value_list))


/home/aistudio
200
# 保存
savename = '/home/aistudio/result.txt'
with open(savename, 'w', newline='') as f:
    for line in value_list:
        f.write(line+"\n")

个人总结

给大家打个样,开拓下视野,可以选择多种模型,也可以多种参数调整,分分钟准确率上去了。

由于系统保存版本文件限制,修改过的work/PaddleClas/tools/infer/predict.py文件,以及work/PaddleClas/configs/EfficientNet/EfficientNetB0.yaml单独存放于/home/aistudio即当前用户目录下了,请自提。

aistudio项目地址

用PaddleClas解决蝴蝶分类https://aistudio.baidu.com/aistudio/projectdetail/1415075

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值