Răsfoiți Sursa

Merge pull request #126 from PaddlePaddle/develop

fix v1.0.4 bug
Jason 5 ani în urmă
părinte
comite
8654456987

+ 2 - 0
.pre-commit-config.yaml

@@ -23,6 +23,7 @@
         files: \.(c|cc|cxx|cpp|cu|h|hpp|hxx|proto|py)$
         files: \.(c|cc|cxx|cpp|cu|h|hpp|hxx|proto|py)$
         exclude: (?!.*third_party)^.*$
         exclude: (?!.*third_party)^.*$
 
 
+-   repo: local
     hooks:
     hooks:
     -   id: clang-format-with-version-check
     -   id: clang-format-with-version-check
         name: clang-format
         name: clang-format
@@ -31,6 +32,7 @@
         language: system
         language: system
         files: \.(c|cc|cxx|cpp|cu|h|hpp|hxx|proto)$
         files: \.(c|cc|cxx|cpp|cu|h|hpp|hxx|proto)$
 
 
+-   repo: local
     hooks:
     hooks:
     -   id: cpplint-cpp-source
     -   id: cpplint-cpp-source
         name: cpplint
         name: cpplint

+ 2 - 6
deploy/cpp/include/paddlex/transforms.h

@@ -83,7 +83,7 @@ class ResizeByShort : public Transform {
     } else {
     } else {
       max_size_ = -1;
       max_size_ = -1;
     }
     }
-  };
+  }
   virtual bool Run(cv::Mat* im, ImageBlob* data);
   virtual bool Run(cv::Mat* im, ImageBlob* data);
 
 
  private:
  private:
@@ -96,7 +96,7 @@ class ResizeByLong : public Transform {
  public:
  public:
   virtual void Init(const YAML::Node& item) {
   virtual void Init(const YAML::Node& item) {
     long_size_ = item["long_size"].as<int>();
     long_size_ = item["long_size"].as<int>();
-  };
+  }
   virtual bool Run(cv::Mat* im, ImageBlob* data);
   virtual bool Run(cv::Mat* im, ImageBlob* data);
 
 
  private:
  private:
@@ -167,9 +167,6 @@ class Padding : public Transform {
         height_ = item["target_size"].as<std::vector<int>>()[1];
         height_ = item["target_size"].as<std::vector<int>>()[1];
       }
       }
     }
     }
-    if (item["im_padding_value"].IsDefined()) {
-      value_ = item["im_padding_value"].as<std::vector<float>>();
-    }
   }
   }
   virtual bool Run(cv::Mat* im, ImageBlob* data);
   virtual bool Run(cv::Mat* im, ImageBlob* data);
 
 
@@ -177,7 +174,6 @@ class Padding : public Transform {
   int coarsest_stride_ = -1;
   int coarsest_stride_ = -1;
   int width_ = 0;
   int width_ = 0;
   int height_ = 0;
   int height_ = 0;
-  std::vector<float> value_;
 };
 };
 
 
 class Transforms {
 class Transforms {

+ 7 - 7
docs/apis/transforms/det_transforms.md

@@ -232,12 +232,12 @@ eval_transforms = transforms.Composed([
 ```
 ```
 
 
 
 
-## ComposedYOLOTransforms类
+## ComposedYOLOv3Transforms类
 ```python
 ```python
-paddlex.det.transforms.ComposedYOLOTransforms(mode, shape=[608, 608], mixup_epoch=250, mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
+paddlex.det.transforms.ComposedYOLOv3Transforms(mode, shape=[608, 608], mixup_epoch=250, mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
 ```
 ```
-目标检测YOLOv3模型中已经组合好的数据处理流程,开发者可以直接使用ComposedYOLOTransforms,简化手动组合transforms的过程, 该类中已经包含了[MixupImage](#MixupImage)、[RandomDistort](#RandomDistort)、[RandomExpand](#RandomExpand)、[RandomCrop](#RandomCrop)、[RandomHorizontalFlip](#RandomHorizontalFlip)5种数据增强方式,你仍可以通过[add_augmenters函数接口](#add_augmenters)添加新的数据增强方式。  
-ComposedYOLOTransforms共包括以下几个步骤:
+目标检测YOLOv3模型中已经组合好的数据处理流程,开发者可以直接使用ComposedYOLOv3Transforms,简化手动组合transforms的过程, 该类中已经包含了[MixupImage](#MixupImage)、[RandomDistort](#RandomDistort)、[RandomExpand](#RandomExpand)、[RandomCrop](#RandomCrop)、[RandomHorizontalFlip](#RandomHorizontalFlip)5种数据增强方式,你仍可以通过[add_augmenters函数接口](#add_augmenters)添加新的数据增强方式。  
+ComposedYOLOv3Transforms共包括以下几个步骤:
 > 训练阶段:
 > 训练阶段:
 > > 1. 在前mixup_epoch轮迭代中,使用MixupImage策略
 > > 1. 在前mixup_epoch轮迭代中,使用MixupImage策略
 > > 2. 对图像进行随机扰动,包括亮度,对比度,饱和度和色调
 > > 2. 对图像进行随机扰动,包括亮度,对比度,饱和度和色调
@@ -259,7 +259,7 @@ ComposedYOLOTransforms共包括以下几个步骤:
 
 
 ### 添加数据增强方式
 ### 添加数据增强方式
 ```python
 ```python
-ComposedYOLOTransforms.add_augmenters(augmenters)
+ComposedYOLOv3Transforms.add_augmenters(augmenters)
 ```
 ```
 > **参数**
 > **参数**
 > * **augmenters**(list): 数据增强方式列表
 > * **augmenters**(list): 数据增强方式列表
@@ -268,8 +268,8 @@ ComposedYOLOTransforms.add_augmenters(augmenters)
 ```
 ```
 import paddlex as pdx
 import paddlex as pdx
 from paddlex.det import transforms
 from paddlex.det import transforms
-train_transforms = transforms.ComposedYOLOTransforms(mode='train', shape=[480, 480])
-eval_transforms = transforms.ComposedYOLOTransforms(mode='eval', shape=[480, 480])
+train_transforms = transforms.ComposedYOLOv3Transforms(mode='train', shape=[480, 480])
+eval_transforms = transforms.ComposedYOLOv3Transforms(mode='eval', shape=[480, 480])
 
 
 # 添加数据增强
 # 添加数据增强
 import imgaug.augmenters as iaa
 import imgaug.augmenters as iaa

+ 18 - 0
new_tutorials/train/README.md

@@ -0,0 +1,18 @@
+# 使用教程——训练模型
+
+本目录下整理了使用PaddleX训练模型的示例代码,代码中均提供了示例数据的自动下载,并均使用单张GPU卡进行训练。
+
+|代码 | 模型任务 | 数据 |
+|------|--------|---------|
+|classification/mobilenetv2.py | 图像分类MobileNetV2 | 蔬菜分类 |
+|classification/resnet50.py | 图像分类ResNet50 | 蔬菜分类 |
+|detection/faster_rcnn_r50_fpn.py | 目标检测FasterRCNN | 昆虫检测 |
+|detection/mask_rcnn_f50_fpn.py | 实例分割MaskRCNN | 垃圾分拣 |
+|segmentation/deeplabv3p.py | 语义分割DeepLabV3| 视盘分割 |
+|segmentation/unet.py | 语义分割UNet | 视盘分割 |
+
+## 开始训练
+在安装PaddleX后,使用如下命令开始训练
+```
+python classification/mobilenetv2.py
+```

+ 47 - 0
new_tutorials/train/classification/mobilenetv2.py

@@ -0,0 +1,47 @@
+import os
+# 选择使用0号卡
+os.environ['CUDA_VISIBLE_DEVICES'] = '0'
+
+from paddlex.cls import transforms
+import paddlex as pdx
+
+# 下载和解压蔬菜分类数据集
+veg_dataset = 'https://bj.bcebos.com/paddlex/datasets/vegetables_cls.tar.gz'
+pdx.utils.download_and_decompress(veg_dataset, path='./')
+
+# 定义训练和验证时的transforms
+# API说明: https://paddlex.readthedocs.io/zh_CN/latest/apis/transforms/cls_transforms.html#composedclstransforms
+train_transforms = transforms.ComposedClsTransforms(mode='train', crop_size=[224, 224])
+eval_transforms = transforms.ComposedClsTransforms(mode='eval', crop_size=[224, 224])
+
+# 定义训练和验证所用的数据集
+# API说明: https://paddlex.readthedocs.io/zh_CN/latest/apis/datasets/classification.html#imagenet
+train_dataset = pdx.datasets.ImageNet(
+    data_dir='vegetables_cls',
+    file_list='vegetables_cls/train_list.txt',
+    label_list='vegetables_cls/labels.txt',
+    transforms=train_transforms,
+    shuffle=True)
+eval_dataset = pdx.datasets.ImageNet(
+    data_dir='vegetables_cls',
+    file_list='vegetables_cls/val_list.txt',
+    label_list='vegetables_cls/labels.txt',
+    transforms=eval_transforms)
+
+# 初始化模型,并进行训练
+# 可使用VisualDL查看训练指标
+# VisualDL启动方式: visualdl --logdir output/mobilenetv2/vdl_log --port 8001
+# 浏览器打开 https://0.0.0.0:8001即可
+# 其中0.0.0.0为本机访问,如为远程服务, 改成相应机器IP
+
+# API说明: https://paddlex.readthedocs.io/zh_CN/latest/apis/models/classification.html#resnet50
+model = pdx.cls.MobileNetV2(num_classes=len(train_dataset.labels))
+model.train(
+    num_epochs=10,
+    train_dataset=train_dataset,
+    train_batch_size=32,
+    eval_dataset=eval_dataset,
+    lr_decay_epochs=[4, 6, 8],
+    learning_rate=0.025,
+    save_dir='output/mobilenetv2',
+    use_vdl=True)

+ 56 - 0
new_tutorials/train/classification/resnet50.py

@@ -0,0 +1,56 @@
+import os
+# 选择使用0号卡
+os.environ['CUDA_VISIBLE_DEVICES'] = '0'
+
+import paddle.fluid as fluid
+from paddlex.cls import transforms
+import paddlex as pdx
+
+# 下载和解压蔬菜分类数据集
+veg_dataset = 'https://bj.bcebos.com/paddlex/datasets/vegetables_cls.tar.gz'
+pdx.utils.download_and_decompress(veg_dataset, path='./')
+
+# 定义训练和验证时的transforms
+# API说明: https://paddlex.readthedocs.io/zh_CN/latest/apis/transforms/cls_transforms.html#composedclstransforms
+train_transforms = transforms.ComposedClsTransforms(mode='train', crop_size=[224, 224])
+eval_transforms = transforms.ComposedClsTransforms(mode='eval', crop_size=[224, 224])
+
+# 定义训练和验证所用的数据集
+# API说明: https://paddlex.readthedocs.io/zh_CN/latest/apis/datasets/classification.html#imagenet
+train_dataset = pdx.datasets.ImageNet(
+    data_dir='vegetables_cls',
+    file_list='vegetables_cls/train_list.txt',
+    label_list='vegetables_cls/labels.txt',
+    transforms=train_transforms,
+    shuffle=True)
+eval_dataset = pdx.datasets.ImageNet(
+    data_dir='vegetables_cls',
+    file_list='vegetables_cls/val_list.txt',
+    label_list='vegetables_cls/labels.txt',
+    transforms=eval_transforms)
+
+# PaddleX支持自定义构建优化器
+step_each_epoch = train_dataset.num_samples // 32
+learning_rate = fluid.layers.cosine_decay(
+    learning_rate=0.025, step_each_epoch=step_each_epoch, epochs=10)
+optimizer = fluid.optimizer.Momentum(
+    learning_rate=learning_rate,
+    momentum=0.9,
+    regularization=fluid.regularizer.L2Decay(4e-5))
+
+# 初始化模型,并进行训练
+# 可使用VisualDL查看训练指标
+# VisualDL启动方式: visualdl --logdir output/resnet50/vdl_log --port 8001
+# 浏览器打开 https://0.0.0.0:8001即可
+# 其中0.0.0.0为本机访问,如为远程服务, 改成相应机器IP
+
+# API说明: https://paddlex.readthedocs.io/zh_CN/latest/apis/models/classification.html#resnet50
+model = pdx.cls.ResNet50(num_classes=len(train_dataset.labels))
+model.train(
+    num_epochs=10,
+    train_dataset=train_dataset,
+    train_batch_size=32,
+    eval_dataset=eval_dataset,
+    optimizer=optimizer,
+    save_dir='output/resnet50',
+    use_vdl=True)

+ 49 - 0
new_tutorials/train/detection/faster_rcnn_r50_fpn.py

@@ -0,0 +1,49 @@
+import os
+# 选择使用0号卡
+os.environ['CUDA_VISIBLE_DEVICES'] = '0'
+
+from paddlex.det import transforms
+import paddlex as pdx
+
+# 下载和解压昆虫检测数据集
+insect_dataset = 'https://bj.bcebos.com/paddlex/datasets/insect_det.tar.gz'
+pdx.utils.download_and_decompress(insect_dataset, path='./')
+
+# 定义训练和验证时的transforms
+# API说明: https://paddlex.readthedocs.io/zh_CN/latest/apis/transforms/det_transforms.html#composedrcnntransforms
+train_transforms = transforms.ComposedRCNNTransforms(mode='train', min_max_size=[800, 1333])
+eval_transforms = transforms.ComposedRCNNTransforms(mode='eval', min_max_size=[800, 1333])
+
+# 定义训练和验证所用的数据集
+# API说明: https://paddlex.readthedocs.io/zh_CN/latest/apis/datasets/detection.html#vocdetection
+train_dataset = pdx.datasets.VOCDetection(
+    data_dir='insect_det',
+    file_list='insect_det/train_list.txt',
+    label_list='insect_det/labels.txt',
+    transforms=train_transforms,
+    shuffle=True)
+eval_dataset = pdx.datasets.VOCDetection(
+    data_dir='insect_det',
+    file_list='insect_det/val_list.txt',
+    label_list='insect_det/labels.txt',
+    transforms=eval_transforms)
+
+# 初始化模型,并进行训练
+# 可使用VisualDL查看训练指标
+# VisualDL启动方式: visualdl --logdir output/faster_rcnn_r50_fpn/vdl_log --port 8001
+# 浏览器打开 https://0.0.0.0:8001即可
+# 其中0.0.0.0为本机访问,如为远程服务, 改成相应机器IP
+# num_classes 需要设置为包含背景类的类别数,即: 目标类别数量 + 1
+
+# API说明: https://paddlex.readthedocs.io/zh_CN/latest/apis/models/detection.html#fasterrcnn
+num_classes = len(train_dataset.labels) + 1
+model = pdx.det.FasterRCNN(num_classes=num_classes)
+model.train(
+    num_epochs=12,
+    train_dataset=train_dataset,
+    train_batch_size=2,
+    eval_dataset=eval_dataset,
+    learning_rate=0.0025,
+    lr_decay_epochs=[8, 11],
+    save_dir='output/faster_rcnn_r50_fpn',
+    use_vdl=True)

+ 48 - 0
new_tutorials/train/detection/mask_rcnn_r50_fpn.py

@@ -0,0 +1,48 @@
+import os
+# 选择使用0号卡
+os.environ['CUDA_VISIBLE_DEVICES'] = '0'
+
+from paddlex.det import transforms
+import paddlex as pdx
+
+# 下载和解压小度熊分拣数据集
+xiaoduxiong_dataset = 'https://bj.bcebos.com/paddlex/datasets/xiaoduxiong_ins_det.tar.gz'
+pdx.utils.download_and_decompress(xiaoduxiong_dataset, path='./')
+
+# 定义训练和验证时的transforms
+# API说明: https://paddlex.readthedocs.io/zh_CN/latest/apis/transforms/det_transforms.html#composedrcnntransforms
+train_transforms = transforms.ComposedRCNNTransforms(mode='train', min_max_size=[800, 1333])
+eval_transforms = transforms.ComposedRCNNTransforms(mode='eval', min_max_size=[800, 1333])
+
+# 定义训练和验证所用的数据集
+# API说明: https://paddlex.readthedocs.io/zh_CN/latest/apis/datasets/detection.html#cocodetection
+train_dataset = pdx.datasets.CocoDetection(
+    data_dir='xiaoduxiong_ins_det/JPEGImages',
+    ann_file='xiaoduxiong_ins_det/train.json',
+    transforms=train_transforms,
+    shuffle=True)
+eval_dataset = pdx.datasets.CocoDetection(
+    data_dir='xiaoduxiong_ins_det/JPEGImages',
+    ann_file='xiaoduxiong_ins_det/val.json',
+    transforms=eval_transforms)
+
+# 初始化模型,并进行训练
+# 可使用VisualDL查看训练指标
+# VisualDL启动方式: visualdl --logdir output/mask_rcnn_r50_fpn/vdl_log --port 8001
+# 浏览器打开 https://0.0.0.0:8001即可
+# 其中0.0.0.0为本机访问,如为远程服务, 改成相应机器IP
+# num_classes 需要设置为包含背景类的类别数,即: 目标类别数量 + 1
+
+# API说明: https://paddlex.readthedocs.io/zh_CN/latest/apis/models/instance_segmentation.html#maskrcnn
+num_classes = len(train_dataset.labels) + 1
+model = pdx.det.MaskRCNN(num_classes=num_classes)
+model.train(
+    num_epochs=12,
+    train_dataset=train_dataset,
+    train_batch_size=1,
+    eval_dataset=eval_dataset,
+    learning_rate=0.00125,
+    warmup_steps=10,
+    lr_decay_epochs=[8, 11],
+    save_dir='output/mask_rcnn_r50_fpn',
+    use_vdl=True)

+ 48 - 0
new_tutorials/train/detection/yolov3_darknet53.py

@@ -0,0 +1,48 @@
+import os
+# 选择使用0号卡
+os.environ['CUDA_VISIBLE_DEVICES'] = '0'
+
+from paddlex.det import transforms
+import paddlex as pdx
+
+# 下载和解压昆虫检测数据集
+insect_dataset = 'https://bj.bcebos.com/paddlex/datasets/insect_det.tar.gz'
+pdx.utils.download_and_decompress(insect_dataset, path='./')
+
+# 定义训练和验证时的transforms
+# API说明: https://paddlex.readthedocs.io/zh_CN/latest/apis/transforms/det_transforms.html#composedyolotransforms
+train_transforms = transforms.ComposedYOLOv3Transforms(mode='train', shape=[608, 608])
+eval_transforms = transforms.ComposedYOLOv3Transforms(mode='eva', shape=[608, 608])
+
+# 定义训练和验证所用的数据集
+# API说明: https://paddlex.readthedocs.io/zh_CN/latest/apis/datasets/detection.html#vocdetection
+train_dataset = pdx.datasets.VOCDetection(
+    data_dir='insect_det',
+    file_list='insect_det/train_list.txt',
+    label_list='insect_det/labels.txt',
+    transforms=train_transforms,
+    shuffle=True)
+eval_dataset = pdx.datasets.VOCDetection(
+    data_dir='insect_det',
+    file_list='insect_det/val_list.txt',
+    label_list='insect_det/labels.txt',
+    transforms=eval_transforms)
+
+# 初始化模型,并进行训练
+# 可使用VisualDL查看训练指标
+# VisualDL启动方式: visualdl --logdir output/yolov3_darknet/vdl_log --port 8001
+# 浏览器打开 https://0.0.0.0:8001即可
+# 其中0.0.0.0为本机访问,如为远程服务, 改成相应机器IP
+
+# API说明: https://paddlex.readthedocs.io/zh_CN/latest/apis/models/detection.html#yolov3
+num_classes = len(train_dataset.labels)
+model = pdx.det.YOLOv3(num_classes=num_classes, backbone='DarkNet53')
+model.train(
+    num_epochs=270,
+    train_dataset=train_dataset,
+    train_batch_size=8,
+    eval_dataset=eval_dataset,
+    learning_rate=0.000125,
+    lr_decay_epochs=[210, 240],
+    save_dir='output/yolov3_darknet53',
+    use_vdl=True)

+ 51 - 0
new_tutorials/train/segmentation/deeplabv3p.py

@@ -0,0 +1,51 @@
+import os
+# 选择使用0号卡
+os.environ['CUDA_VISIBLE_DEVICES'] = '0'
+
+import paddlex as pdx
+from paddlex.seg import transforms
+
+# 下载和解压视盘分割数据集
+optic_dataset = 'https://bj.bcebos.com/paddlex/datasets/optic_disc_seg.tar.gz'
+pdx.utils.download_and_decompress(optic_dataset, path='./')
+
+# 定义训练和验证时的transforms
+# API说明: https://paddlex.readthedocs.io/zh_CN/latest/apis/transforms/seg_transforms.html#composedsegtransforms
+train_transforms = transforms.ComposedSegTransforms(mode='train', train_crop_size=[769, 769])
+eval_transforms = transforms.ComposedSegTransforms(mode='eval')
+
+train_transforms.add_augmenters([
+    transforms.RandomRotate()
+])
+
+# 定义训练和验证所用的数据集
+# API说明: https://paddlex.readthedocs.io/zh_CN/latest/apis/datasets/semantic_segmentation.html#segdataset
+train_dataset = pdx.datasets.SegDataset(
+    data_dir='optic_disc_seg',
+    file_list='optic_disc_seg/train_list.txt',
+    label_list='optic_disc_seg/labels.txt',
+    transforms=train_transforms,
+    shuffle=True)
+eval_dataset = pdx.datasets.SegDataset(
+    data_dir='optic_disc_seg',
+    file_list='optic_disc_seg/val_list.txt',
+    label_list='optic_disc_seg/labels.txt',
+    transforms=eval_transforms)
+
+# 初始化模型,并进行训练
+# 可使用VisualDL查看训练指标
+# VisualDL启动方式: visualdl --logdir output/deeplab/vdl_log --port 8001
+# 浏览器打开 https://0.0.0.0:8001即可
+# 其中0.0.0.0为本机访问,如为远程服务, 改成相应机器IP
+
+# API说明: https://paddlex.readthedocs.io/zh_CN/latest/apis/models/semantic_segmentation.html#deeplabv3p
+num_classes = len(train_dataset.labels)
+model = pdx.seg.DeepLabv3p(num_classes=num_classes)
+model.train(
+    num_epochs=40,
+    train_dataset=train_dataset,
+    train_batch_size=4,
+    eval_dataset=eval_dataset,
+    learning_rate=0.01,
+    save_dir='output/deeplab',
+    use_vdl=True)

+ 47 - 0
new_tutorials/train/segmentation/hrnet.py

@@ -0,0 +1,47 @@
+import os
+# 选择使用0号卡
+os.environ['CUDA_VISIBLE_DEVICES'] = '0'
+
+import paddlex as pdx
+from paddlex.seg import transforms
+
+# 下载和解压视盘分割数据集
+optic_dataset = 'https://bj.bcebos.com/paddlex/datasets/optic_disc_seg.tar.gz'
+pdx.utils.download_and_decompress(optic_dataset, path='./')
+
+# 定义训练和验证时的transforms
+# API说明: https://paddlex.readthedocs.io/zh_CN/latest/apis/transforms/seg_transforms.html#composedsegtransforms
+train_transforms = transforms.ComposedSegTransforms(mode='train', train_crop_size=[769, 769])
+eval_transforms = transforms.ComposedSegTransforms(mode='eval')
+
+# 定义训练和验证所用的数据集
+# API说明: https://paddlex.readthedocs.io/zh_CN/latest/apis/datasets/semantic_segmentation.html#segdataset
+train_dataset = pdx.datasets.SegDataset(
+    data_dir='optic_disc_seg',
+    file_list='optic_disc_seg/train_list.txt',
+    label_list='optic_disc_seg/labels.txt',
+    transforms=train_transforms,
+    shuffle=True)
+eval_dataset = pdx.datasets.SegDataset(
+    data_dir='optic_disc_seg',
+    file_list='optic_disc_seg/val_list.txt',
+    label_list='optic_disc_seg/labels.txt',
+    transforms=eval_transforms)
+
+# 初始化模型,并进行训练
+# 可使用VisualDL查看训练指标
+# VisualDL启动方式: visualdl --logdir output/unet/vdl_log --port 8001
+# 浏览器打开 https://0.0.0.0:8001即可
+# 其中0.0.0.0为本机访问,如为远程服务, 改成相应机器IP
+
+# https://paddlex.readthedocs.io/zh_CN/latest/apis/models/semantic_segmentation.html#hrnet
+num_classes = len(train_dataset.labels)
+model = pdx.seg.HRNet(num_classes=num_classes)
+model.train(
+    num_epochs=20,
+    train_dataset=train_dataset,
+    train_batch_size=4,
+    eval_dataset=eval_dataset,
+    learning_rate=0.01,
+    save_dir='output/hrnet',
+    use_vdl=True)

+ 47 - 0
new_tutorials/train/segmentation/unet.py

@@ -0,0 +1,47 @@
+import os
+# 选择使用0号卡
+os.environ['CUDA_VISIBLE_DEVICES'] = '0'
+
+import paddlex as pdx
+from paddlex.seg import transforms
+
+# 下载和解压视盘分割数据集
+optic_dataset = 'https://bj.bcebos.com/paddlex/datasets/optic_disc_seg.tar.gz'
+pdx.utils.download_and_decompress(optic_dataset, path='./')
+
+# 定义训练和验证时的transforms
+# API说明: https://paddlex.readthedocs.io/zh_CN/latest/apis/transforms/seg_transforms.html#composedsegtransforms
+train_transforms = transforms.ComposedSegTransforms(mode='train', train_crop_size=[769, 769])
+eval_transforms = transforms.ComposedSegTransforms(mode='eval')
+
+# 定义训练和验证所用的数据集
+# API说明: https://paddlex.readthedocs.io/zh_CN/latest/apis/datasets/semantic_segmentation.html#segdataset
+train_dataset = pdx.datasets.SegDataset(
+    data_dir='optic_disc_seg',
+    file_list='optic_disc_seg/train_list.txt',
+    label_list='optic_disc_seg/labels.txt',
+    transforms=train_transforms,
+    shuffle=True)
+eval_dataset = pdx.datasets.SegDataset(
+    data_dir='optic_disc_seg',
+    file_list='optic_disc_seg/val_list.txt',
+    label_list='optic_disc_seg/labels.txt',
+    transforms=eval_transforms)
+
+# 初始化模型,并进行训练
+# 可使用VisualDL查看训练指标
+# VisualDL启动方式: visualdl --logdir output/unet/vdl_log --port 8001
+# 浏览器打开 https://0.0.0.0:8001即可
+# 其中0.0.0.0为本机访问,如为远程服务, 改成相应机器IP
+
+# API说明: https://paddlex.readthedocs.io/zh_CN/latest/apis/models/semantic_segmentation.html#unet
+num_classes = len(train_dataset.labels)
+model = pdx.seg.UNet(num_classes=num_classes)
+model.train(
+    num_epochs=20,
+    train_dataset=train_dataset,
+    train_batch_size=4,
+    eval_dataset=eval_dataset,
+    learning_rate=0.01,
+    save_dir='output/unet',
+    use_vdl=True)

+ 1 - 1
paddlex/__init__.py

@@ -53,4 +53,4 @@ log_level = 2
 
 
 from . import interpret
 from . import interpret
 
 
-__version__ = '1.0.4'
+__version__ = '1.0.5'

+ 2 - 1
paddlex/cv/models/deeplabv3p.py

@@ -337,7 +337,8 @@ class DeepLabv3p(BaseAPI):
             for d in data:
             for d in data:
                 padding_label = np.zeros(
                 padding_label = np.zeros(
                     (1, im_h, im_w)).astype('int64') + self.ignore_index
                     (1, im_h, im_w)).astype('int64') + self.ignore_index
-                padding_label[:, :im_h, :im_w] = d[1]
+                _, label_h, label_w = d[1].shape
+                padding_label[:, :label_h, :label_w] = d[1]
                 labels.append(padding_label)
                 labels.append(padding_label)
             labels = np.array(labels)
             labels = np.array(labels)
 
 

+ 6 - 1
paddlex/cv/transforms/cls_transforms.py

@@ -18,6 +18,7 @@ import random
 import os.path as osp
 import os.path as osp
 import numpy as np
 import numpy as np
 from PIL import Image, ImageEnhance
 from PIL import Image, ImageEnhance
+import paddlex.utils.logging as logging
 
 
 
 
 class ClsTransform:
 class ClsTransform:
@@ -96,7 +97,11 @@ class Compose(ClsTransform):
         if not isinstance(augmenters, list):
         if not isinstance(augmenters, list):
             raise Exception(
             raise Exception(
                 "augmenters should be list type in func add_augmenters()")
                 "augmenters should be list type in func add_augmenters()")
-        self.transforms = augmenters + self.transforms.transforms
+        transform_names = [type(x).__name__ for x in self.transforms]
+        for aug in augmenters:
+            if type(aug).__name__ in transform_names:
+                logging.error("{} is already in ComposedTransforms, need to remove it from add_augmenters().".format(type(aug).__name__))
+        self.transforms = augmenters + self.transforms
 
 
 
 
 class RandomCrop(ClsTransform):
 class RandomCrop(ClsTransform):

+ 8 - 3
paddlex/cv/transforms/det_transforms.py

@@ -27,6 +27,7 @@ from PIL import Image, ImageEnhance
 from .imgaug_support import execute_imgaug
 from .imgaug_support import execute_imgaug
 from .ops import *
 from .ops import *
 from .box_utils import *
 from .box_utils import *
+import paddlex.utils.logging as logging
 
 
 
 
 class DetTransform:
 class DetTransform:
@@ -156,7 +157,11 @@ class Compose(DetTransform):
         if not isinstance(augmenters, list):
         if not isinstance(augmenters, list):
             raise Exception(
             raise Exception(
                 "augmenters should be list type in func add_augmenters()")
                 "augmenters should be list type in func add_augmenters()")
-        self.transforms = augmenters + self.transforms.transforms
+        transform_names = [type(x).__name__ for x in self.transforms]
+        for aug in augmenters:
+            if type(aug).__name__ in transform_names:
+                logging.error("{} is already in ComposedTransforms, need to remove it from add_augmenters().".format(type(aug).__name__))
+        self.transforms = augmenters + self.transforms
 
 
 
 
 class ResizeByShort(DetTransform):
 class ResizeByShort(DetTransform):
@@ -1282,7 +1287,7 @@ class ComposedRCNNTransforms(Compose):
         super(ComposedRCNNTransforms, self).__init__(transforms)
         super(ComposedRCNNTransforms, self).__init__(transforms)
 
 
 
 
-class ComposedYOLOTransforms(Compose):
+class ComposedYOLOv3Transforms(Compose):
     """YOLOv3模型的图像预处理流程,具体如下,
     """YOLOv3模型的图像预处理流程,具体如下,
         训练阶段:
         训练阶段:
         1. 在前mixup_epoch轮迭代中,使用MixupImage策略,见https://paddlex.readthedocs.io/zh_CN/latest/apis/transforms/det_transforms.html#mixupimage
         1. 在前mixup_epoch轮迭代中,使用MixupImage策略,见https://paddlex.readthedocs.io/zh_CN/latest/apis/transforms/det_transforms.html#mixupimage
@@ -1337,4 +1342,4 @@ class ComposedYOLOTransforms(Compose):
                     target_size=width, interp='CUBIC'), Normalize(
                     target_size=width, interp='CUBIC'), Normalize(
                         mean=mean, std=std)
                         mean=mean, std=std)
             ]
             ]
-        super(ComposedYOLOTransforms, self).__init__(transforms)
+        super(ComposedYOLOv3Transforms, self).__init__(transforms)

+ 6 - 1
paddlex/cv/transforms/seg_transforms.py

@@ -21,6 +21,7 @@ import numpy as np
 from PIL import Image
 from PIL import Image
 import cv2
 import cv2
 from collections import OrderedDict
 from collections import OrderedDict
+import paddlex.utils.logging as logging
 
 
 
 
 class SegTransform:
 class SegTransform:
@@ -112,7 +113,11 @@ class Compose(SegTransform):
         if not isinstance(augmenters, list):
         if not isinstance(augmenters, list):
             raise Exception(
             raise Exception(
                 "augmenters should be list type in func add_augmenters()")
                 "augmenters should be list type in func add_augmenters()")
-        self.transforms = augmenters + self.transforms.transforms
+        transform_names = [type(x).__name__ for x in self.transforms]
+        for aug in augmenters:
+            if type(aug).__name__ in transform_names:
+                logging.error("{} is already in ComposedTransforms, need to remove it from add_augmenters().".format(type(aug).__name__))
+        self.transforms = augmenters + self.transforms
 
 
 
 
 class RandomHorizontalFlip(SegTransform):
 class RandomHorizontalFlip(SegTransform):

+ 3 - 2
paddlex/utils/logging.py

@@ -47,9 +47,10 @@ def info(message="", use_color=False):
     log(level=2, message=message, use_color=use_color)
     log(level=2, message=message, use_color=use_color)
 
 
 
 
-def warning(message="", use_color=False):
+def warning(message="", use_color=True):
     log(level=1, message=message, use_color=use_color)
     log(level=1, message=message, use_color=use_color)
 
 
 
 
-def error(message="", use_color=False):
+def error(message="", use_color=True):
     log(level=0, message=message, use_color=use_color)
     log(level=0, message=message, use_color=use_color)
+    sys.exit(-1)

+ 1 - 1
setup.py

@@ -19,7 +19,7 @@ long_description = "PaddleX. A end-to-end deeplearning model development toolkit
 
 
 setuptools.setup(
 setuptools.setup(
     name="paddlex",
     name="paddlex",
-    version='1.0.4',
+    version='1.0.5',
     author="paddlex",
     author="paddlex",
     author_email="paddlex@baidu.com",
     author_email="paddlex@baidu.com",
     description=long_description,
     description=long_description,