专栏首页相约机器人LineFlow:PyTorch或任何框架的简单NLP数据集处理程序

LineFlow:PyTorch或任何框架的简单NLP数据集处理程序

作者 | Yasufumi TANIGUCHI

来源 | Medium

编辑 | 代码医生团队

对于NLP任务,可能需要在预处理中标记文本或构建词汇表。可能已经体验到预处理代码与桌面一样混乱。如这就是为什么创建LineFlow来缓解痛苦!它将使“桌面”尽可能干净。真正的代码如何?看看下图。预处理包括标记化,构建词汇表和索引。

https://github.com/tofunlp/lineflow

左边部分是来自PyTorch官方示例存储库的示例代码,它对文本数据进行常见的预处理。右边部分用LineFlow编写,以实现完全相同的处理。了解LineFlow如何减轻痛苦。可以从此链接查看完整代码。

https://gist.github.com/yasufumy/ba73b587bd3c516b66fb94b3a90bac71

在这篇文章中,将详细解释右边的代码并展示 LineFlow 的用法。开始一个干净的“桌面”生活!

1.加载文本数据

加载文本数据由上面代码的第8行完成。稍后会解释一下这张地图。lf.TextDataset 将文本文件的路径作为参数并加载它。

dataset = lf.TextDataset(path, encoding='utf-8').map(...)

lf.TextDataset 期望的数据格式是每行对应于一个数据。如果文本数据满足此条件,则可以加载任何类型的文本数据。

加载后,它将文本数据转换为列表。列表中的项目对应于文本数据中的行。请看下图。这是直观的形象 lf.TextDataset。该d图中表示dataset的代码。

LineFlow已经提供了一些公开可用的数据集。所以可以立即使用它。可以在此处查看提供的数据集。

https://github.com/tofunlp/lineflow#datasets

2.标记化

文本标记化也由第8行完成。map将作为参数传递的处理应用于文本数据的每一行。

dataset = lf.TextDataset(...).map(lambda x: x.split() + ['<eos>'])

请看下图。这是直观的形象 lf.TextDataset.map。该d图中表示 dataset 的代码。

深入了解下面的实际处理。

lambda x: x.split() + ['<eos>']

在这里,将文本数据中的每一行用空格分割为标记,然后添加<eos>到这些标记的末尾。按照WikiText官方页面中的处理方式进行操作。

在这个时候,str.split 用于标记化。可以使用其他标记化方法,如 spaCy,StanfordNLP 和 Bling Fire 等。例如如果想使用 Bling Fire ,将获得以下代码。

from blingfire import text_to_words
d = lf.TextDataset('/path/to/your/text')
d.map(text_to_words).map(str.split)

此外,只要处理将每行文本数据作为参数,就可以进行任何想要的处理。例如,可以计算令牌的数量。在以下代码中,标记的数量在第二个元素中定义。

d = lf.TextDataset('/path/to/text')
d.map(tokenize).map(lambda x: (x, len(x)))

当想要为注意机制或LSTM制作掩码时,这个处理很有用。

3.索引

索引从第9行到第12行完成。这些行如下图所示。在这个代码块中,构建了词汇表和索引。按顺序看看这些。

for word in dataset.flat_map(lambda x: x):
    self.dictionary.add_word(word)
return torch.LongTensor(dataset.flat_map(...))

首先,将看到构建词汇表的障碍。在下面的代码块中,构建了词汇表。flat_map 将作为参数传递的处理应用于数据中的每一行,然后将其展平。所以将获得个人令牌

dataset.flat_map(lambda x: x)。
for word in dataset.flat_map(lambda x: x):
self.dictionary.add_word(word)

请看下图。这是直观的形象dataset.flat_map(lambda x: x)。该d图中表示dataset的代码。

flat_map 有点令人困惑,但它等于以下代码。

from itertools import chain
chain.from_iterable(map(lambda x: x, dataset))


dataset.flat_map(lambda x: x) # same as above

通过使用提取每个标记后 flat_map,传递 self.dictionary.add_word 构建词汇表的标记。

self.dictionary.add_word(word)

接下来,将看到索引的代码块。索引由以下块完成。在这里还使用flat_map索引每个标记并展平它。这是因为PyTorch的例子需要扁平标记的张量。

dataset.flat_map(
    [lambda x: self.dictionary.word2idx[token] for token in x)])

请看下图。这是直观的形象 dataset.flat_map(indexer)。该 d 图中表示 dataset 的代码。

此代码等于以下代码。

from itertools import chain
chain.from_iterable(map(indexer, dataset))
 
dataset.flat_map(indexer) # same as above

最后,将其包装torch.LongTensor以使其tensor。完成了加载文本数据。

return torch.LongTensor(dataset.flat_map(...))

可以查看到目前为止已经看到的完整代码。

import os
import torch
import lineflow as lf
 
class Dictionary(object):
    def __init__(self):
        self.word2idx = {}
        self.idx2word = []
 
    def add_word(self, word):
        if word not in self.word2idx:
            self.idx2word.append(word)
            self.word2idx[word] = len(self.idx2word) - 1
        return self.word2idx[word]
 
    def __len__(self):
        return len(self.idx2word)
 
 
class Corpus(object):
    def __init__(self, path):
        self.dictionary = Dictionary()
        self.train = self.tokenize(os.path.join(path, 'train.txt'))
        self.valid = self.tokenize(os.path.join(path, 'valid.txt'))
        self.test = self.tokenize(os.path.join(path, 'test.txt'))
 
    def tokenize(self, path):
        assert os.path.exists(path)
        dataset = lf.TextDataset(path, encoding='utf-8').map(lambda x: x.split() + ['<eos>'])
        for word in dataset.flat_map(lambda x: x):
            self.dictionary.add_word(word)
        return torch.LongTensor(dataset.flat_map(
            lambda x: [self.dictionary.word2idx[token] for token in x]))

这就是解释的全部内容。LineFlow通过矢量化文本数据来完成less循环和较少嵌套的代码。可以使用Python的map完全相同。但 LineFlow 提供了可读和干净的代码,因为它构建了像管道(Fluent Interface)这样的处理。

如果喜欢LineFlow并想了解更多信息,请访问下面的存储库。

https://github.com/tofunlp/lineflow/tree/master/examples?source=post_page-----1caf7851125e----------------------

本文分享自微信公众号 - 相约机器人(xiangyuejiqiren),作者:代码医生

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-08-23

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • U-GAT-IT - 官方TensorFlow实施

    ├── xxx.jpg (name, format doesn't matter)

    代码医生工作室
  • Seaborn-让绘图变得有趣

    如果曾经在Python中使用过线图,条形图等图形,那么一定已经遇到了名为matplotlib的库。

    代码医生工作室
  • 用命令行管理你的GitHub项目,不必再开网页,官方CLI工具1.0版今日上线

    经过大半年的迭代与完善,今天GitHub CLI已经成功从beta版升级为1.0正式版,可供所有用户使用。

    代码医生工作室
  • python中的zip、lambda、map操作

    python 中有几个比较酷炫的操作,比如:zip、lambda、map 一、zip操作 zip字面意思:拉链。这么记,把几个东西扔到一个包里,拉上拉链,就算打...

    菩提树下的杨过
  • 全面盘点当前Android后台保活方案的真实运行效果(截止2019年前)1、引言2、先总结一下,Android端APP为何要搞保活黑科技?3、相关文章4、常见的Android端保活黑科技方案盘点5、汇

    本文原作者“minminaya”,作者网站:minminaya.cn,为了提升文章品质,即时通讯网对内容作了幅修订和改动,感谢原作者。

    JackJiang
  • 锦囊篇|一文摸懂ButterKnife

    于2020年3月26号,Jack Wharton 官宣 ButterKnife 废弃了。但是我们就没有必要去学习了吗?显然并不是这样的,一个开源库背后的每一分思...

    ClericYi
  • openlayers实现画圆

    通过OpenLayers.Control.DrawFeature和OpenLayers.Handler.Point实现在地图上画圆心。

    lzugis
  • 交通工程跨界思考:何为无人驾驶仿真中的交通流仿真以及可用平台有哪些?

    据世界卫生组织最新数据显示,每年约有 135 万人由于道路交通事故而死亡,其中超过 90% 的交通事故是人为因素造成的[1]。而无人驾驶从不醉酒、分心或是疲劳,...

    机器之心
  • Go语言学习(四)| 数组、切片、集合

    array由 [n]<type> 定义,n为array的长度,<type>标示希望存储的内容的类型。例:

    Mervyn
  • python3的一个奇怪设计--map

    这个改动真是太不正常了,ruby、js和lisp都没这么干的。我也没搞懂这样做有什么好处?

    py3study

扫码关注云+社区

领取腾讯云代金券