@@ -10,14 +10,50 @@ fastNLP 由 :mod:`~fastNLP.core` 、 :mod:`~fastNLP.io` 、:mod:`~fastNLP.module | |||||
fastNLP 中最常用的组件可以直接从 fastNLP 包中 import ,他们的文档如下: | fastNLP 中最常用的组件可以直接从 fastNLP 包中 import ,他们的文档如下: | ||||
""" | """ | ||||
__all__ = ["Instance", "FieldArray", "Batch", "Vocabulary", "DataSet", "Const", | |||||
"Trainer", "Tester", "Callback", | |||||
"Padder", "AutoPadder", "EngChar2DPadder", | |||||
"AccuracyMetric", "BMESF1PreRecMetric", "SpanFPreRecMetric", "SQuADMetric", | |||||
"Optimizer", "SGD", "Adam", | |||||
"Sampler", "SequentialSampler", "BucketSampler", "RandomSampler", | |||||
"LossFunc", "CrossEntropyLoss", "L1Loss", "BCELoss", "NLLLoss", "LossInForward", | |||||
"cache_results"] | |||||
__all__ = [ | |||||
"Instance", | |||||
"FieldArray", | |||||
"Batch", | |||||
"Vocabulary", | |||||
"DataSet", | |||||
"Const", | |||||
"Trainer", | |||||
"Tester", | |||||
"Callback", | |||||
"GradientClipCallback", | |||||
"EarlyStopCallback", | |||||
"TensorboardCallback", | |||||
"LRScheduler", | |||||
"ControlC", | |||||
"Padder", | |||||
"AutoPadder", | |||||
"EngChar2DPadder", | |||||
"AccuracyMetric", | |||||
"BMESF1PreRecMetric", | |||||
"SpanFPreRecMetric", | |||||
"SQuADMetric", | |||||
"Optimizer", | |||||
"SGD", | |||||
"Adam", | |||||
"Sampler", | |||||
"SequentialSampler", | |||||
"BucketSampler", | |||||
"RandomSampler", | |||||
"LossFunc", | |||||
"CrossEntropyLoss", | |||||
"L1Loss", "BCELoss", | |||||
"NLLLoss", | |||||
"LossInForward", | |||||
"cache_results" | |||||
] | |||||
from .core import * | from .core import * | ||||
from . import models | from . import models | ||||
from . import modules | from . import modules | ||||
@@ -10,10 +10,11 @@ core 模块里实现了 fastNLP 的核心框架,常用的组件都可以从 fa | |||||
对于常用的功能,你只需要在 :doc:`fastNLP` 中查看即可。如果想了解各个子模块的分工,您可以阅读以下文档: | 对于常用的功能,你只需要在 :doc:`fastNLP` 中查看即可。如果想了解各个子模块的分工,您可以阅读以下文档: | ||||
TODO 向导 | |||||
""" | """ | ||||
from .batch import Batch | from .batch import Batch | ||||
from .callback import Callback | |||||
from .callback import Callback, GradientClipCallback, EarlyStopCallback, TensorboardCallback, LRScheduler, ControlC | |||||
from .const import Const | from .const import Const | ||||
from .dataset import DataSet | from .dataset import DataSet | ||||
from .field import FieldArray, Padder, AutoPadder, EngChar2DPadder | from .field import FieldArray, Padder, AutoPadder, EngChar2DPadder | ||||
@@ -1,7 +1,62 @@ | |||||
""" | |||||
callback模块实现了 fastNLP 中的Callback类,用于增强 :class:`~fastNLP.Trainer` 类, | |||||
r""" | |||||
callback模块实现了 fastNLP 中的许多 callback 类,用于增强 :class:`~fastNLP.Trainer` 类, | |||||
我们将 :meth:`~fastNLP.Train.train` 这个函数内部分为以下的阶段,在对应阶段会触发相应的调用:: | |||||
callback.on_train_begin() # 开始进行训练 | |||||
for i in range(1, n_epochs+1): | |||||
callback.on_epoch_begin() # 开始新的epoch | |||||
for batch_x, batch_y in Batch: | |||||
callback.on_batch_begin(batch_x, batch_y, indices) # batch_x是设置为input的field,batch_y是设置为target的field | |||||
获取模型输出 | |||||
callback.on_loss_begin() | |||||
计算loss | |||||
callback.on_backward_begin() # 可以进行一些检查,比如loss是否为None | |||||
反向梯度回传 | |||||
callback.on_backward_end() # 进行梯度截断等 | |||||
进行参数更新 | |||||
callback.on_step_end() | |||||
callback.on_batch_end() | |||||
# 根据设置进行evaluation,比如这是本epoch最后一个batch或者达到一定step | |||||
if do evaluation: | |||||
callback.on_valid_begin() | |||||
进行dev data上的验证 | |||||
callback.on_valid_end() # 可以进行在其它数据集上进行验证 | |||||
callback.on_epoch_end() # epoch结束调用 | |||||
callback.on_train_end() # 训练结束 | |||||
callback.on_exception() # 这是一个特殊的步骤,在训练过程中遭遇exception会跳转到这里 | |||||
关于Trainer的详细文档,请参见 :doc:`trainer 模块<fastNLP.core.trainer>` | 关于Trainer的详细文档,请参见 :doc:`trainer 模块<fastNLP.core.trainer>` | ||||
如下面的例子所示,我们可以使用内置的 callback 类,或者继承 :class:`~fastNLP.core.callback.Callback` | |||||
定义自己的 callback 类:: | |||||
from fastNLP import Callback, EarlyStopCallback, Trainer, CrossEntropyLoss, AccuracyMetric | |||||
from fastNLP.models import CNNText | |||||
start_time = time.time() | |||||
class MyCallback(Callback): | |||||
def on_epoch_end(self): | |||||
print('{:d}ms\n\n'.format(round((time.time()-start_time)*1000))) | |||||
model = CNNText((len(vocab),50), num_classes=5, padding=2, dropout=0.1) | |||||
trainer = Trainer(model=model, train_data=train_data, dev_data=dev_data, loss=CrossEntropyLoss(), | |||||
metrics=AccuracyMetric(), callbacks=[MyCallback(),EarlyStopCallback(10)]) | |||||
trainer.train() | |||||
""" | """ | ||||
__all__ = [ | |||||
"Callback", | |||||
"GradientClipCallback", | |||||
"EarlyStopCallback", | |||||
"TensorboardCallback", | |||||
"LRScheduler", | |||||
"ControlC", | |||||
"CallbackException", | |||||
"EarlyStopError" | |||||
] | |||||
import os | import os | ||||
import torch | import torch | ||||
from ..io.model_io import ModelSaver, ModelLoader | from ..io.model_io import ModelSaver, ModelLoader | ||||
@@ -19,7 +74,7 @@ class Callback(object): | |||||
Callback是fastNLP中被设计用于增强 :class:`~fastNLP.Trainer` 的类。 | Callback是fastNLP中被设计用于增强 :class:`~fastNLP.Trainer` 的类。 | ||||
如果Callback被传递给了 Trainer , 则 Trainer 会在对应的阶段调用Callback的函数, | 如果Callback被传递给了 Trainer , 则 Trainer 会在对应的阶段调用Callback的函数, | ||||
具体调用时机可以通过 :doc:`trainer 模块<fastNLP.core.trainer>` 查看。 | 具体调用时机可以通过 :doc:`trainer 模块<fastNLP.core.trainer>` 查看。 | ||||
这是Callback的基类,所有的callback必须继承自这个类(参见 :doc:`callback 模块 <fastNLP.core.callback>` ) | |||||
这是Callback的基类,所有的callback必须继承自这个类 | |||||
""" | """ | ||||
@@ -236,7 +291,7 @@ class CallbackManager(Callback): | |||||
for env_name, env_val in env.items(): | for env_name, env_val in env.items(): | ||||
for callback in self.callbacks: | for callback in self.callbacks: | ||||
print(callback, env_name, env_val ) | |||||
print(callback, env_name, env_val) | |||||
setattr(callback, '_' + env_name, env_val) # Callback.trainer | setattr(callback, '_' + env_name, env_val) # Callback.trainer | ||||
@_transfer | @_transfer | ||||
@@ -294,12 +349,15 @@ class CallbackManager(Callback): | |||||
class GradientClipCallback(Callback): | class GradientClipCallback(Callback): | ||||
""" | """ | ||||
别名::class:`fastNLP.GradientClipCallback` :class:`fastNLP.core.callback.GradientClipCallback` | |||||
每次backward前,将parameter的gradient clip到某个范围。 | 每次backward前,将parameter的gradient clip到某个范围。 | ||||
:param None,torch.Tensor,List[torch.Tensor] parameters: 一般通过model.parameters()获得。如果为None则默认对Trainer | :param None,torch.Tensor,List[torch.Tensor] parameters: 一般通过model.parameters()获得。如果为None则默认对Trainer | ||||
的model中所有参数进行clip | 的model中所有参数进行clip | ||||
:param float clip_value: 将gradient 限制到[-clip_value, clip_value]。clip_value应该为正数 | :param float clip_value: 将gradient 限制到[-clip_value, clip_value]。clip_value应该为正数 | ||||
:param str clip_type: 支持'norm', 'value'两种:: | |||||
:param str clip_type: 支持'norm', 'value' | |||||
两种:: | |||||
1 'norm', 将gradient的norm rescale到[-clip_value, clip_value] | 1 'norm', 将gradient的norm rescale到[-clip_value, clip_value] | ||||
@@ -331,8 +389,11 @@ class GradientClipCallback(Callback): | |||||
class EarlyStopCallback(Callback): | class EarlyStopCallback(Callback): | ||||
""" | """ | ||||
别名::class:`fastNLP.EarlyStopCallback` :class:`fastNLP.core.callback.EarlyStopCallback` | |||||
多少个epoch没有变好就停止训练,相关类 :class:`EarlyStopError` | |||||
:param int patience: 多少个epoch没有变好就停止训练 | |||||
:param int patience: epoch的数量 | |||||
""" | """ | ||||
def __init__(self, patience): | def __init__(self, patience): | ||||
@@ -358,11 +419,10 @@ class EarlyStopCallback(Callback): | |||||
class LRScheduler(Callback): | class LRScheduler(Callback): | ||||
"""对PyTorch LR Scheduler的包装以使得其可以被Trainer所使用 | |||||
Example:: | |||||
""" | |||||
别名::class:`fastNLP.LRScheduler` :class:`fastNLP.core.callback.LRScheduler` | |||||
from fastNLP import LRScheduler | |||||
对PyTorch LR Scheduler的包装以使得其可以被Trainer所使用 | |||||
:param torch.optim.lr_scheduler._LRScheduler lr_scheduler: PyTorch的lr_scheduler | :param torch.optim.lr_scheduler._LRScheduler lr_scheduler: PyTorch的lr_scheduler | ||||
""" | """ | ||||
@@ -382,6 +442,7 @@ class LRScheduler(Callback): | |||||
class ControlC(Callback): | class ControlC(Callback): | ||||
""" | """ | ||||
别名::class:`fastNLP.ControlC` :class:`fastNLP.core.callback.ControlC` | |||||
:param bool quit_all: 若为True,则检测到control+C 直接退出程序;否则只退出Trainer | :param bool quit_all: 若为True,则检测到control+C 直接退出程序;否则只退出Trainer | ||||
""" | """ | ||||
@@ -418,6 +479,8 @@ class SmoothValue(object): | |||||
class LRFinder(Callback): | class LRFinder(Callback): | ||||
""" | """ | ||||
别名::class:`fastNLP.LRFinder` :class:`fastNLP.core.callback.LRFinder` | |||||
用第一个 epoch 找最佳的学习率,从第二个epoch开始应用它 | 用第一个 epoch 找最佳的学习率,从第二个epoch开始应用它 | ||||
:param float start_lr: 学习率下界 | :param float start_lr: 学习率下界 | ||||
@@ -442,7 +505,7 @@ class LRFinder(Callback): | |||||
def lr_gen(self): | def lr_gen(self): | ||||
scale = (self.end_lr - self.start_lr) / self.batch_per_epoch | scale = (self.end_lr - self.start_lr) / self.batch_per_epoch | ||||
return (self.start_lr + scale * (step + 1) for step in range(self.batch_per_epoch)) | return (self.start_lr + scale * (step + 1) for step in range(self.batch_per_epoch)) | ||||
@property | @property | ||||
def num_it(self): | def num_it(self): | ||||
return self.batch_per_epoch | return self.batch_per_epoch | ||||
@@ -487,10 +550,17 @@ class LRFinder(Callback): | |||||
class TensorboardCallback(Callback): | class TensorboardCallback(Callback): | ||||
""" | """ | ||||
别名::class:`fastNLP.TensorboardCallback` :class:`fastNLP.core.callback.TensorboardCallback` | |||||
接受以下一个或多个字符串作为参数: | 接受以下一个或多个字符串作为参数: | ||||
- "model" | - "model" | ||||
- "loss" | - "loss" | ||||
- "metric" | - "metric" | ||||
.. warning:: | |||||
fastNLP 已停止对此功能的维护,请等待 fastNLP 兼容 PyTorch1.1 的下一个版本。 | |||||
或者使用和 fastNLP 高度配合的 fitlog(参见 :doc:`/user/with_fitlog` )。 | |||||
""" | """ | ||||
def __init__(self, *options): | def __init__(self, *options): | ||||
@@ -798,7 +798,10 @@ class DataSet(object): | |||||
@classmethod | @classmethod | ||||
def read_csv(cls, csv_path, headers=None, sep=",", dropna=True): | def read_csv(cls, csv_path, headers=None, sep=",", dropna=True): | ||||
""" | """ | ||||
从csv_path路径下以csv的格式读取数据. | |||||
.. warning:: | |||||
此方法会在下个版本移除,请使用 :class:`fastNLP.io.CSVLoader` | |||||
从csv_path路径下以csv的格式读取数据。 | |||||
:param str csv_path: 从哪里读取csv文件 | :param str csv_path: 从哪里读取csv文件 | ||||
:param list[str] headers: 如果为None,则使用csv文件的第一行作为header; 如果传入list(str), 则元素的个数必须 | :param list[str] headers: 如果为None,则使用csv文件的第一行作为header; 如果传入list(str), 则元素的个数必须 | ||||
@@ -1,4 +1,4 @@ | |||||
""" | |||||
r""" | |||||
Trainer在fastNLP中用于组织单任务的训练过程,可以避免用户在不同训练任务中重复撰以下步骤的代码 | Trainer在fastNLP中用于组织单任务的训练过程,可以避免用户在不同训练任务中重复撰以下步骤的代码 | ||||
(1) epoch循环; | (1) epoch循环; | ||||
@@ -93,7 +93,10 @@ Trainer在fastNLP中用于组织单任务的训练过程,可以避免用户在 | |||||
尽管fastNLP使用了映射机制来使得loss的计算变得比较灵活,但有些情况下loss必须在模型中进行计算,比如使用了CRF的模型。 | 尽管fastNLP使用了映射机制来使得loss的计算变得比较灵活,但有些情况下loss必须在模型中进行计算,比如使用了CRF的模型。 | ||||
fastNLP中提供了 :class:`~fastNLP.LossInForward` 这个loss。 | fastNLP中提供了 :class:`~fastNLP.LossInForward` 这个loss。 | ||||
这个loss的原理是直接在forward()的返回结果中找到loss_key(默认寻找'loss')指定的那个tensor,并使用它作为loss。 | 这个loss的原理是直接在forward()的返回结果中找到loss_key(默认寻找'loss')指定的那个tensor,并使用它作为loss。 | ||||
如果Trainer初始化没有提供loss则默认使用 :class:`~fastNLP.LossInForward` 。TODO 补充一个例子 详细例子可以参照 | |||||
如果Trainer初始化没有提供loss则默认使用 :class:`~fastNLP.LossInForward` 。 | |||||
.. todo:: | |||||
补充一个例子 详细例子可以参照 | |||||
1.3 Metric | 1.3 Metric | ||||
:mod:`Metric<fastNLP.core.metrics>` 使用了与上述Loss一样的策略,即使用名称进行匹配。 | :mod:`Metric<fastNLP.core.metrics>` 使用了与上述Loss一样的策略,即使用名称进行匹配。 | ||||
@@ -102,7 +105,10 @@ Trainer在fastNLP中用于组织单任务的训练过程,可以避免用户在 | |||||
在进行验证时,可能用到的计算与forward()中不太一致,没有办法直接从forward()的结果中得到预测值,这时模型可以提供一个predict()方法, | 在进行验证时,可能用到的计算与forward()中不太一致,没有办法直接从forward()的结果中得到预测值,这时模型可以提供一个predict()方法, | ||||
如果提供的模型具有predict方法,则在模型验证时将调用predict()方法获取预测结果, | 如果提供的模型具有predict方法,则在模型验证时将调用predict()方法获取预测结果, | ||||
传入到predict()的参数也是从DataSet中被设置为input的field中选择出来的; | 传入到predict()的参数也是从DataSet中被设置为input的field中选择出来的; | ||||
与forward()一样,返回值需要为一个dict。 TODO 补充一个例子 具体例子可以参考 | |||||
与forward()一样,返回值需要为一个dict。 | |||||
.. todo:: | |||||
补充一个例子 具体例子可以参考 | |||||
2 Trainer的代码检查 | 2 Trainer的代码检查 | ||||
由于在fastNLP中采取了映射的机制,所以难免可能存在对应出错的情况。Trainer提供一种映射检查机制,可以通过check_code_level来进行控制 | 由于在fastNLP中采取了映射的机制,所以难免可能存在对应出错的情况。Trainer提供一种映射检查机制,可以通过check_code_level来进行控制 | ||||
@@ -267,37 +273,26 @@ Example2.3 | |||||
虽然Trainer本身已经集成了一些功能,但仍然不足以囊括训练过程中可能需要到的功能,比如负采样,learning rate decay, Early Stop等。 | 虽然Trainer本身已经集成了一些功能,但仍然不足以囊括训练过程中可能需要到的功能,比如负采样,learning rate decay, Early Stop等。 | ||||
为了解决这个问题fastNLP引入了callback的机制,:class:`~fastNLP.Callback` 是一种在Trainer训练过程中特定阶段会运行的函数集合, | 为了解决这个问题fastNLP引入了callback的机制,:class:`~fastNLP.Callback` 是一种在Trainer训练过程中特定阶段会运行的函数集合, | ||||
所有的 :class:`~fastNLP.Callback` 都具有on_*(比如on_train_start, on_backward_begin)等函数。 | 所有的 :class:`~fastNLP.Callback` 都具有on_*(比如on_train_start, on_backward_begin)等函数。 | ||||
如果 Callback 实现了该函数,则Trainer运行至对应阶段,会进行调用。 | |||||
我们将Train.train()这个函数内部分为以下的阶段,在对应阶段会触发相应的调用。 | |||||
Example:: | |||||
如果 Callback 实现了该函数,则Trainer运行至对应阶段,会进行调用,例如:: | |||||
from fastNLP import Callback, EarlyStopCallback, Trainer, CrossEntropyLoss, AccuracyMetric | |||||
from fastNLP.models import CNNText | |||||
callback.on_train_begin() # 开始进行训练 | |||||
for i in range(1, n_epochs+1): | |||||
callback.on_epoch_begin() # 开始新的epoch | |||||
for batch_x, batch_y in Batch: | |||||
callback.on_batch_begin(batch_x, batch_y, indices) # batch_x是设置为input的field,batch_y是设置为target的field | |||||
获取模型输出 | |||||
callback.on_loss_begin() | |||||
计算loss | |||||
callback.on_backward_begin() # 可以进行一些检查,比如loss是否为None | |||||
反向梯度回传 | |||||
callback.on_backward_end() # 进行梯度截断等 | |||||
进行参数更新 | |||||
callback.on_step_end() | |||||
callback.on_batch_end() | |||||
# 根据设置进行evaluation,比如这是本epoch最后一个batch或者达到一定step | |||||
if do evaluation: | |||||
callback.on_valid_begin() | |||||
进行dev data上的验证 | |||||
callback.on_valid_end() # 可以进行在其它数据集上进行验证 | |||||
callback.on_epoch_end() # epoch结束调用 | |||||
callback.on_train_end() # 训练结束 | |||||
callback.on_exception() # 这是一个特殊的步骤,在训练过程中遭遇exception会跳转到这里 | |||||
fastNLP已经自带了很多callback函数供使用,可以参考 :class:`~fastNLP.Callback` 。 | |||||
TODO callback的例子 一些关于callback的例子,请参考 | |||||
start_time = time.time() | |||||
class MyCallback(Callback): | |||||
def on_epoch_end(self): | |||||
print('{:d}ms\n\n'.format(round((time.time()-start_time)*1000))) | |||||
model = CNNText((len(vocab),50), num_classes=5, padding=2, dropout=0.1) | |||||
trainer = Trainer(model=model, train_data=train_data, dev_data=dev_data, loss=CrossEntropyLoss(), | |||||
metrics=AccuracyMetric(), callbacks=[MyCallback(),EarlyStopCallback(10)]) | |||||
trainer.train() | |||||
这里,我们通过继承 :class:`~fastNLP.Callback` 类定义了自己的 callback 的,并和内置的 :class:`~fastNLP.EarlyStopCallback` | |||||
一起传给了 :class:`~fastNLP.Trainer` ,增强了 :class:`~fastNLP.Trainer` 的功能 | |||||
fastNLP已经自带了很多callback函数供使用,可以参考 :doc:`fastNLP.core.callback` 。 | |||||
""" | """ | ||||
@@ -445,6 +440,7 @@ class Trainer(object): | |||||
_check_code(dataset=train_data, model=model, losser=losser, metrics=metrics, dev_data=dev_data, | _check_code(dataset=train_data, model=model, losser=losser, metrics=metrics, dev_data=dev_data, | ||||
metric_key=metric_key, check_level=check_code_level, | metric_key=metric_key, check_level=check_code_level, | ||||
batch_size=min(batch_size, DEFAULT_CHECK_BATCH_SIZE)) | batch_size=min(batch_size, DEFAULT_CHECK_BATCH_SIZE)) | ||||
# _check_code 是 fastNLP 帮助你检查代码是否正确的方法 。如果你在错误栈中看到这行注释,请认真检查你的代码 | |||||
self.train_data = train_data | self.train_data = train_data | ||||
self.dev_data = dev_data # If None, No validation. | self.dev_data = dev_data # If None, No validation. | ||||
@@ -11,7 +11,16 @@ Example:: | |||||
# ... do stuff | # ... do stuff | ||||
""" | """ | ||||
__all__ = [ | |||||
'DataSetLoader', | |||||
'CSVLoader', | |||||
'JsonLoader', | |||||
'ConllLoader', | |||||
'SNLILoader', | |||||
'SSTLoader', | |||||
'PeopleDailyCorpusLoader', | |||||
'Conll2003Loader', | |||||
] | |||||
from nltk.tree import Tree | from nltk.tree import Tree | ||||
from ..core.dataset import DataSet | from ..core.dataset import DataSet | ||||