未验证 提交 8468e1ac 编写于 作者: K KP 提交者: GitHub

Remove fluid api in modules and pkg. (#1906)

上级 5294a272
...@@ -180,8 +180,10 @@ ...@@ -180,8 +180,10 @@
初始发布 初始发布
* 1.0.1 * 1.0.3
移除 fluid api
- ```shell - ```shell
$ hub install stylepro_artistic==1.0.1 $ hub install stylepro_artistic==1.0.3
``` ```
...@@ -179,8 +179,10 @@ ...@@ -179,8 +179,10 @@
First release First release
* 1.0.1 * 1.0.3
Remove fluid api
- ```shell - ```shell
$ hub install stylepro_artistic==1.0.1 $ hub install stylepro_artistic==1.0.3
``` ```
# coding=utf-8
from paddle.fluid.initializer import Constant
from paddle.fluid.param_attr import ParamAttr
import paddle.fluid as fluid
def decoder_net():
x2paddle_22 = fluid.layers.create_parameter(
dtype='float32', shape=[4], name='x2paddle_22', attr='x2paddle_22', default_initializer=Constant(0.0))
x2paddle_36 = fluid.layers.create_parameter(
dtype='float32', shape=[4], name='x2paddle_36', attr='x2paddle_36', default_initializer=Constant(0.0))
x2paddle_44 = fluid.layers.create_parameter(
dtype='float32', shape=[4], name='x2paddle_44', attr='x2paddle_44', default_initializer=Constant(0.0))
x2paddle_input_1 = fluid.layers.data(
dtype='float32', shape=[1, 512, 64, 64], name='x2paddle_input_1', append_batch_size=False)
x2paddle_19 = fluid.layers.pad2d(
x2paddle_input_1, pad_value=0.0, mode='reflect', paddings=[1, 1, 1, 1], name='x2paddle_19')
x2paddle_20 = fluid.layers.conv2d(
x2paddle_19,
num_filters=256,
filter_size=[3, 3],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='x2paddle_1',
name='x2paddle_20',
bias_attr='x2paddle_2')
x2paddle_21 = fluid.layers.relu(x2paddle_20, name='x2paddle_21')
x2paddle_23 = fluid.layers.resize_nearest(x2paddle_21, name='x2paddle_23', out_shape=[128, 128])
x2paddle_24 = fluid.layers.pad2d(
x2paddle_23, pad_value=0.0, mode='reflect', paddings=[1, 1, 1, 1], name='x2paddle_24')
x2paddle_25 = fluid.layers.conv2d(
x2paddle_24,
num_filters=256,
filter_size=[3, 3],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='x2paddle_3',
name='x2paddle_25',
bias_attr='x2paddle_4')
x2paddle_26 = fluid.layers.relu(x2paddle_25, name='x2paddle_26')
x2paddle_27 = fluid.layers.pad2d(
x2paddle_26, pad_value=0.0, mode='reflect', paddings=[1, 1, 1, 1], name='x2paddle_27')
x2paddle_28 = fluid.layers.conv2d(
x2paddle_27,
num_filters=256,
filter_size=[3, 3],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='x2paddle_5',
name='x2paddle_28',
bias_attr='x2paddle_6')
x2paddle_29 = fluid.layers.relu(x2paddle_28, name='x2paddle_29')
x2paddle_30 = fluid.layers.pad2d(
x2paddle_29, pad_value=0.0, mode='reflect', paddings=[1, 1, 1, 1], name='x2paddle_30')
x2paddle_31 = fluid.layers.conv2d(
x2paddle_30,
num_filters=256,
filter_size=[3, 3],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='x2paddle_7',
name='x2paddle_31',
bias_attr='x2paddle_8')
x2paddle_32 = fluid.layers.relu(x2paddle_31, name='x2paddle_32')
x2paddle_33 = fluid.layers.pad2d(
x2paddle_32, pad_value=0.0, mode='reflect', paddings=[1, 1, 1, 1], name='x2paddle_33')
x2paddle_34 = fluid.layers.conv2d(
x2paddle_33,
num_filters=128,
filter_size=[3, 3],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='x2paddle_9',
name='x2paddle_34',
bias_attr='x2paddle_10')
x2paddle_35 = fluid.layers.relu(x2paddle_34, name='x2paddle_35')
x2paddle_37 = fluid.layers.resize_nearest(x2paddle_35, name='x2paddle_37', out_shape=[256, 256])
x2paddle_38 = fluid.layers.pad2d(
x2paddle_37, pad_value=0.0, mode='reflect', paddings=[1, 1, 1, 1], name='x2paddle_38')
x2paddle_39 = fluid.layers.conv2d(
x2paddle_38,
num_filters=128,
filter_size=[3, 3],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='x2paddle_11',
name='x2paddle_39',
bias_attr='x2paddle_12')
x2paddle_40 = fluid.layers.relu(x2paddle_39, name='x2paddle_40')
x2paddle_41 = fluid.layers.pad2d(
x2paddle_40, pad_value=0.0, mode='reflect', paddings=[1, 1, 1, 1], name='x2paddle_41')
x2paddle_42 = fluid.layers.conv2d(
x2paddle_41,
num_filters=64,
filter_size=[3, 3],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='x2paddle_13',
name='x2paddle_42',
bias_attr='x2paddle_14')
x2paddle_43 = fluid.layers.relu(x2paddle_42, name='x2paddle_43')
x2paddle_45 = fluid.layers.resize_nearest(x2paddle_43, name='x2paddle_45', out_shape=[512, 512])
x2paddle_46 = fluid.layers.pad2d(
x2paddle_45, pad_value=0.0, mode='reflect', paddings=[1, 1, 1, 1], name='x2paddle_46')
x2paddle_47 = fluid.layers.conv2d(
x2paddle_46,
num_filters=64,
filter_size=[3, 3],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='x2paddle_15',
name='x2paddle_47',
bias_attr='x2paddle_16')
x2paddle_48 = fluid.layers.relu(x2paddle_47, name='x2paddle_48')
x2paddle_49 = fluid.layers.pad2d(
x2paddle_48, pad_value=0.0, mode='reflect', paddings=[1, 1, 1, 1], name='x2paddle_49')
x2paddle_50 = fluid.layers.conv2d(
x2paddle_49,
num_filters=3,
filter_size=[3, 3],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='x2paddle_17',
name='x2paddle_50',
bias_attr='x2paddle_18')
return x2paddle_input_1, x2paddle_50
# coding=utf-8
from paddle.fluid.initializer import Constant
from paddle.fluid.param_attr import ParamAttr
import paddle.fluid as fluid
def encoder_net():
x2paddle_0 = fluid.layers.data(dtype='float32', shape=[1, 3, 512, 512], name='x2paddle_0', append_batch_size=False)
x2paddle_21 = fluid.layers.conv2d(
x2paddle_0,
num_filters=3,
filter_size=[1, 1],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='x2paddle_1',
name='x2paddle_21',
bias_attr='x2paddle_2')
x2paddle_22 = fluid.layers.pad2d(
x2paddle_21, pad_value=0.0, mode='reflect', paddings=[1, 1, 1, 1], name='x2paddle_22')
x2paddle_23 = fluid.layers.conv2d(
x2paddle_22,
num_filters=64,
filter_size=[3, 3],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='x2paddle_3',
name='x2paddle_23',
bias_attr='x2paddle_4')
x2paddle_24 = fluid.layers.relu(x2paddle_23, name='x2paddle_24')
x2paddle_25 = fluid.layers.pad2d(
x2paddle_24, pad_value=0.0, mode='reflect', paddings=[1, 1, 1, 1], name='x2paddle_25')
x2paddle_26 = fluid.layers.conv2d(
x2paddle_25,
num_filters=64,
filter_size=[3, 3],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='x2paddle_5',
name='x2paddle_26',
bias_attr='x2paddle_6')
x2paddle_27 = fluid.layers.relu(x2paddle_26, name='x2paddle_27')
x2paddle_28 = fluid.layers.pool2d(
x2paddle_27,
pool_size=[2, 2],
pool_type='max',
pool_stride=[2, 2],
pool_padding=[0, 0],
ceil_mode=False,
name='x2paddle_28',
exclusive=False)
x2paddle_29 = fluid.layers.pad2d(
x2paddle_28, pad_value=0.0, mode='reflect', paddings=[1, 1, 1, 1], name='x2paddle_29')
x2paddle_30 = fluid.layers.conv2d(
x2paddle_29,
num_filters=128,
filter_size=[3, 3],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='x2paddle_7',
name='x2paddle_30',
bias_attr='x2paddle_8')
x2paddle_31 = fluid.layers.relu(x2paddle_30, name='x2paddle_31')
x2paddle_32 = fluid.layers.pad2d(
x2paddle_31, pad_value=0.0, mode='reflect', paddings=[1, 1, 1, 1], name='x2paddle_32')
x2paddle_33 = fluid.layers.conv2d(
x2paddle_32,
num_filters=128,
filter_size=[3, 3],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='x2paddle_9',
name='x2paddle_33',
bias_attr='x2paddle_10')
x2paddle_34 = fluid.layers.relu(x2paddle_33, name='x2paddle_34')
x2paddle_35 = fluid.layers.pool2d(
x2paddle_34,
pool_size=[2, 2],
pool_type='max',
pool_stride=[2, 2],
pool_padding=[0, 0],
ceil_mode=False,
name='x2paddle_35',
exclusive=False)
x2paddle_36 = fluid.layers.pad2d(
x2paddle_35, pad_value=0.0, mode='reflect', paddings=[1, 1, 1, 1], name='x2paddle_36')
x2paddle_37 = fluid.layers.conv2d(
x2paddle_36,
num_filters=256,
filter_size=[3, 3],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='x2paddle_11',
name='x2paddle_37',
bias_attr='x2paddle_12')
x2paddle_38 = fluid.layers.relu(x2paddle_37, name='x2paddle_38')
x2paddle_39 = fluid.layers.pad2d(
x2paddle_38, pad_value=0.0, mode='reflect', paddings=[1, 1, 1, 1], name='x2paddle_39')
x2paddle_40 = fluid.layers.conv2d(
x2paddle_39,
num_filters=256,
filter_size=[3, 3],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='x2paddle_13',
name='x2paddle_40',
bias_attr='x2paddle_14')
x2paddle_41 = fluid.layers.relu(x2paddle_40, name='x2paddle_41')
x2paddle_42 = fluid.layers.pad2d(
x2paddle_41, pad_value=0.0, mode='reflect', paddings=[1, 1, 1, 1], name='x2paddle_42')
x2paddle_43 = fluid.layers.conv2d(
x2paddle_42,
num_filters=256,
filter_size=[3, 3],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='x2paddle_15',
name='x2paddle_43',
bias_attr='x2paddle_16')
x2paddle_44 = fluid.layers.relu(x2paddle_43, name='x2paddle_44')
x2paddle_45 = fluid.layers.pad2d(
x2paddle_44, pad_value=0.0, mode='reflect', paddings=[1, 1, 1, 1], name='x2paddle_45')
x2paddle_46 = fluid.layers.conv2d(
x2paddle_45,
num_filters=256,
filter_size=[3, 3],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='x2paddle_17',
name='x2paddle_46',
bias_attr='x2paddle_18')
x2paddle_47 = fluid.layers.relu(x2paddle_46, name='x2paddle_47')
x2paddle_48 = fluid.layers.pool2d(
x2paddle_47,
pool_size=[2, 2],
pool_type='max',
pool_stride=[2, 2],
pool_padding=[0, 0],
ceil_mode=False,
name='x2paddle_48',
exclusive=False)
x2paddle_49 = fluid.layers.pad2d(
x2paddle_48, pad_value=0.0, mode='reflect', paddings=[1, 1, 1, 1], name='x2paddle_49')
x2paddle_50 = fluid.layers.conv2d(
x2paddle_49,
num_filters=512,
filter_size=[3, 3],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='x2paddle_19',
name='x2paddle_50',
bias_attr='x2paddle_20')
x2paddle_51 = fluid.layers.relu(x2paddle_50, name='x2paddle_51')
return x2paddle_0, x2paddle_51
...@@ -2,32 +2,38 @@ ...@@ -2,32 +2,38 @@
from __future__ import absolute_import from __future__ import absolute_import
from __future__ import division from __future__ import division
import argparse
import ast import ast
import copy import copy
import time
import os import os
import argparse import time
import numpy as np import numpy as np
import paddle.fluid as fluid import paddle
import paddlehub as hub from paddle.inference import Config
from paddle.fluid.core import PaddleTensor, AnalysisConfig, create_paddle_predictor from paddle.inference import create_predictor
from paddlehub.module.module import moduleinfo, runnable, serving
from stylepro_artistic.encoder_network import encoder_net
from stylepro_artistic.decoder_network import decoder_net
from stylepro_artistic.processor import postprocess, fr, cv2_to_base64, base64_to_cv2
from stylepro_artistic.data_feed import reader from stylepro_artistic.data_feed import reader
from stylepro_artistic.processor import base64_to_cv2
from stylepro_artistic.processor import cv2_to_base64
from stylepro_artistic.processor import fr
from stylepro_artistic.processor import postprocess
import paddlehub as hub
from paddlehub.module.module import moduleinfo
from paddlehub.module.module import runnable
from paddlehub.module.module import serving
# coding=utf-8
@moduleinfo( @moduleinfo(
name="stylepro_artistic", name="stylepro_artistic",
version="1.0.2", version="1.0.3",
type="cv/style_transfer", type="cv/style_transfer",
summary="StylePro Artistic is an algorithm for Arbitrary image style, which is parameter-free, fast yet effective.", summary="StylePro Artistic is an algorithm for Arbitrary image style, which is parameter-free, fast yet effective.",
author="baidu-bdl", author="baidu-bdl",
author_email="") author_email="")
class StyleProjection(hub.Module): class StyleProjection(hub.Module):
def _initialize(self): def _initialize(self):
self.pretrained_encoder_net = os.path.join(self.directory, "style_projection_enc") self.pretrained_encoder_net = os.path.join(self.directory, "style_projection_enc")
self.pretrained_decoder_net = os.path.join(self.directory, "style_projection_dec") self.pretrained_decoder_net = os.path.join(self.directory, "style_projection_dec")
...@@ -38,15 +44,15 @@ class StyleProjection(hub.Module): ...@@ -38,15 +44,15 @@ class StyleProjection(hub.Module):
predictor config setting predictor config setting
""" """
# encoder # encoder
cpu_config_enc = AnalysisConfig(self.pretrained_encoder_net) cpu_config_enc = Config(self.pretrained_encoder_net)
cpu_config_enc.disable_glog_info() cpu_config_enc.disable_glog_info()
cpu_config_enc.disable_gpu() cpu_config_enc.disable_gpu()
self.cpu_predictor_enc = create_paddle_predictor(cpu_config_enc) self.cpu_predictor_enc = create_predictor(cpu_config_enc)
# decoder # decoder
cpu_config_dec = AnalysisConfig(self.pretrained_decoder_net) cpu_config_dec = Config(self.pretrained_decoder_net)
cpu_config_dec.disable_glog_info() cpu_config_dec.disable_glog_info()
cpu_config_dec.disable_gpu() cpu_config_dec.disable_gpu()
self.cpu_predictor_dec = create_paddle_predictor(cpu_config_dec) self.cpu_predictor_dec = create_predictor(cpu_config_dec)
try: try:
_places = os.environ["CUDA_VISIBLE_DEVICES"] _places = os.environ["CUDA_VISIBLE_DEVICES"]
...@@ -56,15 +62,15 @@ class StyleProjection(hub.Module): ...@@ -56,15 +62,15 @@ class StyleProjection(hub.Module):
use_gpu = False use_gpu = False
if use_gpu: if use_gpu:
# encoder # encoder
gpu_config_enc = AnalysisConfig(self.pretrained_encoder_net) gpu_config_enc = Config(self.pretrained_encoder_net)
gpu_config_enc.disable_glog_info() gpu_config_enc.disable_glog_info()
gpu_config_enc.enable_use_gpu(memory_pool_init_size_mb=1000, device_id=0) gpu_config_enc.enable_use_gpu(memory_pool_init_size_mb=1000, device_id=0)
self.gpu_predictor_enc = create_paddle_predictor(gpu_config_enc) self.gpu_predictor_enc = create_predictor(gpu_config_enc)
# decoder # decoder
gpu_config_dec = AnalysisConfig(self.pretrained_decoder_net) gpu_config_dec = Config(self.pretrained_decoder_net)
gpu_config_dec.disable_glog_info() gpu_config_dec.disable_glog_info()
gpu_config_dec.enable_use_gpu(memory_pool_init_size_mb=1000, device_id=0) gpu_config_dec.enable_use_gpu(memory_pool_init_size_mb=1000, device_id=0)
self.gpu_predictor_dec = create_paddle_predictor(gpu_config_dec) self.gpu_predictor_dec = create_predictor(gpu_config_dec)
def style_transfer(self, def style_transfer(self,
images=None, images=None,
...@@ -102,22 +108,36 @@ class StyleProjection(hub.Module): ...@@ -102,22 +108,36 @@ class StyleProjection(hub.Module):
"Environment Variable CUDA_VISIBLE_DEVICES is not set correctly. If you wanna use gpu, please set CUDA_VISIBLE_DEVICES as cuda_device_id." "Environment Variable CUDA_VISIBLE_DEVICES is not set correctly. If you wanna use gpu, please set CUDA_VISIBLE_DEVICES as cuda_device_id."
) )
predictor_enc = self.gpu_predictor_enc if use_gpu else self.cpu_predictor_enc
input_names_enc = predictor_enc.get_input_names()
input_handle_enc = predictor_enc.get_input_handle(input_names_enc[0])
output_names_enc = predictor_enc.get_output_names()
output_handle_enc = predictor_enc.get_output_handle(output_names_enc[0])
predictor_dec = self.gpu_predictor_dec if use_gpu else self.cpu_predictor_dec
input_names_dec = predictor_dec.get_input_names()
input_handle_dec = predictor_dec.get_input_handle(input_names_dec[0])
output_names_dec = predictor_dec.get_output_names()
output_handle_dec = predictor_dec.get_output_handle(output_names_dec[0])
im_output = [] im_output = []
for component, w, h in reader(images, paths): for component, w, h in reader(images, paths):
content = PaddleTensor(component['content_arr'].copy()) input_handle_enc.copy_from_cpu(component['content_arr'])
content_feats = self.gpu_predictor_enc.run([content]) if use_gpu else self.cpu_predictor_enc.run([content]) predictor_enc.run()
content_feats = output_handle_enc.copy_to_cpu()
accumulate = np.zeros((3, 512, 512)) accumulate = np.zeros((3, 512, 512))
for idx, style_arr in enumerate(component['styles_arr_list']): for idx, style_arr in enumerate(component['styles_arr_list']):
style = PaddleTensor(style_arr.copy())
# encode # encode
style_feats = self.gpu_predictor_enc.run([style]) if use_gpu else self.cpu_predictor_enc.run([style]) input_handle_enc.copy_from_cpu(style_arr)
fr_feats = fr(content_feats[0].as_ndarray(), style_feats[0].as_ndarray(), alpha) predictor_enc.run()
fr_feats = PaddleTensor(fr_feats.copy()) style_feats = output_handle_enc.copy_to_cpu()
fr_feats = fr(content_feats, style_feats, alpha)
# decode # decode
predict_outputs = self.gpu_predictor_dec.run([fr_feats]) if use_gpu else self.cpu_predictor_dec.run( input_handle_dec.copy_from_cpu(fr_feats)
[fr_feats]) predictor_dec.run()
predict_outputs = output_handle_dec.copy_to_cpu()
# interpolation # interpolation
accumulate += predict_outputs[0].as_ndarray()[0] * component['style_interpolation_weights'][idx] accumulate += predict_outputs[0] * component['style_interpolation_weights'][idx]
# postprocess # postprocess
save_im_name = 'ndarray_{}.jpg'.format(time.time()) save_im_name = 'ndarray_{}.jpg'.format(time.time())
result = postprocess(accumulate, output_dir, save_im_name, visualization, size=(w, h)) result = postprocess(accumulate, output_dir, save_im_name, visualization, size=(w, h))
...@@ -134,39 +154,37 @@ class StyleProjection(hub.Module): ...@@ -134,39 +154,37 @@ class StyleProjection(hub.Module):
if combined: if combined:
model_filename = "__model__" if not model_filename else model_filename model_filename = "__model__" if not model_filename else model_filename
params_filename = "__params__" if not params_filename else params_filename params_filename = "__params__" if not params_filename else params_filename
place = fluid.CPUPlace() place = paddle.CPUPlace()
exe = fluid.Executor(place) exe = paddle.Executor(place)
encode_program, encode_feeded_var_names, encode_target_vars = fluid.io.load_inference_model( encode_program, encode_feeded_var_names, encode_target_vars = paddle.static.load_inference_model(
dirname=self.pretrained_encoder_net, executor=exe) dirname=self.pretrained_encoder_net, executor=exe)
fluid.io.save_inference_model( paddle.static.save_inference_model(dirname=dirname,
dirname=dirname, main_program=encode_program,
main_program=encode_program, executor=exe,
executor=exe, feeded_var_names=encode_feeded_var_names,
feeded_var_names=encode_feeded_var_names, target_vars=encode_target_vars,
target_vars=encode_target_vars, model_filename=model_filename,
model_filename=model_filename, params_filename=params_filename)
params_filename=params_filename)
def _save_decode_model(self, dirname, model_filename=None, params_filename=None, combined=True): def _save_decode_model(self, dirname, model_filename=None, params_filename=None, combined=True):
if combined: if combined:
model_filename = "__model__" if not model_filename else model_filename model_filename = "__model__" if not model_filename else model_filename
params_filename = "__params__" if not params_filename else params_filename params_filename = "__params__" if not params_filename else params_filename
place = fluid.CPUPlace() place = paddle.CPUPlace()
exe = fluid.Executor(place) exe = paddle.Executor(place)
decode_program, decode_feeded_var_names, decode_target_vars = fluid.io.load_inference_model( decode_program, decode_feeded_var_names, decode_target_vars = paddle.static.load_inference_model(
dirname=self.pretrained_decoder_net, executor=exe) dirname=self.pretrained_decoder_net, executor=exe)
fluid.io.save_inference_model( paddle.static.save_inference_model(dirname=dirname,
dirname=dirname, main_program=decode_program,
main_program=decode_program, executor=exe,
executor=exe, feeded_var_names=decode_feeded_var_names,
feeded_var_names=decode_feeded_var_names, target_vars=decode_target_vars,
target_vars=decode_target_vars, model_filename=model_filename,
model_filename=model_filename, params_filename=params_filename)
params_filename=params_filename)
@serving @serving
def serving_method(self, images, **kwargs): def serving_method(self, images, **kwargs):
...@@ -186,11 +204,10 @@ class StyleProjection(hub.Module): ...@@ -186,11 +204,10 @@ class StyleProjection(hub.Module):
""" """
Run as a command. Run as a command.
""" """
self.parser = argparse.ArgumentParser( self.parser = argparse.ArgumentParser(description="Run the {} module.".format(self.name),
description="Run the {} module.".format(self.name), prog='hub run {}'.format(self.name),
prog='hub run {}'.format(self.name), usage='%(prog)s',
usage='%(prog)s', add_help=True)
add_help=True)
self.arg_input_group = self.parser.add_argument_group(title="Input options", description="Input data. Required") 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( self.arg_config_group = self.parser.add_argument_group(
...@@ -202,20 +219,29 @@ class StyleProjection(hub.Module): ...@@ -202,20 +219,29 @@ class StyleProjection(hub.Module):
paths = [{'content': args.content, 'styles': args.styles.split(',')}] paths = [{'content': args.content, 'styles': args.styles.split(',')}]
else: else:
paths = [{'content': args.content, 'styles': args.styles.split(','), 'weights': list(args.weights)}] paths = [{'content': args.content, 'styles': args.styles.split(','), 'weights': list(args.weights)}]
results = self.style_transfer( results = self.style_transfer(paths=paths,
paths=paths, alpha=args.alpha, use_gpu=args.use_gpu, output_dir=args.output_dir, visualization=True) alpha=args.alpha,
use_gpu=args.use_gpu,
output_dir=args.output_dir,
visualization=True)
return results return results
def add_module_config_arg(self): def add_module_config_arg(self):
""" """
Add the command config options. Add the command config options.
""" """
self.arg_config_group.add_argument( self.arg_config_group.add_argument('--use_gpu',
'--use_gpu', type=ast.literal_eval, default=False, help="whether use GPU or not") type=ast.literal_eval,
self.arg_config_group.add_argument( default=False,
'--output_dir', type=str, default='transfer_result', help="The directory to save output images.") help="whether use GPU or not")
self.arg_config_group.add_argument( self.arg_config_group.add_argument('--output_dir',
'--visualization', type=ast.literal_eval, default=True, help="whether to save output as images.") type=str,
default='transfer_result',
help="The directory to save output images.")
self.arg_config_group.add_argument('--visualization',
type=ast.literal_eval,
default=True,
help="whether to save output as images.")
def add_module_input_arg(self): def add_module_input_arg(self):
""" """
...@@ -223,7 +249,11 @@ class StyleProjection(hub.Module): ...@@ -223,7 +249,11 @@ class StyleProjection(hub.Module):
""" """
self.arg_input_group.add_argument('--content', type=str, help="path to content.") self.arg_input_group.add_argument('--content', type=str, help="path to content.")
self.arg_input_group.add_argument('--styles', type=str, help="path to styles.") self.arg_input_group.add_argument('--styles', type=str, help="path to styles.")
self.arg_input_group.add_argument( self.arg_input_group.add_argument('--weights',
'--weights', type=ast.literal_eval, default=None, help="interpolation weights of styles.") type=ast.literal_eval,
self.arg_config_group.add_argument( default=None,
'--alpha', type=ast.literal_eval, default=1, help="The parameter to control the tranform degree.") help="interpolation weights of styles.")
self.arg_config_group.add_argument('--alpha',
type=ast.literal_eval,
default=1,
help="The parameter to control the tranform degree.")
# resnet50_vd_animals # resnet50_vd_animals
|模型名称|resnet50_vd_animals| |模型名称|resnet50_vd_animals|
| :--- | :---: | | :--- | :---: |
|类别|图像-图像分类| |类别|图像-图像分类|
|网络|ResNet50_vd| |网络|ResNet50_vd|
|数据集|百度自建动物数据集| |数据集|百度自建动物数据集|
...@@ -31,13 +31,13 @@ ...@@ -31,13 +31,13 @@
- ### 2、安装 - ### 2、安装
- ```shell - ```shell
$ hub install resnet50_vd_animals==1.0.0 $ hub install resnet50_vd_animals
``` ```
- 如您安装时遇到问题,可参考:[零基础windows安装](../../../../docs/docs_ch/get_start/windows_quickstart.md) - 如您安装时遇到问题,可参考:[零基础windows安装](../../../../docs/docs_ch/get_start/windows_quickstart.md)
| [零基础Linux安装](../../../../docs/docs_ch/get_start/linux_quickstart.md) | [零基础MacOS安装](../../../../docs/docs_ch/get_start/mac_quickstart.md) | [零基础Linux安装](../../../../docs/docs_ch/get_start/linux_quickstart.md) | [零基础MacOS安装](../../../../docs/docs_ch/get_start/mac_quickstart.md)
## 三、模型API预测 ## 三、模型API预测
- ### 1、命令行预测 - ### 1、命令行预测
- ``` - ```
...@@ -167,3 +167,11 @@ ...@@ -167,3 +167,11 @@
* 1.0.0 * 1.0.0
初始发布 初始发布
* 1.0.1
移除 fluid api
- ```shell
$ hub install resnet50_vd_animals==1.0.1
```
...@@ -171,3 +171,10 @@ ...@@ -171,3 +171,10 @@
First release First release
* 1.0.1
Remove fluid api
- ```shell
$ hub install resnet50_vd_animals==1.0.1
```
...@@ -2,22 +2,23 @@ ...@@ -2,22 +2,23 @@
from __future__ import absolute_import from __future__ import absolute_import
from __future__ import division from __future__ import division
import ast
import argparse import argparse
import ast
import os import os
import numpy as np import numpy as np
import paddle.fluid as fluid import paddle
import paddlehub as hub
from paddle.inference import Config from paddle.inference import Config
from paddle.inference import create_predictor from paddle.inference import create_predictor
from resnet50_vd_animals.data_feed import reader
from resnet50_vd_animals.processor import base64_to_cv2
from resnet50_vd_animals.processor import postprocess
from paddlehub.module.module import moduleinfo, runnable, serving import paddlehub as hub
from paddlehub.common.paddle_helper import add_vars_prefix from paddlehub.common.paddle_helper import add_vars_prefix
from paddlehub.module.module import moduleinfo
from resnet50_vd_animals.processor import postprocess, base64_to_cv2 from paddlehub.module.module import runnable
from resnet50_vd_animals.data_feed import reader from paddlehub.module.module import serving
from resnet50_vd_animals.resnet_vd import ResNet50_vd
@moduleinfo( @moduleinfo(
...@@ -26,8 +27,9 @@ from resnet50_vd_animals.resnet_vd import ResNet50_vd ...@@ -26,8 +27,9 @@ from resnet50_vd_animals.resnet_vd import ResNet50_vd
author="baidu-vis", author="baidu-vis",
author_email="", author_email="",
summary="ResNet50vd is a image classfication model, this module is trained with Baidu's self-built animals dataset.", summary="ResNet50vd is a image classfication model, this module is trained with Baidu's self-built animals dataset.",
version="1.0.0") version="1.0.1")
class ResNet50vdAnimals(hub.Module): class ResNet50vdAnimals(hub.Module):
def _initialize(self): def _initialize(self):
self.default_pretrained_model_path = os.path.join(self.directory, "model") self.default_pretrained_model_path = os.path.join(self.directory, "model")
label_file = os.path.join(self.directory, "label_list.txt") label_file = os.path.join(self.directory, "label_list.txt")
...@@ -97,54 +99,6 @@ class ResNet50vdAnimals(hub.Module): ...@@ -97,54 +99,6 @@ class ResNet50vdAnimals(hub.Module):
xpu_config.enable_xpu(100) xpu_config.enable_xpu(100)
self.xpu_predictor = create_predictor(xpu_config) self.xpu_predictor = create_predictor(xpu_config)
def context(self, trainable=True, pretrained=True):
"""context for transfer learning.
Args:
trainable (bool): Set parameters in program to be trainable.
pretrained (bool) : Whether to load pretrained model.
Returns:
inputs (dict): key is 'image', corresponding vaule is image tensor.
outputs (dict): key is :
'classification', corresponding value is the result of classification.
'feature_map', corresponding value is the result of the layer before the fully connected layer.
context_prog (fluid.Program): program for transfer learning.
"""
context_prog = fluid.Program()
startup_prog = fluid.Program()
with fluid.program_guard(context_prog, startup_prog):
with fluid.unique_name.guard():
image = fluid.layers.data(name="image", shape=[3, 224, 224], dtype="float32")
resnet_vd = ResNet50_vd()
output, feature_map = resnet_vd.net(input=image, class_dim=len(self.label_list))
name_prefix = '@HUB_{}@'.format(self.name)
inputs = {'image': name_prefix + image.name}
outputs = {'classification': name_prefix + output.name, 'feature_map': name_prefix + feature_map.name}
add_vars_prefix(context_prog, name_prefix)
add_vars_prefix(startup_prog, name_prefix)
global_vars = context_prog.global_block().vars
inputs = {key: global_vars[value] for key, value in inputs.items()}
outputs = {key: global_vars[value] for key, value in outputs.items()}
place = fluid.CPUPlace()
exe = fluid.Executor(place)
# pretrained
if pretrained:
def _if_exist(var):
b = os.path.exists(os.path.join(self.default_pretrained_model_path, var.name))
return b
fluid.io.load_vars(exe, self.default_pretrained_model_path, context_prog, predicate=_if_exist)
else:
exe.run(startup_prog)
# trainable
for param in context_prog.global_block().iter_parameters():
param.trainable = trainable
return inputs, outputs, context_prog
def classification(self, images=None, paths=None, batch_size=1, use_gpu=False, top_k=1, use_device=None): def classification(self, images=None, paths=None, batch_size=1, use_gpu=False, top_k=1, use_device=None):
""" """
API for image classification. API for image classification.
...@@ -215,19 +169,19 @@ class ResNet50vdAnimals(hub.Module): ...@@ -215,19 +169,19 @@ class ResNet50vdAnimals(hub.Module):
if combined: if combined:
model_filename = "__model__" if not model_filename else model_filename model_filename = "__model__" if not model_filename else model_filename
params_filename = "__params__" if not params_filename else params_filename params_filename = "__params__" if not params_filename else params_filename
place = fluid.CPUPlace() place = paddle.CPUPlace()
exe = fluid.Executor(place) exe = paddle.Executor(place)
program, feeded_var_names, target_vars = fluid.io.load_inference_model( program, feeded_var_names, target_vars = paddle.static.load_inference_model(
dirname=self.default_pretrained_model_path, executor=exe) dirname=self.default_pretrained_model_path, executor=exe)
fluid.io.save_inference_model(dirname=dirname, paddle.static.save_inference_model(dirname=dirname,
main_program=program, main_program=program,
executor=exe, executor=exe,
feeded_var_names=feeded_var_names, feeded_var_names=feeded_var_names,
target_vars=target_vars, target_vars=target_vars,
model_filename=model_filename, model_filename=model_filename,
params_filename=params_filename) params_filename=params_filename)
@serving @serving
def serving_method(self, images, **kwargs): def serving_method(self, images, **kwargs):
......
#copyright (c) 2019 PaddlePaddle Authors. All Rights Reserve.
#
#Licensed under the Apache License, Version 2.0 (the "License");
#you may not use this file except in compliance with the License.
#You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
#Unless required by applicable law or agreed to in writing, software
#distributed under the License is distributed on an "AS IS" BASIS,
#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#See the License for the specific language governing permissions and
#limitations under the License.
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import math
import paddle
import paddle.fluid as fluid
from paddle.fluid.param_attr import ParamAttr
__all__ = ["ResNet", "ResNet50_vd", "ResNet101_vd", "ResNet152_vd", "ResNet200_vd"]
train_parameters = {
"input_size": [3, 224, 224],
"input_mean": [0.485, 0.456, 0.406],
"input_std": [0.229, 0.224, 0.225],
"learning_strategy": {
"name": "piecewise_decay",
"batch_size": 256,
"epochs": [30, 60, 90],
"steps": [0.1, 0.01, 0.001, 0.0001]
}
}
class ResNet():
def __init__(self, layers=50, is_3x3=False):
self.params = train_parameters
self.layers = layers
self.is_3x3 = is_3x3
def net(self, input, class_dim=1000):
is_3x3 = self.is_3x3
layers = self.layers
supported_layers = [50, 101, 152, 200]
assert layers in supported_layers, \
"supported layers are {} but input layer is {}".format(supported_layers, layers)
if layers == 50:
depth = [3, 4, 6, 3]
elif layers == 101:
depth = [3, 4, 23, 3]
elif layers == 152:
depth = [3, 8, 36, 3]
elif layers == 200:
depth = [3, 12, 48, 3]
num_filters = [64, 128, 256, 512]
if is_3x3 == False:
conv = self.conv_bn_layer(input=input, num_filters=64, filter_size=7, stride=2, act='relu')
else:
conv = self.conv_bn_layer(input=input, num_filters=32, filter_size=3, stride=2, act='relu', name='conv1_1')
conv = self.conv_bn_layer(input=conv, num_filters=32, filter_size=3, stride=1, act='relu', name='conv1_2')
conv = self.conv_bn_layer(input=conv, num_filters=64, filter_size=3, stride=1, act='relu', name='conv1_3')
conv = fluid.layers.pool2d(input=conv, pool_size=3, pool_stride=2, pool_padding=1, pool_type='max')
for block in range(len(depth)):
for i in range(depth[block]):
if layers in [101, 152, 200] and block == 2:
if i == 0:
conv_name = "res" + str(block + 2) + "a"
else:
conv_name = "res" + str(block + 2) + "b" + str(i)
else:
conv_name = "res" + str(block + 2) + chr(97 + i)
conv = self.bottleneck_block(
input=conv,
num_filters=num_filters[block],
stride=2 if i == 0 and block != 0 else 1,
if_first=block == 0,
name=conv_name)
pool = fluid.layers.pool2d(input=conv, pool_size=7, pool_type='avg', global_pooling=True)
stdv = 1.0 / math.sqrt(pool.shape[1] * 1.0)
out = fluid.layers.fc(
input=pool,
size=class_dim,
param_attr=fluid.param_attr.ParamAttr(initializer=fluid.initializer.Uniform(-stdv, stdv)))
return out, pool
def conv_bn_layer(self, input, num_filters, filter_size, stride=1, groups=1, act=None, name=None):
conv = fluid.layers.conv2d(
input=input,
num_filters=num_filters,
filter_size=filter_size,
stride=stride,
padding=(filter_size - 1) // 2,
groups=groups,
act=None,
param_attr=ParamAttr(name=name + "_weights"),
bias_attr=False)
if name == "conv1":
bn_name = "bn_" + name
else:
bn_name = "bn" + name[3:]
return fluid.layers.batch_norm(
input=conv,
act=act,
param_attr=ParamAttr(name=bn_name + '_scale'),
bias_attr=ParamAttr(bn_name + '_offset'),
moving_mean_name=bn_name + '_mean',
moving_variance_name=bn_name + '_variance')
def conv_bn_layer_new(self, input, num_filters, filter_size, stride=1, groups=1, act=None, name=None):
pool = fluid.layers.pool2d(input=input, pool_size=2, pool_stride=2, pool_padding=0, pool_type='avg')
conv = fluid.layers.conv2d(
input=pool,
num_filters=num_filters,
filter_size=filter_size,
stride=1,
padding=(filter_size - 1) // 2,
groups=groups,
act=None,
param_attr=ParamAttr(name=name + "_weights"),
bias_attr=False)
if name == "conv1":
bn_name = "bn_" + name
else:
bn_name = "bn" + name[3:]
return fluid.layers.batch_norm(
input=conv,
act=act,
param_attr=ParamAttr(name=bn_name + '_scale'),
bias_attr=ParamAttr(bn_name + '_offset'),
moving_mean_name=bn_name + '_mean',
moving_variance_name=bn_name + '_variance')
def shortcut(self, input, ch_out, stride, name, if_first=False):
ch_in = input.shape[1]
if ch_in != ch_out or stride != 1:
if if_first:
return self.conv_bn_layer(input, ch_out, 1, stride, name=name)
else:
return self.conv_bn_layer_new(input, ch_out, 1, stride, name=name)
else:
return input
def bottleneck_block(self, input, num_filters, stride, name, if_first):
conv0 = self.conv_bn_layer(
input=input, num_filters=num_filters, filter_size=1, act='relu', name=name + "_branch2a")
conv1 = self.conv_bn_layer(
input=conv0, num_filters=num_filters, filter_size=3, stride=stride, act='relu', name=name + "_branch2b")
conv2 = self.conv_bn_layer(
input=conv1, num_filters=num_filters * 4, filter_size=1, act=None, name=name + "_branch2c")
short = self.shortcut(input, num_filters * 4, stride, if_first=if_first, name=name + "_branch1")
return fluid.layers.elementwise_add(x=short, y=conv2, act='relu')
def ResNet50_vd():
model = ResNet(layers=50, is_3x3=True)
return model
def ResNet101_vd():
model = ResNet(layers=101, is_3x3=True)
return model
def ResNet152_vd():
model = ResNet(layers=152, is_3x3=True)
return model
def ResNet200_vd():
model = ResNet(layers=200, is_3x3=True)
return model
...@@ -163,8 +163,10 @@ ...@@ -163,8 +163,10 @@
初始发布 初始发布
* 1.2.0 * 1.2.1
移除 fluid api
- ```shell - ```shell
$ hub install pyramidbox_lite_mobile==1.2.0 $ hub install pyramidbox_lite_mobile==1.2.1
``` ```
...@@ -162,8 +162,10 @@ ...@@ -162,8 +162,10 @@
First release First release
* 1.2.0 * 1.2.1
Remove fluid api
- ```shell - ```shell
$ hub install pyramidbox_lite_mobile==1.2.0 $ hub install pyramidbox_lite_mobile==1.2.1
``` ```
...@@ -2,28 +2,32 @@ ...@@ -2,28 +2,32 @@
from __future__ import absolute_import from __future__ import absolute_import
from __future__ import division from __future__ import division
import ast
import argparse import argparse
import ast
import os import os
import numpy as np import numpy as np
import paddle.fluid as fluid import paddle
import paddlehub as hub from paddle.inference import Config
from paddle.fluid.core import PaddleTensor, AnalysisConfig, create_paddle_predictor from paddle.inference import create_predictor
from paddlehub.module.module import moduleinfo, runnable, serving
from pyramidbox_lite_mobile.data_feed import reader from pyramidbox_lite_mobile.data_feed import reader
from pyramidbox_lite_mobile.processor import postprocess, base64_to_cv2 from pyramidbox_lite_mobile.processor import base64_to_cv2
from pyramidbox_lite_mobile.processor import postprocess
import paddlehub as hub
from paddlehub.module.module import moduleinfo
from paddlehub.module.module import runnable
from paddlehub.module.module import serving
@moduleinfo(
name="pyramidbox_lite_mobile", @moduleinfo(name="pyramidbox_lite_mobile",
type="CV/face_detection", type="CV/face_detection",
author="baidu-vis", author="baidu-vis",
author_email="", author_email="",
summary="PyramidBox-Lite-Mobile is a high-performance face detection model.", summary="PyramidBox-Lite-Mobile is a high-performance face detection model.",
version="1.2.0") version="1.2.1")
class PyramidBoxLiteMobile(hub.Module): class PyramidBoxLiteMobile(hub.Module):
def _initialize(self): def _initialize(self):
self.default_pretrained_model_path = os.path.join(self.directory, "pyramidbox_lite_mobile_face_detection") self.default_pretrained_model_path = os.path.join(self.directory, "pyramidbox_lite_mobile_face_detection")
self._set_config() self._set_config()
...@@ -33,10 +37,10 @@ class PyramidBoxLiteMobile(hub.Module): ...@@ -33,10 +37,10 @@ class PyramidBoxLiteMobile(hub.Module):
""" """
predictor config setting predictor config setting
""" """
cpu_config = AnalysisConfig(self.default_pretrained_model_path) cpu_config = Config(self.default_pretrained_model_path)
cpu_config.disable_glog_info() cpu_config.disable_glog_info()
cpu_config.disable_gpu() cpu_config.disable_gpu()
self.cpu_predictor = create_paddle_predictor(cpu_config) self.cpu_predictor = create_predictor(cpu_config)
try: try:
_places = os.environ["CUDA_VISIBLE_DEVICES"] _places = os.environ["CUDA_VISIBLE_DEVICES"]
...@@ -45,10 +49,10 @@ class PyramidBoxLiteMobile(hub.Module): ...@@ -45,10 +49,10 @@ class PyramidBoxLiteMobile(hub.Module):
except: except:
use_gpu = False use_gpu = False
if use_gpu: if use_gpu:
gpu_config = AnalysisConfig(self.default_pretrained_model_path) gpu_config = Config(self.default_pretrained_model_path)
gpu_config.disable_glog_info() gpu_config.disable_glog_info()
gpu_config.enable_use_gpu(memory_pool_init_size_mb=1000, device_id=0) gpu_config.enable_use_gpu(memory_pool_init_size_mb=1000, device_id=0)
self.gpu_predictor = create_paddle_predictor(gpu_config) self.gpu_predictor = create_predictor(gpu_config)
def face_detection(self, def face_detection(self,
images=None, images=None,
...@@ -98,18 +102,26 @@ class PyramidBoxLiteMobile(hub.Module): ...@@ -98,18 +102,26 @@ class PyramidBoxLiteMobile(hub.Module):
# process one by one # process one by one
for element in reader(images, paths, shrink): for element in reader(images, paths, shrink):
image = np.expand_dims(element['image'], axis=0).astype('float32') image = np.expand_dims(element['image'], axis=0).astype('float32')
image_tensor = PaddleTensor(image.copy())
data_out = self.gpu_predictor.run([image_tensor]) if use_gpu else self.cpu_predictor.run([image_tensor]) predictor = self.gpu_predictor if use_gpu else self.cpu_predictor
out = postprocess( input_names = predictor.get_input_names()
data_out=data_out[0].as_ndarray(), input_handle = predictor.get_input_handle(input_names[0])
org_im=element['org_im'], input_handle.copy_from_cpu(image)
org_im_path=element['org_im_path'],
image_width=element['image_width'], predictor.run()
image_height=element['image_height'], output_names = predictor.get_output_names()
output_dir=output_dir, output_handle = predictor.get_output_handle(output_names[0])
visualization=visualization, output_data = output_handle.copy_to_cpu()
shrink=shrink,
confs_threshold=confs_threshold) out = postprocess(data_out=output_data,
org_im=element['org_im'],
org_im_path=element['org_im_path'],
image_width=element['image_width'],
image_height=element['image_height'],
output_dir=output_dir,
visualization=visualization,
shrink=shrink,
confs_threshold=confs_threshold)
res.append(out) res.append(out)
return res return res
...@@ -117,23 +129,21 @@ class PyramidBoxLiteMobile(hub.Module): ...@@ -117,23 +129,21 @@ class PyramidBoxLiteMobile(hub.Module):
if combined: if combined:
model_filename = "__model__" if not model_filename else model_filename model_filename = "__model__" if not model_filename else model_filename
params_filename = "__params__" if not params_filename else params_filename params_filename = "__params__" if not params_filename else params_filename
place = fluid.CPUPlace() place = paddle.CPUPlace()
exe = fluid.Executor(place) exe = paddle.Executor(place)
program, feeded_var_names, target_vars = fluid.io.load_inference_model( program, feeded_var_names, target_vars = paddle.static.load_inference_model(
dirname=self.default_pretrained_model_path, executor=exe) dirname=self.default_pretrained_model_path, executor=exe)
var = program.global_block().vars['detection_output_0.tmp_1'] var = program.global_block().vars['detection_output_0.tmp_1']
var.desc.set_dtype(fluid.core.VarDesc.VarType.INT32)
fluid.io.save_inference_model( paddle.static.save_inference_model(dirname=dirname,
dirname=dirname, main_program=program,
main_program=program, executor=exe,
executor=exe, feeded_var_names=feeded_var_names,
feeded_var_names=feeded_var_names, target_vars=target_vars,
target_vars=target_vars, model_filename=model_filename,
model_filename=model_filename, params_filename=params_filename)
params_filename=params_filename)
@serving @serving
def serving_method(self, images, **kwargs): def serving_method(self, images, **kwargs):
...@@ -149,36 +159,40 @@ class PyramidBoxLiteMobile(hub.Module): ...@@ -149,36 +159,40 @@ class PyramidBoxLiteMobile(hub.Module):
""" """
Run as a command. Run as a command.
""" """
self.parser = argparse.ArgumentParser( self.parser = argparse.ArgumentParser(description="Run the {} module.".format(self.name),
description="Run the {} module.".format(self.name), prog='hub run {}'.format(self.name),
prog='hub run {}'.format(self.name), usage='%(prog)s',
usage='%(prog)s', add_help=True)
add_help=True)
self.arg_input_group = self.parser.add_argument_group(title="Input options", description="Input data. Required") 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( self.arg_config_group = self.parser.add_argument_group(
title="Config options", description="Run configuration for controlling module behavior, not required.") title="Config options", description="Run configuration for controlling module behavior, not required.")
self.add_module_config_arg() self.add_module_config_arg()
self.add_module_input_arg() self.add_module_input_arg()
args = self.parser.parse_args(argvs) args = self.parser.parse_args(argvs)
results = self.face_detection( results = self.face_detection(paths=[args.input_path],
paths=[args.input_path], use_gpu=args.use_gpu,
use_gpu=args.use_gpu, output_dir=args.output_dir,
output_dir=args.output_dir, visualization=args.visualization,
visualization=args.visualization, shrink=args.shrink,
shrink=args.shrink, confs_threshold=args.confs_threshold)
confs_threshold=args.confs_threshold)
return results return results
def add_module_config_arg(self): def add_module_config_arg(self):
""" """
Add the command config options. Add the command config options.
""" """
self.arg_config_group.add_argument( self.arg_config_group.add_argument('--use_gpu',
'--use_gpu', type=ast.literal_eval, default=False, help="whether use GPU or not") type=ast.literal_eval,
self.arg_config_group.add_argument( default=False,
'--output_dir', type=str, default='detection_result', help="The directory to save output images.") help="whether use GPU or not")
self.arg_config_group.add_argument( self.arg_config_group.add_argument('--output_dir',
'--visualization', type=ast.literal_eval, default=False, help="whether to save output as images.") type=str,
default='detection_result',
help="The directory to save output images.")
self.arg_config_group.add_argument('--visualization',
type=ast.literal_eval,
default=False,
help="whether to save output as images.")
def add_module_input_arg(self): def add_module_input_arg(self):
""" """
...@@ -190,5 +204,7 @@ class PyramidBoxLiteMobile(hub.Module): ...@@ -190,5 +204,7 @@ class PyramidBoxLiteMobile(hub.Module):
type=ast.literal_eval, type=ast.literal_eval,
default=0.5, default=0.5,
help="resize the image to shrink * original_shape before feeding into network.") help="resize the image to shrink * original_shape before feeding into network.")
self.arg_input_group.add_argument( self.arg_input_group.add_argument('--confs_threshold',
'--confs_threshold', type=ast.literal_eval, default=0.6, help="confidence threshold.") type=ast.literal_eval,
default=0.6,
help="confidence threshold.")
...@@ -208,7 +208,10 @@ ...@@ -208,7 +208,10 @@
初始发布 初始发布
* 1.3.0 * 1.3.1
移除 fluid api
- ```shell - ```shell
$ hub install pyramidbox_lite_mobile_mask==1.3.0 $ hub install pyramidbox_lite_mobile_mask==1.3.1
``` ```
...@@ -184,7 +184,10 @@ ...@@ -184,7 +184,10 @@
First release First release
* 1.3.0 * 1.3.1
Remove fluid api
- ```shell - ```shell
$ hub install pyramidbox_lite_mobile_mask==1.3.0 $ hub install pyramidbox_lite_mobile_mask==1.3.1
``` ```
...@@ -2,18 +2,22 @@ ...@@ -2,18 +2,22 @@
from __future__ import absolute_import from __future__ import absolute_import
from __future__ import division from __future__ import division
import ast
import argparse import argparse
import ast
import os import os
import numpy as np import numpy as np
import paddle.fluid as fluid import paddle
import paddlehub as hub from paddle.inference import Config
from paddle.fluid.core import PaddleTensor, AnalysisConfig, create_paddle_predictor from paddle.inference import create_predictor
from paddlehub.module.module import moduleinfo, runnable, serving
from pyramidbox_lite_mobile_mask.data_feed import reader from pyramidbox_lite_mobile_mask.data_feed import reader
from pyramidbox_lite_mobile_mask.processor import postprocess, base64_to_cv2 from pyramidbox_lite_mobile_mask.processor import base64_to_cv2
from pyramidbox_lite_mobile_mask.processor import postprocess
import paddlehub as hub
from paddlehub.module.module import moduleinfo
from paddlehub.module.module import runnable
from paddlehub.module.module import serving
@moduleinfo( @moduleinfo(
...@@ -23,8 +27,9 @@ from pyramidbox_lite_mobile_mask.processor import postprocess, base64_to_cv2 ...@@ -23,8 +27,9 @@ from pyramidbox_lite_mobile_mask.processor import postprocess, base64_to_cv2
author_email="", author_email="",
summary= summary=
"Pyramidbox-Lite-Mobile-Mask is a high-performance face detection model used to detect whether people wear masks.", "Pyramidbox-Lite-Mobile-Mask is a high-performance face detection model used to detect whether people wear masks.",
version="1.3.0") version="1.3.1")
class PyramidBoxLiteMobileMask(hub.Module): class PyramidBoxLiteMobileMask(hub.Module):
def _initialize(self, face_detector_module=None): def _initialize(self, face_detector_module=None):
""" """
Args: Args:
...@@ -42,10 +47,10 @@ class PyramidBoxLiteMobileMask(hub.Module): ...@@ -42,10 +47,10 @@ class PyramidBoxLiteMobileMask(hub.Module):
""" """
predictor config setting predictor config setting
""" """
cpu_config = AnalysisConfig(self.default_pretrained_model_path) cpu_config = Config(self.default_pretrained_model_path)
cpu_config.disable_glog_info() cpu_config.disable_glog_info()
cpu_config.disable_gpu() cpu_config.disable_gpu()
self.cpu_predictor = create_paddle_predictor(cpu_config) self.cpu_predictor = create_predictor(cpu_config)
try: try:
_places = os.environ["CUDA_VISIBLE_DEVICES"] _places = os.environ["CUDA_VISIBLE_DEVICES"]
...@@ -54,10 +59,10 @@ class PyramidBoxLiteMobileMask(hub.Module): ...@@ -54,10 +59,10 @@ class PyramidBoxLiteMobileMask(hub.Module):
except: except:
use_gpu = False use_gpu = False
if use_gpu: if use_gpu:
gpu_config = AnalysisConfig(self.default_pretrained_model_path) gpu_config = Config(self.default_pretrained_model_path)
gpu_config.disable_glog_info() gpu_config.disable_glog_info()
gpu_config.enable_use_gpu(memory_pool_init_size_mb=1000, device_id=0) gpu_config.enable_use_gpu(memory_pool_init_size_mb=1000, device_id=0)
self.gpu_predictor = create_paddle_predictor(gpu_config) self.gpu_predictor = create_predictor(gpu_config)
def set_face_detector_module(self, face_detector_module): def set_face_detector_module(self, face_detector_module):
""" """
...@@ -146,12 +151,18 @@ class PyramidBoxLiteMobileMask(hub.Module): ...@@ -146,12 +151,18 @@ class PyramidBoxLiteMobileMask(hub.Module):
pass pass
image_arr = np.squeeze(np.array(batch_data), axis=1) image_arr = np.squeeze(np.array(batch_data), axis=1)
image_tensor = PaddleTensor(image_arr.copy())
data_out = self.gpu_predictor.run([image_tensor]) if use_gpu else self.cpu_predictor.run([image_tensor]) predictor = self.gpu_predictor if use_gpu else self.cpu_predictor
# len(data_out) == 1 input_names = predictor.get_input_names()
# data_out[0].as_ndarray().shape == (-1, 2) input_handle = predictor.get_input_handle(input_names[0])
data_out = data_out[0].as_ndarray() input_handle.copy_from_cpu(image_arr)
predict_out = np.concatenate((predict_out, data_out))
predictor.run()
output_names = predictor.get_output_names()
output_handle = predictor.get_output_handle(output_names[0])
output_data = output_handle.copy_to_cpu()
predict_out = np.concatenate((predict_out, output_data))
predict_out = predict_out[1:] predict_out = predict_out[1:]
# postprocess one by one # postprocess one by one
...@@ -160,13 +171,12 @@ class PyramidBoxLiteMobileMask(hub.Module): ...@@ -160,13 +171,12 @@ class PyramidBoxLiteMobileMask(hub.Module):
detect_faces_list = [handled['face'] for handled in all_element[i]['preprocessed']] detect_faces_list = [handled['face'] for handled in all_element[i]['preprocessed']]
interval_left = sum(element_image_num[0:i]) interval_left = sum(element_image_num[0:i])
interval_right = interval_left + element_image_num[i] interval_right = interval_left + element_image_num[i]
out = postprocess( out = postprocess(confidence_out=predict_out[interval_left:interval_right],
confidence_out=predict_out[interval_left:interval_right], org_im=all_element[i]['org_im'],
org_im=all_element[i]['org_im'], org_im_path=all_element[i]['org_im_path'],
org_im_path=all_element[i]['org_im_path'], detected_faces=detect_faces_list,
detected_faces=detect_faces_list, output_dir=output_dir,
output_dir=output_dir, visualization=visualization)
visualization=visualization)
res.append(out) res.append(out)
return res return res
...@@ -183,20 +193,19 @@ class PyramidBoxLiteMobileMask(hub.Module): ...@@ -183,20 +193,19 @@ class PyramidBoxLiteMobileMask(hub.Module):
if combined: if combined:
model_filename = "__model__" if not model_filename else model_filename model_filename = "__model__" if not model_filename else model_filename
params_filename = "__params__" if not params_filename else params_filename params_filename = "__params__" if not params_filename else params_filename
place = fluid.CPUPlace() place = paddle.CPUPlace()
exe = fluid.Executor(place) exe = paddle.Executor(place)
program, feeded_var_names, target_vars = fluid.io.load_inference_model( program, feeded_var_names, target_vars = paddle.static.load_inference_model(
dirname=self.default_pretrained_model_path, executor=exe) dirname=self.default_pretrained_model_path, executor=exe)
fluid.io.save_inference_model( paddle.static.save_inference_model(dirname=dirname,
dirname=dirname, main_program=program,
main_program=program, executor=exe,
executor=exe, feeded_var_names=feeded_var_names,
feeded_var_names=feeded_var_names, target_vars=target_vars,
target_vars=target_vars, model_filename=model_filename,
model_filename=model_filename, params_filename=params_filename)
params_filename=params_filename)
@serving @serving
def serving_method(self, images, **kwargs): def serving_method(self, images, **kwargs):
...@@ -212,36 +221,40 @@ class PyramidBoxLiteMobileMask(hub.Module): ...@@ -212,36 +221,40 @@ class PyramidBoxLiteMobileMask(hub.Module):
""" """
Run as a command. Run as a command.
""" """
self.parser = argparse.ArgumentParser( self.parser = argparse.ArgumentParser(description="Run the {} module.".format(self.name),
description="Run the {} module.".format(self.name), prog='hub run {}'.format(self.name),
prog='hub run {}'.format(self.name), usage='%(prog)s',
usage='%(prog)s', add_help=True)
add_help=True)
self.arg_input_group = self.parser.add_argument_group(title="Input options", description="Input data. Required") 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( self.arg_config_group = self.parser.add_argument_group(
title="Config options", description="Run configuration for controlling module behavior, not required.") title="Config options", description="Run configuration for controlling module behavior, not required.")
self.add_module_config_arg() self.add_module_config_arg()
self.add_module_input_arg() self.add_module_input_arg()
args = self.parser.parse_args(argvs) args = self.parser.parse_args(argvs)
results = self.face_detection( results = self.face_detection(paths=[args.input_path],
paths=[args.input_path], use_gpu=args.use_gpu,
use_gpu=args.use_gpu, output_dir=args.output_dir,
output_dir=args.output_dir, visualization=args.visualization,
visualization=args.visualization, shrink=args.shrink,
shrink=args.shrink, confs_threshold=args.confs_threshold)
confs_threshold=args.confs_threshold)
return results return results
def add_module_config_arg(self): def add_module_config_arg(self):
""" """
Add the command config options. Add the command config options.
""" """
self.arg_config_group.add_argument( self.arg_config_group.add_argument('--use_gpu',
'--use_gpu', type=ast.literal_eval, default=False, help="whether use GPU or not") type=ast.literal_eval,
self.arg_config_group.add_argument( default=False,
'--output_dir', type=str, default='detection_result', help="The directory to save output images.") help="whether use GPU or not")
self.arg_config_group.add_argument( self.arg_config_group.add_argument('--output_dir',
'--visualization', type=ast.literal_eval, default=False, help="whether to save output as images.") type=str,
default='detection_result',
help="The directory to save output images.")
self.arg_config_group.add_argument('--visualization',
type=ast.literal_eval,
default=False,
help="whether to save output as images.")
def add_module_input_arg(self): def add_module_input_arg(self):
""" """
...@@ -253,5 +266,7 @@ class PyramidBoxLiteMobileMask(hub.Module): ...@@ -253,5 +266,7 @@ class PyramidBoxLiteMobileMask(hub.Module):
type=ast.literal_eval, type=ast.literal_eval,
default=0.5, default=0.5,
help="resize the image to `shrink * original_shape` before feeding into network.") help="resize the image to `shrink * original_shape` before feeding into network.")
self.arg_input_group.add_argument( self.arg_input_group.add_argument('--confs_threshold',
'--confs_threshold', type=ast.literal_eval, default=0.6, help="confidence threshold.") type=ast.literal_eval,
default=0.6,
help="confidence threshold.")
...@@ -166,6 +166,11 @@ ...@@ -166,6 +166,11 @@
* 1.2.0 * 1.2.0
修复numpy数据读取问题 修复numpy数据读取问题
* 1.2.1
移除 fluid api
- ```shell - ```shell
$ hub install pyramidbox_lite_server==1.2.0 $ hub install pyramidbox_lite_server==1.2.1
``` ```
...@@ -166,6 +166,11 @@ ...@@ -166,6 +166,11 @@
* 1.2.0 * 1.2.0
Fix the problem of reading numpy Fix the problem of reading numpy
* 1.2.1
Remove fluid api
- ```shell - ```shell
$ hub install pyramidbox_lite_server==1.2.0 $ hub install pyramidbox_lite_server==1.2.1
``` ```
...@@ -2,28 +2,32 @@ ...@@ -2,28 +2,32 @@
from __future__ import absolute_import from __future__ import absolute_import
from __future__ import division from __future__ import division
import ast
import argparse import argparse
import ast
import os import os
import numpy as np import numpy as np
import paddle.fluid as fluid import paddle
import paddlehub as hub from paddle.inference import Config
from paddle.fluid.core import PaddleTensor, AnalysisConfig, create_paddle_predictor from paddle.inference import create_predictor
from paddlehub.module.module import moduleinfo, runnable, serving
from pyramidbox_lite_server.data_feed import reader from pyramidbox_lite_server.data_feed import reader
from pyramidbox_lite_server.processor import postprocess, base64_to_cv2 from pyramidbox_lite_server.processor import base64_to_cv2
from pyramidbox_lite_server.processor import postprocess
import paddlehub as hub
from paddlehub.module.module import moduleinfo
from paddlehub.module.module import runnable
from paddlehub.module.module import serving
@moduleinfo(
name="pyramidbox_lite_server", @moduleinfo(name="pyramidbox_lite_server",
type="CV/face_detection", type="CV/face_detection",
author="baidu-vis", author="baidu-vis",
author_email="", author_email="",
summary="PyramidBox-Lite-Server is a high-performance face detection model.", summary="PyramidBox-Lite-Server is a high-performance face detection model.",
version="1.2.0") version="1.2.1")
class PyramidBoxLiteServer(hub.Module): class PyramidBoxLiteServer(hub.Module):
def _initialize(self): def _initialize(self):
self.default_pretrained_model_path = os.path.join(self.directory, "pyramidbox_lite_server_face_detection") self.default_pretrained_model_path = os.path.join(self.directory, "pyramidbox_lite_server_face_detection")
self._set_config() self._set_config()
...@@ -33,10 +37,10 @@ class PyramidBoxLiteServer(hub.Module): ...@@ -33,10 +37,10 @@ class PyramidBoxLiteServer(hub.Module):
""" """
predictor config setting predictor config setting
""" """
cpu_config = AnalysisConfig(self.default_pretrained_model_path) cpu_config = Config(self.default_pretrained_model_path)
cpu_config.disable_glog_info() cpu_config.disable_glog_info()
cpu_config.disable_gpu() cpu_config.disable_gpu()
self.cpu_predictor = create_paddle_predictor(cpu_config) self.cpu_predictor = create_predictor(cpu_config)
try: try:
_places = os.environ["CUDA_VISIBLE_DEVICES"] _places = os.environ["CUDA_VISIBLE_DEVICES"]
...@@ -45,10 +49,10 @@ class PyramidBoxLiteServer(hub.Module): ...@@ -45,10 +49,10 @@ class PyramidBoxLiteServer(hub.Module):
except: except:
use_gpu = False use_gpu = False
if use_gpu: if use_gpu:
gpu_config = AnalysisConfig(self.default_pretrained_model_path) gpu_config = Config(self.default_pretrained_model_path)
gpu_config.disable_glog_info() gpu_config.disable_glog_info()
gpu_config.enable_use_gpu(memory_pool_init_size_mb=1000, device_id=0) gpu_config.enable_use_gpu(memory_pool_init_size_mb=1000, device_id=0)
self.gpu_predictor = create_paddle_predictor(gpu_config) self.gpu_predictor = create_predictor(gpu_config)
def face_detection(self, def face_detection(self,
images=None, images=None,
...@@ -98,18 +102,26 @@ class PyramidBoxLiteServer(hub.Module): ...@@ -98,18 +102,26 @@ class PyramidBoxLiteServer(hub.Module):
# process one by one # process one by one
for element in reader(images, paths, shrink): for element in reader(images, paths, shrink):
image = np.expand_dims(element['image'], axis=0).astype('float32') image = np.expand_dims(element['image'], axis=0).astype('float32')
image_tensor = PaddleTensor(image.copy())
data_out = self.gpu_predictor.run([image_tensor]) if use_gpu else self.cpu_predictor.run([image_tensor]) predictor = self.gpu_predictor if use_gpu else self.cpu_predictor
out = postprocess( input_names = predictor.get_input_names()
data_out=data_out[0].as_ndarray(), input_handle = predictor.get_input_handle(input_names[0])
org_im=element['org_im'], input_handle.copy_from_cpu(image)
org_im_path=element['org_im_path'],
image_width=element['image_width'], predictor.run()
image_height=element['image_height'], output_names = predictor.get_output_names()
output_dir=output_dir, output_handle = predictor.get_output_handle(output_names[0])
visualization=visualization, output_data = output_handle.copy_to_cpu()
shrink=shrink,
confs_threshold=confs_threshold) out = postprocess(data_out=output_data,
org_im=element['org_im'],
org_im_path=element['org_im_path'],
image_width=element['image_width'],
image_height=element['image_height'],
output_dir=output_dir,
visualization=visualization,
shrink=shrink,
confs_threshold=confs_threshold)
res.append(out) res.append(out)
return res return res
...@@ -117,20 +129,19 @@ class PyramidBoxLiteServer(hub.Module): ...@@ -117,20 +129,19 @@ class PyramidBoxLiteServer(hub.Module):
if combined: if combined:
model_filename = "__model__" if not model_filename else model_filename model_filename = "__model__" if not model_filename else model_filename
params_filename = "__params__" if not params_filename else params_filename params_filename = "__params__" if not params_filename else params_filename
place = fluid.CPUPlace() place = paddle.CPUPlace()
exe = fluid.Executor(place) exe = paddle.Executor(place)
program, feeded_var_names, target_vars = fluid.io.load_inference_model( program, feeded_var_names, target_vars = paddle.static.load_inference_model(
dirname=self.default_pretrained_model_path, executor=exe) dirname=self.default_pretrained_model_path, executor=exe)
fluid.io.save_inference_model( paddle.static.save_inference_model(dirname=dirname,
dirname=dirname, main_program=program,
main_program=program, executor=exe,
executor=exe, feeded_var_names=feeded_var_names,
feeded_var_names=feeded_var_names, target_vars=target_vars,
target_vars=target_vars, model_filename=model_filename,
model_filename=model_filename, params_filename=params_filename)
params_filename=params_filename)
@serving @serving
def serving_method(self, images, **kwargs): def serving_method(self, images, **kwargs):
...@@ -146,36 +157,40 @@ class PyramidBoxLiteServer(hub.Module): ...@@ -146,36 +157,40 @@ class PyramidBoxLiteServer(hub.Module):
""" """
Run as a command. Run as a command.
""" """
self.parser = argparse.ArgumentParser( self.parser = argparse.ArgumentParser(description="Run the {} module.".format(self.name),
description="Run the {} module.".format(self.name), prog='hub run {}'.format(self.name),
prog='hub run {}'.format(self.name), usage='%(prog)s',
usage='%(prog)s', add_help=True)
add_help=True)
self.arg_input_group = self.parser.add_argument_group(title="Input options", description="Input data. Required") 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( self.arg_config_group = self.parser.add_argument_group(
title="Config options", description="Run configuration for controlling module behavior, not required.") title="Config options", description="Run configuration for controlling module behavior, not required.")
self.add_module_config_arg() self.add_module_config_arg()
self.add_module_input_arg() self.add_module_input_arg()
args = self.parser.parse_args(argvs) args = self.parser.parse_args(argvs)
results = self.face_detection( results = self.face_detection(paths=[args.input_path],
paths=[args.input_path], use_gpu=args.use_gpu,
use_gpu=args.use_gpu, output_dir=args.output_dir,
output_dir=args.output_dir, visualization=args.visualization,
visualization=args.visualization, shrink=args.shrink,
shrink=args.shrink, confs_threshold=args.confs_threshold)
confs_threshold=args.confs_threshold)
return results return results
def add_module_config_arg(self): def add_module_config_arg(self):
""" """
Add the command config options. Add the command config options.
""" """
self.arg_config_group.add_argument( self.arg_config_group.add_argument('--use_gpu',
'--use_gpu', type=ast.literal_eval, default=False, help="whether use GPU or not") type=ast.literal_eval,
self.arg_config_group.add_argument( default=False,
'--output_dir', type=str, default='detection_result', help="The directory to save output images.") help="whether use GPU or not")
self.arg_config_group.add_argument( self.arg_config_group.add_argument('--output_dir',
'--visualization', type=ast.literal_eval, default=False, help="whether to save output as images.") type=str,
default='detection_result',
help="The directory to save output images.")
self.arg_config_group.add_argument('--visualization',
type=ast.literal_eval,
default=False,
help="whether to save output as images.")
def add_module_input_arg(self): def add_module_input_arg(self):
""" """
...@@ -187,5 +202,7 @@ class PyramidBoxLiteServer(hub.Module): ...@@ -187,5 +202,7 @@ class PyramidBoxLiteServer(hub.Module):
type=ast.literal_eval, type=ast.literal_eval,
default=0.5, default=0.5,
help="resize the image to shrink * original_shape before feeding into network.") help="resize the image to shrink * original_shape before feeding into network.")
self.arg_input_group.add_argument( self.arg_input_group.add_argument('--confs_threshold',
'--confs_threshold', type=ast.literal_eval, default=0.6, help="confidence threshold.") type=ast.literal_eval,
default=0.6,
help="confidence threshold.")
...@@ -208,7 +208,10 @@ ...@@ -208,7 +208,10 @@
初始发布 初始发布
* 1.3.1 * 1.3.2
移除 fluid api
- ```shell - ```shell
$ hub install pyramidbox_lite_server_mask==1.3.1 $ hub install pyramidbox_lite_server_mask==1.3.2
``` ```
...@@ -185,7 +185,10 @@ ...@@ -185,7 +185,10 @@
First release First release
* 1.3.1 * 1.3.2
Remove fluid api
- ```shell - ```shell
$ hub install pyramidbox_lite_server_mask==1.3.1 $ hub install pyramidbox_lite_server_mask==1.3.2
``` ```
...@@ -2,18 +2,22 @@ ...@@ -2,18 +2,22 @@
from __future__ import absolute_import from __future__ import absolute_import
from __future__ import division from __future__ import division
import ast
import argparse import argparse
import ast
import os import os
import numpy as np import numpy as np
import paddle.fluid as fluid import paddle
import paddlehub as hub from paddle.inference import Config
from paddle.fluid.core import PaddleTensor, AnalysisConfig, create_paddle_predictor from paddle.inference import create_predictor
from paddlehub.module.module import moduleinfo, runnable, serving
from pyramidbox_lite_server_mask.data_feed import reader from pyramidbox_lite_server_mask.data_feed import reader
from pyramidbox_lite_server_mask.processor import postprocess, base64_to_cv2 from pyramidbox_lite_server_mask.processor import base64_to_cv2
from pyramidbox_lite_server_mask.processor import postprocess
import paddlehub as hub
from paddlehub.module.module import moduleinfo
from paddlehub.module.module import runnable
from paddlehub.module.module import serving
@moduleinfo( @moduleinfo(
...@@ -23,15 +27,15 @@ from pyramidbox_lite_server_mask.processor import postprocess, base64_to_cv2 ...@@ -23,15 +27,15 @@ from pyramidbox_lite_server_mask.processor import postprocess, base64_to_cv2
author_email="", author_email="",
summary= summary=
"PyramidBox-Lite-Server-Mask is a high-performance face detection model used to detect whether people wear masks.", "PyramidBox-Lite-Server-Mask is a high-performance face detection model used to detect whether people wear masks.",
version="1.3.1") version="1.3.2")
class PyramidBoxLiteServerMask(hub.Module): class PyramidBoxLiteServerMask(hub.Module):
def _initialize(self, face_detector_module=None): def _initialize(self, face_detector_module=None):
""" """
Args: Args:
face_detector_module (class): module to detect face. face_detector_module (class): module to detect face.
""" """
self.default_pretrained_model_path = os.path.join( self.default_pretrained_model_path = os.path.join(self.directory, "pyramidbox_lite_server_mask_model")
self.directory, "pyramidbox_lite_server_mask_model")
if face_detector_module is None: if face_detector_module is None:
self.face_detector = hub.Module(name='pyramidbox_lite_server') self.face_detector = hub.Module(name='pyramidbox_lite_server')
else: else:
...@@ -43,10 +47,10 @@ class PyramidBoxLiteServerMask(hub.Module): ...@@ -43,10 +47,10 @@ class PyramidBoxLiteServerMask(hub.Module):
""" """
predictor config setting predictor config setting
""" """
cpu_config = AnalysisConfig(self.default_pretrained_model_path) cpu_config = Config(self.default_pretrained_model_path)
cpu_config.disable_glog_info() cpu_config.disable_glog_info()
cpu_config.disable_gpu() cpu_config.disable_gpu()
self.cpu_predictor = create_paddle_predictor(cpu_config) self.cpu_predictor = create_predictor(cpu_config)
try: try:
_places = os.environ["CUDA_VISIBLE_DEVICES"] _places = os.environ["CUDA_VISIBLE_DEVICES"]
...@@ -55,11 +59,10 @@ class PyramidBoxLiteServerMask(hub.Module): ...@@ -55,11 +59,10 @@ class PyramidBoxLiteServerMask(hub.Module):
except: except:
use_gpu = False use_gpu = False
if use_gpu: if use_gpu:
gpu_config = AnalysisConfig(self.default_pretrained_model_path) gpu_config = Config(self.default_pretrained_model_path)
gpu_config.disable_glog_info() gpu_config.disable_glog_info()
gpu_config.enable_use_gpu( gpu_config.enable_use_gpu(memory_pool_init_size_mb=1000, device_id=0)
memory_pool_init_size_mb=1000, device_id=0) self.gpu_predictor = create_predictor(gpu_config)
self.gpu_predictor = create_paddle_predictor(gpu_config)
def set_face_detector_module(self, face_detector_module): def set_face_detector_module(self, face_detector_module):
""" """
...@@ -123,16 +126,13 @@ class PyramidBoxLiteServerMask(hub.Module): ...@@ -123,16 +126,13 @@ class PyramidBoxLiteServerMask(hub.Module):
# get all data # get all data
all_element = list() all_element = list()
for yield_data in reader(self.face_detector, shrink, confs_threshold, for yield_data in reader(self.face_detector, shrink, confs_threshold, images, paths, use_gpu, use_multi_scale):
images, paths, use_gpu, use_multi_scale):
all_element.append(yield_data) all_element.append(yield_data)
image_list = list() image_list = list()
element_image_num = list() element_image_num = list()
for i in range(len(all_element)): for i in range(len(all_element)):
element_image = [ element_image = [handled['image'] for handled in all_element[i]['preprocessed']]
handled['image'] for handled in all_element[i]['preprocessed']
]
element_image_num.append(len(element_image)) element_image_num.append(len(element_image))
image_list.extend(element_image) image_list.extend(element_image)
...@@ -150,76 +150,61 @@ class PyramidBoxLiteServerMask(hub.Module): ...@@ -150,76 +150,61 @@ class PyramidBoxLiteServerMask(hub.Module):
pass pass
image_arr = np.squeeze(np.array(batch_data), axis=1) image_arr = np.squeeze(np.array(batch_data), axis=1)
image_tensor = PaddleTensor(image_arr.copy())
data_out = self.gpu_predictor.run([ predictor = self.gpu_predictor if use_gpu else self.cpu_predictor
image_tensor input_names = predictor.get_input_names()
]) if use_gpu else self.cpu_predictor.run([image_tensor]) input_handle = predictor.get_input_handle(input_names[0])
# len(data_out) == 1 input_handle.copy_from_cpu(image_arr)
# data_out[0].as_ndarray().shape == (-1, 2)
data_out = data_out[0].as_ndarray() predictor.run()
predict_out = np.concatenate((predict_out, data_out)) output_names = predictor.get_output_names()
output_handle = predictor.get_output_handle(output_names[0])
output_data = output_handle.copy_to_cpu()
predict_out = np.concatenate((predict_out, output_data))
predict_out = predict_out[1:] predict_out = predict_out[1:]
# postprocess one by one # postprocess one by one
res = list() res = list()
for i in range(len(all_element)): for i in range(len(all_element)):
detect_faces_list = [ detect_faces_list = [handled['face'] for handled in all_element[i]['preprocessed']]
handled['face'] for handled in all_element[i]['preprocessed']
]
interval_left = sum(element_image_num[0:i]) interval_left = sum(element_image_num[0:i])
interval_right = interval_left + element_image_num[i] interval_right = interval_left + element_image_num[i]
out = postprocess( out = postprocess(confidence_out=predict_out[interval_left:interval_right],
confidence_out=predict_out[interval_left:interval_right], org_im=all_element[i]['org_im'],
org_im=all_element[i]['org_im'], org_im_path=all_element[i]['org_im_path'],
org_im_path=all_element[i]['org_im_path'], detected_faces=detect_faces_list,
detected_faces=detect_faces_list, output_dir=output_dir,
output_dir=output_dir, visualization=visualization)
visualization=visualization)
res.append(out) res.append(out)
return res return res
def save_inference_model(self, def save_inference_model(self, dirname, model_filename=None, params_filename=None, combined=True):
dirname,
model_filename=None,
params_filename=None,
combined=True):
classifier_dir = os.path.join(dirname, 'mask_detector') classifier_dir = os.path.join(dirname, 'mask_detector')
detector_dir = os.path.join(dirname, 'pyramidbox_lite') detector_dir = os.path.join(dirname, 'pyramidbox_lite')
self._save_classifier_model(classifier_dir, model_filename, self._save_classifier_model(classifier_dir, model_filename, params_filename, combined)
params_filename, combined) self._save_detector_model(detector_dir, model_filename, params_filename, combined)
self._save_detector_model(detector_dir, model_filename, params_filename,
combined) def _save_detector_model(self, dirname, model_filename=None, params_filename=None, combined=True):
self.face_detector.save_inference_model(dirname, model_filename, params_filename, combined)
def _save_detector_model(self,
dirname, def _save_classifier_model(self, dirname, model_filename=None, params_filename=None, combined=True):
model_filename=None,
params_filename=None,
combined=True):
self.face_detector.save_inference_model(dirname, model_filename,
params_filename, combined)
def _save_classifier_model(self,
dirname,
model_filename=None,
params_filename=None,
combined=True):
if combined: if combined:
model_filename = "__model__" if not model_filename else model_filename model_filename = "__model__" if not model_filename else model_filename
params_filename = "__params__" if not params_filename else params_filename params_filename = "__params__" if not params_filename else params_filename
place = fluid.CPUPlace() place = paddle.CPUPlace()
exe = fluid.Executor(place) exe = paddle.Executor(place)
program, feeded_var_names, target_vars = fluid.io.load_inference_model( program, feeded_var_names, target_vars = paddle.static.load_inference_model(
dirname=self.default_pretrained_model_path, executor=exe) dirname=self.default_pretrained_model_path, executor=exe)
fluid.io.save_inference_model( paddle.static.save_inference_model(dirname=dirname,
dirname=dirname, main_program=program,
main_program=program, executor=exe,
executor=exe, feeded_var_names=feeded_var_names,
feeded_var_names=feeded_var_names, target_vars=target_vars,
target_vars=target_vars, model_filename=model_filename,
model_filename=model_filename, params_filename=params_filename)
params_filename=params_filename)
@serving @serving
def serving_method(self, images, **kwargs): def serving_method(self, images, **kwargs):
...@@ -235,64 +220,52 @@ class PyramidBoxLiteServerMask(hub.Module): ...@@ -235,64 +220,52 @@ class PyramidBoxLiteServerMask(hub.Module):
""" """
Run as a command. Run as a command.
""" """
self.parser = argparse.ArgumentParser( self.parser = argparse.ArgumentParser(description="Run the {} module.".format(self.name),
description="Run the {} module.".format(self.name), prog='hub run {}'.format(self.name),
prog='hub run {}'.format(self.name), usage='%(prog)s',
usage='%(prog)s', add_help=True)
add_help=True) self.arg_input_group = self.parser.add_argument_group(title="Input options", description="Input data. Required")
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( self.arg_config_group = self.parser.add_argument_group(
title="Config options", title="Config options", description="Run configuration for controlling module behavior, not required.")
description=
"Run configuration for controlling module behavior, not required.")
self.add_module_config_arg() self.add_module_config_arg()
self.add_module_input_arg() self.add_module_input_arg()
args = self.parser.parse_args(argvs) args = self.parser.parse_args(argvs)
results = self.face_detection( results = self.face_detection(paths=[args.input_path],
paths=[args.input_path], use_gpu=args.use_gpu,
use_gpu=args.use_gpu, output_dir=args.output_dir,
output_dir=args.output_dir, visualization=args.visualization,
visualization=args.visualization, shrink=args.shrink,
shrink=args.shrink, confs_threshold=args.confs_threshold)
confs_threshold=args.confs_threshold)
return results return results
def add_module_config_arg(self): def add_module_config_arg(self):
""" """
Add the command config options. Add the command config options.
""" """
self.arg_config_group.add_argument( self.arg_config_group.add_argument('--use_gpu',
'--use_gpu', type=ast.literal_eval,
type=ast.literal_eval, default=False,
default=False, help="whether use GPU or not")
help="whether use GPU or not") self.arg_config_group.add_argument('--output_dir',
self.arg_config_group.add_argument( type=str,
'--output_dir', default='detection_result',
type=str, help="The directory to save output images.")
default='detection_result', self.arg_config_group.add_argument('--visualization',
help="The directory to save output images.") type=ast.literal_eval,
self.arg_config_group.add_argument( default=False,
'--visualization', help="whether to save output as images.")
type=ast.literal_eval,
default=False,
help="whether to save output as images.")
def add_module_input_arg(self): def add_module_input_arg(self):
""" """
Add the command input options. Add the command input options.
""" """
self.arg_input_group.add_argument( self.arg_input_group.add_argument('--input_path', type=str, help="path to image.")
'--input_path', type=str, help="path to image.")
self.arg_input_group.add_argument( self.arg_input_group.add_argument(
'--shrink', '--shrink',
type=ast.literal_eval, type=ast.literal_eval,
default=0.5, default=0.5,
help= help="resize the image to `shrink * original_shape` before feeding into network.")
"resize the image to `shrink * original_shape` before feeding into network." self.arg_input_group.add_argument('--confs_threshold',
) type=ast.literal_eval,
self.arg_input_group.add_argument( default=0.6,
'--confs_threshold', help="confidence threshold.")
type=ast.literal_eval,
default=0.6,
help="confidence threshold.")
...@@ -164,7 +164,10 @@ ...@@ -164,7 +164,10 @@
初始发布 初始发布
* 1.1.2 * 1.1.3
移除 fluid api
- ```shell - ```shell
$ hub install ultra_light_fast_generic_face_detector_1mb_320==1.1.2 $ hub install ultra_light_fast_generic_face_detector_1mb_320==1.1.3
``` ```
...@@ -163,7 +163,10 @@ ...@@ -163,7 +163,10 @@
First release First release
* 1.1.2 * 1.1.3
Remove fluid api
- ```shell - ```shell
$ hub install ultra_light_fast_generic_face_detector_1mb_320==1.1.2 $ hub install ultra_light_fast_generic_face_detector_1mb_320==1.1.3
``` ```
# coding=utf-8
from paddle.fluid.initializer import Constant
from paddle.fluid.param_attr import ParamAttr
import paddle.fluid as fluid
def face_detector_320():
_319 = fluid.layers.fill_constant(shape=[1], dtype='int32', value=0)
_322 = fluid.layers.fill_constant(shape=[1], dtype='int32', value=-1)
_323 = fluid.layers.fill_constant(shape=[1], dtype='int32', value=2)
_333 = fluid.layers.fill_constant(shape=[1], dtype='int32', value=0)
_336 = fluid.layers.fill_constant(shape=[1], dtype='int32', value=-1)
_337 = fluid.layers.fill_constant(shape=[1], dtype='int32', value=4)
_365 = fluid.layers.fill_constant(shape=[1], dtype='int32', value=0)
_368 = fluid.layers.fill_constant(shape=[1], dtype='int32', value=-1)
_369 = fluid.layers.fill_constant(shape=[1], dtype='int32', value=2)
_379 = fluid.layers.fill_constant(shape=[1], dtype='int32', value=0)
_382 = fluid.layers.fill_constant(shape=[1], dtype='int32', value=-1)
_383 = fluid.layers.fill_constant(shape=[1], dtype='int32', value=4)
_405 = fluid.layers.fill_constant(shape=[1], dtype='int32', value=0)
_408 = fluid.layers.fill_constant(shape=[1], dtype='int32', value=-1)
_409 = fluid.layers.fill_constant(shape=[1], dtype='int32', value=2)
_419 = fluid.layers.fill_constant(shape=[1], dtype='int32', value=0)
_422 = fluid.layers.fill_constant(shape=[1], dtype='int32', value=-1)
_423 = fluid.layers.fill_constant(shape=[1], dtype='int32', value=4)
_437 = fluid.layers.fill_constant(shape=[1], dtype='int32', value=0)
_440 = fluid.layers.fill_constant(shape=[1], dtype='int32', value=-1)
_441 = fluid.layers.fill_constant(shape=[1], dtype='int32', value=2)
_449 = fluid.layers.fill_constant(shape=[1], dtype='int32', value=0)
_452 = fluid.layers.fill_constant(shape=[1], dtype='int32', value=-1)
_453 = fluid.layers.fill_constant(shape=[1], dtype='int32', value=4)
_463 = fluid.layers.fill_constant(shape=[1], dtype='float32', value=0.10000000149011612)
_465 = fluid.layers.create_parameter(
dtype='float32', shape=[1, 4420, 2], name='_465', attr='_465', default_initializer=Constant(0.0))
_467 = fluid.layers.create_parameter(
dtype='float32', shape=[1, 4420, 2], name='_467', attr='_467', default_initializer=Constant(0.0))
_470 = fluid.layers.fill_constant(shape=[1], dtype='float32', value=0.20000000298023224)
_473 = fluid.layers.create_parameter(
dtype='float32', shape=[1, 4420, 2], name='_473', attr='_473', default_initializer=Constant(0.0))
_478 = fluid.layers.fill_constant(shape=[1], dtype='float32', value=2.0)
_483 = fluid.layers.fill_constant(shape=[1], dtype='float32', value=2.0)
_input = fluid.layers.data(dtype='float32', shape=[1, 3, 240, 320], name='_input', append_batch_size=False)
_325 = fluid.layers.assign(_322)
_326 = fluid.layers.assign(_323)
_339 = fluid.layers.assign(_336)
_340 = fluid.layers.assign(_337)
_371 = fluid.layers.assign(_368)
_372 = fluid.layers.assign(_369)
_385 = fluid.layers.assign(_382)
_386 = fluid.layers.assign(_383)
_411 = fluid.layers.assign(_408)
_412 = fluid.layers.assign(_409)
_425 = fluid.layers.assign(_422)
_426 = fluid.layers.assign(_423)
_443 = fluid.layers.assign(_440)
_444 = fluid.layers.assign(_441)
_455 = fluid.layers.assign(_452)
_456 = fluid.layers.assign(_453)
_245 = fluid.layers.conv2d(
_input,
num_filters=16,
filter_size=[3, 3],
stride=[2, 2],
padding=[1, 1],
dilation=[1, 1],
groups=1,
param_attr='_base_net_0_0_weight',
name='_245',
bias_attr=False)
_246 = fluid.layers.batch_norm(
_245,
momentum=0.8999999761581421,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_0_1_weight',
bias_attr='_base_net_0_1_bias',
moving_mean_name='_base_net_0_1_running_mean',
moving_variance_name='_base_net_0_1_running_var',
use_global_stats=False,
name='_246')
_247 = fluid.layers.relu(_246, name='_247')
_248 = fluid.layers.conv2d(
_247,
num_filters=16,
filter_size=[3, 3],
stride=[1, 1],
padding=[1, 1],
dilation=[1, 1],
groups=16,
param_attr='_base_net_1_0_weight',
name='_248',
bias_attr=False)
_249 = fluid.layers.batch_norm(
_248,
momentum=0.8999999761581421,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_1_1_weight',
bias_attr='_base_net_1_1_bias',
moving_mean_name='_base_net_1_1_running_mean',
moving_variance_name='_base_net_1_1_running_var',
use_global_stats=False,
name='_249')
_250 = fluid.layers.relu(_249, name='_250')
_251 = fluid.layers.conv2d(
_250,
num_filters=32,
filter_size=[1, 1],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='_base_net_1_3_weight',
name='_251',
bias_attr=False)
_252 = fluid.layers.batch_norm(
_251,
momentum=0.8999999761581421,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_1_4_weight',
bias_attr='_base_net_1_4_bias',
moving_mean_name='_base_net_1_4_running_mean',
moving_variance_name='_base_net_1_4_running_var',
use_global_stats=False,
name='_252')
_253 = fluid.layers.relu(_252, name='_253')
_254 = fluid.layers.conv2d(
_253,
num_filters=32,
filter_size=[3, 3],
stride=[2, 2],
padding=[1, 1],
dilation=[1, 1],
groups=32,
param_attr='_base_net_2_0_weight',
name='_254',
bias_attr=False)
_255 = fluid.layers.batch_norm(
_254,
momentum=0.8999999761581421,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_2_1_weight',
bias_attr='_base_net_2_1_bias',
moving_mean_name='_base_net_2_1_running_mean',
moving_variance_name='_base_net_2_1_running_var',
use_global_stats=False,
name='_255')
_256 = fluid.layers.relu(_255, name='_256')
_257 = fluid.layers.conv2d(
_256,
num_filters=32,
filter_size=[1, 1],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='_base_net_2_3_weight',
name='_257',
bias_attr=False)
_258 = fluid.layers.batch_norm(
_257,
momentum=0.8999999761581421,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_2_4_weight',
bias_attr='_base_net_2_4_bias',
moving_mean_name='_base_net_2_4_running_mean',
moving_variance_name='_base_net_2_4_running_var',
use_global_stats=False,
name='_258')
_259 = fluid.layers.relu(_258, name='_259')
_260 = fluid.layers.conv2d(
_259,
num_filters=32,
filter_size=[3, 3],
stride=[1, 1],
padding=[1, 1],
dilation=[1, 1],
groups=32,
param_attr='_base_net_3_0_weight',
name='_260',
bias_attr=False)
_261 = fluid.layers.batch_norm(
_260,
momentum=0.8999999761581421,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_3_1_weight',
bias_attr='_base_net_3_1_bias',
moving_mean_name='_base_net_3_1_running_mean',
moving_variance_name='_base_net_3_1_running_var',
use_global_stats=False,
name='_261')
_262 = fluid.layers.relu(_261, name='_262')
_263 = fluid.layers.conv2d(
_262,
num_filters=32,
filter_size=[1, 1],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='_base_net_3_3_weight',
name='_263',
bias_attr=False)
_264 = fluid.layers.batch_norm(
_263,
momentum=0.8999999761581421,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_3_4_weight',
bias_attr='_base_net_3_4_bias',
moving_mean_name='_base_net_3_4_running_mean',
moving_variance_name='_base_net_3_4_running_var',
use_global_stats=False,
name='_264')
_265 = fluid.layers.relu(_264, name='_265')
_266 = fluid.layers.conv2d(
_265,
num_filters=32,
filter_size=[3, 3],
stride=[2, 2],
padding=[1, 1],
dilation=[1, 1],
groups=32,
param_attr='_base_net_4_0_weight',
name='_266',
bias_attr=False)
_267 = fluid.layers.batch_norm(
_266,
momentum=0.8999999761581421,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_4_1_weight',
bias_attr='_base_net_4_1_bias',
moving_mean_name='_base_net_4_1_running_mean',
moving_variance_name='_base_net_4_1_running_var',
use_global_stats=False,
name='_267')
_268 = fluid.layers.relu(_267, name='_268')
_269 = fluid.layers.conv2d(
_268,
num_filters=64,
filter_size=[1, 1],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='_base_net_4_3_weight',
name='_269',
bias_attr=False)
_270 = fluid.layers.batch_norm(
_269,
momentum=0.8999999761581421,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_4_4_weight',
bias_attr='_base_net_4_4_bias',
moving_mean_name='_base_net_4_4_running_mean',
moving_variance_name='_base_net_4_4_running_var',
use_global_stats=False,
name='_270')
_271 = fluid.layers.relu(_270, name='_271')
_272 = fluid.layers.conv2d(
_271,
num_filters=64,
filter_size=[3, 3],
stride=[1, 1],
padding=[1, 1],
dilation=[1, 1],
groups=64,
param_attr='_base_net_5_0_weight',
name='_272',
bias_attr=False)
_273 = fluid.layers.batch_norm(
_272,
momentum=0.8999999761581421,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_5_1_weight',
bias_attr='_base_net_5_1_bias',
moving_mean_name='_base_net_5_1_running_mean',
moving_variance_name='_base_net_5_1_running_var',
use_global_stats=False,
name='_273')
_274 = fluid.layers.relu(_273, name='_274')
_275 = fluid.layers.conv2d(
_274,
num_filters=64,
filter_size=[1, 1],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='_base_net_5_3_weight',
name='_275',
bias_attr=False)
_276 = fluid.layers.batch_norm(
_275,
momentum=0.8999999761581421,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_5_4_weight',
bias_attr='_base_net_5_4_bias',
moving_mean_name='_base_net_5_4_running_mean',
moving_variance_name='_base_net_5_4_running_var',
use_global_stats=False,
name='_276')
_277 = fluid.layers.relu(_276, name='_277')
_278 = fluid.layers.conv2d(
_277,
num_filters=64,
filter_size=[3, 3],
stride=[1, 1],
padding=[1, 1],
dilation=[1, 1],
groups=64,
param_attr='_base_net_6_0_weight',
name='_278',
bias_attr=False)
_279 = fluid.layers.batch_norm(
_278,
momentum=0.8999999761581421,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_6_1_weight',
bias_attr='_base_net_6_1_bias',
moving_mean_name='_base_net_6_1_running_mean',
moving_variance_name='_base_net_6_1_running_var',
use_global_stats=False,
name='_279')
_280 = fluid.layers.relu(_279, name='_280')
_281 = fluid.layers.conv2d(
_280,
num_filters=64,
filter_size=[1, 1],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='_base_net_6_3_weight',
name='_281',
bias_attr=False)
_282 = fluid.layers.batch_norm(
_281,
momentum=0.8999999761581421,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_6_4_weight',
bias_attr='_base_net_6_4_bias',
moving_mean_name='_base_net_6_4_running_mean',
moving_variance_name='_base_net_6_4_running_var',
use_global_stats=False,
name='_282')
_283 = fluid.layers.relu(_282, name='_283')
_284 = fluid.layers.conv2d(
_283,
num_filters=8,
filter_size=[1, 1],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='_base_net_7_branch0_0_conv_weight',
name='_284',
bias_attr=False)
_291 = fluid.layers.conv2d(
_283,
num_filters=8,
filter_size=[1, 1],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='_base_net_7_branch1_0_conv_weight',
name='_291',
bias_attr=False)
_298 = fluid.layers.conv2d(
_283,
num_filters=8,
filter_size=[1, 1],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='_base_net_7_branch2_0_conv_weight',
name='_298',
bias_attr=False)
_311 = fluid.layers.conv2d(
_283,
num_filters=64,
filter_size=[1, 1],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='_base_net_7_shortcut_conv_weight',
name='_311',
bias_attr=False)
_285 = fluid.layers.batch_norm(
_284,
momentum=0.9900000095367432,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_7_branch0_0_bn_weight',
bias_attr='_base_net_7_branch0_0_bn_bias',
moving_mean_name='_base_net_7_branch0_0_bn_running_mean',
moving_variance_name='_base_net_7_branch0_0_bn_running_var',
use_global_stats=False,
name='_285')
_292 = fluid.layers.batch_norm(
_291,
momentum=0.9900000095367432,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_7_branch1_0_bn_weight',
bias_attr='_base_net_7_branch1_0_bn_bias',
moving_mean_name='_base_net_7_branch1_0_bn_running_mean',
moving_variance_name='_base_net_7_branch1_0_bn_running_var',
use_global_stats=False,
name='_292')
_299 = fluid.layers.batch_norm(
_298,
momentum=0.9900000095367432,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_7_branch2_0_bn_weight',
bias_attr='_base_net_7_branch2_0_bn_bias',
moving_mean_name='_base_net_7_branch2_0_bn_running_mean',
moving_variance_name='_base_net_7_branch2_0_bn_running_var',
use_global_stats=False,
name='_299')
_312 = fluid.layers.batch_norm(
_311,
momentum=0.9900000095367432,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_7_shortcut_bn_weight',
bias_attr='_base_net_7_shortcut_bn_bias',
moving_mean_name='_base_net_7_shortcut_bn_running_mean',
moving_variance_name='_base_net_7_shortcut_bn_running_var',
use_global_stats=False,
name='_312')
_286 = fluid.layers.conv2d(
_285,
num_filters=16,
filter_size=[3, 3],
stride=[1, 1],
padding=[1, 1],
dilation=[1, 1],
groups=1,
param_attr='_base_net_7_branch0_1_conv_weight',
name='_286',
bias_attr=False)
_293 = fluid.layers.conv2d(
_292,
num_filters=16,
filter_size=[3, 3],
stride=[1, 1],
padding=[1, 1],
dilation=[1, 1],
groups=1,
param_attr='_base_net_7_branch1_1_conv_weight',
name='_293',
bias_attr=False)
_300 = fluid.layers.conv2d(
_299,
num_filters=12,
filter_size=[3, 3],
stride=[1, 1],
padding=[1, 1],
dilation=[1, 1],
groups=1,
param_attr='_base_net_7_branch2_1_conv_weight',
name='_300',
bias_attr=False)
_287 = fluid.layers.batch_norm(
_286,
momentum=0.9900000095367432,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_7_branch0_1_bn_weight',
bias_attr='_base_net_7_branch0_1_bn_bias',
moving_mean_name='_base_net_7_branch0_1_bn_running_mean',
moving_variance_name='_base_net_7_branch0_1_bn_running_var',
use_global_stats=False,
name='_287')
_294 = fluid.layers.batch_norm(
_293,
momentum=0.9900000095367432,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_7_branch1_1_bn_weight',
bias_attr='_base_net_7_branch1_1_bn_bias',
moving_mean_name='_base_net_7_branch1_1_bn_running_mean',
moving_variance_name='_base_net_7_branch1_1_bn_running_var',
use_global_stats=False,
name='_294')
_301 = fluid.layers.batch_norm(
_300,
momentum=0.9900000095367432,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_7_branch2_1_bn_weight',
bias_attr='_base_net_7_branch2_1_bn_bias',
moving_mean_name='_base_net_7_branch2_1_bn_running_mean',
moving_variance_name='_base_net_7_branch2_1_bn_running_var',
use_global_stats=False,
name='_301')
_288 = fluid.layers.relu(_287, name='_288')
_295 = fluid.layers.relu(_294, name='_295')
_302 = fluid.layers.relu(_301, name='_302')
_289 = fluid.layers.conv2d(
_288,
num_filters=16,
filter_size=[3, 3],
stride=[1, 1],
padding=[2, 2],
dilation=[2, 2],
groups=1,
param_attr='_base_net_7_branch0_2_conv_weight',
name='_289',
bias_attr=False)
_296 = fluid.layers.conv2d(
_295,
num_filters=16,
filter_size=[3, 3],
stride=[1, 1],
padding=[3, 3],
dilation=[3, 3],
groups=1,
param_attr='_base_net_7_branch1_2_conv_weight',
name='_296',
bias_attr=False)
_303 = fluid.layers.conv2d(
_302,
num_filters=16,
filter_size=[3, 3],
stride=[1, 1],
padding=[1, 1],
dilation=[1, 1],
groups=1,
param_attr='_base_net_7_branch2_2_conv_weight',
name='_303',
bias_attr=False)
_290 = fluid.layers.batch_norm(
_289,
momentum=0.9900000095367432,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_7_branch0_2_bn_weight',
bias_attr='_base_net_7_branch0_2_bn_bias',
moving_mean_name='_base_net_7_branch0_2_bn_running_mean',
moving_variance_name='_base_net_7_branch0_2_bn_running_var',
use_global_stats=False,
name='_290')
_297 = fluid.layers.batch_norm(
_296,
momentum=0.9900000095367432,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_7_branch1_2_bn_weight',
bias_attr='_base_net_7_branch1_2_bn_bias',
moving_mean_name='_base_net_7_branch1_2_bn_running_mean',
moving_variance_name='_base_net_7_branch1_2_bn_running_var',
use_global_stats=False,
name='_297')
_304 = fluid.layers.batch_norm(
_303,
momentum=0.9900000095367432,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_7_branch2_2_bn_weight',
bias_attr='_base_net_7_branch2_2_bn_bias',
moving_mean_name='_base_net_7_branch2_2_bn_running_mean',
moving_variance_name='_base_net_7_branch2_2_bn_running_var',
use_global_stats=False,
name='_304')
_305 = fluid.layers.relu(_304, name='_305')
_306 = fluid.layers.conv2d(
_305,
num_filters=16,
filter_size=[3, 3],
stride=[1, 1],
padding=[5, 5],
dilation=[5, 5],
groups=1,
param_attr='_base_net_7_branch2_3_conv_weight',
name='_306',
bias_attr=False)
_307 = fluid.layers.batch_norm(
_306,
momentum=0.9900000095367432,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_7_branch2_3_bn_weight',
bias_attr='_base_net_7_branch2_3_bn_bias',
moving_mean_name='_base_net_7_branch2_3_bn_running_mean',
moving_variance_name='_base_net_7_branch2_3_bn_running_var',
use_global_stats=False,
name='_307')
_308 = fluid.layers.concat([_290, _297, _307], axis=1)
_309 = fluid.layers.conv2d(
_308,
num_filters=64,
filter_size=[1, 1],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='_base_net_7_ConvLinear_conv_weight',
name='_309',
bias_attr=False)
_310 = fluid.layers.batch_norm(
_309,
momentum=0.9900000095367432,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_7_ConvLinear_bn_weight',
bias_attr='_base_net_7_ConvLinear_bn_bias',
moving_mean_name='_base_net_7_ConvLinear_bn_running_mean',
moving_variance_name='_base_net_7_ConvLinear_bn_running_var',
use_global_stats=False,
name='_310')
_313 = fluid.layers.elementwise_add(x=_310, y=_312, name='_313')
_314 = fluid.layers.relu(_313, name='_314')
_315 = fluid.layers.conv2d(
_314,
num_filters=64,
filter_size=[3, 3],
stride=[1, 1],
padding=[1, 1],
dilation=[1, 1],
groups=64,
param_attr='_classification_headers_0_0_weight',
name='_315',
bias_attr='_classification_headers_0_0_bias')
_329 = fluid.layers.conv2d(
_314,
num_filters=64,
filter_size=[3, 3],
stride=[1, 1],
padding=[1, 1],
dilation=[1, 1],
groups=64,
param_attr='_regression_headers_0_0_weight',
name='_329',
bias_attr='_regression_headers_0_0_bias')
_343 = fluid.layers.conv2d(
_314,
num_filters=64,
filter_size=[3, 3],
stride=[2, 2],
padding=[1, 1],
dilation=[1, 1],
groups=64,
param_attr='_base_net_8_0_weight',
name='_343',
bias_attr=False)
_316 = fluid.layers.relu(_315, name='_316')
_330 = fluid.layers.relu(_329, name='_330')
_344 = fluid.layers.batch_norm(
_343,
momentum=0.8999999761581421,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_8_1_weight',
bias_attr='_base_net_8_1_bias',
moving_mean_name='_base_net_8_1_running_mean',
moving_variance_name='_base_net_8_1_running_var',
use_global_stats=False,
name='_344')
_317 = fluid.layers.conv2d(
_316,
num_filters=6,
filter_size=[1, 1],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='_classification_headers_0_2_weight',
name='_317',
bias_attr='_classification_headers_0_2_bias')
_331 = fluid.layers.conv2d(
_330,
num_filters=12,
filter_size=[1, 1],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='_regression_headers_0_2_weight',
name='_331',
bias_attr='_regression_headers_0_2_bias')
_345 = fluid.layers.relu(_344, name='_345')
_318 = fluid.layers.transpose(_317, perm=[0, 2, 3, 1], name='_318')
_332 = fluid.layers.transpose(_331, perm=[0, 2, 3, 1], name='_332')
_346 = fluid.layers.conv2d(
_345,
num_filters=128,
filter_size=[1, 1],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='_base_net_8_3_weight',
name='_346',
bias_attr=False)
_320 = fluid.layers.shape(_318)
_334 = fluid.layers.shape(_332)
_347 = fluid.layers.batch_norm(
_346,
momentum=0.8999999761581421,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_8_4_weight',
bias_attr='_base_net_8_4_bias',
moving_mean_name='_base_net_8_4_running_mean',
moving_variance_name='_base_net_8_4_running_var',
use_global_stats=False,
name='_347')
_321 = fluid.layers.gather(input=_320, index=_319)
_335 = fluid.layers.gather(input=_334, index=_333)
_348 = fluid.layers.relu(_347, name='_348')
_324 = fluid.layers.assign(_321)
_338 = fluid.layers.assign(_335)
_349 = fluid.layers.conv2d(
_348,
num_filters=128,
filter_size=[3, 3],
stride=[1, 1],
padding=[1, 1],
dilation=[1, 1],
groups=128,
param_attr='_base_net_9_0_weight',
name='_349',
bias_attr=False)
_327 = fluid.layers.concat([_324, _325, _326], axis=0)
_341 = fluid.layers.concat([_338, _339, _340], axis=0)
_350 = fluid.layers.batch_norm(
_349,
momentum=0.8999999761581421,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_9_1_weight',
bias_attr='_base_net_9_1_bias',
moving_mean_name='_base_net_9_1_running_mean',
moving_variance_name='_base_net_9_1_running_var',
use_global_stats=False,
name='_350')
_327_cast = fluid.layers.cast(_327, dtype='int32')
_328 = fluid.layers.reshape(_318, name='_328', actual_shape=_327_cast, shape=[1, -1, 2])
_341_cast = fluid.layers.cast(_341, dtype='int32')
_342 = fluid.layers.reshape(_332, name='_342', actual_shape=_341_cast, shape=[1, -1, 4])
_351 = fluid.layers.relu(_350, name='_351')
_352 = fluid.layers.conv2d(
_351,
num_filters=128,
filter_size=[1, 1],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='_base_net_9_3_weight',
name='_352',
bias_attr=False)
_353 = fluid.layers.batch_norm(
_352,
momentum=0.8999999761581421,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_9_4_weight',
bias_attr='_base_net_9_4_bias',
moving_mean_name='_base_net_9_4_running_mean',
moving_variance_name='_base_net_9_4_running_var',
use_global_stats=False,
name='_353')
_354 = fluid.layers.relu(_353, name='_354')
_355 = fluid.layers.conv2d(
_354,
num_filters=128,
filter_size=[3, 3],
stride=[1, 1],
padding=[1, 1],
dilation=[1, 1],
groups=128,
param_attr='_base_net_10_0_weight',
name='_355',
bias_attr=False)
_356 = fluid.layers.batch_norm(
_355,
momentum=0.8999999761581421,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_10_1_weight',
bias_attr='_base_net_10_1_bias',
moving_mean_name='_base_net_10_1_running_mean',
moving_variance_name='_base_net_10_1_running_var',
use_global_stats=False,
name='_356')
_357 = fluid.layers.relu(_356, name='_357')
_358 = fluid.layers.conv2d(
_357,
num_filters=128,
filter_size=[1, 1],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='_base_net_10_3_weight',
name='_358',
bias_attr=False)
_359 = fluid.layers.batch_norm(
_358,
momentum=0.8999999761581421,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_10_4_weight',
bias_attr='_base_net_10_4_bias',
moving_mean_name='_base_net_10_4_running_mean',
moving_variance_name='_base_net_10_4_running_var',
use_global_stats=False,
name='_359')
_360 = fluid.layers.relu(_359, name='_360')
_361 = fluid.layers.conv2d(
_360,
num_filters=128,
filter_size=[3, 3],
stride=[1, 1],
padding=[1, 1],
dilation=[1, 1],
groups=128,
param_attr='_classification_headers_1_0_weight',
name='_361',
bias_attr='_classification_headers_1_0_bias')
_375 = fluid.layers.conv2d(
_360,
num_filters=128,
filter_size=[3, 3],
stride=[1, 1],
padding=[1, 1],
dilation=[1, 1],
groups=128,
param_attr='_regression_headers_1_0_weight',
name='_375',
bias_attr='_regression_headers_1_0_bias')
_389 = fluid.layers.conv2d(
_360,
num_filters=128,
filter_size=[3, 3],
stride=[2, 2],
padding=[1, 1],
dilation=[1, 1],
groups=128,
param_attr='_base_net_11_0_weight',
name='_389',
bias_attr=False)
_362 = fluid.layers.relu(_361, name='_362')
_376 = fluid.layers.relu(_375, name='_376')
_390 = fluid.layers.batch_norm(
_389,
momentum=0.8999999761581421,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_11_1_weight',
bias_attr='_base_net_11_1_bias',
moving_mean_name='_base_net_11_1_running_mean',
moving_variance_name='_base_net_11_1_running_var',
use_global_stats=False,
name='_390')
_363 = fluid.layers.conv2d(
_362,
num_filters=4,
filter_size=[1, 1],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='_classification_headers_1_2_weight',
name='_363',
bias_attr='_classification_headers_1_2_bias')
_377 = fluid.layers.conv2d(
_376,
num_filters=8,
filter_size=[1, 1],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='_regression_headers_1_2_weight',
name='_377',
bias_attr='_regression_headers_1_2_bias')
_391 = fluid.layers.relu(_390, name='_391')
_364 = fluid.layers.transpose(_363, perm=[0, 2, 3, 1], name='_364')
_378 = fluid.layers.transpose(_377, perm=[0, 2, 3, 1], name='_378')
_392 = fluid.layers.conv2d(
_391,
num_filters=256,
filter_size=[1, 1],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='_base_net_11_3_weight',
name='_392',
bias_attr=False)
_366 = fluid.layers.shape(_364)
_380 = fluid.layers.shape(_378)
_393 = fluid.layers.batch_norm(
_392,
momentum=0.8999999761581421,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_11_4_weight',
bias_attr='_base_net_11_4_bias',
moving_mean_name='_base_net_11_4_running_mean',
moving_variance_name='_base_net_11_4_running_var',
use_global_stats=False,
name='_393')
_367 = fluid.layers.gather(input=_366, index=_365)
_381 = fluid.layers.gather(input=_380, index=_379)
_394 = fluid.layers.relu(_393, name='_394')
_370 = fluid.layers.assign(_367)
_384 = fluid.layers.assign(_381)
_395 = fluid.layers.conv2d(
_394,
num_filters=256,
filter_size=[3, 3],
stride=[1, 1],
padding=[1, 1],
dilation=[1, 1],
groups=256,
param_attr='_base_net_12_0_weight',
name='_395',
bias_attr=False)
_373 = fluid.layers.concat([_370, _371, _372], axis=0)
_387 = fluid.layers.concat([_384, _385, _386], axis=0)
_396 = fluid.layers.batch_norm(
_395,
momentum=0.8999999761581421,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_12_1_weight',
bias_attr='_base_net_12_1_bias',
moving_mean_name='_base_net_12_1_running_mean',
moving_variance_name='_base_net_12_1_running_var',
use_global_stats=False,
name='_396')
_373_cast = fluid.layers.cast(_373, dtype='int32')
_374 = fluid.layers.reshape(_364, name='_374', actual_shape=_373_cast, shape=[1, -1, 2])
_387_cast = fluid.layers.cast(_387, dtype='int32')
_388 = fluid.layers.reshape(_378, name='_388', actual_shape=_387_cast, shape=[1, -1, 4])
_397 = fluid.layers.relu(_396, name='_397')
_398 = fluid.layers.conv2d(
_397,
num_filters=256,
filter_size=[1, 1],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='_base_net_12_3_weight',
name='_398',
bias_attr=False)
_399 = fluid.layers.batch_norm(
_398,
momentum=0.8999999761581421,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_12_4_weight',
bias_attr='_base_net_12_4_bias',
moving_mean_name='_base_net_12_4_running_mean',
moving_variance_name='_base_net_12_4_running_var',
use_global_stats=False,
name='_399')
_400 = fluid.layers.relu(_399, name='_400')
_401 = fluid.layers.conv2d(
_400,
num_filters=256,
filter_size=[3, 3],
stride=[1, 1],
padding=[1, 1],
dilation=[1, 1],
groups=256,
param_attr='_classification_headers_2_0_weight',
name='_401',
bias_attr='_classification_headers_2_0_bias')
_415 = fluid.layers.conv2d(
_400,
num_filters=256,
filter_size=[3, 3],
stride=[1, 1],
padding=[1, 1],
dilation=[1, 1],
groups=256,
param_attr='_regression_headers_2_0_weight',
name='_415',
bias_attr='_regression_headers_2_0_bias')
_429 = fluid.layers.conv2d(
_400,
num_filters=64,
filter_size=[1, 1],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='_extras_0_0_weight',
name='_429',
bias_attr='_extras_0_0_bias')
_402 = fluid.layers.relu(_401, name='_402')
_416 = fluid.layers.relu(_415, name='_416')
_430 = fluid.layers.relu(_429, name='_430')
_403 = fluid.layers.conv2d(
_402,
num_filters=4,
filter_size=[1, 1],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='_classification_headers_2_2_weight',
name='_403',
bias_attr='_classification_headers_2_2_bias')
_417 = fluid.layers.conv2d(
_416,
num_filters=8,
filter_size=[1, 1],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='_regression_headers_2_2_weight',
name='_417',
bias_attr='_regression_headers_2_2_bias')
_431 = fluid.layers.conv2d(
_430,
num_filters=64,
filter_size=[3, 3],
stride=[2, 2],
padding=[1, 1],
dilation=[1, 1],
groups=64,
param_attr='_extras_0_2_0_weight',
name='_431',
bias_attr='_extras_0_2_0_bias')
_404 = fluid.layers.transpose(_403, perm=[0, 2, 3, 1], name='_404')
_418 = fluid.layers.transpose(_417, perm=[0, 2, 3, 1], name='_418')
_432 = fluid.layers.relu(_431, name='_432')
_406 = fluid.layers.shape(_404)
_420 = fluid.layers.shape(_418)
_433 = fluid.layers.conv2d(
_432,
num_filters=256,
filter_size=[1, 1],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='_extras_0_2_2_weight',
name='_433',
bias_attr='_extras_0_2_2_bias')
_407 = fluid.layers.gather(input=_406, index=_405)
_421 = fluid.layers.gather(input=_420, index=_419)
_434 = fluid.layers.relu(_433, name='_434')
_410 = fluid.layers.assign(_407)
_424 = fluid.layers.assign(_421)
_435 = fluid.layers.conv2d(
_434,
num_filters=6,
filter_size=[3, 3],
stride=[1, 1],
padding=[1, 1],
dilation=[1, 1],
groups=1,
param_attr='_classification_headers_3_weight',
name='_435',
bias_attr='_classification_headers_3_bias')
_447 = fluid.layers.conv2d(
_434,
num_filters=12,
filter_size=[3, 3],
stride=[1, 1],
padding=[1, 1],
dilation=[1, 1],
groups=1,
param_attr='_regression_headers_3_weight',
name='_447',
bias_attr='_regression_headers_3_bias')
_413 = fluid.layers.concat([_410, _411, _412], axis=0)
_427 = fluid.layers.concat([_424, _425, _426], axis=0)
_436 = fluid.layers.transpose(_435, perm=[0, 2, 3, 1], name='_436')
_448 = fluid.layers.transpose(_447, perm=[0, 2, 3, 1], name='_448')
_413_cast = fluid.layers.cast(_413, dtype='int32')
_414 = fluid.layers.reshape(_404, name='_414', actual_shape=_413_cast, shape=[1, -1, 2])
_427_cast = fluid.layers.cast(_427, dtype='int32')
_428 = fluid.layers.reshape(_418, name='_428', actual_shape=_427_cast, shape=[1, -1, 4])
_438 = fluid.layers.shape(_436)
_450 = fluid.layers.shape(_448)
_439 = fluid.layers.gather(input=_438, index=_437)
_451 = fluid.layers.gather(input=_450, index=_449)
_442 = fluid.layers.assign(_439)
_454 = fluid.layers.assign(_451)
_445 = fluid.layers.concat([_442, _443, _444], axis=0)
_457 = fluid.layers.concat([_454, _455, _456], axis=0)
_445_cast = fluid.layers.cast(_445, dtype='int32')
_446 = fluid.layers.reshape(_436, name='_446', actual_shape=_445_cast, shape=[1, -1, 2])
_457_cast = fluid.layers.cast(_457, dtype='int32')
_458 = fluid.layers.reshape(_448, name='_458', actual_shape=_457_cast, shape=[1, -1, 4])
_459 = fluid.layers.concat([_328, _374, _414, _446], axis=1)
_460 = fluid.layers.concat([_342, _388, _428, _458], axis=1)
_scores = fluid.layers.softmax(_459, axis=2, name='_scores')
_462 = fluid.layers.slice(_460, axes=[2], starts=[0], ends=[2])
_469 = fluid.layers.slice(_460, axes=[2], starts=[2], ends=[4])
_464 = fluid.layers.elementwise_mul(x=_462, y=_463, name='_464')
_471 = fluid.layers.elementwise_mul(x=_469, y=_470, name='_471')
_466 = fluid.layers.elementwise_mul(x=_464, y=_465, name='_466')
_472 = fluid.layers.exp(_471, name='_472')
_468 = fluid.layers.elementwise_add(x=_466, y=_467, name='_468')
_474 = fluid.layers.elementwise_mul(x=_472, y=_473, name='_474')
_475 = fluid.layers.concat([_468, _474], axis=2)
_476 = fluid.layers.slice(_475, axes=[2], starts=[0], ends=[2])
_477 = fluid.layers.slice(_475, axes=[2], starts=[2], ends=[4])
_481 = fluid.layers.slice(_475, axes=[2], starts=[0], ends=[2])
_482 = fluid.layers.slice(_475, axes=[2], starts=[2], ends=[4])
_479 = fluid.layers.elementwise_div(x=_477, y=_478, name='_479')
_484 = fluid.layers.elementwise_div(x=_482, y=_483, name='_484')
_480 = fluid.layers.elementwise_sub(x=_476, y=_479, name='_480')
_485 = fluid.layers.elementwise_add(x=_481, y=_484, name='_485')
_boxes = fluid.layers.concat([_480, _485], axis=2)
return [_input], [_scores, _boxes]
def run_net(param_dir="./"):
import os
inputs, outputs = face_detector_320()
for i, out in enumerate(outputs):
if isinstance(out, list):
for out_part in out:
outputs.append(out_part)
del outputs[i]
exe = fluid.Executor(fluid.CPUPlace())
exe.run(fluid.default_startup_program())
def if_exist(var):
b = os.path.exists(os.path.join(param_dir, var.name))
return b
fluid.io.load_vars(exe, param_dir, fluid.default_main_program(), predicate=if_exist)
...@@ -2,18 +2,22 @@ ...@@ -2,18 +2,22 @@
from __future__ import absolute_import from __future__ import absolute_import
from __future__ import division from __future__ import division
import ast
import argparse import argparse
import ast
import os import os
import numpy as np import numpy as np
import paddle.fluid as fluid import paddle
import paddlehub as hub from paddle.inference import Config
from paddle.fluid.core import PaddleTensor, AnalysisConfig, create_paddle_predictor from paddle.inference import create_predictor
from paddlehub.module.module import moduleinfo, runnable, serving
from ultra_light_fast_generic_face_detector_1mb_320.processor import postprocess, base64_to_cv2
from ultra_light_fast_generic_face_detector_1mb_320.data_feed import reader from ultra_light_fast_generic_face_detector_1mb_320.data_feed import reader
from ultra_light_fast_generic_face_detector_1mb_320.processor import base64_to_cv2
from ultra_light_fast_generic_face_detector_1mb_320.processor import postprocess
import paddlehub as hub
from paddlehub.module.module import moduleinfo
from paddlehub.module.module import runnable
from paddlehub.module.module import serving
@moduleinfo( @moduleinfo(
...@@ -23,8 +27,9 @@ from ultra_light_fast_generic_face_detector_1mb_320.data_feed import reader ...@@ -23,8 +27,9 @@ from ultra_light_fast_generic_face_detector_1mb_320.data_feed import reader
author_email="paddle-dev@baidu.com", author_email="paddle-dev@baidu.com",
summary= summary=
"Ultra-Light-Fast-Generic-Face-Detector-1MB is a high-performance object detection model release on https://github.com/Linzaer/Ultra-Light-Fast-Generic-Face-Detector-1MB.", "Ultra-Light-Fast-Generic-Face-Detector-1MB is a high-performance object detection model release on https://github.com/Linzaer/Ultra-Light-Fast-Generic-Face-Detector-1MB.",
version="1.1.2") version="1.1.3")
class FaceDetector320(hub.Module): class FaceDetector320(hub.Module):
def _initialize(self): def _initialize(self):
self.default_pretrained_model_path = os.path.join(self.directory, self.default_pretrained_model_path = os.path.join(self.directory,
"ultra_light_fast_generic_face_detector_1mb_320") "ultra_light_fast_generic_face_detector_1mb_320")
...@@ -34,10 +39,10 @@ class FaceDetector320(hub.Module): ...@@ -34,10 +39,10 @@ class FaceDetector320(hub.Module):
""" """
predictor config setting predictor config setting
""" """
cpu_config = AnalysisConfig(self.default_pretrained_model_path) cpu_config = Config(self.default_pretrained_model_path)
cpu_config.disable_glog_info() cpu_config.disable_glog_info()
cpu_config.disable_gpu() cpu_config.disable_gpu()
self.cpu_predictor = create_paddle_predictor(cpu_config) self.cpu_predictor = create_predictor(cpu_config)
try: try:
_places = os.environ["CUDA_VISIBLE_DEVICES"] _places = os.environ["CUDA_VISIBLE_DEVICES"]
...@@ -46,29 +51,28 @@ class FaceDetector320(hub.Module): ...@@ -46,29 +51,28 @@ class FaceDetector320(hub.Module):
except: except:
use_gpu = False use_gpu = False
if use_gpu: if use_gpu:
gpu_config = AnalysisConfig(self.default_pretrained_model_path) gpu_config = Config(self.default_pretrained_model_path)
gpu_config.disable_glog_info() gpu_config.disable_glog_info()
gpu_config.enable_use_gpu(memory_pool_init_size_mb=1000, device_id=0) gpu_config.enable_use_gpu(memory_pool_init_size_mb=1000, device_id=0)
self.gpu_predictor = create_paddle_predictor(gpu_config) self.gpu_predictor = create_predictor(gpu_config)
def save_inference_model(self, dirname, model_filename=None, params_filename=None, combined=True): def save_inference_model(self, dirname, model_filename=None, params_filename=None, combined=True):
if combined: if combined:
model_filename = "__model__" if not model_filename else model_filename model_filename = "__model__" if not model_filename else model_filename
params_filename = "__params__" if not params_filename else params_filename params_filename = "__params__" if not params_filename else params_filename
place = fluid.CPUPlace() place = paddle.CPUPlace()
exe = fluid.Executor(place) exe = paddle.Executor(place)
program, feeded_var_names, target_vars = fluid.io.load_inference_model( program, feeded_var_names, target_vars = paddle.static.load_inference_model(
dirname=self.default_pretrained_model_path, executor=exe) dirname=self.default_pretrained_model_path, executor=exe)
fluid.io.save_inference_model( paddle.static.save_inference_model(dirname=dirname,
dirname=dirname, main_program=program,
main_program=program, executor=exe,
executor=exe, feeded_var_names=feeded_var_names,
feeded_var_names=feeded_var_names, target_vars=target_vars,
target_vars=target_vars, model_filename=model_filename,
model_filename=model_filename, params_filename=params_filename)
params_filename=params_filename)
def face_detection(self, def face_detection(self,
images=None, images=None,
...@@ -129,24 +133,31 @@ class FaceDetector320(hub.Module): ...@@ -129,24 +133,31 @@ class FaceDetector320(hub.Module):
except: except:
pass pass
# feed batch image # feed batch image
batch_image = np.array([data['image'] for data in batch_data]) batch_image = np.array([data['image'] for data in batch_data]).astype('float32')
batch_image = PaddleTensor(batch_image.astype('float32')) predictor = self.gpu_predictor if use_gpu else self.cpu_predictor
data_out = self.gpu_predictor.run([batch_image]) if use_gpu else self.cpu_predictor.run([batch_image]) input_names = predictor.get_input_names()
confidences = data_out[0].as_ndarray() input_handle = predictor.get_input_handle(input_names[0])
boxes = data_out[1].as_ndarray() input_handle.copy_from_cpu(batch_image)
predictor.run()
output_names = predictor.get_output_names()
output_handle = predictor.get_output_handle(output_names[0])
confidences = output_handle.copy_to_cpu()
output_handle = predictor.get_output_handle(output_names[1])
boxes = output_handle.copy_to_cpu()
# postprocess one by one # postprocess one by one
for i in range(len(batch_data)): for i in range(len(batch_data)):
out = postprocess( out = postprocess(confidences=confidences[i],
confidences=confidences[i], boxes=boxes[i],
boxes=boxes[i], orig_im=batch_data[i]['orig_im'],
orig_im=batch_data[i]['orig_im'], orig_im_shape=batch_data[i]['orig_im_shape'],
orig_im_shape=batch_data[i]['orig_im_shape'], orig_im_path=batch_data[i]['orig_im_path'],
orig_im_path=batch_data[i]['orig_im_path'], output_dir=output_dir,
output_dir=output_dir, visualization=visualization,
visualization=visualization, confs_threshold=confs_threshold,
confs_threshold=confs_threshold, iou_threshold=iou_threshold)
iou_threshold=iou_threshold)
res.append(out) res.append(out)
return res return res
...@@ -164,38 +175,39 @@ class FaceDetector320(hub.Module): ...@@ -164,38 +175,39 @@ class FaceDetector320(hub.Module):
""" """
Run as a command. Run as a command.
""" """
self.parser = argparse.ArgumentParser( self.parser = argparse.ArgumentParser(description="Run the {} module.".format(self.name),
description="Run the {} module.".format(self.name), prog='hub run {}'.format(self.name),
prog='hub run {}'.format(self.name), usage='%(prog)s',
usage='%(prog)s', add_help=True)
add_help=True)
self.arg_input_group = self.parser.add_argument_group(title="Input options", description="Input data. Required") 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( self.arg_config_group = self.parser.add_argument_group(
title="Config options", description="Run configuration for controlling module behavior, not required.") title="Config options", description="Run configuration for controlling module behavior, not required.")
self.add_module_config_arg() self.add_module_config_arg()
self.add_module_input_arg() self.add_module_input_arg()
args = self.parser.parse_args(argvs) args = self.parser.parse_args(argvs)
results = self.face_detection( results = self.face_detection(paths=[args.input_path],
paths=[args.input_path], batch_size=args.batch_size,
batch_size=args.batch_size, use_gpu=args.use_gpu,
use_gpu=args.use_gpu, output_dir=args.output_dir,
output_dir=args.output_dir, visualization=args.visualization)
visualization=args.visualization)
return results return results
def add_module_config_arg(self): def add_module_config_arg(self):
""" """
Add the command config options. Add the command config options.
""" """
self.arg_config_group.add_argument( self.arg_config_group.add_argument('--use_gpu',
'--use_gpu', type=ast.literal_eval, default=False, help="whether use GPU or not") type=ast.literal_eval,
self.arg_config_group.add_argument( default=False,
'--output_dir', help="whether use GPU or not")
type=str, self.arg_config_group.add_argument('--output_dir',
default='face_detector_320_predict_output', type=str,
help="The directory to save output images.") default='face_detector_320_predict_output',
self.arg_config_group.add_argument( help="The directory to save output images.")
'--visualization', type=ast.literal_eval, default=False, help="whether to save output as images.") self.arg_config_group.add_argument('--visualization',
type=ast.literal_eval,
default=False,
help="whether to save output as images.")
self.arg_config_group.add_argument('--batch_size', type=ast.literal_eval, default=1, help="batch size.") self.arg_config_group.add_argument('--batch_size', type=ast.literal_eval, default=1, help="batch size.")
def add_module_input_arg(self): def add_module_input_arg(self):
......
...@@ -164,7 +164,10 @@ ...@@ -164,7 +164,10 @@
初始发布 初始发布
* 1.1.2 * 1.1.3
移除 fluid api
- ```shell - ```shell
$ hub install ultra_light_fast_generic_face_detector_1mb_640==1.1.2 $ hub install ultra_light_fast_generic_face_detector_1mb_640==1.1.3
``` ```
...@@ -163,7 +163,10 @@ ...@@ -163,7 +163,10 @@
First release First release
* 1.1.2 * 1.1.3
Remove fluid api
- ```shell - ```shell
$ hub install ultra_light_fast_generic_face_detector_1mb_640==1.1.2 $ hub install ultra_light_fast_generic_face_detector_1mb_640==1.1.3
``` ```
# coding=utf-8
from paddle.fluid.initializer import Constant
from paddle.fluid.param_attr import ParamAttr
import paddle.fluid as fluid
def face_detector():
_319 = fluid.layers.fill_constant(shape=[1], dtype='int32', value=0)
_322 = fluid.layers.fill_constant(shape=[1], dtype='int32', value=-1)
_323 = fluid.layers.fill_constant(shape=[1], dtype='int32', value=2)
_333 = fluid.layers.fill_constant(shape=[1], dtype='int32', value=0)
_336 = fluid.layers.fill_constant(shape=[1], dtype='int32', value=-1)
_337 = fluid.layers.fill_constant(shape=[1], dtype='int32', value=4)
_365 = fluid.layers.fill_constant(shape=[1], dtype='int32', value=0)
_368 = fluid.layers.fill_constant(shape=[1], dtype='int32', value=-1)
_369 = fluid.layers.fill_constant(shape=[1], dtype='int32', value=2)
_379 = fluid.layers.fill_constant(shape=[1], dtype='int32', value=0)
_382 = fluid.layers.fill_constant(shape=[1], dtype='int32', value=-1)
_383 = fluid.layers.fill_constant(shape=[1], dtype='int32', value=4)
_405 = fluid.layers.fill_constant(shape=[1], dtype='int32', value=0)
_408 = fluid.layers.fill_constant(shape=[1], dtype='int32', value=-1)
_409 = fluid.layers.fill_constant(shape=[1], dtype='int32', value=2)
_419 = fluid.layers.fill_constant(shape=[1], dtype='int32', value=0)
_422 = fluid.layers.fill_constant(shape=[1], dtype='int32', value=-1)
_423 = fluid.layers.fill_constant(shape=[1], dtype='int32', value=4)
_437 = fluid.layers.fill_constant(shape=[1], dtype='int32', value=0)
_440 = fluid.layers.fill_constant(shape=[1], dtype='int32', value=-1)
_441 = fluid.layers.fill_constant(shape=[1], dtype='int32', value=2)
_449 = fluid.layers.fill_constant(shape=[1], dtype='int32', value=0)
_452 = fluid.layers.fill_constant(shape=[1], dtype='int32', value=-1)
_453 = fluid.layers.fill_constant(shape=[1], dtype='int32', value=4)
_463 = fluid.layers.fill_constant(shape=[1], dtype='float32', value=0.10000000149011612)
_465 = fluid.layers.create_parameter(
dtype='float32', shape=[1, 17640, 2], name='_465', attr='_465', default_initializer=Constant(0.0))
_467 = fluid.layers.create_parameter(
dtype='float32', shape=[1, 17640, 2], name='_467', attr='_467', default_initializer=Constant(0.0))
_470 = fluid.layers.fill_constant(shape=[1], dtype='float32', value=0.20000000298023224)
_473 = fluid.layers.create_parameter(
dtype='float32', shape=[1, 17640, 2], name='_473', attr='_473', default_initializer=Constant(0.0))
_478 = fluid.layers.fill_constant(shape=[1], dtype='float32', value=2.0)
_483 = fluid.layers.fill_constant(shape=[1], dtype='float32', value=2.0)
_input = fluid.layers.data(dtype='float32', shape=[1, 3, 480, 640], name='_input', append_batch_size=False)
_325 = fluid.layers.assign(_322)
_326 = fluid.layers.assign(_323)
_339 = fluid.layers.assign(_336)
_340 = fluid.layers.assign(_337)
_371 = fluid.layers.assign(_368)
_372 = fluid.layers.assign(_369)
_385 = fluid.layers.assign(_382)
_386 = fluid.layers.assign(_383)
_411 = fluid.layers.assign(_408)
_412 = fluid.layers.assign(_409)
_425 = fluid.layers.assign(_422)
_426 = fluid.layers.assign(_423)
_443 = fluid.layers.assign(_440)
_444 = fluid.layers.assign(_441)
_455 = fluid.layers.assign(_452)
_456 = fluid.layers.assign(_453)
_245 = fluid.layers.conv2d(
_input,
num_filters=16,
filter_size=[3, 3],
stride=[2, 2],
padding=[1, 1],
dilation=[1, 1],
groups=1,
param_attr='_base_net_0_0_weight',
name='_245',
bias_attr=False)
_246 = fluid.layers.batch_norm(
_245,
momentum=0.8999999761581421,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_0_1_weight',
bias_attr='_base_net_0_1_bias',
moving_mean_name='_base_net_0_1_running_mean',
moving_variance_name='_base_net_0_1_running_var',
use_global_stats=False,
name='_246')
_247 = fluid.layers.relu(_246, name='_247')
_248 = fluid.layers.conv2d(
_247,
num_filters=16,
filter_size=[3, 3],
stride=[1, 1],
padding=[1, 1],
dilation=[1, 1],
groups=16,
param_attr='_base_net_1_0_weight',
name='_248',
bias_attr=False)
_249 = fluid.layers.batch_norm(
_248,
momentum=0.8999999761581421,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_1_1_weight',
bias_attr='_base_net_1_1_bias',
moving_mean_name='_base_net_1_1_running_mean',
moving_variance_name='_base_net_1_1_running_var',
use_global_stats=False,
name='_249')
_250 = fluid.layers.relu(_249, name='_250')
_251 = fluid.layers.conv2d(
_250,
num_filters=32,
filter_size=[1, 1],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='_base_net_1_3_weight',
name='_251',
bias_attr=False)
_252 = fluid.layers.batch_norm(
_251,
momentum=0.8999999761581421,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_1_4_weight',
bias_attr='_base_net_1_4_bias',
moving_mean_name='_base_net_1_4_running_mean',
moving_variance_name='_base_net_1_4_running_var',
use_global_stats=False,
name='_252')
_253 = fluid.layers.relu(_252, name='_253')
_254 = fluid.layers.conv2d(
_253,
num_filters=32,
filter_size=[3, 3],
stride=[2, 2],
padding=[1, 1],
dilation=[1, 1],
groups=32,
param_attr='_base_net_2_0_weight',
name='_254',
bias_attr=False)
_255 = fluid.layers.batch_norm(
_254,
momentum=0.8999999761581421,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_2_1_weight',
bias_attr='_base_net_2_1_bias',
moving_mean_name='_base_net_2_1_running_mean',
moving_variance_name='_base_net_2_1_running_var',
use_global_stats=False,
name='_255')
_256 = fluid.layers.relu(_255, name='_256')
_257 = fluid.layers.conv2d(
_256,
num_filters=32,
filter_size=[1, 1],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='_base_net_2_3_weight',
name='_257',
bias_attr=False)
_258 = fluid.layers.batch_norm(
_257,
momentum=0.8999999761581421,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_2_4_weight',
bias_attr='_base_net_2_4_bias',
moving_mean_name='_base_net_2_4_running_mean',
moving_variance_name='_base_net_2_4_running_var',
use_global_stats=False,
name='_258')
_259 = fluid.layers.relu(_258, name='_259')
_260 = fluid.layers.conv2d(
_259,
num_filters=32,
filter_size=[3, 3],
stride=[1, 1],
padding=[1, 1],
dilation=[1, 1],
groups=32,
param_attr='_base_net_3_0_weight',
name='_260',
bias_attr=False)
_261 = fluid.layers.batch_norm(
_260,
momentum=0.8999999761581421,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_3_1_weight',
bias_attr='_base_net_3_1_bias',
moving_mean_name='_base_net_3_1_running_mean',
moving_variance_name='_base_net_3_1_running_var',
use_global_stats=False,
name='_261')
_262 = fluid.layers.relu(_261, name='_262')
_263 = fluid.layers.conv2d(
_262,
num_filters=32,
filter_size=[1, 1],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='_base_net_3_3_weight',
name='_263',
bias_attr=False)
_264 = fluid.layers.batch_norm(
_263,
momentum=0.8999999761581421,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_3_4_weight',
bias_attr='_base_net_3_4_bias',
moving_mean_name='_base_net_3_4_running_mean',
moving_variance_name='_base_net_3_4_running_var',
use_global_stats=False,
name='_264')
_265 = fluid.layers.relu(_264, name='_265')
_266 = fluid.layers.conv2d(
_265,
num_filters=32,
filter_size=[3, 3],
stride=[2, 2],
padding=[1, 1],
dilation=[1, 1],
groups=32,
param_attr='_base_net_4_0_weight',
name='_266',
bias_attr=False)
_267 = fluid.layers.batch_norm(
_266,
momentum=0.8999999761581421,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_4_1_weight',
bias_attr='_base_net_4_1_bias',
moving_mean_name='_base_net_4_1_running_mean',
moving_variance_name='_base_net_4_1_running_var',
use_global_stats=False,
name='_267')
_268 = fluid.layers.relu(_267, name='_268')
_269 = fluid.layers.conv2d(
_268,
num_filters=64,
filter_size=[1, 1],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='_base_net_4_3_weight',
name='_269',
bias_attr=False)
_270 = fluid.layers.batch_norm(
_269,
momentum=0.8999999761581421,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_4_4_weight',
bias_attr='_base_net_4_4_bias',
moving_mean_name='_base_net_4_4_running_mean',
moving_variance_name='_base_net_4_4_running_var',
use_global_stats=False,
name='_270')
_271 = fluid.layers.relu(_270, name='_271')
_272 = fluid.layers.conv2d(
_271,
num_filters=64,
filter_size=[3, 3],
stride=[1, 1],
padding=[1, 1],
dilation=[1, 1],
groups=64,
param_attr='_base_net_5_0_weight',
name='_272',
bias_attr=False)
_273 = fluid.layers.batch_norm(
_272,
momentum=0.8999999761581421,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_5_1_weight',
bias_attr='_base_net_5_1_bias',
moving_mean_name='_base_net_5_1_running_mean',
moving_variance_name='_base_net_5_1_running_var',
use_global_stats=False,
name='_273')
_274 = fluid.layers.relu(_273, name='_274')
_275 = fluid.layers.conv2d(
_274,
num_filters=64,
filter_size=[1, 1],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='_base_net_5_3_weight',
name='_275',
bias_attr=False)
_276 = fluid.layers.batch_norm(
_275,
momentum=0.8999999761581421,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_5_4_weight',
bias_attr='_base_net_5_4_bias',
moving_mean_name='_base_net_5_4_running_mean',
moving_variance_name='_base_net_5_4_running_var',
use_global_stats=False,
name='_276')
_277 = fluid.layers.relu(_276, name='_277')
_278 = fluid.layers.conv2d(
_277,
num_filters=64,
filter_size=[3, 3],
stride=[1, 1],
padding=[1, 1],
dilation=[1, 1],
groups=64,
param_attr='_base_net_6_0_weight',
name='_278',
bias_attr=False)
_279 = fluid.layers.batch_norm(
_278,
momentum=0.8999999761581421,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_6_1_weight',
bias_attr='_base_net_6_1_bias',
moving_mean_name='_base_net_6_1_running_mean',
moving_variance_name='_base_net_6_1_running_var',
use_global_stats=False,
name='_279')
_280 = fluid.layers.relu(_279, name='_280')
_281 = fluid.layers.conv2d(
_280,
num_filters=64,
filter_size=[1, 1],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='_base_net_6_3_weight',
name='_281',
bias_attr=False)
_282 = fluid.layers.batch_norm(
_281,
momentum=0.8999999761581421,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_6_4_weight',
bias_attr='_base_net_6_4_bias',
moving_mean_name='_base_net_6_4_running_mean',
moving_variance_name='_base_net_6_4_running_var',
use_global_stats=False,
name='_282')
_283 = fluid.layers.relu(_282, name='_283')
_284 = fluid.layers.conv2d(
_283,
num_filters=8,
filter_size=[1, 1],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='_base_net_7_branch0_0_conv_weight',
name='_284',
bias_attr=False)
_291 = fluid.layers.conv2d(
_283,
num_filters=8,
filter_size=[1, 1],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='_base_net_7_branch1_0_conv_weight',
name='_291',
bias_attr=False)
_298 = fluid.layers.conv2d(
_283,
num_filters=8,
filter_size=[1, 1],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='_base_net_7_branch2_0_conv_weight',
name='_298',
bias_attr=False)
_311 = fluid.layers.conv2d(
_283,
num_filters=64,
filter_size=[1, 1],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='_base_net_7_shortcut_conv_weight',
name='_311',
bias_attr=False)
_285 = fluid.layers.batch_norm(
_284,
momentum=0.9900000095367432,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_7_branch0_0_bn_weight',
bias_attr='_base_net_7_branch0_0_bn_bias',
moving_mean_name='_base_net_7_branch0_0_bn_running_mean',
moving_variance_name='_base_net_7_branch0_0_bn_running_var',
use_global_stats=False,
name='_285')
_292 = fluid.layers.batch_norm(
_291,
momentum=0.9900000095367432,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_7_branch1_0_bn_weight',
bias_attr='_base_net_7_branch1_0_bn_bias',
moving_mean_name='_base_net_7_branch1_0_bn_running_mean',
moving_variance_name='_base_net_7_branch1_0_bn_running_var',
use_global_stats=False,
name='_292')
_299 = fluid.layers.batch_norm(
_298,
momentum=0.9900000095367432,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_7_branch2_0_bn_weight',
bias_attr='_base_net_7_branch2_0_bn_bias',
moving_mean_name='_base_net_7_branch2_0_bn_running_mean',
moving_variance_name='_base_net_7_branch2_0_bn_running_var',
use_global_stats=False,
name='_299')
_312 = fluid.layers.batch_norm(
_311,
momentum=0.9900000095367432,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_7_shortcut_bn_weight',
bias_attr='_base_net_7_shortcut_bn_bias',
moving_mean_name='_base_net_7_shortcut_bn_running_mean',
moving_variance_name='_base_net_7_shortcut_bn_running_var',
use_global_stats=False,
name='_312')
_286 = fluid.layers.conv2d(
_285,
num_filters=16,
filter_size=[3, 3],
stride=[1, 1],
padding=[1, 1],
dilation=[1, 1],
groups=1,
param_attr='_base_net_7_branch0_1_conv_weight',
name='_286',
bias_attr=False)
_293 = fluid.layers.conv2d(
_292,
num_filters=16,
filter_size=[3, 3],
stride=[1, 1],
padding=[1, 1],
dilation=[1, 1],
groups=1,
param_attr='_base_net_7_branch1_1_conv_weight',
name='_293',
bias_attr=False)
_300 = fluid.layers.conv2d(
_299,
num_filters=12,
filter_size=[3, 3],
stride=[1, 1],
padding=[1, 1],
dilation=[1, 1],
groups=1,
param_attr='_base_net_7_branch2_1_conv_weight',
name='_300',
bias_attr=False)
_287 = fluid.layers.batch_norm(
_286,
momentum=0.9900000095367432,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_7_branch0_1_bn_weight',
bias_attr='_base_net_7_branch0_1_bn_bias',
moving_mean_name='_base_net_7_branch0_1_bn_running_mean',
moving_variance_name='_base_net_7_branch0_1_bn_running_var',
use_global_stats=False,
name='_287')
_294 = fluid.layers.batch_norm(
_293,
momentum=0.9900000095367432,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_7_branch1_1_bn_weight',
bias_attr='_base_net_7_branch1_1_bn_bias',
moving_mean_name='_base_net_7_branch1_1_bn_running_mean',
moving_variance_name='_base_net_7_branch1_1_bn_running_var',
use_global_stats=False,
name='_294')
_301 = fluid.layers.batch_norm(
_300,
momentum=0.9900000095367432,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_7_branch2_1_bn_weight',
bias_attr='_base_net_7_branch2_1_bn_bias',
moving_mean_name='_base_net_7_branch2_1_bn_running_mean',
moving_variance_name='_base_net_7_branch2_1_bn_running_var',
use_global_stats=False,
name='_301')
_288 = fluid.layers.relu(_287, name='_288')
_295 = fluid.layers.relu(_294, name='_295')
_302 = fluid.layers.relu(_301, name='_302')
_289 = fluid.layers.conv2d(
_288,
num_filters=16,
filter_size=[3, 3],
stride=[1, 1],
padding=[2, 2],
dilation=[2, 2],
groups=1,
param_attr='_base_net_7_branch0_2_conv_weight',
name='_289',
bias_attr=False)
_296 = fluid.layers.conv2d(
_295,
num_filters=16,
filter_size=[3, 3],
stride=[1, 1],
padding=[3, 3],
dilation=[3, 3],
groups=1,
param_attr='_base_net_7_branch1_2_conv_weight',
name='_296',
bias_attr=False)
_303 = fluid.layers.conv2d(
_302,
num_filters=16,
filter_size=[3, 3],
stride=[1, 1],
padding=[1, 1],
dilation=[1, 1],
groups=1,
param_attr='_base_net_7_branch2_2_conv_weight',
name='_303',
bias_attr=False)
_290 = fluid.layers.batch_norm(
_289,
momentum=0.9900000095367432,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_7_branch0_2_bn_weight',
bias_attr='_base_net_7_branch0_2_bn_bias',
moving_mean_name='_base_net_7_branch0_2_bn_running_mean',
moving_variance_name='_base_net_7_branch0_2_bn_running_var',
use_global_stats=False,
name='_290')
_297 = fluid.layers.batch_norm(
_296,
momentum=0.9900000095367432,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_7_branch1_2_bn_weight',
bias_attr='_base_net_7_branch1_2_bn_bias',
moving_mean_name='_base_net_7_branch1_2_bn_running_mean',
moving_variance_name='_base_net_7_branch1_2_bn_running_var',
use_global_stats=False,
name='_297')
_304 = fluid.layers.batch_norm(
_303,
momentum=0.9900000095367432,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_7_branch2_2_bn_weight',
bias_attr='_base_net_7_branch2_2_bn_bias',
moving_mean_name='_base_net_7_branch2_2_bn_running_mean',
moving_variance_name='_base_net_7_branch2_2_bn_running_var',
use_global_stats=False,
name='_304')
_305 = fluid.layers.relu(_304, name='_305')
_306 = fluid.layers.conv2d(
_305,
num_filters=16,
filter_size=[3, 3],
stride=[1, 1],
padding=[5, 5],
dilation=[5, 5],
groups=1,
param_attr='_base_net_7_branch2_3_conv_weight',
name='_306',
bias_attr=False)
_307 = fluid.layers.batch_norm(
_306,
momentum=0.9900000095367432,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_7_branch2_3_bn_weight',
bias_attr='_base_net_7_branch2_3_bn_bias',
moving_mean_name='_base_net_7_branch2_3_bn_running_mean',
moving_variance_name='_base_net_7_branch2_3_bn_running_var',
use_global_stats=False,
name='_307')
_308 = fluid.layers.concat([_290, _297, _307], axis=1)
_309 = fluid.layers.conv2d(
_308,
num_filters=64,
filter_size=[1, 1],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='_base_net_7_ConvLinear_conv_weight',
name='_309',
bias_attr=False)
_310 = fluid.layers.batch_norm(
_309,
momentum=0.9900000095367432,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_7_ConvLinear_bn_weight',
bias_attr='_base_net_7_ConvLinear_bn_bias',
moving_mean_name='_base_net_7_ConvLinear_bn_running_mean',
moving_variance_name='_base_net_7_ConvLinear_bn_running_var',
use_global_stats=False,
name='_310')
_313 = fluid.layers.elementwise_add(x=_310, y=_312, name='_313')
_314 = fluid.layers.relu(_313, name='_314')
_315 = fluid.layers.conv2d(
_314,
num_filters=64,
filter_size=[3, 3],
stride=[1, 1],
padding=[1, 1],
dilation=[1, 1],
groups=64,
param_attr='_classification_headers_0_0_weight',
name='_315',
bias_attr='_classification_headers_0_0_bias')
_329 = fluid.layers.conv2d(
_314,
num_filters=64,
filter_size=[3, 3],
stride=[1, 1],
padding=[1, 1],
dilation=[1, 1],
groups=64,
param_attr='_regression_headers_0_0_weight',
name='_329',
bias_attr='_regression_headers_0_0_bias')
_343 = fluid.layers.conv2d(
_314,
num_filters=64,
filter_size=[3, 3],
stride=[2, 2],
padding=[1, 1],
dilation=[1, 1],
groups=64,
param_attr='_base_net_8_0_weight',
name='_343',
bias_attr=False)
_316 = fluid.layers.relu(_315, name='_316')
_330 = fluid.layers.relu(_329, name='_330')
_344 = fluid.layers.batch_norm(
_343,
momentum=0.8999999761581421,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_8_1_weight',
bias_attr='_base_net_8_1_bias',
moving_mean_name='_base_net_8_1_running_mean',
moving_variance_name='_base_net_8_1_running_var',
use_global_stats=False,
name='_344')
_317 = fluid.layers.conv2d(
_316,
num_filters=6,
filter_size=[1, 1],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='_classification_headers_0_2_weight',
name='_317',
bias_attr='_classification_headers_0_2_bias')
_331 = fluid.layers.conv2d(
_330,
num_filters=12,
filter_size=[1, 1],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='_regression_headers_0_2_weight',
name='_331',
bias_attr='_regression_headers_0_2_bias')
_345 = fluid.layers.relu(_344, name='_345')
_318 = fluid.layers.transpose(_317, perm=[0, 2, 3, 1], name='_318')
_332 = fluid.layers.transpose(_331, perm=[0, 2, 3, 1], name='_332')
_346 = fluid.layers.conv2d(
_345,
num_filters=128,
filter_size=[1, 1],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='_base_net_8_3_weight',
name='_346',
bias_attr=False)
_320 = fluid.layers.shape(_318)
_334 = fluid.layers.shape(_332)
_347 = fluid.layers.batch_norm(
_346,
momentum=0.8999999761581421,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_8_4_weight',
bias_attr='_base_net_8_4_bias',
moving_mean_name='_base_net_8_4_running_mean',
moving_variance_name='_base_net_8_4_running_var',
use_global_stats=False,
name='_347')
_321 = fluid.layers.gather(input=_320, index=_319)
_335 = fluid.layers.gather(input=_334, index=_333)
_348 = fluid.layers.relu(_347, name='_348')
_324 = fluid.layers.assign(_321)
_338 = fluid.layers.assign(_335)
_349 = fluid.layers.conv2d(
_348,
num_filters=128,
filter_size=[3, 3],
stride=[1, 1],
padding=[1, 1],
dilation=[1, 1],
groups=128,
param_attr='_base_net_9_0_weight',
name='_349',
bias_attr=False)
_327 = fluid.layers.concat([_324, _325, _326], axis=0)
_341 = fluid.layers.concat([_338, _339, _340], axis=0)
_350 = fluid.layers.batch_norm(
_349,
momentum=0.8999999761581421,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_9_1_weight',
bias_attr='_base_net_9_1_bias',
moving_mean_name='_base_net_9_1_running_mean',
moving_variance_name='_base_net_9_1_running_var',
use_global_stats=False,
name='_350')
_327_cast = fluid.layers.cast(_327, dtype='int32')
_328 = fluid.layers.reshape(_318, name='_328', actual_shape=_327_cast, shape=[1, -1, 2])
_341_cast = fluid.layers.cast(_341, dtype='int32')
_342 = fluid.layers.reshape(_332, name='_342', actual_shape=_341_cast, shape=[1, -1, 4])
_351 = fluid.layers.relu(_350, name='_351')
_352 = fluid.layers.conv2d(
_351,
num_filters=128,
filter_size=[1, 1],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='_base_net_9_3_weight',
name='_352',
bias_attr=False)
_353 = fluid.layers.batch_norm(
_352,
momentum=0.8999999761581421,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_9_4_weight',
bias_attr='_base_net_9_4_bias',
moving_mean_name='_base_net_9_4_running_mean',
moving_variance_name='_base_net_9_4_running_var',
use_global_stats=False,
name='_353')
_354 = fluid.layers.relu(_353, name='_354')
_355 = fluid.layers.conv2d(
_354,
num_filters=128,
filter_size=[3, 3],
stride=[1, 1],
padding=[1, 1],
dilation=[1, 1],
groups=128,
param_attr='_base_net_10_0_weight',
name='_355',
bias_attr=False)
_356 = fluid.layers.batch_norm(
_355,
momentum=0.8999999761581421,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_10_1_weight',
bias_attr='_base_net_10_1_bias',
moving_mean_name='_base_net_10_1_running_mean',
moving_variance_name='_base_net_10_1_running_var',
use_global_stats=False,
name='_356')
_357 = fluid.layers.relu(_356, name='_357')
_358 = fluid.layers.conv2d(
_357,
num_filters=128,
filter_size=[1, 1],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='_base_net_10_3_weight',
name='_358',
bias_attr=False)
_359 = fluid.layers.batch_norm(
_358,
momentum=0.8999999761581421,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_10_4_weight',
bias_attr='_base_net_10_4_bias',
moving_mean_name='_base_net_10_4_running_mean',
moving_variance_name='_base_net_10_4_running_var',
use_global_stats=False,
name='_359')
_360 = fluid.layers.relu(_359, name='_360')
_361 = fluid.layers.conv2d(
_360,
num_filters=128,
filter_size=[3, 3],
stride=[1, 1],
padding=[1, 1],
dilation=[1, 1],
groups=128,
param_attr='_classification_headers_1_0_weight',
name='_361',
bias_attr='_classification_headers_1_0_bias')
_375 = fluid.layers.conv2d(
_360,
num_filters=128,
filter_size=[3, 3],
stride=[1, 1],
padding=[1, 1],
dilation=[1, 1],
groups=128,
param_attr='_regression_headers_1_0_weight',
name='_375',
bias_attr='_regression_headers_1_0_bias')
_389 = fluid.layers.conv2d(
_360,
num_filters=128,
filter_size=[3, 3],
stride=[2, 2],
padding=[1, 1],
dilation=[1, 1],
groups=128,
param_attr='_base_net_11_0_weight',
name='_389',
bias_attr=False)
_362 = fluid.layers.relu(_361, name='_362')
_376 = fluid.layers.relu(_375, name='_376')
_390 = fluid.layers.batch_norm(
_389,
momentum=0.8999999761581421,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_11_1_weight',
bias_attr='_base_net_11_1_bias',
moving_mean_name='_base_net_11_1_running_mean',
moving_variance_name='_base_net_11_1_running_var',
use_global_stats=False,
name='_390')
_363 = fluid.layers.conv2d(
_362,
num_filters=4,
filter_size=[1, 1],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='_classification_headers_1_2_weight',
name='_363',
bias_attr='_classification_headers_1_2_bias')
_377 = fluid.layers.conv2d(
_376,
num_filters=8,
filter_size=[1, 1],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='_regression_headers_1_2_weight',
name='_377',
bias_attr='_regression_headers_1_2_bias')
_391 = fluid.layers.relu(_390, name='_391')
_364 = fluid.layers.transpose(_363, perm=[0, 2, 3, 1], name='_364')
_378 = fluid.layers.transpose(_377, perm=[0, 2, 3, 1], name='_378')
_392 = fluid.layers.conv2d(
_391,
num_filters=256,
filter_size=[1, 1],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='_base_net_11_3_weight',
name='_392',
bias_attr=False)
_366 = fluid.layers.shape(_364)
_380 = fluid.layers.shape(_378)
_393 = fluid.layers.batch_norm(
_392,
momentum=0.8999999761581421,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_11_4_weight',
bias_attr='_base_net_11_4_bias',
moving_mean_name='_base_net_11_4_running_mean',
moving_variance_name='_base_net_11_4_running_var',
use_global_stats=False,
name='_393')
_367 = fluid.layers.gather(input=_366, index=_365)
_381 = fluid.layers.gather(input=_380, index=_379)
_394 = fluid.layers.relu(_393, name='_394')
_370 = fluid.layers.assign(_367)
_384 = fluid.layers.assign(_381)
_395 = fluid.layers.conv2d(
_394,
num_filters=256,
filter_size=[3, 3],
stride=[1, 1],
padding=[1, 1],
dilation=[1, 1],
groups=256,
param_attr='_base_net_12_0_weight',
name='_395',
bias_attr=False)
_373 = fluid.layers.concat([_370, _371, _372], axis=0)
_387 = fluid.layers.concat([_384, _385, _386], axis=0)
_396 = fluid.layers.batch_norm(
_395,
momentum=0.8999999761581421,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_12_1_weight',
bias_attr='_base_net_12_1_bias',
moving_mean_name='_base_net_12_1_running_mean',
moving_variance_name='_base_net_12_1_running_var',
use_global_stats=False,
name='_396')
_373_cast = fluid.layers.cast(_373, dtype='int32')
_374 = fluid.layers.reshape(_364, name='_374', actual_shape=_373_cast, shape=[1, -1, 2])
_387_cast = fluid.layers.cast(_387, dtype='int32')
_388 = fluid.layers.reshape(_378, name='_388', actual_shape=_387_cast, shape=[1, -1, 4])
_397 = fluid.layers.relu(_396, name='_397')
_398 = fluid.layers.conv2d(
_397,
num_filters=256,
filter_size=[1, 1],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='_base_net_12_3_weight',
name='_398',
bias_attr=False)
_399 = fluid.layers.batch_norm(
_398,
momentum=0.8999999761581421,
epsilon=9.999999747378752e-06,
data_layout='NCHW',
is_test=True,
param_attr='_base_net_12_4_weight',
bias_attr='_base_net_12_4_bias',
moving_mean_name='_base_net_12_4_running_mean',
moving_variance_name='_base_net_12_4_running_var',
use_global_stats=False,
name='_399')
_400 = fluid.layers.relu(_399, name='_400')
_401 = fluid.layers.conv2d(
_400,
num_filters=256,
filter_size=[3, 3],
stride=[1, 1],
padding=[1, 1],
dilation=[1, 1],
groups=256,
param_attr='_classification_headers_2_0_weight',
name='_401',
bias_attr='_classification_headers_2_0_bias')
_415 = fluid.layers.conv2d(
_400,
num_filters=256,
filter_size=[3, 3],
stride=[1, 1],
padding=[1, 1],
dilation=[1, 1],
groups=256,
param_attr='_regression_headers_2_0_weight',
name='_415',
bias_attr='_regression_headers_2_0_bias')
_429 = fluid.layers.conv2d(
_400,
num_filters=64,
filter_size=[1, 1],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='_extras_0_0_weight',
name='_429',
bias_attr='_extras_0_0_bias')
_402 = fluid.layers.relu(_401, name='_402')
_416 = fluid.layers.relu(_415, name='_416')
_430 = fluid.layers.relu(_429, name='_430')
_403 = fluid.layers.conv2d(
_402,
num_filters=4,
filter_size=[1, 1],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='_classification_headers_2_2_weight',
name='_403',
bias_attr='_classification_headers_2_2_bias')
_417 = fluid.layers.conv2d(
_416,
num_filters=8,
filter_size=[1, 1],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='_regression_headers_2_2_weight',
name='_417',
bias_attr='_regression_headers_2_2_bias')
_431 = fluid.layers.conv2d(
_430,
num_filters=64,
filter_size=[3, 3],
stride=[2, 2],
padding=[1, 1],
dilation=[1, 1],
groups=64,
param_attr='_extras_0_2_0_weight',
name='_431',
bias_attr='_extras_0_2_0_bias')
_404 = fluid.layers.transpose(_403, perm=[0, 2, 3, 1], name='_404')
_418 = fluid.layers.transpose(_417, perm=[0, 2, 3, 1], name='_418')
_432 = fluid.layers.relu(_431, name='_432')
_406 = fluid.layers.shape(_404)
_420 = fluid.layers.shape(_418)
_433 = fluid.layers.conv2d(
_432,
num_filters=256,
filter_size=[1, 1],
stride=[1, 1],
padding=[0, 0],
dilation=[1, 1],
groups=1,
param_attr='_extras_0_2_2_weight',
name='_433',
bias_attr='_extras_0_2_2_bias')
_407 = fluid.layers.gather(input=_406, index=_405)
_421 = fluid.layers.gather(input=_420, index=_419)
_434 = fluid.layers.relu(_433, name='_434')
_410 = fluid.layers.assign(_407)
_424 = fluid.layers.assign(_421)
_435 = fluid.layers.conv2d(
_434,
num_filters=6,
filter_size=[3, 3],
stride=[1, 1],
padding=[1, 1],
dilation=[1, 1],
groups=1,
param_attr='_classification_headers_3_weight',
name='_435',
bias_attr='_classification_headers_3_bias')
_447 = fluid.layers.conv2d(
_434,
num_filters=12,
filter_size=[3, 3],
stride=[1, 1],
padding=[1, 1],
dilation=[1, 1],
groups=1,
param_attr='_regression_headers_3_weight',
name='_447',
bias_attr='_regression_headers_3_bias')
_413 = fluid.layers.concat([_410, _411, _412], axis=0)
_427 = fluid.layers.concat([_424, _425, _426], axis=0)
_436 = fluid.layers.transpose(_435, perm=[0, 2, 3, 1], name='_436')
_448 = fluid.layers.transpose(_447, perm=[0, 2, 3, 1], name='_448')
_413_cast = fluid.layers.cast(_413, dtype='int32')
_414 = fluid.layers.reshape(_404, name='_414', actual_shape=_413_cast, shape=[1, -1, 2])
_427_cast = fluid.layers.cast(_427, dtype='int32')
_428 = fluid.layers.reshape(_418, name='_428', actual_shape=_427_cast, shape=[1, -1, 4])
_438 = fluid.layers.shape(_436)
_450 = fluid.layers.shape(_448)
_439 = fluid.layers.gather(input=_438, index=_437)
_451 = fluid.layers.gather(input=_450, index=_449)
_442 = fluid.layers.assign(_439)
_454 = fluid.layers.assign(_451)
_445 = fluid.layers.concat([_442, _443, _444], axis=0)
_457 = fluid.layers.concat([_454, _455, _456], axis=0)
_445_cast = fluid.layers.cast(_445, dtype='int32')
_446 = fluid.layers.reshape(_436, name='_446', actual_shape=_445_cast, shape=[1, -1, 2])
_457_cast = fluid.layers.cast(_457, dtype='int32')
_458 = fluid.layers.reshape(_448, name='_458', actual_shape=_457_cast, shape=[1, -1, 4])
_459 = fluid.layers.concat([_328, _374, _414, _446], axis=1)
_460 = fluid.layers.concat([_342, _388, _428, _458], axis=1)
_scores = fluid.layers.softmax(_459, axis=2, name='_scores')
_462 = fluid.layers.slice(_460, axes=[2], starts=[0], ends=[2])
_469 = fluid.layers.slice(_460, axes=[2], starts=[2], ends=[4])
_464 = fluid.layers.elementwise_mul(x=_462, y=_463, name='_464')
_471 = fluid.layers.elementwise_mul(x=_469, y=_470, name='_471')
_466 = fluid.layers.elementwise_mul(x=_464, y=_465, name='_466')
_472 = fluid.layers.exp(_471, name='_472')
_468 = fluid.layers.elementwise_add(x=_466, y=_467, name='_468')
_474 = fluid.layers.elementwise_mul(x=_472, y=_473, name='_474')
_475 = fluid.layers.concat([_468, _474], axis=2)
_476 = fluid.layers.slice(_475, axes=[2], starts=[0], ends=[2])
_477 = fluid.layers.slice(_475, axes=[2], starts=[2], ends=[4])
_481 = fluid.layers.slice(_475, axes=[2], starts=[0], ends=[2])
_482 = fluid.layers.slice(_475, axes=[2], starts=[2], ends=[4])
_479 = fluid.layers.elementwise_div(x=_477, y=_478, name='_479')
_484 = fluid.layers.elementwise_div(x=_482, y=_483, name='_484')
_480 = fluid.layers.elementwise_sub(x=_476, y=_479, name='_480')
_485 = fluid.layers.elementwise_add(x=_481, y=_484, name='_485')
_boxes = fluid.layers.concat([_480, _485], axis=2)
return [_input], [_scores, _boxes]
def run_net(param_dir="./"):
import os
inputs, outputs = face_detector()
for i, out in enumerate(outputs):
if isinstance(out, list):
for out_part in out:
outputs.append(out_part)
del outputs[i]
exe = fluid.Executor(fluid.CPUPlace())
exe.run(fluid.default_startup_program())
def if_exist(var):
b = os.path.exists(os.path.join(param_dir, var.name))
return b
fluid.io.load_vars(exe, param_dir, fluid.default_main_program(), predicate=if_exist)
...@@ -2,18 +2,22 @@ ...@@ -2,18 +2,22 @@
from __future__ import absolute_import from __future__ import absolute_import
from __future__ import division from __future__ import division
import ast
import argparse import argparse
import ast
import os import os
import numpy as np import numpy as np
import paddle.fluid as fluid import paddle
import paddlehub as hub from paddle.inference import Config
from paddle.fluid.core import PaddleTensor, AnalysisConfig, create_paddle_predictor from paddle.inference import create_predictor
from paddlehub.module.module import moduleinfo, runnable, serving
from ultra_light_fast_generic_face_detector_1mb_640.processor import postprocess, base64_to_cv2
from ultra_light_fast_generic_face_detector_1mb_640.data_feed import reader from ultra_light_fast_generic_face_detector_1mb_640.data_feed import reader
from ultra_light_fast_generic_face_detector_1mb_640.processor import base64_to_cv2
from ultra_light_fast_generic_face_detector_1mb_640.processor import postprocess
import paddlehub as hub
from paddlehub.module.module import moduleinfo
from paddlehub.module.module import runnable
from paddlehub.module.module import serving
@moduleinfo( @moduleinfo(
...@@ -23,8 +27,9 @@ from ultra_light_fast_generic_face_detector_1mb_640.data_feed import reader ...@@ -23,8 +27,9 @@ from ultra_light_fast_generic_face_detector_1mb_640.data_feed import reader
author_email="paddle-dev@baidu.com", author_email="paddle-dev@baidu.com",
summary= summary=
"Ultra-Light-Fast-Generic-Face-Detector-1MB is a high-performance object detection model release on https://github.com/Linzaer/Ultra-Light-Fast-Generic-Face-Detector-1MB.", "Ultra-Light-Fast-Generic-Face-Detector-1MB is a high-performance object detection model release on https://github.com/Linzaer/Ultra-Light-Fast-Generic-Face-Detector-1MB.",
version="1.1.2") version="1.1.3")
class FaceDetector640(hub.Module): class FaceDetector640(hub.Module):
def _initialize(self): def _initialize(self):
self.default_pretrained_model_path = os.path.join(self.directory, self.default_pretrained_model_path = os.path.join(self.directory,
"ultra_light_fast_generic_face_detector_1mb_640") "ultra_light_fast_generic_face_detector_1mb_640")
...@@ -34,10 +39,10 @@ class FaceDetector640(hub.Module): ...@@ -34,10 +39,10 @@ class FaceDetector640(hub.Module):
""" """
predictor config setting predictor config setting
""" """
cpu_config = AnalysisConfig(self.default_pretrained_model_path) cpu_config = Config(self.default_pretrained_model_path)
cpu_config.disable_glog_info() cpu_config.disable_glog_info()
cpu_config.disable_gpu() cpu_config.disable_gpu()
self.cpu_predictor = create_paddle_predictor(cpu_config) self.cpu_predictor = create_predictor(cpu_config)
try: try:
_places = os.environ["CUDA_VISIBLE_DEVICES"] _places = os.environ["CUDA_VISIBLE_DEVICES"]
...@@ -46,29 +51,28 @@ class FaceDetector640(hub.Module): ...@@ -46,29 +51,28 @@ class FaceDetector640(hub.Module):
except: except:
use_gpu = False use_gpu = False
if use_gpu: if use_gpu:
gpu_config = AnalysisConfig(self.default_pretrained_model_path) gpu_config = Config(self.default_pretrained_model_path)
gpu_config.disable_glog_info() gpu_config.disable_glog_info()
gpu_config.enable_use_gpu(memory_pool_init_size_mb=1000, device_id=0) gpu_config.enable_use_gpu(memory_pool_init_size_mb=1000, device_id=0)
self.gpu_predictor = create_paddle_predictor(gpu_config) self.gpu_predictor = create_predictor(gpu_config)
def save_inference_model(self, dirname, model_filename=None, params_filename=None, combined=True): def save_inference_model(self, dirname, model_filename=None, params_filename=None, combined=True):
if combined: if combined:
model_filename = "__model__" if not model_filename else model_filename model_filename = "__model__" if not model_filename else model_filename
params_filename = "__params__" if not params_filename else params_filename params_filename = "__params__" if not params_filename else params_filename
place = fluid.CPUPlace() place = paddle.CPUPlace()
exe = fluid.Executor(place) exe = paddle.Executor(place)
program, feeded_var_names, target_vars = fluid.io.load_inference_model( program, feeded_var_names, target_vars = paddle.static.load_inference_model(
dirname=self.default_pretrained_model_path, executor=exe) dirname=self.default_pretrained_model_path, executor=exe)
fluid.io.save_inference_model( paddle.static.save_inference_model(dirname=dirname,
dirname=dirname, main_program=program,
main_program=program, executor=exe,
executor=exe, feeded_var_names=feeded_var_names,
feeded_var_names=feeded_var_names, target_vars=target_vars,
target_vars=target_vars, model_filename=model_filename,
model_filename=model_filename, params_filename=params_filename)
params_filename=params_filename)
def face_detection(self, def face_detection(self,
images=None, images=None,
...@@ -128,24 +132,31 @@ class FaceDetector640(hub.Module): ...@@ -128,24 +132,31 @@ class FaceDetector640(hub.Module):
except: except:
pass pass
# feed batch image # feed batch image
batch_image = np.array([data['image'] for data in batch_data]) batch_image = np.array([data['image'] for data in batch_data]).astype('float32')
batch_image = PaddleTensor(batch_image.astype('float32')) predictor = self.gpu_predictor if use_gpu else self.cpu_predictor
data_out = self.gpu_predictor.run([batch_image]) if use_gpu else self.cpu_predictor.run([batch_image]) input_names = predictor.get_input_names()
confidences = data_out[0].as_ndarray() input_handle = predictor.get_input_handle(input_names[0])
boxes = data_out[1].as_ndarray() input_handle.copy_from_cpu(batch_image)
predictor.run()
output_names = predictor.get_output_names()
output_handle = predictor.get_output_handle(output_names[0])
confidences = output_handle.copy_to_cpu()
output_handle = predictor.get_output_handle(output_names[1])
boxes = output_handle.copy_to_cpu()
# postprocess one by one # postprocess one by one
for i in range(len(batch_data)): for i in range(len(batch_data)):
out = postprocess( out = postprocess(confidences=confidences[i],
confidences=confidences[i], boxes=boxes[i],
boxes=boxes[i], orig_im=batch_data[i]['orig_im'],
orig_im=batch_data[i]['orig_im'], orig_im_shape=batch_data[i]['orig_im_shape'],
orig_im_shape=batch_data[i]['orig_im_shape'], orig_im_path=batch_data[i]['orig_im_path'],
orig_im_path=batch_data[i]['orig_im_path'], output_dir=output_dir,
output_dir=output_dir, visualization=visualization,
visualization=visualization, confs_threshold=confs_threshold,
confs_threshold=confs_threshold, iou_threshold=iou_threshold)
iou_threshold=iou_threshold)
res.append(out) res.append(out)
return res return res
...@@ -163,38 +174,39 @@ class FaceDetector640(hub.Module): ...@@ -163,38 +174,39 @@ class FaceDetector640(hub.Module):
""" """
Run as a command. Run as a command.
""" """
self.parser = argparse.ArgumentParser( self.parser = argparse.ArgumentParser(description="Run the {} module.".format(self.name),
description="Run the {} module.".format(self.name), prog='hub run {}'.format(self.name),
prog='hub run {}'.format(self.name), usage='%(prog)s',
usage='%(prog)s', add_help=True)
add_help=True)
self.arg_input_group = self.parser.add_argument_group(title="Input options", description="Input data. Required") 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( self.arg_config_group = self.parser.add_argument_group(
title="Config options", description="Run configuration for controlling module behavior, not required.") title="Config options", description="Run configuration for controlling module behavior, not required.")
self.add_module_config_arg() self.add_module_config_arg()
self.add_module_input_arg() self.add_module_input_arg()
args = self.parser.parse_args(argvs) args = self.parser.parse_args(argvs)
results = self.face_detection( results = self.face_detection(paths=[args.input_path],
paths=[args.input_path], batch_size=args.batch_size,
batch_size=args.batch_size, use_gpu=args.use_gpu,
use_gpu=args.use_gpu, output_dir=args.output_dir,
output_dir=args.output_dir, visualization=args.visualization)
visualization=args.visualization)
return results return results
def add_module_config_arg(self): def add_module_config_arg(self):
""" """
Add the command config options. Add the command config options.
""" """
self.arg_config_group.add_argument( self.arg_config_group.add_argument('--use_gpu',
'--use_gpu', type=ast.literal_eval, default=False, help="whether use GPU or not") type=ast.literal_eval,
self.arg_config_group.add_argument( default=False,
'--output_dir', help="whether use GPU or not")
type=str, self.arg_config_group.add_argument('--output_dir',
default='face_detector_640_predict_output', type=str,
help="The directory to save output images.") default='face_detector_640_predict_output',
self.arg_config_group.add_argument( help="The directory to save output images.")
'--visualization', type=ast.literal_eval, default=False, help="whether to save output as images.") self.arg_config_group.add_argument('--visualization',
type=ast.literal_eval,
default=False,
help="whether to save output as images.")
self.arg_config_group.add_argument('--batch_size', type=ast.literal_eval, default=1, help="batch size.") self.arg_config_group.add_argument('--batch_size', type=ast.literal_eval, default=1, help="batch size.")
def add_module_input_arg(self): def add_module_input_arg(self):
......
...@@ -48,7 +48,7 @@ ...@@ -48,7 +48,7 @@
- ```shell - ```shell
$ hub run face_landmark_localization --input_path "/PATH/TO/IMAGE" $ hub run face_landmark_localization --input_path "/PATH/TO/IMAGE"
``` ```
- 通过命令行方式实现hub模型的调用,更多请见 [PaddleHub命令行指令](../../../../docs/docs_ch/tutorial/cmd_usage.rst) - 通过命令行方式实现hub模型的调用,更多请见 [PaddleHub命令行指令](../../../../docs/docs_ch/tutorial/cmd_usage.rst)
- ### 2、预测代码示例 - ### 2、预测代码示例
...@@ -56,17 +56,17 @@ ...@@ -56,17 +56,17 @@
- ```python - ```python
import paddlehub as hub import paddlehub as hub
import cv2 import cv2
face_landmark = hub.Module(name="face_landmark_localization") face_landmark = hub.Module(name="face_landmark_localization")
# Replace face detection module to speed up predictions but reduce performance # Replace face detection module to speed up predictions but reduce performance
# face_landmark.set_face_detector_module(hub.Module(name="ultra_light_fast_generic_face_detector_1mb_320")) # face_landmark.set_face_detector_module(hub.Module(name="ultra_light_fast_generic_face_detector_1mb_320"))
result = face_landmark.keypoint_detection(images=[cv2.imread('/PATH/TO/IMAGE')]) result = face_landmark.keypoint_detection(images=[cv2.imread('/PATH/TO/IMAGE')])
# or # or
# result = face_landmark.keypoint_detection(paths=['/PATH/TO/IMAGE']) # result = face_landmark.keypoint_detection(paths=['/PATH/TO/IMAGE'])
``` ```
- ### 3、API - ### 3、API
- ```python - ```python
...@@ -125,7 +125,7 @@ ...@@ -125,7 +125,7 @@
params_filename=None, params_filename=None,
combined=False): combined=False):
``` ```
- 将模型保存到指定路径,由于人脸关键点检测模型由人脸检测+关键点检测两个模型组成,因此保存后会存在两个子目录,其中`face_landmark`为人脸关键点模型,`detector`为人脸检测模型。 - 将模型保存到指定路径,由于人脸关键点检测模型由人脸检测+关键点检测两个模型组成,因此保存后会存在两个子目录,其中`face_landmark`为人脸关键点模型,`detector`为人脸检测模型。
- **参数** - **参数**
- dirname: 存在模型的目录名称 - dirname: 存在模型的目录名称
...@@ -158,17 +158,17 @@ ...@@ -158,17 +158,17 @@
import cv2 import cv2
import base64 import base64
import paddlehub as hub import paddlehub as hub
def cv2_to_base64(image): def cv2_to_base64(image):
data = cv2.imencode('.jpg', image)[1] data = cv2.imencode('.jpg', image)[1]
return base64.b64encode(data.tostring()).decode('utf8') return base64.b64encode(data.tostring()).decode('utf8')
# 发送HTTP请求 # 发送HTTP请求
data = {'images':[cv2_to_base64(cv2.imread("/PATH/TO/IMAGE"))]} data = {'images':[cv2_to_base64(cv2.imread("/PATH/TO/IMAGE"))]}
headers = {"Content-type": "application/json"} headers = {"Content-type": "application/json"}
url = "http://127.0.0.1:8866/predict/face_landmark_localization" url = "http://127.0.0.1:8866/predict/face_landmark_localization"
r = requests.post(url=url, headers=headers, data=json.dumps(data)) r = requests.post(url=url, headers=headers, data=json.dumps(data))
# 打印预测结果 # 打印预测结果
print(r.json()["results"]) print(r.json()["results"])
``` ```
...@@ -178,12 +178,15 @@ ...@@ -178,12 +178,15 @@
* 1.0.0 * 1.0.0
初始发布 初始发布
* 1.0.1 * 1.0.1
* 1.0.2 * 1.0.2
* 1.0.3
移除 fluid api
* ```shell * ```shell
$ hub install face_landmark_localization==1.0.2 $ hub install face_landmark_localization==1.0.3
``` ```
# coding=utf-8
from __future__ import absolute_import
import paddle.fluid as fluid
__all__ = ["face_landmark_localization"]
def face_landmark_localization(image):
# image = fluid.layers.data(shape=[1, 60, 60], name='data', dtype='float32')
Conv1 = fluid.layers.conv2d(
image,
param_attr='Conv1_weights',
name='Conv1',
dilation=[1, 1],
filter_size=[5, 5],
stride=[1, 1],
groups=1,
bias_attr='Conv1_bias',
padding=[2, 2],
num_filters=20)
ActivationTangH1 = fluid.layers.tanh(Conv1, name='ActivationTangH1')
ActivationAbs1 = fluid.layers.abs(ActivationTangH1, name='ActivationAbs1')
Pool1 = fluid.layers.pool2d(
ActivationAbs1,
exclusive=False,
pool_type='max',
pool_padding=[0, 0],
name='Pool1',
global_pooling=False,
pool_stride=[2, 2],
ceil_mode=True,
pool_size=[2, 2])
Conv2 = fluid.layers.conv2d(
Pool1,
param_attr='Conv2_weights',
name='Conv2',
dilation=[1, 1],
filter_size=[5, 5],
stride=[1, 1],
groups=1,
bias_attr='Conv2_bias',
padding=[2, 2],
num_filters=48)
ActivationTangH2 = fluid.layers.tanh(Conv2, name='ActivationTangH2')
ActivationAbs2 = fluid.layers.abs(ActivationTangH2, name='ActivationAbs2')
Pool2 = fluid.layers.pool2d(
ActivationAbs2,
exclusive=False,
pool_type='max',
pool_padding=[0, 0],
name='Pool2',
global_pooling=False,
pool_stride=[2, 2],
ceil_mode=True,
pool_size=[2, 2])
Conv3 = fluid.layers.conv2d(
Pool2,
param_attr='Conv3_weights',
name='Conv3',
dilation=[1, 1],
filter_size=[3, 3],
stride=[1, 1],
groups=1,
bias_attr='Conv3_bias',
padding=[0, 0],
num_filters=64)
ActivationTangH3 = fluid.layers.tanh(Conv3, name='ActivationTangH3')
ActivationAbs3 = fluid.layers.abs(ActivationTangH3, name='ActivationAbs3')
Pool3 = fluid.layers.pool2d(
ActivationAbs3,
exclusive=False,
pool_type='max',
pool_padding=[0, 0],
name='Pool3',
global_pooling=False,
pool_stride=[2, 2],
ceil_mode=True,
pool_size=[3, 3])
Conv4 = fluid.layers.conv2d(
Pool3,
param_attr='Conv4_weights',
name='Conv4',
dilation=[1, 1],
filter_size=[3, 3],
stride=[1, 1],
groups=1,
bias_attr='Conv4_bias',
padding=[0, 0],
num_filters=80)
ActivationTangH4 = fluid.layers.tanh(Conv4, name='ActivationTangH4')
ActivationAbs4 = fluid.layers.abs(ActivationTangH4, name='ActivationAbs4')
Dense1 = fluid.layers.fc(
ActivationAbs4, param_attr='Dense1_weights', act=None, name='Dense1', size=512, bias_attr='Dense1_bias')
ActivationTangH5 = fluid.layers.tanh(Dense1, name='ActivationTangH5')
ActivationAbs5 = fluid.layers.abs(ActivationTangH5, name='ActivationAbs5')
Dense3 = fluid.layers.fc(
ActivationAbs5, param_attr='Dense3_weights', act=None, name='Dense3', size=136, bias_attr='Dense3_bias')
return Dense3
...@@ -2,21 +2,25 @@ ...@@ -2,21 +2,25 @@
from __future__ import absolute_import from __future__ import absolute_import
from __future__ import division from __future__ import division
import ast
import argparse import argparse
import time import ast
import os import os
import time
from collections import OrderedDict from collections import OrderedDict
import cv2 import cv2
import numpy as np import numpy as np
import paddle.fluid as fluid import paddle
import paddlehub as hub
from paddle.fluid.core import PaddleTensor, AnalysisConfig, create_paddle_predictor
from paddlehub.module.module import moduleinfo, runnable, serving
from face_landmark_localization.processor import postprocess, base64_to_cv2
from face_landmark_localization.data_feed import reader from face_landmark_localization.data_feed import reader
from face_landmark_localization.processor import base64_to_cv2
from face_landmark_localization.processor import postprocess
from paddle.inference import Config
from paddle.inference import create_predictor
import paddlehub as hub
from paddlehub.module.module import moduleinfo
from paddlehub.module.module import runnable
from paddlehub.module.module import serving
@moduleinfo( @moduleinfo(
...@@ -26,8 +30,9 @@ from face_landmark_localization.data_feed import reader ...@@ -26,8 +30,9 @@ from face_landmark_localization.data_feed import reader
author_email="paddle-dev@baidu.com", author_email="paddle-dev@baidu.com",
summary= summary=
"Face_Landmark_Localization can be used to locate face landmark. This Module is trained through the MPII Human Pose dataset.", "Face_Landmark_Localization can be used to locate face landmark. This Module is trained through the MPII Human Pose dataset.",
version="1.0.2") version="1.0.3")
class FaceLandmarkLocalization(hub.Module): class FaceLandmarkLocalization(hub.Module):
def _initialize(self, face_detector_module=None): def _initialize(self, face_detector_module=None):
""" """
Args: Args:
...@@ -44,10 +49,10 @@ class FaceLandmarkLocalization(hub.Module): ...@@ -44,10 +49,10 @@ class FaceLandmarkLocalization(hub.Module):
""" """
predictor config setting predictor config setting
""" """
cpu_config = AnalysisConfig(self.default_pretrained_model_path) cpu_config = Config(self.default_pretrained_model_path)
cpu_config.disable_glog_info() cpu_config.disable_glog_info()
cpu_config.disable_gpu() cpu_config.disable_gpu()
self.cpu_predictor = create_paddle_predictor(cpu_config) self.cpu_predictor = create_predictor(cpu_config)
try: try:
_places = os.environ["CUDA_VISIBLE_DEVICES"] _places = os.environ["CUDA_VISIBLE_DEVICES"]
...@@ -56,10 +61,10 @@ class FaceLandmarkLocalization(hub.Module): ...@@ -56,10 +61,10 @@ class FaceLandmarkLocalization(hub.Module):
except: except:
use_gpu = False use_gpu = False
if use_gpu: if use_gpu:
gpu_config = AnalysisConfig(self.default_pretrained_model_path) gpu_config = Config(self.default_pretrained_model_path)
gpu_config.disable_glog_info() gpu_config.disable_glog_info()
gpu_config.enable_use_gpu(memory_pool_init_size_mb=1000, device_id=0) gpu_config.enable_use_gpu(memory_pool_init_size_mb=1000, device_id=0)
self.gpu_predictor = create_paddle_predictor(gpu_config) self.gpu_predictor = create_predictor(gpu_config)
def set_face_detector_module(self, face_detector_module): def set_face_detector_module(self, face_detector_module):
""" """
...@@ -77,24 +82,25 @@ class FaceLandmarkLocalization(hub.Module): ...@@ -77,24 +82,25 @@ class FaceLandmarkLocalization(hub.Module):
if combined: if combined:
model_filename = "__model__" if not model_filename else model_filename model_filename = "__model__" if not model_filename else model_filename
params_filename = "__params__" if not params_filename else params_filename params_filename = "__params__" if not params_filename else params_filename
place = fluid.CPUPlace() place = paddle.CPUPlace()
exe = fluid.Executor(place) exe = paddle.Executor(place)
program, feeded_var_names, target_vars = fluid.io.load_inference_model( program, feeded_var_names, target_vars = paddle.static.load_inference_model(
dirname=self.default_pretrained_model_path, executor=exe) dirname=self.default_pretrained_model_path, executor=exe)
face_landmark_dir = os.path.join(dirname, "face_landmark") face_landmark_dir = os.path.join(dirname, "face_landmark")
detector_dir = os.path.join(dirname, "detector") detector_dir = os.path.join(dirname, "detector")
fluid.io.save_inference_model( paddle.static.save_inference_model(dirname=face_landmark_dir,
dirname=face_landmark_dir, main_program=program,
main_program=program, executor=exe,
executor=exe, feeded_var_names=feeded_var_names,
feeded_var_names=feeded_var_names, target_vars=target_vars,
target_vars=target_vars, model_filename=model_filename,
model_filename=model_filename, params_filename=params_filename)
params_filename=params_filename) self.face_detector.save_inference_model(dirname=detector_dir,
self.face_detector.save_inference_model( model_filename=model_filename,
dirname=detector_dir, model_filename=model_filename, params_filename=params_filename, combined=combined) params_filename=params_filename,
combined=combined)
def keypoint_detection(self, def keypoint_detection(self,
images=None, images=None,
...@@ -143,11 +149,18 @@ class FaceLandmarkLocalization(hub.Module): ...@@ -143,11 +149,18 @@ class FaceLandmarkLocalization(hub.Module):
batch_data.append(all_data[handle_id + image_id]) batch_data.append(all_data[handle_id + image_id])
except: except:
pass pass
# feed batch image # feed batch image
batch_image = np.array([data['face'] for data in batch_data]) batch_image = np.array([data['face'] for data in batch_data]).astype('float32')
face_tensor = PaddleTensor(batch_image.astype('float32')) predictor = self.gpu_predictor if use_gpu else self.cpu_predictor
pred_out = self.gpu_predictor.run([face_tensor]) if use_gpu else self.cpu_predictor.run([face_tensor]) input_names = predictor.get_input_names()
points = pred_out[0].as_ndarray() input_handle = predictor.get_input_handle(input_names[0])
input_handle.copy_from_cpu(batch_image)
predictor.run()
output_names = predictor.get_output_names()
output_handle = predictor.get_output_handle(output_names[0])
points = output_handle.copy_to_cpu()
for idx, sample in enumerate(batch_data): for idx, sample in enumerate(batch_data):
sample['points'] = points[idx].reshape(68, -1) sample['points'] = points[idx].reshape(68, -1)
res += batch_data res += batch_data
...@@ -169,11 +182,10 @@ class FaceLandmarkLocalization(hub.Module): ...@@ -169,11 +182,10 @@ class FaceLandmarkLocalization(hub.Module):
""" """
Run as a command. Run as a command.
""" """
self.parser = argparse.ArgumentParser( self.parser = argparse.ArgumentParser(description="Run the {} module.".format(self.name),
description="Run the {} module.".format(self.name), prog='hub run {}'.format(self.name),
prog='hub run {}'.format(self.name), usage='%(prog)s',
usage='%(prog)s', add_help=True)
add_help=True)
self.arg_input_group = self.parser.add_argument_group(title="Input options", description="Input data. Required") 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( self.arg_config_group = self.parser.add_argument_group(
...@@ -181,20 +193,28 @@ class FaceLandmarkLocalization(hub.Module): ...@@ -181,20 +193,28 @@ class FaceLandmarkLocalization(hub.Module):
self.add_module_config_arg() self.add_module_config_arg()
self.add_module_input_arg() self.add_module_input_arg()
args = self.parser.parse_args(argvs) args = self.parser.parse_args(argvs)
results = self.keypoint_detection( results = self.keypoint_detection(paths=[args.input_path],
paths=[args.input_path], use_gpu=args.use_gpu, output_dir=args.output_dir, visualization=args.visualization) use_gpu=args.use_gpu,
output_dir=args.output_dir,
visualization=args.visualization)
return results return results
def add_module_config_arg(self): def add_module_config_arg(self):
""" """
Add the command config options. Add the command config options.
""" """
self.arg_config_group.add_argument( self.arg_config_group.add_argument('--use_gpu',
'--use_gpu', type=ast.literal_eval, default=False, help="whether use GPU or not") type=ast.literal_eval,
self.arg_config_group.add_argument( default=False,
'--output_dir', type=str, default=None, help="The directory to save output images.") help="whether use GPU or not")
self.arg_config_group.add_argument( self.arg_config_group.add_argument('--output_dir',
'--visualization', type=ast.literal_eval, default=False, help="whether to save output as images.") type=str,
default=None,
help="The directory to save output images.")
self.arg_config_group.add_argument('--visualization',
type=ast.literal_eval,
default=False,
help="whether to save output as images.")
def add_module_input_arg(self): def add_module_input_arg(self):
""" """
......
...@@ -168,6 +168,10 @@ ...@@ -168,6 +168,10 @@
修复numpy数据读取问题 修复numpy数据读取问题
* 1.1.3
移除 fluid api
- ```shell - ```shell
$ hub install ssd_mobilenet_v1_pascal==1.1.2 $ hub install ssd_mobilenet_v1_pascal==1.1.3
``` ```
...@@ -167,6 +167,10 @@ ...@@ -167,6 +167,10 @@
Fix the problem of reading numpy Fix the problem of reading numpy
* 1.1.3
Remove fluid api
- ```shell - ```shell
$ hub install ssd_mobilenet_v1_pascal==1.1.2 $ hub install ssd_mobilenet_v1_pascal==1.1.3
``` ```
# coding=utf-8
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from paddle import fluid
from paddle.fluid.param_attr import ParamAttr
from paddle.fluid.regularizer import L2Decay
__all__ = ['MobileNet']
class MobileNet(object):
"""
MobileNet v1, see https://arxiv.org/abs/1704.04861
Args:
norm_type (str): normalization type, 'bn' and 'sync_bn' are supported
norm_decay (float): weight decay for normalization layer weights
conv_group_scale (int): scaling factor for convolution groups
with_extra_blocks (bool): if extra blocks should be added
extra_block_filters (list): number of filter for each extra block
class_dim (int): number of class while classification
yolo_v3 (bool): whether to output layers which yolo_v3 needs
"""
__shared__ = ['norm_type', 'weight_prefix_name']
def __init__(self,
norm_type='bn',
norm_decay=0.,
conv_group_scale=1,
conv_learning_rate=1.0,
with_extra_blocks=False,
extra_block_filters=[[256, 512], [128, 256], [128, 256],
[64, 128]],
weight_prefix_name='',
class_dim=1000,
yolo_v3=False):
self.norm_type = norm_type
self.norm_decay = norm_decay
self.conv_group_scale = conv_group_scale
self.conv_learning_rate = conv_learning_rate
self.with_extra_blocks = with_extra_blocks
self.extra_block_filters = extra_block_filters
self.prefix_name = weight_prefix_name
self.class_dim = class_dim
self.yolo_v3 = yolo_v3
def _conv_norm(self,
input,
filter_size,
num_filters,
stride,
padding,
num_groups=1,
act='relu',
use_cudnn=True,
name=None):
parameter_attr = ParamAttr(
learning_rate=self.conv_learning_rate,
initializer=fluid.initializer.MSRA(),
name=name + "_weights")
conv = fluid.layers.conv2d(
input=input,
num_filters=num_filters,
filter_size=filter_size,
stride=stride,
padding=padding,
groups=num_groups,
act=None,
use_cudnn=use_cudnn,
param_attr=parameter_attr,
bias_attr=False)
bn_name = name + "_bn"
norm_decay = self.norm_decay
bn_param_attr = ParamAttr(
regularizer=L2Decay(norm_decay), name=bn_name + '_scale')
bn_bias_attr = ParamAttr(
regularizer=L2Decay(norm_decay), name=bn_name + '_offset')
return fluid.layers.batch_norm(
input=conv,
act=act,
param_attr=bn_param_attr,
bias_attr=bn_bias_attr,
moving_mean_name=bn_name + '_mean',
moving_variance_name=bn_name + '_variance')
def depthwise_separable(self,
input,
num_filters1,
num_filters2,
num_groups,
stride,
scale,
name=None):
depthwise_conv = self._conv_norm(
input=input,
filter_size=3,
num_filters=int(num_filters1 * scale),
stride=stride,
padding=1,
num_groups=int(num_groups * scale),
use_cudnn=False,
name=name + "_dw")
pointwise_conv = self._conv_norm(
input=depthwise_conv,
filter_size=1,
num_filters=int(num_filters2 * scale),
stride=1,
padding=0,
name=name + "_sep")
return pointwise_conv
def _extra_block(self,
input,
num_filters1,
num_filters2,
num_groups,
stride,
name=None):
pointwise_conv = self._conv_norm(
input=input,
filter_size=1,
num_filters=int(num_filters1),
stride=1,
num_groups=int(num_groups),
padding=0,
name=name + "_extra1")
normal_conv = self._conv_norm(
input=pointwise_conv,
filter_size=3,
num_filters=int(num_filters2),
stride=2,
num_groups=int(num_groups),
padding=1,
name=name + "_extra2")
return normal_conv
def __call__(self, input):
scale = self.conv_group_scale
blocks = []
# input 1/1
out = self._conv_norm(
input, 3, int(32 * scale), 2, 1, name=self.prefix_name + "conv1")
# 1/2
out = self.depthwise_separable(
out, 32, 64, 32, 1, scale, name=self.prefix_name + "conv2_1")
out = self.depthwise_separable(
out, 64, 128, 64, 2, scale, name=self.prefix_name + "conv2_2")
# 1/4
out = self.depthwise_separable(
out, 128, 128, 128, 1, scale, name=self.prefix_name + "conv3_1")
out = self.depthwise_separable(
out, 128, 256, 128, 2, scale, name=self.prefix_name + "conv3_2")
# 1/8
blocks.append(out)
out = self.depthwise_separable(
out, 256, 256, 256, 1, scale, name=self.prefix_name + "conv4_1")
out = self.depthwise_separable(
out, 256, 512, 256, 2, scale, name=self.prefix_name + "conv4_2")
# 1/16
blocks.append(out)
for i in range(5):
out = self.depthwise_separable(
out,
512,
512,
512,
1,
scale,
name=self.prefix_name + "conv5_" + str(i + 1))
module11 = out
out = self.depthwise_separable(
out, 512, 1024, 512, 2, scale, name=self.prefix_name + "conv5_6")
# 1/32
out = self.depthwise_separable(
out, 1024, 1024, 1024, 1, scale, name=self.prefix_name + "conv6")
module13 = out
blocks.append(out)
if self.yolo_v3:
return blocks
if not self.with_extra_blocks:
out = fluid.layers.pool2d(
input=out, pool_type='avg', global_pooling=True)
out = fluid.layers.fc(
input=out,
size=self.class_dim,
param_attr=ParamAttr(
initializer=fluid.initializer.MSRA(), name="fc7_weights"),
bias_attr=ParamAttr(name="fc7_offset"))
out = fluid.layers.softmax(out)
blocks.append(out)
return blocks
num_filters = self.extra_block_filters
module14 = self._extra_block(module13, num_filters[0][0],
num_filters[0][1], 1, 2,
self.prefix_name + "conv7_1")
module15 = self._extra_block(module14, num_filters[1][0],
num_filters[1][1], 1, 2,
self.prefix_name + "conv7_2")
module16 = self._extra_block(module15, num_filters[2][0],
num_filters[2][1], 1, 2,
self.prefix_name + "conv7_3")
module17 = self._extra_block(module16, num_filters[3][0],
num_filters[3][1], 1, 2,
self.prefix_name + "conv7_4")
return module11, module13, module14, module15, module16, module17
# coding=utf-8 # coding=utf-8
from __future__ import absolute_import from __future__ import absolute_import
import ast
import argparse import argparse
import ast
import os import os
from functools import partial from functools import partial
import yaml
import numpy as np import numpy as np
import paddle.fluid as fluid import paddle
import yaml
from paddle.inference import Config
from paddle.inference import create_predictor
from ssd_mobilenet_v1_pascal.data_feed import reader
from ssd_mobilenet_v1_pascal.processor import base64_to_cv2
from ssd_mobilenet_v1_pascal.processor import load_label_info
from ssd_mobilenet_v1_pascal.processor import postprocess
import paddlehub as hub import paddlehub as hub
from paddle.fluid.core import PaddleTensor, AnalysisConfig, create_paddle_predictor
from paddlehub.module.module import moduleinfo, runnable, serving
from paddlehub.common.paddle_helper import add_vars_prefix from paddlehub.common.paddle_helper import add_vars_prefix
from paddlehub.module.module import moduleinfo
from ssd_mobilenet_v1_pascal.mobilenet_v1 import MobileNet from paddlehub.module.module import runnable
from ssd_mobilenet_v1_pascal.processor import load_label_info, postprocess, base64_to_cv2 from paddlehub.module.module import serving
from ssd_mobilenet_v1_pascal.data_feed import reader
@moduleinfo( @moduleinfo(name="ssd_mobilenet_v1_pascal",
name="ssd_mobilenet_v1_pascal", version="1.1.3",
version="1.1.2", type="cv/object_detection",
type="cv/object_detection", summary="SSD with backbone MobileNet_V1, trained with dataset Pasecal VOC.",
summary="SSD with backbone MobileNet_V1, trained with dataset Pasecal VOC.", author="paddlepaddle",
author="paddlepaddle", author_email="paddle-dev@baidu.com")
author_email="paddle-dev@baidu.com")
class SSDMobileNetv1(hub.Module): class SSDMobileNetv1(hub.Module):
def _initialize(self): def _initialize(self):
self.default_pretrained_model_path = os.path.join( self.default_pretrained_model_path = os.path.join(self.directory, "ssd_mobilenet_v1_model")
self.directory, "ssd_mobilenet_v1_model") self.label_names = load_label_info(os.path.join(self.directory, "label_file.txt"))
self.label_names = load_label_info(
os.path.join(self.directory, "label_file.txt"))
self.model_config = None self.model_config = None
self._set_config() self._set_config()
def _set_config(self): def _set_config(self):
# predictor config setting. # predictor config setting.
cpu_config = AnalysisConfig(self.default_pretrained_model_path) cpu_config = Config(self.default_pretrained_model_path)
cpu_config.disable_glog_info() cpu_config.disable_glog_info()
cpu_config.disable_gpu() cpu_config.disable_gpu()
cpu_config.switch_ir_optim(False) cpu_config.switch_ir_optim(False)
self.cpu_predictor = create_paddle_predictor(cpu_config) self.cpu_predictor = create_predictor(cpu_config)
try: try:
_places = os.environ["CUDA_VISIBLE_DEVICES"] _places = os.environ["CUDA_VISIBLE_DEVICES"]
...@@ -50,10 +52,10 @@ class SSDMobileNetv1(hub.Module): ...@@ -50,10 +52,10 @@ class SSDMobileNetv1(hub.Module):
except: except:
use_gpu = False use_gpu = False
if use_gpu: if use_gpu:
gpu_config = AnalysisConfig(self.default_pretrained_model_path) gpu_config = Config(self.default_pretrained_model_path)
gpu_config.disable_glog_info() gpu_config.disable_glog_info()
gpu_config.enable_use_gpu(memory_pool_init_size_mb=500, device_id=0) gpu_config.enable_use_gpu(memory_pool_init_size_mb=500, device_id=0)
self.gpu_predictor = create_paddle_predictor(gpu_config) self.gpu_predictor = create_predictor(gpu_config)
# model config setting. # model config setting.
if not self.model_config: if not self.model_config:
...@@ -64,99 +66,6 @@ class SSDMobileNetv1(hub.Module): ...@@ -64,99 +66,6 @@ class SSDMobileNetv1(hub.Module):
self.output_decoder_config = self.model_config['SSDOutputDecoder'] self.output_decoder_config = self.model_config['SSDOutputDecoder']
self.mobilenet_config = self.model_config['MobileNet'] self.mobilenet_config = self.model_config['MobileNet']
def context(self, trainable=True, pretrained=True, get_prediction=False):
"""
Distill the Head Features, so as to perform transfer learning.
Args:
trainable (bool): whether to set parameters trainable.
pretrained (bool): whether to load default pretrained model.
get_prediction (bool): whether to get prediction.
Returns:
inputs(dict): the input variables.
outputs(dict): the output variables.
context_prog (Program): the program to execute transfer learning.
"""
context_prog = fluid.Program()
startup_program = fluid.Program()
with fluid.program_guard(context_prog, startup_program):
with fluid.unique_name.guard():
# image
image = fluid.layers.data(
name='image', shape=[3, 300, 300], dtype='float32')
# backbone
backbone = MobileNet(**self.mobilenet_config)
# body_feats
body_feats = backbone(image)
# im_size
im_size = fluid.layers.data(
name='im_size', shape=[2], dtype='int32')
# var_prefix
var_prefix = '@HUB_{}@'.format(self.name)
# names of inputs
inputs = {
'image': var_prefix + image.name,
'im_size': var_prefix + im_size.name
}
# names of outputs
if get_prediction:
locs, confs, box, box_var = fluid.layers.multi_box_head(
inputs=body_feats,
image=image,
num_classes=21,
**self.multi_box_head_config)
pred = fluid.layers.detection_output(
loc=locs,
scores=confs,
prior_box=box,
prior_box_var=box_var,
**self.output_decoder_config)
outputs = {'bbox_out': [var_prefix + pred.name]}
else:
outputs = {
'body_features':
[var_prefix + var.name for var in body_feats]
}
# add_vars_prefix
add_vars_prefix(context_prog, var_prefix)
add_vars_prefix(fluid.default_startup_program(), var_prefix)
# inputs
inputs = {
key: context_prog.global_block().vars[value]
for key, value in inputs.items()
}
outputs = {
out_key: [
context_prog.global_block().vars[varname]
for varname in out_value
]
for out_key, out_value in outputs.items()
}
# trainable
for param in context_prog.global_block().iter_parameters():
param.trainable = trainable
place = fluid.CPUPlace()
exe = fluid.Executor(place)
# pretrained
if pretrained:
def _if_exist(var):
return os.path.exists(
os.path.join(self.default_pretrained_model_path,
var.name))
fluid.io.load_vars(
exe,
self.default_pretrained_model_path,
predicate=_if_exist)
else:
exe.run(startup_program)
return inputs, outputs, context_prog
def object_detection(self, def object_detection(self,
paths=None, paths=None,
images=None, images=None,
...@@ -202,50 +111,48 @@ class SSDMobileNetv1(hub.Module): ...@@ -202,50 +111,48 @@ class SSDMobileNetv1(hub.Module):
paths += data['image'] paths += data['image']
data_reader = partial(reader, paths, images) data_reader = partial(reader, paths, images)
batch_reader = fluid.io.batch(data_reader, batch_size=batch_size) batch_reader = paddle.batch(data_reader, batch_size=batch_size)
res = [] res = []
for iter_id, feed_data in enumerate(batch_reader()): for iter_id, feed_data in enumerate(batch_reader()):
feed_data = np.array(feed_data) feed_data = np.array(feed_data)
image_tensor = PaddleTensor(np.array(list(feed_data[:, 0])).copy())
if use_gpu:
data_out = self.gpu_predictor.run([image_tensor])
else:
data_out = self.cpu_predictor.run([image_tensor])
output = postprocess( predictor = self.gpu_predictor if use_gpu else self.cpu_predictor
paths=paths, input_names = predictor.get_input_names()
images=images, input_handle = predictor.get_input_handle(input_names[0])
data_out=data_out, input_handle.copy_from_cpu(np.array(list(feed_data[:, 0])))
score_thresh=score_thresh,
label_names=self.label_names, predictor.run()
output_dir=output_dir, output_names = predictor.get_output_names()
handle_id=iter_id * batch_size, output_handle = predictor.get_output_handle(output_names[0])
visualization=visualization)
output = postprocess(paths=paths,
images=images,
data_out=output_handle,
score_thresh=score_thresh,
label_names=self.label_names,
output_dir=output_dir,
handle_id=iter_id * batch_size,
visualization=visualization)
res.extend(output) res.extend(output)
return res return res
def save_inference_model(self, def save_inference_model(self, dirname, model_filename=None, params_filename=None, combined=True):
dirname,
model_filename=None,
params_filename=None,
combined=True):
if combined: if combined:
model_filename = "__model__" if not model_filename else model_filename model_filename = "__model__" if not model_filename else model_filename
params_filename = "__params__" if not params_filename else params_filename params_filename = "__params__" if not params_filename else params_filename
place = fluid.CPUPlace() place = paddle.CPUPlace()
exe = fluid.Executor(place) exe = paddle.Executor(place)
program, feeded_var_names, target_vars = fluid.io.load_inference_model( program, feeded_var_names, target_vars = paddle.static.load_inference_model(
dirname=self.default_pretrained_model_path, executor=exe) dirname=self.default_pretrained_model_path, executor=exe)
fluid.io.save_inference_model( paddle.static.save_inference_model(dirname=dirname,
dirname=dirname, main_program=program,
main_program=program, executor=exe,
executor=exe, feeded_var_names=feeded_var_names,
feeded_var_names=feeded_var_names, target_vars=target_vars,
target_vars=target_vars, model_filename=model_filename,
model_filename=model_filename, params_filename=params_filename)
params_filename=params_filename)
@serving @serving
def serving_method(self, images, **kwargs): def serving_method(self, images, **kwargs):
...@@ -261,62 +168,48 @@ class SSDMobileNetv1(hub.Module): ...@@ -261,62 +168,48 @@ class SSDMobileNetv1(hub.Module):
""" """
Run as a command. Run as a command.
""" """
self.parser = argparse.ArgumentParser( self.parser = argparse.ArgumentParser(description="Run the {} module.".format(self.name),
description="Run the {} module.".format(self.name), prog='hub run {}'.format(self.name),
prog='hub run {}'.format(self.name), usage='%(prog)s',
usage='%(prog)s', add_help=True)
add_help=True) self.arg_input_group = self.parser.add_argument_group(title="Input options", description="Input data. Required")
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( self.arg_config_group = self.parser.add_argument_group(
title="Config options", title="Config options", description="Run configuration for controlling module behavior, not required.")
description=
"Run configuration for controlling module behavior, not required.")
self.add_module_config_arg() self.add_module_config_arg()
self.add_module_input_arg() self.add_module_input_arg()
args = self.parser.parse_args(argvs) args = self.parser.parse_args(argvs)
results = self.object_detection( results = self.object_detection(paths=[args.input_path],
paths=[args.input_path], batch_size=args.batch_size,
batch_size=args.batch_size, use_gpu=args.use_gpu,
use_gpu=args.use_gpu, output_dir=args.output_dir,
output_dir=args.output_dir, visualization=args.visualization,
visualization=args.visualization, score_thresh=args.score_thresh)
score_thresh=args.score_thresh)
return results return results
def add_module_config_arg(self): def add_module_config_arg(self):
""" """
Add the command config options. Add the command config options.
""" """
self.arg_config_group.add_argument( self.arg_config_group.add_argument('--use_gpu',
'--use_gpu', type=ast.literal_eval,
type=ast.literal_eval, default=False,
default=False, help="whether use GPU or not")
help="whether use GPU or not") self.arg_config_group.add_argument('--output_dir',
self.arg_config_group.add_argument( type=str,
'--output_dir', default='detection_result',
type=str, help="The directory to save output images.")
default='detection_result', self.arg_config_group.add_argument('--visualization',
help="The directory to save output images.") type=ast.literal_eval,
self.arg_config_group.add_argument( default=False,
'--visualization', help="whether to save output as images.")
type=ast.literal_eval,
default=False,
help="whether to save output as images.")
def add_module_input_arg(self): def add_module_input_arg(self):
""" """
Add the command input options. Add the command input options.
""" """
self.arg_input_group.add_argument( self.arg_input_group.add_argument('--input_path', type=str, help="path to image.")
'--input_path', type=str, help="path to image.") self.arg_input_group.add_argument('--batch_size', type=ast.literal_eval, default=1, help="batch size.")
self.arg_input_group.add_argument( self.arg_input_group.add_argument('--score_thresh',
'--batch_size', type=ast.literal_eval,
type=ast.literal_eval, default=0.5,
default=1, help="threshold for object detecion.")
help="batch size.")
self.arg_input_group.add_argument(
'--score_thresh',
type=ast.literal_eval,
default=0.5,
help="threshold for object detecion.")
...@@ -4,7 +4,8 @@ import os ...@@ -4,7 +4,8 @@ import os
import cv2 import cv2
import numpy as np import numpy as np
from PIL import Image, ImageDraw from PIL import Image
from PIL import ImageDraw
__all__ = ['base64_to_cv2', 'load_label_info', 'postprocess'] __all__ = ['base64_to_cv2', 'load_label_info', 'postprocess']
...@@ -15,6 +16,7 @@ def base64_to_cv2(b64str): ...@@ -15,6 +16,7 @@ def base64_to_cv2(b64str):
data = cv2.imdecode(data, cv2.IMREAD_COLOR) data = cv2.imdecode(data, cv2.IMREAD_COLOR)
return data return data
def check_dir(dir_path): def check_dir(dir_path):
if not os.path.exists(dir_path): if not os.path.exists(dir_path):
os.makedirs(dir_path) os.makedirs(dir_path)
...@@ -22,6 +24,7 @@ def check_dir(dir_path): ...@@ -22,6 +24,7 @@ def check_dir(dir_path):
os.remove(dir_path) os.remove(dir_path)
os.makedirs(dir_path) os.makedirs(dir_path)
def get_save_image_name(img, output_dir, image_path): def get_save_image_name(img, output_dir, image_path):
""" """
Get save image name from source image path. Get save image name from source image path.
...@@ -50,23 +53,17 @@ def draw_bounding_box_on_image(image_path, data_list, save_dir): ...@@ -50,23 +53,17 @@ def draw_bounding_box_on_image(image_path, data_list, save_dir):
image = Image.open(image_path) image = Image.open(image_path)
draw = ImageDraw.Draw(image) draw = ImageDraw.Draw(image)
for data in data_list: for data in data_list:
left, right, top, bottom = data['left'], data['right'], data[ left, right, top, bottom = data['left'], data['right'], data['top'], data['bottom']
'top'], data['bottom']
# draw bbox # draw bbox
draw.line([(left, top), (left, bottom), (right, bottom), (right, top), draw.line([(left, top), (left, bottom), (right, bottom), (right, top), (left, top)], width=2, fill='red')
(left, top)],
width=2,
fill='red')
# draw label # draw label
if image.mode == 'RGB': if image.mode == 'RGB':
text = data['label'] + ": %.2f%%" % (100 * data['confidence']) text = data['label'] + ": %.2f%%" % (100 * data['confidence'])
textsize_width, textsize_height = draw.textsize(text=text) textsize_width, textsize_height = draw.textsize(text=text)
draw.rectangle( draw.rectangle(xy=(left, top - (textsize_height + 5), left + textsize_width + 10, top),
xy=(left, top - (textsize_height + 5), fill=(255, 255, 255))
left + textsize_width + 10, top),
fill=(255, 255, 255))
draw.text(xy=(left, top - 15), text=text, fill=(0, 0, 0)) draw.text(xy=(left, top - 15), text=text, fill=(0, 0, 0))
save_name = get_save_image_name(image, save_dir, image_path) save_name = get_save_image_name(image, save_dir, image_path)
...@@ -95,16 +92,9 @@ def load_label_info(file_path): ...@@ -95,16 +92,9 @@ def load_label_info(file_path):
return label_names return label_names
def postprocess(paths, def postprocess(paths, images, data_out, score_thresh, label_names, output_dir, handle_id, visualization=True):
images,
data_out,
score_thresh,
label_names,
output_dir,
handle_id,
visualization=True):
""" """
postprocess the lod_tensor produced by fluid.Executor.run postprocess the lod_tensor produced by Executor.run
Args: Args:
paths (list[str]): the path of images. paths (list[str]): the path of images.
...@@ -127,9 +117,8 @@ def postprocess(paths, ...@@ -127,9 +117,8 @@ def postprocess(paths,
confidence (float): The confidence of detection result. confidence (float): The confidence of detection result.
save_path (str): The path to save output images. save_path (str): The path to save output images.
""" """
lod_tensor = data_out[0] lod = data_out.lod()[0]
lod = lod_tensor.lod[0] results = data_out.copy_to_cpu()
results = lod_tensor.as_ndarray()
check_dir(output_dir) check_dir(output_dir)
...@@ -159,9 +148,7 @@ def postprocess(paths, ...@@ -159,9 +148,7 @@ def postprocess(paths,
org_img = org_img.astype(np.uint8) org_img = org_img.astype(np.uint8)
org_img = Image.fromarray(org_img[:, :, ::-1]) org_img = Image.fromarray(org_img[:, :, ::-1])
if visualization: if visualization:
org_img_path = get_save_image_name( org_img_path = get_save_image_name(org_img, output_dir, 'image_numpy_{}'.format((handle_id + index)))
org_img, output_dir, 'image_numpy_{}'.format(
(handle_id + index)))
org_img.save(org_img_path) org_img.save(org_img_path)
org_img_height = org_img.height org_img_height = org_img.height
org_img_width = org_img.width org_img_width = org_img.width
...@@ -181,13 +168,11 @@ def postprocess(paths, ...@@ -181,13 +168,11 @@ def postprocess(paths,
dt = {} dt = {}
dt['label'] = label_names[category_id] dt['label'] = label_names[category_id]
dt['confidence'] = float(confidence) dt['confidence'] = float(confidence)
dt['left'], dt['top'], dt['right'], dt['bottom'] = clip_bbox( dt['left'], dt['top'], dt['right'], dt['bottom'] = clip_bbox(bbox, org_img_width, org_img_height)
bbox, org_img_width, org_img_height)
output_i['data'].append(dt) output_i['data'].append(dt)
output.append(output_i) output.append(output_i)
if visualization: if visualization:
output_i['save_path'] = draw_bounding_box_on_image( output_i['save_path'] = draw_bounding_box_on_image(org_img_path, output_i['data'], output_dir)
org_img_path, output_i['data'], output_dir)
return output return output
...@@ -167,6 +167,10 @@ ...@@ -167,6 +167,10 @@
修复numpy数据读取问题 修复numpy数据读取问题
* 1.0.3
移除 fluid api
- ```shell - ```shell
$ hub install yolov3_darknet53_pedestrian==1.0.2 $ hub install yolov3_darknet53_pedestrian==1.0.3
``` ```
...@@ -166,6 +166,10 @@ ...@@ -166,6 +166,10 @@
Fix the problem of reading numpy Fix the problem of reading numpy
* 1.0.3
Remove fluid api
- ```shell - ```shell
$ hub install yolov3_darknet53_pedestrian==1.0.2 $ hub install yolov3_darknet53_pedestrian==1.0.3
``` ```
# coding=utf-8
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import six
import math
from paddle import fluid
from paddle.fluid.param_attr import ParamAttr
from paddle.fluid.regularizer import L2Decay
__all__ = ['DarkNet']
class DarkNet(object):
"""DarkNet, see https://pjreddie.com/darknet/yolo/
Args:
depth (int): network depth, currently only darknet 53 is supported
norm_type (str): normalization type, 'bn' and 'sync_bn' are supported
norm_decay (float): weight decay for normalization layer weights
get_prediction (bool): whether to get prediction
class_dim (int): number of class while classification
"""
def __init__(self,
depth=53,
norm_type='sync_bn',
norm_decay=0.,
weight_prefix_name='',
get_prediction=False,
class_dim=1000):
assert depth in [53], "unsupported depth value"
self.depth = depth
self.norm_type = norm_type
self.norm_decay = norm_decay
self.depth_cfg = {53: ([1, 2, 8, 8, 4], self.basicblock)}
self.prefix_name = weight_prefix_name
self.class_dim = class_dim
self.get_prediction = get_prediction
def _conv_norm(self,
input,
ch_out,
filter_size,
stride,
padding,
act='leaky',
name=None):
conv = fluid.layers.conv2d(
input=input,
num_filters=ch_out,
filter_size=filter_size,
stride=stride,
padding=padding,
act=None,
param_attr=ParamAttr(name=name + ".conv.weights"),
bias_attr=False)
bn_name = name + ".bn"
bn_param_attr = ParamAttr(
regularizer=L2Decay(float(self.norm_decay)),
name=bn_name + '.scale')
bn_bias_attr = ParamAttr(
regularizer=L2Decay(float(self.norm_decay)),
name=bn_name + '.offset')
out = fluid.layers.batch_norm(
input=conv,
act=None,
param_attr=bn_param_attr,
bias_attr=bn_bias_attr,
moving_mean_name=bn_name + '.mean',
moving_variance_name=bn_name + '.var')
# leaky relu here has `alpha` as 0.1, can not be set by
# `act` param in fluid.layers.batch_norm above.
if act == 'leaky':
out = fluid.layers.leaky_relu(x=out, alpha=0.1)
return out
def _downsample(self,
input,
ch_out,
filter_size=3,
stride=2,
padding=1,
name=None):
return self._conv_norm(
input,
ch_out=ch_out,
filter_size=filter_size,
stride=stride,
padding=padding,
name=name)
def basicblock(self, input, ch_out, name=None):
conv1 = self._conv_norm(
input,
ch_out=ch_out,
filter_size=1,
stride=1,
padding=0,
name=name + ".0")
conv2 = self._conv_norm(
conv1,
ch_out=ch_out * 2,
filter_size=3,
stride=1,
padding=1,
name=name + ".1")
out = fluid.layers.elementwise_add(x=input, y=conv2, act=None)
return out
def layer_warp(self, block_func, input, ch_out, count, name=None):
out = block_func(input, ch_out=ch_out, name='{}.0'.format(name))
for j in six.moves.xrange(1, count):
out = block_func(out, ch_out=ch_out, name='{}.{}'.format(name, j))
return out
def __call__(self, input):
"""Get the backbone of DarkNet, that is output for the 5 stages.
:param input: Variable of input image
:type input: Variable
:Returns: The last variables of each stage.
"""
stages, block_func = self.depth_cfg[self.depth]
stages = stages[0:5]
conv = self._conv_norm(
input=input,
ch_out=32,
filter_size=3,
stride=1,
padding=1,
name=self.prefix_name + "yolo_input")
downsample_ = self._downsample(
input=conv,
ch_out=conv.shape[1] * 2,
name=self.prefix_name + "yolo_input.downsample")
blocks = []
for i, stage in enumerate(stages):
block = self.layer_warp(
block_func=block_func,
input=downsample_,
ch_out=32 * 2**i,
count=stage,
name=self.prefix_name + "stage.{}".format(i))
blocks.append(block)
if i < len(stages) - 1: # do not downsaple in the last stage
downsample_ = self._downsample(
input=block,
ch_out=block.shape[1] * 2,
name=self.prefix_name + "stage.{}.downsample".format(i))
if self.get_prediction:
pool = fluid.layers.pool2d(
input=block, pool_type='avg', global_pooling=True)
stdv = 1.0 / math.sqrt(pool.shape[1] * 1.0)
out = fluid.layers.fc(
input=pool,
size=self.class_dim,
param_attr=ParamAttr(
initializer=fluid.initializer.Uniform(-stdv, stdv),
name='fc_weights'),
bias_attr=ParamAttr(name='fc_offset'))
out = fluid.layers.softmax(out)
return out
else:
return blocks
# coding=utf-8 # coding=utf-8
from __future__ import absolute_import from __future__ import absolute_import
import ast
import argparse import argparse
import ast
import os import os
from functools import partial from functools import partial
import numpy as np import numpy as np
import paddle.fluid as fluid import paddle
from paddle.inference import Config
from paddle.inference import create_predictor
from yolov3_darknet53_pedestrian.data_feed import reader
from yolov3_darknet53_pedestrian.processor import base64_to_cv2
from yolov3_darknet53_pedestrian.processor import load_label_info
from yolov3_darknet53_pedestrian.processor import postprocess
import paddlehub as hub import paddlehub as hub
from paddle.fluid.core import PaddleTensor, AnalysisConfig, create_paddle_predictor
from paddlehub.module.module import moduleinfo, runnable, serving
from paddlehub.common.paddle_helper import add_vars_prefix from paddlehub.common.paddle_helper import add_vars_prefix
from paddlehub.module.module import moduleinfo
from yolov3_darknet53_pedestrian.darknet import DarkNet from paddlehub.module.module import runnable
from yolov3_darknet53_pedestrian.processor import load_label_info, postprocess, base64_to_cv2 from paddlehub.module.module import serving
from yolov3_darknet53_pedestrian.data_feed import reader
from yolov3_darknet53_pedestrian.yolo_head import MultiClassNMS, YOLOv3Head
@moduleinfo( @moduleinfo(name="yolov3_darknet53_pedestrian",
name="yolov3_darknet53_pedestrian", version="1.0.3",
version="1.0.2", type="CV/object_detection",
type="CV/object_detection", summary="Baidu's YOLOv3 model for pedestrian detection, with backbone DarkNet53.",
summary= author="paddlepaddle",
"Baidu's YOLOv3 model for pedestrian detection, with backbone DarkNet53.", author_email="paddle-dev@baidu.com")
author="paddlepaddle",
author_email="paddle-dev@baidu.com")
class YOLOv3DarkNet53Pedestrian(hub.Module): class YOLOv3DarkNet53Pedestrian(hub.Module):
def _initialize(self): def _initialize(self):
self.default_pretrained_model_path = os.path.join( self.default_pretrained_model_path = os.path.join(self.directory, "yolov3_darknet53_pedestrian_model")
self.directory, "yolov3_darknet53_pedestrian_model") self.label_names = load_label_info(os.path.join(self.directory, "label_file.txt"))
self.label_names = load_label_info(
os.path.join(self.directory, "label_file.txt"))
self._set_config() self._set_config()
def _set_config(self): def _set_config(self):
""" """
predictor config setting. predictor config setting.
""" """
cpu_config = AnalysisConfig(self.default_pretrained_model_path) cpu_config = Config(self.default_pretrained_model_path)
cpu_config.disable_glog_info() cpu_config.disable_glog_info()
cpu_config.disable_gpu() cpu_config.disable_gpu()
cpu_config.switch_ir_optim(False) cpu_config.switch_ir_optim(False)
self.cpu_predictor = create_paddle_predictor(cpu_config) self.cpu_predictor = create_predictor(cpu_config)
try: try:
_places = os.environ["CUDA_VISIBLE_DEVICES"] _places = os.environ["CUDA_VISIBLE_DEVICES"]
...@@ -52,116 +52,10 @@ class YOLOv3DarkNet53Pedestrian(hub.Module): ...@@ -52,116 +52,10 @@ class YOLOv3DarkNet53Pedestrian(hub.Module):
except: except:
use_gpu = False use_gpu = False
if use_gpu: if use_gpu:
gpu_config = AnalysisConfig(self.default_pretrained_model_path) gpu_config = Config(self.default_pretrained_model_path)
gpu_config.disable_glog_info() gpu_config.disable_glog_info()
gpu_config.enable_use_gpu(memory_pool_init_size_mb=500, device_id=0) gpu_config.enable_use_gpu(memory_pool_init_size_mb=500, device_id=0)
self.gpu_predictor = create_paddle_predictor(gpu_config) self.gpu_predictor = create_predictor(gpu_config)
def context(self, trainable=True, pretrained=True, get_prediction=False):
"""
Distill the Head Features, so as to perform transfer learning.
Args:
trainable (bool): whether to set parameters trainable.
pretrained (bool): whether to load default pretrained model.
get_prediction (bool): whether to get prediction.
Returns:
inputs(dict): the input variables.
outputs(dict): the output variables.
context_prog (Program): the program to execute transfer learning.
"""
context_prog = fluid.Program()
startup_program = fluid.Program()
with fluid.program_guard(context_prog, startup_program):
with fluid.unique_name.guard():
# image
image = fluid.layers.data(
name='image', shape=[3, 608, 608], dtype='float32')
# backbone
backbone = DarkNet(norm_type='sync_bn', norm_decay=0., depth=53)
# body_feats
body_feats = backbone(image)
# im_size
im_size = fluid.layers.data(
name='im_size', shape=[2], dtype='int32')
# yolo_head
yolo_head = YOLOv3Head(
anchor_masks=[[6, 7, 8], [3, 4, 5], [0, 1, 2]],
anchors=[[10, 13], [16, 30], [33, 23], [30, 61], [62, 45],
[59, 119], [116, 90], [156, 198], [373, 326]],
norm_decay=0.,
num_classes=1,
ignore_thresh=0.7,
label_smooth=True,
nms=MultiClassNMS(
background_label=-1,
keep_top_k=100,
nms_threshold=0.45,
nms_top_k=1000,
normalized=False,
score_threshold=0.01))
# head_features
head_features, body_features = yolo_head._get_outputs(
body_feats, is_train=trainable)
place = fluid.CPUPlace()
exe = fluid.Executor(place)
exe.run(fluid.default_startup_program())
# var_prefix
var_prefix = '@HUB_{}@'.format(self.name)
# name of inputs
inputs = {
'image': var_prefix + image.name,
'im_size': var_prefix + im_size.name
}
# name of outputs
if get_prediction:
bbox_out = yolo_head.get_prediction(head_features, im_size)
outputs = {'bbox_out': [var_prefix + bbox_out.name]}
else:
outputs = {
'head_features':
[var_prefix + var.name for var in head_features],
'body_features':
[var_prefix + var.name for var in body_features]
}
# add_vars_prefix
add_vars_prefix(context_prog, var_prefix)
add_vars_prefix(fluid.default_startup_program(), var_prefix)
# inputs
inputs = {
key: context_prog.global_block().vars[value]
for key, value in inputs.items()
}
# outputs
outputs = {
key: [
context_prog.global_block().vars[varname]
for varname in value
]
for key, value in outputs.items()
}
# trainable
for param in context_prog.global_block().iter_parameters():
param.trainable = trainable
# pretrained
if pretrained:
def _if_exist(var):
return os.path.exists(
os.path.join(self.default_pretrained_model_path,
var.name))
fluid.io.load_vars(
exe,
self.default_pretrained_model_path,
predicate=_if_exist)
else:
exe.run(startup_program)
return inputs, outputs, context_prog
def object_detection(self, def object_detection(self,
paths=None, paths=None,
...@@ -204,53 +98,50 @@ class YOLOv3DarkNet53Pedestrian(hub.Module): ...@@ -204,53 +98,50 @@ class YOLOv3DarkNet53Pedestrian(hub.Module):
paths = paths if paths else list() paths = paths if paths else list()
data_reader = partial(reader, paths, images) data_reader = partial(reader, paths, images)
batch_reader = fluid.io.batch(data_reader, batch_size=batch_size) batch_reader = paddle.batch(data_reader, batch_size=batch_size)
res = [] res = []
for iter_id, feed_data in enumerate(batch_reader()): for iter_id, feed_data in enumerate(batch_reader()):
feed_data = np.array(feed_data) feed_data = np.array(feed_data)
image_tensor = PaddleTensor(np.array(list(feed_data[:, 0])))
im_size_tensor = PaddleTensor(np.array(list(feed_data[:, 1])))
if use_gpu:
data_out = self.gpu_predictor.run(
[image_tensor, im_size_tensor])
else:
data_out = self.cpu_predictor.run(
[image_tensor, im_size_tensor])
output = postprocess( predictor = self.gpu_predictor if use_gpu else self.cpu_predictor
paths=paths, input_names = predictor.get_input_names()
images=images, input_handle = predictor.get_input_handle(input_names[0])
data_out=data_out, input_handle.copy_from_cpu(np.array(list(feed_data[:, 0])))
score_thresh=score_thresh, input_handle = predictor.get_input_handle(input_names[1])
label_names=self.label_names, input_handle.copy_from_cpu(np.array(list(feed_data[:, 1])))
output_dir=output_dir,
handle_id=iter_id * batch_size, predictor.run()
visualization=visualization) output_names = predictor.get_output_names()
output_handle = predictor.get_output_handle(output_names[0])
output = postprocess(paths=paths,
images=images,
data_out=output_handle,
score_thresh=score_thresh,
label_names=self.label_names,
output_dir=output_dir,
handle_id=iter_id * batch_size,
visualization=visualization)
res.extend(output) res.extend(output)
return res return res
def save_inference_model(self, def save_inference_model(self, dirname, model_filename=None, params_filename=None, combined=True):
dirname,
model_filename=None,
params_filename=None,
combined=True):
if combined: if combined:
model_filename = "__model__" if not model_filename else model_filename model_filename = "__model__" if not model_filename else model_filename
params_filename = "__params__" if not params_filename else params_filename params_filename = "__params__" if not params_filename else params_filename
place = fluid.CPUPlace() place = paddle.CPUPlace()
exe = fluid.Executor(place) exe = paddle.Executor(place)
program, feeded_var_names, target_vars = fluid.io.load_inference_model( program, feeded_var_names, target_vars = paddle.static.load_inference_model(
dirname=self.default_pretrained_model_path, executor=exe) dirname=self.default_pretrained_model_path, executor=exe)
fluid.io.save_inference_model( paddle.static.save_inference_model(dirname=dirname,
dirname=dirname, main_program=program,
main_program=program, executor=exe,
executor=exe, feeded_var_names=feeded_var_names,
feeded_var_names=feeded_var_names, target_vars=target_vars,
target_vars=target_vars, model_filename=model_filename,
model_filename=model_filename, params_filename=params_filename)
params_filename=params_filename)
@serving @serving
def serving_method(self, images, **kwargs): def serving_method(self, images, **kwargs):
...@@ -266,62 +157,48 @@ class YOLOv3DarkNet53Pedestrian(hub.Module): ...@@ -266,62 +157,48 @@ class YOLOv3DarkNet53Pedestrian(hub.Module):
""" """
Run as a command. Run as a command.
""" """
self.parser = argparse.ArgumentParser( self.parser = argparse.ArgumentParser(description="Run the {} module.".format(self.name),
description="Run the {} module.".format(self.name), prog='hub run {}'.format(self.name),
prog='hub run {}'.format(self.name), usage='%(prog)s',
usage='%(prog)s', add_help=True)
add_help=True) self.arg_input_group = self.parser.add_argument_group(title="Input options", description="Input data. Required")
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( self.arg_config_group = self.parser.add_argument_group(
title="Config options", title="Config options", description="Run configuration for controlling module behavior, not required.")
description=
"Run configuration for controlling module behavior, not required.")
self.add_module_config_arg() self.add_module_config_arg()
self.add_module_input_arg() self.add_module_input_arg()
args = self.parser.parse_args(argvs) args = self.parser.parse_args(argvs)
results = self.object_detection( results = self.object_detection(paths=[args.input_path],
paths=[args.input_path], batch_size=args.batch_size,
batch_size=args.batch_size, use_gpu=args.use_gpu,
use_gpu=args.use_gpu, output_dir=args.output_dir,
output_dir=args.output_dir, visualization=args.visualization,
visualization=args.visualization, score_thresh=args.score_thresh)
score_thresh=args.score_thresh)
return results return results
def add_module_config_arg(self): def add_module_config_arg(self):
""" """
Add the command config options. Add the command config options.
""" """
self.arg_config_group.add_argument( self.arg_config_group.add_argument('--use_gpu',
'--use_gpu', type=ast.literal_eval,
type=ast.literal_eval, default=False,
default=False, help="whether use GPU or not")
help="whether use GPU or not") self.arg_config_group.add_argument('--output_dir',
self.arg_config_group.add_argument( type=str,
'--output_dir', default='yolov3_pedestrian_detect_output',
type=str, help="The directory to save output images.")
default='yolov3_pedestrian_detect_output', self.arg_config_group.add_argument('--visualization',
help="The directory to save output images.") type=ast.literal_eval,
self.arg_config_group.add_argument( default=False,
'--visualization', help="whether to save output as images.")
type=ast.literal_eval,
default=False,
help="whether to save output as images.")
def add_module_input_arg(self): def add_module_input_arg(self):
""" """
Add the command input options. Add the command input options.
""" """
self.arg_input_group.add_argument( self.arg_input_group.add_argument('--input_path', type=str, help="path to image.")
'--input_path', type=str, help="path to image.") self.arg_input_group.add_argument('--batch_size', type=ast.literal_eval, default=1, help="batch size.")
self.arg_input_group.add_argument( self.arg_input_group.add_argument('--score_thresh',
'--batch_size', type=ast.literal_eval,
type=ast.literal_eval, default=0.2,
default=1, help="threshold for object detecion.")
help="batch size.")
self.arg_input_group.add_argument(
'--score_thresh',
type=ast.literal_eval,
default=0.2,
help="threshold for object detecion.")
...@@ -4,7 +4,8 @@ import os ...@@ -4,7 +4,8 @@ import os
import cv2 import cv2
import numpy as np import numpy as np
from PIL import Image, ImageDraw from PIL import Image
from PIL import ImageDraw
__all__ = ['base64_to_cv2', 'load_label_info', 'postprocess'] __all__ = ['base64_to_cv2', 'load_label_info', 'postprocess']
...@@ -50,21 +51,15 @@ def draw_bounding_box_on_image(image_path, data_list, save_dir): ...@@ -50,21 +51,15 @@ def draw_bounding_box_on_image(image_path, data_list, save_dir):
image = Image.open(image_path) image = Image.open(image_path)
draw = ImageDraw.Draw(image) draw = ImageDraw.Draw(image)
for data in data_list: for data in data_list:
left, right, top, bottom = data['left'], data['right'], data[ left, right, top, bottom = data['left'], data['right'], data['top'], data['bottom']
'top'], data['bottom']
# draw bbox # draw bbox
draw.line([(left, top), (left, bottom), (right, bottom), (right, top), draw.line([(left, top), (left, bottom), (right, bottom), (right, top), (left, top)], width=2, fill='red')
(left, top)],
width=2,
fill='red')
# draw label # draw label
if image.mode == 'RGB': if image.mode == 'RGB':
text = data['label'] + ": %.2f%%" % (100 * data['confidence']) text = data['label'] + ": %.2f%%" % (100 * data['confidence'])
textsize_width, textsize_height = draw.textsize(text=text) textsize_width, textsize_height = draw.textsize(text=text)
draw.rectangle( draw.rectangle(xy=(left, top - (textsize_height + 5), left + textsize_width + 10, top),
xy=(left, top - (textsize_height + 5), fill=(255, 255, 255))
left + textsize_width + 10, top),
fill=(255, 255, 255))
draw.text(xy=(left, top - 15), text=text, fill=(0, 0, 0)) draw.text(xy=(left, top - 15), text=text, fill=(0, 0, 0))
save_name = get_save_image_name(image, save_dir, image_path) save_name = get_save_image_name(image, save_dir, image_path)
...@@ -92,14 +87,7 @@ def load_label_info(file_path): ...@@ -92,14 +87,7 @@ def load_label_info(file_path):
return label_names return label_names
def postprocess(paths, def postprocess(paths, images, data_out, score_thresh, label_names, output_dir, handle_id, visualization=True):
images,
data_out,
score_thresh,
label_names,
output_dir,
handle_id,
visualization=True):
""" """
postprocess the lod_tensor produced by fluid.Executor.run postprocess the lod_tensor produced by fluid.Executor.run
...@@ -126,9 +114,8 @@ def postprocess(paths, ...@@ -126,9 +114,8 @@ def postprocess(paths,
confidence (float): The confidence of detection result. confidence (float): The confidence of detection result.
save_path (str): The path to save output images. save_path (str): The path to save output images.
""" """
lod_tensor = data_out[0] lod = data_out.lod()[0]
lod = lod_tensor.lod[0] results = data_out.copy_to_cpu()
results = lod_tensor.as_ndarray()
check_dir(output_dir) check_dir(output_dir)
...@@ -146,7 +133,6 @@ def postprocess(paths, ...@@ -146,7 +133,6 @@ def postprocess(paths,
else: else:
unhandled_paths_num = 0 unhandled_paths_num = 0
output = list() output = list()
for index in range(len(lod) - 1): for index in range(len(lod) - 1):
output_i = {'data': []} output_i = {'data': []}
...@@ -158,9 +144,7 @@ def postprocess(paths, ...@@ -158,9 +144,7 @@ def postprocess(paths,
org_img = org_img.astype(np.uint8) org_img = org_img.astype(np.uint8)
org_img = Image.fromarray(org_img[:, :, ::-1]) org_img = Image.fromarray(org_img[:, :, ::-1])
if visualization: if visualization:
org_img_path = get_save_image_name( org_img_path = get_save_image_name(org_img, output_dir, 'image_numpy_{}'.format((handle_id + index)))
org_img, output_dir, 'image_numpy_{}'.format(
(handle_id + index)))
org_img.save(org_img_path) org_img.save(org_img_path)
org_img_height = org_img.height org_img_height = org_img.height
org_img_width = org_img.width org_img_width = org_img.width
...@@ -176,13 +160,11 @@ def postprocess(paths, ...@@ -176,13 +160,11 @@ def postprocess(paths,
dt = {} dt = {}
dt['label'] = label_names[category_id] dt['label'] = label_names[category_id]
dt['confidence'] = float(confidence) dt['confidence'] = float(confidence)
dt['left'], dt['top'], dt['right'], dt['bottom'] = clip_bbox( dt['left'], dt['top'], dt['right'], dt['bottom'] = clip_bbox(bbox, org_img_width, org_img_height)
bbox, org_img_width, org_img_height)
output_i['data'].append(dt) output_i['data'].append(dt)
output.append(output_i) output.append(output_i)
if visualization: if visualization:
output_i['save_path'] = draw_bounding_box_on_image( output_i['save_path'] = draw_bounding_box_on_image(org_img_path, output_i['data'], output_dir)
org_img_path, output_i['data'], output_dir)
return output return output
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from collections import OrderedDict
from paddle import fluid
from paddle.fluid.param_attr import ParamAttr
from paddle.fluid.regularizer import L2Decay
__all__ = ['MultiClassNMS', 'YOLOv3Head']
class MultiClassNMS(object):
# __op__ = fluid.layers.multiclass_nms
def __init__(self, background_label, keep_top_k, nms_threshold, nms_top_k,
normalized, score_threshold):
super(MultiClassNMS, self).__init__()
self.background_label = background_label
self.keep_top_k = keep_top_k
self.nms_threshold = nms_threshold
self.nms_top_k = nms_top_k
self.normalized = normalized
self.score_threshold = score_threshold
class YOLOv3Head(object):
"""Head block for YOLOv3 network
Args:
norm_decay (float): weight decay for normalization layer weights
num_classes (int): number of output classes
ignore_thresh (float): threshold to ignore confidence loss
label_smooth (bool): whether to use label smoothing
anchors (list): anchors
anchor_masks (list): anchor masks
nms (object): an instance of `MultiClassNMS`
"""
def __init__(self,
norm_decay=0.,
num_classes=80,
ignore_thresh=0.7,
label_smooth=True,
anchors=[[10, 13], [16, 30], [33, 23], [30, 61], [62, 45],
[59, 119], [116, 90], [156, 198], [373, 326]],
anchor_masks=[[6, 7, 8], [3, 4, 5], [0, 1, 2]],
nms=MultiClassNMS(
background_label=-1,
keep_top_k=100,
nms_threshold=0.45,
nms_top_k=1000,
normalized=True,
score_threshold=0.01),
weight_prefix_name=''):
self.norm_decay = norm_decay
self.num_classes = num_classes
self.ignore_thresh = ignore_thresh
self.label_smooth = label_smooth
self.anchor_masks = anchor_masks
self._parse_anchors(anchors)
self.nms = nms
self.prefix_name = weight_prefix_name
def _conv_bn(self,
input,
ch_out,
filter_size,
stride,
padding,
act='leaky',
is_test=True,
name=None):
conv = fluid.layers.conv2d(
input=input,
num_filters=ch_out,
filter_size=filter_size,
stride=stride,
padding=padding,
act=None,
param_attr=ParamAttr(name=name + ".conv.weights"),
bias_attr=False)
bn_name = name + ".bn"
bn_param_attr = ParamAttr(
regularizer=L2Decay(self.norm_decay), name=bn_name + '.scale')
bn_bias_attr = ParamAttr(
regularizer=L2Decay(self.norm_decay), name=bn_name + '.offset')
out = fluid.layers.batch_norm(
input=conv,
act=None,
is_test=is_test,
param_attr=bn_param_attr,
bias_attr=bn_bias_attr,
moving_mean_name=bn_name + '.mean',
moving_variance_name=bn_name + '.var')
if act == 'leaky':
out = fluid.layers.leaky_relu(x=out, alpha=0.1)
return out
def _detection_block(self, input, channel, is_test=True, name=None):
assert channel % 2 == 0, \
"channel {} cannot be divided by 2 in detection block {}" \
.format(channel, name)
conv = input
for j in range(2):
conv = self._conv_bn(
conv,
channel,
filter_size=1,
stride=1,
padding=0,
is_test=is_test,
name='{}.{}.0'.format(name, j))
conv = self._conv_bn(
conv,
channel * 2,
filter_size=3,
stride=1,
padding=1,
is_test=is_test,
name='{}.{}.1'.format(name, j))
route = self._conv_bn(
conv,
channel,
filter_size=1,
stride=1,
padding=0,
is_test=is_test,
name='{}.2'.format(name))
tip = self._conv_bn(
route,
channel * 2,
filter_size=3,
stride=1,
padding=1,
is_test=is_test,
name='{}.tip'.format(name))
return route, tip
def _upsample(self, input, scale=2, name=None):
out = fluid.layers.resize_nearest(
input=input, scale=float(scale), name=name)
return out
def _parse_anchors(self, anchors):
"""
Check ANCHORS/ANCHOR_MASKS in config and parse mask_anchors
"""
self.anchors = []
self.mask_anchors = []
assert len(anchors) > 0, "ANCHORS not set."
assert len(self.anchor_masks) > 0, "ANCHOR_MASKS not set."
for anchor in anchors:
assert len(anchor) == 2, "anchor {} len should be 2".format(anchor)
self.anchors.extend(anchor)
anchor_num = len(anchors)
for masks in self.anchor_masks:
self.mask_anchors.append([])
for mask in masks:
assert mask < anchor_num, "anchor mask index overflow"
self.mask_anchors[-1].extend(anchors[mask])
def _get_outputs(self, input, is_train=True):
"""
Get YOLOv3 head output
Args:
input (list): List of Variables, output of backbone stages
is_train (bool): whether in train or test mode
Returns:
outputs (list): Variables of each output layer
"""
outputs = []
# get last out_layer_num blocks in reverse order
out_layer_num = len(self.anchor_masks)
if isinstance(input, OrderedDict):
blocks = list(input.values())[-1:-out_layer_num - 1:-1]
else:
blocks = input[-1:-out_layer_num - 1:-1]
route = None
for i, block in enumerate(blocks):
if i > 0: # perform concat in first 2 detection_block
block = fluid.layers.concat(input=[route, block], axis=1)
route, tip = self._detection_block(
block,
channel=512 // (2**i),
is_test=(not is_train),
name=self.prefix_name + "yolo_block.{}".format(i))
# out channel number = mask_num * (5 + class_num)
num_filters = len(self.anchor_masks[i]) * (self.num_classes + 5)
block_out = fluid.layers.conv2d(
input=tip,
num_filters=num_filters,
filter_size=1,
stride=1,
padding=0,
act=None,
param_attr=ParamAttr(name=self.prefix_name +
"yolo_output.{}.conv.weights".format(i)),
bias_attr=ParamAttr(
regularizer=L2Decay(0.),
name=self.prefix_name +
"yolo_output.{}.conv.bias".format(i)))
outputs.append(block_out)
if i < len(blocks) - 1:
# do not perform upsample in the last detection_block
route = self._conv_bn(
input=route,
ch_out=256 // (2**i),
filter_size=1,
stride=1,
padding=0,
is_test=(not is_train),
name=self.prefix_name + "yolo_transition.{}".format(i))
# upsample
route = self._upsample(route)
return outputs, blocks
def get_prediction(self, outputs, im_size):
"""
Get prediction result of YOLOv3 network
Args:
outputs (list): list of Variables, return from _get_outputs
im_size (Variable): Variable of size([h, w]) of each image
Returns:
pred (Variable): The prediction result after non-max suppress.
"""
boxes = []
scores = []
downsample = 32
for i, output in enumerate(outputs):
box, score = fluid.layers.yolo_box(
x=output,
img_size=im_size,
anchors=self.mask_anchors[i],
class_num=self.num_classes,
conf_thresh=self.nms.score_threshold,
downsample_ratio=downsample,
name=self.prefix_name + "yolo_box" + str(i))
boxes.append(box)
scores.append(fluid.layers.transpose(score, perm=[0, 2, 1]))
downsample //= 2
yolo_boxes = fluid.layers.concat(boxes, axis=1)
yolo_scores = fluid.layers.concat(scores, axis=2)
pred = fluid.layers.multiclass_nms(
bboxes=yolo_boxes,
scores=yolo_scores,
score_threshold=self.nms.score_threshold,
nms_top_k=self.nms.nms_top_k,
keep_top_k=self.nms.keep_top_k,
nms_threshold=self.nms.nms_threshold,
background_label=self.nms.background_label,
normalized=self.nms.normalized,
name="multiclass_nms")
return pred
...@@ -166,6 +166,10 @@ ...@@ -166,6 +166,10 @@
修复numpy数据读取问题 修复numpy数据读取问题
* 1.0.3
移除 fluid api
- ```shell - ```shell
$ hub install yolov3_darknet53_vehicles==1.0.2 $ hub install yolov3_darknet53_vehicles==1.0.3
``` ```
...@@ -166,6 +166,10 @@ ...@@ -166,6 +166,10 @@
Fix the problem of reading numpy Fix the problem of reading numpy
* 1.0.3
Remove fluid api
- ```shell - ```shell
$ hub install yolov3_darknet53_vehicles==1.0.2 $ hub install yolov3_darknet53_vehicles==1.0.3
``` ```
# coding=utf-8
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import six
import math
from paddle import fluid
from paddle.fluid.param_attr import ParamAttr
from paddle.fluid.regularizer import L2Decay
__all__ = ['DarkNet']
class DarkNet(object):
"""DarkNet, see https://pjreddie.com/darknet/yolo/
Args:
depth (int): network depth, currently only darknet 53 is supported
norm_type (str): normalization type, 'bn' and 'sync_bn' are supported
norm_decay (float): weight decay for normalization layer weights
get_prediction (bool): whether to get prediction
class_dim (int): number of class while classification
"""
def __init__(self,
depth=53,
norm_type='sync_bn',
norm_decay=0.,
weight_prefix_name='',
get_prediction=False,
class_dim=1000):
assert depth in [53], "unsupported depth value"
self.depth = depth
self.norm_type = norm_type
self.norm_decay = norm_decay
self.depth_cfg = {53: ([1, 2, 8, 8, 4], self.basicblock)}
self.prefix_name = weight_prefix_name
self.class_dim = class_dim
self.get_prediction = get_prediction
def _conv_norm(self,
input,
ch_out,
filter_size,
stride,
padding,
act='leaky',
name=None):
conv = fluid.layers.conv2d(
input=input,
num_filters=ch_out,
filter_size=filter_size,
stride=stride,
padding=padding,
act=None,
param_attr=ParamAttr(name=name + ".conv.weights"),
bias_attr=False)
bn_name = name + ".bn"
bn_param_attr = ParamAttr(
regularizer=L2Decay(float(self.norm_decay)),
name=bn_name + '.scale')
bn_bias_attr = ParamAttr(
regularizer=L2Decay(float(self.norm_decay)),
name=bn_name + '.offset')
out = fluid.layers.batch_norm(
input=conv,
act=None,
param_attr=bn_param_attr,
bias_attr=bn_bias_attr,
moving_mean_name=bn_name + '.mean',
moving_variance_name=bn_name + '.var')
# leaky relu here has `alpha` as 0.1, can not be set by
# `act` param in fluid.layers.batch_norm above.
if act == 'leaky':
out = fluid.layers.leaky_relu(x=out, alpha=0.1)
return out
def _downsample(self,
input,
ch_out,
filter_size=3,
stride=2,
padding=1,
name=None):
return self._conv_norm(
input,
ch_out=ch_out,
filter_size=filter_size,
stride=stride,
padding=padding,
name=name)
def basicblock(self, input, ch_out, name=None):
conv1 = self._conv_norm(
input,
ch_out=ch_out,
filter_size=1,
stride=1,
padding=0,
name=name + ".0")
conv2 = self._conv_norm(
conv1,
ch_out=ch_out * 2,
filter_size=3,
stride=1,
padding=1,
name=name + ".1")
out = fluid.layers.elementwise_add(x=input, y=conv2, act=None)
return out
def layer_warp(self, block_func, input, ch_out, count, name=None):
out = block_func(input, ch_out=ch_out, name='{}.0'.format(name))
for j in six.moves.xrange(1, count):
out = block_func(out, ch_out=ch_out, name='{}.{}'.format(name, j))
return out
def __call__(self, input):
"""Get the backbone of DarkNet, that is output for the 5 stages.
:param input: Variable of input image
:type input: Variable
:Returns: The last variables of each stage.
"""
stages, block_func = self.depth_cfg[self.depth]
stages = stages[0:5]
conv = self._conv_norm(
input=input,
ch_out=32,
filter_size=3,
stride=1,
padding=1,
name=self.prefix_name + "yolo_input")
downsample_ = self._downsample(
input=conv,
ch_out=conv.shape[1] * 2,
name=self.prefix_name + "yolo_input.downsample")
blocks = []
for i, stage in enumerate(stages):
block = self.layer_warp(
block_func=block_func,
input=downsample_,
ch_out=32 * 2**i,
count=stage,
name=self.prefix_name + "stage.{}".format(i))
blocks.append(block)
if i < len(stages) - 1: # do not downsaple in the last stage
downsample_ = self._downsample(
input=block,
ch_out=block.shape[1] * 2,
name=self.prefix_name + "stage.{}.downsample".format(i))
if self.get_prediction:
pool = fluid.layers.pool2d(
input=block, pool_type='avg', global_pooling=True)
stdv = 1.0 / math.sqrt(pool.shape[1] * 1.0)
out = fluid.layers.fc(
input=pool,
size=self.class_dim,
param_attr=ParamAttr(
initializer=fluid.initializer.Uniform(-stdv, stdv),
name='fc_weights'),
bias_attr=ParamAttr(name='fc_offset'))
out = fluid.layers.softmax(out)
return out
else:
return blocks
# coding=utf-8 # coding=utf-8
from __future__ import absolute_import from __future__ import absolute_import
import ast
import argparse import argparse
import ast
import os import os
from functools import partial from functools import partial
import numpy as np import numpy as np
import paddle.fluid as fluid import paddle
import paddlehub as hub
from paddle.inference import Config from paddle.inference import Config
from paddle.inference import create_predictor from paddle.inference import create_predictor
from paddlehub.module.module import moduleinfo, runnable, serving
from paddlehub.common.paddle_helper import add_vars_prefix
from yolov3_darknet53_vehicles.darknet import DarkNet
from yolov3_darknet53_vehicles.processor import load_label_info, postprocess, base64_to_cv2
from yolov3_darknet53_vehicles.data_feed import reader from yolov3_darknet53_vehicles.data_feed import reader
from yolov3_darknet53_vehicles.yolo_head import MultiClassNMS, YOLOv3Head from yolov3_darknet53_vehicles.processor import base64_to_cv2
from yolov3_darknet53_vehicles.processor import load_label_info
from yolov3_darknet53_vehicles.processor import postprocess
import paddlehub as hub
from paddlehub.common.paddle_helper import add_vars_prefix
from paddlehub.module.module import moduleinfo
from paddlehub.module.module import runnable
from paddlehub.module.module import serving
@moduleinfo( @moduleinfo(name="yolov3_darknet53_vehicles",
name="yolov3_darknet53_vehicles", version="1.0.3",
version="1.0.2", type="CV/object_detection",
type="CV/object_detection", summary="Baidu's YOLOv3 model for vehicles detection, with backbone DarkNet53.",
summary="Baidu's YOLOv3 model for vehicles detection, with backbone DarkNet53.", author="paddlepaddle",
author="paddlepaddle", author_email="paddle-dev@baidu.com")
author_email="paddle-dev@baidu.com")
class YOLOv3DarkNet53Vehicles(hub.Module): class YOLOv3DarkNet53Vehicles(hub.Module):
def _initialize(self): def _initialize(self):
self.default_pretrained_model_path = os.path.join(self.directory, "yolov3_darknet53_vehicles_model") self.default_pretrained_model_path = os.path.join(self.directory, "yolov3_darknet53_vehicles_model")
self.label_names = load_label_info(os.path.join(self.directory, "label_file.txt")) self.label_names = load_label_info(os.path.join(self.directory, "label_file.txt"))
...@@ -81,93 +83,6 @@ class YOLOv3DarkNet53Vehicles(hub.Module): ...@@ -81,93 +83,6 @@ class YOLOv3DarkNet53Vehicles(hub.Module):
xpu_config.enable_xpu(100) xpu_config.enable_xpu(100)
self.xpu_predictor = create_predictor(xpu_config) self.xpu_predictor = create_predictor(xpu_config)
def context(self, trainable=True, pretrained=True, get_prediction=False):
"""
Distill the Head Features, so as to perform transfer learning.
Args:
trainable (bool): whether to set parameters trainable.
pretrained (bool): whether to load default pretrained model.
get_prediction (bool): whether to get prediction.
Returns:
inputs(dict): the input variables.
outputs(dict): the output variables.
context_prog (Program): the program to execute transfer learning.
"""
context_prog = fluid.Program()
startup_program = fluid.Program()
with fluid.program_guard(context_prog, startup_program):
with fluid.unique_name.guard():
# image
image = fluid.layers.data(name='image', shape=[3, 608, 608], dtype='float32')
# backbone
backbone = DarkNet(norm_type='sync_bn', norm_decay=0., depth=53)
# body_feats
body_feats = backbone(image)
# im_size
im_size = fluid.layers.data(name='im_size', shape=[2], dtype='int32')
# yolo_head
yolo_head = YOLOv3Head(
anchor_masks=[[6, 7, 8], [3, 4, 5], [0, 1, 2]],
anchors=[[8, 9], [10, 23], [19, 15], [23, 33], [40, 25], [54, 50], [101, 80], [139, 145],
[253, 224]],
norm_decay=0.,
num_classes=6,
ignore_thresh=0.7,
label_smooth=False,
nms=MultiClassNMS(
background_label=-1,
keep_top_k=100,
nms_threshold=0.45,
nms_top_k=400,
normalized=False,
score_threshold=0.005))
# head_features
head_features, body_features = yolo_head._get_outputs(body_feats, is_train=trainable)
place = fluid.CPUPlace()
exe = fluid.Executor(place)
exe.run(fluid.default_startup_program())
# var_prefix
var_prefix = '@HUB_{}@'.format(self.name)
# name of inputs
inputs = {'image': var_prefix + image.name, 'im_size': var_prefix + im_size.name}
# name of outputs
if get_prediction:
bbox_out = yolo_head.get_prediction(head_features, im_size)
outputs = {'bbox_out': [var_prefix + bbox_out.name]}
else:
outputs = {
'head_features': [var_prefix + var.name for var in head_features],
'body_features': [var_prefix + var.name for var in body_features]
}
# add_vars_prefix
add_vars_prefix(context_prog, var_prefix)
add_vars_prefix(fluid.default_startup_program(), var_prefix)
# inputs
inputs = {key: context_prog.global_block().vars[value] for key, value in inputs.items()}
# outputs
outputs = {
key: [context_prog.global_block().vars[varname] for varname in value]
for key, value in outputs.items()
}
# trainable
for param in context_prog.global_block().iter_parameters():
param.trainable = trainable
# pretrained
if pretrained:
def _if_exist(var):
return os.path.exists(os.path.join(self.default_pretrained_model_path, var.name))
fluid.io.load_vars(exe, self.default_pretrained_model_path, predicate=_if_exist)
else:
exe.run(startup_program)
return inputs, outputs, context_prog
def object_detection(self, def object_detection(self,
paths=None, paths=None,
images=None, images=None,
...@@ -222,7 +137,7 @@ class YOLOv3DarkNet53Vehicles(hub.Module): ...@@ -222,7 +137,7 @@ class YOLOv3DarkNet53Vehicles(hub.Module):
paths = paths if paths else list() paths = paths if paths else list()
data_reader = partial(reader, paths, images) data_reader = partial(reader, paths, images)
batch_reader = fluid.io.batch(data_reader, batch_size=batch_size) batch_reader = paddle.batch(data_reader, batch_size=batch_size)
res = [] res = []
for iter_id, feed_data in enumerate(batch_reader()): for iter_id, feed_data in enumerate(batch_reader()):
feed_data = np.array(feed_data) feed_data = np.array(feed_data)
...@@ -243,15 +158,14 @@ class YOLOv3DarkNet53Vehicles(hub.Module): ...@@ -243,15 +158,14 @@ class YOLOv3DarkNet53Vehicles(hub.Module):
output_names = predictor.get_output_names() output_names = predictor.get_output_names()
output_handle = predictor.get_output_handle(output_names[0]) output_handle = predictor.get_output_handle(output_names[0])
output = postprocess( output = postprocess(paths=paths,
paths=paths, images=images,
images=images, data_out=output_handle,
data_out=output_handle, score_thresh=score_thresh,
score_thresh=score_thresh, label_names=self.label_names,
label_names=self.label_names, output_dir=output_dir,
output_dir=output_dir, handle_id=iter_id * batch_size,
handle_id=iter_id * batch_size, visualization=visualization)
visualization=visualization)
res.extend(output) res.extend(output)
return res return res
...@@ -259,20 +173,19 @@ class YOLOv3DarkNet53Vehicles(hub.Module): ...@@ -259,20 +173,19 @@ class YOLOv3DarkNet53Vehicles(hub.Module):
if combined: if combined:
model_filename = "__model__" if not model_filename else model_filename model_filename = "__model__" if not model_filename else model_filename
params_filename = "__params__" if not params_filename else params_filename params_filename = "__params__" if not params_filename else params_filename
place = fluid.CPUPlace() place = paddle.CPUPlace()
exe = fluid.Executor(place) exe = paddle.Executor(place)
program, feeded_var_names, target_vars = fluid.io.load_inference_model( program, feeded_var_names, target_vars = paddle.static.load_inference_model(
dirname=self.default_pretrained_model_path, executor=exe) dirname=self.default_pretrained_model_path, executor=exe)
fluid.io.save_inference_model( paddle.static.save_inference_model(dirname=dirname,
dirname=dirname, main_program=program,
main_program=program, executor=exe,
executor=exe, feeded_var_names=feeded_var_names,
feeded_var_names=feeded_var_names, target_vars=target_vars,
target_vars=target_vars, model_filename=model_filename,
model_filename=model_filename, params_filename=params_filename)
params_filename=params_filename)
@serving @serving
def serving_method(self, images, **kwargs): def serving_method(self, images, **kwargs):
...@@ -288,44 +201,44 @@ class YOLOv3DarkNet53Vehicles(hub.Module): ...@@ -288,44 +201,44 @@ class YOLOv3DarkNet53Vehicles(hub.Module):
""" """
Run as a command. Run as a command.
""" """
self.parser = argparse.ArgumentParser( self.parser = argparse.ArgumentParser(description="Run the {} module.".format(self.name),
description="Run the {} module.".format(self.name), prog='hub run {}'.format(self.name),
prog='hub run {}'.format(self.name), usage='%(prog)s',
usage='%(prog)s', add_help=True)
add_help=True)
self.arg_input_group = self.parser.add_argument_group(title="Input options", description="Input data. Required") 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( self.arg_config_group = self.parser.add_argument_group(
title="Config options", description="Run configuration for controlling module behavior, not required.") title="Config options", description="Run configuration for controlling module behavior, not required.")
self.add_module_config_arg() self.add_module_config_arg()
self.add_module_input_arg() self.add_module_input_arg()
args = self.parser.parse_args(argvs) args = self.parser.parse_args(argvs)
results = self.object_detection( results = self.object_detection(paths=[args.input_path],
paths=[args.input_path], batch_size=args.batch_size,
batch_size=args.batch_size, use_gpu=args.use_gpu,
use_gpu=args.use_gpu, output_dir=args.output_dir,
output_dir=args.output_dir, visualization=args.visualization,
visualization=args.visualization, score_thresh=args.score_thresh,
score_thresh=args.score_thresh, use_device=args.use_device)
use_device=args.use_device)
return results return results
def add_module_config_arg(self): def add_module_config_arg(self):
""" """
Add the command config options. Add the command config options.
""" """
self.arg_config_group.add_argument( self.arg_config_group.add_argument('--use_gpu',
'--use_gpu', type=ast.literal_eval, default=False, help="whether use GPU or not") type=ast.literal_eval,
self.arg_config_group.add_argument( default=False,
'--output_dir', help="whether use GPU or not")
type=str, self.arg_config_group.add_argument('--output_dir',
default='yolov3_vehicles_detect_output', type=str,
help="The directory to save output images.") default='yolov3_vehicles_detect_output',
self.arg_config_group.add_argument( help="The directory to save output images.")
'--visualization', type=ast.literal_eval, default=False, help="whether to save output as images.") self.arg_config_group.add_argument('--visualization',
self.arg_config_group.add_argument( type=ast.literal_eval,
'--use_device', default=False,
choices=["cpu", "gpu", "xpu", "npu"], help="whether to save output as images.")
help="use cpu, gpu, xpu or npu. overwrites use_gpu flag.") self.arg_config_group.add_argument('--use_device',
choices=["cpu", "gpu", "xpu", "npu"],
help="use cpu, gpu, xpu or npu. overwrites use_gpu flag.")
def add_module_input_arg(self): def add_module_input_arg(self):
""" """
...@@ -333,5 +246,7 @@ class YOLOv3DarkNet53Vehicles(hub.Module): ...@@ -333,5 +246,7 @@ class YOLOv3DarkNet53Vehicles(hub.Module):
""" """
self.arg_input_group.add_argument('--input_path', type=str, help="path to image.") self.arg_input_group.add_argument('--input_path', type=str, help="path to image.")
self.arg_input_group.add_argument('--batch_size', type=ast.literal_eval, default=1, help="batch size.") self.arg_input_group.add_argument('--batch_size', type=ast.literal_eval, default=1, help="batch size.")
self.arg_input_group.add_argument( self.arg_input_group.add_argument('--score_thresh',
'--score_thresh', type=ast.literal_eval, default=0.2, help="threshold for object detecion.") type=ast.literal_eval,
default=0.2,
help="threshold for object detecion.")
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from collections import OrderedDict
from paddle import fluid
from paddle.fluid.param_attr import ParamAttr
from paddle.fluid.regularizer import L2Decay
__all__ = ['MultiClassNMS', 'YOLOv3Head']
class MultiClassNMS(object):
# __op__ = fluid.layers.multiclass_nms
def __init__(self, background_label, keep_top_k, nms_threshold, nms_top_k,
normalized, score_threshold):
super(MultiClassNMS, self).__init__()
self.background_label = background_label
self.keep_top_k = keep_top_k
self.nms_threshold = nms_threshold
self.nms_top_k = nms_top_k
self.normalized = normalized
self.score_threshold = score_threshold
class YOLOv3Head(object):
"""Head block for YOLOv3 network
Args:
norm_decay (float): weight decay for normalization layer weights
num_classes (int): number of output classes
ignore_thresh (float): threshold to ignore confidence loss
label_smooth (bool): whether to use label smoothing
anchors (list): anchors
anchor_masks (list): anchor masks
nms (object): an instance of `MultiClassNMS`
"""
def __init__(self,
norm_decay=0.,
num_classes=80,
ignore_thresh=0.7,
label_smooth=True,
anchors=[[10, 13], [16, 30], [33, 23], [30, 61], [62, 45],
[59, 119], [116, 90], [156, 198], [373, 326]],
anchor_masks=[[6, 7, 8], [3, 4, 5], [0, 1, 2]],
nms=MultiClassNMS(
background_label=-1,
keep_top_k=100,
nms_threshold=0.45,
nms_top_k=1000,
normalized=True,
score_threshold=0.01),
weight_prefix_name=''):
self.norm_decay = norm_decay
self.num_classes = num_classes
self.ignore_thresh = ignore_thresh
self.label_smooth = label_smooth
self.anchor_masks = anchor_masks
self._parse_anchors(anchors)
self.nms = nms
self.prefix_name = weight_prefix_name
def _conv_bn(self,
input,
ch_out,
filter_size,
stride,
padding,
act='leaky',
is_test=True,
name=None):
conv = fluid.layers.conv2d(
input=input,
num_filters=ch_out,
filter_size=filter_size,
stride=stride,
padding=padding,
act=None,
param_attr=ParamAttr(name=name + ".conv.weights"),
bias_attr=False)
bn_name = name + ".bn"
bn_param_attr = ParamAttr(
regularizer=L2Decay(self.norm_decay), name=bn_name + '.scale')
bn_bias_attr = ParamAttr(
regularizer=L2Decay(self.norm_decay), name=bn_name + '.offset')
out = fluid.layers.batch_norm(
input=conv,
act=None,
is_test=is_test,
param_attr=bn_param_attr,
bias_attr=bn_bias_attr,
moving_mean_name=bn_name + '.mean',
moving_variance_name=bn_name + '.var')
if act == 'leaky':
out = fluid.layers.leaky_relu(x=out, alpha=0.1)
return out
def _detection_block(self, input, channel, is_test=True, name=None):
assert channel % 2 == 0, \
"channel {} cannot be divided by 2 in detection block {}" \
.format(channel, name)
conv = input
for j in range(2):
conv = self._conv_bn(
conv,
channel,
filter_size=1,
stride=1,
padding=0,
is_test=is_test,
name='{}.{}.0'.format(name, j))
conv = self._conv_bn(
conv,
channel * 2,
filter_size=3,
stride=1,
padding=1,
is_test=is_test,
name='{}.{}.1'.format(name, j))
route = self._conv_bn(
conv,
channel,
filter_size=1,
stride=1,
padding=0,
is_test=is_test,
name='{}.2'.format(name))
tip = self._conv_bn(
route,
channel * 2,
filter_size=3,
stride=1,
padding=1,
is_test=is_test,
name='{}.tip'.format(name))
return route, tip
def _upsample(self, input, scale=2, name=None):
out = fluid.layers.resize_nearest(
input=input, scale=float(scale), name=name)
return out
def _parse_anchors(self, anchors):
"""
Check ANCHORS/ANCHOR_MASKS in config and parse mask_anchors
"""
self.anchors = []
self.mask_anchors = []
assert len(anchors) > 0, "ANCHORS not set."
assert len(self.anchor_masks) > 0, "ANCHOR_MASKS not set."
for anchor in anchors:
assert len(anchor) == 2, "anchor {} len should be 2".format(anchor)
self.anchors.extend(anchor)
anchor_num = len(anchors)
for masks in self.anchor_masks:
self.mask_anchors.append([])
for mask in masks:
assert mask < anchor_num, "anchor mask index overflow"
self.mask_anchors[-1].extend(anchors[mask])
def _get_outputs(self, input, is_train=True):
"""
Get YOLOv3 head output
Args:
input (list): List of Variables, output of backbone stages
is_train (bool): whether in train or test mode
Returns:
outputs (list): Variables of each output layer
"""
outputs = []
# get last out_layer_num blocks in reverse order
out_layer_num = len(self.anchor_masks)
if isinstance(input, OrderedDict):
blocks = list(input.values())[-1:-out_layer_num - 1:-1]
else:
blocks = input[-1:-out_layer_num - 1:-1]
route = None
for i, block in enumerate(blocks):
if i > 0: # perform concat in first 2 detection_block
block = fluid.layers.concat(input=[route, block], axis=1)
route, tip = self._detection_block(
block,
channel=512 // (2**i),
is_test=(not is_train),
name=self.prefix_name + "yolo_block.{}".format(i))
# out channel number = mask_num * (5 + class_num)
num_filters = len(self.anchor_masks[i]) * (self.num_classes + 5)
block_out = fluid.layers.conv2d(
input=tip,
num_filters=num_filters,
filter_size=1,
stride=1,
padding=0,
act=None,
param_attr=ParamAttr(name=self.prefix_name +
"yolo_output.{}.conv.weights".format(i)),
bias_attr=ParamAttr(
regularizer=L2Decay(0.),
name=self.prefix_name +
"yolo_output.{}.conv.bias".format(i)))
outputs.append(block_out)
if i < len(blocks) - 1:
# do not perform upsample in the last detection_block
route = self._conv_bn(
input=route,
ch_out=256 // (2**i),
filter_size=1,
stride=1,
padding=0,
is_test=(not is_train),
name=self.prefix_name + "yolo_transition.{}".format(i))
# upsample
route = self._upsample(route)
return outputs, blocks
def get_prediction(self, outputs, im_size):
"""
Get prediction result of YOLOv3 network
Args:
outputs (list): list of Variables, return from _get_outputs
im_size (Variable): Variable of size([h, w]) of each image
Returns:
pred (Variable): The prediction result after non-max suppress.
"""
boxes = []
scores = []
downsample = 32
for i, output in enumerate(outputs):
box, score = fluid.layers.yolo_box(
x=output,
img_size=im_size,
anchors=self.mask_anchors[i],
class_num=self.num_classes,
conf_thresh=self.nms.score_threshold,
downsample_ratio=downsample,
name=self.prefix_name + "yolo_box" + str(i))
boxes.append(box)
scores.append(fluid.layers.transpose(score, perm=[0, 2, 1]))
downsample //= 2
yolo_boxes = fluid.layers.concat(boxes, axis=1)
yolo_scores = fluid.layers.concat(scores, axis=2)
pred = fluid.layers.multiclass_nms(
bboxes=yolo_boxes,
scores=yolo_scores,
score_threshold=self.nms.score_threshold,
nms_top_k=self.nms.nms_top_k,
keep_top_k=self.nms.keep_top_k,
nms_threshold=self.nms.nms_threshold,
background_label=self.nms.background_label,
normalized=self.nms.normalized,
name="multiclass_nms")
return pred
# deeplabv3p_xception65_humanseg # deeplabv3p_xception65_humanseg
|模型名称|deeplabv3p_xception65_humanseg| |模型名称|deeplabv3p_xception65_humanseg|
| :--- | :---: | | :--- | :---: |
|类别|图像-图像分割| |类别|图像-图像分割|
|网络|deeplabv3p| |网络|deeplabv3p|
|数据集|百度自建数据集| |数据集|百度自建数据集|
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
<p align="center"> <p align="center">
<img src="https://user-images.githubusercontent.com/35907364/130913092-312a5f37-842e-4fd0-8db4-5f853fd8419f.jpg" width = "337" height = "505" hspace='10'/> <img src="https://user-images.githubusercontent.com/35907364/130913256-41056b21-1c3d-4ee2-b481-969c94754609.png" width = "337" height = "505" hspace='10'/> <img src="https://user-images.githubusercontent.com/35907364/130913092-312a5f37-842e-4fd0-8db4-5f853fd8419f.jpg" width = "337" height = "505" hspace='10'/> <img src="https://user-images.githubusercontent.com/35907364/130913256-41056b21-1c3d-4ee2-b481-969c94754609.png" width = "337" height = "505" hspace='10'/>
</p> </p>
- ### 模型介绍 - ### 模型介绍
- DeepLabv3+使用百度自建数据集进行训练,可用于人像分割,支持任意大小的图片输入。 - DeepLabv3+使用百度自建数据集进行训练,可用于人像分割,支持任意大小的图片输入。
...@@ -41,7 +41,7 @@ ...@@ -41,7 +41,7 @@
- ```shell - ```shell
$ hub install deeplabv3p_xception65_humanseg $ hub install deeplabv3p_xception65_humanseg
``` ```
- 如您安装时遇到问题,可参考:[零基础windows安装](../../../../docs/docs_ch/get_start/windows_quickstart.md) - 如您安装时遇到问题,可参考:[零基础windows安装](../../../../docs/docs_ch/get_start/windows_quickstart.md)
| [零基础Linux安装](../../../../docs/docs_ch/get_start/linux_quickstart.md) | [零基础MacOS安装](../../../../docs/docs_ch/get_start/mac_quickstart.md) | [零基础Linux安装](../../../../docs/docs_ch/get_start/linux_quickstart.md) | [零基础MacOS安装](../../../../docs/docs_ch/get_start/mac_quickstart.md)
...@@ -176,4 +176,8 @@ ...@@ -176,4 +176,8 @@
* 1.1.2 * 1.1.2
修复cudnn为8.0.4显存泄露问题 移除 fluid api
- ```shell
$ hub install deeplabv3p_xception65_humanseg==1.1.2
```
# deeplabv3p_xception65_humanseg # deeplabv3p_xception65_humanseg
|Module Name |deeplabv3p_xception65_humanseg| |Module Name |deeplabv3p_xception65_humanseg|
| :--- | :---: | | :--- | :---: |
|Category|Image segmentation| |Category|Image segmentation|
|Network|deeplabv3p| |Network|deeplabv3p|
|Dataset|Baidu self-built dataset| |Dataset|Baidu self-built dataset|
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
|Data indicators |-| |Data indicators |-|
|Latest update date|2021-02-26| |Latest update date|2021-02-26|
## I. Basic Information ## I. Basic Information
- ### Application Effect Display - ### Application Effect Display
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
<p align="center"> <p align="center">
<img src="https://user-images.githubusercontent.com/35907364/130913092-312a5f37-842e-4fd0-8db4-5f853fd8419f.jpg" width = "337" height = "505" hspace='10'/> <img src="https://user-images.githubusercontent.com/35907364/130913256-41056b21-1c3d-4ee2-b481-969c94754609.png" width = "337" height = "505" hspace='10'/> <img src="https://user-images.githubusercontent.com/35907364/130913092-312a5f37-842e-4fd0-8db4-5f853fd8419f.jpg" width = "337" height = "505" hspace='10'/> <img src="https://user-images.githubusercontent.com/35907364/130913256-41056b21-1c3d-4ee2-b481-969c94754609.png" width = "337" height = "505" hspace='10'/>
</p> </p>
- ### Module Introduction - ### Module Introduction
- DeepLabv3+ model is trained by Baidu self-built dataset, which can be used for portrait segmentation. - DeepLabv3+ model is trained by Baidu self-built dataset, which can be used for portrait segmentation.
...@@ -89,9 +89,9 @@ ...@@ -89,9 +89,9 @@
- **Return** - **Return**
* res (list\[dict\]): The list of recognition results, where each element is dict and each field is: * res (list\[dict\]): The list of recognition results, where each element is dict and each field is:
* save\_path (str, optional): Save path of the result. * save\_path (str, optional): Save path of the result.
* data (numpy.ndarray): The result of portrait segmentation. * data (numpy.ndarray): The result of portrait segmentation.
- ```python - ```python
def save_inference_model(dirname, def save_inference_model(dirname,
...@@ -172,4 +172,8 @@ ...@@ -172,4 +172,8 @@
* 1.1.2 * 1.1.2
Fix memory leakage problem of on cudnn 8.0.4 Remove fluid api
- ```shell
$ hub install deeplabv3p_xception65_humanseg==1.1.2
```
...@@ -2,28 +2,33 @@ ...@@ -2,28 +2,33 @@
from __future__ import absolute_import from __future__ import absolute_import
from __future__ import division from __future__ import division
import argparse
import ast import ast
import os import os
import argparse
import numpy as np import numpy as np
import paddle.fluid as fluid import paddle
import paddlehub as hub
from paddle.fluid.core import PaddleTensor, AnalysisConfig, create_paddle_predictor
from paddlehub.module.module import moduleinfo, runnable, serving
from deeplabv3p_xception65_humanseg.processor import postprocess, base64_to_cv2, cv2_to_base64
from deeplabv3p_xception65_humanseg.data_feed import reader from deeplabv3p_xception65_humanseg.data_feed import reader
from deeplabv3p_xception65_humanseg.processor import base64_to_cv2
from deeplabv3p_xception65_humanseg.processor import cv2_to_base64
from deeplabv3p_xception65_humanseg.processor import postprocess
from paddle.inference import Config
from paddle.inference import create_predictor
import paddlehub as hub
from paddlehub.module.module import moduleinfo
from paddlehub.module.module import runnable
from paddlehub.module.module import serving
@moduleinfo(
name="deeplabv3p_xception65_humanseg", @moduleinfo(name="deeplabv3p_xception65_humanseg",
type="CV/semantic_segmentation", type="CV/semantic_segmentation",
author="baidu-vis", author="baidu-vis",
author_email="", author_email="",
summary="DeepLabv3+ is a semantic segmentation model.", summary="DeepLabv3+ is a semantic segmentation model.",
version="1.1.1") version="1.1.2")
class DeeplabV3pXception65HumanSeg(hub.Module): class DeeplabV3pXception65HumanSeg(hub.Module):
def _initialize(self): def _initialize(self):
self.default_pretrained_model_path = os.path.join(self.directory, "deeplabv3p_xception65_humanseg_model") self.default_pretrained_model_path = os.path.join(self.directory, "deeplabv3p_xception65_humanseg_model")
self._set_config() self._set_config()
...@@ -32,10 +37,10 @@ class DeeplabV3pXception65HumanSeg(hub.Module): ...@@ -32,10 +37,10 @@ class DeeplabV3pXception65HumanSeg(hub.Module):
""" """
predictor config setting predictor config setting
""" """
cpu_config = AnalysisConfig(self.default_pretrained_model_path) cpu_config = Config(self.default_pretrained_model_path)
cpu_config.disable_glog_info() cpu_config.disable_glog_info()
cpu_config.disable_gpu() cpu_config.disable_gpu()
self.cpu_predictor = create_paddle_predictor(cpu_config) self.cpu_predictor = create_predictor(cpu_config)
try: try:
_places = os.environ["CUDA_VISIBLE_DEVICES"] _places = os.environ["CUDA_VISIBLE_DEVICES"]
...@@ -44,10 +49,10 @@ class DeeplabV3pXception65HumanSeg(hub.Module): ...@@ -44,10 +49,10 @@ class DeeplabV3pXception65HumanSeg(hub.Module):
except: except:
use_gpu = False use_gpu = False
if use_gpu: if use_gpu:
gpu_config = AnalysisConfig(self.default_pretrained_model_path) gpu_config = Config(self.default_pretrained_model_path)
gpu_config.disable_glog_info() gpu_config.disable_glog_info()
gpu_config.enable_use_gpu(memory_pool_init_size_mb=1000, device_id=0) gpu_config.enable_use_gpu(memory_pool_init_size_mb=1000, device_id=0)
self.gpu_predictor = create_paddle_predictor(gpu_config) self.gpu_predictor = create_predictor(gpu_config)
def segmentation(self, def segmentation(self,
images=None, images=None,
...@@ -107,18 +112,25 @@ class DeeplabV3pXception65HumanSeg(hub.Module): ...@@ -107,18 +112,25 @@ class DeeplabV3pXception65HumanSeg(hub.Module):
pass pass
# feed batch image # feed batch image
batch_image = np.array([data['image'] for data in batch_data]) batch_image = np.array([data['image'] for data in batch_data])
batch_image = PaddleTensor(batch_image.copy())
output = self.gpu_predictor.run([batch_image]) if use_gpu else self.cpu_predictor.run([batch_image]) predictor = self.gpu_predictor if use_gpu else self.cpu_predictor
output = np.expand_dims(output[0].as_ndarray(), axis=1) input_names = predictor.get_input_names()
input_handle = predictor.get_input_handle(input_names[0])
input_handle.copy_from_cpu(batch_image)
predictor.run()
output_names = predictor.get_output_names()
output_handle = predictor.get_output_handle(output_names[0])
output_data = output_handle.copy_to_cpu()
output = np.expand_dims(output_data, axis=1)
# postprocess one by one # postprocess one by one
for i in range(len(batch_data)): for i in range(len(batch_data)):
out = postprocess( out = postprocess(data_out=output[i],
data_out=output[i], org_im=batch_data[i]['org_im'],
org_im=batch_data[i]['org_im'], org_im_shape=batch_data[i]['org_im_shape'],
org_im_shape=batch_data[i]['org_im_shape'], org_im_path=batch_data[i]['org_im_path'],
org_im_path=batch_data[i]['org_im_path'], output_dir=output_dir,
output_dir=output_dir, visualization=visualization)
visualization=visualization)
res.append(out) res.append(out)
return res return res
...@@ -126,20 +138,19 @@ class DeeplabV3pXception65HumanSeg(hub.Module): ...@@ -126,20 +138,19 @@ class DeeplabV3pXception65HumanSeg(hub.Module):
if combined: if combined:
model_filename = "__model__" if not model_filename else model_filename model_filename = "__model__" if not model_filename else model_filename
params_filename = "__params__" if not params_filename else params_filename params_filename = "__params__" if not params_filename else params_filename
place = fluid.CPUPlace() place = paddle.CPUPlace()
exe = fluid.Executor(place) exe = paddle.Executor(place)
program, feeded_var_names, target_vars = fluid.io.load_inference_model( program, feeded_var_names, target_vars = paddle.static.load_inference_model(
dirname=self.default_pretrained_model_path, executor=exe) dirname=self.default_pretrained_model_path, executor=exe)
fluid.io.save_inference_model( paddle.static.save_inference_model(dirname=dirname,
dirname=dirname, main_program=program,
main_program=program, executor=exe,
executor=exe, feeded_var_names=feeded_var_names,
feeded_var_names=feeded_var_names, target_vars=target_vars,
target_vars=target_vars, model_filename=model_filename,
model_filename=model_filename, params_filename=params_filename)
params_filename=params_filename)
@serving @serving
def serving_method(self, images, **kwargs): def serving_method(self, images, **kwargs):
...@@ -156,11 +167,10 @@ class DeeplabV3pXception65HumanSeg(hub.Module): ...@@ -156,11 +167,10 @@ class DeeplabV3pXception65HumanSeg(hub.Module):
""" """
Run as a command. Run as a command.
""" """
self.parser = argparse.ArgumentParser( self.parser = argparse.ArgumentParser(description="Run the {} module.".format(self.name),
description="Run the {} module.".format(self.name), prog='hub run {}'.format(self.name),
prog='hub run {}'.format(self.name), usage='%(prog)s',
usage='%(prog)s', add_help=True)
add_help=True)
self.arg_input_group = self.parser.add_argument_group(title="Input options", description="Input data. Required") 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( self.arg_config_group = self.parser.add_argument_group(
...@@ -168,24 +178,29 @@ class DeeplabV3pXception65HumanSeg(hub.Module): ...@@ -168,24 +178,29 @@ class DeeplabV3pXception65HumanSeg(hub.Module):
self.add_module_config_arg() self.add_module_config_arg()
self.add_module_input_arg() self.add_module_input_arg()
args = self.parser.parse_args(argvs) args = self.parser.parse_args(argvs)
results = self.segmentation( results = self.segmentation(paths=[args.input_path],
paths=[args.input_path], batch_size=args.batch_size,
batch_size=args.batch_size, use_gpu=args.use_gpu,
use_gpu=args.use_gpu, output_dir=args.output_dir,
output_dir=args.output_dir, visualization=args.visualization)
visualization=args.visualization)
return results return results
def add_module_config_arg(self): def add_module_config_arg(self):
""" """
Add the command config options. Add the command config options.
""" """
self.arg_config_group.add_argument( self.arg_config_group.add_argument('--use_gpu',
'--use_gpu', type=ast.literal_eval, default=False, help="whether use GPU or not") type=ast.literal_eval,
self.arg_config_group.add_argument( default=False,
'--output_dir', type=str, default='humanseg_output', help="The directory to save output images.") help="whether use GPU or not")
self.arg_config_group.add_argument( self.arg_config_group.add_argument('--output_dir',
'--visualization', type=ast.literal_eval, default=False, help="whether to save output as images.") type=str,
default='humanseg_output',
help="The directory to save output images.")
self.arg_config_group.add_argument('--visualization',
type=ast.literal_eval,
default=False,
help="whether to save output as images.")
self.arg_config_group.add_argument('--batch_size', type=ast.literal_eval, default=1, help="batch size.") self.arg_config_group.add_argument('--batch_size', type=ast.literal_eval, default=1, help="batch size.")
def add_module_input_arg(self): def add_module_input_arg(self):
......
# chinese_ocr_db_crnn_mobile # chinese_ocr_db_crnn_mobile
|模型名称|chinese_ocr_db_crnn_mobile| |模型名称|chinese_ocr_db_crnn_mobile|
| :--- | :---: | | :--- | :---: |
|类别|图像-文字识别| |类别|图像-文字识别|
|网络|Differentiable Binarization+RCNN| |网络|Differentiable Binarization+RCNN|
|数据集|icdar2015数据集| |数据集|icdar2015数据集|
...@@ -35,9 +35,9 @@ ...@@ -35,9 +35,9 @@
## 二、安装 ## 二、安装
- ### 1、环境依赖 - ### 1、环境依赖
- paddlepaddle >= 1.7.2 - paddlepaddle >= 1.7.2
- paddlehub >= 1.6.0 | [如何安装paddlehub](../../../../docs/docs_ch/get_start/installation.rst) - paddlehub >= 1.6.0 | [如何安装paddlehub](../../../../docs/docs_ch/get_start/installation.rst)
...@@ -48,7 +48,7 @@ ...@@ -48,7 +48,7 @@
- ```shell - ```shell
$ pip install shapely pyclipper $ pip install shapely pyclipper
``` ```
- **该Module依赖于第三方库shapely和pyclipper,使用该Module之前,请先安装shapely和pyclipper。** - **该Module依赖于第三方库shapely和pyclipper,使用该Module之前,请先安装shapely和pyclipper。**
- ### 2、安装 - ### 2、安装
...@@ -87,7 +87,7 @@ ...@@ -87,7 +87,7 @@
- ```python - ```python
__init__(text_detector_module=None, enable_mkldnn=False) __init__(text_detector_module=None, enable_mkldnn=False)
``` ```
- 构造ChineseOCRDBCRNN对象 - 构造ChineseOCRDBCRNN对象
- **参数** - **参数**
...@@ -191,11 +191,15 @@ ...@@ -191,11 +191,15 @@
* 1.1.1 * 1.1.1
支持文本中空格识别。 支持文本中空格识别。
* 1.1.2 * 1.1.2
修复只能检出30字段问题。 修复只能检出30字段问题。
* 1.1.3
移除 fluid api
- ```shell - ```shell
$ hub install chinese_ocr_db_crnn_mobile==1.1.2 $ hub install chinese_ocr_db_crnn_mobile==1.1.3
``` ```
...@@ -197,6 +197,10 @@ ...@@ -197,6 +197,10 @@
Fixed an issue where only 30 fields can be detected. Fixed an issue where only 30 fields can be detected.
* 1.1.3
Remove fluid api
- ```shell - ```shell
$ hub install chinese_ocr_db_crnn_mobile==1.1.2 $ hub install chinese_ocr_db_crnn_mobile==1.1.3
``` ```
...@@ -6,28 +6,35 @@ import math ...@@ -6,28 +6,35 @@ import math
import os import os
import time import time
from paddle.fluid.core import AnalysisConfig, create_paddle_predictor, PaddleTensor
from paddlehub.common.logger import logger
from paddlehub.module.module import moduleinfo, runnable, serving
from PIL import Image
import cv2 import cv2
import numpy as np import numpy as np
import paddle.fluid as fluid import paddle
import paddlehub as hub
from chinese_ocr_db_crnn_mobile.character import CharacterOps from chinese_ocr_db_crnn_mobile.character import CharacterOps
from chinese_ocr_db_crnn_mobile.utils import base64_to_cv2, draw_ocr, get_image_ext, sorted_boxes from chinese_ocr_db_crnn_mobile.utils import base64_to_cv2
from chinese_ocr_db_crnn_mobile.utils import draw_ocr
from chinese_ocr_db_crnn_mobile.utils import get_image_ext
from chinese_ocr_db_crnn_mobile.utils import sorted_boxes
from paddle.inference import Config
from paddle.inference import create_predictor
from PIL import Image
import paddlehub as hub
from paddlehub.common.logger import logger
from paddlehub.module.module import moduleinfo
from paddlehub.module.module import runnable
from paddlehub.module.module import serving
@moduleinfo( @moduleinfo(
name="chinese_ocr_db_crnn_mobile", name="chinese_ocr_db_crnn_mobile",
version="1.1.2", version="1.1.3",
summary="The module can recognize the chinese texts in an image. Firstly, it will detect the text box positions \ summary="The module can recognize the chinese texts in an image. Firstly, it will detect the text box positions \
based on the differentiable_binarization_chn module. Then it classifies the text angle and recognizes the chinese texts. ", based on the differentiable_binarization_chn module. Then it classifies the text angle and recognizes the chinese texts. ",
author="paddle-dev", author="paddle-dev",
author_email="paddle-dev@baidu.com", author_email="paddle-dev@baidu.com",
type="cv/text_recognition") type="cv/text_recognition")
class ChineseOCRDBCRNN(hub.Module): class ChineseOCRDBCRNN(hub.Module):
def _initialize(self, text_detector_module=None, enable_mkldnn=False): def _initialize(self, text_detector_module=None, enable_mkldnn=False):
""" """
initialize with the necessary elements initialize with the necessary elements
...@@ -60,7 +67,7 @@ class ChineseOCRDBCRNN(hub.Module): ...@@ -60,7 +67,7 @@ class ChineseOCRDBCRNN(hub.Module):
model_file_path = os.path.join(pretrained_model_path, 'model') model_file_path = os.path.join(pretrained_model_path, 'model')
params_file_path = os.path.join(pretrained_model_path, 'params') params_file_path = os.path.join(pretrained_model_path, 'params')
config = AnalysisConfig(model_file_path, params_file_path) config = Config(model_file_path, params_file_path)
try: try:
_places = os.environ["CUDA_VISIBLE_DEVICES"] _places = os.environ["CUDA_VISIBLE_DEVICES"]
int(_places[0]) int(_places[0])
...@@ -81,14 +88,14 @@ class ChineseOCRDBCRNN(hub.Module): ...@@ -81,14 +88,14 @@ class ChineseOCRDBCRNN(hub.Module):
config.delete_pass("conv_transpose_eltwiseadd_bn_fuse_pass") config.delete_pass("conv_transpose_eltwiseadd_bn_fuse_pass")
config.switch_use_feed_fetch_ops(False) config.switch_use_feed_fetch_ops(False)
predictor = create_paddle_predictor(config) predictor = create_predictor(config)
input_names = predictor.get_input_names() input_names = predictor.get_input_names()
input_tensor = predictor.get_input_tensor(input_names[0]) input_tensor = predictor.get_input_handle(input_names[0])
output_names = predictor.get_output_names() output_names = predictor.get_output_names()
output_tensors = [] output_tensors = []
for output_name in output_names: for output_name in output_names:
output_tensor = predictor.get_output_tensor(output_name) output_tensor = predictor.get_output_handle(output_name)
output_tensors.append(output_tensor) output_tensors.append(output_tensor)
return predictor, input_tensor, output_tensors return predictor, input_tensor, output_tensors
...@@ -99,8 +106,9 @@ class ChineseOCRDBCRNN(hub.Module): ...@@ -99,8 +106,9 @@ class ChineseOCRDBCRNN(hub.Module):
text detect module text detect module
""" """
if not self._text_detector_module: if not self._text_detector_module:
self._text_detector_module = hub.Module( self._text_detector_module = hub.Module(name='chinese_text_detection_db_mobile',
name='chinese_text_detection_db_mobile', enable_mkldnn=self.enable_mkldnn, version='1.0.4') enable_mkldnn=self.enable_mkldnn,
version='1.0.4')
return self._text_detector_module return self._text_detector_module
def read_images(self, paths=[]): def read_images(self, paths=[]):
...@@ -129,8 +137,10 @@ class ChineseOCRDBCRNN(hub.Module): ...@@ -129,8 +137,10 @@ class ChineseOCRDBCRNN(hub.Module):
img_crop_height = int(max(np.linalg.norm(points[0] - points[3]), np.linalg.norm(points[1] - points[2]))) img_crop_height = int(max(np.linalg.norm(points[0] - points[3]), np.linalg.norm(points[1] - points[2])))
pts_std = np.float32([[0, 0], [img_crop_width, 0], [img_crop_width, img_crop_height], [0, img_crop_height]]) pts_std = np.float32([[0, 0], [img_crop_width, 0], [img_crop_width, img_crop_height], [0, img_crop_height]])
M = cv2.getPerspectiveTransform(points, pts_std) M = cv2.getPerspectiveTransform(points, pts_std)
dst_img = cv2.warpPerspective( dst_img = cv2.warpPerspective(img,
img, M, (img_crop_width, img_crop_height), borderMode=cv2.BORDER_REPLICATE, flags=cv2.INTER_CUBIC) M, (img_crop_width, img_crop_height),
borderMode=cv2.BORDER_REPLICATE,
flags=cv2.INTER_CUBIC)
dst_img_height, dst_img_width = dst_img.shape[0:2] dst_img_height, dst_img_width = dst_img.shape[0:2]
if dst_img_height * 1.0 / dst_img_width >= 1.5: if dst_img_height * 1.0 / dst_img_width >= 1.5:
dst_img = np.rot90(dst_img) dst_img = np.rot90(dst_img)
...@@ -223,8 +233,9 @@ class ChineseOCRDBCRNN(hub.Module): ...@@ -223,8 +233,9 @@ class ChineseOCRDBCRNN(hub.Module):
assert predicted_data != [], "There is not any image to be predicted. Please check the input data." assert predicted_data != [], "There is not any image to be predicted. Please check the input data."
detection_results = self.text_detector_module.detect_text( detection_results = self.text_detector_module.detect_text(images=predicted_data,
images=predicted_data, use_gpu=self.use_gpu, box_thresh=box_thresh) use_gpu=self.use_gpu,
box_thresh=box_thresh)
boxes = [np.array(item['data']).astype(np.float32) for item in detection_results] boxes = [np.array(item['data']).astype(np.float32) for item in detection_results]
all_results = [] all_results = []
...@@ -240,8 +251,8 @@ class ChineseOCRDBCRNN(hub.Module): ...@@ -240,8 +251,8 @@ class ChineseOCRDBCRNN(hub.Module):
tmp_box = copy.deepcopy(boxes[num_box]) tmp_box = copy.deepcopy(boxes[num_box])
img_crop = self.get_rotate_crop_image(original_image, tmp_box) img_crop = self.get_rotate_crop_image(original_image, tmp_box)
img_crop_list.append(img_crop) img_crop_list.append(img_crop)
img_crop_list, angle_list = self._classify_text( img_crop_list, angle_list = self._classify_text(img_crop_list,
img_crop_list, angle_classification_thresh=angle_classification_thresh) angle_classification_thresh=angle_classification_thresh)
rec_results = self._recognize_text(img_crop_list) rec_results = self._recognize_text(img_crop_list)
# if the recognized text confidence score is lower than text_thresh, then drop it # if the recognized text confidence score is lower than text_thresh, then drop it
...@@ -273,18 +284,23 @@ class ChineseOCRDBCRNN(hub.Module): ...@@ -273,18 +284,23 @@ class ChineseOCRDBCRNN(hub.Module):
return results return results
def save_result_image( def save_result_image(
self, self,
original_image, original_image,
detection_boxes, detection_boxes,
rec_results, rec_results,
output_dir='ocr_result', output_dir='ocr_result',
text_thresh=0.5, text_thresh=0.5,
): ):
image = Image.fromarray(cv2.cvtColor(original_image, cv2.COLOR_BGR2RGB)) image = Image.fromarray(cv2.cvtColor(original_image, cv2.COLOR_BGR2RGB))
txts = [item[0] for item in rec_results] txts = [item[0] for item in rec_results]
scores = [item[1] for item in rec_results] scores = [item[1] for item in rec_results]
draw_img = draw_ocr( draw_img = draw_ocr(image,
image, detection_boxes, txts, scores, font_file=self.font_file, draw_txt=True, drop_score=text_thresh) detection_boxes,
txts,
scores,
font_file=self.font_file,
draw_txt=True,
drop_score=text_thresh)
if not os.path.exists(output_dir): if not os.path.exists(output_dir):
os.makedirs(output_dir) os.makedirs(output_dir)
...@@ -322,7 +338,7 @@ class ChineseOCRDBCRNN(hub.Module): ...@@ -322,7 +338,7 @@ class ChineseOCRDBCRNN(hub.Module):
norm_img_batch = norm_img_batch.copy() norm_img_batch = norm_img_batch.copy()
self.cls_input_tensor.copy_from_cpu(norm_img_batch) self.cls_input_tensor.copy_from_cpu(norm_img_batch)
self.cls_predictor.zero_copy_run() self.cls_predictor.run()
prob_out = self.cls_output_tensors[0].copy_to_cpu() prob_out = self.cls_output_tensors[0].copy_to_cpu()
label_out = self.cls_output_tensors[1].copy_to_cpu() label_out = self.cls_output_tensors[1].copy_to_cpu()
...@@ -366,7 +382,7 @@ class ChineseOCRDBCRNN(hub.Module): ...@@ -366,7 +382,7 @@ class ChineseOCRDBCRNN(hub.Module):
norm_img_batch = norm_img_batch.copy() norm_img_batch = norm_img_batch.copy()
self.rec_input_tensor.copy_from_cpu(norm_img_batch) self.rec_input_tensor.copy_from_cpu(norm_img_batch)
self.rec_predictor.zero_copy_run() self.rec_predictor.run()
rec_idx_batch = self.rec_output_tensors[0].copy_to_cpu() rec_idx_batch = self.rec_output_tensors[0].copy_to_cpu()
rec_idx_lod = self.rec_output_tensors[0].lod()[0] rec_idx_lod = self.rec_output_tensors[0].lod()[0]
...@@ -407,60 +423,57 @@ class ChineseOCRDBCRNN(hub.Module): ...@@ -407,60 +423,57 @@ class ChineseOCRDBCRNN(hub.Module):
if combined: if combined:
model_filename = "__model__" if not model_filename else model_filename model_filename = "__model__" if not model_filename else model_filename
params_filename = "__params__" if not params_filename else params_filename params_filename = "__params__" if not params_filename else params_filename
place = fluid.CPUPlace() place = paddle.CPUPlace()
exe = fluid.Executor(place) exe = paddle.Executor(place)
model_file_path = os.path.join(self.rec_pretrained_model_path, 'model') model_file_path = os.path.join(self.rec_pretrained_model_path, 'model')
params_file_path = os.path.join(self.rec_pretrained_model_path, 'params') params_file_path = os.path.join(self.rec_pretrained_model_path, 'params')
program, feeded_var_names, target_vars = fluid.io.load_inference_model( program, feeded_var_names, target_vars = paddle.static.load_inference_model(
dirname=self.rec_pretrained_model_path, dirname=self.rec_pretrained_model_path,
model_filename=model_file_path, model_filename=model_file_path,
params_filename=params_file_path, params_filename=params_file_path,
executor=exe) executor=exe)
fluid.io.save_inference_model( paddle.static.save_inference_model(dirname=dirname,
dirname=dirname, main_program=program,
main_program=program, executor=exe,
executor=exe, feeded_var_names=feeded_var_names,
feeded_var_names=feeded_var_names, target_vars=target_vars,
target_vars=target_vars, model_filename=model_filename,
model_filename=model_filename, params_filename=params_filename)
params_filename=params_filename)
def _save_classifier_model(self, dirname, model_filename=None, params_filename=None, combined=True): def _save_classifier_model(self, dirname, model_filename=None, params_filename=None, combined=True):
if combined: if combined:
model_filename = "__model__" if not model_filename else model_filename model_filename = "__model__" if not model_filename else model_filename
params_filename = "__params__" if not params_filename else params_filename params_filename = "__params__" if not params_filename else params_filename
place = fluid.CPUPlace() place = paddle.CPUPlace()
exe = fluid.Executor(place) exe = paddle.Executor(place)
model_file_path = os.path.join(self.cls_pretrained_model_path, 'model') model_file_path = os.path.join(self.cls_pretrained_model_path, 'model')
params_file_path = os.path.join(self.cls_pretrained_model_path, 'params') params_file_path = os.path.join(self.cls_pretrained_model_path, 'params')
program, feeded_var_names, target_vars = fluid.io.load_inference_model( program, feeded_var_names, target_vars = paddle.static.load_inference_model(
dirname=self.cls_pretrained_model_path, dirname=self.cls_pretrained_model_path,
model_filename=model_file_path, model_filename=model_file_path,
params_filename=params_file_path, params_filename=params_file_path,
executor=exe) executor=exe)
fluid.io.save_inference_model( paddle.static.save_inference_model(dirname=dirname,
dirname=dirname, main_program=program,
main_program=program, executor=exe,
executor=exe, feeded_var_names=feeded_var_names,
feeded_var_names=feeded_var_names, target_vars=target_vars,
target_vars=target_vars, model_filename=model_filename,
model_filename=model_filename, params_filename=params_filename)
params_filename=params_filename)
@runnable @runnable
def run_cmd(self, argvs): def run_cmd(self, argvs):
""" """
Run as a command Run as a command
""" """
self.parser = argparse.ArgumentParser( self.parser = argparse.ArgumentParser(description="Run the %s module." % self.name,
description="Run the %s module." % self.name, prog='hub run %s' % self.name,
prog='hub run %s' % self.name, usage='%(prog)s',
usage='%(prog)s', add_help=True)
add_help=True)
self.arg_input_group = self.parser.add_argument_group(title="Input options", description="Input data. Required") 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( self.arg_config_group = self.parser.add_argument_group(
...@@ -470,20 +483,28 @@ class ChineseOCRDBCRNN(hub.Module): ...@@ -470,20 +483,28 @@ class ChineseOCRDBCRNN(hub.Module):
self.add_module_input_arg() self.add_module_input_arg()
args = self.parser.parse_args(argvs) args = self.parser.parse_args(argvs)
results = self.recognize_text( results = self.recognize_text(paths=[args.input_path],
paths=[args.input_path], use_gpu=args.use_gpu, output_dir=args.output_dir, visualization=args.visualization) use_gpu=args.use_gpu,
output_dir=args.output_dir,
visualization=args.visualization)
return results return results
def add_module_config_arg(self): def add_module_config_arg(self):
""" """
Add the command config options Add the command config options
""" """
self.arg_config_group.add_argument( self.arg_config_group.add_argument('--use_gpu',
'--use_gpu', type=ast.literal_eval, default=False, help="whether use GPU or not") type=ast.literal_eval,
self.arg_config_group.add_argument( default=False,
'--output_dir', type=str, default='ocr_result', help="The directory to save output images.") help="whether use GPU or not")
self.arg_config_group.add_argument( self.arg_config_group.add_argument('--output_dir',
'--visualization', type=ast.literal_eval, default=False, help="whether to save output as images.") type=str,
default='ocr_result',
help="The directory to save output images.")
self.arg_config_group.add_argument('--visualization',
type=ast.literal_eval,
default=False,
help="whether to save output as images.")
def add_module_input_arg(self): def add_module_input_arg(self):
""" """
......
# chinese_ocr_db_crnn_server # chinese_ocr_db_crnn_server
|模型名称|chinese_ocr_db_crnn_server| |模型名称|chinese_ocr_db_crnn_server|
| :--- | :---: | | :--- | :---: |
|类别|图像-文字识别| |类别|图像-文字识别|
|网络|Differentiable Binarization+RCNN| |网络|Differentiable Binarization+RCNN|
|数据集|icdar2015数据集| |数据集|icdar2015数据集|
...@@ -32,9 +32,9 @@ ...@@ -32,9 +32,9 @@
## 二、安装 ## 二、安装
- ### 1、环境依赖 - ### 1、环境依赖
- paddlepaddle >= 1.7.2 - paddlepaddle >= 1.7.2
- paddlehub >= 1.6.0 | [如何安装paddlehub](../../../../docs/docs_ch/get_start/installation.rst) - paddlehub >= 1.6.0 | [如何安装paddlehub](../../../../docs/docs_ch/get_start/installation.rst)
...@@ -45,7 +45,7 @@ ...@@ -45,7 +45,7 @@
- ```shell - ```shell
$ pip install shapely pyclipper $ pip install shapely pyclipper
``` ```
- **该Module依赖于第三方库shapely和pyclipper,使用该Module之前,请先安装shapely和pyclipper。** - **该Module依赖于第三方库shapely和pyclipper,使用该Module之前,请先安装shapely和pyclipper。**
- ### 2、安装 - ### 2、安装
...@@ -183,11 +183,15 @@ ...@@ -183,11 +183,15 @@
* 1.1.1 * 1.1.1
支持文本中空格识别。 支持文本中空格识别。
* 1.1.2 * 1.1.2
修复检出字段无法超过30个问题。 修复检出字段无法超过30个问题。
* 1.1.3
移除 fluid api
- ```shell - ```shell
$ hub install chinese_ocr_db_crnn_server==1.1.2 $ hub install chinese_ocr_db_crnn_server==1.1.3
``` ```
...@@ -10,28 +10,35 @@ import math ...@@ -10,28 +10,35 @@ import math
import os import os
import time import time
from paddle.fluid.core import AnalysisConfig, create_paddle_predictor, PaddleTensor
from paddlehub.common.logger import logger
from paddlehub.module.module import moduleinfo, runnable, serving
from PIL import Image
import cv2 import cv2
import numpy as np import numpy as np
import paddle.fluid as fluid import paddle
import paddlehub as hub
from chinese_ocr_db_crnn_server.character import CharacterOps from chinese_ocr_db_crnn_server.character import CharacterOps
from chinese_ocr_db_crnn_server.utils import base64_to_cv2, draw_ocr, get_image_ext, sorted_boxes from chinese_ocr_db_crnn_server.utils import base64_to_cv2
from chinese_ocr_db_crnn_server.utils import draw_ocr
from chinese_ocr_db_crnn_server.utils import get_image_ext
from chinese_ocr_db_crnn_server.utils import sorted_boxes
from paddle.inference import Config
from paddle.inference import create_predictor
from PIL import Image
import paddlehub as hub
from paddlehub.common.logger import logger
from paddlehub.module.module import moduleinfo
from paddlehub.module.module import runnable
from paddlehub.module.module import serving
@moduleinfo( @moduleinfo(
name="chinese_ocr_db_crnn_server", name="chinese_ocr_db_crnn_server",
version="1.1.2", version="1.1.3",
summary= summary=
"The module can recognize the chinese texts in an image. Firstly, it will detect the text box positions based on the differentiable_binarization_chn module. Then it recognizes the chinese texts. ", "The module can recognize the chinese texts in an image. Firstly, it will detect the text box positions based on the differentiable_binarization_chn module. Then it recognizes the chinese texts. ",
author="paddle-dev", author="paddle-dev",
author_email="paddle-dev@baidu.com", author_email="paddle-dev@baidu.com",
type="cv/text_recognition") type="cv/text_recognition")
class ChineseOCRDBCRNNServer(hub.Module): class ChineseOCRDBCRNNServer(hub.Module):
def _initialize(self, text_detector_module=None, enable_mkldnn=False): def _initialize(self, text_detector_module=None, enable_mkldnn=False):
""" """
initialize with the necessary elements initialize with the necessary elements
...@@ -64,7 +71,7 @@ class ChineseOCRDBCRNNServer(hub.Module): ...@@ -64,7 +71,7 @@ class ChineseOCRDBCRNNServer(hub.Module):
model_file_path = os.path.join(pretrained_model_path, 'model') model_file_path = os.path.join(pretrained_model_path, 'model')
params_file_path = os.path.join(pretrained_model_path, 'params') params_file_path = os.path.join(pretrained_model_path, 'params')
config = AnalysisConfig(model_file_path, params_file_path) config = Config(model_file_path, params_file_path)
try: try:
_places = os.environ["CUDA_VISIBLE_DEVICES"] _places = os.environ["CUDA_VISIBLE_DEVICES"]
int(_places[0]) int(_places[0])
...@@ -85,14 +92,14 @@ class ChineseOCRDBCRNNServer(hub.Module): ...@@ -85,14 +92,14 @@ class ChineseOCRDBCRNNServer(hub.Module):
config.delete_pass("conv_transpose_eltwiseadd_bn_fuse_pass") config.delete_pass("conv_transpose_eltwiseadd_bn_fuse_pass")
config.switch_use_feed_fetch_ops(False) config.switch_use_feed_fetch_ops(False)
predictor = create_paddle_predictor(config) predictor = create_predictor(config)
input_names = predictor.get_input_names() input_names = predictor.get_input_names()
input_tensor = predictor.get_input_tensor(input_names[0]) input_tensor = predictor.get_input_handle(input_names[0])
output_names = predictor.get_output_names() output_names = predictor.get_output_names()
output_tensors = [] output_tensors = []
for output_name in output_names: for output_name in output_names:
output_tensor = predictor.get_output_tensor(output_name) output_tensor = predictor.get_output_handle(output_name)
output_tensors.append(output_tensor) output_tensors.append(output_tensor)
return predictor, input_tensor, output_tensors return predictor, input_tensor, output_tensors
...@@ -103,8 +110,9 @@ class ChineseOCRDBCRNNServer(hub.Module): ...@@ -103,8 +110,9 @@ class ChineseOCRDBCRNNServer(hub.Module):
text detect module text detect module
""" """
if not self._text_detector_module: if not self._text_detector_module:
self._text_detector_module = hub.Module( self._text_detector_module = hub.Module(name='chinese_text_detection_db_server',
name='chinese_text_detection_db_server', enable_mkldnn=self.enable_mkldnn, version='1.0.2') enable_mkldnn=self.enable_mkldnn,
version='1.0.2')
return self._text_detector_module return self._text_detector_module
def read_images(self, paths=[]): def read_images(self, paths=[]):
...@@ -133,8 +141,10 @@ class ChineseOCRDBCRNNServer(hub.Module): ...@@ -133,8 +141,10 @@ class ChineseOCRDBCRNNServer(hub.Module):
img_crop_height = int(max(np.linalg.norm(points[0] - points[3]), np.linalg.norm(points[1] - points[2]))) img_crop_height = int(max(np.linalg.norm(points[0] - points[3]), np.linalg.norm(points[1] - points[2])))
pts_std = np.float32([[0, 0], [img_crop_width, 0], [img_crop_width, img_crop_height], [0, img_crop_height]]) pts_std = np.float32([[0, 0], [img_crop_width, 0], [img_crop_width, img_crop_height], [0, img_crop_height]])
M = cv2.getPerspectiveTransform(points, pts_std) M = cv2.getPerspectiveTransform(points, pts_std)
dst_img = cv2.warpPerspective( dst_img = cv2.warpPerspective(img,
img, M, (img_crop_width, img_crop_height), borderMode=cv2.BORDER_REPLICATE, flags=cv2.INTER_CUBIC) M, (img_crop_width, img_crop_height),
borderMode=cv2.BORDER_REPLICATE,
flags=cv2.INTER_CUBIC)
dst_img_height, dst_img_width = dst_img.shape[0:2] dst_img_height, dst_img_width = dst_img.shape[0:2]
if dst_img_height * 1.0 / dst_img_width >= 1.5: if dst_img_height * 1.0 / dst_img_width >= 1.5:
dst_img = np.rot90(dst_img) dst_img = np.rot90(dst_img)
...@@ -227,8 +237,9 @@ class ChineseOCRDBCRNNServer(hub.Module): ...@@ -227,8 +237,9 @@ class ChineseOCRDBCRNNServer(hub.Module):
assert predicted_data != [], "There is not any image to be predicted. Please check the input data." assert predicted_data != [], "There is not any image to be predicted. Please check the input data."
detection_results = self.text_detector_module.detect_text( detection_results = self.text_detector_module.detect_text(images=predicted_data,
images=predicted_data, use_gpu=self.use_gpu, box_thresh=box_thresh) use_gpu=self.use_gpu,
box_thresh=box_thresh)
boxes = [np.array(item['data']).astype(np.float32) for item in detection_results] boxes = [np.array(item['data']).astype(np.float32) for item in detection_results]
all_results = [] all_results = []
...@@ -244,8 +255,8 @@ class ChineseOCRDBCRNNServer(hub.Module): ...@@ -244,8 +255,8 @@ class ChineseOCRDBCRNNServer(hub.Module):
tmp_box = copy.deepcopy(boxes[num_box]) tmp_box = copy.deepcopy(boxes[num_box])
img_crop = self.get_rotate_crop_image(original_image, tmp_box) img_crop = self.get_rotate_crop_image(original_image, tmp_box)
img_crop_list.append(img_crop) img_crop_list.append(img_crop)
img_crop_list, angle_list = self._classify_text( img_crop_list, angle_list = self._classify_text(img_crop_list,
img_crop_list, angle_classification_thresh=angle_classification_thresh) angle_classification_thresh=angle_classification_thresh)
rec_results = self._recognize_text(img_crop_list) rec_results = self._recognize_text(img_crop_list)
# if the recognized text confidence score is lower than text_thresh, then drop it # if the recognized text confidence score is lower than text_thresh, then drop it
...@@ -277,18 +288,23 @@ class ChineseOCRDBCRNNServer(hub.Module): ...@@ -277,18 +288,23 @@ class ChineseOCRDBCRNNServer(hub.Module):
return results return results
def save_result_image( def save_result_image(
self, self,
original_image, original_image,
detection_boxes, detection_boxes,
rec_results, rec_results,
output_dir='ocr_result', output_dir='ocr_result',
text_thresh=0.5, text_thresh=0.5,
): ):
image = Image.fromarray(cv2.cvtColor(original_image, cv2.COLOR_BGR2RGB)) image = Image.fromarray(cv2.cvtColor(original_image, cv2.COLOR_BGR2RGB))
txts = [item[0] for item in rec_results] txts = [item[0] for item in rec_results]
scores = [item[1] for item in rec_results] scores = [item[1] for item in rec_results]
draw_img = draw_ocr( draw_img = draw_ocr(image,
image, detection_boxes, txts, scores, font_file=self.font_file, draw_txt=True, drop_score=text_thresh) detection_boxes,
txts,
scores,
font_file=self.font_file,
draw_txt=True,
drop_score=text_thresh)
if not os.path.exists(output_dir): if not os.path.exists(output_dir):
os.makedirs(output_dir) os.makedirs(output_dir)
...@@ -326,7 +342,7 @@ class ChineseOCRDBCRNNServer(hub.Module): ...@@ -326,7 +342,7 @@ class ChineseOCRDBCRNNServer(hub.Module):
norm_img_batch = norm_img_batch.copy() norm_img_batch = norm_img_batch.copy()
self.cls_input_tensor.copy_from_cpu(norm_img_batch) self.cls_input_tensor.copy_from_cpu(norm_img_batch)
self.cls_predictor.zero_copy_run() self.cls_predictor.run()
prob_out = self.cls_output_tensors[0].copy_to_cpu() prob_out = self.cls_output_tensors[0].copy_to_cpu()
label_out = self.cls_output_tensors[1].copy_to_cpu() label_out = self.cls_output_tensors[1].copy_to_cpu()
...@@ -370,7 +386,7 @@ class ChineseOCRDBCRNNServer(hub.Module): ...@@ -370,7 +386,7 @@ class ChineseOCRDBCRNNServer(hub.Module):
norm_img_batch = norm_img_batch.copy() norm_img_batch = norm_img_batch.copy()
self.rec_input_tensor.copy_from_cpu(norm_img_batch) self.rec_input_tensor.copy_from_cpu(norm_img_batch)
self.rec_predictor.zero_copy_run() self.rec_predictor.run()
rec_idx_batch = self.rec_output_tensors[0].copy_to_cpu() rec_idx_batch = self.rec_output_tensors[0].copy_to_cpu()
rec_idx_lod = self.rec_output_tensors[0].lod()[0] rec_idx_lod = self.rec_output_tensors[0].lod()[0]
...@@ -411,60 +427,57 @@ class ChineseOCRDBCRNNServer(hub.Module): ...@@ -411,60 +427,57 @@ class ChineseOCRDBCRNNServer(hub.Module):
if combined: if combined:
model_filename = "__model__" if not model_filename else model_filename model_filename = "__model__" if not model_filename else model_filename
params_filename = "__params__" if not params_filename else params_filename params_filename = "__params__" if not params_filename else params_filename
place = fluid.CPUPlace() place = paddle.CPUPlace()
exe = fluid.Executor(place) exe = paddle.Executor(place)
model_file_path = os.path.join(self.rec_pretrained_model_path, 'model') model_file_path = os.path.join(self.rec_pretrained_model_path, 'model')
params_file_path = os.path.join(self.rec_pretrained_model_path, 'params') params_file_path = os.path.join(self.rec_pretrained_model_path, 'params')
program, feeded_var_names, target_vars = fluid.io.load_inference_model( program, feeded_var_names, target_vars = paddle.static.load_inference_model(
dirname=self.rec_pretrained_model_path, dirname=self.rec_pretrained_model_path,
model_filename=model_file_path, model_filename=model_file_path,
params_filename=params_file_path, params_filename=params_file_path,
executor=exe) executor=exe)
fluid.io.save_inference_model( paddle.static.save_inference_model(dirname=dirname,
dirname=dirname, main_program=program,
main_program=program, executor=exe,
executor=exe, feeded_var_names=feeded_var_names,
feeded_var_names=feeded_var_names, target_vars=target_vars,
target_vars=target_vars, model_filename=model_filename,
model_filename=model_filename, params_filename=params_filename)
params_filename=params_filename)
def _save_classifier_model(self, dirname, model_filename=None, params_filename=None, combined=True): def _save_classifier_model(self, dirname, model_filename=None, params_filename=None, combined=True):
if combined: if combined:
model_filename = "__model__" if not model_filename else model_filename model_filename = "__model__" if not model_filename else model_filename
params_filename = "__params__" if not params_filename else params_filename params_filename = "__params__" if not params_filename else params_filename
place = fluid.CPUPlace() place = paddle.CPUPlace()
exe = fluid.Executor(place) exe = paddle.Executor(place)
model_file_path = os.path.join(self.cls_pretrained_model_path, 'model') model_file_path = os.path.join(self.cls_pretrained_model_path, 'model')
params_file_path = os.path.join(self.cls_pretrained_model_path, 'params') params_file_path = os.path.join(self.cls_pretrained_model_path, 'params')
program, feeded_var_names, target_vars = fluid.io.load_inference_model( program, feeded_var_names, target_vars = paddle.static.load_inference_model(
dirname=self.cls_pretrained_model_path, dirname=self.cls_pretrained_model_path,
model_filename=model_file_path, model_filename=model_file_path,
params_filename=params_file_path, params_filename=params_file_path,
executor=exe) executor=exe)
fluid.io.save_inference_model( paddle.static.save_inference_model(dirname=dirname,
dirname=dirname, main_program=program,
main_program=program, executor=exe,
executor=exe, feeded_var_names=feeded_var_names,
feeded_var_names=feeded_var_names, target_vars=target_vars,
target_vars=target_vars, model_filename=model_filename,
model_filename=model_filename, params_filename=params_filename)
params_filename=params_filename)
@runnable @runnable
def run_cmd(self, argvs): def run_cmd(self, argvs):
""" """
Run as a command Run as a command
""" """
self.parser = argparse.ArgumentParser( self.parser = argparse.ArgumentParser(description="Run the %s module." % self.name,
description="Run the %s module." % self.name, prog='hub run %s' % self.name,
prog='hub run %s' % self.name, usage='%(prog)s',
usage='%(prog)s', add_help=True)
add_help=True)
self.arg_input_group = self.parser.add_argument_group(title="Input options", description="Input data. Required") 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( self.arg_config_group = self.parser.add_argument_group(
...@@ -474,20 +487,28 @@ class ChineseOCRDBCRNNServer(hub.Module): ...@@ -474,20 +487,28 @@ class ChineseOCRDBCRNNServer(hub.Module):
self.add_module_input_arg() self.add_module_input_arg()
args = self.parser.parse_args(argvs) args = self.parser.parse_args(argvs)
results = self.recognize_text( results = self.recognize_text(paths=[args.input_path],
paths=[args.input_path], use_gpu=args.use_gpu, output_dir=args.output_dir, visualization=args.visualization) use_gpu=args.use_gpu,
output_dir=args.output_dir,
visualization=args.visualization)
return results return results
def add_module_config_arg(self): def add_module_config_arg(self):
""" """
Add the command config options Add the command config options
""" """
self.arg_config_group.add_argument( self.arg_config_group.add_argument('--use_gpu',
'--use_gpu', type=ast.literal_eval, default=False, help="whether use GPU or not") type=ast.literal_eval,
self.arg_config_group.add_argument( default=False,
'--output_dir', type=str, default='ocr_result', help="The directory to save output images.") help="whether use GPU or not")
self.arg_config_group.add_argument( self.arg_config_group.add_argument('--output_dir',
'--visualization', type=ast.literal_eval, default=False, help="whether to save output as images.") type=str,
default='ocr_result',
help="The directory to save output images.")
self.arg_config_group.add_argument('--visualization',
type=ast.literal_eval,
default=False,
help="whether to save output as images.")
def add_module_input_arg(self): def add_module_input_arg(self):
""" """
......
# chinese_text_detection_db_mobile # chinese_text_detection_db_mobile
|模型名称|chinese_text_detection_db_mobile| |模型名称|chinese_text_detection_db_mobile|
| :--- | :---: | | :--- | :---: |
|类别|图像-文字识别| |类别|图像-文字识别|
|网络|Differentiable Binarization| |网络|Differentiable Binarization|
|数据集|icdar2015数据集| |数据集|icdar2015数据集|
...@@ -33,9 +33,9 @@ ...@@ -33,9 +33,9 @@
## 二、安装 ## 二、安装
- ### 1、环境依赖 - ### 1、环境依赖
- paddlepaddle >= 1.7.2 - paddlepaddle >= 1.7.2
- paddlehub >= 1.6.0 | [如何安装paddlehub](../../../../docs/docs_ch/get_start/installation.rst) - paddlehub >= 1.6.0 | [如何安装paddlehub](../../../../docs/docs_ch/get_start/installation.rst)
...@@ -46,7 +46,7 @@ ...@@ -46,7 +46,7 @@
- ```shell - ```shell
$ pip install shapely pyclipper $ pip install shapely pyclipper
``` ```
- **该Module依赖于第三方库shapely和pyclipper,使用该Module之前,请先安装shapely和pyclipper。** - **该Module依赖于第三方库shapely和pyclipper,使用该Module之前,请先安装shapely和pyclipper。**
- ### 2、安装 - ### 2、安装
...@@ -85,7 +85,7 @@ ...@@ -85,7 +85,7 @@
- ```python - ```python
__init__(enable_mkldnn=False) __init__(enable_mkldnn=False)
``` ```
- 构造ChineseTextDetectionDB对象 - 构造ChineseTextDetectionDB对象
- **参数** - **参数**
...@@ -100,7 +100,7 @@ ...@@ -100,7 +100,7 @@
box_thresh=0.5, box_thresh=0.5,
visualization=False) visualization=False)
``` ```
- 预测API,检测输入图片中的所有中文文本的位置。 - 预测API,检测输入图片中的所有中文文本的位置。
- **参数** - **参数**
...@@ -181,7 +181,11 @@ ...@@ -181,7 +181,11 @@
* 1.0.4 * 1.0.4
使用超轻量级的三阶段模型(文本框检测-角度分类-文字识别)识别图片文字。 使用超轻量级的三阶段模型(文本框检测-角度分类-文字识别)识别图片文字。
* 1.0.5
移除 fluid api
- ```shell - ```shell
$ hub install chinese_text_detection_db_mobile==1.0.4 $ hub install chinese_text_detection_db_mobile==1.0.5
``` ```
...@@ -5,19 +5,23 @@ from __future__ import print_function ...@@ -5,19 +5,23 @@ from __future__ import print_function
import argparse import argparse
import ast import ast
import base64
import math import math
import os import os
import time import time
from paddle.fluid.core import AnalysisConfig, create_paddle_predictor, PaddleTensor
from paddlehub.common.logger import logger
from paddlehub.module.module import moduleinfo, runnable, serving
from PIL import Image
import base64
import cv2 import cv2
import numpy as np import numpy as np
import paddle.fluid as fluid import paddle
from paddle.inference import Config
from paddle.inference import create_predictor
from PIL import Image
import paddlehub as hub import paddlehub as hub
from paddlehub.common.logger import logger
from paddlehub.module.module import moduleinfo
from paddlehub.module.module import runnable
from paddlehub.module.module import serving
def base64_to_cv2(b64str): def base64_to_cv2(b64str):
...@@ -29,13 +33,14 @@ def base64_to_cv2(b64str): ...@@ -29,13 +33,14 @@ def base64_to_cv2(b64str):
@moduleinfo( @moduleinfo(
name="chinese_text_detection_db_mobile", name="chinese_text_detection_db_mobile",
version="1.0.4", version="1.0.5",
summary= summary=
"The module aims to detect chinese text position in the image, which is based on differentiable_binarization algorithm.", "The module aims to detect chinese text position in the image, which is based on differentiable_binarization algorithm.",
author="paddle-dev", author="paddle-dev",
author_email="paddle-dev@baidu.com", author_email="paddle-dev@baidu.com",
type="cv/text_recognition") type="cv/text_recognition")
class ChineseTextDetectionDB(hub.Module): class ChineseTextDetectionDB(hub.Module):
def _initialize(self, enable_mkldnn=False): def _initialize(self, enable_mkldnn=False):
""" """
initialize with the necessary elements initialize with the necessary elements
...@@ -60,7 +65,7 @@ class ChineseTextDetectionDB(hub.Module): ...@@ -60,7 +65,7 @@ class ChineseTextDetectionDB(hub.Module):
model_file_path = os.path.join(self.pretrained_model_path, 'model') model_file_path = os.path.join(self.pretrained_model_path, 'model')
params_file_path = os.path.join(self.pretrained_model_path, 'params') params_file_path = os.path.join(self.pretrained_model_path, 'params')
config = AnalysisConfig(model_file_path, params_file_path) config = Config(model_file_path, params_file_path)
try: try:
_places = os.environ["CUDA_VISIBLE_DEVICES"] _places = os.environ["CUDA_VISIBLE_DEVICES"]
int(_places[0]) int(_places[0])
...@@ -83,13 +88,13 @@ class ChineseTextDetectionDB(hub.Module): ...@@ -83,13 +88,13 @@ class ChineseTextDetectionDB(hub.Module):
# use zero copy # use zero copy
config.delete_pass("conv_transpose_eltwiseadd_bn_fuse_pass") config.delete_pass("conv_transpose_eltwiseadd_bn_fuse_pass")
config.switch_use_feed_fetch_ops(False) config.switch_use_feed_fetch_ops(False)
self.predictor = create_paddle_predictor(config) self.predictor = create_predictor(config)
input_names = self.predictor.get_input_names() input_names = self.predictor.get_input_names()
self.input_tensor = self.predictor.get_input_tensor(input_names[0]) self.input_tensor = self.predictor.get_input_handle(input_names[0])
output_names = self.predictor.get_output_names() output_names = self.predictor.get_output_names()
self.output_tensors = [] self.output_tensors = []
for output_name in output_names: for output_name in output_names:
output_tensor = self.predictor.get_output_tensor(output_name) output_tensor = self.predictor.get_output_handle(output_name)
self.output_tensors.append(output_tensor) self.output_tensors.append(output_tensor)
def read_images(self, paths=[]): def read_images(self, paths=[]):
...@@ -218,7 +223,7 @@ class ChineseTextDetectionDB(hub.Module): ...@@ -218,7 +223,7 @@ class ChineseTextDetectionDB(hub.Module):
else: else:
im = im.copy() im = im.copy()
self.input_tensor.copy_from_cpu(im) self.input_tensor.copy_from_cpu(im)
self.predictor.zero_copy_run() self.predictor.run()
outputs = [] outputs = []
for output_tensor in self.output_tensors: for output_tensor in self.output_tensors:
...@@ -255,25 +260,23 @@ class ChineseTextDetectionDB(hub.Module): ...@@ -255,25 +260,23 @@ class ChineseTextDetectionDB(hub.Module):
if combined: if combined:
model_filename = "__model__" if not model_filename else model_filename model_filename = "__model__" if not model_filename else model_filename
params_filename = "__params__" if not params_filename else params_filename params_filename = "__params__" if not params_filename else params_filename
place = fluid.CPUPlace() place = paddle.CPUPlace()
exe = fluid.Executor(place) exe = paddle.Executor(place)
model_file_path = os.path.join(self.pretrained_model_path, 'model') model_file_path = os.path.join(self.pretrained_model_path, 'model')
params_file_path = os.path.join(self.pretrained_model_path, 'params') params_file_path = os.path.join(self.pretrained_model_path, 'params')
program, feeded_var_names, target_vars = fluid.io.load_inference_model( program, feeded_var_names, target_vars = paddle.static.load_inference_model(dirname=self.pretrained_model_path,
dirname=self.pretrained_model_path, model_filename=model_file_path,
model_filename=model_file_path, params_filename=params_file_path,
params_filename=params_file_path, executor=exe)
executor=exe)
paddle.static.save_inference_model(dirname=dirname,
fluid.io.save_inference_model( main_program=program,
dirname=dirname, executor=exe,
main_program=program, feeded_var_names=feeded_var_names,
executor=exe, target_vars=target_vars,
feeded_var_names=feeded_var_names, model_filename=model_filename,
target_vars=target_vars, params_filename=params_filename)
model_filename=model_filename,
params_filename=params_filename)
@serving @serving
def serving_method(self, images, **kwargs): def serving_method(self, images, **kwargs):
...@@ -289,11 +292,10 @@ class ChineseTextDetectionDB(hub.Module): ...@@ -289,11 +292,10 @@ class ChineseTextDetectionDB(hub.Module):
""" """
Run as a command Run as a command
""" """
self.parser = argparse.ArgumentParser( self.parser = argparse.ArgumentParser(description="Run the %s module." % self.name,
description="Run the %s module." % self.name, prog='hub run %s' % self.name,
prog='hub run %s' % self.name, usage='%(prog)s',
usage='%(prog)s', add_help=True)
add_help=True)
self.arg_input_group = self.parser.add_argument_group(title="Input options", description="Input data. Required") 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( self.arg_config_group = self.parser.add_argument_group(
...@@ -303,20 +305,28 @@ class ChineseTextDetectionDB(hub.Module): ...@@ -303,20 +305,28 @@ class ChineseTextDetectionDB(hub.Module):
self.add_module_input_arg() self.add_module_input_arg()
args = self.parser.parse_args(argvs) args = self.parser.parse_args(argvs)
results = self.detect_text( results = self.detect_text(paths=[args.input_path],
paths=[args.input_path], use_gpu=args.use_gpu, output_dir=args.output_dir, visualization=args.visualization) use_gpu=args.use_gpu,
output_dir=args.output_dir,
visualization=args.visualization)
return results return results
def add_module_config_arg(self): def add_module_config_arg(self):
""" """
Add the command config options Add the command config options
""" """
self.arg_config_group.add_argument( self.arg_config_group.add_argument('--use_gpu',
'--use_gpu', type=ast.literal_eval, default=False, help="whether use GPU or not") type=ast.literal_eval,
self.arg_config_group.add_argument( default=False,
'--output_dir', type=str, default='detection_result', help="The directory to save output images.") help="whether use GPU or not")
self.arg_config_group.add_argument( self.arg_config_group.add_argument('--output_dir',
'--visualization', type=ast.literal_eval, default=False, help="whether to save output as images.") type=str,
default='detection_result',
help="The directory to save output images.")
self.arg_config_group.add_argument('--visualization',
type=ast.literal_eval,
default=False,
help="whether to save output as images.")
def add_module_input_arg(self): def add_module_input_arg(self):
""" """
......
# chinese_text_detection_db_server # chinese_text_detection_db_server
|模型名称|chinese_text_detection_db_server| |模型名称|chinese_text_detection_db_server|
| :--- | :---: | | :--- | :---: |
|类别|图像-文字识别| |类别|图像-文字识别|
|网络|Differentiable Binarization| |网络|Differentiable Binarization|
|数据集|icdar2015数据集| |数据集|icdar2015数据集|
...@@ -33,9 +33,9 @@ ...@@ -33,9 +33,9 @@
## 二、安装 ## 二、安装
- ### 1、环境依赖 - ### 1、环境依赖
- paddlepaddle >= 1.7.2 - paddlepaddle >= 1.7.2
- paddlehub >= 1.6.0 | [如何安装paddlehub](../../../../docs/docs_ch/get_start/installation.rst) - paddlehub >= 1.6.0 | [如何安装paddlehub](../../../../docs/docs_ch/get_start/installation.rst)
...@@ -46,7 +46,7 @@ ...@@ -46,7 +46,7 @@
- ```shell - ```shell
$ pip install shapely pyclipper $ pip install shapely pyclipper
``` ```
- **该Module依赖于第三方库shapely和pyclipper,使用该Module之前,请先安装shapely和pyclipper。** - **该Module依赖于第三方库shapely和pyclipper,使用该Module之前,请先安装shapely和pyclipper。**
- ### 2、安装 - ### 2、安装
...@@ -100,7 +100,7 @@ ...@@ -100,7 +100,7 @@
visualization=False) visualization=False)
``` ```
- 预测API,检测输入图片中的所有中文文本的位置。 - 预测API,检测输入图片中的所有中文文本的位置。
- **参数** - **参数**
- paths (list\[str\]): 图片的路径; - paths (list\[str\]): 图片的路径;
...@@ -145,7 +145,7 @@ ...@@ -145,7 +145,7 @@
def cv2_to_base64(image): def cv2_to_base64(image):
data = cv2.imencode('.jpg', image)[1] data = cv2.imencode('.jpg', image)[1]
return base64.b64encode(data.tostring()).decode('utf8') return base64.b64encode(data.tostring()).decode('utf8')
# 发送HTTP请求 # 发送HTTP请求
data = {'images':[cv2_to_base64(cv2.imread("/PATH/TO/IMAGE"))]} data = {'images':[cv2_to_base64(cv2.imread("/PATH/TO/IMAGE"))]}
headers = {"Content-type": "application/json"} headers = {"Content-type": "application/json"}
...@@ -170,7 +170,11 @@ ...@@ -170,7 +170,11 @@
* 1.0.2 * 1.0.2
增加更多预训练数据,更新预训练参数 增加更多预训练数据,更新预训练参数
* 1.0.3
移除 fluid api
- ```shell - ```shell
$ hub install chinese_text_detection_db_server==1.0.2 $ hub install chinese_text_detection_db_server==1.0.3
``` ```
...@@ -5,19 +5,23 @@ from __future__ import print_function ...@@ -5,19 +5,23 @@ from __future__ import print_function
import argparse import argparse
import ast import ast
import base64
import math import math
import os import os
import time import time
from paddle.fluid.core import AnalysisConfig, create_paddle_predictor, PaddleTensor
from paddlehub.common.logger import logger
from paddlehub.module.module import moduleinfo, runnable, serving
from PIL import Image
import base64
import cv2 import cv2
import numpy as np import numpy as np
import paddle.fluid as fluid import paddle
from paddle.inference import Config
from paddle.inference import create_predictor
from PIL import Image
import paddlehub as hub import paddlehub as hub
from paddlehub.common.logger import logger
from paddlehub.module.module import moduleinfo
from paddlehub.module.module import runnable
from paddlehub.module.module import serving
def base64_to_cv2(b64str): def base64_to_cv2(b64str):
...@@ -29,13 +33,14 @@ def base64_to_cv2(b64str): ...@@ -29,13 +33,14 @@ def base64_to_cv2(b64str):
@moduleinfo( @moduleinfo(
name="chinese_text_detection_db_server", name="chinese_text_detection_db_server",
version="1.0.2", version="1.0.3",
summary= summary=
"The module aims to detect chinese text position in the image, which is based on differentiable_binarization algorithm.", "The module aims to detect chinese text position in the image, which is based on differentiable_binarization algorithm.",
author="paddle-dev", author="paddle-dev",
author_email="paddle-dev@baidu.com", author_email="paddle-dev@baidu.com",
type="cv/text_recognition") type="cv/text_recognition")
class ChineseTextDetectionDBServer(hub.Module): class ChineseTextDetectionDBServer(hub.Module):
def _initialize(self, enable_mkldnn=False): def _initialize(self, enable_mkldnn=False):
""" """
initialize with the necessary elements initialize with the necessary elements
...@@ -60,7 +65,7 @@ class ChineseTextDetectionDBServer(hub.Module): ...@@ -60,7 +65,7 @@ class ChineseTextDetectionDBServer(hub.Module):
model_file_path = os.path.join(self.pretrained_model_path, 'model') model_file_path = os.path.join(self.pretrained_model_path, 'model')
params_file_path = os.path.join(self.pretrained_model_path, 'params') params_file_path = os.path.join(self.pretrained_model_path, 'params')
config = AnalysisConfig(model_file_path, params_file_path) config = Config(model_file_path, params_file_path)
try: try:
_places = os.environ["CUDA_VISIBLE_DEVICES"] _places = os.environ["CUDA_VISIBLE_DEVICES"]
int(_places[0]) int(_places[0])
...@@ -80,13 +85,13 @@ class ChineseTextDetectionDBServer(hub.Module): ...@@ -80,13 +85,13 @@ class ChineseTextDetectionDBServer(hub.Module):
# use zero copy # use zero copy
config.delete_pass("conv_transpose_eltwiseadd_bn_fuse_pass") config.delete_pass("conv_transpose_eltwiseadd_bn_fuse_pass")
config.switch_use_feed_fetch_ops(False) config.switch_use_feed_fetch_ops(False)
self.predictor = create_paddle_predictor(config) self.predictor = create_predictor(config)
input_names = self.predictor.get_input_names() input_names = self.predictor.get_input_names()
self.input_tensor = self.predictor.get_input_tensor(input_names[0]) self.input_tensor = self.predictor.get_input_handle(input_names[0])
output_names = self.predictor.get_output_names() output_names = self.predictor.get_output_names()
self.output_tensors = [] self.output_tensors = []
for output_name in output_names: for output_name in output_names:
output_tensor = self.predictor.get_output_tensor(output_name) output_tensor = self.predictor.get_output_handle(output_name)
self.output_tensors.append(output_tensor) self.output_tensors.append(output_tensor)
def read_images(self, paths=[]): def read_images(self, paths=[]):
...@@ -202,7 +207,7 @@ class ChineseTextDetectionDBServer(hub.Module): ...@@ -202,7 +207,7 @@ class ChineseTextDetectionDBServer(hub.Module):
im = im.copy() im = im.copy()
starttime = time.time() starttime = time.time()
self.input_tensor.copy_from_cpu(im) self.input_tensor.copy_from_cpu(im)
self.predictor.zero_copy_run() self.predictor.run()
data_out = self.output_tensors[0].copy_to_cpu() data_out = self.output_tensors[0].copy_to_cpu()
dt_boxes_list = postprocessor(data_out, [ratio_list]) dt_boxes_list = postprocessor(data_out, [ratio_list])
boxes = self.filter_tag_det_res(dt_boxes_list[0], original_image.shape) boxes = self.filter_tag_det_res(dt_boxes_list[0], original_image.shape)
...@@ -229,25 +234,23 @@ class ChineseTextDetectionDBServer(hub.Module): ...@@ -229,25 +234,23 @@ class ChineseTextDetectionDBServer(hub.Module):
if combined: if combined:
model_filename = "__model__" if not model_filename else model_filename model_filename = "__model__" if not model_filename else model_filename
params_filename = "__params__" if not params_filename else params_filename params_filename = "__params__" if not params_filename else params_filename
place = fluid.CPUPlace() place = paddle.CPUPlace()
exe = fluid.Executor(place) exe = paddle.static.Executor(place)
model_file_path = os.path.join(self.pretrained_model_path, 'model') model_file_path = os.path.join(self.pretrained_model_path, 'model')
params_file_path = os.path.join(self.pretrained_model_path, 'params') params_file_path = os.path.join(self.pretrained_model_path, 'params')
program, feeded_var_names, target_vars = fluid.io.load_inference_model( program, feeded_var_names, target_vars = paddle.static.load_inference_model(dirname=self.pretrained_model_path,
dirname=self.pretrained_model_path, model_filename=model_file_path,
model_filename=model_file_path, params_filename=params_file_path,
params_filename=params_file_path, executor=exe)
executor=exe)
paddle.static.save_inference_model(dirname=dirname,
fluid.io.save_inference_model( main_program=program,
dirname=dirname, executor=exe,
main_program=program, feeded_var_names=feeded_var_names,
executor=exe, target_vars=target_vars,
feeded_var_names=feeded_var_names, model_filename=model_filename,
target_vars=target_vars, params_filename=params_filename)
model_filename=model_filename,
params_filename=params_filename)
@serving @serving
def serving_method(self, images, **kwargs): def serving_method(self, images, **kwargs):
...@@ -263,11 +266,10 @@ class ChineseTextDetectionDBServer(hub.Module): ...@@ -263,11 +266,10 @@ class ChineseTextDetectionDBServer(hub.Module):
""" """
Run as a command Run as a command
""" """
self.parser = argparse.ArgumentParser( self.parser = argparse.ArgumentParser(description="Run the %s module." % self.name,
description="Run the %s module." % self.name, prog='hub run %s' % self.name,
prog='hub run %s' % self.name, usage='%(prog)s',
usage='%(prog)s', add_help=True)
add_help=True)
self.arg_input_group = self.parser.add_argument_group(title="Input options", description="Input data. Required") 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( self.arg_config_group = self.parser.add_argument_group(
...@@ -277,20 +279,28 @@ class ChineseTextDetectionDBServer(hub.Module): ...@@ -277,20 +279,28 @@ class ChineseTextDetectionDBServer(hub.Module):
self.add_module_input_arg() self.add_module_input_arg()
args = self.parser.parse_args(argvs) args = self.parser.parse_args(argvs)
results = self.detect_text( results = self.detect_text(paths=[args.input_path],
paths=[args.input_path], use_gpu=args.use_gpu, output_dir=args.output_dir, visualization=args.visualization) use_gpu=args.use_gpu,
output_dir=args.output_dir,
visualization=args.visualization)
return results return results
def add_module_config_arg(self): def add_module_config_arg(self):
""" """
Add the command config options Add the command config options
""" """
self.arg_config_group.add_argument( self.arg_config_group.add_argument('--use_gpu',
'--use_gpu', type=ast.literal_eval, default=False, help="whether use GPU or not") type=ast.literal_eval,
self.arg_config_group.add_argument( default=False,
'--output_dir', type=str, default='detection_result', help="The directory to save output images.") help="whether use GPU or not")
self.arg_config_group.add_argument( self.arg_config_group.add_argument('--output_dir',
'--visualization', type=ast.literal_eval, default=False, help="whether to save output as images.") type=str,
default='detection_result',
help="The directory to save output images.")
self.arg_config_group.add_argument('--visualization',
type=ast.literal_eval,
default=False,
help="whether to save output as images.")
def add_module_input_arg(self): def add_module_input_arg(self):
""" """
......
...@@ -25,9 +25,9 @@ ...@@ -25,9 +25,9 @@
- ### 1、环境依赖 - ### 1、环境依赖
- paddlepaddle >= 2.2.0 - paddlepaddle >= 2.0.0
- paddlehub >= 2.2.0 | [如何安装PaddleHub](../../../../docs/docs_ch/get_start/installation.rst) - paddlehub >= 2.0.0 | [如何安装PaddleHub](../../../../docs/docs_ch/get_start/installation.rst)
- ### 2、安装 - ### 2、安装
......
# simnet_bow # simnet_bow
|模型名称|simnet_bow| |模型名称|simnet_bow|
| :--- | :---: | | :--- | :---: |
|类别|文本-语义匹配| |类别|文本-语义匹配|
|网络|BOW| |网络|BOW|
|数据集|百度自建数据集| |数据集|百度自建数据集|
...@@ -59,7 +59,7 @@ ...@@ -59,7 +59,7 @@
# [{'text_1': '这道题太难了', 'text_2': '这道题是上一年的考题', 'similarity': 0.689}, {'text_1': '这道题太难了', 'text_2': '这道题不简单', 'similarity': 0.855}, {'text_1': '这道题太难了', 'text_2': '这道题很有意思', 'similarity': 0.8166}] # [{'text_1': '这道题太难了', 'text_2': '这道题是上一年的考题', 'similarity': 0.689}, {'text_1': '这道题太难了', 'text_2': '这道题不简单', 'similarity': 0.855}, {'text_1': '这道题太难了', 'text_2': '这道题很有意思', 'similarity': 0.8166}]
``` ```
- ### 3、 API - ### 3、 API
- ```python - ```python
...@@ -153,3 +153,11 @@ ...@@ -153,3 +153,11 @@
* 1.2.0 * 1.2.0
模型升级,支持用于文本分类,文本匹配等各种任务迁移学习 模型升级,支持用于文本分类,文本匹配等各种任务迁移学习
* 1.2.1
移除 fluid api
- ```shell
$ hub install simnet_bow==1.2.1
```
...@@ -8,35 +8,39 @@ import ast ...@@ -8,35 +8,39 @@ import ast
import json import json
import math import math
import os import os
import six
import numpy as np import numpy as np
import paddle.fluid as fluid import six
from paddle.fluid.core import PaddleTensor, AnalysisConfig, create_paddle_predictor from paddle.inference import Config
from paddle.inference import create_predictor
from simnet_bow.processor import load_vocab
from simnet_bow.processor import postprocess
from simnet_bow.processor import preprocess
import paddlehub as hub import paddlehub as hub
from paddlehub.common.paddle_helper import add_vars_prefix, get_variable_info from paddlehub.common.paddle_helper import add_vars_prefix
from paddlehub.common.paddle_helper import get_variable_info
from paddlehub.common.utils import sys_stdin_encoding from paddlehub.common.utils import sys_stdin_encoding
from paddlehub.io.parser import txt_parser from paddlehub.io.parser import txt_parser
from paddlehub.module.module import serving
from paddlehub.module.module import moduleinfo from paddlehub.module.module import moduleinfo
from paddlehub.module.module import runnable from paddlehub.module.module import runnable
from paddlehub.module.module import serving
from simnet_bow.processor import load_vocab, preprocess, postprocess
class DataFormatError(Exception): class DataFormatError(Exception):
def __init__(self, *args): def __init__(self, *args):
self.args = args self.args = args
@moduleinfo( @moduleinfo(name="simnet_bow",
name="simnet_bow", version="1.2.1",
version="1.2.0", summary="Baidu's open-source similarity network model based on bow_pairwise.",
summary="Baidu's open-source similarity network model based on bow_pairwise.", author="baidu-nlp",
author="baidu-nlp", author_email="",
author_email="", type="nlp/sentiment_analysis")
type="nlp/sentiment_analysis")
class SimnetBow(hub.Module): class SimnetBow(hub.Module):
def _initialize(self): def _initialize(self):
""" """
initialize with the necessary elements initialize with the necessary elements
...@@ -62,11 +66,11 @@ class SimnetBow(hub.Module): ...@@ -62,11 +66,11 @@ class SimnetBow(hub.Module):
""" """
predictor config setting predictor config setting
""" """
cpu_config = AnalysisConfig(self.pretrained_model_path) cpu_config = Config(self.pretrained_model_path)
cpu_config.disable_glog_info() cpu_config.disable_glog_info()
cpu_config.disable_gpu() cpu_config.disable_gpu()
cpu_config.switch_ir_optim(False) cpu_config.switch_ir_optim(False)
self.cpu_predictor = create_paddle_predictor(cpu_config) self.cpu_predictor = create_predictor(cpu_config)
try: try:
_places = os.environ["CUDA_VISIBLE_DEVICES"] _places = os.environ["CUDA_VISIBLE_DEVICES"]
...@@ -75,125 +79,18 @@ class SimnetBow(hub.Module): ...@@ -75,125 +79,18 @@ class SimnetBow(hub.Module):
except: except:
use_gpu = False use_gpu = False
if use_gpu: if use_gpu:
gpu_config = AnalysisConfig(self.pretrained_model_path) gpu_config = Config(self.pretrained_model_path)
gpu_config.disable_glog_info() gpu_config.disable_glog_info()
gpu_config.enable_use_gpu(memory_pool_init_size_mb=500, device_id=0) gpu_config.enable_use_gpu(memory_pool_init_size_mb=500, device_id=0)
self.gpu_predictor = create_paddle_predictor(gpu_config) self.gpu_predictor = create_predictor(gpu_config)
def context(self, trainable=False, max_seq_len=128, num_slots=1):
"""
Get the input ,output and program of the pretrained simnet_bow
Args:
trainable(bool): whether fine-tune the pretrained parameters of simnet_bow or not。
max_seq_len (int): It will limit the total sequence returned so that it has a maximum length.
num_slots(int): It's number of data inputted to the model, selectted as following options:
- 1(default): There's only one data to be feeded in the model, e.g. the module is used for sentence classification task.
- 2: There are two data to be feeded in the model, e.g. the module is used for text matching task (point-wise).
- 3: There are three data to be feeded in the model, e.g. the module is used for text matching task (pair-wise).
Returns: def _texts_process(self, texts):
inputs(dict): the input variables of simnet_bow (words)
outputs(dict): the output variables of input words (word embeddings) and sequence lenght of the first input_text
main_program(Program): the main_program of simnet_bow with pretrained prameters
"""
assert num_slots >= 1 and num_slots <= 3, "num_slots must be 1, 2, or 3, but the input is %d" % num_slots
main_program = fluid.Program()
startup_program = fluid.Program()
with fluid.program_guard(main_program, startup_program):
text_1 = fluid.layers.data(name="text", shape=[-1, max_seq_len, 1], dtype="int64", lod_level=0)
seq_len = fluid.layers.data(name="seq_len", shape=[1], dtype='int64', lod_level=0)
seq_len_used = fluid.layers.squeeze(seq_len, axes=[1])
# Add embedding layer.
w_param_attrs = fluid.ParamAttr(
name="emb", initializer=fluid.initializer.TruncatedNormal(scale=0.02), trainable=trainable)
dict_dim = 500002
emb_1 = fluid.layers.embedding(
input=text_1,
size=[dict_dim, 128],
is_sparse=True,
padding_idx=dict_dim - 1,
dtype='float32',
param_attr=w_param_attrs)
emb_1_name = emb_1.name
data_list = [text_1]
emb_name_list = [emb_1_name]
if num_slots > 1:
text_2 = fluid.data(name='text_2', shape=[-1, max_seq_len], dtype='int64', lod_level=0)
emb_2 = fluid.embedding(
input=text_2,
size=[dict_dim, 128],
is_sparse=True,
padding_idx=dict_dim - 1,
dtype='float32',
param_attr=w_param_attrs)
emb_2_name = emb_2.name
data_list.append(text_2)
emb_name_list.append(emb_2_name)
if num_slots > 2:
text_3 = fluid.data(name='text_3', shape=[-1, max_seq_len], dtype='int64', lod_level=0)
emb_3 = fluid.embedding(
input=text_3,
size=[dict_dim, 128],
is_sparse=True,
padding_idx=dict_dim - 1,
dtype='float32',
param_attr=w_param_attrs)
emb_3_name = emb_3.name
data_list.append(text_3)
emb_name_list.append(emb_3_name)
variable_names = filter(lambda v: v not in ['text', 'text_2', 'text_3', "seq_len"],
list(main_program.global_block().vars.keys()))
prefix_name = "@HUB_{}@".format(self.name)
add_vars_prefix(program=main_program, prefix=prefix_name, vars=variable_names)
for param in main_program.global_block().iter_parameters():
param.trainable = trainable
place = fluid.CPUPlace()
exe = fluid.Executor(place)
# Load the senta_lstm pretrained model.
def if_exist(var):
return os.path.exists(os.path.join(self.pretrained_model_path, var.name))
fluid.io.load_vars(exe, self.pretrained_model_path, predicate=if_exist)
inputs = {'seq_len': seq_len}
outputs = {}
for index, data in enumerate(data_list):
if index == 0:
inputs['text'] = data
outputs['emb'] = main_program.global_block().vars[prefix_name + emb_name_list[0]]
else:
inputs['text_%s' % (index + 1)] = data
outputs['emb_%s' % (index + 1)] = main_program.global_block().vars[prefix_name +
emb_name_list[index]]
return inputs, outputs, main_program
def texts2tensor(self, texts):
"""
Tranform the texts(dict) to PaddleTensor
Args:
texts(list): texts
Returns:
tensor(PaddleTensor): tensor with texts data
"""
lod = [0] lod = [0]
data = [] data = []
for i, text in enumerate(texts): for i, text in enumerate(texts):
data += text['processed'] data += text['processed']
lod.append(len(text['processed']) + lod[i]) lod.append(len(text['processed']) + lod[i])
tensor = PaddleTensor(np.array(data).astype('int64')) return np.array(data).astype('int64'), [lod], [lod[-1], 1]
tensor.name = "words"
tensor.lod = [lod]
tensor.shape = [lod[-1], 1]
return tensor
def to_unicode(self, texts): def to_unicode(self, texts):
""" """
...@@ -282,14 +179,28 @@ class SimnetBow(hub.Module): ...@@ -282,14 +179,28 @@ class SimnetBow(hub.Module):
start_idx = start_idx + batch_size start_idx = start_idx + batch_size
processed_results = preprocess(self.word_seg_module, self.vocab, batch_data, use_gpu, batch_size) processed_results = preprocess(self.word_seg_module, self.vocab, batch_data, use_gpu, batch_size)
tensor_words_1 = self.texts2tensor(processed_results["text_1"]) data_1, lod_1, shape_1 = self._texts_process(processed_results["text_1"])
tensor_words_2 = self.texts2tensor(processed_results["text_2"]) data_2, lod_2, shape_2 = self._texts_process(processed_results["text_2"])
if use_gpu: predictor = self.gpu_predictor if use_gpu else self.cpu_predictor
batch_out = self.gpu_predictor.run([tensor_words_1, tensor_words_2])
else: input_names = predictor.get_input_names()
batch_out = self.cpu_predictor.run([tensor_words_1, tensor_words_2]) input_handle = predictor.get_input_handle(input_names[0])
batch_result = postprocess(batch_out[1], processed_results) input_handle.copy_from_cpu(data_1)
input_handle.set_lod(lod_1)
input_handle.reshape(shape_1)
input_handle = predictor.get_input_handle(input_names[1])
input_handle.copy_from_cpu(data_2)
input_handle.set_lod(lod_2)
input_handle.reshape(shape_2)
predictor.run()
output_names = predictor.get_output_names()
output_handle = predictor.get_output_handle(output_names[1])
batch_out = output_handle.copy_to_cpu()
batch_result = postprocess(batch_out, processed_results)
results += batch_result results += batch_result
return results return results
...@@ -298,8 +209,10 @@ class SimnetBow(hub.Module): ...@@ -298,8 +209,10 @@ class SimnetBow(hub.Module):
""" """
Run as a command Run as a command
""" """
self.parser = argparse.ArgumentParser( self.parser = argparse.ArgumentParser(description="Run the simnet_bow module.",
description="Run the simnet_bow module.", prog='hub run simnet_bow', usage='%(prog)s', add_help=True) prog='hub run simnet_bow',
usage='%(prog)s',
add_help=True)
self.arg_input_group = self.parser.add_argument_group(title="Input options", description="Input data. Required") 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( self.arg_config_group = self.parser.add_argument_group(
...@@ -324,8 +237,10 @@ class SimnetBow(hub.Module): ...@@ -324,8 +237,10 @@ class SimnetBow(hub.Module):
""" """
Add the command config options Add the command config options
""" """
self.arg_config_group.add_argument( self.arg_config_group.add_argument('--use_gpu',
'--use_gpu', type=ast.literal_eval, default=False, help="whether use GPU for prediction") type=ast.literal_eval,
default=False,
help="whether use GPU for prediction")
self.arg_config_group.add_argument('--batch_size', type=int, default=1, help="batch size for prediction") self.arg_config_group.add_argument('--batch_size', type=int, default=1, help="batch size for prediction")
......
...@@ -46,12 +46,11 @@ def preprocess(lac, word_dict, data_dict, use_gpu=False, batch_size=1): ...@@ -46,12 +46,11 @@ def preprocess(lac, word_dict, data_dict, use_gpu=False, batch_size=1):
return result return result
def postprocess(predict_out, data_info): def postprocess(pred, data_info):
""" """
Convert model's output tensor to pornography label Convert model's output tensor to pornography label
""" """
result = [] result = []
pred = predict_out.as_ndarray()
for index in range(len(data_info[text_a_key])): for index in range(len(data_info[text_a_key])):
result_i = {} result_i = {}
result_i[text_a_key] = data_info[text_a_key][index]['origin'] result_i[text_a_key] = data_info[text_a_key][index]['origin']
......
# jieba_paddle # jieba_paddle
|模型名称|jieba_paddle| |模型名称|jieba_paddle|
| :--- | :---: | | :--- | :---: |
|类别|文本-词法分析| |类别|文本-词法分析|
|网络|BiGRU+CRF| |网络|BiGRU+CRF|
|数据集|百度自建数据集| |数据集|百度自建数据集|
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
- ### 1、环境依赖 - ### 1、环境依赖
- paddlepaddle >= 1.8.0 - paddlepaddle >= 1.8.0
- paddlehub >= 1.8.0 | [如何安装PaddleHub](../../../../docs/docs_ch/get_start/installation.rst) - paddlehub >= 1.8.0 | [如何安装PaddleHub](../../../../docs/docs_ch/get_start/installation.rst)
- ### 2、安装 - ### 2、安装
...@@ -59,10 +59,10 @@ ...@@ -59,10 +59,10 @@
import paddlehub as hub import paddlehub as hub
jieba = hub.Module(name="jieba_paddle") jieba = hub.Module(name="jieba_paddle")
results = jieba.cut("今天是个好日子", cut_all=False, HMM=True) results = jieba.cut("今天是个好日子", cut_all=False, HMM=True)
print(results) print(results)
# ['今天', '是', '个', '好日子'] # ['今天', '是', '个', '好日子']
``` ```
...@@ -89,7 +89,7 @@ ...@@ -89,7 +89,7 @@
- ```python - ```python
def cut_for_search(sentence, HMM=True) def cut_for_search(sentence, HMM=True)
``` ```
- jieba的搜索引擎模式切词,该方法适合用于搜索引擎构建倒排索引的分词,粒度比较细 - jieba的搜索引擎模式切词,该方法适合用于搜索引擎构建倒排索引的分词,粒度比较细
- **参数** - **参数**
...@@ -212,7 +212,12 @@ ...@@ -212,7 +212,12 @@
* 1.0.0 * 1.0.0
初始发布 初始发布
* 1.0.1
移除 fluid api
- ```shell - ```shell
$ hub install jieba_paddle==1.0.0 $ hub install jieba_paddle==1.0.1
``` ```
...@@ -6,21 +6,22 @@ from __future__ import print_function ...@@ -6,21 +6,22 @@ from __future__ import print_function
import logging import logging
import os import os
import paddle.fluid as fluid
import paddlehub as hub import paddlehub as hub
from paddlehub.common.logger import logger from paddlehub.common.logger import logger
from paddlehub.module.module import moduleinfo, serving from paddlehub.module.module import moduleinfo
from paddlehub.module.module import serving
@moduleinfo( @moduleinfo(
name="jieba_paddle", name="jieba_paddle",
version="1.0.0", version="1.0.1",
summary= summary=
"jieba_paddle is a chineses tokenizer using BiGRU base on the PaddlePaddle deeplearning framework. More information please refer to https://github.com/fxsjy/jieba.", "jieba_paddle is a chineses tokenizer using BiGRU base on the PaddlePaddle deeplearning framework. More information please refer to https://github.com/fxsjy/jieba.",
author="baidu-paddle", author="baidu-paddle",
author_email="paddle-dev@gmail.com", author_email="paddle-dev@gmail.com",
type="nlp/lexical_analysis") type="nlp/lexical_analysis")
class JiebaPaddle(hub.Module): class JiebaPaddle(hub.Module):
def _initialize(self): def _initialize(self):
pass pass
...@@ -119,8 +120,11 @@ class JiebaPaddle(hub.Module): ...@@ -119,8 +120,11 @@ class JiebaPaddle(hub.Module):
import jieba import jieba
import jieba.analyse import jieba.analyse
jieba.setLogLevel(logging.ERROR) jieba.setLogLevel(logging.ERROR)
res = jieba.analyse.extract_tags( res = jieba.analyse.extract_tags(sentence,
sentence, topK=topK, withWeight=withWeight, allowPOS=allowPOS, withFlag=withFlag) topK=topK,
withWeight=withWeight,
allowPOS=allowPOS,
withFlag=withFlag)
return res return res
def textrank(self, sentence, topK=20, withWeight=False, allowPOS=('ns', 'n', 'vn', 'v'), withFlag=False): def textrank(self, sentence, topK=20, withWeight=False, allowPOS=('ns', 'n', 'vn', 'v'), withFlag=False):
...@@ -143,24 +147,3 @@ class JiebaPaddle(hub.Module): ...@@ -143,24 +147,3 @@ class JiebaPaddle(hub.Module):
jieba.setLogLevel(logging.ERROR) jieba.setLogLevel(logging.ERROR)
res = jieba.analyse.textrank(sentence, topK=topK, withWeight=withWeight, allowPOS=allowPOS, withFlag=withFlag) res = jieba.analyse.textrank(sentence, topK=topK, withWeight=withWeight, allowPOS=allowPOS, withFlag=withFlag)
return res return res
if __name__ == "__main__":
jb_pd = JiebaPaddle()
res = jb_pd.cut(
sentence="我来到北京清华大学",
use_paddle=True,
)
print(res)
res = jb_pd.cut(sentence="我来到北京清华大学", use_paddle=False, cut_all=True)
print(res)
res = jb_pd.cut(sentence="我来到北京清华大学", use_paddle=False, cut_all=False)
print(res)
res = jb_pd.cut_for_search(sentence="我来到北京清华大学")
print(res)
res = jb_pd.extract_tags(sentence="我来到北京清华大学")
print(res)
res = jb_pd.extract_tags(sentence="我来到北京清华大学", withWeight=True)
print(res)
res = jb_pd.textrank(sentence="我来到北京清华大学", withWeight=True)
print(res)
# lac # lac
|模型名称|lac| |模型名称|lac|
| :--- | :---: | | :--- | :---: |
|类别|文本-词法分析| |类别|文本-词法分析|
|网络|BiGRU+CRF| |网络|BiGRU+CRF|
|数据集|百度自建数据集| |数据集|百度自建数据集|
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
- ### 模型介绍 - ### 模型介绍
- Lexical Analysis of Chinese,简称 LAC,是一个联合的词法分析模型,能整体性地完成中文分词、词性标注、专名识别任务。在百度自建数据集上评测,LAC效果:Precision=88.0%,Recall=88.7%,F1-Score=88.4%。该PaddleHub Module支持预测。 - Lexical Analysis of Chinese,简称 LAC,是一个联合的词法分析模型,能整体性地完成中文分词、词性标注、专名识别任务。在百度自建数据集上评测,LAC效果:Precision=88.0%,Recall=88.7%,F1-Score=88.4%。该PaddleHub Module支持预测。
<p align="center"> <p align="center">
<img src="https://user-images.githubusercontent.com/76040149/130606395-60691079-d33f-4d74-a980-b4d9e3bc663e.png" height = "300" hspace='10'/> <br /> <img src="https://user-images.githubusercontent.com/76040149/130606395-60691079-d33f-4d74-a980-b4d9e3bc663e.png" height = "300" hspace='10'/> <br />
</p> </p>
...@@ -32,15 +32,15 @@ ...@@ -32,15 +32,15 @@
- ### 1、环境依赖 - ### 1、环境依赖
- paddlepaddle >= 1.6.2 - paddlepaddle >= 1.6.2
- paddlehub >= 1.6.0 | [如何安装PaddleHub](../../../../docs/docs_ch/get_start/installation.rst) - paddlehub >= 1.6.0 | [如何安装PaddleHub](../../../../docs/docs_ch/get_start/installation.rst)
- 若使用词典干预功能,额外依赖第三方库 pyahocorasick - 若使用词典干预功能,额外依赖第三方库 pyahocorasick
- ```shell - ```shell
$ pip install pyahocorasick $ pip install pyahocorasick
``` ```
- ### 2、安装 - ### 2、安装
- ```shell - ```shell
...@@ -63,23 +63,23 @@ ...@@ -63,23 +63,23 @@
- ```shell - ```shell
$ hub run lac --input_file test.txt --user_dict user.dict $ hub run lac --input_file test.txt --user_dict user.dict
``` ```
- test.txt 存放待分词文本, 如: - test.txt 存放待分词文本, 如:
- ```shell - ```shell
今天是个好日子 今天是个好日子
今天天气晴朗 今天天气晴朗
``` ```
- user.dict 为用户自定义词典,可以不指定,当指定自定义词典时,可以干预默认分词结果。如: - user.dict 为用户自定义词典,可以不指定,当指定自定义词典时,可以干预默认分词结果。如:
- ```shell - ```shell
春天/SEASON 春天/SEASON
花/n 开/v 花/n 开/v
秋天的风 秋天的风
落 阳 落 阳
``` ```
- 词典文件每行表示一个定制化的item,由一个单词或多个连续的单词组成,每个单词后使用'/'表示标签,如果没有'/'标签则会使用模型默认的标签。每个item单词数越多,干预效果会越精准。 - 词典文件每行表示一个定制化的item,由一个单词或多个连续的单词组成,每个单词后使用'/'表示标签,如果没有'/'标签则会使用模型默认的标签。每个item单词数越多,干预效果会越精准。
- Note:该PaddleHub Module使用词典干预功能时,依赖于第三方库pyahocorasick,请自行安装 - Note:该PaddleHub Module使用词典干预功能时,依赖于第三方库pyahocorasick,请自行安装
- 通过命令行方式实现文字识别模型的调用,更多请见 [PaddleHub命令行指令](../../../../docs/docs_ch/tutorial/cmd_usage.rst) - 通过命令行方式实现文字识别模型的调用,更多请见 [PaddleHub命令行指令](../../../../docs/docs_ch/tutorial/cmd_usage.rst)
- ### 2、预测代码示例 - ### 2、预测代码示例
...@@ -95,7 +95,7 @@ ...@@ -95,7 +95,7 @@
for result in results: for result in results:
print(result['word']) print(result['word'])
print(result['tag']) print(result['tag'])
# ['今天', '是', '个', '好日子'] # ['今天', '是', '个', '好日子']
# ['TIME', 'v', 'q', 'n'] # ['TIME', 'v', 'q', 'n']
# ['天气预报', '说', '今天', '要', '下雨'] # ['天气预报', '说', '今天', '要', '下雨']
...@@ -103,9 +103,9 @@ ...@@ -103,9 +103,9 @@
# ['下', '一班', '地铁', '马上', '就要', '到', '了'] # ['下', '一班', '地铁', '马上', '就要', '到', '了']
# ['f', 'm', 'n', 'd', 'v', 'v', 'xc'] # ['f', 'm', 'n', 'd', 'v', 'v', 'xc']
``` ```
- ### 3、API - ### 3、API
- ```python - ```python
...@@ -135,7 +135,7 @@ ...@@ -135,7 +135,7 @@
- ```python - ```python
def lexical_analysis(texts=[], data={}, use_gpu=False, batch_size=1, user_dict=None, return_tag=True) def lexical_analysis(texts=[], data={}, use_gpu=False, batch_size=1, user_dict=None, return_tag=True)
``` ```
- **该接口将会在未来版本被废弃,如有需要,请使用cut接口预测** - **该接口将会在未来版本被废弃,如有需要,请使用cut接口预测**
- lac预测接口,预测输入句子的分词结果 - lac预测接口,预测输入句子的分词结果
...@@ -282,6 +282,11 @@ ...@@ -282,6 +282,11 @@
* 2.2.0 * 2.2.0
升级自定义词典功能,支持增加不属于lac默认提供的词性 升级自定义词典功能,支持增加不属于lac默认提供的词性
* 2.2.1
移除 fluid api
- ```shell - ```shell
$ hub install lac==2.2.0 $ hub install lac==2.2.1
``` ```
...@@ -9,11 +9,14 @@ import io ...@@ -9,11 +9,14 @@ import io
import json import json
import math import math
import os import os
import six
import numpy as np import numpy as np
import paddle.fluid as fluid import paddle
import six
from lac.custom import Customization
from lac.processor import load_kv_dict
from lac.processor import parse_result
from lac.processor import word_to_ids
from paddle.inference import Config from paddle.inference import Config
from paddle.inference import create_predictor from paddle.inference import create_predictor
...@@ -22,27 +25,27 @@ from paddlehub.common.logger import logger ...@@ -22,27 +25,27 @@ from paddlehub.common.logger import logger
from paddlehub.common.paddle_helper import add_vars_prefix from paddlehub.common.paddle_helper import add_vars_prefix
from paddlehub.common.utils import sys_stdin_encoding from paddlehub.common.utils import sys_stdin_encoding
from paddlehub.io.parser import txt_parser from paddlehub.io.parser import txt_parser
from paddlehub.module.module import moduleinfo, runnable, serving from paddlehub.module.module import moduleinfo
from paddlehub.module.module import runnable
from lac.network import lex_net from paddlehub.module.module import serving
from lac.processor import load_kv_dict, word_to_ids, parse_result
from lac.custom import Customization
class DataFormatError(Exception): class DataFormatError(Exception):
def __init__(self, *args): def __init__(self, *args):
self.args = args self.args = args
@moduleinfo( @moduleinfo(
name="lac", name="lac",
version="2.2.0", version="2.2.1",
summary= summary=
"Baidu's open-source lexical analysis tool for Chinese, including word segmentation, part-of-speech tagging & named entity recognition", "Baidu's open-source lexical analysis tool for Chinese, including word segmentation, part-of-speech tagging & named entity recognition",
author="baidu-nlp", author="baidu-nlp",
author_email="paddle-dev@baidu.com", author_email="paddle-dev@baidu.com",
type="nlp/lexical_analysis") type="nlp/lexical_analysis")
class LAC(hub.Module): class LAC(hub.Module):
def _initialize(self, user_dict=None): def _initialize(self, user_dict=None):
""" """
initialize with the necessary elements initialize with the necessary elements
...@@ -65,129 +68,27 @@ class LAC(hub.Module): ...@@ -65,129 +68,27 @@ class LAC(hub.Module):
self._set_config() self._set_config()
def _get_device_id(self, places):
try:
places = os.environ[places]
id = int(places)
except:
id = -1
return id
def _set_config(self): def _set_config(self):
""" """
predictor config setting predictor config setting
""" """
# create default cpu predictor
cpu_config = Config(self.pretrained_model_path) cpu_config = Config(self.pretrained_model_path)
cpu_config.disable_glog_info() cpu_config.disable_glog_info()
cpu_config.disable_gpu() cpu_config.disable_gpu()
self.cpu_predictor = create_predictor(cpu_config) self.cpu_predictor = create_predictor(cpu_config)
# create predictors using various types of devices try:
_places = os.environ["CUDA_VISIBLE_DEVICES"]
# npu int(_places[0])
npu_id = self._get_device_id("FLAGS_selected_npus") use_gpu = True
if npu_id != -1: except:
# use npu use_gpu = False
npu_config = Config(self.pretrained_model_path) if use_gpu:
npu_config.disable_glog_info()
npu_config.enable_npu(device_id=npu_id)
self.npu_predictor = create_predictor(npu_config)
# gpu
gpu_id = self._get_device_id("CUDA_VISIBLE_DEVICES")
if gpu_id != -1:
# use gpu
gpu_config = Config(self.pretrained_model_path) gpu_config = Config(self.pretrained_model_path)
gpu_config.disable_glog_info() gpu_config.disable_glog_info()
gpu_config.enable_use_gpu(memory_pool_init_size_mb=500, device_id=gpu_id) gpu_config.enable_use_gpu(memory_pool_init_size_mb=500, device_id=0)
self.gpu_predictor = create_predictor(gpu_config) self.gpu_predictor = create_predictor(gpu_config)
# xpu
xpu_id = self._get_device_id("XPU_VISIBLE_DEVICES")
if xpu_id != -1:
# use xpu
xpu_config = Config(self.pretrained_model_path)
xpu_config.disable_glog_info()
xpu_config.enable_xpu(100)
self.xpu_predictor = create_predictor(xpu_config)
def _internal_predict(self, predictor, texts):
"""
Tranform the texts(list) to Tensor and then do "real predict"
Args:
texts(list): texts
Returns:
result(PaddleInferTensor): predict output
"""
# texts to data and lod
lod = [0]
data = []
for i, text in enumerate(texts):
text_inds = word_to_ids(text, self.word2id_dict, self.word_replace_dict, oov_id=self.oov_id)
data += text_inds
lod.append(len(text_inds) + lod[i])
# get predictor tensor
input_names = predictor.get_input_names()
input_tensor = predictor.get_input_handle(input_names[0])
# set data, shape and lod
input_tensor.copy_from_cpu(np.array(data).astype('int64'))
input_tensor.reshape([lod[-1], 1])
input_tensor.set_lod([lod])
# real predict
predictor.run()
output_names = predictor.get_output_names()
output_handle = predictor.get_output_handle(output_names[0])
return output_handle
def context(self, trainable=False):
"""
Get the input ,output and program of the pretrained lac
Args:
trainable(bool): whether fine-tune the pretrained parameters of lac or not
Returns:
inputs(dict): the input variables of lac (words)
outputs(dict): the output variables of lac (the word segmentation results)
main_program(Program): the main_program of lac with pretrained prameters
"""
main_program = fluid.Program()
startup_program = fluid.Program()
with fluid.program_guard(main_program, startup_program):
with fluid.unique_name.guard():
crf_decode, word, fc = lex_net(self.word_dict_len, self.label_dict_len)
word_name = word.name
pred_name = crf_decode.name
fc_name = fc.name
prefix_name = "@HUB_{}@".format(self.name)
add_vars_prefix(program=main_program, prefix=prefix_name)
for param in main_program.global_block().iter_parameters():
param.trainable = trainable
place = fluid.CPUPlace()
exe = fluid.Executor(place)
# load the lac pretrained model
def if_exist(var):
return os.path.exists(os.path.join(self.pretrained_model_path, var.name))
fluid.io.load_vars(exe, self.pretrained_model_path, predicate=if_exist)
inputs = {"words": main_program.global_block().vars[prefix_name + word_name]}
outputs = {
"predicted": main_program.global_block().vars[prefix_name + pred_name],
"sentence_feature": main_program.global_block().vars[prefix_name + fc_name]
}
return inputs, outputs, main_program
def set_user_dict(self, dict_path, sep=None): def set_user_dict(self, dict_path, sep=None):
""" """
Set the costomized dictionary if you wanna exploit the self-defined dictionary Set the costomized dictionary if you wanna exploit the self-defined dictionary
...@@ -230,6 +131,22 @@ class LAC(hub.Module): ...@@ -230,6 +131,22 @@ class LAC(hub.Module):
texts = unicode_texts texts = unicode_texts
return texts return texts
def preprocess(self, texts):
"""
Tranform the texts(list) to PaddleTensor
Args:
texts(list): texts
Returns:
np.array, list, list
"""
lod = [0]
data = []
for i, text in enumerate(texts):
text_inds = word_to_ids(text, self.word2id_dict, self.word_replace_dict, oov_id=self.oov_id)
data += text_inds
lod.append(len(text_inds) + lod[i])
return np.array(data).astype('int64'), [lod], [lod[-1], 1]
def _get_index(self, data_list, item=""): def _get_index(self, data_list, item=""):
""" """
find all indexes of item in data_list find all indexes of item in data_list
...@@ -241,7 +158,7 @@ class LAC(hub.Module): ...@@ -241,7 +158,7 @@ class LAC(hub.Module):
return res return res
@serving @serving
def cut(self, text, use_gpu=False, batch_size=1, return_tag=True, use_device=None): def cut(self, text, use_gpu=False, batch_size=1, return_tag=True):
""" """
The main function that segments an entire text that contains The main function that segments an entire text that contains
Chinese characters into separated words. Chinese characters into separated words.
...@@ -250,32 +167,20 @@ class LAC(hub.Module): ...@@ -250,32 +167,20 @@ class LAC(hub.Module):
use_gpu(bool): whether use gpu to predict or not use_gpu(bool): whether use gpu to predict or not
batch_size(int): the program deals once with one batch batch_size(int): the program deals once with one batch
return_tag: Whether to get tag or not. return_tag: Whether to get tag or not.
use_device (str): use cpu, gpu, xpu or npu, overwrites use_gpu flag.
Returns: Returns:
results(dict or list): The word segmentation result of the input text, whose key is 'word', if text is a list. results(dict or list): The word segmentation result of the input text, whose key is 'word', if text is a list.
If text is a str, the word segmentation result (list) is obtained. If text is a str, the word segmentation result (list) is obtained.
""" """
if use_gpu:
# real predictor to use try:
if use_device is not None: _places = os.environ["CUDA_VISIBLE_DEVICES"]
if use_device == "cpu": int(_places[0])
predictor = self.cpu_predictor except:
elif use_device == "xpu": raise RuntimeError(
predictor = self.xpu_predictor "Environment Variable CUDA_VISIBLE_DEVICES is not set correctly. If you wanna use gpu, please set CUDA_VISIBLE_DEVICES as cuda_device_id."
elif use_device == "npu": )
predictor = self.npu_predictor
elif use_device == "gpu":
predictor = self.gpu_predictor
else:
raise Exception("Unsupported device: " + use_device)
else:
# use_device is not set, therefore follow use_gpu
if use_gpu:
predictor = self.gpu_predictor
else:
predictor = self.cpu_predictor
if isinstance(text, list) and len(text) != 0: if isinstance(text, list) and len(text) != 0:
...@@ -295,8 +200,20 @@ class LAC(hub.Module): ...@@ -295,8 +200,20 @@ class LAC(hub.Module):
batch_data = predicted_data[start_idx:] batch_data = predicted_data[start_idx:]
start_idx = start_idx + batch_size start_idx = start_idx + batch_size
batch_out = self._internal_predict(predictor, batch_data) data, lod, shape = self.preprocess(batch_data)
batch_result = parse_result(batch_data, batch_out, self.id2label_dict, interventer=self.custom)
predictor = self.gpu_predictor if use_gpu else self.cpu_predictor
input_names = predictor.get_input_names()
input_handle = predictor.get_input_handle(input_names[0])
input_handle.copy_from_cpu(data)
input_handle.set_lod(lod)
input_handle.reshape(shape)
predictor.run()
output_names = predictor.get_output_names()
output_handle = predictor.get_output_handle(output_names[0])
batch_result = parse_result(batch_data, output_handle, self.id2label_dict, interventer=self.custom)
results += batch_result results += batch_result
for index in empty_str_indexes: for index in empty_str_indexes:
...@@ -309,8 +226,20 @@ class LAC(hub.Module): ...@@ -309,8 +226,20 @@ class LAC(hub.Module):
return results return results
elif isinstance(text, str) and text != "": elif isinstance(text, str) and text != "":
batch_out = self._internal_predict(predictor, [text]) data, lod, shape = self.preprocess([text])
batch_result = parse_result([text], batch_out, self.id2label_dict, interventer=self.custom)
predictor = self.gpu_predictor if use_gpu else self.cpu_predictor
input_names = predictor.get_input_names()
input_handle = predictor.get_input_handle(input_names[0])
input_handle.copy_from_cpu(data)
input_handle.set_lod(lod)
input_handle.reshape(shape)
predictor.run()
output_names = predictor.get_output_names()
output_handle = predictor.get_output_handle(output_names[0])
batch_result = parse_result([text], output_handle, self.id2label_dict, interventer=self.custom)
return batch_result[0]['word'] return batch_result[0]['word']
elif text == "": elif text == "":
...@@ -318,7 +247,7 @@ class LAC(hub.Module): ...@@ -318,7 +247,7 @@ class LAC(hub.Module):
else: else:
raise TypeError("The input data is inconsistent with expectations.") raise TypeError("The input data is inconsistent with expectations.")
def lexical_analysis(self, texts=[], data={}, use_gpu=False, batch_size=1, return_tag=True, use_device=None): def lexical_analysis(self, texts=[], data={}, use_gpu=False, batch_size=1, return_tag=True):
""" """
Get the word segmentation results with the texts as input Get the word segmentation results with the texts as input
...@@ -328,30 +257,19 @@ class LAC(hub.Module): ...@@ -328,30 +257,19 @@ class LAC(hub.Module):
use_gpu(bool): whether use gpu to predict or not use_gpu(bool): whether use gpu to predict or not
batch_size(int): the program deals once with one batch batch_size(int): the program deals once with one batch
return_tag: Whether to get tag or not. return_tag: Whether to get tag or not.
use_device (str): use cpu, gpu, xpu or npu, overwrites use_gpu flag.
Returns: Returns:
results(list): the word segmentation results results(list): the word segmentation results
""" """
# real predictor to use if use_gpu:
if use_device is not None: try:
if use_device == "cpu": _places = os.environ["CUDA_VISIBLE_DEVICES"]
predictor = self.cpu_predictor int(_places[0])
elif use_device == "xpu": except:
predictor = self.xpu_predictor raise RuntimeError(
elif use_device == "npu": "Environment Variable CUDA_VISIBLE_DEVICES is not set correctly. If you wanna use gpu, please set CUDA_VISIBLE_DEVICES as cuda_device_id."
predictor = self.npu_predictor )
elif use_device == "gpu":
predictor = self.gpu_predictor
else:
raise Exception("Unsupported device: " + use_device)
else:
# use_device is not set, therefore follow use_gpu
if use_gpu:
predictor = self.gpu_predictor
else:
predictor = self.cpu_predictor
if texts != [] and isinstance(texts, list) and data == {}: if texts != [] and isinstance(texts, list) and data == {}:
predicted_data = texts predicted_data = texts
...@@ -376,8 +294,20 @@ class LAC(hub.Module): ...@@ -376,8 +294,20 @@ class LAC(hub.Module):
batch_data = predicted_data[start_idx:] batch_data = predicted_data[start_idx:]
start_idx = start_idx + batch_size start_idx = start_idx + batch_size
batch_out = self._internal_predict(predictor, batch_data) data, lod, shape = self.preprocess(batch_data)
batch_result = parse_result(batch_data, batch_out, self.id2label_dict, interventer=self.custom)
predictor = self.gpu_predictor if use_gpu else self.cpu_predictor
input_names = predictor.get_input_names()
input_handle = predictor.get_input_handle(input_names[0])
input_handle.copy_from_cpu(data)
input_handle.set_lod(lod)
input_handle.reshape(shape)
predictor.run()
output_names = predictor.get_output_names()
output_handle = predictor.get_output_handle(output_names[0])
batch_result = parse_result(batch_data, output_handle, self.id2label_dict, interventer=self.custom)
results += batch_result results += batch_result
for index in empty_str_indexes: for index in empty_str_indexes:
...@@ -421,8 +351,7 @@ class LAC(hub.Module): ...@@ -421,8 +351,7 @@ class LAC(hub.Module):
results = self.lexical_analysis(texts=input_data, results = self.lexical_analysis(texts=input_data,
use_gpu=args.use_gpu, use_gpu=args.use_gpu,
batch_size=args.batch_size, batch_size=args.batch_size,
return_tag=args.return_tag, return_tag=args.return_tag)
use_device=args.use_device)
return results return results
...@@ -458,9 +387,6 @@ class LAC(hub.Module): ...@@ -458,9 +387,6 @@ class LAC(hub.Module):
type=ast.literal_eval, type=ast.literal_eval,
default=True, default=True,
help="whether return tags of results or not") help="whether return tags of results or not")
self.arg_config_group.add_argument('--use_device',
choices=["cpu", "gpu", "xpu", "npu"],
help="use cpu, gpu, xpu or npu. overwrites use_gpu flag.")
def add_module_input_arg(self): def add_module_input_arg(self):
""" """
...@@ -489,30 +415,3 @@ class LAC(hub.Module): ...@@ -489,30 +415,3 @@ class LAC(hub.Module):
raise DataFormatError raise DataFormatError
return input_data return input_data
if __name__ == '__main__':
lac = LAC(user_dict="user.dict")
# or use the fuction user_dict to set
# lac.set_user_dict("user.dict")
test_text = ["今天是个好日子", "天气预报说今天要下雨", "", "下一班地铁马上就要到了", "", "调料份量不能多,也不能少,味道才能正好", "", "", "春天的花开秋天的风以及冬天的落阳"]
# execute predict and print the result
results = lac.cut(text=test_text, use_gpu=True, batch_size=7, return_tag=True)
for result in results:
if six.PY2:
print(json.dumps(result['word'], encoding="utf8", ensure_ascii=False))
print(json.dumps(result['tag'], encoding="utf8", ensure_ascii=False))
else:
print(result['word'])
print(result['tag'])
# delete the costomized dictionary
lac.del_user_dict()
results = lac.cut(text="春天的花开秋天的风以及冬天的落阳", use_gpu=False, batch_size=1, return_tag=False)
print(results)
# get the tags that was exploited as pretraining lac
print(lac.get_tags())
# -*- coding:utf-8 -*- # -*- coding:utf-8 -*-
import io import io
import numpy as np
import os import os
import numpy as np
import six import six
class Query(object): class Query(object):
def __init__(self, lac_query): def __init__(self, lac_query):
self.set_query(lac_query) self.set_query(lac_query)
...@@ -35,6 +37,7 @@ class Query(object): ...@@ -35,6 +37,7 @@ class Query(object):
class Bound(object): class Bound(object):
def __init__(self, start_index=0, end_index=0, left_bound=0, right_bound=0, left_char_bound=0, right_char_bound=0): def __init__(self, start_index=0, end_index=0, left_bound=0, right_bound=0, left_char_bound=0, right_char_bound=0):
self.start_index = start_index # 命中的词的起始位置,char级别 self.start_index = start_index # 命中的词的起始位置,char级别
self.end_index = end_index # 命中的词的结束位置,char级别 self.end_index = end_index # 命中的词的结束位置,char级别
...@@ -45,6 +48,7 @@ class Bound(object): ...@@ -45,6 +48,7 @@ class Bound(object):
class Interventer(object): class Interventer(object):
def __init__(self, ngram_dict_path, user_dict_path): def __init__(self, ngram_dict_path, user_dict_path):
self.ngram_dict_path = ngram_dict_path self.ngram_dict_path = ngram_dict_path
self.user_dict_path = user_dict_path self.user_dict_path = user_dict_path
......
# ernie_skep_sentiment_analysis # ernie_skep_sentiment_analysis
|模型名称|ernie_skep_sentiment_analysis| |模型名称|ernie_skep_sentiment_analysis|
| :--- | :---: | | :--- | :---: |
|类别|文本-情感分析| |类别|文本-情感分析|
|网络|SKEP| |网络|SKEP|
|数据集|百度自建数据集| |数据集|百度自建数据集|
...@@ -29,13 +29,13 @@ ...@@ -29,13 +29,13 @@
- ### 1、环境依赖 - ### 1、环境依赖
- paddlepaddle >= 1.8.0 - paddlepaddle >= 1.8.0
- paddlehub >= 1.7.0 | [如何安装PaddleHub](../../../../docs/docs_ch/get_start/installation.rst) - paddlehub >= 1.7.0 | [如何安装PaddleHub](../../../../docs/docs_ch/get_start/installation.rst)
- ### 2、安装 - ### 2、安装
- ```shell - ```shell
$ hub install ernie_skep_sentiment_analysis==1.0.0 $ hub install ernie_skep_sentiment_analysis
``` ```
- 如您安装时遇到问题,可参考:[零基础windows安装](../../../../docs/docs_ch/get_start/windows_quickstart.md) - 如您安装时遇到问题,可参考:[零基础windows安装](../../../../docs/docs_ch/get_start/windows_quickstart.md)
| [零基础Linux安装](../../../../docs/docs_ch/get_start/linux_quickstart.md) | [零基础MacOS安装](../../../../docs/docs_ch/get_start/mac_quickstart.md) | [零基础Linux安装](../../../../docs/docs_ch/get_start/linux_quickstart.md) | [零基础MacOS安装](../../../../docs/docs_ch/get_start/mac_quickstart.md)
...@@ -49,7 +49,7 @@ ...@@ -49,7 +49,7 @@
- ```shell - ```shell
$ hub run ernie_skep_sentiment_analysis --input_text='虽然小明很努力,但是他还是没有考100分' $ hub run ernie_skep_sentiment_analysis --input_text='虽然小明很努力,但是他还是没有考100分'
``` ```
- ### 2、预测代码示例 - ### 2、预测代码示例
- ```python - ```python
...@@ -61,13 +61,13 @@ ...@@ -61,13 +61,13 @@
# Predict sentiment label # Predict sentiment label
test_texts = ['你不是不聪明,而是不认真', '虽然小明很努力,但是他还是没有考100分'] test_texts = ['你不是不聪明,而是不认真', '虽然小明很努力,但是他还是没有考100分']
results = module.predict_sentiment(test_texts, use_gpu=False) results = module.predict_sentiment(test_texts, use_gpu=False)
for result in results: for result in results:
print(result['text']) print(result['text'])
print(result['sentiment_label']) print(result['sentiment_label'])
print(result['positive_probs']) print(result['positive_probs'])
print(result['negative_probs']) print(result['negative_probs'])
# 你不是不聪明,而是不认真 negative 0.10738129168748856 0.8926186561584473 # 你不是不聪明,而是不认真 negative 0.10738129168748856 0.8926186561584473
# 虽然小明很努力,但是他还是没有考100分 negative 0.05391530692577362 0.94608473777771 # 虽然小明很努力,但是他还是没有考100分 negative 0.05391530692577362 0.94608473777771
``` ```
...@@ -137,7 +137,7 @@ ...@@ -137,7 +137,7 @@
headers = {"Content-type": "application/json"} headers = {"Content-type": "application/json"}
url = "http://127.0.0.1:8866/predict/ernie_skep_sentiment_analysis" url = "http://127.0.0.1:8866/predict/ernie_skep_sentiment_analysis"
r = requests.post(url=url, headers=headers, data=json.dumps(data)) r = requests.post(url=url, headers=headers, data=json.dumps(data))
# 打印预测结果 # 打印预测结果
print(r.json()["results"]) print(r.json()["results"])
``` ```
...@@ -147,7 +147,11 @@ ...@@ -147,7 +147,11 @@
* 1.0.0 * 1.0.0
初始发布 初始发布
* 1.0.1
移除 fluid api
- ```shell - ```shell
$ hub install ernie_skep_sentiment_analysis==1.0.0 $ hub install ernie_skep_sentiment_analysis==1.0.1
``` ```
...@@ -13,7 +13,6 @@ ...@@ -13,7 +13,6 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
"""ERNIE""" """ERNIE"""
from __future__ import absolute_import from __future__ import absolute_import
from __future__ import division from __future__ import division
from __future__ import print_function from __future__ import print_function
...@@ -22,261 +21,8 @@ from __future__ import unicode_literals ...@@ -22,261 +21,8 @@ from __future__ import unicode_literals
import json import json
import logging import logging
import paddle.fluid as fluid
import six import six
from .transformer_encoder import encoder, pre_process_layer
from .transformer_encoder import gelu
class ErnieModel(object):
"""
ErnieModel
"""
def __init__(self, src_ids, position_ids, sentence_ids, input_mask, config, weight_sharing=True, use_fp16=False):
"""
:param src_ids:
:param position_ids:
:param sentence_ids:
:param input_mask:
:param config:
:param weight_sharing:
:param use_fp16:
"""
self._hidden_size = config.get('hidden_size', 768)
self._emb_size = config.get('emb_size', self._hidden_size)
self._n_layer = config.get('num_hidden_layers', 12)
self._n_head = config.get('num_attention_heads', 12)
self._voc_size = config.get('vocab_size', 30522)
self._max_position_seq_len = config.get('max_position_embeddings', 512)
self._param_share = config.get('param_share', "normal")
self._pre_encoder_cmd = config.get('pre_encoder_cmd', "nd")
self._preprocess_cmd = config.get('preprocess_cmd', "")
self._postprocess_cmd = config.get('postprocess_cmd', "dan")
self._epsilon = config.get('epsilon', 1e-05)
self._emb_mapping_in = config.get('emb_mapping_in', False)
self._n_layer_per_block = config.get('n_layer_per_block', 1)
if config.has('sent_type_vocab_size'):
self._sent_types = config['sent_type_vocab_size']
else:
self._sent_types = config.get('type_vocab_size', 2)
self._use_sentence_id = config.get('use_sentence_id', True)
self._use_task_id = config.get('use_task_id', False)
if self._use_task_id:
self._task_types = config.get('task_type_vocab_size', 3)
self._hidden_act = config.get('hidden_act', 'gelu')
self._prepostprocess_dropout = config.get('hidden_dropout_prob', 0.1)
self._attention_dropout = config.get('attention_probs_dropout_prob', 0.1)
self._weight_sharing = weight_sharing
self._word_emb_name = "word_embedding"
self._pos_emb_name = "pos_embedding"
self._sent_emb_name = "sent_embedding"
self._task_emb_name = "task_embedding"
self._dtype = "float16" if use_fp16 else "float32"
self._emb_dtype = "float32"
# Initialize all weigths by truncated normal initializer, and all biases
# will be initialized by constant zero by default.
self._param_initializer = fluid.initializer.TruncatedNormal(scale=config.get('initializer_range', 0.02))
self._build_model(src_ids, position_ids, sentence_ids, input_mask)
def _build_model(self, src_ids, position_ids, sentence_ids, input_mask):
"""
:param src_ids:
:param position_ids:
:param sentence_ids:
:param input_mask:
:return:
"""
# padding id in vocabulary must be set to 0
emb_out = fluid.layers.embedding(
input=src_ids,
dtype=self._emb_dtype,
size=[self._voc_size, self._emb_size],
param_attr=fluid.ParamAttr(name=self._word_emb_name, initializer=self._param_initializer),
is_sparse=False)
position_emb_out = fluid.layers.embedding(
input=position_ids,
dtype=self._emb_dtype,
size=[self._max_position_seq_len, self._emb_size],
param_attr=fluid.ParamAttr(name=self._pos_emb_name, initializer=self._param_initializer))
emb_out = emb_out + position_emb_out
if self._use_sentence_id:
sent_emb_out = fluid.layers.embedding(
sentence_ids,
dtype=self._emb_dtype,
size=[self._sent_types, self._emb_size],
param_attr=fluid.ParamAttr(name=self._sent_emb_name, initializer=self._param_initializer))
emb_out = emb_out + sent_emb_out
emb_out = pre_process_layer(
emb_out, self._pre_encoder_cmd, self._prepostprocess_dropout, name='pre_encoder', epsilon=self._epsilon)
if self._emb_mapping_in:
emb_out = fluid.layers.fc(
input=emb_out,
num_flatten_dims=2,
size=self._hidden_size,
param_attr=fluid.ParamAttr(name='emb_hidden_mapping', initializer=self._param_initializer),
bias_attr='emb_hidden_mapping_bias')
if self._dtype == "float16":
emb_out = fluid.layers.cast(x=emb_out, dtype=self._dtype)
input_mask = fluid.layers.cast(x=input_mask, dtype=self._dtype)
self_attn_mask = fluid.layers.matmul(x=input_mask, y=input_mask, transpose_y=True)
self_attn_mask = fluid.layers.scale(x=self_attn_mask, scale=10000.0, bias=-1.0, bias_after_scale=False)
n_head_self_attn_mask = fluid.layers.stack(x=[self_attn_mask] * self._n_head, axis=1)
n_head_self_attn_mask.stop_gradient = True
self._enc_out, self._checkpoints = encoder(
enc_input=emb_out,
attn_bias=n_head_self_attn_mask,
n_layer=self._n_layer,
n_head=self._n_head,
d_key=self._hidden_size // self._n_head,
d_value=self._hidden_size // self._n_head,
d_model=self._hidden_size,
d_inner_hid=self._hidden_size * 4,
prepostprocess_dropout=self._prepostprocess_dropout,
attention_dropout=self._attention_dropout,
relu_dropout=0,
hidden_act=self._hidden_act,
preprocess_cmd=self._preprocess_cmd,
postprocess_cmd=self._postprocess_cmd,
param_initializer=self._param_initializer,
name='encoder',
param_share=self._param_share,
epsilon=self._epsilon,
n_layer_per_block=self._n_layer_per_block)
if self._dtype == "float16":
self._enc_out = fluid.layers.cast(x=self._enc_out, dtype=self._emb_dtype)
def get_sequence_output(self):
"""
:return:
"""
return self._enc_out
def get_pooled_output(self):
"""Get the first feature of each sequence for classification"""
next_sent_feat = fluid.layers.slice(input=self._enc_out, axes=[1], starts=[0], ends=[1])
"""
if self._dtype == "float16":
next_sent_feat = fluid.layers.cast(
x=next_sent_feat, dtype=self._emb_dtype)
next_sent_feat = fluid.layers.fc(
input=next_sent_feat,
size=self._emb_size,
param_attr=fluid.ParamAttr(
name="mask_lm_trans_fc.w_0", initializer=self._param_initializer),
bias_attr="mask_lm_trans_fc.b_0")
"""
"""
next_sent_feat = fluid.layers.fc(
input=next_sent_feat,
size=self._emb_size,
param_attr=fluid.ParamAttr(
name="mask_lm_trans_fc.w_0", initializer=self._param_initializer),
bias_attr="mask_lm_trans_fc.b_0")
"""
next_sent_feat = fluid.layers.fc(
input=next_sent_feat,
size=self._hidden_size,
act="tanh",
param_attr=fluid.ParamAttr(name="pooled_fc.w_0", initializer=self._param_initializer),
bias_attr="pooled_fc.b_0")
return next_sent_feat
def get_lm_output(self, mask_label, mask_pos):
"""Get the loss & accuracy for pretraining"""
mask_pos = fluid.layers.cast(x=mask_pos, dtype='int32')
# extract the first token feature in each sentence
self.next_sent_feat = self.get_pooled_output()
reshaped_emb_out = fluid.layers.reshape(x=self._enc_out, shape=[-1, self._hidden_size])
# extract masked tokens' feature
mask_feat = fluid.layers.gather(input=reshaped_emb_out, index=mask_pos)
if self._dtype == "float16":
mask_feat = fluid.layers.cast(x=mask_feat, dtype=self._emb_dtype)
# transform: fc
if self._hidden_act == 'gelu' or self._hidden_act == 'gelu.precise':
_hidden_act = 'gelu'
elif self._hidden_act == 'gelu.approximate':
_hidden_act = None
else:
_hidden_act = self._hidden_act
mask_trans_feat = fluid.layers.fc(
input=mask_feat,
size=self._emb_size,
act=_hidden_act,
param_attr=fluid.ParamAttr(name='mask_lm_trans_fc.w_0', initializer=self._param_initializer),
bias_attr=fluid.ParamAttr(name='mask_lm_trans_fc.b_0'))
if self._hidden_act == 'gelu.approximate':
mask_trans_feat = gelu(mask_trans_feat)
else:
pass
# transform: layer norm
mask_trans_feat = fluid.layers.layer_norm(
mask_trans_feat,
begin_norm_axis=len(mask_trans_feat.shape) - 1,
param_attr=fluid.ParamAttr(
name='mask_lm_trans_layer_norm_scale', initializer=fluid.initializer.Constant(1.)),
bias_attr=fluid.ParamAttr(name='mask_lm_trans_layer_norm_bias', initializer=fluid.initializer.Constant(1.)))
# transform: layer norm
# mask_trans_feat = pre_process_layer(
# mask_trans_feat, 'n', name='mask_lm_trans')
mask_lm_out_bias_attr = fluid.ParamAttr(
name="mask_lm_out_fc.b_0", initializer=fluid.initializer.Constant(value=0.0))
if self._weight_sharing:
fc_out = fluid.layers.matmul(
x=mask_trans_feat,
y=fluid.default_main_program().global_block().var(self._word_emb_name),
transpose_y=True)
fc_out += fluid.layers.create_parameter(
shape=[self._voc_size], dtype=self._emb_dtype, attr=mask_lm_out_bias_attr, is_bias=True)
else:
fc_out = fluid.layers.fc(
input=mask_trans_feat,
size=self._voc_size,
param_attr=fluid.ParamAttr(name="mask_lm_out_fc.w_0", initializer=self._param_initializer),
bias_attr=mask_lm_out_bias_attr)
mask_lm_loss = fluid.layers.softmax_with_cross_entropy(logits=fc_out, label=mask_label)
mean_mask_lm_loss = fluid.layers.mean(mask_lm_loss)
return mean_mask_lm_loss
def get_task_output(self, task, task_labels):
"""
:param task:
:param task_labels:
:return:
"""
task_fc_out = fluid.layers.fc(
input=self.next_sent_feat,
size=task["num_labels"],
param_attr=fluid.ParamAttr(name=task["task_name"] + "_fc.w_0", initializer=self._param_initializer),
bias_attr=task["task_name"] + "_fc.b_0")
task_loss, task_softmax = fluid.layers.softmax_with_cross_entropy(
logits=task_fc_out, label=task_labels, return_softmax=True)
task_acc = fluid.layers.accuracy(input=task_softmax, label=task_labels)
mean_task_loss = fluid.layers.mean(task_loss)
return mean_task_loss, task_acc
class ErnieConfig(object): class ErnieConfig(object):
"""parse ernie config""" """parse ernie config"""
......
# -*- coding:utf-8 -**
# Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Transformer encoder."""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from functools import partial
import paddle.fluid as fluid
import paddle.fluid.layers as layers
import numpy as np
def gelu(x):
"""Gaussian Error Linear Unit.
This is a smoother version of the RELU.
Original paper: https://arxiv.org/abs/1606.08415
Args:
x: float Tensor to perform activation.
Returns:
`x` with the GELU activation applied.
"""
cdf = 0.5 * (1.0 + fluid.layers.tanh((np.sqrt(2.0 / np.pi) * (x + 0.044715 * fluid.layers.pow(x, 3.0)))))
return x * cdf
def multi_head_attention(queries,
keys,
values,
attn_bias,
d_key,
d_value,
d_model,
n_head=1,
dropout_rate=0.,
cache=None,
param_initializer=None,
name='multi_head_att'):
"""
Multi-Head Attention. Note that attn_bias is added to the logit before
computing softmax activiation to mask certain selected positions so that
they will not considered in attention weights.
"""
keys = queries if keys is None else keys
values = keys if values is None else values
if not (len(queries.shape) == len(keys.shape) == len(values.shape) == 3):
raise ValueError(
"Inputs: quries, keys and values should all be 3-D tensors. but {} v.s. {} v.s. {}"\
.format(queries.shape, keys.shape, values.shape))
def __compute_qkv(queries, keys, values, n_head, d_key, d_value):
"""
Add linear projection to queries, keys, and values.
"""
q = layers.fc(
input=queries,
size=d_key * n_head,
num_flatten_dims=2,
param_attr=fluid.ParamAttr(name=name + '_query_fc.w_0', initializer=param_initializer),
bias_attr=name + '_query_fc.b_0')
k = layers.fc(
input=keys,
size=d_key * n_head,
num_flatten_dims=2,
param_attr=fluid.ParamAttr(name=name + '_key_fc.w_0', initializer=param_initializer),
bias_attr=name + '_key_fc.b_0')
v = layers.fc(
input=values,
size=d_value * n_head,
num_flatten_dims=2,
param_attr=fluid.ParamAttr(name=name + '_value_fc.w_0', initializer=param_initializer),
bias_attr=name + '_value_fc.b_0')
return q, k, v
def __split_heads(x, n_head):
"""
Reshape the last dimension of inpunt tensor x so that it becomes two
dimensions and then transpose. Specifically, input a tensor with shape
[bs, max_sequence_length, n_head * hidden_dim] then output a tensor
with shape [bs, n_head, max_sequence_length, hidden_dim].
"""
hidden_size = x.shape[-1]
# The value 0 in shape attr means copying the corresponding dimension
# size of the input as the output dimension size.
reshaped = layers.reshape(x=x, shape=[0, 0, n_head, hidden_size // n_head], inplace=True)
# permuate the dimensions into:
# [batch_size, n_head, max_sequence_len, hidden_size_per_head]
return layers.transpose(x=reshaped, perm=[0, 2, 1, 3])
def __combine_heads(x):
"""
Transpose and then reshape the last two dimensions of inpunt tensor x
so that it becomes one dimension, which is reverse to __split_heads.
"""
if len(x.shape) == 3: return x
if len(x.shape) != 4:
raise ValueError("Input(x) should be a 4-D Tensor.")
trans_x = layers.transpose(x, perm=[0, 2, 1, 3])
# The value 0 in shape attr means copying the corresponding dimension
# size of the input as the output dimension size.
return layers.reshape(x=trans_x, shape=[0, 0, trans_x.shape[2] * trans_x.shape[3]], inplace=True)
def scaled_dot_product_attention(q, k, v, attn_bias, d_key, dropout_rate):
"""
Scaled Dot-Product Attention
"""
scaled_q = layers.scale(x=q, scale=d_key**-0.5)
product = layers.matmul(x=scaled_q, y=k, transpose_y=True)
if attn_bias:
product += attn_bias
weights = layers.softmax(product)
if dropout_rate:
weights = layers.dropout(
weights, dropout_prob=dropout_rate, dropout_implementation="upscale_in_train", is_test=False)
out = layers.matmul(weights, v)
return out
q, k, v = __compute_qkv(queries, keys, values, n_head, d_key, d_value)
if cache is not None: # use cache and concat time steps
# Since the inplace reshape in __split_heads changes the shape of k and
# v, which is the cache input for next time step, reshape the cache
# input from the previous time step first.
k = cache["k"] = layers.concat([layers.reshape(cache["k"], shape=[0, 0, d_model]), k], axis=1)
v = cache["v"] = layers.concat([layers.reshape(cache["v"], shape=[0, 0, d_model]), v], axis=1)
q = __split_heads(q, n_head)
k = __split_heads(k, n_head)
v = __split_heads(v, n_head)
ctx_multiheads = scaled_dot_product_attention(q, k, v, attn_bias, d_key, dropout_rate)
out = __combine_heads(ctx_multiheads)
# Project back to the model size.
proj_out = layers.fc(
input=out,
size=d_model,
num_flatten_dims=2,
param_attr=fluid.ParamAttr(name=name + '_output_fc.w_0', initializer=param_initializer),
bias_attr=name + '_output_fc.b_0')
return proj_out
def positionwise_feed_forward(x, d_inner_hid, d_hid, dropout_rate, hidden_act, param_initializer=None, name='ffn'):
"""
Position-wise Feed-Forward Networks.
This module consists of two linear transformations with a ReLU activation
in between, which is applied to each position separately and identically.
"""
if hidden_act == 'gelu' or hidden_act == 'gelu.precise':
_hidden_act = 'gelu'
elif hidden_act == 'gelu.approximate':
_hidden_act = None
else:
_hidden_act = hidden_act
hidden = layers.fc(
input=x,
size=d_inner_hid,
num_flatten_dims=2,
act=_hidden_act,
param_attr=fluid.ParamAttr(name=name + '_fc_0.w_0', initializer=param_initializer),
bias_attr=name + '_fc_0.b_0')
if hidden_act == 'gelu.approximate':
hidden = gelu(hidden)
if dropout_rate:
hidden = layers.dropout(
hidden, dropout_prob=dropout_rate, dropout_implementation="upscale_in_train", is_test=False)
out = layers.fc(
input=hidden,
size=d_hid,
num_flatten_dims=2,
param_attr=fluid.ParamAttr(name=name + '_fc_1.w_0', initializer=param_initializer),
bias_attr=name + '_fc_1.b_0')
return out
def pre_post_process_layer(prev_out, out, process_cmd, dropout_rate=0., epsilon=1e-12, name=''):
"""
Add residual connection, layer normalization and droput to the out tensor
optionally according to the value of process_cmd.
This will be used before or after multi-head attention and position-wise
feed-forward networks.
"""
for cmd in process_cmd:
if cmd == "a": # add residual connection
out = out + prev_out if prev_out else out
elif cmd == "n": # add layer normalization
out_dtype = out.dtype
if out_dtype == fluid.core.VarDesc.VarType.FP16:
out = layers.cast(x=out, dtype="float32")
out = layers.layer_norm(
out,
begin_norm_axis=len(out.shape) - 1,
param_attr=fluid.ParamAttr(name=name + '_layer_norm_scale', initializer=fluid.initializer.Constant(1.)),
bias_attr=fluid.ParamAttr(name=name + '_layer_norm_bias', initializer=fluid.initializer.Constant(0.)),
epsilon=epsilon)
if out_dtype == fluid.core.VarDesc.VarType.FP16:
out = layers.cast(x=out, dtype="float16")
elif cmd == "d": # add dropout
if dropout_rate:
out = layers.dropout(
out, dropout_prob=dropout_rate, dropout_implementation="upscale_in_train", is_test=False)
return out
pre_process_layer = partial(pre_post_process_layer, None)
post_process_layer = pre_post_process_layer
def encoder_layer(
enc_input,
attn_bias,
n_head,
d_key,
d_value,
d_model,
d_inner_hid,
prepostprocess_dropout,
attention_dropout,
relu_dropout,
hidden_act,
preprocess_cmd="n",
postprocess_cmd="da",
param_initializer=None,
name='',
epsilon=1e-12,
):
"""The encoder layers that can be stacked to form a deep encoder.
This module consits of a multi-head (self) attention followed by
position-wise feed-forward networks and both the two components companied
with the post_process_layer to add residual connection, layer normalization
and droput.
"""
attn_output = multi_head_attention(
enc_input,
None,
None,
attn_bias,
d_key,
d_value,
d_model,
n_head,
attention_dropout,
param_initializer=param_initializer,
name=name + '_multi_head_att')
attn_output = post_process_layer(
enc_input, attn_output, postprocess_cmd, prepostprocess_dropout, name=name + '_post_att', epsilon=epsilon)
ffd_output = positionwise_feed_forward(
attn_output,
d_inner_hid,
d_model,
relu_dropout,
hidden_act,
param_initializer=param_initializer,
name=name + '_ffn')
return post_process_layer(
attn_output, ffd_output, postprocess_cmd, prepostprocess_dropout, name=name + '_post_ffn',
epsilon=epsilon), ffd_output
def encoder_inner_share(enc_input,
attn_bias,
n_head,
d_key,
d_value,
d_model,
d_inner_hid,
prepostprocess_dropout,
attention_dropout,
relu_dropout,
hidden_act,
preprocess_cmd,
postprocess_cmd,
epsilon,
param_initializer=None,
name='',
n_layer_per_block=1):
"""
The encoder_inner_share is composed of n_layer_per_block layers returned by calling
encoder_layer.
"""
_checkpoints = []
for i in range(n_layer_per_block):
enc_output, cp = encoder_layer(
enc_input,
attn_bias,
n_head,
d_key,
d_value,
d_model,
d_inner_hid,
prepostprocess_dropout,
attention_dropout,
relu_dropout,
hidden_act,
preprocess_cmd,
postprocess_cmd,
param_initializer=param_initializer,
name=name + '_layer_' + str(i),
epsilon=epsilon,
)
_checkpoints.append(cp)
enc_input = enc_output
return enc_output, _checkpoints
def encoder_outer_share(enc_input,
attn_bias,
n_head,
d_key,
d_value,
d_model,
d_inner_hid,
prepostprocess_dropout,
attention_dropout,
relu_dropout,
hidden_act,
preprocess_cmd,
postprocess_cmd,
epsilon,
param_initializer=None,
name='',
n_layer_per_block=1):
"""
The encoder_outer_share is composed of n_layer_per_block layers returned by calling
encoder_layer.
"""
_checkpoints = []
for i in range(n_layer_per_block):
enc_output, cp = encoder_layer(
enc_input,
attn_bias,
n_head,
d_key,
d_value,
d_model,
d_inner_hid,
prepostprocess_dropout,
attention_dropout,
relu_dropout,
hidden_act,
preprocess_cmd,
postprocess_cmd,
param_initializer=param_initializer,
name=name,
epsilon=epsilon)
_checkpoints.append(cp)
enc_input = enc_output
return enc_output, _checkpoints
def encoder(enc_input,
attn_bias,
n_layer,
n_head,
d_key,
d_value,
d_model,
d_inner_hid,
prepostprocess_dropout,
attention_dropout,
relu_dropout,
hidden_act,
preprocess_cmd,
postprocess_cmd,
epsilon,
n_layer_per_block,
param_initializer=None,
name='',
param_share=None):
"""
The encoder is composed of a stack of identical layers returned by calling
encoder_layer .
"""
checkpoints = []
# for outer_share it will share same param in one block,
# and for inner_share it will share param across blocks, rather than in one same block
#
# outer-share inner-share
# [1] [1] ----\ 1st block
# [1] [2] ----/
# [2] [1] ----\ 2nd block
# [2] [2] ----/
if param_share == "normal" or param_share == 'outer_share':
#n_layer_per_block=1, n_layer=24 for bert-large
#n_layer_per_block=1, n_layer=12 for bert-base
#n_layer_per_block=12, n_layer=12 for albert-xxlarge
#n_layer_per_block=6, n_layer=12 for albert-xxlarge-outershare
enc_fn = encoder_outer_share
name_fn = lambda i: name + '_layer_' + str(i)
elif param_share == "inner_share":
#n_layer_per_block = 2
enc_fn = encoder_inner_share
name_fn = lambda i: name
else:
raise ValueError('unsupported param share mode')
for i in range(n_layer // n_layer_per_block):
enc_output, cp = enc_fn(
enc_input,
attn_bias,
n_head,
d_key,
d_value,
d_model,
d_inner_hid,
prepostprocess_dropout,
attention_dropout,
relu_dropout,
hidden_act,
preprocess_cmd,
postprocess_cmd,
param_initializer=param_initializer,
name=name_fn(i),
n_layer_per_block=n_layer_per_block,
epsilon=epsilon,
)
checkpoints.extend(cp)
enc_input = enc_output
enc_output = pre_process_layer(
enc_output, preprocess_cmd, prepostprocess_dropout, name="post_encoder", epsilon=epsilon)
return enc_output, checkpoints
...@@ -20,19 +20,22 @@ import argparse ...@@ -20,19 +20,22 @@ import argparse
import ast import ast
import os import os
from paddle.fluid.core import PaddleTensor, AnalysisConfig, create_paddle_predictor
from paddlehub import TransformerModule
from paddlehub.module.module import moduleinfo, runnable, serving
from paddlehub.reader.tokenization import convert_to_unicode, FullTokenizer
from paddlehub.reader.batching import pad_batch_data
import numpy as np import numpy as np
from ernie_skep_sentiment_analysis.model.ernie import ErnieConfig
from paddle.framework import core
from ernie_skep_sentiment_analysis.model.ernie import ErnieModel, ErnieConfig from paddlehub import TransformerModule
from paddlehub.module.module import moduleinfo
from paddlehub.module.module import runnable
from paddlehub.module.module import serving
from paddlehub.reader.batching import pad_batch_data
from paddlehub.reader.tokenization import convert_to_unicode
from paddlehub.reader.tokenization import FullTokenizer
@moduleinfo( @moduleinfo(
name="ernie_skep_sentiment_analysis", name="ernie_skep_sentiment_analysis",
version="1.0.0", version="1.0.1",
summary= summary=
"SKEP: Sentiment Knowledge Enhanced Pre-training for Sentiment Analysis. Ernie_skep_sentiment_analysis module is initialize with enie_1.0_chn_large when pretraining. This module is finetuned on ChnSentiCorp dataset to do sentiment claasification. It can do sentiment analysis prediction directly, label as positive or negative.", "SKEP: Sentiment Knowledge Enhanced Pre-training for Sentiment Analysis. Ernie_skep_sentiment_analysis module is initialize with enie_1.0_chn_large when pretraining. This module is finetuned on ChnSentiCorp dataset to do sentiment claasification. It can do sentiment analysis prediction directly, label as positive or negative.",
author="baidu-nlp", author="baidu-nlp",
...@@ -69,7 +72,7 @@ class ErnieSkepSentimentAnalysis(TransformerModule): ...@@ -69,7 +72,7 @@ class ErnieSkepSentimentAnalysis(TransformerModule):
model_file_path = os.path.join(self.infer_model_path, 'model') model_file_path = os.path.join(self.infer_model_path, 'model')
params_file_path = os.path.join(self.infer_model_path, 'params') params_file_path = os.path.join(self.infer_model_path, 'params')
config = AnalysisConfig(model_file_path, params_file_path) config = core.AnalysisConfig(model_file_path, params_file_path)
try: try:
_places = os.environ["CUDA_VISIBLE_DEVICES"] _places = os.environ["CUDA_VISIBLE_DEVICES"]
int(_places[0]) int(_places[0])
...@@ -84,38 +87,13 @@ class ErnieSkepSentimentAnalysis(TransformerModule): ...@@ -84,38 +87,13 @@ class ErnieSkepSentimentAnalysis(TransformerModule):
config.disable_glog_info() config.disable_glog_info()
self.predictor = create_paddle_predictor(config) self.predictor = core.create_paddle_predictor(config)
def net(self, input_ids, position_ids, segment_ids, input_mask):
"""
create neural network.
Args:
input_ids (tensor): the word ids.
position_ids (tensor): the position ids.
segment_ids (tensor): the segment ids.
input_mask (tensor): the padding mask.
Returns:
pooled_output (tensor): sentence-level output for classification task.
sequence_output (tensor): token-level output for sequence task.
"""
ernie = ErnieModel(
src_ids=input_ids,
position_ids=position_ids,
sentence_ids=segment_ids,
input_mask=input_mask,
config=self.ernie_config,
use_fp16=False)
pooled_output = ernie.get_pooled_output()
sequence_output = ernie.get_sequence_output()
return pooled_output, sequence_output
def array2tensor(self, arr_data): def array2tensor(self, arr_data):
""" """
convert numpy array to PaddleTensor convert numpy array to PaddleTensor
""" """
tensor_data = PaddleTensor(arr_data) tensor_data = core.PaddleTensor(arr_data)
return tensor_data return tensor_data
@serving @serving
...@@ -212,11 +190,10 @@ class ErnieSkepSentimentAnalysis(TransformerModule): ...@@ -212,11 +190,10 @@ class ErnieSkepSentimentAnalysis(TransformerModule):
""" """
Run as a command Run as a command
""" """
self.parser = argparse.ArgumentParser( self.parser = argparse.ArgumentParser(description="Run the %s module." % self.name,
description="Run the %s module." % self.name, prog='hub run %s' % self.name,
prog='hub run %s' % self.name, usage='%(prog)s',
usage='%(prog)s', add_help=True)
add_help=True)
self.arg_input_group = self.parser.add_argument_group(title="Input options", description="Input data. Required") 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( self.arg_config_group = self.parser.add_argument_group(
...@@ -233,8 +210,10 @@ class ErnieSkepSentimentAnalysis(TransformerModule): ...@@ -233,8 +210,10 @@ class ErnieSkepSentimentAnalysis(TransformerModule):
""" """
Add the command config options Add the command config options
""" """
self.arg_config_group.add_argument( self.arg_config_group.add_argument('--use_gpu',
'--use_gpu', type=ast.literal_eval, default=False, help="whether use GPU or not") type=ast.literal_eval,
default=False,
help="whether use GPU or not")
def add_module_input_arg(self): def add_module_input_arg(self):
""" """
......
# senta_bilstm # senta_bilstm
|模型名称|senta_bilstm| |模型名称|senta_bilstm|
| :--- | :---: | | :--- | :---: |
|类别|文本-情感分析| |类别|文本-情感分析|
|网络|BiLSTM| |网络|BiLSTM|
|数据集|百度自建数据集| |数据集|百度自建数据集|
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
- ### 1、环境依赖 - ### 1、环境依赖
- paddlepaddle >= 1.8.0 - paddlepaddle >= 1.8.0
- paddlehub >= 1.8.0 | [如何安装PaddleHub](../../../../docs/docs_ch/get_start/installation.rst) - paddlehub >= 1.8.0 | [如何安装PaddleHub](../../../../docs/docs_ch/get_start/installation.rst)
- ### 2、安装 - ### 2、安装
...@@ -45,12 +45,12 @@ ...@@ -45,12 +45,12 @@
或者 或者
- ```shell - ```shell
$ hub run senta_bilstm --input_file test.txt $ hub run senta_bilstm --input_file test.txt
``` ```
- test.txt 存放待预测文本, 如: - test.txt 存放待预测文本, 如:
> 这家餐厅很好吃 > 这家餐厅很好吃
> 这部电影真的很差劲 > 这部电影真的很差劲
- 通过命令行方式实现文字识别模型的调用,更多请见 [PaddleHub命令行指令](../../../../docs/docs_ch/tutorial/cmd_usage.rst) - 通过命令行方式实现文字识别模型的调用,更多请见 [PaddleHub命令行指令](../../../../docs/docs_ch/tutorial/cmd_usage.rst)
- ### 2、预测代码示例 - ### 2、预测代码示例
...@@ -60,17 +60,17 @@ ...@@ -60,17 +60,17 @@
senta = hub.Module(name="senta_bilstm") senta = hub.Module(name="senta_bilstm")
test_text = ["这家餐厅很好吃", "这部电影真的很差劲"] test_text = ["这家餐厅很好吃", "这部电影真的很差劲"]
results = senta.sentiment_classify(texts=test_text, results = senta.sentiment_classify(texts=test_text,
use_gpu=False, use_gpu=False,
batch_size=1) batch_size=1)
for result in results: for result in results:
print(result['text']) print(result['text'])
print(result['sentiment_label']) print(result['sentiment_label'])
print(result['sentiment_key']) print(result['sentiment_key'])
print(result['positive_probs']) print(result['positive_probs'])
print(result['negative_probs']) print(result['negative_probs'])
# 这家餐厅很好吃 1 positive 0.9407 0.0593 # 这家餐厅很好吃 1 positive 0.9407 0.0593
# 这部电影真的很差劲 0 negative 0.02 0.98 # 这部电影真的很差劲 0 negative 0.02 0.98
``` ```
...@@ -80,7 +80,7 @@ ...@@ -80,7 +80,7 @@
- ```python - ```python
def sentiment_classify(texts=[], data={}, use_gpu=False, batch_size=1) def sentiment_classify(texts=[], data={}, use_gpu=False, batch_size=1)
``` ```
- senta_bilstm预测接口,预测输入句子的情感分类(二分类,积极/消极) - senta_bilstm预测接口,预测输入句子的情感分类(二分类,积极/消极)
- **参数** - **参数**
...@@ -170,7 +170,7 @@ ...@@ -170,7 +170,7 @@
* 1.0.0 * 1.0.0
初始发布 初始发布
* 1.0.1 * 1.0.1
词汇表升级 词汇表升级
...@@ -182,6 +182,11 @@ ...@@ -182,6 +182,11 @@
* 1.2.0 * 1.2.0
模型升级,支持用于文本分类,文本匹配等各种任务迁移学习 模型升级,支持用于文本分类,文本匹配等各种任务迁移学习
* 1.2.1
移除 fluid api
- ```shell - ```shell
$ hub install senta_bilstm==1.2.0 $ hub install senta_bilstm==1.2.1
``` ```
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
- ### 1、Environmental dependence - ### 1、Environmental dependence
- paddlepaddle >= 1.8.0 - paddlepaddle >= 1.8.0
- paddlehub >= 1.8.0 | [How to install PaddleHub](../../../../docs/docs_ch/get_start/installation.rst) - paddlehub >= 1.8.0 | [How to install PaddleHub](../../../../docs/docs_ch/get_start/installation.rst)
- ### 2、Installation - ### 2、Installation
...@@ -47,16 +47,16 @@ ...@@ -47,16 +47,16 @@
or or
- ```shell - ```shell
$ hub run senta_bilstm --input_file test.txt $ hub run senta_bilstm --input_file test.txt
``` ```
- test.txt stores the text to be predicted, for example: - test.txt stores the text to be predicted, for example:
> 这家餐厅很好吃 > 这家餐厅很好吃
> 这部电影真的很差劲 > 这部电影真的很差劲
- If you want to call the Hub module through the command line, please refer to: [PaddleHub Command line instruction](../../../../docs/docs_ch/tutorial/cmd_usage.rst) - If you want to call the Hub module through the command line, please refer to: [PaddleHub Command line instruction](../../../../docs/docs_ch/tutorial/cmd_usage.rst)
- ### 2、Prediction Code Example - ### 2、Prediction Code Example
- ```python - ```python
...@@ -64,17 +64,17 @@ ...@@ -64,17 +64,17 @@
senta = hub.Module(name="senta_bilstm") senta = hub.Module(name="senta_bilstm")
test_text = ["这家餐厅很好吃", "这部电影真的很差劲"] test_text = ["这家餐厅很好吃", "这部电影真的很差劲"]
results = senta.sentiment_classify(texts=test_text, results = senta.sentiment_classify(texts=test_text,
use_gpu=False, use_gpu=False,
batch_size=1) batch_size=1)
for result in results: for result in results:
print(result['text']) print(result['text'])
print(result['sentiment_label']) print(result['sentiment_label'])
print(result['sentiment_key']) print(result['sentiment_key'])
print(result['positive_probs']) print(result['positive_probs'])
print(result['negative_probs']) print(result['negative_probs'])
# 这家餐厅很好吃 1 positive 0.9407 0.0593 # 这家餐厅很好吃 1 positive 0.9407 0.0593
# 这部电影真的很差劲 0 negative 0.02 0.98 # 这部电影真的很差劲 0 negative 0.02 0.98
``` ```
...@@ -84,7 +84,7 @@ ...@@ -84,7 +84,7 @@
- ```python - ```python
def sentiment_classify(texts=[], data={}, use_gpu=False, batch_size=1) def sentiment_classify(texts=[], data={}, use_gpu=False, batch_size=1)
``` ```
- senta_bilstm predicting interfaces, predicting sentiment classification of input sentences (dichotomies, positive/negative) - senta_bilstm predicting interfaces, predicting sentiment classification of input sentences (dichotomies, positive/negative)
- **Parameter** - **Parameter**
...@@ -173,7 +173,7 @@ ...@@ -173,7 +173,7 @@
* 1.0.0 * 1.0.0
First release First release
* 1.0.1 * 1.0.1
Vocabulary upgrade Vocabulary upgrade
...@@ -182,9 +182,10 @@ ...@@ -182,9 +182,10 @@
Significantly improve predictive performance Significantly improve predictive performance
* 1.2.0 * 1.2.1
Remove fluid api
Model upgrade, support transfer learning for text classification, text matching and other tasks
- ```shell - ```shell
$ hub install senta_bilstm==1.2.0 $ hub install senta_bilstm==1.2.1
``` ```
...@@ -6,25 +6,26 @@ from __future__ import print_function ...@@ -6,25 +6,26 @@ from __future__ import print_function
import json import json
import math import math
import os import os
import six import six
from senta_bilstm.processor import load_vocab
from senta_bilstm.processor import postprocess
from senta_bilstm.processor import preprocess
import paddle.fluid as fluid
import paddlehub as hub import paddlehub as hub
from paddlehub.common.paddle_helper import add_vars_prefix from paddlehub.common.paddle_helper import add_vars_prefix
from paddlehub.module.module import moduleinfo, serving from paddlehub.module.module import moduleinfo
from paddlehub.module.module import serving
from senta_bilstm.net import bilstm_net
from senta_bilstm.processor import load_vocab, preprocess, postprocess
@moduleinfo( @moduleinfo(name="senta_bilstm",
name="senta_bilstm", version="1.2.1",
version="1.2.0", summary="Baidu's open-source Sentiment Classification System.",
summary="Baidu's open-source Sentiment Classification System.", author="baidu-nlp",
author="baidu-nlp", author_email="",
author_email="", type="nlp/sentiment_analysis")
type="nlp/sentiment_analysis")
class SentaBiLSTM(hub.NLPPredictionModule): class SentaBiLSTM(hub.NLPPredictionModule):
def _initialize(self): def _initialize(self):
""" """
initialize with the necessary elements initialize with the necessary elements
...@@ -47,111 +48,6 @@ class SentaBiLSTM(hub.NLPPredictionModule): ...@@ -47,111 +48,6 @@ class SentaBiLSTM(hub.NLPPredictionModule):
self._word_seg_module = hub.Module(name="lac") self._word_seg_module = hub.Module(name="lac")
return self._word_seg_module return self._word_seg_module
def context(self, trainable=False, max_seq_len=128, num_slots=1):
"""
Get the input ,output and program of the pretrained senta_bilstm
Args:
trainable(bool): whether fine-tune the pretrained parameters of senta_bilstm or not.
max_seq_len (int): It will limit the total sequence returned so that it has a maximum length.
num_slots(int): It's number of data inputted to the model, selectted as following options:
- 1(default): There's only one data to be feeded in the model, e.g. the module is used for text classification task.
- 2: There are two data to be feeded in the model, e.g. the module is used for text matching task (point-wise).
- 3: There are three data to be feeded in the model, e.g. the module is used for text matching task (pair-wise).
Returns:
inputs(dict): the input variables of senta_bilstm (words)
outputs(dict): the output variables of input words (word embeddings and label probilities);
the sentence embedding and sequence length of the first input text.
main_program(Program): the main_program of Senta with pretrained prameters
"""
assert num_slots >= 1 and num_slots <= 3, "num_slots must be 1, 2, or 3, but the input is %d" % num_slots
main_program = fluid.Program()
startup_program = fluid.Program()
with fluid.program_guard(main_program, startup_program):
text_1 = fluid.layers.data(name="text", shape=[-1, max_seq_len, 1], dtype="int64", lod_level=0)
seq_len = fluid.layers.data(name="seq_len", shape=[1], dtype='int64', lod_level=0)
seq_len_used = fluid.layers.squeeze(seq_len, axes=[1])
# Add embedding layer.
w_param_attrs = fluid.ParamAttr(
name="embedding_0.w_0", initializer=fluid.initializer.TruncatedNormal(scale=0.02), trainable=trainable)
dict_dim = 1256607
emb_1 = fluid.layers.embedding(
input=text_1,
size=[dict_dim, 128],
is_sparse=True,
padding_idx=dict_dim - 1,
dtype='float32',
param_attr=w_param_attrs)
emb_1_name = emb_1.name
data_list = [text_1]
emb_name_list = [emb_1_name]
# Add lstm layer.
pred, fc = bilstm_net(emb_1, seq_len_used)
pred_name = pred.name
fc_name = fc.name
if num_slots > 1:
text_2 = fluid.data(name='text_2', shape=[-1, max_seq_len], dtype='int64', lod_level=0)
emb_2 = fluid.embedding(
input=text_2,
size=[dict_dim, 128],
is_sparse=True,
padding_idx=dict_dim - 1,
dtype='float32',
param_attr=w_param_attrs)
emb_2_name = emb_2.name
data_list.append(text_2)
emb_name_list.append(emb_2_name)
if num_slots > 2:
text_3 = fluid.data(name='text_3', shape=[-1, max_seq_len], dtype='int64', lod_level=0)
emb_3 = fluid.embedding(
input=text_3,
size=[dict_dim, 128],
is_sparse=True,
padding_idx=dict_dim - 1,
dtype='float32',
param_attr=w_param_attrs)
emb_3_name = emb_3.name
data_list.append(text_3)
emb_name_list.append(emb_3_name)
variable_names = filter(lambda v: v not in ['text', 'text_2', 'text_3', "seq_len"],
list(main_program.global_block().vars.keys()))
prefix_name = "@HUB_{}@".format(self.name)
add_vars_prefix(program=main_program, prefix=prefix_name, vars=variable_names)
for param in main_program.global_block().iter_parameters():
param.trainable = trainable
place = fluid.CPUPlace()
exe = fluid.Executor(place)
# Load the senta_lstm pretrained model.
def if_exist(var):
return os.path.exists(os.path.join(self.pretrained_model_path, var.name))
fluid.io.load_vars(exe, self.pretrained_model_path, predicate=if_exist)
inputs = {'seq_len': seq_len}
outputs = {
"class_probs": main_program.global_block().vars[prefix_name + pred_name],
"sentence_feature": main_program.global_block().vars[prefix_name + fc_name]
}
for index, data in enumerate(data_list):
if index == 0:
inputs['text'] = data
outputs['emb'] = main_program.global_block().vars[prefix_name + emb_name_list[0]]
else:
inputs['text_%s' % (index + 1)] = data
outputs['emb_%s' % (index + 1)] = main_program.global_block().vars[prefix_name +
emb_name_list[index]]
return inputs, outputs, main_program
@serving @serving
def sentiment_classify(self, texts=[], data={}, use_gpu=False, batch_size=1): def sentiment_classify(self, texts=[], data={}, use_gpu=False, batch_size=1):
""" """
...@@ -212,27 +108,3 @@ class SentaBiLSTM(hub.NLPPredictionModule): ...@@ -212,27 +108,3 @@ class SentaBiLSTM(hub.NLPPredictionModule):
""" """
self.labels = {"positive": 1, "negative": 0} self.labels = {"positive": 1, "negative": 0}
return self.labels return self.labels
if __name__ == "__main__":
senta = SentaBiLSTM()
inputs, outputs, main_program = senta.context(num_slots=3)
print(inputs)
print(outputs)
# Data to be predicted
test_text = ["这家餐厅很好吃", "这部电影真的很差劲"]
# execute predict and print the result
input_dict = {"text": test_text}
results = senta.sentiment_classify(data=input_dict, batch_size=3)
for index, result in enumerate(results):
if six.PY2:
print(json.dumps(results[index], encoding="utf8", ensure_ascii=False))
else:
print(results[index])
results = senta.sentiment_classify(texts=test_text)
for index, result in enumerate(results):
if six.PY2:
print(json.dumps(results[index], encoding="utf8", ensure_ascii=False))
else:
print(results[index])
# -*- coding:utf-8 -*-
import paddle.fluid as fluid
def bilstm_net(emb, seq_len, emb_dim=128, hid_dim=128, hid_dim2=96, class_dim=2, emb_lr=30.0):
"""
Bi-Lstm net
"""
# unpad the token_feature
unpad_feature = fluid.layers.sequence_unpad(emb, length=seq_len)
# bi-lstm layer
fc0 = fluid.layers.fc(input=unpad_feature, size=hid_dim * 4)
rfc0 = fluid.layers.fc(input=unpad_feature, size=hid_dim * 4)
lstm_h, c = fluid.layers.dynamic_lstm(input=fc0, size=hid_dim * 4, is_reverse=False)
rlstm_h, c = fluid.layers.dynamic_lstm(input=rfc0, size=hid_dim * 4, is_reverse=True)
# extract last layer
lstm_last = fluid.layers.sequence_last_step(input=lstm_h)
rlstm_last = fluid.layers.sequence_last_step(input=rlstm_h)
lstm_last_tanh = fluid.layers.tanh(lstm_last)
rlstm_last_tanh = fluid.layers.tanh(rlstm_last)
# concat layer
lstm_concat = fluid.layers.concat(input=[lstm_last, rlstm_last], axis=1)
# full connect layer
fc1 = fluid.layers.fc(input=lstm_concat, size=hid_dim2, act='tanh')
# softmax layer
prediction = fluid.layers.fc(input=fc1, size=class_dim, act='softmax')
return prediction, fc1
# senta_bow # senta_bow
|模型名称|senta_bow| |模型名称|senta_bow|
| :--- | :---: | | :--- | :---: |
|类别|文本-情感分析| |类别|文本-情感分析|
|网络|BOW| |网络|BOW|
|数据集|百度自建数据集| |数据集|百度自建数据集|
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
- ### 1、环境依赖 - ### 1、环境依赖
- paddlepaddle >= 1.8.0 - paddlepaddle >= 1.8.0
- paddlehub >= 1.8.0 | [如何安装PaddleHub](../../../../docs/docs_ch/get_start/installation.rst) - paddlehub >= 1.8.0 | [如何安装PaddleHub](../../../../docs/docs_ch/get_start/installation.rst)
- ### 2、安装 - ### 2、安装
...@@ -52,9 +52,9 @@ ...@@ -52,9 +52,9 @@
``` ```
- test.txt 存放待预测文本, 如: - test.txt 存放待预测文本, 如:
> 这家餐厅很好吃 > 这家餐厅很好吃
> 这部电影真的很差劲 > 这部电影真的很差劲
- 通过命令行方式实现文字识别模型的调用,更多请见 [PaddleHub命令行指令](../../../../docs/docs_ch/tutorial/cmd_usage.rst) - 通过命令行方式实现文字识别模型的调用,更多请见 [PaddleHub命令行指令](../../../../docs/docs_ch/tutorial/cmd_usage.rst)
- ### 2、预测代码示例 - ### 2、预测代码示例
...@@ -73,12 +73,12 @@ ...@@ -73,12 +73,12 @@
print(result['sentiment_key']) print(result['sentiment_key'])
print(result['positive_probs']) print(result['positive_probs'])
print(result['negative_probs']) print(result['negative_probs'])
# 这家餐厅很好吃 1 positive 0.9782 0.0218 # 这家餐厅很好吃 1 positive 0.9782 0.0218
# 这部电影真的很差劲 0 negative 0.0124 0.9876 # 这部电影真的很差劲 0 negative 0.0124 0.9876
``` ```
- ### 3、API - ### 3、API
- ```python - ```python
...@@ -175,7 +175,7 @@ ...@@ -175,7 +175,7 @@
* 1.0.0 * 1.0.0
初始发布 初始发布
* 1.0.1 * 1.0.1
词汇表升级 词汇表升级
...@@ -187,7 +187,11 @@ ...@@ -187,7 +187,11 @@
* 1.2.0 * 1.2.0
模型升级,支持用于文本分类,文本匹配等各种任务迁移学习 模型升级,支持用于文本分类,文本匹配等各种任务迁移学习
* 1.2.1
移除 fluid api
- ```shell - ```shell
$ hub install senta_bow==1.2.0 $ hub install senta_bow==1.2.1
``` ```
...@@ -6,25 +6,26 @@ from __future__ import print_function ...@@ -6,25 +6,26 @@ from __future__ import print_function
import json import json
import math import math
import os import os
import six import six
from senta_bow.processor import load_vocab
from senta_bow.processor import postprocess
from senta_bow.processor import preprocess
import paddle.fluid as fluid
import paddlehub as hub import paddlehub as hub
from paddlehub.common.paddle_helper import add_vars_prefix from paddlehub.common.paddle_helper import add_vars_prefix
from paddlehub.module.module import serving, moduleinfo from paddlehub.module.module import moduleinfo
from paddlehub.module.module import serving
from senta_bow.net import bow_net
from senta_bow.processor import load_vocab, preprocess, postprocess
@moduleinfo( @moduleinfo(name="senta_bow",
name="senta_bow", version="1.2.1",
version="1.2.0", summary="Baidu's open-source Sentiment Classification System.",
summary="Baidu's open-source Sentiment Classification System.", author="baidu-nlp",
author="baidu-nlp", author_email="",
author_email="", type="nlp/sentiment_analysis")
type="nlp/sentiment_analysis")
class SentaBow(hub.NLPPredictionModule): class SentaBow(hub.NLPPredictionModule):
def _initialize(self): def _initialize(self):
""" """
initialize with the necessary elements initialize with the necessary elements
...@@ -47,111 +48,6 @@ class SentaBow(hub.NLPPredictionModule): ...@@ -47,111 +48,6 @@ class SentaBow(hub.NLPPredictionModule):
self._word_seg_module = hub.Module(name="lac") self._word_seg_module = hub.Module(name="lac")
return self._word_seg_module return self._word_seg_module
def context(self, trainable=False, max_seq_len=128, num_slots=1):
"""
Get the input ,output and program of the pretrained senta_bow
Args:
trainable(bool): Whether fine-tune the pretrained parameters of senta_bow or not.
max_seq_len (int): It will limit the total sequence returned so that it has a maximum length.
num_slots(int): It's number of data inputted to the model, selectted as following options:
- 1(default): There's only one data to be feeded in the model, e.g. the module is used for text classification task.
- 2: There are two data to be feeded in the model, e.g. the module is used for text matching task (point-wise).
- 3: There are three data to be feeded in the model, e.g. the module is used for text matching task (pair-wise).
Returns:
inputs(dict): the input variables of senta_bow (words)
outputs(dict): the output variables of input words (word embeddings and label probilities);
the sentence embedding and sequence length of the first input text.
main_program(Program): the main_program of Senta with pretrained prameters
"""
assert num_slots >= 1 and num_slots <= 3, "num_slots must be 1, 2, or 3, but the input is %d" % num_slots
main_program = fluid.Program()
startup_program = fluid.Program()
with fluid.program_guard(main_program, startup_program):
text_1 = fluid.layers.data(name="text", shape=[-1, max_seq_len, 1], dtype="int64", lod_level=0)
seq_len = fluid.layers.data(name="seq_len", shape=[1], dtype='int64', lod_level=0)
seq_len_used = fluid.layers.squeeze(seq_len, axes=[1])
# Add embedding layer.
w_param_attrs = fluid.ParamAttr(
name="embedding_0.w_0", initializer=fluid.initializer.TruncatedNormal(scale=0.02), trainable=trainable)
dict_dim = 1256607
emb_1 = fluid.layers.embedding(
input=text_1,
size=[dict_dim, 128],
is_sparse=True,
padding_idx=dict_dim - 1,
dtype='float32',
param_attr=w_param_attrs)
emb_1_name = emb_1.name
data_list = [text_1]
emb_name_list = [emb_1_name]
# Add lstm layer.
pred, fc = bow_net(emb_1, seq_len_used)
pred_name = pred.name
fc_name = fc.name
if num_slots > 1:
text_2 = fluid.data(name='text_2', shape=[-1, max_seq_len], dtype='int64', lod_level=0)
emb_2 = fluid.embedding(
input=text_2,
size=[dict_dim, 128],
is_sparse=True,
padding_idx=dict_dim - 1,
dtype='float32',
param_attr=w_param_attrs)
emb_2_name = emb_2.name
data_list.append(text_2)
emb_name_list.append(emb_2_name)
if num_slots > 2:
text_3 = fluid.data(name='text_3', shape=[-1, max_seq_len], dtype='int64', lod_level=0)
emb_3 = fluid.embedding(
input=text_3,
size=[dict_dim, 128],
is_sparse=True,
padding_idx=dict_dim - 1,
dtype='float32',
param_attr=w_param_attrs)
emb_3_name = emb_3.name
data_list.append(text_3)
emb_name_list.append(emb_3_name)
variable_names = filter(lambda v: v not in ['text', 'text_2', 'text_3', "seq_len"],
list(main_program.global_block().vars.keys()))
prefix_name = "@HUB_{}@".format(self.name)
add_vars_prefix(program=main_program, prefix=prefix_name, vars=variable_names)
for param in main_program.global_block().iter_parameters():
param.trainable = trainable
place = fluid.CPUPlace()
exe = fluid.Executor(place)
# Load the senta_bow pretrained model.
def if_exist(var):
return os.path.exists(os.path.join(self.pretrained_model_path, var.name))
fluid.io.load_vars(exe, self.pretrained_model_path, predicate=if_exist)
inputs = {'seq_len': seq_len}
outputs = {
"class_probs": main_program.global_block().vars[prefix_name + pred_name],
"sentence_feature": main_program.global_block().vars[prefix_name + fc_name]
}
for index, data in enumerate(data_list):
if index == 0:
inputs['text'] = data
outputs['emb'] = main_program.global_block().vars[prefix_name + emb_name_list[0]]
else:
inputs['text_%s' % (index + 1)] = data
outputs['emb_%s' % (index + 1)] = main_program.global_block().vars[prefix_name +
emb_name_list[index]]
return inputs, outputs, main_program
@serving @serving
def sentiment_classify(self, texts=[], data={}, use_gpu=False, batch_size=1): def sentiment_classify(self, texts=[], data={}, use_gpu=False, batch_size=1):
""" """
...@@ -212,28 +108,3 @@ class SentaBow(hub.NLPPredictionModule): ...@@ -212,28 +108,3 @@ class SentaBow(hub.NLPPredictionModule):
""" """
self.labels = {"positive": 1, "negative": 0} self.labels = {"positive": 1, "negative": 0}
return self.labels return self.labels
if __name__ == "__main__":
senta = SentaBow()
inputs, outputs, main_program = senta.context(num_slots=3)
print(inputs)
print('*' * 20)
print(outputs)
# Data to be predicted
test_text = ["这家餐厅很好吃", "这部电影真的很差劲"]
# execute predict and print the result
input_dict = {"text": test_text}
results = senta.sentiment_classify(data=input_dict)
for index, result in enumerate(results):
if six.PY2:
print(json.dumps(results[index], encoding="utf8", ensure_ascii=False))
else:
print(results[index])
results = senta.sentiment_classify(texts=test_text)
for index, result in enumerate(results):
if six.PY2:
print(json.dumps(results[index], encoding="utf8", ensure_ascii=False))
else:
print(results[index])
# -*- coding:utf-8 -*-
import paddle.fluid as fluid
def bow_net(emb, seq_len, hid_dim=128, hid_dim2=96, class_dim=2):
"""
Bow net
"""
# unpad the token_feature
unpad_feature = fluid.layers.sequence_unpad(emb, length=seq_len)
# bow layer
bow = fluid.layers.sequence_pool(input=unpad_feature, pool_type='sum')
bow_tanh = fluid.layers.tanh(bow)
# full connect layer
fc_1 = fluid.layers.fc(input=bow_tanh, size=hid_dim, act="tanh")
fc_2 = fluid.layers.fc(input=fc_1, size=hid_dim2, act="tanh")
# softmax layer
prediction = fluid.layers.fc(input=[fc_2], size=class_dim, act="softmax")
return prediction, fc_2
# senta_cnn # senta_cnn
|模型名称|senta_cnn| |模型名称|senta_cnn|
| :--- | :---: | | :--- | :---: |
|类别|文本-情感分析| |类别|文本-情感分析|
|网络|CNN| |网络|CNN|
|数据集|百度自建数据集| |数据集|百度自建数据集|
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
- ### 1、环境依赖 - ### 1、环境依赖
- paddlepaddle >= 1.8.0 - paddlepaddle >= 1.8.0
- paddlehub >= 1.8.0 | [如何安装PaddleHub](../../../../docs/docs_ch/get_start/installation.rst) - paddlehub >= 1.8.0 | [如何安装PaddleHub](../../../../docs/docs_ch/get_start/installation.rst)
- ### 2、安装 - ### 2、安装
...@@ -47,9 +47,9 @@ ...@@ -47,9 +47,9 @@
``` ```
- test.txt 存放待预测文本, 如: - test.txt 存放待预测文本, 如:
> 这家餐厅很好吃 > 这家餐厅很好吃
> 这部电影真的很差劲 > 这部电影真的很差劲
- 通过命令行方式实现文字识别模型的调用,更多请见:[PaddleHub命令行指令](../../../../docs/docs_ch/tutorial/cmd_usage.rst) - 通过命令行方式实现文字识别模型的调用,更多请见:[PaddleHub命令行指令](../../../../docs/docs_ch/tutorial/cmd_usage.rst)
- ### 2、预测代码示例 - ### 2、预测代码示例
...@@ -59,17 +59,17 @@ ...@@ -59,17 +59,17 @@
senta = hub.Module(name="senta_cnn") senta = hub.Module(name="senta_cnn")
test_text = ["这家餐厅很好吃", "这部电影真的很差劲"] test_text = ["这家餐厅很好吃", "这部电影真的很差劲"]
results = senta.sentiment_classify(texts=test_text, results = senta.sentiment_classify(texts=test_text,
use_gpu=False, use_gpu=False,
batch_size=1) batch_size=1)
for result in results: for result in results:
print(result['text']) print(result['text'])
print(result['sentiment_label']) print(result['sentiment_label'])
print(result['sentiment_key']) print(result['sentiment_key'])
print(result['positive_probs']) print(result['positive_probs'])
print(result['negative_probs']) print(result['negative_probs'])
# 这家餐厅很好吃 1 positive 0.7902 0.2098 # 这家餐厅很好吃 1 positive 0.7902 0.2098
# 这部电影真的很差劲 0 negative 0.0343 0.9657 # 这部电影真的很差劲 0 negative 0.0343 0.9657
``` ```
...@@ -79,7 +79,7 @@ ...@@ -79,7 +79,7 @@
- ```python - ```python
def sentiment_classify(texts=[], data={}, use_gpu=False, batch_size=1) def sentiment_classify(texts=[], data={}, use_gpu=False, batch_size=1)
``` ```
- senta_cnn预测接口,预测输入句子的情感分类(二分类,积极/消极) - senta_cnn预测接口,预测输入句子的情感分类(二分类,积极/消极)
- **参数** - **参数**
...@@ -93,7 +93,7 @@ ...@@ -93,7 +93,7 @@
- results(list): 情感分类结果 - results(list): 情感分类结果
- ```python - ```python
def get_labels() def get_labels()
``` ```
...@@ -171,7 +171,7 @@ ...@@ -171,7 +171,7 @@
* 1.0.0 * 1.0.0
初始发布 初始发布
* 1.0.1 * 1.0.1
词汇表升级 词汇表升级
...@@ -183,7 +183,11 @@ ...@@ -183,7 +183,11 @@
* 1.2.0 * 1.2.0
模型升级,支持用于文本分类,文本匹配等各种任务迁移学习 模型升级,支持用于文本分类,文本匹配等各种任务迁移学习
* 1.2.1
移除 fluid api
- ```shell - ```shell
$ hub install senta_cnn==1.2.0 $ hub install senta_cnn==1.2.1
``` ```
...@@ -6,25 +6,26 @@ from __future__ import print_function ...@@ -6,25 +6,26 @@ from __future__ import print_function
import json import json
import math import math
import os import os
import six import six
from senta_cnn.processor import load_vocab
from senta_cnn.processor import postprocess
from senta_cnn.processor import preprocess
import paddle.fluid as fluid
import paddlehub as hub import paddlehub as hub
from paddlehub.common.paddle_helper import add_vars_prefix from paddlehub.common.paddle_helper import add_vars_prefix
from paddlehub.module.module import moduleinfo, serving from paddlehub.module.module import moduleinfo
from paddlehub.module.module import serving
from senta_cnn.net import cnn_net
from senta_cnn.processor import load_vocab, preprocess, postprocess
@moduleinfo( @moduleinfo(name="senta_cnn",
name="senta_cnn", version="1.2.1",
version="1.2.0", summary="Baidu's open-source Sentiment Classification System.",
summary="Baidu's open-source Sentiment Classification System.", author="baidu-nlp",
author="baidu-nlp", author_email="",
author_email="", type="nlp/sentiment_analysis")
type="nlp/sentiment_analysis")
class SentaCNN(hub.NLPPredictionModule): class SentaCNN(hub.NLPPredictionModule):
def _initialize(self, user_dict=None): def _initialize(self, user_dict=None):
""" """
initialize with the necessary elements initialize with the necessary elements
...@@ -47,104 +48,6 @@ class SentaCNN(hub.NLPPredictionModule): ...@@ -47,104 +48,6 @@ class SentaCNN(hub.NLPPredictionModule):
self._word_seg_module = hub.Module(name="lac") self._word_seg_module = hub.Module(name="lac")
return self._word_seg_module return self._word_seg_module
def context(self, trainable=False, max_seq_len=128, num_slots=1):
"""
Get the input ,output and program of the pretrained senta_cnn
Args:
trainable(bool): Whether fine-tune the pretrained parameters of senta_cnn or not.
max_seq_len (int): It will limit the total sequence returned so that it has a maximum length.
num_slots(int): It's number of data inputted to the model, selectted as following options:
- 1(default): There's only one data to be feeded in the model, e.g. the module is used for text classification task.
- 2: There are two data to be feeded in the model, e.g. the module is used for text matching task (point-wise).
- 3: There are three data to be feeded in the model, e.g. the module is used for text matching task (pair-wise).
Returns:
inputs(dict): the input variables of senta_cnn (words)
outputs(dict): the output variables of input words (word embeddings and label probilities);
the sentence embedding and sequence length of the first input text.
main_program(Program): the main_program of Senta with pretrained prameters
"""
assert num_slots >= 1 and num_slots <= 3, "num_slots must be 1, 2, or 3, but the input is %d" % num_slots
main_program = fluid.Program()
startup_program = fluid.Program()
with fluid.program_guard(main_program, startup_program):
text_1 = fluid.layers.data(name="text", shape=[-1, max_seq_len, 1], dtype="int64", lod_level=0)
seq_len = fluid.layers.data(name="seq_len", shape=[1], dtype='int64', lod_level=0)
seq_len_used = fluid.layers.squeeze(seq_len, axes=[1])
# Add embedding layer.
w_param_attrs = fluid.ParamAttr(
name="embedding_0.w_0", initializer=fluid.initializer.TruncatedNormal(scale=0.02), trainable=trainable)
dict_dim = 1256607
emb_1 = fluid.layers.embedding(
input=text_1, size=[dict_dim, 128], padding_idx=dict_dim - 1, dtype='float32', param_attr=w_param_attrs)
emb_1_name = emb_1.name
data_list = [text_1]
emb_name_list = [emb_1_name]
# Add lstm layer.
pred, fc = cnn_net(emb_1, seq_len_used)
pred_name = pred.name
fc_name = fc.name
if num_slots > 1:
text_2 = fluid.data(name='text_2', shape=[-1, max_seq_len], dtype='int64', lod_level=0)
emb_2 = fluid.embedding(
input=text_2,
size=[dict_dim, 128],
padding_idx=dict_dim - 1,
dtype='float32',
param_attr=w_param_attrs)
emb_2_name = emb_2.name
data_list.append(text_2)
emb_name_list.append(emb_2_name)
if num_slots > 2:
text_3 = fluid.data(name='text_3', shape=[-1, max_seq_len], dtype='int64', lod_level=0)
emb_3 = fluid.embedding(
input=text_3,
size=[dict_dim, 128],
padding_idx=dict_dim - 1,
dtype='float32',
param_attr=w_param_attrs)
emb_3_name = emb_3.name
data_list.append(text_3)
emb_name_list.append(emb_3_name)
variable_names = filter(lambda v: v not in ['text', 'text_2', 'text_3', "seq_len"],
list(main_program.global_block().vars.keys()))
prefix_name = "@HUB_{}@".format(self.name)
add_vars_prefix(program=main_program, prefix=prefix_name, vars=variable_names)
for param in main_program.global_block().iter_parameters():
param.trainable = trainable
place = fluid.CPUPlace()
exe = fluid.Executor(place)
# Load the senta_lstm pretrained model.
def if_exist(var):
return os.path.exists(os.path.join(self.pretrained_model_path, var.name))
fluid.io.load_vars(exe, self.pretrained_model_path, predicate=if_exist)
inputs = {'seq_len': seq_len}
outputs = {
"class_probs": main_program.global_block().vars[prefix_name + pred_name],
"sentence_feature": main_program.global_block().vars[prefix_name + fc_name]
}
for index, data in enumerate(data_list):
if index == 0:
inputs['text'] = data
outputs['emb'] = main_program.global_block().vars[prefix_name + emb_name_list[0]]
else:
inputs['text_%s' % (index + 1)] = data
outputs['emb_%s' % (index + 1)] = main_program.global_block().vars[prefix_name +
emb_name_list[index]]
return inputs, outputs, main_program
@serving @serving
def sentiment_classify(self, texts=[], data={}, use_gpu=False, batch_size=1): def sentiment_classify(self, texts=[], data={}, use_gpu=False, batch_size=1):
""" """
...@@ -205,25 +108,3 @@ class SentaCNN(hub.NLPPredictionModule): ...@@ -205,25 +108,3 @@ class SentaCNN(hub.NLPPredictionModule):
""" """
self.labels = {"positive": 1, "negative": 0} self.labels = {"positive": 1, "negative": 0}
return self.labels return self.labels
if __name__ == "__main__":
senta = SentaCNN()
inputs, outputs, program = senta.context(num_slots=3)
# Data to be predicted
test_text = ["这家餐厅很好吃", "这部电影真的很差劲"]
# execute predict and print the result
input_dict = {"text": test_text}
results = senta.sentiment_classify(data=input_dict)
for index, result in enumerate(results):
if six.PY2:
print(json.dumps(results[index], encoding="utf8", ensure_ascii=False))
else:
print(results[index])
results = senta.sentiment_classify(texts=test_text)
for index, result in enumerate(results):
if six.PY2:
print(json.dumps(results[index], encoding="utf8", ensure_ascii=False))
else:
print(results[index])
# -*- coding:utf-8 -*-
import paddle.fluid as fluid
def cnn_net(emb, seq_len, hid_dim=128, hid_dim2=96, class_dim=2, win_size=3):
"""
Conv net
"""
# unpad the token_feature
unpad_feature = fluid.layers.sequence_unpad(emb, length=seq_len)
# convolution layer
conv_3 = fluid.nets.sequence_conv_pool(
input=unpad_feature, num_filters=hid_dim, filter_size=win_size, act="tanh", pool_type="max")
# full connect layer
fc_1 = fluid.layers.fc(input=[conv_3], size=hid_dim2)
# softmax layer
prediction = fluid.layers.fc(input=[fc_1], size=class_dim, act="softmax")
return prediction, fc_1
# senta_gru # senta_gru
|模型名称|senta_gru| |模型名称|senta_gru|
| :--- | :---: | | :--- | :---: |
|类别|文本-情感分析| |类别|文本-情感分析|
|网络|GRU| |网络|GRU|
|数据集|百度自建数据集| |数据集|百度自建数据集|
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
- ### 1、环境依赖 - ### 1、环境依赖
- paddlepaddle >= 1.8.0 - paddlepaddle >= 1.8.0
- paddlehub >= 1.8.0 | [如何安装PaddleHub](../../../../docs/docs_ch/get_start/installation.rst) - paddlehub >= 1.8.0 | [如何安装PaddleHub](../../../../docs/docs_ch/get_start/installation.rst)
- ### 2、安装 - ### 2、安装
...@@ -51,9 +51,9 @@ ...@@ -51,9 +51,9 @@
``` ```
- test.txt 存放待预测文本, 如: - test.txt 存放待预测文本, 如:
> 这家餐厅很好吃 > 这家餐厅很好吃
> 这部电影真的很差劲 > 这部电影真的很差劲
- 通过命令行方式实现文字识别模型的调用,更多请见 [PaddleHub命令行指令](../../../../docs/docs_ch/tutorial/cmd_usage.rst) - 通过命令行方式实现文字识别模型的调用,更多请见 [PaddleHub命令行指令](../../../../docs/docs_ch/tutorial/cmd_usage.rst)
- ### 2、预测代码示例 - ### 2、预测代码示例
...@@ -75,7 +75,7 @@ ...@@ -75,7 +75,7 @@
# 这家餐厅很好吃 1 positive 0.9607 0.0393 # 这家餐厅很好吃 1 positive 0.9607 0.0393
# 这部电影真的很差劲 0 negative 0.0187 0.9813 # 这部电影真的很差劲 0 negative 0.0187 0.9813
``` ```
- ### 3、API - ### 3、API
- ```python - ```python
...@@ -94,7 +94,7 @@ ...@@ -94,7 +94,7 @@
- results(list): 情感分类结果 - results(list): 情感分类结果
- ```python - ```python
def get_labels() def get_labels()
``` ```
...@@ -147,7 +147,7 @@ ...@@ -147,7 +147,7 @@
# 待预测数据 # 待预测数据
text = ["这家餐厅很好吃", "这部电影真的很差劲"] text = ["这家餐厅很好吃", "这部电影真的很差劲"]
# 设置运行配置 # 设置运行配置
# 对应本地预测senta_gru.sentiment_classify(texts=text, batch_size=1, use_gpu=True) # 对应本地预测senta_gru.sentiment_classify(texts=text, batch_size=1, use_gpu=True)
data = {"texts": text, "batch_size": 1, "use_gpu":True} data = {"texts": text, "batch_size": 1, "use_gpu":True}
...@@ -157,7 +157,7 @@ ...@@ -157,7 +157,7 @@
url = "http://HOST_IP:8866/predict/senta_gru" url = "http://HOST_IP:8866/predict/senta_gru"
headers = {"Content-Type": "application/json"} headers = {"Content-Type": "application/json"}
r = requests.post(url=url, headers=headers, data=json.dumps(data)) r = requests.post(url=url, headers=headers, data=json.dumps(data))
# 打印预测结果 # 打印预测结果
print(json.dumps(r.json(), indent=4, ensure_ascii=False)) print(json.dumps(r.json(), indent=4, ensure_ascii=False))
``` ```
...@@ -181,7 +181,11 @@ ...@@ -181,7 +181,11 @@
* 1.2.0 * 1.2.0
模型升级,支持用于文本分类,文本匹配等各种任务迁移学习 模型升级,支持用于文本分类,文本匹配等各种任务迁移学习
* 1.2.1
移除 fluid api
- ```shell - ```shell
$ hub install senta_gru==1.2.0 $ hub install senta_gru==1.2.1
``` ```
...@@ -6,25 +6,26 @@ from __future__ import print_function ...@@ -6,25 +6,26 @@ from __future__ import print_function
import json import json
import math import math
import os import os
import six import six
from senta_gru.processor import load_vocab
from senta_gru.processor import postprocess
from senta_gru.processor import preprocess
import paddle.fluid as fluid
import paddlehub as hub import paddlehub as hub
from paddlehub.common.paddle_helper import add_vars_prefix from paddlehub.common.paddle_helper import add_vars_prefix
from paddlehub.module.module import moduleinfo, serving from paddlehub.module.module import moduleinfo
from paddlehub.module.module import serving
from senta_gru.net import gru_net
from senta_gru.processor import load_vocab, preprocess, postprocess
@moduleinfo( @moduleinfo(name="senta_gru",
name="senta_gru", version="1.2.1",
version="1.2.0", summary="Baidu's open-source Sentiment Classification System.",
summary="Baidu's open-source Sentiment Classification System.", author="baidu-nlp",
author="baidu-nlp", author_email="",
author_email="", type="nlp/sentiment_analysis")
type="nlp/sentiment_analysis")
class SentaGRU(hub.NLPPredictionModule): class SentaGRU(hub.NLPPredictionModule):
def _initialize(self, user_dict=None): def _initialize(self, user_dict=None):
""" """
initialize with the necessary elements initialize with the necessary elements
...@@ -47,104 +48,6 @@ class SentaGRU(hub.NLPPredictionModule): ...@@ -47,104 +48,6 @@ class SentaGRU(hub.NLPPredictionModule):
self._word_seg_module = hub.Module(name="lac") self._word_seg_module = hub.Module(name="lac")
return self._word_seg_module return self._word_seg_module
def context(self, trainable=False, max_seq_len=128, num_data=1):
"""
Get the input ,output and program of the pretrained senta_gru
Args:
trainable(bool): Whether fine-tune the pretrained parameters of senta_gru or not.
max_seq_len (int): It will limit the total sequence returned so that it has a maximum length.
num_data(int): It's number of data inputted to the model, selectted as following options:
- 1(default): There's only one data to be feeded in the model, e.g. the module is used for text classification task.
- 2: There are two data to be feeded in the model, e.g. the module is used for text matching task (point-wise).
- 3: There are three data to be feeded in the model, e.g. the module is used for text matching task (pair-wise).
Returns:
inputs(dict): the input variables of senta_gru (words)
outputs(dict): the output variables of input words (word embeddings and label probilities);
the sentence embedding and sequence length of the first input text.
main_program(Program): the main_program of Senta with pretrained prameters
"""
assert num_data >= 1 and num_data <= 3, "num_data(%d) must be 1, 2, or 3" % num_data
main_program = fluid.Program()
startup_program = fluid.Program()
with fluid.program_guard(main_program, startup_program):
text_1 = fluid.layers.data(name="text", shape=[-1, max_seq_len, 1], dtype="int64", lod_level=0)
seq_len = fluid.layers.data(name="seq_len", shape=[1], dtype='int64', lod_level=0)
seq_len_used = fluid.layers.squeeze(seq_len, axes=[1])
# Add embedding layer.
w_param_attrs = fluid.ParamAttr(
name="embedding_0.w_0", initializer=fluid.initializer.TruncatedNormal(scale=0.02), trainable=trainable)
dict_dim = 1256607
emb_1 = fluid.layers.embedding(
input=text_1, size=[dict_dim, 128], padding_idx=dict_dim - 1, dtype='float32', param_attr=w_param_attrs)
emb_1_name = emb_1.name
data_list = [text_1]
emb_name_list = [emb_1_name]
# Add lstm layer.
pred, fc = gru_net(emb_1, seq_len_used)
pred_name = pred.name
fc_name = fc.name
if num_data > 1:
text_2 = fluid.data(name='text_2', shape=[-1, max_seq_len], dtype='int64', lod_level=0)
emb_2 = fluid.embedding(
input=text_2,
size=[dict_dim, 128],
padding_idx=dict_dim - 1,
dtype='float32',
param_attr=w_param_attrs)
emb_2_name = emb_2.name
data_list.append(text_2)
emb_name_list.append(emb_2_name)
if num_data > 2:
text_3 = fluid.data(name='text_3', shape=[-1, max_seq_len], dtype='int64', lod_level=0)
emb_3 = fluid.embedding(
input=text_3,
size=[dict_dim, 128],
padding_idx=dict_dim - 1,
dtype='float32',
param_attr=w_param_attrs)
emb_3_name = emb_3.name
data_list.append(text_3)
emb_name_list.append(emb_3_name)
variable_names = filter(lambda v: v not in ['text', 'text_2', 'text_3', "seq_len"],
list(main_program.global_block().vars.keys()))
prefix_name = "@HUB_{}@".format(self.name)
add_vars_prefix(program=main_program, prefix=prefix_name, vars=variable_names)
for param in main_program.global_block().iter_parameters():
param.trainable = trainable
place = fluid.CPUPlace()
exe = fluid.Executor(place)
# Load the senta_lstm pretrained model.
def if_exist(var):
return os.path.exists(os.path.join(self.pretrained_model_path, var.name))
fluid.io.load_vars(exe, self.pretrained_model_path, predicate=if_exist)
inputs = {'seq_len': seq_len}
outputs = {
"class_probs": main_program.global_block().vars[prefix_name + pred_name],
"sentence_feature": main_program.global_block().vars[prefix_name + fc_name]
}
for index, data in enumerate(data_list):
if index == 0:
inputs['text'] = data
outputs['emb'] = main_program.global_block().vars[prefix_name + emb_name_list[0]]
else:
inputs['text_%s' % (index + 1)] = data
outputs['emb_%s' % (index + 1)] = main_program.global_block().vars[prefix_name +
emb_name_list[index]]
return inputs, outputs, main_program
@serving @serving
def sentiment_classify(self, texts=[], data={}, use_gpu=False, batch_size=1): def sentiment_classify(self, texts=[], data={}, use_gpu=False, batch_size=1):
""" """
...@@ -205,25 +108,3 @@ class SentaGRU(hub.NLPPredictionModule): ...@@ -205,25 +108,3 @@ class SentaGRU(hub.NLPPredictionModule):
""" """
self.labels = {"positive": 1, "negative": 0} self.labels = {"positive": 1, "negative": 0}
return self.labels return self.labels
if __name__ == "__main__":
senta = SentaGRU()
inputs, outputs, main_program = senta.context(num_slots=3)
# Data to be predicted
test_text = ["这家餐厅很好吃", "这部电影真的很差劲"]
# execute predict and print the result
input_dict = {"text": test_text}
results = senta.sentiment_classify(data=input_dict)
for index, result in enumerate(results):
if six.PY2:
print(json.dumps(results[index], encoding="utf8", ensure_ascii=False))
else:
print(results[index])
results = senta.sentiment_classify(texts=test_text)
for index, result in enumerate(results):
if six.PY2:
print(json.dumps(results[index], encoding="utf8", ensure_ascii=False))
else:
print(results[index])
# -*- coding:utf-8 -*-
import paddle.fluid as fluid
def gru_net(emb, seq_len, emb_dim=128, hid_dim=128, hid_dim2=96, class_dim=2, emb_lr=30.0):
"""
gru net
"""
# unpad the token_feature
unpad_feature = fluid.layers.sequence_unpad(emb, length=seq_len)
fc0 = fluid.layers.fc(input=unpad_feature, size=hid_dim * 3)
# GRU layer
gru_h = fluid.layers.dynamic_gru(input=fc0, size=hid_dim, is_reverse=False)
gru_max = fluid.layers.sequence_pool(input=gru_h, pool_type='max')
gru_max_tanh = fluid.layers.tanh(gru_max)
# full connect layer
fc1 = fluid.layers.fc(input=gru_max_tanh, size=hid_dim2, act='tanh')
# softmax layer
prediction = fluid.layers.fc(input=fc1, size=class_dim, act='softmax')
return prediction, fc1
# senta_lstm # senta_lstm
|模型名称|senta_lstm| |模型名称|senta_lstm|
| :--- | :---: | | :--- | :---: |
|类别|文本-情感分析| |类别|文本-情感分析|
|网络|LSTM| |网络|LSTM|
|数据集|百度自建数据集| |数据集|百度自建数据集|
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
- ### 1、环境依赖 - ### 1、环境依赖
- paddlepaddle >= 1.8.0 - paddlepaddle >= 1.8.0
- paddlehub >= 1.8.0 | [如何安装PaddleHub](../../../../docs/docs_ch/get_start/installation.rst) - paddlehub >= 1.8.0 | [如何安装PaddleHub](../../../../docs/docs_ch/get_start/installation.rst)
- ### 2、安装 - ### 2、安装
...@@ -48,9 +48,9 @@ ...@@ -48,9 +48,9 @@
``` ```
- test.txt 存放待预测文本, 如: - test.txt 存放待预测文本, 如:
> 这家餐厅很好吃 > 这家餐厅很好吃
> 这部电影真的很差劲 > 这部电影真的很差劲
- 通过命令行方式实现文字识别模型的调用,更多请见 [PaddleHub命令行指令](../../../../docs/docs_ch/tutorial/cmd_usage.rst) - 通过命令行方式实现文字识别模型的调用,更多请见 [PaddleHub命令行指令](../../../../docs/docs_ch/tutorial/cmd_usage.rst)
- ### 2、预测代码示例 - ### 2、预测代码示例
...@@ -60,17 +60,17 @@ ...@@ -60,17 +60,17 @@
senta = hub.Module(name="senta_lstm") senta = hub.Module(name="senta_lstm")
test_text = ["这家餐厅很好吃", "这部电影真的很差劲"] test_text = ["这家餐厅很好吃", "这部电影真的很差劲"]
results = senta.sentiment_classify(texts=test_text, results = senta.sentiment_classify(texts=test_text,
use_gpu=False, use_gpu=False,
batch_size=1) batch_size=1)
for result in results: for result in results:
print(result['text']) print(result['text'])
print(result['sentiment_label']) print(result['sentiment_label'])
print(result['sentiment_key']) print(result['sentiment_key'])
print(result['positive_probs']) print(result['positive_probs'])
print(result['negative_probs']) print(result['negative_probs'])
# 这家餐厅很好吃 1 positive 0.9285 0.0715 # 这家餐厅很好吃 1 positive 0.9285 0.0715
# 这部电影真的很差劲 0 negative 0.0187 0.9813 # 这部电影真的很差劲 0 negative 0.0187 0.9813
``` ```
...@@ -80,7 +80,7 @@ ...@@ -80,7 +80,7 @@
- ```python - ```python
sentiment_classify(texts=[], data={}, use_gpu=False, batch_size=1) sentiment_classify(texts=[], data={}, use_gpu=False, batch_size=1)
``` ```
- senta_lstm预测接口,预测输入句子的情感分类(二分类,积极/消极) - senta_lstm预测接口,预测输入句子的情感分类(二分类,积极/消极)
- **参数** - **参数**
...@@ -107,7 +107,7 @@ ...@@ -107,7 +107,7 @@
- ```python - ```python
get_vocab_path() get_vocab_path()
``` ```
- 获取预训练时使用的词汇表 - 获取预训练时使用的词汇表
- **返回** - **返回**
...@@ -171,15 +171,19 @@ ...@@ -171,15 +171,19 @@
* 1.0.1 * 1.0.1
词汇表升级 词汇表升级
* 1.1.0 * 1.1.0
大幅提升预测性能 大幅提升预测性能
* 1.2.0 * 1.2.0
模型升级,支持用于文本分类,文本匹配等各种任务迁移学习 模型升级,支持用于文本分类,文本匹配等各种任务迁移学习
* 1.2.1
移除 fluid api
- ```shell - ```shell
$ hub install senta_lstm==1.2.0 $ hub install senta_lstm==1.2.1
``` ```
...@@ -6,25 +6,26 @@ from __future__ import print_function ...@@ -6,25 +6,26 @@ from __future__ import print_function
import json import json
import math import math
import os import os
import six import six
from senta_lstm.processor import load_vocab
from senta_lstm.processor import postprocess
from senta_lstm.processor import preprocess
import paddle.fluid as fluid
import paddlehub as hub import paddlehub as hub
from paddlehub.common.paddle_helper import add_vars_prefix from paddlehub.common.paddle_helper import add_vars_prefix
from paddlehub.module.module import moduleinfo, serving from paddlehub.module.module import moduleinfo
from paddlehub.module.module import serving
from senta_lstm.net import lstm_net
from senta_lstm.processor import load_vocab, preprocess, postprocess
@moduleinfo( @moduleinfo(name="senta_lstm",
name="senta_lstm", version="1.2.1",
version="1.2.0", summary="Baidu's open-source Sentiment Classification System.",
summary="Baidu's open-source Sentiment Classification System.", author="baidu-nlp",
author="baidu-nlp", author_email="",
author_email="", type="nlp/sentiment_analysis")
type="nlp/sentiment_analysis")
class SentaLSTM(hub.NLPPredictionModule): class SentaLSTM(hub.NLPPredictionModule):
def _initialize(self, user_dict=None): def _initialize(self, user_dict=None):
""" """
initialize with the necessary elements initialize with the necessary elements
...@@ -47,104 +48,6 @@ class SentaLSTM(hub.NLPPredictionModule): ...@@ -47,104 +48,6 @@ class SentaLSTM(hub.NLPPredictionModule):
self._word_seg_module = hub.Module(name="lac") self._word_seg_module = hub.Module(name="lac")
return self._word_seg_module return self._word_seg_module
def context(self, trainable=False, max_seq_len=128, num_slots=1):
"""
Get the input ,output and program of the pretrained senta_lstm
Args:
trainable(bool): Whether fine-tune the pretrained parameters of senta_lstm or not.
max_seq_len (int): It will limit the total sequence returned so that it has a maximum length.
num_slots(int): It's number of data inputted to the model, selectted as following options:
- 1(default): There's only one data to be feeded in the model, e.g. the module is used for text classification task.
- 2: There are two data to be feeded in the model, e.g. the module is used for text matching task (point-wise).
- 3: There are three data to be feeded in the model, e.g. the module is used for text matching task (pair-wise).
Returns:
inputs(dict): the input variables of senta_lstm (words)
outputs(dict): the output variables of input words (word embeddings and label probilities);
the sentence embedding and sequence length of the first input text.
main_program(Program): the main_program of Senta with pretrained prameters
"""
assert num_slots >= 1 and num_slots <= 3, "num_slots must be 1, 2, or 3, but the input is %d" % num_slots
main_program = fluid.Program()
startup_program = fluid.Program()
with fluid.program_guard(main_program, startup_program):
text_1 = fluid.layers.data(name="text", shape=[-1, max_seq_len, 1], dtype="int64", lod_level=0)
seq_len = fluid.layers.data(name="seq_len", shape=[1], dtype='int64', lod_level=0)
seq_len_used = fluid.layers.squeeze(seq_len, axes=[1])
# Add embedding layer.
w_param_attrs = fluid.ParamAttr(
name="embedding_0.w_0", initializer=fluid.initializer.TruncatedNormal(scale=0.02), trainable=trainable)
dict_dim = 1256607
emb_1 = fluid.layers.embedding(
input=text_1, size=[dict_dim, 128], padding_idx=dict_dim - 1, dtype='float32', param_attr=w_param_attrs)
emb_1_name = emb_1.name
data_list = [text_1]
emb_name_list = [emb_1_name]
# Add lstm layer.
pred, fc = lstm_net(emb_1, seq_len_used)
pred_name = pred.name
fc_name = fc.name
if num_slots > 1:
text_2 = fluid.data(name='text_2', shape=[-1, max_seq_len], dtype='int64', lod_level=0)
emb_2 = fluid.embedding(
input=text_2,
size=[dict_dim, 128],
padding_idx=dict_dim - 1,
dtype='float32',
param_attr=w_param_attrs)
emb_2_name = emb_2.name
data_list.append(text_2)
emb_name_list.append(emb_2_name)
if num_slots > 2:
text_3 = fluid.data(name='text_3', shape=[-1, max_seq_len], dtype='int64', lod_level=0)
emb_3 = fluid.embedding(
input=text_3,
size=[dict_dim, 128],
padding_idx=dict_dim - 1,
dtype='float32',
param_attr=w_param_attrs)
emb_3_name = emb_3.name
data_list.append(text_3)
emb_name_list.append(emb_3_name)
variable_names = filter(lambda v: v not in ['text', 'text_2', 'text_3', "seq_len"],
list(main_program.global_block().vars.keys()))
prefix_name = "@HUB_{}@".format(self.name)
add_vars_prefix(program=main_program, prefix=prefix_name, vars=variable_names)
for param in main_program.global_block().iter_parameters():
param.trainable = trainable
place = fluid.CPUPlace()
exe = fluid.Executor(place)
# Load the senta_lstm pretrained model.
def if_exist(var):
return os.path.exists(os.path.join(self.pretrained_model_path, var.name))
fluid.io.load_vars(exe, self.pretrained_model_path, predicate=if_exist)
inputs = {'seq_len': seq_len}
outputs = {
"class_probs": main_program.global_block().vars[prefix_name + pred_name],
"sentence_feature": main_program.global_block().vars[prefix_name + fc_name]
}
for index, data in enumerate(data_list):
if index == 0:
inputs['text'] = data
outputs['emb'] = main_program.global_block().vars[prefix_name + emb_name_list[0]]
else:
inputs['text_%s' % (index + 1)] = data
outputs['emb_%s' % (index + 1)] = main_program.global_block().vars[prefix_name +
emb_name_list[index]]
return inputs, outputs, main_program
@serving @serving
def sentiment_classify(self, texts=[], data={}, use_gpu=False, batch_size=1): def sentiment_classify(self, texts=[], data={}, use_gpu=False, batch_size=1):
""" """
...@@ -205,20 +108,3 @@ class SentaLSTM(hub.NLPPredictionModule): ...@@ -205,20 +108,3 @@ class SentaLSTM(hub.NLPPredictionModule):
""" """
self.labels = {"positive": 1, "negative": 0} self.labels = {"positive": 1, "negative": 0}
return self.labels return self.labels
if __name__ == "__main__":
senta = SentaLSTM()
senta.context(num_slots=3)
# Data to be predicted
test_text = ["这家餐厅很好吃", "这部电影真的很差劲"]
# execute predict and print the result
input_dict = {"text": test_text}
results = senta.sentiment_classify(data=input_dict)
for index, result in enumerate(results):
if six.PY2:
print(json.dumps(results[index], encoding="utf8", ensure_ascii=False))
else:
print(results[index])
# -*- coding:utf-8 -*-
import paddle.fluid as fluid
def lstm_net(emb, seq_len, hid_dim=128, hid_dim2=96, class_dim=2, emb_lr=30.0):
"""
Lstm net
"""
# unpad the token_feature
unpad_feature = fluid.layers.sequence_unpad(emb, length=seq_len)
# Lstm layer
fc0 = fluid.layers.fc(input=unpad_feature, size=hid_dim * 4)
lstm_h, c = fluid.layers.dynamic_lstm(input=fc0, size=hid_dim * 4, is_reverse=False)
# max pooling layer
lstm_max = fluid.layers.sequence_pool(input=lstm_h, pool_type='max')
lstm_max_tanh = fluid.layers.tanh(lstm_max)
# full connect layer
fc1 = fluid.layers.fc(input=lstm_max_tanh, size=hid_dim2, act='tanh')
# softmax layer
prediction = fluid.layers.fc(input=fc1, size=class_dim, act='softmax')
return prediction, fc1
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
- ### 1、环境依赖 - ### 1、环境依赖
- paddlepaddle >= 1.6.2 - paddlepaddle >= 1.6.2
- paddlehub >= 1.6.0 | [如何安装PaddleHub](../../../../docs/docs_ch/get_start/installation.rst) - paddlehub >= 1.6.0 | [如何安装PaddleHub](../../../../docs/docs_ch/get_start/installation.rst)
- ### 2、安装 - ### 2、安装
...@@ -39,44 +39,44 @@ ...@@ -39,44 +39,44 @@
- ```shell - ```shell
$ hub run porn_detection_lstm --input_text "黄片下载" $ hub run porn_detection_lstm --input_text "黄片下载"
``` ```
- 或者 - 或者
- ```shell - ```shell
$ hub run porn_detection_lstm --input_file test.txt $ hub run porn_detection_lstm --input_file test.txt
``` ```
- 其中test.txt存放待审查文本,每行仅放置一段待审核文本 - 其中test.txt存放待审查文本,每行仅放置一段待审核文本
- 通过命令行方式实现hub模型的调用,更多请见 [PaddleHub命令行指令](../../../../docs/docs_ch/tutorial/cmd_usage.rst) - 通过命令行方式实现hub模型的调用,更多请见 [PaddleHub命令行指令](../../../../docs/docs_ch/tutorial/cmd_usage.rst)
- ### 2、预测代码示例 - ### 2、预测代码示例
- ```python - ```python
import paddlehub as hub import paddlehub as hub
porn_detection_lstm = hub.Module(name="porn_detection_lstm") porn_detection_lstm = hub.Module(name="porn_detection_lstm")
test_text = ["黄片下载", "打击黄牛党"] test_text = ["黄片下载", "打击黄牛党"]
results = porn_detection_lstm.detection(texts=test_text, use_gpu=True, batch_size=1) results = porn_detection_lstm.detection(texts=test_text, use_gpu=True, batch_size=1)
for index, text in enumerate(test_text): for index, text in enumerate(test_text):
results[index]["text"] = text results[index]["text"] = text
for index, result in enumerate(results): for index, result in enumerate(results):
print(results[index]) print(results[index])
# 输出结果如下: # 输出结果如下:
# {'text': '黄片下载', 'porn_detection_label': 1, 'porn_detection_key': 'porn', 'porn_probs': 0.9879, 'not_porn_probs': 0.0121} # {'text': '黄片下载', 'porn_detection_label': 1, 'porn_detection_key': 'porn', 'porn_probs': 0.9879, 'not_porn_probs': 0.0121}
# {'text': '打击黄牛党', 'porn_detection_label': 0, 'porn_detection_key': 'not_porn', 'porn_probs': 0.0004, 'not_porn_probs': 0.9996} # {'text': '打击黄牛党', 'porn_detection_label': 0, 'porn_detection_key': 'not_porn', 'porn_probs': 0.0004, 'not_porn_probs': 0.9996}
``` ```
- ### 3、API - ### 3、API
- ```python - ```python
def detection(texts=[], data={}, use_gpu=False, batch_size=1): def detection(texts=[], data={}, use_gpu=False, batch_size=1):
``` ```
- porn_detection_lstm预测接口,鉴定输入句子是否为黄文 - porn_detection_lstm预测接口,鉴定输入句子是否为黄文
- **参数** - **参数**
...@@ -84,36 +84,23 @@ ...@@ -84,36 +84,23 @@
- data(dict): 预测数据,key必须为text,value是带预测数据。如果使用data参数,则不用传入texts参数,二选一即可。建议使用texts参数,data参数后续会废弃。 - data(dict): 预测数据,key必须为text,value是带预测数据。如果使用data参数,则不用传入texts参数,二选一即可。建议使用texts参数,data参数后续会废弃。
- use_gpu(bool): 是否使用GPU预测 - use_gpu(bool): 是否使用GPU预测
- batch_size(int): 批处理大小 - batch_size(int): 批处理大小
- **返回** - **返回**
- results(list): 鉴定结果 - results(list): 鉴定结果
- ```python
def context(trainable=False):
```
- 获取porn_detection_lstm的预训练program以及program的输入输出变量
- **参数**
- trainable(bool): trainable=True表示program中的参数在Fine-tune时需要微调,否则保持不变。
- **返回**
- inputs(dict): program的输入变量
- outputs(dict): program的输出变量
- main_program(Program): 带有预训练参数的program
- ```python - ```python
def get_labels(): def get_labels():
``` ```
- 获取porn_detection_lstm的可识别的类别及其编号 - 获取porn_detection_lstm的可识别的类别及其编号
- **返回** - **返回**
- labels(dict): porn_detection_lstm的类别及其对应编号(二分类,是/不是) - labels(dict): porn_detection_lstm的类别及其对应编号(二分类,是/不是)
- ```python - ```python
def get_vocab_path(): def get_vocab_path():
``` ```
- 获取预训练时使用的词汇表 - 获取预训练时使用的词汇表
- **返回** - **返回**
- vocab_path(str): 词汇表路径 - vocab_path(str): 词汇表路径
...@@ -139,20 +126,20 @@ ...@@ -139,20 +126,20 @@
- ```python - ```python
import requests import requests
import json import json
# 待预测数据 # 待预测数据
text = ["黄片下载", "打击黄牛党"] text = ["黄片下载", "打击黄牛党"]
# 设置运行配置 # 设置运行配置
# 对应本地预测porn_detection_lstm.detection(texts=text, batch_size=1, use_gpu=True) # 对应本地预测porn_detection_lstm.detection(texts=text, batch_size=1, use_gpu=True)
data = {"texts": text, "batch_size": 1, "use_gpu":True} data = {"texts": text, "batch_size": 1, "use_gpu":True}
# 指定预测方法为porn_detection_lstm并发送post请求,content-type类型应指定json方式 # 指定预测方法为porn_detection_lstm并发送post请求,content-type类型应指定json方式
# HOST_IP为服务器IP # HOST_IP为服务器IP
url = "http://HOST_IP:8866/predict/porn_detection_lstm" url = "http://HOST_IP:8866/predict/porn_detection_lstm"
headers = {"Content-Type": "application/json"} headers = {"Content-Type": "application/json"}
r = requests.post(url=url, headers=headers, data=json.dumps(data)) r = requests.post(url=url, headers=headers, data=json.dumps(data))
# 打印预测结果 # 打印预测结果
print(json.dumps(r.json(), indent=4, ensure_ascii=False)) print(json.dumps(r.json(), indent=4, ensure_ascii=False))
``` ```
...@@ -169,6 +156,10 @@ ...@@ -169,6 +156,10 @@
大幅提升预测性能,同时简化接口使用 大幅提升预测性能,同时简化接口使用
* 1.1.1
移除 fluid api
- ```shell - ```shell
$ hub install porn_detection_lstm==1.1.0 $ hub install porn_detection_lstm==1.1.1
``` ```
...@@ -6,25 +6,28 @@ from __future__ import print_function ...@@ -6,25 +6,28 @@ from __future__ import print_function
import json import json
import math import math
import os import os
import paddle
import six import six
from porn_detection_lstm.processor import load_vocab
from porn_detection_lstm.processor import postprocess
from porn_detection_lstm.processor import preprocess
import paddle.fluid as fluid
import paddlehub as hub import paddlehub as hub
from paddlehub.common.paddle_helper import get_variable_info from paddlehub.common.paddle_helper import get_variable_info
from paddlehub.module.module import moduleinfo, serving from paddlehub.module.module import moduleinfo
from paddlehub.module.module import serving
from paddlehub.reader import tokenization from paddlehub.reader import tokenization
from porn_detection_lstm.processor import load_vocab, preprocess, postprocess
@moduleinfo( @moduleinfo(name="porn_detection_lstm",
name="porn_detection_lstm", version="1.1.1",
version="1.1.0", summary="Baidu's open-source Porn Detection Model.",
summary="Baidu's open-source Porn Detection Model.", author="baidu-nlp",
author="baidu-nlp", author_email="",
author_email="", type="nlp/sentiment_analysis")
type="nlp/sentiment_analysis")
class PornDetectionLSTM(hub.NLPPredictionModule): class PornDetectionLSTM(hub.NLPPredictionModule):
def _initialize(self): def _initialize(self):
""" """
initialize with the necessary elements initialize with the necessary elements
...@@ -42,41 +45,6 @@ class PornDetectionLSTM(hub.NLPPredictionModule): ...@@ -42,41 +45,6 @@ class PornDetectionLSTM(hub.NLPPredictionModule):
self._set_config() self._set_config()
def context(self, trainable=False):
"""
Get the input ,output and program of the pretrained porn_detection_lstm
Args:
trainable(bool): whether fine-tune the pretrained parameters of porn_detection_lstm or not
Returns:
inputs(dict): the input variables of porn_detection_lstm (words)
outputs(dict): the output variables of porn_detection_lstm (the sentiment prediction results)
main_program(Program): the main_program of lac with pretrained prameters
"""
place = fluid.CPUPlace()
exe = fluid.Executor(place)
program, feed_target_names, fetch_targets = fluid.io.load_inference_model(
dirname=self.pretrained_model_path, executor=exe)
with open(self.param_file, 'r') as file:
params_list = file.readlines()
for param in params_list:
param = param.strip()
var = program.global_block().var(param)
var_info = get_variable_info(var)
program.global_block().create_parameter(
shape=var_info['shape'], dtype=var_info['dtype'], name=var_info['name'])
for param in program.global_block().iter_parameters():
param.trainable = trainable
for name, var in program.global_block().vars.items():
if name == feed_target_names[0]:
inputs = {"words": var}
# output of sencond layer from the end prediction layer (fc-softmax)
if name == "@HUB_porn_detection_lstm@layer_norm_0.tmp_2":
outputs = {"class_probs": fetch_targets[0], "sentence_feature": var}
return inputs, outputs, program
@serving @serving
def detection(self, texts=[], data={}, use_gpu=False, batch_size=1): def detection(self, texts=[], data={}, use_gpu=False, batch_size=1):
""" """
...@@ -134,27 +102,3 @@ class PornDetectionLSTM(hub.NLPPredictionModule): ...@@ -134,27 +102,3 @@ class PornDetectionLSTM(hub.NLPPredictionModule):
""" """
self.labels = {"porn": 1, "not_porn": 0} self.labels = {"porn": 1, "not_porn": 0}
return self.labels return self.labels
if __name__ == "__main__":
porn_detection_lstm = PornDetectionLSTM()
porn_detection_lstm.context()
test_text = ["黄片下载", "打击黄牛党"]
results = porn_detection_lstm.detection(texts=test_text)
for index, text in enumerate(test_text):
results[index]["text"] = text
for index, result in enumerate(results):
if six.PY2:
print(json.dumps(results[index], encoding="utf8", ensure_ascii=False))
else:
print(results[index])
input_dict = {"text": test_text}
results = porn_detection_lstm.detection(data=input_dict)
for index, text in enumerate(test_text):
results[index]["text"] = text
for index, result in enumerate(results):
if six.PY2:
print(json.dumps(results[index], encoding="utf8", ensure_ascii=False))
else:
print(results[index])
...@@ -12,10 +12,10 @@ ...@@ -12,10 +12,10 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
import functools import functools
import os import os
from typing import Tuple, List from typing import List
from typing import Tuple
import paddle import paddle
import paddle2onnx import paddle2onnx
...@@ -23,7 +23,8 @@ from easydict import EasyDict ...@@ -23,7 +23,8 @@ from easydict import EasyDict
from paddlehub.compat import paddle_utils from paddlehub.compat import paddle_utils
from paddlehub.compat.module import module_v1_utils from paddlehub.compat.module import module_v1_utils
from paddlehub.utils import utils, log from paddlehub.utils import log
from paddlehub.utils import utils
class ModuleV1(object): class ModuleV1(object):
...@@ -85,16 +86,15 @@ class ModuleV1(object): ...@@ -85,16 +86,15 @@ class ModuleV1(object):
# Since the pre-trained model saved by the old version of Paddle cannot restore the corresponding # Since the pre-trained model saved by the old version of Paddle cannot restore the corresponding
# parameters, we need to restore them manually. # parameters, we need to restore them manually.
global_block.create_parameter( global_block.create_parameter(name=name,
name=name, shape=var.shape,
shape=var.shape, dtype=var.dtype,
dtype=var.dtype, type=var.type,
type=var.type, lod_level=var.lod_level,
lod_level=var.lod_level, error_clip=var.error_clip,
error_clip=var.error_clip, stop_gradient=var.stop_gradient,
stop_gradient=var.stop_gradient, is_data=var.is_data,
is_data=var.is_data, **attrs)
**attrs)
log.logger.info('{} pretrained paramaters loaded by PaddleHub'.format(num_param_loaded)) log.logger.info('{} pretrained paramaters loaded by PaddleHub'.format(num_param_loaded))
...@@ -112,7 +112,7 @@ class ModuleV1(object): ...@@ -112,7 +112,7 @@ class ModuleV1(object):
def _load_model(self): def _load_model(self):
model_path = os.path.join(self.directory, 'model') model_path = os.path.join(self.directory, 'model')
exe = paddle.static.Executor(paddle.CPUPlace()) exe = paddle.static.Executor(paddle.CPUPlace())
self.program, _, _ = paddle.fluid.io.load_inference_model(model_path, executor=exe) self.program, _, _ = paddle.static.load_inference_model(model_path, executor=exe)
# Clear the callstack since it may leak the privacy of the creator. # Clear the callstack since it may leak the privacy of the creator.
for block in self.program.blocks: for block in self.program.blocks:
...@@ -122,7 +122,10 @@ class ModuleV1(object): ...@@ -122,7 +122,10 @@ class ModuleV1(object):
op._set_attr('op_callstack', ['']) op._set_attr('op_callstack', [''])
@paddle_utils.run_in_static_mode @paddle_utils.run_in_static_mode
def context(self, signature: str = None, for_test: bool = False, trainable: bool = True, def context(self,
signature: str = None,
for_test: bool = False,
trainable: bool = True,
max_seq_len: int = 128) -> Tuple[dict, dict, paddle.static.Program]: max_seq_len: int = 128) -> Tuple[dict, dict, paddle.static.Program]:
'''Get module context information, including graph structure and graph input and output variables.''' '''Get module context information, including graph structure and graph input and output variables.'''
program = self.program.clone(for_test=for_test) program = self.program.clone(for_test=for_test)
...@@ -171,6 +174,7 @@ class ModuleV1(object): ...@@ -171,6 +174,7 @@ class ModuleV1(object):
'''Call the specified signature function for prediction.''' '''Call the specified signature function for prediction.'''
def _get_reader_and_feeder(data_format, data, place): def _get_reader_and_feeder(data_format, data, place):
def _reader(process_data): def _reader(process_data):
for item in zip(*process_data): for item in zip(*process_data):
yield item yield item
...@@ -284,14 +288,13 @@ class ModuleV1(object): ...@@ -284,14 +288,13 @@ class ModuleV1(object):
exe = paddle.static.Executor(place) exe = paddle.static.Executor(place)
feed_dict, fetch_dict, program = self.context(for_test=True, trainable=False) feed_dict, fetch_dict, program = self.context(for_test=True, trainable=False)
paddle.fluid.io.save_inference_model( paddle.static.save_inference_model(dirname=dirname,
dirname=dirname, main_program=program,
main_program=program, executor=exe,
executor=exe, feeded_var_names=[var.name for var in list(feed_dict.values())],
feeded_var_names=[var.name for var in list(feed_dict.values())], target_vars=list(fetch_dict.values()),
target_vars=list(fetch_dict.values()), model_filename=model_filename,
model_filename=model_filename, params_filename=params_filename)
params_filename=params_filename)
log.logger.info('Paddle Inference model saved in {}.'.format(dirname)) log.logger.info('Paddle Inference model saved in {}.'.format(dirname))
...@@ -315,13 +318,12 @@ class ModuleV1(object): ...@@ -315,13 +318,12 @@ class ModuleV1(object):
outputs = [program.global_block().vars[key] for key in outputs] outputs = [program.global_block().vars[key] for key in outputs]
save_file = os.path.join(dirname, '{}.onnx'.format(self.name)) save_file = os.path.join(dirname, '{}.onnx'.format(self.name))
paddle2onnx.program2onnx( paddle2onnx.program2onnx(program=program,
program=program, scope=paddle.static.global_scope(),
scope=paddle.static.global_scope(), feed_var_names=inputs,
feed_var_names=inputs, target_vars=outputs,
target_vars=outputs, save_file=save_file,
save_file=save_file, **kwargs)
**kwargs)
def sub_modules(self, recursive: bool = True): def sub_modules(self, recursive: bool = True):
''' '''
......
...@@ -12,32 +12,38 @@ ...@@ -12,32 +12,38 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
import argparse import argparse
import ast import ast
import os import os
import re import re
import six from typing import Any
from typing import Any, List, Text, Tuple from typing import List
from typing import Text
from typing import Tuple
import paddle
import numpy as np import numpy as np
import paddle
import six
from paddle.framework import core
from paddlehub.compat import paddle_utils from paddlehub.compat import paddle_utils
from paddlehub.compat.task.transformer_emb_task import TransformerEmbeddingTask
from paddlehub.compat.task.config import RunConfig from paddlehub.compat.task.config import RunConfig
from paddlehub.compat.task.reader import ClassifyReader from paddlehub.compat.task.reader import ClassifyReader
from paddlehub.module.module import runnable, RunModule from paddlehub.compat.task.transformer_emb_task import TransformerEmbeddingTask
from paddlehub.module.module import RunModule
from paddlehub.module.module import runnable
from paddlehub.utils.parser import txt_parser from paddlehub.utils.parser import txt_parser
from paddlehub.utils.utils import sys_stdin_encoding from paddlehub.utils.utils import sys_stdin_encoding
class DataFormatError(Exception): class DataFormatError(Exception):
def __init__(self, *args): def __init__(self, *args):
self.args = args self.args = args
class NLPBaseModule(RunModule): class NLPBaseModule(RunModule):
def get_vocab_path(self): def get_vocab_path(self):
''' '''
Get the path to the vocabulary whih was used to pretrain Get the path to the vocabulary whih was used to pretrain
...@@ -48,12 +54,13 @@ class NLPBaseModule(RunModule): ...@@ -48,12 +54,13 @@ class NLPBaseModule(RunModule):
class NLPPredictionModule(NLPBaseModule): class NLPPredictionModule(NLPBaseModule):
def _set_config(self): def _set_config(self):
'''predictor config setting''' '''predictor config setting'''
cpu_config = paddle.fluid.core.AnalysisConfig(self.pretrained_model_path) cpu_config = core.AnalysisConfig(self.pretrained_model_path)
cpu_config.disable_glog_info() cpu_config.disable_glog_info()
cpu_config.disable_gpu() cpu_config.disable_gpu()
self.cpu_predictor = paddle.fluid.core.create_paddle_predictor(cpu_config) self.cpu_predictor = core.create_paddle_predictor(cpu_config)
try: try:
_places = os.environ['CUDA_VISIBLE_DEVICES'] _places = os.environ['CUDA_VISIBLE_DEVICES']
...@@ -62,10 +69,10 @@ class NLPPredictionModule(NLPBaseModule): ...@@ -62,10 +69,10 @@ class NLPPredictionModule(NLPBaseModule):
except: except:
use_gpu = False use_gpu = False
if use_gpu: if use_gpu:
gpu_config = paddle.fluid.core.AnalysisConfig(self.pretrained_model_path) gpu_config = core.AnalysisConfig(self.pretrained_model_path)
gpu_config.disable_glog_info() gpu_config.disable_glog_info()
gpu_config.enable_use_gpu(memory_pool_init_size_mb=500, device_id=0) gpu_config.enable_use_gpu(memory_pool_init_size_mb=500, device_id=0)
self.gpu_predictor = paddle.fluid.core.create_paddle_predictor(gpu_config) self.gpu_predictor = core.create_paddle_predictor(gpu_config)
def texts2tensor(self, texts: List[dict]) -> paddle.Tensor: def texts2tensor(self, texts: List[dict]) -> paddle.Tensor:
''' '''
...@@ -81,7 +88,7 @@ class NLPPredictionModule(NLPBaseModule): ...@@ -81,7 +88,7 @@ class NLPPredictionModule(NLPBaseModule):
for i, text in enumerate(texts): for i, text in enumerate(texts):
data += text['processed'] data += text['processed']
lod.append(len(text['processed']) + lod[i]) lod.append(len(text['processed']) + lod[i])
tensor = paddle.fluid.core.PaddleTensor(np.array(data).astype('int64')) tensor = core.PaddleTensor(np.array(data).astype('int64'))
tensor.name = 'words' tensor.name = 'words'
tensor.lod = [lod] tensor.lod = [lod]
tensor.shape = [lod[-1], 1] tensor.shape = [lod[-1], 1]
...@@ -108,11 +115,10 @@ class NLPPredictionModule(NLPBaseModule): ...@@ -108,11 +115,10 @@ class NLPPredictionModule(NLPBaseModule):
@runnable @runnable
def run_cmd(self, argvs: List[Any]): def run_cmd(self, argvs: List[Any]):
'''Run as a command''' '''Run as a command'''
self.parser = argparse.ArgumentParser( self.parser = argparse.ArgumentParser(description='Run the %s module.' % self.name,
description='Run the %s module.' % self.name, prog='hub run %s' % self.name,
prog='hub run %s' % self.name, usage='%(prog)s',
usage='%(prog)s', add_help=True)
add_help=True)
self.arg_input_group = self.parser.add_argument_group(title='Input options', description='Input data. Required') 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( self.arg_config_group = self.parser.add_argument_group(
...@@ -135,8 +141,10 @@ class NLPPredictionModule(NLPBaseModule): ...@@ -135,8 +141,10 @@ class NLPPredictionModule(NLPBaseModule):
def add_module_config_arg(self): def add_module_config_arg(self):
'''Add the command config options''' '''Add the command config options'''
self.arg_config_group.add_argument( self.arg_config_group.add_argument('--use_gpu',
'--use_gpu', type=ast.literal_eval, default=False, help='whether use GPU for prediction') type=ast.literal_eval,
default=False,
help='whether use GPU for prediction')
self.arg_config_group.add_argument('--batch_size', type=int, default=1, help='batch size for prediction') self.arg_config_group.add_argument('--batch_size', type=int, default=1, help='batch size for prediction')
...@@ -172,8 +180,11 @@ class TransformerModule(NLPBaseModule): ...@@ -172,8 +180,11 @@ class TransformerModule(NLPBaseModule):
**kwargs): **kwargs):
if not directory: if not directory:
return return
super(TransformerModule, self).__init__( super(TransformerModule, self).__init__(name=name,
name=name, directory=directory, module_dir=module_dir, version=version, **kwargs) directory=directory,
module_dir=module_dir,
version=version,
**kwargs)
self.max_seq_len = max_seq_len self.max_seq_len = max_seq_len
...@@ -186,21 +197,20 @@ class TransformerModule(NLPBaseModule): ...@@ -186,21 +197,20 @@ class TransformerModule(NLPBaseModule):
return False return False
return os.path.exists(os.path.join(pretraining_params_path, var.name)) return os.path.exists(os.path.join(pretraining_params_path, var.name))
paddle.static.load( paddle.static.load(executor=exe,
executor=exe, model_path=pretraining_params_path,
model_path=pretraining_params_path, program=main_program,
program=main_program, var_list=main_program.all_parameters())
var_list=main_program.all_parameters())
def param_prefix(self) -> str: def param_prefix(self) -> str:
return '@HUB_%s@' % self.name return '@HUB_%s@' % self.name
@paddle_utils.run_in_static_mode @paddle_utils.run_in_static_mode
def context( def context(
self, self,
max_seq_len: int = None, max_seq_len: int = None,
trainable: bool = True, trainable: bool = True,
num_slots: int = 1, num_slots: int = 1,
) -> Tuple[dict, dict, paddle.static.Program]: ) -> Tuple[dict, dict, paddle.static.Program]:
''' '''
get inputs, outputs and program from pre-trained module get inputs, outputs and program from pre-trained module
...@@ -225,42 +235,64 @@ class TransformerModule(NLPBaseModule): ...@@ -225,42 +235,64 @@ class TransformerModule(NLPBaseModule):
module_program = paddle.static.Program() module_program = paddle.static.Program()
startup_program = paddle.static.Program() startup_program = paddle.static.Program()
with paddle.static.program_guard(module_program, startup_program): with paddle.static.program_guard(module_program, startup_program):
with paddle.fluid.unique_name.guard(): with paddle.utils.unique_name.guar.guard():
input_ids = paddle.static.data(name='input_ids', shape=[-1, max_seq_len, 1], dtype='int64', lod_level=0) input_ids = paddle.static.data(name='input_ids', shape=[-1, max_seq_len, 1], dtype='int64', lod_level=0)
position_ids = paddle.static.data( position_ids = paddle.static.data(name='position_ids',
name='position_ids', shape=[-1, max_seq_len, 1], dtype='int64', lod_level=0) shape=[-1, max_seq_len, 1],
segment_ids = paddle.static.data( dtype='int64',
name='segment_ids', shape=[-1, max_seq_len, 1], dtype='int64', lod_level=0) lod_level=0)
input_mask = paddle.static.data( segment_ids = paddle.static.data(name='segment_ids',
name='input_mask', shape=[-1, max_seq_len, 1], dtype='float32', lod_level=0) shape=[-1, max_seq_len, 1],
dtype='int64',
lod_level=0)
input_mask = paddle.static.data(name='input_mask',
shape=[-1, max_seq_len, 1],
dtype='float32',
lod_level=0)
pooled_output, sequence_output = self.net(input_ids, position_ids, segment_ids, input_mask) pooled_output, sequence_output = self.net(input_ids, position_ids, segment_ids, input_mask)
data_list = [(input_ids, position_ids, segment_ids, input_mask)] data_list = [(input_ids, position_ids, segment_ids, input_mask)]
output_name_list = [(pooled_output.name, sequence_output.name)] output_name_list = [(pooled_output.name, sequence_output.name)]
if num_slots > 1: if num_slots > 1:
input_ids_2 = paddle.static.data( input_ids_2 = paddle.static.data(name='input_ids_2',
name='input_ids_2', shape=[-1, max_seq_len, 1], dtype='int64', lod_level=0) shape=[-1, max_seq_len, 1],
position_ids_2 = paddle.static.data( dtype='int64',
name='position_ids_2', shape=[-1, max_seq_len, 1], dtype='int64', lod_level=0) lod_level=0)
segment_ids_2 = paddle.static.data( position_ids_2 = paddle.static.data(name='position_ids_2',
name='segment_ids_2', shape=[-1, max_seq_len, 1], dtype='int64', lod_level=0) shape=[-1, max_seq_len, 1],
input_mask_2 = paddle.static.data( dtype='int64',
name='input_mask_2', shape=[-1, max_seq_len, 1], dtype='float32', lod_level=0) lod_level=0)
segment_ids_2 = paddle.static.data(name='segment_ids_2',
shape=[-1, max_seq_len, 1],
dtype='int64',
lod_level=0)
input_mask_2 = paddle.static.data(name='input_mask_2',
shape=[-1, max_seq_len, 1],
dtype='float32',
lod_level=0)
pooled_output_2, sequence_output_2 = self.net(input_ids_2, position_ids_2, segment_ids_2, pooled_output_2, sequence_output_2 = self.net(input_ids_2, position_ids_2, segment_ids_2,
input_mask_2) input_mask_2)
data_list.append((input_ids_2, position_ids_2, segment_ids_2, input_mask_2)) data_list.append((input_ids_2, position_ids_2, segment_ids_2, input_mask_2))
output_name_list.append((pooled_output_2.name, sequence_output_2.name)) output_name_list.append((pooled_output_2.name, sequence_output_2.name))
if num_slots > 2: if num_slots > 2:
input_ids_3 = paddle.static.data( input_ids_3 = paddle.static.data(name='input_ids_3',
name='input_ids_3', shape=[-1, max_seq_len, 1], dtype='int64', lod_level=0) shape=[-1, max_seq_len, 1],
position_ids_3 = paddle.static.data( dtype='int64',
name='position_ids_3', shape=[-1, max_seq_len, 1], dtype='int64', lod_level=0) lod_level=0)
segment_ids_3 = paddle.static.data( position_ids_3 = paddle.static.data(name='position_ids_3',
name='segment_ids_3', shape=[-1, max_seq_len, 1], dtype='int64', lod_level=0) shape=[-1, max_seq_len, 1],
input_mask_3 = paddle.static.data( dtype='int64',
name='input_mask_3', shape=[-1, max_seq_len, 1], dtype='float32', lod_level=0) lod_level=0)
segment_ids_3 = paddle.static.data(name='segment_ids_3',
shape=[-1, max_seq_len, 1],
dtype='int64',
lod_level=0)
input_mask_3 = paddle.static.data(name='input_mask_3',
shape=[-1, max_seq_len, 1],
dtype='float32',
lod_level=0)
pooled_output_3, sequence_output_3 = self.net(input_ids_3, position_ids_3, segment_ids_3, pooled_output_3, sequence_output_3 = self.net(input_ids_3, position_ids_3, segment_ids_3,
input_mask_3) input_mask_3)
data_list.append((input_ids_3, position_ids_3, segment_ids_3, input_mask_3)) data_list.append((input_ids_3, position_ids_3, segment_ids_3, input_mask_3))
...@@ -305,10 +337,12 @@ class TransformerModule(NLPBaseModule): ...@@ -305,10 +337,12 @@ class TransformerModule(NLPBaseModule):
inputs['position_ids_%s' % (index + 1)] = data[1] inputs['position_ids_%s' % (index + 1)] = data[1]
inputs['segment_ids_%s' % (index + 1)] = data[2] inputs['segment_ids_%s' % (index + 1)] = data[2]
inputs['input_mask_%s' % (index + 1)] = data[3] inputs['input_mask_%s' % (index + 1)] = data[3]
outputs['pooled_output_%s' % (index + 1)] = module_program.global_block().vars[ outputs['pooled_output_%s' %
self.param_prefix() + output_name_list[index][0]] (index + 1)] = module_program.global_block().vars[self.param_prefix() +
outputs['sequence_output_%s' % (index + 1)] = module_program.global_block().vars[ output_name_list[index][0]]
self.param_prefix() + output_name_list[index][1]] outputs['sequence_output_%s' %
(index + 1)] = module_program.global_block().vars[self.param_prefix() +
output_name_list[index][1]]
return inputs, outputs, module_program return inputs, outputs, module_program
......
...@@ -12,30 +12,31 @@ ...@@ -12,30 +12,31 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
import contextlib import contextlib
import copy import copy
from typing import Callable, List from typing import Callable
from typing import List
import paddle import paddle
from paddle.framework import core
from paddlehub.utils.utils import Version from paddlehub.utils.utils import Version
dtype_map = { dtype_map = {
paddle.fluid.core.VarDesc.VarType.FP32: "float32", core.VarDesc.VarType.FP32: "float32",
paddle.fluid.core.VarDesc.VarType.FP64: "float64", core.VarDesc.VarType.FP64: "float64",
paddle.fluid.core.VarDesc.VarType.FP16: "float16", core.VarDesc.VarType.FP16: "float16",
paddle.fluid.core.VarDesc.VarType.INT32: "int32", core.VarDesc.VarType.INT32: "int32",
paddle.fluid.core.VarDesc.VarType.INT16: "int16", core.VarDesc.VarType.INT16: "int16",
paddle.fluid.core.VarDesc.VarType.INT64: "int64", core.VarDesc.VarType.INT64: "int64",
paddle.fluid.core.VarDesc.VarType.BOOL: "bool", core.VarDesc.VarType.BOOL: "bool",
paddle.fluid.core.VarDesc.VarType.INT16: "int16", core.VarDesc.VarType.INT16: "int16",
paddle.fluid.core.VarDesc.VarType.UINT8: "uint8", core.VarDesc.VarType.UINT8: "uint8",
paddle.fluid.core.VarDesc.VarType.INT8: "int8", core.VarDesc.VarType.INT8: "int8",
} }
def convert_dtype_to_string(dtype: str) -> paddle.fluid.core.VarDesc.VarType: def convert_dtype_to_string(dtype: str) -> core.VarDesc.VarType:
if dtype in dtype_map: if dtype in dtype_map:
return dtype_map[dtype] return dtype_map[dtype]
raise TypeError("dtype shoule in %s" % list(dtype_map.keys())) raise TypeError("dtype shoule in %s" % list(dtype_map.keys()))
......
...@@ -12,22 +12,29 @@ ...@@ -12,22 +12,29 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
import contextlib import contextlib
import inspect import inspect
import os import os
from functools import partial from functools import partial
from typing import Any, Callable, Generator, Generic, Iterator, List, Union from typing import Any
from typing import Callable
from typing import Generator
from typing import Generic
from typing import Iterator
from typing import List
from typing import Union
import paddle
import numpy as np import numpy as np
import paddle
from paddle.framework import core
from visualdl import LogWriter from visualdl import LogWriter
from paddlehub.compat import paddle_utils from paddlehub.compat import paddle_utils
from paddlehub.compat.task.checkpoint import load_checkpoint
from paddlehub.compat.task.config import RunConfig from paddlehub.compat.task.config import RunConfig
from paddlehub.compat.task.hook import TaskHooks from paddlehub.compat.task.hook import TaskHooks
from paddlehub.compat.task.task_utils import RunEnv, RunState from paddlehub.compat.task.task_utils import RunEnv
from paddlehub.compat.task.checkpoint import load_checkpoint from paddlehub.compat.task.task_utils import RunState
from paddlehub.utils.log import logger from paddlehub.utils.log import logger
from paddlehub.utils.utils import generate_tempdir from paddlehub.utils.utils import generate_tempdir
...@@ -66,8 +73,8 @@ class BaseTask(object): ...@@ -66,8 +73,8 @@ class BaseTask(object):
else: else:
self._base_main_program = paddle_utils.clone_program(main_program, for_test=False) self._base_main_program = paddle_utils.clone_program(main_program, for_test=False)
if startup_program is None: if startup_program is None:
self._base_startup_program = paddle_utils.clone_program( self._base_startup_program = paddle_utils.clone_program(paddle.static.default_startup_program(),
paddle.static.default_startup_program(), for_test=False) for_test=False)
else: else:
self._base_startup_program = paddle_utils.clone_program(startup_program, for_test=False) self._base_startup_program = paddle_utils.clone_program(startup_program, for_test=False)
self.is_checkpoint_loaded = False self.is_checkpoint_loaded = False
...@@ -168,7 +175,7 @@ class BaseTask(object): ...@@ -168,7 +175,7 @@ class BaseTask(object):
self.env.startup_program = paddle.static.Program() self.env.startup_program = paddle.static.Program()
with paddle.static.program_guard(self.env.main_program, self._base_startup_program): with paddle.static.program_guard(self.env.main_program, self._base_startup_program):
with paddle.fluid.unique_name.guard(self.env.UNG): with paddle.utils.unique_name.guard(self.env.UNG):
self.env.outputs = self._build_net() self.env.outputs = self._build_net()
if self.is_train_phase or self.is_test_phase: if self.is_train_phase or self.is_test_phase:
self.env.labels = self._add_label() self.env.labels = self._add_label()
...@@ -181,11 +188,12 @@ class BaseTask(object): ...@@ -181,11 +188,12 @@ class BaseTask(object):
if self.is_train_phase: if self.is_train_phase:
with paddle.static.program_guard(self.env.main_program, self._base_startup_program): with paddle.static.program_guard(self.env.main_program, self._base_startup_program):
with paddle.fluid.unique_name.guard(self.env.UNG): with paddle.utils.unique_name.guard(self.env.UNG):
if self._compatible_mode: if self._compatible_mode:
# This branch is compatible code for usage deprecated in paddlehub v1.8. # This branch is compatible code for usage deprecated in paddlehub v1.8.
self._base_data_reader.data_generator( self._base_data_reader.data_generator(batch_size=self.config.batch_size,
batch_size=self.config.batch_size, phase='train', shuffle=True) phase='train',
shuffle=True)
num_train_examples = self._base_data_reader.num_examples['train'] num_train_examples = self._base_data_reader.num_examples['train']
try: try:
# nlp_reader # nlp_reader
...@@ -300,7 +308,9 @@ class BaseTask(object): ...@@ -300,7 +308,9 @@ class BaseTask(object):
@property @property
def generator(self) -> Generator: def generator(self) -> Generator:
def data_generator(records): def data_generator(records):
def wrapper(): def wrapper():
for record in records: for record in records:
values = [] values = []
...@@ -311,8 +321,10 @@ class BaseTask(object): ...@@ -311,8 +321,10 @@ class BaseTask(object):
return wrapper return wrapper
if self._compatible_mode: if self._compatible_mode:
self.env.generator = self._base_data_reader.data_generator( self.env.generator = self._base_data_reader.data_generator(batch_size=self.config.batch_size,
batch_size=self.config.batch_size, phase=self.phase, data=self._predict_data, return_list=True) phase=self.phase,
data=self._predict_data,
return_list=True)
else: else:
if self.is_predict_phase: if self.is_predict_phase:
records = self._predict_data records = self._predict_data
...@@ -360,7 +372,7 @@ class BaseTask(object): ...@@ -360,7 +372,7 @@ class BaseTask(object):
return self.env.metrics return self.env.metrics
@property @property
def unique_name_generator(self) -> paddle.fluid.unique_name.UniqueNameGenerator: def unique_name_generator(self):
return self.env.UNG return self.env.UNG
@property @property
...@@ -504,16 +516,16 @@ class BaseTask(object): ...@@ -504,16 +516,16 @@ class BaseTask(object):
''' '''
eval_scores, eval_loss, run_speed = self._calculate_metrics(run_states) eval_scores, eval_loss, run_speed = self._calculate_metrics(run_states)
if 'train' in self._envs: if 'train' in self._envs:
self.vdl_writer.add_scalar( self.vdl_writer.add_scalar(tag='Loss_{}'.format(self.phase),
tag='Loss_{}'.format(self.phase), value=eval_loss, step=self._envs['train'].current_step) value=eval_loss,
step=self._envs['train'].current_step)
log_scores = '' log_scores = ''
for metric in eval_scores: for metric in eval_scores:
if 'train' in self._envs: if 'train' in self._envs:
self.vdl_writer.add_scalar( self.vdl_writer.add_scalar(tag='{}_{}'.format(metric, self.phase),
tag='{}_{}'.format(metric, self.phase), value=eval_scores[metric],
value=eval_scores[metric], step=self._envs['train'].current_step)
step=self._envs['train'].current_step)
log_scores += '{}={:.5f} '.format(metric, eval_scores[metric]) log_scores += '{}={:.5f} '.format(metric, eval_scores[metric])
logger.eval('[{} dataset evaluation result] loss={:.5f} {}[step/sec: {:.2f}]'.format( logger.eval('[{} dataset evaluation result] loss={:.5f} {}[step/sec: {:.2f}]'.format(
...@@ -540,12 +552,14 @@ class BaseTask(object): ...@@ -540,12 +552,14 @@ class BaseTask(object):
run_states (object): the results in train phase run_states (object): the results in train phase
''' '''
scores, avg_loss, run_speed = self._calculate_metrics(run_states) scores, avg_loss, run_speed = self._calculate_metrics(run_states)
self.vdl_writer.add_scalar( self.vdl_writer.add_scalar(tag='Loss_{}'.format(self.phase),
tag='Loss_{}'.format(self.phase), value=avg_loss, step=self._envs['train'].current_step) value=avg_loss,
step=self._envs['train'].current_step)
log_scores = '' log_scores = ''
for metric in scores: for metric in scores:
self.vdl_writer.add_scalar( self.vdl_writer.add_scalar(tag='{}_{}'.format(metric, self.phase),
tag='{}_{}'.format(metric, self.phase), value=scores[metric], step=self._envs['train'].current_step) value=scores[metric],
step=self._envs['train'].current_step)
log_scores += '{}={:.5f} '.format(metric, scores[metric]) log_scores += '{}={:.5f} '.format(metric, scores[metric])
logger.train('step {} / {}: loss={:.5f} {}[step/sec: {:.2f}]'.format(self.current_step, self.max_train_steps, logger.train('step {} / {}: loss={:.5f} {}[step/sec: {:.2f}]'.format(self.current_step, self.max_train_steps,
avg_loss, log_scores, run_speed)) avg_loss, log_scores, run_speed))
...@@ -569,7 +583,7 @@ class BaseTask(object): ...@@ -569,7 +583,7 @@ class BaseTask(object):
raise NotImplementedError raise NotImplementedError
def _add_metrics(self): def _add_metrics(self):
# Some metrics like acc, auc can be calculated by fluid.layers # Some metrics like acc, auc
# The others can be calculated in _calculate_metrics function # The others can be calculated in _calculate_metrics function
raise NotImplementedError raise NotImplementedError
...@@ -590,6 +604,7 @@ class BaseTask(object): ...@@ -590,6 +604,7 @@ class BaseTask(object):
return is_load_successful return is_load_successful
def load_parameters(self, dirname): def load_parameters(self, dirname):
def if_exist(var): def if_exist(var):
path = os.path.join(dirname, var.name) path = os.path.join(dirname, var.name)
return os.path.exists(path) return os.path.exists(path)
...@@ -598,14 +613,13 @@ class BaseTask(object): ...@@ -598,14 +613,13 @@ class BaseTask(object):
def save_inference_model(self, dirname: str, model_filename: str = None, params_filename: str = None): def save_inference_model(self, dirname: str, model_filename: str = None, params_filename: str = None):
with self.phase_guard('predict'): with self.phase_guard('predict'):
paddle.static.save_inference_model( paddle.static.save_inference_model(dirname=dirname,
dirname=dirname, executor=self.exe,
executor=self.exe, main_program=self.main_program,
main_program=self.main_program, feeded_var_names=self.feed_list,
feeded_var_names=self.feed_list, target_vars=self.fetch_var_list,
target_vars=self.fetch_var_list, model_filename=model_filename,
model_filename=model_filename, params_filename=params_filename)
params_filename=params_filename)
def finetune_and_eval(self) -> List[RunState]: def finetune_and_eval(self) -> List[RunState]:
return self.finetune(do_eval=True) return self.finetune(do_eval=True)
...@@ -673,7 +687,7 @@ class BaseTask(object): ...@@ -673,7 +687,7 @@ class BaseTask(object):
self._eval_end_event(run_states) self._eval_end_event(run_states)
return run_states return run_states
def _create_predictor(self) -> paddle.fluid.core.PaddlePredictor: def _create_predictor(self) -> core.PaddlePredictor:
''' '''
create high-performance predictor for predict. create high-performance predictor for predict.
Returns: Returns:
...@@ -681,7 +695,7 @@ class BaseTask(object): ...@@ -681,7 +695,7 @@ class BaseTask(object):
''' '''
with generate_tempdir() as _dir: with generate_tempdir() as _dir:
self.save_inference_model(dirname=_dir) self.save_inference_model(dirname=_dir)
predictor_config = paddle.fluid.core.AnalysisConfig(_dir) predictor_config = core.AnalysisConfig(_dir)
predictor_config.disable_glog_info() predictor_config.disable_glog_info()
if self.config.use_cuda: if self.config.use_cuda:
...@@ -690,7 +704,7 @@ class BaseTask(object): ...@@ -690,7 +704,7 @@ class BaseTask(object):
else: else:
predictor_config.disable_gpu() predictor_config.disable_gpu()
predictor_config.enable_memory_optim() predictor_config.enable_memory_optim()
return paddle.fluid.core.create_paddle_predictor(predictor_config) return core.create_paddle_predictor(predictor_config)
def _run_with_predictor(self) -> List[RunState]: def _run_with_predictor(self) -> List[RunState]:
''' '''
...@@ -723,7 +737,7 @@ class BaseTask(object): ...@@ -723,7 +737,7 @@ class BaseTask(object):
tensor_batch = [[] for i in range(len(self.feed_list))] tensor_batch = [[] for i in range(len(self.feed_list))]
for i in range(len(processed_batch)): for i in range(len(processed_batch)):
processed_batch[i] = np.array(processed_batch[i]).reshape(feed_var_shape[i]).astype(feed_var_type[i]) processed_batch[i] = np.array(processed_batch[i]).reshape(feed_var_shape[i]).astype(feed_var_type[i])
tensor_batch[i] = paddle.fluid.core.PaddleTensor(processed_batch[i]) tensor_batch[i] = core.PaddleTensor(processed_batch[i])
fetch_result = self._predictor.run(tensor_batch) fetch_result = self._predictor.run(tensor_batch)
for index, result in enumerate(fetch_result): for index, result in enumerate(fetch_result):
...@@ -737,12 +751,12 @@ class BaseTask(object): ...@@ -737,12 +751,12 @@ class BaseTask(object):
return global_run_states return global_run_states
def predict( def predict(
self, self,
data: List[Any] = None, data: List[Any] = None,
label_list: List[Any] = None, label_list: List[Any] = None,
load_best_model: bool = True, load_best_model: bool = True,
return_result: bool = True, return_result: bool = True,
accelerate_mode: bool = True, accelerate_mode: bool = True,
) -> List[RunState]: ) -> List[RunState]:
''' '''
make prediction for the input data. make prediction for the input data.
...@@ -802,14 +816,20 @@ class BaseTask(object): ...@@ -802,14 +816,20 @@ class BaseTask(object):
RunState: the running result of specific phase RunState: the running result of specific phase
''' '''
with paddle.static.program_guard(self.main_program, self.startup_program): with paddle.static.program_guard(self.main_program, self.startup_program):
data_loader = paddle.io.DataLoader.from_generator( data_loader = paddle.io.DataLoader.from_generator(feed_list=self.feed_var_list,
feed_list=self.feed_var_list, capacity=64, use_double_buffer=True, iterable=True) capacity=64,
use_double_buffer=True,
iterable=True)
if self.is_predict_phase: if self.is_predict_phase:
data_reader = data_loader.set_sample_generator( data_reader = data_loader.set_sample_generator(self.generator,
self.generator, places=self.places, batch_size=self.config.batch_size, drop_last=False) places=self.places,
batch_size=self.config.batch_size,
drop_last=False)
else: else:
data_reader = data_loader.set_sample_generator( data_reader = data_loader.set_sample_generator(self.generator,
self.generator, places=self.places, batch_size=self.config.batch_size, drop_last=True) places=self.places,
batch_size=self.config.batch_size,
drop_last=True)
global_run_states = [] global_run_states = []
period_run_states = [] period_run_states = []
...@@ -822,8 +842,10 @@ class BaseTask(object): ...@@ -822,8 +842,10 @@ class BaseTask(object):
tmp = np.array(batch[0][tmp_name]) tmp = np.array(batch[0][tmp_name])
num_batch_examples = tmp.shape[0] num_batch_examples = tmp.shape[0]
fetch_result = self.exe.run( fetch_result = self.exe.run(self.main_program_to_be_run,
self.main_program_to_be_run, feed=batch, fetch_list=self.fetch_list, return_numpy=self.return_numpy) feed=batch,
fetch_list=self.fetch_list,
return_numpy=self.return_numpy)
if not self.return_numpy: if not self.return_numpy:
fetch_result = [np.array(x) for x in fetch_result] fetch_result = [np.array(x) for x in fetch_result]
......
...@@ -12,7 +12,6 @@ ...@@ -12,7 +12,6 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
import ast import ast
import builtins import builtins
import codecs import codecs
...@@ -20,18 +19,25 @@ import inspect ...@@ -20,18 +19,25 @@ import inspect
import os import os
import re import re
import sys import sys
from typing import Callable, Generic, List, Optional, Union from typing import Callable
from typing import Generic
from typing import List
from typing import Optional
from typing import Union
import paddle import paddle
import paddle2onnx import paddle2onnx
from easydict import EasyDict from easydict import EasyDict
from paddlehub.utils import parser, log, utils
from paddlehub.compat import paddle_utils from paddlehub.compat import paddle_utils
from paddlehub.compat.module.module_v1 import ModuleV1 from paddlehub.compat.module.module_v1 import ModuleV1
from paddlehub.utils import log
from paddlehub.utils import parser
from paddlehub.utils import utils
class InvalidHubModule(Exception): class InvalidHubModule(Exception):
def __init__(self, directory: str): def __init__(self, directory: str):
self.directory = directory self.directory = directory
...@@ -194,12 +200,11 @@ class RunModule(object): ...@@ -194,12 +200,11 @@ class RunModule(object):
for key, _sub_module in self.sub_modules().items(): for key, _sub_module in self.sub_modules().items():
try: try:
sub_dirname = os.path.normpath(os.path.join(dirname, key)) sub_dirname = os.path.normpath(os.path.join(dirname, key))
_sub_module.save_inference_model( _sub_module.save_inference_model(sub_dirname,
sub_dirname, include_sub_modules=include_sub_modules,
include_sub_modules=include_sub_modules, model_filename=model_filename,
model_filename=model_filename, params_filename=params_filename,
params_filename=params_filename, combined=combined)
combined=combined)
except: except:
utils.record_exception('Failed to save sub module {}'.format(_sub_module.name)) utils.record_exception('Failed to save sub module {}'.format(_sub_module.name))
...@@ -249,21 +254,20 @@ class RunModule(object): ...@@ -249,21 +254,20 @@ class RunModule(object):
if os.path.exists(os.path.join(self._pretrained_model_path, '__params__')): if os.path.exists(os.path.join(self._pretrained_model_path, '__params__')):
_params_filename = '__params__' _params_filename = '__params__'
program, feeded_var_names, target_vars = paddle.fluid.io.load_inference_model( program, feeded_var_names, target_vars = paddle.static.load_inference_model(
dirname=self._pretrained_model_path, dirname=self._pretrained_model_path,
executor=exe, executor=exe,
model_filename=_model_filename, model_filename=_model_filename,
params_filename=_params_filename, params_filename=_params_filename,
) )
paddle.fluid.io.save_inference_model( paddle.static.save_inference_model(dirname=dirname,
dirname=dirname, main_program=program,
main_program=program, executor=exe,
executor=exe, feeded_var_names=feeded_var_names,
feeded_var_names=feeded_var_names, target_vars=target_vars,
target_vars=target_vars, model_filename=model_filename,
model_filename=model_filename, params_filename=params_filename)
params_filename=params_filename)
log.logger.info('Paddle Inference model saved in {}.'.format(dirname)) log.logger.info('Paddle Inference model saved in {}.'.format(dirname))
...@@ -333,19 +337,17 @@ class RunModule(object): ...@@ -333,19 +337,17 @@ class RunModule(object):
save_file = os.path.join(dirname, '{}.onnx'.format(self.name)) save_file = os.path.join(dirname, '{}.onnx'.format(self.name))
program, inputs, outputs = paddle.fluid.io.load_inference_model( program, inputs, outputs = paddle.static.load_inference_model(dirname=self._pretrained_model_path,
dirname=self._pretrained_model_path, model_filename=model_filename,
model_filename=model_filename, params_filename=params_filename,
params_filename=params_filename, executor=exe)
executor=exe)
paddle2onnx.program2onnx( paddle2onnx.program2onnx(program=program,
program=program, scope=paddle.static.global_scope(),
scope=paddle.static.global_scope(), feed_var_names=inputs,
feed_var_names=inputs, target_vars=outputs,
target_vars=outputs, save_file=save_file,
save_file=save_file, **kwargs)
**kwargs)
class Module(object): class Module(object):
...@@ -385,14 +387,13 @@ class Module(object): ...@@ -385,14 +387,13 @@ class Module(object):
from paddlehub.server.server import CacheUpdater from paddlehub.server.server import CacheUpdater
# This branch come from hub.Module(name='xxx') or hub.Module(directory='xxx') # This branch come from hub.Module(name='xxx') or hub.Module(directory='xxx')
if name: if name:
module = cls.init_with_name( module = cls.init_with_name(name=name,
name=name, version=version,
version=version, source=source,
source=source, update=update,
update=update, branch=branch,
branch=branch, ignore_env_mismatch=ignore_env_mismatch,
ignore_env_mismatch=ignore_env_mismatch, **kwargs)
**kwargs)
CacheUpdater("update_cache", module=name, version=version).start() CacheUpdater("update_cache", module=name, version=version).start()
elif directory: elif directory:
module = cls.init_with_directory(directory=directory, **kwargs) module = cls.init_with_directory(directory=directory, **kwargs)
...@@ -484,13 +485,12 @@ class Module(object): ...@@ -484,13 +485,12 @@ class Module(object):
manager = LocalModuleManager() manager = LocalModuleManager()
user_module_cls = manager.search(name, source=source, branch=branch) user_module_cls = manager.search(name, source=source, branch=branch)
if not user_module_cls or not user_module_cls.version.match(version): if not user_module_cls or not user_module_cls.version.match(version):
user_module_cls = manager.install( user_module_cls = manager.install(name=name,
name=name, version=version,
version=version, source=source,
source=source, update=update,
update=update, branch=branch,
branch=branch, ignore_env_mismatch=ignore_env_mismatch)
ignore_env_mismatch=ignore_env_mismatch)
directory = manager._get_normalized_path(user_module_cls.name) directory = manager._get_normalized_path(user_module_cls.name)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册