Browse Source

split the class's doc & __init__'s doc (core part)

tags/v0.4.10
ChenXin 5 years ago
parent
commit
b1fe5f5321
13 changed files with 286 additions and 239 deletions
  1. +20
    -16
      fastNLP/core/batch.py
  2. +65
    -50
      fastNLP/core/callback.py
  3. +11
    -10
      fastNLP/core/dataset.py
  4. +6
    -6
      fastNLP/core/field.py
  5. +2
    -1
      fastNLP/core/instance.py
  6. +13
    -10
      fastNLP/core/losses.py
  7. +34
    -32
      fastNLP/core/metrics.py
  8. +34
    -22
      fastNLP/core/optimizer.py
  9. +4
    -2
      fastNLP/core/predictor.py
  10. +7
    -5
      fastNLP/core/sampler.py
  11. +25
    -24
      fastNLP/core/tester.py
  12. +50
    -48
      fastNLP/core/trainer.py
  13. +15
    -13
      fastNLP/core/vocabulary.py

+ 20
- 16
fastNLP/core/batch.py View File

@@ -9,15 +9,16 @@ __all__ = [
] ]


import atexit import atexit
from numbers import Number


import numpy as np import numpy as np
import torch import torch
import torch.utils.data import torch.utils.data
from numbers import Number


from .sampler import SequentialSampler
from .dataset import DataSet
from ._logger import logger from ._logger import logger
from .dataset import DataSet
from .sampler import SequentialSampler

_python_is_exit = False _python_is_exit = False




@@ -153,23 +154,26 @@ class DataSetIter(BatchIter):
for batch_x, batch_y in batch: for batch_x, batch_y in batch:
# do stuff ... # do stuff ...


:param dataset: :class:`~fastNLP.DataSet` 对象, 数据集
:param int batch_size: 取出的batch大小
:param sampler: 规定使用的 :class:`~fastNLP.Sampler` 方式. 若为 ``None`` , 使用 :class:`~fastNLP.SequentialSampler`.

Default: ``None``
:param bool as_numpy: 若为 ``True`` , 输出batch为 numpy.array. 否则为 :class:`torch.Tensor`.

Default: ``False``
:param int num_workers: 使用多少个进程来预处理数据
:param bool pin_memory: 是否将产生的tensor使用pin memory, 可能会加快速度。
:param bool drop_last: 如果最后一个batch没有batch_size这么多sample,就扔掉最后一个
:param timeout:
:param worker_init_fn: 在每个worker启动时调用该函数,会传入一个值,该值是worker的index。
""" """
def __init__(self, dataset, batch_size=1, sampler=None, as_numpy=False, def __init__(self, dataset, batch_size=1, sampler=None, as_numpy=False,
num_workers=0, pin_memory=False, drop_last=False, num_workers=0, pin_memory=False, drop_last=False,
timeout=0, worker_init_fn=None): timeout=0, worker_init_fn=None):
"""
:param dataset: :class:`~fastNLP.DataSet` 对象, 数据集
:param int batch_size: 取出的batch大小
:param sampler: 规定使用的 :class:`~fastNLP.Sampler` 方式. 若为 ``None`` , 使用 :class:`~fastNLP.SequentialSampler`.
Default: ``None``
:param bool as_numpy: 若为 ``True`` , 输出batch为 numpy.array. 否则为 :class:`torch.Tensor`.
Default: ``False``
:param int num_workers: 使用多少个进程来预处理数据
:param bool pin_memory: 是否将产生的tensor使用pin memory, 可能会加快速度。
:param bool drop_last: 如果最后一个batch没有batch_size这么多sample,就扔掉最后一个
:param timeout:
:param worker_init_fn: 在每个worker启动时调用该函数,会传入一个值,该值是worker的index。
"""
super().__init__() super().__init__()
assert isinstance(dataset, DataSet) assert isinstance(dataset, DataSet)
if not isinstance(sampler, torch.utils.data.Sampler): if not isinstance(sampler, torch.utils.data.Sampler):


+ 65
- 50
fastNLP/core/callback.py View File

@@ -317,9 +317,11 @@ def _transfer(func):




class CallbackManager(Callback): class CallbackManager(Callback):
"""
内部使用的Callback管理类
"""
def __init__(self, env, callbacks=None): def __init__(self, env, callbacks=None):
""" """
内部使用的Callback管理类


:param dict env: The key is the name of the Trainer attribute(str). The value is the attribute itself. :param dict env: The key is the name of the Trainer attribute(str). The value is the attribute itself.
:param List[Callback] callbacks: :param List[Callback] callbacks:
@@ -435,23 +437,23 @@ class DistCallbackManager(CallbackManager):
class GradientClipCallback(Callback): class GradientClipCallback(Callback):
""" """
每次backward前,将parameter的gradient clip到某个范围。 每次backward前,将parameter的gradient clip到某个范围。

:param None,torch.Tensor,List[torch.Tensor] parameters: 一般通过model.parameters()获得。
如果为None则默认对Trainer的model中所有参数进行clip
:param float clip_value: 将gradient 限制到[-clip_value, clip_value]。clip_value应该为正数
:param str clip_type: 支持'norm', 'value'
两种::

1 'norm', 将gradient的norm rescale到[-clip_value, clip_value]
2 'value', 将gradient限制在[-clip_value, clip_value],
小于-clip_value的gradient被赋值为-clip_value;
大于clip_value的gradient被赋值为clip_value.

""" """
def __init__(self, parameters=None, clip_value=1, clip_type='norm'): def __init__(self, parameters=None, clip_value=1, clip_type='norm'):
"""
:param None,torch.Tensor,List[torch.Tensor] parameters: 一般通过model.parameters()获得。
如果为None则默认对Trainer的model中所有参数进行clip
:param float clip_value: 将gradient 限制到[-clip_value, clip_value]。clip_value应该为正数
:param str clip_type: 支持'norm', 'value'
两种::
1 'norm', 将gradient的norm rescale到[-clip_value, clip_value]
2 'value', 将gradient限制在[-clip_value, clip_value],
小于-clip_value的gradient被赋值为-clip_value;
大于clip_value的gradient被赋值为clip_value.
"""
super().__init__() super().__init__()
from torch import nn from torch import nn
@@ -477,12 +479,14 @@ class GradientClipCallback(Callback):


class EarlyStopCallback(Callback): class EarlyStopCallback(Callback):
""" """
多少个epoch没有变好就停止训练,相关类 :class:`EarlyStopError`

:param int patience: epoch的数量
多少个epoch没有变好就停止训练,相关类 :class:`~fastNLP.core.callback.EarlyStopError`
""" """
def __init__(self, patience): def __init__(self, patience):
"""
:param int patience: epoch的数量
"""
super(EarlyStopCallback, self).__init__() super(EarlyStopCallback, self).__init__()
self.patience = patience self.patience = patience
self.wait = 0 self.wait = 0
@@ -510,17 +514,19 @@ class FitlogCallback(Callback):
一个(或多个)test数据集进行测试(只有在trainer具有dev时才能使用),每次在dev上evaluate之后会在这些数据集上验证一下。 一个(或多个)test数据集进行测试(只有在trainer具有dev时才能使用),每次在dev上evaluate之后会在这些数据集上验证一下。
并将验证结果写入到fitlog中。这些数据集的结果是根据dev上最好的结果报道的,即如果dev在第3个epoch取得了最佳,则 并将验证结果写入到fitlog中。这些数据集的结果是根据dev上最好的结果报道的,即如果dev在第3个epoch取得了最佳,则
fitlog中记录的关于这些数据集的结果就是来自第三个epoch的结果。 fitlog中记录的关于这些数据集的结果就是来自第三个epoch的结果。

:param ~fastNLP.DataSet,Dict[~fastNLP.DataSet] data: 传入DataSet对象,会使用多个Trainer中的metric对数据进行验证。如果需要
传入多个DataSet请通过dict的方式传入,dict的key将作为对应dataset的name传递给fitlog。data的结果的名称以'data'开头。
:param ~fastNLP.Tester,Dict[~fastNLP.Tester] tester: Tester对象,将在on_valid_end时调用。tester的结果的名称以'tester'开头
:param int log_loss_every: 多少个step记录一次loss(记录的是这几个batch的loss平均值),如果数据集较大建议将该值设置得
大一些,不然会导致log文件巨大。默认为0, 即不要记录loss。
:param int verbose: 是否在终端打印evaluation的结果,0不打印。
:param bool log_exception: fitlog是否记录发生的exception信息
""" """


def __init__(self, data=None, tester=None, log_loss_every=0, verbose=0, log_exception=False): def __init__(self, data=None, tester=None, log_loss_every=0, verbose=0, log_exception=False):
"""
:param ~fastNLP.DataSet,Dict[~fastNLP.DataSet] data: 传入DataSet对象,会使用多个Trainer中的metric对数据进行验证。如果需要
传入多个DataSet请通过dict的方式传入,dict的key将作为对应dataset的name传递给fitlog。data的结果的名称以'data'开头。
:param ~fastNLP.Tester,Dict[~fastNLP.Tester] tester: Tester对象,将在on_valid_end时调用。tester的结果的名称以'tester'开头
:param int log_loss_every: 多少个step记录一次loss(记录的是这几个batch的loss平均值),如果数据集较大建议将该值设置得
大一些,不然会导致log文件巨大。默认为0, 即不要记录loss。
:param int verbose: 是否在终端打印evaluation的结果,0不打印。
:param bool log_exception: fitlog是否记录发生的exception信息
"""
super().__init__() super().__init__()
self.datasets = {} self.datasets = {}
self.testers = {} self.testers = {}
@@ -604,13 +610,14 @@ class FitlogCallback(Callback):
class EvaluateCallback(Callback): class EvaluateCallback(Callback):
""" """
该callback用于扩展Trainer训练过程中只能对dev数据进行验证的问题。 该callback用于扩展Trainer训练过程中只能对dev数据进行验证的问题。

:param ~fastNLP.DataSet,Dict[~fastNLP.DataSet] data: 传入DataSet对象,会使用多个Trainer中的metric对数据进行验证。如果需要传入多个
DataSet请通过dict的方式传入。
:param ~fastNLP.Tester,Dict[~fastNLP.DataSet] tester: Tester对象,将在on_valid_end时调用。
""" """


def __init__(self, data=None, tester=None): def __init__(self, data=None, tester=None):
"""
:param ~fastNLP.DataSet,Dict[~fastNLP.DataSet] data: 传入DataSet对象,会使用多个Trainer中的metric对数据进行验证。如果需要传入多个
DataSet请通过dict的方式传入。
:param ~fastNLP.Tester,Dict[~fastNLP.DataSet] tester: Tester对象,将在on_valid_end时调用。
"""
super().__init__() super().__init__()
self.datasets = {} self.datasets = {}
self.testers = {} self.testers = {}
@@ -664,12 +671,12 @@ class EvaluateCallback(Callback):
class LRScheduler(Callback): class LRScheduler(Callback):
""" """
对PyTorch LR Scheduler的包装以使得其可以被Trainer所使用 对PyTorch LR Scheduler的包装以使得其可以被Trainer所使用

:param torch.optim.lr_scheduler._LRScheduler lr_scheduler: PyTorch的lr_scheduler
""" """
def __init__(self, lr_scheduler): def __init__(self, lr_scheduler):
"""
:param torch.optim.lr_scheduler._LRScheduler lr_scheduler: PyTorch的lr_scheduler
"""
super(LRScheduler, self).__init__() super(LRScheduler, self).__init__()
import torch.optim import torch.optim
if isinstance(lr_scheduler, torch.optim.lr_scheduler._LRScheduler): if isinstance(lr_scheduler, torch.optim.lr_scheduler._LRScheduler):
@@ -683,12 +690,13 @@ class LRScheduler(Callback):


class ControlC(Callback): class ControlC(Callback):
""" """

:param bool quit_all: 若为True,则检测到control+C 直接退出程序;否则只退出Trainer
检测到 control+C 时的反馈
""" """
def __init__(self, quit_all): def __init__(self, quit_all):
"""
:param bool quit_all: 若为True,则检测到control+C 直接退出程序;否则只退出Trainer
"""
super(ControlC, self).__init__() super(ControlC, self).__init__()
if type(quit_all) != bool: if type(quit_all) != bool:
raise ValueError("In KeyBoardInterrupt, quit_all arguemnt must be a bool.") raise ValueError("In KeyBoardInterrupt, quit_all arguemnt must be a bool.")
@@ -720,13 +728,14 @@ class SmoothValue(object):
class LRFinder(Callback): class LRFinder(Callback):
""" """
用第一个 epoch 找最佳的学习率,从第二个epoch开始应用它 用第一个 epoch 找最佳的学习率,从第二个epoch开始应用它

:param float start_lr: 学习率下界
:param float end_lr: 学习率上界
""" """
def __init__(self, start_lr=1e-6, end_lr=10): def __init__(self, start_lr=1e-6, end_lr=10):
"""
:param float start_lr: 学习率下界
:param float end_lr: 学习率上界
"""
super(LRFinder, self).__init__() super(LRFinder, self).__init__()
self.start_lr, self.end_lr = start_lr, end_lr self.start_lr, self.end_lr = start_lr, end_lr
@@ -864,13 +873,15 @@ class TensorboardCallback(Callback):
class WarmupCallback(Callback): class WarmupCallback(Callback):
""" """
按一定的周期调节Learning rate的大小。 按一定的周期调节Learning rate的大小。

:param int,float warmup: 如果warmup为int,则在该step之前,learning rate根据schedule的策略变化; 如果warmup为float,
如0.1, 则前10%的step是按照schedule策略调整learning rate。
:param str schedule: 以哪种方式调整。linear: 前warmup的step上升到指定的learning rate(从Trainer中的optimizer处获取的), 后
warmup的step下降到0; constant前warmup的step上升到指定learning rate,后面的step保持learning rate.
""" """
def __init__(self, warmup=0.1, schedule='constant'): def __init__(self, warmup=0.1, schedule='constant'):
"""
:param int,float warmup: 如果warmup为int,则在该step之前,learning rate根据schedule的策略变化; 如果warmup为float,
如0.1, 则前10%的step是按照schedule策略调整learning rate。
:param str schedule: 以哪种方式调整。linear: 前warmup的step上升到指定的learning rate(从Trainer中的optimizer处获取的), 后
warmup的step下降到0; constant前warmup的step上升到指定learning rate,后面的step保持learning rate.
"""
super().__init__() super().__init__()
self.warmup = max(warmup, 0.) self.warmup = max(warmup, 0.)


@@ -920,13 +931,15 @@ class SaveModelCallback(Callback):
-epoch:1_step:40_{metric_key}:{evaluate_performance}.pt -epoch:1_step:40_{metric_key}:{evaluate_performance}.pt
-2019-07-03-15-10-00 -2019-07-03-15-10-00
-epoch:0_step:20_{metric_key}:{evaluate_performance}.pt # metric是给定的metric_key, evaluate_perfomance是性能 -epoch:0_step:20_{metric_key}:{evaluate_performance}.pt # metric是给定的metric_key, evaluate_perfomance是性能
:param str save_dir: 将模型存放在哪个目录下,会在该目录下创建以时间戳命名的目录,并存放模型
:param int top: 保存dev表现top多少模型。-1为保存所有模型。
:param bool only_param: 是否只保存模型d饿权重。
:param save_on_exception: 发生exception时,是否保存一份发生exception的模型。模型名称为epoch:x_step:x_Exception:{exception_name}.
""" """
def __init__(self, save_dir, top=3, only_param=False, save_on_exception=False): def __init__(self, save_dir, top=3, only_param=False, save_on_exception=False):
"""
:param str save_dir: 将模型存放在哪个目录下,会在该目录下创建以时间戳命名的目录,并存放模型
:param int top: 保存dev表现top多少模型。-1为保存所有模型。
:param bool only_param: 是否只保存模型d饿权重。
:param save_on_exception: 发生exception时,是否保存一份发生exception的模型。模型名称为epoch:x_step:x_Exception:{exception_name}.
"""
super().__init__() super().__init__()


if not os.path.isdir(save_dir): if not os.path.isdir(save_dir):
@@ -992,11 +1005,13 @@ class SaveModelCallback(Callback):
class CallbackException(BaseException): class CallbackException(BaseException):
""" """
当需要通过callback跳出训练的时候可以通过抛出CallbackException并在on_exception中捕获这个值。 当需要通过callback跳出训练的时候可以通过抛出CallbackException并在on_exception中捕获这个值。

:param str msg: Exception的信息。
""" """
def __init__(self, msg): def __init__(self, msg):
"""
:param str msg: Exception的信息。
"""
super(CallbackException, self).__init__(msg) super(CallbackException, self).__init__(msg)






+ 11
- 10
fastNLP/core/dataset.py View File

@@ -288,30 +288,31 @@ __all__ = [
] ]


import _pickle as pickle import _pickle as pickle
import warnings
from copy import deepcopy


import numpy as np import numpy as np
from copy import deepcopy


from ._logger import logger
from .const import Const
from .field import AppendToTargetOrInputException
from .field import AutoPadder from .field import AutoPadder
from .field import FieldArray from .field import FieldArray
from .field import SetInputOrTargetException
from .instance import Instance from .instance import Instance
from .utils import _get_func_signature from .utils import _get_func_signature
from .field import AppendToTargetOrInputException
from .field import SetInputOrTargetException
from .const import Const
from ._logger import logger



class DataSet(object): class DataSet(object):
""" """
fastNLP的数据容器,详细的使用方法见文档 :doc:`fastNLP.core.dataset` fastNLP的数据容器,详细的使用方法见文档 :doc:`fastNLP.core.dataset`
:param data: 如果为dict类型,则每个key的value应该为等长的list; 如果为list,
每个元素应该为具有相同field的 :class:`~fastNLP.Instance` 。

""" """
def __init__(self, data=None): def __init__(self, data=None):
"""
:param data: 如果为dict类型,则每个key的value应该为等长的list; 如果为list,
每个元素应该为具有相同field的 :class:`~fastNLP.Instance` 。
"""
self.field_arrays = {} self.field_arrays = {}
if data is not None: if data is not None:
if isinstance(data, dict): if isinstance(data, dict):


+ 6
- 6
fastNLP/core/field.py View File

@@ -468,18 +468,18 @@ class Padder:
用于对batch进行padding操作。传入的element是inplace的,即直接修改element可能导致数据变化,建议inplace修改之前deepcopy一份。 用于对batch进行padding操作。传入的element是inplace的,即直接修改element可能导致数据变化,建议inplace修改之前deepcopy一份。


.. py:function:: __call__(self, contents, field_name, field_ele_dtype): .. py:function:: __call__(self, contents, field_name, field_ele_dtype):
"""
def __init__(self, pad_val=0, **kwargs):
"""
传入的是List内容。假设有以下的DataSet。

:param List[Any] contents: 传入的element是inplace的,即直接修改element可能导致数据变化,建议inplace修改之前 :param List[Any] contents: 传入的element是inplace的,即直接修改element可能导致数据变化,建议inplace修改之前
deepcopy一份。 deepcopy一份。
:param str, field_name: field的名称。 :param str, field_name: field的名称。
:param np.int64,np.float64,np.str,None, field_ele_dtype: 该field的内层元素的类型。如果该field的ignore_type为True,该这个值为None。 :param np.int64,np.float64,np.str,None, field_ele_dtype: 该field的内层元素的类型。如果该field的ignore_type为True,该这个值为None。
:return: np.array([padded_element]) :return: np.array([padded_element])

"""
def __init__(self, pad_val=0, **kwargs):
"""
self.pad_val = pad_val self.pad_val = pad_val
def set_pad_val(self, pad_val): def set_pad_val(self, pad_val):


+ 2
- 1
fastNLP/core/instance.py View File

@@ -37,7 +37,8 @@ class Instance(object):
def items(self): def items(self):
""" """
返回一个迭代器,迭代器返回两个内容,第一个内容是field_name, 第二个内容是field_value 返回一个迭代器,迭代器返回两个内容,第一个内容是field_name, 第二个内容是field_value
:return:
:return: 一个迭代器
""" """
return self.fields.items() return self.fields.items()


+ 13
- 10
fastNLP/core/losses.py View File

@@ -20,7 +20,6 @@ from collections import defaultdict
import torch import torch
import torch.nn.functional as F import torch.nn.functional as F


from ..core.const import Const
from .utils import _CheckError from .utils import _CheckError
from .utils import _CheckRes from .utils import _CheckRes
from .utils import _build_args from .utils import _build_args
@@ -28,7 +27,7 @@ from .utils import _check_arg_dict_list
from .utils import _check_function_or_method from .utils import _check_function_or_method
from .utils import _get_func_signature from .utils import _get_func_signature
from .utils import seq_len_to_mask from .utils import seq_len_to_mask
import warnings
from ..core.const import Const




class LossBase(object): class LossBase(object):
@@ -284,15 +283,17 @@ class BCELoss(LossBase):
class NLLLoss(LossBase): class NLLLoss(LossBase):
""" """
负对数似然损失函数 负对数似然损失函数
:param pred: 参数映射表中 `pred` 的映射关系,None表示映射关系为 `pred` -> `pred`
:param target: 参数映射表中 `target` 的映射关系,None表示映射关系为 `target` -> `target`
:param ignore_idx: ignore的index,在计算loss时将忽略target中标号为ignore_idx的内容, 可以通过该值代替
传入seq_len.
:param str reduction: 支持 `mean` ,`sum` 和 `none` .
""" """
def __init__(self, pred=None, target=None, ignore_idx=-100, reduction='mean'): def __init__(self, pred=None, target=None, ignore_idx=-100, reduction='mean'):
"""
:param pred: 参数映射表中 `pred` 的映射关系,None表示映射关系为 `pred` -> `pred`
:param target: 参数映射表中 `target` 的映射关系,None表示映射关系为 `target` -> `target`
:param ignore_idx: ignore的index,在计算loss时将忽略target中标号为ignore_idx的内容, 可以通过该值代替
传入seq_len.
:param str reduction: 支持 `mean` ,`sum` 和 `none` .
"""
super(NLLLoss, self).__init__() super(NLLLoss, self).__init__()
self._init_param_map(pred=pred, target=target) self._init_param_map(pred=pred, target=target)
assert reduction in ('mean', 'sum', 'none') assert reduction in ('mean', 'sum', 'none')
@@ -306,11 +307,13 @@ class NLLLoss(LossBase):
class LossInForward(LossBase): class LossInForward(LossBase):
""" """
从forward()函数返回结果中获取loss 从forward()函数返回结果中获取loss
:param str loss_key: 在forward函数中loss的键名,默认为loss
""" """
def __init__(self, loss_key=Const.LOSS): def __init__(self, loss_key=Const.LOSS):
"""
:param str loss_key: 在forward函数中loss的键名,默认为loss
"""
super().__init__() super().__init__()
if not isinstance(loss_key, str): if not isinstance(loss_key, str):
raise TypeError(f"Only str allowed for loss_key, got {type(loss_key)}.") raise TypeError(f"Only str allowed for loss_key, got {type(loss_key)}.")


+ 34
- 32
fastNLP/core/metrics.py View File

@@ -10,7 +10,10 @@ __all__ = [
] ]


import inspect import inspect
import warnings
from abc import abstractmethod
from collections import defaultdict from collections import defaultdict
from typing import Union


import numpy as np import numpy as np
import torch import torch
@@ -22,9 +25,7 @@ from .utils import _check_arg_dict_list
from .utils import _get_func_signature from .utils import _get_func_signature
from .utils import seq_len_to_mask from .utils import seq_len_to_mask
from .vocabulary import Vocabulary from .vocabulary import Vocabulary
from abc import abstractmethod
import warnings
from typing import Union



class MetricBase(object): class MetricBase(object):
""" """
@@ -295,13 +296,15 @@ class MetricBase(object):
class AccuracyMetric(MetricBase): class AccuracyMetric(MetricBase):
""" """
准确率Metric(其它的Metric参见 :doc:`fastNLP.core.metrics` ) 准确率Metric(其它的Metric参见 :doc:`fastNLP.core.metrics` )
:param pred: 参数映射表中 `pred` 的映射关系,None表示映射关系为 `pred` -> `pred`
:param target: 参数映射表中 `target` 的映射关系,None表示映射关系为 `target` -> `target`
:param seq_len: 参数映射表中 `seq_len` 的映射关系,None表示映射关系为 `seq_len` -> `seq_len`
""" """
def __init__(self, pred=None, target=None, seq_len=None): def __init__(self, pred=None, target=None, seq_len=None):
"""
:param pred: 参数映射表中 `pred` 的映射关系,None表示映射关系为 `pred` -> `pred`
:param target: 参数映射表中 `target` 的映射关系,None表示映射关系为 `target` -> `target`
:param seq_len: 参数映射表中 `seq_len` 的映射关系,None表示映射关系为 `seq_len` -> `seq_len`
"""
super().__init__() super().__init__()
@@ -584,25 +587,23 @@ class SpanFPreRecMetric(MetricBase):
'rec-label':xxx, 'rec-label':xxx,
... ...
} }

:param tag_vocab: 标签的 :class:`~fastNLP.Vocabulary` 。支持的标签为"B"(没有label);或"B-xxx"(xxx为某种label,比如POS中的NN),
在解码时,会将相同xxx的认为是同一个label,比如['B-NN', 'E-NN']会被合并为一个'NN'.
:param str pred: 用该key在evaluate()时从传入dict中取出prediction数据。 为None,则使用 `pred` 取数据
:param str target: 用该key在evaluate()时从传入dict中取出target数据。 为None,则使用 `target` 取数据
:param str seq_len: 用该key在evaluate()时从传入dict中取出sequence length数据。为None,则使用 `seq_len` 取数据。
:param str encoding_type: 目前支持bio, bmes, bmeso, bioes。默认为None,通过tag_vocab自动判断.
:param list ignore_labels: str 组成的list. 这个list中的class不会被用于计算。例如在POS tagging时传入['NN'],则不会计算'NN'这
个label
:param bool only_gross: 是否只计算总的f1, precision, recall的值;如果为False,不仅返回总的f1, pre, rec, 还会返回每个
label的f1, pre, rec
:param str f_type: `micro` 或 `macro` . `micro` :通过先计算总体的TP,FN和FP的数量,再计算f, precision, recall; `macro` :
分布计算每个类别的f, precision, recall,然后做平均(各类别f的权重相同)
:param float beta: f_beta分数, :math:`f_{beta} = \frac{(1 + {beta}^{2})*(pre*rec)}{({beta}^{2}*pre + rec)}` .
常用为beta=0.5, 1, 2. 若为0.5则精确率的权重高于召回率;若为1,则两者平等;若为2,则召回率权重高于精确率。
""" """
def __init__(self, tag_vocab, pred=None, target=None, seq_len=None, encoding_type=None, ignore_labels=None, def __init__(self, tag_vocab, pred=None, target=None, seq_len=None, encoding_type=None, ignore_labels=None,
only_gross=True, f_type='micro', beta=1): only_gross=True, f_type='micro', beta=1):
r"""
:param tag_vocab: 标签的 :class:`~fastNLP.Vocabulary` 。支持的标签为"B"(没有label);或"B-xxx"(xxx为某种label,比如POS中的NN),
在解码时,会将相同xxx的认为是同一个label,比如['B-NN', 'E-NN']会被合并为一个'NN'.
:param str pred: 用该key在evaluate()时从传入dict中取出prediction数据。 为None,则使用 `pred` 取数据
:param str target: 用该key在evaluate()时从传入dict中取出target数据。 为None,则使用 `target` 取数据
:param str seq_len: 用该key在evaluate()时从传入dict中取出sequence length数据。为None,则使用 `seq_len` 取数据。
:param str encoding_type: 目前支持bio, bmes, bmeso, bioes。默认为None,通过tag_vocab自动判断.
:param list ignore_labels: str 组成的list. 这个list中的class不会被用于计算。例如在POS tagging时传入['NN'],则不会计算'NN'个label
:param bool only_gross: 是否只计算总的f1, precision, recall的值;如果为False,不仅返回总的f1, pre, rec, 还会返回每个label的f1, pre, rec
:param str f_type: `micro` 或 `macro` . `micro` :通过先计算总体的TP,FN和FP的数量,再计算f, precision, recall; `macro` : 分布计算每个类别的f, precision, recall,然后做平均(各类别f的权重相同)
:param float beta: f_beta分数, :math:`f_{beta} = \frac{(1 + {beta}^{2})*(pre*rec)}{({beta}^{2}*pre + rec)}` . 常用为 `beta=0.5, 1, 2` 若为0.5则精确率的权重高于召回率;若为1,则两者平等;若为2,则召回率权重高于精确率。
"""


if not isinstance(tag_vocab, Vocabulary): if not isinstance(tag_vocab, Vocabulary):
raise TypeError("tag_vocab can only be fastNLP.Vocabulary, not {}.".format(type(tag_vocab))) raise TypeError("tag_vocab can only be fastNLP.Vocabulary, not {}.".format(type(tag_vocab)))
@@ -829,20 +830,21 @@ class ExtractiveQAMetric(MetricBase):
r""" r"""
抽取式QA(如SQuAD)的metric. 抽取式QA(如SQuAD)的metric.
:param pred1: 参数映射表中 `pred1` 的映射关系,None表示映射关系为 `pred1` -> `pred1`
:param pred2: 参数映射表中 `pred2` 的映射关系,None表示映射关系为 `pred2` -> `pred2`
:param target1: 参数映射表中 `target1` 的映射关系,None表示映射关系为 `target1` -> `target1`
:param target2: 参数映射表中 `target2` 的映射关系,None表示映射关系为 `target2` -> `target2`
:param float beta: f_beta分数, :math:`f_{beta} = \frac{(1 + {beta}^{2})*(pre*rec)}{({beta}^{2}*pre + rec)}` .
常用为beta=0.5, 1, 2. 若为0.5则精确率的权重高于召回率;若为1,则两者平等;若为2,则召回率权重高于精确率。
:param bool right_open: right_open为true表示start跟end指针指向一个左闭右开区间,为false表示指向一个左闭右闭区间。
:param bool print_predict_stat: True则输出预测答案是否为空与正确答案是否为空的统计信息, False则不输出
""" """
def __init__(self, pred1=None, pred2=None, target1=None, target2=None, def __init__(self, pred1=None, pred2=None, target1=None, target2=None,
beta=1, right_open=True, print_predict_stat=False): beta=1, right_open=True, print_predict_stat=False):
r"""
:param pred1: 参数映射表中 `pred1` 的映射关系,None表示映射关系为 `pred1` -> `pred1`
:param pred2: 参数映射表中 `pred2` 的映射关系,None表示映射关系为 `pred2` -> `pred2`
:param target1: 参数映射表中 `target1` 的映射关系,None表示映射关系为 `target1` -> `target1`
:param target2: 参数映射表中 `target2` 的映射关系,None表示映射关系为 `target2` -> `target2`
:param float beta: f_beta分数, :math:`f_{beta} = \frac{(1 + {beta}^{2})*(pre*rec)}{({beta}^{2}*pre + rec)}` .
常用为beta=0.5, 1, 2. 若为0.5则精确率的权重高于召回率;若为1,则两者平等;若为2,则召回率权重高于精确率。
:param bool right_open: right_open为true表示start跟end指针指向一个左闭右开区间,为false表示指向一个左闭右闭区间。
:param bool print_predict_stat: True则输出预测答案是否为空与正确答案是否为空的统计信息, False则不输出
"""
super(ExtractiveQAMetric, self).__init__() super(ExtractiveQAMetric, self).__init__()
self._init_param_map(pred1=pred1, pred2=pred2, target1=target1, target2=target2) self._init_param_map(pred1=pred1, pred2=pred2, target1=target1, target2=target2)


+ 34
- 22
fastNLP/core/optimizer.py View File

@@ -9,20 +9,23 @@ __all__ = [
"AdamW" "AdamW"
] ]


import torch
import math import math

import torch import torch
from torch.optim.optimizer import Optimizer as TorchOptimizer from torch.optim.optimizer import Optimizer as TorchOptimizer




class Optimizer(object): class Optimizer(object):
""" """

:param model_params: a generator. E.g. ``model.parameters()`` for PyTorch models.
:param kwargs: additional parameters.
Optimizer
""" """
def __init__(self, model_params, **kwargs): def __init__(self, model_params, **kwargs):
"""
:param model_params: a generator. E.g. ``model.parameters()`` for PyTorch models.
:param kwargs: additional parameters.
"""
if model_params is not None and not hasattr(model_params, "__next__"): if model_params is not None and not hasattr(model_params, "__next__"):
raise RuntimeError("model parameters should be a generator, rather than {}.".format(type(model_params))) raise RuntimeError("model parameters should be a generator, rather than {}.".format(type(model_params)))
self.model_params = model_params self.model_params = model_params
@@ -59,13 +62,15 @@ class NullOptimizer(Optimizer):


class SGD(Optimizer): class SGD(Optimizer):
""" """

:param float lr: learning rate. Default: 0.01
:param float momentum: momentum. Default: 0
:param model_params: a generator. E.g. ``model.parameters()`` for PyTorch models.
SGD
""" """
def __init__(self, lr=0.001, momentum=0, model_params=None): def __init__(self, lr=0.001, momentum=0, model_params=None):
"""
:param float lr: learning rate. Default: 0.01
:param float momentum: momentum. Default: 0
:param model_params: a generator. E.g. ``model.parameters()`` for PyTorch models.
"""
if not isinstance(lr, float): if not isinstance(lr, float):
raise TypeError("learning rate has to be float.") raise TypeError("learning rate has to be float.")
super(SGD, self).__init__(model_params, lr=lr, momentum=momentum) super(SGD, self).__init__(model_params, lr=lr, momentum=momentum)
@@ -81,12 +86,17 @@ class SGD(Optimizer):
class Adam(Optimizer): class Adam(Optimizer):
""" """


:param float lr: learning rate
:param float weight_decay:
:param model_params: a generator. E.g. ``model.parameters()`` for PyTorch models.
""" """
def __init__(self, lr=0.001, weight_decay=0, betas=(0.9, 0.999), eps=1e-8, amsgrad=False, model_params=None): def __init__(self, lr=0.001, weight_decay=0, betas=(0.9, 0.999), eps=1e-8, amsgrad=False, model_params=None):
"""
:param float lr: learning rate
:param float weight_decay:
:param eps:
:param amsgrad:
:param model_params: a generator. E.g. ``model.parameters()`` for PyTorch models.
"""
if not isinstance(lr, float): if not isinstance(lr, float):
raise TypeError("learning rate has to be float.") raise TypeError("learning rate has to be float.")
super(Adam, self).__init__(model_params, lr=lr, betas=betas, eps=eps, amsgrad=amsgrad, super(Adam, self).__init__(model_params, lr=lr, betas=betas, eps=eps, amsgrad=amsgrad,
@@ -110,17 +120,6 @@ class AdamW(TorchOptimizer):
The original Adam algorithm was proposed in `Adam: A Method for Stochastic Optimization`_. The original Adam algorithm was proposed in `Adam: A Method for Stochastic Optimization`_.
The AdamW variant was proposed in `Decoupled Weight Decay Regularization`_. The AdamW variant was proposed in `Decoupled Weight Decay Regularization`_.


:param params (iterable): iterable of parameters to optimize or dicts defining
parameter groups
:param lr (float, optional): learning rate (default: 1e-3)
:param betas (Tuple[float, float], optional): coefficients used for computing
running averages of gradient and its square (default: (0.9, 0.99))
:param eps (float, optional): term added to the denominator to improve
numerical stability (default: 1e-8)
:param weight_decay (float, optional): weight decay coefficient (default: 1e-2)
algorithm from the paper `On the Convergence of Adam and Beyond`_
(default: False)

.. _Adam\: A Method for Stochastic Optimization: .. _Adam\: A Method for Stochastic Optimization:
https://arxiv.org/abs/1412.6980 https://arxiv.org/abs/1412.6980
.. _Decoupled Weight Decay Regularization: .. _Decoupled Weight Decay Regularization:
@@ -131,6 +130,19 @@ class AdamW(TorchOptimizer):


def __init__(self, params, lr=1e-3, betas=(0.9, 0.999), eps=1e-8, def __init__(self, params, lr=1e-3, betas=(0.9, 0.999), eps=1e-8,
weight_decay=1e-2, amsgrad=False): weight_decay=1e-2, amsgrad=False):
"""
:param params (iterable): iterable of parameters to optimize or dicts defining
parameter groups
:param lr (float, optional): learning rate (default: 1e-3)
:param betas (Tuple[float, float], optional): coefficients used for computing
running averages of gradient and its square (default: (0.9, 0.99))
:param eps (float, optional): term added to the denominator to improve
numerical stability (default: 1e-8)
:param weight_decay (float, optional): weight decay coefficient (default: 1e-2)
algorithm from the paper `On the Convergence of Adam and Beyond`_
(default: False)
"""
if not 0.0 <= lr: if not 0.0 <= lr:
raise ValueError("Invalid learning rate: {}".format(lr)) raise ValueError("Invalid learning rate: {}".format(lr))
if not 0.0 <= eps: if not 0.0 <= eps:


+ 4
- 2
fastNLP/core/predictor.py View File

@@ -20,11 +20,13 @@ class Predictor(object):


与测试器(Tester)不同的是,predictor不关心模型性能的评价指标,只做inference。 与测试器(Tester)不同的是,predictor不关心模型性能的评价指标,只做inference。
这是一个fastNLP调用的高级模型包装器。它与Trainer、Tester不共享任何操作。 这是一个fastNLP调用的高级模型包装器。它与Trainer、Tester不共享任何操作。

:param torch.nn.Module network: 用来完成预测任务的模型
""" """
def __init__(self, network): def __init__(self, network):
"""
:param torch.nn.Module network: 用来完成预测任务的模型
"""
if not isinstance(network, torch.nn.Module): if not isinstance(network, torch.nn.Module):
raise ValueError( raise ValueError(
"Only fastNLP.models.BaseModel or torch.nn,Module is allowed, not {}".format(type(network))) "Only fastNLP.models.BaseModel or torch.nn,Module is allowed, not {}".format(type(network)))


+ 7
- 5
fastNLP/core/sampler.py View File

@@ -51,14 +51,16 @@ class RandomSampler(Sampler):
class BucketSampler(Sampler): class BucketSampler(Sampler):
""" """
带Bucket的 `Random Sampler`. 可以随机地取出长度相似的元素 带Bucket的 `Random Sampler`. 可以随机地取出长度相似的元素

:param int num_buckets: bucket的数量
:param int batch_size: batch的大小. 默认为None,Trainer在调用BucketSampler时,会将该值正确设置,如果是非Trainer场景使用,需
要显示传递该值
:param str seq_len_field_name: 对应序列长度的 `field` 的名字
""" """
def __init__(self, num_buckets=10, batch_size=None, seq_len_field_name='seq_len'): def __init__(self, num_buckets=10, batch_size=None, seq_len_field_name='seq_len'):
"""
:param int num_buckets: bucket的数量
:param int batch_size: batch的大小. 默认为None,Trainer在调用BucketSampler时,会将该值正确设置,如果是非Trainer场景使用,需
要显示传递该值
:param str seq_len_field_name: 对应序列长度的 `field` 的名字
"""
self.num_buckets = num_buckets self.num_buckets = num_buckets
self.batch_size = batch_size self.batch_size = batch_size
self.seq_len_field_name = seq_len_field_name self.seq_len_field_name = seq_len_field_name


+ 25
- 24
fastNLP/core/tester.py View File

@@ -66,30 +66,32 @@ __all__ = [
class Tester(object): class Tester(object):
""" """
Tester是在提供数据,模型以及metric的情况下进行性能测试的类。需要传入模型,数据以及metric进行验证。 Tester是在提供数据,模型以及metric的情况下进行性能测试的类。需要传入模型,数据以及metric进行验证。

:param ~fastNLP.DataSet data: 需要测试的数据集
:param torch.nn.module model: 使用的模型
:param ~fastNLP.core.metrics.MetricBase,List[~fastNLP.core.metrics.MetricBase] metrics: 测试时使用的metrics
:param int batch_size: evaluation时使用的batch_size有多大。
:param str,int,torch.device,list(int) device: 将模型load到哪个设备。默认为None,即Trainer不对模型
的计算位置进行管理。支持以下的输入:

1. str: ['cpu', 'cuda', 'cuda:0', 'cuda:1', ...] 依次为'cpu'中, 可见的第一个GPU中,可见的第一个GPU中,可见的第二个GPU中;

2. torch.device:将模型装载到torch.device上。

3. int: 将使用device_id为该值的gpu进行训练

4. list(int):如果多于1个device,将使用torch.nn.DataParallel包裹model, 并使用传入的device。

5. None. 为None则不对模型进行任何处理,如果传入的model为torch.nn.DataParallel该值必须为None。

如果模型是通过predict()进行预测的话,那么将不能使用多卡(DataParallel)进行验证,只会使用第一张卡上的模型。
:param int verbose: 如果为0不输出任何信息; 如果为1,打印出验证结果。
:param bool use_tqdm: 是否使用tqdm来显示测试进度; 如果为False,则不会显示任何内容。
""" """
def __init__(self, data, model, metrics, batch_size=16, num_workers=0, device=None, verbose=1, use_tqdm=True): def __init__(self, data, model, metrics, batch_size=16, num_workers=0, device=None, verbose=1, use_tqdm=True):
"""
:param ~fastNLP.DataSet data: 需要测试的数据集
:param torch.nn.module model: 使用的模型
:param ~fastNLP.core.metrics.MetricBase,List[~fastNLP.core.metrics.MetricBase] metrics: 测试时使用的metrics
:param int batch_size: evaluation时使用的batch_size有多大。
:param str,int,torch.device,list(int) device: 将模型load到哪个设备。默认为None,即Trainer不对模型
的计算位置进行管理。支持以下的输入:
1. str: ['cpu', 'cuda', 'cuda:0', 'cuda:1', ...] 依次为'cpu'中, 可见的第一个GPU中,可见的第一个GPU中,可见的第二个GPU中;
2. torch.device:将模型装载到torch.device上。
3. int: 将使用device_id为该值的gpu进行训练
4. list(int):如果多于1个device,将使用torch.nn.DataParallel包裹model, 并使用传入的device。
5. None. 为None则不对模型进行任何处理,如果传入的model为torch.nn.DataParallel该值必须为None。
如果模型是通过predict()进行预测的话,那么将不能使用多卡(DataParallel)进行验证,只会使用第一张卡上的模型。
:param int verbose: 如果为0不输出任何信息; 如果为1,打印出验证结果。
:param bool use_tqdm: 是否使用tqdm来显示测试进度; 如果为False,则不会显示任何内容。
"""
super(Tester, self).__init__() super(Tester, self).__init__()


if not isinstance(model, nn.Module): if not isinstance(model, nn.Module):
@@ -137,10 +139,9 @@ class Tester(object):
self._predict_func_wrapper = self._model.forward self._predict_func_wrapper = self._model.forward
def test(self): def test(self):
"""开始进行验证,并返回验证结果。
r"""开始进行验证,并返回验证结果。


:return Dict[Dict] : dict的二层嵌套结构,dict的第一层是metric的名称; 第二层是这个metric的指标。
一个AccuracyMetric的例子为{'AccuracyMetric': {'acc': 1.0}}。
:return Dict[Dict]: dict的二层嵌套结构,dict的第一层是metric的名称; 第二层是这个metric的指标。一个AccuracyMetric的例子为{'AccuracyMetric': {'acc': 1.0}}。
""" """
# turn on the testing mode; clean up the history # turn on the testing mode; clean up the history
self._model_device = _get_model_device(self._model) self._model_device = _get_model_device(self._model)


+ 50
- 48
fastNLP/core/trainer.py View File

@@ -365,54 +365,6 @@ class Trainer(object):
(5) 保存获得更好验证性能的模型等。 (5) 保存获得更好验证性能的模型等。
详细的介绍参见 :doc:`fastNLP.core.trainer` 详细的介绍参见 :doc:`fastNLP.core.trainer`
:param train_data: 训练集, :class:`~fastNLP.DataSet` 类型。
:param nn.modules model: 待训练的模型
:param optimizer: `torch.optim.Optimizer` 优化器。如果为None,则Trainer使用默认的Adam(model.parameters(), lr=4e-3)这个优化器
:param int batch_size: 训练和验证的时候的batch大小。
:param loss: 使用的 :class:`~fastNLP.core.losses.LossBase` 对象。当为None时,默认使用 :class:`~fastNLP.LossInForward`
:param sampler: Batch数据生成的顺序, :class:`~fastNLP.Sampler` 类型。如果为None,默认使用 :class:`~fastNLP.RandomSampler`
:param drop_last: 如果最后一个batch没有正好为batch_size这么多数据,就扔掉最后一个batch
:param num_workers: int, 有多少个线程来进行数据pad处理。
:param update_every: int, 多少步更新一次梯度。用于希望累计梯度的场景,比如需要128的batch_size, 但是直接设为128
会导致内存不足,通过设置batch_size=32, update_every=4达到目的。当optimizer为None时,该参数无效。
:param int n_epochs: 需要优化迭代多少次。
:param int print_every: 多少次反向传播更新tqdm显示的loss; 如果use_tqdm=False, 则多少次反向传播打印loss。
:param dev_data: 用于做验证的DataSet, :class:`~fastNLP.DataSet` 类型。
:param metrics: 验证的评估函数。可以只使用一个 :class:`Metric<fastNLP.core.metrics.MetricBase>` ,
也可以使用多个 :class:`Metric<fastNLP.core.metrics.MetricBase>` ,通过列表传入。
如验证时取得了更好的验证结果(如果有多个Metric,以列表中第一个Metric为准),且save_path不为None,
则保存当前模型。Metric种类详见 :doc:`metrics模块 <fastNLP.core.metrics>` 。仅在传入dev_data时有效。
:param str,None metric_key: :class:`Metric<fastNLP.core.metrics.MetricBase>` 有时会有多个指标,
比如 :class:`~fastNLP.core.metrics.SpanFPreRecMetric` 中包含了'f', 'pre', 'rec'。此时需
要指定以哪个指标为准。另外有些指标是越小效果越好,比如语言模型的困惑度,这种情况下,在key前面增加一个'-'来表
明验证时,值越小越好(比如: "-ppl")。仅在传入dev_data时有效。
:param int validate_every: 多少个step在验证集上验证一次; 如果为-1,则每个epoch结束验证一次。仅在传入dev_data时有效。
:param str,None save_path: 将模型保存路径,如果路径不存在,将自动创建文件夹。如果为None,则不保存模型。如果dev_data为None,则保存
最后一次迭代的模型。保存的时候不仅保存了参数,还保存了模型结构。即便使用DataParallel,这里也只保存模型。
:param bool use_tqdm: 是否使用tqdm来显示训练进度; 如果为False,则将loss打印在终端中。
:param str,int,torch.device,list(int) device: 将模型load到哪个设备。默认为None,即Trainer不对模型
的计算位置进行管理。支持以下的输入:

1. str: ['cpu', 'cuda', 'cuda:0', 'cuda:1', ...] 依次为'cpu'中, 可见的第一个GPU中, 可见的第一个GPU中,
可见的第二个GPU中;

2. torch.device:将模型装载到torch.device上。

3. int: 将使用device_id为该值的gpu进行训练

4. list(int):如果多于1个device,将使用torch.nn.DataParallel包裹model, 并使用传入的device。

5. None. 为None则不对模型进行任何处理,如果传入的model为torch.nn.DataParallel该值必须为None。

已知可能会出现的问题:Adagrad优化器可能无法正常使用这个参数,请手动管理模型位置。

:param list(callbacks) callbacks: 用于在train过程中起调节作用的回调函数。比如early stop,negative sampling等可以
通过callback机制实现。 可使用的callback参见 :doc:`callback模块 <fastNLP.core.callback>`
:param int check_code_level: 模型检查等级. -1: 不进行检查; 0: 仅出现错误时停止; 1: 如果有field没有被使用,
报告警告信息; 2: 有任何field没有被使用都报错. 检查的原理是通过使用很小的batch(默认2个sample)来运行代码,但是
这个过程理论上不会修改任何参数,只是会检查能否运行。但如果(1)模型中存在将batch_size写为某个固定值的情况;
(2)模型中存在累加前向计算次数的,可能会多计算1次。以上情况建议将check_code_level设置为-1。
""" """
def __init__(self, train_data, model, optimizer=None, loss=None, def __init__(self, train_data, model, optimizer=None, loss=None,
@@ -421,6 +373,56 @@ class Trainer(object):
dev_data=None, metrics=None, metric_key=None, dev_data=None, metrics=None, metric_key=None,
validate_every=-1, save_path=None, use_tqdm=True, device=None, validate_every=-1, save_path=None, use_tqdm=True, device=None,
callbacks=None, check_code_level=0, **kwargs): callbacks=None, check_code_level=0, **kwargs):
"""
:param train_data: 训练集, :class:`~fastNLP.DataSet` 类型。
:param nn.modules model: 待训练的模型
:param optimizer: `torch.optim.Optimizer` 优化器。如果为None,则Trainer使用默认的Adam(model.parameters(), lr=4e-3)这个优化器
:param int batch_size: 训练和验证的时候的batch大小。
:param loss: 使用的 :class:`~fastNLP.core.losses.LossBase` 对象。当为None时,默认使用 :class:`~fastNLP.LossInForward`
:param sampler: Batch数据生成的顺序, :class:`~fastNLP.Sampler` 类型。如果为None,默认使用 :class:`~fastNLP.RandomSampler`
:param drop_last: 如果最后一个batch没有正好为batch_size这么多数据,就扔掉最后一个batch
:param num_workers: int, 有多少个线程来进行数据pad处理。
:param update_every: int, 多少步更新一次梯度。用于希望累计梯度的场景,比如需要128的batch_size, 但是直接设为128
会导致内存不足,通过设置batch_size=32, update_every=4达到目的。当optimizer为None时,该参数无效。
:param int n_epochs: 需要优化迭代多少次。
:param int print_every: 多少次反向传播更新tqdm显示的loss; 如果use_tqdm=False, 则多少次反向传播打印loss。
:param dev_data: 用于做验证的DataSet, :class:`~fastNLP.DataSet` 类型。
:param metrics: 验证的评估函数。可以只使用一个 :class:`Metric<fastNLP.core.metrics.MetricBase>` ,
也可以使用多个 :class:`Metric<fastNLP.core.metrics.MetricBase>` ,通过列表传入。
如验证时取得了更好的验证结果(如果有多个Metric,以列表中第一个Metric为准),且save_path不为None,
则保存当前模型。Metric种类详见 :doc:`metrics模块 <fastNLP.core.metrics>` 。仅在传入dev_data时有效。
:param str,None metric_key: :class:`Metric<fastNLP.core.metrics.MetricBase>` 有时会有多个指标,
比如 :class:`~fastNLP.core.metrics.SpanFPreRecMetric` 中包含了'f', 'pre', 'rec'。此时需
要指定以哪个指标为准。另外有些指标是越小效果越好,比如语言模型的困惑度,这种情况下,在key前面增加一个'-'来表
明验证时,值越小越好(比如: "-ppl")。仅在传入dev_data时有效。
:param int validate_every: 多少个step在验证集上验证一次; 如果为-1,则每个epoch结束验证一次。仅在传入dev_data时有效。
:param str,None save_path: 将模型保存路径,如果路径不存在,将自动创建文件夹。如果为None,则不保存模型。如果dev_data为None,则保存
最后一次迭代的模型。保存的时候不仅保存了参数,还保存了模型结构。即便使用DataParallel,这里也只保存模型。
:param bool use_tqdm: 是否使用tqdm来显示训练进度; 如果为False,则将loss打印在终端中。
:param str,int,torch.device,list(int) device: 将模型load到哪个设备。默认为None,即Trainer不对模型
的计算位置进行管理。支持以下的输入:
1. str: ['cpu', 'cuda', 'cuda:0', 'cuda:1', ...] 依次为'cpu'中, 可见的第一个GPU中, 可见的第一个GPU中,
可见的第二个GPU中;
2. torch.device:将模型装载到torch.device上。
3. int: 将使用device_id为该值的gpu进行训练
4. list(int):如果多于1个device,将使用torch.nn.DataParallel包裹model, 并使用传入的device。
5. None. 为None则不对模型进行任何处理,如果传入的model为torch.nn.DataParallel该值必须为None。
已知可能会出现的问题:Adagrad优化器可能无法正常使用这个参数,请手动管理模型位置。
:param list(callbacks) callbacks: 用于在train过程中起调节作用的回调函数。比如early stop,negative sampling等可以
通过callback机制实现。 可使用的callback参见 :doc:`callback模块 <fastNLP.core.callback>`
:param int check_code_level: 模型检查等级. -1: 不进行检查; 0: 仅出现错误时停止; 1: 如果有field没有被使用,
报告警告信息; 2: 有任何field没有被使用都报错. 检查的原理是通过使用很小的batch(默认2个sample)来运行代码,但是
这个过程理论上不会修改任何参数,只是会检查能否运行。但如果(1)模型中存在将batch_size写为某个固定值的情况;
(2)模型中存在累加前向计算次数的,可能会多计算1次。以上情况建议将check_code_level设置为-1。
"""
super(Trainer, self).__init__() super(Trainer, self).__init__()
if not isinstance(model, nn.Module): if not isinstance(model, nn.Module):
raise TypeError(f"The type of model must be torch.nn.Module, got {type(model)}.") raise TypeError(f"The type of model must be torch.nn.Module, got {type(model)}.")


+ 15
- 13
fastNLP/core/vocabulary.py View File

@@ -73,21 +73,23 @@ class Vocabulary(object):
vocab.update(word_list) vocab.update(word_list)
vocab["word"] # str to int vocab["word"] # str to int
vocab.to_word(5) # int to str vocab.to_word(5) # int to str

:param int max_size: `Vocabulary` 的最大大小, 即能存储词的最大数量
若为 ``None`` , 则不限制大小. Default: ``None``
:param int min_freq: 能被记录下的词在文本中的最小出现频率, 应大于或等于 1.
若小于该频率, 词语将被视为 `unknown`. 若为 ``None`` , 所有文本中的词都被记录. Default: ``None``
:param str optional padding: padding的字符. 如果设置为 ``None`` ,
则vocabulary中不考虑padding, 也不计入词表大小,为 ``None`` 的情况多在为label建立Vocabulary的情况.
Default: '<pad>'
:param str optional unknown: unknown的字符,所有未被记录的词在转为 `int` 时将被视为unknown.
如果设置为 ``None`` ,则vocabulary中不考虑unknow, 也不计入词表大小.
为 ``None`` 的情况多在为label建立Vocabulary的情况.
Default: '<unk>'
""" """
def __init__(self, max_size=None, min_freq=None, padding='<pad>', unknown='<unk>'): def __init__(self, max_size=None, min_freq=None, padding='<pad>', unknown='<unk>'):
"""
:param int max_size: `Vocabulary` 的最大大小, 即能存储词的最大数量
若为 ``None`` , 则不限制大小. Default: ``None``
:param int min_freq: 能被记录下的词在文本中的最小出现频率, 应大于或等于 1.
若小于该频率, 词语将被视为 `unknown`. 若为 ``None`` , 所有文本中的词都被记录. Default: ``None``
:param str optional padding: padding的字符. 如果设置为 ``None`` ,
则vocabulary中不考虑padding, 也不计入词表大小,为 ``None`` 的情况多在为label建立Vocabulary的情况.
Default: '<pad>'
:param str optional unknown: unknown的字符,所有未被记录的词在转为 `int` 时将被视为unknown.
如果设置为 ``None`` ,则vocabulary中不考虑unknow, 也不计入词表大小.
为 ``None`` 的情况多在为label建立Vocabulary的情况.
Default: '<unk>'
"""
self.max_size = max_size self.max_size = max_size
self.min_freq = min_freq self.min_freq = min_freq
self.word_count = Counter() self.word_count = Counter()
@@ -402,7 +404,7 @@ class Vocabulary(object):
def to_index(self, w): def to_index(self, w):
""" """
将词转为数字. 若词不再词典中被记录, 将视为 unknown, 若 ``unknown=None`` , 将抛出``ValueError``::
将词转为数字. 若词不再词典中被记录, 将视为 unknown, 若 ``unknown=None`` , 将抛出 ``ValueError`` ::


index = vocab.to_index('abc') index = vocab.to_index('abc')
# equals to # equals to


Loading…
Cancel
Save