Using Paddlepaddle to recognize flowers

Jimmy (xiaoke) Shen
5 min readJan 25, 2022

PaddlePaddle is a Chinese based DL framework developped by China’s Google Baidu. If you are interested in exploring this DL framework, here is an example of how to use paddlepaddle to train a flower classification model.

Install paddlepaddle

Following the official instruction, which is pretty clear.

Prepare the code

git clone https://github.com/PaddlePaddle/PaddleClas.git

Dataset

Download the data

# Go to the root path of the PaddleClas repo
cd dataset/
wget https://paddle-imagenet-models-name.bj.bcebos.com/data/flowers102.zip
unzip flowers102.zip

After downlading the dataset, you will have

flowers102├── flowers102_label_list.txt├── jpg│   ├── image_00001.jpg│   ├── image_00002.jpg│   ├── image_00003.jpg│   ├── image_00004.jpg
...
│ ├── image_08185.jpg
│ ├── image_08186.jpg│ ├── image_08187.jpg│ ├── image_08188.jpg│ └── image_08189.jpg├── train_extra_list.txt├── train_list.txt└── val_list.txt

Which means you have 8189 images in total. Some samples like the following:

How many labels (categories) do we have?

If you check the flowers102_label_list.txt, as the name suggested, we have 102 different types.

0 pink primrose1 hard-leaved pocket orchid2 canterbury bells3 sweet pea4 english marigold5 tiger lily6 moon orchid7 bird of paradise8 monkshood9 globe thistle
...
96 mallow
97 mexican petunia98 bromelia99 blanket flower100 trumpet creeper101 blackberry lily

Train and val split

We have the file of

train_extra_list.txt train_list.txt val_list.txt

Here is the samples in train_list.txt which indicate the train dataset’s

file name and label id.

jpg/image_06765.jpg 0jpg/image_06755.jpg 0jpg/image_06768.jpg 0jpg/image_06736.jpg 0jpg/image_06744.jpg 0jpg/image_06766.jpg 0jpg/image_06771.jpg 0jpg/image_06750.jpg 0jpg/image_06741.jpg 0jpg/image_06762.jpg 0jpg/image_05145.jpg 1jpg/image_05137.jpg 1jpg/image_05142.jpg 1jpg/image_05115.jpg 1jpg/image_05091.jpg 1jpg/image_05106.jpg 1

Train the model

In order to run the code, you need install several packages except the paddlepaddle

pip install tqdm
conda install -c anaconda scikit-learn
pip install pyyaml
conda install -c conda-forge opencv
pip install visualdl

Using this command to train from a pretrained model

python tools/train.py -c ./ppcls/configs/quick_start/new_user/ShuffleNetV2_x0_25.yaml  -o Arch.pretrained=True

If the training process goes well, you will see something like this

[2022/01/24 23:15:44] root INFO:             channel_first : False[2022/01/24 23:15:44] root INFO:             to_rgb : True[2022/01/24 23:15:44] root INFO:         ResizeImage :[2022/01/24 23:15:44] root INFO:             resize_short : 256[2022/01/24 23:15:44] root INFO:         CropImage :[2022/01/24 23:15:44] root INFO:             size : 224[2022/01/24 23:15:44] root INFO:         NormalizeImage :[2022/01/24 23:15:44] root INFO:             mean : [0.485, 0.456, 0.406][2022/01/24 23:15:44] root INFO:             order :[2022/01/24 23:15:44] root INFO:             scale : 1.0/255.0[2022/01/24 23:15:44] root INFO:             std : [0.229, 0.224, 0.225][2022/01/24 23:15:44] root INFO:         ToCHWImage : None[2022/01/24 23:15:44] root INFO: Loss :[2022/01/24 23:15:44] root INFO:     Eval :[2022/01/24 23:15:44] root INFO:         CELoss :[2022/01/24 23:15:44] root INFO:             weight : 1.0[2022/01/24 23:15:44] root INFO:     Train :[2022/01/24 23:15:44] root INFO:         CELoss :[2022/01/24 23:15:44] root INFO:             weight : 1.0[2022/01/24 23:15:44] root INFO: Metric :[2022/01/24 23:15:44] root INFO:     Eval :[2022/01/24 23:15:44] root INFO:         TopkAcc :[2022/01/24 23:15:44] root INFO:             topk : [1, 5][2022/01/24 23:15:44] root INFO:     Train :[2022/01/24 23:15:44] root INFO:         TopkAcc :[2022/01/24 23:15:44] root INFO:             topk : [1, 5][2022/01/24 23:15:44] root INFO: Optimizer :[2022/01/24 23:15:44] root INFO:     lr :[2022/01/24 23:15:44] root INFO:         learning_rate : 0.0125[2022/01/24 23:15:44] root INFO:         name : Cosine[2022/01/24 23:15:44] root INFO:         warmup_epoch : 5[2022/01/24 23:15:44] root INFO:     momentum : 0.9[2022/01/24 23:15:44] root INFO:     name : Momentum[2022/01/24 23:15:44] root INFO:     regularizer :[2022/01/24 23:15:44] root INFO:         coeff : 1e-05[2022/01/24 23:15:44] root INFO:         name : L2[2022/01/24 23:15:44] root INFO: profiler_options : None[2022/01/24 23:15:44] root INFO: train with paddle 2.2.1 and device CUDAPlace(0)W0124 23:15:44.645875 39134 device_context.cc:447] Please NOTE: device: 0, GPU Compute Capability: 7.0, Driver API Version: 11.0, Runtime API Version: 11.0W0124 23:15:45.481689 39134 device_context.cc:465] device: 0, cuDNN Version: 8.0.
[2022/01/24 23:17:25] root INFO: unique_endpoints {''}
[2022/01/24 23:17:25] root INFO: Downloading ResNet50_vd_pretrained.pdparams from https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/legendary_models/ResNet50_vd_pretrained.pdparams100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 151674/151674 [00:44<00:00, 3438.65it/s]/home/ubuntu/anaconda3/envs/paddle/lib/python3.7/site-packages/paddle/fluid/dygraph/layers.py:1436: UserWarning: Skip loading for fc.weight. fc.weight receives a shape [2048, 1000], but the expected shape is [2048, 102].warnings.warn(("Skip loading for {}. ".format(key) + str(err)))/home/ubuntu/anaconda3/envs/paddle/lib/python3.7/site-packages/paddle/fluid/dygraph/layers.py:1436: UserWarning: Skip loading for fc.bias. fc.bias receives a shape [1000], but the expected shape is [102].warnings.warn(("Skip loading for {}. ".format(key) + str(err)))
...
0.33236, batch_cost: 0.20485s, reader_cost: 0.00014, ips: 156.21518 images/sec, eta: 0:01:08
[2022/01/24 23:23:39] root INFO: [Train][Epoch 10/20][Iter: 30/32]lr: 0.00941, top1: 0.91230, top5: 0.97681, CELoss: 0.37659, loss: 0.37659, batch_cost: 0.20435s, reader_cost: 0.00012, ips: 156.59497 images/sec, eta: 0:01:05[2022/01/24 23:23:39] root INFO: [Train][Epoch 10/20][Avg]top1: 0.91373, top5: 0.97745, CELoss: 0.37335, loss: 0.37335[2022/01/24 23:23:40] root INFO: [Eval][Epoch 10][Iter: 0/16]CELoss: 0.75603, loss: 0.75603, top1: 0.82812, top5: 0.93750, batch_cost: 1.02958s, reader_cost: 0.91494, ips: 62.16100 images/sec[2022/01/24 23:23:42] root INFO: [Eval][Epoch 10][Iter: 10/16]CELoss: 0.24584, loss: 0.24584, top1: 0.92188, top5: 1.00000, batch_cost: 0.17600s, reader_cost: 0.06913, ips: 363.64605 images/sec[2022/01/24 23:23:43] root INFO: [Eval][Epoch 10][Avg]CELoss: 0.37863, loss: 0.37863, top1: 0.90000, top5: 0.97843[2022/01/24 23:23:49] root INFO: Already save model in ./output/ResNet50_vd/best_model[2022/01/24 23:23:49] root INFO: [Eval][Epoch 10][best metric: 0.8999999983637941][2022/01/24 23:23:50] root INFO: Already save model in ./output/ResNet50_vd/epoch_10[2022/01/24 23:23:54] root INFO: Already save model in ./output/ResNet50_vd/latest[2022/01/24 23:23:55] root INFO: [Train][Epoch 11/20][Iter: 0/32]lr: 0.00934, top1: 0.93750, top5: 1.00000, CELoss: 0.15017, loss: 0.15017, batch_cost: 0.21860s, reader_cost: 0.01467, ips: 146.38531 images/sec, eta: 0:01:09[2022/01/24 23:23:57] root INFO: [Train][Epoch 11/20][Iter: 10/32]lr: 0.00898, top1: 0.93466, top5: 0.99148, CELoss: 0.24013, loss: 0.24013, batch_cost: 0.20525s, reader_cost: 0
...
[2022/01/24 23:26:21] root INFO: [Train][Epoch 20/20][Avg]top1: 0.98235, top5: 0.99608, CELoss: 0.07628, loss: 0.07628[2022/01/24 23:26:22] root INFO: [Eval][Epoch 20][Iter: 0/16]CELoss: 0.59098, loss: 0.59098, top1: 0.87500, top5: 0.95312, batch_cost: 1.02575s, reader_cost: 0.90770, ips: 62.39326 images/sec[2022/01/24 23:26:24] root INFO: [Eval][Epoch 20][Iter: 10/16]CELoss: 0.28884, loss: 0.28884, top1: 0.92188, top5: 0.98438, batch_cost: 0.16941s, reader_cost: 0.06267, ips: 377.79246 images/sec[2022/01/24 23:26:25] root INFO: [Eval][Epoch 20][Avg]CELoss: 0.23456, loss: 0.23456, top1: 0.94706, top5: 0.98627[2022/01/24 23:26:25] root INFO: [Eval][Epoch 20][best metric: 0.9470588244643866][2022/01/24 23:26:25] root INFO: Already save model in ./output/ResNet50_vd/epoch_20[2022/01/24 23:26:26] root INFO: Already save model in ./output/ResNet50_vd/latest

If you check you GPU usage

nvidia-smi

You can see

Inference

python tools/infer.py -c ./ppcls/configs/quick_start/ResNet50_vd.yaml -o Infer.infer_imgs=dataset/flowers102/jpg/image_00001.jpg -o Global.pretrained_model=output/ResNet50_vd/best_model

output

Pretty good, the image tested has the label of 76. The model’s prediction matches.

[{'class_ids': [76, 11, 9, 70, 12], 'scores': [0.99713, 0.00109, 0.00042, 0.00016, 0.00012], 'file_name': 'dataset/flowers102/jpg/image_00001.jpg', 'label_names': ['passion flower', "colt's foot", 'globe thistle', 'gazania', 'king protea']}]

Reference

[1]https://github.com/PaddlePaddle/PaddleClas/blob/release/2.3/docs/zh_CN/quick_start/quick_start_classification_new_user.md

--

--