赞
踩
from torchtext.data import Field,Example,Dataset
from torchtext import vocab
import os
import nltk
squential:数据是否为序列数据,默认为Ture。如果为False,则不能使用分词。
use_vocab:是否使用词典,默认为True。如果为False,那么输入的数据类型必须是数值类型(即使用vocab转换后的)。
init_token:文本的其实字符,默认为None。
eos_token:文本的结束字符,默认为None。
fix_length:所有样本的长度,不够则使用pad_token补全。默认为None,表示灵活长度。
tensor_type:把数据转换成的tensor类型 默认值为torch.LongTensor。
preprocessing:预处理pipeline, 用于分词之后、数值化之前,默认值为None。
postprocessing:后处理pipeline,用于数值化之后、转换为tensor之前,默认为None。
lower:是否把数据转换为小写,默认为False;
tokenize:分词函数,默认为str.split
include_lengths:是否返回一个已经补全的最小batch的元组和和一个包含每条数据长度的列表,默认值为False。
batch_first:batch作为第一个维度;
pad_token:用于补全的字符,默认为<pad>。
unk_token:替换袋外词的字符,默认为<unk>。
pad_first:是否从句子的开头进行补全,默认为False;
truncate_first:是否从句子的开头截断句子,默认为False;
stop_words:停用词;
# 1.数据 corpus = ["D'aww! He matches this background colour", "Yo bitch Ja Rule is more succesful then", "If you have a look back at the source"] labels = [0,1,0] # 2.定义不同的Field TEXT = Field(sequential=True, lower=True, fix_length=10,tokenize=str.split,batch_first=True) LABEL = Field(sequential=False, use_vocab=False) fields = [("comment", TEXT),("label",LABEL)] # 3.将数据转换为Example对象的列表 examples = [] for text,label in zip(corpus,labels): example = Example.fromlist([text,label],fields=fields) examples.append(example) print(type(examples[0])) print(examples[0].comment) print(examples[0].label) # 4.构建词表 new_corpus = [example.comment for example in examples] TEXT.build_vocab(new_corpus) print(TEXT.process(new_corpus))
<class 'torchtext.data.example.Example'>
["d'aww!", 'he', 'matches', 'this', 'background', 'colour']
0
tensor([[ 8, 10, 15, 22, 5, 7, 1, 1, 1, 1],
[23, 6, 13, 17, 12, 16, 19, 21, 1, 1],
[11, 24, 9, 2, 14, 4, 3, 20, 18, 1]])
Field中的参数tokenize必须是一个函数,其作用是给定一个字符串,该函数以列表的形式返回分词结果。这里以jieba分词为例:
import jieba
# jieba分词返回的是迭代器,因此不能直接作为tokenize
print(jieba.cut("我爱北京天安门"))
# 使用lambda定义新的函数cut,其直接返回分词结果的列表,这样才可以作为tokenize
cut = lambda x:list(jieba.cut(x))
cut("我爱北京天安门")
<generator object Tokenizer.cut at 0x000002038CEFF938>
['我', '爱', '北京', '天安门']
前面的代码中Field对象TEXT通过调用build_vocab()方法来生成一个内置的Vocab对象,即TEXT.build_vocab(new_corpus)
。下面看一下Vocab对象的常见用法:
print(type(TEXT.vocab.freqs)) # freqs是一个Counter对象,包含了词表中单词的计数信息
print(TEXT.vocab.freqs['at'])
print(TEXT.vocab.itos[1]) # itos表示index to str
print(TEXT.vocab.stoi['<unk>']) # stoi表示str to index
print(TEXT.vocab.unk_index)
print(TEXT.vocab.vectors) # 词向量
<class 'collections.Counter'>
1
<pad>
0
0
None
可以看到TEXT.vocab.vectors
为None,因为在build_vocab()没有指定参数vectors,此时可以通过load_vectors方法来加载词向量。load_vectors的参数可以是字符串(例如:“fasttext.en.300d”),其会自动下载词向量并缓存到本地。但如果是自己训练的词向量,则需要指定词向量在本地的路径。
TEXT.vocab.load_vectors('fasttext.en.300d')
print(TEXT.vocab.vectors.shape)
torch.Size([25, 300])
p = os.path.expanduser("~\\.vector_cache\\sgns.wiki.bigram-char")
TEXT.vocab.load_vectors(vocab.Vectors(p))
这里自定义Field,其通过字符串(例如:“nltk”、“jieba”、“str”)等方式指定tokenize,并且能够通过名称来指定自定义的词向量。
class MyField(Field): def __init__(self, tokenize="nltk",**kwargs): self.tokenize_name = tokenize tokenize = MyField._get_tokenizer(tokenize) super(MyField, self).__init__(tokenize=tokenize, **kwargs) @staticmethod def _get_tokenizer(tokenizer): if tokenizer=='nltk': return nltk.word_tokenize elif tokenizer=='jieba': return lambda x:list(jieba.cut(x)) elif tokenizer=='split': return str.split else: raise ValueError("不支持的tokenizer") @classmethod def _get_vector_data(cls, vecs): if not isinstance(vecs, list): vecs = [vecs] vec_datas = [] for vec in vecs: if not isinstance(vec, vocab.Vectors): if vec=="fasttext": embed_file = os.path.expanduser("~\\.vector_cache\\wiki-news-300d-1M.vec") vec_data = vocab.Vectors(embed_file) elif vec=='sgns': embed_file = os.path.expanduser("~\\.vector_cache\\sgns.wiki.bigram-char") vec_data = vocab.Vectors(embed_file) else: raise ValueError("不支持的词向量类型") vec_datas.append(vec_data) else: vec_datas.append(vec) return vec_datas def build_vocab(self, *args, vectors=None, **kwargs): if vectors is not None: vectors = MyField._get_vector_data(vectors) super(MyField, self).build_vocab(*args, vectors=vectors, **kwargs)
corpus = ["D'aww! He matches this background colour",
"Yo bitch Ja Rule is more succesful then",
"If you have a look back at the source"]
TEXT = MyField(sequential=True, lower=True, fix_length=10,tokenize="jieba",batch_first=True)
fields = [("comment", TEXT)]
examples = []
for text in corpus:
example = Example.fromlist([text],fields=fields)
examples.append(example)
data = Dataset(examples, fields)
TEXT.build_vocab(data, vectors="sgns")
print(len(TEXT.vocab.freqs))
print(TEXT.vocab.vectors.shape)
<class 'torchtext.vocab.Vectors'>
27
torch.Size([29, 300])
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。