【ArchSummit】如何通过AIOps推动可量化的业务价值增长和效率提升?>>> 了解详情
写点什么

LineFlow 开源:比 PyTorch 简洁数倍,适用任何框架的 NLP 数据集处理程序

  • 2019-12-31
  • 本文字数:2771 字

    阅读完需:约 9 分钟

LineFlow开源:比PyTorch简洁数倍,适用任何框架的NLP数据集处理程序

一般来讲,用 PyTorch 处理自然语言比较繁琐。于是,国外一位开发者 Yasufumi TANIGUCHI 开发了 LineFlow,为了尽可能减轻编码的痛苦,并保证完成同样的任务。Yasufumi TANIGUCHI 表示,LineFlow 要比 PyTorch 简洁数倍,让我们来看看 LineFlow 究竟能简洁到什么地步?


对自然语言处理任务来说,你可能需要在预处理中对文本进行词法分析或构建词汇表。因为这个过程非常痛苦,所以我创建了LineFlow ,尽可能让整个过程干净整洁。真正的代码看起来是什么样子?请看下面的图,预处理包括词法分析、词汇表构建和索引。



左边部分是来自 PyTorch 官方示例仓库的示例代码,它对文本数据进行常见的预处理。右边部分是用 LineFolw 编写的,实现了完全相同的处理。看完对比之后,你应该明白 LineFlow 是如何减轻痛苦的。要查看完整的代码,可以访问此链接


在本文中,我将详细解释上图右边部分的代码,并讲解 LineFlow 的用法。

加载文本数据

文本数据的加载,是通过上面代码中的第 8 行完成的,我稍后会详细解释这个 map。lf.TextDataset 将文本文件的路径作为参数并进行加载。


dataset = lf.TextDataset(path, encoding='utf-8').map(...)
复制代码


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




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



LineFlow 已经提供了一些公开可用的数据集。所以你可以马上使用它。要查看提供的数据集,请访问此链接

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 进行标记化。我们可以使用其他的标记化方法,如 spaCyStanfordNLPBling 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)))
复制代码


当我们想要制作用于注意力机制或长短期记忆网络的掩码时,这种处理就很有用。

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 将它包起来,把它变成张量。至此就完成了文本数据的加载。


return torch.LongTensor(dataset.flat_map(...))
复制代码


现在我们可以阅读完整的代码了,如下所示:


import osimport torchimport lineflow as lfclass 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 通过对文本数据进行向量化来完成较少的循环和嵌套代码。我们可以使用 Python 的 map 来完成同样的工作。但是,LineFlow 为我们提供了可读的、干净的代码,因为它像管道(Fluent Interface)一样构建了处理过程。


如果你喜欢 LineFlow,并想了解更多信息,请访问 LineFlow 在 GitHub 的仓库


作者介绍:


Yasufumi TANIGUCHI,软件工程师,对自然语言处理有着浓厚的兴趣。本文最初发表于 Medium 博客,经原作者 Yasufumi TANIGUCHI 授权,InfoQ 中文站翻译并分享。


原文链接:


https://towardsdatascience.com/lineflow-introduction-1caf7851125e


公众号推荐:

跳进 AI 的奇妙世界,一起探索未来工作的新风貌!想要深入了解 AI 如何成为产业创新的新引擎?好奇哪些城市正成为 AI 人才的新磁场?《中国生成式 AI 开发者洞察 2024》由 InfoQ 研究中心精心打造,为你深度解锁生成式 AI 领域的最新开发者动态。无论你是资深研发者,还是对生成式 AI 充满好奇的新手,这份报告都是你不可错过的知识宝典。欢迎大家扫码关注「AI前线」公众号,回复「开发者洞察」领取。

2019-12-31 09:482860
用户头像
赵钰莹 InfoQ 主编

发布了 875 篇内容, 共 606.8 次阅读, 收获喜欢 2671 次。

关注

评论

发布
暂无评论
发现更多内容

云图说|华为HiLens云上管理平台,花样管理多种端侧设备

华为云开发者联盟

AI 华为云 云图说 华为HiLens EI智能体

《大数据大创新:阿里巴巴云上数据中台之道》:解密阿里数据中台建设

云祁

大数据 读书笔记 数据中台 7月日更

HVC矿机系统开发|HVC矿机软件APP开发

如何用EasyRecovery 快速找回误删的截图

淋雨

EasyRecovery 文件恢复 硬盘数据恢复 固态硬盘数据恢复

DGTT挖矿智能合约系统软件开发案例

Vchat挖矿软件开发|Vchat挖矿系统APP开发

计算机时间到底是怎么来的?程序员必看的时间知识!

Kaito

操作系统 计算机基础 时间 ntp

Pandas高级教程之:统计方法

程序那些事

Python 数据分析 pandas 程序那些事

不藏了,这些Java反射用法总结都告诉你们

华为云开发者联盟

Java JVM 反射 java框架 MyBase

多媒体技术(一)之图形图像

轻口味

android 音视频 计算机图形学 图形图像处理

大数据成神之路面试合集&资源开放下载

王知无

大数据 面试

【LeetCode】和相同的二元子数组Java题解

Albert

算法 LeetCode 7月日更

TCP 的 Keepalive 和 HTTP 的 Keep-Alive 是一个东西吗?

小林coding

计算机网络 HTTP TCP/IP

小马哥的Java项目训练营-毕业总结

姑射仙人

DolphinDB插件开发深度解析

DolphinDB

数据库 大数据 时序数据库 插件开发 DolphinDB

打造中国数字军人 数军科技携黑科技亮相军博会

科技热闻

无意中发现一个好用的前后端代码生成网

江湖一点雨

mybatis java代码 自动生成 vue自动生成 sql转实体

【Flutter 专题】93 图解 Dart 单线程实现异步处理之 Isolate (二)

阿策小和尚

Flutter 小菜 0 基础学习 Flutter Android 小菜鸟 7月日更

领哆哆APP开发|领哆哆软件系统开发

Redisson 分布式锁源码 06:公平锁排队加锁

程序员小航

Java redis 分布式锁 redisson

架构训练营模块一作业

Lemon

架构训练营

基于Erlang语言的视频相似推荐(三十一)

数据与智能

erlang 实时计算 推荐系统

萌宠大陆APP开发|萌宠大陆系统软件开发

互联网公司的「敏捷开发」流程是怎么样的?每个职位的角色和分工是什么?

万事ONES

我给我讲GIT,并成功把我得罪了

加百利

git 7月日更

union 分页/group/join 复杂查询(.net core/framework)

Spook

sql ORM

Rust从0到1-智能指针-Deref trait

rust 智能指针 smart pointer deref

FIL挖矿怎么样?FIL挖矿靠谱吗?

高级码农设计的程序能解耦,是多么重要的一件事情!

小傅哥

spring 设计模式 小傅哥 观察者模式 系统解耦

Swarm节点系统开发|Swarm节点APP软件开发

研发管理和项目管理有哪些痛点?

万事ONES

研发管理 ONES 项目管理工具

LineFlow开源:比PyTorch简洁数倍,适用任何框架的NLP数据集处理程序_开源_Yasufumi TANIGUCHI_InfoQ精选文章