diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4cd4bd7fa92f0c5d4de590838220d4cd6973c2bf..15d8e516abaffd444f20057c1099658c5aa215d5 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -33,6 +33,3 @@ - id: trailing-whitespace files: \.(md|yml)$ - id: check-case-conflict - - id: flake8 - args: ['--ignore=E265'] - diff --git a/configs/EfficientNet/EfficientNetB0.yaml b/configs/EfficientNet/EfficientNetB0.yaml index 381a4dd45d659e5bb1cb018c0d739592fa839695..d3ad0c83900ef97ceffc8e1358be73b35603e76e 100644 --- a/configs/EfficientNet/EfficientNetB0.yaml +++ b/configs/EfficientNet/EfficientNetB0.yaml @@ -46,10 +46,10 @@ TRAIN: channel_first: False - RandCropImage: size: 224 - interpolation: 2 + #interpolation: 2 - RandFlipImage: flip_code: 1 - - AutoArgument: + - AutoAugment: - NormalizeImage: scale: 1./255. mean: [0.485, 0.456, 0.406] diff --git a/ppcls/data/imaug/operators.py b/ppcls/data/imaug/operators.py index 6eb91b5c91b0dffeafd72e378ecb585be245aa2e..06abd9a2744ecbfe91c343c6a4031bb1f808c8b6 100644 --- a/ppcls/data/imaug/operators.py +++ b/ppcls/data/imaug/operators.py @@ -25,7 +25,8 @@ import random import cv2 import numpy as np -from autoargument import ImageNetPolicy +from .autoaugment import ImageNetPolicy + class OperatorParamError(ValueError): """ OperatorParamError @@ -172,12 +173,12 @@ class RandFlipImage(object): else: return img -class AutoArgument(object): - + +class AutoAugment(object): def __init__(self): self.policy = ImageNetPolicy() - def __call__(self,img): + def __call__(self, img): from PIL import Image img = np.ascontiguousarray(img) img = Image.fromarray(img) diff --git a/ppcls/modeling/architectures/efficientnet.py b/ppcls/modeling/architectures/efficientnet.py index d6bac79bd8674b6bcb315d512fc095577fc6c97a..8da13a753247d067490ba142fdfa01943c7b058a 100644 --- a/ppcls/modeling/architectures/efficientnet.py +++ b/ppcls/modeling/architectures/efficientnet.py @@ -383,7 +383,9 @@ class EfficientNet(): use_bias=True, padding_type=self.padding_type, name=name + '_se_expand') - se_out = inputs * fluid.layers.sigmoid(x_squeezed) + #se_out = inputs * fluid.layers.sigmoid(x_squeezed) + se_out = fluid.layers.elementwise_mul( + inputs, fluid.layers.sigmoid(x_squeezed), axis=-1) return se_out def extract_features(self, inputs, is_test): @@ -467,8 +469,8 @@ class BlockDecoder(object): # Check stride cond_1 = ('s' in options and len(options['s']) == 1) - cond_2 = ((len(options['s']) == 2) - and (options['s'][0] == options['s'][1])) + cond_2 = ((len(options['s']) == 2) and + (options['s'][0] == options['s'][1])) assert (cond_1 or cond_2) return BlockArgs( diff --git a/ppcls/optimizer/learning_rate.py b/ppcls/optimizer/learning_rate.py index b6de18bafef062d2ca3cfde857a2d03d9d1dd178..0227ae43e0f5c99894dcaeb1b51425fbdc9a8c82 100644 --- a/ppcls/optimizer/learning_rate.py +++ b/ppcls/optimizer/learning_rate.py @@ -1,16 +1,16 @@ -#copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. +# copyright (c) 2020 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 +# 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. +# 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 @@ -130,7 +130,7 @@ class CosineWarmup(object): with fluid.layers.control_flow.Switch() as switch: with switch.case(epoch < self.warmup_epoch): decayed_lr = self.lr * \ - (global_step / (self.step_each_epoch * self.warmup_epoch)) + (global_step / (self.step_each_epoch * self.warmup_epoch)) fluid.layers.tensor.assign( input=decayed_lr, output=learning_rate) with switch.default(): @@ -146,7 +146,6 @@ class CosineWarmup(object): class ExponentialWarmup(object): - """ Exponential learning rate decay with warmup [0, warmup_epoch): linear warmup @@ -160,8 +159,14 @@ class ExponentialWarmup(object): warmup_epoch(int): epoch num of warmup """ - def __init__(self, lr, step_each_epoch, decay_epochs=2.4, decay_rate=0.97, warmup_epoch=5, **kwargs): - super(CosineWarmup, self).__init__() + def __init__(self, + lr, + step_each_epoch, + decay_epochs=2.4, + decay_rate=0.97, + warmup_epoch=5, + **kwargs): + super(ExponentialWarmup, self).__init__() self.lr = lr self.step_each_epoch = step_each_epoch self.decay_epochs = decay_epochs * self.step_each_epoch @@ -185,19 +190,20 @@ class ExponentialWarmup(object): with fluid.layers.control_flow.Switch() as switch: with switch.case(epoch < self.warmup_epoch): decayed_lr = self.lr * \ - (global_step / (self.step_each_epoch * self.warmup_epoch)) + (global_step / (self.step_each_epoch * self.warmup_epoch)) fluid.layers.tensor.assign( input=decayed_lr, output=learning_rate) with switch.default(): rest_step = global_step - self.warmup_epoch * self.step_each_epoch div_res = ops.floor(rest_step / self.decay_epochs) - decayed_lr = self.lr*(self.decay_rate**div_res) + decayed_lr = self.lr * (self.decay_rate**div_res) fluid.layers.tensor.assign( input=decayed_lr, output=learning_rate) return learning_rate + class LearningRateBuilder(): """ Build learning rate variable diff --git a/tools/program.py b/tools/program.py index d1cc285e06db9006cd4166b972fb66a274fc4a29..78f362b47b3304266a31b7473d1a3f81176b2d83 100644 --- a/tools/program.py +++ b/tools/program.py @@ -36,7 +36,7 @@ from ppcls.utils import logger from paddle.fluid.incubate.fleet.collective import fleet from paddle.fluid.incubate.fleet.collective import DistributedStrategy -import ema +from ema import ExponentialMovingAverage def create_feeds(image_shape, use_mix=None): @@ -359,10 +359,12 @@ def build(config, main_prog, startup_prog, is_train=True): optimizer.minimize(fetchs['loss'][0]) if config.get('use_ema'): - global_steps = fluid.layers.learning_rate_scheduler._decay_step_counter() - ema = ExponentialMovingAverage(config.get('ema_decay'), thres_steps=global_steps) + global_steps = fluid.layers.learning_rate_scheduler._decay_step_counter( + ) + ema = ExponentialMovingAverage( + config.get('ema_decay'), thres_steps=global_steps) ema.update() - fetchs['ema'] = ema + return dataloader, fetchs, ema return dataloader, fetchs @@ -396,7 +398,13 @@ def compile(config, program, loss_name=None): total_step = 0 -def run(dataloader, exe, program, fetchs, epoch=0, mode='train', vdl_writer=None): +def run(dataloader, + exe, + program, + fetchs, + epoch=0, + mode='train', + vdl_writer=None): """ Feed data to the model and fetch the measures and loss @@ -410,6 +418,7 @@ def run(dataloader, exe, program, fetchs, epoch=0, mode='train', vdl_writer=None Returns: """ + print(fetchs) fetch_list = [f[0] for f in fetchs.values()] metric_list = [f[1] for f in fetchs.values()] for m in metric_list: diff --git a/tools/train.py b/tools/train.py index deb953b16581989b7a48246b4c8b5b8aff3c3e14..6dc362e845997f9f471d8320461feb3f83e8dfbb 100644 --- a/tools/train.py +++ b/tools/train.py @@ -70,8 +70,12 @@ def main(args): best_top1_acc = 0.0 # best top1 acc record - train_dataloader, train_fetchs = program.build( - config, train_prog, startup_prog, is_train=True) + if not config.get('use_ema'): + train_dataloader, train_fetchs = program.build( + config, train_prog, startup_prog, is_train=True) + else: + train_dataloader, train_fetchs, ema = program.build( + config, train_prog, startup_prog, is_train=True) if config.validate: valid_prog = fluid.Program() @@ -81,11 +85,11 @@ def main(args): valid_prog = valid_prog.clone(for_test=True) # create the "Executor" with the statement of which place - exe = fluid.Executor(place=place) - # only run startup_prog once to init + exe = fluid.Executor(place) + # Parameter initialization exe.run(startup_prog) - # load model from checkpoint or pretrained model + # load model from 1. checkpoint to resume training, 2. pretrained model to finetune init_model(config, train_prog, exe) train_reader = Reader(config, 'train')() @@ -110,8 +114,8 @@ def main(args): logger.info(logger.coloring("EMA validate start...")) with train_fetchs('ema').apply(exe): top1_acc = program.run(valid_dataloader, exe, - compiled_valid_prog, valid_fetchs, - epoch_id, 'valid') + compiled_valid_prog, + valid_fetchs, epoch_id, 'valid') logger.info(logger.coloring("EMA validate over!")) top1_acc = program.run(valid_dataloader, exe,