Browse Source

Merge branch 'dev0.5.0' of https://github.com/fastnlp/fastNLP into dev0.5.0

tags/v0.4.10
yh 5 years ago
parent
commit
12cfa5e42e
18 changed files with 113 additions and 49 deletions
  1. +11
    -2
      README.md
  2. +1
    -1
      docs/source/tutorials/tutorial_9_seq_labeling.rst
  3. +5
    -5
      fastNLP/__init__.py
  4. +1
    -1
      fastNLP/core/__init__.py
  5. +4
    -4
      fastNLP/core/callback.py
  6. +1
    -1
      fastNLP/core/dataset.py
  7. +4
    -5
      fastNLP/core/dist_trainer.py
  8. +1
    -1
      fastNLP/core/instance.py
  9. +1
    -1
      fastNLP/core/metrics.py
  10. +1
    -1
      fastNLP/core/tester.py
  11. +4
    -4
      fastNLP/core/trainer.py
  12. +16
    -4
      fastNLP/core/utils.py
  13. +4
    -4
      fastNLP/io/__init__.py
  14. +34
    -4
      fastNLP/io/loader/matching.py
  15. +4
    -3
      fastNLP/modules/__init__.py
  16. +2
    -1
      setup.py
  17. +1
    -1
      test/core/test_dist_trainer.py
  18. +18
    -6
      test/models/test_cnn_text_classification.py

+ 11
- 2
README.md View File

@@ -44,19 +44,28 @@ fastNLP0.5.0版本将在近期推出,请密切关注。

## fastNLP教程

### 快速入门

- [0. 快速入门](https://fastnlp.readthedocs.io/zh/latest/user/quickstart.html)

### 详细使用教程

- [1. 使用DataSet预处理文本](https://fastnlp.readthedocs.io/zh/latest/tutorials/tutorial_1_data_preprocess.html)
- [2. 使用Vocabulary转换文本与index](https://fastnlp.readthedocs.io/zh/latest/tutorials/tutorial_2_vocabulary.html)
- [3. 使用Embedding模块将文本转成向量](https://fastnlp.readthedocs.io/zh/latest/tutorials/tutorial_3_embedding.html)
- [4. 使用Loader和Pipe加载并处理数据集](https://fastnlp.readthedocs.io/zh/latest/tutorials/tutorial_4_load_dataset.html)
- [5. 动手实现一个文本分类器II-使用DataSetIter实现自定义训练过程](https://fastnlp.readthedocs.io/zh/latest/tutorials/tutorial_5_datasetiter.html)
- [6. 动手实现一个文本分类器I-使用Trainer和Tester快速训练和测试](https://fastnlp.readthedocs.io/zh/latest/tutorials/tutorial_6_loss_optimizer.html)
- [5. 动手实现一个文本分类器I-使用Trainer和Tester快速训练和测试](https://fastnlp.readthedocs.io/zh/latest/tutorials/tutorial_5_loss_optimizer.html)
- [6. 动手实现一个文本分类器II-使用DataSetIter实现自定义训练过程](https://fastnlp.readthedocs.io/zh/latest/tutorials/tutorial_6_datasetiter.html)
- [7. 使用Metric快速评测你的模型](https://fastnlp.readthedocs.io/zh/latest/tutorials/tutorial_7_metrics.html)
- [8. 使用Modules和Models快速搭建自定义模型](https://fastnlp.readthedocs.io/zh/latest/tutorials/tutorial_8_modules_models.html)
- [9. 快速实现序列标注模型](https://fastnlp.readthedocs.io/zh/latest/tutorials/tutorial_9_seq_labeling.html)
- [10. 使用Callback自定义你的训练过程](https://fastnlp.readthedocs.io/zh/latest/tutorials/tutorial_10_callback.html)
- [11. 使用fitlog 辅助 fastNLP 进行科研](https://fastnlp.readthedocs.io/zh/latest/tutorials/tutorial_11_fitlog.html)

### 扩展教程

- [Extend-1. BertEmbedding的各种用法](https://fastnlp.readthedocs.io/zh/latest/tutorials/extend_1_bert_embedding.html)



## 内置组件


+ 1
- 1
docs/source/tutorials/tutorial_9_seq_labeling.rst View File

@@ -114,7 +114,7 @@ fastNLP的数据载入主要是由Loader与Pipe两个基类衔接完成的,您
SpanFPreRecMetric: f=0.515528, pre=0.65098, rec=0.426735
Reloaded the best model.

训练结束之后过,可以通过 :class:`fastNLP.Tester`测试其在测试集上的性能
训练结束之后过,可以通过 :class:`~fastNLP.Tester` 测试其在测试集上的性能

.. code-block::python



+ 5
- 5
fastNLP/__init__.py View File

@@ -2,11 +2,11 @@
fastNLP 由 :mod:`~fastNLP.core` 、 :mod:`~fastNLP.io` 、:mod:`~fastNLP.embeddings` 、 :mod:`~fastNLP.modules`、
:mod:`~fastNLP.models` 等子模块组成,你可以查看每个模块的文档。

- :mod:`~fastNLP.core` 是fastNLP 的核心模块,包括 DataSet、 Trainer、 Tester 等组件。详见文档 :doc:`/fastNLP.core`
- :mod:`~fastNLP.io` 是实现输入输出的模块,包括了数据集的读取,模型的存取等功能。详见文档 :doc:`/fastNLP.io`
- :mod:`~fastNLP.embeddings` 提供用于构建复杂网络模型所需的各种embedding。详见文档 :doc:`/fastNLP.embeddings`
- :mod:`~fastNLP.modules` 包含了用于搭建神经网络模型的诸多组件,可以帮助用户快速搭建自己所需的网络。详见文档 :doc:`/fastNLP.modules`
- :mod:`~fastNLP.models` 包含了一些使用 fastNLP 实现的完整网络模型,包括 :class:`~fastNLP.models.CNNText` 、 :class:`~fastNLP.models.SeqLabeling` 等常见模型。详见文档 :doc:`fastNLP.models`
- :mod:`~fastNLP.core` 是fastNLP 的核心模块,包括 DataSet、 Trainer、 Tester 等组件。详见文档 :mod:`fastNLP.core`
- :mod:`~fastNLP.io` 是实现输入输出的模块,包括了数据集的读取,模型的存取等功能。详见文档 :mod:`fastNLP.io`
- :mod:`~fastNLP.embeddings` 提供用于构建复杂网络模型所需的各种embedding。详见文档 :mod:`fastNLP.embeddings`
- :mod:`~fastNLP.modules` 包含了用于搭建神经网络模型的诸多组件,可以帮助用户快速搭建自己所需的网络。详见文档 :mod:`fastNLP.modules`
- :mod:`~fastNLP.models` 包含了一些使用 fastNLP 实现的完整网络模型,包括 :class:`~fastNLP.models.CNNText` 、 :class:`~fastNLP.models.SeqLabeling` 等常见模型。详见文档 :mod:`fastNLP.models`

fastNLP 中最常用的组件可以直接从 fastNLP 包中 import ,他们的文档如下:
"""


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

@@ -8,7 +8,7 @@ core 模块里实现了 fastNLP 的核心框架,常用的功能都可以从 fa
# 从 core 模块的子模块 batch 中 import DataSetIter
from fastNLP.core.batch import DataSetIter

对于常用的功能,你只需要在 :doc:`fastNLP` 中查看即可。如果想了解各个子模块的具体作用,您可以在下面找到每个子模块的具体文档。
对于常用的功能,你只需要在 :mod:`fastNLP` 中查看即可。如果想了解各个子模块的具体作用,您可以在下面找到每个子模块的具体文档。

"""
__all__ = [


+ 4
- 4
fastNLP/core/callback.py View File

@@ -4,7 +4,7 @@ callback模块实现了 fastNLP 中的许多 callback 类,用于增强 :class:
虽然Trainer本身已经集成了一些功能,但仍然不足以囊括训练过程中可能需要到的功能,
比如负采样,learning rate decay 和 early stop等。
为了解决这个问题,fastNLP引入了callback的机制,:class:`~fastNLP.Callback` 是一种在Trainer训练过程中特定阶段会运行的函数集合。
关于 :class:`~fastNLP.Trainer` 的详细文档,请参见 :doc:`trainer 模块<fastNLP.core.trainer>`
关于 :class:`~fastNLP.Trainer` 的详细文档,请参见 :mod:`trainer 模块<fastNLP.core.trainer>`

我们将 :meth:`~fastNLP.Trainer.train` 这个函数内部分为以下的阶段,在对应阶段会触发相应的调用::

@@ -102,7 +102,7 @@ class Callback(object):
"""
Callback是fastNLP中被设计用于增强 :class:`~fastNLP.Trainer` 的类。
如果Callback被传递给了 Trainer , 则 Trainer 会在对应的阶段调用Callback的函数,
具体调用时机可以通过 :doc:`trainer 模块<fastNLP.core.trainer>` 查看。
具体调用时机可以通过 :mod:`trainer 模块<fastNLP.core.trainer>` 查看。
这是Callback的基类,所有的callback必须继承自这个类

"""
@@ -978,7 +978,7 @@ class SaveModelCallback(Callback):
return save_pair, delete_pair

def _save_this_model(self, metric_value):
name = "epoch:{}_step:{}_{}:{:.6f}.pt".format(self.epoch, self.step, self.trainer.metric_key, metric_value)
name = "epoch-{}_step-{}_{}-{:.6f}.pt".format(self.epoch, self.step, self.trainer.metric_key, metric_value)
save_pair, delete_pair = self._insert_into_ordered_save_models((metric_value, name))
if save_pair:
try:
@@ -995,7 +995,7 @@ class SaveModelCallback(Callback):

def on_exception(self, exception):
if self.save_on_exception:
name = "epoch:{}_step:{}_Exception:{}.pt".format(self.epoch, self.step, exception.__class__.__name__)
name = "epoch-{}_step-{}_Exception-{}.pt".format(self.epoch, self.step, exception.__class__.__name__)
_save_model(self.model, model_name=name, save_dir=self.save_dir, only_param=self.only_param)




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

@@ -306,7 +306,7 @@ from .utils import pretty_table_printer

class DataSet(object):
"""
fastNLP的数据容器,详细的使用方法见文档 :doc:`fastNLP.core.dataset`
fastNLP的数据容器,详细的使用方法见文档 :mod:`fastNLP.core.dataset`
"""

def __init__(self, data=None):


+ 4
- 5
fastNLP/core/dist_trainer.py View File

@@ -23,10 +23,9 @@ from .dataset import DataSet
from .losses import _prepare_losser
from .optimizer import Optimizer
from .utils import _build_args
from .utils import _check_fp16
from .utils import _get_func_signature
from .utils import _move_dict_value_to_device
from .utils import _check_fp16


try:
from apex import amp
@@ -76,9 +75,9 @@ class DistTrainer():
:param optimizer: `torch.optim.Optimizer` 优化器。如果为None,则Trainer使用默认的Adam(model.parameters(), lr=4e-3)这个优化器
:param loss: 使用的 :class:`~fastNLP.core.losses.LossBase` 对象。当为None时,默认使用 :class:`~fastNLP.LossInForward`
:param list callbacks_all: 用于在train过程中起调节作用的回调函数,作用于所有训练进程中。
可使用的callback参见 :doc:`callback模块 <fastNLP.core.callback>`
可使用的callback参见 :mod:`callback模块 <fastNLP.core.callback>`
:param list callbacks_master: 用于在train过程中起调节作用的回调函数,只作用于其中一个进程( Master 进程)。
可使用的callback参见 :doc:`callback模块 <fastNLP.core.callback>`
可使用的callback参见 :mod:`callback模块 <fastNLP.core.callback>`
:param int batch_size_per_gpu: 训练时,每个进程的 batch 大小。
:param int n_epochs: 需要优化迭代多少次。
:param num_workers: int, 有多少个线程来进行数据pad处理。
@@ -87,7 +86,7 @@ class DistTrainer():
: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时有效。
则保存当前模型。Metric种类详见 :mod:`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前面增加一个'-'来表


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

@@ -1,6 +1,6 @@
"""
instance 模块实现了Instance 类在fastNLP中对应sample。一个sample可以认为是一个Instance类型的对象。
便于理解的例子可以参考文档 :doc:`fastNLP.core.dataset` 中的表格
便于理解的例子可以参考文档 :mod:`fastNLP.core.dataset` 中的表格

"""



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

@@ -296,7 +296,7 @@ class MetricBase(object):

class AccuracyMetric(MetricBase):
"""
准确率Metric(其它的Metric参见 :doc:`fastNLP.core.metrics` )
准确率Metric(其它的Metric参见 :mod:`fastNLP.core.metrics` )
"""
def __init__(self, pred=None, target=None, seq_len=None):


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

@@ -27,7 +27,7 @@ tester模块实现了 fastNLP 所需的Tester类,能在提供数据、模型
tester = Tester(dataset, model, metrics=AccuracyMetric())
eval_results = tester.test()

这里Metric的映射规律是和 :class:`fastNLP.Trainer` 中一致的,具体使用请参考 :doc:`trainer 模块<fastNLP.core.trainer>` 的1.3部分。
这里Metric的映射规律是和 :class:`fastNLP.Trainer` 中一致的,具体使用请参考 :mod:`trainer 模块<fastNLP.core.trainer>` 的1.3部分。
Tester在验证进行之前会调用model.eval()提示当前进入了evaluation阶段,即会关闭nn.Dropout()等,在验证结束之后会调用model.train()恢复到训练状态。




+ 4
- 4
fastNLP/core/trainer.py View File

@@ -314,7 +314,7 @@ Example2.3
这里,我们通过继承 :class:`~fastNLP.Callback` 类定义了自己的 callback 的,并和内置的 :class:`~fastNLP.EarlyStopCallback`
一起传给了 :class:`~fastNLP.Trainer` ,增强了 :class:`~fastNLP.Trainer` 的功能

fastNLP已经自带了很多callback函数供使用,可以参考 :doc:`fastNLP.core.callback` 。
fastNLP已经自带了很多callback函数供使用,可以参考 :mod:`fastNLP.core.callback` 。

"""
__all__ = [
@@ -364,7 +364,7 @@ class Trainer(object):
(4) 每个epoch结束或一定step后进行验证集验证;
(5) 保存获得更好验证性能的模型等。
详细的介绍参见 :doc:`fastNLP.core.trainer`
详细的介绍参见 :mod:`fastNLP.core.trainer`
"""
def __init__(self, train_data, model, optimizer=None, loss=None,
@@ -391,7 +391,7 @@ class Trainer(object):
: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时有效。
则保存当前模型。Metric种类详见 :mod:`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前面增加一个'-'来表
@@ -417,7 +417,7 @@ class Trainer(object):
已知可能会出现的问题:Adagrad优化器可能无法正常使用这个参数,请手动管理模型位置。
:param list(callbacks) callbacks: 用于在train过程中起调节作用的回调函数。比如early stop,negative sampling等可以
通过callback机制实现。 可使用的callback参见 :doc:`callback模块 <fastNLP.core.callback>`
通过callback机制实现。 可使用的callback参见 :mod:`callback模块 <fastNLP.core.callback>`
:param int check_code_level: 模型检查等级. -1: 不进行检查; 0: 仅出现错误时停止; 1: 如果有field没有被使用,
报告警告信息; 2: 有任何field没有被使用都报错. 检查的原理是通过使用很小的batch(默认2个sample)来运行代码,但是
这个过程理论上不会修改任何参数,只是会检查能否运行。但如果(1)模型中存在将batch_size写为某个固定值的情况;


+ 16
- 4
fastNLP/core/utils.py View File

@@ -777,6 +777,7 @@ def pretty_table_printer(dataset_or_ins) -> PrettyTable:
except OSError:
column = 144
row = 11

if type(dataset_or_ins).__name__ == "DataSet":
x.field_names = list(dataset_or_ins.field_arrays.keys())
c_size = len(x.field_names)
@@ -793,6 +794,8 @@ def pretty_table_printer(dataset_or_ins) -> PrettyTable:

else:
raise Exception("only accept DataSet and Instance")
x.align = "l"

return x


@@ -804,11 +807,20 @@ def sub_column(string: str, c: int, c_size: int, title: str) -> str:
:param title: 列名
:return: 对一个过长的列进行截断的结果
"""
avg = max(int(c / c_size), len(title))
avg = max(int(c / c_size / 2), len(title))
string = str(string)
if len(string) > avg:
string = string[:(avg - 3)] + "..."
return string
res = ""
counter = 0
for char in string:
if ord(char) > 255:
counter += 2
else:
counter += 1
res += char
if counter > avg:
res = res + "..."
break
return res


def _check_fp16():


+ 4
- 4
fastNLP/io/__init__.py View File

@@ -1,13 +1,13 @@
"""
用于IO的模块, 具体包括:

1. 用于读入 embedding 的 :doc:`EmbedLoader <fastNLP.io.embed_loader>` 类,
1. 用于读入 embedding 的 :mod:`EmbedLoader <fastNLP.io.embed_loader>` 类,

2. 用于读入不同格式数据的 :doc:`Loader <fastNLP.io.loader>` 类
2. 用于读入不同格式数据的 :mod:`Loader <fastNLP.io.loader>` 类

3. 用于处理读入数据的 :doc:`Pipe <fastNLP.io.pipe>` 类
3. 用于处理读入数据的 :mod:`Pipe <fastNLP.io.pipe>` 类

4. 用于保存和载入模型的类, 参考 :doc:`model_io文档</fastNLP.io.model_io>`
4. 用于保存和载入模型的类, 参考 :mod:`model_io模块 <fastNLP.io.model_io>`

这些类的使用方法如下:
"""


+ 34
- 4
fastNLP/io/loader/matching.py View File

@@ -358,8 +358,26 @@ class CNXNLILoader(Loader):
super(CNXNLILoader, self).__init__()

def _load(self, path: str = None):
csv_loader = CSVLoader(sep='\t')
ds_all = csv_loader._load(path)
#csv_loader = CSVLoader(sep='\t')
#ds_all = csv_loader._load(path)
ds_all = DataSet()
with open(path, 'r', encoding='utf-8') as f:
head_name_list = f.readline().strip().split('\t')
sentence1_index = head_name_list.index('sentence1')
sentence2_index = head_name_list.index('sentence2')
gold_label_index = head_name_list.index('gold_label')
language_index = head_name_list.index(('language'))

for line in f:
line = line.strip()
raw_instance = line.split('\t')
sentence1 = raw_instance[sentence1_index]
sentence2 = raw_instance[sentence2_index]
gold_label = raw_instance[gold_label_index]
language = raw_instance[language_index]
if sentence1:
ds_all.append(Instance(sentence1=sentence1, sentence2=sentence2, gold_label=gold_label, language=language))

ds_zh = DataSet()
for i in ds_all:
if i['language'] == 'zh':
@@ -368,8 +386,20 @@ class CNXNLILoader(Loader):
return ds_zh

def _load_train(self, path: str = None):
csv_loader = CSVLoader(sep='\t')
ds = csv_loader._load(path)
#csv_loader = CSVLoader(sep='\t')
#ds = csv_loader._load(path)
ds = DataSet()

with open(path, 'r', encoding='utf-8') as f:
next(f)
for line in f:
raw_instance = line.strip().split('\t')
premise = raw_instance[0]
hypo = raw_instance[1]
label = raw_instance[-1]
if premise:
ds.append(Instance(premise=premise, hypo=hypo, label=label))

ds.rename_field('label', 'target')
ds.rename_field('premise', 'raw_chars1')
ds.rename_field('hypo', 'raw_chars2')


+ 4
- 3
fastNLP/modules/__init__.py View File

@@ -9,7 +9,7 @@
.. csv-table::
:header: "类型", "功能", "常见组件"

"embedding", 参见 :doc:`/fastNLP.embeddings` , "Elmo, Bert"
"embedding", 参见 :mod:`/fastNLP.embeddings` , "Elmo, Bert"
"encoder", "将输入编码为具有表示能力的向量", "CNN, LSTM, Transformer"
"decoder", "将具有某种表示意义的向量解码为需要的输出形式 ", "MLP, CRF"
"其它", "配合其它组件使用的组件", "Dropout"
@@ -52,13 +52,14 @@ __all__ = [
'summary'
]

import sys

from . import decoder
from . import encoder
from .decoder import *
from .dropout import TimestepDropout
from .encoder import *
from .utils import summary

import sys
from ..doc_utils import doc_process

doc_process(sys.modules[__name__])

+ 2
- 1
setup.py View File

@@ -13,7 +13,8 @@ with open('requirements.txt', encoding='utf-8') as f:

setup(
name='FastNLP',
version='dev0.5.0',
version='0.4.9',
url='https://github.com/fastnlp/fastNLP',
description='fastNLP: Deep Learning Toolkit for NLP, developed by Fudan FastNLP Team',
long_description=readme,
long_description_content_type='text/markdown',


+ 1
- 1
test/core/test_dist_trainer.py View File

@@ -148,7 +148,7 @@ class TestDistTrainer(unittest.TestCase):
def run_dist(self, run_id):
if torch.cuda.is_available():
ngpu = min(2, torch.cuda.device_count())
path = __file__
path = os.path.abspath(__file__)
cmd = ['python', '-m', 'torch.distributed.launch',
'--nproc_per_node', str(ngpu), path, '--test', str(run_id)]
print(' '.join(cmd))


+ 18
- 6
test/models/test_cnn_text_classification.py View File

@@ -6,12 +6,24 @@ from fastNLP.models.cnn_text_classification import CNNText


class TestCNNText(unittest.TestCase):
def init_model(self, kernel_sizes, kernel_nums=(1,3,5)):
model = CNNText((VOCAB_SIZE, 30),
NUM_CLS,
kernel_nums=kernel_nums,
kernel_sizes=kernel_sizes)
return model

def test_case1(self):
# 测试能否正常运行CNN
init_emb = (VOCAB_SIZE, 30)
model = CNNText(init_emb,
NUM_CLS,
kernel_nums=(1, 3, 5),
kernel_sizes=(1, 3, 5),
dropout=0.5)
model = self.init_model((1,3,5))
RUNNER.run_model_with_task(TEXT_CLS, model)

def test_init_model(self):
self.assertRaises(Exception, self.init_model, (2,4))
self.assertRaises(Exception, self.init_model, (2,))

def test_output(self):
model = self.init_model((3,), (1,))
global MAX_LEN
MAX_LEN = 2
RUNNER.run_model_with_task(TEXT_CLS, model)

Loading…
Cancel
Save