【PyTorch实战】手把手教你用torchtext处理文本数据

【导读】我们一直在关心深度学习模型的具体实现, 实际上,无论是什么实验, 数据的处理总是占大头的。如何将一个纯文本数据(比如一个 txt 文本), 变成一个模型可接受的数据(比如一个 embedding 序列)呢?

如果你是 pytorch 的用户,你可能已经非常熟悉 torchvision 了,因为它已经比较稳定,而且官方也为它出了教程。torchtext 跟 torchvision 一样,是为了处理特定的数据和数据集而存在的。正如 NLP和 CV的热度一样, torchtext的热度也较 torchvision 少了许多,至今还在积极开发中,甚至在使用过程中你可能会遇见一些 bug。但是, torchtext 的可用性是肯定的,它提供了一整套文本数据处理流程。

在本文中,我们将使用torchtext,来处理文本数据。其中,数据集采用kaggle的《有毒评论》数据集(https://www.kaggle.com/c/jigsaw-toxic-comment-classification-challenge)。

该数据集格式如下:

存储在一个 csv文件中。

一、预处理CSV文件



import pandas aspd
importnumpy as np
VAL_RATIO =0.2
defprepare_csv(seed=999):
    # 加载训练数据
   df_train = pd.read_csv("data/train.csv")
   df_train["comment_text"] = df_train.comment_text.str.replace("\n", " ")
    idx =np.arange(df_train.shape[0])
    # 将训练数据分成训练集和验证集
   np.random.seed(seed)
   np.random.shuffle(idx)
   val_size =int(len(idx) * VAL_RATIO)
   df_train.iloc[idx[val_size:], :].to_csv("cache/dataset_train.csv", index=False)
   df_train.iloc[idx[:val_size], :].to_csv("cache/dataset_val.csv", index=False)
    # 加载测试数据
   df_test = pd.read_csv("data/test.csv")
   df_test["comment_text"] = df_test.comment_text.str.replace("\n", " ")
   df_test.to_csv("cache/dataset_test.csv", index=False)

主要是为了将数据集分成训练,验证,测试三部分。

二、标记化(Tokenization)



mport re
importspacy
NLP = spacy.load('en')
MAX_CHARS =20000
deftokenizer(comment):
   comment = re.sub(r"[\*\"“”\n\\…\+\-\/\=\(\)‘•:\[\]\|’\!;]", " ", str(comment))
   comment = re.sub(r"[]+", " ",comment)
   comment = re.sub(r"\!+", "!", comment)
   comment = re.sub(r"\,+", ",", comment)
   comment = re.sub(r"\?+", "?", comment)
    # 如果数据太长,将被截断
    if (len(comment) > MAX_CHARS):
       comment = comment[:MAX_CHARS]
    return[x.text for x in NLP.tokenizer(comment) if x.text !=" "]

这里使用正则表达式清洗一下数据,然后,直接调用 Spacy ,使用其中的 tokenizer函数,将文本标记化。

三、加载数据



import logging
importtorch
fromtorchtext
LOGGER = logging.getLogger("toxic_dataset")
defget_dataset(fix_length=100, lower=False, vectors=None):
    ifvectors isnotNone:
       lower =True
   LOGGER.debug("预处理 csv...")
   prepare_csv()
    # 用 torchtext 的 data 类加载数据
   comment = torchtext.data.Field(
       sequential=True,
       fix_length=fix_length,
       tokenize=tokenizer,
       pad_first=True,
       tensor_type=torch.cuda.LongTensor,
       lower=lower
    )
   LOGGER.debug("读 train csv...")
    train=data.TabularDataset(
       path='cache/dataset_train.csv',format='csv', skip_header=True,
       fields=[
           ('id', None),
           ('comment_text', comment),
           ('toxic', data.Field(
               use_vocab=False,sequential=False,tensor_type=torch.cuda.ByteTensor)),
           ('severe_toxic', data.Field(
               use_vocab=False,sequential=False,tensor_type=torch.cuda.ByteTensor)),
           ('obscene', data.Field(
               use_vocab=False,sequential=False,tensor_type=torch.cuda.ByteTensor)),
           ('threat', data.Field(
               use_vocab=False,sequential=False,tensor_type=torch.cuda.ByteTensor)),
           ('insult', data.Field(
               use_vocab=False,sequential=False,tensor_type=torch.cuda.ByteTensor)),
           ('identity_hate', data.Field(
               use_vocab=False,sequential=False,tensor_type=torch.cuda.ByteTensor)),
       ])
   LOGGER.debug("读 test csv file...")
    test =torchtext.data.TabularDataset(
       path='cache/dataset_test.csv',format='csv', 
       skip_header=True,
       fields=[
           ('id', None),
           ('comment_text', comment)
       ])
   LOGGER.debug("构建词表...")
   comment.build_vocab(
       train, val, test,
       max_size=20000,
       min_freq=50,
       vectors=vectors
    )
   LOGGER.debug("预处理结束")
    returntrain.examples, test.examples, comment

data.Field函数,定义了处理数据的pipline,然后返回给了comment,用于在data.TabularDataset中,针对csv 文件里的comment_text这一Field做处理。

其中:

comment =torchtext.data.Field(
   sequential=True,# 该列数据是否是序列数据
   fix_length=fix_length, #最大长度
   tokenize=tokenizer, #标记化函数,上面定义过
   pad_first=True,# 在句子前方 pad
   tensor_type=torch.cuda.LongTensor, #数据转换后的类型
    lower=lower# 是否小写
)

另外,.build_vocab也非常有用。

comment.build_vocab(
   train, val, test,
   max_size=20000, # 词典大小
   min_freq=50,    #词频率最小值
   vectors=vectors #word embedding
)

它能够建立词汇表用于将token 或者词转化成数字,另外,它还能自动对齐word embedding (comment.vocab.vectors`)。

其他几个字段就是 label了,一共有6个:toxic, severe_toxic, obscene, threat, insult, identity_hate都是0-1变量.

data.TabularDataset.splits能够一次读取多个文件比如上面的代码中,我们就同时读取了训练集和验证集。另外,值得注意的是,在fields处理中,必须要按照顺序,一列一列的处理,不能跳过,所以,对一我们不要的那些列,需要显式的声明,比如:("id", None)。

四、分batch和迭代



def get_iterator(dataset, batch_size, train=True,
   shuffle=True,repeat=False):
   dataset_iter = torchtext.data.Iterator(
       dataset, batch_size=batch_size, device=0,
       train=train, shuffle=shuffle, repeat=repeat,
       sort=False
    )
    return dataset_iter

创建迭代器非常简单,我们也可以自定义一些别的属性,不然 repeat 等等。

for examples inget_iterator(
           train_dataset, batch_size, train=True,
           shuffle=True,repeat=False
       ):
    x =examples.comment_text #(fix_length, batch_size) Tensor
    y =torch.stack([
       examples.toxic, 
       examples.severe_toxic, 
       examples.obscene,
       examples.threat, 
       examples.insult, 
       examples.identity_hate
    ],dim=1)

以及使用以训练的 word emebdding (假设你的 model 的 embedding 放在 word_em 下面,同时你的训练集叫 train_dataset)

model.word_em.weight.data = train_dataset.fields["comment_text"].vocab.vectors

至此,我们就完成了了数据从纯文本到纯 embedding 的转换了了。下一步就可以 Feed 进模型,比如 RNN等。

-END-

原文发布于微信公众号 - 专知(Quan_Zhuanzhi)

原文发表时间:2018-06-14

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

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏常用编程思想与算法

常用编程思想与算法

本文是在阅读Aditya Bhargava先生算法图解一书所做的总结,文中部分代码引用了原文的代码,在此感谢Aditya Bhargava先生所作出的这么简单的...

21510
来自专栏算法修养

POJ 1964&HDU 1505&HOJ 1644 City Game(最大0,1子矩阵和总结)

最大01子矩阵和,就是一个矩阵的元素不是0就是1,然后求最大的子矩阵,子矩阵里的元素都是相同的。 这个题目,三个oj有不同的要求,hoj的要求是5s,...

34540
来自专栏编程之旅

数据结构——最小生成树(C++和Java实现)

快要一整个月没有更新博客了,之前的几周每周都想着要写,但是最后时间还是排不开,最近的状态是一直在写代码,一直在怼工作的需求,顺便刷刷算法题,国庆则是没心没肺的玩...

36140
来自专栏java一日一条

我是如何击败Java自带排序算法的

Java 8 对自带的排序算法进行了很好的优化。对于整形和其他的基本类型, Arrays.sort() 综合利用了双枢轴快速排序、归并排序和启发式插入排序。这个...

12910
来自专栏有趣的Python和你

Python数据分析之锁具装箱问题问题重述问题分析建模与求解

11730
来自专栏潇涧技术专栏

Python Algorithms - C3 Counting 101

原书主要介绍了一些基础数学,例如排列组合以及递归循环等,但是本节只重点介绍计算算法的运行时间的三种方法

9640
来自专栏Python小屋

最快的组合数算法之Python实现

原理:以Cni(8,3)为例,按定义式将其展开为(8*7*6*5*4*3*2*1)/(3*2*1)/(5*4*3*2*1),对于8到6之间的数,分子上出现一次而...

37470
来自专栏深度学习那些事儿

pytorch新手需要注意的隐晦操作Tensor,max,gather

先看官方的介绍: 如果input是一个n维的tensor,size为 (x0,x1…,xi−1,xi,xi+1,…,xn−1),dim为i,然后index必须...

1.5K80
来自专栏爱撒谎的男孩

回溯算法

28130
来自专栏tkokof 的技术,小趣及杂念

Sweet Snippet系列 之 随机选择

  平日工作学习时总会遇到一些令人欣喜的代码段子(Snippet),虽然都很短小,但是其间所含的道理都颇有意味,遂而觉得应该不时的将她们记下,一来算作复习整理,...

11920

扫码关注云+社区

领取腾讯云代金券