Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
PaddlePaddle
PaddleX
提交
7b49b396
P
PaddleX
项目概览
PaddlePaddle
/
PaddleX
通知
138
Star
4
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
43
列表
看板
标记
里程碑
合并请求
5
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
P
PaddleX
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
43
Issue
43
列表
看板
标记
里程碑
合并请求
5
合并请求
5
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
7b49b396
编写于
7月 09, 2020
作者:
J
jiangjiajun
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
update and tutorials
上级
ca89f2fe
变更
33
隐藏空白更改
内联
并排
Showing
33 changed file
with
826 addition
and
421 deletion
+826
-421
docs/apis/datasets.md
docs/apis/datasets.md
+7
-7
docs/apis/models/classification.md
docs/apis/models/classification.md
+1
-1
docs/apis/models/detection.md
docs/apis/models/detection.md
+2
-2
docs/apis/models/instance_segmentation.md
docs/apis/models/instance_segmentation.md
+1
-1
docs/apis/models/semantic_segmentation.md
docs/apis/models/semantic_segmentation.md
+1
-1
docs/apis/transforms/augment.md
docs/apis/transforms/augment.md
+7
-7
docs/apis/transforms/cls_transforms.md
docs/apis/transforms/cls_transforms.md
+62
-62
docs/apis/transforms/det_transforms.md
docs/apis/transforms/det_transforms.md
+135
-130
docs/apis/transforms/seg_transforms.md
docs/apis/transforms/seg_transforms.md
+62
-58
docs/apis/visualize.md
docs/apis/visualize.md
+2
-2
docs/appendix/parameters.md
docs/appendix/parameters.md
+50
-34
docs/change_log.md
docs/change_log.md
+29
-7
docs/data/annotation.md
docs/data/annotation.md
+6
-2
docs/quick_start.md
docs/quick_start.md
+11
-11
docs/train/classification.md
docs/train/classification.md
+8
-5
docs/train/prediction.md
docs/train/prediction.md
+1
-1
paddlex/cv/transforms/seg_transforms.py
paddlex/cv/transforms/seg_transforms.py
+32
-21
tutorials/train/image_classification/alexnet.py
tutorials/train/image_classification/alexnet.py
+12
-22
tutorials/train/image_classification/mobilenetv2.py
tutorials/train/image_classification/mobilenetv2.py
+2
-7
tutorials/train/image_classification/mobilenetv3_small_ssld.py
...ials/train/image_classification/mobilenetv3_small_ssld.py
+46
-0
tutorials/train/image_classification/resnet50_vd_ssld.py
tutorials/train/image_classification/resnet50_vd_ssld.py
+46
-0
tutorials/train/image_classification/shufflenetv2.py
tutorials/train/image_classification/shufflenetv2.py
+46
-0
tutorials/train/instance_segmentation/mask_rcnn_hrnet_fpn.py
tutorials/train/instance_segmentation/mask_rcnn_hrnet_fpn.py
+54
-0
tutorials/train/instance_segmentation/mask_rcnn_r50_fpn.py
tutorials/train/instance_segmentation/mask_rcnn_r50_fpn.py
+7
-7
tutorials/train/object_detection/faster_rcnn_hrnet_fpn.py
tutorials/train/object_detection/faster_rcnn_hrnet_fpn.py
+55
-0
tutorials/train/object_detection/faster_rcnn_r50_fpn.py
tutorials/train/object_detection/faster_rcnn_r50_fpn.py
+6
-10
tutorials/train/object_detection/yolov3_darknet53.py
tutorials/train/object_detection/yolov3_darknet53.py
+4
-5
tutorials/train/object_detection/yolov3_mobilenetv1.py
tutorials/train/object_detection/yolov3_mobilenetv1.py
+55
-0
tutorials/train/object_detection/yolov3_mobilenetv3.py
tutorials/train/object_detection/yolov3_mobilenetv3.py
+55
-0
tutorials/train/semantic_segmentation/deeplabv3p_mobilenetv2.py
...als/train/semantic_segmentation/deeplabv3p_mobilenetv2.py
+7
-7
tutorials/train/semantic_segmentation/fast_scnn.py
tutorials/train/semantic_segmentation/fast_scnn.py
+9
-3
tutorials/train/semantic_segmentation/hrnet.py
tutorials/train/semantic_segmentation/hrnet.py
+2
-2
tutorials/train/semantic_segmentation/unet.py
tutorials/train/semantic_segmentation/unet.py
+3
-6
未找到文件。
docs/apis/datasets.md
浏览文件 @
7b49b396
...
...
@@ -5,7 +5,7 @@
```
paddlex.datasets.ImageNet(data_dir, file_list, label_list, transforms=None, num_workers=‘auto’, buffer_size=100, parallel_method='thread', shuffle=False)
```
读取ImageNet格式的分类数据集,并对样本进行相应的处理。ImageNet数据集格式的介绍可查看文档:
[
数据集格式说明
](
../data
sets.md
)
读取ImageNet格式的分类数据集,并对样本进行相应的处理。ImageNet数据集格式的介绍可查看文档:
[
数据集格式说明
](
../data
/format/index.html
)
示例:
[
代码文件
](
https://github.com/PaddlePaddle/PaddleX/blob/develop/tutorials/train/classification/mobilenetv2.py#L25
)
...
...
@@ -26,7 +26,7 @@ paddlex.datasets.ImageNet(data_dir, file_list, label_list, transforms=None, num_
paddlex.datasets.PascalVOC(data_dir, file_list, label_list, transforms=None, num_workers=‘auto’, buffer_size=100, parallel_method='thread', shuffle=False)
```
> 读取PascalVOC格式的检测数据集,并对样本进行相应的处理。PascalVOC数据集格式的介绍可查看文档:[数据集格式说明](../data
sets.md
)
> 读取PascalVOC格式的检测数据集,并对样本进行相应的处理。PascalVOC数据集格式的介绍可查看文档:[数据集格式说明](../data
/format/index.html
)
> 示例:[代码文件](https://github.com/PaddlePaddle/PaddleX/blob/develop/tutorials/train/detection/yolov3_darknet53.py#L29)
...
...
@@ -47,7 +47,7 @@ paddlex.datasets.PascalVOC(data_dir, file_list, label_list, transforms=None, num
paddlex.datasets.MSCOCO(data_dir, ann_file, transforms=None, num_workers='auto', buffer_size=100, parallel_method='thread', shuffle=False)
```
> 读取MSCOCO格式的检测数据集,并对样本进行相应的处理,该格式的数据集同样可以应用到实例分割模型的训练中。MSCOCO数据集格式的介绍可查看文档:[数据集格式说明](../data
sets.md
)
> 读取MSCOCO格式的检测数据集,并对样本进行相应的处理,该格式的数据集同样可以应用到实例分割模型的训练中。MSCOCO数据集格式的介绍可查看文档:[数据集格式说明](../data
/format/index.html
)
> 示例:[代码文件](https://github.com/PaddlePaddle/PaddleX/blob/develop/tutorials/train/detection/mask_rcnn_r50_fpn.py#L27)
...
...
@@ -67,7 +67,7 @@ paddlex.datasets.MSCOCO(data_dir, ann_file, transforms=None, num_workers='auto',
paddlex.datasets.SegDataset(data_dir, file_list, label_list, transforms=None, num_workers='auto', buffer_size=100, parallel_method='thread', shuffle=False)
```
> 读取语义分割任务数据集,并对样本进行相应的处理。语义分割任务数据集格式的介绍可查看文档:[数据集格式说明](../data
sets.md
)
> 读取语义分割任务数据集,并对样本进行相应的处理。语义分割任务数据集格式的介绍可查看文档:[数据集格式说明](../data
/format/index.html
)
> 示例:[代码文件](https://github.com/PaddlePaddle/PaddleX/blob/develop/tutorials/train/segmentation/unet.py#L27)
...
...
@@ -88,7 +88,7 @@ paddlex.datasets.SegDataset(data_dir, file_list, label_list, transforms=None, nu
paddlex.datasets.EasyDataCls(data_dir, file_list, label_list, transforms=None, num_workers='auto', buffer_size=100, parallel_method='thread', shuffle=False)
```
> 读取EasyData平台标注图像分类数据集,并对样本进行相应的处理。
EasyData图像分类任务数据集格式的介绍可查看文档:[数据集格式说明](../datasets.md)。
> 读取EasyData平台标注图像分类数据集,并对样本进行相应的处理。
> **参数**
...
...
@@ -107,7 +107,7 @@ paddlex.datasets.EasyDataCls(data_dir, file_list, label_list, transforms=None, n
paddlex.datasets.EasyDataDet(data_dir, file_list, label_list, transforms=None, num_workers=‘auto’, buffer_size=100, parallel_method='thread', shuffle=False)
```
> 读取EasyData目标检测
格式数据集,并对样本进行相应的处理,该格式的数据集同样可以应用到实例分割模型的训练中。EasyData目标检测或实例分割任务数据集格式的介绍可查看文档:[数据集格式说明](../datasets.md)
> 读取EasyData目标检测
/实例分割格式数据集,并对样本进行相应的处理,该格式的数据集同样可以应用到实例分割模型的训练中。
> **参数**
...
...
@@ -127,7 +127,7 @@ paddlex.datasets.EasyDataDet(data_dir, file_list, label_list, transforms=None, n
paddlex.datasets.EasyDataSeg(data_dir, file_list, label_list, transforms=None, num_workers='auto', buffer_size=100, parallel_method='thread', shuffle=False)
```
> 读取EasyData语义分割任务数据集,并对样本进行相应的处理。
EasyData语义分割任务数据集格式的介绍可查看文档:[数据集格式说明](../datasets.md)
> 读取EasyData语义分割任务数据集,并对样本进行相应的处理。
> **参数**
...
...
docs/apis/models/classification.md
浏览文件 @
7b49b396
...
...
@@ -69,7 +69,7 @@ predict(self, img_file, transforms=None, topk=5)
> **参数**
>
> > - **img_file** (str
): 预测图像路径
。
> > - **img_file** (str
|np.ndarray): 预测图像路径或numpy数组(HWC排列,BGR格式)
。
> > - **transforms** (paddlex.cls.transforms): 数据预处理操作。
> > - **topk** (int): 预测时前k个最大值。
...
...
docs/apis/models/detection.md
浏览文件 @
7b49b396
...
...
@@ -87,7 +87,7 @@ predict(self, img_file, transforms=None)
> **参数**
>
> > - **img_file** (str
): 预测图像路径
。
> > - **img_file** (str
|np.ndarray): 预测图像路径或numpy数组(HWC排列,BGR格式)
。
> > - **transforms** (paddlex.det.transforms): 数据预处理操作。
>
> **返回值**
...
...
@@ -172,7 +172,7 @@ predict(self, img_file, transforms=None)
> **参数**
>
> > - **img_file** (str
): 预测图像路径
。
> > - **img_file** (str
|np.ndarray): 预测图像路径或numpy数组(HWC排列,BGR格式)
。
> > - **transforms** (paddlex.det.transforms): 数据预处理操作。
>
> **返回值**
...
...
docs/apis/models/instance_segmentation.md
浏览文件 @
7b49b396
...
...
@@ -77,7 +77,7 @@ predict(self, img_file, transforms=None)
> **参数**
>
> > - **img_file** (str
): 预测图像路径
。
> > - **img_file** (str
|np.ndarray): 预测图像路径或numpy数组(HWC排列,BGR格式)
。
> > - **transforms** (paddlex.det.transforms): 数据预处理操作。
>
> **返回值**
...
...
docs/apis/models/semantic_segmentation.md
浏览文件 @
7b49b396
...
...
@@ -83,7 +83,7 @@ predict(self, im_file, transforms=None):
> **参数**
> >
> > - **img_file** (str
): 预测图像路径
。
> > - **img_file** (str
|np.ndarray): 预测图像路径或numpy数组(HWC排列,BGR格式)
。
> > - **transforms** (paddlex.seg.transforms): 数据预处理操作。
> **返回值**
...
...
docs/apis/transforms/augment.md
浏览文件 @
7b49b396
# 数据增强与imgaug支持
说明
# 数据增强与imgaug支持
数据增强操作可用于在模型训练时,增加训练样本的多样性,从而提升模型的泛化能力。
...
...
@@ -19,11 +19,11 @@ PaddleX目前已适配imgaug图像增强库,用户可以直接在PaddleX构造
import paddlex as pdx
from paddlex.cls import transforms
import imgaug.augmenters as iaa
train_transforms = transforms.ComposedClsTransforms(mode='train', crop_size=[224, 224])
train_transforms.add_augmenters([
train_transforms = transforms.Compose([
# 随机在[0.0 3.0]中选值对图像进行模糊
iaa.blur.GaussianBlur(sigma=(0.0, 3.0)),
transforms.RandomCrop(crop_size=224)
transforms.RandomCrop(crop_size=224),
transforms.Normalize()
])
```
除了上述用法,
`Compose`
接口中也支持imgaug的
`Someof`
、
`Sometimes`
、
`Sequential`
、
`Oneof`
等操作,开发者可以通过这些方法随意组合出增强流程。由于imgaug对于标注信息(目标检测框和实例分割mask)与PaddleX模型训练逻辑有部分差异,
**目前在检测和分割中,只支持pixel-level的增强方法,(即在增强时,不对图像的大小和方向做改变) 其它方法仍在适配中**
,详情可见下表,
...
...
@@ -58,9 +58,9 @@ from paddlex.cls import transforms
img_augmenters = iaa.Sometimes(0.6, [
iaa.blur.GaussianBlur(sigma=(0.0, 3.0))
])
train_transforms = transforms.ComposedClsTransforms(mode='train', crop_size=[224, 224])
train_transforms.add_augmenters([
train_transforms = transforms.Compose([
img_augmenters,
transforms.RandomCrop(crop_size=224)
transforms.RandomCrop(crop_size=224),
transforms.Normalize()
])
```
docs/apis/transforms/cls_transforms.md
浏览文件 @
7b49b396
...
...
@@ -12,68 +12,6 @@ paddlex.cls.transforms.Compose(transforms)
> **参数**
> * **transforms** (list): 数据预处理/数据增强列表。
## ComposedClsTransforms
```
python
paddlex
.
cls
.
transforms
.
ComposedClsTransforms
(
mode
,
crop_size
=
[
224
,
224
],
mean
=
[
0.485
,
0.456
,
0.406
],
std
=
[
0.229
,
0.224
,
0.225
])
```
分类模型中已经组合好的数据处理流程,开发者可以直接使用ComposedClsTransforms,简化手动组合transforms的过程, 该类中已经包含了
[
RandomCrop
](
#RandomCrop
)
和
[
RandomHorizontalFlip
](
#RandomHorizontalFlip
)
两种数据增强方式,你仍可以通过
[
add_augmenters函数接口
](
#add_augmenters
)
添加新的数据增强方式。
ComposedClsTransforms共包括以下几个步骤:
> 训练阶段:
> > 1. 随机从图像中crop一块子图,并resize成crop_size大小
> > 2. 将1的输出按0.5的概率随机进行水平翻转
> > 3. 将图像进行归一化
> 验证/预测阶段:
> > 1. 将图像按比例Resize,使得最小边长度为crop_size[0] * 1.14
> > 2. 从图像中心crop出一个大小为crop_size的图像
> > 3. 将图像进行归一化
### 参数
*
**mode**
(str): Transforms所处的阶段,包括
`train', 'eval'或'test'
* **crop_size** (int|list): 输入到模型里的图像大小,默认为[224, 224](与原图大小无关,根据上述几个步骤,会将原图处理成该图大小输入给模型训练)
* **mean** (list): 图像均值, 默认为[0.485, 0.456, 0.406]。
* **std** (list): 图像方差,默认为[0.229, 0.224, 0.225]。
### 添加数据增强方式
```python
ComposedClsTransforms.add_augmenters(augmenters)
```
> **参数**
> * **augmenters**(list): 数据增强方式列表
#### 使用示例
```
import paddlex as pdx
from paddlex.cls import transforms
train_transforms = transforms.ComposedClsTransforms(mode='train', crop_size=[320, 320])
eval_transforms = transforms.ComposedClsTransforms(mode='eval', crop_size=[320, 320])
# 添加数据增强
import imgaug.augmenters as iaa
train_transforms.add_augmenters([
transforms.RandomDistort(),
iaa.blur.GaussianBlur(sigma=(0.0, 3.0))
])
```
上面代码等价于
```
import paddlex as pdx
from paddlex.cls import transforms
train_transforms = transforms.Composed([
transforms.RandomDistort(),
iaa.blur.GaussianBlur(sigma=(0.0, 3.0)),
# 上面两个为通过add_augmenters额外添加的数据增强方式
transforms.RandomCrop(crop_size=320),
transforms.RandomHorizontalFlip(prob=0.5),
transforms.Normalize()
])
eval_transforms = transforms.Composed([
transforms.ResizeByShort(short_size=int(320*1.14)),
transforms.CenterCrop(crop_size=320),
transforms.Normalize()
])
```
## Normalize
```
python
paddlex
.
cls
.
transforms
.
Normalize
(
mean
=
[
0.485
,
0.456
,
0.406
],
std
=
[
0.229
,
0.224
,
0.225
])
...
...
@@ -183,3 +121,65 @@ paddlex.cls.transforms.RandomDistort(brightness_range=0.9, brightness_prob=0.5,
*
**saturation_prob**
(float): 随机调整饱和度的概率。默认为0.5。
*
**hue_range**
(int): 色调因子的范围。默认为18。
*
**hue_prob**
(float): 随机调整色调的概率。默认为0.5。
## ComposedClsTransforms
```
python
paddlex
.
cls
.
transforms
.
ComposedClsTransforms
(
mode
,
crop_size
=
[
224
,
224
],
mean
=
[
0.485
,
0.456
,
0.406
],
std
=
[
0.229
,
0.224
,
0.225
],
random_horizontal_flip
=
True
)
```
分类模型中已经组合好的数据处理流程,开发者可以直接使用ComposedClsTransforms,简化手动组合transforms的过程, 该类中已经包含了
[
RandomCrop
](
#RandomCrop
)
和
[
RandomHorizontalFlip
](
#RandomHorizontalFlip
)
两种数据增强方式,你仍可以通过
[
add_augmenters函数接口
](
#add_augmenters
)
添加新的数据增强方式。
ComposedClsTransforms共包括以下几个步骤:
> 训练阶段:
> > 1. 随机从图像中crop一块子图,并resize成crop_size大小
> > 2. 将1的输出按0.5的概率随机进行水平翻转, 若random_horizontal_flip为False,则跳过此步骤
> > 3. 将图像进行归一化
> 验证/预测阶段:
> > 1. 将图像按比例Resize,使得最小边长度为crop_size[0] * 1.14
> > 2. 从图像中心crop出一个大小为crop_size的图像
> > 3. 将图像进行归一化
### 参数
*
**mode**
(str): Transforms所处的阶段,包括
`train', 'eval'或'test'
* **crop_size** (int|list): 输入到模型里的图像大小,默认为[224, 224](与原图大小无关,根据上述几个步骤,会将原图处理成该图大小输入给模型训练)
* **mean** (list): 图像均值, 默认为[0.485, 0.456, 0.406]。
* **std** (list): 图像方差,默认为[0.229, 0.224, 0.225]。
* **random_horizontal_flip**(bool): 数据增强,是否以0,5的概率使用随机水平翻转增强,仅在model为'train'时生效,默认为True。底层实现采用[paddlex.cls.transforms.RandomHorizontalFlip](#randomhorizontalflip)
### 添加数据增强方式
```python
ComposedClsTransforms.add_augmenters(augmenters)
```
> **参数**
> * **augmenters**(list): 数据增强方式列表
#### 使用示例
```
import paddlex as pdx
from paddlex.cls import transforms
train_transforms = transforms.ComposedClsTransforms(mode='train', crop_size=[320, 320])
eval_transforms = transforms.ComposedClsTransforms(mode='eval', crop_size=[320, 320])
# 添加数据增强
import imgaug.augmenters as iaa
train_transforms.add_augmenters([
transforms.RandomDistort(),
iaa.blur.GaussianBlur(sigma=(0.0, 3.0))
])
```
上面代码等价于
```
import paddlex as pdx
from paddlex.cls import transforms
train_transforms = transforms.Composed([
transforms.RandomDistort(),
iaa.blur.GaussianBlur(sigma=(0.0, 3.0)),
# 上面两个为通过add_augmenters额外添加的数据增强方式
transforms.RandomCrop(crop_size=320),
transforms.RandomHorizontalFlip(prob=0.5),
transforms.Normalize()
])
eval_transforms = transforms.Composed([
transforms.ResizeByShort(short_size=int(320*1.14)),
transforms.CenterCrop(crop_size=320),
transforms.Normalize()
])
``
`
docs/apis/transforms/det_transforms.md
浏览文件 @
7b49b396
...
...
@@ -12,136 +12,6 @@ paddlex.det.transforms.Compose(transforms)
### 参数
*
**transforms**
(list): 数据预处理/数据增强列表。
## ComposedRCNNTransforms
```
python
paddlex
.
det
.
transforms
.
ComposedRCNNTransforms
(
mode
,
min_max_size
=
[
224
,
224
],
mean
=
[
0.485
,
0.456
,
0.406
],
std
=
[
0.229
,
0.224
,
0.225
])
```
目标检测FasterRCNN和实例分割MaskRCNN模型中已经组合好的数据处理流程,开发者可以直接使用ComposedRCNNTransforms,简化手动组合transforms的过程, 该类中已经包含了
[
RandomHorizontalFlip
](
#RandomHorizontalFlip
)
数据增强方式,你仍可以通过
[
add_augmenters函数接口
](
#add_augmenters
)
添加新的数据增强方式。
ComposedRCNNTransforms共包括以下几个步骤:
> 训练阶段:
> > 1. 随机以0.5的概率将图像水平翻转
> > 2. 将图像进行归一化
> > 3. 图像采用[ResizeByShort](#ResizeByShort)方式,根据min_max_size参数,进行缩入
> > 4. 使用[Padding](#Padding)将图像的长和宽分别Padding成32的倍数
> 验证/预测阶段:
> > 1. 将图像进行归一化
> > 2. 图像采用[ResizeByShort](#ResizeByShort)方式,根据min_max_size参数,进行缩入
> > 3. 使用[Padding](#Padding)将图像的长和宽分别Padding成32的倍数
### 参数
*
**mode**
(str): Transforms所处的阶段,包括
`train', 'eval'或'test'
* **min_max_size** (list): 输入模型中图像的最短边长度和最长边长度,参考[ResizeByShort](#ResizeByShort)(与原图大小无关,根据上述几个步骤,会将原图处理成相应大小输入给模型训练),默认[800, 1333]
* **mean** (list): 图像均值, 默认为[0.485, 0.456, 0.406]。
* **std** (list): 图像方差,默认为[0.229, 0.224, 0.225]。
### 添加数据增强方式
```python
ComposedRCNNTransforms.add_augmenters(augmenters)
```
> **参数**
> * **augmenters**(list): 数据增强方式列表
#### 使用示例
```
import paddlex as pdx
from paddlex.det import transforms
train_transforms = transforms.ComposedRCNNTransforms(mode='train', min_max_size=[800, 1333])
eval_transforms = transforms.ComposedRCNNTransforms(mode='eval', min_max_size=[800, 1333])
# 添加数据增强
import imgaug.augmenters as iaa
train_transforms.add_augmenters([
transforms.RandomDistort(),
iaa.blur.GaussianBlur(sigma=(0.0, 3.0))
])
```
上面代码等价于
```
import paddlex as pdx
from paddlex.det import transforms
train_transforms = transforms.Composed([
transforms.RandomDistort(),
iaa.blur.GaussianBlur(sigma=(0.0, 3.0)),
# 上面两个为通过add_augmenters额外添加的数据增强方式
transforms.RandomHorizontalFlip(prob=0.5),
transforms.Normalize(),
transforms.ResizeByShort(short_size=800, max_size=1333),
transforms.Padding(coarsest_stride=32)
])
eval_transforms = transforms.Composed([
transforms.Normalize(),
transforms.ResizeByShort(short_size=800, max_size=1333),
transforms.Padding(coarsest_stride=32)
])
```
## ComposedYOLOv3Transforms
```python
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模型中已经组合好的数据处理流程,开发者可以直接使用ComposedYOLOv3Transforms,简化手动组合transforms的过程, 该类中已经包含了[MixupImage](#MixupImage)、[RandomDistort](#RandomDistort)、[RandomExpand](#RandomExpand)、[RandomCrop](#RandomCrop)、[RandomHorizontalFlip](#RandomHorizontalFlip)5种数据增强方式,你仍可以通过[add_augmenters函数接口](#add_augmenters)添加新的数据增强方式。
ComposedYOLOv3Transforms共包括以下几个步骤:
> 训练阶段:
> > 1. 在前mixup_epoch轮迭代中,使用MixupImage策略
> > 2. 对图像进行随机扰动,包括亮度,对比度,饱和度和色调
> > 3. 随机扩充图像
> > 4. 随机裁剪图像
> > 5. 将4步骤的输出图像Resize成shape参数的大小
> > 6. 随机0.5的概率水平翻转图像
> > 7. 图像归一化
> 验证/预测阶段:
> > 1. 将图像Resize成shape参数大小
> > 2. 图像归一化
### 参数
* **mode** (str): Transforms所处的阶段,包括`
train', 'eval'或'test'
*
**shape**
(list): 输入模型中图像的大小(与原图大小无关,根据上述几个步骤,会将原图处理成相应大小输入给模型训练), 默认[608, 608]
*
**mixup_epoch**
(int): 模型训练过程中,在前mixup_epoch轮迭代中,使用mixup策略,如果为-1,则不使用mixup策略, 默认250。
*
**mean**
(list): 图像均值, 默认为[0.485, 0.456, 0.406]。
*
**std**
(list): 图像方差,默认为[0.229, 0.224, 0.225]。
### 添加数据增强方式
```
python
ComposedYOLOv3Transforms
.
add_augmenters
(
augmenters
)
```
> **参数**
> * **augmenters**(list): 数据增强方式列表
#### 使用示例
```
import paddlex as pdx
from paddlex.det import transforms
train_transforms = transforms.ComposedYOLOv3Transforms(mode='train', shape=[480, 480])
eval_transforms = transforms.ComposedYOLOv3Transforms(mode='eval', shape=[480, 480])
# 添加数据增强
import imgaug.augmenters as iaa
train_transforms.add_augmenters([
iaa.blur.GaussianBlur(sigma=(0.0, 3.0))
])
```
上面代码等价于
```
import paddlex as pdx
from paddlex.det import transforms
train_transforms = transforms.Composed([
iaa.blur.GaussianBlur(sigma=(0.0, 3.0)),
# 上面为通过add_augmenters额外添加的数据增强方式
transforms.MixupImage(mixup_epoch=250),
transforms.RandomDistort(),
transforms.RandomExpand(),
transforms.RandomCrop(),
transforms.Resize(target_size=480, interp='RANDOM'),
transforms.RandomHorizontalFlip(prob=0.5),
transforms.Normalize()
])
eval_transforms = transforms.Composed([
transforms.Resize(target_size=480, interp='CUBIC'),
transforms.Normalize()
])
```
## Normalize
```
python
paddlex
.
det
.
transforms
.
Normalize
(
mean
=
[
0.485
,
0.456
,
0.406
],
std
=
[
0.229
,
0.224
,
0.225
])
...
...
@@ -297,3 +167,138 @@ paddlex.det.transforms.RandomCrop(aspect_ratio=[.5, 2.], thresholds=[.0, .1, .3,
*
**num_attempts**
(int): 在放弃寻找有效裁剪区域前尝试的次数。默认值为50。
*
**allow_no_crop**
(bool): 是否允许未进行裁剪。默认值为True。
*
**cover_all_box**
(bool): 是否要求所有的真实标注框都必须在裁剪区域内。默认值为False。
## ComposedRCNNTransforms
```
python
paddlex
.
det
.
transforms
.
ComposedRCNNTransforms
(
mode
,
min_max_size
=
[
224
,
224
],
mean
=
[
0.485
,
0.456
,
0.406
],
std
=
[
0.229
,
0.224
,
0.225
],
random_horizontal_flip
=
True
)
```
目标检测FasterRCNN和实例分割MaskRCNN模型中已经组合好的数据处理流程,开发者可以直接使用ComposedRCNNTransforms,简化手动组合transforms的过程, 该类中已经包含了
[
RandomHorizontalFlip
](
#RandomHorizontalFlip
)
数据增强方式,你仍可以通过
[
add_augmenters函数接口
](
#add_augmenters
)
添加新的数据增强方式。
ComposedRCNNTransforms共包括以下几个步骤:
> 训练阶段:
> > 1. 随机以0.5的概率将图像水平翻转, 若random_horizontal_flip为False,则跳过此步骤
> > 2. 将图像进行归一化
> > 3. 图像采用[ResizeByShort](#ResizeByShort)方式,根据min_max_size参数,进行缩入
> > 4. 使用[Padding](#Padding)将图像的长和宽分别Padding成32的倍数
> 验证/预测阶段:
> > 1. 将图像进行归一化
> > 2. 图像采用[ResizeByShort](#ResizeByShort)方式,根据min_max_size参数,进行缩入
> > 3. 使用[Padding](#Padding)将图像的长和宽分别Padding成32的倍数
### 参数
*
**mode**
(str): Transforms所处的阶段,包括
`train', 'eval'或'test'
* **min_max_size** (list): 输入模型中图像的最短边长度和最长边长度,参考[ResizeByShort](#ResizeByShort)(与原图大小无关,根据上述几个步骤,会将原图处理成相应大小输入给模型训练),默认[800, 1333]
* **mean** (list): 图像均值, 默认为[0.485, 0.456, 0.406]。
* **std** (list): 图像方差,默认为[0.229, 0.224, 0.225]。
* **random_horizontal_flip**(bool): 数据增强,是否以0.5的概率使用随机水平翻转增强,仅在mode为'train'时生效,默认为True。底层实现采用[paddlex.det.transforms.RandomHorizontalFlip](#randomhorizontalflip)
### 添加数据增强方式
```python
ComposedRCNNTransforms.add_augmenters(augmenters)
```
> **参数**
> * **augmenters**(list): 数据增强方式列表
#### 使用示例
```
import paddlex as pdx
from paddlex.det import transforms
train_transforms = transforms.ComposedRCNNTransforms(mode='train', min_max_size=[800, 1333])
eval_transforms = transforms.ComposedRCNNTransforms(mode='eval', min_max_size=[800, 1333])
# 添加数据增强
import imgaug.augmenters as iaa
train_transforms.add_augmenters([
transforms.RandomDistort(),
iaa.blur.GaussianBlur(sigma=(0.0, 3.0))
])
```
上面代码等价于
```
import paddlex as pdx
from paddlex.det import transforms
train_transforms = transforms.Composed([
transforms.RandomDistort(),
iaa.blur.GaussianBlur(sigma=(0.0, 3.0)),
# 上面两个为通过add_augmenters额外添加的数据增强方式
transforms.RandomHorizontalFlip(prob=0.5),
transforms.Normalize(),
transforms.ResizeByShort(short_size=800, max_size=1333),
transforms.Padding(coarsest_stride=32)
])
eval_transforms = transforms.Composed([
transforms.Normalize(),
transforms.ResizeByShort(short_size=800, max_size=1333),
transforms.Padding(coarsest_stride=32)
])
```
## ComposedYOLOv3Transforms
```python
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], random_distort=True, random_expand=True, random_crop=True, random_horizontal_flip=True)
```
目标检测YOLOv3模型中已经组合好的数据处理流程,开发者可以直接使用ComposedYOLOv3Transforms,简化手动组合transforms的过程, 该类中已经包含了[MixupImage](#MixupImage)、[RandomDistort](#RandomDistort)、[RandomExpand](#RandomExpand)、[RandomCrop](#RandomCrop)、[RandomHorizontalFlip](#RandomHorizontalFlip)5种数据增强方式,你仍可以通过[add_augmenters函数接口](#add_augmenters)添加新的数据增强方式。
ComposedYOLOv3Transforms共包括以下几个步骤:
> 训练阶段:
> > 1. 在前mixup_epoch轮迭代中,使用MixupImage策略,若mixup_epoch为-1,则跳过此步骤
> > 2. 对图像进行随机扰动,包括亮度,对比度,饱和度和色调,若random_distort为False,则跳过此步骤
> > 3. 随机扩充图像,若random_expand为False, 则跳过此步骤
> > 4. 随机裁剪图像,若random_crop为False, 则跳过此步骤
> > 5. 将4步骤的输出图像Resize成shape参数的大小
> > 6. 随机0.5的概率水平翻转图像,若random_horizontal_flip为False,则跳过此步骤
> > 7. 图像归一化
> 验证/预测阶段:
> > 1. 将图像Resize成shape参数大小
> > 2. 图像归一化
### 参数
* **mode** (str): Transforms所处的阶段,包括`
train', 'eval'或'test'
*
**shape**
(list): 输入模型中图像的大小(与原图大小无关,根据上述几个步骤,会将原图处理成相应大小输入给模型训练), 默认[608, 608]
*
**mixup_epoch**
(int): 模型训练过程中,在前mixup_epoch轮迭代中,使用mixup策略,如果为-1,则不使用mixup策略, 默认250。底层实现采用
[
paddlex.det.transforms.MixupImage
](
#mixupimage
)
*
**mean**
(list): 图像均值, 默认为[0.485, 0.456, 0.406]。
*
**std**
(list): 图像方差,默认为[0.229, 0.224, 0.225]。
*
**random_distort**
(bool): 数据增强,是否在训练过程中随机扰动图像,仅在mode为'train'时生效,默认为True。底层实现采用
[
paddlex.det.transforms.RandomDistort
](
#randomdistort
)
*
**random_expand**
(bool): 数据增强,是否在训练过程随机扩张图像,仅在mode为'train'时生效,默认为True。底层实现采用
[
paddlex.det.transforms.RandomExpand
](
#randomexpand
)
*
**random_crop**
(bool): 数据增强,是否在训练过程中随机裁剪图像,仅在mode为'train'时生效,默认为True。底层实现采用
[
paddlex.det.transforms.RandomCrop
](
#randomcrop
)
*
**random_horizontal_flip**
(bool): 数据增强,是否在训练过程中随机水平翻转图像,仅在mode为'train'时生效,默认为True。底层实现采用
[
paddlex.det.transforms.RandomHorizontalFlip
](
#randomhorizontalflip
)
### 添加数据增强方式
```
python
ComposedYOLOv3Transforms
.
add_augmenters
(
augmenters
)
```
> **参数**
> * **augmenters**(list): 数据增强方式列表
#### 使用示例
```
import paddlex as pdx
from paddlex.det import transforms
train_transforms = transforms.ComposedYOLOv3Transforms(mode='train', shape=[480, 480])
eval_transforms = transforms.ComposedYOLOv3Transforms(mode='eval', shape=[480, 480])
# 添加数据增强
import imgaug.augmenters as iaa
train_transforms.add_augmenters([
iaa.blur.GaussianBlur(sigma=(0.0, 3.0))
])
```
上面代码等价于
```
import paddlex as pdx
from paddlex.det import transforms
train_transforms = transforms.Composed([
iaa.blur.GaussianBlur(sigma=(0.0, 3.0)),
# 上面为通过add_augmenters额外添加的数据增强方式
transforms.MixupImage(mixup_epoch=250),
transforms.RandomDistort(),
transforms.RandomExpand(),
transforms.RandomCrop(),
transforms.Resize(target_size=480, interp='RANDOM'),
transforms.RandomHorizontalFlip(prob=0.5),
transforms.Normalize()
])
eval_transforms = transforms.Composed([
transforms.Resize(target_size=480, interp='CUBIC'),
transforms.Normalize()
])
```
docs/apis/transforms/seg_transforms.md
浏览文件 @
7b49b396
...
...
@@ -11,64 +11,6 @@ paddlex.seg.transforms.Compose(transforms)
### 参数
*
**transforms**
(list): 数据预处理/数据增强列表。
## ComposedSegTransforms
```
python
paddlex
.
det
.
transforms
.
ComposedSegTransforms
(
mode
,
train_crop_shape
=
[
769
,
769
],
mean
=
[
0.485
,
0.456
,
0.406
],
std
=
[
0.229
,
0.224
,
0.225
])
```
语义分割DeepLab和UNet模型中已经组合好的数据处理流程,开发者可以直接使用ComposedSegTransforms,简化手动组合transforms的过程, 该类中已经包含了
[
RandomHorizontalFlip
](
#RandomHorizontalFlip
)
、
[
ResizeStepScaling
](
#ResizeStepScaling
)
、
[
RandomPaddingCrop
](
#RandomPaddingCrop
)
3种数据增强方式,你仍可以通过
[
add_augmenters函数接口
](
#add_augmenters
)
添加新的数据增强方式。
ComposedSegTransforms共包括以下几个步骤:
> 训练阶段:
> > 1. 随机对图像以0.5的概率水平翻转
> > 2. 按不同的比例随机Resize原图
> > 3. 从原图中随机crop出大小为train_crop_size大小的子图,如若crop出来的图小于train_crop_size,则会将图padding到对应大小
> > 4. 图像归一化
> 预测阶段:
> > 1. 图像归一化
### 参数
*
**mode**
(str): Transforms所处的阶段,包括
`train', 'eval'或'test'
* **train_crop_size** (list): 训练过程中随机Crop和Resize后(验证或预测过程中不需配置该参数,自动使用原图大小),输入到模型中图像的大小(与原图大小无关,根据上述几个步骤,会将原图处理成相应大小输入给模型训练), 默认[769, 769]
* **mean** (list): 图像均值, 默认为[0.485, 0.456, 0.406]。
* **std** (list): 图像方差,默认为[0.229, 0.224, 0.225]。
### 添加数据增强方式
```python
ComposedSegTransforms.add_augmenters(augmenters)
```
> **参数**
> * **augmenters**(list): 数据增强方式列表
#### 使用示例
```
import paddlex as pdx
from paddlex.seg import transforms
train_transforms = transforms.ComposedSegTransforms(mode='train', train_crop_size=[512, 512])
eval_transforms = transforms.ComposedSegTransforms(mode='eval')
# 添加数据增强
import imgaug.augmenters as iaa
train_transforms.add_augmenters([
transforms.RandomDistort(),
iaa.blur.GaussianBlur(sigma=(0.0, 3.0))
])
```
上面代码等价于
```
import paddlex as pdx
from paddlex.det import transforms
train_transforms = transforms.Composed([
transforms.RandomDistort(),
iaa.blur.GaussianBlur(sigma=(0.0, 3.0)),
# 上面2行为通过add_augmenters额外添加的数据增强方式
transforms.RandomHorizontalFlip(prob=0.5),
transforms.ResizeStepScaling(),
transforms.PaddingCrop(crop_size=[512, 512]),
transforms.Normalize()
])
eval_transforms = transforms.Composed([
transforms.Normalize()
])
```
## RandomHorizontalFlip
```
python
...
...
@@ -224,3 +166,65 @@ paddlex.seg.transforms.RandomDistort(brightness_range=0.5, brightness_prob=0.5,
*
**saturation_prob**
(float): 随机调整饱和度的概率。默认为0.5。
*
**hue_range**
(int): 色调因子的范围。默认为18。
*
**hue_prob**
(float): 随机调整色调的概率。默认为0.5。
## ComposedSegTransforms
```
python
paddlex
.
det
.
transforms
.
ComposedSegTransforms
(
mode
,
min_max_size
=
[
400
,
600
],
train_crop_shape
=
[
769
,
769
],
mean
=
[
0.485
,
0.456
,
0.406
],
std
=
[
0.229
,
0.224
,
0.225
],
random_horizontal_flip
=
True
)
```
语义分割DeepLab和UNet模型中已经组合好的数据处理流程,开发者可以直接使用ComposedSegTransforms,简化手动组合transforms的过程, 该类中已经包含了
[
RandomHorizontalFlip
](
#RandomHorizontalFlip
)
、
[
ResizeStepScaling
](
#ResizeStepScaling
)
、
[
RandomPaddingCrop
](
#RandomPaddingCrop
)
3种数据增强方式,你仍可以通过
[
add_augmenters函数接口
](
#add_augmenters
)
添加新的数据增强方式。
ComposedSegTransforms共包括以下几个步骤:
> 训练阶段:
> > 1. 随机对图像以0.5的概率水平翻转,若random_horizontal_flip为False,则跳过此步骤
> > 2. 按不同的比例随机Resize原图, 处理方式参考[paddlex.seg.transforms.ResizeRangeScaling](#resizerangescaling)。若min_max_size为None,则跳过此步骤
> > 3. 从原图中随机crop出大小为train_crop_size大小的子图,如若crop出来的图小于train_crop_size,则会将图padding到对应大小
> > 4. 图像归一化
> 预测阶段:
> > 1. 将图像的最长边resize至(min_max_size[0] + min_max_size[1])//2, 短边按比例resize。若min_max_size为None,则跳过此步骤
> > 1. 图像归一化
### 参数
*
**mode**
(str): Transforms所处的阶段,包括
`train', 'eval'或'test'
* **min_max_size**(list): 用于对图像进行resize,具体作用参见上述步骤。
* **train_crop_size** (list): 训练过程中随机裁剪原图用于训练,具体作用参见上述步骤。此参数仅在mode为`
train
`时生效。
* **mean** (list): 图像均值, 默认为[0.485, 0.456, 0.406]。
* **std** (list): 图像方差,默认为[0.229, 0.224, 0.225]。
* **random_horizontal_flip**(bool): 数据增强,是否随机水平翻转图像,此参数仅在mode为`
train
`时生效。
### 添加数据增强方式
```python
ComposedSegTransforms.add_augmenters(augmenters)
```
> **参数**
> * **augmenters**(list): 数据增强方式列表
#### 使用示例
```
import paddlex as pdx
from paddlex.seg import transforms
train_transforms = transforms.ComposedSegTransforms(mode='train', train_crop_size=[512, 512])
eval_transforms = transforms.ComposedSegTransforms(mode='eval')
# 添加数据增强
import imgaug.augmenters as iaa
train_transforms.add_augmenters([
transforms.RandomDistort(),
iaa.blur.GaussianBlur(sigma=(0.0, 3.0))
])
```
上面代码等价于
```
import paddlex as pdx
from paddlex.det import transforms
train_transforms = transforms.Composed([
transforms.RandomDistort(),
iaa.blur.GaussianBlur(sigma=(0.0, 3.0)),
# 上面2行为通过add_augmenters额外添加的数据增强方式
transforms.RandomHorizontalFlip(prob=0.5),
transforms.ResizeStepScaling(),
transforms.PaddingCrop(crop_size=[512, 512]),
transforms.Normalize()
])
eval_transforms = transforms.Composed([
transforms.Normalize()
])
``
`
docs/apis/visualize.md
浏览文件 @
7b49b396
...
...
@@ -10,7 +10,7 @@ paddlex.det.visualize(image, result, threshold=0.5, save_dir='./')
将目标检测/实例分割模型预测得到的Box框和Mask在原图上进行可视化。
### 参数
> * **image** (str
): 原图文件路径
。
> * **image** (str
|np.ndarray): 原图文件路径或numpy数组(HWC排列,BGR格式)
。
> * **result** (str): 模型预测结果。
> * **threshold**(float): score阈值,将Box置信度低于该阈值的框过滤不进行可视化。默认0.5
> * **save_dir**(str): 可视化结果保存路径。若为None,则表示不保存,该函数将可视化的结果以np.ndarray的形式返回;若设为目录路径,则将可视化结果保存至该目录下。默认值为'./'。
...
...
@@ -32,7 +32,7 @@ paddlex.seg.visualize(image, result, weight=0.6, save_dir='./')
将语义分割模型预测得到的Mask在原图上进行可视化。
### 参数
> * **image** (str
): 原图文件路径
。
> * **image** (str
|np.ndarray): 原图文件路径或numpy数组(HWC排列,BGR格式)
。
> * **result** (str): 模型预测结果。
> * **weight**(float): mask可视化结果与原图权重因子,weight表示原图的权重。默认0.6。
> * **save_dir**(str): 可视化结果保存路径。若为None,则表示不保存,该函数将可视化的结果以np.ndarray的形式返回;若设为目录路径,则将可视化结果保存至该目录下。默认值为'./'。
...
...
docs/appendix/parameters.md
浏览文件 @
7b49b396
...
...
@@ -5,53 +5,69 @@ PaddleX所有训练接口中,内置的参数均为根据单GPU卡相应batch_s
## 1.Epoch数的调整
Epoch数是模型训练过程,迭代的轮数,用户可以设置较大的数值,根据模型迭代过程在验证集上的指标表现,来判断模型是否收敛,进而提前终止训练。此外也可以使用
`train`
接口中的
`early_stop`
策略,模型在训练过程会自动判断模型是否收敛自动中止。
## 2.Batch Size的调整
Batch Size指模型在训练过程中,一次性处理的样本数量, 如若使用多卡训练, batch_size会均分到各张卡上(因此需要让batch size整除卡数)。这个参数跟机器的显存/内存高度相关,
`batch_size`
越高,所消耗的显存/内存就越高。PaddleX在各个
`train`
接口中均配置了默认的batch size,如若用户调整batch size,则也注意需要对应调整其它参数,如下表所示展示YOLOv3在训练时的参数配置
## 2.batch_size和learning_rate
| 参数 | 默认值 | 调整比例 | 示例 |
|:---------------- | :------------ | :------------------ | :------------ |
| train_batch_size | 8 | 调整为 8
*
alpha | 16 |
| learning_rate | 1.0/8000 | 调整为 alpha/8000 | 2.0/8000 |
| warmup_steps | 1000 | 调整为 1000/alpha
<br>
(该参数也可以自行根据数据情况调整) | 500 |
| lr_decay_epochs | [213, 240] | 不变 | [213, 240] |
> - Batch Size指模型在训练过程中,一次性处理的样本数量
> - 如若使用多卡训练, batch_size会均分到各张卡上(因此需要让batch size整除卡数)
> - Batch Size跟机器的显存/内存高度相关,`batch_size`越高,所消耗的显存/内存就越高
> - PaddleX在各个`train`接口中均配置了默认的batch size(默认针对单GPU卡),如若训练时提示GPU显存不足,则相应调低BatchSize,如若GPU显存高或使用多张GPU卡时,可相应调高BatchSize。
> - **如若用户调整batch size,则也注意需要对应调整其它参数,特别是train接口中默认的learning_rate值**。如在YOLOv3模型中,默认`train_batch_size`为8,`learning_rate`为0.000125,当用户将模型在2卡机器上训练时,可以将`train_batch_size`调整为16, 那么同时`learning_rate`也可以对应调整为0.000125 * 2 = 0.00025
## 3.warmup_steps和warmup_start_lr
更多训练接口可以参考
-
[
分类模型-train
](
https://paddlex.readthedocs.io/zh_CN/latest/apis/models/classification.html#train
)
-
[
目标检测检测FasterRCNN-train
](
https://paddlex.readthedocs.io/zh_CN/latest/apis/models/detection.html#id2
)
-
[
目标检测YOLOv3-train
](
https://paddlex.readthedocs.io/zh_CN/latest/apis/models/detection.html#train
)
-
[
实例分割MaskRCNN-train
](
https://paddlex.readthedocs.io/zh_CN/latest/apis/models/instance_segmentation.html#train
)
-
[
语义分割DeepLabv3p-train
](
https://paddlex.readthedocs.io/zh_CN/latest/apis/models/semantic_segmentation.html#train
)
-
[
语义分割UNet
](
https://paddlex.readthedocs.io/zh_CN/latest/apis/models/semantic_segmentation.html#id2
)
在训练模型时,一般都会使用预训练模型,例如检测模型在训练时使用backbone在ImageNet数据集上的预训练权重。但由于在自行训练时,自己的数据与ImageNet数据集存在较大的差异,可能会一开始由于梯度过大使得训练出现问题,因此可以在刚开始训练时,让学习率以一个较小的值,慢慢增长到设定的学习率。因此
`warmup_steps`
和
`warmup_start_lr`
就是这个作用,模型开始训练时,学习率会从
`warmup_start_lr`
开始,在
`warmup_steps`
个batch数据迭代后线性增长到设定的学习率。
## 关于lr_decay_epoch, warmup_steps等参数的说明
> 例如YOLOv3的train接口,默认`train_batch_size`为8,`learning_rate`为0.000125, `warmup_steps`为1000, `warmup_start_lr`为0.0;在此参数配置下表示,模型在启动训练后,在前1000个step(每个step表示一个batch的数据,也就是8个样本)内,学习率会从0.0开始线性增长到设定的0.000125。
在PaddleX或其它深度学习模型的训练过程中,经常见到lr_decay_epoch, warmup_steps, warmup_start_lr等参数设置,下面介绍一些这些参数的作用。
## 4.lr_decay_epochs和lr_decay_gamma
首先这些参数都是用于控制模型训练过程中学习率的变化方式,例如我们在训练时将learning_rate设为0.1, 通常情况,在模型的训练过程中,学习率一直以0.1不变训练下去, 但为了调出更好的模型效果,我们往往不希望学习率一直保持不变
。
`lr_decay_epochs`
用于让学习率在模型训练后期逐步衰减,它一般是一个list,如[6, 8, 10],表示学习率在第6个epoch时衰减一次,第8个epoch时再衰减一次,第10个epoch时再衰减一次。每次学习率衰减为之前的学习率
*
lr_decay_gamma
。
### warmup_steps和warmup_start_lr
> 例如YOLOv3的train接口,默认`num_epochs`为270,`learning_rate`为0.000125, `lr_decay_epochs`为[213, 240],`lr_decay_gamma`为0.1;在此参数配置下表示,模型在启动训练后,在前213个epoch中,训练时使用的学习率为0.000125,在第213至240个epoch之间,训练使用的学习率为0.000125*0.1,在240个epoch之后,使用的学习率为0.000125*0.1*0.1
我们在训练模型时,一般都会使用预训练模型,例如检测模型在训练时使用backbone在ImageNet数据集上的预训练权重。但由于在自行训练时,自己的数据与ImageNet数据集存在较大的差异,可能会一开始由于梯度过大使得训练出现问题,因此可以在刚开始训练时,让学习率以一个较小的值,慢慢增长到设定的学习率。因此
`warmup_steps`
和
`warmup_start_lr`
就是这个作用,模型开始训练时,学习率会从
`warmup_start_lr`
开始,在
`warmup_steps`
内线性增长到设定的学习率。
## 5.参数设定时的约束
根据上述几个参数,可以了解到学习率的变化分为WarmUp热身阶段和Decay衰减阶段,
> - Wamup热身阶段:随着训练迭代,学习率从较低的值逐渐线性增长至设定的值,以step为单位
> - Decay衰减阶段:随着训练迭代,学习率逐步衰减,如每次衰减为之前的0.1, 以epoch为单位
> step与epoch的关系:1个epoch由多个step组成,例如训练样本有800张图像,`train_batch_size`为8, 那么每个epoch都要完整用这800张图片训一次模型,而每个epoch总共包含800//8即100个step
### lr_decay_epochs和lr_decay_gamma
在PaddleX中,约束warmup必须在Decay之前结束,因此各参数设置需要满足下面条件
```
warmup_steps <= lr_decay_epochs[0] * num_steps_each_epoch
```
其中
`num_steps_each_epoch`
计算方式如下,
```
num_steps_each_eposh = num_samples_in_train_dataset // train_batch_size
```
因此,如若你在启动训练时,被提示
`warmup_steps should be less than...`
时,即表示需要根据上述公式调整你的参数啦,可以调整
`lr_decay_epochs`
或者是
`warmup_steps`
。
`lr_decay_epochs`
用于让学习率在模型训练后期逐步衰减,它一般是一个list,如[6, 8, 10],表示学习率在第6个epoch时衰减一次,第8个epoch时再衰减一次,第10个epoch时再衰减一次。每次学习率衰减为之前的学习率
*
lr_decay_gamma
## 6.如何使用多GPU卡进行训练
在
`import paddlex`
前配置环境变量,代码如下
```
import os
os.environ['CUDA_VISIBLE_DEVICES'] = '0' # 使用第1张GPU卡进行训练
# 注意paddle或paddlex都需要在设置环境变量后再import
import paddlex as pdx
```
### Notice
```
import os
os.environ['CUDA_VISIBLE_DEVICES'] = '' # 不使用GPU,使用CPU进行训练
import paddlex as pdx
```
在PaddleX中,限制warmup需要在第一个学习率decay衰减前结束,因此要满足下面的公式
```
warmup_steps <= lr_decay_epochs[0] * num_steps_each_epoch
import os
os.environ['CUDA_VISIBLE_DEVICES'] = '0,1,3' # 使用第1、2、4张GPU卡进行训练
import paddlex as pdx
```
其中公式中
`num_steps_each_epoch = num_samples_in_train_dataset // train_batch_size`
。
> 因此如若在训练时PaddleX提示`warmup_steps should be less than xxx`时,即可根据上述公式来调整你的`lr_decay_epochs`或者是`warmup_steps`使得两个参数满足上面的条件
> - 图像分类模型 [train接口文档](https://paddlex.readthedocs.io/zh_CN/latest/apis/models/classification.html#train)
> - FasterRCNN [train接口文档](https://paddlex.readthedocs.io/zh_CN/latest/apis/models/detection.html#fasterrcnn)
> - YOLOv3 [train接口文档](https://paddlex.readthedocs.io/zh_CN/latest/apis/models/detection.html#yolov3
)
> - MaskRCNN [train接口文档](https://paddlex.readthedocs.io/zh_CN/latest/apis/models/instance_segmentation.html#maskrcnn
)
> - DeepLab [train接口文档](https://paddlex.readthedocs.io/zh_CN/latest/apis/models/semantic_segmentation.html#deeplabv3p
)
> - UNet [train接口文档](https://paddlex.readthedocs.io/zh_CN/latest/apis/models/semantic_segmentation.html#unet
)
> - HRNet [train接口文档](https://paddlex.readthedocs.io/zh_CN/latest/apis/models/semantic_segmentation.html#hrnet
)
## 相关模型接口
-
图像分类模型
[
train接口
](
../apis/models/classification.html#train
)
-
FasterRCNN
[
train接口
](
../apis/models/detection.html#id1
)
-
YOLOv3
[
train接口
](
../apis/models/detection.html#train
)
-
MaskRCNN
[
train接口
](
../apis/models/instance_segmentation.html#train
)
-
DeepLabv3p
[
train接口
](
../apis/models/semantic_segmentation.html#train
)
docs/change_log.md
浏览文件 @
7b49b396
# 更新日志
## 2020.05.20
### PaddleX v1.0.0发布
-
新增XXX
-
新增XXX
**v1.1.0**
2020.07.10
### PaddleX-GUI V1.0.0发布
-
新增XXX
-
新增XXX
-
模型更新
> - 新增语义分割模型HRNet、FastSCNN
> - 目标检测FasterRCNN、实例分割MaskRCNN新增backbone HRNet
> - 目标检测/实例分割模型新增COCO数据集预训练模型
> - 集成X2Paddle,PaddleX所有分类模型和语义分割模型支持导出为ONNX协议
-
模型部署更新
> - 模型加密增加支持Windows平台
> - 新增Jetson、PaddleLite模型部署预测方案
> - C++部署代码新增batch批预测,并采用OpenMP对预处理进行并行加速
-
新增2个PaddleX产业案例
> - [人像分割案例]()
> - [工业表计读数案例]()
-
新增数据格式转换功能,LabelMe、精灵标注助手和EasyData平台标注的数据转为PaddleX支持加载的数据格式
-
PaddleX文档更新,优化文档结构
**v1.0.0**
2020.05.20
-
增加模型C++部署和Python部署代码
-
增加模型加密部署方案
-
增加分类模型的OpenVINO部署方案
-
增加模型可解释性的接口
**v0.1.8**
2020.05.17
-
修复部分代码Bug
-
新增EasyData平台数据标注格式支持
-
支持imgaug数据增强库的pixel-level算子
docs/data/annotation.md
浏览文件 @
7b49b396
...
...
@@ -10,11 +10,13 @@ PaddleX支持图像分类、目标检测、实例分割和语义分割四大视
| 标注工具 | 图像分类 | 目标检测 | 实例分割 | 语义分割 | 安装 |
| :--------- | :------- | :------ | :------ | :------- | :----------------------------------------------- |
| Labelme | - | √ | √ | √ | pip install labelme (本地数据标注) |
| 精灵标注 | √ |
-
| √ | √ |
[
官网下载
](
http://www.jinglingbiaozhu.com/
)
(本地数据标注) |
| 精灵标注 | √ |
√
*
| √ | √ |
[
官网下载
](
http://www.jinglingbiaozhu.com/
)
(本地数据标注) |
| EasyData | √ | √ | √ | √ |
[
Web页面标注
](
https://ai.baidu.com/easydata/
)
(需上传数据进行标注) |
数据标注完成后,参照如下流程,将标注数据转为可用PaddleX模型训练的数据组织格式。
> *注*:精灵标注的目标检测数据可以在工具内部导出为PascalVOC格式,因此paddlex未提供精灵标注数据到PascalVOC格式的转换
## 标注数据格式转换
...
...
@@ -22,6 +24,9 @@ PaddleX支持图像分类、目标检测、实例分割和语义分割四大视
> 1. 将所有的原图文件放在同一个目录下,如`pics`目录
> 2. 将所有的标注json文件放在同一个目录下,如`annotations`目录
> 3. 使用如下命令进行转换
> *注*:精灵标注的目标检测数据可以在工具内部导出为PascalVOC格式,因此paddlex未提供精灵标注数据到PascalVOC格式的转换
```
paddlex --data_conversion --source labelme --to PascalVOC --pics ./pics --annotations ./annotations --save_dir ./converted_dataset_dir
```
...
...
@@ -29,4 +34,3 @@ paddlex --data_conversion --source labelme --to PascalVOC --pics ./pics --annota
> `--to`表示数据需要转换成为的格式,支持`ImageNet`(图像分类)、`PascalVOC`(目标检测),`MSCOCO`(实例分割,也可用于目标检测)和`SEG`(语义分割)
> `--pics`指定原图所在的目录路径
> `--annotations`指定标注文件所在的目录路径
> 【备注】由于标注精灵可以标注PascalVOC格式的数据集,所以此处不再支持标注精灵到PascalVOC格式数据集的转换
docs/quick_start.md
浏览文件 @
7b49b396
...
...
@@ -25,19 +25,19 @@ tar xzvf vegetables_cls.tar.gz
<a
name=
"定义训练验证图像处理流程transforms"
></a>
**3. 定义训练/验证图像处理流程transforms**
使用PaddleX内置的分类模型训练图像处理流程
`ComposedClsTransforms`
,点击查看
[
API文档说明
](
apis/transforms/classification.html#composedclstransforms
)
。
`ComposedClsTransforms`
内置
`RandomHorizontalFlip`
图像增强,用户也可通过
`add_augmenters`
函数,为训练过程添加更多数据增强操作,目前分类过程支持多程数据增强操作,详情查阅
[
数据增强文档
](
apis/transforms/data_augmentations.md
)
由于训练时数据增强操作的加入,因此模型在训练和验证过程中,数据处理流程需要分别进行定义。如下所示,代码在
`train_transforms`
中加入了
[
RandomCrop
](
apis/transforms/cls_transforms.html#RandomCrop
)
和
[
RandomHorizontalFlip
](
apis/transforms/cls_transforms.html#RandomHorizontalFlip
)
两种数据增强方式, 更多方法可以参考
[
数据增强文档
](
apis/transforms/augment.md
)
。
```
from paddlex.cls import transforms
train_transforms = transforms.Compose
dClsTransforms(
mode='train'
,
crop_size=[224, 224])
eval_transforms = transforms.ComposedClsTransforms(
mode='eval',
crop_size=[224, 224])
```
通过
`add_augmenters`
添加更多训练过程中的数据增强操作,例如
```
train_transforms.add_augmenters([transforms.RandomDistort()
])
train_transforms = transforms.Compose
([
transforms.RandomCrop(crop_size=224)
,
transforms.RandomHorizontalFlip(),
transforms.Normalize()
])
eval_transforms = transforms.Compose([
transforms.ResizeByShort(short_size=256),
transforms.CenterCrop(crop_size=224),
transforms.Normalize()
])
```
<a
name=
"定义dataset加载图像分类数据集"
></a>
...
...
docs/train/classification.md
浏览文件 @
7b49b396
...
...
@@ -6,18 +6,21 @@ PaddleX共提供了20+的图像分类模型,包括基于大规模数据训练
| 模型 | Top1精度 | 模型大小 | GPU预测速度 | Arm预测速度 | 备注 |
| :---------------- | :------- | :------- | :--------- | :--------- | |
| ResNet50_vd_ssld | 97.5% | 22M | 10ms | 200ms | |
| ResNet101_vd_ssld | | | | | |
| MobileNetV3_small_ssld | | | | | |
| MobileNetV3_large_ssld | | | | | |
| MobileNetV2 | | | | | |
| ShuffleNetV2 | | | | | |
| AlexNet | | | | | |
| ResNet50_vd_ssld | 97.5% | 22M | 10ms | 200ms | |
更多图像分类模型,可查阅PaddleX模型库和API使用文档。
在选取分类模型时,一般模型大小越大,表示模型的拟合能力越强,但并非越大训练效果越佳。需要用户根据自己的数据集来评估,一般数据样本较少时,MobileNetV3_small_ssld已经可以满足大部分需求。
将对应模型的训练代码保存到本地后,即可直接训练,训练代码会自动下载训练数据开始训练,如保存为
`resnet50_vd
_ssld.py`
,如下命令即可开始训练
点击上述表格模型名,将对应模型的训练代码保存到本地后,即可直接训练,训练代码会自动下载训练数据开始训练,如保存为
`mobilenetv3_small
_ssld.py`
,如下命令即可开始训练
```
python
resnet50_vd
_ssld.py
python
mobilenetv3_small
_ssld.py
```
-
针对自己的机器环境和数据,调整训练参数?先了解下PaddleX中训练参数。
[
——>>传送门
](
)
...
...
docs/train/prediction.md
浏览文件 @
7b49b396
#
模型预测可视化
#
加载模型预测
PaddleX可以使用
`load_model`
接口加载模型(包括训练过程中保存的模型,导出的部署模型,量化模型以及裁剪的模型)进行预测,同时PaddleX中也内置了一系列的可视化工具函数,帮助用户方便地检查模型的效果。
...
...
paddlex/cv/transforms/seg_transforms.py
浏览文件 @
7b49b396
...
...
@@ -1102,20 +1102,21 @@ class ArrangeSegmenter(SegTransform):
class
ComposedSegTransforms
(
Compose
):
""" 语义分割模型(UNet/DeepLabv3p)的图像处理流程,具体如下
训练阶段:
1. 随机对图像以0.5的概率水平翻转
2. 按不同的比例随机Resize原图
1. 随机对图像以0.5的概率水平翻转
,若random_horizontal_flip为False,则跳过此步骤
2. 按不同的比例随机Resize原图
, 处理方式参考[paddlex.seg.transforms.ResizeRangeScaling](#resizerangescaling)。若min_max_size为None,则跳过此步骤
3. 从原图中随机crop出大小为train_crop_size大小的子图,如若crop出来的图小于train_crop_size,则会将图padding到对应大小
4. 图像归一化
预测阶段:
1. 图像归一化
预测阶段:
1. 将图像的最长边resize至(min_max_size[0] + min_max_size[1])//2, 短边按比例resize。若min_max_size为None,则跳过此步骤
2. 图像归一化
Args:
mode(str):
图像处理所处阶段,训练/验证/预测,分别对应'train', 'eval',
'test'
min_max_size(list):
训练过程中,图像的最长边会随机resize至此区间(短边按比例相应resize);预测阶段,图像最长边会resize至此区间中间值,即(min_size+max_size)/2。默认为[400, 600]
train_crop_size(list):
仅在mode为'train`时生效,训练过程中,随机从图像中裁剪出对应大小的子图(如若原图小于此大小,则会padding到此大小),默认为[400, 600]
mean(list): 图像均值
std(list): 图像方差
random_horizontal_flip(bool): 数据增强
方式,仅在mode为`train`时生效,表示训练过程是否随机水平翻转图像,默认为True
mode(str):
Transforms所处的阶段,包括`train', 'eval'或
'test'
min_max_size(list):
用于对图像进行resize,具体作用参见上述步骤。
train_crop_size(list):
训练过程中随机裁剪原图用于训练,具体作用参见上述步骤。此参数仅在mode为`train`时生效。
mean(list): 图像均值
, 默认为[0.485, 0.456, 0.406]。
std(list): 图像方差
,默认为[0.229, 0.224, 0.225]。
random_horizontal_flip(bool): 数据增强
,是否随机水平翻转图像,此参数仅在mode为`train`时生效。
"""
def
__init__
(
self
,
...
...
@@ -1127,19 +1128,29 @@ class ComposedSegTransforms(Compose):
random_horizontal_flip
=
True
):
if
mode
==
'train'
:
# 训练时的transforms,包含数据增强
transforms
=
[
ResizeRangeScaling
(
min_value
=
min
(
min_max_size
),
max_value
=
max
(
min_max_size
)),
RandomPaddingCrop
(
crop_size
=
train_crop_size
),
Normalize
(
mean
=
mean
,
std
=
std
)
]
if
min_max_size
is
None
:
transforms
=
[
RandomPaddingCrop
(
crop_size
=
train_crop_size
),
Normalize
(
mean
=
mean
,
std
=
std
)
]
else
:
transforms
=
[
ResizeRangeScaling
(
min_value
=
min
(
min_max_size
),
max_value
=
max
(
min_max_size
)),
RandomPaddingCrop
(
crop_size
=
train_crop_size
),
Normalize
(
mean
=
mean
,
std
=
std
)
]
if
random_horizontal_flip
:
transforms
.
insert
(
0
,
RandomHorizontalFlip
())
else
:
# 验证/预测时的transforms
long_size
=
(
min
(
min_max_size
)
+
max
(
min_max_size
))
//
2
transforms
=
[
ResizeByLong
(
long_size
=
long_size
),
Normalize
(
mean
=
mean
,
std
=
std
)
]
if
min_max_size
is
None
:
transforms
=
[
Normalize
(
mean
=
mean
,
std
=
std
)]
else
:
long_size
=
(
min
(
min_max_size
)
+
max
(
min_max_size
))
//
2
transforms
=
[
ResizeByLong
(
long_size
=
long_size
),
Normalize
(
mean
=
mean
,
std
=
std
)
]
super
(
ComposedSegTransforms
,
self
).
__init__
(
transforms
)
tutorials/train/
classification/resnet50
.py
→
tutorials/train/
image_classification/alexnet
.py
浏览文件 @
7b49b396
import
os
# 选择使用0号卡
os
.
environ
[
'CUDA_VISIBLE_DEVICES'
]
=
'0'
import
paddle.fluid
as
fluid
from
paddlex.cls
import
transforms
import
paddlex
as
pdx
...
...
@@ -11,13 +7,13 @@ veg_dataset = 'https://bj.bcebos.com/paddlex/datasets/vegetables_cls.tar.gz'
pdx
.
utils
.
download_and_decompress
(
veg_dataset
,
path
=
'./'
)
# 定义训练和验证时的transforms
train_transforms
=
transforms
.
Compose
(
[
transforms
.
RandomCrop
(
crop_size
=
224
),
transforms
.
Normalize
()])
train_transforms
=
transforms
.
Compose
([
transforms
.
RandomCrop
(
crop_size
=
224
),
transforms
.
RandomHorizontalFlip
(),
transforms
.
Normalize
()
])
eval_transforms
=
transforms
.
Compose
([
transforms
.
ResizeByShort
(
short_size
=
256
),
transforms
.
CenterCrop
(
crop_size
=
224
),
transforms
.
Normalize
()
transforms
.
CenterCrop
(
crop_size
=
224
),
transforms
.
Normalize
()
])
# 定义训练和验证所用的数据集
...
...
@@ -33,26 +29,20 @@ eval_dataset = pdx.datasets.ImageNet(
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
# VisualDL启动方式: visualdl --logdir output/
mobilenetv2
/vdl_log --port 8001
# 浏览器打开 https://0.0.0.0:8001即可
# 其中0.0.0.0为本机访问,如为远程服务, 改成相应机器IP
model
=
pdx
.
cls
.
ResNet50
(
num_classes
=
len
(
train_dataset
.
labels
))
model
=
pdx
.
cls
.
AlexNet
(
num_classes
=
len
(
train_dataset
.
labels
))
# AlexNet需要指定确定的input_shape
model
.
fixed_input_shape
=
[
224
,
224
]
model
.
train
(
num_epochs
=
10
,
train_dataset
=
train_dataset
,
train_batch_size
=
32
,
eval_dataset
=
eval_dataset
,
optimizer
=
optimizer
,
save_dir
=
'output/resnet50'
,
lr_decay_epochs
=
[
4
,
6
,
8
],
learning_rate
=
0.0025
,
save_dir
=
'output/alexnet'
,
use_vdl
=
True
)
tutorials/train/classification/mobilenetv2.py
→
tutorials/train/
image_
classification/mobilenetv2.py
浏览文件 @
7b49b396
import
os
# 选择使用0号卡
os
.
environ
[
'CUDA_VISIBLE_DEVICES'
]
=
'0'
from
paddlex.cls
import
transforms
import
paddlex
as
pdx
...
...
@@ -11,14 +8,12 @@ pdx.utils.download_and_decompress(veg_dataset, path='./')
# 定义训练和验证时的transforms
train_transforms
=
transforms
.
Compose
([
transforms
.
RandomCrop
(
crop_size
=
224
),
transforms
.
RandomHorizontalFlip
(),
transforms
.
RandomCrop
(
crop_size
=
224
),
transforms
.
RandomHorizontalFlip
(),
transforms
.
Normalize
()
])
eval_transforms
=
transforms
.
Compose
([
transforms
.
ResizeByShort
(
short_size
=
256
),
transforms
.
CenterCrop
(
crop_size
=
224
),
transforms
.
Normalize
()
transforms
.
CenterCrop
(
crop_size
=
224
),
transforms
.
Normalize
()
])
# 定义训练和验证所用的数据集
...
...
tutorials/train/image_classification/mobilenetv3_small_ssld.py
0 → 100644
浏览文件 @
7b49b396
import
os
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
train_transforms
=
transforms
.
Compose
([
transforms
.
RandomCrop
(
crop_size
=
224
),
transforms
.
RandomHorizontalFlip
(),
transforms
.
Normalize
()
])
eval_transforms
=
transforms
.
Compose
([
transforms
.
ResizeByShort
(
short_size
=
256
),
transforms
.
CenterCrop
(
crop_size
=
224
),
transforms
.
Normalize
()
])
# 定义训练和验证所用的数据集
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
model
=
pdx
.
cls
.
MobileNetV3_small_ssld
(
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/mobilenetv3_small_ssld'
,
use_vdl
=
True
)
tutorials/train/image_classification/resnet50_vd_ssld.py
0 → 100644
浏览文件 @
7b49b396
import
os
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
train_transforms
=
transforms
.
Compose
([
transforms
.
RandomCrop
(
crop_size
=
224
),
transforms
.
RandomHorizontalFlip
(),
transforms
.
Normalize
()
])
eval_transforms
=
transforms
.
Compose
([
transforms
.
ResizeByShort
(
short_size
=
256
),
transforms
.
CenterCrop
(
crop_size
=
224
),
transforms
.
Normalize
()
])
# 定义训练和验证所用的数据集
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
model
=
pdx
.
cls
.
ResNet50_vd_ssld
(
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/resnet50_vd_ssld'
,
use_vdl
=
True
)
tutorials/train/image_classification/shufflenetv2.py
0 → 100644
浏览文件 @
7b49b396
import
os
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
train_transforms
=
transforms
.
Compose
([
transforms
.
RandomCrop
(
crop_size
=
224
),
transforms
.
RandomHorizontalFlip
(),
transforms
.
Normalize
()
])
eval_transforms
=
transforms
.
Compose
([
transforms
.
ResizeByShort
(
short_size
=
256
),
transforms
.
CenterCrop
(
crop_size
=
224
),
transforms
.
Normalize
()
])
# 定义训练和验证所用的数据集
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
model
=
pdx
.
cls
.
ShuffleNetV2
(
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/shufflenetv2'
,
use_vdl
=
True
)
tutorials/train/instance_segmentation/mask_rcnn_hrnet_fpn.py
0 → 100644
浏览文件 @
7b49b396
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
train_transforms
=
transforms
.
Compose
([
transforms
.
RandomHorizontalFlip
(),
transforms
.
Normalize
(),
transforms
.
ResizeByShort
(
short_size
=
800
,
max_size
=
1333
),
transforms
.
Padding
(
coarsest_stride
=
32
)
])
eval_transforms
=
transforms
.
Compose
([
transforms
.
Normalize
(),
transforms
.
ResizeByShort
(
short_size
=
800
,
max_size
=
1333
),
transforms
.
Padding
(
coarsest_stride
=
32
),
])
# 定义训练和验证所用的数据集
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
num_classes
=
len
(
train_dataset
.
labels
)
+
1
model
=
pdx
.
det
.
MaskRCNN
(
num_classes
=
num_classes
,
backbone
=
'HRNet_W18'
)
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_hrnet_fpn'
,
use_vdl
=
True
)
tutorials/train/
detec
tion/mask_rcnn_r50_fpn.py
→
tutorials/train/
instance_segmenta
tion/mask_rcnn_r50_fpn.py
浏览文件 @
7b49b396
...
...
@@ -11,16 +11,16 @@ pdx.utils.download_and_decompress(xiaoduxiong_dataset, path='./')
# 定义训练和验证时的transforms
train_transforms
=
transforms
.
Compose
([
transforms
.
RandomHorizontalFlip
(),
transforms
.
Normalize
(),
transforms
.
ResizeByShort
(
short_size
=
800
,
max_size
=
1333
),
transforms
.
Padding
(
coarsest_stride
=
32
)
transforms
.
RandomHorizontalFlip
(),
transforms
.
Normalize
(),
transforms
.
ResizeByShort
(
short_size
=
800
,
max_size
=
1333
),
transforms
.
Padding
(
coarsest_stride
=
32
)
])
eval_transforms
=
transforms
.
Compose
([
transforms
.
Normalize
(),
transforms
.
ResizeByShort
(
short_size
=
800
,
max_size
=
1333
),
transforms
.
Padding
(
coarsest_stride
=
32
)
transforms
.
ResizeByShort
(
short_size
=
800
,
max_size
=
1333
),
transforms
.
Padding
(
coarsest_stride
=
32
),
])
# 定义训练和验证所用的数据集
...
...
@@ -41,7 +41,7 @@ eval_dataset = pdx.datasets.CocoDetection(
# 其中0.0.0.0为本机访问,如为远程服务, 改成相应机器IP
# num_classes 需要设置为包含背景类的类别数,即: 目标类别数量 + 1
num_classes
=
len
(
train_dataset
.
labels
)
+
1
model
=
pdx
.
det
.
MaskRCNN
(
num_classes
=
num_classes
)
model
=
pdx
.
det
.
MaskRCNN
(
num_classes
=
num_classes
,
backbone
=
'ResNet50_vd'
)
model
.
train
(
num_epochs
=
12
,
train_dataset
=
train_dataset
,
...
...
tutorials/train/object_detection/faster_rcnn_hrnet_fpn.py
0 → 100644
浏览文件 @
7b49b396
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
train_transforms
=
transforms
.
Compose
([
transforms
.
RandomHorizontalFlip
(),
transforms
.
Normalize
(),
transforms
.
ResizeByShort
(
short_size
=
800
,
max_size
=
1333
),
transforms
.
Padding
(
coarsest_stride
=
32
)
])
eval_transforms
=
transforms
.
Compose
([
transforms
.
Normalize
(),
transforms
.
ResizeByShort
(
short_size
=
800
,
max_size
=
1333
),
transforms
.
Padding
(
coarsest_stride
=
32
),
])
# 定义训练和验证所用的数据集
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
num_classes
=
len
(
train_dataset
.
labels
)
+
1
model
=
pdx
.
det
.
FasterRCNN
(
num_classes
=
num_classes
,
backbone
=
'HRNet_W18'
)
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_hrnet_fpn'
,
use_vdl
=
True
)
tutorials/train/detection/faster_rcnn_r50_fpn.py
→
tutorials/train/
object_
detection/faster_rcnn_r50_fpn.py
浏览文件 @
7b49b396
import
os
# 选择使用0号卡
os
.
environ
[
'CUDA_VISIBLE_DEVICES'
]
=
'0'
from
paddlex.det
import
transforms
import
paddlex
as
pdx
...
...
@@ -11,18 +8,17 @@ pdx.utils.download_and_decompress(insect_dataset, path='./')
# 定义训练和验证时的transforms
train_transforms
=
transforms
.
Compose
([
transforms
.
RandomHorizontalFlip
(),
transforms
.
Normalize
(),
transforms
.
ResizeByShort
(
short_size
=
800
,
max_size
=
1333
),
transforms
.
Padding
(
coarsest_stride
=
32
)
transforms
.
RandomHorizontalFlip
(),
transforms
.
Normalize
(),
transforms
.
ResizeByShort
(
short_size
=
800
,
max_size
=
1333
),
transforms
.
Padding
(
coarsest_stride
=
32
)
])
eval_transforms
=
transforms
.
Compose
([
transforms
.
Normalize
(),
transforms
.
ResizeByShort
(
short_size
=
800
,
max_size
=
1333
),
transforms
.
ResizeByShort
(
short_size
=
800
,
max_size
=
1333
),
transforms
.
Padding
(
coarsest_stride
=
32
),
])
# 定义训练和验证所用的数据集
train_dataset
=
pdx
.
datasets
.
VOCDetection
(
data_dir
=
'insect_det'
,
...
...
@@ -43,7 +39,7 @@ eval_dataset = pdx.datasets.VOCDetection(
# 其中0.0.0.0为本机访问,如为远程服务, 改成相应机器IP
# num_classes 需要设置为包含背景类的类别数,即: 目标类别数量 + 1
num_classes
=
len
(
train_dataset
.
labels
)
+
1
model
=
pdx
.
det
.
FasterRCNN
(
num_classes
=
num_classes
)
model
=
pdx
.
det
.
FasterRCNN
(
num_classes
=
num_classes
,
backbone
=
'ResNet50_vd'
)
model
.
train
(
num_epochs
=
12
,
train_dataset
=
train_dataset
,
...
...
tutorials/train/detection/yolov3_darknet53.py
→
tutorials/train/
object_
detection/yolov3_darknet53.py
浏览文件 @
7b49b396
import
os
# 选择使用0号卡
os
.
environ
[
'CUDA_VISIBLE_DEVICES'
]
=
'0'
from
paddlex.det
import
transforms
import
paddlex
as
pdx
...
...
@@ -15,13 +12,15 @@ train_transforms = transforms.Compose([
transforms
.
RandomDistort
(),
transforms
.
RandomExpand
(),
transforms
.
RandomCrop
(),
transforms
.
Resize
(
target_size
=
608
,
interp
=
'RANDOM'
),
transforms
.
Resize
(
target_size
=
608
,
interp
=
'RANDOM'
),
transforms
.
RandomHorizontalFlip
(),
transforms
.
Normalize
(),
])
eval_transforms
=
transforms
.
Compose
([
transforms
.
Resize
(
target_size
=
608
,
interp
=
'CUBIC'
),
transforms
.
Resize
(
target_size
=
608
,
interp
=
'CUBIC'
),
transforms
.
Normalize
(),
])
...
...
tutorials/train/object_detection/yolov3_mobilenetv1.py
0 → 100644
浏览文件 @
7b49b396
import
os
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
train_transforms
=
transforms
.
Compose
([
transforms
.
MixupImage
(
mixup_epoch
=
250
),
transforms
.
RandomDistort
(),
transforms
.
RandomExpand
(),
transforms
.
RandomCrop
(),
transforms
.
Resize
(
target_size
=
608
,
interp
=
'RANDOM'
),
transforms
.
RandomHorizontalFlip
(),
transforms
.
Normalize
(),
])
eval_transforms
=
transforms
.
Compose
([
transforms
.
Resize
(
target_size
=
608
,
interp
=
'CUBIC'
),
transforms
.
Normalize
(),
])
# 定义训练和验证所用的数据集
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
num_classes
=
len
(
train_dataset
.
labels
)
model
=
pdx
.
det
.
YOLOv3
(
num_classes
=
num_classes
,
backbone
=
'MobileNetV1'
)
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_mobilenetv1'
,
use_vdl
=
True
)
tutorials/train/object_detection/yolov3_mobilenetv3.py
0 → 100644
浏览文件 @
7b49b396
import
os
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
train_transforms
=
transforms
.
Compose
([
transforms
.
MixupImage
(
mixup_epoch
=
250
),
transforms
.
RandomDistort
(),
transforms
.
RandomExpand
(),
transforms
.
RandomCrop
(),
transforms
.
Resize
(
target_size
=
608
,
interp
=
'RANDOM'
),
transforms
.
RandomHorizontalFlip
(),
transforms
.
Normalize
(),
])
eval_transforms
=
transforms
.
Compose
([
transforms
.
Resize
(
target_size
=
608
,
interp
=
'CUBIC'
),
transforms
.
Normalize
(),
])
# 定义训练和验证所用的数据集
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
num_classes
=
len
(
train_dataset
.
labels
)
model
=
pdx
.
det
.
YOLOv3
(
num_classes
=
num_classes
,
backbone
=
'MobileNetV3_large'
)
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_mobilenetv3'
,
use_vdl
=
True
)
tutorials/train/se
gmentation/deeplabv3p
.py
→
tutorials/train/se
mantic_segmentation/deeplabv3p_mobilenetv2
.py
浏览文件 @
7b49b396
...
...
@@ -11,14 +11,14 @@ pdx.utils.download_and_decompress(optic_dataset, path='./')
# 定义训练和验证时的transforms
train_transforms
=
transforms
.
Compose
([
transforms
.
RandomHorizontalFlip
(),
transforms
.
Resize
(
target_size
=
512
),
transforms
.
RandomPaddingCrop
(
crop_size
=
500
),
transforms
.
Normalize
()
transforms
.
RandomHorizontalFlip
(),
transforms
.
ResizeRangeScaling
(),
transforms
.
RandomPaddingCrop
(
crop_size
=
512
),
transforms
.
Normalize
()
])
eval_transforms
=
transforms
.
Compose
(
[
transforms
.
Resize
(
512
),
transforms
.
Normalize
()])
eval_transforms
=
transforms
.
Compose
([
transforms
.
ResizeByLong
(
long_size
=
512
),
transforms
.
Padding
(
target_size
=
512
),
transforms
.
Normalize
()
])
# 定义训练和验证所用的数据集
train_dataset
=
pdx
.
datasets
.
SegDataset
(
...
...
@@ -46,5 +46,5 @@ model.train(
train_batch_size
=
4
,
eval_dataset
=
eval_dataset
,
learning_rate
=
0.01
,
save_dir
=
'output/deeplab'
,
save_dir
=
'output/deeplab
v3p_mobilenetv2
'
,
use_vdl
=
True
)
tutorials/train/segmentation/fast_scnn.py
→
tutorials/train/se
mantic_se
gmentation/fast_scnn.py
浏览文件 @
7b49b396
...
...
@@ -11,9 +11,15 @@ 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
=
transforms
.
Compose
([
transforms
.
RandomHorizontalFlip
(),
transforms
.
ResizeRangeScaling
(),
transforms
.
RandomPaddingCrop
(
crop_size
=
512
),
transforms
.
Normalize
()
])
eval_transforms
=
transforms
.
Compose
([
transforms
.
ResizeByLong
(
long_size
=
512
),
transforms
.
Padding
(
target_size
=
512
),
transforms
.
Normalize
()
])
# 定义训练和验证所用的数据集
# API说明: https://paddlex.readthedocs.io/zh_CN/latest/apis/datasets/semantic_segmentation.html#segdataset
...
...
tutorials/train/segmentation/hrnet.py
→
tutorials/train/se
mantic_se
gmentation/hrnet.py
浏览文件 @
7b49b396
...
...
@@ -16,8 +16,8 @@ train_transforms = transforms.Compose([
])
eval_transforms
=
transforms
.
Compose
([
transforms
.
ResizeByLong
(
long_size
=
512
),
transforms
.
Padding
(
target_size
=
512
),
transforms
.
Normalize
()
transforms
.
ResizeByLong
(
long_size
=
512
),
transforms
.
Padding
(
target_size
=
512
),
transforms
.
Normalize
()
])
# 定义训练和验证所用的数据集
...
...
tutorials/train/segmentation/unet.py
→
tutorials/train/se
mantic_se
gmentation/unet.py
浏览文件 @
7b49b396
...
...
@@ -11,15 +11,12 @@ pdx.utils.download_and_decompress(optic_dataset, path='./')
# 定义训练和验证时的transforms
train_transforms
=
transforms
.
Compose
([
transforms
.
RandomHorizontalFlip
(),
transforms
.
ResizeRangeScaling
(),
transforms
.
RandomPaddingCrop
(
crop_size
=
512
),
transforms
.
Normalize
()
transforms
.
RandomHorizontalFlip
(),
transforms
.
ResizeRangeScaling
(),
transforms
.
RandomPaddingCrop
(
crop_size
=
512
),
transforms
.
Normalize
()
])
eval_transforms
=
transforms
.
Compose
([
transforms
.
ResizeByLong
(
long_size
=
512
),
transforms
.
Padding
(
target_size
=
512
),
transforms
.
ResizeByLong
(
long_size
=
512
),
transforms
.
Padding
(
target_size
=
512
),
transforms
.
Normalize
()
])
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录