Browse Source

evaluator 的文档

tags/v1.0.0alpha
YWMditto 2 years ago
parent
commit
93012a1004
3 changed files with 98 additions and 67 deletions
  1. +72
    -48
      fastNLP/core/controllers/evaluator.py
  2. +25
    -18
      fastNLP/core/controllers/trainer.py
  3. +1
    -1
      fastNLP/core/utils/utils.py

+ 72
- 48
fastNLP/core/controllers/evaluator.py View File

@@ -1,7 +1,15 @@
r"""
``Evaluator`` 是新版 fastNLP 中用来进行评测模型的评测器,其与 ``Trainer`` 相对应,二者共同构建起了 fastNLP 中**训练**和**评测**的框架。
``Evaluator`` 的整体架构与 ``Trainer`` 类似,也是利用 ``Driver`` 来负责底层的评测逻辑。通过使用 ``Evaluator``,您可以快速、方便、准确地
对您的模型进行全方位地评测。

.. note::

``Trainer`` 通过来自己内部内置一个 ``Evaluator`` 实例来支持在训练过程中进行验证的功能;
"""

from typing import Union, List, Optional, Dict, Callable
from functools import partial
from dataclasses import is_dataclass
import sys

__all__ = [
'Evaluator'
@@ -20,6 +28,65 @@ from fastNLP.core.log import logger


class Evaluator:
"""
用于评测模型性能好坏的评测器;

.. note::

``Evaluator`` 与 ``Trainer`` 类似,都是使用 ``Driver`` 作为底层来实现评测或者训练,因此大多数与 ``Trainer`` 同名的参数的意义和使用都与
``Trainer`` 中的参数相同,对于这些参数,您可以参考 ``Trainer`` 的文档来获取更详细的信息;详见 :class:`~fastNLP.core.controllers.trainer.Trainer`;

:param model: 训练所需要的模型,例如 ``torch.nn.Module``,等价于 ``Trainer`` 中的 ``model`` 参数;
:param dataloaders: 用于评测的数据集。如果为多个,您需要使用 ``dict`` 传入,即对每一个数据集标上用于标识它们的标签;
:param metrics: 评测时使用的指标。注意该参数必须为 ``dict`` 类型,其中 ``key`` 为一个 ``metric`` 的名称,``value`` 为具体的 ``Metric`` 对象。目前支持以下 metrics:

1. fastNLP 自己的 ``metric``:详见 :class:`fastNLP.core.metrics.Metric`;
2. torchmetrics;
3. allennlp.training.metrics;
4. paddle.metric;

:param driver: 等价于 ``Trainer`` 中的 ``driver`` 参数;
:param device: 等价于 ``Trainer`` 中的 ``device`` 参数;
:param evaluate_batch_step_fn: 您可以传入该参数来定制每次评测一个 batch 的数据时所执行的函数。该函数应接受的两个参数为 ``evaluator`` 和 ``batch``,
不需要有返回值;可以参考 :meth:`~fastNLP.core.controllers.loops.evaluate_batch_loop.EvaluateBatchLoop.batch_step_fn`;
:param evaluate_fn: 用来控制 ``Evaluator`` 在评测的前向传播过程中调用的是哪一个函数,例如对于 pytorch 而言,通过该参数确定使用的是 ``model.evaluate_step`` 还是
``model.forward``(不同训练框架所使用的的前向传播函数的方法名称不同);

1. 如果该值是 ``None``,那么我们会默认使用 ``evaluate_step`` 当做前向传播的函数,如果在模型中没有找到该方法,则使用训练框架默认的前向传播函数;
2. 如果为 ``str`` 类型,例如为 ``my_evaluate_step_fn``,则尝试寻找 ``model.my_evaluate_step_fn``,如果找不到则直接报错;

:param input_mapping: 等价于 ``Trainer`` 中的 ``input_mapping`` 参数;对具体的用于评测一个 batch 的数据使用 ``input_mapping`` 处理之后再输入到 ``model`` 以及 ``metric`` 中。如果针对
``model`` 和 ``metric`` 需要不同的 ``mapping``,请考虑使用 ``evaluate_batch_step_fn`` 参数定制;

.. todo::

之后链接上 参数匹配 的文档;

:param output_mapping: 等价于 ``Trainer`` 中的 ``output_mapping`` 参数;对 ``model`` 输出的内容,将通过 ``output_mapping`` 处理之后再输入到 ``metric`` 中;
:param model_wo_auto_param_call: 等价于 ``Trainer`` 中的 ``model_wo_auto_param_call`` 参数;

.. note::

一个十分需要注意的问题在于 ``model_wo_auto_param_call`` 只会关闭部分的参数匹配,即指挥关闭前向传播时的参数匹配,但是由于 ``Evaluator`` 中
``metric`` 的计算都是自动化的,因此其一定需要参数匹配:根据 ``metric.update`` 的函数签名直接从字典数据中抽取其需要的参数传入进去;


:param fp16: 是否在评测时使用 fp16;
:param verbose: 是否打印 evaluate 的结果;
:kwargs:
* *torch_kwargs* -- 等价于 ``Trainer`` 中的 ``torch_kwargs`` 参数;
* *data_device* -- 等价于 ``Trainer`` 中的 ``data_device`` 参数;
* *model_use_eval_mode* (``bool``) --
是否在评测的时候将 ``model`` 的状态设置成 ``eval`` 状态。在 ``eval`` 状态下,``model`` 的
``dropout`` 与 ``batch normalization`` 将会关闭。默认为 ``True``。如果为 ``False``,``fastNLP`` 不会对 ``model`` 的 ``evaluate`` 状态做任何设置。无论
该值是什么,``fastNLP`` 都会在评测后将 ``model`` 的状态设置为 ``train``;
* *use_dist_sampler* --
是否使用分布式评测的方式。仅当 ``driver`` 为分布式类型时,该参数才有效。默认为根据 ``driver`` 是否支持
分布式进行设置。如果为 ``True``,将使得每个进程上的 ``dataloader`` 自动使用不同数据,所有进程的数据并集是整个数据集;
* *output_from_new_proc* -- 等价于 ``Trainer`` 中的 ``output_from_new_proc`` 参数;
* *progress_bar* -- 等价于 ``Trainer`` 中的 ``progress_bar`` 参数;
"""

driver: Driver
_evaluate_batch_loop: Loop

@@ -29,51 +96,6 @@ class Evaluator:
input_mapping: Optional[Union[Callable, Dict]] = None,
output_mapping: Optional[Union[Callable, Dict]] = None, model_wo_auto_param_call: bool = False,
fp16: bool = False, verbose: int = 1, **kwargs):
"""
用于对数据进行评测。

:param model: 待测试的模型,如果传入的 driver 为 Driver 实例,该参数将被忽略。
:param dataloaders: 待评测的数据集。如果为多个,请使用 dict 传入。
:param metrics: 使用的 metric 。必须为 dict 类型,其中 key 为 metric 的名称,value 为一个 Metric 对象。支持 fastNLP 的
metric ,torchmetrics,allennlpmetrics 等。
:param driver: 使用 driver 。
:param device: 使用的设备。
:param evaluate_batch_step_fn: 定制每次 evaluate batch 执行的函数。该函数应接受的两个参数为 `evaluator` 和 `batch`,
不需要有返回值;可以参考 fastNLP.core.controllers.loops.evaluate_batch_loop.EvaluateBatchLoop中的batch_step_fn函数。
:param evaluate_fn: 用来控制 `Evaluator` 在评测的前向传播过程中是调用哪一个函数,例如是 `model.evaluate_step` 还是
`model.forward`;(1) 如果该值是 None,那么我们会默认使用 `evaluate_step` 当做前向传播的函数,如果在模型中没有
找到该方法,则使用 `model.forward` 函数;(2) 如果为 str 类型,则尝试从 model 中寻找该方法,找不到则报错。
:param input_mapping: 对 dataloader 中输出的内容将通过 input_mapping 处理之后再输入到 model 以及 metric 中。如果针对
model 和 metric 需要不同的 mapping,请考虑使用 evaluate_batch_step_fn 参数定制。
:param output_mapping: 对 model 输出的内容,将通过 output_mapping 处理之后再输入到 metric 中。
:param model_wo_auto_param_call: 是否关闭在训练时调用我们的 auto_param_call 来自动匹配 batch 和 forward 函数的参数的行为;
如果该值为 True,并且当 batch 为字典时,我们会根据 forward 所需要的参数从 batch 中提取对应的对象,传入到 forward 函数中;如果该值
为 False,那么我们会将 batch 直接透传给 forward 函数。注意上述逻辑同样应用于 `train_step`, `evaluate_step` 和 `test_step`;
:param fp16: 是否使用 fp16 。
:param verbose: 是否打印 evaluate 的结果。
:kwargs:
* *torch_kwargs* -- 用于在指定 ``driver`` 为 'torch' 时设定具体 driver 实例的一些参数:
* ddp_kwargs -- 用于在使用 ``TorchDDPDriver`` 时指定 ``DistributedDataParallel`` 初始化时的参数;例如传入
{'find_unused_parameters': True} 来解决有参数不参与前向运算导致的报错等;
* torch_non_blocking -- 表示用于 pytorch 的 tensor 的 to 方法的参数 non_blocking;
* *data_device* -- 表示如果用户的模型 device (在 Driver 中对应为参数 model_device)为 None 时,我们会将数据迁移到 data_device 上;
注意如果 model_device 为 None,那么 data_device 不会起作用;
* *model_use_eval_mode* (``bool``) --
是否在 evaluate 的时候将 model 的状态设置成 eval 状态。在 eval 状态下,model 的
dropout 与 batch normalization 将会关闭。默认为True。如果为 False,fastNLP 不会对 model 的 evaluate 状态做任何设置。无论
该值是什么,fastNLP 都会在 evaluate 接受后将 model 的状态设置为 train 。
* *use_dist_sampler* --
是否使用分布式evaluate的方式。仅当 driver 为分布式类型时,该参数才有效。默认为根据 driver 是否支持
分布式进行设置。如果为True,将使得每个进程上的 dataloader 自动使用不同数据,所有进程的数据并集是整个数据集。
* *output_from_new_proc* --
应当为一个字符串,表示在多进程的 driver 中其它进程的输出流应当被做如何处理;其值应当为以下之一:
["all", "ignore", "only_error"];当该参数的值不是以上值时,该值应当表示一个文件夹的名字,我们会将其他 rank 的输出流重定向到
log 文件中,然后将 log 文件保存在通过该参数值设定的文件夹中;默认为 "only_error";
* *progress_bar* --
evaluate 的时候显示的 progress bar 。目前支持三种 [None, 'raw', 'rich', 'auto'], auto 表示如果检测
到当前terminal为交互型则使用 rich,否则使用 raw。
"""

self.model = model
self.metrics = metrics
self.driver = choose_driver(model, driver, device, fp16=fp16, model_wo_auto_param_call=model_wo_auto_param_call,
@@ -127,8 +149,10 @@ class Evaluator:

self.driver.barrier()

def run(self, num_eval_batch_per_dl: int = -1, **kwargs) -> Dict:
def run(self, num_eval_batch_per_dl: int = -1) -> Dict:
"""
该函数是在 ``Evaluator`` 初始化后用于真正开始评测的函数;

返回一个字典类型的数据,其中key为metric的名字,value为对应metric的结果。
如果存在多个metric,一个dataloader的情况,key的命名规则是
metric_indicator_name#metric_name


+ 25
- 18
fastNLP/core/controllers/trainer.py View File

@@ -43,20 +43,27 @@ class Trainer(TrainerEventTrigger):

:param model: 训练所需要的模型,例如 ``torch.nn.Module``;

.. note::
.. note::

当使用 pytorch 时,注意参数 ``model`` 在大多数情况下为 ``nn.Module``。但是您仍能够通过使用一些特定的组合来使用情况,如下所示:
当使用 pytorch 时,注意参数 ``model`` 在大多数情况下为 ``nn.Module``。但是您仍能够通过使用一些特定的组合来使用情况,如下所示:

1. 当希望使用 ``DataParallel`` 时,您应当使用 ``TorchSingleDriver``,意味着您在初始化 ``Trainer`` 时参数 ``device`` 不应当为
一个 ``List``;
1. 当希望使用 ``DataParallel`` 时,您应当使用 ``TorchSingleDriver``,意味着您在初始化 ``Trainer`` 时参数 ``device`` 不应当为
一个 ``List``;

2. 当您选择自己初始化 ``init_process_group`` 时(这种情况要求您传入的 ``model`` 参数一定为 ``DistributedDataParallel``),
您应当使用 ``TorchDDPDriver``,意味着您需要通过 ``python -m torch.distributed.launch`` 的方式来启动训练,此时参数 ``device``
应当设置为 None(此时我们会忽略该参数),具体见下面对于参数 ``device`` 的更详细的解释。
2. 当您选择自己初始化 ``init_process_group`` 时(这种情况要求您传入的 ``model`` 参数一定为 ``DistributedDataParallel``),
您应当使用 ``TorchDDPDriver``,意味着您需要通过 ``python -m torch.distributed.launch`` 的方式来启动训练,此时参数 ``device``
应当设置为 None(此时我们会忽略该参数),具体见下面对于参数 ``device`` 的更详细的解释。

:param driver: 训练模型所使用的具体的驱动模式,应当为以下选择中的一个:["torch"],之后我们会加入 jittor、paddle 等
国产框架的训练模式;其中 "torch" 表示使用 ``TorchSingleDriver`` 或者 ``TorchDDPDriver``,具体使用哪一种取决于参数 ``device``
的设置;

.. warning::

因为设计上的原因,您可以直接传入一个初始化好的 ``driver`` 实例,但是需要注意的是一个 ``Driver`` 在初始化时需要 ``model`` 这一参数,
这意味着当您传入一个 ``Driver`` 实例时,您传入给 ``Trainer`` 的 ``model`` 参数将会被忽略;也就是说模型在训练时使用的真正的模型是
您传入的 ``Driver`` 实例中的模型;

:param train_dataloader: 训练数据集,注意其必须是单独的一个数据集,不能是 List 或者 Dict;
:param optimizers: 训练所需要的优化器;可以是单独的一个优化器实例,也可以是多个优化器组成的 List;
:param device: 该参数用来指定具体训练时使用的机器;注意当该参数仅当您通过 `torch.distributed.launch/run` 启动时可以为 None,
@@ -268,28 +275,28 @@ class Trainer(TrainerEventTrigger):
* role_maker -- 初始化 ``fleet`` 分布式训练 API 时使用的 ``RoleMaker``
* 其它用于初始化 ``DataParallel`` 的参数;
* *data_device* -- 一个具体的 driver 实例中,有 ``model_device`` 和 ``data_device``,前者表示模型所在的设备,后者表示
当 ``model_device`` 为 None 时应当将数据迁移到哪个设备;
当 ``model_device`` 为 None 时应当将数据迁移到哪个设备;

.. note::

注意您在绝大部分情况下不会用到该参数!
注意您在绝大部分情况下不会用到该参数!

1. 当 driver 实例的 ``model_device`` 不为 None 时,该参数无效;
2. 对于 pytorch,仅当用户自己通过 ``python -m torch.distributed.launch`` 并且自己初始化 ``init_process_group`` 时,
driver 实例的 ``model_device`` 才会为 None;
3. 对于 paddle,该参数无效;
1. 当 driver 实例的 ``model_device`` 不为 None 时,该参数无效;
2. 对于 pytorch,仅当用户自己通过 ``python -m torch.distributed.launch`` 并且自己初始化 ``init_process_group`` 时,
driver 实例的 ``model_device`` 才会为 None;
3. 对于 paddle,该参数无效;

* *use_dist_sampler* -- 表示是否使用分布式的 ``sampler``。在多卡时,分布式 ``sampler`` 将自动决定每张卡上读取的 sample ,使得一个 epoch
内所有卡的 sample 加起来为一整个数据集的 sample。默认会根据 driver 是否为分布式进行设置。
内所有卡的 sample 加起来为一整个数据集的 sample。默认会根据 driver 是否为分布式进行设置。
* *evaluate_use_dist_sampler* -- 表示在 ``Evaluator`` 中在使用分布式的时候是否将 dataloader 的 ``sampler`` 替换为分布式的 ``sampler``;默认为 ``True``;
* *output_from_new_proc* -- 应当为一个字符串,表示在多进程的 driver 中其它进程的输出流应当被做如何处理;其值应当为以下之一:
["all", "ignore", "only_error"];当该参数的值不是以上值时,该值应当表示一个文件夹的名字,我们会将其他 rank 的输出流重定向到
log 文件中,然后将 log 文件保存在通过该参数值设定的文件夹中;默认为 "only_error";
["all", "ignore", "only_error"];当该参数的值不是以上值时,该值应当表示一个文件夹的名字,我们会将其他 rank 的输出流重定向到
log 文件中,然后将 log 文件保存在通过该参数值设定的文件夹中;默认为 "only_error";

注意该参数仅当使用分布式的 ``driver`` 时才有效,例如 ``TorchDDPDriver``;
* *progress_bar* -- 以哪种方式显示 progress ,目前支持[None, 'raw', 'rich', 'auto'] 或者 RichCallback, RawTextCallback对象,
默认为 auto , auto 表示如果检测到当前 terminal 为交互型则使用 RichCallback,否则使用 RawTextCallback对象。如果
需要定制 progress bar 的参数,例如打印频率等,可以传入 RichCallback, RawTextCallback 对象。
默认为 auto , auto 表示如果检测到当前 terminal 为交互型则使用 RichCallback,否则使用 RawTextCallback对象。如果
需要定制 progress bar 的参数,例如打印频率等,可以传入 RichCallback, RawTextCallback 对象。
* *train_input_mapping* -- 与 input_mapping 一致,但是只用于 ``Trainer`` 中。与 input_mapping 互斥。
* *train_output_mapping* -- 与 output_mapping 一致,但是只用于 ``Trainer`` 中。与 output_mapping 互斥。
* *evaluate_input_mapping* -- 与 input_mapping 一致,但是只用于 ``Evaluator`` 中。与 input_mapping 互斥。


+ 1
- 1
fastNLP/core/utils/utils.py View File

@@ -142,7 +142,7 @@ def auto_param_call(fn: Callable, *args, signature_fn: Optional[Callable] = None
if _name not in _has_params:
_has_params[_name] = _value

if len(_has_params)<len(_need_params):
if len(_has_params) < len(_need_params):
miss_params = list(set(_need_params.keys()) - set(_has_params.keys()))
fn_msg = _get_fun_msg(fn if signature_fn is None else signature_fn)
_provided_keys = _get_keys(args)


Loading…
Cancel
Save