Paddle图像分类

Paddle图像分类

V1.8

1
2
paddlepaddle 1.8.3
paddlehub 1.8.3

预测

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import paddlehub as hub
import os


def run(img_name):
classifier = hub.Module(directory="vgg19_imagenet")
path = './images/'
input_dict = {"image": [os.path.join(path, img_name)]}
result = classifier.classification(data=input_dict)
print(result)
return result


if __name__ == "__main__":
run('test_img_cat.jpg')

返回结果:[[{'tiger cat': 0.5675306916236877}]]

finetune

官方文档:github

自定义数据集

1
2
3
4
5
6
├─data: 数据目录
  ├─train_list.txt:训练集数据列表
  ├─test_list.txt:测试集数据列表
  ├─validate_list.txt:验证集数据列表
  ├─label_list.txt:标签列表
  └─……

训练/验证/测试集的数据列表文件的格式如下

1
2
3
图片1路径 图片1标签
图片2路径 图片2标签
...

label_list.txt的格式如下

1
2
3
分类1名称
分类2名称
...

以fruits数据集为例,数据列表文件为:

1
2
3
JPEGImages/apple_21.jpg 0
JPEGImages/apple_22.jpg 0
...

目录结构为:

1
2
3
4
5
6
7
├─Dataset: 数据目录
├─JPEGImages:储存图片
├─train_list.txt:训练集数据列表
├─test_list.txt:测试集数据列表
├─validate_list.txt:验证集数据列表
├─label_list.txt:标签列表
└─……

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# coding:utf-8

import os
import paddle.fluid as fluid
import paddlehub as hub
import numpy as np
import datetime
from paddlehub.dataset.base_cv_dataset import BaseCVDataset


# os.environ["CUDA_VISIBLE_DEVICES"] = "9"
# os.environ['FLAGS_eager_delete_tensor_gb'] = '0.0'


class SelfDataset(BaseCVDataset):
def __init__(self, dataset):
base_path = '/..../Datasets/' + dataset
super(SelfDataset, self).__init__(
base_path=base_path,
train_list_file="train_list.txt",
validate_list_file="validate_list.txt",
test_list_file="test_list.txt",
label_list_file="label_list.txt",
label_list=None)


def finetune(module_name, dataset_name, checkpoint_name, use_selfdataset=False, use_gpu=True, num_epoch=10, batch_size=16, use_data_parallel=True):
# Load Paddlehub pretrained model
module = hub.Module(name=module_name)
input_dict, output_dict, program = module.context(trainable=True)

# Load dataset
if use_selfdataset:
try:
dataset = SelfDataset(dataset_name)
except ValueError:
print("%s dataset can't be loaded" % dataset_name)
else:
if dataset_name.lower() == "flowers":
dataset = hub.dataset.Flowers()
elif dataset_name.lower() == "dogcat":
dataset = hub.dataset.DogCat()
elif dataset_name.lower() == "indoor67":
dataset = hub.dataset.Indoor67()
elif dataset_name.lower() == "food101":
dataset = hub.dataset.Food101()
else:
raise ValueError("%s dataset is not defined" % dataset_name)

# Use ImageClassificationReader to read dataset
data_reader = hub.reader.ImageClassificationReader(
image_width=module.get_expected_image_width(),
image_height=module.get_expected_image_height(),
images_mean=module.get_pretrained_images_mean(),
images_std=module.get_pretrained_images_std(),
dataset=dataset)

feature_map = output_dict["feature_map"]

# Setup feed list for data feeder
feed_list = [input_dict["image"].name]

checkpoint_dir = os.path.join('./finetune_ckpt/', checkpoint_name)
if not os.path.exists(checkpoint_dir):
os.makedirs(checkpoint_dir)

# Setup RunConfig for PaddleHub Fine-tune API
config = hub.RunConfig(
use_data_parallel=use_data_parallel,
use_cuda=use_gpu,
num_epoch=num_epoch,
batch_size=batch_size,
checkpoint_dir=checkpoint_dir,
strategy=hub.finetune.strategy.DefaultFinetuneStrategy())

# Define a image classification task by PaddleHub Fine-tune API
task = hub.ImageClassifierTask(
data_reader=data_reader,
feed_list=feed_list,
feature=feature_map,
num_classes=dataset.num_labels,
config=config)

# Fine-tune by PaddleHub's API
task.finetune_and_eval()


if __name__ == "__main__":
finetune('vgg19_imagenet', 'indoor67', 'vgg_indoor_test_gpu', use_selfdataset=False, num_epoch=10, batch_size = 128, use_gpu=True)

接口

1
def finetune(module_name, dataset_name, checkpoint_name, use_selfdataset=False, use_gpu=True, num_epoch=10, batch_size=16, use_data_parallel=True):
  • module_name:目前包括四个图像分类模型:efficientnetb7_imagenet、resnext50_vd_64x4d_imagenet、vgg19_imagenet、xception71_imagenet
  • dataset_name:paddle自带数据集包括:flowers、dogcat、indoor67、food101. 如果是用户自定义数据集,dataset_name为Datasets目录下用户自定义数据集名。
  • checkpoint_name:模型和cache文件保存位置,默认在 finetune_ckpt目录下。命名时不要重复。
  • use_selfdataset:当使用用户自定义数据集时设置为True

保存loss

为了在运行过程中输出loss到txt文件,对paddlehub/finetune/task/base_task.py进行修改

修改部分如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
BaseTask类:

__init__函数中,添加以下代码
#### BEGIN #### (约313行,self.device_count定义之后)
self.cachefilepath = os.path.join(self.config.checkpoint_dir, 'cache.txt')
##### END #####

_default_eval_end_event函数中,添加以下代码
#### BEGIN #### (约822行,logger.eval之后)
with open(self.cachefilepath, "a") as file:
file.write("[%s dataset evaluation result] loss=%.5f %s[step/sec: %.2f]\n" %
(self.phase, eval_loss, log_scores, run_speed))
##### END #####

#### BEGIN #### (约845行,logger.eval之后)
with open(self.cachefilepath, "a") as file:
file.write("best model saved to %s [best %s=%.5f]\n" %
(model_saved_dir, main_metric, main_value))
##### END #####

_default_log_interval_event函数中,添加以下代码
#### BEGIN #### (约875行,logger.train之后)
with open(self.cachefilepath, "a") as file:
file.write("step %d / %d: loss=%.5f %s[step/sec: %.2f]\n" %
(self.current_step, self.max_train_steps, avg_loss,
log_scores, run_speed))
##### END #####

被调用在_run函数中,约1247行,部分代码如下:

1
2
3
4
5
6
7
8
9
10
11
if self.is_train_phase:
if self.current_step % self.config.log_interval == 0:
self._log_interval_event(period_run_states)
global_run_states += period_run_states
period_run_states = []

if self.config.save_ckpt_interval and self.current_step % self.config.save_ckpt_interval == 0:
self._save_ckpt_interval_event()

if do_eval and self.current_step % self.config.eval_interval == 0:
self._eval_interval_event()