diff --git a/paddlex/__init__.py b/paddlex/__init__.py index d1656161a0d764c0a7fbd125f246d0e43125bcda..b80363f2e6adfdbd6ce712cfec486540753abbb7 100644 --- a/paddlex/__init__.py +++ b/paddlex/__init__.py @@ -53,4 +53,4 @@ log_level = 2 from . import interpret -__version__ = '1.0.5' +__version__ = '1.0.6' diff --git a/paddlex/cls.py b/paddlex/cls.py index 0dce289d7ee77c9559a4fce2104cca8786b81f52..90c5eefce512c966a04975ebfe6457613012c872 100644 --- a/paddlex/cls.py +++ b/paddlex/cls.py @@ -37,5 +37,6 @@ DenseNet161 = cv.models.DenseNet161 DenseNet201 = cv.models.DenseNet201 ShuffleNetV2 = cv.models.ShuffleNetV2 HRNet_W18 = cv.models.HRNet_W18 +AlexNet = cv.models.AlexNet transforms = cv.transforms.cls_transforms diff --git a/paddlex/cv/models/__init__.py b/paddlex/cv/models/__init__.py index 22485f2701e1e06c6e050c0c15238c32ed4a6a02..622878933c12f1934960eb42aed1f992e7164708 100644 --- a/paddlex/cv/models/__init__.py +++ b/paddlex/cv/models/__init__.py @@ -35,6 +35,7 @@ from .classifier import DenseNet161 from .classifier import DenseNet201 from .classifier import ShuffleNetV2 from .classifier import HRNet_W18 +from .classifier import AlexNet from .base import BaseAPI from .yolo_v3 import YOLOv3 from .faster_rcnn import FasterRCNN diff --git a/paddlex/cv/models/base.py b/paddlex/cv/models/base.py index ac8989ff83980bf45d7705985353435e6e19a9e6..14db42b8aed39674f2911f3fe5ee472435b8da34 100644 --- a/paddlex/cv/models/base.py +++ b/paddlex/cv/models/base.py @@ -221,8 +221,8 @@ class BaseAPI: logging.info( "Load pretrain weights from {}.".format(pretrain_weights), use_color=True) - paddlex.utils.utils.load_pretrain_weights( - self.exe, self.train_prog, pretrain_weights, fuse_bn) + paddlex.utils.utils.load_pretrain_weights(self.exe, self.train_prog, + pretrain_weights, fuse_bn) # 进行裁剪 if sensitivities_file is not None: import paddleslim @@ -262,6 +262,7 @@ class BaseAPI: info['_Attributes']['num_classes'] = self.num_classes info['_Attributes']['labels'] = self.labels + info['_Attributes']['fixed_input_shape'] = self.fixed_input_shape try: primary_metric_key = list(self.eval_metrics.keys())[0] primary_metric_value = float(self.eval_metrics[primary_metric_key]) @@ -325,9 +326,7 @@ class BaseAPI: logging.info("Model saved in {}.".format(save_dir)) def export_inference_model(self, save_dir): - test_input_names = [ - var.name for var in list(self.test_inputs.values()) - ] + test_input_names = [var.name for var in list(self.test_inputs.values())] test_outputs = list(self.test_outputs.values()) if self.__class__.__name__ == 'MaskRCNN': from paddlex.utils.save import save_mask_inference_model @@ -364,8 +363,7 @@ class BaseAPI: # 模型保存成功的标志 open(osp.join(save_dir, '.success'), 'w').close() - logging.info("Model for inference deploy saved in {}.".format( - save_dir)) + logging.info("Model for inference deploy saved in {}.".format(save_dir)) def train_loop(self, num_epochs, @@ -489,13 +487,11 @@ class BaseAPI: eta = ((num_epochs - i) * total_num_steps - step - 1 ) * avg_step_time if time_eval_one_epoch is not None: - eval_eta = ( - total_eval_times - i // save_interval_epochs - ) * time_eval_one_epoch + eval_eta = (total_eval_times - i // save_interval_epochs + ) * time_eval_one_epoch else: - eval_eta = ( - total_eval_times - i // save_interval_epochs - ) * total_num_steps_eval * avg_step_time + eval_eta = (total_eval_times - i // save_interval_epochs + ) * total_num_steps_eval * avg_step_time eta_str = seconds_to_hms(eta + eval_eta) logging.info( diff --git a/paddlex/cv/models/classifier.py b/paddlex/cv/models/classifier.py index 7248b211cf72dfeb1d7f2a750dbc4549d34553d0..48a0d17604e7af59377af49967fb8c527f094b09 100644 --- a/paddlex/cv/models/classifier.py +++ b/paddlex/cv/models/classifier.py @@ -48,6 +48,8 @@ class BaseClassifier(BaseAPI): self.fixed_input_shape = None def build_net(self, mode='train'): + if self.__class__.__name__ == "AlexNet": + assert self.fixed_input_shape is not None, "In AlexNet, input_shape should be defined, e.g. model = paddlex.cls.AlexNet(num_classes=1000, input_shape=[224, 224])" if self.fixed_input_shape is not None: input_shape = [ None, 3, self.fixed_input_shape[1], self.fixed_input_shape[0] @@ -427,3 +429,10 @@ class HRNet_W18(BaseClassifier): def __init__(self, num_classes=1000): super(HRNet_W18, self).__init__( model_name='HRNet_W18', num_classes=num_classes) + + +class AlexNet(BaseClassifier): + def __init__(self, num_classes=1000, input_shape=None): + super(AlexNet, self).__init__( + model_name='AlexNet', num_classes=num_classes) + self.fixed_input_shape = input_shape diff --git a/paddlex/cv/models/load_model.py b/paddlex/cv/models/load_model.py index 738f4ff00452d278b3988d9303bb15b0d8885979..5138445afcd8c8fd8f4d0d396703b3280d4e3e51 100644 --- a/paddlex/cv/models/load_model.py +++ b/paddlex/cv/models/load_model.py @@ -41,7 +41,16 @@ def load_model(model_dir, fixed_input_shape=None): if 'model_name' in info['_init_params']: del info['_init_params']['model_name'] model = getattr(paddlex.cv.models, info['Model'])(**info['_init_params']) + model.fixed_input_shape = fixed_input_shape + if '_Attributes' in info: + if 'fixed_input_shape' in info['_Attributes']: + fixed_input_shape = info['_Attributes']['fixed_input_shape'] + if fixed_input_shape is not None: + logging.info("Model already has fixed_input_shape with {}". + format(fixed_input_shape)) + model.fixed_input_shape = fixed_input_shape + if status == "Normal" or \ status == "Prune" or status == "fluid.save": startup_prog = fluid.Program() @@ -88,8 +97,8 @@ def load_model(model_dir, fixed_input_shape=None): model.model_type, info['Transforms'], info['BatchTransforms']) model.eval_transforms = copy.deepcopy(model.test_transforms) else: - model.test_transforms = build_transforms( - model.model_type, info['Transforms'], to_rgb) + model.test_transforms = build_transforms(model.model_type, + info['Transforms'], to_rgb) model.eval_transforms = copy.deepcopy(model.test_transforms) if '_Attributes' in info: diff --git a/paddlex/cv/models/utils/pretrain_weights.py b/paddlex/cv/models/utils/pretrain_weights.py index 3abbdd93d80efd5eb41ead32ac321d758d080104..39d9cb50c61e27a8516790cfd2984153ca84cc6e 100644 --- a/paddlex/cv/models/utils/pretrain_weights.py +++ b/paddlex/cv/models/utils/pretrain_weights.py @@ -70,6 +70,8 @@ image_pretrain = { 'https://paddle-imagenet-models-name.bj.bcebos.com/HRNet_W60_C_pretrained.tar', 'HRNet_W64': 'https://paddle-imagenet-models-name.bj.bcebos.com/HRNet_W64_C_pretrained.tar', + 'AlexNet': + 'http://paddle-imagenet-models-name.bj.bcebos.com/AlexNet_pretrained.tar' } coco_pretrain = { @@ -99,10 +101,12 @@ def get_pretrain_weights(flag, model_type, backbone, save_dir): backbone = 'DetResNet50' assert backbone in image_pretrain, "There is not ImageNet pretrain weights for {}, you may try COCO.".format( backbone) - # url = image_pretrain[backbone] - # fname = osp.split(url)[-1].split('.')[0] - # paddlex.utils.download_and_decompress(url, path=new_save_dir) - # return osp.join(new_save_dir, fname) + + if backbone == 'AlexNet': + url = image_pretrain[backbone] + fname = osp.split(url)[-1].split('.')[0] + paddlex.utils.download_and_decompress(url, path=new_save_dir) + return osp.join(new_save_dir, fname) try: hub.download(backbone, save_path=new_save_dir) except Exception as e: diff --git a/paddlex/cv/nets/__init__.py b/paddlex/cv/nets/__init__.py index b1441c59395c2f7788dbab937ab5ad629d4aa940..6e5102a26c9a573db25ad63984dad41c633c987d 100644 --- a/paddlex/cv/nets/__init__.py +++ b/paddlex/cv/nets/__init__.py @@ -24,6 +24,7 @@ from .xception import Xception from .densenet import DenseNet from .shufflenet_v2 import ShuffleNetV2 from .hrnet import HRNet +from .alexnet import AlexNet def resnet18(input, num_classes=1000): @@ -153,3 +154,8 @@ def shufflenetv2(input, num_classes=1000): def hrnet_w18(input, num_classes=1000): model = HRNet(width=18, num_classes=num_classes) return model(input) + + +def alexnet(input, num_classes=1000): + model = AlexNet(num_classes=num_classes) + return model(input) diff --git a/paddlex/cv/nets/alexnet.py b/paddlex/cv/nets/alexnet.py new file mode 100644 index 0000000000000000000000000000000000000000..6770f437d982428cd8d5ed7edb44e00915754139 --- /dev/null +++ b/paddlex/cv/nets/alexnet.py @@ -0,0 +1,170 @@ +#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 +# +# 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 + + +class AlexNet(): + def __init__(self, num_classes=1000): + assert num_classes is not None, "In AlextNet, num_classes cannot be None" + self.num_classes = num_classes + + def __call__(self, input): + stdv = 1.0 / math.sqrt(input.shape[1] * 11 * 11) + layer_name = [ + "conv1", "conv2", "conv3", "conv4", "conv5", "fc6", "fc7", "fc8" + ] + conv1 = fluid.layers.conv2d( + input=input, + num_filters=64, + filter_size=11, + stride=4, + padding=2, + groups=1, + act='relu', + bias_attr=fluid.param_attr.ParamAttr( + initializer=fluid.initializer.Uniform(-stdv, stdv), + name=layer_name[0] + "_offset"), + param_attr=fluid.param_attr.ParamAttr( + initializer=fluid.initializer.Uniform(-stdv, stdv), + name=layer_name[0] + "_weights")) + pool1 = fluid.layers.pool2d( + input=conv1, + pool_size=3, + pool_stride=2, + pool_padding=0, + pool_type='max') + + stdv = 1.0 / math.sqrt(pool1.shape[1] * 5 * 5) + conv2 = fluid.layers.conv2d( + input=pool1, + num_filters=192, + filter_size=5, + stride=1, + padding=2, + groups=1, + act='relu', + bias_attr=fluid.param_attr.ParamAttr( + initializer=fluid.initializer.Uniform(-stdv, stdv), + name=layer_name[1] + "_offset"), + param_attr=fluid.param_attr.ParamAttr( + initializer=fluid.initializer.Uniform(-stdv, stdv), + name=layer_name[1] + "_weights")) + pool2 = fluid.layers.pool2d( + input=conv2, + pool_size=3, + pool_stride=2, + pool_padding=0, + pool_type='max') + + stdv = 1.0 / math.sqrt(pool2.shape[1] * 3 * 3) + conv3 = fluid.layers.conv2d( + input=pool2, + num_filters=384, + filter_size=3, + stride=1, + padding=1, + groups=1, + act='relu', + bias_attr=fluid.param_attr.ParamAttr( + initializer=fluid.initializer.Uniform(-stdv, stdv), + name=layer_name[2] + "_offset"), + param_attr=fluid.param_attr.ParamAttr( + initializer=fluid.initializer.Uniform(-stdv, stdv), + name=layer_name[2] + "_weights")) + + stdv = 1.0 / math.sqrt(conv3.shape[1] * 3 * 3) + conv4 = fluid.layers.conv2d( + input=conv3, + num_filters=256, + filter_size=3, + stride=1, + padding=1, + groups=1, + act='relu', + bias_attr=fluid.param_attr.ParamAttr( + initializer=fluid.initializer.Uniform(-stdv, stdv), + name=layer_name[3] + "_offset"), + param_attr=fluid.param_attr.ParamAttr( + initializer=fluid.initializer.Uniform(-stdv, stdv), + name=layer_name[3] + "_weights")) + + stdv = 1.0 / math.sqrt(conv4.shape[1] * 3 * 3) + conv5 = fluid.layers.conv2d( + input=conv4, + num_filters=256, + filter_size=3, + stride=1, + padding=1, + groups=1, + act='relu', + bias_attr=fluid.param_attr.ParamAttr( + initializer=fluid.initializer.Uniform(-stdv, stdv), + name=layer_name[4] + "_offset"), + param_attr=fluid.param_attr.ParamAttr( + initializer=fluid.initializer.Uniform(-stdv, stdv), + name=layer_name[4] + "_weights")) + pool5 = fluid.layers.pool2d( + input=conv5, + pool_size=3, + pool_stride=2, + pool_padding=0, + pool_type='max') + + drop6 = fluid.layers.dropout(x=pool5, dropout_prob=0.5) + stdv = 1.0 / math.sqrt(drop6.shape[1] * drop6.shape[2] * + drop6.shape[3] * 1.0) + + fc6 = fluid.layers.fc( + input=drop6, + size=4096, + act='relu', + bias_attr=fluid.param_attr.ParamAttr( + initializer=fluid.initializer.Uniform(-stdv, stdv), + name=layer_name[5] + "_offset"), + param_attr=fluid.param_attr.ParamAttr( + initializer=fluid.initializer.Uniform(-stdv, stdv), + name=layer_name[5] + "_weights")) + drop7 = fluid.layers.dropout(x=fc6, dropout_prob=0.5) + stdv = 1.0 / math.sqrt(drop7.shape[1] * 1.0) + + fc7 = fluid.layers.fc( + input=drop7, + size=4096, + act='relu', + bias_attr=fluid.param_attr.ParamAttr( + initializer=fluid.initializer.Uniform(-stdv, stdv), + name=layer_name[6] + "_offset"), + param_attr=fluid.param_attr.ParamAttr( + initializer=fluid.initializer.Uniform(-stdv, stdv), + name=layer_name[6] + "_weights")) + + stdv = 1.0 / math.sqrt(fc7.shape[1] * 1.0) + out = fluid.layers.fc( + input=fc7, + size=self.num_classes, + bias_attr=fluid.param_attr.ParamAttr( + initializer=fluid.initializer.Uniform(-stdv, stdv), + name=layer_name[7] + "_offset"), + param_attr=fluid.param_attr.ParamAttr( + initializer=fluid.initializer.Uniform(-stdv, stdv), + name=layer_name[7] + "_weights")) + return out diff --git a/setup.py b/setup.py index db62ca5e9e8107f2f32e804a0e92fb48766d3c27..44aca0f9dc2a214ff4bcf4e2817d06423c26812b 100644 --- a/setup.py +++ b/setup.py @@ -19,7 +19,7 @@ long_description = "PaddleX. A end-to-end deeplearning model development toolkit setuptools.setup( name="paddlex", - version='1.0.5', + version='1.0.6', author="paddlex", author_email="paddlex@baidu.com", description=long_description,