diff --git a/README.md b/README.md index be3ebea..4a55317 100644 --- a/README.md +++ b/README.md @@ -200,8 +200,9 @@ PaddleRS目录树中关键部分如下: * [智能标注工具EISeg](https://github.com/PaddlePaddle/PaddleSeg/tree/release/2.6/EISeg) * [遥感影像处理工具集](./docs/data/tools.md) * 组件介绍 - * [数据预处理/数据增强](./docs/intro/transforms.md) + * [数据集预处理脚本](./docs/intro/data_prep.md) * [模型库](./docs/intro/model_zoo.md) + * [数据变换算子](./docs/intro/transforms.md) * 模型训练 * [模型训练API说明](./docs/apis/train.md) * 模型部署 diff --git a/docs/apis/data.md b/docs/apis/data.md index ab8a523..6be2e32 100644 --- a/docs/apis/data.md +++ b/docs/apis/data.md @@ -86,6 +86,22 @@ ### 图像复原数据集`ResDataset` +`ResDataset`定义在:https://github.com/PaddlePaddle/PaddleRS/blob/develop/paddlers/datasets/res_dataset.py + +其初始化参数列表如下: + +|参数名称|类型|参数说明|默认值| +|-------|----|--------|-----| +|`data_dir`|`str`|数据集存放目录。|| +|`file_list`|`str`|file list路径。file list是一个文本文件,其中每一行包含一个样本的路径信息。`ResDataset`对file list的具体要求请参见下文。|| +|`transforms`|`paddlers.transforms.Compose`|对输入数据应用的数据变换算子。|| +|`num_workers`|`int` \| `str`|加载数据时使用的辅助进程数。若设置为`'auto'`,则按照如下规则确定使用进程数:当CPU核心数大于16时,使用8个数据读取辅助进程;否则,使用CPU核心数一半数量的辅助进程。|`'auto'`| +|`shuffle`|`bool`|是否随机打乱数据集中的样本。|`False`| +|`sr_factor`|`int` \| `None`|对于超分辨率重建任务,指定为超分辨率倍数;对于其它任务,指定为`None`。|`None`| + +`ResDataset`对file list的要求如下: + +- file list中的每一行应该包含2个以空格分隔的项,依次表示输入影像(例如超分辨率重建任务中的低分辨率影像)相对`data_dir`的路径以及目标影像(例如超分辨率重建任务中的高分辨率影像)相对`data_dir`的路径。 ### 图像分割数据集`SegDataset` diff --git a/docs/apis/infer.md b/docs/apis/infer.md index 2a5b62d..880b5cc 100644 --- a/docs/apis/infer.md +++ b/docs/apis/infer.md @@ -89,7 +89,28 @@ def predict(self, img_file, transforms=None): #### `BaseRestorer.predict()` +接口形式: + +```python +def predict(self, img_file, transforms=None): +``` + +输入参数: + +|参数名称|类型|参数说明|默认值| +|-------|----|--------|-----| +|`img_file`|`list[str\|np.ndarray]` \| `str` \| `np.ndarray`|输入影像数据(NumPy数组形式)或输入影像路径。若需要一次性预测一组影像,以列表包含这些影像的数据或路径(每幅影像对应列表中的一个元素)。|| +|`transforms`|`paddlers.transforms.Compose` \| `None`|对输入数据应用的数据变换算子。若为`None`,则使用训练器在验证阶段使用的数据变换算子。|`None`| + +返回格式: + +若`img_file`是一个字符串或NumPy数组,则返回对象为包含下列键值对的字典: +``` +{"res_map": 模型输出的复原或重建影像(以[h, w, c]格式排布)} +``` + +若`img_file`是一个列表,则返回对象为与`img_file`等长的列表,其中的每一项为一个字典(键值对如上所示),顺序对应`img_file`中的每个元素。 #### `BaseSegmenter.predict()` @@ -190,7 +211,7 @@ def predict(self, |参数名称|类型|参数说明|默认值| |-------|----|--------|-----| -|`img_file`|`list[str\|tuple\|np.ndarray]` \| `str` \| `tuple` \| `np.ndarray`|对于场景分类、目标检测和图像分割任务来说,该参数可为单一图像路径,或是解码后的、排列格式为[h, w, c]且具有float32类型的图像数据(表示为NumPy数组形式),或者是一组图像路径或np.ndarray对象构成的列表;对于变化检测任务来说,该参数可以为图像路径二元组(分别表示前后两个时相影像路径),或是解码后的两幅图像组成的二元组,或者是上述两种二元组之一构成的列表。|| +|`img_file`|`list[str\|tuple\|np.ndarray]` \| `str` \| `tuple` \| `np.ndarray`|对于场景分类、目标检测、图像复原和图像分割任务来说,该参数可为单一图像路径,或是解码后的、排列格式为[h, w, c]且具有float32类型的图像数据(表示为NumPy数组形式),或者是一组图像路径或np.ndarray对象构成的列表;对于变化检测任务来说,该参数可以为图像路径二元组(分别表示前后两个时相影像路径),或是解码后的两幅图像组成的二元组,或者是上述两种二元组之一构成的列表。|| |`topk`|`int`|场景分类模型预测时使用,表示选取模型输出概率大小排名前`topk`的类别作为最终结果。|`1`| |`transforms`|`paddlers.transforms.Compose`\|`None`|对输入数据应用的数据变换算子。若为`None`,则使用从`model.yml`中读取的算子。|`None`| |`warmup_iters`|`int`|预热轮数,用于评估模型推理以及前后处理速度。若大于1,将预先重复执行`warmup_iters`次推理,而后才开始正式的预测及其速度评估。|`0`| diff --git a/docs/apis/train.md b/docs/apis/train.md index 1cfd883..d28aa94 100644 --- a/docs/apis/train.md +++ b/docs/apis/train.md @@ -1,6 +1,6 @@ # PaddleRS训练API说明 -**训练器**封装了模型训练、验证、量化以及动态图推理等逻辑,定义在`paddlers/tasks/`目录下的文件中。为了方便用户使用,PaddleRS为所有支持的模型均提供了继承自父类[`BaseModel`](https://github.com/PaddlePaddle/PaddleRS/blob/develop/paddlers/tasks/base.py)的训练器,并对外提供数个API。变化检测、场景分类、图像分割以及目标检测任务对应的训练器类型分别为`BaseChangeDetector`、`BaseClassifier`、`BaseDetector`和`BaseSegmenter`。本文档介绍训练器的初始化函数以及`train()`、`evaluate()` API。 +**训练器**封装了模型训练、验证、量化以及动态图推理等逻辑,定义在`paddlers/tasks/`目录下的文件中。为了方便用户使用,PaddleRS为所有支持的模型均提供了继承自父类[`BaseModel`](https://github.com/PaddlePaddle/PaddleRS/blob/develop/paddlers/tasks/base.py)的训练器,并对外提供数个API。变化检测、场景分类、目标检测、图像复原以及图像分割任务对应的训练器类型分别为`BaseChangeDetector`、`BaseClassifier`、`BaseDetector`、`BaseRestorer`和`BaseSegmenter`。本文档介绍训练器的初始化函数以及`train()`、`evaluate()` API。 ## 初始化训练器 @@ -28,7 +28,9 @@ ### 初始化`BaseRestorer`子类对象 - +- 一般支持设置`sr_factor`参数,表示超分辨率倍数;对于不支持超分辨率重建任务的模型,`sr_factor`设置为`None`。 +- 可通过`losses`参数指定模型训练时使用的损失函数,传入实参需为可调用对象或字典。手动指定的`losses`与子类的`default_loss()`方法返回值必须具有相同的格式。 +- 不同的子类支持与模型相关的输入参数,详情请参考[模型定义](https://github.com/PaddlePaddle/PaddleRS/blob/develop/paddlers/rs_models/res)和[训练器定义](https://github.com/PaddlePaddle/PaddleRS/blob/develop/paddlers/tasks/restorer.py)。 ### 初始化`BaseSegmenter`子类对象 @@ -180,6 +182,46 @@ def train(self, ### `BaseRestorer.train()` +接口形式: + +```python +def train(self, + num_epochs, + train_dataset, + train_batch_size=2, + eval_dataset=None, + optimizer=None, + save_interval_epochs=1, + log_interval_steps=2, + save_dir='output', + pretrain_weights='CITYSCAPES', + learning_rate=0.01, + lr_decay_power=0.9, + early_stop=False, + early_stop_patience=5, + use_vdl=True, + resume_checkpoint=None): +``` + +其中各参数的含义如下: + +|参数名称|类型|参数说明|默认值| +|-------|----|--------|-----| +|`num_epochs`|`int`|训练的epoch数目。|| +|`train_dataset`|`paddlers.datasets.ResDataset`|训练数据集。|| +|`train_batch_size`|`int`|训练时使用的batch size。|`2`| +|`eval_dataset`|`paddlers.datasets.ResDataset` \| `None`|验证数据集。|`None`| +|`optimizer`|`paddle.optimizer.Optimizer` \| `None`|训练时使用的优化器。若为`None`,则使用默认定义的优化器。|`None`| +|`save_interval_epochs`|`int`|训练时存储模型的间隔epoch数。|`1`| +|`log_interval_steps`|`int`|训练时打印日志的间隔step数(即迭代数)。|`2`| +|`save_dir`|`str`|存储模型的路径。|`'output'`| +|`pretrain_weights`|`str` \| `None`|预训练权重的名称/路径。若为`None`,则不适用预训练权重。|`'CITYSCAPES'`| +|`learning_rate`|`float`|训练时使用的学习率大小,适用于默认优化器。|`0.01`| +|`lr_decay_power`|`float`|学习率衰减系数,适用于默认优化器。|`0.9`| +|`early_stop`|`bool`|训练过程是否启用早停策略。|`False`| +|`early_stop_patience`|`int`|启用早停策略时的`patience`参数(参见[`EarlyStop`](https://github.com/PaddlePaddle/PaddleRS/blob/develop/paddlers/utils/utils.py))。|`5`| +|`use_vdl`|`bool`|是否启用VisualDL日志。|`True`| +|`resume_checkpoint`|`str` \| `None`|检查点路径。PaddleRS支持从检查点(包含先前训练过程中存储的模型权重和优化器权重)继续训练,但需注意`resume_checkpoint`与`pretrain_weights`不得同时设置为`None`以外的值。|`None`| ### `BaseSegmenter.train()` @@ -284,7 +326,7 @@ def evaluate(self, eval_dataset, batch_size=1, return_details=False): ``` {"top1": top1准确率, - "top5": `top5准确率} + "top5": top5准确率} ``` ### `BaseDetector.evaluate()` @@ -324,6 +366,26 @@ def evaluate(self, ### `BaseRestorer.evaluate()` +接口形式: + +```python +def evaluate(self, eval_dataset, batch_size=1, return_details=False): +``` + +输入参数如下: + +|参数名称|类型|参数说明|默认值| +|-------|----|--------|-----| +|`eval_dataset`|`paddlers.datasets.ResDataset`|评估数据集。|| +|`batch_size`|`int`|评估时使用的batch size(多卡训练时,为所有设备合计batch size)。|`1`| +|`return_details`|`bool`|*当前版本请勿手动设置此参数。*|`False`| + +输出为一个`collections.OrderedDict`对象,包含如下键值对: + +``` +{"psnr": PSNR指标, + "ssim": SSIM指标} +``` ### `BaseSegmenter.evaluate()` diff --git a/docs/data/tools.md b/docs/data/tools.md index f434c49..035832d 100644 --- a/docs/data/tools.md +++ b/docs/data/tools.md @@ -8,8 +8,9 @@ PaddleRS在`tools`目录中提供了丰富的遥感影像处理工具,包括 - `match.py`:用于实现两幅影像的配准。 - `split.py`:用于对大幅面影像数据进行切片。 - `coco_tools/`:COCO工具合集,用于统计处理COCO格式标注文件。 +- `prepare_dataset/`:数据集预处理脚本合集。 -## 使用示例 +## 使用说明 首先请确保您已将PaddleRS下载到本地。进入`tools`目录: @@ -101,3 +102,24 @@ python split.py --image_path {输入影像路径} [--mask_path {真值标签路 - `json_Merge.py`: 将多个json文件合并为一个。 详细使用方法请参见[coco_tools使用说明](coco_tools.md)。 + +### prepare_dataset + +`prepare_dataset`目录中包含一系列数据预处理脚本,主要用于预处理已下载到本地的遥感开源数据集,使其符合PaddleRS训练、验证、测试的标准。 + +在执行脚本前,您可以通过`--help`选项获取帮助信息。例如: + +```shell +python prepare_dataset/prepare_levircd.py --help +``` + +以下列出了脚本中常见的命令行选项: + +- `--in_dataset_dir`:下载到本地的原始数据集所在路径。示例:`--in_dataset_dir downloads/LEVIR-CD`。 +- `--out_dataset_dir`:处理后的数据集存放路径。示例:`--out_dataset_dir data/levircd`。 +- `--crop_size`:对于支持影像裁块的数据集,指定切分的影像块大小。示例:`--crop_size 256`。 +- `--crop_stride`:对于支持影像裁块的数据集,指定切分时滑窗移动的步长。示例:`--crop_stride 256`。 +- `--seed`:随机种子。可用于固定随机数生成器产生的伪随机数序列,从而得到固定的数据集划分结果。示例:`--seed 1919810` +- `--ratios`:对于支持子集随机划分的数据集,指定需要划分的各个子集的样本比例。示例:`--ratios 0.7 0.2 0.1`。 + +您可以在[此文档](https://github.com/PaddlePaddle/PaddleRS/blob/develop/docs/intro/data_prep.md)中查看PaddleRS提供哪些数据集的预处理脚本。 diff --git a/docs/dev/dev_guide.md b/docs/dev/dev_guide.md index 9f678af..e4de181 100644 --- a/docs/dev/dev_guide.md +++ b/docs/dev/dev_guide.md @@ -70,6 +70,15 @@ Args: 4. 在全局变量`__all__`中添加新增训练器的类名。 +需要注意的是,对于图像复原任务,模型的前向、反向逻辑均实现在训练器定义中。对于GAN等需要用到多个网络的模型,训练器的编写请参照如下规范: +- 重写`build_net()`方法,使用`GANAdapter`维护所有网络。`GANAdapter`对象在构造时接受两个列表作为输入:第一个列表中包含所有的生成器,其中第一个元素为主生成器;第二个列表中包含所有的判别器。 +- 重写`default_loss()`方法,构建损失函数。若训练过程中需要用到多个损失函数,推荐以字典的形式组织。 +- 重写`default_optimizer()`方法,构建一个或多个优化器。当`build_net()`返回值的类型为`GANAdapter`时,`parameters`参数为一个字典。其中,`parameters['params_g']`是一个列表,顺序包含各个生成器的state dict;`parameters['params_d']`是一个列表,顺序包含各个判别器的state dict。若构建多个优化器,在返回时应使用`OptimizerAdapter`包装。 +- 重写`run_gan()`方法,该方法接受`net`、`inputs`、`mode`、和`gan_mode`四个参数,用于执行训练过程中的某一个子任务,例如生成器的前向计算、判别器的前向计算等等。 +- 重写`train_step()`方法,在其中编写模型训练过程中一次迭代的具体逻辑。通常的做法是反复调用`run_gan()`,每次调用时都根据需要构造不同的`inputs`、并使其工作在不同的`gan_mode`,并从每次返回的`outputs`字典中抽取有用的字段(如各项损失),汇总至最终结果。 + +GAN训练器的具体例子可以参考`ESRGAN`。 + ## 2 新增数据预处理/数据增强函数或算子 ### 2.1 新增数据预处理/数据增强函数 diff --git a/docs/intro/data_prep.md b/docs/intro/data_prep.md new file mode 100644 index 0000000..6932e6b --- /dev/null +++ b/docs/intro/data_prep.md @@ -0,0 +1,9 @@ +# 数据集预处理脚本 + +## PaddleRS已支持的数据集预处理脚本列表 + +| 任务 | 数据集名称 | 数据集地址 | 预处理脚本 | +|-----|-----------|----------|----------| +| 变化检测 | LEVIR-CD | https://justchenhao.github.io/LEVIR/ | [prepare_levircd.py](https://github.com/PaddlePaddle/PaddleRS/blob/develop/tools/prepare_dataset/prepare_levircd.py) | +| 变化检测 | Season-varying | https://paperswithcode.com/dataset/cdd-dataset-season-varying | [prepare_svcd.py](https://github.com/PaddlePaddle/PaddleRS/blob/develop/tools/prepare_dataset/prepare_svcd.py) | +| 目标检测 | RSOD | https://github.com/RSIA-LIESMARS-WHU/RSOD-Dataset- | [prepare_rsod](https://github.com/PaddlePaddle/PaddleRS/blob/develop/tools/prepare_dataset/prepare_rsod.py) | diff --git a/docs/intro/transforms.md b/docs/intro/transforms.md index c7234de..f568541 100644 --- a/docs/intro/transforms.md +++ b/docs/intro/transforms.md @@ -1,4 +1,4 @@ -# 数据预处理/数据增强 +# 数据变换算子 ## PaddleRS已支持的数据变换算子列表 diff --git a/paddlers/tasks/change_detector.py b/paddlers/tasks/change_detector.py index 7a45172..d79734e 100644 --- a/paddlers/tasks/change_detector.py +++ b/paddlers/tasks/change_detector.py @@ -409,18 +409,18 @@ class BaseChangeDetector(BaseModel): key-value pairs: For binary change detection (number of classes == 2), the key-value pairs are like: - {"iou": `intersection over union for the change class`, - "f1": `F1 score for the change class`, - "oacc": `overall accuracy`, - "kappa": ` kappa coefficient`}. + {"iou": intersection over union for the change class, + "f1": F1 score for the change class, + "oacc": overall accuracy, + "kappa": kappa coefficient}. For multi-class change detection (number of classes > 2), the key-value pairs are like: - {"miou": `mean intersection over union`, - "category_iou": `category-wise mean intersection over union`, - "oacc": `overall accuracy`, - "category_acc": `category-wise accuracy`, - "kappa": ` kappa coefficient`, - "category_F1-score": `F1 score`}. + {"miou": mean intersection over union, + "category_iou": category-wise mean intersection over union, + "oacc": overall accuracy, + "category_acc": category-wise accuracy, + "kappa": kappa coefficient, + "category_F1-score": F1 score}. """ self._check_transforms(eval_dataset.transforms, 'eval') diff --git a/paddlers/tasks/classifier.py b/paddlers/tasks/classifier.py index 23ab154..5756c71 100644 --- a/paddlers/tasks/classifier.py +++ b/paddlers/tasks/classifier.py @@ -380,8 +380,8 @@ class BaseClassifier(BaseModel): Returns: If `return_details` is False, return collections.OrderedDict with key-value pairs: - {"top1": `acc of top1`, - "top5": `acc of top5`}. + {"top1": acc of top1, + "top5": acc of top5}. """ self._check_transforms(eval_dataset.transforms, 'eval') diff --git a/paddlers/tasks/object_detector.py b/paddlers/tasks/object_detector.py index 3086bd5..e954a69 100644 --- a/paddlers/tasks/object_detector.py +++ b/paddlers/tasks/object_detector.py @@ -491,7 +491,7 @@ class BaseDetector(BaseModel): Returns: If `return_details` is False, return collections.OrderedDict with key-value pairs: - {"bbox_mmap":`mean average precision (0.50, 11point)`}. + {"bbox_mmap": mean average precision (0.50, 11point)}. """ if metric is None: diff --git a/paddlers/tasks/restorer.py b/paddlers/tasks/restorer.py index f68264d..5a56c48 100644 --- a/paddlers/tasks/restorer.py +++ b/paddlers/tasks/restorer.py @@ -365,8 +365,8 @@ class BaseRestorer(BaseModel): Returns: If `return_details` is False, return collections.OrderedDict with key-value pairs: - {"psnr": `peak signal-to-noise ratio`, - "ssim": `structural similarity`}. + {"psnr": peak signal-to-noise ratio, + "ssim": structural similarity}. """ diff --git a/paddlers/tasks/segmenter.py b/paddlers/tasks/segmenter.py index b9c586f..8a4c34f 100644 --- a/paddlers/tasks/segmenter.py +++ b/paddlers/tasks/segmenter.py @@ -398,12 +398,12 @@ class BaseSegmenter(BaseModel): Returns: collections.OrderedDict with key-value pairs: - {"miou": `mean intersection over union`, - "category_iou": `category-wise mean intersection over union`, - "oacc": `overall accuracy`, - "category_acc": `category-wise accuracy`, - "kappa": ` kappa coefficient`, - "category_F1-score": `F1 score`}. + {"miou": mean intersection over union, + "category_iou": category-wise mean intersection over union, + "oacc": overall accuracy, + "category_acc": category-wise accuracy, + "kappa": kappa coefficient, + "category_F1-score": F1 score}. """