【PaddleHub模型貢獻】如何將飛槳PaddlePaddle模型收錄至PaddleHub

將訓練保存的模型轉化爲PaddleHub Module並完成一鍵加載

下載安裝命令

## CPU版本安裝命令
pip install -f https://paddlepaddle.org.cn/pip/oschina/cpu paddlepaddle

## GPU版本安裝命令
pip install -f https://paddlepaddle.org.cn/pip/oschina/gpu paddlepaddle-gpu

本教程旨在把幫助各位開發者把在ai studio上作的精品項目轉入到PaddleHub的Module裏,使其具有一鍵預測的能力。html

運行該項目請到AI Studio:
https://aistudio.baidu.com/aistudio/projectdetail/1259178python

1、訓練鮮花識別模型

原項目來自開發者笨笨的——圖像分類-VGG,該項目使用公開的鮮花據集,數據集壓縮包裏包含五個文件夾,每一個文件夾一種花卉。分別是雛菊,蒲公英,玫瑰,向日葵,鬱金香,每種各690-890張圖片,網絡採用VGGapi

1. 解壓鮮花數據集及預訓練參數


# 解壓花朵數據集
!cd data/data2815 && unzip -qo flower_photos.zip

# 解壓預訓練參數
!cd data/data6489 && unzip -qo VGG16_pretrained.zip

2. 數據預處理


!python work/DataPreprocessing.py
['daisy', 'dandelion', 'roses', 'sunflowers', 'tulips']

3. 模型訓練

本項目的主要目的是轉換Module,因此訓練的epochs設爲1網絡


!python work/train.py
2020-11-24 19:06:16,867-INFO: create prog success
2020-11-24 19:06:16,867 - train.py[line:460] - INFO: create prog success
2020-11-24 19:06:16,867-INFO: train config: {'input_size': [3, 224, 224], 'class_dim': 5, 'image_count': 2955, 'label_dict': {'daisy': 0, 'dandelion': 1, 'roses': 2, 'sunflowers': 3, 'tulips': 4}, 'data_dir': 'data/data2815', 'train_file_list': 'train.txt', 'label_file': 'label_list.txt', 'save_freeze_dir': './freeze-model', 'save_persistable_dir': './persistable-params', 'continue_train': False, 'pretrained': True, 'pretrained_dir': 'data/data6489/VGG16_pretrained', 'mode': 'train', 'num_epochs': 1, 'train_batch_size': 24, 'mean_rgb': [127.5, 127.5, 127.5], 'use_gpu': True, 'image_enhance_strategy': {'need_distort': True, 'need_rotate': True, 'need_crop': True, 'need_flip': True, 'hue_prob': 0.5, 'hue_delta': 18, 'contrast_prob': 0.5, 'contrast_delta': 0.5, 'saturation_prob': 0.5, 'saturation_delta': 0.5, 'brightness_prob': 0.5, 'brightness_delta': 0.125}, 'early_stop': {'sample_frequency': 50, 'successive_limit': 3, 'good_acc1': 0.92}, 'rsm_strategy': {'learning_rate': 0.0005, 'lr_epochs': [20, 40, 60, 80, 100], 'lr_decay': [1, 0.5, 0.25, 0.1, 0.01, 0.002]}, 'momentum_strategy': {'learning_rate': 0.0005, 'lr_epochs': [20, 40, 60, 80, 100], 'lr_decay': [1, 0.5, 0.25, 0.1, 0.01, 0.002]}, 'sgd_strategy': {'learning_rate': 0.0005, 'lr_epochs': [20, 40, 60, 80, 100], 'lr_decay': [1, 0.5, 0.25, 0.1, 0.01, 0.002]}, 'adam_strategy': {'learning_rate': 0.0005}}
2020-11-24 19:06:16,867 - train.py[line:461] - INFO: train config: {'input_size': [3, 224, 224], 'class_dim': 5, 'image_count': 2955, 'label_dict': {'daisy': 0, 'dandelion': 1, 'roses': 2, 'sunflowers': 3, 'tulips': 4}, 'data_dir': 'data/data2815', 'train_file_list': 'train.txt', 'label_file': 'label_list.txt', 'save_freeze_dir': './freeze-model', 'save_persistable_dir': './persistable-params', 'continue_train': False, 'pretrained': True, 'pretrained_dir': 'data/data6489/VGG16_pretrained', 'mode': 'train', 'num_epochs': 1, 'train_batch_size': 24, 'mean_rgb': [127.5, 127.5, 127.5], 'use_gpu': True, 'image_enhance_strategy': {'need_distort': True, 'need_rotate': True, 'need_crop': True, 'need_flip': True, 'hue_prob': 0.5, 'hue_delta': 18, 'contrast_prob': 0.5, 'contrast_delta': 0.5, 'saturation_prob': 0.5, 'saturation_delta': 0.5, 'brightness_prob': 0.5, 'brightness_delta': 0.125}, 'early_stop': {'sample_frequency': 50, 'successive_limit': 3, 'good_acc1': 0.92}, 'rsm_strategy': {'learning_rate': 0.0005, 'lr_epochs': [20, 40, 60, 80, 100], 'lr_decay': [1, 0.5, 0.25, 0.1, 0.01, 0.002]}, 'momentum_strategy': {'learning_rate': 0.0005, 'lr_epochs': [20, 40, 60, 80, 100], 'lr_decay': [1, 0.5, 0.25, 0.1, 0.01, 0.002]}, 'sgd_strategy': {'learning_rate': 0.0005, 'lr_epochs': [20, 40, 60, 80, 100], 'lr_decay': [1, 0.5, 0.25, 0.1, 0.01, 0.002]}, 'adam_strategy': {'learning_rate': 0.0005}}
2020-11-24 19:06:16,868-INFO: build input custom reader and data feeder
2020-11-24 19:06:16,868 - train.py[line:462] - INFO: build input custom reader and data feeder
2020-11-24 19:06:16,869-INFO: build newwork
2020-11-24 19:06:16,869 - train.py[line:475] - INFO: build newwork
W1124 19:06:18.083617   144 device_context.cc:236] Please NOTE: device: 0, CUDA Capability: 70, Driver API Version: 10.1, Runtime API Version: 9.0
W1124 19:06:18.087874   144 device_context.cc:244] device: 0, cuDNN Version: 7.3.
2020-11-24 19:06:19,710-INFO: load params from pretrained model
2020-11-24 19:06:19,710 - train.py[line:449] - INFO: load params from pretrained model
2020-11-24 19:06:21,383-INFO: current pass: 0, start read image
2020-11-24 19:06:21,383 - train.py[line:504] - INFO: current pass: 0, start read image
2020-11-24 19:06:24,815-INFO: Pass 0, trainbatch 10, loss 1.6219388246536255, acc1 0.0833333358168602, time 0.14 sec
2020-11-24 19:06:24,815 - train.py[line:519] - INFO: Pass 0, trainbatch 10, loss 1.6219388246536255, acc1 0.0833333358168602, time 0.14 sec
2020-11-24 19:06:28,441-INFO: Pass 0, trainbatch 20, loss 1.558526635169983, acc1 0.4583333432674408, time 0.15 sec
2020-11-24 19:06:28,441 - train.py[line:519] - INFO: Pass 0, trainbatch 20, loss 1.558526635169983, acc1 0.4583333432674408, time 0.15 sec
2020-11-24 19:06:31,856-INFO: Pass 0, trainbatch 30, loss 1.574629783630371, acc1 0.3333333432674408, time 0.14 sec
2020-11-24 19:06:31,856 - train.py[line:519] - INFO: Pass 0, trainbatch 30, loss 1.574629783630371, acc1 0.3333333432674408, time 0.14 sec
2020-11-24 19:06:35,593-INFO: Pass 0, trainbatch 40, loss 1.5624138116836548, acc1 0.5, time 0.14 sec
2020-11-24 19:06:35,593 - train.py[line:519] - INFO: Pass 0, trainbatch 40, loss 1.5624138116836548, acc1 0.5, time 0.14 sec
2020-11-24 19:06:39,171-INFO: Pass 0, trainbatch 50, loss 1.6100339889526367, acc1 0.1666666716337204, time 0.14 sec
2020-11-24 19:06:39,171 - train.py[line:519] - INFO: Pass 0, trainbatch 50, loss 1.6100339889526367, acc1 0.1666666716337204, time 0.14 sec
2020-11-24 19:06:39,172-INFO: temp save 50 batch train result, current acc1 0.1666666716337204
2020-11-24 19:06:39,172 - train.py[line:538] - INFO: temp save 50 batch train result, current acc1 0.1666666716337204
2020-11-24 19:06:46,603-INFO: Pass 0, trainbatch 60, loss 1.6188973188400269, acc1 0.2083333283662796, time 0.14 sec
2020-11-24 19:06:46,603 - train.py[line:519] - INFO: Pass 0, trainbatch 60, loss 1.6188973188400269, acc1 0.2083333283662796, time 0.14 sec
2020-11-24 19:06:50,057-INFO: Pass 0, trainbatch 70, loss 1.6400723457336426, acc1 0.125, time 0.14 sec
2020-11-24 19:06:50,057 - train.py[line:519] - INFO: Pass 0, trainbatch 70, loss 1.6400723457336426, acc1 0.125, time 0.14 sec
2020-11-24 19:06:53,692-INFO: Pass 0, trainbatch 80, loss 1.5995646715164185, acc1 0.25, time 0.14 sec
2020-11-24 19:06:53,692 - train.py[line:519] - INFO: Pass 0, trainbatch 80, loss 1.5995646715164185, acc1 0.25, time 0.14 sec
2020-11-24 19:06:57,141-INFO: Pass 0, trainbatch 90, loss 1.539711833000183, acc1 0.3333333432674408, time 0.14 sec
2020-11-24 19:06:57,141 - train.py[line:519] - INFO: Pass 0, trainbatch 90, loss 1.539711833000183, acc1 0.3333333432674408, time 0.14 sec
2020-11-24 19:07:00,644-INFO: Pass 0, trainbatch 100, loss 1.593304991722107, acc1 0.125, time 0.14 sec
2020-11-24 19:07:00,644 - train.py[line:519] - INFO: Pass 0, trainbatch 100, loss 1.593304991722107, acc1 0.125, time 0.14 sec
2020-11-24 19:07:00,645-INFO: temp save 100 batch train result, current acc1 0.125
2020-11-24 19:07:00,645 - train.py[line:538] - INFO: temp save 100 batch train result, current acc1 0.125
2020-11-24 19:07:08,069-INFO: Pass 0, trainbatch 110, loss 1.5976566076278687, acc1 0.3333333432674408, time 0.14 sec
2020-11-24 19:07:08,069 - train.py[line:519] - INFO: Pass 0, trainbatch 110, loss 1.5976566076278687, acc1 0.3333333432674408, time 0.14 sec
2020-11-24 19:07:11,569-INFO: Pass 0, trainbatch 120, loss 1.6223376989364624, acc1 0.125, time 0.14 sec
2020-11-24 19:07:11,569 - train.py[line:519] - INFO: Pass 0, trainbatch 120, loss 1.6223376989364624, acc1 0.125, time 0.14 sec
2020-11-24 19:07:12,698-INFO: training till last epcho, end training
2020-11-24 19:07:12,698 - train.py[line:544] - INFO: training till last epcho, end training

2、整理成PaddleHub Module格式

PaddleHub Module是使用PaddleHub的基礎。其能夠經過指定名稱便可方便地完成一鍵加載,如加載預訓練模型ERNIE僅需一行代碼便可完成,hub.Module(name=‘ernie’),省去了複雜的網絡結構代碼以及參數加載的繁瑣過程。app

1. 必要的目錄與文件

建立一個大目錄,並在該目錄下分別建立__init__.py、module.py、processor.py、net.py等文件框架

目錄名稱即Module的名稱,如這裏我起名爲VGG16:dom

VGG16/
├── assets # 資源文件夾
│   ├── infer_model # 模型文件
│   └── vocab.txt # 詞彙表文件
├── data_feed.py
├── __init__.py # 空文件
├── module.py # 主模塊,提供Module的實現代碼
├── net.py # 網絡框架的實現
└── processor.py # 輔助模塊,如提供詞表加載的方法

2.infer_model

infer_model下存放的是使用fluid.io.save_inference_model保存的模型文件ide


# 建立必要的文件夾
!mkdir -p VGG16/assets/infer_model
# 將模型文件複製到Module指定目錄下
!cp -r freeze-model/* VGG16/assets/infer_model

3. vocab.txt

在圖像分類任務中,詞彙表文件存放的是每個類別函數

vocab = open("VGG16/assets/vocab.txt", "w")
vocab.writelines(['daisy\n', 'dandelion\n', 'roses\n', 'sunflowers\n', 'tulips\n'])
vocab.close()

4. __ init__.py

__ init__.py是一個空文件,直接建立便可oop

init = open("VGG16/__init__.py", "w")

5. processor.py

輔助模塊,在processor.py中實現詞彙表的讀取,以及文本輸入模型以前須要作的預處理

本案例中用於加載vocab.txt,下面是代碼示例:

def load_label_info(file_path):
    with open(file_path, 'r') as fr:
        return fr.read().split("\n")[:-1]

 

processor = open("VGG16/processor.py", "w")

6.net.py

網路框架的實現,模型訓練時的網絡,下面是代碼示例:

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

from paddle import fluid

class VGGNet(object):
    """
    vgg的網絡類
    """
    def __init__(self, layers=16):
        """
        vgg網絡構造函數
        :param layers:
        """
        self.layers = layers

    def name(self):
        """
        返回網絡名字
        :return:
        """
        return 'vgg-net'

    def net(self, input, class_dim=1000):
        layers = self.layers
        vgg_spec = {
            11: ([1, 1, 2, 2, 2]),
            13: ([2, 2, 2, 2, 2]),
            16: ([2, 2, 3, 3, 3]),
            19: ([2, 2, 4, 4, 4])
        }
        assert layers in vgg_spec.keys(), \
            "supported layers are {} but input layer is {}".format(vgg_spec.keys(), layers)

        nums = vgg_spec[layers]
        conv1 = self.conv_block(input, 64, nums[0], name="conv1_")
        conv2 = self.conv_block(conv1, 128, nums[1], name="conv2_")
        conv3 = self.conv_block(conv2, 256, nums[2], name="conv3_")
        conv4 = self.conv_block(conv3, 512, nums[3], name="conv4_")
        conv5 = self.conv_block(conv4, 512, nums[4], name="conv5_")

        fc_dim = 4096
        fc_name = ["fc6", "fc7", "fc8"]
        fc1 = fluid.layers.fc(
            input=conv5,
            size=fc_dim,
            act='relu',
            param_attr=fluid.param_attr.ParamAttr(name=fc_name[0] + "_weights"),
            bias_attr=fluid.param_attr.ParamAttr(name=fc_name[0] + "_offset"))
        fc1 = fluid.layers.dropout(x=fc1, dropout_prob=0.5)
        fc2 = fluid.layers.fc(
            input=fc1,
            size=fc_dim,
            act='relu',
            param_attr=fluid.param_attr.ParamAttr(name=fc_name[1] + "_weights"),
            bias_attr=fluid.param_attr.ParamAttr(name=fc_name[1] + "_offset"))
        fc2 = fluid.layers.dropout(x=fc2, dropout_prob=0.5)
        out = fluid.layers.fc(
            input=fc2,
            size=class_dim,
            act='softmax',
            param_attr=fluid.param_attr.ParamAttr(name=fc_name[2] + "_weights"),
            bias_attr=fluid.param_attr.ParamAttr(name=fc_name[2] + "_offset"))

        return out

    def conv_block(self, input, num_filter, groups, name=None):
        conv = input
        for i in range(groups):
            conv = fluid.layers.conv2d(
                input=conv,
                num_filters=num_filter,
                filter_size=3,
                stride=1,
                padding=1,
                act='relu',
                param_attr=fluid.param_attr.ParamAttr(
                    name=name + str(i + 1) + "_weights"),
                bias_attr=fluid.param_attr.ParamAttr(
                    name=name + str(i + 1) + "_offset"))
        return fluid.layers.pool2d(
            input=conv, pool_size=2, pool_type='max', pool_stride=2)

 

net = open("VGG16/net.py", "w")

7. data_feed.py

處理圖像,以便送入網絡進行預測,下面是參考代碼:

from __future__ import absolute_import
from __future__ import print_function
from __future__ import division

import os
from collections import OrderedDict

import cv2
import numpy as np
from PIL import Image, ImageEnhance
from paddle import fluid

DATA_DIM = 224
img_mean = np.array([0.485, 0.456, 0.406]).reshape((3, 1, 1))
img_std = np.array([0.229, 0.224, 0.225]).reshape((3, 1, 1))


def resize_short(img, target_size):
    percent = float(target_size) / min(img.size[0], img.size[1])
    resized_width = int(round(img.size[0] * percent))
    resized_height = int(round(img.size[1] * percent))
    img = img.resize((resized_width, resized_height), Image.LANCZOS)
    return img


def crop_image(img, target_size, center):
    width, height = img.size
    size = target_size
    if center == True:
        w_start = (width - size) / 2
        h_start = (height - size) / 2
    else:
        w_start = np.random.randint(0, width - size + 1)
        h_start = np.random.randint(0, height - size + 1)
    w_end = w_start + size
    h_end = h_start + size
    img = img.crop((w_start, h_start, w_end, h_end))
    return img


def process_image(img):
    img = resize_short(img, target_size=256)
    img = crop_image(img, target_size=DATA_DIM, center=True)
    if img.mode != 'RGB':
        img = img.convert('RGB')
    #img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    img = np.array(img).astype('float32').transpose((2, 0, 1)) / 255
    img -= img_mean
    img /= img_std
    return img


def test_reader(paths=None, images=None):
    """data generator
    :param paths: path to images.
    :type paths: list, each element is a str
    :param images: data of images, [N, H, W, C]
    :type images: numpy.ndarray
    """
    img_list = []
    if paths:
        assert os.path.isfile(
            paths), "The {} isn't a valid file path.".format(img_path)
        img = Image.open(paths)
        #img = cv2.imread(img_path)
        img_list.append(img)
    if images is not None:
        for img in images:
            img_list.append(Image.fromarray(np.uint8(img)))
    for im in img_list:
        im = process_image(im)
        yield im

 

8. module.py

module.py文件爲Module的入口代碼所在,須要在其中實現預測邏輯。


module = open("VGG16/module.py", "w")

引入必要的頭文件

當引用Module中模塊時,須要輸入全路徑,如VGG16.net

import os
import ast
import argparse

import numpy as np
import paddlehub as hub
import paddle.fluid as fluid
from paddlehub.module.module import moduleinfo, runnable
from paddle.fluid.core import PaddleTensor, AnalysisConfig, create_paddle_predictor
from paddlehub.io.parser import txt_parser

填寫模型基本信息

一個PaddleHub Module,其基本信息以下:

@moduleinfo(
    name="VGG16",
    version="1.0.0",
    type="cv/classification",
    summary=
    "VGG16 is a image classfication model trained with Flower dataset.",
    author="paddlepaddle",
    author_email="paddle-dev@baidu.com")

實現邏輯預測

module.py中須要有一個繼承了hub.Module的類存在,該類負責實現預測邏輯,並使用moduleinfo填寫基本信息。 當使用hub.Module(name=「senta_test」)加載Module時,PaddleHub會自動建立該類的對象並返回。

class VGG16(hub.Module):
    def _initialize(self):
        self.default_pretrained_model_path = os.path.join(self.directory, "assets/infer_model") # 模型文件的路徑
        self.label_names = load_label_info(os.path.join(self.directory, "assets/vocab.txt")) # 圖像分類任務的標籤
        self.infer_prog = None
        self.pred_out = None
        self._set_config()

    def get_expected_image_width(self):
        return 224

    def get_expected_image_height(self):
        return 224

    def get_pretrained_images_mean(self):
        im_mean = np.array([0.485, 0.456, 0.406]).reshape(1, 3)
        return im_mean

    def get_pretrained_images_std(self):
        im_std = np.array([0.229, 0.224, 0.225]).reshape(1, 3)
        return im_std

    def _set_config(self):
        """
        predictor config setting
        """
        cpu_config = AnalysisConfig(self.default_pretrained_model_path)
        cpu_config.disable_glog_info()
        cpu_config.disable_gpu()
        cpu_config.switch_ir_optim(False)
        self.cpu_predictor = create_paddle_predictor(cpu_config)

        try:
            _places = os.environ["CUDA_VISIBLE_DEVICES"]
            int(_places[0])
            use_gpu = True
        except:
            use_gpu = False
        if use_gpu:
            gpu_config = AnalysisConfig(self.default_pretrained_model_path)
            gpu_config.disable_glog_info()
            gpu_config.enable_use_gpu(memory_pool_init_size_mb=500, device_id=0)
            self.gpu_predictor = create_paddle_predictor(gpu_config)

    def context(self,
                input_image=None,
                trainable=True,
                pretrained=True,
                param_prefix='',
                get_prediction=False,
                extra_block_filters=((256, 512, 1, 2, 3), (128, 256, 1, 2, 3),
                                     (128, 256, 0, 1, 3), (128, 256, 0, 1, 3)),
                normalizations=(20., -1, -1, -1, -1, -1)):
        """Distill the Head Features, so as to perform transfer learning.
        :param input_image: image tensor.
        :type input_image: <class 'paddle.fluid.framework.Variable'>
        :param trainable: whether to set parameters trainable.
        :type trainable: bool
        :param pretrained: whether to load default pretrained model.
        :type pretrained: bool
        :param param_prefix: the prefix of parameters.
        :type param_prefix: str
        :param get_prediction: whether to get prediction.
        :type get_prediction: bool
        :param extra_block_filters: in each extra block, params:
            [in_channel, out_channel, padding_size, stride_size, filter_size]
        :type extra_block_filters: list
        :param normalizations: params list of init scale in l2 norm, skip init
            scale if param is -1.
        :type normalizations: list
        """
        context_prog = input_image.block.program if input_image else fluid.Program(
        )
        startup_program = fluid.Program()
        with fluid.program_guard(context_prog, startup_program):
            image = input_image if input_image else fluid.data(
                name='image',
                shape=[-1, 3, 224, 224],
                dtype='float32',
                lod_level=0)

            backbone = VGGNet(layers=16)
            out = backbone.net(input=image, class_dim=5)
            # out = backbone(image)
            inputs = {'image': image}
            if get_prediction:
                outputs = {'pred_out': out}
            else:
                outputs = {'body_feats': out}

            place = fluid.CPUPlace()
            exe = fluid.Executor(place)
            if pretrained:

                def _if_exist(var):
                    return os.path.exists(
                        os.path.join(self.default_pretrained_model_path,
                                     var.name))

                if not param_prefix:
                    fluid.io.load_vars(
                        exe,
                        self.default_pretrained_model_path,
                        main_program=context_prog,
                        predicate=_if_exist)
            else:
                exe.run(startup_program)
            return inputs, outputs, context_prog

    def classification(self,
                       paths=None,
                       images=None,
                       use_gpu=False,
                       batch_size=1,
                       top_k=1):
        """API of Classification.
        :param paths: the path of images.
        :type paths: list, each element is correspond to the path of an image.
        :param images: data of images, [N, H, W, C]
        :type images: numpy.ndarray
        :param use_gpu: whether to use gpu or not.
        :type use_gpu: bool
        :param batch_size: bathc size.
        :type batch_size: int
        :param top_k: result of top k
        :type top_k: int
        """
        if self.infer_prog is None:
            inputs, outputs, self.infer_prog = self.context(
                trainable=False, pretrained=True, get_prediction=True)
            self.infer_prog = self.infer_prog.clone(for_test=True)
            self.pred_out = outputs['pred_out']
        place = fluid.CUDAPlace(0) if use_gpu else fluid.CPUPlace()
        exe = fluid.Executor(place)
        all_images = []
        paths = paths if paths else []
        for yield_data in test_reader(paths, images):
            all_images.append(yield_data)

        images_num = len(all_images)
        loop_num = int(np.ceil(images_num / batch_size))
        res_list = []
        top_k = max(min(top_k, 1000), 1)
        for iter_id in range(loop_num):
            batch_data = []
            handle_id = iter_id * batch_size
            for image_id in range(batch_size):
                try:
                    batch_data.append(all_images[handle_id + image_id])
                except:
                    pass
            batch_data = np.array(batch_data).astype('float32')
            data_tensor = PaddleTensor(batch_data.copy())
            if use_gpu:
                result = self.gpu_predictor.run([data_tensor])
            else:
                result = self.cpu_predictor.run([data_tensor])
            for i, res in enumerate(result[0].as_ndarray()):
                res_dict = {}
                pred_label = np.argsort(res)[::-1][:top_k]
                for k in pred_label:
                    class_name = self.label_names[int(k)].split(',')[0]
                    max_prob = res[k]
                    res_dict[class_name] = max_prob
                res_list.append(res_dict)
        return res_list

    def add_module_config_arg(self):
        """
        Add the command config options
        """
        self.arg_config_group.add_argument(
            '--use_gpu',
            type=ast.literal_eval,
            default=False,
            help="whether use GPU or not")

        self.arg_config_group.add_argument(
            '--batch_size',
            type=int,
            default=1,
            help="batch size for prediction")

    def add_module_input_arg(self):
        """
        Add the command input options
        """
        self.arg_input_group.add_argument(
            '--input_path', type=str, default=None, help="input data")

        self.arg_input_group.add_argument(
            '--input_file',
            type=str,
            default=None,
            help="file contain input data")

    def check_input_data(self, args):
        input_data = []
        if args.input_path:
            input_data = [args.input_path]
        elif args.input_file:
            if not os.path.exists(args.input_file):
                raise RuntimeError("File %s is not exist." % args.input_file)
            else:
                input_data = txt_parser.parse(args.input_file, use_strip=True)
        return input_data

    @runnable
    def run_cmd(self, argvs):
        self.parser = argparse.ArgumentParser(
            description="Run the {}".format(self.name),
            prog="hub run {}".format(self.name),
            usage='%(prog)s',
            add_help=True)
        self.arg_input_group = self.parser.add_argument_group(
            title="Input options", description="Input data. Required")
        self.arg_config_group = self.parser.add_argument_group(
            title="Config options",
            description=
            "Run configuration for controlling module behavior, not required.")
        self.add_module_config_arg()

        self.add_module_input_arg()
        args = self.parser.parse_args(argvs)
        input_data = self.check_input_data(args)
        if len(input_data) == 0:
            self.parser.print_help()
            exit(1)
        else:
            for image_path in input_data:
                if not os.path.exists(image_path):
                    raise RuntimeError(
                        "File %s or %s is not exist." % image_path)
        return self.classification(
            paths=input_data, use_gpu=args.use_gpu, batch_size=args.batch_size)

 

# 查看目錄結構
!tree VGG16/

 

VGG16/
├── assets
│   ├── infer_model
│   │   ├── conv1_1_offset
│   │   ├── conv1_1_weights
│   │   ├── conv1_2_offset
│   │   ├── conv1_2_weights
│   │   ├── conv2_1_offset
│   │   ├── conv2_1_weights
│   │   ├── conv2_2_offset
│   │   ├── conv2_2_weights
│   │   ├── conv3_1_offset
│   │   ├── conv3_1_weights
│   │   ├── conv3_2_offset
│   │   ├── conv3_2_weights
│   │   ├── conv3_3_offset
│   │   ├── conv3_3_weights
│   │   ├── conv4_1_offset
│   │   ├── conv4_1_weights
│   │   ├── conv4_2_offset
│   │   ├── conv4_2_weights
│   │   ├── conv4_3_offset
│   │   ├── conv4_3_weights
│   │   ├── conv5_1_offset
│   │   ├── conv5_1_weights
│   │   ├── conv5_2_offset
│   │   ├── conv5_2_weights
│   │   ├── conv5_3_offset
│   │   ├── conv5_3_weights
│   │   ├── fc6_offset
│   │   ├── fc6_weights
│   │   ├── fc7_offset
│   │   ├── fc7_weights
│   │   ├── fc8_offset
│   │   ├── fc8_weights
│   │   └── __model__
│   └── vocab.txt
├── data_feed.py
├── __init__.py
├── module.py
├── net.py
├── processor.py
└── __pycache__
    ├── data_feed.cpython-37.pyc
    ├── __init__.cpython-37.pyc
    ├── module.cpython-37.pyc
    ├── net.cpython-37.pyc
    └── processor.cpython-37.pyc

3 directories, 44 files

 

3、 測試Module

完成Module編寫後,咱們能夠經過如下方式測試該Module

1. 經過hub.Module(name=…)加載

將Module安裝到本機中,再經過hub.Module(name=…)加載

!hub install VGG16
!hub show VGG16

 

Successfully installed VGG16

+-----------------+----------------------------------------------------+
|   ModuleName    |VGG16                                               |
+-----------------+----------------------------------------------------+
|     Version     |1.1.0                                               |
+-----------------+----------------------------------------------------+
|     Summary     |VGG16 is a image classfication model trained with   |
|                 |Flower dataset.                              |
+-----------------+----------------------------------------------------+
|     Author      |paddlepaddle                                        |
+-----------------+----------------------------------------------------+
|  Author-Email   |paddle-dev@baidu.com                                |
+-----------------+----------------------------------------------------+
|    Location     |/home/aistudio/.paddlehub/modules/VGG16             |
+-----------------+----------------------------------------------------+

 

import paddlehub as hub

vgg16_test = hub.Module(name="VGG16")

test_img_path = "data/data2815/tulips/17165583356_38cb1f231d_n.jpg"

# execute predict and print the result
results = vgg16_test.classification(test_img_path)
# print(results)
for result in results:
    print(result)

 

[32m[2020-11-25 12:37:22,531] [    INFO] - Installing VGG16 module[0m
[32m[2020-11-25 12:37:22,533] [    INFO] - Module VGG16 already installed in /home/aistudio/.paddlehub/modules/VGG16[0m


{'dandelion': 0.24343227}

 

2. 直接經過hub.Module(directory=…)加載

 

import paddlehub as hub

vgg16_test = hub.Module(directory="VGG16/")

test_img_path = "data/data2815/tulips/17165583356_38cb1f231d_n.jpg"

# execute predict and print the result
results = vgg16_test.classification(test_img_path)
# print(results)
for result in results:
    print(result)

 

{'dandelion': 0.24343227}
下載安裝命令

## CPU版本安裝命令
pip install -f https://paddlepaddle.org.cn/pip/oschina/cpu paddlepaddle

## GPU版本安裝命令
pip install -f https://paddlepaddle.org.cn/pip/oschina/gpu paddlepaddle-gpu

在這裏插入圖片描述

本文同步分享在 博客「Mr.鄭先生_」(CSDN)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索