diff --git a/PaddleCV/image_classification/README.md b/PaddleCV/image_classification/README.md index 180e51f7b4efb2184b3f97708e39f5979c0f1349..1359b038aca4444b4701cb1eb695bd07bab38601 100644 --- a/PaddleCV/image_classification/README.md +++ b/PaddleCV/image_classification/README.md @@ -32,7 +32,7 @@ ### 安装说明 -在当前目录下运行样例代码需要python 2.7及以上版本,PadddlePaddle Fluid v1.5.1或以上的版本。如果你的运行环境中的PaddlePaddle低于此版本,请根据 [安装文档](http://paddlepaddle.org/documentation/docs/zh/1.5/beginners_guide/install/index_cn.html) 中的说明来更新PaddlePaddle。 +在当前目录下运行样例代码需要python 2.7及以上版本,PadddlePaddle Fluid v1.6或以上的版本。如果你的运行环境中的PaddlePaddle低于此版本,请根据 [安装文档](http://paddlepaddle.org/documentation/docs/zh/1.6/beginners_guide/install/index_cn.html) 中的说明来更新PaddlePaddle。 #### 环境依赖 @@ -46,7 +46,7 @@ pip install numpy ### 数据准备 -下面给出了ImageNet分类任务的样例 +下面给出了ImageNet分类任务的样例, 在Linux系统下通过如下的方式进行数据的准备: ``` cd data/ILSVRC2012/ @@ -70,7 +70,7 @@ val/ILSVRC2012_val_00000001.jpeg 65 ``` 注意:可能需要根据本地环境调整reader.py中相关路径来正确读取数据。 -**Windows系统下请用户自行下载ImageNet数据。[label下载链接](http://paddle-imagenet-models.bj.bcebos.com/ImageNet_label.tgz)** +**Windows系统下请用户自行下载ImageNet数据,[label下载链接](http://paddle-imagenet-models.bj.bcebos.com/ImageNet_label.tgz)** ### 模型训练 diff --git a/PaddleCV/image_classification/README_en.md b/PaddleCV/image_classification/README_en.md index bdc84ee1b37cdee79ae10598d9b2148a1326d8e6..bcc92ff1afa26890f090cd405b44c0a991ba8f8f 100644 --- a/PaddleCV/image_classification/README_en.md +++ b/PaddleCV/image_classification/README_en.md @@ -33,7 +33,7 @@ We also recommend users to take a look at the  [IPython Notebook demo](https:/ ### Installation -Running samples in this directory requires Python 2.7 and later, CUDA 8.0 and later, CUDNN 7.0 and later, python package: numpy and opencv-python, PaddelPaddle Fluid v1.5 and later, the latest release version is recommended, If the PaddlePaddle on your device is lower than v1.5, please follow the instructions in [installation document](http://paddlepaddle.org/documentation/docs/zh/1.5/beginners_guide/install/index_cn.html) and make an update. +Running samples in this directory requires Python 2.7 and later, CUDA 8.0 and later, CUDNN 7.0 and later, python package: numpy and opencv-python, PaddelPaddle Fluid v1.6 and later, the latest release version is recommended, If the PaddlePaddle on your device is lower than v1.6, please follow the instructions in [installation document](http://paddlepaddle.org/documentation/docs/zh/1.6/beginners_guide/install/index_cn.html) and make an update. ### Data preparation diff --git a/PaddleCV/image_classification/build_model.py b/PaddleCV/image_classification/build_model.py index 09236f4ceb3038b2c28204ef2e4ddde61114945c..709f58d7e4d7539c43fc7a64ef5c05c4523595b0 100644 --- a/PaddleCV/image_classification/build_model.py +++ b/PaddleCV/image_classification/build_model.py @@ -107,7 +107,7 @@ def _mixup_model(data, model, args, is_train): def create_model(model, args, is_train): """Create model, include basic model, googlenet model and mixup model """ - py_reader, data = utility.create_pyreader(is_train, args) + data_loader, data = utility.create_data_loader(is_train, args) if args.model == "GoogLeNet": loss_out = _googlenet_model(data, model, args, is_train) @@ -116,4 +116,4 @@ def create_model(model, args, is_train): loss_out = _mixup_model(data, model, args, is_train) else: loss_out = _basic_model(data, model, args, is_train) - return py_reader, loss_out + return data_loader, loss_out diff --git a/PaddleCV/image_classification/eval.py b/PaddleCV/image_classification/eval.py index e81842987fd3d3211aef766c783aa3c430e11160..0b66f9521445c4cb1e61403d4065011f601fffb1 100644 --- a/PaddleCV/image_classification/eval.py +++ b/PaddleCV/image_classification/eval.py @@ -63,12 +63,14 @@ def eval(args): ), "{} doesn't exist, please load right pretrained model path for eval".format( args.pretrained_model) - image = fluid.layers.data(name='image', shape=image_shape, dtype='float32') - label = fluid.layers.data(name='label', shape=[1], dtype='int64') + image = fluid.data( + name='image', shape=[None] + image_shape, dtype='float32') + label = fluid.data(name='label', shape=[None, 1], dtype='int64') # model definition if args.model.startswith('EfficientNet'): - model = models.__dict__[args.model](is_test=True, padding_type=args.padding_type, + model = models.__dict__[args.model](is_test=True, + padding_type=args.padding_type, use_se=args.use_se) else: model = models.__dict__[args.model]() @@ -144,6 +146,7 @@ def main(): args = parser.parse_args() print_arguments(args) check_gpu() + check_version() eval(args) diff --git a/PaddleCV/image_classification/fast_imagenet/train.py b/PaddleCV/image_classification/fast_imagenet/train.py index 2e2352468e13bac3d92e0cb470c9c72e08a99c15..dc39b592616f9a2aa8eaadb4cacec2b45185eeb0 100644 --- a/PaddleCV/image_classification/fast_imagenet/train.py +++ b/PaddleCV/image_classification/fast_imagenet/train.py @@ -112,10 +112,9 @@ def build_program(args, use_double_buffer=True) input, label = fluid.layers.read_file(pyreader) else: - input = fluid.layers.data( - name="image", shape=[3, 244, 244], dtype="uint8") - label = fluid.layers.data( - name="label", shape=[1], dtype="int64") + input = fluid.data( + name="image", shape=[None, 3, 244, 244], dtype="uint8") + label = fluid.data(name="label", shape=[None, 1], dtype="int64") cast_img_type = "float16" if args.fp16 else "float32" cast = fluid.layers.cast(input, cast_img_type) img_mean = fluid.layers.create_global_var( diff --git a/PaddleCV/image_classification/infer.py b/PaddleCV/image_classification/infer.py index 30fa925594e5f07f2f30591be2063e99d44b83b0..0fb7de7791b7cf87605f32bfebcd3c7a8bd483e0 100644 --- a/PaddleCV/image_classification/infer.py +++ b/PaddleCV/image_classification/infer.py @@ -49,6 +49,8 @@ add_arg('crop_size', int, 224, "The value of crop size" add_arg('topk', int, 1, "topk") add_arg('label_path', str, "./utils/tools/readable_label.txt", "readable label filepath") add_arg('interpolation', int, None, "The interpolation mode") +add_arg('padding_type', str, "SAME", "Padding type of convolution") +add_arg('use_se', bool, True, "Whether to use Squeeze-and-Excitation module for EfficientNet.") # yapf: enable @@ -59,8 +61,16 @@ def infer(args): model_list) assert os.path.isdir(args.pretrained_model ), "please load right pretrained model path for infer" - image = fluid.layers.data(name='image', shape=image_shape, dtype='float32') - model = models.__dict__[args.model]() + image = fluid.data( + name='image', shape=[None] + image_shape, dtype='float32') + + if args.model.startswith('EfficientNet'): + model = models.__dict__[args.model](is_test=True, + padding_type=args.padding_type, + use_se=args.use_se) + else: + model = models.__dict__[args.model]() + if args.model == "GoogLeNet": out, _, _ = model.net(input=image, class_dim=args.class_dim) else: @@ -120,6 +130,7 @@ def main(): args = parser.parse_args() print_arguments(args) check_gpu() + check_version() infer(args) diff --git a/PaddleCV/image_classification/train.py b/PaddleCV/image_classification/train.py index 37679db6e414665dfaa7c60a48e212b621a385aa..4a4c4899a703710804d11d6c45ed6636487b22f0 100755 --- a/PaddleCV/image_classification/train.py +++ b/PaddleCV/image_classification/train.py @@ -21,6 +21,7 @@ import numpy as np import time import sys + def set_paddle_flags(flags): for key, value in flags.items(): if os.environ.get(key, None) is None: @@ -42,6 +43,7 @@ from utils import * import models from build_model import create_model + def build_program(is_train, main_prog, startup_prog, args): """build program, and add grad op in program accroding to different mode @@ -52,16 +54,18 @@ def build_program(is_train, main_prog, startup_prog, args): args: arguments Returns : - train mode: [Loss, global_lr, py_reader] - test mode: [Loss, py_reader] + train mode: [Loss, global_lr, data_loader] + test mode: [Loss, data_loader] """ if args.model.startswith('EfficientNet'): is_test = False if is_train else True override_params = {"drop_connect_rate": args.drop_connect_rate} padding_type = args.padding_type use_se = args.use_se - model = models.__dict__[args.model](is_test=is_test, override_params=override_params, - padding_type=padding_type, use_se=use_se) + model = models.__dict__[args.model](is_test=is_test, + override_params=override_params, + padding_type=padding_type, + use_se=use_se) else: model = models.__dict__[args.model]() with fluid.program_guard(main_prog, startup_prog): @@ -69,7 +73,7 @@ def build_program(is_train, main_prog, startup_prog, args): main_prog.random_seed = args.random_seed startup_prog.random_seed = args.random_seed with fluid.unique_name.guard(): - py_reader, loss_out = create_model(model, args, is_train) + data_loader, loss_out = create_model(model, args, is_train) # add backward op in program if is_train: optimizer = create_optimizer(args) @@ -80,18 +84,22 @@ def build_program(is_train, main_prog, startup_prog, args): global_lr.persistable = True loss_out.append(global_lr) if args.use_ema: - global_steps = fluid.layers.learning_rate_scheduler._decay_step_counter() - ema = ExponentialMovingAverage(args.ema_decay, thres_steps=global_steps) + global_steps = fluid.layers.learning_rate_scheduler._decay_step_counter( + ) + ema = ExponentialMovingAverage( + args.ema_decay, thres_steps=global_steps) ema.update() loss_out.append(ema) - loss_out.append(py_reader) + loss_out.append(data_loader) return loss_out -def validate(args, test_py_reader, exe, test_prog, test_fetch_list, pass_id, train_batch_metrics_record): + +def validate(args, test_data_loader, exe, test_prog, test_fetch_list, pass_id, + train_batch_metrics_record): test_batch_time_record = [] test_batch_metrics_record = [] test_batch_id = 0 - test_py_reader.start() + test_data_loader.start() try: while True: t1 = time.time() @@ -111,7 +119,7 @@ def validate(args, test_py_reader, exe, test_prog, test_fetch_list, pass_id, tra test_batch_id += 1 except fluid.core.EOFException: - test_py_reader.reset() + test_data_loader.reset() #train_epoch_time_avg = np.mean(np.array(train_batch_time_record)) train_epoch_metrics_avg = np.mean( np.array(train_batch_metrics_record), axis=0) @@ -124,6 +132,7 @@ def validate(args, test_py_reader, exe, test_prog, test_fetch_list, pass_id, tra list(train_epoch_metrics_avg) + list(test_epoch_metrics_avg), test_epoch_time_avg, "epoch") + def train(args): """Train model @@ -139,7 +148,7 @@ def train(args): main_prog=train_prog, startup_prog=startup_prog, args=args) - train_py_reader = train_out[-1] + train_data_loader = train_out[-1] if args.use_ema: train_fetch_vars = train_out[:-2] ema = train_out[-2] @@ -153,7 +162,7 @@ def train(args): main_prog=test_prog, startup_prog=startup_prog, args=args) - test_py_reader = test_out[-1] + test_data_loader = test_out[-1] test_fetch_vars = test_out[:-1] test_fetch_list = [var.name for var in test_fetch_vars] @@ -173,20 +182,21 @@ def train(args): train_reader = imagenet_reader.train(settings=args) test_reader = imagenet_reader.val(settings=args) - train_py_reader.decorate_sample_list_generator(train_reader, place) - test_py_reader.decorate_sample_list_generator(test_reader, place) + train_data_loader.set_sample_list_generator(train_reader, place) + test_data_loader.set_sample_list_generator(test_reader, place) compiled_train_prog = best_strategy_compiled(args, train_prog, train_fetch_vars[0], exe) trainer_id = int(os.getenv("PADDLE_TRAINER_ID", 0)) for pass_id in range(args.num_epochs): if num_trainers > 1: - imagenet_reader.set_shuffle_seed(pass_id + (args.random_seed if args.random_seed else 0)) + imagenet_reader.set_shuffle_seed(pass_id + ( + args.random_seed if args.random_seed else 0)) train_batch_id = 0 train_batch_time_record = [] train_batch_metrics_record = [] - train_py_reader.start() + train_data_loader.start() try: while True: @@ -201,21 +211,25 @@ def train(args): train_batch_metrics_record.append(train_batch_metrics_avg) if trainer_id == 0: print_info(pass_id, train_batch_id, args.print_step, - train_batch_metrics_avg, train_batch_elapse, "batch") + train_batch_metrics_avg, train_batch_elapse, + "batch") sys.stdout.flush() train_batch_id += 1 except fluid.core.EOFException: - train_py_reader.reset() + train_data_loader.reset() if trainer_id == 0: if args.use_ema: print('ExponentialMovingAverage validate start...') with ema.apply(exe): - validate(args, test_py_reader, exe, test_prog, test_fetch_list, pass_id, train_batch_metrics_record) + validate(args, test_data_loader, exe, test_prog, + test_fetch_list, pass_id, + train_batch_metrics_record) print('ExponentialMovingAverage validate over!') - validate(args, test_py_reader, exe, test_prog, test_fetch_list, pass_id, train_batch_metrics_record) + validate(args, test_data_loader, exe, test_prog, test_fetch_list, + pass_id, train_batch_metrics_record) #For now, save model per epoch. if pass_id % args.save_step == 0: save_model(args, exe, train_prog, pass_id) diff --git a/PaddleCV/image_classification/utils/__init__.py b/PaddleCV/image_classification/utils/__init__.py index 61ca1cbb4c65890119720b271f2bf0fa7b06a092..4677e4535712c9f261bf18ba08ba6446d2db76d8 100644 --- a/PaddleCV/image_classification/utils/__init__.py +++ b/PaddleCV/image_classification/utils/__init__.py @@ -12,4 +12,4 @@ #See the License for the specific language governing permissions and #limitations under the License. from .optimizer import cosine_decay, lr_warmup, cosine_decay_with_warmup, exponential_decay_with_warmup, Optimizer, create_optimizer -from .utility import add_arguments, print_arguments, parse_args, check_gpu, check_args, init_model, save_model, create_pyreader, print_info, best_strategy_compiled, init_model, save_model, ExponentialMovingAverage +from .utility import add_arguments, print_arguments, parse_args, check_gpu, check_args, check_version, init_model, save_model, create_data_loader, print_info, best_strategy_compiled, init_model, save_model, ExponentialMovingAverage diff --git a/PaddleCV/image_classification/utils/utility.py b/PaddleCV/image_classification/utils/utility.py index 982972d7f556d13a92246094311dfb8b7f5d5244..092f3c05524e303845ac7247169b6c73812a6be9 100644 --- a/PaddleCV/image_classification/utils/utility.py +++ b/PaddleCV/image_classification/utils/utility.py @@ -34,6 +34,7 @@ from paddle.fluid.framework import Program, program_guard, name_scope, default_m from paddle.fluid import unique_name, layers from utils import dist_utils + def print_arguments(args): """Print argparse's arguments. @@ -167,6 +168,22 @@ def check_gpu(): pass +def check_version(): + """ + Log error and exit when the installed version of paddlepaddle is + not satisfied. + """ + err = "PaddlePaddle version 1.6 or higher is required, " \ + "or a suitable develop version is satisfied as well. \n" \ + "Please make sure the version is good with your code." \ + + try: + fluid.require_version('1.6.0') + except Exception as e: + print(err) + sys.exit(1) + + def check_args(args): """check arguments before running @@ -183,7 +200,8 @@ def check_args(args): # check learning rate strategy lr_strategy_list = [ - "piecewise_decay", "cosine_decay", "linear_decay", "cosine_decay_warmup", "exponential_decay_warmup" + "piecewise_decay", "cosine_decay", "linear_decay", + "cosine_decay_warmup", "exponential_decay_warmup" ] if args.lr_strategy not in lr_strategy_list: warnings.warn( @@ -242,6 +260,7 @@ def check_args(args): #check gpu check_gpu() + check_version() def init_model(exe, args, program): @@ -269,49 +288,52 @@ def save_model(args, exe, train_prog, info): print("Already save model in %s" % (model_path)) -def create_pyreader(is_train, args): - """create PyReader +def create_data_loader(is_train, args): + """create data_loader Usage: - Using mixup process in training, it will return 5 results, include py_reader, image, y_a(label), y_b(label) and lamda, or it will return 3 results, include py_reader, image, and label. + Using mixup process in training, it will return 5 results, include data_loader, image, y_a(label), y_b(label) and lamda, or it will return 3 results, include data_loader, image, and label. Args: is_train: mode args: arguments Returns: - py_reader and the input data of net, + data_loader and the input data of net, """ image_shape = [int(m) for m in args.image_shape.split(",")] - feed_image = fluid.layers.data( - name="feed_image", shape=image_shape, dtype="float32", lod_level=0) + feed_image = fluid.data( + name="feed_image", + shape=[None] + image_shape, + dtype="float32", + lod_level=0) - feed_label = fluid.layers.data( - name="feed_label", shape=[1], dtype="int64", lod_level=0) - feed_y_a = fluid.layers.data( - name="feed_y_a", shape=[1], dtype="int64", lod_level=0) + feed_label = fluid.data( + name="feed_label", shape=[None, 1], dtype="int64", lod_level=0) + feed_y_a = fluid.data( + name="feed_y_a", shape=[None, 1], dtype="int64", lod_level=0) if is_train and args.use_mixup: - feed_y_b = fluid.layers.data( - name="feed_y_b", shape=[1], dtype="int64", lod_level=0) - feed_lam = fluid.layers.data( - name="feed_lam", shape=[1], dtype="float32", lod_level=0) + feed_y_b = fluid.data( + name="feed_y_b", shape=[None, 1], dtype="int64", lod_level=0) + feed_lam = fluid.data( + name="feed_lam", shape=[None, 1], dtype="float32", lod_level=0) - py_reader = fluid.io.PyReader( + data_loader = fluid.io.DataLoader.from_generator( feed_list=[feed_image, feed_y_a, feed_y_b, feed_lam], capacity=64, use_double_buffer=True, iterable=False) - return py_reader, [feed_image, feed_y_a, feed_y_b, feed_lam] + return data_loader, [feed_image, feed_y_a, feed_y_b, feed_lam] else: - py_reader = fluid.io.PyReader( + data_loader = fluid.io.DataLoader.from_generator( feed_list=[feed_image, feed_label], capacity=64, use_double_buffer=True, iterable=False) - return py_reader, [feed_image, feed_label] + return data_loader, [feed_image, feed_label] def print_info(pass_id, batch_id, print_step, metrics, time_info, info_mode): @@ -409,8 +431,11 @@ def best_strategy_compiled(args, program, loss, exe): class ExponentialMovingAverage(object): - - def __init__(self, decay=0.999, thres_steps=None, zero_debias=False, name=None): + def __init__(self, + decay=0.999, + thres_steps=None, + zero_debias=False, + name=None): self._decay = decay self._thres_steps = thres_steps self._name = name if name is not None else '' @@ -430,7 +455,7 @@ class ExponentialMovingAverage(object): self._ema_vars = {} for param, tmp in self._params_tmps: with param.block.program._optimized_guard( - [param, tmp]), name_scope('moving_average'): + [param, tmp]), name_scope('moving_average'): self._ema_vars[param.name] = self._create_ema_vars(param) self.apply_program = Program() @@ -500,14 +525,14 @@ class ExponentialMovingAverage(object): param_master_emas = [] for param, tmp in self._params_tmps: with param.block.program._optimized_guard( - [param, tmp]), name_scope('moving_average'): + [param, tmp]), name_scope('moving_average'): param_ema = self._ema_vars[param.name] if param.name + '.master' in self._ema_vars: master_ema = self._ema_vars[param.name + '.master'] param_master_emas.append([param_ema, master_ema]) else: ema_t = param_ema * self._decay_var + param * ( - 1 - self._decay_var) + 1 - self._decay_var) layers.assign(input=ema_t, output=param_ema) # for fp16 params